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