|
|
1.1 root 1: /* $Header: Boolean.c,v 1.2 87/09/12 12:41:35 swick Exp $ */
2: #ifndef lint
3: static char *sccsid = "@(#)Boolean.c 1.8 2/24/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: #include <stdio.h>
31: #include <strings.h>
32: #include "Xlib.h"
33: #include "Intrinsic.h"
34: #include "Boolean.h"
35: #include "Atoms.h"
36:
37: /* Private Definitions */
38:
39: typedef void (*NotifyProc)();
40:
41: typedef struct _WidgetDataRec {
42: Display *dpy; /* widget display connection */
43: Window window; /* widget window */
44: Position x, y; /* location of widget */
45: Dimension borderWidth; /* border width in pixels */
46: Dimension width, height; /* width/height in pixels */
47: int ibw, ibh; /* internal border width/height in pixels */
48: char *text; /* button text */
49: int fgpixel; /* color index for text */
50: int bgpixel; /* color index for background */
51: int brpixel; /* color for border */
52: Boolean highlighted; /* are we highlighted? */
53: Boolean value; /* pointer to value */
54: XFontStruct *fontstruct; /* font for text */
55: Dimension twidth, theight;/* text width/height */
56: XtJustify justify; /* text justification */
57: NotifyProc proc; /* procedure to invoke on value change */
58: caddr_t tag; /* widget client data */
59: XtEventsPtr eventTable; /* Table for Translation Manager */
60: caddr_t state; /* state for Translation Manager */
61: int eventlevels; /* recursion levels of event handling */
62: GC gc; /* current gc */
63: GC onGC; /* GC to use when on */
64: GC offGC; /* GC to use when off */
65: } WidgetDataRec, *WidgetData;
66:
67: extern void Dummy();
68: static WidgetDataRec globaldata;
69: static WidgetDataRec globalinit = {
70:
71: NULL, /* Display dpy; */
72: NULL, /* Window window; */
73: 0,0, /* x,y */
74: 1, /* int borderWidth; */
75: 0, 0, /* int width, height; */
76: 4, 2, /* int ibw, ibh; */
77: NULL, /* char *text; */
78: NULL, /* int fgpixel; */ /* init proc */
79: NULL, /* int bgpixel; */ /* init proc */
80: NULL, /* Pixmap brpixmap; */ /* init proc */
81: FALSE, /* Boolean highlighted; */
82: FALSE, /* Boolean value; */
83: NULL, /* XFontStruct *fontstruct; */ /* init proc */
84: 0, 0, /* int twidth, theight; */
85: XtjustifyCenter, /* justify */
86: Dummy, /* void (*proc) (); */
87: NULL, /* caddr_t tag; */
88: NULL, /* event table pointer */
89: NULL, /* state for Translation Manager */
90: NULL, /* event levels */
91: NULL, /* gc */
92: NULL, /* onGC */
93: NULL, /* offGC */
94: };
95:
96: /* Private Data */
97:
98: static int defaultBorderWidth = 1;
99: static int defaultInternalBorderWidth = 4;
100: static int defaultInternalBorderHeight = 2;
101: static XtJustify defaultJustify = XtjustifyCenter;
102: static NotifyProc defaultFunction = Dummy;
103:
104: static Resource resources[] = {
105: {XtNvalue, XtCValue, XrmRBoolean, sizeof(Boolean),
106: (caddr_t)&globaldata.value, (caddr_t)NULL},
107: {XtNwindow, XtCWindow, XrmRWindow, sizeof(Window),
108: (caddr_t)&globaldata.window, (caddr_t)NULL},
109: {XtNborderWidth, XtCBorderWidth, XrmRInt, sizeof(int),
110: (caddr_t)&globaldata.borderWidth, (caddr_t)&defaultBorderWidth},
111: {XtNwidth, XtCWidth, XrmRInt, sizeof(int),
112: (caddr_t)&globaldata.width, (caddr_t)NULL},
113: {XtNheight, XtCHeight, XrmRInt, sizeof(int),
114: (caddr_t)&globaldata.height, (caddr_t)NULL},
115: {XtNinternalWidth, XtCWidth, XrmRInt, sizeof(int),
116: (caddr_t)&globaldata.ibw, (caddr_t)&defaultInternalBorderWidth},
117: {XtNinternalHeight, XtCHeight, XrmRInt, sizeof(int),
118: (caddr_t)&globaldata.ibh, (caddr_t)&defaultInternalBorderHeight},
119: {XtNlabel, XtCLabel, XrmRString, sizeof(char *),
120: (caddr_t)&globaldata.text, (caddr_t)NULL},
121: {XtNforeground, XtCColor, XrmRPixel, sizeof(int),
122: (caddr_t)&globaldata.fgpixel, (caddr_t)&XtDefaultFGPixel},
123: {XtNbackground, XtCColor, XrmRPixel, sizeof(int),
124: (caddr_t)&globaldata.bgpixel, (caddr_t)&XtDefaultBGPixel},
125: {XtNborder, XtCColor, XrmRPixel, sizeof(int),
126: (caddr_t)&globaldata.brpixel, (caddr_t)&XtDefaultFGPixel},
127: {XtNfont, XtCFont, XrmRFontStruct, sizeof(XFontStruct *),
128: (caddr_t)&globaldata.fontstruct,(caddr_t)NULL},
129: {XtNjustify, XtCJustify, XtRJustify, sizeof(XtJustify),
130: (caddr_t)&globaldata.justify, (caddr_t)&defaultJustify},
131: {XtNfunction, XtCFunction, XtRFunction, sizeof(NotifyProc),
132: (caddr_t)&globaldata.proc, (caddr_t)&defaultFunction},
133: {XtNparameter, XtCParameter, XrmRPointer, sizeof(caddr_t),
134: (caddr_t)&globaldata.tag, (caddr_t)NULL},
135: {XtNeventBindings, XtCEventBindings,XtREventBindings, sizeof(caddr_t),
136: (caddr_t)&globaldata.eventTable,NULL },
137: };
138:
139: static char *defaultEventBindings[] = {
140: "<EnterWindow>: highlight\n",
141: "<LeaveWindow>: unhighlight\n",
142: "<ButtonPress>left: toggle\n",
143: "<ButtonRelease>left: notify\n",
144: NULL
145: };
146:
147: /****************************************************************
148: *
149: * Private Procedures
150: *
151: ****************************************************************/
152:
153: static Boolean initialized = FALSE; /* !!! STATIC !!! */
154:
155: static XContext widgetContext;
156:
157: static void BooleanInitialize (dpy)
158: Display *dpy;
159: {
160: if (initialized)
161: return;
162: initialized = TRUE;
163:
164: widgetContext = XUniqueContext();
165:
166: globalinit.fontstruct = XLoadQueryFont(dpy,"fixed");
167: globalinit.justify = XtjustifyCenter;
168: globalinit.eventTable = XtParseEventBindings(defaultEventBindings);
169: }
170:
171: static void SetTextWidthAndHeight(data)
172: WidgetData data;
173: {
174: data->theight = data->fontstruct->max_bounds.ascent +
175: data->fontstruct->max_bounds.descent;
176: data->twidth = XTextWidth(data->fontstruct, data->text,
177: strlen(data->text));
178: }
179:
180: /*ARGSUSED*/
181: static void Dummy(p)
182: caddr_t p;
183: {
184: (void) printf("dummy notify for Boolean\n");
185: }
186:
187: static void Ignore ()
188: {
189: (void) printf("you are being ignored\n");
190: }
191:
192: /*
193: * Given a display and window, get the widget data.
194: */
195:
196: static WidgetData DataFromWindow(dpy, window)
197: Display *dpy;
198: Window window;
199: {
200: WidgetData result;
201: if (XFindContext(dpy, window, widgetContext, (caddr_t *)&result))
202: return NULL;
203: return result;
204: }
205:
206: /*
207: *
208: * Repaint the widget window
209: *
210: */
211:
212: static void Redisplay (data)
213: WidgetData data;
214: {
215: int textx, texty;
216: Window w = data->window;
217:
218:
219: /*
220: * Calculate Text x,y given window width and text width
221: * to the specified justification
222: */
223:
224: if (data->justify == XtjustifyLeft)
225: textx = 2;
226: else if (data->justify == XtjustifyRight)
227: textx = data->width - data->twidth;
228: else
229: textx = ((data->width - data->twidth) / 2);
230: if (textx < 0) textx = 0;
231: texty = (data->height - data->theight) / 2 +
232: data->fontstruct->max_bounds.ascent;
233:
234: XFillRectangle(data->dpy, w,
235: (data->highlighted ? data->onGC : data->offGC),
236: 0, 0, data->width, data->height);
237:
238: XDrawImageString(
239: data->dpy, w, (((data->value)) ? data->offGC : data->onGC),
240: textx, texty, data->text, strlen(data->text));
241:
242: }
243:
244: extern void Destroy();
245:
246: /*
247: *
248: * Generic widget event handler
249: *
250: */
251:
252: static XtEventReturnCode EventHandler(event, eventdata)
253: XEvent *event;
254: caddr_t eventdata;
255: {
256: WidgetData data = (WidgetData) eventdata;
257: XtActionTokenPtr actionList;
258: NotifyProc proc;
259:
260: data->eventlevels++;
261:
262: switch (event->type) {
263: case ConfigureNotify:
264: data->width = event->xconfigure.width;
265: data->height = event->xconfigure.height;
266: data->borderWidth = event->xconfigure.border_width;
267: break;
268:
269: case DestroyNotify: Destroy(data); break;
270:
271: case Expose:
272: if (event->xexpose.count == 0)
273: Redisplay(data);
274: break;
275:
276: default:
277: actionList = (XtActionTokenPtr)XtTranslateEvent(
278: event, (TranslationPtr) data->state);
279: for (; actionList != NULL; actionList = actionList->next) {
280: if (actionList->type == XttokenAction) {
281: proc = (NotifyProc)XtInterpretAction(
282: data->dpy,
283: (TranslationPtr) data->state,
284: actionList->value.action);
285: (*proc) (data);
286: }
287: }
288: break;
289: }
290:
291: data->eventlevels--;
292: return (XteventHandled);
293: }
294:
295: /*
296: *
297: * Widget hilight event handler
298: *
299: */
300:
301: /*ARGSUSED*/
302: static XtEventReturnCode Highlight(data)
303: WidgetData data;
304: {
305: data->highlighted = TRUE;
306: Redisplay(data);
307: return (XteventHandled);
308: }
309:
310: /*
311: *
312: * Widget un-hilight event handler
313: *
314: */
315:
316: /*ARGSUSED*/
317: static XtEventReturnCode Unhighlight(data)
318: WidgetData data;
319: {
320: data->highlighted = FALSE;
321: Redisplay(data);
322: return (XteventHandled);
323: }
324:
325: static void SetValue(data, newval)
326: WidgetData data;
327: Boolean newval;
328: {
329: if ((data->value) == newval) return;
330:
331: (data->value) = newval;
332: data->gc = (newval ? data->onGC : data->offGC);
333: /*
334: XSetWindowBackground(data->dpy, data->window, data->gc->value.background);
335: */
336: Redisplay(data);
337: }
338:
339: /*
340: *
341: * Widget set value event handler
342: *
343: */
344:
345: /*ARGSUSED*/
346: static XtEventReturnCode On(event, eventdata)
347: XEvent *event;
348: caddr_t eventdata;
349: {
350: WidgetData data = (WidgetData) eventdata;
351:
352: SetValue(data, TRUE);
353: return (XteventHandled);
354: }
355:
356: /*
357: *
358: * Widget un-set value event handler
359: *
360: */
361:
362: /*ARGSUSED*/
363: static XtEventReturnCode Off(event, eventdata)
364: XEvent *event;
365: caddr_t eventdata;
366: {
367: WidgetData data = (WidgetData) eventdata;
368:
369: SetValue(data, FALSE);
370: return (XteventHandled);
371: }
372:
373: /*
374: *
375: * Widget toggle value event handler
376: *
377: */
378:
379: /*ARGSUSED*/
380: static XtEventReturnCode Toggle(data)
381: WidgetData data;
382: {
383: SetValue(data, ! (data->value));
384: return (XteventHandled);
385: }
386:
387: /*
388: * Widget handler to invoke application routine */
389:
390: /*ARGSUSED*/
391: static XtEventReturnCode Notify(data)
392: WidgetData data;
393: {
394: Redisplay(data);
395: XFlush(data->dpy);
396: data->proc(data->tag); /* invoke application proc */
397:
398: return(XteventHandled);
399: }
400:
401:
402: /*
403: *
404: * Destroy the widget
405: *
406: */
407:
408: static void Destroy(data)
409: WidgetData data;
410: {
411: (void) XDeleteContext(data->dpy, data->window, widgetContext);
412: XtClearEventHandlers(data->dpy, data->window);
413: XtFree ((char*)data->text);
414: XtFree ((char *) data);
415: }
416:
417: /****************************************************************
418: *
419: * Public Procedures
420: *
421: ****************************************************************/
422:
423: Window XtBooleanCreate(dpy, parent, args, argCount)
424: Display *dpy;
425: Window parent;
426: ArgList args;
427: int argCount;
428: {
429: WidgetData data;
430: XrmNameList names;
431: XrmClassList classes;
432: Position x, y;
433: unsigned int depth;
434: Drawable root;
435: unsigned long valuemask;
436: XSetWindowAttributes wvals;
437: XGCValues values;
438:
439: static XtActionsRec actionsTable[] = {
440: {"toggle", (caddr_t)Toggle},
441: {"highlight", (caddr_t)Highlight},
442: {"unhighlight", (caddr_t)Unhighlight},
443: {"notify", (caddr_t)Notify},
444: {"on", (caddr_t)On},
445: {"off", (caddr_t)Off},
446: {NULL, NULL}
447: };
448:
449:
450: if (!initialized)
451: BooleanInitialize(dpy);
452:
453: data = (WidgetData) XtMalloc (sizeof(WidgetDataRec));
454:
455: /* Set Default Values */
456: globaldata = globalinit;
457: globaldata.dpy = dpy;
458: XtGetResources(dpy, resources, XtNumber(resources), args, argCount, parent,
459: "boolean", "Boolean", &names, &classes);
460: *data = globaldata;
461:
462: data->state = XtSetActionBindings(
463: data->dpy,
464: data->eventTable, actionsTable, (caddr_t)Ignore);
465:
466: if (data->text == NULL)
467: data->text = XrmNameToAtom(names[XrmNameListLength(names) - 1]);
468: data->text = strcpy( XtMalloc ((unsigned) strlen(data->text) + 1),
469: data->text);
470:
471: /* obtain text dimensions and calculate the window size */
472: SetTextWidthAndHeight(data);
473: if (data->width == 0) data->width = data->twidth + 2*data->ibw;
474: if (data->height == 0) data->height = data->theight + 2*data->ibh;
475:
476: wvals.background_pixel = data->bgpixel;
477: wvals.border_pixel = data->brpixel;
478: wvals.bit_gravity = CenterGravity;
479:
480: valuemask = CWBackPixel | CWBorderPixel | CWBitGravity;
481:
482: if (data->window != NULL) {
483: /* set global data from window parameters */
484: if (
485: XGetGeometry(
486: data->dpy, data->window, &root,
487: &x, &y, &(data->width), &(data->height),
488: &(data->borderWidth), &depth)
489: ) {
490: XReparentWindow(data->dpy, data->window, parent, data->x,data->y);
491: XChangeWindowAttributes(data->dpy, data->window, valuemask, &wvals);
492: } else
493: data->window = NULL;
494: }
495: if (data->window == NULL)
496: data->window = XCreateWindow(data->dpy, parent, data->x, data->y,
497: data->width, data->height, data->borderWidth,
498: 0, (unsigned) InputOutput, (Visual *) CopyFromParent,
499: valuemask, &wvals);
500:
501: values.foreground = data->fgpixel;
502: values.background = data->bgpixel;
503: values.font = data->fontstruct->fid;
504: valuemask = GCForeground | GCBackground | GCFont;
505: data->onGC = XtGetGC(data->dpy, widgetContext, data->window,
506: valuemask, &values);
507: values.foreground = data->bgpixel;
508: values.background = data->fgpixel;
509: data->offGC = XtGetGC(data->dpy, widgetContext, data->window,
510: valuemask, &values);
511:
512: XtSetNameAndClass(data->dpy, data->window, names, classes);
513: XrmFreeNameList(names);
514: XrmFreeClassList(classes);
515:
516: (void)XSaveContext(data->dpy, data->window, widgetContext, (caddr_t)data);
517:
518: /* set handler for expose, resize, and message events */
519: XtSetEventHandler (data->dpy, data->window, (XtEventHandler) EventHandler,
520: StructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask
521: | EnterWindowMask | LeaveWindowMask, (caddr_t)data);
522:
523: return (data->window);
524: }
525:
526: /*
527: * Set specified arguments in widget
528: */
529:
530: void XtBooleanSetValues (dpy, window, args, argCount)
531: Display *dpy;
532: Window window;
533: ArgList args;
534: int argCount;
535: {
536: WidgetData data;
537: data = DataFromWindow(dpy, window);
538: if (data == NULL) return;
539:
540: globaldata = *data;
541: XtSetValues(resources, XtNumber(resources), args, argCount);
542:
543: (globaldata.value) = ((globaldata.value) ? TRUE : FALSE);
544:
545: if (strcmp (data->text, globaldata.text)
546: || data->fontstruct != globaldata.fontstruct) {
547: XtGeometryReturnCode reply;
548: WindowBox reqbox, replybox;
549:
550: globaldata.text = strcpy(
551: XtMalloc ((unsigned) strlen(globaldata.text) + 1),
552: globaldata.text);
553: XtFree ((char *) data->text);
554:
555: /* obtain text dimensions and calculate the window size */
556: SetTextWidthAndHeight(&globaldata);
557: reqbox.width = (int) globaldata.twidth + 2*globaldata.ibw;
558: reqbox.height = (int) globaldata.theight + 2*globaldata.ibh;
559: reply = XtMakeGeometryRequest(
560: globaldata.dpy, globaldata.window,
561: XtgeometryResize, &reqbox, &replybox);
562: if (reply == XtgeometryAlmost) {
563: reqbox = replybox;
564: (void) XtMakeGeometryRequest(
565: globaldata.dpy, globaldata.window,
566: XtgeometryResize, &reqbox, &replybox);
567: }
568: }
569:
570: *data = globaldata;
571: Redisplay (data);
572: }
573:
574: /*
575: * Get specified arguments from widget
576: */
577:
578: void XtBooleanGetValues (dpy, window, args, argCount)
579: Display *dpy;
580: Window window;
581: ArgList args;
582: int argCount;
583: {
584: WidgetData data;
585: data = DataFromWindow(dpy, window);
586: if (data == NULL) return;
587:
588: globaldata = *data;
589: XtGetValues(resources, XtNumber(resources), args, argCount);
590: }
591:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.