Commit e4881761 authored by Sven Neumann's avatar Sven Neumann Committed by Sven Neumann

plug-ins/help/Makefile.am new files with code to handle locales.

2004-03-18  Sven Neumann  <sven@gimp.org>

	* plug-ins/help/Makefile.am
	* plug-ins/help/locales.[ch]: new files with code to handle locales.

	* plug-ins/help/help.c: changed accordingly.

	* plug-ins/help/domain.[ch]: added support for a fallback URL to
        handle missing help content. i18n support is missing still.
parent 21ab6496
2004-03-18 Sven Neumann <sven@gimp.org>
* plug-ins/help/Makefile.am
* plug-ins/help/locales.[ch]: new files with code to handle locales.
* plug-ins/help/help.c: changed accordingly.
* plug-ins/help/domain.[ch]: added support for a fallback URL to
handle missing help content. i18n support is missing still.
2004-03-17 Simon Budig <simon@gimp.org>
* app/core/gimpbrushpipe.c: ensure that each rank of a
......@@ -10,6 +10,8 @@ libexec_PROGRAMS = help
help_SOURCES = \
domain.c \
domain.h \
locales.c \
locales.h \
help.c
INCLUDES = \
......
......@@ -23,11 +23,9 @@
#include "config.h"
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <glib-object.h>
#include <glib.h>
#include "libgimpbase/gimpbase.h"
......@@ -41,16 +39,17 @@ struct _HelpDomain
gchar *help_domain;
gchar *help_uri;
GHashTable *help_id_mapping;
gchar *help_missing;
};
/* local function prototypes */
HelpDomain * domain_new (const gchar *domain_name,
const gchar *domain_uri);
void domain_free (HelpDomain *domain);
gboolean domain_parse (HelpDomain *domain,
GError **error);
static HelpDomain * domain_new (const gchar *domain_name,
const gchar *domain_uri);
static void domain_free (HelpDomain *domain);
static gboolean domain_parse (HelpDomain *domain,
GError **error);
/* private variables */
......@@ -67,12 +66,14 @@ domain_register (const gchar *domain_name,
g_return_if_fail (domain_name != NULL);
g_return_if_fail (domain_uri != NULL);
#ifdef GIMP_HELP_DEBUG
g_printerr ("help: registering help domain \"%s\" with base uri \"%s\"\n",
domain_name, domain_uri);
#endif
if (! domain_hash)
domain_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, (GDestroyNotify ) domain_free);
g_free, (GDestroyNotify) domain_free);
g_hash_table_insert (domain_hash,
g_strdup (domain_name),
......@@ -91,15 +92,14 @@ domain_lookup (const gchar *domain_name)
}
gchar *
domain_map (HelpDomain *domain,
const gchar *help_locale,
const gchar *help_id)
domain_map (HelpDomain *domain,
GList *help_locales,
const gchar *help_id)
{
const gchar *ref;
gchar *full_uri;
g_return_val_if_fail (domain != NULL, NULL);
g_return_val_if_fail (help_locale != NULL, NULL);
g_return_val_if_fail (help_locales != NULL, NULL);
g_return_val_if_fail (help_id != NULL, NULL);
if (! domain->help_id_mapping)
......@@ -112,7 +112,8 @@ domain_map (HelpDomain *domain,
g_message (_("Failed to open help files:\n%s"), error->message);
else
g_message (_("Parse error in help domain:\n%s\n\n"
"(Added entires before error anyway)"), error->message);
"(entries appearing before the error have been added anyway)"),
error->message);
if (error)
g_clear_error (&error);
......@@ -124,29 +125,26 @@ domain_map (HelpDomain *domain,
ref = g_hash_table_lookup (domain->help_id_mapping, help_id);
if (! ref)
ref = domain->help_missing;
if (! ref)
{
g_message (_("Help ID '%s' unknown"), help_id);
return NULL;
}
full_uri = g_strconcat (domain->help_uri, "/",
help_locale, "/",
ref, NULL);
return full_uri;
return g_strconcat (domain->help_uri, "/", ref, NULL);
}
/* private functions */
HelpDomain *
static HelpDomain *
domain_new (const gchar *domain_name,
const gchar *domain_uri)
{
HelpDomain *domain;
domain = g_new0 (HelpDomain, 1);
HelpDomain *domain = g_new0 (HelpDomain, 1);
domain->help_domain = g_strdup (domain_name);
domain->help_uri = g_strdup (domain_uri);
......@@ -154,7 +152,7 @@ domain_new (const gchar *domain_name,
return domain;
}
void
static void
domain_free (HelpDomain *domain)
{
g_return_if_fail (domain != NULL);
......@@ -164,6 +162,7 @@ domain_free (HelpDomain *domain)
g_free (domain->help_domain);
g_free (domain->help_uri);
g_free (domain->help_missing);
g_free (domain);
}
......@@ -175,6 +174,7 @@ typedef enum
DOMAIN_START,
DOMAIN_IN_HELP,
DOMAIN_IN_ITEM,
DOMAIN_IN_MISSING,
DOMAIN_IN_UNKNOWN
} DomainParserState;
......@@ -191,6 +191,9 @@ typedef struct
gchar *id_attr_name;
} DomainParser;
static gboolean domain_parser_parse (GMarkupParseContext *context,
GIOChannel *io,
GError **error);
static void domain_parser_start_element (GMarkupParseContext *context,
const gchar *element_name,
const gchar **attribute_names,
......@@ -212,6 +215,9 @@ static void domain_parser_parse_namespace (DomainParser *parser,
static void domain_parser_parse_item (DomainParser *parser,
const gchar **names,
const gchar **values);
static void domain_parser_parse_missing (DomainParser *parser,
const gchar **names,
const gchar **values);
static const GMarkupParser markup_parser =
{
......@@ -222,7 +228,7 @@ static const GMarkupParser markup_parser =
domain_parser_error
};
gboolean
static gboolean
domain_parse (HelpDomain *domain,
GError **error)
{
......@@ -230,22 +236,24 @@ domain_parse (HelpDomain *domain,
DomainParser *parser;
gchar *base_dir;
gchar *filename;
FILE *fp;
gsize bytes;
gchar buf[4096];
GIOChannel *io;
g_return_val_if_fail (domain != NULL, FALSE);
g_return_val_if_fail (domain->help_id_mapping == NULL, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
base_dir = g_filename_from_uri (domain->help_uri, NULL, NULL);
filename = g_build_filename (base_dir, "gimp-help.xml", NULL);
g_free (base_dir);
fp = fopen (filename, "r");
if (! fp)
io = g_io_channel_new_file (filename, "r", error);
if (!io)
{
gchar *msg;
gchar *msg2;
const gchar *msg;
gchar *msg2;
if (! error)
return FALSE;
if (! strcmp (domain->help_domain, GIMP_HELP_DEFAULT_DOMAIN))
msg = _("The GIMP help files are not installed.");
......@@ -254,14 +262,16 @@ domain_parse (HelpDomain *domain,
msg2 = g_strdup_printf (_("Could not open '%s' for reading: %s"),
gimp_filename_to_utf8 (filename),
g_strerror (errno));
(*error)->message);
g_clear_error (error);
g_set_error (error, 0, 0, "%s\n\n%s\n\n%s",
msg, msg2, _("Please check your installation."));
g_free (msg2);
g_free (filename);
return FALSE;
}
......@@ -273,15 +283,10 @@ domain_parse (HelpDomain *domain,
context = g_markup_parse_context_new (&markup_parser, 0, parser, NULL);
while ((bytes = fread (buf, sizeof (gchar), sizeof (buf), fp)) > 0 &&
g_markup_parse_context_parse (context, buf, bytes, error))
;
domain_parser_parse (context, io, error);
if (error == NULL || *error == NULL)
g_markup_parse_context_end_parse (context, error);
fclose (fp);
g_markup_parse_context_free (context);
g_io_channel_unref (io);
g_string_free (parser->value, TRUE);
g_free (parser->id_attr_name);
......@@ -292,6 +297,38 @@ domain_parse (HelpDomain *domain,
return (domain->help_id_mapping != NULL);
}
static gboolean
domain_parser_parse (GMarkupParseContext *context,
GIOChannel *io,
GError **error)
{
GIOStatus status;
gsize len;
gchar buffer[4096];
while (TRUE)
{
if (! g_markup_parse_context_parse (context, buffer, len, error))
return FALSE;
status = g_io_channel_read_chars (io,
buffer, sizeof (buffer), &len, error);
switch (status)
{
case G_IO_STATUS_ERROR:
return FALSE;
case G_IO_STATUS_EOF:
return g_markup_parse_context_end_parse (context, error);
case G_IO_STATUS_NORMAL:
case G_IO_STATUS_AGAIN:
break;
}
}
return TRUE;
}
static void
domain_parser_start_element (GMarkupParseContext *context,
const gchar *element_name,
......@@ -308,8 +345,8 @@ domain_parser_start_element (GMarkupParseContext *context,
if (strcmp (element_name, "gimp-help") == 0)
{
parser->state = DOMAIN_IN_HELP;
domain_parser_parse_namespace (parser, attribute_names,
attribute_values);
domain_parser_parse_namespace (parser,
attribute_names, attribute_values);
}
else
domain_parser_start_unknown (parser);
......@@ -319,14 +356,21 @@ domain_parser_start_element (GMarkupParseContext *context,
if (strcmp (element_name, "help-item") == 0)
{
parser->state = DOMAIN_IN_ITEM;
domain_parser_parse_item (parser, attribute_names,
attribute_values);
domain_parser_parse_item (parser,
attribute_names, attribute_values);
}
else if (strcmp (element_name, "help-missing") == 0)
{
parser->state = DOMAIN_IN_MISSING;
domain_parser_parse_missing (parser,
attribute_names, attribute_values);
}
else
domain_parser_start_unknown (parser);
break;
case DOMAIN_IN_ITEM:
case DOMAIN_IN_MISSING:
case DOMAIN_IN_UNKNOWN:
domain_parser_start_unknown (parser);
break;
......@@ -352,6 +396,7 @@ domain_parser_end_element (GMarkupParseContext *context,
break;
case DOMAIN_IN_ITEM:
case DOMAIN_IN_MISSING:
parser->state = DOMAIN_IN_HELP;
break;
......@@ -397,7 +442,7 @@ domain_parser_parse_namespace (DomainParser *parser,
const gchar **names,
const gchar **values)
{
while (*names && *values)
for (; *names && *values; names++, values++)
{
if (! strncmp (*names, "xmlns:", 6) &&
! strcmp (*values, parser->domain->help_domain))
......@@ -405,12 +450,11 @@ domain_parser_parse_namespace (DomainParser *parser,
g_free (parser->id_attr_name);
parser->id_attr_name = g_strdup_printf ("%s:id", *names + 6);
#ifdef GIMP_HELP_DEBUG
g_printerr ("help: id attribute name for \"%s\" is \"%s\"\n",
parser->domain->help_domain, parser->id_attr_name);
#endif
}
names++;
values++;
}
}
......@@ -422,16 +466,13 @@ domain_parser_parse_item (DomainParser *parser,
const gchar *id = NULL;
const gchar *ref = NULL;
while (*names && *values)
for (; *names && *values; names++, values++)
{
if (! strcmp (*names, parser->id_attr_name))
id = *values;
if (! strcmp (*names, "ref"))
ref = *values;
names++;
values++;
}
if (id && ref)
......@@ -445,6 +486,32 @@ domain_parser_parse_item (DomainParser *parser,
g_hash_table_insert (parser->domain->help_id_mapping,
g_strdup (id), g_strdup (ref));
#ifdef GIMP_HELP_DEBUG
g_printerr ("help: added mapping \"%s\" -> \"%s\"\n", id, ref);
#endif
}
}
static void
domain_parser_parse_missing (DomainParser *parser,
const gchar **names,
const gchar **values)
{
const gchar *ref = NULL;
for (; *names && *values; names++, values++)
{
if (! strcmp (*names, "ref"))
ref = *values;
}
if (ref &&
parser->domain->help_missing == NULL)
{
parser->domain->help_missing = g_strdup (ref);
#ifdef GIMP_HELP_DEBUG
g_printerr ("help: added fallback for missing help -> \"%s\"\n", ref);
#endif
}
}
......@@ -31,13 +31,13 @@
typedef struct _HelpDomain HelpDomain;
void domain_register (const gchar *domain_name,
const gchar *domain_uri);
HelpDomain * domain_lookup (const gchar *domain_name);
void domain_register (const gchar *domain_name,
const gchar *domain_uri);
HelpDomain * domain_lookup (const gchar *domain_name);
gchar * domain_map (HelpDomain *domain,
const gchar *help_locale,
const gchar *help_id);
gchar * domain_map (HelpDomain *domain,
GList *help_locales,
const gchar *help_id);
#endif /* ! __DOMAIN_H__ */
......@@ -23,11 +23,9 @@
#include "config.h"
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <glib-object.h>
#include <glib.h>
#include "libgimpbase/gimpbase.h"
......@@ -41,16 +39,17 @@ struct _HelpDomain
gchar *help_domain;
gchar *help_uri;
GHashTable *help_id_mapping;
gchar *help_missing;
};
/* local function prototypes */
HelpDomain * domain_new (const gchar *domain_name,
const gchar *domain_uri);
void domain_free (HelpDomain *domain);
gboolean domain_parse (HelpDomain *domain,
GError **error);
static HelpDomain * domain_new (const gchar *domain_name,
const gchar *domain_uri);
static void domain_free (HelpDomain *domain);
static gboolean domain_parse (HelpDomain *domain,
GError **error);
/* private variables */
......@@ -67,12 +66,14 @@ domain_register (const gchar *domain_name,
g_return_if_fail (domain_name != NULL);
g_return_if_fail (domain_uri != NULL);
#ifdef GIMP_HELP_DEBUG
g_printerr ("help: registering help domain \"%s\" with base uri \"%s\"\n",
domain_name, domain_uri);
#endif
if (! domain_hash)
domain_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, (GDestroyNotify ) domain_free);
g_free, (GDestroyNotify) domain_free);
g_hash_table_insert (domain_hash,
g_strdup (domain_name),
......@@ -91,15 +92,14 @@ domain_lookup (const gchar *domain_name)
}
gchar *
domain_map (HelpDomain *domain,
const gchar *help_locale,
const gchar *help_id)
domain_map (HelpDomain *domain,
GList *help_locales,
const gchar *help_id)
{
const gchar *ref;
gchar *full_uri;
g_return_val_if_fail (domain != NULL, NULL);
g_return_val_if_fail (help_locale != NULL, NULL);
g_return_val_if_fail (help_locales != NULL, NULL);
g_return_val_if_fail (help_id != NULL, NULL);
if (! domain->help_id_mapping)
......@@ -112,7 +112,8 @@ domain_map (HelpDomain *domain,
g_message (_("Failed to open help files:\n%s"), error->message);
else
g_message (_("Parse error in help domain:\n%s\n\n"
"(Added entires before error anyway)"), error->message);
"(entries appearing before the error have been added anyway)"),
error->message);
if (error)
g_clear_error (&error);
......@@ -124,29 +125,26 @@ domain_map (HelpDomain *domain,
ref = g_hash_table_lookup (domain->help_id_mapping, help_id);
if (! ref)
ref = domain->help_missing;
if (! ref)
{
g_message (_("Help ID '%s' unknown"), help_id);
return NULL;
}
full_uri = g_strconcat (domain->help_uri, "/",
help_locale, "/",
ref, NULL);
return full_uri;
return g_strconcat (domain->help_uri, "/", ref, NULL);
}
/* private functions */
HelpDomain *
static HelpDomain *
domain_new (const gchar *domain_name,
const gchar *domain_uri)
{
HelpDomain *domain;
domain = g_new0 (HelpDomain, 1);
HelpDomain *domain = g_new0 (HelpDomain, 1);
domain->help_domain = g_strdup (domain_name);
domain->help_uri = g_strdup (domain_uri);
......@@ -154,7 +152,7 @@ domain_new (const gchar *domain_name,
return domain;
}
void
static void
domain_free (HelpDomain *domain)
{
g_return_if_fail (domain != NULL);
......@@ -164,6 +162,7 @@ domain_free (HelpDomain *domain)
g_free (domain->help_domain);
g_free (domain->help_uri);
g_free (domain->help_missing);
g_free (domain);
}
......@@ -175,6 +174,7 @@ typedef enum
DOMAIN_START,
DOMAIN_IN_HELP,
DOMAIN_IN_ITEM,
DOMAIN_IN_MISSING,
DOMAIN_IN_UNKNOWN
} DomainParserState;
......@@ -191,6 +191,9 @@ typedef struct
gchar *id_attr_name;
} DomainParser;
static gboolean domain_parser_parse (GMarkupParseContext *context,
GIOChannel *io,
GError **error);
static void domain_parser_start_element (GMarkupParseContext *context,
const gchar *element_name,
const gchar **attribute_names,
......@@ -212,6 +215,9 @@ static void domain_parser_parse_namespace (DomainParser *parser,
static void domain_parser_parse_item (DomainParser *parser,
const gchar **names,
const gchar **values);
static void domain_parser_parse_missing (DomainParser *parser,
const gchar **names,
const gchar **values);
static const GMarkupParser markup_parser =
{
......@@ -222,7 +228,7 @@ static const GMarkupParser markup_parser =
domain_parser_error
};
gboolean
static gboolean
domain_parse (HelpDomain *domain,
GError **error)
{
......@@ -230,22 +236,24 @@ domain_parse (HelpDomain *domain,
DomainParser *parser;
gchar *base_dir;
gchar *filename;
FILE *fp;
gsize bytes;
gchar buf[4096];
GIOChannel *io;
g_return_val_if_fail (domain != NULL, FALSE);
g_return_val_if_fail (domain->help_id_mapping == NULL, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
base_dir = g_filename_from_uri (domain->help_uri, NULL, NULL);
filename = g_build_filename (base_dir, "gimp-help.xml", NULL);
g_free (base_dir);
fp = fopen (filename, "r");
if (! fp)
io = g_io_channel_new_file (filename, "r", error);
if (!io)
{
gchar *msg;
gchar *msg2;
const gchar *msg;
gchar *msg2;
if (! error)
return FALSE;
if (! strcmp (domain->help_domain, GIMP_HELP_DEFAULT_DOMAIN))
msg = _("The GIMP help files are not installed.");
......@@ -254,14 +262,16 @@ domain_parse (HelpDomain *domain,
msg2 = g_strdup_printf (_("Could not open '%s' for reading: %s"),
gimp_filename_to_utf8 (filename),
g_strerror (errno));
(*error)->message);
g_clear_error (error);
g_set_error (error, 0, 0, "%s\n\n%s\n\n%s",
msg, msg2, _("Please check your installation."));
g_free (msg2);
g_free (filename);
return FALSE;
}
......@@ -273,15 +283,10 @@ domain_parse (HelpDomain *domain,
context = g_markup_parse_context_new (&markup_parser, 0, parser, NULL);
while ((bytes = fread (buf, sizeof (gchar), sizeof (buf), fp)) > 0 &&
g_markup_parse_context_parse (context, buf, bytes, error))
;
domain_parser_parse (context, io, error);
if (error == NULL || *error == NULL)
g_markup_parse_context_end_parse (context, error);
fclose (fp);
g_markup_parse_context_free (context);
g_io_channel_unref (io);
g_string_free (parser->value, TRUE);
g_free (parser->id_attr_name);
......@@ -292,6 +297,38 @@ domain_parse (HelpDomain *domain,
return (domain->help_id_mapping != NULL);
}
static gboolean
domain_parser_parse (GMarkupParseContext *context,
GIOChannel *io,
GError **error)
{
GIOStatus status;
gsize len;
gchar buffer[4096];
while (TRUE)
{
if (! g_markup_parse_context_parse (context, buffer, len, error))
return FALSE;
status = g_io_channel_read_chars (io,
buffer, sizeof (buffer), &len, error);
switch (status)
{
case G_IO_STATUS_ERROR:
return FALSE;
case G_IO_STATUS_EOF:
return g_markup_parse_context_end_parse (context, error);
case G_IO_STATUS_NORMAL:
case G_IO_STATUS_AGAIN:
break;
}
}
return TRUE;
}
static void
domain_parser_start_element (GMarkupParseContext *context,
const gchar *element_name,
......@@ -308,8 +345,8 @@ domain_parser_start_element (GMarkupParseContext *context,
if (strcmp (element_name, "gimp-help") == 0)
{
parser->state = DOMAIN_IN_HELP;
domain_parser_parse_namespace (parser, attribute_names,
attribute_values);
domain_parser_parse_namespace (parser,
attribute_names, attribute_values);
}
else
domain_parser_start_unknown (parser);
......@@ -319,14 +356,21 @@ domain_parser_start_element (GMarkupParseContext *context,
if (strcmp (element_name, "help-item") == 0)
{
parser->state = DOMAIN_IN_ITEM;
domain_parser_parse_item (parser, attribute_names,
attribute_values);
domain_parser_parse_item (parser,
attribute_names, attribute_values);
}
else if (strcmp (element_name, "help-missing") == 0)
{
parser->state = DOMAIN_IN_MISSING;
domain_parser_parse_missing (parser,
attribute_names, attribute_values);
}
else
domain_parser_start_unknown (parser);
break;
case DOMAIN_IN_ITEM:
case DOMAIN_IN_MISSING:
case DOMAIN_IN_UNKNOWN:
domain_parser_start_unknown (parser);
break;
......@@ -352,6 +396,7 @@ domain_parser_end_element (GMarkupParseContext *context,
break;
case DOMAIN_IN_ITEM:
case DOMAIN_IN_MISSING:
parser->state = DOMAIN_IN_HELP;
break;
......@@ -397,7 +442,7 @@ domain_parser_parse_namespace (DomainParser *parser,
const gchar **names,
const gchar **values)
{
while (*names && *values)
for (; *names && *values; names++, values++)
{
if (! strncmp (*names, "xmlns:", 6) &&
! strcmp (*values, parser->domain