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., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
-/* AIX requires this to be the first thing in the file. */
#include <config.h>
-#if __GNUC__
-#define alloca __builtin_alloca
-#else
-#if HAVE_ALLOCA_H
-#include <alloca.h>
-#else
-#ifdef _AIX
-#pragma alloca
-#else
-#ifndef alloca /* predefined by HP cc +Olibcalls */
-char *alloca ();
-#endif
-#endif
-#endif
-#endif
/*this #if encloses the remainder of the file. */
#if !NO_POSTSCRIPT
#include <ctype.h>
-#include <assert.h>
+#include "error.h"
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
+#include <time.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
-#if TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#if HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-#endif
-
#include "alloc.h"
#include "bitvector.h"
#include "error.h"
#include "filename.h"
#include "font.h"
+#include "getl.h"
#include "getline.h"
+#include "glob.h"
#include "hash.h"
#include "main.h"
#include "misc.h"
-#include "misc.h"
#include "output.h"
+#include "som.h"
#include "version.h"
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
/* FIXMEs:
optimize-text-size not implemented.
static void free_font_entry (void *, void *foo);
static struct font_entry *load_font (struct outp_driver *, const char *dit);
static void init_fonts (void);
+static void done_fonts (void);
static void dump_lines (struct outp_driver *this);
\f
/* Driver initialization. */
-int
-ps_open_global (struct outp_class *this unused)
+static int
+ps_open_global (struct outp_class *this UNUSED)
{
init_fonts ();
groff_init ();
return 1;
}
-int
-ps_close_global (struct outp_class *this unused)
+static int
+ps_close_global (struct outp_class *this UNUSED)
{
+ groff_done ();
+ done_fonts ();
return 1;
}
-int *
-ps_font_sizes (struct outp_class *this unused, int *n_valid_sizes)
+static int *
+ps_font_sizes (struct outp_class *this UNUSED, int *n_valid_sizes)
{
/* Allow fonts up to 1" in height. */
static int valid_sizes[] =
return valid_sizes;
}
-int
+static int
ps_preopen_driver (struct outp_driver *this)
{
struct ps_driver_ext *x;
assert (this->driver_open == 0);
msg (VM (1), _("PostScript driver initializing as `%s'..."), this->name);
- this->ext = x = xmalloc (sizeof (struct ps_driver_ext));
+ this->ext = x = xmalloc (sizeof *x);
this->res = PSUS;
this->horiz = this->vert = 1;
this->width = this->length = 0;
return 1;
}
-int
+static int
ps_postopen_driver (struct outp_driver *this)
{
struct ps_driver_ext *x = this->ext;
return 1;
}
-int
+static int
ps_close_driver (struct outp_driver *this)
{
struct ps_driver_ext *x = this->ext;
/* font_entry comparison function for hash tables. */
static int
-compare_font_entry (const void *a, const void *b, void *foobar unused)
+compare_font_entry (const void *a, const void *b, void *foobar UNUSED)
{
return strcmp (((struct font_entry *) a)->dit, ((struct font_entry *) b)->dit);
}
/* font_entry hash function for hash tables. */
static unsigned
-hash_font_entry (const void *fe_, void *foobar unused)
+hash_font_entry (const void *fe_, void *foobar UNUSED)
{
const struct font_entry *fe = fe_;
return hsh_hash_string (fe->dit);
/* font_entry destructor function for hash tables. */
static void
-free_font_entry (void *pa, void *foo unused)
+free_font_entry (void *pa, void *foo UNUSED)
{
struct font_entry *a = pa;
free (a->dit);
};
static struct outp_option_info option_info;
-void
+static void
ps_option (struct outp_driver *this, const char *key, const struct string *val)
{
struct ps_driver_ext *x = this->ext;
int cat, subcat;
- char *value = ds_value (val);
+ char *value = ds_c_str (val);
cat = outp_match_keyword (key, option_tab, &option_info, &subcat);
break;
default:
assert (0);
+ abort ();
}
if (setting)
x->output_options |= mask;
break;
default:
assert (0);
+ abort ();
}
if (*dest)
free (*dest);
/* Hash table comparison function for ps_encoding's. */
static int
-compare_ps_encoding (const void *pa, const void *pb, void *foo unused)
+compare_ps_encoding (const void *pa, const void *pb, void *foo UNUSED)
{
const struct ps_encoding *a = pa;
const struct ps_encoding *b = pb;
/* Hash table hash function for ps_encoding's. */
static unsigned
-hash_ps_encoding (const void *pa, void *foo unused)
+hash_ps_encoding (const void *pa, void *foo UNUSED)
{
const struct ps_encoding *a = pa;
/* Hash table free function for ps_encoding's. */
static void
-free_ps_encoding (void *pa, void *foo unused)
+free_ps_encoding (void *pa, void *foo UNUSED)
{
struct ps_encoding *a = pa;
struct string line, buf;
- ds_init (NULL, &line, 128);
- ds_init (NULL, &buf, 128);
+ ds_init (&line, 128);
+ ds_init (&buf, 128);
for (pe = hsh_first (x->encodings, &iter); pe != NULL;
pe = hsh_next (x->encodings, &iter))
{
while (ds_get_config_line (f, &buf, &where))
{
- char *sp;
-
- pschar = strtok_r (ds_value (&buf), " \t\r\n", &sp);
+ char *sp;
+
+ if (buf.length == 0)
+ continue;
+
+ pschar = strtok_r (ds_c_str (&buf), " \t\r\n", &sp);
code = strtok_r (NULL, " \t\r\n", &sp);
if (*pschar == 0 || *code == 0)
continue;
if (ds_length (&line) + strlen (temp) > 70)
{
- ds_concat (&line, x->eol);
- fputs (ds_value (&line), x->file.file);
+ ds_puts (&line, x->eol);
+ fputs (ds_c_str (&line), x->file.file);
ds_clear (&line);
}
- ds_concat (&line, temp);
+ ds_puts (&line, temp);
}
- ds_concat (&line, x->eol);
- fputs (ds_value (&line), x->file.file);
+ ds_puts (&line, x->eol);
+ fputs (ds_c_str (&line), x->file.file);
if (fclose (f) == EOF)
msg (MW, _("PostScript driver: Error closing encoding file `%s'."),
add_encoding (struct outp_driver *this, char *filename)
{
struct ps_driver_ext *x = this->ext;
-
struct ps_encoding **pe;
filename = find_encoding_file (this, filename);
if (!filename)
return;
- pe = (struct ps_encoding **) hsh_probe (x->encodings, (void *) &filename);
+ pe = (struct ps_encoding **) hsh_probe (x->encodings, &filename);
if (*pe)
{
free (filename);
where.line_number = 0;
err_push_file_locator (&where);
- ds_init (NULL, &line, 128);
+ ds_init (&line, 128);
for (;;)
{
- char *bp;
-
if (!ds_get_config_line (f, &line, &where))
{
if (ferror (f))
break;
}
- add_encoding (this, bp);
+ add_encoding (this, line.string);
}
ds_destroy (&line);
char *beg;
beg = buf2 = fn_interp_vars (buf, ps_get_var);
len = strlen (buf2);
- while (isspace (*beg))
+ while (isspace ((unsigned char) *beg))
beg++, len--;
if (beg[len - 1] == '\n')
len--;
const char *sp;
for (sp = string; *sp; sp++)
- switch (*(unsigned char *) sp)
+ switch (*sp)
{
case 'a':
case 'f':
*dp++ = '<';
for (sp = string; *sp && dp < &dest[256]; sp++)
{
- sprintf (dp, "%02x", *(unsigned char *) sp);
+ sprintf (dp, "%02x", (unsigned char) *sp);
dp += 2;
}
return stpcpy (dp, ">cvn");
dp = stpcpy (dp, "\\(");
else if (*sp == ')')
dp = stpcpy (dp, "\\)");
- else if (*sp < 32 || *((unsigned char *) sp) > 127)
+ else if (*sp < 32 || (unsigned char) *sp > 127)
dp = spprintf (dp, "\\%3o", *sp);
else
*dp++ = *sp;
return 1;
}
-int
+static int
ps_open_page (struct outp_driver *this)
{
struct ps_driver_ext *x = this->ext;
draw_headers (this);
}
+ this->cp_y = 0;
+
return !ferror (x->file.file);
}
-int
+static int
ps_close_page (struct outp_driver *this)
{
struct ps_driver_ext *x = this->ext;
this->page_open = 0;
return !ferror (x->file.file);
}
+
+static void
+ps_submit (struct outp_driver *this UNUSED, struct som_entity *s)
+{
+ switch (s->type)
+ {
+ case SOM_CHART:
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
\f
/* Lines. */
/* qsort() comparison function for int tuples. */
static int
-int_2_compare (const void *a, const void *b)
+int_2_compare (const void *a_, const void *b_)
{
- return *((const int *) a) - *((const int *) b);
+ const int *a = a_;
+ const int *b = b_;
+
+ return *a < *b ? -1 : *a > *b;
}
/* Hash table comparison function for cached lines. */
static int
-compare_line (const void *a, const void *b, void *foo unused)
+compare_line (const void *a_, const void *b_, void *foo UNUSED)
{
- return ((struct line_form *) a)->ind - ((struct line_form *) b)->ind;
+ const struct line_form *a = a_;
+ const struct line_form *b = b_;
+
+ return a->ind < b->ind ? -1 : a->ind > b->ind;
}
/* Hash table hash function for cached lines. */
static unsigned
-hash_line (const void *pa, void *foo unused)
+hash_line (const void *pa, void *foo UNUSED)
{
const struct line_form *a = pa;
/* Hash table free function for cached lines. */
static void
-free_line (void *pa, void *foo unused)
+free_line (void *pa, void *foo UNUSED)
{
free (pa);
}
if (ext->lines[type] == NULL)
ext->lines[type] = hsh_create (31, compare_line, hash_line,
free_line, NULL);
- f = (struct line_form **) hsh_probe (ext->lines[type],
- (struct line_form *) & ind);
+ f = (struct line_form **) hsh_probe (ext->lines[type], &ind);
if (*f == NULL)
{
*f = xmalloc (sizeof **f + sizeof (int[15][2]));
if ((*f)->ndep >= (*f)->mdep)
{
(*f)->mdep += 16;
- *f = xrealloc (*f, (sizeof **f + sizeof (int[2]) * ((*f)->mdep - 1)));
+ *f = xrealloc (*f, sizeof **f + sizeof (int[2]) * ((*f)->mdep - 1));
}
(*f)->dep[(*f)->ndep][0] = dep1;
(*f)->dep[(*f)->ndep][1] = dep2;
(*f)->ndep++;
}
-void
+static void
ps_line_horz (struct outp_driver *this, const struct rect *r,
- const struct color *c unused, int style)
+ const struct color *c UNUSED, int style)
{
/* Must match output.h:OUTP_L_*. */
static const int types[OUTP_L_COUNT] =
line (this, style, y, r->x1, r->x2);
}
-void
+static void
ps_line_vert (struct outp_driver *this, const struct rect *r,
- const struct color *c unused, int style)
+ const struct color *c UNUSED, int style)
{
/* Must match output.h:OUTP_L_*. */
static const int types[OUTP_L_COUNT] =
#define T (style->t != OUTP_L_NONE)
#define B (style->b != OUTP_L_NONE)
-void
+static void
ps_line_intersection (struct outp_driver *this, const struct rect *r,
- const struct color *c unused,
+ const struct color *c UNUSED,
const struct outp_styles *style)
{
struct ps_driver_ext *ext = this->ext;
}
}
-void
-ps_line_width (struct outp_driver *this, int *width, int *height)
-{
- struct ps_driver_ext *x = this->ext;
-
- assert (this->driver_open && this->page_open);
- width[0] = height[0] = 0;
- width[1] = height[1] = 2 * x->line_gutter + x->line_width;
- width[2] = height[2] = (2 * x->line_gutter + 2 * x->line_width
- + x->line_space);
- width[3] = height[3] = 2 * x->line_gutter + x->line_width;
-}
-
-void
-ps_box (struct outp_driver *this unused, const struct rect *r unused,
- const struct color *bord unused, const struct color *fill unused)
+static void
+ps_box (struct outp_driver *this UNUSED, const struct rect *r UNUSED,
+ const struct color *bord UNUSED, const struct color *fill UNUSED)
{
assert (this->driver_open && this->page_open);
}
-void
-ps_polyline_begin (struct outp_driver *this unused,
- const struct color *c unused)
+static void
+ps_polyline_begin (struct outp_driver *this UNUSED,
+ const struct color *c UNUSED)
{
assert (this->driver_open && this->page_open);
}
-void
-ps_polyline_point (struct outp_driver *this unused, int x unused, int y unused)
+static void
+ps_polyline_point (struct outp_driver *this UNUSED, int x UNUSED, int y UNUSED)
{
assert (this->driver_open && this->page_open);
}
-void
-ps_polyline_end (struct outp_driver *this unused)
+static void
+ps_polyline_end (struct outp_driver *this UNUSED)
{
assert (this->driver_open && this->page_open);
}
int rh_width;
char buf[128];
- sprintf (buf, _("%s - Page %d"), curdate, ext->page_number);
+ sprintf (buf, _("%s - Page %d"), get_start_date (), ext->page_number);
rh_width = text_width (this, buf);
out_text_plain (this, buf, this->width - this->prop_em_width - rh_width,
\f
/* Text. */
-void
+static void
ps_text_set_font_by_name (struct outp_driver *this, const char *dit)
{
struct ps_driver_ext *x = this->ext;
x->current = fe;
}
-void
+static void
ps_text_set_font_by_position (struct outp_driver *this, int pos)
{
struct ps_driver_ext *x = this->ext;
local_free (dit);
}
-void
+static void
ps_text_set_font_family (struct outp_driver *this, const char *s)
{
struct ps_driver_ext *x = this->ext;
x->family = xstrdup (s);
}
-const char *
+static const char *
ps_text_get_font_name (struct outp_driver *this)
{
struct ps_driver_ext *x = this->ext;
return x->current->font->name;
}
-const char *
+static const char *
ps_text_get_font_family (struct outp_driver *this)
{
struct ps_driver_ext *x = this->ext;
return x->family;
}
-int
+static int
ps_text_set_size (struct outp_driver *this, int size)
{
struct ps_driver_ext *x = this->ext;
return 1;
}
-int
+static int
ps_text_get_size (struct outp_driver *this, int *em_width)
{
struct ps_driver_ext *x = this->ext;
/* Hash table comparison function for ps_combo structs. */
static int
-compare_ps_combo (const void *pa, const void *pb, void *foo unused)
+compare_ps_combo (const void *pa, const void *pb, void *foo UNUSED)
{
const struct ps_font_combo *a = pa;
const struct ps_font_combo *b = pb;
/* Hash table hash function for ps_combo structs. */
static unsigned
-hash_ps_combo (const void *pa, void *foo unused)
+hash_ps_combo (const void *pa, void *foo UNUSED)
{
const struct ps_font_combo *a = pa;
unsigned name_hash = hsh_hash_string (a->font->font->internal_name);
/* Hash table free function for ps_combo structs. */
static void
-free_ps_combo (void *a, void *foo unused)
+free_ps_combo (void *a, void *foo UNUSED)
{
free (a);
}
static void
write_text (struct outp_driver *this,
const struct output_char *cp, const struct output_char *end,
- struct outp_text *t, int width unused, int width_left)
+ struct outp_text *t, int width UNUSED, int width_left)
{
struct ps_driver_ext *ext = this->ext;
int ofs;
case OUTP_T_JUST_CENTER:
ofs = width_left / 2;
break;
+ default:
+ assert (0);
+ abort ();
}
lp = line;
if (TEST_BIT (literal_chars[ext->data], cp->ch))
*lp++ = cp->ch;
else
- switch (cp->ch)
+ switch ((char) cp->ch)
{
case '(':
lp = stpcpy (lp, "\\(");
buf_loc = buf;
assert (!ls_null_p (&t->s));
- cp = ls_value (&t->s);
+ cp = ls_c_str (&t->s);
end = ls_end (&t->s);
if (draw)
{
x = t->x;
y = t->y;
}
+ else
+ x = y = 0;
width = width_left = (t->options & OUTP_T_HORZ) ? t->h : INT_MAX;
height_left = (t->options & OUTP_T_VERT) ? t->v : INT_MAX;
max_height = 0;
prev_char = -1;
space_char = NULL;
+ space_buf_loc = NULL;
+ space_width_left = 0;
+
if (!width || !height_left)
goto exit;
/* Set char_name to the name of the character or ligature at
*cp. */
+ local_char_name[0] = *cp;
+ char_name = local_char_name;
if (ext->current->font->ligatures && *cp == 'f')
{
int lig = 0;
+ char_name = NULL;
if (cp < end - 1)
switch (cp[1])
}
if ((lig & ext->current->font->ligatures) == 0)
{
- local_char_name[0] = *cp++; /* 'f' */
+ local_char_name[0] = *cp; /* 'f' */
char_name = local_char_name;
}
- else
- cp += strlen (char_name);
}
else if (*cp == '\n')
{
set separate to 1. */
continue;
}
- else
- {
- local_char_name[0] = *cp++;
- char_name = local_char_name;
- }
+ cp += strlen (char_name);
/* Figure out what size this character is, and what kern
adjustment we need. */
}
else
{
- buf = xrealloc (buf, sizeof *buf * buf_len * 2);
+ buf = xnrealloc (buf, buf_len * 2, sizeof *buf);
buf_loc = buf + buf_len;
buf_end = buf + buf_len * 2;
}
ext->size = old_size;
}
-void
+static void
ps_text_metrics (struct outp_driver *this, struct outp_text *t)
{
assert (this->driver_open && this->page_open);
text (this, t, 0);
}
-void
+static void
ps_text_draw (struct outp_driver *this, struct outp_text *t)
{
assert (this->driver_open && this->page_open);
/* Hash table comparison function for filename2font structs. */
static int
-compare_filename2font (const void *a, const void *b, void *param unused)
+compare_filename2font (const void *a, const void *b, void *param UNUSED)
{
return strcmp (((struct filename2font *) a)->filename,
((struct filename2font *) b)->filename);
/* Hash table hash function for filename2font structs. */
static unsigned
-hash_filename2font (const void *f2f_, void *param unused)
+hash_filename2font (const void *f2f_, void *param UNUSED)
{
const struct filename2font *f2f = f2f_;
return hsh_hash_string (f2f->filename);
NULL, NULL);
}
+static void
+done_fonts (void)
+{
+ hsh_destroy (ps_fonts);
+}
+
/* Loads the font having Groff name DIT into THIS driver instance.
Specifically, adds it into the THIS driver's `loaded' hash
table. */
return fe;
}
+static void
+ps_chart_initialise (struct outp_driver *this UNUSED, struct chart *ch)
+{
+#ifdef NO_CHARTS
+ ch->lp = NULL;
+#else
+ struct ps_driver_ext *x = this->ext;
+ char page_size[128];
+ int size;
+ int x_origin, y_origin;
+
+ ch->file = tmpfile ();
+ if (ch->file == NULL)
+ {
+ ch->lp = NULL;
+ return;
+ }
+
+ size = this->width < this->length ? this->width : this->length;
+ x_origin = x->left_margin + (size - this->width) / 2;
+ y_origin = x->bottom_margin + (size - this->length) / 2;
+
+ snprintf (page_size, sizeof page_size,
+ "a,xsize=%.3f,ysize=%.3f,xorigin=%.3f,yorigin=%.3f",
+ (double) size / PSUS, (double) size / PSUS,
+ (double) x_origin / PSUS, (double) y_origin / PSUS);
+
+ ch->pl_params = pl_newplparams ();
+ pl_setplparam (ch->pl_params, "PAGESIZE", page_size);
+ ch->lp = pl_newpl_r ("ps", NULL, ch->file, stderr, ch->pl_params);
+#endif
+}
+
+static void
+ps_chart_finalise (struct outp_driver *this UNUSED, struct chart *ch UNUSED)
+{
+#ifndef NO_CHARTS
+ struct ps_driver_ext *x = this->ext;
+ char buf[BUFSIZ];
+ static int doc_num = 0;
+
+ if (this->page_open)
+ {
+ this->class->close_page (this);
+ this->page_open = 0;
+ }
+ this->class->open_page (this);
+ fprintf (x->file.file,
+ "/sp save def%s"
+ "%d %d translate 1000 dup scale%s"
+ "userdict begin%s"
+ "/showpage { } def%s"
+ "0 setgray 0 setlinecap 1 setlinewidth%s"
+ "0 setlinejoin 10 setmiterlimit [ ] 0 setdash newpath clear%s"
+ "%%%%BeginDocument: %d%s",
+ x->eol,
+ -x->left_margin, -x->bottom_margin, x->eol,
+ x->eol,
+ x->eol,
+ x->eol,
+ x->eol,
+ doc_num++, x->eol);
+
+ rewind (ch->file);
+ while (fwrite (buf, 1, fread (buf, 1, sizeof buf, ch->file), x->file.file))
+ continue;
+ fclose (ch->file);
+
+ fprintf (x->file.file,
+ "%%%%EndDocument%s"
+ "end%s"
+ "sp restore%s",
+ x->eol,
+ x->eol,
+ x->eol);
+ this->class->close_page (this);
+ this->page_open = 0;
+#endif
+}
+
/* PostScript driver class. */
struct outp_class postscript_class =
{
ps_open_page,
ps_close_page,
- NULL,
+ ps_submit,
ps_line_horz,
ps_line_vert,
ps_text_get_size,
ps_text_metrics,
ps_text_draw,
+
+ ps_chart_initialise,
+ ps_chart_finalise
};
/* EPSF driver class. FIXME: Probably doesn't work right. */
ps_open_page,
ps_close_page,
- NULL,
+ ps_submit,
ps_line_horz,
ps_line_vert,
ps_text_get_size,
ps_text_metrics,
ps_text_draw,
+
+ ps_chart_initialise,
+ ps_chart_finalise
+
};
#endif /* NO_POSTSCRIPT */