output: Support decimal and mixed alignment,
authorBen Pfaff <blp@cs.stanford.edu>
Wed, 26 Dec 2018 22:07:16 +0000 (14:07 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Tue, 1 Jan 2019 06:19:40 +0000 (22:19 -0800)
14 files changed:
src/output/ascii.c
src/output/cairo.c
src/output/html.c
src/output/render.c
src/output/tab.c
src/output/tab.h
src/output/table-casereader.c
src/output/table-item.c
src/output/table-item.h
src/output/table-provider.h
src/output/table.c
src/output/table.h
src/output/text-item.c
src/output/text-item.h

index 330c113042f637f25291494f719691a0fc9c6de8..c0218e6626232fbfced7122e8d65d2af0e163528 100644 (file)
@@ -436,7 +436,7 @@ ascii_output_text (struct ascii_driver *a, const char *text)
 {
   struct table_item *table_item;
 
-  table_item = table_item_create (table_from_string (TAB_LEFT, text),
+  table_item = table_item_create (table_from_string (TABLE_HALIGN_LEFT, text),
                                   NULL, NULL);
   ascii_output_table_item (a, table_item);
   table_item_unref (table_item);
@@ -631,7 +631,7 @@ ascii_reserve (struct ascii_driver *a, int y, int x0, int x1, int n)
 }
 
 static void
-text_draw (struct ascii_driver *a, unsigned int options,
+text_draw (struct ascii_driver *a, enum table_halign halign, int options,
            bool bold, bool underline,
            int bb[TABLE_N_AXES][2], int clip[TABLE_N_AXES][2],
            int y, const uint8_t *string, int n, size_t width)
@@ -645,15 +645,16 @@ text_draw (struct ascii_driver *a, unsigned int options,
   if (y < y0 || y >= y1)
     return;
 
-  switch (options & TAB_HALIGN)
+  switch (table_halign_interpret (halign, options & TAB_NUMERIC))
     {
-    case TAB_LEFT:
+    case TABLE_HALIGN_LEFT:
       x = bb[H][0];
       break;
-    case TAB_CENTER:
+    case TABLE_HALIGN_CENTER:
       x = (bb[H][0] + bb[H][1] - width + 1) / 2;
       break;
-    case TAB_RIGHT:
+    case TABLE_HALIGN_RIGHT:
+    case TABLE_HALIGN_DECIMAL:
       x = bb[H][1] - width;
       break;
     default:
@@ -872,7 +873,9 @@ ascii_layout_cell (struct ascii_driver *a, const struct table_cell *cell,
       width -= ofs - graph_ofs;
 
       /* Draw text. */
-      text_draw (a, cell->options, cell->style->bold, cell->style->underline,
+      text_draw (a, cell->style->cell_style.halign, cell->options,
+                 cell->style->font_style.bold,
+                 cell->style->font_style.underline,
                  bb, clip, y, line, graph_ofs, width);
 
       /* If a new-line ended the line, just skip the new-line.  Otherwise, skip
@@ -905,9 +908,9 @@ ascii_test_write (struct output_driver *driver,
   if (a->file == NULL && !ascii_open_page (a))
     return;
 
-  struct cell_style style = {
-    .bold = bold,
-    .underline = underline,
+  struct area_style style = {
+    .font_style.bold = bold,
+    .font_style.underline = underline,
   };
   struct table_cell cell = {
     .options = TAB_LEFT,
index 4584181d32a3a779365e7993682010c2231fe544..1dc8fe09668b1969ecf2a4b85f7b8dc1c20d7192 100644 (file)
@@ -408,6 +408,14 @@ xr_measure_fonts (cairo_t *cairo, const struct xr_font fonts[XR_N_FONTS],
     }
 }
 
+static int
+get_layout_height (PangoLayout *layout)
+{
+  int w, h;
+  pango_layout_get_size (layout, &w, &h);
+  return h;
+}
+
 static int
 xr_render_page_heading (cairo_t *cairo, const PangoFontDescription *font,
                         const struct page_heading *ph, int page_number,
@@ -426,10 +434,12 @@ xr_render_page_heading (cairo_t *cairo, const PangoFontDescription *font,
       pango_layout_set_markup (layout, markup, -1);
       free (markup);
 
-      pango_layout_set_alignment (layout,
-                                  (pp->halign == TAB_RIGHT ? PANGO_ALIGN_RIGHT
-                                   : pp->halign == TAB_LEFT ? PANGO_ALIGN_LEFT
-                                   : PANGO_ALIGN_CENTER));
+      pango_layout_set_alignment (
+        layout,
+        (pp->halign == TABLE_HALIGN_LEFT ? PANGO_ALIGN_LEFT
+         : pp->halign == TABLE_HALIGN_CENTER ? PANGO_ALIGN_CENTER
+         : pp->halign == TABLE_HALIGN_MIXED ? PANGO_ALIGN_LEFT
+         : PANGO_ALIGN_RIGHT));
       pango_layout_set_width (layout, xr_to_pango (width));
       if (draw)
         {
@@ -439,9 +449,7 @@ xr_render_page_heading (cairo_t *cairo, const PangoFontDescription *font,
           cairo_restore (cairo);
         }
 
-      int w, h;
-      pango_layout_get_size (layout, &w, &h);
-      y += pango_to_xr (h);
+      y += pango_to_xr (get_layout_height (layout));
     }
 
   g_object_unref (G_OBJECT (layout));
@@ -1056,11 +1064,11 @@ xr_measure_cell_width (void *xr_, const struct table_cell *cell,
   xr_layout_cell (xr, cell, bb, clip, min_width, &h, NULL);
 
   if (*min_width > 0)
-    *min_width += px_to_xr (cell->style->margin[H][0]
-                            + cell->style->margin[H][1]);
+    *min_width += px_to_xr (cell->style->cell_style.margin[H][0]
+                            + cell->style->cell_style.margin[H][1]);
   if (*max_width > 0)
-    *max_width += px_to_xr (cell->style->margin[H][0]
-                            + cell->style->margin[H][1]);
+    *max_width += px_to_xr (cell->style->cell_style.margin[H][0]
+                            + cell->style->cell_style.margin[H][1]);
 }
 
 static int
@@ -1072,13 +1080,14 @@ xr_measure_cell_height (void *xr_, const struct table_cell *cell, int width)
   int w, h;
 
   bb[H][0] = 0;
-  bb[H][1] = width - px_to_xr (cell->style->margin[H][0]
-                               + cell->style->margin[H][1]);
+  bb[H][1] = width - px_to_xr (cell->style->cell_style.margin[H][0]
+                               + cell->style->cell_style.margin[H][1]);
   bb[V][0] = 0;
   bb[V][1] = INT_MAX;
   clip[H][0] = clip[H][1] = clip[V][0] = clip[V][1] = 0;
   xr_layout_cell (xr, cell, bb, clip, &w, &h, NULL);
-  h += px_to_xr (cell->style->margin[V][0] + cell->style->margin[V][1]);
+  h += px_to_xr (cell->style->cell_style.margin[V][0]
+                 + cell->style->cell_style.margin[V][1]);
   return h;
 }
 
@@ -1107,9 +1116,9 @@ xr_draw_cell (void *xr_, const struct table_cell *cell, int color_idx,
     }
   xr_clip (xr, bg_clip);
   cairo_set_source_rgb (xr->cairo,
-                        cell->style->bg[color_idx].r / 255.,
-                        cell->style->bg[color_idx].g / 255.,
-                        cell->style->bg[color_idx].b / 255.);
+                        cell->style->font_style.bg[color_idx].r / 255.,
+                        cell->style->font_style.bg[color_idx].g / 255.,
+                        cell->style->font_style.bg[color_idx].b / 255.);
   fill_rectangle (xr,
                   bb[H][0] - spill[H][0],
                   bb[V][0] - spill[V][0],
@@ -1119,14 +1128,14 @@ xr_draw_cell (void *xr_, const struct table_cell *cell, int color_idx,
 
   cairo_save (xr->cairo);
   cairo_set_source_rgb (xr->cairo,
-                        cell->style->fg[color_idx].r / 255.,
-                        cell->style->fg[color_idx].g / 255.,
-                        cell->style->fg[color_idx].b / 255.);
+                        cell->style->font_style.fg[color_idx].r / 255.,
+                        cell->style->font_style.fg[color_idx].g / 255.,
+                        cell->style->font_style.fg[color_idx].b / 255.);
 
   for (int axis = 0; axis < TABLE_N_AXES; axis++)
     {
-      bb[axis][0] += px_to_xr (cell->style->margin[axis][0]);
-      bb[axis][1] -= px_to_xr (cell->style->margin[axis][1]);
+      bb[axis][0] += px_to_xr (cell->style->cell_style.margin[axis][0]);
+      bb[axis][1] -= px_to_xr (cell->style->cell_style.margin[axis][1]);
     }
   if (bb[H][0] < bb[H][1] && bb[V][0] < bb[V][1])
     xr_layout_cell (xr, cell, bb, clip, &w, &h, &brk);
@@ -1146,13 +1155,13 @@ xr_adjust_break (void *xr_, const struct table_cell *cell,
     return -1;
 
   bb[H][0] = 0;
-  bb[H][1] = width - px_to_xr (cell->style->margin[H][0]
-                               + cell->style->margin[H][1]);
+  bb[H][1] = width - px_to_xr (cell->style->cell_style.margin[H][0]
+                               + cell->style->cell_style.margin[H][1]);
   if (bb[H][1] <= 0)
     return 0;
   bb[V][0] = 0;
-  bb[V][1] = height - px_to_xr (cell->style->margin[V][0]
-                                + cell->style->margin[V][1]);
+  bb[V][1] = height - px_to_xr (cell->style->cell_style.margin[V][0]
+                                + cell->style->cell_style.margin[V][1]);
   clip[H][0] = clip[H][1] = clip[V][0] = clip[V][1] = 0;
   xr_layout_cell (xr, cell, bb, clip, &w, &h, &brk);
   return brk;
@@ -1214,7 +1223,8 @@ 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)
 {
-  const struct cell_style *style = cell->style;
+  const struct font_style *font_style = &cell->style->font_style;
+  const struct cell_style *cell_style = &cell->style->cell_style;
   unsigned int options = cell->options;
 
   enum table_axis X = options & TAB_ROTATE ? V : H;
@@ -1225,12 +1235,12 @@ xr_layout_cell_text (struct xr_driver *xr, const struct table_cell *cell,
                           : options & TAB_EMPH ? &xr->fonts[XR_FONT_EMPHASIS]
                           : &xr->fonts[XR_FONT_PROPORTIONAL]);
   struct xr_font local_font;
-  if (cell->style->typeface)
+  if (font_style->typeface)
     {
       PangoFontDescription *desc = parse_font (
-        style->typeface,
-        style->size ? style->size * 1000 * 72 / 128 : 10000,
-        style->bold, style->italic);
+        font_style->typeface,
+        font_style->size ? font_style->size * 1000 * 72 / 128 : 10000,
+        font_style->bold, font_style->italic);
       if (desc)
         {
           PangoLayout *layout = pango_cairo_create_layout (xr->cairo);
@@ -1242,30 +1252,26 @@ xr_layout_cell_text (struct xr_driver *xr, const struct table_cell *cell,
         }
     }
 
-  int footnote_adjustment;
-  if (cell->n_footnotes == 0)
-    footnote_adjustment = 0;
-  else if (cell->n_footnotes == 1 && (options & TAB_HALIGN) == TAB_RIGHT)
+  const char *text = cell->text;
+  enum table_halign halign = table_halign_interpret (
+    cell_style->halign, cell->options & TAB_NUMERIC);
+  if (cell_style->halign == TABLE_HALIGN_DECIMAL && !(options & TAB_ROTATE))
     {
-      const char *marker = cell->footnotes[0]->marker;
-      pango_layout_set_text (font->layout, marker, strlen (marker));
+      int margin_adjustment = -px_to_xr (cell_style->decimal_offset);
 
-      PangoAttrList *attrs = pango_attr_list_new ();
-      pango_attr_list_insert (attrs, pango_attr_rise_new (7000));
-      pango_layout_set_attributes (font->layout, attrs);
-      pango_attr_list_unref (attrs);
-
-      int w = get_layout_dimension (font->layout, X);
-      int right_margin = px_to_xr (cell->style->margin[X][R]);
-      footnote_adjustment = MIN (w, right_margin);
+      const char *decimal = strrchr (text, cell_style->decimal_char);
+      if (decimal)
+        {
+          pango_layout_set_text (font->layout, decimal, strlen (decimal));
+          pango_layout_set_width (font->layout, -1);
+          margin_adjustment += get_layout_dimension (font->layout, H);
+        }
 
-      pango_layout_set_attributes (font->layout, NULL);
+      if (margin_adjustment < 0)
+        bb[H][1] += margin_adjustment;
     }
-  else
-    footnote_adjustment = px_to_xr (cell->style->margin[X][R]);
 
   struct string tmp = DS_EMPTY_INITIALIZER;
-  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
@@ -1295,8 +1301,28 @@ xr_layout_cell_text (struct xr_driver *xr, const struct table_cell *cell,
         }
     }
 
-  if (footnote_adjustment)
+  if (cell->n_footnotes)
     {
+      int footnote_adjustment;
+      if (cell->n_footnotes == 1 && halign == TABLE_HALIGN_RIGHT)
+        {
+          const char *marker = cell->footnotes[0]->marker;
+          pango_layout_set_text (font->layout, marker, strlen (marker));
+
+          PangoAttrList *attrs = pango_attr_list_new ();
+          pango_attr_list_insert (attrs, pango_attr_rise_new (7000));
+          pango_layout_set_attributes (font->layout, attrs);
+          pango_attr_list_unref (attrs);
+
+          int w = get_layout_dimension (font->layout, X);
+          int right_margin = px_to_xr (cell_style->margin[X][R]);
+          footnote_adjustment = MIN (w, right_margin);
+
+          pango_layout_set_attributes (font->layout, NULL);
+        }
+      else
+        footnote_adjustment = px_to_xr (cell_style->margin[X][R]);
+
       if (R)
         bb[X][R] += footnote_adjustment;
       else
@@ -1328,7 +1354,7 @@ xr_layout_cell_text (struct xr_driver *xr, const struct table_cell *cell,
         pango_layout_set_text (font->layout, ds_cstr (&tmp), ds_length (&tmp));
 
       PangoAttrList *attrs = pango_attr_list_new ();
-      if (style->underline)
+      if (font_style->underline)
         pango_attr_list_insert (attrs, pango_attr_underline_new (
                                PANGO_UNDERLINE_SINGLE));
       add_attr_with_start (attrs, pango_attr_rise_new (7000), initial_length);
@@ -1345,7 +1371,7 @@ xr_layout_cell_text (struct xr_driver *xr, const struct table_cell *cell,
       else
         pango_layout_set_text (font->layout, content, -1);
 
-      if (style->underline)
+      if (font_style->underline)
         {
           PangoAttrList *attrs = pango_attr_list_new ();
           pango_attr_list_insert (attrs, pango_attr_underline_new (
@@ -1356,11 +1382,10 @@ xr_layout_cell_text (struct xr_driver *xr, const struct table_cell *cell,
     }
   ds_destroy (&tmp);
 
-  pango_layout_set_alignment (
-    font->layout,
-    ((options & TAB_HALIGN) == TAB_RIGHT ? PANGO_ALIGN_RIGHT
-     : (options & TAB_HALIGN) == TAB_LEFT ? PANGO_ALIGN_LEFT
-     : PANGO_ALIGN_CENTER));
+  pango_layout_set_alignment (font->layout,
+                              (halign == TABLE_HALIGN_RIGHT ? PANGO_ALIGN_RIGHT
+                               : halign == TABLE_HALIGN_LEFT ? PANGO_ALIGN_LEFT
+                               : PANGO_ALIGN_CENTER));
   pango_layout_set_width (
     font->layout,
     bb[X][1] == INT_MAX ? -1 : xr_to_pango (bb[X][1] - bb[X][0]));
@@ -1561,7 +1586,7 @@ xr_rendering_create_text (struct xr_driver *xr, const char *text, cairo_t *cr)
   struct table_item *table_item;
   struct xr_rendering *r;
 
-  table_item = table_item_create (table_from_string (TAB_LEFT, text),
+  table_item = table_item_create (table_from_string (TABLE_HALIGN_LEFT, text),
                                   NULL, NULL);
   r = xr_rendering_create (xr, &table_item->output_item, cr);
   table_item_unref (table_item);
index 959519e46e1b4e2a961dfbe9236b98a618b0c4fa..05fc08eb62f55dbfe407140a634d82fd4c8748f7 100644 (file)
@@ -501,15 +501,23 @@ html_output_table (struct html_driver *html, const struct table_item *item)
           tag = is_header ? "TH" : "TD";
           fprintf (html->file, "    <%s", tag);
 
-          int halign = cell.options & TAB_HALIGN;
-          if (halign != TAB_LEFT)
-            fprintf (html->file, " ALIGN=\"%s\"",
-                     halign == TAB_RIGHT ? "RIGHT" : "CENTER");
+          enum table_halign halign = table_halign_interpret (
+            cell.style->cell_style.halign, cell.options & TAB_NUMERIC);
+          if (halign != TABLE_HALIGN_LEFT)
+            {
+              fprintf (html->file, " ALIGN=\"%s\"",
+                       (halign == TABLE_HALIGN_RIGHT ? "RIGHT"
+                        : halign == TABLE_HALIGN_CENTER ? "CENTER"
+                        : "CHAR"));
+              if (cell.style->cell_style.decimal_char)
+                fprintf (html->file, " CHAR=\"%c\"",
+                         cell.style->cell_style.decimal_char);
+            }
 
-          int valign = cell.options & TAB_VALIGN;
-          if (valign != TAB_TOP)
+          if (cell.style->cell_style.valign != TABLE_VALIGN_TOP)
             fprintf (html->file, " ALIGN=\"%s\"",
-                     valign == TAB_BOTTOM ? "BOTTOM" : "MIDDLE");
+                     (cell.style->cell_style.valign == TABLE_VALIGN_BOTTOM
+                      ? "BOTTOM" : "MIDDLE"));
 
           colspan = table_cell_colspan (&cell);
           if (colspan > 1)
index 61b03f0285cc4f86605596b65b0ffae7984eb24c..4e9a15509585da846724945bb68414d6cf73b6c4 100644 (file)
@@ -507,7 +507,7 @@ measure_rule (const struct render_params *params, const struct table *table,
 
   /* Calculate maximum width of the rules that are present. */
   int width = 0;
-  for (size_t i = 0; i < N_LINES; i++)
+  for (size_t i = 0; i < TABLE_N_STROKES; i++)
     if (rules & (1u << i))
       width = MAX (width, params->line_widths[a][rule_to_render_type (i)]);
   return width;
@@ -983,15 +983,15 @@ render_cell (const struct render_page *page, const int ofs[TABLE_N_AXES],
   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->options & TAB_VALIGN;
-  if (valign != TAB_TOP)
+  enum table_valign valign = cell->style->cell_style.valign;
+  if (valign != TABLE_VALIGN_TOP)
     {
       int height = page->params->measure_cell_height (
         page->params->aux, cell, bb[H][1] - bb[H][0]);
       int extra = bb[V][1] - bb[V][0] - height;
       if (extra > 0)
         {
-          if (valign == TAB_MIDDLE)
+          if (valign == TABLE_VALIGN_CENTER)
             extra /= 2;
           bb[V][0] += extra;
         }
@@ -1453,11 +1453,11 @@ add_text_page (struct render_pager *p, const struct table_item_text *t,
     return;
 
   struct tab_table *tab = tab_create (1, 1);
-  tab_text (tab, 0, 0, t->halign, t->content);
+  tab_text (tab, 0, 0, 0, t->content);
   for (size_t i = 0; i < t->n_footnotes; i++)
     tab_add_footnote (tab, 0, 0, t->footnotes[i]);
   if (t->style)
-    tab->styles[0] = cell_style_clone (tab->container, t->style);
+    tab->styles[0] = area_style_clone (tab->container, t->style);
   render_pager_add_table (p, &tab->table, min_width);
 }
 
index 8eab07e6f151a1490d30a7c3268212d35faf84b5..ec00c432226cf4f993c8c5d36367f7b5432160cb 100644 (file)
@@ -65,7 +65,7 @@ struct tab_joined_cell
   size_t n_footnotes;
   const struct footnote **footnotes;
 
-  const struct cell_style *style;
+  const struct area_style *style;
 };
 
 static const struct table_class tab_table_class;
@@ -621,7 +621,7 @@ tab_joint_text_format (struct tab_table *table, int x1, int y1, int x2,
 
 struct footnote *
 tab_create_footnote (struct tab_table *table, size_t idx, const char *content,
-                     const char *marker, struct cell_style *style)
+                     const char *marker, struct area_style *style)
 {
   struct footnote *f = pool_alloc (table->container, sizeof *f);
   f->idx = idx;
@@ -657,7 +657,7 @@ tab_add_footnote (struct tab_table *table, int x, int y,
 
 void
 tab_add_style (struct tab_table *table, int x, int y,
-               const struct cell_style *style)
+               const struct area_style *style)
 {
   int index = x + y * table->cf;
   unsigned short opt = table->ct[index];
@@ -819,9 +819,37 @@ tab_get_cell (const struct table *table, int x, int y,
   cell->destructor = NULL;
 
   int style_idx = (opt & TAB_STYLE_MASK) >> TAB_STYLE_SHIFT;
-  const struct cell_style *style = t->styles[style_idx];
+  const struct area_style *style = t->styles[style_idx];
   if (style)
     cell->style = style;
+  else
+    {
+      static const struct area_style styles[3][3] = {
+#define S(H,V) [H][V] = { AREA_STYLE_INITIALIZER__,     \
+                          .cell_style.halign = H,       \
+                          .cell_style.valign = V }
+        S(TABLE_HALIGN_LEFT, TABLE_VALIGN_TOP),
+        S(TABLE_HALIGN_LEFT, TABLE_VALIGN_CENTER),
+        S(TABLE_HALIGN_LEFT, TABLE_VALIGN_BOTTOM),
+        S(TABLE_HALIGN_CENTER, TABLE_VALIGN_TOP),
+        S(TABLE_HALIGN_CENTER, TABLE_VALIGN_CENTER),
+        S(TABLE_HALIGN_CENTER, TABLE_VALIGN_BOTTOM),
+        S(TABLE_HALIGN_RIGHT, TABLE_VALIGN_TOP),
+        S(TABLE_HALIGN_RIGHT, TABLE_VALIGN_CENTER),
+        S(TABLE_HALIGN_RIGHT, TABLE_VALIGN_BOTTOM),
+      };
+
+      enum table_halign halign
+        = ((opt & TAB_HALIGN) == TAB_LEFT ? TABLE_HALIGN_LEFT
+           : (opt & TAB_HALIGN) == TAB_CENTER ? TABLE_HALIGN_CENTER
+           : TABLE_HALIGN_RIGHT);
+      enum table_valign valign
+        = ((opt & TAB_VALIGN) == TAB_TOP ? TABLE_VALIGN_TOP
+           : (opt & TAB_VALIGN) == TAB_CENTER ? TABLE_VALIGN_CENTER
+           : TABLE_VALIGN_BOTTOM);
+
+      cell->style = &styles[halign][valign];
+    }
 
   if (opt & TAB_JOIN)
     {
index 40f871b12df5101cc718a07d16e2de02cbaf627f..abd786119c13c5ab39ef8f97cf5cdd3a2056db33 100644 (file)
@@ -51,8 +51,23 @@ enum result_class
     n_RC
   };
 
-#define TAB_STYLE_MASK (7u << (TAB_FIRST_AVAILABLE + 3))
-#define TAB_STYLE_SHIFT (TAB_FIRST_AVAILABLE + 3)
+#define TAB_STYLE_MASK (7u << (TAB_FIRST_AVAILABLE + 1))
+#define TAB_STYLE_SHIFT (TAB_FIRST_AVAILABLE + 1)
+
+enum
+  {
+    /* Horizontal alignment of cell contents. */
+    TAB_RIGHT      = 0 << (TAB_FIRST_AVAILABLE + 2),
+    TAB_LEFT       = 1 << (TAB_FIRST_AVAILABLE + 2),
+    TAB_CENTER     = 2 << (TAB_FIRST_AVAILABLE + 2),
+    TAB_HALIGN     = 3 << (TAB_FIRST_AVAILABLE + 2), /* Alignment mask. */
+
+    /* Vertical alignment of cell contents. */
+    TAB_TOP        = 0 << (TAB_FIRST_AVAILABLE + 4),
+    TAB_MIDDLE     = 1 << (TAB_FIRST_AVAILABLE + 4),
+    TAB_BOTTOM     = 2 << (TAB_FIRST_AVAILABLE + 4),
+    TAB_VALIGN     = 3 << (TAB_FIRST_AVAILABLE + 4), /* Alignment mask. */
+  };
 
 /* Rule masks. */
 #define TAB_RULE_TYPE_MASK   7
@@ -78,7 +93,7 @@ struct tab_table
        points to a struct tab_joined_cell. */
     void **cc;                  /* Cell contents; void *[nr][nc]. */
     unsigned short *ct;                /* Cell types; unsigned short[nr][nc]. */
-    struct cell_style *styles[8];
+    struct area_style *styles[8];
 
     /* Rules. */
     unsigned char *rh;         /* Horiz rules; unsigned char[nr+1][nc]. */
@@ -156,12 +171,12 @@ void tab_joint_text_format (struct tab_table *, int x1, int y1, int x2, int y2,
 
 struct footnote *tab_create_footnote (struct tab_table *, size_t idx,
                                       const char *content, const char *marker,
-                                      struct cell_style *);
+                                      struct area_style *);
 void tab_add_footnote (struct tab_table *, int x, int y,
                        const struct footnote *);
 
 void tab_add_style (struct tab_table *, int x, int y,
-                    const struct cell_style *);
+                    const struct area_style *);
 
 bool tab_cell_is_empty (const struct tab_table *, int c, int r);
 
index 018fa6328e546bee6c0000b9d5b8397dda1212de..e1b75ac5da28564684e1dca3f9ac0d53c24e2df1 100644 (file)
@@ -106,11 +106,17 @@ table_casereader_get_cell (const struct table *t, int x, int y,
   struct ccase *c;
   char *s;
 
+  static const struct area_style style = {
+    AREA_STYLE_INITIALIZER__,
+    .cell_style.halign = TABLE_HALIGN_RIGHT
+  };
+
   cell->d[TABLE_HORZ][0] = x;
   cell->d[TABLE_HORZ][1] = x + 1;
   cell->d[TABLE_VERT][0] = y;
   cell->d[TABLE_VERT][1] = y + 1;
-  cell->options = TAB_RIGHT;
+  cell->style = &style;
+  cell->options = 0;
   cell->n_footnotes = 0;
   if (tc->heading != NULL)
     {
index 1308cb86503cddd887354bbdac1d13c9c6798555..e24d59b37a15858c736aaeae0b975a2e947d3dd2 100644 (file)
@@ -35,8 +35,7 @@ table_item_text_create (const char *content)
     return NULL;
 
   struct table_item_text *text = xmalloc (sizeof *text);
-  *text = (struct table_item_text) { .content = xstrdup (content),
-                                     .halign = TAB_LEFT };
+  *text = (struct table_item_text) { .content = xstrdup (content) };
   return text;
 }
 
@@ -52,8 +51,7 @@ table_item_text_clone (const struct table_item_text *old)
     .footnotes = xmemdup (old->footnotes,
                           old->n_footnotes * sizeof *old->footnotes),
     .n_footnotes = old->n_footnotes,
-    .style = cell_style_clone (NULL, old->style),
-    .halign = old->halign,
+    .style = area_style_clone (NULL, old->style),
   };
   return new;
 }
@@ -65,7 +63,7 @@ table_item_text_destroy (struct table_item_text *text)
     {
       free (text->content);
       free (text->footnotes);
-      cell_style_free (text->style);
+      area_style_free (text->style);
       free (text);
     }
 }
index ffdc4b682c204ce8dc2be9e729f6fb438cc2640b..b7866a3c9b565f95fe996d62d562c604aab4d14e 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "libpspp/compiler.h"
 #include "output/output-item.h"
+#include "output/table.h"
 
 /* Title or caption in a table item. */
 struct table_item_text
@@ -34,8 +35,7 @@ struct table_item_text
     char *content;
     const struct footnote **footnotes;
     size_t n_footnotes;
-    int halign;                 /* TAB_*. */
-    struct cell_style *style;
+    struct area_style *style;
   };
 
 struct table_item_text *table_item_text_create (const char *);
index ab39b4b25c5fc7d1e848726a98b1e457ca0feda2..ef1f6ea5b916da933f179bf8e3178f856a9129e8 100644 (file)
 struct pool;
 struct string;
 
+enum table_halign table_halign_interpret (enum table_halign, bool numeric);
+
 struct footnote
   {
     size_t idx;
     char *content;
     char *marker;
-    struct cell_style *style;
-  };
-
-struct cell_color
-  {
-    uint8_t r, g, b;
+    struct area_style *style;
   };
 
-#define CELL_COLOR(r, g, b) (struct cell_color) { r, g, b }
-#define CELL_COLOR_BLACK CELL_COLOR (0, 0, 0)
-#define CELL_COLOR_WHITE CELL_COLOR (255, 255, 255)
-
-static inline bool
-cell_color_equal (const struct cell_color *a, const struct cell_color *b)
-{
-  return a->r == b->r && a->g == b->g && a->b == b->b;
-}
-
-struct cell_style
-  {
-    struct cell_color fg[2], bg[2];
-    int margin[TABLE_N_AXES][2];
-    char *typeface;
-    int size;
-    bool bold, italic, underline;
-  };
-
-#define CELL_STYLE_INITIALIZER                                  \
-    {                                                           \
-      .fg = { [0] = CELL_COLOR_BLACK, [1] = CELL_COLOR_BLACK},  \
-      .bg = { [0] = CELL_COLOR_WHITE, [1] = CELL_COLOR_WHITE},  \
-      .margin = { [TABLE_HORZ][0] = 8, [TABLE_HORZ][1] = 11,    \
-                  [TABLE_VERT][0] = 1, [TABLE_VERT][1] = 1 },   \
-      .typeface = NULL,                                         \
-      .size = 0,                                                \
-      .bold = false,                                            \
-      .italic = false,                                          \
-      .underline = false,                                       \
-    }
-
-struct cell_style *cell_style_clone (struct pool *, const struct cell_style *);
-void cell_style_free (struct cell_style *);
-
 /* A cell in a table. */
 struct table_cell
   {
@@ -98,7 +60,7 @@ struct table_cell
     const struct footnote **footnotes;
     size_t n_footnotes;
 
-    const struct cell_style *style;
+    const struct area_style *style;
 
     /* Called to free the cell's data, if nonnull. */
     void (*destructor) (void *destructor_aux);
index f909bf3ade90f925be4b13f70762a8a3ee0c8c1b..d94316eed2bc62ed430d6085431652ec7554e347 100644 (file)
 #include "output/table-provider.h"
 
 #include <assert.h>
+#include <inttypes.h>
 #include <stdlib.h>
 
+#include "libpspp/assertion.h"
 #include "libpspp/cast.h"
 #include "libpspp/compiler.h"
 #include "libpspp/pool.h"
@@ -130,22 +132,22 @@ table_set_nr (struct table *table, int nr)
   table->n[TABLE_VERT] = nr;
 }
 \f
-struct cell_style *
-cell_style_clone (struct pool *pool, const struct cell_style *old)
+struct area_style *
+area_style_clone (struct pool *pool, const struct area_style *old)
 {
-  struct cell_style *new = pool_malloc (pool, sizeof *new);
+  struct area_style *new = pool_malloc (pool, sizeof *new);
   *new = *old;
-  if (new->typeface)
-    new->typeface = pool_strdup (pool, new->typeface);
+  if (new->font_style.typeface)
+    new->font_style.typeface = pool_strdup (pool, new->font_style.typeface);
   return new;
 }
 
 void
-cell_style_free (struct cell_style *style)
+area_style_free (struct area_style *style)
 {
   if (style)
     {
-      free (style->typeface);
+      free (style->font_style.typeface);
       free (style);
     }
 }
@@ -162,7 +164,7 @@ table_get_cell (const struct table *table, int x, int y,
   assert (x >= 0 && x < table->n[TABLE_HORZ]);
   assert (y >= 0 && y < table->n[TABLE_VERT]);
 
-  static const struct cell_style default_style = CELL_STYLE_INITIALIZER;
+  static const struct area_style default_style = AREA_STYLE_INITIALIZER;
   cell->style = &default_style;
 
   table->klass->get_cell (table, x, y, cell);
@@ -220,7 +222,7 @@ table_get_rule (const struct table *table, enum table_axis axis, int x, int y,
 {
   assert (x >= 0 && x < table->n[TABLE_HORZ] + (axis == TABLE_HORZ));
   assert (y >= 0 && y < table->n[TABLE_VERT] + (axis == TABLE_VERT));
-  *color = CELL_COLOR_BLACK;
+  *color = (struct cell_color) CELL_COLOR_BLACK;
   return table->klass->get_rule (table, axis, x, y, color);
 }
 
@@ -374,7 +376,7 @@ struct table_string
   {
     struct table table;
     char *string;
-    unsigned int options;
+    enum table_halign halign;
   };
 
 static const struct table_class table_string_class;
@@ -382,13 +384,13 @@ static const struct table_class table_string_class;
 /* Returns a table that contains a single cell, whose contents are S with
    options OPTIONS (a combination of TAB_* values).  */
 struct table *
-table_from_string (unsigned int options, const char *s)
+table_from_string (enum table_halign halign, const char *s)
 {
   struct table_string *ts = xmalloc (sizeof *ts);
   table_init (&ts->table, &table_string_class);
   ts->table.n[TABLE_HORZ] = ts->table.n[TABLE_VERT] = 1;
   ts->string = xstrdup (s);
-  ts->options = options;
+  ts->halign = halign;
   return &ts->table;
 }
 
@@ -411,12 +413,21 @@ static void
 table_string_get_cell (const struct table *ts_, int x UNUSED, int y UNUSED,
                        struct table_cell *cell)
 {
+  static const struct area_style styles[] = {
+#define S(H) [H] = { AREA_STYLE_INITIALIZER__, .cell_style.halign = H }
+    S(TABLE_HALIGN_LEFT),
+    S(TABLE_HALIGN_CENTER),
+    S(TABLE_HALIGN_RIGHT),
+    S(TABLE_HALIGN_MIXED),
+    S(TABLE_HALIGN_DECIMAL),
+  };
   struct table_string *ts = table_string_cast (ts_);
   cell->d[TABLE_HORZ][0] = 0;
   cell->d[TABLE_HORZ][1] = 1;
   cell->d[TABLE_VERT][0] = 0;
   cell->d[TABLE_VERT][1] = 1;
-  cell->options = ts->options;
+  cell->options = 0;
+  cell->style = &styles[table_halign_interpret (ts->halign, false)];
   cell->text = ts->string;
   cell->n_footnotes = 0;
   cell->destructor = NULL;
@@ -439,3 +450,139 @@ static const struct table_class table_string_class =
     NULL,                       /* paste */
     NULL,                       /* select */
   };
+\f
+const char *
+table_halign_to_string (enum table_halign halign)
+{
+  switch (halign)
+    {
+    case TABLE_HALIGN_LEFT: return "left";
+    case TABLE_HALIGN_CENTER: return "center";
+    case TABLE_HALIGN_RIGHT: return "right";
+    case TABLE_HALIGN_DECIMAL: return "decimal";
+    case TABLE_HALIGN_MIXED: return "mixed";
+    default: return "**error**";
+    }
+}
+
+const char *
+table_valign_to_string (enum table_valign valign)
+{
+  switch (valign)
+    {
+    case TABLE_VALIGN_TOP: return "top";
+    case TABLE_VALIGN_CENTER: return "center";
+    case TABLE_VALIGN_BOTTOM: return "bottom";
+    default: return "**error**";
+    }
+}
+
+enum table_halign
+table_halign_interpret (enum table_halign halign, bool numeric)
+{
+  switch (halign)
+    {
+    case TABLE_HALIGN_LEFT:
+    case TABLE_HALIGN_CENTER:
+    case TABLE_HALIGN_RIGHT:
+      return halign;
+
+    case TABLE_HALIGN_MIXED:
+      return numeric ? TABLE_HALIGN_RIGHT : TABLE_HALIGN_LEFT;
+
+    case TABLE_HALIGN_DECIMAL:
+      return TABLE_HALIGN_DECIMAL;
+
+    default:
+      NOT_REACHED ();
+    }
+}
+
+void
+font_style_copy (struct font_style *dst, const struct font_style *src)
+{
+  *dst = *src;
+  if (dst->typeface)
+    dst->typeface = xstrdup (dst->typeface);
+}
+
+void
+font_style_uninit (struct font_style *font)
+{
+  if (font)
+    free (font->typeface);
+}
+
+void
+area_style_copy (struct area_style *dst, const struct area_style *src)
+{
+  font_style_copy (&dst->font_style, &src->font_style);
+  dst->cell_style = src->cell_style;
+}
+
+void
+area_style_uninit (struct area_style *area)
+{
+  if (area)
+    font_style_uninit (&area->font_style);
+}
+
+const char *
+table_stroke_to_string (enum table_stroke stroke)
+{
+  switch (stroke)
+    {
+    case TABLE_STROKE_NONE: return "none";
+    case TABLE_STROKE_SOLID: return "solid";
+    case TABLE_STROKE_DASHED: return "dashed";
+    case TABLE_STROKE_THICK: return "thick";
+    case TABLE_STROKE_THIN: return "thin";
+    case TABLE_STROKE_DOUBLE: return "double";
+    default:
+      return "**error**";
+    }
+}
+
+void
+cell_color_dump (const struct cell_color *c)
+{
+  if (c->alpha != 255)
+    printf ("rgba(%d, %d, %d, %d)", c->r, c->g, c->b, c->alpha);
+  else
+    printf ("#%02"PRIx8"%02"PRIx8"%02"PRIx8, c->r, c->g, c->b);
+}
+
+void
+font_style_dump (const struct font_style *f)
+{
+  printf ("%s %dpx ", f->typeface, f->size);
+  cell_color_dump (&f->fg[0]);
+  putchar ('/');
+  cell_color_dump (&f->bg[0]);
+  if (!cell_color_equal (&f->fg[0], &f->fg[1])
+      || !cell_color_equal (&f->bg[0], &f->bg[1]))
+    {
+      printf (" alt=");
+      cell_color_dump (&f->fg[1]);
+      putchar ('/');
+      cell_color_dump (&f->bg[1]);
+    }
+  if (f->bold)
+    fputs (" bold", stdout);
+  if (f->italic)
+    fputs (" italic", stdout);
+  if (f->underline)
+    fputs (" underline", stdout);
+}
+
+void
+cell_style_dump (const struct cell_style *c)
+{
+  fputs (table_halign_to_string (c->halign), stdout);
+  if (c->halign == TABLE_HALIGN_DECIMAL)
+    printf ("(%.2gpx)", c->decimal_offset);
+  printf (" %s", table_valign_to_string (c->valign));
+  printf (" %d,%d,%d,%dpx",
+          c->margin[TABLE_HORZ][0], c->margin[TABLE_HORZ][1],
+          c->margin[TABLE_VERT][0], c->margin[TABLE_VERT][1]);
+}
index 8586ac1779748e5ca38221187547a592dc0a4cd7..b2c194367f6979df381da49f602958d4b19b5fec 100644 (file)
    table-item.h) for that purpose. */
 
 #include <stdbool.h>
+#include <stdint.h>
 #include <stddef.h>
 
 struct casereader;
 struct fmt_spec;
+struct pool;
 struct table_item;
 struct variable;
 
-/* Properties of a table cell. */
-enum
+/* A table axis.
+
+   Many table-related declarations use 2-element arrays in place of "x" and "y"
+   variables.  This reduces code duplication significantly, because much table
+   code treats rows and columns the same way.
+
+   A lot of code that uses these enumerations assumes that the two values are 0
+   and 1, so don't change them to other values. */
+enum table_axis
   {
-    TAB_NONE = 0,
+    TABLE_HORZ,
+    TABLE_VERT,
+    TABLE_N_AXES
+  };
+
+struct cell_color
+  {
+    uint8_t alpha, r, g, b;
+  };
+
+#define CELL_COLOR(r, g, b) (struct cell_color) { 255, r, g, b }
+#define CELL_COLOR_BLACK CELL_COLOR (0, 0, 0)
+#define CELL_COLOR_WHITE CELL_COLOR (255, 255, 255)
+
+static inline bool
+cell_color_equal (const struct cell_color *a, const struct cell_color *b)
+{
+  return a->alpha == b->alpha && a->r == b->r && a->g == b->g && a->b == b->b;
+}
+
+void cell_color_dump (const struct cell_color *);
+
+enum table_stroke
+  {
+    TABLE_STROKE_NONE,
+    TABLE_STROKE_SOLID,
+    TABLE_STROKE_DASHED,
+    TABLE_STROKE_THICK,
+    TABLE_STROKE_THIN,
+    TABLE_STROKE_DOUBLE,
+    TABLE_N_STROKES,
+  };
+
+const char *table_stroke_to_string (enum table_stroke);
+
+struct table_border_style
+  {
+    enum table_stroke stroke;
+    struct cell_color color;
+  };
+
+#define TABLE_BORDER_STYLE_INITIALIZER { TABLE_STROKE_SOLID, CELL_COLOR_BLACK }
+
+enum table_halign
+  {
+    TABLE_HALIGN_RIGHT,
+    TABLE_HALIGN_LEFT,
+    TABLE_HALIGN_CENTER,
+    TABLE_HALIGN_MIXED,
+    TABLE_HALIGN_DECIMAL
+  };
+
+const char *table_halign_to_string (enum table_halign);
 
-    /* Horizontal alignment of cell contents. */
-    TAB_RIGHT      = 0 << 0,
-    TAB_LEFT       = 1 << 0,
-    TAB_CENTER     = 2 << 0,
-    TAB_HALIGN     = 3 << 0,   /* Alignment mask. */
+enum table_valign
+  {
+    TABLE_VALIGN_TOP,
+    TABLE_VALIGN_CENTER,
+    TABLE_VALIGN_BOTTOM,
+  };
+
+const char *table_valign_to_string (enum table_valign);
+
+struct cell_style
+  {
+    enum table_halign halign;
+    enum table_valign valign;
+    double decimal_offset;       /* In 1/96" units. */
+    char decimal_char;           /* Either '.' or ','. */
+    int margin[TABLE_N_AXES][2]; /* In 1/96" units. */
+  };
+
+#define CELL_STYLE_INITIALIZER { CELL_STYLE_INITIALIZER__ }
+#define CELL_STYLE_INITIALIZER__                                \
+        .margin = { [TABLE_HORZ][0] = 8, [TABLE_HORZ][1] = 11,  \
+                    [TABLE_VERT][0] = 1, [TABLE_VERT][1] = 1 }
+
+void cell_style_dump (const struct cell_style *);
+
+struct font_style
+  {
+    bool bold, italic, underline, markup;
+    struct cell_color fg[2], bg[2];
+    char *typeface;
+    int size;
+  };
+
+#define FONT_STYLE_INITIALIZER { FONT_STYLE_INITIALIZER__ }
+#define FONT_STYLE_INITIALIZER__                                        \
+        .fg = { [0] = CELL_COLOR_BLACK, [1] = CELL_COLOR_BLACK},        \
+        .bg = { [0] = CELL_COLOR_WHITE, [1] = CELL_COLOR_WHITE},
 
-    /* Vertical alignment of cell contents. */
-    TAB_TOP        = 0 << 2,
-    TAB_MIDDLE     = 1 << 2,
-    TAB_BOTTOM     = 2 << 2,
-    TAB_VALIGN     = 3 << 2,   /* Alignment mask. */
+void font_style_copy (struct font_style *, const struct font_style *);
+void font_style_uninit (struct font_style *);
+void font_style_dump (const struct font_style *);
 
-    /* These flags may be combined with any alignment. */
-    TAB_EMPH       = 1 << 4,    /* Emphasize cell contents. */
-    TAB_FIX        = 1 << 5,    /* Use fixed font. */
-    TAB_MARKUP     = 1 << 6,    /* Text contains Pango markup. */
-    TAB_ROTATE     = 1 << 7,    /* Rotate cell contents 90 degrees. */
+struct area_style
+  {
+    struct cell_style cell_style;
+    struct font_style font_style;
+  };
+
+#define AREA_STYLE_INITIALIZER { AREA_STYLE_INITIALIZER__ }
+#define AREA_STYLE_INITIALIZER__                \
+       .cell_style = CELL_STYLE_INITIALIZER,    \
+       .font_style = FONT_STYLE_INITIALIZER
+
+struct area_style *area_style_clone (struct pool *, const struct area_style *);
+void area_style_copy (struct area_style *, const struct area_style *);
+void area_style_uninit (struct area_style *);
+void area_style_free (struct area_style *);
+
+/* Properties of a table cell. */
+enum
+  {
+    TAB_NONE = 0,
+    TAB_EMPH       = 1 << 0,    /* Emphasize cell contents. */
+    TAB_FIX        = 1 << 1,    /* Use fixed font. */
+    TAB_MARKUP     = 1 << 2,    /* Text contains Pango markup. */
+    TAB_NUMERIC    = 1 << 3,    /* Cell contents are numeric. */
+    TAB_ROTATE     = 1 << 4,    /* Rotate cell contents 90 degrees. */
 
     /* Bits with values (1 << TAB_FIRST_AVAILABLE) and higher are
        not used, so they are available for subclasses to use as
        they wish. */
-    TAB_FIRST_AVAILABLE = 8
+    TAB_FIRST_AVAILABLE = 5
   };
 
 /* Styles for the rules around table cells. */
 enum
   {
-    TAL_NONE,                  /* No spacing. */
+    TAL_NONE = TABLE_STROKE_NONE,
 #define TAL_0 TAL_NONE
-    TAL_SOLID,
+    TAL_SOLID = TABLE_STROKE_SOLID,
 #define TAL_1 TAL_SOLID
-    TAL_DASHED,
-    TAL_THICK,
-    TAL_THIN,
-    TAL_DOUBLE,
+    TAL_DASHED = TABLE_STROKE_DASHED,
+    TAL_THICK = TABLE_STROKE_THICK,
+    TAL_THIN = TABLE_STROKE_THIN,
+    TAL_DOUBLE = TABLE_STROKE_DOUBLE,
 #define TAL_2 TAL_DOUBLE
-    N_LINES
   };
 
 /* Given line styles A and B (each one of the TAL_* enumeration constants
@@ -98,21 +208,6 @@ static inline int table_rule_combine (int a, int b)
   return a > b ? a : b;
 }
 
-/* A table axis.
-
-   Many table-related declarations use 2-element arrays in place of "x" and "y"
-   variables.  This reduces code duplication significantly, because much table
-   code has treat rows and columns the same way.
-
-   A lot of code that uses these enumerations assumes that the two values are 0
-   and 1, so don't change them to other values. */
-enum table_axis
-  {
-    TABLE_HORZ,
-    TABLE_VERT,
-    TABLE_N_AXES
-  };
-
 /* A table. */
 struct table
   {
@@ -175,9 +270,7 @@ void table_set_hb (struct table *, int hb);
 /* Table classes. */
 
 /* Simple kinds of tables. */
-struct table *table_from_string (unsigned int options, const char *);
-struct table *table_from_string_span (unsigned int options, const char *,
-                                      int colspan, int rowspan);
+struct table *table_from_string (enum table_halign, const char *);
 struct table *table_from_variables (unsigned int options,
                                     struct variable **, size_t);
 struct table *table_from_casereader (const struct casereader *,
index 5b18e54c5d4618c693865fb5e9d624accc8ef852..a122caf3bff0c90303fa00077a7f77238db1f538 100644 (file)
@@ -99,14 +99,16 @@ text_item_to_table_item (struct text_item *text_item)
 {
   struct tab_table *tab = tab_create (1, 1);
 
-  struct cell_style *style = pool_alloc (tab->container, sizeof *style);
-  *style = (struct cell_style) CELL_STYLE_INITIALIZER;
+  struct area_style *style = pool_alloc (tab->container, sizeof *style);
+  *style = (struct area_style) AREA_STYLE_INITIALIZER;
+  struct font_style *font_style = &style->font_style;
   if (text_item->typeface)
-    style->typeface = pool_strdup (tab->container, text_item->typeface);
-  style->size = text_item->size;
-  style->bold = text_item->bold;
-  style->italic = text_item->italic;
-  style->underline = text_item->underline;
+    font_style->typeface = pool_strdup (tab->container, text_item->typeface);
+  font_style->size = text_item->size;
+  font_style->bold = text_item->bold;
+  font_style->italic = text_item->italic;
+  font_style->underline = text_item->underline;
+  font_style->markup = text_item->markup;
   tab->styles[0] = style;
 
   int opts = TAB_LEFT;
index a8f1e493e92fdb7382c91d947d1fe59b6ed62479..2e27529fecbae5ad29039bf4f07ea618c978ed26 100644 (file)
@@ -50,9 +50,10 @@ struct text_item
     struct output_item output_item;
     char *text;                 /* The content. */
     enum text_item_type type;   /* Type. */
+
+    bool bold, italic, underline, markup;
     char *typeface;
     int size;
-    bool bold, italic, underline, markup;
   };
 
 struct text_item *text_item_create (enum text_item_type, const char *text);