(file) Return to psgen.c CVS log (file) (dir) Up to [RizwankCVS] / testProject / source / src

   1 rizwank 1.1 /*
   2              * Convert ASCII to PostScript.
   3              * Copyright (c) 1995-2002 Markku Rossi.
   4              *
   5              * Author: Markku Rossi <mtr@iki.fi>
   6              */
   7             
   8             /*
   9              * This file is part of GNU enscript.
  10              *
  11              * This program is free software; you can redistribute it and/or modify
  12              * it under the terms of the GNU General Public License as published by
  13              * the Free Software Foundation; either version 2, or (at your option)
  14              * any later version.
  15              *
  16              * This program is distributed in the hope that it will be useful,
  17              * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18              * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19              * GNU General Public License for more details.
  20              *
  21              * You should have received a copy of the GNU General Public License
  22 rizwank 1.1  * along with this program; see the file COPYING.  If not, write to
  23              * the Free Software Foundation, 59 Temple Place - Suite 330,
  24              * Boston, MA 02111-1307, USA.
  25              */
  26             
  27             #include "gsint.h"
  28             
  29             /*
  30              * Types and definitions.
  31              */
  32             
  33             /* Values for token flags. */
  34             
  35             /* EPSF. */
  36             #define F_EPSF_CENTER			0x01
  37             #define F_EPSF_RIGHT			0x02
  38             #define M_EPSF_JUSTIFICATION		0x03
  39             
  40             #define F_EPSF_NO_CPOINT_UPDATE_X	0x04
  41             #define F_EPSF_NO_CPOINT_UPDATE_Y	0x08
  42             
  43 rizwank 1.1 #define F_EPSF_ABSOLUTE_X		0x10
  44             #define F_EPSF_ABSOLUTE_Y		0x20
  45             
  46             #define F_EPSF_SCALE_X			0x40
  47             #define F_EPSF_SCALE_Y			0x80
  48             
  49             
  50             /* Predicate to check if we are at the correct slice. */
  51             #define CORRECT_SLICE() (slicing == 0 || current_slice == slice)
  52             
  53             /* Predicates for the current body font. */
  54             
  55             /* Is character <ch> printable. */
  56             #define ISPRINT(ch) (font_ctype[(unsigned char) (ch)] != ' ')
  57             
  58             /* Does character <ch> exist in current body font? */
  59             #define EXISTS(ch) (font_ctype[(unsigned char) (ch)] == '*')
  60             
  61             
  62             #define RESOURCE_LINE_WIDTH 75
  63             
  64 rizwank 1.1 /* Token types. */
  65             typedef enum
  66             {
  67               tNONE,
  68               tEOF,
  69               tSTRING,
  70               tFORMFEED,
  71               tNEWLINE,
  72               tCARRIAGE_RETURN,
  73               tWRAPPED_NEWLINE,
  74               tEPSF,
  75               tSETFILENAME,
  76               tSETPAGENUMBER,
  77               tNEWPAGE,
  78               tFONT,
  79               tCOLOR,
  80               tBGCOLOR,
  81               tSAVEX,
  82               tLOADX,
  83               tPS
  84             } TokenType;
  85 rizwank 1.1 
  86             /* Special escape tokens. */
  87             typedef enum
  88             {
  89               ESC_COMMENT,
  90               ESC_EPSF,
  91               ESC_FONT,
  92               ESC_COLOR,
  93               ESC_BGCOLOR,
  94               ESC_NEWPAGE,
  95               ESC_SETFILENAME,
  96               ESC_SETPAGENUMBER,
  97               ESC_SHADE,
  98               ESC_BGGRAY,
  99               ESC_ESCAPE,
 100               ESC_SAVEX,
 101               ESC_LOADX,
 102               ESC_PS
 103             } SpecialEscape;
 104             
 105             /* Token structure. */
 106 rizwank 1.1 struct gs_token_st
 107             {
 108               TokenType type;
 109               unsigned int flags;
 110               double new_x;			/* Current point x after this token. */
 111               double new_y;			/* Current point y after this token. */
 112               int new_col;			/* Line column after this token. */
 113             
 114               union
 115                 {
 116                   int i;
 117                   char *str;
 118                   struct
 119             	{
 120             	  double x;		/* x-offset */
 121             	  double y;		/* y-offset */
 122             	  double w;		/* width */
 123             	  double h;		/* height */
 124             	  double xscale;
 125             	  double yscale;
 126             	  int llx, lly, urx, ury; /* Bounding box. */
 127 rizwank 1.1 	  char filename[512];
 128             	  char *skipbuf;
 129             	  unsigned int skipbuf_len;
 130             	  unsigned int skipbuf_pos;
 131             	  FILE *fp;		/* File from which eps image is read. */
 132             	  int pipe;		/* Is <fp> opened to pipe?  */
 133             	} epsf;
 134                   Color color;
 135                   Color bgcolor;
 136                   struct
 137             	{
 138             	  char name[512];
 139             	  FontPoint size;
 140             	  InputEncoding encoding;
 141             	} font;
 142                   char filename[512];
 143                 } u;
 144             };
 145             
 146             typedef struct gs_token_st Token;
 147             
 148 rizwank 1.1 
 149             /*
 150              * Prototypes for static functions.
 151              */
 152             
 153             static void get_next_token ___P ((InputStream *is, double linestart,
 154             				  double linepos, unsigned int col,
 155             				  double linew, Token *token));
 156             
 157             static void dump_ps_page_header ___P ((char *fname, int empty));
 158             
 159             static void dump_ps_page_trailer ();
 160             
 161             static void dump_empty_page ();
 162             
 163             /*
 164              * Recognize a EPS file described by <token>.  Returns 1 if file was a
 165              * valid EPS file or 0 otherwise.  File is accepted if it starts with
 166              * the PostScript magic `%!' and it has a valid `%%BoundingBox' DSC
 167              * comment.
 168              */
 169 rizwank 1.1 static int recognize_eps_file ___P ((Token *token));
 170             
 171             /*
 172              * Insert EPS file described by <token> to the output stream.
 173              */
 174             static void paste_epsf ___P ((Token *token));
 175             
 176             /*
 177              * Check if InputStream <is> contains a file which can be passed
 178              * through without any modifications.  Returns 1 if file was passed or
 179              * 0 otherwise.
 180              */
 181             static int do_pass_through ___P ((char *fname, InputStream *is));
 182             
 183             /*
 184              * Read one float dimension from InputStream <is>.  If <units> is
 185              * true, number can be followed by an optional unit specifier.  If
 186              * <horizontal> is true, dimension is horizontal, otherwise it is
 187              * vertical (this is used to find out how big `line' units are).
 188              */
 189             static double read_float ___P ((InputStream *is, int units, int horizontal));
 190 rizwank 1.1 
 191             /*
 192              * Print linenumber <linenum> to the beginning of the current line.
 193              * Current line start is specified by point (x, y).
 194              */
 195             static void print_line_number ___P ((double x, double y, double space,
 196             				     double margin, unsigned int linenum));
 197             
 198             /* Send PostScript to the output file. */
 199             #define OUTPUT(body)	\
 200               do {			\
 201                 if (cofp == NULL)	\
 202                   cofp = ofp;	\
 203                 if (do_print)	\
 204                   fprintf body;	\
 205               } while (0)
 206             
 207             /* Divert output to tmp file so the total page count can be counted. */
 208             static void divert ();
 209             
 210             /* Paste diverted data to the output and patch the total page counts. */
 211 rizwank 1.1 static void undivert ();
 212             
 213             /*
 214              * Handle two-side printing related binding options.  This function is
 215              * called once for each even-numbered page.
 216              */
 217             static void handle_two_side_options ();
 218             
 219             /*
 220              * Global variables.
 221              */
 222             
 223             unsigned int current_pagenum = 0; /* The number of the current page. */
 224             unsigned int total_pages_in_file;
 225             unsigned int input_filenum = 0;
 226             unsigned int current_file_linenum;
 227             int first_pagenum_for_file;
 228             char *fname = NULL;		/* The name of the current input file. */
 229             
 230             
 231             /*
 232 rizwank 1.1  * Static variables
 233              */
 234             
 235             /* Have we dumped PS header? */
 236             static int ps_header_dumped = 0;
 237             
 238             /* Divert file. */
 239             static FILE *divertfp = NULL;
 240             
 241             /* Current output() file. */
 242             static FILE *cofp = NULL;
 243             
 244             /* To print or not to print, that's a question. */
 245             static int do_print = 1;
 246             
 247             /* Is ^@font{}-defined font active? */
 248             static int user_fontp = 0;
 249             
 250             /* The user ^@font{}-defined font. */
 251             static char user_font_name[256];
 252             static FontPoint user_font_pt;
 253 rizwank 1.1 static InputEncoding user_font_encoding;
 254             
 255             /* Is ^@color{}-defined color active? */
 256             static int user_colorp = 0;
 257             
 258             /* The user ^@color{}-defined color. */
 259             static Color user_color;
 260             
 261             /* Is ^@bgcolor{}-defined color active? */
 262             static int user_bgcolorp = 0;
 263             
 264             /* The user ^@bgcolor{}-defined color. */
 265             static Color user_bgcolor;
 266             
 267             /* The last linenumber printed by print_line_number(). */
 268             static unsigned int print_line_number_last;
 269             
 270             /* Registers to store X-coordinates with the ^@savex{} escape.
 271                Initially these are uninitialized. */
 272             static double xstore[256];
 273             
 274 rizwank 1.1 /*
 275              * Global functions.
 276              */
 277             
 278             void
 279             dump_ps_header ()
 280             {
 281               char *cp, *cp2;
 282               int i, j, got;
 283             
 284               /* Dump PS header only once. */
 285               if (ps_header_dumped)
 286                 return;
 287               ps_header_dumped = 1;
 288             
 289               /*
 290                * Header.
 291                */
 292             
 293               OUTPUT ((cofp, "%s\n", output_first_line));
 294               OUTPUT ((cofp, "%%%%BoundingBox: %d %d %d %d\n", media->llx, media->lly,
 295 rizwank 1.1 	   media->urx, media->ury));
 296               OUTPUT ((cofp, "%%%%Title: %s\n", title));
 297               OUTPUT ((cofp, "%%%%For: %s\n", passwd->pw_gecos));
 298               OUTPUT ((cofp, "%%%%Creator: %s\n", version_string));
 299               OUTPUT ((cofp, "%%%%CreationDate: %s\n", date_string));
 300               OUTPUT ((cofp, "%%%%Orientation: %s\n",
 301             	   ((nup > 1) && nup_landscape)
 302             	   || ((nup == 1) && landscape) ? "Landscape" : "Portrait"));
 303               OUTPUT ((cofp, "%%%%Pages: (atend)\n"));
 304               OUTPUT ((cofp, "%%%%DocumentMedia: %s %d %d 0 () ()\n",
 305             	   media->name, media->w, media->h));
 306               OUTPUT ((cofp, "%%%%DocumentNeededResources: (atend)\n"));
 307             
 308               if (count_key_value_set (pagedevice) > 0)
 309                 OUTPUT ((cofp, "%%%%LanguageLevel: 2\n"));
 310             
 311               OUTPUT ((cofp, "%%%%EndComments\n"));
 312             
 313             
 314               /*
 315                * Procedure Definitions.
 316 rizwank 1.1    */
 317             
 318               OUTPUT ((cofp, "%%%%BeginProlog\n"));
 319             
 320               /* Prolog. */
 321               OUTPUT ((cofp, "%%%%BeginResource: procset Enscript-Prolog %s\n",
 322             	   ps_version_string));
 323               if (!paste_file ("enscript", ".pro"))
 324                 FATAL ((stderr, _("couldn't find prolog \"%s\": %s\n"), "enscript.pro",
 325             	    strerror (errno)));
 326               OUTPUT ((cofp, "%%%%EndResource\n"));
 327             
 328               /* Encoding vector. */
 329               OUTPUT ((cofp, "%%%%BeginResource: procset Enscript-Encoding-%s %s\n",
 330             	   encoding_name, ps_version_string));
 331               if (!paste_file (encoding_name, ".enc"))
 332                 FATAL ((stderr, _("couldn't find encoding file \"%s.enc\": %s\n"),
 333             	    encoding_name, strerror (errno)));
 334               OUTPUT ((cofp, "%%%%EndResource\n"));
 335             
 336               OUTPUT ((cofp, "%%%%EndProlog\n"));
 337 rizwank 1.1 
 338             
 339               /*
 340                * Document Setup.
 341                */
 342             
 343               OUTPUT ((cofp, "%%%%BeginSetup\n"));
 344             
 345               /* Download fonts. */
 346               for (got = strhash_get_first (download_fonts, &cp, &j, (void **) &cp2); got;
 347                    got = strhash_get_next (download_fonts, &cp, &j, (void **) &cp2))
 348                 download_font (cp);
 349             
 350               /* For each required font, emit %%IncludeResouce comment. */
 351               for (got = strhash_get_first (res_fonts, &cp, &j, (void **) &cp2); got;
 352                    got = strhash_get_next (res_fonts, &cp, &j, (void **) &cp2))
 353                 OUTPUT ((cofp, "%%%%IncludeResource: font %s\n", cp));
 354             
 355               OUTPUT ((cofp, "/HFpt_w %g def\n", HFpt.w));
 356               OUTPUT ((cofp, "/HFpt_h %g def\n", HFpt.h));
 357             
 358 rizwank 1.1 
 359               /* Select our fonts. */
 360             
 361               /* Header font HF. */
 362               OUTPUT ((cofp, "/%s /HF-gs-font MF\n", HFname));
 363               OUTPUT ((cofp,
 364             	   "/HF /HF-gs-font findfont [HFpt_w 0 0 HFpt_h 0 0] makefont def\n"));
 365             
 366               /* Our default typing font F. */
 367               OUTPUT ((cofp, "/%s /F-gs-font MF\n", Fname));
 368               OUTPUT ((cofp, "/F-gs-font %g %g SF\n", Fpt.w, Fpt.h));
 369             
 370               /* Underlay. */
 371               if (underlay != NULL)
 372                 {
 373                   OUTPUT ((cofp, "/ul_str (%s) def\n", underlay));
 374                   OUTPUT ((cofp, "/ul_w_ptsize %g def\n", ul_ptsize.w));
 375                   OUTPUT ((cofp, "/ul_h_ptsize %g def\n", ul_ptsize.h));
 376                   OUTPUT ((cofp, "/ul_gray %g def\n", ul_gray));
 377                   OUTPUT ((cofp, "/ul_x %g def\n", ul_x));
 378                   OUTPUT ((cofp, "/ul_y %g def\n", ul_y));
 379 rizwank 1.1       OUTPUT ((cofp, "/ul_angle %g def\n", ul_angle));
 380                   OUTPUT ((cofp, "/ul_style %d def\n", ul_style));
 381                   OUTPUT ((cofp, "/%s /F-ul-font MF\n", ul_font));
 382                   OUTPUT ((cofp, "/ul_font /F-ul-font findfont \
 383             [ul_w_ptsize 0 0 ul_h_ptsize 0 0] makefont def\n"));
 384                 }
 385             
 386               /* Number of copies. */
 387               OUTPUT ((cofp, "/#copies %d def\n", num_copies));
 388             
 389               /* Page prefeed. */
 390               if (page_prefeed)
 391                 OUTPUT ((cofp, "true page_prefeed\n"));
 392             
 393               /* Statusdict definitions. */
 394               if (count_key_value_set (statusdict) > 0)
 395                 {
 396                   OUTPUT ((cofp, "%% Statustdict definitions:\nstatusdict begin\n  "));
 397                   i = 2;
 398                   for (got = strhash_get_first (statusdict, &cp, &j, (void **) &cp2); got;
 399             	   got = strhash_get_next (statusdict, &cp, &j, (void **) &cp2))
 400 rizwank 1.1 	{
 401             	  j = strlen (cp) + 1 + strlen (cp2) + 1;
 402             	  if (i + j > RESOURCE_LINE_WIDTH)
 403             	    {
 404             	      OUTPUT ((cofp, "\n  "));
 405             	      i = 2;
 406             	    }
 407             	  OUTPUT ((cofp, "%s %s ", cp2, cp));
 408             	  i += j;
 409             	}
 410                   OUTPUT ((cofp, "\nend\n"));
 411                 }
 412             
 413               /* Page device definitions. */
 414               if (pslevel >= 2 &&
 415                   (count_key_value_set (pagedevice) > 0 || generate_PageSize))
 416                 {
 417                   OUTPUT ((cofp, "%% Pagedevice definitions:\n"));
 418                   OUTPUT ((cofp, "gs_languagelevel 1 gt {\n  <<\n    "));
 419             
 420                   i = 4;
 421 rizwank 1.1       for (got = strhash_get_first (pagedevice, &cp, &j, (void **) &cp2); got;
 422             	   got = strhash_get_next (pagedevice, &cp, &j, (void **) &cp2))
 423             	{
 424             	  j = strlen (cp2) + 1 + strlen (cp) + 2;
 425             	  if (i + j > RESOURCE_LINE_WIDTH)
 426             	    {
 427             	      OUTPUT ((cofp, "\n    "));
 428             	      i = 4;
 429             	    }
 430             	  OUTPUT ((cofp, "/%s %s ", cp, cp2));
 431             	  i += j;
 432             	}
 433             
 434                   if (generate_PageSize)
 435             	{
 436             	  if (i + 21 > RESOURCE_LINE_WIDTH)
 437             	    {
 438             	      OUTPUT ((cofp, "\n    "));
 439             	      i = 4;
 440             	    }
 441             	  OUTPUT ((cofp, "/PageSize [%d %d] ", media->w, media->h));
 442 rizwank 1.1 	  i += 21;
 443             	}
 444             
 445                   OUTPUT ((cofp, "\n  >> setpagedevice\n} if\n"));
 446                 }
 447             
 448               /*
 449                * Dump header procset.  Header must come after all font inclusions
 450                * and enscript's dynamic state definition.
 451                */
 452               if (header != HDR_NONE)
 453                 {
 454                   char *hdr;
 455                   if (header == HDR_SIMPLE)
 456             	hdr = "simple";
 457                   else
 458             	hdr = fancy_header_name;
 459             
 460                   OUTPUT ((cofp, "%%%%BeginResource: procset Enscript-Header-%s %s\n",
 461             	       hdr, ps_version_string));
 462                   if (!paste_file (hdr, ".hdr"))
 463 rizwank 1.1 	FATAL ((stderr,
 464             		_("couldn't find header definition file \"%s.hdr\": %s\n"),
 465             		hdr, strerror (errno)));
 466                   OUTPUT ((cofp, "%%%%EndResource\n"));
 467                 }
 468             
 469               /*
 470                * Count output width and height here; we can't do it earlier because
 471                * header might have just allocated some extra space.
 472                */
 473               d_output_w = d_page_w;
 474               d_output_h = d_page_h - d_header_h - d_footer_h;
 475             
 476               /* Dump our current dynamic state. */
 477               OUTPUT ((cofp, "/d_page_w %d def\n", d_page_w));
 478               OUTPUT ((cofp, "/d_page_h %d def\n", d_page_h));
 479             
 480               OUTPUT ((cofp, "/d_header_x %d def\n", 0));
 481               OUTPUT ((cofp, "/d_header_y %d def\n", d_output_h + d_footer_h));
 482               OUTPUT ((cofp, "/d_header_w %d def\n", d_header_w));
 483               OUTPUT ((cofp, "/d_header_h %d def\n", d_header_h));
 484 rizwank 1.1 
 485               OUTPUT ((cofp, "/d_footer_x %d def\n", 0));
 486               OUTPUT ((cofp, "/d_footer_y %d def\n", 0));
 487               OUTPUT ((cofp, "/d_footer_w %d def\n", d_header_w));
 488               OUTPUT ((cofp, "/d_footer_h %d def\n", d_footer_h));
 489             
 490               OUTPUT ((cofp, "/d_output_w %d def\n", d_output_w));
 491               OUTPUT ((cofp, "/d_output_h %d def\n", d_output_h));
 492               OUTPUT ((cofp, "/cols %d def\n", num_columns));
 493             
 494               OUTPUT ((cofp, "%%%%EndSetup\n"));
 495             }
 496             
 497             
 498             void
 499             dump_ps_trailer ()
 500             {
 501               int i, j, got;
 502               char *cp;
 503               void *value;
 504               unsigned int nup_subpage;
 505 rizwank 1.1 
 506               if (!ps_header_dumped)
 507                 /* No header, let's be consistent and forget trailer also. */
 508                 return;
 509             
 510               /* The possible pending N-up showpage. */
 511               nup_subpage = (total_pages - 1) % nup;
 512               if (nup > 1 && nup_subpage + 1 != nup)
 513                 /* N-up showpage missing. */
 514                 OUTPUT ((cofp, "_R\nS\n"));
 515             
 516               /* Trailer. */
 517             
 518               OUTPUT ((cofp, "%%%%Trailer\n"));
 519             
 520               if (page_prefeed)
 521                 OUTPUT ((cofp, "false page_prefeed\n"));
 522             
 523               OUTPUT ((cofp, "%%%%Pages: %d\n", total_pages));
 524             
 525               /* Document needed resources. */
 526 rizwank 1.1 
 527               /* fonts. */
 528               OUTPUT ((cofp, "%%%%DocumentNeededResources: font "));
 529               i = 32;			/* length of the previous string. */
 530               for (got = strhash_get_first (res_fonts, &cp, &j, &value); got;
 531                    got = strhash_get_next (res_fonts, &cp, &j, &value))
 532                 {
 533                   if (i + strlen (cp) + 1 > RESOURCE_LINE_WIDTH)
 534             	{
 535             	  OUTPUT ((cofp, "\n%%%%+ font "));
 536             	  i = 9;		/* length of the previous string. */
 537             	}
 538                   OUTPUT ((cofp, "%s ", cp));
 539                   i += strlen (cp) + 1;
 540                 }
 541               OUTPUT ((cofp, "\n%%%%EOF\n"));
 542             }
 543             
 544             
 545             void
 546             process_file (char *fname_arg, InputStream *is, int is_toc)
 547 rizwank 1.1 {
 548               int col;
 549               double x, y;
 550               double lx, ly;
 551               double linewidth;		/* Line width in points. */
 552               double lineend;
 553               int done = 0;
 554               int page_clear = 1;
 555               unsigned int line_column;
 556               unsigned int current_linenum;
 557               double linenumber_space = 0;
 558               double linenumber_margin = 0;
 559               Token token;
 560               int reuse_last_token = 0;
 561               unsigned int current_slice = 1;
 562               int last_wrapped_line = -1;
 563               int last_spaced_file_linenum = -1;
 564               int save_current_pagenum;
 565               int toc_pagenum = 0;
 566             
 567               /* Save filename. */
 568 rizwank 1.1   xfree (fname);
 569               fname = xstrdup (fname_arg);
 570             
 571               /* Init page number and line counters. */
 572               if (!continuous_page_numbers)
 573                 current_pagenum = 0;
 574               total_pages_in_file = 0;
 575               current_file_linenum = start_line_number;
 576             
 577               /*
 578                * Count possible line number spaces.  This should be enought for 99999
 579                * lines
 580                */
 581               linenumber_space = CHAR_WIDTH ('0') * 5 + 1.0;
 582               linenumber_margin = CHAR_WIDTH (':') + CHAR_WIDTH ('m');
 583             
 584               /* We got a new input file. */
 585               input_filenum++;
 586             
 587               /* We haven't printed any line numbers yet. */
 588               print_line_number_last = (unsigned int) -1;
 589 rizwank 1.1 
 590               if (pass_through || output_language_pass_through)
 591                 if (do_pass_through (fname, is))
 592                   /* All done. */
 593                   return;
 594             
 595               /* We have work to do, let's give header a chance to dump itself. */
 596               dump_ps_header ();
 597             
 598               /*
 599                * Align files to the file_align boundary, this is handy for two-side
 600                * printing.
 601                */
 602               while ((total_pages % file_align) != 0)
 603                 {
 604                   total_pages++;
 605                   dump_empty_page ();
 606                 }
 607             
 608               MESSAGE (1, (stderr, _("processing file \"%s\"...\n"), fname));
 609             
 610 rizwank 1.1   linewidth = d_output_w / num_columns - 2 * d_output_x_margin
 611                 - line_indent;
 612             
 613               /* Save the current running page number for possible toc usage. */
 614               first_pagenum_for_file = total_pages + 1;
 615             
 616               /*
 617                * Divert our output to a temp file.  We will re-process it
 618                * afterwards to patch, for example, the number of pages in the
 619                * document.
 620                */
 621               divert ();
 622             
 623               /* Process this input file. */
 624               while (!done)
 625                 {
 626                   /* Start a new page. */
 627                   page_clear = 1;
 628             
 629                   for (col = 0; !done && col < num_columns; col++)
 630             	{
 631 rizwank 1.1 	  /* Move to the beginning of the column <col>. */
 632             	  lx = x = col * d_output_w / (float) num_columns + d_output_x_margin
 633             	    + line_indent;
 634             	  lineend = lx + linewidth;
 635             
 636             	  ly = y = d_footer_h + d_output_h - d_output_y_margin - LINESKIP;
 637             	  current_linenum = 0;
 638             	  line_column = 0;
 639             
 640             	  while (1)
 641             	    {
 642             	      if (line_numbers && line_column == 0
 643             		  && (current_file_linenum != last_spaced_file_linenum))
 644             		{
 645             		  /* Forward x by the amount needed by our line numbers. */
 646             		  x += linenumber_space + linenumber_margin;
 647             		  last_spaced_file_linenum = current_file_linenum;
 648             		}
 649             
 650             	      /* Get token. */
 651             	      if (!reuse_last_token)
 652 rizwank 1.1 		get_next_token (is, lx, x, line_column, lineend, &token);
 653             	      reuse_last_token = 0;
 654             
 655             	      /*
 656             	       * Page header printing is delayed to this point because
 657             	       * we want to handle files ending with a newline character
 658             	       * with care.  If the last newline would cause a pagebreak,
 659             	       * otherwise we would print page header to the non-existent
 660             	       * next page and that would be ugly ;)
 661             	       */
 662             
 663             	      if (token.type == tEOF)
 664             		{
 665             		  done = 1;
 666             		  goto end_of_page;
 667             		}
 668             
 669             	      /*
 670             	       * Now we know that we are going to make marks to this page
 671             	       * => print page header.
 672             	       */
 673 rizwank 1.1 
 674             	      if (page_clear)
 675             		{
 676             		  PageRange *pr;
 677             
 678             		  current_pagenum++;
 679             		  total_pages_in_file++;
 680             
 681             		  /* Check page ranges. */
 682             		  if (page_ranges == NULL)
 683             		    do_print = 1;
 684             		  else
 685             		    {
 686             		      do_print = 0;
 687             		      for (pr = page_ranges; pr; pr = pr->next)
 688             			{
 689             			  if (pr->odd || pr->even)
 690             			    {
 691             			      if ((pr->odd && (current_pagenum % 2) == 1)
 692             				  || (pr->even && (current_pagenum % 2) == 0))
 693             				{
 694 rizwank 1.1 				  do_print = 1;
 695             				  break;
 696             				}
 697             			    }
 698             			  else
 699             			    {
 700             			      if (pr->start <= current_pagenum
 701             				  && current_pagenum <= pr->end)
 702             				{
 703             				  do_print = 1;
 704             				  break;
 705             				}
 706             			    }
 707             			}
 708             		    }
 709             
 710             		  if (do_print)
 711             		    total_pages++;
 712             
 713             		  if (is_toc)
 714             		    {
 715 rizwank 1.1 		      save_current_pagenum = current_pagenum;
 716             		      toc_pagenum--;
 717             		      current_pagenum = toc_pagenum;
 718             		    }
 719             
 720             		  dump_ps_page_header (fname, 0);
 721             		  page_clear = 0;
 722             
 723             		  if (is_toc)
 724             		    current_pagenum = save_current_pagenum;
 725             		}
 726             
 727             	      /* Print line highlight. */
 728             	      if (line_column == 0 && line_highlight_gray < 1.0)
 729             		OUTPUT ((cofp, "%g %g %g %g %g line_highlight\n",
 730             			 lx, (y - baselineskip
 731             			      + (font_bbox_lly * Fpt.h / UNITS_PER_POINT)),
 732             			 linewidth, Fpt.h + baselineskip,
 733             			 line_highlight_gray));
 734             
 735             	      /* Print line numbers if needed. */
 736 rizwank 1.1 	      if (line_numbers && line_column == 0 && token.type != tFORMFEED)
 737             		print_line_number (lx, y, linenumber_space, linenumber_margin,
 738             				   current_file_linenum);
 739             
 740             	      /* Check rest of tokens. */
 741             	      switch (token.type)
 742             		{
 743             		case tFORMFEED:
 744             		  switch (formfeed_type)
 745             		    {
 746             		    case FORMFEED_COLUMN:
 747             		      goto end_of_column;
 748             		      break;
 749             
 750             		    case FORMFEED_PAGE:
 751             		      goto end_of_page;
 752             		      break;
 753             
 754             		    case FORMFEED_HCOLUMN:
 755             		      /*
 756             		       * Advance y-coordinate to the next even
 757 rizwank 1.1 		       * `horizontal_column_height' position.
 758             		       */
 759             		      {
 760             			int current_row;
 761             
 762             			current_row = (ly - y) / horizontal_column_height;
 763             			y = ly - (current_row + 1) * horizontal_column_height;
 764             
 765             			/* Check the end of the page. */
 766             			if (y < d_footer_h + d_output_y_margin)
 767             			  goto end_of_column;
 768             		      }
 769             		      break;
 770             		    }
 771             		  break;
 772             
 773             		case tSTRING:
 774             		  if (CORRECT_SLICE ())
 775             		    {
 776             		      if (bggray < 1.0)
 777             			{
 778 rizwank 1.1 			  OUTPUT ((cofp, "%g %g %g %g %g (%s) bgs\n", x, y,
 779             				   Fpt.h + baselineskip,
 780             				   baselineskip
 781             				   - (font_bbox_lly * Fpt.h / UNITS_PER_POINT),
 782             				   bggray,
 783             				   token.u.str));
 784             			}
 785             		      else if (user_bgcolorp)
 786             			{
 787             			  OUTPUT ((cofp, "%g %g %g %g %g %g %g (%s) bgcs\n",
 788             				   x, y, Fpt.h + baselineskip,
 789             				   baselineskip
 790             				   - (font_bbox_lly * Fpt.h / UNITS_PER_POINT),
 791             				   user_bgcolor.r,
 792             				   user_bgcolor.g,
 793             				   user_bgcolor.b,
 794             				   token.u.str));
 795             			}
 796             		      else
 797             			{
 798             			  OUTPUT ((cofp, "%g %g M\n(%s) s\n", x, y,
 799 rizwank 1.1 				   token.u.str));
 800             			}
 801             		    }
 802             		  x = token.new_x;
 803             		  line_column = token.new_col;
 804             		  break;
 805             
 806             		case tCARRIAGE_RETURN:
 807             		  /* Just reset the x-coordinate. */
 808             		  x = col * d_output_w / (float) num_columns
 809             		    + d_output_x_margin + line_indent;
 810             		  line_column = 0;
 811             		  break;
 812             
 813             		case tNEWLINE:
 814             		case tWRAPPED_NEWLINE:
 815             		  if (token.type == tNEWLINE)
 816             		    {
 817             		      current_file_linenum++;
 818             		      current_slice = 1;
 819             		      y -= LINESKIP;
 820 rizwank 1.1 		    }
 821             		  else
 822             		    {
 823             		      current_slice++;
 824             		      if (!slicing)
 825             			{
 826             			  /* Mark wrapped line marks. */
 827             			  switch (mark_wrapped_lines_style)
 828             			    {
 829             			    case MWLS_NONE:
 830             			      /* nothing */
 831             			      break;
 832             
 833             			    case MWLS_PLUS:
 834             			      OUTPUT ((cofp, "%g %g M (+) s\n", x, y));
 835             			      break;
 836             
 837             			    default:
 838             			      /* Print some fancy graphics. */
 839             			      OUTPUT ((cofp,
 840             				       "%g %g %g %g %d wrapped_line_mark\n",
 841 rizwank 1.1 				       x, y, Fpt.w, Fpt.h,
 842             				       mark_wrapped_lines_style));
 843             			      break;
 844             			    }
 845             
 846             			  /*
 847             			   * For wrapped newlines, decrement y only if
 848             			   * we are not slicing the input.
 849             			   */
 850             			  y -= LINESKIP;
 851             			}
 852             
 853             		      /* Count the wrapped lines here. */
 854             		      if (!slicing || current_slice > slice)
 855             			if (current_file_linenum != last_wrapped_line)
 856             			  {
 857             			    if (do_print)
 858             			      num_truncated_lines++;
 859             			    last_wrapped_line = current_file_linenum;
 860             			  }
 861             		    }
 862 rizwank 1.1 
 863             		  current_linenum++;
 864             		  if (current_linenum >= lines_per_page
 865             		      || y < d_footer_h + d_output_y_margin)
 866             		    goto end_of_column;
 867             
 868             		  x = col * d_output_w / (float) num_columns
 869             		    + d_output_x_margin + line_indent;
 870             		  line_column = 0;
 871             		  break;
 872             
 873             		case tEPSF:
 874             		  /* Count current point movement. */
 875             
 876             		  if (token.flags & F_EPSF_ABSOLUTE_Y)
 877             		    token.new_y = ly;
 878             		  else
 879             		    token.new_y = y;
 880             		  token.new_y += token.u.epsf.y - token.u.epsf.h;
 881             
 882             		  if (token.flags & F_EPSF_ABSOLUTE_X)
 883 rizwank 1.1 		    token.new_x = lx;
 884             		  else
 885             		    token.new_x = x;
 886             		  token.new_x += token.u.epsf.x;
 887             
 888             		  /* Check flags. */
 889             
 890             		  /* Justification flags overwrite <x_ofs>. */
 891             		  if (token.flags & F_EPSF_CENTER)
 892             		    token.new_x = lx + (linewidth - token.u.epsf.w) / 2;
 893             		  if (token.flags & F_EPSF_RIGHT)
 894             		    token.new_x = lx + (linewidth - token.u.epsf.w);
 895             
 896             		  /* Check if eps file does not fit to this column. */
 897             		  if ((token.flags & F_EPSF_NO_CPOINT_UPDATE_Y) == 0
 898             		      && token.new_y < d_footer_h + d_output_y_margin)
 899             		    {
 900             		      if (current_linenum == 0)
 901             			{
 902             			  /*
 903             			   * At the beginning of the column, warn user
 904 rizwank 1.1 			   * and print image.
 905             			   */
 906             			  MESSAGE (0, (stderr, _("EPS file \"%s\" is too \
 907             large for page\n"),
 908             				       token.u.epsf.filename));
 909             			}
 910             		      else
 911             			{
 912             			  /* Must start a new column. */
 913             			  reuse_last_token = 1;
 914             			  goto end_of_column;
 915             			}
 916             		    }
 917             
 918             		  /* Do paste. */
 919             		  if (CORRECT_SLICE ())
 920             		    paste_epsf (&token);
 921             
 922             		  /* Update current point? */
 923             		  if (!(token.flags & F_EPSF_NO_CPOINT_UPDATE_Y))
 924             		    y = token.new_y;
 925 rizwank 1.1 		  if (!(token.flags & F_EPSF_NO_CPOINT_UPDATE_X))
 926             		    x = token.new_x + token.u.epsf.w;
 927             
 928             		  if (y < d_footer_h + d_output_y_margin)
 929             		    goto end_of_column;
 930             		  break;
 931             
 932             		case tFONT:
 933             		  /* Select a new current font. */
 934             		  if (line_column == 0)
 935             		    {
 936             		      double newh;
 937             
 938             		      /* Check for possible line skip change. */
 939             		      if (token.u.font.name[0] == '\0')
 940             			newh = default_Fpt.h;
 941             		      else
 942             			newh = token.u.font.size.h;
 943             
 944             		      if (newh != Fpt.h)
 945             			{
 946 rizwank 1.1 			  /* We need a different line skip value. */
 947             			  y -= (newh - Fpt.h);
 948             			}
 949             		      /*
 950             		       * We must check for page overflow after we have
 951             		       * set the new font.
 952             		       */
 953             		    }
 954             
 955             		  MESSAGE (2, (stderr, "^@font="));
 956             		  if (token.u.font.name[0] == '\0')
 957             		    {
 958             		      /* Select the default font. */
 959             		      Fpt.w = default_Fpt.w;
 960             		      Fpt.h = default_Fpt.h;
 961             		      Fname = default_Fname;
 962             		      encoding = default_Fencoding;
 963             		      OUTPUT ((cofp, "/F-gs-font %g %g SF\n", Fpt.w, Fpt.h));
 964             		      user_fontp = 0;
 965             		    }
 966             		  else
 967 rizwank 1.1 		    {
 968             		      strhash_put (res_fonts, token.u.font.name,
 969             				   strlen (token.u.font.name) + 1,
 970             				   NULL, NULL);
 971             		      if (token.u.font.encoding == default_Fencoding)
 972             			OUTPUT ((cofp, "/%s %g %g SUF\n", token.u.font.name,
 973             				 token.u.font.size.w, token.u.font.size.h));
 974             		      else if (token.u.font.encoding == ENC_PS)
 975             			OUTPUT ((cofp, "/%s %g %g SUF_PS\n", token.u.font.name,
 976             				 token.u.font.size.w, token.u.font.size.h));
 977             		      else
 978             			FATAL ((stderr,
 979             				_("user font encoding can be only the system's default or `ps'")));
 980             
 981             		      strcpy (user_font_name, token.u.font.name);
 982             		      user_font_pt.w = token.u.font.size.w;
 983             		      user_font_pt.h = token.u.font.size.h;
 984             		      user_font_encoding = token.u.font.encoding;
 985             		      user_fontp = 1;
 986             
 987             		      Fpt.w = user_font_pt.w;
 988 rizwank 1.1 		      Fpt.h = user_font_pt.h;
 989             		      Fname = user_font_name;
 990             		      encoding = user_font_encoding;
 991             		    }
 992             		  MESSAGE (2, (stderr, "%s %g/%gpt\n", Fname, Fpt.w, Fpt.h));
 993             		  read_font_info ();
 994             
 995             		  /*
 996             		   * Check for page overflow in that case that we were
 997             		   * at the first column and font were changed to a bigger
 998             		   * one.
 999             		   */
1000             		  if (y < d_footer_h + d_output_y_margin)
1001             		    goto end_of_column;
1002             		  break;
1003             
1004             		case tCOLOR:
1005             		  /* Select a new color. */
1006             		  MESSAGE (2, (stderr, "^@color{%f %f %f}\n",
1007             			       token.u.color.r,
1008             			       token.u.color.g,
1009 rizwank 1.1 			       token.u.color.b));
1010             		  if (token.u.color.r == token.u.color.g
1011             		      && token.u.color.g == token.u.color.b
1012             		      && token.u.color.b == 0.0)
1013             		    {
1014             		      /* Select the default color (black). */
1015             		      OUTPUT ((cofp, "0 setgray\n"));
1016             		      user_colorp = 0;
1017             		    }
1018             		  else
1019             		    {
1020             		      OUTPUT ((cofp, "%g %g %g setrgbcolor\n",
1021             			       token.u.color.r,
1022             			       token.u.color.g,
1023             			       token.u.color.b));
1024             
1025             		      user_color.r = token.u.color.r;
1026             		      user_color.g = token.u.color.g;
1027             		      user_color.b = token.u.color.b;
1028             		      user_colorp = 1;
1029             		    }
1030 rizwank 1.1 		  break;
1031             
1032             		case tBGCOLOR:
1033             		  /* Select a new background color. */
1034             		  MESSAGE (2, (stderr, "^@bgcolor{%f %f %f}\n",
1035             			       token.u.color.r,
1036             			       token.u.color.g,
1037             			       token.u.color.b));
1038             
1039             		  if (token.u.color.r == token.u.color.g
1040             		      && token.u.color.g == token.u.color.b
1041             		      && token.u.color.b == 1.0)
1042             		    {
1043             		      /* Select the default bgcolor (white). */
1044             		      user_bgcolorp = 0;
1045             		    }
1046             		  else
1047             		    {
1048             		      user_bgcolor.r = token.u.color.r;
1049             		      user_bgcolor.g = token.u.color.g;
1050             		      user_bgcolor.b = token.u.color.b;
1051 rizwank 1.1 		      user_bgcolorp = 1;
1052             		    }
1053             		  break;
1054             
1055             		case tSETFILENAME:
1056             		  xfree (fname);
1057             		  fname = xstrdup (token.u.filename);
1058             		  break;
1059             
1060             		case tSETPAGENUMBER:
1061             		  current_pagenum = token.u.i - 1;
1062             		  break;
1063             
1064             		case tNEWPAGE:
1065             		  if (current_linenum >= token.u.i)
1066             		    goto end_of_page;
1067             		  break;
1068             
1069             		case tSAVEX:
1070             		  xstore[(unsigned char) token.u.i] = x;
1071             		  break;
1072 rizwank 1.1 
1073             		case tLOADX:
1074             		  x = xstore[(unsigned char) token.u.i];
1075             		  break;
1076             
1077             		case tPS:
1078             		  OUTPUT ((cofp, "%g %g M\n%s\n", x, y, token.u.str));
1079             		  xfree (token.u.str);
1080             		  break;
1081             
1082             		case tNONE:
1083             		default:
1084             		  FATAL ((stderr, "process_file(): got illegal token %d",
1085             			  token.type));
1086             		  break;
1087             		}
1088             	    }
1089             	end_of_column:
1090             	  ;			/* ULTRIX's cc needs this line. */
1091             	}
1092             
1093 rizwank 1.1     end_of_page:
1094                   if (!page_clear)
1095             	dump_ps_page_trailer ();
1096                 }
1097             
1098               /*
1099                * Reset print flag to true so all the required document trailers
1100                * etc. get printed properly.
1101                */
1102               do_print = 1;
1103             
1104               /* Undivert our output from the temp file to our output stream. */
1105               undivert ();
1106             
1107               /* Table of contents? */
1108               if (toc)
1109                 {
1110                   char *cp;
1111                   int save_total_pages = total_pages;
1112             
1113                   /* use first pagenum in file for toc */
1114 rizwank 1.1       total_pages = first_pagenum_for_file;
1115             
1116                   cp = format_user_string ("TOC", toc_fmt_string);
1117                   fprintf (toc_fp, "%s\n", cp);
1118                   xfree (cp);
1119             
1120                   total_pages = save_total_pages;
1121                 }
1122             }
1123             
1124             
1125             /*
1126              * Static functions.
1127              */
1128             
1129             /* Help macros. */
1130             
1131             /* Check if character <ch> fits to current line. */
1132             #define FITS_ON_LINE(ch) ((linepos + CHAR_WIDTH (ch) < linew) || col == 0)
1133             
1134             /* Is line buffer empty? */
1135 rizwank 1.1 #define BUFFER_EMPTY() (bufpos == 0)
1136             
1137             /* Unconditionally append character <ch> to the line buffer. */
1138             #define APPEND_CHAR(ch) 				\
1139               do {							\
1140                 if (bufpos >= buflen)				\
1141                   {							\
1142             	buflen += 4096;					\
1143             	buffer = xrealloc (buffer, buflen);		\
1144                   }							\
1145                 buffer[bufpos++] = ch;				\
1146               } while (0)
1147             
1148             /*
1149              * Copy character <ch> (it fits to this line) to output buffer and
1150              * update current point counters.
1151              */
1152             #define EMIT(ch) 		\
1153               do {				\
1154                 APPEND_CHAR (ch);		\
1155                 linepos += CHAR_WIDTH (ch);	\
1156 rizwank 1.1     col++;			\
1157               } while (0)
1158             
1159             #define UNEMIT(ch)		\
1160               do {				\
1161                 linepos -= CHAR_WIDTH (ch); \
1162                 col--;			\
1163               } while (0)
1164             
1165             #define ISSPACE(ch) ((ch) == ' ' || (ch) == '\t')
1166             #define ISOCTAL(ch) ('0' <= (ch) && (ch) <= '7')
1167             
1168             /* Read one special escape from input <fp>. */
1169             
1170             static struct
1171             {
1172               char *name;
1173               SpecialEscape escape;
1174             } escapes[] =
1175               {
1176                 {"comment",		ESC_COMMENT},
1177 rizwank 1.1     {"epsf", 		ESC_EPSF},
1178                 {"font", 		ESC_FONT},
1179                 {"color",		ESC_COLOR},
1180                 {"bgcolor",		ESC_BGCOLOR},
1181                 {"newpage",		ESC_NEWPAGE},
1182                 {"ps",		ESC_PS},
1183                 {"setfilename",	ESC_SETFILENAME},
1184                 {"setpagenumber",	ESC_SETPAGENUMBER},
1185                 {"shade",		ESC_SHADE},
1186                 {"bggray",		ESC_BGGRAY},
1187                 {"escape",		ESC_ESCAPE},
1188                 {"savex",		ESC_SAVEX},
1189                 {"loadx",		ESC_LOADX},
1190                 {NULL, 0},
1191               };
1192             
1193             
1194             static void
1195             read_special_escape (InputStream *is, Token *token)
1196             {
1197               char escname[256];
1198 rizwank 1.1   char buf[4096];
1199               int i, e;
1200               int ch;
1201             
1202               /* Get escape name. */
1203               for (i = 0; i < sizeof (escname) - 1 && (ch = is_getc (is)) != EOF; i++)
1204                 {
1205                   if (!isalnum (ch))
1206             	{
1207             	  is_ungetc (ch, is);
1208             	  break;
1209             	}
1210                   else
1211             	escname[i] = ch;
1212                 }
1213               escname[i] = '\0';
1214             
1215               /* Lookup escape. */
1216               for (e = 0; escapes[e].name; e++)
1217                 if (strcmp (escname, escapes[e].name) == 0)
1218                   break;
1219 rizwank 1.1   if (escapes[e].name == NULL)
1220                 FATAL ((stderr, _("unknown special escape: %s"), escname));
1221             
1222               /*
1223                * The epsf escape takes optional arguments so it must be handled
1224                * differently.
1225                */
1226               if (escapes[e].escape == ESC_EPSF)
1227                 {
1228                   int i;
1229                   int pw, ph;
1230                   double scale;
1231             
1232                   token->flags = 0;
1233                   token->u.epsf.x = 0.0;
1234                   token->u.epsf.y = 0.0;
1235                   token->u.epsf.h = 0.0;
1236                   token->u.epsf.pipe = 0;
1237             
1238                   ch = is_getc (is);
1239                   if (ch == '[')
1240 rizwank 1.1 	{
1241             	  /* Read options. */
1242             	  while ((ch = is_getc (is)) != EOF && ch != ']')
1243             	    {
1244             	      switch (ch)
1245             		{
1246             		case 'c':	/* center justification */
1247             		  token->flags &= ~M_EPSF_JUSTIFICATION;
1248             		  token->flags |= F_EPSF_CENTER;
1249             		  break;
1250             
1251             		case 'n':	/* no current point update */
1252             		  /* Check the next character. */
1253             		  ch = is_getc (is);
1254             		  switch (ch)
1255             		    {
1256             		    case 'x':
1257             		      token->flags |= F_EPSF_NO_CPOINT_UPDATE_X;
1258             		      break;
1259             
1260             		    case 'y':
1261 rizwank 1.1 		      token->flags |= F_EPSF_NO_CPOINT_UPDATE_Y;
1262             		      break;
1263             
1264             		    default:
1265             		      is_ungetc (ch, is);
1266             		      token->flags |= F_EPSF_NO_CPOINT_UPDATE_X;
1267             		      token->flags |= F_EPSF_NO_CPOINT_UPDATE_Y;
1268             		      break;
1269             		    }
1270             		  break;
1271             
1272             		case 'r':	/* right justification */
1273             		  token->flags &= ~M_EPSF_JUSTIFICATION;
1274             		  token->flags |= F_EPSF_RIGHT;
1275             		  break;
1276             
1277             
1278             		case 's':	/* scale */
1279             		  /* Check the next character. */
1280             		  ch = is_getc (is);
1281             		  switch (ch)
1282 rizwank 1.1 		    {
1283             		    case 'x':
1284             		      token->flags |= F_EPSF_SCALE_X;
1285             		      token->u.epsf.xscale = read_float (is, 0, 1);
1286             		      break;
1287             
1288             		    case 'y':
1289             		      token->flags |= F_EPSF_SCALE_Y;
1290             		      token->u.epsf.yscale = read_float (is, 0, 0);
1291             		      break;
1292             
1293             		    default:
1294             		      is_ungetc (ch, is);
1295             		      token->flags |= F_EPSF_SCALE_X;
1296             		      token->flags |= F_EPSF_SCALE_Y;
1297             		      token->u.epsf.xscale = token->u.epsf.yscale
1298             			= read_float (is, 0, 1);
1299             		      break;
1300             		    }
1301             		  break;
1302             
1303 rizwank 1.1 		case 'x':	/* x-position */
1304             		  token->u.epsf.x = read_float (is, 1, 1);
1305             
1306             		  /* Check the next character. */
1307             		  ch = is_getc (is);
1308             		  switch (ch)
1309             		    {
1310             		    case 'a':
1311             		      token->flags |= F_EPSF_ABSOLUTE_X;
1312             		      break;
1313             
1314             		    default:
1315             		      is_ungetc (ch, is);
1316             		      break;
1317             		    }
1318             		  break;
1319             
1320             		case 'y':	/* y-position */
1321             		  token->u.epsf.y = - read_float (is, 1, 0);
1322             
1323             		  /* Check the next character. */
1324 rizwank 1.1 		  ch = is_getc (is);
1325             		  switch (ch)
1326             		    {
1327             		    case 'a':
1328             		      token->flags |= F_EPSF_ABSOLUTE_Y;
1329             		      break;
1330             
1331             		    default:
1332             		      is_ungetc (ch, is);
1333             		      break;
1334             		    }
1335             		  break;
1336             
1337             		case 'h':	/* height */
1338             		  token->u.epsf.h = read_float (is, 1, 0);
1339             		  break;
1340             
1341             		case ' ':
1342             		case '\t':
1343             		  break;
1344             
1345 rizwank 1.1 		default:
1346             		  FATAL ((stderr, _("illegal option %c for ^@epsf escape"),
1347             			  ch));
1348             		}
1349             	    }
1350             	  if (ch != ']')
1351             	    FATAL ((stderr,
1352             		    _("malformed ^@epsf escape: no ']' after options")));
1353             
1354             	  ch = is_getc (is);
1355             	}
1356                   if (ch == '{')
1357             	{
1358             	  /* Read filename. */
1359             	  for (i = 0; (ch = is_getc (is)) != EOF && ch != '}'; i++)
1360             	    {
1361             	      token->u.epsf.filename[i] = ch;
1362             	      if (i + 1 >= sizeof (token->u.epsf.filename))
1363             		FATAL ((stderr,
1364             			_("too long file name for ^@epsf escape:\n%.*s"),
1365             			i, token->u.epsf.filename));
1366 rizwank 1.1 	    }
1367             	  if (ch == EOF)
1368             	    FATAL ((stderr, _("unexpected EOF while scanning ^@epsf escape")));
1369             
1370             	  token->u.epsf.filename[i] = '\0';
1371             	  token->type = tEPSF;
1372             	}
1373                   else
1374             	FATAL ((stderr, _("malformed ^@epsf escape: no '{' found")));
1375             
1376                   /*
1377                    * Now we have a valid epsf-token in <token>.  Let's read BoundingBox
1378                    * and do some calculations.
1379                    */
1380                   if (!recognize_eps_file (token))
1381             	/* Recognize eps has already printed error message so we are done. */
1382             	token->type = tNONE;
1383                   else
1384             	{
1385             	  /* Some fixups for x and y dimensions. */
1386             	  token->u.epsf.y += LINESKIP - 1;
1387 rizwank 1.1 	  if (token->u.epsf.h != 0.0)
1388             	    token->u.epsf.h -= 1.0;
1389             
1390             	  /* Count picture's width and height. */
1391             
1392             	  pw = token->u.epsf.urx - token->u.epsf.llx;
1393             	  ph = token->u.epsf.ury - token->u.epsf.lly;
1394             
1395             	  /* The default scale. */
1396             	  if (token->u.epsf.h == 0.0)
1397             	    scale = 1.0;
1398             	  else
1399             	    scale = token->u.epsf.h / ph;
1400             
1401             	  if ((token->flags & F_EPSF_SCALE_X) == 0)
1402             	    token->u.epsf.xscale = scale;
1403             	  if ((token->flags & F_EPSF_SCALE_Y) == 0)
1404             	    token->u.epsf.yscale = scale;
1405             
1406             	  pw *= token->u.epsf.xscale;
1407             	  ph *= token->u.epsf.yscale;
1408 rizwank 1.1 
1409             	  token->u.epsf.w = pw;
1410             	  token->u.epsf.h = ph;
1411             	}
1412                 }
1413               else if (escapes[e].escape == ESC_COMMENT)
1414                 {
1415                   /* Comment the rest of this line. */
1416                   while ((ch = is_getc (is)) != EOF && ch != nl)
1417             	;
1418                   token->type = tNONE;
1419                 }
1420               else
1421                 {
1422                   char *cp;
1423                   int parenlevel;
1424             
1425                   /*
1426                    * Handle the rest of the escapes.
1427                    */
1428             
1429 rizwank 1.1       /* Read argument. */
1430                   ch = is_getc (is);
1431                   if (ch != '{')
1432             	FATAL ((stderr, _("malformed %s escape: no '{' found"),
1433             		escapes[e].name));
1434             
1435                   parenlevel = 0;
1436                   for (i = 0;
1437             	   (ch = is_getc (is)) != EOF && (parenlevel > 0 || ch != '}'); i++)
1438             	{
1439             	  if (ch == '{')
1440             	    parenlevel++;
1441             	  else if (ch == '}')
1442             	    parenlevel--;
1443             
1444             	  buf[i] = ch;
1445             	  if (i + 1 >= sizeof (buf))
1446             	    FATAL ((stderr, _("too long argument for %s escape:\n%.*s"),
1447             		    escapes[i].name, i, buf));
1448             	}
1449                   buf[i] = '\0';
1450 rizwank 1.1 
1451                   /* And now handle the escape. */
1452                   switch (escapes[e].escape)
1453             	{
1454             	case ESC_FONT:
1455             	  strcpy (token->u.font.name, buf);
1456             
1457             	  /* Check for the default font. */
1458             	  if (strcmp (token->u.font.name, "default") == 0)
1459             	    token->u.font.name[0] = '\0';
1460             	  else
1461             	    {
1462             	      if (!parse_font_spec (token->u.font.name, &cp,
1463             				    &token->u.font.size,
1464             				    &token->u.font.encoding))
1465             		FATAL ((stderr, _("malformed font spec for ^@font escape: %s"),
1466             			token->u.font.name));
1467             
1468             	      strcpy (token->u.font.name, cp);
1469             	      xfree (cp);
1470             	    }
1471 rizwank 1.1 	  token->type = tFONT;
1472             	  break;
1473             
1474             	case ESC_COLOR:
1475             	case ESC_BGCOLOR:
1476             	  /* Check for the default color. */
1477             	  if (strcmp (buf, "default") == 0)
1478             	    {
1479             	      double val = 0;
1480             
1481             	      if (escapes[e].escape == ESC_BGCOLOR)
1482             		val = 1;
1483             
1484             	      token->u.color.r = val;
1485             	      token->u.color.g = val;
1486             	      token->u.color.b = val;
1487             	    }
1488             	  else
1489             	    {
1490             	      int got;
1491             
1492 rizwank 1.1 	      got = sscanf (buf, "%g %g %g",
1493             			    &token->u.color.r,
1494             			    &token->u.color.g,
1495             			    &token->u.color.b);
1496             	      switch (got)
1497             		{
1498             		case 0:
1499             		case 2:
1500             		  FATAL ((stderr,
1501             			  _("malformed color spec for ^@%s escape: %s"),
1502             			  escapes[e].escape == ESC_COLOR
1503             			  ? "color" : "bgcolor",
1504             			  buf));
1505             		  break;
1506             
1507             		case 1:
1508             		  token->u.color.g = token->u.color.b = token->u.color.r;
1509             		  break;
1510             
1511             		default:
1512             		  /* Got all three components. */
1513 rizwank 1.1 		  break;
1514             		}
1515             	    }
1516             	  if (escapes[e].escape == ESC_COLOR)
1517             	    token->type = tCOLOR;
1518             	  else
1519             	    token->type = tBGCOLOR;
1520             	  break;
1521             
1522             	case ESC_SHADE:
1523             	  line_highlight_gray = atof (buf);
1524             	  if (line_highlight_gray < 0.0 || line_highlight_gray > 1.0)
1525             	    FATAL ((stderr, _("invalid value for ^@shade escape: %s"), buf));
1526             
1527             	  token->type = tNONE;
1528             	  break;
1529             
1530             	case ESC_BGGRAY:
1531             	  bggray = atof (buf);
1532             	  if (bggray < 0.0 || bggray > 1.0)
1533             	    FATAL ((stderr, _("invalid value for ^@bggray escape: %s"), buf));
1534 rizwank 1.1 
1535             	  token->type = tNONE;
1536             	  break;
1537             
1538             	case ESC_ESCAPE:
1539             	  if (strcmp (buf, "default") == 0)
1540             	    escape_char = default_escape_char;
1541             	  else
1542             	    escape_char = atoi (buf);
1543             	  token->type = tNONE;
1544             	  break;
1545             
1546             	case ESC_SETFILENAME:
1547             	  strcpy (token->u.filename, buf);
1548             	  token->type = tSETFILENAME;
1549             	  break;
1550             
1551             	case ESC_SETPAGENUMBER:
1552             	  token->u.i = atoi (buf);
1553             	  token->type = tSETPAGENUMBER;
1554             	  break;
1555 rizwank 1.1 
1556             	case ESC_NEWPAGE:
1557             	  if (i == 0)
1558             	    token->u.i = 1;	/* The default is the first line. */
1559             	  else
1560             	    token->u.i = atoi (buf);
1561             	  token->type = tNEWPAGE;
1562             	  break;
1563             
1564             	case ESC_SAVEX:
1565             	  token->type = tSAVEX;
1566             	  token->u.i = atoi (buf);
1567             	  break;
1568             
1569             	case ESC_LOADX:
1570             	  token->type = tLOADX;
1571             	  token->u.i = atoi (buf);
1572             	  break;
1573             
1574             	case ESC_PS:
1575             	  token->u.str = xstrdup (buf);
1576 rizwank 1.1 	  token->type = tPS;
1577             	  break;
1578             
1579             	default:
1580             	  /* NOTREACHED */
1581             	  abort ();
1582             	  break;
1583             	}
1584                 }
1585             }
1586             
1587             
1588             /* Get next token from input file <fp>. */
1589             static void
1590             get_next_token (InputStream *is, double linestart, double linepos,
1591             		unsigned int col, double linew, Token *token)
1592             {
1593               static unsigned char *buffer = NULL; /* output buffer */
1594               static unsigned int buflen = 0; /* output buffer's length */
1595               unsigned int bufpos = 0;	/* current position in output buffer */
1596               int ch = 0;
1597 rizwank 1.1   int done = 0;
1598               int i;
1599               static int pending_token = tNONE;
1600               unsigned int original_col = col;
1601             
1602               if (pending_token != tNONE)
1603                 {
1604                   token->type = pending_token;
1605                   pending_token = tNONE;
1606                   return;
1607                 }
1608             
1609             #define DONE_DONE 1
1610             #define DONE_WRAP 2
1611             
1612               while (!done)
1613                 {
1614                   ch = is_getc (is);
1615                   switch (ch)
1616             	{
1617             	case EOF:
1618 rizwank 1.1 	  if (BUFFER_EMPTY ())
1619             	    {
1620             	      token->type = tEOF;
1621             	      return;
1622             	    }
1623             
1624             	  done = DONE_DONE;
1625             	  break;
1626             
1627             	case '\r':
1628             	case '\n':
1629             	  /*
1630             	   * One of these is the newline character and the other one
1631             	   * is carriage return.
1632             	   */
1633             	  if (ch == nl)
1634             	    {
1635             	      /* The newline character. */
1636             	      if (BUFFER_EMPTY ())
1637             		{
1638             		  token->type = tNEWLINE;
1639 rizwank 1.1 		  return;
1640             		}
1641             	      else
1642             		{
1643             		  is_ungetc (ch, is);
1644             		  done = DONE_DONE;
1645             		}
1646             	    }
1647             	  else
1648             	    {
1649             	      /* The carriage return character. */
1650             	      if (BUFFER_EMPTY ())
1651             		{
1652             		  token->type = tCARRIAGE_RETURN;
1653             		  return;
1654             		}
1655             	      else
1656             		{
1657             		  is_ungetc (ch, is);
1658             		  done = DONE_DONE;
1659             		}
1660 rizwank 1.1 	    }
1661             	  break;
1662             
1663             	case '\t':
1664             	  if (font_is_fixed)
1665             	    {
1666             	      i = tabsize - (col % tabsize);
1667             	      for (; i > 0; i--)
1668             		{
1669             		  if (FITS_ON_LINE (' '))
1670             		    EMIT (' ');
1671             		  else
1672             		    {
1673             		      done = DONE_WRAP;
1674             		      break;
1675             		    }
1676             		}
1677             	    }
1678             	  else
1679             	    {
1680             	      /* Proportional font. */
1681 rizwank 1.1 
1682             	      double grid = tabsize * CHAR_WIDTH (' ');
1683             	      col++;
1684             
1685             	      /* Move linepos to the next multiple of <grid>. */
1686             	      linepos = (((int) ((linepos - linestart) / grid) + 1) * grid
1687             			 + linestart);
1688             	      if (linepos >= linew)
1689             		done = DONE_WRAP;
1690             	      else
1691             		done = DONE_DONE;
1692             	    }
1693             	  break;
1694             
1695             	case '\f':
1696             	  if (BUFFER_EMPTY ())
1697             	    {
1698             	      if (interpret_formfeed)
1699             		token->type = tFORMFEED;
1700             	      else
1701             		token->type = tNEWLINE;
1702 rizwank 1.1 	      return;
1703             	    }
1704             	  else
1705             	    {
1706             	      is_ungetc (ch, is);
1707             	      done = DONE_DONE;
1708             	    }
1709             	  break;
1710             
1711             	default:
1712             	  /* Handle special escapes. */
1713             	  if (special_escapes && ch == escape_char)
1714             	    {
1715             	      if (BUFFER_EMPTY ())
1716             		{
1717             		  /* Interpret special escapes. */
1718             		  read_special_escape (is, token);
1719             		  if (token->type != tNONE)
1720             		    return;
1721             
1722             		  /*
1723 rizwank 1.1 		   * Got tNONE special escape => read_special_escape()
1724             		   * has already done what was needed.  Just read more.
1725             		   */
1726             		  break;
1727             		}
1728             	      else
1729             		{
1730             		  is_ungetc (ch, is);
1731             		  done = DONE_DONE;
1732             		  break;
1733             		}
1734             	    }
1735             
1736             	  /* Handle backspace character. */
1737             	  if (ch == bs)
1738             	    {
1739             	      if (BUFFER_EMPTY () || !EXISTS (buffer[bufpos - 1]))
1740             		linepos -= CHAR_WIDTH ('m');
1741             	      else
1742             		linepos -= CHAR_WIDTH (buffer[bufpos - 1]);
1743             
1744 rizwank 1.1 	      done = DONE_DONE;
1745             	      break;
1746             	    }
1747             
1748             	  /* Check normal characters. */
1749             	  if (EXISTS (ch))
1750             	    {
1751             	      if (FITS_ON_LINE (ch))
1752             		{
1753             		  /*
1754             		   * Print control characters (and optionally
1755             		   * characters greater than 127) in the escaped form
1756             		   * so PostScript interpreter will not hang on them.
1757             		   */
1758             		  if (ch < 040 || (clean_7bit && ch >= 0200))
1759             		    {
1760             		      char buf[10];
1761             
1762             		      sprintf (buf, "\\%03o", ch);
1763             		      for (i = 0; buf[i]; i++)
1764             			APPEND_CHAR (buf[i]);
1765 rizwank 1.1 
1766             		      /* Update current point counters manually. */
1767             		      linepos += CHAR_WIDTH (ch);
1768             		      col++;
1769             		    }
1770             		  else if (ch == '(' || ch == ')' || ch == '\\')
1771             		    {
1772             		      /* These must be quoted in PostScript strings. */
1773             		      APPEND_CHAR ('\\');
1774             		      EMIT (ch);
1775             		    }
1776             		  else
1777             		    EMIT (ch);
1778             		}
1779             	      else
1780             		{
1781             		  is_ungetc (ch, is);
1782             		  done = DONE_WRAP;
1783             		}
1784             	    }
1785             	  else if (ISPRINT (ch))
1786 rizwank 1.1 	    {
1787             	      /* Printable, but do not exists in this font. */
1788             	      if (FITS_ON_LINE ('?'))
1789             		{
1790             		  EMIT ('?');
1791             		  if (missing_chars[ch]++ == 0)
1792             		    num_missing_chars++;
1793             		}
1794             	      else
1795             		{
1796             		  is_ungetc (ch, is);
1797             		  done = DONE_WRAP;
1798             		}
1799             	    }
1800             	  else
1801             	    {
1802             	      char buf[20];
1803             	      double len = 0.0;
1804             
1805             	      /*
1806             	       * Non-printable and does not exist in current font, print
1807 rizwank 1.1 	       * it in the format specified by non_printable_format.
1808             	       */
1809             
1810             	      if (non_printable_chars[ch]++ == 0)
1811             		num_non_printable_chars++;
1812             
1813             	      switch (non_printable_format)
1814             		{
1815             		case NPF_SPACE:
1816             		  strcpy (buf, " ");
1817             		  break;
1818             
1819             		case NPF_QUESTIONMARK:
1820             		  strcpy (buf, "?");
1821             		  break;
1822             
1823             		case NPF_CARET:
1824             		  if (ch < 0x20)
1825             		    {
1826             		      buf[0] = '^';
1827             		      buf[1] = '@' + ch;
1828 rizwank 1.1 		      buf[2] = '\0';
1829             		      break;
1830             		    }
1831             		  /* FALLTHROUGH */
1832             
1833             		case NPF_OCTAL:
1834             		  sprintf (buf, "\\%03o", ch);
1835             		  break;
1836             		}
1837             
1838             	      /* Count length. */
1839             	      for (i = 0; buf[i]; i++)
1840             		len += CHAR_WIDTH (buf[i]);
1841             
1842             	      if (linepos + len < linew || col == 0)
1843             		{
1844             		  /* Print it. */
1845             		  for (i = 0; buf[i]; i++)
1846             		    {
1847             		      if (buf[i] == '\\')
1848             			APPEND_CHAR ('\\'); /* Escape '\\' characters. */
1849 rizwank 1.1 		      EMIT (buf[i]);
1850             		    }
1851             		}
1852             	      else
1853             		{
1854             		  is_ungetc (ch, is);
1855             		  done = DONE_WRAP;
1856             		}
1857             	    }
1858             	  break;
1859             	}
1860                 }
1861             
1862               /* Got a string. */
1863             
1864               /* Check for wrapped line. */
1865               if (done == DONE_WRAP)
1866                 {
1867                   /* This line is too long. */
1868                   ch = nl;
1869                   if (line_end == LE_TRUNCATE)
1870 rizwank 1.1 	{
1871             	  /* Truncate this line. */
1872             	  while ((ch = is_getc (is)) != EOF && ch != nl)
1873             	    ;
1874             	}
1875                   else if (!BUFFER_EMPTY () && line_end == LE_WORD_WRAP)
1876             	{
1877             	  int w;
1878             
1879             	  if (ISSPACE (buffer[bufpos - 1]))
1880             	    {
1881             	      /* Skip all whitespace from the end of the wrapped line. */
1882             	      while ((w = is_getc (is)) != EOF && ISSPACE (w))
1883             		;
1884             	      is_ungetc (w, is);
1885             	    }
1886             	  else
1887             	    {
1888             	      /* Find the previous word boundary for the wrap. */
1889             	      for (w = bufpos - 1; w >= 0 && !ISSPACE (buffer[w]); w--)
1890             		;
1891 rizwank 1.1 	      w++;
1892             	      if (w > 0 || original_col > 0)
1893             		{
1894             		  /*
1895             		   * Ok, we found a word boundary.  Now we must unemit
1896             		   * characters from the buffer to the intput stream.
1897             		   *
1898             		   * Note:
1899             		   *  - bufpos is unsigned integer variable
1900             		   *  - some characters are escaped with '\\'
1901             		   *  - some characters are printed in octal notation
1902             		   */
1903             		  do
1904             		    {
1905             		      bufpos--;
1906             
1907             		      /* Check for '(', ')' and '\\'. */
1908             		      if (bufpos > w
1909             			  && (buffer[bufpos] == '('
1910             			      || buffer[bufpos] ==  ')'
1911             			      || buffer[bufpos] == '\\')
1912 rizwank 1.1 			  && buffer[bufpos - 1] == '\\')
1913             			{
1914             			  is_ungetc (buffer[bufpos], is);
1915             			  UNEMIT (buffer[bufpos]);
1916             			  bufpos--;
1917             			}
1918             		      /* Check the octal notations "\\%03o". */
1919             		      else if (bufpos - 2 > w
1920             			       && ISOCTAL (buffer[bufpos])
1921             			       && ISOCTAL (buffer[bufpos - 1])
1922             			       && ISOCTAL (buffer[bufpos - 2])
1923             			       && buffer[bufpos - 3] == '\\')
1924             			{
1925             			  unsigned int ti;
1926             
1927             			  /*
1928             			   * It is a potential octal character.  Now we
1929             			   * must process the buffer from the beginning
1930             			   * and see if `bufpos - 3' really starts a character.
1931             			   */
1932             			  for (ti = w; ti < bufpos - 3; ti++)
1933 rizwank 1.1 			    {
1934             			      if (buffer[ti] == '\\')
1935             				{
1936             				  if (ISOCTAL (buffer[ti + 1]))
1937             				    {
1938             				      unsigned int tti;
1939             
1940             				      for (tti = 0;
1941             					   tti < 3 && ISOCTAL (buffer[ti + 1]);
1942             					   tti++, ti++)
1943             					;
1944             				    }
1945             				  else
1946             				    /* Simple escape. */
1947             				    ti++;
1948             				}
1949             			    }
1950             
1951             			  /*
1952             			   * If <ti> is equal to <bufpos - 3>, we found
1953             			   * an octal character, otherwise the leading
1954 rizwank 1.1 			   * backslash at <bufpos - 3> belongs to the
1955             			   * previous character.
1956             			   */
1957             			  if (ti == bufpos - 3)
1958             			    {
1959             			      int tch;
1960             
1961             			      tch = (((buffer[bufpos - 2] - '0') << 6)
1962             				     + ((buffer[bufpos - 1] - '0') << 3)
1963             				     + (buffer[bufpos] - '0'));
1964             			      is_ungetc (tch, is);
1965             			      UNEMIT (tch);
1966             			      bufpos -= 3;
1967             			    }
1968             			  else
1969             			    /* Normal character. */
1970             			    goto unemit_normal;
1971             			}
1972             		      else
1973             			{
1974             			  /* Normal character, just unget it. */
1975 rizwank 1.1 			unemit_normal:
1976             			  is_ungetc (buffer[bufpos], is);
1977             			  UNEMIT (buffer[bufpos]);
1978             			}
1979             		    }
1980             		  while (bufpos > w);
1981             		}
1982             	    }
1983             	}
1984             
1985                   if (ch == nl)
1986             	{
1987             	  if (line_end == LE_TRUNCATE)
1988             	    {
1989             	      if (do_print)
1990             		num_truncated_lines++;
1991             	      pending_token = tNEWLINE;
1992             	    }
1993             	  else
1994             	    pending_token = tWRAPPED_NEWLINE;
1995             	}
1996 rizwank 1.1       else
1997             	pending_token = tEOF;
1998                 }
1999             
2000               APPEND_CHAR ('\0');
2001               token->type = tSTRING;
2002               token->u.str = (char *) buffer;
2003               token->new_x = linepos;
2004               token->new_col = col;
2005             }
2006             
2007             
2008             static void
2009             dump_ps_page_header (char *fname, int empty)
2010             {
2011               char buf[512];
2012               char *ftail;
2013               int got, i;
2014               char *cp, *cp2;
2015               char *cstr = "%%";
2016               unsigned int nup_subpage;
2017 rizwank 1.1 
2018               /* The N-up printing sub-page. */
2019               nup_subpage = (total_pages - 1) % nup;
2020             
2021               /* Create fdir and ftail. */
2022               ftail = strrchr (fname, '/');
2023             
2024             #if defined(WIN32)
2025               if (ftail == NULL)
2026                 ftail = strrchr (fname, '\\');
2027             #endif /* WIN32 */
2028             
2029               if (ftail == NULL)
2030                 {
2031                   buf[0] = '\0';
2032                   ftail = fname;
2033                 }
2034               else
2035                 {
2036                   ftail++;
2037                   strncpy (buf, fname, ftail - fname);
2038 rizwank 1.1       buf[ftail - fname] = '\0';
2039                 }
2040             
2041               if (nup > 1)
2042                 {
2043                   /* N-up printing is active. */
2044                   cstr = "%";
2045             
2046                   if (nup_subpage == 0)
2047             	{
2048             	  /* This is a real page start. */
2049             
2050             	  switch (page_label)
2051             	    {
2052             	    case LABEL_SHORT:
2053             	      OUTPUT ((cofp, "%%%%Page: (%d-%d) %d\n", current_pagenum,
2054             		       current_pagenum + nup - 1, total_pages / nup + 1));
2055             	      break;
2056             
2057             	    case LABEL_LONG:
2058             	      OUTPUT ((cofp, "%%%%Page: (%s:%3d-%3d) %d\n", ftail,
2059 rizwank 1.1 		       current_pagenum, current_pagenum + nup - 1,
2060             		       total_pages / nup + 1));
2061             	      break;
2062             	    }
2063             
2064             	  /* Page setup. */
2065             	  OUTPUT ((cofp, "%%%%BeginPageSetup\n_S\n"));
2066             
2067             	  if ((total_pages / nup + 1) % 2 == 0)
2068             	    /* Two-side binding options for the even pages. */
2069             	    handle_two_side_options ();
2070             
2071             #define PRINT_BOUNDING_BOXES 0
2072             
2073             #if PRINT_BOUNDING_BOXES
2074             	  OUTPUT ((cofp,
2075             		   "%d %d moveto %d %d lineto %d %d lineto %d %d lineto closepath stroke\n",
2076             		   media->llx, media->lly, media->llx, media->ury,
2077             		   media->urx, media->ury, media->urx, media->lly));
2078             #endif
2079             
2080 rizwank 1.1 	  if (landscape)
2081             	    {
2082             	      if (nup_landscape)
2083             		OUTPUT ((cofp, "90 rotate\n%d %d translate\n",
2084             			 media->lly, -media->urx));
2085             	      else
2086             		OUTPUT ((cofp, "%d %d translate\n", media->llx, media->lly));
2087             	    }
2088             	  else
2089             	    {
2090             	      if (nup_landscape)
2091             		OUTPUT ((cofp, "90 rotate\n%d %d translate\n",
2092             			 media->lly, -media->llx));
2093             	      else
2094             		OUTPUT ((cofp, "%d %d translate\n", media->llx, media->ury));
2095             	    }
2096             	}
2097                 }
2098             
2099               /* Page start comment. */
2100               switch (page_label)
2101 rizwank 1.1     {
2102                 case LABEL_SHORT:
2103                   OUTPUT ((cofp, "%sPage: (%d) %d\n", cstr, current_pagenum, total_pages));
2104                   break;
2105             
2106                 case LABEL_LONG:
2107                   OUTPUT ((cofp, "%sPage: (%s:%3d) %d\n", cstr, ftail, current_pagenum,
2108             	       total_pages));
2109                   break;
2110                 }
2111             
2112               /*
2113                * Page Setup.
2114                */
2115             
2116               OUTPUT ((cofp, "%sBeginPageSetup\n_S\n", cstr));
2117             
2118               if (nup > 1)
2119                 {
2120                   int xm, ym;
2121             
2122 rizwank 1.1       OUTPUT ((cofp, "%% N-up sub-page %d/%d\n", nup_subpage + 1, nup));
2123                   if (landscape)
2124             	{
2125             	  if (nup_columnwise)
2126             	    {
2127             	      xm = nup_subpage % nup_columns;
2128             	      ym = nup_subpage / nup_columns;
2129             	    }
2130             	  else
2131             	    {
2132             	      xm = nup_subpage / nup_rows;
2133             	      ym = nup_subpage % nup_rows;
2134             	    }
2135             
2136             	  OUTPUT ((cofp, "%d %d translate\n",
2137             		   xm * (nup_width + nup_xpad),
2138             		   ym * (nup_height + nup_ypad)));
2139             	}
2140                   else
2141             	{
2142             	  if (nup_columnwise)
2143 rizwank 1.1 	    {
2144             	      xm = nup_subpage / nup_rows;
2145             	      ym = nup_subpage % nup_rows;
2146             	    }
2147             	  else
2148             	    {
2149             	      xm = nup_subpage % nup_columns;
2150             	      ym = nup_subpage / nup_columns;
2151             	    }
2152             
2153             	  OUTPUT ((cofp, "%d %d translate\n",
2154             		   xm * (nup_width + nup_xpad),
2155             		   -((int) (ym * (nup_height + nup_ypad) + nup_height))));
2156             	}
2157                   OUTPUT ((cofp, "%g dup scale\n", nup_scale));
2158             
2159                   /* And finally, the real page setup. */
2160                   if (landscape)
2161             	OUTPUT ((cofp, "90 rotate\n%d %d translate\n", 0, -d_page_h));
2162                 }
2163               else
2164 rizwank 1.1     {
2165                   /* No N-up printing. */
2166             
2167                   if (total_pages % 2 == 0)
2168             	/* Two-side binding options for the even pages. */
2169             	handle_two_side_options ();
2170             
2171                   if (landscape)
2172             	OUTPUT ((cofp, "90 rotate\n%d %d translate\n",
2173             		 media->lly, -media->urx));
2174                   else
2175             	OUTPUT ((cofp, "%d %d translate\n", media->llx, media->lly));
2176                 }
2177             
2178               /* Some constants etc. */
2179               OUTPUT ((cofp, "/pagenum %d def\n", current_pagenum));
2180             
2181               cp = escape_string (fname);
2182               OUTPUT ((cofp, "/fname (%s) def\n", cp));
2183               xfree (cp);
2184             
2185 rizwank 1.1   cp = escape_string (buf);
2186               OUTPUT ((cofp, "/fdir (%s) def\n", cp));
2187               xfree (cp);
2188             
2189               cp = escape_string (ftail);
2190               OUTPUT ((cofp, "/ftail (%s) def\n", cp));
2191               xfree (cp);
2192             
2193               /* Do we have a pending ^@font{} font? */
2194               if (user_fontp)
2195                 {
2196                   if (encoding == default_Fencoding)
2197             	OUTPUT ((cofp, "/%s %g %g SUF\n", Fname, Fpt.w, Fpt.h));
2198                   else
2199             	/* This must be the case. */
2200             	OUTPUT ((cofp, "/%s %g %g SUF_PS\n", Fname, Fpt.w, Fpt.h));
2201                 }
2202             
2203               /* Dump user defined strings. */
2204               if (count_key_value_set (user_strings) > 0)
2205                 {
2206 rizwank 1.1       OUTPUT ((cofp, "%% User defined strings:\n"));
2207                   for (got = strhash_get_first (user_strings, &cp, &i, (void **) &cp2);
2208             	   got;
2209             	   got = strhash_get_next (user_strings, &cp, &i, (void **) &cp2))
2210             	{
2211             	  cp2 = format_user_string ("%Format", cp2);
2212             	  OUTPUT ((cofp, "/%s (%s) def\n", cp, cp2));
2213             	  xfree (cp2);
2214             	}
2215                 }
2216             
2217               /* User supplied header? */
2218               if (page_header)
2219                 {
2220                   char *h_left;
2221                   char *h_center;
2222                   char *h_right = NULL;
2223             
2224                   h_left = format_user_string ("page header", page_header);
2225                   h_center = strchr (h_left, '|');
2226                   if (h_center)
2227 rizwank 1.1 	{
2228             	  *h_center = '\0';
2229             	  h_center++;
2230             
2231             	  h_right = strchr (h_center, '|');
2232             	  if (h_right)
2233             	    {
2234             	      *h_right = '\0';
2235             	      h_right++;
2236             	    }
2237             	}
2238             
2239                   OUTPUT ((cofp, "/user_header_p true def\n"));
2240                   OUTPUT ((cofp, "/user_header_left_str (%s) def\n", h_left));
2241                   OUTPUT ((cofp, "/user_header_center_str (%s) def\n",
2242             	       h_center ? h_center : ""));
2243                   OUTPUT ((cofp, "/user_header_right_str (%s) def\n",
2244             	       h_right ? h_right : ""));
2245                   xfree (h_left);
2246                 }
2247               else
2248 rizwank 1.1     OUTPUT ((cofp, "/user_header_p false def\n"));
2249             
2250               /* User supplied footer? */
2251               if (page_footer)
2252                 {
2253                   char *f_left;
2254                   char *f_center;
2255                   char *f_right = NULL;
2256             
2257                   f_left = format_user_string ("page footer", page_footer);
2258                   f_center = strchr (f_left, '|');
2259                   if (f_center)
2260             	{
2261             	  *f_center = '\0';
2262             	  f_center++;
2263             
2264             	  f_right = strchr (f_center, '|');
2265             	  if (f_right)
2266             	    {
2267             	      *f_right = '\0';
2268             	      f_right++;
2269 rizwank 1.1 	    }
2270             	}
2271             
2272                   OUTPUT ((cofp, "/user_footer_p true def\n"));
2273                   OUTPUT ((cofp, "/user_footer_left_str (%s) def\n", f_left));
2274                   OUTPUT ((cofp, "/user_footer_center_str (%s) def\n",
2275             	       f_center ? f_center : ""));
2276                   OUTPUT ((cofp, "/user_footer_right_str (%s) def\n",
2277             	       f_right ? f_right : ""));
2278                   xfree (f_left);
2279                 }
2280               else
2281                 OUTPUT ((cofp, "/user_footer_p false def\n"));
2282             
2283               OUTPUT ((cofp, "%%%%EndPageSetup\n"));
2284             
2285               /*
2286                * Mark standard page decorations.
2287                */
2288             
2289               if (!empty)
2290 rizwank 1.1     {
2291                   /* Highlight bars. */
2292                   if (highlight_bars)
2293             	OUTPUT ((cofp, "%d %f %d %f highlight_bars\n", highlight_bars,
2294             		 LINESKIP, d_output_y_margin, highlight_bar_gray));
2295             
2296                   /* Underlay. */
2297                   if (underlay != NULL)
2298             	{
2299             	  if (ul_position_p || ul_angle_p)
2300             	    OUTPUT ((cofp, "user_underlay\n"));
2301             	  else
2302             	    OUTPUT ((cofp, "underlay\n"));
2303             	}
2304             
2305                   /* Column lines. */
2306                   if (num_columns > 1 && (header == HDR_FANCY || borders))
2307             	OUTPUT ((cofp, "column_lines\n"));
2308             
2309                   /* Borders around columns. */
2310                   if (borders)
2311 rizwank 1.1 	OUTPUT ((cofp, "column_borders\n"));
2312             
2313                   /* Header. */
2314                   switch (header)
2315             	{
2316             	case HDR_NONE:
2317             	  break;
2318             
2319             	case HDR_SIMPLE:
2320             	case HDR_FANCY:
2321             	  OUTPUT ((cofp, "do_header\n"));
2322             	  break;
2323             	}
2324                 }
2325             
2326               /* Do we have a pending ^@color{} color? */
2327               if (user_colorp)
2328                 OUTPUT ((cofp, "%g %g %g setrgbcolor\n", user_color.r, user_color.g,
2329             	     user_color.b));
2330             }
2331             
2332 rizwank 1.1 
2333             static void
2334             dump_ps_page_trailer ()
2335             {
2336               unsigned int nup_subpage = (total_pages - 1) % nup;
2337             
2338               OUTPUT ((cofp, "_R\n"));
2339             
2340               if (nup > 1)
2341                 {
2342                   if (nup_subpage + 1 == nup)
2343             	/* Real end of page. */
2344             	OUTPUT ((cofp, "_R\nS\n"));
2345                 }
2346               else
2347                 OUTPUT ((cofp, "S\n"));
2348             }
2349             
2350             
2351             static void
2352             dump_empty_page ()
2353 rizwank 1.1 {
2354               if (nup > 1)
2355                 {
2356                   unsigned int nup_subpage = (total_pages - 1) % nup;
2357             
2358                   if (nup_subpage == 0)
2359             	{
2360             	  /* Real start of the page, must do it the harder way. */
2361             	  dump_ps_page_header ("", 1);
2362             	  OUTPUT ((cofp, "_R\n"));
2363             	}
2364                   else
2365             	OUTPUT ((cofp, "%%Page: (-) %d\n", total_pages));
2366             
2367                   if (nup_subpage + 1 == nup)
2368             	/* This is the last page on this sheet, dump us. */
2369             	OUTPUT ((cofp, "_R\nS\n"));
2370                 }
2371               else
2372                 OUTPUT ((cofp, "%%%%Page: (-) %d\nS\n", total_pages));
2373             }
2374 rizwank 1.1 
2375             
2376             static int
2377             recognize_eps_file (Token *token)
2378             {
2379               int i;
2380               char buf[4096];
2381               int line;
2382               int valid_epsf;
2383               float llx, lly, urx, ury;
2384             
2385               MESSAGE (2, (stderr, "^@epsf=\"%s\"\n", token->u.epsf.filename));
2386             
2387               i = strlen (token->u.epsf.filename);
2388               if (i > 0 && token->u.epsf.filename[i - 1] == '|')
2389                 {
2390                   /* Read EPS data from pipe. */
2391                   token->u.epsf.pipe = 1;
2392                   token->u.epsf.filename[i - 1] = '\0';
2393                   token->u.epsf.fp = popen (token->u.epsf.filename, "r");
2394                   if (token->u.epsf.fp == NULL)
2395 rizwank 1.1 	{
2396             	  MESSAGE (0, (stderr,
2397             		       _("epsf: couldn't open pipe to command \"%s\": %s\n"),
2398             		       token->u.epsf.filename, strerror (errno)));
2399             	  return 0;
2400             	}
2401                 }
2402               else
2403                 {
2404                   char *filename;
2405             
2406                   /* Read EPS data from file. */
2407                   filename = tilde_subst (token->u.epsf.filename);
2408             
2409                   token->u.epsf.fp = fopen (filename, "rb");
2410                   xfree (filename);
2411             
2412                   if (token->u.epsf.fp == NULL)
2413             	{
2414             	  if (token->u.epsf.filename[0] != '/')
2415             	    {
2416 rizwank 1.1 	      /* Name is not absolute, let's lookup path. */
2417             	      FileLookupCtx ctx;
2418             
2419             	      ctx.name = token->u.epsf.filename;
2420             	      ctx.suffix = "";
2421             	      ctx.fullname = buffer_alloc ();
2422             
2423             	      if (pathwalk (libpath, file_lookup, &ctx))
2424             		token->u.epsf.fp = fopen (buffer_ptr (ctx.fullname), "rb");
2425             
2426             	      buffer_free (ctx.fullname);
2427             	    }
2428             	  if (token->u.epsf.fp == NULL)
2429             	    {
2430             	      MESSAGE (0, (stderr, _("couldn't open EPS file \"%s\": %s\n"),
2431             			   token->u.epsf.filename, strerror (errno)));
2432             	      return 0;
2433             	    }
2434             	}
2435                 }
2436             
2437 rizwank 1.1   /* Find BoundingBox DSC comment. */
2438             
2439               line = 0;
2440               valid_epsf = 0;
2441               token->u.epsf.skipbuf = NULL;
2442               token->u.epsf.skipbuf_len = 0;
2443               token->u.epsf.skipbuf_pos = 0;
2444             
2445               while (fgets (buf, sizeof (buf), token->u.epsf.fp))
2446                 {
2447                   line++;
2448             
2449                   /* Append data to the skip buffer. */
2450                   i = strlen (buf);
2451                   if (i + token->u.epsf.skipbuf_pos >= token->u.epsf.skipbuf_len)
2452             	{
2453             	  token->u.epsf.skipbuf_len += 8192;
2454             	  token->u.epsf.skipbuf = xrealloc (token->u.epsf.skipbuf,
2455             					    token->u.epsf.skipbuf_len);
2456             	}
2457                   memcpy (token->u.epsf.skipbuf + token->u.epsf.skipbuf_pos, buf, i);
2458 rizwank 1.1       token->u.epsf.skipbuf_pos += i;
2459             
2460                   /* Check the "%!" magic cookie. */
2461                   if (line == 1)
2462             	{
2463             	  if (buf[0] != '%' || buf[1] != '!')
2464             	    {
2465             	      MESSAGE (0,
2466             		       (stderr,
2467             			_("EPS file \"%s\" does not start with \"%%!\" magic\n"),
2468             			token->u.epsf.filename));
2469             	      break;
2470             	    }
2471             	}
2472             
2473             #define BB_DSC "%%BoundingBox:"
2474             
2475                   if (strncmp (buf, BB_DSC, strlen (BB_DSC)) == 0)
2476             	{
2477             	  i = sscanf (buf + strlen (BB_DSC), "%f %f %f %f",
2478             		      &llx, &lly, &urx, &ury);
2479 rizwank 1.1 	  if (i != 4)
2480             	    {
2481             	      /* (atend) ? */
2482             
2483             	      /* Skip possible whitespace. */
2484             	      for (i = strlen (BB_DSC);
2485             		   buf[i] && (buf[i] == ' ' || buf[i] == '\t');
2486             		   i++)
2487             		;
2488             #define BB_DSC_ATEND "(atend)"
2489             	      if (strncmp (buf + i, BB_DSC_ATEND, strlen (BB_DSC_ATEND)) != 0)
2490             		{
2491             		  /* No, this BoundingBox comment is corrupted. */
2492             		  MESSAGE (0, (stderr, _("EPS file \"%s\" contains malformed \
2493             %%%%BoundingBox row:\n\"%.*s\"\n"),
2494             			       token->u.epsf.filename, strlen (buf) - 1, buf));
2495             		  break;
2496             		}
2497             	    }
2498             	  else
2499             	    {
2500 rizwank 1.1 	      /* It was a valid EPS file. */
2501             
2502             	      /* We store bounding box in int format. */
2503             	      token->u.epsf.llx = llx;
2504             	      token->u.epsf.lly = lly;
2505             	      token->u.epsf.urx = urx;
2506             	      token->u.epsf.ury = ury;
2507             
2508             	      valid_epsf = 1;
2509             	      break;
2510             	    }
2511             	}
2512                 }
2513             
2514               /* Check that we found the BoundingBox comment. */
2515               if (!valid_epsf)
2516                 {
2517                   MESSAGE (0, (stderr, _("EPS file \"%s\" is not a valid EPS file\n"),
2518             		   token->u.epsf.filename));
2519                   if (token->u.epsf.pipe)
2520             	pclose (token->u.epsf.fp);
2521 rizwank 1.1       else
2522             	fclose (token->u.epsf.fp);
2523                   xfree (token->u.epsf.skipbuf);
2524                   return 0;
2525                 }
2526             
2527               MESSAGE (2, (stderr, "BoundingBox: %d %d %d %d\n",
2528             	       token->u.epsf.llx, token->u.epsf.lly,
2529             	       token->u.epsf.urx, token->u.epsf.ury));
2530             
2531               return 1;
2532             }
2533             
2534             
2535             static void
2536             paste_epsf (Token *token)
2537             {
2538               char buf[4096];
2539               int i;
2540             
2541               /* EPSF import header. */
2542 rizwank 1.1   OUTPUT ((cofp, "BeginEPSF\n"));
2543               OUTPUT ((cofp, "%g %g translate\n", token->new_x, token->new_y));
2544               OUTPUT ((cofp, "%g %g scale\n", token->u.epsf.xscale, token->u.epsf.yscale));
2545               OUTPUT ((cofp, "%d %d translate\n", -token->u.epsf.llx,
2546             	   -token->u.epsf.lly));
2547               OUTPUT ((cofp, "%d %d %d %d Box clip newpath\n",
2548             	   token->u.epsf.llx - 1,
2549             	   token->u.epsf.lly - 1,
2550             	   token->u.epsf.urx - token->u.epsf.llx + 2,
2551             	   token->u.epsf.ury - token->u.epsf.lly + 2));
2552               OUTPUT ((cofp, "%%%%BeginDocument: %s%s\n", token->u.epsf.filename,
2553             	   token->u.epsf.pipe ? "|" : ""));
2554             
2555               if (do_print)
2556                 {
2557                   /* Dump skip buffer. */
2558                   fwrite (token->u.epsf.skipbuf, 1, token->u.epsf.skipbuf_pos, cofp);
2559             
2560                   /* Dump file. */
2561                   while ((i = fread (buf, 1, sizeof (buf), token->u.epsf.fp)) != 0)
2562             	fwrite (buf, 1, i, cofp);
2563 rizwank 1.1     }
2564             
2565               /* Add a newline to keep comments correct */
2566               OUTPUT ((cofp, "\n"));
2567             
2568               /* EPSF import trailer. */
2569               OUTPUT ((cofp, "%%%%EndDocument\nEndEPSF\n"));
2570             
2571               /* Cleanup. */
2572               if (token->u.epsf.pipe)
2573                 pclose (token->u.epsf.fp);
2574               else
2575                 fclose (token->u.epsf.fp);
2576               xfree (token->u.epsf.skipbuf);
2577             }
2578             
2579             
2580             static double
2581             read_float (InputStream *is, int units, int horizontal)
2582             {
2583               char buf[256];
2584 rizwank 1.1   int i, ch;
2585               double val;
2586             
2587               for (i = 0; (i < sizeof (buf) - 1
2588             	       && (ch = is_getc (is)) != EOF
2589             	       && ISNUMBERDIGIT (ch));
2590                    i++)
2591                 buf[i] = ch;
2592               buf[i] = '\0';
2593               if (ch != EOF)
2594                 is_ungetc (ch, is);
2595             
2596               val = atof (buf);
2597             
2598               if (units)
2599                 {
2600                   /* Get unit. */
2601                   ch = is_getc (is);
2602                   switch (ch)
2603             	{
2604             	case 'c':		/* centimeters */
2605 rizwank 1.1 	  val *= 72 / 2.54;
2606             	  break;
2607             
2608             	case 'p':		/* PostScript points */
2609             	  break;
2610             
2611             	case 'i':		/* inches */
2612             	  val *= 72;
2613             	  break;
2614             
2615             	default:
2616             	  is_ungetc (ch, is);
2617             	  /* FALLTHROUGH */
2618             
2619             	case 'l':		/* lines or characters */
2620             	  if (horizontal)
2621             	    val *= CHAR_WIDTH ('m');
2622             	  else
2623             	    val *= LINESKIP;
2624             	  break;
2625             	}
2626 rizwank 1.1     }
2627             
2628               return val;
2629             }
2630             
2631             
2632             /* Magics used to recognize different pass-through files. */
2633             static struct
2634             {
2635               char *magic;
2636               unsigned int magiclen;
2637               char *name;
2638               int revert_delta;
2639             } pass_through_magics[] =
2640               {
2641                 {"%!", 	2, "PostScript", 	-2},
2642                 {"\004%!",	3, "PostScript", 	-2},
2643                 {"\033E",	2, "PCL",		-2},
2644                 {"\033%",	2, "PCL",		-2},
2645                 {NULL, 0, NULL, 0},
2646               };
2647 rizwank 1.1 
2648             
2649             static int
2650             do_pass_through (char *fname, InputStream *is)
2651             {
2652               int ch;
2653               unsigned long saved_pos = is->bufpos;
2654               int i, j;
2655             
2656               if (output_language_pass_through)
2657                 MESSAGE (1,
2658             	     (stderr,
2659             	      _("passing through all input files for output language `%s'\n"),
2660             	      output_language));
2661               else
2662                 {
2663                   /*
2664                    * Try to recognize pass-through files.
2665                    */
2666             
2667                   for (i = 0; pass_through_magics[i].magic; i++)
2668 rizwank 1.1 	{
2669             	  for (j = 0; j < pass_through_magics[i].magiclen; j++)
2670             	    {
2671             	      ch = is_getc (is);
2672             	      if (ch == EOF
2673             		  || ch != (unsigned char) pass_through_magics[i].magic[j])
2674             		break;
2675             	    }
2676             
2677             	  if (j >= pass_through_magics[i].magiclen)
2678             	    /* The <i>th one matched. */
2679             	    break;
2680             
2681             	  /*
2682             	   * Try the next one, but first, seek the input stream to its
2683             	   * start.
2684             	   */
2685             	  is->bufpos = saved_pos;
2686             	}
2687             
2688                   /* Did we find any? */
2689 rizwank 1.1       if (pass_through_magics[i].magic == NULL)
2690             	/* No we didn't. */
2691             	return 0;
2692             
2693                   /* Yes, it really is a pass-through file.  Now do the pass through. */
2694             
2695                   is->bufpos += pass_through_magics[i].revert_delta;
2696             
2697                   if (ps_header_dumped)
2698             	{
2699             	  /* A pass-through file between normal ASCII files, obey DSC. */
2700             
2701             	  /*
2702             	   * XXX I don't know how to handle PCL files... Let's hope none
2703             	   * mixes them with the normal ASCII files.
2704             	   */
2705             
2706             	  OUTPUT ((cofp,
2707             		   "%%%%Page: (%s) -1\n_S\n%%%%BeginDocument: %s\n",
2708             		   fname, fname));
2709             	}
2710 rizwank 1.1 
2711                   MESSAGE (1, (stderr, _("passing through %s file \"%s\"\n"),
2712             		   pass_through_magics[i].name, fname));
2713                 }
2714             
2715               /* And now, do the actual pass-through. */
2716               do
2717                 {
2718                   /* Note: this will be written directly to the <ofp>. */
2719                   fwrite (is->buf + is->bufpos, 1, is->data_in_buf - is->bufpos, ofp);
2720                   is->bufpos = is->data_in_buf;
2721             
2722                   /* Read more data to the input buffer. */
2723                   ch = is_getc (is);
2724                   is->bufpos = 0;
2725                 }
2726               while (ch != EOF);
2727             
2728               if (!output_language_pass_through)
2729                 {
2730                   if (ps_header_dumped)
2731 rizwank 1.1 	/*
2732             	 * XXX How to end a PCL file mixed between ASCII files?
2733             	 */
2734             	OUTPUT ((cofp, "%%%%EndDocument\n_R\n"));
2735                 }
2736             
2737               return 1;
2738             }
2739             
2740             
2741             static void
2742             print_line_number (double x, double y, double space, double margin,
2743             		   unsigned int linenum)
2744             {
2745               double len = 0.0;
2746               char buf[20];
2747               int i;
2748               char *saved_Fname = "";
2749               FontPoint saved_Fpt;
2750               InputEncoding saved_Fencoding;
2751             
2752 rizwank 1.1   saved_Fpt.w = 0.0;
2753               saved_Fpt.h = 0.0;
2754             
2755               /* Do not print linenumbers for wrapped lines. */
2756               if (linenum == print_line_number_last)
2757                 return;
2758               print_line_number_last = linenum;
2759             
2760               if (user_fontp)
2761                 {
2762                   /* Re-select our default typing font. */
2763                   saved_Fname = Fname;
2764                   saved_Fpt.w = Fpt.w;
2765                   saved_Fpt.h = Fpt.h;
2766                   saved_Fencoding = encoding;
2767             
2768                   Fname = default_Fname;
2769                   Fpt.w = default_Fpt.w;
2770                   Fpt.h = default_Fpt.h;
2771                   encoding = default_Fencoding;
2772             
2773 rizwank 1.1       OUTPUT ((cofp, "/F-gs-font %g %g SF\n", Fpt.w, Fpt.h));
2774                   read_font_info ();
2775                 }
2776             
2777               /* Count linenumber string length. */
2778               sprintf (buf, "%d", linenum);
2779               for (i = 0; buf[i]; i++)
2780                 len += CHAR_WIDTH (buf[i]);
2781             
2782               /* Print line numbers. */
2783               OUTPUT ((cofp, "%g %g M (%s:) s\n", x + space - len, y, buf));
2784             
2785               if (user_fontp)
2786                 {
2787                   /* Switch back to the user font. */
2788                   Fname = saved_Fname;
2789                   Fpt.w = saved_Fpt.w;
2790                   Fpt.h = saved_Fpt.h;
2791                   encoding = saved_Fencoding;
2792             
2793                   OUTPUT ((cofp, "/%s %g %g SUF\n", Fname, Fpt.w, Fpt.h));
2794 rizwank 1.1       read_font_info ();
2795                 }
2796             }
2797             
2798             
2799             /*
2800              * The name of the divert file, shared between divert() and undivert()
2801              * functions.
2802              */
2803             static char divertfname[512];
2804             
2805             static void
2806             divert ()
2807             {
2808               assert (divertfp == NULL);
2809             
2810               /* Open divert file. */
2811             
2812               divertfp = tmpfile ();
2813               if (divertfp == NULL)
2814                 FATAL ((stderr, _("couldn't create temporary divert file: %s"),
2815 rizwank 1.1 	    strerror (errno)));
2816             
2817               cofp = divertfp;
2818             }
2819             
2820             
2821             static void
2822             undivert ()
2823             {
2824               char buf[1024];
2825               int doc_level = 0;
2826               char *cp;
2827             
2828               assert (divertfp != NULL);
2829             
2830               if (fseek (divertfp, 0, SEEK_SET) != 0)
2831                 FATAL ((stderr, _("couldn't rewind divert file: %s"), strerror (errno)));
2832             
2833               while (fgets (buf, sizeof (buf), divertfp))
2834                 {
2835                   if (strncmp (buf, "%%BeginDocument", 15) == 0)
2836 rizwank 1.1 	doc_level++;
2837                   else if (strncmp (buf, "%%EndDocument", 13) == 0)
2838             	doc_level--;
2839             
2840                   if (doc_level == 0)
2841             	{
2842             	  if (strncmp (buf, "% User defined strings", 22) == 0)
2843             	    {
2844             	      fputs (buf, ofp);
2845             	      while (fgets (buf, sizeof (buf), divertfp))
2846             		{
2847             		  if (strncmp (buf, "%%EndPageSetup", 14) == 0)
2848             		    break;
2849             
2850             		  /* Patch total pages to the user defined strings. */
2851             		  cp = strchr (buf, '\001');
2852             		  if (cp)
2853             		    {
2854             		      *cp = '\0';
2855             		      fputs (buf, ofp);
2856             		      fprintf (ofp, "%d", total_pages_in_file);
2857 rizwank 1.1 		      fputs (cp + 1, ofp);
2858             		    }
2859             		  else
2860             		    fputs (buf, ofp);
2861             		}
2862             	    }
2863             	}
2864             
2865                   fputs (buf, ofp);
2866                 }
2867             
2868               fclose (divertfp);
2869               divertfp = NULL;
2870             
2871               cofp = ofp;
2872             }
2873             
2874             
2875             static void
2876             handle_two_side_options ()
2877             {
2878 rizwank 1.1   if (rotate_even_pages)
2879                 /* Rotate page 180 degrees. */
2880                 OUTPUT ((cofp, "180 rotate\n%d %d translate\n",
2881             	     -media->w, -media->h));
2882             
2883               if (swap_even_page_margins)
2884                 OUTPUT ((cofp, "%d 0 translate\n",
2885             	     -(media->llx - (media->w - media->urx))));
2886             }

Rizwan Kassim
Powered by
ViewCVS 0.9.2