home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2233.zip / wxOS2-2_3_3.zip / wxWindows-2.3.3 / include / wx / log.h < prev    next >
C/C++ Source or Header  |  2002-09-04  |  23KB  |  602 lines

  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: log.h,v 1.72 2002/09/04 09:35:13 RL Exp $
  8. // Copyright:   (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
  9. // Licence:     wxWindows license
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. #ifndef   _WX_LOG_H_
  13. #define   _WX_LOG_H_
  14.  
  15. #if defined(__GNUG__) && !defined(__APPLE__)
  16.     #pragma interface "log.h"
  17. #endif
  18.  
  19. #include "wx/setup.h"
  20. #include "wx/string.h"
  21.  
  22. // ----------------------------------------------------------------------------
  23. // forward declarations
  24. // ----------------------------------------------------------------------------
  25.  
  26. class WXDLLEXPORT wxTextCtrl;
  27. class WXDLLEXPORT wxLogFrame;
  28. class WXDLLEXPORT wxFrame;
  29.  
  30. // ----------------------------------------------------------------------------
  31. // types
  32. // ----------------------------------------------------------------------------
  33.  
  34. typedef unsigned long wxTraceMask;
  35. typedef unsigned long wxLogLevel;
  36.  
  37. // ----------------------------------------------------------------------------
  38. // headers
  39. // ----------------------------------------------------------------------------
  40.  
  41. #if wxUSE_LOG
  42.  
  43. #include <time.h>   // for time_t
  44.  
  45. #include "wx/dynarray.h"
  46.  
  47. // ----------------------------------------------------------------------------
  48. // constants
  49. // ----------------------------------------------------------------------------
  50.  
  51. // different standard log levels (you may also define your own)
  52. enum
  53. {
  54.     wxLOG_FatalError, // program can't continue, abort immediately
  55.     wxLOG_Error,      // a serious error, user must be informed about it
  56.     wxLOG_Warning,    // user is normally informed about it but may be ignored
  57.     wxLOG_Message,    // normal message (i.e. normal output of a non GUI app)
  58.     wxLOG_Info,       // informational message (a.k.a. 'Verbose')
  59.     wxLOG_Status,     // informational: might go to the status line of GUI app
  60.     wxLOG_Debug,      // never shown to the user, disabled in release mode
  61.     wxLOG_Trace,      // trace messages are also only enabled in debug mode
  62.     wxLOG_Progress,   // used for progress indicator (not yet)
  63.     wxLOG_User = 100  // user defined levels start here
  64. };
  65.  
  66. // symbolic trace masks - wxLogTrace("foo", "some trace message...") will be
  67. // discarded unless the string "foo" has been added to the list of allowed
  68. // ones with AddTraceMask()
  69.  
  70. #define wxTRACE_MemAlloc wxT("memalloc") // trace memory allocation (new/delete)
  71. #define wxTRACE_Messages wxT("messages") // trace window messages/X callbacks
  72. #define wxTRACE_ResAlloc wxT("resalloc") // trace GDI resource allocation
  73. #define wxTRACE_RefCount wxT("refcount") // trace various ref counting operations
  74.  
  75. #ifdef  __WXMSW__
  76.     #define wxTRACE_OleCalls wxT("ole")  // OLE interface calls
  77. #endif
  78.  
  79. // the trace masks have been superceded by symbolic trace constants, they're
  80. // for compatibility only andwill be removed soon - do NOT use them
  81.  
  82. // meaning of different bits of the trace mask (which allows selectively
  83. // enable/disable some trace messages)
  84. #define wxTraceMemAlloc 0x0001  // trace memory allocation (new/delete)
  85. #define wxTraceMessages 0x0002  // trace window messages/X callbacks
  86. #define wxTraceResAlloc 0x0004  // trace GDI resource allocation
  87. #define wxTraceRefCount 0x0008  // trace various ref counting operations
  88.  
  89. #ifdef  __WXMSW__
  90.     #define wxTraceOleCalls 0x0100  // OLE interface calls
  91. #endif
  92.  
  93. #include "wx/ioswrap.h"
  94.  
  95. // ----------------------------------------------------------------------------
  96. // derive from this class to redirect (or suppress, or ...) log messages
  97. // normally, only a single instance of this class exists but it's not enforced
  98. // ----------------------------------------------------------------------------
  99.  
  100. class WXDLLEXPORT wxLog
  101. {
  102. public:
  103.     // ctor
  104.     wxLog();
  105.  
  106.     // Internal buffer.
  107.         // Allow replacement of the fixed size static buffer with
  108.         // a user allocated one.  Pass in NULL to restore the
  109.         // built in static buffer.
  110.     static wxChar *SetLogBuffer( wxChar *buf, size_t size = 0 );
  111.  
  112.     // these functions allow to completely disable all log messages
  113.         // is logging disabled now?
  114.     static bool IsEnabled() { return ms_doLog; }
  115.         // change the flag state, return the previous one
  116.     static bool EnableLogging(bool doIt = TRUE)
  117.         { bool doLogOld = ms_doLog; ms_doLog = doIt; return doLogOld; }
  118.  
  119.     // static sink function - see DoLog() for function to overload in the
  120.     // derived classes
  121.     static void OnLog(wxLogLevel level, const wxChar *szString, time_t t)
  122.     {
  123.         if ( IsEnabled() ) {
  124.             wxLog *pLogger = GetActiveTarget();
  125.             if ( pLogger )
  126.                 pLogger->DoLog(level, szString, t);
  127.         }
  128.     }
  129.  
  130.     // message buffering
  131.         // flush shows all messages if they're not logged immediately (FILE
  132.         // and iostream logs don't need it, but wxGuiLog does to avoid showing
  133.         // 17 modal dialogs one after another)
  134.     virtual void Flush();
  135.         // call to Flush() may be optimized: call it only if this function
  136.         // returns true (although Flush() also returns immediately if there is
  137.         // no messages, this functions is more efficient because inline)
  138.     bool HasPendingMessages() const { return m_bHasMessages; }
  139.  
  140.     // only one sink is active at each moment
  141.         // flush the active target if any
  142.     static void FlushActive()
  143.     {
  144.         if ( !ms_suspendCount )
  145.         {
  146.             wxLog *log = GetActiveTarget();
  147.             if ( log && log->HasPendingMessages() )
  148.                 log->Flush();
  149.         }
  150.     }
  151.         // get current log target, will call wxApp::CreateLogTarget() to
  152.         // create one if none exists
  153.     static wxLog *GetActiveTarget();
  154.         // change log target, pLogger may be NULL
  155.     static wxLog *SetActiveTarget(wxLog *pLogger);
  156.  
  157.         // suspend the message flushing of the main target until the next call
  158.         // to Resume() - this is mainly for internal use (to prevent wxYield()
  159.         // from flashing the messages)
  160.     static void Suspend() { ms_suspendCount++; }
  161.         // must be called for each Suspend()!
  162.     static void Resume() { ms_suspendCount--; }
  163.  
  164.     // functions controlling the default wxLog behaviour
  165.         // verbose mode is activated by standard command-line '-verbose'
  166.         // option
  167.     static void SetVerbose(bool bVerbose = TRUE) { ms_bVerbose = bVerbose; }
  168.         // should GetActiveTarget() try to create a new log object if the
  169.         // current is NULL?
  170.     static void DontCreateOnDemand();
  171.  
  172.         // trace mask (see wxTraceXXX constants for details)
  173.     static void SetTraceMask(wxTraceMask ulMask) { ms_ulTraceMask = ulMask; }
  174.         // add string trace mask
  175.     static void AddTraceMask(const wxString& str) { ms_aTraceMasks.Add(str); }
  176.         // add string trace mask
  177.     static void RemoveTraceMask(const wxString& str);
  178.         // remove all string trace masks
  179.     static void ClearTraceMasks();
  180.         // get string trace masks
  181.     static const wxArrayString &GetTraceMasks() { return ms_aTraceMasks; }
  182.  
  183.         // sets the timestamp string: this is used as strftime() format string
  184.         // for the log targets which add time stamps to the messages - set it
  185.         // to NULL to disable time stamping completely.
  186.     static void SetTimestamp(const wxChar *ts) { ms_timestamp = ts; }
  187.  
  188.     // accessors
  189.         // gets the verbose status
  190.     static bool GetVerbose() { return ms_bVerbose; }
  191.         // get trace mask
  192.     static wxTraceMask GetTraceMask() { return ms_ulTraceMask; }
  193.         // is this trace mask in the list?
  194.     static bool IsAllowedTraceMask(const wxChar *mask)
  195.         { return ms_aTraceMasks.Index(mask) != wxNOT_FOUND; }
  196.  
  197.         // get the current timestamp format string (may be NULL)
  198.     static const wxChar *GetTimestamp() { return ms_timestamp; }
  199.  
  200.     // helpers
  201.         // put the time stamp into the string if ms_timestamp != NULL (don't
  202.         // change it otherwise)
  203.     static void TimeStamp(wxString *str);
  204.  
  205.     // make dtor virtual for all derived classes
  206.     virtual ~wxLog() { }
  207.  
  208. protected:
  209.     bool m_bHasMessages; // any messages in the queue?
  210.  
  211.     // the logging functions that can be overriden
  212.         // default DoLog() prepends the time stamp and a prefix corresponding
  213.         // to the message to szString and then passes it to DoLogString()
  214.     virtual void DoLog(wxLogLevel level, const wxChar *szString, time_t t);
  215.         // default DoLogString does nothing but is not pure virtual because if
  216.         // you override DoLog() you might not need it at all
  217.     virtual void DoLogString(const wxChar *szString, time_t t);
  218.  
  219. private:
  220.     // static variables
  221.     // ----------------
  222.  
  223.     static wxLog      *ms_pLogger;      // currently active log sink
  224.     static bool        ms_doLog;        // FALSE => all logging disabled
  225.     static bool        ms_bAutoCreate;  // create new log targets on demand?
  226.     static bool        ms_bVerbose;     // FALSE => ignore LogInfo messages
  227.  
  228.     static size_t      ms_suspendCount; // if positive, logs are not flushed
  229.  
  230.     // format string for strftime(), if NULL, time stamping log messages is
  231.     // disabled
  232.     static const wxChar *ms_timestamp;
  233.  
  234.     static wxTraceMask ms_ulTraceMask;   // controls wxLogTrace behaviour
  235.     static wxArrayString ms_aTraceMasks; // more powerful filter for wxLogTrace
  236. };
  237.  
  238. // ----------------------------------------------------------------------------
  239. // "trivial" derivations of wxLog
  240. // ----------------------------------------------------------------------------
  241.  
  242. // log everything to a "FILE *", stderr by default
  243. class WXDLLEXPORT wxLogStderr : public wxLog
  244. {
  245.     DECLARE_NO_COPY_CLASS(wxLogStderr)
  246.  
  247. public:
  248.     // redirect log output to a FILE
  249.     wxLogStderr(FILE *fp = (FILE *) NULL);
  250.  
  251. protected:
  252.     // implement sink function
  253.     virtual void DoLogString(const wxChar *szString, time_t t);
  254.  
  255.     FILE *m_fp;
  256. };
  257.  
  258. #if wxUSE_STD_IOSTREAM
  259.  
  260. // log everything to an "ostream", cerr by default
  261. class WXDLLEXPORT wxLogStream : public wxLog
  262. {
  263. public:
  264.     // redirect log output to an ostream
  265.     wxLogStream(wxSTD ostream *ostr = (wxSTD ostream *) NULL);
  266.  
  267. protected:
  268.     // implement sink function
  269.     virtual void DoLogString(const wxChar *szString, time_t t);
  270.  
  271.     // using ptr here to avoid including <iostream.h> from this file
  272.     wxSTD ostream *m_ostr;
  273. };
  274.  
  275. #endif // wxUSE_STD_IOSTREAM
  276.  
  277. // ----------------------------------------------------------------------------
  278. // /dev/null log target: suppress logging until this object goes out of scope
  279. // ----------------------------------------------------------------------------
  280.  
  281. // example of usage:
  282. /*
  283.     void Foo()
  284.     {
  285.         wxFile file;
  286.  
  287.         // wxFile.Open() normally complains if file can't be opened, we don't
  288.         // want it
  289.         wxLogNull logNo;
  290.  
  291.         if ( !file.Open("bar") )
  292.             ... process error ourselves ...
  293.  
  294.         // ~wxLogNull called, old log sink restored
  295.     }
  296.  */
  297. class WXDLLEXPORT wxLogNull
  298. {
  299. public:
  300.     wxLogNull() : m_flagOld(wxLog::EnableLogging(FALSE)) { }
  301.     ~wxLogNull() { (void)wxLog::EnableLogging(m_flagOld); }
  302.  
  303. private:
  304.     bool m_flagOld; // the previous value of the wxLog::ms_doLog
  305. };
  306.  
  307. // ----------------------------------------------------------------------------
  308. // chaining log target: installs itself as a log target and passes all
  309. // messages to the real log target given to it in the ctor but also forwards
  310. // them to the previously active one
  311. //
  312. // note that you don't have to call SetActiveTarget() with this class, it
  313. // does it itself in its ctor
  314. // ----------------------------------------------------------------------------
  315.  
  316. class WXDLLEXPORT wxLogChain : public wxLog
  317. {
  318. public:
  319.     wxLogChain(wxLog *logger);
  320.     virtual ~wxLogChain();
  321.  
  322.     // change the new log target
  323.     void SetLog(wxLog *logger);
  324.  
  325.     // this can be used to temporarily disable (and then reenable) passing
  326.     // messages to the old logger (by default we do pass them)
  327.     void PassMessages(bool bDoPass) { m_bPassMessages = bDoPass; }
  328.  
  329.     // are we passing the messages to the previous log target?
  330.     bool IsPassingMessages() const { return m_bPassMessages; }
  331.  
  332.     // return the previous log target (may be NULL)
  333.     wxLog *GetOldLog() const { return m_logOld; }
  334.  
  335.     // override base class version to flush the old logger as well
  336.     virtual void Flush();
  337.  
  338. protected:
  339.     // pass the chain to the old logger if needed
  340.     virtual void DoLog(wxLogLevel level, const wxChar *szString, time_t t);
  341.  
  342. private:
  343.     // the current log target
  344.     wxLog *m_logNew;
  345.  
  346.     // the previous log target
  347.     wxLog *m_logOld;
  348.  
  349.     // do we pass the messages to the old logger?
  350.     bool m_bPassMessages;
  351. };
  352.  
  353. // a chain log target which uses itself as the new logger
  354. class WXDLLEXPORT wxLogPassThrough : public wxLogChain
  355. {
  356. public:
  357.     wxLogPassThrough();
  358. };
  359.  
  360. // ----------------------------------------------------------------------------
  361. // the following log targets are only compiled in if the we're compiling the
  362. // GUI part (andnot just the base one) of the library, they're implemented in
  363. // src/generic/logg.cpp *and not src/common/log.cpp unlike all the rest)
  364. // ----------------------------------------------------------------------------
  365.  
  366. #if wxUSE_GUI
  367.  
  368. #if wxUSE_TEXTCTRL
  369.  
  370. // log everything to a text window (GUI only of course)
  371. class WXDLLEXPORT wxLogTextCtrl : public wxLog
  372. {
  373. public:
  374.     wxLogTextCtrl(wxTextCtrl *pTextCtrl);
  375.  
  376. private:
  377.     // implement sink function
  378.     virtual void DoLogString(const wxChar *szString, time_t t);
  379.  
  380.     // the control we use
  381.     wxTextCtrl *m_pTextCtrl;
  382. };
  383.  
  384. #endif // wxUSE_TEXTCTRL
  385.  
  386. // ----------------------------------------------------------------------------
  387. // GUI log target, the default one for wxWindows programs
  388. // ----------------------------------------------------------------------------
  389.  
  390. #if wxUSE_LOGGUI
  391.  
  392. class WXDLLEXPORT wxLogGui : public wxLog
  393. {
  394. public:
  395.     // ctor
  396.     wxLogGui();
  397.  
  398.     // show all messages that were logged since the last Flush()
  399.     virtual void Flush();
  400.  
  401. protected:
  402.     virtual void DoLog(wxLogLevel level, const wxChar *szString, time_t t);
  403.  
  404.     // empty everything
  405.     void Clear();
  406.  
  407.     wxArrayString m_aMessages;      // the log message texts
  408.     wxArrayInt    m_aSeverity;      // one of wxLOG_XXX values
  409.     wxArrayLong   m_aTimes;         // the time of each message
  410.     bool          m_bErrors,        // do we have any errors?
  411.                   m_bWarnings;      // any warnings?
  412. };
  413.  
  414. #endif // wxUSE_LOGGUI
  415.  
  416. // ----------------------------------------------------------------------------
  417. // (background) log window: this class forwards all log messages to the log
  418. // target which was active when it was instantiated, but also collects them
  419. // to the log window. This window has it's own menu which allows the user to
  420. // close it, clear the log contents or save it to the file.
  421. // ----------------------------------------------------------------------------
  422.  
  423. #if wxUSE_LOGWINDOW
  424.  
  425. class WXDLLEXPORT wxLogWindow : public wxLogPassThrough
  426. {
  427. public:
  428.     wxLogWindow(wxFrame *pParent,         // the parent frame (can be NULL)
  429.                 const wxChar *szTitle,    // the title of the frame
  430.                 bool bShow = TRUE,        // show window immediately?
  431.                 bool bPassToOld = TRUE);  // pass messages to the old target?
  432.  
  433.     ~wxLogWindow();
  434.  
  435.     // window operations
  436.         // show/hide the log window
  437.     void Show(bool bShow = TRUE);
  438.         // retrieve the pointer to the frame
  439.     wxFrame *GetFrame() const;
  440.  
  441.     // overridables
  442.         // called immediately after the log frame creation allowing for
  443.         // any extra initializations
  444.     virtual void OnFrameCreate(wxFrame *frame);
  445.         // called if the user closes the window interactively, will not be
  446.         // called if it is destroyed for another reason (such as when program
  447.         // exits) - return TRUE from here to allow the frame to close, FALSE
  448.         // to prevent this from happening
  449.     virtual bool OnFrameClose(wxFrame *frame);
  450.         // called right before the log frame is going to be deleted: will
  451.         // always be called unlike OnFrameClose()
  452.     virtual void OnFrameDelete(wxFrame *frame);
  453.  
  454. protected:
  455.     virtual void DoLog(wxLogLevel level, const wxChar *szString, time_t t);
  456.     virtual void DoLogString(const wxChar *szString, time_t t);
  457.  
  458. private:
  459.     wxLogFrame *m_pLogFrame;      // the log frame
  460. };
  461.  
  462. #endif // wxUSE_LOGWINDOW
  463.  
  464. #endif // wxUSE_GUI
  465.  
  466. // ============================================================================
  467. // global functions
  468. // ============================================================================
  469.  
  470. // ----------------------------------------------------------------------------
  471. // Log functions should be used by application instead of stdio, iostream &c
  472. // for log messages for easy redirection
  473. // ----------------------------------------------------------------------------
  474.  
  475. // ----------------------------------------------------------------------------
  476. // get error code/error message from system in a portable way
  477. // ----------------------------------------------------------------------------
  478.  
  479. // return the last system error code
  480. WXDLLEXPORT unsigned long wxSysErrorCode();
  481.  
  482. // return the error message for given (or last if 0) error code
  483. WXDLLEXPORT const wxChar* wxSysErrorMsg(unsigned long nErrCode = 0);
  484.  
  485. // ----------------------------------------------------------------------------
  486. // define wxLog<level>
  487. // ----------------------------------------------------------------------------
  488.  
  489. #define DECLARE_LOG_FUNCTION(level)                                 \
  490. extern void WXDLLEXPORT wxVLog##level(const wxChar *szFormat,       \
  491.                                       va_list argptr);              \
  492. extern void WXDLLEXPORT wxLog##level(const wxChar *szFormat,        \
  493.                                      ...) ATTRIBUTE_PRINTF_1
  494. #define DECLARE_LOG_FUNCTION2(level, arg1)                          \
  495. extern void WXDLLEXPORT wxVLog##level(arg1, const wxChar *szFormat, \
  496.                                       va_list argptr);              \
  497. extern void WXDLLEXPORT wxLog##level(arg1, const wxChar *szFormat,  \
  498.                                      ...) ATTRIBUTE_PRINTF_2
  499.  
  500. #else // !wxUSE_LOG
  501.  
  502. // log functions do nothing at all
  503. #define DECLARE_LOG_FUNCTION(level)                                 \
  504. inline void WXDLLEXPORT wxVLog##level(const wxChar *szFormat,       \
  505.                                      va_list argptr) {}             \
  506. inline void WXDLLEXPORT wxLog##level(const wxChar *szFormat, ...) {}
  507. #define DECLARE_LOG_FUNCTION2(level, arg1)                          \
  508. inline void WXDLLEXPORT wxVLog##level(arg1, const wxChar *szFormat, \
  509.                                      va_list argptr) {}             \
  510. inline void WXDLLEXPORT wxLog##level(arg1, const wxChar *szFormat, ...) {}
  511.  
  512. #endif // wxUSE_LOG/!wxUSE_LOG
  513.  
  514. // a generic function for all levels (level is passes as parameter)
  515. DECLARE_LOG_FUNCTION2(Generic, wxLogLevel level);
  516.  
  517. // one function per each level
  518. DECLARE_LOG_FUNCTION(FatalError);
  519. DECLARE_LOG_FUNCTION(Error);
  520. DECLARE_LOG_FUNCTION(Warning);
  521. DECLARE_LOG_FUNCTION(Message);
  522. DECLARE_LOG_FUNCTION(Info);
  523. DECLARE_LOG_FUNCTION(Verbose);
  524.  
  525. // this function sends the log message to the status line of the top level
  526. // application frame, if any
  527. DECLARE_LOG_FUNCTION(Status);
  528.  
  529. // this one is the same as previous except that it allows to explicitly
  530. // specify the frame to which the output should go
  531. DECLARE_LOG_FUNCTION2(Status, wxFrame *pFrame);
  532.  
  533. // additional one: as wxLogError, but also logs last system call error code
  534. // and the corresponding error message if available
  535. DECLARE_LOG_FUNCTION(SysError);
  536.  
  537. // and another one which also takes the error code (for those broken APIs
  538. // that don't set the errno (like registry APIs in Win32))
  539. DECLARE_LOG_FUNCTION2(SysError, long lErrCode);
  540.  
  541. // debug functions do nothing in release mode
  542. #ifdef  __WXDEBUG__
  543.     DECLARE_LOG_FUNCTION(Debug);
  544.  
  545.     // first kind of LogTrace is unconditional: it doesn't check the level,
  546.     DECLARE_LOG_FUNCTION(Trace);
  547.  
  548.     // this second version will only log the message if the mask had been
  549.     // added to the list of masks with AddTraceMask()
  550.     DECLARE_LOG_FUNCTION2(Trace, const wxChar *mask);
  551.  
  552.     // the last one does nothing if all of level bits are not set
  553.     // in wxLog::GetActive()->GetTraceMask() - it's deprecated in favour of
  554.     // string identifiers
  555.     DECLARE_LOG_FUNCTION2(Trace, wxTraceMask mask);
  556. #else   //!debug
  557.     // these functions do nothing in release builds
  558.     inline void wxVLogDebug(const wxChar *, va_list) { }
  559.     inline void wxLogDebug(const wxChar *, ...) { }
  560.     inline void wxVLogTrace(const wxChar *, va_list) { }
  561.     inline void wxLogTrace(const wxChar *, ...) { }
  562.     inline void wxVLogTrace(wxTraceMask, const wxChar *, va_list) { }
  563.     inline void wxLogTrace(wxTraceMask, const wxChar *, ...) { }
  564.     inline void wxVLogTrace(const wxChar *, const wxChar *, va_list) { }
  565.     inline void wxLogTrace(const wxChar *, const wxChar *, ...) { }
  566. #endif // debug/!debug
  567.  
  568. // wxLogFatalError helper: show the (fatal) error to the user in a safe way,
  569. // i.e. without using wxMessageBox() for example because it could crash
  570. void WXDLLEXPORT wxSafeShowMessage(const wxString& title, const wxString& text);
  571.  
  572. // ----------------------------------------------------------------------------
  573. // debug only logging functions: use them with API name and error code
  574. // ----------------------------------------------------------------------------
  575.  
  576. #ifdef __WXDEBUG__
  577.     // make life easier for people using VC++ IDE: clicking on the message
  578.     // will take us immediately to the place of the failed API
  579. #ifdef __VISUALC__
  580.     #define wxLogApiError(api, rc)                                            \
  581.         wxLogDebug(wxT("%s(%d): '%s' failed with error 0x%08lx (%s)."),       \
  582.                    __TFILE__, __LINE__, api,                                  \
  583.                    (long)rc, wxSysErrorMsg(rc))
  584. #else // !VC++
  585.     #define wxLogApiError(api, rc)                                            \
  586.         wxLogDebug(wxT("In file %s at line %d: '%s' failed with "             \
  587.                        "error 0x%08lx (%s)."),                                \
  588.                    __TFILE__, __LINE__, api,                                  \
  589.                    (long)rc, wxSysErrorMsg(rc))
  590. #endif // VC++/!VC++
  591.  
  592.     #define wxLogLastError(api) wxLogApiError(api, wxSysErrorCode())
  593.  
  594. #else   //!debug
  595.     inline void wxLogApiError(const wxChar *, long) { }
  596.     inline void wxLogLastError(const wxChar *) { }
  597. #endif  //debug/!debug
  598.  
  599. #endif  // _WX_LOG_H_
  600.  
  601. // vi:sts=4:sw=4:et
  602.