~ubuntu-branches/ubuntu/trusty/gtk+1.2/trusty

« back to all changes in this revision

Viewing changes to gtk/gtktypeutils.c

  • Committer: Bazaar Package Importer
  • Author(s): Akira TAGOH
  • Date: 2002-04-15 02:19:49 UTC
  • Revision ID: james.westby@ubuntu.com-20020415021949-eh01yrgh4b85p9z7
Tags: upstream-1.2.10
ImportĀ upstreamĀ versionĀ 1.2.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
33
typedef struct _GtkTypeNode GtkTypeNode;
 
34
 
 
35
struct _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
 
 
65
static void  gtk_type_class_init                (GtkType      node_type);
 
66
static void  gtk_type_init_builtin_types        (void);
 
67
 
 
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;
 
72
 
 
73
 
 
74
static GtkTypeNode*
 
75
gtk_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
 
 
128
void
 
129
gtk_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
 
 
142
void
 
143
gtk_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
 
 
165
static GtkType
 
166
gtk_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
 
 
234
GtkType
 
235
gtk_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
 
 
263
gchar*
 
264
gtk_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
 
 
276
GtkType
 
277
gtk_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
 
 
291
GtkType
 
292
gtk_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
 
 
303
gpointer
 
304
gtk_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
 
 
331
gpointer
 
332
gtk_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
 
 
349
gpointer
 
350
gtk_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
 
 
406
void
 
407
gtk_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
 
 
422
GList*
 
423
gtk_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
 
 
434
void
 
435
gtk_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
 
 
457
void
 
458
gtk_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
 
 
499
gboolean
 
500
gtk_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
 
 
526
static void
 
527
gtk_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, (gpointer) 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 = (GtkClassInitFunc) 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
 
 
602
static inline gchar*
 
603
gtk_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
 
 
614
GtkTypeObject*
 
615
gtk_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
 
 
651
GtkTypeClass*
 
652
gtk_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
 
 
682
GtkEnumValue*
 
683
gtk_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
 
 
701
GtkFlagValue*
 
702
gtk_type_flags_get_values (GtkType        flags_type)
 
703
{
 
704
  return gtk_type_enum_get_values (flags_type);
 
705
}
 
706
 
 
707
GtkEnumValue*
 
708
gtk_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
 
 
735
GtkFlagValue*
 
736
gtk_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
 
 
744
typedef struct _GtkTypeVarargType GtkTypeVarargType;
 
745
struct _GtkTypeVarargType
 
746
{
 
747
  GtkType foreign_type;
 
748
  GtkType varargs_type;
 
749
};
 
750
 
 
751
static GtkTypeVarargType *vararg_types = NULL;
 
752
static guint              n_vararg_types = 0;
 
753
 
 
754
void
 
755
gtk_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
 
 
786
GtkType
 
787
gtk_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
 
 
803
static inline GtkType
 
804
gtk_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
 
 
843
GtkType
 
844
gtk_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
 
 
864
GtkType
 
865
gtk_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
 
 
885
GtkTypeQuery*
 
886
gtk_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
 
 
907
extern 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
 
 
917
static void
 
918
gtk_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
 
 
992
GtkType
 
993
gtk_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
}