"Fossies" - the Fresh Open Source Software Archive

Member "xterm-379/Tekproc.c" (6 Oct 2022, 56997 Bytes) of package /linux/misc/xterm-379.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "Tekproc.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 373_vs_374.

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