]> Pileus Git - ~andy/gtk/blob - gtk/gtktypeutils.c
added args ::show_text, ::text_xalign, ::text_yalign, ::activity_mode.
[~andy/gtk] / gtk / gtktypeutils.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 #include <string.h>
20 #include "gtktypeutils.h"
21
22
23 #define TYPE_NODES_BLOCK_SIZE   (200)
24
25 typedef struct _GtkTypeNode GtkTypeNode;
26
27 struct _GtkTypeNode
28 {
29   GtkType type;
30   GtkTypeInfo type_info;
31   guint n_supers : 24;
32   guint chunk_alloc_locked : 1;
33   GtkType *supers;
34   GtkType parent_type;
35   gpointer klass;
36   GList *children_types;
37   GMemChunk *mem_chunk;
38 };
39
40
41 #define LOOKUP_TYPE_NODE(node_var, type)        { \
42   if (type > 0) \
43   { \
44     register GtkType sqn = GTK_TYPE_SEQNO (type); \
45     if (sqn < n_type_nodes) \
46       node_var = type_nodes + sqn; \
47     else \
48       node_var = NULL; \
49   } \
50   else \
51     node_var = NULL; \
52 }
53
54 static void  gtk_type_class_init                (GtkType      node_type);
55 static guint gtk_type_name_hash                 (const char  *key);
56 static gint  gtk_type_name_compare              (const char  *a,
57                                                  const char  *b);
58 static void  gtk_type_init_builtin_types        (void);
59
60 static GtkTypeNode *type_nodes = NULL;
61 static guint        n_type_nodes = 0;
62 static GHashTable  *type_name_2_type_ht = NULL;
63
64
65 static GtkTypeNode*
66 gtk_type_node_next_and_invalidate (void)
67 {
68   static guint  n_free_type_nodes = 0;
69   register GtkTypeNode  *node;
70   register GtkType new_type;
71   
72   /* don't keep *any* GtkTypeNode pointers across invokation of this function!!!
73    */
74   
75   if (n_free_type_nodes == 0)
76     {
77       register guint i;
78       register guint size;
79       
80       /* nearest pow
81        */
82       size = n_type_nodes + TYPE_NODES_BLOCK_SIZE;
83       size *= sizeof (GtkTypeNode);
84       i = 1;
85       while (i < size)
86         i <<= 1;
87       size = i;
88       
89       type_nodes = g_realloc (type_nodes, size);
90       
91       n_free_type_nodes = size / sizeof (GtkTypeNode) - n_type_nodes;
92       
93       memset (type_nodes + n_type_nodes, 0, n_free_type_nodes * sizeof (GtkTypeNode));
94     }
95   
96   new_type = n_type_nodes++;
97   n_free_type_nodes--;
98   
99   /* This can't be used here - new_type can be over 256!
100    * LOOKUP_TYPE_NODE (node, new_type);
101    * Code copied from above (we may assume we are all right here):
102    */
103
104   if(new_type == 0) 
105     return NULL;
106   node = type_nodes + new_type;
107
108   if (node)
109     node->type = new_type;
110   
111   return node;
112 }
113
114 void
115 gtk_type_init (void)
116 {
117   if (n_type_nodes == 0)
118     {
119       GtkTypeNode *zero;
120       
121       g_assert (sizeof (GtkType) >= 4);
122       
123       zero = gtk_type_node_next_and_invalidate ();
124       g_assert (zero == NULL);
125       
126       type_name_2_type_ht = g_hash_table_new ((GHashFunc) gtk_type_name_hash,
127                                               (GCompareFunc) gtk_type_name_compare);
128       
129       gtk_type_init_builtin_types ();
130     }
131 }
132
133 void
134 gtk_type_set_chunk_alloc (GtkType      type,
135                           guint        n_chunks)
136 {
137   GtkTypeNode *node;
138   
139   LOOKUP_TYPE_NODE (node, type);
140   g_return_if_fail (node != NULL);
141   g_return_if_fail (node->chunk_alloc_locked == FALSE);
142   
143   if (node->mem_chunk)
144     {
145       g_mem_chunk_destroy (node->mem_chunk);
146       node->mem_chunk = NULL;
147     }
148   
149   if (n_chunks)
150     node->mem_chunk = g_mem_chunk_new (node->type_info.type_name,
151                                        node->type_info.object_size,
152                                        node->type_info.object_size * n_chunks,
153                                        G_ALLOC_AND_FREE);
154 }
155
156 static GtkType
157 gtk_type_create (GtkType      parent_type,
158                  gchar        *type_name,
159                  GtkTypeInfo *type_info)
160 {
161   GtkTypeNode *new_node;
162   GtkTypeNode *parent;
163   guint i;
164   
165   if (g_hash_table_lookup (type_name_2_type_ht, type_name))
166     {
167       g_warning ("gtk_type_create(): type `%s' already exists.", type_name);
168       return 0;
169     }
170   
171   if (parent_type)
172     {
173       GtkTypeNode *tmp_node;
174       
175       LOOKUP_TYPE_NODE (tmp_node, parent_type);
176       if (!tmp_node)
177         {
178           g_warning ("gtk_type_create(): unknown parent type `%u'.", parent_type);
179           return 0;
180         }
181     }
182   
183   /* relookup pointers afterwards.
184    */
185   new_node = gtk_type_node_next_and_invalidate ();
186   
187   if (parent_type)
188     {
189       new_node->type = GTK_TYPE_MAKE (parent_type, new_node->type);
190       LOOKUP_TYPE_NODE (parent, parent_type);
191     }
192   else
193     {
194       g_assert (new_node->type <= 0xff);
195       parent = NULL;
196     }
197   
198   new_node->type_info = *type_info;
199   new_node->type_info.type_name = type_name;
200   /* new_node->type_info.reserved_1 = NULL; */
201   new_node->type_info.reserved_2 = NULL;
202   new_node->n_supers = parent ? parent->n_supers + 1 : 0;
203   new_node->chunk_alloc_locked = FALSE;
204   new_node->supers = g_new0 (GtkType, new_node->n_supers + 1);
205   new_node->parent_type = parent_type;
206   new_node->klass = NULL;
207   new_node->children_types = NULL;
208   new_node->mem_chunk = NULL;
209   
210   if (parent)
211     parent->children_types = g_list_append (parent->children_types, GUINT_TO_POINTER (new_node->type));
212   
213   parent = new_node;
214   for (i = 0; i < new_node->n_supers + 1; i++)
215     {
216       new_node->supers[i] = parent->type;
217       LOOKUP_TYPE_NODE (parent, parent->parent_type);
218     }
219   
220   g_hash_table_insert (type_name_2_type_ht, new_node->type_info.type_name, GUINT_TO_POINTER (new_node->type));
221   
222   return new_node->type;
223 }
224
225 GtkType
226 gtk_type_unique (GtkType      parent_type,
227                  GtkTypeInfo *type_info)
228 {
229   GtkType new_type;
230   gchar *type_name;
231   
232   g_return_val_if_fail (type_info != NULL, 0);
233   g_return_val_if_fail (type_info->type_name != NULL, 0);
234   
235   if (n_type_nodes == 0)
236     gtk_type_init ();
237   
238   type_name = g_strdup (type_info->type_name);
239   
240   /* relookup pointers afterwards.
241    */
242   new_type = gtk_type_create (parent_type, type_name, type_info);
243   
244   if (!new_type)
245     g_free (type_name);
246   
247   return new_type;
248 }
249
250 gchar*
251 gtk_type_name (GtkType type)
252 {
253   GtkTypeNode *node;
254   
255   LOOKUP_TYPE_NODE (node, type);
256   
257   if (node)
258     return node->type_info.type_name;
259   
260   return NULL;
261 }
262
263 GtkType
264 gtk_type_from_name (const gchar *name)
265 {
266   if (type_name_2_type_ht)
267     {
268       GtkType type;
269       
270       type = GPOINTER_TO_UINT (g_hash_table_lookup (type_name_2_type_ht, (gpointer) name));
271       
272       return type;
273     }
274   
275   return 0;
276 }
277
278 GtkType
279 gtk_type_parent (GtkType type)
280 {
281   GtkTypeNode *node;
282   
283   LOOKUP_TYPE_NODE (node, type);
284   if (node)
285     return node->parent_type;
286   
287   return 0;
288 }
289
290 gpointer
291 gtk_type_parent_class (GtkType type)
292 {
293   GtkTypeNode *node;
294   
295   LOOKUP_TYPE_NODE (node, type);
296   g_return_val_if_fail (node != NULL, NULL);
297   
298   if (node)
299     {
300       LOOKUP_TYPE_NODE (node, node->parent_type);
301       
302       if (node)
303         {
304           if (!node->klass)
305             {
306               type = node->type;
307               gtk_type_class_init (type);
308               LOOKUP_TYPE_NODE (node, type);
309             }
310           
311           return node->klass;
312         }
313     }
314   
315   return NULL;
316 }
317
318 gpointer
319 gtk_type_class (GtkType type)
320 {
321   GtkTypeNode *node;
322   
323   LOOKUP_TYPE_NODE (node, type);
324   g_return_val_if_fail (node != NULL, NULL);
325   
326   if (!node->klass)
327     {
328       type = node->type;
329       gtk_type_class_init (type);
330       LOOKUP_TYPE_NODE (node, type);
331     }
332   
333   return node->klass;
334 }
335
336 gpointer
337 gtk_type_new (GtkType type)
338 {
339   GtkTypeNode *node;
340   GtkTypeObject *tobject;
341   gpointer klass;
342   
343   LOOKUP_TYPE_NODE (node, type);
344   g_return_val_if_fail (node != NULL, NULL);
345   
346   klass = node->klass;
347   if (!klass)
348     {
349       klass = gtk_type_class (type);
350       LOOKUP_TYPE_NODE (node, type);
351     }
352   node->chunk_alloc_locked = TRUE;
353
354   if (node->mem_chunk)
355     tobject = g_mem_chunk_alloc0 (node->mem_chunk);
356   else
357     tobject = g_malloc0 (node->type_info.object_size);
358   
359   /* we need to call the base classes' object_init_func for derived
360    * objects with the object's ->klass field still pointing to the
361    * corresponding base class, otherwise overridden class functions
362    * could get called with partly-initialized objects. the real object
363    * class is passed as second argment to the initializers.
364    */
365   if (node->n_supers)
366     {
367       guint i;
368       GtkType *supers;
369       GtkTypeNode *pnode;
370
371       supers = node->supers;
372       for (i = node->n_supers; i > 0; i--)
373         {
374           LOOKUP_TYPE_NODE (pnode, supers[i]);
375           if (pnode->type_info.object_init_func)
376             {
377               tobject->klass = pnode->klass;
378               pnode->type_info.object_init_func (tobject, klass);
379             }
380         }
381       LOOKUP_TYPE_NODE (node, type);
382     }
383   tobject->klass = klass;
384   if (node->type_info.object_init_func)
385     {
386       node->type_info.object_init_func (tobject, klass);
387       tobject->klass = klass;
388     }
389   
390   return tobject;
391 }
392
393 void
394 gtk_type_free (GtkType      type,
395                gpointer     mem)
396 {
397   GtkTypeNode *node;
398   
399   g_return_if_fail (mem != NULL);
400   LOOKUP_TYPE_NODE (node, type);
401   g_return_if_fail (node != NULL);
402   
403   if (node->mem_chunk)
404     g_mem_chunk_free (node->mem_chunk, mem);
405   else
406     g_free (mem);
407 }
408
409 GList*
410 gtk_type_children_types (GtkType type)
411 {
412   GtkTypeNode *node;
413   
414   LOOKUP_TYPE_NODE (node, type);
415   if (node)
416     return node->children_types;
417   
418   return NULL;
419 }
420
421 void
422 gtk_type_describe_heritage (GtkType type)
423 {
424   GtkTypeNode *node;
425   gchar *is_a = "";
426   
427   LOOKUP_TYPE_NODE (node, type);
428   
429   while (node)
430     {
431       if (node->type_info.type_name)
432         g_message ("%s%s",
433                    is_a,
434                    node->type_info.type_name);
435       else
436         g_message ("%s<unnamed type>",
437                    is_a);
438       is_a = "is a ";
439       
440       LOOKUP_TYPE_NODE (node, node->parent_type);
441     }
442 }
443
444 void
445 gtk_type_describe_tree (GtkType  type,
446                         gboolean show_size)
447 {
448   GtkTypeNode *node;
449   
450   LOOKUP_TYPE_NODE (node, type);
451   
452   if (node)
453     {
454       static gint indent = 0;
455       GList *list;
456       guint old_indent;
457       guint i;
458       GString *gstring;
459
460       gstring = g_string_new ("");
461       
462       for (i = 0; i < indent; i++)
463         g_string_append_c (gstring, ' ');
464       
465       if (node->type_info.type_name)
466         g_string_append (gstring, node->type_info.type_name);
467       else
468         g_string_append (gstring, "<unnamed type>");
469       
470       if (show_size)
471         g_string_sprintfa (gstring, " (%d bytes)", node->type_info.object_size);
472
473       g_message ("%s", gstring->str);
474       g_string_free (gstring, TRUE);
475       
476       old_indent = indent;
477       indent += 4;
478       
479       for (list = node->children_types; list; list = list->next)
480         gtk_type_describe_tree (GPOINTER_TO_UINT (list->data), show_size);
481       
482       indent = old_indent;
483     }
484 }
485
486 gboolean
487 gtk_type_is_a (GtkType type,
488                GtkType is_a_type)
489 {
490   if (type == is_a_type)
491     return TRUE;
492   else
493     {
494       register GtkTypeNode *node;
495       
496       LOOKUP_TYPE_NODE (node, type);
497       if (node)
498         {
499           register GtkTypeNode *a_node;
500           
501           LOOKUP_TYPE_NODE (a_node, is_a_type);
502           if (a_node)
503             {
504               if (a_node->n_supers <= node->n_supers)
505                 return node->supers[node->n_supers - a_node->n_supers] == is_a_type;
506             }
507         }
508     }
509   
510   return FALSE;
511 }
512
513 static void
514 gtk_type_class_init (GtkType type)
515 {
516   GtkTypeNode *node;
517
518   /* we need to relookup nodes everytime we called an external function */
519   LOOKUP_TYPE_NODE (node, type);
520   
521   if (!node->klass && node->type_info.class_size)
522     {
523       GtkTypeClass *type_class;
524       GtkTypeNode *base_node;
525       GSList *slist;
526       
527       if (node->type_info.class_size < sizeof (GtkTypeClass))
528         g_warning ("The `%s' class is too small to inherit from GtkTypeClass",
529                    node->type_info.type_name);
530       
531       node->klass = g_malloc0 (node->type_info.class_size);
532       
533       if (node->parent_type)
534         {
535           GtkTypeNode *parent;
536           
537           LOOKUP_TYPE_NODE (parent, node->parent_type);
538           
539           if (node->type_info.class_size < parent->type_info.class_size)
540             g_warning ("The `%s' class is smaller than its parent class `%s'",
541                        node->type_info.type_name,
542                        parent->type_info.type_name);
543           
544           if (!parent->klass)
545             {
546               gtk_type_class_init (parent->type);
547               LOOKUP_TYPE_NODE (node, type);
548               LOOKUP_TYPE_NODE (parent, node->parent_type);
549             }
550           
551           if (parent->klass)
552             memcpy (node->klass, parent->klass, parent->type_info.class_size);
553         }
554       
555       type_class = node->klass;
556       type_class->type = node->type;
557       
558       /* stack all base class initialization functions, so we
559        * call them in ascending order.
560        */
561       base_node = node;
562       slist = NULL;
563       while (base_node)
564         {
565           if (base_node->type_info.base_class_init_func)
566             slist = g_slist_prepend (slist, base_node->type_info.base_class_init_func);
567           LOOKUP_TYPE_NODE (base_node, base_node->parent_type);
568         }
569       if (slist)
570         {
571           GSList *walk;
572           
573           for (walk = slist; walk; walk = walk->next)
574             {
575               register GtkClassInitFunc base_class_init;
576               
577               base_class_init = walk->data;
578               base_class_init (node->klass);
579               LOOKUP_TYPE_NODE (node, type);
580             }
581           g_slist_free (slist);
582         }
583       
584       if (node->type_info.class_init_func)
585         node->type_info.class_init_func (node->klass);
586     }
587 }
588
589 static inline gchar*
590 gtk_type_descriptive_name (GtkType type)
591 {
592   gchar *name;
593
594   name = gtk_type_name (type);
595   if (!name)
596     name = "(unknown)";
597
598   return name;
599 }
600
601 GtkTypeObject*
602 gtk_type_check_object_cast (GtkTypeObject  *type_object,
603                             GtkType         cast_type)
604 {
605   if (!type_object)
606     {
607       g_warning ("invalid cast from (NULL) pointer to `%s'",
608                  gtk_type_descriptive_name (cast_type));
609       return type_object;
610     }
611   if (!type_object->klass)
612     {
613       g_warning ("invalid unclassed pointer in cast to `%s'",
614                  gtk_type_descriptive_name (cast_type));
615       return type_object;
616     }
617   /* currently, GTK_TYPE_OBJECT is the lowest fundamental type
618    * dominator for types that introduce classes.
619    */
620   if (type_object->klass->type < GTK_TYPE_OBJECT)
621     {
622       g_warning ("invalid class type `%s' in cast to `%s'",
623                  gtk_type_descriptive_name (type_object->klass->type),
624                  gtk_type_descriptive_name (cast_type));
625       return type_object;
626     }
627   if (!gtk_type_is_a (type_object->klass->type, cast_type))
628     {
629       g_warning ("invalid cast from `%s' to `%s'",
630                  gtk_type_descriptive_name (type_object->klass->type),
631                  gtk_type_descriptive_name (cast_type));
632       return type_object;
633     }
634
635   return type_object;
636 }
637
638 GtkTypeClass*
639 gtk_type_check_class_cast (GtkTypeClass   *klass,
640                            GtkType         cast_type)
641 {
642   if (!klass)
643     {
644       g_warning ("invalid class cast from (NULL) pointer to `%s'",
645                  gtk_type_descriptive_name (cast_type));
646       return klass;
647     }
648   /* currently, GTK_TYPE_OBJECT is the lowest fundamental type
649    * dominator for types that introduce classes.
650    */
651   if (klass->type < GTK_TYPE_OBJECT)
652     {
653       g_warning ("invalid class type `%s' in class cast to `%s'",
654                  gtk_type_descriptive_name (klass->type),
655                  gtk_type_descriptive_name (cast_type));
656       return klass;
657     }
658   if (!gtk_type_is_a (klass->type, cast_type))
659     {
660       g_warning ("invalid class cast from `%s' to `%s'",
661                  gtk_type_descriptive_name (klass->type),
662                  gtk_type_descriptive_name (cast_type));
663       return klass;
664     }
665
666   return klass;
667 }
668
669 GtkEnumValue*
670 gtk_type_enum_get_values (GtkType      enum_type)
671 {
672   if (GTK_FUNDAMENTAL_TYPE (enum_type) == GTK_TYPE_ENUM ||
673       GTK_FUNDAMENTAL_TYPE (enum_type) == GTK_TYPE_FLAGS)
674     {
675       GtkTypeNode *node;
676       
677       LOOKUP_TYPE_NODE (node, enum_type);
678       if (node)
679         return (GtkEnumValue*) node->type_info.reserved_1;
680     }
681   
682   g_warning ("gtk_type_enum_get_values(): type `%s' is not derived from `GtkEnum' or `GtkFlags'",
683              gtk_type_name (enum_type));
684   
685   return NULL;
686 }
687
688 GtkFlagValue*
689 gtk_type_flags_get_values (GtkType        flags_type)
690 {
691   return gtk_type_enum_get_values (flags_type);
692 }
693
694 GtkEnumValue*
695 gtk_type_enum_find_value (GtkType        enum_type,
696                           const gchar    *value_name)
697 {
698   g_return_val_if_fail (value_name != NULL, NULL);
699   
700   if (GTK_FUNDAMENTAL_TYPE (enum_type) == GTK_TYPE_ENUM ||
701       GTK_FUNDAMENTAL_TYPE (enum_type) == GTK_TYPE_FLAGS)
702     {
703       GtkEnumValue *vals;
704
705       vals = gtk_type_enum_get_values (enum_type);
706       if (vals)
707         while (vals->value_name)
708           {
709             if (strcmp (vals->value_name, value_name) == 0 ||
710                 strcmp (vals->value_nick, value_name) == 0)
711               return vals;
712             vals++;
713           }
714     }
715   else
716     g_warning ("gtk_type_enum_find_value(): type `%s' is not derived from `GtkEnum' or `GtkFlags'",
717                gtk_type_name (enum_type));
718   
719   return NULL;
720 }
721
722 GtkFlagValue*
723 gtk_type_flags_find_value (GtkType         flag_type,
724                            const gchar    *value_name)
725 {
726   g_return_val_if_fail (value_name != NULL, NULL);
727
728   return gtk_type_enum_find_value (flag_type, value_name);
729 }
730
731 typedef struct _GtkTypeVarargType GtkTypeVarargType;
732 struct _GtkTypeVarargType
733 {
734   GtkType foreign_type;
735   GtkType varargs_type;
736 };
737
738 static GtkTypeVarargType *vararg_types = NULL;
739 static guint              n_vararg_types = 0;
740
741 void
742 gtk_type_set_varargs_type (GtkType        foreign_type,
743                            GtkType        varargs_type)
744 {
745   g_return_if_fail (foreign_type == GTK_FUNDAMENTAL_TYPE (foreign_type));
746   g_return_if_fail (foreign_type > GTK_TYPE_FUNDAMENTAL_LAST);
747
748   if (!((varargs_type >= GTK_TYPE_STRUCTURED_FIRST &&
749          varargs_type <= GTK_TYPE_STRUCTURED_LAST) ||
750         (varargs_type >= GTK_TYPE_FLAT_FIRST &&
751          varargs_type <= GTK_TYPE_FLAT_LAST) ||
752         varargs_type == GTK_TYPE_NONE))
753     {
754       g_warning ("invalid varargs type `%s' for fundamental type `%s'",
755                  gtk_type_name (varargs_type),
756                  gtk_type_name (foreign_type));
757       return;
758     }
759   if (gtk_type_get_varargs_type (foreign_type))
760     {
761       g_warning ("varargs type is already registered for fundamental type `%s'",
762                  gtk_type_name (foreign_type));
763       return;
764     }
765
766   n_vararg_types++;
767   vararg_types = g_realloc (vararg_types, sizeof (GtkTypeVarargType) * n_vararg_types);
768
769   vararg_types[n_vararg_types - 1].foreign_type = foreign_type;
770   vararg_types[n_vararg_types - 1].varargs_type = varargs_type;
771 }
772
773 GtkType
774 gtk_type_get_varargs_type (GtkType foreign_type)
775 {
776   GtkType type;
777   guint i;
778
779   type = GTK_FUNDAMENTAL_TYPE (foreign_type);
780   if (type <= GTK_TYPE_FUNDAMENTAL_LAST)
781     return type;
782
783   for (i = 0; i < n_vararg_types; i++)
784     if (vararg_types[i].foreign_type == type)
785       return vararg_types[i].varargs_type;
786
787   return 0;
788 }
789
790 static inline GtkType
791 gtk_type_register_intern (gchar        *name,
792                           GtkType       parent,
793                           GtkEnumValue *values)
794 {
795   GtkType type_id;
796   GtkTypeInfo info;
797   
798   info.type_name = name;
799   info.object_size = 0;
800   info.class_size = 0;
801   info.class_init_func = NULL;
802   info.object_init_func = NULL;
803   info.reserved_1 = values;
804   info.reserved_2 = NULL;
805   
806   /* relookup pointers afterwards.
807    */
808   type_id = gtk_type_create (parent, name, &info);
809   
810   if (type_id && values)
811     {
812       guint i;
813       
814       /* check for proper type consistency and NULL termination
815        * of value array
816        */
817       g_assert (GTK_FUNDAMENTAL_TYPE (type_id) == GTK_TYPE_ENUM ||
818                 GTK_FUNDAMENTAL_TYPE (type_id) == GTK_TYPE_FLAGS);
819       
820       i = 0;
821       while (values[i].value_name)
822         i++;
823       
824       g_assert (values[i].value_name == NULL && values[i].value_nick == NULL);
825     }
826   
827   return type_id;
828 }
829
830 GtkType
831 gtk_type_register_enum (const gchar    *type_name,
832                         GtkEnumValue   *values)
833 {
834   GtkType type_id;
835   gchar *name;
836   
837   g_return_val_if_fail (type_name != NULL, 0);
838   
839   name = g_strdup (type_name);
840   
841   /* relookup pointers afterwards.
842    */
843   type_id = gtk_type_register_intern (name, GTK_TYPE_ENUM, values);
844   
845   if (!type_id)
846     g_free (name);
847   
848   return type_id;
849 }
850
851 GtkType
852 gtk_type_register_flags (const gchar    *type_name,
853                          GtkFlagValue   *values)
854 {
855   GtkType type_id;
856   gchar *name;
857   
858   g_return_val_if_fail (type_name != NULL, 0);
859   
860   name = g_strdup (type_name);
861   
862   /* relookup pointers afterwards.
863    */
864   type_id = gtk_type_register_intern (name, GTK_TYPE_FLAGS, values);
865   
866   if (!type_id)
867     g_free (name);
868   
869   return type_id;
870 }
871
872 static guint
873 gtk_type_name_hash (const char *key)
874 {
875   guint result;
876   
877   result = 0;
878   while (*key)
879     result += (result << 3) + *key++;
880   
881   return result;
882 }
883
884 static gint
885 gtk_type_name_compare (const char *a,
886                        const char *b)
887 {
888   return (strcmp (a, b) == 0);
889 }
890
891 extern void gtk_object_init_type (void);
892
893 #include "makeenums.h"                  /* include for various places
894                                          * with enum definitions
895                                          */
896 #include "gtktypebuiltins_vars.c"       /* type variable declarations
897                                          */
898 #include "gtktypebuiltins_evals.c"      /* enum value definition arrays
899                                          */
900
901 static void
902 gtk_type_init_builtin_types (void)
903 {
904   /* GTK_TYPE_INVALID has typeid 0.  The first type id returned by
905    * gtk_type_unique is 1, which is GTK_TYPE_NONE.  And so on.
906    */
907   
908   struct {
909     GtkType type_id;
910     gchar *name;
911   } fundamental_info[] = {
912     { GTK_TYPE_NONE,            "void" },
913     { GTK_TYPE_CHAR,            "gchar" },
914     { GTK_TYPE_UCHAR,           "guchar" },
915     { GTK_TYPE_BOOL,            "gboolean" },
916     { GTK_TYPE_INT,             "gint" },
917     { GTK_TYPE_UINT,            "guint" },
918     { GTK_TYPE_LONG,            "glong" },
919     { GTK_TYPE_ULONG,           "gulong" },
920     { GTK_TYPE_FLOAT,           "gfloat" },
921     { GTK_TYPE_DOUBLE,          "gdouble" },
922     { GTK_TYPE_STRING,          "GtkString" },
923     { GTK_TYPE_ENUM,            "GtkEnum" },
924     { GTK_TYPE_FLAGS,           "GtkFlags" },
925     { GTK_TYPE_BOXED,           "GtkBoxed" },
926     { GTK_TYPE_POINTER,         "gpointer" },
927     
928     { GTK_TYPE_SIGNAL,          "GtkSignal" },
929     { GTK_TYPE_ARGS,            "GtkArgs" },
930     { GTK_TYPE_CALLBACK,        "GtkCallback" },
931     { GTK_TYPE_C_CALLBACK,      "GtkCCallback" },
932     { GTK_TYPE_FOREIGN,         "GtkForeign" },
933   };
934   struct {
935     gchar *type_name;
936     GtkType *type_id;
937     GtkType parent;
938     GtkEnumValue *values;
939   } builtin_info[GTK_TYPE_NUM_BUILTINS + 1] = {
940 #include "gtktypebuiltins_ids.c"        /* type entries */
941     { NULL }
942   };
943   guint i;
944   
945   for (i = 0; i < sizeof (fundamental_info) / sizeof (fundamental_info[0]); i++)
946     {
947       GtkType type_id;
948       
949       /* relookup pointers afterwards.
950        */
951       type_id = gtk_type_register_intern (fundamental_info[i].name, GTK_TYPE_INVALID, NULL);
952       
953       g_assert (type_id == fundamental_info[i].type_id);
954     }
955   
956   gtk_object_init_type ();
957   
958   for (i = 0; i < GTK_TYPE_NUM_BUILTINS; i++)
959     {
960       GtkType type_id;
961       
962       g_assert (builtin_info[i].type_name != NULL);
963       
964       /* relookup pointers afterwards.
965        */
966       type_id = gtk_type_register_intern (builtin_info[i].type_name,
967                                           builtin_info[i].parent,
968                                           builtin_info[i].values);
969       
970       g_assert (type_id != GTK_TYPE_INVALID);
971       
972       (*builtin_info[i].type_id) = type_id;
973     }
974 }
975
976 GtkType
977 gtk_identifier_get_type (void)
978 {
979   static GtkType identifier_type = 0;
980   
981   if (!identifier_type)
982     identifier_type = gtk_type_register_intern ("GtkIdentifier", GTK_TYPE_STRING, NULL);
983   
984   return identifier_type;
985 }