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