View Issue Details

IDProjectCategoryView StatusLast Update
0032583PackagesLCLpublic2018-02-25 16:06
ReporterHandoko Assigned ToJuha Manninen  
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionfixed 
PlatformLinuxOSUbuntu Mate 
Product Version1.8RC5 
Summary0032583: TMemo.SelText does not work correctly
Description"TMemo.SelText := something" does not work correctly on my tests on Lazarus 1.8.0RC5 Linux 64 Gtk2. Some said it works correctly on Windows but I haven't tested it on Windows.

Please visit this discussion for more information:
http://forum.lazarus.freepascal.org/index.php/topic,38661.msg263329.html#msg263329
Steps To ReproduceUse the code below the reproduce the issue:

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
begin
  Memo1.Text := 'abcdefg';
  for i := 1 to 5 do begin
    Memo1.SelStart := 1;
    Memo1.SelLength := 2;
    Memo1.SelText := 'a';
  end;
end;
TagsNo tags attached.
Fixed in Revisionr56138
LazTarget-
WidgetsetGTK 2
Attached Files

Relationships

related to 0024371 resolvedJuha Manninen Lazarus Wrong usage of SelStart and SelLength in OnChange event only the first time 
related to 0033225 resolvedJuha Manninen Lazarus TMemo SelText problems (Lazarus / Linux) 

Activities

accorp

2017-10-20 13:50

reporter  

issue-32583-seltext.diff (1,442 bytes)   
Index: lcl/interfaces/gtk2/gtk2memostrings.inc
===================================================================
--- lcl/interfaces/gtk2/gtk2memostrings.inc	(revision 56132)
+++ lcl/interfaces/gtk2/gtk2memostrings.inc	(working copy)
@@ -38,6 +38,7 @@
   public
     //property Sorted: boolean read FSorted write SetSorted;
     property Owner: TWinControl read FOwner;
+    property QueueCursorMovePos: Integer read FQueueCursorMove;
     property QueueSelLength: Integer read FQueueSelLength;
   end;
 {$ELSE}
Index: lcl/interfaces/gtk2/gtk2wscustommemo.inc
===================================================================
--- lcl/interfaces/gtk2/gtk2wscustommemo.inc	(revision 56132)
+++ lcl/interfaces/gtk2/gtk2wscustommemo.inc	(working copy)
@@ -328,6 +328,7 @@
 class function TGtk2WSCustomMemo.GetSelStart(const ACustomEdit: TCustomEdit
   ): integer;
 var
+  MemoStrings: TGtk2MemoStrings;
   TextView: PGtkTextView;
   TextBuffer: PGtkTextBuffer;
   TextMark: PGtkTextMark;
@@ -339,6 +340,11 @@
   if not WSCheckHandleAllocated(ACustomEdit, 'GetSelStart') then
     Exit;
 
+  MemoStrings := TCustomMemo(ACustomEdit).Lines as TGtk2MemoStrings;
+  Result := MemoStrings.QueueCursorMovePos;
+  if Result > 0 then
+    Exit;
+
   TextView := PGtkTextView(GetWidgetInfo({%H-}Pointer(ACustomEdit.Handle), False)^.CoreWidget);
   TextBuffer := gtk_text_view_get_buffer(TextView);
   TextMark := gtk_text_buffer_get_insert(TextBuffer);
issue-32583-seltext.diff (1,442 bytes)   

accorp

2017-10-20 13:53

reporter   ~0103605

A patch uploaded.

Thaddy de Koning

2017-10-20 13:56

reporter   ~0103606

Isn't sellength a byte length? And zero terminated?

Juha Manninen

2017-10-20 23:04

developer   ~0103624

The patch really fixes the problem. Applied, thanks.
Could you please also test the related issue.

Handoko

2017-10-23 18:44

reporter   ~0103722

The patch did not fully fix the problem.

Try this:
----------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Text := 'abc';
  Memo1.SelStart := 0;
  Memo1.SelLength := 1;
  Memo1.SelText := 'd'; // Result should be 'dbc', but is 'abcd'
end;
----------------------------------------

More information:
http://forum.lazarus.freepascal.org/index.php/topic,38661.msg263723.html#msg263723

accorp

2017-10-23 20:52

reporter  

issue-32583-fix-zero-pos.diff (2,336 bytes)   
Index: lcl/interfaces/gtk2/gtk2memostrings.inc
===================================================================
--- lcl/interfaces/gtk2/gtk2memostrings.inc	(revision 56176)
+++ lcl/interfaces/gtk2/gtk2memostrings.inc	(working copy)
@@ -57,7 +57,7 @@
 
   AStrings.FTimerMove:=0; // to know if this timer is active when destroyed
 
-  if AStrings.FQueueCursorMove = -1 then
+  if AStrings.FQueueCursorMove = -2 then
   begin
     // always scroll so the cursor is visible
     TextMark := gtk_text_buffer_get_insert(AStrings.FGtkBuf);
@@ -71,7 +71,7 @@
   end;
   gtk_text_view_scroll_to_mark(AStrings.FGtkText, TextMark, 0, True, 0, 1);
 
-  AStrings.FQueueCursorMove := 0;
+  AStrings.FQueueCursorMove := -1;
 end;
 
 function UpdateMemoSelLengthCB(AStrings: TGtk2MemoStrings): gboolean; cdecl;
@@ -153,6 +153,7 @@
   if TheOwner = nil then RaiseGDBException(
     'TGtk2MemoStrings.Create Unspecified owner');
   FOwner:=TheOwner;
+  FQueueCursorMove := -1;
   FQueueSelLength := -1;
   FTimerMove := 0;
   FTimerSel := 0;
@@ -231,12 +232,12 @@
       NewLine := S+LineEnding;
   end;
 
-  if FQueueCursorMove = 0 then
+  if FQueueCursorMove = -1 then
   begin
     TextMark := gtk_text_buffer_get_insert(FGtkBuf);
     gtk_text_buffer_get_iter_at_mark(FGtkBuf, @CursorIter, TextMark);
     if gtk_text_iter_equal(@StartIter, @CursorIter) then
-      QueueCursorMove(-1);
+      QueueCursorMove(-2);
   end;
   
   // and finally insert the new text
@@ -280,7 +281,7 @@
 begin
   // needed because there is a callback that updates the GtkBuffer
   // internally so that it actually knows where the cursor is
-  if FQueueCursorMove = 0 then
+  if FQueueCursorMove = -1 then
     FTimerMove := gtk_timeout_add(0,TGSourceFunc(@UpdateMemoCursorCB), Pointer(Self));
   FQueueCursorMove := APosition;
 end;
Index: lcl/interfaces/gtk2/gtk2wscustommemo.inc
===================================================================
--- lcl/interfaces/gtk2/gtk2wscustommemo.inc	(revision 56176)
+++ lcl/interfaces/gtk2/gtk2wscustommemo.inc	(working copy)
@@ -344,7 +344,7 @@
 
   MemoStrings := TCustomMemo(ACustomEdit).Lines as TGtk2MemoStrings;
   Result := MemoStrings.QueueCursorMovePos;
-  if Result > 0 then
+  if Result > -1 then
     Exit;
 
   TextView := PGtkTextView(GetWidgetInfo({%H-}Pointer(ACustomEdit.Handle), False)^.CoreWidget);
issue-32583-fix-zero-pos.diff (2,336 bytes)   

accorp

2017-10-23 20:54

reporter   ~0103725

Zero position is used internally to indicate there is no move attempts in queue, attached patch change it to -1, please test.

tomitomy

2017-10-24 14:36

reporter   ~0103736

this code can't get the correct results after applied the last patch:
----------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Text := 'abcd';
  Memo1.SelStart := 1;
  Memo1.SelLength := 1;
  Memo1.SelText := 'x';
  Memo1.SelText := 'x'; // should be 'axxcd', but is 'axxd'
  Memo1.SetFocus;
  writeln(Memo1.SelStart, ' ', Memo1.SelLength);
end;
----------------------------------------

More information:
http://forum.lazarus.freepascal.org/index.php/topic,38661.msg263743.html#msg263743

accorp

2017-10-25 00:54

reporter  

issue-32583-fix-sel.diff (474 bytes)   
Index: lcl/interfaces/gtk2/gtk2memostrings.inc
===================================================================
--- lcl/interfaces/gtk2/gtk2memostrings.inc	(revision 56180)
+++ lcl/interfaces/gtk2/gtk2memostrings.inc	(working copy)
@@ -245,6 +245,8 @@
 
 procedure TGtk2MemoStrings.SetTextStr(const Value: string);
 begin
+  if FQueueSelLength <> -1 then
+    QueueSelectLength(0);
   if (Value <> Text) then
   begin
     LockOnChange({%H-}PGtkObject(Owner.Handle), 1);
issue-32583-fix-sel.diff (474 bytes)   

accorp

2017-10-25 00:55

reporter   ~0103750

Added "issue-32583-fix-sel.diff" - reset SelLength on text assignment.

accorp

2017-10-25 15:11

reporter  

issue-32583-fix-onchange.diff (627 bytes)   
Index: lcl/widgetset/wsstdctrls.pp
===================================================================
--- lcl/widgetset/wsstdctrls.pp	(revision 56188)
+++ lcl/widgetset/wsstdctrls.pp	(working copy)
@@ -582,8 +582,9 @@
   NewText := UTF8Copy(OldText, 1, OldPos) +
              NewSelText +
              UTF8Copy(OldText, OldPos + ACustomEdit.SelLength + 1, MaxInt);
+  ACustomEdit.SelStart := OldPos + UTF8Length(NewSelText);
+  ACustomEdit.SelLength := 0;
   ACustomEdit.Text := NewText;
-  ACustomEdit.SelStart := OldPos + UTF8Length(NewSelText);
 end;
 
 class procedure TWSCustomEdit.Cut(const ACustomEdit: TCustomEdit);

accorp

2017-10-25 15:12

reporter   ~0103762

Added "issue-32583-fix-onchange.diff" - set valid SelStart and SelLength before OnChange event occur.

tomitomy

2017-12-27 03:22

reporter   ~0105033

These bugs still exists in Lazarus 1.8.0, the patches seems have not applied in Lazarus 1.8.0

Fedon Kadifeli

2018-01-04 10:14

reporter   ~0105315

By adding
   Application.ProcessMessages;
before
   Memo1.SelText := ...
I am able to fix the problem. Do the SelStart and/or SelText properties need to call ProcessMessages and/or HandleMessages before returning to the calling process?

Fedon Kadifeli

2018-01-27 15:20

reporter   ~0106073

Is there a possibility to reopen this issue? Or shall I report a new bug?

jamie philbrook

2018-01-27 20:47

reporter   ~0106077

To set the record straight, taking this from the Delphi Help manual which
should be the way the MEMO is to work...

 When setting the selText while the SelLength Is not zero , it will over write
the selection where the SelStart is, not insert! If Sellength is 0, then it will insert the text where the cursor is only if the control has focus of course.
 
 And on top of this, the strings are 0 based indexed.

Fedon Kadifeli

2018-01-31 17:30

reporter   ~0106147

Jamie.

This problem is not related to SelLength or SelStart. SelText does not get the new SelStart and SelLength values when run in the same action block:

The code:

procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Text := 'abcd';
  Memo1.SelStart := 1;
  Memo1.SelLength := 1;
  Memo1.SelText := 'x';
  Memo1.SelText := 'x';
  Memo1.SetFocus;
  writeln(Memo1.SelStart, ' ', Memo1.SelLength);
end;

Results in:

abcdxx
6 1

However if we put Application.ProcessMessages before Memo1.SelText like this:

procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Text := 'abcd';
  Memo1.SelStart := 1;
  Memo1.SelLength := 1;
 Application.ProcessMessages;
  Memo1.SelText := 'x';
 Application.ProcessMessages;
  Memo1.SelText := 'x';
  Memo1.SetFocus;
  writeln(Memo1.SelStart, ' ', Memo1.SelLength);
end;

we get (the correct answer):

axxcd
5 0


This problem occurs ONLY on Linux! On Windows there is no need for Application.ProcessMessages.

Fedon Kadifeli

2018-02-19 18:31

reporter   ~0106461

Problem is present in 1.8.0, but it seems to have been fixed in 1.9.0 (SVN 57264).

Issue History

Date Modified Username Field Change
2017-10-20 08:45 Handoko New Issue
2017-10-20 13:50 accorp File Added: issue-32583-seltext.diff
2017-10-20 13:53 accorp Note Added: 0103605
2017-10-20 13:56 Thaddy de Koning Note Added: 0103606
2017-10-20 22:44 Juha Manninen Relationship added related to 0024371
2017-10-20 23:02 Juha Manninen Assigned To => Juha Manninen
2017-10-20 23:02 Juha Manninen Status new => assigned
2017-10-20 23:04 Juha Manninen Fixed in Revision => r56138
2017-10-20 23:04 Juha Manninen LazTarget => -
2017-10-20 23:04 Juha Manninen Note Added: 0103624
2017-10-20 23:04 Juha Manninen Status assigned => resolved
2017-10-20 23:04 Juha Manninen Resolution open => fixed
2017-10-23 18:44 Handoko Note Added: 0103722
2017-10-23 20:52 accorp File Added: issue-32583-fix-zero-pos.diff
2017-10-23 20:54 accorp Note Added: 0103725
2017-10-24 14:36 tomitomy Note Added: 0103736
2017-10-25 00:54 accorp File Added: issue-32583-fix-sel.diff
2017-10-25 00:55 accorp Note Added: 0103750
2017-10-25 15:11 accorp File Added: issue-32583-fix-onchange.diff
2017-10-25 15:12 accorp Note Added: 0103762
2017-12-27 03:22 tomitomy Note Added: 0105033
2018-01-04 10:14 Fedon Kadifeli Note Added: 0105315
2018-01-27 15:20 Fedon Kadifeli Note Added: 0106073
2018-01-27 20:47 jamie philbrook Note Added: 0106077
2018-01-31 17:30 Fedon Kadifeli Note Added: 0106147
2018-02-19 18:31 Fedon Kadifeli Note Added: 0106461
2018-02-25 16:06 Juha Manninen Relationship added related to 0033225