This better matches SPSS behavior.
#include "libpspp/message.h"
#include "libpspp/start-date.h"
#include "libpspp/version.h"
-#include "output/text-item.h"
+#include "output/driver.h"
#include "gl/xalloc.h"
#include "gettext.h"
#define _(msgid) gettext (msgid)
-static int parse_title (struct lexer *, enum text_item_type);
-static void set_title (const char *title, enum text_item_type);
-
-int
-cmd_title (struct lexer *lexer, struct dataset *ds UNUSED)
-{
- return parse_title (lexer, TEXT_ITEM_TITLE);
-}
-
-int
-cmd_subtitle (struct lexer *lexer, struct dataset *ds UNUSED)
-{
- return parse_title (lexer, TEXT_ITEM_SUBTITLE);
-}
-
static int
-parse_title (struct lexer *lexer, enum text_item_type type)
+parse_title (struct lexer *lexer, void (*set_title) (const char *))
{
if (!lex_force_string (lexer))
return CMD_FAILURE;
- set_title (lex_tokcstr (lexer), type);
+ set_title (lex_tokcstr (lexer));
lex_get (lexer);
return CMD_SUCCESS;
}
-static void
-set_title (const char *title, enum text_item_type type)
+int
+cmd_title (struct lexer *lexer, struct dataset *ds UNUSED)
+{
+ return parse_title (lexer, output_set_title);
+}
+
+int
+cmd_subtitle (struct lexer *lexer, struct dataset *ds UNUSED)
{
- text_item_submit (text_item_create (type, title));
+ return parse_title (lexer, output_set_subtitle);
}
/* Performs the FILE LABEL command. */
switch (type)
{
- case TEXT_ITEM_TITLE:
- case TEXT_ITEM_SUBTITLE:
+ case TEXT_ITEM_PAGE_TITLE:
case TEXT_ITEM_COMMAND_OPEN:
case TEXT_ITEM_COMMAND_CLOSE:
break;
xr_render_text (struct xr_driver *xr, const struct text_item *text_item)
{
enum text_item_type type = text_item_get_type (text_item);
- const char *text = text_item_get_text (text_item);
switch (type)
{
- case TEXT_ITEM_TITLE:
- free (xr->title);
- xr->title = xstrdup (text);
- break;
-
- case TEXT_ITEM_SUBTITLE:
- free (xr->subtitle);
- xr->subtitle = xstrdup (text);
+ case TEXT_ITEM_PAGE_TITLE:
break;
case TEXT_ITEM_COMMAND_CLOSE:
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_format_footnotes (const struct footnote **f, size_t n, struct string *s)
{
const char *text = text_item_get_text (text_item);
if (type == TEXT_ITEM_COMMAND_OPEN || type == TEXT_ITEM_COMMAND_CLOSE
- || type == TEXT_ITEM_SYNTAX)
+ || 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;
- }
+ csv_output_field (csv, text);
putc ('\n', csv->file);
}
else if (is_message_item (output_item))
struct llx_list drivers; /* Contains "struct output_driver"s. */
struct string deferred_syntax; /* TEXT_ITEM_SYNTAX being accumulated. */
char *command_name; /* Name of command being processed. */
+ char *title, *subtitle; /* Components of page title. */
};
static const struct output_driver_factory *factories[];
llx_init (&e->drivers);
ds_init_empty (&e->deferred_syntax);
e->command_name = NULL;
+ e->title = NULL;
+ e->subtitle = NULL;
}
void
}
ds_destroy (&e->deferred_syntax);
free (e->command_name);
+ free (e->title);
+ free (e->subtitle);
}
void
d->class->flush (d);
}
}
+
+static void
+output_set_title__ (struct output_engine *e, char **dst, const char *src)
+{
+ free (*dst);
+ *dst = src ? xstrdup (src) : NULL;
+
+ char *page_title
+ = (e->title && e->subtitle ? xasprintf ("%s\n%s", e->title, e->subtitle)
+ : e->title ? xstrdup (e->title)
+ : e->subtitle ? xstrdup (e->subtitle)
+ : xzalloc (1));
+ text_item_submit (text_item_create_nocopy (TEXT_ITEM_PAGE_TITLE,
+ page_title));
+}
+
+void
+output_set_title (const char *title)
+{
+ struct output_engine *e = engine_stack_top ();
+
+ output_set_title__ (e, &e->title, title);
+}
+
+void
+output_set_subtitle (const char *subtitle)
+{
+ struct output_engine *e = engine_stack_top ();
+
+ output_set_title__ (e, &e->subtitle, subtitle);
+}
\f
void
output_driver_init (struct output_driver *driver,
void output_submit (struct output_item *);
void output_flush (void);
+void output_set_title (const char *);
+void output_set_subtitle (const char *);
+
void output_driver_parse_option (const char *option,
struct string_map *options);
struct output_driver *output_driver_create (struct string_map *options);
switch (text_item_get_type (text_item))
{
- case TEXT_ITEM_TITLE:
- print_title_tag (html->file, "H1", s);
- break;
-
- case TEXT_ITEM_SUBTITLE:
- print_title_tag (html->file, "H2", s);
+ case TEXT_ITEM_PAGE_TITLE:
break;
case TEXT_ITEM_COMMAND_OPEN:
TEXT_ITEM_COMMAND_CLOSE, /* Command completed. */
/* Headings. */
- TEXT_ITEM_TITLE, /* TITLE command. */
- TEXT_ITEM_SUBTITLE, /* SUBTITLE command. */
+ TEXT_ITEM_PAGE_TITLE, /* TITLE and SUBTITLE commands. */
TEXT_ITEM_SUBHEAD, /* Heading within a command's output.*/
/* Syntax. */
END DATA.
])
AT_CHECK([pspp -O format=csv begin-data.sps], [0], [dnl
-Title: Test BEGIN DATA ... END DATA
-
Table: Reading 1 record from INLINE.
Variable,Record,Columns,Format
a,1,1- 1,F1.0
])
AT_CHECK([pspp -o pspp.csv split-file.sps])
AT_CHECK([cat pspp.csv], [0], [dnl
-Title: Test SPLIT FILE utility
-
Variable,Value,Label
X,1,
AT_CHECK([pspp -O format=csv split-file.sps], [0],[ignore])
-AT_CLEANUP
\ No newline at end of file
+AT_CLEANUP
descript all/stat=all/format=serial.
])
-AT_CHECK([pspp -O format=csv descriptives.sps], [0],
- [Title: Test DESCRIPTIVES procedure
-
+AT_CHECK([pspp -O format=csv descriptives.sps], [0], [dnl
Table: Reading 1 record from INLINE.
Variable,Record,Columns,Format
V0,1,1- 1,F1.0
LIST.
])
AT_CHECK([pspp -O format=csv count.sps], [0], [dnl
-Title: Test COUNT transformation
-
Table: Reading 1 record from INLINE.
Variable,Record,Columns,Format
v1,1,1- 2,A2