date and time created 87/02/05 15:19:02 by slatteng
authorDave Slattengren <slatteng@ucbvax.Berkeley.EDU>
Fri, 6 Feb 1987 07:19:02 +0000 (23:19 -0800)
committerDave Slattengren <slatteng@ucbvax.Berkeley.EDU>
Fri, 6 Feb 1987 07:19:02 +0000 (23:19 -0800)
SCCS-vsn: local/ditroff/ditroff.old.okeeffe/driver/qms2ch.c 1.1

usr/src/local/ditroff/ditroff.old.okeeffe/driver/qms2ch.c [new file with mode: 0644]

diff --git a/usr/src/local/ditroff/ditroff.old.okeeffe/driver/qms2ch.c b/usr/src/local/ditroff/ditroff.old.okeeffe/driver/qms2ch.c
new file mode 100644 (file)
index 0000000..ec251f6
--- /dev/null
@@ -0,0 +1,332 @@
+/*     qms2ch.c        1.1     87/02/05
+ *
+ * Font translation for QMS-style fonts (qms' QUIC format) to character format.
+ *
+ *     Use:  qms2ch [ -b# ] fontfile [ character_list ]
+ *
+ *             Reads "fontfile" from current directory (or if not found,
+ *     from BITDIR defined below) and converts it to a character font format
+ *     editable by real people, and convertable back to QUIC format by the
+ *     ch2qms program.  The "-b" flag sets a baseline unless the font has
+ *     one itself.  Output goes to stdout.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+
+
+#define  RES           300     /* resolution, in pixels per inch */
+#define  DIRSIZ                256     /* maximum number of characters in font */
+#define  HEADER                "^PY^-^F^-^DF"
+#define  BITDIR                "/usr/lib/font/devqms/fonts"
+
+
+char   defascii[DIRSIZ];       /* list of ascii characters to print */
+char   *fontdir = BITDIR;      /* place to look for fonts */
+char   *header = HEADER;       /* string that must start each QUIC font file */
+char   filename[100];          /* input file name put here */
+char   input[100];             /* general-purpose input string */
+FILE   *FID;                   /* input file number */
+int    height;                 /* height of every character in the font */
+int    fontid;                 /* the "font number" */
+int    landscape = 0;          /* flag:  is this a landscape font? */
+int    insertion = 0;          /* flag:  is this an addition to a font? */
+int    signed = 0;             /* flag:  can this font have signed offsets? */
+int    version = 0;            /* version code */
+int    baseline = 0;           /* baseline of font (if specified) */
+int     printwidth;            /* printwidth of each character */
+                               /* variables to use when printing characters */
+int    H, W, Hoff, Woff, lbound, rbound;
+
+
+main(argc,argv)
+int argc;
+char **argv;
+{
+       register int i;
+       register int j;
+       register int k;
+       register int Hpoint;
+       register int Wpoint;
+
+
+       if (argc < 2 || argc > 4) {
+           usage:
+               error("usage: %s [ -b# ] filename [ charlist ]", *argv);
+       }
+       ++argv;
+       if (**argv == '-' && (*argv)[1]) {
+               argc--;
+               if (argv[0][1] != 'b')
+                       goto usage;
+               baseline = atoi(&(argv[0][2]));
+               argv++;
+       }
+       if (argc == 3) {
+               do
+                       defascii[argv[1][0]] = 1;
+               while (*++(argv[1]));
+       } else {
+               for (i = 0; i < DIRSIZ; i++)
+                       defascii[i] = 1;
+       }
+
+       sprintf(filename, "%s", *argv);
+       if (filename[0] != '-' || filename[1]) {
+               if ((FID = fopen(filename, "r")) == NULL) {
+                       sprintf(filename, "%s/%s", fontdir, *argv);
+                       if ((FID = fopen(filename, "r")) == NULL)
+                               error("can't find %s", *argv);
+               }
+       } else {
+               FID = stdin;
+       }
+
+       j = strlen(header);
+       (void) getnumber(j);
+       if (strncmp(input, header, j))
+               error("%s, not a QMS Font file.", filename);
+
+       (void) getnumber(6);
+       k = (int) input[0];
+       if (k == 'i' || k == 'I') {
+               fontid = atoi(input + 1);
+               (void) getnumber(1);
+               k = (int) input[0];
+       } else {
+               k = (int) input[5];
+               input[5] = 0;
+               fontid = atoi(input);
+       }
+       switch (k) {
+               case 'y': case 'Y': case 'L': case 'l':
+                       landscape = 1;
+                       break;
+
+               case 'x': case 'X': case 'P': case 'p':
+                       break;
+
+               default:
+                       error("font is not portrait or landscape");
+       }
+       version = getnumber(1);
+       (void) getnumber(4);
+       printf("fontheader\nname %s\n", input);
+       printf("version %d\n", version);
+       printf("rot %d\n", landscape ? 1 : 0);
+       printf("cadv %d\n", landscape ? 1 : 2);
+       printf("ladv %d\n", landscape ? 2 : 1);
+       height = getnumber(3);
+       printf("linesp %d.00\n", height);
+       printf("id %d\nres %d\n", fontid, RES);
+       j = getnumber(1);
+       if (isdigit(input[0])) {
+               baseline = j * 100 + getnumber(2);
+               printf("baseline %d.00\n", baseline);
+               (void) getnumber(1);
+               if (landscape)
+                   baseline = height - baseline;
+       }
+       if (input[0] != ',') {
+               signed = 1;
+               (void) getnumber(1);
+               if (input[0] != ',')
+                       error("error in header, expected \",\"");
+       }
+
+       for (;;) {      /* for each character */
+           k = getnumber(1);           /* first digit of character number */
+           if (input[0] == '^') {
+               (void) getnumber(1);
+               if (input[0] != 'G')
+                   error("expected \"G\"");
+               exit(0);
+           }
+
+           k = k * 16 + getnumber(1);  /* second digit of character number */
+           if (!defascii[k]) {
+               do
+                   i = getc(FID);
+               while (i != EOF && i != ',');
+               continue;               /* ignore characters not asked for */
+           }
+
+           printwidth = getnumber(3);
+           H = getnumber(2);
+           if (input[0] == '^') {
+               switch (input[1]) {
+                   case 'M': case 'm':
+                       break;
+                   case 'R': case 'r':
+                       break;
+               }
+               H = getnumber(3);
+           } else {
+               H = H * 10 + getnumber(1);
+           }
+           W = getnumber(3);
+           Hoff = getnumber(3);
+           if (ispunct(input[0])) {
+               if (input[0] == '-')
+                   Hoff = 10 * Hoff - getnumber(1);
+               else
+                   Hoff = 10 * Hoff + getnumber(1);
+           }
+           Woff = getnumber(3);
+           if (ispunct(input[0])) {
+               if (input[0] == '-')
+                   Woff = 10 * Woff - getnumber(1);
+               else
+                   Woff = 10 * Woff + getnumber(1);
+           }
+           printf(":%d, width = %d.00\n", k, printwidth);
+
+           if (landscape) {
+               Hpoint = -Hoff;
+               Wpoint = baseline - Woff;
+           } else {
+               Hpoint = baseline - Hoff;
+               Wpoint = -Woff;
+           }
+           if ((lbound = Wpoint) > 0) lbound = 0;
+           if ((rbound = Wpoint + 1) < W) rbound = W;
+
+           for (k = Hpoint; k < 0; k++) {
+               for (i = lbound; i < rbound; i++)
+                   printf("%c", k==Hpoint && i==Wpoint ? 'x':'.');
+               putchar ('\n');
+           }
+           for (k = 0; k < H; k++) {
+                               /* read in one "line" at a time */
+               (void) getnumber(((W + 15) / 16) * 4);
+
+               for (i = lbound; i < 0; i++)
+                   printf("%c", k==Hpoint && i==Wpoint ? 'x':'.');
+               for (i = 0; i < W; i++)
+                   printf("%c", k==Hpoint && i==Wpoint ?
+                           (fbit(i) ? 'X':'x') : fbit(i) ? '@':'.');
+               while (i < rbound) {
+                   printf("%c", k==Hpoint && i==Wpoint ? 'x':'.');
+                   i++;
+               }
+               putchar ('\n');
+           }
+           while (k <= Hpoint) {
+               for (i = lbound; i < rbound; i++)
+                   printf("%c", k==Hpoint && i==Wpoint ? 'x':'.');
+               putchar ('\n');
+               k++;
+           }
+           putchar ('\n');
+           (void) getnumber(1);
+           if (input[0] != ',')
+               error("expected \",\"");
+       }
+}
+
+
+/*----------------------------------------------------------------------------*
+ | Routine:    error (format_string, argument1, argument2.... )
+ |
+ | Results:    fprints a message to standard error, then exits with error
+ |             code 1
+ |
+ | Side Efct:  This routine does NOT return
+ *----------------------------------------------------------------------------*/
+/*VARARGS1*/
+error(string, a1, a2, a3, a4)
+char *string;
+{ 
+       fprintf(stderr, "qms2ch: ");
+       fprintf(stderr, string, a1, a2, a3, a4);
+       fprintf(stderr, "\n");
+       exit(1);
+}
+
+
+/*----------------------------------------------------------------------------*
+ | Routine:    fbit (row)
+ |
+ | Results:    returns true (non-0) or false (0) to signify whether the bit
+ |             in "row" of the current input line (hex digits) is on or off.
+ |
+ | Side Efct:  exits the program if the character in the line isn't valid hex
+ *----------------------------------------------------------------------------*/
+
+fbit(row)
+int row;
+{
+       register int piece = row & 3;
+
+       switch (input[row / 4]) {
+               case '0': return 0;
+               case '1': return (piece == 3);
+               case '2': return (piece == 2);
+               case '3': return (piece > 1);
+               case '4': return (piece == 1);
+               case '5': return (piece == 1 || piece == 3);
+               case '6': return (piece == 1 || piece == 2);
+               case '7': return (piece);
+               case '8': return (!piece);
+               case '9': return (piece == 3 || !piece);
+               case 'A': case 'a': return (piece == 2 || !piece);
+               case 'B': case 'b': return (piece != 1);
+               case 'C': case 'c': return (piece < 2);
+               case 'D': case 'd': return (piece != 2);
+               case 'E': case 'e': return (piece != 3);
+               case 'F': case 'f': return 1;
+
+               default: error("expected HEX digit");
+       }
+}
+
+
+/*----------------------------------------------------------------------------*
+ | Routine:    getnumber (digits)
+ |
+ | Results:    read a string of "digits" length from the input file "FID"
+ |             and return the decimal value of the string.  If the string
+ |             is one character long, it may be interpreted as a hex number.
+ |             In any case the null-terminated string is returned globally
+ |             to "input".
+ |
+ | Side Efct:  This routine SKIPS WHITE SPACE, and exits upon error.
+ *----------------------------------------------------------------------------*/
+
+int
+getnumber(digits)
+int digits;
+{
+       register int i;
+       register int j;
+
+       for (i = 0; i < digits; ) {
+               if ((j = getc(FID)) == EOF)
+                       error ("unexpected end of input");
+               if (!isspace(input[i] = (char) j))
+                       i++;
+       }
+       input[digits] = (char) 0;
+       if (digits > 1) {
+               return (atoi(input));
+       } else switch (input[0]) {
+               case '0': return 0;
+               case '1': return 1;
+               case '2': return 2;
+               case '3': return 3;
+               case '4': return 4;
+               case '5': return 5;
+               case '6': return 6;
+               case '7': return 7;
+               case '8': return 8;
+               case '9': return 9;
+               case 'A': case 'a': return 10;
+               case 'B': case 'b': return 11;
+               case 'C': case 'c': return 12;
+               case 'D': case 'd': return 13;
+               case 'E': case 'e': return 14;
+               case 'F': case 'f': return 15;
+
+               default: return 0;
+       }
+}