Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

366 lines
8.5 KiB

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