[glabels] Libglabels mods to support reorganization of template database



commit 2d0ad672af26c3bc863e0a56a65a6be89944ced8
Author: Jim Evins <evins snaught com>
Date:   Sun Dec 6 21:41:40 2009 -0500

    Libglabels mods to support reorganization of template database
    
    Added "equiv" attribute to "Template" tag.  The "equiv" attribute works
    differently than the "Alias" tag: instead of defining a simple alias for
    the current template struct, it says to use the equivalent part as the
    prototype for this template.  The template could override (or append)
    unique meta data for this part number.  The "Alias" tag is still supported,
    but is deprecated.
    
    Added a "product_url" attribute to the "Meta" tag.
    
    Added a "vendor.xml" file which contains a database of vendors and their
    primary url.  This file has only been populated with a few examples so far.
    
    A new DTD file has been created to describe the above changes.
    
    The "Avery 5160" family in "avery-us-templates.xml", has been organized in
    the new scheme as an example.

 libglabels/Makefile.am                         |    4 +
 libglabels/db.c                                |  383 +++++++++++++++++++++---
 libglabels/db.h                                |   16 +
 libglabels/libglabels-private.h                |    3 +
 libglabels/template.c                          |   56 ++++
 libglabels/template.h                          |   17 +-
 libglabels/vendor.c                            |  133 ++++++++
 libglabels/vendor.h                            |   63 ++++
 libglabels/xml-template.c                      |   82 ++++--
 libglabels/xml-template.h                      |    4 +-
 libglabels/xml-vendor.c                        |  176 +++++++++++
 libglabels/xml-vendor.h                        |   51 ++++
 templates/Makefile.am                          |    1 +
 templates/avery-us-templates.xml               |   63 ++--
 templates/{glabels-2.2.dtd => glabels-2.3.dtd} |   35 ++-
 templates/vendors.xml                          |   42 +++
 16 files changed, 1016 insertions(+), 113 deletions(-)
---
diff --git a/libglabels/Makefile.am b/libglabels/Makefile.am
index 5e654ae..51812dd 100644
--- a/libglabels/Makefile.am
+++ b/libglabels/Makefile.am
@@ -24,12 +24,16 @@ libglabels_la_SOURCES =		\
 	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			\
diff --git a/libglabels/db.c b/libglabels/db.c
index 4a582e8..b05f54d 100644
--- a/libglabels/db.c
+++ b/libglabels/db.c
@@ -32,6 +32,7 @@
 
 #include "xml-paper.h"
 #include "xml-category.h"
+#include "xml-vendor.h"
 #include "xml-template.h"
 
 
@@ -46,6 +47,7 @@
 
 static GList *papers     = NULL;
 static GList *categories = NULL;
+static GList *vendors    = NULL;
 static GList *templates  = NULL;
 
 static GHashTable *template_cache = NULL;
@@ -66,9 +68,12 @@ static GList *read_categories              (void);
 static GList *read_category_files_from_dir (GList       *categories,
                                             const gchar *dirname);
 
-static GList *read_templates               (void);
-static GList *read_template_files_from_dir (GList       *templates,
-                                            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);
 
@@ -85,8 +90,8 @@ static lglTemplate *template_full_page     (const gchar *page_size);
  * 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, and its template
- * database.. It will search both system and user template directories to locate
+ * 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
@@ -94,6 +99,7 @@ lgl_db_init (void)
 {
 	lglPaper    *paper_other;
         lglCategory *category_user_defined;
+        lglTemplate *template;
         GList       *page_sizes;
         GList       *p;
 
@@ -124,12 +130,22 @@ lgl_db_init (void)
 	}
 
         /*
+         * Vendors
+         */
+	if (!vendors)
+        {
+                vendors = read_vendors ();
+	}
+
+        /*
          * Templates
          */
 	if (!templates)
         {
 
-                templates = read_templates ();
+                init_template_cache ();
+
+                read_templates ();
 
                 /* Create and append generic full page templates. */
                 page_sizes = lgl_db_get_paper_id_list ();
@@ -137,13 +153,12 @@ lgl_db_init (void)
                 {
                         if ( !lgl_db_is_paper_id_other (p->data) )
                         {
-                                templates = g_list_append (templates,
-                                                           template_full_page (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);
-
-                init_template_cache ();
 	}
 }
 
@@ -507,8 +522,7 @@ read_paper_files_from_dir (GList       *papers,
 
 		if (extension != NULL) {
 
-			if ( ASCII_EQUAL (extension, ".paper") ||
-			     ASCII_EQUAL (filename, "paper-sizes.xml") )
+			if ( ASCII_EQUAL (filename, "paper-sizes.xml") )
                         {
 
 				full_filename =
@@ -900,8 +914,7 @@ read_category_files_from_dir (GList       *categories,
 
 		if (extension != NULL) {
 
-			if ( ASCII_EQUAL (extension, ".category") ||
-			     ASCII_EQUAL (filename, "categories.xml") )
+			if ( ASCII_EQUAL (filename, "categories.xml") )
                         {
 
 				full_filename =
@@ -955,6 +968,242 @@ lgl_db_print_known_categories (void)
 
 
 /*===========================================*/
+/* 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 (!papers)
+        {
+		lgl_db_init ();
+	}
+
+	for ( p=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 (!papers)
+        {
+		lgl_db_init ();
+	}
+
+	if (name == NULL)
+        {
+		/* If no name, return first vendor as a default */
+		return lgl_vendor_dup ((lglVendor *) vendors->data);
+	}
+
+	for (p = 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 (!papers)
+        {
+		lgl_db_init ();
+	}
+
+	if (name == NULL)
+        {
+		return FALSE;
+	}
+
+	for (p = 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 = LGL_SYSTEM_DATA_DIR;
+	vendors = read_vendor_files_from_dir (vendors, data_dir);
+	g_free (data_dir);
+
+	data_dir = LGL_USER_DATA_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, "vendor-sizes.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 (!papers) {
+		lgl_db_init ();
+	}
+
+	g_print ("%s():\n", __FUNCTION__);
+	for (p = 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.                       */
 /*===========================================*/
 
@@ -1037,6 +1286,17 @@ lgl_db_free_brand_list (GList *brands)
 /* Template db functions.                    */
 /*===========================================*/
 
+void
+_lgl_db_register_template_internal (const lglTemplate   *template)
+{
+        lglTemplate *template_copy;
+
+        template_copy = lgl_template_dup (template);
+        templates = g_list_append (templates, template_copy);
+        add_to_template_cache (template_copy);
+}
+
+
 /**
  * lgl_db_register_template:
  * @template:  Pointer to a template structure to add to database.
@@ -1376,28 +1636,74 @@ lgl_db_lookup_template_from_name (const gchar *name)
 }
 
 
-static void
-init_template_cache (void)
+/**
+ * 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)
 {
-	GList            *p_tmplt, *p_alias;
+        gchar            *name;
+	GList            *p_alias;
 	lglTemplate      *template;
         lglTemplateAlias *alias;
-        gchar            *name;
+        gchar            *candidate_name;
+	lglTemplate      *new_template;
 
-        template_cache = g_hash_table_new (g_str_hash, g_str_equal);
+	if (!templates)
+        {
+		lgl_db_init ();
+	}
 
-        for ( p_tmplt=templates; p_tmplt != NULL; p_tmplt=p_tmplt->next )
+	if ((brand == NULL) || (part == NULL))
         {
-		template = (lglTemplate *) p_tmplt->data;
+		/* If no name, return first template as a default */
+		return lgl_template_dup ((lglTemplate *) templates->data);
+	}
+
+        name = g_strdup_printf ("%s %s", brand, part);
+        template = g_hash_table_lookup (template_cache, name);
 
-                for ( p_alias=template->aliases; p_alias != NULL; p_alias=p_alias->next )
+        if (template)
+        {
+                for (p_alias = template->aliases; p_alias != NULL; p_alias = p_alias->next)
                 {
                         alias = (lglTemplateAlias *)p_alias->data;
-                        name = g_strdup_printf ("%s %s", alias->brand, alias->part);
+                        candidate_name = g_strdup_printf ("%s %s", alias->brand, alias->part);
+
+                        if ( UTF8_EQUAL (candidate_name, name) )
+                        {
+                                g_free (candidate_name);
+                                new_template = lgl_template_dup (template);
+                                g_free (new_template->brand);
+                                new_template->brand = g_strdup (alias->brand);
+                                g_free (new_template->part);
+                                new_template->part = g_strdup (alias->part);
+                                g_free (name);
+                                return new_template;
+                        }
 
-                        g_hash_table_insert (template_cache, name, template);
+                        g_free (candidate_name);
                 }
         }
+
+	/* No matching template has been found so return the first template */
+        g_free (name);
+	return lgl_template_dup ((lglTemplate *) templates->data);
+}
+
+
+static void
+init_template_cache (void)
+{
+        template_cache = g_hash_table_new (g_str_hash, g_str_equal);
 }
 
 
@@ -1418,11 +1724,10 @@ add_to_template_cache (lglTemplate *template)
 }
 
 
-static GList *
+void
 read_templates (void)
 {
 	gchar       *data_dir;
-	GList       *templates = NULL;
         GList       *p;
         lglTemplate *template;
 
@@ -1430,7 +1735,7 @@ read_templates (void)
          * User defined templates.  Add to user-defined category.
          */
 	data_dir = LGL_USER_DATA_DIR;
-	templates = read_template_files_from_dir (templates, data_dir);
+	read_template_files_from_dir (data_dir);
 	g_free (data_dir);
         for ( p=templates; p != NULL; p=p->next )
         {
@@ -1442,41 +1747,37 @@ read_templates (void)
          * System templates.
          */
 	data_dir = LGL_SYSTEM_DATA_DIR;
-	templates = read_template_files_from_dir (templates, data_dir);
+	read_template_files_from_dir (data_dir);
 	g_free (data_dir);
 
 	if (templates == NULL)
         {
 		g_critical (_("Unable to locate any template files.  Libglabels may not be installed correctly!"));
 	}
-
-	return templates;
 }
 
 
-static GList *
-read_template_files_from_dir (GList       *templates,
-			      const gchar *dirname)
+void
+read_template_files_from_dir (const gchar *dirname)
 {
 	GDir        *dp;
 	const gchar *filename, *extension, *extension2;
 	gchar       *full_filename = NULL;
 	GError      *gerror = NULL;
-	GList       *new_templates = NULL;
 
 	if (dirname == NULL)
-		return templates;
+		return;
 
 	if (!g_file_test (dirname, G_FILE_TEST_EXISTS))
         {
-		return templates;
+		return;
 	}
 
 	dp = g_dir_open (dirname, 0, &gerror);
 	if (gerror != NULL)
         {
 	        g_message ("cannot open data directory: %s", gerror->message );
-		return templates;
+		return;
 	}
 
 	while ((filename = g_dir_read_name (dp)) != NULL)
@@ -1490,19 +1791,13 @@ read_template_files_from_dir (GList       *templates,
                 {
 
 			full_filename = g_build_filename (dirname, filename, NULL);
-			new_templates =
-				lgl_xml_template_read_templates_from_file (full_filename);
+                        lgl_xml_template_read_templates_from_file (full_filename);
 			g_free (full_filename);
-
-			templates = g_list_concat (templates, new_templates);
-			new_templates = NULL;
 		}
 
 	}
 
 	g_dir_close (dp);
-
-	return templates;
 }
 
 
diff --git a/libglabels/db.h b/libglabels/db.h
index 465929f..3fd9f3a 100644
--- a/libglabels/db.h
+++ b/libglabels/db.h
@@ -25,6 +25,7 @@
 
 #include "paper.h"
 #include "category.h"
+#include "vendor.h"
 #include "template.h"
 
 G_BEGIN_DECLS
@@ -91,6 +92,18 @@ 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,
@@ -121,6 +134,9 @@ 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
diff --git a/libglabels/libglabels-private.h b/libglabels/libglabels-private.h
index fa205ee..b5f6c21 100644
--- a/libglabels/libglabels-private.h
+++ b/libglabels/libglabels-private.h
@@ -24,6 +24,7 @@
 #include <glib.h>
 
 #include "str.h"
+#include "template.h"
 
 /* Data system and user data directories.  (must free w/ g_free()) */
 #define LGL_SYSTEM_DATA_DIR g_build_filename (LIBGLABELS_TEMPLATE_DIR, NULL)
@@ -35,6 +36,8 @@
 #define UTF8_EQUAL(s1,s2) (!lgl_str_utf8_casecmp (s1, s2))
 #define ASCII_EQUAL(s1,s2) (!g_ascii_strcasecmp (s1, s2))
 
+void _lgl_db_register_template_internal (const lglTemplate   *template);
+
 
 #endif /* __LIBGLABELS_PRIVATE_H__ */
 
diff --git a/libglabels/template.c b/libglabels/template.c
index 5675c40..3425203 100644
--- a/libglabels/template.c
+++ b/libglabels/template.c
@@ -30,6 +30,7 @@
 
 #include "libglabels-private.h"
 
+#include "db.h"
 #include "paper.h"
 
 /*===========================================*/
@@ -101,6 +102,58 @@ lgl_template_new (const gchar         *brand,
 
 
 /**
+ * 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;
+        GList            *p_alias;
+        lglTemplateAlias *alias;
+
+        template = lgl_db_lookup_template_from_brand_part (brand, equiv_part);
+        if (template)
+        {
+                g_free (template->part);
+                g_free (template->equiv_part);
+
+                template->part       = g_strdup (part);
+                template->equiv_part = g_strdup (equiv_part);
+
+                for ( p_alias = template->aliases; p_alias != NULL; p_alias = p_alias->next )
+                {
+                        alias = (lglTemplateAlias *)p_alias->data;
+                        lgl_template_alias_free (alias);
+                }
+                g_list_free (template->aliases);
+                template->aliases = NULL;
+
+                alias = lgl_template_alias_new (brand, part);
+                lgl_template_add_alias (template, alias);
+        }
+        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
  *
@@ -762,6 +815,9 @@ lgl_template_dup (const lglTemplate *orig_template)
                                      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->aliases; p != NULL; p=p->next )
         {
                 alias = (lglTemplateAlias *)p->data;
diff --git a/libglabels/template.h b/libglabels/template.h
index f8e5383..5793ea6 100644
--- a/libglabels/template.h
+++ b/libglabels/template.h
@@ -52,22 +52,25 @@ struct _lglTemplate {
 
 	gchar               *brand;
         gchar               *part;
+        gchar               *equiv_part;
+
 	gchar               *description;
 	gchar               *paper_id;
 	gdouble              page_width;
 	gdouble              page_height;
 
-	/* List of (lglTemplateAlias *) aliase structures. */
-	GList               *aliases;
-
-        /* List of (gchar *) category ids. */
-	GList               *category_ids;
+        /* 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;
 
+	/* Deprecated: List of (lglTemplateAlias *) alias structures. */
+	GList               *aliases;
+
 };
 
 
@@ -290,6 +293,10 @@ lglTemplate         *lgl_template_new                  (const gchar          *br
                                                         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_alias            (lglTemplate          *template,
                                                         lglTemplateAlias     *alias);
 
diff --git a/libglabels/vendor.c b/libglabels/vendor.c
new file mode 100644
index 0000000..9ee29bf
--- /dev/null
+++ b/libglabels/vendor.c
@@ -0,0 +1,133 @@
+/*
+ *  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:
+ * @id:       Id of vendor definition. (E.g. US-Letter, A4, etc.)  Should be
+ *            unique.
+ * @name:     Localized name of vendor.
+ * @width:    Width of vendor in points.
+ * @height:   Height of vendor in points.
+ * @pwg_size: PWG 5101.1-2002 size name.
+ *
+ * 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
+ */
diff --git a/libglabels/vendor.h b/libglabels/vendor.h
new file mode 100644
index 0000000..68b9ff5
--- /dev/null
+++ b/libglabels/vendor.h
@@ -0,0 +1,63 @@
+/*
+ *  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
+ */
diff --git a/libglabels/xml-template.c b/libglabels/xml-template.c
index 9a880c3..c33cc58 100644
--- a/libglabels/xml-template.c
+++ b/libglabels/xml-template.c
@@ -64,7 +64,8 @@ static void  xml_parse_markup_rect_node     (xmlNodePtr              markup_node
 static void  xml_parse_alias_node           (xmlNodePtr              alias_node,
 					     lglTemplate            *template);
 
-static void  xml_create_meta_node           (const gchar                  *category,
+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,
@@ -99,7 +100,7 @@ static void  xml_create_alias_node          (const lglTemplateAlias       *alias
  * Returns: a list of #lglTemplate structures.
  *
  */
-GList *
+void
 lgl_xml_template_read_templates_from_file (const gchar *utf8_filename)
 {
 	gchar      *filename;
@@ -111,22 +112,20 @@ lgl_xml_template_read_templates_from_file (const gchar *utf8_filename)
 	filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
 	if (!filename) {
 		g_message ("Utf8 filename conversion error");
-		return NULL;
+		return;
 	}
 
 	templates_doc = xmlParseFile (filename);
 	if (!templates_doc) {
 		g_message ("\"%s\" is not a glabels template file (not XML)",
 		      filename);
-		return templates;
+		return;
 	}
 
-	templates = lgl_xml_template_parse_templates_doc (templates_doc);
+	lgl_xml_template_parse_templates_doc (templates_doc);
 
 	g_free (filename);
 	xmlFreeDoc (templates_doc);
-
-	return templates;
 }
 
 
@@ -139,11 +138,10 @@ lgl_xml_template_read_templates_from_file (const gchar *utf8_filename)
  * Returns: a list of #lglTemplate structures.
  *
  */
-GList *
+void
 lgl_xml_template_parse_templates_doc (const xmlDocPtr templates_doc)
 {
 	
-	GList       *templates = NULL;
 	xmlNodePtr   root, node;
 	lglTemplate *template;
 
@@ -153,19 +151,20 @@ lgl_xml_template_parse_templates_doc (const xmlDocPtr templates_doc)
 	if (!root || !root->name) {
 		g_message ("\"%s\" is not a glabels template file (no root node)",
 			   templates_doc->URL);
-		return templates;
+		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 templates;
+		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);
-			templates = g_list_append (templates, template);
+                        _lgl_db_register_template_internal (template);
+                        lgl_template_free (template);
 		} else {
 			if ( !xmlNodeIsText(node) ) {
 				if (!lgl_xml_is_node (node,"comment")) {
@@ -174,8 +173,6 @@ lgl_xml_template_parse_templates_doc (const xmlDocPtr templates_doc)
 			}
 		}
 	}
-
-	return templates;
 }
 
 
@@ -194,10 +191,11 @@ 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;
+	lglPaper              *paper = NULL;
 	lglTemplate           *template;
 	xmlNodePtr             node;
         gchar                **v;
@@ -222,6 +220,10 @@ lgl_xml_template_parse_template_node (const xmlNodePtr template_node)
                 }
         }
 
+
+        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);
 
@@ -254,8 +256,23 @@ lgl_xml_template_parse_template_node (const xmlNodePtr template_node)
 		paper = NULL;
 	}
 
-	template = lgl_template_new (brand, part, description,
-                                     paper_id, page_width, page_height);
+
+        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) {
@@ -280,6 +297,7 @@ lgl_xml_template_parse_template_node (const xmlNodePtr template_node)
 
 	g_free (brand);
 	g_free (part);
+	g_free (equiv_part);
 	g_free (description);
 	g_free (paper_id);
 
@@ -293,11 +311,18 @@ static void
 xml_parse_meta_node (xmlNodePtr   meta_node,
 		     lglTemplate *template)
 {
+        gchar               *product_url;
 	gchar               *category;
 
-	category = lgl_xml_get_prop_string (meta_node, "category", NULL);
+        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;
+        }
 
-	if (category != NULL)
+	category = lgl_xml_get_prop_string (meta_node, "category", NULL);
+	if ( category != NULL )
 	{
 		lgl_template_add_category (template, category);
 		g_free (category);
@@ -746,9 +771,10 @@ lgl_xml_template_create_template_node (const lglTemplate *template,
 			xml_create_alias_node ( alias, node, ns );
 		}
 	}
+        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 ( p->data, node, ns );
+                xml_create_meta_node ( "category", p->data, node, ns );
 	}
 	for ( p=template->frames; p != NULL; p=p->next )
         {
@@ -759,17 +785,21 @@ lgl_xml_template_create_template_node (const lglTemplate *template,
 }
 
 /*--------------------------------------------------------------------------*/
-/* PRIVATE.  Add XML Template->Meta Node.                                   */
+/* PRIVATE.  Add XML Template->Meta Node with category.                     */
 /*--------------------------------------------------------------------------*/
 static void
-xml_create_meta_node (const gchar      *category,
-		      xmlNodePtr        root,
-		      const xmlNsPtr    ns)
+xml_create_meta_node (const gchar      *attr,
+                      const gchar      *value,
+                      xmlNodePtr        root,
+                      const xmlNsPtr    ns)
 {
 	xmlNodePtr node;
 
-	node = xmlNewChild (root, ns, (xmlChar *)"Meta", NULL);
-	lgl_xml_set_prop_string (node, "category", category);
+        if ( value != NULL )
+        {
+                node = xmlNewChild (root, ns, (xmlChar *)"Meta", NULL);
+                lgl_xml_set_prop_string (node, attr, value);
+        }
 
 }
 
diff --git a/libglabels/xml-template.h b/libglabels/xml-template.h
index 205faa7..3c32349 100644
--- a/libglabels/xml-template.h
+++ b/libglabels/xml-template.h
@@ -28,9 +28,9 @@
 
 G_BEGIN_DECLS
 
-GList       *lgl_xml_template_read_templates_from_file (const gchar       *utf8_filename);
+void         lgl_xml_template_read_templates_from_file (const gchar       *utf8_filename);
 
-GList       *lgl_xml_template_parse_templates_doc      (const xmlDocPtr    templates_doc);
+void         lgl_xml_template_parse_templates_doc      (const xmlDocPtr    templates_doc);
 
 lglTemplate *lgl_xml_template_parse_template_node      (const xmlNodePtr   template_node);
 
diff --git a/libglabels/xml-vendor.c b/libglabels/xml-vendor.c
new file mode 100644
index 0000000..153f935
--- /dev/null
+++ b/libglabels/xml-vendor.c
@@ -0,0 +1,176 @@
+/*
+ *  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;
+        gchar                 *url;
+
+
+	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
+ */
diff --git a/libglabels/xml-vendor.h b/libglabels/xml-vendor.h
new file mode 100644
index 0000000..a565eb0
--- /dev/null
+++ b/libglabels/xml-vendor.h
@@ -0,0 +1,51 @@
+/*
+ *  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
+ */
diff --git a/templates/Makefile.am b/templates/Makefile.am
index e740e61..cf2cd1e 100644
--- a/templates/Makefile.am
+++ b/templates/Makefile.am
@@ -10,6 +10,7 @@ templatesdir = $(datadir)/glabels/templates
 templates_DATA = \
 	paper-sizes.xml \
 	categories.xml \
+	vendors.xml \
 	avery-us-templates.xml \
 	avery-iso-templates.xml \
 	avery-other-templates.xml \
diff --git a/templates/avery-us-templates.xml b/templates/avery-us-templates.xml
index 6626ed0..a1861aa 100644
--- a/templates/avery-us-templates.xml
+++ b/templates/avery-us-templates.xml
@@ -40,7 +40,7 @@
   <!-- ******************************************************************** -->
 
   <!-- =================================================================== -->
-  <!-- Avery 5160 family: Address Labels, 1'' x 2_5/8'', 30 per sheet    x -->
+  <!-- Avery 5160 family: Address Labels, 2_5/8'' x 1'', 20 per sheet      -->
   <!-- =================================================================== -->
   <Template brand="Avery" part="5160" size="US-Letter" _description="Address Labels">
     <Meta category="label"/>
@@ -49,41 +49,42 @@
       <Markup-margin size="0.0625in"/>
       <Layout nx="3" ny="10" x0="0.1875in" y0="0.5in" dx="2.75in" dy="1in"/>
     </Label-rectangle>
-    <Alias brand="Avery" part="5260"/>
-    <Alias brand="Avery" part="5510"/>
-    <Alias brand="Avery" part="5520"/>
-    <Alias brand="Avery" part="5560"/>
-    <Alias brand="Avery" part="5810"/>
-    <Alias brand="Avery" part="5920"/>
-    <Alias brand="Avery" part="5960"/>
-    <Alias brand="Avery" part="5970"/>
-    <Alias brand="Avery" part="5971"/>
-    <Alias brand="Avery" part="5972"/>
-    <Alias brand="Avery" part="5979"/>
-    <Alias brand="Avery" part="5980"/>
-    <Alias brand="Avery" part="6231"/>
-    <Alias brand="Avery" part="6233"/>
-    <Alias brand="Avery" part="6245"/>
-    <Alias brand="Avery" part="6460"/>
-    <Alias brand="Avery" part="6498"/>
-    <Alias brand="Avery" part="8160"/>
-    <Alias brand="Avery" part="8250"/>
-    <Alias brand="Avery" part="8460"/>
-    <Alias brand="Avery" part="8560"/>
-    <Alias brand="Avery" part="8620"/>
-    <Alias brand="Avery" part="8660"/>
-    <Alias brand="Avery" part="8810"/>
-    <Alias brand="Avery" part="8920"/>
-    <Alias brand="Avery" part="8930"/>
-    <Alias brand="Avery" part="15160"/>
-    <Alias brand="Avery" part="18160"/>
-    <Alias brand="Avery" part="18660"/>
-    <Alias brand="Avery" part="25160"/>
     <!-- Look alikes -->
     <Alias brand="Maco" part="ll5805"/>
     <Alias brand="Worldlabel" part="OL875"/>
   </Template>
 
+  <Template brand="Avery" part="5260" equiv="5160"/>
+  <Template brand="Avery" part="5510" equiv="5160"/>
+  <Template brand="Avery" part="5520" equiv="5160"/>
+  <Template brand="Avery" part="5560" equiv="5160"/>
+  <Template brand="Avery" part="5810" equiv="5160"/>
+  <Template brand="Avery" part="5920" equiv="5160"/>
+  <Template brand="Avery" part="5960" equiv="5160"/>
+  <Template brand="Avery" part="5970" equiv="5160"/>
+  <Template brand="Avery" part="5971" equiv="5160"/>
+  <Template brand="Avery" part="5972" equiv="5160"/>
+  <Template brand="Avery" part="5979" equiv="5160"/>
+  <Template brand="Avery" part="5980" equiv="5160"/>
+  <Template brand="Avery" part="6231" equiv="5160"/>
+  <Template brand="Avery" part="6233" equiv="5160"/>
+  <Template brand="Avery" part="6245" equiv="5160"/>
+  <Template brand="Avery" part="6460" equiv="5160"/>
+  <Template brand="Avery" part="6498" equiv="5160"/>
+  <Template brand="Avery" part="8160" equiv="5160"/>
+  <Template brand="Avery" part="8250" equiv="5160"/>
+  <Template brand="Avery" part="8460" equiv="5160"/>
+  <Template brand="Avery" part="8560" equiv="5160"/>
+  <Template brand="Avery" part="8620" equiv="5160"/>
+  <Template brand="Avery" part="8660" equiv="5160"/>
+  <Template brand="Avery" part="8810" equiv="5160"/>
+  <Template brand="Avery" part="8920" equiv="5160"/>
+  <Template brand="Avery" part="8930" equiv="5160"/>
+  <Template brand="Avery" part="15160" equiv="5160"/>
+  <Template brand="Avery" part="18160" equiv="5160"/>
+  <Template brand="Avery" part="18660" equiv="5160"/>
+  <Template brand="Avery" part="25160" equiv="5160"/>
+
   <!-- =================================================================== -->
   <!-- Avery 5161 family: Address Labels, 1'' x 4'', 20 per sheet        x -->
   <!-- =================================================================== -->
diff --git a/templates/glabels-2.2.dtd b/templates/glabels-2.3.dtd
similarity index 91%
rename from templates/glabels-2.2.dtd
rename to templates/glabels-2.3.dtd
index 9525e77..c788c33 100644
--- a/templates/glabels-2.2.dtd
+++ b/templates/glabels-2.3.dtd
@@ -1,5 +1,5 @@
 <!--
-  glabels-2.2.dtd
+  glabels-2.3.dtd
 
   This file is a part of the glabels template database.
  
@@ -103,6 +103,16 @@
 
 <!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
 <!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
+<!-- Top-level glabels vendors data base                                  -->
+<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
+<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
+<!ELEMENT Glabels-vendors (Vendor*)>
+<!ATTLIST Glabels-vendors
+                 xmlns           %STRING_TYPE;           #IMPLIED
+>
+
+<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
+<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
 <!-- Top-level glabels template data base                                 -->
 <!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
 <!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
@@ -145,17 +155,27 @@
 >
 
 <!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
+<!-- Vendor                                                               -->
+<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
+<!ELEMENT Vendor EMPTY>
+<!ATTLIST Vendor
+                 name            %STRING_TYPE;           #REQUIRED
+                 url             %STRING_TYPE;           #IMPLIED
+>
+
+<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
 <!-- Template Section                                                     -->
 <!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
 <!ENTITY % label_element  "Label-rectangle | Label-round | Label-cd">
 <!ENTITY % markup_element "Markup-margin | Markup-line | Markup-circle | Markup-rect">
 
-<!ELEMENT Template (Meta*, (%label_element;)+, Alias*)>
+<!ELEMENT Template (Meta*, (%label_element;)*, Alias*)>
 <!ATTLIST Template
                  brand           %STRING_TYPE;           #REQUIRED
                  part            %STRING_TYPE;           #REQUIRED
                  name            %STRING_TYPE;           #IMPLIED
-                 size            %STRING_TYPE;           #REQUIRED
+	         equiv           %STRING_TYPE;           #IMPLIED
+                 size            %STRING_TYPE;           #IMPLIED
                  width           %LENGTH_TYPE;           #IMPLIED
                  height          %LENGTH_TYPE;           #IMPLIED
                  description     %STRING_TYPE;           #IMPLIED
@@ -164,7 +184,8 @@
 
 <!ELEMENT Meta EMPTY>
 <!ATTLIST Meta
-                 category        %STRING_TYPE;           #REQUIRED
+                 product_url     %STRING_TYPE;           #IMPLIED
+                 category        %STRING_TYPE;           #IMPLIED
 >
 
 <!ELEMENT Label-rectangle ((%markup_element;)*, Layout+)>
@@ -289,7 +310,11 @@
 >
 
 <!ENTITY % shadow_attrs
-                 ""
+                 "shadow          %BOOLEAN_TYPE;         #IMPLIED
+		  shadow_x        %FLOAT_TYPE;           #IMPLIED
+		  shadow_y        %FLOAT_TYPE;           #IMPLIED
+		  shadow_color    %UINT_TYPE;            #IMPLIED
+		  shadow_opacity  %FLOAT_TYPE;           #IMPLIED"
 >
 
 <!ELEMENT Object-text (Span)>
diff --git a/templates/vendors.xml b/templates/vendors.xml
new file mode 100644
index 0000000..887d07f
--- /dev/null
+++ b/templates/vendors.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+
+<!--
+  vendors.xml
+  This file is a part of the glabels template database.
+ 
+  Copyright (c) 2001-2009 Jim Evins
+ 
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation
+  files (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use,
+  copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the
+  Software is furnished to do so, subject to the following
+  conditions:
+ 
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+ 
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+  OTHER DEALINGS IN THE SOFTWARE.
+-->
+
+<Glabels-vendors>
+
+  <Vendor name="Avery"          url="http://www.avery.com/";           />
+  <Vendor name="Brother"        url="http://www.brother-usa.com/";     />
+  <Vendor name="Dymo"           url="http://global.dymo.com/";         />
+  <Vendor name="Maco"           url="http://www.maco.com/";            />
+  <Vendor name="Online Labels"  url="http://www.onlinelabels.com/";    />
+  <Vendor name="Worldlabel"     url="http://www.worldlabel.com/";      />
+  <Vendor name="Zweckform"      url="http://www.avery-zweckform.com/"; />
+
+
+</Glabels-vendors>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]