Thanks to John Darrington for review.
* ascii.c (struct ascii_driver_ext): Add chart_type,
chart_file_name, chart_cnt members.
(ascii_open_driver): Initialize new members.
(static array option_tab): Add new options, reorganize slightly.
(handle_option): Handle new options.
(ascii_submit): New function.
(ascii_chart_initialise): Implement.
(ascii_chart_finalise): Implement.
* chart.c (chart_init_separate): New function.
(chart_finalise_separate): New function.
* dummy-chart.c (chart_init_separate): New function.
(chart_finalise_separate): New function.
* html.c (html_open_driver): Don't free chart_file_name.
(html_close_driver): Do free chart_file_name.
(handle_option): Only give an error for chart-files options that
don't contain "#".
(html_initialise_chart): Use new chart_init_separate.
(html_finalise_chart): Use new chart_finalise_separate.
(e.g., @code{"pspp.txt"}), a pipe (e.g., @code{"|more"}), or
stdout (@code{"-"}). Default: @code{"pspp.list"}.
+@item chart-files=@var{file-name-template}
+Template for the file names used for charts. The name should contain
+a single @samp{#}, which is replaced by the chart number. Default:
+@file{"pspp-#.png"}.
+
+@item chart-type=@var{type}.
+Type of charts to output. Available types typically include @samp{X},
+@samp{png}, @samp{gif}, @samp{svg}, @samp{ps}, @samp{cgm}, @samp{fig},
+@samp{pcl}, @samp{hpgl}, @samp{regis}, @samp{tek}, and @samp{meta}.
+Default: @samp{png}.
+
+You may specify @samp{none} to disable chart output. Charts are also
+disabled if your installation of PSPP was compiled without
+@code{libplot}.
+
@item paginate=@var{boolean}
If set, a formfeed will be written at the end of every page. Default:
+2007-08-12 Ben Pfaff <blp@gnu.org>
+
+ Add support for charts to ASCII driver. Bug #16364.
+ Thanks to John Darrington for review.
+
+ * ascii.c (struct ascii_driver_ext): Add chart_type,
+ chart_file_name, chart_cnt members.
+ (ascii_open_driver): Initialize new members.
+ (static array option_tab): Add new options, reorganize slightly.
+ (handle_option): Handle new options.
+ (ascii_submit): New function.
+ (ascii_chart_initialise): Implement.
+ (ascii_chart_finalise): Implement.
+
+ * chart.c (chart_init_separate): New function.
+ (chart_finalise_separate): New function.
+
+ * dummy-chart.c (chart_init_separate): New function.
+ (chart_finalise_separate): New function.
+
+ * html.c (html_open_driver): Don't free chart_file_name.
+ (html_close_driver): Do free chart_file_name.
+ (handle_option): Only give an error for chart-files options that
+ don't contain "#".
+ (html_initialise_chart): Use new chart_init_separate.
+ (html_finalise_chart): Use new chart_finalise_separate.
+
2007-07-25 Ben Pfaff <blp@gnu.org>
Allow the user to specify an initialization string to write at the
#include <ctype.h>
#include <errno.h>
#include <limits.h>
+#include <stdint.h>
#include <stdlib.h>
#include <data/file-name.h>
/* ASCII driver options: (defaults listed first)
output-file="pspp.list"
+ chart-files="pspp-#.png" Name used for charts.
+ chart-type=png Format of charts (use "none" to disable).
+
paginate=on|off Formfeeds are desired?
tab-width=8 Width of a tab; 0 to not use tabs.
bool squeeze_blank_lines; /* Squeeze multiple blank lines into one? */
enum emphasis_style emphasis; /* How to emphasize text. */
int tab_width; /* Width of a tab; 0 not to use tabs. */
+ const char *chart_type; /* Type of charts to output; NULL for none. */
+ const char *chart_file_name; /* Name of files used for charts. */
int page_length; /* Page length before subtracting margins. */
int top_margin; /* Top margin in lines. */
int page_number; /* Current page number. */
struct line *lines; /* Page content. */
int line_cap; /* Number of lines allocated. */
+ int chart_cnt; /* Number of charts so far. */
};
static void ascii_flush (struct outp_driver *);
x->squeeze_blank_lines = false;
x->emphasis = EMPH_BOLD;
x->tab_width = 8;
+ x->chart_file_name = pool_strdup (x->pool, "pspp-#.png");
+ x->chart_type = pool_strdup (x->pool, "png");
x->page_length = 66;
x->top_margin = 2;
x->bottom_margin = 2;
x->page_number = 0;
x->lines = NULL;
x->line_cap = 0;
+ x->chart_cnt = 0;
if (!outp_parse_options (options, handle_option, this))
goto error;
emphasis_arg,
nonneg_int_arg,
pos_int_arg,
- output_file_arg,
string_arg
};
{"emphasis", emphasis_arg, 0},
- {"output-file", output_file_arg, 0},
-
{"length", pos_int_arg, 0},
{"width", pos_int_arg, 1},
{"bottom-margin", nonneg_int_arg, 1},
{"tab-width", nonneg_int_arg, 2},
- {"init", string_arg, 0},
+ {"output-file", string_arg, 0},
+ {"chart-files", string_arg, 1},
+ {"chart-type", string_arg, 2},
+ {"init", string_arg, 3},
{NULL, 0, 0},
};
case -1:
error (0, 0, _("ascii: unknown parameter `%s'"), key);
break;
- case output_file_arg:
- x->file_name = pool_strdup (x->pool, value);
- break;
case pos_int_arg:
{
char *tail;
}
break;
case string_arg:
- free (x->init);
- x->init = pool_strdup (x->pool, value);
+ switch (subcat)
+ {
+ case 0:
+ x->file_name = pool_strdup (x->pool, value);
+ break;
+ case 1:
+ if (ds_find_char (val, '#') != SIZE_MAX)
+ x->chart_file_name = pool_strdup (x->pool, value);
+ else
+ error (0, 0, _("`chart-files' value must contain `#'"));
+ break;
+ case 2:
+ if (value[0] != '\0')
+ x->chart_type = pool_strdup (x->pool, value);
+ else
+ x->chart_type = NULL;
+ break;
+ case 3:
+ x->init = pool_strdup (x->pool, value);
+ break;
+ }
break;
default:
NOT_REACHED ();
}
}
+static void
+ascii_submit (struct outp_driver *this UNUSED, struct som_entity *s)
+{
+ extern struct som_table_class tab_table_class;
+
+ assert (s->class == &tab_table_class);
+ assert (s->type == SOM_CHART);
+}
+
static void
text_draw (struct outp_driver *this,
enum outp_font font,
ext->lines[y].chars[x++] = *string++ | attr;
}
-/* Divides the text T->S into lines of width T->H. Sets T->V to the
- number of lines necessary. Actually draws the text if DRAW is
- true. */
+/* Divides the text T->S into lines of width T->H. Sets *WIDTH
+ to the maximum width of a line and *HEIGHT to the number of
+ lines, if those arguments are non-null. Actually draws the
+ text if DRAW is true. */
static void
delineate (struct outp_driver *this, const struct outp_text *text, bool draw,
int *width, int *height)
assert (this->page_open);
delineate (this, t, true, NULL, NULL);
}
-
\f
/* ascii_close_page () and support routines. */
}
static void
-ascii_chart_initialise (struct outp_driver *d UNUSED, struct chart *ch)
+ascii_chart_initialise (struct outp_driver *this, struct chart *ch)
{
- error (0, 0, _("ascii: charts are unsupported by this driver"));
- ch->lp = 0;
+ struct ascii_driver_ext *x = this->ext;
+ struct outp_text t;
+ char *text;
+
+ if (x->chart_type == NULL)
+ return;
+
+ /* Initialize chart. */
+ chart_init_separate (ch, x->chart_type, x->chart_file_name, ++x->chart_cnt);
+ if (ch->file_name == NULL)
+ return;
+
+ /* Mention chart in output.
+ First advance current position. */
+ if (!this->page_open)
+ outp_open_page (this);
+ else
+ {
+ this->cp_y++;
+ if (this->cp_y >= this->length)
+ {
+ outp_close_page (this);
+ outp_open_page (this);
+ }
+ }
+
+ /* Then write the text. */
+ text = xasprintf ("See %s for a chart.", ch->file_name);
+ t.font = OUTP_FIXED;
+ t.justification = OUTP_LEFT;
+ t.string = ss_cstr (text);
+ t.h = this->width;
+ t.v = 1;
+ t.x = 0;
+ t.y = this->cp_y;
+ ascii_text_draw (this, &t);
+ this->cp_y++;
+
+ free (text);
}
static void
-ascii_chart_finalise (struct outp_driver *d UNUSED, struct chart *ch UNUSED)
+ascii_chart_finalise (struct outp_driver *this, struct chart *ch)
{
-
+ struct ascii_driver_ext *x = this->ext;
+ if (x->chart_type != NULL)
+ chart_finalise_separate (ch);
}
const struct outp_class ascii_class =
ascii_close_page,
ascii_flush,
- NULL,
+ ascii_submit,
ascii_line,
ascii_text_metrics,
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
+
+#include <output/chart.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <float.h>
+#include <math.h>
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
-#include <plot.h>
-#include <stdarg.h>
#include <string.h>
-#include <float.h>
-#include <assert.h>
-#include <math.h>
-#include "chart.h"
-#include <libpspp/str.h>
+#include <plot.h>
+
#include <libpspp/alloc.h>
-#include "manager.h"
-#include "output.h"
+#include <libpspp/str.h>
+#include <output/manager.h>
+#include <output/output.h>
+
+#include "error.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
extern struct som_table_class tab_table_class;
free(chart);
}
+void
+chart_init_separate (struct chart *ch, const char *type,
+ const char *file_name_tmpl, int number)
+{
+ FILE *fp;
+ int number_pos;
+
+ number_pos = strchr (file_name_tmpl, '#') - file_name_tmpl;
+ ch->file_name = xasprintf ("%.*s%d%s",
+ number_pos, file_name_tmpl,
+ number,
+ file_name_tmpl + number_pos + 1);
+ fp = fopen (ch->file_name, "wb");
+ if (fp == NULL)
+ {
+ error (0, errno, _("creating \"%s\""), ch->file_name);
+ free (ch->file_name);
+ ch->file_name = NULL;
+ return;
+ }
+
+ ch->pl_params = pl_newplparams ();
+ ch->lp = pl_newpl_r (type, 0, fp, stderr, ch->pl_params);
+}
+
+void
+chart_finalise_separate (struct chart *ch)
+{
+ free (ch->file_name);
+}
struct chart * chart_create(void);
void chart_submit(struct chart *ch);
+/* Helper functions for output drivers that put each chart into a
+ separate file. */
+void chart_init_separate (struct chart *, const char *type,
+ const char *file_name_tmpl, int number);
+void chart_finalise_separate (struct chart *);
+
#endif
{
}
+void
+chart_init_separate (struct chart *ch UNUSED, const char *type UNUSED,
+ const *file_name_tmpl UNUSED, int number UNUSED)
+{
+}
+
+void
+chart_finalise_separate (struct chart *ch)
+{
+}
#include "chart.h"
#include "htmlP.h"
#include <errno.h>
+#include <stdint.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include "table.h"
#include <libpspp/version.h>
-#include "size_max.h"
-
#include "gettext.h"
#define _(msgid) gettext (msgid)
+/* HTML driver options: (defaults listed first)
+
+ output-file="pspp.html"
+ chart-files="pspp-#.png"
+*/
+
static void escape_string (FILE *file,
const char *text, size_t length,
const char *space);
fputs (" LINK=\"#1f00ff\" ALINK=\"#ff0000\" VLINK=\"#9900dd\">\n", x->file);
print_title_tag (x->file, "H1", outp_title);
print_title_tag (x->file, "H2", outp_subtitle);
- free (x->chart_file_name);
return true;
}
else
ok = true;
+ free (x->chart_file_name);
free (x->file_name);
free (x);
free (x->chart_file_name);
x->chart_file_name = ds_xstrdup (val);
}
- error (0, 0, _("`chart-files' value must contain `#'"));
+ else
+ error (0, 0, _("`chart-files' value must contain `#'"));
break;
default:
NOT_REACHED ();
static void
html_initialise_chart (struct outp_driver *this UNUSED, struct chart *ch)
{
-#ifdef NO_CHARTS
- ch->lp = NULL;
-#else
struct html_driver_ext *x = this->ext;
-
- FILE *fp;
- int number_pos;
-
- x->chart_cnt++;
-
- number_pos = strchr (x->chart_file_name, '#') - x->chart_file_name;
- ch->file_name = xasprintf ("%.*s%d%s",
- number_pos, x->chart_file_name,
- (int) x->chart_cnt,
- x->chart_file_name + number_pos + 1);
- fp = fopen (ch->file_name, "wb");
- if (fp == NULL)
- {
- error (0, errno, _("creating \"%s\""), ch->file_name);
- free (ch->file_name);
- ch->file_name = NULL;
- return;
- }
-
- ch->pl_params = pl_newplparams ();
- ch->lp = pl_newpl_r ("png", 0, fp, stderr, ch->pl_params);
-#endif
+ chart_init_separate (ch, "png", x->chart_file_name, ++x->chart_cnt);
}
static void
html_finalise_chart(struct outp_driver *d UNUSED, struct chart *ch)
{
- free(ch->file_name);
+ chart_finalise_separate (ch);
}