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.

1394 lines
32 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. spdsputl.c
  5. Abstract:
  6. Display utility routines for text setup.
  7. Author:
  8. Ted Miller (tedm) 12-Aug-1993
  9. Revision History:
  10. --*/
  11. #include "spprecmp.h"
  12. #pragma hdrstop
  13. extern BOOLEAN ForceConsole;
  14. BOOLEAN DisableCmdConsStatusText = TRUE;
  15. //
  16. // This value will hold the localized mnemonic keys,
  17. // in order indicated by the MNEMONIC_KEYS enum.
  18. //
  19. PWCHAR MnemonicValues;
  20. //
  21. // As messages are built on on-screen, this value remembers where
  22. // the next message in the screen should be placed.
  23. //
  24. ULONG NextMessageTopLine = 0;
  25. ULONG
  26. SpDisplayText(
  27. IN PWCHAR Message,
  28. IN ULONG MsgLen,
  29. IN BOOLEAN CenterHorizontally,
  30. IN BOOLEAN CenterVertically,
  31. IN UCHAR Attribute,
  32. IN ULONG X,
  33. IN ULONG Y
  34. )
  35. /*++
  36. Routine Description:
  37. Worker routine for vSpDisplayFormattedMessage().
  38. Arguments:
  39. Message - supplies message text.
  40. MsgLen - supplies the number of unicode characters in the message,
  41. including the terminating nul.
  42. CenterHorizontally - if TRUE, each line will be centered horizontally
  43. on the screen.
  44. Attribute - supplies attributes for text.
  45. X - supplies the x coordinate (0-based) for the left margin of the text.
  46. If the text spans multiple line, all will start at this coordinate.
  47. Y - supplies the y coordinate (0-based) for the first line of
  48. the text.
  49. arglist - supply arguments gfor insertion into the given message.
  50. Return Value:
  51. Number of lines the text took up on the screen, unless CenterVertically
  52. is TRUE, in which case n is the line number of the first line below where
  53. the text was displayed.
  54. --*/
  55. {
  56. PWCHAR p,q;
  57. WCHAR c;
  58. ULONG y;
  59. int i;
  60. //
  61. // Must have at least one char + terminating nul in there.
  62. //
  63. if(MsgLen <= 1) {
  64. return(CenterVertically ? (VideoVars.ScreenHeight/2) : 0);
  65. }
  66. //
  67. // MsgLen includes terminating nul.
  68. //
  69. p = Message + MsgLen - 1;
  70. //
  71. // Find last non-space char in message.
  72. //
  73. while((p > Message) && SpIsSpace(*(p-1))) {
  74. p--;
  75. }
  76. //
  77. // Find end of the last significant line and terminate the message
  78. // after it.
  79. //
  80. if(q = wcschr(p,L'\n')) {
  81. *(++q) = 0;
  82. }
  83. for(i = (CenterVertically ? 0 : 1); i<2; i++) {
  84. for(y=Y, p=Message; q = SpFindCharFromListInString(p,L"\n\r"); y++) {
  85. c = *q;
  86. *q = 0;
  87. if(i) {
  88. BOOLEAN Intense = (BOOLEAN)((p[0] == L'%') && (p[1] == L'I'));
  89. SpvidDisplayString(
  90. Intense ? p+2 : p,
  91. (UCHAR)(Attribute | (Intense ? ATT_FG_INTENSE : 0)),
  92. CenterHorizontally
  93. ? (VideoVars.ScreenWidth-(SplangGetColumnCount(p)-(Intense ? 2 : 0)))/2 : X,
  94. y
  95. );
  96. }
  97. *q = c;
  98. //
  99. // If cr/lf terminated the line, make sure we skip both chars.
  100. //
  101. if((c == L'\r') && (*(q+1) == L'\n')) {
  102. q++;
  103. }
  104. p = ++q;
  105. }
  106. //
  107. // Write the final line (if there is one).
  108. //
  109. if(i) {
  110. if(wcslen(p)) {
  111. SpvidDisplayString(
  112. p,
  113. Attribute,
  114. CenterHorizontally ? (VideoVars.ScreenWidth-SplangGetColumnCount(p))/2 : X,
  115. y++
  116. );
  117. }
  118. }
  119. if(i == 0) {
  120. //
  121. // Center the text on the screen (not within the client area).
  122. //
  123. Y = (VideoVars.ScreenHeight - (y-Y)) / 2;
  124. }
  125. }
  126. return(CenterVertically ? y : (y-Y));
  127. }
  128. ULONG
  129. vSpDisplayFormattedMessage(
  130. IN ULONG MessageId,
  131. IN BOOLEAN CenterHorizontally,
  132. IN BOOLEAN CenterVertically,
  133. IN UCHAR Attribute,
  134. IN ULONG X,
  135. IN ULONG Y,
  136. IN va_list arglist
  137. )
  138. /*++
  139. Routine Description:
  140. A formatted multiline message may be displayed with this routine.
  141. The format string is fetched from setup's text resources; arguments
  142. are substituted into the format string according to FormatMessage
  143. semantics.
  144. The screen is NOT cleared by this routine.
  145. If a line starts with %I (ie, the first 2 characters at the
  146. start of the message, or after a newline), it will be displayed
  147. with the intensity attribute on.
  148. Arguments:
  149. MessageId - supplies id of message resource containing the text,
  150. which is treated as a format string for FormatMessage.
  151. CenterHorizontally - if TRUE, each line will be centered horizontally
  152. on the screen.
  153. Attribute - supplies attributes for text.
  154. X - supplies the x coordinate (0-based) for the left margin of the text.
  155. If the text spans multiple line, all will start at this coordinate.
  156. Y - supplies the y coordinate (0-based) for the first line of
  157. the text.
  158. arglist - supply arguments gfor insertion into the given message.
  159. Return Value:
  160. Number of lines the text took up on the screen, unless CenterVertically
  161. is TRUE, in which case n is the line number of the first line below where
  162. the text was displayed.
  163. --*/
  164. {
  165. ULONG BytesInMsg;
  166. ULONG n;
  167. vSpFormatMessage(TemporaryBuffer,sizeof(TemporaryBuffer),MessageId,&BytesInMsg,&arglist);
  168. //
  169. // Must have at least one char + terminating nul in there.
  170. //
  171. if(BytesInMsg <= sizeof(WCHAR)) {
  172. return(CenterVertically ? (VideoVars.ScreenHeight/2) : 0);
  173. }
  174. n = SpDisplayText(
  175. TemporaryBuffer,
  176. BytesInMsg / sizeof(WCHAR),
  177. CenterHorizontally,
  178. CenterVertically,
  179. Attribute,
  180. X,
  181. Y
  182. );
  183. return(n);
  184. }
  185. ULONG
  186. SpDisplayFormattedMessage(
  187. IN ULONG MessageId,
  188. IN BOOLEAN CenterHorizontally,
  189. IN BOOLEAN CenterVertically,
  190. IN UCHAR Attribute,
  191. IN ULONG X,
  192. IN ULONG Y,
  193. ...
  194. )
  195. /*++
  196. Routine Description:
  197. Display a message on the screen. Does not clear the screen first.
  198. Arguments:
  199. MessageId - supplies id of message resource containing the text,
  200. which is treated as a format string for FormatMessage.
  201. CenterHorizontally - if TRUE, each line will be centered horizontally
  202. on the screen.
  203. Attribute - supplies attributes for text.
  204. X - supplies the x coordinate (0-based) for the left margin of the text.
  205. If the text spans multiple line, all will start at this coordinate.
  206. Y - supplies the y coordinate (0-based) for the first line of
  207. the text.
  208. ... - supply arguments gfor insertion into the given message.
  209. Return Value:
  210. Number of lines the text took up on the screen.
  211. --*/
  212. {
  213. va_list arglist;
  214. ULONG n;
  215. va_start(arglist,Y);
  216. n = vSpDisplayFormattedMessage(
  217. MessageId,
  218. CenterHorizontally,
  219. CenterVertically,
  220. Attribute,
  221. X,
  222. Y,
  223. arglist
  224. );
  225. va_end(arglist);
  226. return(n);
  227. }
  228. VOID
  229. SpDisplayHeaderText(
  230. IN ULONG MessageId,
  231. IN UCHAR Attribute
  232. )
  233. /*++
  234. Routine Description:
  235. Display text in the header area of the screen. The header area will be
  236. cleared to the given attribute before displaying the text. We will
  237. draw a double-underline under the text also.
  238. Arguments:
  239. MessageId - supplies id of message resource containing the text.
  240. Attribute - supplies attributes for text.
  241. Return Value:
  242. none.
  243. --*/
  244. {
  245. ULONG Length,i;
  246. WCHAR Underline;
  247. WCHAR *p;
  248. SpvidClearScreenRegion(0,0,VideoVars.ScreenWidth,HEADER_HEIGHT,(UCHAR)(Attribute >> 4));
  249. //
  250. // Get message and display at (1,1)
  251. //
  252. vSpFormatMessage(TemporaryBuffer,sizeof(TemporaryBuffer),MessageId,NULL,NULL);
  253. p = (WCHAR *)TemporaryBuffer;
  254. SpvidDisplayString(p,Attribute,1,1);
  255. //
  256. // Build a row of underline characters.
  257. //
  258. Length = SplangGetColumnCount(p) + 2;
  259. Underline = SplangGetLineDrawChar(LineCharDoubleHorizontal);
  260. for(i=0; i<Length; i++) {
  261. p[i] = Underline;
  262. }
  263. p[Length] = 0;
  264. SpvidDisplayString(p,Attribute,0,2);
  265. }
  266. #define MAX_STATUS_ACTION_LABEL 50
  267. WCHAR StatusActionLabel[MAX_STATUS_ACTION_LABEL];
  268. ULONG StatusActionLeftX;
  269. ULONG StatusActionObjectX;
  270. BOOLEAN StatusActionLabelDisplayed = FALSE;
  271. VOID
  272. SpDisplayStatusActionLabel(
  273. IN ULONG ActionMessageId, OPTIONAL
  274. IN ULONG FieldWidth
  275. )
  276. {
  277. ULONG l;
  278. if(ActionMessageId) {
  279. //
  280. // Prefix the text with a separating vertical bar.
  281. //
  282. StatusActionLabel[0] = SplangGetLineDrawChar(LineCharSingleVertical);
  283. //
  284. // Fetch the action verb (something like "Copying:")
  285. //
  286. SpFormatMessage(
  287. StatusActionLabel+1,
  288. sizeof(StatusActionLabel)-sizeof(WCHAR),
  289. ActionMessageId
  290. );
  291. //
  292. // Now calculate the position on the status line
  293. // for the action label. We want to leave 1 space
  294. // between the colon and the object, and a space between
  295. // the object and the rightmost column on the screen.
  296. //
  297. l = SplangGetColumnCount(StatusActionLabel);
  298. StatusActionObjectX = VideoVars.ScreenWidth - FieldWidth - 1;
  299. StatusActionLeftX = StatusActionObjectX - l - 1;
  300. //
  301. // Display the label and clear out the rest of the line.
  302. //
  303. SpvidDisplayString(
  304. StatusActionLabel,
  305. DEFAULT_STATUS_ATTRIBUTE,
  306. StatusActionLeftX,
  307. VideoVars.ScreenHeight-STATUS_HEIGHT
  308. );
  309. SpvidClearScreenRegion(
  310. StatusActionObjectX-1,
  311. VideoVars.ScreenHeight-STATUS_HEIGHT,
  312. VideoVars.ScreenWidth-StatusActionObjectX+1,
  313. STATUS_HEIGHT,
  314. DEFAULT_STATUS_BACKGROUND
  315. );
  316. StatusActionLabelDisplayed = TRUE;
  317. } else {
  318. //
  319. // Caller wants to clear out the previous area.
  320. //
  321. StatusActionLabel[0] = 0;
  322. SpvidClearScreenRegion(
  323. StatusActionLeftX,
  324. VideoVars.ScreenHeight-STATUS_HEIGHT,
  325. VideoVars.ScreenWidth-StatusActionLeftX,
  326. STATUS_HEIGHT,
  327. DEFAULT_STATUS_BACKGROUND
  328. );
  329. StatusActionLabelDisplayed = FALSE;
  330. }
  331. }
  332. VOID
  333. SpDisplayStatusActionObject(
  334. IN PWSTR ObjectText
  335. )
  336. {
  337. //
  338. // clear the area and draw the text.
  339. //
  340. SpvidClearScreenRegion(
  341. StatusActionObjectX,
  342. VideoVars.ScreenHeight-STATUS_HEIGHT,
  343. VideoVars.ScreenWidth-StatusActionObjectX,
  344. STATUS_HEIGHT,
  345. DEFAULT_STATUS_BACKGROUND
  346. );
  347. SpvidDisplayString(
  348. ObjectText,
  349. DEFAULT_STATUS_ATTRIBUTE,
  350. StatusActionObjectX,
  351. VideoVars.ScreenHeight-STATUS_HEIGHT
  352. );
  353. }
  354. VOID
  355. SpCmdConsEnableStatusText(
  356. IN BOOLEAN EnableStatusText
  357. )
  358. {
  359. DisableCmdConsStatusText = !EnableStatusText;
  360. }
  361. VOID
  362. SpDisplayStatusText(
  363. IN ULONG MessageId,
  364. IN UCHAR Attribute,
  365. ...
  366. )
  367. {
  368. va_list arglist;
  369. if (ForceConsole && DisableCmdConsStatusText) {
  370. return;
  371. }
  372. SpvidClearScreenRegion(
  373. 0,
  374. VideoVars.ScreenHeight-STATUS_HEIGHT,
  375. VideoVars.ScreenWidth,
  376. STATUS_HEIGHT,
  377. (UCHAR)(Attribute >> 4) // background part of attribute
  378. );
  379. va_start(arglist,Attribute);
  380. vSpDisplayFormattedMessage(
  381. MessageId,
  382. FALSE,FALSE, // no centering
  383. Attribute,
  384. 2,
  385. VideoVars.ScreenHeight-STATUS_HEIGHT,
  386. arglist
  387. );
  388. va_end(arglist);
  389. }
  390. VOID
  391. SpDisplayStatusOptions(
  392. IN UCHAR Attribute,
  393. ...
  394. )
  395. {
  396. WCHAR StatusText[79];
  397. WCHAR Option[79];
  398. va_list arglist;
  399. ULONG MessageId;
  400. StatusText[0] = 0;
  401. va_start(arglist,Attribute);
  402. while(MessageId = va_arg(arglist,ULONG)) {
  403. //
  404. // Fetch the message text for this option.
  405. //
  406. Option[0] = 0;
  407. SpFormatMessage(Option,sizeof(Option),MessageId);
  408. //
  409. // If the option fits, place it in the status text line we're
  410. // building up.
  411. //
  412. if((SplangGetColumnCount(StatusText) + SplangGetColumnCount(Option) + 2)
  413. < (sizeof(StatusText)/sizeof(StatusText[0]))) {
  414. wcscat(StatusText,L" ");
  415. wcscat(StatusText,Option);
  416. }
  417. }
  418. va_end(arglist);
  419. //
  420. // Display the text.
  421. //
  422. SpvidClearScreenRegion(
  423. 0,
  424. VideoVars.ScreenHeight-STATUS_HEIGHT,
  425. VideoVars.ScreenWidth,
  426. STATUS_HEIGHT,
  427. (UCHAR)(Attribute >> (UCHAR)4) // background part of attribute
  428. );
  429. SpvidDisplayString(StatusText,Attribute,0,VideoVars.ScreenHeight-STATUS_HEIGHT);
  430. }
  431. VOID
  432. SpStartScreen(
  433. IN ULONG MessageId,
  434. IN ULONG LeftMargin,
  435. IN ULONG TopLine,
  436. IN BOOLEAN CenterHorizontally,
  437. IN BOOLEAN CenterVertically,
  438. IN UCHAR Attribute,
  439. ...
  440. )
  441. /*++
  442. Routine Description:
  443. Display a formatted message on the screen, treating it as the first
  444. message in what might be a multi-message screen.
  445. The client area of the screen will be cleared before displaying the message.
  446. Arguments:
  447. MessageId - supplies id of message resource containing the text.
  448. LeftMargin - supplies the 0-based x-coordinate for the each line of the text.
  449. TopLine - supplies the 0-based y-coordinate for the topmost line of the text.
  450. CenterHorizontally - if TRUE, each line in the message will be printed
  451. centered horizontally. In this case, LeftMargin is ignored.
  452. CenterVertically - if TRUE, the message will approximately centered vertically
  453. within the client area of the screen. In this case, TopLine is ignored.
  454. Attribute - supplies attribute for text.
  455. ... - supply arguments for insertion/substitution into the message text.
  456. Return Value:
  457. none.
  458. --*/
  459. {
  460. va_list arglist;
  461. ULONG n;
  462. CLEAR_CLIENT_SCREEN();
  463. va_start(arglist,Attribute);
  464. n = vSpDisplayFormattedMessage(
  465. MessageId,
  466. CenterHorizontally,
  467. CenterVertically,
  468. Attribute,
  469. LeftMargin,
  470. TopLine,
  471. arglist
  472. );
  473. va_end(arglist);
  474. //
  475. // Remember where the message ended.
  476. //
  477. NextMessageTopLine = CenterVertically ? n : TopLine+n;
  478. }
  479. VOID
  480. SpContinueScreen(
  481. IN ULONG MessageId,
  482. IN ULONG LeftMargin,
  483. IN ULONG SpacingLines,
  484. IN BOOLEAN CenterHorizontally,
  485. IN UCHAR Attribute,
  486. ...
  487. )
  488. /*++
  489. Routine Description:
  490. Display a formatted message on the screen, treating it as the continuation
  491. of a multi-message screen previously begun by calling SpStartScreen().
  492. The message will be placed under the previously displayed message.
  493. Arguments:
  494. MessageId - supplies id of message resource containing the text.
  495. LeftMargin - supplies the 0-based x-coordinate for the each line of the text.
  496. SpacingLines - supplies the number of lines to leave between the end of the
  497. previous message and the start of this message.
  498. CenterHorizontally - if TRUE, each line in the message will be printed
  499. centered horizontally. In this case, LeftMargin is ignored.
  500. Attribute - supplies attribute for text.
  501. ... - supply arguments for insertion/substitution into the message text.
  502. Return Value:
  503. none.
  504. --*/
  505. {
  506. va_list arglist;
  507. ULONG n;
  508. va_start(arglist,Attribute);
  509. n = vSpDisplayFormattedMessage(
  510. MessageId,
  511. CenterHorizontally,
  512. FALSE,
  513. Attribute,
  514. LeftMargin,
  515. NextMessageTopLine + SpacingLines,
  516. arglist
  517. );
  518. va_end(arglist);
  519. //
  520. // Remember where the message ended.
  521. //
  522. NextMessageTopLine += n + SpacingLines;
  523. }
  524. VOID
  525. vSpDisplayRawMessage(
  526. IN ULONG MessageId,
  527. IN ULONG SpacingLines,
  528. IN va_list arglist
  529. )
  530. /*++
  531. Routine Description:
  532. This routine outputs a multiline message to the screen, dumping it
  533. terminal style, to the console.
  534. The format string is fetched from setup's text resources; arguments are
  535. substituted into the format string according to FormatMessage semantics;
  536. and then the resulting unicode string is translated into an ANSI string
  537. suitable for the HAL printing routine.
  538. The screen is NOT cleared by this routine.
  539. Arguments:
  540. MessageId - supplies id of message resource containing the text,
  541. which is treated as a format string for FormatMessage.
  542. SpacingLines - supplies the number of lines to skip down before starting this
  543. message.
  544. arglist - supply arguments for insertion into the given message.
  545. Return Value:
  546. none.
  547. --*/
  548. {
  549. ULONG BytesInMsg, BufferLeft, i;
  550. PWCHAR p, q;
  551. WCHAR c;
  552. PUCHAR HalPrintString;
  553. vSpFormatMessage(
  554. TemporaryBuffer,
  555. sizeof(TemporaryBuffer),
  556. MessageId,
  557. &BytesInMsg,
  558. &arglist
  559. );
  560. //
  561. // Must have at least one char + terminating nul in there.
  562. //
  563. if(BytesInMsg <= sizeof(WCHAR)) {
  564. return;
  565. } else {
  566. for(i=0; i<SpacingLines; i++) {
  567. InbvDisplayString("\r\n");
  568. }
  569. }
  570. //
  571. // BytesInMsg includes terminating nul.
  572. //
  573. p = TemporaryBuffer + (BytesInMsg / sizeof(WCHAR)) - 1;
  574. //
  575. // Find last non-space char in message.
  576. //
  577. while((p > TemporaryBuffer) && SpIsSpace(*(p-1))) {
  578. p--;
  579. }
  580. //
  581. // Find end of the last significant line and terminate the message
  582. // after it.
  583. //
  584. if(q = wcschr(p, L'\n')) {
  585. *(++q) = 0;
  586. q++;
  587. } else {
  588. q = TemporaryBuffer + (BytesInMsg / sizeof(WCHAR));
  589. }
  590. //
  591. // Grab rest of buffer to put ANSI translation into
  592. //
  593. HalPrintString = (PUCHAR)q;
  594. BufferLeft = (ULONG)(sizeof(TemporaryBuffer) - ((PUCHAR)q - (PUCHAR)TemporaryBuffer));
  595. //
  596. // Print out message, line-by-line
  597. //
  598. for(p=TemporaryBuffer; q = SpFindCharFromListInString(p, L"\n\r"); ) {
  599. c = *q;
  600. *q = 0;
  601. RtlUnicodeToOemN(
  602. HalPrintString,
  603. BufferLeft,
  604. &BytesInMsg,
  605. p,
  606. (ULONG)((PUCHAR)q - (PUCHAR)p + sizeof(WCHAR))
  607. );
  608. if(BytesInMsg) {
  609. InbvDisplayString(HalPrintString);
  610. }
  611. InbvDisplayString("\r\n");
  612. *q = c;
  613. //
  614. // If cr/lf terminated the line, make sure we skip both chars.
  615. //
  616. if((c == L'\r') && (*(q+1) == L'\n')) {
  617. q++;
  618. }
  619. p = ++q;
  620. }
  621. //
  622. // Write the final line (if there is one).
  623. //
  624. if(wcslen(p)) {
  625. RtlUnicodeToOemN(
  626. HalPrintString,
  627. BufferLeft,
  628. &BytesInMsg,
  629. p,
  630. (wcslen(p) + 1) * sizeof(WCHAR)
  631. );
  632. if(BytesInMsg) {
  633. InbvDisplayString(HalPrintString);
  634. }
  635. InbvDisplayString("\r\n");
  636. }
  637. }
  638. VOID
  639. SpDisplayRawMessage(
  640. IN ULONG MessageId,
  641. IN ULONG SpacingLines,
  642. ...
  643. )
  644. /*++
  645. Routine Description:
  646. Output a message to the screen using the HAL-supplied console output routine.
  647. The message is merely dumped, line-by-line, to the screen, terminal-style.
  648. Arguments:
  649. MessageId - supplies id of message resource containing the text,
  650. which is treated as a format string for FormatMessage.
  651. SpacingLines - supplies the number of lines to skip down before starting this
  652. message.
  653. ... - supply arguments for insertion into the given message.
  654. Return Value:
  655. none.
  656. --*/
  657. {
  658. va_list arglist;
  659. va_start(arglist, SpacingLines);
  660. vSpDisplayRawMessage(
  661. MessageId,
  662. SpacingLines,
  663. arglist
  664. );
  665. va_end(arglist);
  666. }
  667. VOID
  668. SpBugCheck(
  669. IN ULONG BugCode,
  670. IN ULONG Param1,
  671. IN ULONG Param2,
  672. IN ULONG Param3
  673. )
  674. /*++
  675. Routine Description:
  676. Display a message on the screen, informing the user that a fatal
  677. Setup error has occurred, and that they should reboot the machine.
  678. Arguments:
  679. BugCode - Bugcheck code number as defined in spmisc.h and documented in
  680. ntos\nls\bugcodes.txt
  681. Param1 - 1st informative parameter
  682. Param2 - 2nd informative parameter
  683. Param3 - 3rd informative parameter
  684. Return Value:
  685. DOES NOT RETURN
  686. --*/
  687. {
  688. if(VideoInitialized) {
  689. //
  690. // If we are in upgrade graphics mode then
  691. // switch to textmode
  692. //
  693. SpvidSwitchToTextmode();
  694. SpStartScreen(
  695. SP_SCRN_FATAL_SETUP_ERROR,
  696. 3,
  697. HEADER_HEIGHT+1,
  698. FALSE,
  699. FALSE,
  700. DEFAULT_ATTRIBUTE,
  701. BugCode,
  702. Param1,
  703. Param2,
  704. Param3
  705. );
  706. if(KbdLayoutInitialized) {
  707. SpContinueScreen(
  708. SP_SCRN_F3_TO_REBOOT,
  709. 3,
  710. 1,
  711. FALSE,
  712. DEFAULT_ATTRIBUTE
  713. );
  714. SpDisplayStatusText(SP_STAT_F3_EQUALS_EXIT, DEFAULT_STATUS_ATTRIBUTE);
  715. SpInputDrain();
  716. while(SpInputGetKeypress() != KEY_F3);
  717. SpDone(0,FALSE, TRUE);
  718. } else {
  719. //
  720. // we haven't loaded the layout dll yet, so we can't prompt for a keypress to reboot
  721. //
  722. SpContinueScreen(
  723. SP_SCRN_POWER_DOWN,
  724. 3,
  725. 1,
  726. FALSE,
  727. DEFAULT_ATTRIBUTE
  728. );
  729. SpDisplayStatusText(SP_STAT_KBD_HARD_REBOOT, DEFAULT_STATUS_ATTRIBUTE);
  730. while(TRUE); // Loop forever
  731. }
  732. } else {
  733. SpDisplayRawMessage(
  734. SP_SCRN_FATAL_SETUP_ERROR,
  735. 2,
  736. BugCode,
  737. Param1,
  738. Param2,
  739. Param3
  740. );
  741. SpDisplayRawMessage(SP_SCRN_POWER_DOWN, 1);
  742. while(TRUE); // loop forever
  743. }
  744. }
  745. VOID
  746. SpDrawFrame(
  747. IN ULONG LeftX,
  748. IN ULONG Width,
  749. IN ULONG TopY,
  750. IN ULONG Height,
  751. IN UCHAR Attribute,
  752. IN BOOLEAN DoubleLines
  753. )
  754. {
  755. PWSTR Buffer;
  756. ULONG u;
  757. WCHAR w;
  758. Buffer = SpMemAlloc((Width+1) * sizeof(WCHAR));
  759. ASSERT(Buffer);
  760. if(!Buffer) {
  761. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to allocate memory for buffer to draw frame\n"));
  762. return;
  763. }
  764. Buffer[Width] = 0;
  765. //
  766. // Top.
  767. //
  768. w = SplangGetLineDrawChar(DoubleLines ? LineCharDoubleHorizontal : LineCharSingleHorizontal);
  769. for(u=1; u<Width-1; u++) {
  770. Buffer[u] = w;
  771. }
  772. Buffer[0] = SplangGetLineDrawChar(DoubleLines ? LineCharDoubleUpperLeft : LineCharSingleUpperLeft);
  773. Buffer[Width-1] = SplangGetLineDrawChar(DoubleLines ? LineCharDoubleUpperRight : LineCharSingleUpperRight);
  774. SpvidDisplayString(Buffer,Attribute,LeftX,TopY);
  775. //
  776. // Bottom.
  777. //
  778. Buffer[0] = SplangGetLineDrawChar(DoubleLines ? LineCharDoubleLowerLeft : LineCharSingleLowerLeft);
  779. Buffer[Width-1] = SplangGetLineDrawChar(DoubleLines ? LineCharDoubleLowerRight : LineCharSingleLowerRight);
  780. SpvidDisplayString(Buffer,Attribute,LeftX,TopY+Height-1);
  781. //
  782. // Interior lines.
  783. //
  784. for(u=1; u<Width-1; u++) {
  785. Buffer[u] = L' ';
  786. }
  787. Buffer[0] = SplangGetLineDrawChar(DoubleLines ? LineCharDoubleVertical : LineCharSingleVertical);
  788. Buffer[Width-1] = SplangGetLineDrawChar(DoubleLines ? LineCharDoubleVertical : LineCharSingleVertical);
  789. for(u=1; u<Height-1; u++) {
  790. SpvidDisplayString(Buffer,Attribute,LeftX,TopY+u);
  791. }
  792. SpMemFree(Buffer);
  793. }
  794. ULONG
  795. SpWaitValidKey(
  796. IN PULONG ValidKeys1,
  797. IN PULONG ValidKeys2, OPTIONAL
  798. IN PULONG MnemonicKeys OPTIONAL
  799. )
  800. /*++
  801. Routine Description:
  802. Wait for a key to be pressed that appears in a list of valid keys.
  803. Arguments:
  804. ValidKeys1 - supplies list of valid keystrokes. The list must be
  805. terminated with a 0 entry.
  806. ValidKeys2 - if specified, supplies an additional list of valid keystrokes.
  807. MnemonicKeys - if specified, specifies a list of indices into the
  808. SP_MNEMONICS message string (see the MNEMONIC_KEYS enum).
  809. If the user's keystroke is not listed in ValidKeys, it will be
  810. uppercased and compared against each character indexed by a value
  811. in MnemonicKeys. If a match is found, the returned value is the
  812. index (ie,MNEMONIC_KEYS enum value), and the high bit will be set.
  813. Return Value:
  814. The key that was pressed (see above).
  815. --*/
  816. {
  817. ULONG c;
  818. ULONG i;
  819. SpInputDrain();
  820. while(1) {
  821. c = SpInputGetKeypress();
  822. //
  823. // Check for normal key.
  824. //
  825. for(i=0; ValidKeys1[i]; i++) {
  826. if(c == ValidKeys1[i]) {
  827. return(c);
  828. }
  829. }
  830. //
  831. // Check secondary list.
  832. //
  833. if(ValidKeys2) {
  834. for(i=0; ValidKeys2[i]; i++) {
  835. if(c == ValidKeys2[i]) {
  836. return(c);
  837. }
  838. }
  839. }
  840. //
  841. // Check for mnemonic keys.
  842. //
  843. if(MnemonicKeys && !(c & KEY_NON_CHARACTER)) {
  844. c = (ULONG)RtlUpcaseUnicodeChar((WCHAR)c);
  845. for(i=0; MnemonicKeys[i]; i++) {
  846. if((WCHAR)c == MnemonicValues[MnemonicKeys[i]]) {
  847. return((ULONG)MnemonicKeys[i] | KEY_MNEMONIC);
  848. }
  849. }
  850. }
  851. }
  852. }
  853. //
  854. // Attributes for text edit fields.
  855. //
  856. #define EDIT_FIELD_BACKGROUND ATT_WHITE
  857. #define EDIT_FIELD_TEXT (ATT_FG_BLACK | ATT_BG_WHITE)
  858. BOOLEAN
  859. SpGetInput(
  860. IN PKEYPRESS_CALLBACK ValidateKey,
  861. IN ULONG X,
  862. IN ULONG Y,
  863. IN ULONG MaxLength,
  864. IN OUT PWCHAR Buffer,
  865. IN BOOLEAN ValidateEscape
  866. )
  867. /*++
  868. Routine Description:
  869. Allow the user to enter text in an edit field of a specified size.
  870. Some special keys are interpreted and handled locally; others are passed
  871. to a caller-supplied routine for validation.
  872. Keys handled locally include ENTER, BACKSPACE, and ESCAPE (subject to ValidateEscape):
  873. these keys will never be passed to the callback routine.
  874. Other keys are passed to the callback function. This specifically includes
  875. function keys, which may have special meaning to the caller, and upon which
  876. the caller must act before returning. (IE, if the user presses F3, the caller
  877. might put up an exit confirmation dialog.
  878. Arguments:
  879. ValidateKey - supplies address of a function to be called for each keypress.
  880. The function takes the keypress as an argument, and returns one of the
  881. following values:
  882. ValidationAccept - acecpt the keystroke into the string being input.
  883. If the keystroke is not a unicode character (ie, is a function key)
  884. then this value must not be returned.
  885. ValidationIgnore - do not accept the keystroke into the string.
  886. ValidationReject - same as ValidationIgnore, except that there may be some
  887. addition action, such as beeping the speaker.
  888. ValidationTerminate - end input ad return from SpGetInput immediately
  889. with a value of FALSE.
  890. ValidationRepaint - same as ValidationIgnore, except that the input field is
  891. repainted.
  892. X,Y - specify the coordinate for the leftmost character in the edit field.
  893. MaxLength - supplies the maximum number of characters in the edit field.
  894. Buffer - On input supplies a default string for the edit field. On output,
  895. receives the string entered by the user. This buffer should be large
  896. enough to contain MaxLength +1 unicode characters (ie, should be able to
  897. hold a nul-terminated string of length MaxLength).
  898. ValidateEscape - if TRUE, treat escape like a normal character, passing it to
  899. the validation routine. If FALSE, escape clears the input field.
  900. Return Value:
  901. TRUE if the user's input was terminated normally (ie, by he user pressed ENTER).
  902. FALSE if terminated by ValidateKey returning ValidationTerminate.
  903. --*/
  904. {
  905. ULONG c;
  906. ValidationValue vval;
  907. ULONG CurrentCharCount;
  908. WCHAR str[3];
  909. WCHAR CURSOR = SplangGetCursorChar();
  910. //
  911. // Make sure edit field is in a reasonable place on the screen.
  912. //
  913. ASSERT(X + MaxLength + 1 < VideoVars.ScreenWidth);
  914. ASSERT(Y < VideoVars.ScreenHeight - STATUS_HEIGHT);
  915. //
  916. // Prime the pump.
  917. //
  918. vval = ValidateRepaint;
  919. CurrentCharCount = wcslen(Buffer);
  920. str[1] = 0;
  921. str[2] = 0;
  922. ASSERT(CurrentCharCount <= MaxLength);
  923. while(1) {
  924. //
  925. // Perform action based on previous state.
  926. //
  927. switch(vval) {
  928. case ValidateAccept:
  929. //
  930. // Insert the previous key into the input.
  931. //
  932. ASSERT(Buffer[CurrentCharCount] == 0);
  933. ASSERT(CurrentCharCount < MaxLength);
  934. ASSERT(!(c & KEY_NON_CHARACTER));
  935. Buffer[CurrentCharCount++] = (USHORT)c;
  936. Buffer[CurrentCharCount ] = 0;
  937. break;
  938. case ValidateRepaint:
  939. //
  940. // Repaint the edit field in its current state.
  941. // The edit field is one character too large, to accomodate
  942. // the cursor after the last legal character in the edit field.
  943. //
  944. SpvidClearScreenRegion(X,Y,MaxLength+1,1,EDIT_FIELD_BACKGROUND);
  945. SpvidDisplayString(Buffer,EDIT_FIELD_TEXT,X,Y);
  946. //
  947. // Draw the cursor.
  948. //
  949. str[0] = CURSOR;
  950. SpvidDisplayString(str,EDIT_FIELD_TEXT,X+CurrentCharCount,Y);
  951. break;
  952. case ValidateIgnore:
  953. case ValidateReject:
  954. //
  955. // Ignore the previous keystroke.
  956. //
  957. break;
  958. case ValidateTerminate:
  959. //
  960. // Callback wants us to terminate.
  961. //
  962. return(FALSE);
  963. }
  964. //
  965. // Get a keystroke.
  966. //
  967. c = SpInputGetKeypress();
  968. //
  969. // Do something with the key.
  970. //
  971. switch(c) {
  972. case ASCI_CR:
  973. //
  974. // Input is terminated. We're done.
  975. //
  976. return(TRUE);
  977. case ASCI_BS:
  978. //
  979. // Backspace character. If we're not at the beginning
  980. // of the edit field, erase the previous character, replacing it
  981. // with the cursor character.
  982. //
  983. if(CurrentCharCount) {
  984. Buffer[--CurrentCharCount] = 0;
  985. str[0] = CURSOR;
  986. str[1] = L' ';
  987. SpvidDisplayString(str,EDIT_FIELD_TEXT,X+CurrentCharCount,Y);
  988. str[1] = 0;
  989. }
  990. vval = ValidateIgnore;
  991. break;
  992. case ASCI_ESC:
  993. //
  994. // Escape character. Clear the edit field.
  995. //
  996. if(!ValidateEscape) {
  997. RtlZeroMemory(Buffer,(MaxLength+1) * sizeof(WCHAR));
  998. CurrentCharCount = 0;
  999. vval = ValidateRepaint;
  1000. break;
  1001. }
  1002. //
  1003. // Otherwise, we want to validate escape like a normal character.
  1004. // So just fall through.
  1005. //
  1006. default:
  1007. //
  1008. // Some other character. Pass it to the callback function
  1009. // for validation.
  1010. //
  1011. vval = ValidateKey(c);
  1012. if(vval == ValidateAccept) {
  1013. //
  1014. // We want to accept the keystroke. If there is not enough
  1015. // room in the buffer, convert acceptance to ignore.
  1016. // Otherwise (ie, there is enough room), put the character
  1017. // up on the screen and advance the cursor.
  1018. //
  1019. if(CurrentCharCount < MaxLength) {
  1020. ASSERT(!(c & KEY_NON_CHARACTER));
  1021. str[0] = (WCHAR)c;
  1022. SpvidDisplayString(str,EDIT_FIELD_TEXT,X+CurrentCharCount,Y);
  1023. str[0] = CURSOR;
  1024. SpvidDisplayString(str,EDIT_FIELD_TEXT,X+CurrentCharCount+1,Y);
  1025. } else {
  1026. vval = ValidateIgnore;
  1027. }
  1028. }
  1029. break;
  1030. }
  1031. }
  1032. }