diff --git a/buffer.c b/buffer.c index 27a9e54..d10f6fd 100644 --- a/buffer.c +++ b/buffer.c @@ -954,7 +954,6 @@ void eb_trace_bytes(const void *buf, int size, int state) endp = p0 + size; #define MAX_TRACE_WIDTH 98 - // XXX: should encode into a local buffer by chunks for (p = p0; p0 < endp; p++) { while (p >= endp || *p < 32 || *p >= 127 || *p == '\\') { if (p0 >= endp) diff --git a/qe.c b/qe.c index 1686692..5481923 100644 --- a/qe.c +++ b/qe.c @@ -61,6 +61,7 @@ static int screen_height = 0; static int no_init_file; static int single_window; int force_tty; +int tty_mk = 2; int disable_crc; #ifdef CONFIG_SESSION int use_session_file; @@ -10374,19 +10375,19 @@ static void show_usage(void) static int parse_command_line(int argc, char **argv) { - int _optind; + int optind_; - for (_optind = 1; _optind < argc;) { - const char *arg, *r, *_optarg; + for (optind_ = 1; optind_ < argc;) { + const char *arg, *r, *optarg_; CmdLineOptionDef *p; bstr_t opt1; bstr_t opt2; - r = arg = argv[_optind]; + r = arg = argv[optind_]; /* stop before first non option */ if (r[0] != '-') break; - _optind++; + optind_++; opt1.s = opt2.s = r + 1; if (r[1] == '-') { @@ -10396,10 +10397,10 @@ static int parse_command_line(int argc, char **argv) break; } /* parse optional argument specified with opt=arg or opt:arg syntax */ - _optarg = NULL; + optarg_ = NULL; while (*r) { if (*r == ':' || *r == '=') { - _optarg = r + 1; + optarg_ = r + 1; break; } r++; @@ -10414,30 +10415,30 @@ static int parse_command_line(int argc, char **argv) bstr_t name = bstr_token(s, '|', &s); bstr_t argname = bstr_token(s, '|', &s); if (bstr_equal(opt1, shortname) || bstr_equal(opt2, name)) { - if (argname.len && _optarg == NULL) { - if (_optind >= argc) { - put_status(NULL, - "cmdline argument %.*s expected for --%.*s", - argname.len, argname.s, name.len, name.s); + if (p->need_arg && optarg_ == NULL) { + if (optind_ >= argc) { + put_error(NULL, + "cmdline argument %.*s expected for --%.*s", + argname.len, argname.s, name.len, name.s); goto next_cmd; } - _optarg = argv[_optind++]; + optarg_ = argv[optind_++]; } switch (p->type) { case CMD_LINE_TYPE_BOOL: - *p->u.int_ptr = qe_strtobool(_optarg, 1); + *p->u.int_ptr = qe_strtobool(optarg_, 1); break; case CMD_LINE_TYPE_INT: - *p->u.int_ptr = strtol(_optarg, NULL, 0); + *p->u.int_ptr = strtol(optarg_, NULL, 0); break; case CMD_LINE_TYPE_STRING: - *p->u.string_ptr = _optarg; + *p->u.string_ptr = optarg_; break; case CMD_LINE_TYPE_FVOID: p->u.func_noarg(); break; case CMD_LINE_TYPE_FARG: - p->u.func_arg(_optarg); + p->u.func_arg(optarg_); break; case CMD_LINE_TYPE_NONE: case CMD_LINE_TYPE_NEXT: @@ -10448,11 +10449,11 @@ static int parse_command_line(int argc, char **argv) p++; } } - put_status(NULL, "unknown cmdline option '%s'", arg); + put_error(NULL, "unknown cmdline option '%s'", arg); next_cmd: ; } - return _optind; + return optind_; } void do_add_resource_path(EditState *s, const char *path) @@ -10541,6 +10542,8 @@ static CmdLineOptionDef cmd_options[] = { CMD_LINE_BOOL("", "free-all", &free_everything, "free all structures upon exit"), #endif + CMD_LINE_INT("mk", "modify-other-keys", "VAL", &tty_mk, + "set the modifyOtherKeys tty configuration (0,1,2)"), CMD_LINE_LINK() }; diff --git a/qe.h b/qe.h index 1048660..38c0ff4 100644 --- a/qe.h +++ b/qe.h @@ -152,6 +152,7 @@ enum CmdLineOptionType { typedef struct CmdLineOptionDef { const char *desc; enum CmdLineOptionType type; + BOOL need_arg; union { int *int_ptr; const char **string_ptr; @@ -161,13 +162,13 @@ typedef struct CmdLineOptionDef { } u; } CmdLineOptionDef; -#define CMD_LINE_NONE() { NULL, CMD_LINE_TYPE_NONE, { NULL }} -#define CMD_LINE_BOOL(s,n,p,h) { s "|" n "||" h, CMD_LINE_TYPE_BOOL, { .int_ptr = p }} -#define CMD_LINE_INT(s,n,a,p,h) { s "|" n "|" a "|" h, CMD_LINE_TYPE_INT, { .int_ptr = p }} -#define CMD_LINE_STRING(s,n,a,p,h) { s "|" n "|" a "|" h, CMD_LINE_TYPE_STRING, { .string_ptr = p }} -#define CMD_LINE_FVOID(s,n,p,h) { s "|" n "||" h, CMD_LINE_TYPE_FVOID, { .func_noarg = p }} -#define CMD_LINE_FARG(s,n,a,p,h) { s "|" n "|" a "|" h, CMD_LINE_TYPE_FARG, { .func_arg = p }} -#define CMD_LINE_LINK() { NULL, CMD_LINE_TYPE_NEXT, { NULL }} +#define CMD_LINE_NONE() { NULL, CMD_LINE_TYPE_NONE, FALSE, { NULL }} +#define CMD_LINE_BOOL(s,n,p,h) { s "|" n "||" h, CMD_LINE_TYPE_BOOL, TRUE, { .int_ptr = p }} +#define CMD_LINE_INT(s,n,a,p,h) { s "|" n "|" a "|" h, CMD_LINE_TYPE_INT, TRUE, { .int_ptr = p }} +#define CMD_LINE_STRING(s,n,a,p,h) { s "|" n "|" a "|" h, CMD_LINE_TYPE_STRING, TRUE, { .string_ptr = p }} +#define CMD_LINE_FVOID(s,n,p,h) { s "|" n "||" h, CMD_LINE_TYPE_FVOID, FALSE, { .func_noarg = p }} +#define CMD_LINE_FARG(s,n,a,p,h) { s "|" n "|" a "|" h, CMD_LINE_TYPE_FARG, TRUE, { .func_arg = p }} +#define CMD_LINE_LINK() { NULL, CMD_LINE_TYPE_NEXT, FALSE, { NULL }} void qe_register_cmd_line_options(CmdLineOptionDef *table); @@ -890,6 +891,7 @@ int qe_free_mode_data(QEModeData *md); /* from tty.c */ /* set from command line option to prevent GUI such as X11 */ extern int force_tty; +extern int tty_mk; enum QEStyle { #define STYLE_DEF(constant, name, fg_color, bg_color, \ diff --git a/tty.c b/tty.c index fc153f9..d608a3a 100644 --- a/tty.c +++ b/tty.c @@ -322,6 +322,10 @@ static int tty_dpy_init(QEditScreen *s, "\033[39;49m" /* orig_pair */ "\033[?1h\033=" /* keypad_xmit */ ); + if (tty_mk) { + /* modifyOtherKeys: report shift states */ + TTY_FPRINTF(s->STDOUT, "\033[>4;%dm", tty_mk); + } #endif /* Get charset from command line option */ @@ -417,6 +421,7 @@ static int tty_dpy_init(QEditScreen *s, sigemptyset(&sig.sa_mask); sig.sa_flags = 0; sigaction(SIGWINCH, &sig, NULL); + fcntl(fileno(s->STDIN), F_SETFL, O_NONBLOCK); /* If stdout is to a pty, make sure we aren't in nonblocking mode. * Otherwise, the printf()s in term_flush() can fail with EAGAIN, @@ -454,7 +459,11 @@ static void tty_dpy_close(QEditScreen *s) "\033[?1l\033>" /* keypad_local */ "\033[?25h" /* show cursor */ "\r\033[m\033[K" /* return erase eol */ - ); + ); + if (tty_mk) { + /* modifyOtherKeys: report shift states */ + TTY_FPRINTF(s->STDOUT, "\033[>4m"); + } #endif fflush(s->STDOUT); tcsetattr(fileno(s->STDIN), TCSANOW, &ts->oldtty); @@ -657,7 +666,7 @@ static void tty_read_handler(void *opaque) * keys transmitting escape sequences starting with \033 * but followed immediately by more characters. */ - goto the_end; + goto the_end_meta; } ts->input_state = IS_ESC; break; @@ -675,11 +684,10 @@ static void tty_read_handler(void *opaque) if (!pending) { /* Distinguish alt-ESC from ESC prefix applied to other keys */ ch = KEY_META(KEY_ESC); - ts->input_state = IS_NORM; goto the_end; } /* cygwin A-right transmit ESC ESC[C ... */ - ts->has_meta = 8; + ts->has_meta = KEY_STATE_META; break; } if (ch == '[' && pending) { // CSI @@ -708,7 +716,6 @@ static void tty_read_handler(void *opaque) } /* FIXME: handle terminal answers */ ch = KEY_META(ch); - ts->input_state = IS_NORM; goto the_end; case IS_CSI: @@ -731,6 +738,7 @@ static void tty_read_handler(void *opaque) if (ts->interm) { /* syntax error: ignore CSI sequence */ ts->input_state = IS_NORM; + ts->has_meta = 0; break; } if (ts->nb_params < countof(ts->params)) { @@ -754,7 +762,6 @@ static void tty_read_handler(void *opaque) /* FIXME: Should only accept final bytes in range 40..7E, * and ignore other bytes. */ - ts->input_state = IS_NORM; n1 = ts->params[0] >= 0 ? ts->params[0] : 0; n2 = ts->params[1] >= 0 ? ts->params[1] : 1; switch ((ts->leader << 16) | (ts->interm << 8) | ch) { @@ -774,8 +781,13 @@ static void tty_read_handler(void *opaque) ch = ts->params[2]; if (ch == 8 && (ts->term_flags |= KBS_CONTROL_H)) ch = KEY_DEL; + // XXX: iTerm2 3.14.19 encoding bug for M-C-a to M-C-z + if (n2 == 4 && ch >= 'A' && ch <= 'Z') { + n2 |= 2; + ch += 'a' - 'A'; + } ch = get_modified_key(ch, n2); - goto the_end; + goto the_end_meta; } if (n1 < countof(csi_lookup)) { ch = csi_lookup[n1]; @@ -789,7 +801,7 @@ static void tty_read_handler(void *opaque) * supported by xterm if formatOtherKeys resource is selected */ ch = get_modified_key(n1, n2 - 1); - goto the_end; + goto the_end_meta; /* All these for ansi|cygwin */ default: /* n2 contains the shift status + 1: @@ -834,19 +846,17 @@ static void tty_read_handler(void *opaque) case 'Z': ch = KEY_SHIFT_TAB; goto the_end_modified; // kcbt } ch = KEY_UNKNOWN; - ts->has_meta = 0; goto the_end; } break; case IS_CSI2: /* cygwin/linux terminal */ - ts->input_state = IS_NORM; switch (ch) { - case 'A': ch = KEY_F1; goto the_end; - case 'B': ch = KEY_F2; goto the_end; - case 'C': ch = KEY_F3; goto the_end; - case 'D': ch = KEY_F4; goto the_end; - case 'E': ch = KEY_F5; goto the_end; + case 'A': ch = KEY_F1; goto the_end_meta; + case 'B': ch = KEY_F2; goto the_end_meta; + case 'C': ch = KEY_F3; goto the_end_meta; + case 'D': ch = KEY_F4; goto the_end_meta; + case 'E': ch = KEY_F5; goto the_end_meta; } ch = KEY_UNKNOWN; goto the_end; @@ -859,7 +869,6 @@ static void tty_read_handler(void *opaque) break; } n2 = ts->params[0] > 0 ? ts->params[0] - 1 : 0; - ts->input_state = IS_NORM; switch (ch) { case 'A': ch = KEY_UP; goto the_end_modified; case 'B': ch = KEY_DOWN; goto the_end_modified; @@ -888,14 +897,14 @@ static void tty_read_handler(void *opaque) ch = KEY_META(ch); if (n2 & 4) ch = KEY_CONTROL(ch); - goto the_end; the_end_meta: - if (ts->has_meta) { - ts->has_meta = 0; + if (ts->has_meta) ch = KEY_META(ch); - } + the_end: + ts->input_state = IS_NORM; + ts->has_meta = 0; // XXX: should add custom key sequences, especially for KEY_UNKNOWN ev->key_event.type = QE_KEY_EVENT; ev->key_event.key = ch; @@ -905,7 +914,7 @@ static void tty_read_handler(void *opaque) case IS_OSC: /* OSC syntax is: OSC string 07 or OSC string ST (ESC \) */ if (ch == 27) { - ts->has_meta = 1; + ts->has_meta = KEY_STATE_META; break; } if (ts->has_meta && ch == '\\') { @@ -915,6 +924,7 @@ static void tty_read_handler(void *opaque) break; // FIXME: handle terminal response ts->input_state = IS_NORM; + ts->has_meta = 0; break; } } diff --git a/util.c b/util.c index 2f4c6af..51f9834 100644 --- a/util.c +++ b/util.c @@ -1946,8 +1946,8 @@ int buf_put_key(buf_t *out, int key) { buf_put_key(out, key & 0xff); } else // FIXME: handle @-_ @@@ - if (key >= KEY_CTRL('a') && key <= KEY_CTRL('z')) { - buf_printf(out, "C-%c", key + 'a' - 1); + if (key >= KEY_CTRL('@') && key <= KEY_CTRL('_')) { + buf_printf(out, "C-%c", qe_tolower(key + 'A' - 1)); } else { buf_putc_utf8(out, key); } @@ -2410,9 +2410,9 @@ bstr_t bstr_token(const char *s, int sep, const char **pp) { continue; bs.len = s - bs.s; - if (pp) { - *pp = *s ? s + 1 : NULL; - } + } + if (pp) { + *pp = (s && *s) ? s + 1 : NULL; } return bs; }