File: headers\helpcom.h
1
2 /*
3 * helpcom.h
4 *
5 *
6 * Common #defines, structures and code for HC.C and HELP.C
7 *
8 */
9
10 #ifndef HELPCOM_H
11 #define HELPCOM_H
12
13
14 /*
15 * help file signature
16 * If you get a syntax error, remove the LU from the end of the number.
17 */
18
19 #define HELP_SIG (0xAFBC1823LU)
20
21
22 /*
23 * commands imbedded in the help text
24 */
25
26 #define CMD_LITERAL 1 /* next char taken literally */
27 #define CMD_PARA 2 /* paragraph start code */
28 #define CMD_LINK 3 /* hot-link start/end code */
29 #define CMD_FF 4 /* force a form-feed */
30 #define CMD_XONLINE 5 /* exclude from online help on/off */
31 #define CMD_XDOC 6 /* exclude from printed document on/off */
32 #define CMD_CENTER 7 /* center this line */
33 #define CMD_SPACE 8 /* next byte is count of spaces */
34
35 #define MAX_CMD 8
36
37
38 /*
39 * on-line help dimensions
40 */
41
42 #define SCREEN_WIDTH (78)
43 #define SCREEN_DEPTH (22)
44 #define SCREEN_INDENT (1)
45
46
47 /*
48 * printed document dimensions
49 */
50
51 #define PAGE_WIDTH (72) /* width of printed text */
52 #define PAGE_INDENT (2) /* indent all text by this much */
53 #define TITLE_INDENT (1) /* indent titles by this much */
54
55 #define PAGE_RDEPTH (59) /* the total depth (inc. heading) */
56 #define PAGE_HEADING_DEPTH (3) /* depth of the heading */
57 #define PAGE_DEPTH (PAGE_RDEPTH-PAGE_HEADING_DEPTH) /* depth of text */
58
59
60 /*
61 * Document page-break macros. Goto to next page if this close (or closer)
62 * to end of page when starting a CONTENT, TOPIC, or at a BLANK line.
63 */
64
65 #define CONTENT_BREAK (7) /* start of a "DocContent" entry */
66 #define TOPIC_BREAK (4) /* start of each topic under a DocContent entry */
67 #define BLANK_BREAK (2) /* a blank line */
68
69
70 /*
71 * tokens returned by find_token_length
72 */
73
74 #define TOK_DONE (0) /* len == 0 */
75 #define TOK_SPACE (1) /* a run of spaces */
76 #define TOK_LINK (2) /* an entire link */
77 #define TOK_PARA (3) /* a CMD_PARA */
78 #define TOK_NL (4) /* a new-line ('\n') */
79 #define TOK_FF (5) /* a form-feed (CMD_FF) */
80 #define TOK_WORD (6) /* a word */
81 #define TOK_XONLINE (7) /* a CMD_XONLINE */
82 #define TOK_XDOC (8) /* a CMD_XDOC */
83 #define TOK_CENTER (9) /* a CMD_CENTER */
84
85
86 /*
87 * modes for find_token_length() and find_line_width()
88 */
89
90 #define ONLINE 1
91 #define DOC 2
92
93
94 /*
95 * struct PD_INFO used by process_document()
96 */
97
98 typedef struct
99 {
100
101 /* used by process_document -- look but don't touch! */
102
103 int pnum,
104 lnum;
105
106 /* PD_GET_TOPIC is allowed to change these */
107
108 char far *curr;
109 unsigned len;
110
111 /* PD_GET_CONTENT is allowed to change these */
112
113 char far *id;
114 char far *title;
115 int new_page;
116
117 /* general parameters */
118
119 char far *s;
120 int i;
121
122
123 } PD_INFO;
124
125
126 /*
127 * Commands passed to (*get_info)() and (*output)() by process_document()
128 */
129
130 enum PD_COMMANDS
131 {
132
133 /* commands sent to pd_output */
134
135 PD_HEADING, /* call at the top of each page */
136 PD_FOOTING, /* called at the end of each page */
137 PD_PRINT, /* called to send text to the printer */
138 PD_PRINTN, /* called to print a char n times */
139 PD_PRINT_SEC, /* called to print the section title line */
140 PD_START_SECTION, /* called at the start of each section */
141 PD_START_TOPIC, /* called at the start of each topic */
142 PD_SET_SECTION_PAGE, /* set the current sections page number */
143 PD_SET_TOPIC_PAGE, /* set the current topics page number */
144 PD_PERIODIC, /* called just before curr is incremented to next token */
145
146 /* commands sent to pd_get_info */
147
148 PD_GET_CONTENT,
149 PD_GET_TOPIC,
150 PD_RELEASE_TOPIC,
151 PD_GET_LINK_PAGE
152
153 } ;
154
155
156 typedef int (*PD_FUNC)(int cmd, PD_INFO *pd, VOIDPTR info);
157
158
159 int _find_token_length(char far *curr, unsigned len, int *size, int *width);
160 int find_token_length(int mode, char far *curr, unsigned len, int *size, int *width);
161 int find_line_width(int mode, char far *curr, unsigned len);
162 int process_document(PD_FUNC get_info, PD_FUNC output, VOIDPTR info);
163
164
165 /*
166 * Code common to both HC.C and HELP.C (in Fractint).
167 * #include INCLUDE_COMMON once for each program
168 */
169
170
171 #endif
172 #ifdef INCLUDE_COMMON
173
174
175 #ifndef XFRACT
176 #define getint(ptr) (*(int far *)(ptr))
177 #define setint(ptr,n) (*(int far *)(ptr)) = n
178 #else
179 /* Get an int from an unaligned pointer
180 * This routine is needed because this program uses unaligned 2 byte
181 * pointers all over the place.
182 */
183 int
184 getint(ptr)
185 char *ptr;
186 {
187 int s;
188 bcopy(ptr,&s,sizeof(int));
189 return s;
190 }
191
192 /* Set an int to an unaligned pointer */
193 void setint(ptr, n)
194 int n;
195 char *ptr;
196 {
197 bcopy(&n,ptr,sizeof(int));
198 }
199 #endif
200
201
202 static int is_hyphen(char far *ptr) /* true if ptr points to a real hyphen */
203 { /* checkes for "--" and " -" */
204 if ( *ptr != '-' )
205 return (0); /* that was easy! */
206
207 --ptr;
208
209 return ( *ptr!=' ' && *ptr!='-' );
210 }
211
212
213 int _find_token_length(register char far *curr, unsigned len, int *size, int *width)
214 {
215 register int _size = 0;
216 register int _width = 0;
217 int tok;
218
219 if (len == 0)
220 tok = TOK_DONE;
221
222 else
223 {
224 switch ( *curr )
225 {
226 case ' ': /* it's a run of spaces */
227 tok = TOK_SPACE;
228 while ( *curr == ' ' && _size < (int)len )
229 {
230 ++curr;
231 ++_size;
232 ++_width;
233 }
234 break;
235
236 case CMD_SPACE:
237 tok = TOK_SPACE;
238 ++curr;
239 ++_size;
240 _width = *curr;
241 ++curr;
242 ++_size;
243 break;
244
245 case CMD_LINK:
246 tok = TOK_LINK;
247 _size += 1+3*sizeof(int); /* skip CMD_LINK + topic_num + topic_off + page_num */
248 curr += 1+3*sizeof(int);
249
250 while ( *curr != CMD_LINK )
251 {
252 if ( *curr == CMD_LITERAL )
253 {
254 ++curr;
255 ++_size;
256 }
257 ++curr;
258 ++_size;
259 ++_width;
260 assert(_size < len);
261 }
262
263 ++_size; /* skip ending CMD_LINK */
264 break;
265
266 case CMD_PARA:
267 tok = TOK_PARA;
268 _size += 3; /* skip CMD_PARA + indent + margin */
269 break;
270
271 case CMD_XONLINE:
272 tok = TOK_XONLINE;
273 ++_size;
274 break;
275
276 case CMD_XDOC:
277 tok = TOK_XDOC;
278 ++_size;
279 break;
280
281 case CMD_CENTER:
282 tok = TOK_CENTER;
283 ++_size;
284 break;
285
286 case '\n':
287 tok = TOK_NL;
288 ++_size;
289 break;
290
291 case CMD_FF:
292 tok = TOK_FF;
293 ++_size;
294 break;
295
296 default: /* it must be a word */
297 tok = TOK_WORD;
298 for(;;)
299 {
300 if ( _size >= (int)len )
301 break;
302
303 else if ( *curr == CMD_LITERAL )
304 {
305 curr += 2;
306 _size += 2;
307 _width += 1;
308 }
309
310 else if ( *curr == '\0' )
311 {
312 assert(0);
313 }
314
315 else if ((unsigned)*curr <= MAX_CMD || *curr == ' ' ||
316 *curr == '\n')
317 break;
318
319 else if ( *curr == '-' )
320 {
321 ++curr;
322 ++_size;
323 ++_width;
324 if ( is_hyphen(curr-1) )
325 break;
326 }
327
328 else
329 {
330 ++curr;
331 ++_size;
332 ++_width;
333 }
334 }
335 break;
336 } /* switch */
337 }
338
339 if (size != NULL) *size = _size;
340 if (width != NULL) *width = _width;
341
342 return (tok);
343 }
344
345
346 int find_token_length(int mode, char far *curr, unsigned len, int *size, int *width)
347 {
348 int tok;
349 int t;
350 int _size;
351
352 tok = _find_token_length(curr, len, &t, width);
353
354 if ( (tok == TOK_XONLINE && mode == ONLINE) ||
355 (tok == TOK_XDOC && mode == DOC) )
356 {
357 _size = 0;
358
359 for(;;)
360 {
361 curr += t;
362 len -= t;
363 _size += t;
364
365 tok = _find_token_length(curr, len, &t, NULL);
366
367 if ( (tok == TOK_XONLINE && mode == ONLINE) ||
368 (tok == TOK_XDOC && mode == DOC) ||
369 (tok == TOK_DONE) )
370 break;
371 }
372
373 _size += t;
374 }
375 else
376 _size = t;
377
378 if (size != NULL )
379 *size = _size;
380
381 return (tok);
382 }
383
384
385 int find_line_width(int mode, char far *curr, unsigned len)
386 {
387 int size = 0,
388 width = 0,
389 lwidth = 0,
390 done = 0,
391 tok;
392
393 do
394 {
395 tok = find_token_length(mode, curr, len, &size, &width);
396
397 switch(tok)
398 {
399 case TOK_DONE:
400 case TOK_PARA:
401 case TOK_NL:
402 case TOK_FF:
403 done = 1;
404 break;
405
406 case TOK_XONLINE:
407 case TOK_XDOC:
408 case TOK_CENTER:
409 curr += size;
410 len -= size;
411 break;
412
413 default: /* TOK_SPACE, TOK_LINK or TOK_WORD */
414 lwidth += width;
415 curr += size;
416 len -= size;
417 break;
418 }
419 }
420 while ( !done );
421
422 return (lwidth);
423 }
424
425
426 #define DO_PRINTN(ch,n) ( pd.s = &(ch), pd.i = (n), output(PD_PRINTN, &pd, info) )
427 #define DO_PRINT(str,n) ( pd.s = (str), pd.i = (n), output(PD_PRINT, &pd, info) )
428
429
430 int process_document(PD_FUNC get_info, PD_FUNC output, VOIDPTR info)
431 {
432 int skip_blanks;
433 int tok;
434 int size,
435 width;
436 int col;
437 char page_text[10];
438 PD_INFO pd;
439 char nl = '\n',
440 sp = ' ';
441 int first_section,
442 first_topic;
443
444 pd.pnum = 1;
445 pd.lnum = 0;
446
447 col = 0;
448
449 output(PD_HEADING, &pd, info);
450
451 first_section = 1;
452
453 while ( get_info(PD_GET_CONTENT, &pd, info) )
454 {
455 if ( !output(PD_START_SECTION, &pd, info) )
456 return (0);
457
458 if ( pd.new_page && pd.lnum != 0 )
459 {
460 if ( !output(PD_FOOTING, &pd, info) )
461 return (0);
462 ++pd.pnum;
463 pd.lnum = 0;
464 if ( !output(PD_HEADING, &pd, info) )
465 return (0);
466 }
467
468 else
469 {
470 if ( pd.lnum+2 > PAGE_DEPTH-CONTENT_BREAK )
471 {
472 if ( !output(PD_FOOTING, &pd, info) )
473 return (0);
474 ++pd.pnum;
475 pd.lnum = 0;
476 if ( !output(PD_HEADING, &pd, info) )
477 return (0);
478 }
479 else if (pd.lnum > 0)
480 {
481 if ( !DO_PRINTN(nl, 2) )
482 return (0);
483 pd.lnum += 2;
484 }
485 }
486
487 if ( !output(PD_SET_SECTION_PAGE, &pd, info) )
488 return (0);
489
490 if ( !first_section )
491 {
492 if ( !output(PD_PRINT_SEC, &pd, info) )
493 return (0);
494 ++pd.lnum;
495 }
496
497 col = 0;
498
499 first_topic = 1;
500
501 while ( get_info(PD_GET_TOPIC, &pd, info) )
502 {
503 if ( !output(PD_START_TOPIC, &pd, info) )
504 return (0);
505
506 skip_blanks = 0;
507 col = 0;
508
509 if ( !first_section ) /* do not skip blanks for DocContents */
510 {
511 while (pd.len > 0)
512 {
513 tok = find_token_length(DOC, pd.curr, pd.len, &size, NULL);
514 if (tok != TOK_XDOC && tok != TOK_XONLINE &&
515 tok != TOK_NL && tok != TOK_DONE )
516 break;
517 pd.curr += size;
518 pd.len -= size;
519 }
520 if ( first_topic && pd.len != 0 )
521 {
522 if ( !DO_PRINTN(nl, 1) )
523 return (0);
524 ++pd.lnum;
525 }
526 }
527
528 if ( pd.lnum > PAGE_DEPTH-TOPIC_BREAK )
529 {
530 if ( !output(PD_FOOTING, &pd, info) )
531 return (0);
532 ++pd.pnum;
533 pd.lnum = 0;
534 if ( !output(PD_HEADING, &pd, info) )
535 return (0);
536 }
537 else if ( !first_topic )
538 {
539 if ( !DO_PRINTN(nl, 1) )
540 return (0);
541 pd.lnum++;
542 }
543
544 if ( !output(PD_SET_TOPIC_PAGE, &pd, info) )
545 return (0);
546
547 do
548 {
549 if ( !output(PD_PERIODIC, &pd, info) )
550 return (0);
551
552 tok = find_token_length(DOC, pd.curr, pd.len, &size, &width);
553
554 switch ( tok )
555 {
556 case TOK_PARA:
557 {
558 int indent,
559 margin;
560 unsigned holdlen = 0;
561 char far *holdcurr = 0;
562 int in_link = 0;
563
564 ++pd.curr;
565
566 indent = *pd.curr++;
567 margin = *pd.curr++;
568
569 pd.len -= 3;
570
571 if ( !DO_PRINTN(sp, indent) )
572 return (0);
573
574 col = indent;
575
576 for(;;)
577 {
578 if ( !output(PD_PERIODIC, &pd, info) )
579 return (0);
580
581 tok = find_token_length(DOC, pd.curr, pd.len, &size, &width);
582
583 if ( tok == TOK_NL || tok == TOK_FF )
584 break;
585
586 if ( tok == TOK_DONE )
587 {
588 if (in_link == 0)
589 {
590 col = 0;
591 ++pd.lnum;
592 if ( !DO_PRINTN(nl, 1) )
593 return (0);
594 break;
595 }
596
597 else if (in_link == 1)
598 {
599 tok = TOK_SPACE;
600 width = 1;
601 size = 0;
602 ++in_link;
603 }
604
605 else if (in_link == 2)
606 {
607 tok = TOK_WORD;
608 width = strlen(page_text);
609 col += 8 - width;
610 size = 0;
611 pd.curr = page_text;
612 ++in_link;
613 }
614
615 else if (in_link == 3)
616 {
617 pd.curr = holdcurr;
618 pd.len = holdlen;
619 in_link = 0;
620 continue;
621 }
622 }
623
624 if ( tok == TOK_PARA )
625 {
626 col = 0; /* fake a nl */
627 ++pd.lnum;
628 if ( !DO_PRINTN(nl, 1) )
629 return (0);
630 break;
631 }
632
633 if (tok == TOK_XONLINE || tok == TOK_XDOC )
634 {
635 pd.curr += size;
636 pd.len -= size;
637 continue;
638 }
639
640 if ( tok == TOK_LINK )
641 {
642 pd.s = pd.curr+1;
643 if ( get_info(PD_GET_LINK_PAGE, &pd, info) )
644 {
645 in_link = 1;
646 sprintf(page_text, "(p. %d)", pd.i);
647 }
648 else
649 in_link = 3;
650 holdcurr = pd.curr + size;
651 holdlen = pd.len - size;
652 pd.len = size - 2 - 3*sizeof(int);
653 pd.curr += 1 + 3*sizeof(int);
654 continue;
655 }
656
657 /* now tok is TOK_SPACE or TOK_WORD */
658
659 if (col+width > PAGE_WIDTH)
660 { /* go to next line... */
661 if ( !DO_PRINTN(nl, 1) )
662 return (0);
663 if ( ++pd.lnum >= PAGE_DEPTH )
664 {
665 if ( !output(PD_FOOTING, &pd, info) )
666 return (0);
667 ++pd.pnum;
668 pd.lnum = 0;
669 if ( !output(PD_HEADING, &pd, info) )
670 return (0);
671 }
672
673 if ( tok == TOK_SPACE )
674 width = 0; /* skip spaces at start of a line */
675
676 if ( !DO_PRINTN(sp, margin) )
677 return (0);
678 col = margin;
679 }
680
681 if (width > 0)
682 {
683 if (tok == TOK_SPACE)
684 {
685 if ( !DO_PRINTN(sp, width) )
686 return (0);
687 }
688 else
689 {
690 if ( !DO_PRINT(pd.curr, (size==0) ? width : size) )
691 return (0);
692 }
693 }
694
695 col += width;
696 pd.curr += size;
697 pd.len -= size;
698 }
699
700 skip_blanks = 0;
701 width = size = 0;
702 break;
703 }
704
705 case TOK_NL:
706 if (skip_blanks && col == 0)
707 break;
708
709 ++pd.lnum;
710
711 if ( pd.lnum >= PAGE_DEPTH || (col == 0 && pd.lnum >= PAGE_DEPTH-BLANK_BREAK) )
712 {
713 if ( col != 0 ) /* if last wasn't a blank line... */
714 {
715 if ( !DO_PRINTN(nl, 1) )
716 return (0);
717 }
718 if ( !output(PD_FOOTING, &pd, info) )
719 return (0);
720 ++pd.pnum;
721 pd.lnum = 0;
722 skip_blanks = 1;
723 if ( !output(PD_HEADING, &pd, info) )
724 return (0);
725 }
726 else
727 {
728 if ( !DO_PRINTN(nl, 1) )
729 return (0);
730 }
731
732 col = 0;
733 break;
734
735 case TOK_FF:
736 if (skip_blanks)
737 break;
738 if ( !output(PD_FOOTING, &pd, info) )
739 return (0);
740 col = 0;
741 pd.lnum = 0;
742 ++pd.pnum;
743 if ( !output(PD_HEADING, &pd, info) )
744 return (0);
745 break;
746
747 case TOK_CENTER:
748 width = (PAGE_WIDTH - find_line_width(DOC,pd.curr,pd.len)) / 2;
749 if ( !DO_PRINTN(sp, width) )
750 return (0);
751 break;
752
753 case TOK_LINK:
754 skip_blanks = 0;
755 if ( !DO_PRINT(pd.curr+1+3*sizeof(int),
756 size-3*sizeof(int)-2) )
757 return (0);
758 pd.s = pd.curr+1;
759 if ( get_info(PD_GET_LINK_PAGE, &pd, info) )
760 {
761 width += 9;
762 sprintf(page_text, " (p. %d)", pd.i);
763 if ( !DO_PRINT(page_text, strlen(page_text)) )
764 return (0);
765 }
766 break;
767
768 case TOK_WORD:
769 skip_blanks = 0;
770 if ( !DO_PRINT(pd.curr, size) )
771 return (0);
772 break;
773
774 case TOK_SPACE:
775 skip_blanks = 0;
776 if ( !DO_PRINTN(sp, width) )
777 return (0);
778 break;
779
780 case TOK_DONE:
781 case TOK_XONLINE: /* skip */
782 case TOK_XDOC: /* ignore */
783 break;
784
785 } /* switch */
786
787 pd.curr += size;
788 pd.len -= size;
789 col += width;
790 }
791 while (pd.len > 0);
792
793 get_info(PD_RELEASE_TOPIC, &pd, info);
794
795 first_topic = 0;
796 } /* while */
797
798 first_section = 0;
799 } /* while */
800
801 if ( !output(PD_FOOTING, &pd, info) )
802 return (0);
803
804 return (1);
805 }
806
807 #undef DO_PRINT
808 #undef DO_PRINTN
809
810
811 #undef INCLUDE_COMMON 812 #endif /* #ifdef INCLUDE_COMMON */
813