343 lines
8 KiB
C
343 lines
8 KiB
C
|
/*** mhutil - utilities for the help extension for the Microsoft Editor
|
|||
|
*
|
|||
|
* Copyright <C> 1988, Microsoft Corporation
|
|||
|
*
|
|||
|
* Revision History (most recent first):
|
|||
|
*
|
|||
|
* 01-Dec-1988 ln Cleanup & dislog help
|
|||
|
* 28-Sep-1988 ln Correct GrabWord return value
|
|||
|
* 02-Sep-1988 ln Make all data inited. Add info in debug vers.
|
|||
|
* [] 16-May-1988 Extracted from mehelp.c
|
|||
|
*
|
|||
|
*************************************************************************/
|
|||
|
#include <string.h> /* string functions */
|
|||
|
#include <malloc.h>
|
|||
|
#include "mh.h" /* help extension include file */
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/************************************************************************
|
|||
|
**
|
|||
|
** procArgs
|
|||
|
**
|
|||
|
** Purpose:
|
|||
|
** decode arguments passed into extension into commonly used variables.
|
|||
|
**
|
|||
|
** Entry:
|
|||
|
** pArg = pointer to arg structure, courtesy of Z
|
|||
|
**
|
|||
|
** Exit:
|
|||
|
** returns pArg->argType. Global variables updated.
|
|||
|
*/
|
|||
|
int pascal near procArgs (pArg)
|
|||
|
ARG far *pArg; /* argument data */
|
|||
|
{
|
|||
|
buf[0] = 0;
|
|||
|
pArgWord = pArgText = 0;
|
|||
|
rnArg.flFirst.col = rnArg.flLast.col = 0;
|
|||
|
rnArg.flFirst.lin = rnArg.flLast.lin = 0;
|
|||
|
cArg = 0;
|
|||
|
|
|||
|
opendefault ();
|
|||
|
pFileCur = FileNameToHandle ("", ""); /* get current file handle */
|
|||
|
fnCur[0] = 0;
|
|||
|
GetEditorObject(RQ_FILE_NAME,0,fnCur); /* get filename */
|
|||
|
fnExtCur = strchr (fnCur, '.'); /* and pointer to extension */
|
|||
|
|
|||
|
switch (pArg->argType) {
|
|||
|
case NOARG: /* <function> only, no arg */
|
|||
|
cArg = 0;
|
|||
|
pArgText = NULL;
|
|||
|
break;
|
|||
|
|
|||
|
case NULLARG: /* <arg><function> */
|
|||
|
cArg = pArg->arg.nullarg.cArg; /* get <arg> count */
|
|||
|
GrabWord (); /* get argtext and argword */
|
|||
|
break;
|
|||
|
|
|||
|
case STREAMARG: /* <arg>line movement<function> */
|
|||
|
cArg = pArg->arg.streamarg.cArg;/* get <arg> count */
|
|||
|
rnArg.flFirst.col = pArg->arg.streamarg.xStart;
|
|||
|
rnArg.flLast.col = pArg->arg.streamarg.xEnd;
|
|||
|
rnArg.flFirst.lin = pArg->arg.streamarg.yStart;
|
|||
|
if (GetLine(rnArg.flFirst.lin, buf, pFileCur) > rnArg.flFirst.col) {
|
|||
|
pArgText = &buf[rnArg.flFirst.col]; /* point at word */
|
|||
|
buf[rnArg.flLast.col] = 0; /* terminate string */
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case TEXTARG: /* <arg> text <function> */
|
|||
|
cArg = pArg->arg.textarg.cArg; /* get <arg> count */
|
|||
|
pArgText = pArg->arg.textarg.pText;
|
|||
|
break;
|
|||
|
}
|
|||
|
return pArg->argType;
|
|||
|
/* end procArgs */}
|
|||
|
|
|||
|
/************************************************************************
|
|||
|
**
|
|||
|
** GrabWord - Grab the word under the editor cursor
|
|||
|
**
|
|||
|
** Purpose:
|
|||
|
** grabs the word underneath the cursor for context sensitive help look-up.
|
|||
|
**
|
|||
|
** Entry:
|
|||
|
** none
|
|||
|
**
|
|||
|
** Returns:
|
|||
|
** nothing. pArgWord points to word, if it was parsed.
|
|||
|
*/
|
|||
|
void pascal near GrabWord () {
|
|||
|
|
|||
|
pArgText = pArgWord = 0;
|
|||
|
pFileCur = FileNameToHandle ("", ""); /* get current file handle */
|
|||
|
GetTextCursor (&rnArg.flFirst.col, &rnArg.flFirst.lin);
|
|||
|
if (GetLine(rnArg.flFirst.lin, buf, pFileCur)) { /* get line */
|
|||
|
pArgText = &buf[rnArg.flFirst.col]; /* point at word */
|
|||
|
while (!wordSepar((int)*pArgText))
|
|||
|
pArgText++; /* search for end */
|
|||
|
*pArgText = 0; /* and terminate */
|
|||
|
pArgWord = pArgText = &buf[rnArg.flFirst.col]; /* point at word */
|
|||
|
while ((pArgWord > &buf[0]) && !wordSepar ((int)*(pArgWord-1)))
|
|||
|
pArgWord--;
|
|||
|
}
|
|||
|
/* end GrabWord */}
|
|||
|
|
|||
|
/*** appTitle - Append help file title to buffer
|
|||
|
*
|
|||
|
* Read in the title of a help file and append it to a buffer.
|
|||
|
*
|
|||
|
* Input:
|
|||
|
* fpDest - far pointer to destination of string
|
|||
|
* ncInit - Any nc of file to get title for
|
|||
|
*
|
|||
|
* Output:
|
|||
|
* Returns
|
|||
|
*
|
|||
|
*************************************************************************/
|
|||
|
void pascal near appTitle (
|
|||
|
char far *pDest,
|
|||
|
nc ncInit
|
|||
|
) {
|
|||
|
/*
|
|||
|
** first, point to end of string to append to
|
|||
|
*/
|
|||
|
while (*pDest)
|
|||
|
pDest++;
|
|||
|
/*
|
|||
|
** Start by getting the info on the file referenced, so that we can get the
|
|||
|
** ncInit for that file.
|
|||
|
*/
|
|||
|
if (!HelpGetInfo (ncInit, &hInfoCur, sizeof(hInfoCur))) {
|
|||
|
ncInit = NCINIT(&hInfoCur);
|
|||
|
/*
|
|||
|
** Find the context string, and read the topic. Then just read the first
|
|||
|
** line into the destination
|
|||
|
*/
|
|||
|
ncInit = HelpNc ("h.title",ncInit);
|
|||
|
if (ncInit.cn && (fReadNc(ncInit))) {
|
|||
|
pDest += HelpGetLine (1, BUFLEN, pDest, pTopic);
|
|||
|
*pDest = 0;
|
|||
|
free (pTopic);
|
|||
|
pTopic = NULL;
|
|||
|
}
|
|||
|
/*
|
|||
|
** If no title was found, then just place the help file name there.
|
|||
|
*/
|
|||
|
else
|
|||
|
strcpy (pDest, HFNAME(&hInfoCur));
|
|||
|
}
|
|||
|
/*
|
|||
|
** If we couldn't even get the info, then punt...
|
|||
|
*/
|
|||
|
else
|
|||
|
strcpy (pDest, "** unknown **");
|
|||
|
/* end appTitle */}
|
|||
|
|
|||
|
|
|||
|
/*** errstat - display error status message
|
|||
|
*
|
|||
|
* In non cw, just display the strings on the status line. In CW, bring up
|
|||
|
* a message box.
|
|||
|
*
|
|||
|
* Input:
|
|||
|
* sz1 = first error message line
|
|||
|
* sz2 = second. May be NULL.
|
|||
|
*
|
|||
|
* Output:
|
|||
|
* Returns FALSE
|
|||
|
*************************************************************************/
|
|||
|
flagType pascal near errstat (
|
|||
|
char *sz1,
|
|||
|
char *sz2
|
|||
|
) {
|
|||
|
#if defined(PWB)
|
|||
|
DoMessageBox (sz1, sz2, NULL, MBOX_OK);
|
|||
|
#else
|
|||
|
buffer buf;
|
|||
|
|
|||
|
strcpy (buf, sz1);
|
|||
|
if (sz2) {
|
|||
|
strcat (buf, " ");
|
|||
|
strcat (buf, sz2);
|
|||
|
}
|
|||
|
stat (buf);
|
|||
|
#endif
|
|||
|
return FALSE;
|
|||
|
/* end errstat */}
|
|||
|
|
|||
|
/*** stat - display status line message
|
|||
|
*
|
|||
|
* Places extension name and message on the status line
|
|||
|
*
|
|||
|
* Entry:
|
|||
|
* pszFcn - Pointer to string to be prepended.
|
|||
|
*
|
|||
|
* Exit:
|
|||
|
* none
|
|||
|
*
|
|||
|
*************************************************************************/
|
|||
|
void pascal near stat(pszFcn)
|
|||
|
char *pszFcn; /* function name */
|
|||
|
{
|
|||
|
buffer buf; /* message buffer */
|
|||
|
|
|||
|
strcpy(buf,"mhelp: "); /* start with name */
|
|||
|
if (strlen(pszFcn) > 72) {
|
|||
|
pszFcn+= strlen(pszFcn) - 69;
|
|||
|
strcat (buf, "...");
|
|||
|
}
|
|||
|
strcat(buf,pszFcn); /* append message */
|
|||
|
DoMessage (buf); /* display */
|
|||
|
/* end stat */}
|
|||
|
|
|||
|
#ifdef DEBUG
|
|||
|
buffer debstring = {0};
|
|||
|
extern int delay; /* message delay */
|
|||
|
|
|||
|
/*** debhex - output long in hex
|
|||
|
*
|
|||
|
* Display the value of a long in hex
|
|||
|
*
|
|||
|
* Input:
|
|||
|
* lval = long value
|
|||
|
*
|
|||
|
* Output:
|
|||
|
* Returns nothing
|
|||
|
*
|
|||
|
*************************************************************************/
|
|||
|
void pascal near debhex (
|
|||
|
long lval
|
|||
|
) {
|
|||
|
char lbuf[10];
|
|||
|
|
|||
|
_ultoa (lval, lbuf, 16);
|
|||
|
debmsg (lbuf);
|
|||
|
/* end debhex */}
|
|||
|
|
|||
|
/*** debmsg - piece together debug message
|
|||
|
*
|
|||
|
* Outputs a the cummulative message formed by successive calls.
|
|||
|
*
|
|||
|
* Input:
|
|||
|
* psz = pointer to message part
|
|||
|
*
|
|||
|
* Output:
|
|||
|
* Returns nothing
|
|||
|
*************************************************************************/
|
|||
|
void pascal near debmsg (
|
|||
|
char far *psz
|
|||
|
) {
|
|||
|
_stat (strcat (debstring, psz ? psz : "<NULL>" ));
|
|||
|
/* end debmsg */}
|
|||
|
|
|||
|
/*** debend - terminates message accumulation & pauses
|
|||
|
*
|
|||
|
* Terminates the message accumulation, displays the final message, and
|
|||
|
* pauses, either for the pause time, or for a keystroke.
|
|||
|
*
|
|||
|
* Input:
|
|||
|
* fWait = TRUE => wait for a keystroke
|
|||
|
*
|
|||
|
* Output:
|
|||
|
* Returns nothing
|
|||
|
*
|
|||
|
*************************************************************************/
|
|||
|
void pascal near debend (
|
|||
|
flagType fWait
|
|||
|
) {
|
|||
|
if (fWait && delay) {
|
|||
|
#if defined(PWB)
|
|||
|
DoMessageBox (debstring, NULL, NULL, MBOX_OK);
|
|||
|
#else
|
|||
|
_stat (strcat (debstring, " Press a key..."));
|
|||
|
ReadChar ();
|
|||
|
#endif
|
|||
|
}
|
|||
|
#ifdef OS2
|
|||
|
else if (delay)
|
|||
|
DosSleep ((long)delay);
|
|||
|
#endif
|
|||
|
debstring[0] = 0;
|
|||
|
/* end debend */}
|
|||
|
|
|||
|
/*** _mhassertexit - display assertion message and exit
|
|||
|
*
|
|||
|
* Input:
|
|||
|
* pszExp - expression which failed
|
|||
|
* pszFn - filename containing failure
|
|||
|
* line - line number failed at
|
|||
|
*
|
|||
|
* Output:
|
|||
|
* Doesn't return
|
|||
|
*
|
|||
|
*************************************************************************/
|
|||
|
void pascal near _mhassertexit (
|
|||
|
char *pszExp,
|
|||
|
char *pszFn,
|
|||
|
int line
|
|||
|
) {
|
|||
|
char lbuf[10];
|
|||
|
|
|||
|
_ultoa (line, lbuf, 10);
|
|||
|
strcpy (buf, pszExp);
|
|||
|
strcat (buf, " in ");
|
|||
|
strcat (buf, pszFn);
|
|||
|
strcat (buf, ": line ");
|
|||
|
strcat (buf, lbuf);
|
|||
|
errstat ("Help assertion failed", buf);
|
|||
|
|
|||
|
fExecute ("exit");
|
|||
|
|
|||
|
/* end _mhassertexit */}
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
flagType pascal wordSepar (int i) {
|
|||
|
CHAR c = (CHAR)i;
|
|||
|
if (((c >= 'a') && (c <= 'z')) ||
|
|||
|
((c >= 'A') && (c <= 'Z')) ||
|
|||
|
((c >= '0') && (c <= '9')) ||
|
|||
|
( c == '_' ) ||
|
|||
|
( c == '$' ) ) {
|
|||
|
return FALSE;
|
|||
|
} else {
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
char far * pascal near xrefCopy (char far *dst, char far *src)
|
|||
|
{
|
|||
|
if ( *src ) {
|
|||
|
strcpy( dst, src );
|
|||
|
} else {
|
|||
|
dst[0] = src[0];
|
|||
|
dst[1] = src[1];
|
|||
|
dst[2] = src[2];
|
|||
|
}
|
|||
|
|
|||
|
return dst;
|
|||
|
}
|