X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Foutput%2Fspv%2Fspv-writer.c;h=bb37a05e24b103ab86be47f9e766e2a39e98fe7d;hb=17d00f9ba94128390819277e5d614a03e98aade0;hp=4883ebf5ba36477cff3fa7bcf90a696a93a74d5f;hpb=5164eb1bfa0527dcb32248fb1fc7db55c2bcc94c;p=pspp diff --git a/src/output/spv/spv-writer.c b/src/output/spv/spv-writer.c index 4883ebf5ba..bb37a05e24 100644 --- a/src/output/spv/spv-writer.c +++ b/src/output/spv/spv-writer.c @@ -18,6 +18,7 @@ #include "output/spv/spv-writer.h" +#include #include #include #include @@ -32,9 +33,11 @@ #include "libpspp/temp-file.h" #include "libpspp/version.h" #include "libpspp/zip-writer.h" -#include "output/page-setup-item.h" +#include "output/cairo-chart.h" +#include "output/driver.h" +#include "output/output-item.h" +#include "output/page-setup.h" #include "output/pivot-table.h" -#include "output/text-item.h" #include "gl/xalloc.h" #include "gl/xvasprintf.h" @@ -58,6 +61,8 @@ struct spv_writer bool need_page_break; }; +static void spv_writer_close_heading (struct spv_writer *); + char * WARN_UNUSED_RESULT spv_writer_open (const char *filename, struct spv_writer **writerp) { @@ -93,14 +98,6 @@ spv_writer_close (struct spv_writer *w) return error; } -void -spv_writer_set_page_setup (struct spv_writer *w, - const struct page_setup *page_setup) -{ - page_setup_destroy (w->page_setup); - w->page_setup = page_setup_clone (page_setup); -} - static void write_attr (struct spv_writer *w, const char *name, const char *value) { @@ -197,8 +194,9 @@ spv_writer_open_file (struct spv_writer *w) time_t t = time (NULL); struct tm *tm = gmtime (&t); - char *tm_s = asctime (tm); - write_attr (w, "creation-date-time", tm_s); + char tm_s[128]; + if (strftime (tm_s, sizeof tm_s, "%x %X", tm)) + write_attr (w, "creation-date-time", tm_s); write_attr (w, "creator", version); @@ -224,9 +222,8 @@ spv_writer_open_file (struct spv_writer *w) return true; } -void -spv_writer_open_heading (struct spv_writer *w, const char *command_id, - const char *label) +static void +spv_writer_open_heading (struct spv_writer *w, const struct output_item *item) { if (!w->heading) { @@ -236,12 +233,15 @@ spv_writer_open_heading (struct spv_writer *w, const char *command_id, w->heading_depth++; start_elem (w, "heading"); - write_attr (w, "commandName", command_id); + if (item->command_name) + write_attr (w, "commandName", item->command_name); + if (!item->show) + write_attr (w, "visibility", "collapsed"); /* XXX locale */ /* XXX olang */ start_elem (w, "label"); - write_text (w, label); + write_text (w, output_item_get_label (item)); end_elem (w); } @@ -263,7 +263,7 @@ spv_writer_close_file (struct spv_writer *w, const char *infix) w->heading = NULL; } -void +static void spv_writer_close_heading (struct spv_writer *w) { const char *infix = ""; @@ -279,51 +279,92 @@ spv_writer_close_heading (struct spv_writer *w) } static void -start_container (struct spv_writer *w) +open_container (struct spv_writer *w, const struct output_item *item, + const char *inner_elem) { start_elem (w, "container"); - write_attr (w, "visibility", "visible"); + write_attr (w, "visibility", item->show ? "visible" : "hidden"); if (w->need_page_break) { write_attr (w, "page-break-before", "always"); w->need_page_break = false; } + + start_elem (w, "label"); + write_text (w, output_item_get_label (item)); + end_elem (w); + + start_elem (w, inner_elem); + if (item->command_name) + write_attr (w, "commandName", item->command_name); } -void -spv_writer_put_text (struct spv_writer *w, const struct text_item *text, - const char *command_id) +static void +close_container (struct spv_writer *w) { - if (text->type == TEXT_ITEM_EJECT_PAGE) - w->need_page_break = true; + end_elem (w); + end_elem (w); +} +static void +spv_writer_put_text (struct spv_writer *w, struct output_item *item) +{ bool initial_depth = w->heading_depth; if (!initial_depth) spv_writer_open_file (w); - start_container (w); + open_container (w, item, "vtx:text"); + write_attr (w, "type", + (item->text.subtype == TEXT_ITEM_TITLE ? "title" + : item->text.subtype == TEXT_ITEM_PAGE_TITLE ? "page-title" + : "log")); - start_elem (w, "label"); - write_text (w, (text->type == TEXT_ITEM_TITLE ? "Title" - : text->type == TEXT_ITEM_PAGE_TITLE ? "Page Title" - : "Log")); + start_elem (w, "html"); + char *s = text_item_get_plain_text (item); + write_text (w, s); + free (s); end_elem (w); - start_elem (w, "vtx:text"); - write_attr (w, "type", (text->type == TEXT_ITEM_TITLE ? "title" - : text->type == TEXT_ITEM_PAGE_TITLE ? "page-title" - : "log")); - if (command_id) - write_attr (w, "commandName", command_id); + close_container (w); - start_elem (w, "html"); - write_text (w, text->text); /* XXX */ - end_elem (w); /* html */ - end_elem (w); /* vtx:text */ - end_elem (w); /* container */ + if (!initial_depth) + spv_writer_close_file (w, ""); + + output_item_unref (item); +} + +static cairo_status_t +write_to_zip (void *zw_, const unsigned char *data, unsigned int length) +{ + struct zip_writer *zw = zw_; + + zip_writer_add_write (zw, data, length); + return CAIRO_STATUS_SUCCESS; +} + +static void +spv_writer_put_image (struct spv_writer *w, const struct output_item *item, + cairo_surface_t *image) +{ + bool initial_depth = w->heading_depth; + if (!initial_depth) + spv_writer_open_file (w); + + char *uri = xasprintf ("%010d_Imagegeneric.png", ++w->n_tables); + + open_container (w, item, "object"); + write_attr (w, "type", "unknown"); + write_attr (w, "uri", uri); + close_container (w); if (!initial_depth) spv_writer_close_file (w, ""); + + zip_writer_add_start (w->zw, uri); + cairo_surface_write_to_png_stream (image, write_to_zip, w->zw); + zip_writer_add_finish (w->zw); + + free (uri); } #define H TABLE_HORZ @@ -517,20 +558,25 @@ static void put_value_mod (struct buf *buf, const struct pivot_value *value, const char *template) { - if (value->n_footnotes || value->n_subscripts - || template || value->font_style || value->cell_style) + if ((value->ex + && (value->ex->n_footnotes + || value->ex->n_subscripts + || value->ex->font_style + || value->ex->cell_style)) + || template) { + const struct pivot_value_ex *ex = pivot_value_ex (value); put_byte (buf, 0x31); /* Footnotes. */ - put_u32 (buf, value->n_footnotes); - for (size_t i = 0; i < value->n_footnotes; i++) - put_u16 (buf, value->footnotes[i]->idx); + put_u32 (buf, ex->n_footnotes); + for (size_t i = 0; i < ex->n_footnotes; i++) + put_u16 (buf, ex->footnote_indexes[i]); /* Subscripts. */ - put_u32 (buf, value->n_subscripts); - for (size_t i = 0; i < value->n_subscripts; i++) - put_string (buf, value->subscripts[i]); + put_u32 (buf, ex->n_subscripts); + for (size_t i = 0; i < ex->n_subscripts; i++) + put_string (buf, ex->subscripts[i]); /* Template and style. */ uint32_t v3_start = start_count (buf); @@ -544,7 +590,7 @@ put_value_mod (struct buf *buf, const struct pivot_value *value, put_string (buf, template); } end_count_u32 (buf, template_string_start); - put_style_pair (buf, value->font_style, value->cell_style); + put_style_pair (buf, ex->font_style, ex->cell_style); end_count_u32 (buf, v3_start); } else @@ -552,9 +598,10 @@ put_value_mod (struct buf *buf, const struct pivot_value *value, } static void -put_format (struct buf *buf, const struct fmt_spec *f) +put_format (struct buf *buf, const struct fmt_spec *f, bool honor_small) { - put_u32 (buf, (fmt_to_io (f->type) << 16) | (f->w << 8) | f->d); + int type = f->type == FMT_F && honor_small ? 40 : fmt_to_io (f->type); + put_u32 (buf, (type << 16) | (f->w << 8) | f->d); } static int @@ -582,7 +629,7 @@ put_value (struct buf *buf, const struct pivot_value *value) { put_byte (buf, 2); put_value_mod (buf, value, NULL); - put_format (buf, &value->numeric.format); + put_format (buf, &value->numeric.format, value->numeric.honor_small); put_double (buf, value->numeric.x); put_string (buf, value->numeric.var_name); put_string (buf, value->numeric.value_label); @@ -592,7 +639,7 @@ put_value (struct buf *buf, const struct pivot_value *value) { put_byte (buf, 1); put_value_mod (buf, value, NULL); - put_format (buf, &value->numeric.format); + put_format (buf, &value->numeric.format, value->numeric.honor_small); put_double (buf, value->numeric.x); } break; @@ -600,8 +647,12 @@ put_value (struct buf *buf, const struct pivot_value *value) case PIVOT_VALUE_STRING: put_byte (buf, 4); put_value_mod (buf, value, NULL); - put_format (buf, - &(struct fmt_spec) { FMT_A, strlen (value->string.s), 0 }); + size_t len = strlen (value->string.s); + if (value->string.hex) + put_format (buf, &(struct fmt_spec) { .type = FMT_AHEX, .w = len * 2 }, + false); + else + put_format (buf, &(struct fmt_spec) { .type = FMT_A, .w = len }, false); put_string (buf, value->string.value_label); put_string (buf, value->string.var_name); put_show_values (buf, value->string.show); @@ -684,7 +735,7 @@ put_category (struct buf *buf, const struct pivot_category *c) else { put_bytes (buf, "\0\0\1", 3); - put_u32 (buf, 0); + put_u32 (buf, 0); /* x23 */ put_u32 (buf, -1); put_u32 (buf, c->n_subs); for (size_t i = 0; i < c->n_subs; i++) @@ -695,9 +746,9 @@ put_category (struct buf *buf, const struct pivot_category *c) static void put_y0 (struct buf *buf, const struct pivot_table *table) { - put_u32 (buf, table->epoch); - put_byte (buf, table->decimal); - put_byte (buf, table->grouping); + put_u32 (buf, table->settings.epoch); + put_byte (buf, table->settings.decimal); + put_byte (buf, ','); } static void @@ -705,22 +756,30 @@ put_custom_currency (struct buf *buf, const struct pivot_table *table) { put_u32 (buf, 5); for (int i = 0; i < 5; i++) - put_string (buf, table->ccs[i]); + { + enum fmt_type types[5] = { FMT_CCA, FMT_CCB, FMT_CCC, FMT_CCD, FMT_CCE }; + char *cc = fmt_number_style_to_string (fmt_settings_get_style ( + &table->settings, types[i])); + put_string (buf, cc); + free (cc); + } } static void put_x1 (struct buf *buf, const struct pivot_table *table) { - put_bytes (buf, "\0\1\0", 3); - put_byte (buf, 0); + put_byte (buf, 0); /* x14 */ + put_byte (buf, table->show_title ? 1 : 10); + put_byte (buf, 0); /* x16 */ + put_byte (buf, 0); /* lang */ put_show_values (buf, table->show_variables); put_show_values (buf, table->show_values); - put_u32 (buf, -1); - put_u32 (buf, -1); + put_u32 (buf, -1); /* x18 */ + put_u32 (buf, -1); /* x19 */ for (int i = 0; i < 17; i++) put_byte (buf, 0); - put_bool (buf, false); - put_byte (buf, 1); + put_bool (buf, false); /* x20 */ + put_byte (buf, table->show_caption); } static void @@ -733,9 +792,8 @@ put_x2 (struct buf *buf) } static void -put_x3 (struct buf *buf, const struct pivot_table *table) +put_y1 (struct buf *buf, const struct pivot_table *table) { - put_bytes (buf, "\1\0\4\0\0\0", 6); put_string (buf, table->command_c); put_string (buf, table->command_local); put_string (buf, table->language); @@ -743,6 +801,26 @@ put_x3 (struct buf *buf, const struct pivot_table *table) put_string (buf, table->locale); put_bytes (buf, "\0\0\1\1", 4); put_y0 (buf, table); +} + +static void +put_y2 (struct buf *buf, const struct pivot_table *table) +{ + put_custom_currency (buf, table); + put_byte (buf, '.'); + put_bool (buf, 0); +} + +static void +put_x3 (struct buf *buf, const struct pivot_table *table) +{ + put_byte (buf, 1); + put_byte (buf, 0); + put_byte (buf, 4); /* x21 */ + put_byte (buf, 0); + put_byte (buf, 0); + put_byte (buf, 0); + put_y1 (buf, table); put_double (buf, table->small); put_byte (buf, 1); put_string (buf, table->dataset); @@ -750,11 +828,22 @@ put_x3 (struct buf *buf, const struct pivot_table *table) put_u32 (buf, 0); put_u32 (buf, table->date); put_u32 (buf, 0); + put_y2 (buf, table); +} - /* Y2. */ - put_custom_currency (buf, table); - put_byte (buf, '.'); - put_bool (buf, 0); +static uint32_t +encode_current_layer (const struct pivot_table *table) +{ + uint32_t current_layer = 0; + + const struct pivot_axis *axis = &table->axes[PIVOT_AXIS_LAYER]; + for (size_t i = axis->n_dimensions - 1; i < axis->n_dimensions; i--) + { + const struct pivot_dimension *d = axis->dimensions[i]; + current_layer = current_layer * d->n_leaves + table->current_layer[i]; + } + + return current_layer; } static void @@ -770,10 +859,10 @@ put_light_table (struct buf *buf, uint64_t table_id, put_bool (buf, table->rotate_outer_row_labels); put_bool (buf, true); put_u32 (buf, 0x15); - put_u32 (buf, table->look.width_ranges[H][0]); - put_u32 (buf, table->look.width_ranges[H][1]); - put_u32 (buf, table->look.width_ranges[V][0]); - put_u32 (buf, table->look.width_ranges[V][1]); + put_u32 (buf, table->look->width_ranges[H][0]); + put_u32 (buf, table->look->width_ranges[H][1]); + put_u32 (buf, table->look->width_ranges[V][0]); + put_u32 (buf, table->look->width_ranges[V][1]); put_u64 (buf, table_id); /* Titles. */ @@ -787,15 +876,16 @@ put_light_table (struct buf *buf, uint64_t table_id, put_u32 (buf, table->n_footnotes); for (size_t i = 0; i < table->n_footnotes; i++) { - put_value (buf, table->footnotes[i]->content); - put_optional_value (buf, table->footnotes[i]->marker); - put_u32 (buf, 0); + const struct pivot_footnote *f = table->footnotes[i]; + put_value (buf, f->content); + put_optional_value (buf, f->marker); + put_u32 (buf, f->show ? 1 : -1); } /* Areas. */ for (size_t i = 0; i < PIVOT_N_AREAS; i++) { - const struct table_area_style *a = &table->look.areas[i]; + const struct table_area_style *a = &table->look->areas[i]; put_byte (buf, i + 1); put_byte (buf, 0x31); put_string (buf, (a->font_style.typeface @@ -838,7 +928,7 @@ put_light_table (struct buf *buf, uint64_t table_id, put_be32 (buf, PIVOT_N_BORDERS); for (size_t i = 0; i < PIVOT_N_BORDERS; i++) { - const struct table_border_style *b = &table->look.borders[i]; + const struct table_border_style *b = &table->look->borders[i]; put_be32 (buf, i); put_be32 (buf, (b->stroke == TABLE_STROKE_NONE ? 0 : b->stroke == TABLE_STROKE_SOLID ? 1 @@ -858,25 +948,25 @@ put_light_table (struct buf *buf, uint64_t table_id, /* Print Settings. */ uint32_t ps_start = start_count (buf); put_be32 (buf, 1); - put_bool (buf, table->look.print_all_layers); - put_bool (buf, table->look.paginate_layers); - put_bool (buf, table->look.shrink_to_fit[H]); - put_bool (buf, table->look.shrink_to_fit[V]); - put_bool (buf, table->look.top_continuation); - put_bool (buf, table->look.bottom_continuation); - put_be32 (buf, table->look.n_orphan_lines); - put_bestring (buf, table->look.continuation); + put_bool (buf, table->look->print_all_layers); + put_bool (buf, table->look->paginate_layers); + put_bool (buf, table->look->shrink_to_fit[H]); + put_bool (buf, table->look->shrink_to_fit[V]); + put_bool (buf, table->look->top_continuation); + put_bool (buf, table->look->bottom_continuation); + put_be32 (buf, table->look->n_orphan_lines); + put_bestring (buf, table->look->continuation); end_count_u32 (buf, ps_start); /* Table Settings. */ uint32_t ts_start = start_count (buf); put_be32 (buf, 1); put_be32 (buf, 4); - put_be32 (buf, 0); /* XXX current_layer */ - put_bool (buf, table->look.omit_empty); - put_bool (buf, table->look.row_labels_in_corner); - put_bool (buf, !table->look.show_numeric_markers); - put_bool (buf, table->look.footnote_marker_superscripts); + put_be32 (buf, encode_current_layer (table)); + put_bool (buf, table->look->omit_empty); + put_bool (buf, table->look->row_labels_in_corner); + put_bool (buf, !table->look->show_numeric_markers); + put_bool (buf, table->look->footnote_marker_superscripts); put_byte (buf, 0); uint32_t keep_start = start_count (buf); put_be32 (buf, 0); /* n-row-breaks */ @@ -887,7 +977,7 @@ put_light_table (struct buf *buf, uint64_t table_id, put_be32 (buf, 0); /* n-column-point-keeps */ end_count_be32 (buf, keep_start); put_bestring (buf, table->notes); - put_bestring (buf, table->look.name); + put_bestring (buf, table->look->name); for (size_t i = 0; i < 82; i++) put_byte (buf, 0); end_count_u32 (buf, ts_start); @@ -928,9 +1018,9 @@ put_light_table (struct buf *buf, uint64_t table_id, { const struct pivot_dimension *d = table->dimensions[i]; put_value (buf, d->root->name); - put_byte (buf, 0); + put_byte (buf, 0); /* x1 */ put_byte (buf, x2[i]); - put_u32 (buf, 2); + put_u32 (buf, 2); /* x3 */ put_bool (buf, !d->root->show_label); put_bool (buf, d->hide_all_labels); put_bool (buf, 1); @@ -967,41 +1057,24 @@ put_light_table (struct buf *buf, uint64_t table_id, } } -void -spv_writer_put_table (struct spv_writer *w, const struct pivot_table *table) +static void +spv_writer_put_table (struct spv_writer *w, const struct output_item *item) { - struct pivot_table *table_rw = CONST_CAST (struct pivot_table *, table); - if (!table_rw->subtype) - table_rw->subtype = pivot_value_new_user_text ("unknown", -1); - int table_id = ++w->n_tables; bool initial_depth = w->heading_depth; if (!initial_depth) spv_writer_open_file (w); - start_container (w); - - char *title = pivot_value_to_string (table->title, - SETTINGS_VALUE_SHOW_DEFAULT, - SETTINGS_VALUE_SHOW_DEFAULT); - - char *subtype = pivot_value_to_string (table->subtype, - SETTINGS_VALUE_SHOW_DEFAULT, - SETTINGS_VALUE_SHOW_DEFAULT); - - start_elem (w, "label"); - write_text (w, title); - end_elem (w); + open_container (w, item, "vtb:table"); - start_elem (w, "vtb:table"); - write_attr (w, "commandName", table->command_c); write_attr (w, "type", "table"); /* XXX */ - write_attr (w, "subType", subtype); write_attr_format (w, "tableId", "%d", table_id); - + char *subtype = (item->table->subtype + ? pivot_value_to_string (item->table->subtype, item->table) + : xstrdup ("unknown")); + write_attr (w, "subType", subtype); free (subtype); - free (title); start_elem (w, "vtb:tableStructure"); start_elem (w, "vtb:dataPath"); @@ -1009,16 +1082,71 @@ spv_writer_put_table (struct spv_writer *w, const struct pivot_table *table) write_text (w, data_path); end_elem (w); /* vtb:dataPath */ end_elem (w); /* vtb:tableStructure */ - end_elem (w); /* vtb:table */ - end_elem (w); /* container */ + + close_container (w); if (!initial_depth) spv_writer_close_file (w, ""); struct buf buf = { NULL, 0, 0 }; - put_light_table (&buf, table_id, table); + put_light_table (&buf, table_id, item->table); zip_writer_add_memory (w->zw, data_path, buf.data, buf.len); free (buf.data); free (data_path); } + +void +spv_writer_write (struct spv_writer *w, const struct output_item *item) +{ + switch (item->type) + { + case OUTPUT_ITEM_CHART: + { + cairo_surface_t *surface = xr_draw_image_chart ( + item->chart, + &(struct cell_color) CELL_COLOR_BLACK, + &(struct cell_color) CELL_COLOR_WHITE); + if (cairo_surface_status (surface) == CAIRO_STATUS_SUCCESS) + spv_writer_put_image (w, item, surface); + cairo_surface_destroy (surface); + } + break; + + case OUTPUT_ITEM_GROUP: + spv_writer_open_heading (w, item); + for (size_t i = 0; i < item->group.n_children; i++) + spv_writer_write (w, item->group.children[i]); + spv_writer_close_heading (w); + break; + + case OUTPUT_ITEM_IMAGE: + spv_writer_put_image (w, item, item->image); + break; + + case OUTPUT_ITEM_MESSAGE: + spv_writer_put_text ( + w, message_item_to_text_item (output_item_ref (item))); + break; + + case OUTPUT_ITEM_PAGE_BREAK: + w->need_page_break = true; + break; + + case OUTPUT_ITEM_TABLE: + spv_writer_put_table (w, item); + break; + + case OUTPUT_ITEM_TEXT: + spv_writer_put_text (w, output_item_ref (item)); + break; + } +} + +void +spv_writer_set_page_setup (struct spv_writer *w, + const struct page_setup *ps) +{ + page_setup_destroy (w->page_setup); + w->page_setup = page_setup_clone (ps); +}