win_syscon.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #pragma hdrstop
  21. #include "../../idlib/precompiled.h"
  22. #include <errno.h>
  23. #include <float.h>
  24. #include <fcntl.h>
  25. #include <stdio.h>
  26. #include <direct.h>
  27. #include <io.h>
  28. #include <conio.h>
  29. #include "win_local.h"
  30. #include "rc/doom_resource.h"
  31. #define COPY_ID 1
  32. #define QUIT_ID 2
  33. #define CLEAR_ID 3
  34. #define ERRORBOX_ID 10
  35. #define ERRORTEXT_ID 11
  36. #define EDIT_ID 100
  37. #define INPUT_ID 101
  38. #define COMMAND_HISTORY 64
  39. typedef struct {
  40. HWND hWnd;
  41. HWND hwndBuffer;
  42. HWND hwndButtonClear;
  43. HWND hwndButtonCopy;
  44. HWND hwndButtonQuit;
  45. HWND hwndErrorBox;
  46. HWND hwndErrorText;
  47. HBITMAP hbmLogo;
  48. HBITMAP hbmClearBitmap;
  49. HBRUSH hbrEditBackground;
  50. HBRUSH hbrErrorBackground;
  51. HFONT hfBufferFont;
  52. HFONT hfButtonFont;
  53. HWND hwndInputLine;
  54. char errorString[80];
  55. char consoleText[512], returnedText[512];
  56. bool quitOnClose;
  57. int windowWidth, windowHeight;
  58. WNDPROC SysInputLineWndProc;
  59. idEditField historyEditLines[COMMAND_HISTORY];
  60. int nextHistoryLine;// the last line in the history buffer, not masked
  61. int historyLine; // the line being displayed from history buffer
  62. // will be <= nextHistoryLine
  63. idEditField consoleField;
  64. } WinConData;
  65. static WinConData s_wcd;
  66. static LONG WINAPI ConWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  67. char *cmdString;
  68. static bool s_timePolarity;
  69. switch (uMsg) {
  70. case WM_ACTIVATE:
  71. if ( LOWORD( wParam ) != WA_INACTIVE ) {
  72. SetFocus( s_wcd.hwndInputLine );
  73. }
  74. break;
  75. case WM_CLOSE:
  76. if ( s_wcd.quitOnClose ) {
  77. PostQuitMessage( 0 );
  78. } else {
  79. Sys_ShowConsole( 0, false );
  80. win32.win_viewlog.SetBool( false );
  81. }
  82. return 0;
  83. case WM_CTLCOLORSTATIC:
  84. if ( ( HWND ) lParam == s_wcd.hwndBuffer ) {
  85. SetBkColor( ( HDC ) wParam, RGB( 0x00, 0x00, 0x80 ) );
  86. SetTextColor( ( HDC ) wParam, RGB( 0xff, 0xff, 0x00 ) );
  87. return ( long ) s_wcd.hbrEditBackground;
  88. } else if ( ( HWND ) lParam == s_wcd.hwndErrorBox ) {
  89. if ( s_timePolarity & 1 ) {
  90. SetBkColor( ( HDC ) wParam, RGB( 0x80, 0x80, 0x80 ) );
  91. SetTextColor( ( HDC ) wParam, RGB( 0xff, 0x0, 0x00 ) );
  92. } else {
  93. SetBkColor( ( HDC ) wParam, RGB( 0x80, 0x80, 0x80 ) );
  94. SetTextColor( ( HDC ) wParam, RGB( 0x00, 0x0, 0x00 ) );
  95. }
  96. return ( long ) s_wcd.hbrErrorBackground;
  97. }
  98. break;
  99. case WM_SYSCOMMAND:
  100. if ( wParam == SC_CLOSE ) {
  101. PostQuitMessage( 0 );
  102. }
  103. break;
  104. case WM_COMMAND:
  105. if ( wParam == COPY_ID ) {
  106. SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 );
  107. SendMessage( s_wcd.hwndBuffer, WM_COPY, 0, 0 );
  108. } else if ( wParam == QUIT_ID ) {
  109. if ( s_wcd.quitOnClose ) {
  110. PostQuitMessage( 0 );
  111. } else {
  112. cmdString = Mem_CopyString( "quit" );
  113. Sys_QueEvent( SE_CONSOLE, 0, 0, strlen( cmdString ) + 1, cmdString, 0 );
  114. }
  115. } else if ( wParam == CLEAR_ID ) {
  116. SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 );
  117. SendMessage( s_wcd.hwndBuffer, EM_REPLACESEL, FALSE, ( LPARAM ) "" );
  118. UpdateWindow( s_wcd.hwndBuffer );
  119. }
  120. break;
  121. case WM_CREATE:
  122. s_wcd.hbrEditBackground = CreateSolidBrush( RGB( 0x00, 0x00, 0x80 ) );
  123. s_wcd.hbrErrorBackground = CreateSolidBrush( RGB( 0x80, 0x80, 0x80 ) );
  124. SetTimer( hWnd, 1, 1000, NULL );
  125. break;
  126. /*
  127. case WM_ERASEBKGND:
  128. HGDIOBJ oldObject;
  129. HDC hdcScaled;
  130. hdcScaled = CreateCompatibleDC( ( HDC ) wParam );
  131. assert( hdcScaled != 0 );
  132. if ( hdcScaled ) {
  133. oldObject = SelectObject( ( HDC ) hdcScaled, s_wcd.hbmLogo );
  134. assert( oldObject != 0 );
  135. if ( oldObject )
  136. {
  137. StretchBlt( ( HDC ) wParam, 0, 0, s_wcd.windowWidth, s_wcd.windowHeight,
  138. hdcScaled, 0, 0, 512, 384,
  139. SRCCOPY );
  140. }
  141. DeleteDC( hdcScaled );
  142. hdcScaled = 0;
  143. }
  144. return 1;
  145. */
  146. case WM_TIMER:
  147. if ( wParam == 1 ) {
  148. s_timePolarity = (bool)!s_timePolarity;
  149. if ( s_wcd.hwndErrorBox ) {
  150. InvalidateRect( s_wcd.hwndErrorBox, NULL, FALSE );
  151. }
  152. }
  153. break;
  154. }
  155. return DefWindowProc( hWnd, uMsg, wParam, lParam );
  156. }
  157. LONG WINAPI InputLineWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  158. int key, cursor;
  159. switch ( uMsg ) {
  160. case WM_KILLFOCUS:
  161. if ( ( HWND ) wParam == s_wcd.hWnd || ( HWND ) wParam == s_wcd.hwndErrorBox ) {
  162. SetFocus( hWnd );
  163. return 0;
  164. }
  165. break;
  166. case WM_KEYDOWN:
  167. key = ( ( lParam >> 16 ) & 0xFF ) | ( ( ( lParam >> 24 ) & 1 ) << 7 );
  168. // command history
  169. if ( ( key == K_UPARROW ) || ( key == K_KP_8 ) ) {
  170. if ( s_wcd.nextHistoryLine - s_wcd.historyLine < COMMAND_HISTORY && s_wcd.historyLine > 0 ) {
  171. s_wcd.historyLine--;
  172. }
  173. s_wcd.consoleField = s_wcd.historyEditLines[ s_wcd.historyLine % COMMAND_HISTORY ];
  174. SetWindowText( s_wcd.hwndInputLine, s_wcd.consoleField.GetBuffer() );
  175. SendMessage( s_wcd.hwndInputLine, EM_SETSEL, s_wcd.consoleField.GetCursor(), s_wcd.consoleField.GetCursor() );
  176. return 0;
  177. }
  178. if ( ( key == K_DOWNARROW ) || ( key == K_KP_2 ) ) {
  179. if ( s_wcd.historyLine == s_wcd.nextHistoryLine ) {
  180. return 0;
  181. }
  182. s_wcd.historyLine++;
  183. s_wcd.consoleField = s_wcd.historyEditLines[ s_wcd.historyLine % COMMAND_HISTORY ];
  184. SetWindowText( s_wcd.hwndInputLine, s_wcd.consoleField.GetBuffer() );
  185. SendMessage( s_wcd.hwndInputLine, EM_SETSEL, s_wcd.consoleField.GetCursor(), s_wcd.consoleField.GetCursor() );
  186. return 0;
  187. }
  188. break;
  189. case WM_CHAR:
  190. key = ( ( lParam >> 16 ) & 0xFF ) | ( ( ( lParam >> 24 ) & 1 ) << 7 );
  191. GetWindowText( s_wcd.hwndInputLine, s_wcd.consoleField.GetBuffer(), MAX_EDIT_LINE );
  192. SendMessage( s_wcd.hwndInputLine, EM_GETSEL, (WPARAM) NULL, (LPARAM) &cursor );
  193. s_wcd.consoleField.SetCursor( cursor );
  194. // enter the line
  195. if ( key == K_ENTER || key == K_KP_ENTER ) {
  196. strncat( s_wcd.consoleText, s_wcd.consoleField.GetBuffer(), sizeof( s_wcd.consoleText ) - strlen( s_wcd.consoleText ) - 5 );
  197. strcat( s_wcd.consoleText, "\n" );
  198. SetWindowText( s_wcd.hwndInputLine, "" );
  199. Sys_Printf( "]%s\n", s_wcd.consoleField.GetBuffer() );
  200. // copy line to history buffer
  201. s_wcd.historyEditLines[s_wcd.nextHistoryLine % COMMAND_HISTORY] = s_wcd.consoleField;
  202. s_wcd.nextHistoryLine++;
  203. s_wcd.historyLine = s_wcd.nextHistoryLine;
  204. s_wcd.consoleField.Clear();
  205. return 0;
  206. }
  207. // command completion
  208. if ( key == K_TAB ) {
  209. s_wcd.consoleField.AutoComplete();
  210. SetWindowText( s_wcd.hwndInputLine, s_wcd.consoleField.GetBuffer() );
  211. //s_wcd.consoleField.SetWidthInChars( strlen( s_wcd.consoleField.GetBuffer() ) );
  212. SendMessage( s_wcd.hwndInputLine, EM_SETSEL, s_wcd.consoleField.GetCursor(), s_wcd.consoleField.GetCursor() );
  213. return 0;
  214. }
  215. // clear autocompletion buffer on normal key input
  216. if ( ( key >= K_SPACE && key <= K_BACKSPACE ) ||
  217. ( key >= K_KP_SLASH && key <= K_KP_PLUS ) || ( key >= K_KP_STAR && key <= K_KP_EQUALS ) ) {
  218. s_wcd.consoleField.ClearAutoComplete();
  219. }
  220. break;
  221. }
  222. return CallWindowProc( s_wcd.SysInputLineWndProc, hWnd, uMsg, wParam, lParam );
  223. }
  224. /*
  225. ** Sys_CreateConsole
  226. */
  227. void Sys_CreateConsole() {
  228. HDC hDC;
  229. WNDCLASS wc;
  230. RECT rect;
  231. const char *DEDCLASS = WIN32_CONSOLE_CLASS;
  232. int nHeight;
  233. int swidth, sheight;
  234. int DEDSTYLE = WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX;
  235. int i;
  236. memset( &wc, 0, sizeof( wc ) );
  237. wc.style = 0;
  238. wc.lpfnWndProc = (WNDPROC) ConWndProc;
  239. wc.cbClsExtra = 0;
  240. wc.cbWndExtra = 0;
  241. wc.hInstance = win32.hInstance;
  242. wc.hIcon = LoadIcon( win32.hInstance, MAKEINTRESOURCE(IDI_ICON1));
  243. wc.hCursor = LoadCursor (NULL,IDC_ARROW);
  244. wc.hbrBackground = (struct HBRUSH__ *)COLOR_WINDOW;
  245. wc.lpszMenuName = 0;
  246. wc.lpszClassName = DEDCLASS;
  247. if ( !RegisterClass (&wc) ) {
  248. return;
  249. }
  250. rect.left = 0;
  251. rect.right = 540;
  252. rect.top = 0;
  253. rect.bottom = 450;
  254. AdjustWindowRect( &rect, DEDSTYLE, FALSE );
  255. hDC = GetDC( GetDesktopWindow() );
  256. swidth = GetDeviceCaps( hDC, HORZRES );
  257. sheight = GetDeviceCaps( hDC, VERTRES );
  258. ReleaseDC( GetDesktopWindow(), hDC );
  259. s_wcd.windowWidth = rect.right - rect.left + 1;
  260. s_wcd.windowHeight = rect.bottom - rect.top + 1;
  261. //s_wcd.hbmLogo = LoadBitmap( win32.hInstance, MAKEINTRESOURCE( IDB_BITMAP_LOGO) );
  262. s_wcd.hWnd = CreateWindowEx( 0,
  263. DEDCLASS,
  264. GAME_NAME,
  265. DEDSTYLE,
  266. ( swidth - 600 ) / 2, ( sheight - 450 ) / 2 , rect.right - rect.left + 1, rect.bottom - rect.top + 1,
  267. NULL,
  268. NULL,
  269. win32.hInstance,
  270. NULL );
  271. if ( s_wcd.hWnd == NULL ) {
  272. return;
  273. }
  274. //
  275. // create fonts
  276. //
  277. hDC = GetDC( s_wcd.hWnd );
  278. nHeight = -MulDiv( 8, GetDeviceCaps( hDC, LOGPIXELSY ), 72 );
  279. s_wcd.hfBufferFont = CreateFont( nHeight, 0, 0, 0, FW_LIGHT, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_MODERN | FIXED_PITCH, "Courier New" );
  280. ReleaseDC( s_wcd.hWnd, hDC );
  281. //
  282. // create the input line
  283. //
  284. s_wcd.hwndInputLine = CreateWindow( "edit", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER |
  285. ES_LEFT | ES_AUTOHSCROLL,
  286. 6, 400, 528, 20,
  287. s_wcd.hWnd,
  288. ( HMENU ) INPUT_ID, // child window ID
  289. win32.hInstance, NULL );
  290. //
  291. // create the buttons
  292. //
  293. s_wcd.hwndButtonCopy = CreateWindow( "button", NULL, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
  294. 5, 425, 72, 24,
  295. s_wcd.hWnd,
  296. ( HMENU ) COPY_ID, // child window ID
  297. win32.hInstance, NULL );
  298. SendMessage( s_wcd.hwndButtonCopy, WM_SETTEXT, 0, ( LPARAM ) "copy" );
  299. s_wcd.hwndButtonClear = CreateWindow( "button", NULL, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
  300. 82, 425, 72, 24,
  301. s_wcd.hWnd,
  302. ( HMENU ) CLEAR_ID, // child window ID
  303. win32.hInstance, NULL );
  304. SendMessage( s_wcd.hwndButtonClear, WM_SETTEXT, 0, ( LPARAM ) "clear" );
  305. s_wcd.hwndButtonQuit = CreateWindow( "button", NULL, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
  306. 462, 425, 72, 24,
  307. s_wcd.hWnd,
  308. ( HMENU ) QUIT_ID, // child window ID
  309. win32.hInstance, NULL );
  310. SendMessage( s_wcd.hwndButtonQuit, WM_SETTEXT, 0, ( LPARAM ) "quit" );
  311. //
  312. // create the scrollbuffer
  313. //
  314. s_wcd.hwndBuffer = CreateWindow( "edit", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER |
  315. ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY,
  316. 6, 40, 526, 354,
  317. s_wcd.hWnd,
  318. ( HMENU ) EDIT_ID, // child window ID
  319. win32.hInstance, NULL );
  320. SendMessage( s_wcd.hwndBuffer, WM_SETFONT, ( WPARAM ) s_wcd.hfBufferFont, 0 );
  321. s_wcd.SysInputLineWndProc = ( WNDPROC ) SetWindowLong( s_wcd.hwndInputLine, GWL_WNDPROC, ( long ) InputLineWndProc );
  322. SendMessage( s_wcd.hwndInputLine, WM_SETFONT, ( WPARAM ) s_wcd.hfBufferFont, 0 );
  323. // don't show it now that we have a splash screen up
  324. if ( win32.win_viewlog.GetBool() ) {
  325. ShowWindow( s_wcd.hWnd, SW_SHOWDEFAULT);
  326. UpdateWindow( s_wcd.hWnd );
  327. SetForegroundWindow( s_wcd.hWnd );
  328. SetFocus( s_wcd.hwndInputLine );
  329. }
  330. s_wcd.consoleField.Clear();
  331. for ( i = 0 ; i < COMMAND_HISTORY ; i++ ) {
  332. s_wcd.historyEditLines[i].Clear();
  333. }
  334. }
  335. /*
  336. ** Sys_DestroyConsole
  337. */
  338. void Sys_DestroyConsole() {
  339. if ( s_wcd.hWnd ) {
  340. ShowWindow( s_wcd.hWnd, SW_HIDE );
  341. CloseWindow( s_wcd.hWnd );
  342. DestroyWindow( s_wcd.hWnd );
  343. s_wcd.hWnd = 0;
  344. }
  345. }
  346. /*
  347. ** Sys_ShowConsole
  348. */
  349. void Sys_ShowConsole( int visLevel, bool quitOnClose ) {
  350. s_wcd.quitOnClose = quitOnClose;
  351. if ( !s_wcd.hWnd ) {
  352. return;
  353. }
  354. switch ( visLevel ) {
  355. case 0:
  356. ShowWindow( s_wcd.hWnd, SW_HIDE );
  357. break;
  358. case 1:
  359. ShowWindow( s_wcd.hWnd, SW_SHOWNORMAL );
  360. SendMessage( s_wcd.hwndBuffer, EM_LINESCROLL, 0, 0xffff );
  361. break;
  362. case 2:
  363. ShowWindow( s_wcd.hWnd, SW_MINIMIZE );
  364. break;
  365. default:
  366. Sys_Error( "Invalid visLevel %d sent to Sys_ShowConsole\n", visLevel );
  367. break;
  368. }
  369. }
  370. /*
  371. ** Sys_ConsoleInput
  372. */
  373. char *Sys_ConsoleInput() {
  374. if ( s_wcd.consoleText[0] == 0 ) {
  375. return NULL;
  376. }
  377. strcpy( s_wcd.returnedText, s_wcd.consoleText );
  378. s_wcd.consoleText[0] = 0;
  379. return s_wcd.returnedText;
  380. }
  381. /*
  382. ** Conbuf_AppendText
  383. */
  384. void Conbuf_AppendText( const char *pMsg )
  385. {
  386. #define CONSOLE_BUFFER_SIZE 16384
  387. char buffer[CONSOLE_BUFFER_SIZE*2];
  388. char *b = buffer;
  389. const char *msg;
  390. int bufLen;
  391. int i = 0;
  392. static unsigned long s_totalChars;
  393. //
  394. // if the message is REALLY long, use just the last portion of it
  395. //
  396. if ( strlen( pMsg ) > CONSOLE_BUFFER_SIZE - 1 ) {
  397. msg = pMsg + strlen( pMsg ) - CONSOLE_BUFFER_SIZE + 1;
  398. } else {
  399. msg = pMsg;
  400. }
  401. //
  402. // copy into an intermediate buffer
  403. //
  404. while ( msg[i] && ( ( b - buffer ) < sizeof( buffer ) - 1 ) ) {
  405. if ( msg[i] == '\n' && msg[i+1] == '\r' ) {
  406. b[0] = '\r';
  407. b[1] = '\n';
  408. b += 2;
  409. i++;
  410. } else if ( msg[i] == '\r' ) {
  411. b[0] = '\r';
  412. b[1] = '\n';
  413. b += 2;
  414. } else if ( msg[i] == '\n' ) {
  415. b[0] = '\r';
  416. b[1] = '\n';
  417. b += 2;
  418. } else if ( idStr::IsColor( &msg[i] ) ) {
  419. i++;
  420. } else {
  421. *b= msg[i];
  422. b++;
  423. }
  424. i++;
  425. }
  426. *b = 0;
  427. bufLen = b - buffer;
  428. s_totalChars += bufLen;
  429. //
  430. // replace selection instead of appending if we're overflowing
  431. //
  432. if ( s_totalChars > 0x7000 ) {
  433. SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 );
  434. s_totalChars = bufLen;
  435. }
  436. //
  437. // put this text into the windows console
  438. //
  439. SendMessage( s_wcd.hwndBuffer, EM_LINESCROLL, 0, 0xffff );
  440. SendMessage( s_wcd.hwndBuffer, EM_SCROLLCARET, 0, 0 );
  441. SendMessage( s_wcd.hwndBuffer, EM_REPLACESEL, 0, (LPARAM) buffer );
  442. }
  443. /*
  444. ** Win_SetErrorText
  445. */
  446. void Win_SetErrorText( const char *buf ) {
  447. idStr::Copynz( s_wcd.errorString, buf, sizeof( s_wcd.errorString ) );
  448. if ( !s_wcd.hwndErrorBox ) {
  449. s_wcd.hwndErrorBox = CreateWindow( "static", NULL, WS_CHILD | WS_VISIBLE | SS_SUNKEN,
  450. 6, 5, 526, 30,
  451. s_wcd.hWnd,
  452. ( HMENU ) ERRORBOX_ID, // child window ID
  453. win32.hInstance, NULL );
  454. SendMessage( s_wcd.hwndErrorBox, WM_SETFONT, ( WPARAM ) s_wcd.hfBufferFont, 0 );
  455. SetWindowText( s_wcd.hwndErrorBox, s_wcd.errorString );
  456. DestroyWindow( s_wcd.hwndInputLine );
  457. s_wcd.hwndInputLine = NULL;
  458. }
  459. }