Annotation of researchv9/X11/src/X.V11R1/lib/oldXtk/Menu.c, revision 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.