source: trunk/third/gtk/gtk/gtktypeutils.c @ 14482

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