]> git.saurik.com Git - wxWidgets.git/blob - include/wx/log.h
Complete wxEVT_MENU_{OPEN,CLOSE} implementation in wxMSW and wxOSX.
[wxWidgets.git] / include / wx / log.h
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: wx/log.h
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>
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifndef _WX_LOG_H_
13 #define _WX_LOG_H_
14
15 #include "wx/defs.h"
16
17 // ----------------------------------------------------------------------------
18 // types
19 // ----------------------------------------------------------------------------
20
21 // NB: this is needed even if wxUSE_LOG == 0
22 typedef unsigned long wxLogLevel;
23
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
31
32 #ifdef __WXMSW__
33 #define wxTraceOleCalls 0x0100 // OLE interface calls
34 #endif
35
36 typedef unsigned long wxTraceMask;
37 #endif // WXWIN_COMPATIBILITY_2_8
38
39 // ----------------------------------------------------------------------------
40 // headers
41 // ----------------------------------------------------------------------------
42
43 #include "wx/string.h"
44 #include "wx/strvararg.h"
45
46 // ----------------------------------------------------------------------------
47 // forward declarations
48 // ----------------------------------------------------------------------------
49
50 class WXDLLIMPEXP_FWD_BASE wxObject;
51
52 #if wxUSE_GUI
53 class WXDLLIMPEXP_FWD_CORE wxFrame;
54 #endif // wxUSE_GUI
55
56 #if wxUSE_LOG
57
58 #include "wx/arrstr.h"
59
60 #ifndef __WXPALMOS5__
61 #ifndef __WXWINCE__
62 #include <time.h> // for time_t
63 #endif
64 #endif // ! __WXPALMOS5__
65
66 #include "wx/dynarray.h"
67 #include "wx/hashmap.h"
68
69 #if wxUSE_THREADS
70 #include "wx/thread.h"
71 #endif // wxUSE_THREADS
72
73 // wxUSE_LOG_DEBUG enables the debug log messages
74 #ifndef wxUSE_LOG_DEBUG
75 #if wxDEBUG_LEVEL
76 #define wxUSE_LOG_DEBUG 1
77 #else // !wxDEBUG_LEVEL
78 #define wxUSE_LOG_DEBUG 0
79 #endif
80 #endif
81
82 // wxUSE_LOG_TRACE enables the trace messages, they are disabled by default
83 #ifndef wxUSE_LOG_TRACE
84 #if wxDEBUG_LEVEL
85 #define wxUSE_LOG_TRACE 1
86 #else // !wxDEBUG_LEVEL
87 #define wxUSE_LOG_TRACE 0
88 #endif
89 #endif // wxUSE_LOG_TRACE
90
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
104 // ----------------------------------------------------------------------------
105 // constants
106 // ----------------------------------------------------------------------------
107
108 // different standard log levels (you may also define your own)
109 enum wxLogLevelValues
110 {
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)
115 wxLOG_Status, // informational: might go to the status line of GUI app
116 wxLOG_Info, // informational message (a.k.a. 'Verbose')
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)
120 wxLOG_User = 100, // user defined levels start here
121 wxLOG_Max = 10000
122 };
123
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
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
132
133 #ifdef __WXMSW__
134 #define wxTRACE_OleCalls wxT("ole") // OLE interface calls
135 #endif
136
137 #include "wx/iosfwrap.h"
138
139 // ----------------------------------------------------------------------------
140 // information about a log record, i.e. unit of log output
141 // ----------------------------------------------------------------------------
142
143 class wxLogRecordInfo
144 {
145 public:
146 // default ctor creates an uninitialized object
147 wxLogRecordInfo()
148 {
149 memset(this, 0, sizeof(*this));
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_,
156 const char *func_,
157 const char *component_)
158 {
159 filename = filename_;
160 func = func_;
161 line = line_;
162 component = component_;
163
164 timestamp = time(NULL);
165
166 #if wxUSE_THREADS
167 threadId = wxThread::GetCurrentId();
168 #endif // wxUSE_THREADS
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;
188 }
189
190 // dtor is non-virtual, this class is not meant to be derived from
191 ~wxLogRecordInfo()
192 {
193 delete m_data;
194 }
195
196
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
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
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
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
269 private:
270 void Copy(const wxLogRecordInfo& other)
271 {
272 memcpy(this, &other, sizeof(*this));
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;
288 };
289
290 #define wxLOG_KEY_TRACE_MASK "wx.trace_mask"
291
292 // ----------------------------------------------------------------------------
293 // log record: a unit of log output
294 // ----------------------------------------------------------------------------
295
296 struct 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
312 // ----------------------------------------------------------------------------
313 // Derive from this class to customize format of log messages.
314 // ----------------------------------------------------------------------------
315
316 class WXDLLIMPEXP_BASE wxLogFormatter
317 {
318 public:
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
333 protected:
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
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
343 // ----------------------------------------------------------------------------
344
345 class WXDLLIMPEXP_BASE wxLog
346 {
347 public:
348 // ctor
349 wxLog() : m_formatter(new wxLogFormatter) { }
350
351 // make dtor virtual for all derived classes
352 virtual ~wxLog();
353
354
355 // log messages selection
356 // ----------------------
357
358 // these functions allow to completely disable all log messages or disable
359 // log messages at level less important than specified for the current
360 // thread
361
362 // is logging enabled at all now?
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 }
372
373 // change the flag state, return the previous one
374 static bool EnableLogging(bool enable = true)
375 {
376 #if wxUSE_THREADS
377 if ( !wxThread::IsMain() )
378 return EnableThreadLogging(enable);
379 #endif // wxUSE_THREADS
380
381 bool doLogOld = ms_doLog;
382 ms_doLog = enable;
383 return doLogOld;
384 }
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
425 // message buffering
426 // -----------------
427
428 // flush shows all messages if they're not logged immediately (FILE
429 // and iostream logs don't need it, but wxLogGui does to avoid showing
430 // 17 modal dialogs one after another)
431 virtual void Flush();
432
433 // flush the active target if any and also output any pending messages from
434 // background threads
435 static void FlushActive();
436
437 // only one sink is active at each moment get current log target, will call
438 // wxAppTraits::CreateLogTarget() to create one if none exists
439 static wxLog *GetActiveTarget();
440
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
449
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)
453 static void Suspend() { ms_suspendCount++; }
454
455 // must be called for each Suspend()!
456 static void Resume() { ms_suspendCount--; }
457
458 // should GetActiveTarget() try to create a new log object if the
459 // current is NULL?
460 static void DontCreateOnDemand();
461
462 // Make GetActiveTarget() create a new log object again.
463 static void DoCreateOnDemand();
464
465 // log the count of repeating messages instead of logging the messages
466 // multiple times
467 static void SetRepetitionCounting(bool bRepetCounting = true)
468 { ms_bRepetCounting = bRepetCounting; }
469
470 // gets duplicate counting status
471 static bool GetRepetitionCounting() { return ms_bRepetCounting; }
472
473 // add string trace mask
474 static void AddTraceMask(const wxString& str);
475
476 // add string trace mask
477 static void RemoveTraceMask(const wxString& str);
478
479 // remove all string trace masks
480 static void ClearTraceMasks();
481
482 // get string trace masks: note that this is MT-unsafe if other threads can
483 // call AddTraceMask() concurrently
484 static const wxArrayString& GetTraceMasks();
485
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
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.
509 static void SetTimestamp(const wxString& ts) { ms_timestamp = ts; }
510
511 // disable time stamping of log messages
512 static void DisableTimestamp() { SetTimestamp(wxEmptyString); }
513
514
515 // get the current timestamp format string (maybe empty)
516 static const wxString& GetTimestamp() { return ms_timestamp; }
517
518
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
522
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.
525 static void TimeStamp(wxString *str);
526 static void TimeStamp(wxString *str, time_t t);
527
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)
534 {
535 DoLogRecord(level, msg, info);
536 }
537
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 }
564
565
566 // this method exists for backwards compatibility only, don't use
567 bool HasPendingMessages() const { return true; }
568
569 #if WXWIN_COMPATIBILITY_2_6
570 // this function doesn't do anything any more, don't call it
571 static wxDEPRECATED_INLINE(
572 wxChar *SetLogBuffer(wxChar *, size_t = 0), return NULL;
573 );
574 #endif // WXWIN_COMPATIBILITY_2_6
575
576 // don't use integer masks any more, use string trace masks instead
577 #if WXWIN_COMPATIBILITY_2_8
578 static wxDEPRECATED_INLINE( void SetTraceMask(wxTraceMask ulMask),
579 ms_ulTraceMask = ulMask; )
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; }
584 #endif // WXWIN_COMPATIBILITY_2_8
585
586 protected:
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
591
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)
614 #if WXWIN_COMPATIBILITY_2_8
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 );
622
623 // these shouldn't be used by new code
624 wxDEPRECATED_BUT_USED_INTERNALLY_INLINE(
625 virtual void DoLogString(const char *WXUNUSED(szString),
626 time_t WXUNUSED(t)),
627 wxEMPTY_PARAMETER_VALUE
628 )
629
630 wxDEPRECATED_BUT_USED_INTERNALLY_INLINE(
631 virtual void DoLogString(const wchar_t *WXUNUSED(wzString),
632 time_t WXUNUSED(t)),
633 wxEMPTY_PARAMETER_VALUE
634 )
635 #endif // WXWIN_COMPATIBILITY_2_8
636
637
638 // log a message indicating the number of times the previous message was
639 // repeated if previous repetition counter is strictly positive, does
640 // nothing otherwise; return the old value of repetition counter
641 unsigned LogLastRepeatIfNeeded();
642
643 private:
644 #if wxUSE_THREADS
645 // called from FlushActive() to really log any buffered messages logged
646 // from the other threads
647 void FlushThreadMessages();
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);
653 #endif // wxUSE_THREADS
654
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
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()
664 // when it plays back the buffered messages logged from the other threads
665 void CallDoLogNow(wxLogLevel level,
666 const wxString& msg,
667 const wxLogRecordInfo& info);
668
669
670 // variables
671 // ----------------
672
673 wxLogFormatter *m_formatter; // We own this pointer.
674
675
676 // static variables
677 // ----------------
678
679 // if true, don't log the same message multiple times, only log it once
680 // with the number of times it was repeated
681 static bool ms_bRepetCounting;
682
683 static wxLog *ms_pLogger; // currently active log sink
684 static bool ms_doLog; // false => all logging disabled
685 static bool ms_bAutoCreate; // create new log targets on demand?
686 static bool ms_bVerbose; // false => ignore LogInfo messages
687
688 static wxLogLevel ms_logLevel; // limit logging to levels <= ms_logLevel
689
690 static size_t ms_suspendCount; // if positive, logs are not flushed
691
692 // format string for strftime(), if empty, time stamping log messages is
693 // disabled
694 static wxString ms_timestamp;
695
696 #if WXWIN_COMPATIBILITY_2_8
697 static wxTraceMask ms_ulTraceMask; // controls wxLogTrace behaviour
698 #endif // WXWIN_COMPATIBILITY_2_8
699 };
700
701 // ----------------------------------------------------------------------------
702 // "trivial" derivations of wxLog
703 // ----------------------------------------------------------------------------
704
705 // log everything except for the debug/trace messages (which are passed to
706 // wxMessageOutputDebug) to a buffer
707 class WXDLLIMPEXP_BASE wxLogBuffer : public wxLog
708 {
709 public:
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
719 protected:
720 virtual void DoLogTextAtLevel(wxLogLevel level, const wxString& msg);
721
722 private:
723 wxString m_str;
724
725 wxDECLARE_NO_COPY_CLASS(wxLogBuffer);
726 };
727
728
729 // log everything to a "FILE *", stderr by default
730 class WXDLLIMPEXP_BASE wxLogStderr : public wxLog
731 {
732 public:
733 // redirect log output to a FILE
734 wxLogStderr(FILE *fp = NULL);
735
736 protected:
737 // implement sink function
738 virtual void DoLogText(const wxString& msg);
739
740 FILE *m_fp;
741
742 wxDECLARE_NO_COPY_CLASS(wxLogStderr);
743 };
744
745 #if wxUSE_STD_IOSTREAM
746
747 // log everything to an "ostream", cerr by default
748 class WXDLLIMPEXP_BASE wxLogStream : public wxLog
749 {
750 public:
751 // redirect log output to an ostream
752 wxLogStream(wxSTD ostream *ostr = (wxSTD ostream *) NULL);
753
754 protected:
755 // implement sink function
756 virtual void DoLogText(const wxString& msg);
757
758 // using ptr here to avoid including <iostream.h> from this file
759 wxSTD ostream *m_ostr;
760 };
761
762 #endif // wxUSE_STD_IOSTREAM
763
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 */
784 class WXDLLIMPEXP_BASE wxLogNull
785 {
786 public:
787 wxLogNull() : m_flagOld(wxLog::EnableLogging(false)) { }
788 ~wxLogNull() { (void)wxLog::EnableLogging(m_flagOld); }
789
790 private:
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
803 class WXDLLIMPEXP_BASE wxLogChain : public wxLog
804 {
805 public:
806 wxLogChain(wxLog *logger);
807 virtual ~wxLogChain();
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
825 // call to avoid destroying the old log target
826 void DetachOldLog() { m_logOld = NULL; }
827
828 protected:
829 // pass the record to the old logger if needed
830 virtual void DoLogRecord(wxLogLevel level,
831 const wxString& msg,
832 const wxLogRecordInfo& info);
833
834 private:
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;
843
844 wxDECLARE_NO_COPY_CLASS(wxLogChain);
845 };
846
847 // a chain log target which uses itself as the new logger
848
849 #define wxLogPassThrough wxLogInterposer
850
851 class WXDLLIMPEXP_BASE wxLogInterposer : public wxLogChain
852 {
853 public:
854 wxLogInterposer();
855
856 private:
857 wxDECLARE_NO_COPY_CLASS(wxLogInterposer);
858 };
859
860 // a temporary interposer which doesn't destroy the old log target
861 // (calls DetachOldLog)
862
863 class WXDLLIMPEXP_BASE wxLogInterposerTemp : public wxLogChain
864 {
865 public:
866 wxLogInterposerTemp();
867
868 private:
869 wxDECLARE_NO_COPY_CLASS(wxLogInterposerTemp);
870 };
871
872 #if wxUSE_GUI
873 // include GUI log targets:
874 #include "wx/generic/logg.h"
875 #endif // wxUSE_GUI
876
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
888 class wxLogger
889 {
890 public:
891 // ctor takes the basic information about the log record
892 wxLogger(wxLogLevel level,
893 const char *filename,
894 int line,
895 const char *func,
896 const char *component)
897 : m_level(level),
898 m_info(filename, line, func, component)
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)
915 wxLogger& MaybeStore(const wxString& key, wxUIntPtr value = 0)
916 {
917 wxASSERT_MSG( m_optKey.empty(), "can only have one optional value" );
918 m_optKey = key;
919
920 m_info.StoreValue(key, value);
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
932 if ( m_level == wxLOG_FatalError ||
933 wxLog::IsLevelEnabled(m_level, m_info.component) )
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
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
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
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
993 WX_DEFINE_VARARG_FUNC_VOID
994 (
995 Log,
996 2, (wxObject *, const wxFormatString&),
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
1012 // integer mask as first argument determining whether the message should be
1013 // logged or not
1014 WX_DEFINE_VARARG_FUNC_VOID
1015 (
1016 LogTrace,
1017 2, (const wxString&, const wxFormatString&),
1018 DoLogTrace, DoLogTraceUtf8
1019 )
1020
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
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,
1059 2, (wxObject *, const wxString&),
1060 (f1, wxFormatString(f2)))
1061 WX_VARARG_WATCOM_WORKAROUND(void, Log,
1062 2, (wxObject *, const wxCStrData&),
1063 (f1, wxFormatString(f2)))
1064 WX_VARARG_WATCOM_WORKAROUND(void, Log,
1065 2, (wxObject *, const char *),
1066 (f1, wxFormatString(f2)))
1067 WX_VARARG_WATCOM_WORKAROUND(void, Log,
1068 2, (wxObject *, const wchar_t *),
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)))
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
1111 #endif // __WATCOMC__
1112
1113 private:
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 {
1145 if ( !wxLog::IsLevelEnabled(level, m_info.component) )
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 }
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
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 {
1214 if ( !wxLog::IsLevelEnabled(level, m_info.component) )
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 }
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
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 {
1259 DoCallOnLog(m_level, format, argptr);
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
1271 // ============================================================================
1272 // global functions
1273 // ============================================================================
1274
1275 // ----------------------------------------------------------------------------
1276 // get error code/error message from system in a portable way
1277 // ----------------------------------------------------------------------------
1278
1279 // return the last system error code
1280 WXDLLIMPEXP_BASE unsigned long wxSysErrorCode();
1281
1282 // return the error message for given (or last if 0) error code
1283 WXDLLIMPEXP_BASE const wxChar* wxSysErrorMsg(unsigned long nErrCode = 0);
1284
1285 // ----------------------------------------------------------------------------
1286 // define wxLog<level>() functions which can be used by application instead of
1287 // stdio, iostream &c for log messages for easy redirection
1288 // ----------------------------------------------------------------------------
1289
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 */
1317
1318 // creates wxLogger object for the current location
1319 #define wxMAKE_LOGGER(level) \
1320 wxLogger(wxLOG_##level, __FILE__, __LINE__, __WXFUNCTION__, wxLOG_COMPONENT)
1321
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
1325
1326 // this is the non-vararg equivalent
1327 #define wxDO_LOGV(level, format, argptr) \
1328 wxMAKE_LOGGER(level).LogV(format, argptr)
1329
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) \
1353 if ( !wxLog::IsLevelEnabled(wxLOG_##level, wxLOG_COMPONENT) ) \
1354 {} \
1355 else \
1356 wxDO_LOG(level)
1357
1358 // wxLogFatalError() is special as it can't be disabled
1359 #define wxLogFatalError wxDO_LOG(FatalError)
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 \
1373 if ( !(wxLog::IsLevelEnabled(wxLOG_Info, wxLOG_COMPONENT) && \
1374 wxLog::GetVerbose()) ) \
1375 {} \
1376 else \
1377 wxDO_LOG(Info)
1378 #define wxVLogVerbose(format, argptr) \
1379 if ( !(wxLog::IsLevelEnabled(wxLOG_Info, wxLOG_COMPONENT) && \
1380 wxLog::GetVerbose()) ) \
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) \
1397 if ( !wxLog::IsLevelEnabled(wxLOG_##level, wxLOG_COMPONENT) ) \
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
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)
1415 #define wxLOG_KEY_SYS_ERROR_CODE "wx.sys_error"
1416
1417 #define wxLogSysError \
1418 if ( !wxLog::IsLevelEnabled(wxLOG_Error, wxLOG_COMPONENT) ) \
1419 {} \
1420 else \
1421 wxMAKE_LOGGER(Error).MaybeStore(wxLOG_KEY_SYS_ERROR_CODE, \
1422 wxSysErrorCode()).Log
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 \
1428 wxMAKE_LOGGER(Error).MaybeStore(wxLOG_KEY_SYS_ERROR_CODE, \
1429 wxSysErrorCode()).LogV
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 \
1437 if ( !wxLog::IsLevelEnabled(wxLOG_Status, wxLOG_COMPONENT) ) \
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
1445
1446
1447 #else // !wxUSE_LOG
1448
1449 #undef wxUSE_LOG_DEBUG
1450 #define wxUSE_LOG_DEBUG 0
1451
1452 #undef wxUSE_LOG_TRACE
1453 #define wxUSE_LOG_TRACE 0
1454
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
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) \
1467 WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 1, (const wxFormatString&)) \
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 ) \
1473 inline void wxVLog##level(const wxFormatString& WXUNUSED(format), \
1474 va_list WXUNUSED(argptr)) { } \
1475
1476 #define wxDEFINE_EMPTY_LOG_FUNCTION2(level, argclass) \
1477 WX_DEFINE_VARARG_FUNC_NOP(wxLog##level, 2, (argclass, const wxFormatString&)) \
1478 WX_WATCOM_OR_MINGW_ONLY_CODE( \
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 ) \
1483 inline void wxVLog##level(argclass WXUNUSED(arg), \
1484 const wxFormatString& WXUNUSED(format), \
1485 va_list WXUNUSED(argptr)) {}
1486
1487 wxDEFINE_EMPTY_LOG_FUNCTION(FatalError);
1488 wxDEFINE_EMPTY_LOG_FUNCTION(Error);
1489 wxDEFINE_EMPTY_LOG_FUNCTION(SysError);
1490 wxDEFINE_EMPTY_LOG_FUNCTION2(SysError, long);
1491 wxDEFINE_EMPTY_LOG_FUNCTION(Warning);
1492 wxDEFINE_EMPTY_LOG_FUNCTION(Message);
1493 wxDEFINE_EMPTY_LOG_FUNCTION(Info);
1494 wxDEFINE_EMPTY_LOG_FUNCTION(Verbose);
1495
1496 wxDEFINE_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
1503 // Empty Class to fake wxLogNull
1504 class WXDLLIMPEXP_BASE wxLogNull
1505 {
1506 public:
1507 wxLogNull() { }
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
1515 #define wxTRACE_OleCalls wxEmptyString // OLE interface calls
1516
1517 #endif // wxUSE_LOG/!wxUSE_LOG
1518
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
1543 #define wxLogDebug wxDO_LOG_IF_ENABLED(Debug)
1544 #define wxVLogDebug(format, argptr) wxDO_LOGV(Debug, format, argptr)
1545 #else // !wxUSE_LOG_DEBUG
1546 #define wxVLogDebug(fmt, valist) wxLogNop()
1547
1548 #ifdef HAVE_VARIADIC_MACROS
1549 #define wxLogDebug(fmt, ...) wxLogNop()
1550 #else // !HAVE_VARIADIC_MACROS
1551 WX_DEFINE_VARARG_FUNC_NOP(wxLogDebug, 1, (const wxFormatString&))
1552 #endif
1553 #endif // wxUSE_LOG_DEBUG/!wxUSE_LOG_DEBUG
1554
1555 #if wxUSE_LOG_TRACE
1556 #define wxLogTrace \
1557 if ( !wxLog::IsLevelEnabled(wxLOG_Trace, wxLOG_COMPONENT) ) \
1558 {} \
1559 else \
1560 wxMAKE_LOGGER(Trace).LogTrace
1561 #define wxVLogTrace \
1562 if ( !wxLog::IsLevelEnabled(wxLOG_Trace, wxLOG_COMPONENT) ) \
1563 {} \
1564 else \
1565 wxMAKE_LOGGER(Trace).LogVTrace
1566 #else // !wxUSE_LOG_TRACE
1567 #define wxVLogTrace(mask, fmt, valist) wxLogNop()
1568
1569 #ifdef HAVE_VARIADIC_MACROS
1570 #define wxLogTrace(mask, fmt, ...) wxLogNop()
1571 #else // !HAVE_VARIADIC_MACROS
1572 #if WXWIN_COMPATIBILITY_2_8
1573 WX_DEFINE_VARARG_FUNC_NOP(wxLogTrace, 2, (wxTraceMask, const wxFormatString&))
1574 #endif
1575 WX_DEFINE_VARARG_FUNC_NOP(wxLogTrace, 2, (const wxString&, const wxFormatString&))
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
1581 #endif // HAVE_VARIADIC_MACROS/!HAVE_VARIADIC_MACROS
1582 #endif // wxUSE_LOG_TRACE/!wxUSE_LOG_TRACE
1583
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
1586 void WXDLLIMPEXP_BASE
1587 wxSafeShowMessage(const wxString& title, const wxString& text);
1588
1589 // ----------------------------------------------------------------------------
1590 // debug only logging functions: use them with API name and error code
1591 // ----------------------------------------------------------------------------
1592
1593 #if wxUSE_LOG_DEBUG
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__
1597 #define wxLogApiError(api, rc) \
1598 wxLogDebug(wxT("%s(%d): '%s' failed with error 0x%08lx (%s)."), \
1599 __FILE__, __LINE__, api, \
1600 (long)rc, wxSysErrorMsg(rc))
1601 #else // !VC++
1602 #define wxLogApiError(api, rc) \
1603 wxLogDebug(wxT("In file %s at line %d: '%s' failed with ") \
1604 wxT("error 0x%08lx (%s)."), \
1605 __FILE__, __LINE__, api, \
1606 (long)rc, wxSysErrorMsg(rc))
1607 #endif // VC++/!VC++
1608
1609 #define wxLogLastError(api) wxLogApiError(api, wxSysErrorCode())
1610
1611 #else // !wxUSE_LOG_DEBUG
1612 #define wxLogApiError(api, err) wxLogNop()
1613 #define wxLogLastError(api) wxLogNop()
1614 #endif // wxUSE_LOG_DEBUG/!wxUSE_LOG_DEBUG
1615
1616 // wxCocoa has additiional trace masks
1617 #if defined(__WXCOCOA__)
1618 #include "wx/cocoa/log.h"
1619 #endif
1620
1621 #ifdef WX_WATCOM_ONLY_CODE
1622 #undef WX_WATCOM_ONLY_CODE
1623 #endif
1624
1625 // macro which disables debug logging in release builds: this is done by
1626 // default by wxIMPLEMENT_APP() so usually it doesn't need to be used explicitly
1627 #if defined(NDEBUG) && wxUSE_LOG_DEBUG
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
1634 #endif // _WX_LOG_H_
1635