pivot-table: Allow all pivot_value formatting functions to use defaults.
[pspp] / src / output / pivot-table.h
index 56ca865a2d3e4eac589b36b56e5ab1bdb2117d57..630547ebaf755c43c40b0e8c21d41b7e433d11b2 100644 (file)
@@ -25,6 +25,8 @@
 #include "libpspp/hmap.h"
 #include "output/table.h"
 
+struct ccase;
+struct dictionary;
 struct pivot_value;
 struct variable;
 union value;
@@ -177,9 +179,8 @@ enum pivot_axis_type
   {
     PIVOT_AXIS_LAYER,
     PIVOT_AXIS_ROW,
-    PIVOT_AXIS_COLUMN,
-
-    PIVOT_N_AXES
+    PIVOT_AXIS_COLUMN
+#define PIVOT_N_AXES 3
   };
 
 const char *pivot_axis_type_to_string (enum pivot_axis_type);
@@ -278,7 +279,57 @@ struct pivot_dimension *pivot_dimension_create__ (struct pivot_table *,
 
 void pivot_dimension_destroy (struct pivot_dimension *);
 
-void pivot_dimension_dump (const struct pivot_dimension *, int indentation);
+void pivot_dimension_dump (const struct pivot_dimension *,
+                           const struct pivot_table *, int indentation);
+\f
+/* Split file handling with pivot tables.
+
+   When SPLIT FILE is in effect with the LAYERED option, values for the split
+   file variables need to be incorporated into pivot table output.  These
+   functions make that easier.
+
+   To use them:
+
+   1. After adding the rest of the dimensions to an output pivot table, call
+      pivot_splits_create().  If there are any and LAYERED mode is in use, then
+      pivot_splits_create() will add a dimension for each split file
+      variable and return a structure.  Otherwise, it returns NULL.
+
+   2. Before adding data to the pivot table for each SPLIT FILE group, call
+      pivot_splits_new_split(), passing in an example case from the group (the
+      first or last case is fine).  This will the split file handler add
+      categories for the group to the split dimensions.
+
+      pivot_splits_new_split() does nothing if given a null pivot_splits, so
+      it's fine to call it unconditionally.
+
+   3. Use pivot_splits_put*(), instead of pivot_table_put*(), to add data to
+      the pivot table.  These functions automatically add the current group
+      leaf indexes after the indexes passed in, as a convenience.
+
+      These functions still work fine if given a null pivot_splits, so it's
+      fine to use them in all cases.
+
+   4. Destroy the pivot_splits with pivot_splits_destroy() when the pivot table
+      has been fully constructed. */
+
+struct pivot_splits *pivot_splits_create (struct pivot_table *,
+                                          enum pivot_axis_type,
+                                          const struct dictionary *);
+void pivot_splits_destroy (struct pivot_splits *);
+
+void pivot_splits_new_split (struct pivot_splits *, const struct ccase *);
+
+void pivot_splits_put1 (struct pivot_splits *, struct pivot_table *,
+                        size_t idx1, struct pivot_value *);
+void pivot_splits_put2 (struct pivot_splits *, struct pivot_table *,
+                        size_t idx1, size_t idx2, struct pivot_value *);
+void pivot_splits_put3 (struct pivot_splits *, struct pivot_table *,
+                        size_t idx1, size_t idx2, size_t idx3,
+                        struct pivot_value *);
+void pivot_splits_put4 (struct pivot_splits *, struct pivot_table *,
+                        size_t idx1, size_t idx2, size_t idx3, size_t idx4,
+                        struct pivot_value *);
 \f
 /* A pivot_category is a leaf (a category) or a group:
 
@@ -306,10 +357,11 @@ struct pivot_category
     bool show_label_in_corner;
 
     /* Leaf only. */
-    struct fmt_spec format;
     size_t group_index;        /* In ->parent->subs[]. */
     size_t data_index;         /* In ->dimension->data_leaves[]. */
     size_t presentation_index; /* In ->dimension->presentation_leaves[]. */
+    struct fmt_spec format;    /* Default format for values in this category. */
+    bool honor_small;          /* Honor pivot_table 'small' setting? */
   };
 
 static inline bool
@@ -361,6 +413,7 @@ void pivot_category_destroy (struct pivot_category *);
 #define PIVOT_RC_COUNT ("RC_COUNT")
 
 bool pivot_result_class_change (const char *, const struct fmt_spec *);
+bool is_pivot_result_class (const char *);
 \f
 /* Styling for a pivot table.
 
@@ -438,10 +491,8 @@ struct pivot_table
     struct pivot_table_sizing sizing[TABLE_N_AXES];
 
     /* Format settings. */
-    int epoch;
-    char decimal;               /* Usually ',' or '.'. */
+    struct fmt_settings settings;
     char grouping;              /* Usually '.' or ','. */
-    char *ccs[5];               /* Custom currency. */
     double small;
 
     /* Command information. */
@@ -484,9 +535,24 @@ struct pivot_table *pivot_table_create_for_text (struct pivot_value *title,
                                                  struct pivot_value *content);
 
 struct pivot_table *pivot_table_ref (const struct pivot_table *);
+struct pivot_table *pivot_table_unshare (struct pivot_table *);
 void pivot_table_unref (struct pivot_table *);
 bool pivot_table_is_shared (const struct pivot_table *);
 
+/* Titles. */
+void pivot_table_set_title (struct pivot_table *, struct pivot_value *);
+void pivot_table_set_subtype (struct pivot_table *, struct pivot_value *);
+void pivot_table_set_corner_text (struct pivot_table *, struct pivot_value *);
+void pivot_table_set_caption (struct pivot_table *, struct pivot_value *);
+
+/* Axes. */
+void pivot_table_swap_axes (struct pivot_table *,
+                            enum pivot_axis_type, enum pivot_axis_type);
+void pivot_table_transpose (struct pivot_table *);
+void pivot_table_move_dimension (struct pivot_table *,
+                                 struct pivot_dimension *,
+                                 enum pivot_axis_type, size_t ofs);
+
 /* Styling. */
 const struct pivot_table_look *pivot_table_get_look (
   const struct pivot_table *);
@@ -523,6 +589,8 @@ const struct pivot_value *pivot_table_get (const struct pivot_table *,
 struct pivot_value *pivot_table_get_rw (struct pivot_table *,
                                         const size_t *dindexes);
 
+bool pivot_table_delete (struct pivot_table *, const size_t *dindexes);
+
 /* Footnotes.
 
    Use pivot_table_create_footnote() to create a footnote.
@@ -541,6 +609,12 @@ struct pivot_footnote *pivot_table_create_footnote__ (
   struct pivot_table *, size_t idx,
   struct pivot_value *marker, struct pivot_value *content);
 
+void pivot_footnote_format_marker (const struct pivot_footnote *,
+                                   const struct pivot_table *,
+                                   struct string *);
+char *pivot_footnote_marker_string (const struct pivot_footnote *,
+                                    const struct pivot_table *);
+
 void pivot_footnote_destroy (struct pivot_footnote *);
 
 /* Internals. */
@@ -561,7 +635,7 @@ void pivot_table_dump (const struct pivot_table *, int indentation);
 \f
 /* pivot_value. */
 
-enum pivot_value_type
+enum ATTRIBUTE ((packed)) pivot_value_type
   {
     PIVOT_VALUE_NUMERIC,          /* A value of a numeric variable. */
     PIVOT_VALUE_STRING,           /* A value of a string variable. */
@@ -629,71 +703,85 @@ enum pivot_value_type
 */
 struct pivot_value
   {
-    struct font_style *font_style;
-    struct cell_style *cell_style;
-
-    char **subscripts;
-    size_t n_subscripts;
-
-    const struct pivot_footnote **footnotes;
-    size_t n_footnotes;
-
-    enum pivot_value_type type;
+    struct pivot_value_ex *ex;
     union
       {
+        enum pivot_value_type type;
+
         /* PIVOT_VALUE_NUMERIC. */
         struct
           {
-            double x;                 /* The numeric value. */
+            enum pivot_value_type type;
+            enum settings_value_show show; /* Show value or label or both? */
             struct fmt_spec format;   /* Format to display 'x'. */
+            bool honor_small;         /* Honor value of pivot table 'small'? */
+            double x;                 /* The numeric value. */
             char *var_name;           /* May be NULL. */
             char *value_label;        /* May be NULL. */
-            enum settings_value_show show; /* Show value or label or both? */
           }
         numeric;
 
         /* PIVOT_VALUE_STRING. */
         struct
           {
-            char *s;                  /* The string value. */
+            enum pivot_value_type type;
+            enum settings_value_show show; /* Show value or label or both? */
             bool hex;                 /* Display in hex? */
+            char *s;                  /* The string value. */
             char *var_name;           /* May be NULL. */
             char *value_label;        /* May be NULL. */
-            enum settings_value_show show; /* Show value or label or both? */
           }
         string;
 
         /* PIVOT_VALUE_VARIABLE. */
         struct
           {
+            enum pivot_value_type type;
+            enum settings_value_show show; /* Show name or label or both? */
             char *var_name;
             char *var_label;          /* May be NULL. */
-            enum settings_value_show show; /* Show name or label or both? */
           }
         variable;
 
         /* PIVOT_VALUE_TEXT. */
         struct
           {
+            enum pivot_value_type type;
+
+            /* 'local', 'c', and 'id' must all be nonnull, but they are allowed
+               to be the same pointer. */
+            bool user_provided;
             char *local;              /* Localized. */
             char *c;                  /* English. */
             char *id;                 /* Identifier. */
-            bool user_provided;
           }
         text;
 
         /* PIVOT_VALUE_TEMPLATE. */
         struct
           {
+            enum pivot_value_type type;
+
+            /* Arguments.
+
+               The odd ordering in this struct reduces the overall size
+               of struct pivot_value. */
+            unsigned int n_args;
+            struct pivot_argument *args;
+
+            /* Both 'local' and 'id' must be nonnull, but they are allowed to
+               be the same pointer. */
             char *local;              /* Localized. */
             char *id;                 /* Identifier. */
-            struct pivot_argument *args;
-            size_t n_args;
           }
         template;
       };
   };
 
+/* Life cycle. */
+struct pivot_value *pivot_value_clone (const struct pivot_value *);
+void pivot_value_destroy (struct pivot_value *);
+
 /* Numbers resulting from calculations. */
 struct pivot_value *pivot_value_new_number (double);
 struct pivot_value *pivot_value_new_integer (double);
@@ -707,6 +795,8 @@ struct pivot_value *pivot_value_new_value (const union value *, int width,
 
 /* Values from variable names. */
 struct pivot_value *pivot_value_new_variable (const struct variable *);
+struct pivot_value *pivot_value_new_variable__ (const char *name,
+                                                const char *label);
 
 /* Values from text strings. */
 struct pivot_value *pivot_value_new_text (const char *);
@@ -722,6 +812,7 @@ struct pivot_value *pivot_value_new_user_text_nocopy (char *);
 
 /* Footnotes. */
 void pivot_value_add_footnote (struct pivot_value *, const struct pivot_footnote *);
+void pivot_value_sort_footnotes (struct pivot_value *);
 
 /* Numeric formats. */
 void pivot_value_set_rc (const struct pivot_table *, struct pivot_value *,
@@ -729,19 +820,13 @@ void pivot_value_set_rc (const struct pivot_table *, struct pivot_value *,
 
 /* Converting a pivot_value to a string for display. */
 char *pivot_value_to_string (const struct pivot_value *,
-                             enum settings_value_show show_values,
-                             enum settings_value_show show_variables);
-void pivot_value_format (const struct pivot_value *,
-                         enum settings_value_show show_values,
-                         enum settings_value_show show_variables,
-                         struct string *);
+                             const struct pivot_table *);
+bool pivot_value_format (const struct pivot_value *,
+                         const struct pivot_table *, struct string *);
 bool pivot_value_format_body (const struct pivot_value *,
-                              enum settings_value_show show_values,
-                              enum settings_value_show show_variables,
+                              const struct pivot_table *,
                               struct string *);
 
-void pivot_value_destroy (struct pivot_value *);
-
 /* Styling. */
 void pivot_value_get_style (struct pivot_value *,
                             const struct font_style *base_font_style,
@@ -749,6 +834,10 @@ void pivot_value_get_style (struct pivot_value *,
                             struct table_area_style *);
 void pivot_value_set_style (struct pivot_value *,
                             const struct table_area_style *);
+void pivot_value_set_font_style (struct pivot_value *,
+                                 const struct font_style *);
+void pivot_value_set_cell_style (struct pivot_value *,
+                                 const struct cell_style *);
 
 /* Template arguments. */
 struct pivot_argument
@@ -758,6 +847,35 @@ struct pivot_argument
   };
 
 void pivot_argument_uninit (struct pivot_argument *);
+void pivot_argument_copy (struct pivot_argument *,
+                          const struct pivot_argument *);
+\f
+/* Extra styling for a pivot_value.
+
+   This is logically part of pivot_value itself.  It is broken into a separate
+   structure to save memory because it is rarely used. */
+struct pivot_value_ex
+  {
+    struct font_style *font_style;
+    struct cell_style *cell_style;
+
+    char **subscripts;
+    size_t n_subscripts;
+
+    size_t *footnote_indexes;
+    size_t n_footnotes;
+  };
+
+static inline const struct pivot_value_ex *
+pivot_value_ex (const struct pivot_value *value)
+{
+  static const struct pivot_value_ex empty_ex = { .font_style = NULL };
+  return value->ex ? value->ex : &empty_ex;
+}
+
+struct pivot_value_ex *pivot_value_ex_rw (struct pivot_value *);
+struct pivot_value_ex *pivot_value_ex_clone (const struct pivot_value_ex *);
+void pivot_value_ex_destroy (struct pivot_value_ex *);
 \f
 /* One piece of data within a pivot table. */
 struct pivot_cell