[Lazarus] SynEdit.TextBetweenPoints (Martin?)
Bart
bartjunk64 at gmail.com
Sat Aug 10 19:28:24 CEST 2019
Hi,
Consider this piece of code.
On a form have a TSynEdit (named: Ed) and a TSpeedButton.
procedure TForm1.SpeedButton1Click(Sender: TObject);
var
BB, BE: TPoint;
BackwardsSel: Boolean;
SelLength: Integer;
const
Pre = '{';
Post = '}';
begin
writeln('===================');
writeln;
with Ed do
begin
BB := BlockBegin;
BE := BlockEnd;
BackwardsSel := IsBackwardSel;
SelLength := SelEnd-SelStart;
writeln('BlockBegin =',bb.x,',',bb.y);
writeln('BlockEnd =',be.x,',',be.y);
writeln('SelLength =',SelLength);
writeln('BackwardsSel=',BackwardsSel);
//BB is always before BE even if IsBackwardSel=TRUE
//move caret to the end of the selection
LogicalcaretXY := BlockEnd;
//SetLogicalCaret clears the selection, so restore it
BlockBegin := BB;
BlockEnd := BE;
BB := BlockBegin;
BE := BlockEnd;
writeln('After SetLogicalCaret');
writeln('BlockBegin =',bb.x,',',bb.y);
writeln('BlockEnd =',be.x,',',be.y);
//Insert Pre at blockbegin, so in front of the selection: block
moves to the right, blockbegin.x and blockend.x will increase
SetTextBetweenPoints(BB, BB, Pre, [setMoveBlock], scamIgnore,
smaMoveUp, smNormal);
BB := BlockBegin;
BE := BlockEnd;
writeln('After SetTextBetweenPoints(BB,BB,...)');
writeln('BlockBegin =',bb.x,',',bb.y);
writeln('BlockEnd =',be.x,',',be.y);
//Insert Post at blockend, the block does NOT move, so this should
NOT affect the value of blockbegin or blockend
SetTextBetweenPoints(BE, BE, Post, [setMoveBlock], scamIgnore,
smaMoveUp, smNormal);
//Now the caret needs to be moved to BlockBegin, but unfortunately
this unselects the selection
//so we save where it ends, then restore it
BB := BlockBegin;
BE := BlockEnd;
writeln('After SetTextBetweenPoints(BE,BE,...)');
writeln('BlockBegin =',bb.x,',',bb.y);
writeln('BlockEnd =',be.x,',',be.y);
if not BackwardsSel then
LogicalCaretXY := BlockEnd
else
LogicalCaretXY := BlockBegin;
BlockBegin := BB;
BlockEnd := BE;
writeln('After SetLogicalCaret');
writeln('BlockBegin =',bb.x,',',bb.y);
writeln('BlockEnd =',be.x,',',be.y);
end;
writeln;
writeln('===================');
writeln;
end;
It's intention is to put Pre in front of the current selection and
Post after it.
The original selected text should still be selected after it, and the
caret must be at the end of the selected text.
Build and run.
Now in an empty synedit type a single character e.g. '1' (at point (1,1))
Run the code.
It works as expected.
The text is now {1} and the 1 is selected.
Now clear the synedit again.
Run the code again.
This time the text will be {} (as expected), but the entire {} will be selected.
Here's the debug output:
Case 1 (1 character at (1,1) selected):
BlockBegin =1,1
BlockEnd =2,1
SelLength =1
BackwardsSel=FALSE
After SetLogicalCaret
BlockBegin =1,1
BlockEnd =2,1
After SetTextBetweenPoints(BB,BB,...)
BlockBegin =2,1
BlockEnd =3,1
After SetTextBetweenPoints(BE,BE,...)
BlockBegin =2,1
BlockEnd =3,1
After SetLogicalCaret
BlockBegin =2,1
BlockEnd =3,1
Case 2 (no text selected)
BlockBegin =1,1
BlockEnd =1,1
SelLength =0
BackwardsSel=FALSE
After SetLogicalCaret
BlockBegin =1,1
BlockEnd =1,1
After SetTextBetweenPoints(BB,BB,...)
BlockBegin =1,1
BlockEnd =2,1
After SetTextBetweenPoints(BE,BE,...)
BlockBegin =1,1
BlockEnd =3,1
After SetLogicalCaret
BlockBegin =1,1
BlockEnd =3,1
===================
When text is selected, SetTextBetweenPoints will move the block to the
right if we insert text before it and adjust BlockBegin and BlockEnd
accordingly.
However when no text is selected, BlockBegin. remains unchanged, but
BlockEnd is incremented, which IMO is wrong: BlockBegin.X should be
incremented by the amount dicated by the contents of Pre (in this case
BlockBegin.X should be incremented by 1).
Is this a bug (in SetTextBetweenPoints?) or do I need to adjust my
code for the case where no text is selected?
--
Bart
More information about the lazarus
mailing list