1 /*
2 Copyright (C) 1999-2001  Ulric Eriksson <ulric@siag.nu>
3 
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the Licence, or (at your option) any later version.
8 
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 Library General Public License for more details.
13 
14 You should have received a copy of the GNU Library General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
17 MA 02111-1307, USA.
18 */
19 
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <sys/stat.h>
24 
25 #include <X11/IntrinsicP.h>
26 #include <X11/StringDefs.h>
27 
28 #include <X11/xpm.h>
29 
30 #include "MwUtils.h"
31 #include "MwCheckP.h"
32 
33 #include "pixmaps/check_motif_off.xpm"
34 #include "pixmaps/check_motif_on.xpm"
35 #include "pixmaps/radio_motif_off.xpm"
36 #include "pixmaps/radio_motif_on.xpm"
37 #include "pixmaps/tickbox_off.xpm"
38 #include "pixmaps/tickbox_on.xpm"
39 #include "pixmaps/radio_16_off.xpm"
40 #include "pixmaps/radio_16_on.xpm"
41 
42 #define offset(field) XtOffsetOf(MwCheckRec, check.field)
43 static XtResource resources[] = {
44 	{
45 		XtNfont,		/* name */
46 		XtCFont,		/* class */
47 		XtRFontStruct,		/* type */
48 		sizeof(XFontStruct *),	/* size */
49 		offset(font),		/* offset */
50 		XtRString,		/* default_type */
51 		XtDefaultFont	 	/* default_addr */
52 	}, {
53 		XtNstate,
54 		XtCState,
55 		XtRBoolean,
56 		sizeof(Boolean),
57 		offset(state),
58 		XtRImmediate,
59 		(XtPointer)False
60 	}, {
61 		XtNcheckStyle,
62 		XtCCheckStyle,
63 		XtRInt,
64 		sizeof(int),
65 		offset(style),
66 		XtRImmediate,
67 		(XtPointer)MwCheckWin
68 	}, {
69 		XtNradioStart,
70 		XtCRadioStart,
71 		XtRWidget,
72 		sizeof(Widget),
73 		offset(start),
74 		XtRImmediate,
75 		(Widget)None
76 	}, {
77 		XtNradioGroup,
78 		XtCRadioGroup,
79 		XtRWidget,
80 		sizeof(Widget),
81 		offset(group),
82 		XtRImmediate,
83 		(Widget)None
84 	}, {
85 		XtNlabel,
86 		XtCLabel,
87 		XtRString,
88 		sizeof(String),
89 		offset(label),
90 		XtRImmediate,
91 		(XtPointer)NULL
92 	}, {
93 		XtNcallback,
94 		XtCCallback,
95 		XtRCallback,
96 		sizeof(XtPointer),
97 		offset(callbacks),
98 		XtRCallback,
99 		(XtPointer)NULL
100 	}
101 };
102 #undef offset
103 
104 /* methods */
105 static void Redisplay(Widget, XEvent *, Region);
106 static void Realize(Widget, XtValueMask *, XSetWindowAttributes *);
107 static void Initialize(Widget, Widget, ArgList, Cardinal *);
108 static void Destroy(Widget);
109 static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *);
110 static void RadioResetGroup(Widget, Widget);
111 
112 /* actions */
113 static void MwCheckAction(Widget, XEvent *, String *, Cardinal *);
114 
115 static XtActionsRec actions[] =
116 {
117 	{"check", MwCheckAction},
118 };
119 
120 /* translations */
121 static char translations[] =
122 "<Btn1Down>:		check()\n";
123 
124 MwCheckClassRec mwCheckClassRec = {
125   { /* core fields */
126     /* superclass		*/	(WidgetClass) &widgetClassRec,
127     /* class_name		*/	"MwCheck",
128     /* widget_size		*/	sizeof(MwCheckRec),
129     /* class_initialize		*/	NULL,
130     /* class_part_initialize	*/	NULL,
131     /* class_inited		*/	FALSE,
132     /* initialize		*/	Initialize,
133     /* initialize_hook		*/	NULL,
134     /* realize			*/	Realize,
135     /* actions			*/	actions,
136     /* num_actions		*/	XtNumber(actions),
137     /* resources		*/	resources,
138     /* num_resources		*/	XtNumber(resources),
139     /* xrm_class		*/	NULLQUARK,
140     /* compress_motion		*/	TRUE,
141     /* compress_exposure	*/	TRUE,
142     /* compress_enterleave	*/	TRUE,
143     /* visible_interest		*/	FALSE,
144     /* destroy			*/	Destroy,
145     /* resize			*/	NULL,
146     /* expose			*/	Redisplay,
147     /* set_values		*/	SetValues,
148     /* set_values_hook		*/	NULL,
149     /* set_values_almost	*/	XtInheritSetValuesAlmost,
150     /* get_values_hook		*/	NULL,
151     /* accept_focus		*/	NULL,
152     /* version			*/	XtVersion,
153     /* callback_private		*/	NULL,
154     /* tm_table			*/	translations,
155     /* query_geometry		*/	XtInheritQueryGeometry,
156     /* display_accelerator	*/	XtInheritDisplayAccelerator,
157     /* extension		*/	NULL
158   },
159   { /* check fields */
160     /* empty			*/	0
161   }
162 };
163 
164 WidgetClass mwCheckWidgetClass = (WidgetClass)&mwCheckClassRec;
165 
166 /* gw is any widget in the group, pw is where we start searching */
RadioResetGroup(Widget gw,Widget pw)167 static void RadioResetGroup(Widget gw, Widget pw)
168 {
169 	int i;
170 
171 	if (XtIsSubclass(pw, mwCheckWidgetClass)) {
172 		MwCheckWidget cw = (MwCheckWidget)pw;
173 		MwCheckWidget gcw = (MwCheckWidget)gw;
174 		if (pw != gw && cw->check.group == gcw->check.group)
175 			XtVaSetValues(pw, XtNstate, False, (char *)0);
176 	}
177 	if (XtIsSubclass(pw, compositeWidgetClass)) {
178 		CompositeWidget cw = (CompositeWidget)pw;
179 		for (i = 0; i < cw->composite.num_children; i++)
180 			RadioResetGroup(gw, cw->composite.children[i]);
181 	}
182 }
183 
MwCheckAction(Widget w,XEvent * event,String * params,Cardinal * n)184 static void MwCheckAction(Widget w, XEvent *event, String *params, Cardinal *n)
185 {
186 	MwCheckWidget tw = (MwCheckWidget)w;
187 
188 	tw->check.state = !tw->check.state;
189 	if (tw->check.start && tw->check.group)
190 		RadioResetGroup(w, tw->check.start);
191 	XtCallCallbackList(w, tw->check.callbacks, (XtPointer)NULL);
192 	Redisplay(w, NULL, NULL);
193 }
194 
195 #define MakePixmap(d,p) \
196 	result = XpmCreatePixmapFromData(dpy, wi, (d), &(p), NULL, &xa); \
197 	if (result != XpmSuccess) \
198 		fprintf(stderr, "XpmCreatePixmapFromData returns %s\n", \
199 			XpmGetErrorString(result));
200 
Initialize(Widget req,Widget new,ArgList args,Cardinal * num)201 static void Initialize(Widget req, Widget new, ArgList args, Cardinal *num)
202 {
203 	XpmAttributes xa;
204 	int result;
205 	XpmColorSymbol symbol;
206 	Pixel color;
207 	MwCheckWidget cw = (MwCheckWidget)new;
208 	Display *dpy = XtDisplay(new);
209 	Window wi = XRootWindowOfScreen(XtScreen(new));
210 
211 	if (cw->core.width == 0) cw->core.width = 80;
212 	if (cw->core.height == 0) cw->core.height = 20;
213 	XtVaGetValues(new,
214 		XtNbackground, &color,
215 		(char *)0);
216 	xa.closeness = 40000;
217 	xa.exactColors = FALSE;
218 	xa.valuemask = XpmCloseness | XpmExactColors;
219 	symbol.name = NULL;
220 	symbol.value = "none";
221 	symbol.pixel = color;
222 	xa.colorsymbols = &symbol;
223 	xa.numsymbols = 1;
224 	xa.valuemask |= XpmColorSymbols;
225 	MakePixmap(check_motif_off_xpm, cw->check.cmoff);
226 	MakePixmap(check_motif_on_xpm, cw->check.cmon);
227 	MakePixmap(radio_16_off_xpm, cw->check.r16off);
228 	MakePixmap(radio_16_on_xpm, cw->check.r16on);
229 	MakePixmap(radio_motif_off_xpm, cw->check.rmoff);
230 	MakePixmap(radio_motif_on_xpm, cw->check.rmon);
231 	MakePixmap(tickbox_off_xpm, cw->check.tboff);
232 	MakePixmap(tickbox_on_xpm, cw->check.tbon);
233 }
234 
get_gc(Widget w)235 static GC get_gc(Widget w)
236 {
237 	MwCheckWidget tw = (MwCheckWidget)w;
238         unsigned long valuemask;
239         XGCValues values;
240 	GC gc;
241 
242 	values.font = tw->check.font->fid;
243 	valuemask = GCFont;
244         gc = XCreateGC(XtDisplay(w), XtWindow(w),
245                                 valuemask, &values);
246         return gc;
247 }
248 
249 #define superclass (&coreClassRec)
Realize(Widget w,XtValueMask * valueMask,XSetWindowAttributes * attributes)250 static void Realize(Widget w, XtValueMask *valueMask,
251                 XSetWindowAttributes *attributes)
252 {
253         MwCheckWidget tw = (MwCheckWidget) w;
254 
255         (*superclass->core_class.realize) (w, valueMask, attributes);
256         tw->check.gc = get_gc(w);
257 }
258 
Destroy(Widget w)259 static void Destroy(Widget w)
260 {
261         MwCheckWidget tw = (MwCheckWidget) w;
262 	Display *dpy = XtDisplay(w);
263 
264         XFreeGC(dpy, tw->check.gc);
265 	XFreePixmap(dpy, tw->check.cmoff);
266 	XFreePixmap(dpy, tw->check.cmon);
267 	XFreePixmap(dpy, tw->check.r16on);
268 	XFreePixmap(dpy, tw->check.r16off);
269 	XFreePixmap(dpy, tw->check.rmoff);
270 	XFreePixmap(dpy, tw->check.rmon);
271 	XFreePixmap(dpy, tw->check.tbon);
272 	XFreePixmap(dpy, tw->check.tboff);
273 }
274 
Redisplay(Widget w,XEvent * event,Region r)275 static void Redisplay(Widget w, XEvent *event, Region r)
276 {
277 	Pixmap scribble, icon;
278 	Dimension h;
279 	MwCheckWidget aw = (MwCheckWidget) w;
280 	Display *dpy = XtDisplay(w);
281 	Screen *s = XtScreen(w);
282 	Window wi = XtWindow(w);
283 	unsigned long black = BlackPixelOfScreen(s);
284 	unsigned long grey;
285 	XFontStruct *fs = aw->check.font;
286 	char *word = aw->check.label;
287 	int asc = fs->max_bounds.ascent;
288 	int desc = fs->max_bounds.descent;
289 	int height = asc-desc;
290 	int y = (aw->core.height+height)/2;
291 
292 	XtVaGetValues(w,
293 		XtNbackground, &grey,
294 		XtNheight, &h,
295 		(char *)0);
296 	scribble = XCreatePixmap(dpy, wi, aw->core.width,
297 				aw->core.height, aw->core.depth);
298         XSetForeground(dpy, aw->check.gc, grey);
299 	XFillRectangle(dpy, scribble, aw->check.gc, 0, 0,
300 			aw->core.width, aw->core.height);
301 	XSetForeground(dpy, aw->check.gc, black);
302 
303 	switch (aw->check.style) {
304 	case MwCheckWin:
305 		if (aw->check.state) icon = aw->check.tbon;
306 		else icon = aw->check.tboff;
307 		break;
308 	case MwRadioWin:
309 		if (aw->check.state) icon = aw->check.r16on;
310 		else icon = aw->check.r16off;
311 		break;
312 	case MwCheckMotif:
313 		if (aw->check.state) icon = aw->check.cmon;
314 		else icon = aw->check.cmoff;
315 		break;
316 	default:	/* MwRadioMotif */
317 		if (aw->check.state) icon = aw->check.rmon;
318 		else icon = aw->check.rmoff;
319 		break;
320 	}
321 	XCopyArea(dpy, icon, scribble, aw->check.gc,
322 		0, 0, 16, 16, 2, (aw->core.height-16)/2);
323 	if (word) {
324 		XDrawString(dpy, scribble, aw->check.gc,
325 			20, y, word, strlen(word));
326 	}
327 	XCopyArea(dpy, scribble, wi, aw->check.gc,
328 		0, 0, aw->core.width, aw->core.height, 0, 0);
329 	XFreePixmap(dpy, scribble);
330 }
331 
SetValues(Widget current,Widget request,Widget new,ArgList args,Cardinal * nargs)332 static Boolean SetValues(Widget current, Widget request, Widget new,
333 		ArgList args, Cardinal *nargs)
334 {
335 	Boolean do_redisplay = True;
336 	return do_redisplay;
337 }
338 
339