1
/* GTK - The GIMP Toolkit
2
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
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.
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/.
28
#include "gtktypeutils.h"
31
#define TYPE_NODES_BLOCK_SIZE (35) /* needs to be > GTK_TYPE_FUNDAMENTAL_MAX */
33
typedef struct _GtkTypeNode GtkTypeNode;
38
GtkTypeInfo type_info;
40
guint chunk_alloc_locked : 1;
44
GList *children_types;
48
#define LOOKUP_TYPE_NODE(node_var, type) { \
49
GtkTypeNode *__node = NULL; \
50
GtkType sqn = GTK_TYPE_SEQNO (type); \
54
if (sqn < GTK_TYPE_FUNDAMENTAL_MAX) \
56
if (sqn < n_ftype_nodes) \
57
__node = type_nodes + sqn; \
59
else if (sqn < n_type_nodes) \
60
__node = type_nodes + sqn; \
65
static void gtk_type_class_init (GtkType node_type);
66
static void gtk_type_init_builtin_types (void);
68
static GtkTypeNode *type_nodes = NULL;
69
static guint n_type_nodes = 0;
70
static guint n_ftype_nodes = 0;
71
static GHashTable *type_name_2_type_ht = NULL;
75
gtk_type_node_next_and_invalidate (GtkType parent_type)
77
static guint n_free_type_nodes = 0;
80
/* don't keep *any* GtkTypeNode pointers across invokation of this function!!!
83
if (n_free_type_nodes == 0)
90
size = n_type_nodes + TYPE_NODES_BLOCK_SIZE;
91
size *= sizeof (GtkTypeNode);
97
type_nodes = g_realloc (type_nodes, size);
99
n_free_type_nodes = size / sizeof (GtkTypeNode) - n_type_nodes;
101
memset (type_nodes + n_type_nodes, 0, n_free_type_nodes * sizeof (GtkTypeNode));
104
n_type_nodes = GTK_TYPE_FUNDAMENTAL_MAX;
105
n_free_type_nodes -= GTK_TYPE_FUNDAMENTAL_MAX;
111
g_assert (n_ftype_nodes < GTK_TYPE_FUNDAMENTAL_MAX); /* paranoid */
113
node = type_nodes + n_ftype_nodes;
115
node->type = n_ftype_nodes;
119
node = type_nodes + n_type_nodes;
122
node->type = GTK_TYPE_MAKE (parent_type, n_type_nodes);
131
if (n_type_nodes == 0)
133
g_assert (sizeof (GtkType) >= 4);
134
g_assert (TYPE_NODES_BLOCK_SIZE > GTK_TYPE_FUNDAMENTAL_MAX);
136
type_name_2_type_ht = g_hash_table_new (g_str_hash, g_str_equal);
138
gtk_type_init_builtin_types ();
143
gtk_type_set_chunk_alloc (GtkType type,
148
LOOKUP_TYPE_NODE (node, type);
149
g_return_if_fail (node != NULL);
150
g_return_if_fail (node->chunk_alloc_locked == FALSE);
154
g_mem_chunk_destroy (node->mem_chunk);
155
node->mem_chunk = NULL;
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,
166
gtk_type_create (GtkType parent_type,
168
const GtkTypeInfo *type_info)
170
GtkTypeNode *new_node;
174
if (g_hash_table_lookup (type_name_2_type_ht, type_name))
176
g_warning ("gtk_type_create(): type `%s' already exists.", type_name);
182
GtkTypeNode *tmp_node;
184
LOOKUP_TYPE_NODE (tmp_node, parent_type);
187
g_warning ("gtk_type_create(): unknown parent type `%u'.", parent_type);
192
/* relookup pointers afterwards.
194
new_node = gtk_type_node_next_and_invalidate (parent_type);
198
g_assert (GTK_TYPE_SEQNO (new_node->type) > GTK_TYPE_FUNDAMENTAL_MAX);
199
LOOKUP_TYPE_NODE (parent, parent_type);
203
g_assert (new_node->type <= GTK_TYPE_FUNDAMENTAL_MAX);
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;
220
parent->children_types = g_list_append (parent->children_types, GUINT_TO_POINTER (new_node->type));
223
for (i = 0; i < new_node->n_supers + 1; i++)
225
new_node->supers[i] = parent->type;
226
LOOKUP_TYPE_NODE (parent, parent->parent_type);
229
g_hash_table_insert (type_name_2_type_ht, new_node->type_info.type_name, GUINT_TO_POINTER (new_node->type));
231
return new_node->type;
235
gtk_type_unique (GtkType parent_type,
236
const GtkTypeInfo *type_info)
241
g_return_val_if_fail (type_info != NULL, 0);
242
g_return_val_if_fail (type_info->type_name != NULL, 0);
244
if (!parent_type && n_ftype_nodes >= GTK_TYPE_FUNDAMENTAL_MAX)
246
g_warning ("gtk_type_unique(): maximum amount of fundamental types reached, "
247
"try increasing GTK_TYPE_FUNDAMENTAL_MAX");
251
type_name = g_strdup (type_info->type_name);
253
/* relookup pointers afterwards.
255
new_type = gtk_type_create (parent_type, type_name, type_info);
264
gtk_type_name (GtkType type)
268
LOOKUP_TYPE_NODE (node, type);
271
return node->type_info.type_name;
277
gtk_type_from_name (const gchar *name)
279
if (type_name_2_type_ht)
283
type = GPOINTER_TO_UINT (g_hash_table_lookup (type_name_2_type_ht, (gpointer) name));
292
gtk_type_parent (GtkType type)
296
LOOKUP_TYPE_NODE (node, type);
298
return node->parent_type;
304
gtk_type_parent_class (GtkType type)
308
LOOKUP_TYPE_NODE (node, type);
309
g_return_val_if_fail (node != NULL, NULL);
313
LOOKUP_TYPE_NODE (node, node->parent_type);
320
gtk_type_class_init (type);
321
LOOKUP_TYPE_NODE (node, type);
332
gtk_type_class (GtkType type)
336
LOOKUP_TYPE_NODE (node, type);
337
g_return_val_if_fail (node != NULL, NULL);
342
gtk_type_class_init (type);
343
LOOKUP_TYPE_NODE (node, type);
350
gtk_type_new (GtkType type)
353
GtkTypeObject *tobject;
356
LOOKUP_TYPE_NODE (node, type);
357
g_return_val_if_fail (node != NULL, NULL);
362
klass = gtk_type_class (type);
363
LOOKUP_TYPE_NODE (node, type);
365
node->chunk_alloc_locked = TRUE;
368
tobject = g_mem_chunk_alloc0 (node->mem_chunk);
370
tobject = g_malloc0 (node->type_info.object_size);
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.
384
supers = node->supers;
385
for (i = node->n_supers; i > 0; i--)
387
LOOKUP_TYPE_NODE (pnode, supers[i]);
388
if (pnode->type_info.object_init_func)
390
tobject->klass = pnode->klass;
391
pnode->type_info.object_init_func (tobject, klass);
394
LOOKUP_TYPE_NODE (node, type);
396
tobject->klass = klass;
397
if (node->type_info.object_init_func)
399
node->type_info.object_init_func (tobject, klass);
400
tobject->klass = klass;
407
gtk_type_free (GtkType type,
412
g_return_if_fail (mem != NULL);
413
LOOKUP_TYPE_NODE (node, type);
414
g_return_if_fail (node != NULL);
417
g_mem_chunk_free (node->mem_chunk, mem);
423
gtk_type_children_types (GtkType type)
427
LOOKUP_TYPE_NODE (node, type);
429
return node->children_types;
435
gtk_type_describe_heritage (GtkType type)
440
LOOKUP_TYPE_NODE (node, type);
444
if (node->type_info.type_name)
447
node->type_info.type_name);
449
g_message ("%s<unnamed type>",
453
LOOKUP_TYPE_NODE (node, node->parent_type);
458
gtk_type_describe_tree (GtkType type,
463
LOOKUP_TYPE_NODE (node, type);
467
static gint indent = 0;
473
gstring = g_string_new ("");
475
for (i = 0; i < indent; i++)
476
g_string_append_c (gstring, ' ');
478
if (node->type_info.type_name)
479
g_string_append (gstring, node->type_info.type_name);
481
g_string_append (gstring, "<unnamed type>");
484
g_string_sprintfa (gstring, " (%d bytes)", node->type_info.object_size);
486
g_message ("%s", gstring->str);
487
g_string_free (gstring, TRUE);
492
for (list = node->children_types; list; list = list->next)
493
gtk_type_describe_tree (GPOINTER_TO_UINT (list->data), show_size);
500
gtk_type_is_a (GtkType type,
503
if (type == is_a_type)
509
LOOKUP_TYPE_NODE (node, type);
514
LOOKUP_TYPE_NODE (a_node, is_a_type);
517
if (a_node->n_supers <= node->n_supers)
518
return node->supers[node->n_supers - a_node->n_supers] == is_a_type;
527
gtk_type_class_init (GtkType type)
531
/* we need to relookup nodes everytime we called an external function */
532
LOOKUP_TYPE_NODE (node, type);
534
if (!node->klass && node->type_info.class_size)
536
GtkTypeClass *type_class;
537
GtkTypeNode *base_node;
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);
544
node->klass = g_malloc0 (node->type_info.class_size);
546
if (node->parent_type)
550
LOOKUP_TYPE_NODE (parent, node->parent_type);
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);
559
gtk_type_class_init (parent->type);
560
LOOKUP_TYPE_NODE (node, type);
561
LOOKUP_TYPE_NODE (parent, node->parent_type);
565
memcpy (node->klass, parent->klass, parent->type_info.class_size);
568
type_class = node->klass;
569
type_class->type = node->type;
571
/* stack all base class initialization functions, so we
572
* call them in ascending order.
578
if (base_node->type_info.base_class_init_func)
579
slist = g_slist_prepend (slist, (gpointer) base_node->type_info.base_class_init_func);
580
LOOKUP_TYPE_NODE (base_node, base_node->parent_type);
586
for (walk = slist; walk; walk = walk->next)
588
GtkClassInitFunc base_class_init;
590
base_class_init = (GtkClassInitFunc) walk->data;
591
base_class_init (node->klass);
592
LOOKUP_TYPE_NODE (node, type);
594
g_slist_free (slist);
597
if (node->type_info.class_init_func)
598
node->type_info.class_init_func (node->klass);
603
gtk_type_descriptive_name (GtkType type)
607
name = gtk_type_name (type);
615
gtk_type_check_object_cast (GtkTypeObject *type_object,
620
g_warning ("invalid cast from (NULL) pointer to `%s'",
621
gtk_type_descriptive_name (cast_type));
624
if (!type_object->klass)
626
g_warning ("invalid unclassed pointer in cast to `%s'",
627
gtk_type_descriptive_name (cast_type));
630
/* currently, GTK_TYPE_OBJECT is the lowest fundamental type
631
* dominator for types that introduce classes.
633
if (type_object->klass->type < GTK_TYPE_OBJECT)
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));
640
if (!gtk_type_is_a (type_object->klass->type, cast_type))
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));
652
gtk_type_check_class_cast (GtkTypeClass *klass,
657
g_warning ("invalid class cast from (NULL) pointer to `%s'",
658
gtk_type_descriptive_name (cast_type));
661
/* currently, GTK_TYPE_OBJECT is the lowest fundamental type
662
* dominator for types that introduce classes.
664
if (klass->type < GTK_TYPE_OBJECT)
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));
671
if (!gtk_type_is_a (klass->type, cast_type))
673
g_warning ("invalid class cast from `%s' to `%s'",
674
gtk_type_descriptive_name (klass->type),
675
gtk_type_descriptive_name (cast_type));
683
gtk_type_enum_get_values (GtkType enum_type)
685
if (GTK_FUNDAMENTAL_TYPE (enum_type) == GTK_TYPE_ENUM ||
686
GTK_FUNDAMENTAL_TYPE (enum_type) == GTK_TYPE_FLAGS)
690
LOOKUP_TYPE_NODE (node, enum_type);
692
return (GtkEnumValue*) node->type_info.reserved_1;
695
g_warning ("gtk_type_enum_get_values(): type `%s' is not derived from `GtkEnum' or `GtkFlags'",
696
gtk_type_name (enum_type));
702
gtk_type_flags_get_values (GtkType flags_type)
704
return gtk_type_enum_get_values (flags_type);
708
gtk_type_enum_find_value (GtkType enum_type,
709
const gchar *value_name)
711
g_return_val_if_fail (value_name != NULL, NULL);
713
if (GTK_FUNDAMENTAL_TYPE (enum_type) == GTK_TYPE_ENUM ||
714
GTK_FUNDAMENTAL_TYPE (enum_type) == GTK_TYPE_FLAGS)
718
vals = gtk_type_enum_get_values (enum_type);
720
while (vals->value_name)
722
if (strcmp (vals->value_name, value_name) == 0 ||
723
strcmp (vals->value_nick, value_name) == 0)
729
g_warning ("gtk_type_enum_find_value(): type `%s' is not derived from `GtkEnum' or `GtkFlags'",
730
gtk_type_name (enum_type));
736
gtk_type_flags_find_value (GtkType flag_type,
737
const gchar *value_name)
739
g_return_val_if_fail (value_name != NULL, NULL);
741
return gtk_type_enum_find_value (flag_type, value_name);
744
typedef struct _GtkTypeVarargType GtkTypeVarargType;
745
struct _GtkTypeVarargType
747
GtkType foreign_type;
748
GtkType varargs_type;
751
static GtkTypeVarargType *vararg_types = NULL;
752
static guint n_vararg_types = 0;
755
gtk_type_set_varargs_type (GtkType foreign_type,
756
GtkType varargs_type)
758
g_return_if_fail (foreign_type == GTK_FUNDAMENTAL_TYPE (foreign_type));
759
g_return_if_fail (foreign_type > GTK_TYPE_FUNDAMENTAL_LAST);
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))
767
g_warning ("invalid varargs type `%s' for fundamental type `%s'",
768
gtk_type_name (varargs_type),
769
gtk_type_name (foreign_type));
772
if (gtk_type_get_varargs_type (foreign_type))
774
g_warning ("varargs type is already registered for fundamental type `%s'",
775
gtk_type_name (foreign_type));
780
vararg_types = g_realloc (vararg_types, sizeof (GtkTypeVarargType) * n_vararg_types);
782
vararg_types[n_vararg_types - 1].foreign_type = foreign_type;
783
vararg_types[n_vararg_types - 1].varargs_type = varargs_type;
787
gtk_type_get_varargs_type (GtkType foreign_type)
792
type = GTK_FUNDAMENTAL_TYPE (foreign_type);
793
if (type <= GTK_TYPE_FUNDAMENTAL_LAST)
796
for (i = 0; i < n_vararg_types; i++)
797
if (vararg_types[i].foreign_type == type)
798
return vararg_types[i].varargs_type;
803
static inline GtkType
804
gtk_type_register_intern (gchar *name,
806
const GtkEnumValue *values)
811
info.type_name = name;
812
info.object_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;
819
/* relookup pointers afterwards.
821
type_id = gtk_type_create (parent, name, &info);
823
if (type_id && values)
827
/* check for proper type consistency and NULL termination
830
g_assert (GTK_FUNDAMENTAL_TYPE (type_id) == GTK_TYPE_ENUM ||
831
GTK_FUNDAMENTAL_TYPE (type_id) == GTK_TYPE_FLAGS);
834
while (values[i].value_name)
837
g_assert (values[i].value_name == NULL && values[i].value_nick == NULL);
844
gtk_type_register_enum (const gchar *type_name,
845
GtkEnumValue *values)
850
g_return_val_if_fail (type_name != NULL, 0);
852
name = g_strdup (type_name);
854
/* relookup pointers afterwards.
856
type_id = gtk_type_register_intern (name, GTK_TYPE_ENUM, values);
865
gtk_type_register_flags (const gchar *type_name,
866
GtkFlagValue *values)
871
g_return_val_if_fail (type_name != NULL, 0);
873
name = g_strdup (type_name);
875
/* relookup pointers afterwards.
877
type_id = gtk_type_register_intern (name, GTK_TYPE_FLAGS, values);
886
gtk_type_query (GtkType type)
890
LOOKUP_TYPE_NODE (node, type);
895
query = g_new0 (GtkTypeQuery, 1);
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;
907
extern void gtk_object_init_type (void);
909
#include "makeenums.h" /* include for various places
910
* with enum definitions
912
#include "gtktypebuiltins_vars.c" /* type variable declarations
914
#include "gtktypebuiltins_evals.c" /* enum value definition arrays
918
gtk_type_init_builtin_types (void)
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.
924
static const struct {
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" },
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" },
954
const GtkEnumValue *values;
955
} builtin_info[GTK_TYPE_NUM_BUILTINS + 1] = {
956
#include "gtktypebuiltins_ids.c" /* type entries */
961
for (i = 0; i < sizeof (fundamental_info) / sizeof (fundamental_info[0]); i++)
965
/* relookup pointers afterwards.
967
type_id = gtk_type_register_intern (fundamental_info[i].name, 0, NULL);
969
g_assert (type_id == fundamental_info[i].type_id);
972
gtk_object_init_type ();
974
for (i = 0; i < GTK_TYPE_NUM_BUILTINS; i++)
978
g_assert (builtin_info[i].type_name != NULL);
980
/* relookup pointers afterwards.
982
type_id = gtk_type_register_intern (builtin_info[i].type_name,
983
builtin_info[i].parent,
984
builtin_info[i].values);
986
g_assert (GTK_TYPE_SEQNO (type_id) > GTK_TYPE_FUNDAMENTAL_MAX);
988
(*builtin_info[i].type_id) = type_id;
993
gtk_identifier_get_type (void)
995
static GtkType identifier_type = 0;
997
if (!identifier_type)
998
identifier_type = gtk_type_register_intern ("GtkIdentifier", GTK_TYPE_STRING, NULL);
1000
return identifier_type;