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

  1. /*** mhevt - help extension event handling code
  2. *
  3. * Copyright <C> 1988, Microsoft Corporation
  4. *
  5. * This file contains the code called by the edit in response to events
  6. *
  7. * Revision History (most recent first):
  8. *
  9. * 30-Mar-1989 ln Fudge with keyevent to react corectly to what we want.
  10. * 23-Mar-1989 ln Created. Extracted from mhcore & others
  11. *
  12. *************************************************************************/
  13. #include <string.h> /* string functions */
  14. #include <malloc.h>
  15. #include "mh.h" /* help extension include file */
  16. /*************************************************************************
  17. *
  18. * static data
  19. */
  20. static EVT EVThlp = { /* keyboard event definition */
  21. EVT_KEY,
  22. keyevent,
  23. 0,
  24. 0,
  25. 0 /* ALL keys */
  26. };
  27. static EVT EVTcan = { /* cancel event definition */
  28. EVT_CANCEL,
  29. CloseWin,
  30. 0,
  31. 0,
  32. 0
  33. };
  34. static EVT EVTxit = { /* exit event definition */
  35. EVT_EXIT,
  36. CloseWin,
  37. 0,
  38. 0,
  39. 0
  40. };
  41. static EVT EVTidl = { /* idle event definition */
  42. EVT_IDLE,
  43. IdleProc,
  44. 0,
  45. 0,
  46. 0
  47. };
  48. static EVT EVTfcs = { /* focus loss event definition */
  49. EVT_LOSEFOCUS,
  50. LooseFocus,
  51. 0,
  52. 0,
  53. 0
  54. };
  55. /*** mhevtinit - init editor event handling
  56. *
  57. * Input:
  58. * none
  59. *
  60. * Output:
  61. * Returns nothing
  62. *
  63. *************************************************************************/
  64. void pascal near mhevtinit (void) {
  65. EVTidl.focus = EVThlp.focus = pHelp;
  66. RegisterEvent(&EVThlp); /* register help key event */
  67. RegisterEvent(&EVTcan); /* register help cancel event */
  68. RegisterEvent(&EVTidl); /* register help idle event */
  69. RegisterEvent(&EVTxit); /* register help exit event */
  70. RegisterEvent(&EVTfcs); /* register help focus event */
  71. /* end mhevtinit */}
  72. /*** keyevent - called by editor whenever a key is pressed in a help window
  73. *
  74. * When called we know that pHelp is being displayed, and was current.
  75. * Process the key pressed by the user. Keys handled:
  76. *
  77. * TAB - move forward to next hot spot
  78. * BACK-TAB - move backward to next hot spot
  79. * lc Alpha - move forward to next hot spot whose text begins with alpha
  80. * uc Alpha - move backward to next hot spot whose text begins with alpha
  81. * Enter - execute cross reference, if we're on one
  82. * Space - execute cross reference, if we're on one
  83. *
  84. * Input:
  85. * parg = pointer to event arguments
  86. *
  87. * Output:
  88. * If the key pressed is one we recognize return TRUE, else we return FALSE
  89. * and let the editor process the key.
  90. *
  91. *************************************************************************/
  92. flagType pascal EXTERNAL keyevent (
  93. EVTargs far *parg
  94. ) {
  95. uchar c; /* character hit */
  96. int fDir; /* direction flag */
  97. f fWrapped = FALSE; /* wrapped arounf flag */
  98. hotspot hsCur; /* hot spot definition */
  99. char *pText = NULL;
  100. COL x;
  101. LINE y;
  102. c = parg->arg.key.KeyData.Ascii;
  103. //
  104. // if there is no topic, no sense doing anything
  105. //
  106. if (pTopic == 0) {
  107. if ( ((c <= 'z') && (c >= 'a')) ||
  108. ((c <= 'Z') && (c >= 'A')) ||
  109. (c == 0x09) ) {
  110. return TRUE;
  111. }
  112. return FALSE;
  113. }
  114. //
  115. // start by getting this info, in case it is used later.
  116. //
  117. GetTextCursor(&x, &y);
  118. hsCur.line = (ushort)++y;
  119. hsCur.col = (ushort)++x;
  120. //
  121. // If he hit return or space, look for a cross reference at the current loc.
  122. // If there is one, process it.
  123. //
  124. if ((c == 0x0d) || (c == ' ')) {
  125. if (pText = HelpXRef (pTopic, &hsCur)) {
  126. #ifdef DEBUG
  127. debmsg ("Xref: ");
  128. if (*pText) {
  129. debmsg (pText);
  130. } else {
  131. debmsg ("@Local 0x");
  132. debhex ((long)*(ushort far *)(pText+1));
  133. }
  134. debend (TRUE);
  135. #endif
  136. if (!fHelpCmd ( pText /* command/help to look up */
  137. , FALSE /* change focus to help window */
  138. , FALSE /* not pop-up */
  139. )) {
  140. errstat ("Cannot Process Cross Reference", NULL);
  141. }
  142. }
  143. Display(); // Show CUrsor Position
  144. return TRUE;
  145. }
  146. if ( parg->arg.key.KeyData.Flags & (FLAG_CTRL | FLAG_ALT) ) {
  147. return FALSE;
  148. }
  149. //
  150. // Maneuvering keys:
  151. // TAB: Move to next hot spot
  152. // SHIFT+TAB Move to previous hot spot
  153. // lcase alpha Move to next hot spot beginning with alpha
  154. // ucase alpha Move to previous hot spot beginning with alpha
  155. //
  156. if ((c <= 'z') && (c >= 'a')) {
  157. fDir = (int)c-0x20;
  158. } else if ((c <= 'Z') && (c >= 'A')) {
  159. fDir = -(int)c;
  160. } else if (c == 0x09) {
  161. if (parg->arg.key.KeyData.Flags & FLAG_SHIFT) {
  162. fDir = -1;
  163. } else {
  164. fDir = 0;
  165. }
  166. } else {
  167. return FALSE;
  168. }
  169. //
  170. // loop looking for the next cross reference that either follows or precedes
  171. // the current cursor position. Ensure that we do NOT end up on the same xref
  172. // we are currently on. If we've reached the end/beginning of the topic, wrap
  173. // around to the begining/end. Ensure we do this only ONCE, in case there are
  174. // NO cross references at all.
  175. //
  176. while (TRUE) {
  177. if (HelpHlNext(fDir,pTopic,&hsCur)) {
  178. MoveCur((COL)hsCur.col-1,(LINE)hsCur.line-1);
  179. IdleProc(parg);
  180. Display();
  181. if (fWrapped || ((LINE)hsCur.line != y)) {
  182. break;
  183. }
  184. if ((fDir < 0) && ((COL)hsCur.ecol >= x)) {
  185. hsCur.col--;
  186. } else if ((fDir >= 0) && ((COL)hsCur.col <= x)) {
  187. hsCur.col = (ushort)(hsCur.ecol+1);
  188. } else {
  189. break;
  190. }
  191. } else {
  192. if (fWrapped++) {
  193. break;
  194. }
  195. hsCur.col = 1;
  196. hsCur.line = (fDir < 0) ? (ushort)FileLength(pHelp) : (ushort)1;
  197. }
  198. }
  199. return TRUE;
  200. }
  201. /*** IdleProc - Idle event processor
  202. *
  203. * Purpose:
  204. *
  205. * Input:
  206. * Editor event args passed, but ignored.
  207. *
  208. * Output:
  209. * Returns .....
  210. *
  211. *************************************************************************/
  212. flagType pascal EXTERNAL IdleProc (
  213. EVTargs far *arg
  214. ) {
  215. hotspot hsCur; /* hot spot definition */
  216. fl flCur; /* current cursor location */
  217. UNREFERENCED_PARAMETER( arg );
  218. /*
  219. ** if there is no topic, no sense doing anything
  220. */
  221. if (pTopic) {
  222. /*
  223. ** If the cursor position has changed since the last idle call...
  224. */
  225. GetTextCursor(&flCur.col, &flCur.lin);
  226. if ((flCur.col != flIdle.col) || (flCur.lin != flIdle.lin)) {
  227. /*
  228. ** restore the color to the previous line, and check for a cross reference at
  229. ** the current position. If there is one, change it's colors.
  230. */
  231. if (flIdle.lin != -1)
  232. PlaceColor (flIdle.lin, 0, 0);
  233. hsCur.line = (ushort)(flCur.lin+1);
  234. hsCur.col = (ushort)(flCur.col+1);
  235. if (HelpXRef (pTopic, &hsCur))
  236. SetColor (pHelp, flCur.lin, hsCur.col-1, hsCur.ecol-hsCur.col+1, C_WARNING);
  237. flIdle = flCur;
  238. }
  239. }
  240. Display();
  241. return FALSE;
  242. }
  243. /*** LooseFocus - called when help file looses focus
  244. *
  245. * This is called each time a file looses focus. If the help file is no
  246. * longer displayed, we clear it from memory and deallocate any associated
  247. * help text.
  248. *
  249. * Input:
  250. * e - ignored
  251. *
  252. * Output:
  253. * Returns TRUE.
  254. *
  255. *************************************************************************/
  256. flagType pascal EXTERNAL LooseFocus (
  257. EVTargs far *e
  258. ) {
  259. UNREFERENCED_PARAMETER( e );
  260. if (!fInPopUp && pTopic && !fInOpen) {
  261. /*
  262. ** Look for a window that has the help file in it. If found, we're done.
  263. */
  264. if (FindHelpWin (FALSE))
  265. return FALSE;
  266. /*
  267. ** There is no help window currently displayed, deallocate any topic text
  268. ** we have lying around.
  269. */
  270. if (pTopic) {
  271. free (pTopic);
  272. pTopic = NULL;
  273. }
  274. /*
  275. ** If there is a help pFile, discard it's contents
  276. */
  277. if (pHelp)
  278. DelFile (pHelp);
  279. }
  280. return TRUE;
  281. /* end LooseFocus */}
  282. /*** CloseWin - Close a window on the help file
  283. *
  284. * Closes the help window, if it is up. Maintains window currancy after the
  285. * close. Relies on an eventual call to LooseFocus (above) to deallocate the
  286. * topic text, if it is there, and discard the help pFile.
  287. *
  288. * Can be called by editor event processor, in response to CANCEL or EXIT
  289. * event.
  290. *
  291. * Input:
  292. * dummy - EVTargs ignored.
  293. *
  294. * Output:
  295. * Returns TRUE.
  296. *
  297. *************************************************************************/
  298. flagType pascal EXTERNAL CloseWin (
  299. EVTargs far *dummy
  300. ) {
  301. #if defined(PWB)
  302. /*
  303. ** Look for the window that has the help file in it. If found, close it.
  304. */
  305. if (pWinHelp) {
  306. if (!CloseWnd (pWinHelp)) {
  307. return TRUE;
  308. }
  309. #else
  310. PWND pWinCur; /* window on entry */
  311. UNREFERENCED_PARAMETER( dummy );
  312. /*
  313. ** Look for the window that has the help file in it. If found, close it.
  314. */
  315. if (pWinHelp) {
  316. SetEditorObject (RQ_WIN_CUR | 0xff, pWinHelp, 0);
  317. if (fSplit) {
  318. fExecute ("meta window");
  319. } else {
  320. fExecute ("setfile");
  321. }
  322. GetEditorObject (RQ_WIN_HANDLE, 0, &pWinCur);
  323. #endif
  324. pWinHelp = 0;
  325. if (pWinUser) {
  326. SetEditorObject (RQ_WIN_CUR | 0xff, pWinUser, 0);
  327. }
  328. }
  329. return TRUE;
  330. }