home *** CD-ROM | disk | FTP | other *** search
- /*
- * help.c
- *
- *
- *
- * Revision history:
- *
- * 2-26-90 EAN Initial version.
- *
- *
- */
-
- #ifndef TEST /* kills all those assert macros in production version */
- #define NDEBUG
- #endif
-
- #define INCLUDE_COMMON /* include common code in helpcom.h */
-
- #include <stdio.h>
- #include <stdlib.h>
- #ifndef XFRACT
- #include <io.h>
- #include <dos.h>
- #endif
- #include <fcntl.h>
- #include <string.h>
- #include <time.h>
- #include <assert.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #ifdef XFRACT
- #include <unistd.h>
- #endif
- #include "prototyp.h"
- #include "helpdefs.h"
-
- #define MAX_HIST 16 /* number of pages we'll remember */
- #define ALT_F1 1104
- #define ACTION_CALL 0 /* values returned by help_topic() */
- #define ACTION_PREV 1
- #define ACTION_PREV2 2 /* special - go back two topics */
- #define ACTION_INDEX 3
- #define ACTION_QUIT 4
- #define F_HIST (1<<0) /* flags for help_topic() */
- #define F_INDEX (1<<1)
- #define MAX_PAGE_SIZE (80*25) /* no page of text may be larger */
- #define TEXT_START_ROW 2 /* start print the help text here */
-
- typedef struct
- {
- BYTE r, c;
- int width;
- unsigned offset;
- int topic_num;
- unsigned topic_off;
- } LINK;
-
- typedef struct
- {
- int topic_num;
- unsigned topic_off;
- } LABEL;
-
- typedef struct
- {
- unsigned offset;
- unsigned len;
- int margin;
- } PAGE;
-
- typedef struct
- {
- int topic_num;
- unsigned topic_off;
- int link;
- } HIST;
-
- struct help_sig_info
- {
- unsigned long sig;
- int version;
- unsigned long base; /* only if added to fractint.exe */
- } ;
-
- void print_document(char *outfname, int (*msg_func)(int,int), int save_extraseg );
- static int print_doc_msg_func(int pnum, int num_pages);
-
- /* stuff from fractint */
-
- static int help_file = -1; /* help file handle */
- static long base_off; /* offset to help info in help file */
- static int max_links; /* max # of links in any page */
- static int max_pages; /* max # of pages in any topic */
- static int num_label; /* number of labels */
- static int num_topic; /* number of topics */
- static int curr_hist = 0; /* current pos in history */
-
- /* these items alloc'ed in init_help... */
-
- static long far *topic_offset; /* 4*num_topic */
- static LABEL far *label; /* 4*num_label */
- static HIST far *hist; /* 6*MAX_HIST (96 bytes) */
-
- /* these items alloc'ed only while help is active... */
-
- static char far *buffer; /* MAX_PAGE_SIZE (2048 bytes) */
- static LINK far *link_table; /* 10*max_links */
- static PAGE far *page_table; /* 4*max_pages */
-
- static void help_seek(long pos)
- {
- lseek(help_file, base_off+pos, SEEK_SET);
- }
-
- static void displaycc(int row, int col, int color, int ch)
- {
- #ifndef XFRACT
- static char *s = "?";
- #else
- static char s[] = "?";
- #endif
-
- if (text_type == 1) /* if 640x200x2 mode */
- {
- /*
- * This is REALLY ugly, but it works. Non-current links (ones that
- * would be bold if 640x200 supported it) are in upper-case and the
- * current item is inversed.
- *
- */
-
- if (color & INVERSE)
- color = (signed int)INVERSE;
- else if (color & BRIGHT)
- {
- color = 0; /* normal */
- if (ch>='a' && ch<='z')
- ch += 'A' - 'a';
- }
- else
- color = 0; /* normal */
- }
-
- s[0] = (char)ch;
- putstring(row, col, color, s);
- }
-
- static void display_text(int row, int col, int color, char far *text, unsigned len)
- {
- while (len-- != 0)
- {
- if (*text == CMD_LITERAL)
- {
- ++text;
- --len;
- }
- displaycc(row, col++, color, *text++);
- }
- }
-
- static void display_parse_text(char far *text, unsigned len, int start_margin, int *num_link, LINK far *link)
- {
- char far *curr;
- int row, col;
- int tok;
- int size,
- width;
-
- textcbase = SCREEN_INDENT;
- textrbase = TEXT_START_ROW;
-
- curr = text;
- row = 0;
- col = 0;
-
- size = width = 0;
-
- if (start_margin >= 0)
- tok = TOK_PARA;
- else
- tok = -1;
-
- for(;;)
- {
- switch ( tok )
- {
- case TOK_PARA:
- {
- int indent,
- margin;
-
- if (size > 0)
- {
- ++curr;
- indent = *curr++;
- margin = *curr++;
- len -= 3;
- }
- else
- {
- indent = start_margin;
- margin = start_margin;
- }
-
- col = indent;
-
- for(;;)
- {
- tok = find_token_length(ONLINE, curr, len, &size, &width);
-
- if (tok == TOK_DONE || tok == TOK_NL || tok == TOK_FF )
- break;
-
- if (tok == TOK_PARA)
- {
- col = 0; /* fake a new-line */
- row++;
- break;
- }
-
- if (tok == TOK_XONLINE || tok == TOK_XDOC)
- {
- curr += size;
- len -= size;
- continue;
- }
-
- /* now tok is TOK_SPACE or TOK_LINK or TOK_WORD */
-
- if (col+width > SCREEN_WIDTH)
- { /* go to next line... */
- col = margin;
- ++row;
-
- if ( tok == TOK_SPACE )
- width = 0; /* skip spaces at start of a line */
- }
-
- if (tok == TOK_LINK)
- {
- display_text(row, col, C_HELP_LINK, curr+1+3*sizeof(int), width);
- if (num_link != NULL)
- {
- link[*num_link].r = (BYTE)row;
- link[*num_link].c = (BYTE)col;
- link[*num_link].topic_num = getint(curr+1);
- link[*num_link].topic_off = getint(curr+1+sizeof(int));
- link[*num_link].offset = (unsigned) ((curr+1+3*sizeof(int)) - text);
- link[*num_link].width = width;
- ++(*num_link);
- }
- }
- else if (tok == TOK_WORD )
- display_text(row, col, C_HELP_BODY, curr, width);
-
- col += width;
- curr += size;
- len -= size;
- }
-
- width = size = 0;
- break;
- }
-
- case TOK_CENTER:
- col = find_line_width(ONLINE, curr, len);
- col = (SCREEN_WIDTH-col)/2;
- if (col < 0)
- col = 0;
- break;
-
- case TOK_NL:
- col = 0;
- ++row;
- break;
-
- case TOK_LINK:
- display_text(row, col, C_HELP_LINK, curr+1+3*sizeof(int), width);
- if (num_link != NULL)
- {
- link[*num_link].r = (BYTE)row;
- link[*num_link].c = (BYTE)col;
- link[*num_link].topic_num = getint(curr+1);
- link[*num_link].topic_off = getint(curr+1+sizeof(int));
- link[*num_link].offset = (unsigned) ((curr+1+3*sizeof(int)) - text);
- link[*num_link].width = width;
- ++(*num_link);
- }
- break;
-
- case TOK_XONLINE: /* skip */
- case TOK_FF: /* ignore */
- case TOK_XDOC: /* ignore */
- case TOK_DONE:
- case TOK_SPACE:
- break;
-
- case TOK_WORD:
- display_text(row, col, C_HELP_BODY, curr, width);
- break;
- } /* switch */
-
- curr += size;
- len -= size;
- col += width;
-
- if (len == 0)
- break;
-
- tok = find_token_length(ONLINE, curr, len, &size, &width);
- } /* for(;;) */
-
- textcbase = 0;
- textrbase = 0;
- }
-
- static void color_link(LINK far *link, int color)
- {
- textcbase = SCREEN_INDENT;
- textrbase = TEXT_START_ROW;
-
- if (text_type == 1) /* if 640x200x2 mode */
- display_text(link->r, link->c, color, buffer+link->offset, link->width);
- else
- setattr(link->r, link->c, color, link->width);
-
- textcbase = 0;
- textrbase = 0;
- }
-
- /* #define PUT_KEY(name, descrip) putstring(-1,-1,C_HELP_INSTR_KEYS,name), putstring(-1,-1,C_HELP_INSTR," "descrip" ") */
- #ifndef XFRACT
- #define PUT_KEY(name, descrip) putstring(-1,-1,C_HELP_INSTR,name); putstring(-1,-1,C_HELP_INSTR,":"descrip" ")
- #else
- #define PUT_KEY(name, descrip) putstring(-1,-1,C_HELP_INSTR,name);\
- putstring(-1,-1,C_HELP_INSTR,":");\
- putstring(-1,-1,C_HELP_INSTR,descrip);\
- putstring(-1,-1,C_HELP_INSTR," ")
- #endif
-
- static void helpinstr(void)
- {
- int ctr;
-
- for (ctr=0; ctr<80; ctr++)
- putstring(24, ctr, C_HELP_INSTR, " ");
-
- movecursor(24, 1);
- PUT_KEY("F1", "Index");
- #ifndef XFRACT
- PUT_KEY("\030\031\033\032", "Select");
- #else
- PUT_KEY("K J H L", "Select");
- #endif
- PUT_KEY("Enter", "Go to");
- PUT_KEY("Backspace", "Last topic");
- PUT_KEY("Escape", "Exit help");
- }
-
- static void printinstr(void)
- {
- int ctr;
-
- for (ctr=0; ctr<80; ctr++)
- putstring(24, ctr, C_HELP_INSTR, " ");
-
- movecursor(24, 1);
- PUT_KEY("Escape", "Abort");
- }
-
- #undef PUT_KEY
-
- static void display_page(char far *title, char far *text, unsigned text_len, int page, int num_pages, int start_margin, int *num_link, LINK far *link)
- {
- char temp[9];
-
- helptitle();
- helpinstr();
- setattr(2, 0, C_HELP_BODY, 80*22);
- putstringcenter(1, 0, 80, C_HELP_HDG, title);
- sprintf(temp, "%2d of %d", page+1, num_pages);
- #ifndef XFRACT
- putstring(1, 79-(6 + ((num_pages>=10)?2:1)), C_HELP_INSTR, temp);
- #else
- /* Some systems (Ultrix) mess up if you write to column 80 */
- putstring(1, 78-(6 + ((num_pages>=10)?2:1)), C_HELP_INSTR, temp);
- #endif
-
- if (text != NULL)
- display_parse_text(text, text_len, start_margin, num_link, link);
-
- movecursor(25, 80); /* hide cursor */
- }
-
- /*
- * int overlap(int a, int a2, int b, int b2);
- *
- * If a, a2, b, and b2 are points on a line, this function returns the
- * distance of intersection between a-->a2 and b-->b2. If there is no
- * intersection between the lines this function will return a negative number
- * representing the distance between the two lines.
- *
- * There are six possible cases of intersection between the lines:
- *
- * a a2
- * | |
- * b b2 | | b b2
- * |---(1)---| | | |---(2)---|
- * | |
- * b | b2 b | b2
- * |------(3)----| |------(4)-----|
- * | |
- * b | | b2
- * |------+--------(5)----------+---|
- * | |
- * | b b2 |
- * | |--(6)--| |
- * | |
- * | |
- *
- */
-
- static int overlap(int a, int a2, int b, int b2)
- {
- if ( b < a )
- {
- if ( b2 >= a2 )
- return ( a2 - a ); /* case (5) */
-
- return ( b2 - a ); /* case (1), case (3) */
- }
-
- if ( b2 <= a2 )
- return ( b2 - b ); /* case (6) */
-
- return ( a2 - b ); /* case (2), case (4) */
- }
-
- static int dist1(int a, int b)
- {
- int t = a - b;
-
- return (abs(t));
- }
-
- #ifdef __TURBOC__
- # pragma warn -def /* turn off "Possible use before definition" warning */
- #endif
-
- static int find_link_updown(LINK far *link, int num_link, int curr_link, int up)
- {
- int ctr,
- curr_c2,
- best_overlap = 0,
- temp_overlap;
- LINK far *curr,
- far *temp,
- far *best;
- int temp_dist;
-
- curr = &link[curr_link];
- best = NULL;
- curr_c2 = curr->c + curr->width - 1;
-
- for (ctr=0, temp=link; ctr<num_link; ctr++, temp++)
- {
- if ( ctr != curr_link &&
- ( (up && temp->r < curr->r) || (!up && temp->r > curr->r) ) )
- {
- temp_overlap = overlap(curr->c, curr_c2, temp->c, temp->c+temp->width-1);
- /* if >= 3 lines between, prioritize on vertical distance: */
- if ((temp_dist = dist1(temp->r, curr->r)) >= 4)
- temp_overlap -= temp_dist * 100;
-
- if (best != NULL)
- {
- if ( best_overlap >= 0 && temp_overlap >= 0 )
- { /* if they're both under curr set to closest in y dir */
- if ( dist1(best->r, curr->r) > temp_dist )
- best = NULL;
- }
- else
- {
- if ( best_overlap < temp_overlap )
- best = NULL;
- }
- }
-
- if (best == NULL)
- {
- best = temp;
- best_overlap = temp_overlap;
- }
- }
- }
-
- return ( (best==NULL) ? -1 : (int)(best-link) );
- }
-
- static int find_link_leftright(LINK far *link, int num_link, int curr_link, int left)
- {
- int ctr,
- curr_c2,
- best_c2 = 0,
- temp_c2,
- best_dist = 0,
- temp_dist;
- LINK far *curr,
- far *temp,
- far *best;
-
- curr = &link[curr_link];
- best = NULL;
- curr_c2 = curr->c + curr->width - 1;
-
- for (ctr=0, temp=link; ctr<num_link; ctr++, temp++)
- {
- temp_c2 = temp->c + temp->width - 1;
-
- if ( ctr != curr_link &&
- ( (left && temp_c2 < (int)curr->c) || (!left && (int)temp->c > curr_c2) ) )
- {
- temp_dist = dist1(curr->r, temp->r);
-
- if (best != NULL)
- {
- if ( best_dist == 0 && temp_dist == 0 ) /* if both on curr's line... */
- {
- if ( ( left && dist1(curr->c, best_c2) > dist1(curr->c, temp_c2) ) ||
- ( !left && dist1(curr_c2, best->c) > dist1(curr_c2, temp->c) ) )
- best = NULL;
- }
- else
- {
- if ( best_dist >= temp_dist ) /* if temp is closer... */
- best = NULL;
- }
- } /* if (best...) */
-
- if (best == NULL)
- {
- best = temp;
- best_dist = temp_dist;
- best_c2 = temp_c2;
- }
- }
- } /* for */
-
- return ( (best==NULL) ? -1 : (int)(best-link) );
- }
-
- #ifdef __TURBOC__
- # pragma warn .def /* back to default */
- # pragma warn -par /* now turn off "Parameter not used" warning */
- #endif
-
- #ifdef __CLINT__
- # pragma argsused
- #endif
-
- static int find_link_key(LINK far *link, int num_link, int curr_link, int key)
- {
- link = NULL; /* just for warning */
- switch (key)
- {
- case TAB: return ( (curr_link>=num_link-1) ? -1 : curr_link+1 );
- case BACK_TAB: return ( (curr_link<=0) ? -1 : curr_link-1 );
- default: assert(0); return (-1);
- }
- }
-
- #ifdef __TURBOC__
- # pragma warn .par /* back to default */
- #endif
-
- static int do_move_link(LINK far *link, int num_link, int *curr, int (*f)(LINK far *,int,int,int), int val)
- {
- int t;
-
- if (num_link > 1)
- {
- if ( f == NULL )
- t = val;
- else
- t = (*f)(link, num_link, *curr, val);
-
- if ( t >= 0 && t != *curr )
- {
- color_link(&link[*curr], C_HELP_LINK);
- *curr = t;
- color_link(&link[*curr], C_HELP_CURLINK);
- return (1);
- }
- }
-
- return (0);
- }
-
- static int help_topic(HIST *curr, HIST *next, int flags)
- {
- int len;
- int key;
- int num_pages;
- int num_link;
- int page;
- int curr_link;
- char title[81];
- long where;
- int draw_page;
- int action;
- BYTE ch;
-
- where = topic_offset[curr->topic_num]+sizeof(int); /* to skip flags */
- curr_link = curr->link;
-
- help_seek(where);
-
- read(help_file, (char *)&num_pages, sizeof(int));
- assert(num_pages>0 && num_pages<=max_pages);
-
- farread(help_file, (char far *)page_table, 3*sizeof(int)*num_pages);
-
- read(help_file, &ch, 1);
- len = ch;
- assert(len<81);
- read(help_file, (char *)title, len);
- title[len] = '\0';
-
- where += sizeof(int) + num_pages*3*sizeof(int) + 1 + len + sizeof(int);
-
- for(page=0; page<num_pages; page++)
- if (curr->topic_off >= page_table[page].offset &&
- curr->topic_off < page_table[page].offset+page_table[page].len )
- break;
-
- assert(page < num_pages);
-
- action = -1;
- draw_page = 2;
-
- do
- {
- if (draw_page)
- {
- help_seek(where+page_table[page].offset);
- farread(help_file, buffer, page_table[page].len);
-
- num_link = 0;
- display_page(title, buffer, page_table[page].len, page, num_pages,
- page_table[page].margin, &num_link, link_table);
-
- if (draw_page==2)
- {
- assert(num_link<=0 || (curr_link>=0 && curr_link<num_link));
- }
- else if (draw_page==3)
- curr_link = num_link - 1;
- else
- curr_link = 0;
-
- if (num_link > 0)
- color_link(&link_table[curr_link], C_HELP_CURLINK);
-
- draw_page = 0;
- }
-
- key = getakey();
-
- switch(key)
- {
- case PAGE_DOWN:
- if (page<num_pages-1)
- {
- page++;
- draw_page = 1;
- }
- break;
-
- case PAGE_UP:
- if (page>0)
- {
- page--;
- draw_page = 1;
- }
- break;
-
- case HOME:
- if ( page != 0 )
- {
- page = 0;
- draw_page = 1;
- }
- else
- do_move_link(link_table, num_link, &curr_link, NULL, 0);
- break;
-
- case END:
- if ( page != num_pages-1 )
- {
- page = num_pages-1;
- draw_page = 3;
- }
- else
- do_move_link(link_table, num_link, &curr_link, NULL, num_link-1);
- break;
-
- case TAB:
- if ( !do_move_link(link_table, num_link, &curr_link, find_link_key, key) &&
- page<num_pages-1 )
- {
- ++page;
- draw_page = 1;
- }
- break;
-
- case BACK_TAB:
- if ( !do_move_link(link_table, num_link, &curr_link, find_link_key, key) &&
- page>0 )
- {
- --page;
- draw_page = 3;
- }
- break;
-
- case DOWN_ARROW:
- if ( !do_move_link(link_table, num_link, &curr_link, find_link_updown, 0) &&
- page<num_pages-1 )
- {
- ++page;
- draw_page = 1;
- }
- break;
-
- case UP_ARROW:
- if ( !do_move_link(link_table, num_link, &curr_link, find_link_updown, 1) &&
- page>0 )
- {
- --page;
- draw_page = 3;
- }
- break;
-
- case LEFT_ARROW:
- do_move_link(link_table, num_link, &curr_link, find_link_leftright, 1);
- break;
-
- case RIGHT_ARROW:
- do_move_link(link_table, num_link, &curr_link, find_link_leftright, 0);
- break;
-
- case ESC: /* exit help */
- action = ACTION_QUIT;
- break;
-
- case BACKSPACE: /* prev topic */
- case ALT_F1:
- if (flags & F_HIST)
- action = ACTION_PREV;
- break;
-
- case F1: /* help index */
- if (!(flags & F_INDEX))
- action = ACTION_INDEX;
- break;
-
- case ENTER:
- case ENTER_2:
- if (num_link > 0)
- {
- next->topic_num = link_table[curr_link].topic_num;
- next->topic_off = link_table[curr_link].topic_off;
- action = ACTION_CALL;
- }
- break;
- } /* switch */
- }
- while ( action == -1 );
-
- curr->topic_off = page_table[page].offset;
- curr->link = curr_link;
-
- return (action);
- }
-
- int help(int action)
- {
- static FCODE unknowntopic_msg[] = "Unknown Help Topic";
- HIST curr;
- int oldlookatmouse;
- int oldhelpmode;
- int flags;
- HIST next;
-
- if (helpmode == -1) /* is help disabled? */
- {
- return (0);
- }
-
- if (help_file == -1)
- {
- buzzer(2);
- return (0);
- }
-
- buffer = farmemalloc((long)MAX_PAGE_SIZE + sizeof(LINK)*max_links +
- sizeof(PAGE)*max_pages);
-
- if (buffer == NULL)
- {
- buzzer(2);
- return (0);
- }
-
- link_table = (LINK far *)(&buffer[MAX_PAGE_SIZE]);
- page_table = (PAGE far *)(&link_table[max_links]);
-
- oldlookatmouse = lookatmouse;
- lookatmouse = 0;
- timer_start -= clock_ticks();
- stackscreen();
-
- if (helpmode >= 0)
- {
- next.topic_num = label[helpmode].topic_num;
- next.topic_off = label[helpmode].topic_off;
- }
- else
- {
- next.topic_num = helpmode;
- next.topic_off = 0;
- }
-
- oldhelpmode = helpmode;
-
- if (curr_hist <= 0)
- action = ACTION_CALL; /* make sure it isn't ACTION_PREV! */
-
- do
- {
- switch(action)
- {
- case ACTION_PREV2:
- if (curr_hist > 0)
- curr = hist[--curr_hist];
-
- /* fall-through */
-
- case ACTION_PREV:
- if (curr_hist > 0)
- curr = hist[--curr_hist];
- break;
-
- case ACTION_QUIT:
- break;
-
- case ACTION_INDEX:
- next.topic_num = label[HELP_INDEX].topic_num;
- next.topic_off = label[HELP_INDEX].topic_off;
-
- /* fall-through */
-
- case ACTION_CALL:
- curr = next;
- curr.link = 0;
- break;
- } /* switch */
-
- flags = 0;
- if (curr.topic_num == label[HELP_INDEX].topic_num)
- flags |= F_INDEX;
- if (curr_hist > 0)
- flags |= F_HIST;
-
- if ( curr.topic_num >= 0 )
- action = help_topic(&curr, &next, flags);
- else
- {
- if ( curr.topic_num == -100 )
- {
- print_document("FRACTINT.DOC", print_doc_msg_func, 1);
- action = ACTION_PREV2;
- }
-
- else if ( curr.topic_num == -101 )
- action = ACTION_PREV2;
-
- else
- {
- display_page(unknowntopic_msg, NULL, 0, 0, 1, 0, NULL, NULL);
- action = -1;
- while (action == -1)
- {
- switch (getakey())
- {
- case ESC: action = ACTION_QUIT; break;
- case ALT_F1: action = ACTION_PREV; break;
- case F1: action = ACTION_INDEX; break;
- } /* switch */
- } /* while */
- }
- } /* else */
-
- if ( action != ACTION_PREV && action != ACTION_PREV2 )
- {
- if (curr_hist >= MAX_HIST)
- {
- int ctr;
-
- for (ctr=0; ctr<MAX_HIST-1; ctr++)
- hist[ctr] = hist[ctr+1];
-
- curr_hist = MAX_HIST-1;
- }
- hist[curr_hist++] = curr;
- }
- }
- while (action != ACTION_QUIT);
-
- farmemfree((BYTE far *)buffer);
-
- unstackscreen();
- lookatmouse = oldlookatmouse;
- helpmode = oldhelpmode;
- timer_start += clock_ticks();
-
- return(0);
- }
-
- static int dos_version(void)
- {
- #ifndef XFRACT
- union REGS r;
-
- r.x.ax = 0x3000;
- intdos(&r, &r);
-
- return (r.h.al*100 + r.h.ah);
- #else
- return 0;
- #endif
- }
-
- static int exe_path(char *filename, char *path)
- {
- #ifndef XFRACT
- char *ptr;
-
- if (dos_version() >= 300) /* DOS version 3.00+ ? */
- {
- #ifdef __TURBOC__
- strcpy(path, _argv[0]);
- #else /* assume MSC */
- extern char **__argv;
- strcpy(path, __argv[0]); /* note: __argv may be undocumented in MSC */
- #endif
-
- ptr = strrchr(path, SLASHC);
- if (ptr == NULL)
- ptr = path;
- else
- ++ptr;
- strcpy(ptr, filename);
- return (1);
- }
-
- return (0);
- #else
- strcpy(path,SRCDIR);
- strcat(path,"/");
- strcat(path,filename);
- return 1;
- #endif
- }
-
- static int find_file(char *filename, char *path)
- {
- int handle;
-
- if ( exe_path(filename, path) )
- #ifdef __TURBOC__
- if ( (handle=open(path, O_RDONLY|O_DENYWRITE)) != -1)
- #else
- if ( (handle=open(path, O_RDONLY)) != -1)
- #endif
- {
- close(handle);
- return (1);
- }
-
- findpath(filename,path);
- return ( (path[0]) ? 1 : 0);
- }
-
- static int _read_help_topic(int topic, int off, int len, VOIDFARPTR buf)
- {
- static int curr_topic = -1;
- static long curr_base;
- static int curr_len;
- int read_len;
-
- if ( topic != curr_topic )
- {
- int t;
- char ch;
-
- curr_topic = topic;
-
- curr_base = topic_offset[topic];
-
- curr_base += sizeof(int); /* skip flags */
-
- help_seek(curr_base);
- read(help_file, (char *)&t, sizeof(int)); /* read num_pages */
- curr_base += sizeof(int) + t*3*sizeof(int); /* skip page info */
-
- if (t>0)
- help_seek(curr_base);
- read(help_file, &ch, 1); /* read title_len */
- t = ch;
- curr_base += 1 + t; /* skip title */
-
- if (t>0)
- help_seek(curr_base);
- read(help_file, (char *)&curr_len, sizeof(int)); /* read topic len */
- curr_base += sizeof(int);
- }
-
- read_len = (off+len > curr_len) ? curr_len - off : len;
-
- if (read_len > 0)
- {
- help_seek(curr_base + off);
- farread(help_file, (char far *)buf, read_len);
- }
-
- return ( curr_len - (off+len) );
- }
-
- int read_help_topic(int label_num, int off, int len, VOIDFARPTR buf)
- /*
- * reads text from a help topic. Returns number of bytes from (off+len)
- * to end of topic. On "EOF" returns a negative number representing
- * number of bytes not read.
- */
- {
- int ret;
- ret = _read_help_topic(label[label_num].topic_num,
- label[label_num].topic_off + off, len, buf);
- return ( ret );
- }
-
- #define PRINT_BUFFER_SIZE (32767) /* max. size of help topic in doc. */
- #define TEMP_FILE_NAME "HELP.$$$" /* temp file for storing extraseg */
- /* while printing document */
- #define MAX_NUM_TOPIC_SEC (10) /* max. number of topics under any */
- /* single section (CONTENT) */
-
- typedef struct PRINT_DOC_INFO
- {
- int cnum; /* current CONTENT num */
- int tnum; /* current topic num */
-
- long content_pos; /* current CONTENT item offset in file */
- int num_page; /* total number of pages in document */
-
- int num_contents, /* total number of CONTENT entries */
- num_topic; /* number of topics in current CONTENT */
-
- int topic_num[MAX_NUM_TOPIC_SEC]; /* topic_num[] for current CONTENT entry */
-
- char far *buffer; /* text buffer */
-
- char id[81]; /* buffer to store id in */
- char title[81]; /* buffer to store title in */
-
- #ifndef XFRACT
- int (*msg_func)(int pnum, int num_page);
- #else
- int (*msg_func)();
- int pnum;
- #endif
-
- FILE *file; /* file to sent output to */
- int margin; /* indent text by this much */
- int start_of_line; /* are we at the beginning of a line? */
- int spaces; /* number of spaces in a row */
- } PRINT_DOC_INFO;
-
- void print_document(char *outfname, int (*msg_func)(int,int), int save_extraseg );
-
- static void printerc(PRINT_DOC_INFO *info, int c, int n)
- {
- while ( n-- > 0 )
- {
- if (c==' ')
- ++info->spaces;
-
- else if (c=='\n' || c=='\f')
- {
- info->start_of_line = 1;
- info->spaces = 0; /* strip spaces before a new-line */
- putc(c, info->file);
- }
-
- else
- {
- if (info->start_of_line)
- {
- info->spaces += info->margin;
- info->start_of_line = 0;
- }
-
- while (info->spaces > 0)
- {
- fputc(' ', info->file);
- --info->spaces;
- }
-
- fputc(c, info->file);
- }
- }
- }
-
- static void printers(PRINT_DOC_INFO *info, char far *s, int n)
- {
- if (n > 0)
- {
- while ( n-- > 0 )
- printerc(info, *s++, 1);
- }
- else
- {
- while ( *s != '\0' )
- printerc(info, *s++, 1);
- }
- }
-
- static int print_doc_get_info(int cmd, PD_INFO *pd, PRINT_DOC_INFO *info)
- {
- int t;
- BYTE ch;
-
- switch (cmd)
- {
- case PD_GET_CONTENT:
- if ( ++info->cnum >= info->num_contents )
- return (0);
-
- help_seek( info->content_pos );
-
- read(help_file, (char *)&t, sizeof(int)); /* read flags */
- info->content_pos += sizeof(int);
- pd->new_page = (t & 1) ? 1 : 0;
-
- read(help_file, &ch, 1); /* read id len */
- t = ch;
- assert(t<80);
- read(help_file, (char *)info->id, t); /* read the id */
- info->content_pos += 1 + t;
- info->id[t] = '\0';
-
- read(help_file, (char *)&ch, 1); /* read title len */
- t = ch;
- assert(t<80);
- read(help_file, (char *)info->title, t); /* read the title */
- info->content_pos += 1 + t;
- info->title[t] = '\0';
-
- read(help_file, (char *)&ch, 1); /* read num_topic */
- t = ch;
- assert(t<MAX_NUM_TOPIC_SEC);
- read(help_file, (char *)info->topic_num, t*sizeof(int)); /* read topic_num[] */
- info->num_topic = t;
- info->content_pos += 1 + t*sizeof(int);
-
- info->tnum = -1;
-
- pd->id = info->id;
- pd->title = info->title;
- return (1);
-
- case PD_GET_TOPIC:
- if ( ++info->tnum >= info->num_topic )
- return (0);
-
- t = _read_help_topic(info->topic_num[info->tnum], 0, PRINT_BUFFER_SIZE, info->buffer);
-
- assert(t <= 0);
-
- pd->curr = info->buffer;
- pd->len = PRINT_BUFFER_SIZE + t; /* same as ...SIZE - abs(t) */
- return (1);
-
- case PD_GET_LINK_PAGE:
- pd->i = getint(pd->s+sizeof(long));
- return ( (pd->i == -1) ? 0 : 1 );
-
- case PD_RELEASE_TOPIC:
- return (1);
-
- default:
- return (0);
- }
- }
-
- static int print_doc_output(int cmd, PD_INFO *pd, PRINT_DOC_INFO *info)
- {
- switch (cmd)
- {
- case PD_HEADING:
- {
- char line[81];
- char buff[40];
- int width = PAGE_WIDTH + PAGE_INDENT;
- int keep_going;
-
- if ( info->msg_func != NULL )
- keep_going = (*info->msg_func)(pd->pnum, info->num_page);
- else
- keep_going = 1;
-
- info->margin = 0;
-
- memset(line, ' ', 81);
- sprintf(buff, "Fractint Version %d.%01d%c",release/100, (release%100)/10,
- ( (release%10) ? '0'+(release%10) : ' ') );
- memmove(line + ( (width-strlen(buff)) / 2)-4, buff, strlen(buff));
-
- sprintf(buff, "Page %d", pd->pnum);
- memmove(line + (width - strlen(buff)), buff, strlen(buff));
-
- printerc(info, '\n', 1);
- printers(info, line, width);
- printerc(info, '\n', 2);
-
- info->margin = PAGE_INDENT;
-
- return ( keep_going );
- }
-
- case PD_FOOTING:
- info->margin = 0;
- printerc(info, '\f', 1);
- info->margin = PAGE_INDENT;
- return (1);
-
- case PD_PRINT:
- printers(info, pd->s, pd->i);
- return (1);
-
- case PD_PRINTN:
- printerc(info, *pd->s, pd->i);
- return (1);
-
- case PD_PRINT_SEC:
- info->margin = TITLE_INDENT;
- if (pd->id[0] != '\0')
- {
- printers(info, pd->id, 0);
- printerc(info, ' ', 1);
- }
- printers(info, pd->title, 0);
- printerc(info, '\n', 1);
- info->margin = PAGE_INDENT;
- return (1);
-
- case PD_START_SECTION:
- case PD_START_TOPIC:
- case PD_SET_SECTION_PAGE:
- case PD_SET_TOPIC_PAGE:
- case PD_PERIODIC:
- return (1);
-
- default:
- return (0);
- }
- }
-
- static int print_doc_msg_func(int pnum, int num_pages)
- {
- char temp[10];
- int key;
-
- if ( pnum == -1 ) /* successful completion */
- {
- static FCODE msg[] = {"Done -- Press any key"};
- buzzer(0);
- putstringcenter(7, 0, 80, C_HELP_LINK, msg);
- getakey();
- return (0);
- }
-
- if ( pnum == -2 ) /* aborted */
- {
- static FCODE msg[] = {"Aborted -- Press any key"};
- buzzer(1);
- putstringcenter(7, 0, 80, C_HELP_LINK, msg);
- getakey();
- return (0);
- }
-
- if (pnum == 0) /* initialization */
- {
- static FCODE msg[] = {"Generating FRACTINT.DOC"};
- helptitle();
- printinstr();
- setattr(2, 0, C_HELP_BODY, 80*22);
- putstringcenter(1, 0, 80, C_HELP_HDG, msg);
-
- putstring(7, 30, C_HELP_BODY, "Completed:");
-
- movecursor(25,80); /* hide cursor */
- }
-
- sprintf(temp, "%d%%", (int)( (100.0 / num_pages) * pnum ) );
- putstring(7, 41, C_HELP_LINK, temp);
-
- while ( keypressed() )
- {
- key = getakey();
- if ( key == ESC )
- return (0); /* user abort */
- }
-
- return (1); /* AOK -- continue */
- }
-
- int makedoc_msg_func(int pnum, int num_pages)
- {
- if (pnum >= 0)
- {
- printf("\rcompleted %d%%", (int)( (100.0 / num_pages) * pnum ) );
- return (1);
- }
- if ( pnum == -2 )
- printf("\n*** aborted");
- printf("\n");
- return (0);
- }
-
- void print_document(char *outfname, int (*msg_func)(int,int), int save_extraseg )
- {
- static FCODE err_no_temp[] = "Unable to create temporary file.\n";
- static FCODE err_no_out[] = "Unable to create output file.\n";
- static FCODE err_badwrite[] = "Error writing temporary file.\n";
- static FCODE err_badread[] = "Error reading temporary file.\nSystem may be corrupt!\nSave your image and re-start FRACTINT!\n";
-
- PRINT_DOC_INFO info;
- int success = 0;
- int temp_file = -1;
- char far *msg = NULL;
-
- info.buffer = MK_FP(extraseg, 0);
-
- /* help_seek((long)sizeof(int)+sizeof(long)); Strange -- should be 8 -- CWM */
- help_seek(8L); /* indeed it should - Bert */
- read(help_file, (char *)&info.num_contents, sizeof(int));
- read(help_file, (char *)&info.num_page, sizeof(int));
-
- info.cnum = info.tnum = -1;
- info.content_pos = sizeof(long)+4*sizeof(int) + num_topic*sizeof(long) + num_label*2*sizeof(int);
- info.msg_func = msg_func;
-
- if ( msg_func != NULL )
- msg_func(0, info.num_page); /* initialize */
-
- if ( save_extraseg )
- {
- if ( (temp_file=open(TEMP_FILE_NAME, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IREAD|S_IWRITE)) == -1 )
- {
- msg = err_no_temp;
- goto ErrorAbort;
- }
-
- if ( farwrite(temp_file, info.buffer, PRINT_BUFFER_SIZE) != PRINT_BUFFER_SIZE )
- {
- msg = err_badwrite;
- goto ErrorAbort;
- }
- }
-
- if ( (info.file = fopen(outfname, "wt")) == NULL )
- {
- msg = err_no_out;
- goto ErrorAbort;
- }
-
- info.margin = PAGE_INDENT;
- info.start_of_line = 1;
- info.spaces = 0;
-
- success = process_document((PD_FUNC)print_doc_get_info,
- (PD_FUNC)print_doc_output, &info);
- fclose(info.file);
-
- if ( save_extraseg )
- {
- if ( lseek(temp_file, 0L, SEEK_SET) != 0L )
- {
- msg = err_badread;
- goto ErrorAbort;
- }
-
- if ( farread(temp_file, info.buffer, PRINT_BUFFER_SIZE) != PRINT_BUFFER_SIZE )
- {
- msg = err_badread;
- goto ErrorAbort;
- }
- }
-
- ErrorAbort:
- if (temp_file != -1)
- {
- close(temp_file);
- remove(TEMP_FILE_NAME);
- temp_file = -1;
- }
-
- if ( msg != NULL )
- {
- helptitle();
- stopmsg(1, msg);
- }
-
- else if ( msg_func != NULL )
- msg_func((success) ? -1 : -2, info.num_page );
- }
-
- int init_help(void)
- {
- struct help_sig_info hs;
- char path[81];
-
- help_file = -1;
-
- #ifndef WINFRACT
- #ifndef XFRACT
- if (help_file == -1) /* now look for help files in FRACTINT.EXE */
- {
- static FCODE err_no_open[] = "Help system was unable to open FRACTINT.EXE!\n";
- static FCODE err_no_exe[] = "Help system couldn't find FRACTINT.EXE!\n";
- static FCODE err_wrong_ver[] = "Wrong help version in FRACTINT.EXE!\n";
- /*
- static FCODE err_not_in_exe[] = "Help not found in FRACTINT.EXE!\n";
- */
-
- if ( find_file("FRACTINT.EXE", path) )
- {
- #ifdef __TURBOC__
- if ( (help_file = open(path, O_RDONLY|O_BINARY|O_DENYWRITE)) != -1 )
- #else
- if ( (help_file = open(path, O_RDONLY|O_BINARY)) != -1 )
- #endif
- {
- long help_offset;
-
- for (help_offset = -((long)sizeof(hs)); help_offset >= -128L; help_offset--)
- {
- lseek(help_file, help_offset, SEEK_END);
- read(help_file, (char *)&hs, sizeof(hs));
- if (hs.sig == HELP_SIG) break;
- }
-
- if ( hs.sig != HELP_SIG )
- {
- close(help_file);
- help_file = -1;
- /* (leave out the error message)
- stopmsg(1, err_not_in_exe);
- */
- }
-
- else
- {
- if ( hs.version != HELP_VERSION )
- {
- close(help_file);
- help_file = -1;
- stopmsg(1, err_wrong_ver);
- }
- else
- base_off = hs.base;
-
- }
- }
- else
- stopmsg(1, err_no_open);
- }
- else
- stopmsg(1, err_no_exe);
-
- }
- #endif
- #endif
-
- if (help_file == -1) /* look for FRACTINT.HLP */
- {
- if ( find_file("fractint.hlp", path) )
- {
- #ifdef __TURBOC__
- if ( (help_file = open(path, O_RDONLY|O_BINARY|O_DENYWRITE)) != -1 )
- #else
- if ( (help_file = open(path, O_RDONLY|O_BINARY)) != -1 )
- #endif
- {
- read(help_file, (char *)&hs, sizeof(long)+sizeof(int));
-
- if ( hs.sig != HELP_SIG )
- {
- static FCODE msg[] = {"Invalid help signature in FRACTINT.HLP!\n"};
- close(help_file);
- stopmsg(1, msg);
- }
-
- else if ( hs.version != HELP_VERSION )
- {
- static FCODE msg[] = {"Wrong help version in FRACTINT.HLP!\n"};
- close(help_file);
- stopmsg(1, msg);
- }
-
- else
- base_off = sizeof(long)+sizeof(int);
- }
- }
- }
-
- if (help_file == -1) /* Can't find the help files anywhere! */
- {
- static FCODE msg[] =
- #ifndef XFRACT
- {"Help Files aren't in FRACTINT.EXE, and couldn't find FRACTINT.HLP!\n"};
- #else
- {"Couldn't find fractint.hlp; set FRACTDIR to proper directory with setenv.\n"};
- #endif
- stopmsg(1, msg);
- }
-
- help_seek(0L);
-
- read(help_file, (char *)&max_pages, sizeof(int));
- read(help_file, (char *)&max_links, sizeof(int));
- read(help_file, (char *)&num_topic, sizeof(int));
- read(help_file, (char *)&num_label, sizeof(int));
- help_seek((long)6*sizeof(int)); /* skip num_contents and num_doc_pages */
-
- assert(max_pages > 0);
- assert(max_links >= 0);
- assert(num_topic > 0);
- assert(num_label > 0);
-
- /* allocate one big chunk for all three arrays */
-
- topic_offset = (long far *)farmemalloc(sizeof(long)*num_topic + 2L*sizeof(int)*num_label + sizeof(HIST)*MAX_HIST);
-
- if (topic_offset == NULL)
- {
- static FCODE err_no_mem[] = "Not enough memory for help system!\n";
- close(help_file);
- help_file = -1;
- stopmsg(1, err_no_mem);
-
- return (-2);
- }
-
- /* split off the other arrays */
-
- label = (LABEL far *)(&topic_offset[num_topic]);
- hist = (HIST far *)(&label[num_label]);
-
- /* read in the tables... */
-
- farread(help_file, topic_offset, num_topic*sizeof(long));
- farread(help_file, label, num_label*2*sizeof(int));
-
- /* finished! */
-
- return (0); /* success */
- }
-
- void end_help(void)
- {
- if (help_file != -1)
- {
- close(help_file);
- farmemfree((BYTE far *)topic_offset);
- help_file = -1;
- }
- }
-
-