Simple.c revision 994689c1
1/***********************************************************
2
3Copyright 1987, 1988, 1994, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25
26Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
27
28                        All Rights Reserved
29
30Permission to use, copy, modify, and distribute this software and its
31documentation for any purpose and without fee is hereby granted,
32provided that the above copyright notice appear in all copies and that
33both that copyright notice and this permission notice appear in
34supporting documentation, and that the name of Digital not be
35used in advertising or publicity pertaining to distribution of the
36software without specific, written prior permission.
37
38DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
44SOFTWARE.
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 */
66static Bool ChangeSensitive(Widget);
67static void XawSimpleClassInitialize(void);
68static void XawSimpleClassPartInitialize(WidgetClass);
69#ifndef OLDXAW
70static void XawSimpleInitialize(Widget, Widget, ArgList, Cardinal*);
71static void XawSimpleDestroy(Widget);
72static void XawSimpleExpose(Widget, XEvent*, Region);
73#endif
74static void XawSimpleRealize(Widget, Mask*, XSetWindowAttributes*);
75static Boolean XawSimpleSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
76
77/*
78 * Prototypes
79 */
80static void ConvertCursor(Widget);
81
82/*
83 * Initialization
84 */
85#ifndef OLDXAW
86static 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)
95static 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
173SimpleClassRec 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
232WidgetClass simpleWidgetClass = (WidgetClass)&simpleClassRec;
233
234static void
235XawSimpleClassInitialize(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
265static void
266XawSimpleClassPartInitialize(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*/
289static void
290XawSimpleInitialize(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
299static void
300XawSimpleDestroy(Widget w)
301{
302    SimpleWidget simple = (SimpleWidget)w;
303
304    if (simple->simple.tip)
305	XtFree((XtPointer)simple->simple.tip);
306}
307#endif
308
309static void
310XawSimpleRealize(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 */
369static void
370ConvertCursor(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*/
396static Boolean
397XawSimpleSetValues(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
466static void
467XawSimpleExpose(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
476static Bool
477ChangeSensitive(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}
501