Added confidence and prediction intervals to model export
[pspp-builds.git] / src / tab.c
index fbb292fdbb84b6639a844b26a1d689df87e1fc31..4aa7f069bc0cdceb43e426ca0d938aa16bc24091 100644 (file)
--- a/src/tab.c
+++ b/src/tab.c
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA. */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA. */
 
 #include <config.h>
 #include "tab.h"
 #include <ctype.h>
-#include <assert.h>
 #include <stdarg.h>
 #include <limits.h>
 #include <stdlib.h>
+#include "error.h"
 #include "alloc.h"
 #include "command.h"
 #include "format.h"
 #include "som.h"
 #include "var.h"
 
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
 #include "debug-print.h"
 \f
 struct som_table_class tab_table_class;
 
-#if DEBUGGING
-#define DEFFIRST(NAME, LABEL) LABEL,
-#define DEFTAB(NAME, LABEL) LABEL,
-/*
-static const char *tab_names[] =
-  {
-#include "tab.def"
-  };
-*/
-#undef DEFFIRST
-#undef DEFTAB
-#endif
-
 /* Creates a table with NC columns and NR rows.  If REALLOCABLE is
    nonzero then the table's size can be increased later; otherwise,
    its size can only be reduced. */
 struct tab_table *
 tab_create (int nc, int nr, int reallocable)
 {
-  void *(*alloc_func) (struct pool *, size_t);
+  void *(*alloc_func) (struct pool *, size_t n);
+  void *(*nalloc_func) (struct pool *, size_t n, size_t s);
 
   struct tab_table *t;
   
@@ -75,28 +66,29 @@ tab_create (int nc, int nr, int reallocable)
   t->nc = t->cf = nc;
   t->l = t->r = t->t = t->b = 0;
 
+  nalloc_func = reallocable ? pool_nmalloc : pool_nalloc;
   alloc_func = reallocable ? pool_malloc : pool_alloc;
 #if GLOBAL_DEBUGGING
   t->reallocable = reallocable;
 #endif
 
-  t->cc = alloc_func (t->container, nr * nc * sizeof *t->cc);
+  t->cc = nalloc_func (t->container, nr * nc, sizeof *t->cc);
   t->ct = alloc_func (t->container, nr * nc);
   memset (t->ct, TAB_EMPTY, nc * nr);
 
-  t->rh = alloc_func (t->container, nc * (nr + 1));
+  t->rh = nalloc_func (t->container, nc, nr + 1);
   memset (t->rh, 0, nc * (nr + 1));
 
-  t->hrh = alloc_func (t->container, sizeof *t->hrh * (nr + 1));
+  t->hrh = nalloc_func (t->container, nr + 1, sizeof *t->hrh);
   memset (t->hrh, 0, sizeof *t->hrh * (nr + 1));
 
   t->trh = alloc_func (t->container, nr + 1);
   memset (t->trh, 0, nr + 1);
 
-  t->rv = alloc_func (t->container, (nc + 1) * nr);
+  t->rv = nalloc_func (t->container, nr, nc + 1);
   memset (t->rv, 0, (nc + 1) * nr);
 
-  t->wrv = alloc_func (t->container, sizeof *t->wrv * (nc + 1));
+  t->wrv = nalloc_func (t->container, nc + 1, sizeof *t->wrv);
   memset (t->wrv, 0, sizeof *t->wrv * (nc + 1));
 
   t->trv = alloc_func (t->container, nc + 1);
@@ -169,11 +161,11 @@ tab_realloc (struct tab_table *t, int nc, int nr)
       int mr1 = min (nr, t->nr);
       int mc1 = min (nc, t->nc);
       
-      struct len_string *new_cc;
+      struct fixed_string *new_cc;
       unsigned char *new_ct;
       int r;
 
-      new_cc = pool_malloc (t->container, nr * nc * sizeof *new_cc);
+      new_cc = pool_nmalloc (t->container, nr * nc, sizeof *new_cc);
       new_ct = pool_malloc (t->container, nr * nc);
       for (r = 0; r < mr1; r++)
        {
@@ -189,14 +181,13 @@ tab_realloc (struct tab_table *t, int nc, int nr)
     }
   else if (nr != t->nr)
     {
-      t->cc = pool_realloc (t->container, t->cc, nr * nc * sizeof *t->cc);
+      t->cc = pool_nrealloc (t->container, t->cc, nr * nc, sizeof *t->cc);
       t->ct = pool_realloc (t->container, t->ct, nr * nc);
 
-      t->rh = pool_realloc (t->container, t->rh, nc * (nr + 1));
-      t->rv = pool_realloc (t->container, t->rv, (nc + 1) * nr);
+      t->rh = pool_nrealloc (t->container, t->rh, nc, nr + 1);
+      t->rv = pool_nrealloc (t->container, t->rv, nr, nc + 1);
       t->trh = pool_realloc (t->container, t->trh, nr + 1);
-      t->hrh = pool_realloc (t->container, t->hrh,
-                            sizeof *t->hrh * (nr + 1));
+      t->hrh = pool_nrealloc (t->container, t->hrh, nr + 1, sizeof *t->hrh);
       
       if (nr > t->nr)
        {
@@ -223,6 +214,12 @@ void
 tab_headers (struct tab_table *table, int l, int r, int t, int b)
 {
   assert (table != NULL);
+  assert (l < table->nc);
+  assert (r < table->nc);
+  assert (t < table->nr);
+  assert (b < table->nr);
+
+
   table->l = l;
   table->r = r;
   table->t = t;
@@ -252,11 +249,6 @@ tab_vline (struct tab_table *t, int style, int x, int y1, int y2)
   int y;
 
   assert (t != NULL);
-  assert (x  > 0);
-  assert (x  < t->nc);
-  assert (y1 >= 0);
-  assert (y2 >= y1);
-  assert (y2 <=  t->nr);
 
 #if GLOBAL_DEBUGGING
   if (x + t->col_ofs < 0 || x + t->col_ofs > t->nc
@@ -277,6 +269,12 @@ tab_vline (struct tab_table *t, int style, int x, int y1, int y2)
   y1 += t->row_ofs;
   y2 += t->row_ofs;
 
+  assert (x  > 0);
+  assert (x  < t->nc);
+  assert (y1 >= 0);
+  assert (y2 >= y1);
+  assert (y2 <=  t->nr);
+
   if (style != -1)
     {
       if ((style & TAL_SPACING) == 0)
@@ -295,16 +293,16 @@ tab_hline (struct tab_table * t, int style, int x1, int x2, int y)
 
   assert (t != NULL);
 
+  x1 += t->col_ofs;
+  x2 += t->col_ofs;
+  y += t->row_ofs;
+
   assert (y >= 0);
   assert (y < t->nr);
   assert (x2 >= x1 );
   assert (x1 >= 0 );
   assert (x2 < t->nc);
 
-  x1 += t->col_ofs;
-  x2 += t->col_ofs;
-  y += t->row_ofs;
-
   if (style != -1)
     {
       if ((style & TAL_SPACING) == 0)
@@ -326,13 +324,6 @@ tab_box (struct tab_table *t, int f_h, int f_v, int i_h, int i_v,
 {
   assert (t != NULL);
 
-  assert (x2 >= x1);
-  assert (y2 >= y1);
-  assert (x1 >= 0);
-  assert (y1 >= 0);
-  assert (x2 < t->nc);
-  assert (y2 < t->nr);
-
 #if GLOBAL_DEBUGGING
   if (x1 + t->col_ofs < 0 || x1 + t->col_ofs >= t->nc 
       || x2 + t->col_ofs < 0 || x2 + t->col_ofs >= t->nc
@@ -355,6 +346,13 @@ tab_box (struct tab_table *t, int f_h, int f_v, int i_h, int i_v,
   y1 += t->row_ofs;
   y2 += t->row_ofs;
 
+  assert (x2 >= x1);
+  assert (y2 >= y1);
+  assert (x1 >= 0);
+  assert (y1 >= 0);
+  assert (x2 < t->nc);
+  assert (y2 < t->nr);
+
   if (f_h != -1)
     {
       int x;
@@ -416,7 +414,7 @@ tab_box (struct tab_table *t, int f_h, int f_v, int i_h, int i_v,
    the resultant string into S in TABLE's pool. */
 static void
 text_format (struct tab_table *table, int opt, const char *text, va_list args,
-            struct len_string *s)
+            struct fixed_string *s)
 {
   int len;
   
@@ -432,7 +430,8 @@ text_format (struct tab_table *table, int opt, const char *text, va_list args,
   else
     len = strlen (text);
 
-  ls_create_buffer (table->container, s, text, len);
+  ls_create_buffer (s, text, len);
+  pool_register (table->container, free, s->string);
   
   if (opt & TAT_PRINTF)
     local_free (text);
@@ -612,9 +611,7 @@ tab_float (struct tab_table *table, int c, int r, unsigned char opt,
   assert (r >= 0);
   assert (r < table->nr);
 
-  f.type = FMT_F;
-  f.w = w;
-  f.d = d;
+  f = make_output_format (FMT_F, w, d);
   
 #if GLOBAL_DEBUGGING
   if (c + table->col_ofs < 0 || r + table->row_ofs < 0
@@ -689,12 +686,12 @@ tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2,
 
   assert (table != NULL && text != NULL);
 
-  assert (x1 >= 0);
-  assert (y1 >= 0);
+  assert (x1 + table->col_ofs >= 0);
+  assert (y1 + table->row_ofs >= 0);
   assert (y2 >= y1);
   assert (x2 >= x1);
-  assert (y2 < table->nr);
-  assert (x2 < table->nc);
+  assert (y2 + table->row_ofs < table->nr);
+  assert (x2 + table->col_ofs < table->nc);
 
 #if GLOBAL_DEBUGGING
   if (x1 + table->col_ofs < 0 || x1 + table->col_ofs >= table->nc
@@ -731,7 +728,7 @@ tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2,
   opt |= TAB_JOIN;
   
   {
-    struct len_string *cc = &table->cc[x1 + y1 * table->cf];
+    struct fixed_string *cc = &table->cc[x1 + y1 * table->cf];
     unsigned char *ct = &table->ct[x1 + y1 * table->cf];
     const int ofs = table->cf - (x2 - x1);
 
@@ -756,7 +753,7 @@ tab_joint_text (struct tab_table *table, int x1, int y1, int x2, int y2,
 /* 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,
-        struct len_string *string)
+        struct fixed_string *string)
 {
   assert (table != NULL && string != NULL);
   
@@ -873,11 +870,12 @@ tab_flags (struct tab_table *t, unsigned flags)
 void
 tab_submit (struct tab_table *t)
 {
-  struct som_table s;
+  struct som_entity s;
 
   assert (t != NULL);
   s.class = &tab_table_class;
   s.ext = t;
+  s.type = SOM_TABLE;
   som_submit (&s);
   tab_destroy (t);
 }
@@ -932,15 +930,17 @@ int tab_hit;
 
 /* Set the current table to TABLE. */
 static void
-tabi_table (struct som_table *table)
+tabi_table (struct som_entity *table)
 {
   assert (table != NULL);
+  assert (table->type == SOM_TABLE);
+
   t = table->ext;
   tab_offset (t, 0, 0);
   
   assert (t->w == NULL && t->h == NULL);
-  t->w = pool_alloc (t->container, sizeof *t->w * t->nc);
-  t->h = pool_alloc (t->container, sizeof *t->h * t->nr);
+  t->w = pool_nalloc (t->container, t->nc, sizeof *t->w);
+  t->h = pool_nalloc (t->container, t->nr, sizeof *t->h);
 }
 
 /* Set the current output device to DRIVER. */
@@ -1139,6 +1139,45 @@ tabi_flags (unsigned *flags)
   *flags = t->flags;
 }
 
+/* Returns true if the table will fit in the given page WIDTH,
+   false otherwise. */
+static bool
+tabi_fits_width (int width) 
+{
+  int i;
+
+  for (i = t->l; i < t->nc - t->r; i++)
+    if (t->wl + t->wr + t->w[i] > width)
+      return false;
+
+  return true;
+}
+
+/* Returns true if the table will fit in the given page LENGTH,
+   false otherwise. */
+static bool
+tabi_fits_length (int length) 
+{
+  int i;
+
+  for (i = t->t; i < t->nr - t->b; i++)
+    if (t->ht + t->hb + t->h[i] > length)
+      return false;
+
+  return true;
+}
+
+/* Sets the number of header rows/columns on the left, right, top,
+   and bottom sides to HL, HR, HT, and HB, respectively. */
+static void
+tabi_set_headers (int hl, int hr, int ht, int hb)
+{
+  t->l = hl;
+  t->r = hr;
+  t->t = ht;
+  t->b = hb;
+}
+
 /* Render title for current table, with major index X and minor index
    Y.  Y may be zero, or X and Y may be zero, but X should be nonzero
    if Y is nonzero. */
@@ -1161,7 +1200,7 @@ tabi_title (int x, int y)
   cp = stpcpy (cp, ".  ");
   if (!ls_empty_p (&t->title))
     {
-      memcpy (cp, ls_value (&t->title), ls_length (&t->title));
+      memcpy (cp, ls_c_str (&t->title), ls_length (&t->title));
       cp += ls_length (&t->title);
     }
   *cp = 0;
@@ -1239,9 +1278,12 @@ struct som_table_class tab_table_class =
     NULL,
     tabi_cumulate,
     tabi_flags,
+    tabi_fits_width,
+    tabi_fits_length,
     
     NULL,
     NULL,
+    tabi_set_headers,
 
     tabi_title,
     tabi_render,
@@ -1336,7 +1378,7 @@ render_strip (int x, int y, int r, int c1, int c2, int r1 UNUSED, int r2)
                    }
                } else {
                  struct tab_joined_cell *j =
-                   (struct tab_joined_cell *) ls_value (&t->cc[index]);
+                   (struct tab_joined_cell *) ls_c_str (&t->cc[index]);
 
                  if (j->hit != tab_hit)
                    {