1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1989 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 /* 34 * University Copyright- Copyright (c) 1982, 1986, 1988 35 * The Regents of the University of California 36 * All Rights Reserved 37 * 38 * University Acknowledgment- Portions of this document are derived from 39 * software developed by the University of California, Berkeley, and its 40 * contributors. 41 */ 42 43 #include <libintl.h> 44 #include <stdlib.h> 45 46 #include "tdef.h" 47 #ifdef NROFF 48 #include "tw.h" 49 #endif 50 #include "ext.h" 51 #ifdef EUC 52 #include <locale.h> 53 #include <wctype.h> 54 #include <langinfo.h> 55 56 #define ISO646 "646" 57 58 int multi_locale; 59 int (*wdbdg)(wchar_t, wchar_t, int); 60 wchar_t *(*wddlm)(wchar_t, wchar_t, int); 61 62 int csi_width[4] = { 63 1, 64 1, 65 2, 66 3, 67 }; 68 #endif /* EUC */ 69 70 /* 71 * troff9.c 72 * 73 * misc functions 74 */ 75 76 tchar setz() 77 { 78 tchar i; 79 80 if (!ismot(i = getch())) 81 i |= ZBIT; 82 return(i); 83 } 84 85 setline() 86 { 87 register tchar *i; 88 tchar c; 89 int length; 90 int w, cnt, delim, rem, temp; 91 tchar linebuf[NC]; 92 93 if (ismot(c = getch())) 94 return; 95 delim = cbits(c); 96 vflag = 0; 97 dfact = EM; 98 length = quant(atoi(), HOR); 99 dfact = 1; 100 if (!length) { 101 eat(delim); 102 return; 103 } 104 s0: 105 if ((cbits(c = getch())) == delim) { 106 ch = c; 107 c = RULE | chbits; 108 } else if (cbits(c) == FILLER) 109 goto s0; 110 w = width(c); 111 i = linebuf; 112 if (length < 0) { 113 *i++ = makem(length); 114 length = -length; 115 } 116 if (!(cnt = length / w)) { 117 *i++ = makem(-(temp = ((w - length) / 2))); 118 *i++ = c; 119 *i++ = makem(-(w - length - temp)); 120 goto s1; 121 } 122 if (rem = length % w) { 123 if (cbits(c) == RULE || cbits(c) == UNDERLINE || cbits(c) == ROOTEN) 124 *i++ = c | ZBIT; 125 *i++ = makem(rem); 126 } 127 if (cnt) { 128 *i++ = RPT; 129 *i++ = cnt; 130 *i++ = c; 131 } 132 s1: 133 *i++ = 0; 134 eat(delim); 135 pushback(linebuf); 136 } 137 138 139 eat(c) 140 register int c; 141 { 142 register i; 143 144 while ((i = cbits(getch())) != c && (i != '\n')) 145 ; 146 return(i); 147 } 148 149 150 setov() 151 { 152 register j, k; 153 tchar i, o[NOV]; 154 int delim, w[NOV]; 155 156 if (ismot(i = getch())) 157 return; 158 delim = cbits(i); 159 for (k = 0; (k < NOV) && ((j = cbits(i = getch())) != delim) && (j != '\n'); k++) { 160 o[k] = i; 161 w[k] = width(i); 162 } 163 o[k] = w[k] = 0; 164 if (o[0]) 165 for (j = 1; j; ) { 166 j = 0; 167 for (k = 1; o[k] ; k++) { 168 if (w[k-1] < w[k]) { 169 j++; 170 i = w[k]; 171 w[k] = w[k-1]; 172 w[k-1] = i; 173 i = o[k]; 174 o[k] = o[k-1]; 175 o[k-1] = i; 176 } 177 } 178 } 179 else 180 return; 181 *pbp++ = makem(w[0] / 2); 182 for (k = 0; o[k]; k++) 183 ; 184 while (k>0) { 185 k--; 186 *pbp++ = makem(-((w[k] + w[k+1]) / 2)); 187 *pbp++ = o[k]; 188 } 189 } 190 191 192 setbra() 193 { 194 register k; 195 tchar i, *j, dwn; 196 int cnt, delim; 197 tchar brabuf[NC]; 198 199 if (ismot(i = getch())) 200 return; 201 delim = cbits(i); 202 j = brabuf + 1; 203 cnt = 0; 204 #ifdef NROFF 205 dwn = (2 * t.Halfline) | MOT | VMOT; 206 #endif 207 #ifndef NROFF 208 dwn = EM | MOT | VMOT; 209 #endif 210 while (((k = cbits(i = getch())) != delim) && (k != '\n') && (j <= (brabuf + NC - 4))) { 211 *j++ = i | ZBIT; 212 *j++ = dwn; 213 cnt++; 214 } 215 if (--cnt < 0) 216 return; 217 else if (!cnt) { 218 ch = *(j - 2); 219 return; 220 } 221 *j = 0; 222 #ifdef NROFF 223 *--j = *brabuf = (cnt * t.Halfline) | MOT | NMOT | VMOT; 224 #endif 225 #ifndef NROFF 226 *--j = *brabuf = (cnt * EM) / 2 | MOT | NMOT | VMOT; 227 #endif 228 *--j &= ~ZBIT; 229 pushback(brabuf); 230 } 231 232 233 setvline() 234 { 235 register i; 236 tchar c, rem, ver, neg; 237 int cnt, delim, v; 238 tchar vlbuf[NC]; 239 register tchar *vlp; 240 241 if (ismot(c = getch())) 242 return; 243 delim = cbits(c); 244 dfact = lss; 245 vflag++; 246 i = quant(atoi(), VERT); 247 dfact = 1; 248 if (!i) { 249 eat(delim); 250 vflag = 0; 251 return; 252 } 253 if ((cbits(c = getch())) == delim) { 254 c = BOXRULE | chbits; /*default box rule*/ 255 } else 256 getch(); 257 c |= ZBIT; 258 neg = 0; 259 if (i < 0) { 260 i = -i; 261 neg = NMOT; 262 } 263 #ifdef NROFF 264 v = 2 * t.Halfline; 265 #endif 266 #ifndef NROFF 267 v = EM; 268 #endif 269 cnt = i / v; 270 rem = makem(i % v) | neg; 271 ver = makem(v) | neg; 272 vlp = vlbuf; 273 if (!neg) 274 *vlp++ = ver; 275 if (absmot(rem) != 0) { 276 *vlp++ = c; 277 *vlp++ = rem; 278 } 279 while ((vlp < (vlbuf + NC - 3)) && cnt--) { 280 *vlp++ = c; 281 *vlp++ = ver; 282 } 283 *(vlp - 2) &= ~ZBIT; 284 if (!neg) 285 vlp--; 286 *vlp++ = 0; 287 pushback(vlbuf); 288 vflag = 0; 289 } 290 291 #define NPAIR (NC/2-6) /* max pairs in spline, etc. */ 292 293 setdraw() /* generate internal cookies for a drawing function */ 294 { 295 int i, j, k, dx[NPAIR], dy[NPAIR], delim, type; 296 tchar c, drawbuf[NC]; 297 298 /* input is \D'f dx dy dx dy ... c' (or at least it had better be) */ 299 /* this does drawing function f with character c and the */ 300 /* specified dx,dy pairs interpreted as appropriate */ 301 /* pairs are deltas from last point, except for radii */ 302 303 /* l dx dy: line from here by dx,dy */ 304 /* c x: circle of diameter x, left side here */ 305 /* e x y: ellipse of diameters x,y, left side here */ 306 /* a dx1 dy1 dx2 dy2: 307 ccw arc: ctr at dx1,dy1, then end at dx2,dy2 from there */ 308 /* ~ dx1 dy1 dx2 dy2...: 309 spline to dx1,dy1 to dx2,dy2 ... */ 310 /* f dx dy ...: f is any other char: like spline */ 311 312 if (ismot(c = getch())) 313 return; 314 delim = cbits(c); 315 type = cbits(getch()); 316 for (i = 0; i < NPAIR ; i++) { 317 c = getch(); 318 if (cbits(c) == delim) 319 break; 320 /* ought to pick up optional drawing character */ 321 if (cbits(c) != ' ') 322 ch = c; 323 vflag = 0; 324 dfact = EM; 325 dx[i] = quant(atoi(), HOR); 326 if (dx[i] > MAXMOT) 327 dx[i] = MAXMOT; 328 else if (dx[i] < -MAXMOT) 329 dx[i] = -MAXMOT; 330 if (cbits((c = getch())) == delim) { /* spacer */ 331 dy[i++] = 0; 332 break; 333 } 334 vflag = 1; 335 dfact = lss; 336 dy[i] = quant(atoi(), VERT); 337 if (dy[i] > MAXMOT) 338 dy[i] = MAXMOT; 339 else if (dy[i] < -MAXMOT) 340 dy[i] = -MAXMOT; 341 } 342 dfact = 1; 343 vflag = 0; 344 #ifndef NROFF 345 drawbuf[0] = DRAWFCN | chbits | ZBIT; 346 drawbuf[1] = type | chbits | ZBIT; 347 drawbuf[2] = '.' | chbits | ZBIT; /* use default drawing character */ 348 for (k = 0, j = 3; k < i; k++) { 349 drawbuf[j++] = MOT | ((dx[k] >= 0) ? dx[k] : (NMOT | -dx[k])); 350 drawbuf[j++] = MOT | VMOT | ((dy[k] >= 0) ? dy[k] : (NMOT | -dy[k])); 351 } 352 if (type == DRAWELLIPSE) { 353 drawbuf[5] = drawbuf[4] | NMOT; /* so the net vertical is zero */ 354 j = 6; 355 } 356 drawbuf[j++] = DRAWFCN | chbits | ZBIT; /* marks end for ptout */ 357 drawbuf[j] = 0; 358 pushback(drawbuf); 359 #endif 360 } 361 362 363 casefc() 364 { 365 register i; 366 tchar j; 367 368 gchtab[fc] &= ~FCBIT; 369 fc = IMP; 370 padc = ' '; 371 if (skip() || ismot(j = getch()) || (i = cbits(j)) == '\n') 372 return; 373 fc = i; 374 gchtab[fc] |= FCBIT; 375 if (skip() || ismot(ch) || (ch = cbits(ch)) == fc) 376 return; 377 padc = ch; 378 } 379 380 381 tchar 382 setfield(x) 383 int x; 384 { 385 register tchar ii, jj, *fp; 386 register i, j; 387 int length, ws, npad, temp, type; 388 tchar **pp, *padptr[NPP]; 389 tchar fbuf[FBUFSZ]; 390 int savfc, savtc, savlc; 391 tchar rchar; 392 int savepos; 393 394 if (x == tabch) 395 rchar = tabc | chbits; 396 else if (x == ldrch) 397 rchar = dotc | chbits; 398 temp = npad = ws = 0; 399 savfc = fc; 400 savtc = tabch; 401 savlc = ldrch; 402 tabch = ldrch = fc = IMP; 403 savepos = numtab[HP].val; 404 gchtab[tabch] &= ~TABBIT; 405 gchtab[ldrch] &= ~LDRBIT; 406 gchtab[fc] &= ~FCBIT; 407 gchtab[IMP] |= TABBIT|LDRBIT|FCBIT; 408 for (j = 0; ; j++) { 409 if ((tabtab[j] & TABMASK) == 0) { 410 if (x == savfc) 411 errprint(gettext("zero field width.")); 412 jj = 0; 413 goto rtn; 414 } 415 if ((length = ((tabtab[j] & TABMASK) - numtab[HP].val)) > 0 ) 416 break; 417 } 418 type = tabtab[j] & (~TABMASK); 419 fp = fbuf; 420 pp = padptr; 421 if (x == savfc) { 422 while (1) { 423 j = cbits(ii = getch()); 424 jj = width(ii); 425 widthp = jj; 426 numtab[HP].val += jj; 427 if (j == padc) { 428 npad++; 429 *pp++ = fp; 430 if (pp > (padptr + NPP - 1)) 431 break; 432 goto s1; 433 } else if (j == savfc) 434 break; 435 else if (j == '\n') { 436 temp = j; 437 nlflg = 0; 438 break; 439 } 440 ws += jj; 441 s1: 442 *fp++ = ii; 443 if (fp > (fbuf + FBUFSZ - 3)) 444 break; 445 } 446 if (!npad) { 447 npad++; 448 *pp++ = fp; 449 *fp++ = 0; 450 } 451 *fp++ = temp; 452 *fp++ = 0; 453 temp = i = (j = length - ws) / npad; 454 i = (i / HOR) * HOR; 455 if ((j -= i * npad) < 0) 456 j = -j; 457 ii = makem(i); 458 if (temp < 0) 459 ii |= NMOT; 460 for (; npad > 0; npad--) { 461 *(*--pp) = ii; 462 if (j) { 463 j -= HOR; 464 (*(*pp)) += HOR; 465 } 466 } 467 pushback(fbuf); 468 jj = 0; 469 } else if (type == 0) { 470 /*plain tab or leader*/ 471 if ((j = width(rchar)) > 0) { 472 int nchar = length / j; 473 while (nchar-->0 && pbp < &pbbuf[NC-3]) { 474 numtab[HP].val += j; 475 widthp = j; 476 *pbp++ = rchar; 477 } 478 length %= j; 479 } 480 if (length) 481 jj = length | MOT; 482 else 483 jj = getch0(); 484 } else { 485 /*center tab*/ 486 /*right tab*/ 487 while (((j = cbits(ii = getch())) != savtc) && (j != '\n') && (j != savlc)) { 488 jj = width(ii); 489 ws += jj; 490 numtab[HP].val += jj; 491 widthp = jj; 492 *fp++ = ii; 493 if (fp > (fbuf + FBUFSZ - 3)) 494 break; 495 } 496 *fp++ = ii; 497 *fp++ = 0; 498 if (type == RTAB) 499 length -= ws; 500 else 501 length -= ws / 2; /*CTAB*/ 502 pushback(fbuf); 503 if ((j = width(rchar)) != 0 && length > 0) { 504 int nchar = length / j; 505 while (nchar-- > 0 && pbp < &pbbuf[NC-3]) 506 *pbp++ = rchar; 507 length %= j; 508 } 509 length = (length / HOR) * HOR; 510 jj = makem(length); 511 nlflg = 0; 512 } 513 rtn: 514 gchtab[fc] &= ~FCBIT; 515 gchtab[tabch] &= ~TABBIT; 516 gchtab[ldrch] &= ~LDRBIT; 517 fc = savfc; 518 tabch = savtc; 519 ldrch = savlc; 520 gchtab[fc] |= FCBIT; 521 gchtab[tabch] = TABBIT; 522 gchtab[ldrch] |= LDRBIT; 523 numtab[HP].val = savepos; 524 return(jj); 525 } 526 527 528 #ifdef EUC 529 #ifdef NROFF 530 /* locale specific initialization */ 531 int localize() 532 { 533 extern int wdbindf(); 534 extern wchar_t *wddelim(); 535 char *codeset; 536 537 codeset = nl_langinfo(CODESET); 538 539 if (MB_CUR_MAX > 1) 540 multi_locale = 1; 541 else { 542 if (*codeset == '\0' || 543 (strcmp(codeset, ISO646) == 0)) { 544 /* 545 * if codeset is an empty string 546 * assumes this is C locale (7-bit) locale. 547 * This happens in 2.5, 2.5.1, and 2.6 system 548 * Or, if codeset is "646" 549 * this is 7-bit locale. 550 */ 551 multi_locale = 0; 552 } else { 553 /* 8-bit locale */ 554 multi_locale = 1; 555 } 556 557 } 558 wdbdg = wdbindf; 559 wddlm = wddelim; 560 } 561 #endif /* EUC */ 562 #endif /* NROFF */ 563