Annotation of src/usr.bin/tmux/input.c, Revision 1.28
1.28 ! nicm 1: /* $OpenBSD$ */
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 <stdlib.h>
22: #include <string.h>
23:
24: #include "tmux.h"
25:
1.28 ! nicm 26: /*
! 27: * Based on the description by Paul Williams at:
! 28: *
! 29: * http://vt100.net/emu/dec_ansi_parser
! 30: *
! 31: * With the following changes:
! 32: *
! 33: * - 7-bit only.
! 34: *
! 35: * - Support for UTF-8.
! 36: *
! 37: * - OSC (but not APC) may be terminated by \007 as well as ST.
! 38: *
! 39: * - A state for APC similar to OSC. Some terminals appear to use this to set
! 40: * the title.
! 41: *
! 42: * - A state for the screen \033k...\033\\ sequence to rename a window. This is
! 43: * pretty stupid but not supporting it is more trouble than it is worth.
! 44: */
! 45:
! 46: /* Helper functions. */
! 47: int input_split(struct input_ctx *);
! 48: int input_get(struct input_ctx *, u_int, int, int);
! 49: void input_reply(struct input_ctx *, const char *, ...);
! 50:
! 51: /* Transition entry/exit handlers. */
! 52: void input_clear(struct input_ctx *);
! 53: void input_enter_dcs(struct input_ctx *);
! 54: void input_exit_dcs(struct input_ctx *);
! 55: void input_enter_osc(struct input_ctx *);
! 56: void input_exit_osc(struct input_ctx *);
! 57: void input_enter_apc(struct input_ctx *);
! 58: void input_exit_apc(struct input_ctx *);
! 59: void input_enter_rename(struct input_ctx *);
! 60: void input_exit_rename(struct input_ctx *);
! 61:
! 62: /* Input state handlers. */
! 63: int input_print(struct input_ctx *);
! 64: int input_intermediate(struct input_ctx *);
! 65: int input_parameter(struct input_ctx *);
! 66: int input_input(struct input_ctx *);
! 67: int input_c0_dispatch(struct input_ctx *);
! 68: int input_esc_dispatch(struct input_ctx *);
! 69: int input_csi_dispatch(struct input_ctx *);
! 70: void input_csi_dispatch_sgr(struct input_ctx *);
! 71: int input_utf8_open(struct input_ctx *);
! 72: int input_utf8_add(struct input_ctx *);
! 73: int input_utf8_close(struct input_ctx *);
! 74:
! 75: /* Command table comparison function. */
! 76: int input_table_compare(const void *, const void *);
! 77:
! 78: /* Command table entry. */
! 79: struct input_table_entry {
! 80: int ch;
! 81: const char *interm;
! 82: int type;
1.1 nicm 83: };
84:
1.28 ! nicm 85: /* Escape commands. */
! 86: enum input_esc_type {
! 87: INPUT_ESC_DECALN,
! 88: INPUT_ESC_DECKPAM,
! 89: INPUT_ESC_DECKPNM,
! 90: INPUT_ESC_DECRC,
! 91: INPUT_ESC_DECSC,
! 92: INPUT_ESC_HTS,
! 93: INPUT_ESC_IND,
! 94: INPUT_ESC_NEL,
! 95: INPUT_ESC_RI,
! 96: INPUT_ESC_RIS,
! 97: INPUT_ESC_SCSOFF_G0,
! 98: INPUT_ESC_SCSON_G0,
! 99: };
1.1 nicm 100:
1.28 ! nicm 101: /* Escape command table. */
! 102: const struct input_table_entry input_esc_table[] = {
! 103: { '0', "(", INPUT_ESC_SCSOFF_G0 },
! 104: { '7', "", INPUT_ESC_DECSC },
! 105: { '8', "", INPUT_ESC_DECRC },
! 106: { '8', "#", INPUT_ESC_DECALN },
! 107: { '=', "", INPUT_ESC_DECKPAM },
! 108: { '>', "", INPUT_ESC_DECKPNM },
! 109: { 'B', "(", INPUT_ESC_SCSON_G0 },
! 110: { 'D', "", INPUT_ESC_IND },
! 111: { 'E', "", INPUT_ESC_NEL },
! 112: { 'H', "", INPUT_ESC_HTS },
! 113: { 'M', "", INPUT_ESC_RI },
! 114: { 'c', "", INPUT_ESC_RIS },
! 115: };
1.1 nicm 116:
1.28 ! nicm 117: /* Control (CSI) commands. */
! 118: enum input_csi_type {
! 119: INPUT_CSI_CBT,
! 120: INPUT_CSI_CUB,
! 121: INPUT_CSI_CUD,
! 122: INPUT_CSI_CUF,
! 123: INPUT_CSI_CUP,
! 124: INPUT_CSI_CUU,
! 125: INPUT_CSI_DA,
! 126: INPUT_CSI_DCH,
! 127: INPUT_CSI_DECSTBM,
! 128: INPUT_CSI_DL,
! 129: INPUT_CSI_DSR,
! 130: INPUT_CSI_ED,
! 131: INPUT_CSI_EL,
! 132: INPUT_CSI_HPA,
! 133: INPUT_CSI_ICH,
! 134: INPUT_CSI_IL,
! 135: INPUT_CSI_RM,
! 136: INPUT_CSI_RM_PRIVATE,
! 137: INPUT_CSI_SGR,
! 138: INPUT_CSI_SM,
! 139: INPUT_CSI_SM_PRIVATE,
! 140: INPUT_CSI_TBC,
! 141: INPUT_CSI_VPA,
! 142: };
1.1 nicm 143:
1.28 ! nicm 144: /* Control (CSI) command table. */
! 145: const struct input_table_entry input_csi_table[] = {
! 146: { '@', "", INPUT_CSI_ICH },
! 147: { 'A', "", INPUT_CSI_CUU },
! 148: { 'B', "", INPUT_CSI_CUD },
! 149: { 'C', "", INPUT_CSI_CUF },
! 150: { 'D', "", INPUT_CSI_CUB },
! 151: { 'G', "", INPUT_CSI_HPA },
! 152: { 'H', "", INPUT_CSI_CUP },
! 153: { 'J', "", INPUT_CSI_ED },
! 154: { 'K', "", INPUT_CSI_EL },
! 155: { 'L', "", INPUT_CSI_IL },
! 156: { 'M', "", INPUT_CSI_DL },
! 157: { 'P', "", INPUT_CSI_DCH },
! 158: { 'Z', "", INPUT_CSI_CBT },
! 159: { 'c', "", INPUT_CSI_DA },
! 160: { 'd', "", INPUT_CSI_VPA },
! 161: { 'f', "", INPUT_CSI_CUP },
! 162: { 'g', "", INPUT_CSI_TBC },
! 163: { 'h', "", INPUT_CSI_SM },
! 164: { 'h', "?", INPUT_CSI_SM_PRIVATE },
! 165: { 'l', "", INPUT_CSI_RM },
! 166: { 'l', "?", INPUT_CSI_RM_PRIVATE },
! 167: { 'm', "", INPUT_CSI_SGR },
! 168: { 'n', "", INPUT_CSI_DSR },
! 169: { 'r', "", INPUT_CSI_DECSTBM },
! 170: };
1.1 nicm 171:
1.28 ! nicm 172: /* Input transition. */
! 173: struct input_transition {
! 174: int first;
! 175: int last;
1.1 nicm 176:
1.28 ! nicm 177: int (*handler)(struct input_ctx *);
! 178: const struct input_state *state;
! 179: };
1.1 nicm 180:
1.28 ! nicm 181: /* Input state. */
! 182: struct input_state {
! 183: const char *name;
! 184: void (*enter)(struct input_ctx *);
! 185: void (*exit)(struct input_ctx *);
! 186: const struct input_transition *transitions;
! 187: };
1.1 nicm 188:
1.28 ! nicm 189: /* State transitions available from all states. */
! 190: #define INPUT_STATE_ANYWHERE \
! 191: { 0x18, 0x18, input_c0_dispatch, &input_state_ground }, \
! 192: { 0x1a, 0x1a, input_c0_dispatch, &input_state_ground }, \
! 193: { 0x1b, 0x1b, NULL, &input_state_esc_enter }
! 194:
! 195: /* Forward declarations of state tables. */
! 196: const struct input_transition input_state_ground_table[];
! 197: const struct input_transition input_state_esc_enter_table[];
! 198: const struct input_transition input_state_esc_intermediate_table[];
! 199: const struct input_transition input_state_csi_enter_table[];
! 200: const struct input_transition input_state_csi_parameter_table[];
! 201: const struct input_transition input_state_csi_intermediate_table[];
! 202: const struct input_transition input_state_csi_ignore_table[];
! 203: const struct input_transition input_state_dcs_enter_table[];
! 204: const struct input_transition input_state_dcs_parameter_table[];
! 205: const struct input_transition input_state_dcs_intermediate_table[];
! 206: const struct input_transition input_state_dcs_handler_table[];
! 207: const struct input_transition input_state_dcs_ignore_table[];
! 208: const struct input_transition input_state_osc_string_table[];
! 209: const struct input_transition input_state_apc_string_table[];
! 210: const struct input_transition input_state_rename_string_table[];
! 211: const struct input_transition input_state_consume_st_table[];
! 212: const struct input_transition input_state_utf8_three_table[];
! 213: const struct input_transition input_state_utf8_two_table[];
! 214: const struct input_transition input_state_utf8_one_table[];
! 215:
! 216: /* ground state definition. */
! 217: const struct input_state input_state_ground = {
! 218: "ground",
! 219: NULL, NULL,
! 220: input_state_ground_table
! 221: };
1.1 nicm 222:
1.28 ! nicm 223: /* esc_enter state definition. */
! 224: const struct input_state input_state_esc_enter = {
! 225: "esc_enter",
! 226: input_clear, NULL,
! 227: input_state_esc_enter_table
! 228: };
1.1 nicm 229:
1.28 ! nicm 230: /* esc_intermediate state definition. */
! 231: const struct input_state input_state_esc_intermediate = {
! 232: "esc_intermediate",
! 233: NULL, NULL,
! 234: input_state_esc_intermediate_table
! 235: };
1.1 nicm 236:
1.28 ! nicm 237: /* csi_enter state definition. */
! 238: const struct input_state input_state_csi_enter = {
! 239: "csi_enter",
! 240: input_clear, NULL,
! 241: input_state_csi_enter_table
! 242: };
1.1 nicm 243:
1.28 ! nicm 244: /* csi_parameter state definition. */
! 245: const struct input_state input_state_csi_parameter = {
! 246: "csi_parameter",
! 247: NULL, NULL,
! 248: input_state_csi_parameter_table
! 249: };
1.1 nicm 250:
1.28 ! nicm 251: /* csi_intermediate state definition. */
! 252: const struct input_state input_state_csi_intermediate = {
! 253: "csi_intermediate",
! 254: NULL, NULL,
! 255: input_state_csi_intermediate_table
! 256: };
1.1 nicm 257:
1.28 ! nicm 258: /* csi_ignore state definition. */
! 259: const struct input_state input_state_csi_ignore = {
! 260: "csi_ignore",
! 261: NULL, NULL,
! 262: input_state_csi_ignore_table
! 263: };
1.1 nicm 264:
1.28 ! nicm 265: /* dcs_enter state definition. */
! 266: const struct input_state input_state_dcs_enter = {
! 267: "dcs_enter",
! 268: input_clear, NULL,
! 269: input_state_dcs_enter_table
! 270: };
1.1 nicm 271:
1.28 ! nicm 272: /* dcs_parameter state definition. */
! 273: const struct input_state input_state_dcs_parameter = {
! 274: "dcs_parameter",
! 275: NULL, NULL,
! 276: input_state_dcs_parameter_table
! 277: };
1.1 nicm 278:
1.28 ! nicm 279: /* dcs_intermediate state definition. */
! 280: const struct input_state input_state_dcs_intermediate = {
! 281: "dcs_intermediate",
! 282: NULL, NULL,
! 283: input_state_dcs_intermediate_table
! 284: };
1.1 nicm 285:
1.28 ! nicm 286: /* dcs_handler state definition. */
! 287: const struct input_state input_state_dcs_handler = {
! 288: "dcs_handler",
! 289: input_enter_dcs, input_exit_dcs,
! 290: input_state_dcs_handler_table
! 291: };
1.1 nicm 292:
1.28 ! nicm 293: /* dcs_ignore state definition. */
! 294: const struct input_state input_state_dcs_ignore = {
! 295: "dcs_ignore",
! 296: NULL, NULL,
! 297: input_state_dcs_ignore_table
! 298: };
1.1 nicm 299:
1.28 ! nicm 300: /* osc_string state definition. */
! 301: const struct input_state input_state_osc_string = {
! 302: "osc_string",
! 303: input_enter_osc, input_exit_osc,
! 304: input_state_osc_string_table
! 305: };
1.1 nicm 306:
1.28 ! nicm 307: /* apc_string state definition. */
! 308: const struct input_state input_state_apc_string = {
! 309: "apc_string",
! 310: input_enter_apc, input_exit_apc,
! 311: input_state_apc_string_table
! 312: };
1.1 nicm 313:
1.28 ! nicm 314: /* rename_string state definition. */
! 315: const struct input_state input_state_rename_string = {
! 316: "rename_string",
! 317: input_enter_rename, input_exit_rename,
! 318: input_state_rename_string_table
! 319: };
1.1 nicm 320:
1.28 ! nicm 321: /* consume_st state definition. */
! 322: const struct input_state input_state_consume_st = {
! 323: "consume_st",
! 324: NULL, NULL,
! 325: input_state_consume_st_table
! 326: };
1.1 nicm 327:
1.28 ! nicm 328: /* utf8_three state definition. */
! 329: const struct input_state input_state_utf8_three = {
! 330: "utf8_three",
! 331: NULL, NULL,
! 332: input_state_utf8_three_table
! 333: };
1.1 nicm 334:
1.28 ! nicm 335: /* utf8_two state definition. */
! 336: const struct input_state input_state_utf8_two = {
! 337: "utf8_two",
! 338: NULL, NULL,
! 339: input_state_utf8_two_table
! 340: };
1.1 nicm 341:
1.28 ! nicm 342: /* utf8_one state definition. */
! 343: const struct input_state input_state_utf8_one = {
! 344: "utf8_one",
! 345: NULL, NULL,
! 346: input_state_utf8_one_table
! 347: };
1.1 nicm 348:
1.28 ! nicm 349: /* ground state table. */
! 350: const struct input_transition input_state_ground_table[] = {
! 351: INPUT_STATE_ANYWHERE,
! 352:
! 353: { 0x00, 0x17, input_c0_dispatch, NULL },
! 354: { 0x19, 0x19, input_c0_dispatch, NULL },
! 355: { 0x1c, 0x1f, input_c0_dispatch, NULL },
! 356: { 0x20, 0x7e, input_print, NULL },
! 357: { 0x7f, 0x7f, NULL, NULL },
! 358: { 0x80, 0xc1, input_print, NULL },
! 359: { 0xc2, 0xdf, input_utf8_open, &input_state_utf8_one },
! 360: { 0xe0, 0xef, input_utf8_open, &input_state_utf8_two },
! 361: { 0xf0, 0xf4, input_utf8_open, &input_state_utf8_three },
! 362: { 0xf5, 0xff, input_print, NULL },
1.1 nicm 363:
1.28 ! nicm 364: { -1, -1, NULL, NULL }
! 365: };
1.13 nicm 366:
1.28 ! nicm 367: /* esc_enter state table. */
! 368: const struct input_transition input_state_esc_enter_table[] = {
! 369: INPUT_STATE_ANYWHERE,
! 370:
! 371: { 0x00, 0x17, input_c0_dispatch, NULL },
! 372: { 0x19, 0x19, input_c0_dispatch, NULL },
! 373: { 0x1c, 0x1f, input_c0_dispatch, NULL },
! 374: { 0x20, 0x2f, input_intermediate, &input_state_esc_intermediate },
! 375: { 0x30, 0x4f, input_esc_dispatch, &input_state_ground },
! 376: { 0x50, 0x50, NULL, &input_state_dcs_enter },
! 377: { 0x51, 0x57, input_esc_dispatch, &input_state_ground },
! 378: { 0x58, 0x58, NULL, &input_state_consume_st },
! 379: { 0x59, 0x59, input_esc_dispatch, &input_state_ground },
! 380: { 0x5a, 0x5a, input_esc_dispatch, &input_state_ground },
! 381: { 0x5b, 0x5b, NULL, &input_state_csi_enter },
! 382: { 0x5c, 0x5c, input_esc_dispatch, &input_state_ground },
! 383: { 0x5d, 0x5d, NULL, &input_state_osc_string },
! 384: { 0x5e, 0x5e, NULL, &input_state_consume_st },
! 385: { 0x5f, 0x5f, NULL, &input_state_apc_string },
! 386: { 0x60, 0x6a, input_esc_dispatch, &input_state_ground },
! 387: { 0x6b, 0x6b, NULL, &input_state_rename_string },
! 388: { 0x6c, 0x7c, input_esc_dispatch, &input_state_ground },
! 389: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 390:
1.28 ! nicm 391: { -1, -1, NULL, NULL }
! 392: };
1.1 nicm 393:
1.28 ! nicm 394: /* esc_interm state table. */
! 395: const struct input_transition input_state_esc_intermediate_table[] = {
! 396: INPUT_STATE_ANYWHERE,
! 397:
! 398: { 0x00, 0x17, input_c0_dispatch, NULL },
! 399: { 0x19, 0x19, input_c0_dispatch, NULL },
! 400: { 0x1c, 0x1f, input_c0_dispatch, NULL },
! 401: { 0x20, 0x2f, input_intermediate, NULL },
! 402: { 0x30, 0x7e, input_esc_dispatch, &input_state_ground },
! 403: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 404:
1.28 ! nicm 405: { -1, -1, NULL, NULL }
! 406: };
1.1 nicm 407:
1.28 ! nicm 408: /* csi_enter state table. */
! 409: const struct input_transition input_state_csi_enter_table[] = {
! 410: INPUT_STATE_ANYWHERE,
! 411:
! 412: { 0x00, 0x17, input_c0_dispatch, NULL },
! 413: { 0x19, 0x19, input_c0_dispatch, NULL },
! 414: { 0x1c, 0x1f, input_c0_dispatch, NULL },
! 415: { 0x20, 0x2f, input_intermediate, &input_state_csi_intermediate },
! 416: { 0x30, 0x39, input_parameter, &input_state_csi_parameter },
! 417: { 0x3a, 0x3a, NULL, &input_state_csi_ignore },
! 418: { 0x3b, 0x3b, input_parameter, &input_state_csi_parameter },
! 419: { 0x3c, 0x3f, input_intermediate, &input_state_csi_parameter },
! 420: { 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
! 421: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 422:
1.28 ! nicm 423: { -1, -1, NULL, NULL }
! 424: };
1.1 nicm 425:
1.28 ! nicm 426: /* csi_parameter state table. */
! 427: const struct input_transition input_state_csi_parameter_table[] = {
! 428: INPUT_STATE_ANYWHERE,
! 429:
! 430: { 0x00, 0x17, input_c0_dispatch, NULL },
! 431: { 0x19, 0x19, input_c0_dispatch, NULL },
! 432: { 0x1c, 0x1f, input_c0_dispatch, NULL },
! 433: { 0x20, 0x2f, input_intermediate, &input_state_csi_intermediate },
! 434: { 0x30, 0x39, input_parameter, NULL },
! 435: { 0x3a, 0x3a, NULL, &input_state_csi_ignore },
! 436: { 0x3b, 0x3b, input_parameter, NULL },
! 437: { 0x3c, 0x3f, NULL, &input_state_csi_ignore },
! 438: { 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
! 439: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 440:
1.28 ! nicm 441: { -1, -1, NULL, NULL }
! 442: };
1.1 nicm 443:
1.28 ! nicm 444: /* csi_intermediate state table. */
! 445: const struct input_transition input_state_csi_intermediate_table[] = {
! 446: INPUT_STATE_ANYWHERE,
! 447:
! 448: { 0x00, 0x17, input_c0_dispatch, NULL },
! 449: { 0x19, 0x19, input_c0_dispatch, NULL },
! 450: { 0x1c, 0x1f, input_c0_dispatch, NULL },
! 451: { 0x20, 0x2f, input_intermediate, NULL },
! 452: { 0x30, 0x3f, NULL, &input_state_csi_ignore },
! 453: { 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
! 454: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 455:
1.28 ! nicm 456: { -1, -1, NULL, NULL }
! 457: };
1.1 nicm 458:
1.28 ! nicm 459: /* csi_ignore state table. */
! 460: const struct input_transition input_state_csi_ignore_table[] = {
! 461: INPUT_STATE_ANYWHERE,
! 462:
! 463: { 0x00, 0x17, input_c0_dispatch, NULL },
! 464: { 0x19, 0x19, input_c0_dispatch, NULL },
! 465: { 0x1c, 0x1f, input_c0_dispatch, NULL },
! 466: { 0x20, 0x3f, NULL, NULL },
! 467: { 0x40, 0x7e, NULL, &input_state_ground },
! 468: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 469:
1.28 ! nicm 470: { -1, -1, NULL, NULL }
! 471: };
1.1 nicm 472:
1.28 ! nicm 473: /* dcs_enter state table. */
! 474: const struct input_transition input_state_dcs_enter_table[] = {
! 475: INPUT_STATE_ANYWHERE,
! 476:
! 477: { 0x00, 0x17, NULL, NULL },
! 478: { 0x19, 0x19, NULL, NULL },
! 479: { 0x1c, 0x1f, NULL, NULL },
! 480: { 0x20, 0x2f, input_intermediate, &input_state_dcs_intermediate },
! 481: { 0x30, 0x39, input_parameter, &input_state_dcs_parameter },
! 482: { 0x3a, 0x3a, NULL, &input_state_dcs_ignore },
! 483: { 0x3b, 0x3b, input_parameter, &input_state_dcs_parameter },
! 484: { 0x3c, 0x3f, input_intermediate, &input_state_dcs_parameter },
! 485: { 0x40, 0x7e, NULL, &input_state_dcs_handler },
! 486: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 487:
1.28 ! nicm 488: { -1, -1, NULL, NULL }
! 489: };
1.1 nicm 490:
1.28 ! nicm 491: /* dcs_parameter state table. */
! 492: const struct input_transition input_state_dcs_parameter_table[] = {
! 493: INPUT_STATE_ANYWHERE,
! 494:
! 495: { 0x00, 0x17, NULL, NULL },
! 496: { 0x19, 0x19, NULL, NULL },
! 497: { 0x1c, 0x1f, NULL, NULL },
! 498: { 0x20, 0x2f, input_intermediate, &input_state_dcs_intermediate },
! 499: { 0x30, 0x39, input_parameter, NULL },
! 500: { 0x3a, 0x3a, NULL, &input_state_dcs_ignore },
! 501: { 0x3b, 0x3b, input_parameter, NULL },
! 502: { 0x3c, 0x3f, NULL, &input_state_dcs_ignore },
! 503: { 0x40, 0x7e, NULL, &input_state_dcs_handler },
! 504: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 505:
1.28 ! nicm 506: { -1, -1, NULL, NULL }
! 507: };
1.1 nicm 508:
1.28 ! nicm 509: /* dcs_interm state table. */
! 510: const struct input_transition input_state_dcs_intermediate_table[] = {
! 511: INPUT_STATE_ANYWHERE,
! 512:
! 513: { 0x00, 0x17, NULL, NULL },
! 514: { 0x19, 0x19, NULL, NULL },
! 515: { 0x1c, 0x1f, NULL, NULL },
! 516: { 0x20, 0x2f, input_intermediate, NULL },
! 517: { 0x30, 0x3f, NULL, &input_state_dcs_ignore },
! 518: { 0x40, 0x7e, NULL, &input_state_dcs_handler },
! 519: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 520:
1.28 ! nicm 521: { -1, -1, NULL, NULL }
! 522: };
1.1 nicm 523:
1.28 ! nicm 524: /* dcs_handler state table. */
! 525: const struct input_transition input_state_dcs_handler_table[] = {
! 526: INPUT_STATE_ANYWHERE,
! 527:
! 528: { 0x00, 0x17, NULL, NULL },
! 529: { 0x19, 0x19, input_input, NULL },
! 530: { 0x1c, 0x1f, input_input, NULL },
! 531: { 0x20, 0x7e, input_input, NULL },
! 532: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 533:
1.28 ! nicm 534: { -1, -1, NULL, NULL }
! 535: };
1.1 nicm 536:
1.28 ! nicm 537: /* device_ignore state table. */
! 538: const struct input_transition input_state_dcs_ignore_table[] = {
! 539: INPUT_STATE_ANYWHERE,
! 540:
! 541: { 0x00, 0x17, NULL, NULL },
! 542: { 0x19, 0x19, NULL, NULL },
! 543: { 0x1c, 0x1f, NULL, NULL },
! 544: { 0x20, 0xff, NULL, NULL },
1.1 nicm 545:
1.28 ! nicm 546: { -1, -1, NULL, NULL }
! 547: };
1.1 nicm 548:
1.28 ! nicm 549: /* osc_string state table. */
! 550: const struct input_transition input_state_osc_string_table[] = {
! 551: INPUT_STATE_ANYWHERE,
! 552:
! 553: { 0x00, 0x06, NULL, NULL },
! 554: { 0x07, 0x07, NULL, &input_state_ground },
! 555: { 0x08, 0x17, NULL, NULL },
! 556: { 0x19, 0x19, NULL, NULL },
! 557: { 0x1c, 0x1f, NULL, NULL },
! 558: { 0x20, 0xff, input_input, NULL },
1.1 nicm 559:
1.28 ! nicm 560: { -1, -1, NULL, NULL }
! 561: };
1.1 nicm 562:
1.28 ! nicm 563: /* apc_string state table. */
! 564: const struct input_transition input_state_apc_string_table[] = {
! 565: INPUT_STATE_ANYWHERE,
! 566:
! 567: { 0x00, 0x17, NULL, NULL },
! 568: { 0x19, 0x19, NULL, NULL },
! 569: { 0x1c, 0x1f, NULL, NULL },
! 570: { 0x20, 0xff, input_input, NULL },
1.1 nicm 571:
1.28 ! nicm 572: { -1, -1, NULL, NULL }
! 573: };
1.1 nicm 574:
1.28 ! nicm 575: /* rename_string state table. */
! 576: const struct input_transition input_state_rename_string_table[] = {
! 577: INPUT_STATE_ANYWHERE,
! 578:
! 579: { 0x00, 0x17, NULL, NULL },
! 580: { 0x19, 0x19, NULL, NULL },
! 581: { 0x1c, 0x1f, NULL, NULL },
! 582: { 0x20, 0xff, input_input, NULL },
1.1 nicm 583:
1.28 ! nicm 584: { -1, -1, NULL, NULL }
! 585: };
1.1 nicm 586:
1.28 ! nicm 587: /* consume_st state table. */
! 588: const struct input_transition input_state_consume_st_table[] = {
! 589: INPUT_STATE_ANYWHERE,
! 590:
! 591: { 0x00, 0x17, NULL, NULL },
! 592: { 0x19, 0x19, NULL, NULL },
! 593: { 0x1c, 0x1f, NULL, NULL },
! 594: { 0x20, 0xff, NULL, NULL },
1.6 nicm 595:
1.28 ! nicm 596: { -1, -1, NULL, NULL }
! 597: };
1.6 nicm 598:
1.28 ! nicm 599: /* utf8_three state table. */
! 600: const struct input_transition input_state_utf8_three_table[] = {
! 601: /* No INPUT_STATE_ANYWHERE */
! 602:
! 603: { 0x00, 0x7f, NULL, &input_state_ground },
! 604: { 0x80, 0xbf, input_utf8_add, &input_state_utf8_two },
! 605: { 0xc0, 0xff, NULL, &input_state_ground },
1.4 nicm 606:
1.28 ! nicm 607: { -1, -1, NULL, NULL }
! 608: };
1.1 nicm 609:
1.28 ! nicm 610: /* utf8_two state table. */
! 611: const struct input_transition input_state_utf8_two_table[] = {
! 612: /* No INPUT_STATE_ANYWHERE */
! 613:
! 614: { 0x00, 0x7f, NULL, &input_state_ground },
! 615: { 0x80, 0xbf, input_utf8_add, &input_state_utf8_one },
! 616: { 0xc0, 0xff, NULL, &input_state_ground },
1.1 nicm 617:
1.28 ! nicm 618: { -1, -1, NULL, NULL }
! 619: };
1.1 nicm 620:
1.28 ! nicm 621: /* utf8_one state table. */
! 622: const struct input_transition input_state_utf8_one_table[] = {
! 623: /* No INPUT_STATE_ANYWHERE */
! 624:
! 625: { 0x00, 0x7f, NULL, &input_state_ground },
! 626: { 0x80, 0xbf, input_utf8_close, &input_state_ground },
! 627: { 0xc0, 0xff, NULL, &input_state_ground },
1.1 nicm 628:
1.28 ! nicm 629: { -1, -1, NULL, NULL }
! 630: };
1.1 nicm 631:
1.28 ! nicm 632: /* Input table compare. */
! 633: int
! 634: input_table_compare(const void *key, const void *value)
1.1 nicm 635: {
1.28 ! nicm 636: const struct input_ctx *ictx = key;
! 637: const struct input_table_entry *entry = value;
1.1 nicm 638:
1.28 ! nicm 639: if (ictx->ch != entry->ch)
! 640: return (ictx->ch - entry->ch);
! 641: return (strcmp(ictx->interm_buf, entry->interm));
1.1 nicm 642: }
643:
1.28 ! nicm 644: /* Initialise input parser. */
1.1 nicm 645: void
1.28 ! nicm 646: input_init(struct window_pane *wp)
1.1 nicm 647: {
1.28 ! nicm 648: struct input_ctx *ictx = &wp->ictx;
1.1 nicm 649:
1.28 ! nicm 650: memcpy(&ictx->cell, &grid_default_cell, sizeof ictx->cell);
1.1 nicm 651:
1.28 ! nicm 652: memcpy(&ictx->old_cell, &grid_default_cell, sizeof ictx->old_cell);
! 653: ictx->old_cx = 0;
! 654: ictx->old_cy = 0;
1.1 nicm 655:
1.28 ! nicm 656: *ictx->interm_buf = '\0';
! 657: ictx->interm_len = 0;
1.1 nicm 658:
1.28 ! nicm 659: *ictx->param_buf = '\0';
! 660: ictx->param_len = 0;
1.1 nicm 661:
1.28 ! nicm 662: ictx->state = &input_state_ground;
! 663: ictx->flags = 0;
1.1 nicm 664: }
665:
1.28 ! nicm 666: /* Destroy input parser. */
1.1 nicm 667: void
1.28 ! nicm 668: input_free(unused struct window_pane *wp)
1.1 nicm 669: {
670: }
671:
1.28 ! nicm 672: /* Parse input. */
1.1 nicm 673: void
1.28 ! nicm 674: input_parse(struct window_pane *wp)
1.1 nicm 675: {
1.28 ! nicm 676: struct input_ctx *ictx = &wp->ictx;
! 677: const struct input_transition *itr;
! 678: struct evbuffer *evb = wp->event->input;
! 679: u_char *buf;
! 680: size_t len, off;
1.1 nicm 681:
1.28 ! nicm 682: if (EVBUFFER_LENGTH(evb) == 0)
! 683: return;
! 684: wp->window->flags |= WINDOW_ACTIVITY;
1.1 nicm 685:
1.28 ! nicm 686: /*
! 687: * Open the screen. Use NULL wp if there is a mode set as don't want to
! 688: * update the tty.
! 689: */
! 690: if (wp->mode == NULL)
! 691: screen_write_start(&ictx->ctx, wp, &wp->base);
! 692: else
! 693: screen_write_start(&ictx->ctx, NULL, &wp->base);
! 694: ictx->wp = wp;
1.7 nicm 695:
1.28 ! nicm 696: buf = EVBUFFER_DATA(evb);
! 697: len = EVBUFFER_LENGTH(evb);
! 698: off = 0;
! 699:
! 700: /* Parse the input. */
! 701: while (off < len) {
! 702: ictx->ch = buf[off++];
! 703: log_debug("%s: '%c' %s", __func__, ictx->ch, ictx->state->name);
! 704:
! 705: /* Find the transition. */
! 706: itr = ictx->state->transitions;
! 707: while (itr->first != -1 && itr->last != -1) {
! 708: if (ictx->ch >= itr->first && ictx->ch <= itr->last)
1.7 nicm 709: break;
1.28 ! nicm 710: itr++;
1.1 nicm 711: }
1.28 ! nicm 712: if (itr->first == -1 || itr->last == -1) {
! 713: /* No transition? Eh? */
! 714: fatalx("No transition from state!");
1.3 nicm 715: }
1.1 nicm 716:
717: /*
1.28 ! nicm 718: * Execute the handler, if any. Don't switch state if it
! 719: * returns non-zero.
1.1 nicm 720: */
1.28 ! nicm 721: if (itr->handler && itr->handler(ictx) != 0)
! 722: continue;
! 723:
! 724: /* And switch state, if necessary. */
! 725: if (itr->state) {
! 726: if (ictx->state->exit != NULL)
! 727: ictx->state->exit(ictx);
! 728: ictx->state = itr->state;
! 729: if (ictx->state->enter != NULL)
! 730: ictx->state->enter(ictx);
1.1 nicm 731: }
732: }
733:
1.28 ! nicm 734: /* Close the screen. */
! 735: screen_write_stop(&ictx->ctx);
1.1 nicm 736:
1.28 ! nicm 737: evbuffer_drain(evb, len);
1.1 nicm 738: }
739:
1.28 ! nicm 740: /* Split the parameter list (if any). */
! 741: int
! 742: input_split(struct input_ctx *ictx)
1.1 nicm 743:
744: {
1.28 ! nicm 745: const char *errstr;
! 746: char *ptr, *out;
! 747: int n;
1.1 nicm 748:
1.28 ! nicm 749: ictx->param_list_len = 0;
! 750: if (ictx->param_len == 0)
! 751: return (0);
1.1 nicm 752:
1.28 ! nicm 753: ptr = ictx->param_buf;
! 754: while ((out = strsep(&ptr, ";")) != NULL) {
! 755: if (*out == '\0')
! 756: n = -1;
! 757: else {
! 758: n = strtonum(out, 0, INT_MAX, &errstr);
! 759: if (errstr != NULL)
! 760: return (-1);
! 761: }
1.1 nicm 762:
1.28 ! nicm 763: ictx->param_list[ictx->param_list_len++] = n;
! 764: if (ictx->param_list_len == nitems(ictx->param_list))
! 765: return (-1);
! 766: }
1.1 nicm 767:
1.28 ! nicm 768: return (0);
1.1 nicm 769: }
770:
1.28 ! nicm 771: /* Get an argument or return default value..*/
! 772: int
! 773: input_get(struct input_ctx *ictx, u_int validx, int minval, int defval)
1.1 nicm 774: {
1.28 ! nicm 775: int retval;
1.1 nicm 776:
1.28 ! nicm 777: if (validx >= ictx->param_list_len)
! 778: return (defval);
1.1 nicm 779:
1.28 ! nicm 780: retval = ictx->param_list[validx];
! 781: if (retval == -1)
! 782: return (defval);
! 783: if (retval < minval)
! 784: return (minval);
! 785: return (retval);
1.1 nicm 786: }
787:
1.28 ! nicm 788: /* Reply to terminal query. */
1.1 nicm 789: void
1.28 ! nicm 790: input_reply(struct input_ctx *ictx, const char *fmt, ...)
1.1 nicm 791: {
1.28 ! nicm 792: va_list ap;
! 793: char *reply;
1.1 nicm 794:
1.28 ! nicm 795: va_start(ap, fmt);
! 796: vasprintf(&reply, fmt, ap);
! 797: va_end(ap);
1.1 nicm 798:
1.28 ! nicm 799: bufferevent_write(ictx->wp->event, reply, strlen(reply));
! 800: xfree(reply);
1.8 nicm 801: }
802:
1.28 ! nicm 803: /* Clear saved state. */
1.8 nicm 804: void
1.28 ! nicm 805: input_clear(struct input_ctx *ictx)
1.8 nicm 806: {
1.28 ! nicm 807: *ictx->interm_buf = '\0';
! 808: ictx->interm_len = 0;
1.8 nicm 809:
1.28 ! nicm 810: *ictx->param_buf = '\0';
! 811: ictx->param_len = 0;
1.8 nicm 812:
1.28 ! nicm 813: ictx->flags &= ~INPUT_DISCARD;
1.14 nicm 814: }
815:
1.28 ! nicm 816: /* Output this character to the screen. */
! 817: int
! 818: input_print(struct input_ctx *ictx)
1.14 nicm 819: {
1.28 ! nicm 820: ictx->cell.data = ictx->ch;
! 821: screen_write_cell(&ictx->ctx, &ictx->cell, NULL);
1.14 nicm 822:
1.28 ! nicm 823: return (0);
1.1 nicm 824: }
825:
1.28 ! nicm 826: /* Collect intermediate string. */
! 827: int
! 828: input_intermediate(struct input_ctx *ictx)
1.1 nicm 829: {
1.28 ! nicm 830: if (ictx->interm_len == (sizeof ictx->interm_buf) - 1)
! 831: ictx->flags |= INPUT_DISCARD;
! 832: else {
! 833: ictx->interm_buf[ictx->interm_len++] = ictx->ch;
! 834: ictx->interm_buf[ictx->interm_len] = '\0';
! 835: }
1.1 nicm 836:
1.28 ! nicm 837: return (0);
1.1 nicm 838: }
839:
1.28 ! nicm 840: /* Collect parameter string. */
! 841: int
! 842: input_parameter(struct input_ctx *ictx)
1.1 nicm 843: {
1.28 ! nicm 844: if (ictx->param_len == (sizeof ictx->param_buf) - 1)
! 845: ictx->flags |= INPUT_DISCARD;
! 846: else {
! 847: ictx->param_buf[ictx->param_len++] = ictx->ch;
! 848: ictx->param_buf[ictx->param_len] = '\0';
! 849: }
1.1 nicm 850:
1.28 ! nicm 851: return (0);
1.1 nicm 852: }
853:
1.28 ! nicm 854: /* Collect input string. */
! 855: int
! 856: input_input(struct input_ctx *ictx)
1.1 nicm 857: {
1.28 ! nicm 858: if (ictx->input_len == (sizeof ictx->input_buf) - 1)
! 859: ictx->flags |= INPUT_DISCARD;
! 860: else {
! 861: ictx->input_buf[ictx->input_len++] = ictx->ch;
! 862: ictx->input_buf[ictx->input_len] = '\0';
! 863: }
1.1 nicm 864:
1.28 ! nicm 865: return (0);
1.1 nicm 866: }
867:
1.28 ! nicm 868: /* Execute C0 control sequence. */
! 869: int
! 870: input_c0_dispatch(struct input_ctx *ictx)
1.1 nicm 871: {
1.28 ! nicm 872: struct screen_write_ctx *sctx = &ictx->ctx;
! 873: struct window_pane *wp = ictx->wp;
! 874: struct screen *s = sctx->s;
1.1 nicm 875:
1.28 ! nicm 876: log_debug("%s: '%c", __func__, ictx->ch);
1.1 nicm 877:
1.28 ! nicm 878: switch (ictx->ch) {
! 879: case '\000': /* NUL */
! 880: break;
! 881: case '\007': /* BEL */
! 882: wp->window->flags |= WINDOW_BELL;
! 883: break;
! 884: case '\010': /* BS */
! 885: screen_write_backspace(sctx);
! 886: break;
! 887: case '\011': /* HT */
! 888: /* Don't tab beyond the end of the line. */
! 889: if (s->cx >= screen_size_x(s) - 1)
! 890: break;
1.1 nicm 891:
1.28 ! nicm 892: /* Find the next tab point, or use the last column if none. */
! 893: do {
! 894: s->cx++;
! 895: if (bit_test(s->tabs, s->cx))
! 896: break;
! 897: } while (s->cx < screen_size_x(s) - 1);
! 898: break;
! 899: case '\012': /* LF */
! 900: case '\013': /* VT */
! 901: case '\014': /* FF */
! 902: screen_write_linefeed(sctx, 0);
! 903: break;
! 904: case '\015': /* CR */
! 905: screen_write_carriagereturn(sctx);
! 906: break;
! 907: case '\016': /* SO */
! 908: ictx->cell.attr |= GRID_ATTR_CHARSET;
! 909: break;
! 910: case '\017': /* SI */
! 911: ictx->cell.attr &= ~GRID_ATTR_CHARSET;
! 912: break;
! 913: default:
! 914: log_debug("%s: unknown '%c'", __func__, ictx->ch);
! 915: break;
! 916: }
1.1 nicm 917:
1.28 ! nicm 918: return (0);
1.7 nicm 919: }
920:
1.28 ! nicm 921: /* Execute escape sequence. */
! 922: int
! 923: input_esc_dispatch(struct input_ctx *ictx)
1.7 nicm 924: {
1.28 ! nicm 925: struct screen_write_ctx *sctx = &ictx->ctx;
! 926: struct screen *s = sctx->s;
! 927: struct input_table_entry *entry;
1.7 nicm 928:
1.28 ! nicm 929: if (ictx->flags & INPUT_DISCARD)
! 930: return (0);
! 931: log_debug("%s: '%c', %s", __func__, ictx->ch, ictx->interm_buf);
1.7 nicm 932:
1.28 ! nicm 933: entry = bsearch(ictx, input_esc_table, nitems(input_esc_table),
! 934: sizeof input_esc_table[0], input_table_compare);
! 935: if (entry == NULL) {
! 936: log_debug("%s: unknown '%c'", __func__, ictx->ch);
! 937: return (0);
! 938: }
1.7 nicm 939:
1.28 ! nicm 940: switch (entry->type) {
! 941: case INPUT_ESC_RIS:
! 942: memcpy(&ictx->cell, &grid_default_cell, sizeof ictx->cell);
! 943: memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
! 944: ictx->old_cx = 0;
! 945: ictx->old_cy = 0;
1.1 nicm 946:
1.28 ! nicm 947: screen_reset_tabs(sctx->s);
1.1 nicm 948:
1.28 ! nicm 949: screen_write_scrollregion(sctx, 0, screen_size_y(sctx->s) - 1);
1.1 nicm 950:
1.28 ! nicm 951: screen_write_insertmode(sctx, 0);
! 952: screen_write_kcursormode(sctx, 0);
! 953: screen_write_kkeypadmode(sctx, 0);
! 954: screen_write_mousemode(sctx, 0);
1.1 nicm 955:
1.28 ! nicm 956: screen_write_clearscreen(sctx);
! 957: screen_write_cursormove(sctx, 0, 0);
! 958: break;
! 959: case INPUT_ESC_IND:
! 960: screen_write_linefeed(sctx, 0);
! 961: break;
! 962: case INPUT_ESC_NEL:
! 963: screen_write_carriagereturn(sctx);
! 964: screen_write_linefeed(sctx, 0);
! 965: break;
! 966: case INPUT_ESC_HTS:
! 967: if (s->cx < screen_size_x(s))
! 968: bit_set(s->tabs, s->cx);
! 969: break;
! 970: case INPUT_ESC_RI:
! 971: screen_write_reverseindex(sctx);
! 972: break;
! 973: case INPUT_ESC_DECKPAM:
! 974: screen_write_kkeypadmode(sctx, 1);
! 975: break;
! 976: case INPUT_ESC_DECKPNM:
! 977: screen_write_kkeypadmode(sctx, 0);
1.1 nicm 978: break;
1.28 ! nicm 979: case INPUT_ESC_DECSC:
! 980: memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
! 981: ictx->old_cx = s->cx;
! 982: ictx->old_cy = s->cy;
! 983: break;
! 984: case INPUT_ESC_DECRC:
! 985: memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell);
! 986: screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy);
! 987: break;
! 988: case INPUT_ESC_DECALN:
! 989: screen_write_alignmenttest(sctx);
! 990: break;
! 991: case INPUT_ESC_SCSON_G0:
! 992: /*
! 993: * Not really supported, but fake it up enough for those that
! 994: * use it to switch character sets (by redefining G0 to
! 995: * graphics set, rather than switching to G1).
! 996: */
! 997: ictx->cell.attr &= ~GRID_ATTR_CHARSET;
1.1 nicm 998: break;
1.28 ! nicm 999: case INPUT_ESC_SCSOFF_G0:
! 1000: ictx->cell.attr |= GRID_ATTR_CHARSET;
1.1 nicm 1001: break;
1002: }
1.28 ! nicm 1003:
! 1004: return (0);
1.1 nicm 1005: }
1006:
1.28 ! nicm 1007: /* Execute control sequence. */
! 1008: int
! 1009: input_csi_dispatch(struct input_ctx *ictx)
1.1 nicm 1010: {
1.28 ! nicm 1011: struct screen_write_ctx *sctx = &ictx->ctx;
! 1012: struct window_pane *wp = ictx->wp;
! 1013: struct screen *s = sctx->s;
! 1014: struct input_table_entry *entry;
! 1015: int n, m;
1.1 nicm 1016:
1.28 ! nicm 1017: if (ictx->flags & INPUT_DISCARD)
! 1018: return (0);
! 1019: if (input_split(ictx) != 0)
! 1020: return (0);
! 1021: log_debug("%s: '%c' \"%s\" \"%s\"",
! 1022: __func__, ictx->ch, ictx->interm_buf, ictx->param_buf);
1.1 nicm 1023:
1.28 ! nicm 1024: entry = bsearch(ictx, input_csi_table, nitems(input_csi_table),
! 1025: sizeof input_csi_table[0], input_table_compare);
! 1026: if (entry == NULL) {
! 1027: log_debug("%s: unknown '%c'", __func__, ictx->ch);
! 1028: return (0);
! 1029: }
1.1 nicm 1030:
1.28 ! nicm 1031: switch (entry->type) {
! 1032: case INPUT_CSI_CBT:
! 1033: /* Find the previous tab point, n times. */
! 1034: n = input_get(ictx, 0, 1, 1);
! 1035: while (s->cx > 0 && n-- > 0) {
! 1036: do
! 1037: s->cx--;
! 1038: while (s->cx > 0 && !bit_test(s->tabs, s->cx));
! 1039: }
! 1040: break;
! 1041: case INPUT_CSI_CUB:
! 1042: screen_write_cursorleft(sctx, input_get(ictx, 0, 1, 1));
! 1043: break;
! 1044: case INPUT_CSI_CUD:
! 1045: screen_write_cursordown(sctx, input_get(ictx, 0, 1, 1));
! 1046: break;
! 1047: case INPUT_CSI_CUF:
! 1048: screen_write_cursorright(sctx, input_get(ictx, 0, 1, 1));
! 1049: break;
! 1050: case INPUT_CSI_CUP:
! 1051: n = input_get(ictx, 0, 1, 1);
! 1052: m = input_get(ictx, 1, 1, 1);
! 1053: screen_write_cursormove(sctx, m - 1, n - 1);
! 1054: break;
! 1055: case INPUT_CSI_CUU:
! 1056: screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1));
! 1057: break;
! 1058: case INPUT_CSI_DA:
! 1059: switch (input_get(ictx, 0, 0, 0)) {
! 1060: case 0:
! 1061: input_reply(ictx, "\033[?1;2c");
! 1062: break;
! 1063: default:
! 1064: log_debug("%s: unknown '%c'", __func__, ictx->ch);
! 1065: break;
! 1066: }
! 1067: break;
! 1068: case INPUT_CSI_DCH:
! 1069: screen_write_deletecharacter(sctx, input_get(ictx, 0, 1, 1));
! 1070: break;
! 1071: case INPUT_CSI_DECSTBM:
! 1072: n = input_get(ictx, 0, 1, 1);
! 1073: m = input_get(ictx, 1, 1, screen_size_y(s));
! 1074: screen_write_scrollregion(sctx, n - 1, m - 1);
1.1 nicm 1075: break;
1.28 ! nicm 1076: case INPUT_CSI_DL:
! 1077: screen_write_deleteline(sctx, input_get(ictx, 0, 1, 1));
1.1 nicm 1078: break;
1.28 ! nicm 1079: case INPUT_CSI_DSR:
! 1080: switch (input_get(ictx, 0, 0, 0)) {
! 1081: case 5:
! 1082: input_reply(ictx, "\033[0n");
! 1083: break;
! 1084: case 6:
! 1085: input_reply(ictx, "\033[%u;%uR", s->cy + 1, s->cx + 1);
! 1086: break;
! 1087: default:
! 1088: log_debug("%s: unknown '%c'", __func__, ictx->ch);
! 1089: break;
! 1090: }
! 1091: break;
! 1092: case INPUT_CSI_ED:
! 1093: switch (input_get(ictx, 0, 0, 0)) {
! 1094: case 0:
! 1095: screen_write_clearendofscreen(sctx);
! 1096: break;
! 1097: case 1:
! 1098: screen_write_clearstartofscreen(sctx);
! 1099: break;
! 1100: case 2:
! 1101: screen_write_clearscreen(sctx);
! 1102: break;
! 1103: default:
! 1104: log_debug("%s: unknown '%c'", __func__, ictx->ch);
! 1105: break;
! 1106: }
! 1107: break;
! 1108: case INPUT_CSI_EL:
! 1109: switch (input_get(ictx, 0, 0, 0)) {
! 1110: case 0:
! 1111: screen_write_clearendofline(sctx);
! 1112: break;
! 1113: case 1:
! 1114: screen_write_clearstartofline(sctx);
! 1115: break;
! 1116: case 2:
! 1117: screen_write_clearline(sctx);
! 1118: break;
! 1119: default:
! 1120: log_debug("%s: unknown '%c'", __func__, ictx->ch);
! 1121: break;
! 1122: }
! 1123: break;
! 1124: case INPUT_CSI_HPA:
! 1125: n = input_get(ictx, 0, 1, 1);
! 1126: screen_write_cursormove(sctx, n - 1, s->cy);
! 1127: break;
! 1128: case INPUT_CSI_ICH:
! 1129: screen_write_insertcharacter(sctx, input_get(ictx, 0, 1, 1));
! 1130: break;
! 1131: case INPUT_CSI_IL:
! 1132: screen_write_insertline(sctx, input_get(ictx, 0, 1, 1));
! 1133: break;
! 1134: case INPUT_CSI_RM:
! 1135: switch (input_get(ictx, 0, 0, -1)) {
! 1136: case 4: /* IRM */
! 1137: screen_write_insertmode(&ictx->ctx, 0);
! 1138: break;
! 1139: default:
! 1140: log_debug("%s: unknown '%c'", __func__, ictx->ch);
! 1141: break;
! 1142: }
1.1 nicm 1143: break;
1.28 ! nicm 1144: case INPUT_CSI_RM_PRIVATE:
! 1145: switch (input_get(ictx, 0, 0, -1)) {
1.1 nicm 1146: case 1: /* GATM */
1.28 ! nicm 1147: screen_write_kcursormode(&ictx->ctx, 0);
1.1 nicm 1148: break;
1.17 nicm 1149: case 3: /* DECCOLM */
1.24 nicm 1150: screen_write_cursormove(&ictx->ctx, 0, 0);
1.17 nicm 1151: screen_write_clearscreen(&ictx->ctx);
1152: break;
1.1 nicm 1153: case 25: /* TCEM */
1.28 ! nicm 1154: screen_write_cursormode(&ictx->ctx, 0);
1.1 nicm 1155: break;
1156: case 1000:
1.28 ! nicm 1157: screen_write_mousemode(&ictx->ctx, 0);
1.1 nicm 1158: break;
1.9 nicm 1159: case 1049:
1.28 ! nicm 1160: window_pane_alternate_off(wp, &ictx->cell);
1.9 nicm 1161: break;
1.1 nicm 1162: default:
1.28 ! nicm 1163: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1.1 nicm 1164: break;
1165: }
1.28 ! nicm 1166: break;
! 1167: case INPUT_CSI_SGR:
! 1168: input_csi_dispatch_sgr(ictx);
! 1169: break;
! 1170: case INPUT_CSI_SM:
! 1171: switch (input_get(ictx, 0, 0, -1)) {
1.1 nicm 1172: case 4: /* IRM */
1173: screen_write_insertmode(&ictx->ctx, 1);
1174: break;
1175: default:
1.28 ! nicm 1176: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1.1 nicm 1177: break;
1178: }
1.28 ! nicm 1179: break;
! 1180: case INPUT_CSI_SM_PRIVATE:
! 1181: switch (input_get(ictx, 0, 0, -1)) {
1.1 nicm 1182: case 1: /* GATM */
1.28 ! nicm 1183: screen_write_kcursormode(&ictx->ctx, 1);
1.17 nicm 1184: break;
1185: case 3: /* DECCOLM */
1.24 nicm 1186: screen_write_cursormove(&ictx->ctx, 0, 0);
1.17 nicm 1187: screen_write_clearscreen(&ictx->ctx);
1.1 nicm 1188: break;
1189: case 25: /* TCEM */
1.28 ! nicm 1190: screen_write_cursormode(&ictx->ctx, 1);
1.1 nicm 1191: break;
1192: case 1000:
1.28 ! nicm 1193: screen_write_mousemode(&ictx->ctx, 1);
1.9 nicm 1194: break;
1195: case 1049:
1.28 ! nicm 1196: window_pane_alternate_on(wp, &ictx->cell);
1.1 nicm 1197: break;
1198: default:
1.28 ! nicm 1199: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1.1 nicm 1200: break;
1201: }
1.28 ! nicm 1202: break;
! 1203: case INPUT_CSI_TBC:
! 1204: switch (input_get(ictx, 0, 0, 0)) {
! 1205: case 0:
! 1206: if (s->cx < screen_size_x(s))
! 1207: bit_clear(s->tabs, s->cx);
1.1 nicm 1208: break;
1.28 ! nicm 1209: case 3:
! 1210: bit_nclear(s->tabs, 0, screen_size_x(s) - 1);
1.1 nicm 1211: break;
1212: default:
1.28 ! nicm 1213: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1.1 nicm 1214: break;
1215: }
1.28 ! nicm 1216: break;
! 1217: case INPUT_CSI_VPA:
! 1218: n = input_get(ictx, 0, 1, 1);
! 1219: screen_write_cursormove(sctx, s->cx, n - 1);
! 1220: break;
1.1 nicm 1221: }
1222:
1.28 ! nicm 1223: return (0);
1.1 nicm 1224: }
1225:
1.28 ! nicm 1226: /* Handle CSI SGR. */
1.1 nicm 1227: void
1.28 ! nicm 1228: input_csi_dispatch_sgr(struct input_ctx *ictx)
1.1 nicm 1229: {
1.28 ! nicm 1230: struct grid_cell *gc = &ictx->cell;
! 1231: u_int i;
! 1232: int n, m;
! 1233: u_char attr;
1.1 nicm 1234:
1.28 ! nicm 1235: if (ictx->param_list_len == 0) {
1.1 nicm 1236: attr = gc->attr;
1237: memcpy(gc, &grid_default_cell, sizeof *gc);
1.24 nicm 1238: gc->attr |= (attr & GRID_ATTR_CHARSET);
1.1 nicm 1239: return;
1240: }
1241:
1.28 ! nicm 1242: for (i = 0; i < ictx->param_list_len; i++) {
! 1243: n = input_get(ictx, i, 0, 0);
1.1 nicm 1244:
1.28 ! nicm 1245: if (n == 38 || n == 48) {
1.1 nicm 1246: i++;
1.28 ! nicm 1247: if (input_get(ictx, i, 0, -1) != 5)
1.1 nicm 1248: continue;
1249:
1250: i++;
1.28 ! nicm 1251: m = input_get(ictx, i, 0, -1);
! 1252: if (m == -1) {
! 1253: if (n == 38) {
! 1254: gc->flags &= ~GRID_FLAG_FG256;
! 1255: gc->fg = 8;
! 1256: } else if (n == 48) {
! 1257: gc->flags &= ~GRID_FLAG_BG256;
! 1258: gc->fg = 8;
! 1259: }
! 1260:
! 1261: } else {
! 1262: if (n == 38) {
! 1263: gc->flags |= GRID_FLAG_FG256;
! 1264: gc->fg = m;
! 1265: } else if (n == 48) {
! 1266: gc->flags |= GRID_FLAG_BG256;
! 1267: gc->bg = m;
! 1268: }
1.1 nicm 1269: }
1270: continue;
1271: }
1272:
1.28 ! nicm 1273: switch (n) {
1.1 nicm 1274: case 0:
1275: case 10:
1276: attr = gc->attr;
1277: memcpy(gc, &grid_default_cell, sizeof *gc);
1278: gc->attr |= (attr & GRID_ATTR_CHARSET);
1279: break;
1280: case 1:
1281: gc->attr |= GRID_ATTR_BRIGHT;
1282: break;
1283: case 2:
1284: gc->attr |= GRID_ATTR_DIM;
1285: break;
1286: case 3:
1287: gc->attr |= GRID_ATTR_ITALICS;
1288: break;
1289: case 4:
1290: gc->attr |= GRID_ATTR_UNDERSCORE;
1291: break;
1292: case 5:
1293: gc->attr |= GRID_ATTR_BLINK;
1294: break;
1295: case 7:
1296: gc->attr |= GRID_ATTR_REVERSE;
1297: break;
1298: case 8:
1299: gc->attr |= GRID_ATTR_HIDDEN;
1300: break;
1301: case 22:
1302: gc->attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_DIM);
1303: break;
1304: case 23:
1305: gc->attr &= ~GRID_ATTR_ITALICS;
1306: break;
1307: case 24:
1308: gc->attr &= ~GRID_ATTR_UNDERSCORE;
1309: break;
1310: case 25:
1311: gc->attr &= ~GRID_ATTR_BLINK;
1312: break;
1313: case 27:
1314: gc->attr &= ~GRID_ATTR_REVERSE;
1315: break;
1316: case 30:
1317: case 31:
1318: case 32:
1319: case 33:
1320: case 34:
1321: case 35:
1322: case 36:
1323: case 37:
1324: gc->flags &= ~GRID_FLAG_FG256;
1.28 ! nicm 1325: gc->fg = n - 30;
1.1 nicm 1326: break;
1327: case 39:
1328: gc->flags &= ~GRID_FLAG_FG256;
1329: gc->fg = 8;
1330: break;
1331: case 40:
1332: case 41:
1333: case 42:
1334: case 43:
1335: case 44:
1336: case 45:
1337: case 46:
1338: case 47:
1339: gc->flags &= ~GRID_FLAG_BG256;
1.28 ! nicm 1340: gc->bg = n - 40;
1.1 nicm 1341: break;
1342: case 49:
1343: gc->flags &= ~GRID_FLAG_BG256;
1344: gc->bg = 8;
1.20 nicm 1345: break;
1346: case 90:
1347: case 91:
1348: case 92:
1349: case 93:
1350: case 94:
1351: case 95:
1352: case 96:
1353: case 97:
1.26 nicm 1354: gc->flags &= ~GRID_FLAG_FG256;
1.28 ! nicm 1355: gc->fg = n;
1.20 nicm 1356: break;
1357: case 100:
1358: case 101:
1359: case 102:
1360: case 103:
1361: case 104:
1362: case 105:
1363: case 106:
1364: case 107:
1.26 nicm 1365: gc->flags &= ~GRID_FLAG_BG256;
1.28 ! nicm 1366: gc->bg = n;
1.1 nicm 1367: break;
1368: }
1369: }
1.28 ! nicm 1370: }
! 1371:
! 1372: /* DCS string started. */
! 1373: void
! 1374: input_enter_dcs(struct input_ctx *ictx)
! 1375: {
! 1376: log_debug("%s", __func__);
! 1377:
! 1378: ictx->input_len = 0;
! 1379: }
! 1380:
! 1381: /* DCS terminator (ST) received. */
! 1382: void
! 1383: input_exit_dcs(unused struct input_ctx *ictx)
! 1384: {
! 1385: log_debug("%s", __func__);
! 1386: }
! 1387:
! 1388: /* OSC string started. */
! 1389: void
! 1390: input_enter_osc(struct input_ctx *ictx)
! 1391: {
! 1392: log_debug("%s", __func__);
! 1393:
! 1394: ictx->input_len = 0;
! 1395: }
! 1396:
! 1397: /* OSC terminator (ST) received. */
! 1398: void
! 1399: input_exit_osc(struct input_ctx *ictx)
! 1400: {
! 1401: if (ictx->flags & INPUT_DISCARD)
! 1402: return;
! 1403: log_debug("%s: \"%s\"", __func__, ictx->input_buf);
! 1404:
! 1405: if (ictx->input_len < 2 || ictx->input_buf[1] != ';')
! 1406: return;
! 1407: if (ictx->input_buf[0] != '0' && ictx->input_buf[0] != '2')
! 1408: return;
! 1409:
! 1410: screen_set_title(ictx->ctx.s, ictx->input_buf + 2);
! 1411: server_status_window(ictx->wp->window);
! 1412: }
! 1413:
! 1414: /* APC string started. */
! 1415: void
! 1416: input_enter_apc(struct input_ctx *ictx)
! 1417: {
! 1418: log_debug("%s", __func__);
! 1419:
! 1420: ictx->input_len = 0;
! 1421: }
! 1422:
! 1423: /* APC terminator (ST) received. */
! 1424: void
! 1425: input_exit_apc(struct input_ctx *ictx)
! 1426: {
! 1427: if (ictx->flags & INPUT_DISCARD)
! 1428: return;
! 1429: log_debug("%s: \"%s\"", __func__, ictx->input_buf);
! 1430:
! 1431: screen_set_title(ictx->ctx.s, ictx->input_buf);
! 1432: server_status_window(ictx->wp->window);
! 1433: }
! 1434:
! 1435: /* Rename string started. */
! 1436: void
! 1437: input_enter_rename(struct input_ctx *ictx)
! 1438: {
! 1439: log_debug("%s", __func__);
! 1440:
! 1441: ictx->input_len = 0;
! 1442: }
! 1443:
! 1444: /* Rename terminator (ST) received. */
! 1445: void
! 1446: input_exit_rename(struct input_ctx *ictx)
! 1447: {
! 1448: if (ictx->flags & INPUT_DISCARD)
! 1449: return;
! 1450: log_debug("%s: \"%s\"", __func__, ictx->input_buf);
! 1451:
! 1452: xfree(ictx->wp->window->name);
! 1453: ictx->wp->window->name = xstrdup(ictx->input_buf);
! 1454: options_set_number(&ictx->wp->window->options, "automatic-rename", 0);
! 1455:
! 1456: server_status_window(ictx->wp->window);
! 1457: }
! 1458:
! 1459: /* Open UTF-8 character. */
! 1460: int
! 1461: input_utf8_open(struct input_ctx *ictx)
! 1462: {
! 1463: if (!options_get_number(&ictx->wp->window->options, "utf8")) {
! 1464: /* Print, and do not switch state. */
! 1465: input_print(ictx);
! 1466: return (-1);
! 1467: }
! 1468: log_debug("%s", __func__);
! 1469:
! 1470: utf8_open(&ictx->utf8data, ictx->ch);
! 1471: return (0);
! 1472: }
! 1473:
! 1474: /* Append to UTF-8 character. */
! 1475: int
! 1476: input_utf8_add(struct input_ctx *ictx)
! 1477: {
! 1478: log_debug("%s", __func__);
! 1479:
! 1480: utf8_append(&ictx->utf8data, ictx->ch);
! 1481: return (0);
! 1482: }
! 1483:
! 1484: /* Close UTF-8 string. */
! 1485: int
! 1486: input_utf8_close(struct input_ctx *ictx)
! 1487: {
! 1488: log_debug("%s", __func__);
! 1489:
! 1490: utf8_append(&ictx->utf8data, ictx->ch);
! 1491:
! 1492: ictx->cell.flags |= GRID_FLAG_UTF8;
! 1493: screen_write_cell(&ictx->ctx, &ictx->cell, &ictx->utf8data);
! 1494: ictx->cell.flags &= ~GRID_FLAG_UTF8;
! 1495:
! 1496: return (0);
1.1 nicm 1497: }