Recent

Author Topic: ClipBoard.GetAsText bug?  (Read 5997 times)

Bart

  • Hero Member
  • *****
  • Posts: 4689
    • Bart en Mariska's Webstek
ClipBoard.GetAsText bug?
« on: May 15, 2010, 05:43:41 pm »
Hi,

Can anyone confirm this?

On win9x I have a problem with ClipBoard.GetAsText.

Take a look at this example code:

Code: [Select]
  ClipText := ClipBoard.AsText;
  debugln;
  debugln('ClipText = "',ClipText,'"');
  debugln('Length = ',DbgS(Length(ClipText)));
  for i := 1 to length(ClipText) do DbgOut('#',DbgS(Ord(ClipText[i])));
  debugln;

Now when I copy (from Windows Notepad) 'ABC'  to the clipboard and run the above code, the output is

Quote
ClipText = "ABC                            "
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.

I traced this down to (in /lcl/interfaces/win32/win32winapi.inc)

Code: [Select]
  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 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.

Can anyone confirm this?
Is it Windows (win32) only?

Bart

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 7865
  • Debugger - SynEdit - and more
    • wiki
Re: ClipBoard.GetAsText bug?
« Reply #1 on: May 15, 2010, 06:05:31 pm »
Interesting => I actually have seen occasionally trash when pasting from clipboard (and the same clipboard pasting outside lazarus being fine)


theo

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1891
Re: ClipBoard.GetAsText bug?
« Reply #2 on: May 15, 2010, 06:40:51 pm »
Should be easy to fix:

Code: [Select]
var aStr:String;
begin
aStr:=#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;
writeln(length(aStr));
aStr:=PChar(aStr);
writeln(length(aStr));
end;     

Bart

  • Hero Member
  • *****
  • Posts: 4689
    • Bart en Mariska's Webstek
Re: ClipBoard.GetAsText bug?
« Reply #3 on: May 15, 2010, 06:50:43 pm »
That's not a fix, that's a workaround.  ;)

AFAIK a string pasted from the OS clipboard cannot contain a #0.

So the issue might be fixed like this

Code: [Select]
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;
      .....

Bart

theo

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1891
Re: ClipBoard.GetAsText bug?
« Reply #4 on: May 15, 2010, 07:03:24 pm »
Your solution is certainly correct, but I can't see any practical difference to

Result:=PChar(Result);

The overhead is 31 bytes maximum for a short time. Remains to see if a the PChar casting or the IndexByte call is faster.

Bart

  • Hero Member
  • *****
  • Posts: 4689
    • Bart en Mariska's Webstek
Re: ClipBoard.GetAsText bug?
« Reply #5 on: May 15, 2010, 07:11:06 pm »
The bug is not present in Linux gtk.
So maybe it should be fixed in win32winapi.inc?

Bart

 

TinyPortal © 2005-2018