1 #ifndef lint
2 static char sccsid[]="@(#)n10.c	1.2	(CWI)	86/08/15";
3 #endif
4 
5 /*
6 n10.c
7 
8 Device interfaces
9 */
10 
11 #include "tdef.h"
12 #include "ext.h"
13 #include "tw.h"
14 #include <sgtty.h>
15 #include <ctype.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 
19 struct t t;	/* terminal characteristics */
20 
21 int	dtab;
22 int	plotmode;
23 int	esct;
24 
25 char	xchname[4 * (NROFFCHARS-128)];	/* hy, em, etc. */
26 short	xchtab[NROFFCHARS-128];		/* indexes into chname[] */
27 char	*codestr;
28 char	*chname = xchname;
29 short	*chtab = xchtab;
30 
31 
32 int	Inch;
33 int	Hor;
34 int	Vert;
35 int	nfonts	= 4;	/* R, I, B, S */
36 
37 /* these characters are used as various signals or values
38 /* in miscellaneous places.
39 /* values are set in specnames in t10.c
40 */
41 
42 int	c_hyphen;
43 int	c_emdash;
44 int	c_rule;
45 int	c_minus;
46 int	c_fi;
47 int	c_fl;
48 int	c_ff;
49 int	c_ffi;
50 int	c_ffl;
51 int	c_acute;
52 int	c_grave;
53 int	c_under;
54 int	c_rooten;
55 int	c_boxrule;
56 int	c_lefthand;
57 int	c_dagger;
58 int	c_isalnum;
59 
60 ptinit()
61 {
62 	register int i, j;
63 	register char *p, *cp, *q;
64 	int nread, fd;
65 	extern char *skipstr(), *getstr(), *getint();
66 	extern char *setbrk();
67 	struct stat stbuf;
68 	char check[50];
69 
70 	strcat(termtab, devname);
71 	if ((fd = open(termtab, 0)) < 0) {
72 		errprint("cannot open %s", termtab);
73 		exit(-1);
74 	}
75 
76 	fstat(fd, &stbuf);
77 	codestr = setbrk((int) stbuf.st_size);
78 
79 	nread = read(fd, codestr, (int) stbuf.st_size);
80 	close(fd);
81 
82 	p = codestr;
83 	p = skipstr(p);		/* skip over type, could check */
84 	p = skipstr(p); p = getint(p, &t.bset);
85 	p = skipstr(p); p = getint(p, &t.breset);
86 	p = skipstr(p); p = getint(p, &t.Hor);
87 	p = skipstr(p); p = getint(p, &t.Vert);
88 	p = skipstr(p); p = getint(p, &t.Newline);
89 	p = skipstr(p); p = getint(p, &t.Char);
90 	p = skipstr(p); p = getint(p, &t.Em);
91 	p = skipstr(p); p = getint(p, &t.Halfline);
92 	p = skipstr(p); p = getint(p, &t.Adj);
93 	p = skipstr(p); p = getstr(p, t.twinit = p);
94 	p = skipstr(p); p = getstr(p, t.twrest = p);
95 	p = skipstr(p); p = getstr(p, t.twnl = p);
96 	p = skipstr(p); p = getstr(p, t.hlr = p);
97 	p = skipstr(p); p = getstr(p, t.hlf = p);
98 	p = skipstr(p); p = getstr(p, t.flr = p);
99 	p = skipstr(p); p = getstr(p, t.bdon = p);
100 	p = skipstr(p); p = getstr(p, t.bdoff = p);
101 	p = skipstr(p); p = getstr(p, t.iton = p);
102 	p = skipstr(p); p = getstr(p, t.itoff = p);
103 	p = skipstr(p); p = getstr(p, t.ploton = p);
104 	p = skipstr(p); p = getstr(p, t.plotoff = p);
105 	p = skipstr(p); p = getstr(p, t.up = p);
106 	p = skipstr(p); p = getstr(p, t.down = p);
107 	p = skipstr(p); p = getstr(p, t.right = p);
108 	p = skipstr(p); p = getstr(p, t.left = p);
109 	p = skipstr(p); p = getstr(p, t.eject = p);
110 
111 	getstr(p, check);
112 	if (strcmp(check, "charset") != 0) {
113 		errprint("device table apparently curdled");
114 		exit(1);
115 	}
116 
117 	for (i = 0; i < 128; i++)
118 		t.width[i] = 1;	/* default ascii widths */
119 
120 	i = 0;
121 /* this ought to be a pointer array and in place in codestr */
122 	cp = chname + 1;	/* bug if starts at 0, in setch */
123 	while (p < codestr + nread) {
124 		while (*p == ' ' || *p == '\t' || *p == '\n')
125 			p++;
126 		chtab[i] = cp - chname;	/* index, not pointer */
127 		*cp++ = *p++;	/* 2-char names */
128 		*cp++ = *p++;
129 		*cp++ = '\0';
130 		while (*p == ' ' || *p == '\t')
131 			p++;
132 		t.width[i+128] = *p++ - '0';
133 		while (*p == ' ' || *p == '\t')
134 			p++;
135 		t.codetab[i] = p;
136 		p = getstr(p, p);	/* compress string */
137 		p++;
138 		i++;
139 	}
140 
141 	sps = EM;
142 	ics = EM * 2;
143 	dtab = 8 * t.Em;
144 	for (i = 0; i < 16; i++)
145 		tabtab[i] = dtab * (i + 1);
146 	pl = 11 * INCH;
147 	po = PO;
148 	spacesz = SS;
149 	lss = lss1 = VS;
150 	ll = ll1 = lt = lt1 = LL;
151 	smnt = nfonts = 5;	/* R I B BI S */
152 	specnames();	/* install names like "hyphen", etc. */
153 	if (eqflg)
154 		t.Adj = t.Hor;
155 }
156 
157 char *skipstr(s)	/* skip over leading space plus string */
158 	char *s;
159 {
160 	while (*s == ' ' || *s == '\t' || *s == '\n')
161 		s++;
162 	while (*s != ' ' && *s != '\t' && *s != '\n')
163 		if (*s++ == '\\')
164 			s++;
165 	return s;
166 }
167 
168 char *getstr(s, t)	/* find next string in s, copy to t */
169 	char *s, *t;
170 {
171 	int quote = 0;
172 
173 	while (*s == ' ' || *s == '\t' || *s == '\n')
174 		s++;
175 	if (*s == '"') {
176 		s++;
177 		quote = 1;
178 	}
179 	for (;;) {
180 		if (quote && *s == '"') {
181 			s++;
182 			break;
183 		}
184 		if (!quote && (*s == ' ' || *s == '\t' || *s == '\n'))
185 			break;
186 		if (*s != '\\')
187 			*t++ = *s++;
188 		else {
189 			s++;	/* skip \\ */
190 			if (isdigit(s[0]) && isdigit(s[1]) && isdigit(s[2])) {
191 				*t++ = (s[0]-'0')<<6 | (s[1]-'0')<<3 | s[2]-'0';
192 				s += 2;
193 			} else if (isdigit(s[0])) {
194 				*t++ = *s - '0';
195 			} else if (*s == 'b') {
196 				*t++ = '\b';
197 			} else if (*s == 'n') {
198 				*t++ = '\n';
199 			} else if (*s == 'r') {
200 				*t++ = '\r';
201 			} else if (*s == 't') {
202 				*t++ = '\t';
203 			} else {
204 				*t++ = *s;
205 			}
206 			s++;
207 		}
208 	}
209 	*t = '\0';
210 	return s;
211 }
212 
213 char *getint(s, pn)	/* find integer at s */
214 	char *s;
215 	int *pn;
216 {
217 	while (*s == ' ' || *s == '\t' || *s == '\n')
218 		s++;
219 	*pn = 0;
220 	while (isdigit(*s))
221 		*pn = 10 * *pn + *s++ - '0';
222 	return s;
223 }
224 
225 specnames()
226 {
227 	static struct {
228 		int	*n;
229 		char	*v;
230 	} spnames[] = {
231 		&c_hyphen, "hy",
232 		&c_emdash, "em",
233 		&c_rule, "ru",
234 		&c_minus, "\\-",
235 		&c_fi, "fi",
236 		&c_fl, "fl",
237 		&c_ff, "ff",
238 		&c_ffi, "Fi",
239 		&c_ffl, "Fl",
240 		&c_acute, "aa",
241 		&c_grave, "ga",
242 		&c_under, "ul",
243 		&c_rooten, "rn",
244 		&c_boxrule, "br",
245 		&c_lefthand, "lh",
246 		&c_isalnum, "__",
247 		0, 0
248 	};
249 	int	i;
250 
251 	for (i = 0; spnames[i].n; i++)
252 		*spnames[i].n = findch(spnames[i].v);
253 	if (c_isalnum == 0)
254 		c_isalnum = NROFFCHARS;
255 }
256 
257 
258 findch(s)	/* find char s in chname */
259 register char	*s;
260 {
261 	register int	i;
262 
263 	for (i = 0; chtab[i] != 0; i++)
264 		if (strcmp(s, &chname[chtab[i]]) == 0)
265 			return(i + 128);
266 	return(0);
267 }
268 
269 twdone()
270 {
271 	int waitf;
272 
273 	obufp = obuf;
274 	oputs(t.twrest);
275 	flusho();
276 	if (pipeflg) {
277 		close(ptid);
278 		wait(&waitf);
279 	}
280 	if (ttysave != -1) {
281 		ttys.sg_flags = ttysave;
282 		stty(1, &ttys);
283 	}
284 }
285 
286 
287 ptout(i)
288 	tchar i;
289 {
290 	*olinep++ = i;
291 	if (olinep >= &oline[LNSIZE])
292 		olinep--;
293 	if (cbits(i) != '\n')
294 		return;
295 	olinep--;
296 	lead += dip->blss + lss - t.Newline;
297 	dip->blss = 0;
298 	esct = esc = 0;
299 	if (olinep > oline) {
300 		move();
301 		ptout1();
302 		oputs(t.twnl);
303 	} else {
304 		lead += t.Newline;
305 		move();
306 	}
307 	lead += dip->alss;
308 	dip->alss = 0;
309 	olinep = oline;
310 }
311 
312 
313 ptout1()
314 {
315 	register k;
316 	register char	*codep;
317 	extern char	*plot();
318 	int	w, j, phyw;
319 	tchar * q, i;
320 	static int oxfont = FT;	/* start off in roman */
321 
322 	for (q = oline; q < olinep; q++) {
323 		i = *q;
324 		if (ismot(i)) {
325 			j = absmot(i);
326 			if (isnmot(i))
327 				j = -j;
328 			if (isvmot(i))
329 				lead += j;
330 			else
331 				esc += j;
332 			continue;
333 		}
334 		if ((k = cbits(i)) <= 040) {
335 			switch (k) {
336 			case ' ': /*space*/
337 				esc += t.Char;
338 				break;
339 			case '\033':
340 			case '\007':
341 			case '\016':
342 			case '\017':
343 				oput(k);
344 				break;
345 			}
346 			continue;
347 		}
348 		phyw = w = t.Char * t.width[k];
349 		if (iszbit(i))
350 			w = 0;
351 		if (esc || lead)
352 			move();
353 		esct += w;
354 		xfont = fbits(i);
355 		if (xfont != oxfont) {
356 			switch (oxfont) {
357 			case ULFONT:	oputs(t.itoff); break;
358 			case BDFONT:	oputs(t.bdoff); break;
359 			case BIFONT:	oputs(t.itoff); oputs(t.bdoff); break;
360 			}
361 			switch (xfont) {
362 			case ULFONT:
363 				if (*t.iton & 0377) oputs(t.iton); break;
364 			case BDFONT:
365 				if (*t.bdon & 0377) oputs(t.bdon); break;
366 			case BIFONT:
367 				if (*t.bdon & 0377) oputs(t.bdon);
368 				if (*t.iton & 0377) oputs(t.iton);
369 				break;
370 			}
371 			oxfont = xfont;
372 		}
373 		if ((xfont == ULFONT || xfont == BIFONT) && !(*t.iton & 0377)) {
374 			for (j = w / t.Char; j > 0; j--)
375 				oput('_');
376 			for (j = w / t.Char; j > 0; j--)
377 				oput('\b');
378 		}
379 		if (!(*t.bdon & 0377) && ((j = bdtab[xfont]) || xfont == BDFONT || xfont == BIFONT))
380 			j++;
381 		else
382 			j = 1;	/* number of overstrikes for bold */
383 		if (k < 128) {	/* ordinary ascii */
384 			oput(k);
385 			while (--j > 0) {
386 				oput('\b');
387 				oput(k);
388 			}
389 		} else {
390 			int oj = j;
391 			codep = t.codetab[k-128];
392 			while (*codep != 0) {
393 				if (*codep & 0200) {
394 					codep = plot(codep);
395 					oput(' ');
396 				} else {
397 					if (*codep == '%')	/* escape */
398 						codep++;
399 					oput(*codep);
400 					if (*codep != '\b')
401 						for (j = oj; --j > 0; ) {
402 							oput('\b');
403 							oput(*codep);
404 						}
405 					codep++;
406 				}
407 			}
408 		}
409 		if (!w)
410 			for (j = phyw / t.Char; j > 0; j--)
411 				oput('\b');
412 	}
413 }
414 
415 
416 char	*plot(x)
417 char	*x;
418 {
419 	register int	i;
420 	register char	*j, *k;
421 
422 	oputs(t.ploton);
423 	k = x;
424 	if ((*k & 0377) == 0200)
425 		k++;
426 	for (; *k; k++) {
427 		if (*k == '%') {	/* quote char within plot mode */
428 			oput(*++k);
429 		} else if (*k & 0200) {
430 			if (*k & 0100) {
431 				if (*k & 040)
432 					j = t.up;
433 				else
434 					j = t.down;
435 			} else {
436 				if (*k & 040)
437 					j = t.left;
438 				else
439 					j = t.right;
440 			}
441 			if ((i = *k & 037) == 0) {	/* 2nd 0200 turns it off */
442 				++k;
443 				break;
444 			}
445 			while (i--)
446 				oputs(j);
447 		} else
448 			oput(*k);
449 	}
450 	oputs(t.plotoff);
451 	return(k);
452 }
453 
454 
455 move()
456 {
457 	register k;
458 	register char	*i, *j;
459 	char	*p, *q;
460 	int	iesct, dt;
461 
462 	iesct = esct;
463 	if (esct += esc)
464 		i = "\0";
465 	else
466 		i = "\n\0";
467 	j = t.hlf;
468 	p = t.right;
469 	q = t.down;
470 	if (lead) {
471 		if (lead < 0) {
472 			lead = -lead;
473 			i = t.flr;
474 			/*	if(!esct)i = t.flr; else i = "\0";*/
475 			j = t.hlr;
476 			q = t.up;
477 		}
478 		if (*i & 0377) {
479 			k = lead / t.Newline;
480 			lead = lead % t.Newline;
481 			while (k--)
482 				oputs(i);
483 		}
484 		if (*j & 0377) {
485 			k = lead / t.Halfline;
486 			lead = lead % t.Halfline;
487 			while (k--)
488 				oputs(j);
489 		} else { /* no half-line forward, not at line begining */
490 			k = lead / t.Newline;
491 			lead = lead % t.Newline;
492 			if (k > 0)
493 				esc = esct;
494 			i = "\n";
495 			while (k--)
496 				oputs(i);
497 		}
498 	}
499 	if (esc) {
500 		if (esc < 0) {
501 			esc = -esc;
502 			j = "\b";
503 			p = t.left;
504 		} else {
505 			j = " ";
506 			if (hflg)
507 				while ((dt = dtab - (iesct % dtab)) <= esc) {
508 					if (dt % t.Em)
509 						break;
510 					oput(TAB);
511 					esc -= dt;
512 					iesct += dt;
513 				}
514 		}
515 		k = esc / t.Em;
516 		esc = esc % t.Em;
517 		while (k--)
518 			oputs(j);
519 	}
520 	if ((*t.ploton & 0377) && (esc || lead)) {
521 		oputs(t.ploton);
522 		esc /= t.Hor;
523 		lead /= t.Vert;
524 		while (esc--)
525 			oputs(p);
526 		while (lead--)
527 			oputs(q);
528 		oputs(t.plotoff);
529 	}
530 	esc = lead = 0;
531 }
532 
533 
534 ptlead()
535 {
536 	move();
537 }
538 
539 
540 dostop()
541 {
542 	char	junk;
543 
544 	flusho();
545 	read(2, &junk, 1);
546 }
547 
548 
549 newpage(){;}
550 pttrailer(){;}
551