home *** CD-ROM | disk | FTP | other *** search
- /* Copyright 1985, 1986, 1987, 1988 Chris Lewis
- All Rights Reserved
-
- Permission to copy and further distribute is freely given provided
- this copyright notice remains intact and that this software is not
- sold for profit.
-
- Project: Generic Troff drivers
- Module: opt.c
- Author: Chris Lewis
- Specs: Optimizer module
- */
-
- #include "defs.h"
-
- int specXPos, specYPos;
- extern struct cattab tabN[], tabS[];
-
- #ifdef OPT
- #ifndef lint
- static char SCCSid[] =
- "@(#)opt.c: 2.2 Copyright 90/08/10 15:16:19 Chris Lewis";
- #endif
-
- struct insbuf {
- char font, points, nc;
- short xpos, ypos;
- };
-
- #define INSBUFSIZ 200
- #define OPTSIZ 100
- struct insbuf insbuf[INSBUFSIZ];
- static struct insbuf *insptr = insbuf;
- static int insypos = -1;
-
- canoninsert(xpos, ypos, font, points, nc)
- register int xpos, ypos;
- register int font, points, nc; {
- DBP((D_CAT, "canoninsert: %d %d %d %d %d\n", xpos, ypos, font, points,
- nc));
-
- if (insypos != ypos || (insptr - insbuf >= INSBUFSIZ - 2)) {
- canonflush();
- insypos = ypos;
- }
- insptr->font = font;
- insptr->points = points;
- insptr->nc = nc;
- insptr->xpos = xpos;
- insptr++;
- }
-
- #ifdef SORT
- int xsortorder;
-
- xsort(a, b)
- register struct insbuf *a, *b; {
- int ret;
- if (a->xpos < b->xpos)
- ret = -1;
- else if (a->xpos > b->xpos)
- ret = 1;
- else
- ret = 0;
- return(xsortorder * ret);
- }
- #endif
-
- canonflush() {
- register struct insbuf *ip;
- insptr--;
- DBP((D_CAT, "canonflush: start: %d chars\n", insptr - insbuf + 1));
-
- if (insptr < insbuf) {
- insptr = insbuf;
- return;
- }
-
- if (insptr->xpos < insbuf[0].xpos) {
- DBP((D_CAT, "canonflush: BACK (%d chars)\n", insptr - insbuf + 1));
- #ifdef SORT
- xsortorder = -1;
- insdump(insbuf, insptr);
- qsort(insbuf, insptr - insbuf + 1, sizeof(struct insbuf), xsort);
- insdump(insbuf, insptr);
- #endif
- for(ip = insptr;ip >= insbuf; ip--)
- canonchar(ip->xpos, insypos, ip->font, ip->points, ip->nc);
- } else {
- DBP((D_CAT, "canonflush: FORW (%d chars)\n", insptr - insbuf + 1));
- #ifdef SORT
- xsortorder = 1;
- insdump(insbuf, insptr);
- qsort(insbuf, insptr - insbuf + 1, sizeof(struct insbuf), xsort);
- insdump(insbuf, insptr);
- #endif
- for(ip = insbuf;ip <= insptr; ip++)
- canonchar(ip->xpos, insypos, ip->font, ip->points, ip->nc);
- }
- insptr = insbuf;
- optflush();
- }
-
- canonchar(xpos, ypos, font, points, nc)
- register int xpos, ypos;
- register int font, points, nc; {
- static struct insbuf lastchar;
- static short lastypos;
- static sstate = 0;
- static char sbuf[512];
- register char *p;
- #ifdef INSPECIAL
- /* Inline special directives, not supported yet */
- switch(sstate) {
- case 0:
- if (font == 3 && nc == 34) {
- sstate = 1;
- lastchar.xpos = specXPos = xpos;
- lastchar.font = font;
- lastchar.points = points;
- lastchar.nc = nc;
- lastypos = specYPos = ypos;
- optflush();
- return;
- }
- break;
- case 1:
- if (font == 3 && nc == 34) {
- if (xpos == lastchar.xpos && ypos == lastypos) {
- sstate++;
- sbuf[0] = '\0';
- return;
- } else {
- lastchar.xpos = xpos;
- lastypos = ypos;
- /* stay in this state */
- }
- } else
- sstate = 0;
-
- if (be->beputchar)
- (*be->beputchar)(lastchar.xpos, lastypos, lastchar.font,
- lastchar.points, lastchar.nc, (char *) NULL);
- break;
- case 2:
- if (nc == 34 && font == 3) {
- DBP((D_CAT, "Special inline sequence: %s\n", sbuf));
- dospecial(sbuf);
- sstate = 0;
- return;
- }
- if (strlen(sbuf) > sizeof(sbuf) - 1) {
- fprintf(stderr,
- "%s: unterminated/too long \\(bs\\(bstr\\(bs\n",
- progname);
- sstate = 0;
- return;
- }
- if (font == 3)
- p = tabS[nc].ch_name;
- else
- p = tabN[nc].ch_name;
- if (strlen(p) >= 2) {
- if (strcmp(p, "hy") == 0 ||
- strcmp(p, "mi") == 0 ||
- strcmp(p, "\\-") == 0)
- p = "-";
- else if (strcmp(p, "ff") == 0 ||
- strcmp(p, "fi") == 0 ||
- strcmp(p, "fl") == 0)
- ;
- else if (strcmp(p, "Fi") == 0)
- p = "ffi";
- else if (strcmp(p, "Fl") == 0)
- p = "ffl";
- else
- p = " ";
- }
- strcat(sbuf, p);
- return;
- }
- #endif
- optinsert(xpos, ypos, font, points, nc);
- }
-
- int optxpos, optypos;
- int optfont, optpoints, optnc, origxpos;
- char optbuffer[OPTSIZ];
- char *optp = optbuffer;
-
- optflush() {
-
- if (!optimize)
- return;
-
- if (optbuffer[0] && be->beputchar)
- (*be->beputchar)(origxpos, optypos, optfont, optpoints, optnc,
- optbuffer);
- optbuffer[0] = '\0';
- optp = optbuffer;
- }
-
- optinsert(xpos, ypos, font, points, nc)
- int font, points, nc;
- int xpos, ypos; {
- struct troff2befont *bp;
- static char *wp;
- extern struct cattab tabN[], tabS[];
- struct cattab *ct;
- register char *from;
- int cantcache;
-
- if (!optimize) {
- if (be->beputchar)
- (*be->beputchar)(xpos, ypos, font, points, nc, (char *) NULL);
- return;
- }
-
- DBP((D_CHAR, "OLD: x,y,f,p,c = %d,%d,%d,%d,%d\n",
- optxpos, optypos, optfont, optpoints, optnc));
- DBP((D_CHAR, "NEW: x,y,f,p,c = %d,%d,%d,%d,%d\n",
- xpos, ypos, font, points, nc));
-
- /* the 10 is to ensure that there's enough room for moderately
- long multiple-character sequences */
-
- if (ypos != optypos || optfont != font || optpoints != points ||
- wp != xlatetable[font]->widthtable ||
- optp > optbuffer + OPTSIZ - 10)
- optflush();
-
- wp = xlatetable[font]->widthtable;
-
- if (font == 3) {
- bp = &be->besymfont[nc];
- ct = &tabS[nc];
- } else {
- bp = &be->bestdfont[nc];
- ct = &tabN[nc];
- }
-
- cantcache = !wp || (int) wp == 1 || (font == 3 ? bp->t2b_font != S:
- bp->t2b_font != N);
-
- if (bp->t2b_xc || bp->t2b_yc || bp->t2b_scale || cantcache)
- optflush();
-
- if (optxpos != xpos) /* handle spaces one day... */
- optflush();
-
- if (!optbuffer[0]) {
- optypos = ypos;
- optxpos = xpos;
- origxpos = xpos;
- optfont = font;
- optnc = nc;
- optpoints = points;
- }
-
- if (cantcache) {
- if (be->beputchar)
- (*be->beputchar)(xpos, ypos, font, points, nc, (char *) NULL);
- return;
- }
-
- optxpos += ((wp[ct->ch_wididx]) * points + 3) / 6;
- DBP((D_CAT, "optxpos: %d\n", optxpos));
-
- for (from = bp->t2b_charseq; *from;)
- *optp++ = *from++;
- *optp = '\0';
- }
- #endif
-
- #ifdef SORT
- insdump(b, p)
- register struct insbuf *b, *p; {
- if (!(debug&D_VERB))
- return;
- DBP((D_VERB, "insdump:\n"));
- for(; b <= p; b++)
- DBP((D_VERB, "%d %d\n", b->xpos, b->nc));
- }
- #endif
-