Recent

Author Topic: A few questions about SynEdit.  (Read 1087 times)

CM630

  • Hero Member
  • *****
  • Posts: 1091
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
A few questions about SynEdit.
« on: February 19, 2024, 01:34:01 pm »
I tried to use TSynEdit, etc.
I have a few questions/problems:

1. By default TSynEdit is a multiline control. Does it have a genuine ability to switch single line only mode?
2. By default the Delete and the Backspace keys do not work properly. Delete shall erase one character forth, backspace shall erase one character back. But each of them shall erase the selection.
This is not happening.
Their actions are defined in the Keystrokes property of TSynEdit, but I cannot find how to define both (conditional) actions per key.

Edit: Maybe the answer is here: https://wiki.lazarus.freepascal.org/SynEdit#Adding_hotkeys_for_Cut.2FCopy.2FPaste.2Fetc, I will try it.

3. For some reason after an item is selected from the popup of a TSynCompeltion the Activate event of the main form is triggered. Is this the expected behaviour?
4. When I click with the mouse on an area after the last character of the line, the cursor goes there. Is the an option to limit the right (or left in LTF languages) position of the cursor to the rightmost character (like shown on the screenshot)?
5. Any guide / info about using a spellchecker with SynEdit is welcome. Shall I create a custom highlighter?
« Last Edit: February 19, 2024, 02:19:35 pm by CM630 »
Лазар 3,2 32 bit (sometimes 64 bit); FPC3,2,2; rev: Lazarus_3_0 on Win10 64bit.

rvk

  • Hero Member
  • *****
  • Posts: 6163
Re: A few questions about SynEdit.
« Reply #1 on: February 19, 2024, 02:14:50 pm »
1. By default TEdit is a multiline control. Does it have a genuine ability to switch single line only mode?
Did you mean TSynEdit? TEdit should be single line by default.

2. By default the Delete and the Backspace keys do not work properly. Delete shall erase one character forth, backspace shall erase one character back. But each of them shall erase the selection.
Works fine for me in TSynEdit (on Windows).

4. When I click with the mouse on an area after the last character of the line, the cursor goes there.
Yes, this is default in TSynEdit.
You can exclude TSynEdit.Option the option eoScrollPastEol (and possibly eoScrollPastEof).

5. Any guide / info about using a spellchecker with SynEdit is welcome. Shall I create a custom highlighter?
You could. The simplest method would be a combination of LazSpell with the TSynEdit.OnPaint and drawing on TSynEdit.Canvas.
But creating a proper highlighter might be cleaner.
Not sure if there are already spellers available.

For Delphi SynEdit there are some plugins available. But those are from after the split/port of SynEdit to Lazarus.

CM630

  • Hero Member
  • *****
  • Posts: 1091
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: A few questions about SynEdit.
« Reply #2 on: February 19, 2024, 02:27:41 pm »
Did you mean TSynEdit? TEdit should be single line by default.
Yes, I mean tSynEdit, I have fixed my post.

2. By default the Delete and the Backspace keys do not work properly. Delete shall erase one character forth, backspace shall erase one character back. But each of them shall erase the selection.
Works fine for me in TSynEdit (on Windows).

Indeed, on a brand new app it works properly. I must have messed up something.
Edit: After restoring all options to default it works.


4. When I click with the mouse on an area after the last character of the line, the cursor goes there.
Yes, this is default in TSynEdit.
You can exclude TSynEdit.Option the option eoScrollPastEol (and possibly eoScrollPastEof).

Perfect, it works!
« Last Edit: February 19, 2024, 02:45:11 pm by CM630 »
Лазар 3,2 32 bit (sometimes 64 bit); FPC3,2,2; rev: Lazarus_3_0 on Win10 64bit.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9867
  • Debugger - SynEdit - and more
    • wiki
Re: A few questions about SynEdit.
« Reply #3 on: February 19, 2024, 05:22:41 pm »
1. By default TSynEdit is a multiline control. Does it have a genuine ability to switch single line only mode?
You mean pressing "Return" key will not add a new line...

You could edit the key-bindings for that key. But paste can also insert multi-line. And other actions too. You would have to hook them all. Or you would need to add code to SynEdit (might be possible to write a subclass of TSynEditStringsLinked, and add that as via TextViewManager. But that will need quite some research / and I am not sure it will do all you need)


Quote
2. By default the Delete and the Backspace keys do not work properly. Delete shall erase one character forth, backspace shall erase one character back. But each of them shall erase the selection.
This is not happening.
Their actions are defined in the Keystrokes property of TSynEdit, but I cannot find how to define both (conditional) actions per key.
This may depend on the options....
- eoPersistentBlock in SynEdit.Options2
- eoOverwriteBlock in SynEdit.Options2
- Any other *block* or *select* in SynEdit.Options and SynEdit.Options2


Quote
3. For some reason after an item is selected from the popup of a TSynCompeltion the Activate event of the main form is triggered. Is this the expected behaviour?
The popup is a form of its own.  So that could be (it could also be depending on the WS (gtk,qt,win,....), but I am not sure if it would be)

Quote
4. When I click with the mouse on an area after the last character of the line, the cursor goes there. Is the an option to limit the right (or left in LTF languages) position of the cursor to the rightmost character (like shown on the screenshot)?
The (slightly) misnamed eoScrollPastEol in SynEdit.Options

Open the unit SynEditTypes and all the options are listed with comments.

Quote
5. Any guide / info about using a spellchecker with SynEdit is welcome. Shall I create a custom highlighter?
Actually a TSynEditMarkup.

But unfortunately that isn't yet documented.

Look at unit SynEditMarkupHighAll; There are several examples in there

- TSynEditMarkupHighlightAll all occurrences of FSearchString
So that could be changed. Instead of comparing with FSearchString, you check the result of the spellchecker.

Your own class can be added via SynEdit.MarkupManager


CM630

  • Hero Member
  • *****
  • Posts: 1091
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: A few questions about SynEdit.
« Reply #4 on: February 21, 2024, 08:57:47 am »


Actually a TSynEditMarkup.


But unfortunately that isn't yet documented.
....
That seems to be extremely secret, I could not find a single code snippet.
But somehow, I have guessed that TSynEditMarkupHighlightAll.Create(???); can take a TSynEdit instead of TSynEditBase.


So far 3 problems occurred:
1. MyMarkup.SearchOptions := [ssoWholeWord]; does not work for me (see the screenshot attached).
2. I do not know how to change the colour of the underline.
3. I do not know how to make the underline curly.


Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3.  
  4. {$mode objfpc}{$H+}
  5.  
  6.  
  7. interface
  8.  
  9.  
  10. uses
  11.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs,
  12.   SynEdit, SynEditMarkupHighAll, SynEditMarkup, SynEditTypes;
  13.  
  14.  
  15. type
  16.  
  17.  
  18.   { TForm1 }
  19.  
  20.  
  21.   TForm1 = class(TForm)
  22.     SynEdit1: TSynEdit;
  23.     procedure FormCreate(Sender: TObject);
  24.   private
  25.  
  26.  
  27.   public
  28.  
  29.  
  30.   end;
  31.  
  32.  
  33. var
  34.   Form1: TForm1;
  35.   myMarkup: array of TSynEditMarkupHighlightAll;
  36.  
  37.  
  38. implementation
  39.  
  40.  
  41. {$R *.lfm}
  42.  
  43.  
  44. { TForm1 }
  45.  
  46.  
  47. procedure TForm1.FormCreate(Sender: TObject);
  48. var
  49.   i: integer;
  50. begin
  51.   SynEdit1.Gutter.Visible := False;
  52.   SynEdit1.RightGutter.Visible := False;
  53.   SynEdit1.RightEdge := -1;
  54.   SynEdit1.Text := 'Ама ти мислиш, че след тая случкъ ни яде ли вече по толкова?' + #13#10 + 'По идно кринче варени картофи излапва като нищо, една тиква и четири печени царевици отгоре за мезе. Само вода ни пие веднага. Диета пази. Фелдшерът тъй му поръчал.';
  55.  
  56.  
  57.   if SynEdit1.MarkupManager.Count > 0 then
  58.     while SynEdit1.MarkupManager.Count > 0  do
  59.       SynEdit1.MarkupManager.RemoveMarkUp(SynEdit1.MarkupManager.Markup[0]);
  60.  
  61.  
  62.   SetLength(myMarkup,3);
  63.   for i := 0 to high(myMarkup) do
  64.   begin
  65.     MyMarkup[i] :=  TSynEditMarkupHighlightAll.Create(SynEdit1);
  66.     MyMarkup[i].SearchOptions := [ssoWholeWord];
  67.     myMarkup[i].MarkupInfo.Background := clNone;
  68.     myMarkup[i].MarkupInfo.Foreground := clDefault;
  69. //  myMarkup.MarkupInfo.FrameColor := clBlue;
  70.     myMarkup[i].MarkupInfo.Style :=  [TFontStyle.fsUnderline];
  71.     SynEdit1.MarkupManager.AddMarkUp(MyMarkup[i]);
  72.   end; //for
  73.   myMarkup[0].SearchString := 'случкъ';
  74.   myMarkup[1].SearchString := 'ни';
  75.   myMarkup[2].SearchString := 'идно';
  76. end;
  77.  
  78.  
  79. end.
  80.  
« Last Edit: February 21, 2024, 10:41:01 am by CM630 »
Лазар 3,2 32 bit (sometimes 64 bit); FPC3,2,2; rev: Lazarus_3_0 on Win10 64bit.

rvk

  • Hero Member
  • *****
  • Posts: 6163
Re: A few questions about SynEdit.
« Reply #5 on: February 21, 2024, 10:00:19 am »
So far 3 problems occurred:
1. MyMarkup.SearchOptions := [ssoWholeWord]; does not work for me (see the screenshot attached).
2. I do not know how to change the colour of the underline.
3. I do not know how to make the underline curly.
With 2 and 3, weren't you already on your way with that FrameColor ?????

Code: Pascal  [Select][+][-]
  1.     // myMarkup.MarkupInfo.FrameColor := clBlue;
  2.     // myMarkup[i].MarkupInfo.Style :=  [TFontStyle.fsUnderline];
  3.     myMarkup[i].MarkupInfo.FrameColor := clRed;
  4.     myMarkup[i].MarkupInfo.FrameEdges := sfeBottom;
  5.     myMarkup[i].MarkupInfo.FrameStyle := slsWaved;

If you want other styles you probably need to rewrite a (highlighting) component part.

The problem if number 1 is that TSynEditMarkupHighlightAll probably doesn't support UTF-8 completely.
The extended characters beyond 128 will be seen as word boundary.

I checked this by testing some text and using "us" as text.
See image. You see "using" isn't detected but the us in "uséing" is.
(and all those characters in your language are probably extended characters and not standard ascii.)

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9867
  • Debugger - SynEdit - and more
    • wiki
Re: A few questions about SynEdit.
« Reply #6 on: February 21, 2024, 10:29:27 am »
First of all, to clarify my previous answer.

It is technically possible to do the wrong word underlining using a highlighter. It is just not the way it was designed. And, you can only use ONE highlighter, so if you use it for this, then you can't use it for anything else.

There is a wiki on markup https://wiki.freepascal.org/SynEdit_Markup but yes no examples.

Yes, SyneditBase must always be a full SynEdit => It is only there to avoid circular unit uses.

Why do you remove one of the existing Markups?
You can add yours, without removing one.
Some of the existing Markup are essential (like showing the current selected text is a markup - I don't think you want to remove that?)


Red curly underline ("m" is the markup)
Code: Pascal  [Select][+][-]
  1. uses SynEditTypes;
  2. ...
  3.   m.MarkupInfo.FrameEdges := sfeBottom;
  4.   m.MarkupInfo.FrameStyle := slsWaved;
  5.   m.MarkupInfo.FrameColor:= clRed;
  6.  

Quote
MyMarkup.SearchOptions := [ssoWholeWord]; does not work for me (see the screenshot attached).
The screenshot seems missing?
But anyway, you are right => that only works for Latin at the moment. The internally used "FSearch: TSynEditSearch" has "property IdentChars: TSynIdentChars" which is a "set of char" and therefore only support Latin.

But the idea was that you would subclass the markup, with your own code.
Having more than one markup ("myMarkup: array of TSynEditMarkupHighlightAll;") is not the way to go.

You should override
Code: Pascal  [Select][+][-]
  1. function TSynEditMarkupHighlightAll.FindMatches

Look at the original code.

You would not use "fSearch.FindNextOne", but you would go through the text yourself.
Code: Pascal  [Select][+][-]
  1. for i := AStartPoint.y - 1 to AEndPoint.y-1 do begin // those are 1-based // lines is 0-based
  2.   linetext := lines[i];
  3.   // check  for misspelled words
  4.   LStart := 1;
  5.   LEnd := length(linetext):
  6.   for xpos := LStart to LEnd do begin
  7.   end ;
  8.   // e.g. find next word start, find the end, take the word and spellcheck it ...
  9. ....
  10.    if ... then
  11.      FMatches.Insert(...)
  12. end;

And then any words found are added: "FMatches.Insert(...)" // FMatches are NOT allowed to be multi-line.

On the first and last line you should also check the X pos. Any word found must be at least partially inside the line-part given by X.
If AStartPoint.x is in the middle of a word  AStartPoint.x = 7  and linetext ="ab verylongword" then IIRC you should find verylongword too.


If ABackward is set, then you must find ONLY ONE word (or NONE) which is the first that you find going backwards from end-pos.

Result is the start of the last (or for ABackward the only) found word.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9867
  • Debugger - SynEdit - and more
    • wiki
Re: A few questions about SynEdit.
« Reply #7 on: February 21, 2024, 10:33:06 am »
Mind, in case you want to optimize.

If you change text in SynEdit, the matches for the changed line(s) will be removed, and FindMatches will be called again on that line(s). If your dictionary is not that fast, then you could for the line with the caret, cache known good words. (the line with the caret is the one that gets most of the searches).

CM630

  • Hero Member
  • *****
  • Posts: 1091
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: A few questions about SynEdit.
« Reply #8 on: February 21, 2024, 12:04:28 pm »

Code: Pascal  [Select][+][-]
  1.     myMarkup[i].MarkupInfo.FrameColor := clRed;
  2.     myMarkup[i].MarkupInfo.FrameEdges := sfeBottom;
  3.     myMarkup[i].MarkupInfo.FrameStyle := slsWaved;
Thanks, that works just perfect!


The problem if number 1 is that TSynEditMarkupHighlightAll probably doesn't support UTF-8 completely.
The extended characters beyond 128 will be seen as word boundary.
Indeed, @Martin_fr confirmed it below.


Why do you remove one of the existing Markups?
I have no idea what their purpose is, I decided it is safer this way.
But I wll try without removing them.


The screenshot seems missing?
Indeed, I have added it now.


But the idea was that you would subclass the markup, with your own code.
If it worked the current way, it would be okay for me. It is for an application which will rarely have more than 3 lines per text at the same time.


I need time and efforts to comprehend everything else...
Лазар 3,2 32 bit (sometimes 64 bit); FPC3,2,2; rev: Lazarus_3_0 on Win10 64bit.

 

TinyPortal © 2005-2018