Layered split file for FREQUENCIES works.
[pspp] / src / output / pivot-table.h
index 377579a013d356b3f5feb4cea5959381be201ae8..2904fd4f357c1211da1d3b95d5aeb193e3776f6e 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;
@@ -60,15 +62,11 @@ union value;
    Creating a pivot table usually consists of the following steps:
 
    1. Create the table with pivot_table_create(), passing in the title.
-      It's commonly useful to set up a few options at this point:
 
-      - If empty rows or columns should not be displayed, set ->omit_empty to
-        true.
+   2. Optionally, set the format to use for "count" values with
+      pivot_table_set_weight_var() or pivot_table_set_weight_format().
 
-      - Set the format to use for "count" values with
-        pivot_table_set_weight_var() or pivot_table_set_weight_format().
-
-   2. Create each dimension with pivot_dimension_create() and populate it with
+   3. Create each dimension with pivot_dimension_create() and populate it with
       categories and, possibly, with groups that contain the categories.  This
       call also assigns the dimension to an axis.
 
@@ -81,14 +79,14 @@ union value;
       first cell for that variable.  In that case, creating categories and
       inserting data can be interleaved.
 
-   3. Insert data.  For each cell, supply the category indexes, which are
+   4. Insert data.  For each cell, supply the category indexes, which are
       assigned starting from 0 in the order in which the categories were
       created in step 2, and the value to go in the cell.  If the table has a
       small, fixed number of dimensions, functions like, e.g.
       pivot_table_put3() for 3 dimensions, can be used.  The general function
       pivot_table_put() works for other cases.
 
-   4. Output the table for user consumption.  Use pivot_table_submit(). */
+   5. Output the table for user consumption.  Use pivot_table_submit(). */
 \f
 /* Pivot table display styling. */
 
@@ -107,7 +105,6 @@ enum pivot_area
   };
 
 const char *pivot_area_to_string (enum pivot_area);
-const struct area_style *pivot_area_get_default_style (enum pivot_area);
 
 /* Table borders for styling purposes. */
 enum pivot_border
@@ -146,17 +143,12 @@ enum pivot_border
   };
 
 const char *pivot_border_to_string (enum pivot_border);
-void pivot_border_get_default_style (enum pivot_border,
-                                     struct table_border_style *);
 
 /* Sizing for rows or columns of a rendered table.  The comments below talk
    about columns and their widths but they apply equally to rows and their
    heights. */
 struct pivot_table_sizing
   {
-    /* Minimum and maximum column width, in 1/96" units. */
-    int range[2];
-
     /* Specific column widths, in 1/96" units. */
     int *widths;
     size_t n_widths;
@@ -187,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);
@@ -288,7 +279,30 @@ 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
+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 *);
+size_t pivot_splits_get_dindexes (const struct pivot_splits *,
+                                  size_t *dindexes);
+
+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 *);
+
+size_t pivot_splits_count (const struct pivot_splits *);
 \f
 /* A pivot_category is a leaf (a category) or a group:
 
@@ -316,10 +330,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
@@ -371,6 +386,56 @@ 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.
+
+   The division between this and the style information in struct pivot_table
+   seems fairly arbitrary.  The ultimate reason for the division is simply
+   because that's how SPSS documentation and file formats do it. */
+struct pivot_table_look
+  {
+    /* Reference count.  A pivot_table_look may be shared between multiple
+       owners, indicated by a reference count greater than 1.  When this is the
+       case, the pivot_table must not be modified. */
+    int ref_cnt;
+
+    char *name;                 /* May be null. */
+
+    /* General properties. */
+    bool omit_empty;
+    bool row_labels_in_corner;
+    int width_ranges[TABLE_N_AXES][2];      /* In 1/96" units. */
+
+    /* Footnote display settings. */
+    bool show_numeric_markers;
+    bool footnote_marker_superscripts;
+
+    /* Styles. */
+    struct table_area_style areas[PIVOT_N_AREAS];
+    struct table_border_style borders[PIVOT_N_BORDERS];
+
+    /* Print settings. */
+    bool print_all_layers;
+    bool paginate_layers;
+    bool shrink_to_fit[TABLE_N_AXES];
+    bool top_continuation, bottom_continuation;
+    char *continuation;
+    size_t n_orphan_lines;
+  };
+
+const struct pivot_table_look *pivot_table_look_get_default (void);
+void pivot_table_look_set_default (const struct pivot_table_look *);
+
+char *pivot_table_look_read (const char *, struct pivot_table_look **)
+  WARN_UNUSED_RESULT;
+
+const struct pivot_table_look *pivot_table_look_builtin_default (void);
+struct pivot_table_look *pivot_table_look_new_builtin_default (void);
+struct pivot_table_look *pivot_table_look_ref (
+  const struct pivot_table_look *);
+void pivot_table_look_unref (struct pivot_table_look *);
+struct pivot_table_look *pivot_table_look_unshare (struct pivot_table_look *);
 \f
 /* A pivot table.  See the top of this file for more information. */
 struct pivot_table
@@ -380,40 +445,27 @@ struct pivot_table
        the pivot_table must not be modified. */
     int ref_cnt;
 
+    /* Styling. */
+    struct pivot_table_look *look;
+
     /* Display settings. */
     bool rotate_inner_column_labels;
     bool rotate_outer_row_labels;
-    bool row_labels_in_corner;
     bool show_grid_lines;
+    bool show_title;
     bool show_caption;
-    bool omit_empty;       /* Omit empty rows and columns? */
-    size_t *current_layer; /* axis[PIVOT_AXIS_LAYER].n_dimensions elements. */
-    char *table_look;
+    size_t *current_layer; /* axes[PIVOT_AXIS_LAYER].n_dimensions elements. */
     enum settings_value_show show_values;
     enum settings_value_show show_variables;
     struct fmt_spec weight_format;
 
-    /* Footnote display settings. */
-    bool show_numeric_markers;
-    bool footnote_marker_superscripts;
-
     /* Column and row sizing and page breaks.
        sizing[TABLE_HORZ] is for columns, sizing[TABLE_VERT] is for rows. */
     struct pivot_table_sizing sizing[TABLE_N_AXES];
 
-    /* Print settings. */
-    bool print_all_layers;
-    bool paginate_layers;
-    bool shrink_to_fit[TABLE_N_AXES];
-    bool top_continuation, bottom_continuation;
-    char *continuation;
-    size_t n_orphan_lines;
-
     /* 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. */
@@ -436,11 +488,7 @@ struct pivot_table
     struct pivot_value *subtype;  /* Same as spv_item's subtype. */
     struct pivot_value *corner_text;
     struct pivot_value *caption;
-    char *notes;
-
-    /* Styles. */
-    struct area_style areas[PIVOT_N_AREAS];
-    struct table_border_style borders[PIVOT_N_BORDERS];
+    char *notes;                /* Shown as tooltip. */
 
     /* Dimensions. */
     struct pivot_dimension **dimensions;
@@ -460,9 +508,30 @@ 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 *);
+void pivot_table_set_look (struct pivot_table *,
+                           const struct pivot_table_look *);
+
 /* Format of PIVOT_RC_COUNT cells. */
 void pivot_table_set_weight_var (struct pivot_table *,
                                  const struct variable *);
@@ -493,6 +562,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.
@@ -511,6 +582,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. */
@@ -531,7 +608,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. */
@@ -599,73 +676,85 @@ enum pivot_value_type
 */
 struct pivot_value
   {
-    struct font_style *font_style;
-    struct cell_style *cell_style;
-
-    char **subscripts;
-    size_t n_subscripts;
-
-    char *superscript;
-
-    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);
@@ -679,17 +768,24 @@ 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 *);
 struct pivot_value *pivot_value_new_text_format (const char *, ...)
-  PRINTF_FORMAT (1, 2);
+#if defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__>= 4) || __GNUC__ > 4)
+  __attribute__((format(gnu_printf, 1, 2)));
+#else
+  __attribute__((format(__printf__, 1, 2)));
+#endif
 
 struct pivot_value *pivot_value_new_user_text (const char *, size_t length);
 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 *,
@@ -697,25 +793,25 @@ 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 *);
+char *pivot_value_to_string_defaults (const struct pivot_value *);
+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,
                             const struct cell_style *base_cell_style,
-                            struct area_style *);
-void pivot_value_set_style (struct pivot_value *, const struct area_style *);
+                            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
@@ -725,6 +821,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