void
pivot_output (const struct pivot_table *pt,
const size_t *layer_indexes,
+ bool printing UNUSED,
struct table **titlep,
struct table **layersp,
struct table **bodyp,
body->styles[i] = table_area_style_override (
body->container, &pt->look->areas[i], NULL, NULL, false);
+ struct table_border_style borders[PIVOT_N_BORDERS];
+ memcpy (borders, pt->look->borders, sizeof borders);
+ if (!printing && pt->show_grid_lines)
+ for (int b = 0; b < PIVOT_N_BORDERS; b++)
+ if (borders[b].stroke == TABLE_STROKE_NONE)
+ borders[b].stroke = TABLE_STROKE_DASHED;
+
for (size_t i = 0; i < PIVOT_N_BORDERS; i++)
{
const struct table_border_style *in = &pt->look->borders[i];
compose_headings (body,
&pt->axes[PIVOT_AXIS_COLUMN], H, &pt->axes[PIVOT_AXIS_ROW],
- pt->look->borders,
+ borders,
PIVOT_BORDER_DIM_COL_HORZ,
PIVOT_BORDER_DIM_COL_VERT,
PIVOT_BORDER_CAT_COL_HORZ,
compose_headings (body,
&pt->axes[PIVOT_AXIS_ROW], V, &pt->axes[PIVOT_AXIS_COLUMN],
- pt->look->borders,
+ borders,
PIVOT_BORDER_DIM_ROW_VERT,
PIVOT_BORDER_DIM_ROW_HORZ,
PIVOT_BORDER_CAT_ROW_VERT,
if (body->n[H] && body->n[V])
{
table_hline (
- body, get_table_rule (pt->look->borders, PIVOT_BORDER_INNER_TOP),
+ body, get_table_rule (borders, PIVOT_BORDER_INNER_TOP),
0, body->n[H] - 1, 0);
table_hline (
- body, get_table_rule (pt->look->borders, PIVOT_BORDER_INNER_BOTTOM),
+ body, get_table_rule (borders, PIVOT_BORDER_INNER_BOTTOM),
0, body->n[H] - 1, body->n[V]);
table_vline (
- body, get_table_rule (pt->look->borders, PIVOT_BORDER_INNER_LEFT),
+ body, get_table_rule (borders, PIVOT_BORDER_INNER_LEFT),
0, 0, body->n[V] - 1);
table_vline (
- body, get_table_rule (pt->look->borders, PIVOT_BORDER_INNER_RIGHT),
+ body, get_table_rule (borders, PIVOT_BORDER_INNER_RIGHT),
body->n[H], 0, body->n[V] - 1);
if (stub[V])
table_hline (
- body, get_table_rule (pt->look->borders, PIVOT_BORDER_DATA_TOP),
+ body, get_table_rule (borders, PIVOT_BORDER_DATA_TOP),
0, body->n[H] - 1, stub[V]);
if (stub[H])
table_vline (
- body, get_table_rule (pt->look->borders, PIVOT_BORDER_DATA_LEFT),
+ body, get_table_rule (borders, PIVOT_BORDER_DATA_LEFT),
stub[H], 0, body->n[V] - 1);
}
/* Title. */
struct table *title;
- if (pt->title && titlep)
+ if (pt->title && pt->show_title && titlep)
{
title = create_aux_table (pt, 1, 1, PIVOT_AREA_TITLE);
fill_cell (title, 0, 0, 0, 0,
/* Caption. */
struct table *caption;
- if (pt->caption && captionp)
+ if (pt->caption && pt->show_caption && captionp)
{
caption = create_aux_table (pt, 1, 1, PIVOT_AREA_CAPTION);
fill_cell (caption, 0, 0, 0, 0,
#include "libpspp/i18n.h"
#include "libpspp/string-map.h"
#include "output/driver.h"
+#include "output/message-item.h"
+#include "output/options.h"
#include "output/pivot-table.h"
#include "output/table-item.h"
static const char *parse_options (int argc, char **argv);
static void usage (void) NO_RETURN;
static struct pivot_table *read_table (struct lexer *);
+static void output_msg (const struct msg *, void *);
int
main (int argc, char **argv)
exit (1);
struct lexer *lexer = lex_create ();
+ msg_set_handler (output_msg, lexer);
lex_include (lexer, reader);
lex_get (lexer);
OPT_MIN_BREAK,
OPT_EMPHASIS,
OPT_BOX,
+ OPT_TABLE_LOOK,
OPT_HELP
};
static const struct option options[] =
{"emphasis", no_argument, NULL, OPT_EMPHASIS},
{"box", required_argument, NULL, OPT_BOX},
{"output", required_argument, NULL, 'o'},
+ {"table-look", required_argument, NULL, OPT_TABLE_LOOK},
{"help", no_argument, NULL, OPT_HELP},
{NULL, 0, NULL, 0},
};
output_base = optarg;
break;
+ case OPT_TABLE_LOOK:
+ {
+ struct pivot_table_look *look;
+ char *err = pivot_table_look_read (optarg, &look);
+ if (err)
+ error (1, 0, "%s", err);
+ pivot_table_look_set_default (look);
+ pivot_table_look_unref (look);
+ }
+ break;
+
case OPT_HELP:
usage ();
read_group (lexer, pt, dim->root);
}
+static bool
+parse_bool_setting (struct lexer *lexer, const char *name,
+ const char *true_kw, const char *false_kw,
+ bool *out)
+{
+ if (lex_match_id (lexer, name))
+ {
+ if (!lex_force_match (lexer, T_EQUALS))
+ exit (1);
+
+ if (lex_match_id (lexer, true_kw))
+ *out = true;
+ else if (lex_match_id (lexer, false_kw))
+ *out = false;
+ else
+ {
+ lex_error_expecting (lexer, true_kw, false_kw);
+ exit (1);
+ }
+
+ return true;
+ }
+ else
+ return false;
+}
+
static void
read_look (struct lexer *lexer, struct pivot_table *pt)
{
msg (SE, "%s", error);
exit (1);
}
+ lex_get (lexer);
pivot_table_set_look (pt, look);
pivot_table_look_unref (look);
}
+
+ struct pivot_table_look *look = pivot_table_look_unshare (
+ pivot_table_look_ref (pt->look));
+ for (;;)
+ {
+ if (!parse_bool_setting (lexer, "EMPTY", "HIDE", "SHOW",
+ &look->omit_empty)
+ && !parse_bool_setting (lexer, "ROWLABELS", "CORNER", "NESTED",
+ &look->row_labels_in_corner)
+ && !parse_bool_setting (lexer, "MARKERS", "NUMERIC", "ALPHA",
+ &look->show_numeric_markers)
+ && !parse_bool_setting (lexer, "LEVEL", "SUPER", "SUB",
+ &look->footnote_marker_superscripts)
+ && !parse_bool_setting (lexer, "LAYERS", "CURRENT", "ALL",
+ &look->print_all_layers)
+ && !parse_bool_setting (lexer, "PAGINATELAYERS", "YES", "NO",
+ &look->paginate_layers)
+ && !parse_bool_setting (lexer, "HSHRINK", "YES", "NO",
+ &look->shrink_to_fit[TABLE_HORZ])
+ && !parse_bool_setting (lexer, "VSHRINK", "YES", "NO",
+ &look->shrink_to_fit[TABLE_VERT])
+ && !parse_bool_setting (lexer, "TOPCONTINUATION", "YES", "NO",
+ &look->top_continuation)
+ && !parse_bool_setting (lexer, "BOTTOMCONTINUATION", "YES", "NO",
+ &look->bottom_continuation))
+ break;
+ }
+ pivot_table_set_look (pt, look);
+ pivot_table_look_unref (look);
+}
+
+static enum table_stroke
+read_stroke (struct lexer *lexer)
+{
+ for (int stroke = 0; stroke < TABLE_N_STROKES; stroke++)
+ if (lex_match_id (lexer, table_stroke_to_string (stroke)))
+ return stroke;
+
+ lex_error (lexer, "expecting stroke");
+ exit (1);
+}
+
+static void
+read_border (struct lexer *lexer, struct pivot_table *pt)
+{
+ static const char *const pivot_border_ids[PIVOT_N_BORDERS] = {
+ [PIVOT_BORDER_TITLE] = "title",
+ [PIVOT_BORDER_OUTER_LEFT] = "outer-left",
+ [PIVOT_BORDER_OUTER_TOP] = "outer-top",
+ [PIVOT_BORDER_OUTER_RIGHT] = "outer-right",
+ [PIVOT_BORDER_OUTER_BOTTOM] = "outer-bottom",
+ [PIVOT_BORDER_INNER_LEFT] = "inner-left",
+ [PIVOT_BORDER_INNER_TOP] = "inner-top",
+ [PIVOT_BORDER_INNER_RIGHT] = "inner-right",
+ [PIVOT_BORDER_INNER_BOTTOM] = "inner-bottom",
+ [PIVOT_BORDER_DATA_LEFT] = "data-left",
+ [PIVOT_BORDER_DATA_TOP] = "data-top",
+ [PIVOT_BORDER_DIM_ROW_HORZ] = "dim-row-horz",
+ [PIVOT_BORDER_DIM_ROW_VERT] = "dim-row-vert",
+ [PIVOT_BORDER_DIM_COL_HORZ] = "dim-col-horz",
+ [PIVOT_BORDER_DIM_COL_VERT] = "dim-col-vert",
+ [PIVOT_BORDER_CAT_ROW_HORZ] = "cat-row-horz",
+ [PIVOT_BORDER_CAT_ROW_VERT] = "cat-row-vert",
+ [PIVOT_BORDER_CAT_COL_HORZ] = "cat-col-horz",
+ [PIVOT_BORDER_CAT_COL_VERT] = "cat-col-vert",
+ };
+
+ lex_match (lexer, T_EQUALS);
+
+ struct pivot_table_look *look = pivot_table_look_unshare (
+ pivot_table_look_ref (pt->look));
+ while (lex_token (lexer) == T_STRING)
+ {
+ char *s = xstrdup (lex_tokcstr (lexer));
+ lex_get (lexer);
+ if (!lex_force_match (lexer, T_LPAREN))
+ exit (1);
+
+ struct table_border_style style = TABLE_BORDER_STYLE_INITIALIZER;
+ style.stroke = read_stroke (lexer);
+ if (lex_is_string (lexer))
+ {
+ if (!parse_color__ (lex_tokcstr (lexer), &style.color))
+ {
+ msg (SE, "%s: unknown color", lex_tokcstr (lexer));
+ exit (1);
+ }
+ lex_get (lexer);
+ }
+ if (!lex_force_match (lexer, T_RPAREN))
+ exit (1);
+
+ int n = 0;
+ for (int b = 0; b < PIVOT_N_BORDERS; b++)
+ {
+ if (!strncmp (s, pivot_border_ids[b], strlen (s)))
+ {
+ look->borders[b] = style;
+ n++;
+ }
+ }
+ if (!n)
+ {
+ msg (SE, "%s: no matching borders", s);
+ exit (1);
+ }
+ free (s);
+ }
+ pivot_table_set_look (pt, look);
+ pivot_table_look_unref (look);
}
static struct pivot_table *
struct pivot_table *pt = pivot_table_create__ (NULL, NULL);
while (lex_match (lexer, T_SLASH))
{
+ assert (!pivot_table_is_shared (pt));
+
if (lex_match_id (lexer, "ROW"))
read_dimension (lexer, pt, PIVOT_AXIS_ROW);
else if (lex_match_id (lexer, "COLUMN"))
read_dimension (lexer, pt, PIVOT_AXIS_LAYER);
else if (lex_match_id (lexer, "LOOK"))
read_look (lexer, pt);
+ else if (lex_match_id (lexer, "ROTATE"))
+ {
+ lex_match (lexer, T_EQUALS);
+ while (lex_token (lexer) == T_ID)
+ if (!parse_bool_setting (lexer, "INNERCOLUMNS", "YES", "NO",
+ &pt->rotate_inner_column_labels)
+ && !parse_bool_setting (lexer, "OUTERROWS", "YES", "NO",
+ &pt->rotate_outer_row_labels))
+ break;
+ }
+ else if (lex_match_id (lexer, "DISPLAY"))
+ {
+ lex_match (lexer, T_EQUALS);
+ while (lex_token (lexer) == T_ID)
+ if (!parse_bool_setting (lexer, "GRID", "YES", "NO",
+ &pt->show_grid_lines)
+ && !parse_bool_setting (lexer, "CAPTION", "YES", "NO",
+ &pt->show_caption)
+ && !parse_bool_setting (lexer, "TITLE", "YES", "NO",
+ &pt->show_caption))
+ break;
+ }
+ else if (lex_match_id (lexer, "BORDER"))
+ read_border (lexer, pt);
else
{
msg (SE, "Expecting keyword");
exit (1);
return pt;
}
+
+static void
+output_msg (const struct msg *m_, void *lexer_)
+{
+ struct lexer *lexer = lexer_;
+ struct msg m = *m_;
+
+ if (m.file_name == NULL)
+ {
+ m.file_name = CONST_CAST (char *, lex_get_file_name (lexer));
+ m.first_line = lex_get_first_line_number (lexer, 0);
+ m.last_line = lex_get_last_line_number (lexer, 0);
+ }
+
+ m.command_name = output_get_command_name ();
+
+ message_item_submit (message_item_create (&m));
+
+ free (m.command_name);
+}