Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

781 lines
21 KiB

/*** mhcore - help extension for the Microsoft Editor
*
* Copyright <C> 1988, Microsoft Corporation
*
* This file contains the core, top-level entrypoints for the help extension.
*
* Revision History (most recent first):
*
* 16-Apr-1989 ln Increment ref count for psuedo file.
* 12-Mar-1989 ln Various modifications for multiple context lookup.
* 21-Feb-1989 ln Ensure that fPopUp initialized.
* 14-Feb-1989 ln Enable BOXSTR
* 26-Jan-1989 ln Correct key assignments
* 13-Jan-1989 ln PWIN->PWND
* 01-Dec-1988 ln Cleanup & dialog help
* 03-Oct-1988 ln Change xref lookup to call HelpNc first (for xref in same
* file), then SearchHelp (possibly in other files).
* 28-Sep-1988 ln Changes for CW color and event support
* 14-Sep-1988 ln Change event arg definition.
* 12-Sep-1988 mz Made WhenLoaded match declaration
* 31-Aug-1988 Added additional checks for null pointers
* 01-Aug-1988 Add editor exit event, and detection of hot-keys which
* aren't.
* 28-Jul-1988 Change to "h." conventions.
* 12-Jul-1988 Reverse SHIFT+F1 and F1.
* 16-May-1988 Split out from mehelp.c
* 18-Feb-1988 Made to work, in protect mode
* 15-Dec-1987 Created, as test harness for the help engine.
*
*************************************************************************/
#include <string.h> /* string functions */
#include <malloc.h>
#ifdef DEBUG
#include <stdlib.h> /* for ltoa def */
#endif
#include "mh.h" /* help extension include file */
#include "version.h" /* version file */
/*
* use double macro level to force rup to be turned into string representation
*/
#define VER(x,y,z) VER2(x,y,z)
#if defined(PWB)
#define VER2(x,y,z) "Microsoft Editor Help Version v"###x##"."###y##"."###z##" - "##__DATE__" "##__TIME__
#else
#define VER2(x,y,z) "Microsoft Editor Help Version v1.02."###z##" - "##__DATE__" "##__TIME__
#endif
#define EXT_ID VER(rmj,rmm,rup)
/*************************************************************************
**
** Initialization of Global data in MH.H that needs it.
*/
helpfile files[MAXFILES] = {{{0}}}; /* help file structs */
flagType fInOpen = FALSE; /* TRUE=> currently opening win */
#if defined(PWB)
flagType fList = TRUE; /* TRUE=> search for and list dups*/
#else
flagType fList = FALSE; /* TRUE=> search for and list dups*/
#endif
flagType fPopUp = FALSE; /* current item is popup */
flagType fCreateWindow = TRUE; /* create window? */
int ifileCur = 0; /* Current index into files */
nc ncCur = {0,0}; /* most recently accessed */
nc ncLast = {0,0}; /* last topic displayed */
PWND pWinHelp = 0; /* handle to window w/ help in */
uchar far *pTopic = 0; /* mem for topic */
uchar far *pTopicC = 0; /* mem for compressed topic */
fl flIdle = {-1, -1}; /* last position of idle check */
int hlColor = 0x07; /* normal: white on black */
int blColor = 0x0f; /* bold: high white on black */
int itColor = 0x0a; /* italics: high green on black */
int ulColor = 0x0c; /* underline: high red on black */
int wrColor = 0x70; /* warning: black on white */
#ifdef DEBUG
int delay = 0; /* message delay */
#endif
int cArg; /* number of <args> hit */
flagType fInPopUp; /* TRUE=> currently in popup */
flagType fSplit; /* TRUE=> window was split open */
buffer fnCur; /* Current file being editted */
char * fnExtCur; /* ptr to it's extension */
buffer buf;
nc ncInitLast; /* ncInit of most recent topic */
nc ncInitLastFile; /* ncInit of most recent, our files*/
char * pArgText; /* ptr to any single line text */
char * pArgWord; /* ptr to context-sens word */
PFILE pFileCur; /* file handle of user file */
rn rnArg; /* range of argument */
PFILE pHelp; /* help PFILE */
PWND pWinUser; /* User's most recent window */
buffer szLastFound; /* last context string found */
flagType ExtensionLoaded = TRUE;
/*
** assignments
** table of strings of macro definitions & key assignments
*/
char *assignments[] = {
#if !defined(PWB)
"mhcontext:=arg mhelp.mhelp",
"mhback:=meta mhelp.mhelpnext",
"mhcontext:F1",
"mhelp.mhelp:shift+F1",
"mhelp.mhelpnext:ctrl+F1",
"mhback:alt+F1",
"mhelp.sethelp:alt+s",
#else
"pwbhelpcontext:=arg pwbhelp.pwbhelp",
"pwbhelpback:=meta pwbhelp.pwbhelpnext",
"pwbhelpindex:=arg \\\"h.index\\\" pwbhelp.pwbhelp",
"pwbhelpcontents:=arg \\\"h.contents\\\" pwbhelp.pwbhelp",
"pwbhelpagain:=arg pwbhelp.pwbhelpnext",
"pwbhelpcontext:F1",
"pwbhelp.pwbhelp:shift+F1",
"pwbhelp.pwbhelpnext:ctrl+F1",
"pwbhelpback:alt+F1",
"pwbhelp.sethelp:shift+ctrl+s",
#endif
NULL
};
#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
flagType LoadEngineDll(void);
flagType pascal EXTERNAL mhelp (unsigned int argData, ARG far *pArg, flagType fMeta );
flagType pascal EXTERNAL mhelpnext (unsigned int argData, ARG far *pArg, flagType fMeta );
flagType pascal EXTERNAL sethelp (unsigned int argData, ARG far *pArg, flagType fMeta );
/*** WhenLoaded - Routine called by Z when the extension is loaded
*
* This routine is called when Z loads the extension. We identify ourselves
* and assign the default keystroke.
*
* Entry:
* None
*
* Exit:
* None
*
* Exceptions:
* None
*
*************************************************************************/
void EXTERNAL WhenLoaded () {
char **pAsg;
static char *szHelpName = "<mhelp>";
#if !defined(PWB)
PSWI fgcolor;
#endif
int ref; // reference count
#if 0
//
// BUGBUG Delete when proved superfluous.
//
// Initialize global variables
//
cArg = 0;
pArgText = NULL;
pArgWord = NULL;
pFileCur = NULL;
fInOpen = FALSE;
fInPopUp = FALSE;
fSplit = FALSE;
fCreateWindow = FALSE;
fnExtCur = NULL;
ifileCur = 0;
pHelp = NULL;
pWinHelp = NULL;
pWinUser = NULL;
pTopic = NULL;
fList = FALSE;
#endif
if (!LoadEngineDll() ) {
DoMessage( "mhelp: Cannot load help engine" );
ExtensionLoaded = FALSE;
return;
}
DoMessage (EXT_ID); /* display signon */
/*
** Make default key assignments, & create default macros.
*/
strcpy (buf, "arg \"");
for (pAsg = assignments; *pAsg; pAsg++) {
strcpy (buf+5, *pAsg);
strcat (buf, "\" assign");
fExecute (buf);
}
/*
** CW: Init CW specifics & set up the colors that we will use.
*/
#if defined(PWB)
mhcwinit ();
hlColor = rgsa[FGCOLOR*2 +1];
blColor |= hlColor & 0xf0;
itColor |= hlColor & 0xf0;
ulColor |= hlColor & 0xf0;
wrColor |= (hlColor & 0x70) >> 8;
fInPopUp = FALSE;
#else
/*
* make semi-intellgent guesses on users colors.
*/
if (fgcolor = FindSwitch("fgcolor")) {
hlColor = *fgcolor->act.ival;
blColor |= hlColor & 0xf0;
itColor |= hlColor & 0xf0;
ulColor |= hlColor & 0xf0;
wrColor |= (hlColor & 0x70) >> 8;
}
#endif
/*
* create the psuedo file we'll be using for on-line help.
*/
if (pHelp = FileNameToHandle(szHelpName,NULL)) {
DelFile (pHelp);
} else {
pHelp = AddFile (szHelpName);
FileRead (szHelpName, pHelp);
}
//
// Increment the file's reference count so it can't be discarded
//
GetEditorObject (RQ_FILE_REFCNT | 0xff, pHelp, &ref);
ref++;
SetEditorObject (RQ_FILE_REFCNT | 0xff, pHelp, &ref);
mhevtinit ();
}
/*****************************************************************
*
* LoadEngineDll
*
* Loads the help engine and initialize the table of function
* pointers to the engine's entry points (pHelpEntry).
*
* Entry:
* none
*
* Exit:
* none
*
*******************************************************************/
flagType
LoadEngineDll (
void
) {
#if defined (OS2)
USHORT rc;
#endif
CHAR szFullName[256];
CHAR szErrorName[256];
USHORT i;
// Initialize pointers to NULL in case something goes wrong.
for (i=0; i<LASTENTRYPOINT; i++) {
pHelpEntry[i] = 0;
}
strcpy(szFullName, HELPDLL_BASE);
strcpy(szErrorName, HELPDLL_NAME);
#if defined (OS2)
rc = DosLoadModule(szErrorName,
256,
szFullName,
&hModule);
for (i=0; i<LASTENTRYPOINT; i++) {
rc = DosQueryProcAddr(hModule,
0,
szEntryName[i],
(PFN *)&(pHelpEntry[i]));
}
#else
hModule = LoadLibrary(szFullName);
if ( !hModule ) {
return FALSE;
}
for (i=0; i<LASTENTRYPOINT; i++) {
pHelpEntry[i] = (PHF)GetProcAddress(hModule, szEntryName[i]);
}
return TRUE;
#endif // OS2
}
/*** mhelp - editor help function
*
* main entry point for editor help functions.
*
* NOARG: - Get help on "Default"; change focus to help window.
* META NOARG - prompt for keystroke and get help on that function; change
* focus to help window.
* NULLARG: - Get help on word at cursor position; change focus to help
* window.
* STREAMARG: - Get help on text argument; change focus to help window.
* TEXTARG: - Get help on typed in word; change focus to help window.
*
* Entry:
* Standard Z extension
*
* Exit:
* Returns TRUE on successfull ability to get help on selected topic.
*
* Exceptions:
* None
*
*************************************************************************/
flagType pascal EXTERNAL mhelp (
unsigned int argData, /* keystroke invoked with */
ARG far *pArg, /* argument data */
flagType fMeta /* indicates preceded by meta */
) {
buffer tbuf; /* buf to put ctxt string into */
char *pText = NULL; /* pointer to the lookup text */
COL Col; /* Current cursor position */
LINE Line;
flagType RetVal; /* Return Value */
UNREFERENCED_PARAMETER( argData );
if ( !ExtensionLoaded ) {
return FALSE;
}
GetTextCursor(&Col, &Line);
switch (procArgs (pArg)) {
//
// null arg: context sensitive help. First, is we're looking at a help
// topic, check for any cross references that apply to the current location.
// If none do, then if a word was found when processing args, look that up.
//
case NULLARG:
//
// context-sensitive
//
if ((pFileCur == pHelp) && (pTopic)) {
//
// hot spot definition
//
hotspot hsCur;
hsCur.line = (ushort)(rnArg.flFirst.lin+1);
hsCur.col = (ushort)rnArg.flFirst.col+(ushort)1;
if (pText = HelpXRef(pTopic, &hsCur)) {
debmsg ("Xref=>");
debmsg (pText);
break;
}
}
if (pArgText) {
if (*pArgText && (pText = pArgWord)) {
debmsg ("Ctxt=>");
debmsg (pText);
break;
}
}
//
// for stream and textarg types, the argument, if any, is that entered of
// highlighted by the user.
//
case STREAMARG: /* context sensitive */
case TEXTARG: /* user entered context */
if (pArgText) {
if (*pArgText) {
pText = pArgText;
}
}
case NOARG: /* default context */
//
// meta: prompt user for keystroke, get the name of the function assigned
// to whatever he presses, and display help on that.
//
if (fMeta) {
stat("Press Keystroke:");
pText = ReadCmd()->name;
}
break;
}
//
// If after everything above we still have no text, then use the default
// context.
//
if (pText == NULL) {
//
// Default context
//
pText = "h.default";
}
debmsg (" Looking up:");
debmsg (pText);
debend (TRUE);
RetVal = fHelpCmd ( xrefCopy(tbuf,pText) /* command */
, (flagType)(pArg->argType != NOARG) /* change focus?*/
, FALSE /* not pop-up */
);
return RetVal;
}
/*** mhelpnext - editor help traversal function
*
* Handles next and previous help access.
*
* mhelpnext - next physical
* arg mhelpnext - next ocurrance
* meta mhelpnext - previous viewed
*
* Entry:
* Standard Z extension
*
* Exit:
* Returns TRUE on successfull ability to get help on selected topic.
*
* Exceptions:
* None
*
*************************************************************************/
flagType pascal EXTERNAL mhelpnext (
unsigned int argData, /* keystroke invoked with */
ARG far *pArg, /* argument data */
flagType fMeta /* indicates preceded by meta */
) {
UNREFERENCED_PARAMETER( argData );
//
// Ensure that help files are open, and then process the arguments and a few
// other init type things
//
procArgs (pArg);
//
// if there was no help context to start with, then we can't go either way,
// so inform the user
//
if (!ncLast.mh && !ncLast.cn) {
return errstat("No previously viewed help", NULL);
}
if (fMeta) {
//
// meta: attempt to get the most recently viewed help context. If a help
// window is currently up, then if the one we just found is the same as that
// in the window, go back once more. If no back trace, then say so.
//
ncCur = HelpNcBack();
if (FindHelpWin(FALSE)) {
if ((ncCur.mh == ncLast.mh) &&
(ncCur.cn == ncLast.cn)) {
ncCur = HelpNcBack();
}
}
if ((ncCur.mh == 0) && (ncCur.cn == 0)) {
return errstat ("No more backtrace", NULL);
}
} else if (pArg->arg.nullarg.cArg) {
//
// not meta, and args. Try to look again
//
ncCur = ncSearch ( szLastFound /* search for last string again */
, NULL /* no extension restriction */
, ncInitLastFile /* file where we found it last */
, TRUE /* skip all until then */
, FALSE /* don;t look at all files */
);
} else {
//
// not meta, no args, Just get the next help context.
//
ncCur = HelpNcNext(ncLast);
}
if (!ncCur.mh && !ncCur.cn) {
return FALSE;
}
return fDisplayNc ( ncCur /* nc to display */
, TRUE /* add to backtrace list */
, TRUE /* keep focus in current win */
, FALSE); /* Not as a pop-up, though */
}
/*** sethelp - editor help file list manipulation
*
* Function which allows the user to add to, delete from or examine the
* list of help files used by the extension
*
* Input:
* Standard editing function.
*
* Output:
* Returns TRUE if file succefully added or deleted, or the list displayed.
*
*************************************************************************/
flagType pascal EXTERNAL sethelp (
unsigned int argData, /* keystroke invoked with */
ARG far *pArg, /* argument data */
flagType fMeta /* indicates preceded by meta */
) {
int i = 0;
int j;
int iHelpNew; /* file table index */
nc ncNext; /* nc for next file */
char *pT; /* temp pointer */
EVTargs dummy;
int fFile; /* file's flags */
UNREFERENCED_PARAMETER( argData );
procArgs(pArg);
if ( !pArgText ) {
return FALSE;
}
//
// The special request to <sethelp> to "?" displays a list of all open
// help files.
//
// We do this by first clearing the help psudeo file and ensuring that the
// topic text is also gone. Then for each file we output the help engine's
// physical filename, along with any extensions that the user associated
// with it. We also walk the list of appended files, and print the original
// filename and helpfile title for each.
//
// We walk the list in the same way that it is searched, so that the
// displayed list also reflects the default search order.
//
if ( pArgText && (*(ushort UNALIGNED *)pArgText == (ushort)'?') ) {
fInOpen = TRUE;
CloseWin (&dummy);
fInOpen = FALSE;
OpenWin (0);
//
// Ensure that the help pseudo file is marked readonly, and clean
//
GetEditorObject (RQ_FILE_FLAGS | 0xff, pHelp, &fFile);
fFile |= READONLY;
fFile &= ~DIRTY;
SetEditorObject (RQ_FILE_FLAGS | 0xff, pHelp, &fFile);
SetEditorObject (RQ_WIN_CUR | 0xff, pWinHelp, 0);
// asserte(pFileToTop (pHelp)); /* display psuedo file */
MoveCur((COL)0,(LINE)0); /* and go to upper left */
DelFile (pHelp);
if (pTopic) {
free(pTopic);
pTopic = NULL;
}
iHelpNew = ifileCur;
do {
ncNext = files[iHelpNew].ncInit;
while (ncNext.mh && ncNext.cn && !HelpGetInfo (ncNext, &hInfoCur, sizeof(hInfoCur))) {
if ((ncNext.mh == files[iHelpNew].ncInit.mh) &&
(ncNext.cn == files[iHelpNew].ncInit.cn)) {
memset (buf, ' ', 20);
buf[20] = 0;
strncpy (buf, FNAME(&hInfoCur), strlen(FNAME(&hInfoCur)));
pT = &buf[20];
for (j=0; j<MAXEXT; j++) {
if (files[iHelpNew].exts[j][0]) {
buf[19] = '>';
strcat (pT," .");
strcat (pT,files[iHelpNew].exts[j]);
}
}
PutLine((LINE)i++,buf,pHelp);
}
memset (buf, ' ', 15);
strncpy (&buf[2], HFNAME(&hInfoCur), strlen(HFNAME(&hInfoCur)));
strcpy (&buf[15], ": ");
appTitle (buf, ncNext);
PutLine((LINE)i++,buf,pHelp);
ncNext = NCLINK(&hInfoCur);
}
iHelpNew += iHelpNew ? -1 : MAXFILES-1;
} while (iHelpNew != ifileCur);
#ifdef DEBUG
PutLine((LINE)i++," ",pHelp);
strcpy(buf,"ncLast: 0x");
strcat(buf,_ltoa(ncLast,&buf[128],16));
PutLine((LINE)i++,buf,pHelp);
strcpy(buf,"ncCur: 0x");
strcat(buf,_ltoa(ncCur,&buf[128],16));
PutLine((LINE)i++,buf,pHelp);
#endif
DoMessage (NULL);
return TRUE;
}
//
// Not a special request, just the user adding or removing a file from the
// list of files to search.
//
if (fMeta)
return closehelp(pArgText);
{
flagType Status;
openhelp(pArgText, NULL, &Status);
return Status;
}
}
/*************************************************************************
**
** Z communication tables
**
** switch communication table to Z
*/
struct swiDesc swiTable[] = {
{"helpfiles", prochelpfiles, SWI_SPECIAL },
{"helpwindow", toPIF(fCreateWindow), SWI_BOOLEAN },
#if defined(PWB)
{"helplist", toPIF(fList), SWI_BOOLEAN },
#endif
{"helpcolor", toPIF(hlColor), SWI_NUMERIC | RADIX16 },
{"helpboldcolor", toPIF(blColor), SWI_NUMERIC | RADIX16 },
{"helpitalcolor", toPIF(itColor), SWI_NUMERIC | RADIX16 },
{"helpundrcolor", toPIF(ulColor), SWI_NUMERIC | RADIX16 },
{"helpwarncolor", toPIF(wrColor), SWI_NUMERIC | RADIX16 },
#ifdef DEBUG
{"helpdelay", toPIF(delay), SWI_NUMERIC | RADIX10 },
#endif
{0, 0, 0}
};
/*
** command communication table to Z
*/
struct cmdDesc cmdTable[] = {
#if defined(PWB)
{ "pwbhelpnext", mhelpnext, 0, NOARG | NULLARG },
{ "pwbhelp", mhelp, 0, NOARG | NULLARG | STREAMARG | TEXTARG | BOXSTR},
#else
{ "mhelpnext", (funcCmd)mhelpnext, 0, NOARG | NULLARG },
{ "mhelp", (funcCmd)mhelp, 0, NOARG | NULLARG | STREAMARG | TEXTARG | BOXSTR},
#endif
{ "sethelp", (funcCmd)sethelp, 0, NULLARG | STREAMARG | TEXTARG | BOXSTR},
{0, 0, 0}
};