]> git.saurik.com Git - wxWidgets.git/blame - include/wx/log.h
Restore wxEVT_MENU_CLOSE generation under Windows 95 after r70151.
[wxWidgets.git] / include / wx / log.h
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
8ca28fb7 2// Name: wx/log.h
c801d85f
KB
3// Purpose: Assorted wxLogXXX functions, and wxLog (sink for logs)
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 29/01/98
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
65571936 9// Licence: wxWindows licence
c801d85f
KB
10/////////////////////////////////////////////////////////////////////////////
11
886dd7d2
VZ
12#ifndef _WX_LOG_H_
13#define _WX_LOG_H_
c801d85f 14
df5168c4 15#include "wx/defs.h"
38830220 16
0b4f47a3 17// ----------------------------------------------------------------------------
34085a0d 18// types
0b4f47a3
DS
19// ----------------------------------------------------------------------------
20
34085a0d
VZ
21// NB: this is needed even if wxUSE_LOG == 0
22typedef unsigned long wxLogLevel;
0b4f47a3 23
34085a0d
VZ
24// the trace masks have been superseded by symbolic trace constants, they're
25// for compatibility only and will be removed soon - do NOT use them
26#if WXWIN_COMPATIBILITY_2_8
27 #define wxTraceMemAlloc 0x0001 // trace memory allocation (new/delete)
28 #define wxTraceMessages 0x0002 // trace window messages/X callbacks
29 #define wxTraceResAlloc 0x0004 // trace GDI resource allocation
30 #define wxTraceRefCount 0x0008 // trace various ref counting operations
0b4f47a3 31
34085a0d
VZ
32 #ifdef __WXMSW__
33 #define wxTraceOleCalls 0x0100 // OLE interface calls
34 #endif
546db2a8 35
34085a0d
VZ
36 typedef unsigned long wxTraceMask;
37#endif // WXWIN_COMPATIBILITY_2_8
546db2a8
VZ
38
39// ----------------------------------------------------------------------------
40// headers
41// ----------------------------------------------------------------------------
42
b6e4e44a 43#include "wx/string.h"
c9f78968 44#include "wx/strvararg.h"
b6e4e44a 45
b0d58b0e
VZ
46// ----------------------------------------------------------------------------
47// forward declarations
48// ----------------------------------------------------------------------------
49
50class WXDLLIMPEXP_FWD_BASE wxObject;
51
52#if wxUSE_GUI
53 class WXDLLIMPEXP_FWD_CORE wxFrame;
54#endif // wxUSE_GUI
55
1782be31
VZ
56#if wxUSE_LOG
57
1782be31
VZ
58#include "wx/arrstr.h"
59
9b4da627 60#ifndef __WXPALMOS5__
0e0126c2 61#ifndef __WXWINCE__
1782be31 62 #include <time.h> // for time_t
0e0126c2 63#endif
9b4da627 64#endif // ! __WXPALMOS5__
c30aaf75
VZ
65
66#include "wx/dynarray.h"
af588446 67#include "wx/hashmap.h"
d6b9496a 68
bc73d5ae
VZ
69#if wxUSE_THREADS
70 #include "wx/thread.h"
71#endif // wxUSE_THREADS
72
711f12ef 73// wxUSE_LOG_DEBUG enables the debug log messages
edc73852 74#ifndef wxUSE_LOG_DEBUG
23fb9bf5
VZ
75 #if wxDEBUG_LEVEL
76 #define wxUSE_LOG_DEBUG 1
77 #else // !wxDEBUG_LEVEL
78 #define wxUSE_LOG_DEBUG 0
79 #endif
edc73852
RD
80#endif
81
711f12ef
VZ
82// wxUSE_LOG_TRACE enables the trace messages, they are disabled by default
83#ifndef wxUSE_LOG_TRACE
9d2214dd 84 #if wxDEBUG_LEVEL
711f12ef 85 #define wxUSE_LOG_TRACE 1
9d2214dd 86 #else // !wxDEBUG_LEVEL
711f12ef
VZ
87 #define wxUSE_LOG_TRACE 0
88 #endif
89#endif // wxUSE_LOG_TRACE
90
c602c59b
VZ
91// wxLOG_COMPONENT identifies the component which generated the log record and
92// can be #define'd to a user-defined value when compiling the user code to use
93// component-based filtering (see wxLog::SetComponentLevel())
94#ifndef wxLOG_COMPONENT
95 // this is a variable and not a macro in order to allow the user code to
96 // just #define wxLOG_COMPONENT without #undef'ining it first
97 extern WXDLLIMPEXP_DATA_BASE(const char *) wxLOG_COMPONENT;
98
99 #ifdef WXBUILDING
100 #define wxLOG_COMPONENT "wx"
101 #endif
102#endif
103
9ef3052c
VZ
104// ----------------------------------------------------------------------------
105// constants
106// ----------------------------------------------------------------------------
107
108// different standard log levels (you may also define your own)
90adbcca 109enum wxLogLevelValues
9ef3052c 110{
d6b9496a
VZ
111 wxLOG_FatalError, // program can't continue, abort immediately
112 wxLOG_Error, // a serious error, user must be informed about it
113 wxLOG_Warning, // user is normally informed about it but may be ignored
114 wxLOG_Message, // normal message (i.e. normal output of a non GUI app)
d6b9496a 115 wxLOG_Status, // informational: might go to the status line of GUI app
edc73852 116 wxLOG_Info, // informational message (a.k.a. 'Verbose')
d6b9496a
VZ
117 wxLOG_Debug, // never shown to the user, disabled in release mode
118 wxLOG_Trace, // trace messages are also only enabled in debug mode
119 wxLOG_Progress, // used for progress indicator (not yet)
edc73852 120 wxLOG_User = 100, // user defined levels start here
65ca8c0b 121 wxLOG_Max = 10000
9ef3052c
VZ
122};
123
d6b9496a
VZ
124// symbolic trace masks - wxLogTrace("foo", "some trace message...") will be
125// discarded unless the string "foo" has been added to the list of allowed
126// ones with AddTraceMask()
127
08298395
OK
128#define wxTRACE_MemAlloc wxT("memalloc") // trace memory allocation (new/delete)
129#define wxTRACE_Messages wxT("messages") // trace window messages/X callbacks
130#define wxTRACE_ResAlloc wxT("resalloc") // trace GDI resource allocation
131#define wxTRACE_RefCount wxT("refcount") // trace various ref counting operations
d6b9496a
VZ
132
133#ifdef __WXMSW__
08298395 134 #define wxTRACE_OleCalls wxT("ole") // OLE interface calls
d6b9496a
VZ
135#endif
136
65f19af1 137#include "wx/iosfwrap.h"
470b7da3 138
bc73d5ae
VZ
139// ----------------------------------------------------------------------------
140// information about a log record, i.e. unit of log output
141// ----------------------------------------------------------------------------
142
af588446 143class wxLogRecordInfo
bc73d5ae 144{
af588446
VZ
145public:
146 // default ctor creates an uninitialized object
bc73d5ae
VZ
147 wxLogRecordInfo()
148 {
c602c59b 149 memset(this, 0, sizeof(*this));
af588446
VZ
150 }
151
152 // normal ctor, used by wxLogger specifies the location of the log
153 // statement; its time stamp and thread id are set up here
154 wxLogRecordInfo(const char *filename_,
155 int line_,
c602c59b
VZ
156 const char *func_,
157 const char *component_)
af588446
VZ
158 {
159 filename = filename_;
160 func = func_;
161 line = line_;
c602c59b 162 component = component_;
af588446
VZ
163
164 timestamp = time(NULL);
bc73d5ae
VZ
165
166#if wxUSE_THREADS
af588446 167 threadId = wxThread::GetCurrentId();
bc73d5ae 168#endif // wxUSE_THREADS
af588446
VZ
169
170 m_data = NULL;
171 }
172
173 // we need to define copy ctor and assignment operator because of m_data
174 wxLogRecordInfo(const wxLogRecordInfo& other)
175 {
176 Copy(other);
177 }
178
179 wxLogRecordInfo& operator=(const wxLogRecordInfo& other)
180 {
181 if ( &other != this )
182 {
183 delete m_data;
184 Copy(other);
185 }
186
187 return *this;
bc73d5ae
VZ
188 }
189
af588446
VZ
190 // dtor is non-virtual, this class is not meant to be derived from
191 ~wxLogRecordInfo()
192 {
193 delete m_data;
194 }
bc73d5ae
VZ
195
196
af588446
VZ
197 // the file name and line number of the file where the log record was
198 // generated, if available or NULL and 0 otherwise
199 const char *filename;
200 int line;
201
202 // the name of the function where the log record was generated (may be NULL
203 // if the compiler doesn't support __FUNCTION__)
204 const char *func;
205
c602c59b
VZ
206 // the name of the component which generated this message, may be NULL if
207 // not set (i.e. wxLOG_COMPONENT not defined)
208 const char *component;
209
bc73d5ae
VZ
210 // time of record generation
211 time_t timestamp;
212
213#if wxUSE_THREADS
214 // id of the thread which logged this record
215 wxThreadIdType threadId;
216#endif // wxUSE_THREADS
af588446
VZ
217
218
219 // store an arbitrary value in this record context
220 //
221 // wxWidgets always uses keys starting with "wx.", e.g. "wx.sys_error"
222 void StoreValue(const wxString& key, wxUIntPtr val)
223 {
224 if ( !m_data )
225 m_data = new ExtraData;
226
227 m_data->numValues[key] = val;
228 }
229
230 void StoreValue(const wxString& key, const wxString& val)
231 {
232 if ( !m_data )
233 m_data = new ExtraData;
234
235 m_data->strValues[key] = val;
236 }
237
238
239 // these functions retrieve the value of either numeric or string key,
240 // return false if not found
241 bool GetNumValue(const wxString& key, wxUIntPtr *val) const
242 {
243 if ( !m_data )
244 return false;
245
246 wxStringToNumHashMap::const_iterator it = m_data->numValues.find(key);
247 if ( it == m_data->numValues.end() )
248 return false;
249
250 *val = it->second;
251
252 return true;
253 }
254
255 bool GetStrValue(const wxString& key, wxString *val) const
256 {
257 if ( !m_data )
258 return false;
259
260 wxStringToStringHashMap::const_iterator it = m_data->strValues.find(key);
261 if ( it == m_data->strValues.end() )
262 return false;
263
264 *val = it->second;
265
266 return true;
267 }
268
269private:
270 void Copy(const wxLogRecordInfo& other)
271 {
c602c59b 272 memcpy(this, &other, sizeof(*this));
af588446
VZ
273 if ( other.m_data )
274 m_data = new ExtraData(*other.m_data);
275 }
276
277 // extra data associated with the log record: this is completely optional
278 // and can be used to pass information from the log function to the log
279 // sink (e.g. wxLogSysError() uses this to pass the error code)
280 struct ExtraData
281 {
282 wxStringToNumHashMap numValues;
283 wxStringToStringHashMap strValues;
284 };
285
286 // NULL if not used
287 ExtraData *m_data;
bc73d5ae
VZ
288};
289
af588446
VZ
290#define wxLOG_KEY_TRACE_MASK "wx.trace_mask"
291
232addd1
VZ
292// ----------------------------------------------------------------------------
293// log record: a unit of log output
294// ----------------------------------------------------------------------------
295
296struct wxLogRecord
297{
298 wxLogRecord(wxLogLevel level_,
299 const wxString& msg_,
300 const wxLogRecordInfo& info_)
301 : level(level_),
302 msg(msg_),
303 info(info_)
304 {
305 }
306
307 wxLogLevel level;
308 wxString msg;
309 wxLogRecordInfo info;
310};
311
4ffdb640
VZ
312// ----------------------------------------------------------------------------
313// Derive from this class to customize format of log messages.
314// ----------------------------------------------------------------------------
315
316class WXDLLIMPEXP_BASE wxLogFormatter
317{
318public:
319 // Default constructor.
320 wxLogFormatter() { }
321
322 // Trivial but virtual destructor for the base class.
323 virtual ~wxLogFormatter() { }
324
325
326 // Override this method to implement custom formatting of the given log
327 // record. The default implementation simply prepends a level-dependent
328 // prefix to the message and optionally adds a time stamp.
329 virtual wxString Format(wxLogLevel level,
330 const wxString& msg,
331 const wxLogRecordInfo& info) const;
332
333protected:
334 // Override this method to change just the time stamp formatting. It is
335 // called by default Format() implementation.
336 virtual wxString FormatTime(time_t t) const;
337};
338
339
c801d85f
KB
340// ----------------------------------------------------------------------------
341// derive from this class to redirect (or suppress, or ...) log messages
342// normally, only a single instance of this class exists but it's not enforced
c801d85f 343// ----------------------------------------------------------------------------
d6b9496a 344
bddd7a8d 345class WXDLLIMPEXP_BASE wxLog
c801d85f
KB
346{
347public:
d6b9496a 348 // ctor
4ffdb640 349 wxLog() : m_formatter(new wxLogFormatter) { }
bc73d5ae
VZ
350
351 // make dtor virtual for all derived classes
352 virtual ~wxLog();
353
d6b9496a 354
c602c59b
VZ
355 // log messages selection
356 // ----------------------
357
358 // these functions allow to completely disable all log messages or disable
53ff8df7
VZ
359 // log messages at level less important than specified for the current
360 // thread
d1b20379 361
ba3af101 362 // is logging enabled at all now?
53ff8df7
VZ
363 static bool IsEnabled()
364 {
365#if wxUSE_THREADS
366 if ( !wxThread::IsMain() )
367 return IsThreadLoggingEnabled();
368#endif // wxUSE_THREADS
369
370 return ms_doLog;
371 }
d1b20379
DS
372
373 // change the flag state, return the previous one
53ff8df7
VZ
374 static bool EnableLogging(bool enable = true)
375 {
376#if wxUSE_THREADS
377 if ( !wxThread::IsMain() )
378 return EnableThreadLogging(enable);
379#endif // wxUSE_THREADS
d6b9496a 380
53ff8df7
VZ
381 bool doLogOld = ms_doLog;
382 ms_doLog = enable;
383 return doLogOld;
384 }
c602c59b
VZ
385
386 // return the current global log level
387 static wxLogLevel GetLogLevel() { return ms_logLevel; }
388
389 // set global log level: messages with level > logLevel will not be logged
390 static void SetLogLevel(wxLogLevel logLevel) { ms_logLevel = logLevel; }
391
392 // set the log level for the given component
393 static void SetComponentLevel(const wxString& component, wxLogLevel level);
394
395 // return the effective log level for this component, falling back to
396 // parent component and to the default global log level if necessary
397 //
398 // NB: component argument is passed by value and not const reference in an
399 // attempt to encourage compiler to avoid an extra copy: as we modify
400 // the component internally, we'd create one anyhow and like this it
401 // can be avoided if the string is a temporary anyhow
402 static wxLogLevel GetComponentLevel(wxString component);
403
404
405 // is logging of messages from this component enabled at this level?
406 //
407 // usually always called with wxLOG_COMPONENT as second argument
408 static bool IsLevelEnabled(wxLogLevel level, wxString component)
409 {
410 return IsEnabled() && level <= GetComponentLevel(component);
411 }
412
413
414 // enable/disable messages at wxLOG_Verbose level (only relevant if the
415 // current log level is greater or equal to it)
416 //
417 // notice that verbose mode can be activated by the standard command-line
418 // '--verbose' option
419 static void SetVerbose(bool bVerbose = true) { ms_bVerbose = bVerbose; }
420
421 // check if verbose messages are enabled
422 static bool GetVerbose() { return ms_bVerbose; }
423
424
d6b9496a 425 // message buffering
c602c59b 426 // -----------------
d1b20379
DS
427
428 // flush shows all messages if they're not logged immediately (FILE
e55919d8 429 // and iostream logs don't need it, but wxLogGui does to avoid showing
d1b20379 430 // 17 modal dialogs one after another)
d6b9496a 431 virtual void Flush();
d6b9496a 432
acad886c
VZ
433 // flush the active target if any and also output any pending messages from
434 // background threads
435 static void FlushActive();
1ec5cbf3 436
acad886c
VZ
437 // only one sink is active at each moment get current log target, will call
438 // wxAppTraits::CreateLogTarget() to create one if none exists
d6b9496a 439 static wxLog *GetActiveTarget();
d1b20379 440
acad886c
VZ
441 // change log target, logger may be NULL
442 static wxLog *SetActiveTarget(wxLog *logger);
443
444#if wxUSE_THREADS
445 // change log target for the current thread only, shouldn't be called from
446 // the main thread as it doesn't use thread-specific log target
447 static wxLog *SetThreadActiveTarget(wxLog *logger);
448#endif // wxUSE_THREADS
d6b9496a 449
d1b20379
DS
450 // suspend the message flushing of the main target until the next call
451 // to Resume() - this is mainly for internal use (to prevent wxYield()
452 // from flashing the messages)
2ed3265e 453 static void Suspend() { ms_suspendCount++; }
d1b20379
DS
454
455 // must be called for each Suspend()!
2ed3265e
VZ
456 static void Resume() { ms_suspendCount--; }
457
d1b20379
DS
458 // should GetActiveTarget() try to create a new log object if the
459 // current is NULL?
36bd6902 460 static void DontCreateOnDemand();
d6b9496a 461
e94cd97d
DE
462 // Make GetActiveTarget() create a new log object again.
463 static void DoCreateOnDemand();
464
f9837791
VZ
465 // log the count of repeating messages instead of logging the messages
466 // multiple times
467 static void SetRepetitionCounting(bool bRepetCounting = true)
2e7f3845 468 { ms_bRepetCounting = bRepetCounting; }
f9837791
VZ
469
470 // gets duplicate counting status
471 static bool GetRepetitionCounting() { return ms_bRepetCounting; }
472
d1b20379 473 // add string trace mask
f96233d5 474 static void AddTraceMask(const wxString& str);
d1b20379
DS
475
476 // add string trace mask
d6b9496a 477 static void RemoveTraceMask(const wxString& str);
d1b20379
DS
478
479 // remove all string trace masks
36bd6902 480 static void ClearTraceMasks();
d1b20379 481
f96233d5
VZ
482 // get string trace masks: note that this is MT-unsafe if other threads can
483 // call AddTraceMask() concurrently
55e5154d 484 static const wxArrayString& GetTraceMasks();
d6b9496a 485
4ffdb640
VZ
486 // is this trace mask in the list?
487 static bool IsAllowedTraceMask(const wxString& mask);
488
489
490 // log formatting
491 // -----------------
492
493 // Change wxLogFormatter object used by wxLog to format the log messages.
494 //
495 // wxLog takes ownership of the pointer passed in but the caller is
496 // responsible for deleting the returned pointer.
497 wxLogFormatter* SetFormatter(wxLogFormatter* formatter);
498
499
500 // All the time stamp related functions below only work when the default
501 // wxLogFormatter is being used. Defining a custom formatter overrides them
502 // as it could use its own time stamp format or format messages without
503 // using time stamp at all.
504
505
7b1bf3ad
VZ
506 // sets the time stamp string format: this is used as strftime() format
507 // string for the log targets which add time stamps to the messages; set
508 // it to empty string to disable time stamping completely.
d993e05b 509 static void SetTimestamp(const wxString& ts) { ms_timestamp = ts; }
d2e1ef19 510
7b1bf3ad
VZ
511 // disable time stamping of log messages
512 static void DisableTimestamp() { SetTimestamp(wxEmptyString); }
513
edc73852 514
d1279c9a 515 // get the current timestamp format string (maybe empty)
d993e05b 516 static const wxString& GetTimestamp() { return ms_timestamp; }
d2e1ef19 517
edc73852 518
bc73d5ae
VZ
519
520 // helpers: all functions in this section are mostly for internal use only,
521 // don't call them from your code even if they are not formally deprecated
d1b20379 522
4ffdb640
VZ
523 // put the time stamp into the string if ms_timestamp is not empty (don't
524 // change it otherwise); the first overload uses the current time.
d2e1ef19 525 static void TimeStamp(wxString *str);
4ffdb640 526 static void TimeStamp(wxString *str, time_t t);
d2e1ef19 527
bc73d5ae
VZ
528 // these methods should only be called from derived classes DoLogRecord(),
529 // DoLogTextAtLevel() and DoLogText() implementations respectively and
530 // shouldn't be called directly, use logging functions instead
531 void LogRecord(wxLogLevel level,
532 const wxString& msg,
533 const wxLogRecordInfo& info)
efce878a 534 {
bc73d5ae 535 DoLogRecord(level, msg, info);
efce878a
VZ
536 }
537
bc73d5ae
VZ
538 void LogTextAtLevel(wxLogLevel level, const wxString& msg)
539 {
540 DoLogTextAtLevel(level, msg);
541 }
542
543 void LogText(const wxString& msg)
544 {
545 DoLogText(msg);
546 }
547
548 // this is a helper used by wxLogXXX() functions, don't call it directly
549 // and see DoLog() for function to overload in the derived classes
550 static void OnLog(wxLogLevel level,
551 const wxString& msg,
552 const wxLogRecordInfo& info);
553
554 // version called when no information about the location of the log record
555 // generation is available (but the time stamp is), it mainly exists for
556 // backwards compatibility, don't use it in new code
557 static void OnLog(wxLogLevel level, const wxString& msg, time_t t);
558
559 // a helper calling the above overload with current time
560 static void OnLog(wxLogLevel level, const wxString& msg)
561 {
562 OnLog(level, msg, time(NULL));
563 }
c801d85f 564
c801d85f 565
1ec5cbf3 566 // this method exists for backwards compatibility only, don't use
d1b20379 567 bool HasPendingMessages() const { return true; }
1ec5cbf3 568
2e7f3845
VZ
569#if WXWIN_COMPATIBILITY_2_6
570 // this function doesn't do anything any more, don't call it
d65e9d57
VZ
571 static wxDEPRECATED_INLINE(
572 wxChar *SetLogBuffer(wxChar *, size_t = 0), return NULL;
bc73d5ae
VZ
573 );
574#endif // WXWIN_COMPATIBILITY_2_6
2e7f3845 575
34085a0d
VZ
576 // don't use integer masks any more, use string trace masks instead
577#if WXWIN_COMPATIBILITY_2_8
d65e9d57 578 static wxDEPRECATED_INLINE( void SetTraceMask(wxTraceMask ulMask),
34085a0d 579 ms_ulTraceMask = ulMask; )
b356aa55
VZ
580
581 // this one can't be marked deprecated as it's used in our own wxLogger
582 // below but it still is deprecated and shouldn't be used
583 static wxTraceMask GetTraceMask() { return ms_ulTraceMask; }
34085a0d
VZ
584#endif // WXWIN_COMPATIBILITY_2_8
585
1ec5cbf3 586protected:
bc73d5ae
VZ
587 // the logging functions that can be overridden: DoLogRecord() is called
588 // for every "record", i.e. a unit of log output, to be logged and by
589 // default formats the message and passes it to DoLogTextAtLevel() which in
590 // turn passes it to DoLogText() by default
af588446 591
bc73d5ae
VZ
592 // override this method if you want to change message formatting or do
593 // dynamic filtering
594 virtual void DoLogRecord(wxLogLevel level,
595 const wxString& msg,
596 const wxLogRecordInfo& info);
597
598 // override this method to redirect output to different channels depending
599 // on its level only; if even the level doesn't matter, override
600 // DoLogText() instead
601 virtual void DoLogTextAtLevel(wxLogLevel level, const wxString& msg);
602
603 // this function is not pure virtual as it might not be needed if you do
604 // the logging in overridden DoLogRecord() or DoLogTextAtLevel() directly
605 // but if you do not override them in your derived class you must override
606 // this one as the default implementation of it simply asserts
607 virtual void DoLogText(const wxString& msg);
608
609
610 // the rest of the functions are for backwards compatibility only, don't
611 // use them in new code; if you're updating your existing code you need to
612 // switch to overriding DoLogRecord/Text() above (although as long as these
613 // functions exist, log classes using them will continue to work)
5a20d2ce 614#if WXWIN_COMPATIBILITY_2_8
5d88a6b5
VZ
615 wxDEPRECATED_BUT_USED_INTERNALLY(
616 virtual void DoLog(wxLogLevel level, const char *szString, time_t t)
617 );
618
619 wxDEPRECATED_BUT_USED_INTERNALLY(
620 virtual void DoLog(wxLogLevel level, const wchar_t *wzString, time_t t)
621 );
d1b20379 622
5a20d2ce 623 // these shouldn't be used by new code
bc73d5ae
VZ
624 wxDEPRECATED_BUT_USED_INTERNALLY_INLINE(
625 virtual void DoLogString(const char *WXUNUSED(szString),
626 time_t WXUNUSED(t)),
ae2070fb 627 wxEMPTY_PARAMETER_VALUE
bc73d5ae
VZ
628 )
629
630 wxDEPRECATED_BUT_USED_INTERNALLY_INLINE(
631 virtual void DoLogString(const wchar_t *WXUNUSED(wzString),
632 time_t WXUNUSED(t)),
ae2070fb 633 wxEMPTY_PARAMETER_VALUE
bc73d5ae 634 )
b99891b0
VZ
635#endif // WXWIN_COMPATIBILITY_2_8
636
c801d85f 637
2064113c 638 // log a message indicating the number of times the previous message was
bc73d5ae
VZ
639 // repeated if previous repetition counter is strictly positive, does
640 // nothing otherwise; return the old value of repetition counter
dbaa16de 641 unsigned LogLastRepeatIfNeeded();
f9837791 642
d6b9496a 643private:
acad886c
VZ
644#if wxUSE_THREADS
645 // called from FlushActive() to really log any buffered messages logged
646 // from the other threads
647 void FlushThreadMessages();
53ff8df7
VZ
648
649 // these functions are called for non-main thread only by IsEnabled() and
650 // EnableLogging() respectively
651 static bool IsThreadLoggingEnabled();
652 static bool EnableThreadLogging(bool enable = true);
acad886c
VZ
653#endif // wxUSE_THREADS
654
5d7526b0
VZ
655 // get the active log target for the main thread, auto-creating it if
656 // necessary
657 //
658 // this is called from GetActiveTarget() and OnLog() when they're called
659 // from the main thread
660 static wxLog *GetMainThreadActiveTarget();
661
acad886c
VZ
662 // called from OnLog() if it's called from the main thread or if we have a
663 // (presumably MT-safe) thread-specific logger and by FlushThreadMessages()
232addd1 664 // when it plays back the buffered messages logged from the other threads
acad886c
VZ
665 void CallDoLogNow(wxLogLevel level,
666 const wxString& msg,
667 const wxLogRecordInfo& info);
232addd1
VZ
668
669
4ffdb640
VZ
670 // variables
671 // ----------------
672
673 wxLogFormatter *m_formatter; // We own this pointer.
674
675
d6b9496a
VZ
676 // static variables
677 // ----------------
06db8ebd 678
2064113c
VZ
679 // if true, don't log the same message multiple times, only log it once
680 // with the number of times it was repeated
f9837791 681 static bool ms_bRepetCounting;
2064113c 682
d6b9496a 683 static wxLog *ms_pLogger; // currently active log sink
d1b20379 684 static bool ms_doLog; // false => all logging disabled
d6b9496a 685 static bool ms_bAutoCreate; // create new log targets on demand?
d1b20379 686 static bool ms_bVerbose; // false => ignore LogInfo messages
fe7b1156 687
edc73852
RD
688 static wxLogLevel ms_logLevel; // limit logging to levels <= ms_logLevel
689
2ed3265e
VZ
690 static size_t ms_suspendCount; // if positive, logs are not flushed
691
d1279c9a 692 // format string for strftime(), if empty, time stamping log messages is
d2e1ef19 693 // disabled
d993e05b 694 static wxString ms_timestamp;
d2e1ef19 695
34085a0d 696#if WXWIN_COMPATIBILITY_2_8
d6b9496a 697 static wxTraceMask ms_ulTraceMask; // controls wxLogTrace behaviour
34085a0d 698#endif // WXWIN_COMPATIBILITY_2_8
c801d85f
KB
699};
700
701// ----------------------------------------------------------------------------
702// "trivial" derivations of wxLog
703// ----------------------------------------------------------------------------
704
711f12ef
VZ
705// log everything except for the debug/trace messages (which are passed to
706// wxMessageOutputDebug) to a buffer
d3fc1755
VZ
707class WXDLLIMPEXP_BASE wxLogBuffer : public wxLog
708{
709public:
710 wxLogBuffer() { }
711
712 // get the string contents with all messages logged
713 const wxString& GetBuffer() const { return m_str; }
714
715 // show the buffer contents to the user in the best possible way (this uses
716 // wxMessageOutputMessageBox) and clear it
717 virtual void Flush();
718
719protected:
bc73d5ae 720 virtual void DoLogTextAtLevel(wxLogLevel level, const wxString& msg);
b99891b0 721
d3fc1755
VZ
722private:
723 wxString m_str;
724
c0c133e1 725 wxDECLARE_NO_COPY_CLASS(wxLogBuffer);
d3fc1755
VZ
726};
727
0f8218d7 728
c801d85f 729// log everything to a "FILE *", stderr by default
bddd7a8d 730class WXDLLIMPEXP_BASE wxLogStderr : public wxLog
c801d85f
KB
731{
732public:
d6b9496a 733 // redirect log output to a FILE
d3b9f782 734 wxLogStderr(FILE *fp = NULL);
c801d85f 735
03147cd0 736protected:
d6b9496a 737 // implement sink function
bc73d5ae 738 virtual void DoLogText(const wxString& msg);
b99891b0 739
d6b9496a 740 FILE *m_fp;
d3fc1755 741
c0c133e1 742 wxDECLARE_NO_COPY_CLASS(wxLogStderr);
c801d85f
KB
743};
744
4bf78aae 745#if wxUSE_STD_IOSTREAM
03147cd0 746
c801d85f 747// log everything to an "ostream", cerr by default
bddd7a8d 748class WXDLLIMPEXP_BASE wxLogStream : public wxLog
c801d85f
KB
749{
750public:
d6b9496a 751 // redirect log output to an ostream
dd107c50 752 wxLogStream(wxSTD ostream *ostr = (wxSTD ostream *) NULL);
c801d85f
KB
753
754protected:
d6b9496a 755 // implement sink function
bc73d5ae 756 virtual void DoLogText(const wxString& msg);
b99891b0 757
d6b9496a 758 // using ptr here to avoid including <iostream.h> from this file
dd107c50 759 wxSTD ostream *m_ostr;
c801d85f 760};
03147cd0
VZ
761
762#endif // wxUSE_STD_IOSTREAM
c801d85f 763
03147cd0
VZ
764// ----------------------------------------------------------------------------
765// /dev/null log target: suppress logging until this object goes out of scope
766// ----------------------------------------------------------------------------
767
768// example of usage:
769/*
770 void Foo()
771 {
772 wxFile file;
773
774 // wxFile.Open() normally complains if file can't be opened, we don't
775 // want it
776 wxLogNull logNo;
777
778 if ( !file.Open("bar") )
779 ... process error ourselves ...
780
781 // ~wxLogNull called, old log sink restored
782 }
783 */
bddd7a8d 784class WXDLLIMPEXP_BASE wxLogNull
03147cd0
VZ
785{
786public:
d1b20379 787 wxLogNull() : m_flagOld(wxLog::EnableLogging(false)) { }
be52b341 788 ~wxLogNull() { (void)wxLog::EnableLogging(m_flagOld); }
03147cd0
VZ
789
790private:
791 bool m_flagOld; // the previous value of the wxLog::ms_doLog
792};
793
794// ----------------------------------------------------------------------------
795// chaining log target: installs itself as a log target and passes all
796// messages to the real log target given to it in the ctor but also forwards
797// them to the previously active one
798//
799// note that you don't have to call SetActiveTarget() with this class, it
800// does it itself in its ctor
801// ----------------------------------------------------------------------------
802
bddd7a8d 803class WXDLLIMPEXP_BASE wxLogChain : public wxLog
03147cd0
VZ
804{
805public:
806 wxLogChain(wxLog *logger);
8b30a4e4 807 virtual ~wxLogChain();
03147cd0
VZ
808
809 // change the new log target
810 void SetLog(wxLog *logger);
811
812 // this can be used to temporarily disable (and then reenable) passing
813 // messages to the old logger (by default we do pass them)
814 void PassMessages(bool bDoPass) { m_bPassMessages = bDoPass; }
815
816 // are we passing the messages to the previous log target?
817 bool IsPassingMessages() const { return m_bPassMessages; }
818
819 // return the previous log target (may be NULL)
820 wxLog *GetOldLog() const { return m_logOld; }
821
822 // override base class version to flush the old logger as well
823 virtual void Flush();
824
47fe7ff3
JS
825 // call to avoid destroying the old log target
826 void DetachOldLog() { m_logOld = NULL; }
827
03147cd0 828protected:
bc73d5ae
VZ
829 // pass the record to the old logger if needed
830 virtual void DoLogRecord(wxLogLevel level,
831 const wxString& msg,
832 const wxLogRecordInfo& info);
b99891b0 833
03147cd0
VZ
834private:
835 // the current log target
836 wxLog *m_logNew;
837
838 // the previous log target
839 wxLog *m_logOld;
840
841 // do we pass the messages to the old logger?
842 bool m_bPassMessages;
22f3361e 843
c0c133e1 844 wxDECLARE_NO_COPY_CLASS(wxLogChain);
03147cd0
VZ
845};
846
847// a chain log target which uses itself as the new logger
47fe7ff3
JS
848
849#define wxLogPassThrough wxLogInterposer
850
851class WXDLLIMPEXP_BASE wxLogInterposer : public wxLogChain
852{
853public:
854 wxLogInterposer();
855
856private:
c0c133e1 857 wxDECLARE_NO_COPY_CLASS(wxLogInterposer);
47fe7ff3
JS
858};
859
860// a temporary interposer which doesn't destroy the old log target
861// (calls DetachOldLog)
862
863class WXDLLIMPEXP_BASE wxLogInterposerTemp : public wxLogChain
03147cd0
VZ
864{
865public:
47fe7ff3 866 wxLogInterposerTemp();
fc7a2a60
VZ
867
868private:
c0c133e1 869 wxDECLARE_NO_COPY_CLASS(wxLogInterposerTemp);
03147cd0
VZ
870};
871
8ca28fb7 872#if wxUSE_GUI
7e8c564c
VS
873 // include GUI log targets:
874 #include "wx/generic/logg.h"
e90c1d2a 875#endif // wxUSE_GUI
03f38c58 876
af588446
VZ
877// ----------------------------------------------------------------------------
878// wxLogger
879// ----------------------------------------------------------------------------
880
881// wxLogger is a helper class used by wxLogXXX() functions implementation,
882// don't use it directly as it's experimental and subject to change (OTOH it
883// might become public in the future if it's deemed to be useful enough)
884
885// contains information about the context from which a log message originates
886// and provides Log() vararg method which forwards to wxLog::OnLog() and passes
887// this context to it
888class wxLogger
889{
890public:
891 // ctor takes the basic information about the log record
892 wxLogger(wxLogLevel level,
893 const char *filename,
894 int line,
c602c59b
VZ
895 const char *func,
896 const char *component)
af588446 897 : m_level(level),
c602c59b 898 m_info(filename, line, func, component)
af588446
VZ
899 {
900 }
901
902 // store extra data in our log record and return this object itself (so
903 // that further calls to its functions could be chained)
904 template <typename T>
905 wxLogger& Store(const wxString& key, T val)
906 {
907 m_info.StoreValue(key, val);
908 return *this;
909 }
910
911 // hack for "overloaded" wxLogXXX() functions: calling this method
912 // indicates that we may have an extra first argument preceding the format
913 // string and that if we do have it, we should store it in m_info using the
914 // given key (while by default 0 value will be used)
b804f992 915 wxLogger& MaybeStore(const wxString& key, wxUIntPtr value = 0)
af588446
VZ
916 {
917 wxASSERT_MSG( m_optKey.empty(), "can only have one optional value" );
918 m_optKey = key;
919
b804f992 920 m_info.StoreValue(key, value);
af588446
VZ
921 return *this;
922 }
923
924
925 // non-vararg function used by wxVLogXXX():
926
927 // log the message at the level specified in the ctor if this log message
928 // is enabled
929 void LogV(const wxString& format, va_list argptr)
930 {
931 // remember that fatal errors can't be disabled
c602c59b
VZ
932 if ( m_level == wxLOG_FatalError ||
933 wxLog::IsLevelEnabled(m_level, m_info.component) )
af588446
VZ
934 DoCallOnLog(format, argptr);
935 }
936
937 // overloads used by functions with optional leading arguments (whose
938 // values are stored in the key passed to MaybeStore())
939 void LogV(long num, const wxString& format, va_list argptr)
940 {
941 Store(m_optKey, num);
942
943 LogV(format, argptr);
944 }
945
946 void LogV(void *ptr, const wxString& format, va_list argptr)
947 {
948 Store(m_optKey, wxPtrToUInt(ptr));
949
950 LogV(format, argptr);
951 }
952
89d62794
VZ
953 void LogVTrace(const wxString& mask, const wxString& format, va_list argptr)
954 {
955 if ( !wxLog::IsAllowedTraceMask(mask) )
956 return;
957
958 Store(wxLOG_KEY_TRACE_MASK, mask);
959
960 LogV(format, argptr);
961 }
962
af588446
VZ
963
964 // vararg functions used by wxLogXXX():
965
966 // will log the message at the level specified in the ctor
967 //
968 // notice that this function supposes that the caller already checked that
969 // the level was enabled and does no checks itself
970 WX_DEFINE_VARARG_FUNC_VOID
971 (
972 Log,
973 1, (const wxFormatString&),
974 DoLog, DoLogUtf8
975 )
976
977 // same as Log() but with an extra numeric or pointer parameters: this is
978 // used to pass an optional value by storing it in m_info under the name
979 // passed to MaybeStore() and is required to support "overloaded" versions
980 // of wxLogStatus() and wxLogSysError()
981 WX_DEFINE_VARARG_FUNC_VOID
982 (
983 Log,
984 2, (long, const wxFormatString&),
985 DoLogWithNum, DoLogWithNumUtf8
986 )
987
c279530b
VZ
988 // unfortunately we can't use "void *" here as we get overload ambiguities
989 // with Log(wxFormatString, ...) when the first argument is a "char *" or
990 // "wchar_t *" then -- so we only allow passing wxObject here, which is
991 // ugly but fine in practice as this overload is only used by wxLogStatus()
992 // whose first argument is a wxFrame
af588446
VZ
993 WX_DEFINE_VARARG_FUNC_VOID
994 (
995 Log,
c279530b 996 2, (wxObject *, const wxFormatString&),
af588446
VZ
997 DoLogWithPtr, DoLogWithPtrUtf8
998 )
999
1000 // log the message at the level specified as its first argument
1001 //
1002 // as the macros don't have access to the level argument in this case, this
1003 // function does check that the level is enabled itself
1004 WX_DEFINE_VARARG_FUNC_VOID
1005 (
1006 LogAtLevel,
1007 2, (wxLogLevel, const wxFormatString&),
1008 DoLogAtLevel, DoLogAtLevelUtf8
1009 )
1010
1011 // special versions for wxLogTrace() which is passed either string or
ff2e9e2c
VZ
1012 // integer mask as first argument determining whether the message should be
1013 // logged or not
af588446
VZ
1014 WX_DEFINE_VARARG_FUNC_VOID
1015 (
1016 LogTrace,
1017 2, (const wxString&, const wxFormatString&),
1018 DoLogTrace, DoLogTraceUtf8
1019 )
1020
ff2e9e2c
VZ
1021#if WXWIN_COMPATIBILITY_2_8
1022 WX_DEFINE_VARARG_FUNC_VOID
1023 (
1024 LogTrace,
1025 2, (wxTraceMask, const wxFormatString&),
1026 DoLogTraceMask, DoLogTraceMaskUtf8
1027 )
1028#endif // WXWIN_COMPATIBILITY_2_8
1029
af588446
VZ
1030#ifdef __WATCOMC__
1031 // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351
1032 WX_VARARG_WATCOM_WORKAROUND(void, Log,
1033 1, (const wxString&),
1034 (wxFormatString(f1)))
1035 WX_VARARG_WATCOM_WORKAROUND(void, Log,
1036 1, (const wxCStrData&),
1037 (wxFormatString(f1)))
1038 WX_VARARG_WATCOM_WORKAROUND(void, Log,
1039 1, (const char*),
1040 (wxFormatString(f1)))
1041 WX_VARARG_WATCOM_WORKAROUND(void, Log,
1042 1, (const wchar_t*),
1043 (wxFormatString(f1)))
1044
1045 WX_VARARG_WATCOM_WORKAROUND(void, Log,
1046 2, (long, const wxString&),
1047 (f1, wxFormatString(f2)))
1048 WX_VARARG_WATCOM_WORKAROUND(void, Log,
1049 2, (long, const wxCStrData&),
1050 (f1, wxFormatString(f2)))
1051 WX_VARARG_WATCOM_WORKAROUND(void, Log,
1052 2, (long, const char *),
1053 (f1, wxFormatString(f2)))
1054 WX_VARARG_WATCOM_WORKAROUND(void, Log,
1055 2, (long, const wchar_t *),
1056 (f1, wxFormatString(f2)))
1057
1058 WX_VARARG_WATCOM_WORKAROUND(void, Log,
c279530b 1059 2, (wxObject *, const wxString&),
af588446
VZ
1060 (f1, wxFormatString(f2)))
1061 WX_VARARG_WATCOM_WORKAROUND(void, Log,
c279530b 1062 2, (wxObject *, const wxCStrData&),
af588446
VZ
1063 (f1, wxFormatString(f2)))
1064 WX_VARARG_WATCOM_WORKAROUND(void, Log,
c279530b 1065 2, (wxObject *, const char *),
af588446
VZ
1066 (f1, wxFormatString(f2)))
1067 WX_VARARG_WATCOM_WORKAROUND(void, Log,
c279530b 1068 2, (wxObject *, const wchar_t *),
af588446
VZ
1069 (f1, wxFormatString(f2)))
1070
1071 WX_VARARG_WATCOM_WORKAROUND(void, LogAtLevel,
1072 2, (wxLogLevel, const wxString&),
1073 (f1, wxFormatString(f2)))
1074 WX_VARARG_WATCOM_WORKAROUND(void, LogAtLevel,
1075 2, (wxLogLevel, const wxCStrData&),
1076 (f1, wxFormatString(f2)))
1077 WX_VARARG_WATCOM_WORKAROUND(void, LogAtLevel,
1078 2, (wxLogLevel, const char *),
1079 (f1, wxFormatString(f2)))
1080 WX_VARARG_WATCOM_WORKAROUND(void, LogAtLevel,
1081 2, (wxLogLevel, const wchar_t *),
1082 (f1, wxFormatString(f2)))
1083
1084 WX_VARARG_WATCOM_WORKAROUND(void, LogTrace,
1085 2, (const wxString&, const wxString&),
1086 (f1, wxFormatString(f2)))
1087 WX_VARARG_WATCOM_WORKAROUND(void, LogTrace,
1088 2, (const wxString&, const wxCStrData&),
1089 (f1, wxFormatString(f2)))
1090 WX_VARARG_WATCOM_WORKAROUND(void, LogTrace,
1091 2, (const wxString&, const char *),
1092 (f1, wxFormatString(f2)))
1093 WX_VARARG_WATCOM_WORKAROUND(void, LogTrace,
1094 2, (const wxString&, const wchar_t *),
1095 (f1, wxFormatString(f2)))
ff2e9e2c
VZ
1096
1097#if WXWIN_COMPATIBILITY_2_8
1098 WX_VARARG_WATCOM_WORKAROUND(void, LogTrace,
1099 2, (wxTraceMask, wxTraceMask),
1100 (f1, wxFormatString(f2)))
1101 WX_VARARG_WATCOM_WORKAROUND(void, LogTrace,
1102 2, (wxTraceMask, const wxCStrData&),
1103 (f1, wxFormatString(f2)))
1104 WX_VARARG_WATCOM_WORKAROUND(void, LogTrace,
1105 2, (wxTraceMask, const char *),
1106 (f1, wxFormatString(f2)))
1107 WX_VARARG_WATCOM_WORKAROUND(void, LogTrace,
1108 2, (wxTraceMask, const wchar_t *),
1109 (f1, wxFormatString(f2)))
1110#endif // WXWIN_COMPATIBILITY_2_8
af588446
VZ
1111#endif // __WATCOMC__
1112
1113private:
1114#if !wxUSE_UTF8_LOCALE_ONLY
1115 void DoLog(const wxChar *format, ...)
1116 {
1117 va_list argptr;
1118 va_start(argptr, format);
1119 DoCallOnLog(format, argptr);
1120 va_end(argptr);
1121 }
1122
1123 void DoLogWithNum(long num, const wxChar *format, ...)
1124 {
1125 Store(m_optKey, num);
1126
1127 va_list argptr;
1128 va_start(argptr, format);
1129 DoCallOnLog(format, argptr);
1130 va_end(argptr);
1131 }
1132
1133 void DoLogWithPtr(void *ptr, const wxChar *format, ...)
1134 {
1135 Store(m_optKey, wxPtrToUInt(ptr));
1136
1137 va_list argptr;
1138 va_start(argptr, format);
1139 DoCallOnLog(format, argptr);
1140 va_end(argptr);
1141 }
1142
1143 void DoLogAtLevel(wxLogLevel level, const wxChar *format, ...)
1144 {
c602c59b 1145 if ( !wxLog::IsLevelEnabled(level, m_info.component) )
af588446
VZ
1146 return;
1147
1148 va_list argptr;
1149 va_start(argptr, format);
1150 DoCallOnLog(level, format, argptr);
1151 va_end(argptr);
1152 }
1153
1154 void DoLogTrace(const wxString& mask, const wxChar *format, ...)
1155 {
1156 if ( !wxLog::IsAllowedTraceMask(mask) )
1157 return;
1158
1159 Store(wxLOG_KEY_TRACE_MASK, mask);
1160
1161 va_list argptr;
1162 va_start(argptr, format);
1163 DoCallOnLog(format, argptr);
1164 va_end(argptr);
1165 }
ff2e9e2c
VZ
1166
1167#if WXWIN_COMPATIBILITY_2_8
1168 void DoLogTraceMask(wxTraceMask mask, const wxChar *format, ...)
1169 {
1170 if ( (wxLog::GetTraceMask() & mask) != mask )
1171 return;
1172
1173 Store(wxLOG_KEY_TRACE_MASK, mask);
1174
1175 va_list argptr;
1176 va_start(argptr, format);
1177 DoCallOnLog(format, argptr);
1178 va_end(argptr);
1179 }
1180#endif // WXWIN_COMPATIBILITY_2_8
af588446
VZ
1181#endif // !wxUSE_UTF8_LOCALE_ONLY
1182
1183#if wxUSE_UNICODE_UTF8
1184 void DoLogUtf8(const char *format, ...)
1185 {
1186 va_list argptr;
1187 va_start(argptr, format);
1188 DoCallOnLog(format, argptr);
1189 va_end(argptr);
1190 }
1191
1192 void DoLogWithNumUtf8(long num, const char *format, ...)
1193 {
1194 Store(m_optKey, num);
1195
1196 va_list argptr;
1197 va_start(argptr, format);
1198 DoCallOnLog(format, argptr);
1199 va_end(argptr);
1200 }
1201
1202 void DoLogWithPtrUtf8(void *ptr, const char *format, ...)
1203 {
1204 Store(m_optKey, wxPtrToUInt(ptr));
1205
1206 va_list argptr;
1207 va_start(argptr, format);
1208 DoCallOnLog(format, argptr);
1209 va_end(argptr);
1210 }
1211
1212 void DoLogAtLevelUtf8(wxLogLevel level, const char *format, ...)
1213 {
c602c59b 1214 if ( !wxLog::IsLevelEnabled(level, m_info.component) )
af588446
VZ
1215 return;
1216
1217 va_list argptr;
1218 va_start(argptr, format);
1219 DoCallOnLog(level, format, argptr);
1220 va_end(argptr);
1221 }
1222
1223 void DoLogTraceUtf8(const wxString& mask, const char *format, ...)
1224 {
1225 if ( !wxLog::IsAllowedTraceMask(mask) )
1226 return;
1227
1228 Store(wxLOG_KEY_TRACE_MASK, mask);
1229
1230 va_list argptr;
1231 va_start(argptr, format);
1232 DoCallOnLog(format, argptr);
1233 va_end(argptr);
1234 }
ff2e9e2c
VZ
1235
1236#if WXWIN_COMPATIBILITY_2_8
1237 void DoLogTraceMaskUtf8(wxTraceMask mask, const char *format, ...)
1238 {
1239 if ( (wxLog::GetTraceMask() & mask) != mask )
1240 return;
1241
1242 Store(wxLOG_KEY_TRACE_MASK, mask);
1243
1244 va_list argptr;
1245 va_start(argptr, format);
1246 DoCallOnLog(format, argptr);
1247 va_end(argptr);
1248 }
1249#endif // WXWIN_COMPATIBILITY_2_8
af588446
VZ
1250#endif // wxUSE_UNICODE_UTF8
1251
1252 void DoCallOnLog(wxLogLevel level, const wxString& format, va_list argptr)
1253 {
1254 wxLog::OnLog(level, wxString::FormatV(format, argptr), m_info);
1255 }
1256
1257 void DoCallOnLog(const wxString& format, va_list argptr)
1258 {
b804f992 1259 DoCallOnLog(m_level, format, argptr);
af588446
VZ
1260 }
1261
1262
1263 const wxLogLevel m_level;
1264 wxLogRecordInfo m_info;
1265
1266 wxString m_optKey;
1267
1268 wxDECLARE_NO_COPY_CLASS(wxLogger);
1269};
1270
c801d85f
KB
1271// ============================================================================
1272// global functions
1273// ============================================================================
1274
88ac883a
VZ
1275// ----------------------------------------------------------------------------
1276// get error code/error message from system in a portable way
1277// ----------------------------------------------------------------------------
1278
1279// return the last system error code
bddd7a8d 1280WXDLLIMPEXP_BASE unsigned long wxSysErrorCode();
c11d62a6 1281
88ac883a 1282// return the error message for given (or last if 0) error code
bddd7a8d 1283WXDLLIMPEXP_BASE const wxChar* wxSysErrorMsg(unsigned long nErrCode = 0);
88ac883a 1284
c11d62a6 1285// ----------------------------------------------------------------------------
af588446
VZ
1286// define wxLog<level>() functions which can be used by application instead of
1287// stdio, iostream &c for log messages for easy redirection
c11d62a6 1288// ----------------------------------------------------------------------------
c801d85f 1289
af588446
VZ
1290/*
1291 The code below is unreadable because it (unfortunately unavoidably)
1292 contains a lot of macro magic but all it does is to define wxLogXXX() such
1293 that you can call them as vararg functions to log a message at the
1294 corresponding level.
1295
1296 More precisely, it defines:
1297
1298 - wxLog{FatalError,Error,Warning,Message,Verbose,Debug}() functions
1299 taking the format string and additional vararg arguments if needed.
1300 - wxLogGeneric(wxLogLevel level, const wxString& format, ...) which
1301 takes the log level explicitly.
1302 - wxLogSysError(const wxString& format, ...) and wxLogSysError(long
1303 err, const wxString& format, ...) which log a wxLOG_Error severity
1304 message with the error message corresponding to the system error code
1305 err or the last error.
1306 - wxLogStatus(const wxString& format, ...) which logs the message into
1307 the status bar of the main application window and its overload
1308 wxLogStatus(wxFrame *frame, const wxString& format, ...) which logs it
1309 into the status bar of the specified frame.
1310 - wxLogTrace(Mask mask, const wxString& format, ...) which only logs
1311 the message is the specified mask is enabled. This comes in two kinds:
1312 Mask can be a wxString or a long. Both are deprecated.
1313
1314 In addition, wxVLogXXX() versions of all the functions above are also
1315 defined. They take a va_list argument instead of "...".
1316 */
2523e9b7 1317
af588446
VZ
1318// creates wxLogger object for the current location
1319#define wxMAKE_LOGGER(level) \
c602c59b 1320 wxLogger(wxLOG_##level, __FILE__, __LINE__, __WXFUNCTION__, wxLOG_COMPONENT)
2523e9b7 1321
af588446
VZ
1322// this macro generates the expression which logs whatever follows it in
1323// parentheses at the level specified as argument
1324#define wxDO_LOG(level) wxMAKE_LOGGER(level).Log
c9f78968 1325
af588446
VZ
1326// this is the non-vararg equivalent
1327#define wxDO_LOGV(level, format, argptr) \
1328 wxMAKE_LOGGER(level).LogV(format, argptr)
2523e9b7 1329
af588446
VZ
1330// this macro declares wxLog<level>() macro which logs whatever follows it if
1331// logging at specified level is enabled (notice that if it is false, the
1332// following arguments are not even evaluated which is good as it avoids
1333// unnecessary overhead)
1334//
1335// Note: the strange if/else construct is needed to make the following code
1336//
1337// if ( cond )
1338// wxLogError("!!!");
1339// else
1340// ...
1341//
1342// work as expected, without it the second "else" would match the "if"
1343// inside wxLogError(). Unfortunately code like
1344//
1345// if ( cond )
1346// wxLogError("!!!");
1347//
1348// now provokes "suggest explicit braces to avoid ambiguous 'else'"
1349// warnings from g++ 4.3 and later with -Wparentheses on but they can be
1350// easily fixed by adding curly braces around wxLogError() and at least
1351// the code still does do the right thing.
1352#define wxDO_LOG_IF_ENABLED(level) \
c602c59b 1353 if ( !wxLog::IsLevelEnabled(wxLOG_##level, wxLOG_COMPONENT) ) \
af588446
VZ
1354 {} \
1355 else \
1356 wxDO_LOG(level)
1357
1358// wxLogFatalError() is special as it can't be disabled
03647350 1359#define wxLogFatalError wxDO_LOG(FatalError)
af588446
VZ
1360#define wxVLogFatalError(format, argptr) wxDO_LOGV(FatalError, format, argptr)
1361
1362#define wxLogError wxDO_LOG_IF_ENABLED(Error)
1363#define wxVLogError(format, argptr) wxDO_LOGV(Error, format, argptr)
1364
1365#define wxLogWarning wxDO_LOG_IF_ENABLED(Warning)
1366#define wxVLogWarning(format, argptr) wxDO_LOGV(Warning, format, argptr)
1367
1368#define wxLogMessage wxDO_LOG_IF_ENABLED(Message)
1369#define wxVLogMessage(format, argptr) wxDO_LOGV(Message, format, argptr)
1370
1371// this one is special as it only logs if we're in verbose mode
1372#define wxLogVerbose \
c602c59b
VZ
1373 if ( !(wxLog::IsLevelEnabled(wxLOG_Info, wxLOG_COMPONENT) && \
1374 wxLog::GetVerbose()) ) \
af588446
VZ
1375 {} \
1376 else \
1377 wxDO_LOG(Info)
1378#define wxVLogVerbose(format, argptr) \
c602c59b
VZ
1379 if ( !(wxLog::IsLevelEnabled(wxLOG_Info, wxLOG_COMPONENT) && \
1380 wxLog::GetVerbose()) ) \
af588446
VZ
1381 {} \
1382 else \
1383 wxDO_LOGV(Info, format, argptr)
1384
1385// deprecated synonyms for wxLogVerbose() and wxVLogVerbose()
1386#define wxLogInfo wxLogVerbose
1387#define wxVLogInfo wxVLogVerbose
1388
1389
1390// another special case: the level is passed as first argument of the function
1391// and so is not available to the macro
1392//
1393// notice that because of this, arguments of wxLogGeneric() are currently
1394// always evaluated, unlike for the other log functions
1395#define wxLogGeneric wxMAKE_LOGGER(Max).LogAtLevel
1396#define wxVLogGeneric(level, format, argptr) \
c602c59b 1397 if ( !wxLog::IsLevelEnabled(wxLOG_##level, wxLOG_COMPONENT) ) \
af588446
VZ
1398 {} \
1399 else \
1400 wxDO_LOGV(level, format, argptr)
1401
1402
1403// wxLogSysError() needs to stash the error code value in the log record info
1404// so it needs special handling too; additional complications arise because the
1405// error code may or not be present as the first argument
b804f992
VZ
1406//
1407// notice that we unfortunately can't avoid the call to wxSysErrorCode() even
1408// though it may be unneeded if an explicit error code is passed to us because
1409// the message might not be logged immediately (e.g. it could be queued for
1410// logging from the main thread later) and so we can't to wait until it is
1411// logged to determine whether we have last error or not as it will be too late
1412// and it will have changed already by then (in fact it even changes when
1413// wxString::Format() is called because of vsnprintf() inside it so it can
1414// change even much sooner)
af588446
VZ
1415#define wxLOG_KEY_SYS_ERROR_CODE "wx.sys_error"
1416
1417#define wxLogSysError \
c602c59b 1418 if ( !wxLog::IsLevelEnabled(wxLOG_Error, wxLOG_COMPONENT) ) \
af588446
VZ
1419 {} \
1420 else \
b804f992
VZ
1421 wxMAKE_LOGGER(Error).MaybeStore(wxLOG_KEY_SYS_ERROR_CODE, \
1422 wxSysErrorCode()).Log
af588446
VZ
1423
1424// unfortunately we can't have overloaded macros so we can't define versions
1425// both with and without error code argument and have to rely on LogV()
1426// overloads in wxLogger to select between them
1427#define wxVLogSysError \
b804f992
VZ
1428 wxMAKE_LOGGER(Error).MaybeStore(wxLOG_KEY_SYS_ERROR_CODE, \
1429 wxSysErrorCode()).LogV
af588446
VZ
1430
1431#if wxUSE_GUI
1432 // wxLogStatus() is similar to wxLogSysError() as it allows to optionally
1433 // specify the frame to which the message should go
1434 #define wxLOG_KEY_FRAME "wx.frame"
1435
1436 #define wxLogStatus \
c602c59b 1437 if ( !wxLog::IsLevelEnabled(wxLOG_Status, wxLOG_COMPONENT) ) \
af588446
VZ
1438 {} \
1439 else \
1440 wxMAKE_LOGGER(Status).MaybeStore(wxLOG_KEY_FRAME).Log
1441
1442 #define wxVLogStatus(format, argptr) \
1443 wxMAKE_LOGGER(Status).MaybeStore(wxLOG_KEY_FRAME).LogV
1444#endif // wxUSE_GUI
2523e9b7 1445
c9f78968 1446
88ac883a
VZ
1447#else // !wxUSE_LOG
1448
711f12ef
VZ
1449#undef wxUSE_LOG_DEBUG
1450#define wxUSE_LOG_DEBUG 0
1451
1452#undef wxUSE_LOG_TRACE
1453#define wxUSE_LOG_TRACE 0
1454
99fda03a
VS
1455#if defined(__WATCOMC__) || defined(__MINGW32__)
1456 // Mingw has similar problem with wxLogSysError:
1457 #define WX_WATCOM_OR_MINGW_ONLY_CODE( x ) x
1458#else
1459 #define WX_WATCOM_OR_MINGW_ONLY_CODE( x )
1460#endif
1461
af588446
VZ
1462// define macros for defining log functions which do nothing at all
1463//
1464// WX_WATCOM_ONLY_CODE is needed to work around
1465// http://bugzilla.openwatcom.org/show_bug.cgi?id=351
1466#define wxDEFINE_EMPTY_LOG_FUNCTION(level) \
b0d58b0e 1467 WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 1, (const wxFormatString&)) \
2523e9b7
VS
1468 WX_WATCOM_ONLY_CODE( \
1469 WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 1, (const char*)) \
1470 WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 1, (const wchar_t*)) \
1471 WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 1, (const wxCStrData&)) \
1472 ) \
b0d58b0e 1473 inline void wxVLog##level(const wxFormatString& WXUNUSED(format), \
59a14f69 1474 va_list WXUNUSED(argptr)) { } \
c9f78968 1475
af588446 1476#define wxDEFINE_EMPTY_LOG_FUNCTION2(level, argclass) \
b0d58b0e 1477 WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 2, (argclass, const wxFormatString&)) \
99fda03a 1478 WX_WATCOM_OR_MINGW_ONLY_CODE( \
2523e9b7
VS
1479 WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 2, (argclass, const char*)) \
1480 WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 2, (argclass, const wchar_t*)) \
1481 WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 2, (argclass, const wxCStrData&)) \
1482 ) \
c9f78968 1483 inline void wxVLog##level(argclass WXUNUSED(arg), \
b0d58b0e 1484 const wxFormatString& WXUNUSED(format), \
59a14f69 1485 va_list WXUNUSED(argptr)) {}
2523e9b7 1486
af588446
VZ
1487wxDEFINE_EMPTY_LOG_FUNCTION(FatalError);
1488wxDEFINE_EMPTY_LOG_FUNCTION(Error);
1489wxDEFINE_EMPTY_LOG_FUNCTION(SysError);
1490wxDEFINE_EMPTY_LOG_FUNCTION2(SysError, long);
1491wxDEFINE_EMPTY_LOG_FUNCTION(Warning);
1492wxDEFINE_EMPTY_LOG_FUNCTION(Message);
1493wxDEFINE_EMPTY_LOG_FUNCTION(Info);
1494wxDEFINE_EMPTY_LOG_FUNCTION(Verbose);
1495
1496wxDEFINE_EMPTY_LOG_FUNCTION2(Generic, wxLogLevel);
1497
1498#if wxUSE_GUI
1499 wxDEFINE_EMPTY_LOG_FUNCTION(Status);
1500 wxDEFINE_EMPTY_LOG_FUNCTION2(Status, wxFrame *);
1501#endif // wxUSE_GUI
1502
e30285ab 1503// Empty Class to fake wxLogNull
bddd7a8d 1504class WXDLLIMPEXP_BASE wxLogNull
e30285ab
VZ
1505{
1506public:
886dd7d2 1507 wxLogNull() { }
e30285ab
VZ
1508};
1509
1510// Dummy macros to replace some functions.
1511#define wxSysErrorCode() (unsigned long)0
1512#define wxSysErrorMsg( X ) (const wxChar*)NULL
1513
1514// Fake symbolic trace masks... for those that are used frequently
fda7962d 1515#define wxTRACE_OleCalls wxEmptyString // OLE interface calls
e30285ab 1516
88ac883a 1517#endif // wxUSE_LOG/!wxUSE_LOG
bdeb1f0d 1518
711f12ef
VZ
1519
1520// debug functions can be completely disabled in optimized builds
1521
1522// if these log functions are disabled, we prefer to define them as (empty)
1523// variadic macros as this completely removes them and their argument
1524// evaluation from the object code but if this is not supported by compiler we
1525// use empty inline functions instead (defining them as nothing would result in
1526// compiler warnings)
1527//
1528// note that making wxVLogDebug/Trace() themselves (empty inline) functions is
1529// a bad idea as some compilers are stupid enough to not inline even empty
1530// functions if their parameters are complicated enough, but by defining them
1531// as an empty inline function we ensure that even dumbest compilers optimise
1532// them away
1533#ifdef __BORLANDC__
1534 // but Borland gives "W8019: Code has no effect" for wxLogNop() so we need
1535 // to define it differently for it to avoid these warnings (same problem as
1536 // with wxUnusedVar())
1537 #define wxLogNop() { }
1538#else
1539 inline void wxLogNop() { }
1540#endif
1541
1542#if wxUSE_LOG_DEBUG
af588446
VZ
1543 #define wxLogDebug wxDO_LOG_IF_ENABLED(Debug)
1544 #define wxVLogDebug(format, argptr) wxDO_LOGV(Debug, format, argptr)
711f12ef
VZ
1545#else // !wxUSE_LOG_DEBUG
1546 #define wxVLogDebug(fmt, valist) wxLogNop()
d6b9496a 1547
711f12ef
VZ
1548 #ifdef HAVE_VARIADIC_MACROS
1549 #define wxLogDebug(fmt, ...) wxLogNop()
1550 #else // !HAVE_VARIADIC_MACROS
b0d58b0e 1551 WX_DEFINE_VARARG_FUNC_NOP(wxLogDebug, 1, (const wxFormatString&))
711f12ef
VZ
1552 #endif
1553#endif // wxUSE_LOG_DEBUG/!wxUSE_LOG_DEBUG
d6b9496a 1554
711f12ef 1555#if wxUSE_LOG_TRACE
af588446 1556 #define wxLogTrace \
c602c59b 1557 if ( !wxLog::IsLevelEnabled(wxLOG_Trace, wxLOG_COMPONENT) ) \
af588446
VZ
1558 {} \
1559 else \
1560 wxMAKE_LOGGER(Trace).LogTrace
89d62794
VZ
1561 #define wxVLogTrace \
1562 if ( !wxLog::IsLevelEnabled(wxLOG_Trace, wxLOG_COMPONENT) ) \
1563 {} \
1564 else \
1565 wxMAKE_LOGGER(Trace).LogVTrace
711f12ef 1566#else // !wxUSE_LOG_TRACE
388a1f66 1567 #define wxVLogTrace(mask, fmt, valist) wxLogNop()
ca766534
VS
1568
1569 #ifdef HAVE_VARIADIC_MACROS
388a1f66 1570 #define wxLogTrace(mask, fmt, ...) wxLogNop()
ca766534 1571 #else // !HAVE_VARIADIC_MACROS
69e3710e 1572 #if WXWIN_COMPATIBILITY_2_8
b0d58b0e 1573 WX_DEFINE_VARARG_FUNC_NOP(wxLogTrace, 2, (wxTraceMask, const wxFormatString&))
69e3710e 1574 #endif
b0d58b0e 1575 WX_DEFINE_VARARG_FUNC_NOP(wxLogTrace, 2, (const wxString&, const wxFormatString&))
44be939a
VS
1576 #ifdef __WATCOMC__
1577 // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351
1578 WX_DEFINE_VARARG_FUNC_NOP(wxLogTrace, 2, (const char*, const char*))
1579 WX_DEFINE_VARARG_FUNC_NOP(wxLogTrace, 2, (const wchar_t*, const wchar_t*))
1580 #endif
ca766534 1581 #endif // HAVE_VARIADIC_MACROS/!HAVE_VARIADIC_MACROS
711f12ef 1582#endif // wxUSE_LOG_TRACE/!wxUSE_LOG_TRACE
c801d85f 1583
c11d62a6
VZ
1584// wxLogFatalError helper: show the (fatal) error to the user in a safe way,
1585// i.e. without using wxMessageBox() for example because it could crash
bddd7a8d 1586void WXDLLIMPEXP_BASE
886dd7d2 1587wxSafeShowMessage(const wxString& title, const wxString& text);
c11d62a6 1588
88ac883a
VZ
1589// ----------------------------------------------------------------------------
1590// debug only logging functions: use them with API name and error code
1591// ----------------------------------------------------------------------------
c801d85f 1592
23fb9bf5 1593#if wxUSE_LOG_DEBUG
42e69d6b
VZ
1594 // make life easier for people using VC++ IDE: clicking on the message
1595 // will take us immediately to the place of the failed API
1596#ifdef __VISUALC__
4b7f2165
VZ
1597 #define wxLogApiError(api, rc) \
1598 wxLogDebug(wxT("%s(%d): '%s' failed with error 0x%08lx (%s)."), \
0accd1cf 1599 __FILE__, __LINE__, api, \
8b94d999 1600 (long)rc, wxSysErrorMsg(rc))
42e69d6b 1601#else // !VC++
4b7f2165 1602 #define wxLogApiError(api, rc) \
18da7cf2
VZ
1603 wxLogDebug(wxT("In file %s at line %d: '%s' failed with ") \
1604 wxT("error 0x%08lx (%s)."), \
0accd1cf 1605 __FILE__, __LINE__, api, \
8b94d999 1606 (long)rc, wxSysErrorMsg(rc))
42e69d6b
VZ
1607#endif // VC++/!VC++
1608
1609 #define wxLogLastError(api) wxLogApiError(api, wxSysErrorCode())
1610
23fb9bf5 1611#else // !wxUSE_LOG_DEBUG
388a1f66
VZ
1612 #define wxLogApiError(api, err) wxLogNop()
1613 #define wxLogLastError(api) wxLogNop()
23fb9bf5 1614#endif // wxUSE_LOG_DEBUG/!wxUSE_LOG_DEBUG
c801d85f 1615
a619fa3f
DE
1616// wxCocoa has additiional trace masks
1617#if defined(__WXCOCOA__)
1618#include "wx/cocoa/log.h"
1619#endif
1620
82e77a80
VS
1621#ifdef WX_WATCOM_ONLY_CODE
1622 #undef WX_WATCOM_ONLY_CODE
1623#endif
1624
7d9550df 1625// macro which disables debug logging in release builds: this is done by
e4431849 1626// default by wxIMPLEMENT_APP() so usually it doesn't need to be used explicitly
ff464152 1627#if defined(NDEBUG) && wxUSE_LOG_DEBUG
7d9550df
VZ
1628 #define wxDISABLE_DEBUG_LOGGING_IN_RELEASE_BUILD() \
1629 wxLog::SetLogLevel(wxLOG_Info)
1630#else // !NDEBUG
1631 #define wxDISABLE_DEBUG_LOGGING_IN_RELEASE_BUILD()
1632#endif // NDEBUG/!NDEBUG
1633
34138703 1634#endif // _WX_LOG_H_
04662def 1635