Object.c revision a3bd7f05
1/***********************************************************
2Copyright (c) 1993, Oracle and/or its affiliates. All rights reserved.
3
4Permission is hereby granted, free of charge, to any person obtaining a
5copy of this software and associated documentation files (the "Software"),
6to deal in the Software without restriction, including without limitation
7the rights to use, copy, modify, merge, publish, distribute, sublicense,
8and/or sell copies of the Software, and to permit persons to whom the
9Software is furnished to do so, subject to the following conditions:
10
11The above copyright notice and this permission notice (including the next
12paragraph) shall be included in all copies or substantial portions of the
13Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21DEALINGS IN THE SOFTWARE.
22
23Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
24
25                        All Rights Reserved
26
27Permission to use, copy, modify, and distribute this software and its
28documentation for any purpose and without fee is hereby granted,
29provided that the above copyright notice appear in all copies and that
30both that copyright notice and this permission notice appear in
31supporting documentation, and that the name of Digital not be
32used in advertising or publicity pertaining to distribution of the
33software without specific, written prior permission.
34
35DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
36ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
37DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
38ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
39WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
40ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
41SOFTWARE.
42
43******************************************************************/
44
45/*
46
47Copyright 1987, 1988, 1994, 1998  The Open Group
48
49Permission to use, copy, modify, distribute, and sell this software and its
50documentation for any purpose is hereby granted without fee, provided that
51the above copyright notice appear in all copies and that both that
52copyright notice and this permission notice appear in supporting
53documentation.
54
55The above copyright notice and this permission notice shall be included in
56all copies or substantial portions of the Software.
57
58THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
61OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
62AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
63CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
64
65Except as contained in this notice, the name of The Open Group shall not be
66used in advertising or otherwise to promote the sale, use or other dealings
67in this Software without prior written authorization from The Open Group.
68
69*/
70
71#ifdef HAVE_CONFIG_H
72#include <config.h>
73#endif
74#include "IntrinsicI.h"
75#include "StringDefs.h"
76
77/* *INDENT-OFF* */
78static XtResource resources[] = {
79    {XtNdestroyCallback, XtCCallback, XtRCallback,sizeof(XtPointer),
80     XtOffsetOf(ObjectRec,object.destroy_callbacks),
81     XtRCallback, (XtPointer)NULL}
82};
83/* *INDENT-ON* */
84
85static void ObjectClassPartInitialize(WidgetClass);
86static Boolean ObjectSetValues(Widget, Widget, Widget, ArgList, Cardinal *);
87static void ObjectDestroy(Widget);
88
89/* *INDENT-OFF* */
90externaldef(objectclassrec) ObjectClassRec objectClassRec = {
91  {
92    /* superclass              */ NULL,
93    /* class_name              */ "Object",
94    /* widget_size             */ sizeof(ObjectRec),
95    /* class_initialize        */ NULL,
96    /* class_part_initialize   */ ObjectClassPartInitialize,
97    /* class_inited            */ FALSE,
98    /* initialize              */ NULL,
99    /* initialize_hook         */ NULL,
100    /* pad                     */ NULL,
101    /* pad                     */ NULL,
102    /* pad                     */ 0,
103    /* resources               */ resources,
104    /* num_resources           */ XtNumber(resources),
105    /* xrm_class               */ NULLQUARK,
106    /* pad                     */ FALSE,
107    /* pad                     */ FALSE,
108    /* pad                     */ FALSE,
109    /* pad                     */ FALSE,
110    /* destroy                 */ ObjectDestroy,
111    /* pad                     */ NULL,
112    /* pad                     */ NULL,
113    /* set_values              */ ObjectSetValues,
114    /* set_values_hook         */ NULL,
115    /* pad                     */ NULL,
116    /* get_values_hook         */ NULL,
117    /* pad                     */ NULL,
118    /* version                 */ XtVersion,
119    /* callback_offsets        */ NULL,
120    /* pad                     */ NULL,
121    /* pad                     */ NULL,
122    /* pad                     */ NULL,
123    /* extension               */ NULL
124  }
125};
126/* *INDENT-ON* */
127
128externaldef(objectClass)
129WidgetClass objectClass = (WidgetClass) &objectClassRec;
130
131/*
132 * Start of object routines.
133 */
134
135static void
136ConstructCallbackOffsets(WidgetClass myWidgetClass)
137{
138    static XrmQuark QCallback = NULLQUARK;
139    register int i;
140    register int tableSize;
141    register CallbackTable newTable;
142    register CallbackTable superTable;
143    register XrmResourceList resourceList;
144    ObjectClass myObjectClass = (ObjectClass) myWidgetClass;
145
146    /*
147       This function builds an array of pointers to the resource
148       structures which describe the callbacks for this widget class.
149       This array is special in that the 0th entry is the number of
150       callback pointers.
151     */
152
153    if (QCallback == NULLQUARK)
154        QCallback = XrmPermStringToQuark(XtRCallback);
155
156    if (myObjectClass->object_class.superclass != NULL) {
157        superTable = (CallbackTable)
158            ((ObjectClass) myObjectClass->object_class.
159             superclass)->object_class.callback_private;
160        tableSize = (int) (long) superTable[0];
161    }
162    else {
163        superTable = (CallbackTable) NULL;
164        tableSize = 0;
165    }
166
167    /* Count the number of callbacks */
168    resourceList = (XrmResourceList) myObjectClass->object_class.resources;
169    for (i = (int) myObjectClass->object_class.num_resources; --i >= 0;
170         resourceList++)
171        if (resourceList->xrm_type == QCallback)
172            tableSize++;
173
174    /*
175     * Allocate and load the table.  Make sure that the new callback
176     * offsets occur in the table ahead of the superclass callback
177     * offsets so that resource overrides work.
178     */
179    newTable = (CallbackTable)
180        __XtMalloc((Cardinal)
181                   (sizeof(XrmResource *) * (size_t) (tableSize + 1)));
182
183    newTable[0] = (XrmResource *) (long) tableSize;
184
185    if (superTable)
186        tableSize -= (int) (long) superTable[0];
187    resourceList = (XrmResourceList) myObjectClass->object_class.resources;
188    for (i = 1; tableSize > 0; resourceList++)
189        if (resourceList->xrm_type == QCallback) {
190            newTable[i++] = resourceList;
191            tableSize--;
192        }
193
194    if (superTable)
195        for (tableSize = (int) (long) *superTable++;
196             --tableSize >= 0; superTable++)
197            newTable[i++] = *superTable;
198
199    myObjectClass->object_class.callback_private = (XtPointer) newTable;
200}
201
202static void
203InheritObjectExtensionMethods(WidgetClass widget_class)
204{
205    ObjectClass oc = (ObjectClass) widget_class;
206    ObjectClassExtension ext, super_ext = NULL;
207
208    ext = (ObjectClassExtension)
209        XtGetClassExtension(widget_class,
210                            XtOffsetOf(ObjectClassRec, object_class.extension),
211                            NULLQUARK, XtObjectExtensionVersion,
212                            sizeof(ObjectClassExtensionRec));
213
214    if (oc->object_class.superclass)
215        super_ext = (ObjectClassExtension)
216            XtGetClassExtension(oc->object_class.superclass,
217                                XtOffsetOf(ObjectClassRec,
218                                           object_class.extension), NULLQUARK,
219                                XtObjectExtensionVersion,
220                                sizeof(ObjectClassExtensionRec));
221    LOCK_PROCESS;
222    if (ext) {
223        if (ext->allocate == XtInheritAllocate)
224            ext->allocate = (super_ext ? super_ext->allocate : NULL);
225        if (ext->deallocate == XtInheritDeallocate)
226            ext->deallocate = (super_ext ? super_ext->deallocate : NULL);
227    }
228    else if (super_ext) {
229        /* Be careful to inherit only what is appropriate */
230        ext = (ObjectClassExtension)
231            __XtCalloc(1, sizeof(ObjectClassExtensionRec));
232        ext->next_extension = oc->object_class.extension;
233        ext->record_type = NULLQUARK;
234        ext->version = XtObjectExtensionVersion;
235        ext->record_size = sizeof(ObjectClassExtensionRec);
236        ext->allocate = super_ext->allocate;
237        ext->deallocate = super_ext->deallocate;
238        oc->object_class.extension = (XtPointer) ext;
239    }
240    UNLOCK_PROCESS;
241}
242
243static void
244ObjectClassPartInitialize(register WidgetClass wc)
245{
246    ObjectClass oc = (ObjectClass) wc;
247
248    oc->object_class.xrm_class =
249        XrmPermStringToQuark(oc->object_class.class_name);
250
251    if (oc->object_class.resources)
252        _XtCompileResourceList(oc->object_class.resources,
253                               oc->object_class.num_resources);
254
255    ConstructCallbackOffsets(wc);
256    _XtResourceDependencies(wc);
257    InheritObjectExtensionMethods(wc);
258}
259
260static Boolean
261ObjectSetValues(Widget old,
262                Widget request _X_UNUSED,
263                Widget widget,
264                ArgList args _X_UNUSED,
265                Cardinal *num_args _X_UNUSED)
266{
267    CallbackTable offsets;
268    int i;
269
270    LOCK_PROCESS;
271    /* Compile any callback lists into internal form */
272    offsets = (CallbackTable) XtClass(widget)->core_class.callback_private;
273
274    for (i = (int) (long) *(offsets++); --i >= 0; offsets++) {
275        InternalCallbackList *ol, *nl;
276
277        ol = (InternalCallbackList *)
278            ((char *) old - (*offsets)->xrm_offset - 1);
279        nl = (InternalCallbackList *)
280            ((char *) widget - (*offsets)->xrm_offset - 1);
281        if (*ol != *nl) {
282            if (*ol != NULL)
283                XtFree((char *) *ol);
284            if (*nl != NULL)
285                *nl = _XtCompileCallbackList((XtCallbackList) *nl);
286        }
287    }
288    UNLOCK_PROCESS;
289    return False;
290}
291
292static void
293ObjectDestroy(register Widget widget)
294{
295    CallbackTable offsets;
296    int i;
297
298    /* Remove all callbacks associated with widget */
299    LOCK_PROCESS;
300    offsets = (CallbackTable)
301        widget->core.widget_class->core_class.callback_private;
302
303    for (i = (int) (long) *(offsets++); --i >= 0; offsets++) {
304        InternalCallbackList cl = *(InternalCallbackList *)
305            ((char *) widget - (*offsets)->xrm_offset - 1);
306
307        if (cl)
308            XtFree((char *) cl);
309    }
310    UNLOCK_PROCESS;
311}                               /* ObjectDestroy */
312