comparison src/gui-x.c @ 420:41dbb7a9d5f2 r21-2-18

Import from CVS: tag r21-2-18
author cvs
date Mon, 13 Aug 2007 11:24:09 +0200
parents 697ef44129c6
children 11054d720c21
comparison
equal deleted inserted replaced
419:66615b78f1a5 420:41dbb7a9d5f2
33 #include "gui-x.h" 33 #include "gui-x.h"
34 #include "buffer.h" 34 #include "buffer.h"
35 #include "device.h" 35 #include "device.h"
36 #include "frame.h" 36 #include "frame.h"
37 #include "gui.h" 37 #include "gui.h"
38 #include "redisplay.h"
38 #include "opaque.h" 39 #include "opaque.h"
39 40
40 #ifdef HAVE_POPUPS
41 Lisp_Object Qmenu_no_selection_hook; 41 Lisp_Object Qmenu_no_selection_hook;
42 #endif
43 42
44 /* we need a unique id for each popup menu, dialog box, and scrollbar */ 43 /* we need a unique id for each popup menu, dialog box, and scrollbar */
45 static unsigned int lwlib_id_tick; 44 static unsigned int lwlib_id_tick;
46 45
47 LWLIB_ID 46 LWLIB_ID
57 if (!tmp) memory_full (); 56 if (!tmp) memory_full ();
58 return tmp; 57 return tmp;
59 } 58 }
60 59
61 60
62 #ifdef HAVE_POPUPS
63
64 struct mark_widget_value_closure 61 struct mark_widget_value_closure
65 { 62 {
66 void (*markobj) (Lisp_Object); 63 void (*markobj) (Lisp_Object);
67 }; 64 };
68 65
106 return data->last_menubar_buffer; 103 return data->last_menubar_buffer;
107 } 104 }
108 105
109 DEFINE_LRECORD_IMPLEMENTATION ("popup-data", popup_data, 106 DEFINE_LRECORD_IMPLEMENTATION ("popup-data", popup_data,
110 mark_popup_data, internal_object_printer, 107 mark_popup_data, internal_object_printer,
111 0, 0, 0, struct popup_data); 108 0, 0, 0, 0, struct popup_data);
112 109
113 /* This is like FRAME_MENUBAR_DATA (f), but contains an alist of 110 /* This is like FRAME_MENUBAR_DATA (f), but contains an alist of
114 (id . popup-data) for GCPRO'ing the callbacks of the popup menus 111 (id . popup-data) for GCPRO'ing the callbacks of the popup menus
115 and dialog boxes. */ 112 and dialog boxes. */
116 static Lisp_Object Vpopup_callbacks; 113 static Lisp_Object Vpopup_callbacks;
257 { 254 {
258 fn = Qrun_hooks; 255 fn = Qrun_hooks;
259 arg = Qmenu_no_selection_hook; 256 arg = Qmenu_no_selection_hook;
260 } 257 }
261 else 258 else
262 get_gui_callback (data, &fn, &arg); 259 {
260 MARK_SUBWINDOWS_CHANGED;
261 get_gui_callback (data, &fn, &arg);
262 }
263 263
264 /* This is the timestamp used for asserting focus so we need to get an 264 /* This is the timestamp used for asserting focus so we need to get an
265 up-to-date value event if no events has been dispatched to emacs 265 up-to-date value event if no events has been dispatched to emacs
266 */ 266 */
267 #if defined(HAVE_MENUBARS) 267 #if defined(HAVE_MENUBARS)
313 return xstrdup (p+1); 313 return xstrdup (p+1);
314 314
315 return NULL; 315 return NULL;
316 } 316 }
317 317
318 /* set menu accelerator key to first underlined character in menu name */
319
320 Lisp_Object
321 menu_name_to_accelerator (char *name)
322 {
323 while (*name) {
324 if (*name=='%') {
325 ++name;
326 if (!(*name))
327 return Qnil;
328 if (*name=='_' && *(name+1))
329 {
330 int accelerator = (int) (unsigned char) (*(name+1));
331 return make_char (tolower (accelerator));
332 }
333 }
334 ++name;
335 }
336 return Qnil;
337 }
338 318
339 /* This does the dirty work. gc_currently_forbidden is 1 when this is called. 319 /* This does the dirty work. gc_currently_forbidden is 1 when this is called.
340 */ 320 */
341
342 int 321 int
343 button_item_to_widget_value (Lisp_Object desc, widget_value *wv, 322 button_item_to_widget_value (Lisp_Object gui_item, widget_value *wv,
344 int allow_text_field_p, int no_keys_p) 323 int allow_text_field_p, int no_keys_p)
345 { 324 {
346 /* !!#### This function has not been Mule-ized */ 325 /* !!#### This function has not been Mule-ized */
347 /* This function cannot GC because gc_currently_forbidden is set when 326 /* This function cannot GC because gc_currently_forbidden is set when
348 it's called */ 327 it's called */
349 Lisp_Object name = Qnil; 328 struct Lisp_Gui_Item* pgui = XGUI_ITEM (gui_item);
350 Lisp_Object callback = Qnil; 329
351 Lisp_Object suffix = Qnil; 330 if (!NILP (pgui->filter))
352 Lisp_Object active_p = Qt; 331 signal_simple_error(":filter keyword not permitted on leaf nodes", gui_item);
353 Lisp_Object include_p = Qt;
354 Lisp_Object selected_p = Qnil;
355 Lisp_Object keys = Qnil;
356 Lisp_Object style = Qnil;
357 Lisp_Object config_tag = Qnil;
358 Lisp_Object accel = Qnil;
359 int length = XVECTOR_LENGTH (desc);
360 Lisp_Object *contents = XVECTOR_DATA (desc);
361 int plist_p;
362 int selected_spec = 0, included_spec = 0;
363
364 if (length < 2)
365 signal_simple_error ("Button descriptors must be at least 2 long", desc);
366
367 /* length 2: [ "name" callback ]
368 length 3: [ "name" callback active-p ]
369 length 4: [ "name" callback active-p suffix ]
370 or [ "name" callback keyword value ]
371 length 5+: [ "name" callback [ keyword value ]+ ]
372 */
373 plist_p = (length >= 5 || (length > 2 && KEYWORDP (contents [2])));
374
375 if (!plist_p && length > 2)
376 /* the old way */
377 {
378 name = contents [0];
379 callback = contents [1];
380 active_p = contents [2];
381 if (length == 4)
382 suffix = contents [3];
383 }
384 else
385 {
386 /* the new way */
387 int i;
388 if (length & 1)
389 signal_simple_error (
390 "Button descriptor has an odd number of keywords and values",
391 desc);
392
393 name = contents [0];
394 callback = contents [1];
395 for (i = 2; i < length;)
396 {
397 Lisp_Object key = contents [i++];
398 Lisp_Object val = contents [i++];
399 if (!KEYWORDP (key))
400 signal_simple_error_2 ("Not a keyword", key, desc);
401
402 if (EQ (key, Q_active)) active_p = val;
403 else if (EQ (key, Q_suffix)) suffix = val;
404 else if (EQ (key, Q_keys)) keys = val;
405 else if (EQ (key, Q_style)) style = val;
406 else if (EQ (key, Q_selected)) selected_p = val, selected_spec = 1;
407 else if (EQ (key, Q_included)) include_p = val, included_spec = 1;
408 else if (EQ (key, Q_config)) config_tag = val;
409 else if (EQ (key, Q_accelerator))
410 {
411 if ( SYMBOLP (val)
412 || CHARP (val))
413 accel = val;
414 else
415 signal_simple_error ("Bad keyboard accelerator", val);
416 }
417 else if (EQ (key, Q_filter))
418 signal_simple_error(":filter keyword not permitted on leaf nodes", desc);
419 else
420 signal_simple_error_2 ("Unknown menu item keyword", key, desc);
421 }
422 }
423 332
424 #ifdef HAVE_MENUBARS 333 #ifdef HAVE_MENUBARS
425 if ((!NILP (config_tag) && NILP (Fmemq (config_tag, Vmenubar_configuration))) 334 if (!gui_item_included_p (gui_item, Vmenubar_configuration))
426 || (included_spec && NILP (Feval (include_p))))
427 { 335 {
428 /* the include specification says to ignore this item. */ 336 /* the include specification says to ignore this item. */
429 return 0; 337 return 0;
430 } 338 }
431 #endif /* HAVE_MENUBARS */ 339 #endif /* HAVE_MENUBARS */
432 340
433 CHECK_STRING (name); 341 CHECK_STRING (pgui->name);
434 wv->name = (char *) XSTRING_DATA (name); 342 wv->name = (char *) XSTRING_DATA (pgui->name);
435 343 wv->accel = LISP_TO_VOID (gui_item_accelerator (gui_item));
436 if (NILP (accel)) 344
437 accel = menu_name_to_accelerator (wv->name); 345 if (!NILP (pgui->suffix))
438 wv->accel = LISP_TO_VOID (accel);
439
440 if (!NILP (suffix))
441 { 346 {
442 CONST char *const_bogosity; 347 CONST char *const_bogosity;
443 Lisp_Object suffix2; 348 Lisp_Object suffix2;
444 349
445 /* Shortcut to avoid evaluating suffix each time */ 350 /* Shortcut to avoid evaluating suffix each time */
446 if (STRINGP (suffix)) 351 if (STRINGP (pgui->suffix))
447 suffix2 = suffix; 352 suffix2 = pgui->suffix;
448 else 353 else
449 { 354 {
450 suffix2 = Feval (suffix); 355 suffix2 = Feval (pgui->suffix);
451 CHECK_STRING (suffix2); 356 CHECK_STRING (suffix2);
452 } 357 }
453 358
454 GET_C_STRING_FILENAME_DATA_ALLOCA (suffix2, const_bogosity); 359 GET_C_STRING_FILENAME_DATA_ALLOCA (suffix2, const_bogosity);
455 wv->value = (char *) const_bogosity; 360 wv->value = (char *) const_bogosity;
456 wv->value = xstrdup (wv->value); 361 wv->value = xstrdup (wv->value);
457 } 362 }
458 363
459 wv_set_evalable_slot (wv->enabled, active_p); 364 wv_set_evalable_slot (wv->enabled, pgui->active);
460 wv_set_evalable_slot (wv->selected, selected_p); 365 wv_set_evalable_slot (wv->selected, pgui->selected);
461 366
462 wv->call_data = LISP_TO_VOID (callback); 367 if (!NILP (pgui->callback))
368 wv->call_data = LISP_TO_VOID (pgui->callback);
463 369
464 if (no_keys_p 370 if (no_keys_p
465 #ifdef HAVE_MENUBARS 371 #ifdef HAVE_MENUBARS
466 || !menubar_show_keybindings 372 || !menubar_show_keybindings
467 #endif 373 #endif
468 ) 374 )
469 wv->key = 0; 375 wv->key = 0;
470 else if (!NILP (keys)) /* Use this string to generate key bindings */ 376 else if (!NILP (pgui->keys)) /* Use this string to generate key bindings */
471 { 377 {
472 CHECK_STRING (keys); 378 CHECK_STRING (pgui->keys);
473 keys = Fsubstitute_command_keys (keys); 379 pgui->keys = Fsubstitute_command_keys (pgui->keys);
474 if (XSTRING_LENGTH (keys) > 0) 380 if (XSTRING_LENGTH (pgui->keys) > 0)
475 wv->key = xstrdup ((char *) XSTRING_DATA (keys)); 381 wv->key = xstrdup ((char *) XSTRING_DATA (pgui->keys));
476 else 382 else
477 wv->key = 0; 383 wv->key = 0;
478 } 384 }
479 else if (SYMBOLP (callback)) /* Show the binding of this command. */ 385 else if (SYMBOLP (pgui->callback)) /* Show the binding of this command. */
480 { 386 {
481 char buf [1024]; 387 char buf [1024];
482 /* #### Warning, dependency here on current_buffer and point */ 388 /* #### Warning, dependency here on current_buffer and point */
483 where_is_to_char (callback, buf); 389 where_is_to_char (pgui->callback, buf);
484 if (buf [0]) 390 if (buf [0])
485 wv->key = xstrdup (buf); 391 wv->key = xstrdup (buf);
486 else 392 else
487 wv->key = 0; 393 wv->key = 0;
488 } 394 }
489 395
490 CHECK_SYMBOL (style); 396 CHECK_SYMBOL (pgui->style);
491 if (NILP (style)) 397 if (NILP (pgui->style))
492 { 398 {
493 /* If the callback is nil, treat this item like unselectable text. 399 /* If the callback is nil, treat this item like unselectable text.
494 This way, dashes will show up as a separator. */ 400 This way, dashes will show up as a separator. */
495 if (!wv->enabled) 401 if (!wv->enabled)
496 wv->type = BUTTON_TYPE; 402 wv->type = BUTTON_TYPE;
513 else 419 else
514 #endif 420 #endif
515 wv->type = BUTTON_TYPE; 421 wv->type = BUTTON_TYPE;
516 } 422 }
517 } 423 }
518 else if (EQ (style, Qbutton)) 424 else if (EQ (pgui->style, Qbutton))
519 wv->type = BUTTON_TYPE; 425 wv->type = BUTTON_TYPE;
520 else if (EQ (style, Qtoggle)) 426 else if (EQ (pgui->style, Qtoggle))
521 wv->type = TOGGLE_TYPE; 427 wv->type = TOGGLE_TYPE;
522 else if (EQ (style, Qradio)) 428 else if (EQ (pgui->style, Qradio))
523 wv->type = RADIO_TYPE; 429 wv->type = RADIO_TYPE;
524 else if (EQ (style, Qtext)) 430 else if (EQ (pgui->style, Qtext))
525 { 431 {
526 wv->type = TEXT_TYPE; 432 wv->type = TEXT_TYPE;
527 #if 0 433 #if 0
528 wv->value = wv->name; 434 wv->value = wv->name;
529 wv->name = "value"; 435 wv->name = "value";
530 #endif 436 #endif
531 } 437 }
532 else 438 else
533 signal_simple_error_2 ("Unknown style", style, desc); 439 signal_simple_error_2 ("Unknown style", pgui->style, gui_item);
534 440
535 if (!allow_text_field_p && (wv->type == TEXT_TYPE)) 441 if (!allow_text_field_p && (wv->type == TEXT_TYPE))
536 signal_simple_error ("Text field not allowed in this context", desc); 442 signal_simple_error ("Text field not allowed in this context", gui_item);
537 443
538 if (selected_spec && EQ (style, Qtext)) 444 if (!NILP (pgui->selected) && EQ (pgui->style, Qtext))
539 signal_simple_error ( 445 signal_simple_error (
540 ":selected only makes sense with :style toggle, radio or button", 446 ":selected only makes sense with :style toggle, radio or button",
541 desc); 447 gui_item);
542 return 1; 448 return 1;
543 } 449 }
544 450
545 #endif /* HAVE_POPUPS */
546 451
547 /* This is a kludge to make sure emacs can only link against a version of 452 /* This is a kludge to make sure emacs can only link against a version of
548 lwlib that was compiled in the right way. Emacs references symbols which 453 lwlib that was compiled in the right way. Emacs references symbols which
549 correspond to the way it thinks lwlib was compiled, and if lwlib wasn't 454 correspond to the way it thinks lwlib was compiled, and if lwlib wasn't
550 compiled in that way, then somewhat meaningful link errors will result. 455 compiled in that way, then somewhat meaningful link errors will result.
598 } 503 }
599 504
600 void 505 void
601 syms_of_gui_x (void) 506 syms_of_gui_x (void)
602 { 507 {
603 #ifdef HAVE_POPUPS
604 defsymbol (&Qmenu_no_selection_hook, "menu-no-selection-hook"); 508 defsymbol (&Qmenu_no_selection_hook, "menu-no-selection-hook");
605 #endif
606 } 509 }
607 510
608 void 511 void
609 vars_of_gui_x (void) 512 vars_of_gui_x (void)
610 { 513 {
611 lwlib_id_tick = (1<<16); /* start big, to not conflict with Energize */ 514 lwlib_id_tick = (1<<16); /* start big, to not conflict with Energize */
612 515
613 #ifdef HAVE_POPUPS
614 popup_up_p = 0; 516 popup_up_p = 0;
615 517
616 Vpopup_callbacks = Qnil; 518 Vpopup_callbacks = Qnil;
617 staticpro (&Vpopup_callbacks); 519 staticpro (&Vpopup_callbacks);
618 520
623 Function or functions to call when a menu or dialog box is dismissed 525 Function or functions to call when a menu or dialog box is dismissed
624 without a selection having been made. 526 without a selection having been made.
625 */ ); 527 */ );
626 #endif 528 #endif
627 Fset (Qmenu_no_selection_hook, Qnil); 529 Fset (Qmenu_no_selection_hook, Qnil);
628 #endif /* HAVE_POPUPS */
629 530
630 /* this makes only safe calls as in emacs.c */ 531 /* this makes only safe calls as in emacs.c */
631 sanity_check_lwlib (); 532 sanity_check_lwlib ();
632 } 533 }