00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "../../common/common.h"
00027 #include "win_local.h"
00028
00029 #define CONSOLE_WINDOW_STYLE (WS_OVERLAPPED|WS_BORDER|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_CLIPCHILDREN|WS_GROUP)
00030 #define CONSOLE_WINDOW_CLASS_NAME GAME_TITLE" Console"
00031
00032 #ifdef DEDICATED_ONLY
00033 #define CONSOLE_WINDOW_NAME GAME_TITLE" Dedicated Server Console"
00034 #else
00035 #define CONSOLE_WINDOW_NAME CONSOLE_WINDOW_CLASS_NAME
00036 #endif
00037
00038 #define MAX_OUTPUT 32768
00039 #define MAX_PRINTMSG 8192
00040
00041 typedef struct {
00042 int outLen;
00043 char cmdBuffer[MAXCMDLINE];
00044 qboolean timerActive;
00045 qboolean flashColor;
00047
00048 HWND hWnd;
00049 HWND hWndCopy;
00050 HWND hWndClear;
00051 HWND hWndQuit;
00052 HWND hWndOutput;
00053 HWND hWndInput;
00054 HWND hWndMsg;
00055 HFONT hFont;
00056 HFONT hFontBold;
00057 HBRUSH hBrushMsg;
00058 HBRUSH hBrushOutput;
00059 HBRUSH hBrushInput;
00060 WNDPROC defOutputProc;
00061 WNDPROC defInputProc;
00062 } sysConsole_t;
00063
00064 static sysConsole_t sys_console;
00065
00066 int SV_CountPlayers(void);
00067
00071 static void Sys_ConsoleLoop (qboolean error)
00072 {
00073 MSG msg;
00074
00075 while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
00076 if (!GetMessage(&msg, NULL, 0, 0)) {
00077 if (error)
00078 ExitProcess(1);
00079 else
00080 Sys_Quit();
00081 }
00082
00083 TranslateMessage(&msg);
00084 DispatchMessage(&msg);
00085 }
00086 }
00087
00092 const char *Sys_ConsoleInput (void)
00093 {
00094 static char buffer[MAXCMDLINE];
00095
00096 #ifdef DEDICATED_ONLY
00097
00098
00099 Sys_ConsoleLoop(qfalse);
00100 #endif
00101
00102
00103 if (sys_console.cmdBuffer[0] == '\0')
00104 return NULL;
00105
00106 Q_strncpyz(buffer, sys_console.cmdBuffer, sizeof(buffer));
00107
00108
00109 sys_console.cmdBuffer[0] = '\0';
00110
00111 return buffer;
00112 }
00113
00114
00115 void Sys_ConsoleOutput (const char *text)
00116 {
00117 char buffer[MAX_PRINTMSG];
00118 int len = 0;
00119
00120
00121 if (*text == 1)
00122 text++;
00123
00124
00125 while (*text) {
00126 if (*text == '\n' && len < MAX_PRINTMSG - 2) {
00127 buffer[len++] = '\r';
00128 buffer[len++] = '\n';
00129 } else if (len < MAX_PRINTMSG - 1) {
00130 buffer[len++] = *text;
00131 } else {
00132
00133 buffer[len] = '\0';
00134 break;
00135 }
00136
00137 text++;
00138 }
00139 buffer[len] = 0;
00140
00141 sys_console.outLen += len;
00142 if (sys_console.outLen >= MAX_OUTPUT) {
00143 SendMessage(sys_console.hWndOutput, EM_SETSEL, 0, -1);
00144 sys_console.outLen = len;
00145 }
00146
00147
00148 SendMessage(sys_console.hWndOutput, EM_LINESCROLL, 0, 0xFFFF);
00149 SendMessage(sys_console.hWndOutput, EM_SCROLLCARET, 0, 0);
00150
00151 SendMessage(sys_console.hWndOutput, EM_REPLACESEL, FALSE, (LPARAM)buffer);
00152
00153
00154 SendMessage(sys_console.hWndOutput, EM_LINESCROLL, 0, 0xFFFF);
00155 SendMessage(sys_console.hWndOutput, EM_SCROLLCARET, 0, 0);
00156 }
00157
00161 void Sys_Backtrace (void)
00162 {
00163 }
00164
00165 void Sys_Error (const char *error, ...)
00166 {
00167 va_list argptr;
00168 char text[1024];
00169
00170 Sys_Backtrace();
00171
00172 #ifdef COMPILE_MAP
00173 Mem_Shutdown();
00174 #endif
00175
00176 va_start(argptr, error);
00177 Q_vsnprintf(text, sizeof(text), error, argptr);
00178 va_end(argptr);
00179
00180
00181 Sys_ConsoleOutput("\n");
00182 Sys_ConsoleOutput(text);
00183 Sys_ConsoleOutput("\n");
00184
00185
00186 SetWindowText(sys_console.hWndMsg, text);
00187 SetTimer(sys_console.hWnd, 1, 1000, NULL);
00188
00189 sys_console.timerActive = qtrue;
00190
00191
00192 ShowWindow(sys_console.hWndMsg, SW_SHOW);
00193 ShowWindow(sys_console.hWndInput, SW_HIDE);
00194
00195 Sys_ShowConsole(qtrue);
00196
00197
00198 while (1) {
00199 Sys_ConsoleLoop(qtrue);
00200
00201 Sys_Sleep(25);
00202 }
00203 }
00204
00205
00206 void Sys_ShowConsole (qboolean show)
00207 {
00208 if (!show) {
00209 ShowWindow(sys_console.hWnd, SW_HIDE);
00210 return;
00211 }
00212
00213 ShowWindow(sys_console.hWnd, SW_SHOW);
00214 UpdateWindow(sys_console.hWnd);
00215 SetForegroundWindow(sys_console.hWnd);
00216 SetFocus(sys_console.hWnd);
00217
00218
00219 SetFocus(sys_console.hWndInput);
00220
00221
00222 SendMessage(sys_console.hWndOutput, EM_LINESCROLL, 0, 0xFFFF);
00223 SendMessage(sys_console.hWndOutput, EM_SCROLLCARET, 0, 0);
00224 }
00225
00226 static LONG WINAPI Sys_ConsoleProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
00227 {
00228 switch (uMsg) {
00229 case WM_ACTIVATE:
00230 if (LOWORD(wParam) != WA_INACTIVE) {
00231 SetFocus(sys_console.hWndInput);
00232 return 0;
00233 }
00234 break;
00235
00236 case WM_CLOSE:
00237 if (SV_CountPlayers()) {
00238 const int ays = MessageBox(hWnd, "There are still players on the server! Really shut it down?", "WARNING!", MB_YESNO + MB_ICONEXCLAMATION);
00239 if (ays == IDNO)
00240 return TRUE;
00241 }
00242 Sys_Quit();
00243 break;
00244
00245 case WM_COMMAND:
00246 if (HIWORD(wParam) == BN_CLICKED) {
00247 if ((HWND)lParam == sys_console.hWndCopy) {
00248 SendMessage(sys_console.hWndOutput, EM_SETSEL, 0, -1);
00249 SendMessage(sys_console.hWndOutput, WM_COPY, 0, 0);
00250 } else if ((HWND)lParam == sys_console.hWndClear) {
00251 SendMessage(sys_console.hWndOutput, EM_SETSEL, 0, -1);
00252 SendMessage(sys_console.hWndOutput, WM_CLEAR, 0, 0);
00253 } else if ((HWND)lParam == sys_console.hWndQuit)
00254 Sys_Quit();
00255 } else if (HIWORD(wParam) == EN_VSCROLL)
00256 InvalidateRect(sys_console.hWndOutput, NULL, TRUE);
00257 break;
00258
00259 case WM_CTLCOLOREDIT:
00260 if ((HWND)lParam == sys_console.hWndOutput) {
00261 SetBkMode((HDC)wParam, TRANSPARENT);
00262 SetBkColor((HDC)wParam, RGB(255, 255, 255));
00263 SetTextColor((HDC)wParam, RGB(0, 0, 0));
00264 return (LONG)sys_console.hBrushOutput;
00265 } else if ((HWND)lParam == sys_console.hWndInput) {
00266 SetBkMode((HDC)wParam, TRANSPARENT);
00267 SetBkColor((HDC)wParam, RGB(255, 255, 255));
00268 SetTextColor((HDC)wParam, RGB(0, 0, 0));
00269 return (LONG)sys_console.hBrushInput;
00270 }
00271 break;
00272
00273 case WM_CTLCOLORSTATIC:
00274 if ((HWND)lParam == sys_console.hWndMsg) {
00275 SetBkMode((HDC)wParam, TRANSPARENT);
00276 SetBkColor((HDC)wParam, RGB(127, 127, 127));
00277
00278 if (sys_console.flashColor)
00279 SetTextColor((HDC)wParam, RGB(255, 0, 0));
00280 else
00281 SetTextColor((HDC)wParam, RGB(0, 0, 0));
00282
00283 return (LONG)sys_console.hBrushMsg;
00284 }
00285 break;
00286
00287 case WM_TIMER:
00288 sys_console.flashColor = !sys_console.flashColor;
00289 InvalidateRect(sys_console.hWndMsg, NULL, TRUE);
00290 break;
00291
00292 case WM_CREATE:
00293 SetTimer(sys_console.hWnd, 1, 500, NULL);
00294 break;
00295 }
00296
00297 return DefWindowProc(hWnd, uMsg, wParam, lParam);
00298 }
00299
00300
00301 static LONG WINAPI Sys_ConsoleEditProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
00302 {
00303 switch (uMsg) {
00304 case WM_CHAR:
00305 if (hWnd == sys_console.hWndInput) {
00306 switch (wParam) {
00307 case VK_RETURN:
00308 if (GetWindowText(sys_console.hWndInput, sys_console.cmdBuffer, sizeof(sys_console.cmdBuffer))) {
00309 SetWindowText(sys_console.hWndInput, "");
00310 Com_Printf("]%s\n", sys_console.cmdBuffer);
00311 }
00312
00313 return 0;
00314 case VK_TAB:
00315
00316 if (GetWindowText(sys_console.hWndInput, sys_console.cmdBuffer, sizeof(sys_console.cmdBuffer))) {
00317 int inputpos = 0;
00318 if (Com_ConsoleCompleteCommand(sys_console.cmdBuffer, sys_console.cmdBuffer, MAXCMDLINE, &inputpos, 0)) {
00319 SetWindowText(sys_console.hWndInput, sys_console.cmdBuffer);
00320
00321 sys_console.cmdBuffer[0] = '\0';
00322 }
00323 }
00324
00325 return 0;
00326 }
00327 } else if (hWnd == sys_console.hWndOutput)
00328 return 0;
00329 break;
00330
00331 case WM_VSCROLL:
00332 if (LOWORD(wParam) == SB_THUMBTRACK)
00333 return 0;
00334 break;
00335 }
00336
00337 if (hWnd == sys_console.hWndOutput)
00338 return CallWindowProc(sys_console.defOutputProc, hWnd, uMsg, wParam, lParam);
00339 else if (hWnd == sys_console.hWndInput)
00340 return CallWindowProc(sys_console.defInputProc, hWnd, uMsg, wParam, lParam);
00341 return 0;
00342 }
00343
00344
00348 void Sys_ConsoleShutdown (void)
00349 {
00350 if (sys_console.timerActive)
00351 KillTimer(sys_console.hWnd, 1);
00352
00353 if (sys_console.hBrushMsg)
00354 DeleteObject(sys_console.hBrushMsg);
00355 if (sys_console.hBrushOutput)
00356 DeleteObject(sys_console.hBrushOutput);
00357 if (sys_console.hBrushInput)
00358 DeleteObject(sys_console.hBrushInput);
00359
00360 if (sys_console.hFont)
00361 DeleteObject(sys_console.hFont);
00362 if (sys_console.hFontBold)
00363 DeleteObject(sys_console.hFontBold);
00364
00365 if (sys_console.defOutputProc)
00366 SetWindowLong(sys_console.hWndOutput, GWL_WNDPROC, (LONG)sys_console.defOutputProc);
00367 if (sys_console.defInputProc)
00368 SetWindowLong(sys_console.hWndInput, GWL_WNDPROC, (LONG)sys_console.defInputProc);
00369
00370 ShowWindow(sys_console.hWnd, SW_HIDE);
00371 DestroyWindow(sys_console.hWnd);
00372 UnregisterClass(CONSOLE_WINDOW_CLASS_NAME, global_hInstance);
00373 }
00374
00375 void Sys_ConsoleInit (void)
00376 {
00377 WNDCLASSEX wc;
00378 HDC hDC;
00379 RECT r;
00380 int x, y, w, h;
00381
00382
00383 hDC = GetDC(0);
00384 w = GetDeviceCaps(hDC, HORZRES);
00385 h = GetDeviceCaps(hDC, VERTRES);
00386 ReleaseDC(0, hDC);
00387
00388 r.left = (w - 540) / 2;
00389 r.top = (h - 455) / 2;
00390 r.right = r.left + 540;
00391 r.bottom = r.top + 455;
00392
00393 AdjustWindowRect(&r, CONSOLE_WINDOW_STYLE, FALSE);
00394
00395 x = r.left;
00396 y = r.top;
00397 w = r.right - r.left;
00398 h = r.bottom - r.top;
00399
00400 wc.style = 0;
00401 wc.lpfnWndProc = (WNDPROC)Sys_ConsoleProc;
00402 wc.cbClsExtra = 0;
00403 wc.cbWndExtra = 0;
00404 wc.hInstance = global_hInstance;
00405 wc.hIcon = LoadIcon(global_hInstance, MAKEINTRESOURCE(101));
00406 wc.hIconSm = 0;
00407 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
00408 wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
00409 wc.lpszMenuName = 0;
00410 wc.lpszClassName = CONSOLE_WINDOW_CLASS_NAME;
00411 wc.cbSize = sizeof(WNDCLASSEX);
00412
00413 if (!RegisterClassEx(&wc)) {
00414 MessageBox(NULL, "Could not register console window class", "ERROR", MB_OK | MB_ICONERROR | MB_TASKMODAL);
00415 exit(0);
00416 }
00417
00418 sys_console.hWnd = CreateWindowEx(0, CONSOLE_WINDOW_CLASS_NAME, CONSOLE_WINDOW_NAME, CONSOLE_WINDOW_STYLE, x, y, w, h, NULL, NULL, global_hInstance, NULL);
00419 if (!sys_console.hWnd) {
00420 UnregisterClass(CONSOLE_WINDOW_CLASS_NAME, global_hInstance);
00421 MessageBox(NULL, "Could not create console window", "ERROR", MB_OK | MB_ICONERROR | MB_TASKMODAL);
00422 exit(0);
00423 }
00424
00425 sys_console.hWndMsg = CreateWindowEx(0, "STATIC", "", WS_CHILD | SS_SUNKEN, 5, 5, 530, 30, sys_console.hWnd, NULL, global_hInstance, NULL);
00426 sys_console.hWndOutput = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | ES_MULTILINE, 5, 40, 530, 350, sys_console.hWnd, NULL, global_hInstance, NULL);
00427 sys_console.hWndInput = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL, 5, 395, 530, 20, sys_console.hWnd, NULL, global_hInstance, NULL);
00428 sys_console.hWndCopy = CreateWindowEx(0, "BUTTON", "copy", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 5, 425, 70, 25, sys_console.hWnd, NULL, global_hInstance, NULL);
00429 sys_console.hWndClear = CreateWindowEx(0, "BUTTON", "clear", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 80, 425, 70, 25, sys_console.hWnd, NULL, global_hInstance, NULL);
00430 sys_console.hWndQuit = CreateWindowEx(0, "BUTTON", "quit", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 465, 425, 70, 25, sys_console.hWnd, NULL, global_hInstance, NULL);
00431
00432
00433 sys_console.hFont = CreateFont(14, 0, 0, 0, FW_LIGHT, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "Courier New");
00434 sys_console.hFontBold = CreateFont(20, 0, 0, 0, FW_SEMIBOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "System");
00435
00436 SendMessage(sys_console.hWndMsg, WM_SETFONT, (WPARAM)sys_console.hFont, FALSE);
00437 SendMessage(sys_console.hWndOutput, WM_SETFONT, (WPARAM)sys_console.hFont, FALSE);
00438 SendMessage(sys_console.hWndInput, WM_SETFONT, (WPARAM)sys_console.hFont, FALSE);
00439 SendMessage(sys_console.hWndCopy, WM_SETFONT, (WPARAM)sys_console.hFontBold, FALSE);
00440 SendMessage(sys_console.hWndClear, WM_SETFONT, (WPARAM)sys_console.hFontBold, FALSE);
00441 SendMessage(sys_console.hWndQuit, WM_SETFONT, (WPARAM)sys_console.hFontBold, FALSE);
00442
00443
00444 sys_console.hBrushMsg = CreateSolidBrush(RGB(127, 127, 127));
00445 sys_console.hBrushOutput = CreateSolidBrush(RGB(255, 255, 255));
00446 sys_console.hBrushInput = CreateSolidBrush(RGB(255, 255, 255));
00447
00448
00449 sys_console.defOutputProc = (WNDPROC)SetWindowLong(sys_console.hWndOutput, GWL_WNDPROC, (LONG)Sys_ConsoleEditProc);
00450 sys_console.defInputProc = (WNDPROC)SetWindowLong(sys_console.hWndInput, GWL_WNDPROC, (LONG)Sys_ConsoleEditProc);
00451
00452
00453 SendMessage(sys_console.hWndInput, EM_SETLIMITTEXT, (WPARAM)(MAXCMDLINE - 1), 0);
00454
00455
00456 Sys_ShowConsole(qtrue);
00457 }