term: handle DECSTBM to set scrolling region
[fbpad.git] / vt102.c
blob378966a77216c3a5cb957e0d104ef14958ca7f7d
1 static void escseq(void);
2 static void escseq_cs(void);
3 static void escseq_g0(void);
4 static void escseq_g1(void);
5 static void escseq_g2(void);
6 static void escseq_g3(void);
7 static void csiseq(void);
8 static void modeseq(int c, int set);
10 /* control sequences */
11 static void ctlseq(void)
13 int c = readpty();
14 switch (c) {
15 case 0x09: /* HT horizontal tab to next tab stop */
16 move_cursor(row, (col / 8 + 1) * 8);
17 break;
18 case 0x0a: /* LF line feed */
19 case 0x0b: /* VT line feed */
20 case 0x0c: /* FF line feed */
21 move_cursor(row + 1, 0);
22 break;
23 case 0x08: /* BS backspace one column */
24 move_cursor(row, col - 1);
25 break;
26 case 0x1b: /* ESC start escape sequence */
27 escseq();
28 break;
29 case 0x0d: /* CR carriage return */
30 move_cursor(row, 0);
31 break;
32 case 0x00: /* NUL ignored */
33 case 0x07: /* BEL beep */
34 case 0x3f: /* DEL ignored */
35 break;
36 case 0x05: /* ENQ trigger answerback message */
37 case 0x0e: /* SO activate G1 character set & newline */
38 case 0x0f: /* SI activate G0 character set */
39 case 0x11: /* XON resume transmission */
40 case 0x13: /* XOFF stop transmission, ignore characters */
41 case 0x18: /* CAN interrupt escape sequence */
42 case 0x1a: /* SUB interrupt escape sequence */
43 case 0x9b: /* CSI equivalent to ESC [ */
44 printf("ctlseq: <%d:%c>\n", c, c);
45 break;
46 default:
47 term_put(c, row, col);
48 advance(0, 1);
49 break;
53 /* escape sequences */
54 static void escseq(void)
56 int c = readpty();
57 switch(c) {
58 case 'M': /* RI reverse line feed */
59 scroll_screen(top, bot - top - 1, 1);
60 break;
61 case '[': /* CSI control sequence introducer */
62 csiseq();
63 break;
64 case '%': /* CS... escseq_cs table */
65 escseq_cs();
66 break;
67 case '(': /* G0... escseq_g0 table */
68 escseq_g0();
69 break;
70 case ')': /* G1... escseq_g1 table */
71 escseq_g1();
72 break;
73 case '*': /* G2... escseq_g2 table */
74 escseq_g2();
75 break;
76 case '+': /* G3... escseq_g3 table */
77 escseq_g3();
78 break;
79 case 'c': /* RIS reset */
80 case 'D': /* IND line feed */
81 case 'E': /* NEL newline */
82 case 'H': /* HTS set tab stop at current column */
83 case 'Z': /* DECID DEC private ID; return ESC [ ? 6 c (VT102) */
84 case '7': /* DECSC save state (position, charset, attributes) */
85 case '8': /* DECRC restore most recently saved state */
86 case '#': /* DECALN ("#8") DEC alignment test - fill screen with E's */
87 case '>': /* DECPNM set numeric keypad mode */
88 case '=': /* DECPAM set application keypad mode */
89 case 'N': /* SS2 select G2 charset for next char only */
90 case 'O': /* SS3 select G3 charset for next char only */
91 case 'P': /* DCS device control string (ended by ST) */
92 case 'X': /* SOS start of string */
93 case '^': /* PM privacy message (ended by ST) */
94 case '_': /* APC application program command (ended by ST) */
95 case '\\': /* ST string terminator */
96 case 'n': /* LS2 invoke G2 charset */
97 case 'o': /* LS3 invoke G3 charset */
98 case '|': /* LS3R invoke G3 charset as GR */
99 case '}': /* LS2R invoke G2 charset as GR */
100 case '~': /* LS1R invoke G1 charset as GR */
101 case ']': /* OSC operating system command */
102 case 'g': /* BEL alternate BEL */
103 default:
104 printf("escseq: <%d:%c>\n", c, c);
105 break;
109 static void escseq_cs(void)
111 int c = readpty();
112 switch(c) {
113 case '@': /* CSDFL select default charset (ISO646/8859-1) */
114 case 'G': /* CSUTF8 select UTF-8 */
115 case '8': /* CSUTF8 select UTF-8 (obsolete) */
116 default:
117 printf("escseq_cs: <%d:%c>\n", c, c);
118 break;
122 static void escseq_g0(void)
124 int c = readpty();
125 switch(c) {
126 case '8': /* G0DFL G0 charset = default mapping (ISO8859-1) */
127 case '0': /* G0GFX G0 charset = VT100 graphics mapping */
128 case 'U': /* G0ROM G0 charset = null mapping (straight to ROM) */
129 case 'K': /* G0USR G0 charset = user defined mapping */
130 case 'B': /* G0TXT G0 charset = ASCII mapping */
131 default:
132 printf("escseq_g0: <%d:%c>\n", c, c);
133 break;
137 static void escseq_g1(void)
139 int c = readpty();
140 switch(c) {
141 case '8': /* G1DFL G1 charset = default mapping (ISO8859-1) */
142 case '0': /* G1GFX G1 charset = VT100 graphics mapping */
143 case 'U': /* G1ROM G1 charset = null mapping (straight to ROM) */
144 case 'K': /* G1USR G1 charset = user defined mapping */
145 case 'B': /* G1TXT G1 charset = ASCII mapping */
146 default:
147 printf("escseq_g1: <%d:%c>\n", c, c);
148 break;
152 static void escseq_g2(void)
154 int c = readpty();
155 switch(c) {
156 case '8': /* G2DFL G2 charset = default mapping (ISO8859-1) */
157 case '0': /* G2GFX G2 charset = VT100 graphics mapping */
158 case 'U': /* G2ROM G2 charset = null mapping (straight to ROM) */
159 case 'K': /* G2USR G2 charset = user defined mapping */
160 default:
161 printf("escseq_g2: <%d:%c>\n", c, c);
162 break;
166 static void escseq_g3(void)
168 int c = readpty();
169 switch(c) {
170 case '8': /* G3DFL G3 charset = default mapping (ISO8859-1) */
171 case '0': /* G3GFX G3 charset = VT100 graphics mapping */
172 case 'U': /* G3ROM G3 charset = null mapping (straight to ROM) */
173 case 'K': /* G3USR G3 charset = user defined mapping */
174 default:
175 printf("escseq_g3: <%d:%c>\n", c, c);
176 break;
180 #define MAXCSIARGS 32
181 /* ECMA-48 CSI sequences */
182 static void csiseq(void)
184 int args[MAXCSIARGS] = {0};
185 int i;
186 int n = 0;
187 int c = 0;
188 for (i = 0; i < ARRAY_SIZE(args) && !isalpha(c); i++) {
189 int arg = 0;
190 while (isdigit((c = readpty())))
191 arg = arg * 10 + (c - '0');
192 args[n++] = arg;
194 switch(c) {
195 case 'H': /* CUP move cursor to row, column */
196 case 'f': /* HVP move cursor to row, column */
197 move_cursor(MAX(0, args[0] - 1), MAX(0, args[1] - 1));
198 break;
199 case 'J': /* ED erase display */
200 switch(args[0]) {
201 case 0:
202 kill_chars(col, pad_cols());
203 blank_rows(row + 1, pad_rows());
204 break;
205 case 1:
206 kill_chars(0, col + 1);
207 blank_rows(0, row - 1);
208 break;
209 case 2:
210 term_blank();
211 break;
213 break;
214 case 'A': /* CUU move cursor up */
215 advance(MAX(1, args[0]), 0);
216 break;
217 case 'B': /* CUD move cursor down */
218 advance(MAX(1, args[0]), 0);
219 break;
220 case 'C': /* CUF move cursor right */
221 advance(0, MAX(1, args[0]));
222 break;
223 case 'D': /* CUB move cursor left */
224 move_cursor(0, -MAX(1, args[0]));
225 break;
226 case 'K': /* EL erase line */
227 kill_chars(col, pad_cols());
228 break;
229 case 'L': /* IL insert blank lines */
230 insert_lines(MAX(1, args[0]));
231 break;
232 case 'M': /* DL delete lines */
233 delete_lines(MAX(1, args[0]));
234 break;
235 case 'd': /* VPA move to row (current column) */
236 move_cursor(MAX(1, args[0]), col);
237 break;
238 case 'm': /* SGR set graphic rendition */
239 setmode(0);
240 for (i = 0; i < n; i++)
241 setmode(args[i]);
242 break;
243 case 'h': /* SM set mode */
244 modeseq(n <= 1 ? args[0] : 0x80 | args[1], 1);
245 break;
246 case 'l': /* RM reset mode */
247 modeseq(n <= 1 ? args[0] : 0x80 | args[1], 0);
248 break;
249 case 'r': /* DECSTBM set scrolling region to (top, bottom) rows */
250 top = MIN(pad_rows(), MAX(0, args[0] - 1));
251 bot = MIN(pad_rows(), MAX(0, args[1] ? args[1] : pad_rows()));
252 break;
253 case '[': /* IGN ignored control sequence */
254 case '@': /* ICH insert blank characters */
255 case 'E': /* CNL move cursor down and to column 1 */
256 case 'F': /* CPL move cursor up and to column 1 */
257 case 'G': /* CHA move cursor to column in current row */
258 case 'P': /* DCH delete characters on current line */
259 case 'X': /* ECH erase characters on current line */
260 case 'a': /* HPR move cursor right */
261 case 'c': /* DA return ESC [ ? 6 c (VT102) */
262 case 'e': /* VPR move cursor down */
263 case 'g': /* TBC clear tab stop (CSI 3 g = clear all stops) */
264 case 'n': /* DSR device status report */
265 case 'q': /* DECLL set keyboard LEDs */
266 case 's': /* CUPSV save cursor position */
267 case 'u': /* CUPRS restore cursor position */
268 case '`': /* HPA move cursor to column in current row */
269 default:
270 printf("csiseq: <%d:%c>:", c, c);
271 for (i = 0; i < n; i++)
272 printf(" %d", args[i]);
273 printf("\n");
274 break;
278 /* ANSI/DEC specified modes for SM/RM ANSI Specified Modes */
279 static void modeseq(int c, int set)
281 switch(c) {
282 case 0x00: /* IGN Error (Ignored) */
283 case 0x01: /* GATM guarded-area transfer mode (ignored) */
284 case 0x02: /* KAM keyboard action mode (always reset) */
285 case 0x03: /* CRM control representation mode (always reset) */
286 case 0x04: /* IRM insertion/replacement mode (always reset) */
287 case 0x05: /* SRTM status-reporting transfer mode */
288 case 0x06: /* ERM erasure mode (always set) */
289 case 0x07: /* VEM vertical editing mode (ignored) */
290 case 0x0a: /* HEM horizontal editing mode */
291 case 0x0b: /* PUM positioning unit mode */
292 case 0x0c: /* SRM send/receive mode (echo on/off) */
293 case 0x0d: /* FEAM format effector action mode */
294 case 0x0e: /* FETM format effector transfer mode */
295 case 0x0f: /* MATM multiple area transfer mode */
296 case 0x10: /* TTM transfer termination mode */
297 case 0x11: /* SATM selected area transfer mode */
298 case 0x12: /* TSM tabulation stop mode */
299 case 0x13: /* EBM editing boundary mode */
300 case 0x14: /* LNM Line Feed / New Line Mode */
301 /* DEC Private Modes: "?NUM" -> (NUM | 0x80) */
302 case 0x80: /* IGN Error (Ignored) */
303 case 0x81: /* DECCKM Cursorkeys application (set); Cursorkeys normal (reset) */
304 case 0x82: /* DECANM ANSI (set); VT52 (reset) */
305 case 0x83: /* DECCOLM 132 columns (set); 80 columns (reset) */
306 case 0x84: /* DECSCLM Jump scroll (set); Smooth scroll (reset) */
307 case 0x85: /* DECSCNM Reverse screen (set); Normal screen (reset) */
308 case 0x86: /* DECOM Sets relative coordinates (set); Sets absolute coordinates (reset) */
309 case 0x87: /* DECAWM Auto Wrap */
310 case 0x88: /* DECARM Auto Repeat */
311 case 0x89: /* DECINLM Interlace */
312 case 0x92: /* DECPFF Send FF to printer after print screen (set); No char after PS (reset) */
313 case 0x93: /* DECPEX Print screen: prints full screen (set); prints scroll region (reset) */
314 case 0x99: /* DECTCEM Cursor on (set); Cursor off (reset) */
315 default:
316 printf("modeseq: <0x%x>\n", c);
317 break;