Mercurial > hg > xemacs-beta
comparison src/gui-x.c @ 428:3ecd8885ac67 r21-2-22
Import from CVS: tag r21-2-22
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:28:15 +0200 |
parents | |
children | 080151679be2 |
comparison
equal
deleted
inserted
replaced
427:0a0253eac470 | 428:3ecd8885ac67 |
---|---|
1 /* General GUI code -- X-specific. (menubars, scrollbars, toolbars, dialogs) | |
2 Copyright (C) 1995 Board of Trustees, University of Illinois. | |
3 Copyright (C) 1995, 1996 Ben Wing. | |
4 Copyright (C) 1995 Sun Microsystems, Inc. | |
5 Copyright (C) 1998 Free Software Foundation, Inc. | |
6 | |
7 This file is part of XEmacs. | |
8 | |
9 XEmacs is free software; you can redistribute it and/or modify it | |
10 under the terms of the GNU General Public License as published by the | |
11 Free Software Foundation; either version 2, or (at your option) any | |
12 later version. | |
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 | |
20 along with XEmacs; see the file COPYING. If not, write to | |
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
22 Boston, MA 02111-1307, USA. */ | |
23 | |
24 /* Synched up with: Not in FSF. */ | |
25 | |
26 #include <config.h> | |
27 #include "lisp.h" | |
28 | |
29 #include "console-x.h" | |
30 #ifdef LWLIB_USES_MOTIF | |
31 #include <Xm/Xm.h> /* for XmVersion */ | |
32 #endif | |
33 #include "gui-x.h" | |
34 #include "buffer.h" | |
35 #include "device.h" | |
36 #include "frame.h" | |
37 #include "gui.h" | |
38 #include "redisplay.h" | |
39 #include "opaque.h" | |
40 | |
41 Lisp_Object Qmenu_no_selection_hook; | |
42 | |
43 /* we need a unique id for each popup menu, dialog box, and scrollbar */ | |
44 static unsigned int lwlib_id_tick; | |
45 | |
46 LWLIB_ID | |
47 new_lwlib_id (void) | |
48 { | |
49 return ++lwlib_id_tick; | |
50 } | |
51 | |
52 widget_value * | |
53 xmalloc_widget_value (void) | |
54 { | |
55 widget_value *tmp = malloc_widget_value (); | |
56 if (!tmp) memory_full (); | |
57 return tmp; | |
58 } | |
59 | |
60 | |
61 static int | |
62 mark_widget_value_mapper (widget_value *val, void *closure) | |
63 { | |
64 Lisp_Object markee; | |
65 if (val->call_data) | |
66 { | |
67 VOID_TO_LISP (markee, val->call_data); | |
68 mark_object (markee); | |
69 } | |
70 | |
71 if (val->accel) | |
72 { | |
73 VOID_TO_LISP (markee, val->accel); | |
74 mark_object (markee); | |
75 } | |
76 return 0; | |
77 } | |
78 | |
79 static Lisp_Object | |
80 mark_popup_data (Lisp_Object obj) | |
81 { | |
82 struct popup_data *data = (struct popup_data *) XPOPUP_DATA (obj); | |
83 | |
84 /* Now mark the callbacks and such that are hidden in the lwlib | |
85 call-data */ | |
86 | |
87 if (data->id) | |
88 lw_map_widget_values (data->id, mark_widget_value_mapper, 0); | |
89 | |
90 return data->last_menubar_buffer; | |
91 } | |
92 | |
93 DEFINE_LRECORD_IMPLEMENTATION ("popup-data", popup_data, | |
94 mark_popup_data, internal_object_printer, | |
95 0, 0, 0, 0, struct popup_data); | |
96 | |
97 /* This is like FRAME_MENUBAR_DATA (f), but contains an alist of | |
98 (id . popup-data) for GCPRO'ing the callbacks of the popup menus | |
99 and dialog boxes. */ | |
100 static Lisp_Object Vpopup_callbacks; | |
101 | |
102 void | |
103 gcpro_popup_callbacks (LWLIB_ID id) | |
104 { | |
105 struct popup_data *pdata; | |
106 Lisp_Object lid = make_int (id); | |
107 Lisp_Object lpdata; | |
108 | |
109 assert (NILP (assq_no_quit (lid, Vpopup_callbacks))); | |
110 pdata = alloc_lcrecord_type (struct popup_data, &lrecord_popup_data); | |
111 pdata->id = id; | |
112 pdata->last_menubar_buffer = Qnil; | |
113 pdata->menubar_contents_up_to_date = 0; | |
114 XSETPOPUP_DATA (lpdata, pdata); | |
115 Vpopup_callbacks = Fcons (Fcons (lid, lpdata), Vpopup_callbacks); | |
116 } | |
117 | |
118 void | |
119 ungcpro_popup_callbacks (LWLIB_ID id) | |
120 { | |
121 Lisp_Object lid = make_int (id); | |
122 Lisp_Object this = assq_no_quit (lid, Vpopup_callbacks); | |
123 assert (!NILP (this)); | |
124 Vpopup_callbacks = delq_no_quit (this, Vpopup_callbacks); | |
125 } | |
126 | |
127 int | |
128 popup_handled_p (LWLIB_ID id) | |
129 { | |
130 return NILP (assq_no_quit (make_int (id), Vpopup_callbacks)); | |
131 } | |
132 | |
133 /* menu_item_descriptor_to_widget_value() et al. mallocs a | |
134 widget_value, but then may signal lisp errors. If an error does | |
135 not occur, the opaque ptr we have here has had its pointer set to 0 | |
136 to tell us not to do anything. Otherwise we free the widget value. | |
137 (This has nothing to do with GC, it's just about not dropping | |
138 pointers to malloc'd data when errors happen.) */ | |
139 | |
140 Lisp_Object | |
141 widget_value_unwind (Lisp_Object closure) | |
142 { | |
143 widget_value *wv = (widget_value *) get_opaque_ptr (closure); | |
144 free_opaque_ptr (closure); | |
145 if (wv) | |
146 free_widget_value (wv); | |
147 return Qnil; | |
148 } | |
149 | |
150 #if 0 | |
151 static void | |
152 print_widget_value (widget_value *wv, int depth) | |
153 { | |
154 /* !!#### This function has not been Mule-ized */ | |
155 char d [200]; | |
156 int i; | |
157 for (i = 0; i < depth; i++) d[i] = ' '; | |
158 d[depth]=0; | |
159 /* #### - print type field */ | |
160 printf ("%sname: %s\n", d, (wv->name ? wv->name : "(null)")); | |
161 if (wv->value) printf ("%svalue: %s\n", d, wv->value); | |
162 if (wv->key) printf ("%skey: %s\n", d, wv->key); | |
163 printf ("%senabled: %d\n", d, wv->enabled); | |
164 if (wv->contents) | |
165 { | |
166 printf ("\n%scontents: \n", d); | |
167 print_widget_value (wv->contents, depth + 5); | |
168 } | |
169 if (wv->next) | |
170 { | |
171 printf ("\n"); | |
172 print_widget_value (wv->next, depth); | |
173 } | |
174 } | |
175 #endif | |
176 | |
177 /* This recursively calls free_widget_value() on the tree of widgets. | |
178 It must free all data that was malloc'ed for these widget_values. | |
179 | |
180 It used to be that emacs only allocated new storage for the `key' slot. | |
181 All other slots are pointers into the data of Lisp_Strings, and must be | |
182 left alone. */ | |
183 void | |
184 free_popup_widget_value_tree (widget_value *wv) | |
185 { | |
186 if (! wv) return; | |
187 if (wv->key) xfree (wv->key); | |
188 if (wv->value) xfree (wv->value); | |
189 | |
190 wv->name = wv->value = wv->key = (char *) 0xDEADBEEF; | |
191 | |
192 if (wv->contents && (wv->contents != (widget_value*)1)) | |
193 { | |
194 free_popup_widget_value_tree (wv->contents); | |
195 wv->contents = (widget_value *) 0xDEADBEEF; | |
196 } | |
197 if (wv->next) | |
198 { | |
199 free_popup_widget_value_tree (wv->next); | |
200 wv->next = (widget_value *) 0xDEADBEEF; | |
201 } | |
202 free_widget_value (wv); | |
203 } | |
204 | |
205 /* The following is actually called from somewhere within XtDispatchEvent(), | |
206 called from XtAppProcessEvent() in event-Xt.c */ | |
207 | |
208 void | |
209 popup_selection_callback (Widget widget, LWLIB_ID ignored_id, | |
210 XtPointer client_data) | |
211 { | |
212 Lisp_Object fn, arg; | |
213 Lisp_Object data; | |
214 Lisp_Object frame; | |
215 struct device *d = get_device_from_display (XtDisplay (widget)); | |
216 struct frame *f = x_any_widget_or_parent_to_frame (d, widget); | |
217 | |
218 /* set in lwlib to the time stamp associated with the most recent menu | |
219 operation */ | |
220 extern Time x_focus_timestamp_really_sucks_fix_me_better; | |
221 | |
222 if (!f) | |
223 return; | |
224 if (((EMACS_INT) client_data) == 0) | |
225 return; | |
226 VOID_TO_LISP (data, client_data); | |
227 XSETFRAME (frame, f); | |
228 | |
229 #if 0 | |
230 /* #### What the hell? I can't understand why this call is here, | |
231 and doing it is really courting disaster in the new event | |
232 model, since popup_selection_callback is called from | |
233 within next_event_internal() and Faccept_process_output() | |
234 itself calls next_event_internal(). --Ben */ | |
235 | |
236 /* Flush the X and process input */ | |
237 Faccept_process_output (Qnil, Qnil, Qnil); | |
238 #endif | |
239 | |
240 if (((EMACS_INT) client_data) == -1) | |
241 { | |
242 fn = Qrun_hooks; | |
243 arg = Qmenu_no_selection_hook; | |
244 } | |
245 else | |
246 { | |
247 MARK_SUBWINDOWS_STATE_CHANGED; | |
248 get_gui_callback (data, &fn, &arg); | |
249 } | |
250 | |
251 /* This is the timestamp used for asserting focus so we need to get an | |
252 up-to-date value event if no events has been dispatched to emacs | |
253 */ | |
254 #if defined(HAVE_MENUBARS) | |
255 DEVICE_X_MOUSE_TIMESTAMP (d) = x_focus_timestamp_really_sucks_fix_me_better; | |
256 #else | |
257 DEVICE_X_MOUSE_TIMESTAMP (d) = DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (d); | |
258 #endif | |
259 signal_special_Xt_user_event (frame, fn, arg); | |
260 } | |
261 | |
262 #if 1 | |
263 /* Eval the activep slot of the menu item */ | |
264 # define wv_set_evalable_slot(slot,form) do { \ | |
265 Lisp_Object wses_form = (form); \ | |
266 (slot) = (NILP (wses_form) ? 0 : \ | |
267 EQ (wses_form, Qt) ? 1 : \ | |
268 !NILP (Feval (wses_form))); \ | |
269 } while (0) | |
270 #else | |
271 /* Treat the activep slot of the menu item as a boolean */ | |
272 # define wv_set_evalable_slot(slot,form) \ | |
273 ((void) (slot = (!NILP (form)))) | |
274 #endif | |
275 | |
276 char * | |
277 menu_separator_style (CONST char *s) | |
278 { | |
279 CONST char *p; | |
280 char first; | |
281 | |
282 if (!s || s[0] == '\0') | |
283 return NULL; | |
284 first = s[0]; | |
285 if (first != '-' && first != '=') | |
286 return NULL; | |
287 for (p = s; *p == first; p++) | |
288 DO_NOTHING; | |
289 | |
290 /* #### - cannot currently specify a separator tag "--!tag" and a | |
291 separator style "--:style" at the same time. */ | |
292 /* #### - Also, the motif menubar code doesn't deal with the | |
293 double etched style yet, so it's not good to get into the habit of | |
294 using "===" in menubars to get double-etched lines */ | |
295 if (*p == '!' || *p == '\0') | |
296 return ((first == '-') | |
297 ? NULL /* single etched is the default */ | |
298 : xstrdup ("shadowDoubleEtchedIn")); | |
299 else if (*p == ':') | |
300 return xstrdup (p+1); | |
301 | |
302 return NULL; | |
303 } | |
304 | |
305 | |
306 /* This does the dirty work. gc_currently_forbidden is 1 when this is called. | |
307 */ | |
308 int | |
309 button_item_to_widget_value (Lisp_Object gui_item, widget_value *wv, | |
310 int allow_text_field_p, int no_keys_p) | |
311 { | |
312 /* !!#### This function has not been Mule-ized */ | |
313 /* This function cannot GC because gc_currently_forbidden is set when | |
314 it's called */ | |
315 struct Lisp_Gui_Item* pgui = 0; | |
316 | |
317 /* degenerate case */ | |
318 if (STRINGP (gui_item)) | |
319 { | |
320 wv->type = TEXT_TYPE; | |
321 wv->name = (char *) XSTRING_DATA (gui_item); | |
322 wv->name = xstrdup (wv->name); | |
323 return 1; | |
324 } | |
325 else if (!GUI_ITEMP (gui_item)) | |
326 signal_simple_error("need a string or a gui_item here", gui_item); | |
327 | |
328 pgui = XGUI_ITEM (gui_item); | |
329 | |
330 if (!NILP (pgui->filter)) | |
331 signal_simple_error(":filter keyword not permitted on leaf nodes", gui_item); | |
332 | |
333 #ifdef HAVE_MENUBARS | |
334 if (!gui_item_included_p (gui_item, Vmenubar_configuration)) | |
335 { | |
336 /* the include specification says to ignore this item. */ | |
337 return 0; | |
338 } | |
339 #endif /* HAVE_MENUBARS */ | |
340 | |
341 CHECK_STRING (pgui->name); | |
342 wv->name = (char *) XSTRING_DATA (pgui->name); | |
343 wv->name = xstrdup (wv->name); | |
344 wv->accel = LISP_TO_VOID (gui_item_accelerator (gui_item)); | |
345 | |
346 if (!NILP (pgui->suffix)) | |
347 { | |
348 CONST char *const_bogosity; | |
349 Lisp_Object suffix2; | |
350 | |
351 /* Shortcut to avoid evaluating suffix each time */ | |
352 if (STRINGP (pgui->suffix)) | |
353 suffix2 = pgui->suffix; | |
354 else | |
355 { | |
356 suffix2 = Feval (pgui->suffix); | |
357 CHECK_STRING (suffix2); | |
358 } | |
359 | |
360 GET_C_STRING_FILENAME_DATA_ALLOCA (suffix2, const_bogosity); | |
361 wv->value = (char *) const_bogosity; | |
362 wv->value = xstrdup (wv->value); | |
363 } | |
364 | |
365 wv_set_evalable_slot (wv->enabled, pgui->active); | |
366 wv_set_evalable_slot (wv->selected, pgui->selected); | |
367 | |
368 if (!NILP (pgui->callback)) | |
369 wv->call_data = LISP_TO_VOID (pgui->callback); | |
370 | |
371 if (no_keys_p | |
372 #ifdef HAVE_MENUBARS | |
373 || !menubar_show_keybindings | |
374 #endif | |
375 ) | |
376 wv->key = 0; | |
377 else if (!NILP (pgui->keys)) /* Use this string to generate key bindings */ | |
378 { | |
379 CHECK_STRING (pgui->keys); | |
380 pgui->keys = Fsubstitute_command_keys (pgui->keys); | |
381 if (XSTRING_LENGTH (pgui->keys) > 0) | |
382 wv->key = xstrdup ((char *) XSTRING_DATA (pgui->keys)); | |
383 else | |
384 wv->key = 0; | |
385 } | |
386 else if (SYMBOLP (pgui->callback)) /* Show the binding of this command. */ | |
387 { | |
388 char buf [1024]; | |
389 /* #### Warning, dependency here on current_buffer and point */ | |
390 where_is_to_char (pgui->callback, buf); | |
391 if (buf [0]) | |
392 wv->key = xstrdup (buf); | |
393 else | |
394 wv->key = 0; | |
395 } | |
396 | |
397 CHECK_SYMBOL (pgui->style); | |
398 if (NILP (pgui->style)) | |
399 { | |
400 /* If the callback is nil, treat this item like unselectable text. | |
401 This way, dashes will show up as a separator. */ | |
402 if (!wv->enabled) | |
403 wv->type = BUTTON_TYPE; | |
404 if (separator_string_p (wv->name)) | |
405 { | |
406 wv->type = SEPARATOR_TYPE; | |
407 wv->value = menu_separator_style (wv->name); | |
408 } | |
409 else | |
410 { | |
411 #if 0 | |
412 /* #### - this is generally desirable for menubars, but it breaks | |
413 a package that uses dialog boxes and next_command_event magic | |
414 to use the callback slot in dialog buttons for data instead of | |
415 a real callback. | |
416 | |
417 Code is data, right? The beauty of LISP abuse. --Stig */ | |
418 if (NILP (callback)) | |
419 wv->type = TEXT_TYPE; | |
420 else | |
421 #endif | |
422 wv->type = BUTTON_TYPE; | |
423 } | |
424 } | |
425 else if (EQ (pgui->style, Qbutton)) | |
426 wv->type = BUTTON_TYPE; | |
427 else if (EQ (pgui->style, Qtoggle)) | |
428 wv->type = TOGGLE_TYPE; | |
429 else if (EQ (pgui->style, Qradio)) | |
430 wv->type = RADIO_TYPE; | |
431 else if (EQ (pgui->style, Qtext)) | |
432 { | |
433 wv->type = TEXT_TYPE; | |
434 #if 0 | |
435 wv->value = wv->name; | |
436 wv->name = "value"; | |
437 #endif | |
438 } | |
439 else | |
440 signal_simple_error_2 ("Unknown style", pgui->style, gui_item); | |
441 | |
442 if (!allow_text_field_p && (wv->type == TEXT_TYPE)) | |
443 signal_simple_error ("Text field not allowed in this context", gui_item); | |
444 | |
445 if (!NILP (pgui->selected) && EQ (pgui->style, Qtext)) | |
446 signal_simple_error ( | |
447 ":selected only makes sense with :style toggle, radio or button", | |
448 gui_item); | |
449 return 1; | |
450 } | |
451 | |
452 /* parse tree's of gui items into widget_value hierarchies */ | |
453 static void gui_item_children_to_widget_values (Lisp_Object items, widget_value* parent); | |
454 | |
455 static widget_value * | |
456 gui_items_to_widget_values_1 (Lisp_Object items, widget_value* parent, | |
457 widget_value* prev) | |
458 { | |
459 widget_value* wv = 0; | |
460 | |
461 assert ((parent || prev) && !(parent && prev)); | |
462 /* now walk the tree creating widget_values as appropriate */ | |
463 if (!CONSP (items)) | |
464 { | |
465 wv = xmalloc_widget_value(); | |
466 if (parent) | |
467 parent->contents = wv; | |
468 else | |
469 prev->next = wv; | |
470 if (!button_item_to_widget_value (items, wv, 0, 1)) | |
471 { | |
472 free_widget_value (wv); | |
473 if (parent) | |
474 parent->contents = 0; | |
475 else | |
476 prev->next = 0; | |
477 } | |
478 else | |
479 { | |
480 wv->value = xstrdup (wv->name); /* what a mess... */ | |
481 } | |
482 } | |
483 else | |
484 { | |
485 /* first one is the parent */ | |
486 if (CONSP (XCAR (items))) | |
487 signal_simple_error ("parent item must not be a list", XCAR (items)); | |
488 | |
489 if (parent) | |
490 wv = gui_items_to_widget_values_1 (XCAR (items), parent, 0); | |
491 else | |
492 wv = gui_items_to_widget_values_1 (XCAR (items), 0, prev); | |
493 /* the rest are the children */ | |
494 gui_item_children_to_widget_values (XCDR (items), wv); | |
495 } | |
496 return wv; | |
497 } | |
498 | |
499 static void | |
500 gui_item_children_to_widget_values (Lisp_Object items, widget_value* parent) | |
501 { | |
502 widget_value* wv = 0, *prev = 0; | |
503 Lisp_Object rest; | |
504 CHECK_CONS (items); | |
505 | |
506 /* first one is master */ | |
507 prev = gui_items_to_widget_values_1 (XCAR (items), parent, 0); | |
508 /* the rest are the children */ | |
509 LIST_LOOP (rest, XCDR (items)) | |
510 { | |
511 Lisp_Object tab = XCAR (rest); | |
512 wv = gui_items_to_widget_values_1 (tab, 0, prev); | |
513 prev = wv; | |
514 } | |
515 } | |
516 | |
517 widget_value * | |
518 gui_items_to_widget_values (Lisp_Object items) | |
519 { | |
520 /* !!#### This function has not been Mule-ized */ | |
521 /* This function can GC */ | |
522 widget_value *control = 0, *tmp = 0; | |
523 int count = specpdl_depth (); | |
524 Lisp_Object wv_closure; | |
525 | |
526 if (NILP (items)) | |
527 signal_simple_error ("must have some items", items); | |
528 | |
529 /* Inhibit GC during this conversion. The reasons for this are | |
530 the same as in menu_item_descriptor_to_widget_value(); see | |
531 the large comment above that function. */ | |
532 record_unwind_protect (restore_gc_inhibit, | |
533 make_int (gc_currently_forbidden)); | |
534 gc_currently_forbidden = 1; | |
535 | |
536 /* Also make sure that we free the partially-created widget_value | |
537 tree on Lisp error. */ | |
538 control = xmalloc_widget_value(); | |
539 wv_closure = make_opaque_ptr (control); | |
540 record_unwind_protect (widget_value_unwind, wv_closure); | |
541 | |
542 gui_items_to_widget_values_1 (items, control, 0); | |
543 | |
544 /* mess about getting the data we really want */ | |
545 tmp = control; | |
546 control = control->contents; | |
547 tmp->next = 0; | |
548 tmp->contents = 0; | |
549 free_widget_value (tmp); | |
550 | |
551 /* No more need to free the half-filled-in structures. */ | |
552 set_opaque_ptr (wv_closure, 0); | |
553 unbind_to (count, Qnil); | |
554 | |
555 return control; | |
556 } | |
557 | |
558 /* This is a kludge to make sure emacs can only link against a version of | |
559 lwlib that was compiled in the right way. Emacs references symbols which | |
560 correspond to the way it thinks lwlib was compiled, and if lwlib wasn't | |
561 compiled in that way, then somewhat meaningful link errors will result. | |
562 The alternatives to this range from obscure link errors, to obscure | |
563 runtime errors that look a lot like bugs. | |
564 */ | |
565 | |
566 static void | |
567 sanity_check_lwlib (void) | |
568 { | |
569 #define MACROLET(v) { extern int v; v = 1; } | |
570 | |
571 #if (XlibSpecificationRelease == 4) | |
572 MACROLET (lwlib_uses_x11r4); | |
573 #elif (XlibSpecificationRelease == 5) | |
574 MACROLET (lwlib_uses_x11r5); | |
575 #elif (XlibSpecificationRelease == 6) | |
576 MACROLET (lwlib_uses_x11r6); | |
577 #else | |
578 MACROLET (lwlib_uses_unknown_x11); | |
579 #endif | |
580 #ifdef LWLIB_USES_MOTIF | |
581 MACROLET (lwlib_uses_motif); | |
582 #else | |
583 MACROLET (lwlib_does_not_use_motif); | |
584 #endif | |
585 #if (XmVersion >= 1002) | |
586 MACROLET (lwlib_uses_motif_1_2); | |
587 #else | |
588 MACROLET (lwlib_does_not_use_motif_1_2); | |
589 #endif | |
590 #ifdef LWLIB_MENUBARS_LUCID | |
591 MACROLET (lwlib_menubars_lucid); | |
592 #elif defined (HAVE_MENUBARS) | |
593 MACROLET (lwlib_menubars_motif); | |
594 #endif | |
595 #ifdef LWLIB_SCROLLBARS_LUCID | |
596 MACROLET (lwlib_scrollbars_lucid); | |
597 #elif defined (LWLIB_SCROLLBARS_MOTIF) | |
598 MACROLET (lwlib_scrollbars_motif); | |
599 #elif defined (HAVE_SCROLLBARS) | |
600 MACROLET (lwlib_scrollbars_athena); | |
601 #endif | |
602 #ifdef LWLIB_DIALOGS_MOTIF | |
603 MACROLET (lwlib_dialogs_motif); | |
604 #elif defined (HAVE_DIALOGS) | |
605 MACROLET (lwlib_dialogs_athena); | |
606 #endif | |
607 #ifdef LWLIB_WIDGETS_MOTIF | |
608 MACROLET (lwlib_widgets_motif); | |
609 #elif defined (HAVE_WIDGETS) | |
610 MACROLET (lwlib_widgets_athena); | |
611 #endif | |
612 | |
613 #undef MACROLET | |
614 } | |
615 | |
616 void | |
617 syms_of_gui_x (void) | |
618 { | |
619 defsymbol (&Qmenu_no_selection_hook, "menu-no-selection-hook"); | |
620 } | |
621 | |
622 void | |
623 reinit_vars_of_gui_x (void) | |
624 { | |
625 lwlib_id_tick = (1<<16); /* start big, to not conflict with Energize */ | |
626 #ifdef HAVE_POPUPS | |
627 popup_up_p = 0; | |
628 #endif | |
629 | |
630 /* this makes only safe calls as in emacs.c */ | |
631 sanity_check_lwlib (); | |
632 } | |
633 | |
634 void | |
635 vars_of_gui_x (void) | |
636 { | |
637 reinit_vars_of_gui_x (); | |
638 | |
639 Vpopup_callbacks = Qnil; | |
640 staticpro (&Vpopup_callbacks); | |
641 | |
642 #if 0 | |
643 /* This DEFVAR_LISP is just for the benefit of make-docfile. */ | |
644 /* #### misnamed */ | |
645 DEFVAR_LISP ("menu-no-selection-hook", &Vmenu_no_selection_hook /* | |
646 Function or functions to call when a menu or dialog box is dismissed | |
647 without a selection having been made. | |
648 */ ); | |
649 #endif | |
650 Fset (Qmenu_no_selection_hook, Qnil); | |
651 } |