]> code.delx.au - gnu-emacs/blobdiff - lisp/mouse.el
When compiling, require compare-w and skeleton
[gnu-emacs] / lisp / mouse.el
index 8d3c775c7ecabeb317d6cd6807947c65ec3a1f5b..47ede180693cf884d4699462d39fc38474d75d2c 100644 (file)
@@ -49,6 +49,8 @@
   ;; Switch to the window clicked on, because otherwise
   ;; the mode's commands may not make sense.
   (interactive "@e\nP")
+  ;; Let the mode update its menus first.
+  (run-hooks 'activate-menubar-hook)
   (let (;; This is where mouse-major-mode-menu-prefix
        ;; returns the prefix we should use (after menu-bar).
        ;; It is either nil or (SOME-SYMBOL).
 
 (defun mouse-delete-window (click)
   "Delete the window you click on.
-This must be bound to a mouse click."
+If the frame has just one window, bury the current buffer instead.
+This command must be bound to a mouse click."
   (interactive "e")
-  (mouse-minibuffer-check click)
-  (delete-window (posn-window (event-start click))))
+  (if (one-window-p t)
+      (bury-buffer)
+    (mouse-minibuffer-check click)
+    (delete-window (posn-window (event-start click)))))
 
 (defun mouse-select-window (click)
   "Select the window clicked on; don't move point."
@@ -312,12 +317,12 @@ This command must be bound to a mouse click."
              'right)))
     (if (one-window-p t)
        (error "Attempt to resize sole ordinary window"))
-    (if (eq which-side 'left)
-       (if (= (nth 0 (window-edges start-event-window)) 0)
-           (error "Attempt to drag leftmost scrollbar"))
-      (if (= (nth 2 (window-edges start-event-window))
-            (frame-width start-event-frame))
-         (error "Attempt to drag rightmost scrollbar")))
+    (if (eq which-side 'right)
+       (if (= (nth 2 (window-edges start-event-window))
+              (frame-width start-event-frame))
+           (error "Attempt to drag rightmost scrollbar"))
+      (if (= (nth 0 (window-edges start-event-window)) 0)
+         (error "Attempt to drag leftmost scrollbar")))
     (track-mouse
       (progn
        ;; enlarge-window only works on the selected window, so
@@ -358,10 +363,10 @@ This command must be bound to a mouse click."
                 (save-selected-window
                   ;; If the scroll bar is on the window's left,
                   ;; adjust the window on the left.
-                  (if (eq which-side 'left)
-                      (select-window (previous-window)))
+                  (unless (eq which-side 'right)
+                    (select-window (previous-window)))
                   (setq x (- (car (cdr mouse))
-                             (if (eq which-side 'left) 2 0))
+                             (if (eq which-side 'right) 0 2))
                         edges (window-edges)
                         left (nth 0 edges)
                         right (nth 2 edges))
@@ -582,6 +587,25 @@ remains active.  Otherwise, it remains until the next input event."
                  (mouse-scroll-subr start-window (1+ (- mouse-row bottom))
                                     mouse-drag-overlay start-point)
                  (setq end-of-range (overlay-end mouse-drag-overlay))))))))))
+      ;; In case we did not get a mouse-motion event
+      ;; for the final move of the mouse before a drag event
+      ;; pretend that we did get one.
+      (when (and (memq 'drag (event-modifiers (car-safe event)))
+                (setq end (event-end event)
+                      end-point (posn-point end))
+                (eq (posn-window end) start-window)
+                (integer-or-marker-p end-point))
+
+       ;; Go to START-POINT first, so that when we move to END-POINT,
+       ;; if it's in the middle of intangible text,
+       ;; point jumps in the direction away from START-POINT.
+       (goto-char start-point)
+       (goto-char end-point)
+       (if (zerop (% click-count 3))
+           (setq end-of-range (point)))
+       (let ((range (mouse-start-end start-point (point) click-count)))
+         (move-overlay mouse-drag-overlay (car range) (nth 1 range))))
+
       (if (consp event)
          (let ((fun (key-binding (vector (car event)))))
            ;; Run the binding of the terminating up-event, if possible.
@@ -634,7 +658,18 @@ remains active.  Otherwise, it remains until the next input event."
 If DIR is positive skip forward; if negative, skip backward."
   (let* ((char (following-char))
         (syntax (char-to-string (char-syntax char))))
-    (cond ((or (string= syntax "w") (string= syntax " "))
+    (cond ((string= syntax "w")
+          ;; Here, we can't use skip-syntax-forward/backward because
+          ;; they don't pay attention to word-separating-categories,
+          ;; and thus they will skip over a true word boundary.  So,
+          ;; we simularte the original behaviour by using
+          ;; forward-word.
+          (if (< dir 0)
+              (if (not (looking-at "\\<"))
+                  (forward-word -1))
+            (if (or (looking-at "\\<") (not (looking-at "\\>")))
+                (forward-word 1))))
+         ((string= syntax " ")
           (if (< dir 0)
               (skip-syntax-backward syntax)
             (skip-syntax-forward syntax)))
@@ -1310,6 +1345,17 @@ If we have lots of buffers, divide them into groups of
   :type 'integer
   :group 'mouse)
 
+(defcustom mouse-buffer-menu-mode-mult 4
+  "*Group the buffers by the major mode groups on \\[mouse-buffer-menu]?
+This number which determines (in a hairy way) whether \\[mouse-buffer-menu]
+will split the buffer menu by the major modes (see
+`mouse-buffer-menu-mode-groups') or just by menu length.
+Set to 1 (or even 0!) if you want to group by major mode always, and to
+a large number if you prefer a mixed multitude.  The default is 4."
+  :type 'integer
+  :group 'mouse
+  :version "20.3")
+
 (defvar mouse-buffer-menu-mode-groups
   '(("Info\\|Help\\|Apropos\\|Man" . "Help")
     ("\\bVM\\b\\|\\bMH\\b\\|Message\\|Mail\\|Group\\|Score\\|Summary\\|Article"
@@ -1329,8 +1375,7 @@ This switches buffers in the window that you clicked on,
 and selects that window."
   (interactive "e")
   (mouse-minibuffer-check event)
-  (let (buffers alist menu split-by-major-mode sum-of-squares)
-    (setq buffers (buffer-list))
+  (let ((buffers (buffer-list))  alist menu split-by-major-mode sum-of-squares)
     ;; Make an alist of elements that look like (MENU-ITEM . BUFFER).
     (let ((tail buffers))
       (while tail
@@ -1359,10 +1404,10 @@ and selects that window."
       (while tail
        (setq sum-of-squares
              (+ sum-of-squares
-                (* (length (cdr (cdr (car tail))))
-                   (length (cdr (cdr (car tail)))))))
+                (let ((len (length (cdr (cdr (car tail)))))) (* len len))))
        (setq tail (cdr tail))))
-    (if (< (* sum-of-squares 4) (* (length buffers) (length buffers)))
+    (if (< (* sum-of-squares mouse-buffer-menu-mode-mult)
+          (* (length buffers) (length buffers)))
        ;; Subdividing by major modes really helps, so let's do it.
        (let (subdivided-menus (buffers-left (length buffers)))
          ;; Sort the list to put the most popular major modes first.
@@ -1392,23 +1437,20 @@ and selects that window."
                    (cons (cons
                           "Others"
                           (mouse-buffer-menu-alist
-                           (apply 'append
-                                  (mapcar 'cdr
-                                          (mapcar 'cdr split-by-major-mode)))))
+                           ;; we don't need split-by-major-mode any
+                           ;; more, so we can ditch it with nconc.
+                           (apply 'nconc (mapcar 'cddr split-by-major-mode))))
                          subdivided-menus)))
-         (setq subdivided-menus
-               (nreverse subdivided-menus))
-         (setq menu (cons "Buffer Menu" subdivided-menus)))
+         (setq menu (cons "Buffer Menu" (nreverse subdivided-menus))))
       (progn
        (setq alist (mouse-buffer-menu-alist buffers))
        (setq menu (cons "Buffer Menu"
                         (mouse-buffer-menu-split "Select Buffer" alist)))))
     (let ((buf (x-popup-menu event menu))
          (window (posn-window (event-start event))))
-      (if buf
-         (progn
+      (when buf
            (or (framep window) (select-window window))
-           (switch-to-buffer buf))))))
+       (switch-to-buffer buf)))))
 
 (defun mouse-buffer-menu-alist (buffers)
   (let (tail