From: Ben Pfaff Date: Sun, 7 Sep 2014 18:22:35 +0000 (-0700) Subject: render: Render table_items instead of tables. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pspp;a=commitdiff_plain;h=bf3af6fb69dc94a6b3010e11e5d359e9e4abd5ba render: Render table_items instead of tables. A table_item includes the caption, which future commits will want to have render_pager render, so the table_item is a more natural target. --- diff --git a/src/output/ascii.c b/src/output/ascii.c index 3548844693..a2915ee8f7 100644 --- a/src/output/ascii.c +++ b/src/output/ascii.c @@ -461,8 +461,7 @@ ascii_output_table_item (struct ascii_driver *a, if (a->file == NULL && !ascii_open_page (a)) return; - p = render_pager_create (render_page_create (¶ms, table_item_get_table ( - table_item))); + p = render_pager_create (¶ms, table_item); while (render_pager_has_next (p)) { int used; @@ -942,7 +941,6 @@ ascii_layout_subtable (struct ascii_driver *a, int bb[TABLE_N_AXES][2], int clip[TABLE_N_AXES][2] UNUSED, int *widthp) { - const struct table *table = contents->table; struct render_params params; struct render_pager *p; int r[TABLE_N_AXES][2]; @@ -966,7 +964,7 @@ ascii_layout_subtable (struct ascii_driver *a, params.line_widths[V][i] = width; } - p = render_pager_create (render_page_create (¶ms, table)); + p = render_pager_create (¶ms, contents->table); width = render_pager_get_size (p, TABLE_HORZ); height = render_pager_get_size (p, TABLE_VERT); diff --git a/src/output/cairo.c b/src/output/cairo.c index 22e060cf93..3e8c256f81 100644 --- a/src/output/cairo.c +++ b/src/output/cairo.c @@ -565,8 +565,7 @@ xr_render_table_item (struct xr_driver *xr, const struct table_item *item, else *caption_heightp = 0; - return render_pager_create (render_page_create (xr->params, - table_item_get_table (item))); + return render_pager_create (xr->params, item); } static void @@ -1045,7 +1044,6 @@ xr_layout_cell_subtable (struct xr_driver *xr, int bb[TABLE_N_AXES][2], int clip[TABLE_N_AXES][2], int *widthp, int *brk) { - const struct table *table = contents->table; int single_width, double_width; struct render_params params; struct render_pager *p; @@ -1074,7 +1072,7 @@ xr_layout_cell_subtable (struct xr_driver *xr, } xr->nest++; - p = render_pager_create (render_page_create (¶ms, table)); + p = render_pager_create (¶ms, contents->table); width = render_pager_get_size (p, H); height = render_pager_get_size (p, V); if (bb[V][0] + height >= bb[V][1]) diff --git a/src/output/csv.c b/src/output/csv.c index 9be53c8b0f..bd61c51a62 100644 --- a/src/output/csv.c +++ b/src/output/csv.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2009, 2010, 2012, 2013 Free Software Foundation, Inc. + Copyright (C) 2009, 2010, 2012, 2013, 2014 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 @@ -147,6 +147,20 @@ csv_output_field (struct csv_driver *csv, const char *field) fputs (field, csv->file); } +static void PRINTF_FORMAT (2, 3) +csv_output_field_format (struct csv_driver *csv, const char *format, ...) +{ + va_list args; + char *s; + + va_start (args, format); + s = xvasprintf (format, args); + va_end (args); + + csv_output_field (csv, s); + free (s); +} + static void csv_put_field (struct csv_driver *csv, struct string *s, const char *field) { @@ -172,10 +186,18 @@ csv_put_field (struct csv_driver *csv, struct string *s, const char *field) static void csv_output_subtable (struct csv_driver *csv, struct string *s, - const struct table *t) + const struct table_item *item) { + const struct table *t = table_item_get_table (item); + const char *caption = table_item_get_caption (item); int y, x; + if (csv->captions && caption != NULL) + { + csv_output_field_format (csv, "Table: %s", caption); + putc ('\n', csv->file); + } + for (y = 0; y < table_nr (t); y++) { if (y > 0) @@ -219,24 +241,6 @@ csv_output_subtable (struct csv_driver *csv, struct string *s, } } -static void -csv_output_field_format (struct csv_driver *csv, const char *format, ...) - PRINTF_FORMAT (2, 3); - -static void -csv_output_field_format (struct csv_driver *csv, const char *format, ...) -{ - va_list args; - char *s; - - va_start (args, format); - s = xvasprintf (format, args); - va_end (args); - - csv_output_field (csv, s); - free (s); -} - static void csv_put_separator (struct csv_driver *csv) { diff --git a/src/output/html.c b/src/output/html.c index 3e85b3d968..82478d189b 100644 --- a/src/output/html.c +++ b/src/output/html.c @@ -64,8 +64,7 @@ struct html_driver static const struct output_driver_class html_driver_class; -static void html_output_table (struct html_driver *, const struct table *, - const char *caption); +static void html_output_table (struct html_driver *, const struct table_item *); static void escape_string (FILE *file, const char *text, size_t length, const char *space, const char *newline); @@ -236,8 +235,7 @@ html_submit (struct output_driver *driver, if (is_table_item (output_item)) { struct table_item *table_item = to_table_item (output_item); - html_output_table (html, table_item_get_table (table_item), - table_item_get_caption (table_item)); + html_output_table (html, table_item); } #ifdef HAVE_CAIRO else if (is_chart_item (output_item) && html->chart_file_name != NULL) @@ -376,9 +374,10 @@ put_border (FILE *file, int n_borders, int style, const char *border_name) } static void -html_output_table (struct html_driver *html, - const struct table *t, const char *caption) +html_output_table (struct html_driver *html, const struct table_item *item) { + const struct table *t = table_item_get_table (item); + const char *caption = table_item_get_caption (item); int x, y; fputs ("\n", html->file); @@ -486,7 +485,7 @@ html_output_table (struct html_driver *html, fputs ("", html->file); } else - html_output_table (html, c->table, NULL); + html_output_table (html, c->table); } /* Output or . */ diff --git a/src/output/odt.c b/src/output/odt.c index 1b637f20b7..0d4625c8d4 100644 --- a/src/output/odt.c +++ b/src/output/odt.c @@ -75,8 +75,6 @@ struct odt_driver static const struct output_driver_class odt_driver_class; -static void write_table (struct odt_driver *, const struct table *); - static struct odt_driver * odt_driver_cast (struct output_driver *driver) { @@ -413,9 +411,11 @@ write_xml_with_line_breaks (xmlTextWriterPtr writer, char *line) } static void -odt_submit_table (struct odt_driver *odt, struct table_item *item) +write_table (struct odt_driver *odt, const struct table_item *item) { + const struct table *tab = table_item_get_table (item); const char *caption = table_item_get_caption (item); + int r, c; /* Write a heading for the table */ if (caption != NULL) @@ -428,14 +428,6 @@ odt_submit_table (struct odt_driver *odt, struct table_item *item) xmlTextWriterEndElement (odt->content_wtr); } - write_table (odt, table_item_get_table (item)); -} - -static void -write_table (struct odt_driver *odt, const struct table *tab) -{ - int r, c; - /* Start table */ xmlTextWriterStartElement (odt->content_wtr, _xml("table:table")); xmlTextWriterWriteFormatAttribute (odt->content_wtr, _xml("table:name"), @@ -553,7 +545,7 @@ odt_submit (struct output_driver *driver, output_driver_track_current_command (output_item, &odt->command_name); if (is_table_item (output_item)) - odt_submit_table (odt, to_table_item (output_item)); + write_table (odt, to_table_item (output_item)); else if (is_text_item (output_item)) { struct text_item *text_item = to_text_item (output_item); diff --git a/src/output/render.c b/src/output/render.c index 35e0a7a94c..5f2a9d024d 100644 --- a/src/output/render.c +++ b/src/output/render.c @@ -25,6 +25,7 @@ #include "libpspp/hash-functions.h" #include "libpspp/hmap.h" #include "output/render.h" +#include "output/table-item.h" #include "output/table.h" #include "gl/minmax.h" @@ -38,7 +39,11 @@ May represent the layout of an entire table presented to render_page_create(), or a rectangular subregion of a table broken out using - render_break_next() to allow a table to be broken across multiple pages. */ + render_break_next() to allow a table to be broken across multiple pages. + + A page's size is not limited to the size passed in as part of render_params. + render_pager breaks a render_page into smaller render_pages that will fit in + the available space. */ struct render_page { const struct render_params *params; /* Parameters of the target device. */ @@ -120,6 +125,11 @@ struct render_page int *join_crossing[TABLE_N_AXES]; }; +static struct render_page *render_page_create (const struct render_params *, + const struct table *); + +static void render_page_unref (struct render_page *); + /* Returns the offset in struct render_page's cp[axis] array of the rule with index RULE_IDX. That is, if RULE_IDX is 0, then the offset is that of the leftmost or topmost rule; if RULE_IDX is 1, then the offset is that of the @@ -607,7 +617,7 @@ set_join_crossings (struct render_page *page, enum table_axis axis, The new render_page will be suitable for rendering on a device whose page size is PARAMS->size, but the caller is responsible for actually breaking it up to fit on such a device, using the render_break abstraction. */ -struct render_page * +static struct render_page * render_page_create (const struct render_params *params, const struct table *table_) { @@ -783,18 +793,9 @@ render_page_create (const struct render_params *params, return page; } -/* Increases PAGE's reference count. */ -struct render_page * -render_page_ref (const struct render_page *page_) -{ - struct render_page *page = CONST_CAST (struct render_page *, page_); - page->ref_cnt++; - return page; -} - /* Decreases PAGE's reference count and destroys PAGE if this causes the reference count to fall to zero. */ -void +static void render_page_unref (struct render_page *page) { if (page != NULL && --page->ref_cnt == 0) @@ -1309,12 +1310,13 @@ struct render_pager /* Creates and returns a new render_pager for breaking PAGE into smaller chunks. Takes ownership of PAGE. */ struct render_pager * -render_pager_create (struct render_page *page) +render_pager_create (const struct render_params *params, + const struct table_item *table_item) { struct render_pager *p = xmalloc (sizeof *p); - p->width = page->params->size[H]; - p->page = render_page_ref (page); - render_break_init (&p->x_break, page, H); + p->width = params->size[H]; + p->page = render_page_create (params, table_item_get_table (table_item)); + render_break_init (&p->x_break, p->page, H); render_break_init_empty (&p->y_break); return p; } diff --git a/src/output/render.h b/src/output/render.h index 927009e9cb..dd4b822779 100644 --- a/src/output/render.h +++ b/src/output/render.h @@ -21,7 +21,7 @@ #include #include "output/table-provider.h" -struct table; +struct table_item; enum render_line_style { @@ -98,20 +98,10 @@ struct render_params int min_break[TABLE_N_AXES]; }; -/* A "page" of content that is ready to be rendered. - - A page's size is not limited to the size passed in as part of render_params. - Use render_pager (see below) to break a render_page into smaller - render_pages that will fit in the available space. */ -struct render_page *render_page_create (const struct render_params *, - const struct table *); - -struct render_page *render_page_ref (const struct render_page *); -void render_page_unref (struct render_page *); /* An iterator for breaking render_pages into smaller chunks. */ - -struct render_pager *render_pager_create (struct render_page *); +struct render_pager *render_pager_create (const struct render_params *, + const struct table_item *); void render_pager_destroy (struct render_pager *); bool render_pager_has_next (const struct render_pager *); diff --git a/src/output/tab.c b/src/output/tab.c index 2e788e5a37..bb6b82a2da 100644 --- a/src/output/tab.c +++ b/src/output/tab.c @@ -56,7 +56,7 @@ struct tab_joined_cell union { char *text; - struct table *subtable; + struct table_item *subtable; } u; }; @@ -600,14 +600,14 @@ tab_joint_text_format (struct tab_table *table, int x1, int y1, int x2, int y2, static void subtable_unref (void *subtable) { - table_unref (subtable); + table_item_unref (subtable); } /* Places SUBTABLE as the content for cells (X1,X2)-(Y1,Y2) inclusive in TABLE with options OPT. */ void tab_subtable (struct tab_table *table, int x1, int y1, int x2, int y2, - unsigned opt, struct table *subtable) + unsigned opt, struct table_item *subtable) { add_joined_cell (table, x1, y1, x2, y2, opt | TAB_SUBTABLE)->u.subtable = subtable; @@ -622,10 +622,11 @@ tab_subtable (struct tab_table *table, int x1, int y1, int x2, int y2, as a nested table but its contents become part of TABLE. */ void tab_subtable_bare (struct tab_table *table, int x1, int y1, int x2, int y2, - unsigned opt, struct table *subtable) + unsigned opt, struct table_item *subtable) { - assert (table_nc (subtable) == 1); - assert (table_nr (subtable) == 1); + const struct table *t UNUSED = table_item_get_table (subtable); + assert (table_nc (t) == 1); + assert (table_nr (t) == 1); tab_subtable (table, x1, y1, x2, y2, opt | TAB_BARE, subtable); } @@ -761,7 +762,7 @@ tab_get_cell (const struct table *table, int x, int y, struct table_cell *cell) assert (opt & TAB_SUBTABLE); /* This overwrites all of the members of CELL. */ - table_get_cell (jc->u.subtable, 0, 0, cell); + table_get_cell (table_item_get_table (jc->u.subtable), 0, 0, cell); } else { diff --git a/src/output/tab.h b/src/output/tab.h index f0cffc17fd..a973b0414b 100644 --- a/src/output/tab.h +++ b/src/output/tab.h @@ -144,9 +144,9 @@ void tab_joint_text_format (struct tab_table *, int x1, int y1, int x2, int y2, PRINTF_FORMAT (7, 8); void tab_subtable (struct tab_table *, int x1, int y1, int x2, int y2, - unsigned opt, struct table *subtable); + unsigned opt, struct table_item *subtable); void tab_subtable_bare (struct tab_table *, int x1, int y1, int x2, int y2, - unsigned opt, struct table *subtable); + unsigned opt, struct table_item *subtable); bool tab_cell_is_empty (const struct tab_table *, int c, int r); diff --git a/src/output/table-provider.h b/src/output/table-provider.h index 97c264b4f2..35a4b6cebb 100644 --- a/src/output/table-provider.h +++ b/src/output/table-provider.h @@ -26,7 +26,7 @@ struct cell_contents /* Exactly one of these must be nonnull. */ char *text; /* A paragraph of text. */ - struct table *table; /* A table nested within the cell. */ + struct table_item *table; /* A table nested within the cell. */ }; /* A cell in a table. */ diff --git a/src/output/table.c b/src/output/table.c index 2a08e14b55..5dc5651fd9 100644 --- a/src/output/table.c +++ b/src/output/table.c @@ -24,6 +24,7 @@ #include "libpspp/cast.h" #include "libpspp/compiler.h" +#include "output/table-item.h" #include "gl/xalloc.h" @@ -344,19 +345,28 @@ static const struct table_class table_string_class = struct table_nested { struct table table; - struct table *inner; + struct table_item *inner; }; static const struct table_class table_nested_class; -/* Creates and returns a table with a single cell that contains INNER. */ +/* Creates and returns a table with a single cell that contains INNER. + Takes ownership of INNER. */ struct table * -table_create_nested (const struct table *inner) +table_create_nested (struct table *inner) +{ + return table_create_nested_item (table_item_create (inner, NULL)); +} + +/* Creates and returns a table with a single cell that contains INNER. + Takes ownership of INNER. */ +struct table * +table_create_nested_item (struct table_item *inner) { struct table_nested *tn = xmalloc (sizeof *tn); table_init (&tn->table, &table_nested_class); tn->table.n[TABLE_HORZ] = tn->table.n[TABLE_VERT] = 1; - tn->inner = table_ref (inner); + tn->inner = table_item_ref (inner); return &tn->table; } @@ -371,7 +381,7 @@ static void table_nested_destroy (struct table *tn_) { struct table_nested *tn = table_nested_cast (tn_); - table_unref (tn->inner); + table_item_unref (tn->inner); free (tn); } diff --git a/src/output/table.h b/src/output/table.h index cf187f10dc..919777db53 100644 --- a/src/output/table.h +++ b/src/output/table.h @@ -40,6 +40,7 @@ struct casereader; struct fmt_spec; +struct table_item; struct variable; /* Properties of a table cell. */ @@ -170,7 +171,8 @@ struct table *table_from_casereader (const struct casereader *, size_t column, const char *heading, const struct fmt_spec *); -struct table *table_create_nested (const struct table *); +struct table *table_create_nested (struct table *); +struct table *table_create_nested_item (struct table_item *); /* Combining tables. */ struct table *table_paste (struct table *, struct table *, diff --git a/tests/output/render-test.c b/tests/output/render-test.c index a8c912835f..38940baa0c 100644 --- a/tests/output/render-test.c +++ b/tests/output/render-test.c @@ -458,7 +458,8 @@ read_table (FILE *stream, struct table **tables, size_t n_tables) default: error (1, 0, "unexpected subtable modifier \"%c\"", *text); } - tab_subtable (tab, c, r, c + cs - 1, r + rs - 1, opt, table); + tab_subtable (tab, c, r, c + cs - 1, r + rs - 1, opt, + table_item_create (table, NULL)); } else tab_joint_text (tab, c, r, c + cs - 1, r + rs - 1, opt, text);