1 /*
2  * Copyright (C) 1991,1992,1993 NEC Corporation.
3  */
4 #ifndef lint
5 static char rcsid[] =
6 	"$Id: roffout.c,v 2.16 1994/04/19 10:17:03 uchida Exp $ (NEC)";
7 #endif
8 
9 #include <stdio.h>
10 #include "plain2.h"
11 #include "picture.h"
12 #include "table.h"
13 #include "macro.h"
14 
15 struct	macDefs roffMacros[] = {
16 	M_DOC_BEGIN,	".nr Ls 0\n.S #1 #1+2\n",
17 	M_DOC_END,	"",
18 	M_PLAIN_BEGIN,	".P\n",
19 	M_PLAIN_END,	"",
20 	M_EXAM_BEGIN,	".ft CW\n.vs -2\n.nf\n",
21 	M_EXAM_END,	".fi\n.vs +2\n.ft\n",
22 	M_JEXAM_BEGIN,	"",
23 	M_JEXAM_END,	"",  /* These two are not actually used, because when
24 				roff output is selected, the flag useJverb
25 				is always 0 */
26 	M_APPENDIX,	"\\fBAppendix $1\\fP\n",
27 	M_BLANK,	"\n",
28 	M_PAGE,		".bp\n",
29 	M_NEWLINE,	".br\n",
30 	M_CENTER_BEGIN,	".ce 9999\n",
31 	M_CENTER_END,	".ce 0\n",
32 	M_RIGHT_BEGIN,	".ad r\n",
33 	M_RIGHT_END,	".ad b\n",
34 	M_INDENT,	".in #1/2u\n",
35 	M_INDENT0,	".in 0\n",
36 	M_FOOTN_BEGIN,	"\\*F\n.FS\n",
37 	M_FOOTN_END,	".FE\n",
38 	M_BOLD_BEGIN,	"\\fB",
39 	M_BOLD_END,	"\\fP",
40 	M_SECTION,	".H #1 \"@2\"\n",
41 	M_SETSEC,	".nr H#1 #2\n",
42 	M_TITLE,	".ce 999\n\\fB\\s+4&1\n\\fP\\s-4\n.ce 0\n\
43 .ad r\n&3\n.br\n&4\n.br\n&5\n.br\n&6\n.br\n&7\n.br\n.ad b\n.br 2\n",
44 	-1,	"",
45 };
46 
47 struct	macDefs roffMsMacros[] = {
48 	M_SECTION,	".NH #1\n @2\n",
49 	M_SECTION_1,	".NH\n @1\n",
50 	M_DOC_BEGIN,	".nr PI 2n\n.ps #1\n.vs #1+2\n",
51 	M_PLAIN_BEGIN,	".PP\n",
52 	-1,	"",
53 };
54 
55 /*
56  * Roff text output routines
57  */
58 #define	ROFF_TRANS	\
59 	{'\\',"\\e"},\
60 	{'\'',"\\'"},\
61 	{0,0}
62 struct transTable	roffTrans[] = {
63 	ROFF_TRANS
64 };
65 /*
66  * Quote for double quoted strings
67  *	 used for section and description list
68  */
69 struct transTable	roffTransQ[] = {
70 	{'\"',"\\\""},
71 	ROFF_TRANS
72 };
73 char	*
roffQuote1(str)74 roffQuote1(str)
75 char	*str;
76 {
77 	return codeCvt(textQuote(str, roffTrans));
78 }
79 char	*
roffQuote2(str)80 roffQuote2(str)
81 char	*str;
82 {
83 	return codeCvt(textQuote(str, roffTransQ));
84 }
roffPlain(str,attr,newline)85 roffPlain(str, attr, newline)
86 char	*str;
87 int	attr;
88 int	newline;
89 {
90 	if (*str == '.')
91 		fputs("\\&", stdout);
92 	if (attr == IL_RAW)
93 		fputs(codeCvt(str), stdout);
94 	else
95 		fputs(roffQuote1(str), stdout);
96 	if (newline)
97 		fputs("\n", stdout);
98 }
roffExample(str)99 roffExample(str)
100 char	*str;
101 {
102 	if (*str == '.')
103 		fputs("\\&", stdout);
104 	fputs(roffQuote1(str), stdout);
105 	putchar('\n');
106 }
107 #ifdef	KANJI
108 static	char	*bmarks[] = {"\\(bu", "��", "��" };
109 static	char	*dmarks[] = {"-", "��" };
110 #else
111 static	char	*bmarks[] = {"\\(bu"};
112 static	char	*dmarks[] = {"-"};
113 #endif
114 static	int	blevel = 0;
115 static	int	dlevel = 0;
116 
117 #define	MAX_LIST_DEPTH	10
118 static	int	list_number[MAX_LIST_DEPTH];
119 static	int	list_type[MAX_LIST_DEPTH];
120 static	char	*list_format1[MAX_LIST_DEPTH];
121 static	char	*list_format2[MAX_LIST_DEPTH];
122 
roffListBlock(begin,level,ltype,hint)123 roffListBlock(begin, level, ltype, hint)
124 int	begin;
125 int	level;
126 int	ltype;
127 char	hint;
128 {
129 	switch (roffMacro) {
130 	    case MM_MACRO:
131 		mmListBlock(begin, level, ltype, hint);
132 		break;
133 	    case MS_MACRO:
134 		msListBlock(begin, level, ltype, hint);
135 		break;
136 	}
137 
138 }
mmListBlock(begin,level,ltype,hint)139 mmListBlock(begin, level, ltype, hint)
140 int	begin;
141 int	level;
142 int	ltype;
143 char	hint;
144 {
145 	int	i;
146 	if (begin) {
147 		switch (ltype) {
148 		    case L_BULLET:
149 			if (blevel < sizeof(bmarks)/sizeof(char *))
150 				i = blevel;
151 			else
152 				i = sizeof(bmarks)/sizeof(char *) - 1;
153 			printf(".ML %s\n", bmarks[i]);
154 			blevel++;
155 			break;
156 		    case L_DASH:
157 			if (dlevel < sizeof(dmarks)/sizeof(char *))
158 				i = dlevel;
159 			else
160 				i = sizeof(dmarks)/sizeof(char *) - 1;
161 			printf(".ML %s\n", dmarks[i]);
162 			dlevel++;
163 			break;
164 		    case L_DLIST:
165 			fputs(".VL 4 0\n", stdout);
166 			break;
167 		    case L_SROMAN:
168 			fputs(".AL i", stdout);
169 			goto moreStyle;
170 		    case L_LROMAN:
171 			fputs(".AL I", stdout);
172 			goto moreStyle;
173 		    case L_NUMBER:
174 			fputs(".AL 1", stdout);
175 			goto moreStyle;
176 		    case L_LALPHA:
177 			fputs(".AL A", stdout);
178 			goto moreStyle;
179 		    case L_SALPHA:
180 			fputs(".AL a", stdout);
181 			goto moreStyle;
182 		    moreStyle:
183 			if (listDecor) {
184 				switch (hint) {
185 				    case LH_PAREN:
186 					fputs(" ()\n", stdout);
187 					break;
188 				    case LH_RPAREN:
189 					fputs(" )\n", stdout);
190 					break;
191 				    case LH_BRACKET:
192 					fputs(" []\n", stdout);
193 					break;
194 				    case LH_RBRACKET:
195 					fputs(" ]\n", stdout);
196 					break;
197 				    case LH_DOTTED:
198 					fputs(" .\n", stdout);
199 					break;
200 				    default:
201 					fputs(" \n", stdout);
202 					break;
203 				}
204 			}
205 			else
206 				fputs("\n", stdout);
207 			break;
208 		    default:
209 			break;
210 		}
211 	}
212 	else {
213 		switch (ltype) {
214 		    case L_BULLET:
215 			blevel--;
216 			break;
217 		    case L_DASH:
218 			dlevel--;
219 			break;
220 		    default:
221 			break;
222 		}
223 		fputs(".LE\n", stdout);
224 	}
225 }
msListBlock(begin,level,ltype,hint)226 msListBlock(begin, level, ltype, hint)
227 int	begin;
228 int	level;
229 int	ltype;
230 char	hint;
231 {
232 	int	i;
233 	if (begin) {
234 		fputs(".in +2\n.sp .5\n", stdout);
235 		list_type[level]   = ltype;
236 		list_number[level] = 0;
237 		switch (ltype) {
238 		    case L_BULLET:
239 			if (blevel < sizeof(bmarks)/sizeof(char *))
240 				i = blevel;
241 			else
242 				i = sizeof(bmarks)/sizeof(char *) - 1;
243 			list_format1[level] = bmarks[i];
244 			blevel++;
245 			break;
246 		    case L_DASH:
247 			if (dlevel < sizeof(dmarks)/sizeof(char *))
248 				i = dlevel;
249 			else
250 				i = sizeof(dmarks)/sizeof(char *) - 1;
251 			list_format1[level] = dmarks[i];
252 			dlevel++;
253 			break;
254 		    case L_DLIST:
255 			break;
256 		    default:
257 			switch (hint) {
258 			    case LH_PAREN:
259 				list_format1[level] = "(";
260 				list_format2[level] = ")";
261 				break;
262 			    case LH_RPAREN:
263 				list_format1[level] = "";
264 				list_format2[level] = ")";
265 				break;
266 			    case LH_BRACKET:
267 				list_format1[level] = "[";
268 				list_format2[level] = "]";
269 				break;
270 			    case LH_RBRACKET:
271 				list_format1[level] = "";
272 				list_format2[level] = "]";
273 				break;
274 			    case LH_DOTTED:
275 				list_format1[level] = "";
276 				list_format2[level] = ".";
277 				break;
278 			    default:
279 				list_format1[level] = "";
280 				list_format2[level] = "";
281 				break;
282 			}
283 			break;
284 		}
285 	}
286 	else {
287 		switch (ltype) {
288 		    case L_BULLET:
289 			blevel--;
290 			break;
291 		    case L_DASH:
292 			dlevel--;
293 			break;
294 		    default:
295 			break;
296 		}
297 		fputs(".in -2\n", stdout);
298 	}
299 }
roffDlistItem(level,dscr,cont)300 roffDlistItem(level, dscr, cont)
301 int	level;
302 char	*dscr;
303 int	cont;
304 {
305 	switch (roffMacro) {
306 	    case MM_MACRO:
307 		printf(".LI \"\\fB%s\\fP\" \n", roffQuote2(dscr));
308 		break;
309 	    case MS_MACRO:
310 		fputs(".ti -1\n", stdout);
311 		printf("\\fB%s\\fP \n", roffQuote2(dscr));
312 		break;
313 	}
314 }
315 static char *lroman_list[] = {
316 	"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X"
317 	};
318 static char *sroman_list[] = {
319 	"i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix", "x"
320 	};
roffListItem(level)321 roffListItem(level)
322 int	level;
323 {
324 	switch (roffMacro) {
325 	    case MM_MACRO:
326 		fputs(".LI\n", stdout);
327 		break;
328 	    case MS_MACRO:
329 		fputs(".ti -2\n", stdout);
330 		switch (list_type[level]) {
331 		    case L_BULLET:
332 		    case L_DASH:
333 			printf("%s ", list_format1[level]);
334 			break;
335 		    case L_NUMBER:
336 			printf("%s%d%s ", list_format1[level], ++list_number[level],
337 			       list_format2[level]);
338 			break;
339 		    case L_LROMAN:
340 			printf("%s%s%s ",
341 			       list_format1[level],
342 			       lroman_list[list_number[level]++],
343 			       list_format2[level]);
344 			if (list_number[level] >= sizeof(lroman_list) / sizeof(char *))
345 				list_number[level]--;
346 			break;
347 		    case L_SROMAN:
348 			printf("%s%s%s ",
349 			       list_format1[level],
350 			       sroman_list[list_number[level]++],
351 			       list_format2[level]);
352 			if (list_number[level] >= sizeof(sroman_list) / sizeof(char *))
353 				list_number[level]--;
354 			break;
355 		    case L_SALPHA:
356 			printf("%s%c%s ", list_format1[level],
357 			       'a' + list_number[level]++,
358 			       list_format2[level]);
359 			break;
360 		    case L_LALPHA:
361 			printf("%s%c%s ", list_format1[level],
362 			       'A' + list_number[level]++,
363 			       list_format2[level]);
364 		    default:
365 			break;
366 		}
367 		break;
368 	}
369 }
roffSpace(length)370 roffSpace(length)
371 int	length;
372 {
373 	printf(".DS I\n");
374 	printf(".vs 13\n");
375 	printf(".sp %d\n", length);
376 	printf(".vs\n");
377 	printf(".DE\n");
378 }
roffRawText(str)379 roffRawText(str)
380 char	*str; {
381 	printf("%s\n", codeCvt(str));
382 }
roffFTitle(ft,str,capsule)383 roffFTitle(ft, str, capsule)
384 int	ft;
385 char	*str;
386 int	capsule;
387 {
388 	static int	figNumber = 1;
389 	static int	tblNumber = 1;
390 	fputs ("\\s-2", stdout);
391 #ifdef	KANJI
392 	if (japaneseText) {
393 		if (ft == FT_FIGURE)
394 			printf ("\\fB�� %d.\\fP", figNumber++);
395 		else if (ft == FT_TABLE)
396 			printf ("\\fBɽ %d.\\fP", tblNumber++);
397 	}
398 	else {
399 #endif
400 		if (ft == FT_FIGURE)
401 			printf ("\\fBFigure %d.\\fP", figNumber++);
402 		else if (ft == FT_TABLE)
403 			printf ("\\fBTable %d.\\fP", tblNumber++);
404 #ifdef	KANJI
405 	}
406 #endif
407 	printf (" %s\\s0\n", roffQuote1(str));
408 }
409 #ifdef	PICTURE
410 /*
411  * Driver for roff (pic) output
412  */
413 static int	picLines;		/* Number of lines in the block	*/
414 static int	picMinInd;		/* Indentation of the region	*/
415 int	roffVsize;
416 extern struct transTable	roffTransQ[];
417 #define	ROFF_SCALE	134.
418 #define	ROFF_Y(y)	((roffVsize - (y)) * picFontSize / ROFF_SCALE)
419 #define	ROFF_X(x)	((x - picMinInd) * picFontSize / ROFF_SCALE)
420 #define	ROFF_LEN(l)	((l) * picFontSize / ROFF_SCALE)
roffPictureBlock(begin,lines,indent,maxLen)421 roffPictureBlock(begin, lines, indent, maxLen)
422 int	begin;
423 int	lines;
424 int	indent;
425 int	maxLen;
426 {
427 	picLines  = lines;
428 	picMinInd = indent;
429 	if (begin) {
430 		roffVsize = lines * 2;
431 		fputs(".PS\n", stdout);
432 	}
433 	else {
434 		printf(".ps %d\n", picFontSize);
435 		fputs(".PE\n", stdout);
436 	}
437 }
438 /* set line width	*/
roffLineWidth(style)439 roffLineWidth(style)
440 int	style;
441 {
442 	if (style == SY_DBL)
443 		printf(".ps %d\n", fontSize * 2);
444 	else if (style == SY_THICK)
445 		printf(".ps %d\n", fontSize<14 ? 14 : fontSize);
446 	else
447 		printf(".ps %d\n", fontSize / 2);
448 }
roffPicLine(x0,y0,x1,y1,style,vector)449 roffPicLine(x0, y0, x1, y1, style, vector)
450 int	x0, x1, y0, y1;
451 int	style;
452 int	vector;
453 {
454 	DBG4(4, "roffPicLine (%d,%d)-(%d,%d)\n", x0, y0, x1, y1);
455 	roffLineWidth(style);
456 	if (style == SY_ELPS || style == SY_HELPS) {
457 		printf("ellipse wid %f ht %f at %f, %f\n",
458 			ROFF_LEN(x1 - x0), ROFF_LEN((x1 - x0)/4.),
459 			ROFF_X(x0 + (x1 - x0) / 2.),
460 			ROFF_Y(y0 + (y1 - y0) / 2.));
461 		return;
462 	}
463 	if (style == SY_CIRCLE) {
464 		printf("circle radius %f at %d, %d\n",
465 		       ROFF_LEN(abs(x1 - x0) / 2.),
466 		       ROFF_X((x1 + x0) / 2), ROFF_Y(y0 + (x1 - x0) / 2));
467 		return;
468 	}
469 	fputs("line", stdout);
470 	switch (vector) {
471 	    case VECT_BGN:
472 		fputs(" <-", stdout);
473 		break;
474 	    case VECT_END:
475 		fputs(" ->", stdout);
476 		break;
477 	    case VECT_BOTH:
478 		fputs(" <->", stdout);
479 		break;
480 	    default:
481 		break;
482 	}
483 	printf(" from %f, %f to %f, %f",
484 	       ROFF_X(x0), ROFF_Y(y0), ROFF_X(x1), ROFF_Y(y1));
485 	if (style == SY_DASH)
486 		printf(" dashed 0.%02di\n",picFontSize / 4);
487 	else
488 		fputs("\n", stdout);
489 }
roffPicArc(x,y,r,dir,style)490 roffPicArc(x, y, r, dir, style)
491 int	x, y, r;
492 enum	direction dir;
493 int	style;
494 {
495 	int	x0, x1, y0, y1;
496 	float	offset;
497 	x0 = x1 = x;
498 	y0 = y1 = y;
499 	switch (dir) {
500 	    case dir_br:
501 		x0 = x + r;
502 		y1 = y + r;
503 		break;
504 	    case dir_bl:
505 		x1 = x - r;
506 		y0 = y + r;
507 		break;
508 	    case dir_tl:
509 		x0 = x - r;
510 		y1 = y - r;
511 		break;
512 	    case dir_tr:
513 		x1 = x + r;
514 		y0 = y - r;
515 		break;
516 	}
517 	roffLineWidth(style);
518 	if (style == SY_THICK)
519 		offset = (fontSize / 20) / ROFF_SCALE;
520 	else
521 		offset = 0;
522 	printf("arc cw from %f, %f to %f, %f rad %f\n",
523 	       ROFF_X(x0) + offset, ROFF_Y(y0) - offset,
524 	       ROFF_X(x1) + offset, ROFF_Y(y1) - offset, ROFF_LEN(r));
525 /*	       ROFF_X(x0), ROFF_Y(y0), ROFF_X(x1), ROFF_Y(y1),ROFF_LEN(r));*/
526 }
roffPicText(s,xpos,vpos,factor)527 roffPicText(s, xpos, vpos, factor)
528 char	*s;
529 int	xpos;
530 int	vpos;
531 int	factor;
532 {
533 	if (factor < 10)
534 		factor = 10;
535 	printf(".ps %d\n",
536 	       picFontSize * 10 / factor);
537 	printf("\"%s\" ljust at %f, %f\n", roffQuote2(s),
538 	       ROFF_X(xpos), ROFF_Y(vpos + 1));
539 }
540 #endif
roffTitle(style,haifu,title,shozoku,number,date,name,renraku,special8,special9)541 roffTitle(style, haifu, title, shozoku, number, date, name, renraku
542 #ifdef	TITLE_SPECIAL
543 			 ,special8, special9
544 #endif
545 	  )
546 int	style;
547 char	**haifu;
548 char	**title;
549 char	**shozoku;
550 char	**number;
551 char	**date;
552 char	**name;
553 char	**renraku;
554 #ifdef	TITLE_SPECIAL
555 char	**special8, **special9;
556 #endif
557 {
558 	char	**s;
559 	if (style == 0) {
560 		putMacro(M_TITLE,
561 			 title, number, date, shozoku, haifu, name, renraku
562 #ifdef	TITLE_SPECIAL
563 			 ,special8, special9
564 #endif
565 			 );
566 
567 		return;
568 	}
569 #ifdef	NEC_CCS
570 	fputs(".4H\n.ce 0\n", stdout);
571 	for (s = haifu; *s != NULL; s++)
572 		printf("%s\n", roffQuote1(*s));
573 	fputs(".4E\n", stdout);
574 	fputs(".4T\n", stdout);
575 	for (s = title; *s != NULL; s++)
576 		printf("%s\n", roffQuote1(*s));
577 	fputs(".4E\n", stdout);
578 	fputs(".4O\n", stdout);
579 	for (s = shozoku; *s != NULL; s++)
580 		printf("%s\n", roffQuote1(*s));
581 	fputs(".4E\n", stdout);
582 	fputs(".4S\n", stdout);
583 	for (s = number; *s != NULL; s++)
584 		printf("%s\n", roffQuote1(*s));
585 	fputs(".4E\n", stdout);
586 	fputs(".4D\n", stdout);
587 	for (s = date; *s != NULL; s++)
588 		printf("%s\n", roffQuote1(*s));
589 	fputs(".4E\n", stdout);
590 	fputs(".4N\n", stdout);
591 	for (s = name; *s != NULL; s++)
592 		printf("%s\n", roffQuote1(*s));
593 	fputs(".4E\n", stdout);
594 
595 	if (style == TITLE_A47)
596 		fputs(".47\n", stdout);
597 	if (style == TITLE_A47_1)
598 		fputs(".471\n", stdout);
599 
600 	if (*renraku != NULL) {
601 		fputs(".ad r\n", stdout);
602 		for (s = renraku; *s != NULL; s++)
603 			printf("%s\n", roffQuote1(*s));
604 		fputs(".br\n.ad b\n", stdout);
605 	}
606 #endif
607 }
roffTable(begin,end,tblp)608 roffTable(begin, end, tblp)
609 int	begin;
610 int	end;
611 struct	table	*tblp;
612 {
613 	int	j, l, fld;
614 	char	*atr;
615 	int	hattr;
616 	int	exCol;
617 	short	curAttr, prevAttr = HORI_NULL;
618 	fputs(".TS", stdout);
619 	for (l = begin; l < end; l++) {
620 		if ((hattr = lineAttr(texts[l]->body, &atr))
621 		    == HORI_DBL_ALL || hattr == HORI_SNGL_ALL)
622 			continue;
623 		fputs("\n", stdout);
624 		for (j = 0; j < tbl_field[0].vlines; j++)
625 			fputs("|", stdout);
626 		for (fld = 1; fld < tbl_nfield; fld += exCol + 1) {
627 			exCol = extraColumn(atr, texts[l]->length, fld, tblp);
628 			putchar(formatOf(atr, texts[l]->length, fld, exCol, tblp));
629 			for (j = 0; j < exCol; j++)
630 				fputs("s", stdout);
631 
632 			curAttr = attrOfStr(atr, texts[l]->length, fld, exCol, tblp);
633 			if (prevAttr != HORI_SNGL_ALL
634 			    || curAttr != HORI_SNGL_ALL)
635 				for (j = 0; j < tbl_field[fld + exCol].vlines; j++)
636 					fputs("|", stdout);
637 			prevAttr = curAttr;
638 		}
639 	}
640 	fputs(".\n", stdout);
641 	for (l = begin; l < end; l++) {
642 		if ((hattr = lineAttr(texts[l]->body, &atr)) == HORI_SNGL_ALL){
643 			fputs("_\n", stdout);
644 			continue;
645 		}
646 		else if (hattr == HORI_DBL_ALL) {
647 			fputs("=\n", stdout);
648 			continue;
649 		}
650 		for (fld = 1; fld < tbl_nfield; fld += exCol + 1) {
651 			exCol = extraColumn(atr, texts[l]->length, fld, tblp);
652 			if (attrOfStr(atr, texts[l]->length, fld, exCol, tblp)
653 			    == HORI_SNGL_ALL)
654 				fputs("_\t", stdout);
655 			else
656 				printf("%s\t", roffQuote1(tblSubstr(l, fld, exCol, tblp)));
657 		}
658 		fputs("\n", stdout);
659 	}
660 	fputs(".TE\n", stdout);
661 	fputs(".in\n", stdout);
662 }
roffCapsule(begin,type,center)663 roffCapsule(begin, type, center)
664 int	begin;
665 int	type;
666 {
667 	if (begin) {
668 		if (center)
669 			fputs(".DS CB\n", stdout);
670 		else
671 			fputs(".DS\n", stdout);
672 	}
673 	else {
674 		fputs(".DE\n", stdout);
675 	}
676 }
roffComment(begin,end)677 roffComment(begin, end)
678 int	begin;
679 int	end;
680 {
681 	int	l;
682 	for (l = begin; l < end; l++) {
683 		printf ("' %s\n", codeCvt(texts[l]->body));
684 	}
685 }
686