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