1 /* $XTermId: Tekproc.c,v 1.245 2021/06/03 21:23:18 tom Exp $ */
2
3 /*
4 * Copyright 2001-2020,2021 by Thomas E. Dickey
5 *
6 * All Rights Reserved
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sublicense, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
23 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 * Except as contained in this notice, the name(s) of the above copyright
28 * holders shall not be used in advertising or otherwise to promote the
29 * sale, use or other dealings in this Software without prior written
30 * authorization.
31 *
32 * Copyright 1988 X Consortium
33 *
34 * Permission to use, copy, modify, distribute, and sell this software and its
35 * documentation for any purpose is hereby granted without fee, provided that
36 * the above copyright notice appear in all copies and that both that
37 * copyright notice and this permission notice appear in supporting
38 * documentation.
39 *
40 * The above copyright notice and this permission notice shall be included in
41 * all copies or substantial portions of the Software.
42 *
43 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
44 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
45 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
46 * OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
47 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
48 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
49 *
50 * Except as contained in this notice, the name of the X Consortium shall not be
51 * used in advertising or otherwise to promote the sale, use or other dealings
52 * in this Software without prior written authorization from the X Consortium.
53 *
54 * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
55 *
56 * All Rights Reserved
57 *
58 * Permission to use, copy, modify, and distribute this software and its
59 * documentation for any purpose and without fee is hereby granted,
60 * provided that the above copyright notice appear in all copies and that
61 * both that copyright notice and this permission notice appear in
62 * supporting documentation, and that the name of Digital Equipment
63 * Corporation not be used in advertising or publicity pertaining to
64 * distribution of the software without specific, written prior permission.
65 *
66 *
67 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
68 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
69 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
70 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
71 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
72 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
73 * SOFTWARE.
74 */
75
76 /* Tekproc.c */
77
78 #define RES_OFFSET(field) XtOffsetOf(TekWidgetRec, field)
79
80 #include <xterm.h>
81
82 #include <X11/Xatom.h>
83 #include <X11/Xutil.h>
84 #include <X11/Xmu/CharSet.h>
85
86 #if OPT_TOOLBAR
87
88 #if defined(HAVE_LIB_XAW)
89 #include <X11/Xaw/Form.h>
90 #elif defined(HAVE_LIB_XAW3D)
91 #include <X11/Xaw3d/Form.h>
92 #elif defined(HAVE_LIB_XAW3DXFT)
93 #include <X11/Xaw3dxft/Form.h>
94 #elif defined(HAVE_LIB_NEXTAW)
95 #include <X11/neXtaw/Form.h>
96 #elif defined(HAVE_LIB_XAWPLUS)
97 #include <X11/XawPlus/Form.h>
98 #endif
99
100 #endif /* OPT_TOOLBAR */
101
102 #include <assert.h>
103 #include <stdio.h>
104 #include <ctype.h>
105 #include <signal.h>
106
107 #include <Tekparse.h>
108 #include <data.h>
109 #include <error.h>
110 #include <menu.h>
111 #include <xstrings.h>
112
113 #define DefaultGCID(tw) \
114 XGContextFromGC(DefaultGC(XtDisplay(tw), \
115 DefaultScreen(XtDisplay(tw))))
116
117 /* Tek defines */
118
119 #define MY_CLASS "Tek4014"
120 #define MY_NAME "tek4014"
121
122 #define SOLIDLINE 0
123 #define DOTTEDLINE 1
124 #define DOTDASHEDLINE 2
125 #define SHORTDASHEDLINE 3
126 #define LONGDASHEDLINE 4
127
128 #define EAST 001
129 #define WEST 002
130 #define NORTH 004
131 #define SOUTH 010
132
133 #define LINEMASK 07
134 #define MARGIN1 0
135 #define MARGIN2 1
136 #define MAX_PTS 150
137 #define MAX_VTX 300
138 #define PENDOWN 1
139 #define PENUP 0
140 #define TEKBOTTOMPAD 23
141 #define TEKDEFHEIGHT 565
142 #define TEKDEFWIDTH 750
143 #define TEKHEIGHT 3072
144 #define TEKHOME ( (TekChar[tekscr->page.fontsize].nlines - 1) \
145 * TekChar[tekscr->page.fontsize].vsize)
146 #define TEKMINHEIGHT 452
147 #define TEKMINWIDTH 600
148 #define TEKTOPPAD 34
149 #define TEKWIDTH 4096
150
151 #define FULL_HEIGHT (TEKHEIGHT + TEKTOPPAD + TEKBOTTOMPAD)
152
153 #define BottomY(y) (TEKHEIGHT + TEKTOPPAD - (y))
154 #define BorderOf(tw) (TScreenOf((tw)->vt)->border)
155 #define ScaleOf(tw) TekScale(TekScreenOf(tw))
156 #define ScaledX(tw,x) (((x) * ScaleOf(tw)) + BorderOf(tw))
157 #define ScaledY(tw,y) ((BottomY(y) * ScaleOf(tw)) + BorderOf(tw))
158
159 #define TekMove(tw,x,y) do { tekscr->cur_X = x; tekscr->cur_Y = y; } while (0)
160 #define input() Tinput(tw)
161 #define unput(c) *Tpushback++ = (Char) c
162 /* *INDENT-OFF* */
163 static const struct Tek_Char {
164 int hsize; /* in Tek units */
165 int vsize; /* in Tek units */
166 int charsperline;
167 int nlines;
168 } TekChar[TEKNUMFONTS] = {
169 {56, 88, 74, 35}, /* large */
170 {51, 82, 81, 38}, /* #2 */
171 {34, 53, 121, 58}, /* #3 */
172 {31, 48, 133, 64}, /* small */
173 };
174 /* *INDENT-ON* */
175
176 static Cursor GINcursor;
177 static XSegment *line_pt;
178 static int nplot;
179 static TekLink Tek0;
180 static jmp_buf Tekjump;
181 static TekLink *TekRecord;
182 static XSegment *Tline;
183
184 static Const int *curstate = Talptable;
185 static Const int *Tparsestate = Talptable;
186
187 static char defaultTranslations[] = "\
188 ~Meta<KeyPress>: insert-seven-bit() \n\
189 Meta<KeyPress>: insert-eight-bit() \n\
190 !Ctrl <Btn1Down>: popup-menu(mainMenu) \n\
191 !Lock Ctrl <Btn1Down>: popup-menu(mainMenu) \n\
192 !Lock Ctrl @Num_Lock <Btn1Down>: popup-menu(mainMenu) \n\
193 !Ctrl @Num_Lock <Btn1Down>: popup-menu(mainMenu) \n\
194 !Ctrl <Btn2Down>: popup-menu(tekMenu) \n\
195 !Lock Ctrl <Btn2Down>: popup-menu(tekMenu) \n\
196 !Lock Ctrl @Num_Lock <Btn2Down>: popup-menu(tekMenu) \n\
197 !Ctrl @Num_Lock <Btn2Down>: popup-menu(tekMenu) \n\
198 Shift ~Meta<Btn1Down>: gin-press(L) \n\
199 ~Meta<Btn1Down>: gin-press(l) \n\
200 Shift ~Meta<Btn2Down>: gin-press(M) \n\
201 ~Meta<Btn2Down>: gin-press(m) \n\
202 Shift ~Meta<Btn3Down>: gin-press(R) \n\
203 ~Meta<Btn3Down>: gin-press(r)";
204 /* *INDENT-OFF* */
205 static XtActionsRec actionsList[] = {
206 { "string", HandleStringEvent },
207 { "insert", HandleKeyPressed }, /* alias for insert-seven-bit */
208 { "insert-seven-bit", HandleKeyPressed },
209 { "insert-eight-bit", HandleEightBitKeyPressed },
210 { "gin-press", HandleGINInput },
211 { "secure", HandleSecure },
212 { "create-menu", HandleCreateMenu },
213 { "popup-menu", HandlePopupMenu },
214 /* menu actions */
215 { "allow-send-events", HandleAllowSends },
216 { "set-visual-bell", HandleSetVisualBell },
217 #ifdef ALLOWLOGGING
218 { "set-logging", HandleLogging },
219 #endif
220 { "redraw", HandleRedraw },
221 { "send-signal", HandleSendSignal },
222 { "quit", HandleQuit },
223 { "set-scrollbar", HandleScrollbar },
224 { "set-jumpscroll", HandleJumpscroll },
225 { "set-reverse-video", HandleReverseVideo },
226 { "set-autowrap", HandleAutoWrap },
227 { "set-reversewrap", HandleReverseWrap },
228 { "set-autolinefeed", HandleAutoLineFeed },
229 { "set-appcursor", HandleAppCursor },
230 { "set-appkeypad", HandleAppKeypad },
231 { "set-scroll-on-key", HandleScrollKey },
232 { "set-scroll-on-tty-output", HandleScrollTtyOutput },
233 { "set-allow132", HandleAllow132 },
234 { "set-cursesemul", HandleCursesEmul },
235 { "set-marginbell", HandleMarginBell },
236 { "set-altscreen", HandleAltScreen },
237 { "soft-reset", HandleSoftReset },
238 { "hard-reset", HandleHardReset },
239 { "set-terminal-type", HandleSetTerminalType },
240 { "set-visibility", HandleVisibility },
241 { "set-tek-text", HandleSetTekText },
242 { "tek-page", HandleTekPage },
243 { "tek-reset", HandleTekReset },
244 { "tek-copy", HandleTekCopy },
245 #if OPT_TOOLBAR
246 { "set-toolbar", HandleToolbar },
247 #endif
248 };
249 /* *INDENT-ON* */
250
251 static Dimension defOne = 1;
252
253 #define GIN_TERM_NONE_STR "none"
254 #define GIN_TERM_CR_STR "CRonly"
255 #define GIN_TERM_EOT_STR "CR&EOT"
256
257 #define GIN_TERM_NONE 0
258 #define GIN_TERM_CR 1
259 #define GIN_TERM_EOT 2
260
261 #ifdef VMS
262 #define DFT_FONT_SMALL "FIXED"
263 #else
264 #define DFT_FONT_SMALL "6x10"
265 #endif
266
267 static XtResource resources[] =
268 {
269 {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
270 XtOffsetOf(CoreRec, core.width), XtRDimension, (caddr_t) & defOne},
271 {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
272 XtOffsetOf(CoreRec, core.height), XtRDimension, (caddr_t) & defOne},
273 Fres("fontLarge", XtCFont, tek.Tfont[TEK_FONT_LARGE], "9x15"),
274 Fres("font2", XtCFont, tek.Tfont[TEK_FONT_2], "6x13"),
275 Fres("font3", XtCFont, tek.Tfont[TEK_FONT_3], "8x13"),
276 Fres("fontSmall", XtCFont, tek.Tfont[TEK_FONT_SMALL], DFT_FONT_SMALL),
277 Sres(XtNinitialFont, XtCInitialFont, tek.initial_font, "large"),
278 Sres("ginTerminator", "GinTerminator", tek.gin_terminator_str, GIN_TERM_NONE_STR),
279 #if OPT_TOOLBAR
280 Wres(XtNmenuBar, XtCMenuBar, tek.tb_info.menu_bar, 0),
281 Ires(XtNmenuHeight, XtCMenuHeight, tek.tb_info.menu_height, 25),
282 #endif
283 };
284
285 static IChar Tinput(TekWidget /* tw */ );
286 static int getpoint(TekWidget /* tw */ );
287 static void TCursorBack(TekWidget /* tw */ );
288 static void TCursorDown(TekWidget /* tw */ );
289 static void TCursorForward(TekWidget /* tw */ );
290 static void TCursorUp(TekWidget /* tw */ );
291 static void TekBackground(TekWidget /* tw */ ,
292 TScreen * /* screen */ );
293 static void TekResize(Widget /* w */ );
294 static void TekDraw(TekWidget /* tw */ ,
295 int /* x */ ,
296 int /* y */ );
297 static void TekEnq(TekWidget /* tw */ ,
298 unsigned /* status */ ,
299 int /* x */ ,
300 int /* y */ );
301 static void TekFlush(TekWidget /* tw */ );
302 static void TekInitialize(Widget /* request */ ,
303 Widget /* wnew */ ,
304 ArgList /* args */ ,
305 Cardinal * /* num_args */ );
306 static void TekPage(TekWidget /* tw */ );
307 static void TekRealize(Widget /* gw */ ,
308 XtValueMask * /* valuemaskp */ ,
309 XSetWindowAttributes * /* values */ );
310
311 static WidgetClassRec tekClassRec =
312 {
313 {
314 /* core_class fields */
315 (WidgetClass) & widgetClassRec, /* superclass */
316 MY_CLASS, /* class_name */
317 sizeof(TekWidgetRec), /* widget_size */
318 NULL, /* class_initialize */
319 NULL, /* class_part_initialize */
320 False, /* class_inited */
321 TekInitialize, /* initialize */
322 NULL, /* initialize_hook */
323 TekRealize, /* realize */
324 actionsList, /* actions */
325 XtNumber(actionsList), /* num_actions */
326 resources, /* resources */
327 XtNumber(resources), /* num_resources */
328 NULLQUARK, /* xrm_class */
329 True, /* compress_motion */
330 True, /* compress_exposure */
331 True, /* compress_enterleave */
332 False, /* visible_interest */
333 NULL, /* destroy */
334 TekResize, /* resize */
335 TekExpose, /* expose */
336 NULL, /* set_values */
337 NULL, /* set_values_hook */
338 XtInheritSetValuesAlmost, /* set_values_almost */
339 NULL, /* get_values_hook */
340 NULL, /* accept_focus */
341 XtVersion, /* version */
342 NULL, /* callback_offsets */
343 defaultTranslations, /* tm_table */
344 XtInheritQueryGeometry, /* query_geometry */
345 XtInheritDisplayAccelerator, /* display_accelerator */
346 NULL /* extension */
347 }
348 };
349 WidgetClass tekWidgetClass = (WidgetClass) & tekClassRec;
350
351 static Bool Tfailed = False;
352
353 /*
354 * TekInit/TekRun are called after the VT100 widget has been initialized, but
355 * may be before VT100 is realized, depending upon whether Tek4014 is the
356 * first window to be shown.
357 */
358 int
TekInit(void)359 TekInit(void)
360 {
361 Widget form_top, menu_top;
362 Dimension menu_high;
363
364 if (!Tfailed
365 && tekWidget == 0) {
366 Cardinal nargs = 0;
367 Arg myArgs[3];
368 Boolean iconic = 0;
369
370 TRACE(("TekInit\n"));
371 XtSetArg(myArgs[nargs], XtNiconic, &iconic);
372 ++nargs;
373 XtGetValues(toplevel, myArgs, nargs);
374
375 nargs = 0;
376 XtSetArg(myArgs[nargs], XtNiconic, iconic);
377 ++nargs;
378 XtSetArg(myArgs[nargs], XtNallowShellResize, True);
379 ++nargs;
380 XtSetArg(myArgs[nargs], XtNinput, True);
381 ++nargs;
382
383 /* this causes the Initialize method to be called */
384 tekshellwidget =
385 XtCreatePopupShell("tektronix", topLevelShellWidgetClass,
386 toplevel, myArgs, nargs);
387
388 SetupMenus(tekshellwidget, &form_top, &menu_top, &menu_high);
389
390 /* this causes the Realize method to be called */
391 tekWidget = (TekWidget)
392 XtVaCreateManagedWidget(MY_NAME,
393 tekWidgetClass, form_top,
394 #if OPT_TOOLBAR
395 XtNmenuBar, menu_top,
396 XtNresizable, True,
397 XtNfromVert, menu_top,
398 XtNtop, XawChainTop,
399 XtNleft, XawChainLeft,
400 XtNright, XawChainRight,
401 XtNbottom, XawChainBottom,
402 XtNmenuHeight, menu_high,
403 #endif
404 (XtPointer) 0);
405 TRACE(("created tek4014 widget %p, window %#lx\n",
406 (void *) tekWidget, XtWindow(tekWidget)));
407 #if OPT_TOOLBAR
408 ShowToolbar(resource.toolBar);
409 #endif
410 }
411 return (!Tfailed);
412 }
413
414 /*
415 * If we haven't allocated the PtyData struct, do so.
416 */
417 static int
TekPtyData(void)418 TekPtyData(void)
419 {
420 if (Tpushb == 0 && !Tfailed) {
421 if ((Tpushb = TypeMallocN(Char, 10)) == NULL
422 || (Tline = TypeMallocN(XSegment, MAX_VTX)) == NULL) {
423 xtermWarning("Not enough core for Tek mode\n");
424 free(Tpushb);
425 Tfailed = True;
426 }
427 }
428 return (Tfailed ? 0 : 1);
429 }
430
431 static void
Tekparse(TekWidget tw)432 Tekparse(TekWidget tw)
433 {
434 TekScreen *tekscr = TekScreenOf(tw);
435 TScreen *screen = TScreenOf(tw->vt);
436 int x, y;
437 IChar ch;
438 int nextstate;
439
440 for (;;) {
441 IChar c = input();
442 /*
443 * The parsing tables all have 256 entries. If we're supporting
444 * wide characters, we handle them by treating them the same as
445 * printing characters.
446 */
447 #if OPT_WIDE_CHARS
448 if (c > 255) {
449 nextstate = (Tparsestate == Talptable)
450 ? CASE_PRINT
451 : CASE_IGNORE;
452 } else
453 #endif
454 nextstate = Tparsestate[c];
455 TRACE(("Tekparse %04X -> %d\n", c, nextstate));
456
457 switch (nextstate) {
458 case CASE_REPORT:
459 TRACE(("case: report address\n"));
460 if (tekscr->TekGIN) {
461 TekGINoff(tw);
462 TekEnqMouse(tw, 0);
463 } else {
464 c = 064; /* has hard copy unit */
465 if (tekscr->margin == MARGIN2)
466 c |= 02;
467 TekEnq(tw, c, tekscr->cur_X, tekscr->cur_Y);
468 }
469 TekRecord->ptr[-1] = ANSI_NAK; /* remove from recording */
470 Tparsestate = curstate;
471 break;
472
473 case CASE_VT_MODE:
474 TRACE(("case: special return to vt102 mode\n"));
475 Tparsestate = curstate;
476 TekRecord->ptr[-1] = ANSI_NAK; /* remove from recording */
477 FlushLog(tw->vt);
478 return;
479
480 case CASE_SPT_STATE:
481 TRACE(("case: Enter Special Point Plot mode\n"));
482 if (tekscr->TekGIN)
483 TekGINoff(tw);
484 Tparsestate = curstate = Tspttable;
485 break;
486
487 case CASE_GIN:
488 TRACE(("case: Do Tek GIN mode\n"));
489 tekscr->TekGIN = &TekRecord->ptr[-1];
490 /* Set cross-hair cursor raster array */
491 if ((GINcursor =
492 make_colored_cursor(XC_tcross,
493 T_COLOR(screen, MOUSE_FG),
494 T_COLOR(screen, MOUSE_BG))) != 0) {
495 XDefineCursor(XtDisplay(tw), TWindow(tekscr),
496 GINcursor);
497 }
498 Tparsestate = Tbyptable; /* Bypass mode */
499 break;
500
501 case CASE_BEL:
502 TRACE(("case: BEL\n"));
503 if (tekscr->TekGIN)
504 TekGINoff(tw);
505 if (!tekRefreshList)
506 Bell(tw->vt, XkbBI_TerminalBell, 0);
507 Tparsestate = curstate; /* clear bypass condition */
508 break;
509
510 case CASE_BS:
511 TRACE(("case: BS\n"));
512 if (tekscr->TekGIN)
513 TekGINoff(tw);
514 Tparsestate = curstate; /* clear bypass condition */
515 TCursorBack(tw);
516 break;
517
518 case CASE_PT_STATE:
519 TRACE(("case: Enter Tek Point Plot mode\n"));
520 if (tekscr->TekGIN)
521 TekGINoff(tw);
522 Tparsestate = curstate = Tpttable;
523 break;
524
525 case CASE_PLT_STATE:
526 TRACE(("case: Enter Tek Plot mode\n"));
527 if (tekscr->TekGIN)
528 TekGINoff(tw);
529 Tparsestate = curstate = Tplttable;
530 if ((c = input()) == ANSI_BEL)
531 tekscr->pen = PENDOWN;
532 else {
533 unput(c);
534 tekscr->pen = PENUP;
535 }
536 break;
537
538 case CASE_TAB:
539 TRACE(("case: HT\n"));
540 if (tekscr->TekGIN)
541 TekGINoff(tw);
542 Tparsestate = curstate; /* clear bypass condition */
543 TCursorForward(tw);
544 break;
545
546 case CASE_IPL_STATE:
547 TRACE(("case: Enter Tek Incremental Plot mode\n"));
548 if (tekscr->TekGIN)
549 TekGINoff(tw);
550 Tparsestate = curstate = Tipltable;
551 break;
552
553 case CASE_ALP_STATE:
554 TRACE(("case: Enter Tek Alpha mode from any other mode\n"));
555 if (tekscr->TekGIN)
556 TekGINoff(tw);
557 /* if in one of graphics states, move alpha cursor */
558 if (nplot > 0) /* flush line VTbuffer */
559 TekFlush(tw);
560 Tparsestate = curstate = Talptable;
561 break;
562
563 case CASE_UP:
564 TRACE(("case: cursor up\n"));
565 if (tekscr->TekGIN)
566 TekGINoff(tw);
567 Tparsestate = curstate; /* clear bypass condition */
568 TCursorUp(tw);
569 break;
570
571 case CASE_COPY:
572 TRACE(("case: make copy\n"));
573 if (tekscr->TekGIN)
574 TekGINoff(tw);
575 TekCopy(tw);
576 TekRecord->ptr[-1] = ANSI_NAK; /* remove from recording */
577 Tparsestate = curstate; /* clear bypass condition */
578 break;
579
580 case CASE_PAGE:
581 TRACE(("case: Page Function\n"));
582 if (tekscr->TekGIN)
583 TekGINoff(tw);
584 TekPage(tw); /* clear bypass condition */
585 break;
586
587 case CASE_BES_STATE:
588 TRACE(("case: Byp: an escape char\n"));
589 Tparsestate = Tbestable;
590 break;
591
592 case CASE_BYP_STATE:
593 TRACE(("case: set bypass condition\n"));
594 Tparsestate = Tbyptable;
595 break;
596
597 case CASE_IGNORE:
598 TRACE(("case: Esc: totally ignore CR, ESC, LF, ~\n"));
599 break;
600
601 case CASE_ASCII:
602 TRACE(("case: Select ASCII char set\n"));
603 /* ignore for now */
604 Tparsestate = curstate;
605 break;
606
607 case CASE_APL:
608 TRACE(("case: Select APL char set\n"));
609 /* ignore for now */
610 Tparsestate = curstate;
611 break;
612
613 case CASE_CHAR_SIZE:
614 TRACE(("case: character size selector\n"));
615 TekSetFontSize(tw, False, (int) (c & 03));
616 Tparsestate = curstate;
617 break;
618
619 case CASE_BEAM_VEC:
620 TRACE(("case: beam and vector selector\n"));
621 /* only line types */
622 c = (IChar) (c & LINEMASK);
623 if (c != tekscr->cur.linetype) {
624 if (nplot > 0)
625 TekFlush(tw);
626 if (c <= TEKNUMLINES)
627 tekscr->cur.linetype = c;
628 }
629 Tparsestate = curstate;
630 break;
631
632 case CASE_CURSTATE:
633 Tparsestate = curstate;
634 break;
635
636 case CASE_PENUP:
637 TRACE(("case: Ipl: penup\n"));
638 tekscr->pen = PENUP;
639 break;
640
641 case CASE_PENDOWN:
642 TRACE(("case: Ipl: pendown\n"));
643 tekscr->pen = PENDOWN;
644 break;
645
646 case CASE_IPL_POINT:
647 TRACE(("case: Ipl: point\n"));
648 x = tekscr->cur_X;
649 y = tekscr->cur_Y;
650 if (c & NORTH)
651 y++;
652 else if (c & SOUTH)
653 y--;
654 if (c & EAST)
655 x++;
656 else if (c & WEST)
657 x--;
658 if (tekscr->pen == PENDOWN) {
659 TekDraw(tw, x, y);
660 } else {
661 TekMove(tw, x, y);
662 }
663 break;
664
665 case CASE_PLT_VEC:
666 TRACE(("case: Plt: vector\n"));
667 unput(c);
668 if (getpoint(tw)) {
669 if (tekscr->pen == PENDOWN) {
670 TekDraw(tw, tekscr->cur.x, tekscr->cur.y);
671 } else {
672 TekMove(tw, tekscr->cur.x, tekscr->cur.y);
673 }
674 tekscr->pen = PENDOWN;
675 }
676 break;
677
678 case CASE_PT_POINT:
679 TRACE(("case: Pt: point\n"));
680 unput(c);
681 if (getpoint(tw)) {
682 TekMove(tw, tekscr->cur.x, tekscr->cur.y);
683 TekDraw(tw, tekscr->cur.x, tekscr->cur.y);
684 }
685 break;
686
687 case CASE_SPT_POINT:
688 TRACE(("case: Spt: point\n"));
689 /* ignore intensity character in c */
690 if (getpoint(tw)) {
691 TekMove(tw, tekscr->cur.x, tekscr->cur.y);
692 TekDraw(tw, tekscr->cur.x, tekscr->cur.y);
693 }
694 break;
695
696 case CASE_CR:
697 TRACE(("case: CR\n"));
698 if (tekscr->TekGIN)
699 TekGINoff(tw);
700 if (nplot > 0) /* flush line VTbuffer */
701 TekFlush(tw);
702 tekscr->cur_X = tekscr->margin == MARGIN1 ? 0 :
703 TEKWIDTH / 2;
704 Tparsestate = curstate = Talptable;
705 break;
706
707 case CASE_ESC_STATE:
708 TRACE(("case: ESC\n"));
709 Tparsestate = Tesctable;
710 break;
711
712 case CASE_LF:
713 TRACE(("case: LF\n"));
714 if (tekscr->TekGIN)
715 TekGINoff(tw);
716 TCursorDown(tw);
717 if (!tekRefreshList)
718 do_xevents(tw->vt);
719 break;
720
721 case CASE_SP:
722 TRACE(("case: SP\n"));
723 TCursorForward(tw);
724 break;
725
726 case CASE_PRINT:
727 TRACE(("case: printable character\n"));
728 ch = c;
729 x = (int) ScaledX(tw, tekscr->cur_X);
730 y = (int) ScaledY(tw, tekscr->cur_Y);
731
732 #if OPT_WIDE_CHARS
733 if (screen->wide_chars
734 && (ch > 255)) {
735 XChar2b sbuf;
736 sbuf.byte2 = LO_BYTE(ch);
737 sbuf.byte1 = HI_BYTE(ch);
738 XDrawImageString16(XtDisplay(tw),
739 TWindow(tekscr),
740 tekscr->TnormalGC,
741 x,
742 y,
743 &sbuf,
744 1);
745 } else
746 #endif
747 {
748 char ch2 = (char) ch;
749 XDrawString(XtDisplay(tw),
750 TWindow(tekscr),
751 tekscr->TnormalGC,
752 x,
753 y,
754 &ch2,
755 1);
756 }
757 TCursorForward(tw);
758 break;
759 case CASE_OSC:
760 /* FIXME: someone should disentangle the input queues
761 * of this code so that it can be state-driven.
762 */
763 TRACE(("case: do osc escape\n"));
764 {
765 /*
766 * do_osc() can call TekExpose(), which calls TekRefresh(),
767 * and sends us recurring here - don't do that...
768 */
769 static int nested;
770
771 Char buf2[512];
772 IChar c2;
773 size_t len = 0;
774 while ((c2 = input()) != ANSI_BEL) {
775 if (!isprint((int) (c2 & 0x7f))
776 || len + 2 >= (int) sizeof(buf2))
777 break;
778 buf2[len++] = (Char) c2;
779 }
780 buf2[len] = 0;
781 if (!nested++) {
782 if (c2 == ANSI_BEL)
783 do_osc(tw->vt, buf2, len, ANSI_BEL);
784 }
785 --nested;
786 }
787 Tparsestate = curstate;
788 break;
789 }
790 }
791 }
792
793 static int rcnt;
794 static char *rptr;
795 static PtySelect Tselect_mask;
796
797 static IChar
Tinput(TekWidget tw)798 Tinput(TekWidget tw)
799 {
800 TekScreen *tekscr = TekScreenOf(tw);
801 TScreen *screen = TScreenOf(tw->vt);
802 TekLink *tek;
803
804 if (Tpushback > Tpushb)
805 return (*--Tpushback);
806 if (tekRefreshList) {
807 if (rcnt-- > 0)
808 return (IChar) (*rptr++);
809 if ((tek = tekRefreshList->next) != 0) {
810 tekRefreshList = tek;
811 rptr = tek->data;
812 rcnt = tek->count - 1;
813 TekSetFontSize(tw, False, tek->fontsize);
814 return (IChar) (*rptr++);
815 }
816 tekRefreshList = (TekLink *) 0;
817 longjmp(Tekjump, 1);
818 }
819 again:
820 if (VTbuffer->next >= VTbuffer->last) {
821 int update = VTbuffer->update;
822
823 if (nplot > 0) /* flush line */
824 TekFlush(tw);
825 #ifdef VMS
826 Tselect_mask = pty_mask; /* force a read */
827 #else /* VMS */
828 XFD_COPYSET(&pty_mask, &Tselect_mask);
829 #endif /* VMS */
830 for (;;) {
831 #ifdef CRAY
832 struct timeval crocktimeout;
833 crocktimeout.tv_sec = 0;
834 crocktimeout.tv_usec = 0;
835 (void) Select(max_plus1,
836 &Tselect_mask, NULL, NULL,
837 &crocktimeout);
838 #endif
839 if (readPtyData(tw->vt, &Tselect_mask, VTbuffer)) {
840 break;
841 }
842 if (Ttoggled && curstate == Talptable) {
843 TCursorToggle(tw, TOGGLE);
844 Ttoggled = False;
845 }
846 if (xtermAppPending() & XtIMXEvent) {
847 #ifdef VMS
848 Tselect_mask = X_mask;
849 #else /* VMS */
850 XFD_COPYSET(&X_mask, &Tselect_mask);
851 #endif /* VMS */
852 } else {
853 XFlush(XtDisplay(tw));
854 #ifdef VMS
855 Tselect_mask = Select_mask;
856
857 #else /* VMS */
858 XFD_COPYSET(&Select_mask, &Tselect_mask);
859 if (Select(max_plus1, &Tselect_mask, NULL, NULL, NULL) < 0) {
860 if (errno != EINTR)
861 SysError(ERROR_TSELECT);
862 continue;
863 }
864 #endif /* VMS */
865 }
866 #ifdef VMS
867 if (Tselect_mask & X_mask) {
868 xevents(tw->vt);
869 if (VTbuffer->update != update)
870 goto again;
871 }
872 #else /* VMS */
873 if (FD_ISSET(ConnectionNumber(XtDisplay(tw)), &Tselect_mask)) {
874 xevents(tw->vt);
875 if (VTbuffer->update != update)
876 goto again;
877 }
878 #endif /* VMS */
879 }
880 if (!Ttoggled && curstate == Talptable) {
881 TCursorToggle(tw, TOGGLE);
882 Ttoggled = True;
883 }
884 }
885 tek = TekRecord;
886 if (tek->count >= TEK_LINK_BLOCK_SIZE
887 || tek->fontsize != tekscr->cur.fontsize) {
888 if ((TekRecord = tek->next = CastMalloc(TekLink)) == 0) {
889 Panic("Tinput: malloc error (%d)\n", errno);
890 } else {
891 tek = tek->next;
892 tek->next = (TekLink *) 0;
893 tek->fontsize = (unsigned short) tekscr->cur.fontsize;
894 tek->count = 0;
895 tek->ptr = tek->data;
896 }
897 }
898 tek->count++;
899
900 (void) morePtyData(screen, VTbuffer);
901 return (IChar) (*tek->ptr++ = (char) nextPtyData(screen, VTbuffer));
902 }
903
904 static void
TekClear(TekWidget tw)905 TekClear(TekWidget tw)
906 {
907 TekScreen *tekscr = TekScreenOf(tw);
908
909 TRACE(("TekClear\n"));
910 nplot = 0;
911 line_pt = Tline;
912 if (TWindow(tekscr))
913 XClearWindow(XtDisplay(tw), TWindow(tekscr));
914 }
915
916 void
TekSetWinSize(TekWidget tw)917 TekSetWinSize(TekWidget tw)
918 {
919 if (TEK4014_ACTIVE(tw->vt)) {
920 TekScreen *tekscr = TekScreenOf(tw);
921 const struct Tek_Char *t = &TekChar[tekscr->cur.fontsize];
922 int rows = THeight(tekscr) / (int) (ScaleOf(tw) * t->vsize);
923 int cols = TWidth(tekscr) / (int) (ScaleOf(tw) * t->hsize);
924
925 update_winsize(TScreenOf(tw->vt)->respond,
926 rows, cols,
927 TFullHeight(tekscr),
928 TFullWidth(tekscr));
929 }
930 }
931
932 static void
compute_sizes(TekWidget tw)933 compute_sizes(TekWidget tw)
934 {
935 TekScreen *tekscr = TekScreenOf(tw);
936 int border = 2 * BorderOf(tw);
937 double d;
938 #if OPT_TRACE
939 const struct Tek_Char *t = &TekChar[tekscr->cur.fontsize];
940 const XFontStruct *fs = tw->tek.Tfont[tekscr->cur.fontsize];
941 #endif
942
943 /* *INDENT-EQLS* */
944 TWidth(tekscr) = tw->core.width - border;
945 THeight(tekscr) = tw->core.height - border;
946 ScaleOf(tw) = (double) TWidth(tekscr) / TEKWIDTH;
947
948 if ((d = (double) THeight(tekscr) / FULL_HEIGHT) < ScaleOf(tw))
949 ScaleOf(tw) = d;
950
951 TFullWidth(tekscr) = tw->core.width;
952 TFullHeight(tekscr) = tw->core.height;
953
954 TRACE(("%s size %dx%d full %dx%d scale %.2f\n", MY_NAME,
955 THeight(tekscr), TWidth(tekscr),
956 TFullHeight(tekscr), TFullWidth(tekscr),
957 ScaleOf(tw)));
958
959 /* The tek4014 fonts always look odd since their spacing is overridden to
960 * get the "same" size as a real Tektronix terminal. TrueType fonts for
961 * these small sizes would be no better...
962 */
963 TRACE(("unscaled font %dx%d\n", t->vsize, t->hsize));
964 TRACE(("scaled font %.1fx%.1f\n", d * t->vsize, d * t->hsize));
965 TRACE(("actual font %dx%d\n",
966 fs->max_bounds.ascent + fs->max_bounds.descent,
967 fs->max_bounds.width));
968
969 TekSetWinSize(tw);
970 }
971
972 static void
TekResize(Widget w)973 TekResize(Widget w)
974 {
975 TekWidget tw = getTekWidget(w);
976 if (tw != 0) {
977
978 TRACE(("TekResize " TRACE_L "\n"));
979 TekClear(tw);
980
981 compute_sizes(tw);
982
983 TRACE((TRACE_R " TekResize\n"));
984 }
985 }
986
987 /*ARGSUSED*/
988 void
TekExpose(Widget w,XEvent * event GCC_UNUSED,Region region GCC_UNUSED)989 TekExpose(Widget w,
990 XEvent *event GCC_UNUSED,
991 Region region GCC_UNUSED)
992 {
993 TekWidget tw = getTekWidget(w);
994 if (tw != 0) {
995 TekScreen *tekscr = TekScreenOf(tw);
996
997 TRACE(("TekExpose " TRACE_L "\n"));
998
999 #ifdef lint
1000 region = region;
1001 #endif
1002 if (!Ttoggled)
1003 TCursorToggle(tw, CLEAR);
1004 Ttoggled = True;
1005 Tpushback = Tpushb;
1006 tekscr->cur_X = 0;
1007 tekscr->cur_Y = TEKHOME;
1008 tekscr->cur = tekscr->page;
1009 TekSetFontSize(tw, False, tekscr->cur.fontsize);
1010 tekscr->margin = MARGIN1;
1011 if (tekscr->TekGIN) {
1012 tekscr->TekGIN = NULL;
1013 TekGINoff(tw);
1014 }
1015 tekRefreshList = &Tek0;
1016 rptr = tekRefreshList->data;
1017 rcnt = tekRefreshList->count;
1018 Tparsestate = curstate = Talptable;
1019 TRACE(("TekExpose resets data to replay %d bytes\n", rcnt));
1020 first_map_occurred();
1021 if (!tekscr->waitrefresh)
1022 TekRefresh(tw);
1023 TRACE((TRACE_R " TekExpose\n"));
1024 }
1025 }
1026
1027 void
TekRefresh(TekWidget tw)1028 TekRefresh(TekWidget tw)
1029 {
1030 if (tw != 0) {
1031 TScreen *screen = TScreenOf(tw->vt);
1032 TekScreen *tekscr = TekScreenOf(tw);
1033 static Cursor wait_cursor = None;
1034
1035 if (wait_cursor == None)
1036 wait_cursor = make_colored_cursor(XC_watch,
1037 T_COLOR(screen, MOUSE_FG),
1038 T_COLOR(screen, MOUSE_BG));
1039 XDefineCursor(XtDisplay(tw), TWindow(tekscr), wait_cursor);
1040 XFlush(XtDisplay(tw));
1041 if (!setjmp(Tekjump))
1042 Tekparse(tw);
1043 XDefineCursor(XtDisplay(tw), TWindow(tekscr),
1044 (tekscr->TekGIN && GINcursor) ? GINcursor : tekscr->arrow);
1045 }
1046 }
1047
1048 void
TekRepaint(TekWidget tw)1049 TekRepaint(TekWidget tw)
1050 {
1051 TRACE(("TekRepaint\n"));
1052 TekClear(tw);
1053 TekExpose((Widget) tw, (XEvent *) NULL, (Region) NULL);
1054 }
1055
1056 static void
TekPage(TekWidget tw)1057 TekPage(TekWidget tw)
1058 {
1059 TekScreen *tekscr = TekScreenOf(tw);
1060 TekLink *tek;
1061
1062 TRACE(("TekPage\n"));
1063 TekClear(tw);
1064 tekscr->cur_X = 0;
1065 tekscr->cur_Y = TEKHOME;
1066 tekscr->margin = MARGIN1;
1067 tekscr->page = tekscr->cur;
1068 if (tekscr->TekGIN)
1069 TekGINoff(tw);
1070 tek = TekRecord = &Tek0;
1071 tek->fontsize = (unsigned short) tekscr->cur.fontsize;
1072 tek->count = 0;
1073 tek->ptr = tek->data;
1074 tek = tek->next;
1075 if (tek)
1076 do {
1077 TekLink *tek2 = tek->next;
1078
1079 free(tek);
1080 tek = tek2;
1081 } while (tek);
1082 TekRecord->next = (TekLink *) 0;
1083 tekRefreshList = (TekLink *) 0;
1084 Ttoggled = True;
1085 Tparsestate = curstate = Talptable; /* Tek Alpha mode */
1086 }
1087
1088 #define EXTRABITS 017
1089 #define FIVEBITS 037
1090 #define HIBITS (FIVEBITS << SHIFTHI)
1091 #define LOBITS (FIVEBITS << SHIFTLO)
1092 #define SHIFTHI 7
1093 #define SHIFTLO 2
1094 #define TWOBITS 03
1095
1096 static int
getpoint(TekWidget tw)1097 getpoint(TekWidget tw)
1098 {
1099 int x, y, e, lo_y = 0;
1100 TekScreen *tekscr = TekScreenOf(tw);
1101
1102 x = tekscr->cur.x;
1103 y = tekscr->cur.y;
1104
1105 for (;;) {
1106 int c;
1107
1108 if ((c = (int) input()) < ' ') { /* control character */
1109 unput(c);
1110 return (0);
1111 }
1112 if (c < '@') { /* Hi X or Hi Y */
1113 if (lo_y) { /* seen a Lo Y, so this must be Hi X */
1114 x &= ~HIBITS;
1115 x |= (c & FIVEBITS) << SHIFTHI;
1116 continue;
1117 }
1118 /* else Hi Y */
1119 y &= ~HIBITS;
1120 y |= (c & FIVEBITS) << SHIFTHI;
1121 continue;
1122 }
1123 if (c < '`') { /* Lo X */
1124 x &= ~LOBITS;
1125 x |= (c & FIVEBITS) << SHIFTLO;
1126 tekscr->cur.x = x;
1127 tekscr->cur.y = y;
1128 return (1); /* OK */
1129 }
1130 /* else Lo Y */
1131 if (lo_y) { /* seen a Lo Y, so other must be extra bits */
1132 e = (y >> SHIFTLO) & EXTRABITS;
1133 x &= ~TWOBITS;
1134 x |= e & TWOBITS;
1135 y &= ~TWOBITS;
1136 y |= (e >> SHIFTLO) & TWOBITS;
1137 }
1138 y &= ~LOBITS;
1139 y |= (c & FIVEBITS) << SHIFTLO;
1140 lo_y++;
1141 }
1142 }
1143
1144 static void
TCursorBack(TekWidget tw)1145 TCursorBack(TekWidget tw)
1146 {
1147 TekScreen *tekscr = TekScreenOf(tw);
1148 const struct Tek_Char *t;
1149 int x = (tekscr->cur_X -= (t = &TekChar[tekscr->cur.fontsize])->hsize);
1150
1151 if (((tekscr->margin == MARGIN1) && (x < 0))
1152 || ((tekscr->margin == MARGIN2) && (x < TEKWIDTH / 2))) {
1153 int l = ((tekscr->cur_Y + (t->vsize - 1)) / t->vsize + 1);
1154 if (l >= t->nlines) {
1155 tekscr->margin = !tekscr->margin;
1156 l = 0;
1157 }
1158 tekscr->cur_Y = l * t->vsize;
1159 tekscr->cur_X = (t->charsperline - 1) * t->hsize;
1160 }
1161 }
1162
1163 static void
TCursorForward(TekWidget tw)1164 TCursorForward(TekWidget tw)
1165 {
1166 TekScreen *tekscr = TekScreenOf(tw);
1167 const struct Tek_Char *t = &TekChar[tekscr->cur.fontsize];
1168
1169 if ((tekscr->cur_X += t->hsize) > TEKWIDTH) {
1170 int l = (tekscr->cur_Y / t->vsize - 1);
1171 if (l < 0) {
1172 tekscr->margin = !tekscr->margin;
1173 l = t->nlines - 1;
1174 }
1175 tekscr->cur_Y = l * t->vsize;
1176 tekscr->cur_X = tekscr->margin == MARGIN1 ? 0 : TEKWIDTH / 2;
1177 }
1178 }
1179
1180 static void
TCursorUp(TekWidget tw)1181 TCursorUp(TekWidget tw)
1182 {
1183 TekScreen *tekscr = TekScreenOf(tw);
1184 const struct Tek_Char *t;
1185 int l;
1186
1187 t = &TekChar[tekscr->cur.fontsize];
1188
1189 if ((l = (tekscr->cur_Y + (t->vsize - 1)) / t->vsize + 1) >= t->nlines) {
1190 l = 0;
1191 if ((tekscr->margin = !tekscr->margin) != MARGIN1) {
1192 if (tekscr->cur_X < TEKWIDTH / 2)
1193 tekscr->cur_X += TEKWIDTH / 2;
1194 } else if (tekscr->cur_X >= TEKWIDTH / 2)
1195 tekscr->cur_X -= TEKWIDTH / 2;
1196 }
1197 tekscr->cur_Y = l * t->vsize;
1198 }
1199
1200 static void
TCursorDown(TekWidget tw)1201 TCursorDown(TekWidget tw)
1202 {
1203 TekScreen *tekscr = TekScreenOf(tw);
1204 const struct Tek_Char *t;
1205 int l;
1206
1207 t = &TekChar[tekscr->cur.fontsize];
1208
1209 if ((l = tekscr->cur_Y / t->vsize - 1) < 0) {
1210 l = t->nlines - 1;
1211 if ((tekscr->margin = !tekscr->margin) != MARGIN1) {
1212 if (tekscr->cur_X < TEKWIDTH / 2)
1213 tekscr->cur_X += TEKWIDTH / 2;
1214 } else if (tekscr->cur_X >= TEKWIDTH / 2)
1215 tekscr->cur_X -= TEKWIDTH / 2;
1216 }
1217 tekscr->cur_Y = l * t->vsize;
1218 }
1219
1220 static void
AddToDraw(TekWidget tw,int x1,int y1,int x2,int y2)1221 AddToDraw(TekWidget tw, int x1, int y1, int x2, int y2)
1222 {
1223 XSegment *lp;
1224
1225 TRACE(("AddToDraw (%d,%d) (%d,%d)\n", x1, y1, x2, y2));
1226 if (nplot >= MAX_PTS) {
1227 TekFlush(tw);
1228 }
1229 lp = line_pt++;
1230 lp->x1 = (short) ScaledX(tw, x1);
1231 lp->y1 = (short) ScaledY(tw, y1);
1232 lp->x2 = (short) ScaledX(tw, x2);
1233 lp->y2 = (short) ScaledY(tw, y2);
1234 nplot++;
1235 TRACE(("...AddToDraw %d points\n", nplot));
1236 }
1237
1238 static void
TekDraw(TekWidget tw,int x,int y)1239 TekDraw(TekWidget tw, int x, int y)
1240 {
1241 TekScreen *tekscr = TekScreenOf(tw);
1242
1243 if (nplot == 0 || T_lastx != tekscr->cur_X || T_lasty != tekscr->cur_Y) {
1244 /*
1245 * We flush on each unconnected line segment if the line
1246 * type is not solid. This solves a bug in X when drawing
1247 * points while the line type is not solid.
1248 */
1249 if (nplot > 0 && tekscr->cur.linetype != SOLIDLINE)
1250 TekFlush(tw);
1251 }
1252 AddToDraw(tw, tekscr->cur_X, tekscr->cur_Y, x, y);
1253 T_lastx = tekscr->cur_X = x;
1254 T_lasty = tekscr->cur_Y = y;
1255 }
1256
1257 static void
TekFlush(TekWidget tw)1258 TekFlush(TekWidget tw)
1259 {
1260 TekScreen *tekscr = TekScreenOf(tw);
1261
1262 TRACE(("TekFlush\n"));
1263 XDrawSegments(XtDisplay(tw), TWindow(tekscr),
1264 ((tekscr->cur.linetype == SOLIDLINE)
1265 ? tekscr->TnormalGC
1266 : tekscr->linepat[tekscr->cur.linetype - 1]),
1267 Tline, nplot);
1268 nplot = 0;
1269 line_pt = Tline;
1270 }
1271
1272 void
TekGINoff(TekWidget tw)1273 TekGINoff(TekWidget tw)
1274 {
1275 TekScreen *tekscr = TekScreenOf(tw);
1276
1277 TRACE(("TekGINoff\n"));
1278 XDefineCursor(XtDisplay(tw), TWindow(tekscr), tekscr->arrow);
1279 if (GINcursor)
1280 XFreeCursor(XtDisplay(tw), GINcursor);
1281 if (tekscr->TekGIN) {
1282 *tekscr->TekGIN = ANSI_CAN; /* modify recording */
1283 tekscr->TekGIN = NULL;
1284 }
1285 }
1286
1287 void
TekEnqMouse(TekWidget tw,int c)1288 TekEnqMouse(TekWidget tw, int c) /* character pressed */
1289 {
1290 TekScreen *tekscr = TekScreenOf(tw);
1291 int mousex, mousey, rootx, rooty;
1292 unsigned int mask; /* XQueryPointer */
1293 Window root, subw;
1294
1295 TRACE(("TekEnqMouse\n"));
1296 XQueryPointer(
1297 XtDisplay(tw), TWindow(tekscr),
1298 &root, &subw,
1299 &rootx, &rooty,
1300 &mousex, &mousey,
1301 &mask);
1302 if ((mousex = (int) ((mousex - BorderOf(tw)) / ScaleOf(tw))) < 0)
1303 mousex = 0;
1304 else if (mousex >= TEKWIDTH)
1305 mousex = TEKWIDTH - 1;
1306 if ((mousey = (int) BottomY((mousey - BorderOf(tw)) / ScaleOf(tw))) < 0)
1307 mousey = 0;
1308 else if (mousey >= TEKHEIGHT)
1309 mousey = TEKHEIGHT - 1;
1310 TekEnq(tw, (unsigned) c, mousex, mousey);
1311 }
1312
1313 static void
TekEnq(TekWidget tw,unsigned status,int x,int y)1314 TekEnq(TekWidget tw,
1315 unsigned status,
1316 int x,
1317 int y)
1318 {
1319 TScreen *screen = TScreenOf(tw->vt);
1320 TekScreen *tekscr = TekScreenOf(tw);
1321 Char cplot[7];
1322 int len = 5;
1323 int adj = (status != 0) ? 0 : 1;
1324
1325 TRACE(("TekEnq\n"));
1326 cplot[0] = (Char) status;
1327 /* Translate x and y to Tektronix code */
1328 cplot[1] = (Char) (040 | ((x >> SHIFTHI) & FIVEBITS));
1329 cplot[2] = (Char) (040 | ((x >> SHIFTLO) & FIVEBITS));
1330 cplot[3] = (Char) (040 | ((y >> SHIFTHI) & FIVEBITS));
1331 cplot[4] = (Char) (040 | ((y >> SHIFTLO) & FIVEBITS));
1332
1333 if (tekscr->gin_terminator != GIN_TERM_NONE)
1334 cplot[len++] = '\r';
1335 if (tekscr->gin_terminator == GIN_TERM_EOT)
1336 cplot[len++] = '\004';
1337 #ifdef VMS
1338 tt_write(cplot + adj, len - adj);
1339 #else /* VMS */
1340 v_write(screen->respond, cplot + adj, (unsigned) (len - adj));
1341 #endif /* VMS */
1342 }
1343
1344 void
TekRun(void)1345 TekRun(void)
1346 {
1347 XtermWidget xw = term;
1348
1349 assert(xw != 0);
1350 if (tekWidget == 0) {
1351 TekInit();
1352 }
1353 if (tekWidget != 0) {
1354 TRACE(("TekRun ...\n"));
1355
1356 if (!TEK4014_SHOWN(xw)) {
1357 set_tek_visibility(True);
1358 }
1359 update_vttekmode();
1360 update_vtshow();
1361 update_tekshow();
1362 set_tekhide_sensitivity();
1363
1364 Tpushback = Tpushb;
1365 Ttoggled = True;
1366 if (!setjmp(Tekend))
1367 Tekparse(tekWidget);
1368 if (!Ttoggled) {
1369 TCursorToggle(tekWidget, TOGGLE);
1370 Ttoggled = True;
1371 }
1372 TEK4014_ACTIVE(xw) = False;
1373 xtermSetWinSize(xw);
1374 } else {
1375 TEK4014_ACTIVE(xw) = False;
1376 if (VWindow(TScreenOf(xw)) == 0) {
1377 Exit(ERROR_TINIT);
1378 }
1379 }
1380 }
1381
1382 #define DOTTED_LENGTH 2
1383 #define DOT_DASHED_LENGTH 4
1384 #define SHORT_DASHED_LENGTH 2
1385 #define LONG_DASHED_LENGTH 2
1386
1387 static const int dash_length[TEKNUMLINES] =
1388 {
1389 DOTTED_LENGTH,
1390 DOT_DASHED_LENGTH,
1391 SHORT_DASHED_LENGTH,
1392 LONG_DASHED_LENGTH,
1393 };
1394
1395 static _Xconst char dotted[DOTTED_LENGTH] =
1396 {3, 1};
1397 static _Xconst char dot_dashed[DOT_DASHED_LENGTH] =
1398 {3, 4, 3, 1};
1399 static _Xconst char short_dashed[SHORT_DASHED_LENGTH] =
1400 {4, 4};
1401 static _Xconst char long_dashed[LONG_DASHED_LENGTH] =
1402 {4, 7};
1403
1404 static _Xconst char *dashes[TEKNUMLINES] =
1405 {
1406 dotted,
1407 dot_dashed,
1408 short_dashed,
1409 long_dashed,
1410 };
1411
1412 /*
1413 * The following functions are called to initialize and realize the tekWidget
1414 */
1415 static void
TekInitialize(Widget wrequest,Widget new_arg,ArgList args,Cardinal * num_args)1416 TekInitialize(Widget wrequest,
1417 Widget new_arg,
1418 ArgList args,
1419 Cardinal *num_args)
1420 {
1421 XtermWidget xw = term;
1422 TScreen *vtscr = TScreenOf(xw);
1423
1424 TekWidget request = (TekWidget) wrequest;
1425 TekWidget wnew = (TekWidget) new_arg;
1426
1427 Widget tekparent = SHELL_OF(wnew);
1428 TekScreen *tekscr = TekScreenOf((TekWidget) wnew);
1429
1430 int i;
1431 int border;
1432 int pr;
1433 int winX, winY;
1434 unsigned min_width, min_height;
1435 unsigned width, height;
1436 char Tdefault[32];
1437
1438 (void) args;
1439 (void) num_args;
1440
1441 TRACE(("TekInitialize " TRACE_L "\n"));
1442 memset(tekscr, 0, sizeof(*tekscr));
1443
1444 /*
1445 * Eliminate 'term' as global from other functions.
1446 */
1447 wnew->vt = xw;
1448 border = 2 * BorderOf(wnew);
1449 TRACE(("... border*2: %d\n", border));
1450
1451 /* look for focus related events on the shell, because we need
1452 * to care about the shell's border being part of our focus.
1453 */
1454 XtAddEventHandler(tekparent, EnterWindowMask, False,
1455 HandleEnterWindow, (Opaque) 0);
1456 XtAddEventHandler(tekparent, LeaveWindowMask, False,
1457 HandleLeaveWindow, (Opaque) 0);
1458 XtAddEventHandler(tekparent, FocusChangeMask, False,
1459 HandleFocusChange, (Opaque) 0);
1460 XtAddEventHandler(new_arg, PropertyChangeMask, False,
1461 HandleBellPropertyChange, (Opaque) 0);
1462
1463 #ifndef NO_ACTIVE_ICON
1464 tekscr->whichTwin = &(tekscr->fullTwin);
1465 #endif /* NO_ACTIVE_ICON */
1466
1467 init_Sres(tek.initial_font);
1468 init_Sres(tek.gin_terminator_str);
1469 #if OPT_TOOLBAR
1470 init_Ires(tek.tb_info.menu_height);
1471 wnew->tek.tb_info.menu_bar = request->tek.tb_info.menu_bar;
1472 #endif
1473
1474 BorderPixel(wnew) = BorderPixel(xw);
1475
1476 tekscr->arrow = make_colored_cursor(XC_left_ptr,
1477 T_COLOR(vtscr, MOUSE_FG),
1478 T_COLOR(vtscr, MOUSE_BG));
1479
1480 for (i = 0; i < TEKNUMFONTS; i++) {
1481 if (!wnew->tek.Tfont[i]) {
1482 wnew->tek.Tfont[i] = XQueryFont(XtDisplay(wnew), DefaultGCID(wnew));
1483 }
1484 if (wnew->tek.Tfont[i]) {
1485 TRACE(("Tfont[%d] %dx%d\n",
1486 i,
1487 wnew->tek.Tfont[i]->max_bounds.width,
1488 wnew->tek.Tfont[i]->ascent +
1489 wnew->tek.Tfont[i]->descent));
1490 wnew->tek.tobaseline[i] = wnew->tek.Tfont[i]->ascent;
1491 } else {
1492 TRACE(("Tfont[%d] disabled\n", i));
1493 SetItemSensitivity(tekMenuEntries[i].widget, False);
1494 }
1495 }
1496
1497 if (xw->misc.T_geometry == NULL) {
1498 int def_width, def_height;
1499
1500 if (xw->misc.tekSmall) {
1501 def_width = TEKMINWIDTH;
1502 def_height = TEKMINHEIGHT;
1503 } else {
1504 def_width = TEKDEFWIDTH;
1505 def_height = TEKDEFHEIGHT;
1506 }
1507 sprintf(Tdefault, "=%dx%d", def_width + border, def_height + border);
1508 xw->misc.T_geometry = Tdefault;
1509 }
1510
1511 winX = 1;
1512 winY = 1;
1513 width = (unsigned) (TEKDEFWIDTH + border);
1514 height = (unsigned) (TEKDEFHEIGHT + border);
1515 min_width = (unsigned) (TEKMINWIDTH + border);
1516 min_height = (unsigned) (TEKMINHEIGHT + border);
1517
1518 TRACE(("parsing T_geometry %s\n", NonNull(xw->misc.T_geometry)));
1519 if (strlen(xw->misc.T_geometry) <= MAX_U_STRING) {
1520 pr = XParseGeometry(xw->misc.T_geometry,
1521 &winX,
1522 &winY,
1523 &width,
1524 &height);
1525 } else {
1526 pr = 0;
1527 }
1528
1529 /* window-manager hints will do this anyway... */
1530 if (height < min_height) {
1531 TRACE(("... override height from %d to %d\n", height, min_height));
1532 height = min_height;
1533 }
1534 if (width < min_width) {
1535 TRACE(("... override width from %d to %d\n", width, min_width));
1536 width = min_width;
1537 }
1538
1539 TRACE(("... position %d,%d size %dx%d\n", winY, winX, height, width));
1540 if ((pr & XValue) && (pr & XNegative)) {
1541 winX += DisplayWidth(XtDisplay(wnew), DefaultScreen(XtDisplay(wnew)))
1542 - (int) width - (BorderWidth(SHELL_OF(xw)) * 2);
1543 }
1544 if ((pr & YValue) && (pr & YNegative)) {
1545 winY += DisplayHeight(XtDisplay(wnew), DefaultScreen(XtDisplay(wnew)))
1546 - (int) height - (BorderWidth(SHELL_OF(xw)) * 2);
1547 }
1548
1549 /* set up size hints */
1550
1551 /* *INDENT-EQLS* */
1552 wnew->hints.min_width = (int) min_width;
1553 wnew->hints.min_height = (int) min_height;
1554 wnew->hints.width_inc = 1;
1555 wnew->hints.height_inc = 1;
1556 wnew->hints.flags = PMinSize | PResizeInc;
1557 wnew->hints.x = winX;
1558 wnew->hints.y = winY;
1559
1560 if ((XValue & pr) || (YValue & pr)) {
1561 wnew->hints.flags |= USSize | USPosition;
1562 wnew->hints.flags |= PWinGravity;
1563 switch (pr & (XNegative | YNegative)) {
1564 case 0:
1565 wnew->hints.win_gravity = NorthWestGravity;
1566 break;
1567 case XNegative:
1568 wnew->hints.win_gravity = NorthEastGravity;
1569 break;
1570 case YNegative:
1571 wnew->hints.win_gravity = SouthWestGravity;
1572 break;
1573 default:
1574 wnew->hints.win_gravity = SouthEastGravity;
1575 break;
1576 }
1577 } else {
1578 /* set a default size, but do *not* set position */
1579 wnew->hints.flags |= PSize;
1580 }
1581 wnew->hints.width = (int) width;
1582 wnew->hints.height = (int) height;
1583 if ((WidthValue & pr) || (HeightValue & pr))
1584 wnew->hints.flags |= USSize;
1585 else
1586 wnew->hints.flags |= PSize;
1587
1588 tekscr->cur.fontsize = TEK_FONT_LARGE;
1589 if (wnew->tek.initial_font) {
1590 int result = TekGetFontSize(wnew->tek.initial_font);
1591 if (result >= 0)
1592 tekscr->cur.fontsize = result;
1593 }
1594 TRACE(("Tek cur.fontsize=%d\n", tekscr->cur.fontsize));
1595
1596 #define TestGIN(s) XmuCompareISOLatin1(wnew->tek.gin_terminator_str, s)
1597
1598 if (TestGIN(GIN_TERM_NONE_STR) == 0)
1599 tekscr->gin_terminator = GIN_TERM_NONE;
1600 else if (TestGIN(GIN_TERM_CR_STR) == 0)
1601 tekscr->gin_terminator = GIN_TERM_CR;
1602 else if (TestGIN(GIN_TERM_EOT_STR) == 0)
1603 tekscr->gin_terminator = GIN_TERM_EOT;
1604 else
1605 xtermWarning("illegal GIN terminator setting \"%s\"\n",
1606 wnew->tek.gin_terminator_str);
1607 TRACE(("Tek gin_terminator=%d\n", tekscr->gin_terminator));
1608
1609 TRACE((TRACE_R " TekInitialize\n"));
1610 }
1611
1612 static void
TekRealize(Widget gw,XtValueMask * valuemaskp,XSetWindowAttributes * values)1613 TekRealize(Widget gw,
1614 XtValueMask * valuemaskp,
1615 XSetWindowAttributes * values)
1616 {
1617 TekWidget tw = (TekWidget) gw;
1618 TekScreen *tekscr = TekScreenOf(tw);
1619 TScreen *vtscr = TScreenOf(tw->vt);
1620
1621 int i;
1622 TekLink *tek;
1623 XGCValues gcv;
1624 unsigned width, height;
1625 unsigned long TEKgcFontMask;
1626
1627 TRACE(("TekRealize " TRACE_L "\n"));
1628
1629 if (!TekPtyData())
1630 return;
1631
1632 /* use values from TekInitialize... */
1633 height = (unsigned) tw->hints.height;
1634 width = (unsigned) tw->hints.width;
1635
1636 (void) REQ_RESIZE((Widget) tw,
1637 (Dimension) width, (Dimension) height,
1638 &tw->core.width, &tw->core.height);
1639
1640 /* XXX This is bogus. We are parsing geometries too late. This
1641 * is information that the shell widget ought to have before we get
1642 * realized, so that it can do the right thing.
1643 */
1644 if (tw->hints.flags & USPosition)
1645 XMoveWindow(XtDisplay(tw), TShellWindow, tw->hints.x, tw->hints.y);
1646
1647 XSetWMNormalHints(XtDisplay(tw), TShellWindow, &tw->hints);
1648 XFlush(XtDisplay(tw)); /* get it out to window manager */
1649
1650 values->win_gravity = NorthWestGravity;
1651 values->background_pixel = T_COLOR(vtscr, TEK_BG);
1652
1653 XtWindow(tw) = TWindow(tekscr) =
1654 XCreateWindow(XtDisplay(tw),
1655 VShellWindow(tw),
1656 tw->core.x, tw->core.y,
1657 tw->core.width, tw->core.height,
1658 BorderWidth(tw),
1659 (int) tw->core.depth,
1660 InputOutput, CopyFromParent,
1661 ((*valuemaskp) | CWBackPixel | CWWinGravity),
1662 values);
1663
1664 compute_sizes(tw);
1665
1666 gcv.graphics_exposures = True; /* default */
1667 gcv.font = tw->tek.Tfont[tekscr->cur.fontsize]->fid;
1668 gcv.foreground = T_COLOR(vtscr, TEK_FG);
1669 gcv.background = T_COLOR(vtscr, TEK_BG);
1670
1671 /* if font wasn't successfully opened, then gcv.font will contain
1672 the Default GC's ID, meaning that we must use the server default font.
1673 */
1674 TEKgcFontMask = (unsigned long) ((gcv.font == DefaultGCID(tw))
1675 ? 0
1676 : GCFont);
1677 tekscr->TnormalGC = XCreateGC(XtDisplay(tw), TWindow(tekscr),
1678 (TEKgcFontMask | GCGraphicsExposures |
1679 GCForeground | GCBackground),
1680 &gcv);
1681
1682 gcv.function = GXinvert;
1683 gcv.plane_mask = (T_COLOR(vtscr, TEK_BG) ^
1684 T_COLOR(vtscr, TEK_CURSOR));
1685 gcv.join_style = JoinMiter; /* default */
1686 gcv.line_width = 1;
1687 tekscr->TcursorGC = XCreateGC(XtDisplay(tw), TWindow(tekscr),
1688 (GCFunction | GCPlaneMask), &gcv);
1689
1690 gcv.foreground = T_COLOR(vtscr, TEK_FG);
1691 gcv.line_style = LineOnOffDash;
1692 gcv.line_width = 0;
1693 for (i = 0; i < TEKNUMLINES; i++) {
1694 tekscr->linepat[i] = XCreateGC(XtDisplay(tw), TWindow(tekscr),
1695 (GCForeground | GCLineStyle), &gcv);
1696 XSetDashes(XtDisplay(tw), tekscr->linepat[i], 0,
1697 dashes[i], dash_length[i]);
1698 }
1699
1700 TekBackground(tw, vtscr);
1701
1702 tekscr->margin = MARGIN1; /* Margin 1 */
1703 tekscr->TekGIN = False; /* GIN off */
1704
1705 XDefineCursor(XtDisplay(tw), TWindow(tekscr), tekscr->arrow);
1706
1707 { /* there's gotta be a better way... */
1708 static char empty_string[1];
1709 static Arg args[] =
1710 {
1711 {XtNtitle, (XtArgVal) NULL},
1712 {XtNiconName, (XtArgVal) NULL},
1713 };
1714 char *icon_name = NULL;
1715 char *title = NULL;
1716 char *tek_icon_name = NULL;
1717 char *tek_title = NULL;
1718
1719 args[0].value = (XtArgVal) & icon_name;
1720 args[1].value = (XtArgVal) & title;
1721 XtGetValues(SHELL_OF(tw), args, 2);
1722
1723 if (IsEmpty(title)) {
1724 title = empty_string;
1725 }
1726
1727 if (IsEmpty(icon_name)) {
1728 icon_name = empty_string;
1729 }
1730
1731 TRACE(("TekShell title='%s', iconName='%s'\n", title, icon_name));
1732 tek_icon_name = XtMalloc((Cardinal) strlen(icon_name) + 7);
1733 strcpy(tek_icon_name, icon_name);
1734 strcat(tek_icon_name, "(Tek)");
1735 tek_title = XtMalloc((Cardinal) strlen(title) + 7);
1736 strcpy(tek_title, title);
1737 strcat(tek_title, "(Tek)");
1738 args[0].value = (XtArgVal) tek_icon_name;
1739 args[1].value = (XtArgVal) tek_title;
1740 TRACE(("Tek title='%s', iconName='%s'\n", tek_title, tek_icon_name));
1741 XtSetValues(SHELL_OF(tw), args, 2);
1742 XtFree(tek_icon_name);
1743 XtFree(tek_title);
1744 }
1745
1746 /* *INDENT-EQLS* */
1747 tek = TekRecord = &Tek0;
1748 tek->next = (TekLink *) 0;
1749 tek->fontsize = (unsigned short) tekscr->cur.fontsize;
1750 tek->count = 0;
1751 tek->ptr = tek->data;
1752 Tpushback = Tpushb;
1753 tekscr->cur_X = 0;
1754 tekscr->cur_Y = TEKHOME;
1755 line_pt = Tline;
1756 Ttoggled = True;
1757 tekscr->page = tekscr->cur;
1758
1759 TRACE((TRACE_R " TekRealize\n"));
1760 }
1761
1762 int
TekGetFontSize(const char * param)1763 TekGetFontSize(const char *param)
1764 {
1765 int result;
1766
1767 if (XmuCompareISOLatin1(param, "l") == 0 ||
1768 XmuCompareISOLatin1(param, "large") == 0)
1769 result = TEK_FONT_LARGE;
1770 else if (XmuCompareISOLatin1(param, "2") == 0 ||
1771 XmuCompareISOLatin1(param, "two") == 0)
1772 result = TEK_FONT_2;
1773 else if (XmuCompareISOLatin1(param, "3") == 0 ||
1774 XmuCompareISOLatin1(param, "three") == 0)
1775 result = TEK_FONT_3;
1776 else if (XmuCompareISOLatin1(param, "s") == 0 ||
1777 XmuCompareISOLatin1(param, "small") == 0)
1778 result = TEK_FONT_SMALL;
1779 else
1780 result = -1;
1781
1782 return result;
1783 }
1784
1785 void
TekSetFontSize(TekWidget tw,Bool fromMenu,int newitem)1786 TekSetFontSize(TekWidget tw, Bool fromMenu, int newitem)
1787 {
1788 if (tw != 0) {
1789 TekScreen *tekscr = TekScreenOf(tw);
1790 int oldsize = tekscr->cur.fontsize;
1791 int newsize = MI2FS(newitem);
1792 Font fid;
1793
1794 TRACE(("TekSetFontSize(%d) size %d ->%d\n", newitem, oldsize, newsize));
1795 if (newsize < 0 || newsize >= TEKNUMFONTS) {
1796 Bell(tw->vt, XkbBI_MinorError, 0);
1797 } else if (oldsize != newsize) {
1798 if (!Ttoggled)
1799 TCursorToggle(tw, TOGGLE);
1800 set_tekfont_menu_item(oldsize, False);
1801
1802 tekscr->cur.fontsize = newsize;
1803 TekSetWinSize(tw);
1804 if (fromMenu)
1805 tekscr->page.fontsize = newsize;
1806
1807 fid = tw->tek.Tfont[newsize]->fid;
1808 if (fid == DefaultGCID(tw)) {
1809 /* we didn't succeed in opening a real font
1810 for this size. Instead, use server default. */
1811 XCopyGC(XtDisplay(tw),
1812 DefaultGC(XtDisplay(tw), DefaultScreen(XtDisplay(tw))),
1813 GCFont, tekscr->TnormalGC);
1814 } else {
1815 XSetFont(XtDisplay(tw), tekscr->TnormalGC, fid);
1816 }
1817
1818 set_tekfont_menu_item(newsize, True);
1819 if (!Ttoggled)
1820 TCursorToggle(tw, TOGGLE);
1821
1822 if (fromMenu) {
1823 /* we'll get an exposure event after changing fontsize, so we
1824 * have to clear the screen to avoid painting over the previous
1825 * text.
1826 */
1827 TekClear(tw);
1828 }
1829 }
1830 }
1831 }
1832
1833 void
ChangeTekColors(TekWidget tw,TScreen * screen,ScrnColors * pNew)1834 ChangeTekColors(TekWidget tw, TScreen *screen, ScrnColors * pNew)
1835 {
1836 if (tw && screen) {
1837 TekScreen *tekscr = TekScreenOf(tw);
1838 XGCValues gcv;
1839 int i;
1840
1841 if (COLOR_DEFINED(pNew, TEK_FG)) {
1842 T_COLOR(screen, TEK_FG) = COLOR_VALUE(pNew, TEK_FG);
1843 TRACE(("... TEK_FG: %#lx\n", T_COLOR(screen, TEK_FG)));
1844 }
1845 if (COLOR_DEFINED(pNew, TEK_BG)) {
1846 T_COLOR(screen, TEK_BG) = COLOR_VALUE(pNew, TEK_BG);
1847 TRACE(("... TEK_BG: %#lx\n", T_COLOR(screen, TEK_BG)));
1848 }
1849 if (COLOR_DEFINED(pNew, TEK_CURSOR)) {
1850 T_COLOR(screen, TEK_CURSOR) = COLOR_VALUE(pNew, TEK_CURSOR);
1851 TRACE(("... TEK_CURSOR: %#lx\n", T_COLOR(screen, TEK_CURSOR)));
1852 } else {
1853 T_COLOR(screen, TEK_CURSOR) = T_COLOR(screen, TEK_FG);
1854 TRACE(("... TEK_CURSOR: %#lx\n", T_COLOR(screen, TEK_CURSOR)));
1855 }
1856
1857 XSetForeground(XtDisplay(tw), tekscr->TnormalGC,
1858 T_COLOR(screen, TEK_FG));
1859 XSetBackground(XtDisplay(tw), tekscr->TnormalGC,
1860 T_COLOR(screen, TEK_BG));
1861 if (BorderPixel(tw) == T_COLOR(screen, TEK_BG)) {
1862 BorderPixel(tw) = T_COLOR(screen, TEK_FG);
1863 BorderPixel(XtParent(tw)) = T_COLOR(screen, TEK_FG);
1864 if (XtWindow(XtParent(tw)))
1865 XSetWindowBorder(XtDisplay(tw),
1866 XtWindow(XtParent(tw)),
1867 BorderPixel(tw));
1868 }
1869
1870 for (i = 0; i < TEKNUMLINES; i++) {
1871 XSetForeground(XtDisplay(tw), tekscr->linepat[i],
1872 T_COLOR(screen, TEK_FG));
1873 }
1874
1875 gcv.plane_mask = (T_COLOR(screen, TEK_BG) ^
1876 T_COLOR(screen, TEK_CURSOR));
1877 XChangeGC(XtDisplay(tw), tekscr->TcursorGC, GCPlaneMask, &gcv);
1878 TekBackground(tw, screen);
1879 }
1880 return;
1881 }
1882
1883 void
TekReverseVideo(XtermWidget xw,TekWidget tw)1884 TekReverseVideo(XtermWidget xw, TekWidget tw)
1885 {
1886 if (tw) {
1887 TScreen *screen = TScreenOf(xw);
1888 TekScreen *tekscr = TekScreenOf(tw);
1889 Pixel tmp;
1890 XGCValues gcv;
1891 int i;
1892
1893 EXCHANGE(T_COLOR(screen, TEK_FG), T_COLOR(screen, TEK_BG), tmp);
1894
1895 T_COLOR(screen, TEK_CURSOR) = T_COLOR(screen, TEK_FG);
1896
1897 XSetForeground(XtDisplay(tw), tekscr->TnormalGC, T_COLOR(screen, TEK_FG));
1898 XSetBackground(XtDisplay(tw), tekscr->TnormalGC, T_COLOR(screen, TEK_BG));
1899
1900 if (BorderPixel(tw) == T_COLOR(screen, TEK_BG)) {
1901 BorderPixel(tw) = T_COLOR(screen, TEK_FG);
1902 BorderPixel(XtParent(tw)) = T_COLOR(screen, TEK_FG);
1903 if (XtWindow(XtParent(tw)))
1904 XSetWindowBorder(XtDisplay(tw),
1905 XtWindow(XtParent(tw)),
1906 BorderPixel(tw));
1907 }
1908
1909 for (i = 0; i < TEKNUMLINES; i++) {
1910 XSetForeground(XtDisplay(tw), tekscr->linepat[i],
1911 T_COLOR(screen, TEK_FG));
1912 }
1913
1914 gcv.plane_mask = (T_COLOR(screen, TEK_BG) ^
1915 T_COLOR(screen, TEK_CURSOR));
1916 XChangeGC(XtDisplay(tw), tekscr->TcursorGC, GCPlaneMask, &gcv);
1917 TekBackground(tw, screen);
1918 }
1919 }
1920
1921 static void
TekBackground(TekWidget tw,TScreen * screen)1922 TekBackground(TekWidget tw, TScreen *screen)
1923 {
1924 TekScreen *tekscr = TekScreenOf(tw);
1925
1926 if (TWindow(tekscr))
1927 XSetWindowBackground(XtDisplay(tw), TWindow(tekscr),
1928 T_COLOR(screen, TEK_BG));
1929 }
1930
1931 /*
1932 * Toggles cursor on or off at cursor position in screen.
1933 */
1934 void
TCursorToggle(TekWidget tw,int toggle)1935 TCursorToggle(TekWidget tw, int toggle) /* TOGGLE or CLEAR */
1936 {
1937 TekScreen *tekscr;
1938 XtermWidget xw;
1939 int c, x, y;
1940 unsigned cellwidth, cellheight;
1941
1942 if (tw == 0)
1943 return;
1944 if ((tekscr = TekScreenOf(tw)) == 0)
1945 return;
1946 if ((xw = tw->vt) == 0)
1947 return;
1948 if (!TEK4014_SHOWN(xw))
1949 return;
1950
1951 TRACE(("TCursorToggle %s\n", (toggle == TOGGLE) ? "toggle" : "clear"));
1952 c = tekscr->cur.fontsize;
1953 cellwidth = (unsigned) tw->tek.Tfont[c]->max_bounds.width;
1954 cellheight = (unsigned) (tw->tek.Tfont[c]->ascent +
1955 tw->tek.Tfont[c]->descent);
1956
1957 x = (int) ScaledX(tw, tekscr->cur_X);
1958 y = (int) ScaledY(tw, tekscr->cur_Y) - tw->tek.tobaseline[c];
1959
1960 if (toggle == TOGGLE) {
1961 TScreen *screen = TScreenOf(xw);
1962 if (screen->select || screen->always_highlight)
1963 XFillRectangle(XtDisplay(tw), TWindow(tekscr),
1964 tekscr->TcursorGC, x, y,
1965 cellwidth, cellheight);
1966 else { /* fix to use different GC! */
1967 XDrawRectangle(XtDisplay(tw), TWindow(tekscr),
1968 tekscr->TcursorGC, x, y,
1969 cellwidth - 1, cellheight - 1);
1970 }
1971 } else {
1972 /* Clear the entire rectangle, even though we may only
1973 * have drawn an outline. This fits with our refresh
1974 * scheme of redrawing the entire window on any expose
1975 * event and is easier than trying to figure out exactly
1976 * which part of the cursor needs to be erased.
1977 */
1978 XClearArea(XtDisplay(tw), TWindow(tekscr), x, y,
1979 cellwidth, cellheight, False);
1980 }
1981 }
1982
1983 /*
1984 * The Tektronix manual describes the PAGE/RESET button. For PAGE:
1985 * Erases the display, resets to Alpha Mode and home position;
1986 * resets to Margin 1 and cancels Bypass condition.
1987 * For the RESET function:
1988 * Entered with SHIFT held down; creates a "home" function,
1989 * resetting the Terminal to initial status; does not erase.
1990 *
1991 * The reset done here is different, changing the modes (which changes
1992 * the line-type and font to default values) as well as erasing the screen
1993 * (like PAGE).
1994 */
1995 void
TekSimulatePageButton(TekWidget tw,Bool reset)1996 TekSimulatePageButton(TekWidget tw, Bool reset)
1997 {
1998 if (tw != 0) {
1999 TekScreen *tekscr = TekScreenOf(tw);
2000
2001 if (reset) {
2002 memset(&tekscr->cur, 0, sizeof tekscr->cur);
2003 }
2004 tekRefreshList = (TekLink *) 0;
2005 TekPage(tw);
2006 tekscr->cur_X = 0;
2007 tekscr->cur_Y = TEKHOME;
2008 }
2009 }
2010
2011 /* write copy of screen to a file */
2012
2013 void
TekCopy(TekWidget tw)2014 TekCopy(TekWidget tw)
2015 {
2016 if (tw != 0) {
2017 TekScreen *tekscr = TekScreenOf(tw);
2018 TScreen *screen = TScreenOf(tw->vt);
2019
2020 TekLink *Tp;
2021 char buf[TIMESTAMP_LEN + 10];
2022 int tekcopyfd;
2023
2024 timestamp_filename(buf, "COPY");
2025 if (access(buf, F_OK) >= 0
2026 && access(buf, W_OK) < 0) {
2027 Bell(tw->vt, XkbBI_MinorError, 0);
2028 return;
2029 }
2030 #ifndef VMS
2031 if (access(".", W_OK) < 0) { /* can't write in directory */
2032 Bell(tw->vt, XkbBI_MinorError, 0);
2033 return;
2034 }
2035 #endif
2036
2037 tekcopyfd = open_userfile(screen->uid, screen->gid, buf, False);
2038 if (tekcopyfd >= 0) {
2039 char initbuf[5];
2040
2041 sprintf(initbuf, "%c%c%c%c",
2042 ANSI_ESC, (char) (tekscr->page.fontsize + '8'),
2043 ANSI_ESC, (char) (tekscr->page.linetype + '`'));
2044 IGNORE_RC(write(tekcopyfd, initbuf, (size_t) 4));
2045 Tp = &Tek0;
2046 do {
2047 IGNORE_RC(write(tekcopyfd, Tp->data, (size_t) Tp->count));
2048 Tp = Tp->next;
2049 } while (Tp);
2050 close(tekcopyfd);
2051 }
2052 }
2053 }
2054
2055 /*ARGSUSED*/
2056 void
HandleGINInput(Widget w,XEvent * event GCC_UNUSED,String * param_list,Cardinal * nparamsp)2057 HandleGINInput(Widget w,
2058 XEvent *event GCC_UNUSED,
2059 String *param_list,
2060 Cardinal *nparamsp)
2061 {
2062 TekWidget tw = getTekWidget(w);
2063
2064 if (tw != 0) {
2065 TekScreen *tekscr = TekScreenOf(tw);
2066
2067 if (tekscr->TekGIN && *nparamsp == 1) {
2068 int c = param_list[0][0];
2069 switch (c) {
2070 case 'l':
2071 case 'm':
2072 case 'r':
2073 case 'L':
2074 case 'M':
2075 case 'R':
2076 break;
2077 default:
2078 Bell(tw->vt, XkbBI_MinorError, 0); /* let them know they goofed */
2079 c = 'l'; /* provide a default */
2080 }
2081 TekEnqMouse(tw, c | 0x80);
2082 TekGINoff(tw);
2083 } else {
2084 Bell(tw->vt, XkbBI_MinorError, 0);
2085 }
2086 }
2087 }
2088
2089 /*
2090 * Check if the current widget, or any parent, is the "tek4014" widget.
2091 */
2092 TekWidget
getTekWidget(Widget w)2093 getTekWidget(Widget w)
2094 {
2095 TekWidget tw;
2096
2097 if (w == 0) {
2098 tw = (TekWidget) CURRENT_EMU();
2099 if (!IsTekWidget(tw)) {
2100 tw = 0;
2101 }
2102 } else if (IsTekWidget(w)) {
2103 tw = (TekWidget) w;
2104 } else {
2105 tw = getTekWidget(XtParent(w));
2106 }
2107 TRACE2(("getTekWidget %p -> %p\n", w, tw));
2108 return tw;
2109 }
2110