home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / a2.0bemacs-src.lha / Emacs-19.25 / src / amiga_xmenu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-29  |  23.6 KB  |  957 lines

  1. /* Additional Amiga Menu Bar stuff, should be moved to amiga_menu 
  2.    Copyright (C) 1986, 1988, 1993, 1994 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU Emacs.
  5.  
  6. GNU Emacs is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. GNU Emacs is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Emacs; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include <exec/types.h>
  21. #include <libraries/gadtools.h>
  22. #include <intuition/intuition.h>
  23. #include <proto/exec.h>
  24. #include <proto/dos.h>
  25. #include <proto/gadtools.h>
  26. #include <proto/intuition.h>
  27. #include "config.h"
  28. #include "lisp.h"
  29. #include "frame.h"
  30. #include "amiga.h"
  31.  
  32. #ifdef USE_PROTOS
  33. #include "protos.h"
  34. #endif
  35.  
  36. extern Lisp_Object Qmenu_enable;
  37. #if 0
  38. extern Lisp_Object Qmenu_bar;
  39. #endif
  40.  
  41. /* This holds a Lisp vector that holds the results of decoding
  42.    the keymaps or alist-of-alists that specify a menu.
  43.  
  44.    It describes the panes and items within the panes.
  45.  
  46.    Each pane is described by 3 elements in the vector:
  47.    t, the pane name, the pane's prefix key.
  48.    Then follow the pane's items, with 4 elements per item:
  49.    the item string, the enable flag, the item's value,
  50.    and the equivalent keyboard key's description string.
  51.  
  52.    In some cases, multiple levels of menus may be described.
  53.    A single vector slot containing nil indicates the start of a submenu.
  54.    A single vector slot containing lambda indicates the end of a submenu.
  55.    The submenu follows a menu item which is the way to reach the submenu.
  56.  
  57.    A single vector slot containing quote indicates that the
  58.    following items should appear on the right of a dialog box.
  59.  
  60.    Using a Lisp vector to hold this information while we decode it
  61.    takes care of protecting all the data from GC.  */
  62.  
  63. #define MENU_ITEMS_PANE_NAME 1
  64. #define MENU_ITEMS_PANE_PREFIX 2
  65. #define MENU_ITEMS_PANE_LENGTH 3
  66.  
  67. #define MENU_ITEMS_ITEM_NAME 0
  68. #define MENU_ITEMS_ITEM_ENABLE 1
  69. #define MENU_ITEMS_ITEM_VALUE 2
  70. #define MENU_ITEMS_ITEM_EQUIV_KEY 3
  71. #define MENU_ITEMS_ITEM_LENGTH 4
  72.  
  73. #ifdef MULTI_FRAME
  74. you lose! /* each frame needs one of these or it must be copied */
  75. #else
  76. static Lisp_Object menu_items;
  77. #endif
  78.  
  79. /* Number of slots currently allocated in menu_items.  */
  80. static int menu_items_allocated;
  81.  
  82. /* This is (<number of menus> + <number of items> + <number of subitems>) */
  83. static int menu_items_num_items;
  84.  
  85. /* This is the index in menu_items of the first empty slot.  */
  86. static int menu_items_used;
  87.  
  88. /* The number of panes currently recorded in menu_items,
  89.    excluding those within submenus.  */
  90. static int menu_items_n_panes;
  91.  
  92. /* Current depth within submenus.  */
  93. static int menu_items_submenu_depth;
  94.  
  95. /* sum of length of strings used in the current menu */
  96. static int menu_items_string_len;
  97.  
  98. /* Initialize the menu_items structure if we haven't already done so.
  99.    Also mark it as currently empty.  */
  100.  
  101. static void
  102. init_menu_items ()
  103. {
  104.   if (NILP (menu_items))
  105.     {
  106.       menu_items_allocated = 60;
  107.       menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil);
  108.     }
  109.  
  110.   menu_items_used = 0;
  111.   menu_items_n_panes = 0;
  112.   menu_items_submenu_depth = 0;
  113.   menu_items_string_len = 0;
  114.   menu_items_num_items = 0;
  115. }
  116.  
  117. /* Call at the end of generating the data in menu_items.
  118.    This fills in the number of items in the last pane.  */
  119.  
  120. static void
  121. finish_menu_items ()
  122. {
  123. }
  124.  
  125. /* Call when finished using the data for the current menu
  126.    in menu_items.  */
  127.  
  128. static void
  129. discard_menu_items ()
  130. {
  131.   /* Free the structure if it is especially large.
  132.      Otherwise, hold on to it, to save time.  */
  133.   if (menu_items_allocated > 200)
  134.     {
  135.       menu_items = Qnil;
  136.       menu_items_allocated = 0;
  137.     }
  138. }
  139.  
  140. /* Make the menu_items vector twice as large.  */
  141.  
  142. static void
  143. grow_menu_items ()
  144. {
  145.   Lisp_Object old;
  146.   int old_size = menu_items_allocated;
  147.   old = menu_items;
  148.  
  149.   menu_items_allocated *= 2;
  150.   menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil);
  151.   bcopy (XVECTOR (old)->contents, XVECTOR (menu_items)->contents,
  152.      old_size * sizeof (Lisp_Object));
  153. }
  154.  
  155. /* Begin a submenu.  */
  156.  
  157. static void
  158. push_submenu_start ()
  159. {
  160.   if (menu_items_used + 1 > menu_items_allocated)
  161.     grow_menu_items ();
  162.  
  163.   XVECTOR (menu_items)->contents[menu_items_used++] = Qnil;
  164.   menu_items_submenu_depth++;
  165. }
  166.  
  167. /* End a submenu.  */
  168.  
  169. static void
  170. push_submenu_end ()
  171. {
  172.   if (menu_items_used + 1 > menu_items_allocated)
  173.     grow_menu_items ();
  174.  
  175.   XVECTOR (menu_items)->contents[menu_items_used++] = Qlambda;
  176.   menu_items_submenu_depth--;
  177. }
  178.  
  179. /* Indicate boundary between left and right.  */
  180.  
  181. static void
  182. push_left_right_boundary ()
  183. {
  184.   if (menu_items_used + 1 > menu_items_allocated)
  185.     grow_menu_items ();
  186.  
  187.   XVECTOR (menu_items)->contents[menu_items_used++] = Qquote;
  188. }
  189.  
  190. /* Start a new menu pane in menu_items..
  191.    NAME is the pane name.  PREFIX_VEC is a prefix key for this pane.
  192.    NAME_LEN is the length of the name in characters.
  193.  */
  194.  
  195. static void
  196. push_menu_pane (Lisp_Object name, Lisp_Object prefix_vec, int name_len)
  197. {
  198.   if (menu_items_used + MENU_ITEMS_PANE_LENGTH > menu_items_allocated)
  199.     grow_menu_items ();
  200.  
  201.   if (menu_items_submenu_depth == 0)
  202.     menu_items_n_panes++;
  203.   XVECTOR (menu_items)->contents[menu_items_used++] = Qt;
  204.   XVECTOR (menu_items)->contents[menu_items_used++] = name;
  205.   XVECTOR (menu_items)->contents[menu_items_used++] = prefix_vec;
  206.   menu_items_string_len += name_len + 1;
  207.   menu_items_num_items++;
  208. }
  209.  
  210. /* Push one menu item into the current pane.
  211.    NAME is the string to display.  ENABLE if non-nil means
  212.    this item can be selected.  KEY is the key generated by
  213.    choosing this item.  EQUIV is the textual description
  214.    of the keyboard equivalent for this item (or nil if none).
  215.    NAME_LEN is the length of the name in characters.
  216.  */
  217.  
  218. static void
  219. push_menu_item (Lisp_Object name, Lisp_Object enable,
  220.         Lisp_Object key, Lisp_Object equiv,
  221.         int name_len)
  222. {
  223.   if (menu_items_used + MENU_ITEMS_ITEM_LENGTH > menu_items_allocated)
  224.     grow_menu_items ();
  225.  
  226.   XVECTOR (menu_items)->contents[menu_items_used++] = name;
  227.   XVECTOR (menu_items)->contents[menu_items_used++] = enable;
  228.   XVECTOR (menu_items)->contents[menu_items_used++] = key;
  229.   XVECTOR (menu_items)->contents[menu_items_used++] = equiv;
  230.   menu_items_string_len += name_len + 1;
  231.   menu_items_num_items++;
  232. }
  233.  
  234. /* Figure out the current keyboard equivalent of a menu item ITEM1.
  235.    The item string for menu display should be ITEM_STRING.
  236.    Store the equivalent keyboard key sequence's
  237.    textual description into *DESCRIP_PTR.
  238.    Also cache them in the item itself.
  239.    Return the real definition to execute.  */
  240.  
  241. static Lisp_Object
  242. menu_item_equiv_key (item_string, item1, descrip_ptr)
  243.      Lisp_Object item_string;
  244.      Lisp_Object item1;
  245.      Lisp_Object *descrip_ptr;
  246. {
  247.   /* This is the real definition--the function to run.  */
  248.   Lisp_Object def;
  249.   /* This is the sublist that records cached equiv key data
  250.      so we can save time.  */
  251.   Lisp_Object cachelist;
  252.   /* These are the saved equivalent keyboard key sequence
  253.      and its key-description.  */
  254.   Lisp_Object savedkey, descrip;
  255.   Lisp_Object def1;
  256.   int changed = 0;
  257.  
  258.   /* If a help string follows the item string, skip it.  */
  259.   if (CONSP (XCONS (item1)->cdr)
  260.       && STRINGP (XCONS (XCONS (item1)->cdr)->car))
  261.     item1 = XCONS (item1)->cdr;
  262.  
  263.   def = Fcdr (item1);
  264.  
  265.   /* Get out the saved equivalent-keyboard-key info.  */
  266.   cachelist = savedkey = descrip = Qnil;
  267.   if (CONSP (def) && CONSP (XCONS (def)->car)
  268.       && (NILP (XCONS (XCONS (def)->car)->car)
  269.       || VECTORP (XCONS (XCONS (def)->car)->car)))
  270.     {
  271.       cachelist = XCONS (def)->car;
  272.       def = XCONS (def)->cdr;
  273.       savedkey = XCONS (cachelist)->car;
  274.       descrip = XCONS (cachelist)->cdr;
  275.     }
  276.  
  277.   /* Is it still valid?  */
  278.   def1 = Qnil;
  279.   if (!NILP (savedkey))
  280.     def1 = Fkey_binding (savedkey, Qnil);
  281.   /* If not, update it.  */
  282.   if (! EQ (def1, def)
  283.       /* If something had no key binding before, don't recheck it--
  284.      doing that takes too much time and makes menus too slow.  */
  285.       && !(!NILP (cachelist) && NILP (savedkey)))
  286.     {
  287.       changed = 1;
  288.       descrip = Qnil;
  289.       savedkey = Fwhere_is_internal (def, Qnil, Qt, Qnil);
  290.       /* If the command is an alias for another
  291.      (such as easymenu.el and lmenu.el set it up),
  292.      see if the original command name has equivalent keys.  */
  293.       if (SYMBOLP (def) && SYMBOLP (XSYMBOL (def)->function))
  294.     savedkey = Fwhere_is_internal (XSYMBOL (def)->function,
  295.                        Qnil, Qt, Qnil);
  296.  
  297.       if (VECTORP (savedkey)
  298.       && EQ (XVECTOR (savedkey)->contents[0], Qmenu_bar))
  299.     savedkey = Qnil;
  300.       if (!NILP (savedkey))
  301.     {
  302.       descrip = Fkey_description (savedkey);
  303.       descrip = concat2 (make_string ("  (", 3), descrip);
  304.       descrip = concat2 (descrip, make_string (")", 1));
  305.     }
  306.     }
  307.  
  308.   /* Cache the data we just got in a sublist of the menu binding.  */
  309.   if (NILP (cachelist))
  310.     XCONS (item1)->cdr = Fcons (Fcons (savedkey, descrip), def);
  311.   else if (changed)
  312.     {
  313.       XCONS (cachelist)->car = savedkey;
  314.       XCONS (cachelist)->cdr = descrip;
  315.     }
  316.  
  317.   *descrip_ptr = descrip;
  318.   return def;
  319. }
  320.  
  321. /* This is used as the handler when calling internal_condition_case_1.  */
  322.  
  323. static Lisp_Object
  324. menu_item_enabled_p_1 (arg)
  325.      Lisp_Object arg;
  326. {
  327.   return Qnil;
  328. }
  329.  
  330. /* Return non-nil if the command DEF is enabled when used as a menu item.
  331.    This is based on looking for a menu-enable property.
  332.    If NOTREAL is set, don't bother really computing this.  */
  333.  
  334. static Lisp_Object
  335. menu_item_enabled_p (def, notreal)
  336.      Lisp_Object def;
  337. {
  338.   Lisp_Object enabled, tem;
  339.  
  340.   enabled = Qt;
  341.   if (notreal)
  342.     return enabled;
  343.   if (XTYPE (def) == Lisp_Symbol)
  344.     {
  345.       /* No property, or nil, means enable.
  346.      Otherwise, enable if value is not nil.  */
  347.       tem = Fget (def, Qmenu_enable);
  348.       if (!NILP (tem))
  349.     /* (condition-case nil (eval tem)
  350.        (error nil))  */
  351.     enabled = internal_condition_case_1 (Feval, tem, Qerror,
  352.                          menu_item_enabled_p_1);
  353.     }
  354.   return enabled;
  355. }
  356.  
  357.  
  358. void make_amiga_menu_1(FRAME_PTR f,int doprint);
  359. void make_menu_items(FRAME_PTR f, Lisp_Object menu);
  360.  
  361. void
  362. make_amiga_menu(FRAME_PTR f, Lisp_Object menu)
  363. {
  364.     make_menu_items(f, menu);
  365.     if(menu_items_used)
  366.     {
  367.     make_amiga_menu_1(f, 0);
  368.     }
  369. }
  370.  
  371. extern struct Library *GadToolsBase;
  372.  
  373. void
  374. print_amiga_menu(FRAME_PTR f)
  375. {
  376.     make_amiga_menu_1(f,1);
  377. }
  378.  
  379. void
  380. make_amiga_menu_1(FRAME_PTR f, int doprint)
  381. {
  382.     struct NewMenu *menudata, *mkm;
  383.     char *strdata;
  384.     int i, t, first_pane = 0, submenu_depth = 0;
  385.     int level = 0;
  386.  
  387.     if(!doprint)
  388.     {
  389.     check_intuition();
  390.     suspend_menus(f);
  391.  
  392.     if (EMACS_MENU(f)) Famiga_delete_menus(f);
  393.         /* Now create menu structure */
  394.     menudata = (struct NewMenu *)alloca(sizeof(struct NewMenu) * (menu_items_num_items + 1));
  395.     EMACS_MENU_STRINGS(f) = strdata = (char *)xmalloc(menu_items_string_len);
  396.     mkm = menudata;
  397.     }
  398.  
  399.   /* Loop over all panes and items, print/creating menu structure.  */
  400.   i = 0;
  401.   while (i < menu_items_used)
  402.     {
  403.     /* CHFIXME */
  404.     if(mkm >= menudata+menu_items_num_items + 1)
  405.         abort();
  406.     
  407.       if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
  408.     {
  409.         submenu_depth++;
  410.         first_pane = 1;
  411.         i++;
  412.     }
  413.       else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
  414.     {
  415.         --submenu_depth;
  416.       first_pane = 0;
  417.       i++;
  418.     }
  419.       else if (EQ (XVECTOR (menu_items)->contents[i], Qt)
  420.            && submenu_depth != 0)
  421.     i += MENU_ITEMS_PANE_LENGTH;
  422.       /* Ignore a nil in the item list.
  423.      It\'s meaningful only for dialog boxes.  */
  424.       else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
  425.     i += 1;
  426.       else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
  427.     {
  428.       /* Create a new pane.  */
  429.       Lisp_Object pane_name, prefix;
  430.       char *pane_string;
  431.       int len;
  432.       
  433.       pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
  434.       prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
  435.       pane_string = (NILP (pane_name)
  436.              ? "" : (char *) XSTRING (pane_name)->data);
  437.       /* If there is just one top-level pane, put all its items directly
  438.          under the top-level menu.  */
  439.       if (menu_items_n_panes == 1)
  440.         pane_string = "";
  441.  
  442.       /* If the pane has a meaningful name,
  443.          make the pane a top-level menu item
  444.          with its items as a submenu beneath it.  */
  445.       len = strlen(pane_string);
  446.       if (len)
  447.       {
  448.           if(doprint)
  449.           {
  450.           for(t = 0; t < submenu_depth; t++)
  451.             fprintf(stderr,"    ");
  452.         
  453.           fprintf(stderr,"pane = \"%s\"\n", pane_string);
  454.           }
  455.           else
  456.           {
  457.           mkm->nm_Type = NM_TITLE;
  458.           strncpy(strdata, pane_string, len+1);
  459.           mkm->nm_Label = strdata;
  460.           strdata += len + 1;
  461.           mkm->nm_CommKey = 0;
  462.           mkm->nm_Flags = 0;
  463.           mkm->nm_MutualExclude = 0;
  464.           mkm++;
  465.           }
  466. #if 0
  467.           if (keymaps && !NILP (prefix))
  468.         wv->name++;
  469. #endif
  470. #if 0
  471.           wv->value = 0;
  472.           wv->enabled = 1;
  473. #endif
  474.         }
  475.       else if (first_pane)
  476.         {
  477.         }
  478.       first_pane = 0;
  479.       i += MENU_ITEMS_PANE_LENGTH;
  480.     }
  481.       else
  482.     {
  483.       /* Create a new item within current pane.  */
  484.       Lisp_Object item_name, enable, descrip, key;
  485.       char *key_string;
  486.       int len;
  487.       
  488.       item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
  489.       enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
  490.       /* The key generated by choosing this item */
  491.       key
  492.         = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
  493.       descrip
  494.         = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
  495.  
  496.       if(NILP(key))
  497.           key_string = "<nokey>";
  498.       else if(XTYPE(key) == Lisp_String)
  499.           key_string = (char *) XSTRING (key)->data;
  500.       else if(XTYPE(key) == Lisp_Symbol)
  501.           key_string = (char *) XSYMBOL (key)->name->data;
  502.       else
  503.           key_string = "<unknown type>";
  504.           
  505.       if(doprint)
  506.       {
  507.           for(t = 0; t < submenu_depth+1; t++)
  508.           fprintf(stderr,"    ");
  509.       
  510.  
  511.           fprintf(stderr,"name = \"%s\", key = [%s] %s\n",
  512.               (char *) XSTRING (item_name)->data,
  513.               key_string,
  514.           (NILP(enable)) ? "<disabled>" : "<enabled>"
  515.               );
  516.       }
  517.       else
  518.       {
  519.           len = XSTRING (item_name)->size;
  520.           if(submenu_depth == 0)
  521.           {
  522.           mkm->nm_Type = NM_ITEM;
  523.           }
  524.           else if(submenu_depth == 1)
  525.           {
  526.           mkm->nm_Type = NM_SUB;
  527.           }
  528.           else
  529.           abort();
  530.           
  531.           strncpy(strdata, XSTRING (item_name)->data, len+1);
  532.           mkm->nm_Label = strdata;
  533.           strdata += len + 1;
  534.           mkm->nm_CommKey = 0;
  535.           mkm->nm_Flags = 0;
  536.           mkm->nm_MutualExclude = 0;
  537.           if(NILP(enable))
  538.           mkm->nm_Flags |= NM_ITEMDISABLED;
  539.           mkm++;
  540.       }
  541. #if 0
  542.       wv->value = 0;
  543.       wv->call_data = (void *) &XVECTOR (menu_items)->contents[i];
  544. #endif
  545.  
  546.       i += MENU_ITEMS_ITEM_LENGTH;
  547.     }
  548.     }
  549.     mkm->nm_Type = NM_END;
  550.     mkm->nm_Label = 0;
  551.     mkm->nm_CommKey = 0;
  552.     mkm->nm_Flags = 0;
  553.     mkm->nm_MutualExclude = 0;
  554.     if (!(EMACS_MENU(f) = CreateMenus(menudata, TAG_END)))
  555.     {
  556.     free(EMACS_MENU_STRINGS(f));
  557.     EMACS_MENU_STRINGS(f) = 0;
  558. #if 0
  559.     error("Menu couldn't be created"); /* CHFIXME: how to do it for this kind of function? */
  560. #else
  561.     fprintf(stderr,"Menu couldn't be created");
  562. #endif
  563.     
  564.     }
  565.     if (!resume_menus(f))
  566. #if 0
  567.     error("Menu couldn't be layed out");
  568. #else
  569.     fprintf(stderr, "Menu couldn't be layed out");
  570. #endif
  571. }
  572.  
  573. void
  574. make_menu_items(FRAME_PTR f, Lisp_Object menu)
  575. {
  576.   Lisp_Object Result;
  577.   int i;
  578.  
  579.   init_menu_items(); /* CHFIXME */
  580.  
  581.   for (i = 0; i < XVECTOR (menu)->size;i += 3)
  582.     {
  583.       Lisp_Object string;
  584.       Lisp_Object Key, enable, descrip;
  585.       Lisp_Object binding;
  586.  
  587.       Key = XVECTOR (menu)->contents[i];
  588.       string = XVECTOR (menu)->contents[i + 1];
  589.       binding = XVECTOR (menu)->contents[i + 2];
  590.       if(NILP(string))
  591.     break;
  592.  
  593.       make_menu_items_1(Key, string, binding);
  594.     }
  595. }
  596.  
  597. /* CHFIXME */
  598. #define Check(obj, type) if(XTYPE(obj) != type)\
  599. {\
  600.  fprintf(stderr,"make_menu_items_1: Unknown structure (line %d, type %d)\n", __LINE__,XTYPE(obj)); \
  601.  break;\
  602. }
  603.  
  604. Lisp_Object
  605. make_menu_items_1(Lisp_Object prefix, Lisp_Object pane_name, Lisp_Object binding)
  606. {
  607.   Lisp_Object Result;
  608.   int i;
  609.  
  610.   Lisp_Object pending_maps;
  611.   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
  612.   Lisp_Object litems, litem;
  613.   Lisp_Object lsubitems, lsubitem;
  614.   struct Lisp_Cons *item;
  615.   struct Lisp_Cons *subitem;
  616.  
  617.   pending_maps = Qnil;
  618.  
  619.   do
  620.   {
  621.       Check(prefix, Lisp_Symbol);
  622.       Check(pane_name, Lisp_String);
  623.       push_menu_pane (pane_name, prefix, XSTRING(pane_name)->size);
  624.  
  625.       Check(binding, Lisp_Cons);
  626.       binding = XCONS(binding)->car;
  627.       if(EQ(XCONS(binding)->car, Qkeymap))
  628.     {
  629.       for(litems = XCONS(binding)->cdr; XTYPE(litems) == Lisp_Cons; litems = XCONS(litems)->cdr)
  630.         {
  631.           litem = XCONS(litems)->car;
  632.           if(XTYPE(litem) == Lisp_String)
  633.         {
  634.           /*
  635.              ((keymap 
  636.                  "Select Buffer" 
  637.                  ("*scratch*" "*scratch*      " (nil) . menu-bar-select-buffer) 
  638.                  (list-buffers "List All Buffers" . list-buffers)))
  639.              ((keymap 
  640.                  (open-file "Open File..." . find-file) 
  641.                  (dired "Open Directory..." . dired) 
  642.                  "File"))
  643.              */
  644. #if 0
  645.           /* CHFIXME: ignore this name. redundant? */
  646.           fprintf(stderr,"\tmenu = %s\n",
  647.               (char *) XSTRING (litem)->data);
  648. #endif
  649.         }
  650.           else
  651.         {
  652.           Lisp_Object Def;
  653.           /* These are the saved equivalent keyboard key sequence
  654.              and its key-description.  */
  655.           Lisp_Object descrip;
  656.           Lisp_Object tem, enabled;
  657.           Lisp_Object prefix,item_string;
  658.  
  659.           Check(litem, Lisp_Cons);
  660.           item = XCONS(litem);
  661.           prefix = item->car;
  662. #if 0 /* test Buffers menu (strings) */
  663.           Check(prefix, Lisp_Symbol); /* CHFIXME */
  664.           if(XTYPE(prefix) == Lisp_String)
  665.           {
  666.               break; /* CHFIXME */
  667.           }
  668.           else if(XTYPE(prefix) == Lisp_Symbol)
  669.             ;
  670.           else
  671.             Check(prefix, Lisp_Symbol);
  672. #endif
  673.           Check(item->cdr, Lisp_Cons);
  674.           item = XCONS(item->cdr);
  675.           item_string = item->car;
  676.           Check(item_string, Lisp_String);
  677.           Def = item->cdr;
  678.           /* CHFIXME: Def may be (lambda ....) */
  679. #if 0
  680.           Check(Def, Lisp_Symbol);
  681. #endif
  682. #if 0
  683.           def = menu_item_equiv_key (item_string, item1, &descrip);
  684. #endif
  685. #if 0 /* currently not needed, all we have is protected */
  686.           /* GCPRO because we will call eval.
  687.              Protecting KEYMAP preserves everything we use;
  688.              aside from that, must protect whatever might be
  689.              a string.  Since there's no GCPRO5, we refetch
  690.              item_string instead of protecting it.  */
  691.           GCPRO4 (keymap, pending_maps, def, descrip);
  692. #endif
  693. #if 0
  694.           enabled = menu_item_enabled_p (def, notreal);
  695. #endif
  696. #if 0
  697.           UNGCPRO;
  698. #endif
  699.           push_menu_item(item_string, 
  700.                  /* enabled */ Qt, 
  701.                  prefix,
  702.                  /* descrip */ Qnil,
  703.                  XSTRING(item_string)->size);
  704.  
  705.           if(XTYPE(Def) == Lisp_Symbol)
  706.             lsubitems = XSYMBOL(Def)->value;
  707.           else
  708.             lsubitems = Qnil;
  709.           if((XTYPE(lsubitems) == Lisp_Cons) 
  710.              && EQ(XCONS(lsubitems)->car, Qkeymap))
  711.           {
  712.               push_submenu_start ();
  713.  
  714.               for(lsubitems = XCONS(lsubitems)->cdr; 
  715.               XTYPE(lsubitems) == Lisp_Cons;
  716.               lsubitems = XCONS(lsubitems)->cdr)
  717.             {
  718.               Check(lsubitems, Lisp_Cons);
  719.               lsubitem = XCONS(lsubitems)->car;
  720.  
  721.               if(XTYPE(lsubitem) == Lisp_String)
  722.                 {
  723.                   /* ignore this name */
  724.                 }
  725.               else
  726.                 {
  727.                   Check(lsubitem, Lisp_Cons);
  728.                   subitem = XCONS(lsubitem);
  729.                   prefix = subitem->car;
  730.  
  731.                   Check(prefix, Lisp_Symbol); /* CHFIXME */
  732.  
  733.                   Check(subitem->cdr, Lisp_Cons);
  734.                   subitem = XCONS(subitem->cdr);
  735.                   item_string = subitem->car;
  736.                   Check(item_string, Lisp_String);
  737.                   Def = subitem->cdr;
  738.  
  739.                   push_menu_item(item_string, 
  740.                          /* enabled */ Qt, 
  741.                          prefix,
  742.                          /* descrip */ Qnil,
  743.                          XSTRING(item_string)->size);
  744.               }
  745.               }
  746.               push_submenu_end ();
  747.           }
  748.           }
  749.       }
  750.       }
  751.       else
  752.       {
  753.       fprintf(stderr,"make_menu_items_1: Unknown structure\n");
  754.       }
  755.   } while(0);
  756. }
  757.  
  758. /*
  759.  * Map actual menu selection to Lisp Symbol
  760.  *
  761.  * (Notes:
  762.  *   prefixes must be an array of 3 elements,
  763.  *   given numbers start with 0
  764.  *   sub_item = NOSUB means: no subitem)
  765.  */
  766.  
  767. int
  768. map_menu_selection(int menu_num, int item_num, int subitem_num, Lisp_Object *prefixes)
  769. {
  770.   int i;
  771.   int act_menu_num = -1; 
  772.   int act_item_num = -1;
  773.   int act_subitem_num = -1;
  774.   int submenu_depth = 0;
  775.   Lisp_Object prefix;
  776.  
  777.  
  778.   prefixes[0] = Qnil;
  779.   prefixes[1] = Qnil;
  780.   prefixes[2] = Qnil;
  781.  
  782.   prefix = Qnil;
  783.   i = 0;
  784.   while (i < menu_items_used)
  785.     {
  786.       Lisp_Object entry;
  787.  
  788.  
  789.       if (EQ (XVECTOR (menu_items)->contents[i], Qt))
  790.     {
  791.       act_menu_num++;
  792.       if(act_menu_num == menu_num)
  793.         {
  794.           prefixes[0] = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
  795.         }
  796.       else if(act_menu_num >= menu_num)
  797.         {
  798.           break; /* not found */
  799.         }
  800.       act_item_num = -1;
  801.       act_subitem_num = -1;
  802.  
  803.       i += MENU_ITEMS_PANE_LENGTH;
  804.     }
  805.       else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
  806.     i += 1;
  807.       else if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
  808.     {
  809.       submenu_depth ++;
  810.       if(submenu_depth > 1)
  811.         abort();
  812.       i += 1;
  813.     }
  814.       else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
  815.     {
  816.       submenu_depth --;
  817.       if(submenu_depth < 0)
  818.         abort();
  819.       i += 1;
  820.     }
  821.       else
  822.     {
  823.       if(submenu_depth == 0)
  824.       {
  825.           act_item_num ++;
  826.           act_subitem_num = -1;
  827.       }
  828.       else if(submenu_depth == 1)
  829.         act_subitem_num ++;
  830.       else
  831.           abort();
  832.       
  833.       if(act_menu_num < 0)
  834.           abort();
  835.       
  836.       prefixes[submenu_depth+1] = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
  837.  
  838.       if((act_menu_num == menu_num) && 
  839.          (act_item_num == item_num) &&
  840.          ((subitem_num == NOSUB) || (act_subitem_num == subitem_num)))
  841.         {
  842.         if(subitem_num == NOSUB)
  843.             prefixes[2] = Qnil;
  844.           return 1;
  845.         }
  846.       i += MENU_ITEMS_ITEM_LENGTH;
  847.     }
  848.     }
  849.  
  850.   return 0;
  851. }
  852.  
  853. #if 0
  854. extern Lisp_Object Qexternal_debugging_output;
  855. void
  856. print_menu_items_vector(Lisp_Object items, int level)
  857. {
  858.     int i;
  859.     int submenu_depth = 0;
  860.  
  861. #if 0
  862.     if(level)
  863.     {
  864.     for(i = 0; i < level; i++)
  865.         fprintf(stderr,"    ");
  866.     }
  867. #endif
  868.     for (i = 0; i < XVECTOR (items)->size;i += 3)
  869.     {
  870.       Lisp_Object string;
  871.       Lisp_Object key, enable, descrip;
  872.       Lisp_Object binding;
  873.  
  874.       string = XVECTOR (items)->contents[i + 1];
  875.       binding = XVECTOR (items)->contents[i + 2];
  876.       if(NILP(string))
  877.     break;
  878.  
  879.       fprintf(stderr,"\tname = %s\n",
  880.           (char *) XSTRING (string)->data);
  881.       fprintf(stderr,"binding type: %d\n", XTYPE(binding));
  882.       Fprin1(binding, Qexternal_debugging_output);
  883.     }
  884. }
  885. #endif
  886.  
  887. /* from xmenu.c */
  888.  
  889. void
  890. set_frame_menubar (FRAME_PTR f, int first_time)
  891. {
  892.   int id = (int) f;
  893.   Lisp_Object tail, items;
  894.   int i;
  895.  
  896. #if 0 /* CHFIXME: needed ? */
  897.   BLOCK_INPUT;
  898. #endif
  899. #if 0
  900.   fprintf(stderr,"set_frame_menubar\n");
  901. #endif
  902.   if (NILP (items = FRAME_MENU_BAR_ITEMS (f)))
  903.     items = FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
  904.  
  905. #if 0
  906.     make_menu_items(f, items);
  907.     print_amiga_menu(f);
  908. #else
  909.     make_amiga_menu(f, items);
  910. #endif
  911.   
  912. #if 0
  913.   if (menubar_widget)
  914.     lw_modify_all_widgets (id, first_wv, False);
  915.   else
  916.     {
  917.       menubar_widget = lw_create_widget ("menubar", "menubar", 
  918.                      id, first_wv, 
  919.                      f->display.x->column_widget, 
  920.                      0, 0,
  921.                      0, 0);
  922.       f->display.x->menubar_widget = menubar_widget;
  923.       XtVaSetValues (menubar_widget,
  924.              XtNshowGrip, 0,
  925.              XtNresizeToPreferred, 1,
  926.              XtNallowResize, 1,
  927.              0);
  928.     }
  929.   
  930.   free_menubar_widget_value_tree (first_wv);
  931.  
  932.   /* Don't update the menubar the first time it is created via x_window.  */
  933.   if (!first_time)
  934.     update_frame_menubar (f);
  935. #endif
  936. #if 0 /* CHFIXME: needed ? */
  937.   UNBLOCK_INPUT;
  938. #endif
  939. }
  940.  
  941. /* CHFIXME */
  942. Lisp_Object 
  943. map_event_to_object (struct input_event *event, FRAME_PTR f)
  944. {
  945.   fprintf(stderr, "map_event_to_object () called !\n");
  946.  
  947.   return Qnil;
  948. }
  949.  
  950.  
  951. void
  952. syms_of_amiga_xmenu (void)
  953. {
  954.   staticpro (&menu_items);
  955.   menu_items = Qnil;
  956. }
  957.