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