home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / interfaces / mity-mouse / mity-mouse.el < prev    next >
Encoding:
Text File  |  1990-07-24  |  24.4 KB  |  732 lines

  1. ;From ark1!uakari!uflorida!novavax!hcx1!tom Mon Feb 26 14:51:25 1990
  2. ;Article 1489 of comp.emacs:
  3. ;Path: ark1!uakari!uflorida!novavax!hcx1!tom
  4. ;>From tom@ssd.csd.harris.com (Tom Horsley)
  5. ;Newsgroups: comp.emacs
  6. ;Subject: Additional X mouse functions (was Scrolling emacs windows under X...)
  7. ;Message-ID: <TOM.90Feb23070642@hcx2.ssd.csd.harris.com>
  8. ;Date: 23 Feb 90 12:06:42 GMT
  9. ;References: <52442@bbn.COM>
  10. ;Sender: news@hcx1.SSD.CSD.HARRIS.COM
  11. ;Organization: Harris Computer Systems Division
  12. ;Lines: 717
  13. ;In-reply-to: AMANDEL%BRUSP.ANSP.BR@UICVM.UIC.EDU's message of 21 Feb 90 12:29:38 GMT
  14. ;
  15. ;I have been thinking about posting this since I have not made any changes
  16. ;for a while and it seems to be pretty useful. Now that someone has asked
  17. ;about scrolling windows using a mouse, this is a good time. Note that the
  18. ;documentation refers to several other .el files. I don't believe that any of
  19. ;these are required to make this package work, they are merely other packages
  20. ;I have which use the mouse.
  21. ;
  22. ;The one package that *is* required is nuscroll.el, this is the scroll up and
  23. ;down in place code that was written by Joe Wells and posted quite some time
  24. ;ago. If you don't have it, or don't like it, all you have to do is modify
  25. ;the defuns for the x-mouse scrolling commands here to use the ordinary
  26. ;scroll functions rather than scroll up or down in place.
  27.  
  28. ; mighty-mouse.el:
  29. ;
  30. ; Additional mouse functions for gnuemacs under X
  31. ; Revision 2.4 Jan 5, 1990
  32. ;
  33. ; written by Tom Horsley (tahorsley@ssd.csd.harris.com)
  34. ;
  35. ; Additional functions by Bill Leonard - Jan 2, 1990
  36. ;
  37. ; source is in ~tom/gnuemacs/mighty-mouse.el
  38. ;
  39. ; Several routines are modifications of the distributed code in x-mouse.el
  40. ;
  41. ; Functions for positioning and scrolling point and windows.
  42. ;
  43. ; x-mouse-set-window-or-point
  44. ;   A replacement for x-mouse-set-point, this function will simply switch
  45. ;   windows if the mouse is in a different window, but not change point. To
  46. ;   change window and point, click twice.
  47. ;
  48. ; x-mouse-set-window-and-point
  49. ;   A replacement for the standard x-mouse-set-point routine which does not
  50. ;   work correctly in horizontally scrolled windows.
  51. ;
  52. ; x-mouse-remember
  53. ;   Bind this to button down on a key that you will bind something else to
  54. ;   button up on.
  55. ;
  56. ; x-mouse-drag-window
  57. ;   Bind this to button up on the same button that x-mouse-remember is bound
  58. ;   to button down on. The net effect is this. You push the button down
  59. ;   while sitting on a line in the window, move the mouse, then release the
  60. ;   button and the text in the window moves so the line you started on
  61. ;   scrolls to where the mouse is now. If you start the mouse on a mode line
  62. ;   or a boundary between vertically split windows it changes the size of
  63. ;   the windows rather than moving the text.
  64. ;
  65. ; x-mouse-scroll-down-in-place
  66. ;   Scrolls the window where the mouse is, using the scroll-down-in-place
  67. ;   function.
  68. ;
  69. ; x-mouse-scroll-up-in-place
  70. ;   Guess!
  71. ;
  72. ; x-mouse-copy-region
  73. ;   Copy region between mark and mouse.
  74. ;
  75. ; x-mouse-cut-region
  76. ;   Cut region between mark and mouse.
  77. ;
  78. ; x-mouse-insert-space
  79. ;   Insert a rectangle of space starting at the point the button was pushed
  80. ;   down and ending at the point the button was released (bind
  81. ;   x-mouse-remember to button down and x-mouse-insert-space to button up).
  82. ; Font changing functions - you may want to set some variables before
  83. ; loading this file and picking up the defaults:
  84. ;   x-mouse-font-list - list of font names in ascending font size
  85. ;   x-default-font-in-list - index of the default font in this list
  86. ;
  87. ; x-mouse-set-default-font
  88. ;   Set font to a specified default value.
  89. ;
  90. ; x-mouse-set-smaller-font
  91. ;   Set font to next smaller in a list of fonts
  92. ;
  93. ; x-mouse-set-bigger-font
  94. ;   Set font to next bigger in a list of fonts
  95. ;
  96. ; Local/global mouse map support:
  97. ;
  98. ; x-split-mouse-map
  99. ;   Split the mouse map into local and global mouse maps. After calling this
  100. ;   all define-key calls should be done with global-mouse-map.  If mouse-map
  101. ;   is modified, all hell will break loose.
  102. ;
  103. ; x-use-local-mouse-map
  104. ;   Setup a local mouse map, then pass it to this function to be used as the
  105. ;   local mouse map in the current buffer (typically this call is made in a
  106. ;   mode hook). Mouse buttons left un-defined will default to the
  107. ;   global-mouse-map function.
  108. ;
  109. ; Other functions:
  110. ;
  111. ; x-mouse-kill-buffer
  112. ;   Kill the buffer the mouse is pointing at. (Best to bind this to something
  113. ;   complicated like a Control Shift Meta combination.)
  114. ;
  115. ; x-mouse-kill-window
  116. ;   Kill the buffer the mouse is pointing at, and delete that window.
  117. ;
  118. ; The sample bindings I use are:
  119. ;
  120. ;   (define-key global-mouse-map x-button-left 'x-mouse-set-window-or-point)
  121. ;   (define-key global-mouse-map x-button-m-middle 'x-mouse-remember)
  122. ;   (define-key global-mouse-map x-button-m-middle-up 'x-mouse-drag-window)
  123. ;   (define-key global-mouse-map x-button-m-right 'x-mouse-scroll-down-in-place)
  124. ;   (define-key global-mouse-map x-button-m-left 'x-mouse-scroll-up-in-place)
  125. ;   (define-key global-mouse-map x-button-c-s-left 'x-mouse-set-smaller-font)
  126. ;   (define-key global-mouse-map x-button-c-s-middle 'x-mouse-set-default-font)
  127. ;   (define-key global-mouse-map x-button-c-s-right 'x-mouse-set-bigger-font)
  128. ;   (define-key global-mouse-map x-button-c-m-s-right 'x-mouse-kill-buffer)
  129. ;   (define-key global-mouse-map x-button-c-right 'x-mouse-remember)
  130. ;   (define-key global-mouse-map x-button-c-right-up 'x-mouse-insert-space)
  131. ;
  132. ; Other files of interest:
  133. ;
  134. ; mouse-help.el
  135. ;   Print reasonable description of the mouse map.
  136. ;
  137. ; buff-setup.el, buff-mouse.el
  138. ;   Provide functions for use in binding keys to the mouse in buffer menu mode.
  139. ;
  140. ; nuscroll.el
  141. ;   Contains the scroll-down/up-in-place functions used by the mouse window
  142. ;   scroller functions.
  143. ;
  144. ; info-mouse.el, info-setup.el
  145. ;   These files contain functions that make use of the local mouse map to
  146. ;   setup an info browser controlled by the mouse.
  147.  
  148. (provide 'mighty-mouse)
  149.  
  150. (require 'x-mouse)
  151.  
  152. (defun test-position-in-window (abspos winedge)
  153. "Test the position ABSPOS against the window edge list WINEDGE.
  154. Return nil if not in window, or ((col row) status) if in window, where status
  155. is 'on-mode-line if on mode line of window, 'on-right-edge if on the right
  156. edge of a vertically split window or 'in-window if inside window somewhere."
  157.    (let
  158.       (
  159.          (abscol (nth 0 abspos))
  160.          (absrow (nth 1 abspos))
  161.          (winleftcol (nth 0 winedge))
  162.          (wintoprow (nth 1 winedge))
  163.          (winrightcol (nth 2 winedge))
  164.          (winbottomrow (nth 3 winedge))
  165.          (status nil)
  166.       )
  167.       (if (and
  168.              (< absrow winbottomrow)
  169.              (>= absrow wintoprow)
  170.              (< abscol winrightcol)
  171.              (>= abscol winleftcol)
  172.           )
  173.          ; If the window only has one line, it cannot have a mode line so
  174.          ; don't check for mode line in that case. (This really only happens
  175.          ; in the minibuffer, but this test should always work.)
  176.          (if (= wintoprow (1- winbottomrow))
  177.             (setq status 'in-window)
  178.          ; else
  179.             (if (= absrow (1- winbottomrow))
  180.                (setq status 'on-mode-line)
  181.             ; else
  182.                ; if the window does not extend all the way to the screen
  183.                ; edge then check for being on the right edge divider.
  184.                (if (and (= abscol (1- winrightcol))
  185.                         (not (= (screen-width) winrightcol))
  186.                    )
  187.                   (setq status 'on-right-edge)
  188.                ; else
  189.                   (setq status 'in-window)
  190.                )
  191.             )
  192.          )
  193.       )
  194.       (if status
  195.          (list (list (- abscol winleftcol) (- absrow wintoprow)) status)
  196.       ; else
  197.          nil
  198.       )
  199.    )
  200. )
  201.  
  202. (defun get-window-position-config (arg minibuf)
  203. "Return relative window position of absolute screen position.
  204. Checks ARG, a list that looks like (col row) against all the windows and
  205. returns (window (rel-col rel-row) status) giving relative position.  Arg
  206. MINIBUF t means always count the minibuffer window, nil means count
  207. minibuffer only if active, and anything else means never count the
  208. minibuffer."
  209.    (let
  210.       (
  211.          cwin
  212.          (swin (selected-window))
  213.          curstat
  214.       )
  215.       (setq cwin swin)
  216.       (setq curstat (test-position-in-window arg (window-edges cwin)))
  217.       (while (not (or curstat (eq (setq cwin (next-window cwin minibuf)) swin)))
  218.          (setq curstat (test-position-in-window arg (window-edges cwin)))
  219.       )
  220.       (if curstat
  221.          (cons cwin curstat)
  222.       ; else
  223.          nil
  224.       )
  225.    )
  226. )
  227.  
  228. (defun x-get-mouse-window-and-pos (arg)
  229. "Return a list (window (window-x window-y)) giving the mouse window
  230. and relative position in window."
  231.    (get-window-position-config arg nil)
  232. )
  233.  
  234. (defun x-mouse-set-window-or-point (arg)
  235. "Select Emacs window mouse is on, if same as current window move point to
  236. mouse location, otherwise just select the window."
  237.    (let*
  238.       (
  239.          (mouse-pos-info (x-get-mouse-window-and-pos arg))
  240.          (mouse-win-info (car mouse-pos-info))
  241.          (cur-win-info (selected-window))
  242.          (relative-coordinate (car (cdr mouse-pos-info)))
  243.      (rel-x (car relative-coordinate))
  244.      (rel-y (car (cdr relative-coordinate)))
  245.       )
  246.       (if (eq mouse-win-info cur-win-info)
  247.          (if relative-coordinate
  248.             (progn
  249.                (move-to-window-line rel-y)
  250.                (move-to-column
  251.                   (+ rel-x
  252.                      ; Adding in current-column fixes things for lines
  253.                      ; that wrap.
  254.                      (current-column)
  255.                      ; Adding in windwo-hscroll fixes things for
  256.                      ; horizontally scrolled windows.
  257.                      (if (> (window-hscroll) 0) (1- (window-hscroll)) 0)
  258.                      ; Scrolled and wrapped lines probably don't work
  259.                   )
  260.                )
  261.             )
  262.          )
  263.       ; else
  264.          (if mouse-win-info
  265.             (select-window mouse-win-info)
  266.          )
  267.       )
  268.    )
  269. )
  270.  
  271. (defun x-mouse-set-window-and-point (arg)
  272. "Select Emacs window mouse is on, and move cursor to mouse position."
  273.    (let*
  274.       (
  275.          (mouse-pos-info (x-get-mouse-window-and-pos arg))
  276.          (mouse-win-info (car mouse-pos-info))
  277.          (cur-win-info (selected-window))
  278.          (relative-coordinate (car (cdr mouse-pos-info)))
  279.      (rel-x (car relative-coordinate))
  280.      (rel-y (car (cdr relative-coordinate)))
  281.       )
  282.       (if relative-coordinate
  283.          (progn
  284.             (select-window mouse-win-info)
  285.             (move-to-window-line rel-y)
  286.             (move-to-column
  287.                (+ rel-x
  288.                   ; Adding in current-column fixes things for lines
  289.                   ; that wrap.
  290.                   (current-column)
  291.                   ; Adding in windwo-hscroll fixes things for
  292.                   ; horizontally scrolled windows.
  293.                   (if (> (window-hscroll) 0) (1- (window-hscroll)) 0)
  294.                   ; Scrolled and wrapped lines probably don't work
  295.                )
  296.             )
  297.          )
  298.       )
  299.    )
  300. )
  301.  
  302. (defvar x-mouse-remember-original-window nil
  303. "Variable recording window where x-mouse-remember happened."
  304. )
  305.  
  306. (defvar x-mouse-remember-original-x-pos nil
  307. "Variable recording window X position where x-mouse-remember happened."
  308. )
  309.  
  310. (defvar x-mouse-remember-original-y-pos nil
  311. "Variable recording window Y position where x-mouse-remember happened."
  312. )
  313.  
  314. (defvar x-mouse-remember-original-status nil
  315. "Variable that remembers original mouse position status."
  316. )
  317.  
  318. (defun x-mouse-remember (arg)
  319. "This function is designed to be bound to button down events, so another
  320. function (bound to button up) can then do something depending on the
  321. amount the mouse has moved."
  322.    (let
  323.       (
  324.          (mpos (x-get-mouse-window-and-pos arg))
  325.       )
  326.       (setq x-mouse-remember-original-x-pos (car arg))
  327.       (setq x-mouse-remember-original-y-pos (car (cdr arg)))
  328.       (setq x-mouse-remember-original-window (nth 0 mpos))
  329.       (setq x-mouse-remember-original-status (nth 2 mpos))
  330.    )
  331. )
  332.  
  333. (defun x-mouse-drag-window (arg)
  334. "Scroll x-mouse-remember-original-window by the number of lines
  335. between the current mouse position and x-mouse-remember-original-y-pos.
  336. If the mouse starts on a mode like or vertical boundary, simply change
  337. the window size."
  338.    (let
  339.       (
  340.          (initial-window (selected-window))
  341.          (current-y-pos (nth 1 arg))
  342.          (current-x-pos (nth 0 arg))
  343.          lines
  344.       )
  345.       (cond
  346.          ((eq x-mouse-remember-original-status 'in-window)
  347.             (if (and
  348.                     x-mouse-remember-original-y-pos
  349.                     current-y-pos
  350.                     x-mouse-remember-original-window
  351.                 )
  352.                (unwind-protect
  353.                   (progn
  354.                      (setq lines
  355.                         (- x-mouse-remember-original-y-pos current-y-pos)
  356.                      )
  357.                      (select-window x-mouse-remember-original-window)
  358.                      (cond
  359.                         ((> lines 0)
  360.                            (scroll-up lines)
  361.                         )
  362.                         ((< lines 0)
  363.                            (scroll-down (- lines))
  364.                         )
  365.                      )
  366.                   )
  367.                   (select-window initial-window)
  368.                )
  369.             )
  370.          )
  371.          ((eq x-mouse-remember-original-status 'on-mode-line)
  372.             (if (and
  373.                     x-mouse-remember-original-y-pos
  374.                     current-y-pos
  375.                     x-mouse-remember-original-window
  376.                 )
  377.                (unwind-protect
  378.                   (progn
  379.                      (setq lines
  380.                         (- current-y-pos x-mouse-remember-original-y-pos)
  381.                      )
  382.                      (select-window x-mouse-remember-original-window)
  383.                      (enlarge-window lines)
  384.                   )
  385.                   (select-window initial-window)
  386.                )
  387.             )
  388.          )
  389.          ((eq x-mouse-remember-original-status 'on-right-edge)
  390.             (if (and
  391.                     x-mouse-remember-original-x-pos
  392.                     current-x-pos
  393.                     x-mouse-remember-original-window
  394.                 )
  395.                (unwind-protect
  396.                   (progn
  397.                      (setq lines
  398.                         (- current-x-pos x-mouse-remember-original-x-pos)
  399.                      )
  400.                      (select-window x-mouse-remember-original-window)
  401.                      (enlarge-window lines t)
  402.                   )
  403.                   (select-window initial-window)
  404.                )
  405.             )
  406.          )
  407.       )
  408.    )
  409. )
  410.  
  411. (defun x-mouse-scroll-down-in-place (arg)
  412. "Run scroll-down-in-place on the window the mouse is in."
  413.    (let
  414.       (
  415.          (mouse-window (car (x-get-mouse-window-and-pos arg)))
  416.          (initial-window (selected-window))
  417.       )
  418.       (if mouse-window
  419.          (unwind-protect
  420.             (progn
  421.                (select-window mouse-window)
  422.                (scroll-down-in-place nil)
  423.             )
  424.             (select-window initial-window)
  425.          )
  426.       )
  427.    )
  428. )
  429.  
  430. (defun x-mouse-scroll-up-in-place (arg)
  431. "Run scroll-up-in-place on the window the mouse is in."
  432.    (let
  433.       (
  434.          (mouse-window (car (x-get-mouse-window-and-pos arg)))
  435.          (initial-window (selected-window))
  436.       )
  437.       (if mouse-window
  438.          (unwind-protect
  439.             (progn
  440.                (select-window mouse-window)
  441.                (scroll-up-in-place nil)
  442.             )
  443.             (select-window initial-window)
  444.          )
  445.       )
  446.    )
  447. )
  448.  
  449. (defun x-mouse-copy-region (arg)
  450. "Copy text between mark and mouse position into window system cut buffer.
  451. Save in Emacs kill ring also.  Cursor is displayed at mouse position
  452. for one second."
  453.    (let*
  454.       (
  455.          (mouse-pos-info (x-get-mouse-window-and-pos arg))
  456.          (mouse-window (car mouse-pos-info))
  457.       )
  458.       (if mouse-window
  459.          (unwind-protect
  460.             (progn
  461.                (save-excursion
  462.                   (x-mouse-set-point arg)
  463.                   (x-store-cut-buffer (buffer-substring (mark) (point)))
  464.                   (copy-region-as-kill (mark) (point))
  465.                   (sit-for 1)
  466.                )
  467.             )
  468.          )
  469.       )
  470.    )
  471. )
  472.  
  473. (defun x-mouse-cut-region (arg)
  474. "Cut text between mark and mouse position into window system cut buffer.
  475. Save in Emacs kill ring also.  Cursor is displayed at mouse position
  476. for one second."
  477.    (let*
  478.       (
  479.          (mouse-pos-info (x-get-mouse-window-and-pos arg))
  480.          (mouse-window (car mouse-pos-info))
  481.       )
  482.       (if mouse-window
  483.          (unwind-protect
  484.             (progn
  485.                (save-excursion
  486.                   (x-mouse-set-point arg)
  487.                   (x-store-cut-buffer (buffer-substring (mark) (point)))
  488.                   (kill-region (mark) (point))
  489.                   (sit-for 1)
  490.                )
  491.             )
  492.          )
  493.       )
  494.    )
  495. )
  496.  
  497. (defun x-mouse-insert-space (arg)
  498. "Insert a rectangle of space starting at the button down position
  499. and ending at the button up positon."
  500.    (let
  501.       (
  502.          (cur-mouse-col (nth 0 arg))
  503.          (cur-mouse-row (nth 1 arg))
  504.          left-col
  505.          right-col
  506.          bottom-row
  507.          top-row
  508.          mouse-tl-pos
  509.          mouse-br-pos
  510.       )
  511.       (setq left-col (min cur-mouse-col x-mouse-remember-original-x-pos))
  512.       (setq right-col (max cur-mouse-col x-mouse-remember-original-x-pos))
  513.       (setq top-row (min cur-mouse-row x-mouse-remember-original-y-pos))
  514.       (setq bottom-row (max cur-mouse-row x-mouse-remember-original-y-pos))
  515.       (setq mouse-tl-pos
  516.          (x-get-mouse-window-and-pos (list left-col top-row))
  517.       )
  518.       (setq mouse-br-pos
  519.          (x-get-mouse-window-and-pos (list right-col bottom-row))
  520.       )
  521.       (if (equal (nth 0 mouse-tl-pos) (nth 0 mouse-br-pos))
  522.          (progn
  523.             (setq save-window (selected-window))
  524.             (save-excursion
  525.                (unwind-protect
  526.                   (let
  527.                      (
  528.                         (rel-lc (nth 0 (nth 1 mouse-tl-pos)))
  529.                         (rel-rc (nth 0 (nth 1 mouse-br-pos)))
  530.                         (rel-tr (nth 1 (nth 1 mouse-tl-pos)))
  531.                         (rel-br (nth 1 (nth 1 mouse-br-pos)))
  532.                      )
  533.                      (select-window (nth 0 mouse-tl-pos))
  534.                      (while (<= rel-tr rel-br)
  535.                         (move-to-window-line rel-tr)
  536.                         (move-to-column (+ rel-lc (current-column)))
  537.                         (if (= (current-column) rel-lc)
  538.                            (indent-to-column rel-rc)
  539.                         )
  540.                         (setq rel-tr (1+ rel-tr))
  541.                      )
  542.                   )
  543.                   (select-window save-window)
  544.                )
  545.             )
  546.          )
  547.       )
  548.    )
  549. )
  550.  
  551. (defvar x-mouse-font-list
  552.    (list
  553.       "-adobe-courier-medium-o-normal--8-80-75-75-m-50-iso8859-1"
  554.       "-adobe-courier-bold-o-normal--10-100-75-75-m-60-iso8859-1"
  555.       "-adobe-courier-bold-r-normal--12-120-75-75-m-70-iso8859-1"
  556.       "-adobe-courier-medium-r-normal--14-140-75-75-m-90-iso8859-1"
  557.       "-adobe-courier-medium-r-normal--18-180-75-75-m-110-iso8859-1"
  558.       "-adobe-courier-medium-r-normal--24-240-75-75-m-150-iso8859-1"
  559.    )
  560. "*List of fonts to cycle through, should be arranged smallest to largest."
  561. )
  562.  
  563. (defvar x-default-font-in-list 4
  564. "*Index in x-mouse-font-list of default font to use."
  565. )
  566.  
  567. (defvar x-current-font-in-list x-default-font-in-list)
  568.  
  569. (defun x-mouse-set-default-font (arg)
  570. "Set the font to the normal default."
  571.    (x-set-font (nth x-default-font-in-list x-mouse-font-list))
  572.    (setq x-current-font-in-list x-default-font-in-list)
  573. )
  574.  
  575. (defun x-mouse-set-smaller-font (arg)
  576. "Pick a smaller font from list of defaults."
  577.    (if (equal x-current-font-in-list 0)
  578.       (error "The font is as small as it gets!")
  579.       (setq x-current-font-in-list (1- x-current-font-in-list))
  580.       (x-set-font (nth x-current-font-in-list x-mouse-font-list))
  581.    )
  582. )
  583.  
  584. (defun x-mouse-set-bigger-font (arg)
  585. "Pick a biger font from the list of defaults."
  586.    (if (equal x-current-font-in-list (1- (length x-mouse-font-list)))
  587.       (error "The font is as big as it gets!")
  588.       (setq x-current-font-in-list (1+ x-current-font-in-list))
  589.       (x-set-font (nth x-current-font-in-list x-mouse-font-list))
  590.    )
  591. )
  592.  
  593. (defun x-mouse-kill-buffer (arg)
  594. "Kill the buffer the mouse is pointing at."
  595.    (let
  596.       (
  597.          (mouse-window (car (x-get-mouse-window-and-pos arg)))
  598.       )
  599.       (if mouse-window
  600.          (kill-buffer (window-buffer mouse-window))
  601.       )
  602.    )
  603. )
  604.  
  605. (defun x-mouse-kill-window (arg)
  606. "Kill the buffer the mouse is pointing at and delete that window (unless it
  607. is the only window)."
  608.    (let*
  609.       (
  610.          (mouse-window (car (x-get-mouse-window-and-pos arg)))
  611.          (mouse-buffer (window-buffer mouse-window))
  612.       )
  613.       (if mouse-window
  614.          (progn
  615.             (if (not (one-window-p t))
  616.                (delete-window mouse-window)
  617.             )
  618.             (kill-buffer mouse-buffer)
  619.          )
  620.       )
  621.    )
  622. )
  623.  
  624. ; The following functions provide support for separate local and global
  625. ; mouse maps. Run x-split-mouse-maps to activate the functionality.
  626.  
  627. (defvar x-mouse-maps-already-split nil
  628. "Used so x-split-mouse-maps will run only once"
  629. )
  630. (defvar local-mouse-map (make-keymap)
  631. "Keymap used once the mouse maps are split to hold local mouse bindings."
  632. )
  633. (make-variable-buffer-local 'local-mouse-map)
  634.  
  635. ;; The x-mouse-route-click function is used to route mouse clicks to the
  636. ;; appropriate local/global map depending on which one is non-nil.
  637. ;;
  638. ;; NOTE: Possibly the route function should determine which window the mouse
  639. ;; is in, and look at its local-mouse-map, but currently it does not do
  640. ;; that. It should not be too hard to do, I am just not sure if it is really
  641. ;; what I want.
  642.  
  643. (defun x-mouse-route-click (arg)
  644. "Invoke function in local-mouse-map if that is defined, else invoke function
  645. in global-mouse-map. The local-mouse-map should be a buffer local variable
  646. set when the mode is set."
  647.    (let
  648.       (
  649.          (last-click x-mouse-item)
  650.          (mouse-click-function nil)
  651.       )
  652.       (if (and (boundp 'local-mouse-map) (vectorp local-mouse-map))
  653.          (setq mouse-click-function (aref local-mouse-map last-click))
  654.       )
  655.       (if (and (not mouse-click-function)
  656.                (boundp 'global-mouse-map)
  657.                (vectorp global-mouse-map))
  658.          (setq mouse-click-function (aref global-mouse-map last-click))
  659.       )
  660.       (if mouse-click-function
  661.          (if (eq mouse-click-function 'x-mouse-route-click)
  662.             (error "Recursive mouse function loop!")
  663.             (funcall mouse-click-function arg)
  664.          )
  665.          (error "")
  666.       )
  667.    )
  668. )
  669.  
  670. (defun x-split-mouse-maps ()
  671. "x-split-mouse-maps provides support for separate local and global mouse
  672. maps.  It works by copying the current mouse-map bindings to
  673. global-mouse-map and making local-mouse-map a buffer local variable. It then
  674. replaces mouse-map with a vector in which each entry simply invokes
  675. x-mouse-route-click to route the last mouse action to the local-mouse-map,
  676. or if it is nil to the global-mouse-map. Once this function is called
  677. you MUST NOT modify mouse-map, do your define key calls on global-mouse-map."
  678.    (interactive)
  679.    (if x-mouse-maps-already-split
  680.       nil ; ignore multiple calls
  681.    ; else first call
  682.       (setq x-mouse-maps-already-split t)
  683.       (setq global-mouse-map (copy-keymap mouse-map))
  684.       (let
  685.          (
  686.             (key 0)
  687.          )
  688.          (while (< key 128)
  689.             (define-key mouse-map (char-to-string key) 'x-mouse-route-click)
  690.             (setq key (1+ key))
  691.          )
  692.       )
  693.    )
  694. )
  695.  
  696. (defun x-use-local-mouse-map (map)
  697. "Used to define values for local mouse map. Sets the local-mouse-map to
  698. the input keymap. If the input keymap is a sparse map, transforms it into
  699. a vector which the routing function expects."
  700.    (let
  701.       (
  702.          new-map
  703.          one-key
  704.          keys
  705.       )
  706.       ; first make sure we have split the mouse maps
  707.       (x-split-mouse-maps)
  708.       ; then define the local map
  709.       (if (and (not (vectorp map)) (keymapp map))
  710.          (progn
  711.             ; This must be a sparse map, go through it and vectorize it
  712.             (setq new-map (make-vector 128 nil))
  713.             (setq keys (cdr map))
  714.             (while keys
  715.                (setq one-key (car keys))
  716.                (setq keys (cdr keys))
  717.                (aset new-map (car one-key) (cdr one-key))
  718.             )
  719.          )
  720.          (setq new-map map)
  721.       )
  722.       (setq local-mouse-map (copy-keymap new-map))
  723.    )
  724. )
  725. ;--
  726. ;=====================================================================
  727. ;domain: tahorsley@ssd.csd.harris.com  USMail: Tom Horsley
  728. ;  uucp: ...!novavax!hcx1!tahorsley            511 Kingbird Circle
  729. ;      or  ...!uunet!hcx1!tahorsley            Delray Beach, FL  33444
  730. ;======================== Aging: Just say no! ========================
  731.