Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Gimp/plug-ins/help/   (Gimp Bildeditor Version 3.2.0©)  Datei vom 14.2.2026 mit Größe 16 kB image not shown  

Quelle  gimphelplocale.c   Sprache: C

 

/* GIMP - The GNU Image Manipulation Program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * The GIMP Help plug-in
 * Copyright (C) 1999-2008 Sven Neumann <sven@gimp.org>
 *                         Michael Natterer <mitch@gimp.org>
 *                         Henrik Brix Andersen <brix@gimp.org>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */


/*  This code is written so that it can also be compiled standalone.
 *  It shouldn't depend on libgimp.
 */


#include "config.h"

#include <string.h>

#include <glib-object.h>
#include <gio/gio.h>

#include "gimphelp.h"
#include "gimphelpprogress-private.h"

#ifdef DISABLE_NLS
#define _(String)  (String)
#else
#include "libgimp/stdplugins-intl.h"
#endif

#ifdef PLATFORM_OSX
#include <Foundation/Foundation.h>
#endif

/*  local function prototypes  */

static void   locale_set_error (GError      **error,
                                const gchar  *format,
                                GFile        *file);


/*  public functions  */

GimpHelpLocale *
gimp_help_locale_new (const gchar *locale_id)
{
  GimpHelpLocale *locale = g_slice_new0 (GimpHelpLocale);

  locale->locale_id = g_strdup (locale_id);

  return locale;
}

void
gimp_help_locale_free (GimpHelpLocale *locale)
{
  g_return_if_fail (locale != NULL);

  if (locale->help_id_mapping)
    g_hash_table_destroy (locale->help_id_mapping);

  g_free (locale->locale_id);
  g_free (locale->help_missing);

  g_list_free (locale->toplevel_items);

  g_slice_free (GimpHelpLocale, locale);
}

const gchar *
gimp_help_locale_map (GimpHelpLocale *locale,
                      const gchar    *help_id)
{
  g_return_val_if_fail (locale != NULL, NULL);
  g_return_val_if_fail (help_id != NULL, NULL);

  if (locale->help_id_mapping)
    {
      GimpHelpItem *item = g_hash_table_lookup (locale->help_id_mapping,
                                                help_id);

      if (item)
        return item->ref;
    }

  return NULL;
}


/*  the locale mapping parser  */

typedef enum
{
  LOCALE_START,
  LOCALE_IN_HELP,
  LOCALE_IN_ITEM,
  LOCALE_IN_MISSING,
  LOCALE_IN_UNKNOWN
} LocaleParserState;

typedef struct
{
  GFile             *file;
  LocaleParserState  state;
  LocaleParserState  last_known_state;
  gint               markup_depth;
  gint               unknown_depth;
  GString           *value;

  GimpHelpLocale    *locale;
  const gchar       *help_domain;
  gchar             *id_attr_name;
} LocaleParser;

static gboolean  locale_parser_parse       (GMarkupParseContext  *context,
                                            GimpHelpProgress     *progress,
                                            GInputStream         *stream,
                                            goffset               size,
                                            GCancellable         *cancellable,
                                            GError              **error);
static void  locale_parser_start_element   (GMarkupParseContext  *context,
                                            const gchar          *element_name,
                                            const gchar         **attribute_names,
                                            const gchar         **attribute_values,
                                            gpointer              user_data,
                                            GError              **error);
static void  locale_parser_end_element     (GMarkupParseContext  *context,
                                            const gchar          *element_name,
                                            gpointer              user_data,
                                            GError              **error);
static void  locale_parser_error           (GMarkupParseContext  *context,
                                            GError               *error,
                                            gpointer              user_data);
static void  locale_parser_start_unknown   (LocaleParser         *parser);
static void  locale_parser_end_unknown     (LocaleParser         *parser);
static void  locale_parser_parse_namespace (LocaleParser         *parser,
                                            const gchar         **names,
                                            const gchar         **values);
static void  locale_parser_parse_item      (LocaleParser         *parser,
                                            const gchar         **names,
                                            const gchar         **values);
static void  locale_parser_parse_missing   (LocaleParser         *parser,
                                            const gchar         **names,
                                            const gchar         **values);

static const GMarkupParser markup_parser =
{
  locale_parser_start_element,
  locale_parser_end_element,
  NULL,  /*  characters   */
  NULL,  /*  passthrough  */
  locale_parser_error
};

gboolean
gimp_help_locale_parse (GimpHelpLocale    *locale,
                        const gchar       *uri,
                        const gchar       *help_domain,
                        GimpHelpProgress  *progress,
                        GError           **error)
{
  GMarkupParseContext *context;
  GFile               *file        = NULL;
  GCancellable        *cancellable = NULL;
  LocaleParser         parser      = { NULL, };
#ifdef PLATFORM_OSX
  NSURL               *fileURL;
  NSString            *nsUri;
  NSData              *data;
  const gchar         *str;
#else
  GFileInputStream    *stream;
  goffset              size        = 0;
#endif
  gboolean             success;

  g_return_val_if_fail (locale != NULL, FALSE);
  g_return_val_if_fail (uri != NULL, FALSE);
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

  if (locale->help_id_mapping)
    {
      g_hash_table_destroy (locale->help_id_mapping);
      locale->help_id_mapping = NULL;
    }

  if (locale->help_missing)
    {
      g_free (locale->help_missing);
      locale->help_missing = NULL;
    }

#ifdef GIMP_HELP_DEBUG
  g_printerr ("help (%s): parsing '%s' for \"%s\"\n",
              locale->locale_id, uri, help_domain);
#endif

  file = g_file_new_for_uri (uri);

  if (progress)
    {
      gchar *name = g_file_get_parse_name (file);

      cancellable = g_cancellable_new ();
      _gimp_help_progress_start (progress, cancellable,
                                 _("Loading index from '%s'"), name);

      g_clear_object (&cancellable);
      g_free (name);
    }

#ifdef PLATFORM_OSX
  nsUri   = [NSString stringWithUTF8String: uri];
  fileURL = [NSURL URLWithString: nsUri];
  [nsUri release];

  if (progress)
    _gimp_help_progress_pulse (progress);

  /* Load the data from the remote URL into the NSData object */
  data = [NSData dataWithContentsOfURL:fileURL];
  [fileURL release];

  if (! data)
    {
      locale_set_error (error,
                        _("Could not load data from '%s': %s"), file);
      g_object_unref (file);
      return FALSE;
    }

  if (progress)
    _gimp_help_progress_pulse (progress);
#else /* PLATFORM_OSX */
  if (progress)
    {
      GFileInfo *info = g_file_query_info (file,
                                           G_FILE_ATTRIBUTE_STANDARD_SIZE, 0,
                                           cancellable, error);
      if (! info)
        {
          locale_set_error (error,
                            _("Could not open '%s' for reading: %s"), file);
          g_object_unref (file);

          return FALSE;
        }

      size = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_SIZE);

      g_object_unref (info);
    }

  stream = g_file_read (file, cancellable, error);

  if (! stream)
    {
      locale_set_error (error,
                        _("Could not open '%s' for reading: %s"), file);
      g_object_unref (file);

      return FALSE;
    }
#endif /* ! PLATFORM_OSX */

  parser.file         = file;
  parser.value        = g_string_new (NULL);
  parser.locale       = locale;
  parser.help_domain  = help_domain;
  parser.id_attr_name = g_strdup ("id");

  context = g_markup_parse_context_new (&markup_parser, 0, &parser, NULL);

#ifdef PLATFORM_OSX
  str = (const char *)[data bytes];

  if (! g_markup_parse_context_parse (context, str, [data length], error))
    success = FALSE;
  else
    success = g_markup_parse_context_end_parse (context, error);

  [data release];
#else /* PLATFORM_OSX */
  success = locale_parser_parse (context, progress,
                                 G_INPUT_STREAM (stream), size,
                                 cancellable, error);

  g_object_unref (stream);
#endif /* ! PLATFORM_OSX */
  if (progress)
    _gimp_help_progress_finish (progress);

  g_markup_parse_context_free (context);

  g_string_free (parser.value, TRUE);
  g_free (parser.id_attr_name);

  if (! success)
    locale_set_error (error, _("Parse error in '%s':\n%s"), file);

  g_object_unref (file);

  return success;
}

static gboolean
locale_parser_parse (GMarkupParseContext  *context,
                     GimpHelpProgress     *progress,
                     GInputStream         *stream,
                     goffset               size,
                     GCancellable         *cancellable,
                     GError              **error)
{
  gssize  len;
  goffset done = 0;
  gchar   buffer[4096];

  while ((len = g_input_stream_read (stream, buffer, sizeof (buffer),
                                     cancellable, error)) != -1)
    {
      switch (len)
        {
        case 0:
          return g_markup_parse_context_end_parse (context, error);

        default:
          done += len;

          if (progress)
            {
              if (size > 0)
                _gimp_help_progress_update (progress, (gdouble) done / size);
              else
                _gimp_help_progress_pulse (progress);
            }

          if (! g_markup_parse_context_parse (context, buffer, len, error))
            return FALSE;
        }
    }

  return FALSE;
}

static void
locale_parser_start_element (GMarkupParseContext *context,
                             const gchar         *element_name,
                             const gchar        **attribute_names,
                             const gchar        **attribute_values,
                             gpointer             user_data,
                             GError             **error)
{
  LocaleParser *parser = (LocaleParser *) user_data;

  switch (parser->state)
    {
    case LOCALE_START:
      if (strcmp (element_name, "gimp-help") == 0)
        {
          parser->state = LOCALE_IN_HELP;
          locale_parser_parse_namespace (parser,
                                         attribute_names, attribute_values);
        }
      else
        locale_parser_start_unknown (parser);
      break;

    case LOCALE_IN_HELP:
      if (strcmp (element_name, "help-item") == 0)
        {
          parser->state = LOCALE_IN_ITEM;
          locale_parser_parse_item (parser,
                                    attribute_names, attribute_values);
        }
      else if (strcmp (element_name, "help-missing") == 0)
        {
          parser->state = LOCALE_IN_MISSING;
          locale_parser_parse_missing (parser,
                                       attribute_names, attribute_values);
        }
      else
        locale_parser_start_unknown (parser);
      break;

    case LOCALE_IN_ITEM:
    case LOCALE_IN_MISSING:
    case LOCALE_IN_UNKNOWN:
      locale_parser_start_unknown (parser);
      break;
    }
}

static void
locale_parser_end_element (GMarkupParseContext *context,
                           const gchar         *element_name,
                           gpointer             user_data,
                           GError             **error)
{
  LocaleParser *parser = (LocaleParser *) user_data;

  switch (parser->state)
    {
    case LOCALE_START:
      g_warning ("locale_parser: This shouldn't happen.");
      break;

    case LOCALE_IN_HELP:
      parser->state = LOCALE_START;
      break;

    case LOCALE_IN_ITEM:
    case LOCALE_IN_MISSING:
      parser->state = LOCALE_IN_HELP;
      break;

    case LOCALE_IN_UNKNOWN:
      locale_parser_end_unknown (parser);
      break;
    }
}

static void
locale_parser_error (GMarkupParseContext *context,
                     GError              *error,
                     gpointer             user_data)
{
  LocaleParser *parser = (LocaleParser *) user_data;
  gchar        *name   = g_file_get_parse_name (parser->file);

  g_printerr ("help (parsing %s): %s", name, error->message);

  g_free (name);
}

static void
locale_parser_start_unknown (LocaleParser *parser)
{
  if (parser->unknown_depth == 0)
    parser->last_known_state = parser->state;

  parser->state = LOCALE_IN_UNKNOWN;
  parser->unknown_depth++;
}

static void
locale_parser_end_unknown (LocaleParser *parser)
{
  g_assert (parser->unknown_depth > 0 && parser->state == LOCALE_IN_UNKNOWN);

  parser->unknown_depth--;

  if (parser->unknown_depth == 0)
    parser->state = parser->last_known_state;
}

static void
locale_parser_parse_namespace (LocaleParser  *parser,
                               const gchar  **names,
                               const gchar  **values)
{
  for (; *names && *values; names++, values++)
    {
      if (! strncmp (*names, "xmlns:", 6) &&
          ! strcmp (*values, parser->help_domain))
        {
          g_free (parser->id_attr_name);
          parser->id_attr_name = g_strdup_printf ("%s:id", *names + 6);

#ifdef GIMP_HELP_DEBUG
          g_printerr ("help (%s): id attribute name for \"%s\" is \"%s\"\n",
                      parser->locale->locale_id,
                      parser->help_domain,
                      parser->id_attr_name);
#endif
        }
    }
}

static void
locale_parser_parse_item (LocaleParser  *parser,
                          const gchar  **names,
                          const gchar  **values)
{
  const gchar *id     = NULL;
  const gchar *ref    = NULL;
  const gchar *title  = NULL;
  const gchar *sort   = NULL;  /* optional sort key provided by doc team */
  const gchar *parent = NULL;

  for (; *names && *values; names++, values++)
    {
      if (! strcmp (*names, parser->id_attr_name))
        id = *values;

      if (! strcmp (*names, "ref"))
        ref = *values;

      if (! strcmp (*names, "title"))
        title = *values;

      if (! strcmp (*names, "sort"))
        sort = *values;

      if (! strcmp (*names, "parent"))
        parent = *values;
    }

  if (id && ref)
    {
      if (! parser->locale->help_id_mapping)
        parser->locale->help_id_mapping =
          g_hash_table_new_full (g_str_hash,
                                 g_str_equal,
                                 g_free,
                                 (GDestroyNotify) gimp_help_item_free);

      g_hash_table_insert (parser->locale->help_id_mapping,
                           g_strdup (id),
                           gimp_help_item_new (ref, title, sort, parent));

#ifdef GIMP_HELP_DEBUG
      g_printerr ("help (%s): added mapping \"%s\" -> \"%s\"\n",
                  parser->locale->locale_id, id, ref);
#endif
    }
}

static void
locale_parser_parse_missing (LocaleParser  *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->locale->help_missing == NULL)
    {
      parser->locale->help_missing = g_strdup (ref);

#ifdef GIMP_HELP_DEBUG
      g_printerr ("help (%s): added fallback for missing help -> \"%s\"\n",
                  parser->locale->locale_id, ref);
#endif
    }
}

static void
locale_set_error (GError      **error,
                  const gchar  *format,
                  GFile        *file)
{
  if (error && *error)
    {
      gchar *name = g_file_get_parse_name (file);
      gchar *msg;

      msg = g_strdup_printf (format, name, (*error)->message);
      g_free (name);

      g_free ((*error)->message);
      (*error)->message = msg;
    }
}

Messung
CHZG
81999391

¤ Dauer der Verarbeitung: 0.2 Sekunden  (vorverarbeitet am  2026-11-04) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.