Merge commit 'origin/data-encoding'
[pspp-builds.git] / src / output / table.c
index c0af3d0f7dcabb248ba84e435793753219c8d87b..72edf17f08b7f6e9e0dec91ad8b56f5b9e87b88b 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006, 2009 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 #include <data/data-out.h>
 #include <data/format.h>
 #include <data/value.h>
-#include <libpspp/alloc.h>
+#include <data/dictionary.h>
 #include <libpspp/assertion.h>
 #include <libpspp/compiler.h>
 #include <libpspp/misc.h>
 #include <libpspp/pool.h>
 
+#include <data/settings.h>
+
 #include "minmax.h"
+#include "xalloc.h"
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
@@ -370,18 +373,6 @@ tab_box (struct tab_table *t, int f_h, int f_v, int i_h, int i_v,
     }
 }
 
-/* Formats text TEXT and arguments ARGS as indicated in OPT in
-   TABLE's pool and returns the resultant string. */
-static struct substring
-text_format (struct tab_table *table, int opt, const char *text, va_list args)
-{
-  assert (table != NULL && text != NULL);
-
-  return ss_cstr (opt & TAT_PRINTF
-                  ? pool_vasprintf (table->container, text, args)
-                  : pool_strdup (table->container, text));
-}
-
 /* Set the title of table T to TITLE, which is formatted as if
    passed to printf(). */
 void
@@ -397,10 +388,11 @@ tab_title (struct tab_table *t, const char *title, ...)
 
 /* Set DIM_FUNC as the dimension function for table T. */
 void
-tab_dim (struct tab_table *t, tab_dim_func *dim_func)
+tab_dim (struct tab_table *t, tab_dim_func *dim_func, void *aux)
 {
   assert (t != NULL && t->dim == NULL);
   t->dim = dim_func;
+  t->dim_aux = aux;
 }
 
 /* Returns the natural width of column C in table T for driver D, that
@@ -494,7 +486,8 @@ tab_natural_height (struct tab_table *t, struct outp_driver *d, int r)
 /* Callback function to set all columns and rows to their natural
    dimensions.  Not really meant to be called directly.  */
 void
-tab_natural_dimensions (struct tab_table *t, struct outp_driver *d)
+tab_natural_dimensions (struct tab_table *t, struct outp_driver *d,
+                        void *aux UNUSED)
 {
   int i;
 
@@ -514,7 +507,8 @@ tab_natural_dimensions (struct tab_table *t, struct outp_driver *d)
    from V, displayed with format spec F. */
 void
 tab_value (struct tab_table *table, int c, int r, unsigned char opt,
-          const union value *v, const struct fmt_spec *f)
+          const union value *v, const struct dictionary *dict, 
+          const struct fmt_spec *f)
 {
   char *contents;
 
@@ -533,21 +527,19 @@ tab_value (struct tab_table *table, int c, int r, unsigned char opt,
     }
 #endif
 
-  contents = pool_alloc (table->container, f->w);
-  table->cc[c + r * table->cf] = ss_buffer (contents, f->w);
-  table->ct[c + r * table->cf] = opt;
+  contents = data_out_pool (v, dict_get_encoding (dict), f, table->container);
 
-  data_out (v, f, contents);
+  table->cc[c + r * table->cf] = ss_cstr (contents);
+  table->ct[c + r * table->cf] = opt;
 }
 
 /* Sets cell (C,R) in TABLE, with options OPT, to have value VAL
    with NDEC decimal places. */
 void
-tab_float (struct tab_table *table, int c, int r, unsigned char opt,
+tab_fixed (struct tab_table *table, int c, int r, unsigned char opt,
           double val, int w, int d)
 {
-  char *contents;
-  char buf[40], *cp;
+  char *s, *cp;
 
   struct fmt_spec f;
   union value double_value;
@@ -566,7 +558,7 @@ tab_float (struct tab_table *table, int c, int r, unsigned char opt,
       || c + table->col_ofs >= table->nc
       || r + table->row_ofs >= table->nr)
     {
-      printf ("tab_float(): bad cell (%d+%d=%d,%d+%d=%d) in table size "
+      printf ("tab_fixed(): bad cell (%d+%d=%d,%d+%d=%d) in table size "
              "(%d,%d)\n",
              c, table->col_ofs, c + table->col_ofs,
              r, table->row_ofs, r + table->row_ofs,
@@ -576,33 +568,71 @@ tab_float (struct tab_table *table, int c, int r, unsigned char opt,
 #endif
 
   double_value.f = val;
-  data_out (&double_value, &f, buf);
+  s = data_out_pool (&double_value, LEGACY_NATIVE, &f, table->container);
 
-  cp = buf;
-  while (isspace ((unsigned char) *cp) && cp < &buf[w])
+  cp = s;
+  while (isspace ((unsigned char) *cp) && cp < &s[w])
     cp++;
-  f.w = w - (cp - buf);
+  f.w = w - (cp - s);
 
-  contents = pool_alloc (table->container, f.w);
-  table->cc[c + r * table->cf] = ss_buffer (contents, f.w);
+  table->cc[c + r * table->cf] = ss_buffer (cp, f.w);
   table->ct[c + r * table->cf] = opt;
-  memcpy (contents, cp, f.w);
 }
 
-/* Sets cell (C,R) in TABLE, with options OPT, to have text value
-   TEXT. */
+/* Sets cell (C,R) in TABLE, with options OPT, to have value VAL as
+   formatted by FMT.
+   If FMT is null, then the default print format will be used.
+*/
 void
-tab_text (struct tab_table *table, int c, int r, unsigned opt, const char *text, ...)
+tab_double (struct tab_table *table, int c, int r, unsigned char opt,
+          double val, const struct fmt_spec *fmt)
 {
-  va_list args;
+  struct substring ss;
+  union value double_value ;
 
-  assert (table != NULL && text != NULL);
+  assert (table != NULL);
 
-  assert (c >= 0 );
-  assert (r >= 0 );
+  assert (c >= 0);
   assert (c < table->nc);
+  assert (r >= 0);
   assert (r < table->nr);
 
+  if ( fmt == NULL)
+    fmt = settings_get_format ();
+
+  fmt_check_output (fmt);
+
+#if DEBUGGING
+  if (c + table->col_ofs < 0 || r + table->row_ofs < 0
+      || c + table->col_ofs >= table->nc
+      || r + table->row_ofs >= table->nr)
+    {
+      printf ("tab_double(): bad cell (%d+%d=%d,%d+%d=%d) in table size "
+             "(%d,%d)\n",
+             c, table->col_ofs, c + table->col_ofs,
+             r, table->row_ofs, r + table->row_ofs,
+             table->nc, table->nr);
+      return;
+    }
+#endif
+
+  double_value.f = val;
+  ss = ss_cstr (data_out_pool (&double_value, LEGACY_NATIVE, fmt, table->container));
+
+  ss_ltrim (&ss, ss_cstr (" "));
+
+  table->cc[c + r * table->cf] = ss;
+  table->ct[c + r * table->cf] = opt;
+}
+
+
+static void
+do_tab_text (struct tab_table *table, int c, int r, unsigned opt, char *text)
+{
+  assert (c >= 0);
+  assert (r >= 0);
+  assert (c < table->nc);
+  assert (r < table->nr);
 
 #if DEBUGGING
   if (c + table->col_ofs < 0 || r + table->row_ofs < 0
@@ -618,21 +648,38 @@ tab_text (struct tab_table *table, int c, int r, unsigned opt, const char *text,
     }
 #endif
 
-  va_start (args, text);
-  table->cc[c + r * table->cf] = text_format (table, opt, text, args);
+  table->cc[c + r * table->cf] = ss_cstr (text);
   table->ct[c + r * table->cf] = opt;
-  va_end (args);
 }
 
-/* Joins cells (X1,X2)-(Y1,Y2) inclusive in TABLE, and sets them with
-   options OPT to have text value TEXT. */
+/* Sets cell (C,R) in TABLE, with options OPT, to have text value
+   TEXT. */
 void
-tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2,
-               unsigned opt, const char *text, ...)
+tab_text (struct tab_table *table, int c, int r, unsigned opt,
+          const char *text)
 {
-  struct tab_joined_cell *j;
+  do_tab_text (table, c, r, opt, pool_strdup (table->container, text));
+}
+
+/* Sets cell (C,R) in TABLE, with options OPT, to have text value
+   FORMAT, which is formatted as if passed to printf. */
+void
+tab_text_format (struct tab_table *table, int c, int r, unsigned opt,
+                 const char *format, ...)
+{
+  va_list args;
+
+  va_start (args, format);
+  do_tab_text (table, c, r, opt,
+               pool_vasprintf (table->container, format, args));
+  va_end (args);
+}
 
-  assert (table != NULL && text != NULL);
+static void
+do_tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2,
+                   unsigned opt, char *text)
+{
+  struct tab_joined_cell *j;
 
   assert (x1 + table->col_ofs >= 0);
   assert (y1 + table->row_ofs >= 0);
@@ -666,14 +713,7 @@ tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2,
   j->y1 = y1 + table->row_ofs;
   j->x2 = ++x2 + table->col_ofs;
   j->y2 = ++y2 + table->row_ofs;
-
-  {
-    va_list args;
-
-    va_start (args, text);
-    j->contents = text_format (table, opt, text, args);
-    va_end (args);
-  }
+  j->contents = ss_cstr (text);
 
   opt |= TAB_JOIN;
 
@@ -700,6 +740,31 @@ tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2,
   }
 }
 
+/* Joins cells (X1,X2)-(Y1,Y2) inclusive in TABLE, and sets them with
+   options OPT to have text value TEXT. */
+void
+tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2,
+                unsigned opt, const char *text)
+{
+  do_tab_joint_text (table, x1, y1, x2, y2, opt,
+                     pool_strdup (table->container, text));
+}
+
+/* Joins cells (X1,X2)-(Y1,Y2) inclusive in TABLE, and sets them
+   with options OPT to have text value FORMAT, which is formatted
+   as if passed to printf. */
+void
+tab_joint_text_format (struct tab_table *table, int x1, int y1, int x2, int y2,
+                       unsigned opt, const char *format, ...)
+{
+  va_list args;
+
+  va_start (args, format);
+  do_tab_joint_text (table, x1, y1, x2, y2, opt,
+                     pool_vasprintf (table->container, format, args));
+  va_end (args);
+}
+
 /* Sets cell (C,R) in TABLE, with options OPT, to contents STRING. */
 void
 tab_raw (struct tab_table *table, int c, int r, unsigned opt,
@@ -712,7 +777,7 @@ tab_raw (struct tab_table *table, int c, int r, unsigned opt,
       || c + table->col_ofs >= table->nc
       || r + table->row_ofs >= table->nr)
     {
-      printf ("tab_float(): bad cell (%d+%d=%d,%d+%d=%d) in table size "
+      printf ("tab_raw(): bad cell (%d+%d=%d,%d+%d=%d) in table size "
              "(%d,%d)\n",
              c, table->col_ofs, c + table->col_ofs,
              r, table->row_ofs, r + table->row_ofs,
@@ -730,7 +795,7 @@ tab_raw (struct tab_table *table, int c, int r, unsigned opt,
 /* Sets the widths of all the columns and heights of all the rows in
    table T for driver D. */
 static void
-nowrap_dim (struct tab_table *t, struct outp_driver *d)
+nowrap_dim (struct tab_table *t, struct outp_driver *d, void *aux UNUSED)
 {
   t->w[0] = tab_natural_width (t, d, 0);
   t->h[0] = d->font_height;
@@ -739,36 +804,47 @@ nowrap_dim (struct tab_table *t, struct outp_driver *d)
 /* Sets the widths of all the columns and heights of all the rows in
    table T for driver D. */
 static void
-wrap_dim (struct tab_table *t, struct outp_driver *d)
+wrap_dim (struct tab_table *t, struct outp_driver *d, void *aux UNUSED)
 {
   t->w[0] = tab_natural_width (t, d, 0);
   t->h[0] = tab_natural_height (t, d, 0);
 }
 
-/* Outputs text BUF as a table with a single cell having cell options
+static void
+do_tab_output_text (struct tab_table *t, int options, char *text)
+{
+  do_tab_text (t, 0, 0, options, text);
+  tab_flags (t, SOMF_NO_TITLE | SOMF_NO_SPACING);
+  tab_dim (t, options & TAT_NOWRAP ? nowrap_dim : wrap_dim, NULL);
+  tab_submit (t);
+}
+
+/* Outputs TEXT as a table with a single cell having cell options
    OPTIONS, which is a combination of the TAB_* and TAT_*
-   constants. */
+   constants.  */
 void
-tab_output_text (int options, const char *buf, ...)
+tab_output_text (int options, const char *text)
 {
-  struct tab_table *t = tab_create (1, 1, 0);
-  char *tmp_buf = NULL;
-
-  if (options & TAT_PRINTF)
-    {
-      va_list args;
+  struct tab_table *table = tab_create (1, 1, 0);
+  do_tab_output_text (table, options, pool_strdup (table->container, text));
+}
 
-      va_start (args, buf);
-      buf = tmp_buf = xvasprintf (buf, args);
-      va_end (args);
-    }
+/* Outputs FORMAT as a table with a single cell having cell
+   options OPTIONS, which is a combination of the TAB_* and TAT_*
+   constants.  FORMAT is formatted as if it was passed through
+   printf. */
+void
+tab_output_text_format (int options, const char *format, ...)
+{
+  struct tab_table *table;
+  va_list args;
 
-  tab_text (t, 0, 0, options & ~TAT_PRINTF, buf);
-  tab_flags (t, SOMF_NO_TITLE | SOMF_NO_SPACING);
-  tab_dim (t, options & TAT_NOWRAP ? nowrap_dim : wrap_dim);
-  tab_submit (t);
+  table = tab_create (1, 1, 0);
 
-  free (tmp_buf);
+  va_start (args, format);
+  do_tab_output_text (table, options,
+                      pool_vasprintf (table->container, format, args));
+  va_end (args);
 }
 
 /* Set table flags to FLAGS. */
@@ -925,7 +1001,7 @@ tabi_driver (struct outp_driver *driver)
 #endif
 
   assert (t->dim != NULL);
-  t->dim (t, d);
+  t->dim (t, d, t->dim_aux);
 
 #if DEBUGGING
   {