1 /**
2 *
3 * $Id: BaseClass.c,v 1.1 2004/08/28 19:22:43 dannybackx Exp $
4 *
5 * Copyright (C) 1995 Free Software Foundation, Inc.
6 * Copyright (C) 1995-2001 LessTif Development Team
7 *
8 * This file is part of the GNU LessTif Library.
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
19 *
20 * You should have received a copy of the GNU Library General Public
21 * License along with this library; if not, write to the Free
22 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 **/
25
26 static const char rcsid[] = "$Id: BaseClass.c,v 1.1 2004/08/28 19:22:43 dannybackx Exp $";
27
28 #include <LTconfig.h>
29
30 #include <stdio.h>
31 #include <string.h>
32
33 #include <XmI/XmI.h>
34 #include <Xm/XmP.h>
35 #include <Xm/BaseClassP.h>
36 #include <Xm/DisplayP.h>
37 #include <Xm/ExtObjectP.h>
38 #include <Xm/ScreenP.h>
39 #include <Xm/MenuShellP.h>
40 #include <Xm/DragIconP.h>
41 #include <Xm/DropTransP.h>
42 #include <Xm/VendorSEP.h>
43 #include <Xm/DropSMgrP.h>
44 #include <Xm/DialogS.h>
45
46 #include <X11/RectObjP.h>
47 #include <X11/Xutil.h>
48
49 #include <XmI/DebugUtil.h>
50
51
52 /* For the prototype police */
53
54 extern XmWrapperData _XmGetWrapperData(WidgetClass wc);
55 extern void _XmFreeWrapperData(XmWrapperData data);
56
57 /* Some global data */
58 XrmQuark XmQmotif = 0;
59 int _XmInheritClass = 0;
60 XmBaseClassExt *_Xm_fastPtr=0;
61
62 /*
63 * credit where credit is due. A good portion of the changes made today come
64 * from a patch submitted by Harald Albrecht. Don't blame him if you don't
65 * like the coding style, though -- that's my fault (MLM).
66 * Danny gets the credit for the XContext hint, though.
67 */
68 extern XmGenericClassExt *
_XmGetClassExtensionPtr(XmGenericClassExt * listHeadPtr,XrmQuark owner)69 _XmGetClassExtensionPtr(XmGenericClassExt *listHeadPtr,
70 XrmQuark owner)
71 {
72 XmGenericClassExt *ext = listHeadPtr;
73
74 while (ext && *ext && ((*ext)->record_type != owner))
75 {
76 ext = (XmGenericClassExt *)&((*ext)->next_extension);
77 }
78
79 return ext;
80 }
81
82
83 extern Boolean
_XmIsSlowSubclass(WidgetClass wc,unsigned int bit)84 _XmIsSlowSubclass(WidgetClass wc,
85 unsigned int bit)
86 {
87 XmBaseClassExt *bce;
88
89 bce = (XmBaseClassExt *)_XmGetBaseClassExtPtr(wc, XmQmotif);
90
91 if (!bce || !*bce)
92 {
93 return False;
94 }
95
96 if (_XmGetFlagsBit((*bce)->flags, bit))
97 {
98 return True;
99 }
100
101 return False;
102 }
103
104
105 /*
106 * Check a widget class for being a real (core) LessTif widget class. We
107 * consider application defined classes as not being standard (beep) widget
108 * classes.
109 */
110 extern Boolean
_XmIsStandardMotifWidgetClass(WidgetClass wc)111 _XmIsStandardMotifWidgetClass(WidgetClass wc)
112 {
113 XmBaseClassExt *bclass, *super;
114 unsigned char *flags, *sflags;
115 int i;
116
117 /*
118 * If the widget class in question has no extension record it is
119 * apparently no real LessTif widget class.
120 */
121 bclass = (XmBaseClassExt *)_XmGetBaseClassExtPtr(wc, XmQmotif);
122
123 if ((bclass == NULL) || (*bclass == NULL))
124 {
125 return False;
126 }
127
128 super = (XmBaseClassExt *)_XmGetBaseClassExtPtr(wc->core_class.superclass,
129 XmQmotif);
130
131 /*
132 * If our superclass has no extension record then we may be either
133 * a primitive or manager widget. But we're nice and just check for
134 * one of the fast subclass bits set. If we find a bit set, we assume
135 * for a standard motif class. But we consider only standard motif
136 * flags and not the application defined bits from bit 129 upwards.
137 */
138 if ((super == NULL) || (*super == NULL))
139 {
140 flags = (*bclass)->flags;
141
142 for (i = XmLAST_FAST_SUBCLASS_BIT << 3; i >= 0; i--)
143 {
144 if (flags[i] != 0)
145 {
146 return True;
147 }
148 }
149
150 return False;
151 }
152
153 /*
154 * Now make sure that the fast subclass flags differ at least in one bit.
155 * We only consider the standard motif flags, not the possible application
156 * defined bits from bit 129 on.
157 */
158 flags = (*bclass)->flags;
159 sflags = (*super)->flags;
160
161 for (i = XmLAST_FAST_SUBCLASS_BIT << 3; i >= 0; i--)
162 {
163 if (flags[i] != sflags[i])
164 {
165 return True;
166 }
167 }
168
169 return False;
170 }
171
172
173 /*
174 * according to Harald, this is for backwards compatibility only. A local
175 * function, BaseClassPartInitialize(), provides the functionality that
176 * used to be here.
177 */
178 extern void
_XmBaseClassPartInitialize(WidgetClass wc)179 _XmBaseClassPartInitialize(WidgetClass wc)
180 {
181 }
182
183 /* -----------------------------------------------
184 * Widget extension stuff
185 *
186 * why do I always forget about XContexts? Thanks, guys.
187 * 022296 - Harald pointed out to me today that some of these contexts will
188 * be used when the widget is unitialized, therefore XtWindow(widget) will
189 * return NULL. Not really a problem with the way they are currently used
190 * (prehook push, posthook pop), but it will be a problem with, say,
191 * VendorShellExt if we set the extension when the widget is unrealized, and
192 * do a get when the widget is realized (the XID part of the context call will
193 * be wrong, thus we won't get the right [if any] context data). Also, since
194 * they're unitialized, all will use the XID null value, and no longer be
195 * unique. He suggested that I might get around this problem by using the
196 * widget as the XID, which should take care of the uniqueness problem. Even
197 * though the methods for, e.g., get_values/set_values have other Widget values,
198 * we know that the program keeps the same value for the life of the widget,
199 * so we should be okay. Better not use this in class_part_initialize, though.
200 * But then again, why would you...
201 */
202 typedef struct _WidgetStack
203 {
204 struct _WidgetStack *next;
205 XmWidgetExtData data;
206 }
207 XmWidgetExtDataStackRec, *XmWidgetExtDataStackPtr;
208
209 /*
210 * associate a context with an extension type.
211 */
212 static XContext extContexts[XmDEFAULT_EXTENSION + 1] = { 0 };
213
214
215 static XContext
FindAssociatedContext(unsigned int extType)216 FindAssociatedContext(unsigned int extType)
217 {
218 if (extType > XmDEFAULT_EXTENSION)
219 {
220 _XmError(NULL, "Bad extension type for WidgetExtData.");
221 }
222
223 if (extContexts[extType] != 0)
224 {
225 return extContexts[extType];
226 }
227
228 extContexts[extType] = XUniqueContext();
229
230 return extContexts[extType];
231 }
232
233
234 /*
235 * nondestructively fetch an Extension data record. Hey Danny, this
236 * looks like a good way to find the VendorShellExt without looping
237 * through Composite children! Whadaya think?
238 */
239 extern XmWidgetExtData
_XmGetWidgetExtData(Widget widget,unsigned char extType)240 _XmGetWidgetExtData(Widget widget, unsigned char extType)
241 {
242 XContext c = FindAssociatedContext(extType);
243 XmWidgetExtDataStackPtr node;
244
245 if (XFindContext(XtDisplay(widget), (XID)widget, c, (XPointer *)&node) != 0)
246 {
247 return NULL;
248 }
249
250 return node->data;
251 }
252
253
254 extern void
_XmFreeWidgetExtData(Widget widget)255 _XmFreeWidgetExtData(Widget widget)
256 {
257 }
258
259
260 /*
261 * apparently, these can be chained...
262 */
263 extern void
_XmPushWidgetExtData(Widget widget,XmWidgetExtData data,unsigned char extType)264 _XmPushWidgetExtData(Widget widget,
265 XmWidgetExtData data,
266 unsigned char extType)
267 {
268 XContext c = FindAssociatedContext(extType);
269 XmWidgetExtDataStackPtr head = NULL, node;
270
271 node = (XmWidgetExtDataStackPtr)XtCalloc(1,
272 sizeof(XmWidgetExtDataStackRec));
273 node->data = data;
274
275 XFindContext(XtDisplay(widget), (XID)widget, c, (XPointer *)&head);
276
277 node->next = head;
278
279 XSaveContext(XtDisplay(widget), (XID)widget, c, (XPointer)node);
280 }
281
282
283 extern void
_XmPopWidgetExtData(Widget widget,XmWidgetExtData * dataRtn,unsigned char extType)284 _XmPopWidgetExtData(Widget widget,
285 XmWidgetExtData *dataRtn,
286 unsigned char extType)
287 {
288 XContext c = FindAssociatedContext(extType);
289 XmWidgetExtDataStackPtr node;
290
291 if (XFindContext(XtDisplay(widget), (XID)widget, c, (XPointer *)&node) != 0)
292 {
293 /*
294 * Only print this message if the widget is not in the process
295 * of being destroyed.
296 * This is a case in which the message doesn't make sense...
297 */
298 if (! widget->core.being_destroyed)
299 _XmError(widget, "No ExtNode to pop!");
300
301 *dataRtn = NULL;
302
303 return;
304 }
305
306 if (node->next)
307 {
308 XSaveContext(XtDisplay(widget), (XID)widget, c,
309 (XPointer)node->next);
310 }
311 else
312 {
313 XDeleteContext(XtDisplay(widget), (XID)widget, c);
314 }
315
316 *dataRtn = node->data;
317
318 XtFree((char *)node);
319 }
320
321
322 /* -------------------------------------------------------------
323 * Wrapper functions.
324 */
325 /*
326 * Returns the top-most entry on the per-widget-class stack without
327 * removing it from the stack. If the stack is empty or doesn't exists
328 * yet, the entry and the stacks are created on the fly.
329 */
330 XmWrapperData
_XmGetWrapperData(WidgetClass wc)331 _XmGetWrapperData(WidgetClass wc)
332 {
333 XmBaseClassExt *ext, bce;
334
335 ext = (XmBaseClassExt *)_XmGetBaseClassExtPtr(wc, XmQmotif);
336
337 if (*ext)
338 {
339 bce = *ext;
340
341 if (bce->version < XmBaseClassExtVersion)
342 {
343 return (XmWrapperData)NULL;
344 }
345 }
346 else
347 {
348 bce = (XmBaseClassExt)XtCalloc(1, sizeof(XmBaseClassExtRec));
349
350 bce->next_extension = NULL;
351 bce->record_type = XmQmotif;
352 bce->version = XmBaseClassExtVersion;
353 bce->record_size = sizeof(XmBaseClassExtRec);
354
355 *ext = bce;
356 }
357
358 /*
359 * If the wrapper data is missing, create a clean wrapper on-the-fly.
360 */
361 if (bce->wrapperData == NULL)
362 {
363 bce->wrapperData = (XmWrapperData)XtCalloc(1, sizeof(XmWrapperDataRec));
364 }
365
366 return bce->wrapperData;
367 }
368
369
370 /*
371 * This isn't really necessary! Better fold this into the source at the
372 * appropiate places. Or make it a simple #define --aldi
373 *
374 * MLM: True, but I understand the sentiment. The four functions taken
375 * together "black box" the interface. Good information hiding...
376 */
377 extern void
_XmFreeWrapperData(XmWrapperData data)378 _XmFreeWrapperData(XmWrapperData data)
379 {
380 XtFree((char *)data);
381 }
382
383
384 /*
385 * Push information about the hooked function pointer on a per-widget-class
386 * stack.
387 *
388 * BTW - The _XmXXXWrapperData() functions should really be static, as
389 * no-one outside this module should be allowed to call them. They are
390 * considered private and no-one outside this module should ever need
391 * them. --aldi
392 *
393 * I made Push and Pop static, but left Get and Free global, after testing
394 * linkage with M*tif.
395 */
396 static XmWrapperData
_XmPushWrapperData(WidgetClass wc)397 _XmPushWrapperData(WidgetClass wc)
398 {
399 XmBaseClassExt *ext, bce;
400 XmWrapperData wrapper = NULL;
401
402 /*
403 * Try to find the class extension record and if you can't find one,
404 * create one. If we found one, then make sure, it has the right
405 * version number. This way, a widget class with no base class ext.
406 * record will get a fresh one just on-the-fly.
407 */
408 ext = (XmBaseClassExt *)_XmGetBaseClassExtPtr(wc, XmQmotif);
409
410 /*
411 * Remark: As we do not hand over a NULL pointer to
412 * _XmGetBaseClassExtPtr(), we never get back a NULL pointer. So de-
413 * referencing the pointer returned by _XmGetBaseClassExtPtr() is
414 * just fine here.
415 */
416 if (!*ext)
417 {
418 bce = (XmBaseClassExt)XtMalloc(sizeof(XmBaseClassExtRec));
419
420 bce->next_extension = NULL;
421 bce->record_type = XmQmotif;
422 bce->version = XmBaseClassExtVersion;
423 bce->record_size = sizeof(XmBaseClassExtRec);
424 bce->wrapperData = NULL;
425
426 *ext = bce;
427 }
428
429 bce = *ext;
430
431 if (bce->version < XmBaseClassExtVersion)
432 {
433 return wrapper;
434 }
435
436 /*
437 * If there is already some wrapper data in the list, then clone the
438 * head wrapper entry of the list. Otherwise allocate a fresh one
439 * filled with zeros.
440 */
441 if (bce->wrapperData != NULL)
442 {
443 wrapper = (XmWrapperData)XtMalloc(sizeof(XmWrapperDataRec));
444
445 memcpy(wrapper, bce->wrapperData, sizeof(XmWrapperDataRec));
446
447 wrapper->widgetClass = wc;
448 wrapper->next = bce->wrapperData;
449 }
450 else
451 {
452 wrapper = (XmWrapperData)XtMalloc(sizeof(XmWrapperDataRec));
453
454 memset(wrapper, 0, sizeof(XmWrapperDataRec));
455 }
456
457 bce->wrapperData = wrapper;
458
459 return wrapper;
460 }
461
462
463 /*
464 * Pop data from the per-widget-class stack. The wrapper data is *NOT*
465 * freed but instead a pointer to it is returned to the caller. Thus, it's
466 * the caller's responsiblity to free the data later on. And to say it
467 * loud and clear: the wrapper is removen from the list but the memory
468 * isn't freed.
469 */
470 static XmWrapperData
_XmPopWrapperData(WidgetClass wc)471 _XmPopWrapperData(WidgetClass wc)
472 {
473 XmBaseClassExt *ext;
474 XmWrapperData wrapper;
475
476 ext = (XmBaseClassExt *)_XmGetBaseClassExtPtr(wc, XmQmotif);
477 wrapper = (*ext)->wrapperData;
478
479 if (wrapper)
480 {
481 (*ext)->wrapperData = wrapper->next;
482 }
483
484 return wrapper;
485 }
486
487
488 /* ---------------------------------------------------------------------
489 * Following is the realize wrapper stuff. Whereas the wrapper system
490 * for hooking the class_part_init, initialize, set_values and get_values
491 * methods is somewhat... clean, the realize wrapper stuff is going
492 * real dirty! The main reason why this had becoming so clumpsy is to
493 * cope with the way realize methods may be chained up to a class'
494 * superclass:
495 * In principle, there are two ways of chaining. The first one needs
496 * some more work but is also a clean way for chaining (`clean' in the
497 * presence of the wrapper mechanism):
498 * - DON'T let core_class.realize initially point to your own realize
499 * method! Use XtInheritRealize instead for a start.
500 * - During your class_part_init method, core_class.realize has been
501 * resolved to point to your superclass' realize method. So save
502 * this pointer in a safe place (probably within your class record).
503 * Place a pointer to your own realize method into core_class.realize.
504 * - DON'T use your superclass' core_class.realize pointer but use
505 * the pointer saved in the step before.
506 * Then in the ClassPartInitLeafWrapper we could have saved the realize
507 * pointer to a wrapper data block and put a pointer to a wrapper into
508 * core_class.realize. The wrapper then in turn had only to ask the widget
509 * for its class and use the realize proc as specified in the wrapper for
510 * that widget class.
511 * FORGET IT! (sigh)
512 * Almost 100% of the widget code available uses a second chaining method:
513 * - Put a pointer to your realize method into core_class.realize.
514 * - When chaining, just use core_class.super_class->core_class.realize.
515 * While this is appearently easier to code it renders all attempts useless
516 * to cleanly hook the realize proc. Sigh (once again, I'm repeating myself).
517 * The only solution for this misery that don't break existing code is:
518 * Each wrapper entry gets a distinct level number. That number identifies
519 * on what level below the vendorShell widget class a widget class resides.
520 * In order to assign that number to a wrapper we need a separate wrapper
521 * for each level (that is what the RealizeWrapper<#> procs are good for).
522 * This level number indicates which core_class.realize was intended to
523 * be called.
524 *
525 * All these explanations do apply to the geometry_handler and resize
526 * wrappers, too (sigh, once more...).
527 */
528
529 /*
530 * Allow for 7 levels of descendants below the vendor shell widget
531 * class. This is an arbitrary setting, but compatible with M*tif.
532 */
533 static void RealizeWrapper(Widget w, XtValueMask *ValueMask,
534 XSetWindowAttributes *Attribs,
535 int IntentedWrapperDepth);
536 /*
537 * Almost the same as above, but now for the resize stuff.
538 */
539 static void ResizeWrapper(Widget w, int IntentedWrapperDepth);
540
541 /*
542 * Just as above, but now for the geometry handler stuff.
543 */
544 static XtGeometryResult GeometryHandlerWrapper(Widget w,
545 XtWidgetGeometry *request,
546 XtWidgetGeometry *reply,
547 int IntentedWrapperDepth);
548
549 /*
550 * max depths for the wrappers
551 */
552 #define MAX_REALIZE_WRAPPER_DEPTH 7
553 #define MAX_RESIZE_WRAPPER_DEPTH 10
554 #define MAX_GEOM_WRAPPER_DEPTH 9
555
556 /*
557 * shorthand
558 */
559 #define MAKE_REALIZE_WRAPPER(Level) \
560 static void RealizeWrapper##Level(Widget w, XtValueMask *ValueMask, \
561 XSetWindowAttributes *Attribs) \
562 { RealizeWrapper(w, ValueMask, Attribs, Level); }
563
564 #define MAKE_RESIZE_WRAPPER(Level) \
565 static void ResizeWrapper##Level(Widget w) \
566 { ResizeWrapper(w, Level); }
567
568
569 #define MAKE_GEOM_WRAPPER(Level) \
570 static XtGeometryResult GeometryHandlerWrapper##Level(Widget w, \
571 XtWidgetGeometry *request, \
572 XtWidgetGeometry *reply) \
573 { return GeometryHandlerWrapper(w, request, reply, Level); }
574
575 /*
576 * definitions
577 */
578 MAKE_REALIZE_WRAPPER(0)
579 MAKE_REALIZE_WRAPPER(1)
580 MAKE_REALIZE_WRAPPER(2)
581 MAKE_REALIZE_WRAPPER(3)
582 MAKE_REALIZE_WRAPPER(4)
583 MAKE_REALIZE_WRAPPER(5)
584 MAKE_REALIZE_WRAPPER(6)
585 MAKE_REALIZE_WRAPPER(7)
586
587 MAKE_RESIZE_WRAPPER(0)
588 MAKE_RESIZE_WRAPPER(1)
589 MAKE_RESIZE_WRAPPER(2)
590 MAKE_RESIZE_WRAPPER(3)
591 MAKE_RESIZE_WRAPPER(4)
592 MAKE_RESIZE_WRAPPER(5)
593 MAKE_RESIZE_WRAPPER(6)
594 MAKE_RESIZE_WRAPPER(7)
595 MAKE_RESIZE_WRAPPER(8)
596 MAKE_RESIZE_WRAPPER(9)
597 MAKE_RESIZE_WRAPPER(10)
598
599 MAKE_GEOM_WRAPPER(0)
600 MAKE_GEOM_WRAPPER(1)
601 MAKE_GEOM_WRAPPER(2)
602 MAKE_GEOM_WRAPPER(3)
603 MAKE_GEOM_WRAPPER(4)
604 MAKE_GEOM_WRAPPER(5)
605 MAKE_GEOM_WRAPPER(6)
606 MAKE_GEOM_WRAPPER(7)
607 MAKE_GEOM_WRAPPER(8)
608 MAKE_GEOM_WRAPPER(9)
609
610 static XtRealizeProc RealizeWrappers[] =
611 {
612 RealizeWrapper0,
613 RealizeWrapper1,
614 RealizeWrapper2,
615 RealizeWrapper3,
616 RealizeWrapper4,
617 RealizeWrapper5,
618 RealizeWrapper6,
619 RealizeWrapper7
620 };
621
622 static XtWidgetProc ResizeWrappers[] =
623 {
624 ResizeWrapper0,
625 ResizeWrapper1,
626 ResizeWrapper2,
627 ResizeWrapper3,
628 ResizeWrapper4,
629 ResizeWrapper5,
630 ResizeWrapper6,
631 ResizeWrapper7,
632 ResizeWrapper8,
633 ResizeWrapper9,
634 ResizeWrapper10
635 };
636
637 static XtGeometryHandler GeometryWrappers[] =
638 {
639 GeometryHandlerWrapper0,
640 GeometryHandlerWrapper1,
641 GeometryHandlerWrapper2,
642 GeometryHandlerWrapper3,
643 GeometryHandlerWrapper4,
644 GeometryHandlerWrapper5,
645 GeometryHandlerWrapper6,
646 GeometryHandlerWrapper7,
647 GeometryHandlerWrapper8,
648 GeometryHandlerWrapper9
649 };
650
651
652 /*
653 * Returns a widget class' depth in relation to the vendor shell widget
654 * class. Any direct subclass of the vendor shell widget class is
655 * considered to be of depth #1. Any widget class not derived from the
656 * vendor shell class will result in an error message. This is much
657 * securer than bombing later with a NULL pointer or even worse getting
658 * strange results and no-one knows why...
659 */
660 static int
RealizeDepth(WidgetClass MyWc)661 RealizeDepth(WidgetClass MyWc)
662 {
663 int depth = 0;
664 WidgetClass wc = MyWc;
665
666 while ((wc != NULL) && (wc != (WidgetClass)vendorShellWidgetClass))
667 {
668 depth++;
669 wc = wc->core_class.superclass;
670 }
671
672 if (wc == NULL)
673 {
674 _XmError(NULL,
675 "PANIC: widget class \"%s\" tried to take part in the\n"
676 "realize posthook mechanism but is not a descendant class of\n"
677 "vendorShellWidgetClass.",
678 MyWc->core_class.class_name);
679 }
680
681 if (depth > MAX_REALIZE_WRAPPER_DEPTH)
682 {
683 _XmError(NULL,
684 "SORRY: widget class \"%s\" is subclassed too deep from\n"
685 "the vendorShellWidgetClass. Current depth is %i whereas the\n"
686 "allowed maximum depth is %d.",
687 MyWc->core_class.class_name,
688 depth, MAX_REALIZE_WRAPPER_DEPTH);
689 }
690
691 return depth;
692 }
693
694
695 /*
696 * Almost the same as the previous function, but this time the levels
697 * are the distance from the rectObject widget class.
698 */
699 static int
ResizeDepth(WidgetClass MyWc)700 ResizeDepth(WidgetClass MyWc)
701 {
702 int depth = 0;
703 WidgetClass wc = MyWc;
704
705 while ((wc != NULL) && (wc != (WidgetClass)rectObjClass))
706 {
707 depth++;
708 wc = wc->core_class.superclass;
709 }
710
711 if (wc == NULL)
712 {
713 /* yes, there are commas missing in the following lines. No, it's
714 * not a mistake. Let the compiler join the lines.
715 */
716 _XmError(NULL,
717 "PANIC: widget class \"%s\" tried to take part in the\n"
718 "resize posthook mechanism but is not a descendant class of\n"
719 "rectObject. Something strange is happening!",
720 MyWc->core_class.class_name);
721 }
722
723 if (depth >MAX_RESIZE_WRAPPER_DEPTH)
724 {
725 _XmError(NULL,
726 "SORRY: widget class \"%s\" is subclassed too deep from\n"
727 "the rectObject widget class. Current depth is %i whereas\n"
728 "the allowed maximum depth is %d.",
729 MyWc->core_class.class_name,
730 depth, MAX_RESIZE_WRAPPER_DEPTH);
731 }
732
733 return depth;
734 }
735
736
737 /*
738 * Same as above, but this time for the geometry handler stuff.
739 */
740 static int
GeomDepth(WidgetClass MyWc)741 GeomDepth(WidgetClass MyWc)
742 {
743 int depth = 0;
744 WidgetClass wc = MyWc;
745
746 while ((wc != NULL) && (wc != (WidgetClass)rectObjClass))
747 {
748 depth++;
749 wc = wc->core_class.superclass;
750 }
751
752 if (wc == NULL)
753 {
754 _XmError(NULL,
755 "PANIC: widget class \"%s\" tried to take part in the\n"
756 "geometry manager posthook mechanism but is not a descendant\n"
757 "class of rectObject. Something strange is happening!",
758 MyWc->core_class.class_name);
759 }
760
761 if (depth >MAX_GEOM_WRAPPER_DEPTH)
762 {
763 _XmError(NULL,
764 "SORRY: widget class \"%s\" is subclassed too deep from\n"
765 "the rectObject widget class. Current depth is %i whereas\n"
766 "the allowed maximum depth is %d.",
767 MyWc->core_class.class_name,
768 depth, MAX_GEOM_WRAPPER_DEPTH);
769 }
770
771 return depth;
772 }
773
774
775 /*
776 * Initialize the base class extension record of a widget class. The base
777 * class extension record specifies various hooks and other nasty things.
778 * And a widget class can inherit these nasties from its ancestors. This
779 * what we implement here. You know: the failures of the parents will be
780 * punished 'til the fifth generation...
781 *
782 * This function is private to this module! No need to export it... or
783 * someone else may really call it --aldi
784 *
785 * The next static extension record just serves as a reservoir for zeros
786 * (respective NULLs). It is used whenever a widget's superclass has no
787 * extension record.
788 */
789 static XmBaseClassExtRec DummySuperClassExtension = { 0 };
790
791 static void (*ObjectClassPartInit)(WidgetClass c) = NULL;
792 static Boolean (*ObjectSetValues)(Widget old, Widget request, Widget new_w,
793 ArgList args, Cardinal *num_args) = NULL;
794
795
796 /*
797 * Much the same as XtIsSubclass(). But this time it checks whether a
798 * widget *class* is a subclass of some other class. This function is
799 * useful not only to us, but also to others. That may be the reason why
800 * M*tif 2.0 now exports it.
801 */
802 Boolean
_XmIsSubclassOf(WidgetClass wc,WidgetClass sclass)803 _XmIsSubclassOf(WidgetClass wc, WidgetClass sclass)
804 {
805 WidgetClass parent = wc;
806
807 while (parent && parent != sclass)
808 {
809 parent = parent->core_class.superclass;
810 }
811
812 if (parent == sclass)
813 {
814 return True;
815 }
816
817 return False;
818 }
819
820
821 /*
822 * figure out if this widget class is one of those that needs inheritance
823 * wrapper help.
824 */
825 static void
ResolveWrappers(WidgetClass wc,WidgetClass sclass)826 ResolveWrappers(WidgetClass wc, WidgetClass sclass)
827 {
828 XmWrapperData Wrapper, SuperWrapper;
829
830 Wrapper = _XmGetWrapperData(wc);
831 SuperWrapper = _XmGetWrapperData(sclass);
832
833 /*
834 * Only the vendor shell class and its subclasses will take part in
835 * the realize wrapper game...
836 */
837 if (_XmIsSubclassOf(wc, vendorShellWidgetClass))
838 {
839
840 /*
841 * If the widget class wants to inherit the realize method from
842 * its superclass then use the function pointer stored with the
843 * superclass' extension record. Otherwise use the pointer as
844 * specified in the class record and store it in the extension
845 * record. The extension record will always hold the real pointer
846 * whereas the core_class.realize field points to a wrapper.
847 * NOTE: we assert here vendorShellWidgetClass->core_class.realize
848 * is NOT (to repeat: NOT) set to XtInheritRealize!!!
849 */
850 if (wc->core_class.realize == XtInheritRealize)
851 {
852 if (SuperWrapper->realize)
853 {
854 Wrapper->realize = SuperWrapper->realize;
855 }
856 else
857 {
858 Wrapper->realize = sclass->core_class.realize;
859 }
860 }
861 else
862 {
863 Wrapper->realize = wc->core_class.realize;
864 }
865
866 wc->core_class.realize = RealizeWrappers[RealizeDepth(wc)];
867 }
868
869 if (_XmIsSubclassOf(wc, rectObjClass))
870 {
871
872 if (wc->core_class.resize == XtInheritResize)
873 {
874 if (SuperWrapper->resize)
875 {
876 Wrapper->resize = SuperWrapper->resize;
877 }
878 else
879 {
880 Wrapper->resize = sclass->core_class.resize;
881 }
882 }
883 else
884 {
885 Wrapper->resize = wc->core_class.resize;
886 }
887
888 wc->core_class.resize = ResizeWrappers[ResizeDepth(wc)];
889 }
890
891 #define C_C(wc) ((CompositeClassRec *) wc)
892
893 if (_XmIsSubclassOf(wc, compositeWidgetClass))
894 {
895 if (C_C(wc)->composite_class.geometry_manager ==
896 XtInheritGeometryManager)
897 {
898 if (SuperWrapper->geometry_manager)
899 {
900 Wrapper->geometry_manager = SuperWrapper->geometry_manager;
901 }
902 else
903 {
904 Wrapper->geometry_manager =
905 C_C(sclass)->composite_class.geometry_manager;
906 }
907 }
908 else
909 {
910 Wrapper->geometry_manager =
911 C_C(wc)->composite_class.geometry_manager;
912 }
913
914 C_C(wc)->composite_class.geometry_manager =
915 GeometryWrappers[GeomDepth(wc)];
916 }
917 #undef C_C
918 }
919
920
921 static XmBaseClassExt *
BaseClassPartInitialize(WidgetClass wc)922 BaseClassPartInitialize(WidgetClass wc)
923 {
924 XmBaseClassExt *ext = NULL, *sext = NULL;
925 XmBaseClassExt new_ext, super_ext;
926 Boolean need_ext = False;
927 WidgetClass sclass;
928 Boolean need_wrappers = False;
929
930 /*
931 * Some widget classes desperatly need a base class extension record
932 * despite the fact that their superclass has no extension record.
933 * The widget classes concerned of that problem are those with
934 * superclasses which are Xt 'kernel' classes. And the Xt intrinsics
935 * have no knowledge of the dreaded things we're doing here... Sigh,
936 * in former times all things were better!
937 *
938 * --aldi: Testing M*tif's bce records using the wctest programs shows
939 * that the list of widget classes below is more than sufficient. Running
940 * wctest indicates that all these widget classes have their own bce
941 * record anyway. So the test below is overcautious -- at least when
942 * LessTif has reached a certain quality and all those widget classes
943 * have their own bce records attached to their class records.
944 */
945 if (wc == (WidgetClass)&vendorShellClassRec || /* wmShell:: */
946 wc == (WidgetClass)&xmPrimitiveClassRec || /* core:: */
947 wc == (WidgetClass)&xmGadgetClassRec || /* rectObj:: */
948 wc == (WidgetClass)&xmManagerClassRec || /* constraint:: */
949 wc == (WidgetClass)&xmDisplayClassRec || /* applicationShell:: */
950 wc == (WidgetClass)&xmScreenClassRec || /* core:: */
951 wc == (WidgetClass)&xmMenuShellClassRec || /* overrideShell:: */
952 wc == (WidgetClass)&xmExtClassRec) /* object:: */
953 {
954 need_ext = True;
955 }
956 else if (wc == (WidgetClass)&rectObjClassRec ||
957 wc == (WidgetClass)&compositeClassRec)
958 {
959 need_wrappers = True;
960 }
961
962 /*
963 * Ask for a base class extension record of the widget class to be
964 * initialized. Also ask the superclass for its base class extension
965 * record.
966 */
967 sclass = wc->core_class.superclass;
968
969 ext = _XmGetBaseClassExtPtr(wc, XmQmotif);
970
971 /*
972 * If someone really should instanciate an Object...
973 */
974 if (sclass)
975 {
976 sext = _XmGetBaseClassExtPtr(sclass, XmQmotif);
977 }
978
979 DEBUGOUT(_LtDebug(__FILE__, NULL,
980 "BaseClassPartInit on %s with %s base ext rec.\n",
981 wc->core_class.class_name,
982 (ext && *ext) ? "a" : "NO!"));
983
984 DEBUGOUT(_LtDebug(__FILE__, NULL,
985 "BaseClassPartInit: sclass %s with %s base ext rec.\n",
986 wc->core_class.superclass->core_class.class_name,
987 (sext && *sext) ? "a" : "NO!"));
988
989 /*
990 * If the superclass doesn't have a base class extension record and
991 * our widget class hasn't a base class extension record either and
992 * it doesn't need one at all, say goodby to it all! We do hereby
993 * sort out all those crazy widget classes which have an extension
994 * record but are not subclassed of any LessTif widget class.
995 */
996 if (!need_ext)
997 {
998
999 if (need_wrappers)
1000 {
1001 ResolveWrappers(wc, sclass);
1002 return ext;
1003 }
1004
1005 if (!sext || !*sext)
1006 {
1007
1008 /*
1009 * Unfortunatly, the set_values, get_values and initialize
1010 * hooks may trigger nevertheless.
1011 */
1012 if (ext && *ext)
1013 {
1014 _XmWarning(NULL,
1015 "Widget class %s has a base extension record, but\n\
1016 its superclass %s has not. Using the hook mechanism\n\
1017 will cause trouble.\n",
1018 wc->core_class.class_name,
1019 wc->core_class.superclass->core_class.class_name);
1020
1021 return (XmBaseClassExt *)NULL;
1022 }
1023 }
1024 }
1025
1026 /*
1027 * The next one should never happen! Or something very bad is going on.
1028 */
1029 if (!ext)
1030 {
1031 return (XmBaseClassExt *)NULL;
1032 }
1033
1034 if (!*ext)
1035 {
1036 /*
1037 * In case this widget class has no class extension record
1038 * but needs one for LessTif's sake, set up a base class
1039 * extension record and therefore force the use of default
1040 * hook procedures.
1041 * The whole bunch here is necessary in order to support application
1042 * defined widget classes which are inherited from widget classes
1043 * of the LessTif 'core'. So every user contributed class gets
1044 * a base class extension record if it does not already have one.
1045 *
1046 * MLM: Is this really true? Run-time testing of TearOffButton seemed
1047 * to indicate that this class had no base extension...
1048 */
1049 XmBaseClassExt p;
1050 DEBUGOUT(_LtDebug(__FILE__, NULL,
1051 "BaseClassPartInit(): %s got bce record on the fly\n",
1052 wc->core_class.class_name));
1053
1054 *ext = p = (XmBaseClassExt)XtCalloc(sizeof(XmBaseClassExtRec), 1);
1055 p->record_type = XmQmotif;
1056 p->version = XmBaseClassExtVersion;
1057 p->record_size = sizeof(XmBaseClassExtRec);
1058 p->classPartInitPrehook = XmInheritClassPartInitPrehook;
1059 p->classPartInitPosthook = XmInheritClassPartInitPosthook;
1060 p->initializePrehook = XmInheritInitializePrehook;
1061 p->initializePosthook = XmInheritInitializePosthook;
1062 p->setValuesPrehook = XmInheritSetValuesPrehook;
1063 p->setValuesPosthook = XmInheritSetValuesPosthook;
1064 p->getValuesPrehook = XmInheritGetValuesPrehook;
1065 p->getValuesPosthook = XmInheritGetValuesPosthook;
1066 p->secondaryObjectClass = XmInheritClass;
1067 p->secondaryObjectCreate = XmInheritSecObjectCreate;
1068 p->getSecResData = XmInheritGetSecResData;
1069 p->widgetNavigable = XmInheritWidgetNavigable;
1070 p->focusChange = XmInheritFocusChange;
1071 }
1072
1073 /*
1074 * Let us be notorious and always clean the flags. The flags have
1075 * to be set during the class_part_init method of a widget class.
1076 */
1077 memset((*ext)->flags, 0, 32);
1078
1079 /*
1080 * If the superclass hasn't a base class extension record, use
1081 * a dummy record filled with NULLs. This way we never end up with
1082 * unintentionally unresolved XtInherits. On the other side the
1083 * message XtInherit spits out when it gets accidently called may
1084 * help more than a silent ignore.
1085 */
1086 new_ext = *ext;
1087
1088 if (!*sext)
1089 {
1090 super_ext = &DummySuperClassExtension;
1091 }
1092 else
1093 {
1094 super_ext = *sext;
1095
1096 if (super_ext == NULL)
1097 {
1098 super_ext = &DummySuperClassExtension;
1099 }
1100 }
1101
1102 if (new_ext->classPartInitPrehook == XmInheritClassPartInitPrehook)
1103 {
1104 new_ext->classPartInitPrehook = super_ext->classPartInitPrehook;
1105 }
1106
1107 if (new_ext->classPartInitPosthook == XmInheritClassPartInitPosthook)
1108 {
1109 new_ext->classPartInitPosthook = super_ext->classPartInitPosthook;
1110 }
1111
1112 if (new_ext->initializePrehook == XmInheritInitializePrehook)
1113 {
1114 new_ext->initializePrehook = super_ext->initializePrehook;
1115 }
1116
1117 if (new_ext->initializePosthook == XmInheritInitializePosthook)
1118 {
1119 new_ext->initializePosthook = super_ext->initializePosthook;
1120 }
1121
1122 if (new_ext->setValuesPrehook == XmInheritSetValuesPrehook)
1123 {
1124 new_ext->setValuesPrehook = super_ext->setValuesPrehook;
1125 }
1126
1127 if (new_ext->setValuesPosthook == XmInheritSetValuesPosthook)
1128 {
1129 new_ext->setValuesPosthook = super_ext->setValuesPosthook;
1130 }
1131
1132 if (new_ext->secondaryObjectClass == XmInheritClass)
1133 {
1134 new_ext->secondaryObjectClass = super_ext->secondaryObjectClass;
1135 }
1136
1137 if (new_ext->secondaryObjectCreate == XmInheritSecObjectCreate)
1138 {
1139 new_ext->secondaryObjectCreate = super_ext->secondaryObjectCreate;
1140 }
1141
1142 if (new_ext->getValuesPrehook == XmInheritGetValuesPrehook)
1143 {
1144 new_ext->getValuesPrehook = super_ext->getValuesPrehook;
1145 }
1146
1147 if (new_ext->getValuesPosthook == XmInheritGetValuesPosthook)
1148 {
1149 new_ext->getValuesPosthook = super_ext->getValuesPosthook;
1150 }
1151
1152 if (new_ext->widgetNavigable == XmInheritWidgetNavigable)
1153 {
1154 new_ext->widgetNavigable = super_ext->widgetNavigable;
1155 }
1156
1157 if (new_ext->focusChange == XmInheritFocusChange)
1158 {
1159 new_ext->focusChange = super_ext->focusChange;
1160 }
1161
1162 if (new_ext->getSecResData == XmInheritGetSecResData)
1163 {
1164 new_ext->getSecResData = super_ext->getSecResData;
1165 }
1166
1167 ResolveWrappers(wc, sclass);
1168
1169 return ext;
1170 }
1171
1172
1173 /*
1174 * A wrapper shrinked over a widget class' realize procedure. This is
1175 * called from the RealizeWrapper<#> funcions with the last param
1176 * "WrapperDepth" specifying the wrapper number the cpu was taking.
1177 */
1178 static void
RealizeWrapper(Widget w,XtValueMask * ValueMask,XSetWindowAttributes * Attribs,int IntentedWrapperDepth)1179 RealizeWrapper(Widget w, XtValueMask *ValueMask,
1180 XSetWindowAttributes *Attribs, int IntentedWrapperDepth)
1181 {
1182 int WindUp;
1183 WidgetClass wc = XtClass(w);
1184 XmWidgetExtData ext;
1185 XmWrapperData wrap;
1186
1187 /*
1188 * If someone tries to fool us, return immediatly. This is just
1189 * defensive programming... and will effectively hide the real
1190 * cause of the core dump suddenly appearing lateron...
1191 */
1192 if (!XtIsSubclass(w, vendorShellWidgetClass))
1193 {
1194 return;
1195 }
1196
1197 /*
1198 * Call the real realize procedure. We can't never stumple over
1199 * a XtInherit pointer because the vendor shell widget class has
1200 * its own realize procedure. NULL pointers aren't allowed either.
1201 * Well, in theory _XmGetWrapperData may fail to locate a valid
1202 * wrapper data block and create one on the fly which contains
1203 * only NULL pointers. Thus, I'm defensive once again and catch
1204 * such catastrophies.
1205 */
1206 WindUp = RealizeDepth(wc) - IntentedWrapperDepth;
1207
1208 if (WindUp > 0)
1209 {
1210 do
1211 {
1212 wc = wc->core_class.superclass;
1213 }
1214 while (--WindUp > 0);
1215 }
1216
1217 wrap = _XmGetWrapperData(wc);
1218 if (wrap == NULL || wrap->realize == NULL)
1219 {
1220 _XmError(w, "PANIC: no realize procedure specified for this widget.");
1221 }
1222
1223 wrap->realize(w, ValueMask, Attribs);
1224
1225 ext = _XmGetWidgetExtData(w, XmSHELL_EXTENSION);
1226
1227 /* if (ext != NULL && ext->widget != NULL && !XmIsDialogShell(w)) */
1228 if (ext != NULL && ext->widget != NULL && wc != xmDialogShellWidgetClass)
1229 {
1230 /*
1231 * Check for a callback list to be executed (the only exception
1232 * is the XmDialogShell class which has no such callback list).
1233 */
1234 XtCallCallbackList(ext->widget,
1235 VSEP_RealizeCallback(ext->widget),
1236 NULL);
1237 }
1238 }
1239
1240
1241 static void
ResizeWrapper(Widget w,int IntentedWrapperDepth)1242 ResizeWrapper(Widget w, int IntentedWrapperDepth)
1243 {
1244 int WindUp;
1245 WidgetClass wc = XtClass(w);
1246 XmWrapperData WrapperData;
1247 Boolean need_navig = False;
1248 static Boolean recurse = False;
1249
1250 WindUp = ResizeDepth(wc) - IntentedWrapperDepth;
1251
1252 if (WindUp > 0)
1253 {
1254 do
1255 {
1256 wc = wc->core_class.superclass;
1257 }
1258 while (--WindUp > 0);
1259 }
1260
1261 /* _XmNavigResize is only used for shell widgets */
1262 if (XtParent(w) != NULL && XtIsShell(XtParent(w)))
1263 {
1264 need_navig = True;
1265 }
1266
1267 /*
1268 * For the resize wrapper it is just fine to have no resize method.
1269 */
1270 WrapperData = _XmGetWrapperData(wc);
1271
1272 if (WrapperData != NULL && WrapperData->resize != NULL)
1273 {
1274 if (!recurse && _XmDropSiteWrapperCandidate(w))
1275 {
1276 recurse = True;
1277
1278 XmDropSiteStartUpdate(w);
1279 WrapperData->resize(w);
1280 XmDropSiteEndUpdate(w);
1281
1282 recurse = False;
1283 }
1284 else
1285 {
1286 WrapperData->resize(w);
1287 }
1288 }
1289
1290 if (need_navig)
1291 {
1292 _XmNavigResize(w);
1293 }
1294 }
1295
1296
1297 /*
1298 * fun with GeoUtils showed me why this was broken. Remember how a
1299 * geometry manager is called with the child requesting the change?
1300 * Well, guess which Widget class we should use.... The parent's!
1301 */
1302 static XtGeometryResult
GeometryHandlerWrapper(Widget w,XtWidgetGeometry * request,XtWidgetGeometry * reply,int IntentedWrapperDepth)1303 GeometryHandlerWrapper(Widget w, XtWidgetGeometry *request,
1304 XtWidgetGeometry *reply, int IntentedWrapperDepth)
1305 {
1306 int WindUp;
1307 WidgetClass wc = XtClass(XtParent(w));
1308 XmWrapperData WrapperData;
1309 static Boolean recurse = False;
1310 XtGeometryResult ret;
1311
1312 DEBUGOUT(_LtDebug(__FILE__, w, "GeometryHandlerWrapper(%d) : request %s\n",
1313 IntentedWrapperDepth, _LtDebugWidgetGeometry2String(request)));
1314
1315 WindUp = GeomDepth(wc) - IntentedWrapperDepth;
1316
1317 if (WindUp > 0)
1318 {
1319 do
1320 {
1321 wc = wc->core_class.superclass;
1322 }
1323 while (--WindUp > 0);
1324 }
1325
1326 WrapperData = _XmGetWrapperData(wc);
1327
1328 if (WrapperData == NULL || WrapperData->geometry_manager == NULL)
1329 {
1330 _XmError(XtParent(w),
1331 "PANIC: no geometry_manager procedure "
1332 "specified for this widget: %s:%s.",
1333 XtClass(XtParent(w))->core_class.class_name,
1334 XtName(XtParent(w)));
1335 }
1336
1337 if (!recurse && _XmDropSiteWrapperCandidate(w))
1338 {
1339 recurse = True;
1340
1341 XmDropSiteStartUpdate(w);
1342 ret = WrapperData->geometry_manager(w, request, reply);
1343 XmDropSiteEndUpdate(w);
1344
1345 recurse = False;
1346 }
1347 else
1348 {
1349 ret = WrapperData->geometry_manager(w, request, reply);
1350 }
1351
1352 return ret;
1353 }
1354
1355
1356 /* ---------------------------------------------------------------------
1357 * Following is the implementation of the hook wrapper mechanism. In
1358 * order to do pre- and post-processing before/after a widget's class
1359 * methods have been called a wrapper mechanism is used: every wrapper
1360 * consists of a root and a leaf function. The root function replaces
1361 * whatever method installed in the object class and is setup by
1362 * _XmInitializeExtensions(). The pointers to the old methods are
1363 * stored in some global variables in order to call them later in the
1364 * root wrapper level. That root wrapper then checks for a pre-hook and
1365 * call it if one is available. The root wrapper also replaces the
1366 * function pointer to a class method that would have been called as
1367 * the last method by a pointer to the leaf wrapper. In turn, the leaf
1368 * wrapper then calls that last method, restores the original function
1369 * pointer and calls the post-hook function. Any questions remaining...?
1370 */
1371
1372
1373 /*
1374 * This is the ClassPartInit method's post-hook. It calls the last
1375 * ClassPartInit method in the chain and then restores the original
1376 * function pointer to that particular last method.
1377 */
1378 static void
ClassPartInitLeafWrapper(WidgetClass widget_class)1379 ClassPartInitLeafWrapper(WidgetClass widget_class)
1380 {
1381 XmBaseClassExt *bce = NULL;
1382 XmWrapperData wrap;
1383
1384 bce = ((XmBaseClassExt *)_XmGetBaseClassExtPtr(widget_class, XmQmotif));
1385
1386 if (!bce || !*bce)
1387 {
1388 return;
1389 }
1390
1391 wrap = (XmWrapperData)(*bce)->wrapperData;
1392
1393 if (wrap->classPartInitLeaf)
1394 {
1395 (wrap->classPartInitLeaf)(widget_class);
1396 }
1397
1398 if ((*bce)->classPartInitPosthook)
1399 {
1400 ((*bce)->classPartInitPosthook)(widget_class);
1401 }
1402
1403 widget_class->core_class.class_part_initialize = wrap->classPartInitLeaf;
1404
1405 wrap->classPartInitLeaf = NULL;
1406 }
1407
1408
1409 /*
1410 * This ClassPartInit pre-hook is called as the first method whenever a
1411 * new widget class gets initialized.
1412 *
1413 * HEY! What about recursion?! I hope that no-one ever initializes
1414 * another widget class from within his class part init method (and that
1415 * widget class is a subclass of the current widget class).
1416 */
1417 static void
ClassPartInitRootWrapper(WidgetClass widget_class)1418 ClassPartInitRootWrapper(WidgetClass widget_class)
1419 {
1420 XmBaseClassExt *bce = NULL;
1421 XmWrapperData wrap;
1422
1423 bce = BaseClassPartInitialize(widget_class);
1424
1425 if (!bce || !*bce)
1426 {
1427 if (ObjectClassPartInit)
1428 {
1429 (ObjectClassPartInit)(widget_class);
1430 }
1431
1432 return;
1433 }
1434
1435 if ((*bce)->classPartInitPrehook)
1436 {
1437 ((*bce)->classPartInitPrehook)(widget_class);
1438 }
1439
1440 if (ObjectClassPartInit)
1441 {
1442 (ObjectClassPartInit)(widget_class);
1443 }
1444
1445 if ((*bce)->classPartInitPosthook)
1446 {
1447 wrap = _XmGetWrapperData(widget_class);
1448
1449 if (widget_class->core_class.class_part_initialize !=
1450 ClassPartInitLeafWrapper)
1451 {
1452
1453 wrap->classPartInitLeaf =
1454 widget_class->core_class.class_part_initialize;
1455
1456 widget_class->core_class.class_part_initialize =
1457 ClassPartInitLeafWrapper;
1458 }
1459 }
1460 }
1461
1462
1463 /*
1464 * Initialize posthook stuff.
1465 * it is called just before the last init has been called and then redirects
1466 * the control to the last one before activating the post-hook.
1467 */
1468 static void
InitializeLeafWrapper(Widget request,Widget new_w,ArgList args,Cardinal * num_args)1469 InitializeLeafWrapper(Widget request, Widget new_w,
1470 ArgList args, Cardinal *num_args)
1471 {
1472 WidgetClass wc = XtClass(new_w);
1473 XmBaseClassExt *bce = NULL;
1474 XmWrapperData wrap;
1475
1476 bce = ((XmBaseClassExt *)_XmGetBaseClassExtPtr(wc, XmQmotif));
1477
1478 if (!bce || !*bce)
1479 {
1480 return;
1481 }
1482
1483 if ((*bce)->initializePosthook)
1484 {
1485
1486 /*
1487 * If we're not a shell and our parent is constraint, then
1488 * the hook was installed in the class record's constraint part of
1489 * our parent.
1490 * MLM: Ahhh. Somebody said something about this, but I missed the
1491 * real meaning.
1492 */
1493 if (!XtIsShell(new_w) && XtParent(new_w) &&
1494 XtIsConstraint(XtParent(new_w)))
1495 {
1496 wc = XtClass(XtParent(new_w));
1497
1498 wrap = _XmPopWrapperData(wc);
1499
1500 ((ConstraintClassRec *)wc)->constraint_class.initialize =
1501 wrap->initializeLeaf;
1502 }
1503 else
1504 {
1505 wrap = _XmPopWrapperData(wc);
1506
1507 wc->core_class.initialize = wrap->initializeLeaf;
1508 }
1509
1510 if (wrap->initializeLeaf)
1511 {
1512 (wrap->initializeLeaf)(request, new_w, args, num_args);
1513 }
1514
1515 ((*bce)->initializePosthook)(request, new_w, args, num_args);
1516
1517 _XmFreeWrapperData(wrap);
1518 }
1519 }
1520
1521
1522 /*
1523 * The initialze pre-hook is called on any fresh widget instance before
1524 * any other initialize method has ever seen this new_w widget.
1525 */
1526 static void
InitializeRootWrapper(Widget request,Widget new_w,ArgList args,Cardinal * num_args)1527 InitializeRootWrapper(Widget request, Widget new_w,
1528 ArgList args, Cardinal *num_args)
1529 {
1530 WidgetClass wc = XtClass(new_w);
1531 XmBaseClassExt *bce = NULL;
1532 XmWrapperData wrap;
1533
1534 bce = ((XmBaseClassExt *)_XmGetBaseClassExtPtr(wc, XmQmotif));
1535
1536 if (!bce || !*bce)
1537 {
1538 return;
1539 }
1540
1541 /*
1542 * If there is a pre-hook... call it! And if there's a post-hook
1543 * hook it up! But don't forget to check for a constraint parent.
1544 * In this case the parent's constraint initialize method will
1545 * be called after the widget's initialize method (+ superclasses)
1546 * has been called.
1547 */
1548 if ((*bce)->initializePrehook)
1549 {
1550 ((*bce)->initializePrehook)(request, new_w, args, num_args);
1551 }
1552
1553 if ((*bce)->initializePosthook)
1554 {
1555 if (!XtIsShell(new_w) && XtParent(new_w) &&
1556 XtIsConstraint(XtParent(new_w)))
1557 {
1558 wc = XtClass(XtParent(new_w));
1559 wrap = _XmPushWrapperData(wc);
1560
1561 wrap->initializeLeaf =
1562 ((ConstraintClassRec *)wc)->constraint_class.initialize;
1563
1564 ((ConstraintClassRec *)wc)->constraint_class.initialize
1565 = InitializeLeafWrapper;
1566 }
1567 else
1568 {
1569 wrap = _XmPushWrapperData(wc);
1570
1571 wrap->initializeLeaf = wc->core_class.initialize;
1572
1573 wc->core_class.initialize = InitializeLeafWrapper;
1574 }
1575 }
1576 }
1577
1578
1579 /*
1580 * This is the set_values post-hook. It is called as the last set_values
1581 * method in the chain and in turn calls the real last set_values method
1582 * and the post-hook. 'nuff said.
1583 */
1584 static Boolean
SetValuesLeafWrapper(Widget old,Widget request,Widget new_w,ArgList args,Cardinal * num_args)1585 SetValuesLeafWrapper(Widget old, Widget request, Widget new_w,
1586 ArgList args, Cardinal *num_args)
1587 {
1588 WidgetClass wc = XtClass(new_w);
1589 XmBaseClassExt *bce = NULL;
1590 XmWrapperData wrap;
1591 Boolean refresh = False;
1592
1593 bce = ((XmBaseClassExt *)_XmGetBaseClassExtPtr(wc, XmQmotif));
1594
1595 if (!bce || !*bce)
1596 return False;
1597
1598 if ((*bce)->setValuesPosthook)
1599 {
1600 if (!XtIsShell(new_w) && XtParent(new_w) &&
1601 XtIsConstraint(XtParent(new_w)))
1602 {
1603 wrap = _XmPopWrapperData(XtClass(XtParent(new_w)));
1604 wc = XtClass(XtParent(new_w));
1605 (((ConstraintClassRec *)wc)->constraint_class.set_values)
1606 = wrap->setValuesLeaf;
1607 }
1608 else
1609 {
1610 wrap = _XmPopWrapperData(wc);
1611
1612 wc->core_class.set_values = wrap->setValuesLeaf;
1613 }
1614
1615 if (wrap->setValuesLeaf != NULL)
1616 {
1617 refresh = wrap->setValuesLeaf(old, request, new_w, args, num_args);
1618 }
1619
1620 refresh |= (*bce)->setValuesPosthook(old, request, new_w,
1621 args, num_args);
1622
1623 _XmFreeWrapperData(wrap);
1624 }
1625
1626 return refresh;
1627 }
1628
1629
1630 /*
1631 * This SetValues pre-hook is called before any set_values methods whenever
1632 * a XtSetValues() call occures. We then call the registered pre-hook for
1633 * this widget class -- if there is one. And if there is a registered
1634 * post-hook we'll install a special post-hook proc. This proc is then
1635 * called as the last set_values method and calls then the original
1636 * set_values handler as well as the post-hook.
1637 */
1638 static Boolean
SetValuesRootWrapper(Widget old,Widget request,Widget new_w,ArgList args,Cardinal * num_args)1639 SetValuesRootWrapper(Widget old, Widget request, Widget new_w,
1640 ArgList args, Cardinal *num_args)
1641 {
1642 WidgetClass wc = XtClass(request);
1643 XmBaseClassExt *bce = NULL;
1644 XmWrapperData wrap;
1645 Boolean refresh = False;
1646
1647 bce = ((XmBaseClassExt *)_XmGetBaseClassExtPtr(wc, XmQmotif));
1648
1649 if (!bce || !*bce)
1650 {
1651 if (ObjectSetValues)
1652 {
1653 return (ObjectSetValues) (old, request, new_w, args, num_args);
1654 }
1655 }
1656
1657 if ((*bce)->setValuesPrehook)
1658 {
1659 refresh = ((*bce)->setValuesPrehook)(old, request, new_w,
1660 args, num_args);
1661 }
1662
1663 /*
1664 * If this widget has a constraint resources, then the
1665 * setValues method of our parent will be called after all the
1666 * setValues methods of our class and superclasses. In that
1667 * case we have to hook in the setValues method of the parent.
1668 */
1669 if ((*bce)->setValuesPosthook)
1670 {
1671 if (!XtIsShell(new_w) && XtParent(new_w) &&
1672 XtIsConstraint(XtParent(new_w)))
1673 {
1674 wrap = _XmPushWrapperData(XtClass(XtParent(new_w)));
1675
1676 wc = XtClass(XtParent(new_w));
1677
1678 wrap->setValuesLeaf
1679 = ((ConstraintClassRec *)wc)->constraint_class.set_values;
1680
1681 (((ConstraintClassRec *)wc)->constraint_class.set_values)
1682 = SetValuesLeafWrapper;
1683 }
1684 else
1685 {
1686 wrap = _XmPushWrapperData(wc);
1687
1688 wrap->setValuesLeaf = wc->core_class.set_values;
1689
1690 wc->core_class.set_values = SetValuesLeafWrapper;
1691 }
1692 }
1693
1694 if (ObjectSetValues)
1695 {
1696 refresh |= (ObjectSetValues)(old, request, new_w, args, num_args);
1697 }
1698
1699 return refresh;
1700 }
1701
1702
1703 /*
1704 * The GetValues post-hook is called after any get_values_hook methods of
1705 * the current widget's class and superclasses. But it is called BEFORE any
1706 * potential parent's constraint get_values_hook method. Yeah, what a
1707 * design!
1708 */
1709 static void
GetValuesLeafWrapper(Widget w,ArgList args,Cardinal * num_args)1710 GetValuesLeafWrapper(Widget w, ArgList args, Cardinal *num_args)
1711 {
1712 WidgetClass wc = XtClass(w);
1713 XmBaseClassExt *bce = NULL;
1714 XmWrapperData wrap;
1715
1716 bce = ((XmBaseClassExt *)_XmGetBaseClassExtPtr(wc, XmQmotif));
1717
1718 if (!bce || !*bce)
1719 {
1720 return;
1721 }
1722
1723 if ((*bce)->getValuesPosthook)
1724 {
1725 wrap = _XmPopWrapperData(wc);
1726
1727 wc->core_class.get_values_hook = wrap->getValuesLeaf;
1728
1729 if (wrap->getValuesLeaf)
1730 {
1731 (wrap->getValuesLeaf)(w, args, num_args);
1732 }
1733
1734 ((*bce)->getValuesPosthook)(w, args, num_args);
1735
1736 _XmFreeWrapperData(wrap);
1737 }
1738 }
1739
1740
1741 /*
1742 * The GetValues pre-hook is called before any other get_values_hook method.
1743 * But there's a problem with the post-hook function. It isn't called as the
1744 * last function in the chain in SOME circumstances. If a widget uses the
1745 * constraint get_values_hook by defining the appropiate extensions record
1746 * then the hook will be called BEFORE all constraint get_values_hook(s).
1747 * The csf did a clean design, really. Clean of operability. So let us stick
1748 * at 100% compatibility for two (IMHO maybe silly) reasons:
1749 * 1. The whole pre- & post-hook stuff is undocumented, so don't you dare
1750 * to use it with your self-written widgets. And even if the stuff would
1751 * have been documented, you surely wouldn't dare to use it either...
1752 * 2. The LessTif widgets don't need the post-hook to be called AFTER all
1753 * constraint get_values_hooks. So we simply don't worry about it.
1754 * BTW - shall we consider recursive operations? Argh, I'm going crazy
1755 * on this!! --aldi
1756 * MLM: Yes, you have to consider recursion. If you don't, people who do
1757 * a GetValues, for example, in initialize methods will be in extreme pain.
1758 * I had to change _XmGetUnitType because of this (it used to do a GetValues,
1759 * but is called from ImportArgs in ResInd).
1760 * MLM 2: I looked, and the Constraint class adds a separate GetValues
1761 * hook. What is done with that?
1762 */
1763 static void
GetValuesRootWrapper(Widget w,ArgList args,Cardinal * num_args)1764 GetValuesRootWrapper(Widget w, ArgList args, Cardinal *num_args)
1765 {
1766 WidgetClass wc = XtClass(w);
1767 XmBaseClassExt *bce = NULL;
1768 XmWrapperData wrap;
1769
1770 bce = ((XmBaseClassExt *)_XmGetBaseClassExtPtr(wc, XmQmotif));
1771
1772 if (!bce || !*bce)
1773 {
1774 return;
1775 }
1776
1777 if ((*bce)->getValuesPrehook)
1778 {
1779 ((*bce)->getValuesPrehook)(w, args, num_args);
1780 }
1781
1782 if ((*bce)->getValuesPosthook)
1783 {
1784 wrap = _XmPushWrapperData(wc);
1785
1786 wrap->getValuesLeaf = wc->core_class.get_values_hook;
1787
1788 wc->core_class.get_values_hook = GetValuesLeafWrapper;
1789 }
1790 }
1791
1792
1793 /*
1794 * Initialize the dreaded extension mechanism. This new extension is needed
1795 * in LessTif in order to pre- or postprocess some toolkit operations. This
1796 * initialization is done only once during the creation of the first
1797 * vendorShell.
1798 * MLM: Possibly, but I'm gonna make sure it's called by putting in the
1799 * lesstif core widgets -- Gadget, Primitive, Manager, VendorShell.
1800 */
1801 extern void
_XmInitializeExtensions(void)1802 _XmInitializeExtensions(void)
1803 {
1804 /* We want to use the same as Motif, so our
1805 * widgets can be used with theirs. -- Chris */
1806 if (XmQmotif == 0)
1807 {
1808 XmQmotif = XrmStringToQuark("OSF_MOTIF");
1809 }
1810
1811 /* for why this happens, see testXm/baseclass/test3.c */
1812 if (ObjectClassPartInit == NULL)
1813 {
1814
1815 ObjectClassPartInit = objectClassRec.object_class.class_part_initialize;
1816 ObjectSetValues = objectClassRec.object_class.set_values;
1817
1818 objectClassRec.object_class.class_part_initialize
1819 = ClassPartInitRootWrapper;
1820 objectClassRec.object_class.initialize = InitializeRootWrapper;
1821 objectClassRec.object_class.set_values = SetValuesRootWrapper;
1822 objectClassRec.object_class.get_values_hook = GetValuesRootWrapper;
1823 }
1824 }
1825
1826
1827 /*
1828 * Assumption: widgets that have subresources use this as a helper
1829 * function when their getSecResData BaseClassExt function is called.
1830 * Testing shows that the resources are uncompiled -- thus the call
1831 * to _XmTransformSubResources... Note the two allocations, and their
1832 * relationship to testXm/baseclass/test5.c. Now to figure out who uses
1833 * it.
1834 */
1835 extern Cardinal
_XmSecondaryResourceData(XmBaseClassExt bce,XmSecondaryResourceData ** secResDataRtn,XtPointer client_data,String name,String class_name,XmResourceBaseProc basefunctionpointer)1836 _XmSecondaryResourceData(XmBaseClassExt bce,
1837 XmSecondaryResourceData **secResDataRtn,
1838 XtPointer client_data,
1839 String name,
1840 String class_name,
1841 XmResourceBaseProc basefunctionpointer)
1842 {
1843 XmSecondaryResourceData sec, *sd;
1844 WidgetClass wc;
1845
1846 if (!bce)
1847 {
1848 return 0;
1849 }
1850
1851 if (!bce->secondaryObjectClass)
1852 {
1853 return 0;
1854 }
1855
1856 sec = (XmSecondaryResourceData)XtCalloc(1,
1857 sizeof(XmSecondaryResourceDataRec));
1858
1859 wc = bce->secondaryObjectClass;
1860
1861 sec->name = name;
1862 sec->res_class = class_name;
1863 sec->client_data = client_data;
1864 sec->base_proc = basefunctionpointer;
1865
1866 _XmTransformSubResources(wc->core_class.resources,
1867 wc->core_class.num_resources,
1868 &sec->resources, &sec->num_resources);
1869
1870 sd = (XmSecondaryResourceData *)XtMalloc(sizeof(XmSecondaryResourceData));
1871
1872 *sd = sec;
1873 *secResDataRtn = sd;
1874
1875 return 1;
1876 }
1877
1878
1879 /*
1880 * Testing shows that calling this function before and after instantiation
1881 * of a widget results in uncompiled resources. So I assume that this
1882 * guy can "decompile" resources (test by instantiating a subpart).
1883 * Unfortunately, a call to GetSubresources will compile the list (broken,
1884 * broken, broken), and this call won't work if you haven't instantiated
1885 * an object (the "owner" field in the BaseClassExt isn't set until
1886 * class_intialize), thus the following crap.
1887 */
1888 extern void
_XmTransformSubResources(XtResourceList comp_resources,Cardinal num_comp_resources,XtResourceList * resources,Cardinal * num_resources)1889 _XmTransformSubResources(XtResourceList comp_resources,
1890 Cardinal num_comp_resources,
1891 XtResourceList *resources,
1892 Cardinal *num_resources)
1893 {
1894 XtResourceList res;
1895 Cardinal i;
1896
1897 if (num_comp_resources == 0)
1898 {
1899 *resources = NULL;
1900 *num_resources = 0;
1901 return;
1902 }
1903
1904 res = (XtResourceList)XtCalloc(num_comp_resources, sizeof(XtResource));
1905
1906 if ((int)(comp_resources[0].resource_offset) >= 0)
1907 {
1908 memcpy(res, comp_resources, sizeof(XtResource) * num_comp_resources);
1909 }
1910 else
1911 {
1912 /*
1913 * invert the compilation: ripped off from GetResList.c (X11R6).
1914 */
1915 for (i = 0; i < num_comp_resources; i++)
1916 {
1917 res[i].resource_name
1918 = XrmQuarkToString((XrmQuark)(long)comp_resources[i].resource_name);
1919 res[i].resource_class
1920 = XrmQuarkToString((XrmQuark)(long)comp_resources[i].resource_class);
1921 res[i].resource_type
1922 = XrmQuarkToString((XrmQuark)(long)comp_resources[i].resource_type);
1923 /* MLM: sigh. For want of a nail... I coulda saved myself days if
1924 * I'da done this in the first place */
1925 res[i].resource_size
1926 = comp_resources[i].resource_size;
1927 res[i].resource_offset
1928 = -((int)comp_resources[i].resource_offset + 1);
1929 res[i].default_type
1930 = XrmQuarkToString((XrmQuark)(long)comp_resources[i].default_type);
1931 res[i].default_addr
1932 = comp_resources[i].default_addr;
1933 }
1934 }
1935
1936 *resources = res;
1937 *num_resources = num_comp_resources;
1938 }
1939
1940
1941 /*
1942 * lo and behold, there is a man page for this one.
1943 * According to OSF/Motif Programmer's Reference, page 1-539, there are
1944 * three things to free: the resources, the block, and the block array
1945 * (see testXm/baseclass/test5.c).
1946 */
1947 extern Cardinal
XmGetSecondaryResourceData(WidgetClass w_class,XmSecondaryResourceData ** secondaryDataRtn)1948 XmGetSecondaryResourceData(WidgetClass w_class,
1949 XmSecondaryResourceData **secondaryDataRtn)
1950
1951 {
1952 XmBaseClassExt *bce = NULL;
1953
1954 DEBUGOUT(_LtDebug(__FILE__, NULL,
1955 "XmGetSecondaryResourceData() called on %s.\n",
1956 w_class->core_class.class_name));
1957
1958 bce = _XmGetBaseClassExtPtr(w_class, XmQmotif);
1959
1960 if (!bce || !*bce)
1961 {
1962 return 0;
1963 }
1964
1965 if ((*bce)->getSecResData == NULL)
1966 {
1967 return 0;
1968 }
1969
1970 return ((*bce)->getSecResData)(w_class, secondaryDataRtn);
1971 }
1972