comparison src/gui.c @ 251:677f6a0ee643 r20-5b24

Import from CVS: tag r20-5b24
author cvs
date Mon, 13 Aug 2007 10:19:59 +0200
parents 557eaa0339bf
children 11cf20601dec
comparison
equal deleted inserted replaced
250:f385a461c9aa 251:677f6a0ee643
21 Boston, MA 02111-1307, USA. */ 21 Boston, MA 02111-1307, USA. */
22 22
23 /* Synched up with: Not in FSF. */ 23 /* Synched up with: Not in FSF. */
24 24
25 #include <config.h> 25 #include <config.h>
26 #include "lisp.h"
26 #include "gui.h" 27 #include "gui.h"
27 #include "lisp.h"
28 28
29 Lisp_Object Q_active, Q_suffix, Q_keys, Q_style, Q_selected; 29 Lisp_Object Q_active, Q_suffix, Q_keys, Q_style, Q_selected;
30 Lisp_Object Q_filter, Q_config, Q_included; 30 Lisp_Object Q_filter, Q_config, Q_included;
31 Lisp_Object Q_accelerator; 31 Lisp_Object Q_accelerator;
32 Lisp_Object Qtoggle, Qradio; 32 Lisp_Object Qtoggle, Qradio;
58 return 0; 58 return 0;
59 for (p = s; *p == first; p++); 59 for (p = s; *p == first; p++);
60 60
61 if (*p == '!' || *p == ':' || *p == '\0') 61 if (*p == '!' || *p == ':' || *p == '\0')
62 return 1; 62 return 1;
63 return 0;
64 }
65
66 /*
67 * Initialize the gui_item structure by setting all (GC-protected)
68 * fields to their default values. The defaults are t for :active and
69 * :included values, and nil for others.
70 */
71 void
72 gui_item_init (struct gui_item *pgui_item)
73 {
74 pgui_item->name = Qnil;
75 pgui_item->callback = Qnil;
76 pgui_item->suffix = Qnil;
77 pgui_item->active = Qt;
78 pgui_item->included = Qt;
79 pgui_item->config = Qunbound;
80 pgui_item->filter = Qnil;
81 pgui_item->style = Qnil;
82 pgui_item->selected = Qnil;
83 pgui_item->keys = Qnil;
84 }
85
86 /*
87 * Add a value VAL associated with keyword KEY into PGUI_ITEM
88 * structure. If KEY is not a keyword, or is an unknown keyword, then
89 * error is signaled.
90 */
91 void
92 gui_item_add_keyval_pair (struct gui_item *pgui_item,
93 Lisp_Object key, Lisp_Object val)
94 {
95 if (!KEYWORDP (key))
96 error ("Not a keyword %S in gui item %S", key, pgui_item->name);
97
98 if (EQ (key, Q_suffix))
99 pgui_item->suffix = val;
100 else if (EQ (key, Q_active))
101 pgui_item->active = val;
102 else if (EQ (key, Q_included))
103 pgui_item->included = val;
104 else if (EQ (key, Q_config))
105 pgui_item->config = val;
106 else if (EQ (key, Q_filter))
107 pgui_item->filter = val;
108 else if (EQ (key, Q_style))
109 pgui_item->style = val;
110 else if (EQ (key, Q_selected))
111 pgui_item->selected = val;
112 else if (EQ (key, Q_keys))
113 pgui_item->keys = val;
114 else
115 error ("Unknown keyword %S in gui item %S", key, pgui_item->name);
116 }
117
118 /*
119 * ITEM is a lisp vector, describing a menu item or a button. The
120 * function extracts the description of the item into the PGUI_ITEM
121 * structure.
122 */
123 void
124 gui_parse_item_keywords (Lisp_Object item, struct gui_item *pgui_item)
125 {
126 int length, plist_p;
127 Lisp_Object *contents;
128
129 CHECK_VECTOR (item);
130 length = XVECTOR_LENGTH (item);
131 contents = XVECTOR_DATA (item);
132
133 if (length < 3)
134 signal_simple_error ("GUI item descriptors must be at least 3 elts long", item);
135
136 /* length 3: [ "name" callback active-p ]
137 length 4: [ "name" callback active-p suffix ]
138 or [ "name" callback keyword value ]
139 length 5+: [ "name" callback [ keyword value ]+ ]
140 */
141 plist_p = (length >= 5 || KEYWORDP (contents [2]));
142
143 pgui_item->name = contents [0];
144 pgui_item->callback = contents [1];
145
146 if (!plist_p)
147 /* the old way */
148 {
149 pgui_item->active = contents [2];
150 if (length == 4)
151 pgui_item->suffix = contents [3];
152 }
153 else
154 /* the new way */
155 {
156 int i;
157 if (length & 1)
158 signal_simple_error (
159 "GUI item descriptor has an odd number of keywords and values",
160 item);
161
162 for (i = 2; i < length;)
163 {
164 Lisp_Object key = contents [i++];
165 Lisp_Object val = contents [i++];
166 gui_item_add_keyval_pair (pgui_item, key, val);
167 }
168 }
169 }
170
171 /*
172 * Decide whether a GUI item is active by evaluating its :active form
173 * if any
174 */
175 int
176 gui_item_active_p (CONST struct gui_item *pgui_item)
177 {
178 /* This function can call lisp */
179
180 /* Shortcut to avoid evaluating Qt each time */
181 return (EQ (pgui_item->active, Qt)
182 || !NILP (Feval (pgui_item->active)));
183 }
184
185 /*
186 * Decide whether a GUI item is included by evaluating its :included
187 * form if given, and testing its :config form against supplied CONFLIST
188 * configuration variable
189 */
190 int
191 gui_item_included_p (CONST struct gui_item *pgui_item, Lisp_Object conflist)
192 {
193 /* This function can call lisp */
194
195 /* Evaluate :included first. Shortcut to avoid evaluating Qt each time */
196 if (!EQ (pgui_item->included, Qt)
197 && NILP (Feval (pgui_item->included)))
198 return 0;
199
200 /* Do :config if conflist is given */
201 if (!NILP (conflist) && !NILP (pgui_item->config)
202 && NILP (Fmemq (pgui_item->config, conflist)))
203 return 0;
204
205 return 1;
206 }
207
208 static DOESNT_RETURN
209 signal_too_long_error (Lisp_Object name)
210 {
211 error ("GUI item %s produces too long displayable string", name);
212 }
213
214 /*
215 * Format "left flush" display portion of an item into BUF, guarded by
216 * maximum buffer size BUF_LEN. BUF_LEN does not count for terminating
217 * null character, so actual maximum size of buffer consumed is
218 * BUF_LEN + 1 bytes. If buffer is not big enough, then error is
219 * signaled.
220 * Return value is the offset to the terminating null character into the
221 * buffer.
222 */
223 unsigned int
224 gui_item_display_flush_left (CONST struct gui_item *pgui_item,
225 char* buf, unsigned int buf_len)
226 {
227 unsigned int consumed;
228
229 /* Copy item name first */
230 CHECK_STRING (pgui_item->name);
231 if (XSTRING_LENGTH (pgui_item->name) > buf_len)
232 signal_too_long_error (pgui_item->name);
233 strcpy (buf, XSTRING_DATA (pgui_item->name));
234 buf += (consumed = XSTRING_LENGTH (pgui_item->name));
235 buf_len -= consumed;
236
237 /* Add space and suffix text, if there is a suffix */
238 if (!NILP (pgui_item->suffix))
239 {
240 if (XSTRING_LENGTH (pgui_item->suffix) + 1 > buf_len)
241 signal_too_long_error (pgui_item->name);
242 *(buf++) = ' ';
243 strcpy (buf, XSTRING_DATA (pgui_item->suffix));
244 consumed += XSTRING_LENGTH (pgui_item->suffix) + 1;
245 }
246
247 return consumed;
248 }
249
250 /*
251 * Format "right flush" display portion of an item into BUF, guarded by
252 * maximum buffer size BUF_LEN. BUF_LEN does not count for terminating
253 * null character, so actual maximum size of buffer consumed is
254 * BUF_LEN + 1 bytes. If buffer is not big enough, then error is
255 * signaled.
256 * Return value is the offset to the terminating null character into the
257 * buffer.
258 */
259 unsigned int
260 gui_item_display_flush_right (CONST struct gui_item *pgui_item,
261 char* buf, unsigned int buf_len)
262 {
263 *buf = 0;
264
265 /* Have keys? */
266 if (!menubar_show_keybindings)
267 return 0;
268
269 /* Try :keys first */
270 if (!NILP (pgui_item->keys))
271 {
272 CHECK_STRING (pgui_item->keys);
273 if (XSTRING_LENGTH (pgui_item->keys) > buf_len)
274 signal_too_long_error (pgui_item->name);
275 strcpy (buf, XSTRING_DATA (pgui_item->keys));
276 return XSTRING_LENGTH (pgui_item->keys);
277 }
278
279 /* See if we can derive keys out of callback symbol */
280 if (SYMBOLP (pgui_item->callback))
281 {
282 char buf2 [1024];
283 unsigned int len;
284
285 where_is_to_char (pgui_item->callback, buf2);
286 len = strlen (buf2);
287 if (len > buf_len)
288 signal_too_long_error (pgui_item->name);
289 strcpy (buf, buf2);
290 return len;
291 }
292
293 /* No keys - no right flush display */
63 return 0; 294 return 0;
64 } 295 }
65 296
66 #endif /* HAVE_POPUPS */ 297 #endif /* HAVE_POPUPS */
67 298