2 * (LIBGLABELS) Template library for GLABELS
4 * xml.c: GLabels xml utilities module
6 * Copyright (C) 2003, 2004 Jim Evins <evins@snaught.com>.
8 * This file is part of the LIBGLABELS library.
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
20 * You should have received a copy of the GNU Library General Public
21 * License along with this library; if not, write to the Free
22 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
29 #include <glib/gi18n.h>
30 #include <glib/gstrfuncs.h>
31 #include <glib/gmessages.h>
34 #include "libglabels-private.h"
37 /*========================================================*/
38 /* Private macros and constants. */
39 /*========================================================*/
41 #define POINTS_PER_POINT 1.0 /* internal units are points. */
42 #define POINTS_PER_INCH 72.0
43 #define POINTS_PER_MM 2.83464566929
44 #define POINTS_PER_CM (10.0*POINTS_PER_MM)
45 #define POINTS_PER_PICA (1.0/12.0)
47 /*========================================================*/
49 /*========================================================*/
53 gdouble points_per_unit;
56 /*========================================================*/
57 /* Private globals. */
58 /*========================================================*/
60 static UnitTableEntry unit_table[] = {
62 /* These names are identical to the absolute length units supported in
63 the CSS2 Specification (Section 4.3.2) */
65 /* This table must be sorted exactly as the enumerations in lglUnitsType */
67 /* [LGL_UNITS_POINT] */ {(xmlChar *)"pt", POINTS_PER_POINT},
68 /* [LGL_UNITS_INCH] */ {(xmlChar *)"in", POINTS_PER_INCH},
69 /* [LGL_UNITS_MM] */ {(xmlChar *)"mm", POINTS_PER_MM},
70 /* [LGL_UNITS_CM] */ {(xmlChar *)"cm", POINTS_PER_CM},
71 /* [LGL_UNITS_PICA] */ {(xmlChar *)"pc", POINTS_PER_PICA},
75 static lglUnitsType default_units = LGL_UNITS_POINT;
78 /****************************************************************************/
81 * lgl_xml_get_prop_string:
82 * @node: the libxml2 #xmlNodePtr of the node
83 * @property: the property name
84 * @default_val: a default value to return if property not found
86 * Return value of property as a string.
88 * Returns: the property as a pointer to a gchar string. This string should
89 * be freed with g_free().
93 lgl_xml_get_prop_string (xmlNodePtr node,
94 const gchar *property,
95 const gchar *default_val)
100 string = xmlGetProp (node, (xmlChar *)property);
101 if ( string != NULL ) {
102 val = g_strdup ((gchar *)string);
108 return g_strdup (default_val);
116 * lgl_xml_get_prop_i18n_string:
117 * @node: the libxml2 #xmlNodePtr of the node
118 * @property: the property name
119 * @default_val: a default value to return if property not found
121 * Return value of a translatable property as a string.
123 * Returns: the property as a pointer to a gchar string. This string should
124 * be freed with g_free().
128 lgl_xml_get_prop_i18n_string (xmlNodePtr node,
129 const gchar *property,
130 const gchar *default_val)
136 _property = g_strdup_printf ("_%s", property);
137 string = xmlGetProp (node, (xmlChar *)_property);
140 if ( string != NULL ) {
142 val = g_strdup (gettext ((char *)string));
148 string = xmlGetProp (node, (xmlChar *)property);
149 if ( string != NULL ) {
150 val = g_strdup ((gchar *)string);
156 return g_strdup (default_val);
164 * lgl_xml_get_prop_double:
165 * @node: the libxml2 #xmlNodePtr of the node
166 * @property: the property name
167 * @default_val: a default value to return if property not found
169 * Return value of property as a double.
171 * Returns: the property as a double.
175 lgl_xml_get_prop_double (xmlNodePtr node,
176 const gchar *property,
182 string = xmlGetProp (node, (xmlChar *)property);
183 if ( string != NULL ) {
184 val = g_strtod ((gchar *)string, NULL);
194 * lgl_xml_get_prop_boolean:
195 * @node: the libxml2 #xmlNodePtr of the node
196 * @property: the property name
197 * @default_val: a default value to return if property not found
199 * Return value of property as a boolean.
201 * Returns: the property as a boolean.
205 lgl_xml_get_prop_boolean (xmlNodePtr node,
206 const gchar *property,
207 gboolean default_val)
212 string = xmlGetProp (node, (xmlChar *)property);
213 if ( string != NULL ) {
214 val = !((xmlStrcasecmp (string, (xmlChar *)"false") == 0) ||
215 xmlStrEqual (string, (xmlChar *)"0"));;
225 * lgl_xml_get_prop_int:
226 * @node: the libxml2 #xmlNodePtr of the node
227 * @property: the property name
228 * @default_val: a default value to return if property not found
230 * Return value of property as an integer.
232 * Returns: the property as an integer.
236 lgl_xml_get_prop_int (xmlNodePtr node,
237 const gchar *property,
243 string = xmlGetProp (node, (xmlChar *)property);
244 if ( string != NULL ) {
245 val = strtol ((char *)string, NULL, 0);
255 * lgl_xml_get_prop_uint:
256 * @node: the libxml2 #xmlNodePtr of the node
257 * @property: the property name
258 * @default_val: a default value to return if property not found
260 * Return value of property (usually formatted in hex) as an unsigned integer.
262 * Returns: the property as an unsigned integer.
266 lgl_xml_get_prop_uint (xmlNodePtr node,
267 const gchar *property,
273 string = xmlGetProp (node, (xmlChar *)property);
274 if ( string != NULL ) {
275 val = strtoul ((char *)string, NULL, 0);
285 * lgl_xml_get_prop_length:
286 * @node: the libxml2 #xmlNodePtr of the node
287 * @property: the property name
288 * @default_val: a default value to return if property not found
290 * Return value of a length property as a double, converting to internal
291 * units (points). The property is expected to be formatted as a number
292 * followed by a units string. If there is no units string, the length
293 * is assumed to be in points. Valid units strings are "pt" for points,
294 * "in" for inches, "mm" for millimeters, "cm" for centimeters, and
297 * Returns: the length in points.
301 lgl_xml_get_prop_length (xmlNodePtr node,
302 const gchar *property,
310 string = xmlGetProp (node, (xmlChar *)property);
311 if ( string != NULL ) {
313 val = g_strtod ((gchar *)string, (gchar **)&unit);
315 if (unit != string) {
316 unit = (xmlChar *)g_strchug ((gchar *)unit);
317 if (strlen ((char *)unit) > 0 ) {
318 for (i=LGL_UNITS_FIRST; i<=LGL_UNITS_LAST; i++) {
319 if (xmlStrcasecmp (unit, unit_table[i].name) == 0) {
320 val *= unit_table[i].points_per_unit;
324 if (i>LGL_UNITS_LAST) {
325 g_message ("Line %ld, Node \"%s\", Property \"%s\": Unknown unit \"%s\", assuming points",
326 xmlGetLineNo (node), node->name, property,
344 * lgl_xml_set_prop_string:
345 * @node: the libxml2 #xmlNodePtr of the node
346 * @property: the property name
347 * @val: the value to set
349 * Set a property from a string.
353 lgl_xml_set_prop_string (xmlNodePtr node,
354 const gchar *property,
358 xmlSetProp (node, (xmlChar *)property, (xmlChar *)val);
364 * lgl_xml_set_prop_double:
365 * @node: the libxml2 #xmlNodePtr of the node
366 * @property: the property name
367 * @val: the value to set
369 * Set a property from a double.
373 lgl_xml_set_prop_double (xmlNodePtr node,
374 const gchar *property,
377 gchar *string, buffer[G_ASCII_DTOSTR_BUF_SIZE];
379 /* Guarantee "C" locale by use of g_ascii_formatd */
380 string = g_ascii_formatd (buffer, G_ASCII_DTOSTR_BUF_SIZE, "%g", val);
382 xmlSetProp (node, (xmlChar *)property, (xmlChar *)string);
387 * lgl_xml_set_prop_boolean:
388 * @node: the libxml2 #xmlNodePtr of the node
389 * @property: the property name
390 * @val: the value to set
392 * Set a property from a boolean.
396 lgl_xml_set_prop_boolean (xmlNodePtr node,
397 const gchar *property,
400 xmlSetProp (node, (xmlChar *)property, (xmlChar *)(val ? "True" : "False"));
404 * lgl_xml_set_prop_int:
405 * @node: the libxml2 #xmlNodePtr of the node
406 * @property: the property name
407 * @val: the value to set
409 * Set a property from an integer.
413 lgl_xml_set_prop_int (xmlNodePtr node,
414 const gchar *property,
419 string = g_strdup_printf ("%d", val);
420 xmlSetProp (node, (xmlChar *)property, (xmlChar *)string);
425 * lgl_xml_set_prop_uint_hex:
426 * @node: the libxml2 #xmlNodePtr of the node
427 * @property: the property name
428 * @val: the value to set
430 * Set a property from an unsigned integer and format in hex.
434 lgl_xml_set_prop_uint_hex (xmlNodePtr node,
435 const gchar *property,
440 string = g_strdup_printf ("0x%08x", val);
441 xmlSetProp (node, (xmlChar *)property, (xmlChar *)string);
446 * lgl_xml_set_prop_length:
447 * @node: the libxml2 #xmlNodePtr of the node
448 * @property: the property name
449 * @val: the length to set in internal units (points)
451 * Set a property from a length, performing any necessary conversion.
452 * Length properties are formatted as a number followed by a units string.
453 * The units of the formatted property is determined by the most recent call to
454 * lgl_xml_set_default_units().
458 lgl_xml_set_prop_length (xmlNodePtr node,
459 const gchar *property,
462 gchar *string, buffer[G_ASCII_DTOSTR_BUF_SIZE];
465 /* Convert to default units */
466 val /= unit_table[default_units].points_per_unit;
468 /* Guarantee "C" locale by use of g_ascii_formatd */
469 string = g_ascii_formatd (buffer, G_ASCII_DTOSTR_BUF_SIZE, "%g", val);
471 string_unit = g_strdup_printf ("%s%s", string, unit_table[default_units].name);
472 xmlSetProp (node, (xmlChar *)property, (xmlChar *)string_unit);
473 g_free (string_unit);
478 * @node: the libxml2 #xmlNodePtr of the node
479 * @name : the node name
481 * Test if a node name matches given name.
483 * Returns: TRUE if the name of the node matches. Otherwise FALSE.
487 lgl_xml_is_node (xmlNodePtr node,
490 return xmlStrEqual (node->name, (xmlChar *)name);
495 * lgl_xml_get_node_content
496 * @node: the libxml2 #xmlNodePtr of the node
498 * Get the content of a node.
500 * Returns: the property as a pointer to a gchar string. This string should
501 * be freed with g_free().
504 lgl_xml_get_node_content (xmlNodePtr node)
506 xmlChar *xml_content;
509 xml_content = xmlNodeGetContent (node);
511 if (xml_content != NULL) {
513 g_content = g_strdup ((gchar *)xml_content);
514 xmlFree (xml_content);
524 * lgl_xml_set_default_units:
525 * @units: default units selection (#lglUnitsType)
527 * Set the default units when formatting lengths. See
528 * lgl_xml_set_prop_length().
532 lgl_xml_set_default_units (lglUnitsType units)
534 g_return_if_fail ((units >= LGL_UNITS_FIRST) && (units <= LGL_UNITS_LAST));
536 default_units = units;