*** isearch.1.222.el Tue Sep 23 21:04:28 2003 --- isearch.1.222.acm.el Tue Oct 21 20:53:36 2003 *************** *** 1224,1241 **** (goto-char isearch-barrier))) (isearch-process-search-char last-command-char)) (defalias 'isearch-other-control-char 'isearch-other-meta-char) ! (defun isearch-other-meta-char () ! "Exit the search normally and reread this key sequence. ! But only if `search-exit-option' is non-nil, the default. ! If it is the symbol `edit', the search string is edited in the minibuffer ! and the meta character is unread so that it applies to editing the string." ! (interactive) ! (let* ((key (this-command-keys)) (main-event (aref key 0)) ! (keylist (listify-key-sequence key))) (cond ((and (= (length key) 1) (let ((lookup (lookup-key function-key-map key))) (not (or (null lookup) (integerp lookup) --- 1224,1355 ---- (goto-char isearch-barrier))) (isearch-process-search-char last-command-char)) + (defun isearch-unread-key-sequence (keylist) + "Unread the given key-sequence KEYLIST, being careful with scroll-bar or + mode-line events." + (cancel-kbd-macro-events) + (apply 'isearch-unread keylist) + ;; If the event was a scroll-bar or mode-line click, the event will have + ;; been prefixed by a symbol such as vertical-scroll-bar. We must remove + ;; it here, because this symbol will be attached to the event again next + ;; time it gets read by read-key-sequence. + ;; + ;; (Old comment from isearch-other-meta-char: "Note that we don't have to + ;; modify the event anymore in 21 because read_key_sequence no longer + ;; modifies events to produce fake prefix keys.") + (if (and (> (length keylist) 1) + (symbolp (car keylist)) + (listp (cadr keylist)) + (not (numberp (posn-point + (event-start (cadr keylist) ))))) + (pop unread-command-events))) + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; scrolling within isearch-mode. Alan Mackenzie (acm@muc.de), 2003/2/24 + ;; + ;; The idea here is that certain vertical scrolling commands (like C-l + ;; (recenter)) should be usable WITHIN isearch mode. For a command to be + ;; suitable, it must NOT alter the buffer, swap to another buffer or frame, + ;; tamper with isearch's state, or move point. It is unacceptable for the + ;; search string to be scrolled out of the current window. If a command + ;; attempts this, we scroll the text back again. + ;; + ;; Horizontal scrolling commands are currently not catered for. + ;; + ;; We implement this feature with a property called isearch-scroll. If a + ;; command's symbol has the value t for this property it is a scrolling + ;; command. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + (defcustom isearch-allow-scroll nil + "If non-nil, certain scrolling commands are allowed during incremental search." + :type 'boolean + :group 'isearch) + + (defun isearch-string-out-of-window (isearch-point) + "Is the search string currently outside of the window? Return nil if it's + completely visible, or if point is visible, together with as much of the + search string as will fit; 'above if we need to scroll the text downwards; + 'below, if upwards." + (let ((w-start (window-start)) + (w-end (window-end nil t)) + (w-L1 (save-excursion (move-to-window-line 1) (point))) + (w-L-1 (save-excursion (move-to-window-line -1) (point))) + start end) ; start and end of search string in buffer + (if isearch-forward + (setq end isearch-point start (or isearch-other-end isearch-point)) + (setq start isearch-point end (or isearch-other-end isearch-point))) + (cond ((or (and (>= start w-start) (<= end w-end)) + (if isearch-forward + (and (>= isearch-point w-L-1) (< isearch-point w-end)) ; point on Line -1 + (and (>= isearch-point w-start) (< isearch-point w-L1)))) ; point on Line 0 + nil) + ((and (< start w-start) + (< isearch-point w-L-1)) + 'above) + (t 'below)))) + + (defun isearch-back-into-window (above isearch-point) + "Scroll the window to bring the search string back into view, restoring + point to ISEARCH-POINT in the process. ABOVE is t when the search string is + above the top of the window, nil when it is beneath the bottom." + (let (start end) + (if isearch-forward + (setq end isearch-point start (or isearch-other-end isearch-point)) + (setq start isearch-point end (or isearch-other-end isearch-point))) + (if above + (progn + (goto-char start) + (recenter 0) + (when (>= isearch-point (window-end nil t)) + (goto-char isearch-point) + (recenter -1))) + (goto-char end) + (recenter -1) + (when (< isearch-point (window-start)) + (goto-char isearch-point) + (recenter 0)))) + (goto-char isearch-point)) + + (defun isearch-reread-key-sequence-naturally (keylist) + "Reread the current key sequence KEYLIST with isearch-mode's own keymap + deactivated. Return the key sequence as a string/vector." + (isearch-unread-key-sequence keylist) + (let (overriding-terminal-local-map) + (read-key-sequence nil))) ; This will go through function-key-map, if nec. + + (defun isearch-lookup-scroll-key (key) + "If the supplied key sequence, KEY, is bound to a scrolling command, return + this command (always a symbol), otherwise nil." + (let* ((overriding-terminal-local-map nil) + (binding (key-binding key))) + (and binding (symbolp binding) (commandp binding) + (eq (get binding 'isearch-scroll) t) + binding))) (defalias 'isearch-other-control-char 'isearch-other-meta-char) ! (defun isearch-other-meta-char (&optional arg) ! "See if the current key-sequence can be converted to something usable in ! isearch-mode, either by converting it with the function-key-map, downcasing a ! key with C-, or finding a \"scrolling command\" bound to it. \(In ! the last case, we may have to read more events.\) If so, either unread the ! converted sequence or execute the command. ! ! Otherwise, if `search-exit-option' is non-nil (the default) unread the ! key-sequence and exit the search normally. If it is the symbol `edit', the ! search string is edited in the minibuffer and the meta character is unread so ! that it applies to editing the string. ! ! ARG is the prefix argument. It will be transmitted through to the scrolling ! command or to the command which exits isearch-mode." ! (interactive "P") ! (let* ((key (if current-prefix-arg ; not nec the same as ARG ! (substring (this-command-keys) universal-argument-num-events) ! (this-command-keys))) (main-event (aref key 0)) ! (keylist (listify-key-sequence key)) ! scroll-command isearch-point) (cond ((and (= (length key) 1) (let ((lookup (lookup-key function-key-map key))) (not (or (null lookup) (integerp lookup) *************** *** 1287,1309 **** ((eq search-exit-option 'edit) (apply 'isearch-unread keylist) (isearch-edit-string)) (search-exit-option (let (window) ! (cancel-kbd-macro-events) ! (apply 'isearch-unread keylist) ! ! ;; Properly handle scroll-bar and mode-line clicks for ! ;; which a dummy prefix event was generated as (aref key ! ;; 0). Note that we don't have to modify the event ! ;; anymore in 21 because read_key_sequence no longer modifies ! ;; events to produce fake prefix keys. ! (when (and (> (length key) 1) ! (symbolp (aref key 0)) ! (listp (aref key 1)) ! (not (numberp (posn-point ! (event-start (aref key 1)))))) ! (pop unread-command-events) ! (setq main-event (car unread-command-events))) ;; If we got a mouse click event, that event contains the ;; window clicked on. maybe it was read with the buffer --- 1401,1427 ---- ((eq search-exit-option 'edit) (apply 'isearch-unread keylist) (isearch-edit-string)) + ;; Handle a scrolling function. + ((and isearch-allow-scroll + (progn (setq key (isearch-reread-key-sequence-naturally keylist)) + (setq keylist (listify-key-sequence key)) + (setq main-event (aref key 0)) + (setq scroll-command (isearch-lookup-scroll-key key)))) + ;; From this point onwards, KEY, KEYLIST and MAIN-EVENT hold a + ;; complete key sequence, possibly as modified by function-key-map, + ;; not merely the one or two event fragment which invoked + ;; isearch-other-meta-char in the first place. + (setq isearch-point (point)) + (setq prefix-arg arg) + (command-execute scroll-command) + (let ((ab-bel (isearch-string-out-of-window isearch-point))) + (if ab-bel + (isearch-back-into-window (eq ab-bel 'above) isearch-point))) + (isearch-update)) (search-exit-option (let (window) ! (isearch-unread-key-sequence keylist) ! (setq main-event (car unread-command-events)) ;; If we got a mouse click event, that event contains the ;; window clicked on. maybe it was read with the buffer *************** *** 1333,1340 **** (isearch-done) (isearch-clean-overlays)) (isearch-done) ! (isearch-clean-overlays)))) ! (t;; otherwise nil (isearch-process-search-string key key))))) (defun isearch-quote-char () --- 1451,1459 ---- (isearch-done) (isearch-clean-overlays)) (isearch-done) ! (isearch-clean-overlays) ! (setq prefix-arg arg)))) ! (t;; otherwise nil (isearch-process-search-string key key))))) (defun isearch-quote-char () *************** *** 1997,2002 **** --- 2116,2122 ---- (defvar isearch-lazy-highlight-last-string nil) (defvar isearch-lazy-highlight-window nil) (defvar isearch-lazy-highlight-window-start nil) + (defvar isearch-lazy-highlight-window-end nil) (defvar isearch-lazy-highlight-case-fold-search nil) (defvar isearch-lazy-highlight-regexp nil) *************** *** 2031,2042 **** (not (eq isearch-lazy-highlight-regexp isearch-regexp)) (not (= (window-start) ! isearch-lazy-highlight-window-start)))) ;; something important did indeed change (isearch-lazy-highlight-cleanup t) ;kill old loop & remove overlays (when (not isearch-invalid-regexp) (setq isearch-lazy-highlight-window (selected-window) isearch-lazy-highlight-window-start (window-start) isearch-lazy-highlight-start (point) isearch-lazy-highlight-end (point) isearch-lazy-highlight-last-string isearch-string --- 2151,2165 ---- (not (eq isearch-lazy-highlight-regexp isearch-regexp)) (not (= (window-start) ! isearch-lazy-highlight-window-start)) ! (not (= (window-end) ; Window may have been split/joined. ! isearch-lazy-highlight-window-end)))) ;; something important did indeed change (isearch-lazy-highlight-cleanup t) ;kill old loop & remove overlays (when (not isearch-invalid-regexp) (setq isearch-lazy-highlight-window (selected-window) isearch-lazy-highlight-window-start (window-start) + isearch-lazy-highlight-window-end (window-end) isearch-lazy-highlight-start (point) isearch-lazy-highlight-end (point) isearch-lazy-highlight-last-string isearch-string