Lisp_Object menu_parse_submenu_keywords (Lisp_Object desc, Lisp_Object gui_item) { Lisp_Gui_Item *pgui_item = XGUI_ITEM (gui_item); /* Menu descriptor should be a list */ CHECK_CONS (desc); /* First element may be menu name, although can be omitted. Let's think that if stuff begins with anything than a keyword or a list (submenu), this is a menu name, expected to be a string */ if (!KEYWORDP (XCAR (desc)) && !CONSP (XCAR (desc))) { CHECK_STRING (XCAR (desc)); pgui_item->name = XCAR (desc); desc = XCDR (desc); if (!NILP (desc)) CHECK_CONS (desc); } /* Walk along all key-value pairs */ while (!NILP(desc) && KEYWORDP (XCAR (desc))) { Lisp_Object key, val; key = XCAR (desc); desc = XCDR (desc); CHECK_CONS (desc); val = XCAR (desc); desc = XCDR (desc); if (!NILP (desc)) CHECK_CONS (desc); gui_item_add_keyval_pair (gui_item, key, val, ERROR_ME); } /* Return the rest - supposed to be a list of items */ return desc; }
/* This does the dirty work. gc_currently_forbidden is 1 when this is called. */ int button_item_to_widget_value(Lisp_Object gui_object_instance, Lisp_Object gui_item, widget_value * wv, int allow_text_field_p, int no_keys_p, int menu_entry_p, int accel_p) { /* This function cannot GC because gc_currently_forbidden is set when it's called */ Lisp_Gui_Item *pgui = 0; /* degenerate case */ if (STRINGP(gui_item)) { wv->type = TEXT_TYPE; if (accel_p) wv->name = add_accel_and_to_external(gui_item); else LISP_STRING_TO_EXTERNAL_MALLOC(gui_item, wv->name, Qlwlib_encoding); return 1; } else if (!GUI_ITEMP(gui_item)) syntax_error("need a string or a gui_item here", gui_item); pgui = XGUI_ITEM(gui_item); if (!NILP(pgui->filter)) syntax_error(":filter keyword not permitted on leaf nodes", gui_item); #ifdef HAVE_MENUBARS if (menu_entry_p && !gui_item_included_p(gui_item, Vmenubar_configuration)) { /* the include specification says to ignore this item. */ return 0; } #endif /* HAVE_MENUBARS */ if (!STRINGP(pgui->name)) pgui->name = Feval(pgui->name); CHECK_STRING(pgui->name); if (accel_p) { Lisp_Object tmp = gui_item_accelerator(gui_item); wv->name = add_accel_and_to_external(pgui->name); wv->accel = LISP_TO_VOID(tmp); } else { LISP_STRING_TO_EXTERNAL_MALLOC(pgui->name, wv->name, Qlwlib_encoding); wv->accel = LISP_TO_VOID(Qnil); } if (!NILP(pgui->suffix)) { Lisp_Object suffix2; /* Shortcut to avoid evaluating suffix each time */ if (STRINGP(pgui->suffix)) suffix2 = pgui->suffix; else { suffix2 = Feval(pgui->suffix); CHECK_STRING(suffix2); } LISP_STRING_TO_EXTERNAL_MALLOC(suffix2, wv->value, Qlwlib_encoding); } wv_set_evalable_slot(wv->enabled, pgui->active); wv_set_evalable_slot(wv->selected, pgui->selected); if (!NILP(pgui->callback) || !NILP(pgui->callback_ex)) { Lisp_Object tmp = cons3(gui_object_instance, pgui->callback, pgui->callback_ex); wv->call_data = LISP_TO_VOID(tmp); } if (no_keys_p #ifdef HAVE_MENUBARS || (menu_entry_p && !menubar_show_keybindings) #endif ) { wv->key = 0; } else if (!NILP(pgui->keys)) { /* Use this string to generate key bindings */ CHECK_STRING(pgui->keys); pgui->keys = Fsubstitute_command_keys(pgui->keys); if (XSTRING_LENGTH(pgui->keys) > 0) LISP_STRING_TO_EXTERNAL_MALLOC(pgui->keys, wv->key, Qlwlib_encoding); else wv->key = 0; } else if (SYMBOLP(pgui->callback)) { /* Show the binding of this command. */ char buf[1024]; /* #### */ /* #### Warning, dependency here on current_buffer and point */ where_is_to_char(pgui->callback, buf); if (buf[0]) C_STRING_TO_EXTERNAL_MALLOC(buf, wv->key, Qlwlib_encoding); else wv->key = 0; } CHECK_SYMBOL(pgui->style); if (NILP(pgui->style)) { Bufbyte *intname = NULL; Bytecount intlen; /* If the callback is nil, treat this item like unselectable text. This way, dashes will show up as a separator. */ if (!wv->enabled) wv->type = BUTTON_TYPE; TO_INTERNAL_FORMAT(C_STRING, wv->name, ALLOCA, (intname, intlen), Qlwlib_encoding); if (intname != NULL && separator_string_p(intname)) { wv->type = SEPARATOR_TYPE; wv->value = menu_separator_style_and_to_external(intname); } else { #if 0 /* #### - this is generally desirable for menubars, but it breaks a package that uses dialog boxes and next_command_event magic to use the callback slot in dialog buttons for data instead of a real callback. Code is data, right? The beauty of LISP abuse. --Stig */ if (NILP(callback)) wv->type = TEXT_TYPE; else #endif wv->type = BUTTON_TYPE; } } else if (EQ(pgui->style, Qbutton)) wv->type = BUTTON_TYPE; else if (EQ(pgui->style, Qtoggle)) wv->type = TOGGLE_TYPE; else if (EQ(pgui->style, Qradio)) wv->type = RADIO_TYPE; else if (EQ(pgui->style, Qtext)) { wv->type = TEXT_TYPE; #if 0 wv->value = wv->name; wv->name = "value"; #endif } else syntax_error_2("Unknown style", pgui->style, gui_item); if (!allow_text_field_p && (wv->type == TEXT_TYPE)) syntax_error("Text field not allowed in this context", gui_item); if (!NILP(pgui->selected) && EQ(pgui->style, Qtext)) syntax_error (":selected only makes sense with :style toggle, radio or button", gui_item); return 1; }
Find a submenu descriptor within DESC by following PATH. This function finds a submenu descriptor, either from the description DESC or generated by a filter within DESC. The function regards :config and :included keywords in the DESC, and expands submenus along the PATH using :filter functions. Return value is a descriptor for the submenu, NOT expanded and NOT checked against :config and :included. Also, individual menu items are not looked for, only submenus. See also 'find-menu-item'. */ (desc, path)) { Lisp_Object path_entry, submenu_desc, submenu; struct gcpro gcpro1, gcpro2; Lisp_Object gui_item = allocate_gui_item (); Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item); GCPRO2 (gui_item, desc); EXTERNAL_LIST_LOOP (path_entry, path) { /* Verify that DESC describes a menu, not single item */ if (!CONSP (desc)) RETURN_UNGCPRO (Qnil); /* Parse this menu */ desc = menu_parse_submenu_keywords (desc, gui_item); /* Check that this (sub)menu is active */ if (!gui_item_active_p (gui_item)) RETURN_UNGCPRO (Qnil);