diff options
Diffstat (limited to 'src/lprintf.c')
-rw-r--r-- | src/lprintf.c | 382 |
1 files changed, 382 insertions, 0 deletions
diff --git a/src/lprintf.c b/src/lprintf.c new file mode 100644 index 0000000..0951cf3 --- /dev/null +++ b/src/lprintf.c | |||
@@ -0,0 +1,382 @@ | |||
1 | /* Emacs style mode select -*- C++ -*- | ||
2 | *----------------------------------------------------------------------------- | ||
3 | * | ||
4 | * | ||
5 | * PrBoom: a Doom port merged with LxDoom and LSDLDoom | ||
6 | * based on BOOM, a modified and improved DOOM engine | ||
7 | * Copyright (C) 1999 by | ||
8 | * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman | ||
9 | * Copyright (C) 1999-2000 by | ||
10 | * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze | ||
11 | * Copyright 2005, 2006 by | ||
12 | * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or | ||
15 | * modify it under the terms of the GNU General Public License | ||
16 | * as published by the Free Software Foundation; either version 2 | ||
17 | * of the License, or (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||
27 | * 02111-1307, USA. | ||
28 | * | ||
29 | * DESCRIPTION: | ||
30 | * Provides a logical console output routine that allows what is | ||
31 | * output to console normally and when output is redirected to | ||
32 | * be controlled.. | ||
33 | * | ||
34 | *-----------------------------------------------------------------------------*/ | ||
35 | |||
36 | #ifdef HAVE_CONFIG_H | ||
37 | #include "config.h" | ||
38 | #endif | ||
39 | #ifdef _WIN32 | ||
40 | #define WIN32_LEAN_AND_MEAN | ||
41 | #include <windows.h> | ||
42 | #endif | ||
43 | #ifdef _MSC_VER | ||
44 | #include <io.h> | ||
45 | #endif | ||
46 | #include <stdio.h> | ||
47 | #include <stdlib.h> | ||
48 | #include <stdarg.h> | ||
49 | #ifdef HAVE_UNISTD_H | ||
50 | #include <unistd.h> | ||
51 | #endif | ||
52 | #include "doomtype.h" | ||
53 | #include "lprintf.h" | ||
54 | #include "i_main.h" | ||
55 | #include "m_argv.h" | ||
56 | |||
57 | int cons_error_mask = -1-LO_INFO; /* all but LO_INFO when redir'd */ | ||
58 | int cons_output_mask = -1; /* all output enabled */ | ||
59 | |||
60 | /* cphipps - enlarged message buffer and made non-static | ||
61 | * We still have to be careful here, this function can be called after exit | ||
62 | */ | ||
63 | #define MAX_MESSAGE_SIZE 2048 | ||
64 | |||
65 | #ifdef _WIN32 | ||
66 | // Variables for the console | ||
67 | HWND con_hWnd=0; | ||
68 | HFONT OemFont; | ||
69 | LONG OemWidth, OemHeight; | ||
70 | int ConWidth,ConHeight; | ||
71 | char szConName[] = "PrBoomConWinClass"; | ||
72 | char Lines[(80+2)*25+1]; | ||
73 | char *Last = NULL; | ||
74 | boolean console_inited=FALSE; | ||
75 | static boolean should_exit = 0; | ||
76 | |||
77 | static CALLBACK ConWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) | ||
78 | { | ||
79 | PAINTSTRUCT paint; | ||
80 | HDC dc; | ||
81 | |||
82 | switch (iMsg) { | ||
83 | case WM_KEYDOWN: | ||
84 | if (wParam == VK_ESCAPE) | ||
85 | should_exit = 1; | ||
86 | break; | ||
87 | case WM_CLOSE: | ||
88 | return 1; | ||
89 | break; | ||
90 | case WM_PAINT: | ||
91 | if (dc = BeginPaint (con_hWnd, &paint)) | ||
92 | { | ||
93 | if (Last) | ||
94 | { | ||
95 | char *row; | ||
96 | int line, last; | ||
97 | |||
98 | line = paint.rcPaint.top / OemHeight; | ||
99 | last = paint.rcPaint.bottom / OemHeight; | ||
100 | for (row = Lines + (line*(80+2)); line < last; line++) | ||
101 | { | ||
102 | if (row[1]>0) | ||
103 | TextOut (dc, 0, line * OemHeight, &row[2], row[1]); | ||
104 | row += 80 + 2; | ||
105 | } | ||
106 | } | ||
107 | EndPaint (con_hWnd, &paint); | ||
108 | } | ||
109 | return 0; | ||
110 | break; | ||
111 | default: | ||
112 | break; | ||
113 | } | ||
114 | return(DefWindowProc(hwnd,iMsg,wParam,lParam)); | ||
115 | } | ||
116 | |||
117 | static void I_PrintStr (int xp, const char *cp, int count, BOOL scroll) { | ||
118 | RECT rect; | ||
119 | HDC conDC; | ||
120 | |||
121 | if ((!con_hWnd) || (!console_inited)) | ||
122 | return; | ||
123 | if (count) | ||
124 | { | ||
125 | conDC=GetDC(con_hWnd); | ||
126 | TextOut (conDC, xp * OemWidth, ConHeight - OemHeight, cp, count); | ||
127 | ReleaseDC(con_hWnd,conDC); | ||
128 | } | ||
129 | if (scroll) { | ||
130 | rect.left = 0; | ||
131 | rect.top = 0; | ||
132 | rect.right = ConWidth; | ||
133 | rect.bottom = ConHeight; | ||
134 | ScrollWindowEx (con_hWnd, 0, -OemHeight, NULL, &rect, NULL, NULL, SW_ERASE|SW_INVALIDATE); | ||
135 | UpdateWindow (con_hWnd); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | static int I_ConPrintString (const char *outline) | ||
140 | { | ||
141 | const char *cp, *newcp; | ||
142 | static int xp = 0; | ||
143 | int newxp; | ||
144 | BOOL scroll; | ||
145 | |||
146 | if (!console_inited) | ||
147 | return 0; | ||
148 | cp = outline; | ||
149 | while (*cp) { | ||
150 | for (newcp = cp, newxp = xp; | ||
151 | *newcp != '\n' && *newcp != '\0' && newxp < 80; | ||
152 | newcp++) { | ||
153 | if (*newcp == '\x08') { | ||
154 | newxp--; | ||
155 | break; | ||
156 | } | ||
157 | else if (*newcp == '\t') { | ||
158 | newxp = ((newxp + 8) / 8) * 8; | ||
159 | break; | ||
160 | } | ||
161 | else | ||
162 | newxp++; | ||
163 | } | ||
164 | |||
165 | if (*cp) { | ||
166 | const char *poop; | ||
167 | int x; | ||
168 | |||
169 | for (x = xp, poop = cp; poop < newcp; poop++, x++) { | ||
170 | Last[x+2] = ((*poop) < 32) ? 32 : (*poop); | ||
171 | } | ||
172 | |||
173 | if (*newcp == '\t') | ||
174 | for (x = xp; x < newxp; x++) | ||
175 | Last[x+2] = ' '; | ||
176 | |||
177 | if (Last[1] < xp + (newcp - cp)) | ||
178 | Last[1] = xp + (newcp - cp); | ||
179 | |||
180 | if (*newcp == '\n' || xp == 80) { | ||
181 | if (*newcp != '\n') { | ||
182 | Last[0] = 1; | ||
183 | } | ||
184 | memmove (Lines, Lines + (80 + 2), (80 + 2) * (25 - 1)); | ||
185 | Last[0] = 0; | ||
186 | Last[1] = 0; | ||
187 | newxp = 0; | ||
188 | scroll = TRUE; | ||
189 | } else { | ||
190 | scroll = FALSE; | ||
191 | } | ||
192 | I_PrintStr (xp, cp, newcp - cp, scroll); | ||
193 | |||
194 | xp = newxp; | ||
195 | |||
196 | if ((*newcp == '\n') || (*newcp == '\x08') || (*newcp == '\t')) | ||
197 | cp = newcp + 1; | ||
198 | else | ||
199 | cp = newcp; | ||
200 | } | ||
201 | } | ||
202 | |||
203 | return strlen (outline); | ||
204 | } | ||
205 | |||
206 | void I_ConTextAttr(unsigned char a) | ||
207 | { | ||
208 | int r,g,b,col; | ||
209 | HDC conDC; | ||
210 | |||
211 | if (!console_inited) | ||
212 | return; | ||
213 | conDC=GetDC(con_hWnd); | ||
214 | r=0; g=0; b=0; | ||
215 | if (a & FOREGROUND_INTENSITY) col=255; | ||
216 | else col=128; | ||
217 | if (a & FOREGROUND_RED) r=col; | ||
218 | if (a & FOREGROUND_GREEN) g=col; | ||
219 | if (a & FOREGROUND_BLUE) b=col; | ||
220 | SetTextColor(conDC, PALETTERGB(r,g,b)); | ||
221 | r=0; g=0; b=0; | ||
222 | if (a & BACKGROUND_INTENSITY) col=255; | ||
223 | else col=128; | ||
224 | if (a & BACKGROUND_RED) r=col; | ||
225 | if (a & BACKGROUND_GREEN) g=col; | ||
226 | if (a & BACKGROUND_BLUE) b=col; | ||
227 | SetBkColor(conDC, PALETTERGB(r,g,b)); | ||
228 | ReleaseDC(con_hWnd,conDC); | ||
229 | } | ||
230 | |||
231 | void I_UpdateConsole(void) | ||
232 | { | ||
233 | MSG msg; | ||
234 | |||
235 | UpdateWindow(con_hWnd); | ||
236 | while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) > 0) | ||
237 | { | ||
238 | TranslateMessage(&msg); | ||
239 | DispatchMessage(&msg); | ||
240 | } | ||
241 | if (should_exit) | ||
242 | exit(0); | ||
243 | } | ||
244 | |||
245 | static void Init_Console(void) | ||
246 | { | ||
247 | memset(Lines,0,25*(80+2)+1); | ||
248 | Last = Lines + (25 - 1) * (80 + 2); | ||
249 | console_inited=TRUE; | ||
250 | } | ||
251 | |||
252 | int Init_ConsoleWin(void) | ||
253 | { | ||
254 | HDC conDC; | ||
255 | WNDCLASS wndclass; | ||
256 | TEXTMETRIC metrics; | ||
257 | RECT cRect; | ||
258 | int width,height; | ||
259 | int scr_width,scr_height; | ||
260 | HINSTANCE hInstance; | ||
261 | char titlebuffer[2048]; | ||
262 | |||
263 | if (con_hWnd) | ||
264 | return TRUE; | ||
265 | hInstance = GetModuleHandle(NULL); | ||
266 | Init_Console(); | ||
267 | /* Register the frame class */ | ||
268 | wndclass.style = CS_OWNDC; | ||
269 | wndclass.lpfnWndProc = (WNDPROC)ConWndProc; | ||
270 | wndclass.cbClsExtra = 0; | ||
271 | wndclass.cbWndExtra = 0; | ||
272 | wndclass.hInstance = hInstance; | ||
273 | wndclass.hIcon = LoadIcon (hInstance, IDI_WINLOGO); | ||
274 | wndclass.hCursor = LoadCursor (NULL,IDC_ARROW); | ||
275 | wndclass.hbrBackground = (HBRUSH)GetStockObject (BLACK_BRUSH); | ||
276 | wndclass.lpszMenuName = szConName; | ||
277 | wndclass.lpszClassName = szConName; | ||
278 | |||
279 | if (!RegisterClass(&wndclass)) | ||
280 | return FALSE; | ||
281 | |||
282 | width=100; | ||
283 | height=100; | ||
284 | strcpy(titlebuffer,PACKAGE); | ||
285 | strcat(titlebuffer," "); | ||
286 | strcat(titlebuffer,VERSION); | ||
287 | strcat(titlebuffer," console"); | ||
288 | con_hWnd = CreateWindow(szConName, titlebuffer, | ||
289 | WS_CAPTION | WS_POPUP, | ||
290 | 0, 0, width, height, | ||
291 | NULL, NULL, hInstance, NULL); | ||
292 | conDC=GetDC(con_hWnd); | ||
293 | OemFont = GetStockObject(OEM_FIXED_FONT); | ||
294 | SelectObject(conDC, OemFont); | ||
295 | GetTextMetrics(conDC, &metrics); | ||
296 | OemWidth = metrics.tmAveCharWidth; | ||
297 | OemHeight = metrics.tmHeight; | ||
298 | GetClientRect(con_hWnd, &cRect); | ||
299 | width += (OemWidth * 80) - cRect.right; | ||
300 | height += (OemHeight * 25) - cRect.bottom; | ||
301 | // proff 11/09/98: Added code for centering console | ||
302 | scr_width = GetSystemMetrics(SM_CXFULLSCREEN); | ||
303 | scr_height = GetSystemMetrics(SM_CYFULLSCREEN); | ||
304 | MoveWindow(con_hWnd, (scr_width-width)/2, (scr_height-height)/2, width, height, TRUE); | ||
305 | GetClientRect(con_hWnd, &cRect); | ||
306 | ConWidth = cRect.right; | ||
307 | ConHeight = cRect.bottom; | ||
308 | SetTextColor(conDC, RGB(192,192,192)); | ||
309 | SetBkColor(conDC, RGB(0,0,0)); | ||
310 | SetBkMode(conDC, OPAQUE); | ||
311 | ReleaseDC(con_hWnd,conDC); | ||
312 | ShowWindow(con_hWnd, SW_SHOW); | ||
313 | UpdateWindow(con_hWnd); | ||
314 | return TRUE; | ||
315 | } | ||
316 | |||
317 | void Done_ConsoleWin(void) | ||
318 | { | ||
319 | if (con_hWnd) | ||
320 | DestroyWindow(con_hWnd); | ||
321 | UnregisterClass(szConName,GetModuleHandle(NULL)); | ||
322 | con_hWnd=0; | ||
323 | } | ||
324 | #endif | ||
325 | |||
326 | int lprintf(OutputLevels pri, const char *s, ...) | ||
327 | { | ||
328 | int r=0; | ||
329 | char msg[MAX_MESSAGE_SIZE]; | ||
330 | int lvl=pri; | ||
331 | |||
332 | va_list v; | ||
333 | va_start(v,s); | ||
334 | #ifdef HAVE_VSNPRINTF | ||
335 | vsnprintf(msg,sizeof(msg),s,v); /* print message in buffer */ | ||
336 | #else | ||
337 | vsprintf(msg,s,v); | ||
338 | #endif | ||
339 | va_end(v); | ||
340 | |||
341 | if (lvl&cons_output_mask) /* mask output as specified */ | ||
342 | { | ||
343 | r=fprintf(stdout,"%s",msg); | ||
344 | #ifdef _WIN32 | ||
345 | I_ConPrintString(msg); | ||
346 | #endif | ||
347 | } | ||
348 | if (!isatty(1) && lvl&cons_error_mask) /* if stdout redirected */ | ||
349 | r=fprintf(stderr,"%s",msg); /* select output at console */ | ||
350 | |||
351 | return r; | ||
352 | } | ||
353 | |||
354 | /* | ||
355 | * I_Error | ||
356 | * | ||
357 | * cphipps - moved out of i_* headers, to minimise source files that depend on | ||
358 | * the low-level headers. All this does is print the error, then call the | ||
359 | * low-level safe exit function. | ||
360 | * killough 3/20/98: add const | ||
361 | */ | ||
362 | |||
363 | void I_Error(const char *error, ...) | ||
364 | { | ||
365 | char errmsg[MAX_MESSAGE_SIZE]; | ||
366 | va_list argptr; | ||
367 | va_start(argptr,error); | ||
368 | #ifdef HAVE_VSNPRINTF | ||
369 | vsnprintf(errmsg,sizeof(errmsg),error,argptr); | ||
370 | #else | ||
371 | vsprintf(errmsg,error,argptr); | ||
372 | #endif | ||
373 | va_end(argptr); | ||
374 | lprintf(LO_ERROR, "%s\n", errmsg); | ||
375 | #ifdef _MSC_VER | ||
376 | if (!M_CheckParm ("-nodraw")) { | ||
377 | //Init_ConsoleWin(); | ||
378 | MessageBox(con_hWnd,errmsg,"PrBoom",MB_OK | MB_TASKMODAL | MB_TOPMOST); | ||
379 | } | ||
380 | #endif | ||
381 | I_SafeExit(-1); | ||
382 | } | ||