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.

434 lines
11 KiB

  1. /*** mhdisp - help extension display code
  2. *
  3. * Copyright <C> 1988, Microsoft Corporation
  4. *
  5. * This module contains routines dealing with the display of help information.
  6. *
  7. * Revision History (most recent first):
  8. *
  9. * 12-Mar-1989 ln Moved some to mhlook
  10. * 15-Feb-1989 ln Restore to correct current window on close of a
  11. * split window.
  12. * 26-Jan-1989 ln Turn help in dialog back on. (M200 #295)
  13. * 13-Jan-1989 ln PWIN->PWND
  14. * 09-Jan-1989 ln Popup boxes only in CW
  15. * 01-Dec-1988 ln Cleanup & dialog help
  16. * 28-Sep-1988 ln Update for CW
  17. * 22-Sep-1988 ln MessageBox ==> DoMessageBox
  18. * 02-Sep-1988 ln Make all data inited. Remove GP fault in debug vers.
  19. * 05-Aug-1988 ln Rewrote process keys.
  20. * [] 16-May-1988 LN Split off of mehelp.c
  21. *
  22. *************************************************************************/
  23. #include <stdlib.h> /* min macro */
  24. #include <string.h> /* string functions */
  25. #include "mh.h" /* help extension include file */
  26. /*** fDisplayNc - Display topic text for the context number passed in
  27. *
  28. * Input:
  29. * ncCur = context number
  30. * frecord, = TRUE => record for backtrace
  31. * fStay = TRUE => keep focus in current window, else move focus to
  32. * newly opened help window.
  33. * fWantPopUp = TRUE => display as popup window. (Ignored in non-CW)
  34. *
  35. * Exit:
  36. * returns TRUE on success.
  37. *
  38. *************************************************************************/
  39. flagType pascal near fDisplayNc (
  40. nc ncCur,
  41. flagType frecord,
  42. flagType fStay,
  43. flagType fWantPopUp
  44. ) {
  45. ushort cLines = 0; /* # of lines in window */
  46. EVTargs dummy;
  47. int fFile; /* file's flags */
  48. hotspot hsCur; /* hot spot definition */
  49. LINE iHelpLine = 0; /* next help line to read/disp */
  50. PSWI pHeight; /* ptr to heigth switch */
  51. winContents wc; /* description of win contents */
  52. BOOL fDisp = FALSE; /* True when Displayed */
  53. UNREFERENCED_PARAMETER( fWantPopUp );
  54. if (fReadNc(ncCur)) {
  55. debmsg ("Displaying nc:[");
  56. debhex (ncCur.cn);
  57. debmsg ("]");
  58. /*
  59. ** Set up some data....
  60. **
  61. ** - Invalidate the most recent cursor position for highlighting
  62. ** - Get pointer to editor's height switch
  63. ** - Set up current colors
  64. */
  65. flIdle.lin = -1;
  66. pHeight = FindSwitch ("height");
  67. #if defined(PWB)
  68. rgsa[C_NORM*2 + 1] = (uchar)hlColor;
  69. rgsa[C_BOLD*2 + 1] = (uchar)blColor;
  70. rgsa[C_ITALICS*2 + 1] = (uchar)itColor;
  71. rgsa[C_UNDERLINE*2 + 1] = (uchar)ulColor;
  72. rgsa[C_WARNING*2 + 1] = (uchar)wrColor;
  73. #else
  74. SetEditorObject (RQ_COLOR | C_NORM, 0, &hlColor);
  75. SetEditorObject (RQ_COLOR | C_BOLD, 0, &blColor);
  76. SetEditorObject (RQ_COLOR | C_ITALICS, 0, &itColor);
  77. SetEditorObject (RQ_COLOR | C_UNDERLINE,0, &ulColor);
  78. SetEditorObject (RQ_COLOR | C_WARNING, 0, &wrColor);
  79. /*
  80. ** If help window was found, close it, so that we can create it with the
  81. ** correct new size.
  82. */
  83. fInOpen = TRUE;
  84. CloseWin (&dummy);
  85. fInOpen = FALSE;
  86. #endif
  87. /*
  88. ** Set the ncLast, the most recently viewed context, to what we are about to
  89. ** bring up. If recording, save it in the backtrace as well.
  90. */
  91. ncLast = ncCur;
  92. if (frecord) {
  93. HelpNcRecord(ncLast);
  94. }
  95. if (!HelpGetInfo (ncLast, &hInfoCur, sizeof(hInfoCur))) {
  96. ncInitLast = NCINIT(&hInfoCur);
  97. } else {
  98. ncInitLast.mh = (mh)0;
  99. ncInitLast.cn = 0;
  100. }
  101. /*
  102. ** Read through the text, looking for any control lines that we want to
  103. ** respond to. Stop as soon as we discover a non-control line. We currently
  104. ** respond to:
  105. **
  106. ** :lnn where nn is the suggested size of the window.
  107. */
  108. ((topichdr *)pTopic)->linChar = 0xff;
  109. while (HelpGetLine((ushort)++iHelpLine, BUFLEN, buf, pTopic)) {
  110. if (buf[0] != ':') {
  111. break;
  112. }
  113. switch (buf[1]) {
  114. case 'l':
  115. cLines = (USHORT)(atoi (&buf[2]));
  116. default:
  117. break;
  118. }
  119. }
  120. ((topichdr *)pTopic)->linChar = ((topichdr *)pTopic)->appChar;
  121. /*
  122. ** Open the window on the help psuedo file. Read the lines one at a time
  123. ** from the help text, update any embedded key assignements, and put the
  124. ** line and color into the pseudo file.
  125. */
  126. #if defined(PWB)
  127. if (!(fInPopUp || fWantPopUp))
  128. #endif
  129. OpenWin (cLines);
  130. #if defined(PWB)
  131. else
  132. DelFile (pHelp);
  133. #endif
  134. debend (TRUE);
  135. iHelpLine = 0;
  136. while (HelpGetLine((ushort)(iHelpLine+1), (ushort)BUFLEN, (uchar far *)buf, pTopic)) {
  137. if ( buf[0] == ':' ) {
  138. switch (buf[1]) {
  139. case 'x':
  140. return FALSE;
  141. case 'c':
  142. case 'y':
  143. case 'f':
  144. case 'z':
  145. case 'm':
  146. case 'i':
  147. case 'p':
  148. case 'e':
  149. case 'g':
  150. case 'r':
  151. case 'n':
  152. iHelpLine++;
  153. continue;
  154. default:
  155. break;
  156. }
  157. }
  158. ProcessKeys();
  159. PutLine(iHelpLine,buf,pHelp);
  160. PlaceColor ((int)iHelpLine++, 0, 0);
  161. /*
  162. ** This is a speed hack to display help as soon as we get a screen full.
  163. ** "Looks" faster.
  164. */
  165. if (pHeight) {
  166. if (iHelpLine == *(pHeight->act.ival)) {
  167. Display ();
  168. fDisp = TRUE;
  169. }
  170. }
  171. }
  172. if (!fDisp) {
  173. Display();
  174. fDisp = TRUE;
  175. }
  176. /*
  177. ** Ensure that the help psuedo file is marked readonly, and clean
  178. */
  179. GetEditorObject (RQ_FILE_FLAGS | 0xff, pHelp, &fFile);
  180. fFile |= READONLY;
  181. fFile &= ~DIRTY;
  182. SetEditorObject (RQ_FILE_FLAGS | 0xff, pHelp, &fFile);
  183. /*
  184. ** Search for the first hotspot in the text which lies within the current
  185. ** window, and place the cursor there.
  186. */
  187. GetEditorObject (RQ_WIN_CONTENTS, 0, &wc);
  188. hsCur.line = 1;
  189. hsCur.col = 1;
  190. MoveCur((COL)0,(LINE)0);
  191. if (HelpHlNext(0,pTopic,&hsCur)) {
  192. if (hsCur.line <= wc.arcWin.ayBottom - wc.arcWin.ayTop) {
  193. MoveCur((COL)hsCur.col-1,(LINE)hsCur.line-1);
  194. }
  195. }
  196. /*
  197. ** If we're supposed to stay in the previous window, then change currancy
  198. ** to there. Clear the status line, and we're done!
  199. */
  200. #if defined(PWB)
  201. if (fWantPopUp) {
  202. if (!fInPopUp) {
  203. fInPopUp = TRUE;
  204. PopUpBox (pHelp,"Help");
  205. fInPopUp = FALSE;
  206. }
  207. }
  208. else
  209. #endif
  210. SetEditorObject (RQ_WIN_CUR | 0xff, fStay ? pWinUser : pWinHelp, 0);
  211. DoMessage (NULL);
  212. Display();
  213. return TRUE;
  214. }
  215. return errstat("Error Displaying Help",NULL);
  216. }
  217. /*** fReadNc - Read and decompress help topic
  218. *
  219. * Reads and decompresses the help topic associated with the given nc.
  220. * Allocaets memory as appropriate to read it in.
  221. *
  222. * Input:
  223. * ncCur - nc of help topic to read in
  224. *
  225. * Output:
  226. * Returns TRUE on successfull read in
  227. *
  228. * Exceptions:
  229. *
  230. * Notes:
  231. *
  232. *************************************************************************/
  233. flagType pascal near fReadNc (
  234. nc ncCur
  235. ) {
  236. int cbExp; /* size of compressed topic */
  237. flagType fRet = FALSE; /* return value */
  238. uchar far *pTopicC; /* mem for compressed topic */
  239. if (ncCur.mh && ncCur.cn) {
  240. /*
  241. ** Determine the memory required for the compressed topic text, and allocate
  242. ** that. Read in the compressed topic, and get the uncompressed size.
  243. ** Allocate that memory, and decompress. Once decompressed, discard the
  244. ** compressed topic.
  245. */
  246. if (cbExp = HelpNcCb(ncCur)) {
  247. debmsg (" sized,");
  248. if (pTopicC = malloc((long)cbExp)) {
  249. if (cbExp = HelpLook(ncCur,pTopicC)) {
  250. debmsg ("read,");
  251. if (pTopic) {
  252. free (pTopic);
  253. pTopic = NULL;
  254. }
  255. if (pTopic = malloc((long)cbExp)) {
  256. if (!HelpDecomp(pTopicC,pTopic,ncCur)) {
  257. fRet = TRUE;
  258. debmsg ("decomped");
  259. }
  260. }
  261. }
  262. free(pTopicC);
  263. pTopicC = NULL;
  264. }
  265. }
  266. }
  267. return fRet;
  268. /* end fReadNc */}
  269. /*** PlaceColor - Put color into help screen line
  270. *
  271. * Purpose:
  272. *
  273. * Input:
  274. * i = line number to be worked on
  275. * xStart,xEnd = Column range to be highlighted (one based, inclusive)
  276. *
  277. * Globals:
  278. * pTopic = Pointer to topic buffer
  279. *
  280. * Output:
  281. * Returns nothing
  282. *
  283. * Exceptions:
  284. *
  285. * Notes:
  286. *
  287. *************************************************************************/
  288. void pascal near PlaceColor (
  289. int line, /* line number to do */
  290. COL xStart, /* starting highlight column */
  291. COL xEnd /* ending highlight column */
  292. ) {
  293. buffer bufL; /* local buffer */
  294. ushort cbExp; /* size of color info */
  295. COL column = 1;
  296. struct lineAttr *pbT; /* byte lineattr pointer */
  297. lineattr *pwT; /* word lineattr pointer */
  298. /*
  299. ** Convert our internal color indecies into editor color indecies.
  300. */
  301. cbExp = HelpGetLineAttr ((ushort)(line+1), (ushort)BUFLEN, (lineattr far *)buf, pTopic) / sizeof(lineattr);
  302. pbT = (struct lineAttr *)bufL;
  303. pwT = (lineattr *)buf;
  304. while (cbExp-- > 0) {
  305. pbT->attr = atrmap (pwT->attr);
  306. column += (pbT->len = (uchar)pwT->cb);
  307. pbT++;
  308. pwT++;
  309. }
  310. PutColor ((LINE)line, (struct lineAttr far *)bufL, pHelp);
  311. if (xEnd != xStart) {
  312. SetColor (pHelp, line, xStart-1, xEnd-xStart+1, C_WARNING);
  313. }
  314. }
  315. /*** atrmap - map attributes in file to editor attributes
  316. *
  317. * Purpose:
  318. *
  319. * Input:
  320. * fileAtr = attribute word from the help file
  321. *
  322. * Output:
  323. * Returns attribute byte for editor.
  324. *
  325. *************************************************************************/
  326. uchar pascal near atrmap (
  327. ushort fileAtr
  328. ) {
  329. if (fileAtr == 0x7)
  330. return C_WARNING;
  331. else if (fileAtr & A_BOLD)
  332. return C_BOLD;
  333. else if (fileAtr & A_ITALICS)
  334. return C_ITALICS;
  335. else if (fileAtr & A_UNDERLINE)
  336. return C_UNDERLINE;
  337. else
  338. return C_NORM;
  339. /* end atrmap */}
  340. /*** ProcessKeys - replace embedded function names with current keys.
  341. *
  342. * Replaces ocurrances of <<function name>> in the text with the most recent
  343. * keystroke currently assigned to that function. ("<<" and ">>" here are
  344. * actually single graphic characters 174 and 175).
  345. *
  346. * If there is a space preceding the trailing ">>", the field is space filled
  347. * to that width. Else, the length of the keystroke text is used.
  348. *
  349. * Input:
  350. * None.
  351. *
  352. * Global:
  353. * Operates on buf.
  354. *
  355. * Output:
  356. * Returns nothing. Updates buf.
  357. *
  358. *************************************************************************/
  359. void pascal near ProcessKeys() {
  360. char *pKeyBuf;
  361. char *pKeyCur;
  362. char *pKeyEnd; /* ptr to end of magic field */
  363. char *pKeyFill; /* position to fill to */
  364. char *pKeyStart; /* ptr to start of magic field */
  365. buffer keybuf;
  366. pKeyStart = &buf[0];
  367. /*
  368. ** look for magic character to signal replacement. If found, begin replacement
  369. ** process.
  370. */
  371. while (pKeyStart = strchr (pKeyStart,174)) {
  372. /*
  373. ** Search for the terminating magic character. If found, examine the character
  374. ** immediate prior to see if it was a space, and record the "fill to this
  375. ** position" place. Copy the remainder of the line to a holding buffer.
  376. */
  377. if (pKeyFill = pKeyEnd = strchr(pKeyStart,175)) {
  378. if (*(pKeyEnd-1) != ' ')
  379. pKeyFill = 0;
  380. strcpy (keybuf, pKeyEnd+1);
  381. do
  382. *pKeyEnd-- = 0;
  383. while ((*pKeyEnd == ' ') && (pKeyEnd > pKeyStart));
  384. }
  385. /*
  386. ** replace the function name in the line with a list of the keys assigned to
  387. ** it. Search the string placed there for the last keystroke in the space
  388. ** seperated "and" list (which represents the most recent assignment), and
  389. ** then copy that down to the begining of the string.
  390. */
  391. NameToKeys(pKeyStart+1,pKeyStart);
  392. pKeyCur = pKeyStart-1;
  393. do pKeyBuf = pKeyCur+1;
  394. while (pKeyCur = strchr (pKeyBuf,' '));
  395. if (pKeyBuf != pKeyStart)
  396. strcpy (pKeyStart, pKeyBuf);
  397. pKeyStart = strchr(pKeyStart,0);
  398. /*
  399. ** If we are requested to space fill out the field, and our current position
  400. ** is prior to the fill position, then add spaces. Finally, append the
  401. ** remainder of the line back on.
  402. */
  403. if (pKeyFill) {
  404. while (pKeyStart <= pKeyFill)
  405. *pKeyStart++ = ' ';
  406. pKeyStart = pKeyFill + 1;
  407. }
  408. strcpy (pKeyStart, keybuf);
  409. }
  410. /* End ProcessKeys */}