#include <libxml/xpath.h>
#include <stdlib.h>
#include "xalloc.h"
+#include "xvasprintf.h"
#define _(str) gettext (str)
return NULL;
}
+static void
+its_value_list_set_value (struct its_value_list_ty *values,
+ const char *name,
+ const char *value)
+{
+ size_t i;
+
+ for (i = 0; i < values->nitems; i++)
+ {
+ struct its_value_ty *_value = &values->items[i];
+ if (strcmp (_value->name, name) == 0)
+ {
+ free (_value->value);
+ _value->value = xstrdup (value);
+ break;
+ }
+ }
+
+ if (i == values->nitems)
+ its_value_list_append (values, name, value);
+}
+
static void
its_value_list_merge (struct its_value_list_ty *values,
struct its_value_list_ty *other)
return result;
}
-static const char *
+static char *
_its_collect_text_content (xmlNode *node)
{
- static char *buffer;
- static size_t bufmax;
+ char *buffer = NULL;
+ size_t bufmax = 0;
size_t bufpos = 0;
xmlNode *n;
for (n = node->children; n; n = n->next)
- if (n->type == XML_TEXT_NODE)
- {
- xmlChar *content = xmlNodeGetContent (n);
- size_t content_length = xmlStrlen (content);
+ {
+ char *content = NULL;
+
+ switch (n->type)
+ {
+ case XML_TEXT_NODE:
+ {
+ xmlChar *xcontent = xmlNodeGetContent (n);
+ content = xstrdup ((const char *) xcontent);
+ xmlFree (xcontent);
+ }
+ break;
- if (bufpos >= bufmax)
+ case XML_ELEMENT_NODE:
{
- bufmax = 2 * bufmax + content_length + 1;
- buffer = xrealloc (buffer, bufmax);
+ char *p = _its_collect_text_content (n);
+ content = xasprintf ("<%s>%s</%s>", n->name, p, n->name);
+ free (p);
}
- memcpy (&buffer[bufpos], content, content_length);
- bufpos += content_length;
- buffer[bufpos] = 0;
- }
+ break;
+
+ default:
+ break;
+ }
+
+ if (content != NULL)
+ {
+ size_t length = strlen (content);
+
+ if (bufpos + length + 1 >= bufmax)
+ {
+ bufmax = 2 * bufmax + length + 1;
+ buffer = xrealloc (buffer, bufmax);
+ }
+ strcpy (&buffer[bufpos], content);
+ bufpos += length;
+ }
+ free (content);
+ }
+
+ if (buffer == NULL)
+ buffer = xstrdup ("");
return buffer;
}
/* Inherit from the parent elements. */
for (n = node; n && n->type == XML_ELEMENT_NODE; n = n->parent)
- if ((intptr_t) n->_private > 0)
- break;
-
- if (n == NULL || (intptr_t) n->_private == 0)
- /* The default value is translate="yes". */
- its_value_list_append (result, "translate", "yes");
- else
{
intptr_t index = (intptr_t) n->_private;
- struct its_value_list_ty *values;
+ if (index > 0)
+ {
+ struct its_value_list_ty *values;
+ const char *value;
- assert (index <= pool->nitems);
- values = &pool->items[index - 1];
- its_value_list_merge (result, values);
+ assert (index <= pool->nitems);
+ values = &pool->items[index - 1];
+
+ value = its_value_list_get_value (values, "translate");
+ if (value != NULL)
+ {
+ its_value_list_set_value (result, "translate", value);
+ return result;
+ }
+ }
}
+ /* The default value is translate="yes". */
+ its_value_list_append (result, "translate", "yes");
return result;
}
}
if (n)
- its_value_list_append (&pop->values, "locNote",
- _its_collect_text_content (n));
+ {
+ char *content = _its_collect_text_content (n);
+ its_value_list_append (&pop->values, "locNote", content);
+ free (content);
+ }
else if (xmlHasProp (node, BAD_CAST "locNotePointer"))
{
prop = _its_get_attribute (node, "locNotePointer");
/* Inherit from the parent elements. */
for (n = node; n && n->type == XML_ELEMENT_NODE; n = n->parent)
- if ((intptr_t) n->_private > 0)
- break;
+ {
+ intptr_t index = (intptr_t) n->_private;
+ if (index > 0)
+ {
+ struct its_value_list_ty *values;
+ const char *value;
+
+ assert (index <= pool->nitems);
+ values = &pool->items[index - 1];
+
+ value = its_value_list_get_value (values, "locNote");
+ if (value != NULL)
+ {
+ its_value_list_set_value (result, "locNote", value);
+ return result;
+ }
+
+ value = its_value_list_get_value (values, "locNotePointer");
+ if (value != NULL)
+ {
+ its_value_list_set_value (result, "locNotePointer", value);
+ return result;
+ }
+ }
+ }
/* The default value is None. */
- if (n != NULL && (intptr_t) n->_private > 0)
+ return result;
+}
+
+static struct its_rule_class_ty its_localization_note_rule_class =
+ {
+ sizeof (struct its_rule_ty),
+ its_localization_note_rule_constructor,
+ its_rule_destructor,
+ its_rule_apply,
+ its_localization_note_rule_eval,
+ };
+
+/* Implementation of Element Within Text data category. */
+static void
+its_element_within_text_rule_constructor (struct its_rule_ty *pop,
+ xmlNode *node)
+{
+ char *prop;
+
+ if (!xmlHasProp (node, BAD_CAST "selector"))
+ {
+ error (0, 0, _("\"withinTextRule\" node does not contain \"selector\""));
+ return;
+ }
+
+ if (!xmlHasProp (node, BAD_CAST "withinText"))
+ {
+ error (0, 0,
+ _("\"withinTextRule\" node does not contain \"withinText\""));
+ return;
+ }
+
+ prop = _its_get_attribute (node, "selector");
+ if (prop)
+ pop->selector = prop;
+
+ prop = _its_get_attribute (node, "withinText");
+ its_value_list_append (&pop->values, "withinText", prop);
+ free (prop);
+}
+
+struct its_value_list_ty *
+its_element_within_text_rule_eval (struct its_rule_ty *pop,
+ struct its_pool_ty *pool,
+ xmlNode *node)
+{
+ struct its_value_list_ty *result;
+ intptr_t index;
+
+ result = XCALLOC (1, struct its_value_list_ty);
+
+ /* Doesn't inherit from the parent elements, and the default value
+ is None. */
+ index = (intptr_t) node->_private;
+ if (index > 0)
{
- intptr_t index = (intptr_t) n->_private;
struct its_value_list_ty *values;
+ const char *value;
assert (index <= pool->nitems);
values = &pool->items[index - 1];
- its_value_list_merge (result, values);
+
+ value = its_value_list_get_value (values, "withinText");
+ if (value != NULL)
+ its_value_list_set_value (result, "withinText", value);
}
return result;
}
-static struct its_rule_class_ty its_localization_note_rule_class =
+static struct its_rule_class_ty its_element_within_text_rule_class =
{
sizeof (struct its_rule_ty),
- its_localization_note_rule_constructor,
+ its_element_within_text_rule_constructor,
its_rule_destructor,
its_rule_apply,
- its_localization_note_rule_eval,
+ its_element_within_text_rule_eval,
};
static struct its_rule_ty *
ADD_RULE_CLASS ("translateRule", its_translate_rule_class);
ADD_RULE_CLASS ("locNoteRule", its_localization_note_rule_class);
+ ADD_RULE_CLASS ("withinTextRule", its_element_within_text_rule_class);
#undef ADD_RULE_CLASS
}
size_t i;
for (i = 0; i < rules->nitems; i++)
- its_rule_destroy (rules->items[i]);
+ {
+ its_rule_destroy (rules->items[i]);
+ free (rules->items[i]);
+ }
free (rules->items);
its_pool_destroy (&rules->pool);
}
rule = its_rule_parse (node);
if (!rule)
- {
- xmlFreeDoc (doc);
- return false;
- }
+ continue;
if (rules->nitems == rules->nitems_max)
{
return result;
}
+static bool
+its_rule_list_is_translatable (its_rule_list_ty *rules,
+ xmlNode *node,
+ int depth)
+{
+ struct its_value_list_ty *values;
+ const char *value;
+ xmlNode *n;
+
+ if (node->type != XML_ELEMENT_NODE)
+ return false;
+
+ values = its_rule_list_eval (rules, node);
+
+ /* Check if NODE has translate="yes". */
+ value = its_value_list_get_value (values, "translate");
+ if (!(value && strcmp (value, "yes") == 0))
+ {
+ its_value_list_destroy (values);
+ free (values);
+ return false;
+ }
+
+ /* Check if NODE has withinText="yes", if NODE is not top-level. */
+ if (depth > 0)
+ {
+ value = its_value_list_get_value (values, "withinText");
+ if (!(value && strcmp (value, "yes") == 0))
+ {
+ its_value_list_destroy (values);
+ free (values);
+ return false;
+ }
+ }
+
+ its_value_list_destroy (values);
+ free (values);
+
+ for (n = node->children; n; n = n->next)
+ {
+ switch (n->type)
+ {
+ case XML_ELEMENT_NODE:
+ if (!its_rule_list_is_translatable (rules, n, depth + 1))
+ return false;
+ break;
+
+ case XML_TEXT_NODE:
+ break;
+
+ default:
+ return false;
+ }
+ }
+
+ return true;
+}
+
static void
its_rule_list_extract_nodes (its_rule_list_ty *rules,
struct its_node_list_ty *nodes,
- xmlNode *node,
- const struct its_value_ty *values)
+ xmlNode *node)
{
if (node->type == XML_ELEMENT_NODE)
{
- struct its_value_list_ty *element_values;
- size_t i;
xmlNode *n;
- element_values = its_rule_list_eval (rules, node);
- for (i = 0; values[i].name != NULL; i++)
+ if (its_rule_list_is_translatable (rules, node, 0))
+ its_node_list_append (nodes, node);
+ else
{
- size_t j;
-
- for (j = 0; j < element_values->nitems; j++)
- {
- struct its_value_ty *element_value = &element_values->items[j];
- if (strcmp (values[i].name, element_value->name) == 0
- && strcmp (values[i].value, element_value->value) == 0)
- break;
- }
-
- if (j == element_values->nitems)
- break;
+ for (n = node->children; n; n = n->next)
+ its_rule_list_extract_nodes (rules, nodes, n);
}
-
- if (values[i].name == NULL)
- its_node_list_append (nodes, node);
-
- for (n = node->children; n; n = n->next)
- its_rule_list_extract_nodes (rules, nodes, n, values);
}
}
string_list_init (&sl);
for (i = 0; i < nodes->nodeNr; i++)
- string_list_append (&sl, _its_collect_text_content (nodes->nodeTab[i]));
+ {
+ char *content = _its_collect_text_content (nodes->nodeTab[i]);
+ string_list_append (&sl, content);
+ free (content);
+ }
result = string_list_concat (&sl);
+ string_list_destroy (&sl);
}
xmlXPathFreeObject (object);
if (node->type == XML_ELEMENT_NODE)
{
struct its_value_list_ty *values;
- xmlNode *n;
const char *value;
+ char *msgid;
+ char *content;
char *comment = NULL;
values = its_rule_list_eval (rules, node);
comment = _its_get_content (node, value);
}
- for (n = node->children; n; n = n->next)
- if (n->type == XML_TEXT_NODE)
- {
- xmlChar *content = xmlNodeGetContent (n);
-
- if (xmlStrlen (content) > 0)
- {
- lex_pos_ty pos;
-
- pos.file_name = xstrdup (logical_filename);
- pos.line_number = xmlGetLineNo (n);
-
- remember_a_message (mlp, NULL,
- xstrdup ((const char *) content),
- null_context, &pos,
- comment, NULL);
- free (comment);
- }
- xmlFree (content);
- }
+ value = its_value_list_get_value (values, "withinText");
+
+ content = _its_collect_text_content (node);
+ if (value && strcmp (value, "yes") == 0)
+ msgid = xasprintf ("<%s>%s</%s>", node->name, content, node->name);
+ else
+ msgid = xstrdup (content);
+ free (content);
+
+ its_value_list_destroy (values);
+ free (values);
+
+ if (*msgid != '\0')
+ {
+ lex_pos_ty pos;
+
+ pos.file_name = xstrdup (logical_filename);
+ pos.line_number = xmlGetLineNo (node);
+
+ remember_a_message (mlp, NULL,
+ msgid,
+ null_context, &pos,
+ comment, NULL);
+ }
+ free (comment);
}
}
flag_context_list_table_ty *flag_table,
msgdomain_list_ty *mdlp)
{
- const struct its_value_ty values[] =
- {
- { "translate", "yes" },
- { NULL, NULL }
- };
xmlDoc *doc;
struct its_node_list_ty nodes;
size_t i;
memset (&nodes, 0, sizeof (struct its_node_list_ty));
its_rule_list_extract_nodes (rules,
&nodes,
- xmlDocGetRootElement (doc),
- values);
+ xmlDocGetRootElement (doc));
for (i = 0; i < nodes.nitems; i++)
its_rule_list_extract_text (rules, nodes.items[i],