Mercurial > hg > xemacs-beta
diff src/gui.c @ 251:677f6a0ee643 r20-5b24
Import from CVS: tag r20-5b24
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:19:59 +0200 |
parents | 557eaa0339bf |
children | 11cf20601dec |
line wrap: on
line diff
--- a/src/gui.c Mon Aug 13 10:19:12 2007 +0200 +++ b/src/gui.c Mon Aug 13 10:19:59 2007 +0200 @@ -23,8 +23,8 @@ /* Synched up with: Not in FSF. */ #include <config.h> +#include "lisp.h" #include "gui.h" -#include "lisp.h" Lisp_Object Q_active, Q_suffix, Q_keys, Q_style, Q_selected; Lisp_Object Q_filter, Q_config, Q_included; @@ -63,6 +63,237 @@ return 0; } +/* + * Initialize the gui_item structure by setting all (GC-protected) + * fields to their default values. The defaults are t for :active and + * :included values, and nil for others. + */ +void +gui_item_init (struct gui_item *pgui_item) +{ + pgui_item->name = Qnil; + pgui_item->callback = Qnil; + pgui_item->suffix = Qnil; + pgui_item->active = Qt; + pgui_item->included = Qt; + pgui_item->config = Qunbound; + pgui_item->filter = Qnil; + pgui_item->style = Qnil; + pgui_item->selected = Qnil; + pgui_item->keys = Qnil; +} + +/* + * Add a value VAL associated with keyword KEY into PGUI_ITEM + * structure. If KEY is not a keyword, or is an unknown keyword, then + * error is signaled. + */ +void +gui_item_add_keyval_pair (struct gui_item *pgui_item, + Lisp_Object key, Lisp_Object val) +{ + if (!KEYWORDP (key)) + error ("Not a keyword %S in gui item %S", key, pgui_item->name); + + if (EQ (key, Q_suffix)) + pgui_item->suffix = val; + else if (EQ (key, Q_active)) + pgui_item->active = val; + else if (EQ (key, Q_included)) + pgui_item->included = val; + else if (EQ (key, Q_config)) + pgui_item->config = val; + else if (EQ (key, Q_filter)) + pgui_item->filter = val; + else if (EQ (key, Q_style)) + pgui_item->style = val; + else if (EQ (key, Q_selected)) + pgui_item->selected = val; + else if (EQ (key, Q_keys)) + pgui_item->keys = val; + else + error ("Unknown keyword %S in gui item %S", key, pgui_item->name); +} + +/* + * ITEM is a lisp vector, describing a menu item or a button. The + * function extracts the description of the item into the PGUI_ITEM + * structure. + */ +void +gui_parse_item_keywords (Lisp_Object item, struct gui_item *pgui_item) +{ + int length, plist_p; + Lisp_Object *contents; + + CHECK_VECTOR (item); + length = XVECTOR_LENGTH (item); + contents = XVECTOR_DATA (item); + + if (length < 3) + signal_simple_error ("GUI item descriptors must be at least 3 elts long", item); + + /* length 3: [ "name" callback active-p ] + length 4: [ "name" callback active-p suffix ] + or [ "name" callback keyword value ] + length 5+: [ "name" callback [ keyword value ]+ ] + */ + plist_p = (length >= 5 || KEYWORDP (contents [2])); + + pgui_item->name = contents [0]; + pgui_item->callback = contents [1]; + + if (!plist_p) + /* the old way */ + { + pgui_item->active = contents [2]; + if (length == 4) + pgui_item->suffix = contents [3]; + } + else + /* the new way */ + { + int i; + if (length & 1) + signal_simple_error ( + "GUI item descriptor has an odd number of keywords and values", + item); + + for (i = 2; i < length;) + { + Lisp_Object key = contents [i++]; + Lisp_Object val = contents [i++]; + gui_item_add_keyval_pair (pgui_item, key, val); + } + } +} + +/* + * Decide whether a GUI item is active by evaluating its :active form + * if any + */ +int +gui_item_active_p (CONST struct gui_item *pgui_item) +{ + /* This function can call lisp */ + + /* Shortcut to avoid evaluating Qt each time */ + return (EQ (pgui_item->active, Qt) + || !NILP (Feval (pgui_item->active))); +} + +/* + * Decide whether a GUI item is included by evaluating its :included + * form if given, and testing its :config form against supplied CONFLIST + * configuration variable + */ +int +gui_item_included_p (CONST struct gui_item *pgui_item, Lisp_Object conflist) +{ + /* This function can call lisp */ + + /* Evaluate :included first. Shortcut to avoid evaluating Qt each time */ + if (!EQ (pgui_item->included, Qt) + && NILP (Feval (pgui_item->included))) + return 0; + + /* Do :config if conflist is given */ + if (!NILP (conflist) && !NILP (pgui_item->config) + && NILP (Fmemq (pgui_item->config, conflist))) + return 0; + + return 1; +} + +static DOESNT_RETURN +signal_too_long_error (Lisp_Object name) +{ + error ("GUI item %s produces too long displayable string", name); +} + +/* + * Format "left flush" display portion of an item into BUF, guarded by + * maximum buffer size BUF_LEN. BUF_LEN does not count for terminating + * null character, so actual maximum size of buffer consumed is + * BUF_LEN + 1 bytes. If buffer is not big enough, then error is + * signaled. + * Return value is the offset to the terminating null character into the + * buffer. + */ +unsigned int +gui_item_display_flush_left (CONST struct gui_item *pgui_item, + char* buf, unsigned int buf_len) +{ + unsigned int consumed; + + /* Copy item name first */ + CHECK_STRING (pgui_item->name); + if (XSTRING_LENGTH (pgui_item->name) > buf_len) + signal_too_long_error (pgui_item->name); + strcpy (buf, XSTRING_DATA (pgui_item->name)); + buf += (consumed = XSTRING_LENGTH (pgui_item->name)); + buf_len -= consumed; + + /* Add space and suffix text, if there is a suffix */ + if (!NILP (pgui_item->suffix)) + { + if (XSTRING_LENGTH (pgui_item->suffix) + 1 > buf_len) + signal_too_long_error (pgui_item->name); + *(buf++) = ' '; + strcpy (buf, XSTRING_DATA (pgui_item->suffix)); + consumed += XSTRING_LENGTH (pgui_item->suffix) + 1; + } + + return consumed; +} + +/* + * Format "right flush" display portion of an item into BUF, guarded by + * maximum buffer size BUF_LEN. BUF_LEN does not count for terminating + * null character, so actual maximum size of buffer consumed is + * BUF_LEN + 1 bytes. If buffer is not big enough, then error is + * signaled. + * Return value is the offset to the terminating null character into the + * buffer. + */ +unsigned int +gui_item_display_flush_right (CONST struct gui_item *pgui_item, + char* buf, unsigned int buf_len) +{ + *buf = 0; + + /* Have keys? */ + if (!menubar_show_keybindings) + return 0; + + /* Try :keys first */ + if (!NILP (pgui_item->keys)) + { + CHECK_STRING (pgui_item->keys); + if (XSTRING_LENGTH (pgui_item->keys) > buf_len) + signal_too_long_error (pgui_item->name); + strcpy (buf, XSTRING_DATA (pgui_item->keys)); + return XSTRING_LENGTH (pgui_item->keys); + } + + /* See if we can derive keys out of callback symbol */ + if (SYMBOLP (pgui_item->callback)) + { + char buf2 [1024]; + unsigned int len; + + where_is_to_char (pgui_item->callback, buf2); + len = strlen (buf2); + if (len > buf_len) + signal_too_long_error (pgui_item->name); + strcpy (buf, buf2); + return len; + } + + /* No keys - no right flush display */ + return 0; +} + #endif /* HAVE_POPUPS */ void