Recent

Author Topic: Problem to restore previous cursor+scroll-position in a TMemo (Linux gtk2 only)  (Read 527 times)

Hartmut

  • Hero Member
  • *****
  • Posts: 1094
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:
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, LCLType, strutils;
  9.  
  10. type
  11.  
  12.  { TForm1 }
  13.  
  14.  TForm1 = class(TForm)
  15.   Memo1: TMemo;
  16.   procedure FormCreate(Sender: TObject);
  17.   procedure showMemoScrollbar(n: integer);
  18.   procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  19.  end;
  20.  
  21. var Form1: TForm1;
  22.  
  23. implementation
  24.  
  25. {$R *.lfm}
  26.  
  27. { TForm1 }
  28.  
  29. procedure TForm1.FormCreate(Sender: TObject);
  30.    var s: string;
  31.        i: integer;
  32.    begin
  33.    s:=''; {fill the Memo with some text: }
  34.    for i:=1 to 50 do  s:=s + i.ToString + ' abcdefghijklmnopqrstuvwxyz' + LineEnding;
  35.  
  36.    Memo1.ScrollBars:=ssAutoBoth;
  37.    Memo1.Text:=s;
  38.    end;
  39.  
  40. procedure TForm1.showMemoScrollbar(n: integer);
  41.    {shows some infos about 'Memo1.VertScrollBar'}
  42.    var SB: TMemoScrollbar;
  43.    begin
  44.    SB:=Memo1.VertScrollBar;
  45.    writeln('--- ', n.ToString, ') Position=', SB.Position, ' Range=', SB.Range, ' Page=', SB.Page);
  46.    end;
  47.  
  48. procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  49.    {Key 'F5' shows a changed content in the Memo and the previous cursor- and
  50.     scroll-position in the Memo shall be unchanged (restored)}
  51.    var s: string;
  52.        curpos,vpos: longint;
  53.    begin
  54.    if Key <> VK_F5 then exit;
  55.  
  56.    s:=Memo1.Text; {simulate that the Memo has a changed content: }
  57.    if pos('+',s)=0 then s:=AnsiReplaceText(s,'n','+')
  58.                    else s:=AnsiReplaceText(s,'+','n');
  59.  
  60.    curpos:=Memo1.SelStart;             {remember previous cursor position}
  61.    vpos:=Memo1.VertScrollBar.Position; {remember previous scroll position}
  62.    writeln('curpos=', curpos);
  63.    showMemoScrollbar(1);
  64.  
  65.    Memo1.Text:=s;                      {change the content in the Memo}
  66.    showMemoScrollbar(2);
  67.  
  68.    Memo1.VertScrollBar.Position:=vpos; {restore previous scroll position}
  69.    Memo1.SelStart:=curpos;             {restore previous cursor position}
  70.    showMemoScrollbar(3);
  71.    end;
  72.  
  73. 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 qt5
but 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=414

but 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=414

What 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.

Hartmut

  • Hero Member
  • *****
  • Posts: 1094
Meanwhile I found out some more informations which might help:
  • If I skip command 'Memo1.VertScrollBar.Position:=vpos' (in line 68) or if I move it behind command 'Memo1.SelStart:=curpos' then the behaviour is the same as before. So this command to restore the old scroll position seems always to be completely ignored.
  • The problem occurs exactly always, if 'Memo1.VertScrollBar.Position' is greater than '0' (when F5 is pressed).
Can somebody help?

Hartmut

  • Hero Member
  • *****
  • Posts: 1094
I made one more strange observation which possibly might help:
If I deactivate command 'Memo1.SelStart:=curpos' (line 69), then suddenly command 'Memo1.VertScrollBar.Position:=vpos' (line 68) works! That means, scrolling then works correctly (of course, the cursor position then is not restored).
But as soon as 'Memo1.SelStart:=curpos' is active - no matter if before or behind 'Memo1.VertScrollBar.Position:=vpos' - then this command to restore the old scroll position is completely ignored.

What can it be, that 'Memo1.SelStart:=curpos' sabotages 'Memo1.VertScrollBar.Position:=vpos' - no matter if before or behind it? Has someone an idea to overcome this?

 

TinyPortal © 2005-2018