Recent

Author Topic: Lazarus Copy and Paste  (Read 17425 times)

kapibara

  • Hero Member
  • *****
  • Posts: 610
Lazarus Copy and Paste
« on: February 16, 2017, 02:13:31 pm »
In Lazarus GTK2 trunk and fixes, copy and paste between two instances of Lazarus doesn't work anymore. It is caused by a bugfix:
http://bugs.freepascal.org/view.php?id=21453#c92282

I'm not exactly sure how to deal with it, but it would be pity if next release of Lazarus still had this problem.

I have solved it by commenting out 2 lines in:
Code: Pascal  [Select][+][-]
  1. lazarus/lcl/interfaces/gtk2/gtk2callback.inc
..and recompiled.

For trunk, remove lines 3574 and 3575.
Lazarus 1.6 fixes branch: remove lines 3740 and 3741.

Trunk, line 11 and 12:

Code: Pascal  [Select][+][-]
  1. procedure SetData(SelectionData: PGtkSelectionData; MemStream: TMemoryStream);
  2. var
  3.   Buffer: Pointer;
  4.   BufLength: integer;
  5. begin
  6.   BufLength:=integer(MemStream.Size);
  7.   GetMem(Buffer,BufLength);
  8.   Assert(Assigned(Buffer) and (BufLength>0), 'SetData: GTK2 clipboard Buffer=Nil or empty.');
  9.   MemStream.Read(Buffer^,BufLength);
  10.   // Issue #21453. gtk_selection_data_set adds the required null. Remove it here.
  11. //  if PChar(Buffer+BufLength-1)^ = #0 then
  12. //    dec(BufLength);
  13.   gtk_selection_data_set(SelectionData,SelectionData^.Target,8,Buffer,BufLength);
  14.   FreeMem(Buffer);
  15. end;
  16.  

Fixes, line 93 and 94:

Code: Pascal  [Select][+][-]
  1. procedure ClipboardSelectionRequestHandler(TargetWidget: PGtkWidget;
  2.   SelectionData: PGtkSelectionData; Info: cardinal; TimeID: cardinal;
  3.   Data: Pointer); cdecl;
  4. var ClipboardType: TClipboardType;
  5.   MemStream: TMemoryStream;
  6.   FormatID: cardinal;
  7.   Buffer: Pointer;
  8.   BufLength: integer;
  9.   BitCount: integer;
  10.   P: PChar;
  11. begin
  12.   {$IFDEF DEBUG_CLIPBOARD}
  13.   DebugLn('*** [ClipboardSelectionRequestHandler] START');
  14.   {$ENDIF}
  15.   if (Data=nil) or (TimeID=0) or (Info=0) or (TargetWidget=nil) then ;
  16.   if SelectionData^.Target=0 then exit;
  17.   for ClipboardType:=Low(TClipboardType) to High(TClipboardType) do begin
  18.     if SelectionData^.Selection=ClipboardTypeAtoms[ClipboardType] then begin
  19.       if Assigned(ClipboardHandler[ClipboardType]) then begin
  20.         // handler found for this of clipboard
  21.         // now create a stream and find a supported format
  22.         {$IFDEF DEBUG_CLIPBOARD}
  23.         DebugLn('[ClipboardSelectionRequestHandler] "',ClipboardTypeName[ClipboardType],'" Format=',GdkAtomToStr(SelectionData^.Target),' ID=',dbgs(SelectionData^.Target));
  24.         {$ENDIF}
  25.         MemStream:=TMemoryStream.Create;
  26.         try
  27.           // the gtk-interface provides automatically some formats, that the lcl
  28.           // does not know. Wrapping them to lcl formats ...
  29.           FormatID:=SelectionData^.Target;
  30.           if ((FormatID=gdk_atom_intern('COMPOUND_TEXT',GdkTrue))
  31.             and (ClipboardExtraGtkFormats[ClipboardType][gfCOMPOUND_TEXT]))
  32.           or ((FormatID=gdk_atom_intern('UTF8_STRING',GdkTrue))
  33.             and (ClipboardExtraGtkFormats[ClipboardType][gfUTF8_STRING]))
  34.           or ((FormatID=gdk_atom_intern('STRING',GdkTrue))
  35.             and (ClipboardExtraGtkFormats[ClipboardType][gfSTRING]))
  36.           or ((FormatID=gdk_atom_intern('TEXT',GdkTrue))
  37.             and (ClipboardExtraGtkFormats[ClipboardType][gfTEXT]))
  38.           then
  39.             FormatID:=gdk_atom_intern('text/plain',GdkTrue);
  40.  
  41.           {$IFDEF DEBUG_CLIPBOARD}
  42.           DebugLn('[ClipboardSelectionRequestHandler] FormatID=',dbgs(FormatID),'=',GdkAtomToStr(FormatID),' ',dbgs(ClipboardExtraGtkFormats[ClipboardType][gfCOMPOUND_TEXT]));
  43.           {$ENDIF}
  44.           // get the requested data by calling the handler for this clipboard type
  45.           ClipboardHandler[ClipboardType](FormatID,MemStream);
  46.           MemStream.Position:=0;
  47.  
  48.           // build clipboard data for gtk
  49.           Buffer:=nil;
  50.           BufLength:=0;
  51.           BitCount:=8;
  52.  
  53.           // if the format was wrapped, transform it back
  54.           if (FormatID=gdk_atom_intern('text/plain',GdkTrue)) then begin
  55.             if (SelectionData^.Target=gdk_atom_intern('COMPOUND_TEXT',GdkTrue))
  56.             then begin
  57.               // transform text/plain to COMPOUND_TEXT
  58.               BufLength:=integer(MemStream.Size);
  59.               P:=StrAlloc(BufLength+1);
  60.               MemStream.Read(P^,BufLength);
  61.               P[BufLength]:=#0;
  62.  
  63.               BufLength:=0;
  64.               gdk_string_to_compound_text(P,
  65.                 @SelectionData^._Type,
  66.                 @SelectionData^.Format,ppguchar(@Buffer),@BufLength);
  67.               StrDispose(P);
  68.               gtk_selection_data_set(SelectionData,SelectionData^.Target,
  69.                 SelectionData^.Format,Buffer,BufLength);
  70.               gdk_free_compound_text(Buffer);
  71.               exit;
  72.             end;
  73.           end;
  74.           if Buffer=nil then begin
  75.             {$IFDEF DEBUG_CLIPBOARD}
  76.             DebugLn('[ClipboardSelectionRequestHandler] Default MemStream.Size=',dbgs(MemStream.Size));
  77.             {$ENDIF}
  78.             BufLength:=integer(MemStream.Size);
  79.             if BufLength>0 then begin
  80.               GetMem(Buffer,BufLength);
  81.               MemStream.Read(Buffer^,BufLength);
  82.               {SetLength(s,MemStream.Size);
  83.               MemStream.Position:=0;
  84.               MemStream.Read(s[1],MemStream.Size);
  85.               DebugLn(' >>> "',s,'"');}
  86.             end;
  87.           end;
  88.           {$IFDEF DEBUG_CLIPBOARD}
  89.           DebugLn('[ClipboardSelectionRequestHandler] Len=',dbgs(BufLength));
  90.           {$ENDIF}
  91.           // workaround for issues 21453 and 30071.
  92.           // gtk_selection_data_set auto adds the required null term. Remove it here.
  93. //          if (BufLength>0) and (PChar(Buffer+BufLength-1)^ = #0) then
  94. //            dec(BufLength);
  95.           gtk_selection_data_set(SelectionData,SelectionData^.Target,BitCount,
  96.             Buffer,BufLength);
  97.           if Buffer<>nil then
  98.             FreeMem(Buffer);
  99.         finally
  100.           MemStream.Free;
  101.         end;
  102.       end;
  103.       break;
  104.     end;
  105.   end;
  106. end;
« Last Edit: February 16, 2017, 06:23:21 pm by kapibara »
Lazarus trunk / fpc 3.2.2 / Kubuntu 22.04 - 64 bit

jacmoe

  • Full Member
  • ***
  • Posts: 249
    • Jacmoe's Cyber SoapBox
Re: Lazarus Copy and Paste
« Reply #1 on: February 16, 2017, 02:25:52 pm »
Just posting it here will probably not make the bug go away.

Since this is a result of a bug fix, it would probably be appropriate to comment on the bug so that it can be reopened?
more signal - less noise

kapibara

  • Hero Member
  • *****
  • Posts: 610
Re: Lazarus Copy and Paste
« Reply #2 on: February 16, 2017, 02:38:35 pm »
I have already talked to Juha a while ago, he suggested I have a chat with the guy who pushed for the bugfix that caused this.

But I forgot and now I think it's better to have some more opinions about it from the community, how to solve it. Because commenting out the "bug" puts the first guy back on square 1. Seems to be more to it than meets the eye. Maybe someone here knows more.
Lazarus trunk / fpc 3.2.2 / Kubuntu 22.04 - 64 bit

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4459
  • I like bugs.
Re: Lazarus Copy and Paste
« Reply #3 on: February 16, 2017, 04:54:12 pm »
I understood the data copied to clipboard is now correct. The paste operation must be buggy then. But, pasting from other apps works OK. Strange indeed!

@kapibara, why don't you communicate with BBaz and try to solve it yourself?
I will not do it, unfortunately I don't have enough energy for this issue.
I can commit a patch that satisfies all parties though.
Mostly Lazarus trunk and FPC 3.2 on Manjaro Linux 64-bit.

kapibara

  • Hero Member
  • *****
  • Posts: 610
Re: Lazarus Copy and Paste
« Reply #4 on: February 16, 2017, 06:27:03 pm »
@Juha Okay. I invited BBaz to this thread by personal message. His last login here was 2013 though, so not sure he'll receive it. Don't know how else to reach him?
Lazarus trunk / fpc 3.2.2 / Kubuntu 22.04 - 64 bit

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4459
  • I like bugs.
Re: Lazarus Copy and Paste
« Reply #5 on: February 16, 2017, 06:38:27 pm »
Don't know how else to reach him?
His bug tracker profile has an email address. You could try that.
I reopened the issue.
Mostly Lazarus trunk and FPC 3.2 on Manjaro Linux 64-bit.

kapibara

  • Hero Member
  • *****
  • Posts: 610
Re: Lazarus Copy and Paste
« Reply #6 on: February 16, 2017, 11:40:03 pm »
I was logged in but the bugtracker didn't show his address:
Code: Pascal  [Select][+][-]
  1. E-mail          Access Denied.
  2.  
Lazarus trunk / fpc 3.2.2 / Kubuntu 22.04 - 64 bit

guest58172

  • Guest
Re: Lazarus Copy and Paste
« Reply #7 on: February 17, 2017, 12:00:28 am »
My username on Mantis is BBaz, I had others forum accounts (BBaz, Basile.B, others maybe...), lost the logins so it's me now.

I don't care about supplemental fixes, as long as the data copied from Lazarus components to other applications don't contain this damn null sentinel.

Fix the regressions but check that the most important thing is still fixed too, so to verify just paste a line copied from Laz Syn editor to IDEONE.
The bug is fixed when there's no red dot at the end...

For example in the picture it's a line of code copied from a TSynEdit build with LCL 1.6.2 (so not with the fix).

Also, if you cahnge things, make them available for 1.6.4. From my side I do need the fix on the next point release.

kapibara

  • Hero Member
  • *****
  • Posts: 610
Re: Lazarus Copy and Paste
« Reply #8 on: February 17, 2017, 11:19:04 am »
I have tested this on Lazarus trunk and fixes version. With the bugfix removed, copied the text below from Lazarus editor and also from a SynEdit component to the ideone site. No red dot.

Code: Pascal  [Select][+][-]
  1. //Testing copy/paste...
  2.  
  3. import java.util.*;
  4. import java.lang.*;
  5. import java.io.*;

Can you try comment out the 2 lines of code I showed above, recompile Lazarus, and see if it works for you?
« Last Edit: February 17, 2017, 11:20:58 am by kapibara »
Lazarus trunk / fpc 3.2.2 / Kubuntu 22.04 - 64 bit

guest58172

  • Guest
Re: Lazarus Copy and Paste
« Reply #9 on: February 17, 2017, 11:29:53 am »
Awesome but how can I try your patch since you the Pascal guys are still using SVN ? Do you have a git clone with a branch that contains the fix ?

guest58172

  • Guest
Re: Lazarus Copy and Paste
« Reply #10 on: February 17, 2017, 11:35:42 am »
Never mind, propose a patch to Mantis and I'll test it when it'll get merged and when one of the git mirror will be updated.
TBH that's not an ideal workflow, but how to say, when there's no other choice the right way is clear.

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4459
  • I like bugs.
Re: Lazarus Copy and Paste
« Reply #11 on: February 17, 2017, 12:39:23 pm »
Never mind, propose a patch to Mantis and I'll test it when it'll get merged and when one of the git mirror will be updated.
+1
kapibara, please upload a patch against Lazarus trunk to the Mantis issue. The fixes branch does not matter at this point.
BBasile can apply it to his local copy and test.

Quote
TBH that's not an ideal workflow, but how to say, when there's no other choice the right way is clear.
The workflow is pretty much ideal IMO. :)
A patch can be downloaded from Mantis and applied to your local copy of trunk easily.
 http://wiki.freepascal.org/Creating_A_Patch#Applying_a_patch
You can get trunk by using SVN or Git, makes no difference.
The GitHub process with setting your SHA codes, a fork, a "git pull" to local PC, a "git push" to GitHub, a pull request etc. is much more complicated. It is also more limited, for example you could not assign a fork to a Lazarus sub-system maintainer in GitHub.

BTW, I use Git myself for Lazarus development. Local branches and "git bisect" are very nice!
 http://wiki.freepascal.org/Lazarus_git-svn
For read-only access you can use mirrors:
 http://wiki.freepascal.org/git_mirrors
Anyway SVN as a central server is very good. It is robust and we get proper sequential revision numbers. What more, people who like Git can connect to SVN server but it would not be possible the other way around.

This SVN / Git issue must be a flashback from years ago when it was fashionable to bash Lazarus developers for not switching to Git. Switching was said to increase the number of contributions substantially.
I then documented a way to use Git for Lazarus development and asked all other devels to support Git formatted patches. The bashing more or less stopped but, surprise, there were not any more contributions after it.
BTW, I promised to support a forked GitHub repo directly:
 http://wiki.freepascal.org/Creating_A_Patch#Using_a_forked_Git_repository_directly
... but nobody still has offered his fork. Why is that? Maybe it is not so fantastic after all. Actually I am happy about it, patches through Mantis are much easier to handle and any Git user can create them with "git format-patch". Yes, it it easier than the GitHub fork process!

Anyway, let's please cut this SVN / Git nonsense. It is not an issue in real development.
« Last Edit: February 17, 2017, 12:49:13 pm by JuhaManninen »
Mostly Lazarus trunk and FPC 3.2 on Manjaro Linux 64-bit.

kapibara

  • Hero Member
  • *****
  • Posts: 610
Re: Lazarus Copy and Paste
« Reply #12 on: February 17, 2017, 02:00:56 pm »
@Juha It is uploaded
Lazarus trunk / fpc 3.2.2 / Kubuntu 22.04 - 64 bit

guest58172

  • Guest
Re: Lazarus Copy and Paste
« Reply #13 on: February 18, 2017, 08:22:29 am »
Try copy & paste using Lazarus 1.6.2 Vanilla (as distributed or after checkout the tag in the repo) and tell me if you see the red dot on ideone.

Currently I suspect that for a reason or another you've never been affected by the bug. If it's the case then we have a serious problem. The Gtk documentation states clearly that it adds automatically the null terminator.
I you want to discuss about the bug I'm on IRC today (DotBatch), even if, tbh, I really don't want to spent my day to recompile Laz.

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4459
  • I like bugs.
Re: Lazarus Copy and Paste
« Reply #14 on: February 18, 2017, 09:36:35 am »
Try copy & paste using Lazarus 1.6.2 Vanilla (as distributed or after checkout the tag in the repo) and tell me if you see the red dot on ideone.
Using my local Git Lazarus trunk repo, I jumped to r53375 which is before the original commits for this issue. Then I built clean using GTK2 widgetset. I cannot see a red dot when copying from Lazarus to Ideone. So, I cannot reproduce the original bug.

Quote
Currently I suspect that for a reason or another you've never been affected by the bug. If it's the case then we have a serious problem. The Gtk documentation states clearly that it adds automatically the null terminator.
Yes, we must figure out what makes the difference. Is it a GTK2 version issue? It wouldn't be the first one. Does the desktop system affect. I currently use KDE on a Manjaro system which has recent versions of everything. You guys should test with different Linux distros / versions / desktops.
The original reporter cobines should also test. Where is he?

Quote
I you want to discuss about the bug I'm on IRC today (DotBatch), even if, tbh, I really don't want to spent my day to recompile Laz.
This forum is also a good place to communicate IMO. Posts here can be read also later.
Clean build of Lazarus takes some 2 - 10 minutes depending on computer. It surely does not take a whole day. My main computer is a passively cooled ASRock BeeBox and it takes 4 minutes.

You should test the provided patch on Lazarus trunk. Just "patch -p0 < gtk2callback.diff" and then build. Does not take long. Maybe the bug is there no more ...
If it still is there then you people should figure out why it happens only in some systems.

Important:
Can somebody please explain why copy / paste between 2 Lazarus instances does not work now?
As BBasile says the NULL terminator is copied by GTK2. Copy / paste to any other application works. The data clearly is correct!
Another Lazarus instance is the only app that does not accept the data. Why?
There may be a hack of some sort for pasting data. Then another extra NULL hack was added to work around that hack. Who knows? ...

I am asking for a group effort to solve this. I am not a GTK2 expert and I have many other things to do.
« Last Edit: February 18, 2017, 10:12:23 am by JuhaManninen »
Mostly Lazarus trunk and FPC 3.2 on Manjaro Linux 64-bit.

 

TinyPortal © 2005-2018