mirror of
https://github.com/wxWidgets/wxWidgets.git
synced 2026-09-24 07:24:31 +08:00
Add RTF support to wxMSW wxTextCtrl too
Make IsRTFSupported() non-static function as RTF is only supported by some (rich), but not all, wxTextCtrls under Windows. Closes #24718.
This commit is contained in:
committed by
Vadim Zeitlin
parent
78bc9f24f3
commit
44a16be3d8
@@ -40,6 +40,12 @@ public:
|
||||
virtual wxString GetValue() const override;
|
||||
virtual wxString GetRange(long from, long to) const override;
|
||||
|
||||
#if wxUSE_RICHEDIT
|
||||
virtual wxString GetRTFValue() const override;
|
||||
virtual void SetRTFValue(const wxString& val) override;
|
||||
virtual bool IsRTFSupported() override { return IsRich(); }
|
||||
#endif // wxUSE_RICHEDIT
|
||||
|
||||
virtual bool IsEmpty() const;
|
||||
|
||||
virtual void WriteText(const wxString& text) override;
|
||||
|
||||
@@ -718,6 +718,8 @@ public :
|
||||
virtual bool CanClipMaxLength() const { return false; }
|
||||
virtual void SetMaxLength(unsigned long WXUNUSED(len)) {}
|
||||
|
||||
virtual bool IsRTFSupported() { return false; }
|
||||
|
||||
virtual bool CanForceUpper() { return false; }
|
||||
virtual void ForceUpper() {}
|
||||
|
||||
|
||||
@@ -111,6 +111,7 @@ public:
|
||||
|
||||
virtual wxString GetRTFValue() const override;
|
||||
virtual void SetRTFValue(const wxString& val) override;
|
||||
virtual bool IsRTFSupported() override { return IsMultiLine(); }
|
||||
|
||||
// callbacks
|
||||
void OnDropFiles(wxDropFilesEvent& event);
|
||||
|
||||
@@ -103,10 +103,10 @@ const wxTextCoord wxInvalidTextCoord = -2;
|
||||
// wxTextCtrl file types
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// For now only wxOSX supports RTF in wxTextCtrl.
|
||||
#ifdef __WXOSX__
|
||||
// wxOSX and wxMSW support RTF in wxTextCtrl.
|
||||
#if defined(__WXOSX__) || (defined(__WXMSW__) && wxUSE_RICHEDIT)
|
||||
#define wxHAS_TEXTCTRL_RTF
|
||||
#endif // __WXOSX__
|
||||
#endif
|
||||
|
||||
enum wxTextCtrlFileType
|
||||
{
|
||||
@@ -691,7 +691,7 @@ public:
|
||||
virtual void SetValue(const wxString& value) = 0;
|
||||
|
||||
// Returns whether the RTF-related functions below can be used.
|
||||
static bool IsRTFSupported();
|
||||
virtual bool IsRTFSupported() { return false; }
|
||||
|
||||
// Base class implementations simply assert, if IsRTFSupported() returns
|
||||
// true, the port must override these functions to really implement them.
|
||||
|
||||
@@ -76,7 +76,7 @@ enum wxTextCtrlFileType
|
||||
/**
|
||||
Rich Text Format.
|
||||
|
||||
This format is only supported under macOS currently.
|
||||
This format is only supported under macOS and MSW.
|
||||
|
||||
@since 3.3.0
|
||||
*/
|
||||
@@ -1659,14 +1659,15 @@ public:
|
||||
Returns @c true if text controls support reading and writing RTF (Rich
|
||||
Text Format).
|
||||
|
||||
Currently this function only returns true in wxOSX, which is the only
|
||||
port implementing RTF support in wxTextCtrl.
|
||||
This function only returns @true in wxOSX (for multiline contrls) and
|
||||
wxMSW (for rich controls), which are the only ports implementing
|
||||
RTF support in wxTextCtrl.
|
||||
|
||||
@since 3.3.0
|
||||
|
||||
@see GetRTFValue(), SetRTFValue()
|
||||
*/
|
||||
static bool IsRTFSupported();
|
||||
bool IsRTFSupported();
|
||||
|
||||
/**
|
||||
Returns the content of a multiline text control as RTF (Rich Text
|
||||
|
||||
@@ -479,13 +479,12 @@ bool MyApp::OnInit()
|
||||
file_menu->Append(TEXT_LOAD, "&Load file\tCtrl-O",
|
||||
"Load the sample file into text control");
|
||||
|
||||
if ( wxTextCtrl::IsRTFSupported() )
|
||||
{
|
||||
#ifdef wxHAS_TEXTCTRL_RTF
|
||||
file_menu->Append(TEXT_SAVE_RTF, "&Save file as RTF",
|
||||
"Save the text control contents to file");
|
||||
file_menu->Append(TEXT_LOAD_RTF, "&Load RTF file",
|
||||
"Load the sample file into text control");
|
||||
}
|
||||
#endif
|
||||
|
||||
file_menu->AppendSeparator();
|
||||
file_menu->Append(TEXT_RICH_TEXT_TEST, "Show Rich Text Editor");
|
||||
@@ -534,11 +533,10 @@ bool MyApp::OnInit()
|
||||
menuText->Append(TEXT_SELECT, "&Select characters 4 to 8\tCtrl-I");
|
||||
menuText->Append(TEXT_SET, "&Set the first text zone value\tCtrl-E");
|
||||
menuText->Append(TEXT_CHANGE, "&Change the first text zone value\tShift-Ctrl-E");
|
||||
if ( wxTextCtrl::IsRTFSupported() )
|
||||
{
|
||||
#ifdef wxHAS_TEXTCTRL_RTF
|
||||
menuText->AppendSeparator();
|
||||
menuText->Append(TEXT_SET_RTF, "Set the rich text zone value from rich text formatted content");
|
||||
}
|
||||
#endif
|
||||
menuText->AppendSeparator();
|
||||
menuText->Append(TEXT_MOVE_ENDTEXT, "Move cursor to the end of &text");
|
||||
menuText->Append(TEXT_MOVE_ENDENTRY, "Move cursor to the end of &entry");
|
||||
|
||||
@@ -931,16 +931,6 @@ bool wxTextCtrlBase::SetDefaultStyle(const wxTextAttr& style)
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
bool wxTextAreaBase::IsRTFSupported()
|
||||
{
|
||||
#ifdef wxHAS_TEXTCTRL_RTF
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
wxString wxTextAreaBase::GetRTFValue() const
|
||||
{
|
||||
wxFAIL_MSG("Not implemented for the current platform.");
|
||||
|
||||
@@ -1114,6 +1114,92 @@ void wxTextCtrl::DoSetValue(const wxString& value, int flags)
|
||||
}
|
||||
}
|
||||
|
||||
#if wxUSE_RICHEDIT
|
||||
|
||||
DWORD wxCALLBACK MSWEditStreamOutCallback(DWORD_PTR dwCookie, LPBYTE pbBuff,
|
||||
LONG cb, LONG* pcb)
|
||||
{
|
||||
// write the text
|
||||
std::string* psEntry = reinterpret_cast<std::string*>(dwCookie);
|
||||
psEntry->append(reinterpret_cast<const char*>(pbBuff), cb);
|
||||
*pcb = cb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
wxString wxTextCtrl::GetRTFValue() const
|
||||
{
|
||||
if ( !IsRich() )
|
||||
{
|
||||
wxFAIL_MSG("RTF support is only available for rich controls!");
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
// The Rich Edit control must write to a char buffer,
|
||||
// which we will later convert to a Unicode wxString using the current code page.
|
||||
//
|
||||
// We will reserve enough space assuming that the RTF will be twice as large
|
||||
// as the unencoded content.
|
||||
std::string buffer;
|
||||
buffer.reserve(GetLastPosition() * 2);
|
||||
|
||||
// Use a EDITSTREAMCALLBACK to stream text out from the control.
|
||||
EDITSTREAM es{ 0 };
|
||||
es.dwError = 0;
|
||||
es.pfnCallback = MSWEditStreamOutCallback;
|
||||
// our callback will write to a char buffer (i.e., std::string)
|
||||
es.dwCookie = reinterpret_cast<DWORD_PTR>(&buffer);
|
||||
|
||||
// Do NOT call with "(CP_UTF8 << 16) | SF_USECODEPAGE", as this will format the
|
||||
// output RTF to UTF-8 with a "urtf1" header (note the 'u').
|
||||
// Although this is a more modern format, few programs
|
||||
// (including Microsoft Wordpad) recognize it.
|
||||
//
|
||||
// Instead, write the content to an ANSI string using the current code page
|
||||
// (which will use a "rtf1" header). The control will encode any Unicode values
|
||||
// outside of the current code page with "\'[0-9A-F][0-9A-F]" syntax that most
|
||||
// parsers would support.
|
||||
//
|
||||
// Finally, use SFF_PLAINRTF so that the generated RTF is more portable between
|
||||
// RTF readers.
|
||||
::SendMessage(GetHwnd(), EM_STREAMOUT,
|
||||
(WPARAM)(SF_RTF | SFF_PLAINRTF), (LPARAM)&es);
|
||||
|
||||
// Valid RTF is supposed to consist of 7-bit ASCII characters only,
|
||||
// anything else is escaped.
|
||||
return wxString::FromAscii(buffer.c_str(), buffer.length());
|
||||
}
|
||||
|
||||
void wxTextCtrl::SetRTFValue(const wxString& val)
|
||||
{
|
||||
wxCHECK_RET(IsRich(), "RTF support is only available for rich controls!");
|
||||
|
||||
SETTEXTEX textInfo{ 0 };
|
||||
textInfo.flags = ST_DEFAULT | ST_UNICODE;
|
||||
textInfo.codepage = 1200;
|
||||
|
||||
// Setting from Unicode will fail if control is read-only
|
||||
// (this is an undocumented "feature"), so we need to toggle that temporarily.
|
||||
const bool
|
||||
isReadOnly = (::GetWindowLong(GetHwnd(), GWL_STYLE) & ES_READONLY) != 0;
|
||||
if ( isReadOnly )
|
||||
{
|
||||
::SendMessage(GetHwnd(), EM_SETREADONLY, FALSE, 0);
|
||||
}
|
||||
|
||||
::SendMessage(GetHwnd(), EM_SETTEXTEX, (WPARAM)&textInfo,
|
||||
(LPARAM)static_cast<const wchar_t*>(val.wc_str()));
|
||||
|
||||
if ( isReadOnly )
|
||||
{
|
||||
::SendMessage(GetHwnd(), EM_SETREADONLY, TRUE, 0);
|
||||
}
|
||||
|
||||
SetInsertionPoint(0);
|
||||
}
|
||||
|
||||
#endif // wxUSE_RICHEDIT
|
||||
|
||||
void wxTextCtrl::WriteText(const wxString& value)
|
||||
{
|
||||
DoWriteText(value);
|
||||
|
||||
Reference in New Issue
Block a user