source: trunk/emx/src/emxdoc/ipf.c@ 3669

Last change on this file since 3669 was 18, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 14.3 KB
Line 
1/* ipf.c -- IPF output
2 Copyright (c) 1993-2000 Eberhard Mattes
3
4This file is part of emxdoc.
5
6emxdoc is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11emxdoc is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with emxdoc; see the file COPYING. If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <ctype.h>
26#include "emxdoc.h"
27#include "ipf.h"
28#include "xref.h"
29
30#define HBAR 0xc4
31#define VBAR 0xb3
32
33static int idx_refid;
34
35
36void ipf_hilite (int new)
37{
38 int diff, font_changed;
39
40 if (new & HL_EM)
41 new = (new & ~HL_EM) | HL_SL;
42 if (hl_ipf == new)
43 return;
44 font_changed = FALSE;
45 diff = new & ~hl_ipf;
46 if (diff & HL_TT)
47 {
48 write_string (":font");
49 write_space ();
50 write_string ("facename=Courier");
51 write_space ();
52 write_string ("size=16x9.");
53 font_changed = TRUE;
54 }
55 diff = hl_ipf & ~new;
56 if (diff & HL_TT)
57 {
58 write_string (":font");
59 write_space ();
60 write_string ("facename=default");
61 write_space ();
62 write_string ("size=0x0.");
63 font_changed = TRUE;
64 }
65
66 if ((hl_ipf & (HL_BF|HL_SL|HL_UL))
67 != (new & (HL_BF|HL_SL|HL_UL)) || font_changed)
68 {
69 if (hl_ipf_no != 0)
70 write_fmt (":ehp%d.", hl_ipf_no);
71 if (opt_c && (new & HL_SL))
72 hl_ipf_no = 4;
73 else
74 switch (new & (HL_BF|HL_SL|HL_UL))
75 {
76 case 0:
77 hl_ipf_no = 0;
78 break;
79 case HL_SL:
80 hl_ipf_no = 1;
81 break;
82 case HL_SL|HL_BF:
83 hl_ipf_no = 3;
84 break;
85 case HL_SL|HL_UL:
86 case HL_SL|HL_BF|HL_UL:
87 hl_ipf_no = 6;
88 break;
89 case HL_BF:
90 hl_ipf_no = 2;
91 break;
92 case HL_BF|HL_UL:
93 hl_ipf_no = 7;
94 break;
95 case HL_UL:
96 hl_ipf_no = 5;
97 break;
98 default:
99 abort ();
100 }
101 if (hl_ipf_no != 0)
102 write_fmt (":hp%d.", hl_ipf_no);
103 }
104
105 hl_ipf = new;
106}
107
108
109static void ipf_string (const uchar *p, int may_break)
110{
111 const uchar *q;
112
113 while ((q = strpbrk (p, ":&. ")) != NULL)
114 {
115 write_nstring (p, q - p);
116 switch (*q)
117 {
118 case ':':
119 write_string ("&colon.");
120 break;
121 case '&':
122 write_string ("&amp.");
123 break;
124 case ' ':
125 if (output_x >= 60 && may_break)
126 write_nl ();
127 else
128 write_string (" ");
129 break;
130 case '.':
131 if (output_x == 0)
132 write_string ("&per.");
133 else
134 write_string (".");
135 break;
136 default:
137 abort ();
138 }
139 p = q + 1;
140 }
141 write_string (p);
142}
143
144
145void ipf_output (const uchar *p, int may_break)
146{
147 ipf_hilite (hl_stack[hl_sp]);
148 ipf_string (p, may_break);
149}
150
151
152void ipf_para (void)
153{
154 write_break ();
155 write_line (":p.");
156}
157
158
159void ipf_margin (int margin)
160{
161 if (out && mode == 'I')
162 {
163 write_fmt (":lm margin=%d.", margin);
164 write_nl ();
165 }
166}
167
168
169void ipf_env_margin (int sp)
170{
171 ipf_margin (env_stack[sp].imargin);
172}
173
174
175void ipf_elements (enum style style)
176{
177 const struct element *ep;
178 enum style style_stack[STYLE_STACK_SIZE];
179 int style_sp;
180
181 style_sp = 0;
182 style_stack[style_sp] = style;
183 for (ep = elements; ep->el != EL_END; ++ep)
184 switch (ep->el)
185 {
186 case EL_WORD:
187 case EL_PUNCT:
188 if (ep->n != 0)
189 {
190 if (ep->wp->database == NULL)
191 ipf_begin_link (NULL, ep->wp->ref);
192 else
193 ipf_begin_link (ep->wp->database->str, ep->wp->ref);
194 format_output (ep->wp->str, FALSE);
195 ipf_end_link ();
196 }
197 else if (ep->wp->special != NULL && ep->wp->special->ipf != NULL)
198 write_string (ep->wp->special->ipf);
199 else if (style_sp == 0 || style_stack[style_sp] == STYLE_NORMAL)
200 format_string (ep->wp->str, (ep->wp->style != STYLE_NORMAL
201 ? ep->wp->style : style), FALSE);
202 else
203 format_string (ep->wp->str, style_stack[style_sp], FALSE);
204 break;
205 case EL_SPACE:
206 format_spaces (ep->n, style_stack[style_sp], TRUE);
207 break;
208 case EL_BREAK:
209 write_break ();
210 write_line (".br");
211 break;
212 case EL_STYLE:
213 if (style_sp + 1 >= STYLE_STACK_SIZE)
214 fatal ("%s:%d: Style stack overflow", input_fname, line_no);
215 style_stack[++style_sp] = ep->n;
216 break;
217 case EL_ENDSTYLE:
218 if (style_sp == 0)
219 fatal ("%s:%d: Style stack underflow", input_fname, line_no);
220 --style_sp;
221 break;
222 default:
223 abort ();
224 }
225}
226
227
228void ipf_begin_link (const uchar *database, int ref)
229{
230 ipf_hilite (hl_stack[hl_sp]);
231 write_string (":link");
232 write_space ();
233 write_string ("reftype=hd");
234 write_space ();
235 if (database != NULL && !opt_a)
236 {
237 write_space ();
238 write_fmt ("refid=%d database='%s'", ref, database);
239 }
240 else
241 write_fmt ("res=%d", ref);
242 write_string (".");
243}
244
245
246void ipf_end_link (void)
247{
248 write_string (":elink.");
249}
250
251
252void ipf_end_env (void)
253{
254 switch (env_stack[env_sp].env)
255 {
256 case ENV_DESCRIPTION:
257 write_break ();
258 write_line (":edl.");
259 break;
260 case ENV_ENUMERATE:
261 write_break ();
262 write_line (":eol.");
263 break;
264 case ENV_ITEMIZE:
265 write_break ();
266 write_line (":eul.");
267 break;
268 case ENV_LIST:
269 case ENV_INDENT:
270 case ENV_TYPEWRITER:
271 write_break ();
272 ipf_env_margin (env_sp-1);
273 break;
274 default:
275 abort ();
276 }
277}
278
279
280void ipf_toc_start (void)
281{
282 write_line (":lines align=left.");
283}
284
285
286void ipf_toc_line (const uchar *s, const struct toc *tp)
287{
288 format_string (s, STYLE_NORMAL, FALSE);
289 ipf_begin_link (NULL, tp->ref);
290 format_output (tp->title, FALSE);
291 ipf_end_link ();
292 write_nl ();
293}
294
295
296void ipf_toc_end (void)
297{
298 write_line (":elines.");
299}
300
301
302void ipf_heading1 (int level, int ref, int global, unsigned flags)
303{
304 if (hl_sp != 0)
305 fatal ("%s:%d: Hilighting must be off at section heading",
306 input_fname, line_no);
307 ipf_hilite (hl_stack[hl_sp]);
308 write_break ();
309 write_fmt (":h%d res=%d", level, ref);
310 if (global && !opt_a)
311 write_fmt (" id=%d global", ref);
312 if (flags & HF_HIDE)
313 write_string (" hide");
314 write_string (".");
315}
316
317
318void ipf_heading2 (const uchar *s)
319{
320 if (tg_level == 0)
321 {
322 if (para_flag)
323 ipf_para ();
324 ipf_para ();
325 start_hilite (HL_BF);
326 format_output (s, FALSE);
327 end_hilite ();
328 }
329 else
330 format_output (s, FALSE);
331 write_nl ();
332 ipf_env_margin (0);
333}
334
335
336void ipf_description (void)
337{
338 write_fmt (":dl break=fit tsize=%d.", IPF_DESCRIPTION_INDENT);
339 write_nl ();
340}
341
342
343void ipf_enumerate (void)
344{
345 write_line (":ol.");
346}
347
348
349void ipf_itemize (void)
350{
351 write_line (":ul.");
352}
353
354
355void ipf_verbatim_start (enum tag tag_end)
356{
357 switch (tag_end)
358 {
359 case TAG_ENDHEADERS:
360 format_string ("Headers:", STYLE_BOLD, FALSE);
361 break;
362 case TAG_ENDSAMPLECODE:
363 ipf_para ();
364 format_string ("Example:", STYLE_BOLD, FALSE);
365 break;
366 case TAG_ENDEXAMPLE:
367 ipf_margin (env_stack[env_sp].imargin + 4);
368 break;
369 default:
370 break;
371 }
372 write_break ();
373 ipf_hilite (hl_stack[hl_sp]); /* Don't switch font after :cgraphic */
374 write_line (":cgraphic.");
375}
376
377
378void ipf_verbatim_line (void)
379{
380 format_output (input, FALSE);
381 write_nl ();
382}
383
384
385void ipf_verbatim_end (enum tag tag_end)
386{
387 write_line (":ecgraphic.");
388 switch (tag_end)
389 {
390 case TAG_ENDEXAMPLE:
391 ipf_env_margin (env_sp);
392 write_line (".br");
393 para_flag = FALSE;
394 break;
395 default:
396 para_flag = TRUE;
397 break;
398 }
399}
400
401
402void ipf_description_item (const uchar *s)
403{
404 write_break ();
405 write_string (":dt.");
406 make_elements (s);
407 ipf_elements (STYLE_NORMAL);
408 write_break ();
409 write_string (":dd.");
410}
411
412
413void ipf_enumerate_item (void)
414{
415 write_break ();
416 ipf_hilite (hl_stack[hl_sp]); /* Use correct font for number */
417 write_string (":li.");
418}
419
420
421void ipf_itemize_item (void)
422{
423 write_break ();
424 ipf_hilite (hl_stack[hl_sp]); /* Use correct font for mark */
425 write_string (":li.");
426}
427
428
429void ipf_list_item (const uchar *s)
430{
431 ipf_env_margin (env_sp-1);
432 ipf_para ();
433 make_elements (s);
434 ipf_elements (STYLE_NORMAL);
435 ipf_para ();
436 ipf_env_margin (env_sp);
437}
438
439
440void ipf_prototype_start (void)
441{
442 if (para_flag)
443 ipf_para ();
444 format_string (function_count == 1 ? "Prototype:" : "Prototypes:",
445 STYLE_BOLD, FALSE);
446 write_break ();
447 ipf_para ();
448}
449
450
451void ipf_prototype_end (uchar *compat)
452{
453 ipf_elements (STYLE_TTY);
454 ipf_para ();
455 if (compat[0] != 0)
456 {
457 format_string ("Compatibility:", STYLE_BOLD, FALSE);
458 ipf_para ();
459 format_string (compat, STYLE_NORMAL, FALSE);
460 ipf_para ();
461 compat[0] = 0;
462 }
463 format_string ("Description:", STYLE_BOLD, FALSE);
464}
465
466
467void ipf_start (void)
468{
469 write_line (":userdoc.");
470 write_line (":prolog.");
471 write_line (":docprof toc=123.");
472 if (title != NULL)
473 {
474 write_string (":title.");
475 format_string (title, STYLE_NORMAL, FALSE);
476 write_nl ();
477 }
478 write_line (":eprolog.");
479 write_line (":body.");
480}
481
482
483void ipf_table_start (int do_indent, int *widths, int wn)
484{
485 int wi;
486
487 if (do_indent)
488 ipf_margin (env_stack[env_sp].imargin + 4);
489 write_break ();
490 write_string (":table");
491 if (wn != 0)
492 {
493 write_string (" cols='");
494 for (wi = 0; wi < wn; ++wi)
495 {
496 if (wi != 0)
497 write_string (" ");
498 write_fmt ("%d", widths[wi]);
499 }
500 write_string ("'");
501 }
502 write_line (".");
503}
504
505
506void ipf_table_line (const uchar *s, int wn)
507{
508 int wi;
509 uchar word[512], *d;
510
511 if (*s != HBAR)
512 {
513 write_line (":row.");
514 wi = 0;
515 while (*s != 0)
516 {
517 ++wi;
518 write_string (":c.");
519 d = word;
520 while (*s != VBAR && *s != 0)
521 *d++ = *s++;
522 while (d != word && isspace (d[-1]))
523 --d;
524 *d = 0;
525 make_elements (word);
526 ipf_elements (STYLE_NORMAL);
527 write_break ();
528 if (*s != 0)
529 {
530 ++s;
531 while (isspace (*s))
532 ++s;
533 }
534 }
535 if (wi != wn)
536 fatal ("%s:%d: Wrong number of columns", input_fname, line_no);
537 }
538}
539
540
541void ipf_table_end (int do_indent)
542{
543 write_line (":etable.");
544 if (do_indent)
545 {
546 ipf_env_margin (env_sp);
547 write_line (".br");
548 para_flag = FALSE;
549 }
550 else
551 para_flag = TRUE;
552}
553
554
555void ipf_index (const uchar *s)
556{
557 struct word *wp;
558
559 if (!out)
560 return;
561 switch (tg_level)
562 {
563 case 0:
564 write_string (":i1.");
565 ipf_string (s, FALSE);
566 write_nl ();
567 break;
568 case 1:
569 if (*s == 0)
570 idx_refid = 0;
571 else
572 {
573 wp = word_add (s);
574 if (wp->idx == 0)
575 {
576 idx_refid = wp->idx = ++idx_no;
577 write_fmt (":i1 id=%d.", idx_refid);
578 ipf_string (s, FALSE);
579 write_nl ();
580 }
581 else
582 idx_refid = wp->idx;
583 }
584 break;
585 case 2:
586 if (idx_refid == 0)
587 fatal ("%s:%d: %ci2 without %ci1", input_fname, line_no,
588 escape, escape);
589 write_fmt (":i2 refid=%d.", idx_refid);
590 ipf_string (s, FALSE);
591 write_nl ();
592 break;
593 default:
594 abort ();
595 }
596}
597
598
599void ipf_see_also_start (void)
600{
601 if (para_flag)
602 ipf_para ();
603 format_string ("See also: ", STYLE_BOLD, FALSE);
604}
605
606
607void ipf_see_also_word (const uchar *word, const uchar *s)
608{
609 struct word *wp;
610
611 wp = use_reference (word);
612 if (wp != NULL)
613 {
614 if (wp->database == NULL)
615 ipf_begin_link (NULL, wp->ref);
616 else
617 ipf_begin_link (wp->database->str, wp->ref);
618 ipf_string (word, FALSE);
619 ipf_end_link ();
620 }
621 if (*s != 0)
622 {
623 write_string (",");
624 if (output_x >= 60)
625 write_nl ();
626 else
627 write_string (" ");
628 }
629}
630
631
632void ipf_sample_file (const uchar *s)
633{
634 if (para_flag)
635 ipf_para ();
636 format_string ("Example: ", STYLE_BOLD, FALSE);
637 format_string ("See ", STYLE_NORMAL, FALSE);
638 format_string (s, STYLE_TTY, FALSE);
639 para_flag = TRUE;
640}
641
642
643void ipf_libref_section (const uchar *s)
644{
645 if (para_flag)
646 ipf_para ();
647 format_string (s, STYLE_BOLD, FALSE);
648 write_string ("&colon.");
649 para_flag = TRUE;
650}
651
652
653void ipf_function_start (const struct toc *tp)
654{
655 ipf_heading1 (2, tp->ref, tp->global, 0);
656 ipf_string (tp->title, TRUE);
657 if (idx_refid == 0)
658 fatal ("%s:%d: %cfunction without %ci1",
659 input_fname, line_no, escape, escape);
660 ipf_margin (1);
661}
662
663
664void ipf_function_function (const uchar *s)
665{
666 if (out)
667 {
668 write_break ();
669 write_fmt (":i2 refid=%d.", idx_refid);
670 ipf_string (s, FALSE);
671 write_nl ();
672 }
673}
674
675
676void ipf_copy (void)
677{
678 if (para_flag)
679 ipf_para ();
680 switch (env_stack[env_sp].env)
681 {
682 case ENV_TYPEWRITER:
683 ipf_elements (STYLE_TTY);
684 break;
685 default:
686 ipf_elements (STYLE_NORMAL);
687 break;
688 }
689}
690
691
692void ipf_minitoc (const struct toc *tp)
693{
694 int level, any;
695
696 if (tp == NULL)
697 fatal ("%s:%d: Cannot build minitoc before the first heading",
698 input_fname, line_no);
699 if (para_flag)
700 ipf_para ();
701 level = tp->level;
702 tp = tp->next;
703 any = FALSE;
704 while (tp != NULL && tp->level >= level + 1)
705 {
706 if (tp->level == level + 1)
707 {
708 if (!any)
709 {
710 write_line (":lines align=left.");
711 any = TRUE;
712 }
713 ipf_begin_link (NULL, tp->ref);
714 format_output (tp->title, TRUE);
715 ipf_end_link ();
716 write_nl ();
717 }
718 tp = tp->next;
719 }
720 if (any)
721 {
722 write_line (":elines.");
723 para_flag = TRUE;
724 }
725}
726
727
728void ipf_end (void)
729{
730 if (out)
731 {
732 ipf_hilite (0);
733 write_line (":euserdoc.");
734 }
735}
Note: See TracBrowser for help on using the repository browser.