--- rxvt-unicode/src/command.C 2019/07/07 08:06:44 1.585 +++ rxvt-unicode/src/command.C 2023/05/06 08:01:35 1.602 @@ -27,7 +27,7 @@ * Copyright (c) 2001 Marius Gedminas * - Ctrl/Mod4+Tab works like Meta+Tab (options) * Copyright (c) 2003 Rob McMullen - * Copyright (c) 2003-2014 Marc Lehmann + * Copyright (c) 2003-2021 Marc Lehmann * Copyright (c) 2007,2015 Emanuele Giaquinta * * This program is free software; you can redistribute it and/or modify @@ -170,7 +170,7 @@ # if ENABLE_COMBINING if (IS_COMPOSE (ch)) { - len = rxvt_composite.expand (ch, 0); + len = rxvt_composite.expand (ch); alloc = chr = new wchar_t[len]; rxvt_composite.expand (ch, chr); } @@ -1018,7 +1018,7 @@ rxvt_term::refresh_check () { if (want_refresh && !flush_ev.is_active ()) - flush_ev.start (1. / 60.); // refresh at max. 60 Hz normally + flush_ev.start (); display->flush (); } @@ -1279,12 +1279,12 @@ void rxvt_term::mouse_report (XButtonEvent &ev) { - int button_number, key_state = 0; + int button_number, state = 0; int x, y; - int code = 32; + bool release = ev.type == ButtonRelease; - x = Pixel2Col (ev.x) + 1; - y = Pixel2Row (ev.y) + 1; + x = 1 + clamp (Pixel2Col (ev.x), 0, ncol - 1); + y = 1 + clamp (Pixel2Row (ev.y), 0, nrow - 1); if (ev.type == MotionNotify) { @@ -1293,18 +1293,16 @@ mouse_row = x; mouse_col = y; - code += 32; + state += 32; } - if (MEvent.button == AnyButton) - button_number = 3; - else - { - button_number = MEvent.button - Button1; - /* add 0x3D for wheel events, like xterm does */ - if (button_number >= 3) - button_number += 64 - 3; - } + button_number = MEvent.button - Button1; + if (button_number > 10) + return; + else if (button_number >= 7) + button_number += 128 - 7; + else if (button_number >= 3) + button_number += 64 - 3; if (priv_modes & PrivMode_MouseX10) { @@ -1312,8 +1310,7 @@ * do not report ButtonRelease * no state info allowed */ - key_state = 0; - if (button_number == 3) + if (release) return; } else @@ -1325,23 +1322,25 @@ * plus will add in our own Double-Click reporting * 32 = Double Click */ - key_state = ((MEvent.state & ShiftMask) ? 4 : 0) - + ((MEvent.state & ModMetaMask) ? 8 : 0) - + ((MEvent.state & ControlMask) ? 16 : 0); + state += ((MEvent.state & ShiftMask) ? 4 : 0) + + ((MEvent.state & ModMetaMask) ? 8 : 0) + + ((MEvent.state & ControlMask) ? 16 : 0); #ifdef MOUSE_REPORT_DOUBLECLICK - key_state += ((MEvent.clicks > 1) ? 32 : 0); + state += ((MEvent.clicks > 1) ? 32 : 0); #endif } + int code = 32 + (release ? 3 : button_number) + state; + #if DEBUG_MOUSEREPORT fprintf (stderr, "Mouse ["); - if (key_state & 16) + if (state & 16) fputc ('C', stderr); - if (key_state & 4) + if (state & 4) fputc ('S', stderr); - if (key_state & 8) + if (state & 8) fputc ('A', stderr); - if (key_state & 32) + if (state & 32) fputc ('2', stderr); fprintf (stderr, "]: <%d>, %d/%d\n", button_number, @@ -1350,20 +1349,33 @@ #endif #if ENABLE_FRILLS - if (priv_modes & PrivMode_ExtMouseRight) + if (priv_modes & PrivMode_ExtMouseSGR) + tt_printf ("\033[<%d;%d;%d%c", + button_number + state, + x, + y, + release ? 'm' : 'M'); + else if (priv_modes & PrivMode_ExtMouseUrxvt) tt_printf ("\033[%d;%d;%dM", - code + button_number + key_state, + code, x, y); - else if (priv_modes & PrivMode_ExtModeMouse) - tt_printf ("\033[M%c%lc%lc", - code + button_number + key_state, - wint_t (32 + x), - wint_t (32 + y)); + else if (priv_modes & PrivMode_ExtMouseUTF8) + if (code < 128) + tt_printf ("\033[M%c%lc%lc", + code, + wint_t (32 + x), + wint_t (32 + y)); + else + tt_printf ("\033[M%c%c%lc%lc", + 0xc0 + (code >> 6), + 0x80 + (code & 0x3f), + wint_t (32 + x), + wint_t (32 + y)); else #endif tt_printf ("\033[M%c%c%c", - code + button_number + key_state, + code, 32 + x, 32 + y); } @@ -2141,7 +2153,7 @@ { /* mouse report from vt window */ /* don't report release of wheel "buttons" */ - if (ev.button >= 4) + if (ev.button >= 4 && ev.button <= 7) return; #ifdef MOUSE_REPORT_DOUBLECLICK /* only report the release of 'slow' single clicks */ @@ -2151,11 +2163,11 @@ > multiClickTime / 2))) { MEvent.clicks = 0; - MEvent.button = AnyButton; + MEvent.button = ev.button; mouse_report (ev); } #else /* MOUSE_REPORT_DOUBLECLICK */ - MEvent.button = AnyButton; + MEvent.button = ev.button; mouse_report (ev); #endif /* MOUSE_REPORT_DOUBLECLICK */ return; @@ -2352,7 +2364,7 @@ // read the next character wchar_t ecb_hot -rxvt_term::next_char () NOTHROW +rxvt_term::next_char () noexcept { while (cmdbuf_ptr < cmdbuf_endp) { @@ -2388,7 +2400,7 @@ // read the next octet uint32_t ecb_hot -rxvt_term::next_octet () NOTHROW +rxvt_term::next_octet () noexcept { return cmdbuf_ptr < cmdbuf_endp ? (unsigned char)*cmdbuf_ptr++ @@ -2398,7 +2410,7 @@ static class out_of_input out_of_input; wchar_t ecb_hot -rxvt_term::cmd_getc () THROW ((class out_of_input)) +rxvt_term::cmd_getc () { wchar_t c = next_char (); @@ -2409,7 +2421,7 @@ } uint32_t ecb_hot -rxvt_term::cmd_get8 () THROW ((class out_of_input)) +rxvt_term::cmd_get8 () { uint32_t c = next_octet (); @@ -2867,6 +2879,8 @@ case '?': if (ch == 'h' || ch == 'l' || ch == 'r' || ch == 's' || ch == 't') process_terminal_mode (ch, priv, nargs, arg); + if (prev_ch == '$' && ch == 'p') + process_terminal_mode (ch, priv, nargs, arg); break; case '!': @@ -2876,7 +2890,7 @@ scr_soft_reset (); static const int pm_h[] = { 7, 25 }; - static const int pm_l[] = { 1, 3, 4, 5, 6, 9, 66, 1000, 1001, 1005, 1015, 1049 }; + static const int pm_l[] = { 1, 3, 4, 5, 6, 9, 66, 1000, 1001, 1005, 1006, 1015, 1049 }; process_terminal_mode ('h', 0, ecb_array_length (pm_h), pm_h); process_terminal_mode ('l', 0, ecb_array_length (pm_l), pm_l); @@ -3017,8 +3031,13 @@ tt_printf ("%-.250s\012", rs[Rs_display_name]); break; case 8: /* unofficial extension */ - process_xterm_seq (XTerm_title, RESNAME "-" VERSION, CHAR_ST); - break; + { + string_term st; + st.v[0] = CHAR_ST; + st.v[1] = '\0'; + process_xterm_seq (XTerm_title, (char *)RESNAME "-" VERSION, st); // char * cast verified + break; + } } break; @@ -3213,7 +3232,7 @@ * ends_how is terminator used. returned input must be free()'d */ char * -rxvt_term::get_to_st (unicode_t &ends_how) +rxvt_term::get_to_st (string_term &st) { unicode_t ch; bool seen_esc = false; @@ -3252,7 +3271,11 @@ string[n++] = '\0'; - ends_how = (ch == 0x5c ? C0_ESC : ch); + n = 0; + if (ch == 0x5c) + st.v[n++] = C0_ESC; + st.v[n++] = ch; + st.v[n] = '\0'; return rxvt_wcstombs (string); } @@ -3268,8 +3291,8 @@ * Not handled yet */ - unicode_t eh; - char *s = get_to_st (eh); + string_term st; + char *s = get_to_st (st); if (s) free (s); @@ -3291,12 +3314,12 @@ if (ch == ';') { - unicode_t eh; - char *s = get_to_st (eh); + string_term st; + char *s = get_to_st (st); if (s) { - process_xterm_seq (arg, s, eh); + process_xterm_seq (arg, s, st); free (s); } } @@ -3330,34 +3353,49 @@ uint32_t color = (a << 24) | (r << 16) | (g << 8) | b; - unsigned int idx_r = r * (Red_levels - 1) / 0xff; - unsigned int idx_g = g * (Green_levels - 1) / 0xff; - unsigned int idx_b = b * (Blue_levels - 1) / 0xff; - unsigned int idx = colorcube_index (idx_r, idx_g, idx_b); - - /* we allow one of the 6 directly neighbouring colours */ + /* we allow one of the 6 closest neighbouring colours */ /* to replace the current color, if they not used recently */ - static const signed char dxyz[][3] = { - 0, 0, 0, - 0, 0, +1, - 0, 0, -1, - 0, +1, 0, - 0, -1, 0, - +1, 0, 0, - -1, 0, 0, + #if 0 + static const unsigned char dxyz[][3] = { + 0, 0, 0, + 0, 0, 4, + 0, 4, 4, + 4, 4, 0, + 4, 0, 4, + 0, 4, 0, + 4, 0, 0, + }; + #else + // silly compressed verlapping triplets version of above + static const unsigned char dxyz[] = { + 0, 0, 0, 4, 4, 0, 4, 0, 0, }; + #endif - for (int n = 0; n < ecb_array_length (dxyz); ++n) - { - int r = idx_r + dxyz[n][0]; - int g = idx_g + dxyz[n][1]; - int b = idx_b + dxyz[n][2]; + static const unsigned char color_level[8][32] = { + // neighbour index + {0, 0, 1, 0, 0, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3}, + {0, 1, 0, 1, 1, 2, 1, 1, 2, 2, 3, 3, 2, 2, 2, 3, 3, 3, 4, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4}, + {0, 0, 1, 2, 1, 1, 2, 3, 3, 2, 2, 3, 3, 4, 4, 3, 3, 3, 4, 4, 5, 5, 5, 4, 4, 4, 5, 5, 5, 5, 5, 5}, + {0, 0, 2, 1, 2, 3, 2, 2, 3, 4, 4, 3, 3, 4, 4, 5, 5, 4, 4, 5, 5, 5, 6, 6, 5, 5, 5, 6, 6, 6, 6, 6}, + // Red_levels/Green_levels/Blue_levels index + {0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, + {0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, + {0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5}, + {0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6}, + }; - if (!IN_RANGE_EXC (r, 0, Red_levels )) continue; - if (!IN_RANGE_EXC (g, 0, Green_levels)) continue; - if (!IN_RANGE_EXC (b, 0, Blue_levels )) continue; + unsigned int idx; - unsigned int index = colorcube_index (r, g, b); + for (int n = 0; n < ecb_array_length (dxyz) - 2; ++n) + { + unsigned int idx_r = color_level[ Red_levels - dxyz[n + 0]][r / 8]; + unsigned int idx_g = color_level[Green_levels - dxyz[n + 1]][g / 8]; + unsigned int idx_b = color_level[ Blue_levels - dxyz[n + 2]][b / 8]; + unsigned int index = colorcube_index (idx_r, idx_g, idx_b); + + if (n == 0) + idx = index; if (rgb24_color[index] == color) { @@ -3373,8 +3411,8 @@ } // like (rgb24_seqno[idx] > rgb24_seqno[index]) - // but also handles wrap around values good enough - if ((uint16_t)(rgb24_seqno[idx] - rgb24_seqno[index]) < 0x7fff) + // but also handles wrap around values well enough + if ((uint16_t)(rgb24_seqno[idx] - rgb24_seqno[index]) < 0x8000) idx = index; } @@ -3391,19 +3429,25 @@ } void -rxvt_term::process_color_seq (int report, int color, const char *str, char resp) +rxvt_term::process_color_seq (int report, int color, const char *str, string_term &st) { if (str[0] == '?' && !str[1]) { rgba c; pix_colors_focused[color].get (c); + char rgba_str[32]; #if XFT if (c.a != rgba::MAX_CC) - tt_printf ("\033]%d;rgba:%04x/%04x/%04x/%04x%c", report, c.r, c.g, c.b, c.a, resp); + snprintf (rgba_str, sizeof (rgba_str), "rgba:%04x/%04x/%04x/%04x", c.r, c.g, c.b, c.a); else #endif - tt_printf ("\033]%d;rgb:%04x/%04x/%04x%c", report, c.r, c.g, c.b, resp); + snprintf (rgba_str, sizeof (rgba_str), "rgb:%04x/%04x/%04x", c.r, c.g, c.b); + + if (IN_RANGE_INC (color, minCOLOR, maxTermCOLOR)) + tt_printf ("\033]%d;%d;%s%s", report, color - minCOLOR, rgba_str, st.v); + else + tt_printf ("\033]%d;%s%s", report, rgba_str, st.v); } else set_window_color (color, str); @@ -3413,7 +3457,7 @@ * XTerm escape sequences: ESC ] Ps;Pt (ST|BEL) */ void -rxvt_term::process_xterm_seq (int op, char *str, char resp) +rxvt_term::process_xterm_seq (int op, char *str, string_term &st) { int color; char *buf, *name; @@ -3458,7 +3502,7 @@ && actual_format == 8) str = (const char *)(value); - tt_printf ("\033]%d;%s%c", op, option (Opt_insecure) ? str : "", resp); + tt_printf ("\033]%d;%s%s", op, option (Opt_insecure) ? str : "", st.v); XFree (value); } @@ -3492,49 +3536,49 @@ if ((buf = strchr (name, ';')) != NULL) *buf++ = '\0'; - process_color_seq (op, color, name, resp); + process_color_seq (op, color, name, st); } break; case Rxvt_restoreFG: case XTerm_Color00: - process_color_seq (op, Color_fg, str, resp); + process_color_seq (op, Color_fg, str, st); break; case Rxvt_restoreBG: case XTerm_Color01: - process_color_seq (op, Color_bg, str, resp); + process_color_seq (op, Color_bg, str, st); break; #ifndef NO_CURSORCOLOR case XTerm_Color_cursor: - process_color_seq (op, Color_cursor, str, resp); + process_color_seq (op, Color_cursor, str, st); break; #endif case XTerm_Color_pointer_fg: - process_color_seq (op, Color_pointer_fg, str, resp); + process_color_seq (op, Color_pointer_fg, str, st); break; case XTerm_Color_pointer_bg: - process_color_seq (op, Color_pointer_bg, str, resp); + process_color_seq (op, Color_pointer_bg, str, st); break; #ifdef OPTION_HC case XTerm_Color_HC: - process_color_seq (op, Color_HC, str, resp); + process_color_seq (op, Color_HC, str, st); break; case XTerm_Color_HTC: - process_color_seq (op, Color_HTC, str, resp); + process_color_seq (op, Color_HTC, str, st); break; #endif #ifndef NO_BOLD_UNDERLINE_REVERSE case URxvt_Color_BD: - process_color_seq (op, Color_BD, str, resp); + process_color_seq (op, Color_BD, str, st); break; case URxvt_Color_UL: - process_color_seq (op, Color_UL, str, resp); + process_color_seq (op, Color_UL, str, st); break; case URxvt_Color_IT: - process_color_seq (op, Color_IT, str, resp); + process_color_seq (op, Color_IT, str, st); break; #endif case URxvt_Color_border: - process_color_seq (op, Color_border, str, resp); + process_color_seq (op, Color_border, str, st); break; case XTerm_logfile: @@ -3562,10 +3606,10 @@ case URxvt_boldItalicFont: #endif if (query) - tt_printf ("\33]%d;%-.250s%c", saveop, + tt_printf ("\33]%d;%-.250s%s", saveop, option (Opt_insecure) && fontset[op - URxvt_font]->fontdesc ? fontset[op - URxvt_font]->fontdesc : "", - resp); + st.v); else { const char *&res = rs[Rs_font + (op - URxvt_font)]; @@ -3578,16 +3622,23 @@ case URxvt_version: if (query) - tt_printf ("\33]%d;rxvt-unicode;%-.20s;%c;%c%c", + tt_printf ("\33]%d;rxvt-unicode;%-.20s;%c;%c%s", op, rs[Rs_name], VERSION[0], VERSION[2], - resp); + st.v); break; #if !ENABLE_MINIMAL + case URxvt_cellinfo: + if (query) + tt_printf ("\33]%d;%d;%d;%d%s", saveop, + fwidth, fheight, fbase, + st.v); + break; + case URxvt_locale: if (query) - tt_printf ("\33]%d;%-.250s%c", op, option (Opt_insecure) ? locale : "", resp); + tt_printf ("\33]%d;%-.250s%s", op, option (Opt_insecure) ? locale : "", st.v); else { set_locale (str); @@ -3612,7 +3663,7 @@ #if ENABLE_PERL case URxvt_perl: - HOOK_INVOKE ((this, HOOK_OSC_SEQ_PERL, DT_STR, str, DT_STR_LEN, &resp, 1, DT_END)); + HOOK_INVOKE ((this, HOOK_OSC_SEQ_PERL, DT_STR, str, DT_STR, st.v, DT_END)); break; #endif } @@ -3702,12 +3753,13 @@ { 1003, PrivMode_MouseAnyEvent }, #if ENABLE_FRILLS { 1004, PrivMode_FocusEvent }, - { 1005, PrivMode_ExtModeMouse }, + { 1005, PrivMode_ExtMouseUTF8 }, + { 1006, PrivMode_ExtMouseSGR }, #endif { 1010, PrivMode_TtyOutputInh }, // rxvt extension { 1011, PrivMode_Keypress }, // rxvt extension #if ENABLE_FRILLS - { 1015, PrivMode_ExtMouseRight }, // urxvt extension of 1005 + { 1015, PrivMode_ExtMouseUrxvt }, // urxvt extension of 1005 #endif // 1035 enable modifiers for alt, numlock NYI // 1036 send ESC for meta keys NYI @@ -3716,12 +3768,32 @@ // 1048 save and restore cursor, implemented in code { 1049, PrivMode_Screen }, /* xterm extension, clear screen on ti rather than te */ // 1051, 1052, 1060, 1061 keyboard emulation NYI +#if ENABLE_FRILLS { 2004, PrivMode_BracketPaste }, +#endif }; if (nargs == 0) return; + // DECRQM + if (mode == 'p') + { + int status = 0; + if (nargs != 1) + return; + + for (j = 0; j < ecb_array_length (argtopriv); j++) + if (argtopriv[j].argval == arg[0]) + { + status = (priv_modes & argtopriv[j].bit) ? 1 : 2; + break; + } + + tt_printf ("\33[?%d;%d$y", arg[0], status); + return; + } + /* make lo/hi boolean */ if (mode == 'l') mode = 0; /* reset */ @@ -3981,7 +4053,7 @@ { unsigned int fgbg = arg[i] == 38 ? Color_fg : Color_bg; unsigned int idx; - + if (nargs > i + 2 && arg[i + 1] == 5) { idx = minCOLOR + arg[i + 2];