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.

395 lines
10 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. sphelp.c
  5. Abstract:
  6. Routines for displaying on-line help during text setup.
  7. Author:
  8. Ted Miller (tedm) 2-Aug-1993
  9. Revision History:
  10. --*/
  11. #include "spprecmp.h"
  12. #pragma hdrstop
  13. #define MAX_HELP_SCREENS 100
  14. PWSTR HelpScreen[MAX_HELP_SCREENS+1];
  15. VOID
  16. SpHelp(
  17. IN ULONG MessageId, OPTIONAL
  18. IN PCWSTR FileText, OPTIONAL
  19. IN ULONG Flags
  20. )
  21. {
  22. UCHAR StatusAttribute, BackgroundAttribute, HeaderAttribute,
  23. ClientAttribute, ClientIntenseAttribute;
  24. PWSTR HelpText,p,q;
  25. ULONG ScreenCount;
  26. ULONG ValidKeys[8];
  27. ULONG CurrentScreen;
  28. ULONG y;
  29. BOOLEAN Intense;
  30. BOOLEAN Done;
  31. unsigned kc;
  32. //
  33. // Pick the video attributes we want
  34. //
  35. if(Flags & SPHELP_LICENSETEXT) {
  36. StatusAttribute = DEFAULT_STATUS_ATTRIBUTE;
  37. BackgroundAttribute = DEFAULT_BACKGROUND;
  38. HeaderAttribute = DEFAULT_ATTRIBUTE;
  39. ClientAttribute = DEFAULT_ATTRIBUTE;
  40. ClientIntenseAttribute = (ATT_FG_INTENSE | ATT_BG_INTENSE);
  41. } else {
  42. StatusAttribute = (ATT_FG_WHITE | ATT_BG_BLUE);
  43. BackgroundAttribute = ATT_WHITE;
  44. HeaderAttribute = (ATT_FG_BLUE | ATT_BG_WHITE);
  45. ClientAttribute = (ATT_FG_BLACK | ATT_BG_WHITE);
  46. ClientIntenseAttribute = (ATT_FG_BLUE | ATT_BG_WHITE);
  47. }
  48. //
  49. // Retreive the help text.
  50. //
  51. if (FileText) {
  52. HelpText = (PWSTR)FileText;
  53. } else {
  54. HelpText = SpRetreiveMessageText(NULL,MessageId,NULL,0);
  55. if (!HelpText) { // no way to return an error code, so fail quietly
  56. goto s0;
  57. }
  58. }
  59. //
  60. // Shop off extra blank lines in the text.
  61. //
  62. p = HelpText + wcslen(HelpText);
  63. while((p > HelpText) && SpIsSpace(*(p-1))) {
  64. p--;
  65. }
  66. if(q = wcschr(p,L'\n')) {
  67. *(++q) = 0;
  68. }
  69. //
  70. // Break up the help text into screens.
  71. // The maximum length of a help screen will be the client screen size
  72. // minus two lines for spacing. A %P alone at the beginning of a line
  73. // forces a page break.
  74. //
  75. for(p=HelpText,ScreenCount=0; *p; ) {
  76. //
  77. // Mark the start of a new screen.
  78. //
  79. HelpScreen[ScreenCount++] = p;
  80. //
  81. // Count lines in the help text.
  82. //
  83. for(y=0; *p; ) {
  84. //
  85. // Determine whether this line is really a hard page break
  86. // or if we have exhausted the number of lines allowed on a screen.
  87. //
  88. if(((p[0] == L'%') && (p[1] == 'P')) || (++y == CLIENT_HEIGHT-2)) {
  89. break;
  90. }
  91. //
  92. // Find next line start.
  93. //
  94. if(q = wcschr(p,L'\r')) {
  95. p = q + 2;
  96. } else {
  97. p = wcschr(p,0);
  98. }
  99. }
  100. //
  101. // Find the end of the line that broke us out of the loop
  102. // and then the start of the next line (if any).
  103. //
  104. if(q = wcschr(p,L'\r')) {
  105. p = q + 2;
  106. } else {
  107. p = wcschr(p,0);
  108. }
  109. if(ScreenCount == MAX_HELP_SCREENS) {
  110. break;
  111. }
  112. }
  113. //
  114. // Sentinal value: point to the terminating nul byte.
  115. //
  116. HelpScreen[ScreenCount] = p;
  117. //
  118. // Display header text in blue on white.
  119. //
  120. SpvidClearScreenRegion(0,0,VideoVars.ScreenWidth,HEADER_HEIGHT,BackgroundAttribute);
  121. if(Flags & SPHELP_LICENSETEXT) {
  122. SpDisplayHeaderText(SP_HEAD_LICENSE,HeaderAttribute);
  123. } else {
  124. SpDisplayHeaderText(SP_HEAD_HELP,HeaderAttribute);
  125. }
  126. //
  127. // The first screen to display is screen 0.
  128. //
  129. CurrentScreen = 0;
  130. Done = FALSE;
  131. do {
  132. SpvidClearScreenRegion(
  133. 0,
  134. HEADER_HEIGHT,
  135. VideoVars.ScreenWidth,
  136. VideoVars.ScreenHeight-(HEADER_HEIGHT+STATUS_HEIGHT),
  137. BackgroundAttribute
  138. );
  139. //
  140. // Display the current screen.
  141. //
  142. for(y=HEADER_HEIGHT+1, p=HelpScreen[CurrentScreen]; *p && (p < HelpScreen[CurrentScreen+1]); y++) {
  143. Intense = FALSE;
  144. if(p[0] == L'%') {
  145. if(p[1] == L'I') {
  146. Intense = TRUE;
  147. p += 2;
  148. } else {
  149. if(p[1] == L'P') {
  150. p += 2; // don't display %P
  151. }
  152. }
  153. }
  154. q = wcschr(p,L'\r');
  155. if(q) {
  156. *q = 0;
  157. }
  158. SpvidDisplayString(
  159. p,
  160. (UCHAR)(Intense ? ClientIntenseAttribute : ClientAttribute),
  161. 3,
  162. y
  163. );
  164. if(q) {
  165. *q = '\r';
  166. p = q + 2;
  167. } else {
  168. p = wcschr(p,0);
  169. }
  170. }
  171. //
  172. // Construct a list of valid keypresses from the user, depending
  173. // on whether this is the first, last, etc. screen.
  174. //
  175. // If there are previous screens, BACKSPACE=Read Last Help is an option.
  176. // If there are additional screens, ENTER=Continue Reading Help is an option.
  177. // ESC=Cancel Help is always an option for help text.
  178. //
  179. // For licensing text, we allow pageup/pagedown when appropriate,
  180. // and on the last page we allow accept/reject.
  181. //
  182. kc = 0;
  183. if(Flags & SPHELP_LICENSETEXT) {
  184. ValidKeys[kc++] = KEY_F8;
  185. ValidKeys[kc++] = ASCI_ESC;
  186. if(CurrentScreen) {
  187. ValidKeys[kc++] = KEY_PAGEUP;
  188. }
  189. if(CurrentScreen < ScreenCount-1) {
  190. ValidKeys[kc++] = KEY_PAGEDOWN;
  191. }
  192. } else {
  193. ValidKeys[kc++] = ASCI_ESC;
  194. if(CurrentScreen) {
  195. ValidKeys[kc++] = ASCI_BS;
  196. ValidKeys[kc++] = KEY_PAGEUP;
  197. }
  198. if(CurrentScreen < ScreenCount-1) {
  199. ValidKeys[kc++] = ASCI_CR;
  200. ValidKeys[kc++] = KEY_PAGEDOWN;
  201. }
  202. }
  203. ValidKeys[kc] = 0;
  204. if(CurrentScreen && (CurrentScreen < ScreenCount-1)) {
  205. //
  206. // There are screens before and after this one.
  207. //
  208. if(Flags & SPHELP_LICENSETEXT) {
  209. SpDisplayStatusOptions(
  210. StatusAttribute,
  211. SP_STAT_X_EQUALS_ACCEPT_LICENSE,
  212. SP_STAT_X_EQUALS_REJECT_LICENSE,
  213. SP_STAT_PAGEDOWN_EQUALS_NEXT_LIC,
  214. SP_STAT_PAGEUP_EQUALS_PREV_LIC,
  215. 0
  216. );
  217. } else {
  218. SpDisplayStatusOptions(
  219. StatusAttribute,
  220. SP_STAT_ENTER_EQUALS_CONTINUE_HELP,
  221. SP_STAT_BACKSP_EQUALS_PREV_HELP,
  222. SP_STAT_ESC_EQUALS_CANCEL_HELP,
  223. 0
  224. );
  225. }
  226. } else {
  227. if(CurrentScreen) {
  228. //
  229. // This is the last page but not the only page.
  230. //
  231. if(Flags & SPHELP_LICENSETEXT) {
  232. SpDisplayStatusOptions(
  233. StatusAttribute,
  234. SP_STAT_X_EQUALS_ACCEPT_LICENSE,
  235. SP_STAT_X_EQUALS_REJECT_LICENSE,
  236. SP_STAT_PAGEUP_EQUALS_PREV_LIC,
  237. 0
  238. );
  239. } else {
  240. SpDisplayStatusOptions(
  241. StatusAttribute,
  242. SP_STAT_BACKSP_EQUALS_PREV_HELP,
  243. SP_STAT_ESC_EQUALS_CANCEL_HELP,
  244. 0
  245. );
  246. }
  247. } else {
  248. if(CurrentScreen < ScreenCount-1) {
  249. //
  250. // This is the first page but additional pages exist.
  251. //
  252. if(Flags & SPHELP_LICENSETEXT) {
  253. SpDisplayStatusOptions(
  254. StatusAttribute,
  255. SP_STAT_X_EQUALS_ACCEPT_LICENSE,
  256. SP_STAT_X_EQUALS_REJECT_LICENSE,
  257. SP_STAT_PAGEDOWN_EQUALS_NEXT_LIC,
  258. 0
  259. );
  260. } else {
  261. SpDisplayStatusOptions(
  262. StatusAttribute,
  263. SP_STAT_ENTER_EQUALS_CONTINUE_HELP,
  264. SP_STAT_ESC_EQUALS_CANCEL_HELP,
  265. 0
  266. );
  267. }
  268. } else {
  269. //
  270. // This is the only page.
  271. //
  272. if(Flags & SPHELP_LICENSETEXT) {
  273. SpDisplayStatusOptions(
  274. StatusAttribute,
  275. SP_STAT_X_EQUALS_ACCEPT_LICENSE,
  276. SP_STAT_X_EQUALS_REJECT_LICENSE,
  277. 0
  278. );
  279. } else {
  280. SpDisplayStatusOptions(
  281. StatusAttribute,
  282. SP_STAT_ESC_EQUALS_CANCEL_HELP,
  283. 0
  284. );
  285. }
  286. }
  287. }
  288. }
  289. switch(SpWaitValidKey(ValidKeys,NULL,NULL)) {
  290. case ASCI_ESC:
  291. if(Flags & SPHELP_LICENSETEXT) {
  292. SpDone(0,FALSE,TRUE);
  293. }
  294. // ELSE FALL THROUGH
  295. case KEY_F8:
  296. Done = TRUE;
  297. break;
  298. case KEY_PAGEUP:
  299. case ASCI_BS:
  300. ASSERT(CurrentScreen);
  301. CurrentScreen--;
  302. break;
  303. case KEY_PAGEDOWN:
  304. case ASCI_CR:
  305. ASSERT(CurrentScreen < ScreenCount-1);
  306. CurrentScreen++;
  307. break;
  308. }
  309. } while(!Done);
  310. //
  311. // Clean up.
  312. //
  313. if(!FileText) {
  314. SpMemFree(HelpText);
  315. }
  316. s0:
  317. CLEAR_ENTIRE_SCREEN();
  318. SpDisplayHeaderText(
  319. SpGetHeaderTextId(),
  320. DEFAULT_ATTRIBUTE
  321. );
  322. }