home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume26 / screen-3.5 / part06 / ansi.c next >
Encoding:
C/C++ Source or Header  |  1993-07-25  |  39.1 KB  |  2,003 lines

  1. /* Copyright (c) 1993
  2.  *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  3.  *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  4.  * Copyright (c) 1987 Oliver Laumann
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2, or (at your option)
  9.  * any later version.
  10.  *  
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program (see the file COPYING); if not, write to the
  18.  * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  ****************************************************************
  21.  */
  22.  
  23. #include "rcs.h"
  24. RCS_ID("$Id: ansi.c,v 1.12 1993/07/21 15:42:44 mlschroe Exp $ FAU")
  25.  
  26. #include <stdio.h>
  27. #include <sys/types.h>
  28. #include <fcntl.h>
  29. #ifndef sun    /* we want to know about TIOCPKT. */
  30. # include <sys/ioctl.h>
  31. #endif
  32. #include "config.h"
  33. #include "screen.h"
  34. #include "extern.h"
  35.  
  36. extern char *getenv(), *tgetstr(), *tgoto();
  37. #ifndef __STDC__
  38. extern char *malloc();
  39. #endif
  40.  
  41. extern struct win *windows;    /* linked list of all windows */
  42. extern struct win *fore;
  43. extern struct display *display, *displays;
  44.  
  45. extern int  force_vt;
  46. extern int  all_norefresh;    /* => display */
  47. extern char Esc, MetaEsc;    /* => display */
  48. extern time_t Now;
  49.  
  50. int maxwidth;            /* maximum of all widths so far */
  51.  
  52. int Z0width, Z1width;        /* widths for Z0/Z1 switching */
  53.  
  54. static struct win *curr;    /* window we are working on */
  55. static int rows, cols;        /* window size of the curr window */
  56.  
  57. int default_wrap = 1;        /* default: wrap on */
  58. int default_monitor = 0; 
  59.  
  60. int visual_bell = 0;
  61. int use_hardstatus = 1;
  62.  
  63. char *blank;            /* line filled with spaces */
  64. char *null;            /* line filled with '\0' */
  65. char *OldImage, *OldAttr, *OldFont;    /* temporary buffers */
  66.  
  67. static void WinProcess __P((char **, int *));
  68. static void WinRedisplayLine __P((int, int, int, int));
  69. static void WinClearLine __P((int, int, int));
  70. static int  WinRewrite __P((int, int, int, int));
  71. static void WinSetCursor __P((void));
  72. static int  WinResize __P((int, int));
  73. static void WinRestore __P((void));
  74. static int  Special __P((int));
  75. static void DoESC __P((int, int ));
  76. static void DoCSI __P((int, int ));
  77. static void SetChar __P((int));
  78. static void StartString __P((enum string_t));
  79. static void SaveChar __P((int ));
  80. static void PrintChar __P((int ));
  81. static void PrintFlush __P((void));
  82. static void DesignateCharset __P((int, int ));
  83. static void MapCharset __P((int));
  84. static void SaveCursor __P((void));
  85. static void RestoreCursor __P((void));
  86. static void BackSpace __P((void));
  87. static void Return __P((void));
  88. static void LineFeed __P((int));
  89. static void ReverseLineFeed __P((void));
  90. static void InsertAChar __P((int));
  91. static void InsertChar __P((int));
  92. static void DeleteChar __P((int));
  93. static void DeleteLine __P((int));
  94. static void InsertLine __P((int));
  95. static void ScrollUpMap __P((int));
  96. static void ScrollDownMap __P((int));
  97. static void Scroll __P((char *, int, int, char *));
  98. static void ForwardTab __P((void));
  99. static void BackwardTab __P((void));
  100. static void ClearScreen __P((void));
  101. static void ClearFromBOS __P((void));
  102. static void ClearToEOS __P((void));
  103. static void ClearFullLine __P((void));
  104. static void ClearToEOL __P((void));
  105. static void ClearFromBOL __P((void));
  106. static void ClearInLine __P((int, int, int));
  107. static void CursorRight __P((int));
  108. static void CursorUp __P((int));
  109. static void CursorDown __P((int));
  110. static void CursorLeft __P((int));
  111. static void ASetMode __P((int));
  112. static void SelectRendition __P((void));
  113. static void RestorePosAttrFont __P((void));
  114. static void FillWithEs __P((void));
  115. static void UpdateLine __P((char *, char *, char *, int, int, int ));
  116. static void FindAKA __P((void));
  117. static void Report __P((char *, int, int));
  118.  
  119.  
  120. /*
  121.  *  The window layer functions
  122.  */
  123.  
  124. struct LayFuncs WinLf =
  125. {
  126.   WinProcess,
  127.   0,
  128.   WinRedisplayLine,
  129.   WinClearLine,
  130.   WinRewrite,
  131.   WinSetCursor,
  132.   WinResize,
  133.   WinRestore
  134. };
  135.  
  136. static void
  137. WinProcess(bufpp, lenp)
  138. char **bufpp;
  139. int *lenp;
  140. {
  141.   int f, *ilen, l = *lenp;
  142.   char *ibuf;
  143.   
  144.   fore = d_fore;
  145. #ifdef MULTIUSER
  146.   /* if w_wlock is set, only one user may write, else we check acls */
  147.   if ((fore->w_wlock == WLOCK_OFF) ? 
  148.       AclCheckPermWin(d_user, ACL_WRITE, fore) :
  149.       (d_user != fore->w_wlockuser))
  150.     {
  151.       SetCurr(fore);
  152.       Special('\007');
  153.       *bufpp += *lenp;
  154.       *lenp = 0;
  155.       return;
  156.     }
  157. #endif /* MULTIUSER */
  158. #ifdef PSEUDOS
  159.   if (W_UWP(fore))
  160.     {
  161.       /* we send the user input to our pseudowin */
  162.       ibuf = fore->w_pwin->p_inbuf; ilen = &fore->w_pwin->p_inlen;
  163.       f = sizeof(fore->w_pwin->p_inbuf) - *ilen;
  164.     }
  165.   else
  166. #endif /* PSEUDOS */
  167.     {
  168.       /* we send the user input to the window */
  169.       ibuf = fore->w_inbuf; ilen = &fore->w_inlen;
  170.       f = sizeof(fore->w_inbuf) - *ilen;
  171.     }
  172.   if (l > f)
  173.     {
  174.       debug1("Yuck! pty buffer full (%d chars missing). lets beep\n", l - f);
  175.       SetCurr(fore);
  176.       Special('\007');
  177.       l = f;
  178.     }
  179.   if (l > 0)
  180.     {
  181.       bcopy(*bufpp, ibuf + *ilen, l);
  182.       *ilen += l;
  183.     }
  184.   *bufpp += *lenp;
  185.   *lenp = 0;
  186. }
  187.  
  188. static void
  189. WinRedisplayLine(y, from, to, isblank)
  190. int y, from, to, isblank;
  191. {
  192.   if (y < 0)
  193.     return;
  194.   fore = d_fore;
  195.   DisplayLine(isblank ? blank: null, null, null, fore->w_image[y],
  196.               fore->w_attr[y], fore->w_font[y], y, from, to);
  197. }
  198.  
  199. static int
  200. WinRewrite(y, x1, x2, doit)
  201. int y, x1, x2, doit;
  202. {
  203.   register int cost, dx;
  204.   register char *p, *f, *i;
  205.  
  206.   fore = d_fore;
  207.   dx = x2 - x1;
  208.   if (doit)
  209.     {
  210.       i = fore->w_image[y] + x1;
  211.       while (dx-- > 0)
  212.     PUTCHAR(*i++);
  213.       return(0);
  214.     }
  215.   p = fore->w_attr[y] + x1;
  216.   f = fore->w_font[y] + x1;
  217.  
  218.   cost = dx = x2 - x1;
  219.   if (d_insert)
  220.     cost += d_EIcost + d_IMcost;
  221.   while(dx-- > 0)
  222.     {
  223.       if (*p++ != d_attr || *f++ != d_font)
  224.     return EXPENSIVE;
  225.     }
  226.   return cost;
  227. }
  228.  
  229. static void
  230. WinClearLine(y, xs, xe)
  231. int y, xs, xe;
  232. {
  233.   fore = d_fore;
  234.   DisplayLine(fore->w_image[y], fore->w_attr[y], fore->w_font[y],
  235.           blank, null, null, y, xs, xe);
  236. }
  237.  
  238. static void
  239. WinSetCursor()
  240. {
  241.   fore = d_fore;
  242.   GotoPos(fore->w_x, fore->w_y);
  243. }
  244.  
  245. static int
  246. WinResize(wi, he)
  247. int wi, he;
  248. {
  249.   fore = d_fore;
  250.   if (fore)
  251.     ChangeWindowSize(fore, wi, he);
  252.   return 0;
  253. }
  254.  
  255. static void
  256. WinRestore()
  257. {
  258.   fore = d_fore;
  259.   ChangeScrollRegion(fore->w_top, fore->w_bot);
  260.   KeypadMode(fore->w_keypad);
  261.   CursorkeysMode(fore->w_cursorkeys);
  262.   SetFlow(fore->w_flow & FLOW_NOW);
  263.   InsertMode(fore->w_insert);
  264.   fore->w_active = 1;
  265. }
  266.  
  267. /* 
  268.  *  Activate - make fore window active
  269.  *  norefresh = -1 forces a refresh, disregard all_norefresh then.
  270.  */
  271. void
  272. Activate(norefresh)
  273. int norefresh;
  274. {
  275.   debug1("Activate(%d)\n", norefresh);
  276.   if (display == 0)
  277.     return;
  278.   RemoveStatus();
  279.   fore = d_fore;
  280.   if (fore)
  281.     {
  282.       ASSERT(fore->w_display == display);
  283.       fore->w_active = d_layfn == &WinLf;
  284.       if (fore->w_monitor != MON_OFF)
  285.     fore->w_monitor = MON_ON;
  286.       fore->w_bell = BELL_OFF;
  287.       if (ResizeDisplay(fore->w_width, fore->w_height))
  288.     {
  289.       debug2("Cannot resize from (%d,%d)", d_width, d_height);
  290.       debug2(" to (%d,%d) -> resize window\n", fore->w_width, fore->w_height);
  291.       DoResize(d_width, d_height);
  292.     }
  293.     }
  294.   Redisplay(norefresh + all_norefresh);
  295. }
  296.  
  297. void
  298. ResetWindow(p)
  299. register struct win *p;
  300. {
  301.   register int i;
  302.  
  303.   p->w_wrap = default_wrap;
  304.   p->w_origin = 0;
  305.   p->w_insert = 0;
  306.   p->w_vbwait = 0;
  307.   p->w_keypad = 0;
  308.   p->w_cursorkeys = 0;
  309.   p->w_top = 0;
  310.   p->w_bot = p->w_height - 1;
  311.   p->w_saved = 0;
  312.   p->w_Attr = 0;
  313.   p->w_Font = 0;
  314.   p->w_x = p->w_y = 0;
  315.   p->w_state = LIT;
  316.   p->w_StringType = NONE;
  317.   p->w_ss = 0;
  318.   p->w_Charset = G0;
  319.   bzero(p->w_tabs, p->w_width);
  320.   for (i = 8; i < p->w_width; i += 8)
  321.     p->w_tabs[i] = 1;
  322.   for (i = G0; i <= G3; i++)
  323.     p->w_charsets[i] = ASCII;
  324. }
  325.  
  326.  
  327. /*
  328.  *  Here comes the vt100 emulator
  329.  */
  330. void
  331. WriteString(wp, buf, len)
  332. struct win *wp;
  333. register char *buf;
  334. register int len;
  335. {
  336.   register int c;
  337.  
  338.   if (!len)
  339.     return;
  340.   if (wp->w_logfp != NULL)
  341.     if ((int)fwrite(buf, len, 1, wp->w_logfp) < 1)
  342.       {
  343.     Msg(errno, "Error writing logfile");
  344.     fclose(wp->w_logfp);
  345.     wp->w_logfp = NULL;
  346.       }
  347.   /*
  348.    * SetCurr() here may prevent output, as it may set display = 0
  349.    */
  350.   SetCurr(wp);
  351.   if (display)
  352.     {
  353.       if (d_status && !(use_hardstatus && HS))
  354.     RemoveStatus();
  355.     }
  356.   else
  357.     {
  358.       if (curr->w_tstamp.seconds)
  359.         curr->w_tstamp.lastio = Now;
  360.  
  361.       if (curr->w_monitor == MON_ON || curr->w_monitor == MON_DONE)
  362.     {
  363.           debug2("ACTIVITY %d %d\n", curr->w_monitor, curr->w_bell);
  364.           curr->w_monitor = MON_FOUND;
  365.     }
  366.     }
  367.   do
  368.     {
  369.       if (curr->w_Attr && curr->w_attr[curr->w_y] == null)
  370.     {
  371.       if ((curr->w_attr[curr->w_y] = (char *)malloc(curr->w_width + 1)) == 0)
  372.         {
  373.           curr->w_attr[curr->w_y] = null;
  374.           curr->w_Attr = 0;
  375.           Msg(0, "Warning: no space for attr - turned off");
  376.         }
  377.       else
  378.         bzero(curr->w_attr[curr->w_y], curr->w_width + 1);
  379.     }
  380.       if (curr->w_Font && curr->w_font[curr->w_y] == null)
  381.     {
  382.       if ((curr->w_font[curr->w_y] = (char *)malloc(curr->w_width + 1)) == 0)
  383.         {
  384.           curr->w_font[curr->w_y] = null;
  385.               curr->w_Font = curr->w_charsets[curr->w_ss ? curr->w_ss : curr->w_Charset] = 0;
  386.           Msg(0, "Warning: no space for font - turned off");
  387.         }
  388.       else
  389.         bzero(curr->w_font[curr->w_y], curr->w_width + 1);
  390.     }
  391.  
  392.       c = (unsigned char)*buf++;
  393.       if (c == '\177')
  394.     continue;
  395.  
  396.       /* The next part is only for speedup */
  397.       if (curr->w_state == LIT &&
  398.           c >= ' ' && ((c & 0x80) == 0 || display == 0 || !CB8) &&
  399.           !curr->w_insert && !curr->w_ss)
  400.     {
  401.       register int currx;
  402.       register char *imp, *atp, *fop, at, fo;
  403.  
  404.       currx = curr->w_x;
  405.       imp = curr->w_image[curr->w_y] + currx;
  406.       atp = curr->w_attr[curr->w_y] + currx;
  407.       fop = curr->w_font[curr->w_y] + currx;
  408.       at = curr->w_Attr;
  409.       fo = curr->w_Font;
  410.       if (display)
  411.         {
  412.           if (d_x != currx || d_y != curr->w_y)
  413.         GotoPos(currx, curr->w_y);
  414.           if (at != d_attr)
  415.         SetAttr(at);
  416.           if (fo != d_font)
  417.         SetFont(fo);
  418.           if (d_insert)
  419.         InsertMode(0);
  420.         }
  421.       while (currx < cols - 1)
  422.         {
  423.           if (display)
  424.         AddChar(d_font != '0' ? c : d_c0_tab[c]);
  425.           *imp++ = c;
  426.           *atp++ = at;
  427.           *fop++ = fo;
  428.           currx++;
  429. skip:          if (--len == 0)
  430.         break;
  431.               c = (unsigned char)*buf++;
  432.           if (c == '\177')
  433.         goto skip;
  434.           if (c < ' ' || ((c & 0x80) && display && CB8))
  435.         break;
  436.         }
  437.       curr->w_x = currx;
  438.       if (display)
  439.         d_x = currx;
  440.       if (len == 0)
  441.         break;
  442.     }
  443.       /* end of speedup code */
  444.  
  445.       if ((c & 0x80) && display && CB8)
  446.     {
  447.       FILE *logfp = wp->w_logfp;
  448.       char *cb8 = CB8;
  449.     
  450.       wp->w_logfp = NULL;    /* a little hack */
  451.       CB8 = NULL;        /* dito */
  452.       WriteString(wp, cb8, (int)strlen(cb8));
  453.       wp->w_logfp = logfp;
  454.       CB8 = cb8;
  455.       c &= 0x7f;
  456.     }
  457.     tryagain:
  458.       switch (curr->w_state)
  459.     {
  460.     case PRIN:
  461.       switch (c)
  462.         {
  463.         case '\033':
  464.           curr->w_state = PRINESC;
  465.           break;
  466.         default:
  467.           PrintChar(c);
  468.         }
  469.       break;
  470.     case PRINESC:
  471.       switch (c)
  472.         {
  473.         case '[':
  474.           curr->w_state = PRINCSI;
  475.           break;
  476.         default:
  477.           PrintChar('\033');
  478.           PrintChar(c);
  479.           curr->w_state = PRIN;
  480.         }
  481.       break;
  482.     case PRINCSI:
  483.       switch (c)
  484.         {
  485.         case '4':
  486.           curr->w_state = PRIN4;
  487.           break;
  488.         default:
  489.           PrintChar('\033');
  490.           PrintChar('[');
  491.           PrintChar(c);
  492.           curr->w_state = PRIN;
  493.         }
  494.       break;
  495.     case PRIN4:
  496.       switch (c)
  497.         {
  498.         case 'i':
  499.           curr->w_state = LIT;
  500.           PrintFlush();
  501.           break;
  502.         default:
  503.           PrintChar('\033');
  504.           PrintChar('[');
  505.           PrintChar('4');
  506.           PrintChar(c);
  507.           curr->w_state = PRIN;
  508.         }
  509.       break;
  510.     case STRESC:
  511.       switch (c)
  512.         {
  513.         case '\\':
  514.           curr->w_state = LIT;
  515.           *(curr->w_stringp) = '\0';
  516.           switch (curr->w_StringType)
  517.         {
  518.         case GM:
  519.             {
  520.               struct display *old = display;
  521.               for (display = displays; display; display = display->_d_next)
  522.             if (display != old)
  523.               MakeStatus(curr->w_string);
  524.               display = old;
  525.             }
  526.           /*FALLTHROUGH*/
  527.         case PM:
  528.           if (!display)
  529.             break;
  530.           MakeStatus(curr->w_string);
  531.           if (d_status && !(use_hardstatus && HS) && len > 1)
  532.             {
  533.               curr->w_outlen = len - 1;
  534.               bcopy(buf, curr->w_outbuf, curr->w_outlen);
  535.               return;
  536.             }
  537.           break;
  538.         case DCS:
  539.           if (display)
  540.             AddStr(curr->w_string);
  541.           break;
  542.         case AKA:
  543.           if (curr->w_aka == curr->w_akabuf && !*curr->w_string)
  544.             break;
  545.           ChangeAKA(curr, curr->w_string, 20);
  546.           if (!*curr->w_string)
  547.             curr->w_autoaka = curr->w_y + 1;
  548.           break;
  549.         default:
  550.           break;
  551.         }
  552.           break;
  553.         default:
  554.           curr->w_state = ASTR;
  555.           SaveChar('\033');
  556.           SaveChar(c);
  557.         }
  558.       break;
  559.     case ASTR:
  560.       switch (c)
  561.         {
  562.         case '\0':
  563.           break;
  564.         case '\033':
  565.           curr->w_state = STRESC;
  566.           break;
  567.         default:
  568.           SaveChar(c);
  569.         }
  570.       break;
  571.     case ESC:
  572.       switch (c)
  573.         {
  574.         case '[':
  575.           curr->w_NumArgs = 0;
  576.           curr->w_intermediate = 0;
  577.           bzero((char *) curr->w_args, MAXARGS * sizeof(int));
  578.           curr->w_state = CSI;
  579.           break;
  580.         case ']':
  581.           StartString(OSC);
  582.           break;
  583.         case '_':
  584.           StartString(APC);
  585.           break;
  586.         case 'P':
  587.           StartString(DCS);
  588.           break;
  589.         case '^':
  590.           StartString(PM);
  591.           break;
  592.         case '!':
  593.           StartString(GM);
  594.           break;
  595.         case '"':
  596.         case 'k':
  597.           StartString(AKA);
  598.           break;
  599.         default:
  600.           if (Special(c))
  601.         break;
  602.           debug1("not special. c = %x\n", c);
  603.           if (c >= ' ' && c <= '/')
  604.         curr->w_intermediate = curr->w_intermediate ? -1 : c;
  605.           else if (c >= '0' && c <= '~')
  606.         {
  607.           DoESC(c, curr->w_intermediate);
  608.           curr->w_state = LIT;
  609.         }
  610.           else
  611.         {
  612.           curr->w_state = LIT;
  613.           goto tryagain;
  614.         }
  615.         }
  616.       break;
  617.     case CSI:
  618.       switch (c)
  619.         {
  620.         case '0':
  621.         case '1':
  622.         case '2':
  623.         case '3':
  624.         case '4':
  625.         case '5':
  626.         case '6':
  627.         case '7':
  628.         case '8':
  629.         case '9':
  630.           if (curr->w_NumArgs < MAXARGS)
  631.         {
  632.           curr->w_args[curr->w_NumArgs] =
  633.             10 * curr->w_args[curr->w_NumArgs] + c - '0';
  634.         }
  635.           break;
  636.         case ';':
  637.         case ':':
  638.           curr->w_NumArgs++;
  639.           break;
  640.         default:
  641.           if (Special(c))
  642.         break;
  643.           if (c >= '@' && c <= '~')
  644.         {
  645.           curr->w_NumArgs++;
  646.           DoCSI(c, curr->w_intermediate);
  647.           if (curr->w_state != PRIN)
  648.             curr->w_state = LIT;
  649.         }
  650.           else if ((c >= ' ' && c <= '/') || (c >= '<' && c <= '?'))
  651.         curr->w_intermediate = curr->w_intermediate ? -1 : c;
  652.           else
  653.         {
  654.           curr->w_state = LIT;
  655.           goto tryagain;
  656.         }
  657.         }
  658.       break;
  659.     case LIT:
  660.     default:
  661.       if (c < ' ')
  662.         {
  663.           if (c == '\033')
  664.         {
  665.           curr->w_intermediate = 0;
  666.           curr->w_state = ESC;
  667.           if (display && d_lp_missing && (CIC || IC || IM))
  668.             UpdateLine(blank, null, null, d_bot, cols - 2, cols - 1);
  669.           if (curr->w_autoaka < 0)
  670.             curr->w_autoaka = 0;
  671.         }
  672.           else
  673.         Special(c);
  674.           break;
  675.         }
  676.       if (display)
  677.         {
  678.           if (d_attr != curr->w_Attr)
  679.         SetAttr(curr->w_Attr);
  680.           if (d_font != curr->w_Font)
  681.         SetFont(curr->w_Font);
  682.         }
  683.       if (curr->w_x < cols - 1)
  684.         {
  685.           if (curr->w_insert)
  686.         InsertAChar(c);
  687.           else
  688.         {
  689.           if (display)
  690.             PUTCHAR(c);
  691.           SetChar(c);
  692.           curr->w_x++;
  693.         }
  694.         }
  695.       else if (curr->w_x == cols - 1)
  696.         {
  697.           if (display && curr->w_wrap && (CLP || !force_vt || COP))
  698.         {
  699.           RAW_PUTCHAR(c);    /* don't care about d_insert */
  700.           SetChar(c);
  701.           if (AM && !CLP)
  702.             LineFeed(0);    /* terminal auto-wrapped */
  703.           else
  704.             curr->w_x++;
  705.         }
  706.           else
  707.         {
  708.           if (display)
  709.             {
  710.               if (CLP || curr->w_y != d_bot)
  711.             {
  712.               RAW_PUTCHAR(c);
  713.               GotoPos(curr->w_x, curr->w_y);
  714.             }
  715.               else
  716.             CheckLP(c);
  717.             }
  718.           SetChar(c);
  719.           if (curr->w_wrap)
  720.             curr->w_x++;
  721.         }
  722.         }
  723.       else /* curr->w_x > cols - 1 */
  724.         {
  725.               SetChar(0);        /* we wrapped */
  726.           if (curr->w_insert)
  727.         {
  728.           LineFeed(2);        /* cr+lf, handle LP */
  729.           InsertAChar(c);
  730.         }
  731.           else
  732.         {
  733.           LineFeed(display == 0 || AM ? 0 : 2);
  734.           if (display)
  735.             PUTCHAR(c);
  736.           SetChar(c);
  737.           curr->w_x = 1;
  738.         }
  739.         }
  740.       if (curr->w_ss)
  741.         {
  742.           SetFont(curr->w_Font = curr->w_charsets[curr->w_Charset]);
  743.           curr->w_ss = 0;
  744.         }
  745.       break;
  746.     }
  747.     }
  748.   while (--len);
  749.   curr->w_outlen = 0;
  750.   if (curr->w_state == PRIN)
  751.     PrintFlush();
  752. }
  753.  
  754. static int
  755. Special(c)
  756. register int c;
  757. {
  758.   switch (c)
  759.     {
  760.     case '\b':
  761.       BackSpace();
  762.       return 1;
  763.     case '\r':
  764.       Return();
  765.       return 1;
  766.     case '\n':
  767.       if (curr->w_autoaka)
  768.     FindAKA();
  769.       LineFeed(1);
  770.       return 1;
  771.     case '\007':
  772.       if (display == 0)
  773.     curr->w_bell = BELL_ON;
  774.       else
  775.     {
  776.       if (!visual_bell)
  777.         PutStr(BL);
  778.       else
  779.         {
  780.           if (!VB)
  781.         curr->w_bell = BELL_VISUAL;
  782.           else
  783.         PutStr(VB);
  784.         }
  785.     }
  786.       return 1;
  787.     case '\t':
  788.       ForwardTab();
  789.       return 1;
  790.     case '\017':        /* SI */
  791.       MapCharset(G0);
  792.       return 1;
  793.     case '\016':        /* SO */
  794.       MapCharset(G1);
  795.       return 1;
  796.     }
  797.   return 0;
  798. }
  799.  
  800. static void
  801. DoESC(c, intermediate)
  802. int c, intermediate;
  803. {
  804.   debug2("DoESC: %x - inter = %x\n", c, intermediate);
  805.   switch (intermediate)
  806.     {
  807.     case 0:
  808.       switch (c)
  809.     {
  810.     case 'E':
  811.       LineFeed(2);
  812.       break;
  813.     case 'D':
  814.       LineFeed(1);
  815.       break;
  816.     case 'M':
  817.       ReverseLineFeed();
  818.       break;
  819.     case 'H':
  820.       curr->w_tabs[curr->w_x] = 1;
  821.       break;
  822.     case 'Z':        /* jph: Identify as VT100 */
  823.       Report("\033[?%d;%dc", 1, 2);
  824.       break;
  825.     case '7':
  826.       SaveCursor();
  827.       break;
  828.     case '8':
  829.       RestoreCursor();
  830.       break;
  831.     case 'c':
  832.       ClearScreen();
  833.       ResetWindow(curr);
  834.       SetAttrFont(0, ASCII);
  835.       InsertMode(0);
  836.       KeypadMode(0);
  837.       CursorkeysMode(0);
  838.       ChangeScrollRegion(0, rows - 1);
  839.       break;
  840.     case '=':
  841.       KeypadMode(curr->w_keypad = 1);
  842. #ifndef TIOCPKT
  843.       NewAutoFlow(curr, 0);
  844. #endif /* !TIOCPKT */
  845.       break;
  846.     case '>':
  847.       KeypadMode(curr->w_keypad = 0);
  848. #ifndef TIOCPKT
  849.       NewAutoFlow(curr, 1);
  850. #endif /* !TIOCPKT */
  851.       break;
  852.     case 'n':        /* LS2 */
  853.       MapCharset(G2);
  854.       break;
  855.     case 'o':        /* LS3 */
  856.       MapCharset(G3);
  857.       break;
  858.     case 'N':        /* SS2 */
  859.       if (curr->w_charsets[curr->w_Charset] != curr->w_charsets[G2])
  860.         curr->w_Font = curr->w_charsets[curr->w_ss = G2];
  861.       else
  862.         curr->w_ss = 0;
  863.       break;
  864.     case 'O':        /* SS3 */
  865.       if (curr->w_charsets[curr->w_Charset] != curr->w_charsets[G3])
  866.         curr->w_Font = curr->w_charsets[curr->w_ss = G3];
  867.       else
  868.         curr->w_ss = 0;
  869.       break;
  870.     }
  871.       break;
  872.     case '#':
  873.       switch (c)
  874.     {
  875.     case '8':
  876.       FillWithEs();
  877.       break;
  878.     }
  879.       break;
  880.     case '(':
  881.       DesignateCharset(c, G0);
  882.       break;
  883.     case ')':
  884.       DesignateCharset(c, G1);
  885.       break;
  886.     case '*':
  887.       DesignateCharset(c, G2);
  888.       break;
  889.     case '+':
  890.       DesignateCharset(c, G3);
  891.       break;
  892.     }
  893. }
  894.  
  895. static void
  896. DoCSI(c, intermediate)
  897. int c, intermediate;
  898. {
  899.   register int i, a1 = curr->w_args[0], a2 = curr->w_args[1];
  900.  
  901.   if (curr->w_NumArgs > MAXARGS)
  902.     curr->w_NumArgs = MAXARGS;
  903.   switch (intermediate)
  904.     {
  905.     case 0:
  906.       switch (c)
  907.     {
  908.     case 'H':
  909.     case 'f':
  910.       if (a1 < 1)
  911.         a1 = 1;
  912.       if (curr->w_origin)
  913.         a1 += curr->w_top;
  914.       if (a1 > rows)
  915.         a1 = rows;
  916.       if (a2 < 1)
  917.         a2 = 1;
  918.       if (a2 > cols)
  919.         a2 = cols;
  920.       GotoPos(--a2, --a1);
  921.       curr->w_x = a2;
  922.       curr->w_y = a1;
  923.       if (curr->w_autoaka)
  924.         curr->w_autoaka = a1 + 1;
  925.       break;
  926.     case 'J':
  927.       if (a1 < 0 || a1 > 2)
  928.         a1 = 0;
  929.       switch (a1)
  930.         {
  931.         case 0:
  932.           ClearToEOS();
  933.           break;
  934.         case 1:
  935.           ClearFromBOS();
  936.           break;
  937.         case 2:
  938.           ClearScreen();
  939.           GotoPos(curr->w_x, curr->w_y);
  940.           break;
  941.         }
  942.       break;
  943.     case 'K':
  944.       if (a1 < 0 || a1 > 2)
  945.         a1 %= 3;
  946.       switch (a1)
  947.         {
  948.         case 0:
  949.           ClearToEOL();
  950.           break;
  951.         case 1:
  952.           ClearFromBOL();
  953.           break;
  954.         case 2:
  955.           ClearFullLine();
  956.           break;
  957.         }
  958.       break;
  959.     case 'A':
  960.       CursorUp(a1 ? a1 : 1);
  961.       break;
  962.     case 'B':
  963.       CursorDown(a1 ? a1 : 1);
  964.       break;
  965.     case 'C':
  966.       CursorRight(a1 ? a1 : 1);
  967.       break;
  968.     case 'D':
  969.       CursorLeft(a1 ? a1 : 1);
  970.       break;
  971.     case 'm':
  972.       SelectRendition();
  973.       break;
  974.     case 'g':
  975.       if (a1 == 0)
  976.         curr->w_tabs[curr->w_x] = 0;
  977.       else if (a1 == 3)
  978.         bzero(curr->w_tabs, cols);
  979.       break;
  980.     case 'r':
  981.       if (!a1)
  982.         a1 = 1;
  983.       if (!a2)
  984.         a2 = rows;
  985.       if (a1 < 1 || a2 > rows || a1 >= a2)
  986.         break;
  987.       curr->w_top = a1 - 1;
  988.       curr->w_bot = a2 - 1;
  989.       ChangeScrollRegion(curr->w_top, curr->w_bot);
  990.       if (curr->w_origin)
  991.         {
  992.           GotoPos(0, curr->w_top);
  993.           curr->w_y = curr->w_top;
  994.           curr->w_x = 0;
  995.         }
  996.       else
  997.         {
  998.           GotoPos(0, 0);
  999.           curr->w_y = curr->w_x = 0;
  1000.         }
  1001.       break;
  1002.     case 's':
  1003.       SaveCursor();
  1004.       break;
  1005.     case 't':
  1006.       if (a1 != 8)
  1007.         break;
  1008.       a1 = curr->w_args[2];
  1009.       if (a1 < 1)
  1010.         a1 = curr->w_width;
  1011.       if (a2 < 1)
  1012.         a2 = curr->w_height;
  1013.       if (display && CWS == NULL)
  1014.         {
  1015.           a2 = curr->w_height;
  1016.           if (CZ0 == NULL || (a1 != Z0width && a1 != Z1width))
  1017.             a1 = curr->w_width;
  1018.          }
  1019.       if (a1 == curr->w_width && a2 == curr->w_height)
  1020.         break;
  1021.           ChangeWindowSize(curr, a1, a2);
  1022.       SetCurr(curr);
  1023.       if (display)
  1024.         Activate(0);
  1025.       break;
  1026.     case 'u':
  1027.       RestoreCursor();
  1028.       break;
  1029.     case 'I':
  1030.       if (!a1)
  1031.         a1 = 1;
  1032.       while (a1--)
  1033.         ForwardTab();
  1034.       break;
  1035.     case 'Z':
  1036.       if (!a1)
  1037.         a1 = 1;
  1038.       while (a1--)
  1039.         BackwardTab();
  1040.       break;
  1041.     case 'L':
  1042.       InsertLine(a1 ? a1 : 1);
  1043.       break;
  1044.     case 'M':
  1045.       DeleteLine(a1 ? a1 : 1);
  1046.       break;
  1047.     case 'P':
  1048.       DeleteChar(a1 ? a1 : 1);
  1049.       break;
  1050.     case '@':
  1051.       InsertChar(a1 ? a1 : 1);
  1052.       break;
  1053.     case 'h':
  1054.       ASetMode(1);
  1055.       break;
  1056.     case 'l':
  1057.       ASetMode(0);
  1058.       break;
  1059.     case 'i':
  1060.       if (display && PO && a1 == 5)
  1061.         {
  1062.           curr->w_stringp = curr->w_string;
  1063.           curr->w_state = PRIN;
  1064.         }
  1065.       break;
  1066.     case 'n':
  1067.       if (a1 == 6)        /* Report cursor position */
  1068.         Report("\033[%d;%dR", curr->w_y + 1, curr->w_x + 1);
  1069.       break;
  1070.     case 'c':        /* Identify as VT100 */
  1071.       Report("\033[?%d;%dc", 1, 2);
  1072.       break;
  1073.     }
  1074.       break;
  1075.     case '?':
  1076.       debug2("\\E[?%d%c\n",a1,c);
  1077.       if (c != 'h' && c != 'l')
  1078.     break;
  1079.       i = (c == 'h');
  1080.       switch (a1)
  1081.     {
  1082.     case 1:
  1083.       CursorkeysMode(curr->w_cursorkeys = i);
  1084. #ifndef TIOCPKT
  1085.       NewAutoFlow(curr, !i);
  1086. #endif /* !TIOCPKT */
  1087.       break;
  1088.     case 3:
  1089.       i = (i ? Z0width : Z1width);
  1090.       if (curr->w_width != i && (display == 0 || (CZ0 || CWS)))
  1091.         {
  1092.               ChangeWindowSize(curr, i, curr->w_height);
  1093.           SetCurr(curr);    /* update rows/cols */
  1094.           if (display)
  1095.         Activate(0);
  1096.         }
  1097.       break;
  1098.     case 5:
  1099.       if (i)
  1100.         curr->w_vbwait = 1;
  1101.       else
  1102.         {
  1103.           if (display && curr->w_vbwait)
  1104.         PutStr(VB);
  1105.           curr->w_vbwait = 0;
  1106.         }
  1107.       break;
  1108.     case 6:
  1109.       if ((curr->w_origin = i) != 0)
  1110.         {
  1111.           curr->w_y = curr->w_top;
  1112.           curr->w_x = 0;
  1113.         }
  1114.       else
  1115.         curr->w_y = curr->w_x = 0;
  1116.       if (display)
  1117.         GotoPos(curr->w_x, curr->w_y);
  1118.       break;
  1119.     case 7:
  1120.       curr->w_wrap = i;
  1121.       break;
  1122.     case 35:
  1123.       debug1("Cursor %svisible\n", i ? "in" : "");
  1124.       curr->w_cursor_invisible = i;
  1125.       break;
  1126.     }
  1127.       break;
  1128.     }
  1129. }
  1130.  
  1131.  
  1132. static void
  1133. SetChar(c)
  1134. register int c;
  1135. {
  1136.   register struct win *p = curr;
  1137.  
  1138.   p->w_image[p->w_y][p->w_x] = c;
  1139.   p->w_attr[p->w_y][p->w_x] = p->w_Attr;
  1140.   p->w_font[p->w_y][p->w_x] = p->w_Font;
  1141. }
  1142.  
  1143. static void
  1144. StartString(type)
  1145. enum string_t type;
  1146. {
  1147.   curr->w_StringType = type;
  1148.   curr->w_stringp = curr->w_string;
  1149.   curr->w_state = ASTR;
  1150. }
  1151.  
  1152. static void
  1153. SaveChar(c)
  1154. int c;
  1155. {
  1156.   if (curr->w_stringp >= curr->w_string + MAXSTR - 1)
  1157.     curr->w_state = LIT;
  1158.   else
  1159.     *(curr->w_stringp)++ = c;
  1160. }
  1161.  
  1162. static void
  1163. PrintChar(c)
  1164. int c;
  1165. {
  1166.   if (curr->w_stringp >= curr->w_string + MAXSTR - 1)
  1167.     PrintFlush();
  1168.   *(curr->w_stringp)++ = c;
  1169. }
  1170.  
  1171. static void
  1172. PrintFlush()
  1173. {
  1174.   if (display && curr->w_stringp > curr->w_string)
  1175.     {
  1176.       PutStr(PO);
  1177.       AddStrn(curr->w_string, curr->w_stringp - curr->w_string);
  1178.       PutStr(PF);
  1179.       Flush();
  1180.     }
  1181.   curr->w_stringp = curr->w_string;
  1182. }
  1183.  
  1184.  
  1185. void
  1186. NewAutoFlow(win, on)
  1187. struct win *win;
  1188. int on;
  1189. {
  1190.   debug1("NewAutoFlow: %d\n", on);
  1191.   SetCurr(win);
  1192.   if (win->w_flow & FLOW_AUTOFLAG)
  1193.     win->w_flow = FLOW_AUTOFLAG | (FLOW_AUTO|FLOW_NOW) * on;
  1194.   else
  1195.     win->w_flow = (win->w_flow & ~FLOW_AUTO) | FLOW_AUTO * on;
  1196.   if (display)
  1197.     SetFlow(win->w_flow & FLOW_NOW);
  1198. }
  1199.  
  1200. static void
  1201. DesignateCharset(c, n)
  1202. int c, n;
  1203. {
  1204.   curr->w_ss = 0;
  1205.   if (c == 'B')
  1206.     c = ASCII;
  1207.   if (curr->w_charsets[n] != c)
  1208.     {
  1209.       curr->w_charsets[n] = c;
  1210.       if (curr->w_Charset == n)
  1211.     SetFont(curr->w_Font = c);
  1212.     }
  1213. }
  1214.  
  1215. static void
  1216. MapCharset(n)
  1217. int n;
  1218. {
  1219.   curr->w_ss = 0;
  1220.   if (curr->w_Charset != n)
  1221.     {
  1222.       curr->w_Charset = n;
  1223.       SetFont(curr->w_Font = curr->w_charsets[n]);
  1224.     }
  1225. }
  1226.  
  1227. static void
  1228. SaveCursor()
  1229. {
  1230.   curr->w_saved = 1;
  1231.   curr->w_Saved_x = curr->w_x;
  1232.   curr->w_Saved_y = curr->w_y;
  1233.   curr->w_SavedAttr = curr->w_Attr;
  1234.   curr->w_SavedCharset = curr->w_Charset;
  1235.   bcopy((char *) curr->w_charsets, (char *) curr->w_SavedCharsets,
  1236.     4 * sizeof(int));
  1237. }
  1238.  
  1239. static void
  1240. RestoreCursor()
  1241. {
  1242.   if (curr->w_saved)
  1243.     {
  1244.       GotoPos(curr->w_Saved_x, curr->w_Saved_y);
  1245.       curr->w_x = curr->w_Saved_x;
  1246.       curr->w_y = curr->w_Saved_y;
  1247.       curr->w_Attr = curr->w_SavedAttr;
  1248.       SetAttr(curr->w_Attr);
  1249.       bcopy((char *) curr->w_SavedCharsets, (char *) curr->w_charsets,
  1250.         4 * sizeof(int));
  1251.       curr->w_Charset = curr->w_SavedCharset;
  1252.       curr->w_ss = 0;
  1253.       SetFont(curr->w_Font = curr->w_charsets[curr->w_Charset]);
  1254.     }
  1255. }
  1256.  
  1257. static void
  1258. BackSpace()
  1259. {
  1260.   if (curr->w_x > 0)
  1261.     {
  1262.       curr->w_x--;
  1263.     }
  1264.   else if (curr->w_wrap && curr->w_y > 0)
  1265.     {
  1266.       curr->w_x = cols - 1;
  1267.       curr->w_y--;
  1268.     }
  1269.   if (display)
  1270.     GotoPos(curr->w_x, curr->w_y);
  1271. }
  1272.  
  1273. static void
  1274. Return()
  1275. {
  1276.   if (curr->w_x > 0)
  1277.     {
  1278.       curr->w_x = 0;
  1279.       if (display)
  1280.         GotoPos(curr->w_x, curr->w_y);
  1281.     }
  1282. }
  1283.  
  1284. static void
  1285. LineFeed(out_mode)
  1286. int out_mode;
  1287. {
  1288.   /* out_mode: 0=cr+lf no-output, 1=lf, 2=cr+lf */
  1289.   if (out_mode != 1)
  1290.     curr->w_x = 0;
  1291.   if (curr->w_y != curr->w_bot)        /* Don't scroll */
  1292.     {
  1293.       if (curr->w_y < rows-1)
  1294.     curr->w_y++;
  1295.       if (out_mode && display)
  1296.     GotoPos(curr->w_x, curr->w_y);
  1297.       return;
  1298.     }
  1299.   ScrollUpMap(1);
  1300.   if (curr->w_autoaka > 1)
  1301.     curr->w_autoaka--;
  1302.   if (out_mode && display)
  1303.     {
  1304.       ScrollRegion(curr->w_top, curr->w_bot, 1);
  1305.       GotoPos(curr->w_x, curr->w_y);
  1306.     }
  1307. }
  1308.  
  1309. static void
  1310. ReverseLineFeed()
  1311. {
  1312.   if (curr->w_y == curr->w_top)
  1313.     {
  1314.       ScrollDownMap(1);
  1315.       if (!display)
  1316.     return;
  1317.       ScrollRegion(curr->w_top, curr->w_bot, -1);
  1318.       GotoPos(curr->w_x, curr->w_y);
  1319.     }
  1320.   else if (curr->w_y > 0)
  1321.     CursorUp(1);
  1322. }
  1323.  
  1324. static void
  1325. InsertAChar(c)
  1326. int c;
  1327. {
  1328.   register int y = curr->w_y, x = curr->w_x;
  1329.  
  1330.   if (x == cols)
  1331.     x--;
  1332.   bcopy(curr->w_image[y], OldImage, cols);
  1333.   bcopy(curr->w_attr[y], OldAttr, cols);
  1334.   bcopy(curr->w_font[y], OldFont, cols);
  1335.   bcopy(curr->w_image[y] + x, curr->w_image[y] + x + 1, cols - x - 1);
  1336.   bcopy(curr->w_attr[y] + x, curr->w_attr[y] + x + 1, cols - x - 1);
  1337.   bcopy(curr->w_font[y] + x, curr->w_font[y] + x + 1, cols - x - 1);
  1338.   SetChar(c);
  1339.   curr->w_x = x + 1;
  1340.   if (!display)
  1341.     return;
  1342.   if (CIC || IC || IM)
  1343.     {
  1344.       InsertMode(curr->w_insert);
  1345.       INSERTCHAR(c);
  1346.       if (y == d_bot)
  1347.     d_lp_missing = 0;
  1348.     }
  1349.   else
  1350.     UpdateLine(OldImage, OldAttr, OldFont, y, x, cols - 1);
  1351. }
  1352.  
  1353. static void
  1354. InsertChar(n)
  1355. int n;
  1356. {
  1357.   register int i, y = curr->w_y, x = curr->w_x;
  1358.  
  1359.   if (n <= 0)
  1360.     return;
  1361.   /* Hack to be compatible with the old screen versions */
  1362.   if (curr->w_insert)
  1363.     return;
  1364.   if (x == cols)
  1365.     x--;
  1366.   bcopy(curr->w_image[y], OldImage, cols);
  1367.   bcopy(curr->w_attr[y], OldAttr, cols);
  1368.   bcopy(curr->w_font[y], OldFont, cols);
  1369.   if (n > cols - x)
  1370.     n = cols - x;
  1371.   bcopy(curr->w_image[y] + x, curr->w_image[y] + x + n, cols - x - n);
  1372.   bcopy(curr->w_attr[y] + x, curr->w_attr[y] + x + n, cols - x - n);
  1373.   bcopy(curr->w_font[y] + x, curr->w_font[y] + x + n, cols - x - n);
  1374.   ClearInLine(y, x, x + n - 1);
  1375.   if (!display)
  1376.     return;
  1377.   if (IC || CIC || IM)
  1378.     {
  1379.       if (y == d_bot)
  1380.     d_lp_missing = 0;
  1381.       if (!d_insert)
  1382.     {
  1383.       if (n == 1 && IC)
  1384.         {
  1385.           PutStr(IC);
  1386.           return;
  1387.             }
  1388.       if (CIC)
  1389.         {
  1390.           CPutStr(CIC, n);
  1391.           return;
  1392.             }
  1393.     }
  1394.       InsertMode(1);
  1395.       for (i = n; i--; )
  1396.     INSERTCHAR(' ');
  1397.       GotoPos(x, y);
  1398.     }
  1399.   else
  1400.     UpdateLine(OldImage, OldAttr, OldFont, y, x, cols - 1);
  1401. }
  1402.  
  1403. static void
  1404. DeleteChar(n)
  1405. int n;
  1406. {
  1407.   register int i, y = curr->w_y, x = curr->w_x;
  1408.  
  1409.   if (x == cols)
  1410.     x--;
  1411.   bcopy(curr->w_image[y], OldImage, cols);
  1412.   bcopy(curr->w_attr[y], OldAttr, cols);
  1413.   bcopy(curr->w_font[y], OldFont, cols);
  1414.   if (n > cols - x)
  1415.     n = cols - x;
  1416.   bcopy(curr->w_image[y] + x + n, curr->w_image[y] + x, cols - x - n);
  1417.   bcopy(curr->w_attr[y] + x + n, curr->w_attr[y] + x, cols - x - n);
  1418.   bcopy(curr->w_font[y] + x + n, curr->w_font[y] + x, cols - x - n);
  1419.   ClearInLine(y, cols - n, cols - 1);
  1420.   if (!display)
  1421.     return;
  1422.   if (CDC && !(n == 1 && DC))
  1423.     {
  1424.       CPutStr(CDC, n);
  1425.       if (d_lp_missing && y == d_bot)
  1426.     {
  1427.       FixLP(cols - 1 - n, y);
  1428.           GotoPos(x, y);
  1429.     }
  1430.     }
  1431.   else if (DC)
  1432.     {
  1433.       for (i = n; i; i--)
  1434.     PutStr(DC);
  1435.       if (d_lp_missing && y == d_bot)
  1436.     {
  1437.       FixLP(cols - 1 - n, y);
  1438.           GotoPos(x, y);
  1439.     }
  1440.     }
  1441.   else
  1442.     UpdateLine(OldImage, OldAttr, OldFont, y, x, cols - 1);
  1443. }
  1444.  
  1445. static void
  1446. DeleteLine(n)
  1447. int n;
  1448. {
  1449.   register int old = curr->w_top;
  1450.   
  1451.   if (curr->w_y < curr->w_top || curr->w_y > curr->w_bot)
  1452.     return;
  1453.   if (n > curr->w_bot - curr->w_y + 1)
  1454.     n = curr->w_bot - curr->w_y + 1;
  1455.   curr->w_top = curr->w_y;
  1456.   ScrollUpMap(n);
  1457.   curr->w_top = old;
  1458.   if (!display)
  1459.     return;
  1460.   ScrollRegion(curr->w_y, curr->w_bot, n);
  1461.   GotoPos(curr->w_x, curr->w_y);
  1462. }
  1463.  
  1464. static void
  1465. InsertLine(n)
  1466. int n;
  1467. {
  1468.   register int old = curr->w_top;
  1469.  
  1470.   if (curr->w_y < curr->w_top || curr->w_y > curr->w_bot)
  1471.     return;
  1472.   if (n > curr->w_bot - curr->w_y + 1)
  1473.     n = curr->w_bot - curr->w_y + 1;
  1474.   curr->w_top = curr->w_y;
  1475.   ScrollDownMap(n);
  1476.   curr->w_top = old;
  1477.   if (!display)
  1478.     return;
  1479.   ScrollRegion(curr->w_y, curr->w_bot, -n);
  1480.   GotoPos(curr->w_x, curr->w_y);
  1481. }
  1482.  
  1483.  
  1484. static void
  1485. ScrollUpMap(n)
  1486. int n;
  1487. {
  1488.   char tmp[256 * sizeof(char *)];
  1489.   register int i, cnt1, cnt2;
  1490.   register char **ppi, **ppa, **ppf;
  1491. #ifdef COPY_PASTE
  1492.   register int ii;
  1493. #endif
  1494.  
  1495.   i = curr->w_top + n;
  1496.   cnt1 = n * sizeof(char *);
  1497.   cnt2 = (curr->w_bot - i + 1) * sizeof(char *);
  1498.   ppi = curr->w_image + i;
  1499.   ppa = curr->w_attr + i;
  1500.   ppf = curr->w_font + i;
  1501. #ifdef COPY_PASTE
  1502.   for(ii = curr->w_top; ii < i; ii++)
  1503.      AddLineToHist(curr, &curr->w_image[ii], &curr->w_attr[ii], &curr->w_font[ii]);
  1504. #endif
  1505.   for (i = n; i; --i)
  1506.     {
  1507.       bclear(*--ppi, cols + 1);
  1508.       bzero(*--ppa, cols + 1);
  1509.       bzero(*--ppf, cols + 1);
  1510.     }
  1511.   Scroll((char *) ppi, cnt1, cnt2, tmp);
  1512.   Scroll((char *) ppa, cnt1, cnt2, tmp);
  1513.   Scroll((char *) ppf, cnt1, cnt2, tmp);
  1514. }
  1515.  
  1516. static void
  1517. ScrollDownMap(n)
  1518. int n;
  1519. {
  1520.   char tmp[256 * sizeof(char *)];
  1521.   register int i, cnt1, cnt2;
  1522.   register char **ppi, **ppa, **ppf;
  1523.  
  1524.   i = curr->w_top;
  1525.   cnt1 = (curr->w_bot - i - n + 1) * sizeof(char *);
  1526.   cnt2 = n * sizeof(char *);
  1527.   Scroll((char *) (ppi = curr->w_image + i), cnt1, cnt2, tmp);
  1528.   Scroll((char *) (ppa = curr->w_attr + i), cnt1, cnt2, tmp);
  1529.   Scroll((char *) (ppf = curr->w_font + i), cnt1, cnt2, tmp);
  1530.   for (i = n; i; --i)
  1531.     {
  1532.       bclear(*ppi++, cols + 1);
  1533.       bzero(*ppa++, cols + 1);
  1534.       bzero(*ppf++, cols + 1);
  1535.     }
  1536. }
  1537.  
  1538. static void
  1539. Scroll(cp, cnt1, cnt2, tmp)
  1540. char *cp, *tmp;
  1541. int cnt1, cnt2;
  1542. {
  1543.   if (!cnt1 || !cnt2)
  1544.     return;
  1545.   if (cnt1 <= cnt2)
  1546.     {
  1547.       bcopy(cp, tmp, cnt1);
  1548.       bcopy(cp + cnt1, cp, cnt2);
  1549.       bcopy(tmp, cp + cnt2, cnt1);
  1550.     }
  1551.   else
  1552.     {
  1553.       bcopy(cp + cnt1, tmp, cnt2);
  1554.       bcopy(cp, cp + cnt2, cnt1);
  1555.       bcopy(tmp, cp, cnt2);
  1556.     }
  1557. }
  1558.  
  1559. static void
  1560. ForwardTab()
  1561. {
  1562.   register int x = curr->w_x;
  1563.  
  1564.   if (x == cols)
  1565.     {
  1566.       LineFeed(2);
  1567.       x = 0;
  1568.     }
  1569.   if (curr->w_tabs[x] && x < cols - 1)
  1570.     x++;
  1571.   while (x < cols - 1 && !curr->w_tabs[x])
  1572.     x++;
  1573.   GotoPos(x, curr->w_y);
  1574.   curr->w_x = x;
  1575. }
  1576.  
  1577. static void
  1578. BackwardTab()
  1579. {
  1580.   register int x = curr->w_x;
  1581.  
  1582.   if (curr->w_tabs[x] && x > 0)
  1583.     x--;
  1584.   while (x > 0 && !curr->w_tabs[x])
  1585.     x--;
  1586.   GotoPos(x, curr->w_y);
  1587.   curr->w_x = x;
  1588. }
  1589.  
  1590. static void
  1591. ClearScreen()
  1592. {
  1593.   register int i;
  1594.   register char **ppi = curr->w_image, **ppa = curr->w_attr, **ppf = curr->w_font;
  1595.  
  1596.   for (i = 0; i < rows; ++i)
  1597.     {
  1598. #ifdef COPY_PASTE
  1599.       AddLineToHist(curr, ppi, ppa, ppf);
  1600. #endif
  1601.       bclear(*ppi++, cols + 1);
  1602.       bzero(*ppa++, cols + 1);
  1603.       bzero(*ppf++, cols + 1);
  1604.     }
  1605.   if (display)
  1606.     ClearDisplay();
  1607. }
  1608.  
  1609. static void
  1610. ClearFromBOS()
  1611. {
  1612.   register int n, y = curr->w_y, x = curr->w_x;
  1613.  
  1614.   if (display)
  1615.     Clear(0, 0, x, y);
  1616.   for (n = 0; n < y; ++n)
  1617.     ClearInLine(n, 0, cols - 1);
  1618.   ClearInLine(y, 0, x);
  1619.   RestorePosAttrFont();
  1620. }
  1621.  
  1622. static void
  1623. ClearToEOS()
  1624. {
  1625.   register int n, y = curr->w_y, x = curr->w_x;
  1626.  
  1627.   if (x == 0 && y == 0)
  1628.     {
  1629.       ClearScreen();
  1630.       return;
  1631.     }
  1632.   if (display)
  1633.     Clear(x, y, d_width - 1, d_height - 1);
  1634.   ClearInLine(y, x, cols - 1);
  1635.   for (n = y + 1; n < rows; n++)
  1636.     ClearInLine(n, 0, cols - 1);
  1637.   RestorePosAttrFont();
  1638. }
  1639.  
  1640. static void
  1641. ClearFullLine()
  1642. {
  1643.   register int y = curr->w_y;
  1644.  
  1645.   if (display)
  1646.     Clear(0, y, d_width - 1, y);
  1647.   ClearInLine(y, 0, cols - 1);
  1648.   RestorePosAttrFont();
  1649. }
  1650.  
  1651. static void
  1652. ClearToEOL()
  1653. {
  1654.   register int y = curr->w_y, x = curr->w_x;
  1655.  
  1656.   if (display)
  1657.     Clear(x, y, d_width - 1, y);
  1658.   ClearInLine(y, x, cols - 1);
  1659.   RestorePosAttrFont();
  1660. }
  1661.  
  1662. static void
  1663. ClearFromBOL()
  1664. {
  1665.   register int y = curr->w_y, x = curr->w_x;
  1666.  
  1667.   if (display)
  1668.     Clear(0, y, x, y);
  1669.   ClearInLine(y, 0, x);
  1670.   RestorePosAttrFont();
  1671. }
  1672.  
  1673. static void
  1674. ClearInLine(y, x1, x2)
  1675. int y, x1, x2;
  1676. {
  1677.   register int n;
  1678.  
  1679.   if (x1 == cols)
  1680.     x1--;
  1681.   if (x2 == cols - 1)
  1682.     x2++;
  1683.   if ((n = x2 - x1 + 1) != 0)
  1684.     {
  1685.       bclear(curr->w_image[y] + x1, n);
  1686.       bzero(curr->w_attr[y] + x1, n);
  1687.       bzero(curr->w_font[y] + x1, n);
  1688.     }
  1689. }
  1690.  
  1691. static void
  1692. CursorRight(n)
  1693. register int n;
  1694. {
  1695.   register int x = curr->w_x;
  1696.  
  1697.   if (x == cols)
  1698.     {
  1699.       LineFeed(2);
  1700.       x = 0;
  1701.     }
  1702.   if ((curr->w_x += n) >= cols)
  1703.     curr->w_x = cols - 1;
  1704.   GotoPos(curr->w_x, curr->w_y);
  1705. }
  1706.  
  1707. static void
  1708. CursorUp(n)
  1709. register int n;
  1710. {
  1711.   if (curr->w_y < curr->w_top)        /* if above scrolling rgn, */
  1712.     {
  1713.       if ((curr->w_y -= n) < 0)        /* ignore its limits      */
  1714.          curr->w_y = 0;
  1715.     }
  1716.   else
  1717.     if ((curr->w_y -= n) < curr->w_top)
  1718.       curr->w_y = curr->w_top;
  1719.   GotoPos(curr->w_x, curr->w_y);
  1720. }
  1721.  
  1722. static void
  1723. CursorDown(n)
  1724. register int n;
  1725. {
  1726.   if (curr->w_y > curr->w_bot)        /* if below scrolling rgn, */
  1727.     {
  1728.       if ((curr->w_y += n) > rows - 1)    /* ignore its limits      */
  1729.         curr->w_y = rows - 1;
  1730.     }
  1731.   else
  1732.     if ((curr->w_y += n) > curr->w_bot)
  1733.       curr->w_y = curr->w_bot;
  1734.   GotoPos(curr->w_x, curr->w_y);
  1735. }
  1736.  
  1737. static void
  1738. CursorLeft(n)
  1739. register int n;
  1740. {
  1741.   if ((curr->w_x -= n) < 0)
  1742.     curr->w_x = 0;
  1743.   GotoPos(curr->w_x, curr->w_y);
  1744. }
  1745.  
  1746. static void
  1747. ASetMode(on)
  1748. int on;
  1749. {
  1750.   register int i;
  1751.  
  1752.   for (i = 0; i < curr->w_NumArgs; ++i)
  1753.     {
  1754.       switch (curr->w_args[i])
  1755.     {
  1756.     case 4:
  1757.       curr->w_insert = on;
  1758.       InsertMode(on);
  1759.       break;
  1760.     }
  1761.     }
  1762. }
  1763.  
  1764. static char rendlist[] =
  1765. {
  1766.   (1 << NATTR), A_BD, A_DI, A_SO, A_US, A_BL, 0, A_RV, 0, 0,
  1767.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1768.   0, 0, ~(A_BD|A_SO|A_DI), ~A_SO, ~A_US, ~A_BL, 0, ~A_RV
  1769. };
  1770.  
  1771. static void
  1772. SelectRendition()
  1773. {
  1774.   register int j, i = 0, a = curr->w_Attr;
  1775.  
  1776.   do
  1777.     {
  1778.       j = curr->w_args[i];
  1779.       if (j < 0 || j >= (sizeof(rendlist)/sizeof(*rendlist)))
  1780.     continue;
  1781.       j = rendlist[j];
  1782.       if (j & (1 << NATTR))
  1783.         a &= j;
  1784.       else
  1785.         a |= j;
  1786.     }
  1787.   while (++i < curr->w_NumArgs);
  1788.   SetAttr(curr->w_Attr = a);
  1789. }
  1790.  
  1791. static void
  1792. FillWithEs()
  1793. {
  1794.   register int i;
  1795.   register char *p, *ep;
  1796.  
  1797.   curr->w_y = curr->w_x = 0;
  1798.   for (i = 0; i < rows; ++i)
  1799.     {
  1800.       bzero(curr->w_attr[i], cols);
  1801.       bzero(curr->w_font[i], cols);
  1802.       p = curr->w_image[i];
  1803.       ep = p + cols;
  1804.       while (p < ep)
  1805.     *p++ = 'E';
  1806.     }
  1807.   if (display)
  1808.     Redisplay(0);
  1809. }
  1810.  
  1811.  
  1812. static void
  1813. UpdateLine(os, oa, of, y, from, to)
  1814. int from, to, y;
  1815. char *os, *oa, *of;
  1816. {
  1817.   ASSERT(display);
  1818.   DisplayLine(os, oa, of, curr->w_image[y], curr->w_attr[y],
  1819.           curr->w_font[y], y, from, to);
  1820.   RestorePosAttrFont();
  1821. }
  1822.  
  1823. void
  1824. CheckLP(n_ch)
  1825. char n_ch;
  1826. {
  1827.   register int y, x;
  1828.   register char n_at, n_fo, o_ch, o_at, o_fo;
  1829.  
  1830.   ASSERT(display);
  1831.   x = cols - 1;
  1832.   y = d_bot;
  1833.   o_ch = curr->w_image[y][x];
  1834.   o_at = curr->w_attr[y][x];
  1835.   o_fo = curr->w_font[y][x];
  1836.  
  1837.   n_at = curr->w_Attr;
  1838.   n_fo = curr->w_Font;
  1839.  
  1840.   d_lp_image = n_ch;
  1841.   d_lp_attr = n_at;
  1842.   d_lp_font = n_fo;
  1843.   d_lp_missing = 0;
  1844.   if (n_ch == o_ch && n_at == o_at && n_fo == o_fo)
  1845.     return;
  1846.   if (n_ch != ' ' || n_at || n_fo)
  1847.     d_lp_missing = 1;
  1848.   if (o_ch != ' ' || o_at || o_fo)
  1849.     {
  1850.       if (DC)
  1851.     PutStr(DC);
  1852.       else if (CDC)
  1853.     CPutStr(CDC, 1);
  1854.       else if (CE)
  1855.     PutStr(CE);
  1856.       else
  1857.     d_lp_missing = 1;
  1858.     }
  1859. }
  1860.  
  1861. /*
  1862.  *  Ugly autoaka hack support:
  1863.  *    ChangeAKA() sets a new aka
  1864.  *    FindAKA() searches for an autoaka match
  1865.  */
  1866.  
  1867. void
  1868. ChangeAKA(p, s, l)
  1869. struct win *p;
  1870. char *s;
  1871. int l;
  1872. {
  1873.   if (l > 20)
  1874.     l = 20;
  1875.   strncpy(p->w_akachange, s, l);
  1876.   p->w_akachange[l] = 0;
  1877.   p->w_aka = p->w_akachange;
  1878.   if (p->w_akachange != p->w_akabuf)
  1879.     if (p->w_akachange[0] == 0 || p->w_akachange[-1] == ':')
  1880.       p->w_aka = p->w_akabuf + strlen(p->w_akabuf) + 1;
  1881. }
  1882.  
  1883. static void
  1884. FindAKA()
  1885. {
  1886.   register char *cp, *line;
  1887.   register struct win *wp = curr;
  1888.   register int len = strlen(wp->w_akabuf);
  1889.   int y;
  1890.  
  1891.   y = (wp->w_autoaka > 0 && wp->w_autoaka <= wp->w_height) ? wp->w_autoaka - 1 : wp->w_y;
  1892.   cols = wp->w_width;
  1893.  try_line:
  1894.   cp = line = wp->w_image[y];
  1895.   if (wp->w_autoaka > 0 &&  *wp->w_akabuf != '\0')
  1896.     {
  1897.       for (;;)
  1898.     {
  1899.       if (cp - line >= cols - len)
  1900.         {
  1901.           if (++y == wp->w_autoaka && y < rows)
  1902.         goto try_line;
  1903.           return;
  1904.         }
  1905.       if (strncmp(cp, wp->w_akabuf, len) == 0)
  1906.         break;
  1907.       cp++;
  1908.     }
  1909.       cp += len;
  1910.     }
  1911.   for (len = cols - (cp - line); len && *cp == ' '; len--, cp++)
  1912.     ;
  1913.   if (len)
  1914.     {
  1915.       if (wp->w_autoaka > 0 && (*cp == '!' || *cp == '%' || *cp == '^'))
  1916.     wp->w_autoaka = -1;
  1917.       else
  1918.     wp->w_autoaka = 0;
  1919.       line = cp;
  1920.       while (len && *cp != ' ')
  1921.     {
  1922.       if (*cp++ == '/')
  1923.         line = cp;
  1924.       len--;
  1925.     }
  1926.       ChangeAKA(wp, line, cp - line);
  1927.     }
  1928.   else
  1929.     wp->w_autoaka = 0;
  1930. }
  1931.  
  1932. void
  1933. MakeBlankLine(p, n)
  1934. register char *p;
  1935. register int n;
  1936. {
  1937.   while (n--)
  1938.     *p++ = ' ';
  1939. }
  1940.  
  1941. void
  1942. SetCurr(wp)
  1943. struct win *wp;
  1944. {
  1945.   curr = wp;
  1946.   if (curr == 0)
  1947.     return;
  1948.   cols = curr->w_width;
  1949.   rows = curr->w_height;
  1950.   display = curr->w_active ? curr->w_display : 0;
  1951. }
  1952.  
  1953. static void
  1954. RestorePosAttrFont()
  1955. {
  1956.   GotoPos(curr->w_x, curr->w_y);
  1957.   SetAttr(curr->w_Attr);
  1958.   SetFont(curr->w_Font);
  1959. }
  1960.  
  1961. /* Send a terminal report as if it were typed. */ 
  1962. static void
  1963. Report(fmt, n1, n2)
  1964. char *fmt;
  1965. int n1, n2;
  1966. {
  1967.   register int len;
  1968.   char rbuf[40];
  1969.  
  1970.   sprintf(rbuf, fmt, n1, n2);
  1971.   len = strlen(rbuf);
  1972.  
  1973.   if ((unsigned)(curr->w_inlen + len) <= sizeof(curr->w_inbuf))
  1974.     {
  1975.       bcopy(rbuf, curr->w_inbuf + curr->w_inlen, len);
  1976.       curr->w_inlen += len;
  1977.     }
  1978. }
  1979.  
  1980. #ifdef COPY_PASTE
  1981. void
  1982. AddLineToHist(wp, pi, pa, pf)
  1983. struct win *wp;
  1984. char **pi, **pa, **pf;
  1985. {
  1986.   register char *q, *o;
  1987.  
  1988.   if (wp->w_histheight == 0)
  1989.     return;
  1990.   q = *pi; *pi = wp->w_ihist[wp->w_histidx]; wp->w_ihist[wp->w_histidx] = q;
  1991.   q = *pa; o = wp->w_ahist[wp->w_histidx]; wp->w_ahist[wp->w_histidx] = q;
  1992.   if (o != null)
  1993.     free(o);
  1994.  
  1995.   q = *pf; o = wp->w_fhist[wp->w_histidx]; wp->w_fhist[wp->w_histidx] = q;
  1996.   if (o != null)
  1997.     free(o);
  1998.   *pa = *pf = null;
  1999.   if (++wp->w_histidx >= wp->w_histheight)
  2000.     wp->w_histidx = 0;
  2001. }
  2002. #endif
  2003.