SynEdit: Added some tests

git-svn-id: trunk@21025 -
This commit is contained in:
martin 2009-07-31 14:43:51 +00:00
parent f0d8d78022
commit dbfbbff04f
6 changed files with 704 additions and 0 deletions

4
.gitattributes vendored
View File

@ -1647,6 +1647,10 @@ components/synedit/synpropertyeditobjectlist.lrs svneol=native#text/pascal
components/synedit/synpropertyeditobjectlist.pas svneol=native#text/plain
components/synedit/synregexpr.pas svneol=native#text/pascal
components/synedit/syntextdrawer.pp svneol=native#text/pascal
components/synedit/test/SynTest.lpi svneol=native#text/plain
components/synedit/test/SynTest.lpr svneol=native#text/pascal
components/synedit/test/testbase.pas svneol=native#text/pascal
components/synedit/test/testsynselection.pas svneol=native#text/pascal
components/synunihighlighter/CHANGES.txt svneol=native#text/plain
components/synunihighlighter/CREDITS.txt svneol=native#text/plain
components/synunihighlighter/README.txt svneol=native#text/plain

2
.gitignore vendored
View File

@ -137,6 +137,8 @@ components/synedit/design/*.bak
components/synedit/design/units
components/synedit/languages/*.bak
components/synedit/languages/units
components/synedit/test/*.bak
components/synedit/test/units
components/synedit/units
components/synunihighlighter/*.bak
components/synunihighlighter/languages/*.bak

View File

@ -0,0 +1,100 @@
<?xml version="1.0"?>
<CONFIG>
<ProjectOptions>
<PathDelim Value="\"/>
<Version Value="7"/>
<General>
<MainUnit Value="0"/>
<TargetFileExt Value=".exe"/>
<Icon Value="0"/>
<UseXPManifest Value="True"/>
<ActiveEditorIndexAtStart Value="0"/>
</General>
<VersionInfo>
<ProjectVersion Value=""/>
<Language Value=""/>
<CharSet Value=""/>
</VersionInfo>
<PublishOptions>
<Version Value="2"/>
<IgnoreBinaries Value="False"/>
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
<ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
</PublishOptions>
<RunParams>
<local>
<FormatVersion Value="1"/>
</local>
</RunParams>
<RequiredPackages Count="3">
<Item1>
<PackageName Value="FPCUnitTestRunner"/>
</Item1>
<Item2>
<PackageName Value="LCL"/>
</Item2>
<Item3>
<PackageName Value="FCL"/>
</Item3>
</RequiredPackages>
<Units Count="3">
<Unit0>
<Filename Value="SynTest.lpr"/>
<IsPartOfProject Value="True"/>
<UnitName Value="SynTest"/>
<UsageCount Value="24"/>
</Unit0>
<Unit1>
<Filename Value="testsynselection.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="TestSynSelection"/>
<CursorPos X="78" Y="362"/>
<TopLine Value="345"/>
<EditorIndex Value="0"/>
<UsageCount Value="24"/>
<Bookmarks Count="1">
<Item0 X="35" Y="67" ID="1"/>
</Bookmarks>
<Loaded Value="True"/>
</Unit1>
<Unit2>
<Filename Value="testbase.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="TestBase"/>
<CursorPos X="1" Y="59"/>
<TopLine Value="32"/>
<EditorIndex Value="1"/>
<UsageCount Value="24"/>
<Loaded Value="True"/>
</Unit2>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="8"/>
<PathDelim Value="\"/>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)\"/>
</SearchPaths>
<Other>
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>
<Debugging>
<Watches Count="1">
<Item1>
<Expression Value="FCaret^"/>
</Item1>
</Watches>
<Exceptions Count="3">
<Item1>
<Name Value="EAbort"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
</Item3>
</Exceptions>
</Debugging>
</CONFIG>

View File

@ -0,0 +1,16 @@
program SynTest;
{$mode objfpc}{$H+}
uses
Interfaces, Forms, GuiTestRunner, TestSynSelection, LResources, TestBase;
{$IFDEF WINDOWS}{$R SynTest.rc}{$ENDIF}
begin
{$I SynTest.lrs}
Application.Initialize;
Application.CreateForm(TGuiTestRunner, TestRunner);
Application.Run;
end.

View File

@ -0,0 +1,186 @@
unit TestBase;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, fpcunit, SynEdit, LCLType;
type
{ TTestSynEdit }
TTestSynEdit = class(TSynEdit)
public
procedure TestKeyPress(Key: Word; Shift: TShiftState);
end;
{ TTestBase }
TTestBase = class(TTestCase)
private
FBaseTestName: String;
FBaseTestNames: Array of String;
FForm : TForm;
FSynEdit : TTestSynEdit;
procedure SetBaseTestName(const AValue: String);
protected
function LinesToText(Lines: Array of String; Separator: String = LineEnding;
SeparatorAtEnd: Boolean = False): String;
protected
procedure ReCreateEdit;
procedure SetLines(Lines: Array of String);
procedure SetCaret(X, Y: Integer);
procedure SetCaretAndSel(X1, Y1, X2, Y2: Integer);
procedure DoKeyPress(Key: Word; Shift: TShiftState);
procedure TestFail(Name, Func, Expect, Got: String; Result: Boolean = False);
procedure PushBaseName(Add: String);
procedure PopPushBaseName(Add: String);
procedure PopBaseName;
property BaseTestName: String read FBaseTestName write SetBaseTestName;
property SynEdit: TTestSynEdit read FSynEdit;
property Form: TForm read FForm;
protected
procedure SetUp; override;
procedure TearDown; override;
end;
implementation
{ TTestSynEdit }
procedure TTestSynEdit.TestKeyPress(Key: Word; Shift: TShiftState);
var
c: TUTF8Char;
begin
KeyDown(Key, Shift);
c := '';
if Shift = [] then
case Key of
VK_A..VK_Z: c := chr(Key - VK_A + ord('a'));
VK_0..VK_9: c := chr(Key - VK_0 + ord('0'));
VK_RETURN: c := #13;
VK_TAB: c := #9;
VK_ESCAPE: c := #27;
end
else
if Shift = [ssShift] then
case Key of
VK_A..VK_Z: c := chr(Key - VK_A + ord('A'));
end
else
if Shift - [ssShift] = [ssCtrl] then
case Key of
VK_A..VK_Z: c := chr(Key - VK_A + 1);
end;
if c <> '' then
UTF8KeyPress(c);
KeyUp(Key, Shift);
end;
{ TTestBase }
procedure TTestBase.SetUp;
begin
inherited SetUp;
FForm := TForm.Create(nil);
ReCreateEdit;
FForm.Show;
end;
procedure TTestBase.TearDown;
begin
inherited TearDown;
FreeAndNil(FSynEdit);
FreeAndNil(FForm);
end;
procedure TTestBase.TestFail(Name, Func, Expect, Got: String; Result: Boolean = False);
begin
if Result then exit;
if BaseTestName <> '' then
Fail(Format('%s: %s (%s)%sExpected: %s%s Got: %s', [BaseTestName, Name, Func, LineEnding, Expect, LineEnding, Got]))
else
Fail(Format('%s (%s)%sExpected: %s%s Got: %s', [Name, Func, LineEnding, Expect, LineEnding, Got]));
end;
procedure TTestBase.SetBaseTestName(const AValue: String);
begin
FBaseTestNames := nil;
PushBaseName(AValue);
end;
function TTestBase.LinesToText(Lines: array of String; Separator: String = LineEnding;
SeparatorAtEnd: Boolean = False): String;
var
i: Integer;
begin
Result := '';
for i := low(Lines) to high(Lines) do begin
Result := Result + Lines[i];
if (i <> high(Lines)) or SeparatorAtEnd then
Result := Result + Separator;
end;
end;
procedure TTestBase.ReCreateEdit;
begin
FreeAndNil(FSynEdit);
FSynEdit := TTestSynEdit.Create(FForm);
FSynEdit.Parent := FForm;
FSynEdit.Top := 0;
FSynEdit.Left := 0;
FSynEdit.Width:= 500;
FSynEdit.Height := FSynEdit.Font.Height * 20 + 2;
end;
procedure TTestBase.SetLines(Lines: array of String);
begin
SynEdit.Text := LinesToText(Lines);
end;
procedure TTestBase.SetCaret(X, Y: Integer);
begin
SynEdit.BlockBegin := Point(X, Y);
SynEdit.LogicalCaretXY := Point(X, Y);
end;
procedure TTestBase.SetCaretAndSel(X1, Y1, X2, Y2: Integer);
begin
SynEdit.LogicalCaretXY := Point(X2, Y2);
SynEdit.BlockBegin := Point(X1, Y1);
SynEdit.BlockEnd := Point(X2, Y2);
end;
procedure TTestBase.DoKeyPress(Key: Word; Shift: TShiftState);
begin
SynEdit.TestKeyPress(Key, Shift);
end;
procedure TTestBase.PushBaseName(Add: String);
var
i: Integer;
begin
i := length(FBaseTestNames);
SetLength(FBaseTestNames, i + 1);
FBaseTestNames[i] := Add;
FBaseTestName := LinesToText(FBaseTestNames, '; ');
end;
procedure TTestBase.PopPushBaseName(Add: String);
begin
PopBaseName;
PushBaseName(Add);
end;
procedure TTestBase.PopBaseName;
begin
SetLength(FBaseTestNames, length(FBaseTestNames) - 1);
FBaseTestName := LinesToText(FBaseTestNames, ' ');
end;
end.

View File

@ -0,0 +1,396 @@
unit TestSynSelection;
{$mode objfpc}{$H+}
interface
(* TODO:
- SelectetText for selections Past-EOL, current behaviour is not consistent:
smNormal: SelText = empty => should be spaces?
smColumn: SelText = space(s)
smLine: SelText = TheLine (correct)
- smLine Blocks: Begin/End Points return X values inside the line
*)
uses
Classes, SysUtils, fpcunit, testutils, testregistry, TestBase,
SynEdit, SynEditTypes,
LCLType, LCLProc;
type
{ TTestSynSelection }
TTestSynSelection = class(TTestBase)
protected
procedure TestIsCaret(Name: String; X, Y: Integer);
procedure TestIsBlock(Name: String; X1, Y1, X2, Y2: Integer);
procedure TestIsBlock(Name: String; X1, Y1, X2, Y2: Integer; Text: String);
procedure TestIsBlock(Name: String; X1, Y1, X2, Y2: Integer; Text: Array of String);
procedure TestIsNoBlock(Name: String);
published
procedure SelectByKey;
end;
implementation
procedure TTestSynSelection.TestIsCaret(Name: String; X, Y: Integer);
begin
if (SynEdit.LogicalCaretXY.X <> X) or (SynEdit.LogicalCaretXY.Y <> Y) then
TestFail(Name, 'IsCaret',
Format('X/Y=(%d, %d)', [X, Y]),
Format('X/Y=(%d, %d)', [SynEdit.LogicalCaretXY.X, SynEdit.LogicalCaretXY.Y]));
end;
procedure TTestSynSelection.TestIsBlock(Name: String; X1, Y1, X2, Y2: Integer);
begin
if (not SynEdit.SelAvail)
then
TestFail(Name, 'IsBlock',
Format('X/Y=(%d, %d) - (%d, %d)', [X1, Y1, X2, Y2]),
Format('No Sel Avail (X/Y=(%d, %d) - (%d, %d))', [SynEdit.BlockBegin.X, SynEdit.BlockBegin.Y,
SynEdit.BlockEnd.X, SynEdit.BlockEnd.Y])
);
if (SynEdit.BlockBegin.X <> X1) or (SynEdit.BlockBegin.Y <> Y1) or
(SynEdit.BlockEnd.X <> X2) or (SynEdit.BlockEnd.Y <> Y2)
then
TestFail(Name, 'IsBlock',
Format('X/Y=(%d, %d) - (%d, %d)', [X1, Y1, X2, Y2]),
Format('X/Y=(%d, %d) - (%d, %d)', [SynEdit.BlockBegin.X, SynEdit.BlockBegin.Y,
SynEdit.BlockEnd.X, SynEdit.BlockEnd.Y])
);
end;
procedure TTestSynSelection.TestIsBlock(Name: String; X1, Y1, X2, Y2: Integer; Text: String);
begin
TestIsBlock(Name, X1, Y1, X2, Y2);
if (SynEdit.SelText <> Text) then
TestFail(Name, 'IsBlockText', '"'+DbgStr(Text)+'"', '"'+DbgStr(SynEdit.SelText)+'"');
end;
procedure TTestSynSelection.TestIsBlock(Name: String; X1, Y1, X2, Y2: Integer;
Text: array of String);
begin
TestIsBlock(Name, X1, Y1, X2, Y2, LinesToText(Text));
end;
procedure TTestSynSelection.TestIsNoBlock(Name: String);
begin
if (SynEdit.SelAvail) then
TestFail(Name, 'IsNoBlock', 'No Selection',
Format('X/Y=(%d, %d) - (%d, %d) "%s"',
[SynEdit.BlockBegin.X, SynEdit.BlockBegin.Y,
SynEdit.BlockEnd.X, SynEdit.BlockEnd.Y,
'"'+DbgStr(SynEdit.SelText)+'"'])
);
end;
procedure TTestSynSelection.SelectByKey;
var
SkipBlockOtherEndBack: Boolean;
procedure TestKey(Name: String;
StartX, StartY: Integer; Key: Word; Shift: TShiftState;
EndX, EndY: Integer; ExpText: String;
ExitKey: Word; ExitShift: TShiftState;
ExitX, ExitY, ExitSkippedX, ExitSkippedY: Integer;
Persist: Boolean = False );
var
IsBackward: Boolean;
X1, Y1, X2, Y2: Integer;
SkipKey, SkipBackKey: Word;
procedure TestOnlyPersitBlock(XName: String = '');
begin
if Persist
then TestIsBlock(XName, X1, Y1, X2, Y2, ExpText)
else TestIsNoBlock(XName);
end;
procedure TestKeySelect(Catch: Boolean = False); // Simulate Key - Select
begin
SetCaret(StartX, StartY);
TestIsNoBlock('Sanity, after set caret');
DoKeyPress(Key, Shift);
if (ExpText = '') and Catch then ExpText := SynEdit.SelText; // Capture the text, to cmpare with later selections
TestIsCaret('After Select Key', EndX, EndY);
TestIsBlock('After Select Key', X1, Y1, X2, Y2, ExpText);
end;
begin
PushBaseName(Name);
if Persist then
PushBaseName('Persistent');
IsBackward := (EndY < StartY) or ( (EndY = StartY) and (EndX < StartX) );
if IsBackward then begin
X1 := EndX; Y1 := EndY;
X2 := StartX; Y2 := StartY;
SkipKey := VK_RIGHT;
SkipBackKey := VK_LEFT;
end else begin
X1 := StartX; Y1 := StartY;
X2 := EndX; Y2 := EndY;
SkipKey := VK_LEFT;
SkipBackKey := VK_RIGHT;
end;
if (SynEdit.SelectionMode = smLine) then begin
// Todo: Block x are incorect returned in smLine
//X1 := 1;
//X2 := length(Synedit.Lines[Y2]);
end;
if Persist
then SynEdit.Options2 := SynEdit.Options2 + [eoPersistentBlock]
else SynEdit.Options2 := SynEdit.Options2 - [eoPersistentBlock];
SynEdit.Options := SynEdit.Options - [eoNoSelection];
SynEdit.Options2 := SynEdit.Options2 - [eoCaretSkipsSelection];
// Select, and Unselect
PushBaseName ('Plain Select');
TestKeySelect (True);
DoKeyPress (ExitKey, ExitShift);
TestIsCaret ('After Exit Key', ExitX, ExitY);
TestOnlyPersitBlock('After Exit Key');
// if eoCaretSkipsSelection= OFF, then block is unselected, not Skipped
PopPushBaseName ('Skip=Off (unselect)');
TestKeySelect ();
DoKeyPress (SkipKey, []);
TestOnlyPersitBlock('After Skip Key');
SynEdit.Options2 := SynEdit.Options2 + [eoCaretSkipsSelection];
// Block is kept, if caret skips to other end (eoCaretSkipsSelection)
// Next caret move unselects as normal
if (ExitKey <> SkipBackKey) or (ExitShift <> []) then begin
PopPushBaseName ('Skip=On (keep select)');
TestKeySelect ();
DoKeyPress (SkipKey, []);
TestIsBlock ('After Skip Key', X1, Y1, X2, Y2, ExpText);
DoKeyPress (ExitKey, ExitShift);
TestIsCaret ('After Exit Key', ExitSkippedX, ExitSkippedY);
TestOnlyPersitBlock('After Exit Key');
end;
// Block is kept, if caret skips to other end and back (eoCaretSkipsSelection)
// Next caret move unselects as normal
if ((ExitKey <> SkipKey) or (ExitShift <> [])) and (not SkipBlockOtherEndBack) then begin
PopPushBaseName ('Skip=On (keep select, 2nd)');
TestKeySelect ();
DoKeyPress (SkipKey, []);
TestIsBlock ('After Skip Key', X1, Y1, X2, Y2, ExpText);
DoKeyPress (SkipBackKey, []);
TestIsBlock ('After SkipBack Key', X1, Y1, X2, Y2, ExpText);
DoKeyPress (ExitKey, ExitShift);
TestIsCaret ('After Exit Key', ExitX, ExitY);
TestOnlyPersitBlock('After Exit Key');
end;
// Switching eoCaretSkipsSelection= OFF while selected is taken ito account on next move
PopPushBaseName ('Skip=On/Off');
TestKeySelect ();
DoKeyPress (SkipKey, []);
TestIsBlock ('After Skip Key', X1, Y1, X2, Y2, ExpText);
SynEdit.Options2 := SynEdit.Options2 - [eoCaretSkipsSelection];
DoKeyPress (SkipBackKey, []);
TestOnlyPersitBlock('After SkipBack Key (Skip=Off)');
// Switching eoNoSelection=On while selected, clears the block
PopPushBaseName ('change eoNoSelection');
TestKeySelect ();
SynEdit.Options := SynEdit.Options + [eoNoSelection];
TestIsNoBlock ('After setting eoNoSelection');
// No selection, if eoNoSelection=On
PopPushBaseName ('eoNoSelection');
SetCaret(StartX, StartY);
TestIsNoBlock('Sanity, after set caret');
DoKeyPress(Key, Shift);
TestIsNoBlock('After Select Key');
SynEdit.Options := SynEdit.Options - [eoNoSelection];
PopBaseName;
if Persist then
PopBaseName;
PopBaseName;
// Repeat for persistent block
if not Persist then
TestKey(Name, StartX, StartY, Key, Shift, EndX, EndY, ExpText,
ExitKey, ExitShift, ExitX, ExitY, ExitSkippedX, ExitSkippedY,
True
);
end;
procedure TestKey(Name: String;
StartX, StartY: Integer; Key: Word; Shift: TShiftState;
EndX, EndY: Integer; ExpText: Array of String;
ExitKey: Word; ExitShift: TShiftState;
ExitX, ExitY, ExitSkippedX, ExitSkippedY: Integer
);
begin
TestKey(Name, StartX, StartY, Key, Shift, EndX, EndY, LinesToText(ExpText),
ExitKey, ExitShift, ExitX, ExitY, ExitSkippedX, ExitSkippedY
);
end;
begin
ReCreateEdit;
BaseTestName := 'SelectByKey';
(* tests include:
eoPersistentBlock
eoCaretSkipsSelection
eoNoSelection
eoScrollPastEol
*)
// CaretPos are Logical, to save params
SynEdit.TabWidth := 4;
SkipBlockOtherEndBack := False;
SetLines(['begin',
' Foo(bar);',
' // äüöäabc', // Utf8 2 bytes per char
#9#9+'test', // Tab 1 byte / several display cells
'end;'
]);
PushBaseName('Default:smNormal');
SynEdit.DefaultSelectionMode := smNormal;
// Name Start Select-Key Block-End UnSel-Key End-Caret/Skipped
TestKey('S-VK_RIGHT, Exit=VK_RIGHT', 3,2, VK_RIGHT,[ssShift], 4,2, 'F', VK_RIGHT,[], 5,2, 4,2);
TestKey('S-VK_RIGHT, Exit=VK_LEFT', 3,2, VK_RIGHT,[ssShift], 4,2, 'F', VK_LEFT,[], 3,2, 2,2); // VK_LEFT goes back to block begin;
TestKey('S-VK_RIGHT, Exit=VK_UP', 3,2, VK_RIGHT,[ssShift], 4,2, 'F', VK_UP,[], 4,1, 3,1);
TestKey('S-VK_RIGHT, Exit=VK_UP(no move)', 3,1, VK_RIGHT,[ssShift], 4,1, 'g', VK_UP,[], 4,1, 3,1);
TestKey('S-VK_RIGHT, Exit=VK_RIGHT utf8', 8,3, VK_RIGHT,[ssShift], 10,3, 'ü', VK_RIGHT,[], 12,3,10,2);
TestKey('S-VK_RIGHT, Exit=VK_LEFT utf8', 8,3, VK_RIGHT,[ssShift], 10,3, 'ü', VK_LEFT,[], 8,3, 6,3);
// Todo: tab (currently shift-left, from behind a tab, will create blockbegin <> caret
TestKey('S-VK_LEFT, Exit=VK_LEFT', 3,2, VK_LEFT,[ssShift], 2,2, ' ', VK_LEFT,[], 1,2, 2,2);
TestKey('S-VK_LEFT, Exit=VK_RIGHT', 3,2, VK_LEFT,[ssShift], 2,2, ' ', VK_RIGHT,[], 3,2, 4,2);
SynEdit.Options := SynEdit.Options + [eoScrollPastEol];
TestKey('S-VK_LEFT, Exit=VK_LEFT(no move)', 2,2, VK_LEFT,[ssShift], 1,2, ' ', VK_LEFT,[], 1,2, 1,2);
SynEdit.Options := SynEdit.Options - [eoScrollPastEol];
TestKey('S-VK_UP, Exit=VK_DOWN', 3,2, VK_UP,[ssShift], 3,1, ['gin',' '], VK_DOWN,[], 3,2, 3,3);
TestKey('S-VK_END, Exit=VK_END', 7,2, VK_END,[ssShift], 12,2, 'bar);', VK_END,[], 12,2, 12,2);
TestKey('S-VK_HOME, Exit=VK_HOME', 3,1, VK_HOME,[ssShift], 1,1, 'be', VK_HOME,[], 1,1, 1,1);
TestKey('SC-VK_RIGHT, Exit=C-VK_LEFT (word)', 3,2, VK_RIGHT,[ssShift,ssCtrl], 7,2, 'Foo(', VK_LEFT,[ssCtrl], 3,2, 6,1);
TestKey('SC-VK_RIGHT, Exit=C-VK_LEFT (half word)', 4,2, VK_RIGHT,[ssShift,ssCtrl], 7,2, 'oo(', VK_LEFT,[ssCtrl], 3,2, 3,2);
SynEdit.Options := SynEdit.Options + [eoScrollPastEol];
TestKey('S-VK_LEFT, Exit=VK_LEFT', 8,1, VK_LEFT,[ssShift], 7,1, '', VK_LEFT,[], 6,1, 7,1);
TestKey('S-VK_LEFT, Exit=VK_RIGHT', 8,1, VK_LEFT,[ssShift], 7,1, '', VK_RIGHT,[], 8,1, 9,1);
// Column selection (force horiz move, by going to end of shorter line)
SynEdit.Options := SynEdit.Options - [eoScrollPastEol, eoKeepCaretX];
TestKey('SA-VK_UP (Col), Exit=VK_DOWN (PastEOL=Off KeepX=Off)', 10,2, VK_UP,[ssShift, ssAlt], 6,1, [' ','(bar'], VK_DOWN,[], 6,2, 14,3); // caret-after-skip + 4 utf8 2 byte
SkipBlockOtherEndBack := True; // KeepCaretX wouldn't work
SynEdit.Options := SynEdit.Options - [eoScrollPastEol] + [eoKeepCaretX];
TestKey('SA-VK_UP (Col), Exit=VK_DOWN (PastEOL=Off KeepX=On)', 10,2, VK_UP,[ssShift, ssAlt], 6,1, [' ','(bar'], VK_DOWN,[], 10,2, 14,3); // caret-after-skip + 4 utf8 2 byte
SkipBlockOtherEndBack := False;
PopPushBaseName('Default:smColumn');
SynEdit.DefaultSelectionMode := smColumn;
// Name Start Select-Key Block-End UnSel-Key End-Caret/Skipped
TestKey('S-VK_RIGHT, Exit=VK_RIGHT', 3,2, VK_RIGHT,[ssShift], 4,2, 'F', VK_RIGHT,[], 5,2, 4,2);
TestKey('S-VK_RIGHT, Exit=VK_LEFT', 3,2, VK_RIGHT,[ssShift], 4,2, 'F', VK_LEFT,[], 3,2, 2,2); // VK_LEFT goes back to block begin;
SynEdit.Options := SynEdit.Options + [eoScrollPastEol];
TestKey('S-VK_LEFT, Exit=VK_LEFT(no move)', 2,2, VK_LEFT,[ssShift], 1,2, ' ', VK_LEFT,[], 1,2, 1,2);
SynEdit.Options := SynEdit.Options - [eoScrollPastEol];
TestKey('S-VK_END, Exit=VK_END', 7,2, VK_END,[ssShift], 12,2, 'bar);', VK_END,[], 12,2, 12,2);
TestKey('S-VK_HOME, Exit=VK_HOME', 3,1, VK_HOME,[ssShift], 1,1, 'be', VK_HOME,[], 1,1, 1,1);
TestKey('SC-VK_RIGHT, Exit=C-VK_LEFT (word)', 3,2, VK_RIGHT,[ssShift,ssCtrl], 7,2, 'Foo(', VK_LEFT,[ssCtrl], 3,2, 6,1);
TestKey('SC-VK_RIGHT, Exit=C-VK_LEFT (half word)', 4,2, VK_RIGHT,[ssShift,ssCtrl], 7,2, 'oo(', VK_LEFT,[ssCtrl], 3,2, 3,2);
SynEdit.Options := SynEdit.Options + [eoScrollPastEol];
TestKey('S-VK_LEFT, Exit=VK_LEFT', 8,1, VK_LEFT,[ssShift], 7,1, ' ', VK_LEFT,[], 6,1, 7,1);
TestKey('S-VK_LEFT, Exit=VK_RIGHT', 8,1, VK_LEFT,[ssShift], 7,1, ' ', VK_RIGHT,[], 8,1, 9,1);
// Column selection (force horiz move, by going to end of shorter line)
SynEdit.Options := SynEdit.Options - [eoScrollPastEol, eoKeepCaretX];
TestKey('SA-VK_UP (Col), Exit=VK_DOWN (PastEOL=Off KeepX=Off)', 10,2, VK_UP,[ssShift, ssAlt], 6,1, [' ','(bar'], VK_DOWN,[], 6,2, 14,3); // caret-after-skip + 4 utf8 2 byte
SkipBlockOtherEndBack := True; // KeepCaretX wouldn't work
SynEdit.Options := SynEdit.Options - [eoScrollPastEol] + [eoKeepCaretX];
TestKey('SA-VK_UP (Col), Exit=VK_DOWN (PastEOL=Off KeepX=On)', 10,2, VK_UP,[ssShift, ssAlt], 6,1, [' ','(bar'], VK_DOWN,[], 10,2, 14,3); // caret-after-skip + 4 utf8 2 byte
SkipBlockOtherEndBack := False;
PopPushBaseName('Default:smLine');
SynEdit.DefaultSelectionMode := smLine;
// Name Start Select-Key Block-End UnSel-Key End-Caret/Skipped
TestKey('S-VK_RIGHT, Exit=VK_RIGHT', 3,2, VK_RIGHT,[ssShift], 4,2, [' Foo(bar);', ''], VK_RIGHT,[], 5,2, 4,2);
TestKey('S-VK_RIGHT, Exit=VK_LEFT', 3,2, VK_RIGHT,[ssShift], 4,2, [' Foo(bar);', ''], VK_LEFT,[], 3,2, 2,2); // VK_LEFT goes back to block begin;
TestKey('S-VK_RIGHT, Exit=VK_UP', 3,2, VK_RIGHT,[ssShift], 4,2, [' Foo(bar);', ''], VK_UP,[], 4,1, 3,1);
TestKey('S-VK_RIGHT, Exit=VK_UP(no move)', 3,1, VK_RIGHT,[ssShift], 4,1, ['begin', ''], VK_UP,[], 4,1, 3,1);
SynEdit.Options := SynEdit.Options + [eoScrollPastEol];
TestKey('S-VK_LEFT, Exit=VK_LEFT(no move)', 2,2, VK_LEFT,[ssShift], 1,2, [' Foo(bar);', ''], VK_LEFT,[], 1,2, 1,2);
SynEdit.Options := SynEdit.Options - [eoScrollPastEol];
TestKey('S-VK_UP, Exit=VK_DOWN', 3,2, VK_UP,[ssShift], 3,1, ['begin',' Foo(bar);', ''], VK_DOWN,[], 3,2, 3,3);
TestKey('S-VK_END, Exit=VK_END', 7,2, VK_END,[ssShift], 12,2, [' Foo(bar);', ''], VK_END,[], 12,2, 12,2);
TestKey('S-VK_HOME, Exit=VK_HOME', 3,1, VK_HOME,[ssShift], 1,1, ['begin', ''], VK_HOME,[], 1,1, 1,1);
TestKey('SC-VK_RIGHT, Exit=C-VK_LEFT (word)', 3,2, VK_RIGHT,[ssShift,ssCtrl], 7,2, [' Foo(bar);', ''], VK_LEFT,[ssCtrl], 3,2, 6,1);
TestKey('SC-VK_RIGHT, Exit=C-VK_LEFT (half word)', 4,2, VK_RIGHT,[ssShift,ssCtrl], 7,2, [' Foo(bar);', ''], VK_LEFT,[ssCtrl], 3,2, 3,2);
SynEdit.Options := SynEdit.Options + [eoScrollPastEol];
TestKey('S-VK_LEFT, Exit=VK_LEFT', 8,1, VK_LEFT,[ssShift], 7,1, ['begin', ''], VK_LEFT,[], 6,1, 7,1);
TestKey('S-VK_LEFT, Exit=VK_RIGHT', 8,1, VK_LEFT,[ssShift], 7,1, ['begin', ''], VK_RIGHT,[], 8,1, 9,1);
// Column selection (force horiz move, by going to end of shorter line)
SynEdit.Options := SynEdit.Options - [eoScrollPastEol, eoKeepCaretX];
TestKey('SA-VK_UP (Col), Exit=VK_DOWN (PastEOL=Off KeepX=Off)', 10,2, VK_UP,[ssShift, ssAlt], 6,1, [' ','(bar'], VK_DOWN,[], 6,2, 14,3); // caret-after-skip + 4 utf8 2 byte
SkipBlockOtherEndBack := True; // KeepCaretX wouldn't work
SynEdit.Options := SynEdit.Options - [eoScrollPastEol] + [eoKeepCaretX];
TestKey('SA-VK_UP (Col), Exit=VK_DOWN (PastEOL=Off KeepX=On)', 10,2, VK_UP,[ssShift, ssAlt], 6,1, [' ','(bar'], VK_DOWN,[], 10,2, 14,3); // caret-after-skip + 4 utf8 2 byte
SkipBlockOtherEndBack := False;
PopBaseName; // Default:smLine
// ColumnSelection, Continue after zero width
SynEdit.DefaultSelectionMode := smNormal;
PushBaseName('BlockSel through zero width');
SynEdit.Options2 := SynEdit.Options2 - [eoPersistentBlock];
SetCaret(3, 1);
DoKeyPress(VK_RIGHT, [ssShift, ssAlt]);
TestIsBlock('after VK_RIGHT', 3, 1, 4, 1, 'g');
DoKeyPress(VK_DOWN, [ssShift, ssAlt]);
TestIsBlock('after VK_DOWN', 3, 1, 4, 2, ['g', 'F']);
DoKeyPress(VK_LEFT, [ssShift, ssAlt]);
TestIsNoBlock('after VK_LEFT (empty)');
DoKeyPress(VK_LEFT, [ssShift, ssAlt]);
TestIsBlock('after VK_LEFT (continue)', 3, 1, 2, 2, ['e', ' ']);
PushBaseName('BlockSel through zero width (persistent)');
SynEdit.Options2 := SynEdit.Options2 + [eoPersistentBlock];
SetCaret(3, 1);
DoKeyPress(VK_RIGHT, [ssShift, ssAlt]);
TestIsBlock('after VK_RIGHT', 3, 1, 4, 1, 'g');
DoKeyPress(VK_DOWN, [ssShift, ssAlt]);
TestIsBlock('after VK_DOWN', 3, 1, 4, 2, ['g', 'F']);
DoKeyPress(VK_LEFT, [ssShift, ssAlt]);
TestIsNoBlock('after VK_LEFT (empty)');
DoKeyPress(VK_LEFT, [ssShift, ssAlt]);
TestIsBlock('after VK_LEFT (continue)', 3, 1, 2, 2, ['e', ' ']);
end;
initialization
RegisterTest(TTestSynSelection);
end.