log.h 58 KB

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