Implement SET LEADZERO.
[pspp] / src / output / spv / spv-writer.c
index e3f3b28ffae9fbc41aa445fa30ae60de6a657bf2..3d56429d6604c5ca6b90426b457fdffa4416b0ae 100644 (file)
 #include "libpspp/version.h"
 #include "libpspp/zip-writer.h"
 #include "output/cairo-chart.h"
-#include "output/chart-item.h"
 #include "output/driver.h"
-#include "output/group-item.h"
-#include "output/image-item.h"
-#include "output/page-break-item.h"
-#include "output/page-setup-item.h"
+#include "output/output-item.h"
+#include "output/page-setup.h"
 #include "output/pivot-table.h"
-#include "output/table-item.h"
-#include "output/text-item.h"
 
 #include "gl/xalloc.h"
 #include "gl/xvasprintf.h"
@@ -199,8 +194,9 @@ spv_writer_open_file (struct spv_writer *w)
 
   time_t t = time (NULL);
   struct tm *tm = gmtime (&t);
-  char *tm_s = asctime (tm);
-  write_attr (w, "creation-date-time", tm_s);
+  char tm_s[128];
+  if (strftime (tm_s, sizeof tm_s, "%x %X", tm))
+    write_attr (w, "creation-date-time", tm_s);
 
   write_attr (w, "creator", version);
 
@@ -239,6 +235,8 @@ spv_writer_open_heading (struct spv_writer *w, const struct output_item *item)
   start_elem (w, "heading");
   if (item->command_name)
     write_attr (w, "commandName", item->command_name);
+  if (!item->show)
+    write_attr (w, "visibility", "collapsed");
   /* XXX locale */
   /* XXX olang */
 
@@ -285,7 +283,7 @@ open_container (struct spv_writer *w, const struct output_item *item,
                 const char *inner_elem)
 {
   start_elem (w, "container");
-  write_attr (w, "visibility", "visible");
+  write_attr (w, "visibility", item->show ? "visible" : "hidden");
   if (w->need_page_break)
     {
       write_attr (w, "page-break-before", "always");
@@ -309,19 +307,20 @@ close_container (struct spv_writer *w)
 }
 
 static void
-spv_writer_put_text (struct spv_writer *w, const struct text_item *text)
+spv_writer_put_text (struct spv_writer *w, struct output_item *item)
 {
   bool initial_depth = w->heading_depth;
   if (!initial_depth)
     spv_writer_open_file (w);
 
-  open_container (w, &text->output_item, "vtx:text");
-  write_attr (w, "type", (text->type == TEXT_ITEM_TITLE ? "title"
-                          : text->type == TEXT_ITEM_PAGE_TITLE ? "page-title"
-                          : "log"));
+  open_container (w, item, "vtx:text");
+  write_attr (w, "type",
+              (item->text.subtype == TEXT_ITEM_TITLE ? "title"
+               : item->text.subtype == TEXT_ITEM_PAGE_TITLE ? "page-title"
+               : "log"));
 
   start_elem (w, "html");
-  char *s = text_item_get_plain_text (text);
+  char *s = text_item_get_plain_text (item);
   write_text (w, s);
   free (s);
   end_elem (w);
@@ -330,6 +329,8 @@ spv_writer_put_text (struct spv_writer *w, const struct text_item *text)
 
   if (!initial_depth)
     spv_writer_close_file (w, "");
+
+  output_item_unref (item);
 }
 
 static cairo_status_t
@@ -557,20 +558,25 @@ static void
 put_value_mod (struct buf *buf, const struct pivot_value *value,
                const char *template)
 {
-  if (value->n_footnotes || value->n_subscripts
-      || template || value->font_style || value->cell_style)
+  if ((value->ex
+       && (value->ex->n_footnotes
+           || value->ex->n_subscripts
+           || value->ex->font_style
+           || value->ex->cell_style))
+      || template)
     {
+      const struct pivot_value_ex *ex = pivot_value_ex (value);
       put_byte (buf, 0x31);
 
       /* Footnotes. */
-      put_u32 (buf, value->n_footnotes);
-      for (size_t i = 0; i < value->n_footnotes; i++)
-        put_u16 (buf, value->footnote_indexes[i]);
+      put_u32 (buf, ex->n_footnotes);
+      for (size_t i = 0; i < ex->n_footnotes; i++)
+        put_u16 (buf, ex->footnote_indexes[i]);
 
       /* Subscripts. */
-      put_u32 (buf, value->n_subscripts);
-      for (size_t i = 0; i < value->n_subscripts; i++)
-        put_string (buf, value->subscripts[i]);
+      put_u32 (buf, ex->n_subscripts);
+      for (size_t i = 0; i < ex->n_subscripts; i++)
+        put_string (buf, ex->subscripts[i]);
 
       /* Template and style. */
       uint32_t v3_start = start_count (buf);
@@ -584,7 +590,7 @@ put_value_mod (struct buf *buf, const struct pivot_value *value,
           put_string (buf, template);
         }
       end_count_u32 (buf, template_string_start);
-      put_style_pair (buf, value->font_style, value->cell_style);
+      put_style_pair (buf, ex->font_style, ex->cell_style);
       end_count_u32 (buf, v3_start);
     }
   else
@@ -643,9 +649,10 @@ put_value (struct buf *buf, const struct pivot_value *value)
       put_value_mod (buf, value, NULL);
       size_t len = strlen (value->string.s);
       if (value->string.hex)
-        put_format (buf, &(struct fmt_spec) { FMT_AHEX, len * 2, 0 }, false);
+        put_format (buf, &(struct fmt_spec) { .type = FMT_AHEX, .w = len * 2 },
+                    false);
       else
-        put_format (buf, &(struct fmt_spec) { FMT_A, len, 0 }, false);
+        put_format (buf, &(struct fmt_spec) { .type = FMT_A, .w = len }, false);
       put_string (buf, value->string.value_label);
       put_string (buf, value->string.var_name);
       put_show_values (buf, value->string.show);
@@ -792,7 +799,10 @@ put_y1 (struct buf *buf, const struct pivot_table *table)
   put_string (buf, table->language);
   put_string (buf, "UTF-8");    /* XXX */
   put_string (buf, table->locale);
-  put_bytes (buf, "\0\0\1\1", 4);
+  put_bool (buf, false);        /* x10 */
+  put_bool (buf, table->settings.include_leading_zero);
+  put_bool (buf, true);         /* x12 */
+  put_bool (buf, true);         /* x13 */
   put_y0 (buf, table);
 }
 
@@ -1051,7 +1061,7 @@ put_light_table (struct buf *buf, uint64_t table_id,
 }
 
 static void
-spv_writer_put_table (struct spv_writer *w, const struct table_item *item)
+spv_writer_put_table (struct spv_writer *w, const struct output_item *item)
 {
   int table_id = ++w->n_tables;
 
@@ -1059,12 +1069,12 @@ spv_writer_put_table (struct spv_writer *w, const struct table_item *item)
   if (!initial_depth)
     spv_writer_open_file (w);
 
-  open_container (w, &item->output_item, "vtb:table");
+  open_container (w, item, "vtb:table");
 
   write_attr (w, "type", "table"); /* XXX */
   write_attr_format (w, "tableId", "%d", table_id);
-  char *subtype = (item->pt->subtype
-                   ? pivot_value_to_string (item->pt->subtype, item->pt)
+  char *subtype = (item->table->subtype
+                   ? pivot_value_to_string (item->table->subtype, item->table)
                    : xstrdup ("unknown"));
   write_attr (w, "subType", subtype);
   free (subtype);
@@ -1082,7 +1092,7 @@ spv_writer_put_table (struct spv_writer *w, const struct table_item *item)
     spv_writer_close_file (w, "");
 
   struct buf buf = { NULL, 0, 0 };
-  put_light_table (&buf, table_id, item->pt);
+  put_light_table (&buf, table_id, item->table);
   zip_writer_add_memory (w->zw, data_path, buf.data, buf.len);
   free (buf.data);
 
@@ -1092,31 +1102,54 @@ spv_writer_put_table (struct spv_writer *w, const struct table_item *item)
 void
 spv_writer_write (struct spv_writer *w, const struct output_item *item)
 {
-  if (is_group_open_item (item))
-    spv_writer_open_heading (w, item);
-  else if (is_group_close_item (item))
-    spv_writer_close_heading (w);
-  else if (is_table_item (item))
-    spv_writer_put_table (w, to_table_item (item));
-  else if (is_chart_item (item))
-    {
-      cairo_surface_t *surface = xr_draw_image_chart (
-        to_chart_item (item),
-        &(struct cell_color) CELL_COLOR_BLACK,
-        &(struct cell_color) CELL_COLOR_WHITE);
-      if (cairo_surface_status (surface) == CAIRO_STATUS_SUCCESS)
-        spv_writer_put_image (w, item, surface);
-      cairo_surface_destroy (surface);
-    }
-  else if (is_image_item (item))
-    spv_writer_put_image (w, item, to_image_item (item)->image);
-  else if (is_text_item (item))
-    spv_writer_put_text (w, to_text_item (item));
-  else if (is_page_break_item (item))
-    w->need_page_break = true;
-  else if (is_page_setup_item (item))
+  switch (item->type)
     {
-      page_setup_destroy (w->page_setup);
-      w->page_setup = page_setup_clone (to_page_setup_item (item)->page_setup);
+    case OUTPUT_ITEM_CHART:
+      {
+        cairo_surface_t *surface = xr_draw_image_chart (
+          item->chart,
+          &(struct cell_color) CELL_COLOR_BLACK,
+          &(struct cell_color) CELL_COLOR_WHITE);
+        if (cairo_surface_status (surface) == CAIRO_STATUS_SUCCESS)
+          spv_writer_put_image (w, item, surface);
+        cairo_surface_destroy (surface);
+      }
+      break;
+
+    case OUTPUT_ITEM_GROUP:
+      spv_writer_open_heading (w, item);
+      for (size_t i = 0; i < item->group.n_children; i++)
+        spv_writer_write (w, item->group.children[i]);
+      spv_writer_close_heading (w);
+      break;
+
+    case OUTPUT_ITEM_IMAGE:
+      spv_writer_put_image (w, item, item->image);
+      break;
+
+    case OUTPUT_ITEM_MESSAGE:
+      spv_writer_put_text (
+        w, message_item_to_text_item (output_item_ref (item)));
+      break;
+
+    case OUTPUT_ITEM_PAGE_BREAK:
+      w->need_page_break = true;
+      break;
+
+    case OUTPUT_ITEM_TABLE:
+      spv_writer_put_table (w, item);
+      break;
+
+    case OUTPUT_ITEM_TEXT:
+      spv_writer_put_text (w, output_item_ref (item));
+      break;
     }
 }
+
+void
+spv_writer_set_page_setup (struct spv_writer *w,
+                           const struct page_setup *ps)
+{
+  page_setup_destroy (w->page_setup);
+  w->page_setup = page_setup_clone (ps);
+}