home *** CD-ROM | disk | FTP | other *** search
- /*
- * Filter that translates troff CAT output into commands for
- * an HP LaserJet II printer with the K font cartridge.
- * Ideally troff should be used with special width tables,
- * however, the standard CAT tables produce a readable output.
- *
- * Note that the K font cartridge only allows point sizes 8 and 10.
- * A possible fix would be to use the Z font cartridge or to
- * implement downloadable fonts.
- */
- #include <stdio.h>
-
- /*#define DEBUG /* Debug option */
- #define COMPRESS /* Compress text horizontally 5% */
- #define BERKELEY_HACK /* Codes 0116/0117 are not tilt */
- #define LINES (11*432) /* #CAT-lines on a page */
-
- /* Convert CAT units to LaserJet units and set first page offset (CAT units) */
-
- #define SCALE_X(n) ((300*n)/432)
- #ifdef COMPRESS
- # define SCALE_Y(n) ((286.36*n)/432+75) /* 10.5", 0.25" margin */
- # define SKIP 348 /* Empirical */
- #else
- # define SCALE_Y(n) ((300*n)/432) /* 11", no margin */
- # define SKIP 240 /* Empirical */
- #endif
-
- /* Some escape codes for LaserJet */
-
- #define INIT "\033E\033&l0O\033(0U\033(s1p10v0s0b5T"
- #define EXIT "\033E\033&k2G"
- #define X_POS(x) "\033*p%dX",x /* Left to right */
- #define XY_POS(x,y) "\033*p%dx%dY",x,y /* Top to bottom */
- #define FORM_FEED "\033&l1H"
- #define POINT_SIZE(n) "\033(s%dV",n
- #define ITALIC_OFF "\033(s0S"
- #define ITALIC_ON "\033(s1S"
- #define BOLD_OFF "\033(s0B"
- #define BOLD_ON "\033(s3B"
-
- static char *prog_name;
-
- /* State of CAT, escape is horizontal motion, lead is vertical motion */
-
- static char upper_rail = 0;
- static char upper_mag = 0;
- static char tilt_up = 0;
- static char upper_font = 0;
- static char escape_backward = 0;
- static char lead_backward = 0;
- static char lead_magnification = 0;
-
- /* These have corresponding LaserJet variables (below) */
-
- static char cat_font = 2;
- static char cat_ps = 10;
- static int cat_col = 0;
- static int cat_row = -SKIP;
-
- /* State of LaserJet */
-
- static char hp_char_set = 0; /* Values 0 through 5 are allowed */
- static char page_not_blank = 0; /* Flag */
-
- /* These have corresponding CAT variables (above) */
-
- static char hp_font = 2;
- static char hp_ps = 10;
- static int hp_col = -100000; /* These are in LaserJet units */
- static int hp_row = -100000; /* 300 per inch */
-
- static struct char_table {
- char c; /* LaserJet character */
- char char_set; /* LaserJet character set */
- char x_shift; /* Horizontal ajustment */
- char y_shift; /* Vertical ajustment */
- };
-
- /*
- * The next two char_table structures define the mapping of a
- * CAT character position to the corresponding LaserJet character.
- * Note the following restrictions in the K font point sizes:
- *
- * Style Character Set #
- * 0 1 2 3 4 5
- * Roman 8,10 8,10 8,10 8,10 10 10
- * Italic 10 10 * * * *
- * Bold 10 10 * * * *
- *
- * The x_shift, y_shift fields are for fine tuning of the final
- * character position. These will be scaled with the point size
- * and should be given in units 3000 to the inch for point size 10.
- * The coordinate directions are:
- * x_shift: from left to right
- * y_shift: from top to bottom.
- */
-
- static struct char_table standard_table [110] = {
- '\0', 0, 0, 0, /* null */
- 'h', 0, 0, 0, /* h */
- 't', 0, 0, 0, /* t */
- 'n', 0, 0, 0, /* n */
- 'm', 0, 0, 0, /* m */
- 'l', 0, 0, 0, /* l */
- 'i', 0, 0, 0, /* i */
- 'z', 0, 0, 0, /* z */
- 's', 0, 0, 0, /* s */
- 'd', 0, 0, 0, /* d */
- 'b', 0, 0, 0, /* b */
- 'x', 0, 0, 0, /* x */
- 'f', 0, 0, 0, /* f */
- 'j', 0, 0, 0, /* j */
- 'u', 0, 0, 0, /* u */
- 'k', 0, 0, 0, /* k */
- '\0', 0, 0, 0, /* null */
- 'p', 0, 0, 0, /* p */
- 'v', 1, 0, 0, /* 3/4 em dash */
- ';', 0, 0, 0, /* ; */
- '\0', 0, 0, 0, /* null */
- 'a', 0, 0, 0, /* a */
- '_', 0, 0, -85, /* rule */
- 'c', 0, 0, 0, /* c */
- '`', 0, 0, 0, /* open quote */
- 'e', 0, 0, 0, /* e */
- '\'', 0, 0, 0, /* close quote */
- 'o', 0, 0, 0, /* o */
- 'w', 1, 0, 0, /* 1/4 */
- 'r', 0, 0, 0, /* r */
- 'x', 1, 0, 0, /* 1/2 */
- 'v', 0, 0, 0, /* v */
- '-', 0, 0, 0, /* hyphen */
- 'w', 0, 0, 0, /* w */
- 'q', 0, 0, 0, /* q */
- '/', 0, 0, 0, /* / */
- '.', 0, 0, 0, /* . */
- 'g', 0, 0, 0, /* g */
- '\0', 0, 0, 0, /* 3/4 */
- ',', 0, 0, 0, /* , */
- '&', 0, 0, 0, /* & */
- 'y', 0, 0, 0, /* y */
- '\0', 0, 0, 0, /* null */
- '%', 0, 0, 0, /* % */
- '\0', 0, 0, 0, /* null */
- 'Q', 0, 0, 0, /* Q */
- 'T', 0, 0, 0, /* T */
- 'O', 0, 0, 0, /* O */
- 'H', 0, 0, 0, /* H */
- 'N', 0, 0, 0, /* N */
- 'M', 0, 0, 0, /* M */
- 'L', 0, 0, 0, /* L */
- 'R', 0, 0, 0, /* R */
- 'G', 0, 0, 0, /* G */
- 'I', 0, 0, 0, /* I */
- 'P', 0, 0, 0, /* P */
- 'C', 0, 0, 0, /* C */
- 'V', 0, 0, 0, /* V */
- 'E', 0, 0, 0, /* E */
- 'Z', 0, 0, 0, /* Z */
- 'D', 0, 0, 0, /* D */
- 'B', 0, 0, 0, /* B */
- 'S', 0, 0, 0, /* S */
- 'Y', 0, 0, 0, /* Y */
- '\0', 0, 0, 0, /* null */
- 'F', 0, 0, 0, /* F */
- 'X', 0, 0, 0, /* X */
- 'A', 0, 0, 0, /* A */
- 'W', 0, 0, 0, /* W */
- 'J', 0, 0, 0, /* J */
- 'U', 0, 0, 0, /* U */
- 'K', 0, 0, 0, /* K */
- '0', 0, 0, 0, /* 0 */
- '1', 0, 0, 0, /* 1 */
- '2', 0, 0, 0, /* 2 */
- '3', 0, 0, 0, /* 3 */
- '4', 0, 0, 0, /* 4 */
- '5', 0, 0, 0, /* 5 */
- '6', 0, 0, 0, /* 6 */
- '7', 0, 0, 0, /* 7 */
- '8', 0, 0, 0, /* 8 */
- '9', 0, 0, 0, /* 9 */
- '*', 0, 0, 0, /* * */
- '-', 0, 0, 0, /* curent font minus */
- '\0', 0, 0, 0, /* fi */
- '\0', 0, 0, 0, /* fl */
- '\0', 0, 0, 0, /* ff */
- '?', 1, 0, 0, /* cent sign */
- '\0', 0, 0, 0, /* ffl */
- '\0', 0, 0, 0, /* ffi */
- '(', 0, 0, 0, /* ( */
- ')', 0, 0, 0, /* ) */
- '[', 0, 0, 0, /* [ */
- ']', 0, 0, 0, /* ] */
- '3', 1, 0, 0, /* degree */
- 'N', 3, 0, 0, /* dagger */
- '=', 0, 0, 0, /* = */
- ',', 5, 0, 0, /* registered */
- ':', 0, 0, 0, /* : */
- '+', 0, 0, 0, /* + */
- '\0', 0, 0, 0, /* null */
- '!', 0, 0, 0, /* ! */
- 'K', 3, 0, 0, /* bullet */
- '?', 0, 0, 0, /* ? */
- '\'', 2, 0, 0, /* foot mark */
- '|', 0, 0, 0, /* | */
- '\0', 0, 0, 0, /* null */
- '-', 5, 0, 0, /* copyright */
- 'l', 5, 0, 0, /* square */
- '$', 0, 0, 0 /* $ */
- };
-
- static struct char_table special_table [110] = {
- '\0', 2, 0, 0, /* null */
- 'w', 2, 0, 0, /* psi */
- 'h', 2, 0, 0, /* theta */
- 'm', 2, 0, 0, /* nu */
- 'l', 2, 0, 0, /* mu */
- 'k', 2, 0, 0, /* lambda */
- 'i', 2, 0, 0, /* iota */
- 'f', 2, 0, 0, /* zeta */
- 'r', 2, 0, 0, /* sigma */
- 'd', 2, 0, 0, /* delta */
- 'b', 2, 0, 0, /* beta */
- 'n', 2, 0, 0, /* xi */
- 'g', 2, 0, 0, /* eta */
- 'u', 2, 0, 0, /* phi */
- 't', 2, 0, 0, /* upsilon */
- 'j', 2, 0, 0, /* kappa */
- '\0', 2, 0, 0, /* null */
- 'p', 2, 0, 0, /* pi */
- '@', 0, 0, 0, /* @ */
- '#', 3, 0, 0, /* down arrow */
- '\0', 2, 0, 0, /* null */
- 'a', 2, 0, 0, /* alpha */
- '|', 0, 0, 0, /* or */
- 'v', 2, 0, 0, /* chi */
- '"', 0, 0, 0, /* " */
- 'e', 2, 0, 0, /* epsilon */
- '=', 2, 0, 0, /* math equals */
- 'o', 2, 0, 0, /* omicron */
- '$', 3, 0, 0, /* left arrow */
- 'q', 2, 0, 0, /* rho */
- '!', 3, 0, 0, /* up arrow */
- 's', 2, 0, 0, /* tau */
- '_', 0, 0, 0, /* underrule */
- '\\', 0, 0, 0, /* \ */
- 'W', 2, 0, 0, /* Psi */
- 'H', 5, 0, 0, /* bell system sign */
- '$', 2, 0, 0, /* infinity */
- 'c', 2, 0, 0, /* gamma */
- '?', 3, 0, 0, /* improper superset */
- '&', 2, 0, 0, /* proportional to */
- '&', 3, 0, 0, /* right hand */
- 'x', 2, 0, 0, /* omega */
- '\0', 2, 0, 0, /* null */
- 'Y', 2, 0, 0, /* gradient */
- '\0', 2, 0, 0, /* null */
- 'U', 2, 0, 0, /* Phi */
- 'H', 2, 0, 0, /* Theta */
- 'X', 2, 0, 0, /* Omega */
- '5', 3, 0, 0, /* cup (union) */
- '0', 3, 0, 0, /* root en extender */
- '[', 2, 0, 0, /* terminal sigma */
- 'K', 2, 0, 0, /* Lambda */
- '-', 2, 0, 0, /* math minus */
- 'C', 2, 0, 0, /* Gamma */
- 'U', 3, 0, 0, /* integral sign */
- 'P', 2, 0, 0, /* Pi */
- ':', 3, 0, 0, /* subset of */
- ';', 3, 0, 0, /* superset of */
- '~', 0, 0, 0, /* approximates */
- 'Z', 2, 0, 0, /* partial derivative */
- 'D', 2, 0, 0, /* Delta */
- '!', 2, 0, 0, /* square root */
- 'R', 2, 0, 0, /* Sigma */
- '?', 2, 0, 0, /* approx = */
- '\0', 2, 0, 0, /* null */
- '>', 0, 0, 0, /* > */
- 'N', 2, 0, 0, /* Xi */
- '<', 0, 0, 0, /* < */
- '/', 0, 0, 0, /* slash (matching backslash) */
- '6', 3, 0, 0, /* cap (intersection) */
- 'T', 2, 0, 0, /* Upsilon */
- 'H', 3, 0, 0, /* not */
- 'p', 3, 0, 0, /* right ceiling */
- 'b', 3, 0, 0, /* left top */
- 'v', 3, 0, 0, /* bold vertical (used with floor...) */
- 'c', 3, 0, 0, /* left center of big curly bracket */
- 'd', 3, 0, 0, /* left bottom */
- 'r', 3, 0, 0, /* right top */
- 's', 3, 0, 0, /* right center of big curly bracket */
- 't', 3, 0, 0, /* right bottom */
- 'q', 3, 0, 0, /* right floor */
- 'a', 3, 0, 0, /* left floor */
- '`', 3, 0, 0, /* left ceiling */
- '*', 2, 0, 0, /* multiply */
- '%', 2, 0, 0, /* divide */
- '~', 3, 0, 0, /* plus-minus */
- '\\', 2, 0, 0, /* <= */
- '^', 2, 0, 0, /* >= */
- '}', 2, 0, 0, /* identically equal */
- ']', 2, 0, 0, /* not equal */
- '{', 0, 0, 0, /* { */
- '}', 0, 0, 0, /* } */
- '(', 1, 0, 0, /* acute accent */
- ')', 1, 0, 0, /* grave accent */
- '*', 1, 0, 0, /* ^ */
- '#', 0, 0, 0, /* # */
- '(', 3, 0, 0, /* left hand */
- '7', 3, 0, 0, /* member of */
- ',', 1, 0, 0, /* ~ */
- 'X', 3, 0, 0, /* empty set */
- '\0', 2, 0, 0, /* null */
- 'O', 3, 0, 0, /* double dagger */
- 'v', 3, 0, 0, /* box vertical rule */
- '*', 0, 0, 0, /* math star */
- '>', 3, 0, 0, /* improper subset */
- 'M', 3, 0, 0, /* circle */
- '\0', 2, 0, 0, /* null */
- '+', 2, 0, 0, /* math plus */
- '"', 3, 0, 0, /* right arrow */
- '=', 1, 0, 0 /* section */
- };
-
- main (argc, argv)
- int argc;
- char **argv;
- {
- prog_name = *argv;
-
- printf (INIT);
- read_cat ();
- printf (EXIT);
- }
-
- /*
- * Read end interpret CAT codes
- */
- read_cat ()
- {
- register int c;
-
- while ((c = getchar ()) != EOF) {
- if (c & 0200)
- escape ((~c) & 0177);
- else if (c < 0100)
- flash (c);
- else if ((c & 0340) == 0140)
- lead ((~c) & 037);
- else if ((c & 0360) == 0120)
- change_point_size (c & 017);
- else if ((c & 0360) == 0100)
- control (c & 017);
- else
- fprintf (stderr, "%s: Illegal CAT code: 0%o\n", prog_name, c);
- }
- }
-
- /*
- * Horizontal motion
- */
- escape (c)
- int c;
- {
- if (escape_backward)
- cat_col -= c;
- else
- cat_col += c;
- }
-
- /*
- * Print character
- */
- flash (c)
- int c;
- {
- if (upper_font)
- c += 64;
-
- #ifdef DEBUG
- fprintf (stderr, "Flash char %d on font %d, ", c, cat_font);
- #endif
-
- if (cat_font <= 7)
- hp_print_char (standard_table [c]);
- else
- hp_print_char (special_table [c]);
-
- page_not_blank = 1;
- }
-
- /*
- * Vertical motion
- */
- lead (c)
- int c;
- {
- if (lead_magnification)
- c <<= 6;
- lead_magnification = 0;
-
- c *= 3;
-
- if (lead_backward)
- cat_row -= c;
- else
- cat_row += c;
-
- if (cat_row >= LINES) {
- hp_form_feed ();
- cat_row -= LINES;
- }
- }
-
- /*
- * Interpret change-point-size code
- */
- change_point_size (c)
- int c;
- {
- static int c_last = 2;
- static char point_size_table [15] =
- {7, 8, 10, 11, 12, 14, 18, 9, 6, 16, 20, 22, 24, 28, 36};
-
- /* Adjust escape */
-
- if (c_last <= 8 && c > 8) /* Single to double */
- cat_col -= 55;
- else if (c_last > 8 && c <= 8) /* Double to single */
- cat_col += 55;
- c_last = c;
-
- /* Interpret new point size */
-
- if (c >= 0 && c <= 016)
- cat_ps = point_size_table [c];
- else
- fprintf (stderr, "%s: Illegal CAT point size: 0%o\n", prog_name, c);
-
- if (hp_ps != cat_ps)
- hp_change_point_size ();
-
- #ifdef DEBUG
- fprintf (stderr, "New point_size %d\n", cat_ps);
- #endif
- }
-
- /*
- * CAT control codes: init and font changes
- */
- control (c)
- int c;
- {
- switch (c) {
- case 0: /* Initialize */
- upper_rail = 0;
- upper_mag = 0;
- tilt_up = 0;
- upper_font = 0;
- escape_backward = 0;
- lead_backward = 0;
- lead_magnification = 0;
- break;
- case 01: /* Font change */
- upper_rail = 0;
- break;
- case 02: /* Font change */
- upper_rail = 1;
- break;
- case 03: /* Font change */
- upper_mag = 1;
- break;
- case 04: /* Font change */
- upper_mag = 0;
- break;
- case 05: /* Change font half */
- upper_font = 0;
- break;
- case 06: /* Change font half */
- upper_font = 1;
- break;
- case 07: /* Change horizontal direction */
- escape_backward = 0;
- break;
- case 010: /* Change horizontal direction */
- escape_backward = 1;
- break;
- case 011: /* Stop code */
- break;
- case 012: /* Change vertical direction */
- lead_backward = 0;
- break;
- case 014: /* Change vertical direction */
- lead_backward = 1;
- break;
- #ifdef BERKELEY_HACK
- case 016: /* Magnify next lead 64 times */
- lead_magnification = 1;
- break;
- #else
- case 016: /* Font change */
- tilt_up = 1;
- break;
- case 017: /* Font change */
- tilt_up = 0;
- break;
- #endif
- default:
- fprintf (stderr, "%s: Illegal CAT control code: 0%o\n", prog_name, c);
- break;
- }
-
- cat_font = 2 - tilt_up + (upper_rail << 1) + (upper_mag << 2);
-
- if (hp_font != cat_font)
- hp_change_font ();
-
- #ifdef DEBUG
- fprintf (stderr, "Control code: 0%o\n", c);
- #endif
- }
-
- hp_print_char (c)
- struct char_table c;
- {
- int x, y;
-
- if (hp_char_set != c.char_set)
- hp_change_char_set (c.char_set);
-
- /* Convert to LaserJet coordinates (50 is for rounding) */
-
- if (c.x_shift < 0)
- x = SCALE_X(cat_col) + (c.x_shift * hp_ps - 50) / 100;
- else
- x = SCALE_X(cat_col) + (c.x_shift * hp_ps + 50) / 100;
- if (c.y_shift < 0)
- y = SCALE_Y(cat_row) + (c.y_shift * hp_ps - 50) / 100;
- else
- y = SCALE_Y(cat_row) + (c.y_shift * hp_ps + 50) / 100;
-
- /* Position LaserJet (cannot trust hp_col -- see below) */
-
- if (hp_row != y)
- printf (XY_POS(x,y));
- else
- printf (X_POS(x));
-
- putchar (c.c);
-
- hp_col = x; /* Wrong by a character width */
- hp_row = y;
-
- #ifdef DEBUG
- fprintf (stderr, "col=%d, row=%d, ", x, y);
- fprintf (stderr, "hp_c = %c(%d), c_set=%d\n", c.c, c.c, c.char_set);
- #endif
- }
-
- hp_change_char_set (char_set)
- char char_set;
- {
- switch (char_set) {
- case 0: /* USASCII */
- printf ("\033(0U");
- break;
- case 1: /* Roman Extension */
- printf ("\033(0E");
- break;
- case 2: /* Math 8a */
- printf ("\033(0Q");
- break;
- case 3: /* Math 8b */
- printf ("\033(1Q");
- break;
- case 4: /* Math 7 */
- printf ("\033(0A");
- break;
- case 5: /* PiFonta */
- printf ("\033(2Q");
- break;
- default:
- fprintf (stderr, "%s: Illegal HP character set: %d\n", prog_name, char_set);
- break;
- }
- hp_char_set = char_set;
- }
-
- hp_form_feed ()
- {
- if (page_not_blank)
- printf (FORM_FEED);
-
- page_not_blank = 0;
- }
-
- hp_change_point_size ()
- {
-
- /*
- * Note that no checking is done to see if the asked for
- * point size is available.
- */
-
- printf (POINT_SIZE(cat_ps));
-
- hp_ps = cat_ps;
- }
-
- hp_change_font ()
- {
- switch (cat_font) {
- case 1: /* Standard */
- case 2:
- case 7:
- case 8:
- printf (BOLD_OFF);
- printf (ITALIC_OFF);
- break;
- case 3: /* Italic */
- case 4:
- printf (BOLD_OFF);
- printf (ITALIC_ON);
- break;
- case 5: /* Bold */
- case 6:
- printf (BOLD_ON);
- printf (ITALIC_OFF);
- break;
- default:
- fprintf (stderr, "%s: Illegal HP font: %d\n", prog_name, cat_font);
- break;
- }
-
- hp_font = cat_font;
- }
-