home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 24
/
CD_ASCQ_24_0995.iso
/
vrac
/
dflt20.zip
/
HELPBOX.C
< prev
next >
Wrap
Text File
|
1994-05-05
|
19KB
|
624 lines
/* ------------ helpbox.c ----------- */
#include "dflat.h"
#include "htree.h"
extern DBOX HelpBox;
/* -------- strings of D-Flat classes for calling default
help text collections -------- */
char *ClassNames[] = {
#undef ClassDef
#define ClassDef(c,b,p,a) #c,
#include "classes.h"
NULL
};
#define MAXHEIGHT (SCREENHEIGHT-10)
#define MAXHELPKEYWORDS 50 /* --- maximum keywords in a window --- */
#define MAXHELPSTACK 100
static struct helps *FirstHelp;
static struct helps *ThisHelp;
static int HelpCount;
static char HelpFileName[9];
static int HelpStack[MAXHELPSTACK];
static int stacked;
/* --- keywords in the current help text -------- */
static struct keywords {
struct helps *hkey;
int lineno;
int off1, off2, off3;
char isDefinition;
} KeyWords[MAXHELPKEYWORDS];
static struct keywords *thisword;
static int keywordcount;
static FILE *helpfp;
static char hline [160];
static BOOL Helping;
static void SelectHelp(WINDOW, struct helps *, BOOL);
static void ReadHelp(WINDOW);
static struct helps *FindHelp(char *);
static void DisplayDefinition(WINDOW, char *);
static void BestFit(WINDOW, DIALOGWINDOW *);
/* ------------- CREATE_WINDOW message ------------ */
static void CreateWindowMsg(WINDOW wnd)
{
Helping = TRUE;
GetClass(wnd) = HELPBOX;
InitWindowColors(wnd);
if (ThisHelp != NULL)
ThisHelp->hwnd = wnd;
}
/* ------------- COMMAND message ------------ */
static BOOL CommandMsg(WINDOW wnd, PARAM p1)
{
switch ((int)p1) {
case ID_PREV:
if (ThisHelp != NULL)
SelectHelp(wnd, FirstHelp+(ThisHelp->prevhlp), TRUE);
return TRUE;
case ID_NEXT:
if (ThisHelp != NULL)
SelectHelp(wnd, FirstHelp+(ThisHelp->nexthlp), TRUE);
return TRUE;
case ID_BACK:
if (stacked)
SelectHelp(wnd, FirstHelp+HelpStack[--stacked], FALSE);
return TRUE;
default:
break;
}
return FALSE;
}
/* ------------- KEYBOARD message ------------ */
static BOOL KeyboardMsg(WINDOW wnd, PARAM p1)
{
WINDOW cwnd;
cwnd = ControlWindow(wnd->extension, ID_HELPTEXT);
if (cwnd == NULL || inFocus != cwnd)
return FALSE;
switch ((int)p1) {
case '\r':
if (keywordcount)
if (thisword != NULL) {
char *hp = thisword->hkey->hname;
if (thisword->isDefinition)
DisplayDefinition(GetParent(wnd), hp);
else
SelectHelp(wnd, thisword->hkey, TRUE);
}
return TRUE;
case '\t':
if (!keywordcount)
return TRUE;
if (thisword == NULL ||
++thisword == KeyWords+keywordcount)
thisword = KeyWords;
break;
case SHIFT_HT:
if (!keywordcount)
return TRUE;
if (thisword == NULL || thisword == KeyWords)
thisword = KeyWords+keywordcount;
--thisword;
break;;
default:
return FALSE;
}
if (thisword->lineno < cwnd->wtop ||
thisword->lineno >=
cwnd->wtop + ClientHeight(cwnd)) {
int distance = ClientHeight(cwnd)/2;
do {
cwnd->wtop = thisword->lineno-distance;
distance /= 2;
}
while (cwnd->wtop < 0);
}
SendMessage(cwnd, PAINT, 0, 0);
return TRUE;
}
/* ---- window processing module for the HELPBOX ------- */
int HelpBoxProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
{
switch (msg) {
case CREATE_WINDOW:
CreateWindowMsg(wnd);
break;
case INITIATE_DIALOG:
ReadHelp(wnd);
break;
case COMMAND:
if (p2 != 0)
break;
if (CommandMsg(wnd, p1))
return TRUE;
break;
case KEYBOARD:
if (WindowMoving)
break;
if (KeyboardMsg(wnd, p1))
return TRUE;
break;
case CLOSE_WINDOW:
if (ThisHelp != NULL)
ThisHelp->hwnd = NULL;
Helping = FALSE;
break;
default:
break;
}
return BaseWndProc(HELPBOX, wnd, msg, p1, p2);
}
/* ---- PAINT message for the helpbox text editbox ---- */
static int PaintMsg(WINDOW wnd, PARAM p1, PARAM p2)
{
int rtn;
if (thisword != NULL) {
WINDOW pwnd = GetParent(wnd);
char *cp;
cp = TextLine(wnd, thisword->lineno);
cp += thisword->off1;
*(cp+1) =
(pwnd->WindowColors[SELECT_COLOR][FG] & 255) | 0x80;
*(cp+2) =
(pwnd->WindowColors[SELECT_COLOR][BG] & 255) | 0x80;
rtn = DefaultWndProc(wnd, PAINT, p1, p2);
*(cp+1) =
(pwnd->WindowColors[HILITE_COLOR][FG] & 255) | 0x80;
*(cp+2) =
(pwnd->WindowColors[HILITE_COLOR][BG] & 255) | 0x80;
return rtn;
}
return DefaultWndProc(wnd, PAINT, p1, p2);
}
/* ---- LEFT_BUTTON message for the helpbox text editbox ---- */
static int LeftButtonMsg(WINDOW wnd, PARAM p1, PARAM p2)
{
int rtn, mx, my, i;
rtn = DefaultWndProc(wnd, LEFT_BUTTON, p1, p2);
mx = (int)p1 - GetClientLeft(wnd);
my = (int)p2 - GetClientTop(wnd);
my += wnd->wtop;
thisword = KeyWords;
for (i = 0; i < keywordcount; i++) {
if (my == thisword->lineno) {
if (mx >= thisword->off2 &&
mx < thisword->off3) {
SendMessage(wnd, PAINT, 0, 0);
if (thisword->isDefinition) {
WINDOW pwnd = GetParent(wnd);
if (pwnd != NULL)
DisplayDefinition(GetParent(pwnd),
thisword->hkey->hname);
}
break;
}
}
thisword++;
}
if (i == keywordcount)
thisword = NULL;
return rtn;
}
/* --- window processing module for HELPBOX's text EDITBOX -- */
int HelpTextProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
{
switch (msg) {
case KEYBOARD:
break;
case PAINT:
return PaintMsg(wnd, p1, p2);
case LEFT_BUTTON:
return LeftButtonMsg(wnd, p1, p2);
case DOUBLE_CLICK:
PostMessage(wnd, KEYBOARD, '\r', 0);
break;
default:
break;
}
return DefaultWndProc(wnd, msg, p1, p2);
}
/* -------- read the help text into the editbox ------- */
static void ReadHelp(WINDOW wnd)
{
WINDOW cwnd = ControlWindow(wnd->extension, ID_HELPTEXT);
int linectr = 0;
if (cwnd == NULL)
return;
thisword = KeyWords;
keywordcount = 0;
cwnd->wndproc = HelpTextProc;
SendMessage(cwnd, CLEARTEXT, 0, 0);
/* ----- read the help text ------- */
while (TRUE) {
unsigned char *cp = hline, *cp1;
int colorct = 0;
if (GetHelpLine(hline) == NULL)
break;
if (*hline == '<')
break;
hline[strlen(hline)-1] = '\0';
/* --- add help text to the help window --- */
while (cp != NULL) {
if ((cp = strchr(cp, '[')) != NULL) {
/* ----- hit a new key word ----- */
if (*(cp+1) != '.' && *(cp+1) != '*') {
cp++;
continue;
}
thisword->lineno = cwnd->wlines;
thisword->off1 = (int) (cp - hline);
thisword->off2 = thisword->off1 - colorct * 4;
thisword->isDefinition = *(cp+1) == '*';
colorct++;
*cp++ = CHANGECOLOR;
*cp++ =
(wnd->WindowColors [HILITE_COLOR] [FG] & 255) | 0x80;
*cp++ =
(wnd->WindowColors [HILITE_COLOR] [BG] & 255) | 0x80;
cp1 = cp;
if ((cp = strchr(cp, ']')) != NULL) {
if (thisword != NULL)
thisword->off3 =
thisword->off2 + (int) (cp - cp1);
*cp++ = RESETCOLOR;
}
if ((cp = strchr(cp, '<')) != NULL) {
char *cp1 = strchr(cp, '>');
if (cp1 != NULL) {
char hname[80];
int len = (int) (cp1 - cp);
memset(hname, 0, 80);
strncpy(hname, cp+1, len-1);
thisword->hkey = FindHelp(hname);
memmove(cp, cp1+1, strlen(cp1));
}
}
thisword++;
keywordcount++;
}
}
PutItemText(wnd, ID_HELPTEXT, hline);
/* -- display help text as soon as window is full -- */
if (++linectr == ClientHeight(cwnd)) {
struct keywords *holdthis = thisword;
thisword = NULL;
SendMessage(cwnd, PAINT, 0, 0);
thisword = holdthis;
}
if (linectr > ClientHeight(cwnd) &&
!TestAttribute(cwnd, VSCROLLBAR)) {
AddAttribute(cwnd, VSCROLLBAR);
SendMessage(cwnd, BORDER, 0, 0);
}
}
thisword = NULL;
}
/* ---- compute the displayed length of a help text line --- */
static int HelpLength(char *s)
{
int len = strlen(s);
char *cp = strchr(s, '[');
while (cp != NULL) {
len -= 4;
cp = strchr(cp+1, '[');
}
cp = strchr(s, '<');
while (cp != NULL) {
char *cp1 = strchr(cp, '>');
if (cp1 != NULL)
len -= (int) (cp1-cp)+1;
cp = strchr(cp1, '<');
}
return len;
}
/* ----------- load the help text file ------------ */
void LoadHelpFile(char *fname)
{
long where;
int i;
if (Helping)
return;
UnLoadHelpFile();
if ((helpfp = OpenHelpFile(fname, "rb")) == NULL)
return;
strcpy(HelpFileName, fname);
fseek(helpfp, - (long) sizeof(long), SEEK_END);
fread(&where, sizeof(long), 1, helpfp);
fseek(helpfp, where, SEEK_SET);
fread(&HelpCount, sizeof(int), 1, helpfp);
FirstHelp = DFcalloc(sizeof(struct helps) * HelpCount, 1);
for (i = 0; i < HelpCount; i++) {
int len;
fread(&len, sizeof(int), 1, helpfp);
if (len) {
(FirstHelp+i)->hname = DFcalloc(len+1, 1);
fread((FirstHelp+i)->hname, len+1, 1, helpfp);
}
fread(&len, sizeof(int), 1, helpfp);
if (len) {
(FirstHelp+i)->comment = DFcalloc(len+1, 1);
fread((FirstHelp+i)->comment, len+1, 1, helpfp);
}
fread(&(FirstHelp+i)->hptr, sizeof(int)*5+sizeof(long), 1, helpfp);
}
fclose(helpfp);
helpfp = NULL;
}
/* ------ free the memory used by the help file table ------ */
void UnLoadHelpFile(void)
{
int i;
for (i = 0; i < HelpCount; i++) {
free((FirstHelp+i)->comment);
free((FirstHelp+i)->hname);
}
free(FirstHelp);
FirstHelp = NULL;
free(HelpTree);
HelpTree = NULL;
}
static void BuildHelpBox(WINDOW wnd)
{
int offset, i;
/* -- seek to the first line of the help text -- */
SeekHelpLine(ThisHelp->hptr, ThisHelp->bit);
/* ----- read the title ----- */
GetHelpLine(hline);
hline[strlen(hline)-1] = '\0';
free(HelpBox.dwnd.title);
HelpBox.dwnd.title = DFmalloc(strlen(hline)+1);
strcpy(HelpBox.dwnd.title, hline);
/* ----- set the height and width ----- */
HelpBox.dwnd.h = min(ThisHelp->hheight, MAXHEIGHT)+7;
HelpBox.dwnd.w = max(45, ThisHelp->hwidth+6);
/* ------ position the help window ----- */
if (wnd != NULL)
BestFit(wnd, &HelpBox.dwnd);
/* ------- position the command buttons ------ */
HelpBox.ctl[0].dwnd.w = max(40, ThisHelp->hwidth+2);
HelpBox.ctl[0].dwnd.h =
min(ThisHelp->hheight, MAXHEIGHT)+2;
offset = (HelpBox.dwnd.w-40) / 2;
for (i = 1; i < 5; i++) {
HelpBox.ctl[i].dwnd.y =
min(ThisHelp->hheight, MAXHEIGHT)+3;
HelpBox.ctl[i].dwnd.x = (i-1) * 10 + offset;
}
/* ---- disable ineffective buttons ---- */
if (ThisHelp->nexthlp == -1)
DisableButton(&HelpBox, ID_NEXT);
else
EnableButton(&HelpBox, ID_NEXT);
if (ThisHelp->prevhlp == -1)
DisableButton(&HelpBox, ID_PREV);
else
EnableButton(&HelpBox, ID_PREV);
}
/* ----- select a new help window from its name ----- */
static void SelectHelp(WINDOW wnd, struct helps *newhelp, BOOL recall)
{
if (newhelp != NULL) {
int i, x, y;
SendMessage(wnd, HIDE_WINDOW, 0, 0);
if (recall && stacked < MAXHELPSTACK)
HelpStack[stacked++] = ThisHelp-FirstHelp;
ThisHelp = newhelp;
SendMessage(GetParent(wnd), DISPLAY_HELP, (PARAM) ThisHelp->hname, 0);
if (stacked)
EnableButton(&HelpBox, ID_BACK);
else
DisableButton(&HelpBox, ID_BACK);
BuildHelpBox(NULL);
AddTitle(wnd, HelpBox.dwnd.title);
/* --- reposition and resize the help window --- */
HelpBox.dwnd.x = (SCREENWIDTH-HelpBox.dwnd.w)/2;
HelpBox.dwnd.y = (SCREENHEIGHT-HelpBox.dwnd.h)/2;
SendMessage(wnd, MOVE, HelpBox.dwnd.x, HelpBox.dwnd.y);
SendMessage(wnd, SIZE,
HelpBox.dwnd.x + HelpBox.dwnd.w - 1,
HelpBox.dwnd.y + HelpBox.dwnd.h - 1);
/* --- reposition the controls --- */
for (i = 0; i < 5; i++) {
WINDOW cwnd = HelpBox.ctl[i].wnd;
x = HelpBox.ctl[i].dwnd.x+GetClientLeft(wnd);
y = HelpBox.ctl[i].dwnd.y+GetClientTop(wnd);
SendMessage(cwnd, MOVE, x, y);
if (i == 0) {
x += HelpBox.ctl[i].dwnd.w - 1;
y += HelpBox.ctl[i].dwnd.h - 1;
SendMessage(cwnd, SIZE, x, y);
}
}
/* --- read the help text into the help window --- */
ReadHelp(wnd);
ReFocus(wnd);
SendMessage(wnd, SHOW_WINDOW, 0, 0);
}
}
/* ---- strip tildes from the help name ---- */
static void StripTildes(char *fh, char *hp)
{
while (*hp) {
if (*hp != '~')
*fh++ = *hp;
hp++;
}
*fh = '\0';
}
/* --- return the comment associated with a help window --- */
char *HelpComment(char *Help)
{
char FixedHelp[30];
StripTildes(FixedHelp, Help);
if ((ThisHelp = FindHelp(FixedHelp)) != NULL)
return ThisHelp->comment;
return NULL;
}
/* ---------- display help text ----------- */
BOOL DisplayHelp(WINDOW wnd, char *Help)
{
char FixedHelp[30];
BOOL rtn = FALSE;
if (Helping)
return TRUE;
StripTildes(FixedHelp, Help);
stacked = 0;
wnd->isHelping++;
if ((ThisHelp = FindHelp(FixedHelp)) != NULL) {
if ((helpfp = OpenHelpFile(HelpFileName, "rb")) != NULL) {
BuildHelpBox(wnd);
DisableButton(&HelpBox, ID_BACK);
/* ------- display the help window ----- */
DialogBox(NULL, &HelpBox, TRUE, HelpBoxProc);
free(HelpBox.dwnd.title);
HelpBox.dwnd.title = NULL;
fclose(helpfp);
helpfp = NULL;
rtn = TRUE;
}
}
--wnd->isHelping;
return rtn;
}
/* ------- display a definition window --------- */
static void DisplayDefinition(WINDOW wnd, char *def)
{
WINDOW dwnd;
WINDOW hwnd = wnd;
int y;
struct helps *HoldThisHelp;
HoldThisHelp = ThisHelp;
if (GetClass(wnd) == POPDOWNMENU)
hwnd = GetParent(wnd);
y = GetClass(hwnd) == MENUBAR ? 2 : 1;
if ((ThisHelp = FindHelp(def)) != NULL) {
dwnd = CreateWindow(
TEXTBOX,
NULL,
GetClientLeft(hwnd),
GetClientTop(hwnd)+y,
min(ThisHelp->hheight, MAXHEIGHT)+3,
ThisHelp->hwidth+2,
NULL,
wnd,
NULL,
HASBORDER | NOCLIP | SAVESELF);
if (dwnd != NULL) {
clearBIOSbuffer();
/* ----- read the help text ------- */
SeekHelpLine(ThisHelp->hptr, ThisHelp->bit);
while (TRUE) {
clearBIOSbuffer();
if (GetHelpLine(hline) == NULL)
break;
if (*hline == '<')
break;
hline[strlen(hline)-1] = '\0';
SendMessage(dwnd,ADDTEXT,(PARAM)hline,0);
}
SendMessage(dwnd, SHOW_WINDOW, 0, 0);
SendMessage(NULL, WAITKEYBOARD, 0, 0);
SendMessage(NULL, WAITMOUSE, 0, 0);
SendMessage(dwnd, CLOSE_WINDOW, 0, 0);
}
}
ThisHelp = HoldThisHelp;
}
/* ------ compare help names with wild cards ----- */
static BOOL wildcmp(char *s1, char *s2)
{
while (*s1 || *s2) {
if (tolower(*s1) != tolower(*s2))
if (*s1 != '?' && *s2 != '?')
return TRUE;
s1++, s2++;
}
return FALSE;
}
/* --- ThisHelp = the help window matching specified name --- */
static struct helps *FindHelp(char *Help)
{
int i;
struct helps *thishelp = NULL;
for (i = 0; i < HelpCount; i++) {
if (wildcmp(Help, (FirstHelp+i)->hname) == FALSE) {
thishelp = FirstHelp+i;
break;
}
}
return thishelp;
}
static int OverLap(int a, int b)
{
int ov = a - b;
if (ov < 0)
ov = 0;
return ov;
}
/* ----- compute the best location for a help dialogbox ----- */
static void BestFit(WINDOW wnd, DIALOGWINDOW *dwnd)
{
int above, below, right, left;
if (GetClass(wnd) == MENUBAR ||
GetClass(wnd) == APPLICATION) {
dwnd->x = dwnd->y = -1;
return;
}
/* --- compute above overlap ---- */
above = OverLap(dwnd->h, GetTop(wnd));
/* --- compute below overlap ---- */
below = OverLap(GetBottom(wnd), SCREENHEIGHT-dwnd->h);
/* --- compute right overlap ---- */
right = OverLap(GetRight(wnd), SCREENWIDTH-dwnd->w);
/* --- compute left overlap ---- */
left = OverLap(dwnd->w, GetLeft(wnd));
if (above < below)
dwnd->y = max(0, GetTop(wnd)-dwnd->h-2);
else
dwnd->y = min(SCREENHEIGHT-dwnd->h, GetBottom(wnd)+2);
if (right < left)
dwnd->x = min(GetRight(wnd)+2, SCREENWIDTH-dwnd->w);
else
dwnd->x = max(0, GetLeft(wnd)-dwnd->w-2);
if (dwnd->x == GetRight(wnd)+2 ||
dwnd->x == GetLeft(wnd)-dwnd->w-2)
dwnd->y = -1;
if (dwnd->y ==GetTop(wnd)-dwnd->h-2 ||
dwnd->y == GetBottom(wnd)+2)
dwnd->x = -1;
}