Annotation of src/usr.bin/tmux/input.c, Revision 1.22
1.22 ! nicm 1: /* $OpenBSD: input.c,v 1.21 2009/10/26 21:42:04 deraadt Exp $ */
1.1 nicm 2:
3: /*
4: * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15: * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16: * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: #include <sys/types.h>
20:
21: #include <stdint.h>
22: #include <stdlib.h>
23: #include <string.h>
24:
25: #include "tmux.h"
26:
27: #define INPUT_C0CONTROL(ch) (ch <= 0x1f)
28: #define INPUT_INTERMEDIATE(ch) (ch == 0xa0 || (ch >= 0x20 && ch <= 0x2f))
29: #define INPUT_PARAMETER(ch) (ch >= 0x30 && ch <= 0x3f)
30: #define INPUT_UPPERCASE(ch) (ch >= 0x40 && ch <= 0x5f)
31: #define INPUT_LOWERCASE(ch) (ch >= 0x60 && ch <= 0x7e)
32: #define INPUT_DELETE(ch) (ch == 0x7f)
33: #define INPUT_C1CONTROL(ch) (ch >= 0x80 && ch <= 0x9f)
34: #define INPUT_G1DISPLAYABLE(ch) (ch >= 0xa1 && ch <= 0xfe)
35: #define INPUT_SPECIAL(ch) (ch == 0xff)
36:
37: int input_get_argument(struct input_ctx *, u_int, uint16_t *, uint16_t);
1.10 nicm 38: void input_new_argument(struct input_ctx *);
1.1 nicm 39: int input_add_argument(struct input_ctx *, u_char);
40:
41: void input_start_string(struct input_ctx *, int);
42: void input_abort_string(struct input_ctx *);
43: int input_add_string(struct input_ctx *, u_char);
44: char *input_get_string(struct input_ctx *);
45:
46: void input_state(struct input_ctx *, void *);
47:
48: void input_state_first(u_char, struct input_ctx *);
49: void input_state_escape(u_char, struct input_ctx *);
50: void input_state_intermediate(u_char, struct input_ctx *);
51: void input_state_sequence_first(u_char, struct input_ctx *);
52: void input_state_sequence_next(u_char, struct input_ctx *);
53: void input_state_sequence_intermediate(u_char, struct input_ctx *);
54: void input_state_string_next(u_char, struct input_ctx *);
55: void input_state_string_escape(u_char, struct input_ctx *);
56: void input_state_utf8(u_char, struct input_ctx *);
57:
58: void input_handle_character(u_char, struct input_ctx *);
59: void input_handle_c0_control(u_char, struct input_ctx *);
60: void input_handle_c1_control(u_char, struct input_ctx *);
61: void input_handle_private_two(u_char, struct input_ctx *);
62: void input_handle_standard_two(u_char, struct input_ctx *);
63: void input_handle_sequence(u_char, struct input_ctx *);
64:
65: void input_handle_sequence_cuu(struct input_ctx *);
66: void input_handle_sequence_cud(struct input_ctx *);
67: void input_handle_sequence_cuf(struct input_ctx *);
68: void input_handle_sequence_cub(struct input_ctx *);
69: void input_handle_sequence_dch(struct input_ctx *);
1.8 nicm 70: void input_handle_sequence_cbt(struct input_ctx *);
1.14 nicm 71: void input_handle_sequence_da(struct input_ctx *);
1.1 nicm 72: void input_handle_sequence_dl(struct input_ctx *);
73: void input_handle_sequence_ich(struct input_ctx *);
74: void input_handle_sequence_il(struct input_ctx *);
75: void input_handle_sequence_vpa(struct input_ctx *);
76: void input_handle_sequence_hpa(struct input_ctx *);
77: void input_handle_sequence_cup(struct input_ctx *);
78: void input_handle_sequence_cup(struct input_ctx *);
1.7 nicm 79: void input_handle_sequence_tbc(struct input_ctx *);
1.1 nicm 80: void input_handle_sequence_ed(struct input_ctx *);
81: void input_handle_sequence_el(struct input_ctx *);
82: void input_handle_sequence_sm(struct input_ctx *);
83: void input_handle_sequence_rm(struct input_ctx *);
84: void input_handle_sequence_decstbm(struct input_ctx *);
85: void input_handle_sequence_sgr(struct input_ctx *);
86: void input_handle_sequence_dsr(struct input_ctx *);
87:
88: int input_sequence_cmp(const void *, const void *);
89:
90: struct input_sequence_entry {
91: u_char ch;
92: void (*fn)(struct input_ctx *);
93: };
94: const struct input_sequence_entry input_sequence_table[] = {
95: { '@', input_handle_sequence_ich },
96: { 'A', input_handle_sequence_cuu },
97: { 'B', input_handle_sequence_cud },
98: { 'C', input_handle_sequence_cuf },
99: { 'D', input_handle_sequence_cub },
100: { 'G', input_handle_sequence_hpa },
101: { 'H', input_handle_sequence_cup },
102: { 'J', input_handle_sequence_ed },
103: { 'K', input_handle_sequence_el },
104: { 'L', input_handle_sequence_il },
105: { 'M', input_handle_sequence_dl },
106: { 'P', input_handle_sequence_dch },
1.8 nicm 107: { 'Z', input_handle_sequence_cbt },
1.14 nicm 108: { 'c', input_handle_sequence_da },
1.1 nicm 109: { 'd', input_handle_sequence_vpa },
110: { 'f', input_handle_sequence_cup },
1.7 nicm 111: { 'g', input_handle_sequence_tbc },
1.1 nicm 112: { 'h', input_handle_sequence_sm },
113: { 'l', input_handle_sequence_rm },
114: { 'm', input_handle_sequence_sgr },
115: { 'n', input_handle_sequence_dsr },
116: { 'r', input_handle_sequence_decstbm },
117: };
118:
119: int
120: input_sequence_cmp(const void *a, const void *b)
121: {
122: int ai = ((const struct input_sequence_entry *) a)->ch;
123: int bi = ((const struct input_sequence_entry *) b)->ch;
124:
125: return (ai - bi);
126: }
127:
1.10 nicm 128: void
1.1 nicm 129: input_new_argument(struct input_ctx *ictx)
130: {
1.21 deraadt 131: struct input_arg *arg;
1.1 nicm 132:
133: ARRAY_EXPAND(&ictx->args, 1);
134:
135: arg = &ARRAY_LAST(&ictx->args);
136: arg->used = 0;
137: }
138:
139: int
140: input_add_argument(struct input_ctx *ictx, u_char ch)
141: {
1.21 deraadt 142: struct input_arg *arg;
1.1 nicm 143:
144: if (ARRAY_LENGTH(&ictx->args) == 0)
145: return (0);
146:
147: arg = &ARRAY_LAST(&ictx->args);
148: if (arg->used > (sizeof arg->data) - 1)
149: return (-1);
150: arg->data[arg->used++] = ch;
151:
152: return (0);
153: }
154:
155: int
156: input_get_argument(struct input_ctx *ictx, u_int i, uint16_t *n, uint16_t d)
157: {
158: struct input_arg *arg;
159: const char *errstr;
160:
161: *n = d;
162: if (i >= ARRAY_LENGTH(&ictx->args))
163: return (0);
164:
165: arg = &ARRAY_ITEM(&ictx->args, i);
166: if (*arg->data == '\0')
167: return (0);
168:
169: *n = strtonum(arg->data, 0, UINT16_MAX, &errstr);
170: if (errstr != NULL)
171: return (-1);
172: return (0);
173: }
174:
175: void
176: input_start_string(struct input_ctx *ictx, int type)
177: {
178: ictx->string_type = type;
179: ictx->string_len = 0;
180: }
181:
182: void
183: input_abort_string(struct input_ctx *ictx)
184: {
185: if (ictx->string_buf != NULL)
186: xfree(ictx->string_buf);
187: ictx->string_buf = NULL;
188: }
189:
190: int
191: input_add_string(struct input_ctx *ictx, u_char ch)
192: {
193: ictx->string_buf = xrealloc(ictx->string_buf, 1, ictx->string_len + 1);
194: ictx->string_buf[ictx->string_len++] = ch;
195:
196: if (ictx->string_len >= MAXSTRINGLEN) {
197: input_abort_string(ictx);
198: return (1);
199: }
200:
201: return (0);
202: }
203:
204: char *
205: input_get_string(struct input_ctx *ictx)
206: {
207: char *s;
208:
209: if (ictx->string_buf == NULL || input_add_string(ictx, '\0') != 0)
210: return (xstrdup(""));
211:
212: s = ictx->string_buf;
213: ictx->string_buf = NULL;
214: return (s);
215: }
216:
217: void
218: input_state(struct input_ctx *ictx, void *state)
219: {
220: ictx->state = state;
221: }
222:
223: void
224: input_init(struct window_pane *wp)
225: {
226: struct input_ctx *ictx = &wp->ictx;
227:
228: ARRAY_INIT(&ictx->args);
229:
230: ictx->string_len = 0;
231: ictx->string_buf = NULL;
232:
233: memcpy(&ictx->cell, &grid_default_cell, sizeof ictx->cell);
234:
235: memcpy(&ictx->saved_cell, &grid_default_cell, sizeof ictx->saved_cell);
236: ictx->saved_cx = 0;
237: ictx->saved_cy = 0;
238:
239: input_state(ictx, input_state_first);
1.13 nicm 240:
241: ictx->was = 0;
1.1 nicm 242: }
243:
244: void
245: input_free(struct window_pane *wp)
246: {
247: if (wp->ictx.string_buf != NULL)
248: xfree(wp->ictx.string_buf);
249:
250: ARRAY_FREE(&wp->ictx.args);
251: }
252:
253: void
254: input_parse(struct window_pane *wp)
255: {
256: struct input_ctx *ictx = &wp->ictx;
257: u_char ch;
258:
1.22 ! nicm 259: if (EVBUFFER_LENGTH(wp->event->input) == ictx->was)
1.1 nicm 260: return;
1.13 nicm 261: wp->window->flags |= WINDOW_ACTIVITY;
1.1 nicm 262:
1.22 ! nicm 263: ictx->buf = EVBUFFER_DATA(wp->event->input);
! 264: ictx->len = EVBUFFER_LENGTH(wp->event->input);
1.1 nicm 265: ictx->off = 0;
266:
267: ictx->wp = wp;
268:
269: if (wp->mode == NULL)
270: screen_write_start(&ictx->ctx, wp, &wp->base);
271: else
272: screen_write_start(&ictx->ctx, NULL, &wp->base);
273:
274: while (ictx->off < ictx->len) {
275: ch = ictx->buf[ictx->off++];
276: ictx->state(ch, ictx);
277: }
278:
279: screen_write_stop(&ictx->ctx);
280:
1.22 ! nicm 281: evbuffer_drain(wp->event->input, ictx->len);
! 282: ictx->was = EVBUFFER_LENGTH(wp->event->input);
1.1 nicm 283: }
284:
285: void
286: input_state_first(u_char ch, struct input_ctx *ictx)
287: {
288: ictx->intermediate = '\0';
289:
290: if (INPUT_C0CONTROL(ch)) {
291: if (ch == 0x1b)
292: input_state(ictx, input_state_escape);
293: else
294: input_handle_c0_control(ch, ictx);
295: return;
296: }
297:
298: #if 0
299: if (INPUT_C1CONTROL(ch)) {
300: ch -= 0x40;
301: if (ch == '[')
302: input_state(ictx, input_state_sequence_first);
303: else if (ch == ']') {
304: input_start_string(ictx, STRING_SYSTEM);
305: input_state(ictx, input_state_string_next);
306: } else if (ch == '_') {
307: input_start_string(ictx, STRING_APPLICATION);
308: input_state(ictx, input_state_string_next);
309: } else
310: input_handle_c1_control(ch, ictx);
311: return;
312: }
313: #endif
314:
315: if (INPUT_DELETE(ch))
316: return;
317:
318: input_handle_character(ch, ictx);
319: }
320:
321: void
322: input_state_escape(u_char ch, struct input_ctx *ictx)
323: {
324: /* Treat C1 control and G1 displayable as 7-bit equivalent. */
325: if (INPUT_C1CONTROL(ch) || INPUT_G1DISPLAYABLE(ch))
326: ch &= 0x7f;
327:
328: if (INPUT_C0CONTROL(ch)) {
329: input_handle_c0_control(ch, ictx);
330: return;
331: }
332:
333: if (INPUT_INTERMEDIATE(ch)) {
334: log_debug2(":: in1 %zu: %hhu (%c)", ictx->off, ch, ch);
335: ictx->intermediate = ch;
336: input_state(ictx, input_state_intermediate);
337: return;
338: }
339:
340: if (INPUT_PARAMETER(ch)) {
341: input_state(ictx, input_state_first);
342: input_handle_private_two(ch, ictx);
343: return;
344: }
345:
346: if (INPUT_UPPERCASE(ch)) {
347: if (ch == '[')
348: input_state(ictx, input_state_sequence_first);
349: else if (ch == ']') {
350: input_start_string(ictx, STRING_SYSTEM);
351: input_state(ictx, input_state_string_next);
352: } else if (ch == '_') {
353: input_start_string(ictx, STRING_APPLICATION);
354: input_state(ictx, input_state_string_next);
355: } else {
356: input_state(ictx, input_state_first);
357: input_handle_c1_control(ch, ictx);
358: }
359: return;
360: }
361:
362: if (INPUT_LOWERCASE(ch)) {
363: input_state(ictx, input_state_first);
364: input_handle_standard_two(ch, ictx);
365: return;
366: }
367:
368: input_state(ictx, input_state_first);
369: }
370:
371: void
372: input_state_intermediate(u_char ch, struct input_ctx *ictx)
373: {
374: if (INPUT_INTERMEDIATE(ch)) {
375: /* Multiple intermediates currently ignored. */
376: log_debug2(":: in2 %zu: %hhu (%c)", ictx->off, ch, ch);
377: return;
378: }
379:
380: if (INPUT_PARAMETER(ch)) {
381: input_state(ictx, input_state_first);
382: input_handle_private_two(ch, ictx);
383: return;
384: }
385:
386: if (INPUT_UPPERCASE(ch) || INPUT_LOWERCASE(ch)) {
387: input_state(ictx, input_state_first);
388: input_handle_standard_two(ch, ictx);
389: return;
390: }
391:
392: input_state(ictx, input_state_first);
393: }
394:
395: void
396: input_state_sequence_first(u_char ch, struct input_ctx *ictx)
397: {
398: ictx->private = '\0';
399: ARRAY_CLEAR(&ictx->args);
400:
1.4 nicm 401: /* Most C0 control are accepted within CSI. */
402: if (INPUT_C0CONTROL(ch)) {
403: if (ch == 0x1b) { /* ESC */
404: /* Abort sequence and begin with new. */
405: input_state(ictx, input_state_escape);
1.6 nicm 406: return;
407: } else if (ch == 0x18 || ch == 0x1a) { /* CAN and SUB */
1.5 nicm 408: /* Abort sequence. */
409: input_state(ictx, input_state_first);
1.6 nicm 410: return;
1.4 nicm 411: }
1.6 nicm 412:
413: /* Handle C0 immediately. */
414: input_handle_c0_control(ch, ictx);
415:
1.4 nicm 416: /*
417: * Just come back to this state, in case the next character
418: * is the start of a private sequence.
419: */
420: return;
421: }
422:
1.1 nicm 423: input_state(ictx, input_state_sequence_next);
424:
1.4 nicm 425: /* Private sequence: always the first character. */
426: if (ch >= 0x3c && ch <= 0x3f) {
427: ictx->private = ch;
428: return;
1.1 nicm 429: }
430:
431: /* Pass character on directly. */
432: input_state_sequence_next(ch, ictx);
433: }
434:
435: void
436: input_state_sequence_next(u_char ch, struct input_ctx *ictx)
437: {
438: if (INPUT_INTERMEDIATE(ch)) {
439: if (input_add_argument(ictx, '\0') != 0)
440: input_state(ictx, input_state_first);
441: else {
442: log_debug2(":: si1 %zu: %hhu (%c)", ictx->off, ch, ch);
443: input_state(ictx, input_state_sequence_intermediate);
444: }
445: return;
446: }
447:
448: if (INPUT_PARAMETER(ch)) {
1.4 nicm 449: if (ARRAY_EMPTY(&ictx->args))
450: input_new_argument(ictx);
451:
1.1 nicm 452: if (ch == ';') {
453: if (input_add_argument(ictx, '\0') != 0)
454: input_state(ictx, input_state_first);
455: else
456: input_new_argument(ictx);
457: } else if (input_add_argument(ictx, ch) != 0)
458: input_state(ictx, input_state_first);
459: return;
460: }
461:
462: if (INPUT_UPPERCASE(ch) || INPUT_LOWERCASE(ch)) {
463: if (input_add_argument(ictx, '\0') != 0)
464: input_state(ictx, input_state_first);
465: else {
466: input_state(ictx, input_state_first);
467: input_handle_sequence(ch, ictx);
468: }
469: return;
470: }
471:
1.4 nicm 472: /* Most C0 control are accepted within CSI. */
473: if (INPUT_C0CONTROL(ch)) {
474: if (ch == 0x1b) { /* ESC */
475: /* Abort sequence and begin with new. */
476: input_state(ictx, input_state_escape);
1.6 nicm 477: return;
478: } else if (ch == 0x18 || ch == 0x1a) { /* CAN and SUB */
1.5 nicm 479: /* Abort sequence. */
480: input_state(ictx, input_state_first);
1.6 nicm 481: return;
1.4 nicm 482: }
1.6 nicm 483:
484: /* Handle C0 immediately. */
485: input_handle_c0_control(ch, ictx);
486:
1.4 nicm 487: return;
488: }
489:
1.1 nicm 490: input_state(ictx, input_state_first);
491: }
492:
493: void
494: input_state_sequence_intermediate(u_char ch, struct input_ctx *ictx)
495: {
496: if (INPUT_INTERMEDIATE(ch)) {
497: log_debug2(":: si2 %zu: %hhu (%c)", ictx->off, ch, ch);
498: return;
499: }
500:
501: if (INPUT_UPPERCASE(ch) || INPUT_LOWERCASE(ch)) {
502: input_state(ictx, input_state_first);
503: input_handle_sequence(ch, ictx);
504: return;
505: }
506:
507: input_state(ictx, input_state_first);
508: }
509:
510: void
511: input_state_string_next(u_char ch, struct input_ctx *ictx)
512: {
513: if (ch == 0x1b) {
514: input_state(ictx, input_state_string_escape);
515: return;
516: }
517: if (ch == 0x07) {
518: input_state_string_escape(ch, ictx);
519: return;
520: }
521:
1.2 nicm 522: if (ch >= 0x20) {
1.1 nicm 523: if (input_add_string(ictx, ch) != 0)
524: input_state(ictx, input_state_first);
525: return;
526: }
527: }
528:
529: void
530: input_state_string_escape(u_char ch, struct input_ctx *ictx)
531: {
532: char *s;
533:
534: if (ch == '\007' || ch == '\\') {
535: input_state(ictx, input_state_first);
536: switch (ictx->string_type) {
537: case STRING_SYSTEM:
538: if (ch != '\007')
539: return;
540: s = input_get_string(ictx);
541: if ((s[0] != '0' && s[0] != '2') || s[1] != ';') {
542: xfree(s);
543: return;
544: }
545: screen_set_title(ictx->ctx.s, s + 2);
546: server_status_window(ictx->wp->window);
547: xfree(s);
548: break;
549: case STRING_APPLICATION:
550: if (ch != '\\')
551: return;
552: s = input_get_string(ictx);
553: screen_set_title(ictx->ctx.s, s);
554: server_status_window(ictx->wp->window);
555: xfree(s);
556: break;
557: case STRING_NAME:
558: if (ch != '\\')
559: return;
560: xfree(ictx->wp->window->name);
561: ictx->wp->window->name = input_get_string(ictx);
562: server_status_window(ictx->wp->window);
563: break;
564: }
565: return;
566: }
567:
568: input_state(ictx, input_state_string_next);
569: input_state_string_next(ch, ictx);
570: }
571:
572: void
573: input_state_utf8(u_char ch, struct input_ctx *ictx)
574: {
1.18 nicm 575: log_debug2("-- utf8 next: %zu: %hhu (%c)", ictx->off, ch, ch);
1.1 nicm 576:
1.18 nicm 577: if (utf8_append(&ictx->utf8data, ch))
578: return; /* more to come */
1.1 nicm 579: input_state(ictx, input_state_first);
580:
581: ictx->cell.flags |= GRID_FLAG_UTF8;
1.18 nicm 582: screen_write_cell(&ictx->ctx, &ictx->cell, &ictx->utf8data);
1.1 nicm 583: ictx->cell.flags &= ~GRID_FLAG_UTF8;
584: }
585:
586: void
587: input_handle_character(u_char ch, struct input_ctx *ictx)
588: {
589: struct window_pane *wp = ictx->wp;
590:
591: if (ch > 0x7f && options_get_number(&wp->window->options, "utf8")) {
1.18 nicm 592: if (utf8_open(&ictx->utf8data, ch)) {
1.19 nicm 593: log_debug2("-- utf8 size %zu: %zu: %hhu (%c)",
1.18 nicm 594: ictx->utf8data.size, ictx->off, ch, ch);
1.1 nicm 595: input_state(ictx, input_state_utf8);
596: return;
597: }
598: }
599: log_debug2("-- ch %zu: %hhu (%c)", ictx->off, ch, ch);
600:
601: ictx->cell.data = ch;
1.18 nicm 602: screen_write_cell(&ictx->ctx, &ictx->cell, NULL);
1.1 nicm 603: }
604:
605: void
606: input_handle_c0_control(u_char ch, struct input_ctx *ictx)
607: {
608: struct screen *s = ictx->ctx.s;
609:
610: log_debug2("-- c0 %zu: %hhu", ictx->off, ch);
611:
612: switch (ch) {
613: case '\0': /* NUL */
614: break;
615: case '\n': /* LF */
1.12 nicm 616: screen_write_linefeed(&ictx->ctx, 0);
1.1 nicm 617: break;
618: case '\r': /* CR */
619: screen_write_carriagereturn(&ictx->ctx);
620: break;
621: case '\007': /* BELL */
622: ictx->wp->window->flags |= WINDOW_BELL;
623: break;
624: case '\010': /* BS */
1.16 nicm 625: screen_write_backspace(&ictx->ctx);
1.1 nicm 626: break;
627: case '\011': /* TAB */
1.7 nicm 628: /* Don't tab beyond the end of the line. */
629: if (s->cx >= screen_size_x(s) - 1)
630: break;
631:
632: /* Find the next tab point, or use the last column if none. */
633: do {
634: s->cx++;
635: if (bit_test(s->tabs, s->cx))
636: break;
637: } while (s->cx < screen_size_x(s) - 1);
1.4 nicm 638: break;
639: case '\013': /* VT */
1.12 nicm 640: screen_write_linefeed(&ictx->ctx, 0);
1.1 nicm 641: break;
642: case '\016': /* SO */
643: ictx->cell.attr |= GRID_ATTR_CHARSET;
644: break;
645: case '\017': /* SI */
646: ictx->cell.attr &= ~GRID_ATTR_CHARSET;
647: break;
648: default:
649: log_debug("unknown c0: %hhu", ch);
650: break;
651: }
652: }
653:
654: void
655: input_handle_c1_control(u_char ch, struct input_ctx *ictx)
656: {
1.7 nicm 657: struct screen *s = ictx->ctx.s;
658:
1.1 nicm 659: log_debug2("-- c1 %zu: %hhu (%c)", ictx->off, ch, ch);
660:
661: switch (ch) {
1.3 nicm 662: case 'D': /* IND */
1.12 nicm 663: screen_write_linefeed(&ictx->ctx, 0);
1.3 nicm 664: break;
1.1 nicm 665: case 'E': /* NEL */
666: screen_write_carriagereturn(&ictx->ctx);
1.12 nicm 667: screen_write_linefeed(&ictx->ctx, 0);
1.1 nicm 668: break;
1.7 nicm 669: case 'H': /* HTS */
670: if (s->cx < screen_size_x(s))
671: bit_set(s->tabs, s->cx);
672: break;
1.1 nicm 673: case 'M': /* RI */
674: screen_write_reverseindex(&ictx->ctx);
675: break;
676: default:
677: log_debug("unknown c1: %hhu", ch);
678: break;
679: }
680: }
681:
682: void
683: input_handle_private_two(u_char ch, struct input_ctx *ictx)
684: {
685: struct screen *s = ictx->ctx.s;
686:
687: log_debug2(
688: "-- p2 %zu: %hhu (%c) %hhu", ictx->off, ch, ch, ictx->intermediate);
689:
690: switch (ch) {
1.3 nicm 691: case '0': /* SCS */
1.1 nicm 692: /*
693: * Not really supported, but fake it up enough for those that
694: * use it to switch character sets (by redefining G0 to
695: * graphics set, rather than switching to G1).
696: */
697: switch (ictx->intermediate) {
698: case '(': /* G0 */
699: ictx->cell.attr |= GRID_ATTR_CHARSET;
700: break;
701: }
702: break;
703: case '=': /* DECKPAM */
1.3 nicm 704: if (ictx->intermediate != '\0')
705: break;
1.1 nicm 706: screen_write_kkeypadmode(&ictx->ctx, 1);
707: log_debug("kkeypad on (application mode)");
708: break;
709: case '>': /* DECKPNM */
1.3 nicm 710: if (ictx->intermediate != '\0')
711: break;
1.1 nicm 712: screen_write_kkeypadmode(&ictx->ctx, 0);
713: log_debug("kkeypad off (number mode)");
714: break;
715: case '7': /* DECSC */
1.3 nicm 716: if (ictx->intermediate != '\0')
717: break;
1.1 nicm 718: memcpy(&ictx->saved_cell, &ictx->cell, sizeof ictx->saved_cell);
719: ictx->saved_cx = s->cx;
720: ictx->saved_cy = s->cy;
721: break;
1.3 nicm 722: case '8':
723: switch (ictx->intermediate) {
724: case '\0': /* DECRC */
725: memcpy(
726: &ictx->cell, &ictx->saved_cell, sizeof ictx->cell);
727: screen_write_cursormove(
728: &ictx->ctx, ictx->saved_cx, ictx->saved_cy);
729: break;
730: case '#': /* DECALN */
731: screen_write_alignmenttest(&ictx->ctx);
732: break;
733: }
1.1 nicm 734: break;
735: default:
736: log_debug("unknown p2: %hhu", ch);
737: break;
738: }
739: }
740:
741: void
742: input_handle_standard_two(u_char ch, struct input_ctx *ictx)
743: {
744: log_debug2(
745: "-- s2 %zu: %hhu (%c) %hhu", ictx->off, ch, ch, ictx->intermediate);
746:
747: switch (ch) {
1.7 nicm 748: case 'B': /* SCS */
1.1 nicm 749: /*
750: * Not really supported, but fake it up enough for those that
751: * use it to switch character sets (by redefining G0 to
752: * graphics set, rather than switching to G1).
753: */
754: switch (ictx->intermediate) {
755: case '(': /* G0 */
756: ictx->cell.attr &= ~GRID_ATTR_CHARSET;
757: break;
758: }
759: break;
760: case 'c': /* RIS */
761: memcpy(&ictx->cell, &grid_default_cell, sizeof ictx->cell);
762:
763: memcpy(&ictx->saved_cell, &ictx->cell, sizeof ictx->saved_cell);
764: ictx->saved_cx = 0;
765: ictx->saved_cy = 0;
766:
1.7 nicm 767: screen_reset_tabs(ictx->ctx.s);
768:
1.1 nicm 769: screen_write_scrollregion(
770: &ictx->ctx, 0, screen_size_y(ictx->ctx.s) - 1);
771:
772: screen_write_insertmode(&ictx->ctx, 0);
773: screen_write_kcursormode(&ictx->ctx, 0);
774: screen_write_kkeypadmode(&ictx->ctx, 0);
775: screen_write_mousemode(&ictx->ctx, 0);
776:
777: screen_write_clearscreen(&ictx->ctx);
778: screen_write_cursormove(&ictx->ctx, 0, 0);
779: break;
780: case 'k':
781: input_start_string(ictx, STRING_NAME);
782: input_state(ictx, input_state_string_next);
783: break;
784: default:
785: log_debug("unknown s2: %hhu", ch);
786: break;
787: }
788: }
789:
790: void
791: input_handle_sequence(u_char ch, struct input_ctx *ictx)
792: {
793: struct input_sequence_entry *entry, find;
794: struct screen *s = ictx->ctx.s;
1.21 deraadt 795: u_int i;
1.1 nicm 796: struct input_arg *iarg;
797:
798: log_debug2("-- sq %zu: %hhu (%c): %u [sx=%u, sy=%u, cx=%u, cy=%u, "
799: "ru=%u, rl=%u]", ictx->off, ch, ch, ARRAY_LENGTH(&ictx->args),
800: screen_size_x(s), screen_size_y(s), s->cx, s->cy, s->rupper,
801: s->rlower);
802: for (i = 0; i < ARRAY_LENGTH(&ictx->args); i++) {
803: iarg = &ARRAY_ITEM(&ictx->args, i);
804: if (*iarg->data != '\0')
805: log_debug2(" ++ %u: %s", i, iarg->data);
806: }
807:
808: find.ch = ch;
809: entry = bsearch(&find,
810: input_sequence_table, nitems(input_sequence_table),
811: sizeof input_sequence_table[0], input_sequence_cmp);
812: if (entry != NULL)
813: entry->fn(ictx);
814: else
815: log_debug("unknown sq: %c (%hhu %hhu)", ch, ch, ictx->private);
816: }
817:
818: void
819: input_handle_sequence_cuu(struct input_ctx *ictx)
820: {
821: uint16_t n;
822:
823: if (ictx->private != '\0')
824: return;
825:
826: if (ARRAY_LENGTH(&ictx->args) > 1)
827: return;
828: if (input_get_argument(ictx, 0, &n, 1) != 0)
829: return;
830: if (n == 0)
831: n = 1;
832:
833: screen_write_cursorup(&ictx->ctx, n);
834: }
835:
836: void
837: input_handle_sequence_cud(struct input_ctx *ictx)
838: {
839: uint16_t n;
840:
841: if (ictx->private != '\0')
842: return;
843:
844: if (ARRAY_LENGTH(&ictx->args) > 1)
845: return;
846: if (input_get_argument(ictx, 0, &n, 1) != 0)
847: return;
848: if (n == 0)
849: n = 1;
850:
851: screen_write_cursordown(&ictx->ctx, n);
852: }
853:
854: void
855: input_handle_sequence_cuf(struct input_ctx *ictx)
856: {
857: uint16_t n;
858:
859: if (ictx->private != '\0')
860: return;
861:
862: if (ARRAY_LENGTH(&ictx->args) > 1)
863: return;
864: if (input_get_argument(ictx, 0, &n, 1) != 0)
865: return;
866: if (n == 0)
867: n = 1;
868:
869: screen_write_cursorright(&ictx->ctx, n);
870: }
871:
872: void
873: input_handle_sequence_cub(struct input_ctx *ictx)
874: {
875: uint16_t n;
876:
877: if (ictx->private != '\0')
878: return;
879:
880: if (ARRAY_LENGTH(&ictx->args) > 1)
881: return;
882: if (input_get_argument(ictx, 0, &n, 1) != 0)
883: return;
884: if (n == 0)
885: n = 1;
886:
887: screen_write_cursorleft(&ictx->ctx, n);
888: }
889:
890: void
891: input_handle_sequence_dch(struct input_ctx *ictx)
892: {
893: uint16_t n;
894:
895: if (ictx->private != '\0')
896: return;
897:
898: if (ARRAY_LENGTH(&ictx->args) > 1)
899: return;
900: if (input_get_argument(ictx, 0, &n, 1) != 0)
901: return;
902: if (n == 0)
903: n = 1;
904:
905: screen_write_deletecharacter(&ictx->ctx, n);
1.8 nicm 906: }
907:
908: void
909: input_handle_sequence_cbt(struct input_ctx *ictx)
910: {
911: struct screen *s = ictx->ctx.s;
912: uint16_t n;
913:
914: if (ictx->private != '\0')
915: return;
916:
917: if (ARRAY_LENGTH(&ictx->args) > 1)
918: return;
919: if (input_get_argument(ictx, 0, &n, 1) != 0)
920: return;
921: if (n == 0)
922: n = 1;
923:
924: /* Find the previous tab point, n times. */
925: while (s->cx > 0 && n-- > 0) {
926: do
927: s->cx--;
928: while (s->cx > 0 && !bit_test(s->tabs, s->cx));
929: }
1.14 nicm 930: }
931:
932: void
933: input_handle_sequence_da(struct input_ctx *ictx)
934: {
1.22 ! nicm 935: struct window_pane *wp = ictx->wp;
! 936: uint16_t n;
1.14 nicm 937:
938: if (ictx->private != '\0')
939: return;
940:
941: if (ARRAY_LENGTH(&ictx->args) > 1)
942: return;
943: if (input_get_argument(ictx, 0, &n, 0) != 0)
944: return;
945: if (n != 0)
946: return;
947:
1.22 ! nicm 948: bufferevent_write(wp->event, "\033[?1;2c", (sizeof "\033[?1;2c") - 1);
1.1 nicm 949: }
950:
951: void
952: input_handle_sequence_dl(struct input_ctx *ictx)
953: {
954: uint16_t n;
955:
956: if (ictx->private != '\0')
957: return;
958:
959: if (ARRAY_LENGTH(&ictx->args) > 1)
960: return;
961: if (input_get_argument(ictx, 0, &n, 1) != 0)
962: return;
963: if (n == 0)
964: n = 1;
965:
966: screen_write_deleteline(&ictx->ctx, n);
967: }
968:
969: void
970: input_handle_sequence_ich(struct input_ctx *ictx)
971: {
972: uint16_t n;
973:
974: if (ictx->private != '\0')
975: return;
976:
977: if (ARRAY_LENGTH(&ictx->args) > 1)
978: return;
979: if (input_get_argument(ictx, 0, &n, 1) != 0)
980: return;
981: if (n == 0)
982: n = 1;
983:
984: screen_write_insertcharacter(&ictx->ctx, n);
985: }
986:
987: void
988: input_handle_sequence_il(struct input_ctx *ictx)
989: {
990: uint16_t n;
991:
992: if (ictx->private != '\0')
993: return;
994:
995: if (ARRAY_LENGTH(&ictx->args) > 1)
996: return;
997: if (input_get_argument(ictx, 0, &n, 1) != 0)
998: return;
999: if (n == 0)
1000: n = 1;
1001:
1002: screen_write_insertline(&ictx->ctx, n);
1003: }
1004:
1005: void
1006: input_handle_sequence_vpa(struct input_ctx *ictx)
1007: {
1008: struct screen *s = ictx->ctx.s;
1009: uint16_t n;
1010:
1011: if (ictx->private != '\0')
1012: return;
1013:
1014: if (ARRAY_LENGTH(&ictx->args) > 1)
1015: return;
1016: if (input_get_argument(ictx, 0, &n, 1) != 0)
1017: return;
1018: if (n == 0)
1019: n = 1;
1020:
1021: screen_write_cursormove(&ictx->ctx, s->cx, n - 1);
1022: }
1023:
1024: void
1025: input_handle_sequence_hpa(struct input_ctx *ictx)
1026: {
1027: struct screen *s = ictx->ctx.s;
1028: uint16_t n;
1029:
1030: if (ictx->private != '\0')
1031: return;
1032:
1033: if (ARRAY_LENGTH(&ictx->args) > 1)
1034: return;
1035: if (input_get_argument(ictx, 0, &n, 1) != 0)
1036: return;
1037: if (n == 0)
1038: n = 1;
1039:
1040: screen_write_cursormove(&ictx->ctx, n - 1, s->cy);
1041: }
1042:
1043: void
1044: input_handle_sequence_cup(struct input_ctx *ictx)
1045: {
1046: uint16_t n, m;
1047:
1048: if (ictx->private != '\0')
1049: return;
1050:
1051: if (ARRAY_LENGTH(&ictx->args) > 2)
1052: return;
1053: if (input_get_argument(ictx, 0, &n, 1) != 0)
1054: return;
1055: if (input_get_argument(ictx, 1, &m, 1) != 0)
1056: return;
1057: if (n == 0)
1058: n = 1;
1059: if (m == 0)
1060: m = 1;
1061:
1062: screen_write_cursormove(&ictx->ctx, m - 1, n - 1);
1.7 nicm 1063: }
1064:
1065: void
1066: input_handle_sequence_tbc(struct input_ctx *ictx)
1067: {
1068: struct screen *s = ictx->ctx.s;
1069: uint16_t n;
1070:
1071: if (ictx->private != '\0')
1072: return;
1073:
1074: if (ARRAY_LENGTH(&ictx->args) > 1)
1075: return;
1076: if (input_get_argument(ictx, 0, &n, 1) != 0)
1077: return;
1078:
1079: switch (n) {
1080: case 0:
1081: if (s->cx < screen_size_x(s))
1082: bit_clear(s->tabs, s->cx);
1083: break;
1084: case 3:
1085: bit_nclear(s->tabs, 0, screen_size_x(s) - 1);
1086: break;
1087: }
1.1 nicm 1088: }
1089:
1090: void
1091: input_handle_sequence_ed(struct input_ctx *ictx)
1092: {
1093: uint16_t n;
1094:
1095: if (ictx->private != '\0')
1096: return;
1097:
1098: if (ARRAY_LENGTH(&ictx->args) > 1)
1099: return;
1100: if (input_get_argument(ictx, 0, &n, 0) != 0)
1101: return;
1102: if (n > 2)
1103: return;
1104:
1105: switch (n) {
1106: case 0:
1107: screen_write_clearendofscreen(&ictx->ctx);
1108: break;
1109: case 1:
1110: screen_write_clearstartofscreen(&ictx->ctx);
1111: break;
1112: case 2:
1113: screen_write_clearscreen(&ictx->ctx);
1114: break;
1115: }
1116: }
1117:
1118: void
1119: input_handle_sequence_el(struct input_ctx *ictx)
1120: {
1121: uint16_t n;
1122:
1123: if (ictx->private != '\0')
1124: return;
1125:
1126: if (ARRAY_LENGTH(&ictx->args) > 1)
1127: return;
1128: if (input_get_argument(ictx, 0, &n, 0) != 0)
1129: return;
1130: if (n > 2)
1131: return;
1132:
1133: switch (n) {
1134: case 0:
1135: screen_write_clearendofline(&ictx->ctx);
1136: break;
1137: case 1:
1138: screen_write_clearstartofline(&ictx->ctx);
1139: break;
1140: case 2:
1141: screen_write_clearline(&ictx->ctx);
1142: break;
1143: }
1144: }
1145:
1146: void
1147: input_handle_sequence_sm(struct input_ctx *ictx)
1148: {
1.9 nicm 1149: struct window_pane *wp = ictx->wp;
1150: struct screen *s = &wp->base;
1151: u_int sx, sy;
1152: uint16_t n;
1.1 nicm 1153:
1154: if (ARRAY_LENGTH(&ictx->args) > 1)
1155: return;
1156: if (input_get_argument(ictx, 0, &n, 0) != 0)
1157: return;
1158:
1159: if (ictx->private == '?') {
1160: switch (n) {
1161: case 1: /* GATM */
1162: screen_write_kcursormode(&ictx->ctx, 1);
1163: log_debug("kcursor on");
1164: break;
1.17 nicm 1165: case 3: /* DECCOLM */
1166: screen_write_cursormove(&ictx->ctx, 0, 0);
1167: screen_write_clearscreen(&ictx->ctx);
1168: break;
1.1 nicm 1169: case 25: /* TCEM */
1170: screen_write_cursormode(&ictx->ctx, 1);
1171: log_debug("cursor on");
1172: break;
1173: case 1000:
1174: screen_write_mousemode(&ictx->ctx, 1);
1175: log_debug("mouse on");
1176: break;
1.9 nicm 1177: case 1049:
1178: if (wp->saved_grid != NULL)
1179: break;
1180: sx = screen_size_x(s);
1181: sy = screen_size_y(s);
1182:
1183: /*
1184: * Enter alternative screen mode. A copy of the visible
1185: * screen is saved and the history is not updated
1186: */
1187:
1188: wp->saved_grid = grid_create(sx, sy, 0);
1189: grid_duplicate_lines(
1190: wp->saved_grid, 0, s->grid, screen_hsize(s), sy);
1191: wp->saved_cx = s->cx;
1192: wp->saved_cy = s->cy;
1.11 nicm 1193: memcpy(&wp->saved_cell,
1194: &ictx->cell, sizeof wp->saved_cell);
1195:
1.9 nicm 1196: grid_view_clear(s->grid, 0, 0, sx, sy);
1197:
1198: wp->base.grid->flags &= ~GRID_HISTORY;
1199:
1200: wp->flags |= PANE_REDRAW;
1201: break;
1.1 nicm 1202: default:
1203: log_debug("unknown SM [%hhu]: %u", ictx->private, n);
1204: break;
1205: }
1206: } else {
1207: switch (n) {
1208: case 4: /* IRM */
1209: screen_write_insertmode(&ictx->ctx, 1);
1210: log_debug("insert on");
1211: break;
1212: case 34:
1213: /* Cursor high visibility not supported. */
1214: break;
1215: default:
1216: log_debug("unknown SM [%hhu]: %u", ictx->private, n);
1217: break;
1218: }
1219: }
1220: }
1221:
1222: void
1223: input_handle_sequence_rm(struct input_ctx *ictx)
1224: {
1.9 nicm 1225: struct window_pane *wp = ictx->wp;
1226: struct screen *s = &wp->base;
1227: u_int sx, sy;
1228: uint16_t n;
1.1 nicm 1229:
1230: if (ARRAY_LENGTH(&ictx->args) > 1)
1231: return;
1232: if (input_get_argument(ictx, 0, &n, 0) != 0)
1233: return;
1234:
1235: if (ictx->private == '?') {
1236: switch (n) {
1237: case 1: /* GATM */
1238: screen_write_kcursormode(&ictx->ctx, 0);
1239: log_debug("kcursor off");
1.17 nicm 1240: break;
1241: case 3: /* DECCOLM */
1242: screen_write_cursormove(&ictx->ctx, 0, 0);
1243: screen_write_clearscreen(&ictx->ctx);
1.1 nicm 1244: break;
1245: case 25: /* TCEM */
1246: screen_write_cursormode(&ictx->ctx, 0);
1247: log_debug("cursor off");
1248: break;
1249: case 1000:
1250: screen_write_mousemode(&ictx->ctx, 0);
1251: log_debug("mouse off");
1.9 nicm 1252: break;
1253: case 1049:
1254: if (wp->saved_grid == NULL)
1255: break;
1256: sx = screen_size_x(s);
1257: sy = screen_size_y(s);
1258:
1259: /*
1260: * Exit alternative screen mode and restore the copied
1261: * grid.
1262: */
1263:
1264: /*
1265: * If the current size is bigger, temporarily resize
1266: * to the old size before copying back.
1267: */
1268: if (sy > wp->saved_grid->sy)
1269: screen_resize(s, sx, wp->saved_grid->sy);
1270:
1.11 nicm 1271: /* Restore the grid, cursor position and cell. */
1.9 nicm 1272: grid_duplicate_lines(
1273: s->grid, screen_hsize(s), wp->saved_grid, 0, sy);
1274: s->cx = wp->saved_cx;
1275: if (s->cx > screen_size_x(s) - 1)
1276: s->cx = screen_size_x(s) - 1;
1277: s->cy = wp->saved_cy;
1278: if (s->cy > screen_size_y(s) - 1)
1279: s->cy = screen_size_y(s) - 1;
1.11 nicm 1280: memcpy(&ictx->cell, &wp->saved_cell, sizeof ictx->cell);
1.9 nicm 1281:
1282: /*
1283: * Turn history back on (so resize can use it) and then
1284: * resize back to the current size.
1285: */
1286: wp->base.grid->flags |= GRID_HISTORY;
1287: if (sy > wp->saved_grid->sy)
1288: screen_resize(s, sx, sy);
1289:
1290: grid_destroy(wp->saved_grid);
1291: wp->saved_grid = NULL;
1292:
1293: wp->flags |= PANE_REDRAW;
1.1 nicm 1294: break;
1295: default:
1296: log_debug("unknown RM [%hhu]: %u", ictx->private, n);
1297: break;
1298: }
1299: } else if (ictx->private == '\0') {
1300: switch (n) {
1301: case 4: /* IRM */
1302: screen_write_insertmode(&ictx->ctx, 0);
1303: log_debug("insert off");
1304: break;
1305: case 34:
1306: /* Cursor high visibility not supported. */
1307: break;
1308: default:
1309: log_debug("unknown RM [%hhu]: %u", ictx->private, n);
1310: break;
1311: }
1312: }
1313: }
1314:
1315: void
1316: input_handle_sequence_dsr(struct input_ctx *ictx)
1317: {
1.22 ! nicm 1318: struct window_pane *wp = ictx->wp;
! 1319: struct screen *s = ictx->ctx.s;
! 1320: uint16_t n;
! 1321: char reply[32];
1.1 nicm 1322:
1323: if (ARRAY_LENGTH(&ictx->args) > 1)
1324: return;
1325: if (input_get_argument(ictx, 0, &n, 0) != 0)
1326: return;
1327:
1328: if (ictx->private == '\0') {
1329: switch (n) {
1330: case 6: /* cursor position */
1331: xsnprintf(reply, sizeof reply,
1332: "\033[%u;%uR", s->cy + 1, s->cx + 1);
1333: log_debug("cursor request, reply: %s", reply);
1.22 ! nicm 1334: bufferevent_write(wp->event, reply, strlen(reply));
1.1 nicm 1335: break;
1336: }
1337: }
1338: }
1339:
1340: void
1341: input_handle_sequence_decstbm(struct input_ctx *ictx)
1342: {
1343: struct screen *s = ictx->ctx.s;
1344: uint16_t n, m;
1345:
1346: if (ictx->private != '\0')
1347: return;
1348:
1349: if (ARRAY_LENGTH(&ictx->args) > 2)
1350: return;
1351: if (input_get_argument(ictx, 0, &n, 0) != 0)
1352: return;
1353: if (input_get_argument(ictx, 1, &m, 0) != 0)
1354: return;
1355: if (n == 0)
1356: n = 1;
1357: if (m == 0)
1358: m = screen_size_y(s);
1359:
1360: screen_write_scrollregion(&ictx->ctx, n - 1, m - 1);
1361: }
1362:
1363: void
1364: input_handle_sequence_sgr(struct input_ctx *ictx)
1365: {
1366: struct grid_cell *gc = &ictx->cell;
1367: u_int i;
1368: uint16_t m, o;
1369: u_char attr;
1370:
1371: if (ARRAY_LENGTH(&ictx->args) == 0) {
1372: attr = gc->attr;
1373: memcpy(gc, &grid_default_cell, sizeof *gc);
1374: gc->attr |= (attr & GRID_ATTR_CHARSET);
1375: return;
1376: }
1377:
1378: for (i = 0; i < ARRAY_LENGTH(&ictx->args); i++) {
1379: if (input_get_argument(ictx, i, &m, 0) != 0)
1380: return;
1381:
1382: if (m == 38 || m == 48) {
1383: i++;
1384: if (input_get_argument(ictx, i, &o, 0) != 0)
1385: return;
1386: if (o != 5)
1387: continue;
1388:
1389: i++;
1390: if (input_get_argument(ictx, i, &o, 0) != 0)
1391: return;
1392: if (m == 38) {
1393: gc->flags |= GRID_FLAG_FG256;
1394: gc->fg = o;
1395: } else if (m == 48) {
1396: gc->flags |= GRID_FLAG_BG256;
1397: gc->bg = o;
1398: }
1399: continue;
1400: }
1401:
1402: switch (m) {
1403: case 0:
1404: case 10:
1405: attr = gc->attr;
1406: memcpy(gc, &grid_default_cell, sizeof *gc);
1407: gc->attr |= (attr & GRID_ATTR_CHARSET);
1408: break;
1409: case 1:
1410: gc->attr |= GRID_ATTR_BRIGHT;
1411: break;
1412: case 2:
1413: gc->attr |= GRID_ATTR_DIM;
1414: break;
1415: case 3:
1416: gc->attr |= GRID_ATTR_ITALICS;
1417: break;
1418: case 4:
1419: gc->attr |= GRID_ATTR_UNDERSCORE;
1420: break;
1421: case 5:
1422: gc->attr |= GRID_ATTR_BLINK;
1423: break;
1424: case 7:
1425: gc->attr |= GRID_ATTR_REVERSE;
1426: break;
1427: case 8:
1428: gc->attr |= GRID_ATTR_HIDDEN;
1429: break;
1430: case 22:
1431: gc->attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_DIM);
1432: break;
1433: case 23:
1434: gc->attr &= ~GRID_ATTR_ITALICS;
1435: break;
1436: case 24:
1437: gc->attr &= ~GRID_ATTR_UNDERSCORE;
1438: break;
1439: case 25:
1440: gc->attr &= ~GRID_ATTR_BLINK;
1441: break;
1442: case 27:
1443: gc->attr &= ~GRID_ATTR_REVERSE;
1444: break;
1445: case 30:
1446: case 31:
1447: case 32:
1448: case 33:
1449: case 34:
1450: case 35:
1451: case 36:
1452: case 37:
1453: gc->flags &= ~GRID_FLAG_FG256;
1454: gc->fg = m - 30;
1455: break;
1456: case 39:
1457: gc->flags &= ~GRID_FLAG_FG256;
1458: gc->fg = 8;
1459: break;
1460: case 40:
1461: case 41:
1462: case 42:
1463: case 43:
1464: case 44:
1465: case 45:
1466: case 46:
1467: case 47:
1468: gc->flags &= ~GRID_FLAG_BG256;
1469: gc->bg = m - 40;
1470: break;
1471: case 49:
1472: gc->flags &= ~GRID_FLAG_BG256;
1473: gc->bg = 8;
1.20 nicm 1474: break;
1475: case 90:
1476: case 91:
1477: case 92:
1478: case 93:
1479: case 94:
1480: case 95:
1481: case 96:
1482: case 97:
1483: gc->flags |= GRID_FLAG_FG256;
1484: gc->fg = m - 82;
1485: break;
1486: case 100:
1487: case 101:
1488: case 102:
1489: case 103:
1490: case 104:
1491: case 105:
1492: case 106:
1493: case 107:
1494: gc->flags |= GRID_FLAG_BG256;
1495: gc->bg = m - 92;
1.1 nicm 1496: break;
1497: }
1498: }
1499: }