Merge branch 'log-encoding'
See https://github.com/wxWidgets/wxWidgets/pull/552 Closes #17385.
This commit is contained in:
commit
56323b5aba
@ -91,6 +91,7 @@ All:
|
||||
wxLog::SetVerbose() which now only affects wxLogVerbose().
|
||||
- Add wxFileType::GetExpandedCommand() (troelsk).
|
||||
- Make it easier to convert to/from UTF-8-encoded std::string (ARATA Mizuki).
|
||||
- Support custom conversions in wxLogStream and wxLogStderr (Catalin Raceanu).
|
||||
- Add support for loading dynamic lexer in wxStyledTextCtrl (New Pagodi).
|
||||
- Handle strings with embedded NULs in wxDataStream (Nitch).
|
||||
- Don't crash in wxTextFile::GetLastLine() if the file is empty (crohr).
|
||||
|
@ -61,6 +61,7 @@ class WXDLLIMPEXP_FWD_BASE wxObject;
|
||||
|
||||
#include "wx/dynarray.h"
|
||||
#include "wx/hashmap.h"
|
||||
#include "wx/msgout.h"
|
||||
|
||||
#if wxUSE_THREADS
|
||||
#include "wx/thread.h"
|
||||
@ -716,29 +717,31 @@ private:
|
||||
|
||||
|
||||
// log everything to a "FILE *", stderr by default
|
||||
class WXDLLIMPEXP_BASE wxLogStderr : public wxLog
|
||||
class WXDLLIMPEXP_BASE wxLogStderr : public wxLog,
|
||||
private wxMessageOutputStderr
|
||||
{
|
||||
public:
|
||||
// redirect log output to a FILE
|
||||
wxLogStderr(FILE *fp = NULL);
|
||||
wxLogStderr(FILE *fp = NULL,
|
||||
const wxMBConv &conv = wxConvWhateverWorks);
|
||||
|
||||
protected:
|
||||
// implement sink function
|
||||
virtual void DoLogText(const wxString& msg) wxOVERRIDE;
|
||||
|
||||
FILE *m_fp;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxLogStderr);
|
||||
};
|
||||
|
||||
#if wxUSE_STD_IOSTREAM
|
||||
|
||||
// log everything to an "ostream", cerr by default
|
||||
class WXDLLIMPEXP_BASE wxLogStream : public wxLog
|
||||
class WXDLLIMPEXP_BASE wxLogStream : public wxLog,
|
||||
private wxMessageOutputWithConv
|
||||
{
|
||||
public:
|
||||
// redirect log output to an ostream
|
||||
wxLogStream(wxSTD ostream *ostr = (wxSTD ostream *) NULL);
|
||||
wxLogStream(wxSTD ostream *ostr = (wxSTD ostream *) NULL,
|
||||
const wxMBConv& conv = wxConvWhateverWorks);
|
||||
|
||||
protected:
|
||||
// implement sink function
|
||||
@ -746,6 +749,8 @@ protected:
|
||||
|
||||
// using ptr here to avoid including <iostream.h> from this file
|
||||
wxSTD ostream *m_ostr;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxLogStream);
|
||||
};
|
||||
|
||||
#endif // wxUSE_STD_IOSTREAM
|
||||
|
@ -58,22 +58,51 @@ private:
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// implementation which sends output to stderr or specified file
|
||||
// helper mix-in for output targets that can use difference encodings
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class WXDLLIMPEXP_BASE wxMessageOutputStderr : public wxMessageOutput
|
||||
class WXDLLIMPEXP_BASE wxMessageOutputWithConv
|
||||
{
|
||||
public:
|
||||
wxMessageOutputStderr(FILE *fp = stderr) : m_fp(fp) { }
|
||||
|
||||
virtual void Output(const wxString& str) wxOVERRIDE;
|
||||
|
||||
protected:
|
||||
explicit wxMessageOutputWithConv(const wxMBConv& conv)
|
||||
: m_conv(conv.Clone())
|
||||
{
|
||||
}
|
||||
|
||||
~wxMessageOutputWithConv()
|
||||
{
|
||||
delete m_conv;
|
||||
}
|
||||
|
||||
// return the string with "\n" appended if it doesn't already terminate
|
||||
// with it (in which case it's returned unchanged)
|
||||
wxString AppendLineFeedIfNeeded(const wxString& str);
|
||||
|
||||
// Prepare the given string for output by appending a new line to it, if
|
||||
// necessary, and converting it to a narrow string using our conversion
|
||||
// object.
|
||||
wxCharBuffer PrepareForOutput(const wxString& str);
|
||||
|
||||
const wxMBConv* const m_conv;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// implementation which sends output to stderr or specified file
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class WXDLLIMPEXP_BASE wxMessageOutputStderr : public wxMessageOutput,
|
||||
protected wxMessageOutputWithConv
|
||||
{
|
||||
public:
|
||||
wxMessageOutputStderr(FILE *fp = stderr,
|
||||
const wxMBConv &conv = wxConvWhateverWorks);
|
||||
|
||||
virtual void Output(const wxString& str) wxOVERRIDE;
|
||||
|
||||
protected:
|
||||
FILE *m_fp;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxMessageOutputStderr);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -756,8 +756,24 @@ public:
|
||||
/**
|
||||
Constructs a log target which sends all the log messages to the given
|
||||
output stream. If it is @NULL, the messages are sent to @c cerr.
|
||||
The messages will be written in the encoding specified by the
|
||||
given @c wxMBConv.
|
||||
|
||||
The @a conv argument is only available in wxWidgets 3.1.1 and later.
|
||||
|
||||
@note
|
||||
In practice, it is only advisable to specify @c wxConvUTF8 as
|
||||
the @a conv.
|
||||
If using @c wxMBConvUTF16(), the file should be opened in
|
||||
@c std::ios::binary mode.
|
||||
|
||||
@warning
|
||||
If a log message contains any characters that cannot be converted
|
||||
to the character set given by @a conv, that message will be
|
||||
silently ignored, i.e. it will not be written at all.
|
||||
*/
|
||||
wxLogStream(std::ostream *ostr = NULL);
|
||||
wxLogStream(std::ostream *ostr = NULL,
|
||||
const wxMBConv &conv = wxConvWhateverWorks);
|
||||
};
|
||||
|
||||
|
||||
@ -782,8 +798,24 @@ public:
|
||||
/**
|
||||
Constructs a log target which sends all the log messages to the given
|
||||
@c FILE. If it is @NULL, the messages are sent to @c stderr.
|
||||
The messages will be written in the encoding specified by the
|
||||
given @c wxMBConv.
|
||||
|
||||
The @a conv argument is only available in wxWidgets 3.1.1 and later.
|
||||
|
||||
@note
|
||||
In practice, it is only advisable to specify @c wxConvUTF8 as
|
||||
the @a conv.
|
||||
If using @c wxMBConvUTF16(), the file should be opened in
|
||||
@c "wb" mode.
|
||||
|
||||
@warning
|
||||
If a log message contains any characters that cannot be converted
|
||||
to the character set given by @a conv, that message will be
|
||||
silently ignored, i.e. it will not be written at all.
|
||||
*/
|
||||
wxLogStderr(FILE* fp = NULL);
|
||||
wxLogStderr(FILE *fp = NULL,
|
||||
const wxMBConv &conv = wxConvWhateverWorks);
|
||||
};
|
||||
|
||||
|
||||
|
@ -839,12 +839,9 @@ void wxLogBuffer::DoLogTextAtLevel(wxLogLevel level, const wxString& msg)
|
||||
// wxLogStderr class implementation
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
wxLogStderr::wxLogStderr(FILE *fp)
|
||||
wxLogStderr::wxLogStderr(FILE *fp, const wxMBConv& conv)
|
||||
: wxMessageOutputStderr(fp ? fp : stderr, conv)
|
||||
{
|
||||
if ( fp == NULL )
|
||||
m_fp = stderr;
|
||||
else
|
||||
m_fp = fp;
|
||||
}
|
||||
|
||||
void wxLogStderr::DoLogText(const wxString& msg)
|
||||
@ -852,7 +849,7 @@ void wxLogStderr::DoLogText(const wxString& msg)
|
||||
// First send it to stderr, even if we don't have it (e.g. in a Windows GUI
|
||||
// application under) it's not a problem to try to use it and it's easier
|
||||
// than determining whether we do have it or not.
|
||||
wxMessageOutputStderr(m_fp).Output(msg);
|
||||
wxMessageOutputStderr::Output(msg);
|
||||
|
||||
// under GUI systems such as Windows or Mac, programs usually don't have
|
||||
// stderr at all, so show the messages also somewhere else, typically in
|
||||
@ -874,7 +871,8 @@ void wxLogStderr::DoLogText(const wxString& msg)
|
||||
|
||||
#if wxUSE_STD_IOSTREAM
|
||||
#include "wx/ioswrap.h"
|
||||
wxLogStream::wxLogStream(wxSTD ostream *ostr)
|
||||
wxLogStream::wxLogStream(wxSTD ostream *ostr, const wxMBConv& conv)
|
||||
: wxMessageOutputWithConv(conv)
|
||||
{
|
||||
if ( ostr == NULL )
|
||||
m_ostr = &wxSTD cerr;
|
||||
@ -884,7 +882,8 @@ wxLogStream::wxLogStream(wxSTD ostream *ostr)
|
||||
|
||||
void wxLogStream::DoLogText(const wxString& msg)
|
||||
{
|
||||
(*m_ostr) << msg << wxSTD endl;
|
||||
const wxCharBuffer& buf = PrepareForOutput(msg);
|
||||
m_ostr->write(buf, buf.length());
|
||||
}
|
||||
#endif // wxUSE_STD_IOSTREAM
|
||||
|
||||
|
@ -133,10 +133,10 @@ void wxMessageOutputBest::Output(const wxString& str)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxMessageOutputStderr
|
||||
// wxMessageOutputWithConv
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
wxString wxMessageOutputStderr::AppendLineFeedIfNeeded(const wxString& str)
|
||||
wxString wxMessageOutputWithConv::AppendLineFeedIfNeeded(const wxString& str)
|
||||
{
|
||||
wxString strLF(str);
|
||||
if ( strLF.empty() || *strLF.rbegin() != '\n' )
|
||||
@ -145,11 +145,37 @@ wxString wxMessageOutputStderr::AppendLineFeedIfNeeded(const wxString& str)
|
||||
return strLF;
|
||||
}
|
||||
|
||||
wxCharBuffer wxMessageOutputWithConv::PrepareForOutput(const wxString& str)
|
||||
{
|
||||
wxString strWithLF = AppendLineFeedIfNeeded(str);
|
||||
|
||||
#if defined(__WINDOWS__)
|
||||
// Determine whether the encoding is UTF-16. In that case, the file
|
||||
// should have been opened in "wb" mode, and EOL conversion must be done
|
||||
// here as it won't be done at stdio level.
|
||||
if ( m_conv->GetMBNulLen() == 2 )
|
||||
{
|
||||
strWithLF.Replace("\n", "\r\n");
|
||||
}
|
||||
#endif // __WINDOWS__
|
||||
|
||||
return m_conv->cWX2MB(strWithLF.c_str());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxMessageOutputStderr
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
wxMessageOutputStderr::wxMessageOutputStderr(FILE *fp, const wxMBConv& conv)
|
||||
: wxMessageOutputWithConv(conv),
|
||||
m_fp(fp)
|
||||
{
|
||||
}
|
||||
|
||||
void wxMessageOutputStderr::Output(const wxString& str)
|
||||
{
|
||||
const wxString strWithLF = AppendLineFeedIfNeeded(str);
|
||||
|
||||
fprintf(m_fp, "%s", (const char*) strWithLF.mb_str(wxConvWhateverWorks));
|
||||
const wxCharBuffer& buf = PrepareForOutput(str);
|
||||
fwrite(buf, buf.length(), 1, m_fp);
|
||||
fflush(m_fp);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user