711e9007ae523d664a66c3aa0d781d63455eafb1
[framework/uifw/xorg/lib/libxaw.git] / src / Simple.c
1 /***********************************************************
2
3 Copyright 1987, 1988, 1994, 1998  The Open Group
4
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
24
25
26 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
27
28                         All Rights Reserved
29
30 Permission to use, copy, modify, and distribute this software and its 
31 documentation for any purpose and without fee is hereby granted, 
32 provided that the above copyright notice appear in all copies and that
33 both that copyright notice and this permission notice appear in 
34 supporting documentation, and that the name of Digital not be
35 used in advertising or publicity pertaining to distribution of the
36 software without specific, written prior permission.  
37
38 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
44 SOFTWARE.
45
46 ******************************************************************/
47
48 #ifdef HAVE_CONFIG_H
49 #include <config.h>
50 #endif
51 #include <stdio.h>
52 #include <X11/IntrinsicP.h>
53 #include <X11/StringDefs.h>
54 #include <X11/Xmu/Drawing.h>
55 #include <X11/Xmu/SysUtil.h>
56 #include <X11/Xaw/SimpleP.h>
57 #include <X11/Xaw/XawInit.h>
58 #include "Private.h"
59 #ifndef OLDXAW
60 #include <X11/Xaw/Tip.h>
61 #endif
62
63 /*
64  * Class Methods
65  */
66 static Bool ChangeSensitive(Widget);
67 static void XawSimpleClassInitialize(void);
68 static void XawSimpleClassPartInitialize(WidgetClass);
69 #ifndef OLDXAW
70 static void XawSimpleInitialize(Widget, Widget, ArgList, Cardinal*);
71 static void XawSimpleDestroy(Widget);
72 static void XawSimpleExpose(Widget, XEvent*, Region);
73 #endif
74 static void XawSimpleRealize(Widget, Mask*, XSetWindowAttributes*);
75 static Boolean XawSimpleSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
76
77 /*
78  * Prototypes
79  */
80 static void ConvertCursor(Widget);
81
82 /*
83  * Initialization
84  */
85 #ifndef OLDXAW
86 static XtActionsRec actions[] = {
87   {"set-values", XawSetValuesAction},
88   {"get-values", XawGetValuesAction},
89   {"declare",    XawDeclareAction},
90   {"call-proc",  XawCallProcAction},
91 };
92 #endif
93
94 #define offset(field) XtOffsetOf(SimpleRec, simple.field)
95 static XtResource resources[] = {
96   {
97     XtNcursor,
98     XtCCursor,
99     XtRCursor,
100     sizeof(Cursor),
101     offset(cursor),
102     XtRImmediate,
103     (XtPointer)None
104   },
105   {
106     XtNinsensitiveBorder,
107     XtCInsensitive,
108     XtRPixmap,
109     sizeof(Pixmap),
110     offset(insensitive_border),
111     XtRImmediate,
112     NULL
113   },
114   {
115     XtNpointerColor,
116     XtCForeground,
117     XtRPixel,
118     sizeof(Pixel),
119     offset(pointer_fg),
120     XtRString,
121     XtDefaultForeground
122   },
123   {
124     XtNpointerColorBackground,
125     XtCBackground,
126     XtRPixel,
127     sizeof(Pixel),
128     offset(pointer_bg),
129     XtRString,
130     XtDefaultBackground
131   },
132   {
133     XtNcursorName,
134     XtCCursor,
135     XtRString,
136     sizeof(String),
137     offset(cursor_name),
138     XtRString,
139     NULL
140   },
141   {
142     XtNinternational,
143     XtCInternational,
144     XtRBoolean,
145     sizeof(Boolean),
146     offset(international),
147     XtRImmediate,
148     (XtPointer)False
149   },
150 #ifndef OLDXAW
151   {
152     XawNdisplayList,
153     XawCDisplayList,
154     XawRDisplayList,
155     sizeof(XawDisplayList*),
156     offset(display_list),
157     XtRImmediate,
158     NULL
159   },
160   {
161     XtNtip,
162     XtCTip,
163     XtRString,
164     sizeof(String),
165     offset(tip),
166     XtRImmediate,
167     NULL
168   },
169 #endif
170 #undef offset
171 };
172
173 SimpleClassRec simpleClassRec = {
174   /* core */
175   {
176     (WidgetClass)&widgetClassRec,       /* superclass */
177     "Simple",                           /* class_name */
178     sizeof(SimpleRec),                  /* widget_size */
179     XawSimpleClassInitialize,           /* class_initialize */
180     XawSimpleClassPartInitialize,       /* class_part_initialize */
181     False,                              /* class_inited */
182 #ifndef OLDXAW
183     XawSimpleInitialize,                /* initialize */
184 #else
185     NULL,                               /* initialize */
186 #endif
187     NULL,                               /* initialize_hook */
188     XawSimpleRealize,                   /* realize */
189 #ifndef OLDXAW
190     actions,                            /* actions */
191     XtNumber(actions),                  /* num_actions */
192 #else
193     NULL,                               /* actions */
194     0,                                  /* num_actions */
195 #endif
196     resources,                          /* resources */
197     XtNumber(resources),                /* num_resources */
198     NULLQUARK,                          /* xrm_class */
199     True,                               /* compress_motion */
200     True,                               /* compress_exposure */
201     True,                               /* compress_enterleave */
202     False,                              /* visible_interest */
203 #ifndef OLDXAW
204     XawSimpleDestroy,                   /* destroy */
205 #else
206     NULL,                               /* destroy */
207 #endif
208     NULL,                               /* resize */
209 #ifndef OLDXAW
210     XawSimpleExpose,                    /* expose */
211 #else
212     NULL,                               /* expose */
213 #endif
214     XawSimpleSetValues,                 /* set_values */
215     NULL,                               /* set_values_hook */
216     XtInheritSetValuesAlmost,           /* set_values_almost */
217     NULL,                               /* get_values_hook */
218     NULL,                               /* accept_focus */
219     XtVersion,                          /* version */
220     NULL,                               /* callback_private */
221     NULL,                               /* tm_table */
222     XtInheritQueryGeometry,             /* query_geometry */
223     XtInheritDisplayAccelerator,        /* display_accelerator */
224     NULL,                               /* extension */
225   },
226   /* simple */
227   {
228     ChangeSensitive,                    /* change_sensitive */
229   },
230 };
231
232 WidgetClass simpleWidgetClass = (WidgetClass)&simpleClassRec;
233
234 static void
235 XawSimpleClassInitialize(void)
236 {
237     static XtConvertArgRec convertArg[] = {
238     {
239       XtWidgetBaseOffset,
240       (XtPointer)XtOffsetOf(WidgetRec, core.screen),
241       sizeof(Screen *)
242     },
243     {
244       XtResourceString,
245       (XtPointer)XtNpointerColor,
246       sizeof(Pixel)
247     },
248     {
249       XtResourceString,
250       (XtPointer)XtNpointerColorBackground,
251       sizeof(Pixel)
252     },
253     {
254       XtWidgetBaseOffset,
255       (XtPointer)XtOffsetOf(WidgetRec, core.colormap),
256       sizeof(Colormap)
257     },
258     };
259
260     XawInitializeWidgetSet();
261     XtSetTypeConverter(XtRString, XtRColorCursor, XmuCvtStringToColorCursor,
262                        convertArg, XtNumber(convertArg), XtCacheByDisplay, NULL);
263 }
264
265 static void
266 XawSimpleClassPartInitialize(WidgetClass cclass)
267 {
268     SimpleWidgetClass c = (SimpleWidgetClass)cclass;
269     SimpleWidgetClass super = (SimpleWidgetClass)c->core_class.superclass;
270
271     if (c->simple_class.change_sensitive == NULL) {
272         char buf[BUFSIZ];
273
274         (void)XmuSnprintf(buf, sizeof(buf),
275                           "%s Widget: The Simple Widget class method "
276                           "'change_sensitive' is undefined.\nA function "
277                           "must be defined or inherited.",
278                           c->core_class.class_name);
279         XtWarning(buf);
280         c->simple_class.change_sensitive = ChangeSensitive;
281     }
282
283     if (c->simple_class.change_sensitive == XtInheritChangeSensitive)
284         c->simple_class.change_sensitive = super->simple_class.change_sensitive;
285 }
286
287 #ifndef OLDXAW
288 /*ARGSUSED*/
289 static void
290 XawSimpleInitialize(Widget request, Widget cnew,
291                     ArgList args, Cardinal *num_args)
292 {
293     SimpleWidget simple = (SimpleWidget)cnew;
294
295     if (simple->simple.tip)
296         simple->simple.tip = XtNewString(simple->simple.tip);
297 }
298
299 static void
300 XawSimpleDestroy(Widget w)
301 {
302     SimpleWidget simple = (SimpleWidget)w;
303
304     if (simple->simple.tip)
305         XtFree((XtPointer)simple->simple.tip);
306 }
307 #endif
308
309 static void
310 XawSimpleRealize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes)
311 {
312 #ifndef OLDXAW
313     XawPixmap *pixmap;
314 #endif
315     Pixmap border_pixmap = CopyFromParent;
316
317   if (!XtIsSensitive(w))
318     {
319         /* change border to gray; have to remember the old one,
320          * so XtDestroyWidget deletes the proper one */
321         if (((SimpleWidget)w)->simple.insensitive_border == None)
322             ((SimpleWidget)w)->simple.insensitive_border =
323                 XmuCreateStippledPixmap(XtScreen(w),
324                                         w->core.border_pixel, 
325                                         w->core.background_pixel,
326                                         w->core.depth);
327         border_pixmap = w->core.border_pixmap;
328         attributes->border_pixmap =
329           w->core.border_pixmap = ((SimpleWidget)w)->simple.insensitive_border;
330
331         *valueMask |= CWBorderPixmap;
332         *valueMask &= ~CWBorderPixel;
333     }
334
335     ConvertCursor(w);
336
337     if ((attributes->cursor = ((SimpleWidget)w)->simple.cursor) != None)
338         *valueMask |= CWCursor;
339
340   XtCreateWindow(w, InputOutput, (Visual *)CopyFromParent,
341                  *valueMask, attributes);
342
343     if (!XtIsSensitive(w))
344         w->core.border_pixmap = border_pixmap;
345
346 #ifndef OLDXAW
347     if (w->core.background_pixmap > XtUnspecifiedPixmap) {
348         pixmap = XawPixmapFromXPixmap(w->core.background_pixmap, XtScreen(w),
349                                       w->core.colormap, w->core.depth);
350         if (pixmap && pixmap->mask)
351             XawReshapeWidget(w, pixmap);
352     }
353
354     if (((SimpleWidget)w)->simple.tip)
355         XawTipEnable(w);
356 #endif
357 }
358
359 /*
360  * Function:
361  *      ConvertCursor
362  *
363  * Parameters:
364  *      w - simple widget
365  *
366  * Description:
367  *      Converts a name to a new cursor.
368  */
369 static void
370 ConvertCursor(Widget w)
371 {
372     SimpleWidget simple = (SimpleWidget) w;
373     XrmValue from, to;
374     Cursor cursor = None;
375    
376     if (simple->simple.cursor_name == NULL)
377         return;
378
379     from.addr = (XPointer)simple->simple.cursor_name;
380     from.size = strlen((char *)from.addr) + 1;
381
382     to.size = sizeof(Cursor);
383     to.addr = (XPointer)&cursor;
384
385     if (XtConvertAndStore(w, XtRString, &from, XtRColorCursor, &to))
386       simple->simple.cursor = cursor;
387     else
388         XtAppErrorMsg(XtWidgetToApplicationContext(w),
389                       "convertFailed","ConvertCursor","XawError",
390                       "Simple: ConvertCursor failed.",
391                       NULL, NULL);
392 }
393
394
395 /*ARGSUSED*/
396 static Boolean
397 XawSimpleSetValues(Widget current, Widget request, Widget cnew,
398                    ArgList args, Cardinal *num_args)
399 {
400     SimpleWidget s_old = (SimpleWidget)current;
401     SimpleWidget s_new = (SimpleWidget)cnew;
402     Bool new_cursor = False;
403
404     /* this disables user changes after creation */
405     s_new->simple.international = s_old->simple.international;
406
407     if (XtIsSensitive(current) != XtIsSensitive(cnew))
408         (*((SimpleWidgetClass)XtClass(cnew))->simple_class.change_sensitive)
409            (cnew);
410
411     if (s_old->simple.cursor != s_new->simple.cursor)
412         new_cursor = True;
413         
414     /*
415      * We are not handling the string cursor_name correctly here
416      */
417
418     if (s_old->simple.pointer_fg != s_new->simple.pointer_fg ||
419         s_old->simple.pointer_bg != s_new->simple.pointer_bg ||
420         s_old->simple.cursor_name != s_new->simple.cursor_name) {
421         ConvertCursor(cnew);
422         new_cursor = True;
423     }
424
425     if (new_cursor && XtIsRealized(cnew)) {
426         if (s_new->simple.cursor != None)
427             XDefineCursor(XtDisplay(cnew), XtWindow(cnew), s_new->simple.cursor);
428         else
429             XUndefineCursor(XtDisplay(cnew), XtWindow(cnew));
430       }
431
432 #ifndef OLDXAW
433     if (s_old->core.background_pixmap != s_new->core.background_pixmap) {
434         XawPixmap *opix, *npix;
435
436         opix = XawPixmapFromXPixmap(s_old->core.background_pixmap,
437                                     XtScreen(s_old), s_old->core.colormap,
438                                     s_old->core.depth);
439         npix = XawPixmapFromXPixmap(s_new->core.background_pixmap,
440                                     XtScreen(s_new), s_new->core.colormap,
441                                     s_new->core.depth);
442         if ((npix && npix->mask) || (opix && opix->mask))
443             XawReshapeWidget(cnew, npix);
444     }
445
446     if (s_old->simple.tip != s_new->simple.tip) {
447         if (s_old->simple.tip)
448             XtFree((XtPointer)s_old->simple.tip);
449         if (s_new->simple.tip)
450             s_new->simple.tip = XtNewString(s_new->simple.tip);
451     }
452
453     if (s_old->simple.tip && !s_new->simple.tip)
454         XawTipDisable(cnew);
455     else if (!s_old->simple.tip && s_new->simple.tip)
456         XawTipEnable(cnew);
457
458     if (s_old->simple.display_list != s_new->simple.display_list)
459         return (True);
460 #endif /* OLDXAW */
461
462     return (False);
463 }
464
465 #ifndef OLDXAW
466 static void
467 XawSimpleExpose(Widget w, XEvent *event, Region region)
468 {
469     SimpleWidget xaw = (SimpleWidget)w;
470
471     if (xaw->simple.display_list)
472         XawRunDisplayList(w, xaw->simple.display_list, event, region);
473 }
474 #endif
475
476 static Bool
477 ChangeSensitive(Widget w)
478 {
479     if (XtIsRealized(w)) {
480         if (XtIsSensitive(w))
481             if (w->core.border_pixmap != XtUnspecifiedPixmap)
482             XSetWindowBorderPixmap(XtDisplay(w), XtWindow(w),
483                                     w->core.border_pixmap);
484             else
485                 XSetWindowBorder(XtDisplay(w), XtWindow(w),
486                                  w->core.border_pixel);
487         else {
488             if (((SimpleWidget)w)->simple.insensitive_border == None)
489                 ((SimpleWidget)w)->simple.insensitive_border =
490                     XmuCreateStippledPixmap(XtScreen(w),
491                                             w->core.border_pixel, 
492                                             w->core.background_pixel,
493                                             w->core.depth);
494             XSetWindowBorderPixmap(XtDisplay(w), XtWindow(w),
495                                    ((SimpleWidget)w)->simple.insensitive_border);
496         }
497     }
498
499     return (False);
500 }