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