]> icculus.org git repositories - taylor/freespace2.git/blob - src/osapi/outwnd_unix.cpp
const-char warning fixes
[taylor/freespace2.git] / src / osapi / outwnd_unix.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
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 
6  * source.
7  *
8 */
9
10 /*
11  * $Logfile: /Freespace2/code/OsApi/OutWnd.cpp $
12  * $Revision$
13  * $Date$
14  * $Author$
15  *
16  * Routines for debugging output
17  *
18  * $Log$
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
26  *
27  * Revision 2.4  2004/07/26 17:50:02  Goober5000
28  * last bit of Unix fixorage
29  * --Goober5000
30  *
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.
33  *
34  * Revision 2.2.2.1  2002/11/04 21:25:00  randomtiger
35  *
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.
39  *
40  * Revision 2.2  2002/08/01 01:41:09  penguin
41  * The big include file move
42  *
43  * Revision 2.1  2002/07/29 20:12:02  penguin
44  * removed bogus #include windows.h
45  *
46  * Revision 2.0  2002/06/03 04:10:40  penguin
47  * Warpcore CVS sync
48  *
49  * Revision 1.3  2002/05/21 15:46:27  mharris
50  * Turned on debug logging to file
51  *
52  * Revision 1.2  2002/05/17 23:41:41  mharris
53  * We can print even if not inited... also flush after print
54  *
55  * Revision 1.1  2002/05/16 00:47:21  mharris
56  * New version of OsApi files for Unix variants.
57  *
58  * Revision 1.2  2002/05/09 13:52:26  mharris
59  * Removed dead test code
60  *
61  * Revision 1.1  2002/05/02 18:03:12  mharris
62  * Initial checkin - converted filenames and includes to lower case
63  *
64  * 
65  * 6     6/03/99 6:37p Dave
66  * More TNT fun. Made perspective bitmaps more flexible.
67  * 
68  * 5     6/02/99 6:18p Dave
69  * Fixed TNT lockup problems! Wheeeee!
70  * 
71  * 4     12/14/98 12:13p Dave
72  * Spiffed up xfer system a bit. Put in support for squad logo file xfer.
73  * Need to test now.
74  * 
75  * 3     10/08/98 2:38p Dave
76  * Cleanup up OsAPI code significantly. Removed old functions, centralized
77  * registry functions.
78  * 
79  * 2     10/07/98 10:53a Dave
80  * Initial checkin.
81  * 
82  * 1     10/07/98 10:50a Dave
83  * 
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.
87  * 
88  * 48    5/14/98 5:42p John
89  * Revamped the whole window position/mouse code for the graphics windows.
90  * 
91  * 47    5/14/98 11:24a Allender
92  * throw mprints to outtext regardless of gr mode
93  * 
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.
97  * 
98  * 45    4/16/98 6:31p Dave
99  * Doubled MAX_FILTERS to 48
100  * 
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.
105  *  
106  * 
107  * 43    3/11/98 12:06p John
108  * Made it so output window never gets focus upon startup
109  * 
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.
113  * 
114  * 41    2/05/98 9:21p John
115  * Some new Direct3D code.   Added code to monitor a ton of stuff in the
116  * game.
117  * 
118  * 40    1/15/98 9:14p John
119  * Made it so general, error and warning can't be turned off.
120  * 
121  * 39    9/13/97 10:44a Lawrance
122  * allow logging of nprintf output to file
123  * 
124  * 38    8/23/97 11:32a Dave
125  * Made debug window size correctly in standalone mode.
126  * 
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 Assert if we should happen to exceed this
130  * limit.
131  * 
132  * 36    8/05/97 4:29p Dave
133  * Futzed with window sizes/placements for standalone mode.
134  * 
135  * 35    8/04/97 3:15p Dave
136  * Added an include for systemvars.h
137  * 
138  * 34    5/20/97 1:13p Allender
139  * fixes to make outwnd work better under Win95
140  * 
141  * 33    5/14/97 11:08a John
142  * fixed bug under 95 that occasionally hung program.
143  * 
144  * 32    5/07/97 3:01p Lawrance
145  * check for NT in mono_init
146  * 
147  * 31    5/07/97 3:06p John
148  * disabled new mono direct stuff under NT.
149  * 
150  * 30    5/07/97 2:59p John
151  * Made so mono driver works under '95.
152  * 
153  * 29    4/22/97 10:56a John
154  * fixed some resource leaks.
155  *
156  * $NoKeywords: $
157  */
158
159 #ifndef WIN32   // Goober5000
160
161 #ifndef NDEBUG
162
163 #include <stdio.h>
164 #include <stdarg.h>
165 #include <string.h>
166
167 #include "pstypes.h"
168 #include "outwnd.h"
169 #include "osapi.h"
170 #include "osregistry.h"
171 #include "cfile.h"
172 #include "cfilesystem.h"
173
174 extern cf_pathtype Pathtypes[CF_MAX_PATH_TYPES];
175
176
177 void outwnd_print(const char *id, const char *tmp);
178
179 #define MAX_FILTERS 48
180 #define MAX_LINE_WIDTH  128
181
182 bool outwnd_inited = false;
183 bool outwnd_disabled = true;
184 bool OutputActive = false;
185 int Outwnd_no_filter_file = 0;          // 0 = .cfg file found, 1 = not found and warning not printed yet, 2 = not found and warning printed
186
187 struct outwnd_filter_struct {
188         char name[FILTER_NAME_LENGTH];
189         int state;
190 } *outwnd_filter[MAX_FILTERS], real_outwnd_filter[MAX_FILTERS];
191
192
193 int outwnd_filter_count = 0;
194 int outwnd_filter_loaded = 0;
195
196 // used for file logging
197 #ifndef NDEBUG
198         int Log_debug_output_to_file = 1;
199         FILE *Log_fp;
200         const char *Freespace_logfilename = "fs_debug.log";
201 #endif
202
203 void load_filter_info(void)
204 {
205         FILE *fp;
206         char pathname[MAX_PATH_LEN];
207         char inbuf[FILTER_NAME_LENGTH+4];
208         int z;
209
210         outwnd_filter_loaded = 1;
211         outwnd_filter_count = 0;
212
213         snprintf(pathname, MAX_PATH_LEN, "%s/%s/%s/", detect_home(), Osreg_user_dir, Pathtypes[CF_TYPE_DATA].path);
214         strcat(pathname, "debug_filter.cfg" );
215
216         fp = fopen(pathname, "rt");
217         if (!fp)        {
218                 Outwnd_no_filter_file = 1;
219
220                 outwnd_filter[outwnd_filter_count] = &real_outwnd_filter[outwnd_filter_count];
221                 strcpy( outwnd_filter[outwnd_filter_count]->name, "error" );
222                 outwnd_filter[outwnd_filter_count]->state = 1;
223                 outwnd_filter_count++;
224
225                 outwnd_filter[outwnd_filter_count] = &real_outwnd_filter[outwnd_filter_count];
226                 strcpy( outwnd_filter[outwnd_filter_count]->name, "general" );
227                 outwnd_filter[outwnd_filter_count]->state = 1;
228                 outwnd_filter_count++;
229
230                 outwnd_filter[outwnd_filter_count] = &real_outwnd_filter[outwnd_filter_count];
231                 strcpy( outwnd_filter[outwnd_filter_count]->name, "warning" );
232                 outwnd_filter[outwnd_filter_count]->state = 1;
233                 outwnd_filter_count++;
234
235                 return;
236         }
237
238         Outwnd_no_filter_file = 0;
239
240         while (fgets(inbuf, FILTER_NAME_LENGTH+3, fp))
241         {
242                 if (outwnd_filter_count == MAX_FILTERS)
243                         break;
244
245                 outwnd_filter[outwnd_filter_count] = &real_outwnd_filter[outwnd_filter_count];
246                 if (*inbuf == '+')
247                         outwnd_filter[outwnd_filter_count]->state = 1;
248                 else if (*inbuf == '-')
249                         outwnd_filter[outwnd_filter_count]->state = 0;
250                 else continue;  // skip everything else
251
252                 z = strlen(inbuf) - 1;
253                 if (inbuf[z] == '\n')
254                         inbuf[z] = 0;
255
256                 Assert(strlen(inbuf+1) < FILTER_NAME_LENGTH);
257                 strcpy(outwnd_filter[outwnd_filter_count]->name, inbuf + 1);
258
259                 if ( !stricmp( outwnd_filter[outwnd_filter_count]->name, "error" ) )    {
260                         outwnd_filter[outwnd_filter_count]->state = 1;
261                 } else if ( !stricmp( outwnd_filter[outwnd_filter_count]->name, "general" ) )   {
262                         outwnd_filter[outwnd_filter_count]->state = 1;
263                 } else if ( !stricmp( outwnd_filter[outwnd_filter_count]->name, "warning" ) )   {
264                         outwnd_filter[outwnd_filter_count]->state = 1;
265                 }
266
267                 outwnd_filter_count++;
268         }
269
270         if (ferror(fp) && !feof(fp))
271                 nprintf(("Error", "Error reading \"%s\"\n", pathname));
272
273         fclose(fp);
274 }
275
276 void save_filter_info(void)
277 {
278         FILE *fp;
279         int i;
280         char pathname[MAX_PATH_LEN];
281
282         if (!outwnd_filter_loaded)
283                 return;
284
285         if ( Outwnd_no_filter_file )    {
286                 return; // No file, don't save
287         }
288
289         snprintf(pathname, MAX_PATH_LEN, "%s/%s/%s/", detect_home(), Osreg_user_dir, Pathtypes[CF_TYPE_DATA].path);
290         strcat(pathname, "debug_filter.cfg" );
291
292         fp = fopen(pathname, "wt");
293         if (fp)
294         {
295                 for (i=0; i<outwnd_filter_count; i++)
296                         fprintf(fp, "%c%s\n", outwnd_filter[i]->state ? '+' : '-', outwnd_filter[i]->name);
297
298                 fclose(fp);
299         }
300 }
301
302 void outwnd_printf2(const char *format, ...)
303 {
304         char tmp[MAX_LINE_WIDTH*4];
305         va_list args;
306         
307         va_start(args, format);
308         vsprintf(tmp, format, args);
309         va_end(args);
310         outwnd_print("General", tmp);
311 }
312
313 void outwnd_printf(const char *id, const char *format, ...)
314 {
315         char tmp[MAX_LINE_WIDTH*4];
316         va_list args;
317         
318         va_start(args, format);
319         vsprintf(tmp, format, args);
320         va_end(args);
321         outwnd_print(id, tmp);
322 }
323
324 void outwnd_print(const char *id, const char *tmp)
325 {
326         int i;
327         outwnd_filter_struct *temp;
328
329         if (!outwnd_inited) {
330                 fputs("outwnd not initialized yet...  ", stdout);
331                 fputs(tmp, stdout);
332                 fflush(stdout);
333                 return;
334         }
335
336         if ( Outwnd_no_filter_file == 1 )       {
337                 Outwnd_no_filter_file = 2;
338
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" );
343         }
344
345         if (!id)
346                 id = "General";
347
348         for (i=0; i<outwnd_filter_count; i++)
349                 if (!stricmp(id, outwnd_filter[i]->name))
350                         break;
351
352
353         if (i == outwnd_filter_count)  // new id found that's not yet in filter list
354         {
355                 // Only create new filters if there was a filter file
356                 if ( Outwnd_no_filter_file )    {
357                         return;
358                 }
359
360                 if (outwnd_filter_count >= MAX_FILTERS) {
361                         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);
364
365                         i--;  // overwrite the last element (oldest used filter in the list)
366                 }
367
368                 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                 strcpy(outwnd_filter[i]->name, id);
371                 outwnd_filter[i]->state = 1;
372                 outwnd_filter_count = i + 1;
373                 save_filter_info();
374         }
375
376         // sort the filters from most recently used to oldest, so oldest ones will get recycled first
377         temp = outwnd_filter[i];
378         while (i--)
379                 outwnd_filter[i + 1] = outwnd_filter[i];
380
381         i++;
382         outwnd_filter[i] = temp;
383
384         if (!outwnd_filter[i]->state)
385                 return;
386
387 #ifndef NDEBUG
388
389         if ( Log_debug_output_to_file ) {
390                 if ( Log_fp != NULL ) {
391                         fputs(tmp, Log_fp);     
392                         fflush(Log_fp);
393                 }
394         } else {
395                 fputs(tmp, stdout);
396                 fflush(stdout);
397         }
398
399 #else
400
401         fputs(tmp, stdout);
402         fflush(stdout);
403
404 #endif
405 }
406
407
408 void outwnd_init(int display_under_freespace_window)
409 {
410         outwnd_inited = TRUE;
411
412 #ifndef NDEBUG
413         char pathname[MAX_PATH_LEN];
414
415         snprintf(pathname, MAX_PATH_LEN, "%s/%s/%s/", detect_home(), Osreg_user_dir, Pathtypes[CF_TYPE_DATA].path);
416         strcat(pathname, Freespace_logfilename);
417
418         if ( Log_fp == NULL ) {
419                 Log_fp = fopen(pathname, "wb");
420                 if ( Log_fp == NULL ) {
421                         outwnd_printf("Error", "Error opening %s\n", pathname);
422                 } else {
423                         outwnd_printf("General", "Opened %s OK\n", pathname);
424                         printf("Future debug output directed to: %s\n", pathname);
425                 }
426         }
427 #endif 
428 }
429
430 void outwnd_close()
431 {
432 #ifndef NDEBUG
433         if ( Log_fp != NULL ) {
434                 fclose(Log_fp);
435                 Log_fp = NULL;
436         }
437 #endif
438
439 }
440
441 #endif // NDEBUG
442
443 #endif          // Goober5000 - #ifndef WIN32