--- rxvt-unicode/src/command.C 2012/06/07 11:27:08 1.519 +++ rxvt-unicode/src/command.C 2014/04/26 14:07:36 1.543 @@ -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,12 +22,12 @@ * 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) 2003-2014 Marc Lehmann * Copyright (c) 2007 Emanuele Giaquinta * * This program is free software; you can redistribute it and/or modify @@ -402,6 +402,15 @@ return param; } +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) { @@ -512,12 +521,12 @@ if (keysym == XK_Prior) { - scr_page (UP, lnsppg); + scr_page (lnsppg); return; } else if (keysym == XK_Next) { - scr_page (DN, lnsppg); + scr_page (-lnsppg); return; } } @@ -526,12 +535,12 @@ { if (keysym == XK_Up) { - scr_page (UP, 1); + scr_page (1); return; } else if (keysym == XK_Down) { - scr_page (DN, 1); + scr_page (-1); return; } } @@ -541,12 +550,12 @@ { if (keysym == XK_Home) { - scr_move_to (0, 1); + scr_changeview (top_row); return; } else if (keysym == XK_End) { - scr_move_to (1, 1); + scr_changeview (0); return; } } @@ -580,6 +589,21 @@ } } + 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)) @@ -943,7 +967,7 @@ { flush_ev.stop (); -#ifdef HAVE_BG_PIXMAP +#ifdef HAVE_IMG if (bg_flags & BG_NEEDS_REFRESH) { bg_flags &= ~BG_NEEDS_REFRESH; @@ -1079,7 +1103,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; @@ -1094,7 +1118,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 (); @@ -1469,13 +1493,16 @@ bool want_position_change = SHOULD_INVOKE (HOOK_POSITION_CHANGE); + bool moved = false; #ifdef HAVE_BG_PIXMAP if (bg_window_position_sensitive ()) - want_position_change = true; + { + want_position_change = true; + if (bg_img == 0) + moved = true; + } #endif - bool moved = false; - if (want_position_change) { int x, y; @@ -1493,11 +1520,8 @@ parent_x = x; parent_y = y; HOOK_INVOKE ((this, HOOK_POSITION_CHANGE, DT_INT, x, DT_INT, y, DT_END)); + moved = true; } - - if (bg_set_position (x, y) - || !(bg_flags & BG_IS_VALID)) - moved = true; } if (szHint.width != ev.xconfigure.width || szHint.height != ev.xconfigure.height) @@ -1531,19 +1555,14 @@ 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)) + // This is needed at startup for the case of no window manager + // or a non-reparenting window manager and also because we + // defer bg image updates if the window is not mapped. The + // short delay is to optimize for multiple ConfigureNotify + // events at startup when the window manager reparents the + // window, so as to perform the computation after we have + // received all of them. + if (bg_img == 0) update_background_ev.start (0.025); #endif mapped = 1; @@ -1645,6 +1664,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 @@ -1677,6 +1697,7 @@ + 1; min_it (scroll_selection_lines, SELECTION_SCROLL_MAX_LINES); + scroll_selection_lines *= scroll_selection_dir; } else { @@ -1840,7 +1861,7 @@ #endif } -#if ENABLE_TRANSPARENCY || ENABLE_PERL +#if BG_IMAGE_FROM_ROOT || ENABLE_PERL void ecb_hot rxvt_term::rootwin_cb (XEvent &ev) { @@ -1860,13 +1881,14 @@ if (ev.xproperty.atom == xa[XA_XROOTPMAP_ID] || ev.xproperty.atom == xa[XA_ESETROOT_PMAP_ID]) { -# if ENABLE_TRANSPARENCY - bg_set_root_pixmap (); - update_background (); +#if BG_IMAGE_FROM_ROOT + if (option (Opt_transparent)) + { + rxvt_img::new_from_root (this)->replace (root_img); + update_background (); + } #endif -#if ENABLE_PERL HOOK_INVOKE ((this, HOOK_ROOTPMAP_CHANGE, DT_END)); -#endif } break; @@ -2201,24 +2223,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); @@ -2226,7 +2247,7 @@ else # endif { - scr_page (v, i); + scr_page (dirn, lines); scrollBar.show (1); } } @@ -2389,6 +2410,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 } @@ -2803,7 +2826,7 @@ 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] = { }; @@ -2819,6 +2842,7 @@ ch = cmd_getc (); } + prev_ch = 0; /* read any numerical arguments */ for (n = -1; ch < CSI_ICH; ) { @@ -2838,6 +2862,7 @@ else if (IS_CONTROL (ch)) process_nonprinting (ch); + prev_ch = ch; ch = cmd_getc (); } @@ -3081,6 +3106,11 @@ priv_modes |= PrivMode_LFNL; break; + case CSI_71: // DESCUSR: set cursor style + if (prev_ch == ' ') + set_cursor_style (arg[0]); + break; + /* * PRIVATE USE beyond this point. All CSI_7? sequences here */ @@ -3223,7 +3253,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) { @@ -3248,7 +3278,7 @@ seen_esc = false; - if (n >= STRING_MAX - 1) + if (n >= sizeof (string) - 1) // stop at some sane length return NULL; @@ -3375,7 +3405,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); } @@ -3453,7 +3483,8 @@ case URxvt_Color_border: process_color_seq (op, Color_border, str, resp); break; -#if ENABLE_TRANSPARENCY + +#if BG_IMAGE_FROM_ROOT case URxvt_Color_tint: process_color_seq (op, Color_tint, str, resp); { @@ -3490,8 +3521,14 @@ if (*str != ';') { - if (fimage.set_file_geometry (str)) - changed = true; + try + { + fimage.set_file_geometry (this, str); + changed = true; + } + catch (const class rxvt_failure_exception &e) + { + } } else { @@ -3506,7 +3543,8 @@ { int x, y; get_window_origin (x, y); - bg_set_position (x, y); + parent_x = x; + parent_y = y; } update_background (); } @@ -3987,6 +4025,22 @@ } } } + +void +rxvt_term::set_cursor_style (int style) +{ + if (!IN_RANGE_INC (style, 0, 4)) + return; + + set_option (Opt_cursorUnderline, style >= 3); + +#ifdef CURSOR_BLINK + set_option (Opt_cursorBlink, !style || (style & 1)); + cursor_blink_reset (); +#endif + + want_refresh = 1; +} /*}}} */ /* ------------------------------------------------------------------------- */