if (leader)
ds_put_format (&s, "%s: ", leader);
pivot_value_format (cell->value, pt, &s);
- if (cell->font_style->markup)
- {
- char *t = output_get_text_from_markup (ds_cstr (&s));
- ds_assign_cstr (&s, t);
- free (t);
- }
csv_output_field (csv, ds_cstr (&s));
ds_destroy (&s);
}
else if (is_text_item (output_item))
{
const struct text_item *text_item = to_text_item (output_item);
- enum text_item_type type = text_item_get_type (text_item);
- const char *text = text_item_get_text (text_item);
+ enum text_item_type type = text_item_get_type (text_item);
if (type == TEXT_ITEM_SYNTAX || type == TEXT_ITEM_PAGE_TITLE)
return;
csv_put_separator (csv);
- if (text_item->style.markup)
- {
- char *plain_text = output_get_text_from_markup (text);
- csv_output_lines (csv, plain_text);
- free (plain_text);
- }
- else
- csv_output_lines (csv, text);
+ char *text = text_item_get_plain_text (text_item);
+ csv_output_lines (csv, text);
+ free (text);
}
else if (is_page_break_item (output_item))
{
struct string_map *options);
};
-char *output_get_text_from_markup (const char *markup);
-
#endif /* output/driver-provider.h */
#include <ctype.h>
#include <errno.h>
-#include <libxml/parser.h>
-#include <libxml/tree.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
size_t idx = --e->n_groups;
free (e->groups[idx]);
- if (idx >= 1 && idx <= 4)
- {
- char *key = xasprintf ("Head%zu", idx);
- free (string_map_find_and_delete (&e->heading_vars, key));
- free (key);
- }
+
+ char *key = xasprintf ("Head%zu", idx);
+ free (string_map_find_and_delete (&e->heading_vars, key));
+ free (key);
}
else if (is_text_item (item))
{
const struct text_item *text_item = to_text_item (item);
enum text_item_type type = text_item_get_type (text_item);
- const char *text = text_item_get_text (text_item);
- if (type == TEXT_ITEM_TITLE
- && e->n_groups >= 1 && e->n_groups <= 4)
- {
- char *key = xasprintf ("Head%zu", e->n_groups);
- string_map_replace (&e->heading_vars, key, text);
- free (key);
- }
- else if (type == TEXT_ITEM_PAGE_TITLE)
- string_map_replace (&e->heading_vars, "PageTitle", text);
+ char *key = (type == TEXT_ITEM_TITLE ? xasprintf ("Head%zu", e->n_groups)
+ : type == TEXT_ITEM_PAGE_TITLE ? xstrdup ("PageTitle")
+ : NULL);
+ if (key)
+ string_map_replace_nocopy (&e->heading_vars, key,
+ text_item_get_plain_text (text_item));
}
output_submit__ (e, item);
string_map_insert_nocopy (options, key, value);
}
\f
-/* Extracts the actual text content from the given Pango MARKUP and returns it
- as as a malloc()'d string. */
-char *
-output_get_text_from_markup (const char *markup)
-{
- xmlParserCtxt *parser = xmlCreatePushParserCtxt (NULL, NULL, NULL, 0, NULL);
- if (!parser)
- return xstrdup (markup);
-
- xmlParseChunk (parser, "<xml>", strlen ("<xml>"), false);
- xmlParseChunk (parser, markup, strlen (markup), false);
- xmlParseChunk (parser, "</xml>", strlen ("</xml>"), true);
-
- char *content
- = (parser->wellFormed
- ? CHAR_CAST (char *,
- xmlNodeGetContent (xmlDocGetRootElement (parser->myDoc)))
- : xstrdup (markup));
- xmlFreeDoc (parser->myDoc);
- xmlFreeParserCtxt (parser);
-
- return content;
-}
-
char *
output_driver_substitute_heading_vars (const char *src, int page_number)
{
else if (is_text_item (output_item))
{
struct text_item *text_item = to_text_item (output_item);
- const char *s = text_item_get_text (text_item);
+ char *s = text_item_get_plain_text (text_item);
switch (text_item_get_type (text_item))
{
fprintf (html->file, "</p>\n");
break;
}
+
+ free (s);
}
else if (is_message_item (output_item))
{
enum text_item_type type = text_item_get_type (text_item);
if (type == TEXT_ITEM_SYNTAX)
- journal_output (j, text_item_get_text (text_item));
+ {
+ char *text = text_item_get_plain_text (text_item);
+ journal_output (j, text);
+ free (text);
+ }
}
else if (is_message_item (item))
{
if (is_table_item (output_item))
write_table (odt, to_table_item (output_item));
else if (is_text_item (output_item))
- odt_output_text (odt, text_item_get_text (to_text_item (output_item)));
+ {
+ char *text = text_item_get_plain_text (to_text_item (output_item));
+ odt_output_text (odt, text);
+ free (text);
+ }
else if (is_message_item (output_item))
{
const struct message_item *message_item = to_message_item (output_item);
#include "output/pivot-table.h"
+#include <libxml/parser.h>
+#include <libxml/tree.h>
#include <math.h>
#include <stdlib.h>
: global_show);
}
+/* Appends to OUT the actual text content from the given Pango MARKUP. */
+static void
+get_text_from_markup (const char *markup, struct string *out)
+{
+ xmlParserCtxt *parser = xmlCreatePushParserCtxt (NULL, NULL, NULL, 0, NULL);
+ if (!parser)
+ {
+ ds_put_cstr (out, markup);
+ return;
+ }
+
+ xmlParseChunk (parser, "<xml>", strlen ("<xml>"), false);
+ xmlParseChunk (parser, markup, strlen (markup), false);
+ xmlParseChunk (parser, "</xml>", strlen ("</xml>"), true);
+
+ if (parser->wellFormed)
+ {
+ xmlChar *s = xmlNodeGetContent (xmlDocGetRootElement (parser->myDoc));
+ ds_put_cstr (out, CHAR_CAST (char *, s));
+ xmlFree (s);
+ }
+ else
+ ds_put_cstr (out, markup);
+ xmlFreeDoc (parser->myDoc);
+ xmlFreeParserCtxt (parser);
+}
+
/* Appends a text representation of the body of VALUE to OUT. Settings on
PT control whether variable and value labels are included.
break;
case PIVOT_VALUE_TEXT:
- ds_put_cstr (out, value->text.local);
+ if (value->font_style && value->font_style->markup)
+ get_text_from_markup (value->text.local, out);
+ else
+ ds_put_cstr (out, value->text.local);
break;
case PIVOT_VALUE_TEMPLATE:
static const struct pivot_table pt = {
.show_values = SETTINGS_VALUE_SHOW_DEFAULT,
.show_variables = SETTINGS_VALUE_SHOW_DEFAULT,
+ .settings = FMT_SETTINGS_INIT,
};
return pivot_value_to_string (value, &pt);
}
spv_text_submit (const struct spv_item *in)
{
enum spv_item_class class = spv_item_get_class (in);
- enum text_item_type type
- = (class == SPV_CLASS_HEADINGS ? TEXT_ITEM_TITLE
- : class == SPV_CLASS_PAGETITLE ? TEXT_ITEM_PAGE_TITLE
- : TEXT_ITEM_LOG);
- const struct pivot_value *value = spv_item_get_text (in);
- char *text = pivot_value_to_string_defaults (value);
- char *label = in->label ? xstrdup (in->label) : NULL;
- struct text_item *item = text_item_create_nocopy (type, text, label);
-
- if (value->font_style)
- {
- font_style_uninit (&item->style);
- font_style_copy (NULL, &item->style, value->font_style);
- }
+ struct text_item *item = text_item_create_value (
+ (class == SPV_CLASS_HEADINGS ? TEXT_ITEM_TITLE
+ : class == SPV_CLASS_PAGETITLE ? TEXT_ITEM_PAGE_TITLE
+ : TEXT_ITEM_LOG),
+ pivot_value_clone (spv_item_get_text (in)),
+ in->label ? xstrdup (in->label) : NULL);
text_item_submit (item);
}
write_attr (w, "commandName", command_id);
start_elem (w, "html");
- write_text (w, text->text); /* XXX */
+ char *s = text_item_get_plain_text (text);
+ write_text (w, s);
+ free (s);
end_elem (w); /* html */
end_elem (w); /* vtx:text */
end_elem (w); /* container */
else if (is_text_item (output_item))
{
struct text_item *text_item = to_text_item (output_item);
- const char *s = text_item_get_text (text_item);
+ char *s = text_item_get_plain_text (text_item);
switch (text_item_get_type (text_item))
{
printf ("Unhandled type %d\n", text_item_get_type (text_item));
break;
}
+ free (s);
}
else if (is_message_item (output_item))
{
struct text_item *
text_item_create_nocopy (enum text_item_type type, char *text, char *label)
{
- struct text_item *item = xzalloc (sizeof *item);
- *item = (struct text_item) {
- .output_item = OUTPUT_ITEM_INITIALIZER (&text_item_class),
- .output_item.label = label,
- .text = text,
- .type = type,
- .style = FONT_STYLE_INITIALIZER,
- };
-
- if (type == TEXT_ITEM_SYNTAX || type == TEXT_ITEM_LOG)
- {
- free (item->style.typeface);
- item->style.typeface = xstrdup ("Monospaced");
- }
-
- return item;
+ return text_item_create_value (type, pivot_value_new_user_text_nocopy (text),
+ label);
}
/* Creates and returns a new text item containing a copy of TEXT and the
label ? xstrdup (label) : NULL);
}
+/* Creates and returns a new text item containing VALUE, TYPE, and LABEL.
+ Takes ownership of VALUE and LABEL. If LABEL is null, uses a default label
+ for TYPE. */
+struct text_item *
+text_item_create_value (enum text_item_type type, struct pivot_value *value,
+ char *label)
+{
+ if (type == TEXT_ITEM_SYNTAX || type == TEXT_ITEM_LOG)
+ {
+ if (!value->font_style)
+ {
+ value->font_style = xmalloc (sizeof *value->font_style);
+ *value->font_style = (struct font_style) FONT_STYLE_INITIALIZER;
+ }
+
+ free (value->font_style->typeface);
+ value->font_style->typeface = xstrdup ("Monospaced");
+ }
+
+ struct text_item *item = xzalloc (sizeof *item);
+ *item = (struct text_item) {
+ .output_item = OUTPUT_ITEM_INITIALIZER (&text_item_class),
+ .output_item.label = label,
+ .type = type,
+ .text = value,
+ };
+ return item;
+}
+
/* Returns ITEM's type. */
enum text_item_type
text_item_get_type (const struct text_item *item)
return item->type;
}
-/* Returns ITEM's text, which the caller may not modify or free. */
-const char *
-text_item_get_text (const struct text_item *item)
+/* Returns ITEM's text, which the caller must eventually free. */
+char *
+text_item_get_plain_text (const struct text_item *item)
{
- return item->text;
+ return pivot_value_to_string_defaults (item->text);
}
/* Submits ITEM to the configured output drivers, and transfers ownership to
struct text_item *new = xmalloc (sizeof *new);
*new = (struct text_item) {
.output_item = OUTPUT_ITEM_CLONE_INITIALIZER (&old->output_item),
- .text = xstrdup (old->text),
+ .text = pivot_value_clone (old->text),
.type = old->type,
};
- font_style_copy (NULL, &new->style, &old->style);
return new;
}
+static bool
+nullable_font_style_equal (const struct font_style *a,
+ const struct font_style *b)
+{
+ return a && b ? font_style_equal (a, b) : !a && !b;
+}
+
/* Attempts to append the text in SRC to DST. If successful, returns true,
otherwise false.
|| (dst->type != TEXT_ITEM_SYNTAX && dst->type != TEXT_ITEM_LOG)
|| strcmp (output_item_get_label (&dst->output_item),
output_item_get_label (&src->output_item))
- || !font_style_equal (&dst->style, &src->style)
- || dst->style.markup)
+ || !nullable_font_style_equal (dst->text->font_style,
+ src->text->font_style)
+ || (dst->text->font_style && dst->text->font_style->markup)
+ || src->text->type != PIVOT_VALUE_TEXT
+ || dst->text->type != PIVOT_VALUE_TEXT)
return false;
else
{
- char *new_text = xasprintf ("%s\n%s", dst->text, src->text);
- free (dst->text);
- dst->text = new_text;
+ char *new_text = xasprintf ("%s\n%s", dst->text->text.local,
+ src->text->text.local);
+
+ free (dst->text->text.local);
+ if (dst->text->text.c != dst->text->text.local)
+ free (dst->text->text.c);
+ if (dst->text->text.id != dst->text->text.local
+ && dst->text->text.id != dst->text->text.c)
+ free (dst->text->text.id);
+
+ dst->text->text.local = new_text;
+ dst->text->text.c = new_text;
+ dst->text->text.id = new_text;
+
return true;
}
}
d->hide_all_labels = true;
pivot_category_create_leaf (d->root, pivot_value_new_text ("null"));
- struct pivot_value *content = pivot_value_new_user_text (
- text_item->text, SIZE_MAX);
- pivot_value_set_font_style (content, &text_item->style);
- pivot_table_put1 (table, 0, content);
+ pivot_table_put1 (table, 0, pivot_value_clone (text_item->text));
text_item_unref (text_item);
text_item_destroy (struct output_item *output_item)
{
struct text_item *item = to_text_item (output_item);
- free (item->text);
- font_style_uninit (&item->style);
+ pivot_value_destroy (item->text);
free (item);
}
struct text_item
{
struct output_item output_item;
- char *text; /* The content. */
- enum text_item_type type; /* Type. */
- struct font_style style;
+ enum text_item_type type;
+ struct pivot_value *text;
};
struct text_item *text_item_create (enum text_item_type,
const char *text, const char *label);
struct text_item *text_item_create_nocopy (enum text_item_type,
char *text, char *label);
+struct text_item *text_item_create_value (enum text_item_type,
+ struct pivot_value *value,
+ char *label);
enum text_item_type text_item_get_type (const struct text_item *);
-const char *text_item_get_text (const struct text_item *);
+char *text_item_get_plain_text (const struct text_item *);
struct text_item *text_item_unshare (struct text_item *);
bool text_item_append (struct text_item *dst, const struct text_item *src);
else if (is_text_item (item))
{
const struct text_item *text_item = to_text_item (item);
- const char *text = text_item_get_text (text_item);
- if (text[0] == '\0')
+ char *text = text_item_get_plain_text (text_item);
+ bool text_is_empty = text[0] == '\0';
+ free (text);
+ if (text_is_empty)
return;
}