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