|
|
1.1 root 1: /* $Header: Label.c,v 1.2 87/09/12 12:43:01 swick Exp $ */
2: #ifndef lint
3: static char *sccsid = "@(#)Label.c 1.15 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: #include <stdio.h>
31: #include <strings.h>
32: #include "Xlib.h"
33: #include "Intrinsic.h"
34: #include "Label.h"
35: #include "Atoms.h"
36:
37: /* Private Definitions */
38:
39:
40: typedef struct {
41: Display *dpy; /* widget display connection */
42: Window window; /* widget window */
43: Dimension borderWidth; /* border width in pixels */
44: Dimension width; /* window width in pixels */
45: Dimension height; /* window height in pixels */
46: Dimension internalWidth; /* internal border width in pixels */
47: Dimension internalHeight; /* internal border height in pixels */
48: String label; /* button text to display */
49: int labelLength; /* number of non-NULL chars in label */
50: Pixel foreground;
51: Pixel background;
52: Pixel border;
53: XFontStruct *fontStruct; /* label font */
54: Dimension labelWidth; /* label width in pixels */
55: Dimension labelHeight; /* label height in pixels */
56: XtJustify justify; /* left, right, or center */
57: GC gc; /* pointer to GraphicsContext */
58: } WidgetDataRec, *WidgetData;
59:
60: static WidgetDataRec globaldata;
61:
62:
63: /* Private Data */
64:
65: static caddr_t defNULL = (caddr_t) NULL;
66: static Dimension defBorderWidth = 1;
67: static Dimension defInternalWidth = 4;
68: static Dimension defInternalHeight = 2;
69: static XFontStruct *defFontStruct;
70: static XtJustify defJustify = XtjustifyCenter;
71:
72: static Resource resources[] = {
73: {XtNwindow, XtCWindow, XrmRWindow, sizeof(Window),
74: (caddr_t) &globaldata.window, (caddr_t) &defNULL},
75: {XtNborderWidth, XtCBorderWidth, XrmRInt, sizeof(Dimension),
76: (caddr_t) &globaldata.borderWidth, (caddr_t) &defBorderWidth},
77: {XtNwidth, XtCWidth, XrmRInt, sizeof(Dimension),
78: (caddr_t) &globaldata.width, (caddr_t) &defNULL},
79: {XtNheight, XtCHeight, XrmRInt, sizeof(Dimension),
80: (caddr_t) &globaldata.height, (caddr_t) &defNULL},
81: {XtNinternalWidth, XtCWidth, XrmRInt, sizeof(Dimension),
82: (caddr_t) &globaldata.internalWidth, (caddr_t) &defInternalWidth},
83: {XtNinternalHeight, XtCHeight, XrmRInt, sizeof(Dimension),
84: (caddr_t) &globaldata.internalHeight, (caddr_t) &defInternalHeight},
85: {XtNlabel, XtCLabel, XrmRString, sizeof(String),
86: (caddr_t) &globaldata.label, (caddr_t) &defNULL},
87: {XtNforeground, XtCColor, XrmRPixel, sizeof(Pixel),
88: (caddr_t) &globaldata.foreground, (caddr_t) &XtDefaultFGPixel},
89: {XtNbackground, XtCColor, XrmRPixel, sizeof(Pixel),
90: (caddr_t) &globaldata.background, (caddr_t) &XtDefaultBGPixel},
91: {XtNborder, XtCColor, XrmRPixel, sizeof(Pixel),
92: (caddr_t) &globaldata.border, (caddr_t) &XtDefaultFGPixel},
93: {XtNfont, XtCFont, XrmRFontStruct, sizeof(XFontStruct *),
94: (caddr_t) &globaldata.fontStruct, (caddr_t) &defFontStruct},
95: {XtNjustify, XtCJustify, XtRJustify, sizeof(XtJustify),
96: (caddr_t) &globaldata.justify, (caddr_t) &defJustify},
97: };
98:
99:
100: /****************************************************************
101: *
102: * Private Procedures
103: *
104: ****************************************************************/
105:
106: static Boolean initialized = FALSE;
107:
108: static XContext widgetContext;
109:
110: static void LabelInitialize(dpy)
111: Display *dpy;
112: {
113: if (initialized)
114: return;
115: initialized = TRUE;
116:
117: widgetContext = XUniqueContext();
118: defFontStruct = XLoadQueryFont(dpy,"fixed");
119: }
120:
121: /*
122: * Given a display and window, get the widget data.
123: */
124:
125: static WidgetData DataFromWindow(dpy, window)
126: Display *dpy;
127: Window window;
128: {
129: WidgetData result;
130: if (XFindContext(dpy, window, widgetContext, (caddr_t *)&result))
131: return NULL;
132: return result;
133: }
134:
135: /*
136: * Calculate width and height of displayed text in pixels
137: */
138:
139: static void SetTextWidthAndHeight(data)
140: WidgetData data;
141: {
142: register XFontStruct *fs = data->fontStruct;
143:
144: data->labelHeight = fs->max_bounds.ascent + fs->max_bounds.descent;
145: data->labelWidth = XTextWidth(fs, data->label, data->labelLength);
146: }
147:
148:
149: /*
150: * Repaint the widget window
151: */
152:
153: static void Redisplay(data)
154: WidgetData data;
155: {
156: Position x, y;
157:
158: /* Calculate text position within window given window width and height */
159: switch (data->justify) {
160: case XtjustifyLeft :
161: x = data->internalWidth;
162: break;
163: case XtjustifyRight :
164: x = data->width - data->labelWidth - data->internalWidth;
165: break;
166: case XtjustifyCenter :
167: x = (data->width - data->labelWidth) / 2;
168: break;
169: }
170: if (x < 0) x = 0;
171: y = (data->height - data->labelHeight) / 2
172: + data->fontStruct->max_bounds.ascent;
173:
174: XDrawString(data->dpy, data->window, data->gc, x, y,
175: data->label, data->labelLength);
176: }
177:
178:
179: /*
180: * Fill in the gc field
181: */
182:
183: static void GetGC(data)
184: WidgetData data;
185: {
186: XGCValues values;
187:
188: values.foreground = data->foreground;
189: values.font = data->fontStruct->fid;
190: values.background = data->background;
191: data->gc = XtGetGC(data->dpy, (XContext) widgetContext, data->window,
192: GCForeground | GCFont | GCBackground, &values);
193: }
194:
195:
196: /*
197: * Widget event handlers
198: */
199:
200: static XtEventReturnCode HandleExpose(event, eventdata)
201: XEvent *event;
202: caddr_t eventdata;
203: {
204: if (event->xexpose.count == 0)
205: Redisplay((WidgetData) eventdata);
206: return XteventHandled;
207: }
208:
209:
210: /*
211: * ||| Kludge as long as X events are clumped together
212: */
213:
214: static XtEventReturnCode HandleStructureNotify(event, eventdata)
215: XEvent *event;
216: caddr_t eventdata;
217: {
218: register WidgetData data = (WidgetData) eventdata;
219:
220: switch (event->type) {
221: case ConfigureNotify :
222: data->height = event->xconfigure.height;
223: data->width = event->xconfigure.width;
224: return XteventHandled;
225:
226: case DestroyNotify :
227: (void) XDeleteContext(data->dpy, data->window, widgetContext);
228: XtClearEventHandlers(data->dpy, data->window);
229: /* ||| XtFreeGC(data->gc); */
230: XtFree(data->label);
231: XtFree ((char *) data);
232: return XteventHandled;
233: }
234: return XteventNotHandled;
235: }
236:
237:
238: /****************************************************************
239: *
240: * Public Procedures
241: *
242: ****************************************************************/
243:
244: Window XtLabelCreate(dpy, parent, args, argCount)
245: Display *dpy;
246: Window parent;
247: ArgList args;
248: int argCount;
249: {
250: register WidgetData data;
251: XrmNameList names;
252: XrmClassList classes;
253:
254: if (!initialized)
255: LabelInitialize (dpy);
256:
257: data = (WidgetData ) XtMalloc (sizeof (WidgetDataRec));
258:
259: /* Set resource values */
260: globaldata.dpy = dpy;
261: XtGetResources(dpy, resources, XtNumber(resources), args, argCount, parent,
262: "label", "Label", &names, &classes);
263: *data = globaldata;
264:
265:
266: /* Set text label to widget name if needed */
267: if (data->label == NULL)
268: data->label = XrmNameToAtom(names[XrmNameListLength(names) - 1]);
269: data->labelLength = strlen(data->label);
270: data->label = strcpy( XtMalloc ((unsigned) data->labelLength + 1),
271: data->label);
272:
273: /* obtain text dimensions and calculate the window size */
274: SetTextWidthAndHeight(data);
275: if (data->width == 0)
276: data->width = data->labelWidth + 2 * data->internalWidth;
277: if (data->height == 0)
278: data->height = data->labelHeight + 2 * data->internalHeight;
279:
280: if (data->window != NULL) {
281: XWindowAttributes wi;
282: /* set global data from window parameters */
283: if (! XGetWindowAttributes(data->dpy, data->window, &wi)) {
284: data->window = NULL;
285: } else {
286: data->borderWidth = wi.border_width;
287: data->width = wi.width;
288: data->height = wi.height;
289: }
290: }
291: if (data->window == NULL) {
292: #ifdef notdef
293: int gravity;
294: switch(data->justify) {
295: case XtjustifyLeft : gravity = WestGravity; break;
296: case XtjustifyRight : gravity = EastGravity; break;
297: case XtjustifyCenter : gravity = CenterGravity; break;
298: }
299: #endif
300: /* !!! put window gravity into window !!! */
301: /* create the Label button window */
302: data->window = XCreateSimpleWindow(data->dpy,parent, 0, 0,
303: data->width, data->height,
304: data->borderWidth, data->border, data->background);
305: }
306:
307: XtSetNameAndClass(data->dpy, data->window, names, classes);
308: XrmFreeNameList(names);
309: XrmFreeClassList(classes);
310:
311: /* Create a graphics context */
312: GetGC(data);
313:
314: (void)XSaveContext(data->dpy, data->window, widgetContext, (caddr_t)data);
315:
316: /* Set handlers for expose, resize, destroy, and message events */
317: XtSetEventHandler (data->dpy, data->window, (XtEventHandler)HandleStructureNotify,
318: StructureNotifyMask, (caddr_t)data);
319: XtSetEventHandler (data->dpy, data->window, (XtEventHandler)HandleExpose,
320: ExposureMask, (caddr_t)data);
321:
322: return (data->window);
323: }
324:
325:
326: /*
327: * Get specified arguments from widget
328: */
329:
330: void XtLabelGetValues(dpy, window, args, argCount)
331: Display *dpy;
332: Window window;
333: ArgList args;
334: int argCount;
335: {
336: WidgetData data;
337: data = DataFromWindow(dpy, window);
338: if (data == NULL) return;
339: globaldata = *data;
340: XtGetValues(resources, XtNumber(resources), args, argCount);
341: }
342:
343:
344: /*
345: * Set specified arguments into widget
346: */
347:
348: void XtLabelSetValues(dpy, window, args, argCount)
349: Display *dpy;
350: Window window;
351: ArgList args;
352: int argCount;
353: {
354: WidgetData data;
355: data = DataFromWindow(dpy, window);
356: if (data == NULL) return;
357: globaldata = *data;
358: XtSetValues(resources, XtNumber(resources), args, argCount);
359:
360: if (strcmp(data->label, globaldata.label) != 0
361: || data->fontStruct != globaldata.fontStruct) {
362: XtGeometryReturnCode reply;
363: WindowBox reqbox, replybox;
364:
365: globaldata.labelLength = strlen(globaldata.label);
366: globaldata.label = strcpy(
367: XtMalloc ((unsigned) globaldata.labelLength + 1),
368: globaldata.label);
369: XtFree ((char *) data->label);
370:
371: /* obtain text dimensions and calculate the window size */
372: SetTextWidthAndHeight(&globaldata);
373: reqbox.width = globaldata.labelWidth + 2*globaldata.internalWidth;
374: reqbox.height = globaldata.labelHeight + 2*globaldata.internalHeight;
375: reply = XtMakeGeometryRequest(globaldata.dpy, globaldata.window, XtgeometryResize,
376: &reqbox, &replybox);
377: if (reply == XtgeometryAlmost) {
378: reqbox = replybox;
379: reply = XtMakeGeometryRequest(globaldata.dpy, globaldata.window, XtgeometryResize,
380: &reqbox, &replybox);
381: }
382: if (reply == XtgeometryYes) {
383: globaldata.width = reqbox.width;
384: globaldata.height = reqbox.height;
385: }
386: }
387:
388: if (data->foreground != globaldata.foreground
389: || data->background != globaldata.background
390: || data->fontStruct->fid != globaldata.fontStruct->fid) {
391: /* Need new graphics context */
392: /* ||| XtFreeGC(data->gc) */
393: GetGC(&globaldata);
394: }
395: XClearWindow(data->dpy, data->window);
396: *data = globaldata;
397: Redisplay (data);
398: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.