X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Foutput%2Fcsv.c;h=e5b47a06ef0b7c0e1c35517d96338062073c0975;hb=726e15b3d4f61ac4f5a7308c4c096d96d41473c8;hp=ef49759566d9b27829a2d8011d271c149e9ef6f9;hpb=f4bd801640ccaf1d41f45e0206e01e71d3e18604;p=pspp diff --git a/src/output/csv.c b/src/output/csv.c index ef49759566..e5b47a06ef 100644 --- a/src/output/csv.c +++ b/src/output/csv.c @@ -30,9 +30,11 @@ #include "output/driver-provider.h" #include "output/options.h" #include "output/message-item.h" +#include "output/page-eject-item.h" #include "output/table-item.h" #include "output/table-provider.h" +#include "gl/minmax.h" #include "gl/xalloc.h" #include "gl/xvasprintf.h" @@ -127,40 +129,29 @@ csv_flush (struct output_driver *driver) } static void -csv_output_field (struct csv_driver *csv, const char *field) +csv_output_field__ (struct csv_driver *csv, struct substring field) { - while (*field == ' ') - field++; + ss_ltrim (&field, ss_cstr (" ")); - if (csv->quote && field[strcspn (field, csv->quote_set)]) + if (csv->quote && ss_cspan (field, ss_cstr (csv->quote_set)) < field.length) { - const char *p; - putc (csv->quote, csv->file); - for (p = field; *p != '\0'; p++) + for (size_t i = 0; i < field.length; i++) { - if (*p == csv->quote) + if (field.string[i] == csv->quote) putc (csv->quote, csv->file); - putc (*p, csv->file); + putc (field.string[i], csv->file); } putc (csv->quote, csv->file); } else - fputs (field, csv->file); + fwrite (field.string, field.length, 1, csv->file); } -static void PRINTF_FORMAT (2, 3) -csv_output_field_format (struct csv_driver *csv, const char *format, ...) +static void +csv_output_field (struct csv_driver *csv, const char *field) { - va_list args; - char *s; - - va_start (args, format); - s = xvasprintf (format, args); - va_end (args); - - csv_output_field (csv, s); - free (s); + csv_output_field__ (csv, ss_cstr (field)); } static void @@ -170,6 +161,42 @@ csv_put_separator (struct csv_driver *csv) putc ('\n', csv->file); } +static void +csv_output_lines (struct csv_driver *csv, const char *text_) +{ + struct substring text = ss_cstr (text_); + struct substring line; + size_t save_idx = 0; + while (ss_separate (text, ss_cstr ("\n"), &save_idx, &line)) + { + csv_output_field__ (csv, line); + putc ('\n', csv->file); + } +} + +static void +csv_format_footnotes (const struct footnote **f, size_t n, struct string *s) +{ + for (size_t i = 0; i < n; i++) + ds_put_format (s, "[%s]", f[i]->marker); +} + +static void +csv_output_table_item_text (struct csv_driver *csv, + const struct table_item_text *text, + const char *leader) +{ + if (!text) + return; + + struct string s = DS_EMPTY_INITIALIZER; + ds_put_format (&s, "%s: %s", leader, text->content); + csv_format_footnotes (text->footnotes, text->n_footnotes, &s); + csv_output_field (csv, ds_cstr (&s)); + ds_destroy (&s); + putc ('\n', csv->file); +} + static void csv_submit (struct output_driver *driver, const struct output_item *output_item) @@ -179,24 +206,18 @@ csv_submit (struct output_driver *driver, if (is_table_item (output_item)) { struct table_item *table_item = to_table_item (output_item); - const char *title = table_item_get_title (table_item); - const char *caption = table_item_get_caption (table_item); const struct table *t = table_item_get_table (table_item); - int footnote_idx; int x, y; csv_put_separator (csv); - if (csv->titles && title != NULL) - { - csv_output_field_format (csv, "Table: %s", title); - putc ('\n', csv->file); - } + if (csv->titles) + csv_output_table_item_text (csv, table_item_get_title (table_item), + "Table"); - footnote_idx = 0; - for (y = 0; y < table_nr (t); y++) + for (y = 0; y < t->n[TABLE_VERT]; y++) { - for (x = 0; x < table_nc (t); x++) + for (x = 0; x < t->n[TABLE_HORZ]; x++) { struct table_cell cell; @@ -207,85 +228,53 @@ csv_submit (struct output_driver *driver, if (x != cell.d[TABLE_HORZ][0] || y != cell.d[TABLE_VERT][0]) csv_output_field (csv, ""); - else if (cell.n_contents == 1 - && cell.contents[0].text != NULL - && cell.contents[0].n_footnotes == 0) - csv_output_field (csv, cell.contents[0].text); + else if (!(cell.options & TAB_MARKUP) && !cell.n_footnotes + && !cell.n_subscripts) + csv_output_field (csv, cell.text); else { - struct string s; - size_t i; + struct string s = DS_EMPTY_INITIALIZER; - ds_init_empty (&s); - for (i = 0; i < cell.n_contents; i++) + if (cell.options & TAB_MARKUP) { - const struct cell_contents *c = &cell.contents[i]; - int j; - - if (i > 0) - ds_put_cstr (&s, "\n\n"); - - ds_put_cstr (&s, c->text); - - for (j = 0; j < c->n_footnotes; j++) - { - char marker[16]; - - str_format_26adic (++footnote_idx, false, - marker, sizeof marker); - ds_put_format (&s, "[%s]", marker); - } + char *t = output_get_text_from_markup (cell.text); + ds_put_cstr (&s, t); + free (t); } + else + ds_put_cstr (&s, cell.text); + + if (cell.n_subscripts) + for (size_t i = 0; i < cell.n_subscripts; i++) + ds_put_format (&s, "%c%s", + i ? ',' : '_', cell.subscripts[i]); + csv_format_footnotes (cell.footnotes, cell.n_footnotes, &s); csv_output_field (csv, ds_cstr (&s)); ds_destroy (&s); } - - table_cell_free (&cell); } putc ('\n', csv->file); } - if (csv->captions && caption != NULL) - { - csv_output_field_format (csv, "Caption: %s", caption); - putc ('\n', csv->file); - } + if (csv->captions) + csv_output_table_item_text (csv, table_item_get_caption (table_item), + "Caption"); - if (footnote_idx) + const struct footnote **f; + size_t n_footnotes = table_collect_footnotes (table_item, &f); + if (n_footnotes) { - size_t i; - fputs ("\nFootnotes:\n", csv->file); - footnote_idx = 0; - for (y = 0; y < table_nr (t); y++) + for (size_t i = 0; i < n_footnotes; i++) { - struct table_cell cell; - for (x = 0; x < table_nc (t); x = cell.d[TABLE_HORZ][1]) - { - table_get_cell (t, x, y, &cell); - - if (x == cell.d[TABLE_HORZ][0] && y == cell.d[TABLE_VERT][0]) - for (i = 0; i < cell.n_contents; i++) - { - const struct cell_contents *c = &cell.contents[i]; - int j; - - for (j = 0; j < c->n_footnotes; j++) - { - char marker[16]; - - str_format_26adic (++footnote_idx, false, - marker, sizeof marker); - csv_output_field (csv, marker); - fputs (csv->separator, csv->file); - csv_output_field (csv, c->footnotes[j]); - putc ('\n', csv->file); - } - } - table_cell_free (&cell); - } + csv_output_field (csv, f[i]->marker); + fputs (csv->separator, csv->file); + csv_output_field (csv, f[i]->content); + putc ('\n', csv->file); } + + free (f); } } else if (is_text_item (output_item)) @@ -294,32 +283,29 @@ csv_submit (struct output_driver *driver, enum text_item_type type = text_item_get_type (text_item); const char *text = text_item_get_text (text_item); - if (type == TEXT_ITEM_COMMAND_OPEN || type == TEXT_ITEM_COMMAND_CLOSE - || type == TEXT_ITEM_SYNTAX) + if (type == TEXT_ITEM_SYNTAX || type == TEXT_ITEM_PAGE_TITLE) return; csv_put_separator (csv); - switch (type) - { - case TEXT_ITEM_TITLE: - csv_output_field_format (csv, "Title: %s", text); - break; - - case TEXT_ITEM_SUBTITLE: - csv_output_field_format (csv, "Subtitle: %s", text); - break; - default: - csv_output_field (csv, text); - break; + if (text_item->markup) + { + char *plain_text = output_get_text_from_markup (text); + csv_output_lines (csv, plain_text); + free (plain_text); } - putc ('\n', csv->file); + else + csv_output_lines (csv, text); + } + else if (is_page_eject_item (output_item)) + { + csv_put_separator (csv); + csv_output_lines (csv, ""); } else if (is_message_item (output_item)) { const struct message_item *message_item = to_message_item (output_item); - const struct msg *msg = message_item_get_msg (message_item); - char *s = msg_to_string (msg, message_item->command_name); + char *s = msg_to_string (message_item_get_msg (message_item)); csv_put_separator (csv); csv_output_field (csv, s); free (s);