/*** mhutil - utilities for the help extension for the Microsoft Editor * * Copyright 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 functions */ #include #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: /* only, no arg */ cArg = 0; pArgText = NULL; break; case NULLARG: /* */ cArg = pArg->arg.nullarg.cArg; /* get count */ GrabWord (); /* get argtext and argword */ break; case STREAMARG: /* line movement */ cArg = pArg->arg.streamarg.cArg;/* get 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: /* text */ cArg = pArg->arg.textarg.cArg; /* get 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 : "" )); /* 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; }