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