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