|
|
/*** 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
}
|