unit TestBlockIndent; {$mode objfpc}{$H+} interface uses SysUtils, testregistry, TestBase, math, SynEdit, SynEditKeyCmds; type { TTestBlockIndent } TTestBlockIndent = class(TTestBase) protected function TestTextSpace: TStringArray; function TestTextTabs: TStringArray; function ReplaceIndent(AText: TStringArray; AFirstLine: Integer; ANewIndents: Array of String): TStringArray; function AddIndent(AText: TStringArray; AFirstLine, ALastLine, ASpaceCount: Integer): TStringArray; function DelIndent(AText: TStringArray; AFirstLine, ALastLine, ASpaceCount: Integer): TStringArray; procedure TestSelAndText(Name: String; LogX1, LogY1, LogX2, LogY2: Integer; ExpLines: Array of String; SelIsForward: Boolean = True); //procedure DoTest(X1,Y1, X2,Y2: Boolean; CountIndent: Integer; // ExpX1, ExpY1, ExpX2, ExpY2: Integer; // ExpText: A published procedure TestIndent; procedure TestUnIndent; procedure TestIndentWithTab; procedure TestUnIndentWithTab; end; implementation { TTestBlockIndent } function TTestBlockIndent.TestTextSpace: TStringArray; begin SetLength(Result, 9); Result[0] := 'abc'; Result[1] := ' def'; Result[2] := ' 123'; Result[3] := ''; Result[4] := ' QWE'; Result[5] := ' mno'; Result[6] := ' ZX'; Result[7] := ' 321'; Result[8] := ''; end; function TTestBlockIndent.TestTextTabs: TStringArray; begin SetLength(Result, 13); Result[0] := 'abc'; Result[1] := #9'def'; Result[2] := #9' 123'; Result[3] := ' '#9'mno'; Result[4] := #9#9'QWE'; Result[5] := #9#9' mno...'; Result[6] := #9#9' ABCDEF'; Result[7] := #9#9' 321'; Result[8] := #9' '#9'QWE'; Result[9] := #9' '#9' mno...'; Result[10]:= #9' '#9' ABCDEF'; Result[11]:= #9' '#9' 321'; Result[12] := ''; end; function GetLeadWSLen(s: String): integer; var Run : PChar; begin Run := PChar(s); while (Run[0] in [' ', #9]) do Inc(Run); Result := Run - PChar(s); end; function TTestBlockIndent.ReplaceIndent(AText: TStringArray; AFirstLine: Integer; ANewIndents: Array of String): TStringArray; var i: Integer; begin SetLength(Result, length(AText)); for i := 0 to Length(AText) - 1 do Result[i] := AText[i]; for i := 0 to Length(ANewIndents) - 1 do begin Result[AFirstLine + i] := ANewIndents[i] + copy(AText[AFirstLine + i], GetLeadWSLen(AText[AFirstLine + i]) + 1, length(AText[AFirstLine + i])); end; end; function TTestBlockIndent.AddIndent(AText: TStringArray; AFirstLine, ALastLine, ASpaceCount: Integer): TStringArray; var i: Integer; begin SetLength(Result, length(AText)); for i := 0 to Length(AText) - 1 do Result[i] := AText[i]; for i := AFirstLine to ALastLine do begin Result[i] := copy(AText[i], 1, GetLeadWSLen(AText[i])) + StringOfChar(' ', ASpaceCount) + copy(AText[i], GetLeadWSLen(AText[i]) + 1, length(AText[i])); end; end; function TTestBlockIndent.DelIndent(AText: TStringArray; AFirstLine, ALastLine, ASpaceCount: Integer): TStringArray; var i: Integer; begin SetLength(Result, length(AText)); for i := 0 to Length(AText) - 1 do Result[i] := AText[i]; for i := AFirstLine to ALastLine do begin Result[i] := copy(AText[i], 1, Max( GetLeadWSLen(AText[i]) - ASpaceCount, 0)) + copy(AText[i], GetLeadWSLen(AText[i]) + 1, length(AText[i])); end; end; procedure TTestBlockIndent.TestSelAndText(Name: String; LogX1, LogY1, LogX2, LogY2: Integer; ExpLines: array of String; SelIsForward: Boolean); begin if SelIsForward then TestIsCaretAndSel(Name, LogX1, LogY1, LogX2, LogY2) else TestIsCaretAndSelBackward(Name, LogX1, LogY1, LogX2, LogY2); TestIsFullText(Name, ExpLines); end; procedure TTestBlockIndent.TestIndent; var i, j: Integer; begin ReCreateEdit; SetLines(TestTextSpace); PushBaseName(''); {%region simple indent} SynEdit.Options := SynEdit.Options - [eoGroupUndo, eoTrimTrailingSpaces]; for i := 1 to 5 do begin PopPushBaseName('simple Indent BlockIndent='+ IntToStr(i)); SetLines(TestTextSpace); SynEdit.BlockIndent := i; SynEdit.TabWidth := i+8; // make sure it does not interfere SetCaretAndSel(3,1, 9,8); // ab[c ... 3]21 SynEdit.CommandProcessor(ecBlockIndent, '', nil); TestSelAndText('indented', 3+i,1, 9+i,8, AddIndent(TestTextSpace, 0, 7, i)); SynEdit.Undo; TestSelAndText('indent undone', 3,1, 9,8, TestTextSpace); SynEdit.Redo; TestSelAndText('indent redone', 3+i,1, 9+i,8, AddIndent(TestTextSpace, 0, 7, i)); SynEdit.Undo; TestSelAndText('indent undone 2nd', 3,1, 9,8, TestTextSpace); SynEdit.Redo; TestSelAndText('indent redone 2nd', 3+i,1, 9+i,8, AddIndent(TestTextSpace, 0, 7, i)); SetLines(TestTextSpace); SetCaretAndSel(3,2, 2,3); // [def ... ]123 SynEdit.CommandProcessor(ecBlockIndent, '', nil); TestSelAndText('indented 2 line only', 3+i,2, 2+i,3, AddIndent(TestTextSpace, 1, 2, i)); SetLines(TestTextSpace); SetCaretAndSelBackward(3,2, 2,3); // [def ... ]123 SynEdit.CommandProcessor(ecBlockIndent, '', nil); TestSelAndText('indented 2 line only (backward)', 3+i,2, 2+i,3, AddIndent(TestTextSpace, 1, 2, i), False); SetLines(TestTextSpace); SetCaretAndSel(3,2, 4,2); // [d]ef SynEdit.CommandProcessor(ecBlockIndent, '', nil); TestSelAndText('indented 1 line only', 3+i,2, 4+i,2, AddIndent(TestTextSpace, 1, 1, i)); end; {%endregion} {%region double indent, no GroupUndo} SynEdit.Options := SynEdit.Options - [eoGroupUndo, eoTrimTrailingSpaces]; for i := 1 to 5 do begin for j := 1 to 5 do begin PopPushBaseName('double Indent (no GroupUndo) BlockIndent='+ IntToStr(i)+', '+ IntToStr(j)); SetLines(TestTextSpace); SynEdit.BlockIndent := i; SynEdit.TabWidth := i+8; // make sure it does not interfere SetCaretAndSel(3,1, 9,8); // ab[c ... 3]21 SynEdit.CommandProcessor(ecBlockIndent, '', nil); TestSelAndText('indented', 3+i,1, 9+i,8, AddIndent(TestTextSpace, 0, 7, i)); SynEdit.BlockIndent := j; SynEdit.TabWidth := j+8; // make sure it does not interfere SynEdit.CommandProcessor(ecBlockIndent, '', nil); TestSelAndText('2nd indented', 3+i+j,1, 9+i+j,8, AddIndent(TestTextSpace, 0, 7, i+j)); SynEdit.Undo; TestSelAndText('one indent undone', 3+i,1, 9+i,8, AddIndent(TestTextSpace, 0, 7, i)); SynEdit.Redo; TestSelAndText('one indent redone', 3+i+j,1, 9+i+j,8, AddIndent(TestTextSpace, 0, 7, i+j)); SynEdit.Undo; TestSelAndText('one indent undone (2nd)', 3+i,1, 9+i,8, AddIndent(TestTextSpace, 0, 7, i)); SynEdit.Undo; TestSelAndText('two indent undone (2nd)', 3,1, 9,8, TestTextSpace); SynEdit.Redo; TestSelAndText('one indent redone(2nd)', 3+i,1, 9+i,8, AddIndent(TestTextSpace, 0, 7, i)); SynEdit.Redo; TestSelAndText('two indent redone(2nd)', 3+i+j,1, 9+i+j,8, AddIndent(TestTextSpace, 0, 7, i+j)); SynEdit.Undo; TestSelAndText('one indent undone (3rd)', 3+i,1, 9+i,8, AddIndent(TestTextSpace, 0, 7, i)); end; end; {%endregion} {%region double indent, with GroupUndo} SynEdit.Options := SynEdit.Options + [eoGroupUndo] - [eoTrimTrailingSpaces]; for i := 1 to 5 do begin for j := 1 to 5 do begin PopPushBaseName('double Indent (no GroupUndo) BlockIndent='+ IntToStr(i)+', '+ IntToStr(j)); SetLines(TestTextSpace); SynEdit.BlockIndent := i; SynEdit.TabWidth := i+8; // make sure it does not interfere SetCaretAndSel(3,1, 9,8); // ab[c ... 3]21 SynEdit.CommandProcessor(ecBlockIndent, '', nil); TestSelAndText('indented', 3+i,1, 9+i,8, AddIndent(TestTextSpace, 0, 7, i)); SynEdit.BlockIndent := j; SynEdit.TabWidth := j+8; // make sure it does not interfere SynEdit.CommandProcessor(ecBlockIndent, '', nil); TestSelAndText('2nd indented', 3+i+j,1, 9+i+j,8, AddIndent(TestTextSpace, 0, 7, i+j)); SynEdit.Undo; TestSelAndText('indent undone', 3,1, 9,8, TestTextSpace); SynEdit.Redo; TestSelAndText('indent redone', 3+i+j,1, 9+i+j,8, AddIndent(TestTextSpace, 0, 7, i+j)); SynEdit.Undo; TestSelAndText('indent undone (2nd)', 3,1, 9,8, TestTextSpace); SynEdit.Redo; TestSelAndText('indent redone(2nd)', 3+i+j,1, 9+i+j,8, AddIndent(TestTextSpace, 0, 7, i+j)); end; end; {%endregion} end; procedure TTestBlockIndent.TestUnIndent; var i, j: Integer; begin ReCreateEdit; SetLines(TestTextSpace); PushBaseName(''); {%region simple unindent} SynEdit.Options := SynEdit.Options - [eoGroupUndo, eoTrimTrailingSpaces]; for i := 1 to 5 do begin PopPushBaseName('simple Unindent BlockIndent='+ IntToStr(i)); SetLines(TestTextSpace); SynEdit.BlockIndent := i; SynEdit.TabWidth := i+8; // make sure it does not interfere SetCaretAndSel(3,1, 9,8); // ab[c ... 32]1 SynEdit.CommandProcessor(ecBlockUnindent, '', nil); // first line can not be unindented, caret/blockbegin is unchanged TestSelAndText('Unindented', 3,1, Max(9-i,1),8, DelIndent(TestTextSpace, 0, 7, i)); SynEdit.Undo; TestSelAndText('unindent undone', 3,1, 9,8, TestTextSpace); SynEdit.Redo; TestSelAndText('Unindent redone', 3,1, Max(9-i,1),8, DelIndent(TestTextSpace, 0, 7, i)); SynEdit.Undo; TestSelAndText('unindent undone(2nd)', 3,1, 9,8, TestTextSpace); SynEdit.Redo; TestSelAndText('Unindent redone(2nd)', 3,1, Max(9-i,1),8, DelIndent(TestTextSpace, 0, 7, i)); SetLines(TestTextSpace); SetCaretAndSel(3,2, 2,3); // [def ... ]123 SynEdit.CommandProcessor(ecBlockUnindent, '', nil); // line 3 can only be unindented by max 1 TestSelAndText('Unindented 2 line only', Max(3-i,1),2, 2-Min(i,1),3, DelIndent(TestTextSpace, 1, 2, i)); SetLines(TestTextSpace); SetCaretAndSelBackward(3,2, 2,3); // [def ... ]123 SynEdit.CommandProcessor(ecBlockUnindent, '', nil); TestSelAndText('Unindented 2 line only (backward)', Max(3-i,1),2, 2-Min(i,1),3, DelIndent(TestTextSpace, 1, 2, i), False); SetLines(TestTextSpace); SetCaretAndSel(3,2, 4,2); // [d]ef SynEdit.CommandProcessor(ecBlockUnindent, '', nil); TestSelAndText('Unindented 1 line only', 3-Min(i,2),2, 4-Min(i,2),2, DelIndent(TestTextSpace, 1, 1, i)); end; {%endregion} {%region double indent, no GroupUndo} SynEdit.Options := SynEdit.Options - [eoGroupUndo, eoTrimTrailingSpaces]; for i := 1 to 5 do begin for j := 1 to 5 do begin PopPushBaseName('double Indent (no GroupUndo) BlockIndent='+ IntToStr(i)+', '+ IntToStr(j)); SetLines(TestTextSpace); SynEdit.BlockIndent := i; SynEdit.TabWidth := i+8; // make sure it does not interfere SetCaretAndSel(3,1, 9,8); // ab[c ... 32]1 SynEdit.CommandProcessor(ecBlockUnindent, '', nil); TestSelAndText('indented', 3,1, 9-Min(i,6),8, DelIndent(TestTextSpace, 0, 7, i)); SynEdit.BlockIndent := j; SynEdit.TabWidth := j+8; // make sure it does not interfere SynEdit.CommandProcessor(ecBlockUnindent, '', nil); TestSelAndText('2nd indented', 3,1, 9-Min(i+j,6),8, DelIndent(TestTextSpace, 0, 7, i+j)); SynEdit.Undo; TestSelAndText('one indent undone', 3,1, 9-Min(i,6),8, DelIndent(TestTextSpace, 0, 7, i)); SynEdit.Redo; TestSelAndText('one indent redone', 3,1, 9-Min(i+j,6),8, DelIndent(TestTextSpace, 0, 7, i+j)); SynEdit.Undo; TestSelAndText('one indent undone (2nd)', 3,1, 9-Min(i,6),8, DelIndent(TestTextSpace, 0, 7, i)); SynEdit.Undo; TestSelAndText('two indent undone (2nd)', 3,1, 9,8, TestTextSpace); SynEdit.Redo; TestSelAndText('one indent redone(2nd)', 3,1, 9-Min(i,6),8, DelIndent(TestTextSpace, 0, 7, i)); SynEdit.Redo; TestSelAndText('two indent redone(2nd)', 3,1, 9-Min(i+j,6),8, DelIndent(TestTextSpace, 0, 7, i+j)); SynEdit.Undo; TestSelAndText('one indent undone (3rd)', 3,1, 9-Min(i,6),8, DelIndent(TestTextSpace, 0, 7, i)); end; end; {%endregion} end; procedure TTestBlockIndent.TestIndentWithTab; begin ReCreateEdit; {%region Unindent BlockIndent=2 Tab=4} PushBaseName('Unindent BlockIndent=2 Tab=4'); SynEdit.Options := SynEdit.Options - [eoGroupUndo, eoTrimTrailingSpaces]; SetLines(TestTextTabs); SynEdit.BlockIndent := 2; SynEdit.TabWidth := 4; SetCaretAndSel(3,1, 10,12); // ab[c ... 3]21 TestIsCaretPhys('self-test',13,12); SynEdit.CommandProcessor(ecBlockIndent, '', nil); TestSelAndText('Unindented', 5,1, 12,12, ReplaceIndent(TestTextTabs, 0, [ ' ', #9' ', // 'abc' // #9'def' #9' ', ' '#9' ', // #9' 123' // ' '#9'mno' #9#9' ', #9#9' ', // #9#9'QWE' // #9#9' mno' #9#9' ', #9#9' ', // #9#9' ABCDEF' // #9#9' 321' #9' '#9' ', #9' '#9' ', // #9' '#9'QWE' // #9' '#9' mno' #9' '#9' ', #9' '#9' ' // #9' '#9' ABCDE' // #9' '#9' 321' ] )); TestIsCaretPhys('self-test',15,12); SynEdit.Undo; TestSelAndText('unindent undone', 3,1, 10,12, TestTextTabs); SynEdit.Redo; TestSelAndText('Unindent redone', 5,1, 12,12, ReplaceIndent(TestTextTabs, 0, [ ' ', #9' ', // 'abc' // #9'def' #9' ', ' '#9' ', // #9' 123' // ' '#9'mno' #9#9' ', #9#9' ', // #9#9'QWE' // #9#9' mno' #9#9' ', #9#9' ', // #9#9' ABCDEF' // #9#9' 321' #9' '#9' ', #9' '#9' ', // #9' '#9'QWE' // #9' '#9' mno' #9' '#9' ', #9' '#9' ' // #9' '#9' ABCDE' // #9' '#9' 321' ] )); SynEdit.Undo; TestSelAndText('unindent undone(2nd)', 3,1, 10,12, TestTextTabs); SynEdit.Redo; TestSelAndText('Unindent redone(2nd', 5,1, 12,12, ReplaceIndent(TestTextTabs, 0, [ ' ', #9' ', // 'abc' // #9'def' #9' ', ' '#9' ', // #9' 123' // ' '#9'mno' #9#9' ', #9#9' ', // #9#9'QWE' // #9#9' mno' #9#9' ', #9#9' ', // #9#9' ABCDEF' // #9#9' 321' #9' '#9' ', #9' '#9' ', // #9' '#9'QWE' // #9' '#9' mno' #9' '#9' ', #9' '#9' ' // #9' '#9' ABCDE' // #9' '#9' 321' ] )); {%endregion} end; procedure TTestBlockIndent.TestUnIndentWithTab; begin ReCreateEdit; {%region Unindent BlockIndent=2 Tab=4} PushBaseName('Unindent BlockIndent=2 Tab=4'); SynEdit.Options := SynEdit.Options - [eoGroupUndo, eoTrimTrailingSpaces]; SetLines(TestTextTabs); SynEdit.BlockIndent := 2; SynEdit.TabWidth := 4; SetCaretAndSel(3,1, 10,12); // ab[c ... 3]21 TestIsCaretPhys('self-test',13,12); SynEdit.CommandProcessor(ecBlockUnindent, '', nil); // first line can not be unindented, caret/blockbegin is unchanged TestSelAndText('Unindented', 3,1, 8,12, ReplaceIndent(TestTextTabs, 0, [ '', ' ', // 'abc' // #9'def' ' ', ' ', // #9' 123' // ' '#9'mno' #9' ', #9' ', // #9#9'QWE' // #9#9' mno' #9#9, #9#9' ', // #9#9' ABCDEF' // #9#9' 321' #9' ', #9' ', // #9' '#9'QWE' // #9' '#9' mno' #9' '#9, #9' '#9' ' // #9' '#9' ABCDE' // #9' '#9' 321' ] )); TestIsCaretPhys('self-test',11,12); SynEdit.Undo; TestSelAndText('unindent undone', 3,1, 10,12, TestTextTabs); SynEdit.Redo; TestSelAndText('Unindent redone', 3,1, 8,12, ReplaceIndent(TestTextTabs, 0, [ '', ' ', // 'abc' // #9'def' ' ', ' ', // #9' 123' // ' '#9'mno' #9' ', #9' ', // #9#9'QWE' // #9#9' mno' #9#9, #9#9' ', // #9#9' ABCDEF' // #9#9' 321' #9' ', #9' ', // #9' '#9'QWE' // #9' '#9' mno' #9' '#9, #9' '#9' ' // #9' '#9' ABCDE' // #9' '#9' 321' ] )); SynEdit.Undo; TestSelAndText('unindent undone(2nd)', 3,1, 10,12, TestTextTabs); SynEdit.Redo; TestSelAndText('Unindent redone(2nd', 3,1, 8,12, ReplaceIndent(TestTextTabs, 0, [ '', ' ', // 'abc' // #9'def' ' ', ' ', // #9' 123' // ' '#9'mno' #9' ', #9' ', // #9#9'QWE' // #9#9' mno' #9#9, #9#9' ', // #9#9' ABCDEF' // #9#9' 321' #9' ', #9' ', // #9' '#9'QWE' // #9' '#9' mno' #9' '#9, #9' '#9' ' // #9' '#9' ABCDE' // #9' '#9' 321' ] )); // unindent a 2nd time SynEdit.CommandProcessor(ecBlockUnindent, '', nil); // first line can not be unindented, caret/blockbegin is unchanged TestSelAndText('Unindented twice', 3,1, 6,12, ReplaceIndent(TestTextTabs, 0, [ '', '', // 'abc' // #9'def' ' ', '', // #9' 123' // ' '#9'mno' #9, #9' ', // #9#9'QWE' // #9#9' mno' #9' ', #9' ', // #9#9' ABCDEF' // #9#9' 321' #9, #9' ', // #9' '#9'QWE' // #9' '#9' mno' #9' ', #9' ' // #9' '#9' ABCDE' // #9' '#9' 321' ] )); TestIsCaretPhys('self-test',9,12); SynEdit.Undo; TestSelAndText('Unindent twice, undone once', 3,1, 8,12, ReplaceIndent(TestTextTabs, 0, [ '', ' ', // 'abc' // #9'def' ' ', ' ', // #9' 123' // ' '#9'mno' #9' ', #9' ', // #9#9'QWE' // #9#9' mno' #9#9, #9#9' ', // #9#9' ABCDEF' // #9#9' 321' #9' ', #9' ', // #9' '#9'QWE' // #9' '#9' mno' #9' '#9, #9' '#9' ' // #9' '#9' ABCDE' // #9' '#9' 321' ] )); SynEdit.Redo; TestSelAndText('Unindented twice, redone', 3,1, 6,12, ReplaceIndent(TestTextTabs, 0, [ '', '', // 'abc' // #9'def' ' ', '', // #9' 123' // ' '#9'mno' #9, #9' ', // #9#9'QWE' // #9#9' mno' #9' ', #9' ', // #9#9' ABCDEF' // #9#9' 321' #9, #9' ', // #9' '#9'QWE' // #9' '#9' mno' #9' ', #9' ' // #9' '#9' ABCDE' // #9' '#9' 321' ] )); SynEdit.Undo; TestSelAndText('Unindent twice, undone once(2nd)', 3,1, 8,12, ReplaceIndent(TestTextTabs, 0, [ '', ' ', // 'abc' // #9'def' ' ', ' ', // #9' 123' // ' '#9'mno' #9' ', #9' ', // #9#9'QWE' // #9#9' mno' #9#9, #9#9' ', // #9#9' ABCDEF' // #9#9' 321' #9' ', #9' ', // #9' '#9'QWE' // #9' '#9' mno' #9' '#9, #9' '#9' ' // #9' '#9' ABCDE' // #9' '#9' 321' ] )); SynEdit.Undo; TestSelAndText('unindent twice, undone twice(2nd)', 3,1, 10,12, TestTextTabs); SynEdit.Redo; TestSelAndText('Unindent twice, redone 1 of 2 (2nd)', 3,1, 8,12, ReplaceIndent(TestTextTabs, 0, [ '', ' ', // 'abc' // #9'def' ' ', ' ', // #9' 123' // ' '#9'mno' #9' ', #9' ', // #9#9'QWE' // #9#9' mno' #9#9, #9#9' ', // #9#9' ABCDEF' // #9#9' 321' #9' ', #9' ', // #9' '#9'QWE' // #9' '#9' mno' #9' '#9, #9' '#9' ' // #9' '#9' ABCDE' // #9' '#9' 321' ] )); SynEdit.Redo; TestSelAndText('Unindented twice, redone 2 of 2 (2nd)', 3,1, 6,12, ReplaceIndent(TestTextTabs, 0, [ '', '', // 'abc' // #9'def' ' ', '', // #9' 123' // ' '#9'mno' #9, #9' ', // #9#9'QWE' // #9#9' mno' #9' ', #9' ', // #9#9' ABCDEF' // #9#9' 321' #9, #9' ', // #9' '#9'QWE' // #9' '#9' mno' #9' ', #9' ' // #9' '#9' ABCDE' // #9' '#9' 321' ] )); {%endregion} {%region Unindent BlockIndent=3 Tab=4} PushBaseName('Unindent BlockIndent=3 Tab=4'); SynEdit.Options := SynEdit.Options - [eoGroupUndo, eoTrimTrailingSpaces]; SetLines(TestTextTabs); SynEdit.BlockIndent := 3; SynEdit.TabWidth := 4; SetCaretAndSel(3,1, 10,12); // ab[c ... 3]21 TestIsCaretPhys('self-test',13,12); SynEdit.CommandProcessor(ecBlockUnindent, '', nil); // first line can not be unindented, caret/blockbegin is unchanged TestSelAndText('Unindented', 3,1, 7,12, ReplaceIndent(TestTextTabs, 0, [ '', ' ', // 'abc' // #9'def' ' ', ' ', // #9' 123' // ' '#9'mno' #9' ', #9' ', // #9#9'QWE' // #9#9' mno' #9' ', #9#9, // #9#9' ABCDEF' // #9#9' 321' #9' ', #9' ', // #9' '#9'QWE' // #9' '#9' mno' #9' ', #9' '#9 // #9' '#9' ABCDE' // #9' '#9' 321' ] )); TestIsCaretPhys('self-test',10,12); SynEdit.Undo; TestSelAndText('unindent undone', 3,1, 10,12, TestTextTabs); SynEdit.Redo; TestSelAndText('Unindent redone', 3,1, 7,12, ReplaceIndent(TestTextTabs, 0, [ '', ' ', // 'abc' // #9'def' ' ', ' ', // #9' 123' // ' '#9'mno' #9' ', #9' ', // #9#9'QWE' // #9#9' mno' #9' ', #9#9, // #9#9' ABCDEF' // #9#9' 321' #9' ', #9' ', // #9' '#9'QWE' // #9' '#9' mno' #9' ', #9' '#9 // #9' '#9' ABCDE' // #9' '#9' 321' ] )); SynEdit.Undo; TestSelAndText('unindent undone(2nd)', 3,1, 10,12, TestTextTabs); SynEdit.Redo; TestSelAndText('Unindent redone(2nd', 3,1, 7,12, ReplaceIndent(TestTextTabs, 0, [ '', ' ', // 'abc' // #9'def' ' ', ' ', // #9' 123' // ' '#9'mno' #9' ', #9' ', // #9#9'QWE' // #9#9' mno' #9' ', #9#9, // #9#9' ABCDEF' // #9#9' 321' #9' ', #9' ', // #9' '#9'QWE' // #9' '#9' mno' #9' ', #9' '#9 // #9' '#9' ABCDE' // #9' '#9' 321' ] )); {%endregion} end; initialization RegisterTest(TTestBlockIndent); end.