|
|
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.