diff --git a/.gitattributes b/.gitattributes index 061f9e8f42..09d20e7dfc 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3356,6 +3356,13 @@ examples/SynEdit/Completion/SynCompletionSample.lpr svneol=native#text/pascal examples/SynEdit/Completion/SynCompletionSample.res -text examples/SynEdit/Completion/unit1.lfm svneol=native#text/plain examples/SynEdit/Completion/unit1.pas svneol=native#text/pascal +examples/SynEdit/NewHighlighterTutorial/HighlighterTutorial.lpi svneol=native#text/xml +examples/SynEdit/NewHighlighterTutorial/HighlighterTutorial.lpr svneol=native#text/pascal +examples/SynEdit/NewHighlighterTutorial/contexthl.pas svneol=native#text/pascal +examples/SynEdit/NewHighlighterTutorial/foldhl.pas svneol=native#text/pascal +examples/SynEdit/NewHighlighterTutorial/simplehl.pas svneol=native#text/pascal +examples/SynEdit/NewHighlighterTutorial/unit1.lfm svneol=native#text/pascal +examples/SynEdit/NewHighlighterTutorial/unit1.pas svneol=native#text/pascal examples/SynEdit/SynAnyHighlighter/README.txt svneol=native#text/plain examples/SynEdit/SynAnyHighlighter/synanysynhighlighter.lpi svneol=native#text/plain examples/SynEdit/SynAnyHighlighter/synanysynhighlighter.lpr svneol=native#text/plain diff --git a/examples/SynEdit/NewHighlighterTutorial/HighlighterTutorial.lpi b/examples/SynEdit/NewHighlighterTutorial/HighlighterTutorial.lpi new file mode 100644 index 0000000000..58c9e414e2 --- /dev/null +++ b/examples/SynEdit/NewHighlighterTutorial/HighlighterTutorial.lpi @@ -0,0 +1,115 @@ + + + + + + + + + + <ResourceType Value="res"/> + <UseXPManifest Value="True"/> + <Icon Value="0"/> + </General> + <i18n> + <EnableI18N LFM="False"/> + </i18n> + <VersionInfo> + <StringTable ProductVersion=""/> + </VersionInfo> + <BuildModes Count="1"> + <Item1 Name="Default" Default="True"/> + </BuildModes> + <PublishOptions> + <Version Value="2"/> + <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/> + <ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/> + </PublishOptions> + <RunParams> + <local> + <FormatVersion Value="1"/> + </local> + </RunParams> + <RequiredPackages Count="2"> + <Item1> + <PackageName Value="SynEdit"/> + </Item1> + <Item2> + <PackageName Value="LCL"/> + </Item2> + </RequiredPackages> + <Units Count="5"> + <Unit0> + <Filename Value="HighlighterTutorial.lpr"/> + <IsPartOfProject Value="True"/> + <UnitName Value="HighlighterTutorial"/> + </Unit0> + <Unit1> + <Filename Value="unit1.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="Form1"/> + <ResourceBaseClass Value="Form"/> + <UnitName Value="Unit1"/> + </Unit1> + <Unit2> + <Filename Value="simplehl.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="SimpleHl"/> + </Unit2> + <Unit3> + <Filename Value="contexthl.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="ContextHL"/> + </Unit3> + <Unit4> + <Filename Value="foldhl.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="FoldHl"/> + </Unit4> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="11"/> + <PathDelim Value="\"/> + <Target> + <Filename Value="HighlighterTutorial"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <CodeGeneration> + <Checks> + <IOChecks Value="True"/> + <RangeChecks Value="True"/> + <OverflowChecks Value="True"/> + <StackChecks Value="True"/> + </Checks> + </CodeGeneration> + <Linking> + <Debugging> + <DebugInfoType Value="dsDwarf2Set"/> + <UseHeaptrc Value="True"/> + </Debugging> + </Linking> + <Other> + <CompilerMessages> + <UseMsgFile Value="True"/> + </CompilerMessages> + <CompilerPath Value="$(CompPath)"/> + </Other> + </CompilerOptions> + <Debugging> + <Exceptions Count="3"> + <Item1> + <Name Value="EAbort"/> + </Item1> + <Item2> + <Name Value="ECodetoolError"/> + </Item2> + <Item3> + <Name Value="EFOpenError"/> + </Item3> + </Exceptions> + </Debugging> +</CONFIG> diff --git a/examples/SynEdit/NewHighlighterTutorial/HighlighterTutorial.lpr b/examples/SynEdit/NewHighlighterTutorial/HighlighterTutorial.lpr new file mode 100644 index 0000000000..90a05e4223 --- /dev/null +++ b/examples/SynEdit/NewHighlighterTutorial/HighlighterTutorial.lpr @@ -0,0 +1,22 @@ +program HighlighterTutorial; + +{$mode objfpc}{$H+} + +uses + {$IFDEF UNIX}{$IFDEF UseCThreads} + cthreads, + {$ENDIF}{$ENDIF} + Interfaces, // this includes the LCL widgetset + Forms, Unit1, SimpleHl, ContextHL, FoldHl + { you can add units after this }; + +{$R *.res} + +begin + Application.Title := 'project1'; + RequireDerivedFormResource := True; + Application.Initialize; + Application.CreateForm(TForm1, Form1); + Application.Run; +end. + diff --git a/examples/SynEdit/NewHighlighterTutorial/contexthl.pas b/examples/SynEdit/NewHighlighterTutorial/contexthl.pas new file mode 100644 index 0000000000..d966c4c777 --- /dev/null +++ b/examples/SynEdit/NewHighlighterTutorial/contexthl.pas @@ -0,0 +1,82 @@ +unit ContextHL; +(* + This is an example how to implement your own highlighter. + + This example extends the Simple HL: + - The token -- and ++ (must be surrounded by space or line-begin/end to be + a token of their own) will toggle words that start with a,e,i,o,u + + Multply ++ and -- can be nested. Then for each -- a ++ must be given, + before the words highlicht again + + See comments below and http://wiki.lazarus.freepascal.org/SynEdit_Highlighter + + +*) + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, Graphics, SynEditTypes, SynEditHighlighter, SimpleHl; + +type + + { TSynDemoHlContext } + + TSynDemoHlContext = class(TSynDemoHl) + protected + FCurRange: Integer; + public + procedure Next; override; + function GetTokenAttribute: TSynHighlighterAttributes; override; + public + procedure SetRange(Value: Pointer); override; + procedure ResetRange; override; + function GetRange: Pointer; override; + end; + + +implementation + +{ TSynDemoHlContext } + +procedure TSynDemoHlContext.Next; +begin + inherited Next; + if (copy(FLineText, FTokenPos, FTokenEnd - FTokenPos) = '--') then + inc(FCurRange); + if (copy(FLineText, FTokenPos, FTokenEnd - FTokenPos) = '++') and (FCurRange > 0) then + dec(FCurRange); +end; + +function TSynDemoHlContext.GetTokenAttribute: TSynHighlighterAttributes; +begin + Result := inherited GetTokenAttribute; + if (Result = SpecialAttri) and (FCurRange > 0) then + Result := IdentifierAttribute; +end; + +procedure TSynDemoHlContext.SetRange(Value: Pointer); +begin + // Set the current range (for current line) + // The value is provided from an internal storage, where it was kept since the last scan + // This is the and value of the previous line, which is used as start for the new line + FCurRange := PtrInt(Value); +end; + +procedure TSynDemoHlContext.ResetRange; +begin + FCurRange := 0; +end; + +function TSynDemoHlContext.GetRange: Pointer; +begin + // Get a storable copy of the cuurent (working) range + Result := Pointer(PtrInt(FCurRange)); +end; + +end. + + diff --git a/examples/SynEdit/NewHighlighterTutorial/foldhl.pas b/examples/SynEdit/NewHighlighterTutorial/foldhl.pas new file mode 100644 index 0000000000..86771ab9e3 --- /dev/null +++ b/examples/SynEdit/NewHighlighterTutorial/foldhl.pas @@ -0,0 +1,316 @@ +unit FoldHl; +(* + This is an example how to implement your own highlighter. + + This example extends the Simple and Context HL: + - The token -(- and -)- (must be surrounded by space or line-begin/end to be + a token of their own) will add foldable sections + + Multply -(- and -)- can be nested. + + See comments below and http://wiki.lazarus.freepascal.org/SynEdit_Highlighter + +*) + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, Graphics, SynEditTypes, SynEditHighlighter, SynEditHighlighterFoldBase, ContextHL; + +type + + (* This is an EXACT COPY of SynEditHighlighter + + ONLY the base class is changed to add support for folding + + The new code follows below + *) + + TSynDemoHlFoldBase = class(TSynCustomFoldHighlighter) + private + FNotAttri: TSynHighlighterAttributes; + fSpecialAttri: TSynHighlighterAttributes; + fIdentifierAttri: TSynHighlighterAttributes; + fSpaceAttri: TSynHighlighterAttributes; + procedure SetIdentifierAttri(AValue: TSynHighlighterAttributes); + procedure SetNotAttri(AValue: TSynHighlighterAttributes); + procedure SetSpaceAttri(AValue: TSynHighlighterAttributes); + procedure SetSpecialAttri(AValue: TSynHighlighterAttributes); + protected + // accesible for the other examples + FTokenPos, FTokenEnd: Integer; + FLineText: String; + public + procedure SetLine(const NewValue: String; LineNumber: Integer); override; + procedure Next; override; + function GetEol: Boolean; override; + procedure GetTokenEx(out TokenStart: PChar; out TokenLength: integer); override; + function GetTokenAttribute: TSynHighlighterAttributes; override; + public + function GetToken: String; override; + function GetTokenPos: Integer; override; + function GetTokenKind: integer; override; + function GetDefaultAttribute(Index: integer): TSynHighlighterAttributes; override; + constructor Create(AOwner: TComponent); override; + published + (* Define 4 Attributes, for the different highlights. *) + property SpecialAttri: TSynHighlighterAttributes read fSpecialAttri + write SetSpecialAttri; + property NotAttri: TSynHighlighterAttributes read FNotAttri + write SetNotAttri; + property IdentifierAttri: TSynHighlighterAttributes read fIdentifierAttri + write SetIdentifierAttri; + property SpaceAttri: TSynHighlighterAttributes read fSpaceAttri + write SetSpaceAttri; + end; + + (* This is a COPY of SynEditHighlighter + + ONLY the base class is changed to add support for folding + + The new code follows below + *) + + TSynDemoHlContextFoldBase = class(TSynDemoHlFoldBase) + protected + FCurRange: Integer; + public + procedure Next; override; + function GetTokenAttribute: TSynHighlighterAttributes; override; + public + (* The below needed to be changed and are in TSynDemoHlFold + TSynDemoHlContextFoldBase uses Ranges itself. + The Range needed here is therefore stored in a diff location + *) + //procedure SetRange(Value: Pointer); override; + //procedure ResetRange; override; + //function GetRange: Pointer; override; + end; + + { TSynDemoHlContext } + + (* You can base this on either + TSynDemoHlFoldBase or TSynDemoHlContextFoldBase + + Using ranges is NOT a condition for fold. + (If changing, remove Range related code) + + Note that ranges to change. + *) + + //TSynDemoHlFold = class(TSynDemoHlFoldBase) + TSynDemoHlFold = class(TSynDemoHlContextFoldBase) + public + procedure Next; override; + public + procedure SetRange(Value: Pointer); override; + procedure ResetRange; override; + function GetRange: Pointer; override; + end; + +implementation + +{ TSynDemoHlFold } + +procedure TSynDemoHlFold.Next; +begin + inherited Next; + if (copy(FLineText, FTokenPos, FTokenEnd - FTokenPos) = '-(-') then + StartCodeFoldBlock(nil); + if (copy(FLineText, FTokenPos, FTokenEnd - FTokenPos) = '-)-') then + EndCodeFoldBlock; +end; + +procedure TSynDemoHlFold.SetRange(Value: Pointer); +begin + // must call the SetRange in TSynCustomFoldHighlighter + inherited SetRange(Value); + FCurRange := PtrInt(CodeFoldRange.RangeType); + end; + +procedure TSynDemoHlFold.ResetRange; +begin + inherited ResetRange; + FCurRange := 0; +end; + +function TSynDemoHlFold.GetRange: Pointer; +begin + // Store the range first + CodeFoldRange.RangeType := Pointer(PtrInt(FCurRange)); + Result := inherited GetRange; +end; + + +(* This is an EXACT COPY of SynEditHighlighter + + ONLY the base class is changed to add support for folding +*) + +constructor TSynDemoHlFoldBase.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + + (* Create and initialize the attributes *) + fSpecialAttri := TSynHighlighterAttributes.Create('special', 'special'); + AddAttribute(fSpecialAttri); + fSpecialAttri.Style := [fsBold]; + + FNotAttri := TSynHighlighterAttributes.Create('not', 'not'); + AddAttribute(FNotAttri); + FNotAttri.Background := clRed; + + fIdentifierAttri := TSynHighlighterAttributes.Create('ident', 'ident'); + AddAttribute(fIdentifierAttri); + + fSpaceAttri := TSynHighlighterAttributes.Create('space', 'space'); + AddAttribute(fSpaceAttri); + fSpaceAttri.FrameColor := clSilver; + fSpaceAttri.FrameEdges := sfeAround; +end; + +(* Setters for attributes / This allows using in Object inspector*) +procedure TSynDemoHlFoldBase.SetIdentifierAttri(AValue: TSynHighlighterAttributes); +begin + fIdentifierAttri.Assign(AValue); +end; + +procedure TSynDemoHlFoldBase.SetNotAttri(AValue: TSynHighlighterAttributes); +begin + FNotAttri.Assign(AValue); +end; + +procedure TSynDemoHlFoldBase.SetSpaceAttri(AValue: TSynHighlighterAttributes); +begin + fSpaceAttri.Assign(AValue); +end; + +procedure TSynDemoHlFoldBase.SetSpecialAttri(AValue: TSynHighlighterAttributes); +begin + fSpecialAttri.Assign(AValue); +end; + +procedure TSynDemoHlFoldBase.SetLine(const NewValue: String; LineNumber: Integer); +begin + inherited; + FLineText := NewValue; + // Next will start at "FTokenEnd", so set this to 1 + FTokenEnd := 1; + Next; +end; + +procedure TSynDemoHlFoldBase.Next; +var + l: Integer; +begin + // FTokenEnd should be at the start of the next Token (which is the Token we want) + FTokenPos := FTokenEnd; + // assume empty, will only happen for EOL + FTokenEnd := FTokenPos; + + // Scan forward + // FTokenEnd will be set 1 after the last char. That is: + // - The first char of the next token + // - or past the end of line (which allows GetEOL to work) + + l := length(FLineText); + If FTokenPos > l then + // At line end + exit + else + if FLineText[FTokenEnd] in [#9, ' '] then + // At Space? Find end of spaces + while (FTokenEnd <= l) and (FLineText[FTokenEnd] in [#0..#32]) do inc (FTokenEnd) + else + // At None-Space? Find end of None-spaces + while (FTokenEnd <= l) and not(FLineText[FTokenEnd] in [#9, ' ']) do inc (FTokenEnd) +end; + +function TSynDemoHlFoldBase.GetEol: Boolean; +begin + Result := FTokenPos > length(FLineText); +end; + +procedure TSynDemoHlFoldBase.GetTokenEx(out TokenStart: PChar; out TokenLength: integer); +begin + TokenStart := @FLineText[FTokenPos]; + TokenLength := FTokenEnd - FTokenPos; +end; + +function TSynDemoHlFoldBase.GetTokenAttribute: TSynHighlighterAttributes; +begin + // Match the text, specified by FTokenPos and FTokenEnd + + if FLineText[FTokenPos] in [#9, ' '] then + Result := SpaceAttri + else + if LowerCase(FLineText[FTokenPos]) in ['a', 'e', 'i', 'o', 'u'] then + Result := SpecialAttri + else + if LowerCase(copy(FLineText, FTokenPos, FTokenEnd - FTokenPos)) = 'not' then + Result := NotAttri + else + Result := IdentifierAttri; +end; + +function TSynDemoHlFoldBase.GetToken: String; +begin + Result := copy(FLineText, FTokenPos, FTokenEnd - FTokenPos); +end; + +function TSynDemoHlFoldBase.GetTokenPos: Integer; +begin + Result := FTokenPos - 1; +end; + +function TSynDemoHlFoldBase.GetDefaultAttribute(Index: integer): TSynHighlighterAttributes; +begin + // Some default attributes + case Index of + SYN_ATTR_COMMENT: Result := fSpecialAttri; + SYN_ATTR_IDENTIFIER: Result := fIdentifierAttri; + SYN_ATTR_WHITESPACE: Result := fSpaceAttri; + else Result := nil; + end; +end; + +function TSynDemoHlFoldBase.GetTokenKind: integer; +var + a: TSynHighlighterAttributes; +begin + // Map Attribute into a unique number + a := GetTokenAttribute; + Result := 0; + if a = fSpaceAttri then Result := 1; + if a = fSpecialAttri then Result := 2; + if a = fIdentifierAttri then Result := 3; + if a = FNotAttri then Result := 4; +end; + + +(* This is an EXACT COPY of SynEditHighlighter + + ONLY the base class is changed to add support for folding +*) + +procedure TSynDemoHlContextFoldBase.Next; +begin + inherited Next; + if (copy(FLineText, FTokenPos, FTokenEnd - FTokenPos) = '--') then + inc(FCurRange); + if (copy(FLineText, FTokenPos, FTokenEnd - FTokenPos) = '++') and (FCurRange > 0) then + dec(FCurRange); +end; + +function TSynDemoHlContextFoldBase.GetTokenAttribute: TSynHighlighterAttributes; +begin + Result := inherited GetTokenAttribute; + if (Result = SpecialAttri) and (FCurRange > 0) then + Result := IdentifierAttribute; +end; + + +end. + diff --git a/examples/SynEdit/NewHighlighterTutorial/simplehl.pas b/examples/SynEdit/NewHighlighterTutorial/simplehl.pas new file mode 100644 index 0000000000..9fa7a1c9e1 --- /dev/null +++ b/examples/SynEdit/NewHighlighterTutorial/simplehl.pas @@ -0,0 +1,243 @@ +unit SimpleHl; +(* + This is an example how to implement your own highlighter. + + This example does allow to specify different colors for + - text (defaults to not-highlighted) + - spaces (defaults to silver frame) + - words, separated by spaces, that start with a,e,i,o,u (defaults to bold) + - the word "not" (defaults to red background) + + See comments below and http://wiki.lazarus.freepascal.org/SynEdit_Highlighter + + How it works: + + - Creation + The Highlighter creates Attributes that it can return the Words and Spaces. + + - SetLine + Is called by SynEdit before a line gets painted (or before highlight info is needed) + This is also called, each time the text changes fol *all* changed lines + and may even be called for all lines after the change up to the end of text. + + After SetLine was called "GetToken*" should return information about the + first token on the line. + Note: Spaces are token too. + + - Next + Scan to the next token, on the line that was set by "SetLine" + "GetToken*" should return info about that next token. + + - GetEOL + Returns True, if "Next" was called while on the last token of the line. + + - GetTokenEx, GetTokenAttribute + Provide info about the token found by "Next" + + - Next, GetEOL. GetToken* + Are used by SynEdit to iterate over the Line. + Important: The tokens returned for each line, must represent the original + line-text (mothing added, nothing left out), and be returned in the correct order. + + They are called very often and should perform ath high speed. + + - GetToken, GetTokenPos, GetTokenKind + SynEdit uses them e.g for finding matching brackets. If GetTokenKind returns different values per Attribute, then brackets only match, if they are of the same kind (e.g, if there was a string attribute, brackets outside a string would not match brackets inside a string) + + +*) + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, Graphics, SynEditTypes, SynEditHighlighter; + +type + + { TSynDemoHl } + + + TSynDemoHl = class(TSynCustomHighlighter) + private + FNotAttri: TSynHighlighterAttributes; + fSpecialAttri: TSynHighlighterAttributes; + fIdentifierAttri: TSynHighlighterAttributes; + fSpaceAttri: TSynHighlighterAttributes; + procedure SetIdentifierAttri(AValue: TSynHighlighterAttributes); + procedure SetNotAttri(AValue: TSynHighlighterAttributes); + procedure SetSpaceAttri(AValue: TSynHighlighterAttributes); + procedure SetSpecialAttri(AValue: TSynHighlighterAttributes); + protected + // accesible for the other examples + FTokenPos, FTokenEnd: Integer; + FLineText: String; + public + procedure SetLine(const NewValue: String; LineNumber: Integer); override; + procedure Next; override; + function GetEol: Boolean; override; + procedure GetTokenEx(out TokenStart: PChar; out TokenLength: integer); override; + function GetTokenAttribute: TSynHighlighterAttributes; override; + public + function GetToken: String; override; + function GetTokenPos: Integer; override; + function GetTokenKind: integer; override; + function GetDefaultAttribute(Index: integer): TSynHighlighterAttributes; override; + constructor Create(AOwner: TComponent); override; + published + (* Define 4 Attributes, for the different highlights. *) + property SpecialAttri: TSynHighlighterAttributes read fSpecialAttri + write SetSpecialAttri; + property NotAttri: TSynHighlighterAttributes read FNotAttri + write SetNotAttri; + property IdentifierAttri: TSynHighlighterAttributes read fIdentifierAttri + write SetIdentifierAttri; + property SpaceAttri: TSynHighlighterAttributes read fSpaceAttri + write SetSpaceAttri; + end; + +implementation + +constructor TSynDemoHl.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + + (* Create and initialize the attributes *) + fSpecialAttri := TSynHighlighterAttributes.Create('special', 'special'); + AddAttribute(fSpecialAttri); + fSpecialAttri.Style := [fsBold]; + + FNotAttri := TSynHighlighterAttributes.Create('not', 'not'); + AddAttribute(FNotAttri); + FNotAttri.Background := clRed; + + fIdentifierAttri := TSynHighlighterAttributes.Create('ident', 'ident'); + AddAttribute(fIdentifierAttri); + + fSpaceAttri := TSynHighlighterAttributes.Create('space', 'space'); + AddAttribute(fSpaceAttri); + fSpaceAttri.FrameColor := clSilver; + fSpaceAttri.FrameEdges := sfeAround; +end; + +(* Setters for attributes / This allows using in Object inspector*) +procedure TSynDemoHl.SetIdentifierAttri(AValue: TSynHighlighterAttributes); +begin + fIdentifierAttri.Assign(AValue); +end; + +procedure TSynDemoHl.SetNotAttri(AValue: TSynHighlighterAttributes); +begin + FNotAttri.Assign(AValue); +end; + +procedure TSynDemoHl.SetSpaceAttri(AValue: TSynHighlighterAttributes); +begin + fSpaceAttri.Assign(AValue); +end; + +procedure TSynDemoHl.SetSpecialAttri(AValue: TSynHighlighterAttributes); +begin + fSpecialAttri.Assign(AValue); +end; + +procedure TSynDemoHl.SetLine(const NewValue: String; LineNumber: Integer); +begin + inherited; + FLineText := NewValue; + // Next will start at "FTokenEnd", so set this to 1 + FTokenEnd := 1; + Next; +end; + +procedure TSynDemoHl.Next; +var + l: Integer; +begin + // FTokenEnd should be at the start of the next Token (which is the Token we want) + FTokenPos := FTokenEnd; + // assume empty, will only happen for EOL + FTokenEnd := FTokenPos; + + // Scan forward + // FTokenEnd will be set 1 after the last char. That is: + // - The first char of the next token + // - or past the end of line (which allows GetEOL to work) + + l := length(FLineText); + If FTokenPos > l then + // At line end + exit + else + if FLineText[FTokenEnd] in [#9, ' '] then + // At Space? Find end of spaces + while (FTokenEnd <= l) and (FLineText[FTokenEnd] in [#0..#32]) do inc (FTokenEnd) + else + // At None-Space? Find end of None-spaces + while (FTokenEnd <= l) and not(FLineText[FTokenEnd] in [#9, ' ']) do inc (FTokenEnd) +end; + +function TSynDemoHl.GetEol: Boolean; +begin + Result := FTokenPos > length(FLineText); +end; + +procedure TSynDemoHl.GetTokenEx(out TokenStart: PChar; out TokenLength: integer); +begin + TokenStart := @FLineText[FTokenPos]; + TokenLength := FTokenEnd - FTokenPos; +end; + +function TSynDemoHl.GetTokenAttribute: TSynHighlighterAttributes; +begin + // Match the text, specified by FTokenPos and FTokenEnd + + if FLineText[FTokenPos] in [#9, ' '] then + Result := SpaceAttri + else + if LowerCase(FLineText[FTokenPos]) in ['a', 'e', 'i', 'o', 'u'] then + Result := SpecialAttri + else + if LowerCase(copy(FLineText, FTokenPos, FTokenEnd - FTokenPos)) = 'not' then + Result := NotAttri + else + Result := IdentifierAttri; +end; + +function TSynDemoHl.GetToken: String; +begin + Result := copy(FLineText, FTokenPos, FTokenEnd - FTokenPos); +end; + +function TSynDemoHl.GetTokenPos: Integer; +begin + Result := FTokenPos - 1; +end; + +function TSynDemoHl.GetDefaultAttribute(Index: integer): TSynHighlighterAttributes; +begin + // Some default attributes + case Index of + SYN_ATTR_COMMENT: Result := fSpecialAttri; + SYN_ATTR_IDENTIFIER: Result := fIdentifierAttri; + SYN_ATTR_WHITESPACE: Result := fSpaceAttri; + else Result := nil; + end; +end; + +function TSynDemoHl.GetTokenKind: integer; +var + a: TSynHighlighterAttributes; +begin + // Map Attribute into a unique number + a := GetTokenAttribute; + Result := 0; + if a = fSpaceAttri then Result := 1; + if a = fSpecialAttri then Result := 2; + if a = fIdentifierAttri then Result := 3; + if a = FNotAttri then Result := 4; +end; + +end. + diff --git a/examples/SynEdit/NewHighlighterTutorial/unit1.lfm b/examples/SynEdit/NewHighlighterTutorial/unit1.lfm new file mode 100644 index 0000000000..045a6a9fe9 --- /dev/null +++ b/examples/SynEdit/NewHighlighterTutorial/unit1.lfm @@ -0,0 +1,560 @@ +object Form1: TForm1 + Left = 365 + Height = 443 + Top = 142 + Width = 655 + Caption = 'Form1' + ClientHeight = 443 + ClientWidth = 655 + OnCreate = FormCreate + LCLVersion = '0.9.31' + inline SynEdit1: TSynEdit + Left = 0 + Height = 383 + Top = 0 + Width = 655 + Align = alTop + Anchors = [akTop, akLeft, akRight, akBottom] + Font.Height = -13 + Font.Name = 'Courier New' + Font.Pitch = fpFixed + Font.Quality = fqNonAntialiased + ParentColor = False + ParentFont = False + TabOrder = 0 + Gutter.Width = 57 + Gutter.MouseActions = <> + RightGutter.Width = 0 + RightGutter.MouseActions = <> + Keystrokes = < + item + Command = ecUp + ShortCut = 38 + end + item + Command = ecSelUp + ShortCut = 8230 + end + item + Command = ecScrollUp + ShortCut = 16422 + end + item + Command = ecDown + ShortCut = 40 + end + item + Command = ecSelDown + ShortCut = 8232 + end + item + Command = ecScrollDown + ShortCut = 16424 + end + item + Command = ecLeft + ShortCut = 37 + end + item + Command = ecSelLeft + ShortCut = 8229 + end + item + Command = ecWordLeft + ShortCut = 16421 + end + item + Command = ecSelWordLeft + ShortCut = 24613 + end + item + Command = ecRight + ShortCut = 39 + end + item + Command = ecSelRight + ShortCut = 8231 + end + item + Command = ecWordRight + ShortCut = 16423 + end + item + Command = ecSelWordRight + ShortCut = 24615 + end + item + Command = ecPageDown + ShortCut = 34 + end + item + Command = ecSelPageDown + ShortCut = 8226 + end + item + Command = ecPageBottom + ShortCut = 16418 + end + item + Command = ecSelPageBottom + ShortCut = 24610 + end + item + Command = ecPageUp + ShortCut = 33 + end + item + Command = ecSelPageUp + ShortCut = 8225 + end + item + Command = ecPageTop + ShortCut = 16417 + end + item + Command = ecSelPageTop + ShortCut = 24609 + end + item + Command = ecLineStart + ShortCut = 36 + end + item + Command = ecSelLineStart + ShortCut = 8228 + end + item + Command = ecEditorTop + ShortCut = 16420 + end + item + Command = ecSelEditorTop + ShortCut = 24612 + end + item + Command = ecLineEnd + ShortCut = 35 + end + item + Command = ecSelLineEnd + ShortCut = 8227 + end + item + Command = ecEditorBottom + ShortCut = 16419 + end + item + Command = ecSelEditorBottom + ShortCut = 24611 + end + item + Command = ecToggleMode + ShortCut = 45 + end + item + Command = ecCopy + ShortCut = 16429 + end + item + Command = ecPaste + ShortCut = 8237 + end + item + Command = ecDeleteChar + ShortCut = 46 + end + item + Command = ecCut + ShortCut = 8238 + end + item + Command = ecDeleteLastChar + ShortCut = 8 + end + item + Command = ecDeleteLastChar + ShortCut = 8200 + end + item + Command = ecDeleteLastWord + ShortCut = 16392 + end + item + Command = ecUndo + ShortCut = 32776 + end + item + Command = ecRedo + ShortCut = 40968 + end + item + Command = ecLineBreak + ShortCut = 13 + end + item + Command = ecSelectAll + ShortCut = 16449 + end + item + Command = ecCopy + ShortCut = 16451 + end + item + Command = ecBlockIndent + ShortCut = 24649 + end + item + Command = ecLineBreak + ShortCut = 16461 + end + item + Command = ecInsertLine + ShortCut = 16462 + end + item + Command = ecDeleteWord + ShortCut = 16468 + end + item + Command = ecBlockUnindent + ShortCut = 24661 + end + item + Command = ecPaste + ShortCut = 16470 + end + item + Command = ecCut + ShortCut = 16472 + end + item + Command = ecDeleteLine + ShortCut = 16473 + end + item + Command = ecDeleteEOL + ShortCut = 24665 + end + item + Command = ecUndo + ShortCut = 16474 + end + item + Command = ecRedo + ShortCut = 24666 + end + item + Command = ecGotoMarker0 + ShortCut = 16432 + end + item + Command = ecGotoMarker1 + ShortCut = 16433 + end + item + Command = ecGotoMarker2 + ShortCut = 16434 + end + item + Command = ecGotoMarker3 + ShortCut = 16435 + end + item + Command = ecGotoMarker4 + ShortCut = 16436 + end + item + Command = ecGotoMarker5 + ShortCut = 16437 + end + item + Command = ecGotoMarker6 + ShortCut = 16438 + end + item + Command = ecGotoMarker7 + ShortCut = 16439 + end + item + Command = ecGotoMarker8 + ShortCut = 16440 + end + item + Command = ecGotoMarker9 + ShortCut = 16441 + end + item + Command = ecSetMarker0 + ShortCut = 24624 + end + item + Command = ecSetMarker1 + ShortCut = 24625 + end + item + Command = ecSetMarker2 + ShortCut = 24626 + end + item + Command = ecSetMarker3 + ShortCut = 24627 + end + item + Command = ecSetMarker4 + ShortCut = 24628 + end + item + Command = ecSetMarker5 + ShortCut = 24629 + end + item + Command = ecSetMarker6 + ShortCut = 24630 + end + item + Command = ecSetMarker7 + ShortCut = 24631 + end + item + Command = ecSetMarker8 + ShortCut = 24632 + end + item + Command = ecSetMarker9 + ShortCut = 24633 + end + item + Command = EcFoldLevel1 + ShortCut = 41009 + end + item + Command = EcFoldLevel2 + ShortCut = 41010 + end + item + Command = EcFoldLevel1 + ShortCut = 41011 + end + item + Command = EcFoldLevel1 + ShortCut = 41012 + end + item + Command = EcFoldLevel1 + ShortCut = 41013 + end + item + Command = EcFoldLevel6 + ShortCut = 41014 + end + item + Command = EcFoldLevel7 + ShortCut = 41015 + end + item + Command = EcFoldLevel8 + ShortCut = 41016 + end + item + Command = EcFoldLevel9 + ShortCut = 41017 + end + item + Command = EcFoldLevel0 + ShortCut = 41008 + end + item + Command = EcFoldCurrent + ShortCut = 41005 + end + item + Command = EcUnFoldCurrent + ShortCut = 41003 + end + item + Command = EcToggleMarkupWord + ShortCut = 32845 + end + item + Command = ecNormalSelect + ShortCut = 24654 + end + item + Command = ecColumnSelect + ShortCut = 24643 + end + item + Command = ecLineSelect + ShortCut = 24652 + end + item + Command = ecTab + ShortCut = 9 + end + item + Command = ecShiftTab + ShortCut = 8201 + end + item + Command = ecMatchBracket + ShortCut = 24642 + end + item + Command = ecColSelUp + ShortCut = 40998 + end + item + Command = ecColSelDown + ShortCut = 41000 + end + item + Command = ecColSelLeft + ShortCut = 40997 + end + item + Command = ecColSelRight + ShortCut = 40999 + end + item + Command = ecColSelPageDown + ShortCut = 40994 + end + item + Command = ecColSelPageBottom + ShortCut = 57378 + end + item + Command = ecColSelPageUp + ShortCut = 40993 + end + item + Command = ecColSelPageTop + ShortCut = 57377 + end + item + Command = ecColSelLineStart + ShortCut = 40996 + end + item + Command = ecColSelLineEnd + ShortCut = 40995 + end + item + Command = ecColSelEditorTop + ShortCut = 57380 + end + item + Command = ecColSelEditorBottom + ShortCut = 57379 + end> + MouseActions = <> + MouseSelActions = <> + Lines.Strings = ( + 'This is an example how to write a highlighter from scratch.' + 'See the units for each example highlighter.' + '--' + 'This is NOT about extending the IDE. This is about SynEdit and it''s Highlighter only.' + 'Therefore this does not include: ++' + '- registration in the component pallette.' + '- Using the Object Inspector' + 'Those steps are the same as they would be for any other self wriiten componont.' + '' + '-(-' + 'Lorem ipsum dolor sit amet, ' + 'consectetur adipisicing elit, ' + 'sed -- do eiusmod tempor incididunt ut labore et dolore magna aliqua. ' + '-- (Nested double -) Ut enim ad minim veniam, ' + 'quis nostrud exercitation ++ (Nested double +) ullamco laboris nisi ut aliquip ex ea commodo consequat. ' + 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. ' + '++ Excepteur sint occaecat cupidatat non proident, ' + 'sunt in culpa qui officia deserunt mollit anim id est laborum.' + '-(- --' + 'Lorem ipsum dolor sit amet, ' + 'consectetur adipisicing elit, ' + 'sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ' + '++ Ut enim ad minim veniam, ' + 'quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ' + 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. ' + 'Excepteur sint occaecat cupidatat non proident, ' + 'sunt in culpa qui officia deserunt mollit anim id est laborum.' + '-)-' + '-)-' + '' + ) + VisibleSpecialChars = [vscSpace, vscTabAtLast] + BracketHighlightStyle = sbhsBoth + BracketMatchColor.Background = clNone + BracketMatchColor.Foreground = clNone + BracketMatchColor.Style = [fsBold] + FoldedCodeColor.Background = clNone + FoldedCodeColor.Foreground = clGray + FoldedCodeColor.FrameColor = clGray + MouseLinkColor.Background = clNone + MouseLinkColor.Foreground = clBlue + LineHighlightColor.Background = clNone + LineHighlightColor.Foreground = clNone + inline SynLeftGutterPartList1: TSynGutterPartList + object SynGutterMarks1: TSynGutterMarks + Width = 24 + MouseActions = <> + end + object SynGutterLineNumber1: TSynGutterLineNumber + Width = 17 + MouseActions = <> + MarkupInfo.Background = clBtnFace + MarkupInfo.Foreground = clNone + DigitCount = 2 + ShowOnlyLineNumbersMultiplesOf = 1 + ZeroStart = False + LeadingZeros = False + end + object SynGutterChanges1: TSynGutterChanges + Width = 4 + MouseActions = <> + ModifiedColor = 59900 + SavedColor = clGreen + end + object SynGutterSeparator1: TSynGutterSeparator + Width = 2 + MouseActions = <> + end + object SynGutterCodeFolding1: TSynGutterCodeFolding + MouseActions = <> + MarkupInfo.Background = clNone + MarkupInfo.Foreground = clGray + MouseActionsExpanded = <> + MouseActionsCollapsed = <> + end + end + end + object Button1: TButton + Left = 21 + Height = 25 + Top = 408 + Width = 75 + Anchors = [akLeft, akBottom] + Caption = 'SimpleHl' + OnClick = Button1Click + TabOrder = 1 + end + object Button2: TButton + Left = 136 + Height = 25 + Top = 408 + Width = 75 + Anchors = [akLeft, akBottom] + Caption = 'ContextHl' + OnClick = Button2Click + TabOrder = 2 + end + object Button3: TButton + Left = 256 + Height = 25 + Top = 408 + Width = 75 + Anchors = [akLeft, akBottom] + Caption = 'FoldHl' + OnClick = Button3Click + TabOrder = 3 + end +end diff --git a/examples/SynEdit/NewHighlighterTutorial/unit1.pas b/examples/SynEdit/NewHighlighterTutorial/unit1.pas new file mode 100644 index 0000000000..13dd275bc8 --- /dev/null +++ b/examples/SynEdit/NewHighlighterTutorial/unit1.pas @@ -0,0 +1,78 @@ +unit Unit1; +(* + +This is an example how to write a highlighter from scratch. + + See the units for each example highlighter. + +This is NOT about extending the IDE. This is about SynEdit and it's Highlighter only. +Therefore this does not include: +- registration in the component pallette. +- Using the Object Inspector +Those steps are the same as they would be for any other self wriiten componont. + +*) +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, FileUtil, SynEdit, Forms, Controls, Graphics, Dialogs, StdCtrls, + SimpleHl, ContextHL, FoldHl; + +type + + { TForm1 } + + TForm1 = class(TForm) + Button1: TButton; + Button2: TButton; + Button3: TButton; + SynEdit1: TSynEdit; + procedure Button1Click(Sender: TObject); + procedure Button2Click(Sender: TObject); + procedure Button3Click(Sender: TObject); + procedure FormCreate(Sender: TObject); + private + { private declarations } + FSynDemoHl: TSynDemoHl; + FSynDemoHlContext: TSynDemoHlContext; + FSynDemoHlFold: TSynDemoHlFold; + public + { public declarations } + end; + +var + Form1: TForm1; + +implementation + +{$R *.lfm} + +{ TForm1 } + +procedure TForm1.FormCreate(Sender: TObject); +begin + FSynDemoHl := TSynDemoHl.Create(Self); + FSynDemoHlContext := TSynDemoHlContext.Create(Self); + FSynDemoHlFold := TSynDemoHlFold.Create(Self); + SynEdit1.Highlighter := FSynDemoHl; +end; + +procedure TForm1.Button1Click(Sender: TObject); +begin + SynEdit1.Highlighter := FSynDemoHl; +end; + +procedure TForm1.Button2Click(Sender: TObject); +begin + SynEdit1.Highlighter := FSynDemoHlContext; +end; + +procedure TForm1.Button3Click(Sender: TObject); +begin + SynEdit1.Highlighter := FSynDemoHlFold; +end; + +end. +