(Fread_file_name): Correct handling of dollars in file
[bpt/emacs.git] / lisp / menu-bar.el
CommitLineData
235aa29b
ER
1;;; menu-bar.el --- define a default menu bar.
2
b578f267
EN
3;; Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
4
235aa29b 5;; Author: RMS
e4874521 6;; Maintainer: FSF
b7f66977 7;; Keywords: internal
235aa29b 8
1db87953
RS
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
13;; the Free Software Foundation; either version 2, or (at your option)
14;; any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
b578f267
EN
22;; along with GNU Emacs; see the file COPYING. If not, write to the
23;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24;; Boston, MA 02111-1307, USA.
1db87953 25
260130bb
KH
26;; Avishai Yacobi suggested some menu rearrangements.
27
b578f267
EN
28;;; Code:
29
d537086b
RS
30;;; User options:
31
30e19aee 32(defcustom buffers-menu-max-size 10
d537086b
RS
33 "*Maximum number of entries which may appear on the Buffers menu.
34If this is 10, then only the ten most-recently-selected buffers are shown.
35If this is nil, then all buffers are shown.
30e19aee
RS
36A large number or nil slows down menu responsiveness."
37 :type '(choice integer
38 (const :tag "All" nil))
39 :group 'mouse)
d537086b 40
b132f2b1
RM
41;; Don't clobber an existing menu-bar keymap, to preserve any menu-bar key
42;; definitions made in loaddefs.el.
43(or (lookup-key global-map [menu-bar])
44 (define-key global-map [menu-bar] (make-sparse-keymap "menu-bar")))
22390f50 45(defvar menu-bar-help-menu (make-sparse-keymap "Help"))
ffbdd83d
RS
46
47;; Force Help item to come last, after the major mode's own items.
0d31efcd
KH
48;; The symbol used to be called `help', but that gets confused with the
49;; help key.
50(setq menu-bar-final-items '(help-menu))
ffbdd83d 51
0d31efcd 52(define-key global-map [menu-bar help-menu] (cons "Help" menu-bar-help-menu))
ffbdd83d
RS
53(defvar menu-bar-search-menu (make-sparse-keymap "Search"))
54(define-key global-map [menu-bar search] (cons "Search" menu-bar-search-menu))
22390f50 55(defvar menu-bar-edit-menu (make-sparse-keymap "Edit"))
40954111 56(define-key global-map [menu-bar edit] (cons "Edit" menu-bar-edit-menu))
ffbdd83d
RS
57(defvar menu-bar-tools-menu (make-sparse-keymap "Tools"))
58(define-key global-map [menu-bar tools] (cons "Tools" menu-bar-tools-menu))
59(defvar menu-bar-files-menu (make-sparse-keymap "Files"))
60(define-key global-map [menu-bar files] (cons "Files" menu-bar-files-menu))
1b009b97
RS
61
62;; This alias is for compatibility with 19.28 and before.
63(defvar menu-bar-file-menu menu-bar-files-menu)
9bb8e471 64\f
9dcdc43d
RS
65(defvar vc-menu-map (make-sparse-keymap "Version Control"))
66
147f1d2a
RS
67(define-key menu-bar-tools-menu [gdb] '("Debugger..." . gdb))
68(define-key menu-bar-tools-menu [compile] '("Compile..." . compile))
69(define-key menu-bar-tools-menu [grep] '("Search Files..." . grep))
70
71(define-key menu-bar-tools-menu [separator-1]
72 '("--"))
73
e1726722 74(define-key menu-bar-tools-menu [calendar] '("Display Calendar" . calendar))
850b7aa7
SM
75(define-key menu-bar-tools-menu [speedbar]
76 '("Display Speedbar" . speedbar-frame-mode))
c0965058 77(define-key menu-bar-tools-menu [compose-mail] '("Send Mail" . compose-mail))
ffbdd83d 78(define-key menu-bar-tools-menu [rmail] '("Read Mail" . rmail))
96a699d0 79(define-key menu-bar-tools-menu [gnus] '("Read Net News" . gnus))
ffbdd83d
RS
80
81(define-key menu-bar-tools-menu [separator-vc]
82 '("--"))
83
fe74180c 84(define-key menu-bar-tools-menu [vc]
ffbdd83d 85 (cons "Version Control" vc-menu-map))
9bb8e471 86
ffbdd83d 87(define-key menu-bar-tools-menu [separator-compare]
9bb8e471
RS
88 '("--"))
89
dd824ce4
MK
90(define-key menu-bar-tools-menu [ediff-misc]
91 '("Ediff Miscellanea" . menu-bar-ediff-misc-menu))
ffbdd83d 92(define-key menu-bar-tools-menu [epatch]
080ac1ac 93 '("Apply Patch" . menu-bar-epatch-menu))
ffbdd83d 94(define-key menu-bar-tools-menu [ediff-merge]
5438ecd3 95 '("Merge" . menu-bar-ediff-merge-menu))
57eed34a 96(define-key menu-bar-tools-menu [compare]
40a8cde1 97 '("Compare" . menu-bar-ediff-menu))
9bb8e471 98
ffbdd83d 99(define-key menu-bar-tools-menu [separator-print]
9bb8e471
RS
100 '("--"))
101
24f86c2f 102(defvar menu-bar-print-menu (make-sparse-keymap "Print"))
ffbdd83d 103
24f86c2f 104(define-key menu-bar-print-menu [ps-print-region]
ffbdd83d 105 '("Postscript Print Region" . ps-print-region-with-faces))
24f86c2f 106(define-key menu-bar-print-menu [ps-print-buffer]
ffbdd83d 107 '("Postscript Print Buffer" . ps-print-buffer-with-faces))
24f86c2f
SM
108(define-key menu-bar-print-menu [separator-ps-print]
109 '("--"))
110(define-key menu-bar-print-menu [print-region]
ffbdd83d 111 '("Print Region" . print-region))
24f86c2f 112(define-key menu-bar-print-menu [print-buffer]
ffbdd83d 113 '("Print Buffer" . print-buffer))
24f86c2f
SM
114
115(define-key menu-bar-tools-menu [print]
116 (cons "Print" menu-bar-print-menu))
117
118(put 'print-region 'menu-enable 'mark-active)
119(put 'ps-print-region-with-faces 'menu-enable 'mark-active)
ffbdd83d
RS
120\f
121(define-key menu-bar-files-menu [exit-emacs]
122 '("Exit Emacs" . save-buffers-kill-emacs))
123
124(define-key menu-bar-files-menu [separator-exit]
125 '("--"))
126
127(define-key menu-bar-files-menu [one-window]
128 '("One Window" . delete-other-windows))
129
130(define-key menu-bar-files-menu [split-window]
131 '("Split Window" . split-window-vertically))
9bb8e471 132
ca1a9692
RS
133(if (fboundp 'delete-frame)
134 (progn
a4e4b916
RS
135 ;; Don't use delete-frame as event name
136 ;; because that is a special event.
137 (define-key menu-bar-files-menu [delete-this-frame]
ca1a9692 138 '("Delete Frame" . delete-frame))
ffbdd83d
RS
139 (define-key menu-bar-files-menu [make-frame-on-display]
140 '("Open New Display..." . make-frame-on-display))
141 (define-key menu-bar-files-menu [make-frame]
dbe82e01 142 '("Make New Frame" . make-frame-command))))
9bb8e471 143
ffbdd83d 144(define-key menu-bar-files-menu [separator-buffers]
9bb8e471
RS
145 '("--"))
146
ffbdd83d
RS
147(define-key menu-bar-files-menu [kill-buffer]
148 '("Kill Current Buffer" . kill-this-buffer))
149(define-key menu-bar-files-menu [insert-file]
1f50590a 150 '("Insert File..." . insert-file))
f3e1e0dd
RS
151(define-key menu-bar-files-menu [recover-session]
152 '("Recover Session..." . recover-session))
ffbdd83d 153(define-key menu-bar-files-menu [revert-buffer]
2f1139a4 154 '("Revert Buffer" . revert-buffer))
ffbdd83d 155(define-key menu-bar-files-menu [write-file]
2f1139a4 156 '("Save Buffer As..." . write-file))
ffbdd83d
RS
157(define-key menu-bar-files-menu [save-buffer] '("Save Buffer" . save-buffer))
158(define-key menu-bar-files-menu [dired] '("Open Directory..." . dired))
159(define-key menu-bar-files-menu [open-file] '("Open File..." . find-file))
40a8cde1 160
f3e1e0dd
RS
161(put 'recover-session 'menu-enable
162 '(and auto-save-list-file-prefix
163 (directory-files
164 (file-name-directory auto-save-list-file-prefix)
165 nil
166 (concat "\\`"
167 (regexp-quote (file-name-nondirectory
168 auto-save-list-file-prefix)))
169 t)))
9bb8e471 170\f
ffbdd83d
RS
171(defun nonincremental-search-forward (string)
172 "Read a string and search for it nonincrementally."
173 (interactive "sSearch for string: ")
174 (if (equal string "")
175 (search-forward (car search-ring))
176 (isearch-update-ring string nil)
177 (search-forward string)))
178
179(defun nonincremental-search-backward (string)
180 "Read a string and search backward for it nonincrementally."
181 (interactive "sSearch for string: ")
182 (if (equal string "")
183 (search-backward (car search-ring))
184 (isearch-update-ring string nil)
185 (search-backward string)))
186
187(defun nonincremental-re-search-forward (string)
188 "Read a regular expression and search for it nonincrementally."
189 (interactive "sSearch for regexp: ")
190 (if (equal string "")
191 (re-search-forward (car regexp-search-ring))
192 (isearch-update-ring string t)
193 (re-search-forward string)))
194
195(defun nonincremental-re-search-backward (string)
196 "Read a regular expression and search backward for it nonincrementally."
197 (interactive "sSearch for regexp: ")
198 (if (equal string "")
199 (re-search-backward (car regexp-search-ring))
200 (isearch-update-ring string t)
201 (re-search-backward string)))
202
1f50590a 203(defun nonincremental-repeat-search-forward ()
ffbdd83d
RS
204 "Search forward for the previous search string."
205 (interactive)
008c8493
RS
206 (if (null search-ring)
207 (error "No previous search"))
ffbdd83d
RS
208 (search-forward (car search-ring)))
209
1f50590a 210(defun nonincremental-repeat-search-backward ()
ffbdd83d
RS
211 "Search backward for the previous search string."
212 (interactive)
008c8493
RS
213 (if (null search-ring)
214 (error "No previous search"))
ffbdd83d
RS
215 (search-backward (car search-ring)))
216
1f50590a 217(defun nonincremental-repeat-re-search-forward ()
ffbdd83d
RS
218 "Search forward for the previous regular expression."
219 (interactive)
97565dd9 220 (if (null regexp-search-ring)
008c8493 221 (error "No previous search"))
ffbdd83d
RS
222 (re-search-forward (car regexp-search-ring)))
223
1f50590a 224(defun nonincremental-repeat-re-search-backward ()
ffbdd83d
RS
225 "Search backward for the previous regular expression."
226 (interactive)
97565dd9 227 (if (null regexp-search-ring)
008c8493 228 (error "No previous search"))
ffbdd83d
RS
229 (re-search-backward (car regexp-search-ring)))
230
1f50590a
RS
231(define-key menu-bar-search-menu [query-replace-regexp]
232 '("Query Replace Regexp..." . query-replace-regexp))
ffbdd83d 233(define-key menu-bar-search-menu [query-replace]
1f50590a 234 '("Query Replace..." . query-replace))
ffbdd83d 235(define-key menu-bar-search-menu [find-tag]
1f50590a 236 '("Find Tag..." . find-tag))
ffbdd83d
RS
237(define-key menu-bar-search-menu [bookmark]
238 '("Bookmarks" . menu-bar-bookmark-map))
239
240(define-key menu-bar-search-menu [separator-search]
241 '("--"))
242
fe74180c 243(define-key menu-bar-search-menu [repeat-regexp-back]
ffbdd83d 244 '("Repeat Regexp Backwards" . nonincremental-repeat-re-search-backward))
fe74180c 245(define-key menu-bar-search-menu [repeat-search-back]
ffbdd83d 246 '("Repeat Backwards" . nonincremental-repeat-search-backward))
fe74180c 247(define-key menu-bar-search-menu [repeat-regexp-fwd]
ffbdd83d 248 '("Repeat Regexp" . nonincremental-repeat-re-search-forward))
fe74180c 249(define-key menu-bar-search-menu [repeat-search-fwd]
ffbdd83d
RS
250 '("Repeat Search" . nonincremental-repeat-search-forward))
251
252(define-key menu-bar-search-menu [separator-repeat]
9bb8e471
RS
253 '("--"))
254
fe74180c 255(define-key menu-bar-search-menu [re-search-backward]
1f50590a 256 '("Regexp Search Backwards..." . nonincremental-re-search-backward))
fe74180c 257(define-key menu-bar-search-menu [search-backward]
1f50590a 258 '("Search Backwards..." . nonincremental-search-backward))
fe74180c 259(define-key menu-bar-search-menu [re-search-forward]
1f50590a 260 '("Regexp Search..." . nonincremental-re-search-forward))
fe74180c 261(define-key menu-bar-search-menu [search-forward]
1f50590a 262 '("Search..." . nonincremental-search-forward))
ffbdd83d 263\f
5b42ec2b
RS
264(if (fboundp 'start-process)
265 (define-key menu-bar-edit-menu [spell] '("Spell" . ispell-menu-map)))
9bb8e471 266(define-key menu-bar-edit-menu [fill] '("Fill" . fill-region))
6507ffb1 267(define-key menu-bar-edit-menu [props] '("Text Properties" . facemenu-menu))
9bb8e471
RS
268
269(define-key menu-bar-edit-menu [separator-edit]
270 '("--"))
271
272(define-key menu-bar-edit-menu [clear] '("Clear" . delete-region))
3dd92899 273
3dd92899
KH
274(defvar yank-menu (cons "Select Yank" nil))
275(fset 'yank-menu (cons 'keymap yank-menu))
276(define-key menu-bar-edit-menu [select-paste] '("Select and Paste" . yank-menu))
85f7387f 277(define-key menu-bar-edit-menu [paste] '("Paste" . yank))
4c0317b1 278(define-key menu-bar-edit-menu [copy] '("Copy" . menu-bar-kill-ring-save))
057d49d1
RS
279(define-key menu-bar-edit-menu [cut] '("Cut" . kill-region))
280(define-key menu-bar-edit-menu [undo] '("Undo" . undo))
281
4c0317b1
RS
282(defun menu-bar-kill-ring-save (beg end)
283 (interactive "r")
284 (if (mouse-region-match)
b1a4cc61 285 (message "Selecting a region with the mouse does `copy' automatically")
4c0317b1
RS
286 (kill-ring-save beg end)))
287
25b048ee
RS
288(put 'fill-region 'menu-enable '(and mark-active (not buffer-read-only)))
289(put 'kill-region 'menu-enable '(and mark-active (not buffer-read-only)))
4c0317b1 290(put 'menu-bar-kill-ring-save 'menu-enable 'mark-active)
25b048ee
RS
291(put 'yank 'menu-enable '(and (x-selection-exists-p) (not buffer-read-only)))
292(put 'yank-menu 'menu-enable '(and (cdr yank-menu) (not buffer-read-only)))
4c0317b1 293(put 'delete-region 'menu-enable '(and mark-active
25b048ee 294 (not buffer-read-only)
4c0317b1 295 (not (mouse-region-match))))
25b048ee
RS
296(put 'undo 'menu-enable '(and (not buffer-read-only)
297 (if (eq last-command 'undo)
298 pending-undo-list
299 (consp buffer-undo-list))))
3a841b0b 300(put 'query-replace 'menu-enable '(not buffer-read-only))
25b048ee 301(put 'query-replace-regexp 'menu-enable '(not buffer-read-only))
db774a16 302
9e18f0a0
RS
303(autoload 'ispell-menu-map "ispell" nil t 'keymap)
304
f9cf0be2 305;; These are alternative definitions for the cut, paste and copy
4c0317b1 306;; menu items. Use them if your system expects these to use the clipboard.
f9cf0be2 307
f9cf0be2
RS
308(put 'clipboard-kill-region 'menu-enable 'mark-active)
309(put 'clipboard-kill-ring-save 'menu-enable 'mark-active)
310(put 'clipboard-yank 'menu-enable
311 '(or (x-selection-exists-p) (x-selection-exists-p 'CLIPBOARD)))
312
313(defun clipboard-yank ()
ee497664 314 "Insert the clipboard contents, or the last stretch of killed text."
f9cf0be2
RS
315 (interactive)
316 (let ((x-select-enable-clipboard t))
317 (yank)))
318
319(defun clipboard-kill-ring-save (beg end)
320 "Copy region to kill ring, and save in the X clipboard."
321 (interactive "r")
322 (let ((x-select-enable-clipboard t))
323 (kill-ring-save beg end)))
324
325(defun clipboard-kill-region (beg end)
326 "Kill the region, and save it in the X clipboard."
327 (interactive "r")
328 (let ((x-select-enable-clipboard t))
329 (kill-region beg end)))
330
331(defun menu-bar-enable-clipboard ()
5cbdeb30
RS
332 "Make CUT, PASTE and COPY (keys and menu bar items) use the clipboard.
333Do the same for the keys of the same name."
f9cf0be2 334 (interactive)
5754d7f2
RS
335 ;; We can't use constant list structure here because it becomes pure,
336 ;; and because it gets modified with cache data.
337 (define-key menu-bar-edit-menu [paste]
338 (cons "Paste" 'clipboard-yank))
339 (define-key menu-bar-edit-menu [copy]
340 (cons "Copy" 'clipboard-kill-ring-save))
341 (define-key menu-bar-edit-menu [cut]
5cbdeb30
RS
342 (cons "Cut" 'clipboard-kill-region))
343
344 (define-key global-map [f20] 'clipboard-kill-region)
345 (define-key global-map [f16] 'clipboard-kill-ring-save)
346 (define-key global-map [f18] 'clipboard-yank)
347 ;; X11R6 versions
348 (define-key global-map [cut] 'clipboard-kill-region)
349 (define-key global-map [copy] 'clipboard-kill-ring-save)
350 (define-key global-map [paste] 'clipboard-yank))
f9cf0be2 351\f
a9f53ffb
RS
352
353;;; Menu support
354
355(defvar menu-bar-custom-menu (make-sparse-keymap "Customize"))
356
b0f661de
RS
357(define-key menu-bar-custom-menu [customize-apropos-groups]
358 '("Apropos Groups..." . customize-apropos-groups))
359(define-key menu-bar-custom-menu [customize-apropos-faces]
360 '("Apropos Faces..." . customize-apropos-faces))
361(define-key menu-bar-custom-menu [customize-apropos-options]
362 '("Apropos Options..." . customize-apropos-options))
a9f53ffb
RS
363(define-key menu-bar-custom-menu [customize-apropos]
364 '("Apropos..." . customize-apropos))
b0f661de
RS
365(define-key menu-bar-custom-menu [separator-2]
366 '("--"))
c9a86e71
RS
367(define-key menu-bar-custom-menu [customize-group]
368 '("Specific Group..." . customize-group))
a9f53ffb 369(define-key menu-bar-custom-menu [customize-face]
c9a86e71 370 '("Specific Face..." . customize-face))
b0f661de
RS
371(define-key menu-bar-custom-menu [customize-option]
372 '("Specific Option..." . customize-option))
6fe9c658
DN
373(define-key menu-bar-custom-menu [customize-changed-options]
374 '("Changed Options..." . customize-changed-options))
b0f661de
RS
375(define-key menu-bar-custom-menu [separator-3]
376 '("--"))
e6354b3e 377(define-key menu-bar-custom-menu [customize-browse]
b0f661de
RS
378 '("Browse Customization Groups" . customize-browse))
379(define-key menu-bar-custom-menu [customize]
380 '("Top-level Customization Group" . customize))
a9f53ffb 381
bacb2d12 382;; Options menu
21efd27b 383(defvar menu-bar-options-menu (make-sparse-keymap "Global Options"))
bacb2d12
RS
384
385(defmacro menu-bar-make-toggle (name variable doc message &rest body)
386 `(progn
387 (defun ,name ()
388 ,(concat doc ".")
389 (interactive)
390 (if ,(if body `(progn . ,body)
391 `(setq ,variable (not ,variable)))
392 (message ,message "enabled")
393 (message ,message "disabled")))
89f1709f
RS
394 '(menu-item ,doc ,name .
395 (:button (:toggle . (and (boundp ',variable) ,variable))))))
bacb2d12
RS
396
397(define-key menu-bar-options-menu [debug-on-quit]
398 (menu-bar-make-toggle toggle-debug-on-quit debug-on-quit
89f1709f 399 "Debug on Quit" "Debug on Quit %s"))
bacb2d12
RS
400(define-key menu-bar-options-menu [debug-on-error]
401 (menu-bar-make-toggle toggle-debug-on-error debug-on-error
89f1709f 402 "Debug on Error" "Debug on Error %s"))
bacb2d12
RS
403(define-key menu-bar-options-menu [options-separator]
404 '("--"))
405(define-key menu-bar-options-menu [save-place]
406 (menu-bar-make-toggle toggle-save-place-globally save-place
89f1709f 407 "Save Place in Files between Sessions"
bacb2d12 408 "Saving place in files %s"
89f1709f 409 (require 'saveplace)
bacb2d12
RS
410 (setq-default save-place (not (default-value save-place)))))
411(define-key menu-bar-options-menu [uniquify]
412 (menu-bar-make-toggle toggle-uniquify-buffer-names uniquify-buffer-name-style
89f1709f 413 "Use Directory Names in Buffer Names"
bacb2d12
RS
414 "Directory name in buffer names (uniquify) %s"
415 (require 'uniquify)
416 (setq uniquify-buffer-name-style
417 (if (not uniquify-buffer-name-style)
418 'forward))))
3f51f129
RS
419(define-key menu-bar-options-menu [case-fold-search]
420 (menu-bar-make-toggle toggle-case-fold-search case-fold-search
421 "Case folding in searches"
422 "Case folding in searches %s"))
43c35fd7
RS
423(define-key menu-bar-options-menu [truncate-lines]
424 (menu-bar-make-toggle
425 toggle-truncate-lines truncate-lines
426 "Line Truncation" "Line Truncation %s"
427 (prog1 (setq truncate-lines (not truncate-lines))
428 (set-buffer-modified-p (buffer-modified-p)))))
bacb2d12
RS
429(define-key menu-bar-options-menu [transient-mark-mode]
430 (menu-bar-make-toggle toggle-transient-mark-mode transient-mark-mode
89f1709f 431 "Transient Mark Mode (highlights region)"
bacb2d12
RS
432 "Transient Mark mode %s"))
433(define-key menu-bar-options-menu [toggle-auto-compression]
89f1709f
RS
434 '(menu-item "Automatic File De/compression"
435 auto-compression-mode .
436 (:button (:toggle . (rassq 'jka-compr-handler
437 file-name-handler-alist)))))
bacb2d12 438(define-key menu-bar-options-menu [auto-fill-mode]
89f1709f
RS
439 '(menu-item "Auto Fill (word wrap) in Text modes"
440 toggle-text-mode-auto-fill .
441 (:button (:toggle . (member 'turn-on-auto-fill text-mode-hook)))))
8ad97b87 442(define-key menu-bar-options-menu [toggle-global-lazy-font-lock-mode]
89f1709f
RS
443 (menu-bar-make-toggle toggle-global-lazy-font-lock-mode global-font-lock-mode
444 "Global Font Lock (highlights syntax)"
8ad97b87
RS
445 "Global Font Lock mode %s"
446 ;; Make sure a support mode is used;
447 ;; otherwise Font Lock will be too slow.
21efd27b 448 (require 'font-lock)
8ad97b87
RS
449 (if (not global-font-lock-mode)
450 (or font-lock-support-mode
451 (setq font-lock-support-mode 'lazy-lock-mode)))
452 (global-font-lock-mode)))
e5683624
RS
453\f
454(defvar menu-bar-describe-menu (make-sparse-keymap "Describe"))
455
456(define-key menu-bar-describe-menu [describe-variable]
457 '("Describe Variable..." . describe-variable))
458(define-key menu-bar-describe-menu [describe-function]
459 '("Describe Function..." . describe-function))
460(define-key menu-bar-describe-menu [describe-key]
461 '("Describe Key..." . describe-key))
462(define-key menu-bar-describe-menu [list-keybindings]
463 '("List Key Bindings" . describe-bindings))
a16f6b16 464(define-key menu-bar-describe-menu [apropos-variables]
e5683624 465 '("Apropos Variables..." . apropos-variable))
a16f6b16
SM
466(define-key menu-bar-describe-menu [apropos-commands]
467 '("Apropos Commands..." . apropos-command))
e5683624
RS
468(define-key menu-bar-describe-menu [describe-mode]
469 '("Describe Buffer Modes" . describe-mode))
470
471(defvar menu-bar-manuals-menu (make-sparse-keymap "Manuals"))
472
473(define-key menu-bar-manuals-menu [man]
474 '("Read Man Page..." . manual-entry))
475(define-key menu-bar-manuals-menu [sep2]
476 '("--"))
477(define-key menu-bar-manuals-menu [key]
478 '("Find Key in Manual" . Info-goto-emacs-key-command-node))
479(define-key menu-bar-manuals-menu [command]
480 '("Find Command in Manual" . Info-goto-emacs-command-node))
481(define-key menu-bar-manuals-menu [info]
482 '("Browse Manuals with Info" . info))
483(define-key menu-bar-manuals-menu [sep1]
484 '("--"))
485(define-key menu-bar-manuals-menu [emacs-faq]
486 '("Emacs FAQ" . view-emacs-FAQ))
487(define-key menu-bar-manuals-menu [emacs-news]
488 '("Emacs News" . view-emacs-news))
bacb2d12 489
f3e1e0dd
RS
490(define-key menu-bar-help-menu [describe-no-warranty]
491 '("(Non)Warranty" . describe-no-warranty))
492(define-key menu-bar-help-menu [describe-copying]
493 '("Copying Conditions" . describe-copying))
494(define-key menu-bar-help-menu [describe-distribution]
495 '("Getting New Versions" . describe-distribution))
efb166ff
RS
496(define-key menu-bar-help-menu [emacs-version]
497 '("Show Version" . emacs-version))
48433a65 498(define-key menu-bar-help-menu [report-emacs-bug]
1c6e18f6 499 '("Send Bug Report..." . report-emacs-bug))
e5683624
RS
500(define-key menu-bar-help-menu [sep2]
501 '("--"))
260130bb 502(define-key menu-bar-help-menu [finder-by-keyword]
e5683624
RS
503 '("Find Emacs Packages..." . finder-by-keyword))
504(define-key menu-bar-help-menu [describe]
505 (cons "Describe" menu-bar-describe-menu))
506(define-key menu-bar-help-menu [manuals]
507 (cons "Manuals" menu-bar-manuals-menu))
ca9b40a1 508(define-key menu-bar-help-menu [emacs-tutorial]
db774a16 509 '("Emacs Tutorial" . help-with-tutorial))
e5683624
RS
510(define-key menu-bar-help-menu [sep1]
511 '("--"))
512(define-key menu-bar-help-menu [options]
bacb2d12 513 (cons "Options" menu-bar-options-menu))
e5683624 514(define-key menu-bar-help-menu [customize]
a0cd87a4 515 (cons "Customize" menu-bar-custom-menu))
889560ed 516
db774a16
RS
517(defun kill-this-buffer () ; for the menubar
518 "Kills the current buffer."
519 (interactive)
520 (kill-buffer (current-buffer)))
521
2f1139a4
RS
522(defun kill-this-buffer-enabled-p ()
523 (let ((count 0)
524 (buffers (buffer-list)))
525 (while buffers
526 (or (string-match "^ " (buffer-name (car buffers)))
527 (setq count (1+ count)))
528 (setq buffers (cdr buffers)))
a6f8cbf1 529 (and (not (window-minibuffer-p (frame-selected-window menu-updating-frame)))
1f50590a
RS
530 (> count 1))))
531
532(put 'kill-this-buffer 'menu-enable '(kill-this-buffer-enabled-p))
533
534(put 'save-buffer 'menu-enable
535 '(and (buffer-modified-p)
a6f8cbf1 536 (not (window-minibuffer-p (frame-selected-window menu-updating-frame)))))
1f50590a
RS
537
538(put 'write-file 'menu-enable
a6f8cbf1 539 '(not (window-minibuffer-p (frame-selected-window menu-updating-frame))))
1f50590a
RS
540
541(put 'find-file 'menu-enable
a6f8cbf1 542 '(not (window-minibuffer-p (frame-selected-window menu-updating-frame))))
1f50590a
RS
543
544(put 'dired 'menu-enable
a6f8cbf1 545 '(not (window-minibuffer-p (frame-selected-window menu-updating-frame))))
1f50590a
RS
546
547(put 'insert-file 'menu-enable
a6f8cbf1 548 '(not (window-minibuffer-p (frame-selected-window menu-updating-frame))))
2f1139a4 549
da183f87
RS
550(put 'revert-buffer 'menu-enable
551 '(or revert-buffer-function revert-buffer-insert-file-contents-function
552 (and (buffer-file-name)
660fa562
RM
553 (or (buffer-modified-p)
554 (not (verify-visited-file-modtime (current-buffer)))))))
82a74107 555
a0213a97
RS
556;; Permit deleting frame if it would leave a visible or iconified frame.
557(put 'delete-frame 'menu-enable
82a74107
KH
558 '(delete-frame-enabled-p))
559
560(defun delete-frame-enabled-p ()
561 "Return non-nil if `delete-frame' should be enabled in the menu bar."
562 (let ((frames (frame-list))
27aa8132
RS
563 (count 0))
564 (while frames
565 (if (frame-visible-p (car frames))
566 (setq count (1+ count)))
567 (setq frames (cdr frames)))
568 (> count 1)))
2f1139a4 569
db774a16
RS
570(put 'advertised-undo 'menu-enable
571 '(and (not (eq t buffer-undo-list))
572 (if (eq last-command 'undo)
2f1139a4
RS
573 (and (boundp 'pending-undo-list)
574 pending-undo-list)
575 buffer-undo-list)))
2877eac2 576
30e19aee
RS
577(defcustom yank-menu-length 20
578 "*Maximum length to display in the yank-menu."
579 :type 'integer
580 :group 'mouse)
3dd92899
KH
581
582(defun menu-bar-update-yank-menu (string old)
583 (let ((front (car (cdr yank-menu)))
584 (menu-string (if (<= (length string) yank-menu-length)
585 string
c3e1d435
RS
586 (concat
587 (substring string 0 (/ yank-menu-length 2))
588 "..."
589 (substring string (- (/ yank-menu-length 2)))))))
7c70a955
RS
590 ;; Don't let the menu string be all dashes
591 ;; because that has a special meaning in a menu.
592 (if (string-match "\\`-+\\'" menu-string)
593 (setq menu-string (concat menu-string " ")))
3dd92899
KH
594 ;; If we're supposed to be extending an existing string, and that
595 ;; string really is at the front of the menu, then update it in place.
596 (if (and old (or (eq old (car front))
597 (string= old (car front))))
dfabc98f 598 (progn
3dd92899
KH
599 (setcar front string)
600 (setcar (cdr front) menu-string))
601 (setcdr yank-menu
602 (cons
603 (cons string (cons menu-string 'menu-bar-select-yank))
604 (cdr yank-menu)))))
605 (if (> (length (cdr yank-menu)) kill-ring-max)
606 (setcdr (nthcdr kill-ring-max yank-menu) nil)))
607
4cca6fbd 608(put 'menu-bar-select-yank 'apropos-inhibit t)
3dd92899
KH
609(defun menu-bar-select-yank ()
610 (interactive "*")
611 (push-mark (point))
612 (insert last-command-event))
40954111 613\f
3f557298
RS
614;; This definition is just to show what this looks like.
615;; It gets overridden below when menu-bar-update-buffers is called.
616(define-key global-map [menu-bar buffer]
617 (cons "Buffers" (make-sparse-keymap "Buffers")))
40954111 618
d0690d12
RS
619(defvar list-buffers-directory nil)
620
08e8171f
RS
621(defvar menu-bar-update-buffers-maxbuf)
622
09642d97
RS
623(defun menu-bar-select-buffer ()
624 (interactive)
625 (switch-to-buffer last-command-event))
626
627(defun menu-bar-select-frame ()
628 (interactive)
629 (make-frame-visible last-command-event)
630 (raise-frame last-command-event)
631 (select-frame last-command-event))
632
c171b42f
RS
633(defun menu-bar-update-buffers-1 (elt)
634 (cons (format
08e8171f 635 (format "%%%ds %%s%%s %%s" menu-bar-update-buffers-maxbuf)
c171b42f
RS
636 (cdr elt)
637 (if (buffer-modified-p (car elt))
638 "*" " ")
639 (save-excursion
640 (set-buffer (car elt))
641 (if buffer-read-only "%" " "))
642 (let ((file
643 (or (buffer-file-name (car elt))
644 (save-excursion
645 (set-buffer (car elt))
646 list-buffers-directory)
647 "")))
648 (setq file (or (file-name-directory file)
649 ""))
650 (if (> (length file) 20)
651 (setq file (concat "..." (substring file -17))))
652 file))
653 (car elt)))
654
06ff7539
RS
655(defvar menu-bar-buffers-menu-list-buffers-entry nil)
656
09642d97 657(defun menu-bar-update-buffers ()
29397c58 658 ;; If user discards the Buffers item, play along.
4d587a6c 659 (and (lookup-key (current-global-map) [menu-bar buffer])
29397c58
RS
660 (frame-or-buffer-changed-p)
661 (let ((buffers (buffer-list))
662 (frames (frame-list))
b3398af1 663 (maxlen 0)
29397c58
RS
664 buffers-menu frames-menu)
665 ;; If requested, list only the N most recently selected buffers.
666 (if (and (integerp buffers-menu-max-size)
667 (> buffers-menu-max-size 1))
668 (if (> (length buffers) buffers-menu-max-size)
669 (setcdr (nthcdr buffers-menu-max-size buffers) nil)))
670
671 ;; Make the menu of buffers proper.
672 (setq buffers-menu
673 (cons "Select Buffer"
c171b42f
RS
674 (let* ((buffer-list
675 (mapcar 'list buffers))
676 tail
08e8171f 677 (menu-bar-update-buffers-maxbuf 0)
c171b42f
RS
678 alist
679 head)
680 ;; Put into each element of buffer-list
681 ;; the name for actual display,
682 ;; perhaps truncated in the middle.
683 (setq tail buffer-list)
684 (while tail
685 (let ((name (buffer-name (car (car tail)))))
686 (setcdr (car tail)
687 (if (> (length name) 27)
688 (concat (substring name 0 12)
689 "..."
690 (substring name -12))
691 name)))
692 (setq tail (cdr tail)))
693 ;; Compute the maximum length of any name.
694 (setq tail buffer-list)
29397c58 695 (while tail
c171b42f 696 (or (eq ?\ (aref (cdr (car tail)) 0))
08e8171f
RS
697 (setq menu-bar-update-buffers-maxbuf
698 (max menu-bar-update-buffers-maxbuf
c171b42f 699 (length (cdr (car tail))))))
29397c58 700 (setq tail (cdr tail)))
c171b42f
RS
701 ;; Set ALIST to an alist of the form
702 ;; ITEM-STRING . BUFFER
703 (setq tail buffer-list)
29397c58
RS
704 (while tail
705 (let ((elt (car tail)))
c171b42f 706 (or (eq ?\ (aref (cdr elt) 0))
29397c58 707 (setq alist (cons
c171b42f 708 (menu-bar-update-buffers-1 elt)
29397c58
RS
709 alist)))
710 (and alist (> (length (car (car alist))) maxlen)
711 (setq maxlen (length (car (car alist))))))
712 (setq tail (cdr tail)))
713 (setq alist (nreverse alist))
06ff7539
RS
714 ;; Make the menu item for list-buffers
715 ;; or reuse the one we already have.
716 ;; The advantage in reusing one
717 ;; is that it already has the keyboard equivalent
718 ;; cached, so we save the time to look that up again.
719 (or menu-bar-buffers-menu-list-buffers-entry
720 (setq menu-bar-buffers-menu-list-buffers-entry
721 (cons
722 'list-buffers
723 (cons
724 ""
725 'list-buffers))))
726 ;; Update the item string for menu's new width.
727 (setcar (cdr menu-bar-buffers-menu-list-buffers-entry)
728 (concat (make-string (max (- (/ maxlen 2) 8) 0)
729 ?\ )
730 "List All Buffers"))
731 ;; Now make the actual list of items,
732 ;; ending with the list-buffers item.
29397c58
RS
733 (nconc (mapcar '(lambda (pair)
734 ;; This is somewhat risque, to use
735 ;; the buffer name itself as the event
736 ;; type to define, but it works.
737 ;; It would not work to use the buffer
738 ;; since a buffer as an event has its
739 ;; own meaning.
740 (nconc (list (buffer-name (cdr pair))
741 (car pair)
742 (cons nil nil))
743 'menu-bar-select-buffer))
744 alist)
06ff7539 745 (list menu-bar-buffers-menu-list-buffers-entry)))))
29397c58
RS
746
747
748 ;; Make a Frames menu if we have more than one frame.
749 (if (cdr frames)
b3398af1
RS
750 (let ((name (concat (make-string (max (- (/ maxlen 2) 3) 0)
751 ?\ )
752 "Frames"))
753 (frames-menu
754 (cons 'keymap
755 (cons "Select Frame"
756 (mapcar '(lambda (frame)
757 (nconc (list frame
758 (cdr (assq 'name
759 (frame-parameters frame)))
760 (cons nil nil))
761 'menu-bar-select-frame))
762 frames)))))
763 ;; Put it underneath the Buffers menu.
764 (setq buffers-menu (cons (cons 'frames (cons name frames-menu))
765 buffers-menu))))
29397c58
RS
766 (if buffers-menu
767 (setq buffers-menu (cons 'keymap buffers-menu)))
4d587a6c 768 (define-key (current-global-map) [menu-bar buffer]
b3398af1 769 (cons "Buffers" buffers-menu)))))
09642d97
RS
770
771(add-hook 'menu-bar-update-hook 'menu-bar-update-buffers)
2f1139a4 772
3f557298
RS
773(menu-bar-update-buffers)
774
40954111
RS
775;; this version is too slow
776;;;(defun format-buffers-menu-line (buffer)
777;;; "Returns a string to represent the given buffer in the Buffer menu.
778;;;nil means the buffer shouldn't be listed. You can redefine this."
779;;; (if (string-match "\\` " (buffer-name buffer))
780;;; nil
781;;; (save-excursion
782;;; (set-buffer buffer)
783;;; (let ((size (buffer-size)))
784;;; (format "%s%s %-19s %6s %-15s %s"
785;;; (if (buffer-modified-p) "*" " ")
786;;; (if buffer-read-only "%" " ")
787;;; (buffer-name)
788;;; size
789;;; mode-name
790;;; (or (buffer-file-name) ""))))))
791\f
25b048ee
RS
792;;; Set up a menu bar menu for the minibuffer.
793
794(mapcar
795 (function
796 (lambda (map)
797 (define-key map [menu-bar minibuf]
798 (cons "Minibuf" (make-sparse-keymap "Minibuf")))))
799 (list minibuffer-local-ns-map
800 minibuffer-local-must-match-map
801 minibuffer-local-isearch-map
802 minibuffer-local-map
803 minibuffer-local-completion-map))
804
805(mapcar
806 (function
807 (lambda (map)
808 (define-key map [menu-bar minibuf ?\?]
809 '("List Completions" . minibuffer-completion-help))
810 (define-key map [menu-bar minibuf space]
811 '("Complete Word" . minibuffer-complete-word))
812 (define-key map [menu-bar minibuf tab]
4e9d1906 813 '("Complete" . minibuffer-complete))
25b048ee
RS
814 ))
815 (list minibuffer-local-must-match-map
816 minibuffer-local-completion-map))
817
818(mapcar
819 (function
820 (lambda (map)
821 (define-key map [menu-bar minibuf quit]
822 '("Quit" . keyboard-escape-quit))
823 (define-key map [menu-bar minibuf return]
824 '("Enter" . exit-minibuffer))
825 ))
826 (list minibuffer-local-ns-map
827 minibuffer-local-must-match-map
828 minibuffer-local-isearch-map
829 minibuffer-local-map
830 minibuffer-local-completion-map))
831\f
7b7d6615
RS
832(defvar menu-bar-mode nil)
833
057d49d1 834(defun menu-bar-mode (flag)
dfd29450 835 "Toggle display of a menu bar on each frame.
057d49d1
RS
836This command applies to all frames that exist and frames to be
837created in the future.
e1d18ad8
RS
838With a numeric argument, if the argument is positive,
839turn on menu bars; otherwise, turn off menu bars."
dad8e392 840 (interactive "P")
dad8e392 841
7b7d6615
RS
842 ;; Make menu-bar-mode and default-frame-alist consistent.
843 (let ((default (assq 'menu-bar-lines default-frame-alist)))
844 (if default
845 (setq menu-bar-mode (not (eq (cdr default) 0)))
846 (setq default-frame-alist
847 (cons (cons 'menu-bar-lines (if menu-bar-mode 1 0))
848 default-frame-alist))))
849
850 ;; Toggle or set the mode, according to FLAG.
851 (setq menu-bar-mode (if (null flag) (not menu-bar-mode)
852 (> (prefix-numeric-value flag) 0)))
853
854 ;; Apply it to default-frame-alist.
855 (let ((parameter (assq 'menu-bar-lines default-frame-alist)))
856 (if (consp parameter)
857 (setcdr parameter (if menu-bar-mode 1 0))
858 (setq default-frame-alist
859 (cons (cons 'menu-bar-lines (if menu-bar-mode 1 0))
860 default-frame-alist))))
861
862 ;; Apply it to existing frames.
863 (let ((frames (frame-list)))
864 (while frames
865 (let ((height (cdr (assq 'height (frame-parameters (car frames))))))
866 (modify-frame-parameters (car frames)
867 (list (cons 'menu-bar-lines
868 (if menu-bar-mode 1 0))))
869 (modify-frame-parameters (car frames)
870 (list (cons 'height height))))
871 (setq frames (cdr frames)))))
1db87953 872
bffa5d4d
RS
873(provide 'menu-bar)
874
235aa29b 875;;; menu-bar.el ends here