Rev 22 | Rev 24 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 22 | Rev 23 | ||
---|---|---|---|
Line 77... | Line 77... | ||
77 | procedure FindContinue; |
77 | procedure FindContinue; |
78 | procedure FindNext; |
78 | procedure FindNext; |
79 | procedure FindPrev; |
79 | procedure FindPrev; |
80 | 80 | ||
81 | procedure GoToLine( LineNumber: integer ); |
81 | procedure GoToLine( LineNumber: integer ); |
82 | procedure GetLineNumber( Position: Integer; var LineNumber, ColumnNumber: Integer ); |
- | |
83 | {returns the line and column number the cursor is on in the editor} |
- | |
84 | 82 | ||
85 | published |
83 | published |
86 | property Editor: TSynEdit read fEditor write fEditor; |
84 | property Editor: TSynEdit read fEditor write fEditor; |
87 | end; |
85 | end; |
88 | 86 | ||
Line 108... | Line 106... | ||
108 | {create the replace dialog} |
106 | {create the replace dialog} |
109 | fReplaceDialog := TReplaceDialog.Create( Self ); |
107 | fReplaceDialog := TReplaceDialog.Create( Self ); |
110 | {set up the event handlers} |
108 | {set up the event handlers} |
111 | fReplaceDialog.OnReplace := OnReplace; |
109 | fReplaceDialog.OnReplace := OnReplace; |
112 | fReplaceDialog.OnFind := OnFind; |
110 | fReplaceDialog.OnFind := OnFind; |
- | 111 | fReplaceDialog.Options := fReplaceDialog.Options + [frHideWholeWord]; // TODO: currently not supported (see below) |
|
113 | 112 | ||
114 | {set find's default action on end of text to alert the user. |
113 | {set find's default action on end of text to alert the user. |
115 | If a replace function changes this it is it's responsibility |
114 | If a replace function changes this it is it's responsibility |
116 | to change it back} |
115 | to change it back} |
117 | FindActionOnEnd := frcAlertUser; |
116 | FindActionOnEnd := frcAlertUser; |
Line 286... | Line 285... | ||
286 | ReplaceDialog := Sender as TReplaceDialog; |
285 | ReplaceDialog := Sender as TReplaceDialog; |
287 | 286 | ||
288 | {set the action on end to alert the function not the user} |
287 | {set the action on end to alert the function not the user} |
289 | FindActionOnEnd := frcAlertReplace; |
288 | FindActionOnEnd := frcAlertReplace; |
290 | 289 | ||
- | 290 | // TODO: UnDo does not work |
|
- | 291 | ||
291 | {now replace the word} |
292 | {now replace the word} |
292 | if frReplace in ReplaceDialog.Options then |
293 | if frReplace in ReplaceDialog.Options then |
293 | DoReplace(ReplaceDialog) |
294 | DoReplace(ReplaceDialog) |
294 | else |
295 | else |
295 | DoReplaceAll(ReplaceDialog); |
296 | DoReplaceAll(ReplaceDialog); |
Line 298... | Line 299... | ||
298 | FindActionOnEnd := frcAlertUser; |
299 | FindActionOnEnd := frcAlertUser; |
299 | end; |
300 | end; |
300 | 301 | ||
301 | procedure TFindReplace.DoReplace(dialog: TReplaceDialog); |
302 | procedure TFindReplace.DoReplace(dialog: TReplaceDialog); |
302 | begin |
303 | begin |
303 | - | ||
304 | {if the user has highlighted a block of text only replace |
- | |
305 | within that block} |
- | |
306 | if fEditor.SelLength > 0 then |
- | |
307 | begin |
- | |
308 | FindForwards( dialog, fEditor.selStart, fEditor.selStart + fEditor.selLength ); |
- | |
309 | TryAndReplace(dialog); |
- | |
310 | end |
- | |
311 | {otherwise replace within the whole of the text} |
- | |
312 | else |
- | |
313 | begin |
- | |
314 | FindForwards( dialog, fEditor.selStart, fEditor.GetTextLen ); |
304 | FindForwards( dialog, fEditor.selStart, fEditor.GetTextLen ); |
315 | TryAndReplace(dialog); |
305 | TryAndReplace(dialog); |
316 | end; |
- | |
317 | - | ||
- | 306 | FindForwards( dialog, fEditor.selStart, fEditor.GetTextLen ); // Jump to the next occurrence |
|
318 | end; |
307 | end; |
319 | 308 | ||
320 | procedure TFindReplace.DoReplaceAll(dialog: TReplaceDialog); |
309 | procedure TFindReplace.DoReplaceAll(dialog: TReplaceDialog); |
321 | begin |
310 | begin |
322 | {see comments for DoReplace} |
311 | {see comments for DoReplace} |
323 | 312 | ||
- | 313 | fEditor.BeginUpdate; |
|
- | 314 | fEditor.BeginUndoBlock; |
|
- | 315 | try |
|
- | 316 | {if the user has highlighted a block of text only replace |
|
- | 317 | within that block} |
|
324 | if fEditor.SelLength > 0 then |
318 | if fEditor.SelLength > 0 then |
325 | begin |
319 | begin |
- | 320 | // TODO: test this functionality |
|
326 | FindForwards( dialog, fEditor.selStart, fEditor.selStart + fEditor.selLength ); |
321 | FindForwards( dialog, fEditor.selStart, fEditor.selStart + fEditor.selLength ); |
327 | {keep replacing until we reach the end of the text} |
322 | {keep replacing until we reach the end of the text} |
328 | while FindActionOnEnd <> frcEndReached do |
323 | while FindActionOnEnd <> frcEndReached do |
329 | begin |
324 | begin |
330 | {we enclose the TryAndReplace in a loop because there might be more |
325 | {we enclose the TryAndReplace in a loop because there might be more |
Line 333... | Line 328... | ||
333 | FindForwards( dialog, fEditor.selStart, fEditor.selStart + fEditor.selLength ); |
328 | FindForwards( dialog, fEditor.selStart, fEditor.selStart + fEditor.selLength ); |
334 | 329 | ||
335 | FindForwards( dialog, fEditor.selStart, fEditor.selStart + fEditor.selLength ); |
330 | FindForwards( dialog, fEditor.selStart, fEditor.selStart + fEditor.selLength ); |
336 | end; |
331 | end; |
337 | end |
332 | end |
338 | else |
333 | else {otherwise replace within the whole of the text} |
339 | begin |
334 | begin |
340 | FindForwards( dialog, fEditor.selStart, fEditor.GetTextLen ); |
335 | FindForwards( dialog, fEditor.selStart, fEditor.GetTextLen ); |
341 | while FindActionOnEnd <> frcEndReached do |
336 | while FindActionOnEnd <> frcEndReached do |
342 | begin |
337 | begin |
343 | while TryAndReplace(dialog) do |
338 | while TryAndReplace(dialog) do |
344 | FindForwards( dialog, fEditor.selStart, fEditor.GetTextLen ); |
339 | FindForwards( dialog, fEditor.selStart, fEditor.GetTextLen ); |
345 | 340 | ||
346 | FindForwards( dialog, fEditor.selStart, fEditor.GetTextLen ); |
341 | FindForwards( dialog, fEditor.selStart, fEditor.GetTextLen ); |
347 | end; |
342 | end; |
348 | end; |
343 | end; |
- | 344 | finally |
|
- | 345 | fEditor.EndUpdate; |
|
- | 346 | fEditor.EndUndoBlock; |
|
349 | 347 | end; |
|
350 | end; |
348 | end; |
351 | 349 | ||
352 | function TFindReplace.TryAndReplace(dialog: TReplaceDialog): boolean; |
350 | function TFindReplace.TryAndReplace(dialog: TReplaceDialog): boolean; |
353 | {returns true if a replacement was made and false otherwise. This is |
351 | {returns true if a replacement was made and false otherwise. This is |
354 | so a function can keep calling TryAndReplace until it returns false |
352 | so a function can keep calling TryAndReplace until it returns false |
355 | since there might be more than one occurence of the word to replace |
353 | since there might be more than one occurence of the word to replace |
356 | in the line} |
354 | in the line} |
357 | 355 | ||
358 | var |
356 | var |
359 | LineNumber, ColumnNumber: integer; |
357 | LineNumber, ColumnNumber: integer; |
360 | ReplacementString: string; {string used to replace the text} |
- | |
361 | 358 | ||
362 | OldSelStart: integer; {the position of the cursor prior to the text |
359 | OldSelStart: integer; {the position of the cursor prior to the text being replaced} |
363 | being replaced} |
- | |
364 | 360 | ||
365 | 361 | ||
366 | begin |
362 | begin |
367 | {assume no replacement was made} |
363 | {assume no replacement was made} |
368 | Result := false; |
364 | Result := false; |
Line 373... | Line 369... | ||
373 | if not (FindActionOnEnd = frcEndReached) then |
369 | if not (FindActionOnEnd = frcEndReached) then |
374 | begin |
370 | begin |
375 | {get the line number and column number of the cursor which |
371 | {get the line number and column number of the cursor which |
376 | is needed for string manipulations later. We should do this |
372 | is needed for string manipulations later. We should do this |
377 | before the call to clear selection} |
373 | before the call to clear selection} |
- | 374 | ||
- | 375 | // TODO: only replace beginning at the selected section / caret, not from beginning of the line!! |
|
378 | GetLineNumber( fEditor.SelStart, LineNumber, ColumnNumber ); |
376 | LineNumber := fEditor.CaretY-1; |
- | 377 | ColumnNumber := fEditor.CaretX-1; |
|
- | 378 | ||
379 | {get the position of the cursor prior to the replace operation |
379 | {get the position of the cursor prior to the replace operation |
380 | so we cab restore it later} |
380 | so we cab restore it later} |
381 | OldSelStart := fEditor.SelStart; |
381 | OldSelStart := fEditor.SelStart; |
382 | 382 | ||
383 | {delete the unwanted word} |
- | |
384 | fEditor.ClearSelection; |
383 | // Note: "fEditor.ClearSelection" can be used to delete the selected text |
385 | 384 | ||
386 | {Add the replacement text} |
- | |
387 | {Since we can't directly manipulate the Lines field of the |
- | |
388 | TCustomMemo component we'll extract the line, manipulate it |
385 | // TODO: only replace beginning at the selected section / caret, not from beginning of the line |
389 | then put it back} |
386 | // TODO: support "whole word" ? |
390 | ReplacementString := fEditor.Lines[ LineNumber ]; |
- | |
391 | {truncate the newline (#$A#$D) at the end of tempstring} |
- | |
392 | SetLength( ReplacementString, Length( ReplacementString )-2 ); |
- | |
393 | {add the replacement text into tempstring} |
387 | if frMatchCase in dialog.Options then |
394 | Insert( dialog.ReplaceText, ReplacementString, ColumnNumber+1 ); |
- | |
395 | {remove the old string and add the new string into the editor} |
388 | fEditor.Lines[LineNumber] := StringReplace(fEditor.Lines[LineNumber], dialog.FindText, dialog.ReplaceText, []) |
396 | fEditor.Lines.Delete( LineNumber ); |
389 | else |
397 | fEditor.Lines.Insert( LineNumber, ReplacementString ); |
390 | fEditor.Lines[LineNumber] := StringReplace(fEditor.Lines[LineNumber], dialog.FindText, dialog.ReplaceText, [rfIgnoreCase]); |
398 | 391 | ||
399 | {set the result to true since we have made a replacement} |
392 | {set the result to true since we have made a replacement} |
400 | Result := true; |
393 | Result := true; |
401 | 394 | ||
402 | {reposition the cursor to the character after the last chracter in |
395 | {reposition the cursor to the character after the last chracter in |
Line 484... | Line 477... | ||
484 | end |
477 | end |
485 | else |
478 | else |
486 | DoFind(fFindDialog, sdBackwards); |
479 | DoFind(fFindDialog, sdBackwards); |
487 | end; |
480 | end; |
488 | 481 | ||
489 | procedure TFindReplace.GetLineNumber( Position: Integer; var LineNumber, ColumnNumber: integer ); |
- | |
490 | var |
- | |
491 | i: integer; |
- | |
492 | - | ||
493 | begin |
- | |
494 | {initialise line number to 0} |
- | |
495 | LineNumber := 0; |
- | |
496 | - | ||
497 | {increment line number each time we encounter a newline (#$D) in the text} |
- | |
498 | for i := 1 to Position do |
- | |
499 | if fEditor.Text = #$D then |
- | |
500 | inc( LineNumber ); |
- | |
501 | - | ||
502 | {set the column number to position first} |
- | |
503 | ColumnNumber := Position; |
- | |
504 | {get the columnNumber by subtracting the length of each previous line} |
- | |
505 | for i := 0 to (LineNumber-1) do |
- | |
506 | dec( ColumnNumber, (*Length( fEditor.Lines )*) fEditor.Lines.Strings[i].Length ); |
- | |
507 | - | ||
508 | end; |
- | |
509 | - | ||
510 | procedure TFindReplace.GoToLine( LineNumber: integer ); |
482 | procedure TFindReplace.GoToLine( LineNumber: integer ); |
511 | var |
483 | var |
512 | currentLine: integer; |
484 | currentLine: integer; |
513 | i: integer; |
485 | i: integer; |
514 | 486 |