367 lines
8.5 KiB
C
367 lines
8.5 KiB
C
|
/*** mhevt - help extension event handling code
|
|||
|
*
|
|||
|
* Copyright <C> 1988, Microsoft Corporation
|
|||
|
*
|
|||
|
* This file contains the code called by the edit in response to events
|
|||
|
*
|
|||
|
* Revision History (most recent first):
|
|||
|
*
|
|||
|
* 30-Mar-1989 ln Fudge with keyevent to react corectly to what we want.
|
|||
|
* 23-Mar-1989 ln Created. Extracted from mhcore & others
|
|||
|
*
|
|||
|
*************************************************************************/
|
|||
|
#include <string.h> /* string functions */
|
|||
|
#include <malloc.h>
|
|||
|
#include "mh.h" /* help extension include file */
|
|||
|
|
|||
|
/*************************************************************************
|
|||
|
*
|
|||
|
* static data
|
|||
|
*/
|
|||
|
static EVT EVThlp = { /* keyboard event definition */
|
|||
|
EVT_KEY,
|
|||
|
keyevent,
|
|||
|
0,
|
|||
|
0,
|
|||
|
0 /* ALL keys */
|
|||
|
};
|
|||
|
static EVT EVTcan = { /* cancel event definition */
|
|||
|
EVT_CANCEL,
|
|||
|
CloseWin,
|
|||
|
0,
|
|||
|
0,
|
|||
|
0
|
|||
|
};
|
|||
|
static EVT EVTxit = { /* exit event definition */
|
|||
|
EVT_EXIT,
|
|||
|
CloseWin,
|
|||
|
0,
|
|||
|
0,
|
|||
|
0
|
|||
|
};
|
|||
|
static EVT EVTidl = { /* idle event definition */
|
|||
|
EVT_IDLE,
|
|||
|
IdleProc,
|
|||
|
0,
|
|||
|
0,
|
|||
|
0
|
|||
|
};
|
|||
|
static EVT EVTfcs = { /* focus loss event definition */
|
|||
|
EVT_LOSEFOCUS,
|
|||
|
LooseFocus,
|
|||
|
0,
|
|||
|
0,
|
|||
|
0
|
|||
|
};
|
|||
|
|
|||
|
/*** mhevtinit - init editor event handling
|
|||
|
*
|
|||
|
* Input:
|
|||
|
* none
|
|||
|
*
|
|||
|
* Output:
|
|||
|
* Returns nothing
|
|||
|
*
|
|||
|
*************************************************************************/
|
|||
|
void pascal near mhevtinit (void) {
|
|||
|
|
|||
|
EVTidl.focus = EVThlp.focus = pHelp;
|
|||
|
RegisterEvent(&EVThlp); /* register help key event */
|
|||
|
RegisterEvent(&EVTcan); /* register help cancel event */
|
|||
|
RegisterEvent(&EVTidl); /* register help idle event */
|
|||
|
RegisterEvent(&EVTxit); /* register help exit event */
|
|||
|
RegisterEvent(&EVTfcs); /* register help focus event */
|
|||
|
|
|||
|
/* end mhevtinit */}
|
|||
|
|
|||
|
/*** keyevent - called by editor whenever a key is pressed in a help window
|
|||
|
*
|
|||
|
* When called we know that pHelp is being displayed, and was current.
|
|||
|
* Process the key pressed by the user. Keys handled:
|
|||
|
*
|
|||
|
* TAB - move forward to next hot spot
|
|||
|
* BACK-TAB - move backward to next hot spot
|
|||
|
* lc Alpha - move forward to next hot spot whose text begins with alpha
|
|||
|
* uc Alpha - move backward to next hot spot whose text begins with alpha
|
|||
|
* Enter - execute cross reference, if we're on one
|
|||
|
* Space - execute cross reference, if we're on one
|
|||
|
*
|
|||
|
* Input:
|
|||
|
* parg = pointer to event arguments
|
|||
|
*
|
|||
|
* Output:
|
|||
|
* If the key pressed is one we recognize return TRUE, else we return FALSE
|
|||
|
* and let the editor process the key.
|
|||
|
*
|
|||
|
*************************************************************************/
|
|||
|
flagType pascal EXTERNAL keyevent (
|
|||
|
EVTargs far *parg
|
|||
|
) {
|
|||
|
|
|||
|
uchar c; /* character hit */
|
|||
|
int fDir; /* direction flag */
|
|||
|
f fWrapped = FALSE; /* wrapped arounf flag */
|
|||
|
hotspot hsCur; /* hot spot definition */
|
|||
|
char *pText = NULL;
|
|||
|
COL x;
|
|||
|
LINE y;
|
|||
|
|
|||
|
c = parg->arg.key.KeyData.Ascii;
|
|||
|
|
|||
|
//
|
|||
|
// if there is no topic, no sense doing anything
|
|||
|
//
|
|||
|
if (pTopic == 0) {
|
|||
|
if ( ((c <= 'z') && (c >= 'a')) ||
|
|||
|
((c <= 'Z') && (c >= 'A')) ||
|
|||
|
(c == 0x09) ) {
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// start by getting this info, in case it is used later.
|
|||
|
//
|
|||
|
GetTextCursor(&x, &y);
|
|||
|
hsCur.line = (ushort)++y;
|
|||
|
hsCur.col = (ushort)++x;
|
|||
|
|
|||
|
//
|
|||
|
// If he hit return or space, look for a cross reference at the current loc.
|
|||
|
// If there is one, process it.
|
|||
|
//
|
|||
|
if ((c == 0x0d) || (c == ' ')) {
|
|||
|
if (pText = HelpXRef (pTopic, &hsCur)) {
|
|||
|
#ifdef DEBUG
|
|||
|
debmsg ("Xref: ");
|
|||
|
if (*pText) {
|
|||
|
debmsg (pText);
|
|||
|
} else {
|
|||
|
debmsg ("@Local 0x");
|
|||
|
debhex ((long)*(ushort far *)(pText+1));
|
|||
|
}
|
|||
|
debend (TRUE);
|
|||
|
#endif
|
|||
|
if (!fHelpCmd ( pText /* command/help to look up */
|
|||
|
, FALSE /* change focus to help window */
|
|||
|
, FALSE /* not pop-up */
|
|||
|
)) {
|
|||
|
errstat ("Cannot Process Cross Reference", NULL);
|
|||
|
}
|
|||
|
}
|
|||
|
Display(); // Show CUrsor Position
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
if ( parg->arg.key.KeyData.Flags & (FLAG_CTRL | FLAG_ALT) ) {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Maneuvering keys:
|
|||
|
// TAB: Move to next hot spot
|
|||
|
// SHIFT+TAB Move to previous hot spot
|
|||
|
// lcase alpha Move to next hot spot beginning with alpha
|
|||
|
// ucase alpha Move to previous hot spot beginning with alpha
|
|||
|
//
|
|||
|
if ((c <= 'z') && (c >= 'a')) {
|
|||
|
fDir = (int)c-0x20;
|
|||
|
} else if ((c <= 'Z') && (c >= 'A')) {
|
|||
|
fDir = -(int)c;
|
|||
|
} else if (c == 0x09) {
|
|||
|
if (parg->arg.key.KeyData.Flags & FLAG_SHIFT) {
|
|||
|
fDir = -1;
|
|||
|
} else {
|
|||
|
fDir = 0;
|
|||
|
}
|
|||
|
} else {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// loop looking for the next cross reference that either follows or precedes
|
|||
|
// the current cursor position. Ensure that we do NOT end up on the same xref
|
|||
|
// we are currently on. If we've reached the end/beginning of the topic, wrap
|
|||
|
// around to the begining/end. Ensure we do this only ONCE, in case there are
|
|||
|
// NO cross references at all.
|
|||
|
//
|
|||
|
while (TRUE) {
|
|||
|
|
|||
|
if (HelpHlNext(fDir,pTopic,&hsCur)) {
|
|||
|
|
|||
|
MoveCur((COL)hsCur.col-1,(LINE)hsCur.line-1);
|
|||
|
IdleProc(parg);
|
|||
|
Display();
|
|||
|
|
|||
|
if (fWrapped || ((LINE)hsCur.line != y)) {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if ((fDir < 0) && ((COL)hsCur.ecol >= x)) {
|
|||
|
hsCur.col--;
|
|||
|
} else if ((fDir >= 0) && ((COL)hsCur.col <= x)) {
|
|||
|
hsCur.col = (ushort)(hsCur.ecol+1);
|
|||
|
} else {
|
|||
|
break;
|
|||
|
}
|
|||
|
} else {
|
|||
|
if (fWrapped++) {
|
|||
|
break;
|
|||
|
}
|
|||
|
hsCur.col = 1;
|
|||
|
hsCur.line = (fDir < 0) ? (ushort)FileLength(pHelp) : (ushort)1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
/*** IdleProc - Idle event processor
|
|||
|
*
|
|||
|
* Purpose:
|
|||
|
*
|
|||
|
* Input:
|
|||
|
* Editor event args passed, but ignored.
|
|||
|
*
|
|||
|
* Output:
|
|||
|
* Returns .....
|
|||
|
*
|
|||
|
*************************************************************************/
|
|||
|
flagType pascal EXTERNAL IdleProc (
|
|||
|
EVTargs far *arg
|
|||
|
) {
|
|||
|
|
|||
|
hotspot hsCur; /* hot spot definition */
|
|||
|
fl flCur; /* current cursor location */
|
|||
|
|
|||
|
UNREFERENCED_PARAMETER( arg );
|
|||
|
|
|||
|
/*
|
|||
|
** if there is no topic, no sense doing anything
|
|||
|
*/
|
|||
|
if (pTopic) {
|
|||
|
/*
|
|||
|
** If the cursor position has changed since the last idle call...
|
|||
|
*/
|
|||
|
GetTextCursor(&flCur.col, &flCur.lin);
|
|||
|
if ((flCur.col != flIdle.col) || (flCur.lin != flIdle.lin)) {
|
|||
|
/*
|
|||
|
** restore the color to the previous line, and check for a cross reference at
|
|||
|
** the current position. If there is one, change it's colors.
|
|||
|
*/
|
|||
|
if (flIdle.lin != -1)
|
|||
|
PlaceColor (flIdle.lin, 0, 0);
|
|||
|
|
|||
|
hsCur.line = (ushort)(flCur.lin+1);
|
|||
|
hsCur.col = (ushort)(flCur.col+1);
|
|||
|
|
|||
|
if (HelpXRef (pTopic, &hsCur))
|
|||
|
SetColor (pHelp, flCur.lin, hsCur.col-1, hsCur.ecol-hsCur.col+1, C_WARNING);
|
|||
|
|
|||
|
flIdle = flCur;
|
|||
|
}
|
|||
|
}
|
|||
|
Display();
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
/*** LooseFocus - called when help file looses focus
|
|||
|
*
|
|||
|
* This is called each time a file looses focus. If the help file is no
|
|||
|
* longer displayed, we clear it from memory and deallocate any associated
|
|||
|
* help text.
|
|||
|
*
|
|||
|
* Input:
|
|||
|
* e - ignored
|
|||
|
*
|
|||
|
* Output:
|
|||
|
* Returns TRUE.
|
|||
|
*
|
|||
|
*************************************************************************/
|
|||
|
flagType pascal EXTERNAL LooseFocus (
|
|||
|
EVTargs far *e
|
|||
|
) {
|
|||
|
|
|||
|
UNREFERENCED_PARAMETER( e );
|
|||
|
|
|||
|
if (!fInPopUp && pTopic && !fInOpen) {
|
|||
|
/*
|
|||
|
** Look for a window that has the help file in it. If found, we're done.
|
|||
|
*/
|
|||
|
if (FindHelpWin (FALSE))
|
|||
|
return FALSE;
|
|||
|
/*
|
|||
|
** There is no help window currently displayed, deallocate any topic text
|
|||
|
** we have lying around.
|
|||
|
*/
|
|||
|
if (pTopic) {
|
|||
|
free (pTopic);
|
|||
|
pTopic = NULL;
|
|||
|
}
|
|||
|
/*
|
|||
|
** If there is a help pFile, discard it's contents
|
|||
|
*/
|
|||
|
if (pHelp)
|
|||
|
DelFile (pHelp);
|
|||
|
}
|
|||
|
return TRUE;
|
|||
|
/* end LooseFocus */}
|
|||
|
|
|||
|
/*** CloseWin - Close a window on the help file
|
|||
|
*
|
|||
|
* Closes the help window, if it is up. Maintains window currancy after the
|
|||
|
* close. Relies on an eventual call to LooseFocus (above) to deallocate the
|
|||
|
* topic text, if it is there, and discard the help pFile.
|
|||
|
*
|
|||
|
* Can be called by editor event processor, in response to CANCEL or EXIT
|
|||
|
* event.
|
|||
|
*
|
|||
|
* Input:
|
|||
|
* dummy - EVTargs ignored.
|
|||
|
*
|
|||
|
* Output:
|
|||
|
* Returns TRUE.
|
|||
|
*
|
|||
|
*************************************************************************/
|
|||
|
flagType pascal EXTERNAL CloseWin (
|
|||
|
EVTargs far *dummy
|
|||
|
) {
|
|||
|
|
|||
|
|
|||
|
#if defined(PWB)
|
|||
|
/*
|
|||
|
** Look for the window that has the help file in it. If found, close it.
|
|||
|
*/
|
|||
|
if (pWinHelp) {
|
|||
|
if (!CloseWnd (pWinHelp)) {
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
#else
|
|||
|
|
|||
|
PWND pWinCur; /* window on entry */
|
|||
|
|
|||
|
UNREFERENCED_PARAMETER( dummy );
|
|||
|
/*
|
|||
|
** Look for the window that has the help file in it. If found, close it.
|
|||
|
*/
|
|||
|
if (pWinHelp) {
|
|||
|
SetEditorObject (RQ_WIN_CUR | 0xff, pWinHelp, 0);
|
|||
|
if (fSplit) {
|
|||
|
fExecute ("meta window");
|
|||
|
} else {
|
|||
|
fExecute ("setfile");
|
|||
|
}
|
|||
|
GetEditorObject (RQ_WIN_HANDLE, 0, &pWinCur);
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
pWinHelp = 0;
|
|||
|
if (pWinUser) {
|
|||
|
SetEditorObject (RQ_WIN_CUR | 0xff, pWinUser, 0);
|
|||
|
}
|
|||
|
}
|
|||
|
return TRUE;
|
|||
|
}
|