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