|
|
1.1 ! root 1: /* $Header: VPane.c,v 1.1 87/09/11 07:59:07 toddb Exp $ */ ! 2: #ifndef lint ! 3: static char *sccsid = "@(#)VPane.c 1.10 2/25/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: /* VPane.c */ ! 31: ! 32: #include "Xlib.h" ! 33: #include "cursorfont.h" ! 34: #include "Intrinsic.h" ! 35: #include "VPane.h" ! 36: #include "Atoms.h" ! 37: ! 38: /* Private definitions. */ ! 39: ! 40: ! 41: #define BORDERWIDTH 1 /* Size of borders between panes. */ ! 42: /* %%% Should not be a constant! */ ! 43: #define DEFAULTKNOBWIDTH 9 ! 44: #define DEFAULTKNOBHEIGHT 9 ! 45: #define DEFAULTKNOBINDENT 16 ! 46: ! 47: typedef struct { ! 48: Display *dpy; /* Display connection */ ! 49: Window w; /* Subwindow */ ! 50: Position y; /* Location in master window */ ! 51: Position dy; /* Desired location. */ ! 52: Position olddy; /* The last value of dy. */ ! 53: Dimension min, max; /* Minimum and maximum height. */ ! 54: short autochange; /* Whether we're allowed to change this */ ! 55: /* subwindow's height without an */ ! 56: /* explicite command from user. */ ! 57: Dimension height; /* Current height. */ ! 58: Dimension dheight; /* Desired height. */ ! 59: Window knob; /* The knob for this subwindow. */ ! 60: Boolean allowresize; /* Whether we should honor geometry requests */ ! 61: /* from this window to change its height. */ ! 62: } SubWindowInfo, *SubWindowPtr; ! 63: ! 64: typedef struct { ! 65: Display *dpy; /* display connection for paned window */ ! 66: Window ourparent; /* Parent of the paned window. */ ! 67: Window window; /* Window containing everything. */ ! 68: Pixel foregroundpixel; /* Foreground pixmap. */ ! 69: Pixel backgroundpixel; /* Background pixmap. */ ! 70: Position x, y; /* Location of master window. */ ! 71: Dimension width, height; /* Dimension of master window. */ ! 72: Dimension borderWidth; /* Borderwidth of master window. */ ! 73: Dimension borderpixel; /* Color of border of master window. */ ! 74: Dimension knobwidth, knobheight; /* Dimension of knobs. */ ! 75: Position knobindent; /* Location of knobs (offset from */ ! 76: /* right margin.) */ ! 77: Pixel knobpixel; /* Color of knobs. */ ! 78: Dimension heightused; /* Total height used by subwindows. */ ! 79: int numsubwindows; /* How many windows within it. */ ! 80: SubWindowInfo *sub; /* Array of info about the sub windows. */ ! 81: int whichtracking; /* Which knob we are tracking, if any */ ! 82: Position starty; /* Starting y value. */ ! 83: int whichdirection; /* Which direction to refigure things in. */ ! 84: SubWindowPtr whichadd; /* Which subwindow to add changes to. */ ! 85: SubWindowPtr whichsub; /* Which subwindow to sub changes from. */ ! 86: Boolean refiguremode; /* Whether to refigure things right now. */ ! 87: GC normgc; /* GC to use when redrawing borders. */ ! 88: GC invgc; /* GC to use when erasing borders. */ ! 89: GC flipgc; /* GC to use when animating borders. */ ! 90: } WidgetDataRec, *WidgetData; ! 91: ! 92: static WidgetDataRec globaldata, globaldatainit; ! 93: ! 94: static Resource resources[] = { ! 95: {XtNwindow, XtCWindow, XrmRWindow, sizeof(Window), ! 96: (caddr_t)&globaldata.window, NULL}, ! 97: {XtNforeground, XtCColor, XrmRPixel, sizeof(int), ! 98: (caddr_t)&globaldata.foregroundpixel, (caddr_t)&XtDefaultFGPixel}, ! 99: {XtNbackground, XtCColor, XrmRPixel, sizeof(int), ! 100: (caddr_t)&globaldata.backgroundpixel, (caddr_t)&XtDefaultBGPixel}, ! 101: {XtNx, XtCX, XrmRInt, sizeof(int), ! 102: (caddr_t)&globaldata.x, NULL}, ! 103: {XtNy, XtCY, XrmRInt, sizeof(int), ! 104: (caddr_t)&globaldata.y, NULL}, ! 105: {XtNwidth, XtCWidth, XrmRInt, sizeof(int), ! 106: (caddr_t)&globaldata.width, NULL}, ! 107: {XtNheight, XtCHeight, XrmRInt, sizeof(int), ! 108: (caddr_t)&globaldata.height, NULL}, ! 109: {XtNborderWidth, XtCBorderWidth, XrmRInt, sizeof(int), ! 110: (caddr_t)&globaldata.borderWidth, NULL}, ! 111: {XtNborder, XtCColor, XrmRPixmap, sizeof(int), ! 112: (caddr_t)&globaldata.borderpixel, (caddr_t)&XtDefaultFGPixel}, ! 113: {XtNknobWidth, XtCWidth, XrmRInt, sizeof(int), ! 114: (caddr_t)&globaldata.knobwidth, NULL}, ! 115: {XtNknobHeight, XtCHeight, XrmRInt, sizeof(int), ! 116: (caddr_t)&globaldata.knobheight, NULL}, ! 117: {XtNknobIndent, XtCKnobIndent, XrmRInt, sizeof(int), ! 118: (caddr_t)&globaldata.knobindent, NULL}, ! 119: {XtNknobPixel, XtCKnobPixel, XrmRPixel, sizeof(int), ! 120: (caddr_t)&globaldata.knobpixel, (caddr_t)&globaldata.foregroundpixel}, ! 121: }; ! 122: ! 123: static XContext widgetContext; ! 124: static int CursorNums[4] = {0, ! 125: XC_sb_up_arrow, ! 126: XC_sb_v_double_arrow, ! 127: XC_sb_down_arrow}; ! 128: ! 129: static WidgetData DataFromWindow(dpy, w) ! 130: Display *dpy; ! 131: Window w; ! 132: { ! 133: WidgetData data; ! 134: if (XFindContext(dpy, w, widgetContext, (caddr_t *) &data)) return 0; ! 135: return data; ! 136: } ! 137: ! 138: static void TryResize(data, newwidth, newheight) ! 139: WidgetData data; ! 140: Dimension newwidth, newheight; ! 141: { ! 142: WindowBox requestBox, replyBox; ! 143: XtGeometryReturnCode result; ! 144: requestBox.x = 0; ! 145: requestBox.y = 0; ! 146: if (newwidth < 1) newwidth = 1; ! 147: if (newheight < 1) newheight = 1; ! 148: requestBox.width = newwidth; ! 149: requestBox.height = newheight; ! 150: result = XtMakeGeometryRequest(data->dpy, data->window, XtgeometryResize, ! 151: &requestBox, &replyBox); ! 152: if (result == XtgeometryAlmost) { ! 153: requestBox = replyBox; ! 154: result = XtMakeGeometryRequest(data->dpy, data->window, XtgeometryResize, ! 155: &requestBox, &replyBox); ! 156: } ! 157: if (result == XtgeometryYes) { ! 158: data->width = replyBox.width; ! 159: data->height = replyBox.height; ! 160: } ! 161: } ! 162: ! 163: ! 164: static RefigureLocations(data, position, dir) ! 165: WidgetData data; ! 166: int position; ! 167: int dir; /* -1 = up, 1 = down, 0 = this border only */ ! 168: { ! 169: SubWindowPtr sub, firstsub; ! 170: int i, old, y, cdir; ! 171: if (data->numsubwindows == 0 || !data->refiguremode) ! 172: return; ! 173: do { ! 174: data->heightused = 0; ! 175: for (i = 0, sub = data->sub; i < data->numsubwindows; i++, sub++) { ! 176: if (sub->dheight < sub->min) ! 177: sub->dheight = sub->min; ! 178: if (sub->dheight > sub->max) ! 179: sub->dheight = sub->max; ! 180: data->heightused += sub->dheight; ! 181: } ! 182: data->heightused += BORDERWIDTH * (data->numsubwindows - 1); ! 183: if (dir == 0 && data->heightused != data->height) { ! 184: for (i = 0, sub = data->sub; i < data->numsubwindows; i++, sub++) ! 185: if (sub->dheight != sub->height) ! 186: sub->dheight += data->height - data->heightused; ! 187: } ! 188: } while (dir == 0 && data->heightused != data->height); ! 189: ! 190: firstsub = data->sub + position; ! 191: sub = firstsub; ! 192: cdir = dir; ! 193: while (data->heightused != data->height) { ! 194: if (sub->autochange || cdir != dir) { ! 195: old = sub->dheight; ! 196: sub->dheight = data->height - data->heightused + old; ! 197: if (sub->dheight < sub->min) ! 198: sub->dheight = sub->min; ! 199: if (sub->dheight > sub->max) ! 200: sub->dheight = sub->max; ! 201: data->heightused += (sub->dheight - old); ! 202: } ! 203: sub += cdir; ! 204: while (sub < data->sub || sub - data->sub == data->numsubwindows) { ! 205: cdir = -cdir; ! 206: if (cdir == dir) goto doublebreak; ! 207: sub = firstsub + cdir; ! 208: } ! 209: } ! 210: doublebreak: ! 211: y = -BORDERWIDTH; ! 212: for (i = 0, sub = data->sub; i < data->numsubwindows; i++, sub++) { ! 213: sub->dy = y; ! 214: y += sub->dheight + BORDERWIDTH; ! 215: } ! 216: } ! 217: ! 218: ! 219: static CommitNewLocations(data) ! 220: WidgetData data; ! 221: { ! 222: int i, kx, ky; ! 223: SubWindowPtr sub; ! 224: if (data->heightused != data->height) ! 225: TryResize(data, data->width, data->height); ! 226: for (i = 0, sub = data->sub; i < data->numsubwindows; i++, sub++) { ! 227: if (sub->dy != sub->y || sub->dheight != sub->height) { ! 228: WindowBox box; ! 229: XMoveResizeWindow(data->dpy, sub->w, ! 230: box.x = -BORDERWIDTH, ! 231: box.y = sub->dy, ! 232: box.width = data->width, ! 233: box.height = sub->dheight); ! 234: sub->y = sub->dy; ! 235: sub->height = sub->dheight; ! 236: (void) XtSendConfigureNotify(data->dpy, sub->w, &box); ! 237: kx = data->width - data->knobindent; ! 238: ky = sub->y + sub->height - (data->knobheight/2)+1; ! 239: if (i == data->numsubwindows - 1) ! 240: ky = -99; /* Keep the last knob hidden. */ ! 241: XMoveWindow(data->dpy, sub->knob, kx, ky); ! 242: XRaiseWindow(data->dpy,sub->knob); ! 243: ! 244: } ! 245: } ! 246: /* kx = data->width - data->knobindent; ! 247: for (i = 0, sub = data->sub; i < data->numsubwindows; i++, sub++) { ! 248: ky = sub->y + sub->height - (data->knobheight / 2) + 1; ! 249: if (i == data->numsubwindows - 1) ! 250: ky = -99; ! 251: XMoveWindow(data->dpy, sub->knob, kx, ky); ! 252: XRaiseWindow(data->dpy, sub->knob); ! 253: }*/ ! 254: } ! 255: ! 256: ! 257: static RefigureLocationsAndCommit(data, position, dir) ! 258: WidgetData data; ! 259: int position, dir; ! 260: { ! 261: RefigureLocations(data, position, dir); ! 262: CommitNewLocations(data); ! 263: } ! 264: ! 265: ! 266: EraseInternalBorders(data) ! 267: WidgetData data; ! 268: { ! 269: int i; ! 270: for (i = 1; i < data->numsubwindows; i++) ! 271: XFillRectangle(data->dpy, data->window, data->invgc, ! 272: 0, data->sub[i].y, data->width, BORDERWIDTH); ! 273: } ! 274: ! 275: ! 276: DrawInternalBorders(data) ! 277: WidgetData data; ! 278: { ! 279: int i; ! 280: for (i = 1; i < data->numsubwindows; i++) ! 281: XFillRectangle(data->dpy, data->window, data->normgc, ! 282: 0, data->sub[i].y, data->width, BORDERWIDTH); ! 283: } ! 284: ! 285: ! 286: static DrawTrackLines(data) ! 287: WidgetData data; ! 288: { ! 289: int i; ! 290: SubWindowPtr sub; ! 291: for (i = 1, sub = data->sub + 1; i < data->numsubwindows; i++, sub++) { ! 292: if (sub->olddy != sub->dy) { ! 293: XDrawLine(data->dpy, data->window, data->flipgc, ! 294: 0, sub->olddy, (Position) data->width, sub->olddy); ! 295: XDrawLine(data->dpy, data->window, data->flipgc, ! 296: 0, sub->dy, (Position) data->width, sub->dy); ! 297: sub->olddy = sub->dy; ! 298: } ! 299: } ! 300: } ! 301: ! 302: static EraseTrackLines(data) ! 303: WidgetData data; ! 304: { ! 305: int i; ! 306: SubWindowPtr sub; ! 307: for (i = 1, sub = data->sub + 1; i < data->numsubwindows; i++, sub++) ! 308: XDrawLine(data->dpy, data->window, data->flipgc, ! 309: 0, sub->olddy, (Position) data->width, sub->olddy); ! 310: } ! 311: ! 312: ! 313: /* Semi-public routines. */ ! 314: ! 315: static XtGeometryReturnCode PanedWindowGeometryRequest( ! 316: dpy, w, request, reqBox, replBox) ! 317: Display *dpy; ! 318: Window w; ! 319: XtGeometryRequest request; ! 320: WindowBox *reqBox, *replBox; ! 321: { ! 322: WidgetData data; ! 323: int i; ! 324: SubWindowPtr sub; ! 325: ! 326: data = DataFromWindow(dpy, w); ! 327: if (!data) return XtgeometryNo; ! 328: for (i=0 ; i<data->numsubwindows ; i++) ! 329: if (data->sub[i].w == w) break; ! 330: if (i >= data->numsubwindows) return XtgeometryNo; ! 331: sub = data->sub + i; ! 332: if (request == XtgeometryResize) { ! 333: if (!sub->allowresize) return XtgeometryNo; ! 334: if (data->width != reqBox->width) { ! 335: if (sub->height == reqBox->height) ! 336: return XtgeometryNo; ! 337: *replBox = *reqBox; ! 338: replBox->width = data->width; ! 339: return XtgeometryAlmost; ! 340: } ! 341: if (sub->min == sub->height || sub->min > reqBox->height) ! 342: sub->min = reqBox->height; ! 343: if (sub->max == sub->height || sub->max < reqBox->height) ! 344: sub->max = reqBox->height; ! 345: sub->dheight = reqBox->height; ! 346: RefigureLocationsAndCommit(data, i, 1); ! 347: return XtgeometryYes; ! 348: } ! 349: if (request == XtgeometryGetWindowBox) { ! 350: replBox->x = -BORDERWIDTH; ! 351: replBox->y = sub->y; ! 352: replBox->width = data->width; ! 353: replBox->height = sub->height; ! 354: replBox->borderWidth = BORDERWIDTH; ! 355: return XtgeometryYes; ! 356: } ! 357: return XtgeometryNo; ! 358: } ! 359: ! 360: static XtEventReturnCode HandleEvents(event) ! 361: XEvent *event; ! 362: { ! 363: WidgetData data; ! 364: WindowBox box; ! 365: int i; ! 366: ! 367: data = DataFromWindow(event->xany.display, event->xany.window); ! 368: if (!data) return XteventNotHandled; ! 369: switch (event->type) { ! 370: case ConfigureNotify: ! 371: if (data->width != event->xconfigure.width || ! 372: data->height != event->xconfigure.height) { ! 373: if (data->width != event->xconfigure.width) { ! 374: box.x = -BORDERWIDTH; ! 375: box.width = event->xconfigure.width; ! 376: box.borderWidth = BORDERWIDTH; ! 377: for (i = 0; i < data->numsubwindows; i++) { ! 378: XResizeWindow(data->dpy, data->sub[i].w, ! 379: (Dimension) event->xconfigure.width, ! 380: (Dimension) data->sub[i].height); ! 381: box.y = data->sub[i].y; ! 382: box.height = data->sub[i].height; ! 383: (void) XtSendConfigureNotify(data->dpy, data->sub[i].w, ! 384: &box); ! 385: } ! 386: } ! 387: data->width = event->xconfigure.width; ! 388: data->height = event->xconfigure.height; ! 389: RefigureLocationsAndCommit(data, data->numsubwindows - 1, -1); ! 390: } ! 391: data->x = event->xconfigure.x; ! 392: data->y = event->xconfigure.y; ! 393: data->borderWidth = event->xconfigure.border_width; ! 394: return XteventHandled; ! 395: case DestroyNotify: ! 396: data->refiguremode = FALSE; ! 397: for (i = data->numsubwindows-1 ; i >= 0 ; i--) ! 398: (void) XtSendDestroyNotify(data->dpy, data->sub[i].w); ! 399: (void) XDeleteContext(data->dpy, data->window, widgetContext); ! 400: XtClearEventHandlers(data->dpy, data->window); ! 401: XtFree((char *)data->sub); ! 402: XtFree((char *)data); ! 403: return XteventHandled; ! 404: } ! 405: return XteventNotHandled; ! 406: } ! 407: ! 408: static XtEventReturnCode HandleSubwindow(event) ! 409: XEvent *event; ! 410: { ! 411: WidgetData data; ! 412: if (event->type == DestroyNotify) { ! 413: data = DataFromWindow(event->xdestroywindow.display, event->xdestroywindow.window); ! 414: if (data) { ! 415: XtVPanedWindowDeletePane(data->dpy, data->window, ! 416: event->xdestroywindow.window); ! 417: return XteventHandled; ! 418: } ! 419: } ! 420: return XteventNotHandled; ! 421: } ! 422: ! 423: static XtEventReturnCode HandleKnob(event) ! 424: XEvent *event; ! 425: { ! 426: WidgetData data; ! 427: int position, diff, y, i; ! 428: ! 429: data = DataFromWindow(event->xbutton.display, event->xbutton.window); ! 430: if (!data) return XteventNotHandled; ! 431: switch (event->type) { ! 432: case ButtonPress: ! 433: y = event->xbutton.y; ! 434: if (data->whichtracking != -1) ! 435: return XteventNotHandled; ! 436: for (position = 0; position < data->numsubwindows; position++) ! 437: if (data->sub[position].knob == event->xbutton.window) ! 438: break; ! 439: if (position >= data->numsubwindows) ! 440: return XteventNotHandled; ! 441: ! 442: (void) XGrabPointer(data->dpy, event->xbutton.window, FALSE, ! 443: (unsigned int)PointerMotionMask | ButtonReleaseMask, ! 444: GrabModeAsync, GrabModeAsync, None, ! 445: XtGetCursor(data->dpy, ! 446: CursorNums[event->xbutton.button]), ! 447: CurrentTime); ! 448: data->whichadd = data->whichsub = NULL; ! 449: data->whichdirection = 2 - event->xbutton.button;/* Hack! */ ! 450: data->starty = y; ! 451: if (data->whichdirection >= 0) { ! 452: data->whichadd = data->sub + position; ! 453: while (data->whichadd->max == data->whichadd->min && ! 454: data->whichadd > data->sub) ! 455: (data->whichadd)--; ! 456: } ! 457: if (data->whichdirection <= 0) { ! 458: data->whichsub = data->sub + position + 1; ! 459: while (data->whichsub->max == data->whichsub->min && ! 460: data->whichsub < data->sub + data->numsubwindows - 1) ! 461: (data->whichsub)++; ! 462: } ! 463: data->whichtracking = position; ! 464: if (data->whichdirection == 1) ! 465: (data->whichtracking)++; ! 466: EraseInternalBorders(data); ! 467: for (i = 0; i < data->numsubwindows; i++) ! 468: data->sub[i].olddy = -99; ! 469: /* Fall through */ ! 470: ! 471: case MotionNotify: ! 472: case ButtonRelease: ! 473: if (event->type == MotionNotify) y = event->xmotion.y; ! 474: else y = event->xbutton.y; ! 475: if (data->whichtracking == -1) ! 476: return XteventNotHandled; ! 477: for (i = 0; i < data->numsubwindows; i++) ! 478: data->sub[i].dheight = data->sub[i].height; ! 479: diff = y - data->starty; ! 480: if (data->whichadd) ! 481: data->whichadd->dheight = data->whichadd->height + diff; ! 482: if (data->whichsub) ! 483: data->whichsub->dheight = data->whichsub->height - diff; ! 484: RefigureLocations(data, data->whichtracking, data->whichdirection); ! 485: ! 486: if (event->type != ButtonRelease) { ! 487: DrawTrackLines(data);/* Draw new borders */ ! 488: return XteventHandled; ! 489: } ! 490: XUngrabPointer(data->dpy, CurrentTime); ! 491: EraseTrackLines(data); ! 492: CommitNewLocations(data); ! 493: DrawInternalBorders(data); ! 494: data->whichtracking = -1; ! 495: return XteventHandled; ! 496: } ! 497: return XteventNotHandled; ! 498: } ! 499: ! 500: ! 501: /* Public routines. */ ! 502: ! 503: static Boolean initialized = FALSE; ! 504: ! 505: extern void VPanedInitialize() ! 506: { ! 507: if (initialized) ! 508: return; ! 509: initialized = TRUE; ! 510: ! 511: widgetContext = XUniqueContext(); ! 512: globaldatainit.window = NULL; ! 513: globaldatainit.x = globaldatainit.y = 0; ! 514: globaldatainit.width = globaldatainit.height = 10; ! 515: globaldatainit.borderWidth = 1; ! 516: globaldatainit.knobwidth = DEFAULTKNOBWIDTH; ! 517: globaldatainit.knobheight = DEFAULTKNOBHEIGHT; ! 518: globaldatainit.knobindent = DEFAULTKNOBINDENT; ! 519: } ! 520: ! 521: ! 522: Window XtVPanedWindowCreate(dpy, parent, args, argCount) ! 523: Display *dpy; ! 524: Window parent; ! 525: ArgList args; ! 526: int argCount; ! 527: { ! 528: WidgetData data; ! 529: XrmNameList names; ! 530: XrmClassList classes; ! 531: unsigned long valuemask; ! 532: XSetWindowAttributes wvals; ! 533: XGCValues values; ! 534: ! 535: if (!initialized) VPanedInitialize(); ! 536: ! 537: data = (WidgetData) XtMalloc(sizeof(WidgetDataRec)); ! 538: globaldata = globaldatainit; ! 539: globaldata.dpy = dpy; ! 540: XtGetResources(dpy, resources, XtNumber(resources), args, argCount, parent, ! 541: "vpane", "VPane", &names, &classes); ! 542: *data = globaldata; ! 543: ! 544: wvals.background_pixel = data->backgroundpixel; ! 545: wvals.border_pixel = data->borderpixel; ! 546: wvals.bit_gravity = NorthWestGravity; ! 547: valuemask = CWBackPixel | CWBorderPixel | CWBitGravity; ! 548: ! 549: if (data->window != NULL) { ! 550: Drawable root; ! 551: Position x, y; ! 552: unsigned int depth; ! 553: (void) XGetGeometry(data->dpy, data->window, &root, &x, &y, ! 554: &(data->width), &(data->height), &(data->borderWidth), ! 555: &depth); ! 556: XReparentWindow(data->dpy, data->window, parent, data->x, data->y); ! 557: XChangeWindowAttributes(data->dpy, data->window, valuemask, &wvals); ! 558: } else { ! 559: data->window = XCreateWindow(data->dpy, parent, data->x, data->y, ! 560: data->width, data->height, data->borderWidth, ! 561: (int) CopyFromParent, InputOutput, ! 562: (Visual *) CopyFromParent, valuemask, &wvals); ! 563: } ! 564: ! 565: values.foreground = data->foregroundpixel; ! 566: values.function = GXcopy; ! 567: values.plane_mask = ~0; ! 568: values.fill_style = FillSolid; ! 569: values.fill_rule = EvenOddRule; ! 570: values.subwindow_mode = IncludeInferiors; ! 571: valuemask = GCForeground | GCFunction | GCPlaneMask | GCFillStyle ! 572: | GCFillRule | GCSubwindowMode; ! 573: data->normgc = XtGetGC(dpy, widgetContext, data->window, valuemask, &values); ! 574: values.foreground = data->backgroundpixel; ! 575: data->invgc = XtGetGC(dpy, widgetContext, data->window, valuemask, &values); ! 576: values.function = GXinvert; ! 577: #if BORDERWIDTH == 1 ! 578: values.line_width = 0; /* Take advantage of fast server lines. */ ! 579: #else ! 580: values.line_width = BORDERWIDTH; ! 581: #endif ! 582: values.line_style = LineSolid; ! 583: valuemask |= GCLineWidth | GCLineStyle; ! 584: data->flipgc = XtGetGC(dpy, widgetContext, data->window, valuemask, &values); ! 585: ! 586: XtSetNameAndClass(data->dpy, data->window, names, classes); ! 587: XrmFreeNameList(names); ! 588: XrmFreeClassList(classes); ! 589: data->heightused = 0; ! 590: data->numsubwindows = 0; ! 591: data->sub = (SubWindowInfo *) XtMalloc(1); ! 592: data->whichtracking = -1; ! 593: data->refiguremode = TRUE; ! 594: (void) XSaveContext(data->dpy, data->window, widgetContext, (caddr_t) data); ! 595: (void) XtSetEventHandler(data->dpy, data->window, HandleEvents, StructureNotifyMask, ! 596: (caddr_t) NULL); ! 597: return data->window; ! 598: } ! 599: ! 600: ! 601: void XtVPanedWindowDelete(dpy, w) ! 602: Display *dpy; ! 603: Window w; ! 604: { ! 605: WidgetData data; ! 606: int i; ! 607: data = DataFromWindow(dpy, w); ! 608: XUnmapWindow(data->dpy, w); ! 609: for (i=data->numsubwindows-1 ; i>=0 ; i--) ! 610: XtVPanedWindowDeletePane(dpy, w, data->sub[i].w); ! 611: (void) XDeleteContext(dpy, w, widgetContext); ! 612: XtFree((char *) data->sub); ! 613: XtFree((char *) data); ! 614: } ! 615: ! 616: ! 617: ! 618: void XtVPanedWindowAddPane( ! 619: dpy, parent, paneWindow, position, min, max, autochange) ! 620: Display *dpy; ! 621: Window parent, paneWindow; ! 622: int position, min, max, autochange; ! 623: { ! 624: WidgetData data; ! 625: Drawable root; ! 626: int i; ! 627: Position x; ! 628: Dimension width, borderWidth, needed; ! 629: unsigned int depth; ! 630: SubWindowPtr sub; ! 631: data = DataFromWindow(dpy, parent); ! 632: if (!data) return; ! 633: if (position > 0 && position == data->numsubwindows) ! 634: data->sub[position - 1].y = -99; /* HACK to make knob reappear. */ ! 635: data->numsubwindows++; ! 636: data->sub = (SubWindowPtr) ! 637: XtRealloc((char *) data->sub, ! 638: (unsigned) data->numsubwindows * sizeof(SubWindowInfo)); ! 639: for (i = data->numsubwindows - 1; i > position; i--) ! 640: data->sub[i] = data->sub[i - 1]; ! 641: sub = &(data->sub[position]); ! 642: sub->w = paneWindow; ! 643: (void) XGetGeometry(data->dpy, paneWindow, &root, &x, &(sub->y), ! 644: &width, &(sub->height), &borderWidth, &depth); ! 645: XReparentWindow(data->dpy, paneWindow, data->window, -BORDERWIDTH, ! 646: sub->y); ! 647: sub->dheight = sub->height; ! 648: if (width != data->width || borderWidth != BORDERWIDTH) { ! 649: XWindowChanges changes; ! 650: changes.width = data->width; ! 651: changes.border_width = BORDERWIDTH; ! 652: XConfigureWindow(data->dpy, paneWindow, ! 653: (unsigned int) CWWidth | CWBorderWidth, &changes); ! 654: } ! 655: sub->min = min; ! 656: sub->max = max; ! 657: sub->autochange = autochange; ! 658: needed = sub->height + BORDERWIDTH + data->heightused; ! 659: if (needed > data->height) ! 660: TryResize(data, data->width, needed); ! 661: (void) XtSetGeometryHandler(data->dpy, paneWindow, PanedWindowGeometryRequest); ! 662: sub->knob = XCreateSimpleWindow(data->dpy, data->window, -99, -99, ! 663: data->knobwidth, data->knobheight, ! 664: 0, (Pixel) 0, data->knobpixel); ! 665: (void) XSaveContext(dpy, sub->w, widgetContext, (caddr_t) data); ! 666: (void) XSaveContext(dpy, sub->knob, widgetContext, (caddr_t) data); ! 667: XDefineCursor(data->dpy, sub->knob, XtGetCursor(dpy, XC_double_arrow)); ! 668: XMapWindow(data->dpy, sub->w); ! 669: XMapWindow(data->dpy, sub->knob); ! 670: (void) XtSetEventHandler(dpy, sub->w, HandleSubwindow, StructureNotifyMask, ! 671: (caddr_t) NULL); ! 672: (void) XtSetEventHandler(dpy, sub->knob, HandleKnob, ! 673: ButtonPressMask | ButtonReleaseMask | ButtonMotionMask, ! 674: (caddr_t) NULL); ! 675: RefigureLocationsAndCommit(data, position, 1); ! 676: for (i=0 ; i<data->numsubwindows; i++) ! 677: XRaiseWindow(data->dpy, data->sub[i].knob); ! 678: } ! 679: ! 680: ! 681: /* Change the min and max size of the given sub window. */ ! 682: ! 683: void XtVPanedSetMinMax(dpy, w, paneWindow, min, max) ! 684: Display *dpy; ! 685: Window w, paneWindow; ! 686: int min, max; ! 687: { ! 688: WidgetData data; ! 689: int i; ! 690: data = DataFromWindow(dpy, w); ! 691: if (!data) ! 692: return; ! 693: for (i = 0; i < data->numsubwindows; i++) { ! 694: if (data->sub[i].w == paneWindow) { ! 695: data->sub[i].min = min; ! 696: data->sub[i].max = max; ! 697: RefigureLocationsAndCommit(data, i, 1); ! 698: return; ! 699: } ! 700: } ! 701: } ! 702: ! 703: ! 704: /* Get the min and max size of the given sub window. */ ! 705: ! 706: void XtVPanedGetMinMax(dpy, w, paneWindow, min, max) ! 707: Display *dpy; ! 708: Window w, paneWindow; ! 709: int *min, *max; ! 710: { ! 711: WidgetData data; ! 712: int i; ! 713: data = DataFromWindow(dpy, w); ! 714: if (!data) ! 715: return; ! 716: for (i = 0; i < data->numsubwindows; i++) { ! 717: if (data->sub[i].w == paneWindow) { ! 718: *min = data->sub[i].min; ! 719: *max = data->sub[i].max; ! 720: return; ! 721: } ! 722: } ! 723: } ! 724: ! 725: ! 726: ! 727: /* Delete the given paneWindow from the given paned window. Doesn't actually ! 728: destroy the paneWindow. */ ! 729: ! 730: void XtVPanedWindowDeletePane(dpy, w, paneWindow) ! 731: Display *dpy; ! 732: Window w, paneWindow; ! 733: { ! 734: WidgetData data; ! 735: int i; ! 736: Boolean j; ! 737: ! 738: data = DataFromWindow(dpy, w); ! 739: if (!data) ! 740: return; ! 741: j = FALSE; ! 742: for (i = 0; i < data->numsubwindows; i++) { ! 743: if (data->sub[i].w == paneWindow) { ! 744: j = TRUE; ! 745: (void) XDeleteContext(dpy, data->sub[i].w, widgetContext); ! 746: (void) XDeleteContext(dpy, data->sub[i].knob, widgetContext); ! 747: (void) XtSetEventHandler(dpy, data->sub[i].w, HandleSubwindow, ! 748: (unsigned long) NULL, (caddr_t) NULL); ! 749: XtClearEventHandlers(dpy, data->sub[i].knob); ! 750: XDestroyWindow(data->dpy, data->sub[i].knob); ! 751: TryResize(data, data->width, ! 752: data->height - data->sub[i].height - BORDERWIDTH); ! 753: } ! 754: if (j && i < data->numsubwindows - 1) ! 755: data->sub[i] = data->sub[i + 1]; ! 756: } ! 757: if (!j) ! 758: return; ! 759: data->numsubwindows--; ! 760: if (data->numsubwindows > 0) { ! 761: data->sub = (SubWindowPtr) ! 762: XtRealloc((char *) data->sub, ! 763: (unsigned) data->numsubwindows * sizeof(SubWindowInfo)); ! 764: } ! 765: RefigureLocationsAndCommit(data, data->numsubwindows - 1, -1); ! 766: } ! 767: ! 768: ! 769: void XtVPanedAllowResize(dpy, window, paneWindow, allowresize) ! 770: Display *dpy; ! 771: Window window, paneWindow; ! 772: Boolean allowresize; ! 773: { ! 774: WidgetData data; ! 775: int i; ! 776: data = DataFromWindow(dpy, window); ! 777: if (data) ! 778: for (i=0 ; i<data->numsubwindows ; i++) ! 779: if (data->sub[i].w == paneWindow) ! 780: data->sub[i].allowresize = allowresize; ! 781: } ! 782: ! 783: ! 784: ! 785: Boolean XtVPanedGetResize(dpy, window, paneWindow) ! 786: Display *dpy; ! 787: Window window, paneWindow; ! 788: { ! 789: WidgetData data; ! 790: int i; ! 791: data = DataFromWindow(dpy, window); ! 792: if (data) ! 793: for (i=0 ; i<data->numsubwindows ; i++) ! 794: if (data->sub[i].w == paneWindow) ! 795: return(data->sub[i].allowresize); ! 796: return (0); ! 797: } ! 798: ! 799: ! 800: ! 801: int XtVPanedGetNumSub(dpy, window) ! 802: Display *dpy; ! 803: Window window; ! 804: { ! 805: WidgetData data; ! 806: int i; ! 807: data = DataFromWindow(dpy, window); ! 808: if (data) ! 809: return(data->numsubwindows); ! 810: return (0); ! 811: } ! 812: ! 813: ! 814: ! 815: ! 816: void XtVPanedRefigureMode(dpy, window, mode) ! 817: Display *dpy; ! 818: Window window; ! 819: Boolean mode; ! 820: { ! 821: WidgetData data; ! 822: data = DataFromWindow(dpy, window); ! 823: if (data) { ! 824: data->refiguremode = mode; ! 825: if (mode) ! 826: RefigureLocationsAndCommit(data, data->numsubwindows - 1, -1); ! 827: } ! 828: } ! 829: ! 830: void XtVPaneGetValues(dpy, window, args, argCount) ! 831: Display *dpy; ! 832: Window window; ! 833: ArgList args; ! 834: int argCount; ! 835: { ! 836: WidgetData data; ! 837: data = DataFromWindow(dpy, window); ! 838: if (data == NULL) return; ! 839: ! 840: globaldata = *data; ! 841: XtGetValues(resources, XtNumber(resources), args, argCount); ! 842: } ! 843: ! 844: void XtVPaneSetValues(dpy, window, args, argCount) ! 845: Display *dpy; ! 846: Window window; ! 847: ArgList args; ! 848: int argCount; ! 849: { ! 850: WidgetData data; ! 851: data = DataFromWindow(dpy, window); ! 852: if (data == NULL) return; ! 853: ! 854: globaldata = *data; ! 855: XtSetValues(resources, XtNumber(resources), args, argCount); ! 856: *data = globaldata; ! 857: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.