Fix pasting long strings in wxTextCtrl under MSW
Adjust the length limit before pasting to ensure that all text on clipboard will be successfully pasted, instead of only pasting the part of it which fits. Add a unit test checking that this works. Closes #4646.
This commit is contained in:
@@ -47,6 +47,7 @@
|
||||
|
||||
#if wxUSE_CLIPBOARD
|
||||
#include "wx/clipbrd.h"
|
||||
#include "wx/dataobj.h"
|
||||
#endif
|
||||
|
||||
#include "wx/textfile.h"
|
||||
@@ -2213,6 +2214,24 @@ void wxTextCtrl::OnKeyDown(wxKeyEvent& event)
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void wxTextCtrl::Paste()
|
||||
{
|
||||
// Before pasting, check that the pasted text will fit, unless an explicit
|
||||
// maximum length was set, to avoid only pasting some part of it.
|
||||
//
|
||||
// Note that rich text controls do not send WM_PASTE, so we can't do it in
|
||||
// response to it, but we could handle EN_PROTECTED (after requesting it by
|
||||
// specifying ENM_PROTECTED in EM_SETEVENTMASK argument) and check for the
|
||||
// message being WM_PASTE there, but this doesn't seem to be better than
|
||||
// the simpler approach used here.
|
||||
if ( IsRich() )
|
||||
{
|
||||
AdjustMaxLengthBeforePaste();
|
||||
}
|
||||
|
||||
wxTextCtrlBase::Paste();
|
||||
}
|
||||
|
||||
bool
|
||||
wxTextCtrl::MSWHandleMessage(WXLRESULT *rc,
|
||||
WXUINT nMsg,
|
||||
@@ -2317,6 +2336,12 @@ wxTextCtrl::MSWHandleMessage(WXLRESULT *rc,
|
||||
::SetCursor(GetHcursorOf(*wxSTANDARD_CURSOR));
|
||||
}
|
||||
#endif // wxUSE_MENUS
|
||||
|
||||
case WM_PASTE:
|
||||
// Note that we get this message for plain EDIT controls only, rich
|
||||
// controls are dealt with in our own Paste().
|
||||
AdjustMaxLengthBeforePaste();
|
||||
break;
|
||||
}
|
||||
|
||||
return processed;
|
||||
@@ -2455,6 +2480,48 @@ bool wxTextCtrl::AdjustSpaceLimit()
|
||||
return true;
|
||||
}
|
||||
|
||||
void wxTextCtrl::AdjustMaxLengthBeforePaste()
|
||||
{
|
||||
#if wxUSE_CLIPBOARD
|
||||
// We only need to do this for multi line controls, single lines should
|
||||
// never receive more text than fits into them by default anyhow.
|
||||
if ( IsSingleLine() )
|
||||
return;
|
||||
|
||||
// Also don't override an explicitly set limit.
|
||||
unsigned int limit;
|
||||
if ( HasSpaceLimit(&limit) )
|
||||
return;
|
||||
|
||||
// Otherwise check if we have enough space for clipboard data. We only do
|
||||
// it for plain text because this is all we know how to handle here.
|
||||
wxClipboardLocker lock;
|
||||
wxTextDataObject textData;
|
||||
if ( !wxTheClipboard->GetData(textData) )
|
||||
return;
|
||||
|
||||
// Unfortunately we can't just get the length directly because we need to
|
||||
// convert EOLs, otherwise our calculation of the required length could be
|
||||
// way off when there are many lines.
|
||||
const unsigned long lenPasted =
|
||||
wxTextFile::Translate(textData.GetText(), wxTextFileType_Dos).length();
|
||||
|
||||
long from, to;
|
||||
GetSelection(&from, &to);
|
||||
const unsigned long lenSel = to - from;
|
||||
|
||||
const unsigned long lenCurrent = GetLastPosition();
|
||||
|
||||
// We need enough space for all the current text and all the new
|
||||
// text, but the selection will be replaced.
|
||||
const unsigned long lenNeeded = lenCurrent - lenSel + lenPasted;
|
||||
if ( lenNeeded >= limit )
|
||||
{
|
||||
SetMaxLength(lenNeeded);
|
||||
}
|
||||
#endif // wxUSE_CLIPBOARD
|
||||
}
|
||||
|
||||
bool wxTextCtrl::AcceptsFocusFromKeyboard() const
|
||||
{
|
||||
// we don't want focus if we can't be edited unless we're a multiline
|
||||
|
Reference in New Issue
Block a user