#include "gsint.h"
#define F_EPSF_CENTER 0x01
#define F_EPSF_RIGHT 0x02
#define M_EPSF_JUSTIFICATION 0x03
#define F_EPSF_NO_CPOINT_UPDATE_X 0x04
#define F_EPSF_NO_CPOINT_UPDATE_Y 0x08
#define F_EPSF_ABSOLUTE_X 0x10
#define F_EPSF_ABSOLUTE_Y 0x20
#define F_EPSF_SCALE_X 0x40
#define F_EPSF_SCALE_Y 0x80
#define CORRECT_SLICE() (slicing == 0 || current_slice == slice)
#define ISPRINT(ch) (font_ctype[(unsigned char) (ch)] != ' ')
#define EXISTS(ch) (font_ctype[(unsigned char) (ch)] == '*')
#define RESOURCE_LINE_WIDTH 75
typedef enum
{
tNONE,
tEOF,
tSTRING,
tFORMFEED,
tNEWLINE,
tCARRIAGE_RETURN,
tWRAPPED_NEWLINE,
tEPSF,
tSETFILENAME,
tSETPAGENUMBER,
tNEWPAGE,
tFONT,
tCOLOR,
tPS
} TokenType;
typedef enum
{
ESC_COMMENT,
ESC_EPSF,
ESC_FONT,
ESC_COLOR,
ESC_NEWPAGE,
ESC_SETFILENAME,
ESC_SETPAGENUMBER,
ESC_SHADE,
ESC_BGGRAY,
ESC_ESCAPE,
ESC_PS
} SpecialEscape;
struct gs_token_st
{
TokenType type;
unsigned int flags;
double new_x;
double new_y;
int new_col;
union
{
int i;
char *str;
struct
{
double x;
double y;
double w;
double h;
double xscale;
double yscale;
int llx, lly, urx, ury;
char filename[512];
char *skipbuf;
unsigned int skipbuf_len;
unsigned int skipbuf_pos;
FILE *fp;
int pipe;
} epsf;
Color color;
struct
{
char name[512];
FontPoint size;
} font;
char filename[512];
} u;
};
typedef struct gs_token_st Token;
static void get_next_token ___P ((InputStream *is, double linestart,
double linepos, unsigned int col,
double linew, Token *token));
static void dump_ps_page_header ___P ((char *fname, int empty));
static void dump_ps_page_trailer ();
static void dump_empty_page ();
static int recognize_eps_file ___P ((Token *token));
static void paste_epsf ___P ((Token *token));
static int do_pass_through ___P ((char *fname, InputStream *is));
static double read_float ___P ((InputStream *is, int units, int horizontal));
static void print_line_number ___P ((double x, double y, double space,
double margin, unsigned int linenum));
#define OUTPUT(body) \
do { \
if (cofp == NULL) \
cofp = ofp; \
if (do_print) \
fprintf body; \
} while (0)
static void divert ();
static void undivert ();
static void handle_two_side_options ();
unsigned int current_pagenum;
unsigned int total_pages_in_file;
unsigned int input_filenum = 0;
unsigned int current_file_linenum;
char fname[1024];
static int ps_header_dumped = 0;
static FILE *divertfp = NULL;
static FILE *cofp = NULL;
static int do_print = 1;
static int user_fontp = 0;
static char user_font_name[256];
static FontPoint user_font_pt;
static int user_colorp = 0;
static Color user_color;
static unsigned int print_line_number_last;
void
dump_ps_header ()
{
char *cp, *cp2;
int i, j, got;
if (ps_header_dumped)
return;
ps_header_dumped = 1;
OUTPUT ((cofp, "%s\n", output_first_line));
OUTPUT ((cofp, "%%%%BoundingBox: %d %d %d %d\n", media->llx, media->lly,
media->urx, media->ury));
OUTPUT ((cofp, "%%%%Title: %s\n", title));
OUTPUT ((cofp, "%%%%For: %s\n", passwd->pw_gecos));
OUTPUT ((cofp, "%%%%Creator: %s\n", version_string));
OUTPUT ((cofp, "%%%%CreationDate: %s\n", date_string));
OUTPUT ((cofp, "%%%%Orientation: %s\n",
((nup > 1) && nup_landscape)
|| ((nup == 1) && landscape) ? "Landscape" : "Portrait"));
OUTPUT ((cofp, "%%%%Pages: (atend)\n"));
OUTPUT ((cofp, "%%%%DocumentMedia: %s %d %d 0 () ()\n",
media->name, media->w, media->h));
OUTPUT ((cofp, "%%%%DocumentNeededResources: (atend)\n"));
if (count_key_value_set (pagedevice) > 0)
OUTPUT ((cofp, "%%%%LanguageLevel: 2\n"));
OUTPUT ((cofp, "%%%%EndComments\n"));
OUTPUT ((cofp, "%%%%BeginProlog\n"));
OUTPUT ((cofp, "%%%%BeginResource: procset Enscript-Prolog %s\n",
ps_version_string));
if (!paste_file ("enscript", ".pro"))
FATAL ((stderr, _("couldn't find prolog \"%s\": %s\n"), "enscript.pro",
strerror (errno)));
OUTPUT ((cofp, "%%%%EndResource\n"));
OUTPUT ((cofp, "%%%%BeginResource: procset Enscript-Encoding-%s %s\n",
encoding_name, ps_version_string));
if (!paste_file (encoding_name, ".enc"))
FATAL ((stderr, _("couldn't find encoding file \"%s.enc\": %s\n"),
encoding_name, strerror (errno)));
OUTPUT ((cofp, "%%%%EndResource\n"));
OUTPUT ((cofp, "%%%%EndProlog\n"));
OUTPUT ((cofp, "%%%%BeginSetup\n"));
for (got = strhash_get_first (download_fonts, &cp, &j, (void **) &cp2); got;
got = strhash_get_next (download_fonts, &cp, &j, (void **) &cp2))
download_font (cp);
for (got = strhash_get_first (res_fonts, &cp, &j, (void **) &cp2); got;
got = strhash_get_next (res_fonts, &cp, &j, (void **) &cp2))
OUTPUT ((cofp, "%%%%IncludeResource: font %s\n", cp));
OUTPUT ((cofp, "/HFpt_w %g def\n", HFpt.w));
OUTPUT ((cofp, "/HFpt_h %g def\n", HFpt.h));
OUTPUT ((cofp, "/%s /HF-gs-font MF\n", HFname));
OUTPUT ((cofp,
"/HF /HF-gs-font findfont [HFpt_w 0 0 HFpt_h 0 0] makefont def\n"));
OUTPUT ((cofp, "/%s /F-gs-font MF\n", Fname));
OUTPUT ((cofp, "/F-gs-font %g %g SF\n", Fpt.w, Fpt.h));
if (underlay != NULL)
{
OUTPUT ((cofp, "/ul_str (%s) def\n", underlay));
OUTPUT ((cofp, "/ul_w_ptsize %g def\n", ul_ptsize.w));
OUTPUT ((cofp, "/ul_h_ptsize %g def\n", ul_ptsize.h));
OUTPUT ((cofp, "/ul_gray %g def\n", ul_gray));
OUTPUT ((cofp, "/ul_x %g def\n", ul_x));
OUTPUT ((cofp, "/ul_y %g def\n", ul_y));
OUTPUT ((cofp, "/ul_angle %g def\n", ul_angle));
OUTPUT ((cofp, "/ul_style %d def\n", ul_style));
OUTPUT ((cofp, "/%s /F-ul-font MF\n", ul_font));
OUTPUT ((cofp, "/ul_font /F-ul-font findfont \
[ul_w_ptsize 0 0 ul_h_ptsize 0 0] makefont def\n"));
}
OUTPUT ((cofp, "/#copies %d def\n", num_copies));
if (page_prefeed)
OUTPUT ((cofp, "true page_prefeed\n"));
if (count_key_value_set (statusdict) > 0)
{
OUTPUT ((cofp, "%% Statustdict definitions:\nstatusdict begin\n "));
i = 2;
for (got = strhash_get_first (statusdict, &cp, &j, (void **) &cp2); got;
got = strhash_get_next (statusdict, &cp, &j, (void **) &cp2))
{
j = strlen (cp) + 1 + strlen (cp2) + 1;
if (i + j > RESOURCE_LINE_WIDTH)
{
OUTPUT ((cofp, "\n "));
i = 2;
}
OUTPUT ((cofp, "%s %s ", cp2, cp));
i += j;
}
OUTPUT ((cofp, "\nend\n"));
}
if (pslevel >= 2 &&
(count_key_value_set (pagedevice) > 0 || generate_PageSize))
{
OUTPUT ((cofp, "%% Pagedevice definitions:\n"));
OUTPUT ((cofp, "gs_languagelevel 1 gt {\n <<\n "));
i = 4;
for (got = strhash_get_first (pagedevice, &cp, &j, (void **) &cp2); got;
got = strhash_get_next (pagedevice, &cp, &j, (void **) &cp2))
{
j = strlen (cp2) + 1 + strlen (cp) + 2;
if (i + j > RESOURCE_LINE_WIDTH)
{
OUTPUT ((cofp, "\n "));
i = 4;
}
OUTPUT ((cofp, "/%s %s ", cp, cp2));
i += j;
}
if (generate_PageSize)
{
if (i + 21 > RESOURCE_LINE_WIDTH)
{
OUTPUT ((cofp, "\n "));
i = 4;
}
OUTPUT ((cofp, "/PageSize [%d %d] ", media->w, media->h));
i += 21;
}
OUTPUT ((cofp, "\n >> setpagedevice\n} if\n"));
}
if (header != HDR_NONE)
{
char *hdr;
if (header == HDR_SIMPLE)
hdr = "simple";
else
hdr = fancy_header_name;
OUTPUT ((cofp, "%%%%BeginResource: procset Enscript-Header-%s %s\n",
hdr, ps_version_string));
if (!paste_file (hdr, ".hdr"))
FATAL ((stderr,
_("couldn't find header definition file \"%s.hdr\": %s\n"),
hdr, strerror (errno)));
OUTPUT ((cofp, "%%%%EndResource\n"));
}
d_output_w = d_page_w;
d_output_h = d_page_h - d_header_h - d_footer_h;
OUTPUT ((cofp, "/d_page_w %d def\n", d_page_w));
OUTPUT ((cofp, "/d_page_h %d def\n", d_page_h));
OUTPUT ((cofp, "/d_header_x %d def\n", 0));
OUTPUT ((cofp, "/d_header_y %d def\n", d_output_h + d_footer_h));
OUTPUT ((cofp, "/d_header_w %d def\n", d_header_w));
OUTPUT ((cofp, "/d_header_h %d def\n", d_header_h));
OUTPUT ((cofp, "/d_footer_x %d def\n", 0));
OUTPUT ((cofp, "/d_footer_y %d def\n", 0));
OUTPUT ((cofp, "/d_footer_w %d def\n", d_header_w));
OUTPUT ((cofp, "/d_footer_h %d def\n", d_footer_h));
OUTPUT ((cofp, "/d_output_w %d def\n", d_output_w));
OUTPUT ((cofp, "/d_output_h %d def\n", d_output_h));
OUTPUT ((cofp, "/cols %d def\n", num_columns));
OUTPUT ((cofp, "%%%%EndSetup\n"));
}
void
dump_ps_trailer ()
{
int i, j, got;
char *cp;
void *value;
unsigned int nup_subpage;
if (!ps_header_dumped)
return;
nup_subpage = (total_pages - 1) % nup;
if (nup > 1 && nup_subpage + 1 != nup)
OUTPUT ((cofp, "_R\nS\n"));
OUTPUT ((cofp, "%%%%Trailer\n"));
if (page_prefeed)
OUTPUT ((cofp, "false page_prefeed\n"));
OUTPUT ((cofp, "%%%%Pages: %d\n", total_pages));
OUTPUT ((cofp, "%%%%DocumentNeededResources: font "));
i = 32;
for (got = strhash_get_first (res_fonts, &cp, &j, &value); got;
got = strhash_get_next (res_fonts, &cp, &j, &value))
{
if (i + strlen (cp) + 1 > RESOURCE_LINE_WIDTH)
{
OUTPUT ((cofp, "\n%%%%+ font "));
i = 9;
}
OUTPUT ((cofp, "%s ", cp));
i += strlen (cp) + 1;
}
OUTPUT ((cofp, "\n%%%%EOF\n"));
}
void
process_file (char *fname_arg, InputStream *is)
{
int col;
double x, y;
double lx, ly;
double linewidth;
double lineend;
int done = 0;
int page_clear = 1;
unsigned int line_column;
unsigned int current_linenum;
double linenumber_space = 0;
double linenumber_margin = 0;
Token token;
int reuse_last_token = 0;
unsigned int current_slice = 1;
int last_wrapped_line = -1;
int last_spaced_file_linenum = -1;
strcpy (fname, fname_arg);
current_pagenum = 0;
total_pages_in_file = 0;
current_file_linenum = start_line_number;
linenumber_space = CHAR_WIDTH ('0') * 5 + 1.0;
linenumber_margin = CHAR_WIDTH (':') + CHAR_WIDTH ('m');
input_filenum++;
print_line_number_last = (unsigned int) -1;
if (pass_through || output_language_pass_through)
if (do_pass_through (fname, is))
return;
dump_ps_header ();
while ((total_pages % file_align) != 0)
{
total_pages++;
dump_empty_page ();
}
MESSAGE (1, (stderr, _("processing file \"%s\"...\n"), fname));
linewidth = d_output_w / num_columns - 2 * d_output_x_margin
- line_indent;
divert ();
while (!done)
{
page_clear = 1;
for (col = 0; !done && col < num_columns; col++)
{
lx = x = col * d_output_w / (float) num_columns + d_output_x_margin
+ line_indent;
lineend = lx + linewidth;
ly = y = d_footer_h + d_output_h - d_output_y_margin - LINESKIP;
current_linenum = 0;
line_column = 0;
while (1)
{
if (line_numbers && line_column == 0
&& (current_file_linenum != last_spaced_file_linenum))
{
x += linenumber_space + linenumber_margin;
last_spaced_file_linenum = current_file_linenum;
}
if (!reuse_last_token)
get_next_token (is, lx, x, line_column, lineend, &token);
reuse_last_token = 0;
if (token.type == tEOF)
{
done = 1;
goto end_of_page;
}
if (page_clear)
{
PageRange *pr;
current_pagenum++;
total_pages_in_file++;
if (page_ranges == NULL)
do_print = 1;
else
{
do_print = 0;
for (pr = page_ranges; pr; pr = pr->next)
{
if (pr->odd || pr->even)
{
if ((pr->odd && (current_pagenum % 2) == 1)
|| (pr->even && (current_pagenum % 2) == 0))
{
do_print = 1;
break;
}
}
else
{
if (pr->start <= current_pagenum
&& current_pagenum <= pr->end)
{
do_print = 1;
break;
}
}
}
}
if (do_print)
total_pages++;
dump_ps_page_header (fname, 0);
page_clear = 0;
}
if (line_numbers && line_column == 0 && token.type != tFORMFEED)
print_line_number (lx, y, linenumber_space, linenumber_margin,
current_file_linenum);
if (line_column == 0 && line_highlight_gray < 1.0)
OUTPUT ((cofp, "%g %g %g %g %g line_highlight\n",
lx, (y - baselineskip
+ (font_bbox_lly * Fpt.h / UNITS_PER_POINT)),
linewidth, Fpt.h + baselineskip,
line_highlight_gray));
switch (token.type)
{
case tFORMFEED:
switch (formfeed_type)
{
case FORMFEED_COLUMN:
goto end_of_column;
break;
case FORMFEED_PAGE:
goto end_of_page;
break;
case FORMFEED_HCOLUMN:
{
int current_row;
current_row = (ly - y) / horizontal_column_height;
y = ly - (current_row + 1) * horizontal_column_height;
if (y < d_footer_h + d_output_y_margin)
goto end_of_column;
}
break;
}
break;
case tSTRING:
if (CORRECT_SLICE ())
{
if (bggray < 1.0)
{
OUTPUT ((cofp, "%g %g %g %g %g (%s) bgs\n", x, y,
Fpt.h + baselineskip,
baselineskip
- (font_bbox_lly * Fpt.h / UNITS_PER_POINT),
bggray,
token.u.str));
}
else
{
OUTPUT ((cofp, "%g %g M\n(%s) s\n", x, y,
token.u.str));
}
}
x = token.new_x;
line_column = token.new_col;
break;
case tCARRIAGE_RETURN:
x = col * d_output_w / (float) num_columns
+ d_output_x_margin + line_indent;
line_column = 0;
break;
case tNEWLINE:
case tWRAPPED_NEWLINE:
if (token.type == tNEWLINE)
{
current_file_linenum++;
current_slice = 1;
y -= LINESKIP;
}
else
{
current_slice++;
if (!slicing)
{
switch (mark_wrapped_lines_style)
{
case MWLS_NONE:
break;
case MWLS_PLUS:
OUTPUT ((cofp, "%g %g M (+) s\n", x, y));
break;
default:
OUTPUT ((cofp,
"%g %g %g %g %d wrapped_line_mark\n",
x, y, Fpt.w, Fpt.h,
mark_wrapped_lines_style));
break;
}
y -= LINESKIP;
}
if (!slicing || current_slice > slice)
if (current_file_linenum != last_wrapped_line)
{
if (do_print)
num_truncated_lines++;
last_wrapped_line = current_file_linenum;
}
}
current_linenum++;
if (current_linenum >= lines_per_page
|| y < d_footer_h + d_output_y_margin)
goto end_of_column;
x = col * d_output_w / (float) num_columns
+ d_output_x_margin + line_indent;
line_column = 0;
break;
case tEPSF:
if (token.flags & F_EPSF_ABSOLUTE_Y)
token.new_y = ly;
else
token.new_y = y;
token.new_y += token.u.epsf.y - token.u.epsf.h;
if (token.flags & F_EPSF_ABSOLUTE_X)
token.new_x = lx;
else
token.new_x = x;
token.new_x += token.u.epsf.x;
if (token.flags & F_EPSF_CENTER)
token.new_x = lx + (linewidth - token.u.epsf.w) / 2;
if (token.flags & F_EPSF_RIGHT)
token.new_x = lx + (linewidth - token.u.epsf.w);
if ((token.flags & F_EPSF_NO_CPOINT_UPDATE_Y) == 0
&& token.new_y < d_footer_h + d_output_y_margin)
{
if (current_linenum == 0)
{
MESSAGE (0, (stderr, _("EPS file \"%s\" is too \
large for page\n"),
token.u.epsf.filename));
}
else
{
reuse_last_token = 1;
goto end_of_column;
}
}
if (CORRECT_SLICE ())
paste_epsf (&token);
if (!(token.flags & F_EPSF_NO_CPOINT_UPDATE_Y))
y = token.new_y;
if (!(token.flags & F_EPSF_NO_CPOINT_UPDATE_X))
x = token.new_x + token.u.epsf.w;
if (y < d_footer_h + d_output_y_margin)
goto end_of_column;
break;
case tFONT:
if (line_column == 0)
{
double newh;
if (token.u.font.name[0] == '\0')
newh = default_Fpt.h;
else
newh = token.u.font.size.h;
if (newh != Fpt.h)
{
y -= (newh - Fpt.h);
}
}
MESSAGE (2, (stderr, "^@font="));
if (token.u.font.name[0] == '\0')
{
Fpt.w = default_Fpt.w;
Fpt.h = default_Fpt.h;
Fname = default_Fname;
OUTPUT ((cofp, "/F-gs-font %g %g SF\n", Fpt.w, Fpt.h));
user_fontp = 0;
}
else
{
strhash_put (res_fonts, token.u.font.name,
strlen (token.u.font.name) + 1,
NULL, NULL);
OUTPUT ((cofp, "/%s %g %g SUF\n", token.u.font.name,
token.u.font.size.w, token.u.font.size.h));
strcpy (user_font_name, token.u.font.name);
user_font_pt.w = token.u.font.size.w;
user_font_pt.h = token.u.font.size.h;
user_fontp = 1;
Fpt.w = user_font_pt.w;
Fpt.h = user_font_pt.h;
Fname = user_font_name;
}
MESSAGE (2, (stderr, "%s %g/%gpt\n", Fname, Fpt.w, Fpt.h));
read_font_info ();
if (y < d_footer_h + d_output_y_margin)
goto end_of_column;
break;
case tCOLOR:
MESSAGE (2, (stderr, "^@color{%f %f %f}\n",
token.u.color.r,
token.u.color.g,
token.u.color.b));
if (token.u.color.r == token.u.color.g
&& token.u.color.g == token.u.color.b
&& token.u.color.b == 0.0)
{
OUTPUT ((cofp, "0 setgray\n"));
user_colorp = 0;
}
else
{
OUTPUT ((cofp, "%g %g %g setrgbcolor\n",
token.u.color.r,
token.u.color.g,
token.u.color.b));
user_color.r = token.u.color.r;
user_color.g = token.u.color.g;
user_color.b = token.u.color.b;
user_colorp = 1;
}
break;
case tSETFILENAME:
strcpy (fname, token.u.filename);
break;
case tSETPAGENUMBER:
current_pagenum = token.u.i - 1;
break;
case tNEWPAGE:
if (current_linenum >= token.u.i)
goto end_of_page;
break;
case tPS:
OUTPUT ((cofp, "%g %g M\n%s\n", x, y, token.u.str));
xfree (token.u.str);
break;
case tNONE:
default:
FATAL ((stderr, "process_file(): got illegal token %d",
token.type));
break;
}
}
end_of_column:
;
}
end_of_page:
if (!page_clear)
dump_ps_page_trailer ();
}
do_print = 1;
undivert ();
if (toc)
{
char *cp;
cp = format_user_string ("TOC", toc_fmt_string);
fprintf (toc_fp, "%s\n", cp);
xfree (cp);
}
}
#define FITS_ON_LINE(ch) ((linepos + CHAR_WIDTH (ch) < linew) || col == 0)
#define BUFFER_EMPTY() (bufpos == 0)
#define APPEND_CHAR(ch) \
do { \
if (bufpos >= buflen) \
{ \
buflen += 4096; \
buffer = xrealloc (buffer, buflen); \
} \
buffer[bufpos++] = ch; \
} while (0)
#define EMIT(ch) \
do { \
APPEND_CHAR (ch); \
linepos += CHAR_WIDTH (ch); \
col++; \
} while (0)
#define UNEMIT(ch) \
do { \
linepos -= CHAR_WIDTH (ch); \
col--; \
} while (0)
#define ISSPACE(ch) ((ch) == ' ' || (ch) == '\t')
#define ISOCTAL(ch) ('0' <= (ch) && (ch) <= '7')
static struct
{
char *name;
SpecialEscape escape;
} escapes[] =
{
{"comment", ESC_COMMENT},
{"epsf", ESC_EPSF},
{"font", ESC_FONT},
{"color", ESC_COLOR},
{"newpage", ESC_NEWPAGE},
{"ps", ESC_PS},
{"setfilename", ESC_SETFILENAME},
{"setpagenumber", ESC_SETPAGENUMBER},
{"shade", ESC_SHADE},
{"bggray", ESC_BGGRAY},
{"escape", ESC_ESCAPE},
{NULL, 0},
};
static void
read_special_escape (InputStream *is, Token *token)
{
char escname[256];
char buf[4096];
int i, e;
int ch;
for (i = 0; i < sizeof (escname) - 1 && (ch = is_getc (is)) != EOF; i++)
{
if (!isalnum (ch))
{
is_ungetc (ch, is);
break;
}
else
escname[i] = ch;
}
escname[i] = '\0';
for (e = 0; escapes[e].name; e++)
if (strcmp (escname, escapes[e].name) == 0)
break;
if (escapes[e].name == NULL)
FATAL ((stderr, _("unknown special escape: %s"), escname));
if (escapes[e].escape == ESC_EPSF)
{
int i;
int pw, ph;
double scale;
token->flags = 0;
token->u.epsf.x = 0.0;
token->u.epsf.y = 0.0;
token->u.epsf.h = 0.0;
token->u.epsf.pipe = 0;
ch = is_getc (is);
if (ch == '[')
{
while ((ch = is_getc (is)) != EOF && ch != ']')
{
switch (ch)
{
case 'c':
token->flags &= ~M_EPSF_JUSTIFICATION;
token->flags |= F_EPSF_CENTER;
break;
case 'n':
ch = is_getc (is);
switch (ch)
{
case 'x':
token->flags |= F_EPSF_NO_CPOINT_UPDATE_X;
break;
case 'y':
token->flags |= F_EPSF_NO_CPOINT_UPDATE_Y;
break;
default:
is_ungetc (ch, is);
token->flags |= F_EPSF_NO_CPOINT_UPDATE_X;
token->flags |= F_EPSF_NO_CPOINT_UPDATE_Y;
break;
}
break;
case 'r':
token->flags &= ~M_EPSF_JUSTIFICATION;
token->flags |= F_EPSF_RIGHT;
break;
case 's':
ch = is_getc (is);
switch (ch)
{
case 'x':
token->flags |= F_EPSF_SCALE_X;
token->u.epsf.xscale = read_float (is, 0, 1);
break;
case 'y':
token->flags |= F_EPSF_SCALE_Y;
token->u.epsf.yscale = read_float (is, 0, 0);
break;
default:
is_ungetc (ch, is);
token->flags |= F_EPSF_SCALE_X;
token->flags |= F_EPSF_SCALE_Y;
token->u.epsf.xscale = token->u.epsf.yscale
= read_float (is, 0, 1);
break;
}
break;
case 'x':
token->u.epsf.x = read_float (is, 1, 1);
ch = is_getc (is);
switch (ch)
{
case 'a':
token->flags |= F_EPSF_ABSOLUTE_X;
break;
default:
is_ungetc (ch, is);
break;
}
break;
case 'y':
token->u.epsf.y = - read_float (is, 1, 0);
ch = is_getc (is);
switch (ch)
{
case 'a':
token->flags |= F_EPSF_ABSOLUTE_Y;
break;
default:
is_ungetc (ch, is);
break;
}
break;
case 'h':
token->u.epsf.h = read_float (is, 1, 0);
break;
case ' ':
case '\t':
break;
default:
FATAL ((stderr, _("illegal option %c for ^@epsf escape"),
ch));
}
}
if (ch != ']')
FATAL ((stderr,
_("malformed ^@epsf escape: no ']' after options")));
ch = is_getc (is);
}
if (ch == '{')
{
for (i = 0; (ch = is_getc (is)) != EOF && ch != '}'; i++)
{
token->u.epsf.filename[i] = ch;
if (i + 1 >= sizeof (token->u.epsf.filename))
FATAL ((stderr,
_("too long file name for ^@epsf escape:\n%.*s"),
i, token->u.epsf.filename));
}
if (ch == EOF)
FATAL ((stderr, _("unexpected EOF while scanning ^@epsf escape")));
token->u.epsf.filename[i] = '\0';
token->type = tEPSF;
}
else
FATAL ((stderr, _("malformed ^@epsf escape: no '{' found")));
if (!recognize_eps_file (token))
token->type = tNONE;
else
{
token->u.epsf.y += LINESKIP - 1;
if (token->u.epsf.h != 0.0)
token->u.epsf.h -= 1.0;
pw = token->u.epsf.urx - token->u.epsf.llx;
ph = token->u.epsf.ury - token->u.epsf.lly;
if (token->u.epsf.h == 0.0)
scale = 1.0;
else
scale = token->u.epsf.h / ph;
if ((token->flags & F_EPSF_SCALE_X) == 0)
token->u.epsf.xscale = scale;
if ((token->flags & F_EPSF_SCALE_Y) == 0)
token->u.epsf.yscale = scale;
pw *= token->u.epsf.xscale;
ph *= token->u.epsf.yscale;
token->u.epsf.w = pw;
token->u.epsf.h = ph;
}
}
else if (escapes[e].escape == ESC_COMMENT)
{
while ((ch = is_getc (is)) != EOF && ch != nl)
;
token->type = tNONE;
}
else
{
char *cp;
int parenlevel;
ch = is_getc (is);
if (ch != '{')
FATAL ((stderr, _("malformed %s escape: no '{' found"),
escapes[e].name));
parenlevel = 0;
for (i = 0;
(ch = is_getc (is)) != EOF && (parenlevel > 0 || ch != '}'); i++)
{
if (ch == '{')
parenlevel++;
else if (ch == '}')
parenlevel--;
buf[i] = ch;
if (i + 1 >= sizeof (buf))
FATAL ((stderr, _("too long argument for %s escape:\n%.*s"),
escapes[i].name, i, buf));
}
buf[i] = '\0';
switch (escapes[e].escape)
{
case ESC_FONT:
strcpy (token->u.font.name, buf);
if (strcmp (token->u.font.name, "default") == 0)
token->u.font.name[0] = '\0';
else
{
if (!parse_font_spec (token->u.font.name, &cp,
&token->u.font.size))
FATAL ((stderr, _("malformed font spec for ^@font escape: %s"),
token->u.font.name));
strcpy (token->u.font.name, cp);
xfree (cp);
}
token->type = tFONT;
break;
case ESC_COLOR:
if (strcmp (buf, "default") == 0)
{
token->u.color.r = 0;
token->u.color.g = 0;
token->u.color.b = 0;
}
else
{
int got;
got = sscanf (buf, "%g %g %g",
&token->u.color.r,
&token->u.color.g,
&token->u.color.b);
switch (got)
{
case 0:
case 2:
FATAL ((stderr,
_("malformed color spec for ^@color escape: %s"),
buf));
break;
case 1:
token->u.color.g = token->u.color.b = token->u.color.r;
break;
default:
break;
}
}
token->type = tCOLOR;
break;
case ESC_SHADE:
line_highlight_gray = atof (buf);
if (line_highlight_gray < 0.0 || line_highlight_gray > 1.0)
FATAL ((stderr, _("invalid value for ^@shade escape: %s"), buf));
token->type = tNONE;
break;
case ESC_BGGRAY:
bggray = atof (buf);
if (bggray < 0.0 || bggray > 1.0)
FATAL ((stderr, _("invalid value for ^@bggray escape: %s"), buf));
token->type = tNONE;
break;
case ESC_ESCAPE:
if (strcmp (buf, "default") == 0)
escape_char = default_escape_char;
else
escape_char = atoi (buf);
token->type = tNONE;
break;
case ESC_SETFILENAME:
strcpy (token->u.filename, buf);
token->type = tSETFILENAME;
break;
case ESC_SETPAGENUMBER:
token->u.i = atoi (buf);
token->type = tSETPAGENUMBER;
break;
case ESC_NEWPAGE:
if (i == 0)
token->u.i = 1;
else
token->u.i = atoi (buf);
token->type = tNEWPAGE;
break;
case ESC_PS:
token->u.str = xstrdup (buf);
token->type = tPS;
break;
default:
abort ();
break;
}
}
}
static void
get_next_token (InputStream *is, double linestart, double linepos,
unsigned int col, double linew, Token *token)
{
static unsigned char *buffer = NULL;
static unsigned int buflen = 0;
unsigned int bufpos = 0;
int ch = 0;
int done = 0;
int i;
static int pending_token = tNONE;
unsigned int original_col = col;
if (pending_token != tNONE)
{
token->type = pending_token;
pending_token = tNONE;
return;
}
#define DONE_DONE 1
#define DONE_WRAP 2
while (!done)
{
ch = is_getc (is);
switch (ch)
{
case EOF:
if (BUFFER_EMPTY ())
{
token->type = tEOF;
return;
}
done = DONE_DONE;
break;
case '\r':
case '\n':
if (ch == nl)
{
if (BUFFER_EMPTY ())
{
token->type = tNEWLINE;
return;
}
else
{
is_ungetc (ch, is);
done = DONE_DONE;
}
}
else
{
if (BUFFER_EMPTY ())
{
token->type = tCARRIAGE_RETURN;
return;
}
else
{
is_ungetc (ch, is);
done = DONE_DONE;
}
}
break;
case '\t':
if (font_is_fixed)
{
i = tabsize - (col % tabsize);
for (; i > 0; i--)
{
if (FITS_ON_LINE (' '))
EMIT (' ');
else
{
done = DONE_WRAP;
break;
}
}
}
else
{
double grid = tabsize * CHAR_WIDTH (' ');
col++;
linepos = (((int) ((linepos - linestart) / grid) + 1) * grid
+ linestart);
if (linepos >= linew)
done = DONE_WRAP;
else
done = DONE_DONE;
}
break;
case '\f':
if (BUFFER_EMPTY ())
{
if (interpret_formfeed)
token->type = tFORMFEED;
else
token->type = tNEWLINE;
return;
}
else
{
is_ungetc (ch, is);
done = DONE_DONE;
}
break;
default:
if (special_escapes && ch == escape_char)
{
if (BUFFER_EMPTY ())
{
read_special_escape (is, token);
if (token->type != tNONE)
return;
break;
}
else
{
is_ungetc (ch, is);
done = DONE_DONE;
break;
}
}
if (ch == bs)
{
if (BUFFER_EMPTY () || !EXISTS (buffer[bufpos - 1]))
linepos -= CHAR_WIDTH ('m');
else
linepos -= CHAR_WIDTH (buffer[bufpos - 1]);
done = DONE_DONE;
break;
}
if (EXISTS (ch))
{
if (FITS_ON_LINE (ch))
{
if (ch < 040 || (clean_7bit && ch >= 0200))
{
char buf[10];
sprintf (buf, "\\%03o", ch);
for (i = 0; buf[i]; i++)
APPEND_CHAR (buf[i]);
linepos += CHAR_WIDTH (ch);
col++;
}
else if (ch == '(' || ch == ')' || ch == '\\')
{
APPEND_CHAR ('\\');
EMIT (ch);
}
else
EMIT (ch);
}
else
{
is_ungetc (ch, is);
done = DONE_WRAP;
}
}
else if (ISPRINT (ch))
{
if (FITS_ON_LINE ('?'))
{
EMIT ('?');
if (missing_chars[ch]++ == 0)
num_missing_chars++;
}
else
{
is_ungetc (ch, is);
done = DONE_WRAP;
}
}
else
{
char buf[20];
double len = 0.0;
if (non_printable_chars[ch]++ == 0)
num_non_printable_chars++;
switch (non_printable_format)
{
case NPF_SPACE:
strcpy (buf, " ");
break;
case NPF_QUESTIONMARK:
strcpy (buf, "?");
break;
case NPF_CARET:
if (ch < 0x20)
{
buf[0] = '^';
buf[1] = '@' + ch;
buf[2] = '\0';
break;
}
case NPF_OCTAL:
sprintf (buf, "\\%03o", ch);
break;
}
for (i = 0; buf[i]; i++)
len += CHAR_WIDTH (buf[i]);
if (linepos + len < linew || col == 0)
{
for (i = 0; buf[i]; i++)
{
if (buf[i] == '\\')
APPEND_CHAR ('\\');
EMIT (buf[i]);
}
}
else
{
is_ungetc (ch, is);
done = DONE_WRAP;
}
}
break;
}
}
if (done == DONE_WRAP)
{
ch = nl;
if (line_end == LE_TRUNCATE)
{
while ((ch = is_getc (is)) != EOF && ch != nl)
;
}
else if (!BUFFER_EMPTY () && line_end == LE_WORD_WRAP)
{
int w;
if (ISSPACE (buffer[bufpos - 1]))
{
while ((w = is_getc (is)) != EOF && ISSPACE (w))
;
is_ungetc (w, is);
}
else
{
for (w = bufpos - 1; w >= 0 && !ISSPACE (buffer[w]); w--)
;
w++;
if (w > 0 || original_col > 0)
{
do
{
bufpos--;
if (bufpos > w
&& (buffer[bufpos] == '('
|| buffer[bufpos] == ')'
|| buffer[bufpos] == '\\')
&& buffer[bufpos - 1] == '\\')
{
is_ungetc (buffer[bufpos], is);
UNEMIT (buffer[bufpos]);
bufpos--;
}
else if (bufpos - 2 > w
&& ISOCTAL (buffer[bufpos])
&& ISOCTAL (buffer[bufpos - 1])
&& ISOCTAL (buffer[bufpos - 2])
&& buffer[bufpos - 3] == '\\')
{
unsigned int ti;
for (ti = w; ti < bufpos - 3; ti++)
{
if (buffer[ti] == '\\')
{
if (ISOCTAL (buffer[ti + 1]))
{
unsigned int tti;
for (tti = 0;
tti < 3 && ISOCTAL (buffer[ti + 1]);
tti++, ti++)
;
}
else
ti++;
}
}
if (ti == bufpos - 3)
{
int tch;
tch = (((buffer[bufpos - 2] - '0') << 6)
+ ((buffer[bufpos - 1] - '0') << 3)
+ (buffer[bufpos] - '0'));
is_ungetc (tch, is);
UNEMIT (tch);
bufpos -= 3;
}
else
goto unemit_normal;
}
else
{
unemit_normal:
is_ungetc (buffer[bufpos], is);
UNEMIT (buffer[bufpos]);
}
}
while (bufpos > w);
}
}
}
if (ch == nl)
{
if (line_end == LE_TRUNCATE)
{
if (do_print)
num_truncated_lines++;
pending_token = tNEWLINE;
}
else
pending_token = tWRAPPED_NEWLINE;
}
else
pending_token = tEOF;
}
APPEND_CHAR ('\0');
token->type = tSTRING;
token->u.str = (char *) buffer;
token->new_x = linepos;
token->new_col = col;
}
static void
dump_ps_page_header (char *fname, int empty)
{
char buf[512];
char *ftail;
int got, i;
char *cp, *cp2;
char *cstr = "%%";
unsigned int nup_subpage;
nup_subpage = (total_pages - 1) % nup;
ftail = strrchr (fname, '/');
#if defined(WIN32)
if (ftail == NULL)
ftail = strrchr (fname, '\\');
#endif
if (ftail == NULL)
{
buf[0] = '\0';
ftail = fname;
}
else
{
ftail++;
strncpy (buf, fname, ftail - fname);
buf[ftail - fname] = '\0';
}
if (nup > 1)
{
cstr = "%";
if (nup_subpage == 0)
{
switch (page_label)
{
case LABEL_SHORT:
OUTPUT ((cofp, "%%%%Page: (%d-%d) %d\n", current_pagenum,
current_pagenum + nup - 1, total_pages / nup + 1));
break;
case LABEL_LONG:
OUTPUT ((cofp, "%%%%Page: (%s:%3d-%3d) %d\n", ftail,
current_pagenum, current_pagenum + nup - 1,
total_pages / nup + 1));
break;
}
OUTPUT ((cofp, "%%%%BeginPageSetup\n_S\n"));
if ((total_pages / nup + 1) % 2 == 0)
handle_two_side_options ();
#define PRINT_BOUNDING_BOXES 0
#if PRINT_BOUNDING_BOXES
OUTPUT ((cofp,
"%d %d moveto %d %d lineto %d %d lineto %d %d lineto closepath stroke\n",
media->llx, media->lly, media->llx, media->ury,
media->urx, media->ury, media->urx, media->lly));
#endif
if (landscape)
{
if (nup_landscape)
OUTPUT ((cofp, "90 rotate\n%d %d translate\n",
media->lly, -media->urx));
else
OUTPUT ((cofp, "%d %d translate\n", media->llx, media->lly));
}
else
{
if (nup_landscape)
OUTPUT ((cofp, "90 rotate\n%d %d translate\n",
media->lly, -media->llx));
else
OUTPUT ((cofp, "%d %d translate\n", media->llx, media->ury));
}
}
}
switch (page_label)
{
case LABEL_SHORT:
OUTPUT ((cofp, "%sPage: (%d) %d\n", cstr, current_pagenum, total_pages));
break;
case LABEL_LONG:
OUTPUT ((cofp, "%sPage: (%s:%3d) %d\n", cstr, ftail, current_pagenum,
total_pages));
break;
}
OUTPUT ((cofp, "%sBeginPageSetup\n_S\n", cstr));
if (nup > 1)
{
int xm, ym;
OUTPUT ((cofp, "%% N-up sub-page %d/%d\n", nup_subpage + 1, nup));
if (landscape)
{
xm = nup_subpage / nup_rows;
ym = nup_subpage % nup_rows;
OUTPUT ((cofp, "%d %d translate\n",
xm * (nup_width + nup_xpad),
ym * (nup_height + nup_ypad)));
}
else
{
xm = nup_subpage % nup_columns;
ym = nup_subpage / nup_columns;
OUTPUT ((cofp, "%d %d translate\n",
xm * (nup_width + nup_xpad),
-(ym * (nup_height + nup_ypad) + nup_height)));
}
OUTPUT ((cofp, "%g dup scale\n", nup_scale));
if (landscape)
OUTPUT ((cofp, "90 rotate\n%d %d translate\n", 0, -d_page_h));
}
else
{
if (total_pages % 2 == 0)
handle_two_side_options ();
if (landscape)
OUTPUT ((cofp, "90 rotate\n%d %d translate\n",
media->lly, -media->urx));
else
OUTPUT ((cofp, "%d %d translate\n", media->llx, media->lly));
}
OUTPUT ((cofp, "/pagenum %d def\n", current_pagenum));
cp = escape_string (fname);
OUTPUT ((cofp, "/fname (%s) def\n", cp));
xfree (cp);
cp = escape_string (buf);
OUTPUT ((cofp, "/fdir (%s) def\n", cp));
xfree (cp);
cp = escape_string (ftail);
OUTPUT ((cofp, "/ftail (%s) def\n", cp));
xfree (cp);
if (user_fontp)
OUTPUT ((cofp, "/%s %g %g SUF\n", Fname, Fpt.w, Fpt.h));
if (count_key_value_set (user_strings) > 0)
{
OUTPUT ((cofp, "%% User defined strings:\n"));
for (got = strhash_get_first (user_strings, &cp, &i, (void **) &cp2);
got;
got = strhash_get_next (user_strings, &cp, &i, (void **) &cp2))
{
cp2 = format_user_string ("%Format", cp2);
OUTPUT ((cofp, "/%s (%s) def\n", cp, cp2));
xfree (cp2);
}
}
if (page_header)
{
char *h_left;
char *h_center;
char *h_right = NULL;
h_left = format_user_string ("page header", page_header);
h_center = strchr (h_left, '|');
if (h_center)
{
*h_center = '\0';
h_center++;
h_right = strchr (h_center, '|');
if (h_right)
{
*h_right = '\0';
h_right++;
}
}
OUTPUT ((cofp, "/user_header_p true def\n"));
OUTPUT ((cofp, "/user_header_left_str (%s) def\n", h_left));
OUTPUT ((cofp, "/user_header_center_str (%s) def\n",
h_center ? h_center : ""));
OUTPUT ((cofp, "/user_header_right_str (%s) def\n",
h_right ? h_right : ""));
xfree (h_left);
}
else
OUTPUT ((cofp, "/user_header_p false def\n"));
OUTPUT ((cofp, "%%%%EndPageSetup\n"));
if (!empty)
{
if (highlight_bars)
OUTPUT ((cofp, "%d %f %d %f highlight_bars\n", highlight_bars,
LINESKIP, d_output_y_margin, highlight_bar_gray));
if (underlay != NULL)
{
if (ul_position_p || ul_angle_p)
OUTPUT ((cofp, "user_underlay\n"));
else
OUTPUT ((cofp, "underlay\n"));
}
if (num_columns > 1 && (header == HDR_FANCY || borders))
OUTPUT ((cofp, "column_lines\n"));
if (borders)
OUTPUT ((cofp, "column_borders\n"));
switch (header)
{
case HDR_NONE:
break;
case HDR_SIMPLE:
case HDR_FANCY:
OUTPUT ((cofp, "do_header\n"));
break;
}
}
if (user_colorp)
OUTPUT ((cofp, "%g %g %g setrgbcolor\n", user_color.r, user_color.g,
user_color.b));
}
static void
dump_ps_page_trailer ()
{
unsigned int nup_subpage = (total_pages - 1) % nup;
OUTPUT ((cofp, "_R\n"));
if (nup > 1)
{
if (nup_subpage + 1 == nup)
OUTPUT ((cofp, "_R\nS\n"));
}
else
OUTPUT ((cofp, "S\n"));
}
static void
dump_empty_page ()
{
if (nup > 1)
{
unsigned int nup_subpage = (total_pages - 1) % nup;
if (nup_subpage == 0)
{
dump_ps_page_header ("", 1);
OUTPUT ((cofp, "_R\n"));
}
else
OUTPUT ((cofp, "%%Page: (-) %d\n", total_pages));
if (nup_subpage + 1 == nup)
OUTPUT ((cofp, "_R\nS\n"));
}
else
OUTPUT ((cofp, "%%%%Page: (-) %d\nS\n", total_pages));
}
static int
recognize_eps_file (Token *token)
{
int i;
char filename[512];
char buf[4096];
int line;
int valid_epsf;
float llx, lly, urx, ury;
MESSAGE (2, (stderr, "^@epsf=\"%s\"\n", token->u.epsf.filename));
i = strlen (token->u.epsf.filename);
if (i > 0 && token->u.epsf.filename[i - 1] == '|')
{
token->u.epsf.pipe = 1;
token->u.epsf.filename[i - 1] = '\0';
token->u.epsf.fp = popen (token->u.epsf.filename, "r");
if (token->u.epsf.fp == NULL)
{
MESSAGE (0, (stderr,
_("epsf: couldn't open pipe to command \"%s\": %s\n"),
token->u.epsf.filename, strerror (errno)));
return 0;
}
}
else
{
tilde_subst (token->u.epsf.filename, filename);
token->u.epsf.fp = fopen (filename, "rb");
if (token->u.epsf.fp == NULL)
{
if (token->u.epsf.filename[0] != '/')
{
FileLookupCtx ctx;
strcpy (ctx.name, token->u.epsf.filename);
strcpy (ctx.suffix, "");
if (pathwalk (libpath, file_lookup, &ctx))
token->u.epsf.fp = fopen (ctx.fullname, "rb");
}
if (token->u.epsf.fp == NULL)
{
MESSAGE (0, (stderr, _("couldn't open EPS file \"%s\": %s\n"),
token->u.epsf.filename, strerror (errno)));
return 0;
}
}
}
line = 0;
valid_epsf = 0;
token->u.epsf.skipbuf = NULL;
token->u.epsf.skipbuf_len = 0;
token->u.epsf.skipbuf_pos = 0;
while (fgets (buf, sizeof (buf), token->u.epsf.fp))
{
line++;
i = strlen (buf);
if (i + token->u.epsf.skipbuf_pos >= token->u.epsf.skipbuf_len)
{
token->u.epsf.skipbuf_len += 8192;
token->u.epsf.skipbuf = xrealloc (token->u.epsf.skipbuf,
token->u.epsf.skipbuf_len);
}
memcpy (token->u.epsf.skipbuf + token->u.epsf.skipbuf_pos, buf, i);
token->u.epsf.skipbuf_pos += i;
if (line == 1)
{
if (buf[0] != '%' || buf[1] != '!')
{
MESSAGE (0,
(stderr,
_("EPS file \"%s\" does not start with \"%%!\" magic\n"),
token->u.epsf.filename));
break;
}
}
#define BB_DSC "%%BoundingBox:"
if (strncmp (buf, BB_DSC, strlen (BB_DSC)) == 0)
{
i = sscanf (buf + strlen (BB_DSC), "%f %f %f %f",
&llx, &lly, &urx, &ury);
if (i != 4)
{
for (i = strlen (BB_DSC);
buf[i] && (buf[i] == ' ' || buf[i] == '\t');
i++)
;
#define BB_DSC_ATEND "(atend)"
if (strncmp (buf + i, BB_DSC_ATEND, strlen (BB_DSC_ATEND)) != 0)
{
MESSAGE (0, (stderr, _("EPS file \"%s\" contains malformed \
%%%%BoundingBox row:\n\"%.*s\"\n"),
token->u.epsf.filename, strlen (buf) - 1, buf));
break;
}
}
else
{
token->u.epsf.llx = llx;
token->u.epsf.lly = lly;
token->u.epsf.urx = urx;
token->u.epsf.ury = ury;
valid_epsf = 1;
break;
}
}
}
if (!valid_epsf)
{
MESSAGE (0, (stderr, _("EPS file \"%s\" is not a valid EPS file\n"),
token->u.epsf.filename));
if (token->u.epsf.pipe)
pclose (token->u.epsf.fp);
else
fclose (token->u.epsf.fp);
xfree (token->u.epsf.skipbuf);
return 0;
}
MESSAGE (2, (stderr, "BoundingBox: %d %d %d %d\n",
token->u.epsf.llx, token->u.epsf.lly,
token->u.epsf.urx, token->u.epsf.ury));
return 1;
}
static void
paste_epsf (Token *token)
{
char buf[4096];
int i;
OUTPUT ((cofp, "BeginEPSF\n"));
OUTPUT ((cofp, "%g %g translate\n", token->new_x, token->new_y));
OUTPUT ((cofp, "%g %g scale\n", token->u.epsf.xscale, token->u.epsf.yscale));
OUTPUT ((cofp, "%d %d translate\n", -token->u.epsf.llx,
-token->u.epsf.lly));
OUTPUT ((cofp, "%d %d %d %d Box clip newpath\n",
token->u.epsf.llx - 1,
token->u.epsf.lly - 1,
token->u.epsf.urx - token->u.epsf.llx + 2,
token->u.epsf.ury - token->u.epsf.lly + 2));
OUTPUT ((cofp, "%%%%BeginDocument: %s%s\n", token->u.epsf.filename,
token->u.epsf.pipe ? "|" : ""));
if (do_print)
{
fwrite (token->u.epsf.skipbuf, 1, token->u.epsf.skipbuf_pos, cofp);
while ((i = fread (buf, 1, sizeof (buf), token->u.epsf.fp)) != 0)
fwrite (buf, 1, i, cofp);
}
OUTPUT ((cofp, "\n"));
OUTPUT ((cofp, "%%%%EndDocument\nEndEPSF\n"));
if (token->u.epsf.pipe)
pclose (token->u.epsf.fp);
else
fclose (token->u.epsf.fp);
xfree (token->u.epsf.skipbuf);
}
static double
read_float (InputStream *is, int units, int horizontal)
{
char buf[256];
int i, ch;
double val;
for (i = 0; (i < sizeof (buf) - 1
&& (ch = is_getc (is)) != EOF
&& ISNUMBERDIGIT (ch));
i++)
buf[i] = ch;
buf[i] = '\0';
if (ch != EOF)
is_ungetc (ch, is);
val = atof (buf);
if (units)
{
ch = is_getc (is);
switch (ch)
{
case 'c':
val *= 72 / 2.54;
break;
case 'p':
break;
case 'i':
val *= 72;
break;
default:
is_ungetc (ch, is);
case 'l':
if (horizontal)
val *= CHAR_WIDTH ('m');
else
val *= LINESKIP;
break;
}
}
return val;
}
static struct
{
char *magic;
unsigned int magiclen;
char *name;
int revert_delta;
} pass_through_magics[] =
{
{"%!", 2, "PostScript", -2},
{"\004%!", 3, "PostScript", -2},
{"\033E", 2, "PCL", -2},
{"\033%", 2, "PCL", -2},
{NULL, 0, NULL, 0},
};
static int
do_pass_through (char *fname, InputStream *is)
{
int ch;
unsigned long saved_pos = is->bufpos;
int i, j;
if (output_language_pass_through)
MESSAGE (1,
(stderr,
_("passing through all input files for output language `%s'\n"),
output_language));
else
{
for (i = 0; pass_through_magics[i].magic; i++)
{
for (j = 0; j < pass_through_magics[i].magiclen; j++)
{
ch = is_getc (is);
if (ch == EOF
|| ch != (unsigned char) pass_through_magics[i].magic[j])
break;
}
if (j >= pass_through_magics[i].magiclen)
break;
is->bufpos = saved_pos;
}
if (pass_through_magics[i].magic == NULL)
return 0;
is->bufpos += pass_through_magics[i].revert_delta;
if (ps_header_dumped)
{
OUTPUT ((cofp,
"%%%%Page: (%s) -1\n_S\n%%%%BeginDocument: %s\n",
fname, fname));
}
MESSAGE (1, (stderr, _("passing through %s file \"%s\"\n"),
pass_through_magics[i].name, fname));
}
do
{
fwrite (is->buf + is->bufpos, 1, is->data_in_buf - is->bufpos, ofp);
is->bufpos = is->data_in_buf;
ch = is_getc (is);
is->bufpos = 0;
}
while (ch != EOF);
if (!output_language_pass_through)
{
if (ps_header_dumped)
OUTPUT ((cofp, "%%%%EndDocument\n_R\n"));
}
return 1;
}
static void
print_line_number (double x, double y, double space, double margin,
unsigned int linenum)
{
double len = 0.0;
char buf[20];
int i;
char *saved_Fname = "";
FontPoint saved_Fpt;
saved_Fpt.w = 0.0;
saved_Fpt.h = 0.0;
if (linenum == print_line_number_last)
return;
print_line_number_last = linenum;
if (user_fontp)
{
saved_Fname = Fname;
saved_Fpt.w = Fpt.w;
saved_Fpt.h = Fpt.h;
Fname = default_Fname;
Fpt.w = default_Fpt.w;
Fpt.h = default_Fpt.h;
OUTPUT ((cofp, "/F-gs-font %g %g SF\n", Fpt.w, Fpt.h));
read_font_info ();
}
sprintf (buf, "%d", linenum);
for (i = 0; buf[i]; i++)
len += CHAR_WIDTH (buf[i]);
OUTPUT ((cofp, "%g %g M (%s:) s\n", x + space - len, y, buf));
if (user_fontp)
{
Fname = saved_Fname;
Fpt.w = saved_Fpt.w;
Fpt.h = saved_Fpt.h;
OUTPUT ((cofp, "/%s %g %g SUF\n", Fname, Fpt.w, Fpt.h));
read_font_info ();
}
}
static char divertfname[512];
static void
divert ()
{
char *cp;
assert (divertfp == NULL);
cp = tempnam (NULL, "ens");
if (cp == NULL)
FATAL ((stderr, _("couldn't create divert file name: %s"),
strerror (errno)));
strcpy (divertfname, cp);
divertfp = fopen (divertfname, "w+b");
if (divertfp == NULL)
FATAL ((stderr, _("couldn't create divert file \"%s\": %s"), divertfname,
strerror (errno)));
if (remove (divertfname) == 0)
divertfname[0] = '\0';
free (cp);
cofp = divertfp;
}
static void
undivert ()
{
char buf[1024];
int doc_level = 0;
char *cp;
assert (divertfp != NULL);
if (fseek (divertfp, 0, SEEK_SET) != 0)
FATAL ((stderr, _("couldn't rewind divert file: %s"), strerror (errno)));
while (fgets (buf, sizeof (buf), divertfp))
{
if (strncmp (buf, "%%BeginDocument", 15) == 0)
doc_level++;
else if (strncmp (buf, "%%EndDocument", 13) == 0)
doc_level--;
if (doc_level == 0)
{
if (strncmp (buf, "% User defined strings", 22) == 0)
{
fputs (buf, ofp);
while (fgets (buf, sizeof (buf), divertfp))
{
if (strncmp (buf, "%%EndPageSetup", 14) == 0)
break;
cp = strchr (buf, '\001');
if (cp)
{
*cp = '\0';
fputs (buf, ofp);
fprintf (ofp, "%d", total_pages_in_file);
fputs (cp + 1, ofp);
}
else
fputs (buf, ofp);
}
}
}
fputs (buf, ofp);
}
fclose (divertfp);
divertfp = NULL;
if (divertfname[0])
(void) remove (divertfname);
cofp = ofp;
}
static void
handle_two_side_options ()
{
if (rotate_even_pages)
OUTPUT ((cofp, "180 rotate\n%d %d translate\n",
-media->w, -media->h));
}