I want a feature, that the content of a Memo can be replaced by a new content, but the previous cursor- and scroll-position in the Memo shall be unchanged (restored). What I have, works on Windows and Linux qt5, but not on Linux gtk2. I hope to find a solution or workaround which works on Linux gtk2.
This is a short demo for my current code:
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, LCLType, strutils;
type
{ TForm1 }
TForm1 = class(TForm)
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure showMemoScrollbar(n: integer);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
end;
var Form1: TForm1;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
var s: string;
i: integer;
begin
s:=''; {fill the Memo with some text: }
for i:=1 to 50 do s:=s + i.ToString + ' abcdefghijklmnopqrstuvwxyz' + LineEnding;
Memo1.ScrollBars:=ssAutoBoth;
Memo1.Text:=s;
end;
procedure TForm1.showMemoScrollbar(n: integer);
{shows some infos about 'Memo1.VertScrollBar'}
var SB: TMemoScrollbar;
begin
SB:=Memo1.VertScrollBar;
writeln('--- ', n.ToString, ') Position=', SB.Position, ' Range=', SB.Range, ' Page=', SB.Page);
end;
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
{Key 'F5' shows a changed content in the Memo and the previous cursor- and
scroll-position in the Memo shall be unchanged (restored)}
var s: string;
curpos,vpos: longint;
begin
if Key <> VK_F5 then exit;
s:=Memo1.Text; {simulate that the Memo has a changed content: }
if pos('+',s)=0 then s:=AnsiReplaceText(s,'n','+')
else s:=AnsiReplaceText(s,'+','n');
curpos:=Memo1.SelStart; {remember previous cursor position}
vpos:=Memo1.VertScrollBar.Position; {remember previous scroll position}
writeln('curpos=', curpos);
showMemoScrollbar(1);
Memo1.Text:=s; {change the content in the Memo}
showMemoScrollbar(2);
Memo1.VertScrollBar.Position:=vpos; {restore previous scroll position}
Memo1.SelStart:=curpos; {restore previous cursor position}
showMemoScrollbar(3);
end;
end.
This code works on Windows with Lazarus/FPC 3.6.0/3.2.2 and 2.0.10/3.2.0
and on Linux Ubuntu 24.04 with KDE-Plasma-Desktop and X11 with Lazarus/FPC 3.4.0/3.2.2 and
qt5but not on same Linux with Lazarus/FPC 3.4.0/3.2.2 and 2.0.10/3.2.0 and
gtk2.
How to see the problem with gtk2:
- start the program (a compilable project is attached)
- do not scroll, set the cursor in an arbitrary visible line and press F5
Result: the Memo content changes, but cursor- and scroll-position keep unchanged (as it should).
- now scroll down 20 lines, set the cursor somewhere in line 25 and press F5
Result: the cursor-position keeps unchanged (in line 25), but line 25 is now scrolled down to be the last visible line.
This problem occurs
always, if the Memo, at the time pressing F5, was not scrolled to it's top position (so that line1 was the topmost visible line). Then the previous cursor line always is scrolled down to be the last visible line (if there are enough lines above, otherwise the Memo is scrolled up only, until line1 becomes visible).
I made an observation which maybe might help:
When the problem not occurs (Windows and qt5), then the output is e.g.:
curpos=876
--- 1) Position=414 Range=926 Page=414
--- 2) Position=0 Range=926 Page=414
--- 3) Position=414 Range=926 Page=414but when the problem occurs (with gtk2), the output is e.g.:
curpos=876
--- 1) Position=373 Range=969 Page=414
--- 2) Position=373 Range=969 Page=414
--- 3) Position=373 Range=969 Page=414What I mean, is the green marked Position: when it works, always this Position=0, but when it not works, Position stays unchanged. Don't know if that might be relevant.
As said I hope to find a solution or workaround which works on Linux gtk2. Thanks in advance.