<SECTION>
<FILE>db</FILE>
-<INCLUDE>libglabels/db.h</INCLUDE>
+<INCLUDE>libglabels/lgl-db.h</INCLUDE>
lglDbRegStatus
lglDbDeleteStatus
<SUBSECTION Init Functions>
<SECTION>
<FILE>template</FILE>
-<INCLUDE>libglabels/template.h</INCLUDE>
+<INCLUDE>libglabels/lgl-template.h</INCLUDE>
lglTemplate
<SUBSECTION Frame Structure>
lglTemplateFrameShape
<SECTION>
<FILE>paper</FILE>
-<INCLUDE>libglabels/paper.h</INCLUDE>
+<INCLUDE>libglabels/lgl-paper.h</INCLUDE>
lglPaper
lgl_paper_new
lgl_paper_dup
<SECTION>
<FILE>category</FILE>
-<INCLUDE>libglabels/category.h</INCLUDE>
+<INCLUDE>libglabels/lgl-category.h</INCLUDE>
lglCategory
lgl_category_new
lgl_category_dup
<SECTION>
<FILE>vendor</FILE>
-<INCLUDE>libglabels/vendor.h</INCLUDE>
+<INCLUDE>libglabels/lgl-vendor.h</INCLUDE>
lglVendor
lgl_vendor_new
lgl_vendor_dup
<SECTION>
<FILE>xml-paper</FILE>
-<INCLUDE>libglabels/xml-paper.h</INCLUDE>
+<INCLUDE>libglabels/lgl-xml-paper.h</INCLUDE>
lgl_xml_paper_read_papers_from_file
lgl_xml_paper_parse_papers_doc
lgl_xml_paper_parse_paper_node
<SECTION>
<FILE>xml-category</FILE>
-<INCLUDE>libglabels/xml-category.h</INCLUDE>
+<INCLUDE>libglabels/lgl-xml-category.h</INCLUDE>
lgl_xml_category_read_categories_from_file
lgl_xml_category_parse_categories_doc
lgl_xml_category_parse_category_node
<SECTION>
<FILE>xml-template</FILE>
-<INCLUDE>libglabels/xml-templates.h</INCLUDE>
+<INCLUDE>libglabels/lgl-xml-templates.h</INCLUDE>
lgl_xml_template_read_templates_from_file
lgl_xml_template_parse_templates_doc
lgl_xml_template_parse_template_node
<SECTION>
<FILE>xml-vendor</FILE>
-<INCLUDE>libglabels/xml-vendor.h</INCLUDE>
+<INCLUDE>libglabels/lgl-xml-vendor.h</INCLUDE>
lgl_xml_vendor_read_vendors_from_file
lgl_xml_vendor_parse_vendors_doc
lgl_xml_vendor_parse_vendor_node
<SECTION>
<FILE>xml</FILE>
-<INCLUDE>libglabels/xml.h</INCLUDE>
+<INCLUDE>libglabels/lgl-xml.h</INCLUDE>
LGL_XML_NAME_SPACE
<SUBSECTION Get Property Functions>
lgl_xml_get_prop_string
<SECTION>
<FILE>units</FILE>
-<INCLUDE>libglabels/units.h</INCLUDE>
+<INCLUDE>libglabels/lgl-units.h</INCLUDE>
lglUnits
lgl_units_get_id
lgl_units_from_id
<SECTION>
<FILE>str</FILE>
-<INCLUDE>libglabels/str.h</INCLUDE>
+<INCLUDE>libglabels/lgl-str.h</INCLUDE>
lgl_str_utf8_casecmp
lgl_str_part_name_cmp
lgl_str_format_fraction
lib_LTLIBRARIES = libglabels-3.0.la
-libglabels_3_0_la_SOURCES = \
+libglabels_3_0_la_SOURCES = \
libglabels-private.h \
- db.h \
- db.c \
- units.h \
- units.c \
- paper.h \
- paper.c \
- category.h \
- category.c \
- vendor.h \
- vendor.c \
- template.h \
- template.c \
- xml-paper.h \
- xml-paper.c \
- xml-category.h \
- xml-category.c \
- xml-vendor.h \
- xml-vendor.c \
- xml-template.h \
- xml-template.c \
- xml.h \
- xml.c \
- str.h \
- str.c
+ lgl-db.h \
+ lgl-db.c \
+ lgl-units.h \
+ lgl-units.c \
+ lgl-paper.h \
+ lgl-paper.c \
+ lgl-category.h \
+ lgl-category.c \
+ lgl-vendor.h \
+ lgl-vendor.c \
+ lgl-template.h \
+ lgl-template.c \
+ lgl-xml-paper.h \
+ lgl-xml-paper.c \
+ lgl-xml-category.h \
+ lgl-xml-category.c \
+ lgl-xml-vendor.h \
+ lgl-xml-vendor.c \
+ lgl-xml-template.h \
+ lgl-xml-template.c \
+ lgl-xml.h \
+ lgl-xml.c \
+ lgl-str.h \
+ lgl-str.c
libglabels_3_0includedir=$(includedir)/$(LIBGLABELS_BRANCH)
libglabels_3_0subincludedir=$(includedir)/$(LIBGLABELS_BRANCH)/libglabels
-libglabels_3_0subinclude_HEADERS = \
- db.h \
- units.h \
- paper.h \
- category.h \
- template.h \
- xml-paper.h \
- xml-category.h \
- xml-template.h \
- xml.h \
- str.h
+libglabels_3_0subinclude_HEADERS = \
+ lgl-db.h \
+ lgl-units.h \
+ lgl-paper.h \
+ lgl-category.h \
+ lgl-template.h \
+ lgl-xml-paper.h \
+ lgl-xml-category.h \
+ lgl-xml-template.h \
+ lgl-xml.h \
+ lgl-str.h
EXTRA_DIST = \
$(LIBGLABELS_BRANCH).pc.in
+++ /dev/null
-/*
- * category.c
- * Copyright (C) 2006-2009 Jim Evins <evins@snaught.com>.
- *
- * This file is part of libglabels.
- *
- * libglabels is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libglabels 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-
-#include "category.h"
-
-#include <glib/gi18n.h>
-#include <glib.h>
-#include <string.h>
-
-#include "libglabels-private.h"
-
-
-/*===========================================*/
-/* Private types */
-/*===========================================*/
-
-
-/*===========================================*/
-/* Private globals */
-/*===========================================*/
-
-
-/*===========================================*/
-/* Local function prototypes */
-/*===========================================*/
-
-
-/*===========================================*/
-/* Functions. */
-/*===========================================*/
-
-/**
- * lgl_category_new:
- * @id: Id of category definition. (E.g. label, card, etc.) Should be
- * unique.
- * @name: Localized name of category.
- *
- * Allocates and constructs a new #lglCategory structure.
- *
- * Returns: a pointer to a newly allocated #lglCategory structure.
- *
- */
-lglCategory *
-lgl_category_new (gchar *id,
- gchar *name)
-{
- lglCategory *category;
-
- category = g_new0 (lglCategory,1);
- category->id = g_strdup (id);
- category->name = g_strdup (name);
-
- return category;
-}
-
-
-/**
- * lgl_category_dup:
- * @orig: #lglCategory structure to be duplicated.
- *
- * Duplicates an existing #lglCategory structure.
- *
- * Returns: a pointer to a newly allocated #lglCategory structure.
- *
- */
-lglCategory *lgl_category_dup (const lglCategory *orig)
-{
- lglCategory *category;
-
- g_return_val_if_fail (orig, NULL);
-
- category = g_new0 (lglCategory,1);
-
- category->id = g_strdup (orig->id);
- category->name = g_strdup (orig->name);
-
- return category;
-}
-
-
-/**
- * lgl_category_free:
- * @category: pointer to #lglCategory structure to be freed.
- *
- * Free all memory associated with an existing #lglCategory structure.
- *
- */
-void lgl_category_free (lglCategory *category)
-{
-
- if ( category != NULL ) {
-
- g_free (category->id);
- category->id = NULL;
-
- g_free (category->name);
- category->name = NULL;
-
- g_free (category);
- }
-
-}
-
-
-
-/*
- * Local Variables: -- emacs
- * mode: C -- emacs
- * c-basic-offset: 8 -- emacs
- * tab-width: 8 -- emacs
- * indent-tabs-mode: nil -- emacs
- * End: -- emacs
- */
+++ /dev/null
-/*
- * category.h
- * Copyright (C) 2006-2009 Jim Evins <evins@snaught.com>.
- *
- * This file is part of libglabels.
- *
- * libglabels is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libglabels 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __LGL_CATEGORY_H__
-#define __LGL_CATEGORY_H__
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-/*
- * Template class
- */
-typedef struct _lglCategory lglCategory;
-
-struct _lglCategory {
- gchar *id; /* Unique ID of category */
- gchar *name; /* Localized name of category */
-};
-
-
-/*
- * Category construction
- */
-lglCategory *lgl_category_new (gchar *id,
- gchar *name);
-
-lglCategory *lgl_category_dup (const lglCategory *orig);
-void lgl_category_free (lglCategory *category);
-
-
-G_END_DECLS
-
-#endif /* __LGL_CATEGORY_H__ */
-
-
-
-/*
- * Local Variables: -- emacs
- * mode: C -- emacs
- * c-basic-offset: 8 -- emacs
- * tab-width: 8 -- emacs
- * indent-tabs-mode: nil -- emacs
- * End: -- emacs
- */
+++ /dev/null
-/*
- * db.c
- * Copyright (C) 2003-2009 Jim Evins <evins@snaught.com>.
- *
- * This file is part of libglabels.
- *
- * libglabels is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libglabels 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-
-#include "db.h"
-
-#include <glib/gi18n.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <glib-object.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "libglabels-private.h"
-
-#include "xml-paper.h"
-#include "xml-category.h"
-#include "xml-vendor.h"
-#include "xml-template.h"
-
-/*===========================================*/
-/* Private macros and constants. */
-/*===========================================*/
-
-/* Data system and user data directories. (must free w/ g_free()) */
-#define SYSTEM_CONFIG_DIR g_build_filename (LIBGLABELS_CONFIG_DIR, "templates", NULL)
-#define USER_CONFIG_DIR g_build_filename (g_get_user_config_dir (), "libglabels", "templates" , NULL)
-#define ALT_USER_CONFIG_DIR g_build_filename (g_get_home_dir (), ".glabels", NULL)
-
-
-/*===========================================*/
-/* Private types */
-/*===========================================*/
-
-#define TYPE_LGL_DB_MODEL (lgl_db_model_get_type ())
-#define LGL_DB_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_LGL_DB_MODEL, lglDbModel))
-#define LGL_DB_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_LGL_DB_MODEL, lglDbModelClass))
-#define IS_LGL_DB_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_LGL_DB_MODEL))
-#define IS_LGL_DB_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_LGL_DB_MODEL))
-#define LGL_DB_MODEL_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), TYPE_LGL_DB_MODEL, lglDbModelClass))
-
-
-typedef struct _lglDbModel lglDbModel;
-typedef struct _lglDbModelClass lglDbModelClass;
-
-
-struct _lglDbModel {
- GObject parent;
-
- GList *papers;
- GList *categories;
- GList *vendors;
- GList *templates;
-
- GHashTable *template_cache;
-};
-
-
-struct _lglDbModelClass {
- GObjectClass parent_class;
-
- /*
- * Signals
- */
- void (*changed) (lglDbModel *this,
- gpointer user_data);
-
-};
-
-
-enum {
- CHANGED,
- LAST_SIGNAL
-};
-
-
-/*===========================================*/
-/* Private globals */
-/*===========================================*/
-
-static guint signals[LAST_SIGNAL] = {0};
-
-static lglDbModel *model = NULL;
-
-
-/*===========================================*/
-/* Local function prototypes */
-/*===========================================*/
-
-static void lgl_db_model_finalize (GObject *object);
-
-static void add_to_template_cache (lglTemplate *template);
-
-static GList *read_papers (void);
-static GList *read_paper_files_from_dir (GList *papers,
- const gchar *dirname);
-
-static GList *read_categories (void);
-static GList *read_category_files_from_dir (GList *categories,
- const gchar *dirname);
-
-static GList *read_vendors (void);
-static GList *read_vendor_files_from_dir (GList *vendors,
- const gchar *dirname);
-
-static void read_templates (void);
-static void read_template_files_from_dir (const gchar *dirname);
-
-static lglTemplate *template_full_page (const gchar *page_size);
-
-
-/*****************************************************************************/
-/* Object infrastructure. */
-/*****************************************************************************/
-G_DEFINE_TYPE (lglDbModel, lgl_db_model, G_TYPE_OBJECT);
-
-
-/*****************************************************************************/
-/* Class Init Function. */
-/*****************************************************************************/
-static void
-lgl_db_model_class_init (lglDbModelClass *class)
-{
- GObjectClass *gobject_class = (GObjectClass *) class;
-
- lgl_db_model_parent_class = g_type_class_peek_parent (class);
-
- gobject_class->finalize = lgl_db_model_finalize;
-
- signals[CHANGED] =
- g_signal_new ("changed",
- G_OBJECT_CLASS_TYPE (gobject_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (lglDbModelClass, changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE,
- 0);
-}
-
-
-/*****************************************************************************/
-/* Object Instance Init Function. */
-/*****************************************************************************/
-static void
-lgl_db_model_init (lglDbModel *this)
-{
- this->template_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)lgl_template_free);
-}
-
-
-/*****************************************************************************/
-/* Finalize Method. */
-/*****************************************************************************/
-static void
-lgl_db_model_finalize (GObject *object)
-{
- lglDbModel *this;
- GList *p;
-
- g_return_if_fail (object && IS_LGL_DB_MODEL (object));
- this = LGL_DB_MODEL (object);
-
- g_hash_table_unref (this->template_cache);
-
- for (p = this->papers; p != NULL; p = p->next)
- {
- g_free (p->data);
- p->data = NULL;
- }
- g_list_free (this->papers);
-
- for (p = this->categories; p != NULL; p = p->next)
- {
- g_free (p->data);
- p->data = NULL;
- }
- g_list_free (this->categories);
-
- for (p = this->vendors; p != NULL; p = p->next)
- {
- g_free (p->data);
- p->data = NULL;
- }
- g_list_free (this->vendors);
-
- for (p = this->templates; p != NULL; p = p->next)
- {
- lgl_template_free ((lglTemplate *)p->data);
- p->data = NULL;
- }
- g_list_free (this->templates);
-
- G_OBJECT_CLASS (lgl_db_model_parent_class)->finalize (object);
-}
-
-
-/*****************************************************************************/
-/** New Object Generator. */
-/*****************************************************************************/
-lglDbModel *
-lgl_db_model_new (void)
-{
- lglDbModel *this;
-
- this = g_object_new (TYPE_LGL_DB_MODEL, NULL);
-
- return this;
-}
-
-
-/*===========================================*/
-/* Module initialization */
-/*===========================================*/
-
-/**
- * lgl_db_init:
- *
- * Initialize all libglabels subsystems. It is not necessary for an application to call
- * lgl_db_init(), because libglabels will initialize on demand. An application programmer may
- * choose to call lgl_db_init() at startup to minimize the impact of the first libglabels call
- * on GUI response time.
- *
- * This function initializes its paper definitions, category definitions, vendor definitions,
- * and its template database. It will search both system and user template directories to locate
- * this data.
- */
-void
-lgl_db_init (void)
-{
- lglPaper *paper_other;
- lglCategory *category_user_defined;
- lglTemplate *template;
- GList *page_sizes;
- GList *p;
-
- model = lgl_db_model_new ();
-
- /*
- * Paper definitions
- */
- model->papers = read_papers ();
-
- /* Create and append an "Other" entry. */
- /* Translators: "Other" here means other page size. Meaning a page size
- * other than the standard ones that libglabels knows about such as
- * "letter", "A4", etc. */
- paper_other = lgl_paper_new ("Other", _("Other"), 0.0, 0.0, NULL);
- model->papers = g_list_append (model->papers, paper_other);
-
- /*
- * Categories
- */
- model->categories = read_categories ();
-
- /* Create and append a "User defined" entry. */
- category_user_defined = lgl_category_new ("user-defined", _("User defined"));
- model->categories = g_list_append (model->categories, category_user_defined);
-
- /*
- * Vendors
- */
- model->vendors = read_vendors ();
-
- /*
- * Templates
- */
- read_templates ();
-
- /* Create and append generic full page templates. */
- page_sizes = lgl_db_get_paper_id_list ();
- for ( p=page_sizes; p != NULL; p=p->next )
- {
- if ( !lgl_db_is_paper_id_other (p->data) )
- {
- template = template_full_page (p->data);
- _lgl_db_register_template_internal (template);
- lgl_template_free (template);
- }
- }
- lgl_db_free_paper_id_list (page_sizes);
-
-}
-
-
-/**
- * lgl_db_notify_add:
- * @func: Callback function to be called when database changes.
- * @user_data: Passback user data to supply to callback function.
- *
- * Register a notification callback function to be called when the database changes.
- *
- * Returns: an ID for this notification registration.
- */
-gulong
-lgl_db_notify_add (lglDbNotifyFunc func,
- gpointer user_data)
-{
- if (!model)
- {
- lgl_db_init ();
- }
-
- return g_signal_connect_swapped (G_OBJECT (model), "changed", G_CALLBACK (func), user_data);
-}
-
-
-/**
- * lgl_db_notify_remove:
- * @id: ID of notification registration to cancel (see lgl_db_notify_add()).
- *
- * Cancel a previous registration a notification callback function.
- */
-void
-lgl_db_notify_remove (gulong id)
-{
- g_signal_handler_disconnect (G_OBJECT (model), id);
-}
-
-
-/*===========================================*/
-/* Paper db functions. */
-/*===========================================*/
-
-/**
- * lgl_db_get_paper_id_list:
- *
- * Get a list of all paper ids known to libglabels.
- *
- * Returns: a list of paper ids.
- *
- */
-GList *
-lgl_db_get_paper_id_list (void)
-{
- GList *ids = NULL;
- GList *p;
- lglPaper *paper;
-
- if (!model)
- {
- lgl_db_init ();
- }
-
- for ( p=model->papers; p != NULL; p=p->next )
- {
- paper = (lglPaper *)p->data;
- ids = g_list_append (ids, g_strdup (paper->id));
- }
-
- return ids;
-}
-
-
-/**
- * lgl_db_free_paper_id_list:
- * @ids: List of id strings to be freed.
- *
- * Free up all storage associated with an id list obtained with
- * lgl_db_get_paper_id_list().
- *
- */
-void
-lgl_db_free_paper_id_list (GList *ids)
-{
- GList *p;
-
- for (p = ids; p != NULL; p = p->next)
- {
- g_free (p->data);
- p->data = NULL;
- }
-
- g_list_free (ids);
-}
-
-
-/**
- * lgl_db_get_paper_name_list:
- *
- * Get a list of all localized paper names known to libglabels.
- *
- * Returns: a list of localized paper names.
- *
- */
-GList *
-lgl_db_get_paper_name_list (void)
-{
- GList *names = NULL;
- GList *p;
- lglPaper *paper;
-
- if (!model)
- {
- lgl_db_init ();
- }
-
- for ( p=model->papers; p != NULL; p=p->next )
- {
- paper = (lglPaper *)p->data;
- names = g_list_append (names, g_strdup (paper->name));
- }
-
- return names;
-}
-
-
-/**
- * lgl_db_free_paper_name_list:
- * @names: List of localized paper name strings to be freed.
- *
- * Free up all storage associated with a name list obtained with
- * lgl_db_get_paper_name_list().
- *
- */
-void
-lgl_db_free_paper_name_list (GList *names)
-{
- GList *p;
-
- for (p = names; p != NULL; p = p->next)
- {
- g_free (p->data);
- p->data = NULL;
- }
-
- g_list_free (names);
-}
-
-
-/**
- * lgl_db_lookup_paper_from_name:
- * @name: localized paper name string
- *
- * Lookup paper definition from localized paper name string.
- *
- * Returns: pointer to a newly allocated #lglPaper structure.
- *
- */
-lglPaper *
-lgl_db_lookup_paper_from_name (const gchar *name)
-{
- GList *p;
- lglPaper *paper;
-
- if (!model)
- {
- lgl_db_init ();
- }
-
- if (name == NULL)
- {
- /* If no name, return first paper as a default */
- return lgl_paper_dup ((lglPaper *) model->papers->data);
- }
-
- for (p = model->papers; p != NULL; p = p->next)
- {
- paper = (lglPaper *) p->data;
- if (UTF8_EQUAL (paper->name, name))
- {
- return lgl_paper_dup (paper);
- }
- }
-
- return NULL;
-}
-
-
-/**
- * lgl_db_lookup_paper_from_id:
- * @id: paper id string
- *
- * Lookup paper definition from id string.
- *
- * Returns: pointer to a newly allocated #lglPaper structure.
- *
- */
-lglPaper *
-lgl_db_lookup_paper_from_id (const gchar *id)
-{
- GList *p;
- lglPaper *paper;
-
- if (!model)
- {
- lgl_db_init ();
- }
-
- if (id == NULL)
- {
- /* If no id, return first paper as a default */
- return lgl_paper_dup ((lglPaper *) model->papers->data);
- }
-
- for (p = model->papers; p != NULL; p = p->next)
- {
- paper = (lglPaper *) p->data;
- if (ASCII_EQUAL (paper->id, id))
- {
- return lgl_paper_dup (paper);
- }
- }
-
- return NULL;
-}
-
-
-/**
- * lgl_db_lookup_paper_id_from_name:
- * @name: localized paper name stringp
- *
- * Lookup paper name string from localized paper name string.
- *
- * Returns: pointer to a newly allocated id string.
- *
- */
-gchar *
-lgl_db_lookup_paper_id_from_name (const gchar *name)
-{
- lglPaper *paper = NULL;
- gchar *id = NULL;
-
- if (name != NULL)
- {
- paper = lgl_db_lookup_paper_from_name (name);
- if ( paper != NULL )
- {
- id = g_strdup (paper->id);
- lgl_paper_free (paper);
- paper = NULL;
- }
- }
-
- return id;
-}
-
-
-/**
- * lgl_db_lookup_paper_name_from_id:
- * @id: paper id string
- *
- * Lookup localized paper name string from paper id string.
- *
- * Returns: pointer to a newly allocated localized paper name string.
- *
- */
-gchar *
-lgl_db_lookup_paper_name_from_id (const gchar *id)
-{
- lglPaper *paper = NULL;
- gchar *name = NULL;
-
- if (id != NULL)
- {
- paper = lgl_db_lookup_paper_from_id (id);
- if ( paper != NULL )
- {
- name = g_strdup (paper->name);
- lgl_paper_free (paper);
- paper = NULL;
- }
- }
-
- return name;
-}
-
-
-/**
- * lgl_db_is_paper_id_known:
- * @id: paper id to test
- *
- * Determine if given paper id is known to libglabels.
- *
- * Returns: TRUE if id is known, otherwise FALSE.
- *
- */
-gboolean
-lgl_db_is_paper_id_known (const gchar *id)
-{
- GList *p;
- lglPaper *paper;
-
- if (!model)
- {
- lgl_db_init ();
- }
-
- if (id == NULL)
- {
- return FALSE;
- }
-
- for (p = model->papers; p != NULL; p = p->next)
- {
- paper = (lglPaper *) p->data;
- if (ASCII_EQUAL (paper->id, id))
- {
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-
-/**
- * lgl_db_is_paper_id_other:
- * @id: paper id to test
- *
- * Determine if given paper id is the special id "Other."
- *
- * Returns: TRUE if id is "Other", otherwise FALSE.
- *
- */
-gboolean
-lgl_db_is_paper_id_other (const gchar *id)
-{
- if (id == NULL)
- {
- return FALSE;
- }
-
- return (ASCII_EQUAL (id, "Other"));
-}
-
-
-static GList *
-read_papers (void)
-{
- gchar *data_dir;
- GList *papers = NULL;
-
- data_dir = SYSTEM_CONFIG_DIR;
- papers = read_paper_files_from_dir (papers, data_dir);
- g_free (data_dir);
-
- data_dir = USER_CONFIG_DIR;
- papers = read_paper_files_from_dir (papers, data_dir);
- g_free (data_dir);
-
- if (papers == NULL) {
- g_critical (_("Unable to locate paper size definitions. Libglabels may not be installed correctly!"));
- }
-
- return papers;
-}
-
-
-static GList *
-read_paper_files_from_dir (GList *papers,
- const gchar *dirname)
-{
- GDir *dp;
- const gchar *filename, *extension;
- gchar *full_filename = NULL;
- GError *gerror = NULL;
- GList *new_papers = NULL;
-
- if (dirname == NULL) {
- return papers;
- }
-
- if (!g_file_test (dirname, G_FILE_TEST_EXISTS)) {
- return papers;
- }
-
- dp = g_dir_open (dirname, 0, &gerror);
- if (gerror != NULL) {
- g_message ("cannot open data directory: %s", gerror->message );
- return papers;
- }
-
- while ((filename = g_dir_read_name (dp)) != NULL) {
-
- extension = strrchr (filename, '.');
-
- if (extension != NULL) {
-
- if ( ASCII_EQUAL (filename, "paper-sizes.xml") )
- {
-
- full_filename =
- g_build_filename (dirname, filename, NULL);
- new_papers =
- lgl_xml_paper_read_papers_from_file (full_filename);
- g_free (full_filename);
-
- papers = g_list_concat (papers, new_papers);
- new_papers = NULL;
-
- }
-
- }
-
- }
-
- g_dir_close (dp);
-
- return papers;
-}
-
-
-/**
- * lgl_db_print_known_papers:
- *
- * For debugging purposes: print a list of all paper definitions known to
- * libglabels.
- *
- */
-void
-lgl_db_print_known_papers (void)
-{
- GList *p;
- lglPaper *paper;
-
- if (!model) {
- lgl_db_init ();
- }
-
- g_print ("%s():\n", __FUNCTION__);
- for (p = model->papers; p != NULL; p = p->next) {
- paper = (lglPaper *) p->data;
-
- g_print ("PAPER id=\"%s\", name=\"%s\", width=%gpts, height=%gpts\n",
- paper->id, paper->name, paper->width, paper->height);
-
- }
- g_print ("\n");
-
-}
-
-
-/*===========================================*/
-/* Category db functions. */
-/*===========================================*/
-
-/**
- * lgl_db_get_category_id_list:
- *
- * Get a list of all category ids known to libglabels.
- *
- * Returns: a list of category ids.
- *
- */
-GList *
-lgl_db_get_category_id_list (void)
-{
- GList *ids = NULL;
- GList *p;
- lglCategory *category;
-
- if (!model)
- {
- lgl_db_init ();
- }
-
- for ( p=model->categories; p != NULL; p=p->next )
- {
- category = (lglCategory *)p->data;
- ids = g_list_append (ids, g_strdup (category->id));
- }
-
- return ids;
-}
-
-
-/**
- * lgl_db_free_category_id_list:
- * @ids: List of id strings to be freed.
- *
- * Free up all storage associated with an id list obtained with
- * lgl_db_get_category_id_list().
- *
- */
-void
-lgl_db_free_category_id_list (GList *ids)
-{
- GList *p;
-
- for (p = ids; p != NULL; p = p->next)
- {
- g_free (p->data);
- p->data = NULL;
- }
-
- g_list_free (ids);
-}
-
-
-/**
- * lgl_db_get_category_name_list:
- *
- * Get a list of all localized category names known to libglabels.
- *
- * Returns: a list of localized category names.
- *
- */
-GList *
-lgl_db_get_category_name_list (void)
-{
- GList *names = NULL;
- GList *p;
- lglCategory *category;
-
- if (!model)
- {
- lgl_db_init ();
- }
-
- for ( p=model->categories; p != NULL; p=p->next )
- {
- category = (lglCategory *)p->data;
- names = g_list_append (names, g_strdup (category->name));
- }
-
- return names;
-}
-
-
-/**
- * lgl_db_free_category_name_list:
- * @names: List of localized category name strings to be freed.
- *
- * Free up all storage associated with a name list obtained with
- * lgl_db_get_category_name_list().
- *
- */
-void
-lgl_db_free_category_name_list (GList *names)
-{
- GList *p;
-
- for (p = names; p != NULL; p = p->next)
- {
- g_free (p->data);
- p->data = NULL;
- }
-
- g_list_free (names);
-}
-
-
-/**
- * lgl_db_lookup_category_from_name:
- * @name: localized category name string
- *
- * Lookup category definition from localized category name string.
- *
- * Returns: pointer to a newly allocated #lglCategory structure.
- *
- */
-lglCategory *
-lgl_db_lookup_category_from_name (const gchar *name)
-{
- GList *p;
- lglCategory *category;
-
- if (!model)
- {
- lgl_db_init ();
- }
-
- if (name == NULL)
- {
- /* If no name, return first category as a default */
- return lgl_category_dup ((lglCategory *) model->categories->data);
- }
-
- for (p = model->categories; p != NULL; p = p->next)
- {
- category = (lglCategory *) p->data;
- if (UTF8_EQUAL (category->name, name))
- {
- return lgl_category_dup (category);
- }
- }
-
- return NULL;
-}
-
-
-/**
- * lgl_db_lookup_category_from_id:
- * @id: category id string
- *
- * Lookup category definition from id string.
- *
- * Returns: pointer to a newly allocated #lglCategory structure.
- *
- */
-lglCategory *
-lgl_db_lookup_category_from_id (const gchar *id)
-{
- GList *p;
- lglCategory *category;
-
- if (!model)
- {
- lgl_db_init ();
- }
-
- if (id == NULL)
- {
- /* If no id, return first category as a default */
- return lgl_category_dup ((lglCategory *) model->categories->data);
- }
-
- for (p = model->categories; p != NULL; p = p->next)
- {
- category = (lglCategory *) p->data;
- if (ASCII_EQUAL (category->id, id))
- {
- return lgl_category_dup (category);
- }
- }
-
- return NULL;
-}
-
-
-/**
- * lgl_db_lookup_category_id_from_name:
- * @name: localized category name stringp
- *
- * Lookup category name string from localized category name string.
- *
- * Returns: pointer to a newly allocated id string.
- *
- */
-gchar *
-lgl_db_lookup_category_id_from_name (const gchar *name)
-{
- lglCategory *category = NULL;
- gchar *id = NULL;
-
- if (name != NULL)
- {
- category = lgl_db_lookup_category_from_name (name);
- if ( category != NULL )
- {
- id = g_strdup (category->id);
- lgl_category_free (category);
- category = NULL;
- }
- }
-
- return id;
-}
-
-
-/**
- * lgl_db_lookup_category_name_from_id:
- * @id: category id string
- *
- * Lookup localized category name string from category id string.
- *
- * Returns: pointer to a newly allocated localized category name string.
- *
- */
-gchar *
-lgl_db_lookup_category_name_from_id (const gchar *id)
-{
- lglCategory *category = NULL;
- gchar *name = NULL;
-
- if (id != NULL)
- {
- category = lgl_db_lookup_category_from_id (id);
- if ( category != NULL )
- {
- name = g_strdup (category->name);
- lgl_category_free (category);
- category = NULL;
- }
- }
-
- return name;
-}
-
-
-/**
- * lgl_db_is_category_id_known:
- * @id: category id to test
- *
- * Determine if given category id is known to libglabels.
- *
- * Returns: TRUE if id is known, otherwise FALSE.
- *
- */
-gboolean
-lgl_db_is_category_id_known (const gchar *id)
-{
- GList *p;
- lglCategory *category;
-
- if (!model)
- {
- lgl_db_init ();
- }
-
- if (id == NULL)
- {
- return FALSE;
- }
-
- for (p = model->categories; p != NULL; p = p->next)
- {
- category = (lglCategory *) p->data;
- if (ASCII_EQUAL (category->id, id))
- {
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-
-static GList *
-read_categories (void)
-{
- gchar *data_dir;
- GList *categories = NULL;
-
- data_dir = SYSTEM_CONFIG_DIR;
- categories = read_category_files_from_dir (categories, data_dir);
- g_free (data_dir);
-
- data_dir = USER_CONFIG_DIR;
- categories = read_category_files_from_dir (categories, data_dir);
- g_free (data_dir);
-
- if (categories == NULL) {
- g_critical (_("Unable to locate category definitions. Libglabels may not be installed correctly!"));
- }
-
- return categories;
-}
-
-
-static GList *
-read_category_files_from_dir (GList *categories,
- const gchar *dirname)
-{
- GDir *dp;
- const gchar *filename, *extension;
- gchar *full_filename = NULL;
- GError *gerror = NULL;
- GList *new_categories = NULL;
-
- if (dirname == NULL) {
- return categories;
- }
-
- if (!g_file_test (dirname, G_FILE_TEST_EXISTS)) {
- return categories;
- }
-
- dp = g_dir_open (dirname, 0, &gerror);
- if (gerror != NULL) {
- g_message ("cannot open data directory: %s", gerror->message );
- return categories;
- }
-
- while ((filename = g_dir_read_name (dp)) != NULL) {
-
- extension = strrchr (filename, '.');
-
- if (extension != NULL) {
-
- if ( ASCII_EQUAL (filename, "categories.xml") )
- {
-
- full_filename =
- g_build_filename (dirname, filename, NULL);
- new_categories =
- lgl_xml_category_read_categories_from_file (full_filename);
- g_free (full_filename);
-
- categories = g_list_concat (categories, new_categories);
- new_categories = NULL;
-
- }
-
- }
-
- }
-
- g_dir_close (dp);
-
- return categories;
-}
-
-
-/**
- * lgl_db_print_known_categories:
- *
- * For debugging purposes: print a list of all category definitions known to
- * libglabels.
- *
- */
-void
-lgl_db_print_known_categories (void)
-{
- GList *p;
- lglCategory *category;
-
- if (!model) {
- lgl_db_init ();
- }
-
- g_print ("%s():\n", __FUNCTION__);
- for (p = model->categories; p != NULL; p = p->next) {
- category = (lglCategory *) p->data;
-
- g_print ("CATEGORY id=\"%s\", name=\"%s\"\n", category->id, category->name);
-
- }
- g_print ("\n");
-
-}
-
-
-/*===========================================*/
-/* Vendor db functions. */
-/*===========================================*/
-
-/**
- * lgl_db_get_vendor_name_list:
- *
- * Get a list of all localized vendor names known to libglabels.
- *
- * Returns: a list of localized vendor names.
- *
- */
-GList *
-lgl_db_get_vendor_name_list (void)
-{
- GList *names = NULL;
- GList *p;
- lglVendor *vendor;
-
- if (!model)
- {
- lgl_db_init ();
- }
-
- for ( p=model->vendors; p != NULL; p=p->next )
- {
- vendor = (lglVendor *)p->data;
- names = g_list_append (names, g_strdup (vendor->name));
- }
-
- return names;
-}
-
-
-/**
- * lgl_db_free_vendor_name_list:
- * @names: List of localized vendor name strings to be freed.
- *
- * Free up all storage associated with a name list obtained with
- * lgl_db_get_vendor_name_list().
- *
- */
-void
-lgl_db_free_vendor_name_list (GList *names)
-{
- GList *p;
-
- for (p = names; p != NULL; p = p->next)
- {
- g_free (p->data);
- p->data = NULL;
- }
-
- g_list_free (names);
-}
-
-
-/**
- * lgl_db_lookup_vendor_from_name:
- * @name: localized vendor name string
- *
- * Lookup vendor definition from localized vendor name string.
- *
- * Returns: pointer to a newly allocated #lglVendor structure.
- *
- */
-lglVendor *
-lgl_db_lookup_vendor_from_name (const gchar *name)
-{
- GList *p;
- lglVendor *vendor;
-
- if (!model)
- {
- lgl_db_init ();
- }
-
- if (name == NULL)
- {
- /* If no name, return first vendor as a default */
- return lgl_vendor_dup ((lglVendor *) model->vendors->data);
- }
-
- for (p = model->vendors; p != NULL; p = p->next)
- {
- vendor = (lglVendor *) p->data;
- if (UTF8_EQUAL (vendor->name, name))
- {
- return lgl_vendor_dup (vendor);
- }
- }
-
- return NULL;
-}
-
-
-/**
- * lgl_db_is_vendor_name_known:
- * @name: vendor name to test
- *
- * Determine if given vendor id is known to libglabels.
- *
- * Returns: TRUE if id is known, otherwise FALSE.
- *
- */
-gboolean
-lgl_db_is_vendor_name_known (const gchar *name)
-{
- GList *p;
- lglVendor *vendor;
-
- if (!model)
- {
- lgl_db_init ();
- }
-
- if (name == NULL)
- {
- return FALSE;
- }
-
- for (p = model->vendors; p != NULL; p = p->next)
- {
- vendor = (lglVendor *) p->data;
- if (UTF8_EQUAL (vendor->name, name))
- {
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-
-static GList *
-read_vendors (void)
-{
- gchar *data_dir;
- GList *vendors = NULL;
-
- data_dir = SYSTEM_CONFIG_DIR;
- vendors = read_vendor_files_from_dir (vendors, data_dir);
- g_free (data_dir);
-
- data_dir = USER_CONFIG_DIR;
- vendors = read_vendor_files_from_dir (vendors, data_dir);
- g_free (data_dir);
-
- return vendors;
-}
-
-
-static GList *
-read_vendor_files_from_dir (GList *vendors,
- const gchar *dirname)
-{
- GDir *dp;
- const gchar *filename, *extension;
- gchar *full_filename = NULL;
- GError *gerror = NULL;
- GList *new_vendors = NULL;
-
- if (dirname == NULL) {
- return vendors;
- }
-
- if (!g_file_test (dirname, G_FILE_TEST_EXISTS)) {
- return vendors;
- }
-
- dp = g_dir_open (dirname, 0, &gerror);
- if (gerror != NULL) {
- g_message ("cannot open data directory: %s", gerror->message );
- return vendors;
- }
-
- while ((filename = g_dir_read_name (dp)) != NULL) {
-
- extension = strrchr (filename, '.');
-
- if (extension != NULL) {
-
- if ( ASCII_EQUAL (filename, "vendors.xml") )
- {
-
- full_filename =
- g_build_filename (dirname, filename, NULL);
- new_vendors =
- lgl_xml_vendor_read_vendors_from_file (full_filename);
- g_free (full_filename);
-
- vendors = g_list_concat (vendors, new_vendors);
- new_vendors = NULL;
-
- }
-
- }
-
- }
-
- g_dir_close (dp);
-
- return vendors;
-}
-
-
-/**
- * lgl_db_print_known_vendors:
- *
- * For debugging purposes: print a list of all vendor definitions known to
- * libglabels.
- *
- */
-void
-lgl_db_print_known_vendors (void)
-{
- GList *p;
- lglVendor *vendor;
-
- if (!model) {
- lgl_db_init ();
- }
-
- g_print ("%s():\n", __FUNCTION__);
- for (p = model->vendors; p != NULL; p = p->next) {
- vendor = (lglVendor *) p->data;
-
- g_print ("VENDOR name=\"%s\", url=\"%s\"\n",
- vendor->name, vendor->url);
-
- }
- g_print ("\n");
-
-}
-
-
-/*===========================================*/
-/* Brand db functions. */
-/*===========================================*/
-
-/**
- * lgl_db_get_brand_list:
- * @paper_id: If non NULL, limit results to given page size.
- * @category_id: If non NULL, limit results to given template category.
- *
- * Get a list of all valid brands of templates in the template database.
- * Results can be filtered by page size and/or template category. A list of valid page
- * sizes can be obtained using lgl_db_get_paper_id_list(). A list of valid template
- * categories can be obtained using lgl_db_get_category_id_list().
- *
- * Returns: a list of brands
- */
-GList *
-lgl_db_get_brand_list (const gchar *paper_id,
- const gchar *category_id)
-{
- GList *p_tmplt;
- lglTemplate *template;
- GList *brands = NULL;
-
- if (!model)
- {
- lgl_db_init ();
- }
-
- for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
- {
- template = (lglTemplate *) p_tmplt->data;
- if (lgl_template_does_page_size_match (template, paper_id) &&
- lgl_template_does_category_match (template, category_id))
- {
-
- if ( !g_list_find_custom (brands, template->brand,
- (GCompareFunc)lgl_str_utf8_casecmp) )
- {
- brands = g_list_insert_sorted (brands,
- g_strdup (template->brand),
- (GCompareFunc)lgl_str_utf8_casecmp);
- }
- }
- }
-
- return brands;
-}
-
-
-/**
- * lgl_db_free_brand_list:
- * @brands: List of template brand strings to be freed.
- *
- * Free up all storage associated with a list of template names obtained with
- * lgl_db_get_brand_list().
- *
- */
-void
-lgl_db_free_brand_list (GList *brands)
-{
- GList *p_brand;
-
- for (p_brand = brands; p_brand != NULL; p_brand = p_brand->next)
- {
- g_free (p_brand->data);
- p_brand->data = NULL;
- }
-
- g_list_free (brands);
-}
-
-
-/*===========================================*/
-/* Template db functions. */
-/*===========================================*/
-
-void
-_lgl_db_register_template_internal (const lglTemplate *template)
-{
- lglTemplate *template_copy;
-
- if (!lgl_db_does_template_exist (template->brand, template->part))
- {
- template_copy = lgl_template_dup (template);
- model->templates = g_list_append (model->templates, template_copy);
- add_to_template_cache (template_copy);
- }
- else
- {
- g_message ("Duplicate template: %s %s.", template->brand, template->part);
- }
-}
-
-
-/**
- * lgl_db_register_template:
- * @template: Pointer to a template structure to add to database.
- *
- * Register a template. This function adds a template to the template database.
- * The template will be stored in an individual XML file in the user template directory.
- *
- * Returns: Status of registration attempt (#lglDbRegStatus)
- */
-lglDbRegStatus
-lgl_db_register_template (const lglTemplate *template)
-{
- lglTemplate *template_copy;
- gchar *dir, *filename, *abs_filename;
- gint bytes_written;
-
- if (!model)
- {
- lgl_db_init ();
- }
-
- if (lgl_db_does_template_exist (template->brand, template->part))
- {
- return LGL_DB_REG_BRAND_PART_EXISTS;
- }
-
- if (lgl_db_is_paper_id_known (template->paper_id))
- {
- dir = USER_CONFIG_DIR;
- g_mkdir_with_parents (dir, 0775); /* Try to make sure directory exists. */
- filename = g_strdup_printf ("%s_%s.template", template->brand, template->part);
- abs_filename = g_build_filename (dir, filename, NULL);
- bytes_written = lgl_xml_template_write_template_to_file (template, abs_filename);
- g_free (dir);
- g_free (filename);
- g_free (abs_filename);
-
- if (bytes_written > 0)
- {
- template_copy = lgl_template_dup (template);
- lgl_template_add_category (template_copy, "user-defined");
- model->templates = g_list_append (model->templates, template_copy);
- add_to_template_cache (template_copy);
- g_signal_emit (G_OBJECT (model), signals[CHANGED], 0);
- return LGL_DB_REG_OK;
- }
- else
- {
- return LGL_DB_REG_FILE_WRITE_ERROR;
- }
- }
- else
- {
- g_message ("Cannot register new template with unknown page size.");
- return LGL_DB_REG_BAD_PAPER_ID;
- }
-
-}
-
-
-/**
- * lgl_db_delete_template_by_name:
- * @name: Name of template to be deleted.
- *
- * Delete a user defined template. This function deletes a template from
- * the template database. The individual XML file in the user template
- * directory will also be removed.
- *
- * Returns: Status of registration attempt (#lglDbDeleteStatus)
- */
-lglDbDeleteStatus
-lgl_db_delete_template_by_name (const gchar *name)
-{
- lglTemplate *template, *template1;
- gchar *dir, *filename, *abs_filename;
- GList *p;
-
- if (!model)
- {
- lgl_db_init ();
- }
-
- if (!lgl_db_does_template_name_exist (name))
- {
- return LGL_DB_DELETE_DOES_NOT_EXIST;
- }
-
- template = lgl_db_lookup_template_from_name (name);
- if ( lgl_template_does_category_match (template, "user-defined") )
- {
- dir = USER_CONFIG_DIR;
- filename = g_strdup_printf ("%s_%s.template", template->brand, template->part);
- abs_filename = g_build_filename (dir, filename, NULL);
-
- if (!g_file_test (abs_filename, G_FILE_TEST_EXISTS))
- {
- g_message ("File \"%s\" does not exist. Cannot delete template.", abs_filename);
- return LGL_DB_DELETE_DOES_NOT_EXIST;
- }
-
- g_unlink (abs_filename);
-
- g_free (dir);
- g_free (filename);
- g_free (abs_filename);
-
- for ( p=model->templates; p != NULL; p=p->next )
- {
- template1 = (lglTemplate *)p->data;
-
- if ( lgl_template_do_templates_match (template, template1) )
- {
- model->templates = g_list_delete_link (model->templates, p);
- g_hash_table_remove (model->template_cache, name);
- break;
- }
- }
-
- lgl_template_free (template);
-
- g_signal_emit (G_OBJECT (model), signals[CHANGED], 0);
- return LGL_DB_DELETE_OK;
- }
- else
- {
- return LGL_DB_DELETE_NOT_USER_DEFINED;
- }
-
-}
-
-
-/**
- * lgl_db_delete_template_by_brand_part:
- * @brand: Brand name or vendor of template to be deleted.
- * @part: Part name or number of template to be deleted.
- *
- * Delete a user defined template. This function deletes a template from
- * the template database. The individual XML file in the user template
- * directory will also be removed.
- *
- * Returns: Status of registration attempt (#lglDbDeleteStatus)
- */
-lglDbDeleteStatus
-lgl_db_delete_template_by_brand_part (const gchar *brand,
- const gchar *part)
-{
- gchar *name;
- lglDbDeleteStatus status;
-
- name = g_strdup_printf ("%s %s", brand, part);
-
- status = lgl_db_delete_template_by_name (name);
-
- g_free (name);
-
- return status;
-}
-
-
-/**
- * lgl_db_does_template_exist:
- * @brand: Brand name.
- * @part: Part name/number.
- *
- * This function tests whether a template with the given brand and part name/number exists.
- *
- * Returns: TRUE if such a template exists in the database.
- */
-gboolean
-lgl_db_does_template_exist (const gchar *brand,
- const gchar *part)
-{
- GList *p_tmplt;
- lglTemplate *template;
-
- if (!model)
- {
- lgl_db_init ();
- }
-
- if ((brand == NULL) || (part == NULL))
- {
- return FALSE;
- }
-
- for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
- {
- template = (lglTemplate *) p_tmplt->data;
-
- if ( UTF8_EQUAL (brand, template->brand) &&
- UTF8_EQUAL (part, template->part) )
- {
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-
-/**
- * lgl_db_does_template_name_exist:
- * @name: name string
- *
- * This function test whether a template with the given name exists.
- *
- * Returns: TRUE if such a template exists in the database.
- *
- */
-gboolean
-lgl_db_does_template_name_exist (const gchar *name)
-{
- GList *p_tmplt;
- lglTemplate *template;
- gchar *candidate_name;
-
- if (!model)
- {
- lgl_db_init ();
- }
-
- if (name == NULL)
- {
- return FALSE;
- }
-
- for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
- {
- template = (lglTemplate *) p_tmplt->data;
- candidate_name = g_strdup_printf ("%s %s", template->brand, template->part);
-
- if ( UTF8_EQUAL (candidate_name, name) )
- {
- g_free (candidate_name);
- return TRUE;
- }
- g_free (candidate_name);
- }
-
- return FALSE;
-}
-
-
-/**
- * lgl_db_get_template_name_list_all:
- * @brand: If non NULL, limit results to given brand
- * @paper_id: If non NULL, limit results to given page size.
- * @category_id: If non NULL, limit results to given template category.
- *
- * Get a list of all valid names of templates in the template database.
- * Results can be filtered by page size and/or template category. A list of valid page
- * sizes can be obtained using lgl_db_get_paper_id_list(). A list of valid template
- * categories can be obtained using lgl_db_get_category_id_list().
- *
- * Returns: a list of template names.
- */
-GList *
-lgl_db_get_template_name_list_all (const gchar *brand,
- const gchar *paper_id,
- const gchar *category_id)
-{
- GList *p_tmplt;
- lglTemplate *template;
- gchar *name;
- GList *names = NULL;
-
- if (!model)
- {
- lgl_db_init ();
- }
-
- for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
- {
- template = (lglTemplate *) p_tmplt->data;
- if (lgl_template_does_brand_match (template, brand) &&
- lgl_template_does_page_size_match (template, paper_id) &&
- lgl_template_does_category_match (template, category_id))
- {
- name = g_strdup_printf ("%s %s", template->brand, template->part);
- names = g_list_insert_sorted (names, name, (GCompareFunc)lgl_str_part_name_cmp);
- }
- }
-
- return names;
-}
-
-
-/**
- * lgl_db_get_similar_template_name_list:
- * @name: Name of template under test.
- *
- * Get a list of all valid names of templates in the template database that
- * have the same size and layout characteristics as the given template.
- *
- * Returns: a list of template names.
- */
-GList *
-lgl_db_get_similar_template_name_list (const gchar *name)
-{
- GList *p_tmplt;
- lglTemplate *template1;
- lglTemplate *template2;
- gchar *name2;
- GList *names = NULL;
-
- if (!model)
- {
- lgl_db_init ();
- }
-
- if ( !name )
- {
- return NULL;
- }
-
- template1 = lgl_db_lookup_template_from_name (name);
- if ( !template1 )
- {
- return NULL;
- }
-
- for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
- {
- template2 = (lglTemplate *) p_tmplt->data;
-
- if ( lgl_template_are_templates_identical (template1, template2) )
- {
-
- name2 = g_strdup_printf ("%s %s", template2->brand, template2->part);
- if ( !UTF8_EQUAL (name2, name) )
- {
- names = g_list_insert_sorted (names, name2,
- (GCompareFunc)lgl_str_part_name_cmp);
- }
-
- }
- }
-
- return names;
-}
-
-
-/**
- * lgl_db_free_template_name_list:
- * @names: List of template name strings to be freed.
- *
- * Free up all storage associated with a list of template names obtained with
- * lgl_db_get_template_name_list_all().
- *
- */
-void
-lgl_db_free_template_name_list (GList *names)
-{
- GList *p_name;
-
- for (p_name = names; p_name != NULL; p_name = p_name->next)
- {
- g_free (p_name->data);
- p_name->data = NULL;
- }
-
- g_list_free (names);
-}
-
-
-/**
- * lgl_db_lookup_template_from_name:
- * @name: name string
- *
- * Lookup template in template database from name string.
- *
- * Returns: pointer to a newly allocated #lglTemplate structure.
- *
- */
-lglTemplate *
-lgl_db_lookup_template_from_name (const gchar *name)
-{
- lglTemplate *template;
- lglTemplate *new_template;
-
- if (!model)
- {
- lgl_db_init ();
- }
-
- if (name == NULL)
- {
- /* If no name, return first template as a default */
- return lgl_template_dup ((lglTemplate *) model->templates->data);
- }
-
- template = g_hash_table_lookup (model->template_cache, name);
-
- if (template)
- {
- new_template = lgl_template_dup (template);
- return new_template;
- }
-
- /* No matching template has been found so return the first template */
- return lgl_template_dup ((lglTemplate *) model->templates->data);
-}
-
-
-/**
- * lgl_db_lookup_template_from_brand_part:
- * @brand: brand name string
- * @part: part name string
- *
- * Lookup template in template database from brand and part strings.
- *
- * Returns: pointer to a newly allocated #lglTemplate structure.
- *
- */
-lglTemplate *
-lgl_db_lookup_template_from_brand_part(const gchar *brand,
- const gchar *part)
-{
- gchar *name;
- lglTemplate *template;
- lglTemplate *new_template;
-
- if (!model)
- {
- lgl_db_init ();
- }
-
- if ((brand == NULL) || (part == NULL))
- {
- /* If no name, return first template as a default */
- return lgl_template_dup ((lglTemplate *) model->templates->data);
- }
-
- name = g_strdup_printf ("%s %s", brand, part);
- template = g_hash_table_lookup (model->template_cache, name);
-
- if (template)
- {
- new_template = lgl_template_dup (template);
- return new_template;
- }
-
- /* No matching template has been found so return the first template */
- g_free (name);
- return lgl_template_dup ((lglTemplate *) model->templates->data);
-}
-
-
-static void
-add_to_template_cache (lglTemplate *template)
-{
- gchar *name;
-
- name = g_strdup_printf ("%s %s", template->brand, template->part);
-
- g_hash_table_insert (model->template_cache, name, template);
-}
-
-
-void
-read_templates (void)
-{
- gchar *data_dir;
- GList *p;
- lglTemplate *template;
-
- /*
- * User defined templates. Add to user-defined category.
- */
- data_dir = USER_CONFIG_DIR;
- read_template_files_from_dir (data_dir);
- g_free (data_dir);
- for ( p=model->templates; p != NULL; p=p->next )
- {
- template = (lglTemplate *)p->data;
- lgl_template_add_category (template, "user-defined");
- }
-
- /*
- * Alternate user defined templates. (Used for manually created templates).
- */
- data_dir = ALT_USER_CONFIG_DIR;
- read_template_files_from_dir (data_dir);
- g_free (data_dir);
-
- /*
- * System templates.
- */
- data_dir = SYSTEM_CONFIG_DIR;
- read_template_files_from_dir (data_dir);
- g_free (data_dir);
-
- if (model->templates == NULL)
- {
- g_critical (_("Unable to locate any template files. Libglabels may not be installed correctly!"));
- }
-}
-
-
-void
-read_template_files_from_dir (const gchar *dirname)
-{
- GDir *dp;
- const gchar *filename, *extension, *extension2;
- gchar *full_filename = NULL;
- GError *gerror = NULL;
-
- if (dirname == NULL)
- return;
-
- if (!g_file_test (dirname, G_FILE_TEST_EXISTS))
- {
- return;
- }
-
- dp = g_dir_open (dirname, 0, &gerror);
- if (gerror != NULL)
- {
- g_message ("cannot open data directory: %s", gerror->message );
- return;
- }
-
- while ((filename = g_dir_read_name (dp)) != NULL)
- {
-
- extension = strrchr (filename, '.');
- extension2 = strrchr (filename, '-');
-
- if ( (extension && ASCII_EQUAL (extension, ".template")) ||
- (extension2 && ASCII_EQUAL (extension2, "-templates.xml")) )
- {
-
- full_filename = g_build_filename (dirname, filename, NULL);
- lgl_xml_template_read_templates_from_file (full_filename);
- g_free (full_filename);
- }
-
- }
-
- g_dir_close (dp);
-}
-
-
-static lglTemplate *
-template_full_page (const gchar *paper_id)
-{
- lglPaper *paper = NULL;
- lglTemplate *template = NULL;
- lglTemplateFrame *frame = NULL;
- gchar *part;
- gchar *desc;
-
- g_return_val_if_fail (paper_id, NULL);
-
- paper = lgl_db_lookup_paper_from_id (paper_id);
- if ( paper == NULL )
- {
- return NULL;
- }
-
- part = g_strdup_printf ("%s-Full-Page", paper->id);
- desc = g_strdup_printf (_("%s full page label"), paper->name);
-
- template = lgl_template_new ("Generic", part, desc,
- paper_id, paper->width, paper->height);
-
-
- frame = lgl_template_frame_rect_new ("0",
- paper->width,
- paper->height,
- 0.0,
- 0.0,
- 0.0);
- lgl_template_add_frame (template, frame);
-
- lgl_template_frame_add_layout (frame, lgl_template_layout_new (1, 1, 0., 0., 0., 0.));
-
- lgl_template_frame_add_markup (frame, lgl_template_markup_margin_new (9.0));
-
- g_free (desc);
- desc = NULL;
- lgl_paper_free (paper);
- paper = NULL;
-
- return template;
-}
-
-
-/**
- * lgl_db_print_known_templates:
- *
- * Print all known templates (for debugging purposes).
- *
- */
-void
-lgl_db_print_known_templates (void)
-{
- GList *p;
- lglTemplate *template;
-
- if (!model)
- {
- lgl_db_init ();
- }
-
- g_print ("%s():\n", __FUNCTION__);
- for (p=model->templates; p!=NULL; p=p->next)
- {
- template = (lglTemplate *)p->data;
-
- g_print("TEMPLATE brand=\"%s\", part=\"%s\", description=\"%s\"\n",
- template->brand, template->part, template->description);
-
- }
- g_print ("\n");
-
-}
-
-
-
-
-/*
- * Local Variables: -- emacs
- * mode: C -- emacs
- * c-basic-offset: 8 -- emacs
- * tab-width: 8 -- emacs
- * indent-tabs-mode: nil -- emacs
- * End: -- emacs
- */
+++ /dev/null
-/*
- * db.h
- * Copyright (C) 2006-2009 Jim Evins <evins@snaught.com>.
- *
- * This file is part of libglabels.
- *
- * libglabels is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libglabels 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __LGL_DB_H__
-#define __LGL_DB_H__
-
-#include <glib.h>
-
-#include "paper.h"
-#include "category.h"
-#include "vendor.h"
-#include "template.h"
-
-G_BEGIN_DECLS
-
-typedef enum
-{
- LGL_DB_REG_OK = 0,
- LGL_DB_REG_BAD_PAPER_ID = -1,
- LGL_DB_REG_BRAND_PART_EXISTS = -2,
- LGL_DB_REG_FILE_WRITE_ERROR = -3
-} lglDbRegStatus;
-
-typedef enum
-{
- LGL_DB_DELETE_OK = 0,
- LGL_DB_DELETE_DOES_NOT_EXIST = -1,
- LGL_DB_DELETE_NOT_USER_DEFINED = -2,
- LGL_DB_DELETE_FILE_ERROR = -3
-} lglDbDeleteStatus;
-
-
-typedef void (*lglDbNotifyFunc) (gpointer user_data);
-
-
-
-
-/*
- * Module initialization
- */
-void lgl_db_init (void);
-
-
-
-/*
- * Notification
- */
-gulong lgl_db_notify_add (lglDbNotifyFunc func,
- gpointer user_data);
-
-void lgl_db_notify_remove (gulong id);
-
-
-
-/*
- * Paper
- */
-GList *lgl_db_get_paper_id_list (void);
-
-void lgl_db_free_paper_id_list (GList *ids);
-
-GList *lgl_db_get_paper_name_list (void);
-
-void lgl_db_free_paper_name_list (GList *names);
-
-lglPaper *lgl_db_lookup_paper_from_name (const gchar *name);
-
-lglPaper *lgl_db_lookup_paper_from_id (const gchar *id);
-
-gchar *lgl_db_lookup_paper_id_from_name (const gchar *name);
-
-gchar *lgl_db_lookup_paper_name_from_id (const gchar *id);
-
-gboolean lgl_db_is_paper_id_known (const gchar *id);
-
-gboolean lgl_db_is_paper_id_other (const gchar *id);
-
-
-
-/*
- * Template categories
- */
-GList *lgl_db_get_category_id_list (void);
-
-void lgl_db_free_category_id_list (GList *ids);
-
-GList *lgl_db_get_category_name_list (void);
-
-void lgl_db_free_category_name_list (GList *names);
-
-lglCategory *lgl_db_lookup_category_from_name (const gchar *name);
-
-lglCategory *lgl_db_lookup_category_from_id (const gchar *id);
-
-gchar *lgl_db_lookup_category_id_from_name (const gchar *name);
-
-gchar *lgl_db_lookup_category_name_from_id (const gchar *id);
-
-gboolean lgl_db_is_category_id_known (const gchar *id);
-
-
-/*
- * Vendor
- */
-GList *lgl_db_get_vendor_name_list (void);
-
-void lgl_db_free_vendor_name_list (GList *names);
-
-lglVendor *lgl_db_lookup_vendor_from_name (const gchar *name);
-
-gboolean lgl_db_is_vendor_name_known (const gchar *name);
-
-
-/*
- * Template brands
- */
-GList *lgl_db_get_brand_list (const gchar *paper_id,
- const gchar *category_id);
-
-void lgl_db_free_brand_list (GList *brands);
-
-
-/*
- * Templates
- */
-lglDbRegStatus lgl_db_register_template (const lglTemplate *template);
-
-lglDbDeleteStatus lgl_db_delete_template_by_name (const gchar *name);
-
-lglDbDeleteStatus lgl_db_delete_template_by_brand_part (const gchar *brand,
- const gchar *part);
-
-gboolean lgl_db_does_template_exist (const gchar *brand,
- const gchar *part);
-
-gboolean lgl_db_does_template_name_exist (const gchar *name);
-
-GList *lgl_db_get_template_name_list_all (const gchar *brand,
- const gchar *paper_id,
- const gchar *category_id);
-
-GList *lgl_db_get_similar_template_name_list (const gchar *name);
-
-void lgl_db_free_template_name_list (GList *names);
-
-lglTemplate *lgl_db_lookup_template_from_name (const gchar *name);
-
-lglTemplate *lgl_db_lookup_template_from_brand_part(const gchar *brand,
- const gchar *part);
-
-
-/*
- * Debugging functions
- */
-void lgl_db_print_known_papers (void);
-
-void lgl_db_print_known_categories (void);
-
-void lgl_db_print_known_templates (void);
-
-void lgl_db_print_aliases (const lglTemplate *template);
-
-void lgl_db_print_known_vendors (void);
-
-
-
-G_END_DECLS
-
-#endif /* __LGL_DB_H__ */
-
-
-
-/*
- * Local Variables: -- emacs
- * mode: C -- emacs
- * c-basic-offset: 8 -- emacs
- * tab-width: 8 -- emacs
- * indent-tabs-mode: nil -- emacs
- * End: -- emacs
- */
--- /dev/null
+/*
+ * lgl-category.c
+ * Copyright (C) 2006-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "lgl-category.h"
+
+#include <glib/gi18n.h>
+#include <glib.h>
+#include <string.h>
+
+#include "libglabels-private.h"
+
+
+/*===========================================*/
+/* Private types */
+/*===========================================*/
+
+
+/*===========================================*/
+/* Private globals */
+/*===========================================*/
+
+
+/*===========================================*/
+/* Local function prototypes */
+/*===========================================*/
+
+
+/*===========================================*/
+/* Functions. */
+/*===========================================*/
+
+/**
+ * lgl_category_new:
+ * @id: Id of category definition. (E.g. label, card, etc.) Should be
+ * unique.
+ * @name: Localized name of category.
+ *
+ * Allocates and constructs a new #lglCategory structure.
+ *
+ * Returns: a pointer to a newly allocated #lglCategory structure.
+ *
+ */
+lglCategory *
+lgl_category_new (gchar *id,
+ gchar *name)
+{
+ lglCategory *category;
+
+ category = g_new0 (lglCategory,1);
+ category->id = g_strdup (id);
+ category->name = g_strdup (name);
+
+ return category;
+}
+
+
+/**
+ * lgl_category_dup:
+ * @orig: #lglCategory structure to be duplicated.
+ *
+ * Duplicates an existing #lglCategory structure.
+ *
+ * Returns: a pointer to a newly allocated #lglCategory structure.
+ *
+ */
+lglCategory *lgl_category_dup (const lglCategory *orig)
+{
+ lglCategory *category;
+
+ g_return_val_if_fail (orig, NULL);
+
+ category = g_new0 (lglCategory,1);
+
+ category->id = g_strdup (orig->id);
+ category->name = g_strdup (orig->name);
+
+ return category;
+}
+
+
+/**
+ * lgl_category_free:
+ * @category: pointer to #lglCategory structure to be freed.
+ *
+ * Free all memory associated with an existing #lglCategory structure.
+ *
+ */
+void lgl_category_free (lglCategory *category)
+{
+
+ if ( category != NULL ) {
+
+ g_free (category->id);
+ category->id = NULL;
+
+ g_free (category->name);
+ category->name = NULL;
+
+ g_free (category);
+ }
+
+}
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
--- /dev/null
+/*
+ * lgl-category.h
+ * Copyright (C) 2006-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LGL_CATEGORY_H__
+#define __LGL_CATEGORY_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+/*
+ * Template class
+ */
+typedef struct _lglCategory lglCategory;
+
+struct _lglCategory {
+ gchar *id; /* Unique ID of category */
+ gchar *name; /* Localized name of category */
+};
+
+
+/*
+ * Category construction
+ */
+lglCategory *lgl_category_new (gchar *id,
+ gchar *name);
+
+lglCategory *lgl_category_dup (const lglCategory *orig);
+void lgl_category_free (lglCategory *category);
+
+
+G_END_DECLS
+
+#endif /* __LGL_CATEGORY_H__ */
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
--- /dev/null
+/*
+ * lgl-db.c
+ * Copyright (C) 2003-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "lgl-db.h"
+
+#include <glib/gi18n.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <glib-object.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "libglabels-private.h"
+
+#include "lgl-xml-paper.h"
+#include "lgl-xml-category.h"
+#include "lgl-xml-vendor.h"
+#include "lgl-xml-template.h"
+
+/*===========================================*/
+/* Private macros and constants. */
+/*===========================================*/
+
+/* Data system and user data directories. (must free w/ g_free()) */
+#define SYSTEM_CONFIG_DIR g_build_filename (LIBGLABELS_CONFIG_DIR, "templates", NULL)
+#define USER_CONFIG_DIR g_build_filename (g_get_user_config_dir (), "libglabels", "templates" , NULL)
+#define ALT_USER_CONFIG_DIR g_build_filename (g_get_home_dir (), ".glabels", NULL)
+
+
+/*===========================================*/
+/* Private types */
+/*===========================================*/
+
+#define TYPE_LGL_DB_MODEL (lgl_db_model_get_type ())
+#define LGL_DB_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_LGL_DB_MODEL, lglDbModel))
+#define LGL_DB_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_LGL_DB_MODEL, lglDbModelClass))
+#define IS_LGL_DB_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_LGL_DB_MODEL))
+#define IS_LGL_DB_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_LGL_DB_MODEL))
+#define LGL_DB_MODEL_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), TYPE_LGL_DB_MODEL, lglDbModelClass))
+
+
+typedef struct _lglDbModel lglDbModel;
+typedef struct _lglDbModelClass lglDbModelClass;
+
+
+struct _lglDbModel {
+ GObject parent;
+
+ GList *papers;
+ GList *categories;
+ GList *vendors;
+ GList *templates;
+
+ GHashTable *template_cache;
+};
+
+
+struct _lglDbModelClass {
+ GObjectClass parent_class;
+
+ /*
+ * Signals
+ */
+ void (*changed) (lglDbModel *this,
+ gpointer user_data);
+
+};
+
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+
+/*===========================================*/
+/* Private globals */
+/*===========================================*/
+
+static guint signals[LAST_SIGNAL] = {0};
+
+static lglDbModel *model = NULL;
+
+
+/*===========================================*/
+/* Local function prototypes */
+/*===========================================*/
+
+static void lgl_db_model_finalize (GObject *object);
+
+static void add_to_template_cache (lglTemplate *template);
+
+static GList *read_papers (void);
+static GList *read_paper_files_from_dir (GList *papers,
+ const gchar *dirname);
+
+static GList *read_categories (void);
+static GList *read_category_files_from_dir (GList *categories,
+ const gchar *dirname);
+
+static GList *read_vendors (void);
+static GList *read_vendor_files_from_dir (GList *vendors,
+ const gchar *dirname);
+
+static void read_templates (void);
+static void read_template_files_from_dir (const gchar *dirname);
+
+static lglTemplate *template_full_page (const gchar *page_size);
+
+
+/*****************************************************************************/
+/* Object infrastructure. */
+/*****************************************************************************/
+G_DEFINE_TYPE (lglDbModel, lgl_db_model, G_TYPE_OBJECT);
+
+
+/*****************************************************************************/
+/* Class Init Function. */
+/*****************************************************************************/
+static void
+lgl_db_model_class_init (lglDbModelClass *class)
+{
+ GObjectClass *gobject_class = (GObjectClass *) class;
+
+ lgl_db_model_parent_class = g_type_class_peek_parent (class);
+
+ gobject_class->finalize = lgl_db_model_finalize;
+
+ signals[CHANGED] =
+ g_signal_new ("changed",
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (lglDbModelClass, changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+}
+
+
+/*****************************************************************************/
+/* Object Instance Init Function. */
+/*****************************************************************************/
+static void
+lgl_db_model_init (lglDbModel *this)
+{
+ this->template_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)lgl_template_free);
+}
+
+
+/*****************************************************************************/
+/* Finalize Method. */
+/*****************************************************************************/
+static void
+lgl_db_model_finalize (GObject *object)
+{
+ lglDbModel *this;
+ GList *p;
+
+ g_return_if_fail (object && IS_LGL_DB_MODEL (object));
+ this = LGL_DB_MODEL (object);
+
+ g_hash_table_unref (this->template_cache);
+
+ for (p = this->papers; p != NULL; p = p->next)
+ {
+ g_free (p->data);
+ p->data = NULL;
+ }
+ g_list_free (this->papers);
+
+ for (p = this->categories; p != NULL; p = p->next)
+ {
+ g_free (p->data);
+ p->data = NULL;
+ }
+ g_list_free (this->categories);
+
+ for (p = this->vendors; p != NULL; p = p->next)
+ {
+ g_free (p->data);
+ p->data = NULL;
+ }
+ g_list_free (this->vendors);
+
+ for (p = this->templates; p != NULL; p = p->next)
+ {
+ lgl_template_free ((lglTemplate *)p->data);
+ p->data = NULL;
+ }
+ g_list_free (this->templates);
+
+ G_OBJECT_CLASS (lgl_db_model_parent_class)->finalize (object);
+}
+
+
+/*****************************************************************************/
+/** New Object Generator. */
+/*****************************************************************************/
+lglDbModel *
+lgl_db_model_new (void)
+{
+ lglDbModel *this;
+
+ this = g_object_new (TYPE_LGL_DB_MODEL, NULL);
+
+ return this;
+}
+
+
+/*===========================================*/
+/* Module initialization */
+/*===========================================*/
+
+/**
+ * lgl_db_init:
+ *
+ * Initialize all libglabels subsystems. It is not necessary for an application to call
+ * lgl_db_init(), because libglabels will initialize on demand. An application programmer may
+ * choose to call lgl_db_init() at startup to minimize the impact of the first libglabels call
+ * on GUI response time.
+ *
+ * This function initializes its paper definitions, category definitions, vendor definitions,
+ * and its template database. It will search both system and user template directories to locate
+ * this data.
+ */
+void
+lgl_db_init (void)
+{
+ lglPaper *paper_other;
+ lglCategory *category_user_defined;
+ lglTemplate *template;
+ GList *page_sizes;
+ GList *p;
+
+ model = lgl_db_model_new ();
+
+ /*
+ * Paper definitions
+ */
+ model->papers = read_papers ();
+
+ /* Create and append an "Other" entry. */
+ /* Translators: "Other" here means other page size. Meaning a page size
+ * other than the standard ones that libglabels knows about such as
+ * "letter", "A4", etc. */
+ paper_other = lgl_paper_new ("Other", _("Other"), 0.0, 0.0, NULL);
+ model->papers = g_list_append (model->papers, paper_other);
+
+ /*
+ * Categories
+ */
+ model->categories = read_categories ();
+
+ /* Create and append a "User defined" entry. */
+ category_user_defined = lgl_category_new ("user-defined", _("User defined"));
+ model->categories = g_list_append (model->categories, category_user_defined);
+
+ /*
+ * Vendors
+ */
+ model->vendors = read_vendors ();
+
+ /*
+ * Templates
+ */
+ read_templates ();
+
+ /* Create and append generic full page templates. */
+ page_sizes = lgl_db_get_paper_id_list ();
+ for ( p=page_sizes; p != NULL; p=p->next )
+ {
+ if ( !lgl_db_is_paper_id_other (p->data) )
+ {
+ template = template_full_page (p->data);
+ _lgl_db_register_template_internal (template);
+ lgl_template_free (template);
+ }
+ }
+ lgl_db_free_paper_id_list (page_sizes);
+
+}
+
+
+/**
+ * lgl_db_notify_add:
+ * @func: Callback function to be called when database changes.
+ * @user_data: Passback user data to supply to callback function.
+ *
+ * Register a notification callback function to be called when the database changes.
+ *
+ * Returns: an ID for this notification registration.
+ */
+gulong
+lgl_db_notify_add (lglDbNotifyFunc func,
+ gpointer user_data)
+{
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ return g_signal_connect_swapped (G_OBJECT (model), "changed", G_CALLBACK (func), user_data);
+}
+
+
+/**
+ * lgl_db_notify_remove:
+ * @id: ID of notification registration to cancel (see lgl_db_notify_add()).
+ *
+ * Cancel a previous registration a notification callback function.
+ */
+void
+lgl_db_notify_remove (gulong id)
+{
+ g_signal_handler_disconnect (G_OBJECT (model), id);
+}
+
+
+/*===========================================*/
+/* Paper db functions. */
+/*===========================================*/
+
+/**
+ * lgl_db_get_paper_id_list:
+ *
+ * Get a list of all paper ids known to libglabels.
+ *
+ * Returns: a list of paper ids.
+ *
+ */
+GList *
+lgl_db_get_paper_id_list (void)
+{
+ GList *ids = NULL;
+ GList *p;
+ lglPaper *paper;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ for ( p=model->papers; p != NULL; p=p->next )
+ {
+ paper = (lglPaper *)p->data;
+ ids = g_list_append (ids, g_strdup (paper->id));
+ }
+
+ return ids;
+}
+
+
+/**
+ * lgl_db_free_paper_id_list:
+ * @ids: List of id strings to be freed.
+ *
+ * Free up all storage associated with an id list obtained with
+ * lgl_db_get_paper_id_list().
+ *
+ */
+void
+lgl_db_free_paper_id_list (GList *ids)
+{
+ GList *p;
+
+ for (p = ids; p != NULL; p = p->next)
+ {
+ g_free (p->data);
+ p->data = NULL;
+ }
+
+ g_list_free (ids);
+}
+
+
+/**
+ * lgl_db_get_paper_name_list:
+ *
+ * Get a list of all localized paper names known to libglabels.
+ *
+ * Returns: a list of localized paper names.
+ *
+ */
+GList *
+lgl_db_get_paper_name_list (void)
+{
+ GList *names = NULL;
+ GList *p;
+ lglPaper *paper;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ for ( p=model->papers; p != NULL; p=p->next )
+ {
+ paper = (lglPaper *)p->data;
+ names = g_list_append (names, g_strdup (paper->name));
+ }
+
+ return names;
+}
+
+
+/**
+ * lgl_db_free_paper_name_list:
+ * @names: List of localized paper name strings to be freed.
+ *
+ * Free up all storage associated with a name list obtained with
+ * lgl_db_get_paper_name_list().
+ *
+ */
+void
+lgl_db_free_paper_name_list (GList *names)
+{
+ GList *p;
+
+ for (p = names; p != NULL; p = p->next)
+ {
+ g_free (p->data);
+ p->data = NULL;
+ }
+
+ g_list_free (names);
+}
+
+
+/**
+ * lgl_db_lookup_paper_from_name:
+ * @name: localized paper name string
+ *
+ * Lookup paper definition from localized paper name string.
+ *
+ * Returns: pointer to a newly allocated #lglPaper structure.
+ *
+ */
+lglPaper *
+lgl_db_lookup_paper_from_name (const gchar *name)
+{
+ GList *p;
+ lglPaper *paper;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if (name == NULL)
+ {
+ /* If no name, return first paper as a default */
+ return lgl_paper_dup ((lglPaper *) model->papers->data);
+ }
+
+ for (p = model->papers; p != NULL; p = p->next)
+ {
+ paper = (lglPaper *) p->data;
+ if (UTF8_EQUAL (paper->name, name))
+ {
+ return lgl_paper_dup (paper);
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ * lgl_db_lookup_paper_from_id:
+ * @id: paper id string
+ *
+ * Lookup paper definition from id string.
+ *
+ * Returns: pointer to a newly allocated #lglPaper structure.
+ *
+ */
+lglPaper *
+lgl_db_lookup_paper_from_id (const gchar *id)
+{
+ GList *p;
+ lglPaper *paper;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if (id == NULL)
+ {
+ /* If no id, return first paper as a default */
+ return lgl_paper_dup ((lglPaper *) model->papers->data);
+ }
+
+ for (p = model->papers; p != NULL; p = p->next)
+ {
+ paper = (lglPaper *) p->data;
+ if (ASCII_EQUAL (paper->id, id))
+ {
+ return lgl_paper_dup (paper);
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ * lgl_db_lookup_paper_id_from_name:
+ * @name: localized paper name stringp
+ *
+ * Lookup paper name string from localized paper name string.
+ *
+ * Returns: pointer to a newly allocated id string.
+ *
+ */
+gchar *
+lgl_db_lookup_paper_id_from_name (const gchar *name)
+{
+ lglPaper *paper = NULL;
+ gchar *id = NULL;
+
+ if (name != NULL)
+ {
+ paper = lgl_db_lookup_paper_from_name (name);
+ if ( paper != NULL )
+ {
+ id = g_strdup (paper->id);
+ lgl_paper_free (paper);
+ paper = NULL;
+ }
+ }
+
+ return id;
+}
+
+
+/**
+ * lgl_db_lookup_paper_name_from_id:
+ * @id: paper id string
+ *
+ * Lookup localized paper name string from paper id string.
+ *
+ * Returns: pointer to a newly allocated localized paper name string.
+ *
+ */
+gchar *
+lgl_db_lookup_paper_name_from_id (const gchar *id)
+{
+ lglPaper *paper = NULL;
+ gchar *name = NULL;
+
+ if (id != NULL)
+ {
+ paper = lgl_db_lookup_paper_from_id (id);
+ if ( paper != NULL )
+ {
+ name = g_strdup (paper->name);
+ lgl_paper_free (paper);
+ paper = NULL;
+ }
+ }
+
+ return name;
+}
+
+
+/**
+ * lgl_db_is_paper_id_known:
+ * @id: paper id to test
+ *
+ * Determine if given paper id is known to libglabels.
+ *
+ * Returns: TRUE if id is known, otherwise FALSE.
+ *
+ */
+gboolean
+lgl_db_is_paper_id_known (const gchar *id)
+{
+ GList *p;
+ lglPaper *paper;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if (id == NULL)
+ {
+ return FALSE;
+ }
+
+ for (p = model->papers; p != NULL; p = p->next)
+ {
+ paper = (lglPaper *) p->data;
+ if (ASCII_EQUAL (paper->id, id))
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/**
+ * lgl_db_is_paper_id_other:
+ * @id: paper id to test
+ *
+ * Determine if given paper id is the special id "Other."
+ *
+ * Returns: TRUE if id is "Other", otherwise FALSE.
+ *
+ */
+gboolean
+lgl_db_is_paper_id_other (const gchar *id)
+{
+ if (id == NULL)
+ {
+ return FALSE;
+ }
+
+ return (ASCII_EQUAL (id, "Other"));
+}
+
+
+static GList *
+read_papers (void)
+{
+ gchar *data_dir;
+ GList *papers = NULL;
+
+ data_dir = SYSTEM_CONFIG_DIR;
+ papers = read_paper_files_from_dir (papers, data_dir);
+ g_free (data_dir);
+
+ data_dir = USER_CONFIG_DIR;
+ papers = read_paper_files_from_dir (papers, data_dir);
+ g_free (data_dir);
+
+ if (papers == NULL) {
+ g_critical (_("Unable to locate paper size definitions. Libglabels may not be installed correctly!"));
+ }
+
+ return papers;
+}
+
+
+static GList *
+read_paper_files_from_dir (GList *papers,
+ const gchar *dirname)
+{
+ GDir *dp;
+ const gchar *filename, *extension;
+ gchar *full_filename = NULL;
+ GError *gerror = NULL;
+ GList *new_papers = NULL;
+
+ if (dirname == NULL) {
+ return papers;
+ }
+
+ if (!g_file_test (dirname, G_FILE_TEST_EXISTS)) {
+ return papers;
+ }
+
+ dp = g_dir_open (dirname, 0, &gerror);
+ if (gerror != NULL) {
+ g_message ("cannot open data directory: %s", gerror->message );
+ return papers;
+ }
+
+ while ((filename = g_dir_read_name (dp)) != NULL) {
+
+ extension = strrchr (filename, '.');
+
+ if (extension != NULL) {
+
+ if ( ASCII_EQUAL (filename, "paper-sizes.xml") )
+ {
+
+ full_filename =
+ g_build_filename (dirname, filename, NULL);
+ new_papers =
+ lgl_xml_paper_read_papers_from_file (full_filename);
+ g_free (full_filename);
+
+ papers = g_list_concat (papers, new_papers);
+ new_papers = NULL;
+
+ }
+
+ }
+
+ }
+
+ g_dir_close (dp);
+
+ return papers;
+}
+
+
+/**
+ * lgl_db_print_known_papers:
+ *
+ * For debugging purposes: print a list of all paper definitions known to
+ * libglabels.
+ *
+ */
+void
+lgl_db_print_known_papers (void)
+{
+ GList *p;
+ lglPaper *paper;
+
+ if (!model) {
+ lgl_db_init ();
+ }
+
+ g_print ("%s():\n", __FUNCTION__);
+ for (p = model->papers; p != NULL; p = p->next) {
+ paper = (lglPaper *) p->data;
+
+ g_print ("PAPER id=\"%s\", name=\"%s\", width=%gpts, height=%gpts\n",
+ paper->id, paper->name, paper->width, paper->height);
+
+ }
+ g_print ("\n");
+
+}
+
+
+/*===========================================*/
+/* Category db functions. */
+/*===========================================*/
+
+/**
+ * lgl_db_get_category_id_list:
+ *
+ * Get a list of all category ids known to libglabels.
+ *
+ * Returns: a list of category ids.
+ *
+ */
+GList *
+lgl_db_get_category_id_list (void)
+{
+ GList *ids = NULL;
+ GList *p;
+ lglCategory *category;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ for ( p=model->categories; p != NULL; p=p->next )
+ {
+ category = (lglCategory *)p->data;
+ ids = g_list_append (ids, g_strdup (category->id));
+ }
+
+ return ids;
+}
+
+
+/**
+ * lgl_db_free_category_id_list:
+ * @ids: List of id strings to be freed.
+ *
+ * Free up all storage associated with an id list obtained with
+ * lgl_db_get_category_id_list().
+ *
+ */
+void
+lgl_db_free_category_id_list (GList *ids)
+{
+ GList *p;
+
+ for (p = ids; p != NULL; p = p->next)
+ {
+ g_free (p->data);
+ p->data = NULL;
+ }
+
+ g_list_free (ids);
+}
+
+
+/**
+ * lgl_db_get_category_name_list:
+ *
+ * Get a list of all localized category names known to libglabels.
+ *
+ * Returns: a list of localized category names.
+ *
+ */
+GList *
+lgl_db_get_category_name_list (void)
+{
+ GList *names = NULL;
+ GList *p;
+ lglCategory *category;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ for ( p=model->categories; p != NULL; p=p->next )
+ {
+ category = (lglCategory *)p->data;
+ names = g_list_append (names, g_strdup (category->name));
+ }
+
+ return names;
+}
+
+
+/**
+ * lgl_db_free_category_name_list:
+ * @names: List of localized category name strings to be freed.
+ *
+ * Free up all storage associated with a name list obtained with
+ * lgl_db_get_category_name_list().
+ *
+ */
+void
+lgl_db_free_category_name_list (GList *names)
+{
+ GList *p;
+
+ for (p = names; p != NULL; p = p->next)
+ {
+ g_free (p->data);
+ p->data = NULL;
+ }
+
+ g_list_free (names);
+}
+
+
+/**
+ * lgl_db_lookup_category_from_name:
+ * @name: localized category name string
+ *
+ * Lookup category definition from localized category name string.
+ *
+ * Returns: pointer to a newly allocated #lglCategory structure.
+ *
+ */
+lglCategory *
+lgl_db_lookup_category_from_name (const gchar *name)
+{
+ GList *p;
+ lglCategory *category;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if (name == NULL)
+ {
+ /* If no name, return first category as a default */
+ return lgl_category_dup ((lglCategory *) model->categories->data);
+ }
+
+ for (p = model->categories; p != NULL; p = p->next)
+ {
+ category = (lglCategory *) p->data;
+ if (UTF8_EQUAL (category->name, name))
+ {
+ return lgl_category_dup (category);
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ * lgl_db_lookup_category_from_id:
+ * @id: category id string
+ *
+ * Lookup category definition from id string.
+ *
+ * Returns: pointer to a newly allocated #lglCategory structure.
+ *
+ */
+lglCategory *
+lgl_db_lookup_category_from_id (const gchar *id)
+{
+ GList *p;
+ lglCategory *category;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if (id == NULL)
+ {
+ /* If no id, return first category as a default */
+ return lgl_category_dup ((lglCategory *) model->categories->data);
+ }
+
+ for (p = model->categories; p != NULL; p = p->next)
+ {
+ category = (lglCategory *) p->data;
+ if (ASCII_EQUAL (category->id, id))
+ {
+ return lgl_category_dup (category);
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ * lgl_db_lookup_category_id_from_name:
+ * @name: localized category name stringp
+ *
+ * Lookup category name string from localized category name string.
+ *
+ * Returns: pointer to a newly allocated id string.
+ *
+ */
+gchar *
+lgl_db_lookup_category_id_from_name (const gchar *name)
+{
+ lglCategory *category = NULL;
+ gchar *id = NULL;
+
+ if (name != NULL)
+ {
+ category = lgl_db_lookup_category_from_name (name);
+ if ( category != NULL )
+ {
+ id = g_strdup (category->id);
+ lgl_category_free (category);
+ category = NULL;
+ }
+ }
+
+ return id;
+}
+
+
+/**
+ * lgl_db_lookup_category_name_from_id:
+ * @id: category id string
+ *
+ * Lookup localized category name string from category id string.
+ *
+ * Returns: pointer to a newly allocated localized category name string.
+ *
+ */
+gchar *
+lgl_db_lookup_category_name_from_id (const gchar *id)
+{
+ lglCategory *category = NULL;
+ gchar *name = NULL;
+
+ if (id != NULL)
+ {
+ category = lgl_db_lookup_category_from_id (id);
+ if ( category != NULL )
+ {
+ name = g_strdup (category->name);
+ lgl_category_free (category);
+ category = NULL;
+ }
+ }
+
+ return name;
+}
+
+
+/**
+ * lgl_db_is_category_id_known:
+ * @id: category id to test
+ *
+ * Determine if given category id is known to libglabels.
+ *
+ * Returns: TRUE if id is known, otherwise FALSE.
+ *
+ */
+gboolean
+lgl_db_is_category_id_known (const gchar *id)
+{
+ GList *p;
+ lglCategory *category;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if (id == NULL)
+ {
+ return FALSE;
+ }
+
+ for (p = model->categories; p != NULL; p = p->next)
+ {
+ category = (lglCategory *) p->data;
+ if (ASCII_EQUAL (category->id, id))
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+static GList *
+read_categories (void)
+{
+ gchar *data_dir;
+ GList *categories = NULL;
+
+ data_dir = SYSTEM_CONFIG_DIR;
+ categories = read_category_files_from_dir (categories, data_dir);
+ g_free (data_dir);
+
+ data_dir = USER_CONFIG_DIR;
+ categories = read_category_files_from_dir (categories, data_dir);
+ g_free (data_dir);
+
+ if (categories == NULL) {
+ g_critical (_("Unable to locate category definitions. Libglabels may not be installed correctly!"));
+ }
+
+ return categories;
+}
+
+
+static GList *
+read_category_files_from_dir (GList *categories,
+ const gchar *dirname)
+{
+ GDir *dp;
+ const gchar *filename, *extension;
+ gchar *full_filename = NULL;
+ GError *gerror = NULL;
+ GList *new_categories = NULL;
+
+ if (dirname == NULL) {
+ return categories;
+ }
+
+ if (!g_file_test (dirname, G_FILE_TEST_EXISTS)) {
+ return categories;
+ }
+
+ dp = g_dir_open (dirname, 0, &gerror);
+ if (gerror != NULL) {
+ g_message ("cannot open data directory: %s", gerror->message );
+ return categories;
+ }
+
+ while ((filename = g_dir_read_name (dp)) != NULL) {
+
+ extension = strrchr (filename, '.');
+
+ if (extension != NULL) {
+
+ if ( ASCII_EQUAL (filename, "categories.xml") )
+ {
+
+ full_filename =
+ g_build_filename (dirname, filename, NULL);
+ new_categories =
+ lgl_xml_category_read_categories_from_file (full_filename);
+ g_free (full_filename);
+
+ categories = g_list_concat (categories, new_categories);
+ new_categories = NULL;
+
+ }
+
+ }
+
+ }
+
+ g_dir_close (dp);
+
+ return categories;
+}
+
+
+/**
+ * lgl_db_print_known_categories:
+ *
+ * For debugging purposes: print a list of all category definitions known to
+ * libglabels.
+ *
+ */
+void
+lgl_db_print_known_categories (void)
+{
+ GList *p;
+ lglCategory *category;
+
+ if (!model) {
+ lgl_db_init ();
+ }
+
+ g_print ("%s():\n", __FUNCTION__);
+ for (p = model->categories; p != NULL; p = p->next) {
+ category = (lglCategory *) p->data;
+
+ g_print ("CATEGORY id=\"%s\", name=\"%s\"\n", category->id, category->name);
+
+ }
+ g_print ("\n");
+
+}
+
+
+/*===========================================*/
+/* Vendor db functions. */
+/*===========================================*/
+
+/**
+ * lgl_db_get_vendor_name_list:
+ *
+ * Get a list of all localized vendor names known to libglabels.
+ *
+ * Returns: a list of localized vendor names.
+ *
+ */
+GList *
+lgl_db_get_vendor_name_list (void)
+{
+ GList *names = NULL;
+ GList *p;
+ lglVendor *vendor;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ for ( p=model->vendors; p != NULL; p=p->next )
+ {
+ vendor = (lglVendor *)p->data;
+ names = g_list_append (names, g_strdup (vendor->name));
+ }
+
+ return names;
+}
+
+
+/**
+ * lgl_db_free_vendor_name_list:
+ * @names: List of localized vendor name strings to be freed.
+ *
+ * Free up all storage associated with a name list obtained with
+ * lgl_db_get_vendor_name_list().
+ *
+ */
+void
+lgl_db_free_vendor_name_list (GList *names)
+{
+ GList *p;
+
+ for (p = names; p != NULL; p = p->next)
+ {
+ g_free (p->data);
+ p->data = NULL;
+ }
+
+ g_list_free (names);
+}
+
+
+/**
+ * lgl_db_lookup_vendor_from_name:
+ * @name: localized vendor name string
+ *
+ * Lookup vendor definition from localized vendor name string.
+ *
+ * Returns: pointer to a newly allocated #lglVendor structure.
+ *
+ */
+lglVendor *
+lgl_db_lookup_vendor_from_name (const gchar *name)
+{
+ GList *p;
+ lglVendor *vendor;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if (name == NULL)
+ {
+ /* If no name, return first vendor as a default */
+ return lgl_vendor_dup ((lglVendor *) model->vendors->data);
+ }
+
+ for (p = model->vendors; p != NULL; p = p->next)
+ {
+ vendor = (lglVendor *) p->data;
+ if (UTF8_EQUAL (vendor->name, name))
+ {
+ return lgl_vendor_dup (vendor);
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ * lgl_db_is_vendor_name_known:
+ * @name: vendor name to test
+ *
+ * Determine if given vendor id is known to libglabels.
+ *
+ * Returns: TRUE if id is known, otherwise FALSE.
+ *
+ */
+gboolean
+lgl_db_is_vendor_name_known (const gchar *name)
+{
+ GList *p;
+ lglVendor *vendor;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if (name == NULL)
+ {
+ return FALSE;
+ }
+
+ for (p = model->vendors; p != NULL; p = p->next)
+ {
+ vendor = (lglVendor *) p->data;
+ if (UTF8_EQUAL (vendor->name, name))
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+static GList *
+read_vendors (void)
+{
+ gchar *data_dir;
+ GList *vendors = NULL;
+
+ data_dir = SYSTEM_CONFIG_DIR;
+ vendors = read_vendor_files_from_dir (vendors, data_dir);
+ g_free (data_dir);
+
+ data_dir = USER_CONFIG_DIR;
+ vendors = read_vendor_files_from_dir (vendors, data_dir);
+ g_free (data_dir);
+
+ return vendors;
+}
+
+
+static GList *
+read_vendor_files_from_dir (GList *vendors,
+ const gchar *dirname)
+{
+ GDir *dp;
+ const gchar *filename, *extension;
+ gchar *full_filename = NULL;
+ GError *gerror = NULL;
+ GList *new_vendors = NULL;
+
+ if (dirname == NULL) {
+ return vendors;
+ }
+
+ if (!g_file_test (dirname, G_FILE_TEST_EXISTS)) {
+ return vendors;
+ }
+
+ dp = g_dir_open (dirname, 0, &gerror);
+ if (gerror != NULL) {
+ g_message ("cannot open data directory: %s", gerror->message );
+ return vendors;
+ }
+
+ while ((filename = g_dir_read_name (dp)) != NULL) {
+
+ extension = strrchr (filename, '.');
+
+ if (extension != NULL) {
+
+ if ( ASCII_EQUAL (filename, "vendors.xml") )
+ {
+
+ full_filename =
+ g_build_filename (dirname, filename, NULL);
+ new_vendors =
+ lgl_xml_vendor_read_vendors_from_file (full_filename);
+ g_free (full_filename);
+
+ vendors = g_list_concat (vendors, new_vendors);
+ new_vendors = NULL;
+
+ }
+
+ }
+
+ }
+
+ g_dir_close (dp);
+
+ return vendors;
+}
+
+
+/**
+ * lgl_db_print_known_vendors:
+ *
+ * For debugging purposes: print a list of all vendor definitions known to
+ * libglabels.
+ *
+ */
+void
+lgl_db_print_known_vendors (void)
+{
+ GList *p;
+ lglVendor *vendor;
+
+ if (!model) {
+ lgl_db_init ();
+ }
+
+ g_print ("%s():\n", __FUNCTION__);
+ for (p = model->vendors; p != NULL; p = p->next) {
+ vendor = (lglVendor *) p->data;
+
+ g_print ("VENDOR name=\"%s\", url=\"%s\"\n",
+ vendor->name, vendor->url);
+
+ }
+ g_print ("\n");
+
+}
+
+
+/*===========================================*/
+/* Brand db functions. */
+/*===========================================*/
+
+/**
+ * lgl_db_get_brand_list:
+ * @paper_id: If non NULL, limit results to given page size.
+ * @category_id: If non NULL, limit results to given template category.
+ *
+ * Get a list of all valid brands of templates in the template database.
+ * Results can be filtered by page size and/or template category. A list of valid page
+ * sizes can be obtained using lgl_db_get_paper_id_list(). A list of valid template
+ * categories can be obtained using lgl_db_get_category_id_list().
+ *
+ * Returns: a list of brands
+ */
+GList *
+lgl_db_get_brand_list (const gchar *paper_id,
+ const gchar *category_id)
+{
+ GList *p_tmplt;
+ lglTemplate *template;
+ GList *brands = NULL;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
+ {
+ template = (lglTemplate *) p_tmplt->data;
+ if (lgl_template_does_page_size_match (template, paper_id) &&
+ lgl_template_does_category_match (template, category_id))
+ {
+
+ if ( !g_list_find_custom (brands, template->brand,
+ (GCompareFunc)lgl_str_utf8_casecmp) )
+ {
+ brands = g_list_insert_sorted (brands,
+ g_strdup (template->brand),
+ (GCompareFunc)lgl_str_utf8_casecmp);
+ }
+ }
+ }
+
+ return brands;
+}
+
+
+/**
+ * lgl_db_free_brand_list:
+ * @brands: List of template brand strings to be freed.
+ *
+ * Free up all storage associated with a list of template names obtained with
+ * lgl_db_get_brand_list().
+ *
+ */
+void
+lgl_db_free_brand_list (GList *brands)
+{
+ GList *p_brand;
+
+ for (p_brand = brands; p_brand != NULL; p_brand = p_brand->next)
+ {
+ g_free (p_brand->data);
+ p_brand->data = NULL;
+ }
+
+ g_list_free (brands);
+}
+
+
+/*===========================================*/
+/* Template db functions. */
+/*===========================================*/
+
+void
+_lgl_db_register_template_internal (const lglTemplate *template)
+{
+ lglTemplate *template_copy;
+
+ if (!lgl_db_does_template_exist (template->brand, template->part))
+ {
+ template_copy = lgl_template_dup (template);
+ model->templates = g_list_append (model->templates, template_copy);
+ add_to_template_cache (template_copy);
+ }
+ else
+ {
+ g_message ("Duplicate template: %s %s.", template->brand, template->part);
+ }
+}
+
+
+/**
+ * lgl_db_register_template:
+ * @template: Pointer to a template structure to add to database.
+ *
+ * Register a template. This function adds a template to the template database.
+ * The template will be stored in an individual XML file in the user template directory.
+ *
+ * Returns: Status of registration attempt (#lglDbRegStatus)
+ */
+lglDbRegStatus
+lgl_db_register_template (const lglTemplate *template)
+{
+ lglTemplate *template_copy;
+ gchar *dir, *filename, *abs_filename;
+ gint bytes_written;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if (lgl_db_does_template_exist (template->brand, template->part))
+ {
+ return LGL_DB_REG_BRAND_PART_EXISTS;
+ }
+
+ if (lgl_db_is_paper_id_known (template->paper_id))
+ {
+ dir = USER_CONFIG_DIR;
+ g_mkdir_with_parents (dir, 0775); /* Try to make sure directory exists. */
+ filename = g_strdup_printf ("%s_%s.template", template->brand, template->part);
+ abs_filename = g_build_filename (dir, filename, NULL);
+ bytes_written = lgl_xml_template_write_template_to_file (template, abs_filename);
+ g_free (dir);
+ g_free (filename);
+ g_free (abs_filename);
+
+ if (bytes_written > 0)
+ {
+ template_copy = lgl_template_dup (template);
+ lgl_template_add_category (template_copy, "user-defined");
+ model->templates = g_list_append (model->templates, template_copy);
+ add_to_template_cache (template_copy);
+ g_signal_emit (G_OBJECT (model), signals[CHANGED], 0);
+ return LGL_DB_REG_OK;
+ }
+ else
+ {
+ return LGL_DB_REG_FILE_WRITE_ERROR;
+ }
+ }
+ else
+ {
+ g_message ("Cannot register new template with unknown page size.");
+ return LGL_DB_REG_BAD_PAPER_ID;
+ }
+
+}
+
+
+/**
+ * lgl_db_delete_template_by_name:
+ * @name: Name of template to be deleted.
+ *
+ * Delete a user defined template. This function deletes a template from
+ * the template database. The individual XML file in the user template
+ * directory will also be removed.
+ *
+ * Returns: Status of registration attempt (#lglDbDeleteStatus)
+ */
+lglDbDeleteStatus
+lgl_db_delete_template_by_name (const gchar *name)
+{
+ lglTemplate *template, *template1;
+ gchar *dir, *filename, *abs_filename;
+ GList *p;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if (!lgl_db_does_template_name_exist (name))
+ {
+ return LGL_DB_DELETE_DOES_NOT_EXIST;
+ }
+
+ template = lgl_db_lookup_template_from_name (name);
+ if ( lgl_template_does_category_match (template, "user-defined") )
+ {
+ dir = USER_CONFIG_DIR;
+ filename = g_strdup_printf ("%s_%s.template", template->brand, template->part);
+ abs_filename = g_build_filename (dir, filename, NULL);
+
+ if (!g_file_test (abs_filename, G_FILE_TEST_EXISTS))
+ {
+ g_message ("File \"%s\" does not exist. Cannot delete template.", abs_filename);
+ return LGL_DB_DELETE_DOES_NOT_EXIST;
+ }
+
+ g_unlink (abs_filename);
+
+ g_free (dir);
+ g_free (filename);
+ g_free (abs_filename);
+
+ for ( p=model->templates; p != NULL; p=p->next )
+ {
+ template1 = (lglTemplate *)p->data;
+
+ if ( lgl_template_do_templates_match (template, template1) )
+ {
+ model->templates = g_list_delete_link (model->templates, p);
+ g_hash_table_remove (model->template_cache, name);
+ break;
+ }
+ }
+
+ lgl_template_free (template);
+
+ g_signal_emit (G_OBJECT (model), signals[CHANGED], 0);
+ return LGL_DB_DELETE_OK;
+ }
+ else
+ {
+ return LGL_DB_DELETE_NOT_USER_DEFINED;
+ }
+
+}
+
+
+/**
+ * lgl_db_delete_template_by_brand_part:
+ * @brand: Brand name or vendor of template to be deleted.
+ * @part: Part name or number of template to be deleted.
+ *
+ * Delete a user defined template. This function deletes a template from
+ * the template database. The individual XML file in the user template
+ * directory will also be removed.
+ *
+ * Returns: Status of registration attempt (#lglDbDeleteStatus)
+ */
+lglDbDeleteStatus
+lgl_db_delete_template_by_brand_part (const gchar *brand,
+ const gchar *part)
+{
+ gchar *name;
+ lglDbDeleteStatus status;
+
+ name = g_strdup_printf ("%s %s", brand, part);
+
+ status = lgl_db_delete_template_by_name (name);
+
+ g_free (name);
+
+ return status;
+}
+
+
+/**
+ * lgl_db_does_template_exist:
+ * @brand: Brand name.
+ * @part: Part name/number.
+ *
+ * This function tests whether a template with the given brand and part name/number exists.
+ *
+ * Returns: TRUE if such a template exists in the database.
+ */
+gboolean
+lgl_db_does_template_exist (const gchar *brand,
+ const gchar *part)
+{
+ GList *p_tmplt;
+ lglTemplate *template;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if ((brand == NULL) || (part == NULL))
+ {
+ return FALSE;
+ }
+
+ for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
+ {
+ template = (lglTemplate *) p_tmplt->data;
+
+ if ( UTF8_EQUAL (brand, template->brand) &&
+ UTF8_EQUAL (part, template->part) )
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/**
+ * lgl_db_does_template_name_exist:
+ * @name: name string
+ *
+ * This function test whether a template with the given name exists.
+ *
+ * Returns: TRUE if such a template exists in the database.
+ *
+ */
+gboolean
+lgl_db_does_template_name_exist (const gchar *name)
+{
+ GList *p_tmplt;
+ lglTemplate *template;
+ gchar *candidate_name;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if (name == NULL)
+ {
+ return FALSE;
+ }
+
+ for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
+ {
+ template = (lglTemplate *) p_tmplt->data;
+ candidate_name = g_strdup_printf ("%s %s", template->brand, template->part);
+
+ if ( UTF8_EQUAL (candidate_name, name) )
+ {
+ g_free (candidate_name);
+ return TRUE;
+ }
+ g_free (candidate_name);
+ }
+
+ return FALSE;
+}
+
+
+/**
+ * lgl_db_get_template_name_list_all:
+ * @brand: If non NULL, limit results to given brand
+ * @paper_id: If non NULL, limit results to given page size.
+ * @category_id: If non NULL, limit results to given template category.
+ *
+ * Get a list of all valid names of templates in the template database.
+ * Results can be filtered by page size and/or template category. A list of valid page
+ * sizes can be obtained using lgl_db_get_paper_id_list(). A list of valid template
+ * categories can be obtained using lgl_db_get_category_id_list().
+ *
+ * Returns: a list of template names.
+ */
+GList *
+lgl_db_get_template_name_list_all (const gchar *brand,
+ const gchar *paper_id,
+ const gchar *category_id)
+{
+ GList *p_tmplt;
+ lglTemplate *template;
+ gchar *name;
+ GList *names = NULL;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
+ {
+ template = (lglTemplate *) p_tmplt->data;
+ if (lgl_template_does_brand_match (template, brand) &&
+ lgl_template_does_page_size_match (template, paper_id) &&
+ lgl_template_does_category_match (template, category_id))
+ {
+ name = g_strdup_printf ("%s %s", template->brand, template->part);
+ names = g_list_insert_sorted (names, name, (GCompareFunc)lgl_str_part_name_cmp);
+ }
+ }
+
+ return names;
+}
+
+
+/**
+ * lgl_db_get_similar_template_name_list:
+ * @name: Name of template under test.
+ *
+ * Get a list of all valid names of templates in the template database that
+ * have the same size and layout characteristics as the given template.
+ *
+ * Returns: a list of template names.
+ */
+GList *
+lgl_db_get_similar_template_name_list (const gchar *name)
+{
+ GList *p_tmplt;
+ lglTemplate *template1;
+ lglTemplate *template2;
+ gchar *name2;
+ GList *names = NULL;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if ( !name )
+ {
+ return NULL;
+ }
+
+ template1 = lgl_db_lookup_template_from_name (name);
+ if ( !template1 )
+ {
+ return NULL;
+ }
+
+ for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
+ {
+ template2 = (lglTemplate *) p_tmplt->data;
+
+ if ( lgl_template_are_templates_identical (template1, template2) )
+ {
+
+ name2 = g_strdup_printf ("%s %s", template2->brand, template2->part);
+ if ( !UTF8_EQUAL (name2, name) )
+ {
+ names = g_list_insert_sorted (names, name2,
+ (GCompareFunc)lgl_str_part_name_cmp);
+ }
+
+ }
+ }
+
+ return names;
+}
+
+
+/**
+ * lgl_db_free_template_name_list:
+ * @names: List of template name strings to be freed.
+ *
+ * Free up all storage associated with a list of template names obtained with
+ * lgl_db_get_template_name_list_all().
+ *
+ */
+void
+lgl_db_free_template_name_list (GList *names)
+{
+ GList *p_name;
+
+ for (p_name = names; p_name != NULL; p_name = p_name->next)
+ {
+ g_free (p_name->data);
+ p_name->data = NULL;
+ }
+
+ g_list_free (names);
+}
+
+
+/**
+ * lgl_db_lookup_template_from_name:
+ * @name: name string
+ *
+ * Lookup template in template database from name string.
+ *
+ * Returns: pointer to a newly allocated #lglTemplate structure.
+ *
+ */
+lglTemplate *
+lgl_db_lookup_template_from_name (const gchar *name)
+{
+ lglTemplate *template;
+ lglTemplate *new_template;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if (name == NULL)
+ {
+ /* If no name, return first template as a default */
+ return lgl_template_dup ((lglTemplate *) model->templates->data);
+ }
+
+ template = g_hash_table_lookup (model->template_cache, name);
+
+ if (template)
+ {
+ new_template = lgl_template_dup (template);
+ return new_template;
+ }
+
+ /* No matching template has been found so return the first template */
+ return lgl_template_dup ((lglTemplate *) model->templates->data);
+}
+
+
+/**
+ * lgl_db_lookup_template_from_brand_part:
+ * @brand: brand name string
+ * @part: part name string
+ *
+ * Lookup template in template database from brand and part strings.
+ *
+ * Returns: pointer to a newly allocated #lglTemplate structure.
+ *
+ */
+lglTemplate *
+lgl_db_lookup_template_from_brand_part(const gchar *brand,
+ const gchar *part)
+{
+ gchar *name;
+ lglTemplate *template;
+ lglTemplate *new_template;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ if ((brand == NULL) || (part == NULL))
+ {
+ /* If no name, return first template as a default */
+ return lgl_template_dup ((lglTemplate *) model->templates->data);
+ }
+
+ name = g_strdup_printf ("%s %s", brand, part);
+ template = g_hash_table_lookup (model->template_cache, name);
+
+ if (template)
+ {
+ new_template = lgl_template_dup (template);
+ return new_template;
+ }
+
+ /* No matching template has been found so return the first template */
+ g_free (name);
+ return lgl_template_dup ((lglTemplate *) model->templates->data);
+}
+
+
+static void
+add_to_template_cache (lglTemplate *template)
+{
+ gchar *name;
+
+ name = g_strdup_printf ("%s %s", template->brand, template->part);
+
+ g_hash_table_insert (model->template_cache, name, template);
+}
+
+
+void
+read_templates (void)
+{
+ gchar *data_dir;
+ GList *p;
+ lglTemplate *template;
+
+ /*
+ * User defined templates. Add to user-defined category.
+ */
+ data_dir = USER_CONFIG_DIR;
+ read_template_files_from_dir (data_dir);
+ g_free (data_dir);
+ for ( p=model->templates; p != NULL; p=p->next )
+ {
+ template = (lglTemplate *)p->data;
+ lgl_template_add_category (template, "user-defined");
+ }
+
+ /*
+ * Alternate user defined templates. (Used for manually created templates).
+ */
+ data_dir = ALT_USER_CONFIG_DIR;
+ read_template_files_from_dir (data_dir);
+ g_free (data_dir);
+
+ /*
+ * System templates.
+ */
+ data_dir = SYSTEM_CONFIG_DIR;
+ read_template_files_from_dir (data_dir);
+ g_free (data_dir);
+
+ if (model->templates == NULL)
+ {
+ g_critical (_("Unable to locate any template files. Libglabels may not be installed correctly!"));
+ }
+}
+
+
+void
+read_template_files_from_dir (const gchar *dirname)
+{
+ GDir *dp;
+ const gchar *filename, *extension, *extension2;
+ gchar *full_filename = NULL;
+ GError *gerror = NULL;
+
+ if (dirname == NULL)
+ return;
+
+ if (!g_file_test (dirname, G_FILE_TEST_EXISTS))
+ {
+ return;
+ }
+
+ dp = g_dir_open (dirname, 0, &gerror);
+ if (gerror != NULL)
+ {
+ g_message ("cannot open data directory: %s", gerror->message );
+ return;
+ }
+
+ while ((filename = g_dir_read_name (dp)) != NULL)
+ {
+
+ extension = strrchr (filename, '.');
+ extension2 = strrchr (filename, '-');
+
+ if ( (extension && ASCII_EQUAL (extension, ".template")) ||
+ (extension2 && ASCII_EQUAL (extension2, "-templates.xml")) )
+ {
+
+ full_filename = g_build_filename (dirname, filename, NULL);
+ lgl_xml_template_read_templates_from_file (full_filename);
+ g_free (full_filename);
+ }
+
+ }
+
+ g_dir_close (dp);
+}
+
+
+static lglTemplate *
+template_full_page (const gchar *paper_id)
+{
+ lglPaper *paper = NULL;
+ lglTemplate *template = NULL;
+ lglTemplateFrame *frame = NULL;
+ gchar *part;
+ gchar *desc;
+
+ g_return_val_if_fail (paper_id, NULL);
+
+ paper = lgl_db_lookup_paper_from_id (paper_id);
+ if ( paper == NULL )
+ {
+ return NULL;
+ }
+
+ part = g_strdup_printf ("%s-Full-Page", paper->id);
+ desc = g_strdup_printf (_("%s full page label"), paper->name);
+
+ template = lgl_template_new ("Generic", part, desc,
+ paper_id, paper->width, paper->height);
+
+
+ frame = lgl_template_frame_rect_new ("0",
+ paper->width,
+ paper->height,
+ 0.0,
+ 0.0,
+ 0.0);
+ lgl_template_add_frame (template, frame);
+
+ lgl_template_frame_add_layout (frame, lgl_template_layout_new (1, 1, 0., 0., 0., 0.));
+
+ lgl_template_frame_add_markup (frame, lgl_template_markup_margin_new (9.0));
+
+ g_free (desc);
+ desc = NULL;
+ lgl_paper_free (paper);
+ paper = NULL;
+
+ return template;
+}
+
+
+/**
+ * lgl_db_print_known_templates:
+ *
+ * Print all known templates (for debugging purposes).
+ *
+ */
+void
+lgl_db_print_known_templates (void)
+{
+ GList *p;
+ lglTemplate *template;
+
+ if (!model)
+ {
+ lgl_db_init ();
+ }
+
+ g_print ("%s():\n", __FUNCTION__);
+ for (p=model->templates; p!=NULL; p=p->next)
+ {
+ template = (lglTemplate *)p->data;
+
+ g_print("TEMPLATE brand=\"%s\", part=\"%s\", description=\"%s\"\n",
+ template->brand, template->part, template->description);
+
+ }
+ g_print ("\n");
+
+}
+
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
--- /dev/null
+/*
+ * lgl-db.h
+ * Copyright (C) 2006-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LGL_DB_H__
+#define __LGL_DB_H__
+
+#include <glib.h>
+
+#include "lgl-paper.h"
+#include "lgl-category.h"
+#include "lgl-vendor.h"
+#include "lgl-template.h"
+
+G_BEGIN_DECLS
+
+typedef enum
+{
+ LGL_DB_REG_OK = 0,
+ LGL_DB_REG_BAD_PAPER_ID = -1,
+ LGL_DB_REG_BRAND_PART_EXISTS = -2,
+ LGL_DB_REG_FILE_WRITE_ERROR = -3
+} lglDbRegStatus;
+
+typedef enum
+{
+ LGL_DB_DELETE_OK = 0,
+ LGL_DB_DELETE_DOES_NOT_EXIST = -1,
+ LGL_DB_DELETE_NOT_USER_DEFINED = -2,
+ LGL_DB_DELETE_FILE_ERROR = -3
+} lglDbDeleteStatus;
+
+
+typedef void (*lglDbNotifyFunc) (gpointer user_data);
+
+
+
+
+/*
+ * Module initialization
+ */
+void lgl_db_init (void);
+
+
+
+/*
+ * Notification
+ */
+gulong lgl_db_notify_add (lglDbNotifyFunc func,
+ gpointer user_data);
+
+void lgl_db_notify_remove (gulong id);
+
+
+
+/*
+ * Paper
+ */
+GList *lgl_db_get_paper_id_list (void);
+
+void lgl_db_free_paper_id_list (GList *ids);
+
+GList *lgl_db_get_paper_name_list (void);
+
+void lgl_db_free_paper_name_list (GList *names);
+
+lglPaper *lgl_db_lookup_paper_from_name (const gchar *name);
+
+lglPaper *lgl_db_lookup_paper_from_id (const gchar *id);
+
+gchar *lgl_db_lookup_paper_id_from_name (const gchar *name);
+
+gchar *lgl_db_lookup_paper_name_from_id (const gchar *id);
+
+gboolean lgl_db_is_paper_id_known (const gchar *id);
+
+gboolean lgl_db_is_paper_id_other (const gchar *id);
+
+
+
+/*
+ * Template categories
+ */
+GList *lgl_db_get_category_id_list (void);
+
+void lgl_db_free_category_id_list (GList *ids);
+
+GList *lgl_db_get_category_name_list (void);
+
+void lgl_db_free_category_name_list (GList *names);
+
+lglCategory *lgl_db_lookup_category_from_name (const gchar *name);
+
+lglCategory *lgl_db_lookup_category_from_id (const gchar *id);
+
+gchar *lgl_db_lookup_category_id_from_name (const gchar *name);
+
+gchar *lgl_db_lookup_category_name_from_id (const gchar *id);
+
+gboolean lgl_db_is_category_id_known (const gchar *id);
+
+
+/*
+ * Vendor
+ */
+GList *lgl_db_get_vendor_name_list (void);
+
+void lgl_db_free_vendor_name_list (GList *names);
+
+lglVendor *lgl_db_lookup_vendor_from_name (const gchar *name);
+
+gboolean lgl_db_is_vendor_name_known (const gchar *name);
+
+
+/*
+ * Template brands
+ */
+GList *lgl_db_get_brand_list (const gchar *paper_id,
+ const gchar *category_id);
+
+void lgl_db_free_brand_list (GList *brands);
+
+
+/*
+ * Templates
+ */
+lglDbRegStatus lgl_db_register_template (const lglTemplate *template);
+
+lglDbDeleteStatus lgl_db_delete_template_by_name (const gchar *name);
+
+lglDbDeleteStatus lgl_db_delete_template_by_brand_part (const gchar *brand,
+ const gchar *part);
+
+gboolean lgl_db_does_template_exist (const gchar *brand,
+ const gchar *part);
+
+gboolean lgl_db_does_template_name_exist (const gchar *name);
+
+GList *lgl_db_get_template_name_list_all (const gchar *brand,
+ const gchar *paper_id,
+ const gchar *category_id);
+
+GList *lgl_db_get_similar_template_name_list (const gchar *name);
+
+void lgl_db_free_template_name_list (GList *names);
+
+lglTemplate *lgl_db_lookup_template_from_name (const gchar *name);
+
+lglTemplate *lgl_db_lookup_template_from_brand_part(const gchar *brand,
+ const gchar *part);
+
+
+/*
+ * Debugging functions
+ */
+void lgl_db_print_known_papers (void);
+
+void lgl_db_print_known_categories (void);
+
+void lgl_db_print_known_templates (void);
+
+void lgl_db_print_aliases (const lglTemplate *template);
+
+void lgl_db_print_known_vendors (void);
+
+
+
+G_END_DECLS
+
+#endif /* __LGL_DB_H__ */
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
--- /dev/null
+/*
+ * lgl-paper.c
+ * Copyright (C) 2003-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "lgl-paper.h"
+
+#include <glib/gi18n.h>
+#include <glib.h>
+#include <string.h>
+
+#include "libglabels-private.h"
+
+/*===========================================*/
+/* Private types */
+/*===========================================*/
+
+
+/*===========================================*/
+/* Private globals */
+/*===========================================*/
+
+
+/*===========================================*/
+/* Local function prototypes */
+/*===========================================*/
+
+
+/*===========================================*/
+/* Functions. */
+/*===========================================*/
+
+/**
+ * lgl_paper_new:
+ * @id: Id of paper definition. (E.g. US-Letter, A4, etc.) Should be
+ * unique.
+ * @name: Localized name of paper.
+ * @width: Width of paper in points.
+ * @height: Height of paper in points.
+ * @pwg_size: PWG 5101.1-2002 size name.
+ *
+ * Allocates and constructs a new #lglPaper structure.
+ *
+ * Returns: a pointer to a newly allocated #lglPaper structure.
+ *
+ */
+lglPaper *
+lgl_paper_new (gchar *id,
+ gchar *name,
+ gdouble width,
+ gdouble height,
+ gchar *pwg_size)
+{
+ lglPaper *paper;
+
+ paper = g_new0 (lglPaper,1);
+
+ paper->id = g_strdup (id);
+ paper->name = g_strdup (name);
+ paper->width = width;
+ paper->height = height;
+ paper->pwg_size = g_strdup (pwg_size);
+
+ return paper;
+}
+
+
+/**
+ * lgl_paper_dup:
+ * @orig: #lglPaper structure to be duplicated.
+ *
+ * Duplicates an existing #lglPaper structure.
+ *
+ * Returns: a pointer to a newly allocated #lglPaper structure.
+ *
+ */
+lglPaper *lgl_paper_dup (const lglPaper *orig)
+{
+ lglPaper *paper;
+
+ g_return_val_if_fail (orig, NULL);
+
+ paper = g_new0 (lglPaper,1);
+
+ paper->id = g_strdup (orig->id);
+ paper->name = g_strdup (orig->name);
+ paper->width = orig->width;
+ paper->height = orig->height;
+ paper->pwg_size = g_strdup (orig->pwg_size);
+
+ return paper;
+}
+
+
+/**
+ * lgl_paper_free:
+ * @paper: pointer to #lglPaper structure to be freed.
+ *
+ * Free all memory associated with an existing #lglPaper structure.
+ *
+ */
+void lgl_paper_free (lglPaper *paper)
+{
+
+ if ( paper != NULL ) {
+
+ g_free (paper->id);
+ paper->id = NULL;
+
+ g_free (paper->name);
+ paper->name = NULL;
+
+ g_free (paper->pwg_size);
+ paper->pwg_size = NULL;
+
+ g_free (paper);
+ }
+
+}
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
--- /dev/null
+/*
+ * lgl-paper.h
+ * Copyright (C) 2003-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LGL_PAPER_H__
+#define __LGL_PAPER_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+
+/*
+ * lglPaper structure
+ */
+typedef struct _lglPaper lglPaper;
+
+struct _lglPaper {
+ gchar *id; /* Unique ID of paper definition */
+ gchar *name; /* Localized name of paper */
+ gdouble width; /* Width (in points) */
+ gdouble height; /* Height (in points) */
+ gchar *pwg_size; /* PWG 5101.1-2002 size name */
+};
+
+
+/*
+ * Paper construction
+ */
+lglPaper *lgl_paper_new (gchar *id,
+ gchar *name,
+ gdouble width,
+ gdouble height,
+ gchar *pwg_size);
+
+lglPaper *lgl_paper_dup (const lglPaper *orig);
+
+void lgl_paper_free (lglPaper *paper);
+
+
+G_END_DECLS
+
+#endif /* __LGL_PAPER_H__ */
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
--- /dev/null
+/*
+ * lgl-str.c
+ * Copyright (C) 2007-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "lgl-str.h"
+
+#include <string.h>
+#include <math.h>
+
+#define FRAC_EPSILON 0.00005
+
+
+/*===========================================*/
+/* Private types */
+/*===========================================*/
+
+
+/*===========================================*/
+/* Private globals */
+/*===========================================*/
+
+
+/*===========================================*/
+/* Local function prototypes */
+/*===========================================*/
+
+static gchar *span_digits (gchar **p);
+static gchar *span_non_digits (gchar **p);
+
+/*===========================================*/
+/* Functions. */
+/*===========================================*/
+
+/**
+ * lgl_str_utf8_casecmp:
+ * @s1: string to compare with s2.
+ * @s2: string to compare with s1.
+ *
+ * Compare two UTF-8 strings, ignoring the case of characters.
+ *
+ * This function should be used only on strings that are known to be encoded
+ * in UTF-8 or a compatible UTF-8 subset.
+ *
+ * Returns: 0 if the strings match, a negative value if s1 < s2,
+ * or a positive value if s1 > s2.
+ *
+ */
+gint
+lgl_str_utf8_casecmp (const gchar *s1,
+ const gchar *s2)
+{
+ gchar *folded_s1;
+ gchar *folded_s2;
+ gint result;
+
+ folded_s1 = g_utf8_casefold (s1, -1);
+ folded_s2 = g_utf8_casefold (s2, -1);
+
+ result = g_utf8_collate (folded_s1, folded_s2);
+
+ g_free (folded_s1);
+ g_free (folded_s2);
+
+ return result;
+}
+
+
+/**
+ * lgl_str_part_name_cmp:
+ * @s1: string to compare with s2.
+ * @s2: string to compare with s1.
+ *
+ * Compare two UTF-8 strings representing part names or numbers. This function
+ * uses a natural sort order:
+ *
+ * - Ignores case.
+ *
+ * - Strings are divided into chunks (numeric and non-numeric)
+ *
+ * - Non-numeric chunks are compared character by character
+ *
+ * - Numerical chunks are compared numerically, so that "20" precedes "100".
+ *
+ * - Comparison of chunks is performed left to right until the first difference
+ * is encountered or all chunks evaluate as equal.
+ *
+ * This function should be used only on strings that are known to be encoded
+ * in UTF-8 or a compatible UTF-8 subset.
+ *
+ * Numeric chunks are converted to 64 bit unsigned integers for comparison,
+ * so the behaviour may be unpredictable for numeric chunks that exceed
+ * 18446744073709551615.
+ *
+ * Returns: 0 if the strings match, a negative value if s1 < s2,
+ * or a positive value if s1 > s2.
+ *
+ */
+gint
+lgl_str_part_name_cmp (const gchar *s1,
+ const gchar *s2)
+{
+ gchar *folded_s1, *p1, *chunk1;
+ gchar *folded_s2, *p2, *chunk2;
+ gboolean isnum1, isnum2;
+ guint64 n1, n2;
+ gboolean done;
+ gint result;
+
+ if ( s1 == s2 ) return 0;
+ if (s1 == NULL) return -1;
+ if (s2 == NULL) return 1;
+
+ folded_s1 = g_utf8_casefold (s1, -1);
+ folded_s2 = g_utf8_casefold (s2, -1);
+
+ result = 0;
+ done = FALSE;
+ p1 = folded_s1;
+ p2 = folded_s2;
+ while ( (result == 0) && !done )
+ {
+
+ if ( g_ascii_isdigit (*p1) )
+ {
+ chunk1 = span_digits (&p1);
+ isnum1 = TRUE;
+ }
+ else
+ {
+ chunk1 = span_non_digits (&p1);
+ isnum1 = FALSE;
+ }
+
+ if ( g_ascii_isdigit (*p2) )
+ {
+ chunk2 = span_digits (&p2);
+ isnum2 = TRUE;
+ }
+ else
+ {
+ chunk2 = span_non_digits (&p2);
+ isnum2 = FALSE;
+ }
+
+ if ( (strlen(chunk1) == 0) && (strlen(chunk2) == 0) )
+ {
+ /* Case 1: Both are empty. */
+ done = TRUE;
+ }
+ else if ( isnum1 && isnum2 )
+ {
+ /* Case 2: They both contain numbers */
+ n1 = g_ascii_strtoull (chunk1, NULL, 10);
+ n2 = g_ascii_strtoull (chunk2, NULL, 10);
+
+ if ( n1 < n2 ) result = -1;
+ if ( n1 > n2 ) result = 1;
+ }
+ else
+ {
+ /* Case 3: One or both do not contain numbers */
+ result = g_utf8_collate (chunk1, chunk2);
+ }
+
+ g_free (chunk1);
+ g_free (chunk2);
+ }
+
+ g_free (folded_s1);
+ g_free (folded_s2);
+
+ return result;
+}
+
+
+static gchar *
+span_digits (gchar **p)
+{
+ gchar *chunk = g_new0 (gchar, strlen (*p) + 1);
+ gint i;
+
+ for ( i = 0; **p && g_ascii_isdigit (**p); i++, *p = g_utf8_next_char(*p) )
+ {
+ chunk[i] = **p;
+ }
+
+ return chunk;
+}
+
+
+static gchar *
+span_non_digits (gchar **p)
+{
+ gchar *chunk = g_new0 (gchar, strlen (*p) + 1);
+ gint i;
+
+ for ( i = 0; **p && !g_ascii_isdigit (**p); i++, *p = g_utf8_next_char(*p) )
+ {
+ chunk[i] = **p;
+ }
+
+ return chunk;
+}
+
+
+/**
+ * lgl_str_format_fraction:
+ * @x: Floating point number to convert to fractional notation
+ *
+ * Create fractional representation of number, if possible. Uses UTF-8 superscripts and
+ * subscripts for numerator and denominator values respecively.
+ *
+ * Returns: UTF-8 string containing fractional representation of x.
+ */
+gchar *
+lgl_str_format_fraction (gdouble x)
+{
+ static gdouble denom[] = { 1., 2., 3., 4., 8., 16., 32., 0. };
+ static gchar *denom_string[] = { "1", "₂", "₃", "₄", "₈", "₁₆", "₃₂", NULL };
+ static gchar *num_string[] = { "⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹",
+ "¹⁰", "¹¹", "¹²", "¹³", "¹⁴", "¹⁵", "¹⁶", "¹⁷", "¹⁸", "¹⁹",
+ "²⁰", "²¹", "²²", "²³", "²⁴", "²⁵", "²⁶", "²⁷", "²⁸", "²⁹",
+ "³⁰", "³¹" };
+ gint i;
+ gdouble product, remainder;
+ gint n, d;
+
+ for ( i=0; denom[i] != 0.0; i++ ) {
+ product = x * denom[i];
+ remainder = fabs(product - ((gint)(product+0.5)));
+ if ( remainder < FRAC_EPSILON ) break;
+ }
+
+ if ( denom[i] == 0.0 ) {
+ /* None of our denominators work. */
+ return g_strdup_printf ("%.5g", x);
+ }
+ if ( denom[i] == 1.0 ) {
+ /* Simple integer. */
+ return g_strdup_printf ("%.0f", x);
+ }
+ n = (gint)( x * denom[i] + 0.5 );
+ d = (gint)denom[i];
+ if ( n > d ) {
+ return g_strdup_printf ("%d%s/%s", (n/d), num_string[n%d], denom_string[i]);
+ } else {
+ return g_strdup_printf ("%s/%s", num_string[n%d], denom_string[i]);
+ }
+}
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
--- /dev/null
+/*
+ * lgl-str.h
+ * Copyright (C) 2007-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LGL_STR_H__
+#define __LGL_STR_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+gint lgl_str_utf8_casecmp (const gchar *s1,
+ const gchar *s2);
+
+gint lgl_str_part_name_cmp (const gchar *s1,
+ const gchar *s2);
+
+gchar *lgl_str_format_fraction (gdouble x);
+
+G_END_DECLS
+
+
+#endif /* __LGL_STR_H__ */
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
--- /dev/null
+/*
+ * lgl-template.c
+ * Copyright (C) 2001-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "lgl-template.h"
+
+#include <glib/gi18n.h>
+#include <glib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <math.h>
+
+#include "libglabels-private.h"
+
+#include "lgl-db.h"
+#include "lgl-paper.h"
+
+/*===========================================*/
+/* Private macros and constants. */
+/*===========================================*/
+
+/* Allowed error when comparing dimensions. (0.5pts ~= .007in ~= .2mm) */
+#define EPSILON 0.5
+
+/*===========================================*/
+/* Private types */
+/*===========================================*/
+
+
+/*===========================================*/
+/* Private globals */
+/*===========================================*/
+
+
+/*===========================================*/
+/* Local function prototypes */
+/*===========================================*/
+
+static gint compare_origins (gconstpointer a,
+ gconstpointer b,
+ gpointer user_data);
+
+/*===========================================*/
+/* Functions. */
+/*===========================================*/
+
+/**
+ * lgl_template_new:
+ * @brand: Template brand
+ * @part: Template part name/number
+ * @description: Template descriptions
+ * @paper_id: Page size id
+ * @page_width: Page width in points, set to zero unless paper_id="Other"
+ * @page_height: Page height in points, set to zero unless paper_id="Other"
+ *
+ * Create a new template structure, with the given top-level attributes. The
+ * created template will have no initial categories, or frames associated with
+ * it. See lgl_template_add_category() and lgl_template_add_frame() to add
+ * these.
+ *
+ * Returns: pointer to a newly allocated #lglTemplate structure.
+ *
+ */
+lglTemplate *
+lgl_template_new (const gchar *brand,
+ const gchar *part,
+ const gchar *description,
+ const gchar *paper_id,
+ gdouble page_width,
+ gdouble page_height)
+{
+ lglTemplate *template;
+
+ template = g_new0 (lglTemplate,1);
+
+ template->brand = g_strdup (brand);
+ template->part = g_strdup (part);
+ template->description = g_strdup (description);
+ template->paper_id = g_strdup (paper_id);
+ template->page_width = page_width;
+ template->page_height = page_height;
+
+ return template;
+}
+
+
+/**
+ * lgl_template_new_from_equiv:
+ * @brand: Template brand
+ * @part: Template part name/number
+ * @equiv_part: Name of equivalent part to base template on
+ *
+ * Create a new template structure based on an existing template. The
+ * created template will be a duplicate of the original template, except with
+ * the new part name/number.
+ *
+ * Returns: pointer to a newly allocated #lglTemplate structure.
+ *
+ */
+lglTemplate *
+lgl_template_new_from_equiv (const gchar *brand,
+ const gchar *part,
+ const gchar *equiv_part)
+{
+ lglTemplate *template = NULL;
+
+ if ( lgl_db_does_template_exist (brand, equiv_part) )
+ {
+ template = lgl_db_lookup_template_from_brand_part (brand, equiv_part);
+
+ g_free (template->part);
+ g_free (template->equiv_part);
+
+ template->part = g_strdup (part);
+ template->equiv_part = g_strdup (equiv_part);
+ }
+ else
+ {
+ g_message ("Equivalent part (\"%s\") for \"%s\", not previously defined.",
+ equiv_part, part);
+ }
+
+ return template;
+}
+
+
+/**
+ * lgl_template_get_name:
+ * @template: Pointer to template structure to test
+ *
+ * This function returns the name of the given template. The name is the concetenation
+ * of the brand and part name/number.
+ *
+ * Returns: A pointer to a newly allocated name string. Should be freed with g_free().
+ *
+ */
+gchar *
+lgl_template_get_name (const lglTemplate *template)
+{
+ g_return_val_if_fail (template, NULL);
+
+ return g_strdup_printf ("%s %s", template->brand, template->part);
+}
+
+
+/**
+ * lgl_template_do_templates_match:
+ * @template1: Pointer to 1st template structure to test
+ * @template2: Pointer to 2nd template structure to test
+ *
+ * This function tests if the given templates match. This is a simple test that only tests
+ * the brand and part name/number. It does not test if they are actually identical.
+ *
+ * Returns: TRUE if the two templates match.
+ *
+ */
+gboolean
+lgl_template_do_templates_match (const lglTemplate *template1,
+ const lglTemplate *template2)
+{
+ g_return_val_if_fail (template1, FALSE);
+ g_return_val_if_fail (template2, FALSE);
+
+ return (UTF8_EQUAL (template1->brand, template2->brand) &&
+ UTF8_EQUAL (template1->part, template2->part));
+}
+
+
+/**
+ * lgl_template_does_brand_match:
+ * @template: Pointer to template structure to test
+ * @brand: Brand string
+ *
+ * This function tests if the brand of the template matches the given brand.
+ *
+ * Returns: TRUE if the template matches the given brand.
+ *
+ */
+gboolean
+lgl_template_does_brand_match (const lglTemplate *template,
+ const gchar *brand)
+{
+ g_return_val_if_fail (template, FALSE);
+
+ /* NULL matches everything. */
+ if (brand == NULL)
+ {
+ return TRUE;
+ }
+
+ return UTF8_EQUAL (template->brand, brand);
+}
+
+
+/**
+ * lgl_template_does_page_size_match:
+ * @template: Pointer to template structure to test
+ * @paper_id: Page size ID string
+ *
+ * This function tests if the page size of the template matches the given ID.
+ *
+ * Returns: TRUE if the template matches the given page size ID.
+ *
+ */
+gboolean
+lgl_template_does_page_size_match (const lglTemplate *template,
+ const gchar *paper_id)
+{
+ g_return_val_if_fail (template, FALSE);
+
+ /* NULL matches everything. */
+ if (paper_id == NULL)
+ {
+ return TRUE;
+ }
+
+ return ASCII_EQUAL(paper_id, template->paper_id);
+}
+
+
+/**
+ * lgl_template_does_category_match:
+ * @template: Pointer to template structure to test
+ * @category_id: Category ID string
+ *
+ * This function tests if the given template belongs to the given category ID.
+ *
+ * Returns: TRUE if the template matches the given category ID.
+ *
+ */
+gboolean
+lgl_template_does_category_match (const lglTemplate *template,
+ const gchar *category_id)
+{
+ GList *p;
+
+ g_return_val_if_fail (template, FALSE);
+
+ /* NULL matches everything. */
+ if (category_id == NULL)
+ {
+ return TRUE;
+ }
+
+ for ( p=template->category_ids; p != NULL; p=p->next )
+ {
+ if (ASCII_EQUAL(category_id, p->data))
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/**
+ * lgl_template_are_templates_identical:
+ * @template1: Pointer to 1st template structure to test
+ * @template2: Pointer to 2nd template structure to test
+ *
+ * This function tests if the given templates have identical size and layout properties.
+ *
+ * Returns: TRUE if the two templates are identical.
+ *
+ */
+gboolean
+lgl_template_are_templates_identical (const lglTemplate *template1,
+ const lglTemplate *template2)
+{
+ lglTemplateFrame *frame1;
+ lglTemplateFrame *frame2;
+ GList *p1;
+ GList *p2;
+ lglTemplateLayout *layout1;
+ lglTemplateLayout *layout2;
+ gboolean match_found;
+
+
+ if (!UTF8_EQUAL (template1->paper_id, template2->paper_id) ||
+ (template1->page_width != template2->page_width) ||
+ (template1->page_height != template2->page_height))
+ {
+ return FALSE;
+ }
+
+ frame1 = (lglTemplateFrame *)template1->frames->data;
+ frame2 = (lglTemplateFrame *)template2->frames->data;
+
+ if ( frame1->shape != frame2->shape )
+ {
+ return FALSE;
+ }
+
+ switch ( frame1->shape )
+ {
+
+ case LGL_TEMPLATE_FRAME_SHAPE_RECT:
+ if ( (fabs(frame1->rect.w - frame2->rect.w) > EPSILON) ||
+ (fabs(frame1->rect.h - frame2->rect.h) > EPSILON) )
+ {
+ return FALSE;
+ }
+ break;
+
+ case LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE:
+ if ( (fabs(frame1->ellipse.w - frame2->ellipse.w) > EPSILON) ||
+ (fabs(frame1->ellipse.h - frame2->ellipse.h) > EPSILON) )
+ {
+ return FALSE;
+ }
+ break;
+
+ case LGL_TEMPLATE_FRAME_SHAPE_ROUND:
+ if ( fabs(frame1->round.r - frame2->round.r) > EPSILON )
+ {
+ return FALSE;
+ }
+ break;
+
+ case LGL_TEMPLATE_FRAME_SHAPE_CD:
+ if ( (fabs(frame1->cd.r1 - frame2->cd.r1) > EPSILON) ||
+ (fabs(frame1->cd.r2 - frame2->cd.r2) > EPSILON) )
+ {
+ return FALSE;
+ }
+ }
+
+ for ( p1 = frame1->all.layouts; p1; p1 = p1->next )
+ {
+ layout1 = (lglTemplateLayout *)p1->data;
+
+ match_found = FALSE;
+ for ( p2 = frame2->all.layouts; p2 && !match_found; p2 = p2->next )
+ {
+ layout2 = (lglTemplateLayout *)p2->data;
+
+ if ( (layout1->nx == layout2->nx) &&
+ (layout1->ny == layout2->ny) &&
+ (fabs(layout1->x0 - layout2->x0) < EPSILON) &&
+ (fabs(layout1->y0 - layout2->y0) < EPSILON) &&
+ (fabs(layout1->dx - layout2->dx) < EPSILON) &&
+ (fabs(layout1->dy - layout2->dy) < EPSILON) )
+ {
+ match_found = TRUE;
+ }
+
+ }
+ if ( !match_found )
+ {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * lgl_template_add_frame:
+ * @template: Pointer to template structure
+ * @frame: Pointer to frame structure
+ *
+ * This function adds the given frame structure to the template. Once added,
+ * the frame structure belongs to the given template; do not attempt to free
+ * it.
+ *
+ * Note: Currently glabels only supports a single frame per template.
+ *
+ */
+void
+lgl_template_add_frame (lglTemplate *template,
+ lglTemplateFrame *frame)
+{
+ g_return_if_fail (template);
+ g_return_if_fail (frame);
+
+ template->frames = g_list_append (template->frames, frame);
+}
+
+
+/**
+ * lgl_template_add_category:
+ * @template: Pointer to template structure
+ * @category_id: Category ID string
+ *
+ * This function adds the given category ID to a templates category list.
+ *
+ */
+void
+lgl_template_add_category (lglTemplate *template,
+ const gchar *category_id)
+{
+ g_return_if_fail (template);
+ g_return_if_fail (category_id);
+
+ template->category_ids = g_list_append (template->category_ids,
+ g_strdup (category_id));
+}
+
+
+/**
+ * lgl_template_frame_rect_new:
+ * @id: ID of frame. (This should currently always be "0").
+ * @w: width of frame in points.
+ * @h: height of frame in points.
+ * @r: radius of rounded corners in points. (Should be 0 for square corners.)
+ * @x_waste: Amount of overprint to allow in the horizontal direction.
+ * @y_waste: Amount of overprint to allow in the vertical direction.
+ *
+ * This function creates a new template frame for a rectangular label or card.
+ *
+ * Returns: Pointer to newly allocated #lglTemplateFrame structure.
+ *
+ */
+lglTemplateFrame *
+lgl_template_frame_rect_new (const gchar *id,
+ gdouble w,
+ gdouble h,
+ gdouble r,
+ gdouble x_waste,
+ gdouble y_waste)
+{
+ lglTemplateFrame *frame;
+
+ frame = g_new0 (lglTemplateFrame, 1);
+
+ frame->shape = LGL_TEMPLATE_FRAME_SHAPE_RECT;
+ frame->rect.id = g_strdup (id);
+
+ frame->rect.w = w;
+ frame->rect.h = h;
+ frame->rect.r = r;
+ frame->rect.x_waste = x_waste;
+ frame->rect.y_waste = y_waste;
+
+ return frame;
+}
+
+
+/**
+ * lgl_template_frame_ellipse_new:
+ * @id: ID of frame. (This should currently always be "0").
+ * @w: width of frame in points.
+ * @h: height of frame in points.
+ * @waste: Amount of overprint to allow in points.
+ *
+ * This function creates a new template frame for an elliptical label or card.
+ *
+ * Returns: Pointer to newly allocated #lglTemplateFrame structure.
+ *
+ */
+lglTemplateFrame *
+lgl_template_frame_ellipse_new (const gchar *id,
+ gdouble w,
+ gdouble h,
+ gdouble waste)
+{
+ lglTemplateFrame *frame;
+
+ frame = g_new0 (lglTemplateFrame, 1);
+
+ frame->shape = LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE;
+ frame->ellipse.id = g_strdup (id);
+
+ frame->ellipse.w = w;
+ frame->ellipse.h = h;
+ frame->ellipse.waste = waste;
+
+ return frame;
+}
+
+
+/**
+ * lgl_template_frame_round_new:
+ * @id: ID of frame. (This should currently always be "0").
+ * @r: radius of label in points.
+ * @waste: Amount of overprint to allow.
+ *
+ * This function creates a new template frame for a round label.
+ *
+ * Returns: Pointer to newly allocated #lglTemplateFrame structure.
+ *
+ */
+lglTemplateFrame *
+lgl_template_frame_round_new (const gchar *id,
+ gdouble r,
+ gdouble waste)
+{
+ lglTemplateFrame *frame;
+
+ frame = g_new0 (lglTemplateFrame, 1);
+
+ frame->shape = LGL_TEMPLATE_FRAME_SHAPE_ROUND;
+ frame->round.id = g_strdup (id);
+
+ frame->round.r = r;
+ frame->round.waste = waste;
+
+ return frame;
+}
+
+
+/**
+ * lgl_template_frame_cd_new:
+ * @id: ID of frame. (This should currently always be "0").
+ * @r1: outer radius of label in points.
+ * @r2: radius of center hole in points.
+ * @w: clip width of frame in points for business card CDs. Should be 0 for no clipping.
+ * @h: clip height of frame in points for business card CDs. Should be 0 for no clipping.
+ * @waste: Amount of overprint to allow.
+ *
+ * This function creates a new template frame for a CD/DVD label.
+ *
+ * Returns: Pointer to newly allocated #lglTemplateFrame structure.
+ *
+ */
+lglTemplateFrame *
+lgl_template_frame_cd_new (const gchar *id,
+ gdouble r1,
+ gdouble r2,
+ gdouble w,
+ gdouble h,
+ gdouble waste)
+{
+ lglTemplateFrame *frame;
+
+ frame = g_new0 (lglTemplateFrame, 1);
+
+ frame->shape = LGL_TEMPLATE_FRAME_SHAPE_CD;
+ frame->cd.id = g_strdup (id);
+
+ frame->cd.r1 = r1;
+ frame->cd.r2 = r2;
+ frame->cd.w = w;
+ frame->cd.h = h;
+ frame->cd.waste = waste;
+
+ return frame;
+}
+
+
+/**
+ * lgl_template_frame_get_size:
+ * @frame: #lglTemplateFrame structure to query
+ * @w: pointer to location to receive width of frame
+ * @h: pointer to location to receive height of frame
+ *
+ * Get size (width and height) of given #lglTemplateFrame in points.
+ *
+ */
+void
+lgl_template_frame_get_size (const lglTemplateFrame *frame,
+ gdouble *w,
+ gdouble *h)
+{
+ g_return_if_fail (frame);
+
+ switch (frame->shape) {
+ case LGL_TEMPLATE_FRAME_SHAPE_RECT:
+ *w = frame->rect.w;
+ *h = frame->rect.h;
+ break;
+ case LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE:
+ *w = frame->ellipse.w;
+ *h = frame->ellipse.h;
+ break;
+ case LGL_TEMPLATE_FRAME_SHAPE_ROUND:
+ *w = 2.0 * frame->round.r;
+ *h = 2.0 * frame->round.r;
+ break;
+ case LGL_TEMPLATE_FRAME_SHAPE_CD:
+ if (frame->cd.w == 0.0) {
+ *w = 2.0 * frame->cd.r1;
+ } else {
+ *w = frame->cd.w;
+ }
+ if (frame->cd.h == 0.0) {
+ *h = 2.0 * frame->cd.r1;
+ } else {
+ *h = frame->cd.h;
+ }
+ break;
+ default:
+ *w = 0.0;
+ *h = 0.0;
+ break;
+ }
+}
+
+
+/**
+ * lgl_template_frame_get_n_labels:
+ * @frame: #lglTemplateFrame structure to query
+ *
+ * Get total number of labels per sheet corresponding to the given frame.
+ *
+ * Returns: number of labels per sheet.
+ *
+ */
+gint
+lgl_template_frame_get_n_labels (const lglTemplateFrame *frame)
+{
+ gint n_labels = 0;
+ GList *p;
+ lglTemplateLayout *layout;
+
+ g_return_val_if_fail (frame, 0);
+
+ for ( p=frame->all.layouts; p != NULL; p=p->next ) {
+ layout = (lglTemplateLayout *)p->data;
+
+ n_labels += layout->nx * layout->ny;
+ }
+
+ return n_labels;
+}
+
+
+/**
+ * lgl_template_frame_get_layout_description
+ * @frame: #lglTemplateFrame structure to query
+ *
+ * Get a description of the label layout including number of labels per sheet.
+ *
+ * Returns: a newly allocation description string.
+ *
+ */
+gchar *
+lgl_template_frame_get_layout_description (const lglTemplateFrame *frame)
+{
+ gint n_labels;
+ gchar *string;
+ lglTemplateLayout *layout;
+
+ n_labels = lgl_template_frame_get_n_labels (frame);
+
+ if ( frame->all.layouts && (frame->all.layouts->next == NULL) )
+ {
+ layout = (lglTemplateLayout *)frame->all.layouts->data;
+ /*
+ * Translators: 1st %d = number of labels across a page,
+ * 2nd %d = number of labels down a page,
+ * 3rd %d = total number of labels on a page (sheet).
+ */
+ string = g_strdup_printf (_("%d × %d (%d per sheet)"), layout->nx, layout->ny, n_labels);
+ }
+ else
+ {
+ /* Translators: %d is the total number of labels on a page (sheet). */
+ string = g_strdup_printf (_("%d per sheet"), n_labels);
+ }
+
+ return string;
+}
+
+
+/**
+ * lgl_template_frame_get_size_description
+ * @frame: #lglTemplateFrame structure to query
+ * @units: #lglUnits
+ *
+ * Get a description of the label size.
+ *
+ * Returns: a newly allocation description string.
+ *
+ */
+gchar *
+lgl_template_frame_get_size_description (const lglTemplateFrame *frame,
+ lglUnits units)
+{
+ const gchar *units_string;
+ gdouble units_per_point;
+ gchar *string = NULL;
+
+ units_string = lgl_units_get_name (units);
+ units_per_point = lgl_units_get_units_per_point (units);
+
+ switch (frame->shape) {
+ case LGL_TEMPLATE_FRAME_SHAPE_RECT:
+ if ( units == LGL_UNITS_INCH ) {
+ gchar *xstr, *ystr;
+
+ xstr = lgl_str_format_fraction (frame->rect.w*units_per_point);
+ ystr = lgl_str_format_fraction (frame->rect.h*units_per_point);
+ string = g_strdup_printf ("%s × %s %s",
+ xstr, ystr, units_string);
+ g_free (xstr);
+ g_free (ystr);
+ } else {
+ string = g_strdup_printf ("%.5g × %.5g %s",
+ frame->rect.w*units_per_point,
+ frame->rect.h*units_per_point,
+ units_string);
+ }
+ break;
+ case LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE:
+ if ( units == LGL_UNITS_INCH ) {
+ gchar *xstr, *ystr;
+
+ xstr = lgl_str_format_fraction (frame->ellipse.w*units_per_point);
+ ystr = lgl_str_format_fraction (frame->ellipse.h*units_per_point);
+ string = g_strdup_printf ("%s × %s %s",
+ xstr, ystr, units_string);
+ g_free (xstr);
+ g_free (ystr);
+ } else {
+ string = g_strdup_printf ("%.5g × %.5g %s",
+ frame->ellipse.w*units_per_point,
+ frame->ellipse.h*units_per_point,
+ units_string);
+ }
+ break;
+ case LGL_TEMPLATE_FRAME_SHAPE_ROUND:
+ if ( units == LGL_UNITS_INCH ) {
+ gchar *dstr;
+
+ dstr = lgl_str_format_fraction (2.0*frame->round.r*units_per_point);
+ string = g_strdup_printf ("%s %s %s",
+ dstr, units_string,
+ _("diameter"));
+ g_free (dstr);
+ } else {
+ string = g_strdup_printf ("%.5g %s %s",
+ 2.0*frame->round.r*units_per_point,
+ units_string,
+ _("diameter"));
+ }
+ break;
+ case LGL_TEMPLATE_FRAME_SHAPE_CD:
+ if ( units == LGL_UNITS_INCH ) {
+ gchar *dstr;
+
+ dstr = lgl_str_format_fraction (2.0*frame->cd.r1*units_per_point);
+ string = g_strdup_printf ("%s %s %s",
+ dstr, units_string,
+ _("diameter"));
+ g_free (dstr);
+ } else {
+ string = g_strdup_printf ("%.5g %s %s",
+ 2.0*frame->cd.r1*units_per_point,
+ units_string,
+ _("diameter"));
+ }
+ break;
+ default:
+ break;
+ }
+
+ return string;
+}
+
+
+/**
+ * lgl_template_frame_get_origins:
+ * @frame: #lglTemplateFrame structure to query
+ *
+ * Get an array of label origins for the given frame. These origins represent the
+ * upper left hand corner of each label on a page corresponding to the given frame.
+ * The origins will be ordered geometrically left to right and then top to bottom.
+ * The array should be freed using g_free().
+ *
+ * Returns: A newly allocated array of #lglTemplateOrigin structures.
+ *
+ */
+lglTemplateOrigin *
+lgl_template_frame_get_origins (const lglTemplateFrame *frame)
+{
+ gint i_label, n_labels, ix, iy;
+ lglTemplateOrigin *origins;
+ GList *p;
+ lglTemplateLayout *layout;
+
+ g_return_val_if_fail (frame, NULL);
+
+ n_labels = lgl_template_frame_get_n_labels (frame);
+ origins = g_new0 (lglTemplateOrigin, n_labels);
+
+ i_label = 0;
+ for ( p=frame->all.layouts; p != NULL; p=p->next ) {
+ layout = (lglTemplateLayout *)p->data;
+
+ for (iy = 0; iy < layout->ny; iy++) {
+ for (ix = 0; ix < layout->nx; ix++, i_label++) {
+ origins[i_label].x = ix*layout->dx + layout->x0;
+ origins[i_label].y = iy*layout->dy + layout->y0;
+ }
+ }
+ }
+
+ g_qsort_with_data (origins, n_labels, sizeof(lglTemplateOrigin),
+ compare_origins, NULL);
+
+ return origins;
+}
+
+
+/**
+ * lgl_template_frame_add_layout:
+ * @frame: Pointer to template frame to add layout to.
+ * @layout: Pointer to layout structure to add to frame.
+ *
+ * This function adds a layout structure to the given template frame.
+ *
+ */
+void
+lgl_template_frame_add_layout (lglTemplateFrame *frame,
+ lglTemplateLayout *layout)
+{
+ g_return_if_fail (frame);
+ g_return_if_fail (layout);
+
+ frame->all.layouts = g_list_append (frame->all.layouts, layout);
+}
+
+
+/**
+ * lgl_template_frame_add_markup:
+ * @frame: Pointer to template frame to add markup to.
+ * @markup: Pointer to markup structure to add to frame.
+ *
+ * This function adds a markup structure to the given template frame.
+ *
+ */
+void
+lgl_template_frame_add_markup (lglTemplateFrame *frame,
+ lglTemplateMarkup *markup)
+{
+ g_return_if_fail (frame);
+ g_return_if_fail (markup);
+
+ frame->all.markups = g_list_append (frame->all.markups, markup);
+}
+
+
+/**
+ * lgl_template_layout_new:
+ * @nx: Number of labels across.
+ * @ny: Number of labels down.
+ * @x0: X coordinate of the top-left corner of the top-left label in the layout in points.
+ * @y0: Y coordinate of the top-left corner of the top-left label in the layout in points.
+ * @dx: Horizontal pitch in points. This is the distance from left-edge to left-edge.
+ * @dy: Vertical pitch in points. This is the distance from top-edge to top-edge.
+ *
+ * This function creates a new layout structure with the given parameters.
+ *
+ * Returns: a newly allocated #lglTemplateLayout structure.
+ *
+ */
+lglTemplateLayout *
+lgl_template_layout_new (gint nx,
+ gint ny,
+ gdouble x0,
+ gdouble y0,
+ gdouble dx,
+ gdouble dy)
+{
+ lglTemplateLayout *layout;
+
+ layout = g_new0 (lglTemplateLayout, 1);
+
+ layout->nx = nx;
+ layout->ny = ny;
+ layout->x0 = x0;
+ layout->y0 = y0;
+ layout->dx = dx;
+ layout->dy = dy;
+
+ return layout;
+}
+
+
+/**
+ * lgl_template_markup_margin_new:
+ * @size: margin size in points.
+ *
+ * This function creates a new margin markup structure.
+ *
+ * Returns: a newly allocated #lglTemplateMarkup structure.
+ *
+ */
+lglTemplateMarkup *
+lgl_template_markup_margin_new (gdouble size)
+{
+ lglTemplateMarkup *markup;
+
+ markup = g_new0 (lglTemplateMarkup, 1);
+
+ markup->type = LGL_TEMPLATE_MARKUP_MARGIN;
+ markup->margin.size = size;
+
+ return markup;
+}
+
+
+/**
+ * lgl_template_markup_line_new:
+ * @x1: x coordinate of first endpoint.
+ * @y1: y coordinate of first endpoint.
+ * @x2: x coordinate of second endpoint.
+ * @y2: y coordinate of second endpoint.
+ *
+ * This function creates a new line markup structure.
+ *
+ * Returns: a newly allocated #lglTemplateMarkup structure.
+ *
+ */
+lglTemplateMarkup *
+lgl_template_markup_line_new (gdouble x1,
+ gdouble y1,
+ gdouble x2,
+ gdouble y2)
+{
+ lglTemplateMarkup *markup;
+
+ markup = g_new0 (lglTemplateMarkup, 1);
+
+ markup->type = LGL_TEMPLATE_MARKUP_LINE;
+ markup->line.x1 = x1;
+ markup->line.y1 = y1;
+ markup->line.x2 = x2;
+ markup->line.y2 = y2;
+
+ return markup;
+}
+
+
+/**
+ * lgl_template_markup_circle_new:
+ * @x0: x coordinate of center of circle.
+ * @y0: y coordinate of center of circle.
+ * @r: radius of circle.
+ *
+ * This function creates a new circle markup structure.
+ *
+ * Returns: a newly allocated #lglTemplateMarkup structure.
+ *
+ */
+lglTemplateMarkup *
+lgl_template_markup_circle_new (gdouble x0,
+ gdouble y0,
+ gdouble r)
+{
+ lglTemplateMarkup *markup;
+
+ markup = g_new0 (lglTemplateMarkup, 1);
+
+ markup->type = LGL_TEMPLATE_MARKUP_CIRCLE;
+ markup->circle.x0 = x0;
+ markup->circle.y0 = y0;
+ markup->circle.r = r;
+
+ return markup;
+}
+
+
+/**
+ * lgl_template_markup_rect_new:
+ * @x1: x coordinate of top-left corner of rectangle.
+ * @y1: y coordinate of top-left corner of rectangle.
+ * @w: width of rectangle.
+ * @h: height of rectangle.
+ * @r: radius of rounded corner.
+ *
+ * This function creates a new rectangle markup structure.
+ *
+ * Returns: a newly allocated #lglTemplateMarkup structure.
+ *
+ */
+lglTemplateMarkup *
+lgl_template_markup_rect_new (gdouble x1,
+ gdouble y1,
+ gdouble w,
+ gdouble h,
+ gdouble r)
+{
+ lglTemplateMarkup *markup;
+
+ markup = g_new0 (lglTemplateMarkup, 1);
+
+ markup->type = LGL_TEMPLATE_MARKUP_RECT;
+ markup->rect.x1 = x1;
+ markup->rect.y1 = y1;
+ markup->rect.w = w;
+ markup->rect.h = h;
+ markup->rect.r = r;
+
+ return markup;
+}
+
+
+/**
+ * lgl_template_markup_ellipse_new:
+ * @x1: x coordinate of top-left corner of ellipse.
+ * @y1: y coordinate of top-left corner of ellipse.
+ * @w: width of ellipse.
+ * @h: height of ellipse.
+ *
+ * This function creates a new ellipse markup structure.
+ *
+ * Returns: a newly allocated #lglTemplateMarkup structure.
+ *
+ */
+lglTemplateMarkup *
+lgl_template_markup_ellipse_new (gdouble x1,
+ gdouble y1,
+ gdouble w,
+ gdouble h)
+{
+ lglTemplateMarkup *markup;
+
+ markup = g_new0 (lglTemplateMarkup, 1);
+
+ markup->type = LGL_TEMPLATE_MARKUP_ELLIPSE;
+ markup->ellipse.x1 = x1;
+ markup->ellipse.y1 = y1;
+ markup->ellipse.w = w;
+ markup->ellipse.h = h;
+
+ return markup;
+}
+
+
+/**
+ * lgl_template_dup:
+ * @orig_template: Template to duplicate.
+ *
+ * This function duplicates a template structure.
+ *
+ * Returns: a newly allocated #lglTemplate structure.
+ *
+ */
+lglTemplate *
+lgl_template_dup (const lglTemplate *orig_template)
+{
+ lglTemplate *template;
+ GList *p;
+ lglTemplateFrame *frame;
+
+ g_return_val_if_fail (orig_template, NULL);
+
+ template = lgl_template_new (orig_template->brand,
+ orig_template->part,
+ orig_template->description,
+ orig_template->paper_id,
+ orig_template->page_width,
+ orig_template->page_height);
+
+ template->equiv_part = g_strdup (orig_template->equiv_part);
+ template->product_url = g_strdup (orig_template->product_url);
+
+
+ for ( p=orig_template->category_ids; p != NULL; p=p->next )
+ {
+ lgl_template_add_category (template, p->data);
+ }
+
+ for ( p=orig_template->frames; p != NULL; p=p->next )
+ {
+ frame = (lglTemplateFrame *)p->data;
+
+ lgl_template_add_frame (template, lgl_template_frame_dup (frame));
+ }
+
+ return template;
+}
+
+
+/**
+ * lgl_template_free:
+ * @template: Template to free.
+ *
+ * This function frees all memory associated with given template structure.
+ *
+ */
+void
+lgl_template_free (lglTemplate *template)
+{
+ GList *p;
+ lglTemplateFrame *frame;
+
+ if ( template != NULL ) {
+
+ g_free (template->brand);
+ template->brand = NULL;
+
+ g_free (template->part);
+ template->part = NULL;
+
+ g_free (template->description);
+ template->description = NULL;
+
+ g_free (template->paper_id);
+ template->paper_id = NULL;
+
+ for ( p=template->category_ids; p != NULL; p=p->next ) {
+
+ g_free (p->data);
+ p->data = NULL;
+
+ }
+ g_list_free (template->category_ids);
+ template->category_ids = NULL;
+
+ for ( p=template->frames; p != NULL; p=p->next ) {
+
+ frame = (lglTemplateFrame *)p->data;
+
+ lgl_template_frame_free (frame);
+ p->data = NULL;
+ }
+ g_list_free (template->frames);
+ template->frames = NULL;
+
+ g_free (template);
+
+ }
+
+}
+
+
+/**
+ * lgl_template_frame_dup:
+ * @orig_frame: Frame to duplicate.
+ *
+ * This function duplicates a template frame structure.
+ *
+ * Returns: a newly allocated #lglTemplateFrame structure.
+ *
+ */
+lglTemplateFrame *
+lgl_template_frame_dup (const lglTemplateFrame *orig_frame)
+{
+ lglTemplateFrame *frame;
+ GList *p;
+ lglTemplateLayout *layout;
+ lglTemplateMarkup *markup;
+
+ g_return_val_if_fail (orig_frame, NULL);
+
+ switch (orig_frame->shape) {
+
+ case LGL_TEMPLATE_FRAME_SHAPE_RECT:
+ frame =
+ lgl_template_frame_rect_new (orig_frame->all.id,
+ orig_frame->rect.w,
+ orig_frame->rect.h,
+ orig_frame->rect.r,
+ orig_frame->rect.x_waste,
+ orig_frame->rect.y_waste);
+ break;
+
+ case LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE:
+ frame =
+ lgl_template_frame_ellipse_new (orig_frame->all.id,
+ orig_frame->ellipse.w,
+ orig_frame->ellipse.h,
+ orig_frame->ellipse.waste);
+ break;
+
+ case LGL_TEMPLATE_FRAME_SHAPE_ROUND:
+ frame =
+ lgl_template_frame_round_new (orig_frame->all.id,
+ orig_frame->round.r,
+ orig_frame->round.waste);
+ break;
+
+ case LGL_TEMPLATE_FRAME_SHAPE_CD:
+ frame =
+ lgl_template_frame_cd_new (orig_frame->all.id,
+ orig_frame->cd.r1,
+ orig_frame->cd.r2,
+ orig_frame->cd.w,
+ orig_frame->cd.h,
+ orig_frame->cd.waste);
+ break;
+
+ default:
+ return NULL;
+ break;
+ }
+
+ for ( p=orig_frame->all.layouts; p != NULL; p=p->next ) {
+
+ layout = (lglTemplateLayout *)p->data;
+
+ lgl_template_frame_add_layout (frame, lgl_template_layout_dup (layout));
+ }
+
+ for ( p=orig_frame->all.markups; p != NULL; p=p->next ) {
+
+ markup = (lglTemplateMarkup *)p->data;
+
+ lgl_template_frame_add_markup (frame, lgl_template_markup_dup (markup));
+ }
+
+ return frame;
+}
+
+
+/**
+ * lgl_template_frame_free:
+ * @frame: Frame to free.
+ *
+ * This function frees all memory associated with given template frame structure.
+ *
+ */
+void
+lgl_template_frame_free (lglTemplateFrame *frame)
+{
+ GList *p;
+ lglTemplateLayout *layout;
+ lglTemplateMarkup *markup;
+
+ if ( frame != NULL ) {
+
+ g_free (frame->all.id);
+ frame->all.id = NULL;
+
+ for ( p=frame->all.layouts; p != NULL; p=p->next ) {
+
+ layout = (lglTemplateLayout *)p->data;
+
+ lgl_template_layout_free (layout);
+ p->data = NULL;
+ }
+ g_list_free (frame->all.layouts);
+ frame->all.layouts = NULL;
+
+ for ( p=frame->all.markups; p != NULL; p=p->next ) {
+
+ markup = (lglTemplateMarkup *)p->data;
+
+ lgl_template_markup_free (markup);
+ p->data = NULL;
+ }
+ g_list_free (frame->all.markups);
+ frame->all.markups = NULL;
+
+ g_free (frame);
+
+ }
+
+}
+
+
+/**
+ * lgl_template_layout_dup:
+ * @orig_layout: Layout to duplicate.
+ *
+ * This function duplicates a template layout structure.
+ *
+ * Returns: a newly allocated #lglTemplateLayout structure.
+ *
+ */
+lglTemplateLayout *
+lgl_template_layout_dup (const lglTemplateLayout *orig_layout)
+{
+ lglTemplateLayout *layout;
+
+ g_return_val_if_fail (orig_layout, NULL);
+
+ layout = g_new0 (lglTemplateLayout, 1);
+
+ /* copy contents */
+ *layout = *orig_layout;
+
+ return layout;
+}
+
+
+/**
+ * lgl_template_layout_free:
+ * @layout: Layout to free.
+ *
+ * This function frees all memory associated with given template layout structure.
+ *
+ */
+void
+lgl_template_layout_free (lglTemplateLayout *layout)
+{
+ g_free (layout);
+}
+
+
+/**
+ * lgl_template_markup_dup:
+ * @orig_markup: Markup to duplicate.
+ *
+ * This function duplicates a template markup structure.
+ *
+ * Returns: a newly allocated #lglTemplateMarkup structure.
+ *
+ */
+lglTemplateMarkup *
+lgl_template_markup_dup (const lglTemplateMarkup *orig_markup)
+{
+ lglTemplateMarkup *markup;
+
+ g_return_val_if_fail (orig_markup, NULL);
+
+ markup = g_new0 (lglTemplateMarkup, 1);
+
+ *markup = *orig_markup;
+
+ return markup;
+}
+
+
+/**
+ * lgl_template_markup_free:
+ * @markup: Markup to free.
+ *
+ * This function frees all memory associated with given template markup structure.
+ *
+ */
+void
+lgl_template_markup_free (lglTemplateMarkup *markup)
+{
+ g_free (markup);
+}
+
+
+static gint
+compare_origins (gconstpointer a,
+ gconstpointer b,
+ gpointer user_data)
+{
+ const lglTemplateOrigin *a_origin = a, *b_origin = b;
+
+ if ( a_origin->y < b_origin->y ) {
+ return -1;
+ } else if ( a_origin->y > b_origin->y ) {
+ return +1;
+ } else {
+ if ( a_origin->x < b_origin->x ) {
+ return -1;
+ } else if ( a_origin->x > b_origin->x ) {
+ return +1;
+ } else {
+ return 0; /* hopefully 2 labels won't have the same origin */
+ }
+ }
+}
+
+
+/**
+ * lgl_template_print:
+ * @template: template
+ *
+ * Print template details (for debugging purposes).
+ *
+ */
+void
+lgl_template_print (const lglTemplate *template)
+{
+ g_print ("---- %s( TEMPLATE=%p ) ----\n", __FUNCTION__, template);
+
+ g_print("brand=\"%s\", part=\"%s\", description=\"%s\"\n",
+ template->brand, template->part, template->description);
+
+ g_print("paper_id=\"%s\", page_width=%g, page_height=%g\n",
+ template->paper_id, template->page_width, template->page_height);
+
+ g_print ("\n");
+
+}
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
--- /dev/null
+/*
+ * lgl-template.h
+ * Copyright (C) 2001-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LGL_TEMPLATE_H__
+#define __LGL_TEMPLATE_H__
+
+#include <glib.h>
+#include "lgl-units.h"
+
+G_BEGIN_DECLS
+
+typedef struct _lglTemplate lglTemplate;
+
+typedef union _lglTemplateFrame lglTemplateFrame;
+typedef struct _lglTemplateFrameAll lglTemplateFrameAll;
+typedef struct _lglTemplateFrameRect lglTemplateFrameRect;
+typedef struct _lglTemplateFrameEllipse lglTemplateFrameEllipse;
+typedef struct _lglTemplateFrameRound lglTemplateFrameRound;
+typedef struct _lglTemplateFrameCD lglTemplateFrameCD;
+
+typedef struct _lglTemplateLayout lglTemplateLayout;
+
+typedef union _lglTemplateMarkup lglTemplateMarkup;
+typedef struct _lglTemplateMarkupMargin lglTemplateMarkupMargin;
+typedef struct _lglTemplateMarkupLine lglTemplateMarkupLine;
+typedef struct _lglTemplateMarkupCircle lglTemplateMarkupCircle;
+typedef struct _lglTemplateMarkupRect lglTemplateMarkupRect;
+typedef struct _lglTemplateMarkupEllipse lglTemplateMarkupEllipse;
+
+typedef struct _lglTemplateOrigin lglTemplateOrigin;
+
+/*
+ * Top-level Template Structure
+ */
+struct _lglTemplate {
+
+ gchar *brand;
+ gchar *part;
+ gchar *equiv_part;
+
+ gchar *description;
+ gchar *paper_id;
+ gdouble page_width;
+ gdouble page_height;
+
+ /* Meta information. */
+ gchar *product_url; /* URL to manufacturer's product website. */
+ GList *category_ids; /* List of (gchar *) category ids. */
+
+ /* List of (lglTemplateFrame *) label frame structures.
+ * Currently glabels only supports a single label frame per
+ * template. */
+ GList *frames;
+
+};
+
+
+/*
+ * Possible Frame Shapes
+ */
+typedef enum {
+ LGL_TEMPLATE_FRAME_SHAPE_RECT,
+ LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE,
+ LGL_TEMPLATE_FRAME_SHAPE_ROUND,
+ LGL_TEMPLATE_FRAME_SHAPE_CD,
+} lglTemplateFrameShape;
+
+
+/*
+ * Frame Structure
+ */
+struct _lglTemplateFrameAll {
+
+ /* Begin Common Fields */
+ lglTemplateFrameShape shape;
+
+ gchar *id; /* Id, currently always "0" */
+ GList *layouts; /* List of lglTemplateLayouts */
+ GList *markups; /* List of lglTemplateMarkups */
+ /* End Common Fields */
+};
+
+struct _lglTemplateFrameRect {
+
+ /* Begin Common Fields */
+ lglTemplateFrameShape shape; /* Always LGL_TEMPLATE_FRAME_SHAPE_RECT. */
+
+ gchar *id; /* Id, currently always "0" */
+ GList *layouts; /* List of lglTemplateLayouts */
+ GList *markups; /* List of lglTemplateMarkups */
+ /* End Common Fields */
+
+ gdouble w; /* Width */
+ gdouble h; /* Height */
+ gdouble r; /* Corner radius */
+ gdouble x_waste; /* Amount of horiz overprint allowed. */
+ gdouble y_waste; /* Amount of vert overprint allowed. */
+};
+
+struct _lglTemplateFrameEllipse {
+
+ /* Begin Common Fields */
+ lglTemplateFrameShape shape; /* Always LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE. */
+
+ gchar *id; /* Id, currently always "0" */
+ GList *layouts; /* List of lglTemplateLayouts */
+ GList *markups; /* List of lglTemplateMarkups */
+ /* End Common Fields */
+
+ gdouble w; /* Width */
+ gdouble h; /* Height */
+ gdouble waste; /* Amount of overprint allowed. */
+};
+
+struct _lglTemplateFrameRound {
+
+ /* Begin Common Fields */
+ lglTemplateFrameShape shape; /* Always LGL_TEMPLATE_FRAME_SHAPE_ROUND. */
+
+ gchar *id; /* Id, currently always "0" */
+ GList *layouts; /* List of lglTemplateLayouts */
+ GList *markups; /* List of lglTemplateMarkups */
+ /* End Common Fields */
+
+ gdouble r; /* Radius */
+ gdouble waste; /* Amount of overprint allowed. */
+};
+
+struct _lglTemplateFrameCD {
+
+ /* Begin Common Fields */
+ lglTemplateFrameShape shape; /* Always LGL_TEMPLATE_FRAME_SHAPE_CD. */
+
+ gchar *id; /* Id, currently always "0" */
+ GList *layouts; /* List of lglTemplateLayouts */
+ GList *markups; /* List of lglTemplateMarkups */
+ /* End Common Fields */
+
+ gdouble r1; /* Outer radius */
+ gdouble r2; /* Inner radius (hole) */
+ gdouble w; /* Clip width, business card CDs */
+ gdouble h; /* Clip height, business card CDs */
+ gdouble waste; /* Amount of overprint allowed. */
+};
+
+union _lglTemplateFrame{
+
+ lglTemplateFrameShape shape;
+
+ lglTemplateFrameAll all;
+ lglTemplateFrameRect rect;
+ lglTemplateFrameEllipse ellipse;
+ lglTemplateFrameRound round;
+ lglTemplateFrameCD cd;
+};
+
+
+/*
+ * Label Layout Structure
+ */
+struct _lglTemplateLayout {
+
+ gint nx; /* Number of labels across */
+ gint ny; /* Number of labels up and down */
+
+ gdouble x0; /* Left of grid from left edge of paper */
+ gdouble y0; /* Top of grid from top edge of paper */
+
+ gdouble dx; /* Horizontal pitch of grid */
+ gdouble dy; /* Vertical pitch of grid */
+
+};
+
+
+/*
+ * Possible Markup Types
+ */
+typedef enum {
+ LGL_TEMPLATE_MARKUP_MARGIN,
+ LGL_TEMPLATE_MARKUP_LINE,
+ LGL_TEMPLATE_MARKUP_CIRCLE,
+ LGL_TEMPLATE_MARKUP_RECT,
+ LGL_TEMPLATE_MARKUP_ELLIPSE,
+} lglTemplateMarkupType;
+
+
+/*
+ * Label Markup Structure (Helpful lines drawn in glabels to help locate objects)
+ */
+struct _lglTemplateMarkupMargin {
+
+ lglTemplateMarkupType type; /* Always LGL_TEMPLATE_MARKUP_MARGIN */
+
+ gdouble size; /* Margin size */
+};
+
+struct _lglTemplateMarkupLine {
+
+ lglTemplateMarkupType type; /* Always LGL_TEMPLATE_MARKUP_LINE */
+
+ gdouble x1, y1; /* 1st endpoint */
+ gdouble x2, y2; /* 2nd endpoint */
+};
+
+struct _lglTemplateMarkupCircle {
+
+ lglTemplateMarkupType type; /* Always LGL_TEMPLATE_MARKUP_CIRCLE */
+
+ gdouble x0, y0; /* Center of circle */
+ gdouble r; /* Radius of circle */
+};
+
+struct _lglTemplateMarkupRect {
+
+ lglTemplateMarkupType type; /* Always LGL_TEMPLATE_MARKUP_RECT */
+
+ gdouble x1, y1; /* Upper left corner */
+ gdouble w, h; /* Width and height. */
+ gdouble r; /* Radius of corners. */
+};
+
+struct _lglTemplateMarkupEllipse {
+
+ lglTemplateMarkupType type; /* Always LGL_TEMPLATE_MARKUP_ELLIPSE */
+
+ gdouble x1, y1; /* Upper left corner */
+ gdouble w, h; /* Width and height. */
+};
+
+union _lglTemplateMarkup {
+
+ lglTemplateMarkupType type;
+
+ lglTemplateMarkupMargin margin;
+ lglTemplateMarkupLine line;
+ lglTemplateMarkupCircle circle;
+ lglTemplateMarkupRect rect;
+ lglTemplateMarkupEllipse ellipse;
+};
+
+
+/*
+ * Origin coordinates
+ */
+struct _lglTemplateOrigin {
+
+ gdouble x, y; /* Label origin relative to upper
+ * upper left hand corner of paper */
+
+};
+
+
+
+/*
+ * Template query functions
+ */
+gchar *lgl_template_get_name (const lglTemplate *template);
+
+gboolean lgl_template_do_templates_match (const lglTemplate *template1,
+ const lglTemplate *template2);
+
+gboolean lgl_template_does_brand_match (const lglTemplate *template,
+ const gchar *brand);
+
+gboolean lgl_template_does_page_size_match (const lglTemplate *template,
+ const gchar *paper_id);
+
+gboolean lgl_template_does_category_match (const lglTemplate *template,
+ const gchar *category_id);
+
+gboolean lgl_template_are_templates_identical (const lglTemplate *template1,
+ const lglTemplate *template2);
+
+
+
+
+/*
+ * Frame query functions
+ */
+void lgl_template_frame_get_size (const lglTemplateFrame *frame,
+ gdouble *w,
+ gdouble *h);
+
+gint lgl_template_frame_get_n_labels (const lglTemplateFrame *frame);
+
+lglTemplateOrigin *lgl_template_frame_get_origins (const lglTemplateFrame *frame);
+
+gchar *lgl_template_frame_get_layout_description (const lglTemplateFrame *frame);
+
+gchar *lgl_template_frame_get_size_description (const lglTemplateFrame *frame,
+ lglUnits units);
+
+
+
+
+/*
+ * Template Construction
+ */
+lglTemplate *lgl_template_new (const gchar *brand,
+ const gchar *part,
+ const gchar *description,
+ const gchar *paper_id,
+ gdouble page_width,
+ gdouble page_height);
+
+lglTemplate *lgl_template_new_from_equiv (const gchar *brand,
+ const gchar *part,
+ const gchar *equiv_part);
+
+void lgl_template_add_category (lglTemplate *template,
+ const gchar *category_id);
+
+void lgl_template_add_frame (lglTemplate *template,
+ lglTemplateFrame *frame);
+
+lglTemplateFrame *lgl_template_frame_rect_new (const gchar *id,
+ gdouble w,
+ gdouble h,
+ gdouble r,
+ gdouble x_waste,
+ gdouble y_waste);
+
+lglTemplateFrame *lgl_template_frame_ellipse_new (const gchar *id,
+ gdouble w,
+ gdouble h,
+ gdouble waste);
+
+lglTemplateFrame *lgl_template_frame_round_new (const gchar *id,
+ gdouble r,
+ gdouble waste);
+
+lglTemplateFrame *lgl_template_frame_cd_new (const gchar *id,
+ gdouble r1,
+ gdouble r2,
+ gdouble w,
+ gdouble h,
+ gdouble waste);
+
+void lgl_template_frame_add_layout (lglTemplateFrame *frame,
+ lglTemplateLayout *layout);
+
+void lgl_template_frame_add_markup (lglTemplateFrame *frame,
+ lglTemplateMarkup *markup);
+
+lglTemplateLayout *lgl_template_layout_new (gint nx,
+ gint ny,
+ gdouble x0,
+ gdouble y0,
+ gdouble dx,
+ gdouble dy);
+
+lglTemplateMarkup *lgl_template_markup_margin_new (gdouble size);
+
+lglTemplateMarkup *lgl_template_markup_line_new (gdouble x1,
+ gdouble y1,
+ gdouble x2,
+ gdouble y2);
+
+lglTemplateMarkup *lgl_template_markup_circle_new (gdouble x0,
+ gdouble y0,
+ gdouble r);
+
+lglTemplateMarkup *lgl_template_markup_rect_new (gdouble x1,
+ gdouble y1,
+ gdouble w,
+ gdouble h,
+ gdouble r);
+
+lglTemplateMarkup *lgl_template_markup_ellipse_new (gdouble x1,
+ gdouble y1,
+ gdouble w,
+ gdouble h);
+
+lglTemplate *lgl_template_dup (const lglTemplate *orig_template);
+
+void lgl_template_free (lglTemplate *template);
+
+lglTemplateFrame *lgl_template_frame_dup (const lglTemplateFrame *orig_frame);
+void lgl_template_frame_free (lglTemplateFrame *frame);
+
+lglTemplateLayout *lgl_template_layout_dup (const lglTemplateLayout *orig_layout);
+void lgl_template_layout_free (lglTemplateLayout *layout);
+
+lglTemplateMarkup *lgl_template_markup_dup (const lglTemplateMarkup *orig_markup);
+void lgl_template_markup_free (lglTemplateMarkup *markup);
+
+
+/*
+ * Debugging functions.
+ */
+void lgl_template_print (const lglTemplate *template);
+
+
+G_END_DECLS
+
+#endif /* __LGL_TEMPLATE_H__ */
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
--- /dev/null
+/*
+ * lgl-units.c
+ * Copyright (C) 2003-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "lgl-units.h"
+
+#include <glib/gi18n.h>
+#include <glib.h>
+#include <string.h>
+
+#include "libglabels-private.h"
+
+
+/*========================================================*/
+/* Private macros and constants. */
+/*========================================================*/
+
+#define POINTS_PER_POINT 1.0 /* internal units are points. */
+#define POINTS_PER_INCH 72.0
+#define POINTS_PER_MM 2.83464566929
+#define POINTS_PER_CM (10.0*POINTS_PER_MM)
+#define POINTS_PER_PICA (1.0/12.0)
+
+
+/*========================================================*/
+/* Private types. */
+/*========================================================*/
+
+typedef struct {
+ gchar *id;
+ gchar *name;
+ gdouble points_per_unit;
+} UnitTableEntry;
+
+
+/*========================================================*/
+/* Private globals. */
+/*========================================================*/
+
+static UnitTableEntry unit_table[] = {
+
+ /* The ids are identical to the absolute length units supported in
+ the CSS2 Specification (Section 4.3.2) */
+
+ /* This table must be sorted exactly as the enumerations in lglUnits */
+
+ /* [LGL_UNITS_POINT] */ {"pt", N_("points"), POINTS_PER_POINT},
+ /* [LGL_UNITS_INCH] */ {"in", N_("inches"), POINTS_PER_INCH},
+ /* [LGL_UNITS_MM] */ {"mm", N_("mm"), POINTS_PER_MM},
+ /* [LGL_UNITS_CM] */ {"cm", N_("cm"), POINTS_PER_CM},
+ /* [LGL_UNITS_PICA] */ {"pc", N_("picas"), POINTS_PER_PICA},
+
+};
+
+
+
+/**
+ * lgl_units_get_id:
+ * @units: Units (#lglUnits)
+ *
+ * Return a unique ID string for the given units. This ID is how units
+ * are encoded in libglabels XML files and will remain constant across
+ * all locales. IDs are identical to the absolute length units supported
+ * in the CSS2 Specification (Section 4.3.2).
+ *
+ * Returns: ID string.
+ *
+ */
+const gchar *
+lgl_units_get_id (lglUnits units)
+{
+ if ( (units >= LGL_UNITS_FIRST) && (units <= LGL_UNITS_LAST) )
+ {
+ return unit_table[units].id;
+ }
+ else
+ {
+ /* Default to "pt", if invalid. */
+ return unit_table[LGL_UNITS_POINT].id;
+ }
+}
+
+
+/**
+ * lgl_units_from_id:
+ * @id: ID string
+ *
+ * Return the unique #lglUnits for the given ID string.
+ * This ID is how units are encoded in libglabels XML files and will remain
+ * constant across all locales. IDs are identical to the absolute length
+ * units supported in the CSS2 Specification (Section 4.3.2).
+ *
+ * Returns: units (#lglUnits).
+ *
+ */
+lglUnits
+lgl_units_from_id (const gchar *id)
+{
+ lglUnits units;
+
+ /* An empty or missing id defaults to points. */
+ if ( (id == NULL) || (strlen (id) == 0) )
+ {
+ return LGL_UNITS_POINT;
+ }
+
+ for ( units = LGL_UNITS_FIRST; units <= LGL_UNITS_LAST; units++) {
+ if (g_ascii_strcasecmp (id, unit_table[units].id) == 0) {
+ return units;
+ }
+ }
+
+ /* Try name as a fallback. (Will catch some legacy preferences.) */
+ for ( units = LGL_UNITS_FIRST; units <= LGL_UNITS_LAST; units++) {
+ if (g_ascii_strcasecmp (id, unit_table[units].name) == 0) {
+ return units;
+ }
+ }
+
+ /* For compatibility with old preferences. */
+ if (g_ascii_strcasecmp (id, "Millimeters") == 0) {
+ return LGL_UNITS_MM;
+ }
+
+ return LGL_UNITS_INVALID;
+}
+
+
+/**
+ * lgl_units_get_name:
+ * @units: Units (#lglUnits)
+ *
+ * Return a unique name string for the given units. This name is human
+ * readable and will be translated to the current locale.
+ *
+ * Returns: name string.
+ *
+ */
+const gchar *
+lgl_units_get_name (lglUnits units)
+{
+ if ( (units >= LGL_UNITS_FIRST) && (units <= LGL_UNITS_LAST) )
+ {
+ return gettext ((char *)unit_table[units].name);
+ }
+ else
+ {
+ /* Default to "points", if invalid. */
+ return gettext ((char *)unit_table[LGL_UNITS_POINT].name);
+ }
+}
+
+
+/**
+ * lgl_units_from_name:
+ * @name: NAME string
+ *
+ * Return the unique #lglUnits for the given name string. This name is
+ * human readable and is expected to be translated to the current locale.
+ *
+ * Returns: units (#lglUnits).
+ *
+ */
+lglUnits
+lgl_units_from_name (const gchar *name)
+{
+ lglUnits units;
+
+ for ( units = LGL_UNITS_FIRST; units <= LGL_UNITS_LAST; units++) {
+ if (g_ascii_strcasecmp (name, gettext ((char *)unit_table[units].name) ) == 0) {
+ return units;
+ }
+ }
+
+ return LGL_UNITS_INVALID;
+}
+
+
+/**
+ * lgl_units_get_points_per_unit:
+ * @units: Units (#lglUnits)
+ *
+ * Return a scale factor for the given units in points/unit.
+ *
+ * Returns: scale factor.
+ *
+ */
+gdouble
+lgl_units_get_points_per_unit (lglUnits units)
+{
+ if ( (units >= LGL_UNITS_FIRST) && (units <= LGL_UNITS_LAST) )
+ {
+ return unit_table[units].points_per_unit;
+ }
+ else
+ {
+ /* Default to "points", if invalid. */
+ return 1.0;
+ }
+}
+
+
+/**
+ * lgl_units_get_units_per_point:
+ * @units: Units (#lglUnits)
+ *
+ * Return a scale factor for the given units in units/point.
+ *
+ * Returns: scale factor.
+ *
+ */
+gdouble
+lgl_units_get_units_per_point (lglUnits units)
+{
+ if ( (units >= LGL_UNITS_FIRST) && (units <= LGL_UNITS_LAST) )
+ {
+ return 1.0 / unit_table[units].points_per_unit;
+ }
+ else
+ {
+ /* Default to "points", if invalid. */
+ return 1.0;
+ }
+}
+
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
--- /dev/null
+/*
+ * lgl-units.h
+ * Copyright (C) 2003-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LGL_UNITS_H__
+#define __LGL_UNITS_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+
+/*
+ * Units of distance
+ */
+typedef enum {
+ LGL_UNITS_POINT, /* encoded as "pt" */
+ LGL_UNITS_INCH, /* encoded as "in" */
+ LGL_UNITS_MM, /* encoded as "mm" */
+ LGL_UNITS_CM, /* encoded as "cm" */
+ LGL_UNITS_PICA, /* encoded as "pc" */
+
+ LGL_UNITS_FIRST = LGL_UNITS_POINT,
+ LGL_UNITS_LAST = LGL_UNITS_PICA,
+
+ LGL_UNITS_INVALID = -1,
+} lglUnits;
+
+
+const gchar *lgl_units_get_id (lglUnits units);
+lglUnits lgl_units_from_id (const gchar *id);
+
+const gchar *lgl_units_get_name (lglUnits units);
+lglUnits lgl_units_from_name (const gchar *name);
+
+gdouble lgl_units_get_points_per_unit (lglUnits units);
+gdouble lgl_units_get_units_per_point (lglUnits units);
+
+
+G_END_DECLS
+
+
+#endif /* __LGL_UNITS_H__ */
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
--- /dev/null
+/*
+ * lgl-vendor.c
+ * Copyright (C) 2003-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "lgl-vendor.h"
+
+#include <glib/gi18n.h>
+#include <glib.h>
+#include <string.h>
+
+#include "libglabels-private.h"
+
+/*===========================================*/
+/* Private types */
+/*===========================================*/
+
+
+/*===========================================*/
+/* Private globals */
+/*===========================================*/
+
+
+/*===========================================*/
+/* Local function prototypes */
+/*===========================================*/
+
+
+/*===========================================*/
+/* Functions. */
+/*===========================================*/
+
+/**
+ * lgl_vendor_new:
+ * @name: Localized name of vendor.
+ *
+ * Allocates and constructs a new #lglVendor structure.
+ *
+ * Returns: a pointer to a newly allocated #lglVendor structure.
+ *
+ */
+lglVendor *
+lgl_vendor_new (gchar *name)
+{
+ lglVendor *vendor;
+
+ vendor = g_new0 (lglVendor,1);
+
+ vendor->name = g_strdup (name);
+
+ return vendor;
+}
+
+
+/**
+ * lgl_vendor_dup:
+ * @orig: #lglVendor structure to be duplicated.
+ *
+ * Duplicates an existing #lglVendor structure.
+ *
+ * Returns: a pointer to a newly allocated #lglVendor structure.
+ *
+ */
+lglVendor *lgl_vendor_dup (const lglVendor *orig)
+{
+ lglVendor *vendor;
+
+ g_return_val_if_fail (orig, NULL);
+
+ vendor = g_new0 (lglVendor,1);
+
+ vendor->name = g_strdup (orig->name);
+ vendor->url = g_strdup (orig->url);
+
+ return vendor;
+}
+
+
+/**
+ * lgl_vendor_free:
+ * @vendor: pointer to #lglVendor structure to be freed.
+ *
+ * Free all memory associated with an existing #lglVendor structure.
+ *
+ */
+void lgl_vendor_free (lglVendor *vendor)
+{
+
+ if ( vendor != NULL ) {
+
+ g_free (vendor->name);
+ vendor->name = NULL;
+
+ g_free (vendor->url);
+ vendor->url = NULL;
+
+ g_free (vendor);
+ }
+
+}
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
--- /dev/null
+/*
+ * lgl-vendor.h
+ * Copyright (C) 2003-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LGL_VENDOR_H__
+#define __LGL_VENDOR_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+
+/*
+ * lglVendor structure
+ */
+typedef struct _lglVendor lglVendor;
+
+struct _lglVendor {
+ gchar *name; /* Vendor name */
+ gchar *url; /* Vendor URL */
+};
+
+
+/*
+ * Vendor construction
+ */
+lglVendor *lgl_vendor_new (gchar *name);
+
+lglVendor *lgl_vendor_dup (const lglVendor *orig);
+
+void lgl_vendor_free (lglVendor *vendor);
+
+
+G_END_DECLS
+
+#endif /* __LGL_VENDOR_H__ */
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
--- /dev/null
+/*
+ * lgl-xml-category.c
+ * Copyright (C) 2006-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "lgl-xml-category.h"
+
+#include <glib/gi18n.h>
+#include <glib.h>
+#include <string.h>
+#include <libintl.h>
+
+#include "libglabels-private.h"
+
+#include "lgl-xml.h"
+
+/*===========================================*/
+/* Private types */
+/*===========================================*/
+
+/*===========================================*/
+/* Private globals */
+/*===========================================*/
+
+/*===========================================*/
+/* Local function prototypes */
+/*===========================================*/
+
+
+/**
+ * lgl_xml_category_read_categories_from_file:
+ * @utf8_filename: Filename of categories file (name encoded as UTF-8)
+ *
+ * Read category definitions from a file.
+ *
+ * Returns: a list of #lglCategory structures.
+ *
+ */
+GList *
+lgl_xml_category_read_categories_from_file (gchar *utf8_filename)
+{
+ gchar *filename;
+ GList *categories;
+ xmlDocPtr categories_doc;
+
+ LIBXML_TEST_VERSION;
+
+ filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
+ if (!filename) {
+ g_message ("Utf8 filename conversion error");
+ return NULL;
+ }
+
+ categories_doc = xmlParseFile (filename);
+ if (!categories_doc) {
+ g_message ("\"%s\" is not a glabels category file (not XML)",
+ filename);
+ return NULL;
+ }
+
+ categories = lgl_xml_category_parse_categories_doc (categories_doc);
+
+ g_free (filename);
+ xmlFreeDoc (categories_doc);
+
+ return categories;
+}
+
+
+/**
+ * lgl_xml_category_parse_categories_doc:
+ * @categories_doc: libxml #xmlDocPtr tree, representing a categories
+ * definition file.
+ *
+ * Read category definitions from a libxml #xmlDocPtr tree.
+ *
+ * Returns: a list of #lglCategory structures.
+ *
+ */
+GList *
+lgl_xml_category_parse_categories_doc (xmlDocPtr categories_doc)
+{
+ GList *categories = NULL;
+ xmlNodePtr root, node;
+ lglCategory *category;
+
+ LIBXML_TEST_VERSION;
+
+ root = xmlDocGetRootElement (categories_doc);
+ if (!root || !root->name) {
+ g_message ("\"%s\" is not a glabels category file (no root node)",
+ categories_doc->name);
+ xmlFreeDoc (categories_doc);
+ return categories;
+ }
+ if (!lgl_xml_is_node (root, "Glabels-categories")) {
+ g_message ("\"%s\" is not a glabels category file (wrong root node)",
+ categories_doc->name);
+ xmlFreeDoc (categories_doc);
+ return categories;
+ }
+
+ for (node = root->xmlChildrenNode; node != NULL; node = node->next) {
+
+ if (lgl_xml_is_node (node, "Category")) {
+ category = lgl_xml_category_parse_category_node (node);
+ categories = g_list_append (categories, category);
+ } else {
+ if ( !xmlNodeIsText(node) ) {
+ if (!lgl_xml_is_node (node, "comment")) {
+ g_message ("bad node = \"%s\"",node->name);
+ }
+ }
+ }
+ }
+
+ return categories;
+}
+
+
+/**
+ * lgl_xml_category_parse_category_node:
+ * @category_node: libxml #xmlNodePtr category node from a #xmlDocPtr tree.
+ *
+ * Read a single category definition from a libxml #xmlNodePtr node.
+ *
+ * Returns: a pointer to a newly created #lglCategory structure.
+ *
+ */
+lglCategory *
+lgl_xml_category_parse_category_node (xmlNodePtr category_node)
+{
+ lglCategory *category;
+ gchar *id, *name;
+
+ LIBXML_TEST_VERSION;
+
+ id = lgl_xml_get_prop_string (category_node, "id", NULL);
+ name = lgl_xml_get_prop_i18n_string (category_node, "name", NULL);
+
+ category = lgl_category_new (id, name);
+
+ g_free (id);
+ g_free (name);
+
+ return category;
+}
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
--- /dev/null
+/*
+ * lgl-xml-category.h
+ * Copyright (C) 2006-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LGL_XML_CATEGORY_H__
+#define __LGL_XML_CATEGORY_H__
+
+#include <glib.h>
+#include <libxml/tree.h>
+
+#include "lgl-category.h"
+
+G_BEGIN_DECLS
+
+GList *lgl_xml_category_read_categories_from_file (gchar *utf8_filename);
+
+GList *lgl_xml_category_parse_categories_doc (xmlDocPtr categories_doc);
+
+lglCategory *lgl_xml_category_parse_category_node (xmlNodePtr category_node);
+
+
+G_END_DECLS
+
+#endif /* __LGL_XML_CATEGORY_H__ */
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
--- /dev/null
+/*
+ * lgl-xml-paper.c
+ * Copyright (C) 2003-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "lgl-xml-paper.h"
+
+#include <glib/gi18n.h>
+#include <glib.h>
+#include <string.h>
+#include <libintl.h>
+
+#include "libglabels-private.h"
+
+#include "lgl-xml.h"
+
+/*===========================================*/
+/* Private types */
+/*===========================================*/
+
+/*===========================================*/
+/* Private globals */
+/*===========================================*/
+
+/*===========================================*/
+/* Local function prototypes */
+/*===========================================*/
+
+
+/**
+ * lgl_xml_paper_read_papers_from_file:
+ * @utf8_filename: Filename of papers file (name encoded as UTF-8)
+ *
+ * Read paper definitions from a file.
+ *
+ * Returns: a list of #lglPaper structures.
+ *
+ */
+GList *
+lgl_xml_paper_read_papers_from_file (gchar *utf8_filename)
+{
+ gchar *filename;
+ GList *papers;
+ xmlDocPtr papers_doc;
+
+ LIBXML_TEST_VERSION;
+
+ filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
+ if (!filename) {
+ g_message ("Utf8 filename conversion error");
+ return NULL;
+ }
+
+ papers_doc = xmlParseFile (filename);
+ if (!papers_doc) {
+ g_message ("\"%s\" is not a glabels paper file (not XML)",
+ filename);
+ return NULL;
+ }
+
+ papers = lgl_xml_paper_parse_papers_doc (papers_doc);
+
+ g_free (filename);
+ xmlFreeDoc (papers_doc);
+
+ return papers;
+}
+
+
+/**
+ * lgl_xml_paper_parse_papers_doc:
+ * @papers_doc: libxml #xmlDocPtr tree, representing a papers definition file.
+ *
+ * Read paper definitions from a libxml #xmlDocPtr tree.
+ *
+ * Returns: a list of #lglPaper structures.
+ *
+ */
+GList *
+lgl_xml_paper_parse_papers_doc (xmlDocPtr papers_doc)
+{
+ GList *papers = NULL;
+ xmlNodePtr root, node;
+ lglPaper *paper;
+
+ LIBXML_TEST_VERSION;
+
+ root = xmlDocGetRootElement (papers_doc);
+ if (!root || !root->name) {
+ g_message ("\"%s\" is not a glabels paper file (no root node)",
+ papers_doc->name);
+ xmlFreeDoc (papers_doc);
+ return papers;
+ }
+ if (!lgl_xml_is_node (root, "Glabels-paper-sizes")) {
+ g_message ("\"%s\" is not a glabels paper file (wrong root node)",
+ papers_doc->name);
+ xmlFreeDoc (papers_doc);
+ return papers;
+ }
+
+ for (node = root->xmlChildrenNode; node != NULL; node = node->next) {
+
+ if (lgl_xml_is_node (node, "Paper-size")) {
+ paper = lgl_xml_paper_parse_paper_node (node);
+ papers = g_list_append (papers, paper);
+ } else {
+ if ( !xmlNodeIsText(node) ) {
+ if (!lgl_xml_is_node (node, "comment")) {
+ g_message ("bad node = \"%s\"",node->name);
+ }
+ }
+ }
+ }
+
+ return papers;
+}
+
+
+/**
+ * lgl_xml_paper_parse_paper_node:
+ * @paper_node: libxml #xmlNodePtr paper node from a #xmlDocPtr tree.
+ *
+ * Read a single paper definition from a libxml #xmlNodePtr node.
+ *
+ * Returns: a pointer to a newly created #lglPaper structure.
+ *
+ */
+lglPaper *
+lgl_xml_paper_parse_paper_node (xmlNodePtr paper_node)
+{
+ lglPaper *paper;
+ gchar *id, *name, *pwg_size;
+ gdouble width, height;
+
+ LIBXML_TEST_VERSION;
+
+ id = lgl_xml_get_prop_string (paper_node, "id", NULL);
+
+ name = lgl_xml_get_prop_i18n_string (paper_node, "name", NULL);
+
+ width = lgl_xml_get_prop_length (paper_node, "width", 0);
+ height = lgl_xml_get_prop_length (paper_node, "height", 0);
+
+ pwg_size = lgl_xml_get_prop_string (paper_node, "pwg_size", NULL);
+
+ paper = lgl_paper_new (id, name, width, height, pwg_size);
+
+ g_free (id);
+ g_free (name);
+ g_free (pwg_size);
+
+ return paper;
+}
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
--- /dev/null
+/*
+ * lgl-xml-paper.h
+ * Copyright (C) 2003-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LGL_XML_PAPER_H__
+#define __LGL_XML_PAPER_H__
+
+#include <glib.h>
+#include <libxml/tree.h>
+
+#include "lgl-paper.h"
+
+G_BEGIN_DECLS
+
+GList *lgl_xml_paper_read_papers_from_file (gchar *utf8_filename);
+
+GList *lgl_xml_paper_parse_papers_doc (xmlDocPtr papers_doc);
+
+lglPaper *lgl_xml_paper_parse_paper_node (xmlNodePtr paper_node);
+
+
+G_END_DECLS
+
+#endif /* __LGL_XML_PAPER_H__ */
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
--- /dev/null
+/*
+ * lgl-xml-template.c
+ * Copyright (C) 2001-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "lgl-xml-template.h"
+
+#include <glib/gi18n.h>
+#include <glib.h>
+#include <string.h>
+#include <libintl.h>
+
+#include "libglabels-private.h"
+
+#include "lgl-db.h"
+#include "lgl-xml.h"
+
+/*===========================================*/
+/* Private types */
+/*===========================================*/
+
+/*===========================================*/
+/* Private globals */
+/*===========================================*/
+
+/*===========================================*/
+/* Local function prototypes */
+/*===========================================*/
+static void xml_parse_meta_node (xmlNodePtr label_node,
+ lglTemplate *template);
+static void xml_parse_label_rectangle_node (xmlNodePtr label_node,
+ lglTemplate *template);
+static void xml_parse_label_ellipse_node (xmlNodePtr label_node,
+ lglTemplate *template);
+static void xml_parse_label_round_node (xmlNodePtr label_node,
+ lglTemplate *template);
+static void xml_parse_label_cd_node (xmlNodePtr label_node,
+ lglTemplate *template);
+static void xml_parse_layout_node (xmlNodePtr layout_node,
+ lglTemplateFrame *frame);
+static void xml_parse_markup_margin_node (xmlNodePtr markup_node,
+ lglTemplateFrame *frame);
+static void xml_parse_markup_line_node (xmlNodePtr markup_node,
+ lglTemplateFrame *frame);
+static void xml_parse_markup_circle_node (xmlNodePtr markup_node,
+ lglTemplateFrame *frame);
+static void xml_parse_markup_rect_node (xmlNodePtr markup_node,
+ lglTemplateFrame *frame);
+static void xml_parse_markup_ellipse_node (xmlNodePtr markup_node,
+ lglTemplateFrame *frame);
+static void xml_parse_alias_node (xmlNodePtr alias_node,
+ lglTemplate *template);
+
+static void xml_create_meta_node (const gchar *attr,
+ const gchar *value,
+ xmlNodePtr root,
+ const xmlNsPtr ns);
+static void xml_create_label_node (const lglTemplateFrame *frame,
+ xmlNodePtr root,
+ const xmlNsPtr ns);
+static void xml_create_layout_node (const lglTemplateLayout *layout,
+ xmlNodePtr root,
+ const xmlNsPtr ns);
+static void xml_create_markup_margin_node (const lglTemplateMarkup *margin,
+ xmlNodePtr root,
+ const xmlNsPtr ns);
+static void xml_create_markup_line_node (const lglTemplateMarkup *line,
+ xmlNodePtr root,
+ const xmlNsPtr ns);
+static void xml_create_markup_circle_node (const lglTemplateMarkup *circle,
+ xmlNodePtr root,
+ const xmlNsPtr ns);
+static void xml_create_markup_rect_node (const lglTemplateMarkup *circle,
+ xmlNodePtr root,
+ const xmlNsPtr ns);
+static void xml_create_markup_ellipse_node (const lglTemplateMarkup *circle,
+ xmlNodePtr root,
+ const xmlNsPtr ns);
+
+
+/**
+ * lgl_xml_template_read_templates_from_file:
+ * @utf8_filename: Filename of papers file (name encoded as UTF-8)
+ *
+ * Read glabels templates from template file.
+ *
+ */
+void
+lgl_xml_template_read_templates_from_file (const gchar *utf8_filename)
+{
+ gchar *filename;
+ xmlDocPtr templates_doc;
+
+ LIBXML_TEST_VERSION;
+
+ filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
+ if (!filename) {
+ g_message ("Utf8 filename conversion error");
+ return;
+ }
+
+ templates_doc = xmlParseFile (filename);
+ if (!templates_doc) {
+ g_message ("\"%s\" is not a glabels template file (not XML)",
+ filename);
+ return;
+ }
+
+ lgl_xml_template_parse_templates_doc (templates_doc);
+
+ g_free (filename);
+ xmlFreeDoc (templates_doc);
+}
+
+
+/**
+ * lgl_xml_template_parse_templates_doc:
+ * @templates_doc: libxml #xmlDocPtr tree, representing template file.
+ *
+ * Read glabels templates from a libxml #xmlDocPtr tree.
+ *
+ */
+void
+lgl_xml_template_parse_templates_doc (const xmlDocPtr templates_doc)
+{
+
+ xmlNodePtr root, node;
+ lglTemplate *template;
+
+ LIBXML_TEST_VERSION;
+
+ root = xmlDocGetRootElement (templates_doc);
+ if (!root || !root->name)
+ {
+ g_message ("\"%s\" is not a glabels template file (no root node)",
+ templates_doc->URL);
+ return;
+ }
+ if (!lgl_xml_is_node (root, "Glabels-templates"))
+ {
+ g_message ("\"%s\" is not a glabels template file (wrong root node)",
+ templates_doc->URL);
+ return;
+ }
+
+ for (node = root->xmlChildrenNode; node != NULL; node = node->next)
+ {
+
+ if (lgl_xml_is_node (node, "Template"))
+ {
+ template = lgl_xml_template_parse_template_node (node);
+ if (template)
+ {
+ _lgl_db_register_template_internal (template);
+ lgl_template_free (template);
+ }
+ }
+ else
+ {
+ if ( !xmlNodeIsText(node) )
+ {
+ if (!lgl_xml_is_node (node,"comment"))
+ {
+ g_message ("bad node = \"%s\"",node->name);
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ * lgl_xml_template_parse_template_node:
+ * @template_node: libxml #xmlNodePtr template node from a #xmlDocPtr tree.
+ *
+ * Read a single glabels template from a libxml #xmlNodePtr node.
+ *
+ * Returns: a pointer to a newly created #lglTemplate structure.
+ *
+ */
+lglTemplate *
+lgl_xml_template_parse_template_node (const xmlNodePtr template_node)
+{
+ gchar *brand;
+ gchar *part;
+ gchar *name;
+ gchar *equiv_part;
+ gchar *description;
+ gchar *paper_id;
+ gdouble page_width, page_height;
+ lglPaper *paper = NULL;
+ lglTemplate *template;
+ xmlNodePtr node;
+ gchar **v;
+ lglTemplateFrame *frame;
+
+
+ brand = lgl_xml_get_prop_string (template_node, "brand", NULL);
+ part = lgl_xml_get_prop_string (template_node, "part", NULL);
+ if (!brand || !part)
+ {
+ name = lgl_xml_get_prop_string (template_node, "name", NULL);
+ if (name)
+ {
+ v = g_strsplit (name, " ", 2);
+ brand = g_strdup (v[0]);
+ part = g_strchug (g_strdup (v[1]));
+ g_free (name);
+ g_strfreev (v);
+
+ }
+ else
+ {
+ g_message ("Missing name or brand/part attributes.");
+ }
+ }
+
+
+ equiv_part = lgl_xml_get_prop_string (template_node, "equiv", NULL);
+
+
+ description = lgl_xml_get_prop_i18n_string (template_node, "description", NULL);
+ paper_id = lgl_xml_get_prop_string (template_node, "size", NULL);
+
+ if (lgl_db_is_paper_id_other (paper_id)) {
+
+ page_width = lgl_xml_get_prop_length (template_node, "width", 0);
+ page_height = lgl_xml_get_prop_length (template_node, "height", 0);
+
+ } else {
+ paper = lgl_db_lookup_paper_from_id (paper_id);
+ if (paper == NULL) {
+ /* This should always be an id, but just in case a name
+ slips by! */
+ g_message ("Unknown page size id \"%s\", trying as name",
+ paper_id);
+ paper = lgl_db_lookup_paper_from_name (paper_id);
+ g_free (paper_id);
+ paper_id = g_strdup (paper->id);
+ }
+ if (paper != NULL) {
+ page_width = paper->width;
+ page_height = paper->height;
+ } else {
+ page_width = 612;
+ page_height = 792;
+ g_message ("Unknown page size id or name \"%s\"",
+ paper_id);
+ }
+ lgl_paper_free (paper);
+ paper = NULL;
+ }
+
+
+ if (!equiv_part)
+ {
+ template = lgl_template_new (brand, part, description,
+ paper_id, page_width, page_height);
+ }
+ else
+ {
+ template = lgl_template_new_from_equiv (brand, part, equiv_part);
+
+ if (!template)
+ {
+ g_message ("Forward references not supported.");
+ return NULL;
+ }
+ }
+
+
+ for (node = template_node->xmlChildrenNode; node != NULL;
+ node = node->next) {
+ if (lgl_xml_is_node (node, "Meta")) {
+ xml_parse_meta_node (node, template);
+ } else if (lgl_xml_is_node (node, "Label-rectangle")) {
+ xml_parse_label_rectangle_node (node, template);
+ } else if (lgl_xml_is_node (node, "Label-ellipse")) {
+ xml_parse_label_ellipse_node (node, template);
+ } else if (lgl_xml_is_node (node, "Label-round")) {
+ xml_parse_label_round_node (node, template);
+ } else if (lgl_xml_is_node (node, "Label-cd")) {
+ xml_parse_label_cd_node (node, template);
+ } else if (lgl_xml_is_node (node, "Alias")) {
+ xml_parse_alias_node (node, template);
+ } else {
+ if (!xmlNodeIsText (node)) {
+ if (!lgl_xml_is_node (node,"comment")) {
+ g_message ("bad node = \"%s\"",node->name);
+ }
+ }
+ }
+ }
+
+ g_free (brand);
+ g_free (part);
+ g_free (equiv_part);
+ g_free (description);
+ g_free (paper_id);
+
+ /*
+ * Create a default full-page frame, if a known frame type was not found.
+ */
+ if ( template->frames == NULL )
+ {
+ g_message ("%s %s: missing valid frame node", template->brand, template->part);
+ frame = lgl_template_frame_rect_new ("0", page_width, page_height, 0, 0, 0);
+ lgl_template_frame_add_layout (frame, lgl_template_layout_new (1, 1, 0, 0, 0, 0));
+ lgl_template_add_frame (template, frame);
+ }
+
+ /*
+ * Create a default 1x1 layout, if layout is missing.
+ */
+ frame = (lglTemplateFrame *)template->frames->data;
+ if ( frame->all.layouts == NULL )
+ {
+ g_message ("%s %s: missing layout node", template->brand, template->part);
+ lgl_template_frame_add_layout (frame, lgl_template_layout_new (1, 1, 0, 0, 0, 0));
+ }
+
+ return template;
+}
+
+/*--------------------------------------------------------------------------*/
+/* PRIVATE. Parse XML Template->Meta Node. */
+/*--------------------------------------------------------------------------*/
+static void
+xml_parse_meta_node (xmlNodePtr meta_node,
+ lglTemplate *template)
+{
+ gchar *product_url;
+ gchar *category;
+
+ product_url = lgl_xml_get_prop_string (meta_node, "product_url", NULL);
+ if ( product_url != NULL )
+ {
+ g_free (template->product_url);
+ template->product_url = product_url;
+ }
+
+ category = lgl_xml_get_prop_string (meta_node, "category", NULL);
+ if ( category != NULL )
+ {
+ lgl_template_add_category (template, category);
+ g_free (category);
+ }
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* PRIVATE. Parse XML Template->Label-rectangle Node. */
+/*--------------------------------------------------------------------------*/
+static void
+xml_parse_label_rectangle_node (xmlNodePtr label_node,
+ lglTemplate *template)
+{
+ gchar *id;
+ gchar *tmp;
+ gdouble x_waste, y_waste;
+ gdouble w, h, r;
+ lglTemplateFrame *frame;
+ xmlNodePtr node;
+
+ id = lgl_xml_get_prop_string (label_node, "id", NULL);
+
+ if ((tmp = lgl_xml_get_prop_string (label_node, "waste", NULL))) {
+ /* Handle single "waste" property. */
+ x_waste = y_waste = lgl_xml_get_prop_length (label_node, "waste", 0);
+ g_free (tmp);
+ } else {
+ x_waste = lgl_xml_get_prop_length (label_node, "x_waste", 0);
+ y_waste = lgl_xml_get_prop_length (label_node, "y_waste", 0);
+ }
+
+ w = lgl_xml_get_prop_length (label_node, "width", 0);
+ h = lgl_xml_get_prop_length (label_node, "height", 0);
+ r = lgl_xml_get_prop_length (label_node, "round", 0);
+
+ frame = lgl_template_frame_rect_new ((gchar *)id, w, h, r, x_waste, y_waste);
+ lgl_template_add_frame (template, frame);
+
+ for (node = label_node->xmlChildrenNode; node != NULL;
+ node = node->next) {
+ if (lgl_xml_is_node (node, "Layout")) {
+ xml_parse_layout_node (node, frame);
+ } else if (lgl_xml_is_node (node, "Markup-margin")) {
+ xml_parse_markup_margin_node (node, frame);
+ } else if (lgl_xml_is_node (node, "Markup-line")) {
+ xml_parse_markup_line_node (node, frame);
+ } else if (lgl_xml_is_node (node, "Markup-circle")) {
+ xml_parse_markup_circle_node (node, frame);
+ } else if (lgl_xml_is_node (node, "Markup-rect")) {
+ xml_parse_markup_rect_node (node, frame);
+ } else if (lgl_xml_is_node (node, "Markup-ellipse")) {
+ xml_parse_markup_ellipse_node (node, frame);
+ } else if (!xmlNodeIsText (node)) {
+ if (!lgl_xml_is_node (node, "comment")) {
+ g_message ("bad node = \"%s\"",node->name);
+ }
+ }
+ }
+
+ g_free (id);
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* PRIVATE. Parse XML Template->Label-ellipse Node. */
+/*--------------------------------------------------------------------------*/
+static void
+xml_parse_label_ellipse_node (xmlNodePtr label_node,
+ lglTemplate *template)
+{
+ gchar *id;
+ gdouble waste;
+ gdouble w, h;
+ lglTemplateFrame *frame;
+ xmlNodePtr node;
+
+ id = lgl_xml_get_prop_string (label_node, "id", NULL);
+
+ w = lgl_xml_get_prop_length (label_node, "width", 0);
+ h = lgl_xml_get_prop_length (label_node, "height", 0);
+ waste = lgl_xml_get_prop_length (label_node, "waste", 0);
+
+ frame = lgl_template_frame_ellipse_new ((gchar *)id, w, h, waste);
+ lgl_template_add_frame (template, frame);
+
+ for (node = label_node->xmlChildrenNode; node != NULL;
+ node = node->next) {
+ if (lgl_xml_is_node (node, "Layout")) {
+ xml_parse_layout_node (node, frame);
+ } else if (lgl_xml_is_node (node, "Markup-margin")) {
+ xml_parse_markup_margin_node (node, frame);
+ } else if (lgl_xml_is_node (node, "Markup-line")) {
+ xml_parse_markup_line_node (node, frame);
+ } else if (lgl_xml_is_node (node, "Markup-circle")) {
+ xml_parse_markup_circle_node (node, frame);
+ } else if (lgl_xml_is_node (node, "Markup-rect")) {
+ xml_parse_markup_rect_node (node, frame);
+ } else if (lgl_xml_is_node (node, "Markup-ellipse")) {
+ xml_parse_markup_ellipse_node (node, frame);
+ } else if (!xmlNodeIsText (node)) {
+ if (!lgl_xml_is_node (node, "comment")) {
+ g_message ("bad node = \"%s\"",node->name);
+ }
+ }
+ }
+
+ g_free (id);
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* PRIVATE. Parse XML Template->Label-round Node. */
+/*--------------------------------------------------------------------------*/
+static void
+xml_parse_label_round_node (xmlNodePtr label_node,
+ lglTemplate *template)
+{
+ gchar *id;
+ gdouble waste;
+ gdouble r;
+ lglTemplateFrame *frame;
+ xmlNodePtr node;
+
+ id = lgl_xml_get_prop_string (label_node, "id", NULL);
+ waste = lgl_xml_get_prop_length (label_node, "waste", 0);
+ r = lgl_xml_get_prop_length (label_node, "radius", 0);
+
+ frame = lgl_template_frame_round_new ((gchar *)id, r, waste);
+ lgl_template_add_frame (template, frame);
+
+ for (node = label_node->xmlChildrenNode; node != NULL;
+ node = node->next) {
+ if (lgl_xml_is_node (node, "Layout")) {
+ xml_parse_layout_node (node, frame);
+ } else if (lgl_xml_is_node (node, "Markup-margin")) {
+ xml_parse_markup_margin_node (node, frame);
+ } else if (lgl_xml_is_node (node, "Markup-line")) {
+ xml_parse_markup_line_node (node, frame);
+ } else if (lgl_xml_is_node (node, "Markup-circle")) {
+ xml_parse_markup_circle_node (node, frame);
+ } else if (lgl_xml_is_node (node, "Markup-rect")) {
+ xml_parse_markup_rect_node (node, frame);
+ } else if (lgl_xml_is_node (node, "Markup-ellipse")) {
+ xml_parse_markup_ellipse_node (node, frame);
+ } else if (!xmlNodeIsText (node)) {
+ if (!lgl_xml_is_node (node, "comment")) {
+ g_message ("bad node = \"%s\"",node->name);
+ }
+ }
+ }
+
+ g_free (id);
+}
+
+/*--------------------------------------------------------------------------*/
+/* PRIVATE. Parse XML Template->Label-cd Node. */
+/*--------------------------------------------------------------------------*/
+static void
+xml_parse_label_cd_node (xmlNodePtr label_node,
+ lglTemplate *template)
+{
+ gchar *id;
+ gdouble waste;
+ gdouble r1, r2, w, h;
+ lglTemplateFrame *frame;
+ xmlNodePtr node;
+
+ id = lgl_xml_get_prop_string (label_node, "id", NULL);
+ waste = lgl_xml_get_prop_length (label_node, "waste", 0);
+ r1 = lgl_xml_get_prop_length (label_node, "radius", 0);
+ r2 = lgl_xml_get_prop_length (label_node, "hole", 0);
+ w = lgl_xml_get_prop_length (label_node, "width", 0);
+ h = lgl_xml_get_prop_length (label_node, "height", 0);
+
+ frame = lgl_template_frame_cd_new ((gchar *)id, r1, r2, w, h, waste);
+ lgl_template_add_frame (template, frame);
+
+ for (node = label_node->xmlChildrenNode; node != NULL;
+ node = node->next) {
+ if (lgl_xml_is_node (node, "Layout")) {
+ xml_parse_layout_node (node, frame);
+ } else if (lgl_xml_is_node (node, "Markup-margin")) {
+ xml_parse_markup_margin_node (node, frame);
+ } else if (lgl_xml_is_node (node, "Markup-line")) {
+ xml_parse_markup_line_node (node, frame);
+ } else if (lgl_xml_is_node (node, "Markup-circle")) {
+ xml_parse_markup_circle_node (node, frame);
+ } else if (lgl_xml_is_node (node, "Markup-rect")) {
+ xml_parse_markup_rect_node (node, frame);
+ } else if (lgl_xml_is_node (node, "Markup-ellipse")) {
+ xml_parse_markup_ellipse_node (node, frame);
+ } else if (!xmlNodeIsText (node)) {
+ if (!lgl_xml_is_node (node, "comment")) {
+ g_message ("bad node = \"%s\"",node->name);
+ }
+ }
+ }
+
+ g_free (id);
+}
+
+/*--------------------------------------------------------------------------*/
+/* PRIVATE. Parse XML Template->Label->Layout Node. */
+/*--------------------------------------------------------------------------*/
+static void
+xml_parse_layout_node (xmlNodePtr layout_node,
+ lglTemplateFrame *frame)
+{
+ gint nx, ny;
+ gdouble x0, y0, dx, dy;
+ xmlNodePtr node;
+
+ nx = lgl_xml_get_prop_int (layout_node, "nx", 1);
+ ny = lgl_xml_get_prop_int (layout_node, "ny", 1);
+
+ x0 = lgl_xml_get_prop_length (layout_node, "x0", 0);
+ y0 = lgl_xml_get_prop_length (layout_node, "y0", 0);
+
+ dx = lgl_xml_get_prop_length (layout_node, "dx", 0);
+ dy = lgl_xml_get_prop_length (layout_node, "dy", 0);
+
+ lgl_template_frame_add_layout (frame, lgl_template_layout_new (nx, ny, x0, y0, dx, dy));
+
+ for (node = layout_node->xmlChildrenNode; node != NULL;
+ node = node->next) {
+ if (!xmlNodeIsText (node)) {
+ if (!lgl_xml_is_node (node, "comment")) {
+ g_message ("bad node = \"%s\"",node->name);
+ }
+ }
+ }
+
+}
+
+/*--------------------------------------------------------------------------*/
+/* PRIVATE. Parse XML Template->Label->Markup-margin Node. */
+/*--------------------------------------------------------------------------*/
+static void
+xml_parse_markup_margin_node (xmlNodePtr markup_node,
+ lglTemplateFrame *frame)
+{
+ gdouble size;
+ xmlNodePtr node;
+
+ size = lgl_xml_get_prop_length (markup_node, "size", 0);
+
+ lgl_template_frame_add_markup (frame, lgl_template_markup_margin_new (size));
+
+ for (node = markup_node->xmlChildrenNode; node != NULL;
+ node = node->next) {
+ if (!xmlNodeIsText (node)) {
+ if (!lgl_xml_is_node (node, "comment")) {
+ g_message ("bad node = \"%s\"",node->name);
+ }
+ }
+ }
+
+}
+
+/*--------------------------------------------------------------------------*/
+/* PRIVATE. Parse XML Template->Label->Markup-line Node. */
+/*--------------------------------------------------------------------------*/
+static void
+xml_parse_markup_line_node (xmlNodePtr markup_node,
+ lglTemplateFrame *frame)
+{
+ gdouble x1, y1, x2, y2;
+ xmlNodePtr node;
+
+ x1 = lgl_xml_get_prop_length (markup_node, "x1", 0);
+ y1 = lgl_xml_get_prop_length (markup_node, "y1", 0);
+ x2 = lgl_xml_get_prop_length (markup_node, "x2", 0);
+ y2 = lgl_xml_get_prop_length (markup_node, "y2", 0);
+
+ lgl_template_frame_add_markup (frame, lgl_template_markup_line_new (x1, y1, x2, y2));
+
+ for (node = markup_node->xmlChildrenNode; node != NULL;
+ node = node->next) {
+ if (!xmlNodeIsText (node)) {
+ if (!lgl_xml_is_node (node, "comment")) {
+ g_message ("bad node = \"%s\"",node->name);
+ }
+ }
+ }
+
+}
+
+/*--------------------------------------------------------------------------*/
+/* PRIVATE. Parse XML Template->Label->Markup-circle Node. */
+/*--------------------------------------------------------------------------*/
+static void
+xml_parse_markup_circle_node (xmlNodePtr markup_node,
+ lglTemplateFrame *frame)
+{
+ gdouble x0, y0, r;
+ xmlNodePtr node;
+
+ x0 = lgl_xml_get_prop_length (markup_node, "x0", 0);
+ y0 = lgl_xml_get_prop_length (markup_node, "y0", 0);
+ r = lgl_xml_get_prop_length (markup_node, "radius", 0);
+
+ lgl_template_frame_add_markup (frame, lgl_template_markup_circle_new (x0, y0, r));
+
+ for (node = markup_node->xmlChildrenNode; node != NULL;
+ node = node->next) {
+ if (!xmlNodeIsText (node)) {
+ if (!lgl_xml_is_node (node, "comment")) {
+ g_message ("bad node = \"%s\"",node->name);
+ }
+ }
+ }
+
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* PRIVATE. Parse XML Template->Label->Markup-rect Node. */
+/*--------------------------------------------------------------------------*/
+static void
+xml_parse_markup_rect_node (xmlNodePtr markup_node,
+ lglTemplateFrame *frame)
+{
+ gdouble x1, y1, w, h, r;
+ xmlNodePtr node;
+
+ x1 = lgl_xml_get_prop_length (markup_node, "x1", 0);
+ y1 = lgl_xml_get_prop_length (markup_node, "y1", 0);
+ w = lgl_xml_get_prop_length (markup_node, "w", 0);
+ h = lgl_xml_get_prop_length (markup_node, "h", 0);
+ r = lgl_xml_get_prop_length (markup_node, "r", 0);
+
+ lgl_template_frame_add_markup (frame, lgl_template_markup_rect_new (x1, y1, w, h, r));
+
+ for (node = markup_node->xmlChildrenNode; node != NULL;
+ node = node->next) {
+ if (!xmlNodeIsText (node)) {
+ if (!lgl_xml_is_node (node, "comment")) {
+ g_message ("bad node = \"%s\"",node->name);
+ }
+ }
+ }
+
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* PRIVATE. Parse XML Template->Label->Markup-ellipse Node. */
+/*--------------------------------------------------------------------------*/
+static void
+xml_parse_markup_ellipse_node (xmlNodePtr markup_node,
+ lglTemplateFrame *frame)
+{
+ gdouble x1, y1, w, h;
+ xmlNodePtr node;
+
+ x1 = lgl_xml_get_prop_length (markup_node, "x1", 0);
+ y1 = lgl_xml_get_prop_length (markup_node, "y1", 0);
+ w = lgl_xml_get_prop_length (markup_node, "w", 0);
+ h = lgl_xml_get_prop_length (markup_node, "h", 0);
+
+ lgl_template_frame_add_markup (frame, lgl_template_markup_ellipse_new (x1, y1, w, h));
+
+ for (node = markup_node->xmlChildrenNode; node != NULL;
+ node = node->next) {
+ if (!xmlNodeIsText (node)) {
+ if (!lgl_xml_is_node (node, "comment")) {
+ g_message ("bad node = \"%s\"",node->name);
+ }
+ }
+ }
+
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* PRIVATE. Parse deprecated XML Template->Alias Node. */
+/*--------------------------------------------------------------------------*/
+static void
+xml_parse_alias_node (xmlNodePtr alias_node,
+ lglTemplate *template)
+{
+ g_message ("Skipping deprecated \"Alias\" node.");
+}
+
+
+/**
+ * lgl_xml_template_write_templates_to_file:
+ * @templates: List of #lglTemplate structures
+ * @utf8_filename: Filename of templates file (name encoded as UTF-8)
+ *
+ * Write a list of #lglTemplate structures to a glabels XML template file.
+ *
+ * Returns: the number of bytes written or -1 in case of failure
+ *
+ */
+gint
+lgl_xml_template_write_templates_to_file (GList *templates,
+ const gchar *utf8_filename)
+{
+ xmlDocPtr doc;
+ xmlNsPtr ns;
+ gint bytes_written;
+ GList *p;
+ lglTemplate *template;
+ gchar *filename;
+
+ doc = xmlNewDoc ((xmlChar *)"1.0");
+ doc->xmlRootNode = xmlNewDocNode (doc, NULL, (xmlChar *)"Glabels-templates", NULL);
+
+ ns = xmlNewNs (doc->xmlRootNode, (xmlChar *)LGL_XML_NAME_SPACE, NULL);
+ xmlSetNs (doc->xmlRootNode, ns);
+
+ for (p=templates; p!=NULL; p=p->next) {
+ template = (lglTemplate *)p->data;
+ lgl_xml_template_create_template_node (template, doc->xmlRootNode, ns);
+ }
+
+ filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
+ if (!filename)
+ {
+ g_message ("Utf8 conversion error.");
+ return -1;
+ }
+ else
+ {
+ xmlSetDocCompressMode (doc, 0);
+ bytes_written = xmlSaveFormatFile (filename, doc, TRUE);
+ xmlFreeDoc (doc);
+ g_free (filename);
+ return bytes_written;
+ }
+
+}
+
+
+/**
+ * lgl_xml_template_write_template_to_file:
+ * @template: #lglTemplate structure to be written
+ * @utf8_filename: Filename of templates file (name encoded as UTF-8)
+ *
+ * Write a single #lglTemplate structures to a glabels XML template file.
+ *
+ * Returns: the number of bytes written or -1 in case of failure
+ *
+ */
+gint
+lgl_xml_template_write_template_to_file (const lglTemplate *template,
+ const gchar *utf8_filename)
+{
+ GList *templates = NULL;
+ gint bytes_written;
+
+ templates = g_list_append (templates, (gpointer)template);
+
+ bytes_written = lgl_xml_template_write_templates_to_file (templates, utf8_filename);
+
+ g_list_free (templates);
+
+ return bytes_written;
+}
+
+
+/**
+ * lgl_xml_template_create_template_node:
+ * @template: #lglTemplate structure to be written
+ * @root: parent node to receive new child node
+ * @ns: a libxml #xmlNsPtr
+ *
+ * Add a single #lglTemplate child node to given #xmlNodePtr.
+ *
+ */
+void
+lgl_xml_template_create_template_node (const lglTemplate *template,
+ xmlNodePtr root,
+ const xmlNsPtr ns)
+{
+ xmlNodePtr node;
+ GList *p;
+ lglTemplateFrame *frame;
+
+ node = xmlNewChild (root, ns, (xmlChar *)"Template", NULL);
+
+ lgl_xml_set_prop_string (node, "brand", template->brand);
+ lgl_xml_set_prop_string (node, "part", template->part);
+
+ lgl_xml_set_prop_string (node, "size", template->paper_id);
+ if (xmlStrEqual ((xmlChar *)template->paper_id, (xmlChar *)"Other"))
+ {
+
+ lgl_xml_set_prop_length (node, "width", template->page_width);
+ lgl_xml_set_prop_length (node, "height", template->page_height);
+
+ }
+
+ lgl_xml_set_prop_string (node, "description", template->description);
+
+ xml_create_meta_node ("product_url", template->product_url, node, ns );
+ for ( p=template->category_ids; p != NULL; p=p->next )
+ {
+ xml_create_meta_node ( "category", p->data, node, ns );
+ }
+ for ( p=template->frames; p != NULL; p=p->next )
+ {
+ frame = (lglTemplateFrame *)p->data;
+ xml_create_label_node (frame, node, ns);
+ }
+
+}
+
+/*--------------------------------------------------------------------------*/
+/* PRIVATE. Add XML Template->Meta Node with category. */
+/*--------------------------------------------------------------------------*/
+static void
+xml_create_meta_node (const gchar *attr,
+ const gchar *value,
+ xmlNodePtr root,
+ const xmlNsPtr ns)
+{
+ xmlNodePtr node;
+
+ if ( value != NULL )
+ {
+ node = xmlNewChild (root, ns, (xmlChar *)"Meta", NULL);
+ lgl_xml_set_prop_string (node, attr, value);
+ }
+
+}
+
+/*--------------------------------------------------------------------------*/
+/* PRIVATE. Add XML Template->Label Node. */
+/*--------------------------------------------------------------------------*/
+static void
+xml_create_label_node (const lglTemplateFrame *frame,
+ xmlNodePtr root,
+ const xmlNsPtr ns)
+{
+ xmlNodePtr node;
+ GList *p;
+ lglTemplateMarkup *markup;
+ lglTemplateLayout *layout;
+
+ switch (frame->shape) {
+
+ case LGL_TEMPLATE_FRAME_SHAPE_RECT:
+ node = xmlNewChild(root, ns, (xmlChar *)"Label-rectangle", NULL);
+ lgl_xml_set_prop_string (node, "id", frame->all.id);
+ lgl_xml_set_prop_length (node, "width", frame->rect.w);
+ lgl_xml_set_prop_length (node, "height", frame->rect.h);
+ lgl_xml_set_prop_length (node, "round", frame->rect.r);
+ lgl_xml_set_prop_length (node, "x_waste", frame->rect.x_waste);
+ lgl_xml_set_prop_length (node, "y_waste", frame->rect.y_waste);
+ break;
+
+ case LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE:
+ node = xmlNewChild(root, ns, (xmlChar *)"Label-ellipse", NULL);
+ lgl_xml_set_prop_string (node, "id", frame->all.id);
+ lgl_xml_set_prop_length (node, "width", frame->ellipse.w);
+ lgl_xml_set_prop_length (node, "height", frame->ellipse.h);
+ lgl_xml_set_prop_length (node, "waste", frame->ellipse.waste);
+ break;
+
+ case LGL_TEMPLATE_FRAME_SHAPE_ROUND:
+ node = xmlNewChild(root, ns, (xmlChar *)"Label-round", NULL);
+ lgl_xml_set_prop_string (node, "id", frame->all.id);
+ lgl_xml_set_prop_length (node, "radius", frame->round.r);
+ lgl_xml_set_prop_length (node, "waste", frame->round.waste);
+ break;
+
+ case LGL_TEMPLATE_FRAME_SHAPE_CD:
+ node = xmlNewChild(root, ns, (xmlChar *)"Label-cd", NULL);
+ lgl_xml_set_prop_string (node, "id", frame->all.id);
+ lgl_xml_set_prop_length (node, "radius", frame->cd.r1);
+ lgl_xml_set_prop_length (node, "hole", frame->cd.r2);
+ if (frame->cd.w != 0.0) {
+ lgl_xml_set_prop_length (node, "width", frame->cd.w);
+ }
+ if (frame->cd.h != 0.0) {
+ lgl_xml_set_prop_length (node, "height", frame->cd.h);
+ }
+ lgl_xml_set_prop_length (node, "waste", frame->cd.waste);
+ break;
+
+ default:
+ g_message ("Unknown label style");
+ return;
+ break;
+
+ }
+
+ for ( p=frame->all.markups; p != NULL; p=p->next ) {
+ markup = (lglTemplateMarkup *)p->data;
+ switch (markup->type) {
+ case LGL_TEMPLATE_MARKUP_MARGIN:
+ xml_create_markup_margin_node (markup, node, ns);
+ break;
+ case LGL_TEMPLATE_MARKUP_LINE:
+ xml_create_markup_line_node (markup, node, ns);
+ break;
+ case LGL_TEMPLATE_MARKUP_CIRCLE:
+ xml_create_markup_circle_node (markup, node, ns);
+ break;
+ case LGL_TEMPLATE_MARKUP_RECT:
+ xml_create_markup_rect_node (markup, node, ns);
+ break;
+ case LGL_TEMPLATE_MARKUP_ELLIPSE:
+ xml_create_markup_ellipse_node (markup, node, ns);
+ break;
+ default:
+ g_message ("Unknown markup type");
+ break;
+ }
+ }
+
+ for ( p=frame->all.layouts; p != NULL; p=p->next ) {
+ layout = (lglTemplateLayout *)p->data;
+ xml_create_layout_node (layout, node, ns);
+ }
+
+}
+
+/*--------------------------------------------------------------------------*/
+/* PRIVATE. Add XML Template->Label->Layout Node. */
+/*--------------------------------------------------------------------------*/
+static void
+xml_create_layout_node (const lglTemplateLayout *layout,
+ xmlNodePtr root,
+ const xmlNsPtr ns)
+{
+ xmlNodePtr node;
+
+ node = xmlNewChild(root, ns, (xmlChar *)"Layout", NULL);
+ lgl_xml_set_prop_int (node, "nx", layout->nx);
+ lgl_xml_set_prop_int (node, "ny", layout->ny);
+ lgl_xml_set_prop_length (node, "x0", layout->x0);
+ lgl_xml_set_prop_length (node, "y0", layout->y0);
+ lgl_xml_set_prop_length (node, "dx", layout->dx);
+ lgl_xml_set_prop_length (node, "dy", layout->dy);
+
+}
+
+/*--------------------------------------------------------------------------*/
+/* PRIVATE. Add XML Template->Label->Markup-margin Node. */
+/*--------------------------------------------------------------------------*/
+static void
+xml_create_markup_margin_node (const lglTemplateMarkup *markup,
+ xmlNodePtr root,
+ const xmlNsPtr ns)
+{
+ xmlNodePtr node;
+
+ node = xmlNewChild(root, ns, (xmlChar *)"Markup-margin", NULL);
+
+ lgl_xml_set_prop_length (node, "size", markup->margin.size);
+
+}
+
+/*--------------------------------------------------------------------------*/
+/* PRIVATE. Add XML Template->Label->Markup-line Node. */
+/*--------------------------------------------------------------------------*/
+static void
+xml_create_markup_line_node (const lglTemplateMarkup *markup,
+ xmlNodePtr root,
+ const xmlNsPtr ns)
+{
+ xmlNodePtr node;
+
+ node = xmlNewChild(root, ns, (xmlChar *)"Markup-line", NULL);
+
+ lgl_xml_set_prop_length (node, "x1", markup->line.x1);
+ lgl_xml_set_prop_length (node, "y1", markup->line.y1);
+ lgl_xml_set_prop_length (node, "x2", markup->line.x2);
+ lgl_xml_set_prop_length (node, "y2", markup->line.y2);
+
+}
+
+/*--------------------------------------------------------------------------*/
+/* PRIVATE. Add XML Template->Label->Markup-circle Node. */
+/*--------------------------------------------------------------------------*/
+static void
+xml_create_markup_circle_node (const lglTemplateMarkup *markup,
+ xmlNodePtr root,
+ const xmlNsPtr ns)
+{
+ xmlNodePtr node;
+
+ node = xmlNewChild(root, ns, (xmlChar *)"Markup-circle", NULL);
+
+ lgl_xml_set_prop_length (node, "x0", markup->circle.x0);
+ lgl_xml_set_prop_length (node, "y0", markup->circle.y0);
+ lgl_xml_set_prop_length (node, "radius", markup->circle.r);
+
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* PRIVATE. Add XML Template->Label->Markup-rect Node. */
+/*--------------------------------------------------------------------------*/
+static void
+xml_create_markup_rect_node (const lglTemplateMarkup *markup,
+ xmlNodePtr root,
+ const xmlNsPtr ns)
+{
+ xmlNodePtr node;
+
+ node = xmlNewChild(root, ns, (xmlChar *)"Markup-rect", NULL);
+
+ lgl_xml_set_prop_length (node, "x1", markup->rect.x1);
+ lgl_xml_set_prop_length (node, "y1", markup->rect.y1);
+ lgl_xml_set_prop_length (node, "w", markup->rect.w);
+ lgl_xml_set_prop_length (node, "h", markup->rect.h);
+ lgl_xml_set_prop_length (node, "r", markup->rect.r);
+
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* PRIVATE. Add XML Template->Label->Markup-ellipse Node. */
+/*--------------------------------------------------------------------------*/
+static void
+xml_create_markup_ellipse_node (const lglTemplateMarkup *markup,
+ xmlNodePtr root,
+ const xmlNsPtr ns)
+{
+ xmlNodePtr node;
+
+ node = xmlNewChild(root, ns, (xmlChar *)"Markup-ellipse", NULL);
+
+ lgl_xml_set_prop_length (node, "x1", markup->ellipse.x1);
+ lgl_xml_set_prop_length (node, "y1", markup->ellipse.y1);
+ lgl_xml_set_prop_length (node, "w", markup->ellipse.w);
+ lgl_xml_set_prop_length (node, "h", markup->ellipse.h);
+
+}
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
--- /dev/null
+/*
+ * lgl-xml-template.h
+ * Copyright (C) 2001-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LGL_XML_TEMPLATE_H__
+#define __LGL_XML_TEMPLATE_H__
+
+#include <glib.h>
+#include <libxml/tree.h>
+
+#include "lgl-template.h"
+
+G_BEGIN_DECLS
+
+void lgl_xml_template_read_templates_from_file (const gchar *utf8_filename);
+
+void lgl_xml_template_parse_templates_doc (const xmlDocPtr templates_doc);
+
+lglTemplate *lgl_xml_template_parse_template_node (const xmlNodePtr template_node);
+
+
+gint lgl_xml_template_write_templates_to_file (GList *templates,
+ const gchar *utf8_filename);
+
+gint lgl_xml_template_write_template_to_file (const lglTemplate *template,
+ const gchar *utf8_filename);
+
+void lgl_xml_template_create_template_node (const lglTemplate *template,
+ xmlNodePtr root,
+ const xmlNsPtr ns);
+
+G_END_DECLS
+
+#endif /* __LGL_XML_TEMPLATE_H__ */
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
--- /dev/null
+/*
+ * lgl-xml-vendor.c
+ * Copyright (C) 2003-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "lgl-xml-vendor.h"
+
+#include <glib/gi18n.h>
+#include <glib.h>
+#include <string.h>
+#include <libintl.h>
+
+#include "libglabels-private.h"
+
+#include "lgl-xml.h"
+
+/*===========================================*/
+/* Private types */
+/*===========================================*/
+
+/*===========================================*/
+/* Private globals */
+/*===========================================*/
+
+/*===========================================*/
+/* Local function prototypes */
+/*===========================================*/
+
+
+/**
+ * lgl_xml_vendor_read_vendors_from_file:
+ * @utf8_filename: Filename of vendors file (name encoded as UTF-8)
+ *
+ * Read vendor definitions from a file.
+ *
+ * Returns: a list of #lglVendor structures.
+ *
+ */
+GList *
+lgl_xml_vendor_read_vendors_from_file (gchar *utf8_filename)
+{
+ gchar *filename;
+ GList *vendors;
+ xmlDocPtr vendors_doc;
+
+ LIBXML_TEST_VERSION;
+
+ filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
+ if (!filename) {
+ g_message ("Utf8 filename conversion error");
+ return NULL;
+ }
+
+ vendors_doc = xmlParseFile (filename);
+ if (!vendors_doc) {
+ g_message ("\"%s\" is not a glabels vendor file (not XML)",
+ filename);
+ return NULL;
+ }
+
+ vendors = lgl_xml_vendor_parse_vendors_doc (vendors_doc);
+
+ g_free (filename);
+ xmlFreeDoc (vendors_doc);
+
+ return vendors;
+}
+
+
+/**
+ * lgl_xml_vendor_parse_vendors_doc:
+ * @vendors_doc: libxml #xmlDocPtr tree, representing a vendors definition file.
+ *
+ * Read vendor definitions from a libxml #xmlDocPtr tree.
+ *
+ * Returns: a list of #lglVendor structures.
+ *
+ */
+GList *
+lgl_xml_vendor_parse_vendors_doc (xmlDocPtr vendors_doc)
+{
+ GList *vendors = NULL;
+ xmlNodePtr root, node;
+ lglVendor *vendor;
+
+ LIBXML_TEST_VERSION;
+
+ root = xmlDocGetRootElement (vendors_doc);
+ if (!root || !root->name) {
+ g_message ("\"%s\" is not a glabels vendor file (no root node)",
+ vendors_doc->name);
+ xmlFreeDoc (vendors_doc);
+ return vendors;
+ }
+ if (!lgl_xml_is_node (root, "Glabels-vendors")) {
+ g_message ("\"%s\" is not a glabels vendor file (wrong root node)",
+ vendors_doc->name);
+ xmlFreeDoc (vendors_doc);
+ return vendors;
+ }
+
+ for (node = root->xmlChildrenNode; node != NULL; node = node->next) {
+
+ if (lgl_xml_is_node (node, "Vendor")) {
+ vendor = lgl_xml_vendor_parse_vendor_node (node);
+ vendors = g_list_append (vendors, vendor);
+ } else {
+ if ( !xmlNodeIsText(node) ) {
+ if (!lgl_xml_is_node (node, "comment")) {
+ g_message ("bad node = \"%s\"",node->name);
+ }
+ }
+ }
+ }
+
+ return vendors;
+}
+
+
+/**
+ * lgl_xml_vendor_parse_vendor_node:
+ * @vendor_node: libxml #xmlNodePtr vendor node from a #xmlDocPtr tree.
+ *
+ * Read a single vendor definition from a libxml #xmlNodePtr node.
+ *
+ * Returns: a pointer to a newly created #lglVendor structure.
+ *
+ */
+lglVendor *
+lgl_xml_vendor_parse_vendor_node (xmlNodePtr vendor_node)
+{
+ lglVendor *vendor;
+ gchar *name;
+
+ LIBXML_TEST_VERSION;
+
+ name = lgl_xml_get_prop_i18n_string (vendor_node, "name", NULL);
+
+ vendor = lgl_vendor_new (name);
+
+ vendor->url = lgl_xml_get_prop_i18n_string (vendor_node, "url", NULL);
+
+ g_free (name);
+
+ return vendor;
+}
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
--- /dev/null
+/*
+ * lgl-xml-vendor.h
+ * Copyright (C) 2003-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LGL_XML_VENDOR_H__
+#define __LGL_XML_VENDOR_H__
+
+#include <glib.h>
+#include <libxml/tree.h>
+
+#include "lgl-vendor.h"
+
+G_BEGIN_DECLS
+
+GList *lgl_xml_vendor_read_vendors_from_file (gchar *utf8_filename);
+
+GList *lgl_xml_vendor_parse_vendors_doc (xmlDocPtr vendors_doc);
+
+lglVendor *lgl_xml_vendor_parse_vendor_node (xmlNodePtr vendor_node);
+
+
+G_END_DECLS
+
+#endif /* __LGL_XML_VENDOR_H__ */
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
--- /dev/null
+/*
+ * lgl-xml.c
+ * Copyright (C) 2003-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "lgl-xml.h"
+
+#include <glib/gi18n.h>
+#include <glib.h>
+#include <string.h>
+
+#include "libglabels-private.h"
+
+
+/*========================================================*/
+/* Private macros and constants. */
+/*========================================================*/
+
+/*========================================================*/
+/* Private types. */
+/*========================================================*/
+
+/*========================================================*/
+/* Private globals. */
+/*========================================================*/
+
+static lglUnits default_units = LGL_UNITS_POINT;
+
+
+/****************************************************************************/
+
+/**
+ * lgl_xml_get_prop_string:
+ * @node: the libxml2 #xmlNodePtr of the node
+ * @property: the property name
+ * @default_val: a default value to return if property not found
+ *
+ * Return value of property as a string.
+ *
+ * Returns: the property as a pointer to a gchar string. This string should
+ * be freed with g_free().
+ *
+ */
+gchar *
+lgl_xml_get_prop_string (xmlNodePtr node,
+ const gchar *property,
+ const gchar *default_val)
+{
+ gchar *val;
+ xmlChar *string;
+
+ string = xmlGetProp (node, (xmlChar *)property);
+ if ( string != NULL ) {
+ val = g_strdup ((gchar *)string);
+ xmlFree (string);
+ return val;
+ }
+
+ if (default_val) {
+ return g_strdup (default_val);
+ }
+
+ return NULL;
+}
+
+
+/**
+ * lgl_xml_get_prop_i18n_string:
+ * @node: the libxml2 #xmlNodePtr of the node
+ * @property: the property name
+ * @default_val: a default value to return if property not found
+ *
+ * Return value of a translatable property as a string.
+ *
+ * Returns: the property as a pointer to a gchar string. This string should
+ * be freed with g_free().
+ *
+ */
+gchar *
+lgl_xml_get_prop_i18n_string (xmlNodePtr node,
+ const gchar *property,
+ const gchar *default_val)
+{
+ gchar *_property;
+ gchar *val;
+ xmlChar *string;
+
+ _property = g_strdup_printf ("_%s", property);
+ string = xmlGetProp (node, (xmlChar *)_property);
+ g_free (_property);
+
+ if ( string != NULL ) {
+
+ val = g_strdup (gettext ((char *)string));
+ xmlFree (string);
+ return val;
+
+ }
+
+ string = xmlGetProp (node, (xmlChar *)property);
+ if ( string != NULL ) {
+ val = g_strdup ((gchar *)string);
+ xmlFree (string);
+ return val;
+ }
+
+ if (default_val) {
+ return g_strdup (default_val);
+ }
+
+ return NULL;
+}
+
+
+/**
+ * lgl_xml_get_prop_double:
+ * @node: the libxml2 #xmlNodePtr of the node
+ * @property: the property name
+ * @default_val: a default value to return if property not found
+ *
+ * Return value of property as a double.
+ *
+ * Returns: the property as a double.
+ *
+ */
+gdouble
+lgl_xml_get_prop_double (xmlNodePtr node,
+ const gchar *property,
+ gdouble default_val)
+{
+ gdouble val;
+ xmlChar *string;
+
+ string = xmlGetProp (node, (xmlChar *)property);
+ if ( string != NULL ) {
+ val = g_strtod ((gchar *)string, NULL);
+ xmlFree (string);
+ return val;
+ }
+
+ return default_val;
+}
+
+
+/**
+ * lgl_xml_get_prop_boolean:
+ * @node: the libxml2 #xmlNodePtr of the node
+ * @property: the property name
+ * @default_val: a default value to return if property not found
+ *
+ * Return value of property as a boolean.
+ *
+ * Returns: the property as a boolean.
+ *
+ */
+gboolean
+lgl_xml_get_prop_boolean (xmlNodePtr node,
+ const gchar *property,
+ gboolean default_val)
+{
+ gboolean val;
+ xmlChar *string;
+
+ string = xmlGetProp (node, (xmlChar *)property);
+ if ( string != NULL ) {
+ val = !((xmlStrcasecmp (string, (xmlChar *)"false") == 0) ||
+ xmlStrEqual (string, (xmlChar *)"0"));;
+ xmlFree (string);
+ return val;
+ }
+
+ return default_val;
+}
+
+
+/**
+ * lgl_xml_get_prop_int:
+ * @node: the libxml2 #xmlNodePtr of the node
+ * @property: the property name
+ * @default_val: a default value to return if property not found
+ *
+ * Return value of property as an integer.
+ *
+ * Returns: the property as an integer.
+ *
+ */
+gint
+lgl_xml_get_prop_int (xmlNodePtr node,
+ const gchar *property,
+ gint default_val)
+{
+ gint val;
+ xmlChar *string;
+
+ string = xmlGetProp (node, (xmlChar *)property);
+ if ( string != NULL ) {
+ val = strtol ((char *)string, NULL, 0);
+ xmlFree (string);
+ return val;
+ }
+
+ return default_val;
+}
+
+
+/**
+ * lgl_xml_get_prop_uint:
+ * @node: the libxml2 #xmlNodePtr of the node
+ * @property: the property name
+ * @default_val: a default value to return if property not found
+ *
+ * Return value of property (usually formatted in hex) as an unsigned integer.
+ *
+ * Returns: the property as an unsigned integer.
+ *
+ */
+guint
+lgl_xml_get_prop_uint (xmlNodePtr node,
+ const gchar *property,
+ guint default_val)
+{
+ guint val;
+ xmlChar *string;
+
+ string = xmlGetProp (node, (xmlChar *)property);
+ if ( string != NULL ) {
+ val = strtoul ((char *)string, NULL, 0);
+ xmlFree (string);
+ return val;
+ }
+
+ return default_val;
+}
+
+
+/**
+ * lgl_xml_get_prop_length:
+ * @node: the libxml2 #xmlNodePtr of the node
+ * @property: the property name
+ * @default_val: a default value to return if property not found
+ *
+ * Return value of a length property as a double, converting to internal
+ * units (points). The property is expected to be formatted as a number
+ * followed by a units string. If there is no units string, the length
+ * is assumed to be in points. Valid units strings are "pt" for points,
+ * "in" for inches, "mm" for millimeters, "cm" for centimeters, and
+ * "pc" for picas.
+ *
+ * Returns: the length in points.
+ *
+ */
+gdouble
+lgl_xml_get_prop_length (xmlNodePtr node,
+ const gchar *property,
+ gdouble default_val)
+{
+ gdouble val;
+ xmlChar *string;
+ xmlChar *unit_id;
+ lglUnits units;
+
+ string = xmlGetProp (node, (xmlChar *)property);
+ if ( string != NULL ) {
+
+ val = g_strtod ((gchar *)string, (gchar **)&unit_id);
+
+ if (unit_id != string) {
+ unit_id = (xmlChar *)g_strchug ((gchar *)unit_id);
+ units = lgl_units_from_id ((gchar *)unit_id);
+ if (units != LGL_UNITS_INVALID)
+ {
+ val *= lgl_units_get_points_per_unit (units);
+ }
+ else
+ {
+ g_message ("Line %ld, Node \"%s\", Property \"%s\": Unknown unit \"%s\", assuming points",
+ xmlGetLineNo (node), node->name, property, unit_id);
+ }
+ }
+ else {
+ val = 0.0;
+ }
+
+ xmlFree (string);
+ return val;
+ }
+
+ return default_val;
+}
+
+
+/**
+ * lgl_xml_set_prop_string:
+ * @node: the libxml2 #xmlNodePtr of the node
+ * @property: the property name
+ * @val: the value to set
+ *
+ * Set a property from a string.
+ *
+ */
+void
+lgl_xml_set_prop_string (xmlNodePtr node,
+ const gchar *property,
+ const gchar *val)
+{
+ if (val != NULL) {
+ xmlSetProp (node, (xmlChar *)property, (xmlChar *)val);
+ }
+}
+
+
+/**
+ * lgl_xml_set_prop_double:
+ * @node: the libxml2 #xmlNodePtr of the node
+ * @property: the property name
+ * @val: the value to set
+ *
+ * Set a property from a double.
+ *
+ */
+void
+lgl_xml_set_prop_double (xmlNodePtr node,
+ const gchar *property,
+ gdouble val)
+{
+ gchar *string, buffer[G_ASCII_DTOSTR_BUF_SIZE];
+
+ /* Guarantee "C" locale by use of g_ascii_formatd */
+ string = g_ascii_formatd (buffer, G_ASCII_DTOSTR_BUF_SIZE, "%g", val);
+
+ xmlSetProp (node, (xmlChar *)property, (xmlChar *)string);
+}
+
+
+/**
+ * lgl_xml_set_prop_boolean:
+ * @node: the libxml2 #xmlNodePtr of the node
+ * @property: the property name
+ * @val: the value to set
+ *
+ * Set a property from a boolean.
+ *
+ */
+void
+lgl_xml_set_prop_boolean (xmlNodePtr node,
+ const gchar *property,
+ gboolean val)
+{
+ xmlSetProp (node, (xmlChar *)property, (xmlChar *)(val ? "True" : "False"));
+}
+
+/**
+ * lgl_xml_set_prop_int:
+ * @node: the libxml2 #xmlNodePtr of the node
+ * @property: the property name
+ * @val: the value to set
+ *
+ * Set a property from an integer.
+ *
+ */
+void
+lgl_xml_set_prop_int (xmlNodePtr node,
+ const gchar *property,
+ gint val)
+{
+ gchar *string;
+
+ string = g_strdup_printf ("%d", val);
+ xmlSetProp (node, (xmlChar *)property, (xmlChar *)string);
+ g_free (string);
+}
+
+/**
+ * lgl_xml_set_prop_uint_hex:
+ * @node: the libxml2 #xmlNodePtr of the node
+ * @property: the property name
+ * @val: the value to set
+ *
+ * Set a property from an unsigned integer and format in hex.
+ *
+ */
+void
+lgl_xml_set_prop_uint_hex (xmlNodePtr node,
+ const gchar *property,
+ guint val)
+{
+ gchar *string;
+
+ string = g_strdup_printf ("0x%08x", val);
+ xmlSetProp (node, (xmlChar *)property, (xmlChar *)string);
+ g_free (string);
+}
+
+/**
+ * lgl_xml_set_prop_length:
+ * @node: the libxml2 #xmlNodePtr of the node
+ * @property: the property name
+ * @val: the length to set in internal units (points)
+ *
+ * Set a property from a length, performing any necessary conversion.
+ * Length properties are formatted as a number followed by a units string.
+ * The units of the formatted property is determined by the most recent call to
+ * lgl_xml_set_default_units().
+ *
+ */
+void
+lgl_xml_set_prop_length (xmlNodePtr node,
+ const gchar *property,
+ gdouble val)
+{
+ gchar *string, buffer[G_ASCII_DTOSTR_BUF_SIZE];
+ gchar *string_unit;
+
+ /* Convert to default units */
+ val *= lgl_units_get_units_per_point (default_units);
+
+ /* Guarantee "C" locale by use of g_ascii_formatd */
+ string = g_ascii_formatd (buffer, G_ASCII_DTOSTR_BUF_SIZE, "%g", val);
+
+ string_unit = g_strdup_printf ("%s%s", string, lgl_units_get_id (default_units));
+ xmlSetProp (node, (xmlChar *)property, (xmlChar *)string_unit);
+ g_free (string_unit);
+}
+
+/**
+ * lgl_xml_is_node
+ * @node: the libxml2 #xmlNodePtr of the node
+ * @name : the node name
+ *
+ * Test if a node name matches given name.
+ *
+ * Returns: TRUE if the name of the node matches. Otherwise FALSE.
+ *
+ */
+gboolean
+lgl_xml_is_node (xmlNodePtr node,
+ const gchar *name)
+{
+ return xmlStrEqual (node->name, (xmlChar *)name);
+}
+
+
+/**
+ * lgl_xml_get_node_content
+ * @node: the libxml2 #xmlNodePtr of the node
+ *
+ * Get the content of a node.
+ *
+ * Returns: the property as a pointer to a gchar string. This string should
+ * be freed with g_free().
+ */
+gchar *
+lgl_xml_get_node_content (xmlNodePtr node)
+{
+ xmlChar *xml_content;
+ gchar *g_content;
+
+ xml_content = xmlNodeGetContent (node);
+
+ if (xml_content != NULL) {
+
+ g_content = g_strdup ((gchar *)xml_content);
+ xmlFree (xml_content);
+ return g_content;
+
+ }
+
+ return NULL;
+}
+
+
+/**
+ * lgl_xml_set_default_units:
+ * @units: default units selection (#lglUnits)
+ *
+ * Set the default units when formatting lengths. See
+ * lgl_xml_set_prop_length().
+ *
+ */
+void
+lgl_xml_set_default_units (lglUnits units)
+{
+ g_return_if_fail ((units >= LGL_UNITS_FIRST) && (units <= LGL_UNITS_LAST));
+
+ default_units = units;
+}
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
--- /dev/null
+/*
+ * lgl-xml.h
+ * Copyright (C) 2003-2010 Jim Evins <evins@snaught.com>.
+ *
+ * This file is part of libglabels.
+ *
+ * libglabels is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libglabels 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LGL_XML_H__
+#define __LGL_XML_H__
+
+#include <glib.h>
+#include <libxml/tree.h>
+
+#include "lgl-units.h"
+
+#define LGL_XML_NAME_SPACE "http://glabels.org/xmlns/2.3/"
+
+G_BEGIN_DECLS
+
+/*
+ * Get property functions
+ */
+gchar * lgl_xml_get_prop_string (xmlNodePtr node,
+ const gchar *property,
+ const gchar *default_val);
+
+gchar * lgl_xml_get_prop_i18n_string (xmlNodePtr node,
+ const gchar *property,
+ const gchar *default_val);
+
+gdouble lgl_xml_get_prop_double (xmlNodePtr node,
+ const gchar *property,
+ gdouble default_val);
+
+gboolean lgl_xml_get_prop_boolean (xmlNodePtr node,
+ const gchar *property,
+ gboolean default_val);
+
+gint lgl_xml_get_prop_int (xmlNodePtr node,
+ const gchar *property,
+ gint default_val);
+
+guint lgl_xml_get_prop_uint (xmlNodePtr node,
+ const gchar *property,
+ guint default_val);
+
+gdouble lgl_xml_get_prop_length (xmlNodePtr node,
+ const gchar *property,
+ gdouble default_val);
+
+
+/*
+ * Set property functions
+ */
+void lgl_xml_set_prop_string (xmlNodePtr node,
+ const gchar *property,
+ const gchar *val);
+
+void lgl_xml_set_prop_double (xmlNodePtr node,
+ const gchar *property,
+ gdouble val);
+
+void lgl_xml_set_prop_boolean (xmlNodePtr node,
+ const gchar *property,
+ gboolean val);
+
+void lgl_xml_set_prop_int (xmlNodePtr node,
+ const gchar *property,
+ gint val);
+
+void lgl_xml_set_prop_uint_hex (xmlNodePtr node,
+ const gchar *property,
+ guint val);
+
+void lgl_xml_set_prop_length (xmlNodePtr node,
+ const gchar *property,
+ gdouble val);
+
+/*
+ * Other node functions
+ */
+gboolean lgl_xml_is_node (xmlNodePtr node,
+ const gchar *name);
+
+gchar * lgl_xml_get_node_content (xmlNodePtr node);
+
+/*
+ * Misc functions
+ */
+void lgl_xml_set_default_units (lglUnits units);
+
+G_END_DECLS
+
+
+#endif /* __LGL_XML_H__ */
+
+
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */
#include <glib.h>
-#include "str.h"
-#include "template.h"
+#include "lgl-str.h"
+#include "lgl-template.h"
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "LibGlabels"
#ifndef __LIBGLABELS_H__
#define __LIBGLABELS_H__
-#include <libglabels/db.h>
-#include <libglabels/paper.h>
-#include <libglabels/category.h>
-#include <libglabels/template.h>
-#include <libglabels/units.h>
-#include <libglabels/str.h>
-#include <libglabels/xml-paper.h>
-#include <libglabels/xml-category.h>
-#include <libglabels/xml-template.h>
-#include <libglabels/xml.h>
+#include <libglabels/lgl-db.h>
+#include <libglabels/lgl-paper.h>
+#include <libglabels/lgl-category.h>
+#include <libglabels/lgl-template.h>
+#include <libglabels/lgl-units.h>
+#include <libglabels/lgl-str.h>
+#include <libglabels/lgl-xml-paper.h>
+#include <libglabels/lgl-xml-category.h>
+#include <libglabels/lgl-xml-template.h>
+#include <libglabels/lgl-xml.h>
#endif /* __LIBGLABELS_H__ */
+++ /dev/null
-/*
- * paper.c
- * Copyright (C) 2003-2009 Jim Evins <evins@snaught.com>.
- *
- * This file is part of libglabels.
- *
- * libglabels is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libglabels 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-
-#include "paper.h"
-
-#include <glib/gi18n.h>
-#include <glib.h>
-#include <string.h>
-
-#include "libglabels-private.h"
-
-/*===========================================*/
-/* Private types */
-/*===========================================*/
-
-
-/*===========================================*/
-/* Private globals */
-/*===========================================*/
-
-
-/*===========================================*/
-/* Local function prototypes */
-/*===========================================*/
-
-
-/*===========================================*/
-/* Functions. */
-/*===========================================*/
-
-/**
- * lgl_paper_new:
- * @id: Id of paper definition. (E.g. US-Letter, A4, etc.) Should be
- * unique.
- * @name: Localized name of paper.
- * @width: Width of paper in points.
- * @height: Height of paper in points.
- * @pwg_size: PWG 5101.1-2002 size name.
- *
- * Allocates and constructs a new #lglPaper structure.
- *
- * Returns: a pointer to a newly allocated #lglPaper structure.
- *
- */
-lglPaper *
-lgl_paper_new (gchar *id,
- gchar *name,
- gdouble width,
- gdouble height,
- gchar *pwg_size)
-{
- lglPaper *paper;
-
- paper = g_new0 (lglPaper,1);
-
- paper->id = g_strdup (id);
- paper->name = g_strdup (name);
- paper->width = width;
- paper->height = height;
- paper->pwg_size = g_strdup (pwg_size);
-
- return paper;
-}
-
-
-/**
- * lgl_paper_dup:
- * @orig: #lglPaper structure to be duplicated.
- *
- * Duplicates an existing #lglPaper structure.
- *
- * Returns: a pointer to a newly allocated #lglPaper structure.
- *
- */
-lglPaper *lgl_paper_dup (const lglPaper *orig)
-{
- lglPaper *paper;
-
- g_return_val_if_fail (orig, NULL);
-
- paper = g_new0 (lglPaper,1);
-
- paper->id = g_strdup (orig->id);
- paper->name = g_strdup (orig->name);
- paper->width = orig->width;
- paper->height = orig->height;
- paper->pwg_size = g_strdup (orig->pwg_size);
-
- return paper;
-}
-
-
-/**
- * lgl_paper_free:
- * @paper: pointer to #lglPaper structure to be freed.
- *
- * Free all memory associated with an existing #lglPaper structure.
- *
- */
-void lgl_paper_free (lglPaper *paper)
-{
-
- if ( paper != NULL ) {
-
- g_free (paper->id);
- paper->id = NULL;
-
- g_free (paper->name);
- paper->name = NULL;
-
- g_free (paper->pwg_size);
- paper->pwg_size = NULL;
-
- g_free (paper);
- }
-
-}
-
-
-
-/*
- * Local Variables: -- emacs
- * mode: C -- emacs
- * c-basic-offset: 8 -- emacs
- * tab-width: 8 -- emacs
- * indent-tabs-mode: nil -- emacs
- * End: -- emacs
- */
+++ /dev/null
-/*
- * paper.h
- * Copyright (C) 2003-2009 Jim Evins <evins@snaught.com>.
- *
- * This file is part of libglabels.
- *
- * libglabels is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libglabels 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __LGL_PAPER_H__
-#define __LGL_PAPER_H__
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-
-/*
- * lglPaper structure
- */
-typedef struct _lglPaper lglPaper;
-
-struct _lglPaper {
- gchar *id; /* Unique ID of paper definition */
- gchar *name; /* Localized name of paper */
- gdouble width; /* Width (in points) */
- gdouble height; /* Height (in points) */
- gchar *pwg_size; /* PWG 5101.1-2002 size name */
-};
-
-
-/*
- * Paper construction
- */
-lglPaper *lgl_paper_new (gchar *id,
- gchar *name,
- gdouble width,
- gdouble height,
- gchar *pwg_size);
-
-lglPaper *lgl_paper_dup (const lglPaper *orig);
-
-void lgl_paper_free (lglPaper *paper);
-
-
-G_END_DECLS
-
-#endif /* __LGL_PAPER_H__ */
-
-
-
-/*
- * Local Variables: -- emacs
- * mode: C -- emacs
- * c-basic-offset: 8 -- emacs
- * tab-width: 8 -- emacs
- * indent-tabs-mode: nil -- emacs
- * End: -- emacs
- */
+++ /dev/null
-/*
- * str.c
- * Copyright (C) 2007-2009 Jim Evins <evins@snaught.com>.
- *
- * This file is part of libglabels.
- *
- * libglabels is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libglabels 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-
-#include "str.h"
-
-#include <string.h>
-#include <math.h>
-
-#define FRAC_EPSILON 0.00005
-
-
-/*===========================================*/
-/* Private types */
-/*===========================================*/
-
-
-/*===========================================*/
-/* Private globals */
-/*===========================================*/
-
-
-/*===========================================*/
-/* Local function prototypes */
-/*===========================================*/
-
-static gchar *span_digits (gchar **p);
-static gchar *span_non_digits (gchar **p);
-
-/*===========================================*/
-/* Functions. */
-/*===========================================*/
-
-/**
- * lgl_str_utf8_casecmp:
- * @s1: string to compare with s2.
- * @s2: string to compare with s1.
- *
- * Compare two UTF-8 strings, ignoring the case of characters.
- *
- * This function should be used only on strings that are known to be encoded
- * in UTF-8 or a compatible UTF-8 subset.
- *
- * Returns: 0 if the strings match, a negative value if s1 < s2,
- * or a positive value if s1 > s2.
- *
- */
-gint
-lgl_str_utf8_casecmp (const gchar *s1,
- const gchar *s2)
-{
- gchar *folded_s1;
- gchar *folded_s2;
- gint result;
-
- folded_s1 = g_utf8_casefold (s1, -1);
- folded_s2 = g_utf8_casefold (s2, -1);
-
- result = g_utf8_collate (folded_s1, folded_s2);
-
- g_free (folded_s1);
- g_free (folded_s2);
-
- return result;
-}
-
-
-/**
- * lgl_str_part_name_cmp:
- * @s1: string to compare with s2.
- * @s2: string to compare with s1.
- *
- * Compare two UTF-8 strings representing part names or numbers. This function
- * uses a natural sort order:
- *
- * - Ignores case.
- *
- * - Strings are divided into chunks (numeric and non-numeric)
- *
- * - Non-numeric chunks are compared character by character
- *
- * - Numerical chunks are compared numerically, so that "20" precedes "100".
- *
- * - Comparison of chunks is performed left to right until the first difference
- * is encountered or all chunks evaluate as equal.
- *
- * This function should be used only on strings that are known to be encoded
- * in UTF-8 or a compatible UTF-8 subset.
- *
- * Numeric chunks are converted to 64 bit unsigned integers for comparison,
- * so the behaviour may be unpredictable for numeric chunks that exceed
- * 18446744073709551615.
- *
- * Returns: 0 if the strings match, a negative value if s1 < s2,
- * or a positive value if s1 > s2.
- *
- */
-gint
-lgl_str_part_name_cmp (const gchar *s1,
- const gchar *s2)
-{
- gchar *folded_s1, *p1, *chunk1;
- gchar *folded_s2, *p2, *chunk2;
- gboolean isnum1, isnum2;
- guint64 n1, n2;
- gboolean done;
- gint result;
-
- if ( s1 == s2 ) return 0;
- if (s1 == NULL) return -1;
- if (s2 == NULL) return 1;
-
- folded_s1 = g_utf8_casefold (s1, -1);
- folded_s2 = g_utf8_casefold (s2, -1);
-
- result = 0;
- done = FALSE;
- p1 = folded_s1;
- p2 = folded_s2;
- while ( (result == 0) && !done )
- {
-
- if ( g_ascii_isdigit (*p1) )
- {
- chunk1 = span_digits (&p1);
- isnum1 = TRUE;
- }
- else
- {
- chunk1 = span_non_digits (&p1);
- isnum1 = FALSE;
- }
-
- if ( g_ascii_isdigit (*p2) )
- {
- chunk2 = span_digits (&p2);
- isnum2 = TRUE;
- }
- else
- {
- chunk2 = span_non_digits (&p2);
- isnum2 = FALSE;
- }
-
- if ( (strlen(chunk1) == 0) && (strlen(chunk2) == 0) )
- {
- /* Case 1: Both are empty. */
- done = TRUE;
- }
- else if ( isnum1 && isnum2 )
- {
- /* Case 2: They both contain numbers */
- n1 = g_ascii_strtoull (chunk1, NULL, 10);
- n2 = g_ascii_strtoull (chunk2, NULL, 10);
-
- if ( n1 < n2 ) result = -1;
- if ( n1 > n2 ) result = 1;
- }
- else
- {
- /* Case 3: One or both do not contain numbers */
- result = g_utf8_collate (chunk1, chunk2);
- }
-
- g_free (chunk1);
- g_free (chunk2);
- }
-
- g_free (folded_s1);
- g_free (folded_s2);
-
- return result;
-}
-
-
-static gchar *
-span_digits (gchar **p)
-{
- gchar *chunk = g_new0 (gchar, strlen (*p) + 1);
- gint i;
-
- for ( i = 0; **p && g_ascii_isdigit (**p); i++, *p = g_utf8_next_char(*p) )
- {
- chunk[i] = **p;
- }
-
- return chunk;
-}
-
-
-static gchar *
-span_non_digits (gchar **p)
-{
- gchar *chunk = g_new0 (gchar, strlen (*p) + 1);
- gint i;
-
- for ( i = 0; **p && !g_ascii_isdigit (**p); i++, *p = g_utf8_next_char(*p) )
- {
- chunk[i] = **p;
- }
-
- return chunk;
-}
-
-
-/**
- * lgl_str_format_fraction:
- * @x: Floating point number to convert to fractional notation
- *
- * Create fractional representation of number, if possible. Uses UTF-8 superscripts and
- * subscripts for numerator and denominator values respecively.
- *
- * Returns: UTF-8 string containing fractional representation of x.
- */
-gchar *
-lgl_str_format_fraction (gdouble x)
-{
- static gdouble denom[] = { 1., 2., 3., 4., 8., 16., 32., 0. };
- static gchar *denom_string[] = { "1", "₂", "₃", "₄", "₈", "₁₆", "₃₂", NULL };
- static gchar *num_string[] = { "⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹",
- "¹⁰", "¹¹", "¹²", "¹³", "¹⁴", "¹⁵", "¹⁶", "¹⁷", "¹⁸", "¹⁹",
- "²⁰", "²¹", "²²", "²³", "²⁴", "²⁵", "²⁶", "²⁷", "²⁸", "²⁹",
- "³⁰", "³¹" };
- gint i;
- gdouble product, remainder;
- gint n, d;
-
- for ( i=0; denom[i] != 0.0; i++ ) {
- product = x * denom[i];
- remainder = fabs(product - ((gint)(product+0.5)));
- if ( remainder < FRAC_EPSILON ) break;
- }
-
- if ( denom[i] == 0.0 ) {
- /* None of our denominators work. */
- return g_strdup_printf ("%.5g", x);
- }
- if ( denom[i] == 1.0 ) {
- /* Simple integer. */
- return g_strdup_printf ("%.0f", x);
- }
- n = (gint)( x * denom[i] + 0.5 );
- d = (gint)denom[i];
- if ( n > d ) {
- return g_strdup_printf ("%d%s/%s", (n/d), num_string[n%d], denom_string[i]);
- } else {
- return g_strdup_printf ("%s/%s", num_string[n%d], denom_string[i]);
- }
-}
-
-
-
-/*
- * Local Variables: -- emacs
- * mode: C -- emacs
- * c-basic-offset: 8 -- emacs
- * tab-width: 8 -- emacs
- * indent-tabs-mode: nil -- emacs
- * End: -- emacs
- */
+++ /dev/null
-/*
- * str.h
- * Copyright (C) 2007-2009 Jim Evins <evins@snaught.com>.
- *
- * This file is part of libglabels.
- *
- * libglabels is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libglabels 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __LGL_STR_H__
-#define __LGL_STR_H__
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-gint lgl_str_utf8_casecmp (const gchar *s1,
- const gchar *s2);
-
-gint lgl_str_part_name_cmp (const gchar *s1,
- const gchar *s2);
-
-gchar *lgl_str_format_fraction (gdouble x);
-
-G_END_DECLS
-
-
-#endif /* __LGL_STR_H__ */
-
-
-
-/*
- * Local Variables: -- emacs
- * mode: C -- emacs
- * c-basic-offset: 8 -- emacs
- * tab-width: 8 -- emacs
- * indent-tabs-mode: nil -- emacs
- * End: -- emacs
- */
+++ /dev/null
-/*
- * template.c
- * Copyright (C) 2001-2009 Jim Evins <evins@snaught.com>.
- *
- * This file is part of libglabels.
- *
- * libglabels is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libglabels 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-
-#include "template.h"
-
-#include <glib/gi18n.h>
-#include <glib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <math.h>
-
-#include "libglabels-private.h"
-
-#include "db.h"
-#include "paper.h"
-
-/*===========================================*/
-/* Private macros and constants. */
-/*===========================================*/
-
-/* Allowed error when comparing dimensions. (0.5pts ~= .007in ~= .2mm) */
-#define EPSILON 0.5
-
-/*===========================================*/
-/* Private types */
-/*===========================================*/
-
-
-/*===========================================*/
-/* Private globals */
-/*===========================================*/
-
-
-/*===========================================*/
-/* Local function prototypes */
-/*===========================================*/
-
-static gint compare_origins (gconstpointer a,
- gconstpointer b,
- gpointer user_data);
-
-/*===========================================*/
-/* Functions. */
-/*===========================================*/
-
-/**
- * lgl_template_new:
- * @brand: Template brand
- * @part: Template part name/number
- * @description: Template descriptions
- * @paper_id: Page size id
- * @page_width: Page width in points, set to zero unless paper_id="Other"
- * @page_height: Page height in points, set to zero unless paper_id="Other"
- *
- * Create a new template structure, with the given top-level attributes. The
- * created template will have no initial categories, or frames associated with
- * it. See lgl_template_add_category() and lgl_template_add_frame() to add
- * these.
- *
- * Returns: pointer to a newly allocated #lglTemplate structure.
- *
- */
-lglTemplate *
-lgl_template_new (const gchar *brand,
- const gchar *part,
- const gchar *description,
- const gchar *paper_id,
- gdouble page_width,
- gdouble page_height)
-{
- lglTemplate *template;
-
- template = g_new0 (lglTemplate,1);
-
- template->brand = g_strdup (brand);
- template->part = g_strdup (part);
- template->description = g_strdup (description);
- template->paper_id = g_strdup (paper_id);
- template->page_width = page_width;
- template->page_height = page_height;
-
- return template;
-}
-
-
-/**
- * lgl_template_new_from_equiv:
- * @brand: Template brand
- * @part: Template part name/number
- * @equiv_part: Name of equivalent part to base template on
- *
- * Create a new template structure based on an existing template. The
- * created template will be a duplicate of the original template, except with
- * the new part name/number.
- *
- * Returns: pointer to a newly allocated #lglTemplate structure.
- *
- */
-lglTemplate *
-lgl_template_new_from_equiv (const gchar *brand,
- const gchar *part,
- const gchar *equiv_part)
-{
- lglTemplate *template = NULL;
-
- if ( lgl_db_does_template_exist (brand, equiv_part) )
- {
- template = lgl_db_lookup_template_from_brand_part (brand, equiv_part);
-
- g_free (template->part);
- g_free (template->equiv_part);
-
- template->part = g_strdup (part);
- template->equiv_part = g_strdup (equiv_part);
- }
- else
- {
- g_message ("Equivalent part (\"%s\") for \"%s\", not previously defined.",
- equiv_part, part);
- }
-
- return template;
-}
-
-
-/**
- * lgl_template_get_name:
- * @template: Pointer to template structure to test
- *
- * This function returns the name of the given template. The name is the concetenation
- * of the brand and part name/number.
- *
- * Returns: A pointer to a newly allocated name string. Should be freed with g_free().
- *
- */
-gchar *
-lgl_template_get_name (const lglTemplate *template)
-{
- g_return_val_if_fail (template, NULL);
-
- return g_strdup_printf ("%s %s", template->brand, template->part);
-}
-
-
-/**
- * lgl_template_do_templates_match:
- * @template1: Pointer to 1st template structure to test
- * @template2: Pointer to 2nd template structure to test
- *
- * This function tests if the given templates match. This is a simple test that only tests
- * the brand and part name/number. It does not test if they are actually identical.
- *
- * Returns: TRUE if the two templates match.
- *
- */
-gboolean
-lgl_template_do_templates_match (const lglTemplate *template1,
- const lglTemplate *template2)
-{
- g_return_val_if_fail (template1, FALSE);
- g_return_val_if_fail (template2, FALSE);
-
- return (UTF8_EQUAL (template1->brand, template2->brand) &&
- UTF8_EQUAL (template1->part, template2->part));
-}
-
-
-/**
- * lgl_template_does_brand_match:
- * @template: Pointer to template structure to test
- * @brand: Brand string
- *
- * This function tests if the brand of the template matches the given brand.
- *
- * Returns: TRUE if the template matches the given brand.
- *
- */
-gboolean
-lgl_template_does_brand_match (const lglTemplate *template,
- const gchar *brand)
-{
- g_return_val_if_fail (template, FALSE);
-
- /* NULL matches everything. */
- if (brand == NULL)
- {
- return TRUE;
- }
-
- return UTF8_EQUAL (template->brand, brand);
-}
-
-
-/**
- * lgl_template_does_page_size_match:
- * @template: Pointer to template structure to test
- * @paper_id: Page size ID string
- *
- * This function tests if the page size of the template matches the given ID.
- *
- * Returns: TRUE if the template matches the given page size ID.
- *
- */
-gboolean
-lgl_template_does_page_size_match (const lglTemplate *template,
- const gchar *paper_id)
-{
- g_return_val_if_fail (template, FALSE);
-
- /* NULL matches everything. */
- if (paper_id == NULL)
- {
- return TRUE;
- }
-
- return ASCII_EQUAL(paper_id, template->paper_id);
-}
-
-
-/**
- * lgl_template_does_category_match:
- * @template: Pointer to template structure to test
- * @category_id: Category ID string
- *
- * This function tests if the given template belongs to the given category ID.
- *
- * Returns: TRUE if the template matches the given category ID.
- *
- */
-gboolean
-lgl_template_does_category_match (const lglTemplate *template,
- const gchar *category_id)
-{
- GList *p;
-
- g_return_val_if_fail (template, FALSE);
-
- /* NULL matches everything. */
- if (category_id == NULL)
- {
- return TRUE;
- }
-
- for ( p=template->category_ids; p != NULL; p=p->next )
- {
- if (ASCII_EQUAL(category_id, p->data))
- {
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-
-/**
- * lgl_template_are_templates_identical:
- * @template1: Pointer to 1st template structure to test
- * @template2: Pointer to 2nd template structure to test
- *
- * This function tests if the given templates have identical size and layout properties.
- *
- * Returns: TRUE if the two templates are identical.
- *
- */
-gboolean
-lgl_template_are_templates_identical (const lglTemplate *template1,
- const lglTemplate *template2)
-{
- lglTemplateFrame *frame1;
- lglTemplateFrame *frame2;
- GList *p1;
- GList *p2;
- lglTemplateLayout *layout1;
- lglTemplateLayout *layout2;
- gboolean match_found;
-
-
- if (!UTF8_EQUAL (template1->paper_id, template2->paper_id) ||
- (template1->page_width != template2->page_width) ||
- (template1->page_height != template2->page_height))
- {
- return FALSE;
- }
-
- frame1 = (lglTemplateFrame *)template1->frames->data;
- frame2 = (lglTemplateFrame *)template2->frames->data;
-
- if ( frame1->shape != frame2->shape )
- {
- return FALSE;
- }
-
- switch ( frame1->shape )
- {
-
- case LGL_TEMPLATE_FRAME_SHAPE_RECT:
- if ( (fabs(frame1->rect.w - frame2->rect.w) > EPSILON) ||
- (fabs(frame1->rect.h - frame2->rect.h) > EPSILON) )
- {
- return FALSE;
- }
- break;
-
- case LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE:
- if ( (fabs(frame1->ellipse.w - frame2->ellipse.w) > EPSILON) ||
- (fabs(frame1->ellipse.h - frame2->ellipse.h) > EPSILON) )
- {
- return FALSE;
- }
- break;
-
- case LGL_TEMPLATE_FRAME_SHAPE_ROUND:
- if ( fabs(frame1->round.r - frame2->round.r) > EPSILON )
- {
- return FALSE;
- }
- break;
-
- case LGL_TEMPLATE_FRAME_SHAPE_CD:
- if ( (fabs(frame1->cd.r1 - frame2->cd.r1) > EPSILON) ||
- (fabs(frame1->cd.r2 - frame2->cd.r2) > EPSILON) )
- {
- return FALSE;
- }
- }
-
- for ( p1 = frame1->all.layouts; p1; p1 = p1->next )
- {
- layout1 = (lglTemplateLayout *)p1->data;
-
- match_found = FALSE;
- for ( p2 = frame2->all.layouts; p2 && !match_found; p2 = p2->next )
- {
- layout2 = (lglTemplateLayout *)p2->data;
-
- if ( (layout1->nx == layout2->nx) &&
- (layout1->ny == layout2->ny) &&
- (fabs(layout1->x0 - layout2->x0) < EPSILON) &&
- (fabs(layout1->y0 - layout2->y0) < EPSILON) &&
- (fabs(layout1->dx - layout2->dx) < EPSILON) &&
- (fabs(layout1->dy - layout2->dy) < EPSILON) )
- {
- match_found = TRUE;
- }
-
- }
- if ( !match_found )
- {
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-
-/**
- * lgl_template_add_frame:
- * @template: Pointer to template structure
- * @frame: Pointer to frame structure
- *
- * This function adds the given frame structure to the template. Once added,
- * the frame structure belongs to the given template; do not attempt to free
- * it.
- *
- * Note: Currently glabels only supports a single frame per template.
- *
- */
-void
-lgl_template_add_frame (lglTemplate *template,
- lglTemplateFrame *frame)
-{
- g_return_if_fail (template);
- g_return_if_fail (frame);
-
- template->frames = g_list_append (template->frames, frame);
-}
-
-
-/**
- * lgl_template_add_category:
- * @template: Pointer to template structure
- * @category_id: Category ID string
- *
- * This function adds the given category ID to a templates category list.
- *
- */
-void
-lgl_template_add_category (lglTemplate *template,
- const gchar *category_id)
-{
- g_return_if_fail (template);
- g_return_if_fail (category_id);
-
- template->category_ids = g_list_append (template->category_ids,
- g_strdup (category_id));
-}
-
-
-/**
- * lgl_template_frame_rect_new:
- * @id: ID of frame. (This should currently always be "0").
- * @w: width of frame in points.
- * @h: height of frame in points.
- * @r: radius of rounded corners in points. (Should be 0 for square corners.)
- * @x_waste: Amount of overprint to allow in the horizontal direction.
- * @y_waste: Amount of overprint to allow in the vertical direction.
- *
- * This function creates a new template frame for a rectangular label or card.
- *
- * Returns: Pointer to newly allocated #lglTemplateFrame structure.
- *
- */
-lglTemplateFrame *
-lgl_template_frame_rect_new (const gchar *id,
- gdouble w,
- gdouble h,
- gdouble r,
- gdouble x_waste,
- gdouble y_waste)
-{
- lglTemplateFrame *frame;
-
- frame = g_new0 (lglTemplateFrame, 1);
-
- frame->shape = LGL_TEMPLATE_FRAME_SHAPE_RECT;
- frame->rect.id = g_strdup (id);
-
- frame->rect.w = w;
- frame->rect.h = h;
- frame->rect.r = r;
- frame->rect.x_waste = x_waste;
- frame->rect.y_waste = y_waste;
-
- return frame;
-}
-
-
-/**
- * lgl_template_frame_ellipse_new:
- * @id: ID of frame. (This should currently always be "0").
- * @w: width of frame in points.
- * @h: height of frame in points.
- * @waste: Amount of overprint to allow in points.
- *
- * This function creates a new template frame for an elliptical label or card.
- *
- * Returns: Pointer to newly allocated #lglTemplateFrame structure.
- *
- */
-lglTemplateFrame *
-lgl_template_frame_ellipse_new (const gchar *id,
- gdouble w,
- gdouble h,
- gdouble waste)
-{
- lglTemplateFrame *frame;
-
- frame = g_new0 (lglTemplateFrame, 1);
-
- frame->shape = LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE;
- frame->ellipse.id = g_strdup (id);
-
- frame->ellipse.w = w;
- frame->ellipse.h = h;
- frame->ellipse.waste = waste;
-
- return frame;
-}
-
-
-/**
- * lgl_template_frame_round_new:
- * @id: ID of frame. (This should currently always be "0").
- * @r: radius of label in points.
- * @waste: Amount of overprint to allow.
- *
- * This function creates a new template frame for a round label.
- *
- * Returns: Pointer to newly allocated #lglTemplateFrame structure.
- *
- */
-lglTemplateFrame *
-lgl_template_frame_round_new (const gchar *id,
- gdouble r,
- gdouble waste)
-{
- lglTemplateFrame *frame;
-
- frame = g_new0 (lglTemplateFrame, 1);
-
- frame->shape = LGL_TEMPLATE_FRAME_SHAPE_ROUND;
- frame->round.id = g_strdup (id);
-
- frame->round.r = r;
- frame->round.waste = waste;
-
- return frame;
-}
-
-
-/**
- * lgl_template_frame_cd_new:
- * @id: ID of frame. (This should currently always be "0").
- * @r1: outer radius of label in points.
- * @r2: radius of center hole in points.
- * @w: clip width of frame in points for business card CDs. Should be 0 for no clipping.
- * @h: clip height of frame in points for business card CDs. Should be 0 for no clipping.
- * @waste: Amount of overprint to allow.
- *
- * This function creates a new template frame for a CD/DVD label.
- *
- * Returns: Pointer to newly allocated #lglTemplateFrame structure.
- *
- */
-lglTemplateFrame *
-lgl_template_frame_cd_new (const gchar *id,
- gdouble r1,
- gdouble r2,
- gdouble w,
- gdouble h,
- gdouble waste)
-{
- lglTemplateFrame *frame;
-
- frame = g_new0 (lglTemplateFrame, 1);
-
- frame->shape = LGL_TEMPLATE_FRAME_SHAPE_CD;
- frame->cd.id = g_strdup (id);
-
- frame->cd.r1 = r1;
- frame->cd.r2 = r2;
- frame->cd.w = w;
- frame->cd.h = h;
- frame->cd.waste = waste;
-
- return frame;
-}
-
-
-/**
- * lgl_template_frame_get_size:
- * @frame: #lglTemplateFrame structure to query
- * @w: pointer to location to receive width of frame
- * @h: pointer to location to receive height of frame
- *
- * Get size (width and height) of given #lglTemplateFrame in points.
- *
- */
-void
-lgl_template_frame_get_size (const lglTemplateFrame *frame,
- gdouble *w,
- gdouble *h)
-{
- g_return_if_fail (frame);
-
- switch (frame->shape) {
- case LGL_TEMPLATE_FRAME_SHAPE_RECT:
- *w = frame->rect.w;
- *h = frame->rect.h;
- break;
- case LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE:
- *w = frame->ellipse.w;
- *h = frame->ellipse.h;
- break;
- case LGL_TEMPLATE_FRAME_SHAPE_ROUND:
- *w = 2.0 * frame->round.r;
- *h = 2.0 * frame->round.r;
- break;
- case LGL_TEMPLATE_FRAME_SHAPE_CD:
- if (frame->cd.w == 0.0) {
- *w = 2.0 * frame->cd.r1;
- } else {
- *w = frame->cd.w;
- }
- if (frame->cd.h == 0.0) {
- *h = 2.0 * frame->cd.r1;
- } else {
- *h = frame->cd.h;
- }
- break;
- default:
- *w = 0.0;
- *h = 0.0;
- break;
- }
-}
-
-
-/**
- * lgl_template_frame_get_n_labels:
- * @frame: #lglTemplateFrame structure to query
- *
- * Get total number of labels per sheet corresponding to the given frame.
- *
- * Returns: number of labels per sheet.
- *
- */
-gint
-lgl_template_frame_get_n_labels (const lglTemplateFrame *frame)
-{
- gint n_labels = 0;
- GList *p;
- lglTemplateLayout *layout;
-
- g_return_val_if_fail (frame, 0);
-
- for ( p=frame->all.layouts; p != NULL; p=p->next ) {
- layout = (lglTemplateLayout *)p->data;
-
- n_labels += layout->nx * layout->ny;
- }
-
- return n_labels;
-}
-
-
-/**
- * lgl_template_frame_get_layout_description
- * @frame: #lglTemplateFrame structure to query
- *
- * Get a description of the label layout including number of labels per sheet.
- *
- * Returns: a newly allocation description string.
- *
- */
-gchar *
-lgl_template_frame_get_layout_description (const lglTemplateFrame *frame)
-{
- gint n_labels;
- gchar *string;
- lglTemplateLayout *layout;
-
- n_labels = lgl_template_frame_get_n_labels (frame);
-
- if ( frame->all.layouts && (frame->all.layouts->next == NULL) )
- {
- layout = (lglTemplateLayout *)frame->all.layouts->data;
- /*
- * Translators: 1st %d = number of labels across a page,
- * 2nd %d = number of labels down a page,
- * 3rd %d = total number of labels on a page (sheet).
- */
- string = g_strdup_printf (_("%d × %d (%d per sheet)"), layout->nx, layout->ny, n_labels);
- }
- else
- {
- /* Translators: %d is the total number of labels on a page (sheet). */
- string = g_strdup_printf (_("%d per sheet"), n_labels);
- }
-
- return string;
-}
-
-
-/**
- * lgl_template_frame_get_size_description
- * @frame: #lglTemplateFrame structure to query
- * @units: #lglUnits
- *
- * Get a description of the label size.
- *
- * Returns: a newly allocation description string.
- *
- */
-gchar *
-lgl_template_frame_get_size_description (const lglTemplateFrame *frame,
- lglUnits units)
-{
- const gchar *units_string;
- gdouble units_per_point;
- gchar *string = NULL;
-
- units_string = lgl_units_get_name (units);
- units_per_point = lgl_units_get_units_per_point (units);
-
- switch (frame->shape) {
- case LGL_TEMPLATE_FRAME_SHAPE_RECT:
- if ( units == LGL_UNITS_INCH ) {
- gchar *xstr, *ystr;
-
- xstr = lgl_str_format_fraction (frame->rect.w*units_per_point);
- ystr = lgl_str_format_fraction (frame->rect.h*units_per_point);
- string = g_strdup_printf ("%s × %s %s",
- xstr, ystr, units_string);
- g_free (xstr);
- g_free (ystr);
- } else {
- string = g_strdup_printf ("%.5g × %.5g %s",
- frame->rect.w*units_per_point,
- frame->rect.h*units_per_point,
- units_string);
- }
- break;
- case LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE:
- if ( units == LGL_UNITS_INCH ) {
- gchar *xstr, *ystr;
-
- xstr = lgl_str_format_fraction (frame->ellipse.w*units_per_point);
- ystr = lgl_str_format_fraction (frame->ellipse.h*units_per_point);
- string = g_strdup_printf ("%s × %s %s",
- xstr, ystr, units_string);
- g_free (xstr);
- g_free (ystr);
- } else {
- string = g_strdup_printf ("%.5g × %.5g %s",
- frame->ellipse.w*units_per_point,
- frame->ellipse.h*units_per_point,
- units_string);
- }
- break;
- case LGL_TEMPLATE_FRAME_SHAPE_ROUND:
- if ( units == LGL_UNITS_INCH ) {
- gchar *dstr;
-
- dstr = lgl_str_format_fraction (2.0*frame->round.r*units_per_point);
- string = g_strdup_printf ("%s %s %s",
- dstr, units_string,
- _("diameter"));
- g_free (dstr);
- } else {
- string = g_strdup_printf ("%.5g %s %s",
- 2.0*frame->round.r*units_per_point,
- units_string,
- _("diameter"));
- }
- break;
- case LGL_TEMPLATE_FRAME_SHAPE_CD:
- if ( units == LGL_UNITS_INCH ) {
- gchar *dstr;
-
- dstr = lgl_str_format_fraction (2.0*frame->cd.r1*units_per_point);
- string = g_strdup_printf ("%s %s %s",
- dstr, units_string,
- _("diameter"));
- g_free (dstr);
- } else {
- string = g_strdup_printf ("%.5g %s %s",
- 2.0*frame->cd.r1*units_per_point,
- units_string,
- _("diameter"));
- }
- break;
- default:
- break;
- }
-
- return string;
-}
-
-
-/**
- * lgl_template_frame_get_origins:
- * @frame: #lglTemplateFrame structure to query
- *
- * Get an array of label origins for the given frame. These origins represent the
- * upper left hand corner of each label on a page corresponding to the given frame.
- * The origins will be ordered geometrically left to right and then top to bottom.
- * The array should be freed using g_free().
- *
- * Returns: A newly allocated array of #lglTemplateOrigin structures.
- *
- */
-lglTemplateOrigin *
-lgl_template_frame_get_origins (const lglTemplateFrame *frame)
-{
- gint i_label, n_labels, ix, iy;
- lglTemplateOrigin *origins;
- GList *p;
- lglTemplateLayout *layout;
-
- g_return_val_if_fail (frame, NULL);
-
- n_labels = lgl_template_frame_get_n_labels (frame);
- origins = g_new0 (lglTemplateOrigin, n_labels);
-
- i_label = 0;
- for ( p=frame->all.layouts; p != NULL; p=p->next ) {
- layout = (lglTemplateLayout *)p->data;
-
- for (iy = 0; iy < layout->ny; iy++) {
- for (ix = 0; ix < layout->nx; ix++, i_label++) {
- origins[i_label].x = ix*layout->dx + layout->x0;
- origins[i_label].y = iy*layout->dy + layout->y0;
- }
- }
- }
-
- g_qsort_with_data (origins, n_labels, sizeof(lglTemplateOrigin),
- compare_origins, NULL);
-
- return origins;
-}
-
-
-/**
- * lgl_template_frame_add_layout:
- * @frame: Pointer to template frame to add layout to.
- * @layout: Pointer to layout structure to add to frame.
- *
- * This function adds a layout structure to the given template frame.
- *
- */
-void
-lgl_template_frame_add_layout (lglTemplateFrame *frame,
- lglTemplateLayout *layout)
-{
- g_return_if_fail (frame);
- g_return_if_fail (layout);
-
- frame->all.layouts = g_list_append (frame->all.layouts, layout);
-}
-
-
-/**
- * lgl_template_frame_add_markup:
- * @frame: Pointer to template frame to add markup to.
- * @markup: Pointer to markup structure to add to frame.
- *
- * This function adds a markup structure to the given template frame.
- *
- */
-void
-lgl_template_frame_add_markup (lglTemplateFrame *frame,
- lglTemplateMarkup *markup)
-{
- g_return_if_fail (frame);
- g_return_if_fail (markup);
-
- frame->all.markups = g_list_append (frame->all.markups, markup);
-}
-
-
-/**
- * lgl_template_layout_new:
- * @nx: Number of labels across.
- * @ny: Number of labels down.
- * @x0: X coordinate of the top-left corner of the top-left label in the layout in points.
- * @y0: Y coordinate of the top-left corner of the top-left label in the layout in points.
- * @dx: Horizontal pitch in points. This is the distance from left-edge to left-edge.
- * @dy: Vertical pitch in points. This is the distance from top-edge to top-edge.
- *
- * This function creates a new layout structure with the given parameters.
- *
- * Returns: a newly allocated #lglTemplateLayout structure.
- *
- */
-lglTemplateLayout *
-lgl_template_layout_new (gint nx,
- gint ny,
- gdouble x0,
- gdouble y0,
- gdouble dx,
- gdouble dy)
-{
- lglTemplateLayout *layout;
-
- layout = g_new0 (lglTemplateLayout, 1);
-
- layout->nx = nx;
- layout->ny = ny;
- layout->x0 = x0;
- layout->y0 = y0;
- layout->dx = dx;
- layout->dy = dy;
-
- return layout;
-}
-
-
-/**
- * lgl_template_markup_margin_new:
- * @size: margin size in points.
- *
- * This function creates a new margin markup structure.
- *
- * Returns: a newly allocated #lglTemplateMarkup structure.
- *
- */
-lglTemplateMarkup *
-lgl_template_markup_margin_new (gdouble size)
-{
- lglTemplateMarkup *markup;
-
- markup = g_new0 (lglTemplateMarkup, 1);
-
- markup->type = LGL_TEMPLATE_MARKUP_MARGIN;
- markup->margin.size = size;
-
- return markup;
-}
-
-
-/**
- * lgl_template_markup_line_new:
- * @x1: x coordinate of first endpoint.
- * @y1: y coordinate of first endpoint.
- * @x2: x coordinate of second endpoint.
- * @y2: y coordinate of second endpoint.
- *
- * This function creates a new line markup structure.
- *
- * Returns: a newly allocated #lglTemplateMarkup structure.
- *
- */
-lglTemplateMarkup *
-lgl_template_markup_line_new (gdouble x1,
- gdouble y1,
- gdouble x2,
- gdouble y2)
-{
- lglTemplateMarkup *markup;
-
- markup = g_new0 (lglTemplateMarkup, 1);
-
- markup->type = LGL_TEMPLATE_MARKUP_LINE;
- markup->line.x1 = x1;
- markup->line.y1 = y1;
- markup->line.x2 = x2;
- markup->line.y2 = y2;
-
- return markup;
-}
-
-
-/**
- * lgl_template_markup_circle_new:
- * @x0: x coordinate of center of circle.
- * @y0: y coordinate of center of circle.
- * @r: radius of circle.
- *
- * This function creates a new circle markup structure.
- *
- * Returns: a newly allocated #lglTemplateMarkup structure.
- *
- */
-lglTemplateMarkup *
-lgl_template_markup_circle_new (gdouble x0,
- gdouble y0,
- gdouble r)
-{
- lglTemplateMarkup *markup;
-
- markup = g_new0 (lglTemplateMarkup, 1);
-
- markup->type = LGL_TEMPLATE_MARKUP_CIRCLE;
- markup->circle.x0 = x0;
- markup->circle.y0 = y0;
- markup->circle.r = r;
-
- return markup;
-}
-
-
-/**
- * lgl_template_markup_rect_new:
- * @x1: x coordinate of top-left corner of rectangle.
- * @y1: y coordinate of top-left corner of rectangle.
- * @w: width of rectangle.
- * @h: height of rectangle.
- * @r: radius of rounded corner.
- *
- * This function creates a new rectangle markup structure.
- *
- * Returns: a newly allocated #lglTemplateMarkup structure.
- *
- */
-lglTemplateMarkup *
-lgl_template_markup_rect_new (gdouble x1,
- gdouble y1,
- gdouble w,
- gdouble h,
- gdouble r)
-{
- lglTemplateMarkup *markup;
-
- markup = g_new0 (lglTemplateMarkup, 1);
-
- markup->type = LGL_TEMPLATE_MARKUP_RECT;
- markup->rect.x1 = x1;
- markup->rect.y1 = y1;
- markup->rect.w = w;
- markup->rect.h = h;
- markup->rect.r = r;
-
- return markup;
-}
-
-
-/**
- * lgl_template_markup_ellipse_new:
- * @x1: x coordinate of top-left corner of ellipse.
- * @y1: y coordinate of top-left corner of ellipse.
- * @w: width of ellipse.
- * @h: height of ellipse.
- *
- * This function creates a new ellipse markup structure.
- *
- * Returns: a newly allocated #lglTemplateMarkup structure.
- *
- */
-lglTemplateMarkup *
-lgl_template_markup_ellipse_new (gdouble x1,
- gdouble y1,
- gdouble w,
- gdouble h)
-{
- lglTemplateMarkup *markup;
-
- markup = g_new0 (lglTemplateMarkup, 1);
-
- markup->type = LGL_TEMPLATE_MARKUP_ELLIPSE;
- markup->ellipse.x1 = x1;
- markup->ellipse.y1 = y1;
- markup->ellipse.w = w;
- markup->ellipse.h = h;
-
- return markup;
-}
-
-
-/**
- * lgl_template_dup:
- * @orig_template: Template to duplicate.
- *
- * This function duplicates a template structure.
- *
- * Returns: a newly allocated #lglTemplate structure.
- *
- */
-lglTemplate *
-lgl_template_dup (const lglTemplate *orig_template)
-{
- lglTemplate *template;
- GList *p;
- lglTemplateFrame *frame;
-
- g_return_val_if_fail (orig_template, NULL);
-
- template = lgl_template_new (orig_template->brand,
- orig_template->part,
- orig_template->description,
- orig_template->paper_id,
- orig_template->page_width,
- orig_template->page_height);
-
- template->equiv_part = g_strdup (orig_template->equiv_part);
- template->product_url = g_strdup (orig_template->product_url);
-
-
- for ( p=orig_template->category_ids; p != NULL; p=p->next )
- {
- lgl_template_add_category (template, p->data);
- }
-
- for ( p=orig_template->frames; p != NULL; p=p->next )
- {
- frame = (lglTemplateFrame *)p->data;
-
- lgl_template_add_frame (template, lgl_template_frame_dup (frame));
- }
-
- return template;
-}
-
-
-/**
- * lgl_template_free:
- * @template: Template to free.
- *
- * This function frees all memory associated with given template structure.
- *
- */
-void
-lgl_template_free (lglTemplate *template)
-{
- GList *p;
- lglTemplateFrame *frame;
-
- if ( template != NULL ) {
-
- g_free (template->brand);
- template->brand = NULL;
-
- g_free (template->part);
- template->part = NULL;
-
- g_free (template->description);
- template->description = NULL;
-
- g_free (template->paper_id);
- template->paper_id = NULL;
-
- for ( p=template->category_ids; p != NULL; p=p->next ) {
-
- g_free (p->data);
- p->data = NULL;
-
- }
- g_list_free (template->category_ids);
- template->category_ids = NULL;
-
- for ( p=template->frames; p != NULL; p=p->next ) {
-
- frame = (lglTemplateFrame *)p->data;
-
- lgl_template_frame_free (frame);
- p->data = NULL;
- }
- g_list_free (template->frames);
- template->frames = NULL;
-
- g_free (template);
-
- }
-
-}
-
-
-/**
- * lgl_template_frame_dup:
- * @orig_frame: Frame to duplicate.
- *
- * This function duplicates a template frame structure.
- *
- * Returns: a newly allocated #lglTemplateFrame structure.
- *
- */
-lglTemplateFrame *
-lgl_template_frame_dup (const lglTemplateFrame *orig_frame)
-{
- lglTemplateFrame *frame;
- GList *p;
- lglTemplateLayout *layout;
- lglTemplateMarkup *markup;
-
- g_return_val_if_fail (orig_frame, NULL);
-
- switch (orig_frame->shape) {
-
- case LGL_TEMPLATE_FRAME_SHAPE_RECT:
- frame =
- lgl_template_frame_rect_new (orig_frame->all.id,
- orig_frame->rect.w,
- orig_frame->rect.h,
- orig_frame->rect.r,
- orig_frame->rect.x_waste,
- orig_frame->rect.y_waste);
- break;
-
- case LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE:
- frame =
- lgl_template_frame_ellipse_new (orig_frame->all.id,
- orig_frame->ellipse.w,
- orig_frame->ellipse.h,
- orig_frame->ellipse.waste);
- break;
-
- case LGL_TEMPLATE_FRAME_SHAPE_ROUND:
- frame =
- lgl_template_frame_round_new (orig_frame->all.id,
- orig_frame->round.r,
- orig_frame->round.waste);
- break;
-
- case LGL_TEMPLATE_FRAME_SHAPE_CD:
- frame =
- lgl_template_frame_cd_new (orig_frame->all.id,
- orig_frame->cd.r1,
- orig_frame->cd.r2,
- orig_frame->cd.w,
- orig_frame->cd.h,
- orig_frame->cd.waste);
- break;
-
- default:
- return NULL;
- break;
- }
-
- for ( p=orig_frame->all.layouts; p != NULL; p=p->next ) {
-
- layout = (lglTemplateLayout *)p->data;
-
- lgl_template_frame_add_layout (frame, lgl_template_layout_dup (layout));
- }
-
- for ( p=orig_frame->all.markups; p != NULL; p=p->next ) {
-
- markup = (lglTemplateMarkup *)p->data;
-
- lgl_template_frame_add_markup (frame, lgl_template_markup_dup (markup));
- }
-
- return frame;
-}
-
-
-/**
- * lgl_template_frame_free:
- * @frame: Frame to free.
- *
- * This function frees all memory associated with given template frame structure.
- *
- */
-void
-lgl_template_frame_free (lglTemplateFrame *frame)
-{
- GList *p;
- lglTemplateLayout *layout;
- lglTemplateMarkup *markup;
-
- if ( frame != NULL ) {
-
- g_free (frame->all.id);
- frame->all.id = NULL;
-
- for ( p=frame->all.layouts; p != NULL; p=p->next ) {
-
- layout = (lglTemplateLayout *)p->data;
-
- lgl_template_layout_free (layout);
- p->data = NULL;
- }
- g_list_free (frame->all.layouts);
- frame->all.layouts = NULL;
-
- for ( p=frame->all.markups; p != NULL; p=p->next ) {
-
- markup = (lglTemplateMarkup *)p->data;
-
- lgl_template_markup_free (markup);
- p->data = NULL;
- }
- g_list_free (frame->all.markups);
- frame->all.markups = NULL;
-
- g_free (frame);
-
- }
-
-}
-
-
-/**
- * lgl_template_layout_dup:
- * @orig_layout: Layout to duplicate.
- *
- * This function duplicates a template layout structure.
- *
- * Returns: a newly allocated #lglTemplateLayout structure.
- *
- */
-lglTemplateLayout *
-lgl_template_layout_dup (const lglTemplateLayout *orig_layout)
-{
- lglTemplateLayout *layout;
-
- g_return_val_if_fail (orig_layout, NULL);
-
- layout = g_new0 (lglTemplateLayout, 1);
-
- /* copy contents */
- *layout = *orig_layout;
-
- return layout;
-}
-
-
-/**
- * lgl_template_layout_free:
- * @layout: Layout to free.
- *
- * This function frees all memory associated with given template layout structure.
- *
- */
-void
-lgl_template_layout_free (lglTemplateLayout *layout)
-{
- g_free (layout);
-}
-
-
-/**
- * lgl_template_markup_dup:
- * @orig_markup: Markup to duplicate.
- *
- * This function duplicates a template markup structure.
- *
- * Returns: a newly allocated #lglTemplateMarkup structure.
- *
- */
-lglTemplateMarkup *
-lgl_template_markup_dup (const lglTemplateMarkup *orig_markup)
-{
- lglTemplateMarkup *markup;
-
- g_return_val_if_fail (orig_markup, NULL);
-
- markup = g_new0 (lglTemplateMarkup, 1);
-
- *markup = *orig_markup;
-
- return markup;
-}
-
-
-/**
- * lgl_template_markup_free:
- * @markup: Markup to free.
- *
- * This function frees all memory associated with given template markup structure.
- *
- */
-void
-lgl_template_markup_free (lglTemplateMarkup *markup)
-{
- g_free (markup);
-}
-
-
-static gint
-compare_origins (gconstpointer a,
- gconstpointer b,
- gpointer user_data)
-{
- const lglTemplateOrigin *a_origin = a, *b_origin = b;
-
- if ( a_origin->y < b_origin->y ) {
- return -1;
- } else if ( a_origin->y > b_origin->y ) {
- return +1;
- } else {
- if ( a_origin->x < b_origin->x ) {
- return -1;
- } else if ( a_origin->x > b_origin->x ) {
- return +1;
- } else {
- return 0; /* hopefully 2 labels won't have the same origin */
- }
- }
-}
-
-
-/**
- * lgl_template_print:
- * @template: template
- *
- * Print template details (for debugging purposes).
- *
- */
-void
-lgl_template_print (const lglTemplate *template)
-{
- g_print ("---- %s( TEMPLATE=%p ) ----\n", __FUNCTION__, template);
-
- g_print("brand=\"%s\", part=\"%s\", description=\"%s\"\n",
- template->brand, template->part, template->description);
-
- g_print("paper_id=\"%s\", page_width=%g, page_height=%g\n",
- template->paper_id, template->page_width, template->page_height);
-
- g_print ("\n");
-
-}
-
-
-
-/*
- * Local Variables: -- emacs
- * mode: C -- emacs
- * c-basic-offset: 8 -- emacs
- * tab-width: 8 -- emacs
- * indent-tabs-mode: nil -- emacs
- * End: -- emacs
- */
+++ /dev/null
-/*
- * template.h
- * Copyright (C) 2001-2009 Jim Evins <evins@snaught.com>.
- *
- * This file is part of libglabels.
- *
- * libglabels is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libglabels 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __LGL_TEMPLATE_H__
-#define __LGL_TEMPLATE_H__
-
-#include <glib.h>
-#include "units.h"
-
-G_BEGIN_DECLS
-
-typedef struct _lglTemplate lglTemplate;
-
-typedef union _lglTemplateFrame lglTemplateFrame;
-typedef struct _lglTemplateFrameAll lglTemplateFrameAll;
-typedef struct _lglTemplateFrameRect lglTemplateFrameRect;
-typedef struct _lglTemplateFrameEllipse lglTemplateFrameEllipse;
-typedef struct _lglTemplateFrameRound lglTemplateFrameRound;
-typedef struct _lglTemplateFrameCD lglTemplateFrameCD;
-
-typedef struct _lglTemplateLayout lglTemplateLayout;
-
-typedef union _lglTemplateMarkup lglTemplateMarkup;
-typedef struct _lglTemplateMarkupMargin lglTemplateMarkupMargin;
-typedef struct _lglTemplateMarkupLine lglTemplateMarkupLine;
-typedef struct _lglTemplateMarkupCircle lglTemplateMarkupCircle;
-typedef struct _lglTemplateMarkupRect lglTemplateMarkupRect;
-typedef struct _lglTemplateMarkupEllipse lglTemplateMarkupEllipse;
-
-typedef struct _lglTemplateOrigin lglTemplateOrigin;
-
-/*
- * Top-level Template Structure
- */
-struct _lglTemplate {
-
- gchar *brand;
- gchar *part;
- gchar *equiv_part;
-
- gchar *description;
- gchar *paper_id;
- gdouble page_width;
- gdouble page_height;
-
- /* Meta information. */
- gchar *product_url; /* URL to manufacturer's product website. */
- GList *category_ids; /* List of (gchar *) category ids. */
-
- /* List of (lglTemplateFrame *) label frame structures.
- * Currently glabels only supports a single label frame per
- * template. */
- GList *frames;
-
-};
-
-
-/*
- * Possible Frame Shapes
- */
-typedef enum {
- LGL_TEMPLATE_FRAME_SHAPE_RECT,
- LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE,
- LGL_TEMPLATE_FRAME_SHAPE_ROUND,
- LGL_TEMPLATE_FRAME_SHAPE_CD,
-} lglTemplateFrameShape;
-
-
-/*
- * Frame Structure
- */
-struct _lglTemplateFrameAll {
-
- /* Begin Common Fields */
- lglTemplateFrameShape shape;
-
- gchar *id; /* Id, currently always "0" */
- GList *layouts; /* List of lglTemplateLayouts */
- GList *markups; /* List of lglTemplateMarkups */
- /* End Common Fields */
-};
-
-struct _lglTemplateFrameRect {
-
- /* Begin Common Fields */
- lglTemplateFrameShape shape; /* Always LGL_TEMPLATE_FRAME_SHAPE_RECT. */
-
- gchar *id; /* Id, currently always "0" */
- GList *layouts; /* List of lglTemplateLayouts */
- GList *markups; /* List of lglTemplateMarkups */
- /* End Common Fields */
-
- gdouble w; /* Width */
- gdouble h; /* Height */
- gdouble r; /* Corner radius */
- gdouble x_waste; /* Amount of horiz overprint allowed. */
- gdouble y_waste; /* Amount of vert overprint allowed. */
-};
-
-struct _lglTemplateFrameEllipse {
-
- /* Begin Common Fields */
- lglTemplateFrameShape shape; /* Always LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE. */
-
- gchar *id; /* Id, currently always "0" */
- GList *layouts; /* List of lglTemplateLayouts */
- GList *markups; /* List of lglTemplateMarkups */
- /* End Common Fields */
-
- gdouble w; /* Width */
- gdouble h; /* Height */
- gdouble waste; /* Amount of overprint allowed. */
-};
-
-struct _lglTemplateFrameRound {
-
- /* Begin Common Fields */
- lglTemplateFrameShape shape; /* Always LGL_TEMPLATE_FRAME_SHAPE_ROUND. */
-
- gchar *id; /* Id, currently always "0" */
- GList *layouts; /* List of lglTemplateLayouts */
- GList *markups; /* List of lglTemplateMarkups */
- /* End Common Fields */
-
- gdouble r; /* Radius */
- gdouble waste; /* Amount of overprint allowed. */
-};
-
-struct _lglTemplateFrameCD {
-
- /* Begin Common Fields */
- lglTemplateFrameShape shape; /* Always LGL_TEMPLATE_FRAME_SHAPE_CD. */
-
- gchar *id; /* Id, currently always "0" */
- GList *layouts; /* List of lglTemplateLayouts */
- GList *markups; /* List of lglTemplateMarkups */
- /* End Common Fields */
-
- gdouble r1; /* Outer radius */
- gdouble r2; /* Inner radius (hole) */
- gdouble w; /* Clip width, business card CDs */
- gdouble h; /* Clip height, business card CDs */
- gdouble waste; /* Amount of overprint allowed. */
-};
-
-union _lglTemplateFrame{
-
- lglTemplateFrameShape shape;
-
- lglTemplateFrameAll all;
- lglTemplateFrameRect rect;
- lglTemplateFrameEllipse ellipse;
- lglTemplateFrameRound round;
- lglTemplateFrameCD cd;
-};
-
-
-/*
- * Label Layout Structure
- */
-struct _lglTemplateLayout {
-
- gint nx; /* Number of labels across */
- gint ny; /* Number of labels up and down */
-
- gdouble x0; /* Left of grid from left edge of paper */
- gdouble y0; /* Top of grid from top edge of paper */
-
- gdouble dx; /* Horizontal pitch of grid */
- gdouble dy; /* Vertical pitch of grid */
-
-};
-
-
-/*
- * Possible Markup Types
- */
-typedef enum {
- LGL_TEMPLATE_MARKUP_MARGIN,
- LGL_TEMPLATE_MARKUP_LINE,
- LGL_TEMPLATE_MARKUP_CIRCLE,
- LGL_TEMPLATE_MARKUP_RECT,
- LGL_TEMPLATE_MARKUP_ELLIPSE,
-} lglTemplateMarkupType;
-
-
-/*
- * Label Markup Structure (Helpful lines drawn in glabels to help locate objects)
- */
-struct _lglTemplateMarkupMargin {
-
- lglTemplateMarkupType type; /* Always LGL_TEMPLATE_MARKUP_MARGIN */
-
- gdouble size; /* Margin size */
-};
-
-struct _lglTemplateMarkupLine {
-
- lglTemplateMarkupType type; /* Always LGL_TEMPLATE_MARKUP_LINE */
-
- gdouble x1, y1; /* 1st endpoint */
- gdouble x2, y2; /* 2nd endpoint */
-};
-
-struct _lglTemplateMarkupCircle {
-
- lglTemplateMarkupType type; /* Always LGL_TEMPLATE_MARKUP_CIRCLE */
-
- gdouble x0, y0; /* Center of circle */
- gdouble r; /* Radius of circle */
-};
-
-struct _lglTemplateMarkupRect {
-
- lglTemplateMarkupType type; /* Always LGL_TEMPLATE_MARKUP_RECT */
-
- gdouble x1, y1; /* Upper left corner */
- gdouble w, h; /* Width and height. */
- gdouble r; /* Radius of corners. */
-};
-
-struct _lglTemplateMarkupEllipse {
-
- lglTemplateMarkupType type; /* Always LGL_TEMPLATE_MARKUP_ELLIPSE */
-
- gdouble x1, y1; /* Upper left corner */
- gdouble w, h; /* Width and height. */
-};
-
-union _lglTemplateMarkup {
-
- lglTemplateMarkupType type;
-
- lglTemplateMarkupMargin margin;
- lglTemplateMarkupLine line;
- lglTemplateMarkupCircle circle;
- lglTemplateMarkupRect rect;
- lglTemplateMarkupEllipse ellipse;
-};
-
-
-/*
- * Origin coordinates
- */
-struct _lglTemplateOrigin {
-
- gdouble x, y; /* Label origin relative to upper
- * upper left hand corner of paper */
-
-};
-
-
-
-/*
- * Template query functions
- */
-gchar *lgl_template_get_name (const lglTemplate *template);
-
-gboolean lgl_template_do_templates_match (const lglTemplate *template1,
- const lglTemplate *template2);
-
-gboolean lgl_template_does_brand_match (const lglTemplate *template,
- const gchar *brand);
-
-gboolean lgl_template_does_page_size_match (const lglTemplate *template,
- const gchar *paper_id);
-
-gboolean lgl_template_does_category_match (const lglTemplate *template,
- const gchar *category_id);
-
-gboolean lgl_template_are_templates_identical (const lglTemplate *template1,
- const lglTemplate *template2);
-
-
-
-
-/*
- * Frame query functions
- */
-void lgl_template_frame_get_size (const lglTemplateFrame *frame,
- gdouble *w,
- gdouble *h);
-
-gint lgl_template_frame_get_n_labels (const lglTemplateFrame *frame);
-
-lglTemplateOrigin *lgl_template_frame_get_origins (const lglTemplateFrame *frame);
-
-gchar *lgl_template_frame_get_layout_description (const lglTemplateFrame *frame);
-
-gchar *lgl_template_frame_get_size_description (const lglTemplateFrame *frame,
- lglUnits units);
-
-
-
-
-/*
- * Template Construction
- */
-lglTemplate *lgl_template_new (const gchar *brand,
- const gchar *part,
- const gchar *description,
- const gchar *paper_id,
- gdouble page_width,
- gdouble page_height);
-
-lglTemplate *lgl_template_new_from_equiv (const gchar *brand,
- const gchar *part,
- const gchar *equiv_part);
-
-void lgl_template_add_category (lglTemplate *template,
- const gchar *category_id);
-
-void lgl_template_add_frame (lglTemplate *template,
- lglTemplateFrame *frame);
-
-lglTemplateFrame *lgl_template_frame_rect_new (const gchar *id,
- gdouble w,
- gdouble h,
- gdouble r,
- gdouble x_waste,
- gdouble y_waste);
-
-lglTemplateFrame *lgl_template_frame_ellipse_new (const gchar *id,
- gdouble w,
- gdouble h,
- gdouble waste);
-
-lglTemplateFrame *lgl_template_frame_round_new (const gchar *id,
- gdouble r,
- gdouble waste);
-
-lglTemplateFrame *lgl_template_frame_cd_new (const gchar *id,
- gdouble r1,
- gdouble r2,
- gdouble w,
- gdouble h,
- gdouble waste);
-
-void lgl_template_frame_add_layout (lglTemplateFrame *frame,
- lglTemplateLayout *layout);
-
-void lgl_template_frame_add_markup (lglTemplateFrame *frame,
- lglTemplateMarkup *markup);
-
-lglTemplateLayout *lgl_template_layout_new (gint nx,
- gint ny,
- gdouble x0,
- gdouble y0,
- gdouble dx,
- gdouble dy);
-
-lglTemplateMarkup *lgl_template_markup_margin_new (gdouble size);
-
-lglTemplateMarkup *lgl_template_markup_line_new (gdouble x1,
- gdouble y1,
- gdouble x2,
- gdouble y2);
-
-lglTemplateMarkup *lgl_template_markup_circle_new (gdouble x0,
- gdouble y0,
- gdouble r);
-
-lglTemplateMarkup *lgl_template_markup_rect_new (gdouble x1,
- gdouble y1,
- gdouble w,
- gdouble h,
- gdouble r);
-
-lglTemplateMarkup *lgl_template_markup_ellipse_new (gdouble x1,
- gdouble y1,
- gdouble w,
- gdouble h);
-
-lglTemplate *lgl_template_dup (const lglTemplate *orig_template);
-
-void lgl_template_free (lglTemplate *template);
-
-lglTemplateFrame *lgl_template_frame_dup (const lglTemplateFrame *orig_frame);
-void lgl_template_frame_free (lglTemplateFrame *frame);
-
-lglTemplateLayout *lgl_template_layout_dup (const lglTemplateLayout *orig_layout);
-void lgl_template_layout_free (lglTemplateLayout *layout);
-
-lglTemplateMarkup *lgl_template_markup_dup (const lglTemplateMarkup *orig_markup);
-void lgl_template_markup_free (lglTemplateMarkup *markup);
-
-
-/*
- * Debugging functions.
- */
-void lgl_template_print (const lglTemplate *template);
-
-
-G_END_DECLS
-
-#endif /* __LGL_TEMPLATE_H__ */
-
-
-
-/*
- * Local Variables: -- emacs
- * mode: C -- emacs
- * c-basic-offset: 8 -- emacs
- * tab-width: 8 -- emacs
- * indent-tabs-mode: nil -- emacs
- * End: -- emacs
- */
+++ /dev/null
-/*
- * units.c
- * Copyright (C) 2003-2009 Jim Evins <evins@snaught.com>.
- *
- * This file is part of libglabels.
- *
- * libglabels is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libglabels 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-
-#include "units.h"
-
-#include <glib/gi18n.h>
-#include <glib.h>
-#include <string.h>
-
-#include "libglabels-private.h"
-
-
-/*========================================================*/
-/* Private macros and constants. */
-/*========================================================*/
-
-#define POINTS_PER_POINT 1.0 /* internal units are points. */
-#define POINTS_PER_INCH 72.0
-#define POINTS_PER_MM 2.83464566929
-#define POINTS_PER_CM (10.0*POINTS_PER_MM)
-#define POINTS_PER_PICA (1.0/12.0)
-
-
-/*========================================================*/
-/* Private types. */
-/*========================================================*/
-
-typedef struct {
- gchar *id;
- gchar *name;
- gdouble points_per_unit;
-} UnitTableEntry;
-
-
-/*========================================================*/
-/* Private globals. */
-/*========================================================*/
-
-static UnitTableEntry unit_table[] = {
-
- /* The ids are identical to the absolute length units supported in
- the CSS2 Specification (Section 4.3.2) */
-
- /* This table must be sorted exactly as the enumerations in lglUnits */
-
- /* [LGL_UNITS_POINT] */ {"pt", N_("points"), POINTS_PER_POINT},
- /* [LGL_UNITS_INCH] */ {"in", N_("inches"), POINTS_PER_INCH},
- /* [LGL_UNITS_MM] */ {"mm", N_("mm"), POINTS_PER_MM},
- /* [LGL_UNITS_CM] */ {"cm", N_("cm"), POINTS_PER_CM},
- /* [LGL_UNITS_PICA] */ {"pc", N_("picas"), POINTS_PER_PICA},
-
-};
-
-
-
-/**
- * lgl_units_get_id:
- * @units: Units (#lglUnits)
- *
- * Return a unique ID string for the given units. This ID is how units
- * are encoded in libglabels XML files and will remain constant across
- * all locales. IDs are identical to the absolute length units supported
- * in the CSS2 Specification (Section 4.3.2).
- *
- * Returns: ID string.
- *
- */
-const gchar *
-lgl_units_get_id (lglUnits units)
-{
- if ( (units >= LGL_UNITS_FIRST) && (units <= LGL_UNITS_LAST) )
- {
- return unit_table[units].id;
- }
- else
- {
- /* Default to "pt", if invalid. */
- return unit_table[LGL_UNITS_POINT].id;
- }
-}
-
-
-/**
- * lgl_units_from_id:
- * @id: ID string
- *
- * Return the unique #lglUnits for the given ID string.
- * This ID is how units are encoded in libglabels XML files and will remain
- * constant across all locales. IDs are identical to the absolute length
- * units supported in the CSS2 Specification (Section 4.3.2).
- *
- * Returns: units (#lglUnits).
- *
- */
-lglUnits
-lgl_units_from_id (const gchar *id)
-{
- lglUnits units;
-
- /* An empty or missing id defaults to points. */
- if ( (id == NULL) || (strlen (id) == 0) )
- {
- return LGL_UNITS_POINT;
- }
-
- for ( units = LGL_UNITS_FIRST; units <= LGL_UNITS_LAST; units++) {
- if (g_ascii_strcasecmp (id, unit_table[units].id) == 0) {
- return units;
- }
- }
-
- /* Try name as a fallback. (Will catch some legacy preferences.) */
- for ( units = LGL_UNITS_FIRST; units <= LGL_UNITS_LAST; units++) {
- if (g_ascii_strcasecmp (id, unit_table[units].name) == 0) {
- return units;
- }
- }
-
- /* For compatibility with old preferences. */
- if (g_ascii_strcasecmp (id, "Millimeters") == 0) {
- return LGL_UNITS_MM;
- }
-
- return LGL_UNITS_INVALID;
-}
-
-
-/**
- * lgl_units_get_name:
- * @units: Units (#lglUnits)
- *
- * Return a unique name string for the given units. This name is human
- * readable and will be translated to the current locale.
- *
- * Returns: name string.
- *
- */
-const gchar *
-lgl_units_get_name (lglUnits units)
-{
- if ( (units >= LGL_UNITS_FIRST) && (units <= LGL_UNITS_LAST) )
- {
- return gettext ((char *)unit_table[units].name);
- }
- else
- {
- /* Default to "points", if invalid. */
- return gettext ((char *)unit_table[LGL_UNITS_POINT].name);
- }
-}
-
-
-/**
- * lgl_units_from_name:
- * @name: NAME string
- *
- * Return the unique #lglUnits for the given name string. This name is
- * human readable and is expected to be translated to the current locale.
- *
- * Returns: units (#lglUnits).
- *
- */
-lglUnits
-lgl_units_from_name (const gchar *name)
-{
- lglUnits units;
-
- for ( units = LGL_UNITS_FIRST; units <= LGL_UNITS_LAST; units++) {
- if (g_ascii_strcasecmp (name, gettext ((char *)unit_table[units].name) ) == 0) {
- return units;
- }
- }
-
- return LGL_UNITS_INVALID;
-}
-
-
-/**
- * lgl_units_get_points_per_unit:
- * @units: Units (#lglUnits)
- *
- * Return a scale factor for the given units in points/unit.
- *
- * Returns: scale factor.
- *
- */
-gdouble
-lgl_units_get_points_per_unit (lglUnits units)
-{
- if ( (units >= LGL_UNITS_FIRST) && (units <= LGL_UNITS_LAST) )
- {
- return unit_table[units].points_per_unit;
- }
- else
- {
- /* Default to "points", if invalid. */
- return 1.0;
- }
-}
-
-
-/**
- * lgl_units_get_units_per_point:
- * @units: Units (#lglUnits)
- *
- * Return a scale factor for the given units in units/point.
- *
- * Returns: scale factor.
- *
- */
-gdouble
-lgl_units_get_units_per_point (lglUnits units)
-{
- if ( (units >= LGL_UNITS_FIRST) && (units <= LGL_UNITS_LAST) )
- {
- return 1.0 / unit_table[units].points_per_unit;
- }
- else
- {
- /* Default to "points", if invalid. */
- return 1.0;
- }
-}
-
-
-
-
-/*
- * Local Variables: -- emacs
- * mode: C -- emacs
- * c-basic-offset: 8 -- emacs
- * tab-width: 8 -- emacs
- * indent-tabs-mode: nil -- emacs
- * End: -- emacs
- */
+++ /dev/null
-/*
- * units.h
- * Copyright (C) 2003-2009 Jim Evins <evins@snaught.com>.
- *
- * This file is part of libglabels.
- *
- * libglabels is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libglabels 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __LGL_UNITS_H__
-#define __LGL_UNITS_H__
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-
-/*
- * Units of distance
- */
-typedef enum {
- LGL_UNITS_POINT, /* encoded as "pt" */
- LGL_UNITS_INCH, /* encoded as "in" */
- LGL_UNITS_MM, /* encoded as "mm" */
- LGL_UNITS_CM, /* encoded as "cm" */
- LGL_UNITS_PICA, /* encoded as "pc" */
-
- LGL_UNITS_FIRST = LGL_UNITS_POINT,
- LGL_UNITS_LAST = LGL_UNITS_PICA,
-
- LGL_UNITS_INVALID = -1,
-} lglUnits;
-
-
-const gchar *lgl_units_get_id (lglUnits units);
-lglUnits lgl_units_from_id (const gchar *id);
-
-const gchar *lgl_units_get_name (lglUnits units);
-lglUnits lgl_units_from_name (const gchar *name);
-
-gdouble lgl_units_get_points_per_unit (lglUnits units);
-gdouble lgl_units_get_units_per_point (lglUnits units);
-
-
-G_END_DECLS
-
-
-#endif /* __LGL_UNITS_H__ */
-
-
-
-/*
- * Local Variables: -- emacs
- * mode: C -- emacs
- * c-basic-offset: 8 -- emacs
- * tab-width: 8 -- emacs
- * indent-tabs-mode: nil -- emacs
- * End: -- emacs
- */
+++ /dev/null
-/*
- * vendor.c
- * Copyright (C) 2003-2009 Jim Evins <evins@snaught.com>.
- *
- * This file is part of libglabels.
- *
- * libglabels is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libglabels 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-
-#include "vendor.h"
-
-#include <glib/gi18n.h>
-#include <glib.h>
-#include <string.h>
-
-#include "libglabels-private.h"
-
-/*===========================================*/
-/* Private types */
-/*===========================================*/
-
-
-/*===========================================*/
-/* Private globals */
-/*===========================================*/
-
-
-/*===========================================*/
-/* Local function prototypes */
-/*===========================================*/
-
-
-/*===========================================*/
-/* Functions. */
-/*===========================================*/
-
-/**
- * lgl_vendor_new:
- * @name: Localized name of vendor.
- *
- * Allocates and constructs a new #lglVendor structure.
- *
- * Returns: a pointer to a newly allocated #lglVendor structure.
- *
- */
-lglVendor *
-lgl_vendor_new (gchar *name)
-{
- lglVendor *vendor;
-
- vendor = g_new0 (lglVendor,1);
-
- vendor->name = g_strdup (name);
-
- return vendor;
-}
-
-
-/**
- * lgl_vendor_dup:
- * @orig: #lglVendor structure to be duplicated.
- *
- * Duplicates an existing #lglVendor structure.
- *
- * Returns: a pointer to a newly allocated #lglVendor structure.
- *
- */
-lglVendor *lgl_vendor_dup (const lglVendor *orig)
-{
- lglVendor *vendor;
-
- g_return_val_if_fail (orig, NULL);
-
- vendor = g_new0 (lglVendor,1);
-
- vendor->name = g_strdup (orig->name);
- vendor->url = g_strdup (orig->url);
-
- return vendor;
-}
-
-
-/**
- * lgl_vendor_free:
- * @vendor: pointer to #lglVendor structure to be freed.
- *
- * Free all memory associated with an existing #lglVendor structure.
- *
- */
-void lgl_vendor_free (lglVendor *vendor)
-{
-
- if ( vendor != NULL ) {
-
- g_free (vendor->name);
- vendor->name = NULL;
-
- g_free (vendor->url);
- vendor->url = NULL;
-
- g_free (vendor);
- }
-
-}
-
-
-
-/*
- * Local Variables: -- emacs
- * mode: C -- emacs
- * c-basic-offset: 8 -- emacs
- * tab-width: 8 -- emacs
- * indent-tabs-mode: nil -- emacs
- * End: -- emacs
- */
+++ /dev/null
-/*
- * vendor.h
- * Copyright (C) 2003-2009 Jim Evins <evins@snaught.com>.
- *
- * This file is part of libglabels.
- *
- * libglabels is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libglabels 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __LGL_VENDOR_H__
-#define __LGL_VENDOR_H__
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-
-/*
- * lglVendor structure
- */
-typedef struct _lglVendor lglVendor;
-
-struct _lglVendor {
- gchar *name; /* Vendor name */
- gchar *url; /* Vendor URL */
-};
-
-
-/*
- * Vendor construction
- */
-lglVendor *lgl_vendor_new (gchar *name);
-
-lglVendor *lgl_vendor_dup (const lglVendor *orig);
-
-void lgl_vendor_free (lglVendor *vendor);
-
-
-G_END_DECLS
-
-#endif /* __LGL_VENDOR_H__ */
-
-
-
-/*
- * Local Variables: -- emacs
- * mode: C -- emacs
- * c-basic-offset: 8 -- emacs
- * tab-width: 8 -- emacs
- * indent-tabs-mode: nil -- emacs
- * End: -- emacs
- */
+++ /dev/null
-/*
- * xml-category.c
- * Copyright (C) 2006-2009 Jim Evins <evins@snaught.com>.
- *
- * This file is part of libglabels.
- *
- * libglabels is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libglabels 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-
-#include "xml-category.h"
-
-#include <glib/gi18n.h>
-#include <glib.h>
-#include <string.h>
-#include <libintl.h>
-
-#include "libglabels-private.h"
-
-#include "xml.h"
-
-/*===========================================*/
-/* Private types */
-/*===========================================*/
-
-/*===========================================*/
-/* Private globals */
-/*===========================================*/
-
-/*===========================================*/
-/* Local function prototypes */
-/*===========================================*/
-
-
-/**
- * lgl_xml_category_read_categories_from_file:
- * @utf8_filename: Filename of categories file (name encoded as UTF-8)
- *
- * Read category definitions from a file.
- *
- * Returns: a list of #lglCategory structures.
- *
- */
-GList *
-lgl_xml_category_read_categories_from_file (gchar *utf8_filename)
-{
- gchar *filename;
- GList *categories;
- xmlDocPtr categories_doc;
-
- LIBXML_TEST_VERSION;
-
- filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
- if (!filename) {
- g_message ("Utf8 filename conversion error");
- return NULL;
- }
-
- categories_doc = xmlParseFile (filename);
- if (!categories_doc) {
- g_message ("\"%s\" is not a glabels category file (not XML)",
- filename);
- return NULL;
- }
-
- categories = lgl_xml_category_parse_categories_doc (categories_doc);
-
- g_free (filename);
- xmlFreeDoc (categories_doc);
-
- return categories;
-}
-
-
-/**
- * lgl_xml_category_parse_categories_doc:
- * @categories_doc: libxml #xmlDocPtr tree, representing a categories
- * definition file.
- *
- * Read category definitions from a libxml #xmlDocPtr tree.
- *
- * Returns: a list of #lglCategory structures.
- *
- */
-GList *
-lgl_xml_category_parse_categories_doc (xmlDocPtr categories_doc)
-{
- GList *categories = NULL;
- xmlNodePtr root, node;
- lglCategory *category;
-
- LIBXML_TEST_VERSION;
-
- root = xmlDocGetRootElement (categories_doc);
- if (!root || !root->name) {
- g_message ("\"%s\" is not a glabels category file (no root node)",
- categories_doc->name);
- xmlFreeDoc (categories_doc);
- return categories;
- }
- if (!lgl_xml_is_node (root, "Glabels-categories")) {
- g_message ("\"%s\" is not a glabels category file (wrong root node)",
- categories_doc->name);
- xmlFreeDoc (categories_doc);
- return categories;
- }
-
- for (node = root->xmlChildrenNode; node != NULL; node = node->next) {
-
- if (lgl_xml_is_node (node, "Category")) {
- category = lgl_xml_category_parse_category_node (node);
- categories = g_list_append (categories, category);
- } else {
- if ( !xmlNodeIsText(node) ) {
- if (!lgl_xml_is_node (node, "comment")) {
- g_message ("bad node = \"%s\"",node->name);
- }
- }
- }
- }
-
- return categories;
-}
-
-
-/**
- * lgl_xml_category_parse_category_node:
- * @category_node: libxml #xmlNodePtr category node from a #xmlDocPtr tree.
- *
- * Read a single category definition from a libxml #xmlNodePtr node.
- *
- * Returns: a pointer to a newly created #lglCategory structure.
- *
- */
-lglCategory *
-lgl_xml_category_parse_category_node (xmlNodePtr category_node)
-{
- lglCategory *category;
- gchar *id, *name;
-
- LIBXML_TEST_VERSION;
-
- id = lgl_xml_get_prop_string (category_node, "id", NULL);
- name = lgl_xml_get_prop_i18n_string (category_node, "name", NULL);
-
- category = lgl_category_new (id, name);
-
- g_free (id);
- g_free (name);
-
- return category;
-}
-
-
-
-/*
- * Local Variables: -- emacs
- * mode: C -- emacs
- * c-basic-offset: 8 -- emacs
- * tab-width: 8 -- emacs
- * indent-tabs-mode: nil -- emacs
- * End: -- emacs
- */
+++ /dev/null
-/*
- * xml-category.h
- * Copyright (C) 2006-2009 Jim Evins <evins@snaught.com>.
- *
- * This file is part of libglabels.
- *
- * libglabels is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libglabels 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __LGL_XML_CATEGORY_H__
-#define __LGL_XML_CATEGORY_H__
-
-#include <glib.h>
-#include <libxml/tree.h>
-
-#include "category.h"
-
-G_BEGIN_DECLS
-
-GList *lgl_xml_category_read_categories_from_file (gchar *utf8_filename);
-
-GList *lgl_xml_category_parse_categories_doc (xmlDocPtr categories_doc);
-
-lglCategory *lgl_xml_category_parse_category_node (xmlNodePtr category_node);
-
-
-G_END_DECLS
-
-#endif /* __LGL_XML_CATEGORY_H__ */
-
-
-
-/*
- * Local Variables: -- emacs
- * mode: C -- emacs
- * c-basic-offset: 8 -- emacs
- * tab-width: 8 -- emacs
- * indent-tabs-mode: nil -- emacs
- * End: -- emacs
- */
+++ /dev/null
-/*
- * xml-paper.c
- * Copyright (C) 2003-2009 Jim Evins <evins@snaught.com>.
- *
- * This file is part of libglabels.
- *
- * libglabels is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libglabels 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-
-#include "xml-paper.h"
-
-#include <glib/gi18n.h>
-#include <glib.h>
-#include <string.h>
-#include <libintl.h>
-
-#include "libglabels-private.h"
-
-#include "xml.h"
-
-/*===========================================*/
-/* Private types */
-/*===========================================*/
-
-/*===========================================*/
-/* Private globals */
-/*===========================================*/
-
-/*===========================================*/
-/* Local function prototypes */
-/*===========================================*/
-
-
-/**
- * lgl_xml_paper_read_papers_from_file:
- * @utf8_filename: Filename of papers file (name encoded as UTF-8)
- *
- * Read paper definitions from a file.
- *
- * Returns: a list of #lglPaper structures.
- *
- */
-GList *
-lgl_xml_paper_read_papers_from_file (gchar *utf8_filename)
-{
- gchar *filename;
- GList *papers;
- xmlDocPtr papers_doc;
-
- LIBXML_TEST_VERSION;
-
- filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
- if (!filename) {
- g_message ("Utf8 filename conversion error");
- return NULL;
- }
-
- papers_doc = xmlParseFile (filename);
- if (!papers_doc) {
- g_message ("\"%s\" is not a glabels paper file (not XML)",
- filename);
- return NULL;
- }
-
- papers = lgl_xml_paper_parse_papers_doc (papers_doc);
-
- g_free (filename);
- xmlFreeDoc (papers_doc);
-
- return papers;
-}
-
-
-/**
- * lgl_xml_paper_parse_papers_doc:
- * @papers_doc: libxml #xmlDocPtr tree, representing a papers definition file.
- *
- * Read paper definitions from a libxml #xmlDocPtr tree.
- *
- * Returns: a list of #lglPaper structures.
- *
- */
-GList *
-lgl_xml_paper_parse_papers_doc (xmlDocPtr papers_doc)
-{
- GList *papers = NULL;
- xmlNodePtr root, node;
- lglPaper *paper;
-
- LIBXML_TEST_VERSION;
-
- root = xmlDocGetRootElement (papers_doc);
- if (!root || !root->name) {
- g_message ("\"%s\" is not a glabels paper file (no root node)",
- papers_doc->name);
- xmlFreeDoc (papers_doc);
- return papers;
- }
- if (!lgl_xml_is_node (root, "Glabels-paper-sizes")) {
- g_message ("\"%s\" is not a glabels paper file (wrong root node)",
- papers_doc->name);
- xmlFreeDoc (papers_doc);
- return papers;
- }
-
- for (node = root->xmlChildrenNode; node != NULL; node = node->next) {
-
- if (lgl_xml_is_node (node, "Paper-size")) {
- paper = lgl_xml_paper_parse_paper_node (node);
- papers = g_list_append (papers, paper);
- } else {
- if ( !xmlNodeIsText(node) ) {
- if (!lgl_xml_is_node (node, "comment")) {
- g_message ("bad node = \"%s\"",node->name);
- }
- }
- }
- }
-
- return papers;
-}
-
-
-/**
- * lgl_xml_paper_parse_paper_node:
- * @paper_node: libxml #xmlNodePtr paper node from a #xmlDocPtr tree.
- *
- * Read a single paper definition from a libxml #xmlNodePtr node.
- *
- * Returns: a pointer to a newly created #lglPaper structure.
- *
- */
-lglPaper *
-lgl_xml_paper_parse_paper_node (xmlNodePtr paper_node)
-{
- lglPaper *paper;
- gchar *id, *name, *pwg_size;
- gdouble width, height;
-
- LIBXML_TEST_VERSION;
-
- id = lgl_xml_get_prop_string (paper_node, "id", NULL);
-
- name = lgl_xml_get_prop_i18n_string (paper_node, "name", NULL);
-
- width = lgl_xml_get_prop_length (paper_node, "width", 0);
- height = lgl_xml_get_prop_length (paper_node, "height", 0);
-
- pwg_size = lgl_xml_get_prop_string (paper_node, "pwg_size", NULL);
-
- paper = lgl_paper_new (id, name, width, height, pwg_size);
-
- g_free (id);
- g_free (name);
- g_free (pwg_size);
-
- return paper;
-}
-
-
-
-/*
- * Local Variables: -- emacs
- * mode: C -- emacs
- * c-basic-offset: 8 -- emacs
- * tab-width: 8 -- emacs
- * indent-tabs-mode: nil -- emacs
- * End: -- emacs
- */
+++ /dev/null
-/*
- * xml-paper.h
- * Copyright (C) 2003-2009 Jim Evins <evins@snaught.com>.
- *
- * This file is part of libglabels.
- *
- * libglabels is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libglabels 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __LGL_XML_PAPER_H__
-#define __LGL_XML_PAPER_H__
-
-#include <glib.h>
-#include <libxml/tree.h>
-
-#include "paper.h"
-
-G_BEGIN_DECLS
-
-GList *lgl_xml_paper_read_papers_from_file (gchar *utf8_filename);
-
-GList *lgl_xml_paper_parse_papers_doc (xmlDocPtr papers_doc);
-
-lglPaper *lgl_xml_paper_parse_paper_node (xmlNodePtr paper_node);
-
-
-G_END_DECLS
-
-#endif /* __LGL_XML_PAPER_H__ */
-
-
-
-/*
- * Local Variables: -- emacs
- * mode: C -- emacs
- * c-basic-offset: 8 -- emacs
- * tab-width: 8 -- emacs
- * indent-tabs-mode: nil -- emacs
- * End: -- emacs
- */
+++ /dev/null
-/*
- * xml-template.c
- * Copyright (C) 2001-2009 Jim Evins <evins@snaught.com>.
- *
- * This file is part of libglabels.
- *
- * libglabels is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libglabels 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-
-#include "xml-template.h"
-
-#include <glib/gi18n.h>
-#include <glib.h>
-#include <string.h>
-#include <libintl.h>
-
-#include "libglabels-private.h"
-
-#include "db.h"
-#include "xml.h"
-
-/*===========================================*/
-/* Private types */
-/*===========================================*/
-
-/*===========================================*/
-/* Private globals */
-/*===========================================*/
-
-/*===========================================*/
-/* Local function prototypes */
-/*===========================================*/
-static void xml_parse_meta_node (xmlNodePtr label_node,
- lglTemplate *template);
-static void xml_parse_label_rectangle_node (xmlNodePtr label_node,
- lglTemplate *template);
-static void xml_parse_label_ellipse_node (xmlNodePtr label_node,
- lglTemplate *template);
-static void xml_parse_label_round_node (xmlNodePtr label_node,
- lglTemplate *template);
-static void xml_parse_label_cd_node (xmlNodePtr label_node,
- lglTemplate *template);
-static void xml_parse_layout_node (xmlNodePtr layout_node,
- lglTemplateFrame *frame);
-static void xml_parse_markup_margin_node (xmlNodePtr markup_node,
- lglTemplateFrame *frame);
-static void xml_parse_markup_line_node (xmlNodePtr markup_node,
- lglTemplateFrame *frame);
-static void xml_parse_markup_circle_node (xmlNodePtr markup_node,
- lglTemplateFrame *frame);
-static void xml_parse_markup_rect_node (xmlNodePtr markup_node,
- lglTemplateFrame *frame);
-static void xml_parse_markup_ellipse_node (xmlNodePtr markup_node,
- lglTemplateFrame *frame);
-static void xml_parse_alias_node (xmlNodePtr alias_node,
- lglTemplate *template);
-
-static void xml_create_meta_node (const gchar *attr,
- const gchar *value,
- xmlNodePtr root,
- const xmlNsPtr ns);
-static void xml_create_label_node (const lglTemplateFrame *frame,
- xmlNodePtr root,
- const xmlNsPtr ns);
-static void xml_create_layout_node (const lglTemplateLayout *layout,
- xmlNodePtr root,
- const xmlNsPtr ns);
-static void xml_create_markup_margin_node (const lglTemplateMarkup *margin,
- xmlNodePtr root,
- const xmlNsPtr ns);
-static void xml_create_markup_line_node (const lglTemplateMarkup *line,
- xmlNodePtr root,
- const xmlNsPtr ns);
-static void xml_create_markup_circle_node (const lglTemplateMarkup *circle,
- xmlNodePtr root,
- const xmlNsPtr ns);
-static void xml_create_markup_rect_node (const lglTemplateMarkup *circle,
- xmlNodePtr root,
- const xmlNsPtr ns);
-static void xml_create_markup_ellipse_node (const lglTemplateMarkup *circle,
- xmlNodePtr root,
- const xmlNsPtr ns);
-
-
-/**
- * lgl_xml_template_read_templates_from_file:
- * @utf8_filename: Filename of papers file (name encoded as UTF-8)
- *
- * Read glabels templates from template file.
- *
- */
-void
-lgl_xml_template_read_templates_from_file (const gchar *utf8_filename)
-{
- gchar *filename;
- xmlDocPtr templates_doc;
-
- LIBXML_TEST_VERSION;
-
- filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
- if (!filename) {
- g_message ("Utf8 filename conversion error");
- return;
- }
-
- templates_doc = xmlParseFile (filename);
- if (!templates_doc) {
- g_message ("\"%s\" is not a glabels template file (not XML)",
- filename);
- return;
- }
-
- lgl_xml_template_parse_templates_doc (templates_doc);
-
- g_free (filename);
- xmlFreeDoc (templates_doc);
-}
-
-
-/**
- * lgl_xml_template_parse_templates_doc:
- * @templates_doc: libxml #xmlDocPtr tree, representing template file.
- *
- * Read glabels templates from a libxml #xmlDocPtr tree.
- *
- */
-void
-lgl_xml_template_parse_templates_doc (const xmlDocPtr templates_doc)
-{
-
- xmlNodePtr root, node;
- lglTemplate *template;
-
- LIBXML_TEST_VERSION;
-
- root = xmlDocGetRootElement (templates_doc);
- if (!root || !root->name)
- {
- g_message ("\"%s\" is not a glabels template file (no root node)",
- templates_doc->URL);
- return;
- }
- if (!lgl_xml_is_node (root, "Glabels-templates"))
- {
- g_message ("\"%s\" is not a glabels template file (wrong root node)",
- templates_doc->URL);
- return;
- }
-
- for (node = root->xmlChildrenNode; node != NULL; node = node->next)
- {
-
- if (lgl_xml_is_node (node, "Template"))
- {
- template = lgl_xml_template_parse_template_node (node);
- if (template)
- {
- _lgl_db_register_template_internal (template);
- lgl_template_free (template);
- }
- }
- else
- {
- if ( !xmlNodeIsText(node) )
- {
- if (!lgl_xml_is_node (node,"comment"))
- {
- g_message ("bad node = \"%s\"",node->name);
- }
- }
- }
- }
-}
-
-
-/**
- * lgl_xml_template_parse_template_node:
- * @template_node: libxml #xmlNodePtr template node from a #xmlDocPtr tree.
- *
- * Read a single glabels template from a libxml #xmlNodePtr node.
- *
- * Returns: a pointer to a newly created #lglTemplate structure.
- *
- */
-lglTemplate *
-lgl_xml_template_parse_template_node (const xmlNodePtr template_node)
-{
- gchar *brand;
- gchar *part;
- gchar *name;
- gchar *equiv_part;
- gchar *description;
- gchar *paper_id;
- gdouble page_width, page_height;
- lglPaper *paper = NULL;
- lglTemplate *template;
- xmlNodePtr node;
- gchar **v;
- lglTemplateFrame *frame;
-
-
- brand = lgl_xml_get_prop_string (template_node, "brand", NULL);
- part = lgl_xml_get_prop_string (template_node, "part", NULL);
- if (!brand || !part)
- {
- name = lgl_xml_get_prop_string (template_node, "name", NULL);
- if (name)
- {
- v = g_strsplit (name, " ", 2);
- brand = g_strdup (v[0]);
- part = g_strchug (g_strdup (v[1]));
- g_free (name);
- g_strfreev (v);
-
- }
- else
- {
- g_message ("Missing name or brand/part attributes.");
- }
- }
-
-
- equiv_part = lgl_xml_get_prop_string (template_node, "equiv", NULL);
-
-
- description = lgl_xml_get_prop_i18n_string (template_node, "description", NULL);
- paper_id = lgl_xml_get_prop_string (template_node, "size", NULL);
-
- if (lgl_db_is_paper_id_other (paper_id)) {
-
- page_width = lgl_xml_get_prop_length (template_node, "width", 0);
- page_height = lgl_xml_get_prop_length (template_node, "height", 0);
-
- } else {
- paper = lgl_db_lookup_paper_from_id (paper_id);
- if (paper == NULL) {
- /* This should always be an id, but just in case a name
- slips by! */
- g_message ("Unknown page size id \"%s\", trying as name",
- paper_id);
- paper = lgl_db_lookup_paper_from_name (paper_id);
- g_free (paper_id);
- paper_id = g_strdup (paper->id);
- }
- if (paper != NULL) {
- page_width = paper->width;
- page_height = paper->height;
- } else {
- page_width = 612;
- page_height = 792;
- g_message ("Unknown page size id or name \"%s\"",
- paper_id);
- }
- lgl_paper_free (paper);
- paper = NULL;
- }
-
-
- if (!equiv_part)
- {
- template = lgl_template_new (brand, part, description,
- paper_id, page_width, page_height);
- }
- else
- {
- template = lgl_template_new_from_equiv (brand, part, equiv_part);
-
- if (!template)
- {
- g_message ("Forward references not supported.");
- return NULL;
- }
- }
-
-
- for (node = template_node->xmlChildrenNode; node != NULL;
- node = node->next) {
- if (lgl_xml_is_node (node, "Meta")) {
- xml_parse_meta_node (node, template);
- } else if (lgl_xml_is_node (node, "Label-rectangle")) {
- xml_parse_label_rectangle_node (node, template);
- } else if (lgl_xml_is_node (node, "Label-ellipse")) {
- xml_parse_label_ellipse_node (node, template);
- } else if (lgl_xml_is_node (node, "Label-round")) {
- xml_parse_label_round_node (node, template);
- } else if (lgl_xml_is_node (node, "Label-cd")) {
- xml_parse_label_cd_node (node, template);
- } else if (lgl_xml_is_node (node, "Alias")) {
- xml_parse_alias_node (node, template);
- } else {
- if (!xmlNodeIsText (node)) {
- if (!lgl_xml_is_node (node,"comment")) {
- g_message ("bad node = \"%s\"",node->name);
- }
- }
- }
- }
-
- g_free (brand);
- g_free (part);
- g_free (equiv_part);
- g_free (description);
- g_free (paper_id);
-
- /*
- * Create a default full-page frame, if a known frame type was not found.
- */
- if ( template->frames == NULL )
- {
- g_message ("%s %s: missing valid frame node", template->brand, template->part);
- frame = lgl_template_frame_rect_new ("0", page_width, page_height, 0, 0, 0);
- lgl_template_frame_add_layout (frame, lgl_template_layout_new (1, 1, 0, 0, 0, 0));
- lgl_template_add_frame (template, frame);
- }
-
- /*
- * Create a default 1x1 layout, if layout is missing.
- */
- frame = (lglTemplateFrame *)template->frames->data;
- if ( frame->all.layouts == NULL )
- {
- g_message ("%s %s: missing layout node", template->brand, template->part);
- lgl_template_frame_add_layout (frame, lgl_template_layout_new (1, 1, 0, 0, 0, 0));
- }
-
- return template;
-}
-
-/*--------------------------------------------------------------------------*/
-/* PRIVATE. Parse XML Template->Meta Node. */
-/*--------------------------------------------------------------------------*/
-static void
-xml_parse_meta_node (xmlNodePtr meta_node,
- lglTemplate *template)
-{
- gchar *product_url;
- gchar *category;
-
- product_url = lgl_xml_get_prop_string (meta_node, "product_url", NULL);
- if ( product_url != NULL )
- {
- g_free (template->product_url);
- template->product_url = product_url;
- }
-
- category = lgl_xml_get_prop_string (meta_node, "category", NULL);
- if ( category != NULL )
- {
- lgl_template_add_category (template, category);
- g_free (category);
- }
-}
-
-
-/*--------------------------------------------------------------------------*/
-/* PRIVATE. Parse XML Template->Label-rectangle Node. */
-/*--------------------------------------------------------------------------*/
-static void
-xml_parse_label_rectangle_node (xmlNodePtr label_node,
- lglTemplate *template)
-{
- gchar *id;
- gchar *tmp;
- gdouble x_waste, y_waste;
- gdouble w, h, r;
- lglTemplateFrame *frame;
- xmlNodePtr node;
-
- id = lgl_xml_get_prop_string (label_node, "id", NULL);
-
- if ((tmp = lgl_xml_get_prop_string (label_node, "waste", NULL))) {
- /* Handle single "waste" property. */
- x_waste = y_waste = lgl_xml_get_prop_length (label_node, "waste", 0);
- g_free (tmp);
- } else {
- x_waste = lgl_xml_get_prop_length (label_node, "x_waste", 0);
- y_waste = lgl_xml_get_prop_length (label_node, "y_waste", 0);
- }
-
- w = lgl_xml_get_prop_length (label_node, "width", 0);
- h = lgl_xml_get_prop_length (label_node, "height", 0);
- r = lgl_xml_get_prop_length (label_node, "round", 0);
-
- frame = lgl_template_frame_rect_new ((gchar *)id, w, h, r, x_waste, y_waste);
- lgl_template_add_frame (template, frame);
-
- for (node = label_node->xmlChildrenNode; node != NULL;
- node = node->next) {
- if (lgl_xml_is_node (node, "Layout")) {
- xml_parse_layout_node (node, frame);
- } else if (lgl_xml_is_node (node, "Markup-margin")) {
- xml_parse_markup_margin_node (node, frame);
- } else if (lgl_xml_is_node (node, "Markup-line")) {
- xml_parse_markup_line_node (node, frame);
- } else if (lgl_xml_is_node (node, "Markup-circle")) {
- xml_parse_markup_circle_node (node, frame);
- } else if (lgl_xml_is_node (node, "Markup-rect")) {
- xml_parse_markup_rect_node (node, frame);
- } else if (lgl_xml_is_node (node, "Markup-ellipse")) {
- xml_parse_markup_ellipse_node (node, frame);
- } else if (!xmlNodeIsText (node)) {
- if (!lgl_xml_is_node (node, "comment")) {
- g_message ("bad node = \"%s\"",node->name);
- }
- }
- }
-
- g_free (id);
-}
-
-
-/*--------------------------------------------------------------------------*/
-/* PRIVATE. Parse XML Template->Label-ellipse Node. */
-/*--------------------------------------------------------------------------*/
-static void
-xml_parse_label_ellipse_node (xmlNodePtr label_node,
- lglTemplate *template)
-{
- gchar *id;
- gdouble waste;
- gdouble w, h;
- lglTemplateFrame *frame;
- xmlNodePtr node;
-
- id = lgl_xml_get_prop_string (label_node, "id", NULL);
-
- w = lgl_xml_get_prop_length (label_node, "width", 0);
- h = lgl_xml_get_prop_length (label_node, "height", 0);
- waste = lgl_xml_get_prop_length (label_node, "waste", 0);
-
- frame = lgl_template_frame_ellipse_new ((gchar *)id, w, h, waste);
- lgl_template_add_frame (template, frame);
-
- for (node = label_node->xmlChildrenNode; node != NULL;
- node = node->next) {
- if (lgl_xml_is_node (node, "Layout")) {
- xml_parse_layout_node (node, frame);
- } else if (lgl_xml_is_node (node, "Markup-margin")) {
- xml_parse_markup_margin_node (node, frame);
- } else if (lgl_xml_is_node (node, "Markup-line")) {
- xml_parse_markup_line_node (node, frame);
- } else if (lgl_xml_is_node (node, "Markup-circle")) {
- xml_parse_markup_circle_node (node, frame);
- } else if (lgl_xml_is_node (node, "Markup-rect")) {
- xml_parse_markup_rect_node (node, frame);
- } else if (lgl_xml_is_node (node, "Markup-ellipse")) {
- xml_parse_markup_ellipse_node (node, frame);
- } else if (!xmlNodeIsText (node)) {
- if (!lgl_xml_is_node (node, "comment")) {
- g_message ("bad node = \"%s\"",node->name);
- }
- }
- }
-
- g_free (id);
-}
-
-
-/*--------------------------------------------------------------------------*/
-/* PRIVATE. Parse XML Template->Label-round Node. */
-/*--------------------------------------------------------------------------*/
-static void
-xml_parse_label_round_node (xmlNodePtr label_node,
- lglTemplate *template)
-{
- gchar *id;
- gdouble waste;
- gdouble r;
- lglTemplateFrame *frame;
- xmlNodePtr node;
-
- id = lgl_xml_get_prop_string (label_node, "id", NULL);
- waste = lgl_xml_get_prop_length (label_node, "waste", 0);
- r = lgl_xml_get_prop_length (label_node, "radius", 0);
-
- frame = lgl_template_frame_round_new ((gchar *)id, r, waste);
- lgl_template_add_frame (template, frame);
-
- for (node = label_node->xmlChildrenNode; node != NULL;
- node = node->next) {
- if (lgl_xml_is_node (node, "Layout")) {
- xml_parse_layout_node (node, frame);
- } else if (lgl_xml_is_node (node, "Markup-margin")) {
- xml_parse_markup_margin_node (node, frame);
- } else if (lgl_xml_is_node (node, "Markup-line")) {
- xml_parse_markup_line_node (node, frame);
- } else if (lgl_xml_is_node (node, "Markup-circle")) {
- xml_parse_markup_circle_node (node, frame);
- } else if (lgl_xml_is_node (node, "Markup-rect")) {
- xml_parse_markup_rect_node (node, frame);
- } else if (lgl_xml_is_node (node, "Markup-ellipse")) {
- xml_parse_markup_ellipse_node (node, frame);
- } else if (!xmlNodeIsText (node)) {
- if (!lgl_xml_is_node (node, "comment")) {
- g_message ("bad node = \"%s\"",node->name);
- }
- }
- }
-
- g_free (id);
-}
-
-/*--------------------------------------------------------------------------*/
-/* PRIVATE. Parse XML Template->Label-cd Node. */
-/*--------------------------------------------------------------------------*/
-static void
-xml_parse_label_cd_node (xmlNodePtr label_node,
- lglTemplate *template)
-{
- gchar *id;
- gdouble waste;
- gdouble r1, r2, w, h;
- lglTemplateFrame *frame;
- xmlNodePtr node;
-
- id = lgl_xml_get_prop_string (label_node, "id", NULL);
- waste = lgl_xml_get_prop_length (label_node, "waste", 0);
- r1 = lgl_xml_get_prop_length (label_node, "radius", 0);
- r2 = lgl_xml_get_prop_length (label_node, "hole", 0);
- w = lgl_xml_get_prop_length (label_node, "width", 0);
- h = lgl_xml_get_prop_length (label_node, "height", 0);
-
- frame = lgl_template_frame_cd_new ((gchar *)id, r1, r2, w, h, waste);
- lgl_template_add_frame (template, frame);
-
- for (node = label_node->xmlChildrenNode; node != NULL;
- node = node->next) {
- if (lgl_xml_is_node (node, "Layout")) {
- xml_parse_layout_node (node, frame);
- } else if (lgl_xml_is_node (node, "Markup-margin")) {
- xml_parse_markup_margin_node (node, frame);
- } else if (lgl_xml_is_node (node, "Markup-line")) {
- xml_parse_markup_line_node (node, frame);
- } else if (lgl_xml_is_node (node, "Markup-circle")) {
- xml_parse_markup_circle_node (node, frame);
- } else if (lgl_xml_is_node (node, "Markup-rect")) {
- xml_parse_markup_rect_node (node, frame);
- } else if (lgl_xml_is_node (node, "Markup-ellipse")) {
- xml_parse_markup_ellipse_node (node, frame);
- } else if (!xmlNodeIsText (node)) {
- if (!lgl_xml_is_node (node, "comment")) {
- g_message ("bad node = \"%s\"",node->name);
- }
- }
- }
-
- g_free (id);
-}
-
-/*--------------------------------------------------------------------------*/
-/* PRIVATE. Parse XML Template->Label->Layout Node. */
-/*--------------------------------------------------------------------------*/
-static void
-xml_parse_layout_node (xmlNodePtr layout_node,
- lglTemplateFrame *frame)
-{
- gint nx, ny;
- gdouble x0, y0, dx, dy;
- xmlNodePtr node;
-
- nx = lgl_xml_get_prop_int (layout_node, "nx", 1);
- ny = lgl_xml_get_prop_int (layout_node, "ny", 1);
-
- x0 = lgl_xml_get_prop_length (layout_node, "x0", 0);
- y0 = lgl_xml_get_prop_length (layout_node, "y0", 0);
-
- dx = lgl_xml_get_prop_length (layout_node, "dx", 0);
- dy = lgl_xml_get_prop_length (layout_node, "dy", 0);
-
- lgl_template_frame_add_layout (frame, lgl_template_layout_new (nx, ny, x0, y0, dx, dy));
-
- for (node = layout_node->xmlChildrenNode; node != NULL;
- node = node->next) {
- if (!xmlNodeIsText (node)) {
- if (!lgl_xml_is_node (node, "comment")) {
- g_message ("bad node = \"%s\"",node->name);
- }
- }
- }
-
-}
-
-/*--------------------------------------------------------------------------*/
-/* PRIVATE. Parse XML Template->Label->Markup-margin Node. */
-/*--------------------------------------------------------------------------*/
-static void
-xml_parse_markup_margin_node (xmlNodePtr markup_node,
- lglTemplateFrame *frame)
-{
- gdouble size;
- xmlNodePtr node;
-
- size = lgl_xml_get_prop_length (markup_node, "size", 0);
-
- lgl_template_frame_add_markup (frame, lgl_template_markup_margin_new (size));
-
- for (node = markup_node->xmlChildrenNode; node != NULL;
- node = node->next) {
- if (!xmlNodeIsText (node)) {
- if (!lgl_xml_is_node (node, "comment")) {
- g_message ("bad node = \"%s\"",node->name);
- }
- }
- }
-
-}
-
-/*--------------------------------------------------------------------------*/
-/* PRIVATE. Parse XML Template->Label->Markup-line Node. */
-/*--------------------------------------------------------------------------*/
-static void
-xml_parse_markup_line_node (xmlNodePtr markup_node,
- lglTemplateFrame *frame)
-{
- gdouble x1, y1, x2, y2;
- xmlNodePtr node;
-
- x1 = lgl_xml_get_prop_length (markup_node, "x1", 0);
- y1 = lgl_xml_get_prop_length (markup_node, "y1", 0);
- x2 = lgl_xml_get_prop_length (markup_node, "x2", 0);
- y2 = lgl_xml_get_prop_length (markup_node, "y2", 0);
-
- lgl_template_frame_add_markup (frame, lgl_template_markup_line_new (x1, y1, x2, y2));
-
- for (node = markup_node->xmlChildrenNode; node != NULL;
- node = node->next) {
- if (!xmlNodeIsText (node)) {
- if (!lgl_xml_is_node (node, "comment")) {
- g_message ("bad node = \"%s\"",node->name);
- }
- }
- }
-
-}
-
-/*--------------------------------------------------------------------------*/
-/* PRIVATE. Parse XML Template->Label->Markup-circle Node. */
-/*--------------------------------------------------------------------------*/
-static void
-xml_parse_markup_circle_node (xmlNodePtr markup_node,
- lglTemplateFrame *frame)
-{
- gdouble x0, y0, r;
- xmlNodePtr node;
-
- x0 = lgl_xml_get_prop_length (markup_node, "x0", 0);
- y0 = lgl_xml_get_prop_length (markup_node, "y0", 0);
- r = lgl_xml_get_prop_length (markup_node, "radius", 0);
-
- lgl_template_frame_add_markup (frame, lgl_template_markup_circle_new (x0, y0, r));
-
- for (node = markup_node->xmlChildrenNode; node != NULL;
- node = node->next) {
- if (!xmlNodeIsText (node)) {
- if (!lgl_xml_is_node (node, "comment")) {
- g_message ("bad node = \"%s\"",node->name);
- }
- }
- }
-
-}
-
-
-/*--------------------------------------------------------------------------*/
-/* PRIVATE. Parse XML Template->Label->Markup-rect Node. */
-/*--------------------------------------------------------------------------*/
-static void
-xml_parse_markup_rect_node (xmlNodePtr markup_node,
- lglTemplateFrame *frame)
-{
- gdouble x1, y1, w, h, r;
- xmlNodePtr node;
-
- x1 = lgl_xml_get_prop_length (markup_node, "x1", 0);
- y1 = lgl_xml_get_prop_length (markup_node, "y1", 0);
- w = lgl_xml_get_prop_length (markup_node, "w", 0);
- h = lgl_xml_get_prop_length (markup_node, "h", 0);
- r = lgl_xml_get_prop_length (markup_node, "r", 0);
-
- lgl_template_frame_add_markup (frame, lgl_template_markup_rect_new (x1, y1, w, h, r));
-
- for (node = markup_node->xmlChildrenNode; node != NULL;
- node = node->next) {
- if (!xmlNodeIsText (node)) {
- if (!lgl_xml_is_node (node, "comment")) {
- g_message ("bad node = \"%s\"",node->name);
- }
- }
- }
-
-}
-
-
-/*--------------------------------------------------------------------------*/
-/* PRIVATE. Parse XML Template->Label->Markup-ellipse Node. */
-/*--------------------------------------------------------------------------*/
-static void
-xml_parse_markup_ellipse_node (xmlNodePtr markup_node,
- lglTemplateFrame *frame)
-{
- gdouble x1, y1, w, h;
- xmlNodePtr node;
-
- x1 = lgl_xml_get_prop_length (markup_node, "x1", 0);
- y1 = lgl_xml_get_prop_length (markup_node, "y1", 0);
- w = lgl_xml_get_prop_length (markup_node, "w", 0);
- h = lgl_xml_get_prop_length (markup_node, "h", 0);
-
- lgl_template_frame_add_markup (frame, lgl_template_markup_ellipse_new (x1, y1, w, h));
-
- for (node = markup_node->xmlChildrenNode; node != NULL;
- node = node->next) {
- if (!xmlNodeIsText (node)) {
- if (!lgl_xml_is_node (node, "comment")) {
- g_message ("bad node = \"%s\"",node->name);
- }
- }
- }
-
-}
-
-
-/*--------------------------------------------------------------------------*/
-/* PRIVATE. Parse deprecated XML Template->Alias Node. */
-/*--------------------------------------------------------------------------*/
-static void
-xml_parse_alias_node (xmlNodePtr alias_node,
- lglTemplate *template)
-{
- g_message ("Skipping deprecated \"Alias\" node.");
-}
-
-
-/**
- * lgl_xml_template_write_templates_to_file:
- * @templates: List of #lglTemplate structures
- * @utf8_filename: Filename of templates file (name encoded as UTF-8)
- *
- * Write a list of #lglTemplate structures to a glabels XML template file.
- *
- * Returns: the number of bytes written or -1 in case of failure
- *
- */
-gint
-lgl_xml_template_write_templates_to_file (GList *templates,
- const gchar *utf8_filename)
-{
- xmlDocPtr doc;
- xmlNsPtr ns;
- gint bytes_written;
- GList *p;
- lglTemplate *template;
- gchar *filename;
-
- doc = xmlNewDoc ((xmlChar *)"1.0");
- doc->xmlRootNode = xmlNewDocNode (doc, NULL, (xmlChar *)"Glabels-templates", NULL);
-
- ns = xmlNewNs (doc->xmlRootNode, (xmlChar *)LGL_XML_NAME_SPACE, NULL);
- xmlSetNs (doc->xmlRootNode, ns);
-
- for (p=templates; p!=NULL; p=p->next) {
- template = (lglTemplate *)p->data;
- lgl_xml_template_create_template_node (template, doc->xmlRootNode, ns);
- }
-
- filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
- if (!filename)
- {
- g_message ("Utf8 conversion error.");
- return -1;
- }
- else
- {
- xmlSetDocCompressMode (doc, 0);
- bytes_written = xmlSaveFormatFile (filename, doc, TRUE);
- xmlFreeDoc (doc);
- g_free (filename);
- return bytes_written;
- }
-
-}
-
-
-/**
- * lgl_xml_template_write_template_to_file:
- * @template: #lglTemplate structure to be written
- * @utf8_filename: Filename of templates file (name encoded as UTF-8)
- *
- * Write a single #lglTemplate structures to a glabels XML template file.
- *
- * Returns: the number of bytes written or -1 in case of failure
- *
- */
-gint
-lgl_xml_template_write_template_to_file (const lglTemplate *template,
- const gchar *utf8_filename)
-{
- GList *templates = NULL;
- gint bytes_written;
-
- templates = g_list_append (templates, (gpointer)template);
-
- bytes_written = lgl_xml_template_write_templates_to_file (templates, utf8_filename);
-
- g_list_free (templates);
-
- return bytes_written;
-}
-
-
-/**
- * lgl_xml_template_create_template_node:
- * @template: #lglTemplate structure to be written
- * @root: parent node to receive new child node
- * @ns: a libxml #xmlNsPtr
- *
- * Add a single #lglTemplate child node to given #xmlNodePtr.
- *
- */
-void
-lgl_xml_template_create_template_node (const lglTemplate *template,
- xmlNodePtr root,
- const xmlNsPtr ns)
-{
- xmlNodePtr node;
- GList *p;
- lglTemplateFrame *frame;
-
- node = xmlNewChild (root, ns, (xmlChar *)"Template", NULL);
-
- lgl_xml_set_prop_string (node, "brand", template->brand);
- lgl_xml_set_prop_string (node, "part", template->part);
-
- lgl_xml_set_prop_string (node, "size", template->paper_id);
- if (xmlStrEqual ((xmlChar *)template->paper_id, (xmlChar *)"Other"))
- {
-
- lgl_xml_set_prop_length (node, "width", template->page_width);
- lgl_xml_set_prop_length (node, "height", template->page_height);
-
- }
-
- lgl_xml_set_prop_string (node, "description", template->description);
-
- xml_create_meta_node ("product_url", template->product_url, node, ns );
- for ( p=template->category_ids; p != NULL; p=p->next )
- {
- xml_create_meta_node ( "category", p->data, node, ns );
- }
- for ( p=template->frames; p != NULL; p=p->next )
- {
- frame = (lglTemplateFrame *)p->data;
- xml_create_label_node (frame, node, ns);
- }
-
-}
-
-/*--------------------------------------------------------------------------*/
-/* PRIVATE. Add XML Template->Meta Node with category. */
-/*--------------------------------------------------------------------------*/
-static void
-xml_create_meta_node (const gchar *attr,
- const gchar *value,
- xmlNodePtr root,
- const xmlNsPtr ns)
-{
- xmlNodePtr node;
-
- if ( value != NULL )
- {
- node = xmlNewChild (root, ns, (xmlChar *)"Meta", NULL);
- lgl_xml_set_prop_string (node, attr, value);
- }
-
-}
-
-/*--------------------------------------------------------------------------*/
-/* PRIVATE. Add XML Template->Label Node. */
-/*--------------------------------------------------------------------------*/
-static void
-xml_create_label_node (const lglTemplateFrame *frame,
- xmlNodePtr root,
- const xmlNsPtr ns)
-{
- xmlNodePtr node;
- GList *p;
- lglTemplateMarkup *markup;
- lglTemplateLayout *layout;
-
- switch (frame->shape) {
-
- case LGL_TEMPLATE_FRAME_SHAPE_RECT:
- node = xmlNewChild(root, ns, (xmlChar *)"Label-rectangle", NULL);
- lgl_xml_set_prop_string (node, "id", frame->all.id);
- lgl_xml_set_prop_length (node, "width", frame->rect.w);
- lgl_xml_set_prop_length (node, "height", frame->rect.h);
- lgl_xml_set_prop_length (node, "round", frame->rect.r);
- lgl_xml_set_prop_length (node, "x_waste", frame->rect.x_waste);
- lgl_xml_set_prop_length (node, "y_waste", frame->rect.y_waste);
- break;
-
- case LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE:
- node = xmlNewChild(root, ns, (xmlChar *)"Label-ellipse", NULL);
- lgl_xml_set_prop_string (node, "id", frame->all.id);
- lgl_xml_set_prop_length (node, "width", frame->ellipse.w);
- lgl_xml_set_prop_length (node, "height", frame->ellipse.h);
- lgl_xml_set_prop_length (node, "waste", frame->ellipse.waste);
- break;
-
- case LGL_TEMPLATE_FRAME_SHAPE_ROUND:
- node = xmlNewChild(root, ns, (xmlChar *)"Label-round", NULL);
- lgl_xml_set_prop_string (node, "id", frame->all.id);
- lgl_xml_set_prop_length (node, "radius", frame->round.r);
- lgl_xml_set_prop_length (node, "waste", frame->round.waste);
- break;
-
- case LGL_TEMPLATE_FRAME_SHAPE_CD:
- node = xmlNewChild(root, ns, (xmlChar *)"Label-cd", NULL);
- lgl_xml_set_prop_string (node, "id", frame->all.id);
- lgl_xml_set_prop_length (node, "radius", frame->cd.r1);
- lgl_xml_set_prop_length (node, "hole", frame->cd.r2);
- if (frame->cd.w != 0.0) {
- lgl_xml_set_prop_length (node, "width", frame->cd.w);
- }
- if (frame->cd.h != 0.0) {
- lgl_xml_set_prop_length (node, "height", frame->cd.h);
- }
- lgl_xml_set_prop_length (node, "waste", frame->cd.waste);
- break;
-
- default:
- g_message ("Unknown label style");
- return;
- break;
-
- }
-
- for ( p=frame->all.markups; p != NULL; p=p->next ) {
- markup = (lglTemplateMarkup *)p->data;
- switch (markup->type) {
- case LGL_TEMPLATE_MARKUP_MARGIN:
- xml_create_markup_margin_node (markup, node, ns);
- break;
- case LGL_TEMPLATE_MARKUP_LINE:
- xml_create_markup_line_node (markup, node, ns);
- break;
- case LGL_TEMPLATE_MARKUP_CIRCLE:
- xml_create_markup_circle_node (markup, node, ns);
- break;
- case LGL_TEMPLATE_MARKUP_RECT:
- xml_create_markup_rect_node (markup, node, ns);
- break;
- case LGL_TEMPLATE_MARKUP_ELLIPSE:
- xml_create_markup_ellipse_node (markup, node, ns);
- break;
- default:
- g_message ("Unknown markup type");
- break;
- }
- }
-
- for ( p=frame->all.layouts; p != NULL; p=p->next ) {
- layout = (lglTemplateLayout *)p->data;
- xml_create_layout_node (layout, node, ns);
- }
-
-}
-
-/*--------------------------------------------------------------------------*/
-/* PRIVATE. Add XML Template->Label->Layout Node. */
-/*--------------------------------------------------------------------------*/
-static void
-xml_create_layout_node (const lglTemplateLayout *layout,
- xmlNodePtr root,
- const xmlNsPtr ns)
-{
- xmlNodePtr node;
-
- node = xmlNewChild(root, ns, (xmlChar *)"Layout", NULL);
- lgl_xml_set_prop_int (node, "nx", layout->nx);
- lgl_xml_set_prop_int (node, "ny", layout->ny);
- lgl_xml_set_prop_length (node, "x0", layout->x0);
- lgl_xml_set_prop_length (node, "y0", layout->y0);
- lgl_xml_set_prop_length (node, "dx", layout->dx);
- lgl_xml_set_prop_length (node, "dy", layout->dy);
-
-}
-
-/*--------------------------------------------------------------------------*/
-/* PRIVATE. Add XML Template->Label->Markup-margin Node. */
-/*--------------------------------------------------------------------------*/
-static void
-xml_create_markup_margin_node (const lglTemplateMarkup *markup,
- xmlNodePtr root,
- const xmlNsPtr ns)
-{
- xmlNodePtr node;
-
- node = xmlNewChild(root, ns, (xmlChar *)"Markup-margin", NULL);
-
- lgl_xml_set_prop_length (node, "size", markup->margin.size);
-
-}
-
-/*--------------------------------------------------------------------------*/
-/* PRIVATE. Add XML Template->Label->Markup-line Node. */
-/*--------------------------------------------------------------------------*/
-static void
-xml_create_markup_line_node (const lglTemplateMarkup *markup,
- xmlNodePtr root,
- const xmlNsPtr ns)
-{
- xmlNodePtr node;
-
- node = xmlNewChild(root, ns, (xmlChar *)"Markup-line", NULL);
-
- lgl_xml_set_prop_length (node, "x1", markup->line.x1);
- lgl_xml_set_prop_length (node, "y1", markup->line.y1);
- lgl_xml_set_prop_length (node, "x2", markup->line.x2);
- lgl_xml_set_prop_length (node, "y2", markup->line.y2);
-
-}
-
-/*--------------------------------------------------------------------------*/
-/* PRIVATE. Add XML Template->Label->Markup-circle Node. */
-/*--------------------------------------------------------------------------*/
-static void
-xml_create_markup_circle_node (const lglTemplateMarkup *markup,
- xmlNodePtr root,
- const xmlNsPtr ns)
-{
- xmlNodePtr node;
-
- node = xmlNewChild(root, ns, (xmlChar *)"Markup-circle", NULL);
-
- lgl_xml_set_prop_length (node, "x0", markup->circle.x0);
- lgl_xml_set_prop_length (node, "y0", markup->circle.y0);
- lgl_xml_set_prop_length (node, "radius", markup->circle.r);
-
-}
-
-
-/*--------------------------------------------------------------------------*/
-/* PRIVATE. Add XML Template->Label->Markup-rect Node. */
-/*--------------------------------------------------------------------------*/
-static void
-xml_create_markup_rect_node (const lglTemplateMarkup *markup,
- xmlNodePtr root,
- const xmlNsPtr ns)
-{
- xmlNodePtr node;
-
- node = xmlNewChild(root, ns, (xmlChar *)"Markup-rect", NULL);
-
- lgl_xml_set_prop_length (node, "x1", markup->rect.x1);
- lgl_xml_set_prop_length (node, "y1", markup->rect.y1);
- lgl_xml_set_prop_length (node, "w", markup->rect.w);
- lgl_xml_set_prop_length (node, "h", markup->rect.h);
- lgl_xml_set_prop_length (node, "r", markup->rect.r);
-
-}
-
-
-/*--------------------------------------------------------------------------*/
-/* PRIVATE. Add XML Template->Label->Markup-ellipse Node. */
-/*--------------------------------------------------------------------------*/
-static void
-xml_create_markup_ellipse_node (const lglTemplateMarkup *markup,
- xmlNodePtr root,
- const xmlNsPtr ns)
-{
- xmlNodePtr node;
-
- node = xmlNewChild(root, ns, (xmlChar *)"Markup-ellipse", NULL);
-
- lgl_xml_set_prop_length (node, "x1", markup->ellipse.x1);
- lgl_xml_set_prop_length (node, "y1", markup->ellipse.y1);
- lgl_xml_set_prop_length (node, "w", markup->ellipse.w);
- lgl_xml_set_prop_length (node, "h", markup->ellipse.h);
-
-}
-
-
-
-/*
- * Local Variables: -- emacs
- * mode: C -- emacs
- * c-basic-offset: 8 -- emacs
- * tab-width: 8 -- emacs
- * indent-tabs-mode: nil -- emacs
- * End: -- emacs
- */
+++ /dev/null
-/*
- * xml-template.h
- * Copyright (C) 2001-2009 Jim Evins <evins@snaught.com>.
- *
- * This file is part of libglabels.
- *
- * libglabels is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libglabels 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __LGL_XML_TEMPLATE_H__
-#define __LGL_XML_TEMPLATE_H__
-
-#include <glib.h>
-#include <libxml/tree.h>
-
-#include "template.h"
-
-G_BEGIN_DECLS
-
-void lgl_xml_template_read_templates_from_file (const gchar *utf8_filename);
-
-void lgl_xml_template_parse_templates_doc (const xmlDocPtr templates_doc);
-
-lglTemplate *lgl_xml_template_parse_template_node (const xmlNodePtr template_node);
-
-
-gint lgl_xml_template_write_templates_to_file (GList *templates,
- const gchar *utf8_filename);
-
-gint lgl_xml_template_write_template_to_file (const lglTemplate *template,
- const gchar *utf8_filename);
-
-void lgl_xml_template_create_template_node (const lglTemplate *template,
- xmlNodePtr root,
- const xmlNsPtr ns);
-
-G_END_DECLS
-
-#endif /* __LGL_XML_TEMPLATE_H__ */
-
-
-
-/*
- * Local Variables: -- emacs
- * mode: C -- emacs
- * c-basic-offset: 8 -- emacs
- * tab-width: 8 -- emacs
- * indent-tabs-mode: nil -- emacs
- * End: -- emacs
- */
+++ /dev/null
-/*
- * xml-vendor.c
- * Copyright (C) 2003-2009 Jim Evins <evins@snaught.com>.
- *
- * This file is part of libglabels.
- *
- * libglabels is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libglabels 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-
-#include "xml-vendor.h"
-
-#include <glib/gi18n.h>
-#include <glib.h>
-#include <string.h>
-#include <libintl.h>
-
-#include "libglabels-private.h"
-
-#include "xml.h"
-
-/*===========================================*/
-/* Private types */
-/*===========================================*/
-
-/*===========================================*/
-/* Private globals */
-/*===========================================*/
-
-/*===========================================*/
-/* Local function prototypes */
-/*===========================================*/
-
-
-/**
- * lgl_xml_vendor_read_vendors_from_file:
- * @utf8_filename: Filename of vendors file (name encoded as UTF-8)
- *
- * Read vendor definitions from a file.
- *
- * Returns: a list of #lglVendor structures.
- *
- */
-GList *
-lgl_xml_vendor_read_vendors_from_file (gchar *utf8_filename)
-{
- gchar *filename;
- GList *vendors;
- xmlDocPtr vendors_doc;
-
- LIBXML_TEST_VERSION;
-
- filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
- if (!filename) {
- g_message ("Utf8 filename conversion error");
- return NULL;
- }
-
- vendors_doc = xmlParseFile (filename);
- if (!vendors_doc) {
- g_message ("\"%s\" is not a glabels vendor file (not XML)",
- filename);
- return NULL;
- }
-
- vendors = lgl_xml_vendor_parse_vendors_doc (vendors_doc);
-
- g_free (filename);
- xmlFreeDoc (vendors_doc);
-
- return vendors;
-}
-
-
-/**
- * lgl_xml_vendor_parse_vendors_doc:
- * @vendors_doc: libxml #xmlDocPtr tree, representing a vendors definition file.
- *
- * Read vendor definitions from a libxml #xmlDocPtr tree.
- *
- * Returns: a list of #lglVendor structures.
- *
- */
-GList *
-lgl_xml_vendor_parse_vendors_doc (xmlDocPtr vendors_doc)
-{
- GList *vendors = NULL;
- xmlNodePtr root, node;
- lglVendor *vendor;
-
- LIBXML_TEST_VERSION;
-
- root = xmlDocGetRootElement (vendors_doc);
- if (!root || !root->name) {
- g_message ("\"%s\" is not a glabels vendor file (no root node)",
- vendors_doc->name);
- xmlFreeDoc (vendors_doc);
- return vendors;
- }
- if (!lgl_xml_is_node (root, "Glabels-vendors")) {
- g_message ("\"%s\" is not a glabels vendor file (wrong root node)",
- vendors_doc->name);
- xmlFreeDoc (vendors_doc);
- return vendors;
- }
-
- for (node = root->xmlChildrenNode; node != NULL; node = node->next) {
-
- if (lgl_xml_is_node (node, "Vendor")) {
- vendor = lgl_xml_vendor_parse_vendor_node (node);
- vendors = g_list_append (vendors, vendor);
- } else {
- if ( !xmlNodeIsText(node) ) {
- if (!lgl_xml_is_node (node, "comment")) {
- g_message ("bad node = \"%s\"",node->name);
- }
- }
- }
- }
-
- return vendors;
-}
-
-
-/**
- * lgl_xml_vendor_parse_vendor_node:
- * @vendor_node: libxml #xmlNodePtr vendor node from a #xmlDocPtr tree.
- *
- * Read a single vendor definition from a libxml #xmlNodePtr node.
- *
- * Returns: a pointer to a newly created #lglVendor structure.
- *
- */
-lglVendor *
-lgl_xml_vendor_parse_vendor_node (xmlNodePtr vendor_node)
-{
- lglVendor *vendor;
- gchar *name;
-
- LIBXML_TEST_VERSION;
-
- name = lgl_xml_get_prop_i18n_string (vendor_node, "name", NULL);
-
- vendor = lgl_vendor_new (name);
-
- vendor->url = lgl_xml_get_prop_i18n_string (vendor_node, "url", NULL);
-
- g_free (name);
-
- return vendor;
-}
-
-
-
-/*
- * Local Variables: -- emacs
- * mode: C -- emacs
- * c-basic-offset: 8 -- emacs
- * tab-width: 8 -- emacs
- * indent-tabs-mode: nil -- emacs
- * End: -- emacs
- */
+++ /dev/null
-/*
- * xml-vendor.h
- * Copyright (C) 2003-2009 Jim Evins <evins@snaught.com>.
- *
- * This file is part of libglabels.
- *
- * libglabels is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libglabels 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __LGL_XML_VENDOR_H__
-#define __LGL_XML_VENDOR_H__
-
-#include <glib.h>
-#include <libxml/tree.h>
-
-#include "vendor.h"
-
-G_BEGIN_DECLS
-
-GList *lgl_xml_vendor_read_vendors_from_file (gchar *utf8_filename);
-
-GList *lgl_xml_vendor_parse_vendors_doc (xmlDocPtr vendors_doc);
-
-lglVendor *lgl_xml_vendor_parse_vendor_node (xmlNodePtr vendor_node);
-
-
-G_END_DECLS
-
-#endif /* __LGL_XML_VENDOR_H__ */
-
-
-
-/*
- * Local Variables: -- emacs
- * mode: C -- emacs
- * c-basic-offset: 8 -- emacs
- * tab-width: 8 -- emacs
- * indent-tabs-mode: nil -- emacs
- * End: -- emacs
- */
+++ /dev/null
-/*
- * xml.c
- * Copyright (C) 2003-2009 Jim Evins <evins@snaught.com>.
- *
- * This file is part of libglabels.
- *
- * libglabels is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libglabels 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-
-#include "xml.h"
-
-#include <glib/gi18n.h>
-#include <glib.h>
-#include <string.h>
-
-#include "libglabels-private.h"
-
-
-/*========================================================*/
-/* Private macros and constants. */
-/*========================================================*/
-
-/*========================================================*/
-/* Private types. */
-/*========================================================*/
-
-/*========================================================*/
-/* Private globals. */
-/*========================================================*/
-
-static lglUnits default_units = LGL_UNITS_POINT;
-
-
-/****************************************************************************/
-
-/**
- * lgl_xml_get_prop_string:
- * @node: the libxml2 #xmlNodePtr of the node
- * @property: the property name
- * @default_val: a default value to return if property not found
- *
- * Return value of property as a string.
- *
- * Returns: the property as a pointer to a gchar string. This string should
- * be freed with g_free().
- *
- */
-gchar *
-lgl_xml_get_prop_string (xmlNodePtr node,
- const gchar *property,
- const gchar *default_val)
-{
- gchar *val;
- xmlChar *string;
-
- string = xmlGetProp (node, (xmlChar *)property);
- if ( string != NULL ) {
- val = g_strdup ((gchar *)string);
- xmlFree (string);
- return val;
- }
-
- if (default_val) {
- return g_strdup (default_val);
- }
-
- return NULL;
-}
-
-
-/**
- * lgl_xml_get_prop_i18n_string:
- * @node: the libxml2 #xmlNodePtr of the node
- * @property: the property name
- * @default_val: a default value to return if property not found
- *
- * Return value of a translatable property as a string.
- *
- * Returns: the property as a pointer to a gchar string. This string should
- * be freed with g_free().
- *
- */
-gchar *
-lgl_xml_get_prop_i18n_string (xmlNodePtr node,
- const gchar *property,
- const gchar *default_val)
-{
- gchar *_property;
- gchar *val;
- xmlChar *string;
-
- _property = g_strdup_printf ("_%s", property);
- string = xmlGetProp (node, (xmlChar *)_property);
- g_free (_property);
-
- if ( string != NULL ) {
-
- val = g_strdup (gettext ((char *)string));
- xmlFree (string);
- return val;
-
- }
-
- string = xmlGetProp (node, (xmlChar *)property);
- if ( string != NULL ) {
- val = g_strdup ((gchar *)string);
- xmlFree (string);
- return val;
- }
-
- if (default_val) {
- return g_strdup (default_val);
- }
-
- return NULL;
-}
-
-
-/**
- * lgl_xml_get_prop_double:
- * @node: the libxml2 #xmlNodePtr of the node
- * @property: the property name
- * @default_val: a default value to return if property not found
- *
- * Return value of property as a double.
- *
- * Returns: the property as a double.
- *
- */
-gdouble
-lgl_xml_get_prop_double (xmlNodePtr node,
- const gchar *property,
- gdouble default_val)
-{
- gdouble val;
- xmlChar *string;
-
- string = xmlGetProp (node, (xmlChar *)property);
- if ( string != NULL ) {
- val = g_strtod ((gchar *)string, NULL);
- xmlFree (string);
- return val;
- }
-
- return default_val;
-}
-
-
-/**
- * lgl_xml_get_prop_boolean:
- * @node: the libxml2 #xmlNodePtr of the node
- * @property: the property name
- * @default_val: a default value to return if property not found
- *
- * Return value of property as a boolean.
- *
- * Returns: the property as a boolean.
- *
- */
-gboolean
-lgl_xml_get_prop_boolean (xmlNodePtr node,
- const gchar *property,
- gboolean default_val)
-{
- gboolean val;
- xmlChar *string;
-
- string = xmlGetProp (node, (xmlChar *)property);
- if ( string != NULL ) {
- val = !((xmlStrcasecmp (string, (xmlChar *)"false") == 0) ||
- xmlStrEqual (string, (xmlChar *)"0"));;
- xmlFree (string);
- return val;
- }
-
- return default_val;
-}
-
-
-/**
- * lgl_xml_get_prop_int:
- * @node: the libxml2 #xmlNodePtr of the node
- * @property: the property name
- * @default_val: a default value to return if property not found
- *
- * Return value of property as an integer.
- *
- * Returns: the property as an integer.
- *
- */
-gint
-lgl_xml_get_prop_int (xmlNodePtr node,
- const gchar *property,
- gint default_val)
-{
- gint val;
- xmlChar *string;
-
- string = xmlGetProp (node, (xmlChar *)property);
- if ( string != NULL ) {
- val = strtol ((char *)string, NULL, 0);
- xmlFree (string);
- return val;
- }
-
- return default_val;
-}
-
-
-/**
- * lgl_xml_get_prop_uint:
- * @node: the libxml2 #xmlNodePtr of the node
- * @property: the property name
- * @default_val: a default value to return if property not found
- *
- * Return value of property (usually formatted in hex) as an unsigned integer.
- *
- * Returns: the property as an unsigned integer.
- *
- */
-guint
-lgl_xml_get_prop_uint (xmlNodePtr node,
- const gchar *property,
- guint default_val)
-{
- guint val;
- xmlChar *string;
-
- string = xmlGetProp (node, (xmlChar *)property);
- if ( string != NULL ) {
- val = strtoul ((char *)string, NULL, 0);
- xmlFree (string);
- return val;
- }
-
- return default_val;
-}
-
-
-/**
- * lgl_xml_get_prop_length:
- * @node: the libxml2 #xmlNodePtr of the node
- * @property: the property name
- * @default_val: a default value to return if property not found
- *
- * Return value of a length property as a double, converting to internal
- * units (points). The property is expected to be formatted as a number
- * followed by a units string. If there is no units string, the length
- * is assumed to be in points. Valid units strings are "pt" for points,
- * "in" for inches, "mm" for millimeters, "cm" for centimeters, and
- * "pc" for picas.
- *
- * Returns: the length in points.
- *
- */
-gdouble
-lgl_xml_get_prop_length (xmlNodePtr node,
- const gchar *property,
- gdouble default_val)
-{
- gdouble val;
- xmlChar *string;
- xmlChar *unit_id;
- lglUnits units;
-
- string = xmlGetProp (node, (xmlChar *)property);
- if ( string != NULL ) {
-
- val = g_strtod ((gchar *)string, (gchar **)&unit_id);
-
- if (unit_id != string) {
- unit_id = (xmlChar *)g_strchug ((gchar *)unit_id);
- units = lgl_units_from_id ((gchar *)unit_id);
- if (units != LGL_UNITS_INVALID)
- {
- val *= lgl_units_get_points_per_unit (units);
- }
- else
- {
- g_message ("Line %ld, Node \"%s\", Property \"%s\": Unknown unit \"%s\", assuming points",
- xmlGetLineNo (node), node->name, property, unit_id);
- }
- }
- else {
- val = 0.0;
- }
-
- xmlFree (string);
- return val;
- }
-
- return default_val;
-}
-
-
-/**
- * lgl_xml_set_prop_string:
- * @node: the libxml2 #xmlNodePtr of the node
- * @property: the property name
- * @val: the value to set
- *
- * Set a property from a string.
- *
- */
-void
-lgl_xml_set_prop_string (xmlNodePtr node,
- const gchar *property,
- const gchar *val)
-{
- if (val != NULL) {
- xmlSetProp (node, (xmlChar *)property, (xmlChar *)val);
- }
-}
-
-
-/**
- * lgl_xml_set_prop_double:
- * @node: the libxml2 #xmlNodePtr of the node
- * @property: the property name
- * @val: the value to set
- *
- * Set a property from a double.
- *
- */
-void
-lgl_xml_set_prop_double (xmlNodePtr node,
- const gchar *property,
- gdouble val)
-{
- gchar *string, buffer[G_ASCII_DTOSTR_BUF_SIZE];
-
- /* Guarantee "C" locale by use of g_ascii_formatd */
- string = g_ascii_formatd (buffer, G_ASCII_DTOSTR_BUF_SIZE, "%g", val);
-
- xmlSetProp (node, (xmlChar *)property, (xmlChar *)string);
-}
-
-
-/**
- * lgl_xml_set_prop_boolean:
- * @node: the libxml2 #xmlNodePtr of the node
- * @property: the property name
- * @val: the value to set
- *
- * Set a property from a boolean.
- *
- */
-void
-lgl_xml_set_prop_boolean (xmlNodePtr node,
- const gchar *property,
- gboolean val)
-{
- xmlSetProp (node, (xmlChar *)property, (xmlChar *)(val ? "True" : "False"));
-}
-
-/**
- * lgl_xml_set_prop_int:
- * @node: the libxml2 #xmlNodePtr of the node
- * @property: the property name
- * @val: the value to set
- *
- * Set a property from an integer.
- *
- */
-void
-lgl_xml_set_prop_int (xmlNodePtr node,
- const gchar *property,
- gint val)
-{
- gchar *string;
-
- string = g_strdup_printf ("%d", val);
- xmlSetProp (node, (xmlChar *)property, (xmlChar *)string);
- g_free (string);
-}
-
-/**
- * lgl_xml_set_prop_uint_hex:
- * @node: the libxml2 #xmlNodePtr of the node
- * @property: the property name
- * @val: the value to set
- *
- * Set a property from an unsigned integer and format in hex.
- *
- */
-void
-lgl_xml_set_prop_uint_hex (xmlNodePtr node,
- const gchar *property,
- guint val)
-{
- gchar *string;
-
- string = g_strdup_printf ("0x%08x", val);
- xmlSetProp (node, (xmlChar *)property, (xmlChar *)string);
- g_free (string);
-}
-
-/**
- * lgl_xml_set_prop_length:
- * @node: the libxml2 #xmlNodePtr of the node
- * @property: the property name
- * @val: the length to set in internal units (points)
- *
- * Set a property from a length, performing any necessary conversion.
- * Length properties are formatted as a number followed by a units string.
- * The units of the formatted property is determined by the most recent call to
- * lgl_xml_set_default_units().
- *
- */
-void
-lgl_xml_set_prop_length (xmlNodePtr node,
- const gchar *property,
- gdouble val)
-{
- gchar *string, buffer[G_ASCII_DTOSTR_BUF_SIZE];
- gchar *string_unit;
-
- /* Convert to default units */
- val *= lgl_units_get_units_per_point (default_units);
-
- /* Guarantee "C" locale by use of g_ascii_formatd */
- string = g_ascii_formatd (buffer, G_ASCII_DTOSTR_BUF_SIZE, "%g", val);
-
- string_unit = g_strdup_printf ("%s%s", string, lgl_units_get_id (default_units));
- xmlSetProp (node, (xmlChar *)property, (xmlChar *)string_unit);
- g_free (string_unit);
-}
-
-/**
- * lgl_xml_is_node
- * @node: the libxml2 #xmlNodePtr of the node
- * @name : the node name
- *
- * Test if a node name matches given name.
- *
- * Returns: TRUE if the name of the node matches. Otherwise FALSE.
- *
- */
-gboolean
-lgl_xml_is_node (xmlNodePtr node,
- const gchar *name)
-{
- return xmlStrEqual (node->name, (xmlChar *)name);
-}
-
-
-/**
- * lgl_xml_get_node_content
- * @node: the libxml2 #xmlNodePtr of the node
- *
- * Get the content of a node.
- *
- * Returns: the property as a pointer to a gchar string. This string should
- * be freed with g_free().
- */
-gchar *
-lgl_xml_get_node_content (xmlNodePtr node)
-{
- xmlChar *xml_content;
- gchar *g_content;
-
- xml_content = xmlNodeGetContent (node);
-
- if (xml_content != NULL) {
-
- g_content = g_strdup ((gchar *)xml_content);
- xmlFree (xml_content);
- return g_content;
-
- }
-
- return NULL;
-}
-
-
-/**
- * lgl_xml_set_default_units:
- * @units: default units selection (#lglUnits)
- *
- * Set the default units when formatting lengths. See
- * lgl_xml_set_prop_length().
- *
- */
-void
-lgl_xml_set_default_units (lglUnits units)
-{
- g_return_if_fail ((units >= LGL_UNITS_FIRST) && (units <= LGL_UNITS_LAST));
-
- default_units = units;
-}
-
-
-
-/*
- * Local Variables: -- emacs
- * mode: C -- emacs
- * c-basic-offset: 8 -- emacs
- * tab-width: 8 -- emacs
- * indent-tabs-mode: nil -- emacs
- * End: -- emacs
- */
+++ /dev/null
-/*
- * xml.h
- * Copyright (C) 2003-2009 Jim Evins <evins@snaught.com>.
- *
- * This file is part of libglabels.
- *
- * libglabels is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * libglabels 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with libglabels. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __LGL_XML_H__
-#define __LGL_XML_H__
-
-#include <glib.h>
-#include <libxml/tree.h>
-
-#include "units.h"
-
-#define LGL_XML_NAME_SPACE "http://glabels.org/xmlns/2.3/"
-
-G_BEGIN_DECLS
-
-/*
- * Get property functions
- */
-gchar * lgl_xml_get_prop_string (xmlNodePtr node,
- const gchar *property,
- const gchar *default_val);
-
-gchar * lgl_xml_get_prop_i18n_string (xmlNodePtr node,
- const gchar *property,
- const gchar *default_val);
-
-gdouble lgl_xml_get_prop_double (xmlNodePtr node,
- const gchar *property,
- gdouble default_val);
-
-gboolean lgl_xml_get_prop_boolean (xmlNodePtr node,
- const gchar *property,
- gboolean default_val);
-
-gint lgl_xml_get_prop_int (xmlNodePtr node,
- const gchar *property,
- gint default_val);
-
-guint lgl_xml_get_prop_uint (xmlNodePtr node,
- const gchar *property,
- guint default_val);
-
-gdouble lgl_xml_get_prop_length (xmlNodePtr node,
- const gchar *property,
- gdouble default_val);
-
-
-/*
- * Set property functions
- */
-void lgl_xml_set_prop_string (xmlNodePtr node,
- const gchar *property,
- const gchar *val);
-
-void lgl_xml_set_prop_double (xmlNodePtr node,
- const gchar *property,
- gdouble val);
-
-void lgl_xml_set_prop_boolean (xmlNodePtr node,
- const gchar *property,
- gboolean val);
-
-void lgl_xml_set_prop_int (xmlNodePtr node,
- const gchar *property,
- gint val);
-
-void lgl_xml_set_prop_uint_hex (xmlNodePtr node,
- const gchar *property,
- guint val);
-
-void lgl_xml_set_prop_length (xmlNodePtr node,
- const gchar *property,
- gdouble val);
-
-/*
- * Other node functions
- */
-gboolean lgl_xml_is_node (xmlNodePtr node,
- const gchar *name);
-
-gchar * lgl_xml_get_node_content (xmlNodePtr node);
-
-/*
- * Misc functions
- */
-void lgl_xml_set_default_units (lglUnits units);
-
-G_END_DECLS
-
-
-#endif /* __LGL_XML_H__ */
-
-
-
-/*
- * Local Variables: -- emacs
- * mode: C -- emacs
- * c-basic-offset: 8 -- emacs
- * tab-width: 8 -- emacs
- * indent-tabs-mode: nil -- emacs
- * End: -- emacs
- */
src/xml-label.c
src/xml-label.h
-libglabels/category.c
-libglabels/category.h
-libglabels/db.c
-libglabels/db.h
+libglabels/lgl-category.c
+libglabels/lgl-category.h
+libglabels/lgl-db.c
+libglabels/lgl-db.h
+libglabels/lgl-paper.c
+libglabels/lgl-paper.h
+libglabels/lgl-str.c
+libglabels/lgl-str.h
+libglabels/lgl-template.c
+libglabels/lgl-template.h
+libglabels/lgl-units.c
+libglabels/lgl-units.h
+libglabels/lgl-xml.c
+libglabels/lgl-xml.h
+libglabels/lgl-xml-category.c
+libglabels/lgl-xml-category.h
+libglabels/lgl-xml-paper.c
+libglabels/lgl-xml-paper.h
+libglabels/lgl-xml-template.c
+libglabels/lgl-xml-template.h
libglabels/libglabels-private.h
-libglabels/paper.c
-libglabels/paper.h
-libglabels/str.c
-libglabels/str.h
-libglabels/template.c
-libglabels/template.h
-libglabels/units.c
-libglabels/units.h
-libglabels/xml.c
-libglabels/xml.h
-libglabels/xml-category.c
-libglabels/xml-category.h
-libglabels/xml-paper.c
-libglabels/xml-paper.h
-libglabels/xml-template.c
-libglabels/xml-template.h
[type: gettext/glade]data/ui/merge-properties-dialog.ui
[type: gettext/glade]data/ui/media-select.ui