# HG changeset patch # User Chong Yidong # Date 1281209944 14400 # Node ID 14830418f9fc04d22d9d16e8dc0bdf942e01ed0c # Parent 73b2acbfa01be2e9a507b37f6add612d6352a850 Change `select-active-region' mechanics. Save region text prior to buffer modification. Set window selection lazily, during `deactivate-mark' or after each command when the region is temporarily active. * lisp/cus-start.el: Add custom declaration for select-active-regions. * lisp/mouse.el (mouse-drag-track): Remove hacks to deal with old select-active-regions implementation. (mouse-yank-at-click): Doc fix. * lisp/simple.el (select-active-regions): Move to keyboard.c. (deactivate-mark): Used saved-region-selection. (select-active-region): Function removed. (activate-mark, set-mark, push-mark-command) (handle-shift-selection): Don't call it. (keyboard-quit): Avoid adding the region to the window selection. * src/insdel.c (prepare_to_modify_buffer): Save active region text to Vsaved_region_selection. * src/keyboard.c (Vselect_active_regions): Move from simple.el. (Vsaved_region_selection, Qx_set_selection, QPRIMARY, Qlazy): New vars. (command_loop_1): Set window selection prior to deactivating the mark. * src/xselect.c (QPRIMARY): Move to keyboard.c. diff -r 73b2acbfa01b -r 14830418f9fc etc/NEWS --- a/etc/NEWS Sat Aug 07 13:26:42 2010 +0300 +++ b/etc/NEWS Sat Aug 07 15:39:04 2010 -0400 @@ -192,7 +192,10 @@ default, is now similar to other X applications. In particular, kill and yank use the clipboard, in addition to the primary selection. -*** `select-active-regions' now defaults to t. +*** `select-active-regions' now defaults to `lazy'. +This means that any active region made with shift-selection or mouse +dragging, or acted on by Emacs (e.g. with M-w or C-w), is +automatically added to the primary window selection. *** `x-select-enable-clipboard' now defaults to t. diff -r 73b2acbfa01b -r 14830418f9fc lisp/ChangeLog --- a/lisp/ChangeLog Sat Aug 07 13:26:42 2010 +0300 +++ b/lisp/ChangeLog Sat Aug 07 15:39:04 2010 -0400 @@ -1,3 +1,18 @@ +2010-08-07 Chong Yidong + + * simple.el (select-active-regions): Move to keyboard.c. + (deactivate-mark): Used saved-region-selection. + (select-active-region): Function removed. + (activate-mark, set-mark, push-mark-command) + (handle-shift-selection): Don't call it. + (keyboard-quit): Avoid adding the region to the window selection. + + * mouse.el (mouse-drag-track): Remove hacks to deal with old + select-active-regions implementation. + (mouse-yank-at-click): Doc fix. + + * cus-start.el: Add custom declaration for select-active-regions. + 2010-08-07 Eli Zaretskii * simple.el (delete-forward-char): Doc fix. diff -r 73b2acbfa01b -r 14830418f9fc lisp/cus-start.el --- a/lisp/cus-start.el Sat Aug 07 13:26:42 2010 +0300 +++ b/lisp/cus-start.el Sat Aug 07 15:39:04 2010 -0400 @@ -197,6 +197,11 @@ (help-char keyboard character) (help-event-list keyboard (repeat (sexp :format "%v"))) (menu-prompting menu boolean) + (select-active-regions killing + (choice (const :tag "lazy" lazy) + (const :tag "always" t) + (const :tag "off" nil)) + "24.1") (suggest-key-bindings keyboard (choice (const :tag "off" nil) (integer :tag "time" 2) (other :tag "on"))) diff -r 73b2acbfa01b -r 14830418f9fc lisp/mouse.el --- a/lisp/mouse.el Sat Aug 07 13:26:42 2010 +0300 +++ b/lisp/mouse.el Sat Aug 07 15:39:04 2010 -0400 @@ -697,9 +697,6 @@ (window-system) (sit-for 1)) (push-mark) - ;; If `select-active-regions' is non-nil, `set-mark' sets the - ;; primary selection to the buffer's region, overriding the role - ;; of `copy-region-as-kill'; that's why we did the copy first. (set-mark (point)) (if (numberp end) (goto-char end)) (mouse-set-region-1))) @@ -905,10 +902,6 @@ `mouse-drag-region'." (mouse-minibuffer-check start-event) (setq mouse-selection-click-count-buffer (current-buffer)) - ;; We must call deactivate-mark before repositioning point. - ;; Otherwise, for `select-active-regions' non-nil, we get the wrong - ;; selection if the user drags a region, clicks elsewhere to - ;; reposition point, then middle-clicks to paste the selection. (deactivate-mark) (let* ((original-window (selected-window)) ;; We've recorded what we needed from the current buffer and @@ -955,10 +948,7 @@ (if (eq transient-mark-mode 'lambda) '(only) (cons 'only transient-mark-mode))) - (let ((range (mouse-start-end start-point start-point click-count)) - ;; Prevent `push-mark' from clobbering the primary selection - ;; if the user clicks without dragging. - (select-active-regions nil)) + (let ((range (mouse-start-end start-point start-point click-count))) (goto-char (nth 0 range)) (push-mark nil t t) (goto-char (nth 1 range))) @@ -1017,23 +1007,16 @@ ;; If point has moved, finish the drag. (let* (last-command this-command) - ;; Copy the region so that `select-active-regions' can - ;; override `copy-region-as-kill'. (and mouse-drag-copy-region do-mouse-drag-region-post-process (let (deactivate-mark) - (copy-region-as-kill (mark) (point)))) - ;; For `select-active-regions' non-nil, ensure that - ;; further alterations of the region (e.g. via - ;; shift-selection) continue to update PRIMARY. - (select-active-region)) + (copy-region-as-kill (mark) (point))))) ;; If point hasn't moved, run the binding of the ;; terminating up-event. (if do-multi-click (goto-char start-point) - (let (select-active-regions) - (deactivate-mark))) + (deactivate-mark)) (when (and (functionp fun) (= start-hscroll (window-hscroll start-window)) ;; Don't run the up-event handler if the window @@ -1251,9 +1234,7 @@ and set mark at the beginning. Prefix arguments are interpreted as with \\[yank]. If `mouse-yank-at-point' is non-nil, insert at point -regardless of where you click. -If `select-active-regions' is non-nil, the mark is deactivated -before inserting the text." +regardless of where you click." (interactive "e\nP") ;; Give temporary modes such as isearch a chance to turn off. (run-hooks 'mouse-leave-buffer-hook) diff -r 73b2acbfa01b -r 14830418f9fc lisp/simple.el --- a/lisp/simple.el Sat Aug 07 13:26:42 2010 +0300 +++ b/lisp/simple.el Sat Aug 07 15:39:04 2010 -0400 @@ -3666,29 +3666,27 @@ (marker-position (mark-marker)) (signal 'mark-inactive nil))) -(defcustom select-active-regions t - "If non-nil, an active region automatically becomes the window selection." - :type 'boolean - :group 'killing - :version "24.1") - (declare-function x-selection-owner-p "xselect.c" (&optional selection)) -;; Many places set mark-active directly, and several of them failed to also -;; run deactivate-mark-hook. This shorthand should simplify. (defsubst deactivate-mark (&optional force) "Deactivate the mark by setting `mark-active' to nil. Unless FORCE is non-nil, this function does nothing if Transient Mark mode is disabled. This function also runs `deactivate-mark-hook'." (when (or transient-mark-mode force) - ;; Copy the latest region into the primary selection, if desired. - (and select-active-regions - mark-active - (display-selections-p) - (x-selection-owner-p 'PRIMARY) - (x-set-selection 'PRIMARY (buffer-substring-no-properties - (region-beginning) (region-end)))) + (when (and select-active-regions + (region-active-p) + (display-selections-p)) + ;; The var `saved-region-selection', if non-nil, is the text in + ;; the region prior to the last command modifying the buffer. + ;; Set the selection to that, or to the current region. + (cond (saved-region-selection + (x-set-selection 'PRIMARY saved-region-selection) + (setq saved-region-selection nil)) + ((/= (region-beginning) (region-end)) + (x-set-selection 'PRIMARY + (buffer-substring-no-properties + (point) (mark)))))) (if (and (null force) (or (eq transient-mark-mode 'lambda) (and (eq (car-safe transient-mark-mode) 'only) @@ -3706,14 +3704,7 @@ (when (mark t) (setq mark-active t) (unless transient-mark-mode - (setq transient-mark-mode 'lambda)) - (select-active-region))) - -(defsubst select-active-region () - "Set the PRIMARY X selection if `select-active-regions' is non-nil." - (and select-active-regions - (display-selections-p) - (x-set-selection 'PRIMARY (current-buffer)))) + (setq transient-mark-mode 'lambda)))) (defun set-mark (pos) "Set this buffer's mark to POS. Don't use this function! @@ -3736,7 +3727,6 @@ (progn (setq mark-active t) (run-hooks 'activate-mark-hook) - (select-active-region) (set-marker (mark-marker) pos (current-buffer))) ;; Normally we never clear mark-active except in Transient Mark mode. ;; But when we actually clear out the mark value too, we must @@ -3820,7 +3810,6 @@ (push-mark nil nomsg t) (setq mark-active t) (run-hooks 'activate-mark-hook) - (select-active-region) (unless nomsg (message "Mark activated"))))) @@ -4008,11 +3997,8 @@ deactivate it, and restore the variable `transient-mark-mode' to its earlier value." (cond ((and shift-select-mode this-command-keys-shift-translated) - (if (and mark-active - (eq (car-safe transient-mark-mode) 'only)) - ;; Another program may have grabbed the selection; make - ;; sure we get it back now. - (select-active-region) + (unless (and mark-active + (eq (car-safe transient-mark-mode) 'only)) (setq transient-mark-mode (cons 'only (unless (eq transient-mark-mode 'lambda) @@ -5576,7 +5562,10 @@ During execution of Lisp code, this character causes a quit directly. At top-level, as an editor command, this simply beeps." (interactive) - (deactivate-mark) + ;; Avoid adding the region to the window selection. + (setq saved-region-selection nil) + (let (select-active-regions) + (deactivate-mark)) (if (fboundp 'kmacro-keyboard-quit) (kmacro-keyboard-quit)) (setq defining-kbd-macro nil) diff -r 73b2acbfa01b -r 14830418f9fc src/ChangeLog --- a/src/ChangeLog Sat Aug 07 13:26:42 2010 +0300 +++ b/src/ChangeLog Sat Aug 07 15:39:04 2010 -0400 @@ -1,3 +1,16 @@ +2010-08-07 Chong Yidong + + * insdel.c (prepare_to_modify_buffer): Save active region text to + Vsaved_region_selection. + + * xselect.c (QPRIMARY): Move to keyboard.c. + + * keyboard.c (Vselect_active_regions): Move from simple.el. + (Vsaved_region_selection, Qx_set_selection, QPRIMARY, Qlazy): New + vars. + (command_loop_1): Set window selection prior to deactivating the + mark. + 2010-08-07 Juanma Barranquero * alloc.c (lisp_malloc): diff -r 73b2acbfa01b -r 14830418f9fc src/insdel.c --- a/src/insdel.c Sat Aug 07 13:26:42 2010 +0300 +++ b/src/insdel.c Sat Aug 07 15:39:04 2010 -0400 @@ -74,6 +74,8 @@ Lisp_Object Qinhibit_modification_hooks; +extern Lisp_Object Vselect_active_regions, Vsaved_region_selection; + /* Check all markers in the current buffer, looking for something invalid. */ @@ -2047,6 +2049,21 @@ base_buffer->filename); #endif /* not CLASH_DETECTION */ + /* If `select-active-regions' is non-nil, save the region text. */ + if (!NILP (Vselect_active_regions) + && !NILP (current_buffer->mark_active) + && !NILP (Vtransient_mark_mode) + && NILP (Vsaved_region_selection)) + { + Lisp_Object b = Fmarker_position (current_buffer->mark); + Lisp_Object e = make_number (PT); + if (NILP (Fequal (b, e))) + { + validate_region (&b, &e); + Vsaved_region_selection = make_buffer_string (XINT (b), XINT (e), 0); + } + } + signal_before_change (start, end, preserve_ptr); if (current_buffer->newline_cache) diff -r 73b2acbfa01b -r 14830418f9fc src/keyboard.c --- a/src/keyboard.c Sat Aug 07 13:26:42 2010 +0300 +++ b/src/keyboard.c Sat Aug 07 15:39:04 2010 -0400 @@ -361,6 +361,15 @@ X Windows wants this for selection ownership. */ unsigned long last_event_timestamp; +/* If non-nil, active regions automatically become the window selection. */ +Lisp_Object Vselect_active_regions; + +/* The text in the active region prior to modifying the buffer. + Used by the `select-active-regions' feature. */ +Lisp_Object Vsaved_region_selection; + +Lisp_Object Qx_set_selection, QPRIMARY, Qlazy; + Lisp_Object Qself_insert_command; Lisp_Object Qforward_char; Lisp_Object Qbackward_char; @@ -1781,11 +1790,26 @@ Vtransient_mark_mode = Qnil; else if (EQ (Vtransient_mark_mode, Qonly)) Vtransient_mark_mode = Qidentity; + else if (EQ (Vselect_active_regions, Qlazy) + ? EQ (CAR_SAFE (Vtransient_mark_mode), Qonly) + : (!NILP (Vselect_active_regions) + && !NILP (Vtransient_mark_mode))) + { + /* Set window selection. If `select-active-regions' is + `lazy', only do it for temporarily active regions. */ + Lisp_Object beg = Fmarker_position (current_buffer->mark); + Lisp_Object end = make_number (PT); + validate_region (&beg, &end); + call2 (Qx_set_selection, QPRIMARY, + make_buffer_string (XINT (beg), XINT (end), 0)); + } if (!NILP (Vdeactivate_mark)) call0 (Qdeactivate_mark); else if (current_buffer != prev_buffer || MODIFF != prev_modiff) call1 (Vrun_hooks, intern ("activate-mark-hook")); + + Vsaved_region_selection = Qnil; } finalize: @@ -11682,6 +11706,13 @@ Qinput_method_function = intern_c_string ("input-method-function"); staticpro (&Qinput_method_function); + Qx_set_selection = intern_c_string ("x-set-selection"); + staticpro (&Qx_set_selection); + QPRIMARY = intern_c_string ("PRIMARY"); + staticpro (&QPRIMARY); + Qlazy = intern_c_string ("lazy"); + staticpro (&Qlazy); + Qinput_method_exit_on_first_char = intern_c_string ("input-method-exit-on-first-char"); staticpro (&Qinput_method_exit_on_first_char); Qinput_method_use_echo_area = intern_c_string ("input-method-use-echo-area"); @@ -12289,6 +12320,28 @@ and tool-bar buttons. */); Venable_disabled_menus_and_buttons = Qnil; + DEFVAR_LISP ("select-active-regions", + &Vselect_active_regions, + doc: /* If non-nil, an active region automatically becomes the window selection. +This takes effect only when Transient Mark mode is enabled. + +If the value is `lazy', Emacs only sets the window selection during +`deactivate-mark'; unless the region is temporarily active +(e.g. mouse-drags or shift-selection), in which case it sets the +window selection after each command. + +For other non-nil value, Emacs sets the window selection after every +command. */); + Vselect_active_regions = Qlazy; + + DEFVAR_LISP ("saved-region-selection", + &Vsaved_region_selection, + doc: /* Contents of active region prior to buffer modification. +If `select-active-regions' is non-nil, Emacs sets this to the +text in the region before modifying the buffer. The next +`deactivate-mark' call uses this to set the window selection. */); + Vsaved_region_selection = Qnil; + /* Create the initial keyboard. */ initial_kboard = (KBOARD *) xmalloc (sizeof (KBOARD)); init_kboard (initial_kboard); diff -r 73b2acbfa01b -r 14830418f9fc src/xselect.c --- a/src/xselect.c Sat Aug 07 13:26:42 2010 +0300 +++ b/src/xselect.c Sat Aug 07 15:39:04 2010 -0400 @@ -2916,7 +2916,7 @@ \"*selectionTimeout\" resource. */); x_selection_timeout = 0; - QPRIMARY = intern_c_string ("PRIMARY"); staticpro (&QPRIMARY); + /* QPRIMARY is defined in keyboard.c. */ QSECONDARY = intern_c_string ("SECONDARY"); staticpro (&QSECONDARY); QSTRING = intern_c_string ("STRING"); staticpro (&QSTRING); QINTEGER = intern_c_string ("INTEGER"); staticpro (&QINTEGER);