Leaked source code of windows server 2003
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.

824 lines
15 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. dndisp.c
  5. Abstract:
  6. DOS-based NT setup program video display routines.
  7. Author:
  8. Ted Miller (tedm) 30-March-1992
  9. Revision History:
  10. --*/
  11. #include "winnt.h"
  12. #include <string.h>
  13. #define SCREEN_WIDTH 80
  14. #define SCREEN_HEIGHT 25
  15. #define STATUS_HEIGHT 1
  16. #define STATUS_LEFT_MARGIN 2
  17. #define HEADER_HEIGHT 3
  18. //
  19. // Display attributes
  20. //
  21. #define ATT_FG_BLACK 0
  22. #define ATT_FG_BLUE 1
  23. #define ATT_FG_GREEN 2
  24. #define ATT_FG_CYAN 3
  25. #define ATT_FG_RED 4
  26. #define ATT_FG_MAGENTA 5
  27. #define ATT_FG_YELLOW 6
  28. #define ATT_FG_WHITE 7
  29. #define ATT_BG_BLACK (ATT_FG_BLACK << 4)
  30. #define ATT_BG_BLUE (ATT_FG_BLUE << 4)
  31. #define ATT_BG_GREEN (ATT_FG_GREEN << 4)
  32. #define ATT_BG_CYAN (ATT_FG_CYAN << 4)
  33. #define ATT_BG_RED (ATT_FG_RED << 4)
  34. #define ATT_BG_MAGENTA (ATT_FG_MAGENTA << 4)
  35. #define ATT_BG_YELLOW (ATT_FG_YELLOW << 4)
  36. #define ATT_BG_WHITE (ATT_FG_WHITE << 4)
  37. #define ATT_FG_INTENSE 8
  38. #define ATT_BG_INTENSE (ATT_FG_INTENSE << 4)
  39. #define DEFAULT_ATTRIBUTE (ATT_FG_WHITE | ATT_BG_BLUE)
  40. #define STATUS_ATTRIBUTE (ATT_FG_BLACK | ATT_BG_WHITE)
  41. #define EDIT_ATTRIBUTE (ATT_FG_BLACK | ATT_BG_WHITE)
  42. #define EXITDLG_ATTRIBUTE (ATT_FG_RED | ATT_BG_WHITE)
  43. #define GAUGE_ATTRIBUTE (ATT_BG_BLUE | ATT_FG_YELLOW | ATT_FG_INTENSE)
  44. // #define USE_INT10
  45. #ifndef USE_INT10
  46. //
  47. // Far address of the screen buffer.
  48. //
  49. #define SCREEN_BUFFER ((UCHAR _far *)0xb8000000)
  50. #define SCREEN_BUFFER_CHR(x,y) *(SCREEN_BUFFER + (2*((x)+(SCREEN_WIDTH*(y)))))
  51. #define SCREEN_BUFFER_ATT(x,y) *(SCREEN_BUFFER + (2*((x)+(SCREEN_WIDTH*(y))))+1)
  52. BOOLEAN CursorIsActuallyOn;
  53. #endif
  54. //
  55. // Make these near because they are used in _asm blocks
  56. //
  57. UCHAR _near CurrentAttribute;
  58. UCHAR _near ScreenX;
  59. UCHAR _near ScreenY;
  60. BOOLEAN CursorOn;
  61. VOID
  62. DnpBlankScreenArea(
  63. IN UCHAR Attribute,
  64. IN UCHAR Left,
  65. IN UCHAR Right,
  66. IN UCHAR Top,
  67. IN UCHAR Bottom
  68. );
  69. VOID
  70. DnInitializeDisplay(
  71. VOID
  72. )
  73. /*++
  74. Routine Description:
  75. Put the display in a known state (80x25 standard text mode) and
  76. initialize the display package.
  77. Arguments:
  78. None.
  79. Return Value:
  80. None.
  81. --*/
  82. {
  83. CurrentAttribute = DEFAULT_ATTRIBUTE;
  84. CursorOn = FALSE;
  85. //
  86. // Set the display to standard 80x25 mode
  87. //
  88. _asm {
  89. mov ax,3 // set video mode to 3
  90. int 10h
  91. }
  92. //
  93. // Clear the entire screen
  94. //
  95. DnpBlankScreenArea(CurrentAttribute,0,SCREEN_WIDTH-1,0,SCREEN_HEIGHT-1);
  96. DnPositionCursor(0,0);
  97. #ifndef USE_INT10
  98. //
  99. // Shut the cursor off.
  100. //
  101. _asm {
  102. mov ah,2 // function -- position cursor
  103. mov bh,0 // display page
  104. mov dh,SCREEN_HEIGHT
  105. mov dl,0
  106. int 10h
  107. }
  108. CursorIsActuallyOn = FALSE;
  109. #endif
  110. }
  111. VOID
  112. DnClearClientArea(
  113. VOID
  114. )
  115. /*++
  116. Routine Description:
  117. Clear the client area of the screen, ie, the area between the header
  118. and status line.
  119. Arguments:
  120. None.
  121. Return Value:
  122. None.
  123. --*/
  124. {
  125. DnpBlankScreenArea( CurrentAttribute,
  126. 0,
  127. SCREEN_WIDTH-1,
  128. HEADER_HEIGHT,
  129. SCREEN_HEIGHT - STATUS_HEIGHT - 1
  130. );
  131. DnPositionCursor(0,HEADER_HEIGHT);
  132. }
  133. VOID
  134. DnSetGaugeAttribute(
  135. IN BOOLEAN Set
  136. )
  137. /*++
  138. Routine Description:
  139. Prepare for drawing the thermometer portion of a gas gauge.
  140. Arguments:
  141. Set - if TRUE, prepare for drawing the thermometer. If FALSE, restore
  142. the state for normal drawing.
  143. Return Value:
  144. None.
  145. --*/
  146. {
  147. static UCHAR SavedAttribute = 0;
  148. if(Set) {
  149. if(!SavedAttribute) {
  150. SavedAttribute = CurrentAttribute;
  151. CurrentAttribute = GAUGE_ATTRIBUTE;
  152. }
  153. } else {
  154. if(SavedAttribute) {
  155. CurrentAttribute = SavedAttribute;
  156. SavedAttribute = 0;
  157. }
  158. }
  159. }
  160. VOID
  161. DnPositionCursor(
  162. IN UCHAR X,
  163. IN UCHAR Y
  164. )
  165. /*++
  166. Routine Description:
  167. Position the cursor.
  168. Arguments:
  169. X,Y - cursor coords
  170. Return Value:
  171. None.
  172. --*/
  173. {
  174. if(X >= SCREEN_WIDTH) {
  175. X = 0;
  176. Y++;
  177. }
  178. if(Y >= SCREEN_HEIGHT) {
  179. Y = HEADER_HEIGHT;
  180. }
  181. ScreenX = X;
  182. ScreenY = Y;
  183. //
  184. // Invoke BIOS
  185. //
  186. _asm {
  187. mov ah,2 // function -- position cursor
  188. mov bh,0 // display page
  189. mov dh,ScreenY
  190. mov dl,ScreenX
  191. int 10h
  192. }
  193. #ifndef USE_INT10
  194. CursorIsActuallyOn = TRUE;
  195. #endif
  196. }
  197. VOID
  198. DnWriteChar(
  199. IN CHAR chr
  200. )
  201. /*++
  202. Routine Description:
  203. Write a character in the current attribute at the current position.
  204. Arguments:
  205. chr - Character to write
  206. Return Value:
  207. None.
  208. --*/
  209. {
  210. if(chr == '\n') {
  211. ScreenX = 0;
  212. ScreenY++;
  213. return;
  214. }
  215. #ifdef USE_INT10
  216. //
  217. // Position the cursor (turns it on)
  218. //
  219. DnPositionCursor(ScreenX,ScreenY);
  220. //
  221. // Output the character
  222. //
  223. _asm {
  224. mov ah,9 // function -- write char/attribute pair
  225. mov al,chr
  226. mov bh,0 // display page
  227. mov bl,CurrentAttribute
  228. mov cx,1 // replication factor
  229. int 10h
  230. }
  231. //
  232. // If the cursor is supposed to be off, shut it off
  233. //
  234. if(!CursorOn) {
  235. _asm {
  236. mov ah,2 // function -- position cursor
  237. mov bh,0 // display page
  238. mov dh,SCREEN_HEIGHT
  239. mov dl,0
  240. int 10h
  241. }
  242. }
  243. #else
  244. //
  245. // Don't draw outside the actual screen boundaries
  246. //
  247. if ( ( ScreenX < SCREEN_WIDTH ) && ( ScreenY < SCREEN_HEIGHT ) ) {
  248. SCREEN_BUFFER_CHR(ScreenX,ScreenY) = chr;
  249. SCREEN_BUFFER_ATT(ScreenX,ScreenY) = CurrentAttribute;
  250. }
  251. //
  252. // shut cursor off if necessary
  253. //
  254. if(!CursorOn && CursorIsActuallyOn) {
  255. CursorIsActuallyOn = FALSE;
  256. _asm {
  257. mov ah,2 // function -- position cursor
  258. mov bh,0 // display page
  259. mov dh,SCREEN_HEIGHT
  260. mov dl,0
  261. int 10h
  262. }
  263. }
  264. #endif
  265. }
  266. VOID
  267. DnWriteString(
  268. IN PCHAR String
  269. )
  270. /*++
  271. Routine Description:
  272. Write a string on the client area in the current position and
  273. adjust the current position. The string is written in the current
  274. attribute.
  275. Arguments:
  276. String - null terminated string to write.
  277. Return Value:
  278. None.
  279. --*/
  280. {
  281. PCHAR p;
  282. for(p=String; *p; p++) {
  283. DnWriteChar(*p);
  284. if(*p != '\n') {
  285. ScreenX++;
  286. }
  287. }
  288. }
  289. VOID
  290. DnWriteStatusText(
  291. IN PCHAR FormatString OPTIONAL,
  292. ...
  293. )
  294. /*++
  295. Routine Description:
  296. Update the status area
  297. Arguments:
  298. FormatString - if present, supplies a printf format string for the
  299. rest of the arguments. Otherwise the status area is cleared out.
  300. Return Value:
  301. None.
  302. --*/
  303. {
  304. va_list arglist;
  305. int StringLength;
  306. static CHAR String[SCREEN_WIDTH+1];
  307. UCHAR SavedAttribute;
  308. //
  309. // First, clear out the status area.
  310. //
  311. DnpBlankScreenArea( STATUS_ATTRIBUTE,
  312. 0,
  313. SCREEN_WIDTH-1,
  314. SCREEN_HEIGHT-STATUS_HEIGHT,
  315. SCREEN_HEIGHT-1
  316. );
  317. if(FormatString) {
  318. va_start(arglist,FormatString);
  319. StringLength = vsnprintf(String,SCREEN_WIDTH+1,FormatString,arglist);
  320. String[SCREEN_WIDTH] = '\0';
  321. SavedAttribute = CurrentAttribute;
  322. CurrentAttribute = STATUS_ATTRIBUTE;
  323. DnPositionCursor(STATUS_LEFT_MARGIN,SCREEN_HEIGHT - STATUS_HEIGHT);
  324. DnWriteString(String);
  325. CurrentAttribute = SavedAttribute;
  326. }
  327. }
  328. VOID
  329. DnSetCopyStatusText(
  330. IN PCHAR Caption,
  331. IN PCHAR Filename
  332. )
  333. /*++
  334. Routine Description:
  335. Write or erase a copying message in the lower right part of the screen.
  336. Arguments:
  337. Filename - name of file currently being copied. If NULL, erases the
  338. copy status area.
  339. Return Value:
  340. None.
  341. --*/
  342. {
  343. unsigned CopyStatusAreaLen;
  344. CHAR StatusText[100];
  345. //
  346. // The 13 is for 8.3 and a space
  347. //
  348. CopyStatusAreaLen = strlen(Caption) + 13;
  349. //
  350. // First erase the status area.
  351. //
  352. DnpBlankScreenArea( STATUS_ATTRIBUTE,
  353. (UCHAR)(SCREEN_WIDTH - CopyStatusAreaLen),
  354. SCREEN_WIDTH - 1,
  355. SCREEN_HEIGHT - STATUS_HEIGHT,
  356. SCREEN_HEIGHT - 1
  357. );
  358. if(Filename) {
  359. UCHAR SavedAttribute;
  360. UCHAR SavedX,SavedY;
  361. SavedAttribute = CurrentAttribute;
  362. SavedX = ScreenX;
  363. SavedY = ScreenY;
  364. CurrentAttribute = STATUS_ATTRIBUTE;
  365. DnPositionCursor((UCHAR)(SCREEN_WIDTH-CopyStatusAreaLen),SCREEN_HEIGHT-1);
  366. memset(StatusText,0,sizeof(StatusText));
  367. strcpy(StatusText,Caption);
  368. strncpy(StatusText + strlen(StatusText),Filename,12);
  369. DnWriteString(StatusText);
  370. CurrentAttribute = SavedAttribute;
  371. ScreenX = SavedX;
  372. ScreenY = SavedY;
  373. }
  374. }
  375. VOID
  376. DnStartEditField(
  377. IN BOOLEAN CreateField,
  378. IN UCHAR X,
  379. IN UCHAR Y,
  380. IN UCHAR W
  381. )
  382. /*++
  383. Routine Description:
  384. Sets up the display package to start handling an edit field.
  385. Arguments:
  386. CreateField - if TRUE, caller is starting an edit field interaction.
  387. If FALSE, he is ending one.
  388. X,Y,W - supply coords and width in chars of the edit field.
  389. Return Value:
  390. None.
  391. --*/
  392. {
  393. static UCHAR SavedAttribute = 255;
  394. CursorOn = CreateField;
  395. if(CreateField) {
  396. if(SavedAttribute == 255) {
  397. SavedAttribute = CurrentAttribute;
  398. CurrentAttribute = EDIT_ATTRIBUTE;
  399. }
  400. DnpBlankScreenArea(EDIT_ATTRIBUTE,X,(UCHAR)(X+W-1),Y,Y);
  401. } else {
  402. if(SavedAttribute != 255) {
  403. CurrentAttribute = SavedAttribute;
  404. SavedAttribute = 255;
  405. }
  406. }
  407. }
  408. VOID
  409. DnExitDialog(
  410. VOID
  411. )
  412. {
  413. unsigned W,H,X,Y,i;
  414. PUCHAR CharSave;
  415. PUCHAR AttSave;
  416. ULONG Key,ValidKeys[3] = { ASCI_CR,DN_KEY_F3,0 };
  417. UCHAR SavedX,SavedY,SavedAttribute;
  418. #ifndef USE_INT10
  419. BOOLEAN SavedCursorState = CursorOn;
  420. #endif
  421. SavedAttribute = CurrentAttribute;
  422. CurrentAttribute = EXITDLG_ATTRIBUTE;
  423. SavedX = ScreenX;
  424. SavedY = ScreenY;
  425. #ifndef USE_INT10
  426. //
  427. // Shut the cursor off.
  428. //
  429. CursorIsActuallyOn = FALSE;
  430. CursorOn = FALSE;
  431. _asm {
  432. mov ah,2 // function -- position cursor
  433. mov bh,0 // display page
  434. mov dh,SCREEN_HEIGHT
  435. mov dl,0
  436. int 10h
  437. }
  438. #endif
  439. //
  440. // Count lines in the dialog and determine its width.
  441. //
  442. for(H=0; DnsExitDialog.Strings[H]; H++);
  443. W = strlen(DnsExitDialog.Strings[0]);
  444. //
  445. // allocate two buffers for character save and attribute save
  446. //
  447. CharSave = MALLOC(W*H,TRUE);
  448. AttSave = MALLOC(W*H,TRUE);
  449. //
  450. // save the screen patch
  451. //
  452. for(Y=0; Y<H; Y++) {
  453. for(X=0; X<W; X++) {
  454. UCHAR att,chr;
  455. UCHAR x,y;
  456. x = (UCHAR)(X + DnsExitDialog.X);
  457. y = (UCHAR)(Y + DnsExitDialog.Y);
  458. #ifdef USE_INT10
  459. _asm {
  460. // first position cursor
  461. mov ah,2
  462. mov bh,0
  463. mov dh,y
  464. mov dl,x
  465. int 10h
  466. // now read the char/att at the cursor
  467. mov ah,8
  468. mov bh,0
  469. int 10h
  470. mov att,ah
  471. mov chr,al
  472. }
  473. #else
  474. chr = SCREEN_BUFFER_CHR(x,y);
  475. att = SCREEN_BUFFER_ATT(x,y);
  476. #endif
  477. CharSave[Y*W+X] = chr;
  478. AttSave[Y*W+X] = att;
  479. }
  480. }
  481. //
  482. // Put up the dialog
  483. //
  484. for(i=0; i<H; i++) {
  485. DnPositionCursor(DnsExitDialog.X,(UCHAR)(DnsExitDialog.Y+i));
  486. DnWriteString(DnsExitDialog.Strings[i]);
  487. }
  488. CurrentAttribute = SavedAttribute;
  489. //
  490. // Wait for a valid keypress
  491. //
  492. Key = DnGetValidKey(ValidKeys);
  493. if(Key == DN_KEY_F3) {
  494. DnExit(1);
  495. }
  496. //
  497. // Restore the patch
  498. //
  499. for(Y=0; Y<H; Y++) {
  500. for(X=0; X<W; X++) {
  501. UCHAR att,chr;
  502. UCHAR x,y;
  503. x = (UCHAR)(X + DnsExitDialog.X);
  504. y = (UCHAR)(Y + DnsExitDialog.Y);
  505. chr = CharSave[Y*W+X];
  506. att = AttSave[Y*W+X];
  507. #ifdef USE_INT10
  508. _asm {
  509. // first position cursor
  510. mov ah,2
  511. mov bh,0
  512. mov dh,y
  513. mov dl,x
  514. int 10h
  515. // now write the char/att at the cursor
  516. mov ah,9
  517. mov al,chr
  518. mov bh,0
  519. mov bl,att
  520. mov cx,1
  521. int 10h
  522. }
  523. #else
  524. SCREEN_BUFFER_CHR(x,y) = chr;
  525. SCREEN_BUFFER_ATT(x,y) = att;
  526. #endif
  527. }
  528. }
  529. FREE(CharSave);
  530. FREE(AttSave);
  531. #ifndef USE_INT10
  532. CursorOn = SavedCursorState;
  533. #endif
  534. if(CursorOn) {
  535. DnPositionCursor(SavedX,SavedY);
  536. } else {
  537. ScreenX = SavedX;
  538. ScreenY = SavedY;
  539. _asm {
  540. mov ah,2
  541. mov bh,0
  542. mov dh,SCREEN_HEIGHT;
  543. mov dl,0
  544. int 10h
  545. }
  546. #ifndef USE_INT10
  547. CursorIsActuallyOn = FALSE;
  548. #endif
  549. }
  550. }
  551. //
  552. // Internal support routines
  553. //
  554. VOID
  555. DnpBlankScreenArea(
  556. IN UCHAR Attribute,
  557. IN UCHAR Left,
  558. IN UCHAR Right,
  559. IN UCHAR Top,
  560. IN UCHAR Bottom
  561. )
  562. /*++
  563. Routine Description:
  564. Invoke the BIOS to blank a region of the screen.
  565. Arguments:
  566. Attribute - screen attribute to use to blank the region
  567. Left,Right,Top,Bottom - coords of region to blank
  568. Return Value:
  569. None.
  570. --*/
  571. {
  572. #ifdef USE_INT10
  573. //
  574. // Invoke the BIOS
  575. //
  576. _asm {
  577. mov ah,6 // function number -- scroll window up
  578. xor al,al // function code -- blank window
  579. mov bh,Attribute
  580. mov ch,Top
  581. mov cl,Left
  582. mov dh,Bottom
  583. mov dl,Right
  584. int 10h
  585. }
  586. #else
  587. UCHAR x,y;
  588. for(y=Top; y<=Bottom; y++) {
  589. for(x=Left; x<=Right; x++) {
  590. SCREEN_BUFFER_CHR(x,y) = ' ';
  591. SCREEN_BUFFER_ATT(x,y) = Attribute;
  592. }
  593. }
  594. #endif
  595. }
  596. int
  597. DnGetGaugeChar(
  598. VOID
  599. )
  600. {
  601. return(0xdb); //inverse square in cp437, 850, etc.
  602. }