/*** mhevt - help extension event handling code * * Copyright 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 functions */ #include #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; }