+
+static void
+output_set_title__ (struct output_engine *e, char **dst, const char *src)
+{
+ free (*dst);
+ *dst = xstrdup_if_nonnull (src);
+
+ 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));
+ output_item_submit (text_item_create_nocopy (TEXT_ITEM_PAGE_TITLE,
+ page_title, NULL));
+}
+
+void PRINTF_FORMAT (1, 2)
+output_log (const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ char *s = xvasprintf (format, args);
+ va_end (args);
+
+ output_log_nocopy (s);
+}
+
+void
+output_log_nocopy (char *s)
+{
+ output_submit (text_item_create_nocopy (TEXT_ITEM_LOG, s, NULL));
+}
+
+const char *
+output_get_title (void)
+{
+ return engine_stack_top ()->title;
+}
+
+void
+output_set_title (const char *title)
+{
+ struct output_engine *e = engine_stack_top ();
+
+ output_set_title__ (e, &e->title, title);
+}
+
+const char *
+output_get_subtitle (void)
+{
+ return engine_stack_top ()->subtitle;
+}
+
+void
+output_set_subtitle (const char *subtitle)
+{
+ struct output_engine *e = engine_stack_top ();
+
+ output_set_title__ (e, &e->subtitle, subtitle);
+}
+
+void
+output_set_filename (const char *filename)
+{
+ struct output_engine *e = engine_stack_top ();
+
+ string_map_replace (&e->heading_vars, "Filename", filename);
+}