+unsigned wxLog::LogLastRepeatIfNeeded()
+{
+ wxCRIT_SECT_LOCKER(lock, GetPreviousLogCS());
+
+ return LogLastRepeatIfNeededUnlocked();
+}
+
+unsigned wxLog::LogLastRepeatIfNeededUnlocked()
+{
+ const unsigned count = ms_prevCounter;
+
+ if ( ms_prevCounter )
+ {
+ wxString msg;
+#if wxUSE_INTL
+ msg.Printf(wxPLURAL("The previous message repeated once.",
+ "The previous message repeated %lu times.",
+ ms_prevCounter),
+ ms_prevCounter);
+#else
+ msg.Printf(wxS("The previous message was repeated %lu times."),
+ ms_prevCounter);
+#endif
+ ms_prevCounter = 0;
+ ms_prevString.clear();
+ DoLog(ms_prevLevel, msg, ms_prevTimeStamp);
+ }
+
+ return count;
+}
+
+wxLog::~wxLog()
+{
+ // Flush() must be called before destroying the object as otherwise some
+ // messages could be lost
+ if ( ms_prevCounter )
+ {
+ wxMessageOutputDebug().Printf
+ (
+ wxS("Last repeated message (\"%s\", %lu times) wasn't output"),
+ ms_prevString,
+ ms_prevCounter
+ );
+ }
+}
+
+/* static */
+void wxLog::OnLog(wxLogLevel level, const wxString& szString, time_t t)
+{
+ if ( IsEnabled() && ms_logLevel >= level )
+ {
+ wxLog *pLogger = GetActiveTarget();
+ if ( pLogger )
+ {
+ if ( GetRepetitionCounting() )
+ {
+ wxCRIT_SECT_LOCKER(lock, GetPreviousLogCS());
+
+ if ( szString == ms_prevString )
+ {
+ ms_prevCounter++;
+
+ // nothing else to do, in particular, don't log the
+ // repeated message
+ return;
+ }
+
+ pLogger->LogLastRepeatIfNeededUnlocked();
+
+ // reset repetition counter for a new message
+ ms_prevString = szString;
+ ms_prevLevel = level;
+ ms_prevTimeStamp = t;
+ }
+
+ pLogger->DoLog(level, szString, t);
+ }
+ }
+}
+
+// deprecated function
+#if WXWIN_COMPATIBILITY_2_6
+
+wxChar *wxLog::SetLogBuffer(wxChar * WXUNUSED(buf), size_t WXUNUSED(size))
+{
+ return NULL;
+}
+
+#endif // WXWIN_COMPATIBILITY_2_6
+
+#if WXWIN_COMPATIBILITY_2_8
+
+void wxLog::DoLog(wxLogLevel WXUNUSED(level),
+ const char *WXUNUSED(szString),
+ time_t WXUNUSED(t))