home *** CD-ROM | disk | FTP | other *** search
- #include "ansic.h"
- ID(elsieid, "@(#)tlc.c 4.1")
-
- extern int getopt();
- extern char * optarg;
- extern int optind;
-
- #ifndef BUFSIZ
- #define BUFSIZ 1024
- #endif /* !defined BUFSIZ */
-
- #ifndef MAXFILES
- #define MAXFILES 20
- #endif /* !defined MAXFILES */
-
- #ifndef NVPC
- #define NVPC 256
- #endif /* !defined NVPC */
-
- #ifndef TRUE
- #define TRUE 1
- #define FALSE 0
- #endif /* !defined TRUE */
-
- #define NPPI 72 /* Number of Points Per Inch */
- #define NCHUPI 432 /* Number of C/A/T Horizontal Units Per Inch */
- #define NCVUPI 144 /* Number of C/A/T Vertical Units Per Inch */
- #define NCWUPI NCHUPI /* Number of C/A/T Width table Units Per Inch */
- #define CWPS 6 /* C/A/T Width Value Point Size */
- #define DNIPP 11 /* Default Number of Inches Per Page */
- #define NI 256 /* Number of troff width table indices */
- #define MAXPS 36 /* Maxium Point Size */
-
- static struct {
- const char * f_fontnick;
- char * f_in; /* how to get into font */
- char * f_out; /* how to get out of font */
- } fontdata[] = {
- { "R" },
- { "I" },
- { "B" },
- { "S" }
- };
-
- #define NFONTS (sizeof fontdata / sizeof fontdata[0])
-
- #define fontisx(font, x) (fontdata[font].f_fontnick[0] == (x))
- #define fontisR(font) (fontisx(font, 'R'))
- #define fontisI(font) (fontisx(font, 'I'))
- #define fontisB(font) (fontisx(font, 'B'))
- #define fontisS(font) (fontisx(font, 'S'))
-
- /* Number of C/A/T Vertical Units Per Page */
-
- static int ncvupp = NCVUPI * DNIPP;
-
- static float lwupi; /* laser width units per inch */
- static float lwps; /* laser width point size */
- static float lcpi; /* laser characters per inch */
-
- static char * sizes; /* how to get into/out of sizes */
-
- static char * firsts[MAXPS + 1][NFONTS];
- /* for first time font and size seen */
-
- static int lowvalue;
-
- static char * lowstring;
-
- static char * hormove; /* horizontal move format */
- static char * vermove; /* vertical move format */
- static char * enddata; /* data to send when done */
- static char * newpage; /* data to send for new page */
- static char * portrait; /* to go into portrait mode */
- static char * landscape; /* to go into landscape mode */
-
- static int verunitsperinch;/* printer vertical units per inch */
-
- static int horunitsperinch;/* printer horizontal units per inch */
-
- static int leftmargin; /* unprintable left margin */
-
- /*
- ** Per-"character" data.
- */
-
- typedef struct {
- char * ssname; /* symbol set name */
- char * inset; /* how to get into symbol set */
- char * outset; /* how to get out of symbol set */
- char * data; /* character-specific data */
- int widths[NFONTS]; /* widths in various fonts */
- int lwidths[NFONTS]; /* LJ widths */
- char waschar; /* explicitly-set character */
- } item;
-
- static item items[2 * NI];
-
- static int overstruck[NI];
-
- static unsigned char * overnames[2 * NI];
-
- /*
- ** Internal functions.
- */
-
- static void LJ_cput();
- static void LJ_fdput();
- static void LJ_sput();
- static int ascends();
- static char * checkcp();
- static void * checkvp();
- static int ctoi();
- static int descends();
- static FILE * dfopen();
- static void disescape();
- static void dostrike();
- static void dowidth();
- static char * ecatalloc();
- static char * ecpyalloc();
- static void * emalloc();
- static int fiswidth();
- static char * getline();
- static char * icatalloc();
- static char * icpyalloc();
- static void ifree();
- static void * imalloc();
- static int inch();
- static void * irealloc();
- static int linematch();
- static void loadinfo();
- static void loadsub();
- static int lwtocw();
- int main();
- static const char * namefor();
- static int nametoindex();
- static int oscode();
- static int osfind();
- static int ouch();
- static const char * scheck();
- static int splitos();
- static void swift();
- static void tameexit();
- static void wild2();
- static void wild2exit();
- static void wildexit();
- static void wildline();
- static void wildrexit();
-
- /*
- ** External functions.
- */
-
- extern int catsup();
- extern const char * fti2ntn();
- extern int ntn2fti();
- extern int ntnonr();
- extern int ntnons();
-
- /*
- ** Messages and exits.
- */
-
- static const char * progname;
-
- static void
- wild2(part1, part2)
- const char * const part1;
- const char * const part2;
- {
- (void) fflush(stdout);
- /*
- ** One space after the colon matches what perror does
- ** (although your typing teacher may want a second space).
- */
- (void) fprintf(stderr, "\n%s: wild", progname);
- if (part1 != NULL && *part1 != '\0')
- (void) fprintf(stderr, " %s", part1);
- if (part2 != NULL && *part2 != '\0')
- (void) fprintf(stderr, " %s", part2);
- (void) fprintf(stderr, "\n");
- }
-
- static void
- wild2exit(string1, string2)
- const char * const string1;
- const char * const string2;
- {
- wild2(string1, string2);
- exit(EXIT_FAILURE);
- /*NOTREACHED*/
- }
-
- static void
- wildexit(string)
- const char * const string;
- {
- wild2exit(string, (char *) NULL);
- /*NOTREACHED*/
- }
-
- static void
- wildrexit(string)
- const char * const string;
- {
- wild2exit("result from", string);
- /*NOTREACHED*/
- }
-
- static void
- tameexit()
- {
- exit(EXIT_SUCCESS);
- /*NOTREACHED*/
- }
-
- /*
- ** Memory allocation.
- */
-
- #ifndef alloc_size_t
- #define alloc_size_t unsigned
- #endif /* !defined alloc_size_t */
-
- #ifndef alloc_pointer_t
- #define alloc_pointer_t char *
- #endif /* !defined alloc_pointer_t */
-
- #ifdef MAL
- #define NULLMAL(x) ((x) == NULL || (x) == MAL)
- #else /* !defined MAL */
- #define NULLMAL(x) ((x) == NULL)
- #endif /* !defined MAL */
-
- #define nonzero(n) (((n) == 0) ? 1 : (n))
-
- static void *
- imalloc(n)
- int const n;
- {
- #ifdef MAL
- char * result;
-
- result = (void *) malloc((alloc_size_t) nonzero(n));
- return NULLMAL(result) ? NULL : result;
- #else /* !defined MAL */
- return (void *) malloc((alloc_size_t) nonzero(n));
- #endif /* !defined MAL */
- }
-
- static void *
- irealloc(pointer, size)
- void * const pointer;
- int const size;
- {
- if (NULLMAL(pointer))
- return imalloc(size);
- return (void *) realloc((alloc_pointer_t) pointer,
- (alloc_size_t) nonzero(size));
- }
-
- static char *
- icatalloc(old, new)
- char * const old;
- const char * const new;
- {
- char * result;
- int oldsize;
- int newsize;
-
- newsize = NULLMAL(new) ? 0 : strlen(new);
- if (NULLMAL(old))
- oldsize = 0;
- else if (newsize == 0)
- return old;
- else oldsize = strlen(old);
- result = (char *) irealloc((void *) old, oldsize + newsize + 1);
- if (result != NULL)
- if (NULLMAL(new))
- *(result + oldsize) = '\0';
- else (void) strcpy(result + oldsize, new);
- return result;
- }
-
- static char *
- icpyalloc(string)
- const char * const string;
- {
- return icatalloc((char *) NULL, string);
- }
-
- static void
- ifree(p)
- void * const p;
- {
- if (!NULLMAL(p))
- #ifdef USG
- free((alloc_pointer_t) p);
- #endif /* defined USG */
- #ifndef USG
- (void) free((alloc_pointer_t) p);
- #endif /* !defined USG */
- }
-
- static void *
- checkvp(pointer)
- void * const pointer;
- {
- if (pointer == NULL)
- wildrexit("allocating memory");
- return pointer;
- }
-
- static char *
- checkcp(pointer)
- char * const pointer;
- {
- if (pointer == NULL)
- wildrexit("allocating memory");
- return pointer;
- }
-
- static void *
- emalloc(size)
- int const size;
- {
- return checkvp(imalloc(size));
- }
-
- static char *
- ecatalloc(old, new)
- char * const old;
- const char * const new;
- {
- return checkcp(icatalloc(old, new));
- }
-
- static char *
- ecpyalloc(string)
- const char * const string;
- {
- return checkcp(icpyalloc(string));
- }
-
- /*
- ** Check a format against a string...
- */
-
- static const char *
- scheck(string, format)
- const char * const string;
- const char * const format;
- {
- char * fbuf;
- const char * fp;
- char * tp;
- int c;
- const char * result;
- char dummy;
-
- result = "";
- if (string == NULL || format == NULL)
- return result;
- /*
- ** Check for stupid systems that let "9e" match "%f".
- ** We only do the easy cases here.
- */
- {
- int i;
-
- i = strlen(format);
- if (i >= 2 && strcmp(&format[i - 2], "%f") == 0) {
- i = strlen(string);
- if (i > 0 &&
- strchr("0123456789", string[i - 1]) == NULL)
- return result;
- }
- }
- fbuf = (char *) imalloc(2 * strlen(format) + 4);
- if (fbuf == NULL)
- return result;
- fp = format;
- tp = fbuf;
- while ((*tp++ = c = *fp++) != '\0') {
- if (c != '%')
- continue;
- if (*fp == '%') {
- *tp++ = *fp++;
- continue;
- }
- *tp++ = '*';
- if (*fp == '*')
- ++fp;
- while (isascii(*fp) && isdigit(*fp))
- *tp++ = *fp++;
- if (*fp == 'l' || *fp == 'h')
- *tp++ = *fp++;
- else if (*fp == '[')
- do {
- *tp++ = *fp++;
- } while (*fp != '\0' && *fp != ']');
- if ((*tp++ = *fp++) == '\0')
- break;
- }
- *(tp - 1) = '%';
- *tp++ = 'c';
- *tp = '\0';
- if (sscanf(string, fbuf, &dummy) != 1)
- result = format;
- ifree((void *) fbuf);
- return result;
- }
-
- /*
- ** Get [nt]roff names from a file.
- */
-
- static const char * sfilename;
- static int slinenum;
-
- static void
- oops(string)
- const char * const string;
- {
- char line[132];
-
- (void) sprintf(line, "file \"%s\", line %d: %s\n",
- ((sfilename == NULL) ? NULL : sfilename), slinenum, string);
- wildexit(line);
- }
-
- static void
- getnames(filename, names)
- const char * const filename;
- char ** const names;
- {
- FILE * fp;
- char * cp;
- char * dp;
- int i;
- int online;
- char line[132];
-
- sfilename = filename;
- slinenum = 0;
- if (names == NULL)
- oops("NULL names argument");
- if (filename == NULL)
- oops("NULL filename argument");
- if ((fp = fopen(filename, "r")) == NULL) {
- cp = ecpyalloc(filename);
- cp = ecatalloc(cp, ".M");
- fp = fopen(cp, "r");
- free(cp);
- if (fp == NULL)
- oops("can't open file");
- }
- i = 0;
- while (fgets(line, sizeof line, fp) == line) {
- ++slinenum;
- if ((cp = strchr(line, '\n')) == NULL)
- oops("line is too long");
- *cp = '\t'; /* means all fields are tab terminated */
- for (cp = line; *cp != '\0'; ++cp)
- if (!isascii(*cp))
- oops("non-ASCII character in line");
- cp = line;
- if (*cp == '#' || *cp == '\0')
- continue;
- if (i >= NVPC)
- oops("too many lines in input");
- if (!isspace(*cp))
- oops("data line does not begin with space");
- for (online = 0; online < 8; ++online) {
- while (*cp != '\0' && isspace(*cp))
- ++cp;
- dp = cp;
- while (*dp != '\0' && !isspace(*dp))
- ++dp;
- if (dp == NULL)
- oops("too few fields on line");
- *dp = '\0';
- names[i++] = (strcmp(cp, "NULL") == 0) ? NULL :
- ecpyalloc(cp);
- cp = dp + 1;
- }
- while (isspace(*cp))
- ++cp;
- if (*cp != '\0')
- oops("wrong number of fields on line");
- }
- if (!feof(fp) || ferror(fp))
- oops("wild result reading file");
- if (fclose(fp)) {
- fp = NULL;
- oops("wild result closing file");
- }
- for ( ; i < NVPC; ++i)
- names[i] = NULL;
- }
-
- /*
- ** And now the real work begins...
- */
-
- static int
- fiswidth(font, fti, size)
- int const font;
- int const fti;
- int const size;
- {
- int w;
- int result;
-
- w = items[fti].widths[font];
- result = w * size / CWPS;
- if (((w * size) % CWPS) >= (CWPS / 2))
- ++result;
- return result;
- }
-
- static int vflag;
- static int wflag;
- static int xynh;
-
- static int
- inch()
- {
- return getchar();
- }
-
- typedef struct {
- int fti;
- long hor;
- long ver;
- int font;
- int size;
- } strike;
-
- static int
- osfind(a, b)
- int const a;
- int const b;
- {
- unsigned char * ucp;
- int i;
-
- for (i = NI; ; ++i) {
- ucp = (unsigned char *) overnames[i];
- if (ucp == NULL || *ucp == '\0')
- return 0;
- if (*ucp == a && *(ucp + 1) == b)
- return i;
- if (*ucp == b && *(ucp + 1) == a)
- return i;
- }
- }
-
- static int
- oscode(one, two)
- strike one;
- strike two;
- {
- strike three; /* You're out! */
-
- if (one.ver != two.ver || one.size != two.size)
- return 0;
- if (one.font != two.font && !fontisS(one.font) && !fontisS(two.font))
- return 0;
- if (!overstruck[one.fti] || !overstruck[two.fti])
- return 0;
- if (one.fti == two.fti && one.hor != two.hor)
- return 0;
- if (one.hor > two.hor) {
- three = one;
- one = two;
- two = three;
- }
- if ((two.hor - one.hor) >= fiswidth(one.font, one.fti, one.size) / 2)
- return 0;
- return osfind(one.fti, two.fti);
- }
-
- static int
- ouch(charname, wchor, wcver, wsize, fontnick)
- const char * const charname;
- long const wchor; /* wanted C/A/T horizontal position */
- long wcver; /* wanted C/A/T veritcal position */
- int const wsize;
- char * const fontnick;
- {
- int wfont;
- int fti;
- int i;
- strike s;
- static strike ss = { 0, -1, -1, -1, -1 };
-
- fti = ntn2fti(charname);
- wcver -= 31;
- s.fti = fti;
- s.hor = wchor;
- s.ver = wcver;
- for (wfont = 0; ; ++wfont) {
- if (wfont == NFONTS)
- wild2exit("font -", fontnick);
- if (strcmp(fontnick, fontdata[wfont].f_fontnick) == 0)
- break;
- }
- s.font = wfont;
- s.size = wsize;
- if ((i = oscode(s, ss)) > 0) {
- if (s.hor > ss.hor)
- s.hor = ss.hor;
- if (fontisS(s.font))
- s.font = ss.font;
- s.fti = i;
- dostrike(s);
- ss.fti = 0;
- } else {
- if (ss.ver != s.ver ||
- (s.hor - ss.hor) >=
- fiswidth(ss.font, ss.fti, ss.size) / 2) {
- dostrike(ss);
- ss.fti = 0;
- }
- if (!overstruck[fti]) {
- dostrike(s);
- } else {
- dostrike(ss);
- ss = s;
- }
- }
- return 0;
- }
-
- static const char * cartridge;
-
- int
- main(argc, argv)
- int argc;
- char * argv[];
- {
- int c;
- int nargs;
-
- if ((progname = strrchr(argv[0], '/')) == NULL)
- progname = argv[0];
- else ++progname;
- while ((c = getopt(argc, argv, "vwx:y:n:h:")) != EOF)
- if (c == 'x' || c == 'y' || c == 'n' || c == 'h')
- xynh = TRUE;
- else if (c == 'v')
- vflag = TRUE;
- else if (c == 'w')
- wflag = TRUE;
- else break;
- nargs = argc - optind;
- if (c != EOF ||
- (vflag && !wflag) ||
- nargs != (xynh ? 0 : 1) ||
- (nargs == 1 && strcmp(argv[optind], "=") == 0)) {
- (void) fprintf(stderr,
- "%s: usage is %s [-wv] fontdir < file\n",
- progname, progname);
- if (nargs == 1 && strcmp(argv[optind], "=") == 0)
- tameexit();
- else wildexit("usage");
- }
- if (!wflag)
- if ((c = getchar()) == EOF)
- tameexit();
- else (void) ungetc(c, stdin);
- if (nargs == 1)
- cartridge = argv[optind];
- else {
- FILE * fp;
- char * cp;
- static char buf[132];
-
- fp = fopen(".railmag", "r");
- if (fp == NULL)
- wildrexit("opening .railmag");
- if (fgets(buf, sizeof buf, fp) != buf)
- wildrexit("reading .railmag");
- if (strchr(buf, '\n') == NULL)
- wildexit("missing newline in .railmag");
- if ((cp = strrchr(buf, '/')) == NULL)
- wildexit("missing / in .railmag");
- if (fclose(fp))
- wildrexit("closing .railmag");
- *cp = '\0';
- /*
- ** Horrid special case.
- ** Maybe should check that directory exists.
- */
- if (strcmp(buf, "/usr/lib/vfont") == 0) {
- (void) strcpy(buf, DATADIR);
- (void) strcat(buf, "/default");
- }
- cartridge = buf;
- }
- loadinfo();
- if (wflag) {
- dowidth();
- tameexit();
- }
- if (catsup(inch, ouch, TRUE, FALSE) != 0)
- wildrexit("catsup");
- (void) ouch("", 0L, 0L, 0, "R"); /* to flush */
- if (!feof(stdin) || ferror(stdin))
- wildrexit("reading standard input");
- LJ_sput(enddata);
- if (ferror(stdout))
- wildrexit("writing");
- return 0;
- }
-
- /*
- ** Convert laser width table units to C/A/T width table units
- */
-
- static int
- lwtocw(fti, font, lw)
- int const fti;
- int const font;
- int const lw;
- {
- int cw;
- long num;
- long den;
- static int prevind;
-
- num = (long) lw * NCWUPI * CWPS;
- den = lwupi * lwps;
- cw = num / den;
- /*
- ** Selectively round to ensure that rules meet.
- */
- if (isascii(fti) && isprint(fti) && fti != '_')
- if ((num % den) >= (den / 2))
- ++cw;
- if (cw > 077) {
- if (wflag && fti != prevind) {
- (void) fprintf(stderr,
- "%s: note: char %s, font %s in %s too wide (%d, %d)\n",
- progname, fti2ntn(fti),
- fontdata[font].f_fontnick, cartridge, lw, cw);
- prevind = fti;
- }
- cw = 077;
- }
- return cw;
- }
-
- static char * filenames[MAXFILES];
- static long linenums[MAXFILES];
- static int lastfid;
-
- static void
- wildline(message)
- const char * const message;
- {
- char * filename;
- long linenum;
-
- if (lastfid >= 0 && lastfid < MAXFILES) {
- filename = filenames[lastfid];
- linenum = linenums[lastfid];
- } else {
- filename = NULL;
- linenum = -1;
- }
- (void) fprintf(stderr, "%s: ", progname);
- if (filename == NULL)
- (void) fprintf(stderr, "file UNKNOWN, ");
- else (void) fprintf(stderr, "file \"%s\", ", filename);
- (void) fprintf(stderr, "line %ld: ", linenum);
- (void) fprintf(stderr, "wild %s\n",
- ((message == NULL) ? "line" : message));
- wildexit("information file");
- }
-
- static int
- ctoi(c)
- int const c;
- {
- const char * cp;
- static const char digits[] = "0123456789";
-
- cp = strchr(digits, c);
- return (cp == NULL) ? -1 : (cp - digits);
- }
-
- static void
- disescape(cp)
- char * const cp;
- {
- const char * fromp;
- char * top;
- int c;
- int i;
- int j;
-
- fromp = top = cp;
- while ((c = *fromp++) != '\0')
- if (c != '\\')
- *top++ = c;
- else switch ((c = *fromp++)) {
- case '\0': --fromp; *top++ = '\\'; break;
- case 'E': *top++ = '\033'; break;
- case 'b': *top++ = '\b'; break;
- case 'f': *top++ = '\f'; break;
- case 'n': *top++ = '\n'; break;
- case 'r': *top++ = '\r'; break;
- case 't': *top++ = '\t'; break;
- case 'v': *top++ = '\v'; break;
- default:
- i = ctoi(c);
- if (i < 0 || i > 7) {
- *top++ = c;
- break;
- }
- if ((j = ctoi(*fromp)) >= 0 && j <= 7) {
- ++fromp;
- i = i * 8 + j;
- if ((j = ctoi(*fromp)) >= 0 && j <= 7) {
- ++fromp;
- i = i * 8 + j;
- }
- }
- *top++ = i;
- break;
- }
- *top = '\0';
- }
-
- static FILE *
- dfopen(filename, mode, must)
- const char * const filename;
- const char * const mode;
- int const must;
- {
- FILE * fp;
- char * cp;
- char * dp;
- int fid;
- int pass;
-
- dp = ecpyalloc(cartridge);
- for (pass = 1; pass <= 2; ++pass) {
- if (pass == 2)
- if ((cp = strrchr(dp, '/')) == NULL)
- (void) strcpy(dp, ".");
- else *cp = '\0';
- cp = ecpyalloc(dp);
- cp = ecatalloc(cp, "/");
- cp = ecatalloc(cp, filename);
- fp = fopen(cp, mode);
- if (fp == NULL) {
- free(cp);
- continue;
- }
- fid = fileno(fp);
- if (fid < 0)
- wildexit("negative file descriptor!?");
- if (fid >= MAXFILES)
- wildexit("large number of files opened");
- if (filenames[fid] != NULL)
- free(filenames[fid]);
- filenames[fid] = cp;
- linenums[fid] = 0;
- free(dp);
- return fp;
- }
- free(dp);
- if (must)
- wild2exit("result opening file", filename);
- return NULL;
- }
-
- static const char *
- namefor(fp)
- FILE * const fp;
- {
- int fid;
- static const char unknown[] = "UNKNOWN";
-
- if (fp != NULL) {
- fid = fileno(fp);
- if (fid >= 0 && fid < MAXFILES && filenames[fid] != NULL)
- return filenames[fid];
- }
- return unknown;
- }
-
- static char *
- getline(fp)
- FILE * const fp;
- {
- char * cp;
- char * dp;
- static char line[BUFSIZ];
-
- lastfid = fileno(fp);
- for ( ; ; ) {
- if (fgets(line, sizeof line, fp) != line) {
- if (ferror(fp) || !feof(fp))
- wildline("result from reading");
- if (fclose(fp))
- wildline("result from closing");
- return NULL;
- }
- ++linenums[(int) fileno(fp)];
- cp = strchr(line, '\n');
- if (cp == NULL)
- wildline("long line");
- *cp = '\0';
- /*
- ** Strip comments and trailing space.
- */
- dp = NULL;
- for (cp = line; *cp != '\0'; ++cp)
- if (*cp == '#') {
- *cp = '\0';
- break;
- } else if (isascii(*cp) && isspace(*cp)) {
- if (dp == NULL)
- dp = cp;
- } else {
- dp = NULL;
- if (*cp == '\\') {
- if (*++cp == '\0')
- break;
- }
- }
- if (dp != NULL)
- *dp = '\0';
- /*
- ** If we've got something. . .
- */
- if (line[0] != '\0')
- return line;
- }
- }
-
- static int
- splitos(name, vals)
- char * const name;
- int vals[2];
- {
- char * cp;
- int left;
- int right;
- int n;
- int c;
-
- if (name == NULL || *name == '\0')
- return -1;
- n = 0;
- for (cp = name + 1; *cp != '\0'; ++cp) {
- if ((right = ntn2fti(cp)) <= 0)
- continue;
- c = *cp;
- *cp = '\0';
- left = ntn2fti(name);
- *cp = c;
- if (left <= 0)
- continue;
- if (++n > 1)
- return -1;
- vals[0] = left;
- vals[1] = right;
- }
- return (n == 1) ? 0 : -1;
- }
-
- static int
- nametoindex(name)
- const char * const name;
- {
- int fti;
- int vals[2];
- static int oi = NI;
-
- if ((fti = ntn2fti(name)) > 0)
- return fti;
- /*
- ** Overstrike mapping?
- */
- if (splitos(name, vals) != 0) {
- char minibuf[132];
-
- (void) sprintf(minibuf, "character name--\"%s\"", name);
- wildline(minibuf);
- }
- if ((fti = osfind(vals[0], vals[1])) > 0)
- return fti;
- if (oi >= sizeof items / sizeof items[0])
- wildline("large number of overstrikes");
- overstruck[vals[0]] = TRUE;
- overstruck[vals[1]] = TRUE;
- overnames[oi] = (unsigned char *) emalloc(3);
- overnames[oi][0] = vals[0];
- overnames[oi][1] = vals[1];
- overnames[oi][2] = 0;
- return oi++;
- }
-
- static int
- linematch(havetype, havecount, wanttype, wantlo, wanthi)
- const char * const havetype;
- int const havecount;
- const char * const wanttype;
- int const wantlo;
- int const wanthi;
- {
- if (strcmp(havetype, wanttype) != 0)
- return FALSE;
- if (havecount < wantlo || havecount > wanthi)
- wildline("number of fields");
- return TRUE;
- }
-
- static void
- loadsub(filename)
- const char * const filename;
- {
- FILE * fp;
- char * line;
- item * ip;
- int fti;
- int i;
- int n;
- int font;
- int width;
- int size;
- char t[BUFSIZ];
- char f[9][BUFSIZ];
-
- fp = dfopen(filename, "r", TRUE);
- for (i = 0; i < 9; ++i)
- f[i][0] = '\0';
- while ((line = getline(fp)) != NULL) {
- n = sscanf(line, "%s %s %s %s %s %s %s %s",
- t, f[2], f[3], f[4],
- f[5], f[6], f[7], f[8]);
- for (i = 2; i <= n; ++i)
- disescape(f[i]);
- /*
- ** NEWPAGE data
- */
- if (linematch(t, n, "NEWPAGE", 2, 2)) {
- newpage = ecpyalloc(f[2]);
- continue;
- }
- /*
- ** PORTRAIT data
- */
- if (linematch(t, n, "PORTRAIT", 2, 2)) {
- portrait = ecpyalloc(f[2]);
- continue;
- }
- /*
- ** LANDSCAPE data
- */
- if (linematch(t, n, "LANDSCAPE", 2, 2)) {
- landscape = ecpyalloc(f[2]);
- continue;
- }
- /*
- ** DOWNORIENT--always portrait for now.
- */
- if (linematch(t, n, "DOWNORIENT", 1, 1)) {
- LJ_sput(portrait);
- continue;
- }
- /*
- ** LEFTMARGIN size
- */
- if (linematch(t, n, "LEFTMARGIN", 2, 2)) {
- if (sscanf(f[2], scheck(f[2], "%d"),
- &leftmargin) != 1 || leftmargin < 0)
- wildline("left margin");
- continue;
- }
- /*
- ** WIDTHUNITSPERINCH size
- */
- if (linematch(t, n, "WIDTHUNITSPERINCH", 2, 2)) {
- if (sscanf(f[2], scheck(f[2], "%f"), &lwupi) != 1 ||
- lwupi <= 0)
- wildline("width units per inch");
- continue;
- }
- /*
- ** WIDTHPOINTSIZE size
- */
- if (linematch(t, n, "WIDTHPOINTSIZE", 2, 2)) {
- if (sscanf(f[2], scheck(f[2], "%f"), &lwps) != 1 ||
- lwps <= 0)
- wildline("width point size");
- continue;
- }
- /*
- ** LOWCHAR value string
- */
- if (linematch(t, n, "LOWCHAR", 3, 3)) {
- if (sscanf(f[2], scheck(f[2], "%d"), &lowvalue) != 1 ||
- lowvalue <= 0)
- wildline("low value");
- lowstring = ecpyalloc(f[3]);
- continue;
- }
- /*
- ** CPI size
- */
- if (linematch(t, n, "CPI", 2, 2)) {
- if (sscanf(f[2], scheck(f[2], "%f"), &lcpi) != 1 ||
- lcpi <= 0)
- wildline("CPI");
- continue;
- }
- /*
- ** INCLUDE filename
- */
- if (linematch(t, n, "INCLUDE", 2, 2)) {
- loadsub(f[2]);
- continue;
- }
- /*
- ** DOWNDATA data
- */
- if (linematch(t, n, "DOWNDATA", 2, 2)) {
- LJ_sput(f[2]);
- continue;
- }
- /*
- ** ENDDATA data
- */
- if (linematch(t, n, "ENDDATA", 2, 2)) {
- enddata = ecpyalloc(f[2]);
- continue;
- }
- /*
- ** DOWNFILE filename
- */
- if (linematch(t, n, "DOWNFILE", 2, 2)) {
- FILE * dfp;
- char * cp;
- int c;
-
- cp = ecpyalloc(f[2]);
- cp = ecatalloc(cp, ".D");
- dfp = dfopen(cp, "r", TRUE);
- free(cp);
- while ((c = getc(dfp)) != EOF)
- LJ_cput(c);
- if (ferror(dfp) || !feof(dfp) || fclose(dfp))
- wildline("result from downloading");
- continue;
- }
- /*
- ** FORGET charname
- */
- if (linematch(t, n, "FORGET", 2, 2)) {
- fti = nametoindex(f[2]);
- ip = &items[fti];
- ip->ssname = ip->inset =
- ip->outset = ip->data = NULL;
- ip->waschar = FALSE;
- continue;
- }
- /*
- ** UNITSPERINCH horizontal vertical
- */
- if (linematch(t, n, "UNITSPERINCH", 3, 3)) {
- int hupi;
- int vupi;
-
- if (sscanf(f[2], scheck(f[2], "%d"),
- &hupi) != 1 ||
- hupi <= 0)
- wildline("horizontal UNITSPERINCH");
- if (sscanf(f[2], scheck(f[2], "%d"),
- &vupi) != 1 ||
- vupi <= 0)
- wildline("vertical UNITSPERINCH");
- if (horunitsperinch != 0 &&
- (horunitsperinch != hupi ||
- verunitsperinch != vupi))
- wildline("repeated UNITSPERINCH");
- horunitsperinch = hupi;
- verunitsperinch = vupi;
- continue;
- }
- /*
- ** MOVES horizontal-move vertical-move
- */
- if (linematch(t, n, "MOVES", 3, 3)) {
- hormove = ecpyalloc(f[2]);
- vermove = ecpyalloc(f[3]);
- continue;
- }
- /*
- ** FONT name in out
- */
- if (linematch(t, n, "FONT", 4, 4)) {
- for (font = 0; font < NFONTS; ++font) {
- if (strcmp(f[2],
- fontdata[font].f_fontnick) != 0)
- continue;
- fontdata[font].f_in = ecpyalloc(f[3]);
- fontdata[font].f_out = ecpyalloc(f[4]);
- break;
- }
- if (font == NFONTS)
- wildline("unknown font name");
- continue;
- }
- /*
- ** SIZES in
- */
- if (linematch(t, n, "SIZES", 2, 2)) {
- sizes = ecatalloc(sizes, f[2]);
- continue;
- }
- /*
- ** FIRST pointsize font in
- */
- if (linematch(t, n, "FIRST", 4, 4)) {
- if (sscanf(f[2], scheck(f[2], "%d"), &size) != 1 ||
- size < 0 ||
- size >= sizeof firsts / sizeof firsts[0])
- wildline("size");
- for (i = 0; ; ++i) {
- if (i >= NFONTS)
- wildline("font");
- if (strcmp(f[3], fontdata[i].f_fontnick) != 0)
- continue;
- firsts[size][i] = ecatalloc(firsts[size][i],
- f[4]);
- break;
- }
- continue;
- }
- /*
- ** Need width for rest.
- */
- if (lwupi == 0)
- wildline("missing WIDTHUNITSPERINCH line");
- if (lwps == 0)
- wildline("missing WIDTHPOINTSIZE line");
- if (horunitsperinch == 0 || verunitsperinch == 0)
- wildline("missing UNITSPERINCH line");
- /*
- ** SYMBOLS filename [in [out]]
- ** If cpi != 0 and there's no width file,
- ** all widths are set to lwupi / lcpi.
- */
- if (linematch(t, n, "SYMBOLS", 2, 4)) {
- FILE * sfp;
- const char * cp;
- char * template;
- char * names[NI];
- char * rwidths[NI];
- char * iwidths[NI];
- char * bwidths[NI];
- int didr;
- int didib;
- char * ssname;
- char * inset;
- char * outset;
-
- ssname = ecpyalloc(f[2]);
- inset = (n <= 2) ? NULL : ecpyalloc(f[3]);
- outset = (n <= 3) ? NULL : ecpyalloc(f[4]);
- template = ecpyalloc(ssname);
- template = ecatalloc(template, ".X");
- template[strlen(template) - 1] = 'M';
- sfp = dfopen(template, "r", TRUE);
- cp = namefor(sfp);
- (void) fclose(sfp);
- getnames(cp, names);
- template[strlen(template) - 1] = 'R';
- sfp = dfopen(template, "r", lcpi == 0);
- didib = FALSE;
- if (sfp == NULL)
- didr = FALSE;
- else {
- didr = TRUE;
- cp = namefor(sfp);
- (void) fclose(sfp);
- getnames(cp, rwidths);
-
- template[strlen(template) - 1] = 'I';
- sfp = dfopen(template, "r", FALSE);
- if (sfp != NULL) {
- didib = TRUE;
- cp = namefor(sfp);
- (void) fclose(sfp);
- getnames(cp, iwidths);
-
- template[strlen(template) - 1] = 'B';
- sfp = dfopen(template, "r", TRUE);
- cp = namefor(sfp);
- (void) fclose(sfp);
- getnames(cp, bwidths);
- }
- }
- for (i = 0; i < NI; ++i) {
- if (names[i] == NULL)
- continue;
- fti = nametoindex(names[i]);
- ip = &items[fti];
- if (ip->ssname != NULL)
- continue;
- ip->ssname = ssname;
- ip->inset = inset;
- ip->outset = outset;
- ip->data = emalloc(2);
- ip->data[0] = i;
- ip->data[1] = '\0';
- for (font = 0; font < NFONTS; ++font) {
- if (!didr)
- width = lwupi / lcpi;
- else {
- cp = rwidths[i];
- if (didib)
- if (fontisB(font))
- cp = bwidths[i];
- else if (fontisI(font))
- cp = iwidths[i];
- if (cp == NULL)
- width = 0;
- else width = atoi(cp);
- }
- ip->lwidths[font] = width;
- ip->widths[font] = lwtocw(i, font,
- width);
- }
- }
- continue;
- }
- /*
- ** And last but not least. . .
- ** CHAR charname symbolset data [wideas offset]
- */
- if (linematch(t, n, "CHAR", 4, 6)) {
- char * cp;
- int off;
-
- if (n < 6)
- off = 0;
- else if (sscanf(f[6], scheck(f[6], "%d"), &off) != 1)
- wildline("offset");
- fti = nametoindex(f[2]);
- ip = &items[fti];
- if (n == 4 && ip->ssname == NULL &&
- strcmp(f[2], "br") != 0)
- wildline("missing width w/o old width");
- if (ip->waschar)
- wildline("multiple lines for same CHAR");
- ip->waschar = TRUE;
- for (i = 0; i < NI; ++i) {
- item * jp;
-
- jp = &items[i];
- if (jp->ssname != NULL &&
- strcmp(jp->ssname, f[3]) == 0)
- break;
- }
- if (i >= NI)
- wildline("CHAR symbol set");
- ip->ssname = items[i].ssname;
- ip->inset = items[i].inset;
- ip->outset = items[i].outset;
- ip->data = ecpyalloc(f[4]);
- if (n == 4)
- continue;
- for (font = 0; font < NFONTS; ++font) {
- int w;
-
- w = off;
- for (cp = f[5]; *cp != '\0'; ++cp) {
- if (items[(int) *cp].ssname == NULL)
- wildline("'wide as' string");
- w += items[(int) *cp].lwidths[font];
- }
- ip->lwidths[font] = w;
- ip->widths[font] = lwtocw(fti, font, w);
- }
- continue;
- }
- wildline("line of unknown type");
- }
- }
-
- static void
- loadinfo()
- {
- item * ip;
- int i;
- int j;
- int font;
-
- loadsub("table");
- if (hormove == NULL || vermove == NULL)
- wildexit("missing MOVES line in table");
- /*
- ** Characters with multiple width table indices
- */
- i = ntn2fti("ul");
- j = '_';
- if (items[i].ssname == NULL)
- items[i] = items[j];
- else if (items[j].ssname == NULL)
- items[j] = items[i];
- i = ntn2fti("hy");
- j = '-';
- if (items[i].ssname == NULL)
- items[i] = items[j];
- else if (items[j].ssname == NULL)
- items[j] = items[i];
- /*
- ** Overstrike widths.
- */
- for (i = NI; overnames[i] != NULL && overnames[i][0] != '\0'; ++i) {
- ip = &items[overnames[i][0]];
- for (font = 0; font < NFONTS; ++font)
- items[i].widths[font] = ip->widths[font];
- ip = &items[overnames[i][1]];
- for (font = 0; font < NFONTS; ++font)
- if (ip->widths[font] > items[i].widths[font])
- items[i].widths[font] = ip->widths[font];
- }
- if (!vflag)
- return;
- (void) printf("CHAR[S]\tSYMBOLSET %c%c%c%c WIDTHS DATA\n",
- *fontdata[0].f_fontnick, *fontdata[1].f_fontnick,
- *fontdata[2].f_fontnick, *fontdata[3].f_fontnick);
- for (i = 0;
- i < NI || (overnames[i] != NULL && overnames[i][0] != '\0');
- ++i) {
- ip = &items[i];
- if (ip->ssname == NULL)
- continue;
- if (i < NI)
- (void) printf("%s", fti2ntn(i));
- else (void) printf("%s %s", fti2ntn((int) overnames[i][0]),
- fti2ntn((int) overnames[i][1]));
- (void) printf("\t%-9s", ip->ssname);
- for (font = 0; font < NFONTS; ++font)
- (void) printf("%4d", ip->widths[font]);
- (void) printf(" ");
- for (j = 0; ip->data[j] != '\0'; ++j) {
- int c;
-
- c = ip->data[j];
- if (isascii(c) && isprint(c) && c != ' ')
- (void) putchar(c);
- else if (c == '\033')
- (void) printf("\\E");
- else (void) printf("\\%03o", (unsigned char) c);
- }
- (void) printf("\n");
- }
- }
-
- static void
- LJ_cput(c)
- int const c;
- {
- if (!wflag)
- (void) putchar(c);
- }
-
- static void
- LJ_sput(s)
- const char * s;
- {
- int c;
-
- if (s == NULL)
- return;
- while ((c = *s++) != '\0')
- LJ_cput(c);
- }
-
- static void
- LJ_fdput(f, d)
- const char * const f;
- int const d;
- {
- /*
- ** 302 / 1000 is log10(2.0) rounded up.
- ** Subtract one for the sign bit;
- ** add one for integer division truncation;
- ** add one more for a minus sign.
- */
- #define INT_STRLEN_MAXIMUM(type) \
- ((sizeof(type) * CHAR_BIT - 1) * 302 / 1000 + 2)
-
- static char * buf;
- static int bufsize;
- int wantsize;
-
- wantsize = strlen(f) + INT_STRLEN_MAXIMUM(int) + 1;
- if (wantsize > bufsize) {
- ifree(buf);
- buf = emalloc(wantsize);
- bufsize = wantsize;
- }
- (void) sprintf(buf, f, d);
- LJ_sput(buf);
- }
-
- static void
- swift(afont, wfont)
- int const afont;
- int const wfont;
- {
- if (afont >= 0)
- LJ_sput(fontdata[afont].f_out);
- LJ_sput(fontdata[wfont].f_in);
- }
-
- static void
- dostrike(s)
- strike s;
- {
- item * ip;
- static long achor = -1;
- static long acver = -1;
- static int afont = -1;
- static int asize = -1;
- static int apage = -1;
- static item * curip;
- static item * oldip;
- static int called;
-
- if (s.fti <= 0)
- return;
- /*
- ** First time downloading.
- */
- if (firsts[s.size][s.font] != NULL) {
- FILE * fp;
- char * cp;
- char * dp;
- int c;
-
- cp = firsts[s.size][s.font];
- firsts[s.size][s.font] = NULL;
- while ((c = *cp++) != '\0') {
- if (c != '<') {
- LJ_cput(c);
- continue;
- }
- dp = cp;
- while (*dp != '\0' && *dp != '>')
- ++dp;
- if (*dp == '\0') {
- LJ_cput(c);
- continue;
- }
- *dp = '\0';
- /*
- ** Download the file.
- */
- if ((fp = fopen(cp, "r")) == NULL)
- wild2exit("result opening", cp);
- while ((c = getc(fp)) != EOF)
- LJ_cput(c);
- if (ferror(fp) || !feof(fp) || fclose(fp))
- wildexit("result from downloading");
- *dp++ = '>';
- cp = dp;
- }
- curip = NULL; /* to get font reselection */
- }
- ip = &items[s.fti];
- /*
- ** Easiest part first.
- */
- if (curip != NULL && curip->outset != NULL &&
- curip->ssname != ip->ssname) {
- LJ_sput(curip->outset);
- curip = oldip;
- oldip = NULL;
- }
- if (curip == NULL || ip->ssname != curip->ssname) {
- LJ_sput(ip->inset);
- if (ip->outset != NULL)
- oldip = curip;
- curip = ip;
- }
- /*
- ** Get to right page; modulate vertical offset.
- */
- {
- int wpage;
-
- wpage = s.ver / ncvupp;
- if (wpage != apage) {
-
- if (called)
- LJ_sput(newpage);
- apage = wpage;
- acver = 0;
- }
- s.ver %= ncvupp;
- }
- /*
- ** Get to right horizontal place.
- */
- /*
- ** Always position repeated root ens and underlines.
- */
- {
- static int didindices;
- static int rnindex;
- static int ulindex;
- static int _index;
- static int dotindex;
- static int prev;
-
- if (!didindices) {
- didindices = TRUE;
- rnindex = ntn2fti("rn");
- ulindex = ntn2fti("ul");
- _index = ntn2fti("_");
- dotindex = ntn2fti(".");
- }
- if (s.fti == prev &&
- (s.fti == rnindex ||
- s.fti == ulindex ||
- s.fti == _index ||
- s.fti == dotindex))
- achor = ~s.hor;
- prev = s.fti;
- }
- if (s.hor != achor) {
- long wlhor;
- static long adjustment;
-
- wlhor = s.hor * horunitsperinch / NCHUPI;
- /*
- ** Adjust for stupid left margin.
- */
- if (wlhor < leftmargin)
- adjustment = leftmargin;
- wlhor += adjustment;
- /*
- ** Rustproofing.
- */
- if (wlhor < 0)
- wlhor = 0;
- LJ_fdput(hormove, (int) wlhor);
- achor = s.hor;
- }
- /*
- ** Get to right vertical place.
- */
- {
- long wlver;
-
- if (s.ver != acver) {
- wlver = (long) s.ver * verunitsperinch / NCVUPI;
- /*
- ** Rustproofing.
- */
- if (wlver < 0)
- wlver = 0;
- LJ_fdput(vermove, (int) wlver);
- acver = s.ver;
- }
- }
- /*
- ** If haven't already changed font. . .
- */
- if (afont != s.font) {
- swift(afont, s.font);
- afont = s.font;
- }
- if (asize != s.size) {
- LJ_fdput(sizes, s.size);
- asize = s.size;
- }
- /*
- ** Quote if necessary.
- */
- if (ip->data != NULL && ip->data[0] != 0 && ip->data[1] == 0 &&
- lowvalue != 0 && ip->data[0] < lowvalue)
- LJ_sput(lowstring);
- /*
- ** Finally send out the data.
- */
- if (ip->data != NULL)
- LJ_sput(ip->data);
- else if (isascii(s.fti) && isprint(s.fti))
- LJ_cput(s.fti);
- else LJ_cput('\177'); /* make this settable? */
- /*
- ** Update horizontal position.
- */
- achor += fiswidth(s.font, s.fti, s.size);
- called = TRUE;
- }
-
- /*
- ** The stuff below is used only when generating width tables for use with troff.
- */
-
- static int
- ascends(name)
- const char * name;
- {
- if (name[1] == '\0')
- return isdigit(name[0]) || isupper(name[0]) ||
- strchr("bdfhijklt", name[0]) != 0;
- switch (*name++) {
- case '*': return strchr("bdzhlcfqGDHLCPSUFQW", *name) != 0;
- case 'f': return strchr("ilf", *name) != 0;
- case 'F': return strchr("il", *name) != 0;
- case 'g': return *name == 'r';
- }
- return FALSE;
- }
-
- static int
- descends(name)
- const char * const name;
- {
- if (name[1] == '\0')
- return strchr("Qgjpqy", name[0]) != 0;
- if (name[0] == '*')
- return strchr("bgzymcrfxq", name[1]) != 0;
- return strcmp(name, "ts") == 0;
- }
-
- static void
- dowidth()
- {
- FILE * fp;
- char * cp;
- const char * name;
- item * ip;
- int font;
- int j;
- int w;
-
- for (font = 0; font < NFONTS; ++font) {
- cp = ecpyalloc("ft");
- cp = ecatalloc(cp, fontdata[font].f_fontnick);
- fp = dfopen(cp, "w", TRUE);
- free(cp);
- for (j = 0; j < 256; ++j) {
- if ((name = fti2ntn(j)) == NULL) {
- (void) putc(0, fp);
- continue;
- }
- if (fontisS(font) ? ntnonr(name) : ntnons(name)) {
- (void) putc(0, fp);
- continue;
- }
- if (strcmp(name, "\\^") == 0)
- w = (NCHUPI * CWPS) / (NPPI * 12); /* 1/12 em */
- else if (strcmp(name, "\\|") == 0)
- w = (NCHUPI * CWPS) / (NPPI * 6); /* 1/6 em */
- else {
- ip = &items[j];
- if (ip->ssname == NULL) {
- (void) putc(0, fp);
- continue;
- }
- w = ip->widths[font];
- if (ascends(name))
- w |= 0200;
- if (descends(name))
- w |= 0100;
- }
- (void) putc(w, fp);
- }
- if (ferror(fp) || fclose(fp))
- wildline("result writing");
- }
- }
-