2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on the
11 * $Logfile: /Freespace2/code/OsApi/OutWnd.cpp $
16 * Routines for debugging output
19 * Revision 1.1 2004/12/15 04:10:45 taylor
20 * outwnd_unix.cpp from fs2_open for logging to file in debug mode
21 * fixes for default function values
22 * always use vm_* functions for sanity sake
23 * make cfilearchiver 64-bit compatible
24 * fix crash on exit from double free()
25 * fix crash on startup from extra long GL extension string in debug
27 * Revision 2.4 2004/07/26 17:50:02 Goober5000
28 * last bit of Unix fixorage
31 * Revision 2.3 2003/03/18 10:07:05 unknownplayer
32 * The big DX/main line merge. This has been uploaded to the main CVS since I can't manage to get it to upload to the DX branch. Apologies to all who may be affected adversely, but I'll work to debug it as fast as I can.
34 * Revision 2.2.2.1 2002/11/04 21:25:00 randomtiger
36 * When running in D3D all ani's are memory mapped for speed, this takes up more memory but stops gametime locking of textures which D3D8 hates.
37 * Added new command line tag Cmdline_d3dlowmem for people who dont want to make use of this because they have no memory.
38 * Cleaned up some more texture stuff enabled console debug for D3D.
40 * Revision 2.2 2002/08/01 01:41:09 penguin
41 * The big include file move
43 * Revision 2.1 2002/07/29 20:12:02 penguin
44 * removed bogus #include windows.h
46 * Revision 2.0 2002/06/03 04:10:40 penguin
49 * Revision 1.3 2002/05/21 15:46:27 mharris
50 * Turned on debug logging to file
52 * Revision 1.2 2002/05/17 23:41:41 mharris
53 * We can print even if not inited... also flush after print
55 * Revision 1.1 2002/05/16 00:47:21 mharris
56 * New version of OsApi files for Unix variants.
58 * Revision 1.2 2002/05/09 13:52:26 mharris
59 * Removed dead test code
61 * Revision 1.1 2002/05/02 18:03:12 mharris
62 * Initial checkin - converted filenames and includes to lower case
65 * 6 6/03/99 6:37p Dave
66 * More TNT fun. Made perspective bitmaps more flexible.
68 * 5 6/02/99 6:18p Dave
69 * Fixed TNT lockup problems! Wheeeee!
71 * 4 12/14/98 12:13p Dave
72 * Spiffed up xfer system a bit. Put in support for squad logo file xfer.
75 * 3 10/08/98 2:38p Dave
76 * Cleanup up OsAPI code significantly. Removed old functions, centralized
79 * 2 10/07/98 10:53a Dave
82 * 1 10/07/98 10:50a Dave
84 * 49 5/15/98 3:36p John
85 * Fixed bug with new graphics window code and standalone server. Made
86 * hwndApp not be a global anymore.
88 * 48 5/14/98 5:42p John
89 * Revamped the whole window position/mouse code for the graphics windows.
91 * 47 5/14/98 11:24a Allender
92 * throw mprints to outtext regardless of gr mode
94 * 46 4/30/98 4:53p John
95 * Restructured and cleaned up cfile code. Added capability to read off
96 * of CD-ROM drive and out of multiple pack files.
98 * 45 4/16/98 6:31p Dave
99 * Doubled MAX_FILTERS to 48
101 * 44 3/31/98 5:18p John
102 * Removed demo/save/restore. Made NDEBUG defined compile. Removed a
103 * bunch of debug stuff out of player file. Made model code be able to
104 * unload models and malloc out only however many models are needed.
107 * 43 3/11/98 12:06p John
108 * Made it so output window never gets focus upon startup
110 * 42 2/16/98 9:47a John
111 * Made so only error, general, and warning are shown if no
112 * debug_filter.cfg and .cfg file isn't saved if so.
114 * 41 2/05/98 9:21p John
115 * Some new Direct3D code. Added code to monitor a ton of stuff in the
118 * 40 1/15/98 9:14p John
119 * Made it so general, error and warning can't be turned off.
121 * 39 9/13/97 10:44a Lawrance
122 * allow logging of nprintf output to file
124 * 38 8/23/97 11:32a Dave
125 * Made debug window size correctly in standalone mode.
127 * 37 8/22/97 3:42p Hoffoss
128 * Lowered the filter limit to 24, and added support for filter recycling,
129 * instead of the rather nasty SDL_assert if we should happen to exceed this
132 * 36 8/05/97 4:29p Dave
133 * Futzed with window sizes/placements for standalone mode.
135 * 35 8/04/97 3:15p Dave
136 * Added an include for systemvars.h
138 * 34 5/20/97 1:13p Allender
139 * fixes to make outwnd work better under Win95
141 * 33 5/14/97 11:08a John
142 * fixed bug under 95 that occasionally hung program.
144 * 32 5/07/97 3:01p Lawrance
145 * check for NT in mono_init
147 * 31 5/07/97 3:06p John
148 * disabled new mono direct stuff under NT.
150 * 30 5/07/97 2:59p John
151 * Made so mono driver works under '95.
153 * 29 4/22/97 10:56a John
154 * fixed some resource leaks.
168 #include "osregistry.h"
170 #include "cfilesystem.h"
173 void outwnd_print(const char *id, const char *tmp);
175 #define MAX_FILTERS 48
176 #define MAX_LINE_WIDTH 128
178 bool outwnd_inited = false;
179 bool outwnd_disabled = true;
180 bool OutputActive = false;
181 int Outwnd_no_filter_file = 0; // 0 = .cfg file found, 1 = not found and warning not printed yet, 2 = not found and warning printed
183 struct outwnd_filter_struct {
184 char name[FILTER_NAME_LENGTH];
186 } *outwnd_filter[MAX_FILTERS], real_outwnd_filter[MAX_FILTERS];
189 int outwnd_filter_count = 0;
190 int outwnd_filter_loaded = 0;
192 // used for file logging
193 int Log_debug_output_to_file = 1;
195 const char *Freespace_logfilename = "fs_debug.log";
197 void load_filter_info(void)
201 char inbuf[FILTER_NAME_LENGTH+4];
204 outwnd_filter_loaded = 1;
205 outwnd_filter_count = 0;
207 if ( cfile_init_paths() ) {
211 SDL_snprintf(pathname, sizeof(pathname), "%s%s%sdebug_filter.cfg", Cfile_user_dir, Pathtypes[CF_TYPE_DATA].path, DIR_SEPARATOR_STR);
213 fp = fopen(pathname, "rt");
215 Outwnd_no_filter_file = 1;
217 outwnd_filter[outwnd_filter_count] = &real_outwnd_filter[outwnd_filter_count];
218 SDL_strlcpy( outwnd_filter[outwnd_filter_count]->name, "error", FILTER_NAME_LENGTH );
219 outwnd_filter[outwnd_filter_count]->state = 1;
220 outwnd_filter_count++;
222 outwnd_filter[outwnd_filter_count] = &real_outwnd_filter[outwnd_filter_count];
223 SDL_strlcpy( outwnd_filter[outwnd_filter_count]->name, "general", FILTER_NAME_LENGTH );
224 outwnd_filter[outwnd_filter_count]->state = 1;
225 outwnd_filter_count++;
227 outwnd_filter[outwnd_filter_count] = &real_outwnd_filter[outwnd_filter_count];
228 SDL_strlcpy( outwnd_filter[outwnd_filter_count]->name, "warning", FILTER_NAME_LENGTH );
229 outwnd_filter[outwnd_filter_count]->state = 1;
230 outwnd_filter_count++;
235 Outwnd_no_filter_file = 0;
237 while (fgets(inbuf, FILTER_NAME_LENGTH+3, fp))
239 if (outwnd_filter_count == MAX_FILTERS)
242 outwnd_filter[outwnd_filter_count] = &real_outwnd_filter[outwnd_filter_count];
244 outwnd_filter[outwnd_filter_count]->state = 1;
245 else if (*inbuf == '-')
246 outwnd_filter[outwnd_filter_count]->state = 0;
247 else continue; // skip everything else
249 z = strlen(inbuf) - 1;
250 if (inbuf[z] == '\n')
253 SDL_assert(strlen(inbuf+1) < FILTER_NAME_LENGTH);
254 SDL_strlcpy(outwnd_filter[outwnd_filter_count]->name, inbuf + 1, FILTER_NAME_LENGTH);
256 if ( !SDL_strcasecmp( outwnd_filter[outwnd_filter_count]->name, "error" ) ) {
257 outwnd_filter[outwnd_filter_count]->state = 1;
258 } else if ( !SDL_strcasecmp( outwnd_filter[outwnd_filter_count]->name, "general" ) ) {
259 outwnd_filter[outwnd_filter_count]->state = 1;
260 } else if ( !SDL_strcasecmp( outwnd_filter[outwnd_filter_count]->name, "warning" ) ) {
261 outwnd_filter[outwnd_filter_count]->state = 1;
264 outwnd_filter_count++;
267 if (ferror(fp) && !feof(fp))
268 nprintf(("Error", "Error reading \"%s\"\n", pathname));
273 void save_filter_info(void)
279 if (!outwnd_filter_loaded)
282 if ( Outwnd_no_filter_file ) {
283 return; // No file, don't save
286 if ( cfile_init_paths() ) {
290 SDL_snprintf(pathname, sizeof(pathname), "%s%s%sdebug_filter.cfg", Cfile_user_dir, Pathtypes[CF_TYPE_DATA].path, DIR_SEPARATOR_STR);
292 fp = fopen(pathname, "wt");
295 for (i=0; i<outwnd_filter_count; i++)
296 fprintf(fp, "%c%s\n", outwnd_filter[i]->state ? '+' : '-', outwnd_filter[i]->name);
302 void outwnd_printf2(const char *format, ...)
304 char tmp[MAX_LINE_WIDTH*4];
307 va_start(args, format);
308 SDL_vsnprintf(tmp, sizeof(tmp), format, args);
310 outwnd_print("General", tmp);
313 void outwnd_printf(const char *id, const char *format, ...)
315 char tmp[MAX_LINE_WIDTH*4];
318 va_start(args, format);
319 SDL_vsnprintf(tmp, sizeof(tmp), format, args);
321 outwnd_print(id, tmp);
324 void outwnd_print(const char *id, const char *tmp)
327 outwnd_filter_struct *temp;
329 if (!outwnd_inited) {
330 fputs("outwnd not initialized yet... ", stdout);
336 if ( Outwnd_no_filter_file == 1 ) {
337 Outwnd_no_filter_file = 2;
339 outwnd_print( "general", "==========================================================================\n" );
340 outwnd_print( "general", "DEBUG SPEW: No debug_filter.cfg found, so only general, error, and warning\n" );
341 outwnd_print( "general", "categories can be shown and no debug_filter.cfg info will be saved.\n" );
342 outwnd_print( "general", "==========================================================================\n" );
348 for (i=0; i<outwnd_filter_count; i++)
349 if (!SDL_strcasecmp(id, outwnd_filter[i]->name))
353 if (i == outwnd_filter_count) // new id found that's not yet in filter list
355 // Only create new filters if there was a filter file
356 if ( Outwnd_no_filter_file ) {
360 if (outwnd_filter_count >= MAX_FILTERS) {
361 SDL_assert(outwnd_filter_count == MAX_FILTERS); // how did it get over the max? Very bad..
362 outwnd_printf("General", "Outwnd filter limit reached. Recycling \"%s\" to add \"%s\"",
363 outwnd_filter[MAX_FILTERS - 1]->name, id);
365 i--; // overwrite the last element (oldest used filter in the list)
368 SDL_assert(strlen(id) < FILTER_NAME_LENGTH);
369 outwnd_filter[i] = &real_outwnd_filter[i]; // note: this assumes the list doesn't have gaps (from deleting an element for example)
370 SDL_strlcpy(outwnd_filter[i]->name, id, FILTER_NAME_LENGTH);
371 outwnd_filter[i]->state = 1;
372 outwnd_filter_count = i + 1;
376 // sort the filters from most recently used to oldest, so oldest ones will get recycled first
377 temp = outwnd_filter[i];
379 outwnd_filter[i + 1] = outwnd_filter[i];
382 outwnd_filter[i] = temp;
384 if (!outwnd_filter[i]->state)
387 if ( Log_debug_output_to_file ) {
388 if ( Log_fp != NULL ) {
399 void outwnd_init(int display_under_freespace_window)
401 if ( cfile_init_paths() ) {
405 outwnd_inited = TRUE;
409 SDL_snprintf(pathname, sizeof(pathname), "%s%s%s%s", Cfile_user_dir, Pathtypes[CF_TYPE_DATA].path, DIR_SEPARATOR_STR, Freespace_logfilename);
410 cf_create_directory(CF_TYPE_DATA);
412 if ( Log_fp == NULL ) {
413 Log_fp = fopen(pathname, "wb");
414 if ( Log_fp == NULL ) {
415 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "Warning!", "Unable to open debug log file. Debug output will not be saved.", NULL);
422 if ( Log_fp != NULL ) {