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