(x-select-enable-clipboard): New variable.
[bpt/emacs.git] / lisp / menu-bar.el
CommitLineData
235aa29b
ER
1;;; menu-bar.el --- define a default menu bar.
2
3;; Author: RMS
b7f66977 4;; Keywords: internal
235aa29b 5
03dcd202 6;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
1db87953
RS
7
8;; This file is part of GNU Emacs.
9
10;; GNU Emacs is free software; you can redistribute it and/or modify
11;; it under the terms of the GNU General Public License as published by
12;; the Free Software Foundation; either version 2, or (at your option)
13;; any later version.
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
21;; along with GNU Emacs; see the file COPYING. If not, write to
22;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23
235aa29b 24;;; Code:
1db87953 25
b132f2b1
RM
26;; Don't clobber an existing menu-bar keymap, to preserve any menu-bar key
27;; definitions made in loaddefs.el.
28(or (lookup-key global-map [menu-bar])
29 (define-key global-map [menu-bar] (make-sparse-keymap "menu-bar")))
22390f50 30(defvar menu-bar-help-menu (make-sparse-keymap "Help"))
da183f87
RS
31;; Put Help item last.
32(setq menu-bar-final-items '(help))
33(define-key global-map [menu-bar help] (cons "Help" menu-bar-help-menu))
22390f50 34(defvar menu-bar-edit-menu (make-sparse-keymap "Edit"))
40954111 35(define-key global-map [menu-bar edit] (cons "Edit" menu-bar-edit-menu))
22390f50 36(defvar menu-bar-file-menu (make-sparse-keymap "File"))
40954111 37(define-key global-map [menu-bar file] (cons "File" menu-bar-file-menu))
db774a16 38
ca9b40a1 39(define-key menu-bar-file-menu [exit-emacs]
db774a16 40 '("Exit Emacs" . save-buffers-kill-emacs))
2f1139a4
RS
41(define-key menu-bar-file-menu [kill-buffer]
42 '("Kill Buffer" . kill-this-buffer))
43(define-key menu-bar-file-menu [delete-frame] '("Delete Frame" . delete-frame))
966bcddd 44(define-key menu-bar-file-menu [emerge] '("Emerge" . menu-bar-emerge-menu))
661b05a7
RS
45(define-key menu-bar-file-menu [calendar] '("Calendar" . calendar))
46(define-key menu-bar-file-menu [rmail] '("Read Mail" . rmail))
47(define-key menu-bar-file-menu [gnus] '("Read Net News" . gnus))
9d441895 48(define-key menu-bar-file-menu [bookmark]
966bcddd 49 '("Bookmarks" . menu-bar-bookmark-map))
2f1139a4
RS
50(define-key menu-bar-file-menu [print-buffer] '("Print Buffer" . print-buffer))
51(define-key menu-bar-file-menu [revert-buffer]
52 '("Revert Buffer" . revert-buffer))
53(define-key menu-bar-file-menu [write-file]
54 '("Save Buffer As..." . write-file))
55(define-key menu-bar-file-menu [save-buffer] '("Save Buffer" . save-buffer))
76202b57 56(define-key menu-bar-file-menu [dired] '("Open Directory..." . dired))
2f1139a4
RS
57(define-key menu-bar-file-menu [open-file] '("Open File..." . find-file))
58(define-key menu-bar-file-menu [new-frame] '("New Frame" . new-frame))
db774a16 59
966bcddd 60(define-key menu-bar-edit-menu [spell] '("Spell" . ispell-menu-map))
057d49d1
RS
61(define-key menu-bar-edit-menu [fill] '("Fill" . fill-region))
62(define-key menu-bar-edit-menu [clear] '("Clear" . delete-region))
33aa8946
RS
63(define-key menu-bar-edit-menu [query-replace]
64 '("Query Replace" . query-replace))
50d195ee
RS
65(define-key menu-bar-edit-menu [re-search-back]
66 '("Regexp Search Backwards" . re-search-backward))
67(define-key menu-bar-edit-menu [search-back]
68 '("Search Backwards" . search-backward))
69(define-key menu-bar-edit-menu [re-search-fwd]
70 '("Regexp Search" . re-search-forward))
71(define-key menu-bar-edit-menu [search-fwd]
72 '("Search" . search-forward))
75340584 73(define-key menu-bar-edit-menu [choose-next-paste]
f7f19201 74 '("Choose Next Paste >" . mouse-menu-choose-yank))
057d49d1
RS
75(define-key menu-bar-edit-menu [paste] '("Paste" . yank))
76(define-key menu-bar-edit-menu [copy] '("Copy" . kill-ring-save))
77(define-key menu-bar-edit-menu [cut] '("Cut" . kill-region))
78(define-key menu-bar-edit-menu [undo] '("Undo" . undo))
79
80(put 'fill-region 'menu-enable 'mark-active)
81(put 'kill-region 'menu-enable 'mark-active)
82(put 'kill-ring-save 'menu-enable 'mark-active)
83(put 'yank 'menu-enable '(x-selection-exists-p))
84(put 'delete-region 'menu-enable 'mark-active)
85(put 'undo 'menu-enable '(if (eq last-command 'undo)
86 pending-undo-list
87 (consp buffer-undo-list)))
33aa8946 88(put 'query-replace 'menu-enable (not buffer-read-only))
db774a16 89
9e18f0a0
RS
90(autoload 'ispell-menu-map "ispell" nil t 'keymap)
91
ca9b40a1 92(define-key menu-bar-help-menu [emacs-tutorial]
db774a16 93 '("Emacs Tutorial" . help-with-tutorial))
2f1139a4
RS
94(define-key menu-bar-help-menu [man] '("Man..." . manual-entry))
95(define-key menu-bar-help-menu [describe-variable]
96 '("Describe Variable..." . describe-variable))
97(define-key menu-bar-help-menu [describe-function]
98 '("Describe Function..." . describe-function))
99(define-key menu-bar-help-menu [describe-key]
100 '("Describe Key..." . describe-key))
101(define-key menu-bar-help-menu [list-keybindings]
102 '("List Keybindings" . describe-bindings))
103(define-key menu-bar-help-menu [command-apropos]
104 '("Command Apropos..." . command-apropos))
105(define-key menu-bar-help-menu [describe-mode]
106 '("Describe Mode" . describe-mode))
107(define-key menu-bar-help-menu [info] '("Info" . info))
db774a16 108
2f1139a4 109(define-key menu-bar-help-menu [emacs-news] '("Emacs News" . view-emacs-news))
db774a16
RS
110(defun kill-this-buffer () ; for the menubar
111 "Kills the current buffer."
112 (interactive)
113 (kill-buffer (current-buffer)))
114
2f1139a4
RS
115(defun kill-this-buffer-enabled-p ()
116 (let ((count 0)
117 (buffers (buffer-list)))
118 (while buffers
119 (or (string-match "^ " (buffer-name (car buffers)))
120 (setq count (1+ count)))
121 (setq buffers (cdr buffers)))
122 (> count 1)))
123
db774a16 124(put 'save-buffer 'menu-enable '(buffer-modified-p))
da183f87
RS
125(put 'revert-buffer 'menu-enable
126 '(or revert-buffer-function revert-buffer-insert-file-contents-function
127 (and (buffer-file-name)
660fa562
RM
128 (or (buffer-modified-p)
129 (not (verify-visited-file-modtime (current-buffer)))))))
a0213a97
RS
130;; Permit deleting frame if it would leave a visible or iconified frame.
131(put 'delete-frame 'menu-enable
132 '(let ((frames (frame-list))
133 (count 0))
134 (while frames
135 (if (cdr (assq 'visibility (frame-parameters (car frames))))
136 (setq count (1+ count)))
137 (setq frames (cdr frames)))
138 (> count 1)))
2f1139a4
RS
139(put 'kill-this-buffer 'menu-enable '(kill-this-buffer-enabled-p))
140
db774a16
RS
141(put 'advertised-undo 'menu-enable
142 '(and (not (eq t buffer-undo-list))
143 (if (eq last-command 'undo)
2f1139a4
RS
144 (and (boundp 'pending-undo-list)
145 pending-undo-list)
146 buffer-undo-list)))
2877eac2
RS
147
148(defvar yank-menu-length 100
149 "*Maximum length of an item in the menu for \
150\\[mouse-menu-choose-yank].")
151
152(defun mouse-menu-choose-yank (event)
153 "Pop up a menu of the kill-ring for selection with the mouse.
154The kill-ring-yank-pointer is moved to the selected element.
155A subsequent \\[yank] yanks the choice just selected."
156 (interactive "e")
157 (let* ((count 0)
158 (menu (mapcar (lambda (string)
159 (if (> (length string) yank-menu-length)
160 (setq string (substring string
161 0 yank-menu-length)))
162 (prog1 (cons string count)
163 (setq count (1+ count))))
dfabc98f
RM
164 kill-ring))
165 (arg (x-popup-menu event
166 (list "Yank Menu"
75340584 167 (cons "Choose Next Yank" menu)))))
dfabc98f
RM
168 ;; A mouse click outside the menu returns nil.
169 ;; Avoid a confusing error from passing nil to rotate-yank-pointer.
170 ;; XXX should this perhaps do something other than simply return? -rm
171 (if arg
172 (progn
03dcd202
RM
173 ;; We don't use `rotate-yank-pointer' because we want to move
174 ;; relative to the beginning of kill-ring, not the current
175 ;; position. Also, that would ask for any new X selection and
176 ;; thus change the list of items the user just chose from, which
177 ;; would be highly confusing.
178 (setq kill-ring-yank-pointer (nthcdr arg kill-ring))
dfabc98f
RM
179 (if (interactive-p)
180 (message "The next yank will insert the selected text.")
181 (current-kill 0))))))
182(put 'mouse-menu-choose-yank 'menu-enable 'kill-ring)
40954111 183\f
98bee59b 184(define-key global-map [menu-bar buffer] '("Buffers" . mouse-menu-bar-buffers))
40954111
RS
185
186(defvar complex-buffers-menu-p nil
187 "*Non-nil says, offer a choice of actions after you pick a buffer.
188This applies to the Buffers menu from the menu bar.")
189
190(defvar buffers-menu-max-size 10
191 "*Maximum number of entries which may appear on the Buffers menu.
192If this is 10, then only the ten most-recently-selected buffers are shown.
193If this is nil, then all buffers are shown.
194A large number or nil slows down menu responsiveness.")
195
d0690d12
RS
196(defvar list-buffers-directory nil)
197
98bee59b 198(defun mouse-menu-bar-buffers (event)
40954111
RS
199 "Pop up a menu of buffers for selection with the mouse.
200This switches buffers in the window that you clicked on,
201and selects that window."
202 (interactive "e")
203 (let ((buffers (buffer-list))
204 menu)
205 ;; If requested, list only the N most recently selected buffers.
206 (if (and (integerp buffers-menu-max-size)
207 (> buffers-menu-max-size 1))
208 (if (> (length buffers) buffers-menu-max-size)
209 (setcdr (nthcdr buffers-menu-max-size buffers) nil)))
210 (setq menu
e936d399
RM
211 (cons "Select Buffer"
212 (let ((tail buffers)
213 (maxbuf 0)
214 (maxlen 0)
215 head)
216 (while tail
217 (or (eq ?\ (aref (buffer-name (car tail)) 0))
218 (setq maxbuf
219 (max maxbuf
220 (length (buffer-name (car tail))))))
221 (setq tail (cdr tail)))
222 (setq tail buffers)
223 (while tail
224 (let ((elt (car tail)))
225 (if (not (string-match "^ "
226 (buffer-name elt)))
227 (setq head (cons
228 (cons
229 (format
230 (format "%%%ds %%s%%s %%s"
231 maxbuf)
232 (buffer-name elt)
233 (if (buffer-modified-p elt)
234 "*" " ")
235 (save-excursion
236 (set-buffer elt)
237 (if buffer-read-only "%" " "))
75e4aa06
RS
238 (or (buffer-file-name elt)
239 (save-excursion
240 (set-buffer elt)
241 list-buffers-directory)
242 ""))
e936d399
RM
243 elt)
244 head)))
245 (and head (> (length (car (car head))) maxlen)
246 (setq maxlen (length (car (car head))))))
247 (setq tail (cdr tail)))
248 (nconc (nreverse head)
249 (list (cons
250 (concat (make-string (max (- (/ maxlen
251 2)
252 8)
253 0) ?\ )
254 "List All Buffers")
255 'list-buffers))))))
256 (setq menu (list menu))
40954111 257
e936d399
RM
258 (if (cdr (frame-list))
259 (setq menu
260 (cons (cons "Select Frame"
261 (mapcar (lambda (frame)
262 (cons (cdr (assq 'name
263 (frame-parameters frame)))
264 frame))
265 (frame-list)))
266 menu)))
267 (setq menu (cons "Buffer and Frame Menu" menu))
40954111
RS
268
269 (let ((buf (x-popup-menu (if (listp event) event
ea0633d4 270 (list '(0 0) (selected-frame)))
40954111
RS
271 menu))
272 (window (and (listp event) (posn-window (event-start event)))))
e936d399
RM
273 (cond ((framep buf)
274 (make-frame-visible buf)
275 (raise-frame buf)
276 (select-frame buf))
277 ((eq buf 'list-buffers)
278 (list-buffers))
279 (buf
280 (if complex-buffers-menu-p
281 (let ((action (x-popup-menu
282 (if (listp event) event
ea0633d4 283 (list '(0 0) (selected-frame)))
e936d399
RM
284 '("Buffer Action"
285 (""
286 ("Save Buffer" . save-buffer)
287 ("Kill Buffer" . kill-buffer)
288 ("Select Buffer" . switch-to-buffer))))))
289 (if (eq action 'save-buffer)
290 (save-excursion
291 (set-buffer buf)
292 (save-buffer))
293 (funcall action buf)))
294 (and (windowp window)
295 (select-window window))
296 (switch-to-buffer buf)))))))
2f1139a4 297
40954111
RS
298;; this version is too slow
299;;;(defun format-buffers-menu-line (buffer)
300;;; "Returns a string to represent the given buffer in the Buffer menu.
301;;;nil means the buffer shouldn't be listed. You can redefine this."
302;;; (if (string-match "\\` " (buffer-name buffer))
303;;; nil
304;;; (save-excursion
305;;; (set-buffer buffer)
306;;; (let ((size (buffer-size)))
307;;; (format "%s%s %-19s %6s %-15s %s"
308;;; (if (buffer-modified-p) "*" " ")
309;;; (if buffer-read-only "%" " ")
310;;; (buffer-name)
311;;; size
312;;; mode-name
313;;; (or (buffer-file-name) ""))))))
314\f
057d49d1 315(defun menu-bar-mode (flag)
dfd29450 316 "Toggle display of a menu bar on each frame.
057d49d1
RS
317This command applies to all frames that exist and frames to be
318created in the future.
319With a numeric argument, if the argument is negative,
dfd29450 320turn off menu bars; otherwise, turn on menu bars."
dad8e392 321 (interactive "P")
dad8e392
RM
322
323 ;; Obtain the current setting by looking at default-frame-alist.
324 (let ((menu-bar-mode
325 (not (zerop (let ((assq (assq 'menu-bar-lines default-frame-alist)))
326 (if assq (cdr assq) 0))))))
327
328 ;; Tweedle it according to the argument.
329 (setq menu-bar-mode (if (null flag) (not menu-bar-mode)
e48f95c9 330 (> (prefix-numeric-value flag) 0)))
dad8e392
RM
331
332 ;; Apply it to default-frame-alist.
333 (let ((parameter (assq 'menu-bar-lines default-frame-alist)))
334 (if (consp parameter)
335 (setcdr parameter (if menu-bar-mode 1 0))
336 (setq default-frame-alist
337 (cons (cons 'menu-bar-lines (if menu-bar-mode 1 0))
338 default-frame-alist))))
339
340 ;; Apply it to existing frames.
341 (let ((frames (frame-list)))
342 (while frames
343 (modify-frame-parameters (car frames)
344 (list (cons 'menu-bar-lines
345 (if menu-bar-mode 1 0))))
346 (setq frames (cdr frames))))))
1db87953
RS
347
348;; Make frames created from now on have a menu bar.
d0dbd3bf
RS
349(if window-system
350 (menu-bar-mode t))
1db87953 351
bffa5d4d
RS
352(provide 'menu-bar)
353
235aa29b 354;;; menu-bar.el ends here