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