1/* Copyright (c) 1993-2002
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.,
19 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
20 *
21 ****************************************************************
22 */
23
24#include <sys/types.h>
25#include <fcntl.h>
26#ifndef sun	/* we want to know about TIOCPKT. */
27# include <sys/ioctl.h>
28#endif
29
30#include "config.h"
31#include "screen.h"
32#include "braille.h"
33#include "extern.h"
34#include "logfile.h"
35
36extern struct display *display, *displays;
37extern struct win *fore;	/* for 83 escape */
38extern struct layer *flayer;	/* for 83 escape */
39
40extern struct NewWindow nwin_default;	/* for ResetWindow() */
41extern int  nversion;		/* numerical version of screen */
42extern int  log_flush, logtstamp_on, logtstamp_after;
43extern char *logtstamp_string;
44extern char *captionstring;
45extern char *hstatusstring;
46extern char *wliststr;
47#ifdef COPY_PASTE
48extern int compacthist;
49#endif
50#ifdef MULTIUSER
51extern struct acluser *EffectiveAclUser;
52#endif
53
54int Z0width, Z1width;		/* widths for Z0/Z1 switching */
55
56/* globals set in WriteString */
57static struct win *curr;	/* window we are working on */
58static int rows, cols;		/* window size of the curr window */
59
60int visual_bell = 0;
61int use_hardstatus = 1;		/* display status line in hs */
62char *printcmd = 0;
63int use_altscreen = 0;		/* enable alternate screen support? */
64
65unsigned char *blank;		/* line filled with spaces */
66unsigned char *null;		/* line filled with '\0' */
67
68struct mline mline_old;
69struct mline mline_blank;
70struct mline mline_null;
71
72struct mchar mchar_null;
73struct mchar mchar_blank = {' ' /* , 0, 0, ... */};
74struct mchar mchar_so    = {' ', A_SO /* , 0, 0, ... */};
75
76/* keep string_t and string_t_string in sync! */
77static char *string_t_string[] =
78{
79  "NONE",
80  "DCS",			/* Device control string */
81  "OSC",			/* Operating system command */
82  "APC",			/* Application program command */
83				/*  - used for status change */
84  "PM",				/* Privacy message */
85  "AKA",			/* title for current screen */
86  "GM",				/* Global message to every display */
87  "STATUS"			/* User hardstatus line */
88};
89
90/* keep state_t and state_t_string in sync! */
91static char *state_t_string[] =
92{
93  "LIT",			/* Literal input */
94  "ESC",			/* Start of escape sequence */
95  "ASTR",			/* Start of control string */
96  "STRESC",			/* ESC seen in control string */
97  "CSI",			/* Reading arguments in "CSI Pn ;...*/
98  "PRIN",			/* Printer mode */
99  "PRINESC",			/* ESC seen in printer mode */
100  "PRINCSI",			/* CSI seen in printer mode */
101  "PRIN4"			/* CSI 4 seen in printer mode */
102};
103
104static int  Special __P((int));
105static void DoESC __P((int, int));
106static void DoCSI __P((int, int));
107static void StringStart __P((enum string_t));
108static void StringChar __P((int));
109static int  StringEnd __P((void));
110static void PrintStart __P((void));
111static void PrintChar __P((int));
112static void PrintFlush __P((void));
113#ifdef FONT
114static void DesignateCharset __P((int, int));
115static void MapCharset __P((int));
116static void MapCharsetR __P((int));
117#endif
118static void SaveCursor __P((void));
119static void RestoreCursor __P((void));
120static void BackSpace __P((void));
121static void Return __P((void));
122static void LineFeed __P((int));
123static void ReverseLineFeed __P((void));
124static void InsertChar __P((int));
125static void DeleteChar __P((int));
126static void DeleteLine __P((int));
127static void InsertLine __P((int));
128static void Scroll __P((char *, int, int, char *));
129static void ForwardTab __P((void));
130static void BackwardTab __P((void));
131static void ClearScreen __P((void));
132static void ClearFromBOS __P((void));
133static void ClearToEOS __P((void));
134static void ClearLineRegion __P((int, int));
135static void CursorRight __P((int));
136static void CursorUp __P((int));
137static void CursorDown __P((int));
138static void CursorLeft __P((int));
139static void ASetMode __P((int));
140static void SelectRendition __P((void));
141static void RestorePosRendition __P((void));
142static void FillWithEs __P((void));
143static void FindAKA __P((void));
144static void Report __P((char *, int, int));
145static void ScrollRegion __P((int));
146#ifdef COPY_PASTE
147static void WAddLineToHist __P((struct win *, struct mline *));
148#endif
149static void WLogString __P((struct win *, char *, int));
150static void WReverseVideo __P((struct win *, int));
151static int  WindowChangedCheck __P((char *, int, int *));
152static void MFixLine __P((struct win *, int, struct mchar *));
153static void MScrollH __P((struct win *, int, int, int, int, int));
154static void MScrollV __P((struct win *, int, int, int, int));
155static void MClearArea __P((struct win *, int, int, int, int, int));
156static void MInsChar __P((struct win *, struct mchar *, int, int));
157static void MPutChar __P((struct win *, struct mchar *, int, int));
158static void MPutStr __P((struct win *, char *, int, struct mchar *, int, int));
159static void MWrapChar __P((struct win *, struct mchar *, int, int, int, int));
160#ifdef COLOR
161static void MBceLine __P((struct win *, int, int, int, int));
162#endif
163
164#ifdef COLOR
165# define CURR_BCE (curr->w_bce ? rend_getbg(&curr->w_rend) : 0)
166#else
167# define CURR_BCE 0
168#endif
169
170void
171ResetAnsiState(p)
172struct win *p;
173{
174  p->w_state = LIT;
175  p->w_StringType = NONE;
176}
177
178void
179ResetWindow(p)
180register struct win *p;
181{
182  register int i;
183
184  p->w_wrap = nwin_default.wrap;
185  p->w_origin = 0;
186  p->w_insert = 0;
187  p->w_revvid = 0;
188  p->w_mouse = 0;
189  p->w_curinv = 0;
190  p->w_curvvis = 0;
191  p->w_autolf = 0;
192  p->w_keypad = 0;
193  p->w_cursorkeys = 0;
194  p->w_top = 0;
195  p->w_bot = p->w_height - 1;
196  p->w_saved = 0;
197  p->w_x = p->w_y = 0;
198  p->w_state = LIT;
199  p->w_StringType = NONE;
200  bzero(p->w_tabs, p->w_width);
201  for (i = 8; i < p->w_width; i += 8)
202    p->w_tabs[i] = 1;
203  p->w_rend = mchar_null;
204#ifdef FONT
205  ResetCharsets(p);
206#endif
207#ifdef COLOR
208  p->w_bce = nwin_default.bce;
209#endif
210}
211
212/* adds max 22 bytes */
213int
214GetAnsiStatus(w, buf)
215struct win *w;
216char *buf;
217{
218  char *p = buf;
219
220  if (w->w_state == LIT)
221    return 0;
222
223  strcpy(p, state_t_string[w->w_state]);
224  p += strlen(p);
225  if (w->w_intermediate)
226    {
227      *p++ = '-';
228      if (w->w_intermediate > 0xff)
229	p += AddXChar(p, w->w_intermediate >> 8);
230      p += AddXChar(p, w->w_intermediate & 0xff);
231      *p = 0;
232    }
233  if (w->w_state == ASTR || w->w_state == STRESC)
234    sprintf(p, "-%s", string_t_string[w->w_StringType]);
235  p += strlen(p);
236  return p - buf;
237}
238
239
240#ifdef FONT
241
242void
243ResetCharsets(p)
244struct win *p;
245{
246  p->w_gr = nwin_default.gr;
247  p->w_c1 = nwin_default.c1;
248  SetCharsets(p, "BBBB02");
249  if (nwin_default.charset)
250    SetCharsets(p, nwin_default.charset);
251#ifdef ENCODINGS
252  ResetEncoding(p);
253#endif
254}
255
256void
257SetCharsets(p, s)
258struct win *p;
259char *s;
260{
261  int i;
262
263  for (i = 0; i < 4 && *s; i++, s++)
264    if (*s != '.')
265      p->w_charsets[i] = ((*s == 'B') ? ASCII : *s);
266  if (*s && *s++ != '.')
267    p->w_Charset = s[-1] - '0';
268  if (*s && *s != '.')
269    p->w_CharsetR = *s - '0';
270  p->w_ss = 0;
271  p->w_FontL = p->w_charsets[p->w_Charset];
272  p->w_FontR = p->w_charsets[p->w_CharsetR];
273}
274#endif	/* FONT */
275
276/*****************************************************************/
277
278
279/*
280 *  Here comes the vt100 emulator
281 *  - writes logfiles,
282 *  - sets timestamp and flags activity in window.
283 *  - record program output in window scrollback
284 *  - translate program output for the display and put it into the obuf.
285 *
286 */
287void
288WriteString(wp, buf, len)
289struct win *wp;
290register char *buf;
291register int len;
292{
293  register int c;
294#ifdef FONT
295  register int font;
296#endif
297  struct canvas *cv;
298
299  if (!len)
300    return;
301  if (wp->w_log)
302    WLogString(wp, buf, len);
303
304  /* set global variables (yuck!) */
305  curr = wp;
306  cols = curr->w_width;
307  rows = curr->w_height;
308
309  if (curr->w_silence)
310    SetTimeout(&curr->w_silenceev, curr->w_silencewait * 1000);
311
312  if (curr->w_monitor == MON_ON)
313    {
314      debug2("ACTIVITY %d %d\n", curr->w_monitor, curr->w_bell);
315      curr->w_monitor = MON_FOUND;
316    }
317
318  do
319    {
320      c = (unsigned char)*buf++;
321#ifdef FONT
322# ifdef DW_CHARS
323      if (!curr->w_mbcs)
324# endif
325        curr->w_rend.font = curr->w_FontL;	/* Default: GL */
326#endif
327
328      /* The next part is only for speedup */
329      if (curr->w_state == LIT &&
330#ifdef UTF8
331          curr->w_encoding != UTF8 &&
332#endif
333#ifdef DW_CHARS
334          !is_dw_font(curr->w_rend.font) &&
335# ifdef ENCODINGS
336          curr->w_rend.font != KANA && !curr->w_mbcs &&
337# endif
338#endif
339#ifdef FONT
340	  curr->w_rend.font != '<' &&
341#endif
342          c >= ' ' && c != 0x7f &&
343          ((c & 0x80) == 0 || ((c >= 0xa0 || !curr->w_c1) && !curr->w_gr)) && !curr->w_ss &&
344          !curr->w_insert && curr->w_x < cols - 1)
345	{
346	  register int currx = curr->w_x;
347          char *imp = buf - 1;
348
349	  while (currx < cols - 1)
350	    {
351	      currx++;
352	      if (--len == 0)
353		break;
354              c = (unsigned char)*buf++;
355	      if (c < ' ' || c == 0x7f || ((c & 0x80) && ((c < 0xa0 && curr->w_c1) || curr->w_gr)))
356		break;
357	    }
358	  currx -= curr->w_x;
359	  if (currx > 0)
360	    {
361	      MPutStr(curr, imp, currx, &curr->w_rend, curr->w_x, curr->w_y);
362	      LPutStr(&curr->w_layer, imp, currx, &curr->w_rend, curr->w_x, curr->w_y);
363	      curr->w_x += currx;
364	    }
365	  if (len == 0)
366	    break;
367	}
368      /* end of speedup code */
369
370#ifdef UTF8
371      if (curr->w_encoding == UTF8)
372	{
373	  c = FromUtf8(c, &curr->w_decodestate);
374	  if (c == -1)
375	    continue;
376	  if (c == -2)
377	    {
378	      c = UCS_REPL;
379	      /* try char again */
380	      buf--;
381	      len++;
382	    }
383	  if (c > 0xff)
384	    debug1("read UNICODE %04x\n", c);
385	}
386#endif
387
388    tryagain:
389      switch (curr->w_state)
390	{
391	case PRIN:
392	  switch (c)
393	    {
394	    case '\033':
395	      curr->w_state = PRINESC;
396	      break;
397	    default:
398	      PrintChar(c);
399	    }
400	  break;
401	case PRINESC:
402	  switch (c)
403	    {
404	    case '[':
405	      curr->w_state = PRINCSI;
406	      break;
407	    default:
408	      PrintChar('\033');
409	      PrintChar(c);
410	      curr->w_state = PRIN;
411	    }
412	  break;
413	case PRINCSI:
414	  switch (c)
415	    {
416	    case '4':
417	      curr->w_state = PRIN4;
418	      break;
419	    default:
420	      PrintChar('\033');
421	      PrintChar('[');
422	      PrintChar(c);
423	      curr->w_state = PRIN;
424	    }
425	  break;
426	case PRIN4:
427	  switch (c)
428	    {
429	    case 'i':
430	      curr->w_state = LIT;
431	      PrintFlush();
432	      if (curr->w_pdisplay && curr->w_pdisplay->d_printfd >= 0)
433		{
434		  close(curr->w_pdisplay->d_printfd);
435		  curr->w_pdisplay->d_printfd = -1;
436		}
437	      curr->w_pdisplay = 0;
438	      break;
439	    default:
440	      PrintChar('\033');
441	      PrintChar('[');
442	      PrintChar('4');
443	      PrintChar(c);
444	      curr->w_state = PRIN;
445	    }
446	  break;
447	case ASTR:
448	  if (c == 0)
449	    break;
450	  if (c == '\033')
451	    {
452	      curr->w_state = STRESC;
453	      break;
454	    }
455	  /* special xterm hack: accept SetStatus sequence. Yucc! */
456	  /* allow ^E for title escapes */
457	  if (!(curr->w_StringType == OSC && c < ' ' && c != '\005'))
458	    if (!curr->w_c1 || c != ('\\' ^ 0xc0))
459	      {
460		StringChar(c);
461		break;
462	      }
463	  c = '\\';
464	  /* FALLTHROUGH */
465	case STRESC:
466	  switch (c)
467	    {
468	    case '\\':
469	      if (StringEnd() == 0 || len <= 1)
470		break;
471	      /* check if somewhere a status is displayed */
472	      for (cv = curr->w_layer.l_cvlist; cv; cv = cv->c_lnext)
473		{
474		  display = cv->c_display;
475		  if (D_status == STATUS_ON_WIN)
476		    break;
477		}
478	      if (cv)
479		{
480		  if (len > IOSIZE + 1)
481		    len = IOSIZE + 1;
482		  curr->w_outlen = len - 1;
483		  bcopy(buf, curr->w_outbuf, len - 1);
484		  return;	/* wait till status is gone */
485		}
486	      break;
487	    case '\033':
488	      StringChar('\033');
489	      break;
490	    default:
491	      curr->w_state = ASTR;
492	      StringChar('\033');
493	      StringChar(c);
494	      break;
495	    }
496	  break;
497	case ESC:
498	  switch (c)
499	    {
500	    case '[':
501	      curr->w_NumArgs = 0;
502	      curr->w_intermediate = 0;
503	      bzero((char *) curr->w_args, MAXARGS * sizeof(int));
504	      curr->w_state = CSI;
505	      break;
506	    case ']':
507	      StringStart(OSC);
508	      break;
509	    case '_':
510	      StringStart(APC);
511	      break;
512	    case 'P':
513	      StringStart(DCS);
514	      break;
515	    case '^':
516	      StringStart(PM);
517	      break;
518	    case '!':
519	      StringStart(GM);
520	      break;
521	    case '"':
522	    case 'k':
523	      StringStart(AKA);
524	      break;
525	    default:
526	      if (Special(c))
527	        {
528		  curr->w_state = LIT;
529		  break;
530		}
531	      debug1("not special. c = %x\n", c);
532	      if (c >= ' ' && c <= '/')
533		{
534		  if (curr->w_intermediate)
535		    {
536#ifdef DW_CHARS
537		      if (curr->w_intermediate == '$')
538			c |= '$' << 8;
539		      else
540#endif
541		      c = -1;
542		    }
543		  curr->w_intermediate = c;
544		}
545	      else if (c >= '0' && c <= '~')
546		{
547		  DoESC(c, curr->w_intermediate);
548		  curr->w_state = LIT;
549		}
550	      else
551		{
552		  curr->w_state = LIT;
553		  goto tryagain;
554		}
555	    }
556	  break;
557	case CSI:
558	  switch (c)
559	    {
560	    case '0': case '1': case '2': case '3': case '4':
561	    case '5': case '6': case '7': case '8': case '9':
562	      if (curr->w_NumArgs < MAXARGS)
563		{
564		  if (curr->w_args[curr->w_NumArgs] < 100000000)
565		    curr->w_args[curr->w_NumArgs] =
566		      10 * curr->w_args[curr->w_NumArgs] + (c - '0');
567		}
568	      break;
569	    case ';':
570	    case ':':
571	      if (curr->w_NumArgs < MAXARGS)
572	        curr->w_NumArgs++;
573	      break;
574	    default:
575	      if (Special(c))
576		break;
577	      if (c >= '@' && c <= '~')
578		{
579		  if (curr->w_NumArgs < MAXARGS)
580		    curr->w_NumArgs++;
581		  DoCSI(c, curr->w_intermediate);
582		  if (curr->w_state != PRIN)
583		    curr->w_state = LIT;
584		}
585	      else if ((c >= ' ' && c <= '/') || (c >= '<' && c <= '?'))
586		curr->w_intermediate = curr->w_intermediate ? -1 : c;
587	      else
588		{
589		  curr->w_state = LIT;
590		  goto tryagain;
591		}
592	    }
593	  break;
594	case LIT:
595	default:
596#ifdef DW_CHARS
597	  if (curr->w_mbcs)
598	    if (c <= ' ' || c == 0x7f || (c >= 0x80 && c < 0xa0 && curr->w_c1))
599	      curr->w_mbcs = 0;
600#endif
601	  if (c < ' ')
602	    {
603	      if (c == '\033')
604		{
605		  curr->w_intermediate = 0;
606		  curr->w_state = ESC;
607		  if (curr->w_autoaka < 0)
608		    curr->w_autoaka = 0;
609		}
610	      else
611		Special(c);
612	      break;
613	    }
614	  if (c >= 0x80 && c < 0xa0 && curr->w_c1)
615#ifdef FONT
616	    if ((curr->w_FontR & 0xf0) != 0x20
617# ifdef UTF8
618		   || curr->w_encoding == UTF8
619# endif
620	       )
621#endif
622	    {
623	      switch (c)
624		{
625		case 0xc0 ^ 'D':
626		case 0xc0 ^ 'E':
627		case 0xc0 ^ 'H':
628		case 0xc0 ^ 'M':
629		case 0xc0 ^ 'N':		/* SS2 */
630		case 0xc0 ^ 'O':		/* SS3 */
631		  DoESC(c ^ 0xc0, 0);
632		  break;
633		case 0xc0 ^ '[':
634		  if (curr->w_autoaka < 0)
635		    curr->w_autoaka = 0;
636		  curr->w_NumArgs = 0;
637		  curr->w_intermediate = 0;
638		  bzero((char *) curr->w_args, MAXARGS * sizeof(int));
639		  curr->w_state = CSI;
640		  break;
641		case 0xc0 ^ 'P':
642		  StringStart(DCS);
643		  break;
644		default:
645		  break;
646		}
647	      break;
648	    }
649
650#ifdef FONT
651# ifdef DW_CHARS
652	  if (!curr->w_mbcs)
653	    {
654# endif
655	      if (c < 0x80 || curr->w_gr == 0)
656	        curr->w_rend.font = curr->w_FontL;
657# ifdef ENCODINGS
658	      else if (curr->w_gr == 2 && !curr->w_ss)
659	        curr->w_rend.font = curr->w_FontE;
660# endif
661	      else
662	        curr->w_rend.font = curr->w_FontR;
663# ifdef DW_CHARS
664	    }
665# endif
666# ifdef UTF8
667	  if (curr->w_encoding == UTF8)
668	    {
669	      if (curr->w_rend.font == '0')
670		{
671		  struct mchar mc, *mcp;
672
673		  debug1("SPECIAL %x\n", c);
674		  mc.image = c;
675		  mc.mbcs = 0;
676		  mc.font = '0';
677		  mcp = recode_mchar(&mc, 0, UTF8);
678		  debug2("%02x %02x\n", mcp->image, mcp->font);
679		  c = mcp->image | mcp->font << 8;
680		}
681	      curr->w_rend.font = 0;
682	    }
683#  ifdef DW_CHARS
684	  if (curr->w_encoding == UTF8 && c >= 0x1100 && utf8_isdouble(c))
685	    curr->w_mbcs = 0xff;
686#  endif
687	  if (curr->w_encoding == UTF8 && c >= 0x0300 && utf8_iscomb(c))
688	    {
689	      int ox, oy;
690	      struct mchar omc;
691
692	      ox = curr->w_x - 1;
693	      oy = curr->w_y;
694	      if (ox < 0)
695		{
696		  ox = curr->w_width - 1;
697	          oy--;
698		}
699	      if (oy < 0)
700		oy = 0;
701	      copy_mline2mchar(&omc, &curr->w_mlines[oy], ox);
702	      if (omc.image == 0xff && omc.font == 0xff)
703		{
704		  ox--;
705		  if (ox >= 0)
706		    {
707	              copy_mline2mchar(&omc, &curr->w_mlines[oy], ox);
708		      omc.mbcs = 0xff;
709		    }
710		}
711	      if (ox >= 0)
712		{
713		  utf8_handle_comb(c, &omc);
714		  MFixLine(curr, oy, &omc);
715		  copy_mchar2mline(&omc, &curr->w_mlines[oy], ox);
716		  LPutChar(&curr->w_layer, &omc, ox, oy);
717		  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
718		}
719	      break;
720	    }
721	  font = curr->w_rend.font;
722# endif
723# ifdef DW_CHARS
724#  ifdef ENCODINGS
725	  if (font == KANA && curr->w_encoding == SJIS && curr->w_mbcs == 0)
726	    {
727	      /* Lets see if it is the first byte of a kanji */
728	      debug1("%x may be first of SJIS\n", c);
729	      if ((0x81 <= c && c <= 0x9f) || (0xe0 <= c && c <= 0xef))
730		{
731		  debug("YES!\n");
732		  curr->w_mbcs = c;
733		  break;
734		}
735	    }
736#  endif
737	  if (font == 031 && c == 0x80 && !curr->w_mbcs)
738	    font = curr->w_rend.font = 0;
739	  if (is_dw_font(font) && c == ' ')
740	    font = curr->w_rend.font = 0;
741	  if (is_dw_font(font) || curr->w_mbcs)
742	    {
743	      int t = c;
744	      if (curr->w_mbcs == 0)
745		{
746		  curr->w_mbcs = c;
747		  break;
748		}
749	      if (curr->w_x == cols - 1)
750		{
751		  curr->w_x += curr->w_wrap ? 1 : -1;
752		  debug1("Patched w_x to %d\n", curr->w_x);
753		}
754#  ifdef UTF8
755	      if (curr->w_encoding != UTF8)
756#  endif
757		{
758		  c = curr->w_mbcs;
759#  ifdef ENCODINGS
760		  if (font == KANA && curr->w_encoding == SJIS)
761		    {
762		      debug2("SJIS !! %x %x\n", c, t);
763		      /*
764		       * SJIS -> EUC mapping:
765		       *   First byte:
766		       *     81,82...9f -> 21,23...5d
767		       *     e0,e1...ef -> 5f,61...7d
768		       *   Second byte:
769		       *     40-7e -> 21-5f
770		       *     80-9e -> 60-7e
771		       *     9f-fc -> 21-7e (increment first byte!)
772		       */
773		      if (0x40 <= t && t <= 0xfc && t != 0x7f)
774			{
775			  if (c <= 0x9f) c = (c - 0x81) * 2 + 0x21;
776			  else c = (c - 0xc1) * 2 + 0x21;
777			  if (t <= 0x7e) t -= 0x1f;
778			  else if (t <= 0x9e) t -= 0x20;
779			  else t -= 0x7e, c++;
780			  curr->w_rend.font = KANJI;
781			}
782		      else
783			{
784			  /* Incomplete shift-jis - skip first byte */
785			  c = t;
786			  t = 0;
787			}
788		      debug2("SJIS after %x %x\n", c, t);
789		    }
790#  endif
791		  if (t && curr->w_gr && font != 030 && font != 031)
792		    {
793		      t &= 0x7f;
794		      if (t < ' ')
795			goto tryagain;
796		    }
797		  if (t == '\177')
798		    break;
799		  curr->w_mbcs = t;
800		}
801	    }
802# endif	/* DW_CHARS */
803	  if (font == '<' && c >= ' ')
804	    {
805	      font = curr->w_rend.font = 0;
806	      c |= 0x80;
807	    }
808# ifdef UTF8
809	  else if (curr->w_gr && curr->w_encoding != UTF8)
810# else
811	  else if (curr->w_gr)
812# endif
813	    {
814#ifdef ENCODINGS
815	      if (c == 0x80 && font == 0 && curr->w_encoding == GBK)
816		c = 0xa4;
817	      else
818	        c &= 0x7f;
819	      if (c < ' ' && font != 031)
820		goto tryagain;
821#else
822	      c &= 0x7f;
823	      if (c < ' ')	/* this is ugly but kanji support */
824		goto tryagain;	/* prevents nicer programming */
825#endif
826	    }
827#endif /* FONT */
828	  if (c == '\177')
829	    break;
830	  curr->w_rend.image = c;
831#ifdef UTF8
832	  if (curr->w_encoding == UTF8)
833	    curr->w_rend.font = c >> 8;
834#endif
835#ifdef DW_CHARS
836	  curr->w_rend.mbcs = curr->w_mbcs;
837#endif
838	  if (curr->w_x < cols - 1)
839	    {
840	      if (curr->w_insert)
841		{
842		  save_mline(&curr->w_mlines[curr->w_y], cols);
843		  MInsChar(curr, &curr->w_rend, curr->w_x, curr->w_y);
844		  LInsChar(&curr->w_layer, &curr->w_rend, curr->w_x, curr->w_y, &mline_old);
845		  curr->w_x++;
846		}
847	      else
848		{
849		  MPutChar(curr, &curr->w_rend, curr->w_x, curr->w_y);
850		  LPutChar(&curr->w_layer, &curr->w_rend, curr->w_x, curr->w_y);
851		  curr->w_x++;
852		}
853	    }
854	  else if (curr->w_x == cols - 1)
855	    {
856	      MPutChar(curr, &curr->w_rend, curr->w_x, curr->w_y);
857	      LPutChar(&curr->w_layer, &curr->w_rend, curr->w_x, curr->w_y);
858	      if (curr->w_wrap)
859		curr->w_x++;
860	    }
861	  else
862	    {
863	      MWrapChar(curr, &curr->w_rend, curr->w_y, curr->w_top, curr->w_bot, curr->w_insert);
864	      LWrapChar(&curr->w_layer, &curr->w_rend, curr->w_y, curr->w_top, curr->w_bot, curr->w_insert);
865	      if (curr->w_y != curr->w_bot && curr->w_y != curr->w_height - 1)
866	        curr->w_y++;
867	      curr->w_x = 1;
868	    }
869#ifdef FONT
870# ifdef DW_CHARS
871	  if (curr->w_mbcs)
872	    {
873	      curr->w_rend.mbcs = curr->w_mbcs = 0;
874	      curr->w_x++;
875	    }
876# endif
877	  if (curr->w_ss)
878	    {
879	      curr->w_FontL = curr->w_charsets[curr->w_Charset];
880	      curr->w_FontR = curr->w_charsets[curr->w_CharsetR];
881	      curr->w_rend.font = curr->w_FontL;
882	      LSetRendition(&curr->w_layer, &curr->w_rend);
883	      curr->w_ss = 0;
884	    }
885#endif /* FONT */
886	  break;
887	}
888    }
889  while (--len);
890  if (!printcmd && curr->w_state == PRIN)
891    PrintFlush();
892}
893
894static void
895WLogString(p, buf, len)
896struct win *p;
897char *buf;
898int len;
899{
900  if (!p->w_log)
901    return;
902  if (logtstamp_on && p->w_logsilence >= logtstamp_after * 2)
903    {
904      char *t = MakeWinMsg(logtstamp_string, p, '%');
905      logfwrite(p->w_log, t, strlen(t));	/* long time no write */
906    }
907  p->w_logsilence = 0;
908  if (logfwrite(p->w_log, buf, len) < 1)
909    {
910      WMsg(p, errno, "Error writing logfile");
911      logfclose(p->w_log);
912      p->w_log = 0;
913    }
914  if (!log_flush)
915    logfflush(p->w_log);
916}
917
918static int
919Special(c)
920register int c;
921{
922  switch (c)
923    {
924    case '\b':
925      BackSpace();
926      return 1;
927    case '\r':
928      Return();
929      return 1;
930    case '\n':
931      if (curr->w_autoaka)
932	FindAKA();
933      LineFeed(0);
934      return 1;
935    case '\007':
936      WBell(curr, visual_bell);
937      return 1;
938    case '\t':
939      ForwardTab();
940      return 1;
941#ifdef FONT
942    case '\017':		/* SI */
943      MapCharset(G0);
944      return 1;
945    case '\016':		/* SO */
946      MapCharset(G1);
947      return 1;
948#endif
949    }
950  return 0;
951}
952
953static void
954DoESC(c, intermediate)
955int c, intermediate;
956{
957  debug2("DoESC: %x - inter = %x\n", c, intermediate);
958  switch (intermediate)
959    {
960    case 0:
961      switch (c)
962	{
963	case 'E':
964	  LineFeed(1);
965	  break;
966	case 'D':
967	  LineFeed(0);
968	  break;
969	case 'M':
970	  ReverseLineFeed();
971	  break;
972	case 'H':
973	  curr->w_tabs[curr->w_x] = 1;
974	  break;
975	case 'Z':		/* jph: Identify as VT100 */
976	  Report("\033[?%d;%dc", 1, 2);
977	  break;
978	case '7':
979	  SaveCursor();
980	  break;
981	case '8':
982	  RestoreCursor();
983	  break;
984	case 'c':
985	  ClearScreen();
986	  ResetWindow(curr);
987	  LKeypadMode(&curr->w_layer, 0);
988	  LCursorkeysMode(&curr->w_layer, 0);
989#ifndef TIOCPKT
990	  WNewAutoFlow(curr, 1);
991#endif
992	  /* XXX
993          SetRendition(&mchar_null);
994	  InsertMode(0);
995	  ChangeScrollRegion(0, rows - 1);
996	  */
997	  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
998	  break;
999	case '=':
1000	  LKeypadMode(&curr->w_layer, curr->w_keypad = 1);
1001#ifndef TIOCPKT
1002	  WNewAutoFlow(curr, 0);
1003#endif /* !TIOCPKT */
1004	  break;
1005	case '>':
1006	  LKeypadMode(&curr->w_layer, curr->w_keypad = 0);
1007#ifndef TIOCPKT
1008	  WNewAutoFlow(curr, 1);
1009#endif /* !TIOCPKT */
1010	  break;
1011#ifdef FONT
1012	case 'n':		/* LS2 */
1013	  MapCharset(G2);
1014	  break;
1015	case 'o':		/* LS3 */
1016	  MapCharset(G3);
1017	  break;
1018	case '~':
1019	  MapCharsetR(G1);	/* LS1R */
1020	  break;
1021	/* { */
1022	case '}':
1023	  MapCharsetR(G2);	/* LS2R */
1024	  break;
1025	case '|':
1026	  MapCharsetR(G3);	/* LS3R */
1027	  break;
1028	case 'N':		/* SS2 */
1029	  if (curr->w_charsets[curr->w_Charset] != curr->w_charsets[G2]
1030	      || curr->w_charsets[curr->w_CharsetR] != curr->w_charsets[G2])
1031	    curr->w_FontR = curr->w_FontL = curr->w_charsets[curr->w_ss = G2];
1032	  else
1033	    curr->w_ss = 0;
1034	  break;
1035	case 'O':		/* SS3 */
1036	  if (curr->w_charsets[curr->w_Charset] != curr->w_charsets[G3]
1037	      || curr->w_charsets[curr->w_CharsetR] != curr->w_charsets[G3])
1038	    curr->w_FontR = curr->w_FontL = curr->w_charsets[curr->w_ss = G3];
1039	  else
1040	    curr->w_ss = 0;
1041	  break;
1042#endif /* FONT */
1043        case 'g':		/* VBELL, private screen sequence */
1044	  WBell(curr, 1);
1045          break;
1046	}
1047      break;
1048    case '#':
1049      switch (c)
1050	{
1051	case '8':
1052	  FillWithEs();
1053	  break;
1054	}
1055      break;
1056#ifdef FONT
1057    case '(':
1058      DesignateCharset(c, G0);
1059      break;
1060    case ')':
1061      DesignateCharset(c, G1);
1062      break;
1063    case '*':
1064      DesignateCharset(c, G2);
1065      break;
1066    case '+':
1067      DesignateCharset(c, G3);
1068      break;
1069# ifdef DW_CHARS
1070/*
1071 * ESC $ ( Fn: invoke multi-byte charset, Fn, to G0
1072 * ESC $ Fn: same as above.  (old sequence)
1073 * ESC $ ) Fn: invoke multi-byte charset, Fn, to G1
1074 * ESC $ * Fn: invoke multi-byte charset, Fn, to G2
1075 * ESC $ + Fn: invoke multi-byte charset, Fn, to G3
1076 */
1077    case '$':
1078    case '$'<<8 | '(':
1079      DesignateCharset(c & 037, G0);
1080      break;
1081    case '$'<<8 | ')':
1082      DesignateCharset(c & 037, G1);
1083      break;
1084    case '$'<<8 | '*':
1085      DesignateCharset(c & 037, G2);
1086      break;
1087    case '$'<<8 | '+':
1088      DesignateCharset(c & 037, G3);
1089      break;
1090# endif
1091#endif /* FONT */
1092    }
1093}
1094
1095static void
1096DoCSI(c, intermediate)
1097int c, intermediate;
1098{
1099  register int i, a1 = curr->w_args[0], a2 = curr->w_args[1];
1100
1101  if (curr->w_NumArgs > MAXARGS)
1102    curr->w_NumArgs = MAXARGS;
1103  switch (intermediate)
1104    {
1105    case 0:
1106      switch (c)
1107	{
1108	case 'H':
1109	case 'f':
1110	  if (a1 < 1)
1111	    a1 = 1;
1112	  if (curr->w_origin)
1113	    a1 += curr->w_top;
1114	  if (a1 > rows)
1115	    a1 = rows;
1116	  if (a2 < 1)
1117	    a2 = 1;
1118	  if (a2 > cols)
1119	    a2 = cols;
1120	  LGotoPos(&curr->w_layer, --a2, --a1);
1121	  curr->w_x = a2;
1122	  curr->w_y = a1;
1123	  if (curr->w_autoaka)
1124	    curr->w_autoaka = a1 + 1;
1125	  break;
1126	case 'J':
1127	  if (a1 < 0 || a1 > 2)
1128	    a1 = 0;
1129	  switch (a1)
1130	    {
1131	    case 0:
1132	      ClearToEOS();
1133	      break;
1134	    case 1:
1135	      ClearFromBOS();
1136	      break;
1137	    case 2:
1138	      ClearScreen();
1139	      LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1140	      break;
1141	    }
1142	  break;
1143	case 'K':
1144	  if (a1 < 0 || a1 > 2)
1145	    a1 %= 3;
1146	  switch (a1)
1147	    {
1148	    case 0:
1149	      ClearLineRegion(curr->w_x, cols - 1);
1150	      break;
1151	    case 1:
1152	      ClearLineRegion(0, curr->w_x);
1153	      break;
1154	    case 2:
1155	      ClearLineRegion(0, cols - 1);
1156	      break;
1157	    }
1158	  break;
1159	case 'X':
1160	  a1 = curr->w_x + (a1 ? a1 - 1 : 0);
1161	  ClearLineRegion(curr->w_x, a1 < cols ? a1 : cols - 1);
1162	  break;
1163	case 'A':
1164	  CursorUp(a1 ? a1 : 1);
1165	  break;
1166	case 'B':
1167	  CursorDown(a1 ? a1 : 1);
1168	  break;
1169	case 'C':
1170	  CursorRight(a1 ? a1 : 1);
1171	  break;
1172	case 'D':
1173	  CursorLeft(a1 ? a1 : 1);
1174	  break;
1175	case 'E':
1176	  curr->w_x = 0;
1177	  CursorDown(a1 ? a1 : 1);	/* positions cursor */
1178	  break;
1179	case 'F':
1180	  curr->w_x = 0;
1181	  CursorUp(a1 ? a1 : 1);	/* positions cursor */
1182	  break;
1183	case 'G':
1184	case '`':			/* HPA */
1185	  curr->w_x = a1 ? a1 - 1 : 0;
1186	  if (curr->w_x >= cols)
1187	    curr->w_x = cols - 1;
1188	  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1189	  break;
1190	case 'd':			/* VPA */
1191	  curr->w_y = a1 ? a1 - 1 : 0;
1192	  if (curr->w_y >= rows)
1193	    curr->w_y = rows - 1;
1194	  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1195	  break;
1196	case 'm':
1197	  SelectRendition();
1198	  break;
1199	case 'g':
1200	  if (a1 == 0)
1201	    curr->w_tabs[curr->w_x] = 0;
1202	  else if (a1 == 3)
1203	    bzero(curr->w_tabs, cols);
1204	  break;
1205	case 'r':
1206	  if (!a1)
1207	    a1 = 1;
1208	  if (!a2)
1209	    a2 = rows;
1210	  if (a1 < 1 || a2 > rows || a1 >= a2)
1211	    break;
1212	  curr->w_top = a1 - 1;
1213	  curr->w_bot = a2 - 1;
1214	  /* ChangeScrollRegion(curr->w_top, curr->w_bot); */
1215	  if (curr->w_origin)
1216	    {
1217	      curr->w_y = curr->w_top;
1218	      curr->w_x = 0;
1219	    }
1220	  else
1221	    curr->w_y = curr->w_x = 0;
1222	  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1223	  break;
1224	case 's':
1225	  SaveCursor();
1226	  break;
1227	case 't':
1228	  if (a1 != 8)
1229	    break;
1230	  a1 = curr->w_args[2];
1231	  if (a1 < 1)
1232	    a1 = curr->w_width;
1233	  if (a2 < 1)
1234	    a2 = curr->w_height;
1235	  if (a1 > 10000 || a2 > 10000)
1236	    break;
1237	  WChangeSize(curr, a1, a2);
1238	  cols = curr->w_width;
1239	  rows = curr->w_height;
1240	  break;
1241	case 'u':
1242	  RestoreCursor();
1243	  break;
1244	case 'I':
1245	  if (!a1)
1246	    a1 = 1;
1247	  while (a1--)
1248	    ForwardTab();
1249	  break;
1250	case 'Z':
1251	  if (!a1)
1252	    a1 = 1;
1253	  while (a1--)
1254	    BackwardTab();
1255	  break;
1256	case 'L':
1257	  InsertLine(a1 ? a1 : 1);
1258	  break;
1259	case 'M':
1260	  DeleteLine(a1 ? a1 : 1);
1261	  break;
1262	case 'P':
1263	  DeleteChar(a1 ? a1 : 1);
1264	  break;
1265	case '@':
1266	  InsertChar(a1 ? a1 : 1);
1267	  break;
1268	case 'h':
1269	  ASetMode(1);
1270	  break;
1271	case 'l':
1272	  ASetMode(0);
1273	  break;
1274	case 'i':		/* MC Media Control */
1275	  if (a1 == 5)
1276	    PrintStart();
1277	  break;
1278	case 'n':
1279	  if (a1 == 5)		/* Report terminal status */
1280	    Report("\033[0n", 0, 0);
1281	  else if (a1 == 6)		/* Report cursor position */
1282	    Report("\033[%d;%dR", curr->w_y + 1, curr->w_x + 1);
1283	  break;
1284	case 'c':		/* Identify as VT100 */
1285	  if (a1 == 0)
1286	    Report("\033[?%d;%dc", 1, 2);
1287	  break;
1288	case 'x':		/* decreqtparm */
1289	  if (a1 == 0 || a1 == 1)
1290	    Report("\033[%d;1;1;112;112;1;0x", a1 + 2, 0);
1291	  break;
1292	case 'p':		/* obscure code from a 97801 term */
1293	  if (a1 == 6 || a1 == 7)
1294	    {
1295	      curr->w_curinv = 7 - a1;
1296	      LCursorVisibility(&curr->w_layer, curr->w_curinv ? -1 : curr->w_curvvis);
1297	    }
1298	  break;
1299	case 'S':		/* code from a 97801 term / DEC vt400 */
1300	  ScrollRegion(a1 ? a1 : 1);
1301	  break;
1302	case 'T':		/* code from a 97801 term / DEC vt400 */
1303	case '^':		/* SD as per ISO 6429 */
1304	  ScrollRegion(a1 ? -a1 : -1);
1305	  break;
1306	}
1307      break;
1308    case '?':
1309      for (a2 = 0; a2 < curr->w_NumArgs; a2++)
1310	{
1311	  a1 = curr->w_args[a2];
1312	  debug2("\\E[?%d%c\n",a1,c);
1313	  if (c != 'h' && c != 'l')
1314	    break;
1315	  i = (c == 'h');
1316	  switch (a1)
1317	    {
1318	    case 1:	/* CKM:  cursor key mode */
1319	      LCursorkeysMode(&curr->w_layer, curr->w_cursorkeys = i);
1320#ifndef TIOCPKT
1321	      WNewAutoFlow(curr, !i);
1322#endif /* !TIOCPKT */
1323	      break;
1324	    case 2:	/* ANM:  ansi/vt52 mode */
1325	      if (i)
1326		{
1327#ifdef FONT
1328# ifdef ENCODINGS
1329		  if (curr->w_encoding)
1330		    break;
1331# endif
1332		  curr->w_charsets[0] = curr->w_charsets[1] =
1333		    curr->w_charsets[2] = curr->w_charsets[2] =
1334		    curr->w_FontL = curr->w_FontR = ASCII;
1335		  curr->w_Charset = 0;
1336		  curr->w_CharsetR = 2;
1337		  curr->w_ss = 0;
1338#endif
1339		}
1340	      break;
1341	    case 3:	/* COLM: column mode */
1342	      i = (i ? Z0width : Z1width);
1343	      WChangeSize(curr, i, curr->w_height);
1344	      cols = curr->w_width;
1345	      rows = curr->w_height;
1346	      break;
1347	 /* case 4:	   SCLM: scrolling mode */
1348	    case 5:	/* SCNM: screen mode */
1349	      if (i != curr->w_revvid)
1350	        WReverseVideo(curr, i);
1351	      curr->w_revvid = i;
1352	      break;
1353	    case 6:	/* OM:   origin mode */
1354	      if ((curr->w_origin = i) != 0)
1355		{
1356		  curr->w_y = curr->w_top;
1357		  curr->w_x = 0;
1358		}
1359	      else
1360		curr->w_y = curr->w_x = 0;
1361	      LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1362	      break;
1363	    case 7:	/* AWM:  auto wrap mode */
1364	      curr->w_wrap = i;
1365	      break;
1366	 /* case 8:	   ARM:  auto repeat mode */
1367	 /* case 9:	   INLM: interlace mode */
1368	    case 9:	/* X10 mouse tracking */
1369	      curr->w_mouse = i ? 9 : 0;
1370	      LMouseMode(&curr->w_layer, curr->w_mouse);
1371	      break;
1372	 /* case 10:	   EDM:  edit mode */
1373	 /* case 11:	   LTM:  line transmit mode */
1374	 /* case 13:	   SCFDM: space compression / field delimiting */
1375	 /* case 14:	   TEM:  transmit execution mode */
1376	 /* case 16:	   EKEM: edit key execution mode */
1377	 /* case 18:	   PFF:  Printer term form feed */
1378	 /* case 19:	   PEX:  Printer extend screen / scroll. reg */
1379	    case 25:	/* TCEM: text cursor enable mode */
1380	      curr->w_curinv = !i;
1381	      LCursorVisibility(&curr->w_layer, curr->w_curinv ? -1 : curr->w_curvvis);
1382	      break;
1383	 /* case 34:	   RLM:  Right to left mode */
1384	 /* case 35:	   HEBM: hebrew keyboard map */
1385	 /* case 36:	   HEM:  hebrew encoding */
1386	 /* case 38:	         TeK Mode */
1387	 /* case 40:	         132 col enable */
1388	 /* case 42:	   NRCM: 7bit NRC character mode */
1389	 /* case 44:	         margin bell enable */
1390	    case 47:    /*       xterm-like alternate screen */
1391	    case 1047:  /*       xterm-like alternate screen */
1392	    case 1049:  /*       xterm-like alternate screen */
1393	      if (use_altscreen)
1394		{
1395		  if (i)
1396		    EnterAltScreen(curr);
1397		  else
1398		    LeaveAltScreen(curr);
1399		  if (a1 == 47 && !i)
1400		    curr->w_saved = 0;
1401		  LRefreshAll(&curr->w_layer, 0);
1402		  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1403		}
1404	      break;
1405	 /* case 66:	   NKM:  Numeric keypad appl mode */
1406	 /* case 68:	   KBUM: Keyboard usage mode (data process) */
1407	    case 1000:	/* VT200 mouse tracking */
1408	    case 1001:	/* VT200 highlight mouse */
1409	    case 1002:	/* button event mouse*/
1410	    case 1003:	/* any event mouse*/
1411	      curr->w_mouse = i ? a1 : 0;
1412	      LMouseMode(&curr->w_layer, curr->w_mouse);
1413	      break;
1414	    }
1415	}
1416      break;
1417    case '>':
1418      switch (c)
1419	{
1420	case 'c':	/* secondary DA */
1421	  if (a1 == 0)
1422	    Report("\033[>%d;%d;0c", 83, nversion);	/* 83 == 'S' */
1423	  break;
1424	}
1425      break;
1426    }
1427}
1428
1429
1430static void
1431StringStart(type)
1432enum string_t type;
1433{
1434  curr->w_StringType = type;
1435  curr->w_stringp = curr->w_string;
1436  curr->w_state = ASTR;
1437}
1438
1439static void
1440StringChar(c)
1441int c;
1442{
1443  if (curr->w_stringp >= curr->w_string + MAXSTR - 1)
1444    curr->w_state = LIT;
1445  else
1446    *(curr->w_stringp)++ = c;
1447}
1448
1449/*
1450 * Do string processing. Returns -1 if output should be suspended
1451 * until status is gone.
1452 */
1453static int
1454StringEnd()
1455{
1456  struct canvas *cv;
1457  char *p;
1458  int typ;
1459
1460  curr->w_state = LIT;
1461  *curr->w_stringp = '\0';
1462  switch (curr->w_StringType)
1463    {
1464    case OSC:	/* special xterm compatibility hack */
1465      if (curr->w_string[0] == ';' || (p = index(curr->w_string, ';')) == 0)
1466	break;
1467      typ = atoi(curr->w_string);
1468      p++;
1469#ifdef MULTIUSER
1470      if (typ == 83)	/* 83 = 'S' */
1471	{
1472	  /* special execute commands sequence */
1473	  char *args[MAXARGS];
1474	  int argl[MAXARGS];
1475	  struct acluser *windowuser;
1476
1477	  windowuser = *FindUserPtr(":window:");
1478	  if (windowuser && Parse(p, sizeof(curr->w_string) - (p - curr->w_string), args, argl))
1479	    {
1480	      for (display = displays; display; display = display->d_next)
1481		if (D_forecv->c_layer->l_bottom == &curr->w_layer)
1482		  break;	/* found it */
1483	      if (display == 0 && curr->w_layer.l_cvlist)
1484		display = curr->w_layer.l_cvlist->c_display;
1485	      if (display == 0)
1486		display = displays;
1487	      EffectiveAclUser = windowuser;
1488	      fore = curr;
1489	      flayer = fore->w_savelayer ? fore->w_savelayer : &fore->w_layer;
1490	      DoCommand(args, argl);
1491	      EffectiveAclUser = 0;
1492	      fore = 0;
1493	      flayer = 0;
1494	    }
1495	  break;
1496	}
1497#endif
1498#ifdef RXVT_OSC
1499      if (typ == 0 || typ == 1 || typ == 20 || typ == 39 || typ == 49)
1500	{
1501	  int typ2;
1502	  typ2 = typ / 10;
1503	  if (--typ2 < 0)
1504	    typ2 = 0;
1505	  if (strcmp(curr->w_xtermosc[typ2], p))
1506	    {
1507	      strncpy(curr->w_xtermosc[typ2], p, sizeof(curr->w_xtermosc[typ2]) - 1);
1508	      curr->w_xtermosc[typ2][sizeof(curr->w_xtermosc[typ2]) - 1] = 0;
1509
1510	      for (display = displays; display; display = display->d_next)
1511		{
1512		  if (!D_CXT)
1513		    continue;
1514		  if (D_forecv->c_layer->l_bottom == &curr->w_layer)
1515		    SetXtermOSC(typ2, curr->w_xtermosc[typ2]);
1516		  if ((typ2 == 2 || typ2 == 3) && D_xtermosc[typ2])
1517		    Redisplay(0);
1518		}
1519	    }
1520	}
1521      if (typ != 0 && typ != 2)
1522	break;
1523#else
1524      if (typ < 0 || typ > 2)
1525	break;
1526#endif
1527
1528      curr->w_stringp -= p - curr->w_string;
1529      if (curr->w_stringp > curr->w_string)
1530	bcopy(p, curr->w_string, curr->w_stringp - curr->w_string);
1531      *curr->w_stringp = '\0';
1532      /* FALLTHROUGH */
1533    case APC:
1534      if (curr->w_hstatus)
1535	{
1536	  if (strcmp(curr->w_hstatus, curr->w_string) == 0)
1537	    break;	/* not changed */
1538	  free(curr->w_hstatus);
1539	  curr->w_hstatus = 0;
1540	}
1541      if (curr->w_string != curr->w_stringp)
1542	curr->w_hstatus = SaveStr(curr->w_string);
1543      WindowChanged(curr, 'h');
1544      break;
1545    case PM:
1546    case GM:
1547      for (display = displays; display; display = display->d_next)
1548	{
1549	  for (cv = D_cvlist; cv; cv = cv->c_next)
1550	    if (cv->c_layer->l_bottom == &curr->w_layer)
1551	      break;
1552	  if (cv || curr->w_StringType == GM)
1553	    MakeStatus(curr->w_string);
1554	}
1555      return -1;
1556    case DCS:
1557      LAY_DISPLAYS(&curr->w_layer, AddStr(curr->w_string));
1558      break;
1559    case AKA:
1560      if (curr->w_title == curr->w_akabuf && !*curr->w_string)
1561	break;
1562      ChangeAKA(curr, curr->w_string, strlen(curr->w_string));
1563      if (!*curr->w_string)
1564	curr->w_autoaka = curr->w_y + 1;
1565      break;
1566    default:
1567      break;
1568    }
1569  return 0;
1570}
1571
1572static void
1573PrintStart()
1574{
1575  curr->w_pdisplay = 0;
1576
1577  /* find us a nice display to print on, fore prefered */
1578  display = curr->w_lastdisp;
1579  if (!(display && curr == D_fore && (printcmd || D_PO)))
1580    for (display = displays; display; display = display->d_next)
1581      if (curr == D_fore && (printcmd || D_PO))
1582        break;
1583  if (!display)
1584    {
1585      struct canvas *cv;
1586      for (cv = curr->w_layer.l_cvlist; cv; cv = cv->c_lnext)
1587	{
1588	  display = cv->c_display;
1589	  if (printcmd || D_PO)
1590	    break;
1591	}
1592      if (!cv)
1593	{
1594	  display = displays;
1595	  if (!display || display->d_next || !(printcmd || D_PO))
1596	    return;
1597	}
1598    }
1599  curr->w_pdisplay = display;
1600  curr->w_stringp = curr->w_string;
1601  curr->w_state = PRIN;
1602  if (printcmd && curr->w_pdisplay->d_printfd < 0)
1603    curr->w_pdisplay->d_printfd = printpipe(curr, printcmd);
1604}
1605
1606static void
1607PrintChar(c)
1608int c;
1609{
1610  if (curr->w_stringp >= curr->w_string + MAXSTR - 1)
1611    PrintFlush();
1612  *(curr->w_stringp)++ = c;
1613}
1614
1615static void
1616PrintFlush()
1617{
1618  display = curr->w_pdisplay;
1619  if (display && printcmd)
1620    {
1621      char *bp = curr->w_string;
1622      int len = curr->w_stringp - curr->w_string;
1623      int r;
1624      while (len && display->d_printfd >= 0)
1625	{
1626	  r = write(display->d_printfd, bp, len);
1627	  if (r <= 0)
1628	    {
1629	      WMsg(curr, errno, "printing aborted");
1630	      close(display->d_printfd);
1631	      display->d_printfd = -1;
1632	      break;
1633	    }
1634	  bp += r;
1635	  len -= r;
1636	}
1637    }
1638  else if (display && curr->w_stringp > curr->w_string)
1639    {
1640      AddCStr(D_PO);
1641      AddStrn(curr->w_string, curr->w_stringp - curr->w_string);
1642      AddCStr(D_PF);
1643      Flush();
1644    }
1645  curr->w_stringp = curr->w_string;
1646}
1647
1648
1649void
1650WNewAutoFlow(win, on)
1651struct win *win;
1652int on;
1653{
1654  debug1("WNewAutoFlow: %d\n", on);
1655  if (win->w_flow & FLOW_AUTOFLAG)
1656    win->w_flow = FLOW_AUTOFLAG | (FLOW_AUTO|FLOW_NOW) * on;
1657  else
1658    win->w_flow = (win->w_flow & ~FLOW_AUTO) | FLOW_AUTO * on;
1659  LSetFlow(&win->w_layer, win->w_flow & FLOW_NOW);
1660}
1661
1662
1663#ifdef FONT
1664
1665static void
1666DesignateCharset(c, n)
1667int c, n;
1668{
1669  curr->w_ss = 0;
1670# ifdef ENCODINGS
1671  if (c == ('@' & 037))		/* map JIS 6226 to 0208 */
1672    c = KANJI;
1673# endif
1674  if (c == 'B')
1675    c = ASCII;
1676  if (curr->w_charsets[n] != c)
1677    {
1678      curr->w_charsets[n] = c;
1679      if (curr->w_Charset == n)
1680	{
1681	  curr->w_FontL = c;
1682	  curr->w_rend.font = curr->w_FontL;
1683	  LSetRendition(&curr->w_layer, &curr->w_rend);
1684	}
1685      if (curr->w_CharsetR == n)
1686        curr->w_FontR = c;
1687    }
1688}
1689
1690static void
1691MapCharset(n)
1692int n;
1693{
1694  curr->w_ss = 0;
1695  if (curr->w_Charset != n)
1696    {
1697      curr->w_Charset = n;
1698      curr->w_FontL = curr->w_charsets[n];
1699      curr->w_rend.font = curr->w_FontL;
1700      LSetRendition(&curr->w_layer, &curr->w_rend);
1701    }
1702}
1703
1704static void
1705MapCharsetR(n)
1706int n;
1707{
1708  curr->w_ss = 0;
1709  if (curr->w_CharsetR != n)
1710    {
1711      curr->w_CharsetR = n;
1712      curr->w_FontR = curr->w_charsets[n];
1713    }
1714  curr->w_gr = 1;
1715}
1716
1717#endif /* FONT */
1718
1719static void
1720SaveCursor()
1721{
1722  curr->w_saved = 1;
1723  curr->w_Saved_x = curr->w_x;
1724  curr->w_Saved_y = curr->w_y;
1725  curr->w_SavedRend = curr->w_rend;
1726#ifdef FONT
1727  curr->w_SavedCharset = curr->w_Charset;
1728  curr->w_SavedCharsetR = curr->w_CharsetR;
1729  bcopy((char *) curr->w_charsets, (char *) curr->w_SavedCharsets,
1730	4 * sizeof(int));
1731#endif
1732}
1733
1734static void
1735RestoreCursor()
1736{
1737  if (!curr->w_saved)
1738    return;
1739  LGotoPos(&curr->w_layer, curr->w_Saved_x, curr->w_Saved_y);
1740  curr->w_x = curr->w_Saved_x;
1741  curr->w_y = curr->w_Saved_y;
1742  curr->w_rend = curr->w_SavedRend;
1743#ifdef FONT
1744  bcopy((char *) curr->w_SavedCharsets, (char *) curr->w_charsets,
1745	4 * sizeof(int));
1746  curr->w_Charset = curr->w_SavedCharset;
1747  curr->w_CharsetR = curr->w_SavedCharsetR;
1748  curr->w_ss = 0;
1749  curr->w_FontL = curr->w_charsets[curr->w_Charset];
1750  curr->w_FontR = curr->w_charsets[curr->w_CharsetR];
1751#endif
1752  LSetRendition(&curr->w_layer, &curr->w_rend);
1753}
1754
1755static void
1756BackSpace()
1757{
1758  if (curr->w_x > 0)
1759    {
1760      curr->w_x--;
1761    }
1762  else if (curr->w_wrap && curr->w_y > 0)
1763    {
1764      curr->w_x = cols - 1;
1765      curr->w_y--;
1766    }
1767  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1768}
1769
1770static void
1771Return()
1772{
1773  if (curr->w_x == 0)
1774    return;
1775  curr->w_x = 0;
1776  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1777}
1778
1779static void
1780LineFeed(out_mode)
1781int out_mode;
1782{
1783  /* out_mode: 0=lf, 1=cr+lf */
1784  if (out_mode)
1785    curr->w_x = 0;
1786  if (curr->w_y != curr->w_bot)		/* Don't scroll */
1787    {
1788      if (curr->w_y < rows-1)
1789	curr->w_y++;
1790      LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1791      return;
1792    }
1793  if (curr->w_autoaka > 1)
1794    curr->w_autoaka--;
1795  MScrollV(curr, 1, curr->w_top, curr->w_bot, CURR_BCE);
1796  LScrollV(&curr->w_layer, 1, curr->w_top, curr->w_bot, CURR_BCE);
1797  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1798}
1799
1800static void
1801ReverseLineFeed()
1802{
1803  if (curr->w_y == curr->w_top)
1804    {
1805      MScrollV(curr, -1, curr->w_top, curr->w_bot, CURR_BCE);
1806      LScrollV(&curr->w_layer, -1, curr->w_top, curr->w_bot, CURR_BCE);
1807      LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1808    }
1809  else if (curr->w_y > 0)
1810    CursorUp(1);
1811}
1812
1813static void
1814InsertChar(n)
1815int n;
1816{
1817  register int y = curr->w_y, x = curr->w_x;
1818
1819  if (n <= 0)
1820    return;
1821  if (x == cols)
1822    x--;
1823  save_mline(&curr->w_mlines[y], cols);
1824  MScrollH(curr, -n, y, x, curr->w_width - 1, CURR_BCE);
1825  LScrollH(&curr->w_layer, -n, y, x, curr->w_width - 1, CURR_BCE, &mline_old);
1826  LGotoPos(&curr->w_layer, x, y);
1827}
1828
1829static void
1830DeleteChar(n)
1831int n;
1832{
1833  register int y = curr->w_y, x = curr->w_x;
1834
1835  if (x == cols)
1836    x--;
1837  save_mline(&curr->w_mlines[y], cols);
1838  MScrollH(curr, n, y, x, curr->w_width - 1, CURR_BCE);
1839  LScrollH(&curr->w_layer, n, y, x, curr->w_width - 1, CURR_BCE, &mline_old);
1840  LGotoPos(&curr->w_layer, x, y);
1841}
1842
1843static void
1844DeleteLine(n)
1845int n;
1846{
1847  if (curr->w_y < curr->w_top || curr->w_y > curr->w_bot)
1848    return;
1849  if (n > curr->w_bot - curr->w_y + 1)
1850    n = curr->w_bot - curr->w_y + 1;
1851  MScrollV(curr, n, curr->w_y, curr->w_bot, CURR_BCE);
1852  LScrollV(&curr->w_layer, n, curr->w_y, curr->w_bot, CURR_BCE);
1853  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1854}
1855
1856static void
1857InsertLine(n)
1858int n;
1859{
1860  if (curr->w_y < curr->w_top || curr->w_y > curr->w_bot)
1861    return;
1862  if (n > curr->w_bot - curr->w_y + 1)
1863    n = curr->w_bot - curr->w_y + 1;
1864  MScrollV(curr, -n, curr->w_y, curr->w_bot, CURR_BCE);
1865  LScrollV(&curr->w_layer, -n, curr->w_y, curr->w_bot, CURR_BCE);
1866  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1867}
1868
1869static void
1870ScrollRegion(n)
1871int n;
1872{
1873  MScrollV(curr, n, curr->w_top, curr->w_bot, CURR_BCE);
1874  LScrollV(&curr->w_layer, n, curr->w_top, curr->w_bot, CURR_BCE);
1875  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1876}
1877
1878
1879static void
1880ForwardTab()
1881{
1882  register int x = curr->w_x;
1883
1884  if (x == cols)
1885    {
1886      LineFeed(1);
1887      x = 0;
1888    }
1889  if (curr->w_tabs[x] && x < cols - 1)
1890    x++;
1891  while (x < cols - 1 && !curr->w_tabs[x])
1892    x++;
1893  curr->w_x = x;
1894  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1895}
1896
1897static void
1898BackwardTab()
1899{
1900  register int x = curr->w_x;
1901
1902  if (curr->w_tabs[x] && x > 0)
1903    x--;
1904  while (x > 0 && !curr->w_tabs[x])
1905    x--;
1906  curr->w_x = x;
1907  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1908}
1909
1910static void
1911ClearScreen()
1912{
1913  LClearArea(&curr->w_layer, 0, 0, curr->w_width - 1, curr->w_height - 1, CURR_BCE, 1);
1914#ifdef COPY_PASTE
1915  MScrollV(curr, curr->w_height, 0, curr->w_height - 1, CURR_BCE);
1916#else
1917  MClearArea(curr, 0, 0, curr->w_width - 1, curr->w_height - 1, CURR_BCE);
1918#endif
1919}
1920
1921static void
1922ClearFromBOS()
1923{
1924  register int y = curr->w_y, x = curr->w_x;
1925
1926  LClearArea(&curr->w_layer, 0, 0, x, y, CURR_BCE, 1);
1927  MClearArea(curr, 0, 0, x, y, CURR_BCE);
1928  RestorePosRendition();
1929}
1930
1931static void
1932ClearToEOS()
1933{
1934  register int y = curr->w_y, x = curr->w_x;
1935
1936  if (x == 0 && y == 0)
1937    {
1938      ClearScreen();
1939      RestorePosRendition();
1940      return;
1941    }
1942  LClearArea(&curr->w_layer, x, y, cols - 1, rows - 1, CURR_BCE, 1);
1943  MClearArea(curr, x, y, cols - 1, rows - 1, CURR_BCE);
1944  RestorePosRendition();
1945}
1946
1947static void
1948ClearLineRegion(from, to)
1949int from, to;
1950{
1951  register int y = curr->w_y;
1952  LClearArea(&curr->w_layer, from, y, to, y, CURR_BCE, 1);
1953  MClearArea(curr, from, y, to, y, CURR_BCE);
1954  RestorePosRendition();
1955}
1956
1957static void
1958CursorRight(n)
1959register int n;
1960{
1961  register int x = curr->w_x;
1962
1963  if (x == cols)
1964    {
1965      LineFeed(1);
1966      x = 0;
1967    }
1968  if ((curr->w_x += n) >= cols)
1969    curr->w_x = cols - 1;
1970  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1971}
1972
1973static void
1974CursorUp(n)
1975register int n;
1976{
1977  if (curr->w_y < curr->w_top)		/* if above scrolling rgn, */
1978    {
1979      if ((curr->w_y -= n) < 0)		/* ignore its limits      */
1980         curr->w_y = 0;
1981    }
1982  else
1983    if ((curr->w_y -= n) < curr->w_top)
1984      curr->w_y = curr->w_top;
1985  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1986}
1987
1988static void
1989CursorDown(n)
1990register int n;
1991{
1992  if (curr->w_y > curr->w_bot)		/* if below scrolling rgn, */
1993    {
1994      if ((curr->w_y += n) > rows - 1)	/* ignore its limits      */
1995        curr->w_y = rows - 1;
1996    }
1997  else
1998    if ((curr->w_y += n) > curr->w_bot)
1999      curr->w_y = curr->w_bot;
2000  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
2001}
2002
2003static void
2004CursorLeft(n)
2005register int n;
2006{
2007  if ((curr->w_x -= n) < 0)
2008    curr->w_x = 0;
2009  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
2010}
2011
2012static void
2013ASetMode(on)
2014int on;
2015{
2016  register int i;
2017
2018  for (i = 0; i < curr->w_NumArgs; ++i)
2019    {
2020      switch (curr->w_args[i])
2021	{
2022     /* case 2:		   KAM: Lock keyboard */
2023	case 4:		/* IRM: Insert mode */
2024	  curr->w_insert = on;
2025	  LAY_DISPLAYS(&curr->w_layer, InsertMode(on));
2026	  break;
2027     /* case 12:	   SRM: Echo mode on */
2028	case 20:	/* LNM: Linefeed mode */
2029	  curr->w_autolf = on;
2030	  break;
2031	case 34:
2032	  curr->w_curvvis = !on;
2033	  LCursorVisibility(&curr->w_layer, curr->w_curinv ? -1 : curr->w_curvvis);
2034	  break;
2035	default:
2036	  break;
2037	}
2038    }
2039}
2040
2041static char rendlist[] =
2042{
2043  ~((1 << NATTR) - 1), A_BD, A_DI, A_SO, A_US, A_BL, 0, A_RV, 0, 0,
2044  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2045  0, 0, ~(A_BD|A_SO|A_DI), ~A_SO, ~A_US, ~A_BL, 0, ~A_RV
2046};
2047
2048static void
2049SelectRendition()
2050{
2051#ifdef COLOR
2052  register int j, i = 0, a = curr->w_rend.attr, c = curr->w_rend.color;
2053# ifdef COLORS256
2054  int cx = curr->w_rend.colorx;
2055# endif
2056#else
2057  register int j, i = 0, a = curr->w_rend.attr;
2058#endif
2059
2060  do
2061    {
2062      j = curr->w_args[i];
2063#ifdef COLOR
2064      if ((j == 38 || j == 48) && i + 2 < curr->w_NumArgs && curr->w_args[i + 1] == 5)
2065	{
2066	  int jj;
2067
2068	  i += 2;
2069	  jj = curr->w_args[i];
2070	  if (jj < 0 || jj > 255)
2071	    continue;
2072# ifdef COLORS256
2073	  if (j == 38)
2074	    {
2075	      c = (c & 0xf0) | ((jj & 0x0f) ^ 9);
2076	      a |= A_BFG;
2077	      if (jj >= 8 && jj < 16)
2078		c |= 0x08;
2079	      else
2080		a ^= A_BFG;
2081	      a = (a & 0xbf) | (jj & 8 ? 0x40 : 0);
2082	      cx = (cx & 0xf0) | (jj >> 4 & 0x0f);
2083	    }
2084	  else
2085	    {
2086	      c = (c & 0x0f) | ((jj & 0x0f) ^ 9) << 4;
2087	      a |= A_BBG;
2088	      if (jj >= 8 && jj < 16)
2089		c |= 0x80;
2090	      else
2091		a ^= A_BBG;
2092	      cx = (cx & 0x0f) | (jj & 0xf0);
2093	    }
2094	  continue;
2095# else
2096	  jj = color256to16(jj) + 30;
2097	  if (jj >= 38)
2098	    jj += 60 - 8;
2099	  j = j == 38 ? jj : jj + 10;
2100# endif
2101	}
2102# ifdef COLORS16
2103      if (j == 0 || (j >= 30 && j <= 39 && j != 38))
2104	a &= 0xbf;
2105      if (j == 0 || (j >= 40 && j <= 49 && j != 48))
2106	a &= 0x7f;
2107      if (j >= 90 && j <= 97)
2108	a |= 0x40;
2109      if (j >= 100 && j <= 107)
2110	a |= 0x80;
2111# endif
2112      if (j >= 90 && j <= 97)
2113	j -= 60;
2114      if (j >= 100 && j <= 107)
2115	j -= 60;
2116      if (j >= 30 && j <= 39 && j != 38)
2117	c = (c & 0xf0) | ((j - 30) ^ 9);
2118      else if (j >= 40 && j <= 49 && j != 48)
2119	c = (c & 0x0f) | (((j - 40) ^ 9) << 4);
2120      if (j == 0)
2121	c = 0;
2122# ifdef COLORS256
2123      if (j == 0 || (j >= 30 && j <= 39 && j != 38))
2124	cx &= 0xf0;
2125      if (j == 0 || (j >= 40 && j <= 49 && j != 48))
2126	cx &= 0x0f;
2127# endif
2128#endif
2129      if (j < 0 || j >= (int)(sizeof(rendlist)/sizeof(*rendlist)))
2130	continue;
2131      j = rendlist[j];
2132      if (j & (1 << NATTR))
2133        a &= j;
2134      else
2135        a |= j;
2136    }
2137  while (++i < curr->w_NumArgs);
2138  curr->w_rend.attr = a;
2139#ifdef COLOR
2140  curr->w_rend.color = c;
2141# ifdef COLORS256
2142  curr->w_rend.colorx = cx;
2143# endif
2144#endif
2145  LSetRendition(&curr->w_layer, &curr->w_rend);
2146}
2147
2148static void
2149FillWithEs()
2150{
2151  register int i;
2152  register unsigned char *p, *ep;
2153
2154  LClearAll(&curr->w_layer, 1);
2155  curr->w_y = curr->w_x = 0;
2156  for (i = 0; i < rows; ++i)
2157    {
2158      clear_mline(&curr->w_mlines[i], 0, cols + 1);
2159      p = curr->w_mlines[i].image;
2160      ep = p + cols;
2161      while (p < ep)
2162	*p++ = 'E';
2163    }
2164  LRefreshAll(&curr->w_layer, 1);
2165}
2166
2167
2168/*
2169 *  Ugly autoaka hack support:
2170 *    ChangeAKA() sets a new aka
2171 *    FindAKA() searches for an autoaka match
2172 */
2173
2174void
2175ChangeAKA(p, s, l)
2176struct win *p;
2177char *s;
2178int l;
2179{
2180  int i, c;
2181
2182  for (i = 0; l > 0; l--)
2183    {
2184      if (p->w_akachange + i == p->w_akabuf + sizeof(p->w_akabuf) - 1)
2185	break;
2186      c = (unsigned char)*s++;
2187      if (c == 0)
2188	break;
2189      if (c < 32 || c == 127 || (c >= 128 && c < 160 && p->w_c1))
2190	continue;
2191      p->w_akachange[i++] = c;
2192    }
2193  p->w_akachange[i] = 0;
2194  p->w_title = p->w_akachange;
2195  if (p->w_akachange != p->w_akabuf)
2196    if (p->w_akachange[0] == 0 || p->w_akachange[-1] == ':')
2197      p->w_title = p->w_akabuf + strlen(p->w_akabuf) + 1;
2198  WindowChanged(p, 't');
2199  WindowChanged((struct win *)0, 'w');
2200  WindowChanged((struct win *)0, 'W');
2201}
2202
2203static void
2204FindAKA()
2205{
2206  register unsigned char *cp, *line;
2207  register struct win *wp = curr;
2208  register int len = strlen(wp->w_akabuf);
2209  int y;
2210
2211  y = (wp->w_autoaka > 0 && wp->w_autoaka <= wp->w_height) ? wp->w_autoaka - 1 : wp->w_y;
2212  cols = wp->w_width;
2213 try_line:
2214  cp = line = wp->w_mlines[y].image;
2215  if (wp->w_autoaka > 0 &&  *wp->w_akabuf != '\0')
2216    {
2217      for (;;)
2218	{
2219	  if (cp - line >= cols - len)
2220	    {
2221	      if (++y == wp->w_autoaka && y < rows)
2222		goto try_line;
2223	      return;
2224	    }
2225	  if (strncmp((char *)cp, wp->w_akabuf, len) == 0)
2226	    break;
2227	  cp++;
2228	}
2229      cp += len;
2230    }
2231  for (len = cols - (cp - line); len && *cp == ' '; len--, cp++)
2232    ;
2233  if (len)
2234    {
2235      if (wp->w_autoaka > 0 && (*cp == '!' || *cp == '%' || *cp == '^'))
2236	wp->w_autoaka = -1;
2237      else
2238	wp->w_autoaka = 0;
2239      line = cp;
2240      while (len && *cp != ' ')
2241	{
2242	  if (*cp++ == '/')
2243	    line = cp;
2244	  len--;
2245	}
2246      ChangeAKA(wp, (char *)line, cp - line);
2247    }
2248  else
2249    wp->w_autoaka = 0;
2250}
2251
2252static void
2253RestorePosRendition()
2254{
2255  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
2256  LSetRendition(&curr->w_layer, &curr->w_rend);
2257}
2258
2259/* Send a terminal report as if it were typed. */
2260static void
2261Report(fmt, n1, n2)
2262char *fmt;
2263int n1, n2;
2264{
2265  register int len;
2266  char rbuf[40];	/* enough room for all replys */
2267
2268  sprintf(rbuf, fmt, n1, n2);
2269  len = strlen(rbuf);
2270
2271  if ((unsigned)(curr->w_inlen + len) <= sizeof(curr->w_inbuf))
2272    {
2273      bcopy(rbuf, curr->w_inbuf + curr->w_inlen, len);
2274      curr->w_inlen += len;
2275    }
2276}
2277
2278
2279
2280/*
2281 *====================================================================*
2282 *====================================================================*
2283 */
2284
2285/**********************************************************************
2286 *
2287 * Memory subsystem.
2288 *
2289 */
2290
2291static void
2292MFixLine(p, y, mc)
2293struct win *p;
2294int y;
2295struct mchar *mc;
2296{
2297  struct mline *ml = &p->w_mlines[y];
2298  if (mc->attr && ml->attr == null)
2299    {
2300      if ((ml->attr = (unsigned char *)malloc(p->w_width + 1)) == 0)
2301	{
2302	  ml->attr = null;
2303	  mc->attr = p->w_rend.attr = 0;
2304	  WMsg(p, 0, "Warning: no space for attr - turned off");
2305	}
2306      bzero((char *)ml->attr, p->w_width + 1);
2307    }
2308#ifdef FONT
2309  if (mc->font && ml->font == null)
2310    {
2311      if ((ml->font = (unsigned char *)malloc(p->w_width + 1)) == 0)
2312	{
2313	  ml->font = null;
2314	  p->w_FontL = p->w_charsets[p->w_ss ? p->w_ss : p->w_Charset] = 0;
2315	  p->w_FontR = p->w_charsets[p->w_ss ? p->w_ss : p->w_CharsetR] = 0;
2316	  mc->font = p->w_rend.font  = 0;
2317	  WMsg(p, 0, "Warning: no space for font - turned off");
2318	}
2319      bzero((char *)ml->font, p->w_width + 1);
2320    }
2321#endif
2322#ifdef COLOR
2323  if (mc->color && ml->color == null)
2324    {
2325      if ((ml->color = (unsigned char *)malloc(p->w_width + 1)) == 0)
2326	{
2327	  ml->color = null;
2328	  mc->color = p->w_rend.color = 0;
2329	  WMsg(p, 0, "Warning: no space for color - turned off");
2330	}
2331      bzero((char *)ml->color, p->w_width + 1);
2332    }
2333# ifdef COLORS256
2334  if (mc->colorx && ml->colorx == null)
2335    {
2336      if ((ml->colorx = (unsigned char *)malloc(p->w_width + 1)) == 0)
2337	{
2338	  ml->colorx = null;
2339	  mc->colorx = p->w_rend.colorx = 0;
2340	  WMsg(p, 0, "Warning: no space for extended colors - turned off");
2341	}
2342      bzero((char *)ml->colorx, p->w_width + 1);
2343    }
2344# endif
2345#endif
2346}
2347
2348/*****************************************************************/
2349
2350#ifdef DW_CHARS
2351# define MKillDwRight(p, ml, x)					\
2352  if (dw_right(ml, x, p->w_encoding))				\
2353    {								\
2354      if (x > 0)						\
2355	copy_mchar2mline(&mchar_blank, ml, x - 1);		\
2356      copy_mchar2mline(&mchar_blank, ml, x);			\
2357    }
2358
2359# define MKillDwLeft(p, ml, x)					\
2360  if (dw_left(ml, x, p->w_encoding))				\
2361    {								\
2362      copy_mchar2mline(&mchar_blank, ml, x);			\
2363      copy_mchar2mline(&mchar_blank, ml, x + 1);		\
2364    }
2365#else
2366# define MKillDwRight(p, ml, x) ;
2367# define MKillDwLeft(p, ml, x) ;
2368#endif
2369
2370static void
2371MScrollH(p, n, y, xs, xe, bce)
2372struct win *p;
2373int n, y, xs, xe, bce;
2374{
2375  struct mline *ml;
2376
2377  if (n == 0)
2378    return;
2379  ml = &p->w_mlines[y];
2380  MKillDwRight(p, ml, xs);
2381  MKillDwLeft(p, ml, xe);
2382  if (n > 0)
2383    {
2384      if (xe - xs + 1 > n)
2385	{
2386	  MKillDwRight(p, ml, xs + n);
2387	  bcopy_mline(ml, xs + n, xs, xe + 1 - xs - n);
2388	}
2389      else
2390	n = xe - xs + 1;
2391      clear_mline(ml, xe + 1 - n, n);
2392#ifdef COLOR
2393      if (bce)
2394        MBceLine(p, y, xe + 1 - n, n, bce);
2395#endif
2396    }
2397  else
2398    {
2399      n = -n;
2400      if (xe - xs + 1 > n)
2401	{
2402	  MKillDwLeft(p, ml, xe - n);
2403	  bcopy_mline(ml, xs, xs + n, xe + 1 - xs - n);
2404	}
2405      else
2406	n = xe - xs + 1;
2407      clear_mline(ml, xs, n);
2408#ifdef COLOR
2409      if (bce)
2410        MBceLine(p, y, xs, n, bce);
2411#endif
2412    }
2413}
2414
2415static void
2416MScrollV(p, n, ys, ye, bce)
2417struct win *p;
2418int n, ys, ye, bce;
2419{
2420  int i, cnt1, cnt2;
2421  struct mline tmp[256];
2422  struct mline *ml;
2423
2424  if (n == 0)
2425    return;
2426  if (n > 0)
2427    {
2428      if (n > 256)
2429	{
2430	  MScrollV(p, n - 256, ys, ye, bce);
2431	  n = 256;
2432	}
2433      if (ye - ys + 1 < n)
2434	n = ye - ys + 1;
2435#ifdef COPY_PASTE
2436      if (compacthist)
2437	{
2438	  ye = MFindUsedLine(p, ye, ys);
2439	  if (ye - ys + 1 < n)
2440	    n = ye - ys + 1;
2441	  if (n <= 0)
2442	    return;
2443	}
2444#endif
2445      /* Clear lines */
2446      ml = p->w_mlines + ys;
2447      for (i = ys; i < ys + n; i++, ml++)
2448	{
2449#ifdef COPY_PASTE
2450	  if (ys == p->w_top)
2451	    WAddLineToHist(p, ml);
2452#endif
2453	  if (ml->attr != null)
2454	    free(ml->attr);
2455	  ml->attr = null;
2456#ifdef FONT
2457	  if (ml->font != null)
2458	    free(ml->font);
2459	  ml->font = null;
2460#endif
2461#ifdef COLOR
2462	  if (ml->color != null)
2463	    free(ml->color);
2464	  ml->color = null;
2465# ifdef COLORS256
2466	  if (ml->colorx != null)
2467	    free(ml->colorx);
2468	  ml->colorx = null;
2469# endif
2470#endif
2471	  bclear((char *)ml->image, p->w_width + 1);
2472#ifdef COLOR
2473	  if (bce)
2474	    MBceLine(p, i, 0, p->w_width, bce);
2475#endif
2476	}
2477      /* switch 'em over */
2478      cnt1 = n * sizeof(struct mline);
2479      cnt2 = (ye - ys + 1 - n) * sizeof(struct mline);
2480      if (cnt1 && cnt2)
2481	Scroll((char *)(p->w_mlines + ys), cnt1, cnt2, (char *)tmp);
2482    }
2483  else
2484    {
2485      if (n < -256)
2486	{
2487	  MScrollV(p, n + 256, ys, ye, bce);
2488	  n = -256;
2489	}
2490      n = -n;
2491      if (ye - ys + 1 < n)
2492	n = ye - ys + 1;
2493
2494      ml = p->w_mlines + ye;
2495      /* Clear lines */
2496      for (i = ye; i > ye - n; i--, ml--)
2497	{
2498	  if (ml->attr != null)
2499	    free(ml->attr);
2500	  ml->attr = null;
2501#ifdef FONT
2502	  if (ml->font != null)
2503	    free(ml->font);
2504	  ml->font = null;
2505#endif
2506#ifdef COLOR
2507	  if (ml->color != null)
2508	    free(ml->color);
2509	  ml->color = null;
2510# ifdef COLORS256
2511	  if (ml->colorx != null)
2512	    free(ml->colorx);
2513	  ml->colorx = null;
2514# endif
2515#endif
2516	  bclear((char *)ml->image, p->w_width + 1);
2517#ifdef COLOR
2518	  if (bce)
2519	    MBceLine(p, i, 0, p->w_width, bce);
2520#endif
2521	}
2522      cnt1 = n * sizeof(struct mline);
2523      cnt2 = (ye - ys + 1 - n) * sizeof(struct mline);
2524      if (cnt1 && cnt2)
2525	Scroll((char *)(p->w_mlines + ys), cnt2, cnt1, (char *)tmp);
2526    }
2527}
2528
2529static void
2530Scroll(cp, cnt1, cnt2, tmp)
2531char *cp, *tmp;
2532int cnt1, cnt2;
2533{
2534  if (!cnt1 || !cnt2)
2535    return;
2536  if (cnt1 <= cnt2)
2537    {
2538      bcopy(cp, tmp, cnt1);
2539      bcopy(cp + cnt1, cp, cnt2);
2540      bcopy(tmp, cp + cnt2, cnt1);
2541    }
2542  else
2543    {
2544      bcopy(cp + cnt1, tmp, cnt2);
2545      bcopy(cp, cp + cnt2, cnt1);
2546      bcopy(tmp, cp, cnt2);
2547    }
2548}
2549
2550static void
2551MClearArea(p, xs, ys, xe, ye, bce)
2552struct win *p;
2553int xs, ys, xe, ye, bce;
2554{
2555  int n, y;
2556  int xxe;
2557  struct mline *ml;
2558
2559  /* check for magic margin condition */
2560  if (xs >= p->w_width)
2561    xs = p->w_width - 1;
2562  if (xe >= p->w_width)
2563    xe = p->w_width - 1;
2564
2565  MKillDwRight(p, p->w_mlines + ys, xs);
2566  MKillDwLeft(p, p->w_mlines + ye, xe);
2567
2568  ml = p->w_mlines + ys;
2569  for (y = ys; y <= ye; y++, ml++)
2570    {
2571      xxe = (y == ye) ? xe : p->w_width - 1;
2572      n = xxe - xs + 1;
2573      if (n > 0)
2574	clear_mline(ml, xs, n);
2575#ifdef COLOR
2576      if (n > 0 && bce)
2577	MBceLine(p, y, xs, xs + n - 1, bce);
2578#endif
2579      xs = 0;
2580    }
2581}
2582
2583static void
2584MInsChar(p, c, x, y)
2585struct win *p;
2586struct mchar *c;
2587int x, y;
2588{
2589  int n;
2590  struct mline *ml;
2591
2592  ASSERT(x >= 0 && x < p->w_width);
2593  MFixLine(p, y, c);
2594  ml = p->w_mlines + y;
2595  n = p->w_width - x - 1;
2596  MKillDwRight(p, ml, x);
2597  if (n > 0)
2598    {
2599      MKillDwRight(p, ml, p->w_width - 1);
2600      bcopy_mline(ml, x, x + 1, n);
2601    }
2602  copy_mchar2mline(c, ml, x);
2603#ifdef DW_CHARS
2604  if (c->mbcs)
2605    {
2606      if (--n > 0)
2607        {
2608          MKillDwRight(p, ml, p->w_width - 1);
2609	  bcopy_mline(ml, x + 1, x + 2, n);
2610	}
2611      copy_mchar2mline(c, ml, x + 1);
2612      ml->image[x + 1] = c->mbcs;
2613# ifdef UTF8
2614      if (p->w_encoding != UTF8)
2615	ml->font[x + 1] |= 0x80;
2616      else if (p->w_encoding == UTF8 && c->mbcs)
2617	ml->font[x + 1] = c->mbcs;
2618# else
2619      ml->font[x + 1] |= 0x80;
2620# endif
2621    }
2622#endif
2623}
2624
2625static void
2626MPutChar(p, c, x, y)
2627struct win *p;
2628struct mchar *c;
2629int x, y;
2630{
2631  struct mline *ml;
2632
2633  MFixLine(p, y, c);
2634  ml = &p->w_mlines[y];
2635  MKillDwRight(p, ml, x);
2636  MKillDwLeft(p, ml, x);
2637  copy_mchar2mline(c, ml, x);
2638#ifdef DW_CHARS
2639  if (c->mbcs)
2640    {
2641      MKillDwLeft(p, ml, x + 1);
2642      copy_mchar2mline(c, ml, x + 1);
2643      ml->image[x + 1] = c->mbcs;
2644# ifdef UTF8
2645      if (p->w_encoding != UTF8)
2646	ml->font[x + 1] |= 0x80;
2647      else if (p->w_encoding == UTF8 && c->mbcs)
2648	ml->font[x + 1] = c->mbcs;
2649# else
2650      ml->font[x + 1] |= 0x80;
2651# endif
2652    }
2653#endif
2654}
2655
2656
2657static void
2658MWrapChar(p, c, y, top, bot, ins)
2659struct win *p;
2660struct mchar *c;
2661int y, top, bot;
2662int ins;
2663{
2664  struct mline *ml;
2665  int bce;
2666
2667#ifdef COLOR
2668  bce = rend_getbg(c);
2669#else
2670  bce = 0;
2671#endif
2672  MFixLine(p, y, c);
2673  ml = &p->w_mlines[y];
2674  copy_mchar2mline(&mchar_null, ml, p->w_width);
2675  if (y == bot)
2676    MScrollV(p, 1, top, bot, bce);
2677  else if (y < p->w_height - 1)
2678    y++;
2679  if (ins)
2680    MInsChar(p, c, 0, y);
2681  else
2682    MPutChar(p, c, 0, y);
2683}
2684
2685static void
2686MPutStr(p, s, n, r, x, y)
2687struct win *p;
2688char *s;
2689int n;
2690struct mchar *r;
2691int x, y;
2692{
2693  struct mline *ml;
2694  int i;
2695  unsigned char *b;
2696
2697  if (n <= 0)
2698    return;
2699  MFixLine(p, y, r);
2700  ml = &p->w_mlines[y];
2701  MKillDwRight(p, ml, x);
2702  MKillDwLeft(p, ml, x + n - 1);
2703  bcopy(s, (char *)ml->image + x, n);
2704  b = ml->attr + x;
2705  for (i = n; i-- > 0;)
2706    *b++ = r->attr;
2707#ifdef FONT
2708  b = ml->font + x;
2709  for (i = n; i-- > 0;)
2710    *b++ = r->font;
2711#endif
2712#ifdef COLOR
2713  b = ml->color + x;
2714  for (i = n; i-- > 0;)
2715    *b++ = r->color;
2716# ifdef COLORS256
2717  b = ml->colorx + x;
2718  for (i = n; i-- > 0;)
2719    *b++ = r->colorx;
2720# endif
2721#endif
2722}
2723
2724#ifdef COLOR
2725static void
2726MBceLine(p, y, xs, xe, bce)
2727struct win *p;
2728int y, xs, xe, bce;
2729{
2730  struct mchar mc;
2731  struct mline *ml;
2732  int x;
2733
2734  mc = mchar_null;
2735  rend_setbg(&mc, bce);
2736  MFixLine(p, y, &mc);
2737  ml = p->w_mlines + y;
2738# ifdef COLORS16
2739  if (mc.attr)
2740    for (x = xs; x <= xe; x++)
2741      ml->attr[x] = mc.attr;
2742# endif
2743  if (mc.color)
2744    for (x = xs; x <= xe; x++)
2745      ml->color[x] = mc.color;
2746# ifdef COLORS256
2747  if (mc.colorx)
2748    for (x = xs; x <= xe; x++)
2749      ml->colorx[x] = mc.colorx;
2750# endif
2751}
2752#endif
2753
2754
2755#ifdef COPY_PASTE
2756static void
2757WAddLineToHist(wp, ml)
2758struct win *wp;
2759struct mline *ml;
2760{
2761  register unsigned char *q, *o;
2762  struct mline *hml;
2763
2764  if (wp->w_histheight == 0)
2765    return;
2766  hml = &wp->w_hlines[wp->w_histidx];
2767  q = ml->image; ml->image = hml->image; hml->image = q;
2768
2769  q = ml->attr; o = hml->attr; hml->attr = q; ml->attr = null;
2770  if (o != null)
2771    free(o);
2772
2773#ifdef FONT
2774  q = ml->font; o = hml->font; hml->font = q; ml->font = null;
2775  if (o != null)
2776    free(o);
2777#endif
2778
2779#ifdef COLOR
2780  q = ml->color; o = hml->color; hml->color = q; ml->color = null;
2781  if (o != null)
2782    free(o);
2783# ifdef COLORS256
2784  q = ml->colorx; o = hml->colorx; hml->colorx = q; ml->colorx = null;
2785  if (o != null)
2786    free(o);
2787# endif
2788#endif
2789
2790  if (++wp->w_histidx >= wp->w_histheight)
2791    wp->w_histidx = 0;
2792}
2793#endif
2794
2795int
2796MFindUsedLine(p, ye, ys)
2797struct win *p;
2798int ys, ye;
2799{
2800  int y;
2801  struct mline *ml = p->w_mlines + ye;
2802
2803  debug2("MFindUsedLine: %d %d\n", ye, ys);
2804  for (y = ye; y >= ys; y--, ml--)
2805    {
2806      if (bcmp((char*)ml->image, blank, p->w_width))
2807	break;
2808      if (ml->attr != null && bcmp((char*)ml->attr, null, p->w_width))
2809	break;
2810#ifdef COLOR
2811      if (ml->color != null && bcmp((char*)ml->color, null, p->w_width))
2812	break;
2813# ifdef COLORS256
2814      if (ml->colorx != null && bcmp((char*)ml->colorx, null, p->w_width))
2815	break;
2816# endif
2817#endif
2818    }
2819  debug1("MFindUsedLine returning  %d\n", y);
2820  return y;
2821}
2822
2823
2824/*
2825 *====================================================================*
2826 *====================================================================*
2827 */
2828
2829/*
2830 * Tricky: send only one bell even if the window is displayed
2831 * more than once.
2832 */
2833void
2834WBell(p, visual)
2835struct win *p;
2836int visual;
2837{
2838  struct canvas *cv;
2839  for (display = displays; display; display = display->d_next)
2840    {
2841      for (cv = D_cvlist; cv; cv = cv->c_next)
2842	if (cv->c_layer->l_bottom == &p->w_layer)
2843	  break;
2844      if (cv && !visual)
2845	AddCStr(D_BL);
2846      else if (cv && D_VB)
2847	AddCStr(D_VB);
2848      else
2849        p->w_bell = visual ? BELL_VISUAL : BELL_FOUND;
2850    }
2851}
2852
2853/*
2854 * This should be reverse video.
2855 * Only change video if window is fore.
2856 * Because it is used in some termcaps to emulate
2857 * a visual bell we do this hack here.
2858 * (screen uses \Eg as special vbell sequence)
2859 */
2860static void
2861WReverseVideo(p, on)
2862struct win *p;
2863int on;
2864{
2865  struct canvas *cv;
2866  for (cv = p->w_layer.l_cvlist; cv; cv = cv->c_lnext)
2867    {
2868      display = cv->c_display;
2869      if (cv != D_forecv)
2870	continue;
2871      ReverseVideo(on);
2872      if (!on && p->w_revvid && !D_CVR)
2873	{
2874	  if (D_VB)
2875	    AddCStr(D_VB);
2876	  else
2877	    p->w_bell = BELL_VISUAL;
2878	}
2879    }
2880}
2881
2882void
2883WMsg(p, err, str)
2884struct win *p;
2885int err;
2886char *str;
2887{
2888  extern struct layer *flayer;
2889  struct layer *oldflayer = flayer;
2890  flayer = &p->w_layer;
2891  LMsg(err, str);
2892  flayer = oldflayer;
2893}
2894
2895void
2896WChangeSize(p, w, h)
2897struct win *p;
2898int w, h;
2899{
2900  int wok = 0;
2901  struct canvas *cv;
2902
2903  if (p->w_layer.l_cvlist == 0)
2904    {
2905      /* window not displayed -> works always */
2906      ChangeWindowSize(p, w, h, p->w_histheight);
2907      return;
2908    }
2909  for (cv = p->w_layer.l_cvlist; cv; cv = cv->c_lnext)
2910    {
2911      display = cv->c_display;
2912      if (p != D_fore)
2913	continue;		/* change only fore */
2914      if (D_CWS)
2915	break;
2916      if (D_CZ0 && (w == Z0width || w == Z1width))
2917	wok = 1;
2918    }
2919  if (cv == 0 && wok == 0)	/* can't change any display */
2920    return;
2921  if (!D_CWS)
2922    h = p->w_height;
2923  ChangeWindowSize(p, w, h, p->w_histheight);
2924  for (display = displays; display; display = display->d_next)
2925    {
2926      if (p == D_fore)
2927	{
2928	  if (D_cvlist && D_cvlist->c_next == 0)
2929	    ResizeDisplay(w, h);
2930	  else
2931	    ResizeDisplay(w, D_height);
2932	  ResizeLayersToCanvases();	/* XXX Hmm ? */
2933	  continue;
2934	}
2935      for (cv = D_cvlist; cv; cv = cv->c_next)
2936	if (cv->c_layer->l_bottom == &p->w_layer)
2937	  break;
2938      if (cv)
2939	Redisplay(0);
2940    }
2941}
2942
2943static int
2944WindowChangedCheck(s, what, hp)
2945char *s;
2946int what;
2947int *hp;
2948{
2949  int h = 0;
2950  int l;
2951  while(*s)
2952    {
2953      if (*s++ != (hp ? '%' : '\005'))
2954	continue;
2955      l = 0;
2956      while (*s >= '0' && *s <= '9')
2957	s++;
2958      if (*s == 'L')
2959	{
2960	  s++;
2961	  l = 0x100;
2962	}
2963      if (*s == 'h')
2964	h = 1;
2965      if (*s == what || ((*s | l) == what) || what == 'd')
2966	break;
2967      if (*s)
2968	s++;
2969    }
2970  if (hp)
2971    *hp = h;
2972  return *s ? 1 : 0;
2973}
2974
2975void
2976WindowChanged(p, what)
2977struct win *p;
2978int what;
2979{
2980  int inwstr, inhstr, inlstr;
2981  int inwstrh = 0, inhstrh = 0, inlstrh = 0;
2982  int got, ox, oy;
2983  struct display *olddisplay = display;
2984  struct canvas *cv;
2985
2986  inwstr = inhstr = 0;
2987
2988  if (what == 'f')
2989    {
2990      WindowChanged((struct win *)0, 'w'|0x100);
2991      WindowChanged((struct win *)0, 'W'|0x100);
2992    }
2993
2994  if (what)
2995    {
2996      inwstr = WindowChangedCheck(captionstring, what, &inwstrh);
2997      inhstr = WindowChangedCheck(hstatusstring, what, &inhstrh);
2998      inlstr = WindowChangedCheck(wliststr, what, &inlstrh);
2999    }
3000  else
3001    {
3002      inwstr = inhstr = 0;
3003      inlstr = 1;
3004    }
3005
3006  if (p == 0)
3007    {
3008      for (display = displays; display; display = display->d_next)
3009	{
3010	  ox = D_x;
3011	  oy = D_y;
3012	  for (cv = D_cvlist; cv; cv = cv->c_next)
3013	    {
3014	      if (inlstr || (inlstrh && p && p->w_hstatus && *p->w_hstatus && WindowChangedCheck(p->w_hstatus, what, (int *)0)))
3015		WListUpdatecv(cv, (struct win *)0);
3016	      p = Layer2Window(cv->c_layer);
3017	      if (inwstr || (inwstrh && p && p->w_hstatus && *p->w_hstatus && WindowChangedCheck(p->w_hstatus, what, (int *)0)))
3018	        if (cv->c_ye + 1 < D_height)
3019		  RefreshLine(cv->c_ye + 1, 0, D_width - 1, 0);
3020	    }
3021	  p = D_fore;
3022	  if (inhstr || (inhstrh && p && p->w_hstatus && *p->w_hstatus && WindowChangedCheck(p->w_hstatus, what, (int *)0)))
3023	    RefreshHStatus();
3024	  if (ox != -1 && ox != -1)
3025	    GotoPos(ox, oy);
3026	}
3027      display = olddisplay;
3028      return;
3029    }
3030
3031  if (p->w_hstatus && *p->w_hstatus && (inwstrh || inhstrh || inlstrh) && WindowChangedCheck(p->w_hstatus, what, (int *)0))
3032    {
3033      inwstr |= inwstrh;
3034      inhstr |= inhstrh;
3035      inlstr |= inlstrh;
3036    }
3037  if (!inwstr && !inhstr && !inlstr)
3038    return;
3039  for (display = displays; display; display = display->d_next)
3040    {
3041      got = 0;
3042      ox = D_x;
3043      oy = D_y;
3044      for (cv = D_cvlist; cv; cv = cv->c_next)
3045	{
3046	  if (inlstr)
3047	    WListUpdatecv(cv, p);
3048	  if (Layer2Window(cv->c_layer) != p)
3049	    continue;
3050	  got = 1;
3051	  if (inwstr && cv->c_ye + 1 < D_height)
3052	    RefreshLine(cv->c_ye + 1, 0, D_width - 1, 0);
3053	}
3054      if (got && inhstr && p == D_fore)
3055	RefreshHStatus();
3056      if (ox != -1 && ox != -1)
3057	GotoPos(ox, oy);
3058    }
3059  display = olddisplay;
3060}
3061
3062