Add tty and listing devices that use VT100 (and xterm) line-drawing
[pspp-builds.git] / src / output / ascii.c
index cc173cc414b4cebec10c63f49f5a61bb6c690795..0a26c75ab3fee34aad00628e834bce282452c002 100644 (file)
@@ -1,20 +1,18 @@
-/* PSPP - computes sample statistics.
-   Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 1997-9, 2000, 2007 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 the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
+   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
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
 
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA. */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
 #include <config.h>
 
@@ -55,6 +53,7 @@
    bottom-margin=2
 
    box[x]="strng"               Sets box character X (X in base 4: 0-3333).
+   init="string"                Set initialization string.
  */
 
 /* Disable messages by failed range checks. */
@@ -108,6 +107,7 @@ struct ascii_driver_ext
     int bottom_margin;         /* Bottom margin in lines. */
 
     char *box[LNS_COUNT];       /* Line & box drawing characters. */
+    char *init;                 /* Device initialization string. */
 
     /* Internal state. */
     char *file_name;            /* Output file name. */
@@ -117,6 +117,7 @@ struct ascii_driver_ext
     int line_cap;               /* Number of lines allocated. */
   };
 
+static void ascii_flush (struct outp_driver *);
 static int get_default_box_char (size_t idx);
 static bool handle_option (struct outp_driver *this, const char *key,
                            const struct string *val);
@@ -145,6 +146,7 @@ ascii_open_driver (struct outp_driver *this, struct substring options)
   x->bottom_margin = 2;
   for (i = 0; i < LNS_COUNT; i++)
     x->box[i] = NULL;
+  x->init = NULL;
   x->file_name = pool_strdup (x->pool, "pspp.list");
   x->file = NULL;
   x->page_number = 0;
@@ -154,13 +156,6 @@ ascii_open_driver (struct outp_driver *this, struct substring options)
   if (!outp_parse_options (options, handle_option, this))
     goto error;
 
-  x->file = pool_fopen (x->pool, x->file_name, "w");
-  if (x->file == NULL)
-    {
-      error (0, errno, _("ascii: opening output file \"%s\""), x->file_name);
-      goto error;
-    }
-
   this->length = x->page_length - x->top_margin - x->bottom_margin - 1;
   if (x->headers)
     this->length -= 3;
@@ -228,8 +223,7 @@ ascii_close_driver (struct outp_driver *this)
 {
   struct ascii_driver_ext *x = this->ext;
 
-  if (fn_close (x->file_name, x->file) != 0)
-    error (0, errno, _("ascii: closing output file \"%s\""), x->file_name);
+  ascii_flush (this);
   pool_detach_file (x->pool, x->file);
   pool_destroy (x->pool);
 
@@ -240,10 +234,11 @@ ascii_close_driver (struct outp_driver *this)
 enum
   {
     boolean_arg,
-    string_arg,
+    emphasis_arg,
     nonneg_int_arg,
     pos_int_arg,
-    output_file_arg
+    output_file_arg,
+    string_arg
   };
 
 static const struct outp_option option_tab[] =
@@ -252,7 +247,7 @@ static const struct outp_option option_tab[] =
     {"paginate", boolean_arg, 1},
     {"squeeze", boolean_arg, 2},
 
-    {"emphasis", string_arg, 3},
+    {"emphasis", emphasis_arg, 0},
 
     {"output-file", output_file_arg, 0},
 
@@ -263,6 +258,8 @@ static const struct outp_option option_tab[] =
     {"bottom-margin", nonneg_int_arg, 1},
     {"tab-width", nonneg_int_arg, 2},
 
+    {"init", string_arg, 0},
+
     {NULL, 0, 0},
   };
 
@@ -327,7 +324,7 @@ handle_option (struct outp_driver *this, const char *key,
          }
       }
       break;
-    case string_arg:
+    case emphasis_arg:
       if (!strcmp (value, "bold"))
         x->emphasis = EMPH_BOLD;
       else if (!strcmp (value, "underline"))
@@ -399,6 +396,10 @@ handle_option (struct outp_driver *this, const char *key,
          }
       }
       break;
+    case string_arg:
+      free (x->init);
+      x->init = pool_strdup (x->pool, value);
+      break;
     default:
       NOT_REACHED ();
     }
@@ -412,6 +413,21 @@ ascii_open_page (struct outp_driver *this)
   struct ascii_driver_ext *x = this->ext;
   int i;
 
+  if (x->file == NULL)
+    {
+      x->file = fn_open (x->file_name, "w");
+      if (x->file == NULL)
+        {
+          error (0, errno, _("ascii: opening output file \"%s\""),
+                 x->file_name);
+          return;
+        }
+      pool_attach_file (x->pool, x->file);
+
+      if (x->init != NULL)
+        fputs (x->init, x->file);
+    }
+
   x->page_number++;
 
   if (this->length > x->line_cap)
@@ -672,6 +688,9 @@ ascii_close_page (struct outp_driver *this)
   struct string out;
   int line_num;
 
+  if (x->file == NULL)
+    return;
+
   ds_init_empty (&out);
 
   ds_put_char_multiple (&out, '\n', x->top_margin);
@@ -720,6 +739,25 @@ ascii_close_page (struct outp_driver *this)
   ds_destroy (&out);
 }
 
+/* Flushes all output to the user and lets the user deal with it.
+   This is applied only to output drivers that are designated as
+   "screen" drivers that the user is interacting with in real
+   time. */
+static void
+ascii_flush (struct outp_driver *this)
+{
+  struct ascii_driver_ext *x = this->ext;
+
+  if (x->file != NULL)
+    {
+      if (fn_close (x->file_name, x->file) != 0)
+        error (0, errno, _("ascii: closing output file \"%s\""),
+               x->file_name);
+      pool_detach_file (x->pool, x->file);
+      x->file = NULL;
+    }
+}
+
 static void
 ascii_chart_initialise (struct outp_driver *d UNUSED, struct chart *ch)
 {
@@ -743,6 +781,7 @@ const struct outp_class ascii_class =
 
   ascii_open_page,
   ascii_close_page,
+  ascii_flush,
 
   NULL,