--- rxvt-unicode/src/command.C 2011/04/07 12:19:40 1.482 +++ rxvt-unicode/src/command.C 2016/07/14 05:33:26 1.582 @@ -6,7 +6,7 @@ * Copyright (c) 1992 John Bovey, University of Kent at Canterbury * - original version * Copyright (c) 1994 Robert Nation - * - extensive modifications + * - extensive modifications * Copyright (c) 1995 Garrett D'Amore * - vt100 printing * Copyright (c) 1995 Steven Hirsch @@ -22,17 +22,17 @@ * and Linux 1.2.x * Copyright (c) 1997,1998 Oezguer Kesim * Copyright (c) 1998-2001 Geoff Wing - * - extensive modifications + * - extensive modifications * Copyright (c) 1998 Alfredo K. Kojima * Copyright (c) 2001 Marius Gedminas * - Ctrl/Mod4+Tab works like Meta+Tab (options) * Copyright (c) 2003 Rob McMullen - * Copyright (c) 2003-2011 Marc Lehmann - * Copyright (c) 2007 Emanuele Giaquinta + * Copyright (c) 2003-2014 Marc Lehmann + * Copyright (c) 2007,2015 Emanuele Giaquinta * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, @@ -56,10 +56,10 @@ # include "keyboard.h" #endif -#include +#include #if LINUX_YIELD_HACK -# include +# include #endif /*----------------------------------------------------------------------*/ @@ -133,7 +133,7 @@ 0, }; -void +void ecb_cold rxvt_term::iso14755_54 (int x, int y) { x = Pixel2Col (x); @@ -151,7 +151,7 @@ if (t != NOCHAR || !x) { - iso14755_51 (l.t[x], l.r[x], x, y); + iso14755_51 (l.t[x], l.r[x], x, y, view_start); iso14755buf = ISO_14755_54; break; } @@ -160,8 +160,8 @@ } } -void -rxvt_term::iso14755_51 (unicode_t ch, rend_t r, int x, int y) +void ecb_cold +rxvt_term::iso14755_51 (unicode_t ch, rend_t r, int x, int y, int y2) { rxvt_fontset *fs = FONTSET (r); wchar_t *chr, *alloc, ch2, **fname; @@ -184,6 +184,9 @@ len = 1; } + char rowcol[40]; + snprintf (rowcol, sizeof rowcol, "col %d row %d @%d", x, y, y2); + char attr[80]; // plenty sprintf (attr, "%08x = fg %d bg %d%s%s%s%s%s%s", @@ -205,16 +208,17 @@ max_it (width, wcswidth (fname[i], wcslen (fname[i]))); } - max_it (width, 8+5); // for char + hex max_it (width, strlen (attr)); if (y >= 0) { - y = (y >= nrow - len - 4 && x < width + 2) ? 0 : -1; + y = (y >= nrow - len - 5 && x < width + 2) ? 0 : -1; x = 0; } - scr_overlay_new (x, y, width, len * 2 + 1); + scr_overlay_new (x, y, width, len * 2 + 2); + + scr_overlay_set (0, 0, rowcol); r = SET_STYLE (OVERLAY_RSTYLE, GET_STYLE (r)); @@ -225,16 +229,16 @@ ch = *chr++; sprintf (buf, "%8x", ch); - scr_overlay_set (0, y, buf); - scr_overlay_set (9, y, '='); + scr_overlay_set (0, y + 1, buf); + scr_overlay_set (9, y + 1, '='); # if !UNICODE_3 if (ch >= 0x10000) ch = 0xfffd; # endif - scr_overlay_set (11, y, ch, r); + scr_overlay_set (11, y + 1, ch, r); if (WCWIDTH (ch) >= 2) - scr_overlay_set (12, y, NOCHAR, r); + scr_overlay_set (12, y + 1, NOCHAR, r); } // { @@ -242,10 +246,10 @@ // snprintf (buf, sizeof (buf), "(%.4d|%.4d)", x, y); // scr_overlay_set (0, 0, buf); // } - scr_overlay_set (0, len , attr); + scr_overlay_set (0, len + 1, attr); for (int i = 0; i < len; i++) { - scr_overlay_set (0, len + 1 + i, fname[i]); + scr_overlay_set (0, len + 2 + i, fname[i]); free (fname[i]); } @@ -256,25 +260,22 @@ } #endif -void +void ecb_cold rxvt_term::commit_iso14755 () { - wchar_t ch[2]; - - ch[0] = iso14755buf & ISO_14755_MASK; - ch[1] = 0; + wchar_t ch = iso14755buf & ISO_14755_MASK; if (iso14755buf & ISO_14755_51) { - char mb[16]; + char mb[MB_LEN_MAX]; int len; // allow verbatim 0-bytes and control-bytes to be entered - if (ch[0] >= 0x20) - len = wcstombs (mb, ch, 16); + if (ch >= 0x20) + len = wctomb (mb, ch); else { - mb[0] = ch[0]; + mb[0] = ch; len = 1; } @@ -287,7 +288,7 @@ iso14755buf = 0; } -static int +static int ecb_cold hex_keyval (XKeyEvent &ev) { // check whether this event corresponds to a hex digit @@ -306,7 +307,7 @@ } #endif -static inline KeySym +static inline KeySym ecb_cold translate_keypad (KeySym keysym, bool kp) { #ifdef XK_KP_Home @@ -316,13 +317,8 @@ XK_KP_8, // XK_KP_Up XK_KP_6, // XK_KP_Right XK_KP_2, // XK_KP_Down -# ifndef UNSHIFTED_SCROLLKEYS XK_KP_9, // XK_KP_Prior XK_KP_3, // XK_KP_Next -# else - XK_Prior, - XK_Next, -# endif XK_KP_1, // XK_KP_End XK_KP_5, // XK_KP_Begin }; @@ -342,7 +338,7 @@ return keysym; } -static inline int +static inline int ecb_cold map_function_key (KeySym keysym) { int param = 0; @@ -377,7 +373,6 @@ case XK_Select: param = 4; break; -#ifndef UNSHIFTED_SCROLLKEYS case XK_Prior: param = 5; break; @@ -390,7 +385,6 @@ case XK_End: param = 8; break; -#endif case XK_Help: param = 28; break; @@ -401,13 +395,22 @@ return param; } -void +static inline wchar_t * +rxvt_wcsdup (const wchar_t *str, int len) +{ + wchar_t *r = (wchar_t *)rxvt_malloc ((len + 1) * sizeof (wchar_t)); + memcpy (r, str, len * sizeof (wchar_t)); + r[len] = 0; + return r; +} + +void ecb_cold rxvt_term::key_press (XKeyEvent &ev) { int ctrl, meta, shft, len; - KeySym keysym; - int valid_keysym; - char kbuf[KBUFSZ]; + KeySym keysym = NoSymbol; + char rkbuf[KBUFSZ + 1]; + char *kbuf = rkbuf + 1; #if ISO_14755 if (iso14755buf & ISO_14755_52) @@ -426,7 +429,7 @@ kbuf[0] = 0; -#ifdef USE_XIM +#if USE_XIM if (Input_Context) { Status status_return; @@ -474,175 +477,23 @@ else len = 0; } - - valid_keysym = status_return == XLookupKeySym - || status_return == XLookupBoth; } else #endif { len = XLookupString (&ev, kbuf, KBUFSZ, &keysym, &compose); - valid_keysym = keysym != NoSymbol; } - if (valid_keysym) + if (keysym != NoSymbol) { -#ifdef KEYSYM_RESOURCE - if (keyboard->dispatch (this, keysym, ev.state)) - return; -#endif - - if (saveLines) - { -#ifdef UNSHIFTED_SCROLLKEYS - if (!ctrl && !meta) -#else - if (IS_SCROLL_MOD) -#endif - { - int lnsppg; - -#ifdef PAGING_CONTEXT_LINES - lnsppg = nrow - PAGING_CONTEXT_LINES; -#else - lnsppg = nrow * 4 / 5; -#endif - max_it (lnsppg, 1); - - if (keysym == XK_Prior) - { - scr_page (UP, lnsppg); - return; - } - else if (keysym == XK_Next) - { - scr_page (DN, lnsppg); - return; - } - } -#ifdef SCROLL_ON_UPDOWN_KEYS - if (IS_SCROLL_MOD) - { - if (keysym == XK_Up) - { - scr_page (UP, 1); - return; - } - else if (keysym == XK_Down) - { - scr_page (DN, 1); - return; - } - } -#endif -#ifdef SCROLL_ON_HOMEEND_KEYS - if (IS_SCROLL_MOD) - { - if (keysym == XK_Home) - { - scr_move_to (0, 1); - return; - } - else if (keysym == XK_End) - { - scr_move_to (1, 1); - return; - } - } -#endif - } - - if (shft) - { - /* Shift + F1 - F10 generates F11 - F20 */ - if (keysym >= XK_F1 && keysym <= XK_F10) - { - keysym += (XK_F11 - XK_F1); - shft = 0; /* turn off Shift */ - } - else if (!ctrl && !meta && (priv_modes & PrivMode_ShiftKeys)) - { - switch (keysym) - { - /* normal XTerm key bindings */ - case XK_Insert: /* Shift+Insert = paste mouse selection */ - selection_request (ev.time); - return; -#if TODO - /* rxvt extras */ - case XK_KP_Add: /* Shift+KP_Add = bigger font */ - change_font (FONT_UP); - return; - case XK_KP_Subtract: /* Shift+KP_Subtract = smaller font */ - change_font (FONT_DN); - return; -#endif - } - } - } - -#if ENABLE_FRILLS || ISO_14755 - // ISO 14755 support - if (iso14755buf & (ISO_14755_STARTED | ISO_14755_51)) - { - int hv; - - if (iso14755buf & ISO_14755_51 - && (keysym == XK_space || keysym == XK_KP_Space - || keysym == XK_Return || keysym == XK_KP_Enter)) - { - commit_iso14755 (); - iso14755buf = ISO_14755_51; -# if ISO_14755 - iso14755_51 (0); -# endif - return; - } - else if (keysym == XK_BackSpace) - { - iso14755buf = ((iso14755buf & ISO_14755_MASK) >> 4) | ISO_14755_51; -# if ISO_14755 - iso14755_51 (iso14755buf & ISO_14755_MASK); -# endif - return; - } - else if ((hv = hex_keyval (ev)) >= 0) - { - iso14755buf = ((iso14755buf << 4) & ISO_14755_MASK) - | hv | ISO_14755_51; -# if ISO_14755 - iso14755_51 (iso14755buf & ISO_14755_MASK); -# endif - return; - } - else - { -# if ISO_14755 - scr_overlay_off (); -# endif - iso14755buf = 0; - } - } - else if (option (Opt_iso14755) && - ((ctrl && (keysym == XK_Shift_L || keysym == XK_Shift_R)) - || (shft && (keysym == XK_Control_L || keysym == XK_Control_R)))) - if (!(iso14755buf & ISO_14755_STARTED)) - { - iso14755buf |= ISO_14755_STARTED; -# if ISO_14755 - scr_overlay_new (0, -1, sizeof ("ISO 14755 mode") - 1, 1); - scr_overlay_set (0, 0, "ISO 14755 mode"); -# endif - } -#endif + KeySym orig_keysym = keysym; -#ifdef PRINTPIPE - if (keysym == XK_Print) + /* Shift + F1 - F10 generates F11 - F20 */ + if (shft && keysym >= XK_F1 && keysym <= XK_F10) { - scr_printscreen (ctrl | shft); - return; + keysym += (XK_F11 - XK_F1); + shft = 0; /* turn off Shift */ } -#endif if (keysym >= 0xFF00 && keysym <= 0xFFFF) { @@ -783,13 +634,28 @@ if (newlen) len = strlen (kbuf); - /* - * Pass meta for all function keys, if 'meta' option set - */ + if (len > 0) + { + /* + * pass Shift/Control indicators for function keys ending with `~' + * + * eg, + * Prior = "ESC[5~" + * Shift+Prior = "ESC[5$" + * Ctrl+Prior = "ESC[5^" + * Ctrl+Shift+Prior = "ESC[5@" + */ + if (kbuf[0] == C0_ESC && kbuf[1] == '[' && kbuf[len - 1] == '~') + kbuf[len - 1] = (shft ? (ctrl ? '@' : '$') : (ctrl ? '^' : '~')); + + /* + * Pass meta for all function keys, if 'meta' option set + */ #ifdef META8_OPTION - if (meta && (meta_char == 0x80) && len > 0) - kbuf[len - 1] |= 0x80; + if (meta && (meta_char == 0x80)) + kbuf[len - 1] |= 0x80; #endif + } } else if (ctrl && keysym == XK_minus) @@ -812,56 +678,202 @@ for (ch = kbuf; ch < kbuf + len; ch++) *ch |= 0x80; - - meta = 0; } #endif /* nil */ ; } + + keysym = orig_keysym; + } + + /* escape prefix */ + if (len && meta +#ifdef META8_OPTION + && meta_char == C0_ESC +#endif + ) + { + *--kbuf = C0_ESC; + len++; } if (HOOK_INVOKE ((this, HOOK_KEY_PRESS, DT_XEVENT, &ev, DT_INT, keysym, DT_STR_LEN, kbuf, len, DT_END))) return; - if (len <= 0) - return; /* not mapped */ + if (keysym != NoSymbol) + { +#ifdef KEYSYM_RESOURCE + if (keyboard->dispatch (this, keysym, ev.state, kbuf, len)) + return; +#endif - if (option (Opt_scrollTtyKeypress)) - if (view_start) - { - view_start = 0; - want_refresh = 1; - } + if (saveLines) + { +#ifdef UNSHIFTED_SCROLLKEYS + if (!ctrl && !meta) +#else + if (IS_SCROLL_MOD) +#endif + { + int lnsppg; - /* - * these modifications only affect the static keybuffer - * pass Shift/Control indicators for function keys ending with `~' - * - * eg, - * Prior = "ESC[5~" - * Shift+Prior = "ESC[5$" - * Ctrl+Prior = "ESC[5^" - * Ctrl+Shift+Prior = "ESC[5@" - * Meta adds an Escape prefix (with META8_OPTION, if meta == ). - */ - if (kbuf[0] == C0_ESC && kbuf[1] == '[' && kbuf[len - 1] == '~') - kbuf[len - 1] = (shft ? (ctrl ? '@' : '$') : (ctrl ? '^' : '~')); +#ifdef PAGING_CONTEXT_LINES + lnsppg = nrow - PAGING_CONTEXT_LINES; +#else + lnsppg = nrow * 4 / 5; +#endif + max_it (lnsppg, 1); - /* escape prefix */ - if (meta -#ifdef META8_OPTION - && meta_char == C0_ESC + if (keysym == XK_Prior) + { + scr_page (lnsppg); + return; + } + else if (keysym == XK_Next) + { + scr_page (-lnsppg); + return; + } + } +#ifdef SCROLL_ON_UPDOWN_KEYS + if (IS_SCROLL_MOD) + { + if (keysym == XK_Up) + { + scr_page (1); + return; + } + else if (keysym == XK_Down) + { + scr_page (-1); + return; + } + } +#endif +#ifdef SCROLL_ON_HOMEEND_KEYS + if (IS_SCROLL_MOD) + { + if (keysym == XK_Home) + { + scr_changeview (top_row); + return; + } + else if (keysym == XK_End) + { + scr_changeview (0); + return; + } + } +#endif + } + + if (shft) + { + if (!ctrl && !meta && (priv_modes & PrivMode_ShiftKeys)) + { + switch (keysym) + { + /* normal XTerm key bindings */ + case XK_Insert: /* Shift+Insert = paste mouse selection */ + selection_request (ev.time); + return; +#if TODO + /* rxvt extras */ + case XK_KP_Add: /* Shift+KP_Add = bigger font */ + return; + case XK_KP_Subtract: /* Shift+KP_Subtract = smaller font */ + return; +#endif + } + } + } + + if (ctrl && meta && (keysym == XK_c || keysym == XK_v)) + { + if (keysym == XK_v) + selection_request (ev.time, Sel_Clipboard); + else if (selection.len > 0) + { + free (selection.clip_text); + selection.clip_text = rxvt_wcsdup (selection.text, selection.len); + selection.clip_len = selection.len; + selection_grab (CurrentTime, true); + } + + return; + } + +#if ENABLE_FRILLS || ISO_14755 + // ISO 14755 support + if (iso14755buf & (ISO_14755_STARTED | ISO_14755_51)) + { + int hv; + + if (iso14755buf & ISO_14755_51 + && (keysym == XK_space || keysym == XK_KP_Space + || keysym == XK_Return || keysym == XK_KP_Enter)) + { + commit_iso14755 (); + iso14755buf = ISO_14755_51; +# if ISO_14755 + iso14755_51 (0); +# endif + return; + } + else if (keysym == XK_BackSpace) + { + iso14755buf = ((iso14755buf & ISO_14755_MASK) >> 4) | ISO_14755_51; +# if ISO_14755 + iso14755_51 (iso14755buf & ISO_14755_MASK); +# endif + return; + } + else if ((hv = hex_keyval (ev)) >= 0) + { + iso14755buf = ((iso14755buf << 4) & ISO_14755_MASK) + | hv | ISO_14755_51; +# if ISO_14755 + iso14755_51 (iso14755buf & ISO_14755_MASK); +# endif + return; + } + else + { +# if ISO_14755 + scr_overlay_off (); +# endif + iso14755buf = 0; + } + } + else if (option (Opt_iso14755) && + ((ctrl && (keysym == XK_Shift_L || keysym == XK_Shift_R)) + || (shft && (keysym == XK_Control_L || keysym == XK_Control_R)))) + if (!(iso14755buf & ISO_14755_STARTED)) + { + iso14755buf |= ISO_14755_STARTED; +# if ISO_14755 + scr_overlay_new (0, -1, sizeof ("ISO 14755 mode") - 1, 1); + scr_overlay_set (0, 0, "ISO 14755 mode"); +# endif + } +#endif + +#ifdef PRINTPIPE + if (keysym == XK_Print) + { + scr_printscreen (ctrl | shft); + return; + } #endif - ) - { - const char ch = C0_ESC; - tt_write (&ch, 1); } - tt_write (kbuf, (unsigned int)len); + if (len <= 0) + return; /* not mapped */ + + tt_write_user_input (kbuf, (unsigned int)len); } -void +void ecb_cold rxvt_term::key_release (XKeyEvent &ev) { #if (MOUSE_WHEEL && MOUSE_SLIP_WHEELING) || ISO_14755 || ENABLE_PERL @@ -943,7 +955,7 @@ { flush_ev.stop (); -#ifdef HAVE_BG_PIXMAP +#ifdef HAVE_IMG if (bg_flags & BG_NEEDS_REFRESH) { bg_flags &= ~BG_NEEDS_REFRESH; @@ -993,8 +1005,8 @@ scr_refresh (); scrollBar.show (1); -#ifdef USE_XIM - IMSendSpot (); +#if USE_XIM + im_send_spot (); #endif } @@ -1022,6 +1034,24 @@ #ifdef CURSOR_BLINK void +rxvt_term::cursor_blink_reset () +{ + if (!focus) + return; + + if (hidden_cursor) + { + hidden_cursor = 0; + want_refresh = 1; + } + + if (option (Opt_cursorBlink) || (priv_modes & PrivMode_BlinkingCursor)) + cursor_blink_ev.again (); + else + cursor_blink_ev.stop (); +} + +void rxvt_term::cursor_blink_cb (ev::timer &w, int revents) { hidden_cursor = !hidden_cursor; @@ -1049,8 +1079,8 @@ void rxvt_term::cont_scroll_cb (ev::timer &w, int revents) { - if ((scrollBar.state == STATE_UP || scrollBar.state == STATE_DOWN) - && scr_page (scrollBar.state == STATE_UP ? UP : DN, 1)) + if ((scrollBar.state == SB_STATE_UP || scrollBar.state == SB_STATE_DOWN) + && scr_page (scrollBar.state == SB_STATE_UP ? UP : DN, 1)) { want_refresh = 1; refresh_check (); @@ -1064,7 +1094,7 @@ void rxvt_term::sel_scroll_cb (ev::timer &w, int revents) { - if (scr_page (scroll_selection_dir, scroll_selection_lines)) + if (scr_page (scroll_selection_lines)) { selection_extend (selection_save_x, selection_save_y, selection_save_state); want_refresh = 1; @@ -1079,7 +1109,7 @@ void rxvt_term::slip_wheel_cb (ev::timer &w, int revents) { - if (scr_changeview (view_start - mouse_slip_wheel_speed)) + if (scr_page (mouse_slip_wheel_speed)) { want_refresh = 1; refresh_check (); @@ -1210,11 +1240,11 @@ refresh_check (); } -void +void ecb_cold rxvt_term::pointer_unblank () { XDefineCursor (dpy, vt, TermWin_cursor); - recolour_cursor (); + recolor_cursor (); #ifdef POINTER_BLANK hidden_pointer = 0; @@ -1225,7 +1255,7 @@ } #ifdef POINTER_BLANK -void +void ecb_cold rxvt_term::pointer_blank () { if (!option (Opt_pointerBlank)) @@ -1237,7 +1267,7 @@ hidden_pointer = 1; } -void +void ecb_cold rxvt_term::pointer_cb (ev::timer &w, int revents) { make_current (); @@ -1339,7 +1369,7 @@ } /*{{{ process an X event */ -void +void ecb_hot rxvt_term::x_cb (XEvent &ev) { make_current (); @@ -1452,11 +1482,12 @@ while (XCheckTypedWindowEvent (dpy, ev.xconfigure.window, ConfigureNotify, &ev)) ; -#ifdef HAVE_BG_PIXMAP - bool moved = false; - if (bg_window_position_sensitive ()) + bool want_position_change = SHOULD_INVOKE (HOOK_POSITION_CHANGE); + + if (want_position_change) { int x, y; + if (ev.xconfigure.send_event) { x = ev.xconfigure.x; @@ -1465,29 +1496,19 @@ else get_window_origin (x, y); - if (bg_set_position (x, y) - || !(bg_flags & BG_IS_VALID)) - moved = true; + if (x != parent_x || y != parent_y) + { + parent_x = x; + parent_y = y; + HOOK_INVOKE ((this, HOOK_POSITION_CHANGE, DT_INT, x, DT_INT, y, DT_END)); + } } -#endif if (szHint.width != ev.xconfigure.width || szHint.height != ev.xconfigure.height) { seen_resize = 1; resize_all_windows (ev.xconfigure.width, ev.xconfigure.height, 1); } - else - { -#ifdef HAVE_BG_PIXMAP - if (moved) - { - if (mapped) - update_background (); - else - bg_invalidate (); - } -#endif - } HOOK_INVOKE ((this, HOOK_CONFIGURE_NOTIFY, DT_XEVENT, &ev, DT_END)); } @@ -1506,22 +1527,6 @@ break; case MapNotify: -#ifdef HAVE_BG_PIXMAP - /* This is needed specifically to fix the case of no window manager or a - * non-reparenting window manager. In those cases we never get first - * ConfigureNotify. Also that speeds startup under normal WM, by taking - * care of multiplicity of ConfigureNotify events arriving while WM does - * reparenting. - * We should not render background immediately, as there could be several - * ConfigureNotify's to follow. Lets take care of all of them in one scoop - * by scheduling background redraw as soon as we can, but giving a short - * bit of time for ConfigureNotifies to arrive. - * We should render background PRIOR to drawing any text, but AFTER all - * of ConfigureNotifys for the best results. - */ - if (!(bg_flags & BG_IS_VALID)) - update_background_ev.start (0.025); -#endif mapped = 1; #ifdef TEXT_BLINK text_blink_ev.start (); @@ -1569,7 +1574,7 @@ if (scrollBar.state && ev.xany.window == scrollBar.win) { - scrollBar.state = STATE_IDLE; + scrollBar.state = SB_STATE_IDLE; scrollBar.show (0); } } @@ -1580,8 +1585,9 @@ if (hidden_pointer) pointer_unblank (); #endif - if ((priv_modes & PrivMode_MouseBtnEvent && ev.xbutton.state & (Button1Mask|Button2Mask|Button3Mask)) - || priv_modes & PrivMode_MouseAnyEvent) + if (!bypass_keystate + && ((priv_modes & PrivMode_MouseBtnEvent && ev.xbutton.state & (Button1Mask|Button2Mask|Button3Mask)) + || priv_modes & PrivMode_MouseAnyEvent)) mouse_report (ev.xbutton); if ((priv_modes & PrivMode_mouse_report) && !bypass_keystate) break; @@ -1603,9 +1609,9 @@ &ev.xbutton.state); #ifdef MOUSE_THRESHOLD /* deal with a `jumpy' mouse */ - if ((ev.xmotion.time - MEvent.time) > MOUSE_THRESHOLD) - { + if (ev.xmotion.time - MEvent.time > MOUSE_THRESHOLD) #endif + { #if ISO_14755 // 5.4 if (iso14755buf & (ISO_14755_STARTED | ISO_14755_54)) @@ -1621,6 +1627,7 @@ if (ev.xbutton.y < int_bwidth || Pixel2Row (ev.xbutton.y) > (nrow-1)) { + page_dirn scroll_selection_dir; int dist; /* don't clobber the current delay if we are @@ -1645,7 +1652,7 @@ else { scroll_selection_dir = DN; - dist = ev.xbutton.y - (int_bwidth + height); + dist = ev.xbutton.y - (int_bwidth + vt_height); } scroll_selection_lines = Pixel2Height (dist) @@ -1653,6 +1660,7 @@ + 1; min_it (scroll_selection_lines, SELECTION_SCROLL_MAX_LINES); + scroll_selection_lines *= scroll_selection_dir; } else { @@ -1662,12 +1670,10 @@ sel_scroll_ev.stop(); } #endif -#ifdef MOUSE_THRESHOLD } -#endif } } - else if (scrollBar.state == STATE_MOTION && ev.xany.window == scrollBar.win) + else if (scrollBar.state == SB_STATE_MOTION && ev.xany.window == scrollBar.win) { while (XCheckTypedWindowEvent (dpy, scrollBar.win, MotionNotify, &ev)) @@ -1678,7 +1684,7 @@ &unused_root_x, &unused_root_y, &ev.xbutton.x, &ev.xbutton.y, &unused_mask); - scr_move_to (scrollbar_position (ev.xbutton.y) - csrO, + scr_move_to (scrollBar.position (ev.xbutton.y) - csrO, scrollBar.size ()); want_refresh = 1; scrollBar.show (1); @@ -1687,16 +1693,8 @@ } #if defined(CURSOR_BLINK) - if (option (Opt_cursorBlink) && ev.type == KeyPress) - { - if (hidden_cursor) - { - hidden_cursor = 0; - want_refresh = 1; - } - - cursor_blink_ev.again (); - } + if (ev.type == KeyPress) + cursor_blink_reset (); #endif #if defined(POINTER_BLANK) @@ -1717,7 +1715,7 @@ } #if ENABLE_FRILLS -void +void ecb_cold rxvt_term::set_urgency (bool enable) { if (enable == urgency_hint) @@ -1728,11 +1726,12 @@ h->flags = h->flags & ~XUrgencyHint | (enable ? XUrgencyHint : 0); XSetWMHints (dpy, parent, h); urgency_hint = enable; + XFree (h); } } #endif -void +void ecb_cold rxvt_term::focus_in () { if (!focus) @@ -1743,7 +1742,7 @@ #if USE_XIM if (Input_Context != NULL) { - IMSetPosition (); + im_set_position (); XSetICFocus (Input_Context); } #endif @@ -1755,19 +1754,22 @@ if (rs[Rs_fade]) { pix_colors = pix_colors_focused; - scr_recolour (); + scr_recolor (); } #endif #if ENABLE_FRILLS if (option (Opt_urgentOnBell)) set_urgency (0); + + if (priv_modes & PrivMode_FocusEvent) + tt_printf ("\x1b[I"); #endif HOOK_INVOKE ((this, HOOK_FOCUS_IN, DT_END)); } } -void +void ecb_cold rxvt_term::focus_out () { if (focus) @@ -1778,6 +1780,9 @@ #if ENABLE_FRILLS if (option (Opt_urgentOnBell)) set_urgency (0); + + if (priv_modes & PrivMode_FocusEvent) + tt_printf ("\x1b[O"); #endif #if ENABLE_FRILLS || ISO_14755 if (iso14755buf) @@ -1802,7 +1807,7 @@ if (rs[Rs_fade]) { pix_colors = pix_colors_unfocused; - scr_recolour (); + scr_recolor (); } #endif @@ -1810,12 +1815,15 @@ } } -void -rxvt_term::update_fade_color (unsigned int idx) +void ecb_cold +rxvt_term::update_fade_color (unsigned int idx, bool first_time) { #if OFF_FOCUS_FADING if (rs[Rs_fade]) { + if (!first_time) + pix_colors_focused [idx].free (this); + rgba c; pix_colors [Color_fade].get (c); pix_colors_focused [idx].fade (this, atoi (rs[Rs_fade]), pix_colors_unfocused [idx], c); @@ -1823,8 +1831,8 @@ #endif } -#if ENABLE_TRANSPARENCY || ENABLE_PERL -void +#if ENABLE_PERL +void ecb_hot rxvt_term::rootwin_cb (XEvent &ev) { make_current (); @@ -1833,7 +1841,6 @@ && HOOK_INVOKE ((this, HOOK_ROOT_EVENT, DT_XEVENT, &ev, DT_END))) return; -# if ENABLE_TRANSPARENCY switch (ev.type) { case PropertyNotify: @@ -1844,13 +1851,11 @@ if (ev.xproperty.atom == xa[XA_XROOTPMAP_ID] || ev.xproperty.atom == xa[XA_ESETROOT_PMAP_ID]) { - bg_set_root_pixmap (); - update_background (); + HOOK_INVOKE ((this, HOOK_ROOTPMAP_CHANGE, DT_END)); } break; } -# endif refresh_check (); } @@ -1883,7 +1888,7 @@ } #endif - clickintime = ev.time - MEvent.time < MULTICLICK_TIME; + clickintime = ev.time - MEvent.time < multiClickTime; if (reportmode) { @@ -1984,7 +1989,7 @@ else if (scrollBar.dnButton (ev.y)) direction = DN; /* down */ - scrollBar.state = STATE_IDLE; + scrollBar.state = SB_STATE_IDLE; /* * Rxvt-style scrollbar: * move up if mouse is above slider @@ -2033,9 +2038,9 @@ if (scr_page (direction, 1)) { if (direction == UP) - scrollBar.state = STATE_UP; + scrollBar.state = SB_STATE_UP; else - scrollBar.state = STATE_DOWN; + scrollBar.state = SB_STATE_DOWN; } } else @@ -2044,53 +2049,53 @@ case Button2: switch (scrollBar.align) { - case R_SB_ALIGN_TOP: + case SB_ALIGN_TOP: csrO = 0; break; - case R_SB_ALIGN_CENTRE: + case SB_ALIGN_CENTRE: csrO = (scrollBar.bot - scrollBar.top) / 2; break; - case R_SB_ALIGN_BOTTOM: + case SB_ALIGN_BOTTOM: csrO = scrollBar.bot - scrollBar.top; break; } - if (scrollBar.style == R_SB_XTERM - || scrollbar_above_slider (ev.y) - || scrollbar_below_slider (ev.y)) - scr_move_to (scrollbar_position (ev.y) - csrO, scrollBar.size ()); + if (scrollBar.style == SB_STYLE_XTERM + || scrollBar.above_slider (ev.y) + || scrollBar.below_slider (ev.y)) + scr_move_to (scrollBar.position (ev.y) - csrO, scrollBar.size ()); - scrollBar.state = STATE_MOTION; + scrollBar.state = SB_STATE_MOTION; break; case Button1: - if (scrollBar.align == R_SB_ALIGN_CENTRE) + if (scrollBar.align == SB_ALIGN_CENTRE) csrO = ev.y - scrollBar.top; /* FALLTHROUGH */ case Button3: - if (scrollBar.style != R_SB_XTERM) + if (scrollBar.style != SB_STYLE_XTERM) { - if (scrollbar_above_slider (ev.y)) + if (scrollBar.above_slider (ev.y)) # ifdef RXVT_SCROLL_FULL scr_page (UP, nrow - 1); # else scr_page (UP, nrow / 4); # endif - else if (scrollbar_below_slider (ev.y)) + else if (scrollBar.below_slider (ev.y)) # ifdef RXVT_SCROLL_FULL scr_page (DN, nrow - 1); # else scr_page (DN, nrow / 4); # endif else - scrollBar.state = STATE_MOTION; + scrollBar.state = SB_STATE_MOTION; } else { scr_page ((ev.button == Button1 ? DN : UP), (nrow - * scrollbar_position (ev.y) + * scrollBar.position (ev.y) / scrollBar.size ())); } @@ -2111,9 +2116,9 @@ if (!bypass_keystate) reportmode = !! (priv_modes & PrivMode_mouse_report); - if (scrollBar.state == STATE_UP || scrollBar.state == STATE_DOWN) + if (scrollBar.state == SB_STATE_UP || scrollBar.state == SB_STATE_DOWN) { - scrollBar.state = STATE_IDLE; + scrollBar.state = SB_STATE_IDLE; scrollBar.show (0); } @@ -2143,7 +2148,7 @@ if (MEvent.button != AnyButton && (ev.button != MEvent.button || (ev.time - MEvent.time - > MULTICLICK_TIME / 2))) + > multiClickTime / 2))) { MEvent.clicks = 0; MEvent.button = AnyButton; @@ -2173,7 +2178,7 @@ break; case Button2: - if (IN_RANGE_EXC (ev.x, 0, width) && IN_RANGE_EXC (ev.y, 0, height)) // inside window? + if (IN_RANGE_EXC (ev.x, 0, vt_width) && IN_RANGE_EXC (ev.y, 0, vt_height)) // inside window? selection_request (ev.time, ev.state & ModMetaMask ? Sel_Clipboard : Sel_Primary); break; @@ -2181,24 +2186,23 @@ case Button4: case Button5: { - int i; - page_dirn v; + int lines; + page_dirn dirn; - v = ev.button == Button4 ? UP : DN; + dirn = ev.button == Button4 ? UP : DN; if (ev.state & ShiftMask) - i = 1; + lines = 1; else if (option (Opt_mouseWheelScrollPage)) - i = nrow - 1; + lines = nrow - 1; else - i = 5; + lines = 5; # ifdef MOUSE_SLIP_WHEELING if (ev.state & ControlMask) { - mouse_slip_wheel_speed += v ? -1 : 1; - if (mouse_slip_wheel_speed < -nrow) mouse_slip_wheel_speed = -nrow; - if (mouse_slip_wheel_speed > +nrow) mouse_slip_wheel_speed = +nrow; + mouse_slip_wheel_speed += dirn; + clamp_it (mouse_slip_wheel_speed, -nrow, nrow); if (!slip_wheel_ev.is_active ()) slip_wheel_ev.start (SCROLLBAR_CONTINUOUS_DELAY, SCROLLBAR_CONTINUOUS_DELAY); @@ -2206,7 +2210,7 @@ else # endif { - scr_page (v, i); + scr_page (dirn, lines); scrollBar.show (1); } } @@ -2218,7 +2222,7 @@ /*}}} */ -void +void ecb_hot rxvt_term::cmd_parse () { wchar_t ch = NOCHAR; @@ -2226,7 +2230,7 @@ for (;;) { - if (expect_false (ch == NOCHAR)) + if (ecb_unlikely (ch == NOCHAR)) { seq_begin = cmdbuf_ptr; ch = next_char (); @@ -2235,9 +2239,9 @@ break; } - if (expect_true (!IS_CONTROL (ch) || ch == C0_LF || ch == C0_CR || ch == C0_HT)) + if (ecb_likely (!IS_CONTROL (ch) || ch == C0_LF || ch == C0_CR || ch == C0_HT)) { - if (expect_false (!seen_input)) + if (ecb_unlikely (!seen_input)) { seen_input = 1; // many badly-written programs (e.g. jed) contain a race condition: @@ -2260,12 +2264,12 @@ for (;;) { - if (expect_false (ch == NOCHAR || (IS_CONTROL (ch) && ch != C0_LF && ch != C0_CR && ch != C0_HT))) + if (ecb_unlikely (ch == NOCHAR || (IS_CONTROL (ch) && ch != C0_LF && ch != C0_CR && ch != C0_HT))) break; *str++ = ch; - if (expect_false (ch == C0_LF || str >= eol)) + if (ecb_unlikely (ch == C0_LF || str >= eol)) { if (ch == C0_LF) nlines++; @@ -2347,13 +2351,13 @@ } // read the next character -wchar_t +wchar_t ecb_hot rxvt_term::next_char () NOTHROW { while (cmdbuf_ptr < cmdbuf_endp) { // assume 7-bit to be ascii ALWAYS - if (expect_true ((unsigned char)*cmdbuf_ptr <= 0x7f && *cmdbuf_ptr != 0x1b)) + if (ecb_likely ((unsigned char)*cmdbuf_ptr <= 0x7f && *cmdbuf_ptr != 0x1b)) return *cmdbuf_ptr++; wchar_t wc; @@ -2369,6 +2373,8 @@ if (len == (size_t)-1) { mbstate.reset (); // reset now undefined conversion state + // a -1 might indicate that a previous incomplete char is invalid (previous return -2) + // in which case we "erroneously" return the next byte which might be valid. return (unsigned char)*cmdbuf_ptr++; // the _occasional_ latin1 character is allowed to slip through } @@ -2381,7 +2387,7 @@ } // read the next octet -uint32_t +uint32_t ecb_hot rxvt_term::next_octet () NOTHROW { return cmdbuf_ptr < cmdbuf_endp @@ -2391,12 +2397,7 @@ static class out_of_input out_of_input; -/* rxvt_cmd_getc () - Return next input character */ -/* - * Return the next input character after first passing any keyboard input - * to the command. - */ -wchar_t +wchar_t ecb_hot rxvt_term::cmd_getc () THROW ((class out_of_input)) { wchar_t c = next_char (); @@ -2407,7 +2408,7 @@ return c; } -uint32_t +uint32_t ecb_hot rxvt_term::cmd_get8 () THROW ((class out_of_input)) { uint32_t c = next_octet (); @@ -2421,7 +2422,7 @@ /*{{{ print pipe */ /*----------------------------------------------------------------------*/ #ifdef PRINTPIPE -FILE * +FILE * ecb_cold rxvt_term::popen_printer () { FILE *stream = popen (rs[Rs_print_pipe] ? rs[Rs_print_pipe] : PRINTPIPE, "w"); @@ -2432,7 +2433,7 @@ return stream; } -int +int ecb_cold rxvt_term::pclose_printer (FILE *stream) { fflush (stream); @@ -2442,7 +2443,7 @@ /* * simulate attached vt100 printer */ -void +void ecb_cold rxvt_term::process_print_pipe () { FILE *fd = popen_printer (); @@ -2498,7 +2499,6 @@ #endif /* PRINTPIPE */ /*}}} */ -/* *INDENT-OFF* */ enum { C1_40 = 0x40, C1_41 , C1_BPH, C1_NBH, C1_44 , C1_NEL, C1_SSA, C1_ESA, @@ -2506,10 +2506,9 @@ C1_DCS, C1_PU1, C1_PU2, C1_STS, C1_CCH, C1_MW , C1_SPA, C1_EPA, C1_SOS, C1_59 , C1_SCI, C1_CSI, CS_ST , C1_OSC, C1_PM , C1_APC, }; -/* *INDENT-ON* */ /*{{{ process non-printing single characters */ -void +void ecb_hot rxvt_term::process_nonprinting (unicode_t ch) { switch (ch) @@ -2549,13 +2548,13 @@ #ifdef EIGHT_BIT_CONTROLS // 8-bit controls - case 0x90: /* DCS */ + case 0x90: /* DCS */ process_dcs_seq (); break; - case 0x9b: /* CSI */ + case 0x9b: /* CSI */ process_csi_seq (); break; - case 0x9d: /* OSC */ + case 0x9d: /* OSC */ process_osc_seq (); break; #endif @@ -2565,7 +2564,7 @@ /*{{{ process VT52 escape sequences */ -void +void ecb_cold rxvt_term::process_escape_vt52 (unicode_t ch) { int row, col; @@ -2609,7 +2608,7 @@ tt_printf ("\033/Z"); /* I am a VT100 emulating a VT52 */ break; case '<': /* turn off VT52 mode */ - set_privmode (PrivMode_vt52, 0); + priv_modes &= ~PrivMode_vt52; break; case 'F': /* use special graphics character set */ case 'G': /* use regular character set */ @@ -2625,7 +2624,7 @@ /*{{{ process escape sequences */ -void +void ecb_hot rxvt_term::process_escape_seq () { unicode_t ch = cmd_getc (); @@ -2638,7 +2637,6 @@ switch (ch) { - /* case 1: do_tek_mode (); break; */ case '#': if (cmd_getc () == '8') scr_E (); @@ -2671,9 +2669,12 @@ scr_forwardindex (); break; #endif + // DECPAM/DECPNM case '=': + priv_modes |= PrivMode_aplKP; + break; case '>': - set_privmode (PrivMode_aplKP, ch == '='); + priv_modes &= ~PrivMode_aplKP; break; case C1_40: @@ -2687,7 +2688,7 @@ case C1_NEL: /* ESC E */ { wchar_t nlcr[] = { C0_LF, C0_CR }; - scr_add_lines (nlcr, ARRAY_LENGTH(nlcr), 1); + scr_add_lines (nlcr, ecb_array_length (nlcr), 1); } break; @@ -2709,10 +2710,10 @@ break; /* 8.3.142: SINGLE-SHIFT TWO */ - /*case C1_SS2: scr_single_shift (2); break; */ + /* case C1_SS2: break; */ /* 8.3.143: SINGLE-SHIFT THREE */ - /*case C1_SS3: scr_single_shift (3); break; */ + /* case C1_SS3: break; */ /* 8.3.27: DEVICE CONTROL STRING */ case C1_DCS: /* ESC P */ @@ -2755,7 +2756,6 @@ /*}}} */ /*{{{ process CONTROL SEQUENCE INTRODUCER (CSI) sequences `ESC[' */ -/* *INDENT-OFF* */ enum { CSI_ICH = 0x40, CSI_CUU, CSI_CUD, CSI_CUF, CSI_CUB, CSI_CNL, CSI_CPL, CSI_CHA, @@ -2785,12 +2785,11 @@ make_byte (0,0,0,0,0,0,0,0), /* p, q, r, s, t, u, v, w, */ make_byte (0,0,0,0,0,0,0,0), /* x, y, z, {, |, }, ~, */ }; -/* *INDENT-ON* */ -void +void ecb_hot rxvt_term::process_csi_seq () { - unicode_t ch, priv, i; + unicode_t ch, priv, prev_ch, i; unsigned int nargs, p; int n, ndef; int arg[ESC_ARGS] = { }; @@ -2806,6 +2805,7 @@ ch = cmd_getc (); } + prev_ch = 0; /* read any numerical arguments */ for (n = -1; ch < CSI_ICH; ) { @@ -2825,6 +2825,7 @@ else if (IS_CONTROL (ch)) process_nonprinting (ch); + prev_ch = ch; ch = cmd_getc (); } @@ -2875,8 +2876,8 @@ static const int pm_h[] = { 7, 25 }; static const int pm_l[] = { 1, 3, 4, 5, 6, 9, 66, 1000, 1001, 1005, 1015, 1049 }; - process_terminal_mode ('h', 0, ARRAY_LENGTH(pm_h), pm_h); - process_terminal_mode ('l', 0, ARRAY_LENGTH(pm_l), pm_l); + process_terminal_mode ('h', 0, ecb_array_length (pm_h), pm_h); + process_terminal_mode ('l', 0, ecb_array_length (pm_l), pm_l); } break; } @@ -2904,11 +2905,11 @@ #endif case CSI_CUU: /* 8.3.22: (1) CURSOR UP */ - case CSI_VPR: /* 8.3.161: (1) LINE POSITION FORWARD */ + case CSI_VPB: /* 8.3.160: (1) LINE POSITION BACKWARD */ arg[0] = -arg[0]; /* FALLTHROUGH */ case CSI_CUD: /* 8.3.19: (1) CURSOR DOWN */ - case CSI_VPB: /* 8.3.160: (1) LINE POSITION BACKWARD */ + case CSI_VPR: /* 8.3.161: (1) LINE POSITION FORWARD */ scr_gotorc (arg[0], 0, RELATIVE); break; @@ -3068,6 +3069,11 @@ priv_modes |= PrivMode_LFNL; break; + case CSI_71: // DECSCUSR: set cursor style + if (prev_ch == ' ') + set_cursor_style (arg[0]); + break; + /* * PRIVATE USE beyond this point. All CSI_7? sequences here */ @@ -3105,7 +3111,6 @@ /*}}} */ #if !ENABLE_MINIMAL -/* ARGSUSED */ void rxvt_term::process_window_ops (const int *args, unsigned int nargs) { @@ -3152,7 +3157,7 @@ //case 9: NYI, TODO, restore maximized window or maximize window default: if (args[0] >= 24) /* set height (chars) */ - set_widthheight ((unsigned int)width, + set_widthheight ((unsigned int)vt_width, (unsigned int) (args[1] * fheight)); break; @@ -3211,7 +3216,7 @@ unicode_t ch; bool seen_esc = false; unsigned int n = 0; - wchar_t string[STRING_MAX]; + wchar_t string[CBUFSIZ]; while ((ch = cmd_getc ()) != NOCHAR) { @@ -3236,7 +3241,7 @@ seen_esc = false; - if (n >= STRING_MAX - 1) + if (n >= sizeof (string) - 1) // stop at some sane length return NULL; @@ -3295,6 +3300,94 @@ } } +static unsigned int +colorcube_index (unsigned int idx_r, + unsigned int idx_g, + unsigned int idx_b) +{ + assert (idx_r < Red_levels); + assert (idx_g < Green_levels); + assert (idx_b < Blue_levels); + + return idx_r * Blue_levels * Green_levels + + idx_g * Blue_levels + + idx_b; +} + +/* + * Find the nearest color slot in the hidden color cube, + * adapt its value to the 32bit RGBA color. + */ +unsigned int +rxvt_term::map_rgb24_color (unsigned int r, unsigned int g, unsigned int b, unsigned int a) +{ + r &= 0xff; + g &= 0xff; + b &= 0xff; + a &= 0xff; + + 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 */ + /* 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, + }; + + 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]; + + 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 index = colorcube_index (r, g, b); + + if (rgb24_color[index] == color) + { + rgb24_seqno[index] = ++rgb24_sequence; + return index + minTermCOLOR24; + } + + // minor issue: could update index 0 few more times + if ((rgb24_seqno[index] | rgb24_color[index]) == 0) + { + idx = index; + goto update; + } + + // 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) + idx = index; + } + +update: + rgb24_color[idx] = color; + rgb24_seqno[idx] = ++rgb24_sequence; + + idx += minTermCOLOR24; + pix_colors_focused [idx].free (this); + pix_colors_focused [idx].set (this, rgba (r * 0x0101, g * 0x0101, b * 0x0101, a * 0x0101)); + update_fade_color (idx, false); + + return idx; +} + void rxvt_term::process_color_seq (int report, int color, const char *str, char resp) { @@ -3305,7 +3398,7 @@ #if XFT if (c.a != rgba::MAX_CC) - tt_printf ("\033]%d;rgba:%04x/%04x/%04x/%04x%c", report, c.a, c.r, c.g, c.b, resp); + tt_printf ("\033]%d;rgba:%04x/%04x/%04x/%04x%c", report, c.r, c.g, c.b, c.a, resp); else #endif tt_printf ("\033]%d;rgb:%04x/%04x/%04x%c", report, c.r, c.g, c.b, resp); @@ -3363,7 +3456,7 @@ && actual_format == 8) str = (const char *)(value); - tt_printf ("\033]%d;%s%c", op, str, resp); + tt_printf ("\033]%d;%s%c", op, option (Opt_insecure) ? str : "", resp); XFree (value); } @@ -3441,69 +3534,6 @@ case URxvt_Color_border: process_color_seq (op, Color_border, str, resp); break; -#if ENABLE_TRANSPARENCY - case URxvt_Color_tint: - process_color_seq (op, Color_tint, str, resp); - { - bool changed = false; - - if (ISSET_PIXCOLOR (Color_tint)) - changed = bg_set_tint (pix_colors_focused [Color_tint]); - - if (changed) - update_background (); - } - - break; -#endif - -#if BG_IMAGE_FROM_FILE - case Rxvt_Pixmap: - if (!strcmp (str, "?")) - { - char str[256]; - - sprintf (str, "[%dx%d+%d+%d]", - min (h_scale, 32767), min (v_scale, 32767), - min (h_align, 32767), min (v_align, 32767)); - process_xterm_seq (XTerm_title, str, CHAR_ST); - } - else - { - int changed = 0; - - if (*str != ';') - { - if (bg_set_file (str)) /* change pixmap */ - { - changed++; - str = strchr (str, ';'); - if (str == NULL) - bg_set_default_geometry (); - else - bg_set_geometry (str+1); - } - } - else - { - str++; - if (bg_set_geometry (str, true)) - changed++; - } - - if (changed) - { - if (bg_window_position_sensitive ()) - { - int x, y; - get_window_origin (x, y); - bg_set_position (x, y); - } - update_background (); - } - } - break; -#endif case XTerm_logfile: // TODO, when secure mode? @@ -3597,14 +3627,17 @@ * 't' = toggle * so no need for fancy checking */ -int +int ecb_cold rxvt_term::privcases (int mode, unsigned long bit) { int state; if (mode == 's') { - SavedModes |= (priv_modes & bit); + if (priv_modes & bit) + SavedModes |= bit; + else + SavedModes &= ~bit; return -1; } else @@ -3614,7 +3647,10 @@ else state = (mode == 't') ? ! (priv_modes & bit) : mode; - set_privmode (bit, state); + if (state) + priv_modes |= bit; + else + priv_modes &= ~bit; } return state; @@ -3622,7 +3658,7 @@ /* we're not using priv _yet_ */ void -rxvt_term::process_terminal_mode (int mode, int priv UNUSED, unsigned int nargs, const int *arg) +rxvt_term::process_terminal_mode (int mode, int priv ecb_unused, unsigned int nargs, const int *arg) { unsigned int i, j; int state; @@ -3633,7 +3669,7 @@ const unsigned long bit; } argtopriv[] = { { 1, PrivMode_aplCUR }, // DECCKM - { 2, PrivMode_vt52 }, + { 2, PrivMode_vt52 }, // DECANM { 3, PrivMode_132 }, // DECCOLM { 4, PrivMode_smoothScroll }, // DECSCLM { 5, PrivMode_rVideo }, // DECSCNM @@ -3641,9 +3677,10 @@ { 7, PrivMode_Autowrap }, // DECAWM // 8, auto-repeat keys // DECARM { 9, PrivMode_MouseX10 }, + { 12, PrivMode_BlinkingCursor }, // 18 end FF to printer after print screen // 19 Print screen prints full screen/scroll region - { 25, PrivMode_VisibleCursor }, // cnorm/cvvis/civis + { 25, PrivMode_VisibleCursor }, // DECTCEM cnorm/cvvis/civis #ifdef scrollBar_esc { scrollBar_esc, PrivMode_scrollBar }, #endif @@ -3654,7 +3691,7 @@ // 45 margin bell NYI // 46 start logging { 47, PrivMode_Screen }, - { 66, PrivMode_aplKP }, // DECPAM/DECPNM + { 66, PrivMode_aplKP }, // DECNKM #ifndef NO_BACKSPACE_KEY { 67, PrivMode_BackSpace }, // DECBKM #endif @@ -3662,6 +3699,7 @@ { 1002, PrivMode_MouseBtnEvent }, { 1003, PrivMode_MouseAnyEvent }, #if ENABLE_FRILLS + { 1004, PrivMode_FocusEvent }, { 1005, PrivMode_ExtModeMouse }, #endif { 1010, PrivMode_TtyOutputInh }, // rxvt extension @@ -3693,7 +3731,7 @@ state = -1; /* basic handling */ - for (j = 0; j < ARRAY_LENGTH(argtopriv); j++) + for (j = 0; j < ecb_array_length (argtopriv); j++) if (argtopriv[j].argval == arg[i]) { state = privcases (mode, argtopriv[j].bit); @@ -3729,7 +3767,7 @@ * parameter. Return from VT52 mode with an ESC < from * within VT52 mode */ - set_privmode (PrivMode_vt52, 1); + priv_modes |= PrivMode_vt52; break; case 3: /* 80/132 */ if (priv_modes & PrivMode_132OK) @@ -3754,11 +3792,14 @@ break; #ifdef scrollBar_esc case scrollBar_esc: - if (scrollBar.map (state)) - { - resize_all_windows (0, 0, 0); - scr_touch (true); - } + scrollBar.map (state); + resize_all_windows (0, 0, 0); + scr_touch (true); + break; +#endif +#ifdef CURSOR_BLINK + case 12: + cursor_blink_reset (); break; #endif case 25: /* visible/invisible cursor */ @@ -3823,7 +3864,7 @@ /*}}} */ /*{{{ process sgr sequences */ -void +void ecb_hot rxvt_term::process_sgr_mode (unsigned int nargs, const int *arg) { unsigned int i; @@ -3875,22 +3916,22 @@ case 21: // disable bold, faint, sometimes doubly underlined (iso 8613) rendset = 0, rendstyle = RS_Bold; break; - case 22: // normal intensity + case 22: // bold off (vt220) rendset = 0, rendstyle = RS_Bold; break; case 23: // disable italic rendset = 0, rendstyle = RS_Italic; break; - case 24: + case 24: // underline off (vt220) rendset = 0, rendstyle = RS_Uline; break; - case 25: + case 25: // blink off (vt220) rendset = 0, rendstyle = RS_Blink; break; case 26: // variable spacing (iso 8613) rendset = 0, rendstyle = RS_Blink; break; - case 27: + case 27: // reverse off (vt220) rendset = 0, rendstyle = RS_RVid; break; //case 28: // visible. NYI @@ -3915,13 +3956,6 @@ case 37: scr_color ((unsigned int) (minCOLOR + (arg[i] - 30)), Color_fg); break; - case 38: // set fg color, ISO 8613-6 - if (nargs > i + 2 && arg[i + 1] == 5) - { - scr_color ((unsigned int) (minCOLOR + arg[i + 2]), Color_fg); - i += 2; - } - break; case 39: /* default fg */ scr_color (Color_fg, Color_fg); break; @@ -3936,17 +3970,39 @@ case 47: scr_color ((unsigned int) (minCOLOR + (arg[i] - 40)), Color_bg); break; - case 48: // set bg color, ISO 8613-6 - if (nargs > i + 2 && arg[i + 1] == 5) - { - scr_color ((unsigned int) (minCOLOR + arg[i + 2]), Color_bg); - i += 2; - } - break; case 49: /* default bg */ scr_color (Color_bg, Color_bg); break; + case 38: // set fg color, ISO 8613-6 + case 48: // set bg color, ISO 8613-6 + { + 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]; + i += 2; + + scr_color (idx, fgbg); + } + else if (nargs > i + 4 && arg[i + 1] == 2) + { + unsigned int r = arg[i + 2]; + unsigned int g = arg[i + 3]; + unsigned int b = arg[i + 4]; + unsigned int a = 0xff; + + idx = map_rgb24_color (r, g, b, a); + + i += 4; + + scr_color (idx, fgbg); + } + } + break; + //case 50: // not variable spacing #if !ENABLE_MINIMAL @@ -3974,9 +4030,32 @@ } } } + +void +rxvt_term::set_cursor_style (int style) +{ + if (!IN_RANGE_INC (style, 0, 6)) + return; + + if (style == 0) + style = 1; + + cursor_type = (style - 1) / 2; + set_option (Opt_cursorUnderline, cursor_type == 1); + +#ifdef CURSOR_BLINK + set_option (Opt_cursorBlink, style & 1); + cursor_blink_reset (); +#endif + + want_refresh = 1; +} /*}}} */ -/* ------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------- */ +/* Write data to the pty as typed by the user, pasted with the mouse, + * or generated by us in response to a query ESC sequence. + */ /* * Send printf () formatted output to the command. @@ -3994,11 +4073,22 @@ tt_write (buf, strlen (buf)); } -/* ---------------------------------------------------------------------- */ -/* Write data to the pty as typed by the user, pasted with the mouse, - * or generated by us in response to a query ESC sequence. - */ -static const unsigned int MAX_PTY_WRITE = 255; // minimum MAX_INPUT +/* Write data to the pty as typed by the user. */ +void +rxvt_term::tt_write_user_input (const char *data, unsigned int len) +{ + if (HOOK_INVOKE ((this, HOOK_TT_WRITE, DT_STR_LEN, data, len, DT_END))) + return; + + if (option (Opt_scrollTtyKeypress)) + if (view_start) + { + view_start = 0; + want_refresh = 1; + } + + tt_write_ (data, len); +} void rxvt_term::tt_write (const char *data, unsigned int len) @@ -4006,6 +4096,14 @@ if (HOOK_INVOKE ((this, HOOK_TT_WRITE, DT_STR_LEN, data, len, DT_END))) return; + tt_write_ (data, len); +} + +static const unsigned int MAX_PTY_WRITE = 255; // minimum MAX_INPUT + +void +rxvt_term::tt_write_ (const char *data, unsigned int len) +{ if (pty->pty < 0) return;