Simple.c revision 421c997b
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/Xaw/SimpleP.h>
56#include <X11/Xaw/XawInit.h>
57#include "Private.h"
58#ifndef OLDXAW
59#include <X11/Xaw/Tip.h>
60#endif
61
62/*
63 * Class Methods
64 */
65static Bool ChangeSensitive(Widget);
66static void XawSimpleClassInitialize(void);
67static void XawSimpleClassPartInitialize(WidgetClass);
68#ifndef OLDXAW
69static void XawSimpleInitialize(Widget, Widget, ArgList, Cardinal*);
70static void XawSimpleDestroy(Widget);
71static void XawSimpleExpose(Widget, XEvent*, Region);
72#endif
73static void XawSimpleRealize(Widget, Mask*, XSetWindowAttributes*);
74static Boolean XawSimpleSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
75
76/*
77 * Prototypes
78 */
79static void ConvertCursor(Widget);
80
81/*
82 * Initialization
83 */
84#ifndef OLDXAW
85static XtActionsRec actions[] = {
86  {"set-values", XawSetValuesAction},
87  {"get-values", XawGetValuesAction},
88  {"declare",    XawDeclareAction},
89  {"call-proc",  XawCallProcAction},
90};
91#endif
92
93#define offset(field) XtOffsetOf(SimpleRec, simple.field)
94static XtResource resources[] = {
95  {
96    XtNcursor,
97    XtCCursor,
98    XtRCursor,
99    sizeof(Cursor),
100    offset(cursor),
101    XtRImmediate,
102    (XtPointer)None
103  },
104  {
105    XtNinsensitiveBorder,
106    XtCInsensitive,
107    XtRPixmap,
108    sizeof(Pixmap),
109    offset(insensitive_border),
110    XtRImmediate,
111    NULL
112  },
113  {
114    XtNpointerColor,
115    XtCForeground,
116    XtRPixel,
117    sizeof(Pixel),
118    offset(pointer_fg),
119    XtRString,
120    XtDefaultForeground
121  },
122  {
123    XtNpointerColorBackground,
124    XtCBackground,
125    XtRPixel,
126    sizeof(Pixel),
127    offset(pointer_bg),
128    XtRString,
129    XtDefaultBackground
130  },
131  {
132    XtNcursorName,
133    XtCCursor,
134    XtRString,
135    sizeof(String),
136    offset(cursor_name),
137    XtRString,
138    NULL
139  },
140  {
141    XtNinternational,
142    XtCInternational,
143    XtRBoolean,
144    sizeof(Boolean),
145    offset(international),
146    XtRImmediate,
147    (XtPointer)False
148  },
149#ifndef OLDXAW
150  {
151    XawNdisplayList,
152    XawCDisplayList,
153    XawRDisplayList,
154    sizeof(XawDisplayList*),
155    offset(display_list),
156    XtRImmediate,
157    NULL
158  },
159  {
160    XtNtip,
161    XtCTip,
162    XtRString,
163    sizeof(String),
164    offset(tip),
165    XtRImmediate,
166    NULL
167  },
168#endif
169#undef offset
170};
171
172SimpleClassRec simpleClassRec = {
173  /* core */
174  {
175    (WidgetClass)&widgetClassRec,	/* superclass */
176    "Simple",				/* class_name */
177    sizeof(SimpleRec),			/* widget_size */
178    XawSimpleClassInitialize,		/* class_initialize */
179    XawSimpleClassPartInitialize,	/* class_part_initialize */
180    False,				/* class_inited */
181#ifndef OLDXAW
182    XawSimpleInitialize,		/* initialize */
183#else
184    NULL,				/* initialize */
185#endif
186    NULL,				/* initialize_hook */
187    XawSimpleRealize,			/* realize */
188#ifndef OLDXAW
189    actions,				/* actions */
190    XtNumber(actions),			/* num_actions */
191#else
192    NULL,				/* actions */
193    0,					/* num_actions */
194#endif
195    resources,				/* resources */
196    XtNumber(resources),		/* num_resources */
197    NULLQUARK,				/* xrm_class */
198    True,				/* compress_motion */
199    True,				/* compress_exposure */
200    True,				/* compress_enterleave */
201    False,				/* visible_interest */
202#ifndef OLDXAW
203    XawSimpleDestroy,			/* destroy */
204#else
205    NULL,				/* destroy */
206#endif
207    NULL,				/* resize */
208#ifndef OLDXAW
209    XawSimpleExpose,			/* expose */
210#else
211    NULL,				/* expose */
212#endif
213    XawSimpleSetValues,			/* set_values */
214    NULL,				/* set_values_hook */
215    XtInheritSetValuesAlmost,		/* set_values_almost */
216    NULL,				/* get_values_hook */
217    NULL,				/* accept_focus */
218    XtVersion,				/* version */
219    NULL,				/* callback_private */
220    NULL,				/* tm_table */
221    XtInheritQueryGeometry,		/* query_geometry */
222    XtInheritDisplayAccelerator,	/* display_accelerator */
223    NULL,				/* extension */
224  },
225  /* simple */
226  {
227    ChangeSensitive,			/* change_sensitive */
228  },
229};
230
231WidgetClass simpleWidgetClass = (WidgetClass)&simpleClassRec;
232
233static void
234XawSimpleClassInitialize(void)
235{
236    static XtConvertArgRec convertArg[] = {
237    {
238      XtWidgetBaseOffset,
239      (XtPointer)XtOffsetOf(WidgetRec, core.screen),
240      sizeof(Screen *)
241    },
242    {
243      XtResourceString,
244      (XtPointer)XtNpointerColor,
245      sizeof(Pixel)
246    },
247    {
248      XtResourceString,
249      (XtPointer)XtNpointerColorBackground,
250      sizeof(Pixel)
251    },
252    {
253      XtWidgetBaseOffset,
254      (XtPointer)XtOffsetOf(WidgetRec, core.colormap),
255      sizeof(Colormap)
256    },
257    };
258
259    XawInitializeWidgetSet();
260    XtSetTypeConverter(XtRString, XtRColorCursor, XmuCvtStringToColorCursor,
261		       convertArg, XtNumber(convertArg), XtCacheByDisplay, NULL);
262}
263
264static void
265XawSimpleClassPartInitialize(WidgetClass cclass)
266{
267    SimpleWidgetClass c = (SimpleWidgetClass)cclass;
268    SimpleWidgetClass super = (SimpleWidgetClass)c->core_class.superclass;
269
270    if (c->simple_class.change_sensitive == NULL) {
271	char buf[BUFSIZ];
272
273	snprintf(buf, sizeof(buf),
274		 "%s Widget: The Simple Widget class method "
275		 "'change_sensitive' is undefined.\n"
276		 "A function must be defined or inherited.",
277		 c->core_class.class_name);
278	XtWarning(buf);
279	c->simple_class.change_sensitive = ChangeSensitive;
280    }
281
282    if (c->simple_class.change_sensitive == XtInheritChangeSensitive)
283	c->simple_class.change_sensitive = super->simple_class.change_sensitive;
284}
285
286#ifndef OLDXAW
287/*ARGSUSED*/
288static void
289XawSimpleInitialize(Widget request, Widget cnew,
290		    ArgList args, Cardinal *num_args)
291{
292    SimpleWidget simple = (SimpleWidget)cnew;
293
294    if (simple->simple.tip)
295	simple->simple.tip = XtNewString(simple->simple.tip);
296}
297
298static void
299XawSimpleDestroy(Widget w)
300{
301    SimpleWidget simple = (SimpleWidget)w;
302
303    if (simple->simple.tip)
304	XtFree((XtPointer)simple->simple.tip);
305}
306#endif
307
308static void
309XawSimpleRealize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes)
310{
311#ifndef OLDXAW
312    XawPixmap *pixmap;
313#endif
314    Pixmap border_pixmap = CopyFromParent;
315
316  if (!XtIsSensitive(w))
317    {
318	/* change border to gray; have to remember the old one,
319	 * so XtDestroyWidget deletes the proper one */
320	if (((SimpleWidget)w)->simple.insensitive_border == None)
321	    ((SimpleWidget)w)->simple.insensitive_border =
322		XmuCreateStippledPixmap(XtScreen(w),
323					w->core.border_pixel,
324					w->core.background_pixel,
325					w->core.depth);
326        border_pixmap = w->core.border_pixmap;
327	attributes->border_pixmap =
328	  w->core.border_pixmap = ((SimpleWidget)w)->simple.insensitive_border;
329
330	*valueMask |= CWBorderPixmap;
331	*valueMask &= ~CWBorderPixel;
332    }
333
334    ConvertCursor(w);
335
336    if ((attributes->cursor = ((SimpleWidget)w)->simple.cursor) != None)
337	*valueMask |= CWCursor;
338
339  XtCreateWindow(w, InputOutput, (Visual *)CopyFromParent,
340		 *valueMask, attributes);
341
342    if (!XtIsSensitive(w))
343	w->core.border_pixmap = border_pixmap;
344
345#ifndef OLDXAW
346    if (w->core.background_pixmap > XtUnspecifiedPixmap) {
347	pixmap = XawPixmapFromXPixmap(w->core.background_pixmap, XtScreen(w),
348				      w->core.colormap, w->core.depth);
349	if (pixmap && pixmap->mask)
350	    XawReshapeWidget(w, pixmap);
351    }
352
353    if (((SimpleWidget)w)->simple.tip)
354	XawTipEnable(w);
355#endif
356}
357
358/*
359 * Function:
360 *	ConvertCursor
361 *
362 * Parameters:
363 *	w - simple widget
364 *
365 * Description:
366 *	Converts a name to a new cursor.
367 */
368static void
369ConvertCursor(Widget w)
370{
371    SimpleWidget simple = (SimpleWidget) w;
372    XrmValue from, to;
373    Cursor cursor = None;
374
375    if (simple->simple.cursor_name == NULL)
376	return;
377
378    from.addr = (XPointer)simple->simple.cursor_name;
379    from.size = strlen((char *)from.addr) + 1;
380
381    to.size = sizeof(Cursor);
382    to.addr = (XPointer)&cursor;
383
384    if (XtConvertAndStore(w, XtRString, &from, XtRColorCursor, &to))
385      simple->simple.cursor = cursor;
386    else
387	XtAppErrorMsg(XtWidgetToApplicationContext(w),
388		      "convertFailed","ConvertCursor","XawError",
389		      "Simple: ConvertCursor failed.",
390		      NULL, NULL);
391}
392
393
394/*ARGSUSED*/
395static Boolean
396XawSimpleSetValues(Widget current, Widget request, Widget cnew,
397		   ArgList args, Cardinal *num_args)
398{
399    SimpleWidget s_old = (SimpleWidget)current;
400    SimpleWidget s_new = (SimpleWidget)cnew;
401    Bool new_cursor = False;
402
403    /* this disables user changes after creation */
404    s_new->simple.international = s_old->simple.international;
405
406    if (XtIsSensitive(current) != XtIsSensitive(cnew))
407	(*((SimpleWidgetClass)XtClass(cnew))->simple_class.change_sensitive)
408	   (cnew);
409
410    if (s_old->simple.cursor != s_new->simple.cursor)
411	new_cursor = True;
412
413    /*
414     * We are not handling the string cursor_name correctly here
415     */
416
417    if (s_old->simple.pointer_fg != s_new->simple.pointer_fg ||
418	s_old->simple.pointer_bg != s_new->simple.pointer_bg ||
419	s_old->simple.cursor_name != s_new->simple.cursor_name) {
420	ConvertCursor(cnew);
421	new_cursor = True;
422    }
423
424    if (new_cursor && XtIsRealized(cnew)) {
425	if (s_new->simple.cursor != None)
426	    XDefineCursor(XtDisplay(cnew), XtWindow(cnew), s_new->simple.cursor);
427	else
428	    XUndefineCursor(XtDisplay(cnew), XtWindow(cnew));
429      }
430
431#ifndef OLDXAW
432    if (s_old->core.background_pixmap != s_new->core.background_pixmap) {
433	XawPixmap *opix, *npix;
434
435	opix = XawPixmapFromXPixmap(s_old->core.background_pixmap,
436				    XtScreen(s_old), s_old->core.colormap,
437				    s_old->core.depth);
438	npix = XawPixmapFromXPixmap(s_new->core.background_pixmap,
439				    XtScreen(s_new), s_new->core.colormap,
440				    s_new->core.depth);
441	if ((npix && npix->mask) || (opix && opix->mask))
442	    XawReshapeWidget(cnew, npix);
443    }
444
445    if (s_old->simple.tip != s_new->simple.tip) {
446	if (s_old->simple.tip)
447	    XtFree((XtPointer)s_old->simple.tip);
448	if (s_new->simple.tip)
449	    s_new->simple.tip = XtNewString(s_new->simple.tip);
450    }
451
452    if (s_old->simple.tip && !s_new->simple.tip)
453	XawTipDisable(cnew);
454    else if (!s_old->simple.tip && s_new->simple.tip)
455	XawTipEnable(cnew);
456
457    if (s_old->simple.display_list != s_new->simple.display_list)
458	return (True);
459#endif /* OLDXAW */
460
461    return (False);
462}
463
464#ifndef OLDXAW
465static void
466XawSimpleExpose(Widget w, XEvent *event, Region region)
467{
468    SimpleWidget xaw = (SimpleWidget)w;
469
470    if (xaw->simple.display_list)
471	XawRunDisplayList(w, xaw->simple.display_list, event, region);
472}
473#endif
474
475static Bool
476ChangeSensitive(Widget w)
477{
478    if (XtIsRealized(w)) {
479	if (XtIsSensitive(w))
480	    if (w->core.border_pixmap != XtUnspecifiedPixmap)
481	    XSetWindowBorderPixmap(XtDisplay(w), XtWindow(w),
482				    w->core.border_pixmap);
483	    else
484		XSetWindowBorder(XtDisplay(w), XtWindow(w),
485				 w->core.border_pixel);
486	else {
487	    if (((SimpleWidget)w)->simple.insensitive_border == None)
488		((SimpleWidget)w)->simple.insensitive_border =
489		    XmuCreateStippledPixmap(XtScreen(w),
490					    w->core.border_pixel,
491					    w->core.background_pixel,
492					    w->core.depth);
493	    XSetWindowBorderPixmap(XtDisplay(w), XtWindow(w),
494				   ((SimpleWidget)w)->simple.insensitive_border);
495	}
496    }
497
498    return (False);
499}
500