;;; mouse.el --- window system-independent mouse support
;; Copyright (C) 1993, 1994, 1995, 1999, 2000, 2001, 2002, 2003,
-;; 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+;; 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
;; Maintainer: FSF
;; Keywords: hardware, mouse
;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; mouse-major-mode-menu was using `command-execute' instead.
(call-interactively cmd))))
+(defun minor-mode-menu-from-indicator (indicator)
+ "Show menu, if any, for minor mode specified by INDICATOR.
+Interactively, INDICATOR is read using completion."
+ (interactive (list (completing-read "Minor mode indicator: "
+ (describe-minor-mode-completion-table-for-indicator))))
+ (let ((minor-mode (lookup-minor-mode-from-indicator indicator)))
+ (if minor-mode
+ (let* ((map (cdr-safe (assq minor-mode minor-mode-map-alist)))
+ (menu (and (keymapp map) (lookup-key map [menu-bar]))))
+ (if menu
+ (popup-menu menu)
+ (message "No menu for minor mode `%s'" minor-mode)))
+ (error "Cannot find minor mode for `%s'" indicator))))
+
+(defun mouse-minor-mode-menu (event)
+ "Show minor-mode menu for EVENT on minor modes area of the mode line."
+ (interactive "@e")
+ (let ((indicator (car (nth 4 (car (cdr event))))))
+ (minor-mode-menu-from-indicator indicator)))
+
(defvar mouse-major-mode-menu-prefix) ; dynamically bound
(defun mouse-major-mode-menu (event &optional prefix)
;; Make a keymap in which our last command leads to a menu or
;; default to the edit menu.
(newmap (if ancestor
- (make-sparse-keymap (concat mode-name " Mode"))
- menu-bar-edit-menu)))
+ (make-sparse-keymap (concat (format-mode-line mode-name)
+ " Mode"))
+ menu-bar-edit-menu))
+ uniq)
(if ancestor
;; Make our menu inherit from the desired keymap which we want
;; to display as the menu now.
- (set-keymap-parent newmap ancestor))
+ ;; Sometimes keymaps contain duplicate menu code, leading to
+ ;; duplicates in the popped-up menu. Avoid this by simply
+ ;; taking the first of any identically-named menus.
+ ;; http://lists.gnu.org/archive/html/emacs-devel/2007-11/msg00469.html
+ (set-keymap-parent newmap
+ (progn
+ (dolist (e ancestor)
+ (unless (and (listp e)
+ (assoc (car e) uniq))
+ (setq uniq (append uniq (list e)))))
+ uniq)))
(popup-menu newmap event prefix)))
(or (null local-menu)
(stringp local-title-or-map)
(setq local-menu (cons 'keymap
- (cons (concat mode-name " Mode Menu")
+ (cons (concat (format-mode-line mode-name)
+ " Mode Menu")
(cdr local-menu)))))
(or (stringp global-title-or-map)
(setq global-menu (cons 'keymap
(setq mouse-selection-click-count 0)
(yank arg))
+(defun mouse-yank-primary (click)
+ "Insert the primary selection at the position clicked on.
+Move point to the end of the inserted text.
+If `mouse-yank-at-point' is non-nil, insert at point
+regardless of where you click."
+ (interactive "e")
+ ;; Give temporary modes such as isearch a chance to turn off.
+ (run-hooks 'mouse-leave-buffer-hook)
+ (or mouse-yank-at-point (mouse-set-point click))
+ (let ((primary (x-get-selection 'PRIMARY)))
+ (if primary
+ (insert (x-get-selection 'PRIMARY))
+ (error "No primary selection"))))
+
(defun mouse-kill-ring-save (click)
"Copy the region between point and the mouse click in the kill ring.
This does not delete the region; it acts like \\[kill-ring-save]."
;; Give temporary modes such as isearch a chance to turn off.
(run-hooks 'mouse-leave-buffer-hook)
(or mouse-yank-at-point (mouse-set-point click))
- (insert (x-get-selection 'SECONDARY)))
+ (let ((secondary (x-get-selection 'SECONDARY)))
+ (if secondary
+ (insert (x-get-selection 'SECONDARY))
+ (error "No secondary selection"))))
(defun mouse-kill-secondary ()
"Kill the text in the secondary selection.
(mouse-minibuffer-check event)
(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
- ;; Divide all buffers into buckets for various major modes.
- ;; Each bucket looks like (MODE NAMESTRING BUFFERS...).
- (with-current-buffer (car tail)
- (let* ((adjusted-major-mode major-mode) elt)
- (let ((tail mouse-buffer-menu-mode-groups))
- (while tail
- (if (string-match (car (car tail)) mode-name)
- (setq adjusted-major-mode (cdr (car tail))))
- (setq tail (cdr tail))))
- (setq elt (assoc adjusted-major-mode split-by-major-mode))
- (if (null elt)
- (setq elt (list adjusted-major-mode
- (if (stringp adjusted-major-mode)
- adjusted-major-mode
- mode-name))
- split-by-major-mode (cons elt split-by-major-mode)))
- (or (memq (car tail) (cdr (cdr elt)))
- (setcdr (cdr elt) (cons (car tail) (cdr (cdr elt)))))))
- (setq tail (cdr tail))))
+ (dolist (buf buffers)
+ ;; Divide all buffers into buckets for various major modes.
+ ;; Each bucket looks like (MODE NAMESTRING BUFFERS...).
+ (with-current-buffer buf
+ (let* ((adjusted-major-mode major-mode) elt)
+ (dolist (group mouse-buffer-menu-mode-groups)
+ (when (string-match (car group) (format-mode-line mode-name))
+ (setq adjusted-major-mode (cdr group))))
+ (setq elt (assoc adjusted-major-mode split-by-major-mode))
+ (unless elt
+ (setq elt (list adjusted-major-mode
+ (if (stringp adjusted-major-mode)
+ adjusted-major-mode
+ (format-mode-line mode-name nil nil buf)))
+ split-by-major-mode (cons elt split-by-major-mode)))
+ (or (memq buf (cdr (cdr elt)))
+ (setcdr (cdr elt) (cons buf (cdr (cdr elt))))))))
;; Compute the sum of squares of sizes of the major-mode buckets.
(let ((tail split-by-major-mode))
(setq sum-of-squares 0)
(cons
(cons
(format
- (format "%%%ds %%s%%s %%s" maxlen)
+ (format "%%-%ds %%s%%s %%s" maxlen)
(buffer-name elt)
(if (buffer-modified-p elt) "*" " ")
(save-excursion