ClipBoard.GetAsText may return wrong length
Original Reporter info from Mantis: Bart @flyingsheep
-
Reporter name: Bart Broersma
Original Reporter info from Mantis: Bart @flyingsheep
- Reporter name: Bart Broersma
Description:
When calling ClipBoard.GetAsText the length of the returned string may be incorrect. The resulting string may be padded with zero's (and sometimes with garbage).
Steps to reproduce:
This code:
var
ClipTest: AnsiString;
begin
ClipText := ClipBoard.AsText;
debugln('ClipText = "',ClipText,'"');
debugln('Length = ',DbgS(Length(ClipText)));
for i := 1 to length(ClipText) do DbgOut(' ',DbgS(Ord(ClipText[i])));
I copy the text 'ABC' (from within Windows Notepad) to clipboard, then run the above code.
The output is:
ClipText = "ABC____________________________" (_ represents space here)
Length = 31
65 66 67 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
The first 0 after 'C' (67) is consistent, the rest may be garbage.
Additional information:
I traced this down to (in /lcl/interfaces/win32/win32winapi.inc)
function ReadClipboardToStream(DestStream: TStream): Boolean;
begin
Result := false;
DataHandle := Windows.GetClipboardData(FormatID);
if DataHandle<>HWND(0) then
begin
Size := Windows.GlobalSize(DataHandle); // <<-------------------- **
.....
end;
** Size will always be n times 32 (on win32)
In ClipBoard.GetAsText (lcl/include/clipbrd.inc) there is code to remove the last trailing #0 (if there is one), but as the example shows, this is not enough.
Moreover, the last char in the buffer might not even be a #0 and nothing gets removed.
A possible solution might be (in lcl/include/clipbrd.inc)
function TClipboard.GetAsText: string;
var
MemStream: TMemoryStream;
ASize: int64;
begin
//DebugLn('[TClipboard.GetAsText] A ',ClipboardTypeName[ClipboardType]);
Result:='';
MemStream:=TMemoryStream.Create;
try
if GetFormat(PredefinedClipboardFormat(pcfText),MemStream) then begin
//ASize:=MemStream.Size; <<-- replace this with the following 2 lines
ASize := IndexByte(MemStream.Memory^, MemStream.Size, 0);
if (ASize < 0) then ASize := MemStream.Size;
.....
However, since this bug is at least not present in Linux/GTK, a more appropriate solution might be to fix ReadClipboardToStream() in /lcl/interfaces/win32/win32winapi.inc?
(Feel free to set the category to Widgetset in that case.)
Mantis conversion info:
- Mantis ID: 16483
- OS: WinMe
- OS Build: MS
- Build: 25303M
- Platform: i386
- Version: 0.9.29 (SVN)
- Fixed in version: 0.9.29 (SVN)
- Fixed in revision: 27553 (#89bc817f)
- Target version: 0.9.30
- LazTarget: 1.0