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