|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.