1
/*---------------------------------------------------------------------
2
* $Date: 2009-08-18 15:23:20 $ $Revision: 1.2 $
3
*---------------------------------------------------------------------
6
* Copyright (c) 1992, Visual Edge Software Ltd.
8
* ALL RIGHTS RESERVED. Permission to use, copy, modify, and
9
* distribute this software and its documentation for any purpose
10
* and without fee is hereby granted, provided that the above
11
* copyright notice appear in all copies and that both that
12
* copyright notice and this permission notice appear in supporting
13
* documentation, and that the name of Visual Edge Software not be
14
* used in advertising or publicity pertaining to distribution of
15
* the software without specific, written prior permission. The year
16
* included in the notice is the year of the creation of the work.
17
*-------------------------------------------------------------------*/
23
/*------------------------------------------------------------------------
24
* Method registration and dispatch for swidget interfaces.
25
* This version supports the default macros and generated code,
26
* using a simple (and fast) table lookup approach.
27
*------------------------------------------------------------------------*/
42
extern int UxStrEqual();
45
/* Global environment variable supplied for the user's convenience */
46
Environment UxEnv = {NO_EXCEPTION};
48
static char **Names; /* All method names as registered */
49
static int NameLen = 0; /* Gross length of names array */
50
static int NumNames = 0; /* Num Elements in names array */
52
static void ***MethodTable; /* All method pointers */
53
static int *BaseTable; /* Base class id's by class id. */
54
static int NumClasses = 0; /* Active width of method table */
55
static int *MethodCounts; /* Height by row in method table */
58
static int UndefinedMethod ();
60
static int UndefinedMethod (void);
61
#endif /* _NO_PROTO */
64
static XContext xcontext_mid = 0;
67
/*------------------------------------------------------------------------
68
* NAME: UxMethodLookup
69
* INPUT: swidget sw; -- a swidget, usually an interface swidget
70
* int mid; -- a method id from UxMethodRegister
71
* RETURNS: Pointer to method function for this method.
73
* This is the heart of virtual method lookup.
74
* The design-time routing functions and runtime macros
75
* use this function to fnd the implementation of a method.
76
* The return value is the actual function pointer
77
* for the implementation of the method associated with `sw's
80
* LAST REV: Feb 93 fix3910 Add support for subclassing.
81
*------------------------------------------------------------------------*/
84
void* UxMethodLookup(sw, mid, mname)
89
void* UxMethodLookup(swidget sw, int mid, char *mname)
90
#endif /* _NO_PROTO */
92
int cid = UxGetClassCode(sw);
95
mid = UxMessageIndex(mname);
101
/*-----------------------------------------------------------
102
* The method may be registered on this class or a base class.
103
*-----------------------------------------------------------*/
105
while (cid > -1 && cid < NumClasses)
107
if (mid < MethodCounts[cid] && MethodTable[cid][mid])
109
return MethodTable[cid][mid];
111
cid = BaseTable[cid];
114
return (void *) UndefinedMethod;
120
/*------------------------------------------------------------------------
122
* RETURNS: a unique integer each time called.
124
* This is to get a unique id for each interface class registered.
125
* The result is used for calls to UxMethodRegister, and
126
* is associated with each instance of the interface class:
127
* it is returned by UxGetClassId(sw) for each interface swidget sw
128
* that is an instance of the interface it represents.
130
* We have no subclassing. When it comes, parent class id's
131
* will be supplied in this call, and used to initialize the
132
* classes' method table with its parent's versions.
134
* LAST REV: Feb 93 fix3910 Add support for subclassing.
135
*------------------------------------------------------------------------*/
139
#else /* _NO_PROTO */
140
int UxNewClassId(void)
141
#endif /* _NO_PROTO */
143
static int GrossClasses = 0; /* Gross width of method table */
145
int cid = NumClasses++;
147
if (GrossClasses < NumClasses)
150
MethodTable = (void***)
151
UxRealloc(MethodTable,
152
(GrossClasses += 10) * sizeof(void**));
153
MethodCounts = (int*)
154
UxRealloc(MethodCounts,
155
(GrossClasses * sizeof(int)));
158
GrossClasses * sizeof(int));
160
MethodTable = (void***) UxCalloc((GrossClasses += 10),
162
MethodCounts = (int*) UxCalloc(GrossClasses,
164
BaseTable = (int*) UxCalloc(GrossClasses,
168
MethodTable[cid] = (void**) UxCalloc(NumNames, sizeof(void*));
169
MethodCounts[cid] = NumNames;
175
/*------------------------------------------------------------------------
176
* NAME: UxNewSubclassId (super)
177
* <register a new class as a subclass of an existing class>
178
* INPUT: super class id
179
* RETURNS: new class id of a subclass of the superclass.
181
* LAST REV: Feb 93 fix3910 Add support for subclassing.
182
*------------------------------------------------------------------------*/
185
int UxNewSubclassId(super)
187
#else /* _NO_PROTO */
188
int UxNewSubclassId( int super)
189
#endif /* _NO_PROTO */
191
int cid = UxNewClassId();
192
BaseTable[cid] = super;
196
/*------------------------------------------------------------------------
197
* NAME: UxMessageIndex
198
* INPUT: char* name; -- name of a method being registered.
199
* RETURNS: A unique id number for this name.
201
* Assigns a unique integer to a message name.
202
* Must return the same id for all calls with the same name.
204
* This is used while rgistering methods at startup time.
205
* The result is used when method calls are made
206
* (see UxMethodLookup). If a very large number of method names
207
* are being used, initialization could be speeded up by making
208
* this function faster (by sorting or hashing the names).
210
* LAST REV: June 92 fix3574 Created.
211
*------------------------------------------------------------------------*/
213
int UxMessageIndex (name)
215
#else /* _NO_PROTO */
216
int UxMessageIndex ( char* name)
217
#endif /* _NO_PROTO */
221
for (mid = 0 ; mid < NumNames; mid++)
223
if (UxStrEqual(Names[mid], name)) {
227
if (mid >= NameLen) {
229
Names = (char**) UxMalloc((NameLen=64)*sizeof(char*));
231
Names = (char**) UxRealloc(Names,
232
(NameLen*=2)*sizeof(char*));
236
Names[NumNames] = (char*) UxMalloc(strlen(name)+1);
237
strcpy(Names[NumNames], name);
241
/*------------------------------------------------------------------------
242
* NAME: MethodTableSpace
244
* int cid; -- class id from UxNewClassId ()
245
* int mid; -- method id from UxMessageIndex ()
248
* Enlarges the method table for the given cid,
249
* so that it is at least big enough to register a method
250
* for the given message index. We also add a little more space
251
* (two more cells), but not a lot: there's one of these
252
* arrays for each class, so we don't want them growing too large.
254
* LAST REV: Feb 93 fix3910 Add support for subclassing.
255
*------------------------------------------------------------------------*/
258
static void MethodTableSpace (cid, mid)
261
#else /* _NO_PROTO */
262
static void MethodTableSpace (int cid, int mid)
263
#endif /* _NO_PROTO */
265
int old_cnt = MethodCounts[cid];
270
MethodTable[cid] = (void**) UxRealloc(MethodTable[cid],
271
(mid + 2) * sizeof(void*));
272
for (i = old_cnt; i < mid+2; i++)
274
MethodTable[cid][i] = 0;
276
MethodCounts[cid] = mid + 2;
280
/*------------------------------------------------------------------------
281
* NAME: UxMethodRegister
282
* INPUT: int cid; -- a class code from UxNewClassId()
283
* char *name; -- a method name
284
* void (*function) (); -- implementation of the method
285
* for the identified class.
287
* RETURNS: An identifier code for the given method name
288
* to be used in subsequent calls to UxMethodLookup.
289
* All calls to this function with the same method name
290
* return the same index.
293
* Called during interface class initialization for each method
294
* implemented by the class.
295
* It builds the method lookup table for the class.
297
* LAST REV: June 92 fix3574 Created.
298
*------------------------------------------------------------------------*/
301
int UxMethodRegister(cid, name, function)
305
#else /* _NO_PROTO */
306
int UxMethodRegister(int cid, char *name, void (*function) ())
307
#endif /* _NO_PROTO */
309
int mid = UxMessageIndex (name);
311
MethodTableSpace(cid, mid);
312
MethodTable[cid][mid] = (void *) function;
317
/*------------------------------------------------------------------------
318
* NAME: UxGetClassCode
320
* INPUT: some swidget
321
* RETURNS: its ifClassCode, or that of its nearest container
322
* that has a class code.
325
* This makes calling methods a little more flexible.
326
* Class codes are assigned to top-level swidgets in interfaces,
327
* when their delarations are initialized.
330
*------------------------------------------------------------------------*/
333
int UxGetClassCode(sw)
335
#else /* _NO_PROTO */
336
int UxGetClassCode(swidget sw)
337
#endif /* _NO_PROTO */
339
while (sw && UxGetIfClassCode(sw) < 0) {
340
sw = UxGetParent(sw);
344
return UxGetIfClassCode(sw);
349
/******************************************************************************
350
NAME: UxPutClassCode( wgt, id )
352
INPUT: Widget wgt - Widget
353
int id; - Id od method
355
RETURN: int UX_ERROR / UX_NO_ERROR
357
DESCRIPTION: Uses the X Context manager to store the given id
358
in a memory location that is indexed by the given widget id.
360
EXT REFERENCES: UxTopLevel, xcontext_mid
361
EXT EFFECTS: xcontext_mid
363
CREATION: Visual Edge Software January 9 1993
364
-----------------------------------------------------------------------------*/
367
int UxPutClassCode( wgt, id)
371
int UxPutClassCode( Widget wgt, int id)
372
#endif /* _NO_PROTO */
376
if ( xcontext_mid == 0 )
377
xcontext_mid = XUniqueContext();
382
status = XSaveContext( XtDisplay( UxTopLevel ),
389
XtAddCallback (wgt, XmNdestroyCallback,
390
UxDeleteContextCB, (XtPointer) xcontext_mid);
392
return ( UX_NO_ERROR );
396
/******************************************************************************
397
NAME: UxGetIfClassCode( wgt )
399
INPUT: Widget wgt - widget
401
RETURN: caddr_t - the context pointer
403
DESCRIPTION: Uses the X Context manager to find the method id
404
stored in a memory location indexed by the given widget id.
406
EXT REFERENCES: UxTopLevel, xcontext_mid
408
CREATION: Visual Edge Software January 9 1993
409
-----------------------------------------------------------------------------*/
412
int UxGetIfClassCode( wgt )
415
int UxGetIfClassCode( Widget wgt )
416
#endif /* _NO_PROTO */
424
status = XFindContext( XtDisplay( UxTopLevel ),
436
/*------------------------------------------------------------------------
438
* INPUT: swidget inst - user-defined component
439
* Gets the designatedChildSite by composing a call to the childSite
440
* method and calling that method. If the childSite is an intance,
441
* we recur by calling the childSite's childSite method and so on...
442
* LAST REV: March 1993 3988 - don't recur when childSite==this
443
*------------------------------------------------------------------------*/
445
swidget UxChildSite (inst)
447
#else /* _NO_PROTO */
448
swidget UxChildSite (swidget inst)
449
#endif /* _NO_PROTO */
451
/*-----------------------------------------------------
452
* Index of "childSite" in low-level method dispatcher.
453
*-----------------------------------------------------*/
454
static int ChildSiteMID = -1;
456
swidget childSite = NULL;
458
void (*childSiteMethod) () ;
460
void (*childSiteMethod) (swidget, Environment *);
463
if (ChildSiteMID == -1) {
464
ChildSiteMID = UxMessageIndex("childSite");
470
childSiteMethod = (void (*) ())
471
UxMethodLookup (inst, ChildSiteMID, "childSite");
472
if (childSiteMethod) {
473
childSite = ((swidget(*)())childSiteMethod) (inst, &UxEnv);
474
if (childSite && childSite != inst)
476
swidget nested = UxChildSite(childSite);
488
/*------------------------------------------------------------------------
489
* NAME: UxReclassifyCID (cid, super)
490
* <redefine a subclass as being derived from a new base.>
491
* INPUT: sub class id
494
* LAST REV: 3988 Mar 93 Created.
495
*------------------------------------------------------------------------*/
499
void UxReclassifyCID(cid, super)
502
#else /* _NO_PROTO */
503
void UxReclassifyCID(int cid, int super)
504
#endif /* _NO_PROTO */
507
UxInternalError(__FILE__, __LINE__, "Cid == Super Cid");
509
BaseTable[cid] = super;
511
#endif /* DESIGN_TIME */
512
/*------------------------------------------------------------------------
513
* NAME: UxInheritedMethodLookup
514
* INPUT: swidget sw; -- a swidget, usually an interface swidget
515
* int mid; -- a method id from UxMethodRegister
516
* RETURNS: Pointer to method function for this method.
518
* Like UxMethodLookup, but starts searching at the first
519
* base class of the given sw, not at its own class.
521
* LAST REV: 3988 March 93 Created.
522
*------------------------------------------------------------------------*/
526
void* UxInheritedMethodLookup (sw, mid, mname)
530
#else /* _NO_PROTO */
531
void* UxInheritedMethodLookup (swidget sw, int mid, char *mname)
532
#endif /* _NO_PROTO */
534
int cid = UxGetClassCode(sw);
536
if (cid < 0 || cid > NumClasses) {
541
mid = UxMessageIndex(mname);
547
cid = BaseTable[cid];
548
while (cid > -1 && cid < NumClasses)
550
if (mid < MethodCounts[cid] && MethodTable[cid][mid]) {
551
return MethodTable[cid][mid];
553
cid = BaseTable[cid];
557
#endif /* DESIGN_TIME */
560
/*------------------------------------------------------------------------
561
* NAME: UndefinedMethod
564
* DESCRIPTION: Function used as a return value of UxMethodLookup
565
* in case the method lookup fails.
567
* LAST REV: April 8 1993
568
*------------------------------------------------------------------------*/
571
static int UndefinedMethod ()
572
#else /* _NO_PROTO */
573
static int UndefinedMethod (void)
574
#endif /* _NO_PROTO */
578
#endif /* DESIGN_TIME */