"Fossies" - the Fresh Open Source Software Archive 
Member "xterm-379/Tekproc.c" (6 Oct 2022, 56997 Bytes) of package /linux/misc/xterm-379.tgz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "Tekproc.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
373_vs_374.
1 /* $XTermId: Tekproc.c,v 1.249 2022/10/06 19:41:47 tom Exp $ */
2
3 /*
4 * Copyright 2001-2021,2022 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
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
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
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
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
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
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),
926 rows, cols,
927 TFullHeight(tekscr),
928 TFullWidth(tekscr));
929 }
930 }
931
932 static void
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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, (size_t) (len - adj));
1339 #else /* VMS */
1340 v_write(screen->respond, cplot + adj, (size_t) (len - adj));
1341 #endif /* VMS */
1342 }
1343
1344 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
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
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
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
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
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
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
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
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
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
2014 TekCopy(TekWidget tw)
2015 {
2016 #ifdef ALLOWLOGGING
2017 if (tw != 0) {
2018 TekScreen *tekscr = TekScreenOf(tw);
2019 TScreen *screen = TScreenOf(tw->vt);
2020
2021 TekLink *Tp;
2022 char buf[TIMESTAMP_LEN + 10];
2023 int tekcopyfd;
2024
2025 timestamp_filename(buf, "COPY");
2026 if (access(buf, F_OK) >= 0
2027 && access(buf, W_OK) < 0) {
2028 Bell(tw->vt, XkbBI_MinorError, 0);
2029 return;
2030 }
2031 #ifndef VMS
2032 if (access(".", W_OK) < 0) { /* can't write in directory */
2033 Bell(tw->vt, XkbBI_MinorError, 0);
2034 return;
2035 }
2036 #endif
2037
2038 tekcopyfd = open_userfile(screen->uid, screen->gid, buf, False);
2039 if (tekcopyfd >= 0) {
2040 char initbuf[5];
2041
2042 sprintf(initbuf, "%c%c%c%c",
2043 ANSI_ESC, (char) (tekscr->page.fontsize + '8'),
2044 ANSI_ESC, (char) (tekscr->page.linetype + '`'));
2045 IGNORE_RC(write(tekcopyfd, initbuf, (size_t) 4));
2046 Tp = &Tek0;
2047 do {
2048 IGNORE_RC(write(tekcopyfd, Tp->data, (size_t) Tp->count));
2049 Tp = Tp->next;
2050 } while (Tp);
2051 close(tekcopyfd);
2052 }
2053 }
2054 #else
2055 (void) tw;
2056 #endif /* ALLOWLOGGING */
2057 }
2058
2059 /*ARGSUSED*/
2060 void
2061 HandleGINInput(Widget w,
2062 XEvent *event GCC_UNUSED,
2063 String *param_list,
2064 Cardinal *nparamsp)
2065 {
2066 TekWidget tw = getTekWidget(w);
2067
2068 if (tw != 0) {
2069 TekScreen *tekscr = TekScreenOf(tw);
2070
2071 if (tekscr->TekGIN && *nparamsp == 1) {
2072 int c = param_list[0][0];
2073 switch (c) {
2074 case 'l':
2075 case 'm':
2076 case 'r':
2077 case 'L':
2078 case 'M':
2079 case 'R':
2080 break;
2081 default:
2082 Bell(tw->vt, XkbBI_MinorError, 0); /* let them know they goofed */
2083 c = 'l'; /* provide a default */
2084 }
2085 TekEnqMouse(tw, c | 0x80);
2086 TekGINoff(tw);
2087 } else {
2088 Bell(tw->vt, XkbBI_MinorError, 0);
2089 }
2090 }
2091 }
2092
2093 /*
2094 * Check if the current widget, or any parent, is the "tek4014" widget.
2095 */
2096 TekWidget
2097 getTekWidget(Widget w)
2098 {
2099 TekWidget tw;
2100
2101 if (w == 0) {
2102 tw = (TekWidget) CURRENT_EMU();
2103 if (!IsTekWidget(tw)) {
2104 tw = 0;
2105 }
2106 } else if (IsTekWidget(w)) {
2107 tw = (TekWidget) w;
2108 } else {
2109 tw = getTekWidget(XtParent(w));
2110 }
2111 TRACE2(("getTekWidget %p -> %p\n", w, tw));
2112 return tw;
2113 }