1 unit TestBasicSynEdit;
2
3 (* TODO:
4 - TestEditEmpty:
5 Test with different sets of VirtualViews (with/without trimming (enabled/module present at all)
6 *)
7
8 {$mode objfpc}{$H+}
9
10 interface
11
12 uses
13 Classes, SysUtils, testregistry, LCLProc, LCLType, Forms, TestBase, SynEdit,
14 SynEditTextTrimmer, SynEditKeyCmds, LazSynEditText, SynEditPointClasses,
15 SynEditMiscClasses, SynEditTypes, SynEditMiscProcs;
16
17 type
18
19 { TTestBasicSynEdit }
20
21 TTestBasicSynEdit = class(TTestBase)
22 private
23 InsertFlag: Boolean;
24 TrimType: TSynEditStringTrimmingType;
25 TrimEnabled: Boolean;
26 private
27 AllowPastEOL: Boolean;
28 FDoInit: procedure of object;
TStringArraynull29 FTestLines: function: TStringArray of object;
30 Procedure DoInit1;
TestLines1null31 function TestLines1: TStringArray;
32 private
33 FTestCommand:TSynEditorCommand;
34 procedure TestCommand(Name:String; X, Y: Integer;
35 ExpX1, ExpY1: Integer; Repl: Array of const);
36 procedure TestCommand(Name:String; X, Y: Integer;
37 ExpX1, ExpY1: Integer; Repl: Array of const;
38 ExpX2, ExpY2: Integer; Repl2: Array of const);
39 protected
TestMaxLeftProcnull40 function TestMaxLeftProc: Integer;
41 procedure ReCreateEdit; reintroduce;
42 published
43 procedure TestEditEmpty;
44 procedure TestEditTabs;
45 procedure TestEditEcChar;
46 procedure TestPhysicalLogical; // TODO adjust to char tests
47 procedure TestLogicalAdjust;
48 procedure TestCaretObject;
49 procedure TestCaretAutoMove;
50 procedure TestCaretEcDeleteWord;
51 procedure TestCaretEcDeleteLastWord;
52 procedure TestCaretEcDeleteEOL;
53 procedure TestWordBreaker;
54 procedure TestSearchReplace;
55 end;
56
57 implementation
58
59 procedure TTestBasicSynEdit.DoInit1;
60 begin
61 InsertFlag := False;
62 TrimEnabled := False;;
63 ReCreateEdit;
64 if AllowPastEOL
65 then SynEdit.Options := SynEdit.Options + [eoScrollPastEol]
66 else SynEdit.Options := SynEdit.Options - [eoScrollPastEol];
67 SynEdit.TabWidth := 7;
68 SetLines(FTestLines());
69 end;
70
TestLines1null71 function TTestBasicSynEdit.TestLines1: TStringArray;
72 begin
73 SetLength(Result, 16);
74 // 1 6 11 14
75 Result[0] := 'Some text to test'; //1
76 // 1 5 9
77 Result[1] := 'Foo bar abc'; // 2
78 // 8 14 19 24
79 Result[2] := #9'Other line with tab'; // 3
80 // 1 8 11 15
81 Result[3] := 'tab'#9'in the middle'; // 4
82 // 1 9 12 16 23 28
83 Result[4] := 'tab'#9' in the middle with space'; // 5
84 // 1 9 13 16
85 Result[5] := 'umlaute äää in text'; // 6
86 Result[6] := 'normal line';
87 // 4 14 21 28 32
88 Result[7] := ' untrimmed spaces around line '; // 8
89 Result[8] := 'normal line';
90 // 8 15 22 26
91 Result[9] := #9'tab'#9'only'#9'line'#9; // 10
92 // 1 8
93 Result[10] := 'normal line';
94 Result[11] := ''; // 12 (empty)
95 Result[12] := 'normal line';
96 Result[13] := ' '; // space only empty line // 14
97 Result[14] := 'normal line';
98 Result[15] := '';
99 end;
100
101 procedure TTestBasicSynEdit.TestCommand(Name: String; X, Y: Integer; ExpX1,
102 ExpY1: Integer; Repl: array of const);
103 begin
104 FDoInit();
105 SetCaretPhys(X,Y);
106 SynEdit.CommandProcessor(FTestCommand, '', nil);
107 TestIsCaretPhys(Name + '(1st)', ExpX1, ExpY1);
108 TestIsFullText(Name + '(1st)', FTestLines(), Repl);
109 end;
110
111 procedure TTestBasicSynEdit.TestCommand(Name: String; X, Y: Integer; ExpX1,
112 ExpY1: Integer; Repl: array of const; ExpX2, ExpY2: Integer;
113 Repl2: array of const);
114 begin
115 TestCommand(Name, X, Y, ExpX1, ExpY1, Repl);
116 SynEdit.CommandProcessor(FTestCommand, '', nil);
117 TestIsCaretPhys(Name + '(2nd)', ExpX2, ExpY2);
118 TestIsFullText(Name + '(2nd)', FTestLines(), Repl2);
119 end;
120
TestMaxLeftProcnull121 function TTestBasicSynEdit.TestMaxLeftProc: Integer;
122 begin
123 Result := 6000;
124 end;
125
126 procedure TTestBasicSynEdit.ReCreateEdit;
127 begin
128 inherited ReCreateEdit;
129 SynEdit.InsertMode := InsertFlag;
130 SynEdit.TrimSpaceType := TrimType;
131 if TrimEnabled then
132 SynEdit.Options := SynEdit.Options + [eoTrimTrailingSpaces]
133 else
134 SynEdit.Options := SynEdit.Options - [eoTrimTrailingSpaces];
135
136 end;
137
138 procedure TTestBasicSynEdit.TestEditEmpty;
139 procedure CheckText(aName: String; ExpText: String; ExpLines: Integer);
140 var
141 s: String;
142 begin
143 AssertEquals(BaseTestName + aName+' Count', ExpLines, SynEdit.Lines.Count);
144 // TestIsText (without Views => just real text)
145 // TestIsFullText (with Views => eg trimmed spaces)
146 s:='';
147 if ExpLines > 0 then
148 s := LineEnding;
149 TestIsText(aName+' Text', ExpText+s);
150 end;
151 procedure DoChecks;
152 begin
153 ReCreateEdit;
154 CheckText('Empty', '', 0);
155 SynEdit.CommandProcessor(ecChar, 'x', nil);
156 CheckText('After Insert "x"', 'x', 1);
157
158 ReCreateEdit;
159 SynEdit.CommandProcessor(ecChar, ' ', nil);
160 if TrimEnabled then begin
161 CheckText('After Insert <space>', '', 1);
162 if TrimType = settIgnoreAll then begin
163 TestIsFullText('After Insert <space> (FullText)', ''+LineEnding);
164 TestIsCaret('After Insert <space>', 2,1);
165 end else begin
166 TestIsFullText('After Insert <space> (FullText)', ' '+LineEnding);
167 TestIsCaret('After Insert <space>', 2,1);
168 end;
169 end else begin
170 CheckText('After Insert <space>', ' ', 1);
171 TestIsFullText('After Insert <space> (FullText)', ' '+LineEnding);
172 TestIsCaret('After Insert <space>', 2,1);
173 end;
174
175 ReCreateEdit;
176 CheckText('Empty', '', 0);
177 SynEdit.CommandProcessor(ecDeleteChar, '', nil);
178 CheckText('After ecDeleteChar', '', 0);
179
180 ReCreateEdit;
181 SynEdit.CommandProcessor(ecDeleteLastChar, '', nil);
182 CheckText('After ecDeleteLastChar', '', 0);
183
184 ReCreateEdit;
185 SynEdit.CommandProcessor(ecDeleteWord, '', nil);
186 CheckText('After ecDeleteWord', '', 0);
187
188 ReCreateEdit;
189 SynEdit.CommandProcessor(ecDeleteLastWord, '', nil);
190 CheckText('After ecDeleteLastWord', '', 0);
191
192 ReCreateEdit;
193 SynEdit.CommandProcessor(ecInsertLine, '', nil);
194 CheckText('After ecInsertLine', LineEnding, 2);
195
196 ReCreateEdit;
197 SynEdit.CommandProcessor(ecLineBreak, '', nil);
198 CheckText('After ecLineBreak', LineEnding, 2);
199
200 end;
201 begin
202 TrimEnabled := True;
203 TrimType := settEditLine;
204 PushBaseName('Trim=EditLine');
205 PushBaseName('InsertMode');
206 InsertFlag := True;
207 DoChecks;
208 PopPushBaseName('OverwriteMode');
209 InsertFlag := False;
210 DoChecks;
211 PopBaseName;
212
213 TrimType := settIgnoreAll;
214 PopPushBaseName('Trim=IgnoreAll');
215 PushBaseName('InsertMode');
216 InsertFlag := True;
217 DoChecks;
218 PopPushBaseName('OverwriteMode');
219 InsertFlag := False;
220 DoChecks;
221 PopBaseName;
222
223 TrimEnabled := False;
224 PopPushBaseName('Trim=Disabled');
225 PushBaseName('InsertMode');
226 InsertFlag := True;
227 DoChecks;
228 PopPushBaseName('OverwriteMode');
229 InsertFlag := False;
230 DoChecks;
231 PopBaseName;
232
233 end;
234
235 procedure TTestBasicSynEdit.TestEditTabs;
236 begin
237 ReCreateEdit;
238 // witout eoAutoIndent
239 SynEdit.Options := SynEdit.Options
240 - [eoTabIndent, eoTabsToSpaces, eoSpacesToTabs, eoAutoIndent, eoSmartTabs, eoSmartTabDelete];
241 SynEdit.TabWidth := 4;
242 SetLines([' abc', #9'abcde', '']);
243 SetCaret(2, 2); // after tab
244 TestIsCaretPhys('Before delete tab', 5, 2);
245 SynEdit.CommandProcessor(ecDeleteLastChar, '', nil);
246
247 TestIsCaret('After delete tab', 1, 2);
248 TestIsCaretPhys('After delete tab', 1, 2);
249 TestIsText('After delete tab', [' abc', 'abcde', '']);
250
251 ReCreateEdit;
252 // with eoAutoIndent
253 SynEdit.Options := SynEdit.Options + [eoSmartTabs, eoSmartTabDelete, eoAutoIndent]
254 - [eoTabIndent, eoTabsToSpaces, eoSpacesToTabs];
255 SynEdit.TabWidth := 4;
256 SetLines([' abc', #9'abcde', '']);
257 SetCaret(2, 2); // after tab
258 TestIsCaretPhys('Before delete tab', 5, 2);
259 SynEdit.CommandProcessor(ecDeleteLastChar, '', nil);
260
261 // reuqired indent is filled up with spaces
262 TestIsCaret('After delete tab (smart)', 3, 2);
263 TestIsCaretPhys('After delete tab (smart)', 3, 2);
264 TestIsText('After delete tab (smart)', [' abc', ' abcde', '']);
265
266 end;
267
268 procedure TTestBasicSynEdit.TestEditEcChar;
269 var
270 CaretPEol: Boolean;
271
TestText1null272 function TestText1: TStringArray;
273 begin
274 SetLength(Result, 4);
275 Result[0] := 'abc';
276 Result[1] := 'öbc';
277 Result[2] := #9'abc';
278 Result[3] := '';
279 end;
280 procedure InitEdit;
281 begin
282 ReCreateEdit;
283 SynEdit.Options := [];
284 if CaretPEol then SynEdit.Options := SynEdit.Options + [eoScrollPastEol];
285 SynEdit.TabWidth := 6;
286 SetLines(TestText1);
287 end;
288
289 // All Logical pos
290 Procedure DoTest(ATestName: String; StartX, StartY: Integer;
291 Char1: String; ExpX1, ExpY1: Integer; Repl1: Array of const;
292 Char2: String; ExpX2, ExpY2: Integer; Repl2: Array of const;
293 AStartIsPhys: Boolean = False
294 );
295 begin
296 BaseTestName := Format('%s -Ins=%s - PastEol=%s - StartXY=(%d,%d) - ',
297 [ATestName, dbgs(InsertFlag), dbgs(CaretPEol), StartX, StartY]);
298 InitEdit;
299
300 if AStartIsPhys
301 then SetCaretPhys(StartX, StartY)
302 else SetCaret(StartX, StartY);
303
304 SynEdit.TestTypeText(Char1);
305 TestIsCaret('After Char 1', ExpX1, ExpY1);
306 TestIsText ('After Char 1', TestText1, Repl1);
307
308 SynEdit.TestTypeText(Char2);
309 TestIsCaret('After Char 2', ExpX2, ExpY2);
310 TestIsText ('After Char 2', TestText1, Repl2);
311
312 SynEdit.Undo;
313 TestIsCaret('Undo 1', ExpX1, ExpY1);
314 TestIsText ('Undo 1', TestText1, Repl1);
315
316 SynEdit.Redo;
317 TestIsCaret('Redo 1', ExpX2, ExpY2);
318 TestIsText ('Redo 1', TestText1, Repl2);
319
320 SynEdit.Undo;
321 TestIsCaret('Undo 2a', ExpX1, ExpY1);
322 TestIsText ('Undo 2a', TestText1, Repl1);
323
324 SynEdit.Undo;
325 if AStartIsPhys
326 then TestIsCaretPhys('Undo 2b', StartX, StartY)
327 else TestIsCaret('Undo 2b', StartX, StartY);
328 TestIsText ('Undo 2b', TestText1);
329
330 SynEdit.Redo;
331 TestIsCaret('Redo 2a', ExpX1, ExpY1);
332 TestIsText ('Redo 2a', TestText1, Repl1);
333
334 SynEdit.Redo;
335 TestIsCaret('Redo 2b', ExpX2, ExpY2);
336 TestIsText ('Redo 2b', TestText1, Repl2);
337
338 InitEdit;
339
340 if AStartIsPhys
341 then SetCaretPhys(StartX, StartY)
342 else SetCaret(StartX, StartY);
343 SynEdit.TestTypeText(Char1);
344 SynEdit.TestTypeText(Char2);
345 TestIsCaret('After Char 1+2', ExpX2, ExpY2);
346 TestIsText ('After Char 1+2', TestText1, Repl2);
347
348 end;
349 begin
350 TrimEnabled := False; // Trim has its own test
351
352 // Testing ecChar. Tab is ecTab, so not included
353
354 {%region Normal Line}
355 {%region Normal Line -- Normal Char}
356 InsertFlag := True;
357 CaretPEol := False;
358 DoTest('normal line - BOL', 1, 1, 'X', 2, 1, [1,'Xabc'], 'Y', 3,1, [1,'XYabc']);
359 DoTest('normal line - mid', 2, 1, 'X', 3, 1, [1,'aXbc'], 'Y', 4,1, [1,'aXYbc']);
360 DoTest('normal line - EOL', 4, 1, 'X', 5, 1, [1,'abcX'], 'Y', 6,1, [1,'abcXY']);
361 CaretPEol := True;
362 DoTest('normal line - EOL', 4, 1, 'X', 5, 1, [1,'abcX'], 'Y', 6,1, [1,'abcXY']);
363 DoTest('normal line - Past', 6, 1, 'X', 7, 1, [1,'abc X'], 'Y', 8,1, [1,'abc XY']);
364
365 InsertFlag := False;
366 CaretPEol := False;
367 DoTest('normal line - BOL', 1, 1, 'X', 2, 1, [1,'Xbc'], 'Y', 3,1, [1,'XYc']);
368 DoTest('normal line - mid', 2, 1, 'X', 3, 1, [1,'aXc'], 'Y', 4,1, [1,'aXY']);
369 DoTest('normal line - mid', 3, 1, 'X', 4, 1, [1,'abX'], 'Y', 5,1, [1,'abXY']);
370 DoTest('normal line - EOL', 4, 1, 'X', 5, 1, [1,'abcX'], 'Y', 6,1, [1,'abcXY']);
371 CaretPEol := True;
372 DoTest('normal line - EOL', 4, 1, 'X', 5, 1, [1,'abcX'], 'Y', 6,1, [1,'abcXY']);
373 DoTest('normal line - Past', 6, 1, 'X', 7, 1, [1,'abc X'], 'Y', 8,1, [1,'abc XY']);
374 {%endregion}
375
376 {%region Normal Line -- Space (and char)}
377 InsertFlag := True;
378 CaretPEol := False;
379 DoTest('normal line - space,char - BOL', 1, 1, ' ', 2, 1, [1,' abc'], 'Y', 3,1, [1,' Yabc']);
380 DoTest('normal line - space,char - mid', 2, 1, ' ', 3, 1, [1,'a bc'], 'Y', 4,1, [1,'a Ybc']);
381 DoTest('normal line - space,char - EOL', 4, 1, ' ', 5, 1, [1,'abc '], 'Y', 6,1, [1,'abc Y']);
382 CaretPEol := True;
383 DoTest('normal line - space,char - EOL', 4, 1, ' ', 5, 1, [1,'abc '], 'Y', 6,1, [1,'abc Y']);
384 DoTest('normal line - space,char - Past', 6, 1, ' ', 7, 1, [1,'abc '], 'Y', 8,1, [1,'abc Y']);
385
386 InsertFlag := False;
387 CaretPEol := False;
388 DoTest('normal line - space,char - BOL', 1, 1, ' ', 2, 1, [1,' bc'], 'Y', 3,1, [1,' Yc']);
389 DoTest('normal line - space,char - mid', 2, 1, ' ', 3, 1, [1,'a c'], 'Y', 4,1, [1,'a Y']);
390 DoTest('normal line - space,char - mid', 3, 1, ' ', 4, 1, [1,'ab '], 'Y', 5,1, [1,'ab Y']);
391 DoTest('normal line - space,char - EOL', 4, 1, ' ', 5, 1, [1,'abc '], 'Y', 6,1, [1,'abc Y']);
392 CaretPEol := True;
393 DoTest('normal line - space,char - EOL', 4, 1, ' ', 5, 1, [1,'abc '], 'Y', 6,1, [1,'abc Y']);
394 DoTest('normal line - space,char - Past', 6, 1, ' ', 7, 1, [1,'abc '], 'Y', 8,1, [1,'abc Y']);
395 {%endregion}
396
397 {%region Normal Line -- Space}
398 InsertFlag := True;
399 CaretPEol := False;
400 DoTest('normal line - space - BOL', 1, 1, ' ', 2, 1, [1,' abc'], ' ', 3,1, [1,' abc']);
401 DoTest('normal line - space - mid', 2, 1, ' ', 3, 1, [1,'a bc'], ' ', 4,1, [1,'a bc']);
402 DoTest('normal line - space - EOL', 4, 1, ' ', 5, 1, [1,'abc '], ' ', 6,1, [1,'abc ']);
403 CaretPEol := True;
404 DoTest('normal line - space - EOL', 4, 1, ' ', 5, 1, [1,'abc '], ' ', 6,1, [1,'abc ']);
405 DoTest('normal line - space - Past', 6, 1, ' ', 7, 1, [1,'abc '], ' ', 8,1, [1,'abc ']);
406
407 InsertFlag := False;
408 CaretPEol := False;
409 DoTest('normal line - space - BOL', 1, 1, ' ', 2, 1, [1,' bc'], ' ', 3,1, [1,' c']);
410 DoTest('normal line - space - mid', 2, 1, ' ', 3, 1, [1,'a c'], ' ', 4,1, [1,'a ']);
411 DoTest('normal line - space - mid', 3, 1, ' ', 4, 1, [1,'ab '], ' ', 5,1, [1,'ab ']);
412 DoTest('normal line - space - EOL', 4, 1, ' ', 5, 1, [1,'abc '], ' ', 6,1, [1,'abc ']);
413 CaretPEol := True;
414 DoTest('normal line - space - EOL', 4, 1, ' ', 5, 1, [1,'abc '], ' ', 6,1, [1,'abc ']);
415 DoTest('normal line - space - Past', 6, 1, ' ', 7, 1, [1,'abc '], ' ', 8,1, [1,'abc ']);
416 {%endregion}
417
418 {%region Normal Line -- utf8 2 byte Char}
419 InsertFlag := True;
420 CaretPEol := False;
421 DoTest('normal line - 2byte utf8 - BOL', 1, 1, 'Ä', 3, 1, [1,'Äabc'], 'Ü', 5,1, [1,'ÄÜabc']);
422 DoTest('normal line - 2byte utf8 - mid', 2, 1, 'Ä', 4, 1, [1,'aÄbc'], 'Ü', 6,1, [1,'aÄÜbc']);
423 DoTest('normal line - 2byte utf8 - EOL', 4, 1, 'Ä', 6, 1, [1,'abcÄ'], 'Ü', 8,1, [1,'abcÄÜ']);
424 CaretPEol := True;
425 DoTest('normal line - 2byte utf8 - EOL', 4, 1, 'Ä', 6, 1, [1,'abcÄ'], 'Ü', 8,1, [1,'abcÄÜ']);
426 DoTest('normal line - 2byte utf8 - Past', 6, 1, 'Ä', 8, 1, [1,'abc Ä'], 'Ü',10,1, [1,'abc ÄÜ']);
427
428 InsertFlag := False;
429 CaretPEol := False;
430 DoTest('normal line - 2byte utf8 - BOL', 1, 1, 'Ä', 3, 1, [1,'Äbc'], 'Ü', 5,1, [1,'ÄÜc']);
431 DoTest('normal line - 2byte utf8 - mid', 2, 1, 'Ä', 4, 1, [1,'aÄc'], 'Ü', 6,1, [1,'aÄÜ']);
432 DoTest('normal line - 2byte utf8 - mid', 3, 1, 'Ä', 5, 1, [1,'abÄ'], 'Ü', 7,1, [1,'abÄÜ']);
433 DoTest('normal line - 2byte utf8 - EOL', 4, 1, 'Ä', 6, 1, [1,'abcÄ'], 'Ü', 8,1, [1,'abcÄÜ']);
434 CaretPEol := True;
435 DoTest('normal line - 2byte utf8 - EOL', 4, 1, 'Ä', 6, 1, [1,'abcÄ'], 'Ü', 8,1, [1,'abcÄÜ']);
436 DoTest('normal line - 2byte utf8 - Past', 6, 1, 'Ä', 8, 1, [1,'abc Ä'], 'Ü',10,1, [1,'abc ÄÜ']);
437 {%endregion}
438
439 {%region Normal Line -- full width Char - 3 bytes}
440 // May change in future. overwrite only one char
441 InsertFlag := True;
442 CaretPEol := False;
443 DoTest('normal line - 3 byte full witdh - BOL', 1, 1, 'あ', 4, 1, [1,'あabc'], '吾', 7,1, [1,'あ吾abc']);
444 DoTest('normal line - 3 byte full witdh - mid', 2, 1, 'あ', 5, 1, [1,'aあbc'], '吾', 8,1, [1,'aあ吾bc']);
445 DoTest('normal line - 3 byte full witdh - EOL', 4, 1, 'あ', 7, 1, [1,'abcあ'], '吾',10,1, [1,'abcあ吾']);
446 CaretPEol := True;
447 DoTest('normal line - 3 byte full witdh - EOL', 4, 1, 'あ', 7, 1, [1,'abcあ'], '吾',10,1, [1,'abcあ吾']);
448 DoTest('normal line - 3 byte full witdh - Past', 6, 1, 'あ', 9, 1, [1,'abc あ'], '吾',12,1, [1,'abc あ吾']);
449
450 InsertFlag := False;
451 CaretPEol := False;
452 DoTest('normal line - 3 byte full witdh - BOL', 1, 1, 'あ', 4, 1, [1,'あbc'], '吾', 7,1, [1,'あ吾c']);
453 DoTest('normal line - 3 byte full witdh - mid', 2, 1, 'あ', 5, 1, [1,'aあc'], '吾', 8,1, [1,'aあ吾']);
454 DoTest('normal line - 3 byte full witdh - mid', 3, 1, 'あ', 6, 1, [1,'abあ'], '吾', 9,1, [1,'abあ吾']);
455 DoTest('normal line - 3 byte full witdh - EOL', 4, 1, 'あ', 7, 1, [1,'abcあ'], '吾',10,1, [1,'abcあ吾']);
456 CaretPEol := True;
457 DoTest('normal line - 3 byte full witdh - EOL', 4, 1, 'あ', 7, 1, [1,'abcあ'], '吾',10,1, [1,'abcあ吾']);
458 DoTest('normal line - 3 byte full witdh - Past', 6, 1, 'あ', 9, 1, [1,'abc あ'], '吾',12,1, [1,'abc あ吾']);
459 {%endregion}
460 {%endregion}
461
462 {%region Line with utf8 at start}
463 {%region Normal Char}
464 InsertFlag := True;
465 CaretPEol := False;
466 DoTest('utf8 at start - BOL', 1, 2, 'X', 2, 2, [2,'Xöbc'], 'Y', 3,2, [2,'XYöbc']);
467 DoTest('utf8 at start - mid', 3, 2, 'X', 4, 2, [2,'öXbc'], 'Y', 5,2, [2,'öXYbc']);
468 DoTest('utf8 at start - EOL', 5, 2, 'X', 6, 2, [2,'öbcX'], 'Y', 7,2, [2,'öbcXY']);
469 CaretPEol := True;
470 DoTest('utf8 at start - EOL', 5, 2, 'X', 6, 2, [2,'öbcX'], 'Y', 7,2, [2,'öbcXY']);
471 DoTest('utf8 at start - Past', 7, 2, 'X', 8, 2, [2,'öbc X'], 'Y', 9,2, [2,'öbc XY']);
472
473 InsertFlag := False;
474 CaretPEol := False;
475 DoTest('utf8 at start - BOL', 1, 2, 'X', 2, 2, [2,'Xbc'], 'Y', 3,2, [2,'XYc']);
476 DoTest('utf8 at start - mid', 3, 2, 'X', 4, 2, [2,'öXc'], 'Y', 5,2, [2,'öXY']);
477 DoTest('utf8 at start - mid', 4, 2, 'X', 5, 2, [2,'öbX'], 'Y', 6,2, [2,'öbXY']);
478 DoTest('utf8 at start - EOL', 5, 2, 'X', 6, 2, [2,'öbcX'], 'Y', 7,2, [2,'öbcXY']);
479 CaretPEol := True;
480 DoTest('utf8 at start - EOL', 5, 2, 'X', 6, 2, [2,'öbcX'], 'Y', 7,2, [2,'öbcXY']);
481 DoTest('utf8 at start - Past', 7, 2, 'X', 8, 2, [2,'öbc X'], 'Y', 9,2, [2,'öbc XY']);
482 {%endregion}
483
484 {%region utf8 2 byte Char}
485 InsertFlag := True;
486 CaretPEol := False;
487 DoTest('utf8 at start - 2byte utf8 - BOL', 1, 2, 'Ä', 3, 2, [2,'Äöbc'], 'Ü', 5,2, [2,'ÄÜöbc']);
488 DoTest('utf8 at start - 2byte utf8 - mid', 3, 2, 'Ä', 5, 2, [2,'öÄbc'], 'Ü', 7,2, [2,'öÄÜbc']);
489 DoTest('utf8 at start - 2byte utf8 - EOL', 5, 2, 'Ä', 7, 2, [2,'öbcÄ'], 'Ü', 9,2, [2,'öbcÄÜ']);
490 CaretPEol := True;
491 DoTest('utf8 at start - 2byte utf8 - EOL', 5, 2, 'Ä', 7, 2, [2,'öbcÄ'], 'Ü', 9,2, [2,'öbcÄÜ']);
492 DoTest('utf8 at start - 2byte utf8 - Past', 7, 2, 'Ä', 9, 2, [2,'öbc Ä'], 'Ü',11,2, [2,'öbc ÄÜ']);
493
494 InsertFlag := False;
495 CaretPEol := False;
496 DoTest('utf8 at start - 2byte utf8 - BOL', 1, 2, 'Ä', 3, 2, [2,'Äbc'], 'Ü', 5,2, [2,'ÄÜc']);
497 DoTest('utf8 at start - 2byte utf8 - mid', 3, 2, 'Ä', 5, 2, [2,'öÄc'], 'Ü', 7,2, [2,'öÄÜ']);
498 DoTest('utf8 at start - 2byte utf8 - mid', 4, 2, 'Ä', 6, 2, [2,'öbÄ'], 'Ü', 8,2, [2,'öbÄÜ']);
499 DoTest('utf8 at start - 2byte utf8 - EOL', 5, 2, 'Ä', 7, 2, [2,'öbcÄ'], 'Ü', 9,2, [2,'öbcÄÜ']);
500 CaretPEol := True;
501 DoTest('utf8 at start - 2byte utf8 - EOL', 5, 2, 'Ä', 7, 2, [2,'öbcÄ'], 'Ü', 9,2, [2,'öbcÄÜ']);
502 DoTest('utf8 at start - 2byte utf8 - Past', 7, 2, 'Ä', 9, 2, [2,'öbc Ä'], 'Ü',11,2, [2,'öbc ÄÜ']);
503 {%endregion}
504
505 {%endregion}
506
507 {%region Line with tab at start}
508 {%region Normal Char}
509 InsertFlag := True;
510 CaretPEol := False;
511 // Phys start pos
512 DoTest('tab at start - BOL', 1, 3, 'X', 2, 3, [3,'X'#9'abc'], 'Y', 3,3, [3,'XY'#9'abc'], True);
513 DoTest('tab at start - after tab', 7, 3, 'X', 3, 3, [3,#9'Xabc'], 'Y', 4,3, [3,#9'XYabc'], True);
514 DoTest('tab at start - in tab', 3, 3, 'X', 2, 3, [3,'X'#9'abc'], 'Y', 3,3, [3,'XY'#9'abc'], True);
515
516 InsertFlag := False;
517 CaretPEol := False;
518 DoTest('tab at start - BOL', 1, 3, 'X', 2, 3, [3,'Xabc'], 'Y', 3,3, [3,'XYbc'], True);
519 DoTest('tab at start - after tab', 7, 3, 'X', 3, 3, [3,#9'Xbc'], 'Y', 4,3, [3,#9'XYc'], True);
520 DoTest('tab at start - in tab', 3, 3, 'X', 2, 3, [3,'Xabc'], 'Y', 3,3, [3,'XYbc'], True);
521 {%endregion}
522 {%endregion}
523
524 // TODO: 2 byte at EOL
525 // TODO Overwrite selection
526 end;
527
528 procedure TTestBasicSynEdit.TestPhysicalLogical;
529
LogPhysConvnull530 function LogPhysConv: TSynLogicalPhysicalConvertor;
531 begin
532 Result := SynEdit.ViewedTextBuffer.LogPhysConvertor;
533 end;
534
535 procedure TestPhysLog(name: string; y, x: integer;
536 expX: integer; expCol: integer = -1;
537 expXcsRight: integer = -1; expColCsRight: integer = -1;
538 expXcsLtr: integer = -1; expColCsLtr: integer = -1;
539 expXcsRtl: integer = -1; expColCsRtl: integer = -1);
540 var
541 gotX, gotCol: Integer;
542 expDef: Integer;
543 begin
544 name := name + ' y='+inttostr(y)+' x='+inttostr(x);
545
546 expDef := expX;
547 if expXcsLtr >= 0 then expDef := expXcsLtr;
548
549 gotX := SynEdit.PhysicalToLogicalPos(Point(x, y)).x;
550 AssertEquals(name+' PhysicalToLogicalPos', expDef, gotX);
551
552 gotX := SynEdit.PhysicalToLogicalCol(SynEdit.Lines[y-1], y-1, x);
553 AssertEquals(name+' PhysicalToLogicalCol', expDef, gotX);
554
555
556
557 gotX := LogPhysConv.PhysicalToLogical(y-1, x, gotCol, cspLeft);
558 AssertEquals(name+' c.PhysicalToLogical', expX, gotX);
559 if expCol >= 0 then
560 AssertEquals(name+' c.PhysicalToLogical COL', expCol, gotCol);
561
562
563 if expXcsRight >= 0 then begin
564 gotX := LogPhysConv.PhysicalToLogical(y-1, x, gotCol, cspRight);
565 AssertEquals(name+' c.PhysicalToLogical csRight', expXcsRight, gotX);
566 if expColCsRight >= 0 then
567 AssertEquals(name+' c.PhysicalToLogical csRight COL', expColCsRight, gotCol);
568 end;
569
570
571 if expXcsLtr >= 0 then begin
572 gotX := LogPhysConv.PhysicalToLogical(y-1, x, gotCol, cspFollowLtr);
573 AssertEquals(name+' c.PhysicalToLogical csLtr', expXcsLtr, gotX);
574 if expColCsLtr >= 0 then
575 AssertEquals(name+' c.PhysicalToLogical csLtr COL', expColCsLtr, gotCol);
576 end;
577
578
579 if expXcsRtl >= 0 then begin
580 gotX := LogPhysConv.PhysicalToLogical(y-1, x, gotCol, cspFollowRtl);
581 AssertEquals(name+' c.PhysicalToLogical csRtl', expXcsRtl, gotX);
582 if expColCsRtl >= 0 then
583 AssertEquals(name+' c.PhysicalToLogical csRtl COL', expColCsRtl, gotCol);
584 end;
585 end;
586
587 procedure TestLogPhys(name: string; y, x, aCol: integer;
588 expX: integer; expXcsAfter: integer = -1; expXcsLtr: integer = -1; expXcsRtl: integer = -1);
589 var gotX: Integer;
590 expDef: Integer;
591 begin
592 name := name + ' y='+inttostr(y)+' x='+inttostr(x)+' c='+IntToStr(aCol);
593
594 if aCol = 0 then begin
595 expDef := expX;
596 if expXcsLtr >= 0 then expDef := expXcsLtr; // default is now cslFollowLtr
597
598 gotX := SynEdit.LogicalToPhysicalPos(Point(x, y)).x;
599 AssertEquals(name+' LogicalToPhysicalPos', expDef, gotX);
600
601 gotX := SynEdit.LogicalToPhysicalCol(SynEdit.Lines[y-1], y-1, x);
602 AssertEquals(name+' LogicalToPhysicalCol', expDef, gotX);
603 end;
604
605 gotX := LogPhysConv.LogicalToPhysical(y-1, x, aCol, cslBefore);
606 AssertEquals(name+' c.LogicalToPhysical', expX, gotX);
607
608 if expXcsAfter >= 0 then begin
609 gotX := LogPhysConv.LogicalToPhysical(y-1, x, aCol, cslAfter);
610 AssertEquals(name+' c.LogicalToPhysical cslAfter', expXcsAfter, gotX);
611 end;
612
613 if expXcsLtr >= 0 then begin
614 gotX := LogPhysConv.LogicalToPhysical(y-1, x, aCol, cslFollowLtr);
615 AssertEquals(name+' c.LogicalToPhysical cslFollowLtr', expXcsLtr, gotX);
616 end;
617
618 if expXcsRtl >= 0 then begin
619 gotX := LogPhysConv.LogicalToPhysical(y-1, x, aCol, cslFollowRtl);
620 AssertEquals(name+' c.LogicalToPhysical cslFollowRtl', expXcsRtl, gotX);
621 end;
622 end;
623
624 begin
625 ReCreateEdit;
626 SynEdit.TabWidth := 6;
627
628 // Todo Log2Phys: test column is cut off
629
630 SetLines(['abc', ' ääX', #9'mn', 'abc'#9'de', #9'Xää.', 'ab'#9, 'あ吾' ]);
631
632 TestLogPhys('simple line (abc)', 1, 1, 0, 1);
633 TestLogPhys('simple line (abc)', 1, 2, 0, 2);
634 TestLogPhys('simple line (abc)', 1, 4, 0, 4);
635 TestLogPhys('simple line (abc)', 1, 5, 0, 5);
636 TestLogPhys('simple line (abc)', 1, 6, 0, 6);
637 TestLogPhys('line with 2byte-char', 2, 1, 0, 1);
638 TestLogPhys('line with 2byte-char', 2, 2, 0, 2);
639 TestLogPhys('line with 2byte-char', 2, 4, 0, 3); // after ae
640 TestLogPhys('line with 2byte-char', 2, 6, 0, 4);
641 TestLogPhys('line with 2byte-char', 2, 7, 0, 5);
642 TestLogPhys('line with 2byte-char', 2, 8, 0, 6);
643 TestLogPhys('line with 2byte-char', 2, 11, 0, 9);
644 TestLogPhys('line with tab (start)', 3, 1, 0, 1);
645 TestLogPhys('line with tab (start)', 3, 2, 0, 7);
646 TestLogPhys('line with tab (middle)', 4, 3, 0, 3);
647 TestLogPhys('line with tab (middle)', 4, 4, 0, 4); // before tab
648 TestLogPhys('line with tab (middle)', 4, 4, 1, 5); // inside tab
649 TestLogPhys('line with tab (middle)', 4, 4, 2, 6); // inside tab
650 TestLogPhys('line with tab (middle)', 4, 5, 0, 7); // after tab
651 TestLogPhys('line with tab (middle)', 4, 6, 0, 8);
652 TestLogPhys('line with tab (middle)', 4, 9, 0, 11);
653 TestLogPhys('line with tab (start) + 2bc', 5, 1, 0, 1);
654 TestLogPhys('line with tab (start) + 2bc', 5, 2, 0, 7);
655 TestLogPhys('line with tab (start) + 2bc', 5, 3, 0, 8);
656 TestLogPhys('line with tab (start) + 2bc', 5, 5, 0, 9);
657 TestLogPhys('line with tab (end)', 6, 3, 0, 3);
658 TestLogPhys('line with tab (end)', 6, 4, 0, 7);
659 TestLogPhys('line with tab (end)', 6, 5, 0, 8);
660 TestLogPhys('line with tab (end)', 6, 3, 1, 4);
661 TestLogPhys('line with tab (end)', 6, 3, 2, 5);
662 TestLogPhys('line with tab (end)', 6, 3, 3, 6);
663 TestLogPhys('line with double-width/3byte',7, 1, 0, 1);
664 TestLogPhys('line with double-width/3byte',7, 1, 1, 2);
665 TestLogPhys('line with double-width/3byte',7, 4, 0, 3);
666 TestLogPhys('line with double-width/3byte',7, 4, 1, 4);
667 TestLogPhys('line with double-width/3byte',7, 7, 0, 5);
668
669 TestPhysLog('simple line (abc)', 1, 1, 1);
670 TestPhysLog('simple line (abc)', 1, 2, 2);
671 TestPhysLog('simple line (abc)', 1, 4, 4);
672 TestPhysLog('simple line (abc)', 1, 5, 5);
673 TestPhysLog('simple line (abc)', 1, 6, 6);
674 TestPhysLog('line with 3byte-char', 2, 1, 1);
675 TestPhysLog('line with 3byte-char', 2, 2, 2);
676 TestPhysLog('line with 3byte-char', 2, 3, 4);
677 TestPhysLog('line with 3byte-char', 2, 4, 6);
678 TestPhysLog('line with 3byte-char', 2, 5, 7);
679 TestPhysLog('line with 3byte-char', 2, 6, 8);
680 TestPhysLog('line with 3byte-char', 2, 7, 9);
681 TestPhysLog('line with tab (start)', 3, 1, 1);
682 TestPhysLog('line with tab (start)', 3, 2, 1);
683 TestPhysLog('line with tab (start)', 3, 5, 1);
684 TestPhysLog('line with tab (start)', 3, 6, 1);
685 TestPhysLog('line with tab (start)', 3, 7, 2);
686 TestPhysLog('line with tab (start)', 3, 8, 3);
687 TestPhysLog('line with tab (start)', 3, 9, 4);
688 TestPhysLog('line with tab (start)', 3, 11, 6);
689 TestPhysLog('line with double-width/3byte', 7, 1, 1, 0);
690 TestPhysLog('line with double-width/3byte', 7, 2, 1, 1);
691 TestPhysLog('line with double-width/3byte', 7, 3, 4, 0);
692 TestPhysLog('line with double-width/3byte', 7, 4, 4, 1);
693 TestPhysLog('line with double-width/3byte', 7, 5, 7, 0);
694
695 //abc def ghi // 2bytes per char
696
697 (* Order in String "123" / Order on Screen "321"
698 LogicalToPhys
699 Log = 1
700 <|321 L2p (csLeft) => 1 // Log 1 is after it's LEFT neighbour (BOL)
701 321<| L2p (csRight) => 4 // Log 1 is before it's RIGHT neighbour (char "1") // logical right, byte order in string
702 Log = 4
703 |>321 L2p (csLeft) => 1 // Log 4 is after it's LEFT neighbour (char "3") // logical left, byte order in string
704 321|> L2p (csRight) => 4 // Log 4 is before it's RIGHT neighbour (EOL)
705
706 PhysToLog:
707 Phys = 1
708 <|321 L2p (csLeft) => 1
709 |>321 L2p (csRight) => 4
710 Phys = 4
711 321<| L2p (csLeft) => 1
712 321|> L2p (csRight) => 4
713
714 *)
715
716 SetLines(['شىه ايغ عتل', 'ABCشىه ايغ عتلDEF', 'abcشىه ايغ عتل', 'شىه ايغ عتلdef', '']);
717
718 // B, A, L, R
719 TestLogPhys('empty line', 5, 1, 0, 1, 1, 1, 1);
720 TestLogPhys('empty line', 5, 2, 0, 2, 2, 2, 2);
721
722 TestLogPhys('bidi line (arab only)', 1, 1, 0, 1, 12, 1, 12);
723 TestLogPhys('bidi line (arab only)', 1, 3, 0, 11, 11, 11, 11);
724 TestLogPhys('bidi line (arab only)', 1, 5, 0, 10, 10, 10, 10);
725 TestLogPhys('bidi line (arab only)', 1, 7, 0, 9, 9, 9, 9);
726 TestLogPhys('bidi line (arab only)', 1, 8, 0, 8, 8, 8, 8); // after space
727 TestLogPhys('bidi line (arab only)', 1, 15, 0, 4, 4, 4, 4); // after space
728 TestLogPhys('bidi line (arab only)', 1, 19, 0, 2, 2, 2, 2);
729 TestLogPhys('bidi line (arab only)', 1, 21, 0, 1, 12, 12, 1); // at EOL
730 TestLogPhys('bidi line (arab only)', 1, 22, 0, 13, 13, 13, 13); // past eol
731 TestLogPhys('bidi line (arab only)', 1, 23, 0, 14, 14, 14, 14);
732
733 TestLogPhys('bidi line (mixed arab/latin)', 2, 1, 0, 1, 1, 1, 1);
734 TestLogPhys('bidi line (mixed arab/latin)', 2, 4, 0, 4, 15, 4, 15); // after C
735 TestLogPhys('bidi line (mixed arab/latin)', 2, 6, 0, 14, 14, 14, 14); // 1 into arabic
736 TestLogPhys('bidi line (mixed arab/latin)', 2, 22, 0, 5, 5, 5, 5); // 1 before end arabic
737 TestLogPhys('bidi line (mixed arab/latin)', 2, 24, 0, 4, 15, 15, 4); // at end arabic
738 TestLogPhys('bidi line (mixed arab/latin)', 2, 25, 0, 16, 16, 16, 16); // after D
739 TestLogPhys('bidi line (mixed arab/latin)', 2, 27, 0, 18, 18, 18, 18); // at eol
740 TestLogPhys('bidi line (mixed arab/latin)', 2, 28, 0, 19, 19, 19, 19); // after eol
741
742 // Lft Rght LTR RTL
743 TestPhysLog('empty line', 5, 1, 1, 0, 1, 0, 1, 0, 1, 0);
744 TestPhysLog('empty line', 5, 2, 2, 0, 2, 0, 2, 0, 2, 0);
745
746 TestPhysLog('bidi line (arab only)', 1, 1, 1, 0, 21, 0, 1, 0, 21, 0);
747 TestPhysLog('bidi line (arab only)', 1, 2, 19, 0, 19, 0, 19, 0, 19, 0);
748 TestPhysLog('bidi line (arab only)', 1, 3, 17, 0, 17, 0, 17, 0, 17, 0);
749 TestPhysLog('bidi line (arab only)', 1, 4, 15, 0, 15, 0, 15, 0, 15, 0); // before space
750 TestPhysLog('bidi line (arab only)', 1, 5, 14, 0, 14, 0, 14, 0, 14, 0); // after space
751 TestPhysLog('bidi line (arab only)', 1, 10, 5, 0, 5, 0, 5, 0, 5, 0);
752 TestPhysLog('bidi line (arab only)', 1, 11, 3, 0, 3, 0, 3, 0, 3, 0);
753 TestPhysLog('bidi line (arab only)', 1, 12, 1, 0, 21, 0, 21, 0, 1, 0); // at eol
754 TestPhysLog('bidi line (arab only)', 1, 13, 22, 0, 22, 0, 22, 0, 22, 0);
755 TestPhysLog('bidi line (arab only)', 1, 14, 23, 0, 23, 0, 23, 0, 23, 0);
756
757 TestPhysLog('bidi line (mixed arab/latin)',2, 1, 1, 0, 1, 0, 1, 0, 1, 0);
758 TestPhysLog('bidi line (mixed arab/latin)',2, 4, 4, 0, 24, 0, 4, 0, 24, 0);
759 TestPhysLog('bidi line (mixed arab/latin)',2, 15, 4, 0, 24, 0, 24, 0, 4, 0);
760 end;
761
762 procedure TTestBasicSynEdit.TestLogicalAdjust;
763 var
764 tb: TSynEditStrings;
765 begin
766 tb := SynEdit.TextBuffer;
767 // #$CC#$81 Combining
768 AssertEquals('LogicPosIsAtChar 1 ', True, tb.LogicPosIsAtChar('aüb'#$CC#$81'c', 1)); // a
769 AssertEquals('LogicPosIsAtChar 2 ', True, tb.LogicPosIsAtChar('aüb'#$CC#$81'c', 2)); // ü
770 AssertEquals('LogicPosIsAtChar 3 ', False,tb.LogicPosIsAtChar('aüb'#$CC#$81'c', 3)); // mid ü
771 AssertEquals('LogicPosIsAtChar 4 ', True, tb.LogicPosIsAtChar('aüb'#$CC#$81'c', 4)); // b
772 AssertEquals('LogicPosIsAtChar 5 ', False,tb.LogicPosIsAtChar('aüb'#$CC#$81'c', 5)); // AT Combining
773 AssertEquals('LogicPosIsAtChar 6 ', False,tb.LogicPosIsAtChar('aüb'#$CC#$81'c', 6)); // mid Combining
774 AssertEquals('LogicPosIsAtChar 7 ', True, tb.LogicPosIsAtChar('aüb'#$CC#$81'c', 7)); // c
775
776 AssertEquals('LogicPosIsAtChar 1 C', True, tb.LogicPosIsAtChar('aüb'#$CC#$81'c', 1, [lpStopAtCodePoint])); // a
777 AssertEquals('LogicPosIsAtChar 2 C', True, tb.LogicPosIsAtChar('aüb'#$CC#$81'c', 2, [lpStopAtCodePoint])); // ü
778 AssertEquals('LogicPosIsAtChar 3 C', False,tb.LogicPosIsAtChar('aüb'#$CC#$81'c', 3, [lpStopAtCodePoint])); // mid ü
779 AssertEquals('LogicPosIsAtChar 4 C', True, tb.LogicPosIsAtChar('aüb'#$CC#$81'c', 4, [lpStopAtCodePoint])); // b
780 AssertEquals('LogicPosIsAtChar 5 C', True ,tb.LogicPosIsAtChar('aüb'#$CC#$81'c', 5, [lpStopAtCodePoint])); // AT Combining
781 AssertEquals('LogicPosIsAtChar 6 C', False,tb.LogicPosIsAtChar('aüb'#$CC#$81'c', 6, [lpStopAtCodePoint])); // mid Combining
782 AssertEquals('LogicPosIsAtChar 7 C', True, tb.LogicPosIsAtChar('aüb'#$CC#$81'c', 7, [lpStopAtCodePoint])); // c
783
784 // broken text
785 AssertEquals('LogicPosIsAtChar 1 Comb', True, tb.LogicPosIsAtChar(#$CC#$81'c', 1, []));
786 AssertEquals('LogicPosIsAtChar 1 Comb C', True, tb.LogicPosIsAtChar(#$CC#$81'c', 1, [lpStopAtCodePoint]));
787
788
789 AssertEquals('LogicPosAdjustToChar 1 ', 1, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 1)); // a
790 AssertEquals('LogicPosAdjustToChar 2 ', 2, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 2)); // ü
791 AssertEquals('LogicPosAdjustToChar 3 ', 2, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 3)); // mid ü
792 AssertEquals('LogicPosAdjustToChar 4 ', 4, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 4)); // b
793 AssertEquals('LogicPosAdjustToChar 5 ', 4, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 5)); // AT Combining
794 AssertEquals('LogicPosAdjustToChar 6 ', 4, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 6)); // mid Combining
795 AssertEquals('LogicPosAdjustToChar 7 ', 7, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 7)); // c
796
797 AssertEquals('LogicPosAdjustToChar 1N ', 1, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 1, [lpAdjustToNext])); // a
798 AssertEquals('LogicPosAdjustToChar 2N ', 2, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 2, [lpAdjustToNext])); // ü
799 AssertEquals('LogicPosAdjustToChar 3N ', 4, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 3, [lpAdjustToNext])); // mid ü
800 AssertEquals('LogicPosAdjustToChar 4N ', 4, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 4, [lpAdjustToNext])); // b
801 AssertEquals('LogicPosAdjustToChar 5N ', 7, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 5, [lpAdjustToNext])); // AT Combining
802 AssertEquals('LogicPosAdjustToChar 6N ', 7, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 6, [lpAdjustToNext])); // mid Combining
803 AssertEquals('LogicPosAdjustToChar 7N ', 7, tb.LogicPosAdjustToChar('aüb'#$CC#$81'ü', 7, [lpAdjustToNext])); // ü
804 AssertEquals('LogicPosAdjustToChar 8N ', 7, tb.LogicPosAdjustToChar('aüb'#$CC#$81'ü', 8, [lpAdjustToNext])); // mid ü
805 AssertEquals('LogicPosAdjustToChar 8NE', 9, tb.LogicPosAdjustToChar('aüb'#$CC#$81'ü', 8, [lpAdjustToNext, lpAllowPastEol])); // mid ü
806
807 AssertEquals('LogicPosAdjustToChar 1 C', 1, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 1, [lpStopAtCodePoint])); // a
808 AssertEquals('LogicPosAdjustToChar 2 C', 2, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 2, [lpStopAtCodePoint])); // ü
809 AssertEquals('LogicPosAdjustToChar 3 C', 2, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 3, [lpStopAtCodePoint])); // mid ü
810 AssertEquals('LogicPosAdjustToChar 4 C', 4, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 4, [lpStopAtCodePoint])); // b
811 AssertEquals('LogicPosAdjustToChar 5 C', 5, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 5, [lpStopAtCodePoint])); // AT Combining
812 AssertEquals('LogicPosAdjustToChar 6 C', 5, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 6, [lpStopAtCodePoint])); // mid Combining
813 AssertEquals('LogicPosAdjustToChar 7 C', 7, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 7, [lpStopAtCodePoint])); // c
814
815 AssertEquals('LogicPosAdjustToChar 1N C', 1, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 1, [lpStopAtCodePoint, lpAdjustToNext])); // a
816 AssertEquals('LogicPosAdjustToChar 2N C', 2, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 2, [lpStopAtCodePoint, lpAdjustToNext])); // ü
817 AssertEquals('LogicPosAdjustToChar 3N C', 4, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 3, [lpStopAtCodePoint, lpAdjustToNext])); // mid ü
818 AssertEquals('LogicPosAdjustToChar 4N C', 4, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 4, [lpStopAtCodePoint, lpAdjustToNext])); // b
819 AssertEquals('LogicPosAdjustToChar 5N C', 5, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 5, [lpStopAtCodePoint, lpAdjustToNext])); // AT Combining
820 AssertEquals('LogicPosAdjustToChar 6N C', 7, tb.LogicPosAdjustToChar('aüb'#$CC#$81'c', 6, [lpStopAtCodePoint, lpAdjustToNext])); // mid Combining
821 AssertEquals('LogicPosAdjustToChar 7N C', 7, tb.LogicPosAdjustToChar('aüb'#$CC#$81'ü', 7, [lpStopAtCodePoint, lpAdjustToNext])); // ü
822 AssertEquals('LogicPosAdjustToChar 8N C', 7, tb.LogicPosAdjustToChar('aüb'#$CC#$81'ü', 8, [lpStopAtCodePoint, lpAdjustToNext])); // mid ü
823 AssertEquals('LogicPosAdjustToChar 8NE C', 9, tb.LogicPosAdjustToChar('aüb'#$CC#$81'ü', 8, [lpStopAtCodePoint, lpAdjustToNext, lpAllowPastEol])); // mid ü
824
825 // broken text
826 AssertEquals('LogicPosAdjustToChar 1 Comb', 1, tb.LogicPosAdjustToChar(#$CC#$81'c', 1, []));
827 AssertEquals('LogicPosAdjustToChar 2 Comb', 1, tb.LogicPosAdjustToChar(#$CC#$81'c', 2, []));
828 AssertEquals('LogicPosAdjustToChar 1 Comb N', 1, tb.LogicPosAdjustToChar(#$CC#$81'c', 1, [lpAdjustToNext]));
829 AssertEquals('LogicPosAdjustToChar 2 Comb N', 3, tb.LogicPosAdjustToChar(#$CC#$81'c', 2, [lpAdjustToNext]));
830 AssertEquals('LogicPosAdjustToChar 1 Comb', 1, tb.LogicPosAdjustToChar(#$CC#$81'c', 1, [lpStopAtCodePoint]));
831 AssertEquals('LogicPosAdjustToChar 2 Comb', 1, tb.LogicPosAdjustToChar(#$CC#$81'c', 2, [lpStopAtCodePoint]));
832 AssertEquals('LogicPosAdjustToChar 1 Comb N', 1, tb.LogicPosAdjustToChar(#$CC#$81'c', 1, [lpStopAtCodePoint, lpAdjustToNext]));
833 AssertEquals('LogicPosAdjustToChar 2 Comb N', 3, tb.LogicPosAdjustToChar(#$CC#$81'c', 2, [lpStopAtCodePoint, lpAdjustToNext]));
834
835
836 AssertEquals('LogicPosAddChars 1, 1 ', 2, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 1, 1)); // a
837 AssertEquals('LogicPosAddChars 2, 1 ', 4, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 2, 1)); // ü
838 AssertEquals('LogicPosAddChars 3, 1 ', 4, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 3, 1)); // mid ü
839 AssertEquals('LogicPosAddChars 4, 1 ', 7, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 4, 1)); // b
840 AssertEquals('LogicPosAddChars 5, 1 ', 7, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 5, 1)); // comb
841 AssertEquals('LogicPosAddChars 6, 1 ', 7, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 6, 1)); // mid
842 AssertEquals('LogicPosAddChars 7, 1 ', 8, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 7, 1)); // c
843 AssertEquals('LogicPosAddChars 8, 1 ',10, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 8, 1)); // ü
844 AssertEquals('LogicPosAddChars 9, 1 ',10, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 9, 1)); // mid ü
845 AssertEquals('LogicPosAddChars 10, 1 ',10, tb.LogicPosAddChars('aüb'#$CC#$81'cüü',10, 1)); // ü
846 AssertEquals('LogicPosAddChars 11, 1 ',10, tb.LogicPosAddChars('aüb'#$CC#$81'cüü',11, 1)); // mid ü
847 AssertEquals('LogicPosAddChars 10, 1 E',12, tb.LogicPosAddChars('aüb'#$CC#$81'cüü',10, 1, [lpAllowPastEol])); // ü
848 AssertEquals('LogicPosAddChars 11, 1 E',12, tb.LogicPosAddChars('aüb'#$CC#$81'cüü',11, 1, [lpAllowPastEol])); // mid ü
849
850 AssertEquals('LogicPosAddChars 1, 2 ', 4, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 1, 2)); // a
851 AssertEquals('LogicPosAddChars 2, 2 ', 7, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 2, 2)); // ü
852 AssertEquals('LogicPosAddChars 3, 2 ', 7, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 3, 2)); // mid ü
853 AssertEquals('LogicPosAddChars 4, 2 ', 8, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 4, 2)); // b
854 AssertEquals('LogicPosAddChars 5, 2 ', 8, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 5, 2)); // comb
855 AssertEquals('LogicPosAddChars 6, 2 ', 8, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 6, 2)); // mid
856 AssertEquals('LogicPosAddChars 7, 2 ',10, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 7, 2)); // c
857 AssertEquals('LogicPosAddChars 8, 2 ',10, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 8, 2)); // ü
858 AssertEquals('LogicPosAddChars 9, 2 ',10, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 9, 2)); // mid ü
859 AssertEquals('LogicPosAddChars 10, 2 ',10, tb.LogicPosAddChars('aüb'#$CC#$81'cüü',10, 2)); // ü
860 AssertEquals('LogicPosAddChars 11, 2 ',10, tb.LogicPosAddChars('aüb'#$CC#$81'cüü',11, 2)); // mid ü
861 AssertEquals('LogicPosAddChars 8, 2 E',12, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 8, 2, [lpAllowPastEol])); // ü
862 AssertEquals('LogicPosAddChars 9, 2 E',12, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 9, 2, [lpAllowPastEol])); // mid ü
863 AssertEquals('LogicPosAddChars 10, 2 E',13, tb.LogicPosAddChars('aüb'#$CC#$81'cüü',10, 2, [lpAllowPastEol])); // ü
864 AssertEquals('LogicPosAddChars 11, 2 E',13, tb.LogicPosAddChars('aüb'#$CC#$81'cüü',11, 2, [lpAllowPastEol])); // mid ü
865
866 AssertEquals('LogicPosAddChars 1, -1 ', 1, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 1, -1)); // a
867 AssertEquals('LogicPosAddChars 2, -1 ', 1, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 2, -1)); // ü
868 //AssertEquals('LogicPosAddChars 3, -1 ', 1, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 3, -1)); // mid ü
869 AssertEquals('LogicPosAddChars 4, -1 ', 2, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 4, -1)); // b
870 //AssertEquals('LogicPosAddChars 5, -1 ', 2, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 5, -1)); // comb
871 //AssertEquals('LogicPosAddChars 6, -1 ', 2, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 6, -1)); // mid
872 AssertEquals('LogicPosAddChars 7, -1 ', 4, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 7, -1)); // c
873 AssertEquals('LogicPosAddChars 8, -1 ', 7, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 8, -1)); // ü
874 //AssertEquals('LogicPosAddChars 9, -1 ', 7, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 9, -1)); // mid ü
875 AssertEquals('LogicPosAddChars 10, -1 ', 8, tb.LogicPosAddChars('aüb'#$CC#$81'cüü',10, -1)); // ü
876 //AssertEquals('LogicPosAddChars 11, -1 ', 8, tb.LogicPosAddChars('aüb'#$CC#$81'cüü',11, -1)); // mid ü
877
878 AssertEquals('LogicPosAddChars 1, -2 ', 1, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 1, -2)); // a
879 AssertEquals('LogicPosAddChars 2, -2 ', 1, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 2, -2)); // ü
880 //AssertEquals('LogicPosAddChars 3, -2 ', 1, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 3, -2)); // mid ü
881 AssertEquals('LogicPosAddChars 4, -2 ', 1, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 4, -2)); // b
882 //AssertEquals('LogicPosAddChars 5, -2 ', 1, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 5, -2)); // comb
883 //AssertEquals('LogicPosAddChars 6, -2 ', 1, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 6, -2)); // mid
884 AssertEquals('LogicPosAddChars 7, -2 ', 2, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 7, -2)); // c
885 AssertEquals('LogicPosAddChars 8, -2 ', 4, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 8, -2)); // ü
886 //AssertEquals('LogicPosAddChars 9, -2 ', 4, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 9, -2)); // mid ü
887 AssertEquals('LogicPosAddChars 10, -2 ', 7, tb.LogicPosAddChars('aüb'#$CC#$81'cüü',10, -2)); // ü
888 //AssertEquals('LogicPosAddChars 11, -2 ', 7, tb.LogicPosAddChars('aüb'#$CC#$81'cüü',11, -2)); // mid ü
889
890
891 AssertEquals('LogicPosAddChars 1, 1C ', 2, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 1, 1, [lpStopAtCodePoint])); // a
892 AssertEquals('LogicPosAddChars 2, 1C ', 4, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 2, 1, [lpStopAtCodePoint])); // ü
893 AssertEquals('LogicPosAddChars 3, 1C ', 4, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 3, 1, [lpStopAtCodePoint])); // mid ü
894 AssertEquals('LogicPosAddChars 4, 1C ', 5, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 4, 1, [lpStopAtCodePoint])); // b
895 AssertEquals('LogicPosAddChars 5, 1C ', 7, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 5, 1, [lpStopAtCodePoint])); // comb
896 AssertEquals('LogicPosAddChars 6, 1C ', 7, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 6, 1, [lpStopAtCodePoint])); // mid
897 AssertEquals('LogicPosAddChars 7, 1C ', 8, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 7, 1, [lpStopAtCodePoint])); // c
898 AssertEquals('LogicPosAddChars 8, 1C ',10, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 8, 1, [lpStopAtCodePoint])); // ü
899 AssertEquals('LogicPosAddChars 9, 1C ',10, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 9, 1, [lpStopAtCodePoint])); // mid ü
900 AssertEquals('LogicPosAddChars 10, 1C ',10, tb.LogicPosAddChars('aüb'#$CC#$81'cüü',10, 1, [lpStopAtCodePoint])); // ü
901 AssertEquals('LogicPosAddChars 11, 1C ',10, tb.LogicPosAddChars('aüb'#$CC#$81'cüü',11, 1, [lpStopAtCodePoint])); // mid ü
902 AssertEquals('LogicPosAddChars 10, 1C E',12, tb.LogicPosAddChars('aüb'#$CC#$81'cüü',10, 1, [lpAllowPastEol, lpStopAtCodePoint])); // ü
903 AssertEquals('LogicPosAddChars 11, 1C E',12, tb.LogicPosAddChars('aüb'#$CC#$81'cüü',11, 1, [lpAllowPastEol, lpStopAtCodePoint])); // mid ü
904
905 AssertEquals('LogicPosAddChars 1, 2C ', 4, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 1, 2, [lpStopAtCodePoint])); // a
906 AssertEquals('LogicPosAddChars 2, 2C ', 5, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 2, 2, [lpStopAtCodePoint])); // ü
907 AssertEquals('LogicPosAddChars 3, 2C ', 5, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 3, 2, [lpStopAtCodePoint])); // mid ü
908 AssertEquals('LogicPosAddChars 4, 2C ', 7, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 4, 2, [lpStopAtCodePoint])); // b
909 AssertEquals('LogicPosAddChars 5, 2C ', 8, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 5, 2, [lpStopAtCodePoint])); // comb
910 AssertEquals('LogicPosAddChars 6, 2C ', 8, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 6, 2, [lpStopAtCodePoint])); // mid
911 AssertEquals('LogicPosAddChars 7, 2C ',10, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 7, 2, [lpStopAtCodePoint])); // c
912 AssertEquals('LogicPosAddChars 8, 2C ',10, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 8, 2, [lpStopAtCodePoint])); // ü
913 AssertEquals('LogicPosAddChars 9, 2C ',10, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 9, 2, [lpStopAtCodePoint])); // mid ü
914 AssertEquals('LogicPosAddChars 10, 2C ',10, tb.LogicPosAddChars('aüb'#$CC#$81'cüü',10, 2, [lpStopAtCodePoint])); // ü
915 AssertEquals('LogicPosAddChars 11, 2C ',10, tb.LogicPosAddChars('aüb'#$CC#$81'cüü',11, 2, [lpStopAtCodePoint])); // mid ü
916 AssertEquals('LogicPosAddChars 8, 2C E',12, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 8, 2, [lpAllowPastEol, lpStopAtCodePoint])); // ü
917 AssertEquals('LogicPosAddChars 9, 2C E',12, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 9, 2, [lpAllowPastEol, lpStopAtCodePoint])); // mid ü
918 AssertEquals('LogicPosAddChars 10, 2C E',13, tb.LogicPosAddChars('aüb'#$CC#$81'cüü',10, 2, [lpAllowPastEol, lpStopAtCodePoint])); // ü
919 AssertEquals('LogicPosAddChars 11, 2C E',13, tb.LogicPosAddChars('aüb'#$CC#$81'cüü',11, 2, [lpAllowPastEol, lpStopAtCodePoint])); // mid ü
920
921 AssertEquals('LogicPosAddChars 1, -1C ', 1, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 1, -1, [lpStopAtCodePoint])); // a
922 AssertEquals('LogicPosAddChars 2, -1C ', 1, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 2, -1, [lpStopAtCodePoint])); // ü
923 //AssertEquals('LogicPosAddChars 3, -1C ', 1, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 3, -1, [lpStopAtCodePoint])); // mid ü
924 AssertEquals('LogicPosAddChars 4, -1C ', 2, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 4, -1, [lpStopAtCodePoint])); // b
925 AssertEquals('LogicPosAddChars 5, -1C ', 4, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 5, -1, [lpStopAtCodePoint])); // comb
926 //AssertEquals('LogicPosAddChars 6, -1C ', 4, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 6, -1, [lpStopAtCodePoint])); // mid
927 AssertEquals('LogicPosAddChars 7, -1C ', 5, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 7, -1, [lpStopAtCodePoint])); // c
928 AssertEquals('LogicPosAddChars 8, -1C ', 7, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 8, -1, [lpStopAtCodePoint])); // ü
929 //AssertEquals('LogicPosAddChars 9, -1C ', 7, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 9, -1, [lpStopAtCodePoint])); // mid ü
930 AssertEquals('LogicPosAddChars 10, -1C ', 8, tb.LogicPosAddChars('aüb'#$CC#$81'cüü',10, -1, [lpStopAtCodePoint])); // ü
931 //AssertEquals('LogicPosAddChars 11, -1C ', 8, tb.LogicPosAddChars('aüb'#$CC#$81'cüü',11, -1, [lpStopAtCodePoint])); // mid ü
932
933 AssertEquals('LogicPosAddChars 1, -2C ', 1, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 1, -2, [lpStopAtCodePoint])); // a
934 AssertEquals('LogicPosAddChars 2, -2C ', 1, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 2, -2, [lpStopAtCodePoint])); // ü
935 //AssertEquals('LogicPosAddChars 3, -2C ', 1, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 3, -2, [lpStopAtCodePoint])); // mid ü
936 AssertEquals('LogicPosAddChars 4, -2C ', 1, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 4, -2, [lpStopAtCodePoint])); // b
937 AssertEquals('LogicPosAddChars 5, -2C ', 2, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 5, -2, [lpStopAtCodePoint])); // comb
938 //AssertEquals('LogicPosAddChars 6, -2C ', 2, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 6, -2, [lpStopAtCodePoint])); // mid
939 AssertEquals('LogicPosAddChars 7, -2C ', 4, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 7, -2, [lpStopAtCodePoint])); // c
940 AssertEquals('LogicPosAddChars 8, -2C ', 5, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 8, -2, [lpStopAtCodePoint])); // ü
941 //AssertEquals('LogicPosAddChars 9, -2C ', 5, tb.LogicPosAddChars('aüb'#$CC#$81'cüü', 9, -2, [lpStopAtCodePoint])); // mid ü
942 AssertEquals('LogicPosAddChars 10, -2C ', 7, tb.LogicPosAddChars('aüb'#$CC#$81'cüü',10, -2, [lpStopAtCodePoint])); // ü
943 //AssertEquals('LogicPosAddChars 11, -2C ', 7, tb.LogicPosAddChars('aüb'#$CC#$81'cüü',11, -2, [lpStopAtCodePoint])); // mid ü
944
945
946
947 end;
948
949 procedure TTestBasicSynEdit.TestCaretObject;
950 var
951 TestCaret, TestCaret2: TSynEditCaret;
952 TestOrder: Integer;
953 UseAdjustToNextChar, UseIncAdjustToNextChar: Boolean;
954 UseAllowPastEOL, UseIncAllowPastEOL: Boolean;
955 UseKeepCaretX: Boolean;
956 UseLock: Boolean;
957 UseChangeOnTouch: Boolean;
958 UseIncAutoMoveOnEdit: Boolean;
959 UseSkipTabs: Boolean;
960 UseMaxLeft: Boolean;
961
962
963 procedure CheckPhys(AName: String; ExpY, ExpX: Integer);
964 procedure CheckEach;
965 begin
966 AssertEquals(AName + 'Phys.Y', ExpY, TestCaret.LinePos);
967 AssertEquals(AName + 'Phys.X', ExpX, TestCaret.CharPos);
968 end;
969 procedure CheckPoint;
970 begin
971 AssertEquals(AName + 'Phys.XY.Y', ExpY, TestCaret.LineCharPos.Y);
972 AssertEquals(AName + 'Phys.XY.X', ExpX, TestCaret.LineCharPos.x);
973 end;
974 begin
975 if ExpX <= 0 then exit;
976 AName := BaseTestName + ' ' + AName;
977 if (TestOrder and 1) = 0 then begin
978 CheckEach;
979 CheckPoint;
980 end else begin
981 CheckPoint;
982 CheckEach;
983 end;
984 end;
985 procedure CheckIsAtChar(AName: String; ExpY, ExpX: Integer);
986 begin
987 if ExpX <= 0 then exit;
988 AName := BaseTestName + ' ' + AName;
989 if (TestOrder and 1) = 1 then exit; // Only one order
990 AssertEquals(AName + 'IsAtLineChar', True, TestCaret.IsAtLineChar(point(ExpX, ExpY)));
991 AssertEquals(AName + 'NOT IsAtLineChar', False, TestCaret.IsAtLineChar(point(ExpX+1, ExpY)));
992 end;
993
994 procedure CheckLog(AName: String; ExpY, ExpX, ExpOffs: Integer);
995 procedure CheckEach;
996 begin
997 AssertEquals(AName + 'Log.Y', ExpY, TestCaret.LinePos);
998 AssertEquals(AName + 'Log.X', ExpX, TestCaret.BytePos);
999 AssertEquals(AName + 'Log.Offs', ExpOffs, TestCaret.BytePosOffset);
1000 end;
1001 procedure CheckPoint;
1002 begin
1003 AssertEquals(AName + 'Log.XY.Y', ExpY, TestCaret.LineBytePos.y);
1004 AssertEquals(AName + 'Log.XY.X', ExpX, TestCaret.LineBytePos.x);
1005 end;
1006 begin
1007 if ExpX <= 0 then exit;
1008 AName := BaseTestName + ' ' + AName;
1009 AName := BaseTestName + ' ' + AName;
1010 if (TestOrder and 1) = 0 then begin
1011 CheckEach;
1012 CheckPoint;
1013 end else begin
1014 CheckPoint;
1015 CheckEach;
1016 end;
1017 end;
1018 procedure CheckIsAtByte(AName: String; ExpY, ExpX, ExpOffs: Integer);
1019 begin
1020 if ExpX <= 0 then exit;
1021 AName := BaseTestName + ' ' + AName;
1022 if (TestOrder and 1) = 1 then exit; // Only one order
1023 AssertEquals(AName + 'IsAtLineChar', True, TestCaret.IsAtLineByte(point(ExpX, ExpY), ExpOffs));
1024 AssertEquals(AName + 'NOT IsAtLineByte', False, TestCaret.IsAtLineByte(point(ExpX+1, ExpY), ExpOffs));
1025 if ExpOffs = 0 then begin
1026 AssertEquals(AName + 'IsAtLineChar', True, TestCaret.IsAtLineByte(point(ExpX, ExpY)));
1027 AssertEquals(AName + 'NOT IsAtLineByte', False, TestCaret.IsAtLineByte(point(ExpX+1, ExpY)));
1028 AssertEquals(AName + 'NOT IsAtLineByte', False, TestCaret.IsAtLineByte(point(ExpX, ExpY), 1));
1029 end;
1030 end;
1031
1032
1033 procedure CheckLogPhys(AName: String; ExpY, ExpX, ExpLogX, ExpOffs: Integer);
1034 procedure CheckAtPos;
1035 procedure CheckAtPosChar;
1036 begin
1037 TestCaret2.LineBytePos := point(1, 1);
1038 TestCaret2.LineCharPos := point(ExpX, ExpY);
1039 AssertTrue(AName + 'IsAtPos(Char)', TestCaret.IsAtPos(TestCaret2));
1040 TestCaret2.LineCharPos := point(1, ExpY-1);
1041 AssertFalse(AName + 'not IsAtPos(Char)', TestCaret.IsAtPos(TestCaret2));
1042 end;
1043 procedure CheckAtPosByte;
1044 begin
1045 TestCaret2.LineCharPos := point(1, 1);
1046 TestCaret2.LineBytePos := point(ExpLogX, ExpY);
1047 //TestCaret2.BytePosOffset := ExpOffs;
1048 if ExpOffs = 0 then // TODO
1049 AssertTrue(AName + 'IsAtPos(Byte)', TestCaret.IsAtPos(TestCaret2));
1050 TestCaret2.LineBytePos := point(1, ExpY-1);
1051 AssertFalse(AName + 'not IsAtPos(Byte)', TestCaret.IsAtPos(TestCaret2));
1052 end;
1053 begin
1054 if ((TestOrder and 1) = 0) and (ExpX > 0) then CheckAtPosChar;
1055 if (ExpLogX > 0) then CheckAtPosByte;
1056 if ((TestOrder and 1) = 1) and (ExpX > 0) then CheckAtPosChar;
1057 end;
1058 procedure CheckPos;
1059 begin
1060 if (TestOrder and 2) = 0 then begin
1061 if ExpX > 0 then CheckPhys(AName, ExpY, ExpX);
1062 if ExpLogX > 0 then CheckLog (AName, ExpY, ExpLogX, ExpOffs);
1063 end else begin
1064 if ExpLogX > 0 then CheckLog (AName, ExpY, ExpLogX, ExpOffs);
1065 if ExpX > 0 then CheckPhys(AName, ExpY, ExpX);
1066 end;
1067 end;
1068 begin
1069 if (TestOrder and 8) = 8 then
1070 CheckAtPos;
1071
1072 if (TestOrder and 4) = 4 then
1073 CheckPos;
1074
1075 if (TestOrder and 2) = 2 then begin
1076 CheckIsAtChar(AName, ExpY, ExpX);
1077 CheckIsAtByte(AName, ExpY, ExpLogX, ExpOffs);
1078 end else begin
1079 CheckIsAtByte(AName, ExpY, ExpLogX, ExpOffs);
1080 CheckIsAtChar(AName, ExpY, ExpX);
1081 end;
1082
1083 if (TestOrder and 4) = 0 then
1084 CheckPos;
1085
1086 if (TestOrder and 8) = 0 then
1087 CheckAtPos;
1088 end;
1089
1090
1091 Procedure DoOneTest(AName: String; AY, AX, ALogX, ALogOffs: Integer;
1092 ExpY, ExpX, ExpLogX, ExpLogOffs: Integer;
1093 // X,LogX,LogOffs, [X,LogX,LogOffs]
1094 AMoveHorizNext: array of integer; AMoveHorizPrev: array of integer;
1095 ExpMoveHorizFalse: Boolean = False;
1096 ALineForKeepX: Integer = -1; ExpNotKeptX: Integer = -1; ExpNotKeptLogX: Integer = -1
1097 );
1098 procedure DoOneSetLine(Y: Integer);
1099 begin
1100 if UseLock then TestCaret.Lock;
1101 if UseChangeOnTouch then TestCaret.ChangeOnTouch;
1102 TestCaret.LinePos := Y;
1103 if UseLock then TestCaret.Unlock;
1104 end;
1105 procedure DoOneSetChar(Y, X: Integer; ChangeToLine: Integer = -1);
1106 begin
1107 if UseLock then TestCaret.Lock;
1108 if UseChangeOnTouch then TestCaret.ChangeOnTouch;
1109 TestCaret.LineCharPos := point(X, Y);
1110 if ChangeToLine > 0 then TestCaret.LinePos := ChangeToLine;
1111 if UseLock then TestCaret.Unlock;
1112 end;
1113 procedure DoOneSetByte(Y, X, {%H-}O: Integer; ChangeToLine: Integer = -1);
1114 begin
1115 if UseLock then TestCaret.Lock;
1116 if UseChangeOnTouch then TestCaret.ChangeOnTouch;
1117 TestCaret.LineBytePos := point(X, Y);
1118 //TestCaret.BytePosOffset := O;
1119 if ChangeToLine > 0 then TestCaret.LinePos := ChangeToLine;
1120 if UseLock then TestCaret.Unlock;
1121 end;
1122 procedure DoOneMoveHoriz(C: Integer);
1123 begin
1124 if UseLock then TestCaret.Lock;
1125 if UseChangeOnTouch then TestCaret.ChangeOnTouch;
1126 AssertEquals(AName + 'MoveHoriz is '+dbgs(ExpMoveHorizFalse), not ExpMoveHorizFalse, TestCaret.MoveHoriz(C));
1127 if UseLock then TestCaret.Unlock;
1128 end;
1129 procedure DoOneMoveHorizFromChar(C, Y, X: Integer);
1130 begin
1131 if UseLock then TestCaret.Lock;
1132 if UseChangeOnTouch then TestCaret.ChangeOnTouch;
1133 TestCaret.LineCharPos := point(X, Y);
1134 AssertEquals(AName + 'MoveHoriz is '+dbgs(ExpMoveHorizFalse), not ExpMoveHorizFalse, TestCaret.MoveHoriz(C));
1135 if UseLock then TestCaret.Unlock;
1136 end;
1137 procedure DoOneMoveHorizFromByte(C, Y, X, {%H-}O: Integer);
1138 begin
1139 if UseLock then TestCaret.Lock;
1140 if UseChangeOnTouch then TestCaret.ChangeOnTouch;
1141 TestCaret.LineBytePos := point(X, Y);
1142 //TestCaret.BytePosOffset := O;
1143 AssertEquals(AName + 'MoveHoriz is '+dbgs(ExpMoveHorizFalse), not ExpMoveHorizFalse, TestCaret.MoveHoriz(C));
1144 if UseLock then TestCaret.Unlock;
1145 end;
1146 begin
1147 DoOneSetChar(AY, AX);
1148 CheckLogPhys(AName + ' from CharPos', ExpY, ExpX, ExpLogX, ExpLogOffs);
1149
1150 // KeepX
1151 if (ALineForKeepX > 0) and UseKeepCaretX then begin
1152 if (TestOrder and 4) = 4 then begin
1153 TestCaret.LineCharPos := point(1, 1);
1154 if (TestOrder and 6) = 4 then
1155 TestCaret.LineCharPos := point(AX, AY);
1156 end;
1157
1158 if (TestOrder and 6) = 6
1159 then DoOneSetChar(AY, AX, ALineForKeepX)
1160 else DoOneSetLine(ALineForKeepX);
1161 CheckLogPhys(AName + ' from CharPos', ALineForKeepX, ExpNotKeptX, ExpNotKeptLogX, 0);
1162 if ExpNotKeptX < 0 then AssertFalse(AName + '(char) keepx moved (c)', ExpX = TestCaret.CharPos);
1163 if ExpNotKeptLogX < 0 then AssertFalse(AName + '(char) keepx moved (b)', ExpLogX = TestCaret.BytePos);
1164
1165 DoOneSetLine(AY);
1166 CheckLogPhys(AName + ' from CharPos', ExpY, ExpX, ExpLogX, ExpLogOffs);
1167 end;
1168
1169 if length(AMoveHorizNext) >= 3 then begin
1170 DoOneMoveHorizFromChar(1, AY, AX);
1171 CheckLogPhys(AName + ' from CharPos', ExpY, AMoveHorizNext[0], AMoveHorizNext[1], AMoveHorizNext[2]);
1172
1173 if not ExpMoveHorizFalse then begin
1174 DoOneMoveHoriz(-1);
1175 CheckLogPhys(AName + ' from CharPos', ExpY, ExpX, ExpLogX, ExpLogOffs);
1176 end;
1177 end;
1178 if length(AMoveHorizNext) >= 6 then begin
1179 TestCaret.LineCharPos := point(AX, AY);
1180 if UseLock then TestCaret.Lock;
1181 if UseChangeOnTouch then TestCaret.ChangeOnTouch;
1182 AssertEquals(AName + 'MoveHoriz is '+dbgs(ExpMoveHorizFalse), not ExpMoveHorizFalse, TestCaret.MoveHoriz(1));
1183 AssertEquals(AName + 'MoveHoriz is '+dbgs(ExpMoveHorizFalse), not ExpMoveHorizFalse, TestCaret.MoveHoriz(1));
1184 if UseLock then TestCaret.Unlock;
1185 CheckLogPhys(AName + ' from CharPos', ExpY, AMoveHorizNext[3], AMoveHorizNext[4], AMoveHorizNext[5]);
1186
1187 if not ExpMoveHorizFalse then begin
1188 DoOneMoveHoriz(-1);
1189 CheckLogPhys(AName + ' from CharPos', ExpY, AMoveHorizNext[0], AMoveHorizNext[1], AMoveHorizNext[2]);
1190 DoOneMoveHoriz(-1);
1191 CheckLogPhys(AName + ' from CharPos', ExpY, ExpX, ExpLogX, ExpLogOffs);
1192
1193 TestCaret.LineCharPos := point(AX, AY);
1194 DoOneMoveHoriz(2);
1195 CheckLogPhys(AName + ' from CharPos', ExpY, AMoveHorizNext[3], AMoveHorizNext[4], AMoveHorizNext[5]);
1196 end;
1197 end;
1198
1199 if length(AMoveHorizPrev) >= 3 then begin
1200 DoOneMoveHorizFromChar(-1, AY, AX);
1201 CheckLogPhys(AName + ' from CharPos', ExpY, AMoveHorizPrev[0], AMoveHorizPrev[1], AMoveHorizPrev[2]);
1202
1203 if not ExpMoveHorizFalse then begin
1204 DoOneMoveHoriz(1);
1205 CheckLogPhys(AName + ' from CharPos', ExpY, ExpX, ExpLogX, ExpLogOffs);
1206 end;
1207 end;
1208 if length(AMoveHorizPrev) >= 6 then begin
1209 TestCaret.LineCharPos := point(AX, AY);
1210 if UseLock then TestCaret.Lock;
1211 if UseChangeOnTouch then TestCaret.ChangeOnTouch;
1212 AssertEquals(AName + 'MoveHoriz is '+dbgs(ExpMoveHorizFalse), not ExpMoveHorizFalse, TestCaret.MoveHoriz(-1));
1213 AssertEquals(AName + 'MoveHoriz is '+dbgs(ExpMoveHorizFalse), not ExpMoveHorizFalse, TestCaret.MoveHoriz(-1));
1214 if UseLock then TestCaret.Unlock;
1215 CheckLogPhys(AName + ' from CharPos', ExpY, AMoveHorizPrev[3], AMoveHorizPrev[4], AMoveHorizPrev[5]);
1216
1217 if not ExpMoveHorizFalse then begin
1218 DoOneMoveHoriz(1);
1219 CheckLogPhys(AName + ' from CharPos', ExpY, AMoveHorizPrev[0], AMoveHorizPrev[1], AMoveHorizPrev[2]);
1220 DoOneMoveHoriz(1);
1221 CheckLogPhys(AName + ' from CharPos', ExpY, ExpX, ExpLogX, ExpLogOffs);
1222
1223 TestCaret.LineCharPos := point(AX, AY);
1224 DoOneMoveHoriz(-2);
1225 CheckLogPhys(AName + ' from CharPos', ExpY, AMoveHorizPrev[3], AMoveHorizPrev[4], AMoveHorizPrev[5]);
1226 end;
1227 end;
1228
1229
1230
1231 // Logical
1232 if ALogOffs <> 0 then exit; // TODO;
1233 if ALogX > 0 then begin
1234 DoOneSetByte(AY, ALogX, ALogOffs);
1235 CheckLogPhys(AName + ' from BytePos', ExpY, ExpX, ExpLogX, ExpLogOffs);
1236
1237 // KeepX
1238 if (ALineForKeepX > 0) and UseKeepCaretX then begin
1239 if (TestOrder and 4) = 4 then begin
1240 TestCaret.LineBytePos := point(1, 1);
1241 if (TestOrder and 6) = 4 then
1242 TestCaret.LineBytePos := point(ALogX, AY);
1243 end;
1244
1245 if (TestOrder and 6) = 6
1246 then DoOneSetByte(AY, ALogX, ALogOffs, ALineForKeepX)
1247 else DoOneSetLine(ALineForKeepX);
1248 CheckLogPhys(AName + ' from CharPos', ALineForKeepX, ExpNotKeptX, ExpNotKeptLogX, 0);
1249 if ExpNotKeptX < 0 then AssertFalse(AName + '(char) keepx moved (c)', ExpX = TestCaret.CharPos);
1250 if ExpNotKeptLogX < 0 then AssertFalse(AName + '(char) keepx moved (b)', ExpLogX = TestCaret.BytePos);
1251
1252 DoOneSetLine(AY);
1253 CheckLogPhys(AName + ' from CharPos', ExpY, ExpX, ExpLogX, ExpLogOffs);
1254 end;
1255
1256 if length(AMoveHorizNext) >= 3 then begin
1257 DoOneMoveHorizFromByte(1, AY, ALogX, ALogOffs);
1258 CheckLogPhys(AName + ' from CharPos', ExpY, AMoveHorizNext[0], AMoveHorizNext[1], AMoveHorizNext[2]);
1259
1260 if not ExpMoveHorizFalse then begin
1261 DoOneMoveHoriz(-1);
1262 CheckLogPhys(AName + ' from CharPos', ExpY, ExpX, ExpLogX, ExpLogOffs);
1263 end;
1264 end;
1265 if length(AMoveHorizNext) >= 6 then begin
1266 TestCaret.LineBytePos := point(ALogX, AY);
1267 if UseLock then TestCaret.Lock;
1268 if UseChangeOnTouch then TestCaret.ChangeOnTouch;
1269 TestCaret.MoveHoriz(1);
1270 TestCaret.MoveHoriz(1);
1271 if UseLock then TestCaret.Unlock;
1272 CheckLogPhys(AName + ' from CharPos', ExpY, AMoveHorizNext[3], AMoveHorizNext[4], AMoveHorizNext[5]);
1273
1274 if not ExpMoveHorizFalse then begin
1275 DoOneMoveHoriz(-1);
1276 CheckLogPhys(AName + ' from CharPos', ExpY, AMoveHorizNext[0], AMoveHorizNext[1], AMoveHorizNext[2]);
1277 DoOneMoveHoriz(-1);
1278 CheckLogPhys(AName + ' from CharPos', ExpY, ExpX, ExpLogX, ExpLogOffs);
1279
1280 TestCaret.LineBytePos := point(ALogX, AY);
1281 DoOneMoveHoriz(2);
1282 CheckLogPhys(AName + ' from CharPos', ExpY, AMoveHorizNext[3], AMoveHorizNext[4], AMoveHorizNext[5]);
1283 end;
1284 end;
1285
1286 if length(AMoveHorizPrev) >= 3 then begin
1287 DoOneMoveHorizFromByte(-1, AY, ALogX, ALogOffs);
1288 CheckLogPhys(AName + ' from CharPos', ExpY, AMoveHorizPrev[0], AMoveHorizPrev[1], AMoveHorizPrev[2]);
1289
1290 if not ExpMoveHorizFalse then begin
1291 DoOneMoveHoriz(1);
1292 CheckLogPhys(AName + ' from CharPos', ExpY, ExpX, ExpLogX, ExpLogOffs);
1293 end;
1294 end;
1295 if length(AMoveHorizPrev) >= 6 then begin
1296 TestCaret.LineBytePos := point(ALogX, AY);
1297 if UseLock then TestCaret.Lock;
1298 if UseChangeOnTouch then TestCaret.ChangeOnTouch;
1299 TestCaret.MoveHoriz(-1);
1300 TestCaret.MoveHoriz(-1);
1301 if UseLock then TestCaret.Unlock;
1302 CheckLogPhys(AName + ' from CharPos', ExpY, AMoveHorizPrev[3], AMoveHorizPrev[4], AMoveHorizPrev[5]);
1303
1304 if not ExpMoveHorizFalse then begin
1305 DoOneMoveHoriz(1);
1306 CheckLogPhys(AName + ' from CharPos', ExpY, AMoveHorizPrev[0], AMoveHorizPrev[1], AMoveHorizPrev[2]);
1307 DoOneMoveHoriz(1);
1308 CheckLogPhys(AName + ' from CharPos', ExpY, ExpX, ExpLogX, ExpLogOffs);
1309
1310 TestCaret.LineBytePos := point(ALogX, AY);
1311 DoOneMoveHoriz(-2);
1312 CheckLogPhys(AName + ' from CharPos', ExpY, AMoveHorizPrev[3], AMoveHorizPrev[4], AMoveHorizPrev[5]);
1313 end;
1314 end;
1315
1316 end;
1317
1318 end;
1319
1320 procedure DoTests;
1321 begin
1322 if (TestOrder >= 4) and (UseIncAllowPastEOL or UseIncAdjustToNextChar) then
1323 exit;
1324
1325 ReCreateEdit;
1326 SynEdit.TabWidth := 6;
1327 SetLines(['x',
1328 StringOfChar('x', 40),
1329 ' äääbc', // EOL = 7, 10
1330 'X嗚呼あ嗚呼嗚呼あ嗚呼嗚呼あ嗚呼嗚呼あ',
1331 '嗚呼嗚呼あ嗚呼嗚呼あ嗚呼嗚呼あ嗚呼嗚呼あ',
1332 ' '#9#9#9'mn',
1333 '',
1334 'X ab',
1335 '']);
1336 try
1337 PushBaseName(Format('UseLock=%s, AdjustToNextChar=%s, IncAdjustToNextChar=%s,'+
1338 ' AllowPastEOL=%s, IncAllowPastEOL=%s, KeepCaretX=%s,' +
1339 ' ChangeOnTouch=%s, IncAutoMoveOnEdit=%s, SkipTabs=%s' +
1340 ' MaxLeft=%s',
1341 [dbgs(UseLock), dbgs(UseAdjustToNextChar), dbgs(UseIncAdjustToNextChar),
1342 dbgs(UseAllowPastEOL), dbgs(UseIncAllowPastEOL),
1343 dbgs(UseKeepCaretX), dbgs(UseChangeOnTouch),
1344 dbgs(UseIncAutoMoveOnEdit), dbgs(UseSkipTabs), dbgs(UseMaxLeft)
1345 ]));
1346
1347 //debugln(BaseTestName);
1348
1349 TestCaret := TSynEditCaret.Create;
1350 TestCaret.Lines := SynEdit.ViewedTextBuffer;
1351
1352 TestCaret.AdjustToNextChar := UseAdjustToNextChar;
1353 if UseIncAdjustToNextChar then TestCaret.IncForceAdjustToNextChar;
1354
1355 TestCaret.AllowPastEOL := UseAllowPastEOL;
1356 if UseIncAllowPastEOL then TestCaret.IncForcePastEOL;
1357
1358 TestCaret.KeepCaretX := UseKeepCaretX;
1359 if UseIncAutoMoveOnEdit then TestCaret.IncAutoMoveOnEdit;
1360 TestCaret.SkipTabs := UseSkipTabs;
1361 if UseMaxLeft then
1362 TestCaret.MaxLeftChar := @TestMaxLeftProc; // 6000
1363
1364 TestCaret2 := TSynEditCaret.Create;
1365 TestCaret2.Lines := SynEdit.ViewedTextBuffer;
1366
1367
1368
1369 if UseAdjustToNextChar or UseIncAdjustToNextChar
1370 then DoOneTest('Basic', 2, 3, 3, 0, 2, 3, 3, 0,
1371 [4,4,0, 5,5,0], [2,2,0, 1,1,0], False, // MoveHoriz
1372 4, 4, 5 // KeepX
1373 )
1374 else DoOneTest('Basic', 2, 3, 3, 0, 2, 3, 3, 0,
1375 [4,4,0, 5,5,0], [2,2,0, 1,1,0], False, // MoveHoriz
1376 4, 2, 2 // KeepX
1377 );
1378
1379 // past EOL
1380 if UseAllowPastEOL or UseIncAllowPastEOL
1381 then DoOneTest('past EOL', 8, 9, 9, 0, 8, 9, 9, 0,
1382 [10,10,0], [8,8,0])
1383 else DoOneTest('past EOL', 8, 9, 9, 0, 8, 5, 5, 0,
1384 [5,5,0, 5,5,0],[], True);
1385 // BOL
1386 DoOneTest('at BOL', 8, 1, 1, 0, 8, 1, 1, 0,
1387 [],[1,1,0, 1,1,0], True);
1388
1389 // one past EOL
1390 if UseAllowPastEOL or UseIncAllowPastEOL
1391 then DoOneTest('one past EOL', 3, 8,11, 0, 3, 8,11, 0,
1392 [ 9,12,0, 10,13,0], [7,10,0, 6,9,0])
1393 else DoOneTest('one past EOL', 3, 8,11, 0, 3, 7,10, 0,
1394 [7,10,0, 7,10,0], [], True);
1395
1396 // MaxLeftChar 6000 (5999 char / EOL = 6000)
1397 if UseAllowPastEOL or UseIncAllowPastEOL
1398 then if UseMaxLeft
1399 then DoOneTest('past EOL', 3, 6001, 6004, 0, 3, 6000, 6003, 0,
1400 [6000, 6003, 0], [], True)
1401 else DoOneTest('past EOL', 3, 6001, 6004, 0, 3, 6001, 6004, 0,
1402 [], [])
1403 else DoOneTest('past EOL', 3, 6001, 6004, 0, 3, 7,10, 0,
1404 [],[]
1405 );
1406
1407
1408 // ' äääbc'
1409 if UseAdjustToNextChar or UseIncAdjustToNextChar
1410 then DoOneTest('LogPhys', 3, 4, 6, 0, 3, 4, 6, 0,
1411 [5,8,0, 6,9,0], [3,4,0, 2,2,0], False,
1412 5, 5, 7
1413 )
1414 else DoOneTest('LogPhys', 3, 4, 6, 0, 3, 4, 6, 0,
1415 [5,8,0, 6,9,0], [3,4,0, 2,2,0], False,
1416 5, 3, 4
1417 );
1418
1419 // 'X嗚呼あ' // skip "from byte"
1420 if UseAdjustToNextChar or UseIncAdjustToNextChar
1421 then DoOneTest('Mid Dbl-Width', 4, 3, -3, 0, 4, 4, 5, 0,
1422 [6,8,0], [2,2,0], False,
1423 5, 5, 7
1424 )
1425 else DoOneTest('Mid Dbl-Width', 4, 3, -3, 0, 4, 2, 2, 0,
1426 [4,5,0], [1,1,0], False,
1427 5, 1, 1
1428 );
1429
1430 // ' '#9#9#9'mn' // skip "from byte" TODO
1431 if UseSkipTabs
1432 then if UseAdjustToNextChar or UseIncAdjustToNextChar
1433 then DoOneTest('Mid Tab', 6, 8, -3, 1, 6,13, 4, 0,
1434 [19,5,0, 20,6,0], [7,3,0, 2,2,0], False
1435 //7,1,1
1436 )
1437 else if UseAllowPastEOL or UseIncAllowPastEOL
1438 then DoOneTest('Mid Tab', 6, 8, -3, 1, 6, 7, 3, 0,
1439 [13,4,0, 19,5,0], [2,2,0, 1,1,0], False
1440 )
1441 else DoOneTest('Mid Tab', 6, 8, -3, 1, 6, 7, 3, 0,
1442 [13,4,0, 19,5,0], [2,2,0, 1,1,0], False,
1443 7,1,1
1444 )
1445 else if UseAllowPastEOL or UseIncAllowPastEOL
1446 then DoOneTest('Mid Tab', 6, 8, -3, 1, 6, 8, 3, 1,
1447 [9,3,2, 10,3,3], [7,3,0, 6,2,4], False
1448 )
1449 else DoOneTest('Mid Tab', 6, 8, -3, 1, 6, 8, 3, 1,
1450 [9,3,2, 10,3,3], [7,3,0, 6,2,4], False,
1451 7,1,1
1452 );
1453
1454
1455
1456 finally
1457 PopBaseName;
1458 FreeAndNil(TestCaret);
1459 FreeAndNil(TestCaret2);
1460 end;
1461 end;
1462
1463 begin
1464 for TestOrder := 0 to 11 do // CheckAtPos (8) only runs first 4
1465 for UseLock := low(Boolean) to high(Boolean) do
1466 for UseAdjustToNextChar := low(Boolean) to high(Boolean) do
1467 for UseIncAdjustToNextChar := low(Boolean) to high(Boolean) do
1468 for UseAllowPastEOL := low(Boolean) to high(Boolean) do
1469 for UseIncAllowPastEOL := low(Boolean) to high(Boolean) do
1470 for UseKeepCaretX := low(Boolean) to high(Boolean) do
1471 for UseChangeOnTouch := low(Boolean) to high(Boolean) do
1472 for UseIncAutoMoveOnEdit := low(Boolean) to high(Boolean) do
1473 for UseSkipTabs := low(Boolean) to high(Boolean) do
1474 for UseMaxLeft := low(Boolean) to high(Boolean) do
1475 // OldPos, MoveHoriz
1476 // IsAtPos /
1477 DoTests;
1478
1479 end;
1480
1481 procedure TTestBasicSynEdit.TestCaretAutoMove;
1482
1483 procedure DoTest(name: string; y, x, insertY, insertX, InsertY2, InsertX2: integer;
1484 txt: string; expY, expX: Integer);
1485 begin
1486 name := name + ' y='+inttostr(y)+' x='+inttostr(x);
1487 if y > 0 then begin
1488 ReCreateEdit;
1489 SynEdit.TabWidth := 6;
1490 SetLines(['x', 'abc', ' ääX', #9'mn', 'abc'#9'de', #9'Xää.']);
1491 SynEdit.CaretXY := Point(x, y);
1492 end;
1493
1494 SynEdit.TextBetweenPointsEx[Point(insertX, insertY), point(insertX2, InsertY2), scamAdjust]
1495 := txt;
1496 debugln(dbgstr(SynEdit.Text));
1497 TestIsCaretPhys(name, expX, expY);
1498 end;
1499
1500 const
1501 cr = LineEnding;
1502 begin
1503
1504
1505 DoTest('simple insert', 2,2, 2,1, 2,1, 'X', 2,3);
1506 DoTest('simple insert CR', 2,2, 2,1, 2,1, 'X'+cr, 3,2);
1507 DoTest('simple insert CR+', 2,2, 2,1, 2,1, cr+'X', 3,3);
1508 DoTest('simple delete', 2,2, 2,1, 2,2, '', 2,1);
1509 DoTest('simple delete CR', 2,2, 1,2, 2,1, '', 1,3);
1510 DoTest('+simple delete CR', 2,2, 1,1, 2,1, '', 1,2);
1511
1512 DoTest('simple insert (eol)', 2,4, 2,1, 2,1, 'X', 2,5);
1513 DoTest('simple insert (past eol)', 2,7, 2,1, 2,1, 'X', 2,8);
1514
1515 DoTest('insert with tab', 4,8, 4,1, 4,1, 'X', 4,8);
1516 DoTest('insert with tab (cont)', -4,8, 4,2, 4,2, 'Y', 4,8);
1517 DoTest('insert with tab (cont)', -4,8, 4,3, 4,3, 'abc', 4,8);
1518 DoTest('insert with tab (cont)', -4,8, 4,6, 4,6, 'Z', 4,14);
1519 DoTest('insert with tab (cont)', -4,8, 4,7, 4,7, '.', 4,14);
1520 DoTest('delete with tab (cont)', -4,8, 4,1, 4,2, '', 4,14);
1521 DoTest('delete with tab (cont)', -4,8, 4,1, 4,2, '', 4,8);
1522 DoTest('delete with tab (cont)', -4,8, 4,1, 4,2, '', 4,8);
1523 DoTest('delete with tab (cont)', -4,8, 4,1, 4,2, '', 4,8);
1524
1525
1526 SynEdit.CaretObj.IncAutoMoveOnEdit;
1527 DoTest('insert with tab (am-block)', 4,8, 4,1, 4,1, 'X', 4,8);
1528 DoTest('insert with tab (am-block) (cont)', -4,8, 4,2, 4,2, 'Y', 4,8);
1529 DoTest('insert with tab (am-block) (cont)', -4,8, 4,3, 4,3, 'abc', 4,8);
1530 DoTest('insert with tab (am-block) (cont)', -4,8, 4,6, 4,6, 'Z', 4,14);
1531 DoTest('insert with tab (am-block) (cont)', -4,8, 4,7, 4,7, '.', 4,14);
1532 DoTest('delete with tab (cont)', -4,8, 4,1, 4,2, '', 4,14);
1533 DoTest('delete with tab (cont)', -4,8, 4,1, 4,2, '', 4,8);
1534 DoTest('delete with tab (cont)', -4,8, 4,1, 4,2, '', 4,8);
1535 DoTest('delete with tab (cont)', -4,8, 4,1, 4,2, '', 4,8);
1536 SynEdit.CaretObj.DecAutoMoveOnEdit;
1537
1538 end;
1539
1540 procedure TTestBasicSynEdit.TestCaretEcDeleteWord;
1541 begin
1542 FDoInit := @DoInit1;
1543 FTestLines := @TestLines1;
1544 FTestCommand := ecDeleteWord;
1545 AllowPastEOL := True;
1546 PushBaseName('ecDeleteWord');
1547
1548 // if in middle of word, keep spaces after
1549 TestCommand('simple "te|xt"', 8, 1, 8, 1, [1,'Some te to test'],
1550 8, 1, [1,'Some teto test']);
1551 // if at end of word, just del spaces after
1552 TestCommand('simple EOW "text|"', 10, 1, 10, 1, [1,'Some textto test'],
1553 10, 1, [1,'Some text test']);
1554 // if at start of word, do NOT keep spaces after
1555 TestCommand('simple BOW "|text"', 6, 1, 6, 1, [1,'Some to test'],
1556 6, 1, [1,'Some test']);
1557 TestCommand('simple EOT "li|ne"', 10,15, 10,15, [15,'normal li'],
1558 10,15, [15,'normal li']);
1559 TestCommand('simple > EOL, next line "te|st"', 16, 1, 16, 1, [1,'Some text to te'],
1560 16, 1, [1, 1,'Some text to teFoo bar abc']);
1561
1562 TestCommand('tab "li|ne"', 16, 3, 16, 3, [3, #9'Other li with tab'],
1563 16, 3, [3, #9'Other liwith tab']);
1564 TestCommand('tab EOW "line|"', 18, 3, 18, 3, [3, #9'Other linewith tab'],
1565 18, 3, [3, #9'Other line tab']);
1566 TestCommand('tab BOW "|line"', 14, 3, 14, 3, [3, #9'Other with tab'],
1567 14, 3, [3, #9'Other tab']);
1568 TestCommand('tab > EOL, next-line', 25, 3, 25, 3, [3, #9'Other line with t'],
1569 25, 3, [3, 3, #9'Other line with ttab'#9'in the middle']);
1570
1571 TestCommand('M-tab "t|ab"', 2, 4, 2, 4, [4, 't'#9'in the middle'],
1572 2, 4, [4, 'tin the middle']);
1573 TestCommand('M-tab "tab|"', 4, 4, 4, 4, [4, 'tabin the middle'],
1574 4, 4, [4, 'tab the middle']);
1575 TestCommand('M-tab > EOL, next-line-tab', 17, 4, 17, 4, [4, 'tab'#9'in the mi'],
1576 17, 4, [4, 4, 'tab'#9'in the mitab'#9' in the middle with space']);
1577
1578 //TestCommand('M-S-tab BOW "t|ab"', 2, 5, 9, 5,
1579 // 12, 5);
1580 //TestCommand('M-S-tab EOW "tab|"', 4, 5, 9, 5,
1581 // 12, 5);
1582 //TestCommand('M-S-tab BOW "|tab"', 1, 5, 9, 5,
1583 // 12, 5);
1584 //TestCommand('M-S-tab "tab#9| "', 5, 5, 9, 5,
1585 // 12, 5);
1586 //
1587 TestCommand('Umlaut "ää|ä"', 11, 6, 11, 6, [6, 'umlaute ää in text'],
1588 11, 6, [6, 'umlaute ääin text']);
1589 TestCommand('Umlaut EOW "äää|"', 12, 6, 12, 6, [6, 'umlaute äääin text'],
1590 12, 6, [6, 'umlaute äää text']);
1591 TestCommand('Umlaut BOW "|äää"', 9, 6, 9, 6, [6, 'umlaute in text'],
1592 9, 6, [6, 'umlaute text']);
1593 TestCommand('Umlaut "umlaute|"', 8, 6, 8, 6, [6, 'umlauteäää in text'],
1594 8, 6, [6, 'umlaute in text']);
1595 TestCommand('After Umlaut > EOL, next line', 18, 6, 18, 6, [6, 'umlaute äää in te'],
1596 18, 6, [6, 6, 'umlaute äää in te'+FTestLines()[6]]);
1597 // past eol
1598 TestCommand('Umlaut EOW "äää in text |"', 21, 6, 21, 6, [6, 6, 'umlaute äää in text normal line']);
1599
1600 //TestCommand('Before untrimmed > next', 12, 7, 4, 8,
1601 // 14, 8);
1602 //TestCommand('untrimmed > EOL, next', 30, 8, 35, 8,
1603 // 1, 9);
1604 //TestCommand('Before untrimmed tab > next', 12, 9, 8,10,
1605 // 15,10);
1606 //TestCommand('untrimmed tab > EOL, next', 24,10, 29,10,
1607 // 1,11);
1608 //
1609 //TestCommand('Before empty > next', 12,11, 1,12);
1610 //TestCommand('Before space empty > next', 12,13, 1,14,
1611 // 6, 14);
1612 end;
1613
1614 procedure TTestBasicSynEdit.TestCaretEcDeleteLastWord;
1615 begin
1616 FDoInit := @DoInit1;
1617 FTestLines := @TestLines1;
1618 FTestCommand := ecDeleteLastWord;
1619 AllowPastEOL := True;
1620 PushBaseName('ecDeleteLastWord');
1621
1622 TestCommand('simple "te|st"', 16, 1, 14, 1, [1,'Some text to st'],
1623 11, 1, [1,'Some text st']);
1624 TestCommand('simple EOW "test|"', 18, 1, 14, 1, [1,'Some text to '],
1625 11, 1, [1,'Some text ']);
1626 TestCommand('simple BOW "|test"', 14, 1, 11, 1, [1,'Some text test'],
1627 6, 1, [1,'Some test']);
1628 TestCommand('simple > BOT "So|me"', 3, 1, 1, 1, [1,'me text to test'],
1629 1, 1, [1,'me text to test']);
1630 TestCommand('simple > prev-line "F|oo"', 2, 2, 1, 2, [2,'oo bar abc'],
1631 18, 1, [1, 1, 'Some text to testoo bar abc']);
1632 TestCommand('simple > prev-line "|Foo"', 1, 2, 18, 1, [1, 1, 'Some text to testFoo bar abc'],
1633 14, 1, [1, 1, 'Some text to Foo bar abc']);
1634
1635 TestCommand('tab "wi|th"', 21, 3, 19, 3, [3, #9'Other line th tab'],
1636 14, 3, [3, #9'Other th tab']);
1637 TestCommand('tab EOW "with|"', 23, 3, 19, 3, [3, #9'Other line tab'],
1638 14, 3, [3, #9'Other tab']);
1639 TestCommand('tab BOW "|with"', 19, 3, 14, 3, [3, #9'Other with tab'],
1640 8, 3, [3, #9'with tab']);
1641 TestCommand('tab > prev-line "O|ther"', 9, 3, 8, 3, [3, #9'ther line with tab'],
1642 12, 2, [2, 2, 'Foo bar abcther line with tab']);
1643
1644 TestCommand('M-tab "i|n"', 9, 4, 8, 4, [4, 'tab'#9'n the middle'],
1645 1, 4, [4, 'n the middle']);
1646 TestCommand('M-tab > prev-line-tab "ta|b"', 3, 4, 1, 4, [4, 'b'#9'in the middle'],
1647 27, 3, [3, 3, #9'Other line with tabb'#9'in the middle']);
1648
1649 //TestCommand('M-S-tab "i|n"', 10, 5, 9, 5,
1650 // 1, 5);
1651 //TestCommand('M-S-EOW tab "in|"', 11, 5, 9, 5,
1652 // 1, 5);
1653 //TestCommand('M-S-BOW tab "|in"', 9, 5, 1, 5,
1654 // 21, 4);
1655 //TestCommand('M-S-tab "#9| in"', 8, 5, 1, 5);
1656 //
1657 TestCommand('Umlaut "ää|ä"', 11, 6, 9, 6, [6, 'umlaute ä in text'],
1658 1, 6, [6, 'ä in text']);
1659 TestCommand('Umlaut EOW "äää|"', 12, 6, 9, 6, [6, 'umlaute in text'],
1660 1, 6, [6, ' in text']);
1661 TestCommand('Umlaut BOW "|äää"', 9, 6, 1, 6, [6, 'äää in text'],
1662 33, 5, [5, 5, FTestLines()[4]+'äää in text']);
1663 TestCommand('Umlaut "i|n"', 14, 6, 13, 6, [6, 'umlaute äää n text'],
1664 9, 6, [6, 'umlaute n text']);
1665 TestCommand('After Umlaut > prev line', 1, 7, 20, 6, [6, 6, 'umlaute äää in text'+FTestLines()[6]],
1666 16, 6, [6, 6, 'umlaute äää in '+FTestLines()[6]]);
1667
1668 //TestCommand('untrimmed "un|trimmed"', 6, 8, 4, 8,
1669 // 12, 7);
1670 //TestCommand('After untrimmed > prev', 1, 9, 35, 8,
1671 // 28, 8);
1672 //TestCommand('untrimmed tab "t|ab"', 9,10, 8,10,
1673 // 12, 9);
1674 //TestCommand('After untrimmed tab > prev', 1,11, 29,10,
1675 // 22,10);
1676 //
1677 //TestCommand('After empty > prev', 1,13, 1,12);
1678 //TestCommand('After space empty > prev', 1,15, 6,14);
1679 end;
1680
1681 procedure TTestBasicSynEdit.TestCaretEcDeleteEOL;
1682 begin
1683 FDoInit := @DoInit1;
1684 FTestLines := @TestLines1;
1685 FTestCommand := ecDeleteEOL;
1686 AllowPastEOL := True;
1687 PushBaseName('ecDeleteEOL');
1688
1689 TestCommand('simple "te|xt"', 8, 1, 8, 1, [1,'Some te']);
1690 // if at end of line
1691 TestCommand('simple EOL "text|"', 18, 1, 18, 1, []);
1692 // if at start of line
1693 TestCommand('simple BOL "|text"', 1, 1, 1, 1, [1,'']);
1694
1695 // utf8
1696 TestCommand('utf8 "te|xt"', 10, 6, 10, 6, [6,'umlaute ä']);
1697 // if at end of line
1698 TestCommand('utf8 EOL "text|"', 20, 6, 20, 6, []);
1699 // if at start of line
1700 TestCommand('utf8 BOL "|text"', 1, 6, 1, 6, [6,'']);
1701
1702 //tab
1703 TestCommand('tab "te|#9xt"', 11, 10, 11, 10, [10,#9'tab']);
1704 TestCommand('tab "te#9|xt"', 15, 10, 15, 10, [10,#9'tab'#9]);
1705 // if at end of line
1706 TestCommand('tab EOL "text|"', 29, 10, 29, 10, []);
1707 // if at start of line
1708 TestCommand('tab BOL "|text"', 1, 10, 1, 10, [10,'']);
1709
1710 end;
1711
1712 procedure TTestBasicSynEdit.TestWordBreaker;
1713 var
1714 WBrker: TSynWordBreaker;
1715 begin
1716 WBrker := TSynWordBreaker.Create;
1717 WBrker.IdentChars := ['a'..'z', 'A'..'Z', '0'..'9']; // not used
1718 WBrker.WhiteChars := [' ', #9];
1719 WBrker.WordBreakChars := [',', '.', '-', ';' ,':'];
1720
1721 AssertEquals('', True, WBrker.IsInWord('abc 123 ... aa', 1));
1722 AssertEquals('', True, WBrker.IsInWord('abc 123 ... aa', 2));
1723 AssertEquals('', True, WBrker.IsInWord('abc 123 ... aa', 3));
1724 AssertEquals('', True, WBrker.IsInWord('abc 123 ... aa', 4));
1725 AssertEquals('', False, WBrker.IsInWord('abc 123 ... aa', 5));
1726 AssertEquals('', True, WBrker.IsInWord('abc 123 ... aa', 6));
1727 AssertEquals('', True, WBrker.IsInWord('abc 123 ... aa', 7));
1728 AssertEquals('', True, WBrker.IsInWord('abc 123 ... aa', 9));
1729 AssertEquals('', False, WBrker.IsInWord('abc 123 ... aa', 10));
1730 AssertEquals('', False, WBrker.IsInWord('abc 123 ... aa', 11)); // before ...
1731 AssertEquals('', True, WBrker.IsInWord('abc 123 ... aa', 15)); // |aa
1732 AssertEquals('', True, WBrker.IsInWord('abc 123 ... aa', 17)); // at eol
1733 AssertEquals('', False, WBrker.IsInWord('abc 123 ... aa', 18));
1734 AssertEquals('', False, WBrker.IsInWord('abc 123 ... aa', 19));
1735 AssertEquals('', False, WBrker.IsInWord('abc 123 ... aa', 0));
1736 AssertEquals('', False, WBrker.IsInWord('abc 123 ... aa', -1));
1737 AssertEquals('', False, WBrker.IsInWord(' ', 1));
1738 AssertEquals('', False, WBrker.IsInWord(' ', 2));
1739 AssertEquals('', False, WBrker.IsInWord('', 1));
1740 AssertEquals('', False, WBrker.IsInWord('...', 1));
1741 AssertEquals('', False, WBrker.IsInWord('...', 2));
1742 AssertEquals('', False, WBrker.IsInWord('...', 4));
1743 AssertEquals('', False, WBrker.IsInWord('..aa', 2));
1744 AssertEquals('', True, WBrker.IsInWord('..aa', 3));
1745 AssertEquals('', True, WBrker.IsInWord('..aa', 4));
1746 AssertEquals('', True, WBrker.IsInWord('..aa', 5));
1747
1748
1749 AssertEquals('', True, WBrker.IsAtWordStart('abc 123 ... aa', 1));
1750 AssertEquals('', False, WBrker.IsAtWordStart('abc 123 ... aa', 2));
1751 AssertEquals('', False, WBrker.IsAtWordStart('abc 123 ... aa', 3));
1752 AssertEquals('', False, WBrker.IsAtWordStart('abc 123 ... aa', 4));
1753 AssertEquals('', False, WBrker.IsAtWordStart('abc 123 ... aa', 5));
1754 AssertEquals('', True, WBrker.IsAtWordStart('abc 123 ... aa', 6));
1755 AssertEquals('', False, WBrker.IsAtWordStart('abc 123 ... aa', 7));
1756 AssertEquals('', False, WBrker.IsAtWordStart('abc 123 ... aa', 9));
1757 AssertEquals('', False, WBrker.IsAtWordStart('abc 123 ... aa', 10));
1758 AssertEquals('', False, WBrker.IsAtWordStart('abc 123 ... aa', 11)); // before ...
1759 AssertEquals('', True, WBrker.IsAtWordStart('abc 123 ... aa', 15)); // |aa
1760 AssertEquals('', False, WBrker.IsAtWordStart('abc 123 ... aa', 17)); // at eol
1761 AssertEquals('', False, WBrker.IsAtWordStart('abc 123 ... aa', 18));
1762 AssertEquals('', False, WBrker.IsAtWordStart('abc 123 ... aa', 19));
1763 AssertEquals('', False, WBrker.IsAtWordStart('abc 123 ... aa', 0));
1764 AssertEquals('', False, WBrker.IsAtWordStart('abc 123 ... aa', -1));
1765 AssertEquals('', False, WBrker.IsAtWordStart(' ', 1));
1766 AssertEquals('', False, WBrker.IsAtWordStart('', 1));
1767 AssertEquals('', False, WBrker.IsAtWordStart(' ', 2));
1768 AssertEquals('', False, WBrker.IsAtWordStart('...', 1));
1769 AssertEquals('', True, WBrker.IsAtWordStart('..aa', 3));
1770
1771 AssertEquals('', False, WBrker.IsAtWordEnd('abc 123 ... aa', 1));
1772 AssertEquals('', False, WBrker.IsAtWordEnd('abc 123 ... aa', 2));
1773 AssertEquals('', False, WBrker.IsAtWordEnd('abc 123 ... aa', 3));
1774 AssertEquals('', True, WBrker.IsAtWordEnd('abc 123 ... aa', 4));
1775 AssertEquals('', False, WBrker.IsAtWordEnd('abc 123 ... aa', 5));
1776 AssertEquals('', False, WBrker.IsAtWordEnd('abc 123 ... aa', 6));
1777 AssertEquals('', False, WBrker.IsAtWordEnd('abc 123 ... aa', 7));
1778 AssertEquals('', True, WBrker.IsAtWordEnd('abc 123 ... aa', 9));
1779 AssertEquals('', False, WBrker.IsAtWordEnd('abc 123 ... aa', 10));
1780 AssertEquals('', False, WBrker.IsAtWordEnd('abc 123 ... aa', 11)); // before ...
1781 AssertEquals('', False, WBrker.IsAtWordEnd('abc 123 ... aa', 15)); // |aa
1782 AssertEquals('', True, WBrker.IsAtWordEnd('abc 123 ... aa', 17)); // at eol
1783 AssertEquals('', False, WBrker.IsAtWordEnd('abc 123 ... aa', 18));
1784 AssertEquals('', False, WBrker.IsAtWordEnd('abc 123 ... aa', 19));
1785 AssertEquals('', False, WBrker.IsAtWordEnd('abc 123 ... aa', 0));
1786 AssertEquals('', False, WBrker.IsAtWordEnd('abc 123 ... aa', -1));
1787 AssertEquals('', False, WBrker.IsAtWordEnd(' ', 1));
1788 AssertEquals('', False, WBrker.IsAtWordEnd(' ', 2));
1789 AssertEquals('', False, WBrker.IsAtWordEnd('', 1));
1790 AssertEquals('', False, WBrker.IsAtWordEnd('...', 1));
1791 AssertEquals('', False, WBrker.IsAtWordEnd('..aa', 3));
1792
1793 AssertEquals('', 6, WBrker.NextWordStart('abc 123 ... aa', 1, False));
1794 AssertEquals('', 6, WBrker.NextWordStart('abc 123 ... aa', 2, False));
1795 AssertEquals('', 6, WBrker.NextWordStart('abc 123 ... aa', 3, False));
1796 AssertEquals('', 6, WBrker.NextWordStart('abc 123 ... aa', 4, False)); // abc|
1797 AssertEquals('', 6, WBrker.NextWordStart('abc 123 ... aa', 5, False));
1798 AssertEquals('',15, WBrker.NextWordStart('abc 123 ... aa', 6, False)); // |123
1799 AssertEquals('',15, WBrker.NextWordStart('abc 123 ... aa', 7, False)); // 1|23
1800 AssertEquals('',15, WBrker.NextWordStart('abc 123 ... aa', 8, False));
1801 AssertEquals('',15, WBrker.NextWordStart('abc 123 ... aa', 9, False)); // 123|
1802 AssertEquals('',15, WBrker.NextWordStart('abc 123 ... aa', 10, False));
1803 AssertEquals('',15, WBrker.NextWordStart('abc 123 ... aa', 11, False)); // |...
1804 AssertEquals('',15, WBrker.NextWordStart('abc 123 ... aa', 12, False));
1805 AssertEquals('',15, WBrker.NextWordStart('abc 123 ... aa', 13, False));
1806 AssertEquals('',15, WBrker.NextWordStart('abc 123 ... aa', 14, False)); // ...|
1807 AssertEquals('',-1, WBrker.NextWordStart('abc 123 ... aa', 15, False));
1808 AssertEquals('',-1, WBrker.NextWordStart('abc 123 ... aa', 16, False));
1809 AssertEquals('',-1, WBrker.NextWordStart('abc 123 ... aa', 17, False)); // at eol
1810 AssertEquals('',-1, WBrker.NextWordStart('abc 123 ... aa', 18, False));
1811 AssertEquals('',-1, WBrker.NextWordStart('abc 123 ... aa', 19, False));
1812 AssertEquals('',-1, WBrker.NextWordStart('abc 123 ... aa', 0, False));
1813 AssertEquals('',-1, WBrker.NextWordStart('abc 123 ... aa', -1, False));
1814 AssertEquals('',-1, WBrker.NextWordStart('', 1, False));
1815 AssertEquals('',-1, WBrker.NextWordStart(' ', 1, False));
1816 AssertEquals('',-1, WBrker.NextWordStart(' ', 2, False));
1817 AssertEquals('',3, WBrker.NextWordStart('..aa', 1, False));
1818 AssertEquals('',3, WBrker.NextWordStart('..aa', 2, False));
1819 AssertEquals('',-1, WBrker.NextWordStart('..aa', 3, False));
1820 AssertEquals('',-1, WBrker.NextWordStart('..aa', 4, False));
1821 AssertEquals('', 3, WBrker.NextWordStart('a a 1', 1, False));
1822 AssertEquals('', 3, WBrker.NextWordStart('a a 1', 2, False));
1823 AssertEquals('', 5, WBrker.NextWordStart('a a 1', 3, False));
1824 AssertEquals('', 5, WBrker.NextWordStart('a a 1', 4, False));
1825 AssertEquals('',-1, WBrker.NextWordStart('a a 1', 5, False));
1826 AssertEquals('',-1, WBrker.NextWordStart('a a 1', 6, False));
1827 AssertEquals('', 2, WBrker.NextWordStart(' a ', 1, False));
1828 AssertEquals('',-1, WBrker.NextWordStart(' a ', 2, False));
1829 AssertEquals('',-1, WBrker.NextWordStart(' a ', 3, False));
1830 AssertEquals('',-1, WBrker.NextWordStart(' a ', 4, False));
1831
1832 AssertEquals('', 1, WBrker.NextWordStart('abc 123 ... aa', 1, True));
1833 AssertEquals('', 6, WBrker.NextWordStart('abc 123 ... aa', 2, True));
1834 AssertEquals('', 6, WBrker.NextWordStart('abc 123 ... aa', 3, True));
1835 AssertEquals('', 6, WBrker.NextWordStart('abc 123 ... aa', 4, True)); // abc|
1836 AssertEquals('', 6, WBrker.NextWordStart('abc 123 ... aa', 5, True));
1837 AssertEquals('', 6, WBrker.NextWordStart('abc 123 ... aa', 6, True)); // |123
1838 AssertEquals('',15, WBrker.NextWordStart('abc 123 ... aa', 7, True)); // 1|23
1839 AssertEquals('',15, WBrker.NextWordStart('abc 123 ... aa', 8, True));
1840 AssertEquals('',15, WBrker.NextWordStart('abc 123 ... aa', 9, True)); // 123|
1841 AssertEquals('',15, WBrker.NextWordStart('abc 123 ... aa', 10, True));
1842 AssertEquals('',15, WBrker.NextWordStart('abc 123 ... aa', 11, True)); // |...
1843 AssertEquals('',15, WBrker.NextWordStart('abc 123 ... aa', 12, True));
1844 AssertEquals('',15, WBrker.NextWordStart('abc 123 ... aa', 13, True));
1845 AssertEquals('',15, WBrker.NextWordStart('abc 123 ... aa', 14, True)); // ...|
1846 AssertEquals('',15, WBrker.NextWordStart('abc 123 ... aa', 15, True));
1847 AssertEquals('',-1, WBrker.NextWordStart('abc 123 ... aa', 16, True));
1848 AssertEquals('',-1, WBrker.NextWordStart('abc 123 ... aa', 17, True)); // at eol
1849 AssertEquals('',-1, WBrker.NextWordStart('abc 123 ... aa', 18, True));
1850 AssertEquals('',-1, WBrker.NextWordStart('abc 123 ... aa', 19, True));
1851 AssertEquals('',-1, WBrker.NextWordStart('abc 123 ... aa', 0, True));
1852 AssertEquals('',-1, WBrker.NextWordStart('abc 123 ... aa', -1, True));
1853 AssertEquals('',-1, WBrker.NextWordStart('', 1, True));
1854 AssertEquals('',-1, WBrker.NextWordStart(' ', 1, True));
1855 AssertEquals('',-1, WBrker.NextWordStart(' ', 2, True));
1856 AssertEquals('',3, WBrker.NextWordStart('..aa', 1, True));
1857 AssertEquals('',3, WBrker.NextWordStart('..aa', 2, True));
1858 AssertEquals('',3, WBrker.NextWordStart('..aa', 3, True));
1859 AssertEquals('',-1, WBrker.NextWordStart('..aa', 4, True));
1860 AssertEquals('', 1, WBrker.NextWordStart('a a 1', 1, True));
1861 AssertEquals('', 3, WBrker.NextWordStart('a a 1', 2, True));
1862 AssertEquals('', 3, WBrker.NextWordStart('a a 1', 3, True));
1863 AssertEquals('', 5, WBrker.NextWordStart('a a 1', 4, True));
1864 AssertEquals('', 5, WBrker.NextWordStart('a a 1', 5, True));
1865 AssertEquals('',-1, WBrker.NextWordStart('a a 1', 6, True));
1866 AssertEquals('', 2, WBrker.NextWordStart(' a ', 1, True));
1867 AssertEquals('', 2, WBrker.NextWordStart(' a ', 2, True));
1868 AssertEquals('',-1, WBrker.NextWordStart(' a ', 3, True));
1869 AssertEquals('',-1, WBrker.NextWordStart(' a ', 4, True));
1870
1871 AssertEquals('', 4, WBrker.NextWordEnd('abc 123 ... aa', 1, False));
1872 AssertEquals('', 4, WBrker.NextWordEnd('abc 123 ... aa', 2, False));
1873 AssertEquals('', 4, WBrker.NextWordEnd('abc 123 ... aa', 3, False));
1874 AssertEquals('', 9, WBrker.NextWordEnd('abc 123 ... aa', 4, False)); // abc|
1875 AssertEquals('', 9, WBrker.NextWordEnd('abc 123 ... aa', 5, False));
1876 AssertEquals('', 9, WBrker.NextWordEnd('abc 123 ... aa', 6, False)); // |123
1877 AssertEquals('', 9, WBrker.NextWordEnd('abc 123 ... aa', 7, False)); // 1|23
1878 AssertEquals('', 9, WBrker.NextWordEnd('abc 123 ... aa', 8, False));
1879 AssertEquals('',17, WBrker.NextWordEnd('abc 123 ... aa', 9, False)); // 123|
1880 AssertEquals('',17, WBrker.NextWordEnd('abc 123 ... aa', 10, False));
1881 AssertEquals('',17, WBrker.NextWordEnd('abc 123 ... aa', 11, False)); // |...
1882 AssertEquals('',17, WBrker.NextWordEnd('abc 123 ... aa', 12, False));
1883 AssertEquals('',17, WBrker.NextWordEnd('abc 123 ... aa', 13, False));
1884 AssertEquals('',17, WBrker.NextWordEnd('abc 123 ... aa', 14, False)); // ...|
1885 AssertEquals('',17, WBrker.NextWordEnd('abc 123 ... aa', 15, False));
1886 AssertEquals('',17, WBrker.NextWordEnd('abc 123 ... aa', 16, False));
1887 AssertEquals('',-1, WBrker.NextWordEnd('abc 123 ... aa', 17, False)); // at eol
1888 AssertEquals('',-1, WBrker.NextWordEnd('abc 123 ... aa', 18, False));
1889 AssertEquals('',-1, WBrker.NextWordEnd('abc 123 ... aa', 19, False));
1890 AssertEquals('',-1, WBrker.NextWordEnd('abc 123 ... aa', 0, False));
1891 AssertEquals('',-1, WBrker.NextWordEnd('abc 123 ... aa', -1, False));
1892 AssertEquals('',-1, WBrker.NextWordEnd('', 1, False));
1893 AssertEquals('',-1, WBrker.NextWordEnd(' ', 1, False));
1894 AssertEquals('',-1, WBrker.NextWordEnd(' ', 2, False));
1895 AssertEquals('',5, WBrker.NextWordEnd('..aa', 1, False));
1896 AssertEquals('',5, WBrker.NextWordEnd('..aa', 2, False));
1897 AssertEquals('',5, WBrker.NextWordEnd('..aa', 3, False));
1898 AssertEquals('',5, WBrker.NextWordEnd('..aa', 4, False));
1899 AssertEquals('',-1, WBrker.NextWordEnd('..aa', 5, False));
1900 AssertEquals('', 2, WBrker.NextWordEnd('a a 1', 1, False));
1901 AssertEquals('', 4, WBrker.NextWordEnd('a a 1', 2, False));
1902 AssertEquals('', 4, WBrker.NextWordEnd('a a 1', 3, False));
1903 AssertEquals('', 6, WBrker.NextWordEnd('a a 1', 4, False));
1904 AssertEquals('', 6, WBrker.NextWordEnd('a a 1', 5, False));
1905 AssertEquals('',-1, WBrker.NextWordEnd('a a 1', 6, False));
1906 AssertEquals('', 3, WBrker.NextWordEnd(' a ', 1, False));
1907 AssertEquals('', 3, WBrker.NextWordEnd(' a ', 2, False));
1908 AssertEquals('',-1, WBrker.NextWordEnd(' a ', 3, False));
1909 AssertEquals('',-1, WBrker.NextWordEnd(' a ', 4, False));
1910
1911 AssertEquals('', 4, WBrker.NextWordEnd('abc 123 ... aa', 1, True));
1912 AssertEquals('', 4, WBrker.NextWordEnd('abc 123 ... aa', 2, True));
1913 AssertEquals('', 4, WBrker.NextWordEnd('abc 123 ... aa', 3, True));
1914 AssertEquals('', 4, WBrker.NextWordEnd('abc 123 ... aa', 4, True)); // abc|
1915 AssertEquals('', 9, WBrker.NextWordEnd('abc 123 ... aa', 5, True));
1916 AssertEquals('', 9, WBrker.NextWordEnd('abc 123 ... aa', 6, True)); // |123
1917 AssertEquals('', 9, WBrker.NextWordEnd('abc 123 ... aa', 7, True)); // 1|23
1918 AssertEquals('', 9, WBrker.NextWordEnd('abc 123 ... aa', 8, True));
1919 AssertEquals('', 9, WBrker.NextWordEnd('abc 123 ... aa', 9, True)); // 123|
1920 AssertEquals('',17, WBrker.NextWordEnd('abc 123 ... aa', 10, True));
1921 AssertEquals('',17, WBrker.NextWordEnd('abc 123 ... aa', 11, True)); // |...
1922 AssertEquals('',17, WBrker.NextWordEnd('abc 123 ... aa', 12, True));
1923 AssertEquals('',17, WBrker.NextWordEnd('abc 123 ... aa', 13, True));
1924 AssertEquals('',17, WBrker.NextWordEnd('abc 123 ... aa', 14, True)); // ...|
1925 AssertEquals('',17, WBrker.NextWordEnd('abc 123 ... aa', 15, True));
1926 AssertEquals('',17, WBrker.NextWordEnd('abc 123 ... aa', 16, True));
1927 AssertEquals('',17, WBrker.NextWordEnd('abc 123 ... aa', 17, True)); // at eol
1928 AssertEquals('',-1, WBrker.NextWordEnd('abc 123 ... aa', 18, True));
1929 AssertEquals('',-1, WBrker.NextWordEnd('abc 123 ... aa', 19, True));
1930 AssertEquals('',-1, WBrker.NextWordEnd('abc 123 ... aa', 0, True));
1931 AssertEquals('',-1, WBrker.NextWordEnd('abc 123 ... aa', -1, True));
1932 AssertEquals('',-1, WBrker.NextWordEnd('', 1, True));
1933 AssertEquals('',-1, WBrker.NextWordEnd(' ', 1, True));
1934 AssertEquals('',-1, WBrker.NextWordEnd(' ', 2, True));
1935 AssertEquals('',5, WBrker.NextWordEnd('..aa', 1, True));
1936 AssertEquals('',5, WBrker.NextWordEnd('..aa', 2, True));
1937 AssertEquals('',5, WBrker.NextWordEnd('..aa', 3, True));
1938 AssertEquals('',5, WBrker.NextWordEnd('..aa', 4, True));
1939 AssertEquals('',5, WBrker.NextWordEnd('..aa', 5, True));
1940 AssertEquals('', 2, WBrker.NextWordEnd('a a 1', 1, True));
1941 AssertEquals('', 2, WBrker.NextWordEnd('a a 1', 2, True));
1942 AssertEquals('', 4, WBrker.NextWordEnd('a a 1', 3, True));
1943 AssertEquals('', 4, WBrker.NextWordEnd('a a 1', 4, True));
1944 AssertEquals('', 6, WBrker.NextWordEnd('a a 1', 5, True));
1945 AssertEquals('', 6, WBrker.NextWordEnd('a a 1', 6, True));
1946 AssertEquals('', 3, WBrker.NextWordEnd(' a ', 1, True));
1947 AssertEquals('', 3, WBrker.NextWordEnd(' a ', 2, True));
1948 AssertEquals('', 3, WBrker.NextWordEnd(' a ', 3, True));
1949 AssertEquals('',-1, WBrker.NextWordEnd(' a ', 4, True));
1950
1951 AssertEquals('',-1, WBrker.PrevWordStart('abc 123 ... aa', 1, False));
1952 AssertEquals('', 1, WBrker.PrevWordStart('abc 123 ... aa', 2, False));
1953 AssertEquals('', 1, WBrker.PrevWordStart('abc 123 ... aa', 3, False));
1954 AssertEquals('', 1, WBrker.PrevWordStart('abc 123 ... aa', 4, False)); // abc|
1955 AssertEquals('', 1, WBrker.PrevWordStart('abc 123 ... aa', 5, False));
1956 AssertEquals('', 1, WBrker.PrevWordStart('abc 123 ... aa', 6, False)); // |123
1957 AssertEquals('', 6, WBrker.PrevWordStart('abc 123 ... aa', 7, False)); // 1|23
1958 AssertEquals('', 6, WBrker.PrevWordStart('abc 123 ... aa', 8, False));
1959 AssertEquals('', 6, WBrker.PrevWordStart('abc 123 ... aa', 9, False)); // 123|
1960 AssertEquals('', 6, WBrker.PrevWordStart('abc 123 ... aa', 10, False));
1961 AssertEquals('', 6, WBrker.PrevWordStart('abc 123 ... aa', 11, False)); // |...
1962 AssertEquals('', 6, WBrker.PrevWordStart('abc 123 ... aa', 12, False));
1963 AssertEquals('', 6, WBrker.PrevWordStart('abc 123 ... aa', 13, False));
1964 AssertEquals('', 6, WBrker.PrevWordStart('abc 123 ... aa', 14, False)); // ...|
1965 AssertEquals('', 6, WBrker.PrevWordStart('abc 123 ... aa', 15, False));
1966 AssertEquals('',15, WBrker.PrevWordStart('abc 123 ... aa', 16, False));
1967 AssertEquals('',15, WBrker.PrevWordStart('abc 123 ... aa', 17, False)); // at eol
1968 AssertEquals('',-1, WBrker.PrevWordStart('abc 123 ... aa', 18, False));
1969 AssertEquals('',-1, WBrker.PrevWordStart('abc 123 ... aa', 19, False));
1970 AssertEquals('',-1, WBrker.PrevWordStart('abc 123 ... aa', 0, False));
1971 AssertEquals('',-1, WBrker.PrevWordStart('abc 123 ... aa', -1, False));
1972 AssertEquals('',-1, WBrker.PrevWordStart('', 1, False));
1973 AssertEquals('',-1, WBrker.PrevWordStart(' ', 1, False));
1974 AssertEquals('',-1, WBrker.PrevWordStart(' ', 2, False));
1975 AssertEquals('',-1, WBrker.PrevWordStart('..aa', 1, False));
1976 AssertEquals('',-1, WBrker.PrevWordStart('..aa', 2, False));
1977 AssertEquals('',-1, WBrker.PrevWordStart('..aa', 3, False));
1978 AssertEquals('', 3, WBrker.PrevWordStart('..aa', 4, False));
1979 AssertEquals('', 3, WBrker.PrevWordStart('..aa', 5, False));
1980 AssertEquals('',-1, WBrker.PrevWordStart('a a 1', 1, False));
1981 AssertEquals('', 1, WBrker.PrevWordStart('a a 1', 2, False));
1982 AssertEquals('', 1, WBrker.PrevWordStart('a a 1', 3, False));
1983 AssertEquals('', 3, WBrker.PrevWordStart('a a 1', 4, False));
1984 AssertEquals('', 3, WBrker.PrevWordStart('a a 1', 5, False));
1985 AssertEquals('', 5, WBrker.PrevWordStart('a a 1', 6, False));
1986 AssertEquals('',-1, WBrker.PrevWordStart(' a ', 1, False));
1987 AssertEquals('',-1, WBrker.PrevWordStart(' a ', 2, False));
1988 AssertEquals('', 2, WBrker.PrevWordStart(' a ', 3, False));
1989 AssertEquals('', 2, WBrker.PrevWordStart(' a ', 4, False));
1990
1991 AssertEquals('', 1, WBrker.PrevWordStart('abc 123 ... aa', 1, True));
1992 AssertEquals('', 1, WBrker.PrevWordStart('abc 123 ... aa', 2, True));
1993 AssertEquals('', 1, WBrker.PrevWordStart('abc 123 ... aa', 3, True));
1994 AssertEquals('', 1, WBrker.PrevWordStart('abc 123 ... aa', 4, True)); // abc|
1995 AssertEquals('', 1, WBrker.PrevWordStart('abc 123 ... aa', 5, True));
1996 AssertEquals('', 6, WBrker.PrevWordStart('abc 123 ... aa', 6, True)); // |123
1997 AssertEquals('', 6, WBrker.PrevWordStart('abc 123 ... aa', 7, True)); // 1|23
1998 AssertEquals('', 6, WBrker.PrevWordStart('abc 123 ... aa', 8, True));
1999 AssertEquals('', 6, WBrker.PrevWordStart('abc 123 ... aa', 9, True)); // 123|
2000 AssertEquals('', 6, WBrker.PrevWordStart('abc 123 ... aa', 10, True));
2001 AssertEquals('', 6, WBrker.PrevWordStart('abc 123 ... aa', 11, True)); // |...
2002 AssertEquals('', 6, WBrker.PrevWordStart('abc 123 ... aa', 12, True));
2003 AssertEquals('', 6, WBrker.PrevWordStart('abc 123 ... aa', 13, True));
2004 AssertEquals('', 6, WBrker.PrevWordStart('abc 123 ... aa', 14, True)); // ...|
2005 AssertEquals('',15, WBrker.PrevWordStart('abc 123 ... aa', 15, True));
2006 AssertEquals('',15, WBrker.PrevWordStart('abc 123 ... aa', 16, True));
2007 AssertEquals('',15, WBrker.PrevWordStart('abc 123 ... aa', 17, True)); // at eol
2008 AssertEquals('',-1, WBrker.PrevWordStart('abc 123 ... aa', 18, True));
2009 AssertEquals('',-1, WBrker.PrevWordStart('abc 123 ... aa', 19, True));
2010 AssertEquals('',-1, WBrker.PrevWordStart('abc 123 ... aa', 0, True));
2011 AssertEquals('',-1, WBrker.PrevWordStart('abc 123 ... aa', -1, True));
2012 AssertEquals('',-1, WBrker.PrevWordStart('', 1, True));
2013 AssertEquals('',-1, WBrker.PrevWordStart(' ', 1, True));
2014 AssertEquals('',-1, WBrker.PrevWordStart(' ', 2, True));
2015 AssertEquals('',-1, WBrker.PrevWordStart('..aa', 1, True));
2016 AssertEquals('',-1, WBrker.PrevWordStart('..aa', 2, True));
2017 AssertEquals('', 3, WBrker.PrevWordStart('..aa', 3, True));
2018 AssertEquals('', 3, WBrker.PrevWordStart('..aa', 4, True));
2019 AssertEquals('', 3, WBrker.PrevWordStart('..aa', 5, True));
2020 AssertEquals('', 1, WBrker.PrevWordStart('a a 1', 1, True));
2021 AssertEquals('', 1, WBrker.PrevWordStart('a a 1', 2, True));
2022 AssertEquals('', 3, WBrker.PrevWordStart('a a 1', 3, True));
2023 AssertEquals('', 3, WBrker.PrevWordStart('a a 1', 4, True));
2024 AssertEquals('', 5, WBrker.PrevWordStart('a a 1', 5, True));
2025 AssertEquals('', 5, WBrker.PrevWordStart('a a 1', 6, True));
2026 AssertEquals('',-1, WBrker.PrevWordStart(' a ', 1, True));
2027 AssertEquals('', 2, WBrker.PrevWordStart(' a ', 2, True));
2028 AssertEquals('', 2, WBrker.PrevWordStart(' a ', 3, True));
2029 AssertEquals('', 2, WBrker.PrevWordStart(' a ', 4, True));
2030
2031 AssertEquals('', -1, WBrker.PrevWordEnd('abc 123 ... aa', 1, False));
2032 AssertEquals('', -1, WBrker.PrevWordEnd('abc 123 ... aa', 2, False));
2033 AssertEquals('', -1, WBrker.PrevWordEnd('abc 123 ... aa', 3, False));
2034 AssertEquals('', -1, WBrker.PrevWordEnd('abc 123 ... aa', 4, False)); // abc|
2035 AssertEquals('', 4, WBrker.PrevWordEnd('abc 123 ... aa', 5, False));
2036 AssertEquals('',4, WBrker.PrevWordEnd('abc 123 ... aa', 6, False)); // |123
2037 AssertEquals('',4, WBrker.PrevWordEnd('abc 123 ... aa', 7, False)); // 1|23
2038 AssertEquals('',4, WBrker.PrevWordEnd('abc 123 ... aa', 8, False));
2039 AssertEquals('',4, WBrker.PrevWordEnd('abc 123 ... aa', 9, False)); // 123|
2040 AssertEquals('',9, WBrker.PrevWordEnd('abc 123 ... aa', 10, False));
2041 AssertEquals('',9, WBrker.PrevWordEnd('abc 123 ... aa', 11, False)); // |...
2042 AssertEquals('',9, WBrker.PrevWordEnd('abc 123 ... aa', 12, False));
2043 AssertEquals('',9, WBrker.PrevWordEnd('abc 123 ... aa', 13, False));
2044 AssertEquals('',9, WBrker.PrevWordEnd('abc 123 ... aa', 14, False)); // ...|
2045 AssertEquals('',9, WBrker.PrevWordEnd('abc 123 ... aa', 15, False));
2046 AssertEquals('',9, WBrker.PrevWordEnd('abc 123 ... aa', 16, False));
2047 AssertEquals('',9, WBrker.PrevWordEnd('abc 123 ... aa', 17, False)); // at eol
2048 AssertEquals('',-1, WBrker.PrevWordEnd('abc 123 ... aa', 18, False));
2049 AssertEquals('',-1, WBrker.PrevWordEnd('abc 123 ... aa', 19, False));
2050 AssertEquals('',-1, WBrker.PrevWordEnd('abc 123 ... aa', 0, False));
2051 AssertEquals('',-1, WBrker.PrevWordEnd('abc 123 ... aa', -1, False));
2052 AssertEquals('',-1, WBrker.PrevWordEnd('', 1, False));
2053 AssertEquals('',-1, WBrker.PrevWordEnd(' ', 1, False));
2054 AssertEquals('',-1, WBrker.PrevWordEnd(' ', 2, False));
2055 AssertEquals('',-1, WBrker.PrevWordEnd('..aa', 1, False));
2056 AssertEquals('',-1, WBrker.PrevWordEnd('..aa', 2, False));
2057 AssertEquals('',-1, WBrker.PrevWordEnd('..aa', 3, False));
2058 AssertEquals('',-1, WBrker.PrevWordEnd('..aa', 4, False));
2059 AssertEquals('',-1, WBrker.PrevWordEnd('..aa', 5, False));
2060 AssertEquals('',-1, WBrker.PrevWordEnd('a a 1', 1, False));
2061 AssertEquals('',-1, WBrker.PrevWordEnd('a a 1', 2, False));
2062 AssertEquals('', 2, WBrker.PrevWordEnd('a a 1', 3, False));
2063 AssertEquals('', 2, WBrker.PrevWordEnd('a a 1', 4, False));
2064 AssertEquals('', 4, WBrker.PrevWordEnd('a a 1', 5, False));
2065 AssertEquals('', 4, WBrker.PrevWordEnd('a a 1', 6, False));
2066 AssertEquals('',-1, WBrker.PrevWordEnd(' a ', 1, False));
2067 AssertEquals('',-1, WBrker.PrevWordEnd(' a ', 2, False));
2068 AssertEquals('',-1, WBrker.PrevWordEnd(' a ', 3, False));
2069 AssertEquals('', 3, WBrker.PrevWordEnd(' a ', 4, False));
2070
2071 AssertEquals('', -1, WBrker.PrevWordEnd('abc 123 ... aa', 1, True));
2072 AssertEquals('', -1, WBrker.PrevWordEnd('abc 123 ... aa', 2, True));
2073 AssertEquals('', -1, WBrker.PrevWordEnd('abc 123 ... aa', 3, True));
2074 AssertEquals('', 4, WBrker.PrevWordEnd('abc 123 ... aa', 4, True)); // abc|
2075 AssertEquals('', 4, WBrker.PrevWordEnd('abc 123 ... aa', 5, True));
2076 AssertEquals('', 4, WBrker.PrevWordEnd('abc 123 ... aa', 6, True)); // |123
2077 AssertEquals('', 4, WBrker.PrevWordEnd('abc 123 ... aa', 7, True)); // 1|23
2078 AssertEquals('', 4, WBrker.PrevWordEnd('abc 123 ... aa', 8, True));
2079 AssertEquals('', 9, WBrker.PrevWordEnd('abc 123 ... aa', 9, True)); // 123|
2080 AssertEquals('', 9, WBrker.PrevWordEnd('abc 123 ... aa', 10, True));
2081 AssertEquals('', 9, WBrker.PrevWordEnd('abc 123 ... aa', 11, True)); // |...
2082 AssertEquals('', 9, WBrker.PrevWordEnd('abc 123 ... aa', 12, True));
2083 AssertEquals('', 9, WBrker.PrevWordEnd('abc 123 ... aa', 13, True));
2084 AssertEquals('', 9, WBrker.PrevWordEnd('abc 123 ... aa', 14, True)); // ...|
2085 AssertEquals('', 9, WBrker.PrevWordEnd('abc 123 ... aa', 15, True));
2086 AssertEquals('', 9, WBrker.PrevWordEnd('abc 123 ... aa', 16, True));
2087 AssertEquals('',17, WBrker.PrevWordEnd('abc 123 ... aa', 17, True)); // at eol
2088 AssertEquals('',-1, WBrker.PrevWordEnd('abc 123 ... aa', 18, True));
2089 AssertEquals('',-1, WBrker.PrevWordEnd('abc 123 ... aa', 19, True));
2090 AssertEquals('',-1, WBrker.PrevWordEnd('abc 123 ... aa', 0, True));
2091 AssertEquals('',-1, WBrker.PrevWordEnd('abc 123 ... aa', -1, True));
2092 AssertEquals('',-1, WBrker.PrevWordEnd('', 1, True));
2093 AssertEquals('',-1, WBrker.PrevWordEnd(' ', 1, True));
2094 AssertEquals('',-1, WBrker.PrevWordEnd(' ', 2, True));
2095 AssertEquals('',-1, WBrker.PrevWordEnd('..aa', 1, True));
2096 AssertEquals('',-1, WBrker.PrevWordEnd('..aa', 2, True));
2097 AssertEquals('',-1, WBrker.PrevWordEnd('..aa', 3, True));
2098 AssertEquals('',-1, WBrker.PrevWordEnd('..aa', 4, True));
2099 AssertEquals('', 5, WBrker.PrevWordEnd('..aa', 5, True));
2100 AssertEquals('',-1, WBrker.PrevWordEnd('a a 1', 1, True));
2101 AssertEquals('', 2, WBrker.PrevWordEnd('a a 1', 2, True));
2102 AssertEquals('', 2, WBrker.PrevWordEnd('a a 1', 3, True));
2103 AssertEquals('', 4, WBrker.PrevWordEnd('a a 1', 4, True));
2104 AssertEquals('', 4, WBrker.PrevWordEnd('a a 1', 5, True));
2105 AssertEquals('', 6, WBrker.PrevWordEnd('a a 1', 6, True));
2106 AssertEquals('',-1, WBrker.PrevWordEnd(' a ', 1, True));
2107 AssertEquals('',-1, WBrker.PrevWordEnd(' a ', 2, True));
2108 AssertEquals('', 3, WBrker.PrevWordEnd(' a ', 3, True));
2109 AssertEquals('', 3, WBrker.PrevWordEnd(' a ', 4, True));
2110
2111
2112 AssertEquals('', 4, WBrker.NextBoundary('abc 123 ... aa', 1, False));
2113 AssertEquals('', 4, WBrker.NextBoundary('abc 123 ... aa', 2, False));
2114 AssertEquals('', 4, WBrker.NextBoundary('abc 123 ... aa', 3, False));
2115 AssertEquals('', 6, WBrker.NextBoundary('abc 123 ... aa', 4, False)); // abc|
2116 AssertEquals('', 6, WBrker.NextBoundary('abc 123 ... aa', 5, False));
2117 AssertEquals('', 9, WBrker.NextBoundary('abc 123 ... aa', 6, False)); // |123
2118 AssertEquals('', 9, WBrker.NextBoundary('abc 123 ... aa', 7, False)); // 1|23
2119 AssertEquals('', 9, WBrker.NextBoundary('abc 123 ... aa', 8, False));
2120 AssertEquals('',11, WBrker.NextBoundary('abc 123 ... aa', 9, False)); // 123|
2121 AssertEquals('',11, WBrker.NextBoundary('abc 123 ... aa', 10, False));
2122 AssertEquals('',14, WBrker.NextBoundary('abc 123 ... aa', 11, False)); // |...
2123 AssertEquals('',14, WBrker.NextBoundary('abc 123 ... aa', 12, False));
2124 AssertEquals('',14, WBrker.NextBoundary('abc 123 ... aa', 13, False));
2125 AssertEquals('',15, WBrker.NextBoundary('abc 123 ... aa', 14, False)); // ...|
2126 AssertEquals('',17, WBrker.NextBoundary('abc 123 ... aa', 15, False));
2127 AssertEquals('',17, WBrker.NextBoundary('abc 123 ... aa', 16, False));
2128 AssertEquals('',-1, WBrker.NextBoundary('abc 123 ... aa', 17, False)); // at eol
2129 AssertEquals('',-1, WBrker.NextBoundary('abc 123 ... aa', 18, False));
2130 AssertEquals('',-1, WBrker.NextBoundary('abc 123 ... aa', 19, False));
2131 AssertEquals('',-1, WBrker.NextBoundary('abc 123 ... aa', 0, False));
2132 AssertEquals('',-1, WBrker.NextBoundary('abc 123 ... aa', -1, False));
2133 AssertEquals('',-1, WBrker.NextBoundary('', 1, False));
2134 AssertEquals('',-1, WBrker.NextBoundary(' ', 1, False));
2135 AssertEquals('',-1, WBrker.NextBoundary(' ', 2, False));
2136 AssertEquals('',3, WBrker.NextBoundary('..aa', 1, False));
2137 AssertEquals('',3, WBrker.NextBoundary('..aa', 2, False));
2138 AssertEquals('',5, WBrker.NextBoundary('..aa', 3, False));
2139 AssertEquals('',5, WBrker.NextBoundary('..aa', 4, False));
2140 AssertEquals('',-1, WBrker.NextBoundary('..aa', 5, False));
2141 AssertEquals('', 2, WBrker.NextBoundary('a a 1', 1, False));
2142 AssertEquals('', 3, WBrker.NextBoundary('a a 1', 2, False));
2143 AssertEquals('', 4, WBrker.NextBoundary('a a 1', 3, False));
2144 AssertEquals('', 5, WBrker.NextBoundary('a a 1', 4, False));
2145 AssertEquals('', 6, WBrker.NextBoundary('a a 1', 5, False));
2146 AssertEquals('',-1, WBrker.NextBoundary('a a 1', 6, False));
2147 AssertEquals('', 2, WBrker.NextBoundary(' a ', 1, False));
2148 AssertEquals('', 3, WBrker.NextBoundary(' a ', 2, False));
2149 AssertEquals('',-1, WBrker.NextBoundary(' a ', 3, False));
2150 AssertEquals('',-1, WBrker.NextBoundary(' a ', 4, False));
2151
2152 AssertEquals('', 1, WBrker.NextBoundary('abc 123 ... aa', 1, True));
2153 AssertEquals('', 4, WBrker.NextBoundary('abc 123 ... aa', 2, True));
2154 AssertEquals('', 4, WBrker.NextBoundary('abc 123 ... aa', 3, True));
2155 AssertEquals('', 4, WBrker.NextBoundary('abc 123 ... aa', 4, True)); // abc|
2156 AssertEquals('', 6, WBrker.NextBoundary('abc 123 ... aa', 5, True));
2157 AssertEquals('', 6, WBrker.NextBoundary('abc 123 ... aa', 6, True)); // |123
2158 AssertEquals('', 9, WBrker.NextBoundary('abc 123 ... aa', 7, True)); // 1|23
2159 AssertEquals('', 9, WBrker.NextBoundary('abc 123 ... aa', 8, True));
2160 AssertEquals('', 9, WBrker.NextBoundary('abc 123 ... aa', 9, True)); // 123|
2161 AssertEquals('',11, WBrker.NextBoundary('abc 123 ... aa', 10, True));
2162 AssertEquals('',11, WBrker.NextBoundary('abc 123 ... aa', 11, True)); // |...
2163 AssertEquals('',14, WBrker.NextBoundary('abc 123 ... aa', 12, True));
2164 AssertEquals('',14, WBrker.NextBoundary('abc 123 ... aa', 13, True));
2165 AssertEquals('',14, WBrker.NextBoundary('abc 123 ... aa', 14, True)); // ...|
2166 AssertEquals('',15, WBrker.NextBoundary('abc 123 ... aa', 15, True));
2167 AssertEquals('',17, WBrker.NextBoundary('abc 123 ... aa', 16, True));
2168 AssertEquals('',17, WBrker.NextBoundary('abc 123 ... aa', 17, True)); // at eol
2169 AssertEquals('',-1, WBrker.NextBoundary('abc 123 ... aa', 18, True));
2170 AssertEquals('',-1, WBrker.NextBoundary('abc 123 ... aa', 19, True));
2171 AssertEquals('',-1, WBrker.NextBoundary('abc 123 ... aa', 0, True));
2172 AssertEquals('',-1, WBrker.NextBoundary('abc 123 ... aa', -1, True));
2173 AssertEquals('',-1, WBrker.NextBoundary('', 1, True));
2174 AssertEquals('',-1, WBrker.NextBoundary(' ', 1, True));
2175 AssertEquals('',-1, WBrker.NextBoundary(' ', 2, True));
2176 AssertEquals('',1, WBrker.NextBoundary('..aa', 1, True));
2177 AssertEquals('',3, WBrker.NextBoundary('..aa', 2, True));
2178 AssertEquals('',3, WBrker.NextBoundary('..aa', 3, True));
2179 AssertEquals('',5, WBrker.NextBoundary('..aa', 4, True));
2180 AssertEquals('',5, WBrker.NextBoundary('..aa', 5, True));
2181 AssertEquals('', 1, WBrker.NextBoundary('a a 1', 1, True));
2182 AssertEquals('', 2, WBrker.NextBoundary('a a 1', 2, True));
2183 AssertEquals('', 3, WBrker.NextBoundary('a a 1', 3, True));
2184 AssertEquals('', 4, WBrker.NextBoundary('a a 1', 4, True));
2185 AssertEquals('', 5, WBrker.NextBoundary('a a 1', 5, True));
2186 AssertEquals('', 6, WBrker.NextBoundary('a a 1', 6, True));
2187 AssertEquals('', 2, WBrker.NextBoundary(' a ', 1, True));
2188 AssertEquals('', 2, WBrker.NextBoundary(' a ', 2, True));
2189 AssertEquals('', 3, WBrker.NextBoundary(' a ', 3, True));
2190 AssertEquals('',-1, WBrker.NextBoundary(' a ', 4, True));
2191
2192 AssertEquals('',-1, WBrker.PrevBoundary('abc 123 ... aa', 1, False));
2193 AssertEquals('', 1, WBrker.PrevBoundary('abc 123 ... aa', 2, False));
2194 AssertEquals('', 1, WBrker.PrevBoundary('abc 123 ... aa', 3, False));
2195 AssertEquals('', 1, WBrker.PrevBoundary('abc 123 ... aa', 4, False)); // abc|
2196 AssertEquals('', 4, WBrker.PrevBoundary('abc 123 ... aa', 5, False));
2197 AssertEquals('', 4, WBrker.PrevBoundary('abc 123 ... aa', 6, False)); // |123
2198 AssertEquals('', 6, WBrker.PrevBoundary('abc 123 ... aa', 7, False)); // 1|23
2199 AssertEquals('', 6, WBrker.PrevBoundary('abc 123 ... aa', 8, False));
2200 AssertEquals('', 6, WBrker.PrevBoundary('abc 123 ... aa', 9, False)); // 123|
2201 AssertEquals('', 9, WBrker.PrevBoundary('abc 123 ... aa', 10, False));
2202 AssertEquals('', 9, WBrker.PrevBoundary('abc 123 ... aa', 11, False)); // |...
2203 AssertEquals('',11, WBrker.PrevBoundary('abc 123 ... aa', 12, False));
2204 AssertEquals('',11, WBrker.PrevBoundary('abc 123 ... aa', 13, False));
2205 AssertEquals('',11, WBrker.PrevBoundary('abc 123 ... aa', 14, False)); // ...|
2206 AssertEquals('',14, WBrker.PrevBoundary('abc 123 ... aa', 15, False));
2207 AssertEquals('',15, WBrker.PrevBoundary('abc 123 ... aa', 16, False));
2208 AssertEquals('',15, WBrker.PrevBoundary('abc 123 ... aa', 17, False)); // at eol
2209 AssertEquals('',-1, WBrker.PrevBoundary('abc 123 ... aa', 18, False));
2210 AssertEquals('',-1, WBrker.PrevBoundary('abc 123 ... aa', 19, False));
2211 AssertEquals('',-1, WBrker.PrevBoundary('abc 123 ... aa', 0, False));
2212 AssertEquals('',-1, WBrker.PrevBoundary('abc 123 ... aa', -1, False));
2213 AssertEquals('',-1, WBrker.PrevBoundary('', 1, False));
2214 AssertEquals('',-1, WBrker.PrevBoundary(' ', 1, False));
2215 AssertEquals('',-1, WBrker.PrevBoundary(' ', 2, False));
2216 AssertEquals('',-1, WBrker.PrevBoundary('..aa', 1, False));
2217 AssertEquals('',1, WBrker.PrevBoundary('..aa', 2, False));
2218 AssertEquals('',1, WBrker.PrevBoundary('..aa', 3, False));
2219 AssertEquals('',3, WBrker.PrevBoundary('..aa', 4, False));
2220 AssertEquals('',3, WBrker.PrevBoundary('..aa', 5, False));
2221 AssertEquals('',-1, WBrker.PrevBoundary('a a 1', 1, False));
2222 AssertEquals('', 1, WBrker.PrevBoundary('a a 1', 2, False));
2223 AssertEquals('', 2, WBrker.PrevBoundary('a a 1', 3, False));
2224 AssertEquals('', 3, WBrker.PrevBoundary('a a 1', 4, False));
2225 AssertEquals('', 4, WBrker.PrevBoundary('a a 1', 5, False));
2226 AssertEquals('', 5, WBrker.PrevBoundary('a a 1', 6, False));
2227 AssertEquals('',-1, WBrker.PrevBoundary(' a ', 1, False));
2228 AssertEquals('',-1, WBrker.PrevBoundary(' a ', 2, False));
2229 AssertEquals('', 2, WBrker.PrevBoundary(' a ', 3, False));
2230 AssertEquals('', 3, WBrker.PrevBoundary(' a ', 4, False));
2231
2232 AssertEquals('', 1, WBrker.PrevBoundary('abc 123 ... aa', 1, True));
2233 AssertEquals('', 1, WBrker.PrevBoundary('abc 123 ... aa', 2, True));
2234 AssertEquals('', 1, WBrker.PrevBoundary('abc 123 ... aa', 3, True));
2235 AssertEquals('', 4, WBrker.PrevBoundary('abc 123 ... aa', 4, True)); // abc|
2236 AssertEquals('', 4, WBrker.PrevBoundary('abc 123 ... aa', 5, True));
2237 AssertEquals('', 6, WBrker.PrevBoundary('abc 123 ... aa', 6, True)); // |123
2238 AssertEquals('', 6, WBrker.PrevBoundary('abc 123 ... aa', 7, True)); // 1|23
2239 AssertEquals('', 6, WBrker.PrevBoundary('abc 123 ... aa', 8, True));
2240 AssertEquals('', 9, WBrker.PrevBoundary('abc 123 ... aa', 9, True)); // 123|
2241 AssertEquals('', 9, WBrker.PrevBoundary('abc 123 ... aa', 10, True));
2242 AssertEquals('',11, WBrker.PrevBoundary('abc 123 ... aa', 11, True)); // |...
2243 AssertEquals('',11, WBrker.PrevBoundary('abc 123 ... aa', 12, True));
2244 AssertEquals('',11, WBrker.PrevBoundary('abc 123 ... aa', 13, True));
2245 AssertEquals('',14, WBrker.PrevBoundary('abc 123 ... aa', 14, True)); // ...|
2246 AssertEquals('',15, WBrker.PrevBoundary('abc 123 ... aa', 15, True));
2247 AssertEquals('',15, WBrker.PrevBoundary('abc 123 ... aa', 16, True));
2248 AssertEquals('',17, WBrker.PrevBoundary('abc 123 ... aa', 17, True)); // at eol
2249 AssertEquals('',-1, WBrker.PrevBoundary('abc 123 ... aa', 18, True));
2250 AssertEquals('',-1, WBrker.PrevBoundary('abc 123 ... aa', 19, True));
2251 AssertEquals('',-1, WBrker.PrevBoundary('abc 123 ... aa', 0, True));
2252 AssertEquals('',-1, WBrker.PrevBoundary('abc 123 ... aa', -1, True));
2253 AssertEquals('',-1, WBrker.PrevBoundary('', 1, True));
2254 AssertEquals('',-1, WBrker.PrevBoundary(' ', 1, True));
2255 AssertEquals('',-1, WBrker.PrevBoundary(' ', 2, True));
2256 AssertEquals('',1, WBrker.PrevBoundary('..aa', 1, True));
2257 AssertEquals('',1, WBrker.PrevBoundary('..aa', 2, True));
2258 AssertEquals('',3, WBrker.PrevBoundary('..aa', 3, True));
2259 AssertEquals('',3, WBrker.PrevBoundary('..aa', 4, True));
2260 AssertEquals('',5, WBrker.PrevBoundary('..aa', 5, True));
2261 AssertEquals('', 1, WBrker.PrevBoundary('a a 1', 1, True));
2262 AssertEquals('', 2, WBrker.PrevBoundary('a a 1', 2, True));
2263 AssertEquals('', 3, WBrker.PrevBoundary('a a 1', 3, True));
2264 AssertEquals('', 4, WBrker.PrevBoundary('a a 1', 4, True));
2265 AssertEquals('', 5, WBrker.PrevBoundary('a a 1', 5, True));
2266 AssertEquals('', 6, WBrker.PrevBoundary('a a 1', 6, True));
2267 AssertEquals('',-1, WBrker.PrevBoundary(' a ', 1, True));
2268 AssertEquals('', 2, WBrker.PrevBoundary(' a ', 2, True));
2269 AssertEquals('', 3, WBrker.PrevBoundary(' a ', 3, True));
2270 AssertEquals('', 3, WBrker.PrevBoundary(' a ', 4, True));
2271
2272
2273 FreeAndNil(WBrker);
2274 end;
2275
2276 procedure TTestBasicSynEdit.TestSearchReplace;
TestText1null2277 function TestText1: TStringArray;
2278 begin
2279 SetLength(Result, 9);
2280 Result[0] := 'aaaa';
2281 Result[1] := 'xx11';
2282 Result[2] := 'cccc';
2283 Result[3] := '1 1 x';
2284 Result[4] := '9';
2285 Result[5] := '1 1 x';
2286 Result[6] := '9';
2287 Result[7] := '';
2288 Result[8] := '';
2289 end;
2290
2291 type
2292 TCaretBlockCoordinates = record x,y, BBx, BBy, BEx, BEy: Integer end;
2293
expCnull2294 function expC(ExpCaretX, ExpCaretY, ExpBBX, ExpBBY, ExpBEX, ExpBEY : Integer): TCaretBlockCoordinates;
2295 begin
2296 with result do begin
2297 x := ExpCaretX; y := ExpCaretY;
2298 BBx := ExpBBX; BBy := ExpBBY;
2299 BEx := ExpBEX; BEy := ExpBEY;
2300 end;
2301 end;
expCnull2302 function expC(ExpCaretX, ExpCaretY: Integer; ExpBBX : Integer = -1): TCaretBlockCoordinates;
2303 begin
2304 Result := ExpC(ExpCaretX, ExpCaretY, ExpBBX, -1, -1, -1);
2305 end;
expCnull2306 function expC(ExpBBX, ExpBBY, ExpBEX, ExpBEY: Integer): TCaretBlockCoordinates;
2307 begin
2308 with result do begin
2309 x := -1; y := -1;
2310 BBx := ExpBBX; BBy := ExpBBY;
2311 BEx := ExpBEX; BEy := ExpBEY;
2312 end;
2313 end;
expCNonull2314 function expCNo(ExpCaretX, ExpCaretY: Integer): TCaretBlockCoordinates; // no solection
2315 begin
2316 Result := expC(ExpCaretX, ExpCaretY, -2);
2317 end;
expCFwnull2318 function expCFw(ExpBBX, ExpBBY, ExpBEX, ExpBEY: Integer): TCaretBlockCoordinates;
2319 begin // Forward selection
2320 with result do begin
2321 x := ExpBEX; y := ExpBEY;
2322 BBx := ExpBBX; BBy := ExpBBY;
2323 BEx := ExpBEX; BEy := ExpBEY;
2324 end;
2325 end;
expCBwnull2326 function expCBw(ExpBBX, ExpBBY, ExpBEX, ExpBEY: Integer): TCaretBlockCoordinates;
2327 begin // Backward selection
2328 with result do begin
2329 x := ExpBBX; y := ExpBBY;
2330 BBx := ExpBBX; BBy := ExpBBY;
2331 BEx := ExpBEX; BEy := ExpBEY;
2332 end;
2333 end;
2334
nextSelnull2335 function nextSel(ExpBBX, ExpBBY, ExpBEX, ExpBEY: Integer): TCaretBlockCoordinates;
2336 begin
2337 Result := expC(ExpBBX, ExpBBY, ExpBEX, ExpBEY);
2338 end;
2339
2340 var
2341 TheTestText: TStringArray;
2342 NextTestSetSelection: TCaretBlockCoordinates;
2343
2344 procedure TestCoord(Name: String; ExpCoord: TCaretBlockCoordinates);
2345 begin
2346 if ExpCoord.x > 0 then
2347 TestIsCaret(Name+' Caret ', ExpCoord.x, ExpCoord.y);
2348 if ExpCoord.BBx > 0 then
2349 TestIsSelection(Name+' Selection ', ExpCoord.BBx, ExpCoord.BBy, ExpCoord.BEx, ExpCoord.BEy);
2350 if ExpCoord.BBx = -2 then
2351 TestIsSelection(Name+' NO Selection ', SynEdit.LogicalCaretXY.x, SynEdit.CaretY, SynEdit.LogicalCaretXY.x, SynEdit.CaretY);
2352 end;
2353
2354 procedure TestSearch(Name, Find, Repl: String; SrcOpts: TSynSearchOptions;
2355 CaretX, CaretY: Integer;
2356 ExpCnt: Integer; ExpTxt: Array of const;
2357 ExpSearchCoord, ExpReplCoord: TCaretBlockCoordinates
2358 );
2359 var
2360 got: Integer;
2361 begin
2362 ReCreateEdit;
2363 SynEdit.Options := SynEdit.Options + [eoScrollPastEol];
2364 Name := ' - ' + Name;
2365
2366 PushBaseName('Search');
2367 SetLines(TheTestText);
2368 if NextTestSetSelection.BBx > 0 then
2369 with NextTestSetSelection do SetCaretAndSel(BBx, BBy, BEx, BEy)
2370 else
2371 SetCaret(CaretX, CaretY);
2372 got := SynEdit.SearchReplace(Find, '', SrcOpts - [ssoReplace, ssoReplaceAll]);
2373 AssertEquals(BaseTestName + Name + 'Result Count', Min(ExpCnt,1), got);
2374 TestCoord(Name, ExpSearchCoord);
2375 PopBaseName;
2376
2377 PushBaseName('Search ssoRegExprMultiLine');
2378 SetLines(TheTestText);
2379 if NextTestSetSelection.BBx > 0 then
2380 with NextTestSetSelection do SetCaretAndSel(BBx, BBy, BEx, BEy)
2381 else
2382 SetCaret(CaretX, CaretY);
2383 got := SynEdit.SearchReplace(Find, '', SrcOpts - [ssoReplace, ssoReplaceAll]+[ssoRegExprMultiLine]);
2384 AssertEquals(BaseTestName + Name + 'Result Count', Min(ExpCnt,1), got);
2385 TestCoord(Name, ExpSearchCoord);
2386 PopBaseName;
2387
2388 if (SrcOpts * [ssoReplace, ssoReplaceAll]) = [] then exit;
2389
2390 PushBaseName('Replace');
2391 SetLines(TheTestText);
2392 if NextTestSetSelection.BBx > 0 then
2393 with NextTestSetSelection do SetCaretAndSel(BBx, BBy, BEx, BEy)
2394 else
2395 SetCaret(CaretX, CaretY);
2396 got := SynEdit.SearchReplace(Find, Repl, SrcOpts);
2397 AssertEquals(BaseTestName + Name + 'Result Count', ExpCnt, got);
2398 TestIsText(Name + 'Result Text', TheTestText, ExpTxt);
2399 TestCoord(Name, ExpReplCoord);
2400 PopBaseName;
2401
2402 PushBaseName('Replace ssoRegExprMultiLine');
2403 SetLines(TheTestText);
2404 if NextTestSetSelection.BBx > 0 then
2405 with NextTestSetSelection do SetCaretAndSel(BBx, BBy, BEx, BEy)
2406 else
2407 SetCaret(CaretX, CaretY);
2408 got := SynEdit.SearchReplace(Find, Repl, SrcOpts+[ssoRegExprMultiLine]);
2409 AssertEquals(BaseTestName + Name + 'Result Count', ExpCnt, got);
2410 TestIsText(Name + 'Result Text', TheTestText, ExpTxt);
2411 TestCoord(Name, ExpReplCoord);
2412 PopBaseName;
2413
2414 NextTestSetSelection := expCNo(-1,-1);
2415 end;
2416
2417 procedure TestSearch(Name, Find, Repl: String; SrcOpts: TSynSearchOptions;
2418 CaretX, CaretY: Integer; ExpCnt: Integer; ExpTxt: Array of const);
2419 begin
2420 TestSearch(Name, Find, Repl, SrcOpts, CaretX, CaretY, ExpCnt, ExpTxt, ExpC(-1,-1), ExpC(-1,-1));
2421 end;
2422 procedure TestSearch(Name, Find, Repl: String; Opts: TSynSearchOptions;
2423 ExpCnt: Integer; ExpTxt: Array of const);
2424 begin
2425 if ssoBackwards in Opts
2426 then TestSearch(Name, Find, Repl, Opts, 1,length(TheTestText)-1, ExpCnt, ExpTxt)
2427 else TestSearch(Name, Find, Repl, Opts, 1,1, ExpCnt, ExpTxt);
2428 end;
2429 procedure TestSearch(Name, Find, Repl: String; Opts: TSynSearchOptions;
2430 ExpCnt: Integer; ExpTxt: Array of const; ExpSearchCoord, ExpReplCoord: TCaretBlockCoordinates);
2431 begin
2432 if ssoBackwards in Opts
2433 then TestSearch(Name, Find, Repl, Opts, 1,length(TheTestText)-1, ExpCnt, ExpTxt, ExpSearchCoord, ExpReplCoord)
2434 else TestSearch(Name, Find, Repl, Opts, 1,1, ExpCnt, ExpTxt, ExpSearchCoord, ExpReplCoord);
2435 end;
2436
2437 const
2438 LE = LineEnding;
2439 optAllAll: TSynSearchOptions = [ssoEntireScope, ssoReplace, ssoReplaceAll];
2440 optAllAllB: TSynSearchOptions = [ssoEntireScope, ssoReplace, ssoReplaceAll, ssoBackwards];
2441 optSelAll: TSynSearchOptions = [ssoSelectedOnly, ssoReplace, ssoReplaceAll];
2442 optSelAllB: TSynSearchOptions = [ssoSelectedOnly, ssoReplace, ssoReplaceAll, ssoBackwards];
2443 var f, r: String;
2444 var txl: Integer;
2445 begin
2446 TheTestText := TestText1;
2447 txl := length(TheTestText)-1;
2448 NextTestSetSelection := nextSel(0,0, 0,0);
2449
2450 PushBaseName('Find single line term ');
2451 PushBaseName('no match ');
2452 f := '11xx';
2453 r := '2222';
2454 TestSearch('', f, r, optAllAll, 0, [], expCNo(1,1), expCNo(1,1) );
2455 TestSearch('backward', f, r, optAllAllB, 0, [], expCNo(1,txl), expCNo(1,txl) );
2456
2457 PopPushBaseName('match - full line');
2458 f := 'xx11';
2459 r := '2222';
2460 TestSearch('', f, r, optAllAll, 1, [2, '2222'], expCFw(1,2, 5,2), expCFw(1,2, 5,2) );
2461 TestSearch('backward', f, r, optAllAllB, 1, [2, '2222'], expCBw(1,2, 5,2), expCBw(1,2, 5,2) );
2462
2463 r := '';
2464 TestSearch('repl-empty ', f, r, optAllAll, 1, [2, ''], expCFw(1,2, 5,2), expCNo(1,2) );
2465 TestSearch('repl-empty backward', f, r, optAllAllB, 1, [2, ''], expCBw(1,2, 5,2), expCNo(1,2) );
2466
2467 r := LE;
2468 TestSearch('repl-CR ', f, r, optAllAll, 1, [2, '', ''], expCFw(1,2, 5,2), expCFw(1,2, 1,3) );
2469 TestSearch('repl-CR backward', f, r, optAllAllB, 1, [2, '', ''], expCBw(1,2, 5,2), expCBw(1,2, 1,3) );
2470
2471 PopPushBaseName('match - part line (end)');
2472 f := 'x11';
2473 r := '22';
2474 TestSearch('repl-shorter ', f, r, optAllAll, 1, [2, 'x22'], expCFw(2,2, 5,2), expCFw(2,2, 4,2) );
2475 TestSearch('repl-shorter backward', f, r, optAllAllB, 1, [2, 'x22'], expCBw(2,2, 5,2), expCBw(2,2, 4,2) );
2476
2477 r := '2222';
2478 TestSearch('repl-longer ', f, r, optAllAll, 1, [2, 'x2222'], expCFw(2,2, 5,2), expCFw(2,2, 6,2) );
2479 TestSearch('repl-longer backward', f, r, optAllAllB, 1, [2, 'x2222'], expCBw(2,2, 5,2), expCBw(2,2, 6,2) );
2480
2481 r := LE;
2482 TestSearch('repl-CR ', f, r, optAllAll, 1, [2, 'x', ''], expCFw(2,2, 5,2), expCFw(2,2, 1,3) );
2483 TestSearch('repl-CR backward', f, r, optAllAllB, 1, [2, 'x', ''], expCBw(2,2, 5,2), expCBw(2,2, 1,3) );
2484
2485 PopPushBaseName('match in selection');
2486 f := '1';
2487 r := 'N';
2488 NextTestSetSelection := nextSel(1,4, 2,6);
2489 TestSearch('repl-at-end ', f, r, optSelAll, 3, [4,'N N x', 6,'N 1 x'], expCFw(1,4, 2,4), expCFw(1,6, 2,6) );
2490 NextTestSetSelection := nextSel(1,4, 2,6);
2491 TestSearch('repl-at-end backward', f, r, optSelAllB, 3, [4,'N N x', 6,'N 1 x'], expCBw(1,6, 2,6), expCBw(1,4, 2,4) );
2492
2493 NextTestSetSelection := nextSel(1,4, 3,6);
2494 TestSearch('no-repl-after-end ', f, r, optSelAll, 3, [4,'N N x', 6,'N 1 x'], expCFw(1,4, 2,4), expCFw(1,6, 2,6) );
2495 NextTestSetSelection := nextSel(1,4, 3,6);
2496 TestSearch('no-repl-after-end backward', f, r, optSelAllB, 3, [4,'N N x', 6,'N 1 x'], expCBw(1,6, 2,6), expCBw(1,4, 2,4) );
2497
2498 NextTestSetSelection := nextSel(1,4, 1,6);
2499 TestSearch('no-repl-after-end(BOL) ', f, r, optSelAll, 2, [4,'N N x'], expCFw(1,4, 2,4), expCFw(3,4, 4,4) );
2500 NextTestSetSelection := nextSel(1,4, 1,6);
2501 TestSearch('no-repl-after-end(BOL) backward', f, r, optSelAllB, 2, [4,'N N x'], expCBw(3,4, 4,4), expCBw(1,4, 2,4) );
2502
2503 PopPushBaseName('match in selection, repl-SHORTER - to empty');
2504 r := '';
2505 NextTestSetSelection := nextSel(1,4, 4,6);
2506 TestSearch('repl-at-end ', f, r, optSelAll, 4, [4,' x', 6,' x'], expCFw(1,4, 2,4), expCNo(2,6) );
2507 NextTestSetSelection := nextSel(1,4, 4,6);
2508 TestSearch('repl-at-end backward', f, r, optSelAllB, 4, [4,' x', 6,' x'], expCBw(3,6, 4,6), expCNo(1,4) );
2509
2510 NextTestSetSelection := nextSel(1,4, 3,6);
2511 TestSearch('no-repl-after-end ', f, r, optSelAll, 3, [4,' x', 6,' 1 x'], expCFw(1,4, 2,4), expCNo(1,6) );
2512 NextTestSetSelection := nextSel(1,4, 3,6);
2513 TestSearch('no-repl-after-end backward', f, r, optSelAllB, 3, [4,' x', 6,' 1 x'], expCBw(1,6, 2,6), expCNo(1,4) );
2514
2515 PopPushBaseName('match in selection, repl-LONGER');
2516 r := 'NN';
2517 NextTestSetSelection := nextSel(1,4, 4,6);
2518 TestSearch('repl-at-end ', f, r, optSelAll, 4, [4,'NN NN x', 6,'NN NN x'], expCFw(1,4, 2,4), expCFw(4,6, 6,6) );
2519 NextTestSetSelection := nextSel(1,4, 4,6);
2520 TestSearch('repl-at-end backward', f, r, optSelAllB, 4, [4,'NN NN x', 6,'NN NN x'], expCBw(3,6, 4,6), expCBw(1,4, 3,4) );
2521
2522 NextTestSetSelection := nextSel(1,4, 3,6);
2523 TestSearch('no-repl-after-end ', f, r, optSelAll, 3, [4,'NN NN x', 6,'NN 1 x'], expCFw(1,4, 2,4), expCFw(1,6, 3,6) );
2524 NextTestSetSelection := nextSel(1,4, 3,6);
2525 TestSearch('no-repl-after-end backward', f, r, optSelAllB, 3, [4,'NN NN x', 6,'NN 1 x'], expCBw(1,6, 2,6), expCBw(1,4, 3,4) );
2526
2527 PopPushBaseName('match in selection, repl-CR');
2528 r := LE;
2529 NextTestSetSelection := nextSel(1,4, 4,6);
2530 TestSearch('repl-at-end ', f, r, optSelAll, 4, [4,'',' ',' x', 8,'',' ',' x'], expCFw(1,4, 2,4), expCFw(2,9, 1,10) );
2531 NextTestSetSelection := nextSel(1,4, 4,6);
2532 TestSearch('repl-at-end backward', f, r, optSelAllB, 4, [4,'',' ',' x', 8,'',' ',' x'], expCBw(3,6, 4,6), expCBw(1,4, 1,5) );
2533
2534 NextTestSetSelection := nextSel(1,4, 3,6);
2535 TestSearch('no-repl-after-end ', f, r, optSelAll, 3, [4,'',' ',' x', 8,'',' 1 x'], expCFw(1,4, 2,4), expCFw(1,8, 1,9) );
2536 NextTestSetSelection := nextSel(1,4, 3,6);
2537 TestSearch('no-repl-after-end backward', f, r, optSelAllB, 3, [4,'',' ',' x', 8,'',' 1 x'], expCBw(1,6, 2,6), expCBw(1,4, 1,5) );
2538
2539 PopBaseName;
2540
2541
2542 PopPushBaseName('Find with trailing CR ');
2543 PushBaseName('no match ');
2544 f := 'xx'+LE;
2545 r := '11'+LE;
2546 TestSearch('', f, r, optSelAll, 0, [], expCNo(1,1), expCNo(1,1) );
2547 TestSearch('backward', f, r, optSelAllB, 0, [], expCNo(1,txl), expCNo(1,txl) );
2548
2549 PopPushBaseName('match ');
2550 f := '11'+LE;
2551 r := 'bb'+LE;
2552 TestSearch('', f, r, optSelAll, 1, [2, 'xxbb'], expCFw(3,2, 1,3), expCFw(3,2, 1,3) );
2553 TestSearch('backward', f, r, optSelAllB, 1, [2, 'xxbb'], expCBw(3,2, 1,3), expCBw(3,2, 1,3) );
2554 PopBaseName;
2555
2556 PopPushBaseName('Find with leading CR ');
2557 PushBaseName('no match ');
2558 f := LE+'11';
2559 r := LE+'xx';
2560 TestSearch('', f, r, optSelAll, 0, [], expCNo(1,1), expCNo(1,1) );
2561 TestSearch('backward', f, r, optSelAllB, 0, [], expCNo(1,txl), expCNo(1,txl) );
2562
2563 PopPushBaseName('match ');
2564 f := LE+'xx';
2565 r := LE+'bb';
2566 TestSearch('', f, r, optSelAll, 1, [2, 'bb11'], expCFw(5,1, 3,2), expCFw(5,1, 3,2) );
2567 TestSearch('backward', f, r, optSelAllB, 1, [2, 'bb11'], expCBw(5,1, 3,2), expCBw(5,1, 3,2) );
2568 PopBaseName;
2569
2570 PopBaseName;
2571 end;
2572
2573
2574
2575 initialization
2576
2577 RegisterTest(TTestBasicSynEdit);
2578 end.
2579
2580