1 /*
2 * Copyright (C) 1991,1992,1993 NEC Corporation.
3 */
4 /*
5 * modify by k-chinen@is.aist-nara.ac.jp, 1994
6 */
7 #ifndef lint
8
9
10 #endif
11
12 #include <stdio.h>
13 #include "plain2.h"
14 #include "picture.h"
15 #include "macro.h"
16
17 #ifdef MSDOS
18 /* for Turbo-C(V2) BUG */
19 #define bodyStr(textp) (textp)->body + ((textp)->blank? 0: (textp)->indent)
20 #else
21 #define bodyStr(textp) ((textp)->blank\
22 ?(textp)->body\
23 :(textp)->body+(textp)->indent)
24 #endif
25
26 /*
27 * Definition of Output driver routines.
28 */
29 /***** roff *****/
30 int roffPlain(), roffExample(),
31 roffListBlock(), roffDlistItem(),
32 roffListItem(), roffRawText(), roffSpace(),
33 roffCapsule(), roffComment(),
34 #ifdef PICTURE
35 roffPictureBlock(), roffPicLine(), roffPicArc(),
36 roffPicText(), roffLineWidth(),
37 #endif
38 roffTable(), roffFTitle(), roffTitle();
39 char *roffQuote1(), *roffQuote2();
40
41
42 /***** TeX *****/
43 int texPlain(), texExample(),
44 texListBlock(), texDlistItem(),
45 texListItem(), texRawText(), texSpace(),
46 texCapsule(), texComment(),
47 #ifdef PICTURE
48 texPictureBlock(), texPicLine(), texPicArc(),
49 texPicText(), texLineWidth(),
50 #endif
51 texTable(), texFTitle(), texTitle();
52 char *texQuote1(), *texQuote2();
53
54 #ifdef HTML
55 /***** HTML *****/
56 int htmlPlain(), htmlExample(),
57 htmlListBlock(), htmlDlistItem(),
58 htmlListItem(), htmlRawText(), htmlSpace(),
59 htmlCapsule(), htmlComment(),
60 #ifdef PICTURE
61 htmlPictureBlock(), htmlPicLine(), htmlPicArc(),
62 htmlPicText(), htmlLineWidth(),
63 #endif
64 htmlTable(), htmlFTitle(), htmlTitle();
65 char *htmlQuote1(), *htmlQuote2();
66 #endif
67
68 struct outDev roffPut = {
69 roffPlain, roffExample,
70 roffListBlock, roffDlistItem,
71 roffListItem, roffRawText, roffSpace,
72 roffCapsule, roffComment,
73 #ifdef PICTURE
74 roffPictureBlock, roffPicLine, roffPicArc,
75 roffPicText, roffLineWidth,
76 #endif
77 roffTable, roffFTitle, roffTitle,
78 roffQuote1, roffQuote2,
79 };
80
81 struct outDev texPut = {
82 texPlain, texExample,
83 texListBlock, texDlistItem,
84 texListItem, texRawText, texSpace,
85 texCapsule, texComment,
86 #ifdef PICTURE
87 texPictureBlock, texPicLine, texPicArc,
88 texPicText, texLineWidth,
89 #endif
90 texTable, texFTitle, texTitle,
91 texQuote1, texQuote2,
92 };
93
94 #ifdef HTML
95 struct outDev htmlPut = {
96 htmlPlain, htmlExample,
97 htmlListBlock, htmlDlistItem,
98 htmlListItem, htmlRawText, htmlSpace,
99 htmlCapsule, htmlComment,
100 #ifdef PICTURE
101 htmlPictureBlock, htmlPicLine, htmlPicArc,
102 htmlPicText, htmlLineWidth,
103 #endif
104 htmlTable, htmlFTitle, htmlTitle,
105 htmlQuote1, htmlQuote2,
106 };
107 #endif
108
109
110 #ifdef HTML
111 /*
112 * Output text in (roff, TeX or HTML) format.
113 */
114 #else
115 /*
116 * Output text in (roff or TeX) format.
117 */
118 #endif
119
120 struct inline_mark {
121 char il_mark;
122 int il_type;
123 }inline_mark[] = {
124 {'r', IL_RAW},
125 {'f', IL_FOOTNOTE},
126 {'x', IL_REFERENCE},
127 {'b', IL_BOLD},
128 {'i', IL_INDEX},
129 };
130
inlineBegin(s,type)131 inlineBegin(s, type)
132 char *s;
133 int *type;
134 {
135 char *t;
136 int i;
137 int offset = 0;
138 while(*s) {
139 if ((t = index(s, INLINE_BEGIN[0])) == NULL || *(t+1) == '\0')
140 return -1;
141 if (*(t + 1) == INLINE_BEGIN[1]) {
142 for (i = 0; i < sizeof(inline_mark)/sizeof(struct inline_mark);
143 i++) {
144 if (*(t + 2) == inline_mark[i].il_mark) {
145 *type = inline_mark[i].il_type;
146 return t - s + offset;
147 }
148 }
149 }
150 offset += t - s + 1;
151 s = t + 1;
152 }
153 return 0;
154 }
inlineEnd(s)155 inlineEnd(s)
156 char *s;
157 {
158 char *t;
159 int offset = 0;
160
161 while(*s) {
162 if ((t = index(s, INLINE_END[0])) == NULL)
163 return -1;
164 if (*(t + 1) == INLINE_END[1]
165 && *(t + 2) != INLINE_END[0]) /*XXX*/
166 return t - s + offset;
167 offset += t - s + 1;
168 s = t + 1;
169 }
170 return 0;
171 }
inlineEndRegion(begin,end)172 inlineEndRegion(begin, end)
173 int begin;
174 int end;
175 {
176 while (begin < end) {
177 if (inlineEnd(texts[begin++]->body) != -1)
178 return begin;
179 }
180 return 0;
181 }
outAttribute(attr,begin)182 outAttribute(attr, begin)
183 int attr;
184 int begin;
185 {
186 switch (attr) {
187 case IL_RAW:
188 break;
189 case IL_FOOTNOTE:
190 if (begin)
191 putMacro(M_FOOTN_BEGIN);
192 else
193 putMacro(M_FOOTN_END);
194 break;
195 case IL_REFERENCE:
196 if (begin)
197 putMacro(M_REFER_BEGIN);
198 else
199 putMacro(M_REFER_END);
200 break;
201 case IL_BOLD:
202 if (begin)
203 putMacro(M_BOLD_BEGIN);
204 else
205 putMacro(M_BOLD_END);
206 break;
207 case IL_INDEX:
208 if (begin)
209 putMacro(M_INDEX_BEGIN);
210 else
211 putMacro(M_INDEX_END);
212 break;
213 default:
214 fprintf(stderr, "PANIC(unknown inline type)\n");
215 exit(2);
216 }
217 }
218
textOuput(begin,end,s)219 textOuput(begin, end, s)
220 int begin;
221 int end;
222 char *s;
223 {
224 int col1, col2, fend;
225 int inline_attr;
226 static char buf[MAX_LINE_LEN];
227 while (1) {
228 if (s == NULL || *s == '\0') {
229 PRINTED(begin);
230 if (++begin < end)
231 s = bodyStr(texts[begin]);
232 else
233 break;
234 }
235 if (inlineHint
236 && ((col1 = inlineBegin(s, &inline_attr)) != -1)
237 && ((col2 = inlineEnd(s + col1 + INLINE_END_LEN)) != -1)) {
238 if (col1 != 0) {
239 (void)strncpy(buf, s, col1);
240 buf[col1] = '\0';
241 (*put->plain)(buf, IL_PLAIN, 1);
242 }
243
244 outAttribute(inline_attr, BEGIN);
245
246 (void)strncpy(buf, s + col1 + INLINE_BEGIN_LEN, col2);
247 buf[col2] = '\0';
248 (*put->plain)(buf, inline_attr, 1);
249
250 outAttribute(inline_attr, END);
251
252 s += col1 + col2 + INLINE_BEGIN_LEN + INLINE_END_LEN -1;
253 }
254 else if (inlineHint
255 && col1 != -1
256 && (fend = inlineEndRegion(begin + 1, end))) {
257 if (col1 != 0) {
258 (void)strncpy(buf, s, col1);
259 buf[col1] = '\0';
260 (*put->plain)(buf, IL_PLAIN, 1);
261 }
262 outAttribute(inline_attr, BEGIN);
263 (*put->plain)(s + col1 + INLINE_BEGIN_LEN,
264 inline_attr, 1);
265 PRINTED(begin);
266 begin++;
267 while (begin < fend - 1) {
268 (*put->plain)(bodyStr(texts[begin]),
269 inline_attr, 1);
270 PRINTED(begin);
271 begin++;
272 }
273 s = texts[begin]->body;
274 col1 = inlineEnd(s);
275 (void)strncpy(buf, s, col1);
276 buf[col1] = '\0';
277 (*put->plain)(buf, inline_attr, 1);
278 outAttribute(inline_attr, END);
279 s += col1 + INLINE_END_LEN - 1;
280 }
281 else {
282 (*put->plain)(s, IL_PLAIN, 1);
283 PRINTED(begin);
284 if (++begin < end)
285 s = bodyStr(texts[begin]);
286 else
287 break;
288 continue;
289 }
290 }
291 }
292 #define MAX_LIST_LEVEL 8
293 static int listLevel = 0;
294 static int listIndent = 0;
295 listOutput(lbp)
296 struct textBlock *lbp;
297 {
298 char dscr[MAX_LINE_LEN];
299 struct textBlock *lhbp;
300 char *firstLine;
301 int lnum, rend;
302 int lastIndent;
303
304 lastIndent = listIndent;
305 listIndent = texts[lbp->rbegin]->indent;
306 listLevel++;
307 (*put->listBlock)(BEGIN, listLevel, texts[lbp->rbegin]->listType,
308 texts[lbp->rbegin]->listHint);
309 for (lhbp = lbp->nextBlock; lhbp != NULL; lhbp = lhbp->nextBlock) {
310 lnum = lhbp->rbegin;
311 firstLine = NULL;
312 /* output first block (list head block) */
313 if (texts[lnum]->listType == L_DLIST) {
314 (void)strncpy(dscr, bodyStr(texts[lnum]),
315 texts[lnum]->headLen);
316 dscr[texts[lnum]->headLen] = '\0';
317 (*put->dlistItem)(listLevel, dscr,
318 *listSecBody(texts[lnum]) != '\0');
319 if (*listSecBody(texts[lnum]) != '\0')
320 firstLine = listSecBody(texts[lnum]);
321 }
322 else {
323 (*put->listItem)(listLevel);
324 firstLine = listSecBody(texts[lnum]);
325 }
326 textOuput(lnum, lhbp->rend, firstLine);
327 /* output rest of the list body */
328 if (lhbp->nextBlock != NULL) {
329 rend = lhbp->nextBlock->rbegin;
330 }
331 else
332 rend = lbp->rend;
333 outputRegion(lhbp->rend, rend);
334 }
335 (*put->listBlock)(END, listLevel, texts[lbp->rbegin]->listType,
336 texts[lbp->rbegin]->listHint);
337 listLevel--;
338 listIndent = lastIndent;
339 }
340 capsuleOutput(blockTbp)
341 struct textBlock *blockTbp;
342 {
343 struct textBlock *tbp1, *tbp2;
344 int center;
345 int ftType; /* type of the figure/table title */
346 int l;
347
348 tbp1 = blockTbp->nextBlock;
349 tbp2 = tbp1->nextBlock;
350
351 if (tbp1->type == TB_FTITLE) {
352 ftType = texts[tbp1->rbegin]->fTitle;
353 }
354 else /* if (tbp1->type == TB_FTITLE)*/ {
355 ftType = texts[tbp2->rbegin]->fTitle;
356 }
357
358 center = blockIsCenter(blockTbp);
359 (*put->capsule)(BEGIN, ftType, center);
360
361 outputBlock(tbp1, 1);
362 for (l = tbp1->rend; l < tbp2->rbegin; l++) {
363 if (texts[l]->block == NULL && texts[l]->blank)
364 PRINTED(l);
365 }
366 outputBlock(tbp2, 1);
367
368 (*put->capsule)(END, ftType, center);
369 }
370 outputBlock(tbp, capsule)
371 struct textBlock *tbp;
372 int capsule;
373 {
374 int i, blockIndent;
375 int begin, end;
376 begin = tbp->rbegin;
377 end = tbp->rend;
378 if (tbp->hinted) {
379 PRINTED(begin);
380 PRINTED(end - 1);
381 begin++;
382 end--;
383 }
384 switch (tbp->type) {
385 case TB_COMMENT:
386 PRINTED2(begin, end);
387 (*put->comment)(begin, end);
388 break;
389 case TB_PAGE:
390 putMacro(M_PAGE);
391 PRINTED(begin);
392 break;
393 case TB_SPACE:
394 (*put->space)(tbp->rend - tbp->rbegin);
395 PRINTED2(begin, end);
396 break;
397 case TB_APPENDIX:
398 {
399 static firstTime = 1;
400 char *title = listSecBody(texts[begin]);
401 if (firstTime) {
402 firstTime = 0;
403 putMacro(M_APDX_BEGIN);
404 }
405 putMacro(M_APPENDIX, title);
406 if (put == &texPut && crossRefer) {
407 texPutLabel(title);
408 }
409 PRINTED(begin);
410 }
411 break;
412 case TB_SECNUM:
413 {
414 int depth = texts[begin]->secDepth;
415 char *title = listSecBody(texts[begin]);
416 if (anySection)
417 putMacro(M_SECTION_END);
418 else
419 anySection = 1;
420 if (depth < 0)
421 depth = 0;
422 if (accurateSecnum)
423 setSnumFor(texts[begin]);
424 if ((depth > M_SECTION - M_SECTION_1)
425 || putMacro(M_SECTION_1 + depth - 1, title) < 0)
426 putMacro(M_SECTION, depth, title);
427 if (put == &texPut && crossRefer) {
428 texPutLabel(title);
429 }
430 PRINTED(begin);
431 }
432 break;
433 case TB_RIGHT:
434 putIndent(IND_RIGHT, 1);
435 goto rightCenter;
436 case TB_CENTER:
437 putIndent(IND_CENTER, 1);
438 rightCenter:
439 blockIndent = minIndent(begin, end);
440 for (i = begin; i < end; i++) {
441 PRINTED(i);
442 (*put->plain)(bodyStr(texts[i]), IL_PLAIN, 1);
443 putMacro(M_NEWLINE);
444 }
445 putIndent(IND_RESUME, 0);
446 break;
447 case TB_FTITLE:
448 if (!capsule)
449 putIndent(IND_INDENT, texts[begin]->indent);
450 (*put->fTitle)(texts[begin]->fTitle,
451 texts[begin]->body
452 + texts[begin]->indent
453 + texts[begin]->headLen, capsule);
454 PRINTED(begin);
455 if (!capsule){
456 if(texts[begin]->indent && put == &texPut){
457 /* ���ξ�硢texFTitle()�ν��Ϥ���\\�פǽ���äƤ��ꡢ
458 ����putIndent()����\endlist�פ���Ϥ���ľ����
459 ��\mbox{}�פ������underfull hbox�ηٹ���ޤ��� */
460 printf("\\mbox{}");
461 }
462 putIndent(IND_RESUME, 0);
463 }
464 break;
465 case TB_QUOTE:
466 case TB_EXAMPLE:
467 putMacro(useJverb ? M_JEXAM_BEGIN : M_EXAM_BEGIN, fontSize);
468 for (i = begin; i < end; i++) {
469 PRINTED(i);
470 if (texts[i]->blank)
471 (*put->example)(texts[i]->body);
472 else
473 (*put->example)(texts[i]->body + listIndent);
474 }
475 putMacro(useJverb ? M_JEXAM_END : M_EXAM_END);
476 break;
477 case TB_LISTHD:
478 printf("ERROR(List Output%d)%s\n", begin, texts[begin]->body);
479 break;
480 case TB_LIST:
481 blockIndent = minIndent(begin, end);
482 if (listLevel == 0 && blockIndent > 6)
483 putIndent(IND_INDENT,
484 blockIndent - 4);
485 listOutput(tbp);
486 if (listLevel == 0 && blockIndent > 6)
487 putIndent(IND_RESUME, 0);
488 break;
489 case TB_PLAIN:
490 blockIndent = minIndent(begin, end);
491 if (listLevel == 0 && blockIndent > 4)
492 putIndent(IND_INDENT,
493 blockIndent);
494 putMacro(M_PLAIN_BEGIN);
495 textOuput(begin, end, bodyStr(texts[begin]));
496 putMacro(M_PLAIN_END);
497 if (listLevel == 0 && blockIndent > 4)
498 putIndent(IND_RESUME, 0);
499 break;
500 case TB_CAPSULE:
501 capsuleOutput(tbp);
502 break;
503 case TB_TABLE:
504 {
505 int center;
506 int indent_amount = 0;
507
508 if (!capsule) {
509 center = isCenter(begin, end);
510 (*put->capsule)(BEGIN, FT_TABLE, center);
511 if (!center){
512 indent_amount =
513 texts[begin]->indent / 2;
514
515 if(!crossRefer && put == &texPut &&
516 indent_amount){
517 /* ���ξ�硢texCapsule()�ν��Ϥ�
518 ��\\�פǽ���äƤ��ꡢ����
519 putIndent()����{\list{}�ġפ����
520 ����ľ���ˡ�\mbox{}�פ������
521 underfull hbox�ηٹ���ޤ��� */
522 printf("\\mbox{}");
523 }
524 putIndent(IND_INDENT, indent_amount);
525 }
526 }
527 tblOutput(begin, end);
528 if (!capsule) {
529 if (!center){
530 if(put == &texPut && indent_amount){
531 /* ���ξ�硢ľ����putIndent()�ν���
532 ����\\�פǽ���äƤ��ꡢ����
533 putIndent()����\endlist�פ����
534 ����ľ���ˡ�\mbox{}�פ������
535 underfull hbox�ηٹ���ޤ��� */
536 printf("\\mbox{}");
537 }
538 putIndent(IND_RESUME, 0);
539 }
540 (*put->capsule)(END, FT_TABLE, center);
541 }
542 }
543 break;
544 #ifdef PICTURE
545 case TB_PICTURE:
546 {
547 int center;
548 blockIndent = minIndent(begin, end);
549 if (!capsule) {
550 center = isCenter(begin, end);
551 (*put->capsule)(BEGIN, FT_FIGURE, center);
552 }
553 picOutput(begin, end);
554 PRINTED2(begin, end);
555 if (!capsule)
556 (*put->capsule)(END, FT_FIGURE, center);
557 }
558 break;
559 #endif
560 case TB_RAW:
561 for (i = begin; i < end; i++) {
562 (*put->rawText)(texts[i]->body);
563 PRINTED(i);
564 }
565 break;
566 default:
567 fprintf(stderr, "PANIC(unknown in output)\n");
568 exit(2);
569 }
570 }
outputRegion(begin,end)571 outputRegion(begin, end)
572 int begin;
573 int end;
574 {
575 int l;
576 struct textBlock *tbp;
577 l = begin;
578 if (begin >= end)
579 return;
580 while (l < end) {
581 tbp = texts[l]->block;
582 if (tbp) {
583 outputBlock(tbp, 0);
584 l = tbp->rend;
585 }
586 else {
587 if (!texts[l]->blank)
588 printf("undef%d:%s\n", l, texts[l]->body);
589 else {
590 PRINTED(l);
591 if (reflectSpace)
592 putMacro(M_BLANK);
593 }
594 l++;
595 }
596 }
597 }
putIndent2(type,d)598 putIndent2(type, d)
599 int type;
600 int d;
601 {
602 switch (type) {
603 case IND_CENTER:
604 if (d)
605 putMacro(M_CENTER_BEGIN);
606 else
607 putMacro(M_CENTER_END);
608 break;
609 case IND_RIGHT:
610 if (d)
611 putMacro(M_RIGHT_BEGIN);
612 else
613 putMacro(M_RIGHT_END);
614 break;
615 default:
616 if (d)
617 putMacro(M_INDENT, d);
618 else
619 putMacro(M_INDENT0, d);
620 break;
621 }
622 }
putIndent(type,d)623 putIndent(type, d)
624 int type;
625 int d;
626 {
627 static int lastIndentType = -1;
628 static int lastDepth = 0;
629 if (type == IND_RESUME && lastIndentType != -1) {
630 switch (lastIndentType) {
631 case IND_CENTER:
632 case IND_RIGHT:
633 putIndent2(lastIndentType, 0);
634 break;
635 default:
636 if (lastDepth)
637 putIndent2(IND_INDENT, 0);
638 break;
639 }
640 lastIndentType = -1;
641 }
642 if (type == IND_RESUME)
643 return;
644 switch (type) {
645 case IND_CENTER:
646 case IND_RIGHT:
647 putIndent2(type, 1);
648 break;
649 default:
650 if (lastDepth = d)
651 putIndent2(IND_INDENT, d);
652 break;
653 }
654 lastIndentType = type;
655 }
outputDocument()656 outputDocument()
657 {
658 if (textBegin != 1)
659 outputTitle();
660 if (put == &roffPut)
661 roffPutHeader();
662 if (preamble)
663 outputSetSnum(textBegin, textLines);
664 outputRegion(textBegin, textLines);
665 }
666