home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / s / stex2-18.zip / SeeTeX / Xtex / EzMenu.c < prev    next >
C/C++ Source or Header  |  1992-04-25  |  11KB  |  426 lines

  1. #if ( !defined(lint) && !defined(SABER) )
  2. static char Xrcsid[] = "$XConsortium: SimpleMenu.c,v 1.32 89/12/11 15:01:50 kit Exp $";
  3. #endif 
  4.  
  5. /*
  6.  * Copyright 1989 Massachusetts Institute of Technology
  7.  *
  8.  * Permission to use, copy, modify, distribute, and sell this software and its
  9.  * documentation for any purpose is hereby granted without fee, provided that
  10.  * the above copyright notice appear in all copies and that both that
  11.  * copyright notice and this permission notice appear in supporting
  12.  * documentation, and that the name of M.I.T. not be used in advertising or
  13.  * publicity pertaining to distribution of the software without specific,
  14.  * written prior permission.  M.I.T. makes no representations about the
  15.  * suitability of this software for any purpose.  It is provided "as is"
  16.  * without express or implied warranty.
  17.  *
  18.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  19.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  20.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  21.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  22.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  23.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  24.  */
  25.  
  26. #include <stdio.h>
  27. #include <X11/Xlib.h>
  28. #include <X11/Xos.h>  
  29. #include <X11/Intrinsic.h>
  30. #include <X11/IntrinsicP.h>
  31. #include <X11/StringDefs.h>
  32.  
  33. #include "EzMenuP.h"
  34. #include <X11/Xaw/SimpleMenu.h>
  35. #include <X11/Xaw/Sme.h>
  36. #include "EzME.h"
  37. #include <X11/Xaw/SmeBSB.h>
  38. #include <X11/Xaw/SmeLine.h>
  39.  
  40. #include <X11/Xaw/Cardinals.h>
  41.  
  42. #include <ctype.h>
  43.  
  44. #define offset(field) XtOffset(EzMenuWidget, ez_menu.field)
  45.  
  46. static XtResource resources[] = { 
  47.   {XtNmenu,  XtCMenu, XtRString, sizeof(String),
  48.      offset(menu), XtRString, NULL},
  49. };  
  50. #undef offset
  51.  
  52.  
  53. /*
  54.  * Semi Public function definitions. 
  55.  */
  56.  
  57. static void Initialize();
  58. static void Destroy();
  59. static void Realize();
  60. static Boolean SetValues();
  61.  
  62. #define superclass (&simpleMenuClassRec)
  63.     
  64. EzMenuClassRec ezMenuClassRec = {
  65.   {
  66.     /* superclass         */    (WidgetClass) superclass,
  67.     /* class_name         */    "EzMenu",
  68.     /* size               */    sizeof(EzMenuRec),
  69.     /* class_initialize   */    NULL,
  70.     /* class_part_initialize*/    NULL,
  71.     /* Class init'ed      */    FALSE,
  72.     /* initialize         */    Initialize,
  73.     /* initialize_hook    */    NULL,
  74.     /* realize            */    Realize,
  75.     /* actions            */    NULL,
  76.     /* num_actions        */    0,
  77.     /* resources          */    resources,
  78.     /* resource_count     */    XtNumber(resources),
  79.     /* xrm_class          */    NULLQUARK,
  80.     /* compress_motion    */    TRUE, 
  81.     /* compress_exposure  */    TRUE,
  82.     /* compress_enterleave*/     TRUE,
  83.     /* visible_interest   */    FALSE,
  84.     /* destroy            */    Destroy,
  85.     /* resize             */    XtInheritResize,
  86.     /* expose             */    XtInheritExpose,
  87.     /* set_values         */    SetValues,
  88.     /* set_values_hook    */    NULL,
  89.     /* set_values_almost  */    XtInheritSetValuesAlmost,  
  90.     /* get_values_hook    */    NULL,            
  91.     /* accept_focus       */    NULL,
  92.     /* intrinsics version */    XtVersion,
  93.     /* callback offsets   */    NULL,
  94.     /* tm_table          */    XtInheritTranslations,
  95.     /* query_geometry      */    XtInheritQueryGeometry,
  96.     /* display_accelerator*/    XtInheritDisplayAccelerator,
  97.     /* extension      */    NULL
  98.   },{
  99.     /* geometry_manager   */    XtInheritGeometryManager,
  100.     /* change_managed     */    XtInheritChangeManaged,
  101.     /* insert_child      */    XtInheritInsertChild,
  102.     /* delete_child      */    XtInheritDeleteChild,
  103.     /* extension      */    NULL
  104.   },{
  105.     /* Shell extension      */    NULL
  106.   },{
  107.     /* Override extension */    NULL
  108.   },{
  109.     /* Simple Menu extension*/  NULL
  110.   },{
  111.     /* Ez Menu extension*/  NULL
  112.   }
  113. };
  114.  
  115. WidgetClass ezMenuWidgetClass = (WidgetClass)&ezMenuClassRec;
  116.  
  117. /************************************************************
  118.  *
  119.  * Semi-Public Functions.
  120.  *
  121.  ************************************************************/
  122.  
  123. /*
  124.  * routines to process menus
  125.  */
  126.  
  127. #define QUOTE '\"'
  128. #define BACKSLASH '\\'
  129.  
  130. #define SKIPWHITE(cp) while (cp && *cp && isspace(*cp)) cp++
  131. #define FINDPAREN(cp) while (cp && *cp && *cp != '(') cp++
  132. #define FINDQUOTE(cp) while (cp && *cp && *cp != QUOTE) cp++
  133. #define KEY_LEN 32
  134. #define NAME_LEN 128
  135. #define LABEL_LEN 128
  136.  
  137. /*
  138.  * Parse a main level menu decl. and add all children to that parent
  139.  */
  140.  
  141. char *
  142. EzMenuParseString(from, to, maxlen)
  143. char *from;
  144. char *to;
  145. int maxlen;
  146. {
  147.   char *oldto = to;
  148.   SKIPWHITE(from);
  149.   if ( from && *from == QUOTE ) {
  150.     maxlen--;
  151.     from++;
  152.     while (*from && *from != QUOTE && maxlen > 1) {
  153.       if ( *from == BACKSLASH) {
  154.     from++;
  155.       }
  156.       *to++ = *from++;
  157.       maxlen--;
  158.     }
  159.     if ( *from == QUOTE ) {
  160.       from++;
  161.     }
  162.   }
  163.   *to = 0;
  164.   return(from);
  165. }  
  166.  
  167. char *
  168. EzMenuParseMenu(parent,menu,subMenuOk)
  169. Widget parent;
  170. char *menu;
  171. Bool subMenuOk;
  172. {
  173.   char *thisWidgetName[NAME_LEN];
  174.   char *thisWidgetLabel[LABEL_LEN];
  175.  
  176.   *thisWidgetName = 0;
  177.   *thisWidgetLabel = 0;
  178.   while(menu && *menu) {
  179.     SKIPWHITE(menu);
  180.  
  181.     if (!menu || *menu != '(') {
  182.       return( menu );
  183.     }
  184.     else {
  185.       menu++;
  186.     }
  187.  
  188.     SKIPWHITE(menu);
  189.  
  190.     if (isalpha(*menu)) {
  191.       char key[KEY_LEN+1];
  192.       char *p = key;
  193.       int keylen = 0;
  194.  
  195.       while(isalpha(*menu) && keylen < KEY_LEN) {
  196.     *p++ = *menu++;
  197.     keylen++;
  198.       }
  199.       *p = 0;
  200.  
  201.       if (strcmp(key, "action") == 0 ) {
  202.     char name[NAME_LEN];
  203.     Arg arglist[1];
  204.     Cardinal num_args = 0;
  205.  
  206.     menu = EzMenuParseString(menu, name, NAME_LEN);
  207.  
  208.     XtSetArg(arglist[num_args], XtNaction, name); num_args++;
  209.     XtSetValues(parent, arglist, num_args);
  210.       }
  211.       else if (strcmp(key, "blank") == 0 ) {
  212.     char name[NAME_LEN];
  213.     Widget entry;
  214.  
  215.     *name = 0;
  216.     menu = EzMenuParseString(menu, name, NAME_LEN);
  217.     if ( *name == 0 ) {
  218.       static int counter = 0;
  219.       sprintf(name, "blank%d", counter);
  220.     }
  221.     entry = XtCreateManagedWidget(name, smeObjectClass,
  222.                       parent, NULL, ZERO);
  223.       }
  224.       else if (strcmp(key, "line") == 0 ) {
  225.     char name[NAME_LEN];
  226.     Widget entry;
  227.  
  228.     *name = 0;
  229.     menu = EzMenuParseString(menu, name, NAME_LEN);
  230.     if ( *name == 0 ) {
  231.       static int counter = 0;
  232.       sprintf(name, "line%d", counter);
  233.     }
  234.     entry = XtCreateManagedWidget(name, smeLineObjectClass, parent,
  235.                       NULL, ZERO);
  236.       }
  237.       else if (strcmp(key, "item") == 0 || strcmp(key, "menu") == 0 ) {
  238.     char name[NAME_LEN];
  239.     char label[LABEL_LEN];
  240.     Widget entry;
  241.     Bool isMenu;
  242.     extern void MenuSelect();
  243.     Arg arglist[10];
  244.     Cardinal num_args = 0;
  245.  
  246.  
  247.     isMenu = (strcmp(key, "menu") == 0);
  248.     *name = 0;
  249.  
  250.     menu = EzMenuParseString(menu, label, LABEL_LEN);
  251.     menu = EzMenuParseString(menu, name, NAME_LEN);
  252.  
  253.     if ( *name == 0 ) {
  254.       static int counter = 0;
  255.       sprintf(name, "%s%d", key, counter);
  256.     }
  257.  
  258.     if ( *label == 0 ) {
  259.       strcpy(label, name);
  260.     }
  261.  
  262.     if ( isMenu ) {
  263.       char menu_name[NAME_LEN];
  264.       Widget menu_entry;
  265.  
  266.       sprintf(menu_name,"%s-menu", name);
  267.  
  268.       XtSetArg(arglist[num_args], XtNlabel, label); num_args++;
  269.  
  270.       menu_entry = XtCreatePopupShell(menu_name, ezMenuWidgetClass,
  271.                  parent, arglist, num_args);
  272.  
  273.       /* now, parse their menu entry. This is gross, but beats
  274.        scanning ahead to find the stupid balanced parens */
  275.       menu = EzMenuParseMenu(menu_entry, menu, True);
  276.  
  277.       num_args = 0;
  278.       XtSetArg(arglist[num_args], XtNlabel, label); num_args++;
  279.       XtSetArg(arglist[num_args], XtNmenu, menu_entry); num_args++;
  280.       entry = XtCreateManagedWidget(name, ezMEObjectClass, parent, 
  281.                     arglist, num_args);
  282.     }
  283.     else {
  284.       num_args = 0;
  285.       XtSetArg(arglist[num_args], XtNlabel, label); num_args++;
  286.       XtSetArg(arglist[num_args], XtNmenu, 0); num_args++;
  287.       entry = XtCreateManagedWidget(name, ezMEObjectClass, parent, 
  288.                     arglist, num_args);
  289.     }
  290.  
  291.     menu = EzMenuParseMenu(entry, menu, isMenu);
  292.       }
  293.  
  294.       SKIPWHITE(menu);
  295.       if (*menu != ')') {
  296.     char buffer[2048];
  297.     XtAppContext context = 
  298.       XtWidgetToApplicationContext( parent );
  299.  
  300.     sprintf(buffer, "unbalanced parens or bogus format: %s\n", menu);
  301.  
  302.     XtAppError(context, buffer);
  303.     exit(1);
  304.       }
  305.       menu++;
  306.     }
  307.   }
  308.   return(menu);
  309. }
  310.  
  311. /*      Function Name: Initialize
  312.  *      Description: Initializes the simple menu widget
  313.  *      Arguments: request - the widget requested by the argument list.
  314.  *                 new     - the new widget with both resource and non
  315.  *                           resource values.
  316.  *      Returns: none.
  317.  */
  318.  
  319. /* ARGSUSED */
  320. static void
  321. Initialize(request, new)
  322. Widget request, new;
  323. {
  324.   EzMenuWidget newez = (EzMenuWidget) new;
  325.   EzMenuWidget requestez = (EzMenuWidget) request;
  326.  
  327. #ifdef DEBUG
  328.   fprintf(stderr,"Initialize %s\n",
  329.       XtWidgetName(request);
  330. #endif
  331.  
  332.   /* just copy the string that will be used to initialize the menu */
  333.   
  334.   newez -> ez_menu.menu = 0;
  335.  
  336.   if (requestez -> ez_menu.menu ) {
  337.     int len = strlen(requestez -> ez_menu.menu);
  338.     newez -> ez_menu.menu = XtMalloc( len + 1 );
  339.     strcpy( newez -> ez_menu.menu, requestez -> ez_menu.menu);
  340.   }
  341.  
  342.   if ( newez -> ez_menu.menu ) {
  343.     EzMenuParseMenu( newez, newez -> ez_menu.menu, True );
  344.   }
  345. }
  346.  
  347. /*      Function Name: Realize
  348.  *      Description: Realizes the widget.
  349.  *      Arguments: w - the simple menu widget.
  350.  *                 mask - value mask for the window to create.
  351.  *                 attrs - attributes for the window to create.
  352.  *      Returns: none
  353.  */
  354.  
  355. static void
  356. Realize(w, mask, attrs)
  357. Widget w;
  358. XtValueMask * mask;
  359. XSetWindowAttributes * attrs;
  360. {
  361.   EzMenuWidget newez = (EzMenuWidget) w;
  362.   (*superclass->core_class.realize) (w, mask, attrs);
  363. }
  364.  
  365.  
  366. /*      Function Name: SetValues
  367.  *      Description: Relayout the menu when one of the resources is changed.
  368.  *      Arguments: current - current state of the widget.
  369.  *                 request - what was requested.
  370.  *                 new - what the widget will become.
  371.  *      Returns: none
  372.  */
  373.  
  374. /* ARGSUSED */
  375. static Boolean
  376. SetValues(current, request, new)
  377.      Widget current, request, new;
  378. {
  379.   EzMenuWidget ez_old = (EzMenuWidget) current;
  380.   EzMenuWidget ez_want = (EzMenuWidget) request;
  381.   EzMenuWidget ez_new = (EzMenuWidget) new;
  382.   Boolean ret_val = FALSE;
  383.   if (
  384.  
  385.       /* no old menu, want one now */
  386.  
  387.       ( !ez_old -> ez_menu.menu && ez_want -> ez_menu.menu )
  388.       ||
  389.  
  390.       /* old menu, new one is different */
  391.  
  392.       (ez_want -> ez_menu.menu
  393.        && ez_old -> ez_menu.menu
  394.        && ( strcmp( ez_old -> ez_menu.menu,
  395.            ez_want -> ez_menu.menu) != 0 ))
  396.       ) {
  397.  
  398.     int len = strlen(ez_old -> ez_menu.menu);
  399.  
  400.     ez_new -> ez_menu.menu = XtMalloc( len + 1 );
  401.     strcpy( ez_new -> ez_menu.menu,
  402.        ez_old -> ez_menu.menu);
  403.     
  404.     if ( XtIsRealized((Widget) ez_old) ) {
  405.       SimpleMenuWidget smw = (SimpleMenuWidget) ez_old;
  406.       SmeObject *entry;
  407.       
  408.       ForAllChildren(smw, entry) {
  409.     XtDestroyWidget((Widget) entry);
  410.       }
  411.  
  412.       EzMenuParseMenu(ez_new, ez_new -> ez_menu.menu, True);
  413.       ret_val = TRUE;
  414.     }
  415.   }
  416.   return(ret_val);
  417. }
  418.  
  419. static void
  420. Destroy(who)
  421. EzMenuWidget who;
  422. {
  423.   XtFree( who -> ez_menu.menu );
  424. }
  425.  
  426.