Tue Dec 30 22:37:04 2003 Ben Pfaff <blp@gnu.org>
[pspp] / src / ascii.c
index 06addff506fe6e447548695f20410f2e41341f6e..60bd1837ce39bc7499ed0f8823f77f4b46e20083 100644 (file)
@@ -49,6 +49,7 @@
    width=130
    lpi=6                        Only used to determine font size.
    cpi=10                       
+   squeeze=off|on               Squeeze multiple newlines into exactly one.
 
    left-margin=0
    right-margin=0
@@ -161,6 +162,7 @@ struct ascii_driver_ext
     struct len_string fonts[FSTY_COUNT]; /* Font styles; NULL=overstrike. */
     int overstrike_style;      /* OVS_SINGLE or OVS_LINE. */
     int carriage_return_style; /* Carriage return style. */
+    int squeeze_blank_lines;    /* 1=squeeze multiple blank lines into one. */
 
     /* Internal state. */
     struct file_ext file;      /* Output file. */
@@ -182,21 +184,21 @@ static struct pool *ascii_pool;
 static int postopen (struct file_ext *);
 static int preclose (struct file_ext *);
 
-int
+static int
 ascii_open_global (struct outp_class *this unused)
 {
   ascii_pool = pool_create ();
   return 1;
 }
 
-int
+static int
 ascii_close_global (struct outp_class *this unused)
 {
   pool_destroy (ascii_pool);
   return 1;
 }
 
-int *
+static int *
 ascii_font_sizes (struct outp_class *this unused, int *n_valid_sizes)
 {
   static int valid_sizes[] = {12, 12, 0, 0};
@@ -206,7 +208,7 @@ ascii_font_sizes (struct outp_class *this unused, int *n_valid_sizes)
   return valid_sizes;
 }
 
-int
+static int
 ascii_preopen_driver (struct outp_driver *this)
 {
   struct ascii_driver_ext *x;
@@ -235,6 +237,7 @@ ascii_preopen_driver (struct outp_driver *this)
     ls_null (&x->fonts[i]);
   x->overstrike_style = OVS_SINGLE;
   x->carriage_return_style = CRS_BS;
+  x->squeeze_blank_lines = 0;
   x->file.filename = NULL;
   x->file.mode = "wb";
   x->file.file = NULL;
@@ -255,7 +258,7 @@ ascii_preopen_driver (struct outp_driver *this)
   return 1;
 }
 
-int
+static int
 ascii_postopen_driver (struct outp_driver *this)
 {
   struct ascii_driver_ext *x = this->ext;
@@ -380,7 +383,7 @@ ascii_postopen_driver (struct outp_driver *this)
   return 1;
 }
 
-int
+static int
 ascii_close_driver (struct outp_driver *this)
 {
   struct ascii_driver_ext *x = this->ext;
@@ -438,11 +441,12 @@ static struct outp_option option_tab[] =
     {"overstrike-style", 3, 0},
     {"tab-width", nonneg_int_arg, 4},
     {"carriage-return-style", 4, 0},
+    {"squeeze", boolean_arg, 2},
     {"", 0, 0},
   };
 static struct outp_option_info option_info;
 
-void
+static void
 ascii_option (struct outp_driver *this, const char *key,
              const struct string *val)
 {
@@ -622,11 +626,14 @@ ascii_option (struct outp_driver *this, const char *key,
        switch (subcat)
          {
          case 0:
-           x->headers = 0;
+           x->headers = setting;
            break;
          case 1:
            x->paginate = setting;
            break;
+          case 2:
+            x->squeeze_blank_lines = setting;
+            break;
          default:
            assert (0);
          }
@@ -667,7 +674,7 @@ preclose (struct file_ext *f)
   return 1;
 }
 
-int
+static int
 ascii_open_page (struct outp_driver *this)
 {
   struct ascii_driver_ext *x = this->ext;
@@ -726,7 +733,7 @@ expand_line (struct ascii_driver_ext *x, int i, int l)
 #define B(STYLE) (STYLE<<LNS_BOTTOM)
 #define R(STYLE) (STYLE<<LNS_RIGHT)
 
-void
+static void
 ascii_line_horz (struct outp_driver *this, const struct rect *r,
                 const struct color *c unused, int style)
 {
@@ -760,7 +767,7 @@ ascii_line_horz (struct outp_driver *this, const struct rect *r,
     draw_line (x, y1, (style << LNS_LEFT) | (style << LNS_RIGHT));
 }
 
-void
+static void
 ascii_line_vert (struct outp_driver *this, const struct rect *r,
                 const struct color *c unused, int style)
 {
@@ -795,7 +802,7 @@ ascii_line_vert (struct outp_driver *this, const struct rect *r,
     draw_line (x1, y, (style << LNS_TOP) | (style << LNS_BOTTOM));
 }
 
-void
+static void
 ascii_line_intersection (struct outp_driver *this, const struct rect *r,
                         const struct color *c unused,
                         const struct outp_styles *style)
@@ -825,23 +832,9 @@ ascii_line_intersection (struct outp_driver *this, const struct rect *r,
   draw_line (x, y, l);
 }
 
-void
-ascii_line_width (struct outp_driver *this, int *width, int *height)
-{
-  int i;
-
-  assert (this->driver_open && this->page_open);
-  width[0] = height[0] = 0;
-  for (i = 1; i < OUTP_L_COUNT; i++)
-    {
-      width[i] = this->horiz;
-      height[i] = this->vert;
-    }
-}
-
 /* FIXME: Later we could set this up so that for certain devices it
    performs shading? */
-void
+static void
 ascii_box (struct outp_driver *this unused, const struct rect *r unused,
           const struct color *bord unused, const struct color *fill unused)
 {
@@ -849,23 +842,23 @@ ascii_box (struct outp_driver *this unused, const struct rect *r unused,
 }
 
 /* Polylines not supported. */
-void
+static void
 ascii_polyline_begin (struct outp_driver *this unused, const struct color *c unused)
 {
   assert (this->driver_open && this->page_open);
 }
-void
+static void
 ascii_polyline_point (struct outp_driver *this unused, int x unused, int y unused)
 {
   assert (this->driver_open && this->page_open);
 }
-void
+static void
 ascii_polyline_end (struct outp_driver *this unused)
 {
   assert (this->driver_open && this->page_open);
 }
 
-void
+static void
 ascii_text_set_font_by_name (struct outp_driver * this, const char *s)
 {
   struct ascii_driver_ext *x = this->ext;
@@ -886,7 +879,7 @@ ascii_text_set_font_by_name (struct outp_driver * this, const char *s)
     x->cur_font = OUTP_F_B;
 }
 
-void
+static void
 ascii_text_set_font_by_position (struct outp_driver *this, int pos)
 {
   struct ascii_driver_ext *x = this->ext;
@@ -894,13 +887,13 @@ ascii_text_set_font_by_position (struct outp_driver *this, int pos)
   x->cur_font = pos >= 0 && pos < 4 ? pos : 0;
 }
 
-void
+static void
 ascii_text_set_font_by_family (struct outp_driver *this unused, const char *s unused)
 {
   assert (this->driver_open && this->page_open);
 }
 
-const char *
+static const char *
 ascii_text_get_font_name (struct outp_driver *this)
 {
   struct ascii_driver_ext *x = this->ext;
@@ -922,21 +915,21 @@ ascii_text_get_font_name (struct outp_driver *this)
   abort ();
 }
 
-const char *
+static const char *
 ascii_text_get_font_family (struct outp_driver *this unused)
 {
   assert (this->driver_open && this->page_open);
   return "";
 }
 
-int
+static int
 ascii_text_set_size (struct outp_driver *this, int size)
 {
   assert (this->driver_open && this->page_open);
   return size == this->vert;
 }
 
-int
+static int
 ascii_text_get_size (struct outp_driver *this, int *em_width)
 {
   assert (this->driver_open && this->page_open);
@@ -1050,7 +1043,7 @@ delineate (struct outp_driver *this, struct outp_text *t, int draw)
   t->v = (temp.y * this->vert) - t->y;
 }
 
-void
+static void
 ascii_text_metrics (struct outp_driver *this, struct outp_text *t)
 {
   assert (this->driver_open && this->page_open);
@@ -1063,7 +1056,7 @@ ascii_text_metrics (struct outp_driver *this, struct outp_text *t)
     delineate (this, t, 0);
 }
 
-void
+static void
 ascii_text_draw (struct outp_driver *this, struct outp_text *t)
 {
   /* FIXME: orientations not supported. */
@@ -1346,9 +1339,8 @@ static void
 output_lines (struct outp_driver *this, int first, int count)
 {
   struct ascii_driver_ext *ext = this->ext;
+  int line_num;
 
-  unsigned short *p = &ext->page[ext->w * first];
-  int *len = &ext->line_len[first];
   struct len_string *newline = &ext->ops[OPS_NEWLINE];
 
   int n_chars;
@@ -1357,15 +1349,24 @@ output_lines (struct outp_driver *this, int first, int count)
   if (NULL == ext->file.file)
     return;
 
-  while (count--)              /* Iterate over all the lines to be output. */
+  /* Iterate over all the lines to be output. */
+  for (line_num = first; line_num < first + count; line_num++)
     {
-      unsigned short *end_p;
+      unsigned short *p = &ext->page[ext->w * line_num];
+      unsigned short *end_p = p + ext->line_len[line_num];
       unsigned short *bp, *ep;
       unsigned short attr = 0;
 
-      end_p = p + *len++;
       assert (end_p >= p);
 
+      /* Squeeze multiple blank lines into a single blank line if
+         requested. */
+      if (ext->squeeze_blank_lines
+          && line_num > first
+          && ext->line_len[line_num] == 0
+          && ext->line_len[line_num - 1] == 0)
+        continue;
+
       /* Output every character in the line in the appropriate
          manner. */
       n_passes = 1;
@@ -1483,13 +1484,12 @@ output_lines (struct outp_driver *this, int first, int count)
              ep = bp;
            }
        }
-      p += ext->w;
 
       output_string (this, ls_value (newline), ls_end (newline));
     }
 }
 
-int
+static int
 ascii_close_page (struct outp_driver *this)
 {
   static unsigned char *s;