Initial git import
[sxemacs] / src / ui / lwlib / xlwcheckbox.c
1 /* Checkbox Widget for SXEmacs.
2    Copyright (C) 1999 Edward A. Falk
3
4 This file is part of SXEmacs.
5
6 SXEmacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 SXEmacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program.  If not, see <http://www.gnu.org/licenses/>. */
18
19 /* Synched up with: Checkbox.c 1.1 */
20
21 /*
22  * Checkbox.c - Checkbox button widget
23  *
24  * Author: Edward A. Falk
25  *         falk@falconer.vip.best.com
26  *
27  * Date:   June 30, 1997
28  *
29  * Overview:  This widget is identical to the Radio widget in behavior,
30  * except that the button is square and has a check mark.
31  */
32
33 #include <config.h>
34 #include <stdio.h>
35
36 #include <X11/IntrinsicP.h>
37 #include <X11/StringDefs.h>
38 #include ATHENA_XawInit_h_
39 #include "ui/X11/xmu.h"
40 #include "xlwcheckboxP.h"
41
42 /* by using the same size for the checkbox as for the diamond box,
43  * we can let the Radio widget do the vast majority of the work.
44  */
45
46 #define BOX_SIZE        8
47 #define DRAW_CHECK      0       /* don't draw the check mark */
48
49 #define cclass(w)       ((CheckboxWidgetClass)((w)->core.widget_class))
50
51 #ifdef  _ThreeDP_h
52 #define swid(cw)        ((cw)->threeD.shadow_width)
53 #else
54 #define swid(cw)        ((cw)->core.border_width)
55 #endif
56
57 #define bsize(cw)       (cclass(cw)->radio_class.dsize)
58 #define bs(cw)          (bsize(cw) + 2*swid(cw))
59
60 #if     DRAW_CHECK
61 #define check_width 14
62 #define check_height 14
63 static unsigned char check_bits[] = {
64         0x00, 0x00, 0x00, 0x20, 0x00, 0x18, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x03,
65         0x8c, 0x03, 0xde, 0x01, 0xff, 0x01, 0xfe, 0x00, 0xfc, 0x00, 0x78, 0x00,
66         0x70, 0x00, 0x20, 0x00
67 };
68 #endif
69
70 /****************************************************************
71  *
72  * Full class record constant
73  *
74  ****************************************************************/
75
76 #if DRAW_CHECK
77 static char defaultTranslations[] = "<EnterWindow>:     highlight()\n\
78      <LeaveWindow>:     unpress(draw) unhighlight()\n\
79      <Btn1Down>:        press()\n\
80      <Btn1Down>,<Btn1Up>:   unpress(nodraw) toggle() notify()";
81 #endif
82
83 #define offset(field)   XtOffsetOf(CheckboxRec, field)
84 static XtResource resources[] = {
85         {XtNtristate, XtCTristate, XtRBoolean, sizeof(Boolean),
86          offset(checkbox.tristate), XtRImmediate, (XtPointer) FALSE}
87         ,
88 };
89 #undef  offset
90
91         /* Member functions */
92
93 static void CheckboxClassInit(void);
94 static void CheckboxInit(Widget, Widget, ArgList, Cardinal *);
95 #if DRAW_CHECK
96 static void CheckboxRealize(Widget, Mask *, XSetWindowAttributes *);
97 #endif
98 static void DrawCheck(Widget);
99
100         /* Action procs */
101 #if DRAW_CHECK
102 static void CheckboxPress(Widget, XEvent *, String *, Cardinal *);
103 static void CheckboxUnpress(Widget, XEvent *, String *, Cardinal *);
104 #endif
105
106         /* internal privates */
107
108 #if DRAW_CHECK
109 static XtActionsRec actionsList[] = {
110         {"press", CheckboxPress},
111         {"unpress", CheckboxUnpress},
112 };
113 #endif
114
115 #define SuperClass ((RadioWidgetClass)&radioClassRec)
116
117 CheckboxClassRec checkboxClassRec = {
118         {
119          (WidgetClass) SuperClass,      /* superclass           */
120          "Checkbox",            /* class_name           */
121          sizeof(CheckboxRec),   /* size                 */
122          CheckboxClassInit,     /* class_initialize     */
123          NULL,                  /* class_part_initialize  */
124          FALSE,                 /* class_inited         */
125          CheckboxInit,          /* initialize           */
126          NULL,                  /* initialize_hook      */
127 #if DRAW_CHECK
128          CheckboxRealize,       /* realize              */
129          actionsList,           /* actions              */
130          XtNumber(actionsList), /* num_actions          */
131 #else
132          XtInheritRealize,      /* realize              */
133          NULL,                  /* actions              */
134          0,                     /* num_actions          */
135 #endif
136          resources,             /* resources            */
137          XtNumber(resources),   /* resource_count       */
138          NULLQUARK,             /* xrm_class            */
139          TRUE,                  /* compress_motion      */
140          TRUE,                  /* compress_exposure    */
141          TRUE,                  /* compress_enterleave  */
142          FALSE,                 /* visible_interest     */
143          NULL,                  /* destroy              */
144          XtInheritResize,       /* resize               */
145          XtInheritExpose,       /* expose               */
146          NULL,                  /* set_values           */
147          NULL,                  /* set_values_hook      */
148          XtInheritSetValuesAlmost,      /* set_values_almost    */
149          NULL,                  /* get_values_hook      */
150          NULL,                  /* accept_focus         */
151          XtVersion,             /* version              */
152          NULL,                  /* callback_private     */
153 #if DRAW_CHECK
154          defaultTranslations,   /* tm_table             */
155 #else
156          XtInheritTranslations, /* tm_table             */
157 #endif
158          XtInheritQueryGeometry,        /* query_geometry       */
159          XtInheritDisplayAccelerator,   /* display_accelerator  */
160          NULL                   /* extension            */
161          }
162         ,                       /* CoreClass fields initialization */
163         {
164          XtInheritChangeSensitive       /* change_sensitive     */
165          }
166         ,                       /* SimpleClass fields initialization */
167 #ifdef  _ThreeDP_h
168         {
169          XtInheritXaw3dShadowDraw       /* field not used       */
170          }
171         ,                       /* ThreeDClass fields initialization */
172 #endif
173         {
174          0                      /* field not used     */
175          }
176         ,                       /* LabelClass fields initialization */
177         {
178          0                      /* field not used     */
179          }
180         ,                       /* CommandClass fields initialization */
181         {
182          RadioSet,              /* Set Procedure.       */
183          RadioUnset,            /* Unset Procedure.     */
184          NULL                   /* extension.           */
185          }
186         ,                       /* ToggleClass fields initialization */
187         {
188          BOX_SIZE,
189          DrawCheck,             /* draw procedure */
190          NULL                   /* extension. */
191          }
192         ,                       /* RadioClass fields initialization */
193         {
194          NULL                   /* extension. */
195          }
196         ,                       /* CheckboxClass fields initialization */
197 };
198
199   /* for public consumption */
200 WidgetClass checkboxWidgetClass = (WidgetClass) & checkboxClassRec;
201 \f
202 /****************************************************************
203  *
204  * Class Methods
205  *
206  ****************************************************************/
207
208 static void CheckboxClassInit(void)
209 {
210         XawInitializeWidgetSet();
211 }
212
213  /*ARGSUSED*/
214     static void
215 CheckboxInit(Widget request, Widget new, ArgList args, Cardinal * num_args)
216 {
217 #if DRAW_CHECK
218         CheckboxWidget cw = (CheckboxWidget) new;
219         cw->checkbox.checkmark = None;
220         cw->checkbox.checkmark_GC = None;
221 #endif
222 }
223
224 #if DRAW_CHECK
225 static void
226 CheckboxRealize(Widget w, Mask * valueMask, XSetWindowAttributes * attributes)
227 {
228         CheckboxWidget cw = (CheckboxWidget) w;
229         XtGCMask value_mask, dynamic_mask, dontcare_mask;
230         XGCValues values;
231
232         /* first, call superclass realize */
233         (*checkboxWidgetClass->core_class.superclass->core_class.realize)
234             (w, valueMask, attributes);
235
236         /* TODO: cache this via xmu */
237         if (cw->checkbox.checkmark == None)
238                 cw->checkbox.checkmark =
239                     XCreateBitmapFromData(XtDisplay(w), XtWindow(w),
240                                           check_bits, check_width,
241                                           check_height);
242
243         values.fill_style = FillStippled;
244         values.stipple = cw->checkbox.checkmark;
245         values.foreground = cw->label.foreground;
246         value_mask = GCFillStyle | GCStipple | GCForeground;
247         dynamic_mask = GCTileStipXOrigin | GCTileStipYOrigin;
248         dontcare_mask = GCLineWidth | GCLineStyle | GCCapStyle | GCJoinStyle |
249             GCFont | GCSubwindowMode | GCGraphicsExposures |
250             GCDashOffset | GCDashList | GCArcMode;
251         cw->checkbox.checkmark_GC =
252             XtAllocateGC(w, 0, value_mask, &values, dynamic_mask,
253                          dontcare_mask);
254 }
255 #endif
256
257 /*      Function Name: CheckboxDestroy
258  *      Description: Destroy Callback for checkbox widget.
259  *      Arguments: w - the checkbox widget that is being destroyed.
260  *                 junk, garbage - not used.
261  *      Returns: none.
262  */
263
264 /* ARGSUSED */
265 #if defined __GNUC__
266 static void
267 CheckboxDestroy(Widget w, XtPointer junk, XtPointer garbage)
268         __attribute__((unused));
269 #endif
270 static void
271 CheckboxDestroy(Widget w, XtPointer junk, XtPointer garbage)
272 {
273 #if DRAW_CHECK
274         CheckboxWidget cw = (CheckboxWidget) w;
275
276         /* TODO: cache this via xmu */
277         if (cw->checkbox.checkmark != None)
278                 XFreePixmap(XtDisplay(w), cw->checkbox.checkmark);
279         if (cw->checkbox.checkmark_GC != None)
280                 XtReleaseGC(w, cw->checkbox.checkmark_GC);
281 #endif
282 }
283 \f
284 #if DRAW_CHECK
285 /************************************************************
286  *
287  *  Actions Procedures
288  *
289  ************************************************************/
290
291 /* ARGSUSED */
292 static void CheckboxPress(Widget w, XEvent * event, String * params,    /* unused */
293                           Cardinal * num_params)
294 {                               /* unused */
295         CheckboxWidget cw = (CheckboxWidget) w;
296         if (!cw->checkbox.pressed) {
297                 cw->checkbox.pressed = TRUE;
298                 ((CheckboxWidgetClass) (w->core.widget_class))->radio_class.
299                     drawDiamond(w);
300         }
301 }
302
303 static void CheckboxUnpress(Widget w, XEvent * event, String * params,  /* unused */
304                             Cardinal * num_params)
305 {                               /* unused */
306         CheckboxWidget cw = (CheckboxWidget) w;
307         int i;
308
309         if (cw->checkbox.pressed) {
310                 cw->checkbox.pressed = FALSE;
311                 if (*num_params > 0 && **params == 'd')
312                         ((CheckboxWidgetClass) (w->core.widget_class))->
313                             radio_class.drawDiamond(w);
314         }
315 }
316 #endif
317 \f
318 /************************************************************
319  *
320  *  Internal Procedures
321  *
322  ************************************************************/
323
324 static void DrawCheck(Widget w)
325 {
326         CheckboxWidget cw = (CheckboxWidget) w;
327         Display *dpy = XtDisplay(w);
328         Window win = XtWindow(w);
329         GC gc;
330
331 #ifdef  _ThreeDP_h
332         XPoint pts[6];
333 #endif
334         Dimension s = swid(cw);
335         Dimension bsz = bsize(cw);
336         Position bx, by;        /* Check upper-left */
337         Dimension bw, bh;
338 #ifdef  _ThreeDP_h
339         GC top, bot;
340 #endif
341         GC ctr;
342
343         /* foreground GC */
344         gc = XtIsSensitive(w) ? cw->command.normal_GC : cw->label.gray_GC;
345
346         bw = bh = bs(cw);
347         bx = cw->label.internal_width;
348         by = cw->core.height / 2 - bh / 2;
349
350 #ifdef  _ThreeDP_h
351         if (!cw->command.set) {
352                 top = cw->threeD.top_shadow_GC;
353                 bot = cw->threeD.bot_shadow_GC;
354         } else {
355                 top = cw->threeD.bot_shadow_GC;
356                 bot = cw->threeD.top_shadow_GC;
357         }
358         ctr = cw->command.inverse_GC;
359 #else
360         ctr = cw->command.set ? cw->command.normal_GC : cw->command.inverse_GC;
361 #endif
362
363         XFillRectangle(dpy, win, ctr, bx + s, by + s, bsz, bsz);
364
365 #ifdef  _ThreeDP_h
366         /* top-left shadow */
367         pts[0].x = bx;
368         pts[0].y = by;
369         pts[1].x = bw;
370         pts[1].y = 0;
371         pts[2].x = -s;
372         pts[2].y = s;
373         pts[3].x = -bsz;
374         pts[3].y = 0;
375         pts[4].x = 0;
376         pts[4].y = bsz;
377         pts[5].x = -s;
378         pts[5].y = s;
379         XFillPolygon(dpy, win, top, pts, 6, Nonconvex, CoordModePrevious);
380         /* bottom-right shadow */
381         pts[0].x = bx + bw;
382         pts[0].y = by + bh;
383         pts[1].x = -bw;
384         pts[1].y = 0;
385         pts[2].x = s;
386         pts[2].y = -s;
387         pts[3].x = bsz;
388         pts[3].y = 0;
389         pts[4].x = 0;
390         pts[4].y = -bsz;
391         pts[5].x = s;
392         pts[5].y = -s;
393         XFillPolygon(dpy, win, bot, pts, 6, Nonconvex, CoordModePrevious);
394 #else
395         XDrawRectangle(dpy, win, gc, bx + s, by + s, bsz, bsz);
396 #endif
397
398 #if DRAW_CHECK
399         if (cw->command.set && cw->checkbox.checkmark_GC != None) {
400                 XSetTSOrigin(dpy, cw->checkbox.checkmark_GC, bx + s, by + s);
401                 XFillRectangle(dpy, win, cw->checkbox.checkmark_GC,
402                                bx + s, by + s, check_width, check_height);
403         }
404 #endif
405 }