home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume9 / xterm / part02 / Tekproc.c < prev   
Encoding:
C/C++ Source or Header  |  1987-04-19  |  38.5 KB  |  1,634 lines

  1. /*
  2.  *    $Source: /u1/X/xterm/RCS/Tekproc.c,v $
  3.  *    $Header: Tekproc.c,v 10.104 86/12/02 11:35:38 swick Exp $
  4.  */
  5.  
  6. #include <X/mit-copyright.h>
  7.  
  8. /* Copyright (c) 1985 Massachusetts Institute of Technology        */
  9. /* Copyright (c) 1985    Digital Equipment Corporation            */
  10.  
  11. /* Tekproc.c */
  12.  
  13. #include <X/Xlib.h>
  14. #include "scrollbar.h"
  15. #include "ptyx.h"
  16. #include "Tekparse.h"
  17. #include <stdio.h>
  18. #include <sgtty.h>
  19. #include <ctype.h>
  20. #include <errno.h>
  21. #include <setjmp.h>
  22. #include <sys/time.h>
  23. #include <sys/file.h>
  24. #include <pwd.h>
  25. #include "data.h"
  26. #include "error.h"
  27. #ifdef MODEMENU
  28. #include "menu.h"
  29. #endif MODEMENU
  30.  
  31. /* Tek defines */
  32.  
  33. #define    BEL        07
  34. #define    CANCEL        030
  35. #define    DOTDASHEDLINE    2
  36. #define    DOTTEDLINE    1
  37. #define    EAST        01
  38. #define    ETX        03
  39. #define ICONFONT    4
  40. #define    LARGEFONT    0
  41. #define    LARGEFONTNAME    "9x15"
  42. #define    LINEMASK    07
  43. #define    LONGDASHEDLINE    4
  44. #define    MARGIN1        0
  45. #define    MARGIN2        1
  46. #define MAX_PTS        150
  47. #define MAX_VTX        300
  48. #define    NAK        025
  49. #define    NORTH        04
  50. #define    PENDOWN        1
  51. #define    PENUP        0
  52. #define    SHORTDASHEDLINE    3
  53. #define    SMALLFONT    3
  54. #define    SMALLFONTNAME    "6x10"
  55. #define    SOLIDLINE    0
  56. #define    SOUTH        010
  57. #define    TEKBOTTOMPAD    23
  58. #define    TEKDEFHEIGHT    565
  59. #define    TEKDEFWIDTH    750
  60. #define    TEKHEIGHT    3072
  61. #define    TEKHOME        ((TekChar[screen->page.fontsize].nlines - 1)\
  62.              * TekChar[screen->page.fontsize].vsize)
  63. #define    TEKMINHEIGHT    452
  64. #define    TEKMINWIDTH    600
  65. #define    TEKPAD        57
  66. #define    TEKTOPPAD    34
  67. #define    TEKWIDTH    4096
  68. #define    TEXT_BUF_SIZE    256
  69. #define    THREEFONT    2
  70. #define    THREEFONTNAME    "8x13"
  71. #define    TWOFONT        1
  72. #define    TWOFONTNAME    "6x13"
  73. #define    WEST        02
  74.  
  75. #define    TekMove(x,y)    screen->cur_X = x; screen->cur_Y = y
  76. #define    input()        Tinput()
  77. #define    unput(c)    *Tpushback++ = c
  78.  
  79. #ifndef lint
  80. static char sccs_id[] = "@(#)Tekproc.c\tX10/6.6B\t12/26/86";
  81. #endif lint
  82.  
  83. static Vertex *T_box[TEKNUMFONTS] = {
  84.     T_boxlarge,
  85.     T_box2,
  86.     T_box3,
  87.     T_boxsmall,
  88.     T_boxicon,
  89. };
  90. static struct Tek_Char {
  91.     int hsize;    /* in Tek units */
  92.     int vsize;    /* in Tek units */
  93.     int charsperline;
  94.     int nlines;
  95. } TekChar[TEKNUMFONTS] = {
  96.     {56, 88, 74, 35},    /* large */
  97.     {51, 82, 81, 38},    /* #2 */
  98.     {34, 53, 121, 58},    /* #3 */
  99.     {31, 48, 133, 64},    /* small */
  100.     {56, 88, 74,  35},    /* icon is same as large */
  101. };
  102.  
  103. static int *curstate;
  104. static Cursor GINcursor;
  105. static Vertex *line_pt;
  106. static int nplot;
  107. static TekLink Tek0;
  108. static jmp_buf Tekjump;
  109. static TekLink *TekRecord;
  110. static Vertex *Tline;
  111. static int *Tparsestate;
  112.  
  113. extern int Talptable[];
  114. extern int Tbestable[];
  115. extern int Tbyptable[];
  116. extern int Tesctable[];
  117. extern int Tipltable[];
  118. extern int Tplttable[];
  119. extern int Tpttable[];
  120. extern int Tspttable[];
  121.  
  122. Tekparse()
  123. {
  124.     register Screen *screen = &term.screen;
  125.     register int c, x, y;
  126.     register char *cp;
  127.     char ch;
  128.     int arg;
  129.     int Tinput();
  130.  
  131.     for( ; ; )
  132.         switch(Tparsestate[c = input()]) {
  133.          case CASE_REPORT:
  134.             /* report address */
  135.             if(screen->TekGIN) {
  136.                 TekGINoff();
  137.                 TekEnqMouse(0);
  138.             } else {
  139.                 c = 064;    /* has hard copy unit */
  140.                 if(screen->margin == MARGIN2)
  141.                     c |= 02;
  142.                 TekEnq(c, screen->cur_X, screen->cur_Y);
  143.             }
  144.             TekRecord->ptr[-1] = NAK; /* remove from recording */
  145.             Tparsestate = curstate;
  146.             break;
  147.  
  148.          case CASE_VT_MODE:
  149.             /* special return to vt102 mode */
  150.             Tparsestate = curstate;
  151.             TekRecord->ptr[-1] = NAK; /* remove from recording */
  152.             if(screen->logging) {
  153.                 FlushLog(screen);
  154.                 screen->logstart = buffer;
  155.             }
  156.             return;
  157.  
  158.          case CASE_SPT_STATE:
  159.             /* Enter Special Point Plot mode */
  160.             if(screen->TekGIN)
  161.                 TekGINoff();
  162.             Tparsestate = curstate = Tspttable;
  163.             break;
  164.  
  165.          case CASE_GIN:
  166.             /* Do Tek GIN mode */
  167.             screen->TekGIN = &TekRecord->ptr[-1];
  168.                 /* Set cross-hair cursor raster array */
  169.             if(GINcursor = make_tcross(screen->mousecolor,
  170.              screen->background, GXcopy))
  171.                 XDefineCursor(TWindow(screen), GINcursor);
  172.             Tparsestate = Tbyptable;    /* Bypass mode */
  173.             break;
  174.  
  175.          case CASE_BEL:
  176.             /* BEL */
  177.             if(screen->TekGIN)
  178.                 TekGINoff();
  179.             if(!TekRefresh)
  180.                 Bell();
  181.             Tparsestate = curstate;    /* clear bypass condition */
  182.             break;
  183.  
  184.          case CASE_BS:
  185.             /* BS */
  186.             if(screen->TekGIN)
  187.                 TekGINoff();
  188.             Tparsestate = curstate;    /* clear bypass condition */
  189.             TCursorBack();
  190.             break;
  191.  
  192.          case CASE_PT_STATE:
  193.             /* Enter Tek Point Plot mode */
  194.             if(screen->TekGIN)
  195.                 TekGINoff();
  196.             Tparsestate = curstate = Tpttable;
  197.             break;
  198.  
  199.          case CASE_PLT_STATE:
  200.             /* Enter Tek Plot mode */
  201.             if(screen->TekGIN)
  202.                 TekGINoff();
  203.             Tparsestate = curstate = Tplttable;
  204.             if((c = input()) == BEL)
  205.                 screen->pen = PENDOWN;
  206.             else {
  207.                 unput(c);
  208.                 screen->pen = PENUP;
  209.             }
  210.             break;
  211.  
  212.          case CASE_TAB:
  213.             /* HT */
  214.             if(screen->TekGIN)
  215.                 TekGINoff();
  216.             Tparsestate = curstate;    /* clear bypass condition */
  217.             TCursorForward();
  218.             break;
  219.  
  220.          case CASE_IPL_STATE:
  221.             /* Enter Tek Incremental Plot mode */
  222.             if(screen->TekGIN)
  223.                 TekGINoff();
  224.             Tparsestate = curstate = Tipltable;
  225.             break;
  226.  
  227.          case CASE_ALP_STATE:
  228.             /* Enter Tek Alpha mode from any other mode */
  229.             if(screen->TekGIN)
  230.                 TekGINoff();
  231.             /* if in one of graphics states, move alpha cursor */
  232.             if(nplot > 0)    /* flush line Tbuffer */
  233.                 TekFlush();
  234.             Tparsestate = curstate = Talptable;
  235.             break;
  236.  
  237.          case CASE_UP:
  238.             /* cursor up */
  239.             if(screen->TekGIN)
  240.                 TekGINoff();
  241.             Tparsestate = curstate;    /* clear bypass condition */
  242.             TCursorUp();
  243.             break;
  244.  
  245.          case CASE_COPY:
  246.             /* make copy */
  247.             if(screen->TekGIN)
  248.                 TekGINoff();
  249.             TekCopy();
  250.             TekRecord->ptr[-1] = NAK; /* remove from recording */
  251.             Tparsestate = curstate;    /* clear bypass condition */
  252.             break;
  253.  
  254.          case CASE_PAGE:
  255.             /* Page Function */
  256.             if(screen->TekGIN)
  257.                 TekGINoff();
  258.             TekPage();    /* clear bypass condition */
  259.             break;
  260.  
  261.          case CASE_BES_STATE:
  262.             /* Byp: an escape char */
  263.             Tparsestate = Tbestable;
  264.             break;
  265.  
  266.          case CASE_BYP_STATE:
  267.             /* set bypass condition */
  268.             Tparsestate = Tbyptable;
  269.             break;
  270.  
  271.          case CASE_IGNORE:
  272.             /* Esc: totally ignore CR, ESC, LF, ~ */
  273.             break;
  274.  
  275.          case CASE_ASCII:
  276.             /* Select ASCII char set */
  277.             /* ignore for now */
  278.             Tparsestate = curstate;
  279.             break;
  280.  
  281.          case CASE_APL:
  282.             /* Select APL char set */
  283.             /* ignore for now */
  284.             Tparsestate = curstate;
  285.             break;
  286.  
  287.          case CASE_CHAR_SIZE:
  288.             /* character size selector */
  289.             screen->cur.fontsize = c & 03;
  290.             Tparsestate = curstate;
  291.             break;
  292.  
  293.          case CASE_BEAM_VEC:
  294.             /* beam and vector selector */
  295.             /* only line types */
  296.             if((c &= LINEMASK) != screen->cur.linetype) {
  297.                 if(nplot > 0)
  298.                     TekFlush();
  299.                 screen->cur.linetype = c;
  300.             }
  301.             Tparsestate = curstate;
  302.             break;
  303.  
  304.          case CASE_CURSTATE:
  305.             Tparsestate = curstate;
  306.             break;
  307.  
  308.          case CASE_PENUP:
  309.             /* Ipl: penup */
  310.             screen->pen = PENUP;
  311.             break;
  312.  
  313.          case CASE_PENDOWN:
  314.             /* Ipl: pendown */
  315.             screen->pen = PENDOWN;
  316.             break;
  317.  
  318.          case CASE_IPL_POINT:
  319.             /* Ipl: point */
  320.             x = screen->cur_X;
  321.             y = screen->cur_Y;
  322.             if(c & NORTH)
  323.                 y++;
  324.             else if(c & SOUTH)
  325.                 y--;
  326.             if(c & EAST)
  327.                 x++;
  328.             else if(c & WEST)
  329.                 x--;
  330.             if(screen->pen == PENDOWN)
  331.                 TekDraw(x, y);
  332.             else
  333.                 TekMove(x, y);
  334.             break;
  335.  
  336.          case CASE_PLT_VEC:
  337.             /* Plt: vector */
  338.             unput(c);
  339.             if(getpoint()) {
  340.                 if(screen->pen == PENDOWN)
  341.                     TekDraw(screen->cur.x, screen->cur.y);
  342.                 else
  343.                     TekMove(screen->cur.x, screen->cur.y);
  344.                 screen->pen = PENDOWN;
  345.             }
  346.             break;
  347.  
  348.          case CASE_PT_POINT:
  349.             /* Pt: point */
  350.             unput(c);
  351.             if(getpoint()) {
  352.                 TekMove(screen->cur.x, screen->cur.y);
  353.                 TekDraw(screen->cur.x, screen->cur.y);
  354.             }
  355.             break;
  356.  
  357.          case CASE_SPT_POINT:
  358.             /* Spt: point */
  359.             /* ignore intensity character in c */
  360.             if(getpoint()) {
  361.                 TekMove(screen->cur.x, screen->cur.y);
  362.                 TekDraw(screen->cur.x, screen->cur.y);
  363.             }
  364.             break;
  365.  
  366.          case CASE_CR:
  367.             /* CR */
  368.             if(screen->TekGIN)
  369.                 TekGINoff();
  370.             if(nplot > 0)    /* flush line Tbuffer */
  371.                 TekFlush();
  372.             screen->cur_X = screen->margin == MARGIN1 ? 0 :
  373.              TEKWIDTH / 2;
  374.             Tparsestate = curstate = Talptable;
  375.             break;
  376.  
  377.          case CASE_ESC_STATE:
  378.             /* ESC */
  379.             Tparsestate = Tesctable;
  380.             break;
  381.  
  382.          case CASE_LF:
  383.             /* LF */
  384.             if(screen->TekGIN)
  385.                 TekGINoff();
  386.             TCursorDown();
  387.             if(!TekRefresh && (screen->display->qlen > 0 ||
  388.              (ioctl(screen->display->fd, FIONREAD, &arg), arg) > 0))
  389.                 xevents();
  390.             break;
  391.  
  392.          case CASE_SP:
  393.             /* SP */
  394.             TCursorForward();
  395.             break;
  396.  
  397.          case CASE_PRINT:
  398.             /* printable character */
  399.             ch = c;
  400.             c = TActiveIcon(screen)
  401.                 ? ICONFONT
  402.                 : screen->cur.fontsize;
  403.  
  404.             XTextMask(TWindow(screen), (int)(screen->cur_X *
  405.              TekScale(screen)) + screen->border,
  406.              (int)((TEKHEIGHT + TEKTOPPAD - screen->cur_Y) *
  407.              TekScale(screen)) + screen->border + TTitlebar(screen)
  408.              - screen->tobaseline[c], &ch, 1, screen->Tfont[c],
  409.              screen->Tforeground);
  410.             TCursorForward();
  411.             break;
  412.          case CASE_OSC:
  413.             /* do osc escape */
  414.             do_osc(Tinput);
  415.             Tparsestate = curstate;
  416.             break;
  417.         }
  418. }
  419.  
  420. static int rcnt;
  421. static char *rptr;
  422. static int Tselect_mask;
  423.  
  424. Tinput()
  425. {
  426.     register Screen *screen = &term.screen;
  427.     register char *cp;
  428.     register int i;
  429.     register TekLink *tek;
  430.     extern char *malloc();
  431.  
  432.     if(Tpushback > Tpushb)
  433.         return(*--Tpushback);
  434.     if(TekRefresh) {
  435.         if(rcnt-- > 0)
  436.             return(*rptr++);
  437.         if(tek = TekRefresh->next) {
  438.             TekRefresh = tek;
  439.             rcnt = tek->count - 1;
  440.             rptr = tek->data;
  441.             return(*rptr++);
  442.         }
  443.         TekRefresh = (TekLink *)0;
  444.         longjmp(Tekjump, 1);
  445.     }
  446. again:
  447.     if(Tbcnt-- <= 0) {
  448.         if(nplot > 0)    /* flush line Tbuffer */
  449.             TekFlush();
  450.         Tselect_mask = pty_mask;    /* force a read */
  451.         for( ; ; ) {
  452.             if(Tselect_mask & pty_mask) {
  453.                 if(screen->logging)
  454.                     FlushLog(screen);
  455.                 if((Tbcnt = read(screen->respond,
  456.                  Tbptr = Tbuffer, BUF_SIZE)) < 0) {
  457.                     if(errno == EIO && am_slave)
  458.                         exit(0);
  459.                     else if(errno != EWOULDBLOCK)
  460.                         Panic(
  461.                  "Tinput:read returned unexpected error (%d)\n",
  462.                          errno);
  463.                 } else if(Tbcnt == 0)
  464.                     Panic("input: read returned zero\n");
  465.                 else {
  466.                     if(screen->icon_show
  467.                        && !screen->iconinput) {
  468.                         screen->iconinput = TRUE;
  469.                         IconBox(screen);
  470.                     }
  471.                     /* strip parity bit */
  472.                     for(i = Tbcnt, cp = Tbptr ; i > 0 ; i--)
  473.                         *cp++ &= CHAR;
  474.                     break;
  475.                 }
  476.             }
  477.             if (Ttoggled && curstate == Talptable) {
  478.                 TCursorToggle(TOGGLE);
  479.                 Ttoggled = FALSE;
  480.             }
  481.             if(QLength())
  482.                 Tselect_mask = X_mask;
  483.             else {
  484.                 XFlush();
  485.                 Tselect_mask = Select_mask;
  486.                 if((i = select(max_plus1, &Tselect_mask, NULL,
  487.                  NULL, screen->timeout)) < 0){
  488.                     if (errno != EINTR)
  489.                         SysError(ERROR_TSELECT);
  490.                     continue;
  491.                 } else if(i == 0) {
  492.                     if(GetButtonState(screen->sb) & HILITED)
  493.                         WindowScroll(screen,
  494.                          ButtonRegion(screen->sb));
  495.                     screen->timeout->tv_usec = STEPTIME;
  496.                     continue;
  497.                 }
  498.             }
  499.             if(Tselect_mask & X_mask) {
  500.                 xevents();
  501.                 if(Tbcnt > 0)
  502.                     goto again;
  503.             }
  504.         }
  505.         Tbcnt--;
  506.         if (!Ttoggled && curstate == Talptable) {
  507.             TCursorToggle(TOGGLE);
  508.             Ttoggled = TRUE;
  509.         }
  510.     }
  511.     if((tek = TekRecord)->count >= TEK_LINK_BLOCK_SIZE) {
  512.         if((TekRecord = tek->next = (TekLink *)malloc(sizeof(TekLink)))
  513.          == (TekLink *)0)
  514.             Panic("Tinput: malloc error (%d)\n", errno);
  515.         tek = tek->next;
  516.         tek->next = (TekLink *)0;
  517.         tek->count = 0;
  518.         tek->ptr = tek->data;
  519.     }
  520.     tek->count++;
  521.     return(*tek->ptr++ = *Tbptr++);
  522. }
  523.  
  524. TekExpose(rep)
  525. register XExposeWindowEvent *rep;
  526. {
  527.     register Screen *screen = &term.screen;
  528.     register int border = 2 * screen->border;
  529.     register double d;
  530.  
  531.     if(rep && (screen->mappedTwin == &screen->fullTwin)) {
  532.         if (rep->width != (TWidth(screen) + border) || rep->height !=
  533.          (THeight(screen) + border + TTitlebar(screen))) {
  534.             XClear (TWindow(screen));
  535.             TWidth(screen) = rep->width - border;
  536.             THeight(screen) = rep->height - TTitlebar(screen)
  537.              - border;
  538.             TekScale(screen) = (double)TWidth(screen) /
  539.              (TEKWIDTH + TEKPAD);
  540.             if((d = (double)THeight(screen) / (TEKHEIGHT +
  541.              TEKTOPPAD + TEKBOTTOMPAD)) < TekScale(screen))
  542.                 TekScale(screen) = d;
  543.             if(TTitlebar(screen) && TFullWidth(screen) !=
  544.              rep->width)
  545.                 TekTitleResize(rep->width);
  546.             TFullWidth(screen) = rep->width;
  547.             TFullHeight(screen) = rep->height;
  548.             if (screen->active_icon)
  549.                 TSetIconSize( screen );
  550.  
  551.         } else if(TFullHeight(screen) != rep->height)
  552.             TFullHeight(screen) = rep->height;
  553.         else if(!Ttoggled)
  554.             TCursorToggle(CLEAR);
  555.     }
  556.     Ttoggled = TRUE;
  557.     Tpushback = Tpushb;
  558.     screen->cur_X = 0;
  559.     screen->cur_Y = TEKHOME;
  560.     screen->cur = screen->page;
  561.     screen->margin = MARGIN1;
  562.     if(screen->TekGIN) {
  563.         screen->TekGIN = NULL;
  564.         TekGINoff();
  565.     }
  566.     TekRefresh = &Tek0;
  567.     rptr = TekRefresh->data;
  568.     rcnt = TekRefresh->count;
  569.     Tparsestate = curstate = Talptable;
  570.     if(!screen->waitrefresh)
  571.         dorefresh();
  572. }
  573.  
  574. dorefresh()
  575. {
  576.     register Screen *screen = &term.screen;
  577.     register Cursor cur;
  578.  
  579.     XDefineCursor(TWindow(screen), cur = make_wait(screen->mousecolor,
  580.      screen->background, GXcopy));
  581.     XFlush();
  582.     if(!setjmp(Tekjump))
  583.         Tekparse();
  584.     XDefineCursor(TWindow(screen), (screen->TekGIN && GINcursor) ?
  585.      GINcursor : screen->arrow);
  586.     XFreeCursor(cur);
  587. }
  588.  
  589. TekPage()
  590. {
  591.     register Screen *screen = &term.screen;
  592.     register TekLink *tek, *tek2;
  593.  
  594.     XClear(TWindow(screen));
  595.     screen->cur_X = 0;
  596.     screen->cur_Y = TEKHOME;
  597.     screen->margin = MARGIN1;
  598.     screen->page = screen->cur;
  599.     if(screen->TekGIN)
  600.         TekGINoff();
  601.     tek = TekRecord = &Tek0;
  602.     tek->count = 0;
  603.     tek->ptr = tek->data;
  604.     if(tek = tek->next)
  605.         do {
  606.             tek2 = tek->next;
  607.             free((char *)tek);
  608.         } while(tek = tek2);
  609.     TekRecord->next = (TekLink *)0;
  610.     TekRefresh = (TekLink *)0;
  611.     Ttoggled = TRUE;
  612.     Tparsestate = curstate = Talptable;    /* Tek Alpha mode */
  613. }
  614.  
  615. #define    EXTRABITS    017
  616. #define    FIVEBITS    037
  617. #define    HIBITS        (FIVEBITS << SHIFTHI)
  618. #define    LOBITS        (FIVEBITS << SHIFTLO)
  619. #define    SHIFTHI        7
  620. #define    SHIFTLO        2
  621. #define    TWOBITS        03
  622.  
  623. getpoint()
  624. {
  625.     register int c, x, y, e, lo_y = 0;
  626.     register Screen *screen = &term.screen;
  627.  
  628.     x = screen->cur.x;
  629.     y = screen->cur.y;
  630.     for( ; ; ) {
  631.         if((c = input()) < ' ') {    /* control character */
  632.             unput(c);
  633.             return(0);
  634.         }
  635.         if(c < '@') {    /* Hi X or Hi Y */
  636.             if(lo_y) {    /* seen a Lo Y, so this must be Hi X */
  637.                 x &= ~HIBITS;
  638.                 x |= (c & FIVEBITS) << SHIFTHI;
  639.                 continue;
  640.             }
  641.             /* else Hi Y */
  642.             y &= ~HIBITS;
  643.             y |= (c & FIVEBITS) << SHIFTHI;
  644.             continue;
  645.         }
  646.         if(c < '`') {    /* Lo X */
  647.             x &= ~LOBITS;
  648.             x |= (c & FIVEBITS) << SHIFTLO;
  649.             screen->cur.x = x;
  650.             screen->cur.y = y;
  651.             return(1);    /* OK */
  652.         }
  653.         /* else Lo Y */
  654.         if(lo_y) {    /* seen a Lo Y, so other must be extra bits */
  655.             e = (y >> SHIFTLO) & EXTRABITS;
  656.             x &= ~TWOBITS;
  657.             x |= e & TWOBITS;
  658.             y &= ~TWOBITS;
  659.             y |= (e >> SHIFTLO) & TWOBITS;
  660.         }
  661.         y &= ~LOBITS;
  662.         y |= (c & FIVEBITS) << SHIFTLO;
  663.         lo_y++;
  664.     }
  665. }
  666.  
  667. TCursorBack()
  668. {
  669.     register Screen *screen = &term.screen;
  670.     register struct Tek_Char *t;
  671.     register int x, l;
  672.  
  673.     x = ( screen->cur_X -=
  674.         ( t = &TekChar[TActiveIcon(screen)
  675.                    ? ICONFONT
  676.                    : screen->cur.fontsize]
  677.         )->hsize
  678.         );
  679.  
  680.     if(screen->margin == MARGIN1 && x < 0 || screen->margin == MARGIN2
  681.      && x < TEKWIDTH / 2) {
  682.         if((l = (screen->cur_Y + (t->vsize - 1)) / t->vsize + 1) >=
  683.          t->nlines) {
  684.             screen->margin = !screen->margin;
  685.             l = 0;
  686.         }
  687.         screen->cur_Y = l * t->vsize;
  688.         screen->cur_X = (t->charsperline - 1) * t->hsize;
  689.     }
  690. }
  691.  
  692. TCursorForward()
  693. {
  694.     register Screen *screen = &term.screen;
  695.     register struct Tek_Char *t;
  696.     register int l;
  697.  
  698.     if( ( screen->cur_X +=
  699.         ( t = &TekChar[TActiveIcon(screen)
  700.                    ? ICONFONT
  701.                    : screen->cur.fontsize]
  702.         )->hsize
  703.         ) > TEKWIDTH
  704.       ) {
  705.         if((l = screen->cur_Y / t->vsize - 1) < 0) {
  706.             screen->margin = !screen->margin;
  707.             l = t->nlines - 1;
  708.         }
  709.         screen->cur_Y = l * t->vsize;
  710.         screen->cur_X = screen->margin == MARGIN1 ? 0 : TEKWIDTH / 2;
  711.     }
  712. }
  713.  
  714. TCursorUp()
  715. {
  716.     register Screen *screen = &term.screen;
  717.     register struct Tek_Char *t;
  718.     register int l;
  719.  
  720.     t = &TekChar[TActiveIcon(screen)
  721.              ? ICONFONT
  722.              : screen->cur.fontsize];
  723.  
  724.     if((l = (screen->cur_Y + (t->vsize - 1)) / t->vsize + 1) >= t->nlines) {
  725.         l = 0;
  726.         if((screen->margin = !screen->margin) != MARGIN1) {
  727.             if(screen->cur_X < TEKWIDTH / 2)
  728.                 screen->cur_X += TEKWIDTH / 2;
  729.         } else if(screen->cur_X >= TEKWIDTH / 2)
  730.             screen->cur_X -= TEKWIDTH / 2;
  731.     }
  732.     screen->cur_Y = l * t->vsize;
  733. }
  734.  
  735. TCursorDown()
  736. {
  737.     register Screen *screen = &term.screen;
  738.     register struct Tek_Char *t;
  739.     register int l;
  740.  
  741.     t = &TekChar[TActiveIcon(screen)
  742.              ? ICONFONT
  743.              : screen->cur.fontsize];
  744.  
  745.     if((l = screen->cur_Y / t->vsize - 1) < 0) {
  746.         l = t->nlines - 1;
  747.         if((screen->margin = !screen->margin) != MARGIN1) {
  748.             if(screen->cur_X < TEKWIDTH / 2)
  749.                 screen->cur_X += TEKWIDTH / 2;
  750.         } else if(screen->cur_X >= TEKWIDTH / 2)
  751.             screen->cur_X -= TEKWIDTH / 2;
  752.     }
  753.     screen->cur_Y = l * t->vsize;
  754. }
  755.  
  756. TekDraw (x, y)
  757. int x, y;
  758. {
  759.     register Screen *screen = &term.screen;
  760.  
  761.     if(nplot == 0 || T_lastx != screen->cur_X || T_lasty != screen->cur_Y) {
  762.         /*
  763.          * We flush on each unconnected line segment if the line
  764.          * type is not solid.  This solves a bug in X when drawing
  765.          * points while the line type is not solid.
  766.          */
  767.         if(nplot > 0 && screen->cur.linetype != SOLIDLINE)
  768.             TekFlush();
  769.         AddToDraw(VertexDontDraw, screen->cur_X, screen->cur_Y);
  770.     }
  771.     T_lastx = screen->cur_X = x;
  772.     T_lasty = screen->cur_Y = y;
  773.     AddToDraw(VertexDrawLastPoint, x, y);
  774. }
  775.  
  776. AddToDraw(type, x, y)
  777. int type, x, y;
  778. {
  779.     register Screen *screen = &term.screen;
  780.     register int last;
  781.     register Vertex *lp;
  782.  
  783.     if(nplot >= MAX_PTS) {
  784.         if(Tline[last = nplot - 1].flags == VertexDontDraw)
  785.             nplot--;
  786.         TekFlush();
  787.         if(type != VertexDontDraw) {
  788.             *line_pt = Tline[last];
  789.             (line_pt++)->flags = VertexDontDraw;
  790.             nplot++;
  791.         }
  792.     }
  793.     lp = line_pt++;
  794.     lp->flags = type;
  795.     lp->x = x = x * TekScale(screen) + screen->border;
  796.     lp->y = y = (TEKHEIGHT + TEKTOPPAD - y) * TekScale(screen) +
  797.      screen->border + TTitlebar(screen);
  798.     nplot++;
  799. }
  800.  
  801. TekFlush ()
  802. {
  803.     register Screen *screen = &term.screen;
  804.  
  805.     if(screen->cur.linetype == SOLIDLINE)
  806.         XDraw (TWindow(screen), Tline, nplot, 1, 1, screen->Tforeground,
  807.          GXcopy, AllPlanes);
  808.     else
  809.         XDrawDashed (TWindow(screen), Tline, nplot, 1, 1,
  810.          screen->Tforeground, screen->linepat[screen->cur.linetype - 1],
  811.          GXcopy, AllPlanes);
  812.     nplot = 0;
  813.     line_pt = Tline;
  814. }
  815.  
  816. TekGINoff()
  817. {
  818.     register Screen *screen = &term.screen;
  819.     
  820.     XDefineCursor(TWindow(screen), screen->arrow);
  821.     if(GINcursor)
  822.         XFreeCursor(GINcursor);
  823.     if(screen->TekGIN) {
  824.         *screen->TekGIN = CANCEL;    /* modify recording */
  825.         screen->TekGIN = NULL;
  826.     }
  827. }
  828.  
  829. TekEnqMouse(c)
  830. int c;
  831. {
  832.     register Screen *screen = &term.screen;
  833.     int mousex, mousey;
  834.     Window subw;
  835.  
  836.     XUpdateMouse(TWindow(screen), &mousex, &mousey, &subw);
  837.     if((mousex = (mousex - screen->border) / TekScale(screen)) < 0)
  838.         mousex = 0;
  839.     else if(mousex >= TEKWIDTH)
  840.         mousex = TEKWIDTH - 1;
  841.     if((mousey = TEKHEIGHT + TEKTOPPAD - (mousey - screen->border -
  842.      TTitlebar(screen)) / TekScale(screen)) < 0)
  843.         mousey = 0;
  844.     else if(mousey >= TEKHEIGHT)
  845.         mousey = TEKHEIGHT - 1;
  846.     TekEnq(c, mousex, mousey);
  847. }
  848.  
  849. TekEnq (status, x, y)
  850. int status;
  851. register int x, y;
  852. {
  853.     register Screen *screen = &term.screen;
  854.     int pty = screen->respond;
  855.     char cplot [5];
  856.  
  857.     /* Translate x and y to Tektronix code */
  858.     cplot[1] = 040 | ((x >> SHIFTHI) & FIVEBITS);
  859.     cplot[2] = 040 | ((x >> SHIFTLO) & FIVEBITS);
  860.     cplot[3] = 040 | ((y >> SHIFTHI) & FIVEBITS);
  861.     cplot[4] = 040 | ((y >> SHIFTLO) & FIVEBITS);
  862.     if(cplot[0] = status)
  863.         write (pty, cplot, 5);
  864.     else
  865.         write (pty, &cplot[1], 4);
  866. }
  867.  
  868. TekRun()
  869. {
  870.     register Screen *screen = &term.screen;
  871.     register int i;
  872.     
  873.     if(!TWindow(screen) && !TekInit()) {
  874.         if(VWindow(screen)) {
  875.             screen->TekEmu = FALSE;
  876.             return;
  877.         }
  878.         Exit(ERROR_TINIT);
  879.     }
  880.     if(screen->icon_show) {
  881.         if(screen->icon_show < 0) {
  882.             screen->mappedTwin = &screen->iconTwin;
  883.             screen->icon_show = TRUE;
  884.             XMapWindow(TWindow(screen));
  885.         }
  886.     } else if(!screen->Tshow) {
  887.         screen->mappedTwin = &screen->fullTwin;
  888.         screen->Tshow = TRUE;
  889.         XMapWindow(TWindow(screen));
  890.     } else
  891.         XRaiseWindow(TWindow(screen));
  892.     if(screen->select)
  893.         TekSelect();
  894.     if (L_flag > 0) {
  895.         XWarpMouse (TWindow(screen),
  896.                 TFullWidth(screen) >> 1, TFullHeight(screen) >> 1);
  897.         L_flag = -1;
  898.     }
  899.     Tpushback = Tpushb;
  900.     Tbptr = Tbuffer;
  901.     for(i = Tbcnt = bcnt ; i > 0 ; i--)
  902.         *Tbptr++ = *bptr++;
  903.     Tbptr = Tbuffer;
  904.     Ttoggled = TRUE;
  905.     if(!setjmp(Tekend))
  906.         Tekparse();
  907.     if(!Ttoggled) {
  908.         TCursorToggle(TOGGLE);
  909.         Ttoggled = TRUE;
  910.     }
  911.     screen->TekEmu = FALSE;
  912.     TekUnselect();
  913. }
  914.  
  915. static int Tpattern[TEKNUMLINES] = {
  916.     XMakePattern(0x1, 4, 1),    /* dotted */
  917.     XMakePattern(0xf1, 11, 1),    /* dot-dashed */
  918.     XMakePattern(0xf, 8, 1),    /* short-dashed */
  919.     XMakePattern(0x7f, 11, 1),    /* long-dashed */
  920. };
  921.  
  922. TekInit()
  923. {
  924.     register Screen *screen = &term.screen;
  925.     register int i, j;
  926.     register TekLink *tek;
  927.     register int width, height;
  928.     register double d;
  929.     register int border = 2 * screen->border;
  930.     OpaqueFrame twindow;
  931.     FontInfo finfo, ifinfo;
  932.     char Tdefault[32];
  933.     char iconname[128];
  934.     WindowInfo wininfo;
  935.     Color cdef;
  936.     int pixels[2];
  937.     static short Tfailed;
  938.     int x, y;
  939.     Window win;
  940.     extern char *malloc();
  941.  
  942.     screen->mappedTwin = &screen->fullTwin;
  943.  
  944.     if(Tfailed)
  945.         return(0);
  946.     if (!(screen->Tfont[SMALLFONT] = XGetFont(SMALLFONTNAME))) {
  947.         fprintf(stderr, "%s: Could not get font %s!\n",
  948.             xterm_name, SMALLFONTNAME);
  949.         goto fontfailed;
  950.     }
  951.     if((Tbuffer = (char *)malloc(BUF_SIZE)) == NULL ||
  952.      (Tpushb = (char *)malloc(10)) == NULL ||
  953.      (Tline = (Vertex *)malloc(MAX_VTX * sizeof(Vertex))) == NULL) {
  954.         fprintf(stderr, "%s: Not enough core for Tek mode\n",
  955.          xterm_name);
  956.         goto mallocfailed;
  957.     }
  958.  
  959.     screen->xorplane = 1;
  960.     screen->Tbackground = W_Pixel;
  961.     screen->Tforeground = B_Pixel;
  962.     screen->Tcursorcolor = B_Pixel;
  963.  
  964.     if (DisplayCells() > 2 && (fore_color || back_color ||
  965.      curs_color)) {
  966.         if (curs_color && XParseColor(curs_color, &cdef)) {
  967.             if(XGetColorCells(0, 2, 1, &screen->xorplane, pixels)) {
  968.                 screen->cellsused = TRUE;
  969.                 screen->colorcells[2] = cdef;
  970.                 screen->Tbackground = pixels[0];
  971.                 screen->Tforeground = pixels[1];
  972.                 screen->Tcursorcolor = screen->Tbackground |
  973.                  screen->xorplane;
  974.                 screen->Tcolor |= C_CURSOR;
  975.                 screen->planeused = TRUE;
  976.             }
  977.         } else if (XGetColorCells(0, 1, 1, &screen->xorplane,
  978.          &screen->Tbackground)) {
  979.             screen->Tforeground = screen->Tbackground |
  980.              screen->xorplane;
  981.             screen->Tcursorcolor = screen->Tforeground;
  982.             screen->planeused = TRUE;
  983.         }
  984.         if (screen->Tbackground != W_Pixel) {
  985.             if (back_color == NULL ||
  986.                 !XParseColor(back_color, &cdef)) {
  987.                 cdef.pixel = W_Pixel;
  988.                 XQueryColor(&cdef);
  989.                 screen->Tcolor |= C_BACKGROUND;
  990.             }
  991.             cdef.pixel = screen->Tbackground;
  992.             XStoreColor(&cdef);
  993.             if(screen->cellsused) {
  994.                 screen->colorcells[0] = cdef;
  995.                 cdef.pixel = screen->Tforeground |
  996.                     screen->xorplane;
  997.                 XStoreColor(&cdef);
  998.             }
  999.             if (fore_color == NULL ||
  1000.                 !XParseColor(fore_color, &cdef)) {
  1001.                 cdef.pixel = B_Pixel;
  1002.                 XQueryColor(&cdef);
  1003.                 screen->Tcolor |= C_FOREGROUND;
  1004.             }
  1005.             cdef.pixel = screen->Tforeground;
  1006.             XStoreColor(&cdef);
  1007.             if(screen->cellsused) {
  1008.                 screen->colorcells[1] = cdef;
  1009.                 cdef.pixel = screen->Tcursorcolor;
  1010.                 XStoreColor(&cdef);
  1011.             }
  1012.         }
  1013.     }
  1014.     if(term.flags & REVERSE_VIDEO) {
  1015.         screen->Tbgndtile = NULL;
  1016.         TekReverseVideo(screen);
  1017.     } else
  1018.         TekBackground(screen);
  1019.  
  1020.     twindow.bdrwidth = screen->borderwidth;
  1021.     twindow.border = screen->graybordertile;
  1022.     twindow.background = screen->Tbgndtile;
  1023.  
  1024.     sprintf(Tdefault, "=%dx%d+1+1", TEKDEFWIDTH + border, TEKDEFHEIGHT +
  1025.      TTitlebar(screen) + border);
  1026.     if((TWindow(screen) = XCreate ("Tektronix Emulator", xterm_name,
  1027.      T_geometry, Tdefault, &twindow, TEKMINWIDTH + border, TEKMINHEIGHT +
  1028.      TTitlebar(screen) + border)) == NULL) {
  1029.         fprintf(stderr, "%s: Can't create Tek window\n", xterm_name);
  1030.         free((char *)Tline);
  1031. mallocfailed:
  1032.         if(Tpushb)
  1033.             free((char *)Tpushb);
  1034.         if(Tbuffer)
  1035.             free((char *)Tbuffer);
  1036.         XFreeFont(screen->Tfont[SMALLFONT]);
  1037. fontfailed:
  1038.         Tfailed = TRUE;
  1039.         return(FALSE);
  1040.     }
  1041.     XSelectInput(TWindow(screen), TWINDOWEVENTS);
  1042.     screen->Tbox = T_box;
  1043.     /*
  1044.      * XCreate flushes all events, which might include an EnterWindow
  1045.      * or LeaveWindow.  So if the cursor is not where it is supposed to
  1046.      * be, we set select to the appropriate thing.
  1047.      */
  1048.     if(VWindow(screen) && XQueryMouse(RootWindow, &x, &y, &win)) {
  1049.         if(screen->timer) {
  1050.             Timer(0L);
  1051.             screen->timer = 0;
  1052.         }
  1053.         if(win == VWindow(screen))
  1054.             screen->select |= INWINDOW;
  1055.         else
  1056.             screen->select &= ~INWINDOW;
  1057.     }
  1058.  
  1059.     TFullWidth(screen) = twindow.width;
  1060.     TFullHeight(screen) = twindow.height;
  1061.     TWidth(screen) = twindow.width - border;
  1062.     THeight(screen) = twindow.height - TTitlebar(screen) - border;
  1063.     TekScale(screen) = (double)TWidth(screen)
  1064.                     / (TEKWIDTH + TEKPAD);
  1065.     if((d = (double)THeight(screen) / (TEKHEIGHT + TEKTOPPAD +
  1066.      TEKBOTTOMPAD)) < TekScale(screen))
  1067.         TekScale(screen) = d;
  1068.  
  1069.  
  1070.     XQueryFont(screen->Tfont[SMALLFONT], &finfo);
  1071.     screen->tobaseline[SMALLFONT] = finfo.height - finfo.baseline;
  1072.  
  1073.     if (!(screen->Tfont[THREEFONT] = XGetFont(THREEFONTNAME)))
  1074.         screen->Tfont[THREEFONT] = screen->Tfont[SMALLFONT];
  1075.     else
  1076.         XQueryFont(screen->Tfont[THREEFONT], &finfo);
  1077.     screen->tobaseline[THREEFONT] = finfo.height - finfo.baseline;
  1078.  
  1079.     if (!screen->fnt_icon)
  1080.         screen->fnt_icon = XGetFont( f_i );
  1081.  
  1082.     screen->Tfont[ICONFONT] = screen->fnt_icon;
  1083.     XQueryFont( screen->fnt_icon, &ifinfo );
  1084.     Tfontsize[ICONFONT].Twidth = ifinfo.width;
  1085.     Tfontsize[ICONFONT].Theight = ifinfo.height;
  1086.     screen->tobaseline[ICONFONT] = ifinfo.height - ifinfo.baseline;
  1087.     T_boxicon[1].x = ifinfo.width - 1;
  1088.     T_boxicon[2].y = ifinfo.height - 1;
  1089.     T_boxicon[3].x = -ifinfo.width + 1;
  1090.     T_boxicon[4].y = -ifinfo.height + 1;
  1091.  
  1092.     if (!(screen->Tfont[TWOFONT] = XGetFont(TWOFONTNAME)))
  1093.         screen->Tfont[TWOFONT] = screen->Tfont[THREEFONT];
  1094.     else
  1095.         XQueryFont(screen->Tfont[TWOFONT], &finfo);
  1096.     screen->tobaseline[TWOFONT] = finfo.height - finfo.baseline;
  1097.  
  1098.     if (!(screen->Tfont[LARGEFONT] = XGetFont(LARGEFONTNAME)))
  1099.         screen->Tfont[LARGEFONT] = screen->Tfont[TWOFONT];
  1100.     else
  1101.         XQueryFont(screen->Tfont[LARGEFONT], &finfo);
  1102.     screen->tobaseline[LARGEFONT] = finfo.height - finfo.baseline;
  1103.  
  1104.     for(i = 0 ; i < TEKNUMLINES ; i++)
  1105.         screen->linepat[i] = Tpattern[i];
  1106.     screen->margin = MARGIN1;        /* Margin 1        */
  1107.     screen->cur.fontsize = LARGEFONT;    /* set large font    */
  1108.     screen->TekGIN = FALSE;            /* GIN off        */
  1109.  
  1110.     if(screen->iconVwin.window) {
  1111.         XQueryWindow(screen->iconVwin.window, &wininfo);
  1112.         x = wininfo.x;
  1113.         y = wininfo.y;
  1114.     } else {
  1115.         x = twindow.x + (twindow.width - screen->iconTwin.width) / 2;
  1116.         y = twindow.y + (twindow.height - screen->iconTwin.height) / 2;
  1117.         IconGeometry(screen, &x, &y);
  1118.     }
  1119.     screen->iconTwin.window =
  1120.         XCreateWindow( RootWindow, x, y, 1, 1, screen->borderwidth,
  1121.                    screen->bordertile, screen->bgndtile );
  1122.  
  1123.     TSetIconSize( screen );
  1124.     XSetIconWindow( screen->fullTwin.window, screen->iconTwin.window );
  1125.  
  1126.     XDefineCursor( screen->iconTwin.window, screen->arrow );
  1127.     XSelectInput( screen->iconTwin.window,
  1128.               screen->active_icon && (term.flags & ICONINPUT)
  1129.             ? TICONWINDOWEVENTS | ICONINPUTEVENTS
  1130.             : TICONWINDOWEVENTS );
  1131.  
  1132.     XDefineCursor( TWindow(screen), screen->curs );
  1133.     if((screen->Twinname = malloc(screen->winnamelen + 6)) == NULL)
  1134.         Error(ERROR_TWINNAME);
  1135.     strcpy(screen->Twinname, screen->winname);
  1136.     strcat(screen->Twinname, " (Tek)");
  1137.     screen->Twinnamelen = strlen(screen->Twinname);
  1138.     XStoreName (TWindow(screen), screen->Twinname);
  1139.     strcpy(iconname, screen->winname);
  1140.     strcat(iconname, " (icon)");
  1141.     XStoreName (screen->iconTwin.window, iconname);
  1142.     XSetResizeHint (TWindow(screen), TEKMINWIDTH + border, TEKMINHEIGHT
  1143.      + border + TTitlebar(screen), 1, 1);
  1144.  
  1145.     tek = TekRecord = &Tek0;
  1146.     tek->next = (TekLink *)0;
  1147.     tek->count = 0;
  1148.     tek->ptr = tek->data;
  1149.     Tpushback = Tpushb;
  1150.     screen->cur_X = 0;
  1151.     screen->cur_Y = TEKHOME;
  1152.     line_pt = Tline;
  1153.     Ttoggled = TRUE;
  1154.     if(TTitlebar(screen))
  1155.         TekTitleShow(TRUE);
  1156.     Tparsestate = curstate = Talptable;
  1157.     return(TRUE);
  1158. }
  1159.  
  1160. TekReverseVideo(screen)
  1161. register Screen *screen;
  1162. {
  1163.     register int flag, i;
  1164.  
  1165.     if(screen->Tbgndtile && ((screen->Tcolor & C_BACKGROUND) ||
  1166.      screen->planeused))
  1167.         XFreePixmap(screen->Tbgndtile);
  1168.     i = screen->Tbackground;
  1169.     screen->Tbackground = screen->Tforeground;
  1170.     screen->Tforeground = i;
  1171.     screen->Tcolor = (screen->Tcolor & ~C_FBMASK) | switchfb[screen->Tcolor
  1172.      & C_FBMASK];
  1173.  
  1174.     if(screen->cellsused) {
  1175.         flag = (term.flags & REVERSE_VIDEO) != 0;
  1176.         screen->Tcursorcolor = screen->Tbackground | screen->xorplane;
  1177.         i = screen->select ? 2 : !flag;
  1178.         screen->colorcells[i].pixel = screen->Tcursorcolor;
  1179.         XStoreColor(&screen->colorcells[i]);
  1180.         screen->colorcells[flag].pixel = screen->Tforeground |
  1181.          screen->xorplane;
  1182.         XStoreColor(&screen->colorcells[flag]);
  1183.     } else
  1184.         screen->Tcursorcolor = screen->Tforeground;
  1185.     TekBackground(screen);
  1186. }
  1187.  
  1188. TekBackground(screen)
  1189. register Screen *screen;
  1190. {
  1191.     if((screen->Tcolor & C_BACKGROUND) || screen->planeused) {
  1192.         if(!(screen->Tbgndtile = XMakeTile(screen->Tbackground)))
  1193.             Error(ERROR_TBACK);
  1194.     } else
  1195.         screen->Tbgndtile = (screen->Tbackground == W_Pixel) ? W_Pixmap
  1196.          : B_Pixmap;
  1197.     if(TWindow(screen))
  1198.         XChangeBackground(TWindow(screen), screen->Tbgndtile);
  1199. }
  1200.  
  1201. /*
  1202.  * Toggles cursor on or off at cursor position in screen.
  1203.  */
  1204. TCursorToggle(toggle)
  1205. int toggle;
  1206. {
  1207.     register Screen *screen = &term.screen;
  1208.     register int c, x, y;
  1209.     register T_fontsize *Tf;
  1210.     register int pixel, func, planes;
  1211.  
  1212.     if (screen->icon_show && !screen->active_icon) return;
  1213.  
  1214.     if(toggle) {
  1215.         pixel = screen->Tcursorcolor;
  1216.         func = GXinvert;
  1217.         planes = screen->xorplane;
  1218.     } else {
  1219.         pixel = screen->Tbackground;
  1220.         func = GXcopy;
  1221.         planes = AllPlanes;
  1222.     }
  1223.  
  1224.     c = TActiveIcon(screen)
  1225.         ? ICONFONT
  1226.         : screen->cur.fontsize;
  1227.  
  1228.     x = (screen->cur_X * TekScale(screen)) + screen->border;
  1229.     y = ((TEKHEIGHT + TEKTOPPAD - screen->cur_Y) * TekScale(screen)) +
  1230.      screen->border - screen->tobaseline[c] + TTitlebar(screen);
  1231.     if(!toggle || screen->select) {
  1232.         Tf = &Tfontsize[c];
  1233.         XPixFill(TWindow(screen), x, y, Tf->Twidth, Tf->Theight, pixel,
  1234.          (Bitmap)0, func, planes);
  1235.     } else {
  1236.         screen->Tbox[c]->x = x;
  1237.         screen->Tbox[c]->y = y;
  1238.         XDraw(TWindow(screen), screen->Tbox[c], NBOX, 1, 1, pixel,
  1239.          func, planes);
  1240.     }
  1241. }
  1242.  
  1243. TekSelect()
  1244. {
  1245.     register Screen *screen = &term.screen;
  1246.  
  1247.     if(screen->borderwidth > 0)
  1248.         XChangeBorder(TWindow(screen), screen->bordertile);
  1249.     if(TTitlebar(screen))
  1250.         TekTitleHilite();
  1251. }
  1252.  
  1253. TekUnselect()
  1254. {
  1255.     register Screen *screen = &term.screen;
  1256.  
  1257.     if(screen->borderwidth > 0)
  1258.         XChangeBorder(TWindow(screen), screen->graybordertile);
  1259.     if(TTitlebar(screen))
  1260.         TekTitleUnhilite();
  1261. }
  1262.  
  1263. TekCopy()
  1264. {
  1265.     register TekLink *Tp;
  1266.     register int fd;
  1267.     register Screen *screen = &term.screen;
  1268.     register char *cp;
  1269.     register struct tm *tp;
  1270.     long l;
  1271.     char buf[32];
  1272.  
  1273.     /* for login windows, check that a user has logged in */
  1274.     if(L_flag && !checklogin()) {
  1275.         Bell();
  1276.         return;
  1277.     }
  1278.     time(&l);
  1279.     tp = localtime(&l);
  1280.     sprintf(buf, "COPY%02d-%02d-%02d.%02d:%02d:%02d", tp->tm_year,
  1281.      tp->tm_mon, tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec);
  1282.     if(access(buf, F_OK) >= 0) {    /* file exists */
  1283.         if(access(buf, W_OK) < 0) {
  1284.             Bell();
  1285.             return;
  1286.         }
  1287.     } else if(access(".", W_OK) < 0) {    /* can't write in directory */
  1288.         Bell();
  1289.         return;
  1290.     }
  1291.     if((fd = open(buf, O_WRONLY | O_CREAT | O_TRUNC, 0644)) < 0) {
  1292.         Bell();
  1293.         return;
  1294.     }
  1295.     chown(buf, screen->uid, screen->gid);
  1296.     sprintf(buf, "\033%c\033%c", screen->page.fontsize + '8',
  1297.      screen->page.linetype + '`');
  1298.     write(fd, buf, 4);
  1299.     Tp = &Tek0; 
  1300.     do
  1301.         write(fd, (char *)Tp->data, Tp->count);
  1302.     while(Tp = Tp->next);
  1303.     close(fd);
  1304. }
  1305.  
  1306. TekTitleShow(init)
  1307. int init;
  1308. {
  1309.     register Screen *screen = &term.screen;
  1310.     register int border = 2 * screen->border;
  1311.  
  1312.     if(!screen->Ttitle.tbar)
  1313.         TekTitleInit();
  1314.     if(!init) {
  1315.         XSetResizeHint (TWindow(screen), TEKMINWIDTH + border,
  1316.          TEKMINHEIGHT + border + TTitlebar(screen), 1, 1);
  1317.         XChangeWindow (TWindow(screen), TWidth(screen) + border,
  1318.          THeight(screen) + TTitlebar(screen) + border);
  1319.     }
  1320.     if(screen->select && screen->TekEmu)
  1321.         TekTitleHilite();
  1322.     else
  1323.         TekTitleUnhilite();
  1324.     XMapWindow(screen->Ttitle.tbar);
  1325. }
  1326.  
  1327. TekTitleHide()
  1328. {
  1329.     register Screen *screen = &term.screen;
  1330.     register int border = 2 * screen->border;
  1331.  
  1332.     XUnmapWindow(screen->Ttitle.tbar);
  1333.     XSetResizeHint (TWindow(screen), TEKMINWIDTH + border, TEKMINHEIGHT
  1334.      + border, 1, 1);
  1335.     XChangeWindow (TWindow(screen), TWidth(screen) + border,
  1336.      THeight(screen) + border);
  1337. }
  1338.  
  1339. TekTitleHilite()
  1340. {
  1341.     register Screen *screen = &term.screen;
  1342.  
  1343.     if(screen->Ttitle.hilited)
  1344.         return;
  1345.     XMapWindow(screen->Ttitle.left);
  1346.     XMapWindow(screen->Ttitle.right);
  1347.     screen->Ttitle.hilited = TRUE;
  1348. }
  1349.  
  1350. TekTitleUnhilite()
  1351. {
  1352.     register Screen *screen = &term.screen;
  1353.  
  1354.     if(!screen->Ttitle.hilited)
  1355.         return;
  1356.     XUnmapWindow(screen->Ttitle.left);
  1357.     XUnmapWindow(screen->Ttitle.right);
  1358.     screen->Ttitle.hilited = FALSE;
  1359. }
  1360.  
  1361. TekTitleResize(width)
  1362. register int width;
  1363. {
  1364.     register Screen *screen = &term.screen;
  1365.     register int i, j;
  1366.  
  1367.     if((screen->Ttitle.width = i = screen->Ttitle.fullwidth) >
  1368.      (j = width - 2 * (MINHILITE + screen->title_n_size + 1)))
  1369.         screen->Ttitle.width = (i = j) + screen->title_n_size;
  1370.     j = width - i - 2 * (screen->title_n_size + 1);
  1371.     i = j / 2;
  1372.     j -= i;
  1373.     screen->Ttitle.x = i + 1 + screen->title_n_size;
  1374.     XChangeWindow(screen->Ttitle.tbar, width, screen->titleheight - 1);
  1375.     XChangeWindow(screen->Ttitle.left, i, screen->titlefont->height);
  1376.     XConfigureWindow(screen->Ttitle.right, width - j - 1, TITLEPAD, j,
  1377.      screen->titlefont->height);
  1378. }
  1379.  
  1380. TekTitleExpose(rep)
  1381. register XExposeWindowEvent *rep;
  1382. {
  1383.     register Screen *screen = &term.screen;
  1384.  
  1385.     if(rep && (rep->x > (screen->Ttitle.x + screen->Ttitle.width) ||
  1386.      (rep->x + rep->width) < screen->Ttitle.x ||
  1387.      rep->y > (screen->Ttitle.y + screen->titlefont->height) ||
  1388.      (rep->y + rep->height) < screen->Ttitle.y))
  1389.         return;
  1390.     XText(screen->Ttitle.tbar, screen->Ttitle.x, screen->Ttitle.y,
  1391.      screen->Twinname, screen->Twinnamelen, screen->titlefont->id,
  1392.      screen->foreground, screen->background);
  1393. }
  1394.  
  1395. TekTitleInit()
  1396. {
  1397.     register Screen *screen = &term.screen;
  1398.     register int w, i, j;
  1399.     OpaqueFrame hilite[2];
  1400.     extern Pixmap make_hilite();
  1401.  
  1402.     if((screen->Ttitle.tbar = XCreateWindow(TWindow(screen), -1, -1,
  1403.      w = TFullWidth(screen), screen->titleheight - 1, 1, screen->bordertile,
  1404.      screen->bgndtile)) == NULL)
  1405.         Error(ERROR_TCRTITLE);
  1406.     XSelectInput(screen->Ttitle.tbar, ButtonPressed | ButtonReleased |
  1407.      ExposeWindow | EnterWindow | LeaveWindow | UnmapWindow);
  1408.     if(!screen->hilitetile && (screen->hilitetile =
  1409.      make_hilite(screen->foreground, screen->background)) == NULL)
  1410.         Error(ERROR_THILITE);
  1411.     screen->Ttitle.fullwidth = XQueryWidth(screen->Twinname,
  1412.      screen->titlefont->id);
  1413.     if((screen->Ttitle.width = i = screen->Ttitle.fullwidth) >
  1414.      (j = w - 2 * (MINHILITE + screen->title_n_size + 1)))
  1415.         screen->Ttitle.width = (i = j) + screen->title_n_size;
  1416.     j = w - i - 2 * (screen->title_n_size + 1);
  1417.     i = j / 2;
  1418.     j -= i;
  1419.     screen->Ttitle.x = i + 1 + screen->title_n_size;
  1420.     screen->Ttitle.y = TITLEPAD;
  1421.     hilite[0].x = 1;
  1422.     hilite[1].x = w - j - 1;
  1423.     hilite[0].y = hilite[1].y = TITLEPAD;
  1424.     hilite[0].width = i;
  1425.     hilite[1].width = j;
  1426.     hilite[0].height = hilite[1].height = screen->titlefont->height;
  1427.     hilite[0].bdrwidth = hilite[1].bdrwidth = 0;
  1428.     hilite[0].border = hilite[1].border = NULL;
  1429.     hilite[0].background = hilite[1].background = screen->hilitetile;
  1430.     if(XCreateWindows(screen->Ttitle.tbar, hilite, 2) != 2)
  1431.         Error(ERROR_TCRLFRG);
  1432.     screen->Ttitle.left = hilite[0].self;
  1433.     screen->Ttitle.right = hilite[1].self;
  1434. }
  1435.  
  1436. #ifdef MODEMENU
  1437. /*
  1438.  * TMENU_LARGE through TMENU_SMALL must be first, as they must be the same
  1439.  * as the font size values LARGEFONT through SMALLFONT
  1440.  */
  1441. #define    TMENU_LARGE    0
  1442. #define    TMENU_NUM2    (TMENU_LARGE+1)
  1443. #define    TMENU_NUM3    (TMENU_NUM2+1)
  1444. #define    TMENU_SMALL    (TMENU_NUM3+1)
  1445. #define    TMENU_VTWIN    (TMENU_SMALL+1)
  1446. #define    TMENU_LINE    (TMENU_VTWIN+1)
  1447. #define    TMENU_PAGE    (TMENU_LINE+1)
  1448. #define    TMENU_RESET    (TMENU_PAGE+1)
  1449. #define    TMENU_COPY    (TMENU_RESET+1)
  1450. #define    TMENU_VTMODE    (TMENU_COPY+1)
  1451. #define    TMENU_HIDETEK    (TMENU_VTMODE+1)
  1452.  
  1453. static char *Ttext[] = {
  1454.     "Large Characters",
  1455.     "#2 Size Characters",
  1456.     "#3 Size Characters",
  1457.     "Small Characters",
  1458.     "VT Window Showing",
  1459.     "-",
  1460.     "PAGE",
  1461.     "RESET",
  1462.     "COPY",
  1463.     "Select VT Mode",
  1464.     "Hide Tek Window",
  1465.     0,
  1466. };
  1467.  
  1468. static Tmodes curmodes;
  1469. static int Tsize;
  1470. static int vshow;
  1471.  
  1472. Menu *Tsetupmenu(menu)
  1473. register Menu **menu;
  1474. {
  1475.     register Screen *screen = &term.screen;
  1476.     register char **cp;
  1477.     register int size = TActiveIcon(screen)
  1478.                 ? ICONFONT
  1479.                 : screen->cur.fontsize;
  1480.     register int kflags = term.keyboard.flags;
  1481.  
  1482.     curmodes = screen->cur;
  1483.     if (*menu == NULL) {
  1484.         if ((*menu = NewMenu("Tektronix", re_verse)) == NULL)
  1485.             return(NULL);
  1486.         for(cp = Ttext ; *cp ; cp++)
  1487.             AddMenuItem(*menu, *cp);
  1488.         CheckItem(*menu, size);
  1489.         if(vshow = screen->show)
  1490.             CheckItem(*menu, TMENU_VTWIN);
  1491.         else
  1492.             DisableItem(*menu, TMENU_HIDETEK);
  1493.         DisableItem(*menu, TMENU_LINE);
  1494.         Tsize = size;
  1495.         return(*menu);
  1496.     }
  1497.     if (Tsize != size) {
  1498.         UncheckItem(*menu, Tsize);
  1499.         CheckItem(*menu, Tsize = size);
  1500.     }
  1501.     if(vshow != screen->show) {
  1502.         SetItemCheck(*menu, TMENU_VTWIN, (vshow = screen->show));
  1503.         SetItemDisable(*menu, TMENU_HIDETEK, !vshow);
  1504.     }
  1505.     return(*menu);
  1506. }
  1507.  
  1508. static char *changesize[] = {
  1509.     "\0338",
  1510.     "\0339",
  1511.     "\033:",
  1512.     "\033;",
  1513. };
  1514.  
  1515. Tdomenufunc(item)
  1516. int item;
  1517. {
  1518.     register Screen *screen = &term.screen;
  1519.     register char *tp;
  1520.     register char *fp;
  1521.     Window win;
  1522.     int x, y;
  1523.  
  1524.     switch (item) {
  1525.     case TMENU_LARGE:
  1526.     case TMENU_NUM2:
  1527.     case TMENU_NUM3:
  1528.     case TMENU_SMALL:
  1529.         if(!Ttoggled) {
  1530.             TCursorToggle(TOGGLE);
  1531.             Ttoggled = TRUE;
  1532.         }
  1533.         if(Tbcnt < 0)
  1534.             Tbcnt = 0;
  1535.         for(fp = changesize[item], tp = &Tbptr[Tbcnt] ; *fp ; ) {
  1536.             *tp++ = *fp++;
  1537.             Tbcnt++;
  1538.         }
  1539.         break;
  1540.  
  1541.     case TMENU_RESET:
  1542.         bzero((char *)&curmodes, sizeof(Tmodes));
  1543.             /* drop through */
  1544.     case TMENU_PAGE:
  1545.         TekRefresh = (TekLink *)0;
  1546.         screen->cur = curmodes;
  1547.         TekPage();
  1548.         screen->cur_X = 0;
  1549.         screen->cur_Y = TEKHOME;
  1550.         break;
  1551.  
  1552.     case TMENU_COPY:
  1553.         TekCopy();
  1554.         break;
  1555.  
  1556.     case TMENU_HIDETEK:
  1557.         screen->Tshow = FALSE;
  1558.         XUnmapWindow(TWindow(screen));
  1559.         SyncUnmap(TWindow(screen), TWINDOWEVENTS);
  1560.         reselectwindow(screen);
  1561.         TekRefresh = (TekLink *)0;
  1562.             /* drop through */
  1563.     case TMENU_VTMODE:
  1564.         if(TekRefresh)
  1565.             dorefresh();
  1566.         if(screen->TekEmu) {
  1567.             if(screen->logging) {
  1568.                 FlushLog(screen);
  1569.                 screen->logstart = buffer;
  1570.             }
  1571.             longjmp(Tekend, 1);
  1572.         } else
  1573.             XRaiseWindow(VWindow(screen));
  1574.         break;
  1575.  
  1576.     case TMENU_VTWIN:
  1577.         if(screen->show = !screen->show) {
  1578.             if(VWindow(screen) || VTInit()) {
  1579.                 XMapWindow(VWindow(screen));
  1580.                 screen->show = TRUE;
  1581.             }
  1582.         } else {
  1583.             screen->show = FALSE;
  1584.             XUnmapWindow(VWindow(screen));
  1585.             SyncUnmap(VWindow(screen), WINDOWEVENTS);
  1586.             if(!screen->TekEmu) {
  1587.                 if(TekRefresh)
  1588.                     dorefresh();
  1589.                 if(screen->logging) {
  1590.                     FlushLog(screen);
  1591.                     screen->logstart = Tbuffer;
  1592.                 }
  1593.                 screen->TekEmu = TRUE;
  1594.                 longjmp(VTend, 1);
  1595.             }
  1596.         }
  1597.         reselectwindow(screen);
  1598.         break;
  1599.     }
  1600.     if(TekRefresh)
  1601.         dorefresh();
  1602. }
  1603. #endif MODEMENU
  1604.  
  1605.  
  1606. TSetIconSize( screen )
  1607.   Screen *screen;
  1608. {
  1609.     double d;
  1610.  
  1611.     if (screen->active_icon) {
  1612.         screen->iconTwin.width = TWidth(screen)
  1613.                       * Tfontsize[ICONFONT].Twidth
  1614.                       / Tfontsize[THREEFONT].Twidth;
  1615.         screen->iconTwin.height = THeight(screen)
  1616.                       * Tfontsize[ICONFONT].Theight
  1617.                       / Tfontsize[THREEFONT].Theight;
  1618.         XChangeWindow( screen->iconTwin.window,
  1619.                screen->iconTwin.width,
  1620.                screen->iconTwin.height );
  1621.     } else
  1622.         IconRecalc( screen );
  1623.  
  1624.     screen->iconTwin.fullwidth = screen->iconTwin.width;
  1625.     screen->iconTwin.fullheight = screen->iconTwin.height;
  1626.     screen->iconTwin.tekscale = (double) screen->iconTwin.width
  1627.                     / (TEKWIDTH + TEKPAD);
  1628.  
  1629.     if ( (d = (double) screen->iconTwin.height
  1630.              / (TEKHEIGHT + TEKTOPPAD + TEKBOTTOMPAD)
  1631.          ) < screen->iconTwin.tekscale )
  1632.         screen->iconTwin.tekscale = d;
  1633. }
  1634.