home *** CD-ROM | disk | FTP | other *** search
/ vsiftp.vmssoftware.com / VSIPUBLIC@vsiftp.vmssoftware.com.tar / FREEWARE / FREEWARE40.ZIP / xpaint-247 / menu.c < prev    next >
C/C++ Source or Header  |  1997-01-03  |  16KB  |  344 lines

  1. /* +-------------------------------------------------------------------+ */
  2. /* | Copyright 1992, 1993, David Koblas (koblas@netcom.com)            | */
  3. /* |                                                                   | */
  4. /* | Permission to use, copy, modify, and to distribute this software  | */
  5. /* | and its documentation for any purpose is hereby granted without   | */
  6. /* | fee, provided that the above copyright notice appear in all       | */
  7. /* | copies and that both that copyright notice and this permission    | */
  8. /* | notice appear in supporting documentation.  There is no           | */
  9. /* | representations about the suitability of this software for        | */
  10. /* | any purpose.  this software is provided "as is" without express   | */
  11. /* | or implied warranty.                                              | */
  12. /* |                                                                   | */
  13. /* +-------------------------------------------------------------------+ */
  14.  
  15. /* $Id: menu.c,v 1.3 1996/04/19 08:53:40 torsten Exp $ */
  16.  
  17. #include <X11/Intrinsic.h>
  18. #include <X11/StringDefs.h>
  19.  
  20. #ifndef VMS
  21. #include <X11/Xaw/MenuButton.h>
  22. #include <X11/Xaw/SimpleMenu.h>
  23. #include <X11/Xaw/SmeBSB.h>
  24. #include <X11/Xaw/SmeLine.h>
  25. #include <X11/Xaw/Form.h>
  26. #else
  27. #include <X11Xaw/MenuButton.h>
  28. #include <X11Xaw/SimpleMenu.h>
  29. #include <X11Xaw/SmeBSB.h>
  30. #include <X11Xaw/SmeLine.h>
  31. #include <X11Xaw/Form.h>
  32. #endif
  33. #include <stdio.h>
  34. #include "menu.h"
  35.  
  36. #include "bitmaps/checkmark.xbm"
  37. #include "bitmaps/pullright.xbm"
  38.  
  39. #define MAX_GROUPS    4
  40.  
  41. typedef struct group_s {
  42.     int size;
  43.     Widget group[16];
  44.     struct group_s *next;
  45. } GroupList;
  46.  
  47. typedef struct rightlist_s {
  48.     Widget widget;
  49.     Widget shell;
  50.     struct rightlist_s *next;
  51. } RightList;
  52.  
  53. static GroupList *groupHead = NULL;
  54. static RightList *rightHead = NULL;
  55. static Pixmap checkBitmap = None, pullBitmap = None;
  56.  
  57. static void pullRightAction(Widget, XEvent *, String *, Cardinal *);
  58.  
  59. static GroupList *
  60. findGroup(Widget w)
  61. {
  62.     GroupList *cur = groupHead;
  63.     int i;
  64.  
  65.     if (w == None)
  66.     return NULL;
  67.  
  68.     while (cur != NULL) {
  69.     for (i = 0; i < cur->size; i++)
  70.         if (cur->group[i] == w)
  71.         return cur;
  72.     cur = cur->next;
  73.     }
  74.     return NULL;
  75. }
  76.  
  77. static void 
  78. initMenu(Widget w)
  79. {
  80.     static XtActionsRec act =
  81.     {"popup-menu-pullright", (XtActionProc) pullRightAction};
  82.  
  83.     if (checkBitmap != None)
  84.     return;
  85.  
  86.     checkBitmap = XCreateBitmapFromData(XtDisplay(w),
  87.                     DefaultRootWindow(XtDisplay(w)),
  88.                     (char *) checkmark_bits,
  89.                       checkmark_width, checkmark_height);
  90.     pullBitmap = XCreateBitmapFromData(XtDisplay(w),
  91.                        DefaultRootWindow(XtDisplay(w)),
  92.                        (char *) pullright_bits,
  93.                        pullright_width, pullright_height);
  94.  
  95.     XtAppAddActions(XtWidgetToApplicationContext(w), &act, 1);
  96. }
  97.  
  98. static void 
  99. destroy(Widget w, XtPointer data, XtPointer junk)
  100. {
  101.     XtFree((XtPointer) data);
  102. }
  103.  
  104. static void 
  105. pullRightAction(Widget w, XEvent * event, String * params, Cardinal * nparams)
  106. {
  107.     Dimension width, height;
  108.     int x, y;
  109.     RightList *cur;
  110.     Widget cw = XawSimpleMenuGetActiveEntry(w);
  111.  
  112.     if (cw == None || event->type != MotionNotify)
  113.     return;
  114.  
  115.     x = event->xmotion.x;
  116.     y = event->xmotion.y;
  117.  
  118.     XtVaGetValues(w, XtNwidth, &width, XtNheight, &height, NULL);
  119.     if (x < 0 || x >= width || y < 0 || y >= height)
  120.     return;
  121.  
  122.     /*
  123.     **  Only the second half of the menu is sensitive to pulls
  124.      */
  125.     if (x < width / 2)
  126.     return;
  127.  
  128.     for (cur = rightHead; cur != NULL && cur->widget != cw; cur = cur->next);
  129.  
  130.     if (cur == NULL)
  131.     return;
  132.  
  133.     x = event->xmotion.x_root - 20;
  134.     y = event->xmotion.y_root - 20;
  135.     XtVaSetValues(cur->shell, XtNx, x, XtNy, y, NULL);
  136.  
  137.     XtPopup(cur->shell, XtGrabExclusive);
  138. }
  139.  
  140. static void 
  141. createItem(Widget parent, PaintMenuItem * item,
  142.        Widget groups[MAX_GROUPS])
  143. {
  144.     int grp = -1;
  145.     Widget entry;
  146.  
  147.     if (item->name[0] == '\0') {
  148.     entry = XtVaCreateManagedWidget("seperator",
  149.                     smeLineObjectClass, parent,
  150.                     NULL);
  151.     } else if (item->flags & MF_CHECK) {
  152.     entry = XtVaCreateManagedWidget(item->name,
  153.                     smeBSBObjectClass, parent,
  154.                       XtNleftMargin, checkmark_width + 4,
  155.                     NULL);
  156.     } else if (item->right != NULL && item->nright != 0) {
  157.     static XtTranslations trans = None, trans2 = None;
  158.     int i;
  159.     RightList *cur;
  160.     String nm;
  161.  
  162.     if (trans == None) {
  163.         trans = XtParseTranslationTable(
  164.               "<BtnMotion>: highlight() popup-menu-pullright()");
  165. #ifndef VMS
  166.         trans2 = XtParseTranslationTable(
  167.               "<LeaveWindow>: unhighlight() MenuPopdown()\n"
  168.               "<BtnUp>: notify() unhighlight() MenuPopdown()\n"
  169.               "<BtnMotion>: highlight()");
  170. #else
  171. #ifdef __DECC
  172.         trans2 = XtParseTranslationTable(
  173.               "<LeaveWindow>: unhighlight() MenuPopdown()\n"
  174.               "<BtnUp>: notify() unhighlight() MenuPopdown()\n"
  175.               "<BtnMotion>: highlight()");
  176. #else
  177.         trans2 = XtParseTranslationTable(
  178. "<LeaveWindow>: unhighlight() MenuPopdown()\n<BtnUp>: notify() unhighlight() MenuPopdown()<BtnMotion>: highlight()");
  179. #endif
  180. #endif
  181.     }
  182.     entry = XtVaCreateManagedWidget(item->name,
  183.                     smeBSBObjectClass, parent,
  184.                     XtNrightMargin, pullright_width,
  185.                     XtNrightBitmap, pullBitmap,
  186.                     NULL);
  187.  
  188.     nm = (String) XtMalloc(strlen(XtName(XtParent(parent))) +
  189.                    strlen(item->name) + 16);
  190.     sprintf(nm, "%s-%s-right", XtName(XtParent(parent)), item->name);
  191.  
  192.     item->rightShell = XtVaCreatePopupShell(nm,
  193.                        simpleMenuWidgetClass, parent,
  194.                         XtNtranslations, trans2,
  195.                         NULL);
  196.     XtAddCallback(item->rightShell, XtNdestroyCallback, destroy, (XtPointer) nm);
  197.     XtOverrideTranslations(parent, trans);
  198.  
  199.     for (i = 0; i < item->nright; i++)
  200.         createItem(item->rightShell, &item->right[i], groups);
  201.  
  202.     cur = XtNew(RightList);
  203.     cur->shell = item->rightShell;
  204.     cur->widget = entry;
  205.     cur->next = rightHead;
  206.     rightHead = cur;
  207.     } else {
  208.     entry = XtVaCreateManagedWidget(item->name,
  209.                     smeBSBObjectClass, parent,
  210.                     NULL);
  211.     }
  212.  
  213.     if (item->flags & MF_GROUP1)
  214.     grp = 0;
  215.     else if (item->flags & MF_GROUP2)
  216.     grp = 1;
  217.     else if (item->flags & MF_GROUP3)
  218.     grp = 2;
  219.     else if (item->flags & MF_GROUP4)
  220.     grp = 3;
  221.  
  222.     if (grp != -1) {
  223.     GroupList *c = findGroup(groups[grp]);
  224.  
  225.     if (c == NULL) {
  226.         /* XXX GroupList entry leaked */
  227.         c = XtNew(GroupList);
  228.         c->next = groupHead;
  229.         groupHead = c;
  230.         c->size = 0;
  231.         groups[grp] = entry;
  232.     }
  233.     c->group[c->size++] = entry;
  234.     }
  235.     if ((item->flags & MF_CHECKON) == MF_CHECKON)
  236.     XtVaSetValues(entry, XtNleftBitmap, checkBitmap, NULL);
  237.  
  238.     if (item->callback != NULL)
  239.     XtAddCallback(entry, XtNcallback,
  240.               (XtCallbackProc) item->callback, item->data);
  241.     item->widget = entry;
  242. }
  243.  
  244. Widget
  245. MenuBarCreate(Widget parent, int nbar, PaintMenuBar bar[])
  246. {
  247.     int list, item;
  248.     Widget button = None, menu;
  249.     Widget prevButton = None;
  250.     char menuPopupName[80];
  251.     int i;
  252.     Widget groups[MAX_GROUPS];
  253.  
  254.     initMenu(parent);
  255.  
  256.     /*
  257.     **  If there is more than one entry in this bar
  258.     **    reparent it.
  259.      */
  260.     if (nbar > 1)
  261.     parent = XtVaCreateManagedWidget("menu",
  262.                      formWidgetClass, parent,
  263.                      XtNborderWidth, 0,
  264.                      XtNbottom, XtChainTop,
  265.                      XtNright, XtChainLeft,
  266.                      XtNleft, XtChainLeft,
  267.                      NULL);
  268.  
  269.     for (list = 0; list < nbar; list++) {
  270.     char *nm;
  271.     strcpy(menuPopupName, bar[list].name);
  272.     strcat(menuPopupName, "Menu");
  273.  
  274.     nm = XtNewString(menuPopupName);
  275.  
  276.     button = XtVaCreateManagedWidget(bar[list].name,
  277.                      menuButtonWidgetClass, parent,
  278.                      XtNmenuName, nm,
  279.                      XtNfromHoriz, prevButton,
  280.                      NULL);
  281.     XtAddCallback(button, XtNdestroyCallback, destroy, (XtPointer) nm);
  282.     prevButton = button;
  283.  
  284.     menu = XtCreatePopupShell(menuPopupName,
  285.                   simpleMenuWidgetClass, button,
  286.                   NULL, 0);
  287.  
  288.     bar[list].widget = menu;
  289.  
  290.     for (i = 0; i < MAX_GROUPS; i++)
  291.         groups[i] = None;
  292.  
  293.     for (item = 0; item < bar[list].nitems; item++)
  294.         createItem(menu, &bar[list].items[item], groups);
  295.     }
  296.  
  297.     return (nbar > 1) ? parent : button;
  298. }
  299.  
  300. Widget
  301. MenuPopupCreate(Widget parent, int nitems, PaintMenuItem items[])
  302. {
  303.     static XtTranslations trans = None;
  304.     int i;
  305.     Widget menu;
  306.     Widget groups[MAX_GROUPS];
  307.  
  308.     for (i = 0; i < MAX_GROUPS; i++)
  309.     groups[i] = None;
  310.  
  311.     initMenu(parent);
  312.  
  313.     menu = XtCreatePopupShell("popup-menu",
  314.                   simpleMenuWidgetClass, parent,
  315.                   NULL, 0);
  316.  
  317.     if (trans == None)
  318.     trans = XtParseTranslationTable(
  319.     "<Btn3Down>: XawPositionSimpleMenu(popup-menu) MenuPopup(popup-menu)");
  320.  
  321.     XtOverrideTranslations(parent, trans);
  322.  
  323.     for (i = 0; i < nitems; i++)
  324.     createItem(menu, &items[i], groups);
  325.  
  326.     return menu;
  327. }
  328.  
  329. void 
  330. MenuCheckItem(Widget w, Boolean flag)
  331. {
  332.     GroupList *c;
  333.  
  334.     if (w == None)
  335.     return;
  336.  
  337.     if ((c = findGroup(w)) != NULL) {
  338.     int i;
  339.     for (i = 0; i < c->size; i++)
  340.         XtVaSetValues(c->group[i], XtNleftBitmap, None, NULL);
  341.     }
  342.     XtVaSetValues(w, XtNleftBitmap, flag ? checkBitmap : None, NULL);
  343. }
  344. i