From 89255c3b352855d728ae3adc20b0cdd90fe582dd Mon Sep 17 00:00:00 2001 From: Glynn Foster Date: Fri, 24 Jan 2003 16:16:40 +0000 Subject: Provide correct help URL. 2003-01-24 Glynn Foster * src/about.c: Provide correct help URL. * src/util.h, src/util.c: Add functions from libgnome/gnome-i18n so that we can correctly find the apropriate help file. * xmldocs.make: Install help into $(datadir)/help/$(lang)/ * THANKS: Update from the code I stole from libgnome --- src/about.c | 6 +- src/util.c | 332 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/util.h | 3 +- 3 files changed, 333 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/about.c b/src/about.c index fcc9352b..9bca0cc3 100644 --- a/src/about.c +++ b/src/about.c @@ -30,6 +30,7 @@ #include #define GTK_RESPONSE_CREDITS 0 +#define ZENITY_HELP_PATH ZENITY_DATADIR "/help/" static GtkWidget *dialog; static GtkWidget *cred_dialog; @@ -46,6 +47,7 @@ static const gchar *author_credits[] = { "Havoc Pennington ", "Kristian Rietveld ", "Jakub Steiner ", + "Tom Tromey " NULL }; @@ -240,7 +242,6 @@ zenity_about_dialog_response (GtkWidget *widget, int response, gpointer data) { ZenityData *zen_data = data; GError *error = NULL; - gchar *help_string; switch (response) { case GTK_RESPONSE_OK: @@ -249,8 +250,7 @@ zenity_about_dialog_response (GtkWidget *widget, int response, gpointer data) break; case GTK_RESPONSE_HELP: - help_string = g_strconcat ("ghelp://", ZENITY_DATADIR, "help/zenity", NULL); - zenity_util_show_help (help_string, NULL); + zenity_util_show_help (ZENITY_HELP_PATH, "zenity.xml", NULL); break; case GTK_RESPONSE_CREDITS: diff --git a/src/util.c b/src/util.c index dbc30d8f..bbb6d777 100644 --- a/src/util.c +++ b/src/util.c @@ -4,6 +4,7 @@ * Copyright (C) 2002 Sun Microsystems, Inc. * (C) 1999, 2000 Red Hat Inc. * (C) 1998 James Henstridge + * (C) 1995-2002 Free Software Foundation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -23,12 +24,15 @@ * Authors: Glynn Foster * Havoc Pennington * James Henstridge + * Tom Tromey */ #include +#include #include #include "config.h" #include "util.h" +#include "zenity.h" #include #define URL_HANDLER_DIR "/desktop/gnome/url-handlers/" @@ -164,12 +168,329 @@ zenity_util_set_window_icon_from_stock (GtkWidget *widget, const gchar *stock_id g_object_unref (pixbuf); } +/* This is copied from libgnome/gnome-i18n.c since we try and avoid using + * the evils of gnome_program_init (), which messes up the commandline + */ + +static GHashTable *alias_table = NULL; + +/*read an alias file for the locales*/ +static void +zenity_read_aliases (char *file) +{ + FILE *fp; + char buf[256]; + + if (!alias_table) + alias_table = g_hash_table_new (g_str_hash, g_str_equal); + + fp = fopen (file,"r"); + + if (!fp) + return; + + while (fgets (buf,256,fp)) { + gchar *p; + g_strstrip (buf); + + if (buf[0]=='#' || buf[0]=='\0') + continue; + + p = (gchar *) strtok (buf, "\t "); + + if (!p) + continue; + + p = (gchar *) strtok (NULL, "\t "); + + if(!p) + continue; + + if (!g_hash_table_lookup (alias_table, buf)) + g_hash_table_insert (alias_table, g_strdup (buf), g_strdup (p)); + } + + fclose (fp); +} + +/*return the un-aliased language as a newly allocated string*/ +static char * +zenity_unalias_lang (char *lang) +{ + char *p; + int i; + + if (!alias_table) { + zenity_read_aliases ("/usr/share/locale/locale.alias"); + zenity_read_aliases ("/usr/local/share/locale/locale.alias"); + zenity_read_aliases ("/usr/lib/X11/locale/locale.alias"); + zenity_read_aliases ("/usr/openwin/lib/locale/locale.alias"); + } + + i = 0; + while ((p = g_hash_table_lookup (alias_table,lang)) && strcmp (p, lang)) { + lang = p; + + if (i++ == 30) { + static gboolean said_before = FALSE; + + if (!said_before) + g_warning (_("Too many alias levels for a locale may indicate a loop")); + + said_before = TRUE; + return lang; + } + } + return lang; +} + +/* Mask for components of locale spec. The ordering here is from + * least significant to most significant + */ +enum +{ + COMPONENT_CODESET = 1 << 0, + COMPONENT_TERRITORY = 1 << 1, + COMPONENT_MODIFIER = 1 << 2 +}; + +/* Break an X/Open style locale specification into components + */ +static guint +zenity_explode_locale (const gchar *locale, + gchar **language, + gchar **territory, + gchar **codeset, + gchar **modifier) +{ + const gchar *uscore_pos; + const gchar *at_pos; + const gchar *dot_pos; + guint mask = 0; + + uscore_pos = (const gchar *) strchr (locale, '_'); + dot_pos = (const gchar *) strchr (uscore_pos ? uscore_pos : locale, '.'); + at_pos = (const gchar *) strchr (dot_pos ? dot_pos : (uscore_pos ? uscore_pos : locale), '@'); + + if (at_pos) { + mask |= COMPONENT_MODIFIER; + *modifier = g_strdup (at_pos); + } else + at_pos = locale + strlen (locale); + + if (dot_pos) { + mask |= COMPONENT_CODESET; + *codeset = g_new (gchar, 1 + at_pos - dot_pos); + strncpy (*codeset, dot_pos, at_pos - dot_pos); + (*codeset) [at_pos - dot_pos] = '\0'; + } else + dot_pos = at_pos; + + if (uscore_pos) { + mask |= COMPONENT_TERRITORY; + *territory = g_new (gchar, 1 + dot_pos - uscore_pos); + strncpy (*territory, uscore_pos, dot_pos - uscore_pos); + (*territory)[dot_pos - uscore_pos] = '\0'; + } else + uscore_pos = dot_pos; + + *language = g_new (gchar, 1 + uscore_pos - locale); + strncpy (*language, locale, uscore_pos - locale); + (*language) [uscore_pos - locale] = '\0'; + + return mask; +} + +static GList * +zenity_compute_locale_variants (const gchar *locale) +{ + GList *retval = NULL; + gchar *language; + gchar *territory; + gchar *codeset; + gchar *modifier; + guint mask; + guint i; + + + g_return_val_if_fail (locale != NULL, NULL); + + mask = zenity_explode_locale (locale, &language, &territory, &codeset, &modifier); + + /* Iterate through all possible combinations, from least attractive + * to most attractive. + */ + + for (i = 0; i <= mask; i++) + if ((i & ~mask) == 0) { + gchar *val = g_strconcat (language, + (i & COMPONENT_TERRITORY) ? territory : "", + (i & COMPONENT_CODESET) ? codeset : "", + (i & COMPONENT_MODIFIER) ? modifier : "", NULL); + retval = g_list_prepend (retval, val); + } + + g_free (language); + + if (mask & COMPONENT_CODESET) + g_free (codeset); + if (mask & COMPONENT_TERRITORY) + g_free (territory); + if (mask & COMPONENT_MODIFIER) + g_free (modifier); + + return retval; +} + +static const gchar * +zenity_guess_category_value (const gchar *categoryname) +{ + const gchar *retval; + + /* The highest priority value is the `LANGUAGE' environment + * variable. This is a GNU extension. + */ + + retval = g_getenv ("LANGUAGE"); + + if (retval != NULL && retval[0] != '\0') + return retval; + + /* `LANGUAGE' is not set. So we have to proceed with the POSIX + * methods of looking to `LC_ALL', `LC_xxx', and `LANG'. On some + * systems this can be done by the `setlocale' function itself. + */ + + /* Setting of LC_ALL overwrites all other. */ + + retval = g_getenv ("LC_ALL"); + + if (retval != NULL && retval[0] != '\0') + return retval; + + /* Next comes the name of the desired category. */ + retval = g_getenv (categoryname); + + if (retval != NULL && retval[0] != '\0') + return retval; + + /* Last possibility is the LANG environment variable. */ + retval = g_getenv ("LANG"); + if (retval != NULL && retval[0] != '\0') + return retval; + + return NULL; +} + + +static GHashTable *category_table= NULL; + +static const GList * +zenity_i18n_get_language_list (const gchar *category_name) +{ + GList *list; + + if (!category_name) + category_name= "LC_ALL"; + + if (category_table) { + list= g_hash_table_lookup (category_table, (const gpointer) category_name); + } else { + category_table= g_hash_table_new (g_str_hash, g_str_equal); + list= NULL; + } + + if (!list) { + gint c_locale_defined= FALSE; + const gchar *category_value; + gchar *category_memory, *orig_category_memory; + + category_value = zenity_guess_category_value (category_name); + + if (! category_value) + category_value = "C"; + + orig_category_memory = category_memory = g_malloc (strlen (category_value) + 1); + + while (category_value[0] != '\0') { + while (category_value[0] != '\0' && category_value[0] == ':') + ++category_value; + + if (category_value[0] != '\0') { + char *cp= category_memory; + + while (category_value[0] != '\0' && category_value[0] != ':') + *category_memory++= *category_value++; + + category_memory[0]= '\0'; + category_memory++; + + cp = zenity_unalias_lang (cp); + + if (strcmp (cp, "C") == 0) + c_locale_defined= TRUE; + + list= g_list_concat (list, zenity_compute_locale_variants (cp)); + } + } + + g_free (orig_category_memory); + + if (!c_locale_defined) + list= g_list_append (list, "C"); + + g_hash_table_insert (category_table, (gpointer) category_name, list); + } + + return list; +} + +/* This is copied from libgnome/gnome-help.c since we try and avoid using + * the evils of gnome_program_init (), which messes up the commandline + */ + +static char * +zenity_locate_help_file (const char *path, const char *doc_name) +{ + int i; + char *exts[] = { ".xml", ".docbook", ".sgml", ".html", "", NULL }; + const GList *lang_list = zenity_i18n_get_language_list ("LC_MESSAGES"); + + for (;lang_list != NULL; lang_list = lang_list->next) { + const char *lang = lang_list->data; + + /* This has to be a valid language AND a language with + * no encoding postfix. The language will come up without + * encoding next + */ + + if (lang == NULL || (gchar *) strchr (lang, '.') != NULL) + continue; + + for (i = 0; exts[i] != NULL; i++) { + char *name; + char *full; + + name = g_strconcat (doc_name, exts[i], NULL); + full = g_build_filename (path, lang, name, NULL); + + if (g_file_test (full, G_FILE_TEST_EXISTS)) + return full; + + g_free (full); + + } + } + + return NULL; +} + /* This is copied from libgnome/gnome-url.c since we try and avoid using * the evils of gnome_program_init (), which messes up the commandline */ gboolean -zenity_util_show_help (const gchar *url, GError **error) +zenity_util_show_help (const gchar *path, const gchar *document, GError **error) { GConfClient *client; gint i; @@ -177,10 +498,13 @@ zenity_util_show_help (const gchar *url, GError **error) int argc; char **argv; gboolean ret; + char *url; - g_return_val_if_fail (url != NULL, FALSE); - - pos = strchr (url, ':'); + g_return_val_if_fail (path != NULL, FALSE); + g_return_val_if_fail (document != NULL, FALSE); + + url = g_strconcat ("ghelp:///", zenity_locate_help_file (path, document), NULL); + pos = (gchar *) strchr (url, ':'); client = gconf_client_get_default (); diff --git a/src/util.h b/src/util.h index 99c20cb3..a9a7ded4 100644 --- a/src/util.h +++ b/src/util.h @@ -21,7 +21,8 @@ void zenity_util_set_window_icon (GtkWidget *widget, void zenity_util_set_window_icon_from_stock (GtkWidget *widget, const gchar *stock_id); -gboolean zenity_util_show_help (const gchar *url, +gboolean zenity_util_show_help (const gchar *path, + const gchar *document, GError **error); G_END_DECLS -- cgit