source: branches/tree/TOOLS/arb_a2ps.c

Last change on this file was 16766, checked in by westram, 7 years ago
  • 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#include <errno.h>
116
117#ifdef __STDC__
118#include <stdlib.h>
119#include <time.h>
120#include <string.h>
121#else
122#include <strings.h>
123#ifdef SYSV
124#include <sys/timeb.h>
125#include <time.h>
126#include <sys/utsname.h>
127#else
128#ifndef BSD
129#define BSD     1
130#endif
131#include <sys/time.h>
132#endif
133#endif
134
135
136//**********************************************************************
137/*                                                                      */
138//           P r e p r o c e s s i n g   d e f i n i t i o n s
139/*                                                                      */
140//**********************************************************************
141
142/*
143 * Common definitions
144 */
145#define FALSE           0
146#define TRUE            1
147#ifndef NULp
148#define NULp            0
149#endif
150#ifndef NUL
151#define NUL             '\0'
152#endif
153#ifndef EXIT_SUCCESS
154#define EXIT_SUCCESS    0
155#endif
156#ifndef EXIT_FAILURE
157#define EXIT_FAILURE    1
158#endif
159
160
161/*
162 * Version
163 */
164#define VERSION "4.3"
165#define LPR_PRINT 1
166
167/*
168 * Default page dimensions
169 */
170#ifndef WIDTH
171#define WIDTH   8.27
172#endif
173
174#ifndef HEIGHT
175#define HEIGHT  11.0
176#endif
177
178#ifndef MARGIN
179#define MARGIN  .5
180#endif
181
182
183/*
184 * Pathname separator for file system
185 */
186#ifndef DIR_SEP
187#define DIR_SEP '/'
188#endif
189
190
191/*
192 * Printing parameters
193 */
194#if LPR_PRINT
195
196#ifndef LPR_COMMAND
197#define LPR_COMMAND     "lpr"
198#endif
199
200#ifndef LPR_OPT
201#define LPR_OPT "-l"
202#endif
203
204#if defined(ONESIDED) && defined(TWOSIDED)
205#define RECTO_VERSO_PRINTING
206#ifndef TWOSIDED_DFLT
207#define TWOSIDED_DFLT   TRUE
208#endif
209#endif
210
211#endif
212
213
214/*
215 * Configuration values
216 */
217#define PORTRAIT_HEADER         0.29
218#define LANDSCAPE_HEADER        0.22
219#define PIXELS_INCH             72
220#define MAXFILENAME             32
221#define MAX_LINES               320             // max. lines per page
222#define MAN_LINES               66              // no lines for a man
223#define IS_ROMAN                0               // normal font
224#define IS_BOLD                 1               // bold sequence flag
225#if defined(SYSV) || defined(BSD)
226#define MAX_HOSTNAME            40
227#endif
228
229
230//**********************************************************************
231/*                                                                      */
232//                 G l o b a l   d e f i n i t i o n s
233/*                                                                      */
234//**********************************************************************
235
236
237/*
238 * Global types
239 */
240typedef enum { BOLD, NORMAL } WEIGHT;           // font weights
241
242
243/*
244 * Function declarations.
245 */
246
247static void print_page_prologue(int side);
248static void print_standard_prologue(char *datestring);
249static void startpage();
250static void endpage();
251
252#if defined(SYSV) || defined(BSD)
253char *getlogin();
254#endif
255#if defined(BSD)
256int   gethostname(char *name, int namelen);
257#endif
258
259/*
260 * Flags related to options.
261 */
262static int numbering = FALSE;          // Line numbering option
263static int folding = TRUE;             // Line folding option
264static int restart = FALSE;            // Don't restart page number after each file
265static int only_printable = FALSE;     // Replace non printable char by space
266static int interpret = TRUE;           // Interpret TAB, FF and BS chars option
267static int print_binaries = FALSE;     // Force printing for binary files
268static int landscape = TRUE;           // Otherwise portrait format sheets
269static int new_landscape = TRUE;       // To scrute changes of landscape option
270static int twinpages = TRUE;           // 2 pages per sheet if true, 1 otherwise
271static int new_twinpages = TRUE;       // To scrute changes of twinpages option
272static int twinfiles = FALSE;          // Allow 2 files per sheet
273static int no_header = FALSE;          // TRUE if user doesn't want the header
274static int no_border = FALSE;          // Don't print the surrounding border ?
275static int printdate = FALSE;          // Print current date as footnote
276static int filename_footer = TRUE;     // Print file name at bottom of page
277static int no_summary = FALSE;         // Quiet mode?
278static WEIGHT fontweight = NORMAL;     // Control font weight: BOLD or NORMAL
279static WEIGHT new_fontweight = NORMAL; // To scrute changes of bold option
280#if defined(SYSV) || defined(BSD)
281int login_id = TRUE;            // Print login ID at top of page
282#endif
283#if LPR_PRINT
284static int lpr_print = TRUE;           // Fork a lpr process to do the printing
285#ifdef RECTO_VERSO_PRINTING
286int rectoverso = TWOSIDED_DFLT; // Two-side printing
287#endif
288#endif
289static int ISOlatin1 = FALSE;          // Print 8-bit characters?
290
291
292/*
293 * Counters of different kinds.
294 */
295static int column = 0;                 // Column number (in current line)
296static int line = 0;                   // Line number (in current page)
297static int line_number = 0;            // Source line number
298static int pages = 0;                  // Number of logical pages printed
299static int sheets = 0;                 // Number of physical pages printed
300static int old_pages, old_sheets;      // Value before printing current file
301static int sheetside = 0;              // Side of the sheet currently printing
302static int linesperpage;               // Lines per page
303static int lines_requested = 0;        // Lines per page requested by the user
304static int new_linesrequest = 0;       // To scrute new values for lines_requested
305static int columnsperline;             // Characters per output line
306static int nonprinting_chars, chars;   // Number of nonprinting and total chars
307static int copies_number = 1;          // Number of copies to print
308static int column_width = 8;           // Default column tab width (8)
309
310
311/*
312 * Other global variables.
313 */
314static int first_page;                 // First page for a file
315static int no_files = TRUE;            // No file until now
316static int prefix_width;               // Width in characters for line prefix
317static float fontsize = 0.0;           // Size of a char for body font
318static float new_fontsize = 0.0;       // To scrute new values for fontsize
319static char *command;                  // Name of a2ps program
320static char *lpr_opt = NULp;           // Options to lpr
321static char *header_text = NULp;       // Allow for different header text
322static float header_size;              // Size of the page header
323static char *prologue = NULp;          // postscript header file
324static char current_filename[MAXFILENAME+1];   // Name of the file being printed
325static char currentdate[18];           // Date for today
326static char filedate[18];              // Last modification time for current file
327#if defined(SYSV) || defined(BSD)
328char *login = NULp;             // user's login name and host machine
329#endif
330
331
332/*
333 * Sheet dimensions
334 */
335static double page_height = HEIGHT;    // Paper height
336static double page_width = WIDTH;      // Paper width
337
338
339//**********************************************************************
340/*                                                                      */
341/*                                                                      */
342//**********************************************************************
343
344/*
345 * Print a usage message.
346 */
347static void usage(int failure) {
348    // failure: Must we exit with a failure code?
349    fprintf(stderr, "A2ps v%s usage: %s [pos. or global options] [ f1 [ [pos. options] f2 ...] ]\n", VERSION, command);
350    fprintf(stderr, "pos.   =  -#num\t\tnumber of copies to print\n");
351    fprintf(stderr, "          -1\t\tone page per sheet\n");
352    fprintf(stderr, "          -2\t\tTWIN PAGES per sheet\n");
353    fprintf(stderr, "          -d\t-nd\tprint (DON'T PRINT) current date at the bottom\n");
354    fprintf(stderr, "          -Fnum\t\tfont size, num is a float number\n");
355    fprintf(stderr, "          -Hstr\t\tuse str like header title for subsequent files\n");
356#if defined(SYSV) || defined(BSD)
357    fprintf(stderr, "          \t-nL\tdon't print login ID on top of page\n");
358#endif
359    fprintf(stderr, "          -l\t\tprint in LANDSCAPE mode\n");
360    fprintf(stderr, "          -lnum\t\tuse num lines per page\n");
361    fprintf(stderr, "          -m\t\tprocess the file as a man\n");
362    fprintf(stderr, "          -n\t-nn\tNUMBER (don't number) line files\n");
363    fprintf(stderr, "          -p\t\tprint in portrait mode\n");
364    fprintf(stderr, "          -q\t\tprint in quiet mode (no summary)\n");
365    fprintf(stderr, "          -s\t-ns\tPRINT (don't print) surrounding borders\n");
366    fprintf(stderr, "\n");
367    fprintf(stderr, "global =  -?\t\tprint this information\n");
368    fprintf(stderr, "          -B\t-nB\tprint (DON'T PRINT) in bold font\n");
369    fprintf(stderr, "          -b\t-nb\tforce (DON'T FORCE) binary printing\n");
370    fprintf(stderr, "          -c\t-nc\tallow (DON'T ALLOW) two files on the same sheet\n");
371    fprintf(stderr, "          -f\t-nf\tFOLD (don't fold) lines\n");
372    fprintf(stderr, "          \t-nH\tdon't print any header\n");
373    fprintf(stderr, "          -h\t\tprint this information\n");
374    fprintf(stderr, "          -Ifile\tinclude this file as a2ps prologue\n");
375    fprintf(stderr, "          -i\t-ni\tINTERPRET (don't interpret) tab, bs and ff chars\n");
376#if LPR_PRINT
377    fprintf(stderr, "          -Pprinter -nP\tSEND (don't send) directly to the printer");
378#ifdef LPR_OPT
379    if (LPR_OPT && sizeof(LPR_OPT) > 0)
380        fprintf(stderr, "\n\t\t\t(with options '%s' and -Pprinter)", LPR_OPT);
381#endif
382    fprintf(stderr, "\n");
383#endif
384    fprintf(stderr, "          -r\t-nr\tRESTART (don't restart) page number after each file\n");
385#ifdef RECTO_VERSO_PRINTING
386#ifdef TWOSIDED_DFLT
387    fprintf(stderr, "          -s1\t-s2\tone-sided (TWO-SIDED) printing\n");
388#else
389    fprintf(stderr, "          -s1\t-s2\tONE-SIDED (two-sided) printing\n");
390#endif
391#endif
392    fprintf(stderr, "          -tnum\t\tset tab size to n\n");
393    fprintf(stderr, "          \t-nu\tdon't print a filename footer\n");
394    fprintf(stderr, "          -v\t-nv\tVISIBLE (blank) display of unprintable chars\n");
395    fprintf(stderr, "          -8\t-n8\tdisplay (DON'T DISPLAY) 8-bit chars\n");
396    exit(failure);
397}
398
399/*
400 * Set an option only if it's global.
401 */
402static void set_global_option(char *arg) {
403    switch (arg[1]) {
404        case '?':                               // help
405        case 'h':
406            usage(EXIT_SUCCESS);
407        case 'b':                               // print binary files
408            if (arg[2] != NUL)
409                usage(EXIT_FAILURE);
410            print_binaries = TRUE;
411            break;
412        case 'c':                               // allow two files per sheet
413            if (arg[2] != NUL)
414                usage(EXIT_FAILURE);
415            twinfiles = TRUE;
416            break;
417        case 'f':                               // fold lines too large
418            if (arg[2] != NUL)
419                usage(EXIT_FAILURE);
420            folding = TRUE;
421            break;
422        case 'I':                               // include this file as a2ps prologue
423            if (arg[2] == NUL)
424                usage(EXIT_FAILURE);
425            prologue = arg+2;
426            break;
427        case 'i':                               // interpret control chars
428            if (arg[2] != NUL)
429                usage(EXIT_FAILURE);
430            interpret = TRUE;
431            break;
432        case 'n':
433            if (arg[2] == NUL)
434                return;
435            if (arg[3] != NUL)
436                usage(EXIT_FAILURE);
437            switch (arg[2]) {
438                case 'b':                       // don't print binaries
439                    print_binaries = FALSE;
440                    break;
441                case 'c':                       // don't allow 2 files/sheet
442                    twinfiles = FALSE;
443                    break;
444                case 'f':                       // cut lines too long
445                    folding = FALSE;
446                    break;
447                case 'H':                       // don't print header
448                    no_header = TRUE;
449                    break;
450                case 'i':                       // don't interpret ctrl chars
451                    interpret = FALSE;
452                    break;
453#if LPR_PRINT
454                case 'P':                       // don't lpr
455                    lpr_print = FALSE;
456                    break;
457#endif
458                case 'r':                       // don't restart sheet number
459                    restart = FALSE;
460                    break;
461                case 'v':                       // only printable chars
462                    only_printable = TRUE;
463                    break;
464                case '8':                       // don't print 8-bit chars
465                    ISOlatin1 = FALSE;
466                    break;
467                case 'B':
468                case 'd':
469                case 'L':
470                case 'm':
471                case 'n':
472                case 's':
473                case 'u':
474                    if (arg[3] != NUL)
475                        usage(EXIT_FAILURE);
476                    return;
477                default:
478                    usage(EXIT_FAILURE);
479            }
480            break;
481#if LPR_PRINT
482        case 'P':                                       // fork a process to print
483            if (arg[2] != NUL) {
484                lpr_opt = (char *)malloc(strlen(arg)+1);
485                strcpy(lpr_opt, arg);
486            }
487            lpr_print = TRUE;
488            break;
489#endif
490        case 'q':                                       // don't print a summary
491            no_summary = TRUE;
492            break;
493        case 'r':                                       // restart sheet number
494            if (arg[2] != NUL)
495                usage(EXIT_FAILURE);
496            restart = TRUE;
497            break;
498        case 's':
499            if (arg[2] == NUL)
500                return;
501#ifdef RECTO_VERSO_PRINTING
502            if (arg[3] == NUL) {
503                if (arg[2] == '1') {            // one-sided printing
504                    rectoverso = FALSE;
505                    break;
506                }
507                if (arg[2] == '2') {            // two-sided printing
508                    rectoverso = TRUE;
509                    break;
510                }
511            }
512#endif
513            usage(EXIT_FAILURE);
514            break;
515        case 't':                               // set tab size
516            if (arg[2] == NUL || (column_width = atoi(arg+2)) <= 0)
517                usage(EXIT_FAILURE);
518            break;
519        case 'v':                               // print control chars
520            if (arg[2] != NUL)
521                usage(EXIT_FAILURE);
522            only_printable = FALSE;
523            break;
524        case '8':                               // print 8-bit chars
525            if (arg[2] != NUL)
526                usage(EXIT_FAILURE);
527            ISOlatin1 = TRUE;
528            break;
529        case '1':
530        case '2':
531        case 'B':
532        case 'd':
533        case 'm':
534        case 'p':
535            if (arg[2] != NUL)
536                usage(EXIT_FAILURE);
537        case '#':
538        case 'F':
539        case 'H':
540        case 'l':
541            return;
542        default:
543            usage(EXIT_FAILURE);
544    }
545    arg[0] = NUL;
546}
547
548/*
549 * Set an option of the command line. This option will be applied
550 * to all files that will be found in the rest of the command line.
551 * The -H option is the only exception: it is applied only to the
552 * file.
553 */
554static void set_positional_option(char *arg) {
555    int copies;
556    int lines;
557    float size;
558
559    switch (arg[1]) {
560        case NUL:                               // global option
561            break;
562        case '#':                               // n copies
563            if (sscanf(&arg[2], "%d", &copies) != 1 || copies <= 0)
564                fprintf(stderr, "Bad number of copies: '%s'. Ignored\n", &arg[2]);
565            else
566                copies_number = copies;
567            printf("/#copies %d def\n", copies_number);
568            break;
569        case '1':                               // 1 logical page per sheet
570            if (arg[2] != NUL)
571                usage(EXIT_FAILURE);
572            new_twinpages = FALSE;
573            break;
574        case '2':                               // twin pages
575            if (arg[2] != NUL)
576                usage(EXIT_FAILURE);
577            new_twinpages = TRUE;
578            break;
579        case 'B':
580            new_fontweight = BOLD;              // use bold font
581            break;
582        case 'd':                               // print current date/time
583            printdate = TRUE;
584            break;
585        case 'F':                               // change font size
586            if (arg[2] == NUL || sscanf(&arg[2], "%f", &size) != 1 || size == 0.0) {
587                fprintf(stderr, "Wrong value for option -F: '%s'. Ignored\n",
588                        &arg[2]);
589                break;
590            }
591            new_fontsize = size;
592            break;
593        case 'H':                               // header text
594            header_text = arg+2;
595            break;
596        case 'l':
597            if (arg[2] == NUL) {                // landscape format
598                new_landscape = TRUE;
599                break;
600            }
601            // set lines per page
602            // Useful with preformatted files. Scaling is automatically
603            // done when necessary.
604            if (sscanf(&arg[2], "%d", &lines) != 1
605                || lines < 0 || lines > MAX_LINES)
606            {
607                fprintf(stderr, "Wrong value for option -l: '%s'. Ignored\n",
608                        &arg[2]);
609                break;
610            }
611            new_linesrequest = lines;
612            break;
613        case 'm':                               // Process file as a man
614            new_linesrequest = MAN_LINES;
615            numbering = FALSE;
616            break;
617        case 'n':                               // number file lines
618            if (arg[2] == NUL) {
619                numbering = TRUE;
620                break;
621            }
622            switch (arg[2]) {
623                case 'B':                       // disable bold text
624                    new_fontweight = NORMAL;
625                    break;
626                case 'd':                       // don't print date/time
627                    printdate = FALSE;
628                    break;
629#if defined(SYSV) || defined(BSD)
630                case 'L':                       // no login name in footer
631                    login_id = FALSE;
632                    break;
633#endif
634                case 'l':                       // portrait format
635                    new_landscape = FALSE;
636                    break;
637                case 'm':                       // stop processing as a man
638                    new_linesrequest = 0;
639                    break;
640                case 'n':                       // don't number lines
641                    numbering = FALSE;
642                    break;
643                case 'p':                       // landscape format
644                    new_landscape = TRUE;
645                    break;
646                case 's':                       // no surrounding border
647                    no_border = TRUE;
648                    break;
649                case 'u':                       // no filename in footer
650                    filename_footer = FALSE;
651                    break;
652                default:
653                    usage(EXIT_FAILURE);
654            }
655            break;
656        case 'p':                               // portrait format
657            if (arg[2] != NUL)
658                usage(EXIT_FAILURE);
659            new_landscape = FALSE;
660            break;
661        case 's':                               // surrounding border
662            if (arg[2] != NUL)
663                usage(EXIT_FAILURE);
664            no_border = FALSE;
665            break;
666        default:
667            usage(EXIT_FAILURE);
668    }
669}
670
671
672//**************************************************************
673//                      Service routines
674//**************************************************************
675
676/*
677 * This routine buffers a line of input, release one character at a time
678 * or a whole sequence of characters with some meaning like bold sequences
679 * produced by nroff (no others sequences are recognized by the moment):
680 *        <c><\b><c><\b><c><\b><c>
681 */
682static int mygetc(int *statusp) {
683#define BUFFER_SIZE     512
684    static int curr = 0;
685    static int size = 0;
686    static unsigned char buffer[BUFFER_SIZE+1];
687    int c;
688
689    *statusp = IS_ROMAN;
690
691    // Read a new line, if necessary
692    if (curr >= size) {
693        if (!fgets((char *)buffer, BUFFER_SIZE+1, stdin))
694            return  EOF;
695        size = strlen((char *)buffer);
696        if (size < BUFFER_SIZE && buffer[size-1] != '\n') {
697            buffer[size] = '\n';
698            buffer[++size] = '\0';
699        }
700        curr = 0;
701    }
702    if (buffer[curr+1] != '\b')         // this is not a special sequence
703        return  buffer[curr++];
704
705    // Check if it is a bold sequence
706    c = buffer[curr++];
707    if (c               == buffer[curr+1] &&
708        buffer[curr]    == buffer[curr+2] &&
709        c               == buffer[curr+3] &&
710        buffer[curr]    == buffer[curr+4] &&
711        c               == buffer[curr+5])
712    {
713        *statusp = IS_BOLD;
714        curr += 6;
715    }
716
717    // Return the first character of the sequence
718    return  c;
719}
720
721/*
722 * Test if we have a binary file.
723 */
724static int is_binaryfile(char *name) {
725    if (chars > 120 || pages > 1) {
726        first_page = FALSE;
727        if (chars && !print_binaries && (nonprinting_chars*100 / chars) >= 60) {
728            fprintf(stderr, "%s is a binary file: printing aborted\n", name);
729            return TRUE;
730        }
731    }
732    return FALSE;
733}
734
735/*
736 * Cut long filenames.
737 */
738static void cut_filename(char *old_name, char *new_name) {
739    char *p;
740    int   i;
741    char *separator;
742
743    if ((i = strlen(old_name)) <= MAXFILENAME) {
744        strcpy(new_name, old_name);
745        return;
746    }
747    p = old_name + (i-1);
748    separator = NULp;
749    i = 1;
750    while (p >= old_name && i < MAXFILENAME) {
751        if (*p == DIR_SEP)
752            separator = p;
753        p--;
754        i++;
755    }
756    if (separator)
757        p = separator;
758    else if (p >= old_name)
759        while (p >= old_name && *p != DIR_SEP) p--;
760
761    for (i = 0, p++; *p != NUL; i++)
762        *new_name++ = *p++;
763    *new_name = NUL;
764}
765
766/*
767 * Print a char in a form accepted by postscript printers.
768 */
769static int printchar(unsigned char c) {
770
771    if (c >= ' ' && c < 0177) {
772        if (c == '(' || c == ')' || c == '\\')
773            putchar('\\');
774        putchar(c);
775        return 0;
776    }
777
778    if (ISOlatin1 && (c > 0177)) {
779        printf("\\%o", c);
780        return 0;
781    }
782
783    if (only_printable) {
784        putchar(' ');
785        return 1;
786    }
787
788    if (c > 0177) {
789        printf("M-");
790        c &= 0177;
791    }
792    if (c < ' ') {
793        putchar('^');
794        if ((c = c + '@') == '(' || c == ')' || c == '\\')
795            putchar('\\');
796        putchar(c);
797    }
798    else if (c == 0177)
799        printf("^?");
800    else {
801        if (c == '(' || c == ')' || c == '\\')
802            putchar('\\');
803        putchar(c);
804    }
805
806    return 1;
807}
808
809/*
810 * Begins a new logical page.
811 */
812static void skip_page() {
813    if (twinpages == FALSE || sheetside == 0) {
814        printf("%%%%Page: %d %d\n", sheets+1, sheets+1);
815        printf("/pagesave save def\n");
816        // Reinitialize state variables for each new sheet
817        print_page_prologue(0);
818    }
819    startpage();
820}
821
822/*
823 * Fold a line too long.
824 */
825static int fold_line(char *name) {
826    column = 0;
827    printf(") s\n");
828    if (++line >= linesperpage) {
829        endpage();
830        skip_page();
831        if (first_page && is_binaryfile(name))
832            return FALSE;
833        line = 0;
834    }
835    if (numbering)
836        printf("(    +");
837    else
838        printf("( ");
839
840    return TRUE;
841}
842
843/*
844 * Cut a textline too long to the size of a page line.
845 */
846static int cut_line() {
847    int c;
848    int status;
849
850    while ((c = mygetc(&status)) != EOF && c != '\n' && c != '\f') ;
851    return c;
852}
853
854
855//**************************************************************
856//                      "Postscript" routines.
857//**************************************************************
858
859/*
860 * Print a physical page.
861 */
862static void printpage() {
863    sheetside = 0;
864    sheets++;
865    printf("/sd 0 def\n");
866    if (no_border == FALSE)
867        printf("%d sn\n", sheets - (restart ? old_sheets : 0));
868    if (printdate)
869        printf("cd\n");
870    if (filename_footer && landscape)
871        printf("fnf\n");
872#if defined(SYSV) || defined(BSD)
873    if (login_id)
874        printf("lg lgp\n");
875#endif
876    printf("pagesave restore\n");
877    printf("showpage\n");
878}
879
880/*
881 * Prints page header and page border and
882 * initializes printing of the file lines.
883 */
884void startpage() {
885    if (sheetside == 0) {
886#ifdef RECTO_VERSO_PRINTING
887        if (rectoverso && (sheets & 0x1)) {
888            // Shift to left backside pages.
889            printf("rm neg 0 translate\n");
890        }
891#endif
892        if (landscape) {
893            printf("sw 0 translate\n");
894            printf("90 rotate\n");
895        }
896    }
897    pages++;
898    if (no_header == FALSE)
899        printf("%d hp\n", pages - old_pages);
900    if (no_border == FALSE) {
901        printf("border\n");
902        if (no_header == FALSE)
903            printf("hborder\n");
904    }
905    printf("/x0 x %d get bm add def\n", sheetside);
906    printf("/y0 y %d get bm bfs add %s add sub def\n",
907           sheetside, no_header ? "0" : "hs");
908    printf("x0 y0 moveto\n");
909    printf("bf setfont\n");
910}
911
912/*
913 * Terminates printing, flushing last page.
914 */
915static void cleanup() {
916    if (twinpages && sheetside == 1)
917        printpage();
918#ifdef RECTO_VERSO_PRINTING
919    if (!twinfiles && rectoverso && (sheets & 0x1) != 0) {
920        sheetside = 0;
921        sheets++;
922        printf("%%%%Page: %d %d\n", sheets, sheets);
923        printf("showpage\n");
924    }
925#endif
926}
927
928/*
929 * Adds a sheet number to the page (footnote) and prints the formatted
930 * page (physical impression). Activated at the end of each source page.
931 */
932void endpage() {
933    if (twinpages && sheetside == 0) {
934        sheetside = 1;
935        printf("/sd 1 def\n");
936    }
937    else
938        printpage();
939}
940
941
942//**************************************************************
943//              Printing a file
944//**************************************************************
945
946/*
947 * Print the file prologue.
948 */
949static void init_file_printing(char *name, char *title) {
950    int new_format, new_font;
951    char *string;
952    int lines;
953    float char_width;
954    struct stat statbuf;
955
956    // Print last page of previous file, if necessary
957    if (pages > 0 && !twinfiles)
958        cleanup();
959
960    // Initialize variables related to the format
961    new_format = FALSE;
962    if (new_landscape != landscape || new_twinpages != twinpages) {
963        landscape = new_landscape;
964        twinpages = new_twinpages;
965        new_format = TRUE;
966    }
967
968    // Initialize variables related to the header
969    if (no_header && name == title)
970        header_size = 0.0;
971    else {
972        if (landscape || twinpages)
973            header_size = LANDSCAPE_HEADER * PIXELS_INCH;
974        else
975            header_size = PORTRAIT_HEADER * PIXELS_INCH;
976        cut_filename(title, current_filename);
977    }
978
979    // Initialize variables related to the font size
980    new_font = FALSE;
981    if (fontsize != new_fontsize || new_format ||
982        lines_requested != new_linesrequest || fontweight != new_fontweight)
983    {
984        if (new_fontsize == 0.0 || (fontsize == new_fontsize && new_format)) {
985            new_fontsize = landscape ? 6.8 : twinpages ? 6.4 : 9.0;
986        }
987        if (lines_requested != new_linesrequest) {
988            if ((lines_requested = new_linesrequest) != 0) {
989                // Scale fontsize
990                if (landscape)       lines = (int)((page_width-header_size) / new_fontsize) - 1;
991                else if (twinpages)  lines = (int)(((page_height - 2*header_size) / 2) / new_fontsize) - 2;
992                else                 lines = (int)((page_height-header_size) / new_fontsize) - 1;
993                new_fontsize *= (float)lines / (float)lines_requested;
994            }
995        }
996        fontsize = new_fontsize;
997        fontweight = new_fontweight;
998        new_font = TRUE;
999    }
1000
1001    // Initialize file printing, if there is any change
1002    if (new_format || new_font) {
1003        char_width = 0.6 * fontsize;
1004        if (landscape) {
1005            linesperpage = (int)((page_width - header_size) / fontsize) - 1;
1006            if (! twinpages)
1007                columnsperline = (int)(page_height / char_width) - 1;
1008            else
1009                columnsperline = (int)((page_height / 2) / char_width) - 1;
1010        }
1011        else {
1012            if (!twinpages)
1013                linesperpage = (int)((page_height - header_size) / fontsize) - 1;
1014            else
1015                linesperpage = (int)(((page_height - 2*header_size) / 2) / fontsize)
1016                    - 2;
1017            columnsperline = (int)(page_width / char_width) - 1;
1018        }
1019        if (lines_requested > 0)
1020            linesperpage = lines_requested;
1021        if (linesperpage <= 0 || columnsperline <= 0) {
1022            fprintf(stderr, "Font %g too big !!\n", fontsize);
1023            exit(EXIT_FAILURE);
1024        }
1025    }
1026
1027    // Retrieve file modification date and hour
1028    if (fstat(fileno(stdin), &statbuf) == -1) {
1029        fprintf(stderr, "Error getting file modification time\n");
1030        exit(EXIT_FAILURE);
1031    }
1032    // Do we have a pipe?
1033    if (S_ISFIFO(statbuf.st_mode))
1034        strcpy(filedate, currentdate);
1035    else {
1036        string = ctime(&statbuf.st_mtime);
1037        sprintf(filedate, "%.6s %.4s %.5s", string+4, string+20, string+11);
1038    }
1039}
1040
1041/*
1042 * Print the prologue necessary for printing each physical page.
1043 * Adobe convention for page independence is enforced through this routine.
1044 */
1045void print_page_prologue(int side) {
1046    // side: Logical page to print (left/right)
1047
1048    // General format
1049    printf("/twp %s def\n", twinpages ? "true" : "false");
1050    printf("/fnfs %d def\n", landscape ? 11 : twinpages ? 10 : 15);
1051    printf("/dfs fnfs 0.8 mul def\n");
1052    printf("/df /Helvetica dfs getfont def\n");
1053    printf("/dw df setfont td stringwidth pop def\n");
1054    printf("/sfnf filenmfontname fnfs getfont def\n");
1055    printf("/hm fnfs 0.25 mul def\n");
1056    // Header size
1057    if (header_size == 0.0)
1058        printf("/hs 0.0 def\n");
1059    else
1060        printf("/hs %g inch def\n",
1061               landscape || twinpages ? LANDSCAPE_HEADER : PORTRAIT_HEADER);
1062    // Font sizes
1063    printf("/bfs %g def\n", fontsize);
1064    printf("/bdf /Courier-Bold bfs getfont def\n");
1065    printf("/bm bfs 0.7 mul def\n");
1066    printf("/bf %s bfs getfont def\n",
1067           fontweight == NORMAL ? "/CourierBack" : "/Courier-Bold");
1068    // Page attributes
1069    printf("/l %d def\n", linesperpage);
1070    printf("/c %d def\n", columnsperline);
1071    printf("/pw\n");
1072    printf("   bf setfont (0) stringwidth pop c mul bm dup add add\n");
1073    printf("   def\n");
1074    printf("/ph\n");
1075    printf("   bfs l mul bm dup add add hs add\n");
1076    printf("   def\n");
1077    printf("/fns\n");
1078    printf("      pw\n");
1079    printf("      fnfs 4 mul dw add (Page 999) stringwidth pop add\n");
1080    printf("    sub\n");
1081    printf("  def\n");
1082    printf("/tm margin twp {3} {2} ifelse div def\n");
1083    printf("/sd %d def\n", side);
1084    if (landscape) {
1085        printf("/y [ rm ph add bm add\n");
1086        printf("          dup ] def\n");
1087        printf("/sny dfs dfs add def\n");
1088        printf("/snx sh tm dfs add sub def\n");
1089        printf("/dy sny def\n");
1090        printf("/dx tm dfs add def\n");
1091        if (twinpages) {
1092            printf("/x [ tm                     %% left page\n");
1093            printf("          dup 2 mul pw add  %% right page\n");
1094            printf("        ] def\n");
1095        }
1096        else {
1097            printf("/x [ tm dup ] def\n");
1098        }
1099        printf("/scx sh 2 div def\n");
1100    }
1101    else {
1102        printf("/x [ lm dup ] def\n");
1103        printf("/sny tm dfs 2 mul sub def\n");
1104        printf("/snx sw rm sub dfs sub def\n");
1105        printf("/dy sny def\n");
1106        printf("/dx lm def\n");
1107        if (twinpages) {
1108            printf("/y [ tm ph add 2 mul %% up\n");
1109            printf("          tm ph add  %% down\n");
1110            printf("        ] def\n");
1111        }
1112        else {
1113            printf("\n%% Only one logical page\n");
1114            printf("/y [ sh tm sub dup ] def\n");
1115        }
1116        printf("/scx sw 2 div def\n");
1117    }
1118    printf("/fny dy def\n");
1119    printf("/fnx scx def\n");
1120    printf("/ly fnfs 2 div y sd get add def\n");
1121    printf("/lx snx def\n");
1122    printf("/d (%s) def\n", filedate);
1123    printf("( %s ) fn\n", current_filename);
1124}
1125
1126/*
1127 * Print one file.
1128 */
1129static void print_file(char *name, char *header) {
1130    int c;
1131    int nchars;
1132    int start_line, start_page;
1133    int continue_exit;
1134    int status, new_status;
1135
1136    // Reinitialize postscript variables depending on positional options
1137    init_file_printing(name, header ? header : name);
1138
1139    // If we are in compact mode and the file beginning is to be printed
1140    // in the middle of a twinpage, we have to print a new page prologue
1141    if (twinfiles && sheetside == 1)
1142        print_page_prologue(1);
1143
1144    /*
1145     * Boolean to indicates that previous char is \n (or interpreted \f)
1146     * and a new page would be started, if more text follows
1147     */
1148    start_page = FALSE;
1149
1150    /*
1151     * Printing binary files is not very useful. We stop printing
1152     * if we detect one of these files. Our heuristic to detect them:
1153     * if 75% characters of first page are non-printing characters,
1154     * the file is a binary file.
1155     * Option -b force binary files impression.
1156     */
1157    nonprinting_chars = chars = 0;
1158
1159    // Initialize printing variables
1160    column = 0;
1161    line = line_number = 0;
1162    first_page = TRUE;
1163    start_line = TRUE;
1164    prefix_width = numbering ? 6 : 1;
1165
1166    // Start printing
1167    skip_page();
1168
1169    // Process each character of the file
1170    status = IS_ROMAN;
1171    c = mygetc(&new_status);
1172    while (c != EOF) {
1173        /*
1174         * Preprocessing (before printing):
1175         * - TABs expansion (see interpret option)
1176         * - FF and BS interpretation
1177         * - replace non printable characters by a space or a char sequence
1178         *   like:
1179         *     ^X for ascii codes < 0x20 (X = [@, A, B, ...])
1180         *     ^? for del char
1181         *     M-c for ascii codes > 0x3f
1182         * - prefix parents and backslash ['(', ')', '\'] by backslash
1183         *   (escape character in postscript)
1184         */
1185        // Form feed
1186        if (c == '\f' && interpret) {
1187            // Close current line
1188            if (!start_line) {
1189                printf(") s\n");
1190                start_line = TRUE;
1191            }
1192            // start a new page ?
1193            if (start_page)
1194                skip_page();
1195            // Close current page and begin another
1196            endpage();
1197            start_page = TRUE;
1198            // Verification for binary files
1199            if (first_page && is_binaryfile(name))
1200                return;
1201            line = 0;
1202            column = 0;
1203            if ((c = mygetc(&new_status)) == EOF)
1204                break;
1205        }
1206
1207        // Start a new line ?
1208        if (start_line) {
1209            if (start_page) {
1210                // only if there is something to print!
1211                skip_page();
1212                start_page = FALSE;
1213            }
1214            if (numbering)
1215                printf("(%4d|", ++line_number);
1216            else
1217                printf("( ");
1218            start_line = FALSE;
1219        }
1220
1221        // Is a new font ? This feature is used only to detect bold
1222        // sequences produced by nroff (man pages), in connexion with
1223        // mygetc.
1224        if (status != new_status) {
1225            printf(")\n");
1226            printf("%s", status == IS_ROMAN ? "b" : "st");
1227            printf(" (");
1228            status = new_status;
1229        }
1230
1231        // Interpret each character
1232        switch (c) {
1233            case '\b':
1234                if (!interpret)
1235                    goto print;
1236                // A backspace is converted to 2 chars ('\b'). These chars
1237                // with the Courier backspace font produce correct under-
1238                // lined strings.
1239                if (column)
1240                    column--;
1241                putchar('\\');
1242                putchar('b');
1243                break;
1244            case '\n':
1245                column = 0;
1246                start_line = TRUE;
1247                printf(") s\n");
1248                if (++line >= linesperpage) {
1249                    endpage();
1250                    start_page = TRUE;
1251                    if (first_page && is_binaryfile(name))
1252                        return;
1253                    line = 0;
1254                }
1255                break;
1256            case '\t':
1257                if (interpret) {
1258                    continue_exit = FALSE;
1259                    do {
1260                        if (++column + prefix_width > columnsperline) {
1261                            if (folding) {
1262                                if (fold_line(name) == FALSE)
1263                                    return;
1264                            }
1265                            else {
1266                                c = cut_line();
1267                                continue_exit = TRUE;
1268                                break;
1269                            }
1270                        }
1271                        putchar(' ');
1272                    } while (column % column_width);
1273                    if (continue_exit)
1274                        continue;
1275                    break;
1276                }
1277            default:
1278            print :
1279                if (only_printable) {
1280                    nchars = 1;
1281                }
1282                else if (! ISOlatin1) {
1283                    nchars = c > 0177 ? 2 : 0;
1284                    nchars += (c&0177) < ' ' || (c&0177) == 0177 ? 2 : 1;
1285                }
1286                else {
1287                    nchars = c < ' ' || (c >= 0177 && c < 144) ? 2 : 1;
1288                }
1289
1290                if (prefix_width + (column += nchars) > columnsperline) {
1291                    if (folding) {
1292                        if (fold_line(name) == FALSE) {
1293                            return;
1294                        }
1295                    }
1296                    else {
1297                        c = cut_line();
1298                        new_status = IS_ROMAN;
1299                        continue;
1300                    }
1301                }
1302                nonprinting_chars += printchar(c);
1303                chars++;
1304                break;
1305        }
1306        c = mygetc(&new_status);
1307    }
1308
1309    if (!start_line)
1310        printf(") s\n");
1311    if (!start_page)
1312        endpage();
1313}
1314
1315
1316//**************************************************************
1317//              Print a postscript prologue for a2ps.
1318//**************************************************************
1319
1320/*
1321 * Print the a2ps prologue.
1322 */
1323static void print_prologue() {
1324    int             c;
1325    FILE           *f = NULp;
1326    char           *datestring;
1327#if defined(SYSV) || defined(BSD)
1328    char           *logname, *host;
1329    int             rt;
1330#endif
1331#if defined(SYSV)
1332    struct utsname  snames;
1333#endif
1334
1335    // Retrieve date and hour
1336#if defined(__STDC__)
1337    time_t date;
1338
1339    if (time(&date) == -1) {
1340        fprintf(stderr, "Error calculating time\n");
1341        exit(EXIT_FAILURE);
1342    }
1343    datestring = ctime(&date);
1344#else
1345#ifdef BSD
1346    struct timeval date;
1347    struct tm *p;
1348
1349    (void) gettimeofday(&date, (struct timezone *)0);
1350    p = localtime(&date.tv_sec);
1351    datestring = asctime(p);
1352#else
1353#ifdef SYSV
1354    struct timeb date;
1355
1356    (void)ftime(&date);
1357    datestring = ctime(&date.time);
1358#else
1359
1360    datestring = "--- --- -- --:--:-- ----";
1361#endif
1362#endif
1363#endif
1364
1365#if defined(SYSV) || defined(BSD)
1366    // Retrieve user's login name and hostname
1367    logname = getlogin();
1368    host = (char *)malloc(MAX_HOSTNAME);
1369    if (host) {
1370#if defined(SYSV)
1371        if ((rt = uname(&snames)) == -1 || !snames.nodename[0]) {
1372            free(host);
1373            host = NULp;
1374        }
1375        else
1376            strcpy(host, snames.nodename);
1377#else
1378        if ((rt = gethostname(host, MAX_HOSTNAME)) == -1 || !host[0]) {
1379            free(host);
1380            host = NULp;
1381        }
1382#endif
1383    }
1384#endif
1385
1386    // Print a general prologue
1387    if (!prologue)
1388        print_standard_prologue(datestring);
1389    else if ((f = fopen(prologue, "r"))) {
1390        // Header file printing
1391        while ((c = getc(f)) != EOF)
1392            putchar(c);
1393    }
1394    else {
1395        fprintf(stderr, "Postscript header missing: %s\n", prologue);
1396        exit(EXIT_FAILURE);
1397    }
1398
1399    // Completes the prologue with a2ps static variables
1400    printf("\n%% Initialize page description variables.\n");
1401    printf("/x0 0 def\n");
1402    printf("/y0 0 def\n");
1403    printf("/sh %g inch def\n", (double)HEIGHT);
1404    printf("/sw %g inch def\n", (double)WIDTH);
1405    printf("/margin %g inch def\n", (double)MARGIN);
1406    printf("/rm margin 3 div def\n");
1407    printf("/lm margin 2 mul 3 div def\n");
1408    printf("/d () def\n");
1409
1410    // And print them
1411    sprintf(currentdate, "%.6s %.4s %.5s",
1412            datestring+4, datestring+20, datestring+11);
1413    printf("/td (%s) def\n", currentdate);
1414
1415#if defined(SYSV) || defined(BSD)
1416    // Add the user's login name string to the Postscript output
1417    if (logname || host) {
1418        if (logname && host)
1419            printf("/lg (Printed by %s from %s) def\n", logname, host);
1420        else if (logname)
1421            printf("/lg (Printed by %s) def\n", logname);
1422        else
1423            printf("/lg (Printed from %s) def\n", host);
1424    }
1425
1426    // If the host string was allocated via malloc, release the memory
1427    if (host)
1428        free(host);
1429#endif
1430
1431    // Close prolog
1432    printf("%%%%EndProlog\n\n");
1433
1434    // Go on
1435    printf("/docsave save def\n");
1436    if (f) fclose(f);
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, 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        if (pipe(fd) != 0) {
1691            fprintf(stderr, "Could not create pipe (Reason: %s)\n", strerror(errno));
1692            exit(EXIT_FAILURE);
1693        }
1694
1695        if (fork() == 0) {
1696            dup2(fd[0], 0);
1697            close(fd[0]); close(fd[1]);
1698            narg = 0;
1699            lpr_args[narg++] = LPR_COMMAND;
1700#ifdef LPR_OPT
1701            lpr_args[narg++] = LPR_OPT;
1702#endif
1703            if (lpr_opt)
1704                lpr_args[narg++] = lpr_opt;
1705#ifdef RECTO_VERSO_PRINTING
1706            if (rectoverso)
1707                lpr_args[narg++] = TWOSIDED;
1708            else
1709                lpr_args[narg++] = ONESIDED;
1710#endif
1711            lpr_args[narg] = (char *)0;
1712            execvp(LPR_COMMAND, (char**)lpr_args);
1713            fprintf(stderr, "Error starting lpr process \n");
1714            exit(EXIT_FAILURE);
1715        }
1716        dup2(fd[1], 1);
1717        close(fd[0]);
1718        close(fd[1]);
1719    }
1720#endif
1721
1722    // Initialize variables not depending of positional options
1723    landscape = twinpages = -1; // To force format switching
1724    fontsize = -1.0;                    // To force fontsize switching
1725    page_height = (double)(HEIGHT - MARGIN) * PIXELS_INCH;
1726    page_width = (double)(WIDTH - MARGIN) * PIXELS_INCH;
1727
1728    // Postscript prologue printing
1729    print_prologue();
1730
1731    // Print files designated or standard input
1732    arg = argv[narg = 1];
1733    while (narg < argc) {
1734        if (arg[0] != NUL) {
1735            if (arg[0] == '-')
1736                set_positional_option(arg);
1737            else {
1738                if (!freopen(arg, "r", stdin)) {
1739                    fprintf(stderr, "Error opening %s\n", arg);
1740                    cleanup();
1741                    printf("\n%%%%Trailer\ndocsave restore end\n\4");
1742                    exit(EXIT_FAILURE);
1743                }
1744                no_files = FALSE;
1745
1746                // Save counters values
1747                old_pages = pages;
1748                if (twinfiles && twinpages)
1749                    old_sheets = sheets;
1750                else
1751                    old_sheets = sheets + sheetside;
1752
1753                // Print the file
1754                print_file(arg, header_text);
1755
1756                // Print the number of pages and sheets printed
1757                if (no_summary == FALSE) {
1758                    total = pages - old_pages;
1759                    fprintf(stderr, "[%s: %d page%s on ", arg,
1760                            total, total == 1 ? "" : "s");
1761                    total = sheets - old_sheets + sheetside;
1762#ifdef RECTO_VERSO_PRINTING
1763                    if (rectoverso)
1764                        total = (total+1) / 2;
1765#endif
1766                    fprintf(stderr, "%d sheet%s]\n", total, total == 1 ? "" : "s");
1767                }
1768
1769                // Reinitialize header title
1770                header_text = NULp;
1771            }
1772        }
1773        arg = argv[++narg];
1774    }
1775    if (no_files)
1776        print_file((char*)"stdin", header_text);
1777
1778    // Print the total number of pages printed
1779    if (no_summary == FALSE && pages != old_pages) {
1780        fprintf(stderr, "[Total: %d page%s on ", pages, pages == 1 ? "" : "s");
1781        total = sheets + sheetside;
1782#ifdef RECTO_VERSO_PRINTING
1783        if (rectoverso)
1784            total = (total+1) / 2;
1785#endif
1786        fprintf(stderr, "%d sheet%s]\n", total, total == 1 ? "" : "s");
1787    }
1788
1789    // And stop
1790    cleanup();
1791    printf("\n%%%%Trailer\n");
1792    printf("%%%%Pages: %d\n", sheets + sheetside);
1793    printf("docsave restore end\n");
1794
1795    exit(EXIT_SUCCESS);
1796}
Note: See TracBrowser for help on using the repository browser.