Recent

Author Topic: Integrated editing capability  (Read 3609 times)

JFistere

  • New Member
  • *
  • Posts: 25
Integrated editing capability
« on: May 24, 2016, 11:50:17 pm »
In my application I used to start an instance of Notepad to allow editing of my datafile. Then I thought it would be a good idea not to rely on an external application, so I am now using Tmemo. It gives me the ability to so basic editing, but not search and replace. I found an example of that using synedit but it seems really complex.

Will the TFind and TReplace dialogs work with TMemo?  Is there a sample application somewhere?

Or, if TMemo is not the way to go, what would be a better choice?

JFistere

  • New Member
  • *
  • Posts: 25
Re: Integrated editing capability
« Reply #1 on: May 25, 2016, 12:42:22 am »
One thing thing that would help is this: How do I get the TSearch dialog to run in response to Ctrl-F?

Edson

  • Hero Member
  • *****
  • Posts: 1301
Re: Integrated editing capability
« Reply #2 on: May 25, 2016, 12:46:06 am »
FAIK TMemo has not integrated Search/Replace options. You must implement them. TFindDialog and TReplaceDialog are just dialogs you can use or not.

SynEdit is an advanced editor control, and probably the best option.

Implementing a Search/Replace option in SynEdit is not so difficult. You can use the samples of this book: http://blog.pucp.edu.pe/blog/tito/wp-content/uploads/sites/610/2013/10/la_biblia_del_synedit_-_rev6.pdf
on the section 1.7.2 and 1.7.4 (Sorry I have not an english version).
Lazarus 2.2.6 - FPC 3.2.2 - x86_64-win64 on Windows 10

JFistere

  • New Member
  • *
  • Posts: 25
Re: Integrated editing capability
« Reply #3 on: May 27, 2016, 06:08:47 pm »
Thanks, but the SynEdit complex is much more complex than I need. All I need to do is go to the location found for Find and Find next. I can get the Find dialog built into Lazarus to appear, but I don't see how to identify and use the location found. I will continue trying things, but a pointer would help.

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Integrated editing capability
« Reply #4 on: May 27, 2016, 11:03:59 pm »
Here's an example for you. Start a new Lazarus project, and double-click on the form to generate an OnCreate handler. Complete the code as follows:
Code: Pascal  [Select][+][-]
  1. unit mainFind;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Dialogs, StdCtrls, LCLType;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     procedure FormCreate(Sender: TObject);
  16.   private
  17.     FFindDialog: TFindDialog;
  18.     FFindPosition: integer;
  19.     FTextToSearch: string;
  20.     FTextToFind: string;
  21.     FMemo: TMemo;
  22.     procedure FindDialog1Find(Sender: TObject);
  23.     procedure SearchForTextInMemo;
  24.     procedure ShowNotFoundDlg;
  25.     procedure HighlightFoundText;
  26.     procedure MemoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  27.     function SuccessfulSearch: boolean;
  28.   end;
  29.  
  30. var
  31.   Form1: TForm1;
  32.  
  33. implementation
  34.  
  35. {$R *.lfm}
  36.  
  37. { TForm1 }
  38.  
  39. procedure TForm1.SearchForTextInMemo;
  40. begin
  41.   FFindDialog.FindText:=FMemo.SelText;
  42.   FFindDialog.Execute;
  43. end;
  44.  
  45. procedure TForm1.FindDialog1Find(Sender: TObject);
  46. begin
  47.   if (FMemo.Text = '') then
  48.     Exit;
  49.   if (FFindDialog.FindText = '') then
  50.     Exit;
  51.   if not (frMatchCase in FFindDialog.Options) then
  52.     begin
  53.       FTextToSearch:=LowerCase(FMemo.Text);
  54.       FTextToFind:=LowerCase(FFindDialog.FindText);
  55.     end
  56.   else
  57.     begin
  58.       FTextToSearch:=FMemo.Text;
  59.       FTextToFind:=FFindDialog.FindText;
  60.     end;
  61.   if SuccessfulSearch then
  62.     HighlightFoundText
  63.   else ShowNotFoundDlg;
  64. end;
  65.  
  66. procedure TForm1.FormCreate(Sender: TObject);
  67. begin
  68.   FFindDialog:=TFindDialog.Create(Self);
  69.   FFindDialog.OnFind:=@FindDialog1Find;
  70.   FFindDialog.Options:=[frHideWholeWord, frHideUpDown, frHideEntireScope];
  71.   FMemo:=TMemo.Create(Self);
  72.   FMemo.Align:=alClient;
  73.   FMemo.Text:='If the snake bites before it is charmed'#10'what is the use of the charmer?';
  74.   FMemo.OnKeyDown:=@MemoKeyDown;
  75.   FMemo.ScrollBars:=ssAutoBoth;
  76.   FMemo.Parent:=Self;
  77. end;
  78.  
  79. procedure TForm1.HighlightFoundText;
  80. begin
  81.   FMemo.SelStart:=FFindPosition - Length(FTextToFind);
  82.   FMemo.SelLength:=Length(FTextToFind);
  83. end;
  84.  
  85. procedure TForm1.MemoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  86. begin
  87.   if Sender.Equals(FMemo) and (Shift = [ssCtrl]) and (Key = VK_F) then
  88.     begin
  89.       Key:=0;
  90.       SearchForTextInMemo;
  91.     end;
  92. end;
  93.  
  94. procedure TForm1.ShowNotFoundDlg;
  95. begin
  96.   MessageDlg(Format('"%s" was not found', [FFindDialog.FindText]), mtInformation, [mbOk], 0);
  97. end;
  98.  
  99. function TForm1.SuccessfulSearch: boolean;
  100. var
  101.   charsToMatch, startPosition: integer;
  102.   pc: PChar;
  103.  
  104.   procedure ResetPCharAndMatches; inline;
  105.   begin
  106.     charsToMatch:=Length(FTextToFind);
  107.     pc:=PChar(FTextToFind);
  108.   end;
  109.  
  110. begin
  111.   if SameText(FMemo.SelText, FFindDialog.FindText) then
  112.     startPosition:=FMemo.SelStart + FMemo.SelLength + 1
  113.   else startPosition:=1;
  114.  
  115.   Result:=False;
  116.   FFindPosition:=startPosition;
  117.   ResetPCharAndMatches;
  118.   while (FFindPosition <= Length(FTextToSearch)) and (charsToMatch > 0) do
  119.     begin
  120.       if (FTextToSearch[FFindPosition] = pc^) then
  121.         begin
  122.           Dec(charsToMatch);
  123.           Inc(pc);
  124.         end
  125.       else ResetPCharAndMatches;
  126.       if (charsToMatch = 0) then
  127.         Break;
  128.       Inc(FFindPosition);
  129.     end;
  130.   Result:=(charsToMatch = 0);
  131. end;
  132.  
  133. end.

JFistere

  • New Member
  • *
  • Posts: 25
Re: Integrated editing capability
« Reply #5 on: May 29, 2016, 05:59:58 am »
Thanks Howard,

I think I followed your instructions but I got the following fatal error:

project1.lpr(10,10) Fatal: Cannot find mainFind used by Project1.

Here is project1.lpr:

Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   {$IFDEF UNIX}{$IFDEF UseCThreads}
  7.   cthreads,
  8.   {$ENDIF}{$ENDIF}
  9.   Interfaces, // this includes the LCL widgetset
  10.   Forms, mainFind
  11.   { you can add units after this };
  12.  
  13. {$R *.res}
  14.  
  15. begin
  16.   RequireDerivedFormResource:=True;
  17.   Application.Initialize;
  18.   Application.CreateForm(TForm1, Form1);
  19.   Application.Run;
  20. end.  
  21.  

mainFirst is the only other tab. Here are its first few lines:

Code: Pascal  [Select][+][-]
  1. unit mainFind;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Dialogs, StdCtrls, LCLType;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     procedure FormCreate(Sender: TObject);
  16.   private
  17.     FFindDialog: TFindDialog;
  18.     FFindPosition: integer;
  19.     FTextToSearch: string;
  20.     FTextToFind: string;
  21.     FMemo: TMemo;
  22.  
  23. ------ snip ------
  24.  

I doo't know how to link the two files.


howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Integrated editing capability
« Reply #6 on: May 29, 2016, 08:43:54 am »
I had renamed my main unit in the code shown which has mislead you.

Try with a fresh Lazarus application. Keep the default main unit name (unit1.pas), but otherwise copy and paste the rest of the code. You don't need to edit the .lpr file at all.

JFistere

  • New Member
  • *
  • Posts: 25
Re: Integrated editing capability
« Reply #7 on: June 06, 2016, 11:53:39 pm »
I followed your instructions and the program compiled without errors, and function well, except for the behavior mentioned below. Thanks!

The only problem I detected was that you have to close the search dialog before you find out whether the text was found. I suspect that is because the dialogue has the focus, and so the text cannot be highlighted. Do you think there is a way around that? I will try and programmatically set the focus.

If I can solve the immediate highlighting problem mentioned above, I would like to add "Find Next" and a "Whole Word" buttons. I don't think either should be a problem.

Thanks again!

Cheers,
John

 

TinyPortal © 2005-2018