Greatly simplify PSPP configuration.
[pspp-builds.git] / src / output / ascii.c
index afd915262478a8c9d9bc921181c469df4b56ecca..b427df5318007df1cb42a04d75ecebfcafa33d65 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2007, 2009 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2007, 2009, 2010 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -93,12 +93,11 @@ struct ascii_driver
     struct output_driver driver;
 
     /* User parameters. */
-    bool append;                /* Append if output-file already exists? */
+    bool append;                /* Append if output file already exists? */
     bool headers;              /* Print headers at top of page? */
     bool paginate;             /* Insert formfeeds? */
     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. */
     char *chart_file_name;      /* Name of files used for charts. */
 
     int width;                  /* Page width. */
@@ -117,7 +116,7 @@ struct ascii_driver
     char *subtitle;
     char *file_name;            /* Output file name. */
     FILE *file;                 /* Output file. */
-    bool reported_error;        /* Reported file open error? */
+    bool error;                 /* Output error? */
     int page_number;           /* Current page number. */
     struct ascii_line *lines;   /* Page content. */
     int allocated_lines;        /* Number of lines allocated. */
@@ -125,6 +124,10 @@ struct ascii_driver
     int y;
   };
 
+static const struct output_driver_class ascii_driver_class;
+
+static void ascii_submit (struct output_driver *, const struct output_item *);
+
 static int vertical_margins (const struct ascii_driver *);
 
 static const char *get_default_box (int right, int bottom, int left, int top);
@@ -132,7 +135,7 @@ static bool update_page_size (struct ascii_driver *, bool issue_error);
 static int parse_page_size (struct driver_option *);
 
 static void ascii_close_page (struct ascii_driver *);
-static void ascii_open_page (struct ascii_driver *);
+static bool ascii_open_page (struct ascii_driver *);
 
 static void ascii_draw_line (void *, int bb[TABLE_N_AXES][2],
                              enum render_line_style styles[TABLE_N_AXES][2]);
@@ -147,7 +150,7 @@ static void ascii_draw_cell (void *, const struct table_cell *,
 static struct ascii_driver *
 ascii_driver_cast (struct output_driver *driver)
 {
-  assert (driver->class == &ascii_class);
+  assert (driver->class == &ascii_driver_class);
   return UP_CAST (driver, struct ascii_driver, driver);
 }
 
@@ -159,7 +162,7 @@ opt (struct output_driver *d, struct string_map *options, const char *key,
 }
 
 static struct output_driver *
-ascii_create (const char *name, enum output_device_type device_type,
+ascii_create (const char *file_name, enum settings_output_devices device_type,
               struct string_map *o)
 {
   struct output_driver *d;
@@ -169,29 +172,21 @@ ascii_create (const char *name, enum output_device_type device_type,
 
   a = xzalloc (sizeof *a);
   d = &a->driver;
-  output_driver_init (&a->driver, &ascii_class, name, device_type);
+  output_driver_init (&a->driver, &ascii_driver_class, file_name, device_type);
   a->append = parse_boolean (opt (d, o, "append", "false"));
-  a->headers = parse_boolean (opt (d, o, "headers", "true"));
-  a->paginate = parse_boolean (opt (d, o, "paginate", "true"));
-  a->squeeze_blank_lines = parse_boolean (opt (d, o, "squeeze", "false"));
-  a->emphasis = parse_enum (opt (d, o, "emphasis", "bold"),
+  a->headers = parse_boolean (opt (d, o, "headers", "false"));
+  a->paginate = parse_boolean (opt (d, o, "paginate", "false"));
+  a->squeeze_blank_lines = parse_boolean (opt (d, o, "squeeze", "true"));
+  a->emphasis = parse_enum (opt (d, o, "emphasis", "none"),
                             "bold", EMPH_BOLD,
                             "underline", EMPH_UNDERLINE,
                             "none", EMPH_NONE,
                             (char *) NULL);
-  a->tab_width = parse_int (opt (d, o, "tab-width", "0"), 8, INT_MAX);
-
-  if (parse_enum (opt (d, o, "chart-type", "png"),
-                  "png", true,
-                  "none", false,
-                  (char *) NULL))
-    a->chart_file_name = parse_chart_file_name (opt (d, o, "chart-files",
-                                                     "pspp-#.png"));
-  else
-    a->chart_file_name = NULL;
 
-  a->top_margin = parse_int (opt (d, o, "top-margin", "2"), 0, INT_MAX);
-  a->bottom_margin = parse_int (opt (d, o, "bottom-margin", "2"), 0, INT_MAX);
+  a->chart_file_name = parse_chart_file_name (opt (d, o, "charts", file_name));
+
+  a->top_margin = parse_int (opt (d, o, "top-margin", "0"), 0, INT_MAX);
+  a->bottom_margin = parse_int (opt (d, o, "bottom-margin", "0"), 0, INT_MAX);
 
   a->width = parse_page_size (opt (d, o, "width", "79"));
   paper_length = parse_page_size (opt (d, o, "length", "66"));
@@ -216,9 +211,9 @@ ascii_create (const char *name, enum output_device_type device_type,
 
   a->title = xstrdup ("");
   a->subtitle = xstrdup ("");
-  a->file_name = parse_string (opt (d, o, "output-file", "pspp.list"));
+  a->file_name = xstrdup (file_name);
   a->file = NULL;
-  a->reported_error = false;
+  a->error = false;
   a->page_number = 0;
   a->lines = NULL;
   a->allocated_lines = 0;
@@ -333,6 +328,8 @@ ascii_destroy (struct output_driver *driver)
   if (a->y > 0)
     ascii_close_page (a);
 
+  if (a->file != NULL)
+    fn_close (a->file_name, a->file);
   free (a->title);
   free (a->subtitle);
   free (a->file_name);
@@ -340,8 +337,6 @@ ascii_destroy (struct output_driver *driver)
   for (i = 0; i < LNS_COUNT; i++)
     free (a->box[i]);
   free (a->init);
-  if (a->file != NULL)
-    fclose (a->file);
   for (i = 0; i < a->allocated_lines; i++)
     free (a->lines[i].chars);
   free (a->lines);
@@ -376,6 +371,8 @@ ascii_submit (struct output_driver *driver,
               const struct output_item *output_item)
 {
   struct ascii_driver *a = ascii_driver_cast (driver);
+  if (a->error)
+    return;
   if (is_table_item (output_item))
     {
       struct table_item *table_item = to_table_item (output_item);
@@ -414,8 +411,8 @@ ascii_submit (struct output_driver *driver,
           params.line_widths[V][i] = width;
         }
 
-      if (a->file == NULL)
-        ascii_open_page (a);
+      if (a->file == NULL && !ascii_open_page (a))
+        return;
 
       page = render_page_create (&params, table_item_get_table (table_item));
       for (render_break_init (&x_break, page, H);
@@ -439,7 +436,8 @@ ascii_submit (struct output_driver *driver,
                 {
                   assert (a->y > 0);
                   ascii_close_page (a);
-                  ascii_open_page (a);
+                  if (!ascii_open_page (a))
+                    return;
                   continue;
                 }
 
@@ -520,7 +518,8 @@ ascii_submit (struct output_driver *driver,
           {
             struct table_item *item;
 
-            item = table_item_create (table_from_string (0, text), NULL);
+            item = table_item_create (table_from_string (TAB_LEFT, text),
+                                      NULL);
             ascii_submit (&a->driver, &item->output_item);
             table_item_unref (item);
           }
@@ -529,10 +528,14 @@ ascii_submit (struct output_driver *driver,
     }
 }
 
-const struct output_driver_class ascii_class =
+const struct output_driver_factory txt_driver_factory =
+  { "txt", ascii_create };
+const struct output_driver_factory list_driver_factory =
+  { "list", ascii_create };
+
+static const struct output_driver_class ascii_driver_class =
   {
-    "ascii",
-    ascii_create,
+    "text",
     ascii_destroy,
     ascii_submit,
     ascii_flush,
@@ -756,11 +759,14 @@ ascii_layout_cell (struct ascii_driver *a, const struct table_cell *cell,
 \f
 /* ascii_close_page () and support routines. */
 
-static void
+static bool
 ascii_open_page (struct ascii_driver *a)
 {
   int i;
 
+  if (a->error)
+    return false;
+
   if (a->file == NULL)
     {
       a->file = fn_open (a->file_name, a->append ? "a" : "w");
@@ -771,16 +777,10 @@ ascii_open_page (struct ascii_driver *a)
         }
       else
         {
-          /* Report the error to the user and complete
-             initialization.  If we do not finish initialization,
-             then calls to other driver functions will segfault
-             later.  It would be better to simply drop the driver
-             entirely, but we do not have a convenient mechanism
-             for this (yet). */
-          if (!a->reported_error)
-            error (0, errno, _("ascii: opening output file \"%s\""),
-                   a->file_name);
-          a->reported_error = true;
+          error (0, errno, _("ascii: opening output file \"%s\""),
+                 a->file_name);
+          a->error = true;
+          return false;
         }
     }
 
@@ -800,6 +800,8 @@ ascii_open_page (struct ascii_driver *a)
 
   for (i = 0; i < a->length; i++)
     a->lines[i].n_chars = 0;
+
+  return true;
 }
 
 /* Writes LINE to A's output file.  */
@@ -868,6 +870,7 @@ ascii_close_page (struct ascii_driver *a)
   bool any_blank;
   int i, y;
 
+  a->y = 0;
   if (a->file == NULL)
     return;
 
@@ -918,6 +921,4 @@ ascii_close_page (struct ascii_driver *a)
     putc ('\n', a->file);
   if (a->paginate)
     putc ('\f', a->file);
-
-  a->y = 0;
 }