Annotation of researchv9/X11/src/X.V11R1/lib/oldXtk/Menu.c, revision 1.1.1.1

1.1       root        1: /* $Header: Menu.c,v 1.1 87/09/11 07:58:12 toddb Exp $ */
                      2: #ifndef lint
                      3: static char *sccsid = "@(#)Menu.c      1.6     2/26/87";
                      4: #endif lint
                      5: 
                      6: /*
                      7:  * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
                      8:  * 
                      9:  *                         All Rights Reserved
                     10:  * 
                     11:  * Permission to use, copy, modify, and distribute this software and its 
                     12:  * documentation for any purpose and without fee is hereby granted, 
                     13:  * provided that the above copyright notice appear in all copies and that
                     14:  * both that copyright notice and this permission notice appear in 
                     15:  * supporting documentation, and that the name of Digital Equipment
                     16:  * Corporation not be used in advertising or publicity pertaining to
                     17:  * distribution of the software without specific, written prior permission.  
                     18:  * 
                     19:  * 
                     20:  * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
                     21:  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
                     22:  * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
                     23:  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
                     24:  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
                     25:  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
                     26:  * SOFTWARE.
                     27:  */
                     28: 
                     29: /* 
                     30:  * Menu.c - Basic menu widget
                     31:  * 
                     32:  * Author:     M. Gancarz, based on ButtonBox.c by haynes
                     33:  */
                     34: 
                     35: #include       "Xlib.h"
                     36: #include       "Intrinsic.h"
                     37: #include        "Menu.h"
                     38: #include        "Atoms.h"
                     39: 
                     40: #define X10
                     41: 
                     42: #define MAXHEIGHT      ((1 << 31)-1)
                     43: #define MAXWIDTH       ((1 << 31)-1)
                     44: 
                     45: #define max(x, y)      (((x) > (y)) ? (x) : (y))
                     46: #define min(x, y)      (((x) < (y)) ? (x) : (y))
                     47: #define assignmax(x, y)        if ((y) > (x)) x = (y)
                     48: #define assignmin(x, y)        if ((y) < (x)) x = (y)
                     49: 
                     50: #define all_items      i = 0, item = data->entries;\
                     51:                         i < data->numentries; i++, item = item->next
                     52: #define item_w         (item->lug.w)
                     53: #define item_x         (item->lug.wb.x)
                     54: #define item_y         (item->lug.wb.y)
                     55: #define item_width     (item->lug.wb.width)
                     56: #define item_height    (item->lug.wb.height)
                     57: #define item_borderWidth       (item->lug.wb.borderWidth)
                     58: 
                     59: /****************************************************************
                     60:  *
                     61:  * Private Types
                     62:  *
                     63:  ****************************************************************/
                     64: 
                     65: typedef void (*MenuProc)();
                     66: 
                     67: typedef struct _WidgetEntryRec {
                     68:     struct _WidgetEntryRec     *next;          /* ptr to next entry */
                     69:     struct _WidgetEntryRec     *prev;          /* ptr to previous entry */
                     70:     WindowLug                  lug;            /* data for this entry */
                     71: } WidgetEntryRec, *WidgetEntry;
                     72: 
                     73: typedef        struct _WidgetDataRec {
                     74:     Display            *dpy;           /* widget display connection */
                     75:     Window             w;              /* widget window */
                     76:     Position           x,y;            /* widget location */
                     77:     Dimension          width, height;  /* widget window width and height */
                     78:     Dimension          borderWidth;    /* widget window border width */
                     79:     XtOrientation      orient;         /* menu orientation */
                     80:     Pixel              bp;             /* widget window border pixmap */
                     81:     Pixel              bg;             /* widget window background pixmap */
                     82:     Dimension          space;          /* inter-entry spacing */
                     83:     Dimension          hpad, vpad;     /* pad between entries and parent */
                     84:     unsigned long      notify;         /* events which cause a callback */
                     85:     MenuProc           proc;           /* procedure to invoke for callback */
                     86:     caddr_t            tag;            /* widget client data */
                     87:     int                        numentries;     /* number of entries */
                     88:     WidgetEntry                entries;        /* list of entries */
                     89: } WidgetDataRec, *WidgetData;
                     90: 
                     91: typedef struct _ParameterDataRec {
                     92:     XtMenuEntry        *entry;         /* arg MenuEntry */
                     93:     int                i;              /* arg index */
                     94: } ParameterDataRec, *ParameterData;
                     95: 
                     96: 
                     97: /****************************************************************
                     98:  *
                     99:  * Private Data
                    100:  *
                    101:  ****************************************************************/
                    102: 
                    103: static int     BlPixel, WhPixel;
                    104: static XContext  widgetContext;
                    105: 
                    106: extern void Dummy();
                    107: 
                    108: static WidgetDataRec globaldata;
                    109: static WidgetDataRec globalinit = {
                    110:     NULL,              /* Display dpy; */
                    111:     NULL,              /* Window w; */
                    112:     0,0,               /* x,y */
                    113:     1, 1,              /* int width, height; */
                    114:     1,                 /* int borderWidth; */
                    115:     XtorientVertical,  /* XtOrientation orient; */
                    116:     0,                 /* Border pixel */
                    117:     1,                 /* Background pixel */
                    118:     1,                 /* int space; */
                    119:     2, 2,              /* int hpad, vpad; */
                    120:     0,                 /* int notify; */
                    121:     Dummy,             /* void (*Proc)(); */
                    122:     NULL,              /* caddr_t tag; */
                    123:     0,                 /* int numentries; */
                    124:     NULL               /* WidgetEntry entries; */
                    125: };
                    126: 
                    127: static Resource resources[] = {
                    128:     {XtNwindow, XtCWindow, XrmRWindow,
                    129:        sizeof(Window), (caddr_t)&globaldata.w, (caddr_t)NULL},
                    130:     {XtNx, XtCX, XrmRInt,
                    131:        sizeof(int),(caddr_t)&globaldata.x,(caddr_t)NULL},
                    132:     {XtNy, XtCY, XrmRInt,
                    133:        sizeof(int),(caddr_t)&globaldata.y,(caddr_t)NULL},
                    134:     {XtNwidth, XtCWidth, XrmRInt,
                    135:         sizeof(int), (caddr_t)&globaldata.width, (caddr_t)NULL},
                    136:     {XtNheight, XtCHeight, XrmRInt,
                    137:         sizeof(int), (caddr_t)&globaldata.height, (caddr_t)NULL},
                    138:     {XtNorientation, XtCOrientation, XtROrientation,
                    139:         sizeof(XtOrientation), (caddr_t)&globaldata.orient, (caddr_t)NULL},
                    140:     {XtNborderWidth, XtCBorderWidth, XrmRInt,
                    141:         sizeof(int), (caddr_t)&globaldata.borderWidth, (caddr_t)NULL},
                    142:     {XtNborder, XtCColor, XrmRPixmap,
                    143:         sizeof(Pixmap), (caddr_t)&globaldata.bp, (caddr_t)NULL},
                    144:     {XtNbackground, XtCColor, XrmRPixmap,
                    145:         sizeof(Pixmap), (caddr_t)&globaldata.bg, (caddr_t)NULL},
                    146:     {XtNinternalWidth, XtCWidth, XrmRInt,
                    147:         sizeof(int), (caddr_t)&globaldata.hpad, (caddr_t)NULL},
                    148:     {XtNinternalHeight, XtCHeight, XrmRInt,
                    149:         sizeof(int), (caddr_t)&globaldata.vpad, (caddr_t)NULL},
                    150:     {XtNspace, XtCSpace, XrmRInt,
                    151:         sizeof(int), (caddr_t)&globaldata.space, (caddr_t)NULL},
                    152:     {XtNnotify, XtCNotify, XrmRInt,
                    153:         sizeof(int), (caddr_t)&globaldata.notify, (caddr_t)NULL},
                    154:     {XtNfunction, XtCFunction, XtRFunction,
                    155:         sizeof(MenuProc), (caddr_t)&globaldata.proc, (caddr_t)NULL},
                    156:     {XtNparameter, XtCParameter, XrmRPointer,
                    157:         sizeof(caddr_t), (caddr_t)&globaldata.tag, (caddr_t)NULL},
                    158: };
                    159: 
                    160: 
                    161: static ParameterDataRec parms;
                    162: static ParameterDataRec parminit = {
                    163:     NULL,      /* MenuEntry entry */
                    164:     -1,                /* int i; */
                    165: };
                    166: 
                    167: static Resource parmResources[] = {
                    168:     {XtNmenuEntry, XtCMenuEntry, XrmRPointer,
                    169:        sizeof(XtMenuEntry), (caddr_t)&parms.entry, (caddr_t)NULL},
                    170: };
                    171: 
                    172: /****************************************************************
                    173:  *
                    174:  * Private Routines
                    175:  *
                    176:  ****************************************************************/
                    177: 
                    178: static Boolean initialized = FALSE;
                    179: 
                    180: static void MenuInitialize(dpy)
                    181: Display *dpy;
                    182: {
                    183:     if (initialized)
                    184:        return;
                    185:     initialized = TRUE;
                    186: 
                    187:     BlPixel = BlackPixel(dpy, DefaultScreen(dpy));
                    188:     WhPixel = WhitePixel(dpy, DefaultScreen(dpy));
                    189: 
                    190:     globalinit.bp = BlPixel;
                    191:     globalinit.bg = WhPixel;
                    192: 
                    193:     globalinit.orient = XtorientVertical;
                    194:     widgetContext = XUniqueContext();
                    195: }
                    196: 
                    197: /*
                    198:  * Given a display and window, get the widget data.
                    199:  */
                    200: 
                    201: static WidgetData DataFromWindow(dpy, window)
                    202: Display *dpy;
                    203: Window window;
                    204: {
                    205:     WidgetData result;
                    206:     if (XFindContext(dpy, window, widgetContext, (caddr_t *)&result))
                    207:         return NULL;
                    208:     return result;
                    209: }
                    210: 
                    211: /*
                    212:  * Default callback procedure
                    213:  */
                    214: /*ARGSUSED*/
                    215: static void Dummy(tag)
                    216: caddr_t tag;
                    217: {
                    218:     (void) puts("Menu: dummy callback");
                    219: }
                    220: 
                    221: extern void Destroy();
                    222: 
                    223: /*
                    224:  *
                    225:  * Do a layout, either actually assigning positions, or just calculating size
                    226:  *
                    227:  */
                    228: 
                    229: static int DoLayout(data)
                    230: WidgetData     data;
                    231: {
                    232:     int        i;
                    233:     int        vpad, hpad, sp;
                    234:     Dimension maxheight = 0, maxwidth = 0, maxborderWidth = 0;
                    235:     Dimension menuwidth, menuheight, dmaxborderWidth, borderWidth;
                    236:     Position newx, newy, xoffset, yoffset;
                    237:     Dimension newwidth, newheight;
                    238:     WidgetEntry item;
                    239: 
                    240:     if (data->numentries == 0) return(0);
                    241: 
                    242:     sp = data->space;
                    243:     hpad = data->hpad;
                    244:     vpad = data->vpad;
                    245: 
                    246:     for (all_items) {
                    247:         assignmax(maxheight, item->lug.wb.height);
                    248:         assignmax(maxwidth, item_width);
                    249:         assignmax(maxborderWidth, item_borderWidth);
                    250:     }
                    251: 
                    252:     dmaxborderWidth = maxborderWidth << 1;
                    253:     if (data->orient == XtorientVertical) {
                    254:         menuwidth = (hpad << 1) + maxwidth + dmaxborderWidth;
                    255:         menuheight = (data->numentries * (maxheight + dmaxborderWidth)) +
                    256:                      ((data->numentries - 1) * sp) + (vpad << 1);
                    257:     } else {
                    258:         menuwidth = (data->numentries * (maxwidth + dmaxborderWidth)) +
                    259:                      ((data->numentries - 1) * sp) + (hpad << 1);
                    260:         menuheight = (vpad << 1) + maxheight + dmaxborderWidth;
                    261:     }
                    262:     (void) TryLayout(data, menuwidth, menuheight);
                    263:    
                    264:     newx = hpad;
                    265:     newy = vpad;
                    266:     xoffset = maxwidth + dmaxborderWidth;
                    267:     yoffset = maxheight + dmaxborderWidth;
                    268:     for (all_items) {
                    269:         borderWidth = item_borderWidth << 1;
                    270:         newwidth = xoffset - borderWidth;
                    271:         newheight = yoffset - borderWidth;
                    272:         if (newwidth != item_width || newheight != item_height
                    273:          || newx != item_x || newy != item_y) {
                    274:             XMoveResizeWindow(data->dpy, item_w, 
                    275:                newx, newy, newwidth, newheight);
                    276:            XtSendConfigureNotify(item_w,&(item->lug.wb));
                    277:        }
                    278:         item_x = newx;
                    279:         item_y = newy;
                    280:         item_width = newwidth;
                    281:         item_height = newheight;
                    282:         if (data->orient == XtorientVertical)
                    283:             newy += sp + yoffset;
                    284:         else newx += sp + xoffset;
                    285:     }
                    286: 
                    287:     return (1);
                    288: }
                    289: 
                    290: /*
                    291:  *
                    292:  * Compute the layout of the menu
                    293:  *
                    294:  */
                    295: 
                    296: /* ||| Why Layout calls DoLayout I don't know... */
                    297: 
                    298: static void Layout(data)
                    299: WidgetData     data;
                    300: {
                    301:     (void) DoLayout(data);
                    302: }
                    303: 
                    304: /*
                    305:  *
                    306:  * Generic widget event handler
                    307:  *
                    308:  */
                    309: 
                    310: static XtEventReturnCode EventHandler(event, eventdata)
                    311: XEvent *event;
                    312: caddr_t eventdata;
                    313: {
                    314:     WidgetData data = (WidgetData) eventdata;
                    315: 
                    316:     switch (event->type) {
                    317:        case ConfigureNotify:
                    318:            /* we expect to get an expose window on resize */
                    319:             if ((data->height != event->xconfigure.height) ||
                    320:                (data->width != event->xconfigure.width)) {
                    321:                data->height = event->xconfigure.height;
                    322:                data->width = event->xconfigure.width;
                    323:                Layout(data);
                    324:             }
                    325:            break;
                    326: 
                    327:         case DestroyNotify: Destroy(data); break;
                    328: 
                    329: 
                    330:         case Expose:
                    331:             break;
                    332:     }
                    333: 
                    334:     return (XteventHandled);
                    335: }
                    336: 
                    337: /*
                    338:  * Widget notify event handler
                    339:  */
                    340: /*ARGSUSED*/
                    341: static XtEventReturnCode Notify(event, eventdata)
                    342: XEvent *event;
                    343: caddr_t eventdata;
                    344: {
                    345:     WidgetData data = (WidgetData)eventdata;
                    346: 
                    347:     data->proc(data->tag);
                    348:     return(XteventHandled);
                    349: }
                    350: 
                    351: /*
                    352:  *
                    353:  * Destroy the widget
                    354:  *
                    355:  */
                    356: 
                    357: static void Destroy(data)
                    358: WidgetData     data;
                    359: {
                    360:     WidgetEntry item;
                    361:     int        i;
                    362:     /* send destroy messages to all my subwindows */
                    363:     for (all_items) {
                    364:        (void) XtSendDestroyNotify(data->dpy, item_w); }
                    365:        
                    366:     XtFree((char *) data->entries);
                    367: 
                    368:     XtClearEventHandlers(data->dpy, data->w);
                    369:     (void) XDeleteContext(data->dpy, data->w, widgetContext);
                    370:     XDestroyWindow (data->dpy,data->w);
                    371:     XtFree ((char *) data);
                    372: }
                    373: 
                    374: /*
                    375:  *
                    376:  * Find Entry
                    377:  *
                    378:  */
                    379: 
                    380: static WidgetEntry FindEntry(data, w)
                    381:     WidgetData data;
                    382:     Window     w;
                    383: {
                    384:     int        i;
                    385:     WidgetEntry item;
                    386: 
                    387:     for (all_items)
                    388:        if (item_w == w) return (item);
                    389: 
                    390:     return NULL;
                    391: }
                    392: 
                    393: /*
                    394:  *
                    395:  * Resize Entry
                    396:  *
                    397:  */
                    398: 
                    399: static void ResizeEntry(data, b, reqBox, replBox)
                    400: WidgetData     data;
                    401: WindowLugPtr   b;
                    402: WindowBox      *reqBox;
                    403: WindowBox      *replBox;       /* RETURN */
                    404: {
                    405:     b->wb = *reqBox;
                    406:     XResizeWindow(data->dpy,b->w, b->wb.width, b->wb.height);
                    407:     Layout(data);
                    408:     *replBox = b->wb;
                    409: }
                    410: 
                    411: /*
                    412:  *
                    413:  * Try to do a new layout within a particular width and height
                    414:  *
                    415:  */
                    416: 
                    417: static int TryLayout(data, width, height)
                    418: WidgetData     data;
                    419: Dimension      width, height;
                    420: {
                    421:     WindowBox  box, rbox;
                    422: 
                    423:     /* let's see if our parent will go for it. */
                    424:     box.width = width;
                    425:     box.height = height;
                    426:     switch (XtMakeGeometryRequest(data->dpy, data->w, XtgeometryResize, &box, &rbox)) {
                    427: 
                    428:        case XtgeometryNoManager:
                    429:            XResizeWindow(data->dpy,data->w, box.width, box.height);
                    430:            /* fall through to "yes" */
                    431: 
                    432:        case XtgeometryYes:
                    433:            data->width = box.width;
                    434:            data->height = box.height;
                    435:            return (1);
                    436: 
                    437: 
                    438:        case XtgeometryNo:
                    439:            return (0);
                    440: 
                    441: 
                    442:        case XtgeometryAlmost:
                    443:            box = rbox;
                    444:            (void) XtMakeGeometryRequest(data->dpy, data->w, XtgeometryResize, &box, &rbox);
                    445:            data->width = box.width;
                    446:            data->height = box.height;
                    447:            return (1);
                    448: 
                    449:     }
                    450:     return (0);
                    451: }
                    452: 
                    453: /*
                    454:  *
                    455:  * Try to do a new layout
                    456:  *
                    457:  */
                    458: 
                    459: static int TryNewLayout(data)
                    460: WidgetData     data;
                    461: {
                    462:     if (TryLayout(data, data->width, data->height)) return (1);
                    463:     if (TryLayout(data, data->width, MAXHEIGHT)) return (1);
                    464:     if (TryLayout(data, MAXWIDTH, MAXHEIGHT)) return(1);
                    465:     return (0);
                    466: }
                    467: 
                    468: /*
                    469:  *
                    470:  * Entry Resize Request
                    471:  *
                    472:  */
                    473: 
                    474: static XtGeometryReturnCode ResizeEntryRequest(data, w, reqBox, replBox)
                    475: WidgetData     data;
                    476: Window         w;
                    477: WindowBox      *reqBox;
                    478: WindowBox      *replBox;       /* RETURN */
                    479: 
                    480: {
                    481:     WidgetEntry item;
                    482:     WindowLug oldb;
                    483: 
                    484:     item = FindEntry(data, w);
                    485:     if (item == NULL) return (XtgeometryNo);
                    486:     oldb = item->lug;
                    487:     item->lug.wb = *reqBox;
                    488: 
                    489:     if ((reqBox->width <= item_width) && (reqBox->height <= item_height)) {
                    490:         /* making the button smaller always works */
                    491:         ResizeEntry(data, &(item->lug), reqBox, replBox);
                    492:        return (XtgeometryYes);
                    493:     }
                    494: 
                    495:     if (TryNewLayout(data)) {
                    496:        ResizeEntry(data, &(item->lug), reqBox, replBox);
                    497:        return (XtgeometryYes);
                    498:     }
                    499: 
                    500:     item->lug = oldb;
                    501:     return (XtgeometryNo);
                    502: }
                    503: 
                    504: /*
                    505:  *
                    506:  * Menu Entry Geometry Manager
                    507:  *
                    508:  */
                    509: 
                    510: static XtGeometryReturnCode EntryGeometryManager(
                    511:        dpy, w, req, reqBox, replBox)
                    512: Display                *dpy;
                    513: Window         w;
                    514: XtGeometryRequest  req;
                    515: WindowBox      *reqBox;
                    516: WindowBox      *replBox;       /* RETURN */
                    517: {
                    518:     WidgetData data;
                    519: 
                    520:     if (XFindContext(dpy, w, widgetContext, (caddr_t *)&data) == XCNOENT)
                    521:        return (XtgeometryYes);
                    522:     /* requests: move, resize, top, bottom */
                    523:     switch (req) {
                    524:     case XtgeometryTop    : return (XtgeometryYes);
                    525:     case XtgeometryBottom : return (XtgeometryYes);
                    526:     case XtgeometryMove   : return (XtgeometryNo);
                    527:     case XtgeometryResize :
                    528:         return (ResizeEntryRequest(data, w, reqBox, replBox));
                    529:     }
                    530:     return (XtgeometryNo);
                    531: }
                    532: 
                    533: static XtStatus AddEntry(data, w, index)
                    534: WidgetData data;
                    535: Window w, index;
                    536: {
                    537:     int i;
                    538:     Position x, y;
                    539:     Dimension width, height, borderWidth;
                    540:     unsigned depth;
                    541:     Drawable root;
                    542:     WidgetEntry newentry;
                    543:     WidgetEntry item;
                    544: 
                    545:     /*
                    546:      * Return an error if one of the following conditions is true:
                    547:      * 1. The specified window doesn't exist
                    548:      * 2. The specified window is already an entry in this widget
                    549:      * 3. An index was specified, even though no entries exist
                    550:      */
                    551:     (void) XGetGeometry(data->dpy, w, &root, &x, &y, &width, &height,
                    552:                        &borderWidth, &depth);
                    553:     if (FindEntry(data, w) != NULL) return (0);
                    554:     if ((data->numentries == 0) && index) return(0);
                    555: 
                    556:     newentry = (WidgetEntry) XtCalloc(1, sizeof(WidgetEntryRec));
                    557:     newentry->lug.w = w;
                    558:     newentry->lug.wb.x = x;
                    559:     newentry->lug.wb.y = y;
                    560:     newentry->lug.wb.width = width;
                    561:     newentry->lug.wb.height = height;
                    562:     newentry->lug.wb.borderWidth = borderWidth;
                    563: 
                    564:     if (data->numentries == 0)
                    565:        data->entries = newentry;
                    566:     else {
                    567:         if (FindEntry(data, index)) {
                    568:             for (all_items) {
                    569:                 if (item_w == index) {
                    570:                     newentry->next = item;
                    571:                     if (item->prev == NULL)
                    572:                         data->entries = item->prev = newentry;
                    573:                     else {
                    574:                         (item->prev)->next = newentry;
                    575:                         item->prev = newentry;
                    576:                     }
                    577:                     break;
                    578:                 }
                    579:             }
                    580:         } else {
                    581:             for (all_items) /* NULL */ ;
                    582:             for (i = 0, item = data->entries; i < data->numentries - 1;
                    583:                  i++, item = item->next) /* NULL */;
                    584:             item->next = newentry;
                    585:             newentry->prev = item;
                    586:         }
                    587: 
                    588:     }
                    589: 
                    590:     data->numentries++;
                    591:     (void) XSaveContext(data->dpy, newentry->lug.w, widgetContext, (caddr_t)data);
                    592:     (void) XtSetGeometryHandler(data->dpy, newentry->lug.w, EntryGeometryManager);
                    593: 
                    594:     return(1);
                    595: }
                    596: 
                    597: static void BatchAddEntries(data, args, argCount)
                    598: WidgetData data;
                    599: ArgList args;
                    600: int argCount;
                    601: {
                    602:     if (argCount) {
                    603:        for ( ; --argCount >= 0; args++) {
                    604:             if (strcmp(args->name , XtNmenuEntry)==0) {
                    605:                (void) AddEntry(data, (*((XtMenuEntry *)args->value)).w,
                    606:                                 (*((XtMenuEntry *)args->value)).index);
                    607:            }
                    608:        }
                    609: /*     (void) TryNewLayout(data); */
                    610:        Layout(data);
                    611:     }
                    612: }
                    613: 
                    614: 
                    615: /****************************************************************
                    616:  *
                    617:  * Public Routines
                    618:  *
                    619:  ****************************************************************/
                    620: 
                    621: Window XtMenuCreate(dpy, parent, args, argCount)
                    622:     Display  *dpy;
                    623:     Window   parent;
                    624:     ArgList  args;
                    625:     int      argCount;
                    626: {
                    627:     WidgetData data;
                    628:     XrmNameList        names;
                    629:     XrmClassList classes;
                    630:     XSetWindowAttributes wvals;
                    631:     int valuemask;
                    632: 
                    633:     if (!initialized) MenuInitialize(dpy);
                    634: 
                    635:     data = (WidgetData) XtMalloc(sizeof(WidgetDataRec));
                    636: 
                    637:     globaldata = globalinit;
                    638:     globaldata.dpy = dpy;
                    639:     XtGetResources(dpy, resources, XtNumber(resources), args, argCount, parent,
                    640:        "menu", "Menu", &names, &classes);
                    641:     *data = globaldata;
                    642:     if (data->width == 0)
                    643:         data->width = ((data->hpad != 0) ? data->hpad : 10);
                    644:     if (data->height == 0)
                    645:        data->height = ((data->vpad != 0) ? data->vpad : 10);
                    646: 
                    647:     if (data->w != NULL) {
                    648:        XWindowChanges wc;
                    649:        unsigned int valuemask;
                    650:        valuemask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth;
                    651:        wc.x = data->x; wc.y = data->y; wc.width = data->width;
                    652:        wc.height = data->height; wc.border_width = data->borderWidth;
                    653:        XConfigureWindow(data->dpy,data->w,valuemask, &wc);
                    654:        XReparentWindow(data->dpy,data->w,parent,data->x,data->y);
                    655:      }
                    656:     if (data->w == NULL) {   
                    657:      wvals.background_pixel = data->bg;
                    658:      wvals.border_pixel = data->bp;
                    659:      wvals.bit_gravity = CenterGravity;
                    660:     
                    661:      valuemask = CWBackPixel | CWBorderPixel | CWBitGravity;
                    662:        data->w = XCreateWindow(data->dpy, parent, data->x, data->y,
                    663:                         data->width, data->height, data->borderWidth,
                    664:                         0, InputOutput, (Visual *)CopyFromParent,
                    665:                         valuemask, &wvals);
                    666: 
                    667:     }
                    668: 
                    669:     XtSetNameAndClass(data->dpy, data->w, names, classes);
                    670:     XrmFreeNameList(names);
                    671:     XrmFreeClassList(classes);
                    672: 
                    673:     /* set handler for message and destroy events */
                    674: 
                    675:     XtSetEventHandler(data->dpy, data->w, (XtEventHandler)EventHandler,
                    676:                          StructureNotifyMask, (caddr_t) data);
                    677: 
                    678:     /* set handler for notify events, if any */
                    679:     if (data->notify)
                    680:         XtSetEventHandler(data->dpy, data->w, (XtEventHandler)Notify, data->notify,
                    681:                             (caddr_t) data);
                    682: 
                    683:     (void) XSaveContext(data->dpy, data->w, widgetContext, (caddr_t)data);
                    684:     (void) XtSetGeometryHandler(data->dpy, data->w, (XtGeometryHandler) XtMenuGeometryManager);
                    685: 
                    686:     /*
                    687:      * Batch add initial entries
                    688:      */
                    689:     BatchAddEntries(data, args, argCount);
                    690: 
                    691:     return (data->w);
                    692: }
                    693: 
                    694: XtStatus XtMenuAddEntry(dpy, parent, args, argCount)
                    695:     Display  *dpy;
                    696:     Window   parent;
                    697:     ArgList  args;
                    698:     int      argCount;
                    699: {
                    700:     WidgetData data;
                    701: 
                    702:     if (XFindContext(dpy, parent, widgetContext, (caddr_t *)&data) == XCNOENT)
                    703:         return(0);
                    704: 
                    705:     /*
                    706:      * Batch add all entries
                    707:      */
                    708:     BatchAddEntries(data, args, argCount);
                    709: 
                    710:     return (1);
                    711: }
                    712: 
                    713: XtStatus XtMenuDeleteEntry(dpy, parent, args, argCount)
                    714:     Display  *dpy;
                    715:     Window   parent;
                    716:     ArgList  args;
                    717:     int      argCount;
                    718: {
                    719:     WidgetData data;
                    720:     int                i;
                    721:     WidgetEntry item;
                    722: 
                    723:     if (XFindContext(dpy, parent, widgetContext, (caddr_t *)&data) == XCNOENT)
                    724:         return(0);
                    725: 
                    726:     parms = parminit;
                    727:     XtSetValues(parmResources, XtNumber(parmResources), args, argCount);
                    728:     if ((parms.entry == NULL) && (parms.i == -1)) return (0);
                    729: 
                    730:     if (parms.i >= 0) i = parms.i;
                    731:     else {
                    732:         for (all_items)
                    733:             if (item_w == parent) break;
                    734:     }
                    735: 
                    736:     if (i >= data->numentries) return (0);
                    737:     if (data->numentries == 1) {
                    738:         data->entries = NULL;
                    739:     } else if (i == data->numentries - 1) {
                    740:         (item->prev)->next = NULL;
                    741:     } else {
                    742:         (item->prev)->next = item->next;
                    743:         (item->next)->prev = item->prev;
                    744:     }
                    745: 
                    746:     (void) XDeleteContext(dpy, item_w, widgetContext);
                    747:     (void) XtClearGeometryHandler(dpy, item_w);
                    748:     data->numentries--;
                    749:     XtFree((char *) item);
                    750:     Layout(data);
                    751:     return (1);
                    752: }
                    753: 
                    754: /*
                    755:  * Menu Geometry Manager
                    756:  *
                    757:  * Note: The menu widget client typically should write its own.
                    758:  * However, this one simply says "yes" to any request to aid in
                    759:  * menu prototyping because many clients simply don't care if they're
                    760:  * using the menu as a pop-up.
                    761:  */
                    762: /*ARGSUSED*/
                    763: XtGeometryReturnCode XtMenuGeometryManager(dpy, window, req, reqBox, repBox)
                    764:     Display *dpy;
                    765:     Window window;
                    766:     XtGeometryRequest req;
                    767:     WindowBox *reqBox, *repBox;
                    768: {
                    769:     XResizeWindow(dpy, window, reqBox->width, reqBox->height);
                    770:     *repBox = *reqBox;
                    771:     return(XtgeometryYes);
                    772: }
                    773: 
                    774: /*
                    775:  *
                    776:  * Get Attributes
                    777:  *
                    778:  */
                    779: 
                    780: void XtMenuGetValues (dpy, window, args, argCount)
                    781: Display *dpy;
                    782: Window window;
                    783: ArgList args;
                    784: int argCount;
                    785: {
                    786:     WidgetData  data;
                    787:     data = DataFromWindow(dpy, window);
                    788:     if (data == NULL) return;
                    789:     globaldata = *data;
                    790:     XtGetValues(resources, XtNumber(resources), args, argCount);
                    791: }
                    792: 
                    793: /*
                    794:  *
                    795:  * Set Attributes
                    796:  *
                    797:  */
                    798: 
                    799: void XtMenuSetValues (dpy, window, args, argCount)
                    800: Display *dpy;
                    801: Window window;
                    802: ArgList args;
                    803: int argCount;
                    804: {
                    805:     WidgetData  data;
                    806:     data = DataFromWindow(dpy, window);
                    807:     if (data == NULL) return;
                    808:     globaldata = *data;
                    809:     XtSetValues(resources, XtNumber(resources), args, argCount);
                    810:     *data = globaldata;
                    811: }
                    812: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.