|
|
1.1 ! root 1: /* $Header: ScrollMgr.c,v 1.1 87/09/11 07:59:35 toddb Exp $ */ ! 2: #ifndef lint ! 3: static char *sccsid = "@(#)ScrollBarMgr.c 1.4 2/25/87"; ! 4: #endif lint ! 5: /* ! 6: * COPYRIGHT 1987 ! 7: * DIGITAL EQUIPMENT CORPORATION ! 8: * MAYNARD, MASSACHUSETTS ! 9: * ALL RIGHTS RESERVED. ! 10: * ! 11: * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND ! 12: * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. ! 13: * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ! 14: * ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. ! 15: * ! 16: * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT RIGHTS, ! 17: * APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN ADDITION TO THAT ! 18: * SET FORTH ABOVE. ! 19: * ! 20: * ! 21: * Permission to use, copy, modify, and distribute this software and its ! 22: * documentation for any purpose and without fee is hereby granted, provided ! 23: * that the above copyright notice appear in all copies and that both that ! 24: * copyright notice and this permission notice appear in supporting ! 25: * documentation, and that the name of Digital Equipment Corporation not be used ! 26: * in advertising or publicity pertaining to distribution of the software ! 27: * without specific, written prior permission. ! 28: */ ! 29: ! 30: ! 31: /* ScrollBarMgr.c */ ! 32: /* created by weissman: 24 Jul 86 16:26 */ ! 33: ! 34: #include "Xlib.h" ! 35: #include "Intrinsic.h" ! 36: #include "Scroll.h" ! 37: #include "Atoms.h" ! 38: ! 39: /* Private definitions. */ ! 40: ! 41: #define MAXBARS 4 /* How many scrollbars there can be, tops. */ ! 42: #define DEFAULTTHICKNESS 15 /* Default thickness of scrollbars. */ ! 43: ! 44: typedef struct { ! 45: Display *dpy; /* the scrollbar window display */ ! 46: Window sbar; /* The scrollbar window itself. */ ! 47: XtOrientation orientation; /* Orientation of the scrollbar. */ ! 48: Boolean lowerRight; /* Should this one go on the bottom or right */ ! 49: Position x, y; /* Location of this scroll bar. */ ! 50: Dimension width, height; /* Size of this scroll bar. */ ! 51: } ScrollBarData, *ScrollBarDataPtr; ! 52: ! 53: typedef struct { ! 54: Display *dpy; /* display connection for all this */ ! 55: Window outer; /* All encompassing window. */ ! 56: Window frame; /* Window that actually contains the data. */ ! 57: Position x, y; /* Location of outer window. */ ! 58: Dimension pwidth, pheight; /* Size of outer window. */ ! 59: Dimension cwidth, cheight; /* Size of frame. */ ! 60: Position cx, cy; /* Location of frame inside outer window. */ ! 61: Pixel border; /* Pixmap for borders. */ ! 62: Dimension borderWidth; /* Size of the borders. */ ! 63: int thickness; /* Thickness of scroll bars. */ ! 64: int numbars; /* How many scrollbars we have. */ ! 65: ScrollBarData bar[MAXBARS]; /* Data on each scrollbar. */ ! 66: } WidgetDataRec, *WidgetData; ! 67: ! 68: static WidgetDataRec globaldata; ! 69: static WidgetDataRec globalinit = { ! 70: NULL, /* display connection */ ! 71: NULL, /* All encompassing window. */ ! 72: NULL, /* Window that actually contains the data. */ ! 73: 200,200, /* Location of outer window. */ ! 74: 100,100, /* Size of outer window. */ ! 75: 50,50, /* Size of frame. */ ! 76: -99, -99, /* Location of frame. */ ! 77: 0, /* Pixel for borders. */ ! 78: 1, /* Size of the borders. */ ! 79: DEFAULTTHICKNESS, /* Thickness of scroll bars. */ ! 80: 0, /* How many scrollbars we have. */ ! 81: {(Display *) NULL, (Window)NULL, XtorientVertical, (Boolean)0, 0,0, 0,0} ! 82: ! 83: }; ! 84: static Resource resources[] = { ! 85: {XtNwindow, XtCWindow, XrmRWindow, sizeof(Window), ! 86: (caddr_t)&globaldata.outer, NULL}, ! 87: {XtNchildWindow, XtCWindow, XrmRWindow, sizeof(Window), ! 88: (caddr_t)&globaldata.frame, NULL}, ! 89: {XtNborderWidth, XtCBorderWidth, XrmRInt, sizeof(int), ! 90: (caddr_t)&globaldata.borderWidth, NULL}, ! 91: {XtNborder, XtCColor, XrmRPixel, sizeof(int), ! 92: (caddr_t)&globaldata.border, (caddr_t)NULL}, ! 93: {XtNthickness, XtCThickness, XrmRInt, sizeof(int), ! 94: (caddr_t)&globaldata.thickness, NULL}, ! 95: {XtNwidth, XtCWidth, XrmRInt, sizeof(int), ! 96: (caddr_t)&globaldata.pwidth, NULL}, ! 97: {XtNheight, XtCHeight, XrmRInt, sizeof(int), ! 98: (caddr_t)&globaldata.pheight, NULL}, ! 99: {XtNx, XtCX, XrmRInt, sizeof(int), ! 100: (caddr_t)&globaldata.x, NULL}, ! 101: {XtNy, XtCY, XrmRInt, sizeof(int), ! 102: (caddr_t)&globaldata.y, NULL}, ! 103: }; ! 104: ! 105: ! 106: static Boolean lowerRight; ! 107: static XtOrientation orientation; ! 108: ! 109: static Resource addResources[] = { ! 110: {XtNlowerRight, XtCBoolean, XrmRBoolean, sizeof(Boolean), ! 111: (caddr_t)&lowerRight, NULL}, ! 112: {XtNorientation, XtCOrientation, XtROrientation, sizeof(XtOrientation), ! 113: (caddr_t)&orientation, NULL}, ! 114: }; ! 115: ! 116: static XContext scrollBarMgrContext; ! 117: ! 118: static Boolean initialized = FALSE; ! 119: ! 120: static void ScrollBarMgrInitialize () ! 121: { ! 122: if (initialized) ! 123: return; ! 124: initialized = TRUE; ! 125: ! 126: scrollBarMgrContext = XUniqueContext (); ! 127: } ! 128: ! 129: ! 130: static WidgetData GetSBMgrInfoFromWindow(dpy, w) ! 131: Display *dpy; ! 132: Window w; ! 133: { ! 134: WidgetData data; ! 135: if (!XFindContext(dpy, w, scrollBarMgrContext, (caddr_t *) &data)) ! 136: return data; ! 137: return 0; ! 138: } ! 139: ! 140: ! 141: ! 142: static ResizeEverything(data) ! 143: WidgetData data; ! 144: { ! 145: int top = 0, ! 146: bottom = 0, ! 147: left = 0, ! 148: right = 0; ! 149: Dimension thickness = data->thickness; ! 150: Position borderWidth = data->borderWidth; ! 151: Dimension pwidth = data->pwidth; ! 152: Dimension pheight = data->pheight; ! 153: Position x, y; ! 154: Dimension cwidth, cheight, width, height; ! 155: ScrollBarDataPtr bar; ! 156: for (bar = data->bar; ! 157: bar - data->bar < data->numbars; ! 158: bar++) { ! 159: if (bar->orientation == XtorientVertical) { ! 160: if (bar->lowerRight) ! 161: right = thickness; ! 162: else ! 163: left = thickness; ! 164: } ! 165: else { ! 166: if (bar->lowerRight) ! 167: bottom = thickness; ! 168: else ! 169: top = thickness; ! 170: } ! 171: } ! 172: cwidth = pwidth - left - right; ! 173: cheight = pheight - top - bottom; ! 174: if (cwidth < 1 || cheight < 1) ! 175: return; /* Everything is too small still. */ ! 176: if (left != data->cx || top != data->cy || ! 177: cwidth != data->cwidth || cheight != data->cheight) { ! 178: WindowBox box; ! 179: XMoveResizeWindow(data->dpy,data->frame, ! 180: box.x = data->cx = left, ! 181: box.y = data->cy = top, ! 182: box.width = data->cwidth = cwidth, ! 183: box.height = data->cheight = cheight); ! 184: (void) XtSendConfigureNotify(data->dpy, data->frame, &box); ! 185: } ! 186: for (bar = data->bar; ! 187: bar - data->bar < data->numbars; ! 188: bar++) { ! 189: if (bar->orientation == XtorientVertical) { ! 190: x = bar->lowerRight ? pwidth - thickness : -borderWidth; ! 191: y = top - borderWidth; ! 192: width = thickness - borderWidth; ! 193: height = pheight - top - bottom; ! 194: } ! 195: else { ! 196: x = left - borderWidth; ! 197: y = bar->lowerRight ? pheight - thickness : -borderWidth; ! 198: width = pwidth - left - right; ! 199: height = thickness - borderWidth; ! 200: } ! 201: if (width != bar->width || height != bar->height || ! 202: x != bar->x || y != bar->y) { ! 203: WindowBox box; ! 204: XMoveResizeWindow(data->dpy, bar->sbar, ! 205: box.x = bar->x = x, ! 206: box.y = bar->y = y, ! 207: box.width = bar->width = width, ! 208: box.height = bar->height = height); ! 209: (void) XtSendConfigureNotify(data->dpy, bar->sbar, &box); ! 210: } ! 211: } ! 212: } ! 213: ! 214: ! 215: ! 216: ! 217: static XtEventReturnCode HandleEvents(event) ! 218: XEvent *event; ! 219: { ! 220: WidgetData data; ! 221: int i; ! 222: ! 223: data = GetSBMgrInfoFromWindow(event->xany.display, event->xany.window); ! 224: if (!data) return XteventNotHandled; ! 225: ! 226: switch(event->type){ ! 227: case ConfigureNotify: ! 228: if (data->pwidth != event->xconfigure.width ! 229: || data->pheight != event->xconfigure.height) { ! 230: data->pwidth = event->xconfigure.width; ! 231: data->pheight = event->xconfigure.height; ! 232: ResizeEverything(data); ! 233: } ! 234: return XteventHandled; ! 235: ! 236: case DestroyNotify: ! 237: XtClearEventHandlers(data->dpy, data->outer); ! 238: for (i=0; i<MAXBARS; i++) { ! 239: if (data->bar[i].sbar != NULL) ! 240: (void) XtSendDestroyNotify(data->dpy,data->bar[i].sbar); ! 241: } ! 242: (void) XDeleteContext(data->dpy, data->outer,scrollBarMgrContext); ! 243: (void) XDeleteContext(data->dpy, data->frame,scrollBarMgrContext); ! 244: (void) XtSendDestroyNotify(data->dpy, data->frame); ! 245: XtClearEventHandlers(data->dpy, data->frame); ! 246: XtFree((char *)data); ! 247: return XteventHandled; ! 248: } ! 249: ! 250: return XteventNotHandled; ! 251: } ! 252: ! 253: static XtGeometryReturnCode ! 254: ScrollBarGeometryRequest(dpy, myWindow, request, requestBox, replyBox) ! 255: Display *dpy; ! 256: Window myWindow; ! 257: XtGeometryRequest request; ! 258: WindowBox *requestBox, *replyBox; ! 259: { ! 260: WidgetData data; ! 261: WindowBox myRequest, myReply; ! 262: XtGeometryReturnCode result; ! 263: data = GetSBMgrInfoFromWindow(dpy, myWindow); ! 264: if (!data || request != XtgeometryResize) ! 265: return XtgeometryNo; ! 266: myRequest.x = myRequest.y = 0; ! 267: myRequest.width = requestBox->width + data->pwidth - data->cwidth; ! 268: myRequest.height = requestBox->height + data->pheight - data->cheight; ! 269: result = XtMakeGeometryRequest(dpy, data->outer, request, &myRequest, &myReply); ! 270: if (result != XtgeometryNo) { ! 271: replyBox->width = myReply.width + data->cwidth - data->pwidth; ! 272: replyBox->width = myReply.height + data->cheight - data->pheight; ! 273: } ! 274: return result; ! 275: } ! 276: ! 277: ! 278: ! 279: /* Public routines. */ ! 280: ! 281: /* Register this window as one that might require scrollbars within it. ! 282: Returns the window created within that will actually be used to store ! 283: the data. */ ! 284: ! 285: /* ! 286: * Creates a new master window which will in turn contain a window that ! 287: * will be layed out some number of scrollbars. Returns the master window. ! 288: */ ! 289: ! 290: Window XtScrollMgrCreate(dpy, parent, args, argCount) ! 291: Display *dpy; ! 292: Window parent; ! 293: ArgList args; ! 294: int argCount; ! 295: { ! 296: WidgetData data; ! 297: XrmNameList names; ! 298: XrmClassList classes; ! 299: ! 300: if (!initialized) ScrollBarMgrInitialize (); ! 301: ! 302: data = (WidgetData) XtMalloc(sizeof(WidgetDataRec)); ! 303: globaldata = globalinit; ! 304: globaldata.dpy = dpy; ! 305: XtGetResources(dpy, resources, XtNumber(resources), args, argCount, parent, ! 306: "scrollBarMgr", "ScrollBarMgr", &names, &classes); ! 307: *data = globaldata; ! 308: if (data->outer != NULL) { ! 309: XWindowChanges wc; ! 310: unsigned int valuemask; ! 311: valuemask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth; ! 312: wc.x = data->x; wc.y = data->y; wc.width = data->pwidth; ! 313: wc.height = data->pheight; wc.border_width = data->borderWidth; ! 314: XConfigureWindow(data->dpy,data->outer,valuemask, &wc); ! 315: XReparentWindow(data->dpy,data->outer,parent,data->x,data->y); ! 316: ! 317: } else { ! 318: data->outer = XtCreateWindow(data->dpy, parent, data->x, data->y, ! 319: data->pwidth, data->pheight, ! 320: data->borderWidth, ! 321: data->border, (Pixel)NULL, ! 322: NorthWestGravity); ! 323: } ! 324: XtSetNameAndClass(data->dpy, data->outer, names, classes); ! 325: XrmFreeNameList(names); ! 326: XrmFreeClassList(classes); ! 327: ! 328: if (data->frame == NULL) ! 329: data->frame = XtCreateWindow(data->dpy, data->outer, 0, 0, ! 330: data->pwidth, data->pheight, 0, ! 331: (Pixel) 0, (Pixel) 1, ! 332: NorthWestGravity); ! 333: XMapWindow(data->dpy, data->frame); ! 334: (void) XSaveContext(data->dpy, data->outer, scrollBarMgrContext, (caddr_t) data); ! 335: (void) XSaveContext(data->dpy, data->frame, scrollBarMgrContext, (caddr_t) data); ! 336: data->numbars = 0; ! 337: (void) XtSetGeometryHandler(data->dpy, data->frame, (XtGeometryHandler) ScrollBarGeometryRequest); ! 338: (void) XtSetEventHandler(data->dpy, data->outer, (XtEventHandler) HandleEvents, ! 339: StructureNotifyMask, (caddr_t) NULL); ! 340: return data->outer; ! 341: } ! 342: ! 343: ! 344: Window XtScrollMgrGetChild(dpy, parent) ! 345: Display *dpy; ! 346: Window parent; ! 347: { ! 348: WidgetData data; ! 349: data = GetSBMgrInfoFromWindow(dpy, parent); ! 350: if (data) return data->frame; ! 351: else return NULL; ! 352: } ! 353: ! 354: ! 355: Window XtScrollMgrSetChild(dpy, parent, frame) ! 356: Display *dpy; ! 357: Window parent, frame; ! 358: { ! 359: WidgetData data; ! 360: data = GetSBMgrInfoFromWindow(dpy, parent); ! 361: if (data) { ! 362: XUnmapWindow(data->dpy,data->frame); ! 363: (void) XDeleteContext(data->dpy, data->frame, scrollBarMgrContext); ! 364: data->frame = frame; ! 365: (void) XSaveContext(data->dpy, data->frame, scrollBarMgrContext, (caddr_t) data); ! 366: (void) XtSetGeometryHandler(data->dpy, data->frame, ScrollBarGeometryRequest); ! 367: ResizeEverything(data); ! 368: XMapWindow(data->dpy,data->frame); ! 369: } ! 370: } ! 371: ! 372: ! 373: /* Stop this window from being managed as scrollbars. All windows are ! 374: destroyed, except for the outer one. */ ! 375: ! 376: int XtScrollMgrDestroy(dpy, w) ! 377: Display *dpy; ! 378: Window w; ! 379: { ! 380: WidgetData data; ! 381: int i; ! 382: data = GetSBMgrInfoFromWindow(dpy, w); ! 383: if (!data) return; ! 384: for (i=data->numbars - 1 ; i>=0 ; i--) ! 385: XtDeleteScrollBar(dpy, w, data->bar[i].sbar); ! 386: (void) XDeleteContext(dpy, w, scrollBarMgrContext); ! 387: XDestroyWindow(data->dpy,data->frame); ! 388: XtFree((char *) data); ! 389: } ! 390: ! 391: ! 392: ! 393: /* Set the thickness to be used to draw scroll bars in the given window. Any ! 394: already existing scrollbars will be resized to match this. */ ! 395: ! 396: XtScrollMgrSetThickness(dpy, w, thickness) ! 397: Display *dpy; ! 398: Window w; ! 399: int thickness; ! 400: { ! 401: WidgetData data; ! 402: data = GetSBMgrInfoFromWindow(dpy,w); ! 403: if (data->thickness != thickness) { ! 404: data->thickness = thickness; ! 405: ResizeEverything(data); ! 406: } ! 407: } ! 408: ! 409: ! 410: /* Find out the thickness of the scrollbars in the given window. */ ! 411: ! 412: int XtScrollMgrGetThickness(dpy, w) ! 413: Display *dpy; ! 414: Window w; ! 415: { ! 416: WidgetData data; ! 417: data = GetSBMgrInfoFromWindow(dpy, w); ! 418: return data->thickness; ! 419: } ! 420: ! 421: ! 422: /* Add a scroll bar. */ ! 423: ! 424: Window XtScrollMgrAddBar(dpy, parent, args, argCount) ! 425: Display *dpy; ! 426: Window parent; ! 427: ArgList args; ! 428: int argCount; ! 429: { ! 430: WidgetData data; ! 431: int i; ! 432: XrmNameList names; ! 433: XrmClassList classes; ! 434: ! 435: data = GetSBMgrInfoFromWindow(dpy, parent); ! 436: if (data->numbars < MAXBARS) { ! 437: orientation = XtorientVertical; ! 438: lowerRight = FALSE; ! 439: XtGetResources(data->dpy, addResources, XtNumber(addResources), args, argCount, ! 440: parent, "scrollBarMgr", "ScrollBarMgr", &names, &classes); ! 441: XrmFreeNameList(names); ! 442: XrmFreeClassList(classes); ! 443: ! 444: i = (data->numbars)++; ! 445: data->bar[i].sbar = XtScrollBarCreate(data->dpy, data->outer, args, argCount); ! 446: data->bar[i].orientation = orientation; ! 447: data->bar[i].lowerRight = lowerRight; ! 448: data->bar[i].width = 1; ! 449: data->bar[i].height = 1; ! 450: ResizeEverything(data); ! 451: XMapWindow(data->dpy,data->bar[i].sbar); ! 452: return data->bar[i].sbar; ! 453: } ! 454: else return 0; ! 455: } ! 456: ! 457: ! 458: ! 459: /* Delete a scroll bar. */ ! 460: ! 461: XtDeleteScrollBar(dpy, parent, scrollbar) ! 462: Display *dpy; ! 463: Window parent, scrollbar; ! 464: { ! 465: WidgetData data; ! 466: int i; ! 467: data = GetSBMgrInfoFromWindow(dpy, parent); ! 468: for (i = 0; i < data->numbars; i++) { ! 469: if (data->bar[i].sbar == scrollbar) { ! 470: data->bar[i] = data->bar[--(data->numbars)]; ! 471: XDestroyWindow(dpy, scrollbar); ! 472: XtSendDestroyNotify(dpy, scrollbar); ! 473: ResizeEverything(data); ! 474: break; ! 475: } ! 476: } ! 477: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.