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