windows-nt/Source/XPSP1/NT/sdktools/mep/help/htest/htest.c
2020-09-26 16:20:57 +08:00

1442 lines
38 KiB
C

/*** htest - help engine test harness
*
* Copyright <C> 1987, Microsoft Corporation
*
* Revision History:
*
* 15-Dec-1988 ln Added dump command
* [] 21-Oct-1988 LN New Version
*
*************************************************************************/
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined (OS2)
#define INCL_SUB
#define INCL_DOSMODULEMGR
#define INCL_DOSFILEMGR
#define INCL_DOSMISC
#include <ctype.h>
#include <os2.h>
#else
#include <windows.h>
#endif
#include "cons.h"
#include "help.h"
#include "helpfile.h" /* help file format definition */
#include "helpsys.h" /* internal (help sys only) decl*/
#if defined (OS2)
#define HELPDLL_NAME "mshelp1.dll"
#define HELPDLL_BASE "mshelp1"
#else
#define HELPDLL_NAME "mshelp.dll"
#define HELPDLL_BASE "mshelp"
#endif
/*
* text color values
*/
#define BLACK 0
#define BLUE 1
#define GREEN 2
#define CYAN 3
#define RED 4
#define MAGENTA 5
#define BROWN 6
#define WHITE 7
#define GREY 8
#define LIGHTBLUE 9
#define LIGHTGREEN 10
#define LIGHTCYAN 11
#define LIGHTRED 12
#define LIGHTMAGENTA 13
#define YELLOW 14
#define BRIGHTWHITE 15
#define BUFSIZE 128 /* text buffer size */
#define ISERROR(x) (((x).mh == 0L) && ((x).cn <= HELPERR_MAX))
#define SETERROR(x,y) { (x).mh = 0L; (x).cn = y;}
typedef void pascal (*void_F) (void);
typedef int pascal (*int_F) (void);
typedef ushort pascal (*ushort_F) (void);
typedef f pascal (*f_F) (void);
typedef char * pascal (*pchar_F) (void);
typedef nc pascal (*nc_F) (void);
typedef mh pascal (*mh_F) (void);
#if !defined (HELP_HACK)
#define HelpcLines ((int_F) (pEntry[P_HelpcLines ]))
#define HelpClose ((void_F) (pEntry[P_HelpClose ]))
#define HelpCtl ((void_F) (pEntry[P_HelpCtl ]))
#define HelpDecomp ((f_F) (pEntry[P_HelpDecomp ]))
#define HelpGetCells ((int_F) (pEntry[P_HelpGetCells ]))
#define HelpGetInfo ((inf_F) (pEntry[P_HelpGetInfo ]))
#define HelpGetLine ((ushort_F) (pEntry[P_HelpGetLine ]))
#define HelpGetLineAttr ((ushort_F) (pEntry[P_HelpGetLineAttr]))
#define HelpHlNext ((f_F) (pEntry[P_HelpHlNext ]))
#define HelpLook ((ushort_F) (pEntry[P_HelpLook ]))
#define HelpNc ((nc_F) (pEntry[P_HelpNc ]))
#define HelpNcBack ((nc_F) (pEntry[P_HelpNcBack ]))
#define HelpNcCb ((ushort_F) (pEntry[P_HelpNcCb ]))
#define HelpNcCmp ((nc_F) (pEntry[P_HelpNcCmp ]))
#define HelpNcNext ((nc_F) (pEntry[P_HelpNcNext ]))
#define HelpNcPrev ((nc_F) (pEntry[P_HelpNcPrev ]))
#define HelpNcRecord ((void_F) (pEntry[P_HelpNcRecord ]))
#define HelpNcUniq ((nc_F) (pEntry[P_HelpNcUniq ]))
#define HelpOpen ((nc_F) (pEntry[P_HelpOpen ]))
#define HelpShrink ((void_F) (pEntry[P_HelpShrink ]))
#define HelpSzContext ((f_F) (pEntry[P_HelpSzContext ]))
#define HelpXRef ((pchar_F) (pEntry[P_HelpXRef ]))
#define LoadFdb ((f_F) (pEntry[P_LoadFdb ]))
#define LoadPortion ((mh_F) (pEntry[P_LoadPortion ]))
#endif
enum {
P_HelpcLines,
P_HelpClose,
P_HelpCtl,
P_HelpDecomp,
P_HelpGetCells,
P_HelpGetInfo,
P_HelpGetLine,
P_HelpGetLineAttr,
P_HelpHlNext,
P_HelpLook,
P_HelpNc,
P_HelpNcBack,
P_HelpNcCb,
P_HelpNcCmp,
P_HelpNcNext,
P_HelpNcPrev,
P_HelpNcRecord,
P_HelpNcUniq,
P_HelpOpen,
P_HelpShrink,
P_HelpSzContext,
P_HelpXRef,
P_LoadFdb,
P_LoadPortion,
LASTENTRYPOINT
} ENTRYPOINTS;
#define NUM_ENTRYPOINTS (LASTENTRYPOINT - P_HelpcLines)
typedef nc pascal (*PHF) (void);
/*
* Global Data
*/
char buf[BUFSIZ]; /* text buffer */
char cell[2] = {' ',0x1f}; /* background clearing cell */
#define ColorByte cell[1]
int curline; /* current line output */
char *errTbl[] = {
"",
"help file not found",
"ReadHelpFile failed on header",
"to many open helpfiles",
"bad appeneded file",
"Not a help file",
"newer or incompatible help file",
"memory allocation failed"
};
f fBoth = FALSE; /* both stdout & screen */
f fEnable = FALSE; /* enable control lines in disp */
int iNcCur; /* current index in ncTbl */
int lastline;
int lLast; /* last starting line number disp*/
mh mhTopicCur; /* mem handle for most recent */
uchar mpAttr[] = { /* on-screen color map */
0x1f, /* 0: normal text */
0x1c, /* 1: bold */
0x1a, /* 2: italics */
0x1e, /* 3: bold italics */
0x7f, /* 4: underline */
0x7c, /* 5: bold ul */
0x7a, /* 6: italics ul */
0x7e /* 7: bold italics ul */
};
nc ncCur; /* most recently read in topic */
nc ncTbl[MAXFILES]; /* table of open nc's */
char far * pTopicCur; /* ptr to most recent topic */
char *spaces = " \r\n";
#if defined (OS2)
HMODULE hModule;
#else
HANDLE hModule;
#endif
PHF pEntry[NUM_ENTRYPOINTS] = {0};
#if defined (OS2)
char * szEntryName[NUM_ENTRYPOINTS] = {
"_HelpcLines",
"_HelpClose",
"_HelpCtl",
"_HelpDecomp",
"_HelpGetCells",
"_HelpGetInfo",
"_HelpGetLine",
"_HelpGetLineAttr",
"_HelpHlNext",
"_HelpLook",
"_HelpNc",
"_HelpNcBack",
"_HelpNcCb",
"_HelpNcCmp",
"_HelpNcNext",
"_HelpNcPrev",
"_HelpNcRecord",
"_HelpNcUniq",
"_HelpOpen",
"_HelpShrink",
"_HelpSzContext",
"_HelpXRef",
"_LoadFdb",
"_LoadPortion",
};
#else
char * szEntryName[NUM_ENTRYPOINTS] = {
"HelpcLines",
"HelpClose",
"HelpCtl",
"HelpDecomp",
"HelpGetCells",
"HelpGetInfo",
"HelpGetLine",
"HelpGetLineAttr",
"HelpHlNext",
"HelpLook",
"HelpNc",
"HelpNcBack",
"HelpNcCb",
"HelpNcCmp",
"HelpNcNext",
"HelpNcPrev",
"HelpNcRecord",
"HelpNcUniq",
"HelpOpen",
"HelpShrink",
"HelpSzContext",
"HelpXRef",
"LoadFdb",
"LoadPortion",
};
#endif
// rjsa VIOMODEINFO screen;
/*
* Forward declarations
*/
#define ASSERTDOS(x) assertDos(x, __FILE__, __LINE__)
void pascal near assertDos (USHORT, CHAR *, USHORT);
void pascal near cls (void);
void pascal near dispCmd (int, int);
void pascal near dumpCmd ();
void pascal near dumpfileCmd ( char *);
void pascal near fileCmd (char *);
void pascal near helpCmd (void);
void pascal near lookupCmd (char *, int);
void pascal near outtext (char *, BYTE);
void pascal near outtextat (char *, int, int, BYTE);
uchar far * pascal near phrasecopy (uchar *, uchar far *);
void pascal near xrefCmd (char *);
#undef HelpDealloc
#undef HelpLock
#undef HelpUnlock
void pascal far HelpDealloc (mh);
void far * pascal far HelpLock (mh);
void pascal far HelpUnlock (mh);
f pascal near LoadFdb (mh, fdb far *);
mh pascal near LoadPortion (USHORT, mh);
//char far * pascal near hfstrcpy(char far *, char far *);
//ushort pascal near hfstrlen(char far *);
void LoadTheDll(void);
USHORT WrtCellStr (PBYTE buf, int cb, int row, int col);
USHORT WrtLineAttr( PBYTE buf, lineattr* rgAttr, int cb, int row, int col );
USHORT WrtCharStrAtt (PBYTE pText, int cb, int row, int col, PBYTE pcolor);
PSCREEN Scr;
/*** main - main program
*
* Input:
* Standard C main, all ignored
*
* Output:
* Returns via exit()
*
*************************************************************************/
void main(
USHORT argc,
char **argv
) {
char c;
nc ncNull = {0,0};
SCREEN_INFORMATION ScrInfo;
/*
* parse any options
*/
if (argc > 1)
while ((** ++argv) == '-') {
c = *(++(*argv));
switch (toupper(c)) {
case 'B': /* -b: both screen and stdout */
fBoth = TRUE;
break;
default:
fputs ("Unknown switch ignored", stderr);
break;
}
}
// InitializeGlobalState();
Scr = consoleGetCurrentScreen();
// Load help engine DLL and initialize pointers to entry
// points.
//
LoadTheDll();
#if defined(CLEAR)
HelpInit();
#endif
/*
* Start by getting the current config & clearing screen.
*/
// rjsa screen.cb = sizeof(screen);
// rjsa assertDos (VioGetMode (&screen, 0));
// rjsa lastline = screen.row-1;
consoleGetScreenInformation( Scr, &ScrInfo );
lastline = ScrInfo.NumberOfRows-2;
// lastline = 22;
cls();
helpCmd();
/*
* main loop. Position at bottom of screen, and accept one command at at time
* from there. Interpret commands until done.
*/
do {
outtextat ("\r\n", lastline, 0, BRIGHTWHITE);
outtextat (spaces, lastline, 0, BRIGHTWHITE);
outtextat ("HTEST Command> ", lastline, 0, BRIGHTWHITE);
// rjsa VioSetCurPos (lastline, 15, 0);
consoleSetCursor(Scr, lastline, 16);
gets (buf);
cls ();
outtextat ("\r\n", lastline, 0, BRIGHTWHITE);
outtextat ("Processing: ", lastline, 0, LIGHTRED);
outtextat (buf, lastline, 12, BRIGHTWHITE);
outtextat ("\r\n", lastline, 0, BRIGHTWHITE);
/*
* ctrl on/off
*/
if (!strcmp (buf,"ctrl on")) {
fEnable = TRUE;
cls ();
outtextat ("Control Lines Displayed", 0, 0, BRIGHTWHITE);
}
else if (!strcmp (buf,"ctrl off")) {
fEnable = FALSE;
cls ();
outtextat ("Control Lines NOT Displayed", 0, 0, BRIGHTWHITE);
}
/*
* disp
*/
else if (!strcmp (buf,"disp"))
dispCmd (1,lastline);
/*
* down
*/
else if (!strcmp (buf,"down"))
dispCmd (lLast+1,lLast + lastline);
/*
* dump
*/
else if (!strncmp (buf, "dump ", 5))
dumpfileCmd(buf+5);
else if (!strcmp (buf,"dump"))
dumpCmd ();
/*
* file newhelpfilename
*/
else if (!strncmp (buf,"file ", 5))
fileCmd (buf+5);
/*
* help
*/
else if (!strcmp (buf,"help"))
helpCmd ();
/*
* look helpstring
*/
else if (!strncmp (buf,"look ", 5))
lookupCmd (buf+5,0);
/*
* look
*/
else if (!strcmp (buf,"look"))
lookupCmd (NULL,0);
/*
* next
*/
else if (!strcmp (buf,"next"))
lookupCmd (NULL,1);
/*
* prev
*/
else if (!strcmp (buf,"prev"))
lookupCmd (NULL,-1);
/*
* up
*/
else if (!strcmp (buf,"up")) {
lLast = max (1, lLast-1);
dispCmd (lLast,lLast + lastline);
}
/*
* xref xrefnumber
*/
else if (!strncmp (buf,"xref", 4))
xrefCmd (buf+4);
/*
* + page down
*/
else if (!strcmp (buf,"+")) {
lLast += lastline;
dispCmd (lLast,lLast + lastline);
}
/*
* - page up
*/
else if (!strcmp (buf,"-")) {
lLast = max (1, lLast - (lastline));
dispCmd (lLast,lLast + lastline);
}
}
/*
* exit
*/
while (strncmp(buf,"exit",4));
outtextat (spaces, lastline, 0, BRIGHTWHITE);
HelpClose (ncNull);
/* end main */}
/*** dispCmd - display topic text
*
* displays the topic text on the screen.
*
* Input:
* lStart - starting line
* lEnd - ending line
*
* Output:
* Returns nothing
*
*************************************************************************/
void pascal near dispCmd (
int lStart,
int lEnd
) {
char buf[BUFSIZ*2];
lineattr rgAttr[BUFSIZ];
int cb;
int lineCur = 0;
HelpCtl (pTopicCur, fEnable);
cls ();
lLast = lStart;
while (lStart<lEnd) {
if (!isatty(_fileno(stdout)) || fBoth) {
cb = (int)HelpGetLine (lStart, BUFSIZ*2, (char far *)buf, pTopicCur);
if (cb == 0)
lStart = lEnd;
buf[cb-1] = '\r';
buf[cb] = '\n';
buf[cb+1] = 0;
outtext (buf, BLACK);
buf[cb-1] = 0;
}
if (isatty(_fileno(stdout)) || fBoth) {
cb = HelpGetLine(lStart, BUFSIZ*2, (char far*)buf, pTopicCur );
HelpGetLineAttr( lStart, BUFSIZ*sizeof(lineattr), rgAttr, pTopicCur );
WrtLineAttr(buf, rgAttr, cb, lineCur++, 0 );
}
//if (isatty(fileno(stdout)) || fBoth) {
// cb = HelpGetCells (lStart, BUFSIZ*2, buf, pTopicCur, mpAttr);
// if (cb == -1)
// lStart = lEnd;
// else
// ASSERTDOS (WrtCellStr (buf, cb, lineCur++, 0));
// }
lStart++;
}
/* end dispCmd */}
static char *szHS[] = { "HS_INDEX",
"HS_CONTEXTSTRINGS",
"HS_CONTEXTMAP",
"HS_KEYPHRASE",
"HS_HUFFTREE",
"HS_TOPICS",
"unused (6)",
"unused (7)",
"HS_NEXT" };
/*** dumpCmd - process dump command
*
* Dumps the contents of the current help file
*
* NOTE:
* This function uses all sorts of "internal" knowledge and calls to
* do it's job.
*
* Input:
*
* Output:
* Returns nothing
*
*************************************************************************/
void pascal near dumpCmd () {
char buf[BUFSIZ];
int cbKeyPhrase;
fdb fdbLocal; /* local copy of fdb to use */
uchar far *fpT;
ushort far *fpW;
int i;
nc ncNext; /* nc init of appended file */
//uchar uc;
cls();
ncNext = ncCur;
while (ncNext.cn) {
if (LoadFdb (ncNext.mh, &fdbLocal)) {
sprintf (buf,"fhHelp %u\r\n", fdbLocal.fhHelp);
outtext (buf, BRIGHTWHITE);
sprintf (buf,"ncInit %08lx\r\n", fdbLocal.ncInit);
outtext (buf, BRIGHTWHITE);
for (i=0; i<HS_count; i++) {
sprintf (buf,"rgmhSections[%18s] %04x\r\n", szHS[i], fdbLocal.rgmhSections[i]);
outtext (buf, BRIGHTWHITE);
}
sprintf (buf,"ftype %02x\r\n", fdbLocal.ftype );
outtext (buf, BRIGHTWHITE);
sprintf (buf,"fname %14s\r\n", fdbLocal.fname );
outtext (buf, BRIGHTWHITE);
sprintf (buf,"foff %08lx\r\n", fdbLocal.foff );
outtext (buf, BRIGHTWHITE);
sprintf (buf,"ncLink %08lx\r\n", fdbLocal.ncLink);
outtext (buf, BRIGHTWHITE);
sprintf (buf,"hdr.wMagic %04x\r\n", fdbLocal.hdr.wMagic );
outtext (buf, BRIGHTWHITE);
sprintf (buf,"hdr.wVersion %04x\r\n", fdbLocal.hdr.wVersion );
outtext (buf, BRIGHTWHITE);
sprintf (buf,"hdr.wFlags %04x\r\n", fdbLocal.hdr.wFlags );
outtext (buf, BRIGHTWHITE);
sprintf (buf,"hdr.appChar %04x\r\n", fdbLocal.hdr.appChar );
outtext (buf, BRIGHTWHITE);
sprintf (buf,"hdr.cTopics %04x\r\n", fdbLocal.hdr.cTopics );
outtext (buf, BRIGHTWHITE);
sprintf (buf,"hdr.cContexts %04x\r\n", fdbLocal.hdr.cContexts );
outtext (buf, BRIGHTWHITE);
sprintf (buf,"hdr.cbWidth %04x\r\n", fdbLocal.hdr.cbWidth );
outtext (buf, BRIGHTWHITE);
sprintf (buf,"hdr.cPreDef %04x\r\n", fdbLocal.hdr.cPreDef );
outtext (buf, BRIGHTWHITE);
sprintf (buf,"hdr.fname %s\r\n", fdbLocal.hdr.fname );
outtext (buf, BRIGHTWHITE);
sprintf (buf,"hdr.reserved[0] %04x\r\n", fdbLocal.hdr.reserved[0]);
outtext (buf, BRIGHTWHITE);
sprintf (buf,"hdr.reserved[1] %04x\r\n", fdbLocal.hdr.reserved[1]);
for (i=0; i<HS_count; i++) {
sprintf (buf,"hdr.tbPos[%18s] %08lx\r\n", szHS[i], fdbLocal.hdr.tbPos[i]);
outtext (buf, BRIGHTWHITE);
}
outtext ("----- ----- -----\r\n", LIGHTGREEN);
/*
* Topic Index
* This is just a table of (long) offsets within the current file. We just
* report the values, and also calculate the size of each entry by looking
* at the position of the entry following.
*/
fpT = HelpLock (LoadPortion( HS_INDEX ,ncNext.mh));
if (fpT) {
outtext ("Topic Index:\r\n", LIGHTRED);
for (i = 0; i < (int)fdbLocal.hdr.cTopics; i++) {
sprintf (buf, " %2d: %08lx, %ld bytes\r\n", i, ((long far *)fpT)[i], ((long far *)fpT)[i+1]-((long far *)fpT)[i]);
outtext (buf, BRIGHTWHITE);
}
outtext ("----- ----- -----\r\n", LIGHTGREEN);
}
/*
* context strings
* This is just a table of null terminated strings, in no particular order.
* We just list them out sequentially.
*/
fpT = HelpLock (LoadPortion( HS_CONTEXTSTRINGS ,ncNext.mh));
if (fpT) {
outtext ("Context strings:\r\n", LIGHTRED);
for (i=0; i<(int)fdbLocal.hdr.cContexts; i++) {
sprintf (buf, " %03d: ", i);
// rjsa hfstrcpy ((char far *)buf+7, fpT);
strcpy ((char far *)buf+7, fpT);
strcat (buf, "\r\n");
outtext (buf, BRIGHTWHITE);
// rjsa fpT += hfstrlen(fpT) +1;
fpT += strlen(fpT) +1;
}
outtext ("----- ----- -----\r\n", LIGHTGREEN);
}
/*
* Context Map
* This is the mapping of context strings to actual topic numbers. The context
* strings map one to one to the entries in this table, which in turn contains
* indexes into the topic index at the head of the file. We just dump this
* table sequentially.
*/
fpT = HelpLock (LoadPortion( HS_CONTEXTMAP ,ncNext.mh));
if (fpT) {
outtext ("Context map:\r\n", LIGHTRED);
outtext (" Ctx Topic\r\n",BRIGHTWHITE);
outtext (" --- -----\r\n",BRIGHTWHITE);
for (i=0; i<(int)fdbLocal.hdr.cContexts; i++) {
sprintf (buf, " %03d: %04d\r\n", i, ((ushort far *)fpT)[i]);
outtext (buf, BRIGHTWHITE);
}
outtext ("----- ----- -----\r\n", LIGHTGREEN);
}
/*
* keyword table
* This is a table of byte-prefixed strings, which we output in order,
* synthesizing the tokens that they would be in the text as well.
*/
fpT = HelpLock (LoadPortion( HS_KEYPHRASE, ncNext.mh));
if (fpT) {
cbKeyPhrase = 0;
for (i=HS_HUFFTREE; i<HS_count; i++)
if (fdbLocal.hdr.tbPos[i]) {
cbKeyPhrase = (ushort)(fdbLocal.hdr.tbPos[i] - fdbLocal.hdr.tbPos[HS_KEYPHRASE]);
break;
}
outtext ("Keyphrase Table:\r\n", LIGHTRED);
outtext (" Token Phrase\r\n",BRIGHTWHITE);
outtext (" ----- ------\r\n",BRIGHTWHITE);
i = 0;
fpT += 1024 * sizeof (PVOID);
fpW = (ushort far *)(fpT + cbKeyPhrase);
while (fpT < (uchar far *)fpW) {
sprintf (buf, " %04x: ", i+(C_KEYPHRASE0 << 8));
fpT = phrasecopy (buf+8, fpT);
strcat (buf, "\r\n");
outtext (buf, BRIGHTWHITE);
i++;
}
outtext ("----- ----- -----\r\n", LIGHTGREEN);
}
/*
* huffman table
* here we try to get fancy and output some information about the table format
*/
fpW = HelpLock (LoadPortion( HS_HUFFTREE, ncNext.mh));
if (fpW) {
outtext ("Huffman Tree:\r\n", LIGHTRED);
i = 0;
while (*fpW) {
sprintf (buf, " 0x%03x: 0x%04x, %s\r\n", i++, *fpW, *fpW & 0x8000 ? "Leaf" : "Node");
fpW++;
outtext (buf, BRIGHTWHITE);
}
}
outtext ("===== ===== =====\r\n", YELLOW);
ncNext = fdbLocal.ncLink;
}
else {
sprintf(buf, "Cannot load fdb for %08lx\r\n",ncCur);
outtext (buf, LIGHTRED);
return;
}
}
/* end dumpCmd */}
/*** dumpfileCmd - process dump command
*
* Dumps the contents of the current help file
*
* NOTE:
* This function uses all sorts of "internal" knowledge and calls to
* do it's job.
*
* Input:
*
* Output:
* Returns nothing
*
*************************************************************************/
void pascal near dumpfileCmd (char *fname) {
char buf[BUFSIZ];
int cbKeyPhrase;
fdb fdbLocal; /* local copy of fdb to use */
uchar far *fpT;
ushort far *fpW;
int i;
nc ncNext; /* nc init of appended file */
//uchar uc;
FILE* fh = fopen(fname, "w");
if (!fh) {
return;
}
ncNext = ncCur;
while (ncNext.cn) {
if (LoadFdb (ncNext.mh, &fdbLocal)) {
sprintf (buf,"fhHelp %u\r\n", fdbLocal.fhHelp);
fprintf( fh, buf );
sprintf (buf,"ncInit %08lx\r\n", fdbLocal.ncInit);
fprintf( fh, buf );
for (i=0; i<HS_count; i++) {
sprintf (buf,"rgmhSections[%18s] %04x\r\n", szHS[i], fdbLocal.rgmhSections[i]);
fprintf( fh, buf );
}
sprintf (buf,"ftype %02x\r\n", fdbLocal.ftype );
fprintf( fh, buf );
sprintf (buf,"fname %14s\r\n", fdbLocal.fname );
fprintf( fh, buf );
fprintf( fh, buf );
sprintf (buf,"foff %08lx\r\n", fdbLocal.foff );
fprintf( fh, buf );
sprintf (buf,"ncLink %08lx\r\n", fdbLocal.ncLink);
fprintf( fh, buf );
sprintf (buf,"hdr.wMagic %04x\r\n", fdbLocal.hdr.wMagic );
fprintf( fh, buf );
sprintf (buf,"hdr.wVersion %04x\r\n", fdbLocal.hdr.wVersion );
fprintf( fh, buf );
sprintf (buf,"hdr.wFlags %04x\r\n", fdbLocal.hdr.wFlags );
fprintf( fh, buf );
sprintf (buf,"hdr.appChar %04x\r\n", fdbLocal.hdr.appChar );
fprintf( fh, buf );
sprintf (buf,"hdr.cTopics %04x\r\n", fdbLocal.hdr.cTopics );
fprintf( fh, buf );
sprintf (buf,"hdr.cContexts %04x\r\n", fdbLocal.hdr.cContexts );
fprintf( fh, buf );
sprintf (buf,"hdr.cbWidth %04x\r\n", fdbLocal.hdr.cbWidth );
fprintf( fh, buf );
sprintf (buf,"hdr.cPreDef %04x\r\n", fdbLocal.hdr.cPreDef );
fprintf( fh, buf );
sprintf (buf,"hdr.fname %s\r\n", fdbLocal.hdr.fname );
fprintf( fh, buf );
sprintf (buf,"hdr.reserved[0] %04x\r\n", fdbLocal.hdr.reserved[0]);
fprintf( fh, buf );
sprintf (buf,"hdr.reserved[1] %04x\r\n", fdbLocal.hdr.reserved[1]);
for (i=0; i<HS_count; i++) {
sprintf (buf,"hdr.tbPos[%18s] %08lx\r\n", szHS[i], fdbLocal.hdr.tbPos[i]);
fprintf( fh, buf );
}
fprintf( fh,"----- ----- -----\r\n" );
/*
* Topic Index
* This is just a table of (long) offsets within the current file. We just
* report the values, and also calculate the size of each entry by looking
* at the position of the entry following.
*/
fpT = HelpLock (LoadPortion( HS_INDEX ,ncNext.mh));
if (fpT) {
fprintf( fh,"Topic Index:\r\n" );
for (i = 0; i < (int)fdbLocal.hdr.cTopics; i++) {
sprintf (buf, " %2d: %08lx, %ld bytes\r\n", i, ((long far *)fpT)[i], ((long far *)fpT)[i+1]-((long far *)fpT)[i]);
fprintf( fh, buf );
}
fprintf( fh,"----- ----- -----\r\n" );
}
/*
* context strings
* This is just a table of null terminated strings, in no particular order.
* We just list them out sequentially.
*/
fpT = HelpLock (LoadPortion( HS_CONTEXTSTRINGS ,ncNext.mh));
if (fpT) {
fprintf( fh, "Context strings:\r\n" );
for (i=0; i<(int)fdbLocal.hdr.cContexts; i++) {
sprintf (buf, " %03d: ", i);
// rjsa hfstrcpy ((char far *)buf+7, fpT);
strcpy ((char far *)buf+7, fpT);
strcat (buf, "\r\n");
fprintf( fh, buf );
// rjsa fpT += hfstrlen(fpT) +1;
fpT += strlen(fpT) +1;
}
fprintf( fh,"----- ----- -----\r\n" );
}
/*
* Context Map
* This is the mapping of context strings to actual topic numbers. The context
* strings map one to one to the entries in this table, which in turn contains
* indexes into the topic index at the head of the file. We just dump this
* table sequentially.
*/
fpT = HelpLock (LoadPortion( HS_CONTEXTMAP ,ncNext.mh));
if (fpT) {
fprintf( fh, "Context map:\r\n" );
fprintf( fh, " Ctx Topic\r\n" );
fprintf( fh, " --- -----\r\n" );
for (i=0; i<(int)fdbLocal.hdr.cContexts; i++) {
sprintf (buf, " %03d: %04d\r\n", i, ((ushort far *)fpT)[i]);
fprintf( fh, buf );
}
fprintf( fh, "----- ----- -----\r\n" );
}
/*
* keyword table
* This is a table of byte-prefixed strings, which we output in order,
* synthesizing the tokens that they would be in the text as well.
*/
fpT = HelpLock (LoadPortion( HS_KEYPHRASE, ncNext.mh));
if (fpT) {
cbKeyPhrase = 0;
for (i=HS_HUFFTREE; i<HS_count; i++)
if (fdbLocal.hdr.tbPos[i]) {
cbKeyPhrase = (ushort)(fdbLocal.hdr.tbPos[i] - fdbLocal.hdr.tbPos[HS_KEYPHRASE]);
break;
}
fprintf( fh, "Keyphrase Table:\r\n" );
fprintf( fh, " Token Phrase\r\n" );
fprintf( fh, " ----- ------\r\n" );
i = 0;
fpT += 1024 * sizeof (PVOID);
fpW = (ushort far *)(fpT + cbKeyPhrase);
while (fpT < (uchar far *)fpW) {
sprintf (buf, " %04x: ", i+(C_KEYPHRASE0 << 8));
fpT = phrasecopy (buf+8, fpT);
strcat (buf, "\r\n");
fprintf( fh, buf );
i++;
}
fprintf( fh,"----- ----- -----\r\n" );
}
/*
* huffman table
* here we try to get fancy and output some information about the table format
*/
fpW = HelpLock (LoadPortion( HS_HUFFTREE, ncNext.mh));
if (fpW) {
fprintf( fh, "Huffman Tree:\r\n" );
i = 0;
while (*fpW) {
sprintf (buf, " 0x%03x: 0x%04x, %s\r\n", i++, *fpW, *fpW & 0x8000 ? "Leaf" : "Node");
fpW++;
fprintf( fh, buf );
}
}
fprintf( fh, "===== ===== =====\r\n" );
ncNext = fdbLocal.ncLink;
}
else {
sprintf(buf, "Cannot load fdb for %08lx\r\n",ncCur);
fprintf( fh, buf );
fclose(fh);
return;
}
}
/* end dumpCmd */}
/*** fileCmd - process file command
*
* Opens the help file specified.
*
* Input:
* pName = name of help file to be added
*
* Output:
* Returns nothing
*
*************************************************************************/
void pascal near fileCmd (
char *pName
) {
char buf[BUFSIZ];
int i;
nc ncInit;
sprintf (buf,"Opening %s...\r\n",pName);
outtext (buf, BRIGHTWHITE);
/*
* search file table for available slot
*/
for (i=0; i<MAXFILES; i++)
if (!ncTbl[i].cn)
break;
if (i >= MAXFILES) {
sprintf(buf, "Cannot open %s: htest's open file limit exceeded\r\n",pName);
outtext (buf, LIGHTRED);
return;
}
iNcCur = i;
ncInit = HelpOpen(pName);
for (i=0; i<MAXFILES; i++)
if ((ncTbl[i].mh == ncInit.mh) && (ncTbl[i].cn == ncInit.cn)) {
iNcCur = i;
sprintf (buf, "File #%d; Initial Context: 0x%04lx (file already open)\r\n",iNcCur,ncInit);
outtext (buf, BRIGHTWHITE);
return;
}
if (ISERROR(ncInit)) {
sprintf(buf, "Cannot open %s: 0x%04lx, %s\r\n",pName,ncInit, errTbl[ncInit.cn]);
outtext (buf, LIGHTRED);
return;
}
/*
* output initial context, and the available memory
*/
ncCur = ncTbl[iNcCur] = ncInit;
sprintf (buf, "File #%d; Initial Context: 0x%04lx\r\n",iNcCur,ncInit.cn);
outtext (buf, BRIGHTWHITE);
lookupCmd(NULL, 0);
/* end fileCmd */}
/*** helpCmd - display help on commands
*
* Input:
* none
*
* Output:
* Returns nothing
*
*************************************************************************/
void pascal near helpCmd () {
outtext ("HTEST - Help Engine Test Harness\r\n", BRIGHTWHITE);
outtext ("\r\n", BRIGHTWHITE);
outtext ("Comands:\r\n", BRIGHTWHITE);
outtext ("\r\n", BRIGHTWHITE);
outtext ("ctrl on/off - turn on/off display of control lines\r\n", BRIGHTWHITE);
outtext ("disp - display first screen of most recently read topic\r\n", BRIGHTWHITE);
outtext ("down - move ahead one line in topic and display\r\n", BRIGHTWHITE);
outtext ("dump - dump file info (very large)\r\n", BRIGHTWHITE);
outtext ("exit - exit htest\r\n", BRIGHTWHITE);
outtext ("file x - open new help file, or make help file current\r\n", BRIGHTWHITE);
outtext ("help - display this screen\r\n", BRIGHTWHITE);
outtext ("look x - loop up context string & fetch topic\r\n", BRIGHTWHITE);
outtext ("next - fetch next physical topic\r\n", BRIGHTWHITE);
outtext ("prev - fetch previous physical topic\r\n", BRIGHTWHITE);
outtext ("up - move back one line in topic and display\r\n", BRIGHTWHITE);
outtext ("xref x - display all xrefs in current topic, or look up #x\r\n", BRIGHTWHITE);
outtext ("+ - move & redisplay one page down\r\n", BRIGHTWHITE);
outtext ("- - move & redisplay one page up\r\n", BRIGHTWHITE);
/* end helpCmd */}
/*** lookupCmd - process file command
*
* Looks up the specified string in the current helpfile, or the next help
* topic.
*
* Input:
* pString = help string to look up
* dir = direction: 0= look up string, 1=get next, -1= get previous
*
* Output:
* Returns nothing
*
*************************************************************************/
void pascal near lookupCmd (
char *pString,
int dir
) {
char buf[BUFSIZ];
unsigned cbCompressed;
unsigned cbUncompressed;
char far *pCompressed;
/*
* Start with the simple look up of the conetxt to get an nc. Report on
* failure.
*/
if (pString)
ncCur = HelpNc(pString,ncTbl[iNcCur]);
else if (dir>0) {
if (!ncCur.cn)
ncCur = ncTbl[iNcCur];
else
ncCur = HelpNcNext(ncCur);
}
else if (dir<0) {
if (!ncCur.cn)
ncCur = ncTbl[iNcCur];
else if (ncCur.cn != ncTbl[iNcCur].cn)
ncCur = HelpNcPrev(ncCur);
}
else
ncCur = ncTbl[iNcCur];
if (!ncCur.cn) {
outtext ("Lookup Failed: HelpNc/HelpNcNext/HelpNcPrev returned 0", LIGHTRED);
return;
}
/*
* It exists. Indicate what file we're looking in, what we found, and the
* nc that was returned
*/
sprintf (buf, "File #%d; Looking up:%s\r\n",iNcCur,
pString ? (*pString ? pString : "local context")
: (dir ? ((dir>0) ? "**NEXT**" : "**PREV**")
: "current"));
outtext (buf, BRIGHTWHITE);
sprintf (buf, "nc returned = %08lx\r\n",ncCur.cn);
outtext (buf, BRIGHTWHITE);
/*
* Free up memory for previously current topic
*/
if (mhTopicCur)
free(mhTopicCur);
/*
* Get the compressed memory size required, and report it. Alloc it.
*/
cbCompressed = HelpNcCb(ncCur);
sprintf (buf, "size of compressed topic = %d\r\n",cbCompressed);
outtext (buf, BRIGHTWHITE);
pCompressed = malloc(cbCompressed);
/*
* read in the compressed topic, getting the size required for the
* uncompressed results. Report that, and allocate it.
*/
cbUncompressed = HelpLook(ncCur,pCompressed);
sprintf (buf, "size of UNcompressed topic = %d\r\n",cbUncompressed);
outtext (buf, BRIGHTWHITE);
mhTopicCur = malloc(cbUncompressed);
//pTopicCur = MAKEP (mhTopicCur, 0);
pTopicCur = mhTopicCur;
/*
* Decompress the topic.
*/
HelpDecomp(pCompressed,pTopicCur,ncCur);
outtext ("Decompressed\r\n", BRIGHTWHITE);
/*
* exercise SzContext and cLines routines, reporting results
*/
HelpSzContext(buf,ncCur);
strcat (buf, "\r\n");
outtext (buf, BRIGHTWHITE);
sprintf(buf,"%d lines\r\n", HelpcLines(pTopicCur));
outtext (buf, BRIGHTWHITE);
/*
* Report the amount of available memory at this point, and then free up the
* compressed text
*/
free(pCompressed);
/* end lookupCmd */}
/*** xrefCmd - process xref command
*
* Display or execute cross reference
*
* Input:
* pText = pointer to ascii text which, if a non-zero number, indicates the
* xref to execute. If zero, display all
*
* Output:
* Returns nothing
*
*************************************************************************/
void pascal near xrefCmd (
char *pText
) {
hotspot hsCur; /* hot spot definition */
int i; /* working counter */
int iReq; /* request value */
char *pT; /* temp pointer */
iReq = atoi (pText);
hsCur.line = hsCur.col = 1;
i = 1;
while (HelpHlNext(0,pTopicCur,&hsCur)) {
/*
* if not explicit request, then list as much as we can
*/
if (!iReq) {
sprintf (buf, "Xref [%d] @ line: %05d columns %02d to %02d = "
,i
,hsCur.line
,hsCur.col
,hsCur.ecol);
pT = buf + strlen(buf);
if (*hsCur.pXref)
while (*pT++ = *hsCur.pXref++);
else
sprintf(pT, "Local >> topic # 0x%04x ",*(ushort far *)(hsCur.pXref+1));
strcat (buf, "\r\n");
outtext (buf, LIGHTGREEN);
}
else if (i == iReq) {
pT = buf;
if (*hsCur.pXref)
while (*pT++ = *hsCur.pXref++);
else {
*pT++ = *hsCur.pXref++;
*pT++ = *hsCur.pXref++;
*pT++ = *hsCur.pXref++;
}
lookupCmd (buf, 0);
return;
}
++i;
hsCur.col = hsCur.ecol+(ushort)1;
}
/* end xrefCmd */}
/*** outtext - output text with specific colors
*
* sets the forground color and location as appropriate, and displays the
* desired text. Checks for redirection, and if redirected, just outputs the
* text to stdout.
*
* Input:
* ptext = pointer to text to output
* color = color to use
*
* Output:
* Returns
*
*************************************************************************/
void pascal near outtext (
char *pText,
BYTE color
) {
outtextat (pText, curline++, 0, color);
if (curline >= lastline) {
if (isatty(_fileno(stdout))
&& !fBoth) {
outtextat ("More...", lastline, 0, BRIGHTWHITE);
// rjsa VioSetCurPos (lastline, 8, 0);
#if defined (OS2)
consoleSetCursor(lastline,8);
#else
consoleSetCursor(Scr,lastline,8);
#endif
gets (buf);
}
curline = 0;
cls ();
}
/* end outtext */}
/*** outtextat - put text with specific colors at a specific place
*
* sets the forground color and location as appropriate, and displays the
* desired text. Checks for redirection, and if redirected, just outputs the
* text to stdout.
*
* Input:
* ptext = pointer to text to output
* col = column to put into
* color = color to use
*
* Output:
* Returns
*
*************************************************************************/
void pascal near outtextat (
char *pText,
int line,
int col,
BYTE color
) {
char *pEol; /* ptr to nl, if present */
int len;
color |= (ColorByte & 0xf0);
if ((isatty(_fileno(stdout)) || fBoth) && (line <= lastline)) {
len = strlen(pText);
if (pEol = strchr (pText, '\r'))
*pEol = 0;
// rjsa VioWrtCharStrAtt (pText, strlen(pText), line, col, (PBYTE)&color, 0);
WrtCharStrAtt (pText, strlen(pText), line, col, (PBYTE)&color);
if (pEol)
*pEol = '\r';
}
if (!isatty(_fileno(stdout)) || fBoth)
printf ("%s",pText);
/* end outtextat */}
/*** assertDos - asserts that a dos call returned a zero
*
* Just prints the number passed it if non-zero, and quits
*
* Input:
* Return code from a dos call
*
* Output:
* Returns only if zero passed in
*
*************************************************************************/
void pascal near assertDos (
USHORT rv,
CHAR * pFile,
USHORT LineNo
) {
if (rv) {
printf ("assertDos: %u (0x%04x) File %s, line %u\n", rv, rv, pFile, LineNo);
exit (1);
}
/* end assertDos*/}
/*** cls - clear screen
*
* Clear screen to current backround color
*
* Input:
* none
*
* Output:
* Returns screen clear
*
*************************************************************************/
void pascal near cls () {
curline = 0;
// rjsa VioScrollUp (0, 0, 0xffff, 0xffff, 0xffff, cell, 0);
consoleSetAttribute( Scr, 0x1f );
consoleClearScreen(Scr, TRUE);
/* end cls */}
/*** phrasecopy - copy a keyword phrase from the table
*
* Copies a byte-length-prefixed string from far memory to a null terminated
* string in near memory.
*
* Input:
* dst - near pointer to destination
* src - far pointer to source
*
* Output:
* Returns far pointer to byte following source string
*
*************************************************************************/
uchar far * pascal near phrasecopy (
uchar *dst,
uchar far *src
) {
register int i;
if (i = (int)*src++)
while (i--)
*dst++ = *src++;
*dst = 0;
return src;
/* end phrasecopy */}
void far * pascal HelpLock(mhCur)
mh mhCur;
{
//return MAKEP(mhCur,0);
return mhCur;
}
void pascal HelpUnlock(mhCur)
mh mhCur;
{
mhCur;
}
void pascal HelpDealloc(mhCur)
mh mhCur;
{
if (mhCur)
free(mhCur);
}
USHORT WrtCellStr (PBYTE buf, int cb, int row, int col) {
int cl = col;
//consoleSetCursor(Scr,row,col);
while (cb) {
UCHAR c;
UCHAR attr;
c = *buf++;
attr = *buf++;
//consoleSetAttribute(Scr,attr);
//consoleWrite(Scr,&c,1);
consoleWriteLine( Scr, &c, 1, row, cl, attr, FALSE );
cl++;
cb -= 2;
}
consoleShowScreen(Scr);
return 0;
}
USHORT WrtLineAttr ( PBYTE pText,
lineattr *rgAttr,
int cb,
int row,
int col
) {
lineattr *Attr = rgAttr;
char *p = pText;
int l = cb;
int len;
consoleSetCursor(Scr, row, col );
while (cb > 0) {
if ( Attr->cb == 0xFFFF || Attr->attr == 0xFFFF ) {
len = cb;
} else {
len = Attr->cb;
}
outtextat (p, row, col, mpAttr[Attr->attr] );
col += len;
p += len;
cb -= len;
Attr++;
}
return (USHORT)l;
}
USHORT WrtCharStrAtt (PBYTE pText, int cb, int row, int col, PBYTE pcolor) {
//consoleSetCursor(Scr,row,col);
//consoleSetAttribute(Scr,*pcolor);
//consoleWrite( Scr,pText, cb );
consoleWriteLine( Scr, pText, cb, row, col, *pcolor, FALSE );
consoleShowScreen(Scr);
return 0;
}
/**********************************************************************
*
* LoadTheDll
*
* Loads the help engine dll (mshelp.dll) and initializes the
* pointers to the dll's entry points.
*
**********************************************************************/
void
LoadTheDll (
void) {
#if defined (OS2)
USHORT rc;
CHAR szFullName[256];
CHAR szErrorName[256];
USHORT i;
strcpy(szFullName, HELPDLL_BASE);
strcpy(szErrorName, HELPDLL_NAME);
ASSERTDOS(rc = DosLoadModule(szErrorName,
256,
szFullName,
&hModule));
for (i=0; i<LASTENTRYPOINT; i++) {
ASSERTDOS (rc = DosQueryProcAddr(hModule,
0L,
szEntryName[i],
(PFN*)&(pEntry[i])));
}
#else
#if defined (HELP_HACK)
//pEntry[0] = (PHF)HelpcLines;
//pEntry[1] = (PHF)HelpClose;
//pEntry[2] = (PHF)HelpCtl;
//pEntry[3] = (PHF)HelpDecomp;
//pEntry[4] = (PHF)HelpGetCells;
//pEntry[5] = (PHF)HelpGetInfo;
//pEntry[6] = (PHF)HelpGetLine;
//pEntry[7] = (PHF)HelpGetLineAttr;
//pEntry[8] = (PHF)HelpHlNext;
//pEntry[9] = (PHF)HelpLook;
//pEntry[10] = (PHF)HelpNc;
//pEntry[11] = (PHF)HelpNcBack;
//pEntry[12] = (PHF)HelpNcCb;
//pEntry[13] = (PHF)HelpNcCmp;
//pEntry[14] = (PHF)HelpNcNext;
//pEntry[15] = (PHF)HelpNcPrev;
//pEntry[16] = (PHF)HelpNcRecord;
//pEntry[17] = (PHF)HelpNcUniq;
//pEntry[18] = (PHF)HelpOpen;
//pEntry[19] = (PHF)HelpShrink;
//pEntry[20] = (PHF)HelpSzContext;
//pEntry[21] = (PHF)HelpXRef;
//pEntry[22] = (PHF)LoadFdb;
//pEntry[23] = (PHF)LoadPortion;
#else
USHORT i;
hModule = LoadLibrary(HELPDLL_NAME);
for (i=0; i<LASTENTRYPOINT; i++) {
pEntry[i] = (PHF)GetProcAddress(hModule, (LPSTR)szEntryName[i]);
}
#endif
#endif
}