SynEdit: Highlight Begin/End pairs

git-svn-id: trunk@18436 -
This commit is contained in:
martin 2009-01-25 12:36:29 +00:00
parent ebb9b257f7
commit 42a27dba3d
6 changed files with 504 additions and 13 deletions

1
.gitattributes vendored
View File

@ -1430,6 +1430,7 @@ components/synedit/syneditmarkupctrlmouselink.pp svneol=native#text/plain
components/synedit/syneditmarkuphighall.pp svneol=native#text/plain
components/synedit/syneditmarkupselection.pp svneol=native#text/plain
components/synedit/syneditmarkupspecialline.pp svneol=native#text/plain
components/synedit/syneditmarkupwordgroup.pp svneol=native#text/plain
components/synedit/syneditmiscclasses.pp svneol=native#text/pascal
components/synedit/syneditmiscprocs.pp svneol=native#text/pascal
components/synedit/syneditplugins.pas svneol=native#text/pascal

View File

@ -76,7 +76,7 @@ uses
SynEditTypes, SynEditSearch, SynEditKeyCmds, SynEditMiscProcs,
SynEditPointClasses, SynBeautifier, SynEditMarks,
{$ifdef SYN_LAZARUS}
SynEditMarkup, SynEditMarkupHighAll, SynEditMarkupBracket,
SynEditMarkup, SynEditMarkupHighAll, SynEditMarkupBracket, SynEditMarkupWordGroup,
SynEditMarkupCtrlMouseLink, SynEditMarkupSpecialLine, SynEditMarkupSelection,
SynEditTextBase, SynEditTextTrimmer, SynEditFoldedView, SynEditTextTabExpander,
SynGutterBase, SynGutter, SynGutterCodeFolding, SynGutterChanges,
@ -334,6 +334,7 @@ type
fMarkupHighAll : TSynEditMarkupHighlightAll;
fMarkupHighCaret : TSynEditMarkupHighlightAllCaret;
fMarkupBracket : TSynEditMarkupBracket;
fMarkupWordGroup : TSynEditMarkupWordGroup;
fMarkupCtrlMouse : TSynEditMarkupCtrlMouseLink;
fMarkupSpecialLine : TSynEditMarkupSpecialLine;
fMarkupSelection : TSynEditMarkupSelection;
@ -1465,6 +1466,7 @@ begin
fMarkupHighCaret.Selection := FBlockSelection;
fMarkupHighAll := TSynEditMarkupHighlightAll.Create(self);
fMarkupBracket := TSynEditMarkupBracket.Create(self);
fMarkupWordGroup := TSynEditMarkupWordGroup.Create(self);
fMarkupCtrlMouse := TSynEditMarkupCtrlMouseLink.Create(self);
fMarkupSpecialLine := TSynEditMarkupSpecialLine.Create(self);
fMarkupSelection := TSynEditMarkupSelection.Create(self, FBlockSelection);
@ -1475,6 +1477,7 @@ begin
fMarkupManager.AddMarkUp(fMarkupHighAll);
fMarkupManager.AddMarkUp(fMarkupCtrlMouse);
fMarkupManager.AddMarkUp(fMarkupBracket);
fMarkupManager.AddMarkUp(fMarkupWordGroup);
fMarkupManager.AddMarkUp(fMarkupSelection);
fMarkupManager.Lines := TSynEditStrings(FTheLinesView);
fMarkupManager.InvalidateLinesMethod := @InvalidateLines;
@ -6218,6 +6221,7 @@ begin
end;
fHighlighter := Value;
fMarkupHighCaret.Highlighter := Value;
fMarkupWordGroup.Highlighter := Value;
{$IFDEF SYN_LAZARUS}
if fHighlighter<>nil then begin
fHighlighter.ResetRange;

View File

@ -49,7 +49,7 @@ uses
{$ENDIF}
SynEditTypes,
SynEditMiscClasses,
SynEditTextBuffer;
SynEditTextBuffer, SynEditTextBase;
{$DEFINE _Gp_MustEnhanceRegistry}
{$IFDEF SYN_COMPILER_4_UP}
@ -288,6 +288,8 @@ type
function SaveToFile(AFileName: String): boolean; //DDH 10/16/01
procedure HookAttrChangeEvent(ANotifyEvent: TNotifyEvent);
procedure UnhookAttrChangeEvent(ANotifyEvent: TNotifyEvent);
Function GetWordTriplet(LogicalCaret: TPoint; Lines: TSynEditStrings;
out Y1, XB1, XE1, Y2, XB2, XE2, Y3, XB3, XE3: Integer): Boolean; virtual;
property IdentChars: TSynIdentChars read GetIdentChars;
property WordBreakChars: TSynIdentChars read fWordBreakChars write SetWordBreakChars;
property LanguageName: string read GetLanguageName;
@ -1259,6 +1261,13 @@ begin
fAttrChangeHooks.Remove(ANotifyEvent);
end;
function TSynCustomHighlighter.GetWordTriplet(LogicalCaret: TPoint;
Lines: TSynEditStrings; out Y1, XB1, XE1, Y2, XB2, XE2, Y3, XB3, XE3: Integer
): Boolean;
begin
Result := False;
end;
procedure TSynCustomHighlighter.SetEnabled(const Value: boolean);
begin
if fEnabled <> Value then
@ -1525,6 +1534,7 @@ begin
// add a copy
Result:=TSynCustomHighlighterRangeClass(Range.ClassType).Create(Range);
FItems.Add(Result);
if (FItems.Count mod 16) = 0 then DebugLn(['---------- TSynCustomHighlighterRanges Nodes.Count = ', FItems.Count]);
end;
//debugln('TSynCustomHighlighterRanges.GetEqual A ',dbgs(Node),' ',dbgs(Result.Compare(Range)),' ',dbgs(Result.CodeFoldStackSize));
end;

View File

@ -0,0 +1,255 @@
{-------------------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
the specific language governing rights and limitations under the License.
Alternatively, the contents of this file may be used under the terms of the
GNU General Public License Version 2 or later (the "GPL"), in which case
the provisions of the GPL are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms
of the GPL and not to allow others to use your version of this file
under the MPL, indicate your decision by deleting the provisions above and
replace them with the notice and other provisions required by the GPL.
If you do not delete the provisions above, a recipient may use your version
of this file under either the MPL or the GPL.
-------------------------------------------------------------------------------}
unit SynEditMarkupWordGroup;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Graphics, SynEditMarkup, SynEditMiscClasses, Controls,
LCLProc, SynEditHighlighter;
type
TWordPoint = record
Y, X, X2: Integer;
end;
{ TSynEditMarkupWordGroup }
TSynEditMarkupWordGroup = class(TSynEditMarkup)
private
// Physical Position
FHighlightPos1: TWordPoint;
FHighlightPos2: TWordPoint;
FHighlightPos3: TWordPoint;
FHighlighter: TSynCustomHighlighter;
procedure SetHighlighter(const AValue: TSynCustomHighlighter);
protected
procedure FindMatchingWords(PhysCaret: TPoint;
out Word1, Word2, Word3: TWordPoint);
procedure DoCaretChanged(OldCaret : TPoint); override;
procedure DoTopLineChanged(OldTopLine : Integer); override;
procedure DoLinesInWindoChanged(OldLinesInWindow : Integer); override;
procedure DoTextChanged(StartLine, EndLine : Integer); override;
procedure DoMarkupChanged(AMarkup: TSynSelectedColor); override;
procedure InvalidateCurrentHighlight;
public
constructor Create(ASynEdit: TCustomControl);
function GetMarkupAttributeAtRowCol(const aRow, aCol: Integer): TSynSelectedColor; override;
function GetNextMarkupColAfterRowCol(const aRow, aCol: Integer): Integer; override;
property Highlighter: TSynCustomHighlighter
read FHighlighter write SetHighlighter;
end;
implementation
uses
SynEdit;
Function CompareWordPoints(P1, P2: TWordPoint): Integer;
begin
if P1.Y < P2.Y then Exit(-1);
if P1.Y > P2.Y then Exit(+1);
If P1.X < P2.X then Exit(-1);
If P1.X > P2.X then Exit(+1);
If P1.X2 < P2.X2 then Exit(-1);
If P1.X2 > P2.X2 then Exit(+1);
Result := 0;
end;
Function PointToWordPoint(P1: TPoint): TWordPoint;
begin
Result.Y := P1.Y;
Result.X := P1.X;
Result.X2 := P1.X+1;
end;
{ TSynEditMarkupWordGroup }
constructor TSynEditMarkupWordGroup.Create(ASynEdit : TCustomControl);
begin
inherited Create(ASynEdit);
FHighlightPos1.Y := -1;
FHighlightPos2.Y := -1;
MarkupInfo.Foreground := clNone;// clNone;
MarkupInfo.FrameColor := clred;// clNone;
MarkupInfo.Background := clNone;
MarkupInfo.Style := [];
MarkupInfo.StyleMask := [];
end;
procedure TSynEditMarkupWordGroup.SetHighlighter(const AValue: TSynCustomHighlighter);
begin
FHighlighter := AValue;
end;
procedure TSynEditMarkupWordGroup.FindMatchingWords(PhysCaret: TPoint;
out Word1, Word2, Word3: TWordPoint);
var
LogCaretXY: TPoint;
begin
Word1.Y := -1;
Word2.Y := -1;
Word3.Y := -1;
if (not assigned(Lines)) or (not MarkupInfo.IsEnabled) or
(PhysCaret.Y < 1) or (PhysCaret.Y > Lines.Count) or (PhysCaret.X < 1)
then
Exit;
// Check for Begin-End like pairs
if not assigned(FHighlighter) then Exit;
LogCaretXY := TSynEdit(SynEdit).PhysicalToLogicalPos(PhysCaret);
if FHighlighter.GetWordTriplet(LogCaretXY, Lines,
Word1.Y, Word1.X, Word1.X2,
Word3.Y, Word3.X, Word3. X2,
Word2.Y, Word2.X, Word2. X2
) then
exit;
// In Case GetWordTriplet did set them
Word1.Y := -1;
Word2.Y := -1;
Word3.Y := -1;
end;
procedure TSynEditMarkupWordGroup.DoCaretChanged(OldCaret: TPoint);
begin
InvalidateCurrentHighlight;
end;
procedure TSynEditMarkupWordGroup.DoTopLineChanged(OldTopLine: Integer);
begin
InvalidateCurrentHighlight;
end;
procedure TSynEditMarkupWordGroup.DoLinesInWindoChanged(OldLinesInWindow: Integer);
begin
InvalidateCurrentHighlight;
end;
procedure TSynEditMarkupWordGroup.DoTextChanged(StartLine, EndLine: Integer);
begin
InvalidateCurrentHighlight;
end;
procedure TSynEditMarkupWordGroup.DoMarkupChanged(AMarkup: TSynSelectedColor);
begin
InvalidateCurrentHighlight;
end;
procedure TSynEditMarkupWordGroup.InvalidateCurrentHighlight;
var
NewPos, NewAntiPos, NewMiddlePos : TWordPoint;
begin
FindMatchingWords(TSynEdit(SynEdit).CaretXY, NewPos, NewAntiPos, NewMiddlePos);
// invalidate old highlighting, if changed
if (FHighlightPos1.Y > 0)
and (CompareWordPoints(FHighlightPos1, NewPos) <> 0)
then
InvalidateSynLines(FHighlightPos1.Y,FHighlightPos1.Y);
if (FHighlightPos2.Y > 0)
and (CompareWordPoints(FHighlightPos2, NewAntiPos) <> 0)
then
InvalidateSynLines(FHighlightPos2.Y,FHighlightPos2.Y);
if (FHighlightPos3.Y > 0)
and (CompareWordPoints(FHighlightPos3, NewMiddlePos) <> 0)
then
InvalidateSynLines(FHighlightPos3.Y,FHighlightPos3.Y);
// invalidate new highlighting, if changed
if (NewPos.Y>0)
and (CompareWordPoints(FHighlightPos1, NewPos) <> 0) then
InvalidateSynLines(NewPos.Y, NewPos.Y);
if (NewAntiPos.Y>0)
and (CompareWordPoints(FHighlightPos2, NewAntiPos) <> 0) then
InvalidateSynLines(NewAntiPos.Y, NewAntiPos.Y);
if (NewMiddlePos.Y>0)
and (CompareWordPoints(FHighlightPos3, NewMiddlePos) <> 0) then
InvalidateSynLines(NewMiddlePos.Y, NewMiddlePos.Y);
FHighlightPos1 := NewPos;
FHighlightPos2 := NewAntiPos;
FHighlightPos3 := NewMiddlePos;
// DebugLn('TCustomSynEdit.InvalidateCurrentHighlight C P=',dbgs(NewPos),' A=',dbgs(NewAntiPos), ' LP=',dbgs(fLogicalPos),' LA',dbgs(fLogicalAntiPos));
end;
function TSynEditMarkupWordGroup.GetMarkupAttributeAtRowCol(const aRow, aCol: Integer) : TSynSelectedColor;
begin
Result := nil;
if (FHighlightPos1.y = aRow) and
(aCol >= FHighlightPos1.x) and (aCol < FHighlightPos1.X2) then
begin
Result := MarkupInfo;
MarkupInfo.StartX := aCol;
MarkupInfo.EndX := FHighlightPos1.X2 - 1;
end
else
if (FHighlightPos3.y = aRow) and
(aCol >= FHighlightPos3.x) and (aCol < FHighlightPos3.X2) then
begin
Result := MarkupInfo;
MarkupInfo.StartX := aCol;
MarkupInfo.EndX := FHighlightPos3.X2 - 1;
end
else
if (FHighlightPos2.y = aRow) and
(aCol >= FHighlightPos2.x) and (aCol < FHighlightPos2.X2) then
begin
Result := MarkupInfo;
MarkupInfo.StartX := aCol;
MarkupInfo.EndX := FHighlightPos2.X2 - 1;
end;
end;
function TSynEditMarkupWordGroup.GetNextMarkupColAfterRowCol(const aRow, aCol: Integer) : Integer;
Procedure CheckCol(Column: Integer; var Result: Integer);
begin
if (Column <= aCol) or ((Result >= 0) and (Result < Column)) then exit;
Result := Column;
end;
begin
Result := -1;
if (FHighlightPos1.y = aRow) then begin
CheckCol(FHighlightPos1.X, Result);
CheckCol(FHighlightPos1.X2, Result);
end;
if (FHighlightPos3.y = aRow) then begin
CheckCol(FHighlightPos3.X, Result);
CheckCol(FHighlightPos3.X2, Result);
end;
if (FHighlightPos2.y = aRow) then begin
CheckCol(FHighlightPos2.X, Result);
CheckCol(FHighlightPos2.X2, Result);
end;
end;
end.

View File

@ -58,7 +58,7 @@ uses
Windows, Messages,
{$ENDIF}
Classes, Registry, Controls,
SynEditTypes, SynEditHighlighter, SynEditTextBuffer;
SynEditTypes, SynEditHighlighter, SynEditTextBuffer, SynEditTextBase;
type
TtkTokenKind = (tkAsm, tkComment, tkIdentifier, tkKey, tkNull, tkNumber,
@ -103,6 +103,13 @@ type
cfbtProgram,
cfbtRecord
);
TPascalWordTrippletRanges = set of TPascalCodeFoldBlockType;
const
PascalWordTrippletRanges: TPascalWordTrippletRanges =
[cfbtBeginEnd, cfbtProcedure, cfbtClass, cfbtProgram, cfbtRecord];
type
TPascalCompilerMode = (
pcmObjFPC,
pcmDelphi,
@ -119,6 +126,7 @@ type
FMode: TPascalCompilerMode;
FBracketNestLevel : Integer;
FLastLineCodeFoldLevelFix: integer;
FMinimumCodeFoldBlockLevel: Integer;
public
procedure Clear; override;
function Compare(Range: TSynCustomHighlighterRange): integer; override;
@ -128,8 +136,14 @@ type
procedure DecLastLineCodeFoldLevelFix;
property Mode: TPascalCompilerMode read FMode write FMode;
property BracketNestLevel: integer read FBracketNestLevel write FBracketNestLevel;
property LastLineCodeFoldLevelFix: integer read FLastLineCodeFoldLevelFix
write FLastLineCodeFoldLevelFix;
// Refers To LastLine while scanning
// stored as begining of the next line, it will refer to 2nd last line
property LastLineCodeFoldLevelFix: integer
read FLastLineCodeFoldLevelFix write FLastLineCodeFoldLevelFix;
// Refers To this line while scanning
// stored as begining of the next line, it will refer to the last line
property MinimumCodeFoldBlockLevel: integer
read FMinimumCodeFoldBlockLevel write FMinimumCodeFoldBlockLevel;
end;
{$ENDIF}
@ -179,6 +193,7 @@ type
{$ENDIF}
fD4syntax: boolean;
{$IFDEF SYN_LAZARUS}
function GetPasCodeFoldRange: TSynPasSynRange;
procedure SetCompilerMode(const AValue: TPascalCompilerMode);
function TextComp(aText: PChar): Boolean;
function KeyHash: Integer;
@ -315,6 +330,7 @@ type
{$ENDIF}
procedure EndCodeFoldBlockLastLine;
function GetLastLineCodeFoldLevelFix: integer; override;
property PasCodeFoldRange: TSynPasSynRange read GetPasCodeFoldRange;
public
{$IFNDEF SYN_CPPB_1} class {$ENDIF}
function GetCapabilities: TSynHighlighterCapabilities; override;
@ -347,6 +363,8 @@ type
{$IFDEF SYN_LAZARUS}
function TopPascalCodeFoldBlockType: TPascalCodeFoldBlockType;
{$ENDIF}
Function GetWordTriplet(LogicalCaret: TPoint; Lines: TSynEditStrings;
out Y1, XB1, XE1, Y2, XB2, XE2, Y3, XB3, XE3: Integer): Boolean; override;
published
property AsmAttri: TSynHighlighterAttributes read fAsmAttri write fAsmAttri;
property CommentAttri: TSynHighlighterAttributes read fCommentAttri
@ -723,6 +741,11 @@ begin
//DebugLn(['TSynPasSyn.SetCompilerMode FCompilerMode=',ord(FCompilerMode),' FNestedComments=',FNestedComments]);
end;
function TSynPasSyn.GetPasCodeFoldRange: TSynPasSynRange;
begin
Result := TSynPasSynRange(CodeFoldRange);
end;
{$ENDIF}
function TSynPasSyn.Func15: TtkTokenKind;
@ -2149,6 +2172,7 @@ begin
// For speed reasons, we work with fRange instead of CodeFoldRange.RangeType
// -> update now
CodeFoldRange.RangeType:=Pointer(PtrUInt(Integer(fRange)));
PasCodeFoldRange.MinimumCodeFoldBlockLevel := MinimumCodeFoldBlockLevel;
// return a fixed copy of the current CodeFoldRange instance
Result := inherited GetRange;
{$ELSE}
@ -2173,6 +2197,7 @@ procedure TSynPasSyn.ResetRange;
begin
fRange:= [rsAfterSemicolon]; // Begin of file = new Statement
FStartCodeFoldBlockLevel:=0;
FMinimumCodeFoldBlockLevel := 0;
{$IFDEF SYN_LAZARUS}
Inherited ResetRange;
CompilerMode:=pcmDelphi;
@ -2209,6 +2234,191 @@ begin
Result:=TPascalCodeFoldBlockType(PtrUInt(inherited TopCodeFoldBlockType));
end;
// ToDO: pass in Max for the search lines (Begin must be found always)
function TSynPasSyn.GetWordTriplet(LogicalCaret: TPoint; Lines: TSynEditStrings;
out Y1, XB1, XE1, Y2, XB2, XE2, Y3, XB3, XE3: Integer): Boolean;
function GetLevelBeforeCaret: Integer;
var
l: Integer;
begin
SetRange(Lines.Ranges[LogicalCaret.Y - 1]);
FMinimumCodeFoldBlockLevel := CurrentCodeFoldBlockLevel;
l := CurrentCodeFoldBlockLevel;
SetLine(Lines[LogicalCaret.Y - 1], LogicalCaret.Y - 1);
if (MinimumCodeFoldBlockLevel < CurrentCodeFoldBlockLevel)
then Result := MinimumCodeFoldBlockLevel
else Result := l;
while (Run <= LogicalCaret.x - 1) and not GetEol do begin
if (Run = LogicalCaret.x-1) and (Result <> CurrentCodeFoldBlockLevel) then
break;
FMinimumCodeFoldBlockLevel := CurrentCodeFoldBlockLevel;
l := CurrentCodeFoldBlockLevel;
Next;
if (MinimumCodeFoldBlockLevel < CurrentCodeFoldBlockLevel)
then Result := MinimumCodeFoldBlockLevel
else Result := l;
end;
end;
function FindBegin(EndY, EndX, SeekLevel: Integer; out X1, X2: Integer;
out FoldType: TPascalCodeFoldBlockType): integer; // Returns Line
var
MinLvl: Integer;
begin
Result := EndY;
MinLvl := 0; // Search the current line always
repeat
SetRange(Lines.Ranges[Result - 1]);
//PasCodeFoldRange.MinimumCodeFoldBlockLevel;
if (EndX > 0) and (MinLvl <= SeekLevel) then begin
// Search in current Line
X1 := -1;
// Use MinimumCodefoldlevel to detect theimplicit end of "var"/"type" blocks at the next "begin"
FMinimumCodeFoldBlockLevel := CurrentCodeFoldBlockLevel;
MinLvl := PasCodeFoldRange.MinimumCodeFoldBlockLevel; // Before SetLine = LastLine's MinLvl
SetLine(Lines[Result - 1], Result - 1);
while (Run <= EndX) and not GetEol do begin
if (MinimumCodeFoldBlockLevel <= SeekLevel) then begin
X1 := fTokenPos;
X2 := Run;
FoldType := TopPascalCodeFoldBlockType;
end;
FMinimumCodeFoldBlockLevel := CurrentCodeFoldBlockLevel;
Next;
end;
if X1 >= 0 then exit;
end
else
MinLvl := PasCodeFoldRange.MinimumCodeFoldBlockLevel; // Before SetLine = LastLine's MinLvl
// Search previous lines
EndX := MaxInt;
dec(Result);
until Result = 0; // should always exit before
end;
function FindEnd(BeginY, BeginX2, SeekLevel: Integer;
out X1, X2, LvlBefore: Integer): integer; // Returns Line
var
c, MinLvl : Integer;
begin
Result := BeginY;
c := Lines.Count;
MinLvl := 0; // CurrentLine always has samller Minlevel
repeat
SetRange(Lines.Ranges[Result-1]);
if (MinLvl < SeekLevel) then begin
// Search in current Line
LvlBefore := CurrentCodeFoldBlockLevel;
SetLine(Lines[Result - 1], Result - 1);
if (FTokenPos < BeginX2) then
begin
while (FTokenPos < BeginX2) and not GetEol do
Next;
FMinimumCodeFoldBlockLevel := CurrentCodeFoldBlockLevel;
end;
while not GetEol do
begin
if CurrentCodeFoldBlockLevel < SeekLevel then
begin
X1 := fTokenPos;
X2 := Run;
exit
end
else if (MinimumCodeFoldBlockLevel < SeekLevel) or
(CurrentCodeFoldBlockLevel + LastLineCodeFoldLevelFix < SeekLevel)
then
exit(-1); // This block ended in the previous line (implicit end)
LvlBefore := CurrentCodeFoldBlockLevel;
Next;
end;
end;
// Search previous lines
BeginX2 := 0;
inc(Result);
if Result < c-1 then begin
SetRange(Lines.Ranges[Result]);
MinLvl := PasCodeFoldRange.MinimumCodeFoldBlockLevel;
end else begin
MinLvl := 0;
end;
until Result = c;
Result := -1;
end;
var
CurStartLevel, CurEndLevel, CurStartPosX, CurEndPosX, CurPosY: Integer;
EndStartLevel: Integer;
ft, ft2: TPascalCodeFoldBlockType;
begin
Result := False;
CurPosY := LogicalCaret.Y;
CurStartLevel := GetLevelBeforeCaret;
CurEndLevel := CurrentCodeFoldBlockLevel;
CurStartPosX := fTokenPos; // 0 based
CurEndPosX := Run; // 0 based
IF CurEndLevel > CurStartLevel then begin
// block open: begin or middle
if not (TopPascalCodeFoldBlockType in PascalWordTrippletRanges) then
exit;
Y1 := CurPosY;
XB1 := CurStartPosX;
XE1 := CurEndPosX;
Y3 := FindEnd(CurPosY, CurEndPosX, CurEndLevel, XB3, XE3, EndStartLevel);
if Y3 < 0 then exit(false);
Result := true;
if (EndStartLevel - CurrentCodeFoldBlockLevel = 1) then begin;
Y2:=-2;
end else begin
if CurStartLevel = CurrentCodeFoldBlockLevel
then Y2 := FindBegin(Y3, XB3, CurrentCodeFoldBlockLevel+1, XB2, XE2, ft)
else Y2 := FindBegin(Y3, XB3, CurrentCodeFoldBlockLevel, XB2, XE2, ft);
if not (ft in PascalWordTrippletRanges) then
Y2 := -1;
end;
end
else
if CurStartLevel - CurEndLevel = 1 then begin
// block end, 1 lvl
Y1 := FindBegin(CurPosY, CurStartPosX, CurEndLevel, XB1, XE1, ft);
if not (ft in PascalWordTrippletRanges) then
exit;
Y2 := CurPosY;
XB2 := CurStartPosX;
XE2 := CurEndPosX;
Y3 := -2;
Result := true;
end
else
if CurEndLevel < CurStartLevel then begin
// block end, 2 lvl
Y2 := FindBegin(CurPosY, CurStartPosX, CurEndLevel+1, XB2, XE2, ft);
Y1 := FindBegin(Y2, XB2, CurEndLevel, XB1, XE1, ft2);
if not (ft in PascalWordTrippletRanges) then
Y2 := -1;
if not (ft2 in PascalWordTrippletRanges) then
Y1 := -1;
if (Y2 = -1) and (Y1 = -1) then
exit;
Y3 := CurPosY;
XB3 := CurStartPosX;
XE3 := CurEndPosX;
Result := true;
end;
inc(XB1);
inc(XE1);
inc(XB2);
inc(XE2);
inc(XB3);
inc(XE3);
end;
function TSynPasSyn.StartPascalCodeFoldBlock(
ABlockType: TPascalCodeFoldBlockType;
SubBlock: boolean): TSynCustomCodeFoldBlock;
@ -2446,6 +2656,7 @@ begin
inherited Clear;
FBracketNestLevel := 0;
FLastLineCodeFoldLevelFix := 0;
FMinimumCodeFoldBlockLevel := 0;
end;
function TSynPasSynRange.Compare(Range: TSynCustomHighlighterRange): integer;
@ -2456,6 +2667,8 @@ begin
if Result<>0 then exit;
Result := BracketNestLevel - TSynPasSynRange(Range).BracketNestLevel;
if Result<>0 then exit;
Result := FMinimumCodeFoldBlockLevel - TSynPasSynRange(Range).FMinimumCodeFoldBlockLevel;
if Result<>0 then exit;
Result := FLastLineCodeFoldLevelFix - TSynPasSynRange(Range).FLastLineCodeFoldLevelFix;
end;
@ -2464,6 +2677,7 @@ begin
inherited Assign(Src);
FMode:=TSynPasSynRange(Src).FMode;
FBracketNestLevel:=TSynPasSynRange(Src).FBracketNestLevel;
FMinimumCodeFoldBlockLevel := TSynPasSynRange(Src).FMinimumCodeFoldBlockLevel;
FLastLineCodeFoldLevelFix := TSynPasSynRange(Src).FLastLineCodeFoldLevelFix;
end;

View File

@ -40,7 +40,7 @@ uses
Controls, Graphics, LCLProc, FileUtil, LResources,
// synedit
SynEdit, SynEditAutoComplete, SynEditHighlighter, SynEditKeyCmds,
SynEditStrConst, SynEditMarkupBracket, SynEditMarkupHighAll,
SynEditStrConst, SynEditMarkupBracket, SynEditMarkupHighAll, SynEditMarkupWordGroup,
SynGutter, SynGutterBase, SynGutterCodeFolding, SynGutterLineNumber, SynGutterChanges,
SynHighlighterCPP, SynHighlighterHTML, SynHighlighterJava, SynHighlighterLFM,
SynHighlighterPas, SynHighlighterPerl, SynHighlighterPHP, SynHighlighterSQL,
@ -92,7 +92,7 @@ type
ahaInvalidBreakpoint, ahaUnknownBreakpoint,
ahaErrorLine, ahaIncrementalSearch, ahaHighlightAll, ahaBracketMatch,
ahaMouseLink, ahaLineNumber, ahaLineHighlight, ahaModifiedLine,
ahaCodeFoldingTree, ahaHighlightWord, ahaFoldedCode);
ahaCodeFoldingTree, ahaHighlightWord, ahaFoldedCode, ahaWordGroup);
TSingleColorAttribute = (scaGutter, scaRightMargin);
@ -116,7 +116,8 @@ const
'Modified line',
'Code folding tree',
'Highlight current word',
'Folded code'
'Folded code',
'Word-Brackets'
);
SingleColorAttributes: array[TSingleColorAttribute] of String =
@ -171,7 +172,8 @@ const
{ ahaModifiedLine } (BG: clNone; FG: clGreen; FC: $00E9FC; Styles: []; StylesMask: []),
{ ahaCodeFoldingTree } (BG: clWhite; FG: clSilver; FC: clNone; Styles: []; StylesMask: []),
{ ahaHighlightWord } (BG: $E6E6E6; FG: clDefault; FC: clSilver; Styles: []; StylesMask: []),
{ ahaFoldedCode } (BG: clWhite; FG: clSilver; FC: clSilver; Styles: []; StylesMask: [])
{ ahaFoldedCode } (BG: clWhite; FG: clSilver; FC: clSilver; Styles: []; StylesMask: []),
{ ahaWordGroup } (BG: clNone; FG: clNone; FC: clRed; Styles: []; StylesMask: [])
);
Single: (
{ shaGutter } clBtnFace,
@ -209,7 +211,8 @@ const
{ ahaModifiedLine } (BG: clNone; FG: clGreen; FC: $00E9FC; Styles: []; StylesMask: []),
{ ahaCodeFoldingTree } (BG: clDefault; FG: clSilver; FC: clNone; Styles: []; StylesMask: []),
{ ahaHighlightWord } (BG: $303030; FG: clDefault; FC: clSilver; Styles: []; StylesMask: []),
{ ahaFoldedCode } (BG: clDefault; FG: clSilver; FC: clSilver; Styles: []; StylesMask: [])
{ ahaFoldedCode } (BG: clDefault; FG: clSilver; FC: clSilver; Styles: []; StylesMask: []),
{ ahaWordGroup } (BG: clNone; FG: clNone; FC: clRed; Styles: []; StylesMask: [])
);
Single: (
{ shaGutter } clBtnFace,
@ -247,7 +250,8 @@ const
{ ahaModifiedLine } (BG: clNone; FG: clGreen; FC: $00E9FC; Styles: []; StylesMask: []),
{ ahaCodeFoldingTree } (BG: clDefault; FG: clSilver; FC: clNone; Styles: []; StylesMask: []),
{ ahaHighlightWord } (BG: clDefault; FG: clDefault; FC: clSilver; Styles: []; StylesMask: []),
{ ahaFoldedCode } (BG: clDefault; FG: clSilver; FC: clSilver; Styles: []; StylesMask: [])
{ ahaFoldedCode } (BG: clDefault; FG: clSilver; FC: clSilver; Styles: []; StylesMask: []),
{ ahaWordGroup } (BG: clNone; FG: clNone; FC: clRed; Styles: []; StylesMask: [])
);
Single: (
{ shaGutter } clBtnFace,
@ -285,7 +289,8 @@ const
{ ahaModifiedLine } (BG: clNone; FG: clGreen; FC: $00E9FC; Styles: []; StylesMask: []),
{ ahaCodeFoldingTree } (BG: clDefault; FG: clSilver; FC: clNone; Styles: []; StylesMask: []),
{ ahaHighlightWord } (BG: clDefault; FG: clDefault; FC: clSilver; Styles: []; StylesMask: []),
{ ahaFoldedCode } (BG: clDefault; FG: clSilver; FC: clSilver; Styles: []; StylesMask: [])
{ ahaFoldedCode } (BG: clDefault; FG: clSilver; FC: clSilver; Styles: []; StylesMask: []),
{ ahaWordGroup } (BG: clNone; FG: clNone; FC: clRed; Styles: []; StylesMask: [])
);
Single: (
{ shaGutter } clBtnFace,
@ -323,7 +328,8 @@ const
{ ahaModifiedLine } (BG: $F4F4F4; FG: clLime; FC: clYellow;Styles: []; StylesMask: []),
{ ahaCodeFoldingTree } (BG: $F4F4F4; FG: $CC9999; FC: clNone; Styles: []; StylesMask: []),
{ ahaHighlightWord } (BG: clDefault; FG: clDefault; FC: $CCCCD6; Styles: []; StylesMask: []),
{ ahaFoldedCode } (BG: clDefault; FG: $CC9999; FC: $CC9999; Styles: []; StylesMask: [])
{ ahaFoldedCode } (BG: clDefault; FG: $CC9999; FC: $CC9999; Styles: []; StylesMask: []),
{ ahaWordGroup } (BG: clNone; FG: clNone; FC: clRed; Styles: []; StylesMask: [])
);
Single: (
{ shaGutter } clBtnFace,
@ -2323,6 +2329,7 @@ begin
SetMarkupColor(aSynEd.Highlighter, ahaFoldedCode, aSynEd.FoldedCodeColor);
SetMarkupColor(aSynEd.Highlighter, ahaLineHighlight, aSynEd.LineHighlightColor);
SetMarkupColorByClass(ahaHighlightWord, TSynEditMarkupHighlightAllCaret);
SetMarkupColorByClass(ahaWordGroup, TSynEditMarkupWordGroup);
SetGutterColorByClass(ahaLineNumber, TSynGutterLineNumber);
SetGutterColorByClass(ahaModifiedLine, TSynGutterChanges);
SetGutterColorByClass(ahaCodeFoldingTree, TSynGutterCodeFolding);