/* This is -*- C -*- */
/* vim: set sw=2: */
/*
* guppi-category.c
*
* Copyright (C) 2000 EMC Capital Management, Inc.
* Copyright (C) 2001 The Free Software Foundation
*
* Developed by Jon Trowbridge <trow@gnu.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
*/
#include <config.h>
#include "guppi-category.h"
/* #include <gnome.h> */
#include <stdlib.h>
#include <string.h>
#include <libgnome/gnome-defs.h>
#include <libgnome/gnome-config.h>
#include <libgnome/gnome-i18n.h>
#include <guppi-convenient.h>
static GtkObjectClass *parent_class = NULL;
static void
guppi_category_finalize (GtkObject *obj)
{
if (parent_class->finalize)
parent_class->finalize (obj);
}
/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
struct OutPair {
GuppiXMLDocument *doc;
xmlNodePtr node;
};
static void
xml_cont_fn (const gchar *str, code_t code, gpointer data)
{
struct OutPair *pair = (struct OutPair *) data;
gchar buf[64];
xmlNodePtr cat_node;
cat_node = xmlNewNode (pair->doc->ns, "Category");
xmlNewChild (cat_node, pair->doc->ns, "name", str);
g_snprintf (buf, 64, "%d", (gint) code);
xmlNewChild (cat_node, pair->doc->ns, "code", buf);
xmlAddChild (pair->node, cat_node);
}
static void
export_xml (GuppiData *data, GuppiXMLDocument *doc, xmlNodePtr node)
{
struct OutPair pair;
pair.doc = doc;
pair.node = node;
guppi_category_foreach (GUPPI_CATEGORY (data), xml_cont_fn, &pair);
}
static void
guppi_category_class_init (GuppiCategoryClass *klass)
{
GtkObjectClass *object_class = (GtkObjectClass *) klass;
GuppiDataClass *data_class = GUPPI_DATA_CLASS (klass);
parent_class = gtk_type_class (GUPPI_TYPE_DATA);
data_class->export_xml = export_xml;
object_class->finalize = guppi_category_finalize;
}
static void
guppi_category_init (GuppiCategory *obj)
{
}
GtkType guppi_category_get_type (void)
{
static GtkType guppi_category_type = 0;
if (!guppi_category_type) {
static const GtkTypeInfo guppi_category_info = {
"GuppiCategory",
sizeof (GuppiCategory),
sizeof (GuppiCategoryClass),
(GtkClassInitFunc) guppi_category_class_init,
(GtkObjectInitFunc) guppi_category_init,
NULL, NULL, (GtkClassInitFunc) NULL
};
guppi_category_type =
gtk_type_unique (GUPPI_TYPE_DATA, &guppi_category_info);
}
return guppi_category_type;
}
/**************************************************************************/
/* Data Op Stuff */
typedef struct _GuppiDataOp_Category GuppiDataOp_Category;
struct _GuppiDataOp_Category {
GuppiDataOp op;
gchar *name;
code_t code;
};
static void
op_define (GuppiData *d, GuppiDataOp *op)
{
GuppiDataOp_Category *cat_op = (GuppiDataOp_Category *) op;
GuppiCategoryClass *klass;
klass = GUPPI_CATEGORY_CLASS (GTK_OBJECT (d)->klass);
g_assert (klass->define);
klass->define (GUPPI_CATEGORY (d), cat_op->name, cat_op->code);
}
/***************************************************************************/
gsize
guppi_category_size (GuppiCategory *cat)
{
GuppiCategoryClass *klass;
g_return_val_if_fail (GUPPI_IS_CATEGORY (cat), 0);
klass = GUPPI_CATEGORY_CLASS (GTK_OBJECT (cat)->klass);
g_assert (klass->size);
return klass->size (cat);
}
code_t
guppi_category_min_code (GuppiCategory *cat)
{
GuppiCategoryClass *klass;
code_t c = GUPPI_INVALID_CODE;
g_return_val_if_fail (GUPPI_IS_CATEGORY (cat), GUPPI_INVALID_CODE);
klass = GUPPI_CATEGORY_CLASS (GTK_OBJECT (cat)->klass);
g_assert (klass->codes);
klass->codes (cat, &c, NULL, NULL);
return c;
}
code_t
guppi_category_max_code (GuppiCategory *cat)
{
GuppiCategoryClass *klass;
code_t c = GUPPI_INVALID_CODE;
g_return_val_if_fail (GUPPI_IS_CATEGORY (cat), GUPPI_INVALID_CODE);
klass = GUPPI_CATEGORY_CLASS (GTK_OBJECT (cat)->klass);
g_assert (klass->codes);
klass->codes (cat, NULL, &c, NULL);
return c;
}
code_t
guppi_category_unused_code (GuppiCategory *cat)
{
GuppiCategoryClass *klass;
code_t mc = GUPPI_INVALID_CODE;
code_t c = GUPPI_INVALID_CODE;
g_return_val_if_fail (GUPPI_IS_CATEGORY (cat), GUPPI_INVALID_CODE);
klass = GUPPI_CATEGORY_CLASS (GTK_OBJECT (cat)->klass);
g_assert (klass->codes);
klass->codes (cat, NULL, &mc, &c);
if (c == GUPPI_INVALID_CODE && mc != GUPPI_INVALID_CODE)
c = mc + 1;
return c;
}
gboolean
guppi_category_define (GuppiCategory *cat, const gchar *str, code_t c)
{
GuppiCategoryClass *klass;
GuppiDataOp_Category op;
g_return_val_if_fail (GUPPI_IS_CATEGORY (cat), FALSE);
g_return_val_if_fail (str != NULL, FALSE);
g_return_val_if_fail (c != GUPPI_INVALID_CODE, FALSE);
g_return_val_if_fail (guppi_data_can_change (GUPPI_DATA (cat)), FALSE);
klass = GUPPI_CATEGORY_CLASS (GTK_OBJECT (cat)->klass);
g_assert (klass->code2name && klass->name2code);
if (klass->code2name (cat, c) != NULL ||
klass->name2code (cat, str) != GUPPI_INVALID_CODE)
return FALSE;
op.op.op = op_define;
op.name = guppi_strdup (str);
op.code = c;
guppi_data_add_pending_op (GUPPI_DATA (cat), (GuppiDataOp *) & op);
guppi_data_changed (GUPPI_DATA (cat));
return TRUE;
}
code_t
guppi_category_add_by_name (GuppiCategory *cat, const gchar *str)
{
code_t c;
g_return_val_if_fail (GUPPI_IS_CATEGORY (cat), GUPPI_INVALID_CODE);
g_return_val_if_fail (str != NULL, GUPPI_INVALID_CODE);
g_return_val_if_fail (guppi_data_can_change (GUPPI_DATA (cat)), GUPPI_INVALID_CODE);
c = guppi_category_unused_code (cat);
g_return_val_if_fail (c != GUPPI_INVALID_CODE, GUPPI_INVALID_CODE);
if (!guppi_category_define (cat, str, c))
c = GUPPI_INVALID_CODE;
return c;
}
gboolean
guppi_category_contains (GuppiCategory *cat, const gchar *str)
{
GuppiCategoryClass *klass;
g_return_val_if_fail (GUPPI_IS_CATEGORY (cat), FALSE);
g_return_val_if_fail (str != NULL, FALSE);
klass = GUPPI_CATEGORY_CLASS (GTK_OBJECT (cat)->klass);
g_assert (klass->name2code);
return klass->name2code (cat, str) != GUPPI_INVALID_CODE;
}
gboolean
guppi_category_contains_code (GuppiCategory *cat, code_t c)
{
GuppiCategoryClass *klass;
g_return_val_if_fail (GUPPI_IS_CATEGORY (cat), FALSE);
g_return_val_if_fail (c != GUPPI_INVALID_CODE, FALSE);
klass = GUPPI_CATEGORY_CLASS (GTK_OBJECT (cat)->klass);
g_assert (klass->code2name);
return klass->code2name (cat, c) != NULL;
}
code_t
guppi_category_find_by_name (GuppiCategory *cat, const gchar *str)
{
GuppiCategoryClass *klass;
g_return_val_if_fail (GUPPI_IS_CATEGORY (cat), GUPPI_INVALID_CODE);
g_return_val_if_fail (str != NULL, GUPPI_INVALID_CODE);
klass = GUPPI_CATEGORY_CLASS (GTK_OBJECT (cat)->klass);
g_assert (klass->name2code);
return klass->name2code (cat, str);
}
const gchar *
guppi_category_find_by_code (GuppiCategory *cat, code_t c)
{
GuppiCategoryClass *klass;
g_return_val_if_fail (GUPPI_IS_CATEGORY (cat), NULL);
g_return_val_if_fail (c != GUPPI_INVALID_CODE, NULL);
klass = GUPPI_CATEGORY_CLASS (GTK_OBJECT (cat)->klass);
g_assert (klass->code2name);
return klass->code2name (cat, c);
}
gboolean
guppi_category_rename (GuppiCategory *cat, code_t c, const gchar *str)
{
GuppiCategoryClass *klass;
GuppiDataOp_Category op;
code_t alt_code;
const gchar *old_str;
g_return_val_if_fail (GUPPI_IS_CATEGORY (cat), FALSE);
g_return_val_if_fail (c != GUPPI_INVALID_CODE, FALSE);
g_return_val_if_fail (str != NULL, FALSE);
g_return_val_if_fail (guppi_data_can_change (GUPPI_DATA (cat)), FALSE);
klass = GUPPI_CATEGORY_CLASS (GTK_OBJECT (cat)->klass);
g_assert (klass->code2name && klass->name2code);
old_str = klass->code2name (cat, c);
/* Bad code passed in */
if (old_str == NULL)
return FALSE;
/* Old string == new string, so we don't have to do anything. */
if (!strcmp (old_str, str))
return TRUE;
alt_code = klass->name2code (cat, str);
/* Oops... the new name is already used. */
if (alt_code != GUPPI_INVALID_CODE)
return FALSE;
op.op.op = op_define;
op.name = guppi_strdup (str);
op.code = c;
guppi_data_add_pending_op (GUPPI_DATA (cat), (GuppiDataOp *) & op);
guppi_data_changed (GUPPI_DATA (cat));
return TRUE;
}
void
guppi_category_foreach (GuppiCategory *cat, GuppiCategoryFn fn, gpointer user_data)
{
GuppiCategoryClass *klass;
g_return_if_fail (GUPPI_IS_CATEGORY (cat));
g_return_if_fail (fn != NULL);
klass = GUPPI_CATEGORY_CLASS (GTK_OBJECT (cat)->klass);
g_assert (klass->foreach);
klass->foreach (cat, fn, user_data);
}
syntax highlighted by Code2HTML, v. 0.9.1