Mercurial > hg > xemacs-beta
comparison src/menubar-x.c @ 371:cc15677e0335 r21-2b1
Import from CVS: tag r21-2b1
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:03:08 +0200 |
parents | 8e84bee8ddd0 |
children | 6240c7796c7a |
comparison
equal
deleted
inserted
replaced
370:bd866891f083 | 371:cc15677e0335 |
---|---|
122 } | 122 } |
123 else | 123 else |
124 { | 124 { |
125 wv->name = string_chars; | 125 wv->name = string_chars; |
126 wv->enabled = 1; | 126 wv->enabled = 1; |
127 /* dverna Dec. 98: command_builder_operate_menu_accelerator will | |
128 manipulate the accel as a Lisp_Object if the widget has a name. | |
129 Since simple labels have a name, but no accel, we *must* set it | |
130 to nil */ | |
131 wv->accel = LISP_TO_VOID (Qnil); | |
132 } | 127 } |
133 } | 128 } |
134 else if (VECTORP (desc)) | 129 else if (VECTORP (desc)) |
135 { | 130 { |
136 if (!button_item_to_widget_value (desc, wv, 1, | 131 if (!button_item_to_widget_value (desc, wv, 1, |
149 | 144 |
150 if (STRINGP (XCAR (desc))) | 145 if (STRINGP (XCAR (desc))) |
151 { | 146 { |
152 Lisp_Object key, val; | 147 Lisp_Object key, val; |
153 Lisp_Object include_p = Qnil, hook_fn = Qnil, config_tag = Qnil; | 148 Lisp_Object include_p = Qnil, hook_fn = Qnil, config_tag = Qnil; |
154 Lisp_Object active_p = Qt; | |
155 Lisp_Object accel; | 149 Lisp_Object accel; |
156 int included_spec = 0; | 150 int included_spec = 0; |
157 int active_spec = 0; | |
158 wv->type = CASCADE_TYPE; | 151 wv->type = CASCADE_TYPE; |
159 wv->enabled = 1; | 152 wv->enabled = 1; |
160 wv->name = (char *) XSTRING_DATA (LISP_GETTEXT (XCAR (desc))); | 153 wv->name = (char *) XSTRING_DATA (LISP_GETTEXT (XCAR (desc))); |
161 | 154 |
162 accel = menu_name_to_accelerator (wv->name); | 155 accel = menu_name_to_accelerator (wv->name); |
177 include_p = val, included_spec = 1; | 170 include_p = val, included_spec = 1; |
178 else if (EQ (key, Q_config)) | 171 else if (EQ (key, Q_config)) |
179 config_tag = val; | 172 config_tag = val; |
180 else if (EQ (key, Q_filter)) | 173 else if (EQ (key, Q_filter)) |
181 hook_fn = val; | 174 hook_fn = val; |
182 else if (EQ (key, Q_active)) | |
183 active_p = val, active_spec = 1; | |
184 else if (EQ (key, Q_accelerator)) | 175 else if (EQ (key, Q_accelerator)) |
185 { | 176 { |
186 if ( SYMBOLP (val) | 177 if ( SYMBOLP (val) |
187 || CHARP (val)) | 178 || CHARP (val)) |
188 wv->accel = LISP_TO_VOID (val); | 179 wv->accel = LISP_TO_VOID (val); |
189 else | 180 else |
190 signal_simple_error ("bad keyboard accelerator", val); | 181 signal_simple_error ("bad keyboard accelerator", val); |
191 } | 182 } |
192 else if (EQ (key, Q_label)) | |
193 { | |
194 /* implement in 21.2 */ | |
195 } | |
196 else | 183 else |
197 signal_simple_error ("unknown menu cascade keyword", cascade); | 184 signal_simple_error ("unknown menu cascade keyword", cascade); |
198 } | 185 } |
199 | 186 |
200 if ((!NILP (config_tag) | 187 if ((!NILP (config_tag) |
202 || (included_spec && NILP (Feval (include_p)))) | 189 || (included_spec && NILP (Feval (include_p)))) |
203 { | 190 { |
204 wv = NULL; | 191 wv = NULL; |
205 goto menu_item_done; | 192 goto menu_item_done; |
206 } | 193 } |
207 | 194 if (!NILP (hook_fn)) |
208 if (active_spec) | |
209 active_p = Feval (active_p); | |
210 | |
211 if (!NILP (hook_fn) && !NILP (active_p)) | |
212 { | 195 { |
213 #if defined LWLIB_MENUBARS_LUCID || defined LWLIB_MENUBARS_MOTIF | 196 #if defined LWLIB_MENUBARS_LUCID || defined LWLIB_MENUBARS_MOTIF |
214 if (filter_p || depth == 0) | 197 if (filter_p || depth == 0) |
215 { | 198 { |
216 #endif | 199 #endif |
251 sep_wv->next = 0; | 234 sep_wv->next = 0; |
252 | 235 |
253 wv->contents = title_wv; | 236 wv->contents = title_wv; |
254 prev = sep_wv; | 237 prev = sep_wv; |
255 } | 238 } |
256 wv->enabled = ! NILP (active_p); | |
257 if (deep_p && !wv->enabled && !NILP (desc)) | |
258 { | |
259 widget_value *dummy; | |
260 /* Add a fake entry so the menus show up */ | |
261 wv->contents = dummy = xmalloc_widget_value (); | |
262 dummy->name = "(inactive)"; | |
263 dummy->accel = LISP_TO_VOID (Qnil); | |
264 dummy->enabled = 0; | |
265 dummy->selected = 0; | |
266 dummy->value = NULL; | |
267 dummy->type = BUTTON_TYPE; | |
268 dummy->call_data = NULL; | |
269 dummy->next = NULL; | |
270 | |
271 goto menu_item_done; | |
272 } | |
273 | |
274 } | 239 } |
275 else if (menubar_root_p) | 240 else if (menubar_root_p) |
276 { | 241 { |
277 wv->name = (char *) "menubar"; | 242 wv->name = (char *) "menubar"; |
278 wv->type = CASCADE_TYPE; /* Well, nothing else seems to fit and | 243 wv->type = CASCADE_TYPE; /* Well, nothing else seems to fit and |
281 else | 246 else |
282 { | 247 { |
283 signal_simple_error ("menu name (first element) must be a string", | 248 signal_simple_error ("menu name (first element) must be a string", |
284 desc); | 249 desc); |
285 } | 250 } |
286 | 251 |
252 wv->enabled = 1; | |
287 if (deep_p || menubar_root_p) | 253 if (deep_p || menubar_root_p) |
288 { | 254 { |
289 widget_value *next; | 255 widget_value *next; |
290 for (; !NILP (desc); desc = Fcdr (desc)) | 256 for (; !NILP (desc); desc = Fcdr (desc)) |
291 { | 257 { |
365 in_menu_callback = XINT(val); | 331 in_menu_callback = XINT(val); |
366 return Qnil; | 332 return Qnil; |
367 } | 333 } |
368 #endif /* LWLIB_MENUBARS_LUCID || LWLIB_MENUBARS_MOTIF */ | 334 #endif /* LWLIB_MENUBARS_LUCID || LWLIB_MENUBARS_MOTIF */ |
369 | 335 |
370 #if 0 | |
371 /* #### Sort of a hack needed to process Vactivate_menubar_hook | |
372 correctly wrt buffer-local values. A correct solution would | |
373 involve adding a callback mechanism to run_hook(). This function | |
374 is currently unused. */ | |
375 static int | |
376 my_run_hook (Lisp_Object hooksym, int allow_global_p) | |
377 { | |
378 /* This function can GC */ | |
379 Lisp_Object tail; | |
380 Lisp_Object value = Fsymbol_value (hooksym); | |
381 int changes = 0; | |
382 | |
383 if (!NILP (value) && (!CONSP (value) || EQ (XCAR (value), Qlambda))) | |
384 return !EQ (call0 (value), Qt); | |
385 | |
386 EXTERNAL_LIST_LOOP (tail, value) | |
387 { | |
388 if (allow_global_p && EQ (XCAR (tail), Qt)) | |
389 changes |= my_run_hook (Fdefault_value (hooksym), 0); | |
390 if (!EQ (call0 (XCAR (tail)), Qt)) | |
391 changes = 1; | |
392 } | |
393 return changes; | |
394 } | |
395 #endif | |
396 | |
397 | 336 |
398 /* The order in which callbacks are run is funny to say the least. | 337 /* The order in which callbacks are run is funny to say the least. |
399 It's sometimes tricky to avoid running a callback twice, and to | 338 It's sometimes tricky to avoid running a callback twice, and to |
400 avoid returning prematurely. So, this function returns true | 339 avoid returning prematurely. So, this function returns true |
401 if the menu's callbacks are no longer gc protected. So long | 340 if the menu's callbacks are no longer gc protected. So long |
417 | 356 |
418 static void | 357 static void |
419 pre_activate_callback (Widget widget, LWLIB_ID id, XtPointer client_data) | 358 pre_activate_callback (Widget widget, LWLIB_ID id, XtPointer client_data) |
420 { | 359 { |
421 /* This function can GC */ | 360 /* This function can GC */ |
361 struct gcpro gcpro1; | |
422 struct device *d = get_device_from_display (XtDisplay (widget)); | 362 struct device *d = get_device_from_display (XtDisplay (widget)); |
423 struct frame *f = x_any_window_to_frame (d, XtWindow (widget)); | 363 struct frame *f = x_any_window_to_frame (d, XtWindow (widget)); |
364 Lisp_Object rest = Qnil; | |
424 Lisp_Object frame; | 365 Lisp_Object frame; |
366 int any_changes = 0; | |
425 int count; | 367 int count; |
426 | 368 |
427 /* set in lwlib to the time stamp associated with the most recent menu | 369 /* set in lwlib to the time stamp associated with the most recent menu |
428 operation */ | 370 operation */ |
429 extern Time x_focus_timestamp_really_sucks_fix_me_better; | 371 extern Time x_focus_timestamp_really_sucks_fix_me_better; |
465 if (!wv) | 407 if (!wv) |
466 { | 408 { |
467 wv = xmalloc_widget_value (); | 409 wv = xmalloc_widget_value (); |
468 wv->type = CASCADE_TYPE; | 410 wv->type = CASCADE_TYPE; |
469 wv->next = NULL; | 411 wv->next = NULL; |
470 wv->accel = LISP_TO_VOID (Qnil); | |
471 wv->contents = xmalloc_widget_value (); | 412 wv->contents = xmalloc_widget_value (); |
472 wv->contents->type = TEXT_TYPE; | 413 wv->contents->type = TEXT_TYPE; |
473 wv->contents->name = (char *) "No menu"; | 414 wv->contents->name = (char *) "No menu"; |
474 wv->contents->next = NULL; | 415 wv->contents->next = NULL; |
475 wv->contents->accel = LISP_TO_VOID (Qnil); | |
476 } | 416 } |
477 assert (wv && wv->type == CASCADE_TYPE && wv->contents); | 417 assert (wv && wv->type == CASCADE_TYPE && wv->contents); |
478 replace_widget_value_tree (hack_wv, wv->contents); | 418 replace_widget_value_tree (hack_wv, wv->contents); |
479 free_popup_widget_value_tree (wv); | 419 free_popup_widget_value_tree (wv); |
480 } | 420 } |
481 else if (!POPUP_DATAP (FRAME_MENUBAR_DATA (f))) | |
482 return; | |
483 else | 421 else |
484 { | 422 { |
485 #if 0 /* Unused, see comment below. */ | 423 if (!POPUP_DATAP (FRAME_MENUBAR_DATA (f))) |
486 int any_changes; | 424 return; |
487 | |
488 /* #### - this menubar update mechanism is expensively anti-social and | 425 /* #### - this menubar update mechanism is expensively anti-social and |
489 the activate-menubar-hook is now mostly obsolete. */ | 426 the activate-menubar-hook is now mostly obsolete. */ |
490 any_changes = my_run_hook (Qactivate_menubar_hook, 1); | 427 /* make the activate-menubar-hook be a list of functions, not a single |
491 | 428 function, just to simplify things. */ |
429 if (!NILP (Vactivate_menubar_hook) && | |
430 (!CONSP (Vactivate_menubar_hook) || | |
431 EQ (XCAR (Vactivate_menubar_hook), Qlambda))) | |
432 Vactivate_menubar_hook = Fcons (Vactivate_menubar_hook, Qnil); | |
433 | |
434 GCPRO1 (rest); | |
435 for (rest = Vactivate_menubar_hook; !NILP (rest); rest = Fcdr (rest)) | |
436 if (!EQ (call0 (XCAR (rest)), Qt)) | |
437 any_changes = 1; | |
438 #if 0 | |
492 /* #### - It is necessary to *ALWAYS* call set_frame_menubar() now that | 439 /* #### - It is necessary to *ALWAYS* call set_frame_menubar() now that |
493 incremental menus are implemented. If a subtree of a menu has been | 440 incremental menus are implemented. If a subtree of a menu has been |
494 updated incrementally (a destructive operation), then that subtree | 441 updated incrementally (a destructive operation), then that subtree |
495 must somehow be wiped. | 442 must somehow be wiped. |
496 | 443 |
497 It is difficult to undo the destructive operation in lwlib because | 444 It is difficult to undo the destructive operation in lwlib because |
498 a pointer back to lisp data needs to be hidden away somewhere. So | 445 a pointer back to lisp data needs to be hidden away somewhere. So |
499 that an INCREMENTAL_TYPE widget_value can be recreated... Hmmmmm. */ | 446 that an INCREMENTAL_TYPE widget_value can be recreated... Hmmmmm. */ |
500 if (any_changes || | 447 if (any_changes || |
501 !XFRAME_MENUBAR_DATA (f)->menubar_contents_up_to_date) | 448 !XFRAME_MENUBAR_DATA (f)->menubar_contents_up_to_date) |
449 #endif | |
502 set_frame_menubar (f, 1, 0); | 450 set_frame_menubar (f, 1, 0); |
503 #else | |
504 run_hook (Qactivate_menubar_hook); | |
505 set_frame_menubar (f, 1, 0); | |
506 #endif | |
507 DEVICE_X_MOUSE_TIMESTAMP (XDEVICE (FRAME_DEVICE (f))) = | 451 DEVICE_X_MOUSE_TIMESTAMP (XDEVICE (FRAME_DEVICE (f))) = |
508 DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (XDEVICE (FRAME_DEVICE (f))) = | 452 DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (XDEVICE (FRAME_DEVICE (f))) = |
509 x_focus_timestamp_really_sucks_fix_me_better; | 453 x_focus_timestamp_really_sucks_fix_me_better; |
454 UNGCPRO; | |
510 } | 455 } |
511 } | 456 } |
512 | 457 |
513 static widget_value * | 458 static widget_value * |
514 compute_menubar_data (struct frame *f, Lisp_Object menubar, int deep_p) | 459 compute_menubar_data (struct frame *f, Lisp_Object menubar, int deep_p) |
674 btn->display = XtDisplay (daddy); | 619 btn->display = XtDisplay (daddy); |
675 btn->window = XtWindow (daddy); | 620 btn->window = XtWindow (daddy); |
676 if (eev) | 621 if (eev) |
677 { | 622 { |
678 Position shellx, shelly, framex, framey; | 623 Position shellx, shelly, framex, framey; |
624 Widget shell = XtParent (daddy); | |
679 Arg al [2]; | 625 Arg al [2]; |
680 btn->time = eev->timestamp; | 626 btn->time = eev->timestamp; |
681 btn->button = eev->event.button.button; | 627 btn->button = eev->event.button.button; |
682 btn->root = RootWindowOfScreen (XtScreen (daddy)); | 628 btn->root = RootWindowOfScreen (XtScreen (daddy)); |
683 btn->subwindow = (Window) NULL; | 629 btn->subwindow = (Window) NULL; |
684 btn->x = eev->event.button.x; | 630 btn->x = eev->event.button.x; |
685 btn->y = eev->event.button.y; | 631 btn->y = eev->event.button.y; |
686 shellx = shelly = 0; | 632 XtSetArg (al [0], XtNx, &shellx); |
687 #ifndef HAVE_SESSION | 633 XtSetArg (al [1], XtNy, &shelly); |
688 { | 634 XtGetValues (shell, al, 2); |
689 Widget shell = XtParent (daddy); | |
690 | |
691 XtSetArg (al [0], XtNx, &shellx); | |
692 XtSetArg (al [1], XtNy, &shelly); | |
693 XtGetValues (shell, al, 2); | |
694 } | |
695 #endif | |
696 XtSetArg (al [0], XtNx, &framex); | 635 XtSetArg (al [0], XtNx, &framex); |
697 XtSetArg (al [1], XtNy, &framey); | 636 XtSetArg (al [1], XtNy, &framey); |
698 XtGetValues (daddy, al, 2); | 637 XtGetValues (daddy, al, 2); |
699 btn->x_root = shellx + framex + btn->x; | 638 btn->x_root = shellx + framex + btn->x; |
700 btn->y_root = shelly + framey + btn->y;; | 639 btn->y_root = shelly + framey + btn->y;; |