source: tags/svn.1.5.4/TOOLS/arb_a2ps.c

Last change on this file was 8309, checked in by westram, 14 years ago
  • moved much code into static scope

(partly reverted by [8310])

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 59.8 KB
Line 
1//**********************************************************************
2/*                                                                      */
3// Description: Ascii to PostScript printer program.
4// File: bounty:/archive/src/a2ps/Last/a2ps.c
5// Created: Fri Nov 5 8:20 1993 by miguel@bountyimag.fr (Miguel Santana)
6// Version: 4.3
7/*                                                                      */
8// Edit history:
9// 1) Derived of shell program written by evan@csli (Evan Kirshenbaum).
10//    Written in C for improve speed execution and portability. Many
11//    improvements have been added.
12// Fixes by Oscar Nierstrasz @ cui.uucp:
13// 2) Fixed incorrect handling of stdin (removed error if no file names)
14// 3) Added start_page variable to eliminate blank pages printed for
15//      files that are exactly multiples of 132 lines (e.g., man pages)
16// Modified by santana@imag.fr:
17// 4) Added new options at installation : sheet format (height/width in
18//    inches), page format (number of columns per line and of lines per
19//    page).
20// Modified by santana@imag.fr:
21// 5) Added new option to print n copies of a same document.
22// 6) Cut long filenames if don't fit in the page header.
23// Modified by Tim Clark (T.Clark@warwick.ac.uk):
24// 7) Two additional modes of printing (portrait and wide format modes)
25// 8) Fixed to cope with filenames which contain a character which must
26//    be escaped in a PostScript string.
27// Modified by santana@imag.fr to
28// 9) Added new option to suppress heading printing.
29// 10) Added new option to suppress page surrounding border printing.
30// 11) Added new option to change font size. Lines and columns are
31//     automatically adjusted, depending on font size and printing mode
32// 12) Minor changes (best layout, usage message, etc).
33// Modified by tullemans@apolloway.prl.philips.nl
34// 13) Backspaces (^H) are now handled correctly.
35// Modified by Johan Vromans (jv@mh.nl) to
36// 14) Added new option to give a header title that replaces use of
37//     filename.
38// Modified by craig.r.stevenson@att.com to
39// 15) Print last modification date/time in header
40// 16) Printing current date/time on left side of footer (optional)
41// Modified by erikt@cs.umu.se:
42// 17) Added lpr support for the BSD version
43// 18) Added som output of pages printed.
44// Modified by wstahw@lso.win.tue.nl:
45// 19) Added option to allowing the printing of 2 files in one sheet
46// Modified by mai@wolfen.cc.uow.oz
47// 20) Added an option to set the lines per page to a specified value.
48// 21) Added support for printing nroff manuals
49// Modified by santana@imag.fr
50// 22) Integration of changes.
51// 23) No more standard header file (printed directly by a2ps).
52// 24) New format for command options.
53// 25) Other minor changes.
54// Modified by Johan Garpendahl (garp@isy.liu.se) and santana@imag.fr:
55// 26) Added 8-bit characters printing as ISO-latin 1 chars
56// Modified by John Interrante (interran@uluru.stanford.edu) and
57// santana@imag.fr:
58// 27) Two pages per physical page in portrait mode
59// Modified by santana@imag.fr:
60// 28) New option for two-sided printing
61// 29) Several fixes
62// Modified by Chris Adamo (adamo@ll.mit.edu) and
63//     Larry Barbieri (lbarbieri@ll.mit.edu) 3/12/93
64// 30) Output format enhancements.
65// 31) Added login_id flag (for SYSV and BSD only) for printing user's
66//     login ID at top of page.  Added command line parameter (-nL) to
67//     suppress this feature.
68// 33) Added filename_footer flag for printing file name at bottom
69//     of page.  Added command line parameter (-nu) to suppress this
70//     feature.
71// 34) Added -B (-nB) options to enable (disable) bold font
72// Modified by santana@imag.fr:
73// 35) Adapted to respect Adobe conventions for page independence. A2ps
74//     output can be now used by other Postscript processors.
75// 36) Names of most postscript variables have been coded in order to
76//     reduce the size of the output.
77// 37) Ansi C compilers are now automatically taken into account.
78// 38) Enhanced routine for cutting long filenames
79// 39) Added -q option to print files in quiet mode (no summary)
80// 40) Fixed some little bugs (counters, modification time for stdin,
81//     character separator when printing line numbers and cutting a
82//     line).
83// 41) Some minor changes (new preprocessing variables, formatting)
84/*                                                                      */
85//**********************************************************************
86
87/*
88 * Copyright (c) 1993, 1994, Miguel Santana, M.Santana@frgu.bull.fr
89 *
90 * Permission is granted to use, copy, and distribute this software for
91 * non commercial use, provided that the above copyright notice appear in
92 * all copies and that both that copyright notice and this permission
93 * notice appear in supporting documentation.
94 *
95 * Permission to modify the software is granted, but not the right to
96 * distribute the modified code. Please report bugs and changes to
97 * M.Santana@frgu.bull.fr
98 *
99 * This software is provided "as is" without express or implied warranty.
100 */
101
102
103//**********************************************************************
104/*                                                                      */
105//                      I n c l u d e   f i l e s
106/*                                                                      */
107//**********************************************************************
108
109#include <stdio.h>
110#include <stdlib.h>
111#include <unistd.h>
112#include <ctype.h>
113#include <sys/types.h>
114#include <sys/stat.h>
115
116#ifdef __STDC__
117#include <stdlib.h>
118#include <time.h>
119#include <string.h>
120#else
121#include <strings.h>
122#ifdef SYSV
123#include <sys/timeb.h>
124#include <time.h>
125#include <sys/utsname.h>
126#else
127#ifndef BSD
128#define BSD     1
129#endif
130#include <sys/time.h>
131#endif
132#endif
133
134
135//**********************************************************************
136/*                                                                      */
137//           P r e p r o c e s s i n g   d e f i n i t i o n s
138/*                                                                      */
139//**********************************************************************
140
141/*
142 * Common definitions
143 */
144#define FALSE           0
145#define TRUE            1
146#ifndef NULL
147#define NULL            0
148#endif
149#ifndef NUL
150#define NUL             '\0'
151#endif
152#ifndef EXIT_SUCCESS
153#define EXIT_SUCCESS    0
154#endif
155#ifndef EXIT_FAILURE
156#define EXIT_FAILURE    1
157#endif
158
159
160/*
161 * Version
162 */
163#define VERSION "4.3"
164#define LPR_PRINT 1
165
166/*
167 * Default page dimensions
168 */
169#ifndef WIDTH
170#define WIDTH   8.27
171#endif
172
173#ifndef HEIGHT
174#define HEIGHT  11.0
175#endif
176
177#ifndef MARGIN
178#define MARGIN  .5
179#endif
180
181
182/*
183 * Pathname separator for file system
184 */
185#ifndef DIR_SEP
186#define DIR_SEP '/'
187#endif
188
189
190/*
191 * Printing parameters
192 */
193#if LPR_PRINT
194
195#ifndef LPR_COMMAND
196#define LPR_COMMAND     "lpr"
197#endif
198
199#ifndef LPR_OPT
200#define LPR_OPT "-l"
201#endif
202
203#if defined(ONESIDED) && defined(TWOSIDED)
204#define RECTO_VERSO_PRINTING
205#ifndef TWOSIDED_DFLT
206#define TWOSIDED_DFLT   TRUE
207#endif
208#endif
209
210#endif
211
212
213/*
214 * Configuration values
215 */
216#define PORTRAIT_HEADER         0.29
217#define LANDSCAPE_HEADER        0.22
218#define PIXELS_INCH             72
219#define MAXFILENAME             32
220#define MAX_LINES               320             // max. lines per page
221#define MAN_LINES               66              // no lines for a man
222#define IS_ROMAN                0               // normal font
223#define IS_BOLD                 1               // bold sequence flag
224#if defined(SYSV) || defined(BSD)
225#define MAX_HOSTNAME            40
226#endif
227
228
229//**********************************************************************
230/*                                                                      */
231//                 G l o b a l   d e f i n i t i o n s
232/*                                                                      */
233//**********************************************************************
234
235
236/*
237 * Global types
238 */
239typedef enum { BOLD, NORMAL } WEIGHT;           // font weights
240
241
242/*
243 * Function declarations.
244 */
245
246static void print_page_prologue(int side);
247static void print_standard_prologue(char *datestring);
248static void startpage();
249static void endpage();
250
251#if defined(SYSV) || defined(BSD)
252char *getlogin();
253#endif
254#if defined(BSD)
255int   gethostname(char *name, int namelen);
256#endif
257
258/*
259 * Flags related to options.
260 */
261static int numbering = FALSE;          // Line numbering option
262static int folding = TRUE;             // Line folding option
263static int restart = FALSE;            // Don't restart page number after each file
264static int only_printable = FALSE;     // Replace non printable char by space
265static int interpret = TRUE;           // Interpret TAB, FF and BS chars option
266static int print_binaries = FALSE;     // Force printing for binary files
267static int landscape = TRUE;           // Otherwise portrait format sheets
268static int new_landscape = TRUE;       // To scrute changes of landscape option
269static int twinpages = TRUE;           // 2 pages per sheet if true, 1 otherwise
270static int new_twinpages = TRUE;       // To scrute changes of twinpages option
271static int twinfiles = FALSE;          // Allow 2 files per sheet
272static int no_header = FALSE;          // TRUE if user doesn't want the header
273static int no_border = FALSE;          // Don't print the surrounding border ?
274static int printdate = FALSE;          // Print current date as footnote
275static int filename_footer = TRUE;     // Print file name at bottom of page
276static int no_summary = FALSE;         // Quiet mode?
277static WEIGHT fontweight = NORMAL;     // Control font weight: BOLD or NORMAL
278static WEIGHT new_fontweight = NORMAL; // To scrute changes of bold option
279#if defined(SYSV) || defined(BSD)
280int login_id = TRUE;            // Print login ID at top of page
281#endif
282#if LPR_PRINT
283static int lpr_print = TRUE;           // Fork a lpr process to do the printing
284#ifdef RECTO_VERSO_PRINTING
285int rectoverso = TWOSIDED_DFLT; // Two-side printing
286#endif
287#endif
288static int ISOlatin1 = FALSE;          // Print 8-bit characters?
289
290
291/*
292 * Counters of different kinds.
293 */
294static int column = 0;                 // Column number (in current line)
295static int line = 0;                   // Line number (in current page)
296static int line_number = 0;            // Source line number
297static int pages = 0;                  // Number of logical pages printed
298static int sheets = 0;                 // Number of physical pages printed
299static int old_pages, old_sheets;      // Value before printing current file
300static int sheetside = 0;              // Side of the sheet currently printing
301static int linesperpage;               // Lines per page
302static int lines_requested = 0;        // Lines per page requested by the user
303static int new_linesrequest = 0;       // To scrute new values for lines_requested
304static int columnsperline;             // Characters per output line
305static int nonprinting_chars, chars;   // Number of nonprinting and total chars
306static int copies_number = 1;          // Number of copies to print
307static int column_width = 8;           // Default column tab width (8)
308
309
310/*
311 * Other global variables.
312 */
313static int first_page;                 // First page for a file
314static int no_files = TRUE;            // No file until now
315static int prefix_width;               // Width in characters for line prefix
316static float fontsize = 0.0;           // Size of a char for body font
317static float new_fontsize = 0.0;       // To scrute new values for fontsize
318static char *command;                  // Name of a2ps program
319static char *lpr_opt = NULL;           // Options to lpr
320static char *header_text = NULL;       // Allow for different header text
321static float header_size;              // Size of the page header
322static char *prologue = NULL;          // postscript header file
323static char current_filename[MAXFILENAME+1];   // Name of the file being printed
324static char currentdate[18];           // Date for today
325static char filedate[18];              // Last modification time for current file
326#if defined(SYSV) || defined(BSD)
327char *login = NULL;             // user's login name and host machine
328#endif
329
330
331/*
332 * Sheet dimensions
333 */
334static double page_height = HEIGHT;    // Paper height
335static double page_width = WIDTH;      // Paper width
336
337
338//**********************************************************************
339/*                                                                      */
340/*                                                                      */
341//**********************************************************************
342
343/*
344 * Print a usage message.
345 */
346static void usage(int failure) {
347    // failure: Must we exit with a failure code?
348    fprintf(stderr, "A2ps v%s usage: %s [pos. or global options] [ f1 [ [pos. options] f2 ...] ]\n", VERSION, command);
349    fprintf(stderr, "pos.   =  -#num\t\tnumber of copies to print\n");
350    fprintf(stderr, "          -1\t\tone page per sheet\n");
351    fprintf(stderr, "          -2\t\tTWIN PAGES per sheet\n");
352    fprintf(stderr, "          -d\t-nd\tprint (DON'T PRINT) current date at the bottom\n");
353    fprintf(stderr, "          -Fnum\t\tfont size, num is a float number\n");
354    fprintf(stderr, "          -Hstr\t\tuse str like header title for subsequent files\n");
355#if defined(SYSV) || defined(BSD)
356    fprintf(stderr, "          \t-nL\tdon't print login ID on top of page\n");
357#endif
358    fprintf(stderr, "          -l\t\tprint in LANDSCAPE mode\n");
359    fprintf(stderr, "          -lnum\t\tuse num lines per page\n");
360    fprintf(stderr, "          -m\t\tprocess the file as a man\n");
361    fprintf(stderr, "          -n\t-nn\tNUMBER (don't number) line files\n");
362    fprintf(stderr, "          -p\t\tprint in portrait mode\n");
363    fprintf(stderr, "          -q\t\tprint in quiet mode (no summary)\n");
364    fprintf(stderr, "          -s\t-ns\tPRINT (don't print) surrounding borders\n");
365    fprintf(stderr, "\n");
366    fprintf(stderr, "global =  -?\t\tprint this information\n");
367    fprintf(stderr, "          -B\t-nB\tprint (DON'T PRINT) in bold font\n");
368    fprintf(stderr, "          -b\t-nb\tforce (DON'T FORCE) binary printing\n");
369    fprintf(stderr, "          -c\t-nc\tallow (DON'T ALLOW) two files on the same sheet\n");
370    fprintf(stderr, "          -f\t-nf\tFOLD (don't fold) lines\n");
371    fprintf(stderr, "          \t-nH\tdon't print any header\n");
372    fprintf(stderr, "          -h\t\tprint this information\n");
373    fprintf(stderr, "          -Ifile\tinclude this file as a2ps prologue\n");
374    fprintf(stderr, "          -i\t-ni\tINTERPRET (don't interpret) tab, bs and ff chars\n");
375#if LPR_PRINT
376    fprintf(stderr, "          -Pprinter -nP\tSEND (don't send) directly to the printer");
377#ifdef LPR_OPT
378    if (LPR_OPT != NULL && sizeof(LPR_OPT) > 0)
379        fprintf(stderr, "\n\t\t\t(with options '%s' and -Pprinter)", LPR_OPT);
380#endif
381    fprintf(stderr, "\n");
382#endif
383    fprintf(stderr, "          -r\t-nr\tRESTART (don't restart) page number after each file\n");
384#ifdef RECTO_VERSO_PRINTING
385#ifdef TWOSIDED_DFLT
386    fprintf(stderr, "          -s1\t-s2\tone-sided (TWO-SIDED) printing\n");
387#else
388    fprintf(stderr, "          -s1\t-s2\tONE-SIDED (two-sided) printing\n");
389#endif
390#endif
391    fprintf(stderr, "          -tnum\t\tset tab size to n\n");
392    fprintf(stderr, "          \t-nu\tdon't print a filename footer\n");
393    fprintf(stderr, "          -v\t-nv\tVISIBLE (blank) display of unprintable chars\n");
394    fprintf(stderr, "          -8\t-n8\tdisplay (DON'T DISPLAY) 8-bit chars\n");
395    exit(failure);
396}
397
398/*
399 * Set an option only if it's global.
400 */
401static void set_global_option(char *arg) {
402    switch (arg[1]) {
403        case '?':                               // help
404        case 'h':
405            usage(EXIT_SUCCESS);
406        case 'b':                               // print binary files
407            if (arg[2] != NUL)
408                usage(EXIT_FAILURE);
409            print_binaries = TRUE;
410            break;
411        case 'c':                               // allow two files per sheet
412            if (arg[2] != NUL)
413                usage(EXIT_FAILURE);
414            twinfiles = TRUE;
415            break;
416        case 'f':                               // fold lines too large
417            if (arg[2] != NUL)
418                usage(EXIT_FAILURE);
419            folding = TRUE;
420            break;
421        case 'I':                               // include this file as a2ps prologue
422            if (arg[2] == NUL)
423                usage(EXIT_FAILURE);
424            prologue = arg+2;
425            break;
426        case 'i':                               // interpret control chars
427            if (arg[2] != NUL)
428                usage(EXIT_FAILURE);
429            interpret = TRUE;
430            break;
431        case 'n':
432            if (arg[2] == NUL)
433                return;
434            if (arg[3] != NUL)
435                usage(EXIT_FAILURE);
436            switch (arg[2]) {
437                case 'b':                       // don't print binaries
438                    print_binaries = FALSE;
439                    break;
440                case 'c':                       // don't allow 2 files/sheet
441                    twinfiles = FALSE;
442                    break;
443                case 'f':                       // cut lines too long
444                    folding = FALSE;
445                    break;
446                case 'H':                       // don't print header
447                    no_header = TRUE;
448                    break;
449                case 'i':                       // don't interpret ctrl chars
450                    interpret = FALSE;
451                    break;
452#if LPR_PRINT
453                case 'P':                       // don't lpr
454                    lpr_print = FALSE;
455                    break;
456#endif
457                case 'r':                       // don't restart sheet number
458                    restart = FALSE;
459                    break;
460                case 'v':                       // only printable chars
461                    only_printable = TRUE;
462                    break;
463                case '8':                       // don't print 8-bit chars
464                    ISOlatin1 = FALSE;
465                    break;
466                case 'B':
467                case 'd':
468                case 'L':
469                case 'm':
470                case 'n':
471                case 's':
472                case 'u':
473                    if (arg[3] != NUL)
474                        usage(EXIT_FAILURE);
475                    return;
476                default:
477                    usage(EXIT_FAILURE);
478            }
479            break;
480#if LPR_PRINT
481        case 'P':                                       // fork a process to print
482            if (arg[2] != NUL) {
483                lpr_opt = (char *)malloc(strlen(arg)+1);
484                strcpy(lpr_opt, arg);
485            }
486            lpr_print = TRUE;
487            break;
488#endif
489        case 'q':                                       // don't print a summary
490            no_summary = TRUE;
491            break;
492        case 'r':                                       // restart sheet number
493            if (arg[2] != NUL)
494                usage(EXIT_FAILURE);
495            restart = TRUE;
496            break;
497        case 's':
498            if (arg[2] == NUL)
499                return;
500#ifdef RECTO_VERSO_PRINTING
501            if (arg[3] == NUL) {
502                if (arg[2] == '1') {            // one-sided printing
503                    rectoverso = FALSE;
504                    break;
505                }
506                if (arg[2] == '2') {            // two-sided printing
507                    rectoverso = TRUE;
508                    break;
509                }
510            }
511#endif
512            usage(EXIT_FAILURE);
513            break;
514        case 't':                               // set tab size
515            if (arg[2] == NUL || (column_width = atoi(arg+2)) <= 0)
516                usage(EXIT_FAILURE);
517            break;
518        case 'v':                               // print control chars
519            if (arg[2] != NUL)
520                usage(EXIT_FAILURE);
521            only_printable = FALSE;
522            break;
523        case '8':                               // print 8-bit chars
524            if (arg[2] != NUL)
525                usage(EXIT_FAILURE);
526            ISOlatin1 = TRUE;
527            break;
528        case '1':
529        case '2':
530        case 'B':
531        case 'd':
532        case 'm':
533        case 'p':
534            if (arg[2] != NUL)
535                usage(EXIT_FAILURE);
536        case '#':
537        case 'F':
538        case 'H':
539        case 'l':
540            return;
541        default:
542            usage(EXIT_FAILURE);
543    }
544    arg[0] = NUL;
545}
546
547/*
548 * Set an option of the command line. This option will be applied
549 * to all files that will be found in the rest of the command line.
550 * The -H option is the only exception: it is applied only to the
551 * file.
552 */
553static void set_positional_option(char *arg) {
554    int copies;
555    int lines;
556    float size;
557
558    switch (arg[1]) {
559        case NUL:                               // global option
560            break;
561        case '#':                               // n copies
562            if (sscanf(&arg[2], "%d", &copies) != 1 || copies <= 0)
563                fprintf(stderr, "Bad number of copies: '%s'. Ignored\n", &arg[2]);
564            else
565                copies_number = copies;
566            printf("/#copies %d def\n", copies_number);
567            break;
568        case '1':                               // 1 logical page per sheet
569            if (arg[2] != NUL)
570                usage(EXIT_FAILURE);
571            new_twinpages = FALSE;
572            break;
573        case '2':                               // twin pages
574            if (arg[2] != NUL)
575                usage(EXIT_FAILURE);
576            new_twinpages = TRUE;
577            break;
578        case 'B':
579            new_fontweight = BOLD;              // use bold font
580            break;
581        case 'd':                               // print current date/time
582            printdate = TRUE;
583            break;
584        case 'F':                               // change font size
585            if (arg[2] == NUL || sscanf(&arg[2], "%f", &size) != 1 || size == 0.0) {
586                fprintf(stderr, "Wrong value for option -F: '%s'. Ignored\n",
587                        &arg[2]);
588                break;
589            }
590            new_fontsize = size;
591            break;
592        case 'H':                               // header text
593            header_text = arg+2;
594            break;
595        case 'l':
596            if (arg[2] == NUL) {                // landscape format
597                new_landscape = TRUE;
598                break;
599            }
600            // set lines per page
601            // Useful with preformatted files. Scaling is automatically
602            // done when necessary.
603            if (sscanf(&arg[2], "%d", &lines) != 1
604                || lines < 0 || lines > MAX_LINES)
605            {
606                fprintf(stderr, "Wrong value for option -l: '%s'. Ignored\n",
607                        &arg[2]);
608                break;
609            }
610            new_linesrequest = lines;
611            break;
612        case 'm':                               // Process file as a man
613            new_linesrequest = MAN_LINES;
614            numbering = FALSE;
615            break;
616        case 'n':                               // number file lines
617            if (arg[2] == NUL) {
618                numbering = TRUE;
619                break;
620            }
621            switch (arg[2]) {
622                case 'B':                       // disable bold text
623                    new_fontweight = NORMAL;
624                    break;
625                case 'd':                       // don't print date/time
626                    printdate = FALSE;
627                    break;
628#if defined(SYSV) || defined(BSD)
629                case 'L':                       // no login name in footer
630                    login_id = FALSE;
631                    break;
632#endif
633                case 'l':                       // portrait format
634                    new_landscape = FALSE;
635                    break;
636                case 'm':                       // stop processing as a man
637                    new_linesrequest = 0;
638                    break;
639                case 'n':                       // don't number lines
640                    numbering = FALSE;
641                    break;
642                case 'p':                       // landscape format
643                    new_landscape = TRUE;
644                    break;
645                case 's':                       // no surrounding border
646                    no_border = TRUE;
647                    break;
648                case 'u':                       // no filename in footer
649                    filename_footer = FALSE;
650                    break;
651                default:
652                    usage(EXIT_FAILURE);
653            }
654            break;
655        case 'p':                               // portrait format
656            if (arg[2] != NUL)
657                usage(EXIT_FAILURE);
658            new_landscape = FALSE;
659            break;
660        case 's':                               // surrounding border
661            if (arg[2] != NUL)
662                usage(EXIT_FAILURE);
663            no_border = FALSE;
664            break;
665        default:
666            usage(EXIT_FAILURE);
667    }
668}
669
670
671//**************************************************************
672//                      Service routines
673//**************************************************************
674
675/*
676 * This routine buffers a line of input, release one character at a time
677 * or a whole sequence of characters with some meaning like bold sequences
678 * produced by nroff (no others sequences are recognized by the moment):
679 *        <c><\b><c><\b><c><\b><c>
680 */
681static int mygetc(int *statusp) {
682#define BUFFER_SIZE     512
683    static int curr = 0;
684    static int size = 0;
685    static unsigned char buffer[BUFFER_SIZE+1];
686    int c;
687
688    *statusp = IS_ROMAN;
689
690    // Read a new line, if necessary
691    if (curr >= size) {
692        if (fgets((char *)buffer, BUFFER_SIZE+1, stdin) == NULL)
693            return  EOF;
694        size = strlen((char *)buffer);
695        if (size < BUFFER_SIZE && buffer[size-1] != '\n') {
696            buffer[size] = '\n';
697            buffer[++size] = '\0';
698        }
699        curr = 0;
700    }
701    if (buffer[curr+1] != '\b')         // this is not a special sequence
702        return  buffer[curr++];
703
704    // Check if it is a bold sequence
705    c = buffer[curr++];
706    if (c               == buffer[curr+1] &&
707        buffer[curr]    == buffer[curr+2] &&
708        c               == buffer[curr+3] &&
709        buffer[curr]    == buffer[curr+4] &&
710        c               == buffer[curr+5])
711    {
712        *statusp = IS_BOLD;
713        curr += 6;
714    }
715
716    // Return the first character of the sequence
717    return  c;
718}
719
720/*
721 * Test if we have a binary file.
722 */
723static int is_binaryfile(char *name) {
724    if (chars > 120 || pages > 1) {
725        first_page = FALSE;
726        if (chars && !print_binaries && (nonprinting_chars*100 / chars) >= 60) {
727            fprintf(stderr, "%s is a binary file: printing aborted\n", name);
728            return TRUE;
729        }
730    }
731    return FALSE;
732}
733
734/*
735 * Cut long filenames.
736 */
737static void cut_filename(char *old_name, char *new_name) {
738    char *p;
739    int   i;
740    char *separator;
741
742    if ((i = strlen(old_name)) <= MAXFILENAME) {
743        strcpy(new_name, old_name);
744        return;
745    }
746    p = old_name + (i-1);
747    separator = NULL;
748    i = 1;
749    while (p >= old_name && i < MAXFILENAME) {
750        if (*p == DIR_SEP)
751            separator = p;
752        p--;
753        i++;
754    }
755    if (separator != NULL)
756        p = separator;
757    else if (p >= old_name)
758        while (p >= old_name && *p != DIR_SEP) p--;
759
760    for (i = 0, p++; *p != NUL; i++)
761        *new_name++ = *p++;
762    *new_name = NUL;
763}
764
765/*
766 * Print a char in a form accepted by postscript printers.
767 */
768static int printchar(unsigned char c) {
769
770    if (c >= ' ' && c < 0177) {
771        if (c == '(' || c == ')' || c == '\\')
772            putchar('\\');
773        putchar(c);
774        return 0;
775    }
776
777    if (ISOlatin1 && (c > 0177)) {
778        printf("\\%o", c);
779        return 0;
780    }
781
782    if (only_printable) {
783        putchar(' ');
784        return 1;
785    }
786
787    if (c > 0177) {
788        printf("M-");
789        c &= 0177;
790    }
791    if (c < ' ') {
792        putchar('^');
793        if ((c = c + '@') == '(' || c == ')' || c == '\\')
794            putchar('\\');
795        putchar(c);
796    }
797    else if (c == 0177)
798        printf("^?");
799    else {
800        if (c == '(' || c == ')' || c == '\\')
801            putchar('\\');
802        putchar(c);
803    }
804
805    return 1;
806}
807
808/*
809 * Begins a new logical page.
810 */
811static void skip_page() {
812    if (twinpages == FALSE || sheetside == 0) {
813        printf("%%%%Page: %d %d\n", sheets+1, sheets+1);
814        printf("/pagesave save def\n");
815        // Reinitialize state variables for each new sheet
816        print_page_prologue(0);
817    }
818    startpage();
819}
820
821/*
822 * Fold a line too long.
823 */
824static int fold_line(char *name) {
825    column = 0;
826    printf(") s\n");
827    if (++line >= linesperpage) {
828        endpage();
829        skip_page();
830        if (first_page && is_binaryfile(name))
831            return FALSE;
832        line = 0;
833    }
834    if (numbering)
835        printf("(    +");
836    else
837        printf("( ");
838
839    return TRUE;
840}
841
842/*
843 * Cut a textline too long to the size of a page line.
844 */
845static int cut_line() {
846    int c;
847    int status;
848
849    while ((c = mygetc(&status)) != EOF && c != '\n' && c != '\f') ;
850    return c;
851}
852
853
854//**************************************************************
855//                      "Postscript" routines.
856//**************************************************************
857
858/*
859 * Print a physical page.
860 */
861static void printpage() {
862    sheetside = 0;
863    sheets++;
864    printf("/sd 0 def\n");
865    if (no_border == FALSE)
866        printf("%d sn\n", sheets - (restart ? old_sheets : 0));
867    if (printdate)
868        printf("cd\n");
869    if (filename_footer && landscape)
870        printf("fnf\n");
871#if defined(SYSV) || defined(BSD)
872    if (login_id)
873        printf("lg lgp\n");
874#endif
875    printf("pagesave restore\n");
876    printf("showpage\n");
877}
878
879/*
880 * Prints page header and page border and
881 * initializes printing of the file lines.
882 */
883void startpage() {
884    if (sheetside == 0) {
885#ifdef RECTO_VERSO_PRINTING
886        if (rectoverso && (sheets & 0x1)) {
887            // Shift to left backside pages.
888            printf("rm neg 0 translate\n");
889        }
890#endif
891        if (landscape) {
892            printf("sw 0 translate\n");
893            printf("90 rotate\n");
894        }
895    }
896    pages++;
897    if (no_header == FALSE)
898        printf("%d hp\n", pages - old_pages);
899    if (no_border == FALSE) {
900        printf("border\n");
901        if (no_header == FALSE)
902            printf("hborder\n");
903    }
904    printf("/x0 x %d get bm add def\n", sheetside);
905    printf("/y0 y %d get bm bfs add %s add sub def\n",
906           sheetside, no_header ? "0" : "hs");
907    printf("x0 y0 moveto\n");
908    printf("bf setfont\n");
909}
910
911/*
912 * Terminates printing, flushing last page.
913 */
914static void cleanup() {
915    if (twinpages && sheetside == 1)
916        printpage();
917#ifdef RECTO_VERSO_PRINTING
918    if (!twinfiles && rectoverso && (sheets & 0x1) != 0) {
919        sheetside = 0;
920        sheets++;
921        printf("%%%%Page: %d %d\n", sheets, sheets);
922        printf("showpage\n");
923    }
924#endif
925}
926
927/*
928 * Adds a sheet number to the page (footnote) and prints the formatted
929 * page (physical impression). Activated at the end of each source page.
930 */
931void endpage() {
932    if (twinpages && sheetside == 0) {
933        sheetside = 1;
934        printf("/sd 1 def\n");
935    }
936    else
937        printpage();
938}
939
940
941//**************************************************************
942//              Printing a file
943//**************************************************************
944
945/*
946 * Print the file prologue.
947 */
948static void init_file_printing(char *name, char *title) {
949    int new_format, new_font;
950    char *string;
951    int lines;
952    float char_width;
953    struct stat statbuf;
954
955    // Print last page of previous file, if necessary
956    if (pages > 0 && !twinfiles)
957        cleanup();
958
959    // Initialize variables related to the format
960    new_format = FALSE;
961    if (new_landscape != landscape || new_twinpages != twinpages) {
962        landscape = new_landscape;
963        twinpages = new_twinpages;
964        new_format = TRUE;
965    }
966
967    // Initialize variables related to the header
968    if (no_header && name == title)
969        header_size = 0.0;
970    else {
971        if (landscape || twinpages)
972            header_size = LANDSCAPE_HEADER * PIXELS_INCH;
973        else
974            header_size = PORTRAIT_HEADER * PIXELS_INCH;
975        cut_filename(title, current_filename);
976    }
977
978    // Initialize variables related to the font size
979    new_font = FALSE;
980    if (fontsize != new_fontsize || new_format ||
981        lines_requested != new_linesrequest || fontweight != new_fontweight)
982    {
983        if (new_fontsize == 0.0 || (fontsize == new_fontsize && new_format))
984            new_fontsize = landscape ? 6.8 : twinpages ? 6.4 : 9.0;
985        if (lines_requested != new_linesrequest) {
986            if ((lines_requested = new_linesrequest) != 0) {
987                // Scale fontsize
988                if (landscape)
989                    lines = (int)((page_width-header_size) / new_fontsize) - 1;
990                else if (twinpages)
991                    lines = (int)(((page_height - 2*header_size) / 2) / new_fontsize) - 2;
992                else
993                    lines = (int)((page_height-header_size) / new_fontsize) - 1;
994                new_fontsize *= (float)lines / (float)lines_requested;
995            }
996        }
997        fontsize = new_fontsize;
998        fontweight = new_fontweight;
999        new_font = TRUE;
1000    }
1001
1002    // Initialize file printing, if there is any change
1003    if (new_format || new_font) {
1004        char_width = 0.6 * fontsize;
1005        if (landscape) {
1006            linesperpage = (int)((page_width - header_size) / fontsize) - 1;
1007            if (! twinpages)
1008                columnsperline = (int)(page_height / char_width) - 1;
1009            else
1010                columnsperline = (int)((page_height / 2) / char_width) - 1;
1011        }
1012        else {
1013            if (!twinpages)
1014                linesperpage = (int)((page_height - header_size) / fontsize) - 1;
1015            else
1016                linesperpage = (int)(((page_height - 2*header_size) / 2) / fontsize)
1017                    - 2;
1018            columnsperline = (int)(page_width / char_width) - 1;
1019        }
1020        if (lines_requested > 0)
1021            linesperpage = lines_requested;
1022        if (linesperpage <= 0 || columnsperline <= 0) {
1023            fprintf(stderr, "Font %g too big !!\n", fontsize);
1024            exit(EXIT_FAILURE);
1025        }
1026    }
1027
1028    // Retrieve file modification date and hour
1029    if (fstat(fileno(stdin), &statbuf) == -1) {
1030        fprintf(stderr, "Error getting file modification time\n");
1031        exit(EXIT_FAILURE);
1032    }
1033    // Do we have a pipe?
1034    if (S_ISFIFO(statbuf.st_mode))
1035        strcpy(filedate, currentdate);
1036    else {
1037        string = ctime(&statbuf.st_mtime);
1038        sprintf(filedate, "%.6s %.4s %.5s", string+4, string+20, string+11);
1039    }
1040}
1041
1042/*
1043 * Print the prologue necessary for printing each physical page.
1044 * Adobe convention for page independence is enforced through this routine.
1045 */
1046void print_page_prologue(int side) {
1047    // side: Logical page to print (left/right)
1048
1049    // General format
1050    printf("/twp %s def\n", twinpages ? "true" : "false");
1051    printf("/fnfs %d def\n", landscape ? 11 : twinpages ? 10 : 15);
1052    printf("/dfs fnfs 0.8 mul def\n");
1053    printf("/df /Helvetica dfs getfont def\n");
1054    printf("/dw df setfont td stringwidth pop def\n");
1055    printf("/sfnf filenmfontname fnfs getfont def\n");
1056    printf("/hm fnfs 0.25 mul def\n");
1057    // Header size
1058    if (header_size == 0.0)
1059        printf("/hs 0.0 def\n");
1060    else
1061        printf("/hs %g inch def\n",
1062               landscape || twinpages ? LANDSCAPE_HEADER : PORTRAIT_HEADER);
1063    // Font sizes
1064    printf("/bfs %g def\n", fontsize);
1065    printf("/bdf /Courier-Bold bfs getfont def\n");
1066    printf("/bm bfs 0.7 mul def\n");
1067    printf("/bf %s bfs getfont def\n",
1068           fontweight == NORMAL ? "/CourierBack" : "/Courier-Bold");
1069    // Page attributes
1070    printf("/l %d def\n", linesperpage);
1071    printf("/c %d def\n", columnsperline);
1072    printf("/pw\n");
1073    printf("   bf setfont (0) stringwidth pop c mul bm dup add add\n");
1074    printf("   def\n");
1075    printf("/ph\n");
1076    printf("   bfs l mul bm dup add add hs add\n");
1077    printf("   def\n");
1078    printf("/fns\n");
1079    printf("      pw\n");
1080    printf("      fnfs 4 mul dw add (Page 999) stringwidth pop add\n");
1081    printf("    sub\n");
1082    printf("  def\n");
1083    printf("/tm margin twp {3} {2} ifelse div def\n");
1084    printf("/sd %d def\n", side);
1085    if (landscape) {
1086        printf("/y [ rm ph add bm add\n");
1087        printf("          dup ] def\n");
1088        printf("/sny dfs dfs add def\n");
1089        printf("/snx sh tm dfs add sub def\n");
1090        printf("/dy sny def\n");
1091        printf("/dx tm dfs add def\n");
1092        if (twinpages) {
1093            printf("/x [ tm                     %% left page\n");
1094            printf("          dup 2 mul pw add  %% right page\n");
1095            printf("        ] def\n");
1096        }
1097        else {
1098            printf("/x [ tm dup ] def\n");
1099        }
1100        printf("/scx sh 2 div def\n");
1101    }
1102    else {
1103        printf("/x [ lm dup ] def\n");
1104        printf("/sny tm dfs 2 mul sub def\n");
1105        printf("/snx sw rm sub dfs sub def\n");
1106        printf("/dy sny def\n");
1107        printf("/dx lm def\n");
1108        if (twinpages) {
1109            printf("/y [ tm ph add 2 mul %% up\n");
1110            printf("          tm ph add  %% down\n");
1111            printf("        ] def\n");
1112        }
1113        else {
1114            printf("\n%% Only one logical page\n");
1115            printf("/y [ sh tm sub dup ] def\n");
1116        }
1117        printf("/scx sw 2 div def\n");
1118    }
1119    printf("/fny dy def\n");
1120    printf("/fnx scx def\n");
1121    printf("/ly fnfs 2 div y sd get add def\n");
1122    printf("/lx snx def\n");
1123    printf("/d (%s) def\n", filedate);
1124    printf("( %s ) fn\n", current_filename);
1125}
1126
1127/*
1128 * Print one file.
1129 */
1130static void print_file(char *name, char *header) {
1131    int c;
1132    int nchars;
1133    int start_line, start_page;
1134    int continue_exit;
1135    int status, new_status;
1136
1137    // Reinitialize postscript variables depending on positional options
1138    init_file_printing(name, header == NULL ? name : header);
1139
1140    // If we are in compact mode and the file beginning is to be printed
1141    // in the middle of a twinpage, we have to print a new page prologue
1142    if (twinfiles && sheetside == 1)
1143        print_page_prologue(1);
1144
1145    /*
1146     * Boolean to indicates that previous char is \n (or interpreted \f)
1147     * and a new page would be started, if more text follows
1148     */
1149    start_page = FALSE;
1150
1151    /*
1152     * Printing binary files is not very useful. We stop printing
1153     * if we detect one of these files. Our heuristic to detect them:
1154     * if 75% characters of first page are non-printing characters,
1155     * the file is a binary file.
1156     * Option -b force binary files impression.
1157     */
1158    nonprinting_chars = chars = 0;
1159
1160    // Initialize printing variables
1161    column = 0;
1162    line = line_number = 0;
1163    first_page = TRUE;
1164    start_line = TRUE;
1165    prefix_width = numbering ? 6 : 1;
1166
1167    // Start printing
1168    skip_page();
1169
1170    // Process each character of the file
1171    status = IS_ROMAN;
1172    c = mygetc(&new_status);
1173    while (c != EOF) {
1174        /*
1175         * Preprocessing (before printing):
1176         * - TABs expansion (see interpret option)
1177         * - FF and BS interpretation
1178         * - replace non printable characters by a space or a char sequence
1179         *   like:
1180         *     ^X for ascii codes < 0x20 (X = [@, A, B, ...])
1181         *     ^? for del char
1182         *     M-c for ascii codes > 0x3f
1183         * - prefix parents and backslash ['(', ')', '\'] by backslash
1184         *   (escape character in postscript)
1185         */
1186        // Form feed
1187        if (c == '\f' && interpret) {
1188            // Close current line
1189            if (!start_line) {
1190                printf(") s\n");
1191                start_line = TRUE;
1192            }
1193            // start a new page ?
1194            if (start_page)
1195                skip_page();
1196            // Close current page and begin another
1197            endpage();
1198            start_page = TRUE;
1199            // Verification for binary files
1200            if (first_page && is_binaryfile(name))
1201                return;
1202            line = 0;
1203            column = 0;
1204            if ((c = mygetc(&new_status)) == EOF)
1205                break;
1206        }
1207
1208        // Start a new line ?
1209        if (start_line) {
1210            if (start_page) {
1211                // only if there is something to print!
1212                skip_page();
1213                start_page = FALSE;
1214            }
1215            if (numbering)
1216                printf("(%4d|", ++line_number);
1217            else
1218                printf("( ");
1219            start_line = FALSE;
1220        }
1221
1222        // Is a new font ? This feature is used only to detect bold
1223        // sequences produced by nroff (man pages), in connexion with
1224        // mygetc.
1225        if (status != new_status) {
1226            printf(")\n");
1227            printf("%s", status == IS_ROMAN ? "b" : "st");
1228            printf(" (");
1229            status = new_status;
1230        }
1231
1232        // Interpret each character
1233        switch (c) {
1234            case '\b':
1235                if (!interpret)
1236                    goto print;
1237                // A backspace is converted to 2 chars ('\b'). These chars
1238                // with the Courier backspace font produce correct under-
1239                // lined strings.
1240                if (column)
1241                    column--;
1242                putchar('\\');
1243                putchar('b');
1244                break;
1245            case '\n':
1246                column = 0;
1247                start_line = TRUE;
1248                printf(") s\n");
1249                if (++line >= linesperpage) {
1250                    endpage();
1251                    start_page = TRUE;
1252                    if (first_page && is_binaryfile(name))
1253                        return;
1254                    line = 0;
1255                }
1256                break;
1257            case '\t':
1258                if (interpret) {
1259                    continue_exit = FALSE;
1260                    do {
1261                        if (++column + prefix_width > columnsperline) {
1262                            if (folding) {
1263                                if (fold_line(name) == FALSE)
1264                                    return;
1265                            }
1266                            else {
1267                                c = cut_line();
1268                                continue_exit = TRUE;
1269                                break;
1270                            }
1271                        }
1272                        putchar(' ');
1273                    } while (column % column_width);
1274                    if (continue_exit)
1275                        continue;
1276                    break;
1277                }
1278            default:
1279            print :
1280                if (only_printable) {
1281                    nchars = 1;
1282                }
1283                else if (! ISOlatin1) {
1284                    nchars = c > 0177 ? 2 : 0;
1285                    nchars += (c&0177) < ' ' || (c&0177) == 0177 ? 2 : 1;
1286                }
1287                else {
1288                    nchars = c < ' ' || (c >= 0177 && c < 144) ? 2 : 1;
1289                }
1290
1291                if (prefix_width + (column += nchars) > columnsperline) {
1292                    if (folding) {
1293                        if (fold_line(name) == FALSE) {
1294                            return;
1295                        }
1296                    }
1297                    else {
1298                        c = cut_line();
1299                        new_status = IS_ROMAN;
1300                        continue;
1301                    }
1302                }
1303                nonprinting_chars += printchar(c);
1304                chars++;
1305                break;
1306        }
1307        c = mygetc(&new_status);
1308    }
1309
1310    if (!start_line)
1311        printf(") s\n");
1312    if (!start_page)
1313        endpage();
1314}
1315
1316
1317//**************************************************************
1318//              Print a postscript prologue for a2ps.
1319//**************************************************************
1320
1321/*
1322 * Print the a2ps prologue.
1323 */
1324static void print_prologue() {
1325    int             c;
1326    FILE           *f;
1327    char           *datestring;
1328#if defined(SYSV) || defined(BSD)
1329    char           *logname, *host;
1330    int             rt;
1331#endif
1332#if defined(SYSV)
1333    struct utsname  snames;
1334#endif
1335
1336    // Retrieve date and hour
1337#if defined(__STDC__)
1338    time_t date;
1339
1340    if (time(&date) == -1) {
1341        fprintf(stderr, "Error calculating time\n");
1342        exit(EXIT_FAILURE);
1343    }
1344    datestring = ctime(&date);
1345#else
1346#ifdef BSD
1347    struct timeval date;
1348    struct tm *p;
1349
1350    (void) gettimeofday(&date, (struct timezone *)0);
1351    p = localtime(&date.tv_sec);
1352    datestring = asctime(p);
1353#else
1354#ifdef SYSV
1355    struct timeb date;
1356
1357    (void)ftime(&date);
1358    datestring = ctime(&date.time);
1359#else
1360
1361    datestring = "--- --- -- --:--:-- ----";
1362#endif
1363#endif
1364#endif
1365
1366#if defined(SYSV) || defined(BSD)
1367    // Retrieve user's login name and hostname
1368    logname = getlogin();
1369    host = (char *)malloc(MAX_HOSTNAME);
1370    if (host != NULL) {
1371#if defined(SYSV)
1372        if ((rt = uname(&snames)) == -1 || snames.nodename[0] == NULL) {
1373            free(host);
1374            host = NULL;
1375        }
1376        else
1377            strcpy(host, snames.nodename);
1378#else
1379        if ((rt = gethostname(host, MAX_HOSTNAME)) == -1 || host[0] == NULL) {
1380            free(host);
1381            host = NULL;
1382        }
1383#endif
1384    }
1385#endif
1386
1387    // Print a general prologue
1388    if (prologue == NULL)
1389        print_standard_prologue(datestring);
1390    else if ((f = fopen(prologue, "r")) != NULL) {
1391        // Header file printing
1392        while ((c = getc(f)) != EOF)
1393            putchar(c);
1394    }
1395    else {
1396        fprintf(stderr, "Postscript header missing: %s\n", prologue);
1397        exit(EXIT_FAILURE);
1398    }
1399
1400    // Completes the prologue with a2ps static variables
1401    printf("\n%% Initialize page description variables.\n");
1402    printf("/x0 0 def\n");
1403    printf("/y0 0 def\n");
1404    printf("/sh %g inch def\n", (double)HEIGHT);
1405    printf("/sw %g inch def\n", (double)WIDTH);
1406    printf("/margin %g inch def\n", (double)MARGIN);
1407    printf("/rm margin 3 div def\n");
1408    printf("/lm margin 2 mul 3 div def\n");
1409    printf("/d () def\n");
1410
1411    // And print them
1412    sprintf(currentdate, "%.6s %.4s %.5s",
1413            datestring+4, datestring+20, datestring+11);
1414    printf("/td (%s) def\n", currentdate);
1415
1416#if defined(SYSV) || defined(BSD)
1417    // Add the user's login name string to the Postscript output
1418    if (logname != NULL || host != NULL) {
1419        if (logname != NULL && host != NULL)
1420            printf("/lg (Printed by %s from %s) def\n", logname, host);
1421        else if (logname != NULL)
1422            printf("/lg (Printed by %s) def\n", logname);
1423        else
1424            printf("/lg (Printed from %s) def\n", host);
1425    }
1426
1427    // If the host string was allocated via malloc, release the memory
1428    if (host != NULL)
1429        free(host);
1430#endif
1431
1432    // Close prolog
1433    printf("%%%%EndProlog\n\n");
1434
1435    // Go on
1436    printf("/docsave save def\n");
1437}
1438
1439/*
1440 * Print the standard prologue.
1441 */
1442void print_standard_prologue(char *datestring) {
1443    printf("%%!PS-Adobe-3.0\n");
1444    printf("%%%%Creator: A2ps version %s\n", VERSION);
1445    printf("%%%%CreationDate: %.24s\n", datestring);
1446    printf("%%%%Pages: (atend)\n");
1447    printf("%%%%DocumentFonts: Courier Courier-Bold Helvetica Helvetica-Bold\n");
1448    printf("%%%%EndComments\n");
1449    printf("%% Copyright (c) 1993, 1994, Miguel Santana, M.Santana@frgu.bull.fr\n");
1450    printf("\n/$a2psdict 100 dict def\n");
1451    printf("$a2psdict begin\n");
1452    printf("\n%% General macros.\n");
1453    printf("/xdef {exch def} bind def\n");
1454    printf("/getfont {exch findfont exch scalefont} bind def\n");
1455
1456    if (ISOlatin1) {
1457        printf("\n%% Set up ISO Latin 1 character encoding\n");
1458        printf("/reencodeISO {\n");
1459        printf("        dup dup findfont dup length dict begin\n");
1460        printf("        { 1 index /FID ne { def }{ pop pop } ifelse\n");
1461        printf("        } forall\n");
1462        printf("        /Encoding ISOLatin1Encoding def\n");
1463        printf("        currentdict end definefont\n");
1464        printf("} def\n");
1465        printf("/Helvetica-Bold reencodeISO def\n");
1466        printf("/Helvetica reencodeISO def\n");
1467        printf("/Courier reencodeISO def\n");
1468        printf("/Courier-Bold reencodeISO def\n");
1469    }
1470
1471    printf("\n%% Create Courier backspace font\n");
1472    printf("/backspacefont {\n");
1473    printf("    /Courier findfont dup length dict begin\n");
1474    printf("    { %% forall\n");
1475    printf("        1 index /FID eq { pop pop } { def } ifelse\n");
1476    printf("    } forall\n");
1477    printf("    currentdict /UniqueID known { %% if\n");
1478    printf("        /UniqueID UniqueID 16#800000 xor def\n");
1479    printf("    } if\n");
1480    printf("    CharStrings length 1 add dict begin\n");
1481    printf("        CharStrings { def } forall\n");
1482    printf("        /backspace { -600 0 0 0 0 0 setcachedevice } bind def\n");
1483    printf("        currentdict\n");
1484    printf("    end\n");
1485    printf("    /CharStrings exch def\n");
1486    printf("    /Encoding Encoding 256 array copy def\n");
1487    printf("    Encoding 8 /backspace put\n");
1488    printf("    currentdict\n");
1489    printf("    end\n");
1490    printf("    definefont pop\n");
1491    printf("} bind def\n");
1492
1493    printf("\n%% FUNCTIONS\n");
1494    printf("\n%% Function filename: Initialize file printing.\n");
1495    printf("/fn\n");
1496    printf("{ /filenm xdef\n");
1497    printf("  /filenmwidth filenm stringwidth pop def\n");
1498    printf("  /filenmfont\n");
1499    printf("       filenmwidth fns gt\n");
1500    printf("       {\n");
1501    printf("           filenmfontname\n");
1502    printf("           fnfs fns mul filenmwidth div\n");
1503    printf("         getfont\n");
1504    printf("       }\n");
1505    printf("       { sfnf }\n");
1506    printf("     ifelse\n");
1507    printf("  def\n");
1508    printf("} bind def\n");
1509    printf("\n%% Function header: prints page header. no page\n");
1510    printf("%% is passed as argument.\n");
1511    printf("/hp\n");
1512    printf("  { x sd get  y sd get hs sub 1 add  moveto\n");
1513    printf("    df setfont\n");
1514    printf("    gsave\n");
1515    printf("      x sd get y sd get moveto\n");
1516    printf("      0 hs 2 div neg rmoveto \n");
1517    printf("      hs setlinewidth\n");
1518    printf("      0.95 setgray\n");
1519    printf("      pw 0 rlineto stroke\n");
1520    printf("    grestore\n");
1521    printf("    gsave\n");
1522    printf("      dfs hm rmoveto\n");
1523    printf("      d show                                %% date/hour\n");
1524    printf("    grestore\n");
1525    printf("    gsave\n");
1526    printf("      pnum cvs pop                          %% page pop up\n");
1527    printf("        pw (Page 999) stringwidth pop sub\n");
1528    printf("        hm\n");
1529    printf("      rmoveto\n");
1530    printf("      (Page ) show pnum show                %% page number\n");
1531    printf("    grestore\n");
1532    printf("    empty pnum copy pop\n");
1533    printf("    gsave\n");
1534    printf("      filenmfont setfont\n");
1535    printf("         fns filenm stringwidth pop sub 2 div dw add\n");
1536    printf("          bm 2 mul \n");
1537    printf("        add \n");
1538    printf("        hm\n");
1539    printf("      rmoveto\n");
1540    printf("        filenm show                 %% file name\n");
1541    printf("      grestore\n");
1542    printf("    } bind def\n");
1543    printf("\n%% Function border: prints border page\n");
1544    printf("/border \n");
1545    printf("{ x sd get y sd get moveto\n");
1546    printf("  gsave                             %% print four sides\n");
1547    printf("    0.7 setlinewidth                %% of the square\n");
1548    printf("    pw 0 rlineto\n");
1549    printf("    0 ph neg rlineto\n");
1550    printf("    pw neg 0 rlineto\n");
1551    printf("    closepath stroke\n");
1552    printf("  grestore\n");
1553    printf("} bind def\n");
1554    printf("\n%% Function hborder: completes border of the header.\n");
1555    printf("/hborder \n");
1556    printf("{ gsave\n");
1557    printf("    0.7 setlinewidth\n");
1558    printf("    0 hs neg rmoveto\n");
1559    printf("    pw 0 rlineto\n");
1560    printf("    stroke\n");
1561    printf("  grestore\n");
1562    printf("} bind def\n");
1563    printf("\n%% Function sheetnumber: prints the sheet number.\n");
1564    printf("/sn\n");
1565    printf("    { snx sny moveto\n");
1566    printf("      df setfont\n");
1567    printf("      pnum cvs\n");
1568    printf("      dup stringwidth pop (0) stringwidth pop sub neg 0 rmoveto show\n");
1569    printf("      empty pnum copy pop\n");
1570    printf("    } bind def\n");
1571    printf("\n%% Function loginprint: prints the login id of the requestor.\n");
1572    printf("/lgp\n");
1573    printf("    { lx ly moveto\n");
1574    printf("      df setfont\n");
1575    printf("      dup stringwidth pop neg 0 rmoveto show\n");
1576    printf("    } bind def\n");
1577    printf("\n%% Function currentdate: prints the current date.\n");
1578    printf("/cd\n");
1579    printf("    { dx dy moveto\n");
1580    printf("      df setfont\n");
1581    printf("      (Printed: ) show\n");
1582    printf("      td show\n");
1583    printf("    } bind def\n");
1584    printf("\n%% Function filename_footer: prints the file name at bottom of page.\n");
1585    printf("/fnf\n");
1586    printf("    { fnx fny moveto\n");
1587    printf("      df setfont\n");
1588    printf("      filenm center show\n");
1589    printf("    } bind def\n");
1590    printf("\n%% Function center: centers text.\n");
1591    printf("/center\n");
1592    printf("    { dup stringwidth pop\n");
1593    printf("      2 div neg 0 rmoveto\n");
1594    printf("    } bind def\n");
1595    printf("\n%% Function s: print a source line\n");
1596    printf("/s  { show\n");
1597    printf("      /y0 y0 bfs sub def\n");
1598    printf("      x0 y0 moveto\n");
1599    printf("    } bind def\n");
1600    printf("\n%% Functions b and st: change to bold or standard font\n");
1601    printf("/b  { show\n");
1602    printf("      bdf setfont\n");
1603    printf("    } bind def\n");
1604    printf("/st { show\n");
1605    printf("      bf setfont\n");
1606    printf("    } bind def\n");
1607    printf("\n%% Strings used to make easy printing numbers\n");
1608    printf("/pnum 12 string def\n");
1609    printf("/empty 12 string def\n");
1610    printf("\n%% Global initializations\n");
1611    printf("\n/CourierBack backspacefont\n");
1612    printf("/filenmfontname /Helvetica-Bold def\n");
1613    printf("/inch {72 mul} bind def\n");
1614
1615    printf("\n%%\n");
1616    printf("%% Meaning of some variables and functions (coded names)\n");
1617    printf("%%\n");
1618    printf("%%  twp:            twinpages?\n");
1619    printf("%%  sd:             sheet side\n");
1620    printf("%%  l:              line counter\n");
1621    printf("%%  c:              column counter\n");
1622    printf("%%  d:              date\n");
1623    printf("%%  td:             current date (for today)\n");
1624    printf("%%  lg:             login name\n");
1625    printf("%%  fn:             filename printing function\n");
1626    printf("%%  sn:             sheetnumber printing function\n");
1627    printf("%%  cd:             current date printing function\n");
1628    printf("%%  fnf:            filename footer printing function\n");
1629    printf("%%  lgp:            login printing function\n");
1630    printf("%%  hp:             header printing function\n");
1631    printf("%%  y:              y coordinate for the logical page\n");
1632    printf("%%  x:              x coordinate for the logical page\n");
1633    printf("%%  sny:            y coordinate for the sheet number\n");
1634    printf("%%  snx:            x coordinate for the sheet number\n");
1635    printf("%%  dy:             y coordinate for the date\n");
1636    printf("%%  dx:             x coordinate for the date\n");
1637    printf("%%  ly:             y coordinate for the login\n");
1638    printf("%%  lx:             x coordinate for the login\n");
1639    printf("%%  scx:            x coordinate for the sheet center\n");
1640    printf("%%  fny:            y coordinate for the filename (footer)\n");
1641    printf("%%  fnx:            x coordinate for the filename (footer)\n");
1642    printf("%%  fnfs:           filename font size\n");
1643    printf("%%  bfs:            body font size\n");
1644    printf("%%  dfs:            date font size\n");
1645    printf("%%  bfs:            body font size\n");
1646    printf("%%  df:             date font\n");
1647    printf("%%  bf:             body font\n");
1648    printf("%%  bdf:            bold font\n");
1649    printf("%%  sfnf:           standard filename font\n");
1650    printf("%%  dw:             date width\n");
1651    printf("%%  pw:             page width\n");
1652    printf("%%  sw:             sheet width\n");
1653    printf("%%  ph:             page height\n");
1654    printf("%%  sh:             sheet height\n");
1655    printf("%%  hm:             header margin\n");
1656    printf("%%  tm:             top margin\n");
1657    printf("%%  bm:             body margin\n");
1658    printf("%%  rm:             right margin\n");
1659    printf("%%  lm:             left margin\n");
1660    printf("%%  hs:             header size\n");
1661    printf("%%  fns:            filename size\n");
1662}
1663
1664
1665/*
1666 * Main routine for a2ps.
1667 */
1668int ARB_main(int argc, const char *cargv[]) {
1669    char       **argv = (char**)cargv;
1670    int          narg;
1671    char        *arg;
1672    int          total;
1673#if LPR_PRINT
1674    int          fd[2];
1675    const char  *lpr_args[10];
1676#endif
1677
1678    // Process global options
1679    command = argv[0];
1680    arg = argv[narg = 1];
1681    while (narg < argc) {
1682        if (arg[0] == '-')
1683            set_global_option(arg);
1684        arg = argv[++narg];
1685    }
1686
1687#if LPR_PRINT
1688    // Start lpr process
1689    if (lpr_print) {
1690        pipe(fd);
1691        if (fork() == 0) {
1692            dup2(fd[0], 0);
1693            close(fd[0]); close(fd[1]);
1694            narg = 0;
1695            lpr_args[narg++] = LPR_COMMAND;
1696#ifdef LPR_OPT
1697            lpr_args[narg++] = LPR_OPT;
1698#endif
1699            if (lpr_opt)
1700                lpr_args[narg++] = lpr_opt;
1701#ifdef RECTO_VERSO_PRINTING
1702            if (rectoverso)
1703                lpr_args[narg++] = TWOSIDED;
1704            else
1705                lpr_args[narg++] = ONESIDED;
1706#endif
1707            lpr_args[narg] = (char *)0;
1708            execvp(LPR_COMMAND, (char**)lpr_args);
1709            fprintf(stderr, "Error starting lpr process \n");
1710            exit(EXIT_FAILURE);
1711        }
1712        dup2(fd[1], 1);
1713        close(fd[0]);
1714        close(fd[1]);
1715    }
1716#endif
1717
1718    // Initialize variables not depending of positional options
1719    landscape = twinpages = -1; // To force format switching
1720    fontsize = -1.0;                    // To force fontsize switching
1721    page_height = (double)(HEIGHT - MARGIN) * PIXELS_INCH;
1722    page_width = (double)(WIDTH - MARGIN) * PIXELS_INCH;
1723
1724    // Postscript prologue printing
1725    print_prologue();
1726
1727    // Print files designated or standard input
1728    arg = argv[narg = 1];
1729    while (narg < argc) {
1730        if (arg[0] != NUL) {
1731            if (arg[0] == '-')
1732                set_positional_option(arg);
1733            else {
1734                if (freopen(arg, "r", stdin) == NULL) {
1735                    fprintf(stderr, "Error opening %s\n", arg);
1736                    cleanup();
1737                    printf("\n%%%%Trailer\ndocsave restore end\n\4");
1738                    exit(EXIT_FAILURE);
1739                }
1740                no_files = FALSE;
1741
1742                // Save counters values
1743                old_pages = pages;
1744                if (twinfiles && twinpages)
1745                    old_sheets = sheets;
1746                else
1747                    old_sheets = sheets + sheetside;
1748
1749                // Print the file
1750                print_file(arg, header_text);
1751
1752                // Print the number of pages and sheets printed
1753                if (no_summary == FALSE) {
1754                    total = pages - old_pages;
1755                    fprintf(stderr, "[%s: %d page%s on ", arg,
1756                            total, total == 1 ? "" : "s");
1757                    total = sheets - old_sheets + sheetside;
1758#ifdef RECTO_VERSO_PRINTING
1759                    if (rectoverso)
1760                        total = (total+1) / 2;
1761#endif
1762                    fprintf(stderr, "%d sheet%s]\n", total, total == 1 ? "" : "s");
1763                }
1764
1765                // Reinitialize header title
1766                header_text = NULL;
1767            }
1768        }
1769        arg = argv[++narg];
1770    }
1771    if (no_files)
1772        print_file((char*)"stdin", header_text);
1773
1774    // Print the total number of pages printed
1775    if (no_summary == FALSE && pages != old_pages) {
1776        fprintf(stderr, "[Total: %d page%s on ", pages, pages == 1 ? "" : "s");
1777        total = sheets + sheetside;
1778#ifdef RECTO_VERSO_PRINTING
1779        if (rectoverso)
1780            total = (total+1) / 2;
1781#endif
1782        fprintf(stderr, "%d sheet%s]\n", total, total == 1 ? "" : "s");
1783    }
1784
1785    // And stop
1786    cleanup();
1787    printf("\n%%%%Trailer\n");
1788    printf("%%%%Pages: %d\n", sheets + sheetside);
1789    printf("docsave restore end\n");
1790
1791    exit(EXIT_SUCCESS);
1792}
Note: See TracBrowser for help on using the repository browser.