home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume16 / psterm / part04 < prev    next >
Encoding:
Internet Message Format  |  1988-11-01  |  54.4 KB

  1. Subject:  v16i051:  Terminal emulator for NeWS window system, Part04/04
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: hoptoad!gnu (John Gilmore)
  7. Posting-number: Volume 16, Issue 51
  8. Archive-name: psterm/part04
  9.  
  10. : psterm part 4 of 4
  11. : To unbundle, sh this file
  12. echo tcap.cps
  13. cat >tcap.cps <<'@@@ Fin de tcap.cps'
  14. %
  15. % This file is a product of Sun Microsystems, Inc. and is provided for
  16. % unrestricted use provided that this legend is included on all tape
  17. % media and as a part of the software program in whole or part.
  18. % Users may copy, modify or distribute this file at will.
  19. % THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  20. % WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  21. % PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  22. % This file is provided with no support and without any obligation on the
  23. % part of Sun Microsystems, Inc. to assist in its use, correction,
  24. % modification or enhancement.
  25. % SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  26. % INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
  27. % OR ANY PART THEREOF.
  28. % In no event will Sun Microsystems, Inc. be liable for any lost revenue
  29. % or profits or other special, indirect and consequential damages, even
  30. % if Sun has been advised of the possibility of such damages.
  31. % Sun Microsystems, Inc.
  32. % 2550 Garcia Avenue
  33. % Mountain View, California  94043
  34. %
  35. % Modifications to the original Sun Microsystems, Inc. source code
  36. % made by the Grasshopper Group are in the Public Domain.
  37. %
  38. % Extensions to this file by Eric Messick of the Grasshopper Group.
  39. %
  40. % Grasshopper Group
  41. % 212 Clayton St
  42. % San Francisco, CA 94117
  43. %
  44. %
  45. %
  46. % "@(#)tcap.cps 9.5 88/01/19 SMI
  47. % "@(#)$Header: tcap.cps,v 2.2 88/10/04 05:59:57 gnu Release $
  48. %
  49. % Copyright (c) 1985 by Sun Microsystems, Inc.
  50. %/
  51.  
  52. cdef PSDefs(reload)
  53.     systemdict /LoadingPSTerm known {
  54.         createevent dup begin
  55.             /Name [/PSTimer /PSTermLoaded] def
  56.         end expressinterest
  57.         createevent dup begin
  58.             /Name /PSTimer def
  59.             /TimeStamp currenttime .5 add def
  60.         end sendevent awaitevent pop
  61.     } if pause
  62.     systemdict /PSTermDict known not reload 0 ne or {
  63.         systemdict /LoadingPSTerm true put
  64.         systemdict /PSTermDict undef
  65.         (psterm.ps) LoadFile pop
  66.     } if pause
  67.  
  68. cdef PSInitCode(string userinit)
  69.     PSTermDict /UserCodeLoaded known not {
  70.         (.pstermrc) LoadFile pop
  71.         PSTermDict /UserCodeLoaded true put
  72.         systemdict /LoadingPSTerm undef
  73.         createevent dup begin
  74.             /Name /PSTermLoaded def
  75.             /TimeStamp currenttime def
  76.         end sendevent
  77.     } if pause
  78.     userdict end PSTermDict begin begin        
  79.              % PSTermDict begin dictstackexch
  80.     PSTermInit
  81.     PSTermDict userinit known { userinit cvx exec } if
  82.  
  83. cdef CreateWindow(x, y, fs, col, lines, string framelabel,
  84.     string iconlabel, string initialfont, starticonic, iconx, icony)
  85.         x y fs col lines
  86.           framelabel iconlabel initialfont starticonic iconx icony
  87.           createwindow
  88.  
  89. cdef StartInput() startinput
  90. cdef ReInitialize() resetscale
  91.  
  92. cdef CursorUp(x,y,cstring c) c x y CU
  93. cdef CursorDown(x,y,cstring c) c x y CD
  94.  
  95. cdef PaintUnderRev(cstring s)    s UR
  96. cdef PaintUnderNor(cstring s)    s UN
  97. cdef PaintRev(cstring s)    s PR
  98. cdef PaintNor(cstring s)    s PN
  99. cdef MoveTo(x, y)        x y MT
  100. cdef ClearToEndOfLine()        CE
  101. cdef CopyLines(yfrom, yby, w, nl) yby w yfrom nl CL
  102.  
  103. cdef BeginRepair() BRP
  104. cdef EndRepair() ERP
  105. cdef EndRefresh() EOR
  106.  
  107. cdef SetFrameLabel(string str) str SL
  108. cdef SetSelContents(r, s, l, cstring str)    str s l r setselcontents
  109. cdef RingBell() VB        % no audible bell as yet
  110. cdef VisibleBell() VB
  111. cdef SetPageMode(onoff) onoff PM
  112. cdef SetAutoMargins(onoff) onoff AM
  113.  
  114. cdef StartHiLighting(strokeit) strokeit [
  115. cdef HiLightLine(length) length
  116. cdef EndHiLighting(endcol, startcol, startrow) endcol ] startcol startrow HL
  117. cdef ClearSelectionPath() clearselectionpath
  118. cdef RePaintHiLight() PaintHiLight
  119. cdef StrHiLightLine(cstring s) s
  120. cdef StrEndHiLighting(cstring ends, cstring starts,
  121.     startrow) ends ] starts startrow HL
  122. cdef TakeDownOutline() takedownoutline
  123. cdef StartSavingSelection() startselset
  124. cdef SaveSelectionPiece(cstring s) s extsel
  125. cdef FinishSavingSelection() finishselset
  126. cdef HiLightRect(startcol, startrow, endcol, endrow, strokeit)
  127.     strokeit startcol startrow endcol endrow HiLightRect
  128.  
  129. cdef ToggleScrollBar(len) len TSB
  130. cdef SetScrollBarValue(len, pos) len pos SSBV
  131.  
  132. cdef PopMsg(string str)
  133.     gsave framebuffer setcanvas currentcursorlocation str popmsg grestore
  134. @@@ Fin de tcap.cps
  135. echo tcap_ops.c
  136. cat >tcap_ops.c <<'@@@ Fin de tcap_ops.c'
  137. /*
  138.  * This file is a product of Sun Microsystems, Inc. and is provided for
  139.  * unrestricted use provided that this legend is included on all tape
  140.  * media and as a part of the software program in whole or part.
  141.  * Users may copy, modify or distribute this file at will.
  142.  * 
  143.  * THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  144.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  145.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  146.  * 
  147.  * This file is provided with no support and without any obligation on the
  148.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  149.  * modification or enhancement.
  150.  * 
  151.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  152.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
  153.  * OR ANY PART THEREOF.
  154.  * 
  155.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  156.  * or profits or other special, indirect and consequential damages, even
  157.  * if Sun has been advised of the possibility of such damages.
  158.  * 
  159.  * Sun Microsystems, Inc.
  160.  * 2550 Garcia Avenue
  161.  * Mountain View, California  94043
  162.  *
  163.  * Modifications to the original Sun Microsystems, Inc. source code
  164.  * made by the Grasshopper Group are in the Public Domain.
  165.  *
  166.  * Extensions to this file by Eric Messick of the Grasshopper Group.
  167.  *
  168.  * Grasshopper Group
  169.  * 212 Clayton St
  170.  * San Francisco, CA 94117
  171.  *
  172.  */
  173.  
  174. #ifndef lint
  175. static    char sccsid[] = "@(#)tcap_ops.c 9.6 88/01/19 Copyright 1985 Sun Micro";
  176. static    char RCSid[] =
  177.     "@(#)$Header: tcap_ops.c,v 2.3 88/10/04 05:59:59 gnu Release $";
  178. #endif
  179.  
  180. /*
  181.  * Copyright (c) 1985 by Sun Microsystems, Inc.
  182.  */
  183.  
  184. /*-
  185.     tcap_ops.c
  186.  
  187.     tcap_ops.c, Mon Mar 24 11:52:31 1986
  188.  
  189.         David Rosenthal,
  190.         Sun Microsystems
  191.  */
  192.  
  193.  
  194. #include    <stdio.h>
  195. #include    <sys/types.h>
  196. #ifdef REF
  197. #include    <ref/config.h>
  198. #endif
  199. #include    "termcap.h"
  200. #include    "tcap.h"
  201.  
  202. /*
  203.  * Termcap operations module.
  204.  *
  205.  *    The external interface of this module is the array T[] and its
  206.  *    number of elements Ts,  plus the initialization routine:
  207.  *    tc_init_ops()
  208.  */
  209.  
  210. #include    "screen.h"
  211. extern    int CharsPerLine;
  212. extern    int LinesPerScreen;
  213. extern    struct pair Dot;
  214. extern    struct tcap T[];
  215. extern    int Ts;
  216. extern    char *malloc();
  217. #ifndef bcopy
  218. extern    void bcopy();
  219. #endif
  220. #ifndef bzero
  221. extern    void bzero();
  222. #endif
  223. extern    char *strncpy();
  224. static    struct tcap *tc_lookup();
  225.  
  226. static    u_short TopLineOfScrollRegion, BottomLineOfScrollRegion;
  227. static    struct pair SavedCursor;
  228. static    u_short ScrollNLKludge = 0;
  229. struct    tcap *CheckCR = 0;
  230. struct    tcap *CheckNL = 0;
  231. struct    tcap *CheckBS = 0;
  232. struct    tcap *CheckTAB = 0;
  233.  
  234. static unsigned int PermanentModes = 0,  TemporaryModes = 0;
  235.  
  236. static    char *FrameLabel;
  237. static    u_short FLindex;
  238. static    int (*prevInput)();
  239.  
  240. struct    tcap interruptedOp = { 0 };
  241. struct    line *lastInputLine;
  242. int    PageFull = 0;
  243. static    int PrevPageMode = -1;
  244. extern    int PageMode;
  245. extern    int userLinesPerScreen;
  246. extern    int userCharsPerLine;
  247.  
  248. static int al_op(), clear_body(), ce_op(), cm_in(), cs_op();
  249. static int dc_op(), dl_op(), ic_op(), nl_op(), sf_op();
  250.  
  251. tc_init_ops()
  252. {
  253.     struct tcap *me, *tc;
  254.  
  255.     if (userLinesPerScreen > 0)
  256.     LinesPerScreen = userLinesPerScreen;
  257.     if (userCharsPerLine > 0)
  258.     CharsPerLine = userCharsPerLine;
  259.     Dot.x = 0 ;
  260.     Dot.y = LinesPerScreen - 1 ;
  261.     TopLineOfScrollRegion = 0;
  262.     BottomLineOfScrollRegion = LinesPerScreen - 1;
  263.     FrameLabel = malloc((unsigned)CharsPerLine+1);
  264.     /*
  265.      * Beware of termcap entries that define ue and/or se identical
  266.      * to me (turn off ALL attributes).  Since we just pattern
  267.      * match, it's likely we won't get me_op in normal operation,
  268.      * so force the entries here. (known for vt100)
  269.      */
  270.     me = tc_lookup("me");
  271.     if (me) {
  272.     tc = tc_lookup("ue");
  273.     if (tc && tc->t_size == me->t_size &&
  274.         bcmp(me->t_text, tc->t_text, (int)tc->t_size) == 0)
  275.         tc->t_op = me->t_op;
  276.     tc = tc_lookup("se");
  277.     if (tc && tc->t_size == me->t_size &&
  278.         bcmp(me->t_text, tc->t_text, (int)tc->t_size) == 0)
  279.         tc->t_op = me->t_op;
  280.     }
  281.     /*
  282.      * Check for sf == \n, if so we must kludge things so that
  283.      * sf_op will call nl_op as needed (exists on bitgraph).
  284.      */
  285.     tc = tc_lookup("sf");
  286.     if (tc && tc->t_size == 1 && tc->t_text[0] == '\n')
  287.     ScrollNLKludge = 1;
  288.     /*
  289.      * To minimize the number of times the regular text processing
  290.      * is stopped to invoke the pattern matcher we check the most
  291.      * strings CR, NL, BS, and TAB to see if they are \r, \n, \b,,
  292.      * and \t, respectively.  If any are, a quick check on the character
  293.      * is made before the pattern matching machinery is invoked.
  294.      */
  295.     tc = tc_lookup("cr");
  296.     if (tc && tc->t_size == 1 && tc->t_text[0] == '\r')
  297.        CheckCR = tc;
  298.     tc = tc_lookup("nl");
  299.     if (tc && tc->t_size == 1 && tc->t_text[0] == '\n')
  300.        CheckNL = tc;
  301.     tc = tc_lookup("bc");
  302.     if (tc && tc->t_size == 1 && tc->t_text[0] == '\b')
  303.        CheckBS = tc;
  304.     tc = tc_lookup("ta");
  305.     if (tc && tc->t_size == 1 && tc->t_text[0] == '\t')
  306.        CheckTAB = tc;
  307. }
  308.  
  309. tc_initmodemenu()
  310. {
  311.  
  312.     /*
  313.      * Insure menu items properly reflect initial settings.
  314.      */
  315.     SetPageMode(PageMode);
  316.     SetAutoMargins(PermanentModes & AutoMarginMode);
  317. }
  318.  
  319. static struct tcap *
  320. tc_lookup(key)
  321.     char *key;
  322. {
  323.     register struct tcap *tp;
  324.  
  325.     for (tp = T; *tp->t_key; tp++)
  326.     if (strcmp(tp->t_key, key) == 0)
  327.         return (tp);
  328.     return ((struct tcap *)0);
  329. }
  330.  
  331. /*
  332.  * scrollreset is called whenever keyboard input is seen, in order to
  333.  * do deferred scrolling and remember the last line on which the user
  334.  * typed something.
  335.  */
  336.  
  337. scrollreset(l)
  338.     int l;
  339. {
  340.     int n = PageFull;
  341.  
  342.     PageFull = 0;
  343.     lastInputLine = (l == 1) ? screen[1] : 0;
  344.     while (n-- > 0 && !PageFull)
  345.     sf_op((struct tcap *) 0);
  346.     if (lastInputLine == 0)
  347.     lastInputLine = screen[Dot.y];
  348. }
  349.  
  350. toggleautomargins()
  351. {
  352.  
  353.     PermanentModes ^= (unsigned int) AutoMarginMode;
  354.     SetAutoMargins(PermanentModes & AutoMarginMode);
  355.     FlushPostScript();
  356. }
  357.  
  358. togglepagemode()
  359. {
  360.     SetPageMode(PageMode = !PageMode);
  361.     FlushPostScript();
  362. }
  363.  
  364. resetscreensize(row, col)
  365. int row, col;
  366. {
  367.     struct tcap t;
  368.     int dotx, doty;
  369.  
  370.     dotx = Dot.x ;
  371.     if (dotx >= col) dotx = col - 1;
  372.  
  373.     doty = Dot.y - LinesPerScreen + row ;
  374.     if (doty >= row) doty = row - 1;
  375.     if (doty < 0) doty = 0 ;
  376.  
  377.     if (PageMode) {
  378.         /* no scroll stop line */
  379.         lastInputLine = screen[doty - row + LinesPerScreen];
  380.     }
  381.  
  382.     CharsPerLine = col ;
  383.     LinesPerScreen = row ;
  384.  
  385.     t.t_x = LinesPerScreen - 1 ;
  386.     t.t_y = 0 ;
  387.     cs_op(&t);    /* change scrolling region to full screen */
  388.             /* if it wasn't full screen before, then it's the
  389.              * program's responsibility to change it after
  390.              * getting the sigwinch 
  391.              * note that this trashes Dot, so we save it.
  392.              */
  393.     Dot.x = dotx ;
  394.     Dot.y = doty ;
  395. }
  396.  
  397. #ifdef notdef
  398. static
  399. trace(s, t)
  400.     register char *s;
  401.     register struct tcap *t;
  402. {
  403.     register char *q = t->t_text;
  404.  
  405.     fprintf(stderr, "%s: ", s);
  406.     fprintf(stderr, "[%s,", t->t_key);
  407.     if (q == NULL)
  408.     fprintf(stderr, "(nil)");
  409.     else while (*q) {
  410.     if (*q < ' ') {
  411.         fprintf(stderr, "^%c", *q + '@');
  412.     } else {
  413.         fprintf(stderr, "%c", *q);
  414.     }
  415.     q++;
  416.     }
  417.     fprintf(stderr, ",%d,(%d,%d)]\n", t->t_index, t->t_x, t->t_y);
  418. }
  419. #endif
  420.  
  421. #ifndef    notdef
  422. #define    trace(X, Y)    (void)(X, Y)
  423. #endif
  424. #define ChangeScreen()
  425. #define    MoveCursor()
  426.  
  427. #ifdef notdef
  428. static
  429. PrintScreen()
  430. {
  431.     register int y;
  432.  
  433.     for (y = 0; y < LinesPerScreen; y++) {
  434.     register struct line *l = screen[y];
  435.     register int x;
  436.  
  437.     if (l == NULL)
  438.         fprintf(stderr, "(nil)");
  439.     else for (x = 0; x < l->length; x++) {
  440.         if (x == Dot.x && y == Dot.y)
  441.         fprintf(stderr, "+");
  442.         else if (x == l->changeposition)
  443.         fprintf(stderr, "|");
  444.         else
  445.             fprintf(stderr, "%c", (l->body[x] == ' ' ? '.' : l->body[x]));
  446.     }
  447.     fprintf(stderr, "\n");
  448.     }
  449.     fprintf(stderr, "\n");
  450. }
  451. #endif
  452.  
  453. showc(t)
  454. struct tcap *t;
  455. {
  456.     register char *cp = t->t_text;
  457.     register struct line *l;
  458.     register int dotx, c;
  459.     register unsigned Modes = PermanentModes | TemporaryModes;
  460.     int n = t->t_size;
  461.     register char *bp;
  462.     register u_char *pp;
  463.  
  464.     trace("==", t);
  465.     TemporaryModes = 0;
  466.     dotx = Dot.x;
  467.     while (n > 0 && !PageFull) {
  468.         l = screen[Dot.y];
  469.         if (l->changeposition > dotx)
  470.             l->changeposition = dotx;
  471.         if (l->length < dotx)
  472.             l->length = dotx;
  473.         bp = &l->body[dotx] ;
  474.         pp = &l->prop[dotx] ;
  475.         if (Modes & InsertMode && l->length > dotx) {
  476.             n-- ;
  477.             c = *cp++;
  478.             if (c < ' ' || c >= 0177)
  479.                 continue;
  480.             if (l->length < CharsPerLine)
  481.                 l->length++;
  482.  
  483.             bcopy((char *)pp, (char *)pp+1,(int)(l->length-dotx-1));
  484.             bcopy(        bp,         bp+1,(int)(l->length-dotx-1));
  485.  
  486.             l->end_of_changes = CharsPerLine + 1 ;
  487.             *bp = c;
  488.             *pp = (Modes & Attributes);
  489.             if (++dotx >= CharsPerLine) {
  490.                 if (Modes & AutoMarginMode) {
  491.                     trace("cr", t);
  492.                     l->end_of_changes = CharsPerLine + 1 ;
  493.                     l->flags |= LINE_WRAPPED ;
  494.                     if (l->length < dotx)
  495.                         l->length = dotx ;
  496.                     dotx = 0;
  497.                     MoveCursor();
  498.                     nl_op(t);
  499.                     TemporaryModes |= WrapJustHappenedMode;
  500.                     }
  501.                 else    dotx = CharsPerLine - 1;
  502.                 }
  503.             }
  504.         else    {
  505.             while (n-- > 0 && !PageFull) {
  506.                 c = *cp++;
  507.                 if (c < ' ' || c >= 0177)
  508.                     continue;
  509.                 *bp++ = c;
  510.                 *pp++ = (Modes & Attributes);
  511.                 if (++dotx >= CharsPerLine) {
  512.                     if (Modes & AutoMarginMode) {
  513.                         trace("cr", t);
  514.                         l->end_of_changes =
  515.                             CharsPerLine + 1 ;
  516.                         l->flags |= LINE_WRAPPED ;
  517.                         if (l->length < dotx)
  518.                             l->length = dotx ;
  519.                         dotx = 0;
  520.                         MoveCursor();
  521.                         nl_op(t);
  522.                         TemporaryModes |=
  523.                             WrapJustHappenedMode;
  524.                         break;
  525.                         }
  526.                     else    dotx = CharsPerLine - 1;
  527.                     }
  528.                 }
  529.             }
  530.         if (l->length < dotx)
  531.             l->length = dotx ;
  532.         if (l->end_of_changes < dotx)
  533.             l->end_of_changes = dotx;
  534.         }
  535.     Dot.x = dotx;
  536.     ChangeScreen();
  537.     /*
  538.      * If we were interrupted by nl_op setting PageFull, set up
  539.      * interruptedOp with a tcap that can be used to finish this later.
  540.      */
  541.     if (PageFull && ++n > 0) {
  542.         interruptedOp = *t;
  543.         interruptedOp.t_text += (t->t_size - n);
  544.         interruptedOp.t_size = n;
  545.         }
  546.     else    interruptedOp.t_op = 0;
  547. }
  548.  
  549. static int
  550. AL_op(t)    /* add multiple blank lines */
  551.     struct tcap *t;
  552. {
  553.     trace("AL", t);
  554.     /* cheat for now */
  555.     while (t->t_y-- > 0)
  556.     al_op(t);
  557.     ChangeScreen();
  558. }
  559.  
  560. static int
  561. DC_op(t)
  562.     struct tcap *t;
  563. {
  564.     trace("DC", t);
  565.     /* cheat for now */
  566.     while (t->t_y-- > 0)
  567.     dc_op(t);
  568.     ChangeScreen();
  569. }
  570.  
  571. static int
  572. DL_op(t)    /* delete multiple lines */
  573.     struct tcap *t;
  574. {
  575.     trace("DL", t);
  576.     /* cheat for now */
  577.     while (t->t_y-- > 0)
  578.     dl_op(t);
  579.     ChangeScreen();
  580. }
  581.  
  582. static int
  583. DO_in(t)    /* move cursor down n lines */
  584.     struct tcap *t;
  585. {
  586.     trace("DO", t);
  587.     return (cm_in(t));    /* Neat!  It might even work */
  588. }
  589.  
  590. static int
  591. DO_op(t)    /* move cursor down n lines */
  592.     register struct tcap *t;
  593. {
  594.     trace("DO", t);
  595.     if (t->t_y >= 0 && (Dot.y + t->t_y) < LinesPerScreen)
  596.         Dot.y += t->t_y;
  597.     MoveCursor();
  598. }
  599.  
  600. static int
  601. IC_op(t)
  602.     struct tcap *t;
  603. {
  604.     trace("IC", t);
  605.     /* cheat for now */
  606.     while (t->t_y-- > 0)
  607.     ic_op(t);
  608.     ChangeScreen();
  609. }
  610.  
  611. static int
  612. LE_in(t)    /* move cursor left n characters */
  613.     struct tcap *t;
  614. {
  615.     trace("LE", t);
  616.     return (cm_in(t));    /* Neat!  It might even work */
  617. }
  618.  
  619. static int
  620. LE_op(t)    /* move cursor left n characters */
  621.     register struct tcap *t;
  622. {
  623.     trace("LE", t);
  624.     if ((Dot.x - t->t_y) >= 0)
  625.         Dot.x -= t->t_y;
  626.     MoveCursor();
  627. }
  628.  
  629. static int
  630. RI_in(t)    /* move cursor right n characters */
  631.     struct tcap *t;
  632. {
  633.     trace("RI", t);
  634.     return (cm_in(t));    /* Neat!  It might even work */
  635. }
  636.  
  637. static int
  638. RI_op(t)    /* move cursor right n characters */
  639.     register struct tcap *t;
  640. {
  641.     trace("RI", t);
  642.     if (t->t_y >= 0 && (Dot.x + t->t_y) <= CharsPerLine)
  643.         Dot.x += t->t_y;
  644.     MoveCursor();
  645. }
  646.  
  647. static int
  648. UP_in(t)    /* move cursor up n lines */
  649.     struct tcap *t;
  650. {
  651.     trace("UP", t);
  652.     return (cm_in(t));    /* Neat!  It might even work */
  653. }
  654.  
  655. static int
  656. UP_op(t)    /* move cursor up n lines */
  657.     register struct tcap *t;
  658. {
  659.     trace("UP", t);
  660.     if ((Dot.y - t->t_y) >= 0)
  661.         Dot.y -= t->t_y;
  662.     MoveCursor();
  663. }
  664.  
  665. static int
  666. al_op(t)    /* Add new blank line */
  667.     struct tcap *t;
  668. {
  669.     register struct line **p, **current;
  670.     register struct line *old;
  671.  
  672.     trace("al", t);
  673.     current = &screen[Dot.y];
  674.     p = &screen[BottomLineOfScrollRegion];
  675.     old = *p;
  676.     for (; p > current; p--)
  677.     *p = *(p-1);
  678.     *p = old;
  679.     clear_body(old, 0);
  680.     old->length = 0;
  681.     old->changeposition = 0;
  682.     old->end_of_changes = CharsPerLine;
  683.     old->usedtobe = LinesPerScreen;
  684.     ChangeScreen();
  685. }
  686.  
  687. static int
  688. am_in(t)    /* Has auto-margins */
  689.     struct tcap *t;
  690. {
  691.     trace("am", t);
  692.     if (t->t_x) PermanentModes |= AutoMarginMode;
  693.     return (0);
  694. }
  695.  
  696. static int
  697. bc_op(t)    /* back-character */
  698.     struct tcap *t;
  699. {
  700.     trace("bc", t);
  701.     if (Dot.x > 0)
  702.     Dot.x--;
  703.     MoveCursor();
  704. }
  705.  
  706. static int
  707. bl_op(t)    /* Bell character */
  708.     struct tcap *t;
  709. {
  710.     trace("bl", t);
  711.     RingBell();
  712. }
  713.  
  714. /*
  715.  * Clearing the whole line body for the clear ops may be excessive
  716.  * but nothing short of it seems to work for programs which do a lot
  717.  * of cursor manipulation, such as rogue or hack.
  718.  */
  719. static int
  720. clear_body(l, x)
  721.     struct line *l;
  722.     int x;
  723. {
  724.     register int len = l->buffer_length - x;
  725.     register char *cp;
  726.  
  727.     bzero((char *)&l->prop[x], len);
  728.     l->flags = 0 ;
  729.     for (cp = &l->body[x]; len-- > 0;)
  730.      *cp++ = ' ';
  731. }
  732.  
  733. static int
  734. cd_op(t)    /* Clear to end of display */
  735.     struct tcap *t;
  736. {
  737.     register struct line **p, **last;
  738.     register struct line *l;
  739.  
  740.     trace("cd", t);
  741.     ce_op(t);
  742.     last = &screen[LinesPerScreen];
  743.     for (p = &screen[Dot.y+1]; p < last; p++) {
  744.     (l = *p)->length = 0;
  745.     l->changeposition = 0;
  746.     l->end_of_changes = CharsPerLine ;
  747.     clear_body(l, 0);
  748.     }
  749.     ChangeScreen();
  750. }
  751.  
  752. static int
  753. ce_op(t)    /* Clear to end of line */
  754.     struct tcap *t;
  755. {
  756.     register struct line *l = screen[Dot.y];
  757.  
  758.     trace("ce", t);
  759.     l->length = Dot.x;
  760.     if (l->changeposition > Dot.x)
  761.     l->changeposition = Dot.x;
  762.     l->end_of_changes = CharsPerLine ;
  763.     clear_body(l, (int)l->length);
  764.     ChangeScreen();
  765. }
  766.  
  767. static int
  768. cl_op(t)    /* Clear screen */
  769.     struct tcap *t;
  770. {
  771.     register struct line **p, **last;
  772.     register struct line *l;
  773.  
  774.     trace("cl", t);
  775.     Dot.x = Dot.y = 0;
  776.     last = &screen[LinesPerScreen];
  777.     for (p = &screen[0]; p < last; p++) {
  778.     (l = *p)->length = 0;
  779.     l->changeposition = 0;
  780.     l->end_of_changes = CharsPerLine ;
  781.     clear_body(l, 0);
  782.     }
  783.     ChangeScreen();
  784.     if (PageMode)
  785.     lastInputLine = screen[Dot.y];    /* no scroll stop line */
  786. }
  787.  
  788. #ifdef    HAVE_TERMCAP
  789. static int
  790. cm_in(t)    /* Cursor motion */
  791.     register struct tcap *t;
  792. {
  793.     register u_char c;
  794.     char        buf[128];
  795.     register    char *cp = t->t_text, *bp = buf;
  796.  
  797.     trace("cm", t);
  798.  
  799.     if (cp == NULL)
  800.     return(0);
  801.     /* Pre-process out parts of the % escapes */
  802.     while ((c = *cp++) != '\0') {
  803.     if (c == '%') {
  804.         register u_char c2 = *cp++;
  805.  
  806.         switch (c2) {
  807.         case '+':        /* Subtract next then %. */
  808.         switch (t->t_2nd + t->t_pc_r) {
  809.         case 0:
  810.         case 2:
  811.             t->t_yi = *cp++;
  812.             break;
  813.         case 1:
  814.             t->t_xi = *cp++;
  815.             break;
  816.         }
  817.         c2 = '.';
  818.         goto percent_dot;
  819.         case '>':
  820.         switch (t->t_2nd + t->t_pc_r) {
  821.         case 1:
  822.             t->t_xilim = *cp++;
  823.             t->t_xi = *cp++;
  824.             t->t_xilim += t->t_xi + 1;
  825.             break;
  826.         case 0:
  827.         case 2:
  828.             t->t_yilim = *cp++;
  829.             t->t_yi = *cp++;
  830.             t->t_yilim += t->t_yi + 1;
  831.             break;
  832.         }
  833.         t->t_2nd = !t->t_2nd;
  834.         break;
  835.         case 'r':
  836.         t->t_pc_r = 1;
  837.         break;
  838.         case 'i':
  839.         t->t_xi++;
  840.         t->t_yi++;
  841.         break;
  842.         case 'n':
  843.         t->t_pc_n = 1;
  844.         break;
  845.         case 'B':
  846.         t->t_pc_B = 1;
  847.         break;
  848.         case 'D':
  849.         t->t_pc_D = 1;
  850.         break;
  851.         /* The following ones will be interpreted on the fly */
  852.         case 'd':        /* series of decimal digits */
  853.         case '2':        /* two decimal digits */
  854.         case '3':        /* three decimal digits */
  855.         case '.':        /* binary character */
  856.     percent_dot:
  857.         case '%':
  858.         *bp++ = c;
  859.         *bp++ = c2;
  860.         t->t_2nd = !t->t_2nd;
  861.         break;
  862.         default:        /* Bad % escape */
  863.         return (1);
  864.         }
  865.     }
  866.     else {
  867.         *bp++ = c;
  868.     }
  869.     }
  870.     *bp++ = '\0';
  871.     if (bp-buf > 1) {
  872.     if ((t->t_text = malloc((unsigned)(bp-buf+1))) == NULL)
  873.         return (2);
  874.     strncpy(t->t_text, buf, bp-buf);
  875.     t->t_size = bp-buf - 1;
  876.     } else {
  877.     t->t_text = NULL;
  878.     }
  879.     t->t_2nd = 0;
  880.     return (0);
  881. }
  882.  
  883. #else    /* !HAVE_TERMCAP */
  884.  
  885. static int
  886. cm_in(t)    /* Cursor motion */
  887.     register struct tcap *t;
  888. {
  889.     register u_char c;
  890.     char        buf[128];
  891.     register    char *cp = t->t_text, *bp = buf;
  892.  
  893.     trace("cm", t);
  894.  
  895.     if (cp == NULL)
  896.     return(0);
  897.     /* Pre-process out parts of the % escapes */
  898.     while ((c = *cp++) != '\0') {
  899.     static int    seen1 = 0;
  900.  
  901.     if (c == '%') {
  902.         register u_char c2 = *cp++;
  903.  
  904.         switch (c2) {
  905.         case 'p':
  906.         switch (*cp++) {
  907.         case '1':
  908.             seen1++;
  909.             t->t_2nd = 0;
  910.             break;
  911.         case '2':
  912.             if (!seen1)
  913.                 t->t_pc_r = 1;
  914.             t->t_2nd = 1;
  915.             break;
  916.         /*
  917.          * This capability is not available in termcap so we will
  918.          * assume that it is not present in terminfo either. This
  919.          * means that terminal that send more than two pieces of
  920.          * variable data with the "cm" directive will not work.
  921.          * Currently for "cm" only two variables are defined.
  922.          */
  923.         case '3':
  924.         case '4':
  925.         case '5':
  926.         case '6':
  927.         case '7':
  928.         case '8':
  929.         case '9':
  930.            return(1);
  931.         }
  932.         break;
  933.  
  934.         case '\'':        /* store constant for future operator */
  935.         switch (t->t_2nd + t->t_pc_r) {
  936.         case 0:
  937.         case 2:
  938.             t->t_yi = *cp++;
  939.             break;
  940.         case 1:
  941.             t->t_xi = *cp++;
  942.             break;
  943.         }
  944.         if (*cp == '\'')
  945.             cp++;        /* blow past the trailing '\'' */
  946.         else
  947.             return(1);
  948.         break;
  949.         case '{':        /* store decimal constant for future operator */
  950.         switch (t->t_2nd + t->t_pc_r) {
  951.         case 0:
  952.         case 2:
  953.             t->t_yi = ((*cp++) * 10) + (*cp++);
  954.             break;
  955.         case 1:
  956.             t->t_xi = ((*cp++) * 10) + (*cp++);
  957.             break;
  958.         }
  959.         if (*cp == '}')
  960.             cp++;        /* blow past trailing '}' */
  961.         else
  962.             return(1);
  963.         break;
  964.         /* the following will  not work do to the simplifications here */
  965.         case '?':        /* if */
  966.         case 't':        /* then */
  967.         case 'e':        /* else */
  968.         return(1);    /* lets not delude ourselves, the data
  969.                  *  structures were set up to deal with termcap
  970.                  *  not the complexities of terminfo.
  971.                  */
  972.         case 'i':
  973.         t->t_xi++;
  974.         t->t_yi++;
  975.         break;
  976.         case '+':
  977.         if (*cp++ != '%')
  978.             return(1);
  979.         if (*cp++ != 'c')
  980.             return(1);
  981.         *bp++ = '%';        /* make it look like termcap */
  982.         *bp++ = '.';
  983.         break;
  984.         /* use the simpified model of termcap so some of this
  985.          * stuff is not valid
  986.          */
  987.         case '\b':        /* flags in format string */
  988.         case ':':        /* needed for '-' and '+' flags */
  989.         case '#':        /* flags in format string */
  990.         case '.':        /* if only fract part of precision */
  991.         return(1);
  992.         /* just leave a 'd' */
  993.         case '0':        /* numeric part of precision */
  994.         case '1':        /* numeric part of precision */
  995.         case '4':        /* numeric part of precision */
  996.         case '5':        /* numeric part of precision */
  997.         case '6':        /* numeric part of precision */
  998.         case '7':        /* numeric part of precision */
  999.         case '8':        /* numeric part of precision */
  1000.         case '9':        /* numeric part of precision */
  1001.         /* skip past the end of this definition, leave %d in its place*/
  1002.         while (*cp != 'd' && *cp != 'o' && *cp != 'x'
  1003.                 && *cp != 'X' && *cp != 's')
  1004.             cp++;
  1005.         /* don't support anything but 'd' */
  1006.         if (*cp != 'd')
  1007.             return(1);
  1008.         *bp++ = c;        /* '%' */
  1009.         *bp++ = *cp++;        /* 'd' */
  1010.         /* The following ones will be interpreted on the fly. */
  1011.         case '2':        /* numeric part of precision */
  1012.         case '3':        /* numeric part of precision */
  1013.         /* remove %[23]->[doxXs], put %[23] in bp */
  1014.         *bp++ = c;
  1015.         *bp++ = c2;
  1016.         /* skip any factional part of the precision */
  1017.         while (*cp != 'd' && *cp != 'o' && *cp != 'x'
  1018.                 && *cp != 'X' && *cp != 's')
  1019.             cp++;
  1020.         /* don't support anything but 'd' */
  1021.         if (*cp != 'd')
  1022.             return(1);
  1023.         *cp++;        /* get rid of the 'd' */
  1024.         break;
  1025.         /* not suported by termcap, so not supported here */
  1026.         case 'o':        /* octal: no other formating is present */
  1027.         case 'x':        /* hex: no other formating is present */
  1028.         case 'X':        /* HEX: no other formating is present */
  1029.         case 's':        /* String: no other formating is present */
  1030.         case 'c':        /* binary character */
  1031.         case 'l':        /* strlen() operator */
  1032.         case '=':        /* equal operator */ 
  1033.         case '>':        /* greater than operator */
  1034.         case '<':        /* less than operator */
  1035.         case '-':        /* subtract operator */
  1036.         case '*':        /* multiply operator */
  1037.         case '/':        /* divide operator */
  1038.         case 'm':        /* modula operator */
  1039.         case '&':        /* bitwise and operator */
  1040.         case '|':        /* bitwise or operator */
  1041.         case '^':        /* bitwise xor operator */
  1042.         case '~':        /* bitwise not operator */
  1043.         case 'A':        /* logical and operator */
  1044.         case 'O':        /* logical or operator */
  1045.         case '!':        /* logical not operator */
  1046.         return(1);
  1047.         /* include the string "%A" where A = one of the following cases */
  1048.         case 'd':        /* decimal: no other formating is present */
  1049.         case '%':
  1050.         *bp++ = c;
  1051.         *bp++ = c2;
  1052.         break;
  1053.         default:        /* Bad % escape */
  1054.         return (1);
  1055.         }
  1056.     }
  1057.     else {
  1058.         *bp++ = c;
  1059.     }
  1060.     }
  1061.     *bp++ = '\0';
  1062.     if (bp-buf > 1) {
  1063.     if ((t->t_text = malloc(bp-buf+1)) == NULL)
  1064.         return (2);
  1065.     strncpy(t->t_text, buf, bp-buf);
  1066.     t->t_size = bp-buf - 1;
  1067.     } else {
  1068.     t->t_text = NULL;
  1069.     }
  1070.     t->t_2nd = 0;
  1071.     return (0);
  1072. }
  1073. #endif    /* !HAVE_TERMCAP */
  1074.  
  1075. static int
  1076. cm_op(t)    /* Cursor motion */
  1077.     register struct tcap *t;
  1078. {
  1079.  
  1080.     trace("cm", t);
  1081.     lastInputLine = 0;            /* no scroll stop line */
  1082.     if (t->t_x >= 0 && t->t_x < CharsPerLine)
  1083.     Dot.x = t->t_x;
  1084.     if (t->t_y >= 0 && t->t_y < LinesPerScreen)
  1085.     Dot.y = t->t_y;
  1086.     MoveCursor();
  1087. }
  1088.  
  1089. static int
  1090. co_in(t)    /* number of columns */
  1091.     struct tcap *t;
  1092. {
  1093.     trace("co", t);
  1094.     if (userCharsPerLine < 1)
  1095.     CharsPerLine = t->t_x;
  1096.     return (0);
  1097. }
  1098.  
  1099. static int
  1100. cr_op(t)    /* carriage return */
  1101.     struct tcap *t;
  1102. {
  1103.     trace("cr", t);
  1104.     Dot.x = 0;
  1105.     MoveCursor();
  1106. }
  1107.  
  1108. static int
  1109. cs_in(t)    /* change scroll region */
  1110.     struct tcap *t;
  1111. {
  1112.     trace("cs", t);
  1113.     return (cm_in(t));    /* Neat!  It might even work */
  1114. }
  1115.  
  1116. static int
  1117. cs_op(t)    /* change scroll region */
  1118.     register struct tcap *t;
  1119. {
  1120.     trace("cs", t);
  1121.     if (t->t_y >= t->t_x || t->t_x >= LinesPerScreen)
  1122.     return;
  1123.     Dot.x = 0;
  1124.     Dot.y = t->t_y;
  1125.     TopLineOfScrollRegion = t->t_y;
  1126.     BottomLineOfScrollRegion = t->t_x;
  1127.     lastInputLine = 0;            /* no scroll stop line */
  1128.     MoveCursor();
  1129. }
  1130.  
  1131. static int
  1132. dc_op(t)    /* delete character */
  1133.     struct tcap *t;
  1134. {
  1135.     register struct line *l = screen[Dot.y];
  1136.     register int dotx = Dot.x;
  1137.     int len;
  1138.  
  1139.     trace("dc", t);
  1140.     if (l->changeposition > dotx)
  1141.     l->changeposition = dotx;
  1142.     if (dotx < l->length) {
  1143.     l->length--;
  1144.     len = l->length - dotx;
  1145.     bcopy((char *)&l->prop[dotx+1], (char *)&l->prop[dotx], len);
  1146.     l->prop[l->length] = 0 ;
  1147.     bcopy(&l->body[dotx+1], &l->body[dotx], len);
  1148.     l->body[l->length] = ' ' ;
  1149.     }
  1150.     l->end_of_changes = CharsPerLine ;
  1151.     ChangeScreen();
  1152. }
  1153.  
  1154. static int
  1155. dl_op(t)    /* delete line */
  1156.     struct tcap *t;
  1157. {
  1158.     register struct line **p, **bottom;
  1159.     register struct line *old = screen[Dot.y];
  1160.  
  1161.     trace("dl", t);
  1162.     lastInputLine = 0;            /* no scroll stop line */
  1163.     bottom = &screen[BottomLineOfScrollRegion];
  1164.     for (p = &screen[Dot.y]; p < bottom; p++)
  1165.     *p = *(p+1);
  1166.     *p = old;
  1167.     clear_body(old, 0);
  1168.     old->length = 0;
  1169.     old->changeposition = 0;
  1170.     old->end_of_changes = CharsPerLine ;
  1171.     old->usedtobe = LinesPerScreen ;
  1172.     ChangeScreen();
  1173. }
  1174.  
  1175. static int
  1176. do_op(t)    /* down one line */
  1177.     struct tcap *t;
  1178. {
  1179.     trace("do", t);
  1180.     if (PermanentModes & IgnoreNewlineAfterWrapMode) {
  1181.     if (TemporaryModes & WrapJustHappenedMode) {
  1182.         TemporaryModes &= ~WrapJustHappenedMode;
  1183.         return;
  1184.     }
  1185.     }
  1186.     if (Dot.y < LinesPerScreen - 1)
  1187.     Dot.y++;
  1188.     else {
  1189.     sf_op(t);
  1190.     }
  1191.     MoveCursor();
  1192. }
  1193.  
  1194. static int
  1195. ei_op(t)    /* end insert mode */
  1196.     struct tcap *t;
  1197. {
  1198.     trace("ei", t);
  1199.     PermanentModes &= ~InsertMode;
  1200. }
  1201.  
  1202. static int
  1203. el_op(t)    /* end frame label definition mode */
  1204.     struct tcap *t;
  1205. {
  1206.     if (FrameLabel) {
  1207.     FrameLabel[FLindex] = '\0';
  1208.     SetFrameLabel(FrameLabel);
  1209.     }
  1210.     t = T+Ts;
  1211.     t->t_op = prevInput;
  1212. }
  1213.  
  1214. static int
  1215. ke_op(t)    /* leave keyboard transmit mode */
  1216.     struct tcap *t;
  1217. {
  1218.     trace("ke", t);
  1219. }
  1220.  
  1221. static int
  1222. ks_op(t)    /* enter keyboard transmit mode */
  1223.     struct tcap *t;
  1224. {
  1225.     trace("ks", t);
  1226. }
  1227.  
  1228. static int
  1229. ho_op(t)    /* home cursor */
  1230.     struct tcap *t;
  1231. {
  1232.  
  1233.     trace("ho", t);
  1234.     lastInputLine = 0;            /* no scroll stop line */
  1235.     Dot.x = Dot.y = 0;
  1236.     MoveCursor();
  1237. }
  1238.  
  1239. static int
  1240. ic_op(t)    /* insert character */
  1241.     struct tcap *t;
  1242. {
  1243.     trace("ic", t);
  1244.     TemporaryModes |= InsertMode;
  1245. }
  1246.  
  1247. static int
  1248. im_op(t)    /* enter insert mode */
  1249.     struct tcap *t;
  1250. {
  1251.     trace("im", t);
  1252.     PermanentModes |= InsertMode;
  1253. }
  1254.  
  1255. static int
  1256. le_op(t)    /* cursor left */
  1257.     struct tcap *t;
  1258. {
  1259.     trace("le", t);
  1260.     if (Dot.x > 0)
  1261.     Dot.x--;
  1262.     MoveCursor();
  1263. }
  1264.  
  1265. static int
  1266. li_in(t)    /* number of lines */
  1267.     struct tcap *t;
  1268. {
  1269.     trace("li", t);
  1270.     if (userLinesPerScreen < 1)
  1271.     LinesPerScreen = t->t_x;
  1272.     return (0);
  1273. }
  1274.  
  1275. static int
  1276. ll_op(t)    /* last line first column */
  1277.     struct tcap *t;
  1278. {
  1279.     trace("ll", t);
  1280.     Dot.x = 0;
  1281.     Dot.y = LinesPerScreen - 1;
  1282.     MoveCursor();
  1283. }
  1284.  
  1285. static int
  1286. lm_op(t)    /* label mode input */
  1287.     register struct tcap *t;
  1288. {
  1289.     trace("lm", t);
  1290.     if (FLindex + t->t_size >= CharsPerLine)
  1291.     t->t_size = CharsPerLine - FLindex;
  1292.     if (t->t_size > 0) {
  1293.     if (FrameLabel)
  1294.         strncpy(&FrameLabel[FLindex], t->t_text, (int)t->t_size);
  1295.     FLindex += t->t_size;
  1296.     }
  1297. }
  1298.  
  1299. static int
  1300. mb_op(t)    /* enable blink */
  1301.     struct tcap *t;
  1302. {
  1303.     trace("mb", t);
  1304.     PermanentModes |= BlinkMode;
  1305. }
  1306.  
  1307. static int
  1308. md_op(t)    /* enter bold mode */
  1309.     struct tcap *t;
  1310. {
  1311.     trace("md", t);
  1312.     PermanentModes |= BoldMode;
  1313. }
  1314.  
  1315. static int
  1316. me_op(t)    /* turn off attributes */
  1317.     struct tcap *t;
  1318. {
  1319.     trace("me", t);
  1320.     PermanentModes &= ~(Attributes);
  1321. }
  1322.  
  1323. static int
  1324. mr_op(t)    /* enter reverse video */
  1325.     struct tcap *t;
  1326. {
  1327.     trace("mr", t);
  1328.     PermanentModes |= ReverseVideoMode;
  1329. }
  1330.  
  1331. static int
  1332. nd_op(t)    /* cursor right */
  1333.     struct tcap *t;
  1334. {
  1335.     trace("nd", t);
  1336.     if (Dot.x < (CharsPerLine - 1))
  1337.     Dot.x++;
  1338.     MoveCursor();
  1339. }
  1340.  
  1341. static int
  1342. nl_op(t)    /* newline */
  1343.     struct tcap *t;
  1344. {
  1345.     trace("nl", t);
  1346.     if (PermanentModes & IgnoreNewlineAfterWrapMode) {
  1347.     if (TemporaryModes & WrapJustHappenedMode) {
  1348.         TemporaryModes &= ~WrapJustHappenedMode;
  1349.         return;
  1350.     }
  1351.     }
  1352.     if (Dot.y < LinesPerScreen - 1)
  1353.     Dot.y++;
  1354.     else {
  1355.     sf_op(t);
  1356.     }
  1357.     MoveCursor();
  1358. }
  1359.  
  1360. static int
  1361. rc_op(t)    /* restore cursor */
  1362.     struct tcap *t;
  1363. {
  1364.     trace("rc", t);
  1365.     Dot = SavedCursor;
  1366.     MoveCursor();
  1367. }
  1368.  
  1369. static int
  1370. sc_op(t)    /* save cursor */
  1371.     struct tcap *t;
  1372. {
  1373.     trace("sc", t);
  1374.     SavedCursor = Dot;
  1375.     MoveCursor();
  1376. }
  1377.  
  1378. static int
  1379. se_op(t)    /* leave stand-out */
  1380.     struct tcap *t;
  1381. {
  1382.     trace("se", t);
  1383.     PermanentModes &= ~StandOutMode;
  1384. }
  1385.  
  1386. static int
  1387. so_op(t)    /* enter stand-out */
  1388.     struct tcap *t;
  1389. {
  1390.     trace("so", t);
  1391.     PermanentModes |= StandOutMode;
  1392. }
  1393.  
  1394. static int
  1395. sf_op(t)    /* scroll forwards */
  1396.     struct tcap *t;
  1397. {
  1398.     register struct line **p, **bottom;
  1399.     register struct line *old;
  1400.     static int SFrecur = 0;
  1401.  
  1402.     trace("sf", t);
  1403.     /*
  1404.      * When sf is "\n", nl_op won't be called, so we emulate
  1405.      * it's actions here (beware of recursion).
  1406.      */
  1407.     if (ScrollNLKludge && !SFrecur) {
  1408.     SFrecur++; nl_op(t); SFrecur--;
  1409.     return (1);            /* XXX */
  1410.     }
  1411.     p = &screen[TopLineOfScrollRegion];
  1412.     if (PageMode && *p == lastInputLine) {
  1413.     PageFull++;            /* can't scroll this line */
  1414.     return (0);
  1415.     }
  1416.     ScrollSaveLine(*p);
  1417.     bottom = &screen[BottomLineOfScrollRegion];
  1418.     p = &screen[TopLineOfScrollRegion];
  1419.     old = *p;
  1420.     for (; p < bottom; p++)
  1421.     *p = *(p+1);
  1422.     *p = old;
  1423.     clear_body(old, 0);
  1424.     old->length = 0;
  1425.     old->changeposition = 0;
  1426.     old->end_of_changes = CharsPerLine ;
  1427.     old->usedtobe = LinesPerScreen;
  1428.     ChangeScreen();
  1429.     return (1);
  1430. }
  1431.  
  1432. static int
  1433. sl_op(t)    /* start defining new frame label */
  1434.     register struct tcap *t;
  1435. {
  1436.     trace("sl", t);
  1437.     FLindex = 0;
  1438.     t = T+Ts;
  1439.     prevInput = t->t_op;
  1440.     t->t_op = lm_op;
  1441. }
  1442.  
  1443. static int
  1444. sr_op(t)    /* scroll reverse */
  1445.     struct tcap *t;
  1446. {
  1447.     register struct line **p, **top;
  1448.     register struct line *old;
  1449.  
  1450.     trace("sr", t);
  1451.     lastInputLine = 0;            /* no scroll stop line */
  1452.     top = &screen[TopLineOfScrollRegion];
  1453.     p = &screen[BottomLineOfScrollRegion];
  1454.     old = *p;
  1455.     for (; p > top; p--)
  1456.     *p = *(p-1);
  1457.     *p = old;
  1458.     clear_body(old, 0);
  1459.     old->length = 0;
  1460.     old->changeposition = 0;
  1461.     old->end_of_changes = CharsPerLine ;
  1462.     old->usedtobe = LinesPerScreen;
  1463.     ChangeScreen();
  1464. }
  1465.  
  1466. static int
  1467. ta_op(t)    /* tab */
  1468.     struct tcap *t;
  1469. {
  1470.     trace("ta", t);
  1471.     Dot.x = (Dot.x & ~07) + 010;
  1472.     if (Dot.x >= CharsPerLine - 1)
  1473.     Dot.x = CharsPerLine - 1;
  1474.     MoveCursor();
  1475. }
  1476.  
  1477. static int
  1478. te_op(t)    /* end use of termcap */
  1479.     struct tcap *t;
  1480. {
  1481.     trace("te", t);
  1482.     if (PrevPageMode != -1) {
  1483.     PageMode = PrevPageMode;
  1484.     PrevPageMode = -1;
  1485.     }
  1486. }
  1487.  
  1488. static int
  1489. ti_op(t)    /* begin use of termcap */
  1490. {
  1491.     trace("ti", t);
  1492.     /*
  1493.      * Turn off page mode when using termcap.
  1494.      */
  1495.     if (PrevPageMode == -1) {
  1496.     PrevPageMode = PageMode;
  1497.     PageMode = 0;
  1498.     }
  1499. }
  1500.  
  1501. static int
  1502. ue_op(t)    /* end underline */
  1503.     struct tcap *t;
  1504. {
  1505.     trace("ue", t);
  1506.     PermanentModes &= ~UnderlineMode;
  1507. }
  1508.  
  1509. static int
  1510. up_op(t)    /* cursor up */
  1511.     struct tcap *t;
  1512. {
  1513.     trace("up", t);
  1514.     if (Dot.y > 0)
  1515.     Dot.y--;
  1516.     else    /* vi will never do this,  but some ll caps may */
  1517.         Dot.y = LinesPerScreen - 1;
  1518.     MoveCursor();
  1519. }
  1520.  
  1521. static int
  1522. us_op(t)    /* start underline */
  1523.     struct tcap *t;
  1524. {
  1525.     trace("us", t);
  1526.     PermanentModes |= UnderlineMode;
  1527. }
  1528.  
  1529. static int
  1530. vb_op(t)    /* visibile bell */
  1531.     struct tcap *t;
  1532. {
  1533.     trace("bl", t);
  1534.     VisibleBell();
  1535. }
  1536.  
  1537. static int
  1538. xn_in(t)
  1539.     struct tcap *t;
  1540. {
  1541.     trace("xn", t);
  1542.     if (t->t_x) PermanentModes |= IgnoreNewlineAfterWrapMode;
  1543.     return (0);
  1544. }
  1545.  
  1546. /* These capabilities are numeric or boolean - they dont have ops */
  1547. #define am_op    NULL
  1548. #define    bs_op    NULL
  1549. #define    co_op    NULL
  1550. #define    li_op    NULL
  1551. #define pc_op    NULL
  1552. #define xn_op    NULL
  1553.  
  1554. /* These capabilities are strings that dont need initialization */
  1555. #define    al_in    NULL
  1556. #define    bc_in    NULL
  1557. #define    bl_in    NULL
  1558. #define    cd_in    NULL
  1559. #define    ce_in    NULL
  1560. #define    cl_in    NULL
  1561. #define    cr_in    NULL
  1562. #define    dc_in    NULL
  1563. #define    dl_in    NULL
  1564. #define    do_in    NULL
  1565. #define    ei_in    NULL
  1566. #define    ke_in    NULL
  1567. #define    ks_in    NULL
  1568. #define    ho_in    NULL
  1569. #define    ic_in    NULL
  1570. #define    im_in    NULL
  1571. #define    le_in    NULL
  1572. #define    ll_in    NULL
  1573. #define    mb_in    NULL
  1574. #define    md_in    NULL
  1575. #define    me_in    NULL
  1576. #define    mr_in    NULL
  1577. #define    nd_in    NULL
  1578. #define    nl_in    NULL
  1579. #define pc_in    NULL
  1580. #define rc_in    NULL
  1581. #define    sc_in    NULL
  1582. #define    se_in    NULL
  1583. #define    sf_in    NULL
  1584. #define    so_in    NULL
  1585. #define    sr_in    NULL
  1586. #define    ta_in    NULL
  1587. #define    ue_in    NULL
  1588. #define    up_in    NULL
  1589. #define    us_in    NULL
  1590.  
  1591. #define    s    string
  1592. #define n    num
  1593. #define b    bool
  1594.  
  1595. struct tcap T[] = {
  1596. /*
  1597.  *   key   ty op     in     text  deftx sz in tmp  tf
  1598.  *    x  xi xl y  yi yl r  n  B  D  2
  1599.  */
  1600.     {"AL", s, AL_op, cs_in, NULL,   NULL, 0, 0, NULL, 0},
  1601.     {"DL", s, DL_op, cs_in, NULL,   NULL, 0, 0, NULL, 0},
  1602.     {"DC", s, DC_op, cs_in, NULL,   NULL, 0, 0, NULL, 0},
  1603.     {"DO", s, DO_op, DO_in, NULL,   NULL, 0, 0, NULL, 0},
  1604.     {"IC", s, IC_op, cs_in, NULL,   NULL, 0, 0, NULL, 0},
  1605.     {"LE", s, LE_op, LE_in, NULL,   NULL, 0, 0, NULL, 0},
  1606.     {"RI", s, RI_op, RI_in, NULL,   NULL, 0, 0, NULL, 0},
  1607.     {"UP", s, UP_op, UP_in, NULL,   NULL, 0, 0, NULL, 0},
  1608.     {"al", s, al_op, al_in, NULL,   NULL, 0, 0, NULL, 0},
  1609.     {"am", b, am_op, am_in, NULL,   NULL, 0, 0, NULL, 0},
  1610.     {"bc", s, bc_op, bc_in, NULL,  "\10", 0, 0, NULL, 0},
  1611.     {"bl", s, bl_op, bl_in, NULL,   "\7", 0, 0, NULL, 0},
  1612.     {"cd", s, cd_op, cd_in, NULL,   NULL, 0, 0, NULL, 0},
  1613.     {"ce", s, ce_op, ce_in, NULL,   NULL, 0, 0, NULL, 0},
  1614.     {"cl", s, cl_op, cl_in, NULL,   NULL, 0, 0, NULL, 0},
  1615.     {"cm", s, cm_op, cm_in, NULL,   NULL, 0, 0, NULL, 0},
  1616.     {"co", n, co_op, co_in, NULL,   NULL, 0, 0, NULL, 0},
  1617.     {"cr", s, cr_op, cr_in, NULL, "\015", 0, 0, NULL, 0},
  1618.     {"cs", s, cs_op, cs_in, NULL,   NULL, 0, 0, NULL, 0},
  1619.     {"dc", s, dc_op, dc_in, NULL,   NULL, 0, 0, NULL, 0},
  1620.     {"dl", s, dl_op, dl_in, NULL,   NULL, 0, 0, NULL, 0},
  1621.     {"do", s, do_op, do_in, NULL,   NULL, 0, 0, NULL, 0},
  1622.     {"ei", s, ei_op, ei_in, NULL,   NULL, 0, 0, NULL, 0},
  1623.     {"el", s, el_op, NULL,  NULL,"\033\\",0, 0, NULL, 0}, /* end label */
  1624.     {"ke", s, ke_op, ke_in, NULL,   NULL, 0, 0, NULL, 0},
  1625.     {"ks", s, ks_op, ks_in, NULL,   NULL, 0, 0, NULL, 0},
  1626.     {"ho", s, ho_op, ho_in, NULL,   NULL, 0, 0, NULL, 0},
  1627.     {"ic", s, ic_op, ic_in, NULL,   NULL, 0, 0, NULL, 0},
  1628.     {"im", s, im_op, im_in, NULL,   NULL, 0, 0, NULL, 0},
  1629.     {"le", s, le_op, le_in, NULL,   NULL, 0, 0, NULL, 0},
  1630.     {"li", n, li_op, li_in, NULL,   NULL, 0, 0, NULL, 0},
  1631.     {"ll", s, ll_op, ll_in, NULL,   NULL, 0, 0, NULL, 0},
  1632.     {"lm", s, lm_op,  NULL, NULL,   NULL, 0, 0, NULL, 0}, /* label mode input */
  1633.     {"mb", s, mb_op, mb_in, NULL,   NULL, 0, 0, NULL, 0},
  1634.     {"md", s, md_op, md_in, NULL,   NULL, 0, 0, NULL, 0},
  1635.     {"me", s, me_op, me_in, NULL,   NULL, 0, 0, NULL, 0},
  1636.     {"mr", s, mr_op, mr_in, NULL,   NULL, 0, 0, NULL, 0},
  1637.     {"nd", s, nd_op, nd_in, NULL,   NULL, 0, 0, NULL, 0},
  1638.     {"nl", s, nl_op, nl_in, NULL, "\012", 0, 0, NULL, 0},
  1639.     {"pc", s, pc_op, pc_in, NULL, "\200", 0, 0, NULL, 0},
  1640.     {"rc", s, rc_op, rc_in, NULL,   NULL, 0, 0, NULL, 0},
  1641.     {"sc", s, sc_op, sc_in, NULL,   NULL, 0, 0, NULL, 0},
  1642.     {"se", s, se_op, se_in, NULL,   NULL, 0, 0, NULL, 0},
  1643.     {"sf", s, sf_op, sf_in, NULL,   NULL, 0, 0, NULL, 0},
  1644.     {"sl", s, sl_op, NULL,  NULL,"\033]l",0, 0, NULL, 0}, /* start label */
  1645.     {"so", s, so_op, so_in, NULL,   NULL, 0, 0, NULL, 0},
  1646.     {"sr", s, sr_op, sr_in, NULL,   NULL, 0, 0, NULL, 0},
  1647.     {"ta", s, ta_op, ta_in, NULL, "\011", 0, 0, NULL, 0},    /* XXX */
  1648.     {"te", s, te_op, NULL,  NULL,   NULL, 0, 0, NULL, 0},
  1649.     {"ti", s, ti_op, NULL,  NULL,   NULL, 0, 0, NULL, 0},
  1650.     {"ue", s, ue_op, ue_in, NULL,   NULL, 0, 0, NULL, 0},
  1651.     {"up", s, up_op, up_in, NULL,   NULL, 0, 0, NULL, 0},
  1652.     {"us", s, us_op, us_in, NULL,   NULL, 0, 0, NULL, 0},
  1653.     {"vb", s, vb_op,  NULL, NULL,   NULL, 0, 0, NULL, 0},
  1654.     {"xn", b, xn_op, xn_in, NULL,   NULL, 0, 0, NULL, 0},
  1655.     {"",   s, showc,  NULL, NULL,   NULL, 0, 0, NULL, 0},
  1656. };
  1657.  
  1658. /* T[Ts] is a special case - its the display-character operation */
  1659. int Ts = (sizeof T)/(sizeof T[0]) - 1;
  1660. @@@ Fin de tcap_ops.c
  1661. echo tcap_parse.c
  1662. cat >tcap_parse.c <<'@@@ Fin de tcap_parse.c'
  1663. /*
  1664.  * This file is a product of Sun Microsystems, Inc. and is provided for
  1665.  * unrestricted use provided that this legend is included on all tape
  1666.  * media and as a part of the software program in whole or part.
  1667.  * Users may copy, modify or distribute this file at will.
  1668.  * 
  1669.  * THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  1670.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  1671.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  1672.  * 
  1673.  * This file is provided with no support and without any obligation on the
  1674.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  1675.  * modification or enhancement.
  1676.  * 
  1677.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  1678.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
  1679.  * OR ANY PART THEREOF.
  1680.  * 
  1681.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  1682.  * or profits or other special, indirect and consequential damages, even
  1683.  * if Sun has been advised of the possibility of such damages.
  1684.  * 
  1685.  * Sun Microsystems, Inc.
  1686.  * 2550 Garcia Avenue
  1687.  * Mountain View, California  94043
  1688.  *
  1689.  * Modifications to the original Sun Microsystems, Inc. source code
  1690.  * made by the Grasshopper Group are in the Public Domain.
  1691.  *
  1692.  * Extensions to this file by Eric Messick of the Grasshopper Group.
  1693.  *
  1694.  * Grasshopper Group
  1695.  * 212 Clayton St
  1696.  * San Francisco, CA 94117
  1697.  *
  1698.  */
  1699.  
  1700. #ifndef lint
  1701. static    char sccsid[] =
  1702.     "@(#)tcap_parse.c 9.5 88/01/19 Copyright 1985 Sun Micro";
  1703. static    char RCSid[] =
  1704.     "@(#)$Header: tcap_parse.c,v 2.3 88/10/04 06:00:03 gnu Release $";
  1705. #endif
  1706.  
  1707.  
  1708. /*
  1709.  * Copyright (c) 1985 by Sun Microsystems, Inc.
  1710.  */
  1711.  
  1712. /*-
  1713.     tcap_parse.c:  Parse termcap output based on termcap entry.
  1714.  
  1715.     tcap_parse.c, Mon Mar 24 11:25:44 1986
  1716.  
  1717.         David Rosenthal,
  1718.         Sun Microsystems
  1719.  */
  1720.     /* XXX - remember longest outstanding partial match? */
  1721.     /* XXX - overlapping partial matches? */
  1722.  
  1723. #include    <stdio.h>
  1724. #include    <ctype.h>
  1725. #include    <sys/types.h>
  1726. #ifdef REF
  1727. #include    <ref/config.h>
  1728. #endif
  1729. #include    "termcap.h"
  1730.  
  1731. extern char *malloc();
  1732. #ifndef bcopy
  1733. extern void bcopy();
  1734. #endif
  1735.  
  1736. static    int TerminalIsBraindamaged = 0;
  1737. /*  Import these from tcap_ops.c */
  1738. extern struct tcap T[];
  1739. extern int Ts;
  1740. extern struct tcap *CheckCR;
  1741. extern struct tcap *CheckNL;
  1742. extern struct tcap *CheckTAB;
  1743. extern struct tcap *CheckBS;
  1744. extern int PageFull;
  1745. extern int PageMode;
  1746.  
  1747. static char *unpad();
  1748. static int tc_init_stacks();
  1749.  
  1750. /*
  1751.  * Initialize the display system from the TERMCAP entry.
  1752.  * We parse the entry and build the tcap structures
  1753.  * describing the operations supported by this type of
  1754.  * terminal.  These descriptions are then used by tc_display()
  1755.  * in interpreting the data stream generated by the
  1756.  * application
  1757.  */
  1758. int
  1759. tc_initialize(term)
  1760.     char *term;
  1761. {
  1762. #ifdef SUNTGETENT
  1763.     static void tc_fix_tcap_ent();
  1764. #endif
  1765.     static char tcapbuf[1024], tcaparea[1024];
  1766.     char       *areap = tcaparea;
  1767.     extern int tgetent(), tgetnum(), tgetflag();
  1768.     extern char *tgetstr();
  1769.     register struct tcap *tp;
  1770.  
  1771.     if (tgetent(tcapbuf, term) != 1) {        /* unknown terminal type? */
  1772.     fprintf(stderr, "tgetent failed\n");
  1773.     return (1);
  1774.     }
  1775. #ifdef SUNTGETENT
  1776.     tc_fix_tcap_ent(tcapbuf);
  1777. #endif
  1778.     set_environment_var("TERMCAP", tcapbuf);
  1779.     for (tp = T; tp < T+Ts; tp++) {
  1780.     switch (tp->t_type) {
  1781.     case string:
  1782.         tp->t_text = unpad(tgetstr(tp->t_key, &areap));
  1783.         if (tp->t_text == NULL)
  1784.         tp->t_text = tp->t_deftext;
  1785.         if (tp->t_text) {
  1786.             tp->t_size = strlen(tp->t_text);
  1787.             if (isprint(tp->t_text[0]))
  1788.                 TerminalIsBraindamaged = 1;
  1789.         } else
  1790.             tp->t_size = 0;
  1791.         break;
  1792.     case num:
  1793.         tp->t_x = tgetnum(tp->t_key);
  1794.         break;
  1795.     case bool:
  1796.         tp->t_x = tgetflag(tp->t_key);
  1797.         break;
  1798.     }
  1799.     /* invoke any initialize routine */
  1800.     if (tp->t_in && (*tp->t_in)(tp)) {
  1801.         fprintf(stderr, "termcap init failed for %s\n", tp->t_key);
  1802.         return (1);
  1803.         }
  1804.     }
  1805.     tc_init_ops();
  1806.     return tc_init_stacks();
  1807. }
  1808.  
  1809. #ifdef HAVE_TERMCAP
  1810. static char *
  1811. unpad(s)
  1812.     register char *s;
  1813. {
  1814.  
  1815.     if (s) {
  1816.     register pad = 0;
  1817.  
  1818.     while (isdigit(*s))
  1819.         pad++, s++;
  1820.     if (pad && *s == '*')
  1821.         s++;
  1822.     }
  1823.     return (s);
  1824. }
  1825.  
  1826. #else    /* !HAVE_TERMCAP, ie next code is for TERMINFO */
  1827.  
  1828. /*
  1829.  * Remove the substring of the form "$<x^>" where x = number, and ^ = characters
  1830.  * in the set [* /]. This is the terminfo way of specifying delays or padding.
  1831.  */
  1832. static char *
  1833. unpad(s)
  1834.     register char *s;
  1835. {
  1836.  
  1837.     if (s) {
  1838.     register char *spt = s;
  1839.     register char *spt1, *spt2;
  1840.     char *strchr();
  1841.  
  1842.     while (spt1 = strchr(spt, '$')) {
  1843.         if (*(spt1 + 1) == '<') {    /* found the '$<' pair */
  1844.             if (spt2 = strchr(spt1, '>')) {
  1845.                 strcpy(spt1, ++spt2);    /* found end '>' */
  1846.                 spt = spt1;        /* copy tail of */
  1847.                 continue;        /* string over  */
  1848.                             /* '$<..', look */
  1849.                             /* for more */
  1850.             } else
  1851.                 break;        /* no match for '$<' so quit */
  1852.         } else {
  1853.             spt = spt1 + 1;        /* found '$' but no '<', */
  1854.             continue;        /* look for more */
  1855.         }
  1856.             
  1857.     }
  1858.     }
  1859.     return (s);
  1860. }
  1861. #endif    /* !HAVE_TERMCAP */
  1862.  
  1863.  
  1864. #ifdef SUNTGETENT
  1865. #define TCAPBUFSIZE 1024
  1866. #define SPECIALSIZE 2
  1867.  
  1868. static struct {
  1869.     char    *last;
  1870.     char     str[3];
  1871. }   tcapSpecials[SPECIALSIZE] = {
  1872.     NULL,    "co",
  1873.     NULL,    "li"
  1874. };
  1875.  
  1876. /*
  1877.  * Stomp on the first "co" and "li" entries in the termcap entry
  1878.  * to avoid braindamage in the Sun version of the termcap library.
  1879.  * Apparently the Sun version of tgetent() looks at the terminal
  1880.  * state and uses this to prepend extra line+column spec's that
  1881.  * reflect the terminal's current state.  This is not what we want,
  1882.  * so our only recourse is to undo the this braindamage here.
  1883.  */
  1884. static void
  1885. tc_fix_tcap_ent(buf)
  1886.     char *buf;
  1887. {
  1888.     char *bp = buf;
  1889. #ifndef SYSVREF
  1890.     char *index();
  1891. #else
  1892. #define index(s, c)    (char *)strchr(s, c)
  1893. #endif
  1894.     int   i;
  1895.  
  1896.     /* for each item in buf ... */
  1897.     for (bp = index(bp, ':'); bp && *(bp+1); bp = index(bp, ':')) {
  1898.     ++bp;
  1899.     /* for each special tcap code ... */
  1900.     for (i = 0; i < SPECIALSIZE; i++) {
  1901.         if (strncmp(tcapSpecials[i].str, bp, 2) == 0) {
  1902.         if (tcapSpecials[i].last)
  1903.             strncpy(tcapSpecials[i].last, "xx", 2);
  1904.         tcapSpecials[i].last = bp;
  1905.         break;
  1906.         }
  1907.     }
  1908.     }
  1909. }
  1910. #endif /* SUNTGETENT */
  1911.  
  1912. /*
  1913.  * Matching is performed with a push-down automata implemented
  1914.  * with dual stacks.  An initial stack is loaded with all the
  1915.  * potential matches from the termcap structure.  Matching then
  1916.  * takes place by popping each potential match off the ``current
  1917.  * stack'' and, if a successful match for the current character
  1918.  * occurs, pushing the match on the ``other stack''.  When the
  1919.  * ``current stack'' is empty (all elements have been examined),
  1920.  * the stacks are swapped and the process restarted.  This continues
  1921.  * until a completed match or the stack of potential matches has
  1922.  * been exhausted.
  1923.  */
  1924. static    struct    tcap **curstack, **cursp;    /* ``potential match'' stack */
  1925. static    struct tcap **otherstack, **othersp;    /* ``match this pass'' stack */
  1926. static    struct tcap **resetstack;        /* prototype curstack */
  1927. static    int stacksize;                /* # of potential matches */
  1928. static    int MatchInProgress;            /* for fast check */
  1929.  
  1930. #define    PushMatch(tp)    (*--othersp = tp)
  1931. #define    PopMatch()    (*cursp++)
  1932. #define    PopMatched()    (*othersp++)
  1933. #define    SwapStacks() { \
  1934.     struct tcap **t; \
  1935.     t = curstack, curstack = otherstack, otherstack = t; \
  1936.     cursp = othersp, othersp = otherstack + stacksize; \
  1937.     MatchInProgress = 1; \
  1938. }
  1939. #define    ResetMatchStack() { \
  1940.     bcopy((char *)resetstack, (char *)curstack, \
  1941.         stacksize*sizeof (struct tcap *)); \
  1942.     cursp = curstack; \
  1943.     MatchInProgress = 0; \
  1944. }
  1945. #define    FlushStack(sp, stack) { \
  1946.     while (sp < stack+stacksize) { \
  1947.         tp = *sp++; \
  1948.         tp->t_index = 0; \
  1949.         tp->t_param = 0 ; \
  1950.         tp->t_matched = 0; \
  1951.         tp->t_2nd = 0; \
  1952.     } \
  1953. }
  1954. #define    FlushMatchStack()    FlushStack(cursp, curstack)
  1955. #define    FlushMatchedStack()    FlushStack(othersp, otherstack);
  1956. #define    MatchStackEmpty()    (cursp >= curstack+stacksize)
  1957. #define    MatchedStackEmpty()    (othersp >= otherstack+stacksize)
  1958.  
  1959. /*
  1960.  * Reset the pattern matching stack and load
  1961.  * it with all the potential matching entries.
  1962.  */
  1963. static int
  1964. tc_init_stacks()
  1965. {
  1966.     register struct tcap *tp;
  1967.  
  1968.     for (tp = T; tp < T+Ts; tp++)
  1969.         if (tp->t_text != NULL)
  1970.         stacksize++;
  1971.     curstack = (struct tcap **)malloc((unsigned)
  1972.             (3*sizeof(struct tcap *) * stacksize));
  1973.     if (!curstack)
  1974.         return 1;
  1975.     otherstack = curstack+stacksize;
  1976.     resetstack = otherstack+stacksize;
  1977.     othersp = resetstack+stacksize;
  1978.     for (tp = T; tp < T+Ts; tp++)
  1979.         if (tp->t_text != NULL)
  1980.             PushMatch(tp);
  1981.     othersp = otherstack+stacksize;
  1982.     ResetMatchStack();
  1983.     return 0;
  1984. }
  1985.  
  1986. extern struct tcap interruptedOp;
  1987.  
  1988. /*
  1989.  * Interpret data from the application.  We match data against
  1990.  * the ``escape sequences'' expected for this termcap description
  1991.  * and, if successful, invoke the routines used to emulate the
  1992.  * capabilities on the window.
  1993.  */
  1994. tc_display(cp, n)
  1995.     u_char *cp;
  1996.     register int n;
  1997. {
  1998.     register int c, j;
  1999.     register struct tcap *tp;
  2000.     static char dbuf[256], *dp = dbuf;
  2001.     int restart, lim;
  2002.  
  2003.     /*
  2004.      * If we're blocked with a page full, indicate
  2005.      * nothing was sent to the screen.  We should
  2006.      * never be called when already blocked, but
  2007.      * just in case, turn scrolling on again so we
  2008.      * don't lost any data.
  2009.      */
  2010.     if (PageFull) {
  2011.     if (interruptedOp.t_key == 0)
  2012.         return (n);
  2013.     scrollreset(0);            /* XXX */
  2014.     }    
  2015.     /*
  2016.      * If we have previous output, process it first.
  2017.      * Check on completion to see if we filled the screen.
  2018.      */
  2019.     if (interruptedOp.t_key) {
  2020.     (*interruptedOp.t_op)(&interruptedOp);
  2021.     if (PageFull)
  2022.         return (n);
  2023.     interruptedOp.t_key = 0;
  2024.     }
  2025.     /*
  2026.      * For each input character, look for potential
  2027.      * matches in the tcap structure.  For each possible
  2028.      * match, construct the resultant output buffer.
  2029.      * On first match process the operation (e.g. invoke
  2030.      * internal routine) and flush extraneous matches.
  2031.      * If input doesn't match any capability, send it to
  2032.      * the window.
  2033.      */
  2034.     while (n > 0 && !PageFull) {
  2035.     /*
  2036.      * If we're not in the middle of a match, then
  2037.      * try and bypass the pattern matcher by performing
  2038.      * special checks on the most common input.
  2039.      */
  2040.     if (!MatchInProgress) {
  2041.         while (n > 0 && !PageFull) {
  2042.         /*
  2043.          * If terminal has only non-printing escape sequences,
  2044.          * then process printable characters w/o matching against
  2045.          * the termcap strings.
  2046.          */
  2047.         if (!TerminalIsBraindamaged) {
  2048.             for (dp = (char *)cp; n > 0 && isprint((int)*cp); n--)
  2049.             cp++;
  2050.             if ((char *)cp > dp) {
  2051.             tp = T+Ts;
  2052.             tp->t_text = dp;    /* use original storage */
  2053.             tp->t_size = (char *)cp - dp;
  2054.             (*tp->t_op)(tp);
  2055.             if (PageFull)
  2056.                 return (n);
  2057.             continue;
  2058.             }
  2059.         }
  2060.         /*
  2061.          * Make quick checks for standard NL, CR, BS, and TAB
  2062.          * characters.  This speeds up scrolling for most
  2063.          * terminal types.
  2064.          */
  2065.         c = *cp;
  2066.         if (CheckNL && c == '\n')
  2067.             tp = CheckNL;
  2068.         else if (CheckCR && c == '\r')
  2069.             tp = CheckCR;
  2070.         else if (CheckTAB && c == '\t')
  2071.             tp = CheckTAB;
  2072.         else if (CheckBS && c == '\b')
  2073.             tp = CheckBS;
  2074.         else
  2075.             break;
  2076.         cp++, n--;
  2077.         (*tp->t_op)(tp);
  2078.         if (PageFull)
  2079.             return (n);
  2080.         }
  2081.         dp = dbuf;
  2082.         if (n == 0)
  2083.         break;
  2084.     }
  2085.     c = *dp++ = *cp++, n--;
  2086.     while (!MatchStackEmpty()) {
  2087.         tp = PopMatch();
  2088. again:
  2089.         j = tp->t_index;
  2090.         restart = 0;
  2091.         /*
  2092.          * Check match against numeric %[d23] specification.
  2093.          */
  2094.         if (tp->t_text[j] == '%') {
  2095.         switch (tp->t_text[j+1]) {
  2096.         case 'd':            /* series of decimal digits */
  2097.             lim = 127;
  2098.             goto digit;
  2099.         case '2':            /* two decimal digits */
  2100.             lim = 2;
  2101.             goto digit;
  2102.         case '3':            /* three decimal digits */
  2103.             lim = 3;
  2104.             /* fall thru.. */
  2105.         digit:
  2106.             if (isdigit(c) && tp->t_matched < lim) {
  2107.             tp->t_matched++;
  2108.             tp->t_param = tp->t_param*10 + (c-'0');
  2109.             goto plainmatch;
  2110.             } else {
  2111.             if (tp->t_matched == 0)
  2112.                 tp->t_param = 1 ;
  2113.             tp->t_matched = 0;
  2114.             restart = !isdigit(c);
  2115.             goto gotvalue;
  2116.             }
  2117.             /*NOTREACHED*/
  2118.             break;
  2119.         case '.':            /* binary character */
  2120.             tp->t_param = c;
  2121.         gotvalue:
  2122.             switch (tp->t_2nd + tp->t_pc_r) {
  2123.             case 0:
  2124.             case 2:
  2125.             if ((tp->t_y = tp->t_param) >= tp->t_yilim)
  2126.                 tp->t_y -= tp->t_yi;
  2127.             break;
  2128.             case 1:
  2129.             if ((tp->t_x = tp->t_param) >= tp->t_xilim)
  2130.                 tp->t_x -= tp->t_xi;
  2131.             break;
  2132.             }
  2133.             tp->t_2nd = !tp->t_2nd;
  2134.             tp->t_index += 2;
  2135.             tp->t_param = 0 ;
  2136.             goto plainmatch;
  2137.         case '%':
  2138.             if ((c & 0177) == '%') {
  2139.             tp->t_index += 2;
  2140.             goto plainmatch;
  2141.             } else
  2142.             goto nomatch;
  2143.         default:
  2144.             abort();    /* XXX */
  2145.             /* NOTREACHED */
  2146.         }
  2147.         } else if ((c & 0177) == (tp->t_text[j] & 0177)) {
  2148.         tp->t_index++;
  2149.     plainmatch:                    /* plain match */
  2150.         if (tp->t_index >= tp->t_size) {/* match completed */
  2151.             if (tp->t_op)
  2152.             (*tp->t_op)(tp);
  2153.             dp = dbuf;
  2154.             tp->t_index = 0;
  2155.             tp->t_matched = 0;
  2156.             tp->t_param = 0 ;
  2157.             tp->t_2nd = 0;
  2158.             goto done;
  2159.         }
  2160.         /*
  2161.          * The end of a %d match is the only case where a
  2162.          * character must be pushed-back and re-parsed.
  2163.          */
  2164.         if (restart)
  2165.             goto again;
  2166.         PushMatch(tp);            /* push partial match */
  2167.         } else {
  2168.     nomatch:                    /* failed match */
  2169.         tp->t_index = 0;
  2170.         tp->t_param = 0 ;
  2171.         tp->t_matched = 0;
  2172.         tp->t_2nd = 0;
  2173.         }
  2174.     }
  2175.     if (!MatchedStackEmpty()) {
  2176.         SwapStacks();
  2177.         continue;
  2178.     }
  2179. done:
  2180.     /*
  2181.      * Come here either because no partial matches were
  2182.      * found in the table, or because a match completed.
  2183.      * In the first case we send the input data off
  2184.      * immediately.  In the second case we reset the
  2185.      * state machines and go on to the next character.  
  2186.      */
  2187.     if (dp - dbuf) {            /* flush output */
  2188.         tp = T+Ts;
  2189.         tp->t_text = dbuf;
  2190.         tp->t_size = dp - dbuf;
  2191.         (*tp->t_op)(tp);
  2192.         dp = dbuf;
  2193.     }
  2194.     FlushMatchedStack();            /* reset partial matches */
  2195.     FlushMatchStack();            /* reset unchecked partials */
  2196.     ResetMatchStack();            /* re-init match stack */
  2197.     }
  2198.     return (n);                /* return number of chars processed */
  2199. }
  2200. @@@ Fin de tcap_parse.c
  2201. echo termcap.h
  2202. cat >termcap.h <<'@@@ Fin de termcap.h'
  2203. /*
  2204.  * This file is a product of Sun Microsystems, Inc. and is provided for
  2205.  * unrestricted use provided that this legend is included on all tape
  2206.  * media and as a part of the software program in whole or part.
  2207.  * Users may copy, modify or distribute this file at will.
  2208.  * 
  2209.  * THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  2210.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  2211.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  2212.  * 
  2213.  * This file is provided with no support and without any obligation on the
  2214.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  2215.  * modification or enhancement.
  2216.  * 
  2217.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  2218.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
  2219.  * OR ANY PART THEREOF.
  2220.  * 
  2221.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  2222.  * or profits or other special, indirect and consequential damages, even
  2223.  * if Sun has been advised of the possibility of such damages.
  2224.  * 
  2225.  * Sun Microsystems, Inc.
  2226.  * 2550 Garcia Avenue
  2227.  * Mountain View, California  94043
  2228.  *
  2229.  * Modifications to the original Sun Microsystems, Inc. source code
  2230.  * made by the Grasshopper Group are in the Public Domain.
  2231.  *
  2232.  * Extensions to this file by Eric Messick of the Grasshopper Group.
  2233.  *
  2234.  * Grasshopper Group
  2235.  * 212 Clayton St
  2236.  * San Francisco, CA 94117
  2237.  *
  2238.  */
  2239. /*
  2240.  * "@(#)termcap.h 9.4 88/01/19 SMI
  2241.  * "@(#)$Header: termcap.h,v 2.0 88/09/16 00:19:39 eric Release $
  2242.  *
  2243.  * Copyright (c) 1985 by Sun Microsystems, Inc.
  2244.  */
  2245.  
  2246.  
  2247.  
  2248. enum tct { string, num, bool};
  2249.  
  2250. struct tcap {
  2251.     char *    t_key;        /* Capability name */
  2252.     enum tct    t_type;        /* Capability type */
  2253.     int        (*t_op)(/* struct tcap * */);
  2254.     int        (*t_in)(/* struct tcap * */);
  2255.     char *    t_text;        /* Capability text */
  2256.     char *    t_deftext;    /* Default text */
  2257.     u_short    t_size;        /* Length of t_text */
  2258.     u_short    t_index;    /* Posn. in t_text */
  2259.     int        t_param;    /* parameter value for %match */
  2260.     u_short    t_matched;    /* Length of matched string */
  2261.     u_short    t_x;        /* Coordinate for cm= etc. */
  2262.     u_short    t_xi;        /* Offset to subtract from t_x */
  2263.     u_short    t_xilim;    /* If t_x >= t_xilim subtract t_xi */
  2264.     u_short    t_y;
  2265.     u_short    t_yi;
  2266.     u_short    t_yilim;
  2267.     unsigned    t_pc_r    : 1;    /* %r present */
  2268.     unsigned    t_pc_n    : 1;    /* %n present */
  2269.     unsigned    t_pc_B    : 1;    /* %B present */
  2270.     unsigned    t_pc_D    : 1;    /* %D present */
  2271.     unsigned    t_2nd    : 1;    /* On second coord */
  2272. };
  2273. @@@ Fin de termcap.h
  2274. exit 0
  2275.  
  2276.