XEmacs 21.2.29 "Hestia".
[chise/xemacs-chise.git.1] / src / gui.c
index 587c163..d00df80 100644 (file)
--- a/src/gui.c
+++ b/src/gui.c
@@ -34,6 +34,8 @@ Lisp_Object Q_filter, Q_config, Q_included, Q_key_sequence;
 Lisp_Object Q_accelerator, Q_label, Q_callback;
 Lisp_Object Qtoggle, Qradio;
 
+static Lisp_Object parse_gui_item_tree_list (Lisp_Object list);
+
 #ifdef HAVE_POPUPS
 
 /* count of menus/dboxes currently up */
@@ -50,9 +52,9 @@ See `popup-menu' and `popup-dialog-box'.
 #endif /* HAVE_POPUPS */
 
 int
-separator_string_p (CONST char *s)
+separator_string_p (const char *s)
 {
-  CONST char *p;
+  const char *p;
   char first;
 
   if (!s || s[0] == '\0')
@@ -74,7 +76,7 @@ get_gui_callback (Lisp_Object data, Lisp_Object *fn, Lisp_Object *arg)
   if (SYMBOLP (data)
       || (COMPILED_FUNCTIONP (data)
          && XCOMPILED_FUNCTION (data)->flags.interactivep)
-      || (EQ (XCAR (data), Qlambda)
+      || (CONSP (data) && (EQ (XCAR (data), Qlambda))
          && !NILP (Fassq (Qinteractive, Fcdr (Fcdr (data))))))
     {
       *fn = Qcall_interactively;
@@ -103,10 +105,10 @@ get_gui_callback (Lisp_Object data, Lisp_Object *fn, Lisp_Object *arg)
  */
 void
 gui_item_add_keyval_pair (Lisp_Object gui_item,
-                         Lisp_Object key, Lisp_Object val, 
+                         Lisp_Object key, Lisp_Object val,
                          Error_behavior errb)
 {
-  struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
+  Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
 
   if (!KEYWORDP (key))
     signal_simple_error_2 ("Non-keyword in gui item", key, pgui_item->name);
@@ -120,8 +122,15 @@ gui_item_add_keyval_pair (Lisp_Object gui_item,
   else if (EQ (key, Q_selected)) pgui_item->selected = val;
   else if (EQ (key, Q_keys))    pgui_item->keys     = val;
   else if (EQ (key, Q_callback))        pgui_item->callback     = val;
-  else if (EQ (key, Q_key_sequence)) ;   /* ignored for FSF compatability */
+  else if (EQ (key, Q_key_sequence)) ;   /* ignored for FSF compatibility */
   else if (EQ (key, Q_label)) ;   /* ignored for 21.0 implement in 21.2  */
+  else if (EQ (key, Q_accelerator))
+    {
+      if (SYMBOLP (val) || CHARP (val))
+       pgui_item->accelerator = val;
+      else if (ERRB_EQ (errb, ERROR_ME))
+       signal_simple_error ("Bad keyboard accelerator", val);
+    }
   else if (ERRB_EQ (errb, ERROR_ME))
     signal_simple_error_2 ("Unknown keyword in gui item", key, pgui_item->name);
 }
@@ -129,7 +138,7 @@ gui_item_add_keyval_pair (Lisp_Object gui_item,
 void
 gui_item_init (Lisp_Object gui_item)
 {
-  struct Lisp_Gui_Item *lp = XGUI_ITEM (gui_item);
+  Lisp_Gui_Item *lp = XGUI_ITEM (gui_item);
 
   lp->name     = Qnil;
   lp->callback = Qnil;
@@ -141,13 +150,13 @@ gui_item_init (Lisp_Object gui_item)
   lp->style    = Qnil;
   lp->selected = Qnil;
   lp->keys     = Qnil;
+  lp->accelerator     = Qnil;
 }
 
 Lisp_Object
-allocate_gui_item ()
+allocate_gui_item (void)
 {
-  struct Lisp_Gui_Item *lp =
-    alloc_lcrecord_type (struct Lisp_Gui_Item, &lrecord_gui_item);
+  Lisp_Gui_Item *lp = alloc_lcrecord_type (Lisp_Gui_Item, &lrecord_gui_item);
   Lisp_Object val;
 
   zero_lcrecord (lp);
@@ -170,7 +179,7 @@ make_gui_item_from_keywords_internal (Lisp_Object item,
   int length, plist_p, start;
   Lisp_Object *contents;
   Lisp_Object gui_item = allocate_gui_item ();
-  struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
+  Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
 
   CHECK_VECTOR (item);
   length = XVECTOR_LENGTH (item);
@@ -197,7 +206,7 @@ make_gui_item_from_keywords_internal (Lisp_Object item,
       pgui_item->callback = contents [1];
       start = 2;
     }
-  else 
+  else
     start =1;
 
   if (!plist_p && length > 2)
@@ -242,8 +251,8 @@ gui_parse_item_keywords_no_errors (Lisp_Object item)
 void
 gui_add_item_keywords_to_plist (Lisp_Object plist, Lisp_Object gui_item)
 {
-  struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
-  
+  Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
+
   if (!NILP (pgui_item->callback))
     Fplist_put (plist, Q_callback, pgui_item->callback);
   if (!NILP (pgui_item->suffix))
@@ -262,6 +271,8 @@ gui_add_item_keywords_to_plist (Lisp_Object plist, Lisp_Object gui_item)
     Fplist_put (plist, Q_selected, pgui_item->selected);
   if (!NILP (pgui_item->keys))
     Fplist_put (plist, Q_keys, pgui_item->keys);
+  if (!NILP (pgui_item->accelerator))
+    Fplist_put (plist, Q_accelerator, pgui_item->accelerator);
 }
 
 /*
@@ -278,6 +289,41 @@ gui_item_active_p (Lisp_Object gui_item)
          || !NILP (Feval (XGUI_ITEM (gui_item)->active)));
 }
 
+/* set menu accelerator key to first underlined character in menu name */
+Lisp_Object
+gui_item_accelerator (Lisp_Object gui_item)
+{
+  Lisp_Gui_Item* pgui = XGUI_ITEM (gui_item);
+
+  if (!NILP (pgui->accelerator))
+    return pgui->accelerator;
+
+  else
+    return gui_name_accelerator (pgui->name);
+}
+
+Lisp_Object
+gui_name_accelerator (Lisp_Object nm)
+{
+  /* !!#### This function has not been Mule-ized */
+  char* name = (char*)XSTRING_DATA (nm);
+
+  while (*name) {
+    if (*name=='%') {
+      ++name;
+      if (!(*name))
+       return Qnil;
+      if (*name=='_' && *(name+1))
+       {
+         int accelerator = (int) (unsigned char) (*(name+1));
+         return make_char (tolower (accelerator));
+       }
+    }
+    ++name;
+  }
+  return Qnil;
+}
+
 /*
  * Decide whether a GUI item is selected by evaluating its :selected form
  * if any
@@ -301,7 +347,7 @@ int
 gui_item_included_p (Lisp_Object gui_item, Lisp_Object conflist)
 {
   /* This function can call lisp */
-  struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
+  Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
 
   /* Evaluate :included first. Shortcut to avoid evaluating Qt each time */
   if (!EQ (pgui_item->included, Qt)
@@ -336,9 +382,10 @@ unsigned int
 gui_item_display_flush_left  (Lisp_Object gui_item,
                              char* buf, Bytecount buf_len)
 {
+  /* This function can call lisp */
   char *p = buf;
   Bytecount len;
-  struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
+  Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
 
   /* Copy item name first */
   CHECK_STRING (pgui_item->name);
@@ -384,12 +431,14 @@ unsigned int
 gui_item_display_flush_right (Lisp_Object gui_item,
                              char* buf, Bytecount buf_len)
 {
-  struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
+  Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
   *buf = 0;
 
+#ifdef HAVE_MENUBARS
   /* Have keys? */
   if (!menubar_show_keybindings)
     return 0;
+#endif
 
   /* Try :keys first */
   if (!NILP (pgui_item->keys))
@@ -397,7 +446,7 @@ gui_item_display_flush_right (Lisp_Object gui_item,
       CHECK_STRING (pgui_item->keys);
       if (XSTRING_LENGTH (pgui_item->keys) > buf_len)
        signal_too_long_error (pgui_item->name);
-      strcpy (buf, (CONST char *) XSTRING_DATA (pgui_item->keys));
+      strcpy (buf, (const char *) XSTRING_DATA (pgui_item->keys));
       return XSTRING_LENGTH (pgui_item->keys);
     }
 
@@ -421,20 +470,22 @@ gui_item_display_flush_right (Lisp_Object gui_item,
 #endif /* HAVE_WINDOW_SYSTEM */
 
 static Lisp_Object
-mark_gui_item (Lisp_Object obj, void (*markobj) (Lisp_Object))
+mark_gui_item (Lisp_Object obj)
 {
-  struct Lisp_Gui_Item *p = XGUI_ITEM (obj);
-
-  markobj (p->name);
-  markobj (p->callback);
-  markobj (p->suffix);
-  markobj (p->active);
-  markobj (p->included);
-  markobj (p->config);
-  markobj (p->filter);
-  markobj (p->style);
-  markobj (p->selected);
-  markobj (p->keys);
+  Lisp_Gui_Item *p = XGUI_ITEM (obj);
+
+  mark_object (p->name);
+  mark_object (p->callback);
+  mark_object (p->config);
+  mark_object (p->suffix);
+  mark_object (p->active);
+  mark_object (p->included);
+  mark_object (p->config);
+  mark_object (p->filter);
+  mark_object (p->style);
+  mark_object (p->selected);
+  mark_object (p->keys);
+  mark_object (p->accelerator);
 
   return Qnil;
 }
@@ -442,7 +493,7 @@ mark_gui_item (Lisp_Object obj, void (*markobj) (Lisp_Object))
 static unsigned long
 gui_item_hash (Lisp_Object obj, int depth)
 {
-  struct Lisp_Gui_Item *p = XGUI_ITEM (obj);
+  Lisp_Gui_Item *p = XGUI_ITEM (obj);
 
   return HASH2 (HASH5 (internal_hash (p->name, depth + 1),
                       internal_hash (p->callback, depth + 1),
@@ -472,8 +523,8 @@ gui_item_id_hash (Lisp_Object hashtable, Lisp_Object gitem, int slot)
 static int
 gui_item_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
 {
-  struct Lisp_Gui_Item *p1 = XGUI_ITEM (obj1);
-  struct Lisp_Gui_Item *p2 = XGUI_ITEM (obj2);
+  Lisp_Gui_Item *p1 = XGUI_ITEM (obj1);
+  Lisp_Gui_Item *p2 = XGUI_ITEM (obj2);
 
   if (!(internal_equal (p1->name, p2->name, depth + 1)
        &&
@@ -493,6 +544,8 @@ gui_item_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
        &&
        EQ (p1->selected, p2->selected)
        &&
+       EQ (p1->accelerator, p2->accelerator)
+       &&
        EQ (p1->keys, p2->keys)))
     return 0;
   return 1;
@@ -501,7 +554,7 @@ gui_item_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
 static void
 print_gui_item (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
 {
-  struct Lisp_Gui_Item *g = XGUI_ITEM (obj);
+  Lisp_Gui_Item *g = XGUI_ITEM (obj);
   char buf[20];
 
   if (print_readably)
@@ -512,12 +565,62 @@ print_gui_item (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
   write_c_string (buf, printcharfun);
 }
 
+/* parse a glyph descriptor into a tree of gui items.
+
+   The gui_item slot of an image instance can be a single item or an
+   arbitrarily nested hierarchy of item lists. */
+
+static Lisp_Object parse_gui_item_tree_item (Lisp_Object entry)
+{
+  Lisp_Object ret = entry;
+  if (VECTORP (entry))
+    {
+      ret =  gui_parse_item_keywords_no_errors (entry);
+    }
+  else if (STRINGP (entry))
+    {
+      CHECK_STRING (entry);
+    }
+  else
+    signal_simple_error ("item must be a vector or a string", entry);
+
+  return ret;
+}
+
+Lisp_Object parse_gui_item_tree_children (Lisp_Object list)
+{
+  Lisp_Object rest, ret = Qnil;
+  CHECK_CONS (list);
+  /* recursively add items to the tree view */
+  LIST_LOOP (rest, list)
+    {
+      Lisp_Object sub;
+      if (CONSP (XCAR (rest)))
+       sub = parse_gui_item_tree_list (XCAR (rest));
+      else
+       sub = parse_gui_item_tree_item (XCAR (rest));
+
+      ret = Fcons (sub, ret);
+    }
+  /* make the order the same as the items we have parsed */
+  return Fnreverse (ret);
+}
+
+static Lisp_Object parse_gui_item_tree_list (Lisp_Object list)
+{
+  Lisp_Object ret;
+  CHECK_CONS (list);
+  /* first one can never be a list */
+  ret = parse_gui_item_tree_item (XCAR (list));
+  return Fcons (ret, parse_gui_item_tree_children (XCDR (list)));
+}
+
 DEFINE_LRECORD_IMPLEMENTATION ("gui-item", gui_item,
                               mark_gui_item, print_gui_item,
                               0, gui_item_equal,
                               gui_item_hash,
                               0,
-                              struct Lisp_Gui_Item);
+                              Lisp_Gui_Item);
 
 void
 syms_of_gui (void)