Mercurial > hg > xemacs-beta
annotate src/gui.c @ 5624:c39052c921b5
New "foreback" face property.
-------------------- ChangeLog entries follow: --------------------
lisp/ChangeLog addition:
2011-12-27 Didier Verna <didier@xemacs.org>
* cl-macs.el (face-foreback): New defsetf.
* faces.el (set-face-property): Document the foreback property.
* faces.el (face-foreback):
* faces.el (face-foreback-instance):
* faces.el (face-foreback-name):
* faces.el (set-face-foreback): New functions.
* faces.el (face-equal):
* faces.el (init-other-random-faces):
* cus-face.el (custom-face-attributes):
* x-faces.el (x-init-face-from-resources): Handle the foreback
property.
src/ChangeLog addition:
2011-12-27 Didier Verna <didier@xemacs.org>
* faces.h (struct Lisp_Face): New 'foreback slot.
* faces.h (struct face_cachel): New 'foreback and
'foreback_specified slots.
* faces.h (WINDOW_FACE_CACHEL_FOREBACK):
* faces.h (FACE_FOREBACK): New macros.
* faces.c: Declare Qforeback.
* lisp.h: Externalize it.
* faces.c (syms_of_faces): Define it.
* faces.c (vars_of_faces): Update built-in face specifiers.
* faces.c (complex_vars_of_faces): Update specifier fallbacks.
* faces.c (mark_face):
* faces.c (face_equal):
* faces.c (face_getprop):
* faces.c (face_putprop):
* faces.c (face_remprop):
* faces.c (face_plist):
* faces.c (reset_face):
* faces.c (update_face_inheritance_mapper):
* faces.c (Fmake_face):
* faces.c (mark_face_cachels):
* faces.c (update_face_cachel_data):
* faces.c (merge_face_cachel_data):
* faces.c (reset_face_cachel):
* faces.c (face_property_was_changed):
* faces.c (Fcopy_face):
* fontcolor.c (face_color_validate): Handle the foreback property.
* redisplay-msw.c (mswindows_output_blank):
* redisplay-msw.c (mswindows_output_string):
* redisplay-output.c (redisplay_clear_region):
* redisplay-xlike-inc.c (XLIKE_output_string):
* redisplay-xlike-inc.c (XLIKE_output_blank): Use the face's
foreback color instead of the foreground one for drawing a
background bitmap.
author | Didier Verna <didier@xemacs.org> |
---|---|
date | Tue, 27 Dec 2011 17:07:23 +0100 |
parents | 56144c8593a8 |
children | 68f8d295be49 |
rev | line source |
---|---|
428 | 1 /* Generic GUI code. (menubars, scrollbars, toolbars, dialogs) |
2 Copyright (C) 1995 Board of Trustees, University of Illinois. | |
5146
88bd4f3ef8e4
make lrecord UID's have a separate UID space for each object, resurrect debug SOE code in extents.c
Ben Wing <ben@xemacs.org>
parents:
5142
diff
changeset
|
3 Copyright (C) 1995, 1996, 2000, 2001, 2002, 2003, 2010 Ben Wing. |
428 | 4 Copyright (C) 1995 Sun Microsystems, Inc. |
5 Copyright (C) 1998 Free Software Foundation, Inc. | |
6 | |
7 This file is part of XEmacs. | |
8 | |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5191
diff
changeset
|
9 XEmacs is free software: you can redistribute it and/or modify it |
428 | 10 under the terms of the GNU General Public License as published by the |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5191
diff
changeset
|
11 Free Software Foundation, either version 3 of the License, or (at your |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5191
diff
changeset
|
12 option) any later version. |
428 | 13 |
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5191
diff
changeset
|
20 along with XEmacs. If not, see <http://www.gnu.org/licenses/>. */ |
428 | 21 |
22 /* Synched up with: Not in FSF. */ | |
23 | |
793 | 24 /* This file Mule-ized by Ben Wing, 3-24-02. */ |
442 | 25 |
428 | 26 #include <config.h> |
27 #include "lisp.h" | |
872 | 28 |
442 | 29 #include "buffer.h" |
428 | 30 #include "bytecode.h" |
872 | 31 #include "elhash.h" |
32 #include "gui.h" | |
33 #include "menubar.h" | |
1318 | 34 #include "redisplay.h" |
428 | 35 |
442 | 36 Lisp_Object Qmenu_no_selection_hook; |
37 Lisp_Object Vmenu_no_selection_hook; | |
428 | 38 |
39 static Lisp_Object parse_gui_item_tree_list (Lisp_Object list); | |
454 | 40 Lisp_Object find_keyword_in_vector (Lisp_Object vector, Lisp_Object keyword); |
428 | 41 |
563 | 42 Lisp_Object Qgui_error; |
43 | |
428 | 44 #ifdef HAVE_POPUPS |
45 | |
46 /* count of menus/dboxes currently up */ | |
47 int popup_up_p; | |
48 | |
49 DEFUN ("popup-up-p", Fpopup_up_p, 0, 0, 0, /* | |
50 Return t if a popup menu or dialog box is up, nil otherwise. | |
51 See `popup-menu' and `popup-dialog-box'. | |
52 */ | |
53 ()) | |
54 { | |
55 return popup_up_p ? Qt : Qnil; | |
56 } | |
57 #endif /* HAVE_POPUPS */ | |
58 | |
59 int | |
867 | 60 separator_string_p (const Ibyte *s) |
428 | 61 { |
867 | 62 const Ibyte *p; |
63 Ibyte first; | |
428 | 64 |
65 if (!s || s[0] == '\0') | |
66 return 0; | |
67 first = s[0]; | |
68 if (first != '-' && first != '=') | |
69 return 0; | |
70 for (p = s; *p == first; p++) | |
71 ; | |
72 | |
73 return (*p == '!' || *p == ':' || *p == '\0'); | |
74 } | |
75 | |
76 /* Massage DATA to find the correct function and argument. Used by | |
77 popup_selection_callback() and the msw code. */ | |
78 void | |
79 get_gui_callback (Lisp_Object data, Lisp_Object *fn, Lisp_Object *arg) | |
80 { | |
442 | 81 if (EQ (data, Qquit)) |
82 { | |
83 *fn = Qeval; | |
84 *arg = list3 (Qsignal, list2 (Qquote, Qquit), Qnil); | |
85 Vquit_flag = Qt; | |
86 } | |
87 else if (SYMBOLP (data) | |
88 || (COMPILED_FUNCTIONP (data) | |
89 && XCOMPILED_FUNCTION (data)->flags.interactivep) | |
90 || (CONSP (data) && (EQ (XCAR (data), Qlambda)) | |
91 && !NILP (Fassq (Qinteractive, Fcdr (Fcdr (data)))))) | |
428 | 92 { |
93 *fn = Qcall_interactively; | |
94 *arg = data; | |
95 } | |
96 else if (CONSP (data)) | |
97 { | |
98 *fn = Qeval; | |
99 *arg = data; | |
100 } | |
101 else | |
102 { | |
103 *fn = Qeval; | |
104 *arg = list3 (Qsignal, | |
105 list2 (Qquote, Qerror), | |
771 | 106 list2 (Qquote, list2 (build_msg_string |
428 | 107 ("illegal callback"), |
108 data))); | |
109 } | |
110 } | |
111 | |
112 /* | |
113 * Add a value VAL associated with keyword KEY into PGUI_ITEM | |
114 * structure. If KEY is not a keyword, or is an unknown keyword, then | |
115 * error is signaled. | |
116 */ | |
454 | 117 int |
428 | 118 gui_item_add_keyval_pair (Lisp_Object gui_item, |
440 | 119 Lisp_Object key, Lisp_Object val, |
578 | 120 Error_Behavior errb) |
428 | 121 { |
442 | 122 Lisp_Gui_Item *pgui_item = XGUI_ITEM (gui_item); |
454 | 123 int retval = 0; |
428 | 124 |
125 if (!KEYWORDP (key)) | |
563 | 126 sferror_2 ("Non-keyword in gui item", key, pgui_item->name); |
428 | 127 |
454 | 128 if (EQ (key, Q_descriptor)) |
129 { | |
130 if (!EQ (pgui_item->name, val)) | |
131 { | |
132 retval = 1; | |
133 pgui_item->name = val; | |
134 } | |
135 } | |
793 | 136 #define FROB(slot) \ |
454 | 137 else if (EQ (key, Q_##slot)) \ |
138 { \ | |
793 | 139 if (!EQ (pgui_item->slot, val)) \ |
454 | 140 { \ |
141 retval = 1; \ | |
793 | 142 pgui_item->slot = val; \ |
454 | 143 } \ |
144 } | |
145 FROB (suffix) | |
146 FROB (active) | |
147 FROB (included) | |
148 FROB (config) | |
149 FROB (filter) | |
150 FROB (style) | |
151 FROB (selected) | |
152 FROB (keys) | |
153 FROB (callback) | |
154 FROB (callback_ex) | |
155 FROB (value) | |
156 #undef FROB | |
440 | 157 else if (EQ (key, Q_key_sequence)) ; /* ignored for FSF compatibility */ |
428 | 158 else if (EQ (key, Q_label)) ; /* ignored for 21.0 implement in 21.2 */ |
159 else if (EQ (key, Q_accelerator)) | |
160 { | |
454 | 161 if (!EQ (pgui_item->accelerator, val)) |
162 { | |
163 retval = 1; | |
164 if (SYMBOLP (val) || CHARP (val)) | |
165 pgui_item->accelerator = val; | |
166 else if (ERRB_EQ (errb, ERROR_ME)) | |
563 | 167 invalid_argument ("Bad keyboard accelerator", val); |
454 | 168 } |
428 | 169 } |
170 else if (ERRB_EQ (errb, ERROR_ME)) | |
793 | 171 invalid_argument_2 ("Unknown keyword in gui item", key, pgui_item->name); |
454 | 172 return retval; |
428 | 173 } |
174 | |
175 void | |
176 gui_item_init (Lisp_Object gui_item) | |
177 { | |
440 | 178 Lisp_Gui_Item *lp = XGUI_ITEM (gui_item); |
428 | 179 |
180 lp->name = Qnil; | |
181 lp->callback = Qnil; | |
442 | 182 lp->callback_ex = Qnil; |
428 | 183 lp->suffix = Qnil; |
184 lp->active = Qt; | |
185 lp->included = Qt; | |
186 lp->config = Qnil; | |
187 lp->filter = Qnil; | |
188 lp->style = Qnil; | |
189 lp->selected = Qnil; | |
190 lp->keys = Qnil; | |
191 lp->accelerator = Qnil; | |
442 | 192 lp->value = Qnil; |
428 | 193 } |
194 | |
195 Lisp_Object | |
196 allocate_gui_item (void) | |
197 { | |
5127
a9c41067dd88
more cleanups, terminology clarification, lots of doc work
Ben Wing <ben@xemacs.org>
parents:
5125
diff
changeset
|
198 Lisp_Object obj = ALLOC_NORMAL_LISP_OBJECT (gui_item); |
428 | 199 |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3017
diff
changeset
|
200 gui_item_init (obj); |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3017
diff
changeset
|
201 return obj; |
428 | 202 } |
203 | |
204 /* | |
205 * ITEM is a lisp vector, describing a menu item or a button. The | |
206 * function extracts the description of the item into the PGUI_ITEM | |
207 * structure. | |
208 */ | |
209 static Lisp_Object | |
210 make_gui_item_from_keywords_internal (Lisp_Object item, | |
578 | 211 Error_Behavior errb) |
428 | 212 { |
213 int length, plist_p, start; | |
214 Lisp_Object *contents; | |
215 Lisp_Object gui_item = allocate_gui_item (); | |
442 | 216 Lisp_Gui_Item *pgui_item = XGUI_ITEM (gui_item); |
428 | 217 |
218 CHECK_VECTOR (item); | |
219 length = XVECTOR_LENGTH (item); | |
220 contents = XVECTOR_DATA (item); | |
221 | |
222 if (length < 1) | |
563 | 223 sferror ("GUI item descriptors must be at least 1 elts long", item); |
428 | 224 |
225 /* length 1: [ "name" ] | |
226 length 2: [ "name" callback ] | |
227 length 3: [ "name" callback active-p ] | |
228 or [ "name" keyword value ] | |
229 length 4: [ "name" callback active-p suffix ] | |
230 or [ "name" callback keyword value ] | |
231 length 5+: [ "name" callback [ keyword value ]+ ] | |
232 or [ "name" [ keyword value ]+ ] | |
233 */ | |
234 plist_p = (length > 2 && (KEYWORDP (contents [1]) | |
235 || KEYWORDP (contents [2]))); | |
236 | |
237 pgui_item->name = contents [0]; | |
238 if (length > 1 && !KEYWORDP (contents [1])) | |
239 { | |
240 pgui_item->callback = contents [1]; | |
241 start = 2; | |
242 } | |
440 | 243 else |
428 | 244 start =1; |
245 | |
246 if (!plist_p && length > 2) | |
247 /* the old way */ | |
248 { | |
249 pgui_item->active = contents [2]; | |
250 if (length == 4) | |
251 pgui_item->suffix = contents [3]; | |
252 } | |
253 else | |
254 /* the new way */ | |
255 { | |
256 int i; | |
257 if ((length - start) & 1) | |
563 | 258 sferror ( |
428 | 259 "GUI item descriptor has an odd number of keywords and values", |
793 | 260 item); |
428 | 261 |
262 for (i = start; i < length;) | |
263 { | |
264 Lisp_Object key = contents [i++]; | |
265 Lisp_Object val = contents [i++]; | |
266 gui_item_add_keyval_pair (gui_item, key, val, errb); | |
267 } | |
268 } | |
269 return gui_item; | |
270 } | |
271 | |
454 | 272 /* This will only work with descriptors in the new format. */ |
273 Lisp_Object | |
274 widget_gui_parse_item_keywords (Lisp_Object item) | |
275 { | |
276 int i, length; | |
277 Lisp_Object *contents; | |
278 Lisp_Object gui_item = allocate_gui_item (); | |
279 Lisp_Object desc = find_keyword_in_vector (item, Q_descriptor); | |
280 | |
281 CHECK_VECTOR (item); | |
282 length = XVECTOR_LENGTH (item); | |
283 contents = XVECTOR_DATA (item); | |
284 | |
285 if (!NILP (desc) && !STRINGP (desc) && !VECTORP (desc)) | |
563 | 286 sferror ("Invalid GUI item descriptor", item); |
454 | 287 |
288 if (length & 1) | |
289 { | |
290 if (!SYMBOLP (contents [0])) | |
563 | 291 sferror ("Invalid GUI item descriptor", item); |
454 | 292 contents++; /* Ignore the leading symbol. */ |
293 length--; | |
294 } | |
295 | |
296 for (i = 0; i < length;) | |
297 { | |
298 Lisp_Object key = contents [i++]; | |
299 Lisp_Object val = contents [i++]; | |
300 gui_item_add_keyval_pair (gui_item, key, val, ERROR_ME_NOT); | |
301 } | |
302 | |
303 return gui_item; | |
304 } | |
305 | |
306 /* Update a gui item from a partial descriptor. */ | |
307 int | |
308 update_gui_item_keywords (Lisp_Object gui_item, Lisp_Object item) | |
309 { | |
310 int i, length, retval = 0; | |
311 Lisp_Object *contents; | |
312 | |
313 CHECK_VECTOR (item); | |
314 length = XVECTOR_LENGTH (item); | |
315 contents = XVECTOR_DATA (item); | |
316 | |
317 if (length & 1) | |
318 { | |
319 if (!SYMBOLP (contents [0])) | |
563 | 320 sferror ("Invalid GUI item descriptor", item); |
454 | 321 contents++; /* Ignore the leading symbol. */ |
322 length--; | |
323 } | |
324 | |
325 for (i = 0; i < length;) | |
326 { | |
327 Lisp_Object key = contents [i++]; | |
328 Lisp_Object val = contents [i++]; | |
793 | 329 if (gui_item_add_keyval_pair (gui_item, key, val, ERROR_ME_DEBUG_WARN)) |
454 | 330 retval = 1; |
331 } | |
332 return retval; | |
333 } | |
334 | |
428 | 335 Lisp_Object |
336 gui_parse_item_keywords (Lisp_Object item) | |
337 { | |
338 return make_gui_item_from_keywords_internal (item, ERROR_ME); | |
339 } | |
340 | |
341 Lisp_Object | |
342 gui_parse_item_keywords_no_errors (Lisp_Object item) | |
343 { | |
793 | 344 return make_gui_item_from_keywords_internal (item, ERROR_ME_DEBUG_WARN); |
428 | 345 } |
346 | |
347 /* convert a gui item into plist properties */ | |
348 void | |
349 gui_add_item_keywords_to_plist (Lisp_Object plist, Lisp_Object gui_item) | |
350 { | |
442 | 351 Lisp_Gui_Item *pgui_item = XGUI_ITEM (gui_item); |
440 | 352 |
428 | 353 if (!NILP (pgui_item->callback)) |
354 Fplist_put (plist, Q_callback, pgui_item->callback); | |
442 | 355 if (!NILP (pgui_item->callback_ex)) |
356 Fplist_put (plist, Q_callback_ex, pgui_item->callback_ex); | |
428 | 357 if (!NILP (pgui_item->suffix)) |
358 Fplist_put (plist, Q_suffix, pgui_item->suffix); | |
359 if (!NILP (pgui_item->active)) | |
360 Fplist_put (plist, Q_active, pgui_item->active); | |
361 if (!NILP (pgui_item->included)) | |
362 Fplist_put (plist, Q_included, pgui_item->included); | |
363 if (!NILP (pgui_item->config)) | |
364 Fplist_put (plist, Q_config, pgui_item->config); | |
365 if (!NILP (pgui_item->filter)) | |
366 Fplist_put (plist, Q_filter, pgui_item->filter); | |
367 if (!NILP (pgui_item->style)) | |
368 Fplist_put (plist, Q_style, pgui_item->style); | |
369 if (!NILP (pgui_item->selected)) | |
370 Fplist_put (plist, Q_selected, pgui_item->selected); | |
371 if (!NILP (pgui_item->keys)) | |
372 Fplist_put (plist, Q_keys, pgui_item->keys); | |
373 if (!NILP (pgui_item->accelerator)) | |
374 Fplist_put (plist, Q_accelerator, pgui_item->accelerator); | |
442 | 375 if (!NILP (pgui_item->value)) |
376 Fplist_put (plist, Q_value, pgui_item->value); | |
428 | 377 } |
378 | |
1318 | 379 static int |
1913 | 380 gui_item_value (Lisp_Object form) |
1318 | 381 { |
382 /* This function can call Lisp. */ | |
383 #ifndef ERROR_CHECK_DISPLAY | |
384 /* Shortcut to avoid evaluating Qt/Qnil each time; but don't do it when | |
385 error-checking so we catch unprotected eval within redisplay quicker */ | |
386 if (NILP (form)) | |
387 return 0; | |
388 if (EQ (form, Qt)) | |
389 return 1; | |
390 #endif | |
4677
8f1ee2d15784
Support full Common Lisp multiple values in C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
3263
diff
changeset
|
391 return !NILP (in_display ? |
8f1ee2d15784
Support full Common Lisp multiple values in C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
3263
diff
changeset
|
392 IGNORE_MULTIPLE_VALUES (eval_within_redisplay (form)) |
8f1ee2d15784
Support full Common Lisp multiple values in C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
3263
diff
changeset
|
393 : IGNORE_MULTIPLE_VALUES (Feval (form))); |
1318 | 394 } |
395 | |
428 | 396 /* |
397 * Decide whether a GUI item is active by evaluating its :active form | |
398 * if any | |
399 */ | |
400 int | |
1913 | 401 gui_item_active_p (Lisp_Object gui_item) |
428 | 402 { |
1913 | 403 return gui_item_value (XGUI_ITEM (gui_item)->active); |
428 | 404 } |
405 | |
406 /* set menu accelerator key to first underlined character in menu name */ | |
407 Lisp_Object | |
408 gui_item_accelerator (Lisp_Object gui_item) | |
409 { | |
442 | 410 Lisp_Gui_Item *pgui = XGUI_ITEM (gui_item); |
440 | 411 |
428 | 412 if (!NILP (pgui->accelerator)) |
413 return pgui->accelerator; | |
414 | |
415 else | |
442 | 416 return gui_name_accelerator (pgui->name); |
428 | 417 } |
418 | |
419 Lisp_Object | |
420 gui_name_accelerator (Lisp_Object nm) | |
421 { | |
867 | 422 Ibyte *name = XSTRING_DATA (nm); |
428 | 423 |
442 | 424 while (*name) |
425 { | |
426 if (*name == '%') | |
428 | 427 { |
442 | 428 ++name; |
429 if (!(*name)) | |
430 return Qnil; | |
431 if (*name == '_' && *(name + 1)) | |
432 { | |
867 | 433 Ichar accelerator = itext_ichar (name + 1); |
771 | 434 return make_char (DOWNCASE (0, accelerator)); |
442 | 435 } |
428 | 436 } |
867 | 437 INC_IBYTEPTR (name); |
428 | 438 } |
867 | 439 return make_char (DOWNCASE (0, itext_ichar (XSTRING_DATA (nm)))); |
428 | 440 } |
441 | |
442 /* | |
443 * Decide whether a GUI item is selected by evaluating its :selected form | |
444 * if any | |
445 */ | |
446 int | |
1913 | 447 gui_item_selected_p (Lisp_Object gui_item) |
428 | 448 { |
1913 | 449 return gui_item_value (XGUI_ITEM (gui_item)->selected); |
428 | 450 } |
451 | |
442 | 452 Lisp_Object |
453 gui_item_list_find_selected (Lisp_Object gui_item_list) | |
454 { | |
1318 | 455 /* This function can call Lisp but cannot GC because it is called within |
456 redisplay, and redisplay disables GC. */ | |
442 | 457 Lisp_Object rest; |
458 LIST_LOOP (rest, gui_item_list) | |
459 { | |
1913 | 460 if (gui_item_selected_p (XCAR (rest))) |
442 | 461 return XCAR (rest); |
462 } | |
463 return XCAR (gui_item_list); | |
464 } | |
465 | |
428 | 466 /* |
467 * Decide whether a GUI item is included by evaluating its :included | |
468 * form if given, and testing its :config form against supplied CONFLIST | |
469 * configuration variable | |
470 */ | |
471 int | |
472 gui_item_included_p (Lisp_Object gui_item, Lisp_Object conflist) | |
473 { | |
474 /* This function can call lisp */ | |
442 | 475 Lisp_Gui_Item *pgui_item = XGUI_ITEM (gui_item); |
428 | 476 |
477 /* Evaluate :included first. Shortcut to avoid evaluating Qt each time */ | |
1913 | 478 if (!gui_item_value (pgui_item->included)) |
428 | 479 return 0; |
480 | |
481 /* Do :config if conflist is given */ | |
482 if (!NILP (conflist) && !NILP (pgui_item->config) | |
483 && NILP (Fmemq (pgui_item->config, conflist))) | |
484 return 0; | |
485 | |
486 return 1; | |
487 } | |
488 | |
489 /* | |
771 | 490 * Format "left flush" display portion of an item. |
428 | 491 */ |
771 | 492 Lisp_Object |
493 gui_item_display_flush_left (Lisp_Object gui_item) | |
428 | 494 { |
495 /* This function can call lisp */ | |
442 | 496 Lisp_Gui_Item *pgui_item = XGUI_ITEM (gui_item); |
771 | 497 Lisp_Object retval; |
428 | 498 |
499 CHECK_STRING (pgui_item->name); | |
771 | 500 retval = pgui_item->name; |
428 | 501 |
502 if (!NILP (pgui_item->suffix)) | |
503 { | |
504 Lisp_Object suffix = pgui_item->suffix; | |
505 /* Shortcut to avoid evaluating suffix each time */ | |
506 if (!STRINGP (suffix)) | |
507 { | |
508 suffix = Feval (suffix); | |
4677
8f1ee2d15784
Support full Common Lisp multiple values in C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
3263
diff
changeset
|
509 suffix = IGNORE_MULTIPLE_VALUES (suffix); |
428 | 510 CHECK_STRING (suffix); |
511 } | |
512 | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4846
diff
changeset
|
513 retval = concat3 (pgui_item->name, build_ascstring (" "), suffix); |
428 | 514 } |
771 | 515 |
516 return retval; | |
428 | 517 } |
518 | |
519 /* | |
771 | 520 * Format "right flush" display portion of an item into BUF. |
428 | 521 */ |
771 | 522 Lisp_Object |
523 gui_item_display_flush_right (Lisp_Object gui_item) | |
428 | 524 { |
442 | 525 Lisp_Gui_Item *pgui_item = XGUI_ITEM (gui_item); |
428 | 526 |
527 #ifdef HAVE_MENUBARS | |
528 /* Have keys? */ | |
529 if (!menubar_show_keybindings) | |
771 | 530 return Qnil; |
428 | 531 #endif |
532 | |
533 /* Try :keys first */ | |
534 if (!NILP (pgui_item->keys)) | |
535 { | |
536 CHECK_STRING (pgui_item->keys); | |
771 | 537 return pgui_item->keys; |
428 | 538 } |
539 | |
540 /* See if we can derive keys out of callback symbol */ | |
541 if (SYMBOLP (pgui_item->callback)) | |
542 { | |
793 | 543 DECLARE_EISTRING_MALLOC (buf); |
544 Lisp_Object str; | |
545 | |
546 where_is_to_char (pgui_item->callback, buf); | |
547 str = eimake_string (buf); | |
548 eifree (buf); | |
549 return str; | |
428 | 550 } |
551 | |
552 /* No keys - no right flush display */ | |
771 | 553 return Qnil; |
428 | 554 } |
555 | |
1204 | 556 static const struct memory_description gui_item_description [] = { |
934 | 557 { XD_LISP_OBJECT, offsetof (struct Lisp_Gui_Item, name) }, |
558 { XD_LISP_OBJECT, offsetof (struct Lisp_Gui_Item, callback) }, | |
559 { XD_LISP_OBJECT, offsetof (struct Lisp_Gui_Item, callback_ex) }, | |
560 { XD_LISP_OBJECT, offsetof (struct Lisp_Gui_Item, suffix) }, | |
561 { XD_LISP_OBJECT, offsetof (struct Lisp_Gui_Item, active) }, | |
562 { XD_LISP_OBJECT, offsetof (struct Lisp_Gui_Item, included) }, | |
563 { XD_LISP_OBJECT, offsetof (struct Lisp_Gui_Item, config) }, | |
564 { XD_LISP_OBJECT, offsetof (struct Lisp_Gui_Item, filter) }, | |
565 { XD_LISP_OBJECT, offsetof (struct Lisp_Gui_Item, style) }, | |
566 { XD_LISP_OBJECT, offsetof (struct Lisp_Gui_Item, selected) }, | |
567 { XD_LISP_OBJECT, offsetof (struct Lisp_Gui_Item, keys) }, | |
568 { XD_LISP_OBJECT, offsetof (struct Lisp_Gui_Item, accelerator) }, | |
569 { XD_LISP_OBJECT, offsetof (struct Lisp_Gui_Item, value) }, | |
570 { XD_END } | |
571 }; | |
572 | |
428 | 573 static Lisp_Object |
574 mark_gui_item (Lisp_Object obj) | |
575 { | |
440 | 576 Lisp_Gui_Item *p = XGUI_ITEM (obj); |
428 | 577 |
578 mark_object (p->name); | |
579 mark_object (p->callback); | |
442 | 580 mark_object (p->callback_ex); |
428 | 581 mark_object (p->config); |
582 mark_object (p->suffix); | |
583 mark_object (p->active); | |
584 mark_object (p->included); | |
585 mark_object (p->config); | |
586 mark_object (p->filter); | |
587 mark_object (p->style); | |
588 mark_object (p->selected); | |
589 mark_object (p->keys); | |
590 mark_object (p->accelerator); | |
442 | 591 mark_object (p->value); |
428 | 592 |
593 return Qnil; | |
594 } | |
595 | |
665 | 596 static Hashcode |
5191
71ee43b8a74d
Add #'equalp as a hash test by default; add #'define-hash-table-test, GNU API
Aidan Kehoe <kehoea@parhasard.net>
parents:
5146
diff
changeset
|
597 gui_item_hash (Lisp_Object obj, int depth, Boolint UNUSED (equalp)) |
428 | 598 { |
440 | 599 Lisp_Gui_Item *p = XGUI_ITEM (obj); |
428 | 600 |
5191
71ee43b8a74d
Add #'equalp as a hash test by default; add #'define-hash-table-test, GNU API
Aidan Kehoe <kehoea@parhasard.net>
parents:
5146
diff
changeset
|
601 return HASH2 (HASH6 (internal_hash (p->name, depth + 1, 0), |
71ee43b8a74d
Add #'equalp as a hash test by default; add #'define-hash-table-test, GNU API
Aidan Kehoe <kehoea@parhasard.net>
parents:
5146
diff
changeset
|
602 internal_hash (p->callback, depth + 1, 0), |
71ee43b8a74d
Add #'equalp as a hash test by default; add #'define-hash-table-test, GNU API
Aidan Kehoe <kehoea@parhasard.net>
parents:
5146
diff
changeset
|
603 internal_hash (p->callback_ex, depth + 1, 0), |
71ee43b8a74d
Add #'equalp as a hash test by default; add #'define-hash-table-test, GNU API
Aidan Kehoe <kehoea@parhasard.net>
parents:
5146
diff
changeset
|
604 internal_hash (p->suffix, depth + 1, 0), |
71ee43b8a74d
Add #'equalp as a hash test by default; add #'define-hash-table-test, GNU API
Aidan Kehoe <kehoea@parhasard.net>
parents:
5146
diff
changeset
|
605 internal_hash (p->active, depth + 1, 0), |
71ee43b8a74d
Add #'equalp as a hash test by default; add #'define-hash-table-test, GNU API
Aidan Kehoe <kehoea@parhasard.net>
parents:
5146
diff
changeset
|
606 internal_hash (p->included, depth + 1, 0)), |
71ee43b8a74d
Add #'equalp as a hash test by default; add #'define-hash-table-test, GNU API
Aidan Kehoe <kehoea@parhasard.net>
parents:
5146
diff
changeset
|
607 HASH6 (internal_hash (p->config, depth + 1, 0), |
71ee43b8a74d
Add #'equalp as a hash test by default; add #'define-hash-table-test, GNU API
Aidan Kehoe <kehoea@parhasard.net>
parents:
5146
diff
changeset
|
608 internal_hash (p->filter, depth + 1, 0), |
71ee43b8a74d
Add #'equalp as a hash test by default; add #'define-hash-table-test, GNU API
Aidan Kehoe <kehoea@parhasard.net>
parents:
5146
diff
changeset
|
609 internal_hash (p->style, depth + 1, 0), |
71ee43b8a74d
Add #'equalp as a hash test by default; add #'define-hash-table-test, GNU API
Aidan Kehoe <kehoea@parhasard.net>
parents:
5146
diff
changeset
|
610 internal_hash (p->selected, depth + 1, 0), |
71ee43b8a74d
Add #'equalp as a hash test by default; add #'define-hash-table-test, GNU API
Aidan Kehoe <kehoea@parhasard.net>
parents:
5146
diff
changeset
|
611 internal_hash (p->keys, depth + 1, 0), |
71ee43b8a74d
Add #'equalp as a hash test by default; add #'define-hash-table-test, GNU API
Aidan Kehoe <kehoea@parhasard.net>
parents:
5146
diff
changeset
|
612 internal_hash (p->value, depth + 1, 0))); |
428 | 613 } |
614 | |
615 int | |
616 gui_item_id_hash (Lisp_Object hashtable, Lisp_Object gitem, int slot) | |
617 { | |
5191
71ee43b8a74d
Add #'equalp as a hash test by default; add #'define-hash-table-test, GNU API
Aidan Kehoe <kehoea@parhasard.net>
parents:
5146
diff
changeset
|
618 int hashid = gui_item_hash (gitem, 0, 0); |
428 | 619 int id = GUI_ITEM_ID_BITS (hashid, slot); |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5402
diff
changeset
|
620 while (!UNBOUNDP (Fgethash (make_fixnum (id), hashtable, Qunbound))) |
428 | 621 { |
622 id = GUI_ITEM_ID_BITS (id + 1, slot); | |
623 } | |
624 return id; | |
625 } | |
626 | |
1318 | 627 static int |
1913 | 628 gui_value_equal (Lisp_Object a, Lisp_Object b, int depth) |
1318 | 629 { |
1913 | 630 if (in_display) |
1318 | 631 return internal_equal_trapping_problems |
632 (Qredisplay, "Error calling function within redisplay", 0, 0, | |
633 /* say they're not equal in case of error; code calling | |
634 gui_item_equal_sans_selected() in redisplay does extra stuff | |
635 only when equal */ | |
636 0, a, b, depth); | |
637 else | |
638 return internal_equal (a, b, depth); | |
639 } | |
640 | |
442 | 641 int |
1913 | 642 gui_item_equal_sans_selected (Lisp_Object obj1, Lisp_Object obj2, int depth) |
428 | 643 { |
440 | 644 Lisp_Gui_Item *p1 = XGUI_ITEM (obj1); |
645 Lisp_Gui_Item *p2 = XGUI_ITEM (obj2); | |
428 | 646 |
1913 | 647 if (!(gui_value_equal (p1->name, p2->name, depth + 1) |
428 | 648 && |
1913 | 649 gui_value_equal (p1->callback, p2->callback, depth + 1) |
428 | 650 && |
1913 | 651 gui_value_equal (p1->callback_ex, p2->callback_ex, depth + 1) |
442 | 652 && |
428 | 653 EQ (p1->suffix, p2->suffix) |
654 && | |
655 EQ (p1->active, p2->active) | |
656 && | |
657 EQ (p1->included, p2->included) | |
658 && | |
659 EQ (p1->config, p2->config) | |
660 && | |
661 EQ (p1->filter, p2->filter) | |
662 && | |
663 EQ (p1->style, p2->style) | |
664 && | |
665 EQ (p1->accelerator, p2->accelerator) | |
666 && | |
442 | 667 EQ (p1->keys, p2->keys) |
668 && | |
669 EQ (p1->value, p2->value))) | |
670 return 0; | |
671 return 1; | |
672 } | |
673 | |
674 static int | |
4906
6ef8256a020a
implement equalp in C, fix case-folding, add equal() method for keymaps
Ben Wing <ben@xemacs.org>
parents:
4846
diff
changeset
|
675 gui_item_equal (Lisp_Object obj1, Lisp_Object obj2, int depth, |
6ef8256a020a
implement equalp in C, fix case-folding, add equal() method for keymaps
Ben Wing <ben@xemacs.org>
parents:
4846
diff
changeset
|
676 int UNUSED (foldcase)) |
442 | 677 { |
678 Lisp_Gui_Item *p1 = XGUI_ITEM (obj1); | |
679 Lisp_Gui_Item *p2 = XGUI_ITEM (obj2); | |
680 | |
1913 | 681 if (!(gui_item_equal_sans_selected (obj1, obj2, depth) && |
442 | 682 EQ (p1->selected, p2->selected))) |
428 | 683 return 0; |
684 return 1; | |
685 } | |
686 | |
454 | 687 Lisp_Object |
442 | 688 copy_gui_item (Lisp_Object gui_item) |
689 { | |
690 Lisp_Object ret = allocate_gui_item (); | |
691 Lisp_Gui_Item *lp, *g = XGUI_ITEM (gui_item); | |
692 | |
693 lp = XGUI_ITEM (ret); | |
694 lp->name = g->name; | |
695 lp->callback = g->callback; | |
696 lp->callback_ex = g->callback_ex; | |
697 lp->suffix = g->suffix; | |
698 lp->active = g->active; | |
699 lp->included = g->included; | |
700 lp->config = g->config; | |
701 lp->filter = g->filter; | |
702 lp->style = g->style; | |
703 lp->selected = g->selected; | |
704 lp->keys = g->keys; | |
705 lp->accelerator = g->accelerator; | |
706 lp->value = g->value; | |
707 | |
708 return ret; | |
709 } | |
710 | |
711 Lisp_Object | |
712 copy_gui_item_tree (Lisp_Object arg) | |
713 { | |
714 if (CONSP (arg)) | |
715 { | |
716 Lisp_Object rest = arg = Fcopy_sequence (arg); | |
717 while (CONSP (rest)) | |
718 { | |
719 XCAR (rest) = copy_gui_item_tree (XCAR (rest)); | |
720 rest = XCDR (rest); | |
721 } | |
722 return arg; | |
723 } | |
724 else if (GUI_ITEMP (arg)) | |
725 return copy_gui_item (arg); | |
726 else | |
727 return arg; | |
728 } | |
729 | |
428 | 730 /* parse a glyph descriptor into a tree of gui items. |
731 | |
732 The gui_item slot of an image instance can be a single item or an | |
733 arbitrarily nested hierarchy of item lists. */ | |
734 | |
442 | 735 static Lisp_Object |
736 parse_gui_item_tree_item (Lisp_Object entry) | |
428 | 737 { |
738 Lisp_Object ret = entry; | |
442 | 739 struct gcpro gcpro1; |
740 | |
741 GCPRO1 (ret); | |
742 | |
428 | 743 if (VECTORP (entry)) |
744 { | |
442 | 745 ret = gui_parse_item_keywords_no_errors (entry); |
428 | 746 } |
747 else if (STRINGP (entry)) | |
748 { | |
749 CHECK_STRING (entry); | |
750 } | |
751 else | |
563 | 752 sferror ("item must be a vector or a string", entry); |
428 | 753 |
442 | 754 RETURN_UNGCPRO (ret); |
428 | 755 } |
756 | |
442 | 757 Lisp_Object |
758 parse_gui_item_tree_children (Lisp_Object list) | |
428 | 759 { |
442 | 760 Lisp_Object rest, ret = Qnil, sub = Qnil; |
761 struct gcpro gcpro1, gcpro2; | |
762 | |
763 GCPRO2 (ret, sub); | |
428 | 764 CHECK_CONS (list); |
765 /* recursively add items to the tree view */ | |
766 LIST_LOOP (rest, list) | |
767 { | |
768 if (CONSP (XCAR (rest))) | |
769 sub = parse_gui_item_tree_list (XCAR (rest)); | |
770 else | |
771 sub = parse_gui_item_tree_item (XCAR (rest)); | |
440 | 772 |
428 | 773 ret = Fcons (sub, ret); |
774 } | |
775 /* make the order the same as the items we have parsed */ | |
442 | 776 RETURN_UNGCPRO (Fnreverse (ret)); |
428 | 777 } |
778 | |
442 | 779 static Lisp_Object |
780 parse_gui_item_tree_list (Lisp_Object list) | |
428 | 781 { |
782 Lisp_Object ret; | |
442 | 783 struct gcpro gcpro1; |
428 | 784 CHECK_CONS (list); |
785 /* first one can never be a list */ | |
786 ret = parse_gui_item_tree_item (XCAR (list)); | |
442 | 787 GCPRO1 (ret); |
788 ret = Fcons (ret, parse_gui_item_tree_children (XCDR (list))); | |
789 RETURN_UNGCPRO (ret); | |
790 } | |
791 | |
5118
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
792 DEFINE_NODUMP_LISP_OBJECT ("gui-item", gui_item, |
5146
88bd4f3ef8e4
make lrecord UID's have a separate UID space for each object, resurrect debug SOE code in extents.c
Ben Wing <ben@xemacs.org>
parents:
5142
diff
changeset
|
793 mark_gui_item, external_object_printer, |
5124
623d57b7fbe8
separate regular and disksave finalization, print method fixes.
Ben Wing <ben@xemacs.org>
parents:
5118
diff
changeset
|
794 0, gui_item_equal, |
623d57b7fbe8
separate regular and disksave finalization, print method fixes.
Ben Wing <ben@xemacs.org>
parents:
5118
diff
changeset
|
795 gui_item_hash, |
623d57b7fbe8
separate regular and disksave finalization, print method fixes.
Ben Wing <ben@xemacs.org>
parents:
5118
diff
changeset
|
796 gui_item_description, |
623d57b7fbe8
separate regular and disksave finalization, print method fixes.
Ben Wing <ben@xemacs.org>
parents:
5118
diff
changeset
|
797 Lisp_Gui_Item); |
563 | 798 |
799 DOESNT_RETURN | |
2367 | 800 gui_error (const Ascbyte *reason, Lisp_Object frob) |
563 | 801 { |
802 signal_error (Qgui_error, reason, frob); | |
803 } | |
804 | |
569 | 805 DOESNT_RETURN |
2367 | 806 gui_error_2 (const Ascbyte *reason, Lisp_Object frob0, Lisp_Object frob1) |
569 | 807 { |
808 signal_error_2 (Qgui_error, reason, frob0, frob1); | |
809 } | |
810 | |
428 | 811 void |
812 syms_of_gui (void) | |
813 { | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3017
diff
changeset
|
814 INIT_LISP_OBJECT (gui_item); |
428 | 815 |
442 | 816 DEFSYMBOL (Qmenu_no_selection_hook); |
428 | 817 |
563 | 818 DEFERROR_STANDARD (Qgui_error, Qio_error); |
819 | |
428 | 820 #ifdef HAVE_POPUPS |
821 DEFSUBR (Fpopup_up_p); | |
822 #endif | |
823 } | |
824 | |
825 void | |
826 vars_of_gui (void) | |
827 { | |
442 | 828 DEFVAR_LISP ("menu-no-selection-hook", &Vmenu_no_selection_hook /* |
829 Function or functions to call when a menu or dialog box is dismissed | |
830 without a selection having been made. | |
831 */ ); | |
832 Vmenu_no_selection_hook = Qnil; | |
428 | 833 } |