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