comparison src/gui.c @ 412:697ef44129c6 r21-2-14

Import from CVS: tag r21-2-14
author cvs
date Mon, 13 Aug 2007 11:20:41 +0200
parents 501cfd01ee6d
children e804706bfb8c
comparison
equal deleted inserted replaced
411:12e008d41344 412:697ef44129c6
25 25
26 #include <config.h> 26 #include <config.h>
27 #include "lisp.h" 27 #include "lisp.h"
28 #include "gui.h" 28 #include "gui.h"
29 #include "elhash.h" 29 #include "elhash.h"
30 #include "buffer.h"
31 #include "bytecode.h" 30 #include "bytecode.h"
32 31
33 Lisp_Object Q_active, Q_suffix, Q_keys, Q_style, Q_selected; 32 Lisp_Object Q_active, Q_suffix, Q_keys, Q_style, Q_selected;
34 Lisp_Object Q_filter, Q_config, Q_included, Q_key_sequence; 33 Lisp_Object Q_filter, Q_config, Q_included, Q_key_sequence;
35 Lisp_Object Q_accelerator, Q_label, Q_callback, Q_callback_ex, Q_value; 34 Lisp_Object Q_accelerator, Q_label, Q_callback;
36 Lisp_Object Qtoggle, Qradio; 35 Lisp_Object Qtoggle, Qradio;
37
38 static Lisp_Object parse_gui_item_tree_list (Lisp_Object list);
39 36
40 #ifdef HAVE_POPUPS 37 #ifdef HAVE_POPUPS
41 38
42 /* count of menus/dboxes currently up */ 39 /* count of menus/dboxes currently up */
43 int popup_up_p; 40 int popup_up_p;
51 return popup_up_p ? Qt : Qnil; 48 return popup_up_p ? Qt : Qnil;
52 } 49 }
53 #endif /* HAVE_POPUPS */ 50 #endif /* HAVE_POPUPS */
54 51
55 int 52 int
56 separator_string_p (const char *s) 53 separator_string_p (CONST char *s)
57 { 54 {
58 const char *p; 55 CONST char *p;
59 char first; 56 char first;
60 57
61 if (!s || s[0] == '\0') 58 if (!s || s[0] == '\0')
62 return 0; 59 return 0;
63 first = s[0]; 60 first = s[0];
72 /* Massage DATA to find the correct function and argument. Used by 69 /* Massage DATA to find the correct function and argument. Used by
73 popup_selection_callback() and the msw code. */ 70 popup_selection_callback() and the msw code. */
74 void 71 void
75 get_gui_callback (Lisp_Object data, Lisp_Object *fn, Lisp_Object *arg) 72 get_gui_callback (Lisp_Object data, Lisp_Object *fn, Lisp_Object *arg)
76 { 73 {
77 if (EQ (data, Qquit)) 74 if (SYMBOLP (data)
78 { 75 || (COMPILED_FUNCTIONP (data)
79 *fn = Qeval; 76 && XCOMPILED_FUNCTION (data)->flags.interactivep)
80 *arg = list3 (Qsignal, list2 (Qquote, Qquit), Qnil); 77 || (EQ (XCAR (data), Qlambda)
81 Vquit_flag = Qt; 78 && !NILP (Fassq (Qinteractive, Fcdr (Fcdr (data))))))
82 }
83 else if (SYMBOLP (data)
84 || (COMPILED_FUNCTIONP (data)
85 && XCOMPILED_FUNCTION (data)->flags.interactivep)
86 || (CONSP (data) && (EQ (XCAR (data), Qlambda))
87 && !NILP (Fassq (Qinteractive, Fcdr (Fcdr (data))))))
88 { 79 {
89 *fn = Qcall_interactively; 80 *fn = Qcall_interactively;
90 *arg = data; 81 *arg = data;
91 } 82 }
92 else if (CONSP (data)) 83 else if (CONSP (data))
104 data))); 95 data)));
105 } 96 }
106 } 97 }
107 98
108 /* 99 /*
100 * Initialize the gui_item structure by setting all (GC-protected)
101 * fields to their default values. The defaults are t for :active and
102 * :included values, and nil for others.
103 */
104 void
105 gui_item_init (struct gui_item *pgui_item)
106 {
107 pgui_item->name = Qnil;
108 pgui_item->callback = Qnil;
109 pgui_item->suffix = Qnil;
110 pgui_item->active = Qt;
111 pgui_item->included = Qt;
112 pgui_item->config = Qnil;
113 pgui_item->filter = Qnil;
114 pgui_item->style = Qnil;
115 pgui_item->selected = Qnil;
116 pgui_item->keys = Qnil;
117 }
118
119 /*
109 * Add a value VAL associated with keyword KEY into PGUI_ITEM 120 * Add a value VAL associated with keyword KEY into PGUI_ITEM
110 * structure. If KEY is not a keyword, or is an unknown keyword, then 121 * structure. If KEY is not a keyword, or is an unknown keyword, then
111 * error is signaled. 122 * error is signaled.
112 */ 123 */
113 void 124 void
114 gui_item_add_keyval_pair (Lisp_Object gui_item, 125 gui_item_add_keyval_pair (struct gui_item *pgui_item,
115 Lisp_Object key, Lisp_Object val, 126 Lisp_Object key, Lisp_Object val,
116 Error_behavior errb) 127 Error_behavior errb)
117 { 128 {
118 Lisp_Gui_Item *pgui_item = XGUI_ITEM (gui_item);
119
120 if (!KEYWORDP (key)) 129 if (!KEYWORDP (key))
121 signal_simple_error_2 ("Non-keyword in gui item", key, pgui_item->name); 130 signal_simple_error_2 ("Non-keyword in gui item", key, pgui_item->name);
122 131
123 if (EQ (key, Q_suffix)) pgui_item->suffix = val; 132 if (EQ (key, Q_suffix)) pgui_item->suffix = val;
124 else if (EQ (key, Q_active)) pgui_item->active = val; 133 else if (EQ (key, Q_active)) pgui_item->active = val;
126 else if (EQ (key, Q_config)) pgui_item->config = val; 135 else if (EQ (key, Q_config)) pgui_item->config = val;
127 else if (EQ (key, Q_filter)) pgui_item->filter = val; 136 else if (EQ (key, Q_filter)) pgui_item->filter = val;
128 else if (EQ (key, Q_style)) pgui_item->style = val; 137 else if (EQ (key, Q_style)) pgui_item->style = val;
129 else if (EQ (key, Q_selected)) pgui_item->selected = val; 138 else if (EQ (key, Q_selected)) pgui_item->selected = val;
130 else if (EQ (key, Q_keys)) pgui_item->keys = val; 139 else if (EQ (key, Q_keys)) pgui_item->keys = val;
131 else if (EQ (key, Q_callback)) pgui_item->callback = val; 140 else if (EQ (key, Q_callback)) pgui_item->callback = val;
132 else if (EQ (key, Q_callback_ex)) pgui_item->callback_ex = val; 141 else if (EQ (key, Q_key_sequence)) ; /* ignored for FSF compatability */
133 else if (EQ (key, Q_value)) pgui_item->value = val;
134 else if (EQ (key, Q_key_sequence)) ; /* ignored for FSF compatibility */
135 else if (EQ (key, Q_label)) ; /* ignored for 21.0 implement in 21.2 */ 142 else if (EQ (key, Q_label)) ; /* ignored for 21.0 implement in 21.2 */
136 else if (EQ (key, Q_accelerator))
137 {
138 if (SYMBOLP (val) || CHARP (val))
139 pgui_item->accelerator = val;
140 else if (ERRB_EQ (errb, ERROR_ME))
141 signal_simple_error ("Bad keyboard accelerator", val);
142 }
143 else if (ERRB_EQ (errb, ERROR_ME)) 143 else if (ERRB_EQ (errb, ERROR_ME))
144 signal_simple_error_2 ("Unknown keyword in gui item", key, 144 signal_simple_error_2 ("Unknown keyword in gui item", key, pgui_item->name);
145 pgui_item->name);
146 }
147
148 void
149 gui_item_init (Lisp_Object gui_item)
150 {
151 Lisp_Gui_Item *lp = XGUI_ITEM (gui_item);
152
153 lp->name = Qnil;
154 lp->callback = Qnil;
155 lp->callback_ex = Qnil;
156 lp->suffix = Qnil;
157 lp->active = Qt;
158 lp->included = Qt;
159 lp->config = Qnil;
160 lp->filter = Qnil;
161 lp->style = Qnil;
162 lp->selected = Qnil;
163 lp->keys = Qnil;
164 lp->accelerator = Qnil;
165 lp->value = Qnil;
166 }
167
168 Lisp_Object
169 allocate_gui_item (void)
170 {
171 Lisp_Gui_Item *lp = alloc_lcrecord_type (Lisp_Gui_Item, &lrecord_gui_item);
172 Lisp_Object val;
173
174 zero_lcrecord (lp);
175 XSETGUI_ITEM (val, lp);
176
177 gui_item_init (val);
178
179 return val;
180 } 145 }
181 146
182 /* 147 /*
183 * ITEM is a lisp vector, describing a menu item or a button. The 148 * ITEM is a lisp vector, describing a menu item or a button. The
184 * function extracts the description of the item into the PGUI_ITEM 149 * function extracts the description of the item into the PGUI_ITEM
185 * structure. 150 * structure.
186 */ 151 */
187 static Lisp_Object 152 static void
188 make_gui_item_from_keywords_internal (Lisp_Object item, 153 gui_parse_item_keywords_internal (Lisp_Object item, struct gui_item *pgui_item,
189 Error_behavior errb) 154 Error_behavior errb)
190 { 155 {
191 int length, plist_p, start; 156 int length, plist_p, start;
192 Lisp_Object *contents; 157 Lisp_Object *contents;
193 Lisp_Object gui_item = allocate_gui_item ();
194 Lisp_Gui_Item *pgui_item = XGUI_ITEM (gui_item);
195 158
196 CHECK_VECTOR (item); 159 CHECK_VECTOR (item);
197 length = XVECTOR_LENGTH (item); 160 length = XVECTOR_LENGTH (item);
198 contents = XVECTOR_DATA (item); 161 contents = XVECTOR_DATA (item);
199 162
216 if (length > 1 && !KEYWORDP (contents [1])) 179 if (length > 1 && !KEYWORDP (contents [1]))
217 { 180 {
218 pgui_item->callback = contents [1]; 181 pgui_item->callback = contents [1];
219 start = 2; 182 start = 2;
220 } 183 }
221 else 184 else
222 start =1; 185 start =1;
223 186
224 if (!plist_p && length > 2) 187 if (!plist_p && length > 2)
225 /* the old way */ 188 /* the old way */
226 { 189 {
239 202
240 for (i = start; i < length;) 203 for (i = start; i < length;)
241 { 204 {
242 Lisp_Object key = contents [i++]; 205 Lisp_Object key = contents [i++];
243 Lisp_Object val = contents [i++]; 206 Lisp_Object val = contents [i++];
244 gui_item_add_keyval_pair (gui_item, key, val, errb); 207 gui_item_add_keyval_pair (pgui_item, key, val, errb);
245 } 208 }
246 } 209 }
247 return gui_item; 210 }
248 } 211
249 212 void
250 Lisp_Object 213 gui_parse_item_keywords (Lisp_Object item, struct gui_item *pgui_item)
251 gui_parse_item_keywords (Lisp_Object item) 214 {
252 { 215 gui_parse_item_keywords_internal (item, pgui_item, ERROR_ME);
253 return make_gui_item_from_keywords_internal (item, ERROR_ME); 216 }
254 } 217
255 218 void
256 Lisp_Object 219 gui_parse_item_keywords_no_errors (Lisp_Object item, struct gui_item *pgui_item)
257 gui_parse_item_keywords_no_errors (Lisp_Object item) 220 {
258 { 221 gui_parse_item_keywords_internal (item, pgui_item, ERROR_ME_NOT);
259 return make_gui_item_from_keywords_internal (item, ERROR_ME_NOT);
260 }
261
262 /* convert a gui item into plist properties */
263 void
264 gui_add_item_keywords_to_plist (Lisp_Object plist, Lisp_Object gui_item)
265 {
266 Lisp_Gui_Item *pgui_item = XGUI_ITEM (gui_item);
267
268 if (!NILP (pgui_item->callback))
269 Fplist_put (plist, Q_callback, pgui_item->callback);
270 if (!NILP (pgui_item->callback_ex))
271 Fplist_put (plist, Q_callback_ex, pgui_item->callback_ex);
272 if (!NILP (pgui_item->suffix))
273 Fplist_put (plist, Q_suffix, pgui_item->suffix);
274 if (!NILP (pgui_item->active))
275 Fplist_put (plist, Q_active, pgui_item->active);
276 if (!NILP (pgui_item->included))
277 Fplist_put (plist, Q_included, pgui_item->included);
278 if (!NILP (pgui_item->config))
279 Fplist_put (plist, Q_config, pgui_item->config);
280 if (!NILP (pgui_item->filter))
281 Fplist_put (plist, Q_filter, pgui_item->filter);
282 if (!NILP (pgui_item->style))
283 Fplist_put (plist, Q_style, pgui_item->style);
284 if (!NILP (pgui_item->selected))
285 Fplist_put (plist, Q_selected, pgui_item->selected);
286 if (!NILP (pgui_item->keys))
287 Fplist_put (plist, Q_keys, pgui_item->keys);
288 if (!NILP (pgui_item->accelerator))
289 Fplist_put (plist, Q_accelerator, pgui_item->accelerator);
290 if (!NILP (pgui_item->value))
291 Fplist_put (plist, Q_value, pgui_item->value);
292 } 222 }
293 223
294 /* 224 /*
295 * Decide whether a GUI item is active by evaluating its :active form 225 * Decide whether a GUI item is active by evaluating its :active form
296 * if any 226 * if any
297 */ 227 */
298 int 228 int
299 gui_item_active_p (Lisp_Object gui_item) 229 gui_item_active_p (CONST struct gui_item *pgui_item)
300 { 230 {
301 /* This function can call lisp */ 231 /* This function can call lisp */
302 232
303 /* Shortcut to avoid evaluating Qt each time */ 233 /* Shortcut to avoid evaluating Qt each time */
304 return (EQ (XGUI_ITEM (gui_item)->active, Qt) 234 return (EQ (pgui_item->active, Qt)
305 || !NILP (Feval (XGUI_ITEM (gui_item)->active))); 235 || !NILP (Feval (pgui_item->active)));
306 }
307
308 /* set menu accelerator key to first underlined character in menu name */
309 Lisp_Object
310 gui_item_accelerator (Lisp_Object gui_item)
311 {
312 Lisp_Gui_Item *pgui = XGUI_ITEM (gui_item);
313
314 if (!NILP (pgui->accelerator))
315 return pgui->accelerator;
316
317 else
318 return gui_name_accelerator (pgui->name);
319 }
320
321 Lisp_Object
322 gui_name_accelerator (Lisp_Object nm)
323 {
324 Bufbyte *name = XSTRING_DATA (nm);
325
326 while (*name)
327 {
328 if (*name == '%')
329 {
330 ++name;
331 if (!(*name))
332 return Qnil;
333 if (*name == '_' && *(name + 1))
334 {
335 Emchar accelerator = charptr_emchar (name + 1);
336 /* #### bogus current_buffer dependency */
337 return make_char (DOWNCASE (current_buffer, accelerator));
338 }
339 }
340 INC_CHARPTR (name);
341 }
342 return make_char (DOWNCASE (current_buffer,
343 charptr_emchar (XSTRING_DATA (nm))));
344 } 236 }
345 237
346 /* 238 /*
347 * Decide whether a GUI item is selected by evaluating its :selected form 239 * Decide whether a GUI item is selected by evaluating its :selected form
348 * if any 240 * if any
349 */ 241 */
350 int 242 int
351 gui_item_selected_p (Lisp_Object gui_item) 243 gui_item_selected_p (CONST struct gui_item *pgui_item)
352 { 244 {
353 /* This function can call lisp */ 245 /* This function can call lisp */
354 246
355 /* Shortcut to avoid evaluating Qt each time */ 247 /* Shortcut to avoid evaluating Qt each time */
356 return (EQ (XGUI_ITEM (gui_item)->selected, Qt) 248 return (EQ (pgui_item->selected, Qt)
357 || !NILP (Feval (XGUI_ITEM (gui_item)->selected))); 249 || !NILP (Feval (pgui_item->selected)));
358 } 250 }
359 251
360 /* 252 /*
361 * Decide whether a GUI item is included by evaluating its :included 253 * Decide whether a GUI item is included by evaluating its :included
362 * form if given, and testing its :config form against supplied CONFLIST 254 * form if given, and testing its :config form against supplied CONFLIST
363 * configuration variable 255 * configuration variable
364 */ 256 */
365 int 257 int
366 gui_item_included_p (Lisp_Object gui_item, Lisp_Object conflist) 258 gui_item_included_p (CONST struct gui_item *pgui_item, Lisp_Object conflist)
367 { 259 {
368 /* This function can call lisp */ 260 /* This function can call lisp */
369 Lisp_Gui_Item *pgui_item = XGUI_ITEM (gui_item);
370 261
371 /* Evaluate :included first. Shortcut to avoid evaluating Qt each time */ 262 /* Evaluate :included first. Shortcut to avoid evaluating Qt each time */
372 if (!EQ (pgui_item->included, Qt) 263 if (!EQ (pgui_item->included, Qt)
373 && NILP (Feval (pgui_item->included))) 264 && NILP (Feval (pgui_item->included)))
374 return 0; 265 return 0;
396 * signaled. 287 * signaled.
397 * Return value is the offset to the terminating null character into the 288 * Return value is the offset to the terminating null character into the
398 * buffer. 289 * buffer.
399 */ 290 */
400 unsigned int 291 unsigned int
401 gui_item_display_flush_left (Lisp_Object gui_item, 292 gui_item_display_flush_left (CONST struct gui_item *pgui_item,
402 char *buf, Bytecount buf_len) 293 char* buf, Bytecount buf_len)
403 { 294 {
404 /* This function can call lisp */
405 char *p = buf; 295 char *p = buf;
406 Bytecount len; 296 Bytecount len;
407 Lisp_Gui_Item *pgui_item = XGUI_ITEM (gui_item);
408 297
409 /* Copy item name first */ 298 /* Copy item name first */
410 CHECK_STRING (pgui_item->name); 299 CHECK_STRING (pgui_item->name);
411 len = XSTRING_LENGTH (pgui_item->name); 300 len = XSTRING_LENGTH (pgui_item->name);
412 if (len > buf_len) 301 if (len > buf_len)
445 * signaled. 334 * signaled.
446 * Return value is the offset to the terminating null character into the 335 * Return value is the offset to the terminating null character into the
447 * buffer. 336 * buffer.
448 */ 337 */
449 unsigned int 338 unsigned int
450 gui_item_display_flush_right (Lisp_Object gui_item, 339 gui_item_display_flush_right (CONST struct gui_item *pgui_item,
451 char *buf, Bytecount buf_len) 340 char* buf, Bytecount buf_len)
452 { 341 {
453 Lisp_Gui_Item *pgui_item = XGUI_ITEM (gui_item);
454 *buf = 0; 342 *buf = 0;
455 343
456 #ifdef HAVE_MENUBARS
457 /* Have keys? */ 344 /* Have keys? */
458 if (!menubar_show_keybindings) 345 if (!menubar_show_keybindings)
459 return 0; 346 return 0;
460 #endif
461 347
462 /* Try :keys first */ 348 /* Try :keys first */
463 if (!NILP (pgui_item->keys)) 349 if (!NILP (pgui_item->keys))
464 { 350 {
465 CHECK_STRING (pgui_item->keys); 351 CHECK_STRING (pgui_item->keys);
466 if (XSTRING_LENGTH (pgui_item->keys) + 1 > buf_len) 352 if (XSTRING_LENGTH (pgui_item->keys) > buf_len)
467 signal_too_long_error (pgui_item->name); 353 signal_too_long_error (pgui_item->name);
468 memcpy (buf, XSTRING_DATA (pgui_item->keys), 354 strcpy (buf, (CONST char *) XSTRING_DATA (pgui_item->keys));
469 XSTRING_LENGTH (pgui_item->keys) + 1);
470 return XSTRING_LENGTH (pgui_item->keys); 355 return XSTRING_LENGTH (pgui_item->keys);
471 } 356 }
472 357
473 /* See if we can derive keys out of callback symbol */ 358 /* See if we can derive keys out of callback symbol */
474 if (SYMBOLP (pgui_item->callback)) 359 if (SYMBOLP (pgui_item->callback))
475 { 360 {
476 char buf2[1024]; /* #### */ 361 char buf2 [1024];
477 Bytecount len; 362 Bytecount len;
478 363
479 where_is_to_char (pgui_item->callback, buf2); 364 where_is_to_char (pgui_item->callback, buf2);
480 len = strlen (buf2); 365 len = strlen (buf2);
481 if (len > buf_len) 366 if (len > buf_len)
487 /* No keys - no right flush display */ 372 /* No keys - no right flush display */
488 return 0; 373 return 0;
489 } 374 }
490 #endif /* HAVE_WINDOW_SYSTEM */ 375 #endif /* HAVE_WINDOW_SYSTEM */
491 376
492 static Lisp_Object 377 Lisp_Object
493 mark_gui_item (Lisp_Object obj) 378 mark_gui_item (struct gui_item* p, void (*markobj) (Lisp_Object))
494 { 379 {
495 Lisp_Gui_Item *p = XGUI_ITEM (obj); 380 markobj (p->name);
496 381 markobj (p->callback);
497 mark_object (p->name); 382 markobj (p->suffix);
498 mark_object (p->callback); 383 markobj (p->active);
499 mark_object (p->callback_ex); 384 markobj (p->included);
500 mark_object (p->config); 385 markobj (p->config);
501 mark_object (p->suffix); 386 markobj (p->filter);
502 mark_object (p->active); 387 markobj (p->style);
503 mark_object (p->included); 388 markobj (p->selected);
504 mark_object (p->config); 389 markobj (p->keys);
505 mark_object (p->filter);
506 mark_object (p->style);
507 mark_object (p->selected);
508 mark_object (p->keys);
509 mark_object (p->accelerator);
510 mark_object (p->value);
511 390
512 return Qnil; 391 return Qnil;
513 } 392 }
514 393
515 static unsigned long
516 gui_item_hash (Lisp_Object obj, int depth)
517 {
518 Lisp_Gui_Item *p = XGUI_ITEM (obj);
519
520 return HASH2 (HASH6 (internal_hash (p->name, depth + 1),
521 internal_hash (p->callback, depth + 1),
522 internal_hash (p->callback_ex, depth + 1),
523 internal_hash (p->suffix, depth + 1),
524 internal_hash (p->active, depth + 1),
525 internal_hash (p->included, depth + 1)),
526 HASH6 (internal_hash (p->config, depth + 1),
527 internal_hash (p->filter, depth + 1),
528 internal_hash (p->style, depth + 1),
529 internal_hash (p->selected, depth + 1),
530 internal_hash (p->keys, depth + 1),
531 internal_hash (p->value, depth + 1)));
532 }
533
534 int 394 int
535 gui_item_id_hash (Lisp_Object hashtable, Lisp_Object gitem, int slot) 395 gui_item_hash (Lisp_Object hashtable, struct gui_item* g, int slot)
536 { 396 {
537 int hashid = gui_item_hash (gitem, 0); 397 int hashid = HASH2 (internal_hash (g->callback, 0), internal_hash (g->name, 0));
538 int id = GUI_ITEM_ID_BITS (hashid, slot); 398 int id = GUI_ITEM_ID_BITS (hashid, slot);
539 while (!NILP (Fgethash (make_int (id), 399 while (!NILP (Fgethash (make_int (id),
540 hashtable, Qnil))) 400 hashtable, Qnil)))
541 { 401 {
542 id = GUI_ITEM_ID_BITS (id + 1, slot); 402 id = GUI_ITEM_ID_BITS (id + 1, slot);
543 } 403 }
544 return id; 404 return id;
545 } 405 }
546 406
547 static int
548 gui_item_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
549 {
550 Lisp_Gui_Item *p1 = XGUI_ITEM (obj1);
551 Lisp_Gui_Item *p2 = XGUI_ITEM (obj2);
552
553 if (!(internal_equal (p1->name, p2->name, depth + 1)
554 &&
555 internal_equal (p1->callback, p2->callback, depth + 1)
556 &&
557 internal_equal (p1->callback_ex, p2->callback_ex, depth + 1)
558 &&
559 EQ (p1->suffix, p2->suffix)
560 &&
561 EQ (p1->active, p2->active)
562 &&
563 EQ (p1->included, p2->included)
564 &&
565 EQ (p1->config, p2->config)
566 &&
567 EQ (p1->filter, p2->filter)
568 &&
569 EQ (p1->style, p2->style)
570 &&
571 EQ (p1->selected, p2->selected)
572 &&
573 EQ (p1->accelerator, p2->accelerator)
574 &&
575 EQ (p1->keys, p2->keys)
576 &&
577 EQ (p1->value, p2->value)))
578 return 0;
579 return 1;
580 }
581
582 static void
583 print_gui_item (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
584 {
585 Lisp_Gui_Item *g = XGUI_ITEM (obj);
586 char buf[20];
587
588 if (print_readably)
589 error ("printing unreadable object #<gui-item 0x%x>", g->header.uid);
590
591 write_c_string ("#<gui-item ", printcharfun);
592 sprintf (buf, "0x%x>", g->header.uid);
593 write_c_string (buf, printcharfun);
594 }
595
596 static Lisp_Object
597 copy_gui_item (Lisp_Object gui_item)
598 {
599 Lisp_Object ret = allocate_gui_item ();
600 Lisp_Gui_Item *lp, *g = XGUI_ITEM (gui_item);
601
602 lp = XGUI_ITEM (ret);
603 lp->name = g->name;
604 lp->callback = g->callback;
605 lp->callback_ex = g->callback_ex;
606 lp->suffix = g->suffix;
607 lp->active = g->active;
608 lp->included = g->included;
609 lp->config = g->config;
610 lp->filter = g->filter;
611 lp->style = g->style;
612 lp->selected = g->selected;
613 lp->keys = g->keys;
614 lp->accelerator = g->accelerator;
615 lp->value = g->value;
616
617 return ret;
618 }
619
620 Lisp_Object
621 copy_gui_item_tree (Lisp_Object arg)
622 {
623 if (CONSP (arg))
624 {
625 Lisp_Object rest = arg = Fcopy_sequence (arg);
626 while (CONSP (rest))
627 {
628 XCAR (rest) = copy_gui_item_tree (XCAR (rest));
629 rest = XCDR (rest);
630 }
631 return arg;
632 }
633 else if (GUI_ITEMP (arg))
634 return copy_gui_item (arg);
635 else
636 return arg;
637 }
638
639 /* parse a glyph descriptor into a tree of gui items.
640
641 The gui_item slot of an image instance can be a single item or an
642 arbitrarily nested hierarchy of item lists. */
643
644 static Lisp_Object
645 parse_gui_item_tree_item (Lisp_Object entry)
646 {
647 Lisp_Object ret = entry;
648 struct gcpro gcpro1;
649
650 GCPRO1 (ret);
651
652 if (VECTORP (entry))
653 {
654 ret = gui_parse_item_keywords_no_errors (entry);
655 }
656 else if (STRINGP (entry))
657 {
658 CHECK_STRING (entry);
659 }
660 else
661 signal_simple_error ("item must be a vector or a string", entry);
662
663 RETURN_UNGCPRO (ret);
664 }
665
666 Lisp_Object
667 parse_gui_item_tree_children (Lisp_Object list)
668 {
669 Lisp_Object rest, ret = Qnil, sub = Qnil;
670 struct gcpro gcpro1, gcpro2;
671
672 GCPRO2 (ret, sub);
673 CHECK_CONS (list);
674 /* recursively add items to the tree view */
675 LIST_LOOP (rest, list)
676 {
677 if (CONSP (XCAR (rest)))
678 sub = parse_gui_item_tree_list (XCAR (rest));
679 else
680 sub = parse_gui_item_tree_item (XCAR (rest));
681
682 ret = Fcons (sub, ret);
683 }
684 /* make the order the same as the items we have parsed */
685 RETURN_UNGCPRO (Fnreverse (ret));
686 }
687
688 static Lisp_Object
689 parse_gui_item_tree_list (Lisp_Object list)
690 {
691 Lisp_Object ret;
692 struct gcpro gcpro1;
693 CHECK_CONS (list);
694 /* first one can never be a list */
695 ret = parse_gui_item_tree_item (XCAR (list));
696 GCPRO1 (ret);
697 ret = Fcons (ret, parse_gui_item_tree_children (XCDR (list)));
698 RETURN_UNGCPRO (ret);
699 }
700
701 static void
702 finalize_gui_item (void* header, int for_disksave)
703 {
704 }
705
706 DEFINE_LRECORD_IMPLEMENTATION ("gui-item", gui_item,
707 mark_gui_item, print_gui_item,
708 finalize_gui_item, gui_item_equal,
709 gui_item_hash,
710 0,
711 Lisp_Gui_Item);
712
713 void 407 void
714 syms_of_gui (void) 408 syms_of_gui (void)
715 { 409 {
716 INIT_LRECORD_IMPLEMENTATION (gui_item);
717
718 defkeyword (&Q_active, ":active"); 410 defkeyword (&Q_active, ":active");
719 defkeyword (&Q_suffix, ":suffix"); 411 defkeyword (&Q_suffix, ":suffix");
720 defkeyword (&Q_keys, ":keys"); 412 defkeyword (&Q_keys, ":keys");
721 defkeyword (&Q_key_sequence,":key-sequence"); 413 defkeyword (&Q_key_sequence,":key-sequence");
722 defkeyword (&Q_style, ":style"); 414 defkeyword (&Q_style, ":style");
725 defkeyword (&Q_config, ":config"); 417 defkeyword (&Q_config, ":config");
726 defkeyword (&Q_included, ":included"); 418 defkeyword (&Q_included, ":included");
727 defkeyword (&Q_accelerator, ":accelerator"); 419 defkeyword (&Q_accelerator, ":accelerator");
728 defkeyword (&Q_label, ":label"); 420 defkeyword (&Q_label, ":label");
729 defkeyword (&Q_callback, ":callback"); 421 defkeyword (&Q_callback, ":callback");
730 defkeyword (&Q_callback_ex, ":callback-ex");
731 defkeyword (&Q_value, ":value");
732 422
733 defsymbol (&Qtoggle, "toggle"); 423 defsymbol (&Qtoggle, "toggle");
734 defsymbol (&Qradio, "radio"); 424 defsymbol (&Qradio, "radio");
735 425
736 #ifdef HAVE_POPUPS 426 #ifdef HAVE_POPUPS