home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / gnu / epoch / misc / 1136 < prev    next >
Encoding:
Text File  |  1992-11-19  |  26.2 KB  |  836 lines

  1. Newsgroups: gnu.epoch.misc
  2. Path: sparky!uunet!zaphod.mps.ohio-state.edu!news.acns.nwu.edu!gauss!richter
  3. From: richter@gauss.math.nwu.edu (Bill Richter)
  4. Subject: Re:isearch & mouse
  5. Message-ID: <1992Nov19.160716.18185@news.acns.nwu.edu>
  6. Sender: usenet@news.acns.nwu.edu (Usenet on news.acns)
  7. Fcc: stuff
  8. Organization: Northwestern University, Evanston, Illinois, USA
  9. Date: Thu, 19 Nov 1992 16:07:16 GMT
  10. Lines: 824
  11.  
  12. Here's a fix for the isearch bug; now a mouse action will exit an
  13. isearch.  The fix is quite simple and consists of 
  14. 1) changing the position of the line (abort-isearch) in the motion.el
  15. routines
  16. 2) removing the save-window-excursion loop from isearch.el.  I'm
  17. including the mouse part of my .emacs file (which fixes the isearch
  18. bug), followed by my doctored version of isearch.el.
  19.  
  20. If you use my version of isearch.el, make sure it is at the top of
  21. your load-path variable (check with C-h v load-path).  I do this by
  22. putting the new isearch.el in my directory epoch-4.2/epoch-lisp and
  23. byte-compile-ing it to make a new isearch.elc.
  24.  
  25. I also recommend my other included mouse mods, which include
  26. Textedit-like secondary selections (cut/copy/paste a grey region away
  27. from the mouse) and emacstool-like modeline mouse scrolling.  To me
  28. the advantage of epoch is the extra (programmable) mouse capability.
  29.  
  30.  
  31. Bill Richter
  32.  
  33.  
  34.  
  35. ;;; MOUSE CUSTOMIZATIONS. 
  36. ;;; 
  37. ;;;      Everything here works with a split window, but not
  38. ;;; with separate screens. I use an emacs window that fills up
  39. ;;; the whole screen anyway.  We exit gracefully
  40. ;;; from isearches by: putting the line (abort-isearch) at the end of
  41. ;;; our mouse routines; and recompiling search by removing the one
  42. ;;; instance of save-window-excursion in isearch.el.
  43.  
  44. ;;; Primary selections hacked from motion.el to resemble Paul
  45. ;;; Burchard's mods of x-mouse.el
  46. ;;; 
  47. ;;; left mouse       = insert cursor and begin hiliting (underlining).
  48. ;;; middle mouse     = end hiliting & set-mark & copy hilited
  49. ;;;              region to kill ring and x cut-buffer. 
  50. ;;;                 with double click fills-region-as-paragraph.
  51. ;;; right mouse      = paste x cut-buffer at mouse.
  52. ;;; cut (L10) button    = cut hilited region.
  53. ;;; shift middle mouse     = cut region between point and mouse.
  54. ;;; 
  55. ;;; more precisely, sh-mid-mouse-down hilites and sh-mid-mouse-up cuts.
  56. ;;; cut does not take place if you pick up the shift key before
  57. ;;; picking up middle-mouse.
  58.  
  59.  
  60. ;;; Textedit-like secondary selections:
  61. ;;; 
  62. ;;; left meta mouse           = begin secondary hiliting (grey stipple).
  63. ;;; middle meta mouse-down     = hilite and copy to x cut-buffer.
  64. ;;; middle meta mouse-up     = paste here and un-hilite.
  65. ;;;                    (pick up shift to cancel.)
  66. ;;; shift middle meta mouse-down= hilite and copy to x cut-buffer.  
  67. ;;; shift middle meta mouse-up    = paste here and cut there.  
  68. ;;;                    (pick up shift-meta to cancel.)
  69. ;;; right meta mouse          = paste there.
  70. ;;; shift middle meta mouse     = cut there.  
  71.  
  72.  
  73. ;;; Emacstool-like modeline mouse scrolling:
  74. ;;; 
  75. ;;;  (left middle right)-modeline mouse = (page-down recenter page-up)
  76. ;;;  shift-(left middle right)-modeline = (beg-file top-recenter end-file)
  77. ;;;  dbl clicks-(left right)-mod. mouse = (beg-file end-file)
  78.  
  79. (load "isearch")
  80.  
  81. ;;; first the modeline mouse scrolling:
  82.  
  83. (defun mouse-scroll-up (arg)
  84.   (setq curwin (selected-window))
  85.   (select-window (nth 2 arg))
  86.   (if (> mouse::clicks 1) ; multi-click
  87.     (end-of-buffer)
  88.     (scroll-up)
  89.   )
  90.   (select-window curwin) 
  91. )
  92.  
  93. (defun mouse-scroll-down (arg)
  94.   (setq curwin (selected-window))
  95.   (select-window (nth 2 arg))
  96.   (if (> mouse::clicks 1) ; multi-click
  97.     (beginning-of-buffer)
  98.     (scroll-down) 
  99.   )
  100.   (select-window curwin) 
  101. )
  102.  
  103.  
  104. (defun mouse-recenter (arg)
  105.   (setq curwin (selected-window))
  106.   (select-window (nth 2 arg))
  107.   (if (= mouse::clicks 2) ; multi-click
  108.     (top-recenter) 
  109.     (recenter) 
  110.   )
  111.   (if (> mouse::clicks 2) ; multi-click
  112.     (bottom-recenter)
  113.   )
  114.   (select-window curwin) 
  115. )
  116.  
  117. (defun mouse-ebuff-list (arg)
  118.    (electric-buffer-list () ) )
  119.  
  120. (defun mouse-beg-of-buffer (arg)
  121.   (setq curwin (selected-window))
  122.   (select-window (nth 2 arg))
  123.   (beginning-of-buffer) 
  124.   (select-window curwin) 
  125. )
  126.  
  127. (defun mouse-end-of-buffer (arg)
  128.   (setq curwin (selected-window))
  129.   (select-window (nth 2 arg))
  130.   (end-of-buffer) 
  131.   (select-window curwin) 
  132. )
  133.  
  134. (defun mouse-top-recenter (arg)
  135.   (setq curwin (selected-window))
  136.   (select-window (nth 2 arg))
  137.   (top-recenter) 
  138.   (select-window curwin) 
  139. )
  140.  
  141. (defun top-recenter ()
  142.   (interactive)
  143.   (recenter 0))
  144.  
  145. (defun bottom-recenter ()
  146.   (interactive)
  147.   (recenter -1))
  148.  
  149. (global-set-mouse mouse-mode-left mouse-shift 'mouse-end-of-buffer)
  150. (global-set-mouse mouse-mode-left mouse-down 'mouse-scroll-up)
  151.  
  152. (global-set-mouse mouse-mode-right mouse-down 'mouse-scroll-down)
  153. (global-set-mouse mouse-mode-right mouse-shift 'mouse-beg-of-buffer)
  154.  
  155. (global-set-mouse mouse-mode-middle mouse-down 'mouse-recenter)
  156.  
  157. (global-set-mouse mouse-mode-middle mouse-meta 'mouse-ebuff-list)
  158. (global-set-mouse mouse-mode-middle mouse-shift 'mouse-top-recenter)
  159.  
  160.  
  161. ;;;
  162. ;;; Now the Primary selection mouse customizations.  
  163. ;;;
  164.  
  165.  
  166. (defun start-mouse-drag (arg)
  167. ; (when arg
  168.     (setq mouse::downp 'start)
  169.     (mouse::set-point arg)
  170.     (set-mouse-marker)
  171.     (setq mouse::last-point (point))
  172.     (if drag-zone
  173.       (progn
  174.     (delete-zone drag-zone)
  175.     (setq drag-zone nil)
  176.     (redisplay-screen)
  177.       )
  178.     )
  179.     (abort-isearch)
  180. ; )
  181. )
  182.  
  183.  
  184. (defun end-mouse-region (arg)
  185.    "ends the highlited drag-zone, the region between mouse cursor
  186. mouse-left-marker.  With a double click, fills-region-as-paragraph "
  187.   (if drag-zone
  188.      (move-zone drag-zone mouse-down-marker (car arg)
  189.      )
  190.      (setq drag-zone 
  191.     (add-zone mouse-down-marker (car arg) motion::style) 
  192.      )
  193.   )    
  194. ; (set-zone-transient drag-zone t)
  195.   (epoch::redisplay-screen)
  196.   (mouse::copy-zone drag-zone)
  197.   (push-mark (car arg) t)    
  198.   (if (> mouse::clicks 1) ; multi-click
  199.     (fill-region-as-paragraph (point) (zone-end drag-zone))
  200.   )
  201. )
  202.  
  203.  
  204.  
  205. (defun mouse-cut-and-wipe-text (arg)
  206.   "Kill text between point and mouse, like x-cut-and-wipe-text"
  207.   (mouse::copy-zone drag-zone t)    
  208.   (undo-boundary)
  209.   (abort-isearch)
  210. )
  211.  
  212. (defun mouse-show-x-text (arg)
  213.   "Underlines text between point and mouse; like x-cut-and-wipe-text"
  214.   (if drag-zone
  215.      (move-zone drag-zone (point) (car arg) (nth 1 arg)
  216.      )
  217.      (setq drag-zone 
  218.     (add-zone (point) (car arg) motion::style)
  219.      )
  220.   )
  221.   (set-zone-transient drag-zone t)
  222.   (epoch::redisplay-screen)
  223. )
  224.  
  225. (defun bill-mouse::paste-cut-buffer (arg)
  226.    (progn 
  227.     (mouse::paste-cut-buffer arg) 
  228.        (undo-boundary)
  229.        (mouse::set-point arg)
  230.         (abort-isearch)
  231.    ) 
  232. )
  233.  
  234. (defun kill-underlined-region ()
  235. "kills (and X-cuts) the underlined region of text; point is not
  236. moved."
  237.     (interactive)
  238.     (mouse::copy-zone drag-zone t)    
  239.     (undo-boundary)
  240. )
  241.  
  242. (global-set-mouse mouse-left mouse-down 'start-mouse-drag)
  243. (global-set-mouse mouse-left mouse-shift 'start-mouse-drag)
  244. (global-set-mouse mouse-left mouse-up 'end-mouse-drag)
  245.  
  246. ;(global-set-mouse mouse-middle mouse-down 'extend-mouse-drag)
  247. ;(global-set-mouse mouse-middle mouse-up 'end-mouse-drag)
  248.  
  249. (global-set-mouse mouse-middle mouse-shift 'mouse-show-x-text)
  250. (global-set-mouse mouse-middle mouse-shift-up 'mouse-cut-and-wipe-text)
  251.  
  252. (global-set-mouse mouse-right mouse-down 'bill-mouse::paste-cut-buffer)
  253. (global-set-mouse mouse-right mouse-shift 'bill-mouse::paste-cut-buffer)
  254.  
  255. ;(global-set-mouse mouse-left mouse-down 'start-mouse-region)
  256. ;(global-set-mouse mouse-left mouse-shift 'start-mouse-region)
  257.  
  258. (global-set-mouse mouse-middle mouse-down 'end-mouse-region)
  259.  
  260.  
  261. ;rebinds L10 on sparc keyboard as explained in Epoch-FAQ
  262. (rebind-key "L10" 0 "\C-^Xcut")    
  263. (define-key global-map "\C-^Xcut" 'kill-underlined-region)    ;L10=CUT
  264.  
  265.  
  266. ;;; 
  267. ;;; We define secondary selections for mouse actions, hacked from
  268. ;;; motion.el 
  269. ;;; 
  270.  
  271. ;; makes secondary selection appear as gray stipple pattern.
  272. (defvar sec:motion::style nil "style used by secondary drag zone")
  273. (setq-default sec:motion::style (make-style))
  274.  
  275. ;; this pattern is from the EPOCH-FAQ
  276. (set-style-background sec:motion::style (foreground))
  277. (set-style-background-stipple sec:motion::style
  278.       (make-bitmap 4 4 "\167\273\335\356"))
  279.  
  280.  
  281. (defvar sec:drag-zone nil
  282.   "Epoch zone to be used for hilighting the secondary selection."
  283. )
  284. (setq-default sec:drag-zone nil)
  285.  
  286. ;; sec:mouse-down-marker is the marker which marks the left boundary of
  287. ;; our secondary selection, made by clicking the left-meta mouse
  288.   (setq-default sec:mouse-down-marker (make-marker))
  289.  
  290. (defun sec:start-mouse-region (arg)
  291. ;;; arg is a list of ( POINT BUFFER WINDOW SCREEN )
  292.   "starts the epoch region sec:drag-zone, which is one character in
  293. width, starting at location arg_0, in the buffer of arg_1"
  294.     (set-marker sec:mouse-down-marker (car arg) (nth 1 arg))
  295.     (if sec:drag-zone
  296.       (progn
  297.     (delete-zone sec:drag-zone)
  298.     (setq sec:drag-zone nil)
  299.     (redisplay-screen)
  300.       )
  301.     )
  302.     (setq sec:drag-zone   
  303.         (add-zone (car arg) (+ 1 (car arg)) sec:motion::style 
  304.             (nth 2 arg) (nth 1 arg)
  305.           ) 
  306.     )
  307. )
  308.  
  309. (defun sec:end-mouse-region (arg)
  310.    "ends the epoch zone sec:drag-zone, which will be hilited in a grey
  311. stipple pattern."
  312.   (if sec:drag-zone
  313.      (move-zone sec:drag-zone sec:mouse-down-marker (car arg) (nth 1 arg)
  314.      )
  315.      (setq sec:drag-zone 
  316.     (add-zone sec:mouse-down-marker (car arg) sec:motion::style 
  317.             (nth 2 arg) (nth 1 arg)
  318.     ) 
  319.      )
  320.   )    
  321.   (set-zone-transient sec:drag-zone t)
  322.   (epoch::redisplay-screen)
  323.   (mouse::sec:copy-zone sec:drag-zone)    
  324.   (undo-boundary)
  325. )
  326.  
  327.  
  328. (defun sec:mouse-paste-here (arg)
  329.    (yank) 
  330.    (delete-zone sec:drag-zone)
  331.    (setq sec:drag-zone nil)
  332.    (undo-boundary)
  333. )
  334.  
  335. (defun sec:hilite-region (arg)
  336.  "kills (and X-cuts) the highlit region of text; point is not moved."
  337.     (mouse::copy-zone sec:drag-zone t)    
  338.     (undo-boundary)
  339. )
  340.  
  341.  
  342. (defun sec:mouse-paste-here-kill-there (arg)
  343.    (yank) 
  344.    (mouse::copy-zone sec:drag-zone t)    
  345.    (delete-zone sec:drag-zone)
  346.    (setq sec:drag-zone nil)
  347.    (undo-boundary)
  348. )
  349.  
  350. (defun sec:kill-there (arg)
  351.    (mouse::copy-zone sec:drag-zone t)    
  352.    (delete-zone sec:drag-zone)
  353.    (setq sec:drag-zone nil)
  354.    (undo-boundary)
  355. )
  356.  
  357.  
  358.  
  359. (defun paste-there (arg)
  360.    (progn 
  361.     (mouse::paste-cut-buffer arg) 
  362.        (undo-boundary)
  363.    ) 
  364. )
  365.  
  366. (defun mouse::sec:copy-zone (zone)
  367.   "A modification of mouse::copy-zone---``Copy the text in the ZONE to
  368. the appropriate selection atom and to X cut-buffer'':
  369. *** we don't test that (point-max) > (epoch::zone-start&end zone).  This
  370. allows us to copy from the Rmail buffer, in which narrowing occurs;
  371. *** for safety we do not allow optional kills. 
  372. *** We make sure to restore the old buffer when we're done."
  373.   (if (zonep zone)
  374.     (let
  375.       (
  376.         (beg (epoch::zone-start zone) )
  377.     (end (epoch::zone-end zone) )
  378.     (buf (epoch::zone-buffer zone))
  379.     text
  380.       )
  381.       (if (null beg) (setq beg 1))
  382.       (if (null end) (setq end 1))
  383.       (if (bufferp buf)
  384.     (save-excursion
  385.       (set-buffer buf)
  386.       (setq text (buffer-substring beg end))
  387.     )
  388.     (setq text "")
  389.       )
  390.       (epoch::store-cut-buffer text)
  391.       ; assert ownership of PRIMARY selection
  392.       (epoch::acquire-selection mouse::selection-atom)
  393.       ; store data so we people can paste from Epoch to other clients.
  394.       (setq epoch::selection-alist
  395.     (alist-delete mouse::selection-atom epoch::selection-alist))
  396.       (setq epoch::selection-alist
  397.     (cons
  398.       (cons
  399.         mouse::selection-atom text
  400.       )
  401.       epoch::selection-alist
  402.     )
  403.       )
  404.       (if (/= beg end)
  405.     (if (bufferp buf)
  406.       (save-excursion
  407.         (set-buffer buf)
  408.         (copy-region-as-kill beg end)
  409.             ;; Eliminate replication on kill.
  410.             (setq this-command nil)
  411.       )
  412.     )
  413.       )
  414.     )
  415.     (setq epoch::selection-alist
  416.           (cons
  417.            (cons
  418.             mouse::selection-atom ""
  419.             )
  420.            (alist-delete mouse::selection-atom epoch::selection-alist)
  421.            ))
  422.     )
  423. )
  424.  
  425. (global-set-mouse mouse-left mouse-meta 'sec:start-mouse-region)
  426. (global-set-mouse mouse-middle mouse-meta 'sec:end-mouse-region)
  427. (global-set-mouse mouse-middle mouse-meta-up 'sec:mouse-paste-here)
  428.  
  429. (global-set-mouse mouse-left mouse-meta-shift 'sec:start-mouse-region)
  430. (global-set-mouse mouse-middle mouse-meta-shift 'sec:end-mouse-region)
  431. (global-set-mouse mouse-middle mouse-meta-shift-up 
  432.     'sec:mouse-paste-here-kill-there)
  433.  
  434. (global-set-mouse mouse-right mouse-meta-shift 'sec:end-mouse-region)
  435. (global-set-mouse mouse-right mouse-meta-shift-up 'sec:kill-there)
  436. (global-set-mouse mouse-right mouse-meta 'paste-there)
  437.  
  438.  
  439. ;;;;
  440. ;;;;
  441. ;;;; End of mouse customizations!
  442. ;;;;
  443. ;;;;
  444.  
  445.  
  446. ;; Incremental search
  447. ;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
  448.  
  449. ;; This file is part of GNU Emacs.
  450. ;; isearch.el with 2 lines changed by Bill Richter; the
  451. ;; (save-window-excursion ... ) is commented out 
  452.  
  453.  
  454. ;; GNU Emacs is free software; you can redistribute it and/or modify
  455. ;; it under the terms of the GNU General Public License as published by
  456. ;; the Free Software Foundation; either version 1, or (at your option)
  457. ;; any later version.
  458.  
  459. ;; GNU Emacs is distributed in the hope that it will be useful,
  460. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  461. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  462. ;; GNU General Public License for more details.
  463.  
  464. ;; You should have received a copy of the GNU General Public License
  465. ;; along with GNU Emacs; see the file COPYING.  If not, write to
  466. ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  467.  
  468. ; in loaddefs.el
  469. ;(defvar search-last-string ""
  470. ;  "Last string search for by a search command.
  471. ;This does not include direct calls to the primitive search functions,
  472. ;and does not include searches that are aborted.")
  473. ;(defvar search-last-regexp ""
  474. ;  "Last string searched for by a regexp search command.
  475. ;This does not include direct calls to the primitive search functions,
  476. ;and does not include searches that are aborted.")
  477. ;
  478. ;(defconst search-repeat-char ?\C-s
  479. ;  "Character to repeat incremental search forwards.")
  480. ;(defconst search-reverse-char ?\C-r
  481. ;  "Character to repeat incremental search backwards.")
  482. ;(defconst search-exit-char ?\e
  483. ;  "Character to exit incremental search.")
  484. ;(defconst search-delete-char ?\177
  485. ;  "Character to delete from incremental search string.")
  486. ;(defconst search-quote-char ?\C-q
  487. ;  "Character to quote special characters for incremental search.")
  488. ;(defconst search-yank-word-char ?\C-w
  489. ;  "Character to pull next word from buffer into search string.")
  490. ;(defconst search-yank-line-char ?\C-y
  491. ;  "Character to pull rest of line from buffer into search string.")
  492. ;(defconst search-exit-option t
  493. ;  "Non-nil means random control characters terminate incremental search.")
  494. ;
  495. ;(defvar search-slow-window-lines 1
  496. ;  "*Number of lines in slow search display windows.")
  497. ;(defconst search-slow-speed 1200
  498. ;  "*Highest terminal speed at which to use \"slow\" style incremental search.
  499. ;This is the style where a one-line window is created to show the line
  500. ;that the search has reached.")
  501.  
  502. ;; This function does all the work of incremental search.
  503. ;; The functions attached to ^R and ^S are trivial,
  504. ;; merely calling this one, but they are always loaded by default
  505. ;; whereas this file can optionally be autoloadable.
  506. ;; This is the only entry point in this file.
  507.  
  508. (defun isearch (forward &optional regexp)
  509.   (let ((search-string "")
  510.     (search-message "")
  511.     (cmds nil)
  512.     (success t)
  513.     (wrapped nil)
  514.     (barrier (point))
  515.     adjusted
  516.     (invalid-regexp nil)
  517.     (slow-terminal-mode (and (<= (baud-rate) search-slow-speed)
  518.                  (> (window-height)
  519.                     (* 4 search-slow-window-lines))))
  520.     (other-end nil)    ;Start of last match if fwd, end if backwd.
  521.     (small-window nil)        ;if t, using a small window
  522.     (found-point nil)        ;to restore point from a small window
  523.     ;; This is the window-start value found by the search.
  524.     (found-start nil)
  525.     (opoint (point))
  526.     (inhibit-quit t))  ;Prevent ^G from quitting immediately.
  527.     (isearch-push-state)
  528. ;   (save-window-excursion
  529.      (catch 'search-done
  530.        (while t
  531.      (or (>= unread-command-char 0)
  532.          (progn
  533.            (or (input-pending-p)
  534.            (isearch-message))
  535.            (if (and slow-terminal-mode
  536.             (not (or small-window (pos-visible-in-window-p))))
  537.            (progn
  538.              (setq small-window t)
  539.              (setq found-point (point))
  540.              (move-to-window-line 0)
  541.              (let ((window-min-height 1))
  542.                (split-window nil (if (< search-slow-window-lines 0)
  543.                          (1+ (- search-slow-window-lines))
  544.                        (- (window-height)
  545.                           (1+ search-slow-window-lines)))))
  546.              (if (< search-slow-window-lines 0)
  547.              (progn (vertical-motion (- 1 search-slow-window-lines))
  548.                 (set-window-start (next-window) (point))
  549.                 (set-window-hscroll (next-window)
  550.                             (window-hscroll))
  551.                 (set-window-hscroll (selected-window) 0))
  552.                (other-window 1))
  553.              (goto-char found-point)))))
  554.      (let ((char (if quit-flag
  555.              ?\C-g
  556.                (read-char))))
  557.        (setq quit-flag nil adjusted nil)
  558.        ;; Meta character means exit search.
  559.        (cond ((and (>= char 128)
  560.                search-exit-option)
  561.           (setq unread-command-char char)
  562.           (throw 'search-done t))
  563.          ((eq char search-exit-char)
  564.           ;; Esc means exit search normally.
  565.           ;; Except, if first thing typed, it means do nonincremental
  566.           (if (= 0 (length search-string))
  567.               (nonincremental-search forward regexp))
  568.           (throw 'search-done t))
  569.          ((= char ?\C-g)
  570.           ;; ^G means the user tried to quit.
  571.           (ding)
  572.           (discard-input)
  573.           (if success
  574.               ;; If search is successful, move back to starting point
  575.               ;; and really do quit.
  576.               (progn (goto-char opoint)
  577.                  (signal 'quit nil))
  578.             ;; If search is failing, rub out until it is once more
  579.             ;;  successful.
  580.             (while (not success) (isearch-pop))))
  581.          ((or (eq char search-repeat-char)
  582.               (eq char search-reverse-char))
  583.           (if (eq forward (eq char search-repeat-char))
  584.               ;; C-s in forward or C-r in reverse.
  585.               (if (equal search-string "")
  586.               ;; If search string is empty, use last one.
  587.               (setq search-string
  588.                 (if regexp
  589.                     search-last-regexp search-last-string)
  590.                 search-message
  591.                 (mapconcat 'text-char-description
  592.                        search-string ""))
  593.             ;; If already have what to search for, repeat it.
  594.             (or success
  595.                 (progn (goto-char (if forward (point-min) (point-max)))
  596.                    (setq wrapped t))))
  597.             ;; C-s in reverse or C-r in forward, change direction.
  598.             (setq forward (not forward)))
  599.           (setq barrier (point)) ; For subsequent \| if regexp.
  600.           (setq success t)
  601.           (or (equal search-string "")
  602.               (isearch-search))
  603.           (isearch-push-state))
  604.          ((= char search-delete-char)
  605.           ;; Rubout means discard last input item and move point
  606.           ;; back.  If buffer is empty, just beep.
  607.           (if (null (cdr cmds))
  608.               (ding)
  609.             (isearch-pop)))
  610.          (t
  611.           (cond ((or (eq char search-yank-word-char)
  612.                  (eq char search-yank-line-char))
  613.              ;; ^W means gobble next word from buffer.
  614.              ;; ^Y means gobble rest of line from buffer.
  615.              (let ((word (save-excursion
  616.                        (and (not forward) other-end
  617.                         (goto-char other-end))
  618.                        (buffer-substring
  619.                     (point)
  620.                     (save-excursion
  621.                       (if (eq char search-yank-line-char)
  622.                           (end-of-line)
  623.                         (forward-word 1))
  624.                       (point))))))
  625.                (if regexp
  626.                    (setq word (regexp-quote word)))
  627.                (setq search-string (concat search-string word)
  628.                  search-message
  629.                    (concat search-message
  630.                        (mapconcat 'text-char-description
  631.                               word "")))))
  632.              ;; Any other control char =>
  633.              ;;  unread it and exit the search normally.
  634.              ((and search-exit-option
  635.                    (/= char search-quote-char)
  636.                    (or (= char ?\177)
  637.                    (and (< char ? ) (/= char ?\t) (/= char ?\r))))
  638.               (setq unread-command-char char)
  639.               (throw 'search-done t))
  640.              (t
  641.               ;; Any other character => add it to the
  642.               ;;  search string and search.
  643.               (cond ((= char search-quote-char)
  644.                  (setq char (read-quoted-char
  645.                          (isearch-message t))))
  646.                 ((= char ?\r)
  647.                  ;; unix braindeath
  648.                  (setq char ?\n)))
  649.               (setq search-string (concat search-string
  650.                               (char-to-string char))
  651.                 search-message (concat search-message
  652.                                (text-char-description char)))))
  653.           (if (and (not success)
  654.                ;; unsuccessful regexp search may become
  655.                ;;  successful by addition of characters which
  656.                ;;  make search-string valid
  657.                (not regexp))
  658.               nil
  659.             ;; If a regexp search may have been made more
  660.             ;; liberal, retreat the search start.
  661.             ;; Go back to place last successful search started
  662.             ;; or to the last ^S/^R (barrier), whichever is nearer.
  663.             (and regexp success cmds
  664.              (cond ((and (memq char '(?* ??))
  665.                      ;; Don't treat *, ? as special
  666.                      ;; within [] or after \.
  667.                      (not (nth 6 (car cmds))))
  668.                 (setq adjusted t)
  669.                 ;; This used to use element 2
  670.                 ;; in a reverse search, but it seems that 5
  671.                 ;; (which is the end of the old match)
  672.                 ;; is better in that case too.
  673.                 (let ((cs (nth 5 ; old other-end.
  674.                            (car (cdr cmds)))))
  675.                   ;; (car cmds) is after last search;
  676.                   ;; (car (cdr cmds)) is from before it.
  677.                   (setq cs (or cs barrier))
  678.                   (goto-char
  679.                    (if forward
  680.                        (max cs barrier)
  681.                      (min cs barrier)))))
  682.                    ((eq char ?\|)
  683.                 (setq adjusted t)
  684.                 (goto-char barrier))))
  685.             ;; In reverse regexp search, adding a character at
  686.             ;; the end may cause zero or many more chars to be
  687.             ;; matched, in the string following point.
  688.             ;; Allow all those possibiities without moving point as
  689.             ;; long as the match does not extend past search origin.
  690.             (if (and regexp (not forward) (not adjusted)
  691.                  (condition-case ()
  692.                  (looking-at search-string)
  693.                    (error nil))
  694.                  (<= (match-end 0) (min opoint barrier)))
  695.             (setq success t invalid-regexp nil
  696.                   other-end (match-end 0))
  697.               ;; Not regexp, not reverse, or no match at point.
  698.               (if (and other-end (not adjusted))
  699.               (goto-char (if forward other-end
  700.                        (min opoint barrier (1+ other-end)))))
  701.               (isearch-search)))
  702.           (isearch-push-state))))))
  703.      (setq found-start (window-start (selected-window)))
  704.      (setq found-point (point))
  705. ;                   )
  706.     (if (> (length search-string) 0)
  707.     (if regexp
  708.         (setq search-last-regexp search-string)
  709.         (setq search-last-string search-string)))
  710.     ;; If we displayed a single-line window, set point in this window. 
  711.     (if small-window
  712.     (goto-char found-point))
  713.     ;; If there was movement, mark the starting position.
  714.     ;; Maybe should test difference between and set mark iff > threshold.
  715.     (if (/= (point) opoint)
  716.     (push-mark opoint)
  717.       (message ""))
  718.     (or small-window
  719.     ;; Exiting the save-window-excursion clobbers this; restore it.
  720.     (set-window-start (selected-window) found-start t))))
  721.  
  722. (defun isearch-message (&optional c-q-hack ellipsis)
  723.   ;; If about to search, and previous search regexp was invalid,
  724.   ;; check that it still is.  If it is valid now,
  725.   ;; let the message we display while searching say that it is valid.
  726.   (and invalid-regexp ellipsis
  727.        (condition-case ()
  728.        (progn (re-search-forward search-string (point) t)
  729.           (setq invalid-regexp nil))
  730.      (error nil)))
  731.   ;; If currently failing, display no ellipsis.
  732.   (or success (setq ellipsis nil))
  733.   (let ((m (concat (if success "" "failing ")
  734.            (if wrapped "wrapped ")
  735.            (if regexp "regexp " "")
  736.            "I-search"
  737.            (if forward ": " " backward: ")
  738.            search-message
  739.            (if c-q-hack "^Q" "")
  740.            (if invalid-regexp
  741.                (concat " [" invalid-regexp "]")
  742.              ""))))
  743.     (aset m 0 (upcase (aref m 0)))
  744.     (let ((cursor-in-echo-area ellipsis))
  745.       (if c-q-hack m (message "%s" m)))))
  746.  
  747. (defun isearch-pop ()
  748.   (setq cmds (cdr cmds))
  749.   (let ((cmd (car cmds)))
  750.     (setq search-string (car cmd)
  751.       search-message (car (cdr cmd))
  752.       success (nth 3 cmd)
  753.       forward (nth 4 cmd)
  754.       other-end (nth 5 cmd)
  755.       invalid-regexp (nth 6 cmd)
  756.       wrapped (nth 7 cmd)
  757.       barrier (nth 8 cmd))
  758.     (goto-char (car (cdr (cdr cmd))))))
  759.  
  760. (defun isearch-push-state ()
  761.   (setq cmds (cons (list search-string search-message (point)
  762.              success forward other-end invalid-regexp
  763.              wrapped barrier)
  764.            cmds)))
  765.  
  766. (defun isearch-search ()
  767.   (isearch-message nil t)
  768.   (condition-case lossage
  769.       (let ((inhibit-quit nil))
  770.     (if regexp (setq invalid-regexp nil))
  771.     (setq success
  772.           (funcall
  773.            (if regexp
  774.            (if forward 're-search-forward 're-search-backward)
  775.          (if forward 'search-forward 'search-backward))
  776.            search-string nil t))
  777.     (if success
  778.         (setq other-end
  779.           (if forward (match-beginning 0) (match-end 0)))))
  780.     (quit (setq unread-command-char ?\C-g)
  781.       (setq success nil))
  782.     (invalid-regexp (setq invalid-regexp (car (cdr lossage)))
  783.             (if (string-match "\\`Premature \\|\\`Unmatched \\|\\`Invalid "
  784.                       invalid-regexp)
  785.             (setq invalid-regexp "incomplete input"))))
  786.   (if success
  787.       nil
  788.     ;; Ding if failed this time after succeeding last time.
  789.     (and (nth 3 (car cmds))
  790.      (ding))
  791.     (goto-char (nth 2 (car cmds)))))
  792.  
  793. ;; This is called from incremental-search
  794. ;; if the first input character is the exit character.
  795. ;; The interactive-arg-reader uses free variables `forward' and `regexp'
  796. ;; which are bound by `incremental-search'.
  797.  
  798. ;; We store the search string in `search-string'
  799. ;; which has been bound already by `incremental-search'
  800. ;; so that, when we exit, it is copied into `search-last-string'.
  801.  
  802. (defun nonincremental-search (forward regexp)
  803.   (let (message char function string inhibit-quit)
  804.     (let ((cursor-in-echo-area t))
  805.       ;; Prompt assuming not word search,
  806.       (setq message (if regexp 
  807.             (if forward "Regexp search: "
  808.               "Regexp search backward: ")
  809.               (if forward "Search: " "Search backward: ")))
  810.       (message "%s" message)
  811.       ;; Read 1 char and switch to word search if it is ^W.
  812.       (setq char (read-char)))
  813.     (if (eq char search-yank-word-char)
  814.     (setq message (if forward "Word search: " "Word search backward: "))
  815.       ;; Otherwise let that 1 char be part of the search string.
  816.       (setq unread-command-char char))
  817.     (setq function
  818.       (if (eq char search-yank-word-char)
  819.           (if forward 'word-search-forward 'word-search-backward)
  820.         (if regexp
  821.         (if forward 're-search-forward 're-search-backward)
  822.           (if forward 'search-forward 'search-backward))))
  823.     ;; Read the search string with corrected prompt.
  824.     (setq string (read-string message))
  825.     (let ((var (if regexp 'search-last-regexp 'search-last-string)))
  826.       ;; Empty means use default.
  827.       (if (= 0 (length string))
  828.       (setq string (symbol-value var))
  829.     ;; Set last search string now so it is set even if we fail.
  830.     (set var string)))
  831.     ;; Since we used the minibuffer, we should be available for redo.
  832.     (setq command-history (cons (list function string) command-history))
  833.     ;; Go ahead and search.
  834.     (funcall function string)))
  835.  
  836.