[monkey-bubble: 182/753] Use `LIBGNOME_*DIR' instead of `GNOME*DIR'.



commit 04c7314bb5e49c991d0fe7cdddb7e2cdffd2ab62
Author: Martin Baulig <baulig suse de>
Date:   Sat Apr 21 13:36:30 2001 +0000

    Use `LIBGNOME_*DIR' instead of `GNOME*DIR'.
    
    2001-04-21  Martin Baulig  <baulig suse de>
    
    	* Makefile.am (INCLUDES): Use `LIBGNOME_*DIR' instead of `GNOME*DIR'.
    
    	* gnome-program.[ch]: Put this back.
    
    	* gnome-i18n.h: Put this back.
    
    	* *.[ch]: Don't #include <libgnomebase/gnome-portability.h>.

 libgnome/ChangeLog       |   10 +
 libgnome/Makefile.am     |   18 +-
 libgnome/gnome-ditem.c   |    1 -
 libgnome/gnome-exec.c    |    1 -
 libgnome/gnome-i18n.h    |   69 +++
 libgnome/gnome-i18nP.h   |    2 +-
 libgnome/gnome-init.c    |    2 +-
 libgnome/gnome-init.h    |    2 +-
 libgnome/gnome-paper.c   |    2 +-
 libgnome/gnome-program.c | 1367 ++++++++++++++++++++++++++++++++++++++++++++++
 libgnome/gnome-program.h |  209 +++++++
 libgnome/gnome-url.c     |    1 -
 libgnome/gnome-util.c    |    3 +-
 libgnome/gnome-util.h    |    2 +-
 libgnome/libgnome.h      |    3 +-
 libgnome/libgnomeP.h     |    1 -
 16 files changed, 1673 insertions(+), 20 deletions(-)
---
diff --git a/libgnome/ChangeLog b/libgnome/ChangeLog
index 226c618..10614f6 100644
--- a/libgnome/ChangeLog
+++ b/libgnome/ChangeLog
@@ -1,3 +1,13 @@
+2001-04-21  Martin Baulig  <baulig suse de>
+
+	* Makefile.am (INCLUDES): Use `LIBGNOME_*DIR' instead of `GNOME*DIR'.
+
+	* gnome-program.[ch]: Put this back.
+
+	* gnome-i18n.h: Put this back.
+
+	* *.[ch]: Don't #include <libgnomebase/gnome-portability.h>.
+
 2001-04-20  Martin Baulig  <baulig suse de>
 
 	* libgnome-init.c (gnome_oaf_module_info): Put this back.
diff --git a/libgnome/Makefile.am b/libgnome/Makefile.am
index 7715ccc..d515a5c 100644
--- a/libgnome/Makefile.am
+++ b/libgnome/Makefile.am
@@ -24,18 +24,19 @@ INCLUDES = \
 	$(LIBXML_CFLAGS)			\
 	$(GNOME_VFS_CFLAGS)			\
 	$(LIBBONOBO_CFLAGS)			\
-	-DGNOMEPREFIX=\""$(prefix)"\"		\
-	-DGNOMELIBDIR=\""$(libdir)"\"		\
-	-DGNOMEDATADIR=\""$(datadir)"\"		\
-	-DGNOMEBINDIR=\""$(bindir)"\"		\
-	-DGNOMELOCALSTATEDIR=\""$(localstatedir)"\" \
-	-DGNOMELOCALEDIR=\""$(gnomelocaledir)"\" \
-	-DGNOMESYSCONFDIR=\""$(sysconfdir)"\"	\
-	-DVERSION=\""$(VERSION)"\"		\
+	-DLIBGNOME_PREFIX=\""$(prefix)"\"		\
+	-DLIBGNOME_LIBDIR=\""$(libdir)"\"		\
+	-DLIBGNOME_DATADIR=\""$(datadir)"\"		\
+	-DLIBGNOME_BINDIR=\""$(bindir)"\"		\
+	-DLIBGNOME_LOCALSTATEDIR=\""$(localstatedir)"\" \
+	-DLIBGNOME_LOCALEDIR=\""$(gnomelocaledir)"\"	\
+	-DLIBGNOME_SYSCONFDIR=\""$(sysconfdir)"\"	\
+	-DVERSION=\""$(VERSION)"\"			\
 	-DGNOMEVFSVERSION=\""$(GNOME_VFS_VERSION)"\" \
 	-DG_LOG_DOMAIN=\"Gnome\"
 
 libgnome_2_la_SOURCES = \
+	gnome-program.c		\
 	gnome-config.c		\
 	gnome-ditem.c		\
 	gnome-exec.c		\
@@ -52,6 +53,7 @@ libgnome_2_la_SOURCES = \
 	libgnometypes.c
 
 libgnome_headers = \
+	gnome-program.h		\
         gnome-config.h 		\
 	gnome-fileconvert.h	\
 	gnome-ditem.h		\
diff --git a/libgnome/gnome-ditem.c b/libgnome/gnome-ditem.c
index 5b82e95..24e7fed 100644
--- a/libgnome/gnome-ditem.c
+++ b/libgnome/gnome-ditem.c
@@ -42,7 +42,6 @@
 #include <time.h>
 #include <string.h>
 #include "libgnomeP.h"
-#include <libgnomebase/gnome-portability.h>
 #include "gnome-ditem.h"
 #include "gnome-util.h"
 #include "gnome-config.h"
diff --git a/libgnome/gnome-exec.c b/libgnome/gnome-exec.c
index db933ed..49e7bb5 100644
--- a/libgnome/gnome-exec.c
+++ b/libgnome/gnome-exec.c
@@ -26,7 +26,6 @@
 #endif
 
 #include "gnome-exec.h"
-#include <libgnomebase/gnome-portability.h>
 #include "gnome-util.h"
 #include "gnome-config.h"
 #include "gnome-i18nP.h"
diff --git a/libgnome/gnome-i18n.h b/libgnome/gnome-i18n.h
new file mode 100644
index 0000000..9fde70f
--- /dev/null
+++ b/libgnome/gnome-i18n.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation
+ * All rights reserved.
+ *
+ * This file is part of the Gnome Library.
+ *
+ * The Gnome Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * The Gnome Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the Gnome Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+/*
+  @NOTATION@
+ */
+
+/*
+ * Handles all of the internationalization configuration options.
+ * Author: Tom Tromey <tromey creche cygnus com>
+ */
+
+#ifndef __LIBGNOME_I18N_H__
+#define __LIBGNOME_I18N_H__ 1
+
+#include <glib.h>
+
+
+G_BEGIN_DECLS
+
+#if !defined(__LIBGNOME_I18NP_H__)
+
+#ifdef ENABLE_NLS
+#    include <libintl.h>
+#    ifdef GNOME_EXPLICIT_TRANSLATION_DOMAIN
+#        undef _
+#        define _(String) dgettext (GNOME_EXPLICIT_TRANSLATION_DOMAIN, String)
+#    else 
+#        define _(String) gettext (String)
+#    endif
+#    ifdef gettext_noop
+#        define N_(String) gettext_noop (String)
+#    else
+#        define N_(String) (String)
+#    endif
+#else
+/* Stubs that do something close enough.  */
+#    define textdomain(String) (String)
+#    define gettext(String) (String)
+#    define dgettext(Domain,Message) (Message)
+#    define dcgettext(Domain,Message,Type) (Message)
+#    define bindtextdomain(Domain,Directory) (Domain)
+#    define _(String) (String)
+#    define N_(String) (String)
+#endif
+
+#endif
+
+G_END_DECLS
+
+#endif /* __LIBGNOME_I18N_H__ */
diff --git a/libgnome/gnome-i18nP.h b/libgnome/gnome-i18nP.h
index d53064e..4dbdbfc 100644
--- a/libgnome/gnome-i18nP.h
+++ b/libgnome/gnome-i18nP.h
@@ -32,7 +32,7 @@
 #ifndef __GNOME_I18NP_H__
 #define __GNOME_I18NP_H__ 1
 
-#include <libgnomebase/gnome-i18n.h>
+#include <libgnome/gnome-i18n.h>
 
 G_BEGIN_DECLS
 
diff --git a/libgnome/gnome-init.c b/libgnome/gnome-init.c
index 722b79e..e3e4ca7 100644
--- a/libgnome/gnome-init.c
+++ b/libgnome/gnome-init.c
@@ -370,7 +370,7 @@ libgnome_post_args_parse (GnomeProgram *program,
 
     setlocale (LC_ALL, "");
     /* XXX todo - handle multiple installation dirs */
-    bindtextdomain (PACKAGE, GNOMELOCALEDIR);
+    bindtextdomain (PACKAGE, LIBGNOME_LOCALEDIR);
     gnome_i18n_init ();
 }
 
diff --git a/libgnome/gnome-init.h b/libgnome/gnome-init.h
index 1e4163f..104ed67 100644
--- a/libgnome/gnome-init.h
+++ b/libgnome/gnome-init.h
@@ -26,7 +26,7 @@
 #ifndef LIBGNOMEINIT_H
 #define LIBGNOMEINIT_H
 
-#include <libgnomebase/gnome-program.h>
+#include <libgnome/gnome-program.h>
 
 #include <gconf/gconf-client.h>
 
diff --git a/libgnome/gnome-paper.c b/libgnome/gnome-paper.c
index 5f708ac..5439a38 100644
--- a/libgnome/gnome-paper.c
+++ b/libgnome/gnome-paper.c
@@ -77,7 +77,7 @@ paper_init (void)
   gnome_config_push_prefix (NULL);
   
   config_iterator =
-    gnome_config_init_iterator("="GNOMESYSCONFDIR"/paper.config=/Paper/");
+    gnome_config_init_iterator("="LIBGNOME_SYSCONFDIR"/paper.config=/Paper/");
   gnome_config_pop_prefix ();
   
   if (!config_iterator)
diff --git a/libgnome/gnome-program.c b/libgnome/gnome-program.c
new file mode 100644
index 0000000..0bd8a7b
--- /dev/null
+++ b/libgnome/gnome-program.c
@@ -0,0 +1,1367 @@
+
+/*
+ * Copyright (C) 1999, 2000 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This file is part of the Gnome Library.
+ *
+ * The Gnome Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * The Gnome Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the Gnome Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+/*
+  @NOTATION@
+ */
+
+
+/* This module takes care of handling application and library
+   initialization and command line parsing */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gmodule.h>
+#include <libgnome/gnome-program.h>
+#include <libgnome/gnome-i18n.h>
+
+#include "libgnomeP.h"
+
+#include <gobject/gboxed.h>
+#include <gobject/gvaluearray.h>
+#include <gobject/gvaluetypes.h>
+#include <gobject/gparamspecs.h>
+
+struct _GnomeProgramPrivate {
+    enum {
+	APP_UNINIT=0,
+	APP_CREATE_DONE=1,
+	APP_PREINIT_DONE=2,
+	APP_POSTINIT_DONE=3
+    } state;
+
+    /* Construction properties */
+    GnomeModuleInfo *prop_module_info;
+    gchar *prop_module_list;
+    int prop_popt_flags;
+    struct poptOptions *prop_popt_table;
+    gchar *prop_human_readable_name;
+    gchar *prop_app_prefix;
+    gchar *prop_app_libdir;
+    gchar *prop_app_sysconfdir;
+    gchar *prop_app_datadir;
+    gboolean prop_create_directories;
+
+    gchar **gnome_path;
+
+    /* valid-while: state > APP_CREATE_DONE */
+    char *app_id;
+    char *app_version;
+    char **argv;
+    int argc;
+
+    /* valid-while: state == APP_PREINIT_DONE */
+    poptContext arg_context;
+
+    /* valid-while: state == APP_PREINIT_DONE */
+    struct poptOptions *app_options;
+
+    /* valid-while: state == APP_PREINIT_DONE */
+    int app_popt_flags;
+
+    /* valid-while: state == APP_PREINIT_DONE */
+    GArray *top_options_table;
+};
+
+enum {
+    PROP_0,
+    PROP_MODULE_INFO,
+    PROP_MODULES,
+    PROP_APP_ID,
+    PROP_APP_VERSION,
+    PROP_HUMAN_READABLE_NAME,
+    PROP_GNOME_PATH,
+    PROP_APP_PREFIX,
+    PROP_APP_LIBDIR,
+    PROP_APP_DATADIR,
+    PROP_APP_SYSCONFDIR,
+    PROP_CREATE_DIRECTORIES,
+    PROP_POPT_TABLE,
+    PROP_POPT_FLAGS,
+    PROP_POPT_CONTEXT,
+    PROP_LAST
+};
+
+static void gnome_program_class_init    (GnomeProgramClass *klass);
+static void gnome_program_instance_init (GnomeProgram      *program);
+static void gnome_program_finalize      (GObject           *object);
+
+static GQuark quark_get_prop = 0;
+static GQuark quark_set_prop = 0;
+
+static GPtrArray *program_modules = NULL;
+static GPtrArray *program_module_list = NULL;
+static gboolean program_initialized = FALSE;
+static GnomeProgram *global_program = NULL;
+
+static guint last_property_id = PROP_LAST;
+static gpointer parent_class = NULL;
+
+#define	PREALLOC_CPARAMS (8)
+#define	PREALLOC_MODINFOS (8)
+
+GType
+gnome_program_get_type (void)
+{
+    static GType program_type = 0;
+
+    if (!program_type) {
+	static const GTypeInfo program_info = {
+	    sizeof (GnomeProgramClass),
+	    (GBaseInitFunc)         NULL,
+	    (GBaseFinalizeFunc)     NULL,
+	    (GClassInitFunc)        gnome_program_class_init,
+	    NULL,                   /* class_finalize */
+	    NULL,                   /* class_data */
+	    sizeof (GnomeProgram),
+	    0,                      /* n_preallocs */
+	    (GInstanceInitFunc)     gnome_program_instance_init
+	};
+
+	program_type = g_type_register_static
+	    (G_TYPE_OBJECT, "GnomeProgram", &program_info, 0);
+    }
+
+    return program_type;
+}
+
+static void
+gnome_program_set_property (GObject *object, guint param_id,
+			    const GValue *value, GParamSpec *pspec)
+{
+    GnomeProgram *program;
+
+    g_return_if_fail (object != NULL);
+    g_return_if_fail (GNOME_IS_PROGRAM (object));
+
+    program = GNOME_PROGRAM (object);
+
+    switch (param_id) {
+    case PROP_MODULE_INFO:
+	program->_priv->prop_module_info = g_value_dup_boxed ((GValue *) value);
+	break;
+    case PROP_MODULES:
+	program->_priv->prop_module_list = g_value_dup_string (value);
+	break;
+    case PROP_POPT_TABLE:
+	program->_priv->prop_popt_table = g_value_peek_pointer (value);
+	break;
+    case PROP_POPT_FLAGS:
+	program->_priv->prop_popt_flags = g_value_get_int (value);
+	break;
+    case PROP_HUMAN_READABLE_NAME:
+	program->_priv->prop_human_readable_name = g_value_dup_string (value);
+	break;
+    case PROP_GNOME_PATH:
+	if (program->_priv->gnome_path) {
+	    g_strfreev (program->_priv->gnome_path);
+	    program->_priv->gnome_path = NULL;
+	}
+	if (g_value_get_string (value))
+	    program->_priv->gnome_path = g_strsplit
+		(g_value_get_string (value), ":", -1);
+	break;
+    case PROP_APP_PREFIX:
+	program->_priv->prop_app_prefix = g_value_dup_string (value);
+	break;
+    case PROP_APP_SYSCONFDIR:
+	program->_priv->prop_app_sysconfdir = g_value_dup_string (value);
+	break;
+    case PROP_APP_DATADIR:
+	program->_priv->prop_app_datadir = g_value_dup_string (value);
+	break;
+    case PROP_APP_LIBDIR:
+	program->_priv->prop_app_libdir = g_value_dup_string (value);
+	break;
+    case PROP_CREATE_DIRECTORIES:
+	program->_priv->prop_create_directories = g_value_get_boolean (value);
+	break;
+    default: {
+	    GObjectSetPropertyFunc set_func;
+
+	    set_func = g_param_spec_get_qdata (pspec, quark_set_prop);
+	    if (set_func)
+		set_func (object, param_id, value, pspec);
+	    else
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+
+	    break;
+	}
+    }
+}
+
+static void
+gnome_program_get_property (GObject *object, guint param_id, GValue *value,
+			    GParamSpec *pspec)
+{
+    GnomeProgram *program;
+
+    g_return_if_fail (object != NULL);
+    g_return_if_fail (GNOME_IS_PROGRAM (object));
+
+    program = GNOME_PROGRAM (object);
+
+    switch (param_id) {
+    case PROP_APP_ID:
+	g_value_set_string (value, program->_priv->app_id);
+	break;
+    case PROP_APP_VERSION:
+	g_value_set_string (value, program->_priv->app_version);
+	break;
+    case PROP_HUMAN_READABLE_NAME:
+	g_value_set_string (value, program->_priv->prop_human_readable_name);
+	break;
+    case PROP_GNOME_PATH:
+	if (program->_priv->gnome_path)
+	    g_value_set_string (value, g_strjoinv (":", program->_priv->gnome_path));
+	else
+	    g_value_set_string (value, NULL);
+	break;
+    case PROP_APP_PREFIX:
+	g_value_set_string (value, program->_priv->prop_app_prefix);
+	break;
+    case PROP_APP_SYSCONFDIR:
+	g_value_set_string (value, program->_priv->prop_app_sysconfdir);
+	break;
+    case PROP_APP_DATADIR:
+	g_value_set_string (value, program->_priv->prop_app_datadir);
+	break;
+    case PROP_APP_LIBDIR:
+	g_value_set_string (value, program->_priv->prop_app_libdir);
+	break;
+    case PROP_CREATE_DIRECTORIES:
+	g_value_set_boolean (value, program->_priv->prop_create_directories);
+	break;
+    default: {
+	    GObjectSetPropertyFunc get_func;
+
+	    get_func = g_param_spec_get_qdata (pspec, quark_get_prop);
+	    if (get_func)
+		get_func (object, param_id, value, pspec);
+	    else
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+
+	    break;
+	}
+    }
+}
+
+static void
+add_to_module_list (const gchar *module_name)
+{
+    char **modnames;
+    int i, j;
+
+    if (!module_name)
+	return;
+
+    if (!program_module_list)
+	program_module_list = g_ptr_array_new ();
+
+    modnames = g_strsplit (module_name, ",", -1);
+    for (i = 0; modnames && modnames[i]; i++) {
+	for (j = 0; j < program_module_list->len; j++)
+	    if (!strcmp (modnames[i], g_ptr_array_index (program_module_list, j)))
+		return;
+
+	g_ptr_array_add (program_module_list, g_strdup (modnames[i]));
+    }
+    g_strfreev (modnames);
+}
+
+static int
+find_module_in_array (GnomeModuleInfo *ptr, GnomeModuleInfo **array)
+{
+    int i;
+
+    for (i = 0; array[i] && array[i] != ptr; i++) {
+	if (!strcmp(array[i]->name, ptr->name))
+	    break;
+    }
+
+    if (array[i])
+	return i;
+    else
+	return -1;
+}
+
+static void /* recursive */
+gnome_program_module_addtolist (GnomeModuleInfo **new_list,
+				int *times_visited,
+				int *num_items_used,
+				int new_item_idx)
+{
+    GnomeModuleInfo *new_item;
+    int i;
+
+    g_assert (new_item >= 0);
+
+    new_item = g_ptr_array_index (program_modules, new_item_idx);
+    if(!new_item)
+	return;
+
+    if (find_module_in_array (new_item, new_list) >= 0)
+	return; /* already cared for */
+
+    /* Does this item have any dependencies? */
+    if (times_visited[new_item_idx] > 0) {
+	/* We already tried to satisfy all the dependencies for this module,
+	 *  and we've come back to it again. There's obviously a loop going on.
+	 */
+	g_error ("Module '%s' version '%s' has a requirements loop.",
+		 new_item->name, new_item->version);
+    }
+    times_visited[new_item_idx]++;
+
+    if (new_item->requirements) {
+	for (i = 0; new_item->requirements[i].required_version; i++) {
+	    int n;
+
+	    n = find_module_in_array (new_item->requirements[i].module_info,
+				      (GnomeModuleInfo **)program_modules->pdata);
+	    gnome_program_module_addtolist
+		(new_list, times_visited, num_items_used, n);
+	}
+    }
+
+    /* now add this module on */
+    new_list[*num_items_used] = new_item;
+    (*num_items_used)++;
+    new_list[*num_items_used] = NULL;
+}
+
+static void
+gnome_program_module_list_order (void)
+{
+    int i;
+    GnomeModuleInfo **new_list;
+    int *times_visited; /* Detects dependency loops */
+    int num_items_used;
+
+    new_list = alloca (program_modules->len * sizeof(gpointer));
+    new_list[0] = NULL;
+    num_items_used = 0;
+  
+    times_visited = alloca (program_modules->len * sizeof(int));
+    memset(times_visited, '\0', program_modules->len * sizeof(int));
+
+    /* Create the new list with proper ordering */
+    for(i = 0; i < (program_modules->len - 1); i++) {
+	gnome_program_module_addtolist (new_list, times_visited,
+					&num_items_used, i);
+    }
+
+    /* Now stick the new, ordered list in place */
+    memcpy (program_modules->pdata, new_list,
+	    program_modules->len * sizeof(gpointer));
+}
+
+static GObject*
+gnome_program_constructor (GType type, guint n_construct_properties,
+			   GObjectConstructParam *construct_properties)
+{
+    GnomeProgram *program = NULL;
+    GnomeModuleInfo *module_info = NULL;
+    GObjectConstructParam *cparams = NULL;
+    guint n_modinfos = 0, n_cparams = 0, i;
+
+    if (!program_module_list)
+	program_module_list = g_ptr_array_new ();
+
+    if (!program_modules)
+	program_modules = g_ptr_array_new ();
+
+    /*
+     * First walk the list of construction properties and sort out
+     * GNOME_PARAM_MODULES and GNOME_PARAM_MODULE_INFO; we need to
+     * handle this here so we can load the modules before we create
+     * the GnomeProgram object.
+     */
+
+    for (i = 0; i < n_construct_properties; i++) {
+	GValue *value = construct_properties[i].value;
+	GParamSpec *pspec = construct_properties[i].pspec;
+
+	if (!strcmp (pspec->name, GNOME_PARAM_MODULES)) {
+	    if (program_initialized)
+		g_warning (G_STRLOC ": cannot use construction property \"%s\" "
+			   "when program is already initialized", pspec->name);
+	    else
+		add_to_module_list (g_value_get_string (value));
+	} else if (!strcmp (pspec->name, GNOME_PARAM_MODULE_INFO)) {
+	    if (!n_modinfos || n_modinfos >= PREALLOC_MODINFOS)
+		module_info = g_renew (GnomeModuleInfo, module_info,
+				       MAX (n_modinfos + 1, PREALLOC_MODINFOS));
+	    module_info[n_modinfos] = * (GnomeModuleInfo *)
+		g_value_get_boxed (value);
+	    n_modinfos++;
+	} else {
+	    if (!n_cparams || n_cparams >= PREALLOC_CPARAMS)
+		cparams = g_renew (GObjectConstructParam, cparams,
+				   MAX (n_cparams + 1, PREALLOC_CPARAMS));
+	    cparams[n_cparams].pspec = pspec;
+	    cparams[n_cparams].value = value;
+	    n_cparams++;
+	}
+    }
+
+    if (!program_initialized) {
+	/*
+	 * Load all the modules.
+	 */
+
+	for (i = 0; i < n_modinfos; i++)
+	    gnome_program_module_register (&module_info[i]);
+
+	for (i = 0; i < program_module_list->len; i++) {
+	    gchar *modname = g_ptr_array_index (program_module_list, i);
+
+	    gnome_program_module_load (modname);
+	}
+
+	for (i = 0; i < program_modules->len; i++) {
+	    GnomeModuleInfo *a_module = g_ptr_array_index (program_modules, i);
+
+	    if (a_module && a_module->init_pass)
+		a_module->init_pass (a_module);
+	}
+
+	/* Make sure the array is NULL-terminated */
+	g_ptr_array_add (program_modules, NULL);
+
+	/* 2. Order the module list for dependencies */
+	gnome_program_module_list_order ();
+
+	for (i = 0; i < program_modules->len; i++) {
+	    GnomeModuleInfo *a_module = g_ptr_array_index (program_modules, i);
+
+	    if (a_module && a_module->constructor)
+		a_module->constructor (type, n_cparams, cparams, a_module);
+	}
+    }
+
+    program = (GnomeProgram *) G_OBJECT_CLASS (parent_class)->constructor
+	(type, n_cparams, cparams);
+
+    if (!program_initialized) {
+	global_program = program;
+	g_object_ref (G_OBJECT (global_program));
+
+	program_initialized = TRUE;
+    }
+
+    return G_OBJECT (program);
+}
+
+static void
+gnome_program_class_init (GnomeProgramClass *class)
+{
+    GObjectClass *object_class;
+
+    object_class = (GObjectClass*) class;
+    parent_class = g_type_class_peek_parent (class);
+
+    quark_set_prop = g_quark_from_static_string ("gnome-program-set-property");
+    quark_get_prop = g_quark_from_static_string ("gnome-program-g-property");
+
+    object_class->constructor = gnome_program_constructor;
+    object_class->set_property = gnome_program_set_property;
+    object_class->get_property = gnome_program_get_property;
+
+    g_object_class_install_property
+	(object_class,
+	 PROP_MODULE_INFO,
+	 g_param_spec_boxed (GNOME_PARAM_MODULE_INFO, NULL, NULL,
+			     GNOME_TYPE_MODULE_INFO,
+			     (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)));
+
+    g_object_class_install_property
+	(object_class,
+	 PROP_MODULES,
+	 g_param_spec_string (GNOME_PARAM_MODULES, NULL, NULL,
+			      NULL,
+			      (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)));
+
+    g_object_class_install_property
+	(object_class,
+	 PROP_POPT_TABLE,
+	 g_param_spec_pointer (GNOME_PARAM_POPT_TABLE, NULL, NULL,
+			       (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)));
+
+    g_object_class_install_property
+	(object_class,
+	 PROP_POPT_FLAGS,
+	 g_param_spec_int (GNOME_PARAM_POPT_FLAGS, NULL, NULL,
+			   G_MININT, G_MAXINT, 0,
+			   (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)));
+
+    g_object_class_install_property
+	(object_class,
+	 PROP_POPT_CONTEXT,
+	 g_param_spec_pointer (GNOME_PARAM_POPT_CONTEXT, NULL, NULL,
+			       (G_PARAM_READABLE)));
+
+    g_object_class_install_property
+	(object_class,
+	 PROP_HUMAN_READABLE_NAME,
+	 g_param_spec_string (GNOME_PARAM_HUMAN_READABLE_NAME, NULL, NULL,
+			      NULL,
+			      (G_PARAM_READABLE | G_PARAM_WRITABLE |
+			       G_PARAM_CONSTRUCT_ONLY)));
+
+    g_object_class_install_property
+	(object_class,
+	 PROP_GNOME_PATH,
+	 g_param_spec_string (GNOME_PARAM_GNOME_PATH, NULL, NULL,
+			      g_getenv ("GNOME2_PATH"),
+			      (G_PARAM_READABLE | G_PARAM_WRITABLE |
+			       G_PARAM_CONSTRUCT_ONLY)));
+
+    g_object_class_install_property
+	(object_class,
+	 PROP_APP_ID,
+	 g_param_spec_string (GNOME_PARAM_APP_ID, NULL, NULL,
+			      NULL, G_PARAM_READABLE));
+
+    g_object_class_install_property
+	(object_class,
+	 PROP_APP_VERSION,
+	 g_param_spec_string (GNOME_PARAM_APP_VERSION, NULL, NULL,
+			      NULL, G_PARAM_READABLE));
+
+    g_object_class_install_property
+	(object_class,
+	 PROP_APP_PREFIX,
+	 g_param_spec_string (GNOME_PARAM_APP_PREFIX, NULL, NULL,
+			      LIBGNOME_PREFIX,
+			      (G_PARAM_READABLE | G_PARAM_WRITABLE |
+			       G_PARAM_CONSTRUCT_ONLY)));
+
+    g_object_class_install_property
+	(object_class,
+	 PROP_APP_LIBDIR,
+	 g_param_spec_string (GNOME_PARAM_APP_LIBDIR, NULL, NULL,
+			      LIBGNOME_LIBDIR,
+			      (G_PARAM_READABLE | G_PARAM_WRITABLE |
+			       G_PARAM_CONSTRUCT_ONLY)));
+
+    g_object_class_install_property
+	(object_class,
+	 PROP_APP_DATADIR,
+	 g_param_spec_string (GNOME_PARAM_APP_DATADIR, NULL, NULL,
+			      LIBGNOME_DATADIR,
+			      (G_PARAM_READABLE | G_PARAM_WRITABLE |
+			       G_PARAM_CONSTRUCT_ONLY)));
+
+    g_object_class_install_property
+	(object_class,
+	 PROP_APP_SYSCONFDIR,
+	 g_param_spec_string (GNOME_PARAM_APP_SYSCONFDIR, NULL, NULL,
+			      LIBGNOME_SYSCONFDIR,
+			      (G_PARAM_READABLE | G_PARAM_WRITABLE |
+			       G_PARAM_CONSTRUCT_ONLY)));
+
+    g_object_class_install_property
+	(object_class,
+	 PROP_CREATE_DIRECTORIES,
+	 g_param_spec_boolean (GNOME_PARAM_CREATE_DIRECTORIES, NULL, NULL,
+			       TRUE,
+			       (G_PARAM_READABLE | G_PARAM_WRITABLE |
+				G_PARAM_CONSTRUCT_ONLY)));
+
+    object_class->finalize  = gnome_program_finalize;
+}
+
+static void
+gnome_program_instance_init (GnomeProgram *program)
+{
+    program->_priv = g_new0 (GnomeProgramPrivate, 1);
+
+    program->_priv->state = APP_CREATE_DONE;
+}
+
+static void
+gnome_program_finalize (GObject* object)
+{
+    GnomeProgram *program = GNOME_PROGRAM (object);
+
+    g_free (program->_priv);
+    program->_priv = NULL;
+  
+    if (G_OBJECT_CLASS (parent_class)->finalize)
+	(* G_OBJECT_CLASS (parent_class)->finalize) (object);
+}
+
+static gpointer
+gnome_module_info_init (void)
+{
+    return g_new0 (GnomeModuleInfo, 1);
+}
+
+static gpointer
+gnome_module_info_copy (gpointer boxed)
+{
+    return g_memdup (boxed, sizeof (GnomeModuleInfo));
+}
+
+static void
+gnome_module_info_free (gpointer boxed)
+{
+    g_free (boxed);
+}
+
+GType
+gnome_module_info_get_type (void)
+{
+    static GType module_info_type = 0;
+
+    if (!module_info_type)
+	module_info_type = g_boxed_type_register_static
+	    ("GnomeModuleInfo", gnome_module_info_init,
+	     gnome_module_info_copy, gnome_module_info_free,
+	     FALSE);
+
+    return module_info_type;
+}
+
+/**
+ * gnome_program_get:
+ *
+ * Returns an object that stores information on the GNOME application's state.
+ * If the object does not exist, it is created.
+ *
+ * Other functions assume that this will always return an appobject
+ * with state > APP_UNINIT
+ */
+
+GnomeProgram *
+gnome_program_get (void)
+{
+    return global_program;
+}
+
+/**
+ * gnome_program_get_name
+ * @program: The program object
+ *
+ * Description:
+ * This function returns a pointer to a static string that the
+ * application has provided as an identifier. This is not meant as a
+ * human-readable identifier so much as a unique identifier for
+ * programs and libraries.
+ *
+ * Returns: application ID string.
+ */
+const char *
+gnome_program_get_name (GnomeProgram *program)
+{
+    g_return_val_if_fail (program != NULL, NULL);
+    g_return_val_if_fail (GNOME_IS_PROGRAM (program), NULL);
+    g_return_val_if_fail (program->_priv->state >= APP_PREINIT_DONE, NULL);
+
+    return program->_priv->app_id;
+}
+
+/**
+ * gnome_program_get_version
+ * @app: The application object
+ *
+ * Description:
+ * This function returns a pointer to a static string that the
+ * application has provided as a version number. This is not meant as a
+ * human-readable identifier so much as a unique identifier for
+ * programs and libraries.
+ *
+ * Returns: application version string.
+ */
+const char *
+gnome_program_get_version (GnomeProgram *program)
+{
+    g_return_val_if_fail (program != NULL, NULL);
+    g_return_val_if_fail (GNOME_IS_PROGRAM (program), NULL);
+    g_return_val_if_fail (program->_priv->state >= APP_PREINIT_DONE, NULL);
+
+    return program->_priv->app_version;
+}
+
+/**
+ * gnome_program_get_human_readable_name
+ * @app: The application object
+ *
+ * Description:
+ * This function returns a pointer to a static string that the
+ * application has provided as a human readable name. The app
+ * should provide the name with the GNOME_PARAM_HUMAN_READABLE_NAME
+ * init argument. Returns NULL if no name was set.
+ *
+ * Returns: application human-readable name string.
+ */
+const char *
+gnome_program_get_human_readable_name (GnomeProgram *program)
+{
+    g_return_val_if_fail (program != NULL, NULL);
+    g_return_val_if_fail (GNOME_IS_PROGRAM (program), NULL);
+    g_return_val_if_fail (program->_priv->state >= APP_PREINIT_DONE, NULL);
+
+    return program->_priv->prop_human_readable_name;
+}
+
+guint
+gnome_program_install_property (GnomeProgramClass *pclass,
+				GObjectGetPropertyFunc get_fn,
+				GObjectSetPropertyFunc set_fn,
+				GParamSpec *pspec)
+{
+    g_return_val_if_fail (pclass != NULL, -1);
+    g_return_val_if_fail (GNOME_IS_PROGRAM_CLASS (pclass), -1);
+    g_return_val_if_fail (pspec != NULL, -1);
+
+    g_param_spec_set_qdata (pspec, quark_get_prop, get_fn);
+    g_param_spec_set_qdata (pspec, quark_set_prop, set_fn);
+
+    g_object_class_install_property (G_OBJECT_CLASS (pclass),
+				     last_property_id, pspec);
+
+    return last_property_id++;
+}
+
+/**
+ * gnome_program_locate_file:
+ * @domain: A domain (see GnomeFileDomain in gnome-program.h).
+ * @filename: A file name or path inside the 'domain' to find.
+ * @only_if_exists: Only return a full pathname if the specified file
+ *                  actually exists
+ * @ret_locations: If this is not NULL, a list of all the possible locations
+ *                 of the file will be returned.
+ *
+ * This function finds the full path to a file located in the specified
+ * "domain". A domain is a name for a collection of related files.
+ * For example, common domains are "libdir", "pixmap", and "config".
+ *
+ *   NOTE: This function is to locate system-wide files, such as files which
+ *         have been installed by libgnomeui-2 or another platform library.
+ *
+ *         Do *NOT* use it to locate files which are installed by your own
+ *         application; if you have an application `foo' and you want to
+ *         load a pixmap `foo.png' which it installs, define FOOPIXMAPDIR
+ *         in your app's Makefile.am and use FOOPIXMAPDIR "/foo.png".
+ *
+ * The ret_locations list and its contents should be freed by the caller.
+ *
+ * Returns: The full path to the file (if it exists or only_if_exists is
+ *          FALSE) or NULL.
+ */
+gchar *
+gnome_program_locate_file (GnomeProgram *program, GnomeFileDomain domain,
+			   const gchar *file_name, gboolean only_if_exists,
+			   GSList **ret_locations)
+{
+    gchar *prefix_rel = NULL, *attr_name = NULL, *attr_rel = NULL;
+    gchar fnbuf [PATH_MAX], *retval = NULL, *lastval = NULL, **ptr;
+    gboolean append_app_id = FALSE;
+    GValue value = { 0, };
+
+    g_return_val_if_fail (program != NULL, NULL);
+    g_return_val_if_fail (GNOME_IS_PROGRAM (program), NULL);
+    g_return_val_if_fail (program->_priv->state >= APP_PREINIT_DONE, NULL);
+    g_return_val_if_fail (file_name != NULL, NULL);
+
+#define ADD_FILENAME(x) { \
+lastval = (x); \
+if(lastval) { if(ret_locations) *ret_locations = g_slist_append(*ret_locations, lastval); \
+if(!retval && !ret_locations) retval = lastval; } \
+}
+
+    switch (domain) {
+    case GNOME_FILE_DOMAIN_LIBDIR:
+	prefix_rel = "/lib";
+	attr_name = GNOME_PARAM_APP_LIBDIR;
+	attr_rel = "";
+	break;
+    case GNOME_FILE_DOMAIN_DATADIR:
+	prefix_rel = "/share";
+	attr_name = GNOME_PARAM_APP_DATADIR;
+	attr_rel = "";
+	break;
+    case GNOME_FILE_DOMAIN_SOUND:
+	prefix_rel = "/share/sounds";
+	attr_name = GNOME_PARAM_APP_DATADIR;
+	attr_rel = "/sounds";
+	break;
+    case GNOME_FILE_DOMAIN_PIXMAP:
+	prefix_rel = "/share/pixmaps";
+	attr_name = GNOME_PARAM_APP_DATADIR;
+	attr_rel = "/pixmaps";
+	break;
+    case GNOME_FILE_DOMAIN_CONFIG:
+	prefix_rel = "/etc";
+	attr_name = GNOME_PARAM_APP_SYSCONFDIR;
+	attr_rel = "";
+	break;
+    case GNOME_FILE_DOMAIN_HELP:
+	prefix_rel = "/share/gnome/help";
+	attr_name = GNOME_PARAM_APP_DATADIR;
+	attr_rel = "/gnome/help";
+	break;
+    case GNOME_FILE_DOMAIN_APP_HELP:
+	prefix_rel = "/share/gnome/help";
+	attr_name = GNOME_PARAM_APP_DATADIR;
+	attr_rel = "/gnome/help";
+	append_app_id = TRUE;
+	break;
+    default:
+	g_warning (G_STRLOC ": unknown file domain %d", domain);
+	return NULL;
+    }
+
+    if (attr_name) {
+	const gchar *dir;
+
+	g_value_init (&value, G_TYPE_STRING);
+	g_object_get_property (G_OBJECT (program), attr_name, &value);
+	dir = g_value_get_string (&value);
+
+	if (dir) {
+	    if (append_app_id)
+		g_snprintf (fnbuf, sizeof (fnbuf), "%s%s/%s/%s",
+			    dir, attr_rel, program->_priv->app_id, file_name);
+	    else
+		g_snprintf (fnbuf, sizeof (fnbuf), "%s%s/%s",
+			    dir, attr_rel, file_name);
+
+	    if (!only_if_exists || g_file_test (fnbuf, G_FILE_TEST_EXISTS))
+		ADD_FILENAME (g_strdup (fnbuf));
+	}
+
+	g_value_unset (&value);
+    }
+    if (retval && !ret_locations)
+	goto out;
+
+    /* Now check the GNOME_PATH. */
+    for (ptr = program->_priv->gnome_path; ptr && *ptr; ptr++) {
+	if (append_app_id)
+	    g_snprintf (fnbuf, sizeof (fnbuf), "%s%s/%s/%s",
+			*ptr, prefix_rel, program->_priv->app_id, file_name);
+	else
+	    g_snprintf (fnbuf, sizeof (fnbuf), "%s%s/%s",
+			*ptr, prefix_rel, file_name);
+
+	if (!only_if_exists || g_file_test (fnbuf, G_FILE_TEST_EXISTS))
+	    ADD_FILENAME (g_strdup (fnbuf));
+    }
+    if (retval && !ret_locations)
+	goto out;
+
+ out:
+    return retval;
+}
+
+/******** modules *******/
+
+/* Stolen verbatim from rpm/lib/misc.c 
+   RPM is Copyright (c) 1998 by Red Hat Software, Inc.,
+   and may be distributed under the terms of the GPL and LGPL.
+*/
+/* compare alpha and numeric segments of two versions */
+/* return 1: a is newer than b */
+/*        0: a and b are the same version */
+/*       -1: b is newer than a */
+static int rpmvercmp(const char * a, const char * b) {
+    char oldch1, oldch2;
+    char * str1, * str2;
+    char * one, * two;
+    int rc;
+    int isnum;
+    
+    /* easy comparison to see if versions are identical */
+    if (!strcmp(a, b)) return 0;
+
+    str1 = g_alloca(strlen(a) + 1);
+    str2 = g_alloca(strlen(b) + 1);
+
+    strcpy(str1, a);
+    strcpy(str2, b);
+
+    one = str1;
+    two = str2;
+
+    /* loop through each version segment of str1 and str2 and compare them */
+    while (*one && *two) {
+	while (*one && !isalnum(*one)) one++;
+	while (*two && !isalnum(*two)) two++;
+
+	str1 = one;
+	str2 = two;
+
+	/* grab first completely alpha or completely numeric segment */
+	/* leave one and two pointing to the start of the alpha or numeric */
+	/* segment and walk str1 and str2 to end of segment */
+	if (isdigit(*str1)) {
+	    while (*str1 && isdigit(*str1)) str1++;
+	    while (*str2 && isdigit(*str2)) str2++;
+	    isnum = 1;
+	} else {
+	    while (*str1 && isalpha(*str1)) str1++;
+	    while (*str2 && isalpha(*str2)) str2++;
+	    isnum = 0;
+	}
+		
+	/* save character at the end of the alpha or numeric segment */
+	/* so that they can be restored after the comparison */
+	oldch1 = *str1;
+	*str1 = '\0';
+	oldch2 = *str2;
+	*str2 = '\0';
+
+	/* take care of the case where the two version segments are */
+	/* different types: one numeric and one alpha */
+	if (one == str1) return -1;	/* arbitrary */
+	if (two == str2) return -1;
+
+	if (isnum) {
+	    /* this used to be done by converting the digit segments */
+	    /* to ints using atoi() - it's changed because long  */
+	    /* digit segments can overflow an int - this should fix that. */
+	  
+	    /* throw away any leading zeros - it's a number, right? */
+	    while (*one == '0') one++;
+	    while (*two == '0') two++;
+
+	    /* whichever number has more digits wins */
+	    if (strlen(one) > strlen(two)) return 1;
+	    if (strlen(two) > strlen(one)) return -1;
+	}
+
+	/* strcmp will return which one is greater - even if the two */
+	/* segments are alpha or if they are numeric.  don't return  */
+	/* if they are equal because there might be more segments to */
+	/* compare */
+	rc = strcmp(one, two);
+	if (rc) return rc;
+	
+	/* restore character that was replaced by null above */
+	*str1 = oldch1;
+	one = str1;
+	*str2 = oldch2;
+	two = str2;
+    }
+
+    /* this catches the case where all numeric and alpha segments have */
+    /* compared identically but the segment sepparating characters were */
+    /* different */
+    if ((!*one) && (!*two)) return 0;
+
+    /* whichever version still has characters left over wins */
+    if (!*one) return -1; else return 1;
+}
+
+static gboolean
+gnome_program_version_check (const char *required_version,
+			     const char *provided_version)
+{
+    if (required_version && provided_version)
+	return (rpmvercmp (provided_version, required_version) >= 0);
+    else
+	return TRUE;
+}
+
+/**
+ * gnome_program_module_registered:
+ * @module_info: A pointer to a GnomeModuleInfo structure describing the module
+ *               to be queried
+ *
+ * Description: This method checks to see whether a specific module has been
+ *              initialized in the specified program.
+ *
+ * Returns: A value indicating whether the specified module has been
+ *          registered/initialized in the current program
+ */
+gboolean
+gnome_program_module_registered (const GnomeModuleInfo *module_info)
+{
+    int i;
+    GnomeModuleInfo *curmod;
+
+    g_return_val_if_fail (module_info, FALSE);
+
+    if (!program_modules)
+	program_modules = g_ptr_array_new ();
+
+    for(i = 0; i < program_modules->len; i++) {
+	curmod = g_ptr_array_index (program_modules, i);
+	if(curmod == module_info
+	   || !strcmp (curmod->name, module_info->name))
+	    return TRUE;
+    }
+
+    return FALSE;
+}
+
+/**
+ * gnome_program_module_register:
+ * @module_info: A pointer to a GnomeModuleInfo structure describing the module
+ *               to be initialized
+ *
+ * Description:
+ * This function is used to register a module to be initialized by the
+ * GNOME library framework. The memory pointed to by 'module_info' must be
+ * valid during the whole application initialization process, and the module
+ * described by 'module_info' must only use the 'module_info' pointer to
+ * register itself.
+ *
+ */
+void
+gnome_program_module_register (const GnomeModuleInfo *module_info)
+{
+    int i;
+
+    g_return_if_fail (module_info);
+
+    if (program_initialized) {
+	g_warning (G_STRLOC ": cannot load modules after program is initialized");
+	return;
+    }
+
+    if (!program_modules)
+	program_modules = g_ptr_array_new();
+
+    /* Check that it's not already registered. */
+
+    if (gnome_program_module_registered (module_info))
+	return;
+
+    g_ptr_array_add (program_modules, (GnomeModuleInfo *)module_info);
+
+    /* We register requirements *after* the module itself to avoid loops.
+       Initialization order gets sorted out later on. */
+    if (module_info->requirements) {
+	for(i = 0; module_info->requirements[i].required_version; i++) {
+	    GnomeModuleInfo *dep_mod;
+
+	    dep_mod = module_info->requirements[i].module_info;
+	    if (gnome_program_version_check (module_info->requirements[i].required_version,
+					     dep_mod->version))
+		gnome_program_module_register (dep_mod);
+	    else
+		/* The required version is not installed */
+		/* I18N needed */
+		g_error ("Module '%s' requires version '%s' of module '%s' "
+			 "to be installed, and you only have version '%s' of '%s'. "
+			 "Aborting application.",
+			 module_info->name,
+			 module_info->requirements[i].required_version,
+			 dep_mod->name,
+			 dep_mod->version,
+			 dep_mod->name);
+	}
+    }
+}
+
+/**
+ * gnome_program_preinit:
+ * @program: Application object
+ * @app_id: application ID string
+ * @app_version: application version string
+ * @argc: The number of commmand line arguments contained in 'argv'
+ * @argv: A string array of command line arguments
+ *
+ * Description:
+ * This function performs the portion of application initialization that
+ * needs to be done prior to command line argument parsing. The poptContext
+ * returned can be used for getopt()-style option processing.
+ *
+ * Returns: A poptContext representing the argument parsing state.
+ */
+poptContext
+gnome_program_preinit (GnomeProgram *program,
+		       const char *app_id, const char *app_version,
+		       int argc, char **argv)
+{
+    GnomeModuleInfo *a_module;
+    poptContext argctx;
+    int i;
+
+    g_return_val_if_fail (program != NULL, NULL);
+    g_return_val_if_fail (GNOME_IS_PROGRAM (program), NULL);
+
+    if (program->_priv->state != APP_CREATE_DONE)
+	return NULL;
+
+    /* On non-glibc systems, this is not set up for us.  */
+    if (!program_invocation_name) {
+	program_invocation_name = argv[0];
+	program_invocation_short_name = g_path_get_basename (program_invocation_name);
+    }
+
+    /* 0. Misc setup */
+    if (program->_priv->app_id)
+	g_free (program->_priv->app_id);
+    program->_priv->app_id = g_strdup (app_id);
+    g_set_prgname (app_id);
+    if (program->_priv->app_version)
+	g_free (program->_priv->app_version);
+    program->_priv->app_version = g_strdup (app_version);
+    program->_priv->argc = argc;
+    program->_priv->argv = argv;
+
+    if (!program_modules)
+	program_modules = g_ptr_array_new();
+
+    /* Major steps in this function:
+       1. Process all framework attributes in 'attrs'
+       2. Order the module list for dependencies
+       3. Call the preinit functions for the modules
+       4. Process other attributes 
+       5. Create a top-level 'struct poptOption *' for use in arg-parsing.
+       6. Create a poptContext
+       7. Cleanup/return
+    */
+
+    /* 3. call the pre-init functions */
+    for (i = 0; (a_module = g_ptr_array_index (program_modules, i)); i++) {
+	if (a_module->pre_args_parse)
+	    a_module->pre_args_parse (program, a_module);
+    }
+
+    /* 5. Create a top-level 'struct poptOption *' for use in arg-parsing. */
+    {
+	struct poptOption includer = {NULL, '\0', POPT_ARG_INCLUDE_TABLE,
+				      NULL, 0, NULL, NULL};
+
+	program->_priv->top_options_table = g_array_new
+	    (TRUE, TRUE, sizeof (struct poptOption));
+
+	/* Put the special popt table in first */
+	includer.arg = poptHelpOptions;
+	includer.descrip = N_("Help options");
+	g_array_append_val (program->_priv->top_options_table, includer);
+
+	if (program->_priv->prop_popt_table) {
+	    includer.arg = program->_priv->prop_popt_table;
+	    includer.descrip = N_("Application options");
+	    g_array_append_val (program->_priv->top_options_table,
+				includer);
+	}
+
+	for (i = 0; (a_module = g_ptr_array_index(program_modules, i)); i++) {
+	    if (a_module->options) {
+		includer.arg = a_module->options;
+		includer.descrip = (char *)a_module->description;
+
+		g_array_append_val (program->_priv->top_options_table, includer);
+	    }
+	}
+
+	includer.longName = "load-modules";
+	includer.argInfo = POPT_ARG_STRING;
+	includer.descrip = N_("Dynamic modules to load");
+	includer.argDescrip = N_("MODULE1,MODULE2,...");
+	g_array_append_val (program->_priv->top_options_table, includer);
+    }
+
+    argctx = program->_priv->arg_context = poptGetContext
+	(program->_priv->app_id, argc, (const char **) argv,
+	 (struct poptOption *) program->_priv->top_options_table->data,
+	 program->_priv->prop_popt_flags);
+  
+    /* 7. Cleanup/return */
+    program->_priv->state = APP_PREINIT_DONE;
+
+    return argctx;
+}
+
+/**
+ * gnome_program_module_load:
+ * @program: Application object
+ * @mod_name: module name
+ *
+ * Loads a shared library that contains a
+ * 'GnomeModuleInfo dynamic_module_info' structure.
+ */
+void
+gnome_program_module_load (const char *mod_name)
+{
+    GModule *mh;
+    GnomeModuleInfo *gmi;
+    char tbuf[1024];
+
+    g_return_if_fail (mod_name != NULL);
+
+    if (program_initialized) {
+	g_warning (G_STRLOC ": cannot load modules after program is initialized");
+	return;
+    }
+
+    g_snprintf (tbuf, sizeof(tbuf), "lib%s.so.0", mod_name);
+
+    mh = g_module_open (mod_name, G_MODULE_BIND_LAZY);
+    if(!mh) {
+	g_snprintf (tbuf, sizeof(tbuf), "lib%s.so", mod_name);
+
+	mh = g_module_open (mod_name, G_MODULE_BIND_LAZY);
+    }
+
+    if (!mh)
+	return;
+
+    if (g_module_symbol (mh, "dynamic_module_info", (gpointer *)&gmi)) {
+	gnome_program_module_register (gmi);
+	g_module_make_resident (mh);
+    } else
+	g_module_close (mh);
+}
+
+/**
+ * gnome_program_parse_args:
+ * @app: Application object
+ *
+ * Description: Parses the command line arguments for the application
+ */
+void
+gnome_program_parse_args (GnomeProgram *program)
+{
+    int nextopt;
+    poptContext ctx;
+
+    g_return_if_fail (program != NULL);
+    g_return_if_fail (GNOME_IS_PROGRAM (program));
+
+    if (program->_priv->state != APP_PREINIT_DONE)
+	return;
+
+    ctx = program->_priv->arg_context;
+    while ((nextopt = poptGetNextOpt (ctx)) > 0 || nextopt == POPT_ERROR_BADOPT)
+	/* do nothing */ ;
+
+    if (nextopt != -1) {
+	g_print ("Error on option %s: %s.\nRun '%s --help' to see a full list of available command line options.\n",
+		 poptBadOption (ctx, 0),
+		 poptStrerror (nextopt),
+		 program->_priv->argv[0]);
+	exit (1);
+    }
+}
+
+/**
+ * gnome_program_postinit:
+ * @program: Application object
+ *
+ * Description: Called after gnome_program_parse_args(), this function
+ * takes care of post-parse initialization and cleanup
+ */
+void
+gnome_program_postinit (GnomeProgram *program)
+{
+    int i;
+    GnomeModuleInfo *a_module;
+
+    g_return_if_fail (program != NULL);
+    g_return_if_fail (GNOME_IS_PROGRAM (program));
+
+    if (program->_priv->state != APP_PREINIT_DONE)
+	return;
+
+    /* Call post-parse functions */
+    for (i = 0; (a_module = g_ptr_array_index(program_modules, i)); i++) {
+	if (a_module->post_args_parse)
+	    a_module->post_args_parse (program, a_module);
+    }
+
+    /* Free up stuff we don't need to keep around for the lifetime of the app */
+#if 0
+    g_ptr_array_free (program_modules, TRUE);
+    program_modules = NULL;
+#endif
+
+    g_array_free (program->_priv->top_options_table, TRUE);
+    program->_priv->top_options_table = NULL;
+
+    g_blow_chunks(); /* Try to compact memory usage a bit */
+
+    program->_priv->state = APP_POSTINIT_DONE;
+}
+
+/**
+ * gnome_program_init:
+ * @program_id: Application ID string
+ * @app_version: Application version string
+ * @argc: The number of commmand line arguments contained in 'argv'
+ * @argv: A string array of command line arguments
+ * @...: a NULL-terminated list of attribute name/value pairs
+ *
+ * Description:
+ * Performs application initialization.
+ */
+GnomeProgram *
+gnome_program_init (const char *app_id, const char *app_version,
+		    int argc, char **argv,
+		    const char *first_property_name, ...)
+{
+    GnomeProgram *program;
+    va_list args;
+
+    va_start(args, first_property_name);
+    program = gnome_program_initv (app_id, app_version, argc, argv,
+				   first_property_name, args);
+    va_end(args);
+
+    return program;
+}
+
+GnomeProgram *
+gnome_program_initv (const char *app_id, const char *app_version,
+		     int argc, char **argv,
+		     const char *first_property_name, va_list args)
+{
+    GnomeProgram *program;
+    int i;
+
+    libgnome_type_init ();
+
+    if (!program_initialized) {
+	const char *ctmp;
+
+	program_module_list = g_ptr_array_new ();
+	program_modules = g_ptr_array_new ();
+
+	/* We have to handle --load-modules=foo,bar,baz specially */
+	for (i = 0; i < argc; i++) {
+	    if (!strncmp (argv[i], "--load-modules=", strlen ("--load-modules=")))
+		add_to_module_list (argv[i] + strlen("--load-modules="));
+	}
+
+	if ((ctmp = g_getenv ("GNOME_MODULES")))
+	    add_to_module_list (ctmp);
+    }
+
+    program = g_object_new_valist (GNOME_TYPE_PROGRAM,
+				   first_property_name, args);
+
+    gnome_program_preinit (program, app_id, app_version, argc, argv);
+    gnome_program_parse_args (program);
+    gnome_program_postinit (program);
+
+    return program;
+}
diff --git a/libgnome/gnome-program.h b/libgnome/gnome-program.h
new file mode 100644
index 0000000..0a2ad84
--- /dev/null
+++ b/libgnome/gnome-program.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 1999, 2000 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This file is part of the Gnome Library.
+ *
+ * The Gnome Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * The Gnome Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the Gnome Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+/*
+  @NOTATION@
+ */
+
+
+/* This module takes care of handling application and library
+   initialization and command line parsing */
+
+#ifndef GNOME_PROGRAM_H
+#define GNOME_PROGRAM_H
+
+#include <glib.h>
+#include <popt.h>
+#include <stdarg.h>
+
+#include <gobject/gobject.h>
+
+
+G_BEGIN_DECLS
+
+#define GNOME_TYPE_PROGRAM            (gnome_program_get_type ())
+#define GNOME_PROGRAM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNOME_TYPE_PROGRAM, GnomeProgram))
+#define GNOME_PROGRAM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GNOME_TYPE_PROGRAM, GnomeProgramClass))
+#define GNOME_IS_PROGRAM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNOME_TYPE_PROGRAM))
+#define GNOME_IS_PROGRAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNOME_TYPE_PROGRAM))
+
+typedef struct _GnomeProgram          GnomeProgram;
+typedef struct _GnomeProgramPrivate   GnomeProgramPrivate;
+typedef struct _GnomeProgramClass     GnomeProgramClass;
+
+typedef enum _GnomeFileDomain         GnomeFileDomain;
+
+enum _GnomeFileDomain {
+    GNOME_FILE_DOMAIN_UNKNOWN = 0,
+    GNOME_FILE_DOMAIN_LIBDIR,
+    GNOME_FILE_DOMAIN_DATADIR,
+    GNOME_FILE_DOMAIN_SOUND,
+    GNOME_FILE_DOMAIN_PIXMAP,
+    GNOME_FILE_DOMAIN_CONFIG,
+    GNOME_FILE_DOMAIN_HELP,
+    GNOME_FILE_DOMAIN_APP_HELP
+};
+
+struct _GnomeProgram
+{
+    GObject object;
+
+    GnomeProgramPrivate *_priv;
+};
+
+struct _GnomeProgramClass
+{
+    GObjectClass object_class;
+};
+
+GType
+gnome_program_get_type                  (void);
+
+GnomeProgram *
+gnome_program_get                       (void);
+
+const char*
+gnome_program_get_human_readable_name   (GnomeProgram *program);
+
+const char *
+gnome_program_get_name                  (GnomeProgram *program);
+
+const char *
+gnome_program_get_version               (GnomeProgram *program);
+
+gchar *
+gnome_program_locate_file               (GnomeProgram    *program,
+					 GnomeFileDomain  domain,
+					 const gchar     *file_name,
+					 gboolean         only_if_exists,
+					 GSList         **ret_locations);
+
+#define GNOME_PARAM_MODULE_INFO         "module-info"
+#define GNOME_PARAM_MODULES             "modules"
+#define GNOME_PARAM_POPT_TABLE          "popt-table"
+#define GNOME_PARAM_POPT_FLAGS          "popt-flags"
+#define GNOME_PARAM_POPT_CONTEXT        "popt-context"
+#define GNOME_PARAM_CREATE_DIRECTORIES  "create-directories"
+#define GNOME_PARAM_ESPEAKER            "espeaker"
+#define GNOME_PARAM_ENABLE_SOUND        "enable-sound"
+#define GNOME_PARAM_FILE_LOCATOR        "file-locator"
+#define GNOME_PARAM_APP_ID              "app-id"
+#define GNOME_PARAM_APP_VERSION         "app-version"
+#define GNOME_PARAM_APP_PREFIX          "app-prefix"
+#define GNOME_PARAM_APP_SYSCONFDIR      "app-sysconfdir"
+#define GNOME_PARAM_APP_DATADIR         "app-datadir"
+#define GNOME_PARAM_APP_LIBDIR          "app-libdir"
+#define GNOME_PARAM_HUMAN_READABLE_NAME "human-readable-name"
+#define GNOME_PARAM_GNOME_PATH          "gnome-path"
+
+/***** application modules (aka libraries :) ******/
+#define GNOME_TYPE_MODULE_INFO          (gnome_module_info_get_type ())
+
+GType
+gnome_module_info_get_type              (void);
+
+typedef struct _GnomeModuleInfo GnomeModuleInfo;
+typedef struct _GnomeModuleRequirement GnomeModuleRequirement;
+
+struct _GnomeModuleRequirement {
+    const char *required_version;
+    GnomeModuleInfo *module_info;
+};
+
+typedef void (*GnomeModuleInitHook) (const GnomeModuleInfo *mod_info);
+typedef void (*GnomeModuleConstructor) (GType type, guint n_construct_props,
+					GObjectConstructParam *construct_props,
+					const GnomeModuleInfo *mod_info);
+typedef void (*GnomeModuleHook) (GnomeProgram *program,
+				 GnomeModuleInfo *mod_info);
+
+struct _GnomeModuleInfo {
+    const char *name, *version, *description;
+    GnomeModuleRequirement *requirements; /* last element has NULL version */
+
+    GnomeModuleHook pre_args_parse, post_args_parse;
+
+    struct poptOption *options;
+
+    GnomeModuleInitHook init_pass; /* This gets run before the preinit
+				      function to allow the module to
+				      register other modules as needed. The
+				      module cannot assume its required
+				      modules are initialized (they aren't). */
+
+    GnomeModuleConstructor constructor;
+
+    gpointer expansion1, expansion2;
+};
+
+/* This function should be called before gnomelib_preinit() - it's an
+ * alternative to the "module" property passed by the app.
+ */
+void
+gnome_program_module_register (const GnomeModuleInfo *module_info);
+
+gboolean
+gnome_program_module_registered (const GnomeModuleInfo *module_info);
+
+void
+gnome_program_module_load (const char *mod_name);
+
+guint
+gnome_program_install_property (GnomeProgramClass *pclass,
+				GObjectGetPropertyFunc get_fn,
+				GObjectSetPropertyFunc set_fn,
+				GParamSpec *pspec);
+
+/*
+ * If the application writer wishes to use getopt()-style arg
+ * processing, they can do it using a while looped sandwiched between
+ * calls to these two functions.
+ */
+poptContext
+gnome_program_preinit (GnomeProgram *program,
+		       const char *app_id,
+		       const char *app_version,
+		       int argc, char **argv);
+
+void
+gnome_program_parse_args (GnomeProgram *program);
+
+void
+gnome_program_postinit (GnomeProgram *program);
+
+/* These are convenience functions that calls gnomelib_preinit(...), have
+   popt parse all args, and then call gnomelib_postinit() */
+GnomeProgram *
+gnome_program_init (const char *app_id, const char *app_version,
+		    int argc, char **argv,
+		    const char *first_property_name, ...);
+
+GnomeProgram *
+gnome_program_initv (const char *app_id, const char *app_version,
+		     int argc, char **argv,
+		     const char *first_property_name, va_list args);
+
+/* Some systems, like Red Hat 4.0, define these but don't declare
+   them.  Hopefully it is safe to always declare them here.  */
+extern char *program_invocation_short_name;
+extern char *program_invocation_name;
+
+#endif
diff --git a/libgnome/gnome-url.c b/libgnome/gnome-url.c
index 46ba715..7961709 100644
--- a/libgnome/gnome-url.c
+++ b/libgnome/gnome-url.c
@@ -34,7 +34,6 @@
 #include <libgnome/gnome-config.h>
 #include <libgnome/gnome-exec.h>
 #include <libgnome/gnome-util.h>
-#include <libgnomebase/gnome-portability.h>
 #include "gnome-url.h"
 #include "gnome-i18nP.h"
 #include <popt.h>
diff --git a/libgnome/gnome-util.c b/libgnome/gnome-util.c
index 67e65ed..6ab29bf 100644
--- a/libgnome/gnome-util.c
+++ b/libgnome/gnome-util.c
@@ -50,8 +50,7 @@
 #include <pwd.h>
 #include <limits.h>
 #include "libgnomeP.h"
-#include <libgnomebase/gnome-program.h>
-#include <libgnomebase/gnome-portability.h>
+#include <libgnome/gnome-program.h>
 #include <libgnome/gnome-util.h>
 
 /**
diff --git a/libgnome/gnome-util.h b/libgnome/gnome-util.h
index 8ed49dd..c1c4a72 100644
--- a/libgnome/gnome-util.h
+++ b/libgnome/gnome-util.h
@@ -29,7 +29,7 @@
 
 #include <stdlib.h>
 #include <glib.h>
-#include <libgnomebase/gnome-program.h>
+#include <libgnome/gnome-program.h>
 
 G_BEGIN_DECLS
 
diff --git a/libgnome/libgnome.h b/libgnome/libgnome.h
index 3b64c94..baf93b0 100644
--- a/libgnome/libgnome.h
+++ b/libgnome/libgnome.h
@@ -26,7 +26,8 @@
 #ifndef LIBGNOME_H
 #define LIBGNOME_H
 
-#include <libgnomebase/libgnomebase.h>
+#include <libgnome/gnome-program.h>
+#include <libgnome/gnome-i18n.h>
 
 #include <libgnome/gnome-config.h>
 #include <libgnome/gnome-exec.h>
diff --git a/libgnome/libgnomeP.h b/libgnome/libgnomeP.h
index 9c4e0da..fc9d3d8 100644
--- a/libgnome/libgnomeP.h
+++ b/libgnome/libgnomeP.h
@@ -27,7 +27,6 @@
 #define LIBGNOMEP_H
 
 #include <glib.h>
-#include <libgnomebase/libgnomebase.h>
 #include <libgnome/libgnome.h>
 
 #include "gnome-i18nP.h"



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]