Current release notes.
[gtk-doc.git] / gtkdoc-scangobj.in
blobb37a0119b867f894688caa5529e297611d70301e
1 #!@PERL@ -w
2 # -*- cperl -*-
4 # gtk-doc - GTK DocBook documentation generator.
5 # Copyright (C) 1998  Damon Chaplin
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 # This gets information about object heirarchies and signals
24 # by compiling a small C program. CFLAGS and LDFLAGS must be
25 # set appropriately before running this script.
27 # NOTE: the lookup_signal_arg_names() function contains the argument names of
28 #       standard GTK signal handlers. This may need to be updated for new
29 #       GTK signals or Gnome widget signals.
31 use Getopt::Long;
33 unshift @INC, '@PACKAGE_DATA_DIR@';
34 require "gtkdoc-common.pl";
36 # Options
38 # name of documentation module
39 my $MODULE;
40 my $OUTPUT_DIR;
41 my $PRINT_VERSION;
42 my $PRINT_HELP;
43 my $TYPE_INIT_FUNC="g_type_init(); g_type_class_ref(G_TYPE_OBJECT)";
44 my $QUERY_CHILD_PROPERTIES;
46 # --nogtkinit is deprecated, as it is the default now anyway.
47 %optctl = (module => \$MODULE,
48            types => \$TYPES_FILE,
49            nogtkinit => \$NO_GTK_INIT,
50            'type-init-func' => \$TYPE_INIT_FUNC,
51            'query-child-properties' => \$QUERY_CHILD_PROPERTIES,
52            'output-dir' => \$OUTPUT_DIR,
53            'version' => \$PRINT_VERSION,
54            'help' => \$PRINT_HELP);
55            
56 GetOptions(\%optctl, "module=s", "types:s", "output-dir:s", "nogtkinit", "type-init-func:s", "query-child-properties:s", "version", "help");
58 if ($NO_GTK_INIT) {
59   # Do nothing. This just avoids a warning.
62 if ($PRINT_VERSION) {
63     print "@VERSION@\n";
64     exit 0;
67 if (!$MODULE) {
68     $PRINT_HELP = 1;
71 if ($PRINT_HELP) {
72     print "gtkdoc-scangobj version @VERSION@\n";
73     print "\n--module=MODULE_NAME  Name of the doc module being parsed";
74     print "\n--types=FILE          The name of the file to store the types in";
75     print "\n--type-init-func=FUNC The init function to call instead of g_type_init ()";
76     print "\n--query-child-properties=FUNC A function that returns a list of child";
77     print "\n                      properties for a class";
78     print "\n--output-dir=DIRNAME  The directory where the results are stored";
79     print "\n--version             Print the version of this program";
80     print "\n--help                Print this help\n";
81     exit 0;
84 $OUTPUT_DIR = $OUTPUT_DIR ? $OUTPUT_DIR : ".";
86 $TYPES_FILE = $TYPES_FILE ? $TYPES_FILE : "$OUTPUT_DIR/$MODULE.types";
88 open (TYPES, $TYPES_FILE) || die "Cannot open $TYPES_FILE: $!\n";
89 open (OUTPUT, ">$MODULE-scan.c") || die "Cannot open $MODULE-scan.c: $!\n";
91 my $old_signals_filename = "$OUTPUT_DIR/$MODULE.signals";
92 my $new_signals_filename = "$OUTPUT_DIR/$MODULE.signals.new";
93 my $old_hierarchy_filename = "$OUTPUT_DIR/$MODULE.hierarchy";
94 my $new_hierarchy_filename = "$OUTPUT_DIR/$MODULE.hierarchy.new";
95 my $old_interfaces_filename = "$OUTPUT_DIR/$MODULE.interfaces";
96 my $new_interfaces_filename = "$OUTPUT_DIR/$MODULE.interfaces.new";
97 my $old_prerequisites_filename = "$OUTPUT_DIR/$MODULE.prerequisites";
98 my $new_prerequisites_filename = "$OUTPUT_DIR/$MODULE.prerequisites.new";
99 my $old_args_filename = "$OUTPUT_DIR/$MODULE.args";
100 my $new_args_filename = "$OUTPUT_DIR/$MODULE.args.new";
102 # write a C program to scan the types
104 $includes = "";
105 @types = ();
107 for (<TYPES>) {
108     if (/^#include/) {
109         $includes .= $_;
110     } elsif (/^gnome_keyring_item_info_get_type$/) {
111         # HACK: This isn't really a GObject type so skip it.
112         next;
113     } elsif (/^%/) {
114         next;
115     } elsif (/^\s*$/) {
116         next;
117     } else {
118         chomp;
119         push @types, $_;
120     }
123 $ntypes = @types + 1;
125 print OUTPUT <<EOT;
126 #include <string.h>
127 #include <stdlib.h>
128 #include <stdio.h>
129 #include <errno.h>
130 #include <glib-object.h>
134 if ($includes) {
135     print OUTPUT $includes;
136 } else {
137     for (@types) {
138         print OUTPUT "extern GType $_ (void);\n";
139     }
142 if ($QUERY_CHILD_PROPERTIES) {
143   print OUTPUT <<EOT;
144 extern GParamSpec** $QUERY_CHILD_PROPERTIES (gpointer class, guint *n_properties);
148 print OUTPUT <<EOT;
150 #ifdef GTK_IS_WIDGET_CLASS
151 #include <gtk/gtkversion.h>
152 #endif
153 GType object_types[$ntypes];
155 static GType *
156 get_object_types (void)
158     gint i = 0;
161 for (@types) {
162     print OUTPUT "    object_types[i++] = $_ ();\n";
165 print OUTPUT <<EOT;
166     object_types[i] = 0;
168     /* Need to make sure all the types are loaded in and initialize
169      * their signals and properties.
170      */
171     for (i=0; object_types[i]; i++)
172       {
173         if (G_TYPE_IS_CLASSED (object_types[i]))
174           g_type_class_ref (object_types[i]);
175         if (G_TYPE_IS_INTERFACE (object_types[i]))
176           g_type_default_interface_ref (object_types[i]);
177       }
179     return object_types;
183  * This uses GObject type functions to output signal prototypes and the object
184  * hierarchy.
185  */
187 /* The output files */
188 const gchar *signals_filename = "$new_signals_filename";
189 const gchar *hierarchy_filename = "$new_hierarchy_filename";
190 const gchar *interfaces_filename = "$new_interfaces_filename";
191 const gchar *prerequisites_filename = "$new_prerequisites_filename";
192 const gchar *args_filename = "$new_args_filename";
195 static void output_signals (void);
196 static void output_object_signals (FILE *fp,
197                                    GType object_type);
198 static void output_object_signal (FILE *fp,
199                                   const gchar *object_class_name,
200                                   guint signal_id);
201 static const gchar * get_type_name (GType type,
202                                     gboolean * is_pointer);
203 static const gchar * get_gdk_event (const gchar * signal_name);
204 static const gchar ** lookup_signal_arg_names (const gchar * type,
205                                                const gchar * signal_name);
207 static void output_object_hierarchy (void);
208 static void output_hierarchy (FILE *fp,
209                               GType type,
210                               guint level);
212 static void output_object_interfaces (void);
213 static void output_interfaces (FILE *fp,
214                                GType type);
216 static void output_interface_prerequisites (void);
217 static void output_prerequisites (FILE *fp,
218                                   GType type);
220 static void output_args (void);
221 static void output_object_args (FILE *fp, GType object_type);
224 main (int argc, char *argv[])
226   /* Silence the compiler: */
227   if (argv != argv) argc = argc;
229   $TYPE_INIT_FUNC;
231   get_object_types ();
233   output_signals ();
234   output_object_hierarchy ();
235   output_object_interfaces ();
236   output_interface_prerequisites ();
237   output_args ();
239   return 0;
243 static void
244 output_signals (void)
246   FILE *fp;
247   gint i;
249   fp = fopen (signals_filename, "w");
250   if (fp == NULL)
251     {
252       g_warning ("Couldn't open output file: %s : %s", signals_filename, strerror(errno));
253       return;
254     }
256   for (i = 0; object_types[i]; i++)
257     output_object_signals (fp, object_types[i]);
259   fclose (fp);
262 static gint
263 compare_signals (const void *a, const void *b)
265   const guint *signal_a = a;
266   const guint *signal_b = b;
268   return strcmp (g_signal_name (*signal_a), g_signal_name (*signal_b));
271 /* This outputs all the signals of one object. */
272 static void
273 output_object_signals (FILE *fp, GType object_type)
275   const gchar *object_class_name;
276   guint *signals, n_signals;
277   guint sig;
279   if (G_TYPE_IS_INSTANTIATABLE (object_type) ||
280       G_TYPE_IS_INTERFACE (object_type))
281     {
283       object_class_name = g_type_name (object_type);
285       signals = g_signal_list_ids (object_type, &n_signals);
286       qsort (signals, n_signals, sizeof (guint), compare_signals);
288       for (sig = 0; sig < n_signals; sig++)
289         {
290            output_object_signal (fp, object_class_name, signals[sig]);
291         }
292       g_free (signals);
293    }
297 /* This outputs one signal. */
298 static void
299 output_object_signal (FILE *fp,
300                       const gchar *object_name,
301                       guint signal_id)
303   GSignalQuery query_info;
304   const gchar *type_name, *ret_type, *object_arg, *arg_name;
305   gchar *pos, *object_arg_lower;
306   gboolean is_pointer;
307   gchar ret_type_buffer[1024], buffer[1024];
308   guint i, param;
309   const gchar **arg_names;
310   gint param_num, widget_num, event_num, callback_num;
311   gint *arg_num;
312   gchar signal_name[128];
313   gchar flags[16];
315   /*  g_print ("Object: %s Signal: %u\\n", object_name, signal_id);*/
317   param_num = 1;
318   widget_num = event_num = callback_num = 0;
320   g_signal_query (signal_id, &query_info);
322   /* Output the return type and function name. */
323   ret_type = get_type_name (query_info.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE, &is_pointer);
324   sprintf (ret_type_buffer, "%s%s", ret_type, is_pointer ? "*" : "");
326   /* Output the signal object type and the argument name. We assume the
327      type is a pointer - I think that is OK. We remove "Gtk" or "Gnome" and
328      convert to lower case for the argument name. */
329   pos = buffer;
330   sprintf (pos, "%s ", object_name);
331   pos += strlen (pos);
333   if (!strncmp (object_name, "Gtk", 3))
334       object_arg = object_name + 3;
335   else if (!strncmp (object_name, "Gnome", 5))
336       object_arg = object_name + 5;
337   else
338       object_arg = object_name;
340   object_arg_lower = g_ascii_strdown (object_arg, -1);
341   sprintf (pos, "*%s\\n", object_arg_lower);
342   pos += strlen (pos);
343   if (!strncmp (object_arg_lower, "widget", 6))
344     widget_num = 2;
345   g_free(object_arg_lower);
347   /* Convert signal name to use underscores rather than dashes '-'. */
348   strcpy (signal_name, query_info.signal_name);
349   for (i = 0; signal_name[i]; i++)
350     {
351       if (signal_name[i] == '-')
352         signal_name[i] = '_';
353     }
355   /* Output the signal parameters. */
356   arg_names = lookup_signal_arg_names (object_name, signal_name);
358   for (param = 0; param < query_info.n_params; param++)
359     {
360       if (arg_names)
361         {
362           sprintf (pos, "%s\\n", arg_names[param]);
363           pos += strlen (pos);
364         }
365       else
366         {
367           type_name = get_type_name (query_info.param_types[param] & ~G_SIGNAL_TYPE_STATIC_SCOPE, &is_pointer);
369           /* Most arguments to the callback are called "arg1", "arg2", etc.
370              GdkWidgets are called "widget", "widget2", ...
371              GdkEvents are called "event", "event2", ...
372              GtkCallbacks are called "callback", "callback2", ... */
373           if (!strcmp (type_name, "GtkWidget"))
374             {
375               arg_name = "widget";
376               arg_num = &widget_num;
377             }
378           else if (!strcmp (type_name, "GdkEvent"))
379             {
380               type_name = get_gdk_event (signal_name);
381               arg_name = "event";
382               arg_num = &event_num;
383               is_pointer = TRUE;
384             }
385           else if (!strcmp (type_name, "GtkCallback")
386                    || !strcmp (type_name, "GtkCCallback"))
387             {
388               arg_name = "callback";
389               arg_num = &callback_num;
390             }
391           else
392             {
393               arg_name = "arg";
394               arg_num = &param_num;
395             }
396           sprintf (pos, "%s ", type_name);
397           pos += strlen (pos);
399           if (!arg_num || *arg_num == 0)
400             sprintf (pos, "%s%s\\n", is_pointer ? "*" : " ", arg_name);
401           else
402             sprintf (pos, "%s%s%i\\n", is_pointer ? "*" : " ", arg_name,
403                      *arg_num);
404           pos += strlen (pos);
406           if (arg_num)
407             {
408               if (*arg_num == 0)
409                 *arg_num = 2;
410               else
411                 *arg_num += 1;
412             }
413         }
414     }
416   pos = flags;
417   /* We use one-character flags for simplicity. */
418   if (query_info.signal_flags & G_SIGNAL_RUN_FIRST)
419     *pos++ = 'f';
420   if (query_info.signal_flags & G_SIGNAL_RUN_LAST)
421     *pos++ = 'l';
422   if (query_info.signal_flags & G_SIGNAL_RUN_CLEANUP)
423     *pos++ = 'c';
424   if (query_info.signal_flags & G_SIGNAL_NO_RECURSE)
425     *pos++ = 'r';
426   if (query_info.signal_flags & G_SIGNAL_DETAILED)
427     *pos++ = 'd';
428   if (query_info.signal_flags & G_SIGNAL_ACTION)
429     *pos++ = 'a';
430   if (query_info.signal_flags & G_SIGNAL_NO_HOOKS)
431     *pos++ = 'h';
432   *pos = 0;
434   fprintf (fp,
435            "<SIGNAL>\\n<NAME>%s::%s</NAME>\\n<RETURNS>%s</RETURNS>\\n<FLAGS>%s</FLAGS>\\n%s</SIGNAL>\\n\\n",
436            object_name, query_info.signal_name, ret_type_buffer, flags, buffer);
440 /* Returns the type name to use for a signal argument or return value, given
441    the GtkType from the signal info. It also sets is_pointer to TRUE if the
442    argument needs a '*' since it is a pointer. */
443 static const gchar *
444 get_type_name (GType type, gboolean * is_pointer)
446   const gchar *type_name;
448   *is_pointer = FALSE;
449   type_name = g_type_name (type);
451   switch (type) {
452   case G_TYPE_NONE:
453   case G_TYPE_CHAR:
454   case G_TYPE_UCHAR:
455   case G_TYPE_BOOLEAN:
456   case G_TYPE_INT:
457   case G_TYPE_UINT:
458   case G_TYPE_LONG:
459   case G_TYPE_ULONG:
460   case G_TYPE_FLOAT:
461   case G_TYPE_DOUBLE:
462   case G_TYPE_POINTER:
463     /* These all have normal C type names so they are OK. */
464     return type_name;
466   case G_TYPE_STRING:
467     /* A GtkString is really a gchar*. */
468     *is_pointer = TRUE;
469     return "gchar";
471   case G_TYPE_ENUM:
472   case G_TYPE_FLAGS:
473     /* We use a gint for both of these. Hopefully a subtype with a decent
474        name will be registered and used instead, as GTK+ does itself. */
475     return "gint";
477   case G_TYPE_BOXED:
478     /* The boxed type shouldn't be used itself, only subtypes. Though we
479        return 'gpointer' just in case. */
480     return "gpointer";
482   case G_TYPE_PARAM:
483     /* A GParam is really a GParamSpec*. */
484     *is_pointer = TRUE;
485     return "GParamSpec";
487   default:
488     break;
489   }
491   /* For all GObject subclasses we can use the class name with a "*",
492      e.g. 'GtkWidget *'. */
493   if (g_type_is_a (type, G_TYPE_OBJECT))
494     *is_pointer = TRUE;
495   
496   /* Also catch non GObject root types */
497   if (G_TYPE_IS_CLASSED (type))
498     *is_pointer = TRUE;
499   
500   /* All boxed subtypes will be pointers as well. */
501   if (g_type_is_a (type, G_TYPE_BOXED))
502     *is_pointer = TRUE;
504   /* All pointer subtypes will be pointers as well. */
505   if (g_type_is_a (type, G_TYPE_POINTER))
506     *is_pointer = TRUE;
508   /* But enums are not */
509   if (g_type_is_a (type, G_TYPE_ENUM) ||
510       g_type_is_a (type, G_TYPE_FLAGS))
511     *is_pointer = FALSE;
513   return type_name;
517 static const gchar *
518 get_gdk_event (const gchar * signal_name)
520   static const gchar *GbGDKEvents[] =
521   {
522     "button_press_event", "GdkEventButton",
523     "button_release_event", "GdkEventButton",
524     "motion_notify_event", "GdkEventMotion",
525     "delete_event", "GdkEvent",
526     "destroy_event", "GdkEvent",
527     "expose_event", "GdkEventExpose",
528     "key_press_event", "GdkEventKey",
529     "key_release_event", "GdkEventKey",
530     "enter_notify_event", "GdkEventCrossing",
531     "leave_notify_event", "GdkEventCrossing",
532     "configure_event", "GdkEventConfigure",
533     "focus_in_event", "GdkEventFocus",
534     "focus_out_event", "GdkEventFocus",
535     "map_event", "GdkEvent",
536     "unmap_event", "GdkEvent",
537     "property_notify_event", "GdkEventProperty",
538     "selection_clear_event", "GdkEventSelection",
539     "selection_request_event", "GdkEventSelection",
540     "selection_notify_event", "GdkEventSelection",
541     "proximity_in_event", "GdkEventProximity",
542     "proximity_out_event", "GdkEventProximity",
543     "drag_begin_event", "GdkEventDragBegin",
544     "drag_request_event", "GdkEventDragRequest",
545     "drag_end_event", "GdkEventDragRequest",
546     "drop_enter_event", "GdkEventDropEnter",
547     "drop_leave_event", "GdkEventDropLeave",
548     "drop_data_available_event", "GdkEventDropDataAvailable",
549     "other_event", "GdkEventOther",
550     "client_event", "GdkEventClient",
551     "no_expose_event", "GdkEventNoExpose",
552     "visibility_notify_event", "GdkEventVisibility",
553     "window_state_event", "GdkEventWindowState",
554     "scroll_event", "GdkEventScroll",
555     NULL
556   };
558   gint i;
560   for (i = 0; GbGDKEvents[i]; i += 2)
561     {
562       if (!strcmp (signal_name, GbGDKEvents[i]))
563         return GbGDKEvents[i + 1];
564     }
565   return "GdkEvent";
569 /* This returns argument names to use for some known GTK signals.
570     It is passed a widget name, e.g. 'GtkCList' and a signal name, e.g.
571     'select_row' and it returns a pointer to an array of argument types and
572     names. */
573 static const gchar **
574 lookup_signal_arg_names (const gchar * type, const gchar * signal_name)
576   /* Each arg array starts with the object type name and the signal name,
577      and then signal arguments follow. */
578   static const gchar *GbArgTable[][16] =
579   {
580     {"GtkCList", "select_row",
581      "gint             row",
582      "gint             column",
583      "GdkEventButton  *event"},
584     {"GtkCList", "unselect_row",
585      "gint             row",
586      "gint             column",
587      "GdkEventButton  *event"},
588     {"GtkCList", "click_column",
589      "gint             column"},
591     {"GtkCList", "resize_column",
592      "gint             column",
593      "gint             width"},
595     {"GtkCList", "extend_selection",
596      "GtkScrollType    scroll_type",
597      "gfloat           position",
598      "gboolean         auto_start_selection"},
599     {"GtkCList", "scroll_vertical",
600      "GtkScrollType    scroll_type",
601      "gfloat           position"},
602     {"GtkCList", "scroll_horizontal",
603      "GtkScrollType    scroll_type",
604      "gfloat           position"},
606     {"GtkCTree", "tree_select_row",
607      "GtkCTreeNode    *node",
608      "gint             column"},
609     {"GtkCTree", "tree_unselect_row",
610      "GtkCTreeNode    *node",
611      "gint             column"},
612     {"GtkCTree", "tree_expand",
613      "GtkCTreeNode    *node"},
614     {"GtkCTree", "tree_collapse",
615      "GtkCTreeNode    *node"},
616     {"GtkCTree", "tree_move",
617      "GtkCTreeNode    *node",
618      "GtkCTreeNode    *new_parent",
619      "GtkCTreeNode    *new_sibling"},
620     {"GtkCTree", "change_focus_row_expansion",
621      "GtkCTreeExpansionType expansion"},
623     {"GtkEditable", "insert_text",
624      "gchar           *new_text",
625      "gint             new_text_length",
626      "gint            *position"},
627     {"GtkEditable", "delete_text",
628      "gint             start_pos",
629      "gint             end_pos"},
630     {"GtkEditable", "set_editable",
631      "gboolean         is_editable"},
632     {"GtkEditable", "move_cursor",
633      "gint             x",
634      "gint             y"},
635     {"GtkEditable", "move_word",
636      "gint             num_words"},
637     {"GtkEditable", "move_page",
638      "gint             x",
639      "gint             y"},
640     {"GtkEditable", "move_to_row",
641      "gint             row"},
642     {"GtkEditable", "move_to_column",
643      "gint             column"},
645     {"GtkEditable", "kill_char",
646      "gint             direction"},
647     {"GtkEditable", "kill_word",
648      "gint             direction"},
649     {"GtkEditable", "kill_line",
650      "gint             direction"},
653     {"GtkInputDialog", "enable_device",
654      "GdkDevice       *deviceid"},
655     {"GtkInputDialog", "disable_device",
656      "GdkDevice       *deviceid"},
658     {"GtkListItem", "extend_selection",
659      "GtkScrollType    scroll_type",
660      "gfloat           position",
661      "gboolean         auto_start_selection"},
662     {"GtkListItem", "scroll_vertical",
663      "GtkScrollType    scroll_type",
664      "gfloat           position"},
665     {"GtkListItem", "scroll_horizontal",
666      "GtkScrollType    scroll_type",
667      "gfloat           position"},
669     {"GtkMenuShell", "move_current",
670      "GtkMenuDirectionType direction"},
671     {"GtkMenuShell", "activate_current",
672      "gboolean         force_hide"},
675     {"GtkNotebook", "switch_page",
676      "GtkNotebookPage *page",
677      "guint            page_num"},
678     {"GtkStatusbar", "text_pushed",
679      "guint            context_id",
680      "gchar           *text"},
681     {"GtkStatusbar", "text_popped",
682      "guint            context_id",
683      "gchar           *text"},
684     {"GtkTipsQuery", "widget_entered",
685      "GtkWidget       *widget",
686      "gchar           *tip_text",
687      "gchar           *tip_private"},
688     {"GtkTipsQuery", "widget_selected",
689      "GtkWidget       *widget",
690      "gchar           *tip_text",
691      "gchar           *tip_private",
692      "GdkEventButton  *event"},
693     {"GtkToolbar", "orientation_changed",
694      "GtkOrientation   orientation"},
695     {"GtkToolbar", "style_changed",
696      "GtkToolbarStyle  style"},
697     {"GtkWidget", "draw",
698      "GdkRectangle    *area"},
699     {"GtkWidget", "size_request",
700      "GtkRequisition  *requisition"},
701     {"GtkWidget", "size_allocate",
702      "GtkAllocation   *allocation"},
703     {"GtkWidget", "state_changed",
704      "GtkStateType     state"},
705     {"GtkWidget", "style_set",
706      "GtkStyle        *previous_style"},
708     {"GtkWidget", "install_accelerator",
709      "gchar           *signal_name",
710      "gchar            key",
711      "gint             modifiers"},
713     {"GtkWidget", "add_accelerator",
714      "guint            accel_signal_id",
715      "GtkAccelGroup   *accel_group",
716      "guint            accel_key",
717      "GdkModifierType  accel_mods",
718      "GtkAccelFlags    accel_flags"},
720     {"GtkWidget", "parent_set",
721      "GtkObject       *old_parent"},
723     {"GtkWidget", "remove_accelerator",
724      "GtkAccelGroup   *accel_group",
725      "guint            accel_key",
726      "GdkModifierType  accel_mods"},
727     {"GtkWidget", "debug_msg",
728      "gchar           *message"},
729     {"GtkWindow", "move_resize",
730      "gint            *x",
731      "gint            *y",
732      "gint             width",
733      "gint             height"},
734     {"GtkWindow", "set_focus",
735      "GtkWidget       *widget"},
737     {"GtkWidget", "selection_get",
738      "GtkSelectionData *data",
739      "guint            info",
740      "guint            time"},
741     {"GtkWidget", "selection_received",
742      "GtkSelectionData *data",
743      "guint            time"},
745     {"GtkWidget", "drag_begin",
746      "GdkDragContext  *drag_context"},
747     {"GtkWidget", "drag_end",
748      "GdkDragContext  *drag_context"},
749     {"GtkWidget", "drag_data_delete",
750      "GdkDragContext  *drag_context"},
751     {"GtkWidget", "drag_leave",
752      "GdkDragContext  *drag_context",
753      "guint            time"},
754     {"GtkWidget", "drag_motion",
755      "GdkDragContext  *drag_context",
756      "gint             x",
757      "gint             y",
758      "guint            time"},
759     {"GtkWidget", "drag_drop",
760      "GdkDragContext  *drag_context",
761      "gint             x",
762      "gint             y",
763      "guint            time"},
764     {"GtkWidget", "drag_data_get",
765      "GdkDragContext  *drag_context",
766      "GtkSelectionData *data",
767      "guint            info",
768      "guint            time"},
769     {"GtkWidget", "drag_data_received",
770      "GdkDragContext  *drag_context",
771      "gint             x",
772      "gint             y",
773      "GtkSelectionData *data",
774      "guint            info",
775      "guint            time"},
777     {NULL}
778   };
780   gint i;
782   for (i = 0; GbArgTable[i][0]; i++)
783     {
784 #if 1
785       if (!strcmp (type, GbArgTable[i][0])
786           && !strcmp (signal_name, GbArgTable[i][1]))
787         return &GbArgTable[i][2];
788 #endif
789     }
790   return NULL;
793 /* This outputs the hierarchy of all objects which have been initialized,
794    i.e. by calling their XXX_get_type() initialization function. */
795 static void
796 output_object_hierarchy (void)
798   FILE *fp;
799   gint i;
801   fp = fopen (hierarchy_filename, "w");
802   if (fp == NULL)
803     {
804       g_warning ("Couldn't open output file: %s : %s", hierarchy_filename, strerror(errno));
805       return;
806     }
807   output_hierarchy (fp, G_TYPE_OBJECT, 0);
808   output_hierarchy (fp, G_TYPE_INTERFACE, 0);
809   
810   for (i=0; object_types[i]; i++) {
811     if (!g_type_parent (object_types[i]) &&
812       (object_types[i] != G_TYPE_OBJECT) &&
813       (object_types[i] != G_TYPE_INTERFACE)
814     ) {
815       output_hierarchy (fp, object_types[i], 0);
816     }
817   }
819   fclose (fp);
822 /* This is called recursively to output the hierarchy of a widget. */
823 static void
824 output_hierarchy (FILE  *fp,
825                   GType  type,
826                   guint   level)
828   guint i;
829   GType *children;
830   guint n_children;
832   if (!type)
833     return;
835   for (i = 0; i < level; i++)
836     fprintf (fp, "  ");
837   fprintf (fp, g_type_name (type));
838   fprintf (fp, "\\n");
840   children = g_type_children (type, &n_children);
842   for (i=0; i < n_children; i++)
843     output_hierarchy (fp, children[i], level + 1);
845   g_free (children);
848 static void output_object_interfaces (void)
850   guint i;
851   FILE *fp;
853   fp = fopen (interfaces_filename, "w");
854   if (fp == NULL)
855     {
856       g_warning ("Couldn't open output file: %s : %s", interfaces_filename, strerror(errno));
857       return;
858     }
859   output_interfaces (fp, G_TYPE_OBJECT);
861   for (i = 0; object_types[i]; i++)
862     {
863       if (!g_type_parent (object_types[i]) &&
864           (object_types[i] != G_TYPE_OBJECT) &&
865           G_TYPE_IS_INSTANTIATABLE (object_types[i]))
866         {
867           output_interfaces (fp, object_types[i]);
868         }
869     }
870   fclose (fp);
873 static void
874 output_interfaces (FILE  *fp,
875                    GType  type)
877   guint i;
878   GType *children, *interfaces;
879   guint n_children, n_interfaces;
881   if (!type)
882     return;
884   interfaces = g_type_interfaces (type, &n_interfaces);
886   if (n_interfaces > 0)
887     {
888       fprintf (fp, g_type_name (type));
889       for (i=0; i < n_interfaces; i++)
890           fprintf (fp, " %s", g_type_name (interfaces[i]));
891       fprintf (fp, "\\n");
892      }
893   g_free (interfaces);
895   children = g_type_children (type, &n_children);
897   for (i=0; i < n_children; i++)
898     output_interfaces (fp, children[i]);
900   g_free (children);
903 static void output_interface_prerequisites (void)
905   FILE *fp;
907   fp = fopen (prerequisites_filename, "w");
908   if (fp == NULL)
909     {
910       g_warning ("Couldn't open output file: %s : %s", prerequisites_filename, strerror(errno));
911       return;
912     }
913   output_prerequisites (fp, G_TYPE_INTERFACE);
914   fclose (fp);
917 static void
918 output_prerequisites (FILE  *fp,
919                       GType  type)
921 #if GLIB_CHECK_VERSION(2,1,0)
922   guint i;
923   GType *children, *prerequisites;
924   guint n_children, n_prerequisites;
926   if (!type)
927     return;
929   prerequisites = g_type_interface_prerequisites (type, &n_prerequisites);
931   if (n_prerequisites > 0)
932     {
933       fprintf (fp, g_type_name (type));
934       for (i=0; i < n_prerequisites; i++)
935           fprintf (fp, " %s", g_type_name (prerequisites[i]));
936       fprintf (fp, "\\n");
937      }
938   g_free (prerequisites);
940   children = g_type_children (type, &n_children);
942   for (i=0; i < n_children; i++)
943     output_prerequisites (fp, children[i]);
945   g_free (children);
946 #endif
949 static void
950 output_args (void)
952   FILE *fp;
953   gint i;
955   fp = fopen (args_filename, "w");
956   if (fp == NULL)
957     {
958       g_warning ("Couldn't open output file: %s : %s", args_filename, strerror(errno));
959       return;
960     }
962   for (i = 0; object_types[i]; i++) {
963     output_object_args (fp, object_types[i]);
964   }
966   fclose (fp);
969 static gint
970 compare_param_specs (const void *a, const void *b)
972   GParamSpec *spec_a = *(GParamSpec **)a;
973   GParamSpec *spec_b = *(GParamSpec **)b;
975   return strcmp (g_param_spec_get_name (spec_a), g_param_spec_get_name (spec_b));
978 /* Its common to have unsigned properties restricted
979  * to the signed range. Therefore we make this look
980  * a bit nicer by spelling out the max constants.
981  */
983 /* Don't use "==" with floats, it might trigger a gcc warning.  */
984 #define GTKDOC_COMPARE_FLOAT(x, y) (x <= y && x >= y)
986 static gchar*
987 describe_double_constant (gdouble value)
989   gchar *desc;
991   if (GTKDOC_COMPARE_FLOAT (value, G_MAXDOUBLE))
992     desc = g_strdup ("G_MAXDOUBLE");
993   else if (GTKDOC_COMPARE_FLOAT (value, G_MINDOUBLE))
994     desc = g_strdup ("G_MINDOUBLE");
995   else if (GTKDOC_COMPARE_FLOAT (value, -G_MAXDOUBLE))
996     desc = g_strdup ("-G_MAXDOUBLE");
997   else if (GTKDOC_COMPARE_FLOAT (value, G_MAXFLOAT))
998     desc = g_strdup ("G_MAXFLOAT");
999   else if (GTKDOC_COMPARE_FLOAT (value, G_MINFLOAT))
1000     desc = g_strdup ("G_MINFLOAT");
1001   else if (GTKDOC_COMPARE_FLOAT (value, -G_MAXFLOAT))
1002     desc = g_strdup ("-G_MAXFLOAT");
1003   else
1004     desc = g_strdup_printf ("%lg", value);
1006   return desc;
1009 static gchar*
1010 describe_signed_constant (gint64 value)
1012   gchar *desc;
1014   if (value == G_MAXINT)
1015     desc = g_strdup ("G_MAXINT");
1016   else if (value == G_MININT)
1017     desc = g_strdup ("G_MININT");
1018   else if (value == G_MAXUINT)
1019     desc = g_strdup ("G_MAXUINT");
1020   else if (value == G_MAXLONG)
1021     desc = g_strdup ("G_MAXLONG");
1022   else if (value == G_MINLONG)
1023     desc = g_strdup ("G_MINLONG");
1024   else if (value == G_MAXULONG)
1025     desc = g_strdup ("G_MAXULONG");
1026   else if (value == G_MAXINT64)
1027     desc = g_strdup ("G_MAXINT64");
1028   else if (value == G_MININT64)
1029     desc = g_strdup ("G_MININT64");
1030   else
1031     desc = g_strdup_printf ("%" G_GINT64_FORMAT, value);
1033   return desc;
1036 static gchar*
1037 describe_unsigned_constant (guint64 value)
1039   gchar *desc;
1041   if (value == G_MAXINT)
1042     desc = g_strdup ("G_MAXINT");
1043   else if (value == G_MAXUINT)
1044     desc = g_strdup ("G_MAXUINT");
1045   else if (value == G_MAXLONG)
1046     desc = g_strdup ("G_MAXLONG");
1047   else if (value == G_MAXULONG)
1048     desc = g_strdup ("G_MAXULONG");
1049   else if (value == G_MAXINT64)
1050     desc = g_strdup ("G_MAXINT64");
1051   else if (value == G_MAXUINT64)
1052     desc = g_strdup ("G_MAXUINT64");
1053   else
1054     desc = g_strdup_printf ("%" G_GUINT64_FORMAT, value);
1056   return desc;
1059 static gchar*
1060 describe_type (GParamSpec *spec)
1062   gchar *desc;
1063   gchar *lower;
1064   gchar *upper;
1066   if (G_IS_PARAM_SPEC_CHAR (spec))
1067     {
1068       GParamSpecChar *pspec = G_PARAM_SPEC_CHAR (spec);
1070       lower = describe_signed_constant (pspec->minimum);
1071       upper = describe_signed_constant (pspec->maximum);
1072       if (pspec->minimum == G_MININT8 && pspec->maximum == G_MAXINT8)
1073         desc = g_strdup ("");
1074       else if (pspec->minimum == G_MININT8)
1075         desc = g_strdup_printf ("<= %s", upper);
1076       else if (pspec->maximum == G_MAXINT8)
1077         desc = g_strdup_printf (">= %s", lower);
1078       else
1079         desc = g_strdup_printf ("[%s,%s]", lower, upper);
1080       g_free (lower);
1081       g_free (upper);
1082     }
1083   else if (G_IS_PARAM_SPEC_UCHAR (spec))
1084     {
1085       GParamSpecUChar *pspec = G_PARAM_SPEC_UCHAR (spec);
1087       lower = describe_unsigned_constant (pspec->minimum);
1088       upper = describe_unsigned_constant (pspec->maximum);
1089       if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT8)
1090         desc = g_strdup ("");
1091       else if (pspec->minimum == 0)
1092         desc = g_strdup_printf ("<= %s", upper);
1093       else if (pspec->maximum == G_MAXUINT8)
1094         desc = g_strdup_printf (">= %s", lower);
1095       else
1096         desc = g_strdup_printf ("[%s,%s]", lower, upper);
1097       g_free (lower);
1098       g_free (upper);
1099     }
1100   else if (G_IS_PARAM_SPEC_INT (spec))
1101     {
1102       GParamSpecInt *pspec = G_PARAM_SPEC_INT (spec);
1104       lower = describe_signed_constant (pspec->minimum);
1105       upper = describe_signed_constant (pspec->maximum);
1106       if (pspec->minimum == G_MININT && pspec->maximum == G_MAXINT)
1107         desc = g_strdup ("");
1108       else if (pspec->minimum == G_MININT)
1109         desc = g_strdup_printf ("<= %s", upper);
1110       else if (pspec->maximum == G_MAXINT)
1111         desc = g_strdup_printf (">= %s", lower);
1112       else
1113         desc = g_strdup_printf ("[%s,%s]", lower, upper);
1114       g_free (lower);
1115       g_free (upper);
1116     }
1117   else if (G_IS_PARAM_SPEC_UINT (spec))
1118     {
1119       GParamSpecUInt *pspec = G_PARAM_SPEC_UINT (spec);
1121       lower = describe_unsigned_constant (pspec->minimum);
1122       upper = describe_unsigned_constant (pspec->maximum);
1123       if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT)
1124         desc = g_strdup ("");
1125       else if (pspec->minimum == 0)
1126         desc = g_strdup_printf ("<= %s", upper);
1127       else if (pspec->maximum == G_MAXUINT)
1128         desc = g_strdup_printf (">= %s", lower);
1129       else
1130         desc = g_strdup_printf ("[%s,%s]", lower, upper);
1131       g_free (lower);
1132       g_free (upper);
1133     }
1134   else if (G_IS_PARAM_SPEC_LONG (spec))
1135     {
1136       GParamSpecLong *pspec = G_PARAM_SPEC_LONG (spec);
1138       lower = describe_signed_constant (pspec->minimum);
1139       upper = describe_signed_constant (pspec->maximum);
1140       if (pspec->minimum == G_MINLONG && pspec->maximum == G_MAXLONG)
1141         desc = g_strdup ("");
1142       else if (pspec->minimum == G_MINLONG)
1143         desc = g_strdup_printf ("<= %s", upper);
1144       else if (pspec->maximum == G_MAXLONG)
1145         desc = g_strdup_printf (">= %s", lower);
1146       else
1147         desc = g_strdup_printf ("[%s,%s]", lower, upper);
1148       g_free (lower);
1149       g_free (upper);
1150     }
1151   else if (G_IS_PARAM_SPEC_ULONG (spec))
1152     {
1153       GParamSpecULong *pspec = G_PARAM_SPEC_ULONG (spec);
1155       lower = describe_unsigned_constant (pspec->minimum);
1156       upper = describe_unsigned_constant (pspec->maximum);
1157       if (pspec->minimum == 0 && pspec->maximum == G_MAXULONG)
1158         desc = g_strdup ("");
1159       else if (pspec->minimum == 0)
1160         desc = g_strdup_printf ("<= %s", upper);
1161       else if (pspec->maximum == G_MAXULONG)
1162         desc = g_strdup_printf (">= %s", lower);
1163       else
1164         desc = g_strdup_printf ("[%s,%s]", lower, upper);
1165       g_free (lower);
1166       g_free (upper);
1167     }
1168   else if (G_IS_PARAM_SPEC_INT64 (spec))
1169     {
1170       GParamSpecInt64 *pspec = G_PARAM_SPEC_INT64 (spec);
1172       lower = describe_signed_constant (pspec->minimum);
1173       upper = describe_signed_constant (pspec->maximum);
1174       if (pspec->minimum == G_MININT64 && pspec->maximum == G_MAXINT64)
1175         desc = g_strdup ("");
1176       else if (pspec->minimum == G_MININT64)
1177         desc = g_strdup_printf ("<= %s", upper);
1178       else if (pspec->maximum == G_MAXINT64)
1179         desc = g_strdup_printf (">= %s", lower);
1180       else
1181         desc = g_strdup_printf ("[%s,%s]", lower, upper);
1182       g_free (lower);
1183       g_free (upper);
1184     }
1185   else if (G_IS_PARAM_SPEC_UINT64 (spec))
1186     {
1187       GParamSpecUInt64 *pspec = G_PARAM_SPEC_UINT64 (spec);
1189       lower = describe_unsigned_constant (pspec->minimum);
1190       upper = describe_unsigned_constant (pspec->maximum);
1191       if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT64)
1192         desc = g_strdup ("");
1193       else if (pspec->minimum == 0)
1194         desc = g_strdup_printf ("<= %s", upper);
1195       else if (pspec->maximum == G_MAXUINT64)
1196         desc = g_strdup_printf (">= %s", lower);
1197       else
1198         desc = g_strdup_printf ("[%s,%s]", lower, upper);
1199       g_free (lower);
1200       g_free (upper);
1201     }
1202   else if (G_IS_PARAM_SPEC_FLOAT (spec))
1203     {
1204       GParamSpecFloat *pspec = G_PARAM_SPEC_FLOAT (spec);
1206       lower = describe_double_constant (pspec->minimum);
1207       upper = describe_double_constant (pspec->maximum);
1208       if (GTKDOC_COMPARE_FLOAT (pspec->minimum, -G_MAXFLOAT))
1209         {
1210           if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXFLOAT))
1211             desc = g_strdup ("");
1212           else
1213             desc = g_strdup_printf ("<= %s", upper);
1214         }
1215       else if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXFLOAT))
1216         desc = g_strdup_printf (">= %s", lower);
1217       else
1218         desc = g_strdup_printf ("[%s,%s]", lower, upper);
1219       g_free (lower);
1220       g_free (upper);
1221     }
1222   else if (G_IS_PARAM_SPEC_DOUBLE (spec))
1223     {
1224       GParamSpecDouble *pspec = G_PARAM_SPEC_DOUBLE (spec);
1226       lower = describe_double_constant (pspec->minimum);
1227       upper = describe_double_constant (pspec->maximum);
1228       if (GTKDOC_COMPARE_FLOAT (pspec->minimum, -G_MAXDOUBLE))
1229         {
1230           if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXDOUBLE))
1231             desc = g_strdup ("");
1232           else
1233             desc = g_strdup_printf ("<= %s", upper);
1234         }
1235       else if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXDOUBLE))
1236         desc = g_strdup_printf (">= %s", lower);
1237       else
1238         desc = g_strdup_printf ("[%s,%s]", lower, upper);
1239       g_free (lower);
1240       g_free (upper);
1241     }
1242   else
1243     {
1244       desc = g_strdup ("");
1245     }
1247   return desc;
1250 static gchar*
1251 describe_default (GParamSpec *spec)
1253   gchar *desc;
1255   if (G_IS_PARAM_SPEC_CHAR (spec))
1256     {
1257       GParamSpecChar *pspec = G_PARAM_SPEC_CHAR (spec);
1259       desc = g_strdup_printf ("%d", pspec->default_value);
1260     }
1261   else if (G_IS_PARAM_SPEC_UCHAR (spec))
1262     {
1263       GParamSpecUChar *pspec = G_PARAM_SPEC_UCHAR (spec);
1265       desc = g_strdup_printf ("%u", pspec->default_value);
1266     }
1267   else if (G_IS_PARAM_SPEC_BOOLEAN (spec))
1268     {
1269       GParamSpecBoolean *pspec = G_PARAM_SPEC_BOOLEAN (spec);
1271       desc = g_strdup_printf ("%s", pspec->default_value ? "TRUE" : "FALSE");
1272     }
1273   else if (G_IS_PARAM_SPEC_INT (spec))
1274     {
1275       GParamSpecInt *pspec = G_PARAM_SPEC_INT (spec);
1277       desc = g_strdup_printf ("%d", pspec->default_value);
1278     }
1279   else if (G_IS_PARAM_SPEC_UINT (spec))
1280     {
1281       GParamSpecUInt *pspec = G_PARAM_SPEC_UINT (spec);
1283       desc = g_strdup_printf ("%u", pspec->default_value);
1284     }
1285   else if (G_IS_PARAM_SPEC_LONG (spec))
1286     {
1287       GParamSpecLong *pspec = G_PARAM_SPEC_LONG (spec);
1289       desc = g_strdup_printf ("%ld", pspec->default_value);
1290     }
1291   else if (G_IS_PARAM_SPEC_LONG (spec))
1292     {
1293       GParamSpecULong *pspec = G_PARAM_SPEC_ULONG (spec);
1295       desc = g_strdup_printf ("%lu", pspec->default_value);
1296     }
1297   else if (G_IS_PARAM_SPEC_INT64 (spec))
1298     {
1299       GParamSpecInt64 *pspec = G_PARAM_SPEC_INT64 (spec);
1301       desc = g_strdup_printf ("%" G_GINT64_FORMAT, pspec->default_value);
1302     }
1303   else if (G_IS_PARAM_SPEC_UINT64 (spec))
1304     {
1305       GParamSpecUInt64 *pspec = G_PARAM_SPEC_UINT64 (spec);
1307       desc = g_strdup_printf ("%" G_GUINT64_FORMAT, pspec->default_value);
1308     }
1309   else if (G_IS_PARAM_SPEC_UNICHAR (spec))
1310     {
1311       GParamSpecUnichar *pspec = G_PARAM_SPEC_UNICHAR (spec);
1313       if (g_unichar_isprint (pspec->default_value))
1314         desc = g_strdup_printf ("'%c'", pspec->default_value);
1315       else
1316         desc = g_strdup_printf ("%u", pspec->default_value);
1317     }
1318   else if (G_IS_PARAM_SPEC_ENUM (spec))
1319     {
1320       GParamSpecEnum *pspec = G_PARAM_SPEC_ENUM (spec);
1322       GEnumValue *value = g_enum_get_value (pspec->enum_class, pspec->default_value);
1323       if (value)
1324         desc = g_strdup_printf ("%s", value->value_name);
1325       else
1326         desc = g_strdup_printf ("%d", pspec->default_value);
1327     }
1328   else if (G_IS_PARAM_SPEC_FLAGS (spec))
1329     {
1330       GParamSpecFlags *pspec = G_PARAM_SPEC_FLAGS (spec);
1331       guint default_value;
1332       GString *acc;
1334       default_value = pspec->default_value;
1335       acc = g_string_new ("");
1337       while (default_value)
1338         {
1339           GFlagsValue *value = g_flags_get_first_value (pspec->flags_class, default_value);
1341           if (!value)
1342             break;
1344           if (acc->len > 0)
1345             g_string_append (acc, "|");
1346           g_string_append (acc, value->value_name);
1348           default_value &= ~value->value;
1349         }
1351       if (default_value == 0)
1352         desc = g_string_free (acc, FALSE);
1353       else
1354         {
1355           desc = g_strdup_printf ("%d", pspec->default_value);
1356           g_string_free (acc, TRUE);
1357         }
1358     }
1359   else if (G_IS_PARAM_SPEC_FLOAT (spec))
1360     {
1361       GParamSpecFloat *pspec = G_PARAM_SPEC_FLOAT (spec);
1363       desc = g_strdup_printf ("%g", pspec->default_value);
1364     }
1365   else if (G_IS_PARAM_SPEC_DOUBLE (spec))
1366     {
1367       GParamSpecDouble *pspec = G_PARAM_SPEC_DOUBLE (spec);
1369       desc = g_strdup_printf ("%lg", pspec->default_value);
1370     }
1371   else if (G_IS_PARAM_SPEC_STRING (spec))
1372     {
1373       GParamSpecString *pspec = G_PARAM_SPEC_STRING (spec);
1375       if (pspec->default_value)
1376         {
1377           gchar *esc = g_strescape (pspec->default_value, NULL);
1379           desc = g_strdup_printf ("\\"%s\\"", esc);
1381           g_free (esc);
1382         }
1383       else
1384         desc = g_strdup_printf ("NULL");
1385     }
1386   else
1387     {
1388       desc = g_strdup ("");
1389     }
1391   return desc;
1395 static void
1396 output_object_args (FILE *fp, GType object_type)
1398   gpointer class;
1399   const gchar *object_class_name;
1400   guint arg;
1401   gchar flags[16], *pos;
1402   GParamSpec **properties;
1403   guint n_properties;
1404   gboolean child_prop;
1405   gboolean style_prop;
1406   gchar *type_desc;
1407   gchar *default_value;
1409   if (G_TYPE_IS_OBJECT (object_type))
1410     {
1411       class = g_type_class_peek (object_type);
1412       if (!class)
1413         return;
1415       properties = g_object_class_list_properties (class, &n_properties);
1416     }
1417 #if GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 3)
1418   else if (G_TYPE_IS_INTERFACE (object_type))
1419     {
1420       class = g_type_default_interface_ref (object_type);
1422       if (!class)
1423         return;
1425       properties = g_object_interface_list_properties (class, &n_properties);
1426     }
1427 #endif
1428   else
1429     return;
1431   object_class_name = g_type_name (object_type);
1433   child_prop = FALSE;
1434   style_prop = FALSE;
1436   while (TRUE) {
1437     qsort (properties, n_properties, sizeof (GParamSpec *), compare_param_specs);
1438     for (arg = 0; arg < n_properties; arg++)
1439       {
1440         GParamSpec *spec = properties[arg];
1441         const gchar *nick, *blurb, *dot;
1443         if (spec->owner_type != object_type)
1444           continue;
1446         pos = flags;
1447         /* We use one-character flags for simplicity. */
1448         if (child_prop && !style_prop)
1449           *pos++ = 'c';
1450         if (style_prop)
1451           *pos++ = 's';
1452         if (spec->flags & G_PARAM_READABLE)
1453           *pos++ = 'r';
1454         if (spec->flags & G_PARAM_WRITABLE)
1455           *pos++ = 'w';
1456         if (spec->flags & G_PARAM_CONSTRUCT)
1457           *pos++ = 'x';
1458         if (spec->flags & G_PARAM_CONSTRUCT_ONLY)
1459           *pos++ = 'X';
1460         *pos = 0;
1462         nick = g_param_spec_get_nick (spec);
1463         blurb = g_param_spec_get_blurb (spec);
1465         dot = "";
1466         if (blurb) {
1467           int str_len = strlen (blurb);
1468           if (str_len > 0  && blurb[str_len - 1] != '.')
1469             dot = ".";
1470         }
1472         type_desc = describe_type (spec);
1473         default_value = describe_default (spec);
1474         fprintf (fp, "<ARG>\\n<NAME>%s::%s</NAME>\\n<TYPE>%s</TYPE>\\n<RANGE>%s</RANGE>\\n<FLAGS>%s</FLAGS>\\n<NICK>%s</NICK>\\n<BLURB>%s%s</BLURB>\\n<DEFAULT>%s</DEFAULT>\\n</ARG>\\n\\n",
1475                  object_class_name, g_param_spec_get_name (spec), g_type_name (spec->value_type), type_desc, flags, nick ? nick : "(null)", blurb ? blurb : "(null)", dot, default_value);
1476         g_free (type_desc);
1477         g_free (default_value);
1478       }
1480     g_free (properties);
1482 #ifdef GTK_IS_CONTAINER_CLASS
1483     if (!child_prop && GTK_IS_CONTAINER_CLASS (class)) {
1484       properties = gtk_container_class_list_child_properties (class, &n_properties);
1485       child_prop = TRUE;
1486       continue;
1487     }
1488 #endif
1490 #ifdef GTK_IS_WIDGET_CLASS
1491 #if GTK_CHECK_VERSION(2,1,0)
1492     if (!style_prop && GTK_IS_WIDGET_CLASS (class)) {
1493       properties = gtk_widget_class_list_style_properties (GTK_WIDGET_CLASS (class), &n_properties);
1494       style_prop = TRUE;
1495       continue;
1496     }
1497 #endif
1498 #endif
1502 if ($QUERY_CHILD_PROPERTIES) {
1503   print OUTPUT <<EOT;
1504     if (!child_prop) {
1505       properties = $QUERY_CHILD_PROPERTIES (class, &n_properties);
1506       if (properties) {
1507         child_prop = TRUE;
1508         continue;
1509       }
1510    }
1515 print OUTPUT <<EOT;
1516     break;
1517   }
1521 close OUTPUT;
1523 # Compile and run our file
1525 $CC = $ENV{CC} ? $ENV{CC} : "gcc";
1526 $LD = $ENV{LD} ? $ENV{LD} : $CC;
1527 $CFLAGS = $ENV{CFLAGS} ? $ENV{CFLAGS} : "";
1528 $LDFLAGS = $ENV{LDFLAGS} ? $ENV{LDFLAGS} : "";
1530 my $o_file;
1531 if ($CC =~ /libtool/) {
1532   $o_file  = "$MODULE-scan.lo"
1533 } else {
1534   $o_file = "$MODULE-scan.o"
1537 print "gtk-doc: Compiling scanner\n";
1538 $command = "$CC $CFLAGS -c -o $o_file $MODULE-scan.c";
1539 system($command) == 0 or die "Compilation of scanner failed: $!\n";
1541 print "gtk-doc: Linking scanner\n";
1542 $command = "$LD -o $MODULE-scan $o_file $LDFLAGS";
1543 system($command) == 0 or die "Linking of scanner failed: $!\n";
1545 print "gtk-doc: Running scanner $MODULE-scan\n";
1546 system("sh -c ./$MODULE-scan") == 0 or die "Scan failed: $!\n";
1548 unlink "./$MODULE-scan.c", "./$MODULE-scan.o", "./$MODULE-scan.lo", "./$MODULE-scan";
1550 &UpdateFileIfChanged ($old_signals_filename, $new_signals_filename, 0);
1551 &UpdateFileIfChanged ($old_hierarchy_filename, $new_hierarchy_filename, 0);
1552 &UpdateFileIfChanged ($old_interfaces_filename, $new_interfaces_filename, 0);
1553 &UpdateFileIfChanged ($old_prerequisites_filename, $new_prerequisites_filename, 0);
1554 &UpdateFileIfChanged ($old_args_filename, $new_args_filename, 0);