clip[H][0] = clip[H][1] = clip[V][0] = clip[V][1] = 0;
ascii_layout_cell (a, cell, bb, clip, max_width, &h);
- if (cell->n_contents != 1
- || cell->contents[0].n_footnotes
- || strchr (cell->contents[0].text, ' '))
+ if (cell->n_footnotes || strchr (cell->text, ' '))
{
bb[H][1] = 1;
ascii_layout_cell (a, cell, bb, clip, min_width, &h);
}
static char *
-add_footnote_markers (const char *text, const struct cell_contents *contents)
+add_footnote_markers (const char *text, const struct table_cell *cell)
{
struct string s = DS_EMPTY_INITIALIZER;
ds_put_cstr (&s, text);
- for (size_t i = 0; i < contents->n_footnotes; i++)
- ds_put_format (&s, "[%s]", contents->footnotes[i]->marker);
+ for (size_t i = 0; i < cell->n_footnotes; i++)
+ ds_put_format (&s, "[%s]", cell->footnotes[i]->marker);
return ds_steal_cstr (&s);
}
-static int
-ascii_layout_cell_text (struct ascii_driver *a,
- const struct cell_contents *contents,
- bool bold, bool underline,
- int bb[TABLE_N_AXES][2], int clip[TABLE_N_AXES][2],
- int *widthp)
+static void
+ascii_layout_cell (struct ascii_driver *a, const struct table_cell *cell,
+ int bb[TABLE_N_AXES][2], int clip[TABLE_N_AXES][2],
+ int *widthp, int *heightp)
{
- char *breaks;
- int bb_width;
- size_t pos;
-
- int y = bb[V][0];
+ *widthp = 0;
+ *heightp = 0;
/* Get the basic textual contents. */
- const char *plain_text = (contents->options & TAB_MARKUP
- ? output_get_text_from_markup (contents->text)
- : contents->text);
+ const char *plain_text = (cell->options & TAB_MARKUP
+ ? output_get_text_from_markup (cell->text)
+ : cell->text);
/* Append footnote markers if any. */
const char *text;
- if (contents->n_footnotes)
+ if (cell->n_footnotes)
{
- text = add_footnote_markers (plain_text, contents);
- if (plain_text != contents->text)
+ text = add_footnote_markers (plain_text, cell);
+ if (plain_text != cell->text)
free (CONST_CAST (char *, plain_text));
}
else
size_t length = strlen (text);
if (!length)
{
- if (text != contents->text)
+ if (text != cell->text)
free (CONST_CAST (char *, text));
- return y;
+ return;
}
- breaks = xmalloc (length + 1);
+ char *breaks = xmalloc (length + 1);
u8_possible_linebreaks (CHAR_CAST (const uint8_t *, text), length,
"UTF-8", breaks);
breaks[length] = (breaks[length - 1] == UC_BREAK_MANDATORY
? UC_BREAK_PROHIBITED : UC_BREAK_POSSIBLE);
- pos = 0;
- bb_width = bb[H][1] - bb[H][0];
- for (y = bb[V][0]; y < bb[V][1] && pos < length; y++)
+ size_t pos = 0;
+ int bb_width = bb[H][1] - bb[H][0];
+ for (int y = bb[V][0]; y < bb[V][1] && pos < length; y++)
{
const uint8_t *line = CHAR_CAST (const uint8_t *, text + pos);
const char *b = breaks + pos;
width -= ofs - graph_ofs;
/* Draw text. */
- text_draw (a, contents->options, bold, underline,
+ text_draw (a, cell->options, cell->style->bold, cell->style->underline,
bb, clip, y, line, graph_ofs, width);
/* If a new-line ended the line, just skip the new-line. Otherwise, skip
if (width > *widthp)
*widthp = width;
+ ++*heightp;
pos += ofs;
}
free (breaks);
- if (text != contents->text)
+ if (text != cell->text)
free (CONST_CAST (char *, text));
-
- return y;
-}
-
-static void
-ascii_layout_cell (struct ascii_driver *a, const struct table_cell *cell,
- int bb_[TABLE_N_AXES][2], int clip[TABLE_N_AXES][2],
- int *widthp, int *heightp)
-{
- int bb[TABLE_N_AXES][2];
- size_t i;
-
- *widthp = 0;
- *heightp = 0;
-
- memcpy (bb, bb_, sizeof bb);
- for (i = 0; i < cell->n_contents && bb[V][0] < bb[V][1]; i++)
- {
- const struct cell_contents *contents = &cell->contents[i];
-
- /* Put a blank line between contents. */
- if (i > 0)
- {
- bb[V][0]++;
- if (bb[V][0] >= bb[V][1])
- break;
- }
-
- bb[V][0] = ascii_layout_cell_text (a, contents, cell->style->bold,
- cell->style->underline,
- bb, clip, widthp);
- }
- *heightp = bb[V][0] - bb_[V][0];
}
void
if (a->file == NULL && !ascii_open_page (a))
return;
- struct cell_contents contents = {
- .options = TAB_LEFT,
- .text = CONST_CAST (char *, s),
- };
- struct cell_style cell_style = {
+ struct cell_style style = {
.bold = bold,
.underline = underline,
};
struct table_cell cell = {
- .contents = &contents,
- .n_contents = 1,
- .style = &cell_style,
+ .options = TAB_LEFT,
+ .text = CONST_CAST (char *, s),
+ .style = &style,
};
bb[TABLE_HORZ][0] = x;
}
static int
-xr_layout_cell_text (struct xr_driver *xr,
- const struct cell_contents *contents,
- const struct cell_style *style,
+xr_layout_cell_text (struct xr_driver *xr, const struct table_cell *cell,
int bb[TABLE_N_AXES][2], int clip[TABLE_N_AXES][2],
int *widthp, int *brk)
{
- unsigned int options = contents->options;
+ const struct cell_style *style = cell->style;
+ unsigned int options = cell->options;
int w, h;
struct xr_font *font = (options & TAB_FIX ? &xr->fonts[XR_FONT_FIXED]
: options & TAB_EMPH ? &xr->fonts[XR_FONT_EMPHASIS]
: &xr->fonts[XR_FONT_PROPORTIONAL]);
struct xr_font local_font;
- if (style->font)
+ if (cell->style->font)
{
PangoFontDescription *desc = parse_font (
style->font,
}
int footnote_adjustment;
- if (contents->n_footnotes == 0)
+ if (cell->n_footnotes == 0)
footnote_adjustment = 0;
- else if (contents->n_footnotes == 1 && (options & TAB_HALIGN) == TAB_RIGHT)
+ else if (cell->n_footnotes == 1 && (options & TAB_HALIGN) == TAB_RIGHT)
{
PangoAttrList *attrs;
- const char *marker = contents->footnotes[0]->marker;
+ const char *marker = cell->footnotes[0]->marker;
pango_layout_set_text (font->layout, marker, strlen (marker));
attrs = pango_attr_list_new ();
footnote_adjustment = px_to_xr (style->margin[H][1]);
struct string tmp = DS_EMPTY_INITIALIZER;
- const char *text = contents->text;
+ const char *text = cell->text;
/* Deal with an oddity of the Unicode line-breaking algorithm (or perhaps in
Pango's implementation of it): it will break after a period or a comma
}
size_t initial_length = ds_length (&tmp);
- for (size_t i = 0; i < contents->n_footnotes; i++)
+ for (size_t i = 0; i < cell->n_footnotes; i++)
{
if (i)
ds_put_byte (&tmp, ',');
- const char *marker = contents->footnotes[i]->marker;
+ const char *marker = cell->footnotes[i]->marker;
if (options & TAB_MARKUP)
markup_escape (marker, &tmp);
else
pango_font_description_free (font->desc);
}
- return bb[V][0] + h;
+ return h;
}
static void
xr_layout_cell (struct xr_driver *xr, const struct table_cell *cell,
- int bb_[TABLE_N_AXES][2], int clip[TABLE_N_AXES][2],
+ int bb[TABLE_N_AXES][2], int clip[TABLE_N_AXES][2],
int *width, int *height, int *brk)
{
- int bb[TABLE_N_AXES][2];
- size_t i;
-
*width = 0;
*height = 0;
- if (brk)
- *brk = 0;
-
- memcpy (bb, bb_, sizeof bb);
/* If enabled, draws a blue rectangle around the cell extents, which can be
useful for debugging layout. */
}
}
- for (i = 0; i < cell->n_contents && bb[V][0] < bb[V][1]; i++)
- {
- const struct cell_contents *contents = &cell->contents[i];
-
- if (brk)
- *brk = bb[V][0];
- if (i > 0)
- {
- bb[V][0] += xr->char_height / 2;
- if (bb[V][0] >= bb[V][1])
- break;
- if (brk)
- *brk = bb[V][0];
- }
-
- bb[V][0] = xr_layout_cell_text (xr, contents, cell->style, bb, clip,
- width, brk);
- }
- *height = bb[V][0] - bb_[V][0];
+ if (brk)
+ *brk = bb[V][0];
+ *height = xr_layout_cell_text (xr, cell, bb, clip, width, brk);
}
\f
struct output_driver_factory pdf_driver_factory =
if (x != cell.d[TABLE_HORZ][0] || y != cell.d[TABLE_VERT][0])
csv_output_field (csv, "");
- else if (cell.n_contents == 1
- && cell.contents[0].text != NULL
- && cell.contents[0].n_footnotes == 0)
- csv_output_field (csv, cell.contents[0].text);
+ else if (!(cell.options & TAB_MARKUP) && !cell.n_footnotes)
+ csv_output_field (csv, cell.text);
else
{
- struct string s;
- size_t i;
+ struct string s = DS_EMPTY_INITIALIZER;
- ds_init_empty (&s);
- for (i = 0; i < cell.n_contents; i++)
+ if (cell.options & TAB_MARKUP)
{
- const struct cell_contents *c = &cell.contents[i];
-
- if (i > 0)
- ds_put_cstr (&s, "\n\n");
-
- if (c->options & TAB_MARKUP)
- {
- char *t = output_get_text_from_markup (c->text);
- ds_put_cstr (&s, t);
- free (t);
- }
- else
- ds_put_cstr (&s, c->text);
- csv_format_footnotes (c->footnotes, c->n_footnotes, &s);
+ char *t = output_get_text_from_markup (cell.text);
+ ds_put_cstr (&s, t);
+ free (t);
}
+ else
+ ds_put_cstr (&s, cell.text);
+
+ csv_format_footnotes (cell.footnotes, cell.n_footnotes, &s);
csv_output_field (csv, ds_cstr (&s));
ds_destroy (&s);
}
fputs (" <TR>\n", html->file);
for (x = 0; x < table_nc (t); )
{
- const struct cell_contents *c;
struct table_cell cell;
const char *tag;
bool is_header;
tag = is_header ? "TH" : "TD";
fprintf (html->file, " <%s", tag);
- int halign = (cell.n_contents > 0
- ? cell.contents[0].options & TAB_HALIGN
- : TAB_LEFT);
+ int halign = cell.options & TAB_HALIGN;
if (halign != TAB_LEFT)
fprintf (html->file, " ALIGN=\"%s\"",
halign == TAB_RIGHT ? "RIGHT" : "CENTER");
- int valign = (cell.n_contents > 0
- ? cell.contents[0].options & TAB_VALIGN
- : TAB_LEFT);
+ int valign = cell.options & TAB_VALIGN;
if (valign != TAB_TOP)
fprintf (html->file, " ALIGN=\"%s\"",
valign == TAB_BOTTOM ? "BOTTOM" : "MIDDLE");
putc ('>', html->file);
/* Output cell contents. */
- for (c = cell.contents; c < &cell.contents[cell.n_contents]; c++)
+ const char *s = cell.text;
+ if (cell.options & TAB_EMPH)
+ fputs ("<EM>", html->file);
+ if (cell.options & TAB_FIX)
{
- const char *s = c->text;
-
- if (c->options & TAB_EMPH)
- fputs ("<EM>", html->file);
- if (c->options & TAB_FIX)
- {
- fputs ("<TT>", html->file);
- escape_string (html->file, s, strlen (s), " ", "<BR>");
- fputs ("</TT>", html->file);
- }
- else
- {
- s += strspn (s, CC_SPACES);
- escape_string (html->file, s, strlen (s), " ", "<BR>");
- }
- if (c->options & TAB_EMPH)
- fputs ("</EM>", html->file);
-
- html_put_footnote_markers (html, c->footnotes, c->n_footnotes);
+ fputs ("<TT>", html->file);
+ escape_string (html->file, s, strlen (s), " ", "<BR>");
+ fputs ("</TT>", html->file);
}
+ else
+ {
+ s += strspn (s, CC_SPACES);
+ escape_string (html->file, s, strlen (s), " ", "<BR>");
+ }
+ if (cell.options & TAB_EMPH)
+ fputs ("</EM>", html->file);
+
+ html_put_footnote_markers (html, cell.footnotes, cell.n_footnotes);
/* Output </TH> or </TD>. */
fprintf (html->file, "</%s>\n", tag);
for (c = 0 ; c < table_nc (tab) ; ++c)
{
struct table_cell cell;
- size_t i;
table_get_cell (tab, c, r, &cell);
odt->content_wtr, _xml("table:number-rows-spanned"),
"%d", rowspan);
- for (i = 0; i < cell.n_contents; i++)
+ xmlTextWriterStartElement (odt->content_wtr, _xml("text:p"));
+
+ if ( r < table_ht (tab) || c < table_hl (tab) )
+ xmlTextWriterWriteAttribute (odt->content_wtr, _xml("text:style-name"), _xml("Table_20_Heading"));
+ else
+ xmlTextWriterWriteAttribute (odt->content_wtr, _xml("text:style-name"), _xml("Table_20_Contents"));
+
+ if (cell.options & TAB_MARKUP)
{
- const struct cell_contents *contents = &cell.contents[i];
- int j;
-
- xmlTextWriterStartElement (odt->content_wtr, _xml("text:p"));
-
- if ( r < table_ht (tab) || c < table_hl (tab) )
- xmlTextWriterWriteAttribute (odt->content_wtr, _xml("text:style-name"), _xml("Table_20_Heading"));
- else
- xmlTextWriterWriteAttribute (odt->content_wtr, _xml("text:style-name"), _xml("Table_20_Contents"));
-
- if (contents->options & TAB_MARKUP)
- {
- /* XXX */
- char *s = output_get_text_from_markup (
- contents->text);
- write_xml_with_line_breaks (odt, s);
- free (s);
- }
- else
- write_xml_with_line_breaks (odt, contents->text);
-
- for (j = 0; j < contents->n_footnotes; j++)
- write_footnote (odt, contents->footnotes[j]);
-
- xmlTextWriterEndElement (odt->content_wtr); /* text:p */
+ /* XXX */
+ char *s = output_get_text_from_markup (cell.text);
+ write_xml_with_line_breaks (odt, s);
+ free (s);
}
+ else
+ write_xml_with_line_breaks (odt, cell.text);
+
+ for (int i = 0; i < cell.n_footnotes; i++)
+ write_footnote (odt, cell.footnotes[i]);
+
+ xmlTextWriterEndElement (odt->content_wtr); /* text:p */
xmlTextWriterEndElement (odt->content_wtr); /* table:table-cell */
}
else
bb[V][0] = clip[V][0] = ofs[V] + page->cp[V][cell->d[V][0] * 2 + 1];
bb[V][1] = clip[V][1] = ofs[V] + page->cp[V][cell->d[V][1] * 2];
- int valign = (cell->n_contents
- ? cell->contents->options & TAB_VALIGN
- : TAB_TOP);
+ int valign = cell->options & TAB_VALIGN;
if (valign != TAB_TOP)
{
int height = page->params->measure_cell_height (
unsigned short opt = t->ct[index];
const void *cc = t->cc[index];
- cell->inline_contents.options = opt;
- cell->inline_contents.n_footnotes = 0;
+ cell->options = opt;
+ cell->n_footnotes = 0;
cell->destructor = NULL;
int style_idx = (opt & TAB_STYLE_MASK) >> TAB_STYLE_SHIFT;
if (opt & TAB_JOIN)
{
const struct tab_joined_cell *jc = cc;
- cell->contents = &cell->inline_contents;
- cell->n_contents = 1;
- cell->inline_contents.text = jc->u.text;
+ cell->text = jc->u.text;
- cell->inline_contents.footnotes = jc->footnotes;
- cell->inline_contents.n_footnotes = jc->n_footnotes;
+ cell->footnotes = jc->footnotes;
+ cell->n_footnotes = jc->n_footnotes;
cell->d[TABLE_HORZ][0] = jc->d[TABLE_HORZ][0];
cell->d[TABLE_HORZ][1] = jc->d[TABLE_HORZ][1];
cell->d[TABLE_HORZ][1] = x + 1;
cell->d[TABLE_VERT][0] = y;
cell->d[TABLE_VERT][1] = y + 1;
- if (cc != NULL)
- {
- cell->contents = &cell->inline_contents;
- cell->n_contents = 1;
- cell->inline_contents.text = CONST_CAST (char *, cc);
- }
- else
- {
- cell->contents = NULL;
- cell->n_contents = 0;
- }
+ cell->text = CONST_CAST (char *, cc ? cc : "");
}
}
cell->d[TABLE_HORZ][1] = x + 1;
cell->d[TABLE_VERT][0] = y;
cell->d[TABLE_VERT][1] = y + 1;
- cell->contents = &cell->inline_contents;
- cell->n_contents = 1;
- cell->inline_contents.options = TAB_RIGHT;
- cell->inline_contents.n_footnotes = 0;
+ cell->options = TAB_RIGHT;
+ cell->n_footnotes = 0;
if (tc->heading != NULL)
{
if (y == 0)
{
s = xstrdup (tc->heading);
- cell->inline_contents.text = s;
+ cell->text = s;
cell->destructor = free_string;
cell->destructor_aux = s;
return;
s = data_out (case_data_idx (c, 0), UTF8, &tc->format);
case_unref (c);
}
- cell->inline_contents.text = s;
+ cell->text = s;
cell->destructor = free_string;
cell->destructor_aux = s;
}
struct cell_style *style;
};
-/* An item of contents within a table cell. */
-struct cell_contents
- {
- unsigned int options; /* TAB_*. */
- char *text; /* A paragraph of text. */
-
- /* Optional footnote(s). */
- const struct footnote **footnotes;
- size_t n_footnotes;
- };
-
-void cell_contents_format_footnote_markers (const struct cell_contents *,
- struct string *);
-
struct cell_color
{
uint8_t r, g, b;
or both. */
int d[TABLE_N_AXES][2];
- /* The cell's contents.
-
- Most table cells contain only one item (a paragraph of text), but cells
- are allowed to be empty (n_contents == 0) or contain a nested table, or
- multiple items.
+ unsigned int options; /* TAB_*. */
+ char *text; /* A paragraph of text. */
- 'inline_contents' provides a place to store a single item to handle the
- common case.
- */
- const struct cell_contents *contents;
- size_t n_contents;
- struct cell_contents inline_contents;
+ /* Optional footnote(s). */
+ const struct footnote **footnotes;
+ size_t n_footnotes;
const struct cell_style *style;
void table_cell_free (struct table_cell *);
+void table_cell_format_footnote_markers (const struct table_cell *,
+ struct string *);
+
/* Returns the number of columns that CELL spans. This is 1 for an ordinary
cell and greater than one for a cell that joins multiple columns. */
static inline int
}
void
-cell_contents_format_footnote_markers (const struct cell_contents *c,
- struct string *s)
+table_cell_format_footnote_markers (const struct table_cell *cell,
+ struct string *s)
{
- for (size_t i = 0; i < c->n_footnotes; i++)
+ for (size_t i = 0; i < cell->n_footnotes; i++)
{
if (i)
ds_put_byte (s, ',');
- ds_put_cstr (s, c->footnotes[i]->marker);
+ ds_put_cstr (s, cell->footnotes[i]->marker);
}
}
table_get_cell (t, x, y, &cell);
if (x == cell.d[TABLE_HORZ][0] && y == cell.d[TABLE_VERT][0])
- for (size_t i = 0; i < cell.n_contents; i++)
- {
- const struct cell_contents *c = &cell.contents[i];
- footnotes = add_footnotes (c->footnotes, c->n_footnotes,
- footnotes, &allocated, &n);
- }
+ footnotes = add_footnotes (cell.footnotes, cell.n_footnotes,
+ footnotes, &allocated, &n);
table_cell_free (&cell);
}
}
cell->d[TABLE_HORZ][1] = 1;
cell->d[TABLE_VERT][0] = 0;
cell->d[TABLE_VERT][1] = 1;
- cell->contents = &cell->inline_contents;
- cell->inline_contents.options = ts->options;
- cell->inline_contents.text = ts->string;
- cell->inline_contents.n_footnotes = 0;
- cell->n_contents = 1;
+ cell->options = ts->options;
+ cell->text = ts->string;
+ cell->n_footnotes = 0;
cell->destructor = NULL;
}