Logo Search packages:      
Sourcecode: kazehakase version File versions

kz-profile.c

/*
 *  Profile
 *  copyright (c) 2002-2003 Kazuki IWAMOTO http://www.maid.org/ iwm@maid.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 2 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, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/*
 *  2003-10-26 Takuro Ashie <ashie@homa.ne.jp>
 *      Copy section and key string before delete it.
 *
 *  2003-09-03 Takuro Ashie <ashie@homa.ne.jp>
 *      Added Kz and kz_ prefix.
 *      GObjectize.
 *      Remove also space befor a section when delete it.
 *      Added const keyword for value field of KzPrrofileList.
 *
 *  2003-08-28 Takuro Ashie <ashie@homa.ne.jp>
 *      Translated comments into English.
 *
 *  2003-08-27 Takuro Ashie <ashie@homa.ne.jp>
 *      Aggregated related codes into this file.
 *      Modified coding style.
 *      Simplize profile_open().
 */

#include "kz-profile.h"

#include <stdio.h>
#include <string.h>
#include "gobject-utils.h"
#include "glib-utils.h"
#include "kz-marshalers.h"


enum {
      SECTION_ADDED_SIGNAL,
      SECTION_DELETED_SIGNAL,
      KEY_ADDED_SIGNAL,
      KEY_DELETED_SIGNAL,
      CHANGED_SIGNAL,
      LAST_SIGNAL
};


static void kz_profile_class_init (KzProfileClass *klass);
static void kz_profile_init       (KzProfile      *profile);
static void kz_profile_dispose    (GObject        *object);


static GObjectClass *parent_class = NULL;

static gint kz_profile_signals[LAST_SIGNAL] = {0};


KZ_OBJECT_GET_TYPE(kz_profile, "KzProfile", KzProfile,
               kz_profile_class_init, kz_profile_init,
               G_TYPE_OBJECT)


static void
kz_profile_class_init (KzProfileClass *klass)
{
      GObjectClass *object_class;

      parent_class = g_type_class_peek_parent (klass);
      object_class = (GObjectClass *) klass;

      object_class->dispose = kz_profile_dispose;

      klass->section_added   = NULL;
      klass->section_deleted = NULL;
      klass->key_added       = NULL;
      klass->key_deleted     = NULL;
      klass->changed         = NULL;

      kz_profile_signals[SECTION_ADDED_SIGNAL]
            = g_signal_new ("section-added",
                        G_TYPE_FROM_CLASS (klass),
                        G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED,
                        G_STRUCT_OFFSET (KzProfileClass, section_added),
                        NULL, NULL,
                        g_cclosure_marshal_VOID__STRING,
                        G_TYPE_NONE, 1,
                        G_TYPE_STRING);

      kz_profile_signals[SECTION_DELETED_SIGNAL]
            = g_signal_new ("section-deleted",
                        G_TYPE_FROM_CLASS (klass),
                        G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED,
                        G_STRUCT_OFFSET (KzProfileClass, section_deleted),
                        NULL, NULL,
                        g_cclosure_marshal_VOID__STRING,
                        G_TYPE_NONE, 1,
                        G_TYPE_STRING);

      kz_profile_signals[KEY_ADDED_SIGNAL]
            = g_signal_new ("key-added",
                        G_TYPE_FROM_CLASS (klass),
                        G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED,
                        G_STRUCT_OFFSET (KzProfileClass, key_added),
                        NULL, NULL,
                        _kz_marshal_VOID__STRING_STRING,
                        G_TYPE_NONE, 2,
                        G_TYPE_STRING, G_TYPE_STRING);

      kz_profile_signals[KEY_DELETED_SIGNAL]
            = g_signal_new ("key-deleted",
                        G_TYPE_FROM_CLASS (klass),
                        G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED,
                        G_STRUCT_OFFSET (KzProfileClass, key_deleted),
                        NULL, NULL,
                        _kz_marshal_VOID__STRING_STRING,
                        G_TYPE_NONE, 2,
                        G_TYPE_STRING, G_TYPE_STRING);

      kz_profile_signals[CHANGED_SIGNAL]
            = g_signal_new ("changed",
                        G_TYPE_FROM_CLASS (klass),
                        G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED,
                        G_STRUCT_OFFSET (KzProfileClass, changed),
                        NULL, NULL,
                        _kz_marshal_VOID__STRING_STRING_STRING,
                        G_TYPE_NONE, 3,
                        G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
}


static void
kz_profile_init (KzProfile *profile)
{
      profile->save_eachtime = TRUE;
      
      profile->edit    = FALSE;
      profile->file    = NULL;
      profile->subfile = NULL;
      profile->list    = NULL;
      profile->sublist = NULL;
}


static void
kz_profile_dispose (GObject *object)
{
      KzProfile *profile = KZ_PROFILE(object);
      KzProfileList *p, *q;

      if (profile->file)
      {
            g_free(profile->file);
            profile->file = NULL;
      }

      if (profile->subfile)
      {
            g_free(profile->subfile);
            profile->subfile = NULL;
      }

      for (p = profile->list; p; p = q)
      {
            q = p->next;
            g_free(p->data);
            g_free(p->section);
            g_free(p->key);
            g_free(p);
      }
      profile->list = NULL;

      for (p = profile->sublist; p; p = q)
      {
            q = p->next;
            g_free(p->data);
            g_free(p->section);
            g_free(p->key);
            g_free(p);
      }
      profile->sublist = NULL;

      if (G_OBJECT_CLASS (parent_class)->dispose)
            G_OBJECT_CLASS (parent_class)->dispose(object);
}


KzProfile *
kz_profile_new (void)
{
      KzProfile *profile = g_object_new(KZ_TYPE_PROFILE, NULL);
      return profile;
}


/******************************************************************************
*                                                                             *
* Converting between numerical value and string functions                     *
*                                                                             *
******************************************************************************/
const static gchar hex[16]={'0', '1', '2', '3', '4', '5', '6', '7',
                      '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

/*
 * string -> value
 * value,value
 * str,string
 * radix,radix
 * flag,TRUE:signed,FALSE:unsigned
 * RET,TRUE:normal exit,FALSE:error
 */
static gboolean
misc_str_to_val(gint *value,const gchar *str,const gint radix,
            const gboolean flag)
{
      gchar c;
      gint i,j,t;

      *value = 0;
      for (i = 0; str[i] != '\0' && str[i] == ' '; i++);
      if (str[i] == '\0')
            return FALSE;
      if (flag && str[i] == '-')
      {
            i++;
            while (str[i] != '\0')
            {
                  t = *value;
                  *value *= radix;
                  c = g_ascii_toupper(str[i]);
                  for (j = 0; j < radix; j++)
                        if (hex[j] == c)
                              break;
                  *value += j;
                  if (j == radix || *value < t)
                  {
                        *value = t;
                        return FALSE;
                  }
                  i++;
            }
            if (*value < 0)
            {
                  *value = 0;
                  return FALSE;
            }
            *value =- *value;
      }
      else
      {
            while (str[i] != '\0')
            {
                  t = *value;
                  *value *= radix;
                  c = g_ascii_toupper(str[i]);
                  for (j = 0; j < radix; j++)
                        if (hex[j] == c)
                              break;
                  *value += j;
                  if (j == radix || *value < t)
                  {
                        *value = t;
                        return FALSE;
                  }
                  i++;
            }
      }
      return TRUE;
}


/*
 * string -> array of value
 * size,bytes
 * text,string
 * radix,radix
 * flag,TRUE:signed,FALSE:unsigned
 * RET,array of value
 */
static guint8 *
misc_str_to_array(gint *size,const gchar *text,
              const gint radix,const gboolean flag)
{
      gchar *p;
      guint8 *array = NULL;
      gint i, j, value;

      *size = 0;
      if (!text)
            return NULL;
      p = g_malloc((g_strlen(text) + 2) * sizeof(gchar));
      strcpy(p, text);
      for (i = 0; p[i] != '\0'; i++)
      {
            for (j = 0; j < radix; j++)
                  if (p[i] == hex[j])
                        break;
            if (j >= radix)
                  p[i] = '\0';
      }
      p[i+1] = '\0';
      i = 0;
      while (p[i] != '\0')
      {
            if (!misc_str_to_val(&value, p+i, radix, flag))
            {
                  g_free(p);
                  g_free(array);
                  *size = 0;
                  return NULL;
            }
            array = g_realloc(array, *size + 1);
            array[(*size)++] = value;
            i += g_strlen(p + i) + 1;
      }
      g_free(p);
      return array;
}

/******************************************************************************
*                                                                             *
* Initialize file related functions                                           *
*                                                                             *
******************************************************************************/
/*
 * listize the file.
 * file,file name
 * RET,list
 */
static KzProfileList *
kz_profile_list (const gchar *file)
{
      gchar buf[256], *data = NULL, *tmp, *section = NULL;
      gint n;
      FILE *fio;
      KzProfileList *p = NULL, *q, *r;

      fio = fopen(file, "rt");
      if (!fio)
            return NULL;
      while (fgets (buf, 256, fio))
      {
            if (!data)
            {
                  data = g_strdup(buf);
            }
            else
            {
                  tmp = data;
                  data = g_strconcat(tmp, buf, NULL);
                  g_free(tmp);
            }
            n = data ? g_strlen(data) : 0;
            if (n > 0 && data[n - 1] == '\n')
            {
                  data[n - 1] = '\0';
                  q = g_malloc0(sizeof(KzProfileList));
                  q->data = data;
                  q->prev = p;
                  if (p)
                        p->next = q;
                  p = q;
                  data = NULL;
            }
      }
      if (fclose(fio) != 0 || !p)
      {
            while (p)
            {
                  q = p->prev;
                  g_free(p->data);
                  g_free(p);
                  p = q;
            }
            return NULL;
      }
      while (p->prev)
            p = p->prev;
      r = p;
      /* arrange the list */
      while (p)
      {
            data = p->data ? g_strstrip(g_strdup(p->data)) : NULL;
            n = data ? g_strlen(data) : 0;
            if (n <= 0)
            {
                  p->type = KZ_PROFILE_DATA_TYPE_SPACE;
            }
            else if (data[0] == '#' || data[0] == ';')
            {
                  p->type = KZ_PROFILE_DATA_TYPE_COMMENT;
            }
            else if (data[0] == '[' && data[n - 1] == ']')
            {
                  p->type = KZ_PROFILE_DATA_TYPE_SECTION;
                  g_free (section);
                  section = g_strdup(data + 1);
                  section[n - 2] = '\0';
                  for (q = p->prev; q && q->type == KZ_PROFILE_DATA_TYPE_SPACE;
                       q = q->prev)
                  {
                        g_free(q->section);
                        q->section = NULL;
                  }
            }
            else if (strchr(data, '='))
            {
                  p->type = KZ_PROFILE_DATA_TYPE_KEY;
                  p->key = g_strdup(data);
                  *strchr(p->key, '=') = '\0';
                  p->value = strchr(p->data, '=') + 1;
            }
            else
            {
                  p->type = KZ_PROFILE_DATA_TYPE_UNKNOW;
            }
            p->section = g_strdup(section);
            g_free(data);
            p = p->next;
      }
      g_free (section);
      return r;
}


/*
 * Open the initialize file.
 * file,file name
 * RET,the KzProfile struct
 */
KzProfile *
kz_profile_open (const gchar *file, const gchar *subfile)
{
      KzProfile *profile;

      profile = kz_profile_new();

      profile->subfile = subfile ? g_strdup(subfile) : NULL;
      profile->sublist = profile->subfile
            ? kz_profile_list(profile->subfile) : NULL;

      profile->file = file ? g_strdup(file) : NULL;
      profile->list = profile->file
            ? kz_profile_list(profile->file) : NULL;

      return profile;
}


/*
 * Close the initialize file.
 * profile,the KzProfile struct
 * RET,TRUE:normal exit,FALSE:error
 */
gboolean
kz_profile_close (KzProfile *profile)
{
      g_return_val_if_fail(KZ_IS_PROFILE(profile), FALSE);

      kz_profile_save (profile);
      g_object_run_dispose(G_OBJECT(profile));

      return TRUE;
}


/*
 * Save the initialize file.
 * profile,the KzProfile struct
 * RET,TRUE:normal exit,FALSE:error
 */
gboolean
kz_profile_save (KzProfile *profile)
{
      FILE *fio;
      KzProfileList *p;
      
      g_return_val_if_fail(KZ_IS_PROFILE(profile), FALSE);

      if (!profile->edit) return TRUE;
      if (!profile->file) return FALSE;

      fio = fopen(profile->file, "wt");
      if (!fio) return FALSE;

      /* when the profile was modified */
      for (p = profile->list; p; p = p->next)
      {
            if (p->data)
                  fputs(p->data, fio);
            fputc('\n', fio);
      }
      fclose(fio);

      profile->edit = FALSE;

      return TRUE;
}


/*
 * Get a string from the initialize file.
 * profile,the KzProfile struct
 * section,name of the section
 * key,name of the key
 * RET,string,NULL:error
 */
gchar *
kz_profile_get_string (KzProfile *profile,
                   const gchar *section,const gchar *key)
{
      KzProfileList *p;
      
      g_return_val_if_fail(KZ_IS_PROFILE(profile), NULL);

      if (!profile || !section || !key)
            return NULL;
      for (p = profile->list; p; p = p->next)
      {
            if (p->type == KZ_PROFILE_DATA_TYPE_KEY 
                && g_strcmp(p->section, section) == 0
                && g_strcmp(p->key, key) == 0)
            {
                  return g_strdup(p->value);
            }
      }
      for (p = profile->sublist; p; p = p->next)
      {
            if (p->type == KZ_PROFILE_DATA_TYPE_KEY
                && g_strcmp(p->section, section) == 0
                && g_strcmp(p->key, key) == 0)
            {
                  return g_strdup(p->value);
            }
      }
      return NULL;
}


/*
 * Get size of a value.
 * profile,the KzProfile struct
 * section,name of the section
 * key,name of the key
 * type,value type
 * RET,bytes,0:error
 */
gint
kz_profile_get_size (KzProfile *profile,
                 const gchar *section,const gchar *key,const guint type)
{
      guint8 *array;
      gint n;
      KzProfileList *p;

      g_return_val_if_fail(KZ_IS_PROFILE(profile), 0);

      if (!section || !key)
            return 0;
      for (p = profile->list; p; p = p->next)
      {
            if (p->type == KZ_PROFILE_DATA_TYPE_KEY
                && g_strcmp(p->section, section) == 0
                && g_strcmp(p->key, key) == 0)
            {
                  break;
            }
      }
      if (!p)
      {
            for (p = profile->sublist; p; p = p->next)
                  if (p->type == KZ_PROFILE_DATA_TYPE_KEY
                      && g_strcmp(p->section, section) == 0
                      && g_strcmp(p->key, key) == 0)
                  {
                        break;
                  }
      }
      if (!p)
            return 0;
      switch (type)
      {
      case KZ_PROFILE_VALUE_TYPE_BOOL:
            return g_strcmp(p->value, "true") == 0
                  || g_strcmp(p->value, "false") == 0 ? sizeof(gboolean) : 0;
      case KZ_PROFILE_VALUE_TYPE_INT:
            return sizeof(gint);
      case KZ_PROFILE_VALUE_TYPE_STRING:
            return g_strlen(p->value) + 1;
      case KZ_PROFILE_VALUE_TYPE_ARRAY:
            if (!(array=misc_str_to_array(&n, p->value, 10, FALSE)))
                  return 0;
            g_free(array);
            return n;
      }
      return 0;
}


/*
 * Get a value from the initialize file.
 * profile,the KzProfile struct
 * section,name of the section
 * key,name of the key
 * value,buffer to store value.
 * size,size of buffer to store value.
 * type,value type
 * RET,TRUE:normal exit,FALSE:error
 */
gboolean
kz_profile_get_value (KzProfile *profile,
                  const gchar *section,const gchar *key,
                  gpointer value,const gint size,const guint type)
{
      guint8 *array;
      gint n;
      KzProfileList *p;

      g_return_val_if_fail(KZ_IS_PROFILE(profile), FALSE);

      if (!section || !key || !value)
            return FALSE;
      for (p = profile->list; p; p = p->next)
      {
            if (p->type == KZ_PROFILE_DATA_TYPE_KEY
                && g_strcmp(p->section, section) == 0
                && g_strcmp(p->key, key) == 0)
            {
                  break;
            }
      }
      if (!p)
      {
            for (p = profile->sublist; p; p = p->next)
                  if (p->type == KZ_PROFILE_DATA_TYPE_KEY
                      && g_strcmp(p->section, section) == 0
                      && g_strcmp(p->key, key) == 0)
                  {
                        break;
                  }
      }
      if (!p)
            return FALSE;
      switch (type)
      {
      case KZ_PROFILE_VALUE_TYPE_BOOL:
            if (size < sizeof(gboolean))
                  return FALSE;
            if (g_ascii_strcasecmp (p->value, "true") == 0)
                  *((gboolean *)value) = TRUE;
            else if (g_ascii_strcasecmp (p->value, "false") == 0)
                  *((gboolean *)value) = FALSE;
            else
                  return FALSE;
            break;
      case KZ_PROFILE_VALUE_TYPE_INT:
            if (size < sizeof(gint))
                  return FALSE;
            misc_str_to_val((gint *)value, p->value, 10, TRUE);
            break;
      case KZ_PROFILE_VALUE_TYPE_STRING:
            if (size < g_strlen(p->value) + 1)
                  return FALSE;
            strcpy((gchar *)value,p->value);
            break;
      case KZ_PROFILE_VALUE_TYPE_ARRAY:
            if (!(array = misc_str_to_array(&n, p->value, 10, FALSE)))
                  return FALSE;
            if (size <= n)
                  g_memmove(value, array, size);
            g_free(array);
            if (n < size)
                  return FALSE;
            break;
      default:
            return FALSE;
      }
      return TRUE;
}


/*
 * Set a value into the initialize file.
 * profile,the KzProfile struct
 * section,name of the section
 * key,name of the key
 * value,buffer which store the value.
 * size,size of buffer which store the value.
 * type,value type
 * RET,TRUE:normal exit,FALSE:error
 */
gboolean
kz_profile_set_value (KzProfile *profile,
                  const gchar *section,const gchar *key,
                  gconstpointer value,const size_t size,const guint type)
{
      gchar *old_value = NULL;
      gint i;
      KzProfileList *p,*q = NULL;
      GQuark quark;

      g_return_val_if_fail(KZ_IS_PROFILE(profile), FALSE);

      if (!section || !key || !value)
            return FALSE;

      quark = g_quark_from_string(section);

      for (p = profile->list; p; q = p, p = p->next)
      {
            if (p->type == KZ_PROFILE_DATA_TYPE_KEY
                && g_strcmp(p->section, section) == 0
                && g_strcmp(p->key, key) == 0)
            {
                  break;
            }
      }

      if (p)
      {
            if (p->data)
                  old_value = g_strdup(p->data);
      }
      else
      {
            for (p = q; p; p = p->prev)
            {
                  if (p->section && g_strcmp(p->section, section) == 0)
                        break;
            }
            if (!p)
            {
                  if (q)
                  {
                        /* insert space between previous data and current data */
                        p = g_malloc(sizeof(KzProfileList));
                        p->type=KZ_PROFILE_DATA_TYPE_SPACE;
                        p->value = p->data = p->section = p->key = NULL;
                        p->prev = q;
                        p->next = q->next;
                        q->next = p;
                        q = p;
                  }
                  /* create a section if neither section and key aren't exist */
                  p = g_malloc(sizeof(KzProfileList));
                  p->type = KZ_PROFILE_DATA_TYPE_SECTION;
                  p->data = g_strdup_printf("[%s]", section);
                  p->section = g_strdup(section);
                  p->value = p->key = NULL;
                  p->prev = q;
                  if (q)
                  {
                        p->next = q->next;
                        q->next = p;
                  }
                  else
                  {
                        p->next = NULL;
                        profile->list = p;
                  }
                  g_signal_emit(profile,
                              kz_profile_signals[SECTION_ADDED_SIGNAL],
                              quark, p->section);
            }
            q = p;
            while (q->type == KZ_PROFILE_DATA_TYPE_SPACE && q->section
                   && g_strcmp(p->section, section) == 0 && q->prev)
                  q = q->prev;
            /* create a key into last of the section */
            p = g_malloc(sizeof(KzProfileList));
            p->type = KZ_PROFILE_DATA_TYPE_KEY;
            p->data = g_strdup_printf("%s=", key);
            p->section = g_strdup(section);
            p->key = g_strdup(key);
            p->value = strchr(p->data,'=')+1;
            p->prev = q;
            p->next = q->next;
            q->next = p;
            if (p->next)
                  p->next->prev = p;
            g_signal_emit(profile,
                        kz_profile_signals[KEY_ADDED_SIGNAL],
                        quark, p->section, p->key);
      }

      switch (type)
      {
      case KZ_PROFILE_VALUE_TYPE_BOOL:
            g_free(p->data);
            p->data = g_strdup_printf("%s=%s",
                                p->key, *((gboolean *)value) ? "true" : "false");
            break;
      case KZ_PROFILE_VALUE_TYPE_INT:
            g_free(p->data);
            p->data = g_strdup_printf("%s=%d", p->key, *((gint *)value));
            break;
      case KZ_PROFILE_VALUE_TYPE_STRING:
            g_free(p->data);
            p->data = g_strdup_printf("%s=%s", p->key, (gchar *)value);
            break;
      case KZ_PROFILE_VALUE_TYPE_ARRAY:
            g_free(p->data);
            p->data = g_strdup_printf("%s=%u", p->key, ((guint8 *)value)[0]);
            for (i = 1; i < size; i++)
            {
                  gchar *data;
                  data = g_strdup_printf("%s %u", p->data, ((guint8 *)value)[i]);
                  g_free(p->data);
                  p->data = data;
            }
            break;
      default:
            g_free(old_value);
            return FALSE;
      }

      p->value = strchr(p->data,'=') + 1;
      profile->edit = TRUE;

      g_signal_emit(profile, kz_profile_signals[CHANGED_SIGNAL],
                  quark, p->section, p->key, old_value);

      g_free(old_value);

      if (profile->save_eachtime)
            kz_profile_save (profile);

      return TRUE;
}


static void
kz_profile_list_free (KzProfile *profile, KzProfileList *p)
{
      if (!p) return;

      if (p == profile->list)
            profile->list = p->next;
      if (p->prev)
            p->prev->next = p->next;
      if (p->next)
            p->next->prev = p->prev;

      g_free(p->data);
      g_free(p->section);
      g_free(p->key);
      g_free(p);
}


/*
 * Delete a section from the initialize file.
 * profile,the KzProfile struct
 * section,name of the section
 * RET,TRUE:normal exit,FALSE:error
 */
gboolean
kz_profile_delete_section (KzProfile *profile, const gchar *section)
{
      gboolean result = FALSE;
      KzProfileList *p,*q;
      gchar *section_tmp;
      GQuark quark;

      g_return_val_if_fail(KZ_IS_PROFILE(profile), FALSE);

      if (!section)
            return FALSE;

      /*
       * section and p->section may be same memory chunk.
       */
      section_tmp = g_strdup(section);

      for (p = profile->list; p; p = q)
      {
            q = p->next;
            if (p->section && g_strcmp(p->section, section_tmp) == 0)
            {
                  if (p->prev && p->prev->type == KZ_PROFILE_DATA_TYPE_SPACE)
                        kz_profile_list_free(profile, p->prev);
                  kz_profile_list_free(profile, p);
                  profile->edit = TRUE;
                  result = TRUE;
            }
      }

      quark = g_quark_from_string(section_tmp);
      g_signal_emit(profile,
                  kz_profile_signals[SECTION_DELETED_SIGNAL],
                  quark, section_tmp);

      g_free(section_tmp);

      if (profile->save_eachtime)
            kz_profile_save (profile);

      return result;
}


/*
 * Delete a key from the initialize file.
 * profile,the KzProfile struct
 * section,name of the section
 * key,key
 * RET,TRUE:normal exit,FALSE:error
 */
gboolean kz_profile_delete_key (KzProfile *profile,
                        const gchar *section, const gchar *key)
{
      gboolean result = FALSE;
      KzProfileList *p,*q;
      gchar *section_tmp, *key_tmp;
      GQuark quark;

      g_return_val_if_fail(KZ_IS_PROFILE(profile), FALSE);

      if (!section || !key)
            return FALSE;

      /*
       * section and p->section (also key and p->key) may be same memory
       * chunk.
       */
      section_tmp = g_strdup(section);
      key_tmp = g_strdup(key);

      for (p = profile->list; p; p = q)
      {
            q = p->next;
            if (p->section && p->key
                && g_strcmp(p->section, section_tmp) == 0
                && g_strcmp(p->key, key_tmp) == 0)
            {
                  kz_profile_list_free(profile, p);
                  profile->edit = TRUE;
                  result = TRUE;
            }
      }

      quark = g_quark_from_string(section_tmp);
      g_signal_emit(profile,
                  kz_profile_signals[KEY_DELETED_SIGNAL],
                  quark, section_tmp, key_tmp);

      g_free(section_tmp);
      g_free(key_tmp);

      if (profile->save_eachtime)
            kz_profile_save (profile);

      return result;
}


/*
 * Enumerate sections in the initialize file.
 * profile,the KzProfile struct
 * RET,list of sections,NULL:error
 */
GList *
kz_profile_enum_section (KzProfile *profile)
{
      GList *glist = NULL;
      KzProfileList *p;

      g_return_val_if_fail(KZ_IS_PROFILE(profile), FALSE);

      for (p = profile->list; p; p = p->next)
      {
            if (p->section
                && (!glist || !g_list_find_custom(glist, p->section,
                                          (GCompareFunc)strcmp)))
            {
                  glist = g_list_insert_sorted(glist, p->section,
                                         (GCompareFunc)strcmp);
            }
      }
      for (p = profile->sublist; p; p = p->next)
      {
            if (p->section
                && (!glist || !g_list_find_custom(glist, p->section,
                                          (GCompareFunc)strcmp)))
            {
                  glist = g_list_insert_sorted(glist, p->section,
                                         (GCompareFunc)strcmp);
            }
      }
      return glist;
}


static gint
compare_enum_key (gconstpointer a, gconstpointer b)
{
      const gchar *one = (const gchar *)a;
      const gchar *two = (const gchar *)b;
      
      if (strlen(one) != strlen(two))
            return strlen(one) - strlen(two);
      return strcmp(one, two);
}


/*
 * Enumelate keys in the initialize file.
 * profile,the KzProfile struct
 * section,name of the section
 * RET,list of keys,NULL:error
*/
GList *
kz_profile_enum_key (KzProfile *profile, 
                 const gchar *section,
                 gboolean users_only)
{
      GList *glist = NULL;
      KzProfileList *p;

      g_return_val_if_fail(KZ_IS_PROFILE(profile), FALSE);

      for (p = profile->list; p; p = p->next)
      {
            if (p->section && p->key
                && g_strcmp(p->section, section) == 0
                && (!glist || !g_list_find_custom(glist, p->key,
                                         (GCompareFunc)compare_enum_key)))
            {
                  glist = g_list_insert_sorted(glist, p->key,
                                         (GCompareFunc)compare_enum_key);
            }
      }

      /* We need only user's setting if it exists */
      
      if (glist && users_only)
            return glist;
      
      for (p = profile->sublist; p; p = p->next)
      {
            if (p->section && p->key
                && g_strcmp (p->section, section) == 0
                && (!glist || !g_list_find_custom(glist, p->key,
                                          (GCompareFunc)compare_enum_key)))
            {
                  glist = g_list_insert_sorted(glist, p->key,
                                         (GCompareFunc)compare_enum_key);
            }
      }
      return glist;
}

void
kz_profile_set_save_each_time (KzProfile *profile, gboolean save)
{
      profile->save_eachtime = save;
}


Generated by  Doxygen 1.6.0   Back to index