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
setz()75 setz()
76 {
77 tchar i;
78
79 if (!ismot(i = getch()))
80 i |= ZBIT;
81 return (i);
82 }
83
84 int
setline()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
eat(c)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
setov()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
setbra()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
setvline()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
setdraw()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
casefc()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
setfield(x)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
localize()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