Commit | Line | Data |
---|---|---|
029b623a RS |
1 | ;;; easymenu.el --- support the easymenu interface for defining a menu. |
2 | ||
029b623a RS |
3 | ;; Copyright (C) 1994 Free Software Foundation, Inc. |
4 | ||
8df69fb0 RS |
5 | ;; Keywords: emulations |
6 | ;; Author: rms | |
7 | ||
029b623a RS |
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 | |
b578f267 EN |
21 | ;; along with GNU Emacs; see the file COPYING. If not, write to the |
22 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
23 | ;; Boston, MA 02111-1307, USA. | |
029b623a | 24 | |
b578f267 EN |
25 | ;;; Commentary: |
26 | ||
27 | ;; This is compatible with easymenu.el by Per Abrahamsen | |
28 | ;; but it is much simpler as it doesn't try to support other Emacs versions. | |
29 | ;; The code was mostly derived from lmenu.el. | |
029b623a RS |
30 | |
31 | ;;; Code: | |
32 | ||
a8226f67 | 33 | ;;;###autoload |
8df69fb0 | 34 | (defmacro easy-menu-define (symbol maps doc menu) |
029b623a | 35 | "Define a menu bar submenu in maps MAPS, according to MENU. |
819fefed RS |
36 | The menu keymap is stored in symbol SYMBOL, both as its value |
37 | and as its function definition. DOC is used as the doc string for SYMBOL. | |
029b623a RS |
38 | |
39 | The first element of MENU must be a string. It is the menu bar item name. | |
40 | The rest of the elements are menu items. | |
41 | ||
8df69fb0 | 42 | A menu item is usually a vector of three elements: [NAME CALLBACK ENABLE] |
029b623a | 43 | |
a8226f67 | 44 | NAME is a string--the menu item name. |
029b623a | 45 | |
a8226f67 RS |
46 | CALLBACK is a command to run when the item is chosen, |
47 | or a list to evaluate when the item is chosen. | |
029b623a | 48 | |
5a51e0a6 RS |
49 | ENABLE is an expression; the item is enabled for selection |
50 | whenever this expression's value is non-nil. | |
8df69fb0 | 51 | |
1ba15fe6 RS |
52 | Alternatively, a menu item may have the form: |
53 | ||
54 | [ NAME CALLBACK [ KEYWORD ARG ] ... ] | |
55 | ||
56 | Where KEYWORD is one of the symbol defined below. | |
57 | ||
58 | :keys KEYS | |
59 | ||
60 | KEYS is a string; a complex keyboard equivalent to this menu item. | |
61 | This is normally not needed because keyboard equivalents are usually | |
62 | computed automatically. | |
63 | ||
64 | :active ENABLE | |
65 | ||
66 | ENABLE is an expression; the item is enabled for selection | |
67 | whenever this expression's value is non-nil. | |
68 | ||
69 | :suffix NAME | |
70 | ||
71 | NAME is a string; the name of an argument to CALLBACK. | |
72 | ||
41e6ca7a | 73 | :style STYLE |
1ba15fe6 RS |
74 | |
75 | STYLE is a symbol describing the type of menu item. The following are | |
76 | defined: | |
77 | ||
78 | toggle: A checkbox. | |
79 | Currently just prepend the name with the string \"Toggle \". | |
80 | radio: A radio button. | |
81 | nil: An ordinary menu item. | |
82 | ||
83 | :selected SELECTED | |
84 | ||
85 | SELECTED is an expression; the checkbox or radio button is selected | |
86 | whenever this expression's value is non-nil. | |
87 | Currently just disable radio buttons, no effect on checkboxes. | |
88 | ||
a8226f67 RS |
89 | A menu item can be a string. Then that string appears in the menu as |
90 | unselectable text. A string consisting solely of hyphens is displayed | |
91 | as a solid horizontal line. | |
029b623a | 92 | |
a8226f67 | 93 | A menu item can be a list. It is treated as a submenu. |
029b623a RS |
94 | The first element should be the submenu name. That's used as the |
95 | menu item in the top-level menu. The cdr of the submenu list | |
96 | is a list of menu items, as above." | |
1ba15fe6 RS |
97 | (` (progn |
98 | (defvar (, symbol) nil (, doc)) | |
99 | (easy-menu-do-define (quote (, symbol)) (, maps) (, doc) (, menu))))) | |
100 | ||
f39223a6 | 101 | ;;;###autoload |
1ba15fe6 RS |
102 | (defun easy-menu-do-define (symbol maps doc menu) |
103 | ;; We can't do anything that might differ between Emacs dialects in | |
104 | ;; `easy-menu-define' in order to make byte compiled files | |
105 | ;; compatible. Therefore everything interesting is done in this | |
106 | ;; function. | |
107 | (set symbol (easy-menu-create-keymaps (car menu) (cdr menu))) | |
108 | (fset symbol (` (lambda (event) (, doc) (interactive "@e") | |
109 | (easy-popup-menu event (, symbol))))) | |
110 | (mapcar (function (lambda (map) | |
111 | (define-key map (vector 'menu-bar (intern (car menu))) | |
112 | (cons (car menu) (symbol-value symbol))))) | |
113 | (if (keymapp maps) (list maps) maps))) | |
a8226f67 RS |
114 | |
115 | (defvar easy-menu-item-count 0) | |
029b623a RS |
116 | |
117 | ;; Return a menu keymap corresponding to a Lucid-style menu list | |
118 | ;; MENU-ITEMS, and with name MENU-NAME. | |
815d2127 | 119 | ;;;###autoload |
8b4b171e | 120 | (defun easy-menu-create-keymaps (menu-name menu-items) |
029b623a RS |
121 | (let ((menu (make-sparse-keymap menu-name))) |
122 | ;; Process items in reverse order, | |
123 | ;; since the define-key loop reverses them again. | |
124 | (setq menu-items (reverse menu-items)) | |
125 | (while menu-items | |
126 | (let* ((item (car menu-items)) | |
127 | (callback (if (vectorp item) (aref item 1))) | |
128 | command enabler name) | |
129 | (cond ((stringp item) | |
130 | (setq command nil) | |
131 | (setq name (if (string-match "^-+$" item) "" item))) | |
132 | ((consp item) | |
8b4b171e | 133 | (setq command (easy-menu-create-keymaps (car item) (cdr item))) |
4fd6247b | 134 | (setq name (car item))) |
029b623a RS |
135 | ((vectorp item) |
136 | (setq command (make-symbol (format "menu-function-%d" | |
a8226f67 | 137 | easy-menu-item-count))) |
a8226f67 | 138 | (setq easy-menu-item-count (1+ easy-menu-item-count)) |
1ba15fe6 RS |
139 | (setq name (aref item 0)) |
140 | (let ((keyword (aref item 2))) | |
141 | (if (and (symbolp keyword) | |
142 | (= ?: (aref (symbol-name keyword) 0))) | |
143 | (let ((count 2) | |
144 | style selected active keys | |
145 | arg) | |
146 | (while (> (length item) count) | |
147 | (setq keyword (aref item count)) | |
148 | (setq arg (aref item (1+ count))) | |
149 | (setq count (+ 2 count)) | |
150 | (cond ((eq keyword ':keys) | |
151 | (setq keys arg)) | |
152 | ((eq keyword ':active) | |
153 | (setq active arg)) | |
154 | ((eq keyword ':suffix) | |
155 | (setq name (concat name " " arg))) | |
156 | ((eq keyword ':style) | |
157 | (setq style arg)) | |
158 | ((eq keyword ':selected) | |
159 | (setq selected arg)))) | |
160 | (if keys | |
161 | (setq name (concat name " (" keys ")"))) | |
162 | (if (eq style 'toggle) | |
163 | ;; Simulate checkboxes. | |
164 | (setq name (concat "Toggle " name))) | |
165 | (if active | |
166 | (put command 'menu-enable active) | |
167 | (and (eq style 'radio) | |
168 | selected | |
169 | ;; Simulate radio buttons with menu-enable. | |
170 | (put command 'menu-enable | |
0579e89d KH |
171 | (list 'not selected))))) |
172 | (put command 'menu-enable keyword))) | |
8df69fb0 RS |
173 | (if (keymapp callback) |
174 | (setq name (concat name " ..."))) | |
029b623a RS |
175 | (if (symbolp callback) |
176 | (fset command callback) | |
41311853 RS |
177 | (fset command (list 'lambda () '(interactive) callback))) |
178 | (put command 'menu-alias t))) | |
029b623a RS |
179 | (if (null command) |
180 | ;; Handle inactive strings specially--allow any number | |
181 | ;; of identical ones. | |
182 | (setcdr menu (cons (list nil name) (cdr menu))) | |
183 | (if name | |
184 | (define-key menu (vector (intern name)) (cons name command))))) | |
185 | (setq menu-items (cdr menu-items))) | |
186 | menu)) | |
187 | ||
88153c47 RS |
188 | (defun easy-menu-change (path name items) |
189 | "Change menu found at PATH as item NAME to contain ITEMS. | |
190 | PATH is a list of strings for locating the menu containing NAME in the | |
191 | menu bar. ITEMS is a list of menu items, as in `easy-menu-define'. | |
192 | These items entirely replace the previous items in that map. | |
193 | ||
194 | Call this from `activate-menubar-hook' to implement dynamic menus." | |
195 | (let ((map (key-binding (apply 'vector | |
196 | 'menu-bar | |
197 | (mapcar 'intern (append path (list name))))))) | |
198 | (if (keymapp map) | |
199 | (setcdr map (cdr (easy-menu-create-keymaps name items))) | |
200 | (error "Malformed menu in `easy-menu-change'")))) | |
201 | ||
1ba15fe6 | 202 | (defun easy-menu-remove (menu)) |
8df69fb0 | 203 | |
1ba15fe6 | 204 | (defun easy-menu-add (menu &optional map)) |
8df69fb0 | 205 | |
029b623a RS |
206 | (provide 'easymenu) |
207 | ||
208 | ;;; easymenu.el ends here |