home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / UNIX / ARCHIE / CLIENTS / XARCHIE2.TAR / EzMenu / EzMenu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-02  |  11.6 KB  |  465 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 256
  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. #ifdef OLD
  148.   char *oldto = to;
  149.   SKIPWHITE(from);
  150.   if ( from && *from == QUOTE ) {
  151.     maxlen--;
  152.     from++;
  153.     while (*from && *from != QUOTE && maxlen > 1) {
  154.       if ( *from == BACKSLASH) {
  155.     from++;
  156.       }
  157.       *to++ = *from++;
  158.       maxlen--;
  159.     }
  160.     if ( *from == QUOTE ) {
  161.       from++;
  162.     }
  163.   }
  164.   *to = 0;
  165.   return(from);
  166. #else /* NEW: by George Ferguson, ferguson@cs.rochester.edu, 12 Feb 1991.
  167.      Allows escaped double-quotes (and backslashes) within the string
  168.      being parsed, since we often need these for action specs. */
  169.  
  170.   char *oldto = to;
  171.   int escaped = 0;
  172.  
  173.   SKIPWHITE(from);
  174.   if (from && *from == QUOTE ) {
  175.     maxlen--;
  176.     for (from++; *from && maxlen > 1; from++) {
  177.       if (*from == QUOTE)
  178.         if (escaped) {
  179.           *to++ = QUOTE;
  180.           maxlen--;
  181.           escaped = 0;
  182.         } else
  183.           break;
  184.       else if (*from == BACKSLASH)
  185.         if (escaped) {
  186.           *to++ = BACKSLASH;
  187.           maxlen--;
  188.           escaped = 0;
  189.         } else
  190.           escaped = 1;
  191.       else {
  192.         *to++ = *from;
  193.         maxlen--;
  194.     escaped = 0;
  195.       }
  196.     }
  197.     if ( *from == QUOTE ) {
  198.       from++;
  199.     }
  200.   }
  201.   *to = '\0';
  202.   return(from);
  203. #endif /* OLD/NEW */
  204. }  
  205.  
  206. char *
  207. EzMenuParseMenu(parent,menu,subMenuOk)
  208. Widget parent;
  209. char *menu;
  210. Bool subMenuOk;
  211. {
  212.   char *thisWidgetName[NAME_LEN];
  213.   char *thisWidgetLabel[LABEL_LEN];
  214.  
  215.   *thisWidgetName = 0;
  216.   *thisWidgetLabel = 0;
  217.   while(menu && *menu) {
  218.     SKIPWHITE(menu);
  219.  
  220.     if (!menu || *menu != '(') {
  221.       return( menu );
  222.     }
  223.     else {
  224.       menu++;
  225.     }
  226.  
  227.     SKIPWHITE(menu);
  228.  
  229.     if (isalpha(*menu)) {
  230.       char key[KEY_LEN+1];
  231.       char *p = key;
  232.       int keylen = 0;
  233.  
  234.       while(isalpha(*menu) && keylen < KEY_LEN) {
  235.     *p++ = *menu++;
  236.     keylen++;
  237.       }
  238.       *p = 0;
  239.  
  240.       if (strcmp(key, "action") == 0 ) {
  241.     char name[NAME_LEN];
  242.     Arg arglist[1];
  243.     Cardinal num_args = 0;
  244.  
  245.     menu = EzMenuParseString(menu, name, NAME_LEN);
  246.  
  247.     XtSetArg(arglist[num_args], XtNaction, name); num_args++;
  248.     XtSetValues(parent, arglist, num_args);
  249.       }
  250.       else if (strcmp(key, "blank") == 0 ) {
  251.     char name[NAME_LEN];
  252.     Widget entry;
  253.  
  254.     *name = 0;
  255.     menu = EzMenuParseString(menu, name, NAME_LEN);
  256.     if ( *name == 0 ) {
  257.       static int counter = 0;
  258.       sprintf(name, "blank%d", counter);
  259.     }
  260.     entry = XtCreateManagedWidget(name, smeObjectClass,
  261.                       parent, NULL, ZERO);
  262.       }
  263.       else if (strcmp(key, "line") == 0 ) {
  264.     char name[NAME_LEN];
  265.     Widget entry;
  266.  
  267.     *name = 0;
  268.     menu = EzMenuParseString(menu, name, NAME_LEN);
  269.     if ( *name == 0 ) {
  270.       static int counter = 0;
  271.       sprintf(name, "line%d", counter);
  272.     }
  273.     entry = XtCreateManagedWidget(name, smeLineObjectClass, parent,
  274.                       NULL, ZERO);
  275.       }
  276.       else if (strcmp(key, "item") == 0 || strcmp(key, "menu") == 0 ) {
  277.     char name[NAME_LEN];
  278.     char label[LABEL_LEN];
  279.     Widget entry;
  280.     Bool isMenu;
  281.     extern void MenuSelect();
  282.     Arg arglist[10];
  283.     Cardinal num_args = 0;
  284.  
  285.  
  286.     isMenu = (strcmp(key, "menu") == 0);
  287.     *name = 0;
  288.  
  289.     menu = EzMenuParseString(menu, label, LABEL_LEN);
  290.     menu = EzMenuParseString(menu, name, NAME_LEN);
  291.  
  292.     if ( *name == 0 ) {
  293.       static int counter = 0;
  294.       sprintf(name, "%s%d", key, counter);
  295.     }
  296.  
  297.     if ( *label == 0 ) {
  298.       strcpy(label, name);
  299.     }
  300.  
  301.     if ( isMenu ) {
  302.       char menu_name[NAME_LEN];
  303.       Widget menu_entry;
  304.  
  305.       sprintf(menu_name,"%s-menu", name);
  306.  
  307.       XtSetArg(arglist[num_args], XtNlabel, label); num_args++;
  308.  
  309.       menu_entry = XtCreatePopupShell(menu_name, ezMenuWidgetClass,
  310.                  parent, arglist, num_args);
  311.  
  312.       /* now, parse their menu entry. This is gross, but beats
  313.        scanning ahead to find the stupid balanced parens */
  314.       menu = EzMenuParseMenu(menu_entry, menu, True);
  315.  
  316.       num_args = 0;
  317.       XtSetArg(arglist[num_args], XtNlabel, label); num_args++;
  318.       XtSetArg(arglist[num_args], XtNmenu, menu_entry); num_args++;
  319.       entry = XtCreateManagedWidget(name, ezMEObjectClass, parent, 
  320.                     arglist, num_args);
  321.     }
  322.     else {
  323.       num_args = 0;
  324.       XtSetArg(arglist[num_args], XtNlabel, label); num_args++;
  325.       XtSetArg(arglist[num_args], XtNmenu, 0); num_args++;
  326.       entry = XtCreateManagedWidget(name, ezMEObjectClass, parent, 
  327.                     arglist, num_args);
  328.     }
  329.  
  330.     menu = EzMenuParseMenu(entry, menu, isMenu);
  331.       }
  332.  
  333.       SKIPWHITE(menu);
  334.       if (*menu != ')') {
  335.     char buffer[2048];
  336.     XtAppContext context = 
  337.       XtWidgetToApplicationContext( parent );
  338.  
  339.     sprintf(buffer, "unbalanced parens or bogus format: %s\n", menu);
  340.  
  341.     XtAppError(context, buffer);
  342.     exit(1);
  343.       }
  344.       menu++;
  345.     }
  346.   }
  347.   return(menu);
  348. }
  349.  
  350. /*      Function Name: Initialize
  351.  *      Description: Initializes the simple menu widget
  352.  *      Arguments: request - the widget requested by the argument list.
  353.  *                 new     - the new widget with both resource and non
  354.  *                           resource values.
  355.  *      Returns: none.
  356.  */
  357.  
  358. /* ARGSUSED */
  359. static void
  360. Initialize(request, new)
  361. Widget request, new;
  362. {
  363.   EzMenuWidget newez = (EzMenuWidget) new;
  364.   EzMenuWidget requestez = (EzMenuWidget) request;
  365.  
  366. #ifdef EZMENU_DEBUG
  367.   fprintf(stderr,"Initialize %s\n",
  368.       XtName(request);
  369. #endif
  370.  
  371.   /* just copy the string that will be used to initialize the menu */
  372.   
  373.   newez -> ez_menu.menu = 0;
  374.  
  375.   if (requestez -> ez_menu.menu ) {
  376.     int len = strlen(requestez -> ez_menu.menu);
  377.     newez -> ez_menu.menu = XtMalloc( len + 1 );
  378.     strcpy( newez -> ez_menu.menu, requestez -> ez_menu.menu);
  379.   }
  380.  
  381.   if ( newez -> ez_menu.menu ) {
  382.     EzMenuParseMenu( newez, newez -> ez_menu.menu, True );
  383.   }
  384. }
  385.  
  386. /*      Function Name: Realize
  387.  *      Description: Realizes the widget.
  388.  *      Arguments: w - the simple menu widget.
  389.  *                 mask - value mask for the window to create.
  390.  *                 attrs - attributes for the window to create.
  391.  *      Returns: none
  392.  */
  393.  
  394. static void
  395. Realize(w, mask, attrs)
  396. Widget w;
  397. XtValueMask * mask;
  398. XSetWindowAttributes * attrs;
  399. {
  400.   EzMenuWidget newez = (EzMenuWidget) w;
  401.   (*superclass->core_class.realize) (w, mask, attrs);
  402. }
  403.  
  404.  
  405. /*      Function Name: SetValues
  406.  *      Description: Relayout the menu when one of the resources is changed.
  407.  *      Arguments: current - current state of the widget.
  408.  *                 request - what was requested.
  409.  *                 new - what the widget will become.
  410.  *      Returns: none
  411.  */
  412.  
  413. /* ARGSUSED */
  414. static Boolean
  415. SetValues(current, request, new)
  416.      Widget current, request, new;
  417. {
  418.   EzMenuWidget ez_old = (EzMenuWidget) current;
  419.   EzMenuWidget ez_want = (EzMenuWidget) request;
  420.   EzMenuWidget ez_new = (EzMenuWidget) new;
  421.   Boolean ret_val = FALSE;
  422.   if (
  423.  
  424.       /* no old menu, want one now */
  425.  
  426.       ( !ez_old -> ez_menu.menu && ez_want -> ez_menu.menu )
  427.       ||
  428.  
  429.       /* old menu, new one is different */
  430.  
  431.       (ez_want -> ez_menu.menu
  432.        && ez_old -> ez_menu.menu
  433.        && ( strcmp( ez_old -> ez_menu.menu,
  434.            ez_want -> ez_menu.menu) != 0 ))
  435.       ) {
  436.  
  437.     int len = strlen(ez_old -> ez_menu.menu);
  438.  
  439.     ez_new -> ez_menu.menu = XtMalloc( len + 1 );
  440.     strcpy( ez_new -> ez_menu.menu,
  441.        ez_old -> ez_menu.menu);
  442.     
  443.     if ( XtIsRealized(ez_old) ) {
  444.       SimpleMenuWidget smw = (SimpleMenuWidget) ez_old;
  445.       SmeObject *entry;
  446.       
  447.       ForAllChildren(smw, entry) {
  448.     XtDestroyWidget(entry);
  449.       }
  450.  
  451.       EzMenuParseMenu(ez_new, ez_new -> ez_menu.menu, True);
  452.       ret_val = TRUE;
  453.     }
  454.   }
  455.   return(ret_val);
  456. }
  457.  
  458. static void
  459. Destroy(who)
  460. EzMenuWidget who;
  461. {
  462.   XtFree( who -> ez_menu.menu );
  463. }
  464.  
  465.