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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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.
30 # FIXME: this is only needed for undocumented signals, we should remove
31 # the list as its totally undermaintained anyway
35 push @INC, '@PACKAGE_DATA_DIR@';
36 require "gtkdoc-common.pl";
40 # name of documentation module
45 my $TYPE_INIT_FUNC="g_type_init(); g_type_class_ref(G_TYPE_OBJECT)";
46 my $QUERY_CHILD_PROPERTIES;
48 # --nogtkinit is deprecated, as it is the default now anyway.
49 %optctl = (module => \$MODULE,
50 types => \$TYPES_FILE,
51 nogtkinit => \$NO_GTK_INIT,
52 'type-init-func' => \$TYPE_INIT_FUNC,
53 'query-child-properties' => \$QUERY_CHILD_PROPERTIES,
54 'output-dir' => \$OUTPUT_DIR,
55 'version' => \$PRINT_VERSION,
56 'help' => \$PRINT_HELP);
58 GetOptions(\%optctl, "module=s", "types:s", "output-dir:s", "nogtkinit", "type-init-func:s", "query-child-properties:s", "version", "help");
61 # Do nothing. This just avoids a warning.
62 # the option is not used anymore
76 gtkdoc-scangobj version @VERSION@ - introspect g-objects
78 --module=MODULE_NAME Name of the doc module being parsed
79 --types=FILE The name of the file to store the types in
80 --type-init-func=FUNC The init function to call instead of g_type_init()
81 --query-child-properties=FUNC A function that returns a list of child
82 properties for a class
83 --output-dir=DIRNAME The directory where the results are stored
84 --version Print the version of this program
85 --help Print this help
90 $OUTPUT_DIR = $OUTPUT_DIR ? $OUTPUT_DIR : ".";
92 $TYPES_FILE = $TYPES_FILE ? $TYPES_FILE : "$OUTPUT_DIR/$MODULE.types";
94 open (TYPES, $TYPES_FILE) || die "Cannot open $TYPES_FILE: $!\n";
95 open (OUTPUT, ">$MODULE-scan.c") || die "Cannot open $MODULE-scan.c: $!\n";
97 my $old_signals_filename = "$OUTPUT_DIR/$MODULE.signals";
98 my $new_signals_filename = "$OUTPUT_DIR/$MODULE.signals.new";
99 my $old_hierarchy_filename = "$OUTPUT_DIR/$MODULE.hierarchy";
100 my $new_hierarchy_filename = "$OUTPUT_DIR/$MODULE.hierarchy.new";
101 my $old_interfaces_filename = "$OUTPUT_DIR/$MODULE.interfaces";
102 my $new_interfaces_filename = "$OUTPUT_DIR/$MODULE.interfaces.new";
103 my $old_prerequisites_filename = "$OUTPUT_DIR/$MODULE.prerequisites";
104 my $new_prerequisites_filename = "$OUTPUT_DIR/$MODULE.prerequisites.new";
105 my $old_args_filename = "$OUTPUT_DIR/$MODULE.args";
106 my $new_args_filename = "$OUTPUT_DIR/$MODULE.args.new";
108 # write a C program to scan the types
116 } elsif (/^gnome_keyring_item_info_get_type$/) {
117 # HACK: This isn't really a GObject type so skip it.
129 $ntypes = @types + 1;
136 #include <glib-object.h>
141 print OUTPUT $includes;
144 print OUTPUT "extern GType $_ (void);\n";
148 if ($QUERY_CHILD_PROPERTIES) {
150 extern GParamSpec** $QUERY_CHILD_PROPERTIES (gpointer class, guint *n_properties);
156 #ifdef GTK_IS_WIDGET_CLASS
159 GType object_types[$ntypes];
162 get_object_types (void)
164 gpointer g_object_class;
169 print OUTPUT " object_types[i++] = $_ ();\n";
175 /* reference the GObjectClass to initialize the param spec pool
176 * potentially needed by interfaces. See http://bugs.gnome.org/571820 */
177 g_object_class = g_type_class_ref (G_TYPE_OBJECT);
179 /* Need to make sure all the types are loaded in and initialize
180 * their signals and properties.
182 for (i=0; object_types[i]; i++)
184 if (G_TYPE_IS_CLASSED (object_types[i]))
185 g_type_class_ref (object_types[i]);
186 if (G_TYPE_IS_INTERFACE (object_types[i]))
187 g_type_default_interface_ref (object_types[i]);
190 g_type_class_unref (g_object_class);
196 * This uses GObject type functions to output signal prototypes and the object
200 /* The output files */
201 const gchar *signals_filename = "$new_signals_filename";
202 const gchar *hierarchy_filename = "$new_hierarchy_filename";
203 const gchar *interfaces_filename = "$new_interfaces_filename";
204 const gchar *prerequisites_filename = "$new_prerequisites_filename";
205 const gchar *args_filename = "$new_args_filename";
208 static void output_signals (void);
209 static void output_object_signals (FILE *fp,
211 static void output_object_signal (FILE *fp,
212 const gchar *object_class_name,
214 static const gchar * get_type_name (GType type,
215 gboolean * is_pointer);
216 static const gchar * get_gdk_event (const gchar * signal_name);
217 static const gchar ** lookup_signal_arg_names (const gchar * type,
218 const gchar * signal_name);
220 static void output_object_hierarchy (void);
221 static void output_hierarchy (FILE *fp,
225 static void output_object_interfaces (void);
226 static void output_interfaces (FILE *fp,
229 static void output_interface_prerequisites (void);
230 static void output_prerequisites (FILE *fp,
233 static void output_args (void);
234 static void output_object_args (FILE *fp, GType object_type);
237 main (int argc, char *argv[])
244 output_object_hierarchy ();
245 output_object_interfaces ();
246 output_interface_prerequisites ();
254 output_signals (void)
259 fp = fopen (signals_filename, "w");
262 g_warning ("Couldn't open output file: %s : %s", signals_filename, g_strerror(errno));
266 for (i = 0; object_types[i]; i++)
267 output_object_signals (fp, object_types[i]);
273 compare_signals (const void *a, const void *b)
275 const guint *signal_a = a;
276 const guint *signal_b = b;
278 return strcmp (g_signal_name (*signal_a), g_signal_name (*signal_b));
281 /* This outputs all the signals of one object. */
283 output_object_signals (FILE *fp, GType object_type)
285 const gchar *object_class_name;
286 guint *signals, n_signals;
289 if (G_TYPE_IS_INSTANTIATABLE (object_type) ||
290 G_TYPE_IS_INTERFACE (object_type))
293 object_class_name = g_type_name (object_type);
295 signals = g_signal_list_ids (object_type, &n_signals);
296 qsort (signals, n_signals, sizeof (guint), compare_signals);
298 for (sig = 0; sig < n_signals; sig++)
300 output_object_signal (fp, object_class_name, signals[sig]);
307 /* This outputs one signal. */
309 output_object_signal (FILE *fp,
310 const gchar *object_name,
313 GSignalQuery query_info;
314 const gchar *type_name, *ret_type, *object_arg, *arg_name;
315 gchar *pos, *object_arg_lower;
319 const gchar **arg_names;
320 gint param_num, widget_num, event_num, callback_num;
322 gchar signal_name[128];
325 /* g_print ("Object: %s Signal: %u\\n", object_name, signal_id);*/
328 widget_num = event_num = callback_num = 0;
330 g_signal_query (signal_id, &query_info);
332 /* Output the signal object type and the argument name. We assume the
333 type is a pointer - I think that is OK. We remove "Gtk" or "Gnome" and
334 convert to lower case for the argument name. */
336 sprintf (pos, "%s ", object_name);
339 /* Try to come up with a sensible variable name for the first arg
340 * I chops off 2 know prefixes :/ and makes the name lowercase
341 * It should replace lowercase -> uppercase with '_'
342 * GFileMonitor -> file_monitor
343 * GIOExtensionPoint -> extension_point
344 * GtkTreeView -> tree_view
345 * if 2nd char is upper case too
346 * search for first lower case and go back one char
348 * search for next upper case
350 if (!strncmp (object_name, "Gtk", 3))
351 object_arg = object_name + 3;
352 else if (!strncmp (object_name, "Gnome", 5))
353 object_arg = object_name + 5;
355 object_arg = object_name;
357 object_arg_lower = g_ascii_strdown (object_arg, -1);
358 sprintf (pos, "*%s\\n", object_arg_lower);
360 if (!strncmp (object_arg_lower, "widget", 6))
362 g_free(object_arg_lower);
364 /* Convert signal name to use underscores rather than dashes '-'. */
365 strncpy (signal_name, query_info.signal_name, 127);
366 signal_name[127] = '\\0';
367 for (i = 0; signal_name[i]; i++)
369 if (signal_name[i] == '-')
370 signal_name[i] = '_';
373 /* Output the signal parameters. */
374 arg_names = lookup_signal_arg_names (object_name, signal_name);
376 for (param = 0; param < query_info.n_params; param++)
380 sprintf (pos, "%s\\n", arg_names[param]);
385 type_name = get_type_name (query_info.param_types[param] & ~G_SIGNAL_TYPE_STATIC_SCOPE, &is_pointer);
387 /* Most arguments to the callback are called "arg1", "arg2", etc.
388 GdkWidgets are called "widget", "widget2", ...
389 GdkEvents are called "event", "event2", ...
390 GtkCallbacks are called "callback", "callback2", ... */
391 if (!strcmp (type_name, "GtkWidget"))
394 arg_num = &widget_num;
396 else if (!strcmp (type_name, "GdkEvent"))
398 type_name = get_gdk_event (signal_name);
400 arg_num = &event_num;
403 else if (!strcmp (type_name, "GtkCallback")
404 || !strcmp (type_name, "GtkCCallback"))
406 arg_name = "callback";
407 arg_num = &callback_num;
412 arg_num = ¶m_num;
414 sprintf (pos, "%s ", type_name);
417 if (!arg_num || *arg_num == 0)
418 sprintf (pos, "%s%s\\n", is_pointer ? "*" : " ", arg_name);
420 sprintf (pos, "%s%s%i\\n", is_pointer ? "*" : " ", arg_name,
435 /* We use one-character flags for simplicity. */
436 if (query_info.signal_flags & G_SIGNAL_RUN_FIRST)
438 if (query_info.signal_flags & G_SIGNAL_RUN_LAST)
440 if (query_info.signal_flags & G_SIGNAL_RUN_CLEANUP)
442 if (query_info.signal_flags & G_SIGNAL_NO_RECURSE)
444 if (query_info.signal_flags & G_SIGNAL_DETAILED)
446 if (query_info.signal_flags & G_SIGNAL_ACTION)
448 if (query_info.signal_flags & G_SIGNAL_NO_HOOKS)
452 /* Output the return type and function name. */
453 ret_type = get_type_name (query_info.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE, &is_pointer);
456 "<SIGNAL>\\n<NAME>%s::%s</NAME>\\n<RETURNS>%s%s</RETURNS>\\n<FLAGS>%s</FLAGS>\\n%s</SIGNAL>\\n\\n",
457 object_name, query_info.signal_name, ret_type, is_pointer ? "*" : "", flags, buffer);
461 /* Returns the type name to use for a signal argument or return value, given
462 the GtkType from the signal info. It also sets is_pointer to TRUE if the
463 argument needs a '*' since it is a pointer. */
465 get_type_name (GType type, gboolean * is_pointer)
467 const gchar *type_name;
470 type_name = g_type_name (type);
484 /* These all have normal C type names so they are OK. */
488 /* A GtkString is really a gchar*. */
494 /* We use a gint for both of these. Hopefully a subtype with a decent
495 name will be registered and used instead, as GTK+ does itself. */
499 /* The boxed type shouldn't be used itself, only subtypes. Though we
500 return 'gpointer' just in case. */
504 /* A GParam is really a GParamSpec*. */
508 #if GLIB_CHECK_VERSION (2, 25, 9)
518 /* For all GObject subclasses we can use the class name with a "*",
519 e.g. 'GtkWidget *'. */
520 if (g_type_is_a (type, G_TYPE_OBJECT))
523 /* Also catch non GObject root types */
524 if (G_TYPE_IS_CLASSED (type))
527 /* All boxed subtypes will be pointers as well. */
528 /* Exception: GStrv */
529 if (g_type_is_a (type, G_TYPE_BOXED) &&
530 !g_type_is_a (type, G_TYPE_STRV))
533 /* All pointer subtypes will be pointers as well. */
534 if (g_type_is_a (type, G_TYPE_POINTER))
537 /* But enums are not */
538 if (g_type_is_a (type, G_TYPE_ENUM) ||
539 g_type_is_a (type, G_TYPE_FLAGS))
547 get_gdk_event (const gchar * signal_name)
549 static const gchar *GbGDKEvents[] =
551 "button_press_event", "GdkEventButton",
552 "button_release_event", "GdkEventButton",
553 "motion_notify_event", "GdkEventMotion",
554 "delete_event", "GdkEvent",
555 "destroy_event", "GdkEvent",
556 "expose_event", "GdkEventExpose",
557 "key_press_event", "GdkEventKey",
558 "key_release_event", "GdkEventKey",
559 "enter_notify_event", "GdkEventCrossing",
560 "leave_notify_event", "GdkEventCrossing",
561 "configure_event", "GdkEventConfigure",
562 "focus_in_event", "GdkEventFocus",
563 "focus_out_event", "GdkEventFocus",
564 "map_event", "GdkEvent",
565 "unmap_event", "GdkEvent",
566 "property_notify_event", "GdkEventProperty",
567 "selection_clear_event", "GdkEventSelection",
568 "selection_request_event", "GdkEventSelection",
569 "selection_notify_event", "GdkEventSelection",
570 "proximity_in_event", "GdkEventProximity",
571 "proximity_out_event", "GdkEventProximity",
572 "drag_begin_event", "GdkEventDragBegin",
573 "drag_request_event", "GdkEventDragRequest",
574 "drag_end_event", "GdkEventDragRequest",
575 "drop_enter_event", "GdkEventDropEnter",
576 "drop_leave_event", "GdkEventDropLeave",
577 "drop_data_available_event", "GdkEventDropDataAvailable",
578 "other_event", "GdkEventOther",
579 "client_event", "GdkEventClient",
580 "no_expose_event", "GdkEventNoExpose",
581 "visibility_notify_event", "GdkEventVisibility",
582 "window_state_event", "GdkEventWindowState",
583 "scroll_event", "GdkEventScroll",
589 for (i = 0; GbGDKEvents[i]; i += 2)
591 if (!strcmp (signal_name, GbGDKEvents[i]))
592 return GbGDKEvents[i + 1];
598 /* This returns argument names to use for some known GTK signals.
599 It is passed a widget name, e.g. 'GtkCList' and a signal name, e.g.
600 'select_row' and it returns a pointer to an array of argument types and
602 static const gchar **
603 lookup_signal_arg_names (const gchar * type, const gchar * signal_name)
605 /* Each arg array starts with the object type name and the signal name,
606 and then signal arguments follow. */
607 static const gchar *GbArgTable[][16] =
609 {"GtkCList", "select_row",
612 "GdkEventButton *event"},
613 {"GtkCList", "unselect_row",
616 "GdkEventButton *event"},
617 {"GtkCList", "click_column",
620 {"GtkCList", "resize_column",
624 {"GtkCList", "extend_selection",
625 "GtkScrollType scroll_type",
627 "gboolean auto_start_selection"},
628 {"GtkCList", "scroll_vertical",
629 "GtkScrollType scroll_type",
631 {"GtkCList", "scroll_horizontal",
632 "GtkScrollType scroll_type",
635 {"GtkCTree", "tree_select_row",
636 "GtkCTreeNode *node",
638 {"GtkCTree", "tree_unselect_row",
639 "GtkCTreeNode *node",
641 {"GtkCTree", "tree_expand",
642 "GtkCTreeNode *node"},
643 {"GtkCTree", "tree_collapse",
644 "GtkCTreeNode *node"},
645 {"GtkCTree", "tree_move",
646 "GtkCTreeNode *node",
647 "GtkCTreeNode *new_parent",
648 "GtkCTreeNode *new_sibling"},
649 {"GtkCTree", "change_focus_row_expansion",
650 "GtkCTreeExpansionType expansion"},
652 {"GtkEditable", "insert_text",
654 "gint new_text_length",
656 {"GtkEditable", "delete_text",
659 {"GtkEditable", "set_editable",
660 "gboolean is_editable"},
661 {"GtkEditable", "move_cursor",
664 {"GtkEditable", "move_word",
666 {"GtkEditable", "move_page",
669 {"GtkEditable", "move_to_row",
671 {"GtkEditable", "move_to_column",
674 {"GtkEditable", "kill_char",
676 {"GtkEditable", "kill_word",
678 {"GtkEditable", "kill_line",
682 {"GtkInputDialog", "enable_device",
683 "GdkDevice *deviceid"},
684 {"GtkInputDialog", "disable_device",
685 "GdkDevice *deviceid"},
687 {"GtkListItem", "extend_selection",
688 "GtkScrollType scroll_type",
690 "gboolean auto_start_selection"},
691 {"GtkListItem", "scroll_vertical",
692 "GtkScrollType scroll_type",
694 {"GtkListItem", "scroll_horizontal",
695 "GtkScrollType scroll_type",
698 {"GtkMenuShell", "move_current",
699 "GtkMenuDirectionType direction"},
700 {"GtkMenuShell", "activate_current",
701 "gboolean force_hide"},
704 {"GtkNotebook", "switch_page",
705 "GtkNotebookPage *page",
707 {"GtkStatusbar", "text_pushed",
710 {"GtkStatusbar", "text_popped",
713 {"GtkTipsQuery", "widget_entered",
716 "gchar *tip_private"},
717 {"GtkTipsQuery", "widget_selected",
720 "gchar *tip_private",
721 "GdkEventButton *event"},
722 {"GtkToolbar", "orientation_changed",
723 "GtkOrientation orientation"},
724 {"GtkToolbar", "style_changed",
725 "GtkToolbarStyle style"},
726 {"GtkWidget", "draw",
727 "GdkRectangle *area"},
728 {"GtkWidget", "size_request",
729 "GtkRequisition *requisition"},
730 {"GtkWidget", "size_allocate",
731 "GtkAllocation *allocation"},
732 {"GtkWidget", "state_changed",
733 "GtkStateType state"},
734 {"GtkWidget", "style_set",
735 "GtkStyle *previous_style"},
737 {"GtkWidget", "install_accelerator",
738 "gchar *signal_name",
742 {"GtkWidget", "add_accelerator",
743 "guint accel_signal_id",
744 "GtkAccelGroup *accel_group",
746 "GdkModifierType accel_mods",
747 "GtkAccelFlags accel_flags"},
749 {"GtkWidget", "parent_set",
750 "GtkObject *old_parent"},
752 {"GtkWidget", "remove_accelerator",
753 "GtkAccelGroup *accel_group",
755 "GdkModifierType accel_mods"},
756 {"GtkWidget", "debug_msg",
758 {"GtkWindow", "move_resize",
763 {"GtkWindow", "set_focus",
764 "GtkWidget *widget"},
766 {"GtkWidget", "selection_get",
767 "GtkSelectionData *data",
770 {"GtkWidget", "selection_received",
771 "GtkSelectionData *data",
774 {"GtkWidget", "drag_begin",
775 "GdkDragContext *drag_context"},
776 {"GtkWidget", "drag_end",
777 "GdkDragContext *drag_context"},
778 {"GtkWidget", "drag_data_delete",
779 "GdkDragContext *drag_context"},
780 {"GtkWidget", "drag_leave",
781 "GdkDragContext *drag_context",
783 {"GtkWidget", "drag_motion",
784 "GdkDragContext *drag_context",
788 {"GtkWidget", "drag_drop",
789 "GdkDragContext *drag_context",
793 {"GtkWidget", "drag_data_get",
794 "GdkDragContext *drag_context",
795 "GtkSelectionData *data",
798 {"GtkWidget", "drag_data_received",
799 "GdkDragContext *drag_context",
802 "GtkSelectionData *data",
811 for (i = 0; GbArgTable[i][0]; i++)
814 if (!strcmp (type, GbArgTable[i][0])
815 && !strcmp (signal_name, GbArgTable[i][1]))
816 return &GbArgTable[i][2];
822 /* This outputs the hierarchy of all objects which have been initialized,
823 i.e. by calling their XXX_get_type() initialization function. */
825 output_object_hierarchy (void)
830 fp = fopen (hierarchy_filename, "w");
833 g_warning ("Couldn't open output file: %s : %s", hierarchy_filename, g_strerror(errno));
836 output_hierarchy (fp, G_TYPE_OBJECT, 0);
837 output_hierarchy (fp, G_TYPE_INTERFACE, 0);
839 for (i=0; object_types[i]; i++) {
840 if (!g_type_parent (object_types[i]) &&
841 (object_types[i] != G_TYPE_OBJECT) &&
842 (object_types[i] != G_TYPE_INTERFACE)
844 output_hierarchy (fp, object_types[i], 0);
851 /* This is called recursively to output the hierarchy of a widget. */
853 output_hierarchy (FILE *fp,
864 for (i = 0; i < level; i++)
866 fprintf (fp, "%s\\n", g_type_name (type));
868 children = g_type_children (type, &n_children);
870 for (i=0; i < n_children; i++)
871 output_hierarchy (fp, children[i], level + 1);
876 static void output_object_interfaces (void)
881 fp = fopen (interfaces_filename, "w");
884 g_warning ("Couldn't open output file: %s : %s", interfaces_filename, g_strerror(errno));
887 output_interfaces (fp, G_TYPE_OBJECT);
889 for (i = 0; object_types[i]; i++)
891 if (!g_type_parent (object_types[i]) &&
892 (object_types[i] != G_TYPE_OBJECT) &&
893 G_TYPE_IS_INSTANTIATABLE (object_types[i]))
895 output_interfaces (fp, object_types[i]);
902 output_interfaces (FILE *fp,
906 GType *children, *interfaces;
907 guint n_children, n_interfaces;
912 interfaces = g_type_interfaces (type, &n_interfaces);
914 if (n_interfaces > 0)
916 fprintf (fp, "%s", g_type_name (type));
917 for (i=0; i < n_interfaces; i++)
918 fprintf (fp, " %s", g_type_name (interfaces[i]));
923 children = g_type_children (type, &n_children);
925 for (i=0; i < n_children; i++)
926 output_interfaces (fp, children[i]);
931 static void output_interface_prerequisites (void)
935 fp = fopen (prerequisites_filename, "w");
938 g_warning ("Couldn't open output file: %s : %s", prerequisites_filename, g_strerror(errno));
941 output_prerequisites (fp, G_TYPE_INTERFACE);
946 output_prerequisites (FILE *fp,
949 #if GLIB_CHECK_VERSION(2,1,0)
951 GType *children, *prerequisites;
952 guint n_children, n_prerequisites;
957 prerequisites = g_type_interface_prerequisites (type, &n_prerequisites);
959 if (n_prerequisites > 0)
961 fprintf (fp, "%s", g_type_name (type));
962 for (i=0; i < n_prerequisites; i++)
963 fprintf (fp, " %s", g_type_name (prerequisites[i]));
966 g_free (prerequisites);
968 children = g_type_children (type, &n_children);
970 for (i=0; i < n_children; i++)
971 output_prerequisites (fp, children[i]);
983 fp = fopen (args_filename, "w");
986 g_warning ("Couldn't open output file: %s : %s", args_filename, g_strerror(errno));
990 for (i = 0; object_types[i]; i++) {
991 output_object_args (fp, object_types[i]);
998 compare_param_specs (const void *a, const void *b)
1000 GParamSpec *spec_a = *(GParamSpec **)a;
1001 GParamSpec *spec_b = *(GParamSpec **)b;
1003 return strcmp (g_param_spec_get_name (spec_a), g_param_spec_get_name (spec_b));
1006 /* Its common to have unsigned properties restricted
1007 * to the signed range. Therefore we make this look
1008 * a bit nicer by spelling out the max constants.
1011 /* Don't use "==" with floats, it might trigger a gcc warning. */
1012 #define GTKDOC_COMPARE_FLOAT(x, y) (x <= y && x >= y)
1015 describe_double_constant (gdouble value)
1019 if (GTKDOC_COMPARE_FLOAT (value, G_MAXDOUBLE))
1020 desc = g_strdup ("G_MAXDOUBLE");
1021 else if (GTKDOC_COMPARE_FLOAT (value, G_MINDOUBLE))
1022 desc = g_strdup ("G_MINDOUBLE");
1023 else if (GTKDOC_COMPARE_FLOAT (value, -G_MAXDOUBLE))
1024 desc = g_strdup ("-G_MAXDOUBLE");
1025 else if (GTKDOC_COMPARE_FLOAT (value, G_MAXFLOAT))
1026 desc = g_strdup ("G_MAXFLOAT");
1027 else if (GTKDOC_COMPARE_FLOAT (value, G_MINFLOAT))
1028 desc = g_strdup ("G_MINFLOAT");
1029 else if (GTKDOC_COMPARE_FLOAT (value, -G_MAXFLOAT))
1030 desc = g_strdup ("-G_MAXFLOAT");
1032 desc = g_strdup_printf ("%lg", value);
1038 describe_signed_constant (gsize size, gint64 value)
1044 if (sizeof (int) == 2) {
1045 if (value == G_MAXINT)
1046 desc = g_strdup ("G_MAXINT");
1047 else if (value == G_MININT)
1048 desc = g_strdup ("G_MININT");
1049 else if (value == (gint64)G_MAXUINT)
1050 desc = g_strdup ("G_MAXUINT");
1054 if (sizeof (int) == 4) {
1055 if (value == G_MAXINT)
1056 desc = g_strdup ("G_MAXINT");
1057 else if (value == G_MININT)
1058 desc = g_strdup ("G_MININT");
1059 else if (value == (gint64)G_MAXUINT)
1060 desc = g_strdup ("G_MAXUINT");
1062 if (value == G_MAXLONG)
1063 desc = g_strdup ("G_MAXLONG");
1064 else if (value == G_MINLONG)
1065 desc = g_strdup ("G_MINLONG");
1066 else if (value == (gint64)G_MAXULONG)
1067 desc = g_strdup ("G_MAXULONG");
1070 if (value == G_MAXINT64)
1071 desc = g_strdup ("G_MAXINT64");
1072 else if (value == G_MININT64)
1073 desc = g_strdup ("G_MININT64");
1079 desc = g_strdup_printf ("%" G_GINT64_FORMAT, value);
1085 describe_unsigned_constant (gsize size, guint64 value)
1091 if (sizeof (int) == 2) {
1092 if (value == (guint64)G_MAXINT)
1093 desc = g_strdup ("G_MAXINT");
1094 else if (value == G_MAXUINT)
1095 desc = g_strdup ("G_MAXUINT");
1099 if (sizeof (int) == 4) {
1100 if (value == (guint64)G_MAXINT)
1101 desc = g_strdup ("G_MAXINT");
1102 else if (value == G_MAXUINT)
1103 desc = g_strdup ("G_MAXUINT");
1105 if (value == (guint64)G_MAXLONG)
1106 desc = g_strdup ("G_MAXLONG");
1107 else if (value == G_MAXULONG)
1108 desc = g_strdup ("G_MAXULONG");
1111 if (value == G_MAXINT64)
1112 desc = g_strdup ("G_MAXINT64");
1113 else if (value == G_MAXUINT64)
1114 desc = g_strdup ("G_MAXUINT64");
1120 desc = g_strdup_printf ("%" G_GUINT64_FORMAT, value);
1126 describe_type (GParamSpec *spec)
1132 if (G_IS_PARAM_SPEC_CHAR (spec))
1134 GParamSpecChar *pspec = G_PARAM_SPEC_CHAR (spec);
1136 lower = describe_signed_constant (sizeof(gchar), pspec->minimum);
1137 upper = describe_signed_constant (sizeof(gchar), pspec->maximum);
1138 if (pspec->minimum == G_MININT8 && pspec->maximum == G_MAXINT8)
1139 desc = g_strdup ("");
1140 else if (pspec->minimum == G_MININT8)
1141 desc = g_strdup_printf ("<= %s", upper);
1142 else if (pspec->maximum == G_MAXINT8)
1143 desc = g_strdup_printf (">= %s", lower);
1145 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1149 else if (G_IS_PARAM_SPEC_UCHAR (spec))
1151 GParamSpecUChar *pspec = G_PARAM_SPEC_UCHAR (spec);
1153 lower = describe_unsigned_constant (sizeof(guchar), pspec->minimum);
1154 upper = describe_unsigned_constant (sizeof(guchar), pspec->maximum);
1155 if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT8)
1156 desc = g_strdup ("");
1157 else if (pspec->minimum == 0)
1158 desc = g_strdup_printf ("<= %s", upper);
1159 else if (pspec->maximum == G_MAXUINT8)
1160 desc = g_strdup_printf (">= %s", lower);
1162 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1166 else if (G_IS_PARAM_SPEC_INT (spec))
1168 GParamSpecInt *pspec = G_PARAM_SPEC_INT (spec);
1170 lower = describe_signed_constant (sizeof(gint), pspec->minimum);
1171 upper = describe_signed_constant (sizeof(gint), pspec->maximum);
1172 if (pspec->minimum == G_MININT && pspec->maximum == G_MAXINT)
1173 desc = g_strdup ("");
1174 else if (pspec->minimum == G_MININT)
1175 desc = g_strdup_printf ("<= %s", upper);
1176 else if (pspec->maximum == G_MAXINT)
1177 desc = g_strdup_printf (">= %s", lower);
1179 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1183 else if (G_IS_PARAM_SPEC_UINT (spec))
1185 GParamSpecUInt *pspec = G_PARAM_SPEC_UINT (spec);
1187 lower = describe_unsigned_constant (sizeof(guint), pspec->minimum);
1188 upper = describe_unsigned_constant (sizeof(guint), pspec->maximum);
1189 if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT)
1190 desc = g_strdup ("");
1191 else if (pspec->minimum == 0)
1192 desc = g_strdup_printf ("<= %s", upper);
1193 else if (pspec->maximum == G_MAXUINT)
1194 desc = g_strdup_printf (">= %s", lower);
1196 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1200 else if (G_IS_PARAM_SPEC_LONG (spec))
1202 GParamSpecLong *pspec = G_PARAM_SPEC_LONG (spec);
1204 lower = describe_signed_constant (sizeof(glong), pspec->minimum);
1205 upper = describe_signed_constant (sizeof(glong), pspec->maximum);
1206 if (pspec->minimum == G_MINLONG && pspec->maximum == G_MAXLONG)
1207 desc = g_strdup ("");
1208 else if (pspec->minimum == G_MINLONG)
1209 desc = g_strdup_printf ("<= %s", upper);
1210 else if (pspec->maximum == G_MAXLONG)
1211 desc = g_strdup_printf (">= %s", lower);
1213 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1217 else if (G_IS_PARAM_SPEC_ULONG (spec))
1219 GParamSpecULong *pspec = G_PARAM_SPEC_ULONG (spec);
1221 lower = describe_unsigned_constant (sizeof(gulong), pspec->minimum);
1222 upper = describe_unsigned_constant (sizeof(gulong), pspec->maximum);
1223 if (pspec->minimum == 0 && pspec->maximum == G_MAXULONG)
1224 desc = g_strdup ("");
1225 else if (pspec->minimum == 0)
1226 desc = g_strdup_printf ("<= %s", upper);
1227 else if (pspec->maximum == G_MAXULONG)
1228 desc = g_strdup_printf (">= %s", lower);
1230 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1234 else if (G_IS_PARAM_SPEC_INT64 (spec))
1236 GParamSpecInt64 *pspec = G_PARAM_SPEC_INT64 (spec);
1238 lower = describe_signed_constant (sizeof(gint64), pspec->minimum);
1239 upper = describe_signed_constant (sizeof(gint64), pspec->maximum);
1240 if (pspec->minimum == G_MININT64 && pspec->maximum == G_MAXINT64)
1241 desc = g_strdup ("");
1242 else if (pspec->minimum == G_MININT64)
1243 desc = g_strdup_printf ("<= %s", upper);
1244 else if (pspec->maximum == G_MAXINT64)
1245 desc = g_strdup_printf (">= %s", lower);
1247 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1251 else if (G_IS_PARAM_SPEC_UINT64 (spec))
1253 GParamSpecUInt64 *pspec = G_PARAM_SPEC_UINT64 (spec);
1255 lower = describe_unsigned_constant (sizeof(guint64), pspec->minimum);
1256 upper = describe_unsigned_constant (sizeof(guint64), pspec->maximum);
1257 if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT64)
1258 desc = g_strdup ("");
1259 else if (pspec->minimum == 0)
1260 desc = g_strdup_printf ("<= %s", upper);
1261 else if (pspec->maximum == G_MAXUINT64)
1262 desc = g_strdup_printf (">= %s", lower);
1264 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1268 else if (G_IS_PARAM_SPEC_FLOAT (spec))
1270 GParamSpecFloat *pspec = G_PARAM_SPEC_FLOAT (spec);
1272 lower = describe_double_constant (pspec->minimum);
1273 upper = describe_double_constant (pspec->maximum);
1274 if (GTKDOC_COMPARE_FLOAT (pspec->minimum, -G_MAXFLOAT))
1276 if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXFLOAT))
1277 desc = g_strdup ("");
1279 desc = g_strdup_printf ("<= %s", upper);
1281 else if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXFLOAT))
1282 desc = g_strdup_printf (">= %s", lower);
1284 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1288 else if (G_IS_PARAM_SPEC_DOUBLE (spec))
1290 GParamSpecDouble *pspec = G_PARAM_SPEC_DOUBLE (spec);
1292 lower = describe_double_constant (pspec->minimum);
1293 upper = describe_double_constant (pspec->maximum);
1294 if (GTKDOC_COMPARE_FLOAT (pspec->minimum, -G_MAXDOUBLE))
1296 if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXDOUBLE))
1297 desc = g_strdup ("");
1299 desc = g_strdup_printf ("<= %s", upper);
1301 else if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXDOUBLE))
1302 desc = g_strdup_printf (">= %s", lower);
1304 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1308 #if GLIB_CHECK_VERSION (2, 12, 0)
1309 else if (G_IS_PARAM_SPEC_GTYPE (spec))
1311 GParamSpecGType *pspec = G_PARAM_SPEC_GTYPE (spec);
1312 gboolean is_pointer;
1314 desc = g_strdup (get_type_name (pspec->is_a_type, &is_pointer));
1317 #if GLIB_CHECK_VERSION (2, 25, 9)
1318 else if (G_IS_PARAM_SPEC_VARIANT (spec))
1320 GParamSpecVariant *pspec = G_PARAM_SPEC_VARIANT (spec);
1321 gchar *variant_type;
1323 variant_type = g_variant_type_dup_string (pspec->type);
1324 desc = g_strdup_printf ("GVariant<%s>", variant_type);
1325 g_free (variant_type);
1330 desc = g_strdup ("");
1337 describe_default (GParamSpec *spec)
1341 if (G_IS_PARAM_SPEC_CHAR (spec))
1343 GParamSpecChar *pspec = G_PARAM_SPEC_CHAR (spec);
1345 desc = g_strdup_printf ("%d", pspec->default_value);
1347 else if (G_IS_PARAM_SPEC_UCHAR (spec))
1349 GParamSpecUChar *pspec = G_PARAM_SPEC_UCHAR (spec);
1351 desc = g_strdup_printf ("%u", pspec->default_value);
1353 else if (G_IS_PARAM_SPEC_BOOLEAN (spec))
1355 GParamSpecBoolean *pspec = G_PARAM_SPEC_BOOLEAN (spec);
1357 desc = g_strdup_printf ("%s", pspec->default_value ? "TRUE" : "FALSE");
1359 else if (G_IS_PARAM_SPEC_INT (spec))
1361 GParamSpecInt *pspec = G_PARAM_SPEC_INT (spec);
1363 desc = g_strdup_printf ("%d", pspec->default_value);
1365 else if (G_IS_PARAM_SPEC_UINT (spec))
1367 GParamSpecUInt *pspec = G_PARAM_SPEC_UINT (spec);
1369 desc = g_strdup_printf ("%u", pspec->default_value);
1371 else if (G_IS_PARAM_SPEC_LONG (spec))
1373 GParamSpecLong *pspec = G_PARAM_SPEC_LONG (spec);
1375 desc = g_strdup_printf ("%ld", pspec->default_value);
1377 else if (G_IS_PARAM_SPEC_LONG (spec))
1379 GParamSpecULong *pspec = G_PARAM_SPEC_ULONG (spec);
1381 desc = g_strdup_printf ("%lu", pspec->default_value);
1383 else if (G_IS_PARAM_SPEC_INT64 (spec))
1385 GParamSpecInt64 *pspec = G_PARAM_SPEC_INT64 (spec);
1387 desc = g_strdup_printf ("%" G_GINT64_FORMAT, pspec->default_value);
1389 else if (G_IS_PARAM_SPEC_UINT64 (spec))
1391 GParamSpecUInt64 *pspec = G_PARAM_SPEC_UINT64 (spec);
1393 desc = g_strdup_printf ("%" G_GUINT64_FORMAT, pspec->default_value);
1395 else if (G_IS_PARAM_SPEC_UNICHAR (spec))
1397 GParamSpecUnichar *pspec = G_PARAM_SPEC_UNICHAR (spec);
1399 if (g_unichar_isprint (pspec->default_value))
1400 desc = g_strdup_printf ("'%c'", pspec->default_value);
1402 desc = g_strdup_printf ("%u", pspec->default_value);
1404 else if (G_IS_PARAM_SPEC_ENUM (spec))
1406 GParamSpecEnum *pspec = G_PARAM_SPEC_ENUM (spec);
1408 GEnumValue *value = g_enum_get_value (pspec->enum_class, pspec->default_value);
1410 desc = g_strdup_printf ("%s", value->value_name);
1412 desc = g_strdup_printf ("%d", pspec->default_value);
1414 else if (G_IS_PARAM_SPEC_FLAGS (spec))
1416 GParamSpecFlags *pspec = G_PARAM_SPEC_FLAGS (spec);
1417 guint default_value;
1420 default_value = pspec->default_value;
1421 acc = g_string_new ("");
1423 while (default_value)
1425 GFlagsValue *value = g_flags_get_first_value (pspec->flags_class, default_value);
1431 g_string_append (acc, "|");
1432 g_string_append (acc, value->value_name);
1434 default_value &= ~value->value;
1437 if (default_value == 0)
1438 desc = g_string_free (acc, FALSE);
1441 desc = g_strdup_printf ("%d", pspec->default_value);
1442 g_string_free (acc, TRUE);
1445 else if (G_IS_PARAM_SPEC_FLOAT (spec))
1447 GParamSpecFloat *pspec = G_PARAM_SPEC_FLOAT (spec);
1449 desc = g_strdup_printf ("%g", pspec->default_value);
1451 else if (G_IS_PARAM_SPEC_DOUBLE (spec))
1453 GParamSpecDouble *pspec = G_PARAM_SPEC_DOUBLE (spec);
1455 desc = g_strdup_printf ("%lg", pspec->default_value);
1457 else if (G_IS_PARAM_SPEC_STRING (spec))
1459 GParamSpecString *pspec = G_PARAM_SPEC_STRING (spec);
1461 if (pspec->default_value)
1463 gchar *esc = g_strescape (pspec->default_value, NULL);
1465 desc = g_strdup_printf ("\\"%s\\"", esc);
1470 desc = g_strdup_printf ("NULL");
1472 #if GLIB_CHECK_VERSION (2, 25, 9)
1473 else if (G_IS_PARAM_SPEC_VARIANT (spec))
1475 GParamSpecVariant *pspec = G_PARAM_SPEC_VARIANT (spec);
1477 if (pspec->default_value)
1478 desc = g_variant_print (pspec->default_value, TRUE);
1480 desc = g_strdup ("NULL");
1485 desc = g_strdup ("");
1493 output_object_args (FILE *fp, GType object_type)
1496 const gchar *object_class_name;
1498 gchar flags[16], *pos;
1499 GParamSpec **properties;
1501 gboolean child_prop;
1502 gboolean style_prop;
1503 gboolean is_pointer;
1504 const gchar *type_name;
1506 gchar *default_value;
1508 if (G_TYPE_IS_OBJECT (object_type))
1510 class = g_type_class_peek (object_type);
1514 properties = g_object_class_list_properties (class, &n_properties);
1516 #if GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 3)
1517 else if (G_TYPE_IS_INTERFACE (object_type))
1519 class = g_type_default_interface_ref (object_type);
1524 properties = g_object_interface_list_properties (class, &n_properties);
1530 object_class_name = g_type_name (object_type);
1536 qsort (properties, n_properties, sizeof (GParamSpec *), compare_param_specs);
1537 for (arg = 0; arg < n_properties; arg++)
1539 GParamSpec *spec = properties[arg];
1540 const gchar *nick, *blurb, *dot;
1542 if (spec->owner_type != object_type)
1546 /* We use one-character flags for simplicity. */
1547 if (child_prop && !style_prop)
1551 if (spec->flags & G_PARAM_READABLE)
1553 if (spec->flags & G_PARAM_WRITABLE)
1555 if (spec->flags & G_PARAM_CONSTRUCT)
1557 if (spec->flags & G_PARAM_CONSTRUCT_ONLY)
1561 nick = g_param_spec_get_nick (spec);
1562 blurb = g_param_spec_get_blurb (spec);
1566 int str_len = strlen (blurb);
1567 if (str_len > 0 && blurb[str_len - 1] != '.')
1571 type_desc = describe_type (spec);
1572 default_value = describe_default (spec);
1573 type_name = get_type_name (spec->value_type, &is_pointer);
1574 fprintf (fp, "<ARG>\\n<NAME>%s::%s</NAME>\\n<TYPE>%s%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",
1575 object_class_name, g_param_spec_get_name (spec), type_name, is_pointer ? "*" : "", type_desc, flags, nick ? nick : "(null)", blurb ? blurb : "(null)", dot, default_value);
1577 g_free (default_value);
1580 g_free (properties);
1582 #ifdef GTK_IS_CONTAINER_CLASS
1583 if (!child_prop && GTK_IS_CONTAINER_CLASS (class)) {
1584 properties = gtk_container_class_list_child_properties (class, &n_properties);
1590 #ifdef GTK_IS_WIDGET_CLASS
1591 #if GTK_CHECK_VERSION(2,1,0)
1592 if (!style_prop && GTK_IS_WIDGET_CLASS (class)) {
1593 properties = gtk_widget_class_list_style_properties (GTK_WIDGET_CLASS (class), &n_properties);
1602 if ($QUERY_CHILD_PROPERTIES) {
1605 properties = $QUERY_CHILD_PROPERTIES (class, &n_properties);
1623 # Compile and run our file
1625 $CC = $ENV{CC} ? $ENV{CC} : "gcc";
1626 $LD = $ENV{LD} ? $ENV{LD} : $CC;
1627 $CFLAGS = $ENV{CFLAGS} ? $ENV{CFLAGS} : "";
1628 $LDFLAGS = $ENV{LDFLAGS} ? $ENV{LDFLAGS} : "";
1629 $RUN = $ENV{RUN} ? $ENV{RUN} : "";
1632 if ($CC =~ /libtool/) {
1633 $o_file = "$MODULE-scan.lo"
1635 $o_file = "$MODULE-scan.o"
1638 print "gtk-doc: Compiling scanner\n";
1639 $command = "$CC $CFLAGS -c -o $o_file $MODULE-scan.c";
1640 system("($command)") == 0 or die "Compilation of scanner failed: $!\n";
1642 print "gtk-doc: Linking scanner\n";
1643 # FIXME: Can we turn off as-needed for the docs (or better fix it?)
1644 #$command = "$LD -Wl,--no-as-needed $o_file $LDFLAGS -o $MODULE-scan";
1645 $command = "$LD $o_file $LDFLAGS -o $MODULE-scan";
1646 system("($command)") == 0 or die "Linking of scanner failed: $!\n";
1648 print "gtk-doc: Running scanner $MODULE-scan\n";
1649 system("($RUN ./$MODULE-scan)") == 0 or die "Scan failed: $!\n";
1652 if (!defined($ENV{"GTK_DOC_KEEP_INTERMEDIATE"})) {
1653 unlink "./$MODULE-scan.c", "./$MODULE-scan.o", "./$MODULE-scan.lo", "./$MODULE-scan";
1656 &UpdateFileIfChanged ($old_signals_filename, $new_signals_filename, 0);
1657 &UpdateFileIfChanged ($old_hierarchy_filename, $new_hierarchy_filename, 0);
1658 &UpdateFileIfChanged ($old_interfaces_filename, $new_interfaces_filename, 0);
1659 &UpdateFileIfChanged ($old_prerequisites_filename, $new_prerequisites_filename, 0);
1660 &UpdateFileIfChanged ($old_args_filename, $new_args_filename, 0);