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 2003 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 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
33 * All Rights Reserved
34 *
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
37 * contributors.
38 */
39
40 #pragma ident "%Z%%M% %I% %E% SMI"
41
42 /*
43 n10.c
44
45 Device interfaces
46 */
47
48 #include <limits.h>
49 #include <ctype.h>
50 #include <sys/types.h>
51 #include <sys/stat.h>
52 #ifdef EUC
53 #ifdef NROFF
54 #include <stdlib.h>
55 #endif /* NROFF */
56 #endif /* EUC */
57 #include "tdef.h"
58 #include "ext.h"
59 #include "tw.h"
60
61 struct t t; /* terminal characteristics */
62
63 int dtab;
64 int plotmode;
65 int esct;
66
67 char xchname[4 * (NROFFCHARS-_SPECCHAR_ST)]; /* hy, em, etc. */
68 short xchtab[NROFFCHARS-_SPECCHAR_ST]; /* indexes into chname[] */
69 char *codestr;
70 char *chname = xchname;
71 short *chtab = xchtab;
72 int nchtab = 0;
73
74
75 int Inch;
76 int Hor;
77 int Vert;
78 int nfonts = 4; /* R, I, B, S */
79
80 /* these characters are used as various signals or values
81 * in miscellaneous places.
82 * values are set in specnames in t10.c
83 */
84
85 int c_hyphen;
86 int c_emdash;
87 int c_rule;
88 int c_minus;
89 int c_fi;
90 int c_fl;
91 int c_ff;
92 int c_ffi;
93 int c_ffl;
94 int c_acute;
95 int c_grave;
96 int c_under;
97 int c_rooten;
98 int c_boxrule;
99 int c_lefthand;
100 int c_dagger;
101 int c_isalnum;
102
103 int
ptinit()104 ptinit()
105 {
106 int i, j;
107 char *p, *cp, *q;
108 int nread, fd;
109 extern char *skipstr(), *getstr(), *getint();
110 extern char *setbrk();
111 struct stat stbuf;
112 char check[50];
113
114 strcat(termtab, devname);
115 if ((fd = open(termtab, 0)) < 0) {
116 errprint(gettext("cannot open %s"), termtab);
117 exit(-1);
118 }
119
120 fstat(fd, &stbuf);
121 codestr = setbrk((int) stbuf.st_size);
122
123 nread = read(fd, codestr, (int) stbuf.st_size);
124 close(fd);
125
126 p = codestr;
127 p = skipstr(p); /* skip over type, could check */
128 p = skipstr(p); p = getint(p, &t.bset);
129 p = skipstr(p); p = getint(p, &t.breset);
130 p = skipstr(p); p = getint(p, &t.Hor);
131 p = skipstr(p); p = getint(p, &t.Vert);
132 p = skipstr(p); p = getint(p, &t.Newline);
133 p = skipstr(p); p = getint(p, &t.Char);
134 p = skipstr(p); p = getint(p, &t.Em);
135 p = skipstr(p); p = getint(p, &t.Halfline);
136 p = skipstr(p); p = getint(p, &t.Adj);
137 p = skipstr(p); p = getstr(p, t.twinit = p);
138 p = skipstr(p); p = getstr(p, t.twrest = p);
139 p = skipstr(p); p = getstr(p, t.twnl = p);
140 p = skipstr(p); p = getstr(p, t.hlr = p);
141 p = skipstr(p); p = getstr(p, t.hlf = p);
142 p = skipstr(p); p = getstr(p, t.flr = p);
143 p = skipstr(p); p = getstr(p, t.bdon = p);
144 p = skipstr(p); p = getstr(p, t.bdoff = p);
145 p = skipstr(p); p = getstr(p, t.iton = p);
146 p = skipstr(p); p = getstr(p, t.itoff = p);
147 p = skipstr(p); p = getstr(p, t.ploton = p);
148 p = skipstr(p); p = getstr(p, t.plotoff = p);
149 p = skipstr(p); p = getstr(p, t.up = p);
150 p = skipstr(p); p = getstr(p, t.down = p);
151 p = skipstr(p); p = getstr(p, t.right = p);
152 p = skipstr(p); p = getstr(p, t.left = p);
153
154 getstr(p, check);
155 if (strcmp(check, "charset") != 0) {
156 errprint(gettext("device table apparently curdled"));
157 exit(1);
158 }
159
160 for (i = 0; i < _SPECCHAR_ST; i++)
161 t.width[i] = 1; /* default widths */
162
163 i = 0;
164 /* this ought to be a pointer array and in place in codestr */
165 cp = chname + 1; /* bug if starts at 0, in setch */
166 while (p < codestr + nread) {
167 while (*p == ' ' || *p == '\t' || *p == '\n')
168 p++;
169 if (i + _SPECCHAR_ST >= NROFFCHARS) {
170 errprint(gettext("too many names in charset for %s"),
171 termtab);
172 exit(1);
173 }
174 chtab[i] = cp - chname; /* index, not pointer */
175 *cp++ = *p++; /* 2-char names */
176 *cp++ = *p++;
177 *cp++ = '\0';
178 while (*p == ' ' || *p == '\t')
179 p++;
180 t.width[i+_SPECCHAR_ST] = *p++ - '0';
181 while (*p == ' ' || *p == '\t')
182 p++;
183 t.codetab[i] = p;
184 p = getstr(p, p); /* compress string */
185 p++;
186 i++;
187 nchtab++;
188 }
189
190 sps = EM;
191 ics = EM * 2;
192 dtab = 8 * t.Em;
193 for (i = 0; i < 16; i++)
194 tabtab[i] = dtab * (i + 1);
195 pl = 11 * INCH;
196 po = PO;
197 spacesz = SS;
198 lss = lss1 = VS;
199 ll = ll1 = lt = lt1 = LL;
200 smnt = nfonts = 5; /* R I B BI S */
201 specnames(); /* install names like "hyphen", etc. */
202 if (eqflg)
203 t.Adj = t.Hor;
204
205 return (0);
206 }
207
skipstr(s)208 char *skipstr(s) /* skip over leading space plus string */
209 char *s;
210 {
211 while (*s == ' ' || *s == '\t' || *s == '\n')
212 s++;
213 while (*s != ' ' && *s != '\t' && *s != '\n')
214 if (*s++ == '\\')
215 s++;
216 return s;
217 }
218
getstr(s,t)219 char *getstr(s, t) /* find next string in s, copy to t */
220 char *s, *t;
221 {
222 int quote = 0;
223
224 while (*s == ' ' || *s == '\t' || *s == '\n')
225 s++;
226 if (*s == '"') {
227 s++;
228 quote = 1;
229 }
230 for (;;) {
231 if (quote && *s == '"') {
232 s++;
233 break;
234 }
235 if (!quote && (*s == ' ' || *s == '\t' || *s == '\n'))
236 break;
237 if (*s != '\\')
238 *t++ = *s++;
239 else {
240 s++; /* skip \\ */
241 if (isdigit((unsigned char)s[0]) &&
242 isdigit((unsigned char)s[1]) &&
243 isdigit((unsigned char)s[2])) {
244 *t++ = (s[0]-'0')<<6 | (s[1]-'0')<<3 | s[2]-'0';
245 s += 2;
246 } else if (isdigit((unsigned char)s[0])) {
247 *t++ = *s - '0';
248 } else if (*s == 'b') {
249 *t++ = '\b';
250 } else if (*s == 'n') {
251 *t++ = '\n';
252 } else if (*s == 'r') {
253 *t++ = '\r';
254 } else if (*s == 't') {
255 *t++ = '\t';
256 } else {
257 *t++ = *s;
258 }
259 s++;
260 }
261 }
262 *t = '\0';
263 return s;
264 }
265
getint(s,pn)266 char *getint(s, pn) /* find integer at s */
267 char *s;
268 int *pn;
269 {
270 int base;
271
272 while (*s == ' ' || *s == '\t' || *s == '\n')
273 s++;
274 base = (*s == '0') ? 8 : 10;
275 *pn = 0;
276 while (isdigit((unsigned char)*s))
277 *pn = base * *pn + *s++ - '0';
278 return s;
279 }
280
281 int
specnames()282 specnames()
283 {
284 static struct {
285 int *n;
286 char *v;
287 } spnames[] = {
288 &c_hyphen, "hy",
289 &c_emdash, "em",
290 &c_rule, "ru",
291 &c_minus, "\\-",
292 &c_fi, "fi",
293 &c_fl, "fl",
294 &c_ff, "ff",
295 &c_ffi, "Fi",
296 &c_ffl, "Fl",
297 &c_acute, "aa",
298 &c_grave, "ga",
299 &c_under, "ul",
300 &c_rooten, "rn",
301 &c_boxrule, "br",
302 &c_lefthand, "lh",
303 &c_isalnum, "__",
304 0, 0
305 };
306 int i;
307
308 for (i = 0; spnames[i].n; i++)
309 *spnames[i].n = findch(spnames[i].v);
310 if (c_isalnum == 0)
311 c_isalnum = NROFFCHARS;
312
313 return (0);
314 }
315
316
317 int
findch(s)318 findch(s) /* find char s in chname */
319 char *s;
320 {
321 int i;
322
323 for (i = 0; chtab[i] != 0; i++)
324 if (strcmp(s, &chname[chtab[i]]) == 0)
325 return(i + _SPECCHAR_ST);
326 return(0);
327 }
328
329 int
twdone()330 twdone()
331 {
332 int waitf;
333
334 obufp = obuf;
335 if (t.twrest) /* has ptinit() been done yet? */
336 oputs(t.twrest);
337 flusho();
338 if (pipeflg) {
339 close(ptid);
340 wait(&waitf);
341 }
342 restore_tty();
343
344 return (0);
345 }
346
347
348 int
ptout(i)349 ptout(i)
350 tchar i;
351 {
352 *olinep++ = i;
353 if (olinep >= &oline[LNSIZE])
354 olinep--;
355 if (cbits(i) != '\n')
356 return (0);
357 olinep--;
358 lead += dip->blss + lss - t.Newline;
359 dip->blss = 0;
360 esct = esc = 0;
361 if (olinep > oline) {
362 move();
363 ptout1();
364 oputs(t.twnl);
365 } else {
366 lead += t.Newline;
367 move();
368 }
369 lead += dip->alss;
370 dip->alss = 0;
371 olinep = oline;
372
373 return (0);
374 }
375
376
377 int
ptout1()378 ptout1()
379 {
380 int k;
381 char *codep;
382 #ifdef EUC
383 #ifdef NROFF
384 int cnt;
385 tchar *qq;
386 #endif /* NROFF */
387 #endif /* EUC */
388 extern char *plot();
389 int w, j, phyw;
390 #ifdef EUC
391 #ifdef NROFF
392 int jj;
393 #endif /* NROFF */
394 #endif /* EUC */
395 tchar * q, i;
396 static int oxfont = FT; /* start off in roman */
397
398 for (q = oline; q < olinep; q++) {
399 i = *q;
400 if (ismot(i)) {
401 j = absmot(i);
402 if (isnmot(i))
403 j = -j;
404 if (isvmot(i))
405 lead += j;
406 else
407 esc += j;
408 continue;
409 }
410 if ((k = cbits(i)) <= 040) {
411 switch (k) {
412 case ' ': /*space*/
413 esc += t.Char;
414 break;
415 case '\033':
416 case '\007':
417 case '\016':
418 case '\017':
419 oput(k);
420 break;
421 }
422 continue;
423 }
424 #ifdef EUC
425 #ifdef NROFF
426 if (multi_locale && ((k & MBMASK) || (k & CSMASK))) {
427 cnt = 0;
428 while ((*q & MBMASK1) && (cnt + 1 < (int)MB_CUR_MAX)) {
429 cnt++;
430 q++;
431 }
432 if ((cnt && !(*q & CSMASK)) || (*q & MBMASK1)) {
433 q -= cnt;
434 cnt = 0;
435 *q &= ~0xfe00;
436 }
437 k = cbits(i = *q);
438 phyw = w = t.Char * csi_width[cs(i)];
439 } else {
440 #endif /* NROFF */
441 #endif /* EUC */
442 phyw = w = t.Char * t.width[k];
443 if (iszbit(i))
444 w = 0;
445 #ifdef EUC
446 #ifdef NROFF
447 }
448 #endif /* NROFF */
449 #endif /* EUC */
450 if (esc || lead)
451 move();
452 esct += w;
453 #ifndef EUC
454 xfont = fbits(i);
455 #else
456 #ifndef NROFF
457 xfont = fbits(i);
458 #else
459 #endif /* NROFF */
460 xfont = (fbits(*q) % NFONT); /* for invalid code */
461 #endif /* EUC */
462 if (xfont != oxfont) {
463 if (oxfont == ulfont || oxfont == BIFONT)
464 oputs(t.itoff);
465 if (bdtab[oxfont])
466 oputs(t.bdoff);
467 if (xfont == ulfont || xfont == BIFONT)
468 oputs(t.iton);
469 if (bdtab[xfont])
470 oputs(t.bdon);
471 oxfont = xfont;
472 }
473 if ((xfont == ulfont || xfont == BIFONT) && !(*t.iton & 0377)) {
474 for (j = w / t.Char; j > 0; j--)
475 oput('_');
476 for (j = w / t.Char; j > 0; j--)
477 oput('\b');
478 }
479 if ((j = bdtab[xfont]) && !(*t.bdon & 0377))
480 j++;
481 else
482 j = 1; /* number of overstrikes for bold */
483 if (k < 128) { /* ordinary ascii */
484 oput(k);
485 while (--j > 0) {
486 oput('\b');
487 oput(k);
488 }
489 #ifdef EUC
490 #ifdef NROFF
491 } else if (multi_locale && (k & CSMASK)) {
492 for (qq = q - cnt; qq <= q;)
493 oput(cbits(*qq++));
494 while (--j > 0) {
495 for (jj = cnt + 1; jj > 0; jj--)
496 oput('\b');
497 for (qq = q - cnt; qq <= q;)
498 oput(cbits(*qq++));
499 }
500 } else if (k < 256) {
501 /*
502 * Invalid character for C locale or
503 * non-printable 8-bit single byte
504 * character such as <no-break-sp>
505 * in ISO-8859-1
506 */
507 oput(k);
508 while (--j > 0) {
509 oput('\b');
510 oput(k);
511 }
512 #endif /* NROFF */
513 #endif /* EUC */
514 } else if (k >= nchtab + _SPECCHAR_ST) {
515 oput(k - nchtab - _SPECCHAR_ST);
516 } else {
517 int oj = j;
518 codep = t.codetab[k-_SPECCHAR_ST];
519 while (*codep != 0) {
520 if (*codep & 0200) {
521 codep = plot(codep);
522 oput(' ');
523 } else {
524 if (*codep == '%') /* escape */
525 codep++;
526 oput(*codep);
527 if (*codep == '\033')
528 oput(*++codep);
529 else if (*codep != '\b')
530 for (j = oj; --j > 0; ) {
531 oput('\b');
532 oput(*codep);
533 }
534 codep++;
535 }
536 }
537 }
538 if (!w)
539 for (j = phyw / t.Char; j > 0; j--)
540 oput('\b');
541 }
542
543 return (0);
544 }
545
546
plot(x)547 char *plot(x)
548 char *x;
549 {
550 int i;
551 char *j, *k;
552
553 oputs(t.ploton);
554 k = x;
555 if ((*k & 0377) == 0200)
556 k++;
557 for (; *k; k++) {
558 if (*k == '%') { /* quote char within plot mode */
559 oput(*++k);
560 } else if (*k & 0200) {
561 if (*k & 0100) {
562 if (*k & 040)
563 j = t.up;
564 else
565 j = t.down;
566 } else {
567 if (*k & 040)
568 j = t.left;
569 else
570 j = t.right;
571 }
572 if ((i = *k & 037) == 0) { /* 2nd 0200 turns it off */
573 ++k;
574 break;
575 }
576 while (i--)
577 oputs(j);
578 } else
579 oput(*k);
580 }
581 oputs(t.plotoff);
582 return(k);
583 }
584
585
586 int
move()587 move()
588 {
589 int k;
590 char *i, *j;
591 char *p, *q;
592 int iesct, dt;
593
594 iesct = esct;
595 if (esct += esc)
596 i = "\0";
597 else
598 i = "\n\0";
599 j = t.hlf;
600 p = t.right;
601 q = t.down;
602 if (lead) {
603 if (lead < 0) {
604 lead = -lead;
605 i = t.flr;
606 /* if(!esct)i = t.flr; else i = "\0";*/
607 j = t.hlr;
608 q = t.up;
609 }
610 if (*i & 0377) {
611 k = lead / t.Newline;
612 lead = lead % t.Newline;
613 while (k--)
614 oputs(i);
615 }
616 if (*j & 0377) {
617 k = lead / t.Halfline;
618 lead = lead % t.Halfline;
619 while (k--)
620 oputs(j);
621 } else { /* no half-line forward, not at line begining */
622 k = lead / t.Newline;
623 lead = lead % t.Newline;
624 if (k > 0)
625 esc = esct;
626 i = "\n";
627 while (k--)
628 oputs(i);
629 }
630 }
631 if (esc) {
632 if (esc < 0) {
633 esc = -esc;
634 j = "\b";
635 p = t.left;
636 } else {
637 j = " ";
638 if (hflg)
639 while ((dt = dtab - (iesct % dtab)) <= esc) {
640 if (dt % t.Em)
641 break;
642 oput(TAB);
643 esc -= dt;
644 iesct += dt;
645 }
646 }
647 k = esc / t.Em;
648 esc = esc % t.Em;
649 while (k--)
650 oputs(j);
651 }
652 if ((*t.ploton & 0377) && (esc || lead)) {
653 oputs(t.ploton);
654 esc /= t.Hor;
655 lead /= t.Vert;
656 while (esc--)
657 oputs(p);
658 while (lead--)
659 oputs(q);
660 oputs(t.plotoff);
661 }
662 esc = lead = 0;
663
664 return (0);
665 }
666
667
668 int
ptlead()669 ptlead()
670 {
671 move();
672
673 return (0);
674 }
675
676
677 int
dostop()678 dostop()
679 {
680 char junk;
681
682 flusho();
683 read(2, &junk, 1);
684
685 return (0);
686 }
687
688 int
newpage()689 newpage()
690 {
691 return (0);
692 }
693
694
695 int
pttrailer()696 pttrailer()
697 {
698 return (0);
699 }
700