|
|
1.1 ! root 1: #ifndef lint ! 2: static char rcs_id[] = "$Header: bbox.c,v 1.12 87/09/11 08:19:05 toddb Exp $"; ! 3: #endif lint ! 4: /* ! 5: * COPYRIGHT 1987 ! 6: * DIGITAL EQUIPMENT CORPORATION ! 7: * MAYNARD, MASSACHUSETTS ! 8: * ALL RIGHTS RESERVED. ! 9: * ! 10: * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND ! 11: * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. ! 12: * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ! 13: * ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. ! 14: * ! 15: * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT RIGHTS, ! 16: * APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN ADDITION TO THAT ! 17: * SET FORTH ABOVE. ! 18: * ! 19: * ! 20: * Permission to use, copy, modify, and distribute this software and its ! 21: * documentation for any purpose and without fee is hereby granted, provided ! 22: * that the above copyright notice appear in all copies and that both that ! 23: * copyright notice and this permission notice appear in supporting documentation, ! 24: * and that the name of Digital Equipment Corporation not be used in advertising ! 25: * or publicity pertaining to distribution of the software without specific, ! 26: * written prior permission. ! 27: */ ! 28: ! 29: /* bbox.c -- management of buttons and buttonbox's. */ ! 30: ! 31: /* This module implements a simple interface to buttonboxes, allowing a client ! 32: to create new buttonboxes and manage their contents. It is a layer hiding ! 33: the toolkit interfaces. */ ! 34: ! 35: #include "xmh.h" ! 36: #include "bboxint.h" ! 37: ! 38: ! 39: /* Free the storage for the given button. */ ! 40: ! 41: FreeButton(button) ! 42: Button button; ! 43: { ! 44: XtFree(button->name); ! 45: XtFree((char *) button); ! 46: } ! 47: ! 48: ! 49: ! 50: /* Handle a buttonbox getting resized. In particular, tell the VPane widget ! 51: the new range of legal sizes for this buttonbox. */ ! 52: ! 53: #ifdef X11 ! 54: static XtEventReturnCode HandleBBoxResize(event, buttonbox) ! 55: XEvent *event; ! 56: ButtonBox buttonbox; ! 57: { ! 58: switch (event->type) { ! 59: case ConfigureNotify: ! 60: if (event->xconfigure.height != buttonbox->maxheight) { ! 61: buttonbox->maxheight = event->xconfigure.height; ! 62: XtVPanedSetMinMax(DISPLAY buttonbox->scrn->window, ! 63: buttonbox->outer, ! 64: buttonbox->fullsized ? buttonbox->maxheight : 5, ! 65: buttonbox->maxheight); ! 66: } ! 67: return XteventHandled; ! 68: case DestroyNotify: ! 69: XtFree((char *) buttonbox->button); ! 70: XtFree((char *) buttonbox); ! 71: return XteventHandled; ! 72: } ! 73: return XteventNotHandled; ! 74: } ! 75: #endif X11 ! 76: ! 77: #ifdef X10 ! 78: static XtEventReturnCode HandleBBoxResize(event, buttonbox) ! 79: XExposeEvent *event; ! 80: ButtonBox buttonbox; ! 81: { ! 82: switch (event->type) { ! 83: case ResizeWindow: ! 84: if (event->height != buttonbox->maxheight) { ! 85: buttonbox->maxheight = event->height; ! 86: XtVPanedSetMinMax(DISPLAY buttonbox->scrn->window, ! 87: buttonbox->outer, ! 88: buttonbox->fullsized ? buttonbox->maxheight : 5, ! 89: buttonbox->maxheight); ! 90: } ! 91: return XteventHandled; ! 92: case DestroyWindow: ! 93: XtFree((char *) buttonbox->button); ! 94: XtFree((char *) buttonbox); ! 95: return XteventHandled; ! 96: } ! 97: return XteventNotHandled; ! 98: } ! 99: #endif X10 ! 100: ! 101: ! 102: /* Create a new button box. The window for it will be a child of the given ! 103: scrn's window, and it will be added to the scrn's vpane. */ ! 104: ! 105: ButtonBox BBoxRadioCreate(scrn, position, name, radio) ! 106: Scrn scrn; ! 107: int position; /* Position to put it in the vpane. */ ! 108: char *name; /* Name of the buttonbox widget. */ ! 109: Button *radio; /* Pointer to place to store which radio ! 110: button is active. */ ! 111: { ! 112: static Arg arglist[] = { ! 113: {XtNname, (XtArgVal)NULL}, ! 114: {XtNwidth, NULL}, ! 115: {XtNinnerWidth, NULL}, ! 116: {XtNallowVert, (XtArgVal)TRUE}, ! 117: }; ! 118: static Arg arglist2[] = { ! 119: {XtNwidth, NULL}, ! 120: }; ! 121: int width, height; ! 122: ButtonBox buttonbox; ! 123: ! 124: arglist[0].value = (XtArgVal)name; ! 125: GetWindowSize(scrn->window, &width, &height); ! 126: arglist[1].value = arglist[2].value = arglist2[0].value = (XtArgVal) width; ! 127: buttonbox = (ButtonBox) XtMalloc(sizeof(ButtonBoxRec)); ! 128: bzero((char *)buttonbox, sizeof(ButtonBoxRec)); ! 129: buttonbox->updatemode = TRUE; ! 130: buttonbox->scrn = scrn; ! 131: buttonbox->outer = XtScrolledWindowCreate(DISPLAY scrn->window, arglist, ! 132: XtNumber(arglist)); ! 133: buttonbox->inner = ! 134: XtButtonBoxCreate(DISPLAY XtScrolledWindowGetFrame(DISPLAY ! 135: buttonbox->outer), ! 136: arglist2, XtNumber(arglist2)); ! 137: XtScrolledWindowSetChild(DISPLAY buttonbox->outer, buttonbox->inner); ! 138: buttonbox->numbuttons = 0; ! 139: buttonbox->button = (Button *) XtMalloc(1); ! 140: XtVPanedWindowAddPane(DISPLAY scrn->window, buttonbox->outer, position, 5, ! 141: 5, FALSE); ! 142: buttonbox->maxheight = 5; ! 143: buttonbox->radio = radio; ! 144: if (radio) *radio = NULL; ! 145: XtSetEventHandler(DISPLAY buttonbox->inner, HandleBBoxResize, ! 146: #ifdef X11 ! 147: StructureNotifyMask, ! 148: #endif ! 149: #ifdef X10 ! 150: ExposeWindow, ! 151: #endif ! 152: (caddr_t) buttonbox); ! 153: return buttonbox; ! 154: } ! 155: ! 156: ! 157: ! 158: /* Create a new buttonbox which does not manage radio buttons. */ ! 159: ! 160: ButtonBox BBoxCreate(scrn, position, name) ! 161: Scrn scrn; ! 162: int position; ! 163: char *name; ! 164: { ! 165: return BBoxRadioCreate(scrn, position, name, (Button *)NULL); ! 166: } ! 167: ! 168: ! 169: ! 170: /* Set the current button in a radio buttonbox. */ ! 171: ! 172: void BBoxSetRadio(buttonbox, button) ! 173: ButtonBox buttonbox; ! 174: Button button; ! 175: { ! 176: if (buttonbox->radio && *(buttonbox->radio) != button) { ! 177: if (*(buttonbox->radio)) FlipColors(*(buttonbox->radio)); ! 178: FlipColors(button); ! 179: *(buttonbox->radio) = button; ! 180: } ! 181: } ! 182: ! 183: ! 184: ! 185: /* Some buttons have been added to the buttonbox structure; go and actually ! 186: add the button widgets to the buttonbox widget. (It is much more ! 187: efficient to add several buttons at once rather than one at a time.) */ ! 188: ! 189: static ProcessAddedButtons(buttonbox) ! 190: ButtonBox buttonbox; ! 191: { ! 192: int i, position, index; ! 193: ArgList arglist, ptr; ! 194: Button button; ! 195: if (buttonbox->updatemode == FALSE) { ! 196: buttonbox->needsadding = TRUE; ! 197: return; ! 198: } ! 199: position = 0; ! 200: ptr = arglist = (ArgList) ! 201: XtMalloc((unsigned)sizeof(Arg) * (buttonbox->numbuttons + 1)); ! 202: for (i=0 ; i<buttonbox->numbuttons ; i++) { ! 203: button = buttonbox->button[i]; ! 204: if (button->needsadding) { ! 205: if (ptr == arglist) { ! 206: ptr->name = XtNindex; ! 207: index = position; ! 208: ptr->value = (XtArgVal)index; ! 209: ptr++; ! 210: } ! 211: ptr->name = XtNwindow; ! 212: ptr->value = (XtArgVal)(button->window); ! 213: ptr++; ! 214: button->needsadding = FALSE; ! 215: } else if (ptr != arglist) { ! 216: (void)XtButtonBoxAddButton(DISPLAY buttonbox->inner, ! 217: arglist, ptr-arglist); ! 218: ptr = arglist; ! 219: } ! 220: position++; ! 221: } ! 222: if (ptr != arglist) { ! 223: (void)XtButtonBoxAddButton(DISPLAY buttonbox->inner, ! 224: arglist, ptr-arglist); ! 225: } ! 226: XtFree((char *) arglist); ! 227: buttonbox->needsadding = FALSE; ! 228: } ! 229: ! 230: ! 231: ! 232: /* Create a new button, and add it to a buttonbox. */ ! 233: ! 234: void BBoxAddButton(buttonbox, name, func, position, enabled) ! 235: ButtonBox buttonbox; ! 236: char *name; /* Name of button. */ ! 237: void (*func)(); /* Func to call when button pressed. */ ! 238: int position; /* Position to put button in box. */ ! 239: int enabled; /* Whether button is initially enabled. */ ! 240: { ! 241: extern void DoButtonPress(); ! 242: Button button; ! 243: int i; ! 244: static Arg arglist[] = { ! 245: {XtNname, NULL}, ! 246: {XtNfunction, (XtArgVal)DoButtonPress}, ! 247: {XtNparameter, NULL}, ! 248: }; ! 249: if (position > buttonbox->numbuttons) position = buttonbox->numbuttons; ! 250: buttonbox->numbuttons++; ! 251: buttonbox->button = (Button *) ! 252: XtRealloc((char *) buttonbox->button, ! 253: (unsigned) buttonbox->numbuttons * sizeof(Button)); ! 254: for (i=buttonbox->numbuttons-1 ; i>position ; i--) ! 255: buttonbox->button[i] = buttonbox->button[i-1]; ! 256: button = buttonbox->button[position] = ! 257: (Button) XtMalloc(sizeof(ButtonRec)); ! 258: bzero((char *) button, sizeof(ButtonRec)); ! 259: arglist[0].value = (XtArgVal)name; ! 260: arglist[2].value = (XtArgVal)button; ! 261: button->buttonbox = buttonbox; ! 262: button->name = MallocACopy(name); ! 263: button->window = XtCommandCreate(DISPLAY buttonbox->inner, arglist, ! 264: XtNumber(arglist)); ! 265: button->func = func; ! 266: button->needsadding = TRUE; ! 267: button->enabled = TRUE; ! 268: if (!enabled) BBoxDisable(button); ! 269: ProcessAddedButtons(buttonbox); ! 270: if (buttonbox->radio && *(buttonbox->radio) == NULL) { ! 271: *(buttonbox->radio) = button; ! 272: FlipColors(button); ! 273: } ! 274: } ! 275: ! 276: ! 277: ! 278: /* Remove the given button from its buttonbox. The button widget is ! 279: destroyed. If it was the current button in a radio buttonbox, then the ! 280: current button becomes the first button in the box. */ ! 281: ! 282: void BBoxDeleteButton(button) ! 283: Button button; ! 284: { ! 285: ButtonBox buttonbox = button->buttonbox; ! 286: int i, found, reradio; ! 287: static Arg arglist[] = { ! 288: {XtNwindow, (XtArgVal)NULL} ! 289: }; ! 290: found = FALSE; ! 291: for (i=0 ; i<buttonbox->numbuttons; i++) { ! 292: if (found) buttonbox->button[i-1] = buttonbox->button[i]; ! 293: else if (buttonbox->button[i] == button) { ! 294: found = TRUE; ! 295: arglist[0].value = (XtArgVal) button->window; ! 296: (void)XtButtonBoxDeleteButton(DISPLAY buttonbox->inner, ! 297: arglist, XtNumber(arglist)); ! 298: QXDestroyWindow(theDisplay, button->window); ! 299: (void) XtSendDestroyNotify(DISPLAY button->window); ! 300: reradio = (buttonbox->radio && *(buttonbox->radio) == button); ! 301: FreeButton(button); ! 302: } ! 303: } ! 304: if (found) { ! 305: buttonbox->numbuttons--; ! 306: if (reradio) { ! 307: *(buttonbox->radio) = NULL; ! 308: if (buttonbox->numbuttons) ! 309: BBoxSetRadio(buttonbox, buttonbox->button[0]); ! 310: } ! 311: } ! 312: } ! 313: ! 314: ! 315: ! 316: /* Enable or disable the given command button widget. */ ! 317: ! 318: static void SendEnableMsg(window, value) ! 319: Window window; ! 320: int value; /* TRUE for enable, FALSE for disable. */ ! 321: { ! 322: static Arg arglist[] = {XtNsensitive, NULL}; ! 323: arglist[0].value = (XtArgVal) value; ! 324: XtCommandSetValues(DISPLAY window, arglist, XtNumber(arglist)); ! 325: } ! 326: ! 327: ! 328: ! 329: /* Enable the given button (if it's not already). */ ! 330: ! 331: void BBoxEnable(button) ! 332: Button button; ! 333: { ! 334: if (!button->enabled) { ! 335: button->enabled = TRUE; ! 336: SendEnableMsg(button->window, TRUE); ! 337: } ! 338: } ! 339: ! 340: ! 341: ! 342: /* Disable the given button (if it's not already). */ ! 343: ! 344: void BBoxDisable(button) ! 345: Button button; ! 346: { ! 347: if (button->enabled) { ! 348: button->enabled = FALSE; ! 349: SendEnableMsg(button->window, FALSE); ! 350: } ! 351: } ! 352: ! 353: ! 354: /* Given a buttonbox and a button name, find the button in the box with that ! 355: short name. */ ! 356: ! 357: Button BBoxFindButtonNamed(buttonbox, name) ! 358: ButtonBox buttonbox; ! 359: char *name; ! 360: { ! 361: int i; ! 362: for (i=0 ; i<buttonbox->numbuttons; i++) ! 363: if (strcmp(name, buttonbox->button[i]->name) == 0) ! 364: return buttonbox->button[i]; ! 365: return NULL; ! 366: } ! 367: ! 368: ! 369: ! 370: /* Return the nth button in the given buttonbox. */ ! 371: ! 372: Button BBoxButtonNumber(buttonbox, n) ! 373: ButtonBox buttonbox; ! 374: int n; ! 375: { ! 376: return buttonbox->button[n]; ! 377: } ! 378: ! 379: ! 380: ! 381: /* Return how many buttons are in a buttonbox. */ ! 382: ! 383: int BBoxNumButtons(buttonbox) ! 384: ButtonBox buttonbox; ! 385: { ! 386: return buttonbox->numbuttons; ! 387: } ! 388: ! 389: ! 390: /* Given a button, return its name. */ ! 391: ! 392: char *BBoxNameOfButton(button) ! 393: Button button; ! 394: { ! 395: return button->name; ! 396: } ! 397: ! 398: ! 399: ! 400: /* The client calls this routine before doing massive updates to a buttonbox. ! 401: It then must call BBoxStartUpdate when it's finished. This allows us to ! 402: optimize things. Right now, the only optimization performed is to batch ! 403: together requests to add buttons to a buttonbox. */ ! 404: ! 405: void BBoxStopUpdate(buttonbox) ! 406: ButtonBox buttonbox; ! 407: { ! 408: buttonbox->updatemode = FALSE; ! 409: } ! 410: ! 411: ! 412: ! 413: /* The client has finished its massive updates; go and handle any batched ! 414: requests. */ ! 415: ! 416: void BBoxStartUpdate(buttonbox) ! 417: ButtonBox buttonbox; ! 418: { ! 419: buttonbox->updatemode = TRUE; ! 420: if (buttonbox->needsadding) ProcessAddedButtons(buttonbox); ! 421: } ! 422: ! 423: ! 424: ! 425: /* Set things to always display the entire contents of this buttonbox. In ! 426: otherwords, tells the VPane to not let the user make this pane any smaller ! 427: than the buttonbox. */ ! 428: ! 429: void BBoxForceFullSize(buttonbox) ! 430: ButtonBox buttonbox; ! 431: { ! 432: #ifdef X10 /* X10 toolkit doesn't have magic configurenotify events */ ! 433: WindowInfo info; ! 434: XQueryWindow(buttonbox->inner, &info); ! 435: buttonbox->maxheight = info.height; ! 436: #endif ! 437: XtVPanedSetMinMax(DISPLAY buttonbox->scrn->window, buttonbox->outer, ! 438: buttonbox->maxheight, buttonbox->maxheight); ! 439: buttonbox->fullsized = TRUE; ! 440: } ! 441: ! 442: ! 443: /* Set things to allow the user to show only part of a buttonbox. This is the ! 444: default action. */ ! 445: ! 446: void BBoxAllowAnySize(buttonbox) ! 447: ButtonBox buttonbox; ! 448: { ! 449: #ifdef X10 ! 450: BBoxForceFullSize(buttonbox); /* VERY hackish; works only because of the ! 451: limited way I use BBoxForceFullSize.%%% */ ! 452: #endif ! 453: XtVPanedSetMinMax(DISPLAY buttonbox->scrn->window, buttonbox->outer, ! 454: 5, buttonbox->maxheight); ! 455: buttonbox->fullsized = FALSE; ! 456: } ! 457: ! 458: ! 459: ! 460: /* Destroy the given buttonbox. */ ! 461: ! 462: void BBoxDeleteBox(buttonbox) ! 463: ButtonBox buttonbox; ! 464: { ! 465: if (buttonbox->radio) *(buttonbox->radio) = NULL; ! 466: QXDestroyWindow(theDisplay, buttonbox->outer); ! 467: (void) XtSendDestroyNotify(DISPLAY buttonbox->outer); ! 468: } ! 469: ! 470: ! 471: ! 472: /* Change the borderwidth of the given button. */ ! 473: ! 474: void BBoxChangeBorderWidth(button, borderWidth) ! 475: Button button; ! 476: unsigned int borderWidth; ! 477: { ! 478: #ifdef X11 ! 479: XSetWindowBorderWidth(DISPLAY button->window, borderWidth); ! 480: #endif ! 481: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.