lprintf.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  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. #ifdef HAVE_CONFIG_H
  36. #include "config.h"
  37. #endif
  38. #ifdef _WIN32
  39. #define WIN32_LEAN_AND_MEAN
  40. #include <windows.h>
  41. #endif
  42. #ifdef _MSC_VER
  43. #include <io.h>
  44. #endif
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <stdarg.h>
  48. #ifdef HAVE_UNISTD_H
  49. #include <unistd.h>
  50. #endif
  51. #include "doomtype.h"
  52. #include "lprintf.h"
  53. #include "i_main.h"
  54. #include "m_argv.h"
  55. int cons_error_mask = -1-LO_INFO; /* all but LO_INFO when redir'd */
  56. int cons_output_mask = -1; /* all output enabled */
  57. /* cphipps - enlarged message buffer and made non-static
  58. * We still have to be careful here, this function can be called after exit
  59. */
  60. #define MAX_MESSAGE_SIZE 2048
  61. #ifdef _WIN32
  62. // Variables for the console
  63. HWND con_hWnd=0;
  64. HFONT OemFont;
  65. LONG OemWidth, OemHeight;
  66. int ConWidth,ConHeight;
  67. char szConName[] = "PrBoomConWinClass";
  68. char Lines[(80+2)*25+1];
  69. char *Last = NULL;
  70. boolean console_inited=FALSE;
  71. static boolean should_exit = 0;
  72. static CALLBACK ConWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
  73. {
  74. PAINTSTRUCT paint;
  75. HDC dc;
  76. switch (iMsg) {
  77. case WM_KEYDOWN:
  78. if (wParam == VK_ESCAPE)
  79. should_exit = 1;
  80. break;
  81. case WM_CLOSE:
  82. return 1;
  83. break;
  84. case WM_PAINT:
  85. if (dc = BeginPaint (con_hWnd, &paint))
  86. {
  87. if (Last)
  88. {
  89. char *row;
  90. int line, last;
  91. line = paint.rcPaint.top / OemHeight;
  92. last = paint.rcPaint.bottom / OemHeight;
  93. for (row = Lines + (line*(80+2)); line < last; line++)
  94. {
  95. if (row[1]>0)
  96. TextOut (dc, 0, line * OemHeight, &row[2], row[1]);
  97. row += 80 + 2;
  98. }
  99. }
  100. EndPaint (con_hWnd, &paint);
  101. }
  102. return 0;
  103. break;
  104. default:
  105. break;
  106. }
  107. return(DefWindowProc(hwnd,iMsg,wParam,lParam));
  108. }
  109. static void I_PrintStr (int xp, const char *cp, int count, BOOL scroll) {
  110. RECT rect;
  111. HDC conDC;
  112. if ((!con_hWnd) || (!console_inited))
  113. return;
  114. if (count)
  115. {
  116. conDC=GetDC(con_hWnd);
  117. TextOut (conDC, xp * OemWidth, ConHeight - OemHeight, cp, count);
  118. ReleaseDC(con_hWnd,conDC);
  119. }
  120. if (scroll) {
  121. rect.left = 0;
  122. rect.top = 0;
  123. rect.right = ConWidth;
  124. rect.bottom = ConHeight;
  125. ScrollWindowEx (con_hWnd, 0, -OemHeight, NULL, &rect, NULL, NULL, SW_ERASE|SW_INVALIDATE);
  126. UpdateWindow (con_hWnd);
  127. }
  128. }
  129. static int I_ConPrintString (const char *outline)
  130. {
  131. const char *cp, *newcp;
  132. static int xp = 0;
  133. int newxp;
  134. BOOL scroll;
  135. if (!console_inited)
  136. return 0;
  137. cp = outline;
  138. while (*cp) {
  139. for (newcp = cp, newxp = xp;
  140. *newcp != '\n' && *newcp != '\0' && newxp < 80;
  141. newcp++) {
  142. if (*newcp == '\x08') {
  143. newxp--;
  144. break;
  145. }
  146. else if (*newcp == '\t') {
  147. newxp = ((newxp + 8) / 8) * 8;
  148. break;
  149. }
  150. else
  151. newxp++;
  152. }
  153. if (*cp) {
  154. const char *poop;
  155. int x;
  156. for (x = xp, poop = cp; poop < newcp; poop++, x++) {
  157. Last[x+2] = ((*poop) < 32) ? 32 : (*poop);
  158. }
  159. if (*newcp == '\t')
  160. for (x = xp; x < newxp; x++)
  161. Last[x+2] = ' ';
  162. if (Last[1] < xp + (newcp - cp))
  163. Last[1] = xp + (newcp - cp);
  164. if (*newcp == '\n' || xp == 80) {
  165. if (*newcp != '\n') {
  166. Last[0] = 1;
  167. }
  168. memmove (Lines, Lines + (80 + 2), (80 + 2) * (25 - 1));
  169. Last[0] = 0;
  170. Last[1] = 0;
  171. newxp = 0;
  172. scroll = TRUE;
  173. } else {
  174. scroll = FALSE;
  175. }
  176. I_PrintStr (xp, cp, newcp - cp, scroll);
  177. xp = newxp;
  178. if ((*newcp == '\n') || (*newcp == '\x08') || (*newcp == '\t'))
  179. cp = newcp + 1;
  180. else
  181. cp = newcp;
  182. }
  183. }
  184. return strlen (outline);
  185. }
  186. void I_ConTextAttr(unsigned char a)
  187. {
  188. int r,g,b,col;
  189. HDC conDC;
  190. if (!console_inited)
  191. return;
  192. conDC=GetDC(con_hWnd);
  193. r=0; g=0; b=0;
  194. if (a & FOREGROUND_INTENSITY) col=255;
  195. else col=128;
  196. if (a & FOREGROUND_RED) r=col;
  197. if (a & FOREGROUND_GREEN) g=col;
  198. if (a & FOREGROUND_BLUE) b=col;
  199. SetTextColor(conDC, PALETTERGB(r,g,b));
  200. r=0; g=0; b=0;
  201. if (a & BACKGROUND_INTENSITY) col=255;
  202. else col=128;
  203. if (a & BACKGROUND_RED) r=col;
  204. if (a & BACKGROUND_GREEN) g=col;
  205. if (a & BACKGROUND_BLUE) b=col;
  206. SetBkColor(conDC, PALETTERGB(r,g,b));
  207. ReleaseDC(con_hWnd,conDC);
  208. }
  209. void I_UpdateConsole(void)
  210. {
  211. MSG msg;
  212. UpdateWindow(con_hWnd);
  213. while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) > 0)
  214. {
  215. TranslateMessage(&msg);
  216. DispatchMessage(&msg);
  217. }
  218. if (should_exit)
  219. exit(0);
  220. }
  221. static void Init_Console(void)
  222. {
  223. memset(Lines,0,25*(80+2)+1);
  224. Last = Lines + (25 - 1) * (80 + 2);
  225. console_inited=TRUE;
  226. }
  227. int Init_ConsoleWin(void)
  228. {
  229. HDC conDC;
  230. WNDCLASS wndclass;
  231. TEXTMETRIC metrics;
  232. RECT cRect;
  233. int width,height;
  234. int scr_width,scr_height;
  235. HINSTANCE hInstance;
  236. char titlebuffer[2048];
  237. if (con_hWnd)
  238. return TRUE;
  239. hInstance = GetModuleHandle(NULL);
  240. Init_Console();
  241. /* Register the frame class */
  242. wndclass.style = CS_OWNDC;
  243. wndclass.lpfnWndProc = (WNDPROC)ConWndProc;
  244. wndclass.cbClsExtra = 0;
  245. wndclass.cbWndExtra = 0;
  246. wndclass.hInstance = hInstance;
  247. wndclass.hIcon = LoadIcon (hInstance, IDI_WINLOGO);
  248. wndclass.hCursor = LoadCursor (NULL,IDC_ARROW);
  249. wndclass.hbrBackground = (HBRUSH)GetStockObject (BLACK_BRUSH);
  250. wndclass.lpszMenuName = szConName;
  251. wndclass.lpszClassName = szConName;
  252. if (!RegisterClass(&wndclass))
  253. return FALSE;
  254. width=100;
  255. height=100;
  256. strcpy(titlebuffer,PACKAGE);
  257. strcat(titlebuffer," ");
  258. strcat(titlebuffer,VERSION);
  259. strcat(titlebuffer," console");
  260. con_hWnd = CreateWindow(szConName, titlebuffer,
  261. WS_CAPTION | WS_POPUP,
  262. 0, 0, width, height,
  263. NULL, NULL, hInstance, NULL);
  264. conDC=GetDC(con_hWnd);
  265. OemFont = GetStockObject(OEM_FIXED_FONT);
  266. SelectObject(conDC, OemFont);
  267. GetTextMetrics(conDC, &metrics);
  268. OemWidth = metrics.tmAveCharWidth;
  269. OemHeight = metrics.tmHeight;
  270. GetClientRect(con_hWnd, &cRect);
  271. width += (OemWidth * 80) - cRect.right;
  272. height += (OemHeight * 25) - cRect.bottom;
  273. // proff 11/09/98: Added code for centering console
  274. scr_width = GetSystemMetrics(SM_CXFULLSCREEN);
  275. scr_height = GetSystemMetrics(SM_CYFULLSCREEN);
  276. MoveWindow(con_hWnd, (scr_width-width)/2, (scr_height-height)/2, width, height, TRUE);
  277. GetClientRect(con_hWnd, &cRect);
  278. ConWidth = cRect.right;
  279. ConHeight = cRect.bottom;
  280. SetTextColor(conDC, RGB(192,192,192));
  281. SetBkColor(conDC, RGB(0,0,0));
  282. SetBkMode(conDC, OPAQUE);
  283. ReleaseDC(con_hWnd,conDC);
  284. ShowWindow(con_hWnd, SW_SHOW);
  285. UpdateWindow(con_hWnd);
  286. return TRUE;
  287. }
  288. void Done_ConsoleWin(void)
  289. {
  290. if (con_hWnd)
  291. DestroyWindow(con_hWnd);
  292. UnregisterClass(szConName,GetModuleHandle(NULL));
  293. con_hWnd=0;
  294. }
  295. #endif
  296. int lprintf(OutputLevels pri, const char *s, ...)
  297. {
  298. int r=0;
  299. char msg[MAX_MESSAGE_SIZE];
  300. int lvl=pri;
  301. va_list v;
  302. va_start(v,s);
  303. #ifdef HAVE_VSNPRINTF
  304. vsnprintf(msg,sizeof(msg),s,v); /* print message in buffer */
  305. #else
  306. vsprintf(msg,s,v);
  307. #endif
  308. va_end(v);
  309. if (lvl&cons_output_mask) /* mask output as specified */
  310. {
  311. r=fprintf(stdout,"%s",msg);
  312. #ifdef _WIN32
  313. I_ConPrintString(msg);
  314. #endif
  315. }
  316. if (!isatty(1) && lvl&cons_error_mask) /* if stdout redirected */
  317. r=fprintf(stderr,"%s",msg); /* select output at console */
  318. return r;
  319. }
  320. /*
  321. * I_Error
  322. *
  323. * cphipps - moved out of i_* headers, to minimise source files that depend on
  324. * the low-level headers. All this does is print the error, then call the
  325. * low-level safe exit function.
  326. * killough 3/20/98: add const
  327. */
  328. void I_Error(const char *error, ...)
  329. {
  330. char errmsg[MAX_MESSAGE_SIZE];
  331. va_list argptr;
  332. va_start(argptr,error);
  333. #ifdef HAVE_VSNPRINTF
  334. vsnprintf(errmsg,sizeof(errmsg),error,argptr);
  335. #else
  336. vsprintf(errmsg,error,argptr);
  337. #endif
  338. va_end(argptr);
  339. lprintf(LO_ERROR, "%s\n", errmsg);
  340. #ifdef _MSC_VER
  341. if (!M_CheckParm ("-nodraw")) {
  342. //Init_ConsoleWin();
  343. MessageBox(con_hWnd,errmsg,"PrBoom",MB_OK | MB_TASKMODAL | MB_TOPMOST);
  344. }
  345. #endif
  346. while( true ) {
  347. printf( " SAFE EXIT \n" );
  348. usleep(1000);
  349. }
  350. }