Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

#include "tdef.h"
#include "ext.h"
#include "fns.h"

/*
 * troff9.c
 * 
 * misc functions
 */

Tchar setz(void)
{
        Tchar i;

        if (!ismot(i = getch()))
                i |= ZBIT;
        return(i);
}

void setline(void)
{
        Tchar *i;
        Tchar c;
        int length;
        int j, w, cnt, delim, rem, temp;
        Tchar linebuf[NC];

        if (ismot(c = getch()))
                return;
        delim = cbits(c);
        vflag = 0;
        dfact = EM;
        length = quant(atoi0(), HOR);
        dfact = 1;
        if (!length) {
                eat(delim);
                return;
        }
s0:
        if ((j = cbits(c = getch())) == delim || j == '\n') {
                ch = c;
                c = RULE | chbits;
        } else if (cbits(c) == FILLER)
                goto s0;
        w = width(c);
        if (w <= 0) {
                ERROR "zero-width underline character ignored" WARN;
                c = RULE | chbits;
                w = width(c);
        }
        i = linebuf;
        if (length < 0) {
                *i++ = makem(length);
                length = -length;
        }
        if (!(cnt = length / w)) {
                *i++ = makem(-(temp = ((w - length) / 2)));
                *i++ = c;
                *i++ = makem(-(w - length - temp));
                goto s1;
        }
        if (rem = length % w) {
                if (cbits(c) == RULE || cbits(c) == UNDERLINE || cbits(c) == ROOTEN)
                        *i++ = c | ZBIT;
                *i++ = makem(rem);
        }
        if (cnt) {
                *i++ = RPT;
                *i++ = cnt;
                *i++ = c;
        }
s1:
        *i = 0;
        eat(delim);
        pushback(linebuf);
}


eat(int c)
{
        int i;

        while ((i = cbits(getch())) != c && i != '\n')
                ;
        return(i);
}


void setov(void)
{
        int j, k;
        Tchar i, o[NOV+1];
        int delim, w[NOV+1];

        if (ismot(i = getch()))
                return;
        delim = cbits(i);
        for (k = 0; k < NOV && (j = cbits(i = getch())) != delim && j != '\n'; k++) {
                o[k] = i;
                w[k] = width(i);
        }
        o[k] = w[k] = 0;
        if (o[0])
                for (j = 1; j; ) {
                        j = 0;
                        for (k = 1; o[k] ; k++) {
                                if (w[k-1] < w[k]) {
                                        j++;
                                        i = w[k];
                                        w[k] = w[k-1];
                                        w[k-1] = i;
                                        i = o[k];
                                        o[k] = o[k-1];
                                        o[k-1] = i;
                                }
                        }
                }
        else 
                return;
        *pbp++ = makem(w[0] / 2);
        for (k = 0; o[k]; k++)
                ;
        while (k>0) {
                k--;
                *pbp++ = makem(-((w[k] + w[k+1]) / 2));
                *pbp++ = o[k];
        }
}


void setbra(void)
{
        int k;
        Tchar i, *j, dwn;
        int cnt, delim;
        Tchar brabuf[NC];

        if (ismot(i = getch()))
                return;
        delim = cbits(i);
        j = brabuf + 1;
        cnt = 0;
        if (NROFF)
                dwn = (2 * t.Halfline) | MOT | VMOT;
        else
                dwn = EM | MOT | VMOT;
        while ((k = cbits(i = getch())) != delim && k != '\n' && j <= brabuf + NC - 4) {
                *j++ = i | ZBIT;
                *j++ = dwn;
                cnt++;
        }
        if (--cnt < 0)
                return;
        else if (!cnt) {
                ch = *(j - 2);
                return;
        }
        *j = 0;
        if (NROFF)
                *--j = *brabuf = (cnt * t.Halfline) | MOT | NMOT | VMOT;
        else
                *--j = *brabuf = (cnt * EM) / 2 | MOT | NMOT | VMOT;
        *--j &= ~ZBIT;
        pushback(brabuf);
}


void setvline(void)
{
        int i;
        Tchar c, rem, ver, neg;
        int cnt, delim, v;
        Tchar vlbuf[NC];
        Tchar *vlp;

        if (ismot(c = getch()))
                return;
        delim = cbits(c);
        dfact = lss;
        vflag++;
        i = quant(atoi0(), VERT);
        dfact = 1;
        if (!i) {
                eat(delim);
                vflag = 0;
                return;
        }
        if ((cbits(c = getch())) == delim) {
                c = BOXRULE | chbits;   /*default box rule*/
        } else 
                getch();
        c |= ZBIT;
        neg = 0;
        if (i < 0) {
                i = -i;
                neg = NMOT;
        }
        if (NROFF)
                v = 2 * t.Halfline;
        else {
                v = EM;
                if (v < VERT)           /* ATT EVK hack: Erik van Konijnenburg, */
                        v = VERT;       /* hvlpb!evkonij, ATT NSI Hilversum, Holland */
        }

        cnt = i / v;
        rem = makem(i % v) | neg;
        ver = makem(v) | neg;
        vlp = vlbuf;
        if (!neg)
                *vlp++ = ver;
        if (absmot(rem) != 0) {
                *vlp++ = c;
                *vlp++ = rem;
        }
        while (vlp < vlbuf + NC - 3 && cnt--) {
                *vlp++ = c;
                *vlp++ = ver;
        }
        *(vlp - 2) &= ~ZBIT;
        if (!neg)
                vlp--;
        *vlp = 0;
        pushback(vlbuf);
        vflag = 0;
}

#define NPAIR   (NC/2-6)        /* max pairs in spline, etc. */

void setdraw(void)      /* generate internal cookies for a drawing function */
{
        int i, j, k, dx[NPAIR], dy[NPAIR], delim, type;
        Tchar c, drawbuf[NC];
        int drawch = '.';       /* character to draw with */

        /* input is \D'f dx dy dx dy ... c' (or at least it had better be) */
        /* this does drawing function f with character c and the */
        /* specified dx,dy pairs interpreted as appropriate */
        /* pairs are deltas from last point, except for radii */

        /* l dx dy:     line from here by dx,dy */
        /* c x:         circle of diameter x, left side here */
        /* e x y:       ellipse of diameters x,y, left side here */
        /* a dx1 dy1 dx2 dy2:
                        ccw arc: ctr at dx1,dy1, then end at dx2,dy2 from there */
        /* ~ dx1 dy1 dx2 dy2...:
                        spline to dx1,dy1 to dx2,dy2 ... */
        /* b x c:
                        built-up character of type c, ht x */
        /* f dx dy ...: f is any other char:  like spline */

        if (ismot(c = getch()))
                return;
        delim = cbits(c);
        numerr.escarg = type = cbits(getch());
        if (type == '~')        /* head off the .tr ~ problem */
                type = 's';
        for (i = 0; i < NPAIR ; i++) {
                skip();
                vflag = 0;
                dfact = EM;
                dx[i] = quant(atoi0(), HOR);
                if (dx[i] > MAXMOT)
                        dx[i] = MAXMOT;
                else if (dx[i] < -MAXMOT)
                        dx[i] = -MAXMOT;
                skip();
                if (type == 'c') {
                        dy[i] = 0;
                        goto eat;
                }
                vflag = 1;
                dfact = lss;
                dy[i] = quant(atoi0(), VERT);
                if (dy[i] > MAXMOT)
                        dy[i] = MAXMOT;
                else if (dy[i] < -MAXMOT)
                        dy[i] = -MAXMOT;
eat:
                if (cbits(c = getch()) != ' ') {        /* must be the end */
                        if (cbits(c) != delim) {
                                drawch = cbits(c);
                                getch();
                        }
                        i++;
                        break;
                }
        }
        dfact = 1;
        vflag = 0;
        if (TROFF) {
                drawbuf[0] = DRAWFCN | chbits | ZBIT;
                drawbuf[1] = type | chbits | ZBIT;
                drawbuf[2] = drawch | chbits | ZBIT;
                for (k = 0, j = 3; k < i; k++) {
                        drawbuf[j++] = MOT | ((dx[k] >= 0) ? dx[k] : (NMOT | -dx[k]));
                        drawbuf[j++] = MOT | VMOT | ((dy[k] >= 0) ? dy[k] : (NMOT | -dy[k]));
                }
                if (type == DRAWELLIPSE) {
                        drawbuf[5] = drawbuf[4] | NMOT; /* so the net vertical is zero */
                        j = 6;
                } else if (type == DRAWBUILD) {
                        drawbuf[4] = drawbuf[3] | NMOT; /* net horizontal motion is zero */
                        drawbuf[2] &= ~ZBIT;            /* width taken from drawing char */
                        j = 5;
                }
                drawbuf[j++] = DRAWFCN | chbits | ZBIT; /* marks end for ptout */
                drawbuf[j] = 0;
                pushback(drawbuf);
        }
}


void casefc(void)
{
        int i;
        Tchar j;

        gchtab[fc] &= ~FCBIT;
        fc = IMP;
        padc = ' ';
        if (skip() || ismot(j = getch()) || (i = cbits(j)) == '\n')
                return;
        fc = i;
        gchtab[fc] |= FCBIT;
        if (skip() || ismot(ch) || (ch = cbits(ch)) == fc)
                return;
        padc = ch;
}


Tchar setfield(int x)
{
        Tchar rchar, ii, jj, *fp;
        Tchar **pp, *padptr[NPP];
        Tchar fbuf[FBUFSZ];
        int i, j, length, ws, npad, temp, type, savepos, savfc, savtc, savlc;
        static Tchar wbuf[] = { WORDSP, 0};

        if (x == tabch) 
                rchar = tabc | chbits;
        else if (x == ldrch) 
                rchar = dotc | chbits;
        else
                rchar = 0;
        temp = npad = ws = 0;
        savfc = fc;
        savtc = tabch;
        savlc = ldrch;
        tabch = ldrch = fc = IMP;
        savepos = numtabp[HP].val;
        gchtab[tabch] &= ~TABBIT;
        gchtab[ldrch] &= ~LDRBIT;
        gchtab[fc] &= ~FCBIT;
        gchtab[IMP] |= TABBIT|LDRBIT|FCBIT;
        for (j = 0; ; j++) {
                if ((tabtab[j] & TABMASK) == 0) {
                        if (x == savfc)
                                ERROR "zero field width." WARN;
                        jj = 0;
                        goto rtn;
                }
                if ((length = ((tabtab[j] & TABMASK) - numtabp[HP].val)) > 0 )
                        break;
        }
        type = tabtab[j] & ~TABMASK;
        fp = fbuf;
        pp = padptr;
        if (x == savfc) {
                while (1) {
                        j = cbits(ii = getch());
                        jj = width(ii);
                        widthp = jj;
                        numtabp[HP].val += jj;
                        if (j == padc) {
                                npad++;
                                *pp++ = fp;
                                if (pp > padptr + NPP - 1)
                                        break;
                                goto s1;
                        } else if (j == savfc) 
                                break;
                        else if (j == '\n') {
                                temp = j;
                                if (nlflg && ip == 0) {
                                        numtabp[CD].val--;
                                        nlflg = 0;
                                }
                                break;
                        }
                        ws += jj;
s1:
                        *fp++ = ii;
                        if (fp > fbuf + FBUFSZ - 3)
                                break;
                }
                if (ws)
                        *fp++ = WORDSP;
                if (!npad) {
                        npad++;
                        *pp++ = fp;
                        *fp++ = 0;
                }
                *fp++ = temp;
                *fp = 0;
                temp = i = (j = length - ws) / npad;
                i = (i / HOR) * HOR;
                if ((j -= i * npad) < 0)
                        j = -j;
                ii = makem(i);
                if (temp < 0)
                        ii |= NMOT;
                for (; npad > 0; npad--) {
                        *(*--pp) = ii;
                        if (j) {
                                j -= HOR;
                                (*(*pp)) += HOR;
                        }
                }
                pushback(fbuf);
                jj = 0;
        } else if (type == 0) {
                /*plain tab or leader*/
                if ((j = width(rchar)) > 0) {
                        int nchar = length / j;
                        while (nchar-->0 && pbp < &pbbuf[NC-3]) {
                                numtabp[HP].val += j;
                                widthp = j;
                                *pbp++ = rchar;
                        }
                        length %= j;
                }
                if (length)
                        jj = length | MOT;
                else 
                        jj = getch0();
                if (savepos > 0)
                        pushback(wbuf);
        } else {
                /*center tab*/
                /*right tab*/
                while ((j = cbits(ii = getch())) != savtc && j != '\n' && j != savlc) {
                        jj = width(ii);
                        ws += jj;
                        numtabp[HP].val += jj;
                        widthp = jj;
                        *fp++ = ii;
                        if (fp > fbuf + FBUFSZ - 3) 
                                break;
                }
                *fp++ = ii;
                *fp = 0;
                if (type == RTAB)
                        length -= ws;
                else 
                        length -= ws / 2; /*CTAB*/
                pushback(fbuf);
                if ((j = width(rchar)) != 0 && length > 0) {
                        int nchar = length / j;
                        while (nchar-- > 0 && pbp < &pbbuf[NC-3])
                                *pbp++ = rchar;
                        length %= j;
                }
                if (savepos > 0)
                        pushback(wbuf);
                length = (length / HOR) * HOR;
                jj = makem(length);
                if (nlflg) {
                        if (ip == 0)
                                numtabp[CD].val--;
                        nlflg = 0;
                }
        }
rtn:
        gchtab[fc] &= ~FCBIT;
        gchtab[tabch] &= ~TABBIT;
        gchtab[ldrch] &= ~LDRBIT;
        fc = savfc;
        tabch = savtc;
        ldrch = savlc;
        gchtab[fc] |= FCBIT;
        gchtab[tabch] = TABBIT;
        gchtab[ldrch] |= LDRBIT;
        numtabp[HP].val = savepos;
        return(jj);
}