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;
|
||
}
|