345 lines
9.3 KiB
C
345 lines
9.3 KiB
C
|
/*************************************************************************
|
||
|
**
|
||
|
** mhfile - file manipulation for the help extension for the Microsoft Editor
|
||
|
**
|
||
|
** Copyright <C> 1988, Microsoft Corporation
|
||
|
**
|
||
|
** Revision History:
|
||
|
**
|
||
|
** 09-Dec-1988 ln Changes for Dialog help
|
||
|
** 02-Sep-1988 ln Make all data inited. Add info in debug vers.
|
||
|
** 15-Aug-1988 ln New HelpOpen return values
|
||
|
** [] 16-May-1988 Created, extracted from mehelp.c
|
||
|
*/
|
||
|
#include <stdlib.h> /* ultoa */
|
||
|
#include <string.h> /* string functions */
|
||
|
#define _INCLUDE_TOOLS_
|
||
|
#include "mh.h" /* help extension include file */
|
||
|
|
||
|
/*************************************************************************
|
||
|
**
|
||
|
** static data
|
||
|
*/
|
||
|
static uchar envvar[]= "HELPFILES"; /* help file list env var */
|
||
|
static flagType fOpen = FALSE;/* file open attempted */
|
||
|
static uchar szfiles[BUFLEN] = ""; /* string for open help files */
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/************************************************************************
|
||
|
**
|
||
|
** closehelp - close an open help file
|
||
|
**
|
||
|
** Purpose:
|
||
|
**
|
||
|
** Entry:
|
||
|
** pfn = pointer to filename.
|
||
|
**
|
||
|
** Exit:
|
||
|
**
|
||
|
** Exceptions:
|
||
|
**
|
||
|
*/
|
||
|
flagType pascal near closehelp(pfn)
|
||
|
char *pfn;
|
||
|
{
|
||
|
int iHelpNew; /* index into file table */
|
||
|
nc ncNew; /* new file's initial nc */
|
||
|
|
||
|
/*
|
||
|
** attempt to open the file first, to get the initial context. If we cannot
|
||
|
** open the file, we stop here, since it wasn't open to begin with.
|
||
|
*/
|
||
|
ncNew = HelpOpen(pfn);
|
||
|
if (ISERROR(ncNew)) {
|
||
|
/*
|
||
|
** Scan the current file list for the same handle. If the handle returned
|
||
|
** by HelpOpen above is already in the table, then the file was already open,
|
||
|
** and we zero out that table entry.
|
||
|
*/
|
||
|
for (iHelpNew=MAXFILES-1; iHelpNew>=0; iHelpNew--) {
|
||
|
if ((files[iHelpNew].ncInit.mh == ncNew.mh) &&
|
||
|
(files[iHelpNew].ncInit.cn == ncNew.cn)) { /* if already open */
|
||
|
files[iHelpNew].ncInit.mh = 0;
|
||
|
files[iHelpNew].ncInit.cn = 0; /* remove from list */
|
||
|
}
|
||
|
}
|
||
|
/*
|
||
|
** We destory all traces of back-trace and currency, since these contexts may
|
||
|
** reference the now closed helpfile, close it and return.
|
||
|
*/
|
||
|
HelpClose(ncNew); /* close the file */
|
||
|
while (HelpNcBack().cn); /* destroy back-trace */
|
||
|
ncCur.mh = ncLast.mh = 0; /* and clear currancy */
|
||
|
ncCur.cn = ncLast.cn = 0;
|
||
|
}
|
||
|
return TRUE; /* and we're done */
|
||
|
|
||
|
/* end closehelp */}
|
||
|
|
||
|
/************************************************************************
|
||
|
**
|
||
|
** openhelp - open a help file & add to list of files
|
||
|
**
|
||
|
** Purpose:
|
||
|
**
|
||
|
** Entry:
|
||
|
** pfn = pointer to filename.
|
||
|
**
|
||
|
** Exit:
|
||
|
**
|
||
|
** Exceptions:
|
||
|
**
|
||
|
*/
|
||
|
void pascal near openhelp(char *pfn, struct findType *dummy1, void *ReturnValue)
|
||
|
{
|
||
|
int iHelpNew; /* index into file table */
|
||
|
nc ncNew; /* new file's initial nc */
|
||
|
char *pExt = 0; /* pointer to extension string */
|
||
|
flagType RetVal;
|
||
|
buffer pfnbuf;
|
||
|
assert (pfn);
|
||
|
|
||
|
|
||
|
fOpen = TRUE; /* we HAVE openned something */
|
||
|
/*
|
||
|
** preserve any prepended extensions.
|
||
|
*/
|
||
|
if (*pfn == '.') {
|
||
|
pExt = pfn;
|
||
|
while (*pfn && (*pfn != ':'))
|
||
|
pfn++; /* point to actual filename */
|
||
|
if (*pfn) *pfn++ = 0; /* terminate ext string */
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
** attempt to open the file. If we cannot open the file, we stop here.
|
||
|
*/
|
||
|
ncNew = HelpOpen(pfn);
|
||
|
if (ISERROR(ncNew)) {
|
||
|
strcpy (pfnbuf, pfn);
|
||
|
strcpy(buf,"Can't open [");
|
||
|
strcat(buf,pfnbuf);
|
||
|
|
||
|
switch (ncNew.cn) {
|
||
|
case HELPERR_FNF:
|
||
|
pfn = "]: Not Found";
|
||
|
break;
|
||
|
case HELPERR_READ:
|
||
|
pfn = "]: Read Error";
|
||
|
break;
|
||
|
case HELPERR_LIMIT:
|
||
|
pfn = "]: Too many help files";
|
||
|
break;
|
||
|
case HELPERR_BADAPPEND:
|
||
|
pfn = "]: Bad appended help file";
|
||
|
break;
|
||
|
case HELPERR_NOTHELP:
|
||
|
pfn = "]: Not a help file";
|
||
|
break;
|
||
|
case HELPERR_BADVERS:
|
||
|
pfn = "]: Bad help file version";
|
||
|
break;
|
||
|
case HELPERR_MEMORY:
|
||
|
pfn = "]: Out of Memory";
|
||
|
break;
|
||
|
default:
|
||
|
pfn = "]: Unkown error 0x ";
|
||
|
_ultoa (ncNew.cn, &pfn[18], 16);
|
||
|
}
|
||
|
|
||
|
strcat(buf,pfn);
|
||
|
errstat(buf,NULL);
|
||
|
debmsg (buf);
|
||
|
debend (TRUE);
|
||
|
|
||
|
if ( ReturnValue ) {
|
||
|
*((flagType *)ReturnValue) = FALSE;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
/*
|
||
|
** Scan the current file list for the same handle. If the handle returned
|
||
|
** by HelpOpen above is already in the table, then the file was already open,
|
||
|
** and we don't need to add it.
|
||
|
*/
|
||
|
for (iHelpNew=MAXFILES-1; iHelpNew>=0; iHelpNew--)
|
||
|
if ((files[iHelpNew].ncInit.mh == ncNew.mh) &&
|
||
|
(files[iHelpNew].ncInit.cn == ncNew.cn)) { /* if already open */
|
||
|
ifileCur = iHelpNew; /* set currency */
|
||
|
procExt(iHelpNew,pExt); /* process extensions */
|
||
|
if ( ReturnValue ) {
|
||
|
*((flagType *)ReturnValue) = TRUE;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
/*
|
||
|
** Scan the file list again for an unused slot. Once found, save the initial
|
||
|
** context for that help file, and finally set it up as the first help file
|
||
|
** to be searched.
|
||
|
*/
|
||
|
for (iHelpNew=MAXFILES-1; iHelpNew>=0; iHelpNew--)
|
||
|
if ((files[iHelpNew].ncInit.mh == 0) &&
|
||
|
(files[iHelpNew].ncInit.cn == 0)) { /* if available slot */
|
||
|
files[iHelpNew].ncInit = ncNew; /* save initial context */
|
||
|
ifileCur = iHelpNew; /* and set currency */
|
||
|
procExt(iHelpNew,pExt); /* process extensions */
|
||
|
if ( ReturnValue ) {
|
||
|
*((flagType *)ReturnValue) = TRUE;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
/*
|
||
|
** If we got here, it's because the loop above didn't find any open slots in
|
||
|
** our file table. Complain, close and exit.
|
||
|
*/
|
||
|
errstat ("Too many help files",NULL);
|
||
|
HelpClose(ncNew);
|
||
|
if ( ReturnValue ) {
|
||
|
*((flagType *)ReturnValue) = FALSE;
|
||
|
}
|
||
|
dummy1;
|
||
|
/* end openhelp */}
|
||
|
|
||
|
/************************************************************************
|
||
|
**
|
||
|
** procExt - process default extensions for file
|
||
|
**
|
||
|
** Purpose:
|
||
|
** fill in extension table for an openned file
|
||
|
**
|
||
|
** Entry:
|
||
|
** ifileCur = filetable index
|
||
|
** pExt = pointer to extension string
|
||
|
**
|
||
|
** Exit:
|
||
|
** filetable entry updated
|
||
|
*/
|
||
|
void pascal near procExt(ifileCur, pExt)
|
||
|
int ifileCur;
|
||
|
char *pExt;
|
||
|
{
|
||
|
int i,j;
|
||
|
char *pExtDst; /* place to put it */
|
||
|
|
||
|
if (pExt) { /* if there is one */
|
||
|
pExt++; /* skip leading period */
|
||
|
for (i=0; i<MAXEXT; i++) { /* for all possible ext slots */
|
||
|
pExtDst = files[ifileCur].exts[i]; /* point to destination */
|
||
|
j = 0;
|
||
|
while (*pExt && (*pExt != '.') && (j++ < 3))
|
||
|
*pExtDst++ = *pExt++;
|
||
|
if (*pExt == '.')
|
||
|
pExt++; /* skip period separator */
|
||
|
*pExtDst = 0; /* always terminate */
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* end procExt */}
|
||
|
|
||
|
/*** opendefault - if no files open yet, open the default set
|
||
|
*
|
||
|
* We delay this operation, in the case that the user will have a helpfiles:
|
||
|
* switch which will locate the helpfiles explicitly. In those cases this
|
||
|
* routine does nothing, and we don;t waste time up front openning files
|
||
|
* only to close them later.
|
||
|
*
|
||
|
* On the other hand, if he has not set a helpfiles switch by his first
|
||
|
* request for help, we want to try either the environment variable, if it
|
||
|
* exists, or when all else fails, default to mep.hlp.
|
||
|
*
|
||
|
* Input:
|
||
|
* none
|
||
|
*
|
||
|
* Output:
|
||
|
* Returns nothing. Helpfiles open, we hope.
|
||
|
*
|
||
|
*************************************************************************/
|
||
|
void pascal near opendefault ( void ) {
|
||
|
|
||
|
char *tmp;
|
||
|
|
||
|
if (!fOpen) {
|
||
|
if (getenv (envvar)) {
|
||
|
// prochelpfiles (getenv (envvar)); /* Process user-spec'd files */
|
||
|
prochelpfiles (tmp=getenvOem (envvar)); /* Process user-spec'd files */
|
||
|
free( tmp );
|
||
|
}
|
||
|
else
|
||
|
openhelp ("mep.hlp", NULL, NULL); /* else use default */
|
||
|
}
|
||
|
/* end opendefault */}
|
||
|
|
||
|
/************************************************************************
|
||
|
**
|
||
|
** prochelpfiles - process helpfiles: switch
|
||
|
**
|
||
|
** Purpose:
|
||
|
** called by the editor each time the helpfiles switch is changed.
|
||
|
**
|
||
|
** Entry:
|
||
|
** pszfiles = pointer to new switch value
|
||
|
**
|
||
|
** Exit:
|
||
|
**
|
||
|
** Exceptions:
|
||
|
**
|
||
|
*/
|
||
|
flagType pascal EXTERNAL prochelpfiles (pszfiles)
|
||
|
char *pszfiles;
|
||
|
{
|
||
|
char cTerm; /* terminating character */
|
||
|
int iHelp;
|
||
|
char *pEnd; /* pointer to end of current fn */
|
||
|
|
||
|
if ( !ExtensionLoaded ) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
strncpy(szfiles,pszfiles,BUFLEN); /* save specified string */
|
||
|
/*
|
||
|
** begin by closing all open help files and loosing curency
|
||
|
*/
|
||
|
for (iHelp=MAXFILES-1; iHelp>=0; iHelp--)
|
||
|
if ((files[iHelp].ncInit.mh) &&
|
||
|
(files[iHelp].ncInit.cn)) { /* if open file */
|
||
|
HelpClose(files[iHelp].ncInit); /* close it */
|
||
|
files[iHelp].ncInit.mh = 0;
|
||
|
files[iHelp].ncInit.cn = 0;
|
||
|
}
|
||
|
while (HelpNcBack().cn); /* destroy back-trace */
|
||
|
ncCur.mh = ncLast.mh = 0; /* and clear currancy */
|
||
|
ncCur.cn = ncLast.cn = 0;
|
||
|
|
||
|
while (*pszfiles) { /* while files to proc */
|
||
|
if (*pszfiles == ' ') /* strip leading spaces */
|
||
|
pszfiles++;
|
||
|
else {
|
||
|
pEnd = pszfiles;
|
||
|
while (*pEnd && (*pEnd != ' ') && (*pEnd != ';')) pEnd++; /* move to end of fn */
|
||
|
cTerm = *pEnd; /* save terminator */
|
||
|
*pEnd = 0;
|
||
|
|
||
|
|
||
|
forfile(pszfiles, A_ALL, openhelp, NULL);
|
||
|
|
||
|
#if rjsa
|
||
|
// Since pszfiles may contain wild characters, we use
|
||
|
// ffirst/fnext to open all of them
|
||
|
//
|
||
|
rc = ffirst(pszfiles, A_ALL, &buffer);
|
||
|
while (!rc) {
|
||
|
buffer.fbuf.achName[buffer.fbuf.cchName] = '\0';
|
||
|
openhelp(buffer.fbuf.achName, NULL, NULL);
|
||
|
rc = fnext(&buffer);
|
||
|
}
|
||
|
#endif
|
||
|
pszfiles = pEnd; /* point to end */
|
||
|
if (cTerm) pszfiles++; /* if more, move to next */
|
||
|
}
|
||
|
}
|
||
|
ifileCur = MAXFILES-1;
|
||
|
|
||
|
return TRUE;
|
||
|
/* end prochelpfiles */}
|