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 #include <libintl.h> 40 #include <stdlib.h> 41 42 #include "tdef.h" 43 #ifdef NROFF 44 #include "tw.h" 45 #endif 46 #include "ext.h" 47 #ifdef EUC 48 #include <locale.h> 49 #include <wctype.h> 50 #include <langinfo.h> 51 52 #define ISO646 "646" 53 54 int multi_locale; 55 int (*wdbdg)(wchar_t, wchar_t, int); 56 wchar_t *(*wddlm)(wchar_t, wchar_t, int); 57 58 int csi_width[4] = { 59 1, 60 1, 61 2, 62 3, 63 }; 64 #endif /* EUC */ 65 66 /* 67 * troff9.c 68 * 69 * misc functions 70 */ 71 72 tchar 73 setz(void) 74 { 75 tchar i; 76 77 if (!ismot(i = getch())) 78 i |= ZBIT; 79 return (i); 80 } 81 82 int 83 setline(void) 84 { 85 tchar *i; 86 tchar c; 87 int length; 88 int w, cnt, delim, rem, temp; 89 tchar linebuf[NC]; 90 91 if (ismot(c = getch())) 92 return (0); 93 delim = cbits(c); 94 vflag = 0; 95 dfact = EM; 96 length = quant(atoi(), HOR); 97 dfact = 1; 98 if (!length) { 99 eat(delim); 100 return (0); 101 } 102 s0: 103 if ((cbits(c = getch())) == delim) { 104 ch = c; 105 c = RULE | chbits; 106 } else if (cbits(c) == FILLER) 107 goto s0; 108 w = width(c); 109 i = linebuf; 110 if (length < 0) { 111 *i++ = makem(length); 112 length = -length; 113 } 114 if (!(cnt = length / w)) { 115 *i++ = makem(-(temp = ((w - length) / 2))); 116 *i++ = c; 117 *i++ = makem(-(w - length - temp)); 118 goto s1; 119 } 120 if (rem = length % w) { 121 if (cbits(c) == RULE || cbits(c) == UNDERLINE || 122 cbits(c) == ROOTEN) 123 *i++ = c | ZBIT; 124 *i++ = makem(rem); 125 } 126 if (cnt) { 127 *i++ = RPT; 128 *i++ = cnt; 129 *i++ = c; 130 } 131 s1: 132 *i++ = 0; 133 eat(delim); 134 pushback(linebuf); 135 136 return (0); 137 } 138 139 140 int 141 eat(int c) 142 { 143 int i; 144 145 while ((i = cbits(getch())) != c && (i != '\n')) 146 ; 147 return (i); 148 } 149 150 151 int 152 setov(void) 153 { 154 int j, k; 155 tchar i, o[NOV]; 156 int delim, w[NOV]; 157 158 if (ismot(i = getch())) 159 return (0); 160 delim = cbits(i); 161 for (k = 0; (k < NOV) && ((j = cbits(i = getch())) != delim) && 162 (j != '\n'); k++) { 163 o[k] = i; 164 w[k] = width(i); 165 } 166 if (k >= NOV) { 167 k = NOV - 1; 168 } 169 o[k] = w[k] = 0; 170 if (o[0]) 171 for (j = 1; j; ) { 172 j = 0; 173 for (k = 1; o[k]; k++) { 174 if (w[k-1] < w[k]) { 175 j++; 176 i = w[k]; 177 w[k] = w[k-1]; 178 w[k-1] = i; 179 i = o[k]; 180 o[k] = o[k-1]; 181 o[k-1] = i; 182 } 183 } 184 } 185 else 186 return (0); 187 *pbp++ = makem(w[0] / 2); 188 for (k = 0; o[k]; k++) 189 ; 190 while (k > 0) { 191 k--; 192 *pbp++ = makem(-((w[k] + w[k+1]) / 2)); 193 *pbp++ = o[k]; 194 } 195 196 return (0); 197 } 198 199 200 int 201 setbra(void) 202 { 203 int k; 204 tchar i, *j, dwn; 205 int cnt, delim; 206 tchar brabuf[NC]; 207 208 if (ismot(i = getch())) 209 return (0); 210 delim = cbits(i); 211 j = brabuf + 1; 212 cnt = 0; 213 #ifdef NROFF 214 dwn = (2 * t.Halfline) | MOT | VMOT; 215 #endif 216 #ifndef NROFF 217 dwn = EM | MOT | VMOT; 218 #endif 219 while (((k = cbits(i = getch())) != delim) && (k != '\n') && 220 (j <= (brabuf + NC - 4))) { 221 *j++ = i | ZBIT; 222 *j++ = dwn; 223 cnt++; 224 } 225 if (--cnt < 0) 226 return (0); 227 else if (!cnt) { 228 ch = *(j - 2); 229 return (0); 230 } 231 *j = 0; 232 #ifdef NROFF 233 *--j = *brabuf = (cnt * t.Halfline) | MOT | NMOT | VMOT; 234 #endif 235 #ifndef NROFF 236 *--j = *brabuf = (cnt * EM) / 2 | MOT | NMOT | VMOT; 237 #endif 238 *--j &= ~ZBIT; 239 pushback(brabuf); 240 241 return (0); 242 } 243 244 245 int 246 setvline(void) 247 { 248 int i; 249 tchar c, rem, ver, neg; 250 int cnt, delim, v; 251 tchar vlbuf[NC]; 252 tchar *vlp; 253 254 if (ismot(c = getch())) 255 return (0); 256 delim = cbits(c); 257 dfact = lss; 258 vflag++; 259 i = quant(atoi(), VERT); 260 dfact = 1; 261 if (!i) { 262 eat(delim); 263 vflag = 0; 264 return (0); 265 } 266 if ((cbits(c = getch())) == delim) { 267 c = BOXRULE | chbits; /* default box rule */ 268 } else 269 getch(); 270 c |= ZBIT; 271 neg = 0; 272 if (i < 0) { 273 i = -i; 274 neg = NMOT; 275 } 276 #ifdef NROFF 277 v = 2 * t.Halfline; 278 #endif 279 #ifndef NROFF 280 v = EM; 281 #endif 282 cnt = i / v; 283 rem = makem(i % v) | neg; 284 ver = makem(v) | neg; 285 vlp = vlbuf; 286 if (!neg) 287 *vlp++ = ver; 288 if (absmot(rem) != 0) { 289 *vlp++ = c; 290 *vlp++ = rem; 291 } 292 while ((vlp < (vlbuf + NC - 3)) && cnt--) { 293 *vlp++ = c; 294 *vlp++ = ver; 295 } 296 *(vlp - 2) &= ~ZBIT; 297 if (!neg) 298 vlp--; 299 *vlp++ = 0; 300 pushback(vlbuf); 301 vflag = 0; 302 303 return (0); 304 } 305 306 #define NPAIR (NC/2-6) /* max pairs in spline, etc. */ 307 308 /* 309 * Generate internal cookies for a drawing function. 310 */ 311 int 312 setdraw(void) 313 { 314 int i, j, k, dx[NPAIR], dy[NPAIR], delim, type __unused; 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(void) 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(int x) 412 { 413 tchar ii, jj, *fp; 414 int i, j; 415 int length, ws, npad, temp, type; 416 tchar **pp, *padptr[NPP]; 417 tchar fbuf[FBUFSZ]; 418 int savfc, savtc, savlc; 419 tchar rchar; 420 int savepos; 421 422 if (x == tabch) 423 rchar = tabc | chbits; 424 else if (x == ldrch) 425 rchar = dotc | chbits; 426 temp = npad = ws = 0; 427 savfc = fc; 428 savtc = tabch; 429 savlc = ldrch; 430 tabch = ldrch = fc = IMP; 431 savepos = numtab[HP].val; 432 gchtab[tabch] &= ~TABBIT; 433 gchtab[ldrch] &= ~LDRBIT; 434 gchtab[fc] &= ~FCBIT; 435 gchtab[IMP] |= TABBIT|LDRBIT|FCBIT; 436 for (j = 0; ; j++) { 437 if ((tabtab[j] & TABMASK) == 0) { 438 if (x == savfc) 439 errprint(gettext("zero field width.")); 440 jj = 0; 441 goto rtn; 442 } 443 if ((length = ((tabtab[j] & TABMASK) - numtab[HP].val)) > 0) 444 break; 445 } 446 type = tabtab[j] & (~TABMASK); 447 fp = fbuf; 448 pp = padptr; 449 if (x == savfc) { 450 while (1) { 451 j = cbits(ii = getch()); 452 jj = width(ii); 453 widthp = jj; 454 numtab[HP].val += jj; 455 if (j == padc) { 456 npad++; 457 *pp++ = fp; 458 if (pp > (padptr + NPP - 1)) 459 break; 460 goto s1; 461 } else if (j == savfc) 462 break; 463 else if (j == '\n') { 464 temp = j; 465 nlflg = 0; 466 break; 467 } 468 ws += jj; 469 s1: 470 *fp++ = ii; 471 if (fp > (fbuf + FBUFSZ - 3)) 472 break; 473 } 474 if (!npad) { 475 npad++; 476 *pp++ = fp; 477 *fp++ = 0; 478 } 479 *fp++ = temp; 480 *fp++ = 0; 481 temp = i = (j = length - ws) / npad; 482 i = (i / HOR) * HOR; 483 if ((j -= i * npad) < 0) 484 j = -j; 485 ii = makem(i); 486 if (temp < 0) 487 ii |= NMOT; 488 for (; npad > 0; npad--) { 489 *(*--pp) = ii; 490 if (j) { 491 j -= HOR; 492 (*(*pp)) += HOR; 493 } 494 } 495 pushback(fbuf); 496 jj = 0; 497 } else if (type == 0) { 498 /* plain tab or leader */ 499 if ((j = width(rchar)) > 0) { 500 int nchar = length / j; 501 while (nchar-->0 && pbp < &pbbuf[NC-3]) { 502 numtab[HP].val += j; 503 widthp = j; 504 *pbp++ = rchar; 505 } 506 length %= j; 507 } 508 if (length) 509 jj = length | MOT; 510 else 511 jj = getch0(); 512 } else { 513 /* center tab */ 514 /* right tab */ 515 while (((j = cbits(ii = getch())) != savtc) && 516 (j != '\n') && (j != savlc)) { 517 jj = width(ii); 518 ws += jj; 519 numtab[HP].val += jj; 520 widthp = jj; 521 *fp++ = ii; 522 if (fp > (fbuf + FBUFSZ - 3)) 523 break; 524 } 525 *fp++ = ii; 526 *fp++ = 0; 527 if (type == RTAB) 528 length -= ws; 529 else 530 length -= ws / 2; /* CTAB */ 531 pushback(fbuf); 532 if ((j = width(rchar)) != 0 && length > 0) { 533 int nchar = length / j; 534 while (nchar-- > 0 && pbp < &pbbuf[NC-3]) 535 *pbp++ = rchar; 536 length %= j; 537 } 538 length = (length / HOR) * HOR; 539 jj = makem(length); 540 nlflg = 0; 541 } 542 rtn: 543 gchtab[fc] &= ~FCBIT; 544 gchtab[tabch] &= ~TABBIT; 545 gchtab[ldrch] &= ~LDRBIT; 546 fc = savfc; 547 tabch = savtc; 548 ldrch = savlc; 549 gchtab[fc] |= FCBIT; 550 gchtab[tabch] = TABBIT; 551 gchtab[ldrch] |= LDRBIT; 552 numtab[HP].val = savepos; 553 return (jj); 554 } 555 556 557 #ifdef EUC 558 #ifdef NROFF 559 /* locale specific initialization */ 560 int 561 localize(void) 562 { 563 extern int wdbindf(); 564 extern wchar_t *wddelim(); 565 char *codeset; 566 567 codeset = nl_langinfo(CODESET); 568 569 if (MB_CUR_MAX > 1) 570 multi_locale = 1; 571 else { 572 if (*codeset == '\0' || 573 (strcmp(codeset, ISO646) == 0)) { 574 /* 575 * if codeset is an empty string 576 * assumes this is C locale (7-bit) locale. 577 * This happens in 2.5, 2.5.1, and 2.6 system 578 * Or, if codeset is "646" 579 * this is 7-bit locale. 580 */ 581 multi_locale = 0; 582 } else { 583 /* 8-bit locale */ 584 multi_locale = 1; 585 } 586 587 } 588 wdbdg = wdbindf; 589 wddlm = wddelim; 590 591 return (0); 592 } 593 #endif /* EUC */ 594 #endif /* NROFF */ 595