Blame gladeui/glade-name-context.c

Packit 1e8aac
/*
Packit 1e8aac
 * glade-name-context.c
Packit 1e8aac
 *
Packit 1e8aac
 * Copyright (C) 2008 Tristan Van Berkom.
Packit 1e8aac
 *
Packit 1e8aac
 * This library is free software; you can redistribute it and/or modify it
Packit 1e8aac
 * under the terms of the GNU Lesser General Public License as
Packit 1e8aac
 * published by the Free Software Foundation; either version 2.1 of
Packit 1e8aac
 * the License, or (at your option) any later version.
Packit 1e8aac
 *
Packit 1e8aac
 * This library is distributed in the hope that it will be useful, but
Packit 1e8aac
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 1e8aac
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 1e8aac
 * Lesser General Public License for more details.
Packit 1e8aac
 *
Packit 1e8aac
 * You should have received a copy of the GNU Lesser General Public 
Packit 1e8aac
 * License along with this program; if not, write to the Free Software
Packit 1e8aac
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Packit 1e8aac
 *
Packit 1e8aac
 * Authors:
Packit 1e8aac
 *   Tristan Van Berkom <tvb@gnome.org>
Packit 1e8aac
 *
Packit 1e8aac
 */
Packit 1e8aac
#ifdef HAVE_CONFIG_H
Packit 1e8aac
#include <config.h>
Packit 1e8aac
#endif
Packit 1e8aac
Packit 1e8aac
#include <string.h>
Packit 1e8aac
#include <stdlib.h>
Packit 1e8aac
Packit 1e8aac
#include "glade-id-allocator.h"
Packit 1e8aac
#include "glade-name-context.h"
Packit 1e8aac
Packit 1e8aac
struct _GladeNameContext
Packit 1e8aac
{
Packit 1e8aac
  GHashTable *name_allocators;
Packit 1e8aac
Packit 1e8aac
  GHashTable *names;
Packit 1e8aac
};
Packit 1e8aac
Packit 1e8aac
GladeNameContext *
Packit 1e8aac
glade_name_context_new (void)
Packit 1e8aac
{
Packit 1e8aac
  GladeNameContext *context = g_slice_new0 (GladeNameContext);
Packit 1e8aac
Packit 1e8aac
  context->name_allocators = g_hash_table_new_full (g_str_hash,
Packit 1e8aac
                                                    g_str_equal,
Packit 1e8aac
                                                    g_free,
Packit 1e8aac
                                                    (GDestroyNotify)
Packit 1e8aac
                                                    glade_id_allocator_destroy);
Packit 1e8aac
Packit 1e8aac
  context->names = g_hash_table_new_full (g_str_hash,
Packit 1e8aac
                                          g_str_equal, g_free, NULL);
Packit 1e8aac
Packit 1e8aac
  return context;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
void
Packit 1e8aac
glade_name_context_destroy (GladeNameContext *context)
Packit 1e8aac
{
Packit 1e8aac
  g_return_if_fail (context != NULL);
Packit 1e8aac
Packit 1e8aac
  g_hash_table_destroy (context->name_allocators);
Packit 1e8aac
  g_hash_table_destroy (context->names);
Packit 1e8aac
  g_slice_free (GladeNameContext, context);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
gchar *
Packit 1e8aac
glade_name_context_new_name (GladeNameContext *context,
Packit 1e8aac
                             const gchar      *base_name)
Packit 1e8aac
{
Packit 1e8aac
  GladeIDAllocator *id_allocator;
Packit 1e8aac
  const gchar *number;
Packit 1e8aac
  gchar *name = NULL, *freeme = NULL;
Packit 1e8aac
  guint i = 1;
Packit 1e8aac
Packit 1e8aac
  g_return_val_if_fail (context != NULL, NULL);
Packit 1e8aac
  g_return_val_if_fail (base_name && base_name[0], NULL);
Packit 1e8aac
Packit 1e8aac
  number = base_name + strlen (base_name);
Packit 1e8aac
  while (number > base_name && g_ascii_isdigit (number[-1]))
Packit 1e8aac
    --number;
Packit 1e8aac
Packit 1e8aac
  if (*number)
Packit 1e8aac
    {
Packit 1e8aac
      freeme = g_strndup (base_name, number - base_name);
Packit 1e8aac
      base_name = freeme;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  id_allocator = g_hash_table_lookup (context->name_allocators, base_name);
Packit 1e8aac
Packit 1e8aac
  if (id_allocator == NULL)
Packit 1e8aac
    {
Packit 1e8aac
      id_allocator = glade_id_allocator_new ();
Packit 1e8aac
      g_hash_table_insert (context->name_allocators,
Packit 1e8aac
                           g_strdup (base_name), id_allocator);
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  do
Packit 1e8aac
    {
Packit 1e8aac
      g_free (name);
Packit 1e8aac
      i = glade_id_allocator_allocate (id_allocator);
Packit 1e8aac
      name = g_strdup_printf ("%s%u", base_name, i);
Packit 1e8aac
    }
Packit 1e8aac
  while (glade_name_context_has_name (context, name));
Packit 1e8aac
Packit 1e8aac
  g_free (freeme);
Packit 1e8aac
  return name;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
guint
Packit 1e8aac
glade_name_context_n_names (GladeNameContext *context)
Packit 1e8aac
{
Packit 1e8aac
  g_return_val_if_fail (context != NULL, FALSE);
Packit 1e8aac
Packit 1e8aac
  return g_hash_table_size (context->names);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
gboolean
Packit 1e8aac
glade_name_context_has_name (GladeNameContext *context, const gchar *name)
Packit 1e8aac
{
Packit 1e8aac
  g_return_val_if_fail (context != NULL, FALSE);
Packit 1e8aac
  g_return_val_if_fail (name && name[0], FALSE);
Packit 1e8aac
Packit 1e8aac
  return (g_hash_table_lookup (context->names, name) != NULL);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
gboolean
Packit 1e8aac
glade_name_context_add_name (GladeNameContext *context, const gchar *name)
Packit 1e8aac
{
Packit 1e8aac
  gboolean ret = FALSE;
Packit 1e8aac
Packit 1e8aac
  g_return_val_if_fail (context != NULL, FALSE);
Packit 1e8aac
  g_return_val_if_fail (name && name[0], FALSE);
Packit 1e8aac
Packit 1e8aac
  if (!glade_name_context_has_name (context, name))
Packit 1e8aac
    {
Packit 1e8aac
      g_hash_table_insert (context->names, g_strdup (name),
Packit 1e8aac
                           GINT_TO_POINTER (TRUE));
Packit 1e8aac
      ret = TRUE;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  return ret;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
void
Packit 1e8aac
glade_name_context_release_name (GladeNameContext *context, const gchar *name)
Packit 1e8aac
{
Packit 1e8aac
Packit 1e8aac
  const gchar *first_number = name;
Packit 1e8aac
  gchar *end_number, *base_name;
Packit 1e8aac
  GladeIDAllocator *id_allocator;
Packit 1e8aac
  gunichar ch;
Packit 1e8aac
  gint id;
Packit 1e8aac
Packit 1e8aac
  g_return_if_fail (context != NULL);
Packit 1e8aac
  g_return_if_fail (name && name[0]);
Packit 1e8aac
Packit 1e8aac
  /* Remove from name hash first... */
Packit 1e8aac
  g_hash_table_remove (context->names, name);
Packit 1e8aac
Packit 1e8aac
  do
Packit 1e8aac
    {
Packit 1e8aac
      ch = g_utf8_get_char (first_number);
Packit 1e8aac
Packit 1e8aac
      if (ch == 0 || g_unichar_isdigit (ch))
Packit 1e8aac
        break;
Packit 1e8aac
Packit 1e8aac
      first_number = g_utf8_next_char (first_number);
Packit 1e8aac
    }
Packit 1e8aac
  while (TRUE);
Packit 1e8aac
Packit 1e8aac
  /* if there is a number - then we have to unallocate it... */
Packit 1e8aac
  if (ch == 0)
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  base_name = g_strdup (name);
Packit 1e8aac
  *(base_name + (first_number - name)) = 0;
Packit 1e8aac
Packit 1e8aac
  if ((id_allocator =
Packit 1e8aac
       g_hash_table_lookup (context->name_allocators, base_name)) != NULL)
Packit 1e8aac
    {
Packit 1e8aac
      id = (int) strtol (first_number, &end_number, 10);
Packit 1e8aac
      if (*end_number == 0)
Packit 1e8aac
	glade_id_allocator_release (id_allocator, id);
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  g_free (base_name);
Packit 1e8aac
}