Subversion Repositories fastphp

Rev

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