1
/* Copyright (c) 1993-2002
2
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4
* Copyright (c) 1987 Oliver Laumann
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2, or (at your option)
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program (see the file COPYING); if not, write to the
18
* Free Software Foundation, Inc.,
19
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21
****************************************************************
24
#include <sys/types.h>
26
#ifndef sun /* we want to know about TIOCPKT. */
27
# include <sys/ioctl.h>
36
extern struct display *display, *displays;
37
extern struct win *fore; /* for 83 escape */
38
extern struct layer *flayer; /* for 83 escape */
40
extern struct NewWindow nwin_default; /* for ResetWindow() */
41
extern int nversion; /* numerical version of screen */
42
extern int log_flush, logtstamp_on, logtstamp_after;
43
extern char *logtstamp_string;
44
extern char *captionstring;
45
extern char *hstatusstring;
46
extern char *wliststr;
48
extern int compacthist;
51
extern struct acluser *EffectiveAclUser;
54
int Z0width, Z1width; /* widths for Z0/Z1 switching */
56
/* globals set in WriteString */
57
static struct win *curr; /* window we are working on */
58
static int rows, cols; /* window size of the curr window */
61
int use_hardstatus = 1; /* display status line in hs */
63
int use_altscreen = 0; /* enable alternate screen support? */
65
unsigned char *blank; /* line filled with spaces */
66
unsigned char *null; /* line filled with '\0' */
68
struct mline mline_old;
69
struct mline mline_blank;
70
struct mline mline_null;
72
struct mchar mchar_null;
73
struct mchar mchar_blank = {' ' /* , 0, 0, ... */};
74
struct mchar mchar_so = {' ', A_SO /* , 0, 0, ... */};
76
/* keep string_t and string_t_string in sync! */
77
static char *string_t_string[] =
80
"DCS", /* Device control string */
81
"OSC", /* Operating system command */
82
"APC", /* Application program command */
83
/* - used for status change */
84
"PM", /* Privacy message */
85
"AKA", /* title for current screen */
86
"GM", /* Global message to every display */
87
"STATUS" /* User hardstatus line */
90
/* keep state_t and state_t_string in sync! */
91
static char *state_t_string[] =
93
"LIT", /* Literal input */
94
"ESC", /* Start of escape sequence */
95
"ASTR", /* Start of control string */
96
"STRESC", /* ESC seen in control string */
97
"CSI", /* Reading arguments in "CSI Pn ;...*/
98
"PRIN", /* Printer mode */
99
"PRINESC", /* ESC seen in printer mode */
100
"PRINCSI", /* CSI seen in printer mode */
101
"PRIN4" /* CSI 4 seen in printer mode */
104
static int Special __P((int));
105
static void DoESC __P((int, int));
106
static void DoCSI __P((int, int));
107
static void StringStart __P((enum string_t));
108
static void StringChar __P((int));
109
static int StringEnd __P((void));
110
static void PrintStart __P((void));
111
static void PrintChar __P((int));
112
static void PrintFlush __P((void));
114
static void DesignateCharset __P((int, int));
115
static void MapCharset __P((int));
116
static void MapCharsetR __P((int));
118
static void SaveCursor __P((void));
119
static void RestoreCursor __P((void));
120
static void BackSpace __P((void));
121
static void Return __P((void));
122
static void LineFeed __P((int));
123
static void ReverseLineFeed __P((void));
124
static void InsertChar __P((int));
125
static void DeleteChar __P((int));
126
static void DeleteLine __P((int));
127
static void InsertLine __P((int));
128
static void Scroll __P((char *, int, int, char *));
129
static void ForwardTab __P((void));
130
static void BackwardTab __P((void));
131
static void ClearScreen __P((void));
132
static void ClearFromBOS __P((void));
133
static void ClearToEOS __P((void));
134
static void ClearLineRegion __P((int, int));
135
static void CursorRight __P((int));
136
static void CursorUp __P((int));
137
static void CursorDown __P((int));
138
static void CursorLeft __P((int));
139
static void ASetMode __P((int));
140
static void SelectRendition __P((void));
141
static void RestorePosRendition __P((void));
142
static void FillWithEs __P((void));
143
static void FindAKA __P((void));
144
static void Report __P((char *, int, int));
145
static void ScrollRegion __P((int));
147
static void WAddLineToHist __P((struct win *, struct mline *));
149
static void WLogString __P((struct win *, char *, int));
150
static void WReverseVideo __P((struct win *, int));
151
static int WindowChangedCheck __P((char *, int, int *));
152
static void MFixLine __P((struct win *, int, struct mchar *));
153
static void MScrollH __P((struct win *, int, int, int, int, int));
154
static void MScrollV __P((struct win *, int, int, int, int));
155
static void MClearArea __P((struct win *, int, int, int, int, int));
156
static void MInsChar __P((struct win *, struct mchar *, int, int));
157
static void MPutChar __P((struct win *, struct mchar *, int, int));
158
static void MPutStr __P((struct win *, char *, int, struct mchar *, int, int));
159
static void MWrapChar __P((struct win *, struct mchar *, int, int, int, int));
161
static void MBceLine __P((struct win *, int, int, int, int));
165
# define CURR_BCE (curr->w_bce ? rend_getbg(&curr->w_rend) : 0)
175
p->w_StringType = NONE;
180
register struct win *p;
184
p->w_wrap = nwin_default.wrap;
195
p->w_bot = p->w_height - 1;
199
p->w_StringType = NONE;
200
bzero(p->w_tabs, p->w_width);
201
for (i = 8; i < p->w_width; i += 8)
203
p->w_rend = mchar_null;
208
p->w_bce = nwin_default.bce;
212
/* adds max 22 bytes */
214
GetAnsiStatus(w, buf)
220
if (w->w_state == LIT)
223
strcpy(p, state_t_string[w->w_state]);
225
if (w->w_intermediate)
228
if (w->w_intermediate > 0xff)
229
p += AddXChar(p, w->w_intermediate >> 8);
230
p += AddXChar(p, w->w_intermediate & 0xff);
233
if (w->w_state == ASTR || w->w_state == STRESC)
234
sprintf(p, "-%s", string_t_string[w->w_StringType]);
246
p->w_gr = nwin_default.gr;
247
p->w_c1 = nwin_default.c1;
248
SetCharsets(p, "BBBB02");
249
if (nwin_default.charset)
250
SetCharsets(p, nwin_default.charset);
263
for (i = 0; i < 4 && *s; i++, s++)
265
p->w_charsets[i] = ((*s == 'B') ? ASCII : *s);
266
if (*s && *s++ != '.')
267
p->w_Charset = s[-1] - '0';
269
p->w_CharsetR = *s - '0';
271
p->w_FontL = p->w_charsets[p->w_Charset];
272
p->w_FontR = p->w_charsets[p->w_CharsetR];
276
/*****************************************************************/
280
* Here comes the vt100 emulator
282
* - sets timestamp and flags activity in window.
283
* - record program output in window scrollback
284
* - translate program output for the display and put it into the obuf.
288
WriteString(wp, buf, len)
302
WLogString(wp, buf, len);
304
/* set global variables (yuck!) */
306
cols = curr->w_width;
307
rows = curr->w_height;
310
SetTimeout(&curr->w_silenceev, curr->w_silencewait * 1000);
312
if (curr->w_monitor == MON_ON)
314
debug2("ACTIVITY %d %d\n", curr->w_monitor, curr->w_bell);
315
curr->w_monitor = MON_FOUND;
320
c = (unsigned char)*buf++;
325
curr->w_rend.font = curr->w_FontL; /* Default: GL */
328
/* The next part is only for speedup */
329
if (curr->w_state == LIT &&
331
curr->w_encoding != UTF8 &&
334
!is_dw_font(curr->w_rend.font) &&
336
curr->w_rend.font != KANA && !curr->w_mbcs &&
340
curr->w_rend.font != '<' &&
342
c >= ' ' && c != 0x7f &&
343
((c & 0x80) == 0 || ((c >= 0xa0 || !curr->w_c1) && !curr->w_gr)) && !curr->w_ss &&
344
!curr->w_insert && curr->w_x < cols - 1)
346
register int currx = curr->w_x;
349
while (currx < cols - 1)
354
c = (unsigned char)*buf++;
355
if (c < ' ' || c == 0x7f || ((c & 0x80) && ((c < 0xa0 && curr->w_c1) || curr->w_gr)))
361
MPutStr(curr, imp, currx, &curr->w_rend, curr->w_x, curr->w_y);
362
LPutStr(&curr->w_layer, imp, currx, &curr->w_rend, curr->w_x, curr->w_y);
368
/* end of speedup code */
371
if (curr->w_encoding == UTF8)
373
c = FromUtf8(c, &curr->w_decodestate);
384
debug1("read UNICODE %04x\n", c);
389
switch (curr->w_state)
395
curr->w_state = PRINESC;
405
curr->w_state = PRINCSI;
410
curr->w_state = PRIN;
417
curr->w_state = PRIN4;
423
curr->w_state = PRIN;
432
if (curr->w_pdisplay && curr->w_pdisplay->d_printfd >= 0)
434
close(curr->w_pdisplay->d_printfd);
435
curr->w_pdisplay->d_printfd = -1;
437
curr->w_pdisplay = 0;
444
curr->w_state = PRIN;
452
curr->w_state = STRESC;
455
/* special xterm hack: accept SetStatus sequence. Yucc! */
456
/* allow ^E for title escapes */
457
if (!(curr->w_StringType == OSC && c < ' ' && c != '\005'))
458
if (!curr->w_c1 || c != ('\\' ^ 0xc0))
469
if (StringEnd() == 0 || len <= 1)
471
/* check if somewhere a status is displayed */
472
for (cv = curr->w_layer.l_cvlist; cv; cv = cv->c_lnext)
474
display = cv->c_display;
475
if (D_status == STATUS_ON_WIN)
480
if (len > IOSIZE + 1)
482
curr->w_outlen = len - 1;
483
bcopy(buf, curr->w_outbuf, len - 1);
484
return; /* wait till status is gone */
491
curr->w_state = ASTR;
502
curr->w_intermediate = 0;
503
bzero((char *) curr->w_args, MAXARGS * sizeof(int));
531
debug1("not special. c = %x\n", c);
532
if (c >= ' ' && c <= '/')
534
if (curr->w_intermediate)
537
if (curr->w_intermediate == '$')
543
curr->w_intermediate = c;
545
else if (c >= '0' && c <= '~')
547
DoESC(c, curr->w_intermediate);
560
case '0': case '1': case '2': case '3': case '4':
561
case '5': case '6': case '7': case '8': case '9':
562
if (curr->w_NumArgs < MAXARGS)
564
if (curr->w_args[curr->w_NumArgs] < 100000000)
565
curr->w_args[curr->w_NumArgs] =
566
10 * curr->w_args[curr->w_NumArgs] + (c - '0');
571
if (curr->w_NumArgs < MAXARGS)
577
if (c >= '@' && c <= '~')
579
if (curr->w_NumArgs < MAXARGS)
581
DoCSI(c, curr->w_intermediate);
582
if (curr->w_state != PRIN)
585
else if ((c >= ' ' && c <= '/') || (c >= '<' && c <= '?'))
586
curr->w_intermediate = curr->w_intermediate ? -1 : c;
598
if (c <= ' ' || c == 0x7f || (c >= 0x80 && c < 0xa0 && curr->w_c1))
605
curr->w_intermediate = 0;
607
if (curr->w_autoaka < 0)
614
if (c >= 0x80 && c < 0xa0 && curr->w_c1)
616
if ((curr->w_FontR & 0xf0) != 0x20
618
|| curr->w_encoding == UTF8
629
case 0xc0 ^ 'N': /* SS2 */
630
case 0xc0 ^ 'O': /* SS3 */
634
if (curr->w_autoaka < 0)
637
curr->w_intermediate = 0;
638
bzero((char *) curr->w_args, MAXARGS * sizeof(int));
655
if (c < 0x80 || curr->w_gr == 0)
656
curr->w_rend.font = curr->w_FontL;
658
else if (curr->w_gr == 2 && !curr->w_ss)
659
curr->w_rend.font = curr->w_FontE;
662
curr->w_rend.font = curr->w_FontR;
667
if (curr->w_encoding == UTF8)
669
if (curr->w_rend.font == '0')
671
struct mchar mc, *mcp;
673
debug1("SPECIAL %x\n", c);
677
mcp = recode_mchar(&mc, 0, UTF8);
678
debug2("%02x %02x\n", mcp->image, mcp->font);
679
c = mcp->image | mcp->font << 8;
681
curr->w_rend.font = 0;
684
if (curr->w_encoding == UTF8 && c >= 0x1100 && utf8_isdouble(c))
687
if (curr->w_encoding == UTF8 && c >= 0x0300 && utf8_iscomb(c))
696
ox = curr->w_width - 1;
701
copy_mline2mchar(&omc, &curr->w_mlines[oy], ox);
702
if (omc.image == 0xff && omc.font == 0xff)
707
copy_mline2mchar(&omc, &curr->w_mlines[oy], ox);
713
utf8_handle_comb(c, &omc);
714
MFixLine(curr, oy, &omc);
715
copy_mchar2mline(&omc, &curr->w_mlines[oy], ox);
716
LPutChar(&curr->w_layer, &omc, ox, oy);
717
LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
721
font = curr->w_rend.font;
725
if (font == KANA && curr->w_encoding == SJIS && curr->w_mbcs == 0)
727
/* Lets see if it is the first byte of a kanji */
728
debug1("%x may be first of SJIS\n", c);
729
if ((0x81 <= c && c <= 0x9f) || (0xe0 <= c && c <= 0xef))
737
if (font == 031 && c == 0x80 && !curr->w_mbcs)
738
font = curr->w_rend.font = 0;
739
if (is_dw_font(font) && c == ' ')
740
font = curr->w_rend.font = 0;
741
if (is_dw_font(font) || curr->w_mbcs)
744
if (curr->w_mbcs == 0)
749
if (curr->w_x == cols - 1)
751
curr->w_x += curr->w_wrap ? 1 : -1;
752
debug1("Patched w_x to %d\n", curr->w_x);
755
if (curr->w_encoding != UTF8)
760
if (font == KANA && curr->w_encoding == SJIS)
762
debug2("SJIS !! %x %x\n", c, t);
764
* SJIS -> EUC mapping:
766
* 81,82...9f -> 21,23...5d
767
* e0,e1...ef -> 5f,61...7d
771
* 9f-fc -> 21-7e (increment first byte!)
773
if (0x40 <= t && t <= 0xfc && t != 0x7f)
775
if (c <= 0x9f) c = (c - 0x81) * 2 + 0x21;
776
else c = (c - 0xc1) * 2 + 0x21;
777
if (t <= 0x7e) t -= 0x1f;
778
else if (t <= 0x9e) t -= 0x20;
780
curr->w_rend.font = KANJI;
784
/* Incomplete shift-jis - skip first byte */
788
debug2("SJIS after %x %x\n", c, t);
791
if (t && curr->w_gr && font != 030 && font != 031)
802
# endif /* DW_CHARS */
803
if (font == '<' && c >= ' ')
805
font = curr->w_rend.font = 0;
809
else if (curr->w_gr && curr->w_encoding != UTF8)
815
if (c == 0x80 && font == 0 && curr->w_encoding == GBK)
819
if (c < ' ' && font != 031)
823
if (c < ' ') /* this is ugly but kanji support */
824
goto tryagain; /* prevents nicer programming */
830
curr->w_rend.image = c;
832
if (curr->w_encoding == UTF8)
833
curr->w_rend.font = c >> 8;
836
curr->w_rend.mbcs = curr->w_mbcs;
838
if (curr->w_x < cols - 1)
842
save_mline(&curr->w_mlines[curr->w_y], cols);
843
MInsChar(curr, &curr->w_rend, curr->w_x, curr->w_y);
844
LInsChar(&curr->w_layer, &curr->w_rend, curr->w_x, curr->w_y, &mline_old);
849
MPutChar(curr, &curr->w_rend, curr->w_x, curr->w_y);
850
LPutChar(&curr->w_layer, &curr->w_rend, curr->w_x, curr->w_y);
854
else if (curr->w_x == cols - 1)
856
MPutChar(curr, &curr->w_rend, curr->w_x, curr->w_y);
857
LPutChar(&curr->w_layer, &curr->w_rend, curr->w_x, curr->w_y);
863
MWrapChar(curr, &curr->w_rend, curr->w_y, curr->w_top, curr->w_bot, curr->w_insert);
864
LWrapChar(&curr->w_layer, &curr->w_rend, curr->w_y, curr->w_top, curr->w_bot, curr->w_insert);
865
if (curr->w_y != curr->w_bot && curr->w_y != curr->w_height - 1)
873
curr->w_rend.mbcs = curr->w_mbcs = 0;
879
curr->w_FontL = curr->w_charsets[curr->w_Charset];
880
curr->w_FontR = curr->w_charsets[curr->w_CharsetR];
881
curr->w_rend.font = curr->w_FontL;
882
LSetRendition(&curr->w_layer, &curr->w_rend);
890
if (!printcmd && curr->w_state == PRIN)
895
WLogString(p, buf, len)
902
if (logtstamp_on && p->w_logsilence >= logtstamp_after * 2)
904
char *t = MakeWinMsg(logtstamp_string, p, '%');
905
logfwrite(p->w_log, t, strlen(t)); /* long time no write */
908
if (logfwrite(p->w_log, buf, len) < 1)
910
WMsg(p, errno, "Error writing logfile");
936
WBell(curr, visual_bell);
942
case '\017': /* SI */
945
case '\016': /* SO */
954
DoESC(c, intermediate)
957
debug2("DoESC: %x - inter = %x\n", c, intermediate);
958
switch (intermediate)
973
curr->w_tabs[curr->w_x] = 1;
975
case 'Z': /* jph: Identify as VT100 */
976
Report("\033[?%d;%dc", 1, 2);
987
LKeypadMode(&curr->w_layer, 0);
988
LCursorkeysMode(&curr->w_layer, 0);
990
WNewAutoFlow(curr, 1);
993
SetRendition(&mchar_null);
995
ChangeScrollRegion(0, rows - 1);
997
LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1000
LKeypadMode(&curr->w_layer, curr->w_keypad = 1);
1002
WNewAutoFlow(curr, 0);
1003
#endif /* !TIOCPKT */
1006
LKeypadMode(&curr->w_layer, curr->w_keypad = 0);
1008
WNewAutoFlow(curr, 1);
1009
#endif /* !TIOCPKT */
1019
MapCharsetR(G1); /* LS1R */
1023
MapCharsetR(G2); /* LS2R */
1026
MapCharsetR(G3); /* LS3R */
1029
if (curr->w_charsets[curr->w_Charset] != curr->w_charsets[G2]
1030
|| curr->w_charsets[curr->w_CharsetR] != curr->w_charsets[G2])
1031
curr->w_FontR = curr->w_FontL = curr->w_charsets[curr->w_ss = G2];
1036
if (curr->w_charsets[curr->w_Charset] != curr->w_charsets[G3]
1037
|| curr->w_charsets[curr->w_CharsetR] != curr->w_charsets[G3])
1038
curr->w_FontR = curr->w_FontL = curr->w_charsets[curr->w_ss = G3];
1043
case 'g': /* VBELL, private screen sequence */
1058
DesignateCharset(c, G0);
1061
DesignateCharset(c, G1);
1064
DesignateCharset(c, G2);
1067
DesignateCharset(c, G3);
1071
* ESC $ ( Fn: invoke multi-byte charset, Fn, to G0
1072
* ESC $ Fn: same as above. (old sequence)
1073
* ESC $ ) Fn: invoke multi-byte charset, Fn, to G1
1074
* ESC $ * Fn: invoke multi-byte charset, Fn, to G2
1075
* ESC $ + Fn: invoke multi-byte charset, Fn, to G3
1079
DesignateCharset(c & 037, G0);
1082
DesignateCharset(c & 037, G1);
1085
DesignateCharset(c & 037, G2);
1088
DesignateCharset(c & 037, G3);
1096
DoCSI(c, intermediate)
1097
int c, intermediate;
1099
register int i, a1 = curr->w_args[0], a2 = curr->w_args[1];
1101
if (curr->w_NumArgs > MAXARGS)
1102
curr->w_NumArgs = MAXARGS;
1103
switch (intermediate)
1120
LGotoPos(&curr->w_layer, --a2, --a1);
1123
if (curr->w_autoaka)
1124
curr->w_autoaka = a1 + 1;
1127
if (a1 < 0 || a1 > 2)
1139
LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1144
if (a1 < 0 || a1 > 2)
1149
ClearLineRegion(curr->w_x, cols - 1);
1152
ClearLineRegion(0, curr->w_x);
1155
ClearLineRegion(0, cols - 1);
1160
a1 = curr->w_x + (a1 ? a1 - 1 : 0);
1161
ClearLineRegion(curr->w_x, a1 < cols ? a1 : cols - 1);
1164
CursorUp(a1 ? a1 : 1);
1167
CursorDown(a1 ? a1 : 1);
1170
CursorRight(a1 ? a1 : 1);
1173
CursorLeft(a1 ? a1 : 1);
1177
CursorDown(a1 ? a1 : 1); /* positions cursor */
1181
CursorUp(a1 ? a1 : 1); /* positions cursor */
1185
curr->w_x = a1 ? a1 - 1 : 0;
1186
if (curr->w_x >= cols)
1187
curr->w_x = cols - 1;
1188
LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1191
curr->w_y = a1 ? a1 - 1 : 0;
1192
if (curr->w_y >= rows)
1193
curr->w_y = rows - 1;
1194
LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1201
curr->w_tabs[curr->w_x] = 0;
1203
bzero(curr->w_tabs, cols);
1210
if (a1 < 1 || a2 > rows || a1 >= a2)
1212
curr->w_top = a1 - 1;
1213
curr->w_bot = a2 - 1;
1214
/* ChangeScrollRegion(curr->w_top, curr->w_bot); */
1217
curr->w_y = curr->w_top;
1221
curr->w_y = curr->w_x = 0;
1222
LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1230
a1 = curr->w_args[2];
1234
a2 = curr->w_height;
1235
if (a1 > 10000 || a2 > 10000)
1237
WChangeSize(curr, a1, a2);
1238
cols = curr->w_width;
1239
rows = curr->w_height;
1257
InsertLine(a1 ? a1 : 1);
1260
DeleteLine(a1 ? a1 : 1);
1263
DeleteChar(a1 ? a1 : 1);
1266
InsertChar(a1 ? a1 : 1);
1274
case 'i': /* MC Media Control */
1279
if (a1 == 5) /* Report terminal status */
1280
Report("\033[0n", 0, 0);
1281
else if (a1 == 6) /* Report cursor position */
1282
Report("\033[%d;%dR", curr->w_y + 1, curr->w_x + 1);
1284
case 'c': /* Identify as VT100 */
1286
Report("\033[?%d;%dc", 1, 2);
1288
case 'x': /* decreqtparm */
1289
if (a1 == 0 || a1 == 1)
1290
Report("\033[%d;1;1;112;112;1;0x", a1 + 2, 0);
1292
case 'p': /* obscure code from a 97801 term */
1293
if (a1 == 6 || a1 == 7)
1295
curr->w_curinv = 7 - a1;
1296
LCursorVisibility(&curr->w_layer, curr->w_curinv ? -1 : curr->w_curvvis);
1299
case 'S': /* code from a 97801 term / DEC vt400 */
1300
ScrollRegion(a1 ? a1 : 1);
1302
case 'T': /* code from a 97801 term / DEC vt400 */
1303
case '^': /* SD as per ISO 6429 */
1304
ScrollRegion(a1 ? -a1 : -1);
1309
for (a2 = 0; a2 < curr->w_NumArgs; a2++)
1311
a1 = curr->w_args[a2];
1312
debug2("\\E[?%d%c\n",a1,c);
1313
if (c != 'h' && c != 'l')
1318
case 1: /* CKM: cursor key mode */
1319
LCursorkeysMode(&curr->w_layer, curr->w_cursorkeys = i);
1321
WNewAutoFlow(curr, !i);
1322
#endif /* !TIOCPKT */
1324
case 2: /* ANM: ansi/vt52 mode */
1329
if (curr->w_encoding)
1332
curr->w_charsets[0] = curr->w_charsets[1] =
1333
curr->w_charsets[2] = curr->w_charsets[2] =
1334
curr->w_FontL = curr->w_FontR = ASCII;
1335
curr->w_Charset = 0;
1336
curr->w_CharsetR = 2;
1341
case 3: /* COLM: column mode */
1342
i = (i ? Z0width : Z1width);
1343
WChangeSize(curr, i, curr->w_height);
1344
cols = curr->w_width;
1345
rows = curr->w_height;
1347
/* case 4: SCLM: scrolling mode */
1348
case 5: /* SCNM: screen mode */
1349
if (i != curr->w_revvid)
1350
WReverseVideo(curr, i);
1353
case 6: /* OM: origin mode */
1354
if ((curr->w_origin = i) != 0)
1356
curr->w_y = curr->w_top;
1360
curr->w_y = curr->w_x = 0;
1361
LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1363
case 7: /* AWM: auto wrap mode */
1366
/* case 8: ARM: auto repeat mode */
1367
/* case 9: INLM: interlace mode */
1368
case 9: /* X10 mouse tracking */
1369
curr->w_mouse = i ? 9 : 0;
1370
LMouseMode(&curr->w_layer, curr->w_mouse);
1372
/* case 10: EDM: edit mode */
1373
/* case 11: LTM: line transmit mode */
1374
/* case 13: SCFDM: space compression / field delimiting */
1375
/* case 14: TEM: transmit execution mode */
1376
/* case 16: EKEM: edit key execution mode */
1377
/* case 18: PFF: Printer term form feed */
1378
/* case 19: PEX: Printer extend screen / scroll. reg */
1379
case 25: /* TCEM: text cursor enable mode */
1380
curr->w_curinv = !i;
1381
LCursorVisibility(&curr->w_layer, curr->w_curinv ? -1 : curr->w_curvvis);
1383
/* case 34: RLM: Right to left mode */
1384
/* case 35: HEBM: hebrew keyboard map */
1385
/* case 36: HEM: hebrew encoding */
1386
/* case 38: TeK Mode */
1387
/* case 40: 132 col enable */
1388
/* case 42: NRCM: 7bit NRC character mode */
1389
/* case 44: margin bell enable */
1390
case 47: /* xterm-like alternate screen */
1391
case 1047: /* xterm-like alternate screen */
1392
case 1049: /* xterm-like alternate screen */
1396
EnterAltScreen(curr);
1398
LeaveAltScreen(curr);
1401
LRefreshAll(&curr->w_layer, 0);
1402
LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1405
/* case 66: NKM: Numeric keypad appl mode */
1406
/* case 68: KBUM: Keyboard usage mode (data process) */
1407
case 1000: /* VT200 mouse tracking */
1408
case 1001: /* VT200 highlight mouse */
1409
case 1002: /* button event mouse*/
1410
case 1003: /* any event mouse*/
1411
curr->w_mouse = i ? a1 : 0;
1412
LMouseMode(&curr->w_layer, curr->w_mouse);
1420
case 'c': /* secondary DA */
1422
Report("\033[>%d;%d;0c", 83, nversion); /* 83 == 'S' */
1434
curr->w_StringType = type;
1435
curr->w_stringp = curr->w_string;
1436
curr->w_state = ASTR;
1443
if (curr->w_stringp >= curr->w_string + MAXSTR - 1)
1444
curr->w_state = LIT;
1446
*(curr->w_stringp)++ = c;
1450
* Do string processing. Returns -1 if output should be suspended
1451
* until status is gone.
1460
curr->w_state = LIT;
1461
*curr->w_stringp = '\0';
1462
switch (curr->w_StringType)
1464
case OSC: /* special xterm compatibility hack */
1465
if (curr->w_string[0] == ';' || (p = index(curr->w_string, ';')) == 0)
1467
typ = atoi(curr->w_string);
1470
if (typ == 83) /* 83 = 'S' */
1472
/* special execute commands sequence */
1473
char *args[MAXARGS];
1475
struct acluser *windowuser;
1477
windowuser = *FindUserPtr(":window:");
1478
if (windowuser && Parse(p, sizeof(curr->w_string) - (p - curr->w_string), args, argl))
1480
for (display = displays; display; display = display->d_next)
1481
if (D_forecv->c_layer->l_bottom == &curr->w_layer)
1482
break; /* found it */
1483
if (display == 0 && curr->w_layer.l_cvlist)
1484
display = curr->w_layer.l_cvlist->c_display;
1487
EffectiveAclUser = windowuser;
1489
flayer = fore->w_savelayer ? fore->w_savelayer : &fore->w_layer;
1490
DoCommand(args, argl);
1491
EffectiveAclUser = 0;
1499
if (typ == 0 || typ == 1 || typ == 20 || typ == 39 || typ == 49)
1505
if (strcmp(curr->w_xtermosc[typ2], p))
1507
strncpy(curr->w_xtermosc[typ2], p, sizeof(curr->w_xtermosc[typ2]) - 1);
1508
curr->w_xtermosc[typ2][sizeof(curr->w_xtermosc[typ2]) - 1] = 0;
1510
for (display = displays; display; display = display->d_next)
1514
if (D_forecv->c_layer->l_bottom == &curr->w_layer)
1515
SetXtermOSC(typ2, curr->w_xtermosc[typ2]);
1516
if ((typ2 == 2 || typ2 == 3) && D_xtermosc[typ2])
1521
if (typ != 0 && typ != 2)
1524
if (typ < 0 || typ > 2)
1528
curr->w_stringp -= p - curr->w_string;
1529
if (curr->w_stringp > curr->w_string)
1530
bcopy(p, curr->w_string, curr->w_stringp - curr->w_string);
1531
*curr->w_stringp = '\0';
1534
if (curr->w_hstatus)
1536
if (strcmp(curr->w_hstatus, curr->w_string) == 0)
1537
break; /* not changed */
1538
free(curr->w_hstatus);
1539
curr->w_hstatus = 0;
1541
if (curr->w_string != curr->w_stringp)
1542
curr->w_hstatus = SaveStr(curr->w_string);
1543
WindowChanged(curr, 'h');
1547
for (display = displays; display; display = display->d_next)
1549
for (cv = D_cvlist; cv; cv = cv->c_next)
1550
if (cv->c_layer->l_bottom == &curr->w_layer)
1552
if (cv || curr->w_StringType == GM)
1553
MakeStatus(curr->w_string);
1557
LAY_DISPLAYS(&curr->w_layer, AddStr(curr->w_string));
1560
if (curr->w_title == curr->w_akabuf && !*curr->w_string)
1562
ChangeAKA(curr, curr->w_string, strlen(curr->w_string));
1563
if (!*curr->w_string)
1564
curr->w_autoaka = curr->w_y + 1;
1575
curr->w_pdisplay = 0;
1577
/* find us a nice display to print on, fore prefered */
1578
display = curr->w_lastdisp;
1579
if (!(display && curr == D_fore && (printcmd || D_PO)))
1580
for (display = displays; display; display = display->d_next)
1581
if (curr == D_fore && (printcmd || D_PO))
1586
for (cv = curr->w_layer.l_cvlist; cv; cv = cv->c_lnext)
1588
display = cv->c_display;
1589
if (printcmd || D_PO)
1595
if (!display || display->d_next || !(printcmd || D_PO))
1599
curr->w_pdisplay = display;
1600
curr->w_stringp = curr->w_string;
1601
curr->w_state = PRIN;
1602
if (printcmd && curr->w_pdisplay->d_printfd < 0)
1603
curr->w_pdisplay->d_printfd = printpipe(curr, printcmd);
1610
if (curr->w_stringp >= curr->w_string + MAXSTR - 1)
1612
*(curr->w_stringp)++ = c;
1618
display = curr->w_pdisplay;
1619
if (display && printcmd)
1621
char *bp = curr->w_string;
1622
int len = curr->w_stringp - curr->w_string;
1624
while (len && display->d_printfd >= 0)
1626
r = write(display->d_printfd, bp, len);
1629
WMsg(curr, errno, "printing aborted");
1630
close(display->d_printfd);
1631
display->d_printfd = -1;
1638
else if (display && curr->w_stringp > curr->w_string)
1641
AddStrn(curr->w_string, curr->w_stringp - curr->w_string);
1645
curr->w_stringp = curr->w_string;
1650
WNewAutoFlow(win, on)
1654
debug1("WNewAutoFlow: %d\n", on);
1655
if (win->w_flow & FLOW_AUTOFLAG)
1656
win->w_flow = FLOW_AUTOFLAG | (FLOW_AUTO|FLOW_NOW) * on;
1658
win->w_flow = (win->w_flow & ~FLOW_AUTO) | FLOW_AUTO * on;
1659
LSetFlow(&win->w_layer, win->w_flow & FLOW_NOW);
1666
DesignateCharset(c, n)
1671
if (c == ('@' & 037)) /* map JIS 6226 to 0208 */
1676
if (curr->w_charsets[n] != c)
1678
curr->w_charsets[n] = c;
1679
if (curr->w_Charset == n)
1682
curr->w_rend.font = curr->w_FontL;
1683
LSetRendition(&curr->w_layer, &curr->w_rend);
1685
if (curr->w_CharsetR == n)
1695
if (curr->w_Charset != n)
1697
curr->w_Charset = n;
1698
curr->w_FontL = curr->w_charsets[n];
1699
curr->w_rend.font = curr->w_FontL;
1700
LSetRendition(&curr->w_layer, &curr->w_rend);
1709
if (curr->w_CharsetR != n)
1711
curr->w_CharsetR = n;
1712
curr->w_FontR = curr->w_charsets[n];
1723
curr->w_Saved_x = curr->w_x;
1724
curr->w_Saved_y = curr->w_y;
1725
curr->w_SavedRend = curr->w_rend;
1727
curr->w_SavedCharset = curr->w_Charset;
1728
curr->w_SavedCharsetR = curr->w_CharsetR;
1729
bcopy((char *) curr->w_charsets, (char *) curr->w_SavedCharsets,
1739
LGotoPos(&curr->w_layer, curr->w_Saved_x, curr->w_Saved_y);
1740
curr->w_x = curr->w_Saved_x;
1741
curr->w_y = curr->w_Saved_y;
1742
curr->w_rend = curr->w_SavedRend;
1744
bcopy((char *) curr->w_SavedCharsets, (char *) curr->w_charsets,
1746
curr->w_Charset = curr->w_SavedCharset;
1747
curr->w_CharsetR = curr->w_SavedCharsetR;
1749
curr->w_FontL = curr->w_charsets[curr->w_Charset];
1750
curr->w_FontR = curr->w_charsets[curr->w_CharsetR];
1752
LSetRendition(&curr->w_layer, &curr->w_rend);
1762
else if (curr->w_wrap && curr->w_y > 0)
1764
curr->w_x = cols - 1;
1767
LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1776
LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1783
/* out_mode: 0=lf, 1=cr+lf */
1786
if (curr->w_y != curr->w_bot) /* Don't scroll */
1788
if (curr->w_y < rows-1)
1790
LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1793
if (curr->w_autoaka > 1)
1795
MScrollV(curr, 1, curr->w_top, curr->w_bot, CURR_BCE);
1796
LScrollV(&curr->w_layer, 1, curr->w_top, curr->w_bot, CURR_BCE);
1797
LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1803
if (curr->w_y == curr->w_top)
1805
MScrollV(curr, -1, curr->w_top, curr->w_bot, CURR_BCE);
1806
LScrollV(&curr->w_layer, -1, curr->w_top, curr->w_bot, CURR_BCE);
1807
LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1809
else if (curr->w_y > 0)
1817
register int y = curr->w_y, x = curr->w_x;
1823
save_mline(&curr->w_mlines[y], cols);
1824
MScrollH(curr, -n, y, x, curr->w_width - 1, CURR_BCE);
1825
LScrollH(&curr->w_layer, -n, y, x, curr->w_width - 1, CURR_BCE, &mline_old);
1826
LGotoPos(&curr->w_layer, x, y);
1833
register int y = curr->w_y, x = curr->w_x;
1837
save_mline(&curr->w_mlines[y], cols);
1838
MScrollH(curr, n, y, x, curr->w_width - 1, CURR_BCE);
1839
LScrollH(&curr->w_layer, n, y, x, curr->w_width - 1, CURR_BCE, &mline_old);
1840
LGotoPos(&curr->w_layer, x, y);
1847
if (curr->w_y < curr->w_top || curr->w_y > curr->w_bot)
1849
if (n > curr->w_bot - curr->w_y + 1)
1850
n = curr->w_bot - curr->w_y + 1;
1851
MScrollV(curr, n, curr->w_y, curr->w_bot, CURR_BCE);
1852
LScrollV(&curr->w_layer, n, curr->w_y, curr->w_bot, CURR_BCE);
1853
LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1860
if (curr->w_y < curr->w_top || curr->w_y > curr->w_bot)
1862
if (n > curr->w_bot - curr->w_y + 1)
1863
n = curr->w_bot - curr->w_y + 1;
1864
MScrollV(curr, -n, curr->w_y, curr->w_bot, CURR_BCE);
1865
LScrollV(&curr->w_layer, -n, curr->w_y, curr->w_bot, CURR_BCE);
1866
LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1873
MScrollV(curr, n, curr->w_top, curr->w_bot, CURR_BCE);
1874
LScrollV(&curr->w_layer, n, curr->w_top, curr->w_bot, CURR_BCE);
1875
LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1882
register int x = curr->w_x;
1889
if (curr->w_tabs[x] && x < cols - 1)
1891
while (x < cols - 1 && !curr->w_tabs[x])
1894
LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1900
register int x = curr->w_x;
1902
if (curr->w_tabs[x] && x > 0)
1904
while (x > 0 && !curr->w_tabs[x])
1907
LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1913
LClearArea(&curr->w_layer, 0, 0, curr->w_width - 1, curr->w_height - 1, CURR_BCE, 1);
1915
MScrollV(curr, curr->w_height, 0, curr->w_height - 1, CURR_BCE);
1917
MClearArea(curr, 0, 0, curr->w_width - 1, curr->w_height - 1, CURR_BCE);
1924
register int y = curr->w_y, x = curr->w_x;
1926
LClearArea(&curr->w_layer, 0, 0, x, y, CURR_BCE, 1);
1927
MClearArea(curr, 0, 0, x, y, CURR_BCE);
1928
RestorePosRendition();
1934
register int y = curr->w_y, x = curr->w_x;
1936
if (x == 0 && y == 0)
1939
RestorePosRendition();
1942
LClearArea(&curr->w_layer, x, y, cols - 1, rows - 1, CURR_BCE, 1);
1943
MClearArea(curr, x, y, cols - 1, rows - 1, CURR_BCE);
1944
RestorePosRendition();
1948
ClearLineRegion(from, to)
1951
register int y = curr->w_y;
1952
LClearArea(&curr->w_layer, from, y, to, y, CURR_BCE, 1);
1953
MClearArea(curr, from, y, to, y, CURR_BCE);
1954
RestorePosRendition();
1961
register int x = curr->w_x;
1968
if ((curr->w_x += n) >= cols)
1969
curr->w_x = cols - 1;
1970
LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1977
if (curr->w_y < curr->w_top) /* if above scrolling rgn, */
1979
if ((curr->w_y -= n) < 0) /* ignore its limits */
1983
if ((curr->w_y -= n) < curr->w_top)
1984
curr->w_y = curr->w_top;
1985
LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1992
if (curr->w_y > curr->w_bot) /* if below scrolling rgn, */
1994
if ((curr->w_y += n) > rows - 1) /* ignore its limits */
1995
curr->w_y = rows - 1;
1998
if ((curr->w_y += n) > curr->w_bot)
1999
curr->w_y = curr->w_bot;
2000
LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
2007
if ((curr->w_x -= n) < 0)
2009
LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
2018
for (i = 0; i < curr->w_NumArgs; ++i)
2020
switch (curr->w_args[i])
2022
/* case 2: KAM: Lock keyboard */
2023
case 4: /* IRM: Insert mode */
2024
curr->w_insert = on;
2025
LAY_DISPLAYS(&curr->w_layer, InsertMode(on));
2027
/* case 12: SRM: Echo mode on */
2028
case 20: /* LNM: Linefeed mode */
2029
curr->w_autolf = on;
2032
curr->w_curvvis = !on;
2033
LCursorVisibility(&curr->w_layer, curr->w_curinv ? -1 : curr->w_curvvis);
2041
static char rendlist[] =
2043
~((1 << NATTR) - 1), A_BD, A_DI, A_SO, A_US, A_BL, 0, A_RV, 0, 0,
2044
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2045
0, 0, ~(A_BD|A_SO|A_DI), ~A_SO, ~A_US, ~A_BL, 0, ~A_RV
2052
register int j, i = 0, a = curr->w_rend.attr, c = curr->w_rend.color;
2054
int cx = curr->w_rend.colorx;
2057
register int j, i = 0, a = curr->w_rend.attr;
2062
j = curr->w_args[i];
2064
if ((j == 38 || j == 48) && i + 2 < curr->w_NumArgs && curr->w_args[i + 1] == 5)
2069
jj = curr->w_args[i];
2070
if (jj < 0 || jj > 255)
2075
c = (c & 0xf0) | ((jj & 0x0f) ^ 9);
2077
if (jj >= 8 && jj < 16)
2081
a = (a & 0xbf) | (jj & 8 ? 0x40 : 0);
2082
cx = (cx & 0xf0) | (jj >> 4 & 0x0f);
2086
c = (c & 0x0f) | ((jj & 0x0f) ^ 9) << 4;
2088
if (jj >= 8 && jj < 16)
2092
cx = (cx & 0x0f) | (jj & 0xf0);
2096
jj = color256to16(jj) + 30;
2099
j = j == 38 ? jj : jj + 10;
2103
if (j == 0 || (j >= 30 && j <= 39 && j != 38))
2105
if (j == 0 || (j >= 40 && j <= 49 && j != 48))
2107
if (j >= 90 && j <= 97)
2109
if (j >= 100 && j <= 107)
2112
if (j >= 90 && j <= 97)
2114
if (j >= 100 && j <= 107)
2116
if (j >= 30 && j <= 39 && j != 38)
2117
c = (c & 0xf0) | ((j - 30) ^ 9);
2118
else if (j >= 40 && j <= 49 && j != 48)
2119
c = (c & 0x0f) | (((j - 40) ^ 9) << 4);
2123
if (j == 0 || (j >= 30 && j <= 39 && j != 38))
2125
if (j == 0 || (j >= 40 && j <= 49 && j != 48))
2129
if (j < 0 || j >= (int)(sizeof(rendlist)/sizeof(*rendlist)))
2132
if (j & (1 << NATTR))
2137
while (++i < curr->w_NumArgs);
2138
curr->w_rend.attr = a;
2140
curr->w_rend.color = c;
2142
curr->w_rend.colorx = cx;
2145
LSetRendition(&curr->w_layer, &curr->w_rend);
2152
register unsigned char *p, *ep;
2154
LClearAll(&curr->w_layer, 1);
2155
curr->w_y = curr->w_x = 0;
2156
for (i = 0; i < rows; ++i)
2158
clear_mline(&curr->w_mlines[i], 0, cols + 1);
2159
p = curr->w_mlines[i].image;
2164
LRefreshAll(&curr->w_layer, 1);
2169
* Ugly autoaka hack support:
2170
* ChangeAKA() sets a new aka
2171
* FindAKA() searches for an autoaka match
2182
for (i = 0; l > 0; l--)
2184
if (p->w_akachange + i == p->w_akabuf + sizeof(p->w_akabuf) - 1)
2186
c = (unsigned char)*s++;
2189
if (c < 32 || c == 127 || (c >= 128 && c < 160 && p->w_c1))
2191
p->w_akachange[i++] = c;
2193
p->w_akachange[i] = 0;
2194
p->w_title = p->w_akachange;
2195
if (p->w_akachange != p->w_akabuf)
2196
if (p->w_akachange[0] == 0 || p->w_akachange[-1] == ':')
2197
p->w_title = p->w_akabuf + strlen(p->w_akabuf) + 1;
2198
WindowChanged(p, 't');
2199
WindowChanged((struct win *)0, 'w');
2200
WindowChanged((struct win *)0, 'W');
2206
register unsigned char *cp, *line;
2207
register struct win *wp = curr;
2208
register int len = strlen(wp->w_akabuf);
2211
y = (wp->w_autoaka > 0 && wp->w_autoaka <= wp->w_height) ? wp->w_autoaka - 1 : wp->w_y;
2214
cp = line = wp->w_mlines[y].image;
2215
if (wp->w_autoaka > 0 && *wp->w_akabuf != '\0')
2219
if (cp - line >= cols - len)
2221
if (++y == wp->w_autoaka && y < rows)
2225
if (strncmp((char *)cp, wp->w_akabuf, len) == 0)
2231
for (len = cols - (cp - line); len && *cp == ' '; len--, cp++)
2235
if (wp->w_autoaka > 0 && (*cp == '!' || *cp == '%' || *cp == '^'))
2240
while (len && *cp != ' ')
2246
ChangeAKA(wp, (char *)line, cp - line);
2253
RestorePosRendition()
2255
LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
2256
LSetRendition(&curr->w_layer, &curr->w_rend);
2259
/* Send a terminal report as if it were typed. */
2266
char rbuf[40]; /* enough room for all replys */
2268
sprintf(rbuf, fmt, n1, n2);
2271
if ((unsigned)(curr->w_inlen + len) <= sizeof(curr->w_inbuf))
2273
bcopy(rbuf, curr->w_inbuf + curr->w_inlen, len);
2274
curr->w_inlen += len;
2281
*====================================================================*
2282
*====================================================================*
2285
/**********************************************************************
2297
struct mline *ml = &p->w_mlines[y];
2298
if (mc->attr && ml->attr == null)
2300
if ((ml->attr = (unsigned char *)malloc(p->w_width + 1)) == 0)
2303
mc->attr = p->w_rend.attr = 0;
2304
WMsg(p, 0, "Warning: no space for attr - turned off");
2306
bzero((char *)ml->attr, p->w_width + 1);
2309
if (mc->font && ml->font == null)
2311
if ((ml->font = (unsigned char *)malloc(p->w_width + 1)) == 0)
2314
p->w_FontL = p->w_charsets[p->w_ss ? p->w_ss : p->w_Charset] = 0;
2315
p->w_FontR = p->w_charsets[p->w_ss ? p->w_ss : p->w_CharsetR] = 0;
2316
mc->font = p->w_rend.font = 0;
2317
WMsg(p, 0, "Warning: no space for font - turned off");
2319
bzero((char *)ml->font, p->w_width + 1);
2323
if (mc->color && ml->color == null)
2325
if ((ml->color = (unsigned char *)malloc(p->w_width + 1)) == 0)
2328
mc->color = p->w_rend.color = 0;
2329
WMsg(p, 0, "Warning: no space for color - turned off");
2331
bzero((char *)ml->color, p->w_width + 1);
2334
if (mc->colorx && ml->colorx == null)
2336
if ((ml->colorx = (unsigned char *)malloc(p->w_width + 1)) == 0)
2339
mc->colorx = p->w_rend.colorx = 0;
2340
WMsg(p, 0, "Warning: no space for extended colors - turned off");
2342
bzero((char *)ml->colorx, p->w_width + 1);
2348
/*****************************************************************/
2351
# define MKillDwRight(p, ml, x) \
2352
if (dw_right(ml, x, p->w_encoding)) \
2355
copy_mchar2mline(&mchar_blank, ml, x - 1); \
2356
copy_mchar2mline(&mchar_blank, ml, x); \
2359
# define MKillDwLeft(p, ml, x) \
2360
if (dw_left(ml, x, p->w_encoding)) \
2362
copy_mchar2mline(&mchar_blank, ml, x); \
2363
copy_mchar2mline(&mchar_blank, ml, x + 1); \
2366
# define MKillDwRight(p, ml, x) ;
2367
# define MKillDwLeft(p, ml, x) ;
2371
MScrollH(p, n, y, xs, xe, bce)
2373
int n, y, xs, xe, bce;
2379
ml = &p->w_mlines[y];
2380
MKillDwRight(p, ml, xs);
2381
MKillDwLeft(p, ml, xe);
2384
if (xe - xs + 1 > n)
2386
MKillDwRight(p, ml, xs + n);
2387
bcopy_mline(ml, xs + n, xs, xe + 1 - xs - n);
2391
clear_mline(ml, xe + 1 - n, n);
2394
MBceLine(p, y, xe + 1 - n, n, bce);
2400
if (xe - xs + 1 > n)
2402
MKillDwLeft(p, ml, xe - n);
2403
bcopy_mline(ml, xs, xs + n, xe + 1 - xs - n);
2407
clear_mline(ml, xs, n);
2410
MBceLine(p, y, xs, n, bce);
2416
MScrollV(p, n, ys, ye, bce)
2421
struct mline tmp[256];
2430
MScrollV(p, n - 256, ys, ye, bce);
2433
if (ye - ys + 1 < n)
2438
ye = MFindUsedLine(p, ye, ys);
2439
if (ye - ys + 1 < n)
2446
ml = p->w_mlines + ys;
2447
for (i = ys; i < ys + n; i++, ml++)
2451
WAddLineToHist(p, ml);
2453
if (ml->attr != null)
2457
if (ml->font != null)
2462
if (ml->color != null)
2466
if (ml->colorx != null)
2471
bclear((char *)ml->image, p->w_width + 1);
2474
MBceLine(p, i, 0, p->w_width, bce);
2477
/* switch 'em over */
2478
cnt1 = n * sizeof(struct mline);
2479
cnt2 = (ye - ys + 1 - n) * sizeof(struct mline);
2481
Scroll((char *)(p->w_mlines + ys), cnt1, cnt2, (char *)tmp);
2487
MScrollV(p, n + 256, ys, ye, bce);
2491
if (ye - ys + 1 < n)
2494
ml = p->w_mlines + ye;
2496
for (i = ye; i > ye - n; i--, ml--)
2498
if (ml->attr != null)
2502
if (ml->font != null)
2507
if (ml->color != null)
2511
if (ml->colorx != null)
2516
bclear((char *)ml->image, p->w_width + 1);
2519
MBceLine(p, i, 0, p->w_width, bce);
2522
cnt1 = n * sizeof(struct mline);
2523
cnt2 = (ye - ys + 1 - n) * sizeof(struct mline);
2525
Scroll((char *)(p->w_mlines + ys), cnt2, cnt1, (char *)tmp);
2530
Scroll(cp, cnt1, cnt2, tmp)
2538
bcopy(cp, tmp, cnt1);
2539
bcopy(cp + cnt1, cp, cnt2);
2540
bcopy(tmp, cp + cnt2, cnt1);
2544
bcopy(cp + cnt1, tmp, cnt2);
2545
bcopy(cp, cp + cnt2, cnt1);
2546
bcopy(tmp, cp, cnt2);
2551
MClearArea(p, xs, ys, xe, ye, bce)
2553
int xs, ys, xe, ye, bce;
2559
/* check for magic margin condition */
2560
if (xs >= p->w_width)
2561
xs = p->w_width - 1;
2562
if (xe >= p->w_width)
2563
xe = p->w_width - 1;
2565
MKillDwRight(p, p->w_mlines + ys, xs);
2566
MKillDwLeft(p, p->w_mlines + ye, xe);
2568
ml = p->w_mlines + ys;
2569
for (y = ys; y <= ye; y++, ml++)
2571
xxe = (y == ye) ? xe : p->w_width - 1;
2574
clear_mline(ml, xs, n);
2577
MBceLine(p, y, xs, xs + n - 1, bce);
2584
MInsChar(p, c, x, y)
2592
ASSERT(x >= 0 && x < p->w_width);
2594
ml = p->w_mlines + y;
2595
n = p->w_width - x - 1;
2596
MKillDwRight(p, ml, x);
2599
MKillDwRight(p, ml, p->w_width - 1);
2600
bcopy_mline(ml, x, x + 1, n);
2602
copy_mchar2mline(c, ml, x);
2608
MKillDwRight(p, ml, p->w_width - 1);
2609
bcopy_mline(ml, x + 1, x + 2, n);
2611
copy_mchar2mline(c, ml, x + 1);
2612
ml->image[x + 1] = c->mbcs;
2614
if (p->w_encoding != UTF8)
2615
ml->font[x + 1] |= 0x80;
2616
else if (p->w_encoding == UTF8 && c->mbcs)
2617
ml->font[x + 1] = c->mbcs;
2619
ml->font[x + 1] |= 0x80;
2626
MPutChar(p, c, x, y)
2634
ml = &p->w_mlines[y];
2635
MKillDwRight(p, ml, x);
2636
MKillDwLeft(p, ml, x);
2637
copy_mchar2mline(c, ml, x);
2641
MKillDwLeft(p, ml, x + 1);
2642
copy_mchar2mline(c, ml, x + 1);
2643
ml->image[x + 1] = c->mbcs;
2645
if (p->w_encoding != UTF8)
2646
ml->font[x + 1] |= 0x80;
2647
else if (p->w_encoding == UTF8 && c->mbcs)
2648
ml->font[x + 1] = c->mbcs;
2650
ml->font[x + 1] |= 0x80;
2658
MWrapChar(p, c, y, top, bot, ins)
2668
bce = rend_getbg(c);
2673
ml = &p->w_mlines[y];
2674
copy_mchar2mline(&mchar_null, ml, p->w_width);
2676
MScrollV(p, 1, top, bot, bce);
2677
else if (y < p->w_height - 1)
2680
MInsChar(p, c, 0, y);
2682
MPutChar(p, c, 0, y);
2686
MPutStr(p, s, n, r, x, y)
2700
ml = &p->w_mlines[y];
2701
MKillDwRight(p, ml, x);
2702
MKillDwLeft(p, ml, x + n - 1);
2703
bcopy(s, (char *)ml->image + x, n);
2705
for (i = n; i-- > 0;)
2709
for (i = n; i-- > 0;)
2714
for (i = n; i-- > 0;)
2718
for (i = n; i-- > 0;)
2726
MBceLine(p, y, xs, xe, bce)
2735
rend_setbg(&mc, bce);
2736
MFixLine(p, y, &mc);
2737
ml = p->w_mlines + y;
2740
for (x = xs; x <= xe; x++)
2741
ml->attr[x] = mc.attr;
2744
for (x = xs; x <= xe; x++)
2745
ml->color[x] = mc.color;
2748
for (x = xs; x <= xe; x++)
2749
ml->colorx[x] = mc.colorx;
2757
WAddLineToHist(wp, ml)
2761
register unsigned char *q, *o;
2764
if (wp->w_histheight == 0)
2766
hml = &wp->w_hlines[wp->w_histidx];
2767
q = ml->image; ml->image = hml->image; hml->image = q;
2769
q = ml->attr; o = hml->attr; hml->attr = q; ml->attr = null;
2774
q = ml->font; o = hml->font; hml->font = q; ml->font = null;
2780
q = ml->color; o = hml->color; hml->color = q; ml->color = null;
2784
q = ml->colorx; o = hml->colorx; hml->colorx = q; ml->colorx = null;
2790
if (++wp->w_histidx >= wp->w_histheight)
2796
MFindUsedLine(p, ye, ys)
2801
struct mline *ml = p->w_mlines + ye;
2803
debug2("MFindUsedLine: %d %d\n", ye, ys);
2804
for (y = ye; y >= ys; y--, ml--)
2806
if (bcmp((char*)ml->image, blank, p->w_width))
2808
if (ml->attr != null && bcmp((char*)ml->attr, null, p->w_width))
2811
if (ml->color != null && bcmp((char*)ml->color, null, p->w_width))
2814
if (ml->colorx != null && bcmp((char*)ml->colorx, null, p->w_width))
2819
debug1("MFindUsedLine returning %d\n", y);
2825
*====================================================================*
2826
*====================================================================*
2830
* Tricky: send only one bell even if the window is displayed
2839
for (display = displays; display; display = display->d_next)
2841
for (cv = D_cvlist; cv; cv = cv->c_next)
2842
if (cv->c_layer->l_bottom == &p->w_layer)
2846
else if (cv && D_VB)
2849
p->w_bell = visual ? BELL_VISUAL : BELL_FOUND;
2854
* This should be reverse video.
2855
* Only change video if window is fore.
2856
* Because it is used in some termcaps to emulate
2857
* a visual bell we do this hack here.
2858
* (screen uses \Eg as special vbell sequence)
2861
WReverseVideo(p, on)
2866
for (cv = p->w_layer.l_cvlist; cv; cv = cv->c_lnext)
2868
display = cv->c_display;
2872
if (!on && p->w_revvid && !D_CVR)
2877
p->w_bell = BELL_VISUAL;
2888
extern struct layer *flayer;
2889
struct layer *oldflayer = flayer;
2890
flayer = &p->w_layer;
2896
WChangeSize(p, w, h)
2903
if (p->w_layer.l_cvlist == 0)
2905
/* window not displayed -> works always */
2906
ChangeWindowSize(p, w, h, p->w_histheight);
2909
for (cv = p->w_layer.l_cvlist; cv; cv = cv->c_lnext)
2911
display = cv->c_display;
2913
continue; /* change only fore */
2916
if (D_CZ0 && (w == Z0width || w == Z1width))
2919
if (cv == 0 && wok == 0) /* can't change any display */
2923
ChangeWindowSize(p, w, h, p->w_histheight);
2924
for (display = displays; display; display = display->d_next)
2928
if (D_cvlist && D_cvlist->c_next == 0)
2929
ResizeDisplay(w, h);
2931
ResizeDisplay(w, D_height);
2932
ResizeLayersToCanvases(); /* XXX Hmm ? */
2935
for (cv = D_cvlist; cv; cv = cv->c_next)
2936
if (cv->c_layer->l_bottom == &p->w_layer)
2944
WindowChangedCheck(s, what, hp)
2953
if (*s++ != (hp ? '%' : '\005'))
2956
while (*s >= '0' && *s <= '9')
2965
if (*s == what || ((*s | l) == what) || what == 'd')
2976
WindowChanged(p, what)
2980
int inwstr, inhstr, inlstr;
2981
int inwstrh = 0, inhstrh = 0, inlstrh = 0;
2983
struct display *olddisplay = display;
2986
inwstr = inhstr = 0;
2990
WindowChanged((struct win *)0, 'w'|0x100);
2991
WindowChanged((struct win *)0, 'W'|0x100);
2996
inwstr = WindowChangedCheck(captionstring, what, &inwstrh);
2997
inhstr = WindowChangedCheck(hstatusstring, what, &inhstrh);
2998
inlstr = WindowChangedCheck(wliststr, what, &inlstrh);
3002
inwstr = inhstr = 0;
3008
for (display = displays; display; display = display->d_next)
3012
for (cv = D_cvlist; cv; cv = cv->c_next)
3014
if (inlstr || (inlstrh && p && p->w_hstatus && *p->w_hstatus && WindowChangedCheck(p->w_hstatus, what, (int *)0)))
3015
WListUpdatecv(cv, (struct win *)0);
3016
p = Layer2Window(cv->c_layer);
3017
if (inwstr || (inwstrh && p && p->w_hstatus && *p->w_hstatus && WindowChangedCheck(p->w_hstatus, what, (int *)0)))
3018
if (cv->c_ye + 1 < D_height)
3019
RefreshLine(cv->c_ye + 1, 0, D_width - 1, 0);
3022
if (inhstr || (inhstrh && p && p->w_hstatus && *p->w_hstatus && WindowChangedCheck(p->w_hstatus, what, (int *)0)))
3024
if (ox != -1 && ox != -1)
3027
display = olddisplay;
3031
if (p->w_hstatus && *p->w_hstatus && (inwstrh || inhstrh || inlstrh) && WindowChangedCheck(p->w_hstatus, what, (int *)0))
3037
if (!inwstr && !inhstr && !inlstr)
3039
for (display = displays; display; display = display->d_next)
3044
for (cv = D_cvlist; cv; cv = cv->c_next)
3047
WListUpdatecv(cv, p);
3048
if (Layer2Window(cv->c_layer) != p)
3051
if (inwstr && cv->c_ye + 1 < D_height)
3052
RefreshLine(cv->c_ye + 1, 0, D_width - 1, 0);
3054
if (got && inhstr && p == D_fore)
3056
if (ox != -1 && ox != -1)
3059
display = olddisplay;