📄 help.c
字号:
/*
* help.c
*
* This module is linked as an overlay, use ENTER_OVLY and EXIT_OVLY.
*
*
* 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 "fractint.h"
#include "helpcom.h"
#include "helpdefs.h"
#include "prototyp.h"
#define MAX_HIST 16 /* number of pages we'll remember */
#define ALT_F1 1104
#define BACK_TAB 1015
#define BACKSPACE 8
#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);
void help_overlay(void) { }
/* stuff from fractint */
extern int lookatmouse;
extern long timer_start;
extern int helpmode;
extern int text_type; /* 0=real color text, 1=640x200x2, 2=??mono?? */
extern int textcbase;
extern int textrbase;
extern SEGTYPE extraseg;
extern int release;
int putstringcenter (int row, int col, int width, int attr, char far *msg);
void helptitle (void);
void stackscreen (void);
void unstackscreen (void);
void findpath (char *filename, char *path);
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 displayc(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] = 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;
}
displayc(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;
while ( 1 )
{
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;
while (1)
{
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 = row;
link[*num_link].c = 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 = row;
link[*num_link].c = 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);
} /* while */
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 dist(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,
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 = dist(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 ( dist(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) );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -