Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make TSynEdit's Wordwrap same as TMemo's?

I'm using TSynEdit as a more user-friendly TMemo, mostly for the advanced shortcuts, UNDO/REDO, and so on.

Other things are OK, except the wordwrap behavior, please check the attached screenshot below, SynEdit has a strange space shown on the left-most side.

How to avoid that and make it look like TMemo?

enter image description here

The TSynEdit's key property settings:

    synEdit1.UseCodeFolding := False;
    synEdit1.Options := [eoAutoIndent, eoDragDropEditing, eoEnhanceEndKey, 
eoGroupUndo, eoScrollPastEol, eoSmartTabDelete, 
eoSmartTabs, eoTabsToSpaces];
      synEdit1.ScrollBars := ssVertical;
      synEdit1.TabWidth := 4;
      synEdit1.WantTabs := True;
      synEdit1.WordWrap := True;
      synEdit1.FontSmoothing := fsmNone;
like image 237
Edwin Yip Avatar asked Feb 02 '19 16:02

Edwin Yip


1 Answers

This is not a complete, tested answer to the q, but may offer the determined reader a jumping-of point to a functional solution.

The word-wrapping behaviour of a TSynEdit is determined by its current TSynWordWrapPlugin. The default plugin is defined in SynEditWordWrap.Pas and contains the procedure TSynWordWrapPlugin.WrapLines method, starting at line 512 in the version I downloaded yesterday using the D10.2.3 GetIt Manager.

Starting at line 560 there is the block of code which, as far as I can tell, accounts for the space at the start of each wrapped line as illustrated in the q:

      if Editor.IsWordBreakChar(vRunner^) then
      begin
        vRowEnd := vRunner;
        break;
      end;
      Dec(vRunner);

vRunner and vRowEnd are among a number of PWideChar variables used in the WrapLines method.

Watching the behaviour of this code, which is inside a while loop (which is looking for a place to do a word-wrap), it operates so that when Editor.IsWordBreakChar(vRunner^) returns true, the vRunner pointer has already moved backwards past the word-break char, which is why it (the space) ends up on the following line, causing the problem noted by the OP.

Changing the code to

      if Editor.IsWordBreakChar(vRunner^) then
      begin
        {ma} Inc(vRunner);  //  WARNING: not fully tested
        vRowEnd := vRunner;
        break;
      end;
      Dec(vRunner);

forces the vRunner pointer forwards past the word-break character so that the space is included at the end of the line rather than at the start of the next one, so the SynEdit then displays its wrapped text like the standard TMemo.

Personally, I would not use this change, but would instead see if I could persuade the SynEdit developers to provide an official solution. if I did use the change shown above, I certainly wouldn't do it by changing the source of SynEditWordWrap.Pas, I would do it by writing a replacement for TSynWordWrapPlugin and I would include a check that the inc(vRunner) does not exceed the valid bounds of the buffer being used to do the word-wrapping.

like image 190
MartynA Avatar answered Oct 01 '22 02:10

MartynA