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