2
* @OPENGROUP_COPYRIGHT@
4
* Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc.
5
* Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group
6
* ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for
7
* the full copyright text.
9
* This software is subject to an open license. It may only be
10
* used on, with or for operating systems which are themselves open
11
* source systems. You must contact The Open Group for a license
12
* allowing distribution and sublicensing of this software on, with,
13
* or for operating systems which are not Open Source programs.
15
* See http://www.opengroup.org/openmotif/license for full
16
* details of the license agreement. Any use, reproduction, or
17
* distribution of the program constitutes recipient's acceptance of
20
* EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
21
* PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
22
* KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
23
* WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
24
* OR FITNESS FOR A PARTICULAR PURPOSE
26
* EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT
27
* NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT,
28
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED
30
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32
* ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
33
* EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
34
* POSSIBILITY OF SUCH DAMAGES.
46
static char rcsid[] = "$TOG: Mrmwci.c /main/16 1999/05/19 15:25:58 mgreess $"
51
* (c) Copyright 1996 Hewlett-Packard Company *
52
* (c) Copyright 1996 International Business Machines Corp. *
53
* (c) Copyright 1996 Sun Microsystems, Inc. *
54
* (c) Copyright 1996 Novell, Inc. *
55
* (c) Copyright 1989, 1990, 1996 Digital Equipment Corporation. *
56
* (c) Copyright 1996 FUJITSU LIMITED. *
57
* (c) Copyright 1996 Hitachi. *
64
* UIL Resource Manager (URM):
68
* This module holds all routines, structures, and structure definitions
69
* required for the FT1 widget class information package (WCI). This
70
* package provides routines which register information about widget
71
* classes, and which retrieve information about widget classes
85
#include <X11/IntrinsicP.h>
86
#include <X11/CoreP.h>
88
#include <Mrm/MrmAppl.h>
98
static int hash_function ( int l_length , char *c_value );
104
* GLOBAL VARIABLE DECLARATIONS
109
* The list of registered classes, so they can be searched.
111
externaldef(urm__wci) WCIClassDescPtr wci_cldesc_list = NULL;
115
* OWN VARIABLE DECLARATIONS
124
/* The hash tables are initialized to NULL by default. */
125
static Boolean hash_hash_inited = FALSE;
126
static URMHashTableEntryPtr hash_az_hash_table [k_hash_table_size];
127
static Boolean cldesc_hash_inited = FALSE;
128
static URMHashTableEntryPtr cldesc_hash_table [k_hash_table_size];
136
* PROCEDURE DESCRIPTION:
138
* MrmRegisterClass saves the information needed to access the widget
139
* creation routine using the information in URM databases.
140
* type conversion of arglists.
144
* class_code NOW UNUSED
145
* class_name NOW UNUSED
146
* create_name The case-sensitive name of the low-level
147
* create routine for the class; an example
148
* from the Motif toolkit is XmLabelCreate.
149
* Arguments are (parent, name, arglist, argcount)
150
* The string which names the class in UIL.
151
* creator The low-level routine named create_name
152
* class_record The toolkit class record for the class
160
* MrmSUCCESS operation succeeded
161
* MrmFAILURE failure allocating class descriptor
171
#if NeedWidePrototypes
172
int class_code, /* unused */
174
MrmType class_code, /* unused */
176
String class_name, /* unused */
178
Widget (* creator) (),
179
WidgetClass class_record)
181
Cardinal status = MrmRegisterClassWithCleanup(
182
class_code, class_name,
183
create_name, creator,
190
MrmRegisterClassWithCleanup (
191
#if NeedWidePrototypes
192
int class_code, /* unused */
194
MrmType class_code, /* unused */
196
String class_name, /* unused */
198
Widget (* creator) (),
199
WidgetClass class_record,
205
WCIClassDescPtr cldesc; /* creator descriptor being written */
206
URMHashTableEntryPtr hash_entry; /* new hash entry */
211
* Allocate and fill in a new descriptor
213
if (create_name == NULL)
218
cldesc = (WCIClassDescPtr) XtMalloc (sizeof(WCIClassDesc) +
219
strlen(create_name) + 1);
220
if ( cldesc == NULL )
225
cldesc->creator_name = (String) cldesc + sizeof(WCIClassDesc);
226
strcpy (cldesc->creator_name, create_name);
227
cldesc->validation = URMWCIClassDescValid;
228
cldesc->next_desc = wci_cldesc_list;
229
wci_cldesc_list = cldesc;
230
cldesc->creator = creator;
231
cldesc->class_record = class_record;
232
cldesc->cleanup = cleanup;
235
* Enter the descriptor in the descriptor hash table
237
hash_initialize (cldesc_hash_table, &cldesc_hash_inited);
238
hash_entry = (URMHashTableEntryPtr)
239
hash_insert_name (cldesc_hash_table, cldesc->creator_name);
240
/* Begin fixing CR 5573 */
241
if (hash_entry->az_value != NULL)
242
XtFree ((char *) hash_entry->az_value);
243
/* End fixing CR 5573 */
244
hash_entry->az_value = (char *) cldesc;
253
Urm__WCI_UnregisterName (String name)
256
* Make sure the hash table is initialized
258
hash_initialize (hash_az_hash_table, &hash_hash_inited);
259
hash_delete_name (hash_az_hash_table, name);
261
return MrmSUCCESS; /* in any case */
268
* PROCEDURE DESCRIPTION:
270
* This routine inserts the names and their associated values into
271
* the hash table. No check for duplicate names is made - new
272
* values for duplicate names will override the previous value.
276
* names A vector of case-sensitive callback routine names.
277
* values A vector of the corresponding routine addresses
278
* num_cb The number of entries in names and values.
286
* MrmSUCCESS operation succeeded
294
Urm__WCI_RegisterNames (String *names,
300
URMHashTableEntryPtr hash_entry;
306
* Make sure the hash table is initialized
308
hash_initialize (hash_az_hash_table, &hash_hash_inited);
311
* Store each name-value pair in the hash table.
313
for (ndx = 0 ; ndx < num_cb ; ndx++)
315
current_name = names [ndx];
316
current_value = values [ndx];
317
hash_entry = (URMHashTableEntryPtr)
318
hash_insert_name (hash_az_hash_table, current_name);
319
hash_entry -> az_value = current_value;
331
* PROCEDURE DESCRIPTION:
333
* This routin returns a pointer to the class descriptor for a class.
334
* The descriptor hash table is used to look up descriptors.
338
* class_name Class name if class_code is URMwcUnknown
339
* class_return To return pointer to class descriptor
347
* MrmSUCCESS operation succeeded
348
* MrmNOT_FOUND descriptor not found
356
Urm__WCI_LookupClassDescriptor (String class_name,
357
WCIClassDescPtr *class_return)
362
URMHashTableEntryPtr hash_entry; /* hash entry found */
367
* Find a hash entry, and return the value.
369
hash_entry = (URMHashTableEntryPtr)
370
hash_find_name (cldesc_hash_table, class_name);
371
if ( hash_entry == NULL )
373
*class_return = NULL;
374
sprintf (err_msg, _MrmMMsg_0051, class_name);
375
return Urm__UT_Error ("Urm__WCI_LookupClassDescriptor",
376
err_msg, NULL, NULL, MrmNOT_FOUND);
378
*class_return = (WCIClassDescPtr) hash_entry->az_value;
388
* PROCEDURE DESCRIPTION:
390
* This routine locates a class record for a given class name,
391
* and returns the widget class record associated with it.
392
* It searches for a match on either the name in the class record
393
* or the creation routine name.
397
* clname the display name of the class
405
* Class record pointer, or NULL if not found
413
Urm__WCI_GetClRecOfName (String clname)
418
WCIClassDescPtr cldesc; /* current class */
421
* Search the class list
423
for ( cldesc=wci_cldesc_list ; cldesc!=NULL ; cldesc=cldesc->next_desc)
425
if ( strcmp(clname,cldesc->creator_name) == 0 )
426
return cldesc->class_record;
427
if ( cldesc->class_record == NULL ) continue;
428
if ( strcmp(clname,cldesc->class_record->core_class.class_name) == 0 )
429
return cldesc->class_record;
441
* PROCEDURE DESCRIPTION:
443
* This routine gets, from the hash table, the value that corresponds
444
* to the given name. If no match is found, NULL is returned.
448
* name case-sensitive name to be matched
449
* value_return to return value.
457
* MrmSUCCESS operation succeeded
458
* MrmNOT_FOUND no match found
466
Urm__WCI_LookupRegisteredName (String name,
467
XtPointer *value_return)
470
URMHashTableEntryPtr hash_entry;
473
hash_entry = (URMHashTableEntryPtr)
474
hash_find_name (hash_az_hash_table, name);
476
if (hash_entry == NULL)
478
*value_return = NULL;
483
*value_return = hash_entry->az_value;
493
** FUNCTIONAL DESCRIPTION:
495
** This routine initializes a hash table.
497
** FORMAL PARAMETERS:
499
** htable the hash table to initialize
500
** initflag if TRUE, the table is already initialized
518
hash_initialize (URMHashTableEntryPtr *htable,
521
int ndx; /* loop index */
525
* Initialize only once
529
for ( ndx=0 ; ndx<k_hash_table_size ; ndx++ )
539
** FUNCTIONAL DESCRIPTION:
541
** This routine searches for a hash table entry of the same name
542
** as its parameters. If the entry is found, a pointer to the
543
** found hash table entry is returned as the value of the function.
544
** If no entry is found, a NULL pointer is returned.
546
** FORMAL PARAMETERS:
548
** htable the hash table to search
549
** c_text pointer to a null terminated string for name
559
** a pointer to a hash table entry, or NULL
569
hash_find_name (URMHashTableEntryPtr *htable,
573
URMHashTableEntryPtr az_current_name;
575
int l_compare_result;
577
if (c_text == NULL) return(NULL);
579
/* obtain the hash code for the name */
581
l_length = strlen (c_text);
582
l_hash_code = hash_function( l_length, c_text );
585
** chain along hash chain looking for symbol - exit loop under 3 condition
586
** 1) come to the end of the chain: name not found
587
** 2) find symbol: return this symbol
588
** 3) find node > symbol: name not found
591
for (az_current_name = htable[ l_hash_code ];
592
az_current_name != NULL;
593
az_current_name = az_current_name->az_next_entry)
595
l_compare_result = strcmp (c_text, az_current_name->c_text);
597
if (l_compare_result == 0) /* c_text = current name */
599
/* found the entry we are looking for */
601
return az_current_name;
604
if (l_compare_result > 0) /* c_text > current name */
606
/* return NULL - name should be before this spot in list */
608
return (URMHashTableEntryPtr) NULL;
613
/* came to end of the list without finding the name */
615
return (URMHashTableEntryPtr) NULL;
622
** FUNCTIONAL DESCRIPTION:
624
** This routine searches for a name entry of the same name as its parameters.
625
** If the entry is found, a pointer to that entry node is
626
** returned as the value of the function. If no entry is found, one is
627
** allocated and inserted. In this case the value of the function is
628
** a pointer to the name entry created.
630
** Name entries are linked off of a hash table. Those
631
** entries that have the same hash code, are sorted according to the
632
** collating sequence. Thus the algorithm involves hashing the symbol and
633
** then following the chain for that hash code until one of the following
634
** conditions is met. 1) the identifier is found, then return a pointer
635
** to that entry. 2) come to the end of the chain or a hash table
636
** entry that comes later in the collating sequence than the symbol being
637
** searched for. In this case the name is inserted just prior to this
638
** point in the chain.
640
** FORMAL PARAMETERS:
642
** htable the hash table to update
643
** c_text pointer to a null terminated string for name
649
** htable may be updated with an additional name
653
** a pointer to a hash table entry
657
** may create a new entry and update the hash table
663
hash_insert_name (URMHashTableEntryPtr *htable,
667
URMHashTableEntryPtr az_previous_name;
668
URMHashTableEntryPtr az_current_name;
669
URMHashTableEntryPtr az_new_name;
671
int l_compare_result;
674
** algorithm keeps 2 pointers, one for the previous name and one
675
** for the current name. This permits easy insertion of a new name
679
/* obtain the hash code of for the name */
681
l_length = strlen (c_text);
682
l_hash_code = hash_function( l_length, c_text );
685
** chain along hash chain looking for symbol - exit loop under 3 condition
686
** 1) come to the end of the chain: insert new node on end
687
** 2) find symbol: return this symbol
688
** 3) find node > symbol: insert new node prior to current node
691
for (az_current_name = htable[ l_hash_code ],
692
az_previous_name = (URMHashTableEntryPtr) NULL;
694
az_current_name != (URMHashTableEntryPtr) NULL;
696
az_previous_name = az_current_name,
697
az_current_name = az_current_name->az_next_entry)
699
l_compare_result = strcmp (c_text, az_current_name->c_text);
701
if (l_compare_result == 0) /* c_text = current name */
703
/* found the name we are looking for */
705
return az_current_name;
708
if (l_compare_result > 0) /* c_text > current name */
710
/* exit the loop to insert just prior to current name */
720
** name is not in the table so it must be inserted between the
721
** az_previous_name and az_current_name entries.
724
/* allocate and initialize the name entry, including the null */
725
az_new_name = (URMHashTableEntryPtr)
726
XtMalloc (sizeof(URMHashTableEntry)+l_length+1);
728
az_new_name -> az_value = (char *) NULL;
729
UrmBCopy (c_text, az_new_name -> c_text, l_length + 1);
732
** link the name entry into the hash table
735
az_new_name->az_next_entry = az_current_name;
737
if (az_previous_name == (URMHashTableEntryPtr) NULL)
738
htable[ l_hash_code ] = az_new_name;
740
az_previous_name->az_next_entry = az_new_name;
751
** FUNCTIONAL DESCRIPTION:
753
** just like hash_insert_name but removes the item instead
758
hash_delete_name (URMHashTableEntryPtr *htable,
762
URMHashTableEntryPtr az_previous_name;
763
URMHashTableEntryPtr az_current_name;
765
int l_compare_result;
768
** algorithm keeps 2 pointers, one for the previous name and one
769
** for the current name. This permits easy deletion of a name
773
/* obtain the hash code of for the name */
775
l_length = strlen (c_text);
776
l_hash_code = hash_function( l_length, c_text );
779
** chain along hash chain looking for symbol - exit loop under 3 condition
780
** 1) come to the end of the chain: too far; return
781
** 2) find symbol: delete
782
** 3) find node > symbol: too far; return
785
for (az_current_name = htable[ l_hash_code ],
786
az_previous_name = (URMHashTableEntryPtr) NULL;
788
az_current_name != (URMHashTableEntryPtr) NULL;
790
az_previous_name = az_current_name,
791
az_current_name = az_current_name->az_next_entry)
793
l_compare_result = strcmp (c_text, az_current_name->c_text);
795
if (l_compare_result == 0) /* c_text = current name */
797
/* found the name we are looking for */
801
if (l_compare_result > 0) /* c_text > current name */
803
/* return NULL - name should be before this spot in list */
804
return (URMHashTableEntryPtr) NULL;
808
/* came to end of the list without finding the name */
809
return (URMHashTableEntryPtr) NULL;
814
** remove the name entry from the hash table
817
if (az_previous_name == (URMHashTableEntryPtr) NULL)
818
htable[ l_hash_code ] = az_current_name->az_next_entry;
820
az_previous_name->az_next_entry = az_current_name->az_next_entry;
822
XtFree((char*)az_current_name);
824
return (URMHashTableEntryPtr) NULL;
833
** FUNCTIONAL DESCRIPTION:
835
** This procedure is a hashing function. It takes a length and a
836
** pointer to a value. Using this value as a string, the function
837
** returns an integer in the range of 0 to sym_k_hash_table_limit-1.
839
** FORMAL PARAMETERS:
841
** l_length length of the value in bytes not including null
842
** c_value a null terminated string
846
** sym_k_hash_table_limit
854
** integer (the hash code) in range 0 to sym_k_hash_table_limit-1
864
hash_function(int l_length,
869
static unsigned int XmConst mask[ 8 ] =
870
{ 0x00000000000000FF, 0x000000000000FFFF,
871
0x0000000000FFFFFF, 0x00000000FFFFFFFF,
872
0x00000000FFFFFFFF, 0x0000FFFFFFFFFFFF,
873
0x00FFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, };
876
static unsigned int XmConst mask[ 4 ] =
877
{ 0x000000FF, 0x0000FFFF, 0x00FFFFFF, 0xFFFFFFFF };
879
unsigned int l_hash_code;
880
unsigned int al_value[20];
885
/* BEGIN OSF Fix CR 5232 */
886
/* Don't go past array bounds */
887
if (l_length > (sizeof(int) * 20)) l_length = sizeof(int) * 20;
888
/* END OSF Fix CR 5232 */
890
l_limit = (l_length-1) >> _shift; /* divide by wordsize */
891
/* BEGIN OSF Fix CR 5232 */
892
l_extra = (l_length-1) & _shift; /* remainder from divide by wordsize */
893
/* END OSF Fix CR 5232 */
895
bzero((char *)al_value, sizeof(int) * 20);
896
strncpy((char *)al_value, c_value, l_length);
899
for (i = 0 ; i < l_limit ; i++)
900
l_hash_code = l_hash_code ^ al_value[ i ];
902
l_hash_code = l_hash_code ^ (al_value[ i ] & mask[ l_extra ]);
904
/* BEGIN OSF Fix CR 5232 */
905
/* Make sure result isn't negative */
906
return abs((int)(l_hash_code % k_hash_table_size));
907
/* END OSF Fix CR 5232 */