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