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
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)
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.
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 * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 ****************************************************************
29 #include <sys/types.h>
31 #ifndef sun /* we want to know about TIOCPKT. */
32 # include <sys/ioctl.h>
41 extern struct display
*display
, *displays
;
42 extern struct win
*fore
; /* for 83 escape */
43 extern struct layer
*flayer
; /* for 83 escape */
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
;
53 extern int compacthist
;
56 extern struct acluser
*EffectiveAclUser
;
59 int Z0width
, Z1width
; /* widths for Z0/Z1 switching */
61 /* globals set in WriteString */
62 static struct win
*curr
; /* window we are working on */
63 static int rows
, cols
; /* window size of the curr window */
66 int use_hardstatus
= 1; /* display status line in hs */
68 int use_altscreen
= 0; /* enable alternate screen support? */
70 unsigned char *blank
; /* line filled with spaces */
71 unsigned char *null
; /* line filled with '\0' */
73 struct mline mline_old
;
74 struct mline mline_blank
;
75 struct mline mline_null
;
77 struct mchar mchar_null
;
78 struct mchar mchar_blank
= {' ' /* , 0, 0, ... */};
79 struct mchar mchar_so
= {' ', A_SO
/* , 0, 0, ... */};
81 int renditions
[NUM_RENDS
] = {65529 /* =ub */, 65531 /* =b */, 65533 /* =u */ };
83 /* keep string_t and string_t_string in sync! */
84 static char *string_t_string
[] =
87 "DCS", /* Device control string */
88 "OSC", /* Operating system command */
89 "APC", /* Application program command */
90 /* - used for status change */
91 "PM", /* Privacy message */
92 "AKA", /* title for current screen */
93 "GM", /* Global message to every display */
94 "STATUS" /* User hardstatus line */
97 /* keep state_t and state_t_string in sync! */
98 static char *state_t_string
[] =
100 "LIT", /* Literal input */
101 "ESC", /* Start of escape sequence */
102 "ASTR", /* Start of control string */
103 "STRESC", /* ESC seen in control string */
104 "CSI", /* Reading arguments in "CSI Pn ;...*/
105 "PRIN", /* Printer mode */
106 "PRINESC", /* ESC seen in printer mode */
107 "PRINCSI", /* CSI seen in printer mode */
108 "PRIN4" /* CSI 4 seen in printer mode */
111 static int Special
__P((int));
112 static void DoESC
__P((int, int));
113 static void DoCSI
__P((int, int));
114 static void StringStart
__P((enum string_t
));
115 static void StringChar
__P((int));
116 static int StringEnd
__P((void));
117 static void PrintStart
__P((void));
118 static void PrintChar
__P((int));
119 static void PrintFlush
__P((void));
121 static void DesignateCharset
__P((int, int));
122 static void MapCharset
__P((int));
123 static void MapCharsetR
__P((int));
125 static void SaveCursor
__P((struct cursor
*));
126 static void RestoreCursor
__P((struct cursor
*));
127 static void BackSpace
__P((void));
128 static void Return
__P((void));
129 static void LineFeed
__P((int));
130 static void ReverseLineFeed
__P((void));
131 static void InsertChar
__P((int));
132 static void DeleteChar
__P((int));
133 static void DeleteLine
__P((int));
134 static void InsertLine
__P((int));
135 static void Scroll
__P((char *, int, int, char *));
136 static void ForwardTab
__P((void));
137 static void BackwardTab
__P((void));
138 static void ClearScreen
__P((void));
139 static void ClearFromBOS
__P((void));
140 static void ClearToEOS
__P((void));
141 static void ClearLineRegion
__P((int, int));
142 static void CursorRight
__P((int));
143 static void CursorUp
__P((int));
144 static void CursorDown
__P((int));
145 static void CursorLeft
__P((int));
146 static void ASetMode
__P((int));
147 static void SelectRendition
__P((void));
148 static void RestorePosRendition
__P((void));
149 static void FillWithEs
__P((void));
150 static void FindAKA
__P((void));
151 static void Report
__P((char *, int, int));
152 static void ScrollRegion
__P((int));
154 static void WAddLineToHist
__P((struct win
*, struct mline
*));
156 static void WLogString
__P((struct win
*, char *, int));
157 static void WReverseVideo
__P((struct win
*, int));
158 static int WindowChangedCheck
__P((char *, int, int *));
159 static void MFixLine
__P((struct win
*, int, struct mchar
*));
160 static void MScrollH
__P((struct win
*, int, int, int, int, int));
161 static void MScrollV
__P((struct win
*, int, int, int, int));
162 static void MClearArea
__P((struct win
*, int, int, int, int, int));
163 static void MInsChar
__P((struct win
*, struct mchar
*, int, int));
164 static void MPutChar
__P((struct win
*, struct mchar
*, int, int));
165 static void MPutStr
__P((struct win
*, char *, int, struct mchar
*, int, int));
166 static void MWrapChar
__P((struct win
*, struct mchar
*, int, int, int, int));
168 static void MBceLine
__P((struct win
*, int, int, int, int));
172 # define CURR_BCE (curr->w_bce ? rend_getbg(&curr->w_rend) : 0)
182 p
->w_StringType
= NONE
;
187 register struct win
*p
;
191 p
->w_wrap
= nwin_default
.wrap
;
202 p
->w_bot
= p
->w_height
- 1;
206 p
->w_StringType
= NONE
;
207 bzero(p
->w_tabs
, p
->w_width
);
208 for (i
= 8; i
< p
->w_width
; i
+= 8)
210 p
->w_rend
= mchar_null
;
215 p
->w_bce
= nwin_default
.bce
;
219 /* adds max 22 bytes */
221 GetAnsiStatus(w
, buf
)
227 if (w
->w_state
== LIT
)
230 strcpy(p
, state_t_string
[w
->w_state
]);
232 if (w
->w_intermediate
)
235 if (w
->w_intermediate
> 0xff)
236 p
+= AddXChar(p
, w
->w_intermediate
>> 8);
237 p
+= AddXChar(p
, w
->w_intermediate
& 0xff);
240 if (w
->w_state
== ASTR
|| w
->w_state
== STRESC
)
241 sprintf(p
, "-%s", string_t_string
[w
->w_StringType
]);
253 p
->w_gr
= nwin_default
.gr
;
254 p
->w_c1
= nwin_default
.c1
;
255 SetCharsets(p
, "BBBB02");
256 if (nwin_default
.charset
)
257 SetCharsets(p
, nwin_default
.charset
);
270 for (i
= 0; i
< 4 && *s
; i
++, s
++)
272 p
->w_charsets
[i
] = ((*s
== 'B') ? ASCII
: *s
);
273 if (*s
&& *s
++ != '.')
274 p
->w_Charset
= s
[-1] - '0';
276 p
->w_CharsetR
= *s
- '0';
278 p
->w_FontL
= p
->w_charsets
[p
->w_Charset
];
279 p
->w_FontR
= p
->w_charsets
[p
->w_CharsetR
];
283 /*****************************************************************/
287 * Here comes the vt100 emulator
289 * - sets timestamp and flags activity in window.
290 * - record program output in window scrollback
291 * - translate program output for the display and put it into the obuf.
295 WriteString(wp
, buf
, len
)
309 WLogString(wp
, buf
, len
);
311 /* set global variables (yuck!) */
313 cols
= curr
->w_width
;
314 rows
= curr
->w_height
;
317 SetTimeout(&curr
->w_silenceev
, curr
->w_silencewait
* 1000);
319 if (curr
->w_monitor
== MON_ON
)
321 debug2("ACTIVITY %d %d\n", curr
->w_monitor
, curr
->w_bell
);
322 curr
->w_monitor
= MON_FOUND
;
325 if (cols
> 0 && rows
> 0)
329 c
= (unsigned char)*buf
++;
334 curr
->w_rend
.font
= curr
->w_FontL
; /* Default: GL */
337 /* The next part is only for speedup */
338 if (curr
->w_state
== LIT
&&
340 curr
->w_encoding
!= UTF8
&&
343 !is_dw_font(curr
->w_rend
.font
) &&
345 curr
->w_rend
.font
!= KANA
&& !curr
->w_mbcs
&&
349 curr
->w_rend
.font
!= '<' &&
351 c
>= ' ' && c
!= 0x7f &&
352 ((c
& 0x80) == 0 || ((c
>= 0xa0 || !curr
->w_c1
) && !curr
->w_gr
)) && !curr
->w_ss
&&
353 !curr
->w_insert
&& curr
->w_x
< cols
- 1)
355 register int currx
= curr
->w_x
;
358 while (currx
< cols
- 1)
363 c
= (unsigned char)*buf
++;
364 if (c
< ' ' || c
== 0x7f || ((c
& 0x80) && ((c
< 0xa0 && curr
->w_c1
) || curr
->w_gr
)))
370 MPutStr(curr
, imp
, currx
, &curr
->w_rend
, curr
->w_x
, curr
->w_y
);
371 LPutStr(&curr
->w_layer
, imp
, currx
, &curr
->w_rend
, curr
->w_x
, curr
->w_y
);
377 /* end of speedup code */
380 if (curr
->w_encoding
== UTF8
)
382 c
= FromUtf8(c
, &curr
->w_decodestate
);
393 debug1("read UNICODE %04x\n", c
);
398 switch (curr
->w_state
)
404 curr
->w_state
= PRINESC
;
414 curr
->w_state
= PRINCSI
;
419 curr
->w_state
= PRIN
;
426 curr
->w_state
= PRIN4
;
432 curr
->w_state
= PRIN
;
441 if (curr
->w_pdisplay
&& curr
->w_pdisplay
->d_printfd
>= 0)
443 close(curr
->w_pdisplay
->d_printfd
);
444 curr
->w_pdisplay
->d_printfd
= -1;
446 curr
->w_pdisplay
= 0;
453 curr
->w_state
= PRIN
;
461 curr
->w_state
= STRESC
;
464 /* special xterm hack: accept SetStatus sequence. Yucc! */
465 /* allow ^E for title escapes */
466 if (!(curr
->w_StringType
== OSC
&& c
< ' ' && c
!= '\005'))
467 if (!curr
->w_c1
|| c
!= ('\\' ^ 0xc0))
478 if (StringEnd() == 0 || len
<= 1)
480 /* check if somewhere a status is displayed */
481 for (cv
= curr
->w_layer
.l_cvlist
; cv
; cv
= cv
->c_lnext
)
483 display
= cv
->c_display
;
484 if (D_status
== STATUS_ON_WIN
)
489 if (len
> IOSIZE
+ 1)
491 curr
->w_outlen
= len
- 1;
492 bcopy(buf
, curr
->w_outbuf
, len
- 1);
493 return; /* wait till status is gone */
500 curr
->w_state
= ASTR
;
511 curr
->w_intermediate
= 0;
512 bzero((char *) curr
->w_args
, MAXARGS
* sizeof(int));
540 debug1("not special. c = %x\n", c
);
541 if (c
>= ' ' && c
<= '/')
543 if (curr
->w_intermediate
)
546 if (curr
->w_intermediate
== '$')
552 curr
->w_intermediate
= c
;
554 else if (c
>= '0' && c
<= '~')
556 DoESC(c
, curr
->w_intermediate
);
569 case '0': case '1': case '2': case '3': case '4':
570 case '5': case '6': case '7': case '8': case '9':
571 if (curr
->w_NumArgs
< MAXARGS
)
573 if (curr
->w_args
[curr
->w_NumArgs
] < 100000000)
574 curr
->w_args
[curr
->w_NumArgs
] =
575 10 * curr
->w_args
[curr
->w_NumArgs
] + (c
- '0');
580 if (curr
->w_NumArgs
< MAXARGS
)
586 if (c
>= '@' && c
<= '~')
588 if (curr
->w_NumArgs
< MAXARGS
)
590 DoCSI(c
, curr
->w_intermediate
);
591 if (curr
->w_state
!= PRIN
)
594 else if ((c
>= ' ' && c
<= '/') || (c
>= '<' && c
<= '?'))
595 curr
->w_intermediate
= curr
->w_intermediate
? -1 : c
;
607 if (c
<= ' ' || c
== 0x7f || (c
>= 0x80 && c
< 0xa0 && curr
->w_c1
))
614 curr
->w_intermediate
= 0;
616 if (curr
->w_autoaka
< 0)
623 if (c
>= 0x80 && c
< 0xa0 && curr
->w_c1
)
625 if ((curr
->w_FontR
& 0xf0) != 0x20
627 || curr
->w_encoding
== UTF8
638 case 0xc0 ^ 'N': /* SS2 */
639 case 0xc0 ^ 'O': /* SS3 */
643 if (curr
->w_autoaka
< 0)
646 curr
->w_intermediate
= 0;
647 bzero((char *) curr
->w_args
, MAXARGS
* sizeof(int));
664 if (c
< 0x80 || curr
->w_gr
== 0)
665 curr
->w_rend
.font
= curr
->w_FontL
;
667 else if (curr
->w_gr
== 2 && !curr
->w_ss
)
668 curr
->w_rend
.font
= curr
->w_FontE
;
671 curr
->w_rend
.font
= curr
->w_FontR
;
676 if (curr
->w_encoding
== UTF8
)
678 if (curr
->w_rend
.font
== '0')
680 struct mchar mc
, *mcp
;
682 debug1("SPECIAL %x\n", c
);
686 mcp
= recode_mchar(&mc
, 0, UTF8
);
687 debug2("%02x %02x\n", mcp
->image
, mcp
->font
);
688 c
= mcp
->image
| mcp
->font
<< 8;
690 curr
->w_rend
.font
= 0;
693 if (curr
->w_encoding
== UTF8
&& utf8_isdouble(c
))
696 if (curr
->w_encoding
== UTF8
&& c
>= 0x0300 && utf8_iscomb(c
))
705 ox
= curr
->w_width
- 1;
710 copy_mline2mchar(&omc
, &curr
->w_mlines
[oy
], ox
);
711 if (omc
.image
== 0xff && omc
.font
== 0xff)
716 copy_mline2mchar(&omc
, &curr
->w_mlines
[oy
], ox
);
722 utf8_handle_comb(c
, &omc
);
723 MFixLine(curr
, oy
, &omc
);
724 copy_mchar2mline(&omc
, &curr
->w_mlines
[oy
], ox
);
725 LPutChar(&curr
->w_layer
, &omc
, ox
, oy
);
726 LGotoPos(&curr
->w_layer
, curr
->w_x
, curr
->w_y
);
730 font
= curr
->w_rend
.font
;
734 if (font
== KANA
&& curr
->w_encoding
== SJIS
&& curr
->w_mbcs
== 0)
736 /* Lets see if it is the first byte of a kanji */
737 debug1("%x may be first of SJIS\n", c
);
738 if ((0x81 <= c
&& c
<= 0x9f) || (0xe0 <= c
&& c
<= 0xef))
746 if (font
== 031 && c
== 0x80 && !curr
->w_mbcs
)
747 font
= curr
->w_rend
.font
= 0;
748 if (is_dw_font(font
) && c
== ' ')
749 font
= curr
->w_rend
.font
= 0;
750 if (is_dw_font(font
) || curr
->w_mbcs
)
753 if (curr
->w_mbcs
== 0)
758 if (curr
->w_x
== cols
- 1)
760 curr
->w_x
+= curr
->w_wrap
? 1 : -1;
761 debug1("Patched w_x to %d\n", curr
->w_x
);
764 if (curr
->w_encoding
!= UTF8
)
769 if (font
== KANA
&& curr
->w_encoding
== SJIS
)
771 debug2("SJIS !! %x %x\n", c
, t
);
773 * SJIS -> EUC mapping:
775 * 81,82...9f -> 21,23...5d
776 * e0,e1...ef -> 5f,61...7d
780 * 9f-fc -> 21-7e (increment first byte!)
782 if (0x40 <= t
&& t
<= 0xfc && t
!= 0x7f)
784 if (c
<= 0x9f) c
= (c
- 0x81) * 2 + 0x21;
785 else c
= (c
- 0xc1) * 2 + 0x21;
786 if (t
<= 0x7e) t
-= 0x1f;
787 else if (t
<= 0x9e) t
-= 0x20;
789 curr
->w_rend
.font
= KANJI
;
793 /* Incomplete shift-jis - skip first byte */
797 debug2("SJIS after %x %x\n", c
, t
);
800 if (t
&& curr
->w_gr
&& font
!= 030 && font
!= 031)
811 # endif /* DW_CHARS */
812 if (font
== '<' && c
>= ' ')
814 font
= curr
->w_rend
.font
= 0;
818 else if (curr
->w_gr
&& curr
->w_encoding
!= UTF8
)
824 if (c
== 0x80 && font
== 0 && curr
->w_encoding
== GBK
)
828 if (c
< ' ' && font
!= 031)
832 if (c
< ' ') /* this is ugly but kanji support */
833 goto tryagain
; /* prevents nicer programming */
839 curr
->w_rend
.image
= c
;
841 if (curr
->w_encoding
== UTF8
)
842 curr
->w_rend
.font
= c
>> 8;
845 curr
->w_rend
.mbcs
= curr
->w_mbcs
;
847 if (curr
->w_x
< cols
- 1)
851 save_mline(&curr
->w_mlines
[curr
->w_y
], cols
);
852 MInsChar(curr
, &curr
->w_rend
, curr
->w_x
, curr
->w_y
);
853 LInsChar(&curr
->w_layer
, &curr
->w_rend
, curr
->w_x
, curr
->w_y
, &mline_old
);
858 MPutChar(curr
, &curr
->w_rend
, curr
->w_x
, curr
->w_y
);
859 LPutChar(&curr
->w_layer
, &curr
->w_rend
, curr
->w_x
, curr
->w_y
);
863 else if (curr
->w_x
== cols
- 1)
865 MPutChar(curr
, &curr
->w_rend
, curr
->w_x
, curr
->w_y
);
866 LPutChar(&curr
->w_layer
, &curr
->w_rend
, curr
->w_x
, curr
->w_y
);
872 MWrapChar(curr
, &curr
->w_rend
, curr
->w_y
, curr
->w_top
, curr
->w_bot
, curr
->w_insert
);
873 LWrapChar(&curr
->w_layer
, &curr
->w_rend
, curr
->w_y
, curr
->w_top
, curr
->w_bot
, curr
->w_insert
);
874 if (curr
->w_y
!= curr
->w_bot
&& curr
->w_y
!= curr
->w_height
- 1)
882 curr
->w_rend
.mbcs
= curr
->w_mbcs
= 0;
888 curr
->w_FontL
= curr
->w_charsets
[curr
->w_Charset
];
889 curr
->w_FontR
= curr
->w_charsets
[curr
->w_CharsetR
];
890 curr
->w_rend
.font
= curr
->w_FontL
;
891 LSetRendition(&curr
->w_layer
, &curr
->w_rend
);
900 if (!printcmd
&& curr
->w_state
== PRIN
)
905 WLogString(p
, buf
, len
)
912 if (logtstamp_on
&& p
->w_logsilence
>= logtstamp_after
* 2)
914 char *t
= MakeWinMsg(logtstamp_string
, p
, '%');
915 logfwrite(p
->w_log
, t
, strlen(t
)); /* long time no write */
918 if (logfwrite(p
->w_log
, buf
, len
) < 1)
920 WMsg(p
, errno
, "Error writing logfile");
943 case '\013': /* Vertical tab is the same as Line Feed */
947 WBell(curr
, visual_bell
);
953 case '\017': /* SI */
956 case '\016': /* SO */
965 DoESC(c
, intermediate
)
968 debug2("DoESC: %x - inter = %x\n", c
, intermediate
);
969 switch (intermediate
)
984 curr
->w_tabs
[curr
->w_x
] = 1;
986 case 'Z': /* jph: Identify as VT100 */
987 Report("\033[?%d;%dc", 1, 2);
990 SaveCursor(&curr
->w_saved
);
993 RestoreCursor(&curr
->w_saved
);
998 LKeypadMode(&curr
->w_layer
, 0);
999 LCursorkeysMode(&curr
->w_layer
, 0);
1001 WNewAutoFlow(curr
, 1);
1004 SetRendition(&mchar_null);
1006 ChangeScrollRegion(0, rows - 1);
1008 LGotoPos(&curr
->w_layer
, curr
->w_x
, curr
->w_y
);
1011 LKeypadMode(&curr
->w_layer
, curr
->w_keypad
= 1);
1013 WNewAutoFlow(curr
, 0);
1014 #endif /* !TIOCPKT */
1017 LKeypadMode(&curr
->w_layer
, curr
->w_keypad
= 0);
1019 WNewAutoFlow(curr
, 1);
1020 #endif /* !TIOCPKT */
1030 MapCharsetR(G1
); /* LS1R */
1034 MapCharsetR(G2
); /* LS2R */
1037 MapCharsetR(G3
); /* LS3R */
1040 if (curr
->w_charsets
[curr
->w_Charset
] != curr
->w_charsets
[G2
]
1041 || curr
->w_charsets
[curr
->w_CharsetR
] != curr
->w_charsets
[G2
])
1042 curr
->w_FontR
= curr
->w_FontL
= curr
->w_charsets
[curr
->w_ss
= G2
];
1047 if (curr
->w_charsets
[curr
->w_Charset
] != curr
->w_charsets
[G3
]
1048 || curr
->w_charsets
[curr
->w_CharsetR
] != curr
->w_charsets
[G3
])
1049 curr
->w_FontR
= curr
->w_FontL
= curr
->w_charsets
[curr
->w_ss
= G3
];
1054 case 'g': /* VBELL, private screen sequence */
1069 DesignateCharset(c
, G0
);
1072 DesignateCharset(c
, G1
);
1075 DesignateCharset(c
, G2
);
1078 DesignateCharset(c
, G3
);
1082 * ESC $ ( Fn: invoke multi-byte charset, Fn, to G0
1083 * ESC $ Fn: same as above. (old sequence)
1084 * ESC $ ) Fn: invoke multi-byte charset, Fn, to G1
1085 * ESC $ * Fn: invoke multi-byte charset, Fn, to G2
1086 * ESC $ + Fn: invoke multi-byte charset, Fn, to G3
1090 DesignateCharset(c
& 037, G0
);
1093 DesignateCharset(c
& 037, G1
);
1096 DesignateCharset(c
& 037, G2
);
1099 DesignateCharset(c
& 037, G3
);
1107 DoCSI(c
, intermediate
)
1108 int c
, intermediate
;
1110 register int i
, a1
= curr
->w_args
[0], a2
= curr
->w_args
[1];
1112 if (curr
->w_NumArgs
> MAXARGS
)
1113 curr
->w_NumArgs
= MAXARGS
;
1114 switch (intermediate
)
1131 LGotoPos(&curr
->w_layer
, --a2
, --a1
);
1134 if (curr
->w_autoaka
)
1135 curr
->w_autoaka
= a1
+ 1;
1138 if (a1
< 0 || a1
> 2)
1150 LGotoPos(&curr
->w_layer
, curr
->w_x
, curr
->w_y
);
1155 if (a1
< 0 || a1
> 2)
1160 ClearLineRegion(curr
->w_x
, cols
- 1);
1163 ClearLineRegion(0, curr
->w_x
);
1166 ClearLineRegion(0, cols
- 1);
1171 a1
= curr
->w_x
+ (a1
? a1
- 1 : 0);
1172 ClearLineRegion(curr
->w_x
, a1
< cols
? a1
: cols
- 1);
1175 CursorUp(a1
? a1
: 1);
1178 CursorDown(a1
? a1
: 1);
1181 CursorRight(a1
? a1
: 1);
1184 CursorLeft(a1
? a1
: 1);
1188 CursorDown(a1
? a1
: 1); /* positions cursor */
1192 CursorUp(a1
? a1
: 1); /* positions cursor */
1196 curr
->w_x
= a1
? a1
- 1 : 0;
1197 if (curr
->w_x
>= cols
)
1198 curr
->w_x
= cols
- 1;
1199 LGotoPos(&curr
->w_layer
, curr
->w_x
, curr
->w_y
);
1202 curr
->w_y
= a1
? a1
- 1 : 0;
1203 if (curr
->w_y
>= rows
)
1204 curr
->w_y
= rows
- 1;
1205 LGotoPos(&curr
->w_layer
, curr
->w_x
, curr
->w_y
);
1212 curr
->w_tabs
[curr
->w_x
] = 0;
1214 bzero(curr
->w_tabs
, cols
);
1221 if (a1
< 1 || a2
> rows
|| a1
>= a2
)
1223 curr
->w_top
= a1
- 1;
1224 curr
->w_bot
= a2
- 1;
1225 /* ChangeScrollRegion(curr->w_top, curr->w_bot); */
1228 curr
->w_y
= curr
->w_top
;
1232 curr
->w_y
= curr
->w_x
= 0;
1233 LGotoPos(&curr
->w_layer
, curr
->w_x
, curr
->w_y
);
1236 SaveCursor(&curr
->w_saved
);
1242 if (curr
->w_layer
.l_cvlist
)
1243 Report("\033[1t", 0, 0);
1245 Report("\033[2t", 0, 0);
1248 LRefreshAll(&curr
->w_layer
, 0);
1251 a1
= strlen(curr
->w_title
);
1252 if ((unsigned)(curr
->w_inlen
+ 5 + a1
) <= sizeof(curr
->w_inbuf
))
1254 bcopy("\033]l", curr
->w_inbuf
+ curr
->w_inlen
, 3);
1255 bcopy(curr
->w_title
, curr
->w_inbuf
+ curr
->w_inlen
+ 3, a1
);
1256 bcopy("\033\\", curr
->w_inbuf
+ curr
->w_inlen
+ 3 + a1
, 2);
1257 curr
->w_inlen
+= 5 + a1
;
1261 a1
= curr
->w_args
[2];
1265 a2
= curr
->w_height
;
1266 if (a1
> 10000 || a2
> 10000)
1268 WChangeSize(curr
, a1
, a2
);
1269 cols
= curr
->w_width
;
1270 rows
= curr
->w_height
;
1277 RestoreCursor(&curr
->w_saved
);
1292 InsertLine(a1
? a1
: 1);
1295 DeleteLine(a1
? a1
: 1);
1298 DeleteChar(a1
? a1
: 1);
1301 InsertChar(a1
? a1
: 1);
1309 case 'i': /* MC Media Control */
1314 if (a1
== 5) /* Report terminal status */
1315 Report("\033[0n", 0, 0);
1316 else if (a1
== 6) /* Report cursor position */
1317 Report("\033[%d;%dR", curr
->w_y
+ 1, curr
->w_x
+ 1);
1319 case 'c': /* Identify as VT100 */
1321 Report("\033[?%d;%dc", 1, 2);
1323 case 'x': /* decreqtparm */
1324 if (a1
== 0 || a1
== 1)
1325 Report("\033[%d;1;1;112;112;1;0x", a1
+ 2, 0);
1327 case 'p': /* obscure code from a 97801 term */
1328 if (a1
== 6 || a1
== 7)
1330 curr
->w_curinv
= 7 - a1
;
1331 LCursorVisibility(&curr
->w_layer
, curr
->w_curinv
? -1 : curr
->w_curvvis
);
1334 case 'S': /* code from a 97801 term / DEC vt400 */
1335 ScrollRegion(a1
? a1
: 1);
1337 case 'T': /* code from a 97801 term / DEC vt400 */
1338 case '^': /* SD as per ISO 6429 */
1339 ScrollRegion(a1
? -a1
: -1);
1344 for (a2
= 0; a2
< curr
->w_NumArgs
; a2
++)
1346 a1
= curr
->w_args
[a2
];
1347 debug2("\\E[?%d%c\n",a1
,c
);
1348 if (c
!= 'h' && c
!= 'l')
1353 case 1: /* CKM: cursor key mode */
1354 LCursorkeysMode(&curr
->w_layer
, curr
->w_cursorkeys
= i
);
1356 WNewAutoFlow(curr
, !i
);
1357 #endif /* !TIOCPKT */
1359 case 2: /* ANM: ansi/vt52 mode */
1364 if (curr
->w_encoding
)
1367 curr
->w_charsets
[0] = curr
->w_charsets
[1] =
1368 curr
->w_charsets
[2] = curr
->w_charsets
[2] =
1369 curr
->w_FontL
= curr
->w_FontR
= ASCII
;
1370 curr
->w_Charset
= 0;
1371 curr
->w_CharsetR
= 2;
1376 case 3: /* COLM: column mode */
1377 i
= (i
? Z0width
: Z1width
);
1381 WChangeSize(curr
, i
, curr
->w_height
);
1382 cols
= curr
->w_width
;
1383 rows
= curr
->w_height
;
1385 /* case 4: SCLM: scrolling mode */
1386 case 5: /* SCNM: screen mode */
1387 if (i
!= curr
->w_revvid
)
1388 WReverseVideo(curr
, i
);
1391 case 6: /* OM: origin mode */
1392 if ((curr
->w_origin
= i
) != 0)
1394 curr
->w_y
= curr
->w_top
;
1398 curr
->w_y
= curr
->w_x
= 0;
1399 LGotoPos(&curr
->w_layer
, curr
->w_x
, curr
->w_y
);
1401 case 7: /* AWM: auto wrap mode */
1404 /* case 8: ARM: auto repeat mode */
1405 /* case 9: INLM: interlace mode */
1406 case 9: /* X10 mouse tracking */
1407 curr
->w_mouse
= i
? 9 : 0;
1408 LMouseMode(&curr
->w_layer
, curr
->w_mouse
);
1410 /* case 10: EDM: edit mode */
1411 /* case 11: LTM: line transmit mode */
1412 /* case 13: SCFDM: space compression / field delimiting */
1413 /* case 14: TEM: transmit execution mode */
1414 /* case 16: EKEM: edit key execution mode */
1415 /* case 18: PFF: Printer term form feed */
1416 /* case 19: PEX: Printer extend screen / scroll. reg */
1417 case 25: /* TCEM: text cursor enable mode */
1418 curr
->w_curinv
= !i
;
1419 LCursorVisibility(&curr
->w_layer
, curr
->w_curinv
? -1 : curr
->w_curvvis
);
1421 /* case 34: RLM: Right to left mode */
1422 /* case 35: HEBM: hebrew keyboard map */
1423 /* case 36: HEM: hebrew encoding */
1424 /* case 38: TeK Mode */
1425 /* case 40: 132 col enable */
1426 /* case 42: NRCM: 7bit NRC character mode */
1427 /* case 44: margin bell enable */
1428 case 47: /* xterm-like alternate screen */
1429 case 1047: /* xterm-like alternate screen */
1430 case 1049: /* xterm-like alternate screen */
1435 if (!curr
->w_alt
.on
)
1436 SaveCursor(&curr
->w_alt
.cursor
);
1437 EnterAltScreen(curr
);
1441 LeaveAltScreen(curr
);
1442 RestoreCursor(&curr
->w_alt
.cursor
);
1445 curr
->w_saved
.on
= 0;
1446 LRefreshAll(&curr
->w_layer
, 0);
1447 LGotoPos(&curr
->w_layer
, curr
->w_x
, curr
->w_y
);
1452 SaveCursor(&curr
->w_saved
);
1454 RestoreCursor(&curr
->w_saved
);
1456 /* case 66: NKM: Numeric keypad appl mode */
1457 /* case 68: KBUM: Keyboard usage mode (data process) */
1458 case 1000: /* VT200 mouse tracking */
1459 case 1001: /* VT200 highlight mouse */
1460 case 1002: /* button event mouse*/
1461 case 1003: /* any event mouse*/
1462 curr
->w_mouse
= i
? a1
: 0;
1463 LMouseMode(&curr
->w_layer
, curr
->w_mouse
);
1471 case 'c': /* secondary DA */
1473 Report("\033[>%d;%d;0c", 83, nversion
); /* 83 == 'S' */
1485 curr
->w_StringType
= type
;
1486 curr
->w_stringp
= curr
->w_string
;
1487 curr
->w_state
= ASTR
;
1494 if (curr
->w_stringp
>= curr
->w_string
+ MAXSTR
- 1)
1495 curr
->w_state
= LIT
;
1497 *(curr
->w_stringp
)++ = c
;
1501 * Do string processing. Returns -1 if output should be suspended
1502 * until status is gone.
1511 curr
->w_state
= LIT
;
1512 *curr
->w_stringp
= '\0';
1513 switch (curr
->w_StringType
)
1515 case OSC
: /* special xterm compatibility hack */
1516 if (curr
->w_string
[0] == ';' || (p
= index(curr
->w_string
, ';')) == 0)
1518 typ
= atoi(curr
->w_string
);
1521 if (typ
== 83) /* 83 = 'S' */
1523 /* special execute commands sequence */
1524 char *args
[MAXARGS
];
1526 struct acluser
*windowuser
;
1528 windowuser
= *FindUserPtr(":window:");
1529 if (windowuser
&& Parse(p
, sizeof(curr
->w_string
) - (p
- curr
->w_string
), args
, argl
))
1531 for (display
= displays
; display
; display
= display
->d_next
)
1532 if (D_forecv
->c_layer
->l_bottom
== &curr
->w_layer
)
1533 break; /* found it */
1534 if (display
== 0 && curr
->w_layer
.l_cvlist
)
1535 display
= curr
->w_layer
.l_cvlist
->c_display
;
1538 EffectiveAclUser
= windowuser
;
1540 flayer
= fore
->w_savelayer
? fore
->w_savelayer
: &fore
->w_layer
;
1541 DoCommand(args
, argl
);
1542 EffectiveAclUser
= 0;
1550 if (typ
== 0 || typ
== 1 || typ
== 2 || typ
== 20 || typ
== 39 || typ
== 49)
1556 if (strcmp(curr
->w_xtermosc
[typ2
], p
))
1558 strncpy(curr
->w_xtermosc
[typ2
], p
, sizeof(curr
->w_xtermosc
[typ2
]) - 1);
1559 curr
->w_xtermosc
[typ2
][sizeof(curr
->w_xtermosc
[typ2
]) - 1] = 0;
1561 for (display
= displays
; display
; display
= display
->d_next
)
1565 if (D_forecv
->c_layer
->l_bottom
== &curr
->w_layer
)
1566 SetXtermOSC(typ2
, curr
->w_xtermosc
[typ2
]);
1567 if ((typ2
== 2 || typ2
== 3) && D_xtermosc
[typ2
])
1572 if (typ
!= 0 && typ
!= 2)
1575 if (typ
< 0 || typ
> 2)
1579 curr
->w_stringp
-= p
- curr
->w_string
;
1580 if (curr
->w_stringp
> curr
->w_string
)
1581 bcopy(p
, curr
->w_string
, curr
->w_stringp
- curr
->w_string
);
1582 *curr
->w_stringp
= '\0';
1585 if (curr
->w_hstatus
)
1587 if (strcmp(curr
->w_hstatus
, curr
->w_string
) == 0)
1588 break; /* not changed */
1589 free(curr
->w_hstatus
);
1590 curr
->w_hstatus
= 0;
1592 if (curr
->w_string
!= curr
->w_stringp
)
1593 curr
->w_hstatus
= SaveStr(curr
->w_string
);
1594 WindowChanged(curr
, 'h');
1598 for (display
= displays
; display
; display
= display
->d_next
)
1600 for (cv
= D_cvlist
; cv
; cv
= cv
->c_next
)
1601 if (cv
->c_layer
->l_bottom
== &curr
->w_layer
)
1603 if (cv
|| curr
->w_StringType
== GM
)
1604 MakeStatus(curr
->w_string
);
1608 LAY_DISPLAYS(&curr
->w_layer
, AddStr(curr
->w_string
));
1611 if (curr
->w_title
== curr
->w_akabuf
&& !*curr
->w_string
)
1613 ChangeAKA(curr
, curr
->w_string
, strlen(curr
->w_string
));
1614 if (!*curr
->w_string
)
1615 curr
->w_autoaka
= curr
->w_y
+ 1;
1626 curr
->w_pdisplay
= 0;
1628 /* find us a nice display to print on, fore prefered */
1629 display
= curr
->w_lastdisp
;
1630 if (!(display
&& curr
== D_fore
&& (printcmd
|| D_PO
)))
1631 for (display
= displays
; display
; display
= display
->d_next
)
1632 if (curr
== D_fore
&& (printcmd
|| D_PO
))
1637 for (cv
= curr
->w_layer
.l_cvlist
; cv
; cv
= cv
->c_lnext
)
1639 display
= cv
->c_display
;
1640 if (printcmd
|| D_PO
)
1646 if (!display
|| display
->d_next
|| !(printcmd
|| D_PO
))
1650 curr
->w_pdisplay
= display
;
1651 curr
->w_stringp
= curr
->w_string
;
1652 curr
->w_state
= PRIN
;
1653 if (printcmd
&& curr
->w_pdisplay
->d_printfd
< 0)
1654 curr
->w_pdisplay
->d_printfd
= printpipe(curr
, printcmd
);
1661 if (curr
->w_stringp
>= curr
->w_string
+ MAXSTR
- 1)
1663 *(curr
->w_stringp
)++ = c
;
1669 display
= curr
->w_pdisplay
;
1670 if (display
&& printcmd
)
1672 char *bp
= curr
->w_string
;
1673 int len
= curr
->w_stringp
- curr
->w_string
;
1675 while (len
&& display
->d_printfd
>= 0)
1677 r
= write(display
->d_printfd
, bp
, len
);
1680 WMsg(curr
, errno
, "printing aborted");
1681 close(display
->d_printfd
);
1682 display
->d_printfd
= -1;
1689 else if (display
&& curr
->w_stringp
> curr
->w_string
)
1692 AddStrn(curr
->w_string
, curr
->w_stringp
- curr
->w_string
);
1696 curr
->w_stringp
= curr
->w_string
;
1701 WNewAutoFlow(win
, on
)
1705 debug1("WNewAutoFlow: %d\n", on
);
1706 if (win
->w_flow
& FLOW_AUTOFLAG
)
1707 win
->w_flow
= FLOW_AUTOFLAG
| (FLOW_AUTO
|FLOW_NOW
) * on
;
1709 win
->w_flow
= (win
->w_flow
& ~FLOW_AUTO
) | FLOW_AUTO
* on
;
1710 LSetFlow(&win
->w_layer
, win
->w_flow
& FLOW_NOW
);
1717 DesignateCharset(c
, n
)
1722 if (c
== ('@' & 037)) /* map JIS 6226 to 0208 */
1727 if (curr
->w_charsets
[n
] != c
)
1729 curr
->w_charsets
[n
] = c
;
1730 if (curr
->w_Charset
== n
)
1733 curr
->w_rend
.font
= curr
->w_FontL
;
1734 LSetRendition(&curr
->w_layer
, &curr
->w_rend
);
1736 if (curr
->w_CharsetR
== n
)
1746 if (curr
->w_Charset
!= n
)
1748 curr
->w_Charset
= n
;
1749 curr
->w_FontL
= curr
->w_charsets
[n
];
1750 curr
->w_rend
.font
= curr
->w_FontL
;
1751 LSetRendition(&curr
->w_layer
, &curr
->w_rend
);
1760 if (curr
->w_CharsetR
!= n
)
1762 curr
->w_CharsetR
= n
;
1763 curr
->w_FontR
= curr
->w_charsets
[n
];
1772 struct cursor
*cursor
;
1775 cursor
->x
= curr
->w_x
;
1776 cursor
->y
= curr
->w_y
;
1777 cursor
->Rend
= curr
->w_rend
;
1779 cursor
->Charset
= curr
->w_Charset
;
1780 cursor
->CharsetR
= curr
->w_CharsetR
;
1781 bcopy((char *) curr
->w_charsets
, (char *) cursor
->Charsets
,
1787 RestoreCursor(cursor
)
1788 struct cursor
*cursor
;
1792 LGotoPos(&curr
->w_layer
, cursor
->x
, cursor
->y
);
1793 curr
->w_x
= cursor
->x
;
1794 curr
->w_y
= cursor
->y
;
1795 curr
->w_rend
= cursor
->Rend
;
1797 bcopy((char *) cursor
->Charsets
, (char *) curr
->w_charsets
,
1799 curr
->w_Charset
= cursor
->Charset
;
1800 curr
->w_CharsetR
= cursor
->CharsetR
;
1802 curr
->w_FontL
= curr
->w_charsets
[curr
->w_Charset
];
1803 curr
->w_FontR
= curr
->w_charsets
[curr
->w_CharsetR
];
1805 LSetRendition(&curr
->w_layer
, &curr
->w_rend
);
1815 else if (curr
->w_wrap
&& curr
->w_y
> 0)
1817 curr
->w_x
= cols
- 1;
1820 LGotoPos(&curr
->w_layer
, curr
->w_x
, curr
->w_y
);
1829 LGotoPos(&curr
->w_layer
, curr
->w_x
, curr
->w_y
);
1836 /* out_mode: 0=lf, 1=cr+lf */
1839 if (curr
->w_y
!= curr
->w_bot
) /* Don't scroll */
1841 if (curr
->w_y
< rows
-1)
1843 LGotoPos(&curr
->w_layer
, curr
->w_x
, curr
->w_y
);
1846 if (curr
->w_autoaka
> 1)
1848 MScrollV(curr
, 1, curr
->w_top
, curr
->w_bot
, CURR_BCE
);
1849 LScrollV(&curr
->w_layer
, 1, curr
->w_top
, curr
->w_bot
, CURR_BCE
);
1850 LGotoPos(&curr
->w_layer
, curr
->w_x
, curr
->w_y
);
1856 if (curr
->w_y
== curr
->w_top
)
1858 MScrollV(curr
, -1, curr
->w_top
, curr
->w_bot
, CURR_BCE
);
1859 LScrollV(&curr
->w_layer
, -1, curr
->w_top
, curr
->w_bot
, CURR_BCE
);
1860 LGotoPos(&curr
->w_layer
, curr
->w_x
, curr
->w_y
);
1862 else if (curr
->w_y
> 0)
1870 register int y
= curr
->w_y
, x
= curr
->w_x
;
1876 save_mline(&curr
->w_mlines
[y
], cols
);
1877 MScrollH(curr
, -n
, y
, x
, curr
->w_width
- 1, CURR_BCE
);
1878 LScrollH(&curr
->w_layer
, -n
, y
, x
, curr
->w_width
- 1, CURR_BCE
, &mline_old
);
1879 LGotoPos(&curr
->w_layer
, x
, y
);
1886 register int y
= curr
->w_y
, x
= curr
->w_x
;
1890 save_mline(&curr
->w_mlines
[y
], cols
);
1891 MScrollH(curr
, n
, y
, x
, curr
->w_width
- 1, CURR_BCE
);
1892 LScrollH(&curr
->w_layer
, n
, y
, x
, curr
->w_width
- 1, CURR_BCE
, &mline_old
);
1893 LGotoPos(&curr
->w_layer
, x
, y
);
1900 if (curr
->w_y
< curr
->w_top
|| curr
->w_y
> curr
->w_bot
)
1902 if (n
> curr
->w_bot
- curr
->w_y
+ 1)
1903 n
= curr
->w_bot
- curr
->w_y
+ 1;
1904 MScrollV(curr
, n
, curr
->w_y
, curr
->w_bot
, CURR_BCE
);
1905 LScrollV(&curr
->w_layer
, n
, curr
->w_y
, curr
->w_bot
, CURR_BCE
);
1906 LGotoPos(&curr
->w_layer
, curr
->w_x
, curr
->w_y
);
1913 if (curr
->w_y
< curr
->w_top
|| curr
->w_y
> curr
->w_bot
)
1915 if (n
> curr
->w_bot
- curr
->w_y
+ 1)
1916 n
= curr
->w_bot
- curr
->w_y
+ 1;
1917 MScrollV(curr
, -n
, curr
->w_y
, curr
->w_bot
, CURR_BCE
);
1918 LScrollV(&curr
->w_layer
, -n
, curr
->w_y
, curr
->w_bot
, CURR_BCE
);
1919 LGotoPos(&curr
->w_layer
, curr
->w_x
, curr
->w_y
);
1926 MScrollV(curr
, n
, curr
->w_top
, curr
->w_bot
, CURR_BCE
);
1927 LScrollV(&curr
->w_layer
, n
, curr
->w_top
, curr
->w_bot
, CURR_BCE
);
1928 LGotoPos(&curr
->w_layer
, curr
->w_x
, curr
->w_y
);
1935 register int x
= curr
->w_x
;
1942 if (curr
->w_tabs
[x
] && x
< cols
- 1)
1944 while (x
< cols
- 1 && !curr
->w_tabs
[x
])
1947 LGotoPos(&curr
->w_layer
, curr
->w_x
, curr
->w_y
);
1953 register int x
= curr
->w_x
;
1955 if (curr
->w_tabs
[x
] && x
> 0)
1957 while (x
> 0 && !curr
->w_tabs
[x
])
1960 LGotoPos(&curr
->w_layer
, curr
->w_x
, curr
->w_y
);
1966 LClearArea(&curr
->w_layer
, 0, 0, curr
->w_width
- 1, curr
->w_height
- 1, CURR_BCE
, 1);
1968 MScrollV(curr
, curr
->w_height
, 0, curr
->w_height
- 1, CURR_BCE
);
1970 MClearArea(curr
, 0, 0, curr
->w_width
- 1, curr
->w_height
- 1, CURR_BCE
);
1977 register int y
= curr
->w_y
, x
= curr
->w_x
;
1979 LClearArea(&curr
->w_layer
, 0, 0, x
, y
, CURR_BCE
, 1);
1980 MClearArea(curr
, 0, 0, x
, y
, CURR_BCE
);
1981 RestorePosRendition();
1987 register int y
= curr
->w_y
, x
= curr
->w_x
;
1989 if (x
== 0 && y
== 0)
1992 RestorePosRendition();
1995 LClearArea(&curr
->w_layer
, x
, y
, cols
- 1, rows
- 1, CURR_BCE
, 1);
1996 MClearArea(curr
, x
, y
, cols
- 1, rows
- 1, CURR_BCE
);
1997 RestorePosRendition();
2001 ClearLineRegion(from
, to
)
2004 register int y
= curr
->w_y
;
2005 LClearArea(&curr
->w_layer
, from
, y
, to
, y
, CURR_BCE
, 1);
2006 MClearArea(curr
, from
, y
, to
, y
, CURR_BCE
);
2007 RestorePosRendition();
2014 register int x
= curr
->w_x
;
2021 if ((curr
->w_x
+= n
) >= cols
)
2022 curr
->w_x
= cols
- 1;
2023 LGotoPos(&curr
->w_layer
, curr
->w_x
, curr
->w_y
);
2030 if (curr
->w_y
< curr
->w_top
) /* if above scrolling rgn, */
2032 if ((curr
->w_y
-= n
) < 0) /* ignore its limits */
2036 if ((curr
->w_y
-= n
) < curr
->w_top
)
2037 curr
->w_y
= curr
->w_top
;
2038 LGotoPos(&curr
->w_layer
, curr
->w_x
, curr
->w_y
);
2045 if (curr
->w_y
> curr
->w_bot
) /* if below scrolling rgn, */
2047 if ((curr
->w_y
+= n
) > rows
- 1) /* ignore its limits */
2048 curr
->w_y
= rows
- 1;
2051 if ((curr
->w_y
+= n
) > curr
->w_bot
)
2052 curr
->w_y
= curr
->w_bot
;
2053 LGotoPos(&curr
->w_layer
, curr
->w_x
, curr
->w_y
);
2060 if ((curr
->w_x
-= n
) < 0)
2062 LGotoPos(&curr
->w_layer
, curr
->w_x
, curr
->w_y
);
2071 for (i
= 0; i
< curr
->w_NumArgs
; ++i
)
2073 switch (curr
->w_args
[i
])
2075 /* case 2: KAM: Lock keyboard */
2076 case 4: /* IRM: Insert mode */
2077 curr
->w_insert
= on
;
2078 LAY_DISPLAYS(&curr
->w_layer
, InsertMode(on
));
2080 /* case 12: SRM: Echo mode on */
2081 case 20: /* LNM: Linefeed mode */
2082 curr
->w_autolf
= on
;
2085 curr
->w_curvvis
= !on
;
2086 LCursorVisibility(&curr
->w_layer
, curr
->w_curinv
? -1 : curr
->w_curvvis
);
2094 static char rendlist
[] =
2096 ~((1 << NATTR
) - 1), A_BD
, A_DI
, A_SO
, A_US
, A_BL
, 0, A_RV
, 0, 0,
2097 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2098 0, 0, ~(A_BD
|A_SO
|A_DI
), ~A_SO
, ~A_US
, ~A_BL
, 0, ~A_RV
2105 register int j
, i
= 0, a
= curr
->w_rend
.attr
, c
= curr
->w_rend
.color
;
2107 int cx
= curr
->w_rend
.colorx
;
2110 register int j
, i
= 0, a
= curr
->w_rend
.attr
;
2115 j
= curr
->w_args
[i
];
2117 if ((j
== 38 || j
== 48) && i
+ 2 < curr
->w_NumArgs
&& curr
->w_args
[i
+ 1] == 5)
2122 jj
= curr
->w_args
[i
];
2123 if (jj
< 0 || jj
> 255)
2128 c
= (c
& 0xf0) | ((jj
& 0x0f) ^ 9);
2130 if (jj
>= 8 && jj
< 16)
2134 a
= (a
& 0xbf) | (jj
& 8 ? 0x40 : 0);
2135 cx
= (cx
& 0xf0) | (jj
>> 4 & 0x0f);
2139 c
= (c
& 0x0f) | ((jj
& 0x0f) ^ 9) << 4;
2141 if (jj
>= 8 && jj
< 16)
2145 cx
= (cx
& 0x0f) | (jj
& 0xf0);
2149 jj
= color256to16(jj
) + 30;
2152 j
= j
== 38 ? jj
: jj
+ 10;
2156 if (j
== 0 || (j
>= 30 && j
<= 39 && j
!= 38))
2158 if (j
== 0 || (j
>= 40 && j
<= 49 && j
!= 48))
2160 if (j
>= 90 && j
<= 97)
2162 if (j
>= 100 && j
<= 107)
2165 if (j
>= 90 && j
<= 97)
2167 if (j
>= 100 && j
<= 107)
2169 if (j
>= 30 && j
<= 39 && j
!= 38)
2170 c
= (c
& 0xf0) | ((j
- 30) ^ 9);
2171 else if (j
>= 40 && j
<= 49 && j
!= 48)
2172 c
= (c
& 0x0f) | (((j
- 40) ^ 9) << 4);
2176 if (j
== 0 || (j
>= 30 && j
<= 39 && j
!= 38))
2178 if (j
== 0 || (j
>= 40 && j
<= 49 && j
!= 48))
2182 if (j
< 0 || j
>= (int)(sizeof(rendlist
)/sizeof(*rendlist
)))
2185 if (j
& (1 << NATTR
))
2190 while (++i
< curr
->w_NumArgs
);
2191 curr
->w_rend
.attr
= a
;
2193 curr
->w_rend
.color
= c
;
2195 curr
->w_rend
.colorx
= cx
;
2198 LSetRendition(&curr
->w_layer
, &curr
->w_rend
);
2205 register unsigned char *p
, *ep
;
2207 LClearAll(&curr
->w_layer
, 1);
2208 curr
->w_y
= curr
->w_x
= 0;
2209 for (i
= 0; i
< rows
; ++i
)
2211 clear_mline(&curr
->w_mlines
[i
], 0, cols
+ 1);
2212 p
= curr
->w_mlines
[i
].image
;
2217 LRefreshAll(&curr
->w_layer
, 1);
2222 * Ugly autoaka hack support:
2223 * ChangeAKA() sets a new aka
2224 * FindAKA() searches for an autoaka match
2235 for (i
= 0; l
> 0; l
--)
2237 if (p
->w_akachange
+ i
== p
->w_akabuf
+ sizeof(p
->w_akabuf
) - 1)
2239 c
= (unsigned char)*s
++;
2242 if (c
< 32 || c
== 127 || (c
>= 128 && c
< 160 && p
->w_c1
))
2244 p
->w_akachange
[i
++] = c
;
2246 p
->w_akachange
[i
] = 0;
2247 p
->w_title
= p
->w_akachange
;
2248 if (p
->w_akachange
!= p
->w_akabuf
)
2249 if (p
->w_akachange
[0] == 0 || p
->w_akachange
[-1] == ':')
2250 p
->w_title
= p
->w_akabuf
+ strlen(p
->w_akabuf
) + 1;
2251 WindowChanged(p
, 't');
2252 WindowChanged((struct win
*)0, 'w');
2253 WindowChanged((struct win
*)0, 'W');
2259 register unsigned char *cp
, *line
;
2260 register struct win
*wp
= curr
;
2261 register int len
= strlen(wp
->w_akabuf
);
2264 y
= (wp
->w_autoaka
> 0 && wp
->w_autoaka
<= wp
->w_height
) ? wp
->w_autoaka
- 1 : wp
->w_y
;
2267 cp
= line
= wp
->w_mlines
[y
].image
;
2268 if (wp
->w_autoaka
> 0 && *wp
->w_akabuf
!= '\0')
2272 if (cp
- line
>= cols
- len
)
2274 if (++y
== wp
->w_autoaka
&& y
< rows
)
2278 if (strncmp((char *)cp
, wp
->w_akabuf
, len
) == 0)
2284 for (len
= cols
- (cp
- line
); len
&& *cp
== ' '; len
--, cp
++)
2288 if (wp
->w_autoaka
> 0 && (*cp
== '!' || *cp
== '%' || *cp
== '^'))
2293 while (len
&& *cp
!= ' ')
2299 ChangeAKA(wp
, (char *)line
, cp
- line
);
2306 RestorePosRendition()
2308 LGotoPos(&curr
->w_layer
, curr
->w_x
, curr
->w_y
);
2309 LSetRendition(&curr
->w_layer
, &curr
->w_rend
);
2312 /* Send a terminal report as if it were typed. */
2319 char rbuf
[40]; /* enough room for all replys */
2321 sprintf(rbuf
, fmt
, n1
, n2
);
2327 if ((unsigned)(curr
->w_pwin
->p_inlen
+ len
) <= sizeof(curr
->w_pwin
->p_inbuf
))
2329 bcopy(rbuf
, curr
->w_pwin
->p_inbuf
+ curr
->w_pwin
->p_inlen
, len
);
2330 curr
->w_pwin
->p_inlen
+= len
;
2336 if ((unsigned)(curr
->w_inlen
+ len
) <= sizeof(curr
->w_inbuf
))
2338 bcopy(rbuf
, curr
->w_inbuf
+ curr
->w_inlen
, len
);
2339 curr
->w_inlen
+= len
;
2347 *====================================================================*
2348 *====================================================================*
2351 /**********************************************************************
2363 struct mline
*ml
= &p
->w_mlines
[y
];
2364 if (mc
->attr
&& ml
->attr
== null
)
2366 if ((ml
->attr
= (unsigned char *)calloc(p
->w_width
+ 1, 1)) == 0)
2369 mc
->attr
= p
->w_rend
.attr
= 0;
2370 WMsg(p
, 0, "Warning: no space for attr - turned off");
2374 if (mc
->font
&& ml
->font
== null
)
2376 if ((ml
->font
= (unsigned char *)calloc(p
->w_width
+ 1, 1)) == 0)
2379 p
->w_FontL
= p
->w_charsets
[p
->w_ss
? p
->w_ss
: p
->w_Charset
] = 0;
2380 p
->w_FontR
= p
->w_charsets
[p
->w_ss
? p
->w_ss
: p
->w_CharsetR
] = 0;
2381 mc
->font
= p
->w_rend
.font
= 0;
2382 WMsg(p
, 0, "Warning: no space for font - turned off");
2387 if (mc
->color
&& ml
->color
== null
)
2389 if ((ml
->color
= (unsigned char *)calloc(p
->w_width
+ 1, 1)) == 0)
2392 mc
->color
= p
->w_rend
.color
= 0;
2393 WMsg(p
, 0, "Warning: no space for color - turned off");
2397 if (mc
->colorx
&& ml
->colorx
== null
)
2399 if ((ml
->colorx
= (unsigned char *)calloc(p
->w_width
+ 1, 1)) == 0)
2402 mc
->colorx
= p
->w_rend
.colorx
= 0;
2403 WMsg(p
, 0, "Warning: no space for extended colors - turned off");
2410 /*****************************************************************/
2413 # define MKillDwRight(p, ml, x) \
2414 if (dw_right(ml, x, p->w_encoding)) \
2417 copy_mchar2mline(&mchar_blank, ml, x - 1); \
2418 copy_mchar2mline(&mchar_blank, ml, x); \
2421 # define MKillDwLeft(p, ml, x) \
2422 if (dw_left(ml, x, p->w_encoding)) \
2424 copy_mchar2mline(&mchar_blank, ml, x); \
2425 copy_mchar2mline(&mchar_blank, ml, x + 1); \
2428 # define MKillDwRight(p, ml, x) ;
2429 # define MKillDwLeft(p, ml, x) ;
2433 MScrollH(p
, n
, y
, xs
, xe
, bce
)
2435 int n
, y
, xs
, xe
, bce
;
2441 ml
= &p
->w_mlines
[y
];
2442 MKillDwRight(p
, ml
, xs
);
2443 MKillDwLeft(p
, ml
, xe
);
2446 if (xe
- xs
+ 1 > n
)
2448 MKillDwRight(p
, ml
, xs
+ n
);
2449 bcopy_mline(ml
, xs
+ n
, xs
, xe
+ 1 - xs
- n
);
2453 clear_mline(ml
, xe
+ 1 - n
, n
);
2456 MBceLine(p
, y
, xe
+ 1 - n
, n
, bce
);
2462 if (xe
- xs
+ 1 > n
)
2464 MKillDwLeft(p
, ml
, xe
- n
);
2465 bcopy_mline(ml
, xs
, xs
+ n
, xe
+ 1 - xs
- n
);
2469 clear_mline(ml
, xs
, n
);
2472 MBceLine(p
, y
, xs
, n
, bce
);
2478 MScrollV(p
, n
, ys
, ye
, bce
)
2483 struct mline tmp
[256];
2492 MScrollV(p
, n
- 256, ys
, ye
, bce
);
2495 if (ye
- ys
+ 1 < n
)
2500 ye
= MFindUsedLine(p
, ye
, ys
);
2501 if (ye
- ys
+ 1 < n
)
2508 ml
= p
->w_mlines
+ ys
;
2509 for (i
= ys
; i
< ys
+ n
; i
++, ml
++)
2513 WAddLineToHist(p
, ml
);
2515 if (ml
->attr
!= null
)
2519 if (ml
->font
!= null
)
2524 if (ml
->color
!= null
)
2528 if (ml
->colorx
!= null
)
2533 bclear((char *)ml
->image
, p
->w_width
+ 1);
2536 MBceLine(p
, i
, 0, p
->w_width
, bce
);
2539 /* switch 'em over */
2540 cnt1
= n
* sizeof(struct mline
);
2541 cnt2
= (ye
- ys
+ 1 - n
) * sizeof(struct mline
);
2543 Scroll((char *)(p
->w_mlines
+ ys
), cnt1
, cnt2
, (char *)tmp
);
2549 MScrollV(p
, n
+ 256, ys
, ye
, bce
);
2553 if (ye
- ys
+ 1 < n
)
2556 ml
= p
->w_mlines
+ ye
;
2558 for (i
= ye
; i
> ye
- n
; i
--, ml
--)
2560 if (ml
->attr
!= null
)
2564 if (ml
->font
!= null
)
2569 if (ml
->color
!= null
)
2573 if (ml
->colorx
!= null
)
2578 bclear((char *)ml
->image
, p
->w_width
+ 1);
2581 MBceLine(p
, i
, 0, p
->w_width
, bce
);
2584 cnt1
= n
* sizeof(struct mline
);
2585 cnt2
= (ye
- ys
+ 1 - n
) * sizeof(struct mline
);
2587 Scroll((char *)(p
->w_mlines
+ ys
), cnt2
, cnt1
, (char *)tmp
);
2592 Scroll(cp
, cnt1
, cnt2
, tmp
)
2600 bcopy(cp
, tmp
, cnt1
);
2601 bcopy(cp
+ cnt1
, cp
, cnt2
);
2602 bcopy(tmp
, cp
+ cnt2
, cnt1
);
2606 bcopy(cp
+ cnt1
, tmp
, cnt2
);
2607 bcopy(cp
, cp
+ cnt2
, cnt1
);
2608 bcopy(tmp
, cp
, cnt2
);
2613 MClearArea(p
, xs
, ys
, xe
, ye
, bce
)
2615 int xs
, ys
, xe
, ye
, bce
;
2621 /* Check for zero-height window */
2622 if (ys
< 0 || ye
< ys
)
2625 /* check for magic margin condition */
2626 if (xs
>= p
->w_width
)
2627 xs
= p
->w_width
- 1;
2628 if (xe
>= p
->w_width
)
2629 xe
= p
->w_width
- 1;
2631 MKillDwRight(p
, p
->w_mlines
+ ys
, xs
);
2632 MKillDwLeft(p
, p
->w_mlines
+ ye
, xe
);
2634 ml
= p
->w_mlines
+ ys
;
2635 for (y
= ys
; y
<= ye
; y
++, ml
++)
2637 xxe
= (y
== ye
) ? xe
: p
->w_width
- 1;
2640 clear_mline(ml
, xs
, n
);
2643 MBceLine(p
, y
, xs
, xs
+ n
- 1, bce
);
2650 MInsChar(p
, c
, x
, y
)
2658 ASSERT(x
>= 0 && x
< p
->w_width
);
2660 ml
= p
->w_mlines
+ y
;
2661 n
= p
->w_width
- x
- 1;
2662 MKillDwRight(p
, ml
, x
);
2665 MKillDwRight(p
, ml
, p
->w_width
- 1);
2666 bcopy_mline(ml
, x
, x
+ 1, n
);
2668 copy_mchar2mline(c
, ml
, x
);
2674 MKillDwRight(p
, ml
, p
->w_width
- 1);
2675 bcopy_mline(ml
, x
+ 1, x
+ 2, n
);
2677 copy_mchar2mline(c
, ml
, x
+ 1);
2678 ml
->image
[x
+ 1] = c
->mbcs
;
2680 if (p
->w_encoding
!= UTF8
)
2681 ml
->font
[x
+ 1] |= 0x80;
2682 else if (p
->w_encoding
== UTF8
&& c
->mbcs
)
2683 ml
->font
[x
+ 1] = c
->mbcs
;
2685 ml
->font
[x
+ 1] |= 0x80;
2692 MPutChar(p
, c
, x
, y
)
2700 ml
= &p
->w_mlines
[y
];
2701 MKillDwRight(p
, ml
, x
);
2702 MKillDwLeft(p
, ml
, x
);
2703 copy_mchar2mline(c
, ml
, x
);
2707 MKillDwLeft(p
, ml
, x
+ 1);
2708 copy_mchar2mline(c
, ml
, x
+ 1);
2709 ml
->image
[x
+ 1] = c
->mbcs
;
2711 if (p
->w_encoding
!= UTF8
)
2712 ml
->font
[x
+ 1] |= 0x80;
2713 else if (p
->w_encoding
== UTF8
&& c
->mbcs
)
2714 ml
->font
[x
+ 1] = c
->mbcs
;
2716 ml
->font
[x
+ 1] |= 0x80;
2724 MWrapChar(p
, c
, y
, top
, bot
, ins
)
2734 bce
= rend_getbg(c
);
2739 ml
= &p
->w_mlines
[y
];
2740 copy_mchar2mline(&mchar_null
, ml
, p
->w_width
);
2742 MScrollV(p
, 1, top
, bot
, bce
);
2743 else if (y
< p
->w_height
- 1)
2746 MInsChar(p
, c
, 0, y
);
2748 MPutChar(p
, c
, 0, y
);
2752 MPutStr(p
, s
, n
, r
, x
, y
)
2766 ml
= &p
->w_mlines
[y
];
2767 MKillDwRight(p
, ml
, x
);
2768 MKillDwLeft(p
, ml
, x
+ n
- 1);
2769 bcopy(s
, (char *)ml
->image
+ x
, n
);
2771 for (i
= n
; i
-- > 0;)
2775 for (i
= n
; i
-- > 0;)
2780 for (i
= n
; i
-- > 0;)
2784 for (i
= n
; i
-- > 0;)
2792 MBceLine(p
, y
, xs
, xe
, bce
)
2801 rend_setbg(&mc
, bce
);
2802 MFixLine(p
, y
, &mc
);
2803 ml
= p
->w_mlines
+ y
;
2806 for (x
= xs
; x
<= xe
; x
++)
2807 ml
->attr
[x
] = mc
.attr
;
2810 for (x
= xs
; x
<= xe
; x
++)
2811 ml
->color
[x
] = mc
.color
;
2814 for (x
= xs
; x
<= xe
; x
++)
2815 ml
->colorx
[x
] = mc
.colorx
;
2823 WAddLineToHist(wp
, ml
)
2827 register unsigned char *q
, *o
;
2830 if (wp
->w_histheight
== 0)
2832 hml
= &wp
->w_hlines
[wp
->w_histidx
];
2833 q
= ml
->image
; ml
->image
= hml
->image
; hml
->image
= q
;
2835 q
= ml
->attr
; o
= hml
->attr
; hml
->attr
= q
; ml
->attr
= null
;
2840 q
= ml
->font
; o
= hml
->font
; hml
->font
= q
; ml
->font
= null
;
2846 q
= ml
->color
; o
= hml
->color
; hml
->color
= q
; ml
->color
= null
;
2850 q
= ml
->colorx
; o
= hml
->colorx
; hml
->colorx
= q
; ml
->colorx
= null
;
2856 if (++wp
->w_histidx
>= wp
->w_histheight
)
2862 MFindUsedLine(p
, ye
, ys
)
2867 struct mline
*ml
= p
->w_mlines
+ ye
;
2869 debug2("MFindUsedLine: %d %d\n", ye
, ys
);
2870 for (y
= ye
; y
>= ys
; y
--, ml
--)
2872 if (bcmp((char*)ml
->image
, blank
, p
->w_width
))
2874 if (ml
->attr
!= null
&& bcmp((char*)ml
->attr
, null
, p
->w_width
))
2877 if (ml
->color
!= null
&& bcmp((char*)ml
->color
, null
, p
->w_width
))
2880 if (ml
->colorx
!= null
&& bcmp((char*)ml
->colorx
, null
, p
->w_width
))
2885 debug1("MFindUsedLine returning %d\n", y
);
2891 *====================================================================*
2892 *====================================================================*
2896 * Tricky: send only one bell even if the window is displayed
2905 for (display
= displays
; display
; display
= display
->d_next
)
2907 for (cv
= D_cvlist
; cv
; cv
= cv
->c_next
)
2908 if (cv
->c_layer
->l_bottom
== &p
->w_layer
)
2912 else if (cv
&& D_VB
)
2915 p
->w_bell
= visual
? BELL_VISUAL
: BELL_FOUND
;
2920 * This should be reverse video.
2921 * Only change video if window is fore.
2922 * Because it is used in some termcaps to emulate
2923 * a visual bell we do this hack here.
2924 * (screen uses \Eg as special vbell sequence)
2927 WReverseVideo(p
, on
)
2932 for (cv
= p
->w_layer
.l_cvlist
; cv
; cv
= cv
->c_lnext
)
2934 display
= cv
->c_display
;
2938 if (!on
&& p
->w_revvid
&& !D_CVR
)
2943 p
->w_bell
= BELL_VISUAL
;
2954 extern struct layer
*flayer
;
2955 struct layer
*oldflayer
= flayer
;
2956 flayer
= &p
->w_layer
;
2957 LMsg(err
, "%s", str
);
2962 WChangeSize(p
, w
, h
)
2969 if (p
->w_layer
.l_cvlist
== 0)
2971 /* window not displayed -> works always */
2972 ChangeWindowSize(p
, w
, h
, p
->w_histheight
);
2975 for (cv
= p
->w_layer
.l_cvlist
; cv
; cv
= cv
->c_lnext
)
2977 display
= cv
->c_display
;
2979 continue; /* change only fore */
2982 if (D_CZ0
&& (w
== Z0width
|| w
== Z1width
))
2985 if (cv
== 0 && wok
== 0) /* can't change any display */
2989 ChangeWindowSize(p
, w
, h
, p
->w_histheight
);
2990 for (display
= displays
; display
; display
= display
->d_next
)
2994 if (D_cvlist
&& D_cvlist
->c_next
== 0)
2995 ResizeDisplay(w
, h
);
2997 ResizeDisplay(w
, D_height
);
2998 ResizeLayersToCanvases(); /* XXX Hmm ? */
3001 for (cv
= D_cvlist
; cv
; cv
= cv
->c_next
)
3002 if (cv
->c_layer
->l_bottom
== &p
->w_layer
)
3010 WindowChangedCheck(s
, what
, hp
)
3019 if (*s
++ != (hp
? '%' : '\005'))
3024 while (*s
>= '0' && *s
<= '9')
3033 if (*s
== what
|| ((*s
| l
) == what
) || what
== 'd')
3044 WindowChanged(p
, what
)
3048 int inwstr
, inhstr
, inlstr
;
3049 int inwstrh
= 0, inhstrh
= 0, inlstrh
= 0;
3051 struct display
*olddisplay
= display
;
3054 inwstr
= inhstr
= 0;
3058 WindowChanged((struct win
*)0, 'w'|0x100);
3059 WindowChanged((struct win
*)0, 'W'|0x100);
3064 inwstr
= WindowChangedCheck(captionstring
, what
, &inwstrh
);
3065 inhstr
= WindowChangedCheck(hstatusstring
, what
, &inhstrh
);
3066 inlstr
= WindowChangedCheck(wliststr
, what
, &inlstrh
);
3070 inwstr
= inhstr
= 0;
3076 for (display
= displays
; display
; display
= display
->d_next
)
3080 for (cv
= D_cvlist
; cv
; cv
= cv
->c_next
)
3082 if (inlstr
|| (inlstrh
&& p
&& p
->w_hstatus
&& *p
->w_hstatus
&& WindowChangedCheck(p
->w_hstatus
, what
, (int *)0)))
3083 WListUpdatecv(cv
, (struct win
*)0);
3084 p
= Layer2Window(cv
->c_layer
);
3085 if (inwstr
|| (inwstrh
&& p
&& p
->w_hstatus
&& *p
->w_hstatus
&& WindowChangedCheck(p
->w_hstatus
, what
, (int *)0)))
3086 if (cv
->c_ye
+ 1 < D_height
)
3087 RefreshLine(cv
->c_ye
+ 1, 0, D_width
- 1, 0);
3090 if (inhstr
|| (inhstrh
&& p
&& p
->w_hstatus
&& *p
->w_hstatus
&& WindowChangedCheck(p
->w_hstatus
, what
, (int *)0)))
3092 if (ox
!= -1 && oy
!= -1)
3095 display
= olddisplay
;
3099 if (p
->w_hstatus
&& *p
->w_hstatus
&& (inwstrh
|| inhstrh
|| inlstrh
) && WindowChangedCheck(p
->w_hstatus
, what
, (int *)0))
3105 if (!inwstr
&& !inhstr
&& !inlstr
)
3107 for (display
= displays
; display
; display
= display
->d_next
)
3112 for (cv
= D_cvlist
; cv
; cv
= cv
->c_next
)
3115 WListUpdatecv(cv
, p
);
3116 if (Layer2Window(cv
->c_layer
) != p
)
3119 if (inwstr
&& cv
->c_ye
+ 1 < D_height
)
3120 RefreshLine(cv
->c_ye
+ 1, 0, D_width
- 1, 0);
3122 if (got
&& inhstr
&& p
== D_fore
)
3124 if (ox
!= -1 && oy
!= -1)
3127 display
= olddisplay
;