ascii: Drop useless 'wrap_mode' parameter from ascii_layout_cell().
[pspp-builds.git] / src / output / ascii.c
index b427df5318007df1cb42a04d75ecebfcafa33d65..c7c171166a41ff77bbe51bbfa76001f4c9e9791b 100644 (file)
 #include <limits.h>
 #include <stdint.h>
 #include <stdlib.h>
-
-#include <data/file-name.h>
-#include <data/settings.h>
-#include <libpspp/assertion.h>
-#include <libpspp/compiler.h>
-#include <libpspp/start-date.h>
-#include <libpspp/string-map.h>
-#include <libpspp/version.h>
-#include <output/cairo.h>
-#include <output/chart-item-provider.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include "data/file-name.h"
+#include "data/settings.h"
+#include "libpspp/assertion.h"
+#include "libpspp/cast.h"
+#include "libpspp/compiler.h"
+#include "libpspp/message.h"
+#include "libpspp/start-date.h"
+#include "libpspp/string-map.h"
+#include "libpspp/version.h"
+#include "output/cairo.h"
+#include "output/chart-item-provider.h"
+#include "output/driver-provider.h"
+#include "output/message-item.h"
 #include "output/options.h"
-#include <output/tab.h>
-#include <output/text-item.h>
-#include <output/driver-provider.h>
-#include <output/render.h>
-#include <output/table-item.h>
+#include "output/render.h"
+#include "output/tab.h"
+#include "output/table-item.h"
+#include "output/text-item.h"
 
-#include "error.h"
-#include "minmax.h"
-#include "xalloc.h"
+#include "gl/error.h"
+#include "gl/minmax.h"
+#include "gl/xalloc.h"
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
@@ -112,6 +117,7 @@ struct ascii_driver
     char *init;                 /* Device initialization string. */
 
     /* Internal state. */
+    char *command_name;
     char *title;
     char *subtitle;
     char *file_name;            /* Output file name. */
@@ -181,7 +187,7 @@ ascii_create (const char *file_name, enum settings_output_devices device_type,
                             "bold", EMPH_BOLD,
                             "underline", EMPH_UNDERLINE,
                             "none", EMPH_NONE,
-                            (char *) NULL);
+                            NULL_SENTINEL);
 
   a->chart_file_name = parse_chart_file_name (opt (d, o, "charts", file_name));
 
@@ -209,6 +215,7 @@ ascii_create (const char *file_name, enum settings_output_devices device_type,
           }
   a->init = parse_string (opt (d, o, "init", ""));
 
+  a->command_name = NULL;
   a->title = xstrdup ("");
   a->subtitle = xstrdup ("");
   a->file_name = xstrdup (file_name);
@@ -330,6 +337,7 @@ ascii_destroy (struct output_driver *driver)
 
   if (a->file != NULL)
     fn_close (a->file_name, a->file);
+  free (a->command_name);
   free (a->title);
   free (a->subtitle);
   free (a->file_name);
@@ -352,7 +360,7 @@ ascii_flush (struct output_driver *driver)
       ascii_close_page (a);
 
       if (fn_close (a->file_name, a->file) != 0)
-        error (0, errno, _("ascii: closing output file \"%s\""),
+        error (0, errno, _("ascii: closing output file `%s'"),
                a->file_name);
       a->file = NULL;
     }
@@ -367,103 +375,122 @@ ascii_init_caption_cell (const char *caption, struct table_cell *cell)
 }
 
 static void
-ascii_submit (struct output_driver *driver,
-              const struct output_item *output_item)
+ascii_output_table_item (struct ascii_driver *a,
+                         const struct table_item *table_item)
 {
-  struct ascii_driver *a = ascii_driver_cast (driver);
-  if (a->error)
-    return;
-  if (is_table_item (output_item))
+  const char *caption = table_item_get_caption (table_item);
+  struct render_params params;
+  struct render_page *page;
+  struct render_break x_break;
+  int caption_height;
+  int i;
+
+  update_page_size (a, false);
+
+  if (caption != NULL)
     {
-      struct table_item *table_item = to_table_item (output_item);
-      const char *caption = table_item_get_caption (table_item);
-      struct render_params params;
-      struct render_page *page;
-      struct render_break x_break;
-      int caption_height;
-      int i;
+      /* XXX doesn't do well with very large captions */
+      struct table_cell cell;
+      ascii_init_caption_cell (caption, &cell);
+      caption_height = ascii_measure_cell_height (a, &cell, a->width);
+    }
+  else
+    caption_height = 0;
+
+  params.draw_line = ascii_draw_line;
+  params.measure_cell_width = ascii_measure_cell_width;
+  params.measure_cell_height = ascii_measure_cell_height;
+  params.draw_cell = ascii_draw_cell,
+    params.aux = a;
+  params.size[H] = a->width;
+  params.size[V] = a->length - caption_height;
+  params.font_size[H] = 1;
+  params.font_size[V] = 1;
+  for (i = 0; i < RENDER_N_LINES; i++)
+    {
+      int width = i == RENDER_LINE_NONE ? 0 : 1;
+      params.line_widths[H][i] = width;
+      params.line_widths[V][i] = width;
+    }
+
+  if (a->file == NULL && !ascii_open_page (a))
+    return;
 
-      update_page_size (a, false);
+  page = render_page_create (&params, table_item_get_table (table_item));
+  for (render_break_init (&x_break, page, H);
+       render_break_has_next (&x_break); )
+    {
+      struct render_page *x_slice;
+      struct render_break y_break;
 
-      if (caption != NULL)
-        {
-          /* XXX doesn't do well with very large captions */
-          struct table_cell cell;
-          ascii_init_caption_cell (caption, &cell);
-          caption_height = ascii_measure_cell_height (a, &cell, a->width);
-        }
-      else
-        caption_height = 0;
-
-      params.draw_line = ascii_draw_line;
-      params.measure_cell_width = ascii_measure_cell_width;
-      params.measure_cell_height = ascii_measure_cell_height;
-      params.draw_cell = ascii_draw_cell,
-      params.aux = a;
-      params.size[H] = a->width;
-      params.size[V] = a->length - caption_height;
-      params.font_size[H] = 1;
-      params.font_size[V] = 1;
-      for (i = 0; i < RENDER_N_LINES; i++)
+      x_slice = render_break_next (&x_break, a->width);
+      for (render_break_init (&y_break, x_slice, V);
+           render_break_has_next (&y_break); )
         {
-          int width = i == RENDER_LINE_NONE ? 0 : 1;
-          params.line_widths[H][i] = width;
-          params.line_widths[V][i] = width;
-        }
+          struct render_page *y_slice;
+          int space;
 
-      if (a->file == NULL && !ascii_open_page (a))
-        return;
+          if (a->y > 0)
+            a->y++;
 
-      page = render_page_create (&params, table_item_get_table (table_item));
-      for (render_break_init (&x_break, page, H);
-           render_break_has_next (&x_break); )
-        {
-          struct render_page *x_slice;
-          struct render_break y_break;
+          space = a->length - a->y - caption_height;
+          if (render_break_next_size (&y_break) > space)
+            {
+              assert (a->y > 0);
+              ascii_close_page (a);
+              if (!ascii_open_page (a))
+                return;
+              continue;
+            }
 
-          x_slice = render_break_next (&x_break, a->width);
-          for (render_break_init (&y_break, x_slice, V);
-               render_break_has_next (&y_break); )
+          y_slice = render_break_next (&y_break, space);
+          if (caption_height)
             {
-              struct render_page *y_slice;
-              int space;
-
-              if (a->y > 0)
-                a->y++;
-
-              space = a->length - a->y - caption_height;
-              if (render_break_next_size (&y_break) > space)
-                {
-                  assert (a->y > 0);
-                  ascii_close_page (a);
-                  if (!ascii_open_page (a))
-                    return;
-                  continue;
-                }
-
-              y_slice = render_break_next (&y_break, space);
-              if (caption_height)
-                {
-                  struct table_cell cell;
-                  int bb[TABLE_N_AXES][2];
-
-                  ascii_init_caption_cell (caption, &cell);
-                  bb[H][0] = 0;
-                  bb[H][1] = a->width;
-                  bb[V][0] = 0;
-                  bb[V][1] = caption_height;
-                  ascii_draw_cell (a, &cell, bb, bb);
-                  a->y += caption_height;
-                  caption_height = 0;
-                }
-              render_page_draw (y_slice);
-              a->y += render_page_get_size (y_slice, V);
-              render_page_unref (y_slice);
+              struct table_cell cell;
+              int bb[TABLE_N_AXES][2];
+
+              ascii_init_caption_cell (caption, &cell);
+              bb[H][0] = 0;
+              bb[H][1] = a->width;
+              bb[V][0] = 0;
+              bb[V][1] = caption_height;
+              ascii_draw_cell (a, &cell, bb, bb);
+              a->y += caption_height;
+              caption_height = 0;
             }
-          render_break_destroy (&y_break);
+          render_page_draw (y_slice);
+          a->y += render_page_get_size (y_slice, V);
+          render_page_unref (y_slice);
         }
-      render_break_destroy (&x_break);
+      render_break_destroy (&y_break);
     }
+  render_break_destroy (&x_break);
+}
+
+static void
+ascii_output_text (struct ascii_driver *a, const char *text)
+{
+  struct table_item *table_item;
+
+  table_item = table_item_create (table_from_string (TAB_LEFT, text), NULL);
+  ascii_output_table_item (a, table_item);
+  table_item_unref (table_item);
+}
+
+static void
+ascii_submit (struct output_driver *driver,
+              const struct output_item *output_item)
+{
+  struct ascii_driver *a = ascii_driver_cast (driver);
+
+  output_driver_track_current_command (output_item, &a->command_name);
+
+  if (a->error)
+    return;
+
+  if (is_table_item (output_item))
+    ascii_output_table_item (a, to_table_item (output_item));
+#ifdef HAVE_CAIRO
   else if (is_chart_item (output_item) && a->chart_file_name != NULL)
     {
       struct chart_item *chart_item = to_chart_item (output_item);
@@ -483,6 +510,7 @@ ascii_submit (struct output_driver *driver,
           free (file_name);
         }
     }
+#endif  /* HAVE_CAIRO */
   else if (is_text_item (output_item))
     {
       const struct text_item *text_item = to_text_item (output_item);
@@ -515,17 +543,18 @@ ascii_submit (struct output_driver *driver,
           break;
 
         default:
-          {
-            struct table_item *item;
-
-            item = table_item_create (table_from_string (TAB_LEFT, text),
-                                      NULL);
-            ascii_submit (&a->driver, &item->output_item);
-            table_item_unref (item);
-          }
+          ascii_output_text (a, text);
           break;
         }
     }
+  else if (is_message_item (output_item))
+    {
+      const struct message_item *message_item = to_message_item (output_item);
+      const struct msg *msg = message_item_get_msg (message_item);
+      char *s = msg_to_string (msg, a->command_name);
+      ascii_output_text (a, s);
+      free (s);
+    }
 }
 
 const struct output_driver_factory txt_driver_factory =
@@ -541,18 +570,11 @@ static const struct output_driver_class ascii_driver_class =
     ascii_flush,
   };
 \f
-enum wrap_mode
-  {
-    WRAP_WORD,
-    WRAP_CHAR,
-    WRAP_WORD_CHAR
-  };
-
 static void ascii_expand_line (struct ascii_driver *, int y, int length);
 static void ascii_layout_cell (struct ascii_driver *,
                                const struct table_cell *,
                                int bb[TABLE_N_AXES][2],
-                               int clip[TABLE_N_AXES][2], enum wrap_mode wrap,
+                               int clip[TABLE_N_AXES][2],
                                int *width, int *height);
 
 static void
@@ -595,12 +617,12 @@ ascii_measure_cell_width (void *a_, const struct table_cell *cell,
   bb[V][0] = 0;
   bb[V][1] = INT_MAX;
   clip[H][0] = clip[H][1] = clip[V][0] = clip[V][1] = 0;
-  ascii_layout_cell (a, cell, bb, clip, WRAP_WORD, max_width, &h);
+  ascii_layout_cell (a, cell, bb, clip, max_width, &h);
 
   if (strchr (cell->contents, ' '))
     {
       bb[H][1] = 1;
-      ascii_layout_cell (a, cell, bb, clip, WRAP_WORD, min_width, &h);
+      ascii_layout_cell (a, cell, bb, clip, min_width, &h);
     }
   else
     *min_width = *max_width;
@@ -619,7 +641,7 @@ ascii_measure_cell_height (void *a_, const struct table_cell *cell, int width)
   bb[V][0] = 0;
   bb[V][1] = INT_MAX;
   clip[H][0] = clip[H][1] = clip[V][0] = clip[V][1] = 0;
-  ascii_layout_cell (a, cell, bb, clip, WRAP_WORD, &w, &h);
+  ascii_layout_cell (a, cell, bb, clip, &w, &h);
   return h;
 }
 
@@ -630,7 +652,7 @@ ascii_draw_cell (void *a_, const struct table_cell *cell,
   struct ascii_driver *a = a_;
   int w, h;
 
-  ascii_layout_cell (a, cell, bb, clip, WRAP_WORD, &w, &h);
+  ascii_layout_cell (a, cell, bb, clip, &w, &h);
 }
 
 /* Ensures that at least the first LENGTH characters of line Y in
@@ -709,7 +731,7 @@ text_draw (struct ascii_driver *a, const struct table_cell *cell,
 static void
 ascii_layout_cell (struct ascii_driver *a, const struct table_cell *cell,
                    int bb[TABLE_N_AXES][2], int clip[TABLE_N_AXES][2],
-                   enum wrap_mode wrap, int *width, int *height)
+                   int *width, int *height)
 {
   size_t length = strlen (cell->contents);
   int y, pos;
@@ -729,14 +751,14 @@ ascii_layout_cell (struct ascii_driver *a, const struct table_cell *cell,
         line_len = new_line - line;
 
       /* Word wrap. */
-      if (pos + line_len < length && wrap != WRAP_CHAR)
+      if (pos + line_len < length)
         {
           size_t space_len = line_len;
           while (space_len > 0 && !isspace ((unsigned char) line[space_len]))
             space_len--;
           if (space_len > 0)
             line_len = space_len;
-          else if (wrap == WRAP_WORD)
+          else
             {
               while (pos + line_len < length
                      && !isspace ((unsigned char) line[line_len]))
@@ -759,6 +781,17 @@ ascii_layout_cell (struct ascii_driver *a, const struct table_cell *cell,
 \f
 /* ascii_close_page () and support routines. */
 
+
+#if HAVE_DECL_SIGWINCH
+static struct ascii_driver *the_driver;
+
+static void
+winch_handler (int signum UNUSED)
+{
+  update_page_size (the_driver, false);
+}
+#endif
+
 static bool
 ascii_open_page (struct ascii_driver *a)
 {
@@ -772,12 +805,25 @@ ascii_open_page (struct ascii_driver *a)
       a->file = fn_open (a->file_name, a->append ? "a" : "w");
       if (a->file != NULL)
         {
+#if HAVE_DECL_SIGWINCH
+         if ( isatty (fileno (a->file)))
+           {
+             struct sigaction action;
+             sigemptyset (&action.sa_mask);
+             action.sa_flags = 0;
+             action.sa_handler = winch_handler;
+             the_driver = a;
+             a->auto_width = true;
+             a->auto_length = true;
+             sigaction (SIGWINCH, &action, NULL);
+           }
+#endif
           if (a->init != NULL)
             fputs (a->init, a->file);
         }
       else
         {
-          error (0, errno, _("ascii: opening output file \"%s\""),
+          error (0, errno, _("ascii: opening output file `%s'"),
                  a->file_name);
           a->error = true;
           return false;
@@ -848,7 +894,7 @@ static void
 output_title_line (FILE *out, int width, const char *left, const char *right)
 {
   struct string s = DS_EMPTY_INITIALIZER;
-  ds_put_char_multiple (&s, ' ', width);
+  ds_put_byte_multiple (&s, ' ', width);
   if (left != NULL)
     {
       size_t length = MIN (strlen (left), width);
@@ -859,7 +905,7 @@ output_title_line (FILE *out, int width, const char *left, const char *right)
       size_t length = MIN (strlen (right), width);
       memcpy (ds_end (&s) - length, right, length);
     }
-  ds_put_char (&s, '\n');
+  ds_put_byte (&s, '\n');
   fputs (ds_cstr (&s), out);
   ds_destroy (&s);
 }