]> icculus.org git repositories - taylor/freespace2.git/blob - src/osapi/outwnd.cpp
don't play haptic effects when window does not have focus
[taylor/freespace2.git] / src / osapi / outwnd.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 NDEBUG
160
161 #include <stdio.h>
162 #include <stdarg.h>
163 #include <string.h>
164
165 #include "pstypes.h"
166 #include "outwnd.h"
167 #include "osapi.h"
168 #include "osregistry.h"
169 #include "cfile.h"
170 #include "cfilesystem.h"
171
172
173 extern void cf_create_directory( int dir_type );
174
175 void outwnd_print(const char *id, const char *tmp);
176
177 #define MAX_FILTERS 48
178 #define MAX_LINE_WIDTH  128
179
180 bool outwnd_inited = false;
181 bool outwnd_disabled = true;
182 bool OutputActive = false;
183 int Outwnd_no_filter_file = 0;          // 0 = .cfg file found, 1 = not found and warning not printed yet, 2 = not found and warning printed
184
185 struct outwnd_filter_struct {
186         char name[FILTER_NAME_LENGTH];
187         int state;
188 } *outwnd_filter[MAX_FILTERS], real_outwnd_filter[MAX_FILTERS];
189
190
191 int outwnd_filter_count = 0;
192 int outwnd_filter_loaded = 0;
193
194 // used for file logging
195 int Log_debug_output_to_file = 1;
196 FILE *Log_fp;
197 const char *Freespace_logfilename = "fs_debug.log";
198
199 void load_filter_info(void)
200 {
201         FILE *fp;
202         char pathname[512];
203         char inbuf[FILTER_NAME_LENGTH+4];
204         int z;
205
206         outwnd_filter_loaded = 1;
207         outwnd_filter_count = 0;
208
209         if ( cfile_init_paths() ) {
210                 return;
211         }
212
213         snprintf(pathname, sizeof(pathname), "%s%s%sdebug_filter.cfg", Cfile_user_dir, Pathtypes[CF_TYPE_DATA].path, DIR_SEPARATOR_STR);
214
215         fp = fopen(pathname, "rt");
216         if (!fp)        {
217                 Outwnd_no_filter_file = 1;
218
219                 outwnd_filter[outwnd_filter_count] = &real_outwnd_filter[outwnd_filter_count];
220                 strcpy( outwnd_filter[outwnd_filter_count]->name, "error" );
221                 outwnd_filter[outwnd_filter_count]->state = 1;
222                 outwnd_filter_count++;
223
224                 outwnd_filter[outwnd_filter_count] = &real_outwnd_filter[outwnd_filter_count];
225                 strcpy( outwnd_filter[outwnd_filter_count]->name, "general" );
226                 outwnd_filter[outwnd_filter_count]->state = 1;
227                 outwnd_filter_count++;
228
229                 outwnd_filter[outwnd_filter_count] = &real_outwnd_filter[outwnd_filter_count];
230                 strcpy( outwnd_filter[outwnd_filter_count]->name, "warning" );
231                 outwnd_filter[outwnd_filter_count]->state = 1;
232                 outwnd_filter_count++;
233
234                 return;
235         }
236
237         Outwnd_no_filter_file = 0;
238
239         while (fgets(inbuf, FILTER_NAME_LENGTH+3, fp))
240         {
241                 if (outwnd_filter_count == MAX_FILTERS)
242                         break;
243
244                 outwnd_filter[outwnd_filter_count] = &real_outwnd_filter[outwnd_filter_count];
245                 if (*inbuf == '+')
246                         outwnd_filter[outwnd_filter_count]->state = 1;
247                 else if (*inbuf == '-')
248                         outwnd_filter[outwnd_filter_count]->state = 0;
249                 else continue;  // skip everything else
250
251                 z = strlen(inbuf) - 1;
252                 if (inbuf[z] == '\n')
253                         inbuf[z] = 0;
254
255                 Assert(strlen(inbuf+1) < FILTER_NAME_LENGTH);
256                 strcpy(outwnd_filter[outwnd_filter_count]->name, inbuf + 1);
257
258                 if ( !stricmp( outwnd_filter[outwnd_filter_count]->name, "error" ) )    {
259                         outwnd_filter[outwnd_filter_count]->state = 1;
260                 } else if ( !stricmp( outwnd_filter[outwnd_filter_count]->name, "general" ) )   {
261                         outwnd_filter[outwnd_filter_count]->state = 1;
262                 } else if ( !stricmp( outwnd_filter[outwnd_filter_count]->name, "warning" ) )   {
263                         outwnd_filter[outwnd_filter_count]->state = 1;
264                 }
265
266                 outwnd_filter_count++;
267         }
268
269         if (ferror(fp) && !feof(fp))
270                 nprintf(("Error", "Error reading \"%s\"\n", pathname));
271
272         fclose(fp);
273 }
274
275 void save_filter_info(void)
276 {
277         FILE *fp;
278         int i;
279         char pathname[512];
280
281         if (!outwnd_filter_loaded)
282                 return;
283
284         if ( Outwnd_no_filter_file )    {
285                 return; // No file, don't save
286         }
287
288         if ( cfile_init_paths() ) {
289                 return;
290         }
291
292         snprintf(pathname, sizeof(pathname), "%s%s%sdebug_filter.cfg", Cfile_user_dir, Pathtypes[CF_TYPE_DATA].path, DIR_SEPARATOR_STR);
293
294         fp = fopen(pathname, "wt");
295         if (fp)
296         {
297                 for (i=0; i<outwnd_filter_count; i++)
298                         fprintf(fp, "%c%s\n", outwnd_filter[i]->state ? '+' : '-', outwnd_filter[i]->name);
299
300                 fclose(fp);
301         }
302 }
303
304 void outwnd_printf2(const char *format, ...)
305 {
306         char tmp[MAX_LINE_WIDTH*4];
307         va_list args;
308         
309         va_start(args, format);
310         vsprintf(tmp, format, args);
311         va_end(args);
312         outwnd_print("General", tmp);
313 }
314
315 void outwnd_printf(const char *id, const char *format, ...)
316 {
317         char tmp[MAX_LINE_WIDTH*4];
318         va_list args;
319         
320         va_start(args, format);
321         vsprintf(tmp, format, args);
322         va_end(args);
323         outwnd_print(id, tmp);
324 }
325
326 void outwnd_print(const char *id, const char *tmp)
327 {
328         int i;
329         outwnd_filter_struct *temp;
330
331         if (!outwnd_inited) {
332                 fputs("outwnd not initialized yet...  ", stdout);
333                 fputs(tmp, stdout);
334                 fflush(stdout);
335                 return;
336         }
337
338         if ( Outwnd_no_filter_file == 1 )       {
339                 Outwnd_no_filter_file = 2;
340
341                 outwnd_print( "general", "==========================================================================\n" );
342                 outwnd_print( "general", "DEBUG SPEW: No debug_filter.cfg found, so only general, error, and warning\n" );
343                 outwnd_print( "general", "categories can be shown and no debug_filter.cfg info will be saved.\n" );
344                 outwnd_print( "general", "==========================================================================\n" );
345         }
346
347         if (!id)
348                 id = "General";
349
350         for (i=0; i<outwnd_filter_count; i++)
351                 if (!stricmp(id, outwnd_filter[i]->name))
352                         break;
353
354
355         if (i == outwnd_filter_count)  // new id found that's not yet in filter list
356         {
357                 // Only create new filters if there was a filter file
358                 if ( Outwnd_no_filter_file )    {
359                         return;
360                 }
361
362                 if (outwnd_filter_count >= MAX_FILTERS) {
363                         Assert(outwnd_filter_count == MAX_FILTERS);  // how did it get over the max?  Very bad..
364                         outwnd_printf("General", "Outwnd filter limit reached.  Recycling \"%s\" to add \"%s\"",
365                                 outwnd_filter[MAX_FILTERS - 1]->name, id);
366
367                         i--;  // overwrite the last element (oldest used filter in the list)
368                 }
369
370                 Assert(strlen(id) < FILTER_NAME_LENGTH);
371                 outwnd_filter[i] = &real_outwnd_filter[i];  // note: this assumes the list doesn't have gaps (from deleting an element for example)
372                 strcpy(outwnd_filter[i]->name, id);
373                 outwnd_filter[i]->state = 1;
374                 outwnd_filter_count = i + 1;
375                 save_filter_info();
376         }
377
378         // sort the filters from most recently used to oldest, so oldest ones will get recycled first
379         temp = outwnd_filter[i];
380         while (i--)
381                 outwnd_filter[i + 1] = outwnd_filter[i];
382
383         i++;
384         outwnd_filter[i] = temp;
385
386         if (!outwnd_filter[i]->state)
387                 return;
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
400
401 void outwnd_init(int display_under_freespace_window)
402 {
403         if ( cfile_init_paths() ) {
404                 return;
405         }
406
407         outwnd_inited = TRUE;
408
409         char pathname[512];
410
411         snprintf(pathname, sizeof(pathname), "%s%s%s%s", Cfile_user_dir, Pathtypes[CF_TYPE_DATA].path, DIR_SEPARATOR_STR, Freespace_logfilename);
412         cf_create_directory(CF_TYPE_DATA);
413
414         if ( Log_fp == NULL ) {
415                 Log_fp = fopen(pathname, "wb");
416                 if ( Log_fp == NULL ) {
417                         outwnd_printf("Error", "Error opening %s\n", pathname);
418                 } else {
419                         outwnd_printf("General", "Opened %s OK\n", pathname);
420                 //      printf("Future debug output directed to: %s\n", pathname);
421                 }
422         }
423 }
424
425 void outwnd_close()
426 {
427         if ( Log_fp != NULL ) {
428                 fclose(Log_fp);
429                 Log_fp = NULL;
430         }
431 }
432
433 #endif // NDEBUG