source: trunk/emx/src/emxdoc/text.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: 9.3 KB
Line 
1/* text.c -- Text output
2 Copyright (c) 1993-1999 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 "emxdoc.h"
26#include "text.h"
27#include "lb.h"
28
29static int text_width = 70;
30static int format_width;
31static int format_margin;
32static struct lb *lb;
33static struct lbh *lbh = NULL;
34
35static void text_indent (int margin)
36{
37 uchar *s;
38 int i;
39
40 i = margin - output_x;
41 if (i > 0)
42 {
43 s = alloca (i);
44 memset (s, ' ', i);
45 write_nstring (s, i);
46 }
47}
48
49
50static void text_para (void)
51{
52 if (para_flag)
53 {
54 para_flag = FALSE;
55 write_nl ();
56 }
57}
58
59
60static int isblank (const uchar *p)
61{
62 while (*p != 0)
63 if (*p++ != ' ')
64 return FALSE;
65 return TRUE;
66}
67
68
69void text_output (const uchar *p, int may_break)
70{
71 if (opt_b == 0)
72 {
73 if (may_break && output_x + strlen (p) > format_width)
74 write_nl ();
75 text_indent (format_margin);
76 write_string (p);
77 }
78 else
79 {
80 int rc;
81
82 if (may_break && isblank (p))
83 rc = lb_glue (lb, strlen (p), NULL);
84 else
85 rc = lb_word (lb, strlen (p), p, NULL);
86 if (rc != 0)
87 fatal ("lb_glue or lb_word failed, rc=%d", rc);
88 }
89}
90
91
92static int text_elements (int margin, int width, int newline)
93{
94 const struct element *ep, *ep2;
95 int i, spaces, line, rc;
96 enum style style_stack[STYLE_STACK_SIZE];
97 int style_sp;
98 enum style style = STYLE_NORMAL;
99
100 style_sp = 0;
101 style_stack[style_sp] = style;
102 line = output_line_no; spaces = 0;
103 format_width = width; format_margin = margin;
104 if (opt_b != 0)
105 {
106 rc = lb_init (&lb, margin, width);
107 if (rc != 0)
108 fatal ("lb_init failed, rc=%d", rc);
109 if (output_x > margin)
110 lb_first_lmargin (lb, output_x);
111 }
112
113 for (ep = elements; ep->el != EL_END; ++ep)
114 switch (ep->el)
115 {
116 case EL_WORD:
117 case EL_PUNCT:
118 if (spaces != 0)
119 {
120 format_spaces (spaces, STYLE_NORMAL, TRUE); spaces = 0;
121 }
122 if (ep->wp->special != NULL && ep->wp->special->text != NULL)
123 format_output (ep->wp->special->text, FALSE);
124 else if (style_sp == 0 || style_stack[style_sp] == STYLE_NORMAL)
125 format_string (ep->wp->str, (ep->wp->style != STYLE_NORMAL
126 ? ep->wp->style : style), FALSE);
127 else
128 format_string (ep->wp->str, style_stack[style_sp], FALSE);
129 break;
130 case EL_SPACE:
131 if (opt_b == 0)
132 {
133 spaces += ep->n;
134 i = 0;
135 ep2 = ep + 1;
136 while (ep2->el != EL_END && ep2->el != EL_SPACE)
137 {
138 if (ep2->el == EL_WORD || ep2->el == EL_PUNCT)
139 i += strlen (ep2->wp->str);
140 ++ep2;
141 }
142 if (output_x + spaces + i > format_width)
143 {
144 write_nl ();
145 spaces = 0;
146 }
147 }
148 else
149 format_spaces (ep->n, STYLE_NORMAL, TRUE);
150 break;
151 case EL_BREAK:
152 if (opt_b == 0)
153 {
154 if (output_x != 0 || ep->n)
155 {
156 write_nl (); spaces = 0;
157 }
158 }
159 else
160 lb_penalty (lb, -10000);
161 break;
162 case EL_STYLE:
163 if (style_sp + 1 >= STYLE_STACK_SIZE)
164 fatal ("%s:%d: Style stack overflow", input_fname, line_no);
165 style_stack[++style_sp] = ep->n;
166 break;
167 case EL_ENDSTYLE:
168 if (style_sp == 0)
169 fatal ("%s:%d: Style stack underflow", input_fname, line_no);
170 --style_sp;
171 break;
172 default:
173 abort ();
174 }
175
176 if (opt_b != 0)
177 {
178 struct lb_node lbn;
179
180 if (lbh != NULL)
181 lb_use_hyphenation (lb, lbh);
182 rc = lb_format (lb);
183 if (rc != 0)
184 fatal ("lb_format failed, rc=%d", rc);
185 for (;;)
186 {
187 rc = lb_next (lb, &lbn);
188 if (rc != 0)
189 fatal ("lb_next failed, rc=%d", rc);
190 if (lbn.type == LBN_END)
191 break;
192 switch (lbn.type)
193 {
194 case LBN_WORD:
195 case LBN_PRE:
196 case LBN_POST:
197 text_indent (margin);
198 write_string (lbn.word);
199 break;
200 case LBN_GLUE:
201 text_indent (margin);
202 write_fmt ("%*s", lbn.value, "");
203 break;
204 case LBN_NEWLINE:
205 write_nl ();
206 break;
207 default:
208 abort ();
209 }
210 }
211 lb_exit (&lb);
212 }
213
214 if (newline && output_x > margin)
215 write_nl ();
216 return output_line_no - line;
217}
218
219
220void text_heading1 (void)
221{
222 env_stack[0].tmargin = 0;
223 write_nl ();
224 write_nl ();
225}
226
227
228void text_heading2 (uchar *s)
229{
230 if (tg_level == 0)
231 {
232 if (para_flag)
233 write_nl ();
234 write_nl ();
235 }
236 write_line (s);
237 memset (s, tg_underline, strlen (s));
238 write_line (s);
239}
240
241
242void text_see_also_start (void)
243{
244 if (para_flag)
245 write_nl ();
246}
247
248
249void text_see_also_end (const uchar *s)
250{
251 write_string (" See also: ");
252 make_elements (s);
253 text_elements (output_x, text_width, TRUE);
254}
255
256
257void text_description_item (const uchar *s)
258{
259 write_nl ();
260 text_para ();
261 make_elements (s);
262 text_elements (env_stack[env_sp-1].tmargin, text_width, FALSE);
263 if (output_x + 2 <= env_stack[env_sp].tmargin)
264 write_string (" ");
265 else
266 write_nl ();
267}
268
269
270void text_enumerate_item (void)
271{
272 write_nl ();
273 text_para ();
274 text_indent (env_stack[env_sp-1].tmargin);
275 write_fmt ("%d.", ++env_stack[env_sp].counter);
276}
277
278
279void text_itemize_item (void)
280{
281 write_nl ();
282 text_para ();
283 text_indent (env_stack[env_sp-1].tmargin);
284 write_string ("- ");
285}
286
287
288void text_list_item (const uchar *s)
289{
290 write_nl ();
291 text_para ();
292 make_elements (s);
293 text_elements (env_stack[env_sp-1].tmargin, text_width, TRUE);
294 write_nl ();
295}
296
297
298void text_copy (void)
299{
300 if (para_flag)
301 write_nl ();
302 text_elements (env_stack[env_sp].tmargin, text_width, TRUE);
303}
304
305
306void text_verbatim_start (enum tag tag_end, int *ptmargin)
307{
308 switch (tag_end)
309 {
310 case TAG_ENDHEADERS:
311 break;
312 case TAG_ENDSAMPLECODE:
313 write_nl ();
314 write_line (" Example:");
315 write_nl ();
316 break;
317 case TAG_ENDEXAMPLE:
318 *ptmargin += 4;
319 write_nl ();
320 break;
321 default:
322 write_nl ();
323 break;
324 }
325}
326
327
328static void add_compat (uchar *dst, uchar *compat)
329{
330 int i, len;
331
332 len = strlen (dst);
333 i = 78 - len - strlen (compat) - 2;
334 if (i > 0)
335 {
336 memset (dst + len, ' ', i);
337 len += i;
338 }
339 dst[len++] = '[';
340 strcpy (dst+len, compat);
341 strcat (dst+len, "]");
342 compat[0] = 0;
343}
344
345
346void text_verbatim_line (enum tag tag_end, int tmargin, uchar *compat)
347{
348 uchar buf[512];
349
350 memset (buf, ' ', tmargin);
351 strcpy (buf + tmargin, input);
352 if (tag_end == TAG_ENDHEADERS && compat[0] != 0)
353 add_compat (buf, compat);
354 write_line (buf);
355}
356
357
358void text_function (void)
359{
360 env_stack[0].tmargin = 0;
361 write_nl ();
362 write_line("---------------------------------------"
363 "---------------------------------------");
364}
365
366
367void text_prototype_start (uchar *compat)
368{
369 uchar buf[512];
370
371 if (compat[0] != 0)
372 {
373 buf[0] = 0;
374 add_compat (buf, compat);
375 write_string (buf);
376 }
377 write_nl ();
378}
379
380
381void text_prototype_end (void)
382{
383 text_elements (0, 78, TRUE);
384 env_stack[0].tmargin = 4;
385}
386
387
388void text_toc_line (const uchar *s, const struct toc *tp)
389{
390 write_string (s);
391 write_line (tp->title);
392}
393
394
395void text_table_start (int do_indent, int *ptmargin)
396{
397 if (do_indent)
398 *ptmargin += 4;
399 write_nl ();
400}
401
402
403void text_table_line (const uchar *s, int tmargin)
404{
405 make_elements (s);
406 if (text_elements (tmargin, 78, TRUE) > 1)
407 fatal ("%s:%d: Table entry too long", input_fname, line_no);
408}
409
410
411void text_sample_file (const uchar *s)
412{
413 if (para_flag)
414 write_nl ();
415 write_string (" Example: See ");
416 write_line (s);
417}
418
419
420void text_libref_section (const uchar *s)
421{
422 if (para_flag)
423 write_nl ();
424 write_fmt (" %s:", s);
425 write_nl ();
426 para_flag = TRUE;
427}
428
429
430void text_hyphenation (const char *name)
431{
432 FILE *f;
433 char line[128], *p;
434 int line_no, rc;
435
436 if (opt_b == 0)
437 return;
438 rc = lbh_init (&lbh);
439 if (rc != 0)
440 fatal ("lb_init failed, rc=%d", rc);
441 f = fopen (name, "rt");
442 if (f == NULL)
443 {
444 perror (name);
445 exit (1);
446 }
447 line_no = 0;
448 while (fgets (line, sizeof (line), f) != NULL)
449 {
450 ++line_no;
451 p = strchr (line, '\n');
452 if (p == NULL)
453 fatal ("%s:%d: Line too long", name, line_no);
454 *p = 0;
455 rc = lbh_word (lbh, line);
456 if (rc != 0)
457 fatal ("lbh_word failed, rc=%d", rc);
458 }
459 if (ferror (f))
460 {
461 perror (name);
462 exit (1);
463 }
464 fclose (f);
465}
Note: See TracBrowser for help on using the repository browser.