| #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); |
| } |
| |
| int |
| 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 ii, jj, *fp; |
| int i, j; |
| int length, ws, npad, temp, type; |
| Tchar **pp, *padptr[NPP]; |
| Tchar fbuf[FBUFSZ]; |
| int savfc, savtc, savlc; |
| Tchar rchar; |
| int savepos; |
| static Tchar wbuf[] = { WORDSP, 0}; |
| |
| rchar = 0; |
| if (x == tabch) |
| rchar = tabc | chbits; |
| else if (x == ldrch) |
| rchar = dotc | chbits; |
| 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); |
| } |