fbuf: New data structure for buffered file I/O.
[pspp] / src / output / ascii.c
index 562cd72ea76b75df68b0d352bf39c6bf6f28e90e..5a4c8c7e5652bf68fa61f469a864aa06574d8e7b 100644 (file)
@@ -28,6 +28,7 @@
 #include <uniwidth.h>
 
 #include "data/file-name.h"
+#include "data/file-handle-def.h"
 #include "data/settings.h"
 #include "libpspp/assertion.h"
 #include "libpspp/cast.h"
@@ -126,7 +127,15 @@ static const ucs4_t unicode_box_chars[N_BOX] =
 static inline int
 make_box_index (int left, int right, int top, int bottom)
 {
-  return ((right * RENDER_N_LINES + bottom) * RENDER_N_LINES + left) * RENDER_N_LINES + top;
+  int start_side = left;
+  int end_side = right;
+  if (render_direction_rtl ())
+    {
+      start_side = right;
+      end_side = left;
+    }
+
+  return ((end_side * RENDER_N_LINES + bottom) * RENDER_N_LINES + start_side) * RENDER_N_LINES + top;
 }
 
 /* How to emphasize text. */
@@ -172,7 +181,7 @@ struct ascii_driver
     char *command_name;
     char *title;
     char *subtitle;
-    char *file_name;            /* Output file name. */
+    struct file_handle *handle;
     FILE *file;                 /* Output file. */
     bool error;                 /* Output error? */
     int page_number;           /* Current page number. */
@@ -233,7 +242,7 @@ opt (struct output_driver *d, struct string_map *options, const char *key,
 }
 
 static struct output_driver *
-ascii_create (const char *file_name, enum settings_output_devices device_type,
+ascii_create (struct  file_handle *fh, enum settings_output_devices device_type,
               struct string_map *o)
 {
   enum { BOX_ASCII, BOX_UNICODE } box;
@@ -244,7 +253,7 @@ ascii_create (const char *file_name, enum settings_output_devices device_type,
 
   a = xzalloc (sizeof *a);
   d = &a->driver;
-  output_driver_init (&a->driver, &ascii_driver_class, file_name, device_type);
+  output_driver_init (&a->driver, &ascii_driver_class, fh_get_file_name (fh), device_type);
   a->append = parse_boolean (opt (d, o, "append", "false"));
   a->headers = parse_boolean (opt (d, o, "headers", "false"));
   a->paginate = parse_boolean (opt (d, o, "paginate", "false"));
@@ -255,7 +264,8 @@ ascii_create (const char *file_name, enum settings_output_devices device_type,
                             "none", EMPH_NONE,
                             NULL_SENTINEL);
 
-  a->chart_file_name = parse_chart_file_name (opt (d, o, "charts", file_name));
+  a->chart_file_name = parse_chart_file_name (opt (d, o, "charts", fh_get_file_name (fh)));
+  a->handle = fh;
 
   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);
@@ -283,7 +293,6 @@ ascii_create (const char *file_name, enum settings_output_devices device_type,
   a->command_name = NULL;
   a->title = xstrdup ("");
   a->subtitle = xstrdup ("");
-  a->file_name = xstrdup (file_name);
   a->file = NULL;
   a->error = false;
   a->page_number = 0;
@@ -380,11 +389,11 @@ ascii_destroy (struct output_driver *driver)
     ascii_close_page (a);
 
   if (a->file != NULL)
-    fn_close (a->file_name, a->file);
+    fn_close (a->handle, a->file);
+  fh_unref (a->handle);
   free (a->command_name);
   free (a->title);
   free (a->subtitle);
-  free (a->file_name);
   free (a->chart_file_name);
   for (i = 0; i < a->allocated_lines; i++)
     u8_line_destroy (&a->lines[i]);
@@ -400,8 +409,8 @@ ascii_flush (struct output_driver *driver)
     {
       ascii_close_page (a);
 
-      if (fn_close (a->file_name, a->file) != 0)
-        msg_error (errno, _("ascii: closing output file `%s'"), a->file_name);
+      if (fn_close (a->handle, a->file) != 0)
+        msg_error (errno, _("ascii: closing output file `%s'"), fh_get_file_name (a->handle));
       a->file = NULL;
     }
 }
@@ -448,7 +457,7 @@ ascii_output_table_item (struct ascii_driver *a,
       used = render_pager_draw_next (p, a->length - a->y);
       if (used == 0)
         {
-          assert (a->y > 0);
+          assert (a->y >= 0);
           ascii_close_page (a);
           if (!ascii_open_page (a))
             break;
@@ -464,7 +473,8 @@ 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);
+  table_item = table_item_create (table_from_string (TAB_LEFT, text),
+                                  NULL, NULL);
   ascii_output_table_item (a, table_item);
   table_item_unref (table_item);
 }
@@ -490,7 +500,7 @@ ascii_submit (struct output_driver *driver,
 
       file_name = xr_draw_png_chart (chart_item, a->chart_file_name,
                                      a->chart_cnt++,
-                                    &a->fg, 
+                                    &a->fg,
                                     &a->bg);
       if (file_name != NULL)
         {
@@ -1090,7 +1100,7 @@ ascii_open_page (struct ascii_driver *a)
 
   if (a->file == NULL)
     {
-      a->file = fn_open (a->file_name, a->append ? "a" : "w");
+      a->file = fn_fopen (a->handle, a->append ? "a" : "w");
       if (a->file != NULL)
         {
          if ( isatty (fileno (a->file)))
@@ -1110,7 +1120,7 @@ ascii_open_page (struct ascii_driver *a)
       else
         {
           msg_error (errno, _("ascii: opening output file `%s'"),
-                 a->file_name);
+                    fh_get_file_name (a->handle));
           a->error = true;
           return false;
         }