1 /*
2  * Internal header file.
3  * Copyright (c) 1995-2000 Markku Rossi.
4  *
5  * Author: Markku Rossi <mtr@iki.fi>
6  */
7 
8 /*
9  * This file is part of GNU Enscript.
10  *
11  * Enscript is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * Enscript is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with Enscript.  If not, see <http://www.gnu.org/licenses/>.
23  */
24 
25 #ifndef GSINT_H
26 #define GSINT_H
27 
28 /*
29  * Config stuffs.
30  */
31 
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35 
36 #include <stdio.h>
37 
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 
41 #ifndef ___P
42 #if PROTOTYPES
43 #define ___P(protos) protos
44 #else /* no PROTOTYPES */
45 #define ___P(protos) ()
46 #endif /* no PROTOTYPES */
47 #endif
48 
49 #if STDC_HEADERS
50 
51 #include <stdlib.h>
52 #include <string.h>
53 
54 #else /* no STDC_HEADERS */
55 
56 #if HAVE_STDLIB_H
57 #include <stdlib.h>
58 #endif
59 
60 #if HAVE_STRING_H
61 #include <string.h>
62 #endif
63 
64 #ifndef HAVE_STRCHR
65 #define strchr index
66 #define strrchr rindex
67 #endif
68 char *strchr ();
69 char *strrchr ();
70 
71 #ifndef HAVE_STRERROR
72 extern char *strerror ___P ((int));
73 #endif
74 
75 #ifndef HAVE_MEMMOVE
76 extern void *memmove ___P ((void *, void *, size_t));
77 #endif
78 
79 #ifndef HAVE_MEMCPY
80 extern void *memcpy ___P ((void *, void *, size_t));
81 #endif
82 
83 #endif /* no STDC_HEADERS */
84 
85 #if HAVE_UNISTD_H
86 #include <unistd.h>
87 #endif
88 
89 #if HAVE_MATH_H
90 #include <math.h>
91 #else
92 extern double atan2 ___P ((double, double));
93 #endif
94 
95 #include <errno.h>
96 #include <time.h>
97 #include <assert.h>
98 #include <ctype.h>
99 
100 #if HAVE_PWD_H
101 #include <pwd.h>
102 #else
103 #include "dummypwd.h"
104 #endif
105 
106 #include "gettext.h"
107 #define _(String) gettext (String)
108 
109 #if HAVE_LC_MESSAGES
110 #include <locale.h>
111 #endif
112 
113 #ifndef HAVE_GETCWD
114 #if HAVE_GETWD
115 #define getcwd(buf, len) getwd(buf)
116 #endif /* HAVE_GETWD */
117 #endif /* not HAVE_GETCWD */
118 
119 #include "afm.h"
120 #include "strhash.h"
121 #include "xalloc.h"
122 
123 /*
124  * Types and definitions.
125  */
126 
127 #define MATCH(a, b) (strcmp (a, b) == 0)
128 
129 #define ISNUMBERDIGIT(ch) \
130   (('0' <= (ch) && (ch) <= '9') || (ch) == '.' || (ch) == '-' || (ch) == '+')
131 
132 /* Return the width of the character <ch> */
133 #define CHAR_WIDTH(ch) (font_widths[(unsigned char) (ch)])
134 
135 /* Current point y movement from line to line. */
136 #define LINESKIP (Fpt.h + baselineskip)
137 
138 
139 /* Constants for output files. */
140 #define OUTPUT_FILE_NONE   NULL
141 #define OUTPUT_FILE_STDOUT ((char *) 1)
142 
143 /* Underlay styles. */
144 #define UL_STYLE_OUTLINE 	0
145 #define UL_STYLE_FILLED		1
146 
147 struct media_entry_st
148 {
149   struct media_entry_st *next;
150   char *name;
151   int w;
152   int h;
153   int llx;
154   int lly;
155   int urx;
156   int ury;
157 };
158 
159 typedef struct media_entry_st MediaEntry;
160 
161 typedef enum
162 {
163   HDR_NONE,
164   HDR_SIMPLE,
165   HDR_FANCY
166 } HeaderType;
167 
168 
169 typedef enum
170 {
171   ENC_ISO_8859_1,
172   ENC_ISO_8859_2,
173   ENC_ISO_8859_3,
174   ENC_ISO_8859_4,
175   ENC_ISO_8859_5,
176   ENC_ISO_8859_7,
177   ENC_ISO_8859_9,
178   ENC_ISO_8859_10,
179   ENC_ASCII,
180   ENC_ASCII_FISE,
181   ENC_ASCII_DKNO,
182   ENC_IBMPC,
183   ENC_MAC,
184   ENC_VMS,
185   ENC_HP8,
186   ENC_KOI8,
187   ENC_PS
188 } InputEncoding;
189 
190 struct encoding_registry_st
191 {
192   char *names[3];
193   InputEncoding encoding;
194   int nl;
195   int bs;
196 };
197 
198 typedef struct encoding_registry_st EncodingRegistry;
199 
200 typedef enum
201 {
202   LABEL_SHORT,
203   LABEL_LONG
204 } PageLabelFormat;
205 
206 typedef enum
207 {
208   MWLS_NONE	= 0,
209   MWLS_PLUS	= 1,
210   MWLS_BOX	= 2,
211   MWLS_ARROW	= 3
212 } MarkWrappedLinesStyle;
213 
214 typedef enum
215 {
216   NPF_SPACE,
217   NPF_QUESTIONMARK,
218   NPF_CARET,
219   NPF_OCTAL
220 } NonPrintableFormat;
221 
222 typedef enum
223 {
224   FORMFEED_COLUMN,
225   FORMFEED_PAGE,
226   FORMFEED_HCOLUMN
227 } FormFeedType;
228 
229 typedef enum
230 {
231   LE_TRUNCATE,
232   LE_CHAR_WRAP,
233   LE_WORD_WRAP
234 } LineEndType;
235 
236 struct buffer_st
237 {
238   char *data;
239   size_t allocated;
240   size_t len;
241 };
242 
243 typedef struct buffer_st Buffer;
244 
245 struct file_lookup_ctx_st
246 {
247   /* The name of the file to lookup. */
248   char *name;
249 
250   /* The suffix of the file.  This string is appended to <name>. */
251   char *suffix;
252 
253   /* Buffer to which the name of the file is constructed.  If the
254      file_lookup() returns 1, the name of the file is here.  The
255      caller of the file_lookup() must allocate this buffer. */
256   Buffer *fullname;
257 };
258 
259 typedef struct file_lookup_ctx_st FileLookupCtx;
260 
261 typedef int (*PathWalkProc) ___P ((char *path, void *context));
262 
263 
264 struct input_stream_st
265 {
266   int is_pipe;			/* Is <fp> opened to pipe? */
267   FILE *fp;
268   unsigned char buf[4096];
269   unsigned int data_in_buf;
270   unsigned int bufpos;
271   unsigned int nreads;
272   unsigned char *unget_ch;
273   unsigned int unget_pos;
274   unsigned int unget_alloc;
275 };
276 
277 typedef struct input_stream_st InputStream;
278 
279 
280 struct page_range_st
281 {
282   struct page_range_st *next;
283   int odd;
284   int even;
285   unsigned int start;
286   unsigned int end;
287 };
288 
289 typedef struct page_range_st PageRange;
290 
291 struct font_point_st
292 {
293   double w;			/* width */
294   double h;			/* height */
295 };
296 
297 typedef struct font_point_st FontPoint;
298 
299 struct color_st
300 {
301   float r;
302   float g;
303   float b;
304 };
305 
306 typedef struct color_st Color;
307 
308 struct cached_font_info_st
309 {
310   double font_widths[256];
311   char font_ctype[256];
312   AFMBoolean font_is_fixed;
313   AFMNumber font_bbox_lly;
314 };
315 
316 typedef struct cached_font_info_st CachedFontInfo;
317 
318 
319 /*
320  * Global variables.
321  */
322 
323 extern char *program;
324 extern FILE *ofp;
325 extern char *date_string;
326 extern struct tm run_tm;
327 extern struct tm mod_tm;
328 extern struct passwd *passwd;
329 extern char *libpath;
330 extern char *afm_path;
331 extern MediaEntry *media_names;
332 extern MediaEntry *media;
333 extern char *no_job_header_switch;
334 extern char *output_first_line;
335 extern char *queue_param;
336 extern char *spooler_command;
337 extern int nl;
338 extern int bs;
339 extern unsigned int current_pagenum;
340 extern unsigned int input_filenum;
341 extern unsigned int current_file_linenum;
342 extern char *fname;
343 
344 /* Statistics. */
345 extern int total_pages;
346 extern int num_truncated_lines;
347 extern int num_missing_chars;
348 extern int missing_chars[];
349 extern int num_non_printable_chars;
350 extern int non_printable_chars[];
351 
352 /* Dimensions that are used during PostScript generation. */
353 extern int d_page_w;
354 extern int d_page_h;
355 extern int d_header_w;
356 extern int d_header_h;
357 extern int d_footer_h;
358 extern int d_output_w;
359 extern int d_output_h;
360 extern int d_output_x_margin;
361 extern int d_output_y_margin;
362 extern unsigned int nup_xpad;
363 extern unsigned int nup_ypad;
364 
365 /* Document needed resources. */
366 extern StringHashPtr res_fonts;
367 
368 /* Fonts to download. */
369 extern StringHashPtr download_fonts;
370 
371 /* Additional key-value pairs, passed to the generated PostScript code. */
372 extern StringHashPtr pagedevice;
373 extern StringHashPtr statusdict;
374 
375 /* User defined strings. */
376 extern StringHashPtr user_strings;
377 
378 /* Cache for AFM files. */
379 extern StringHashPtr afm_cache;
380 extern StringHashPtr afm_info_cache;
381 
382 /* AFM library handle. */
383 extern AFMHandle afm;
384 
385 /* Fonts. */
386 extern char *HFname;
387 extern FontPoint HFpt;
388 extern char *Fname;
389 extern FontPoint Fpt;
390 extern FontPoint default_Fpt;
391 extern char *default_Fname;
392 extern InputEncoding default_Fencoding;
393 
394 extern double font_widths[];
395 extern char font_ctype[];
396 extern int font_is_fixed;
397 extern double font_bbox_lly;
398 
399 /* Known input encodings. */
400 extern EncodingRegistry encodings[];
401 
402 /* Options. */
403 
404 extern char *printer;
405 extern int verbose;
406 extern int num_copies;
407 extern char *title;
408 extern int num_columns;
409 extern LineEndType line_end;
410 extern int quiet;
411 extern int landscape;
412 extern HeaderType header;
413 extern char *fancy_header_name;
414 extern char *fancy_header_default;
415 extern double line_indent;
416 extern char *page_header;
417 extern char *page_footer;
418 extern char *output_file;
419 extern unsigned int lines_per_page;
420 extern InputEncoding encoding;
421 extern char *media_name;
422 extern char *encoding_name;
423 extern int special_escapes;
424 extern int escape_char;
425 extern int default_escape_char;
426 extern int tabsize;
427 extern double baselineskip;
428 extern FontPoint ul_ptsize;
429 extern double ul_gray;
430 extern char *ul_font;
431 extern char *underlay;
432 extern char *ul_position;
433 extern double ul_x;
434 extern double ul_y;
435 extern double ul_angle;
436 extern unsigned int ul_style;
437 extern char *ul_style_str;
438 extern int ul_position_p;
439 extern int ul_angle_p;
440 extern PageLabelFormat page_label;
441 extern char *page_label_format;
442 extern int pass_through;
443 extern int line_numbers;
444 extern unsigned int start_line_number;
445 extern int interpret_formfeed;
446 extern NonPrintableFormat non_printable_format;
447 extern MarkWrappedLinesStyle mark_wrapped_lines_style;
448 extern char *mark_wrapped_lines_style_name;
449 extern char *npf_name;
450 extern int clean_7bit;
451 extern int append_ctrl_D;
452 extern unsigned int highlight_bars;
453 extern double highlight_bar_gray;
454 extern int page_prefeed;
455 extern PageRange *page_ranges;
456 extern int borders;
457 extern double line_highlight_gray;
458 extern double bggray;
459 extern int accept_composites;
460 extern FormFeedType formfeed_type;
461 extern char *input_filter_stdin;
462 extern int toc;
463 extern FILE *toc_fp;
464 extern char *toc_fmt_string;
465 extern unsigned int file_align;
466 extern int slicing;
467 extern unsigned int slice;
468 
469 extern char *states_binary;
470 extern int states_color;
471 extern char *states_config_file;
472 extern char *states_highlight_style;
473 extern char *states_path;
474 
475 extern unsigned int nup;
476 extern unsigned int nup_rows;
477 extern unsigned int nup_columns;
478 extern int nup_landscape;
479 extern unsigned int nup_width;
480 extern unsigned int nup_height;
481 extern double nup_scale;
482 extern int nup_columnwise;
483 extern char *output_language;
484 extern int output_language_pass_through;
485 extern int generate_PageSize;
486 extern double horizontal_column_height;
487 extern unsigned int pslevel;
488 extern int rotate_even_pages;
489 extern int swap_even_page_margins;
490 extern int continuous_page_numbers;
491 
492 
493 /*
494  * Prototypes for global functions.
495  */
496 
497 /* Print message if <verbose> is >= <verbose_level>. */
498 #define MESSAGE(verbose_level, body)		\
499   do {						\
500     if (!quiet && verbose >= (verbose_level))	\
501       fprintf body;				\
502   } while (0)
503 
504 /* Report continuable error. */
505 #define ERROR(body)			\
506   do {					\
507     fprintf (stderr, "%s: ", program);	\
508     fprintf body;			\
509     fprintf (stderr, "\n");		\
510     fflush (stderr);			\
511   } while (0)
512 
513 /* Report fatal error and exit with status 1.  Function never returns. */
514 #define FATAL(body)			\
515   do {					\
516     fprintf (stderr, "%s: ", program);	\
517     fprintf body;			\
518     fprintf (stderr, "\n");		\
519     fflush (stderr);			\
520     exit (1);				\
521   } while (0)
522 
523 /*
524  * Read config file <path, name>.  Returns bool.  If function fails, error
525  * is found from errno.
526  */
527 int read_config ___P ((char *path, char *name));
528 
529 /* Print PostScript header to our output stream. */
530 void dump_ps_header ___P ((void));
531 
532 /* Print PostScript trailer to our output stream. */
533 void dump_ps_trailer ___P ((void));
534 
535 /*
536  * Open InputStream to <fp> or <fname>.  If <input_filter> is given
537  * it is used to pre-filter the incoming data stream.  Function returns
538  * 1 if stream could be opened or 0 otherwise.
539  */
540 int is_open ___P ((InputStream *is, FILE *fp, char *fname,
541 		   char *input_filter));
542 
543 /* Close InputStream <is>. */
544 void is_close ___P ((InputStream *is));
545 
546 /*
547  * Read next character from the InputStream <is>.  Returns EOF if
548  * EOF was reached.
549  */
550 int is_getc ___P ((InputStream *is));
551 
552 /*
553  * Put character <ch> back to the InputStream <is>.  Function returns EOF
554  * if character couldn't be unget.
555  */
556 int is_ungetc ___P ((int ch, InputStream *is));
557 
558 
559 void buffer_init ___P ((Buffer *buffer));
560 
561 void buffer_uninit ___P ((Buffer *buffer));
562 
563 Buffer *buffer_alloc ();
564 
565 void buffer_free ___P ((Buffer *buffer));
566 
567 void buffer_append ___P ((Buffer *buffer, const char *data));
568 
569 void buffer_append_len ___P ((Buffer *buffer, const char *data, size_t len));
570 
571 char *buffer_copy ___P ((Buffer *buffer));
572 
573 void buffer_clear ___P ((Buffer *buffer));
574 
575 char *buffer_ptr ___P ((Buffer *buffer));
576 
577 size_t buffer_len ___P ((Buffer *buffer));
578 
579 
580 /*
581  * Process single input file <fp>.  File's name is given in <fname> and
582  * it is used to print headers.  The argument <is_toc> specifies whether
583  * the file is a table of contents file or not.
584  */
585 void process_file ___P ((char *fname, InputStream *fp, int is_toc));
586 
587 /* Add a new media to the list of known media. */
588 void add_media ___P ((char *name, int w, int h, int llx, int lly, int urx,
589 		      int ury));
590 
591 /* Print a listing of missing characters. */
592 void do_list_missing_characters ___P ((int *array));
593 
594 /*
595  * Check if file <name, suffix> exists.  Returns bool.  If function fails
596  * error can be found from errno.
597  */
598 int file_existsp ___P ((char *name, char *suffix));
599 
600 /*
601  * Paste file <name, suffix> to output stream.  Returns bool. If
602  * function fails, error can be found from errno.
603  */
604 int paste_file ___P ((char *name, char *suffix));
605 
606 /*
607  * Do tilde substitution for filename <fname>.  The function returns a
608  * xmalloc()ated result that must be freed by the caller.
609  */
610 char *tilde_subst ___P ((char *fname));
611 
612 /*
613  * Parse one float dimension from string <string>.  If <units> is true,
614  * then number can be followed by an optional unit specifier.  If
615  * <horizontal> is true, then dimension is horizontal, otherwise it
616  * is vertical.
617  */
618 double parse_float ___P ((char *string, int units, int horizontal));
619 
620 /*
621  * Parse font spec <spec> and return font's name, size, and encoding
622  * in variables <name_return>, <size_return>, and <encoding_return>.
623  * Returns 1 if <spec> was a valid font spec or 0 otherwise.  Returned
624  * name <name_return> is allocated with xcalloc() and must be freed by
625  * caller.
626  */
627 int parse_font_spec ___P ((char *spec, char **name_return,
628 			   FontPoint *size_return,
629 			   InputEncoding *encoding_return));
630 
631 /*
632  * Read body font's character widths and character codes from AFM files.
633  */
634 void read_font_info ___P ((void));
635 
636 /*
637  * Try to download font <name>.
638  */
639 void download_font ___P ((char *name));
640 
641 /*
642  * Escape all PostScript string's special characters from string <string>.
643  * Returns a xmalloc()ated result.
644  */
645 char *escape_string ___P ((char *string));
646 
647 /*
648  * Expand user escapes from string <string>.  Returns a xmalloc()ated
649  * result.
650  */
651 char *format_user_string ___P ((char *context_name, char *string));
652 
653 /*
654  * Parses key-value pair <kv> and inserts/deletes key from <set>.
655  */
656 void parse_key_value_pair ___P ((StringHashPtr set, char *kv));
657 
658 /*
659  * Count how many non-empty items there are in the key-value set <set>.
660  */
661 int count_key_value_set ___P ((StringHashPtr set));
662 
663 /*
664  * Walk through path <path> and call <proc> once for each of its
665  * components.  Function returns 0 if all components were accessed.
666  * Callback <proc> can interrupt walking by returning a non zero
667  * return value.  In that case value is returned as the return value
668  * of the pathwalk().
669  */
670 int pathwalk ___P ((char *path, PathWalkProc proc, void *context));
671 
672 /* Lookup file from path.  <context> must point to FileLookupCtx. */
673 int file_lookup ___P ((char *path, void *context));
674 
675 
676 /*
677  * Portable printer interface.
678  */
679 
680 /*
681  * Open and initialize printer <cmd>, <options>, <queue_param> and
682  * <printer_name>.  Function returns a FILE pointer to which enscript
683  * can generate its PostScript output or NULL if printer
684  * initialization failed.  Command can store its context information
685  * to variable <context_return> wich is passed as an argument to the
686  * printer_close() function.
687  */
688 FILE *printer_open ___P ((char *cmd, char *options, char *queue_param,
689 			  char *printer_name, void **context_return));
690 
691 /*
692  * Flush all pending output to printer <context> and close it.
693  */
694 void printer_close ___P ((void *context));
695 
696 /*
697  * Escape filenames for shell usage
698  */
699 char *shell_escape ___P ((const char *fn));
700 
701 #endif /* not GSINT_H */
702