(create_process): Fix previous change.
[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
f9cf0be2
RS
92;; These are alternative definitions for the cut, paste and copy
93;; menu items. Use them if your system expects these to use the clipboard
94
f9cf0be2
RS
95(put 'clipboard-kill-region 'menu-enable 'mark-active)
96(put 'clipboard-kill-ring-save 'menu-enable 'mark-active)
97(put 'clipboard-yank 'menu-enable
98 '(or (x-selection-exists-p) (x-selection-exists-p 'CLIPBOARD)))
99
100(defun clipboard-yank ()
101 "Reinsert the last stretch of killed text, or the clipboard contents."
102 (interactive)
103 (let ((x-select-enable-clipboard t))
104 (yank)))
105
106(defun clipboard-kill-ring-save (beg end)
107 "Copy region to kill ring, and save in the X clipboard."
108 (interactive "r")
109 (let ((x-select-enable-clipboard t))
110 (kill-ring-save beg end)))
111
112(defun clipboard-kill-region (beg end)
113 "Kill the region, and save it in the X clipboard."
114 (interactive "r")
115 (let ((x-select-enable-clipboard t))
116 (kill-region beg end)))
117
118(defun menu-bar-enable-clipboard ()
119 "Make the menu bar CUT, PASTE and COPY items use the clipboard."
120 (interactive)
121 (define-key menu-bar-edit-menu [paste] '("Paste" . clipboard-yank))
122 (define-key menu-bar-edit-menu [copy] '("Copy" . clipboard-kill-ring-save))
123 (define-key menu-bar-edit-menu [cut] '("Cut" . clipboard-kill-region)))
2165f676
RS
124
125;; Sun expects these commands on these keys, so why not?
126(define-key global-map [f20] 'clipboard-kill-region)
127(define-key global-map [f16] 'clipboard-kill-ring-save)
128(define-key global-map [f18] 'clipboard-yank)
f9cf0be2 129\f
ca9b40a1 130(define-key menu-bar-help-menu [emacs-tutorial]
db774a16 131 '("Emacs Tutorial" . help-with-tutorial))
2f1139a4
RS
132(define-key menu-bar-help-menu [man] '("Man..." . manual-entry))
133(define-key menu-bar-help-menu [describe-variable]
134 '("Describe Variable..." . describe-variable))
135(define-key menu-bar-help-menu [describe-function]
136 '("Describe Function..." . describe-function))
137(define-key menu-bar-help-menu [describe-key]
138 '("Describe Key..." . describe-key))
139(define-key menu-bar-help-menu [list-keybindings]
140 '("List Keybindings" . describe-bindings))
141(define-key menu-bar-help-menu [command-apropos]
142 '("Command Apropos..." . command-apropos))
143(define-key menu-bar-help-menu [describe-mode]
144 '("Describe Mode" . describe-mode))
145(define-key menu-bar-help-menu [info] '("Info" . info))
db774a16 146
2f1139a4 147(define-key menu-bar-help-menu [emacs-news] '("Emacs News" . view-emacs-news))
db774a16
RS
148(defun kill-this-buffer () ; for the menubar
149 "Kills the current buffer."
150 (interactive)
151 (kill-buffer (current-buffer)))
152
2f1139a4
RS
153(defun kill-this-buffer-enabled-p ()
154 (let ((count 0)
155 (buffers (buffer-list)))
156 (while buffers
157 (or (string-match "^ " (buffer-name (car buffers)))
158 (setq count (1+ count)))
159 (setq buffers (cdr buffers)))
160 (> count 1)))
161
db774a16 162(put 'save-buffer 'menu-enable '(buffer-modified-p))
da183f87
RS
163(put 'revert-buffer 'menu-enable
164 '(or revert-buffer-function revert-buffer-insert-file-contents-function
165 (and (buffer-file-name)
660fa562
RM
166 (or (buffer-modified-p)
167 (not (verify-visited-file-modtime (current-buffer)))))))
a0213a97
RS
168;; Permit deleting frame if it would leave a visible or iconified frame.
169(put 'delete-frame 'menu-enable
170 '(let ((frames (frame-list))
171 (count 0))
172 (while frames
173 (if (cdr (assq 'visibility (frame-parameters (car frames))))
174 (setq count (1+ count)))
175 (setq frames (cdr frames)))
176 (> count 1)))
2f1139a4
RS
177(put 'kill-this-buffer 'menu-enable '(kill-this-buffer-enabled-p))
178
db774a16
RS
179(put 'advertised-undo 'menu-enable
180 '(and (not (eq t buffer-undo-list))
181 (if (eq last-command 'undo)
2f1139a4
RS
182 (and (boundp 'pending-undo-list)
183 pending-undo-list)
184 buffer-undo-list)))
2877eac2
RS
185
186(defvar yank-menu-length 100
187 "*Maximum length of an item in the menu for \
188\\[mouse-menu-choose-yank].")
189
190(defun mouse-menu-choose-yank (event)
191 "Pop up a menu of the kill-ring for selection with the mouse.
192The kill-ring-yank-pointer is moved to the selected element.
193A subsequent \\[yank] yanks the choice just selected."
194 (interactive "e")
195 (let* ((count 0)
196 (menu (mapcar (lambda (string)
197 (if (> (length string) yank-menu-length)
198 (setq string (substring string
199 0 yank-menu-length)))
200 (prog1 (cons string count)
201 (setq count (1+ count))))
dfabc98f
RM
202 kill-ring))
203 (arg (x-popup-menu event
204 (list "Yank Menu"
75340584 205 (cons "Choose Next Yank" menu)))))
dfabc98f
RM
206 ;; A mouse click outside the menu returns nil.
207 ;; Avoid a confusing error from passing nil to rotate-yank-pointer.
208 ;; XXX should this perhaps do something other than simply return? -rm
209 (if arg
210 (progn
03dcd202
RM
211 ;; We don't use `rotate-yank-pointer' because we want to move
212 ;; relative to the beginning of kill-ring, not the current
213 ;; position. Also, that would ask for any new X selection and
214 ;; thus change the list of items the user just chose from, which
215 ;; would be highly confusing.
216 (setq kill-ring-yank-pointer (nthcdr arg kill-ring))
dfabc98f
RM
217 (if (interactive-p)
218 (message "The next yank will insert the selected text.")
219 (current-kill 0))))))
220(put 'mouse-menu-choose-yank 'menu-enable 'kill-ring)
40954111 221\f
98bee59b 222(define-key global-map [menu-bar buffer] '("Buffers" . mouse-menu-bar-buffers))
40954111
RS
223
224(defvar complex-buffers-menu-p nil
225 "*Non-nil says, offer a choice of actions after you pick a buffer.
226This applies to the Buffers menu from the menu bar.")
227
228(defvar buffers-menu-max-size 10
229 "*Maximum number of entries which may appear on the Buffers menu.
230If this is 10, then only the ten most-recently-selected buffers are shown.
231If this is nil, then all buffers are shown.
232A large number or nil slows down menu responsiveness.")
233
d0690d12
RS
234(defvar list-buffers-directory nil)
235
98bee59b 236(defun mouse-menu-bar-buffers (event)
40954111
RS
237 "Pop up a menu of buffers for selection with the mouse.
238This switches buffers in the window that you clicked on,
239and selects that window."
240 (interactive "e")
241 (let ((buffers (buffer-list))
242 menu)
243 ;; If requested, list only the N most recently selected buffers.
244 (if (and (integerp buffers-menu-max-size)
245 (> buffers-menu-max-size 1))
246 (if (> (length buffers) buffers-menu-max-size)
247 (setcdr (nthcdr buffers-menu-max-size buffers) nil)))
248 (setq menu
e936d399
RM
249 (cons "Select Buffer"
250 (let ((tail buffers)
251 (maxbuf 0)
252 (maxlen 0)
253 head)
254 (while tail
255 (or (eq ?\ (aref (buffer-name (car tail)) 0))
256 (setq maxbuf
257 (max maxbuf
258 (length (buffer-name (car tail))))))
259 (setq tail (cdr tail)))
260 (setq tail buffers)
261 (while tail
262 (let ((elt (car tail)))
263 (if (not (string-match "^ "
264 (buffer-name elt)))
265 (setq head (cons
266 (cons
267 (format
268 (format "%%%ds %%s%%s %%s"
269 maxbuf)
270 (buffer-name elt)
271 (if (buffer-modified-p elt)
272 "*" " ")
273 (save-excursion
274 (set-buffer elt)
275 (if buffer-read-only "%" " "))
75e4aa06
RS
276 (or (buffer-file-name elt)
277 (save-excursion
278 (set-buffer elt)
279 list-buffers-directory)
280 ""))
e936d399
RM
281 elt)
282 head)))
283 (and head (> (length (car (car head))) maxlen)
284 (setq maxlen (length (car (car head))))))
285 (setq tail (cdr tail)))
286 (nconc (nreverse head)
287 (list (cons
288 (concat (make-string (max (- (/ maxlen
289 2)
290 8)
291 0) ?\ )
292 "List All Buffers")
293 'list-buffers))))))
e936d399
RM
294 (if (cdr (frame-list))
295 (setq menu
b622e49c
RS
296 (list menu
297 (cons "Select Frame"
e936d399
RM
298 (mapcar (lambda (frame)
299 (cons (cdr (assq 'name
300 (frame-parameters frame)))
301 frame))
b622e49c
RS
302 (frame-list)))))
303 (setq menu (list menu)))
304
e936d399 305 (setq menu (cons "Buffer and Frame Menu" menu))
40954111
RS
306
307 (let ((buf (x-popup-menu (if (listp event) event
ea0633d4 308 (list '(0 0) (selected-frame)))
40954111
RS
309 menu))
310 (window (and (listp event) (posn-window (event-start event)))))
e936d399
RM
311 (cond ((framep buf)
312 (make-frame-visible buf)
313 (raise-frame buf)
314 (select-frame buf))
315 ((eq buf 'list-buffers)
316 (list-buffers))
317 (buf
318 (if complex-buffers-menu-p
319 (let ((action (x-popup-menu
320 (if (listp event) event
ea0633d4 321 (list '(0 0) (selected-frame)))
e936d399
RM
322 '("Buffer Action"
323 (""
324 ("Save Buffer" . save-buffer)
325 ("Kill Buffer" . kill-buffer)
326 ("Select Buffer" . switch-to-buffer))))))
327 (if (eq action 'save-buffer)
328 (save-excursion
329 (set-buffer buf)
330 (save-buffer))
331 (funcall action buf)))
332 (and (windowp window)
333 (select-window window))
334 (switch-to-buffer buf)))))))
2f1139a4 335
40954111
RS
336;; this version is too slow
337;;;(defun format-buffers-menu-line (buffer)
338;;; "Returns a string to represent the given buffer in the Buffer menu.
339;;;nil means the buffer shouldn't be listed. You can redefine this."
340;;; (if (string-match "\\` " (buffer-name buffer))
341;;; nil
342;;; (save-excursion
343;;; (set-buffer buffer)
344;;; (let ((size (buffer-size)))
345;;; (format "%s%s %-19s %6s %-15s %s"
346;;; (if (buffer-modified-p) "*" " ")
347;;; (if buffer-read-only "%" " ")
348;;; (buffer-name)
349;;; size
350;;; mode-name
351;;; (or (buffer-file-name) ""))))))
352\f
057d49d1 353(defun menu-bar-mode (flag)
dfd29450 354 "Toggle display of a menu bar on each frame.
057d49d1
RS
355This command applies to all frames that exist and frames to be
356created in the future.
357With a numeric argument, if the argument is negative,
dfd29450 358turn off menu bars; otherwise, turn on menu bars."
dad8e392 359 (interactive "P")
dad8e392
RM
360
361 ;; Obtain the current setting by looking at default-frame-alist.
362 (let ((menu-bar-mode
363 (not (zerop (let ((assq (assq 'menu-bar-lines default-frame-alist)))
364 (if assq (cdr assq) 0))))))
365
366 ;; Tweedle it according to the argument.
367 (setq menu-bar-mode (if (null flag) (not menu-bar-mode)
e48f95c9 368 (> (prefix-numeric-value flag) 0)))
dad8e392
RM
369
370 ;; Apply it to default-frame-alist.
371 (let ((parameter (assq 'menu-bar-lines default-frame-alist)))
372 (if (consp parameter)
373 (setcdr parameter (if menu-bar-mode 1 0))
374 (setq default-frame-alist
375 (cons (cons 'menu-bar-lines (if menu-bar-mode 1 0))
376 default-frame-alist))))
377
378 ;; Apply it to existing frames.
379 (let ((frames (frame-list)))
380 (while frames
381 (modify-frame-parameters (car frames)
382 (list (cons 'menu-bar-lines
383 (if menu-bar-mode 1 0))))
384 (setq frames (cdr frames))))))
1db87953
RS
385
386;; Make frames created from now on have a menu bar.
d0dbd3bf
RS
387(if window-system
388 (menu-bar-mode t))
1db87953 389
bffa5d4d
RS
390(provide 'menu-bar)
391
235aa29b 392;;; menu-bar.el ends here