n9.c (9091B)
1 #include "tdef.h" 2 #include "ext.h" 3 #include "fns.h" 4 5 /* 6 * troff9.c 7 * 8 * misc functions 9 */ 10 11 Tchar setz(void) 12 { 13 Tchar i; 14 15 if (!ismot(i = getch())) 16 i |= ZBIT; 17 return(i); 18 } 19 20 void setline(void) 21 { 22 Tchar *i; 23 Tchar c; 24 int length; 25 int j, w, cnt, delim, rem, temp; 26 Tchar linebuf[NC]; 27 28 if (ismot(c = getch())) 29 return; 30 delim = cbits(c); 31 vflag = 0; 32 dfact = EM; 33 length = quant(atoi0(), HOR); 34 dfact = 1; 35 if (!length) { 36 eat(delim); 37 return; 38 } 39 s0: 40 if ((j = cbits(c = getch())) == delim || j == '\n') { 41 ch = c; 42 c = RULE | chbits; 43 } else if (cbits(c) == FILLER) 44 goto s0; 45 w = width(c); 46 if (w <= 0) { 47 ERROR "zero-width underline character ignored" WARN; 48 c = RULE | chbits; 49 w = width(c); 50 } 51 i = linebuf; 52 if (length < 0) { 53 *i++ = makem(length); 54 length = -length; 55 } 56 if (!(cnt = length / w)) { 57 *i++ = makem(-(temp = ((w - length) / 2))); 58 *i++ = c; 59 *i++ = makem(-(w - length - temp)); 60 goto s1; 61 } 62 if (rem = length % w) { 63 if (cbits(c) == RULE || cbits(c) == UNDERLINE || cbits(c) == ROOTEN) 64 *i++ = c | ZBIT; 65 *i++ = makem(rem); 66 } 67 if (cnt) { 68 *i++ = RPT; 69 *i++ = cnt; 70 *i++ = c; 71 } 72 s1: 73 *i = 0; 74 eat(delim); 75 pushback(linebuf); 76 } 77 78 int 79 eat(int c) 80 { 81 int i; 82 83 while ((i = cbits(getch())) != c && i != '\n') 84 ; 85 return(i); 86 } 87 88 89 void setov(void) 90 { 91 int j, k; 92 Tchar i, o[NOV+1]; 93 int delim, w[NOV+1]; 94 95 if (ismot(i = getch())) 96 return; 97 delim = cbits(i); 98 for (k = 0; k < NOV && (j = cbits(i = getch())) != delim && j != '\n'; k++) { 99 o[k] = i; 100 w[k] = width(i); 101 } 102 o[k] = w[k] = 0; 103 if (o[0]) 104 for (j = 1; j; ) { 105 j = 0; 106 for (k = 1; o[k] ; k++) { 107 if (w[k-1] < w[k]) { 108 j++; 109 i = w[k]; 110 w[k] = w[k-1]; 111 w[k-1] = i; 112 i = o[k]; 113 o[k] = o[k-1]; 114 o[k-1] = i; 115 } 116 } 117 } 118 else 119 return; 120 *pbp++ = makem(w[0] / 2); 121 for (k = 0; o[k]; k++) 122 ; 123 while (k>0) { 124 k--; 125 *pbp++ = makem(-((w[k] + w[k+1]) / 2)); 126 *pbp++ = o[k]; 127 } 128 } 129 130 131 void setbra(void) 132 { 133 int k; 134 Tchar i, *j, dwn; 135 int cnt, delim; 136 Tchar brabuf[NC]; 137 138 if (ismot(i = getch())) 139 return; 140 delim = cbits(i); 141 j = brabuf + 1; 142 cnt = 0; 143 if (NROFF) 144 dwn = (2 * t.Halfline) | MOT | VMOT; 145 else 146 dwn = EM | MOT | VMOT; 147 while ((k = cbits(i = getch())) != delim && k != '\n' && j <= brabuf + NC - 4) { 148 *j++ = i | ZBIT; 149 *j++ = dwn; 150 cnt++; 151 } 152 if (--cnt < 0) 153 return; 154 else if (!cnt) { 155 ch = *(j - 2); 156 return; 157 } 158 *j = 0; 159 if (NROFF) 160 *--j = *brabuf = (cnt * t.Halfline) | MOT | NMOT | VMOT; 161 else 162 *--j = *brabuf = (cnt * EM) / 2 | MOT | NMOT | VMOT; 163 *--j &= ~ZBIT; 164 pushback(brabuf); 165 } 166 167 168 void setvline(void) 169 { 170 int i; 171 Tchar c, rem, ver, neg; 172 int cnt, delim, v; 173 Tchar vlbuf[NC]; 174 Tchar *vlp; 175 176 if (ismot(c = getch())) 177 return; 178 delim = cbits(c); 179 dfact = lss; 180 vflag++; 181 i = quant(atoi0(), VERT); 182 dfact = 1; 183 if (!i) { 184 eat(delim); 185 vflag = 0; 186 return; 187 } 188 if ((cbits(c = getch())) == delim) { 189 c = BOXRULE | chbits; /*default box rule*/ 190 } else 191 getch(); 192 c |= ZBIT; 193 neg = 0; 194 if (i < 0) { 195 i = -i; 196 neg = NMOT; 197 } 198 if (NROFF) 199 v = 2 * t.Halfline; 200 else { 201 v = EM; 202 if (v < VERT) /* ATT EVK hack: Erik van Konijnenburg, */ 203 v = VERT; /* hvlpb!evkonij, ATT NSI Hilversum, Holland */ 204 } 205 206 cnt = i / v; 207 rem = makem(i % v) | neg; 208 ver = makem(v) | neg; 209 vlp = vlbuf; 210 if (!neg) 211 *vlp++ = ver; 212 if (absmot(rem) != 0) { 213 *vlp++ = c; 214 *vlp++ = rem; 215 } 216 while (vlp < vlbuf + NC - 3 && cnt--) { 217 *vlp++ = c; 218 *vlp++ = ver; 219 } 220 *(vlp - 2) &= ~ZBIT; 221 if (!neg) 222 vlp--; 223 *vlp = 0; 224 pushback(vlbuf); 225 vflag = 0; 226 } 227 228 #define NPAIR (NC/2-6) /* max pairs in spline, etc. */ 229 230 void setdraw(void) /* generate internal cookies for a drawing function */ 231 { 232 int i, j, k, dx[NPAIR], dy[NPAIR], delim, type; 233 Tchar c, drawbuf[NC]; 234 int drawch = '.'; /* character to draw with */ 235 236 /* input is \D'f dx dy dx dy ... c' (or at least it had better be) */ 237 /* this does drawing function f with character c and the */ 238 /* specified dx,dy pairs interpreted as appropriate */ 239 /* pairs are deltas from last point, except for radii */ 240 241 /* l dx dy: line from here by dx,dy */ 242 /* c x: circle of diameter x, left side here */ 243 /* e x y: ellipse of diameters x,y, left side here */ 244 /* a dx1 dy1 dx2 dy2: 245 ccw arc: ctr at dx1,dy1, then end at dx2,dy2 from there */ 246 /* ~ dx1 dy1 dx2 dy2...: 247 spline to dx1,dy1 to dx2,dy2 ... */ 248 /* b x c: 249 built-up character of type c, ht x */ 250 /* f dx dy ...: f is any other char: like spline */ 251 252 if (ismot(c = getch())) 253 return; 254 delim = cbits(c); 255 numerr.escarg = type = cbits(getch()); 256 if (type == '~') /* head off the .tr ~ problem */ 257 type = 's'; 258 for (i = 0; i < NPAIR ; i++) { 259 skip(); 260 vflag = 0; 261 dfact = EM; 262 dx[i] = quant(atoi0(), HOR); 263 if (dx[i] > MAXMOT) 264 dx[i] = MAXMOT; 265 else if (dx[i] < -MAXMOT) 266 dx[i] = -MAXMOT; 267 skip(); 268 if (type == 'c') { 269 dy[i] = 0; 270 goto eat; 271 } 272 vflag = 1; 273 dfact = lss; 274 dy[i] = quant(atoi0(), VERT); 275 if (dy[i] > MAXMOT) 276 dy[i] = MAXMOT; 277 else if (dy[i] < -MAXMOT) 278 dy[i] = -MAXMOT; 279 eat: 280 if (cbits(c = getch()) != ' ') { /* must be the end */ 281 if (cbits(c) != delim) { 282 drawch = cbits(c); 283 getch(); 284 } 285 i++; 286 break; 287 } 288 } 289 dfact = 1; 290 vflag = 0; 291 if (TROFF) { 292 drawbuf[0] = DRAWFCN | chbits | ZBIT; 293 drawbuf[1] = type | chbits | ZBIT; 294 drawbuf[2] = drawch | chbits | ZBIT; 295 for (k = 0, j = 3; k < i; k++) { 296 drawbuf[j++] = MOT | ((dx[k] >= 0) ? dx[k] : (NMOT | -dx[k])); 297 drawbuf[j++] = MOT | VMOT | ((dy[k] >= 0) ? dy[k] : (NMOT | -dy[k])); 298 } 299 if (type == DRAWELLIPSE) { 300 drawbuf[5] = drawbuf[4] | NMOT; /* so the net vertical is zero */ 301 j = 6; 302 } else if (type == DRAWBUILD) { 303 drawbuf[4] = drawbuf[3] | NMOT; /* net horizontal motion is zero */ 304 drawbuf[2] &= ~ZBIT; /* width taken from drawing char */ 305 j = 5; 306 } 307 drawbuf[j++] = DRAWFCN | chbits | ZBIT; /* marks end for ptout */ 308 drawbuf[j] = 0; 309 pushback(drawbuf); 310 } 311 } 312 313 314 void casefc(void) 315 { 316 int i; 317 Tchar j; 318 319 gchtab[fc] &= ~FCBIT; 320 fc = IMP; 321 padc = ' '; 322 if (skip() || ismot(j = getch()) || (i = cbits(j)) == '\n') 323 return; 324 fc = i; 325 gchtab[fc] |= FCBIT; 326 if (skip() || ismot(ch) || (ch = cbits(ch)) == fc) 327 return; 328 padc = ch; 329 } 330 331 332 Tchar setfield(int x) 333 { 334 Tchar ii, jj, *fp; 335 int i, j; 336 int length, ws, npad, temp, type; 337 Tchar **pp, *padptr[NPP]; 338 Tchar fbuf[FBUFSZ]; 339 int savfc, savtc, savlc; 340 Tchar rchar; 341 int savepos; 342 static Tchar wbuf[] = { WORDSP, 0}; 343 344 rchar = 0; 345 if (x == tabch) 346 rchar = tabc | chbits; 347 else if (x == ldrch) 348 rchar = dotc | chbits; 349 temp = npad = ws = 0; 350 savfc = fc; 351 savtc = tabch; 352 savlc = ldrch; 353 tabch = ldrch = fc = IMP; 354 savepos = numtabp[HP].val; 355 gchtab[tabch] &= ~TABBIT; 356 gchtab[ldrch] &= ~LDRBIT; 357 gchtab[fc] &= ~FCBIT; 358 gchtab[IMP] |= TABBIT|LDRBIT|FCBIT; 359 for (j = 0; ; j++) { 360 if ((tabtab[j] & TABMASK) == 0) { 361 if (x == savfc) 362 ERROR "zero field width." WARN; 363 jj = 0; 364 goto rtn; 365 } 366 if ((length = ((tabtab[j] & TABMASK) - numtabp[HP].val)) > 0 ) 367 break; 368 } 369 type = tabtab[j] & ~TABMASK; 370 fp = fbuf; 371 pp = padptr; 372 if (x == savfc) { 373 while (1) { 374 j = cbits(ii = getch()); 375 jj = width(ii); 376 widthp = jj; 377 numtabp[HP].val += jj; 378 if (j == padc) { 379 npad++; 380 *pp++ = fp; 381 if (pp > padptr + NPP - 1) 382 break; 383 goto s1; 384 } else if (j == savfc) 385 break; 386 else if (j == '\n') { 387 temp = j; 388 if (nlflg && ip == 0) { 389 numtabp[CD].val--; 390 nlflg = 0; 391 } 392 break; 393 } 394 ws += jj; 395 s1: 396 *fp++ = ii; 397 if (fp > fbuf + FBUFSZ - 3) 398 break; 399 } 400 if (ws) 401 *fp++ = WORDSP; 402 if (!npad) { 403 npad++; 404 *pp++ = fp; 405 *fp++ = 0; 406 } 407 *fp++ = temp; 408 *fp = 0; 409 temp = i = (j = length - ws) / npad; 410 i = (i / HOR) * HOR; 411 if ((j -= i * npad) < 0) 412 j = -j; 413 ii = makem(i); 414 if (temp < 0) 415 ii |= NMOT; 416 for (; npad > 0; npad--) { 417 *(*--pp) = ii; 418 if (j) { 419 j -= HOR; 420 (*(*pp)) += HOR; 421 } 422 } 423 pushback(fbuf); 424 jj = 0; 425 } else if (type == 0) { 426 /*plain tab or leader*/ 427 if ((j = width(rchar)) > 0) { 428 int nchar = length / j; 429 while (nchar-->0 && pbp < &pbbuf[NC-3]) { 430 numtabp[HP].val += j; 431 widthp = j; 432 *pbp++ = rchar; 433 } 434 length %= j; 435 } 436 if (length) 437 jj = length | MOT; 438 else 439 jj = getch0(); 440 if (savepos > 0) 441 pushback(wbuf); 442 } else { 443 /*center tab*/ 444 /*right tab*/ 445 while ((j = cbits(ii = getch())) != savtc && j != '\n' && j != savlc) { 446 jj = width(ii); 447 ws += jj; 448 numtabp[HP].val += jj; 449 widthp = jj; 450 *fp++ = ii; 451 if (fp > fbuf + FBUFSZ - 3) 452 break; 453 } 454 *fp++ = ii; 455 *fp = 0; 456 if (type == RTAB) 457 length -= ws; 458 else 459 length -= ws / 2; /*CTAB*/ 460 pushback(fbuf); 461 if ((j = width(rchar)) != 0 && length > 0) { 462 int nchar = length / j; 463 while (nchar-- > 0 && pbp < &pbbuf[NC-3]) 464 *pbp++ = rchar; 465 length %= j; 466 } 467 if (savepos > 0) 468 pushback(wbuf); 469 length = (length / HOR) * HOR; 470 jj = makem(length); 471 if (nlflg) { 472 if (ip == 0) 473 numtabp[CD].val--; 474 nlflg = 0; 475 } 476 } 477 rtn: 478 gchtab[fc] &= ~FCBIT; 479 gchtab[tabch] &= ~TABBIT; 480 gchtab[ldrch] &= ~LDRBIT; 481 fc = savfc; 482 tabch = savtc; 483 ldrch = savlc; 484 gchtab[fc] |= FCBIT; 485 gchtab[tabch] = TABBIT; 486 gchtab[ldrch] |= LDRBIT; 487 numtabp[HP].val = savepos; 488 return(jj); 489 }