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