mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-20 19:29:26 +02:00
Nested comment syntax highlighting
This commit is contained in:
parent
297ed5cb0c
commit
67bee1b652
@ -24,7 +24,7 @@ uses
|
||||
WEditor,WCEdit,
|
||||
Comphook,Browcol,
|
||||
WHTMLScn,
|
||||
FPViews,FPSymbol
|
||||
FPViews,FPSymbol,FPSwitch
|
||||
{$ifndef NODEBUG}
|
||||
,fpevalw
|
||||
{$endif};
|
||||
@ -52,6 +52,7 @@ type
|
||||
procedure UpdateMode;
|
||||
procedure UpdateRunMenu(DebuggeeRunning : boolean);
|
||||
procedure UpdateTarget;
|
||||
procedure UpdateEditorsCompilerMode(OldMode:TCompilerMode);
|
||||
procedure GetEvent(var Event: TEvent); virtual;
|
||||
procedure HandleEvent(var Event: TEvent); virtual;
|
||||
procedure GetTileRect(var R: TRect); virtual;
|
||||
@ -184,7 +185,7 @@ uses
|
||||
Dos{,Memory},Menus,Dialogs,StdDlg,timeddlg,
|
||||
Systems,
|
||||
WUtils,WHlpView,WViews,WHTMLHlp,WHelp,WConsole,
|
||||
FPConst,FPVars,FPUtils,FPSwitch,FPIni,FPIntf,FPCompil,FPHelp,
|
||||
FPConst,FPVars,FPUtils,FPIni,FPIntf,FPCompil,FPHelp,
|
||||
FPTemplt,FPCalc,FPUsrScr,FPTools,
|
||||
{$ifndef NODEBUG}
|
||||
FPDebug,FPRegs,
|
||||
|
@ -21,6 +21,7 @@ var R,R2: TRect;
|
||||
SwitchesCount : integer;
|
||||
LastItem: PSItem;
|
||||
L: longint;
|
||||
OldCompilerMode: TCompilerMode;
|
||||
begin
|
||||
SwitchesCount:=ord(high(TSwitchMode))-ord(low(TSwitchMode))+1;
|
||||
R.Assign(0,0,36,4+SwitchesCount);
|
||||
@ -52,8 +53,12 @@ begin
|
||||
end;
|
||||
InsertButtons(D);
|
||||
RB^.Select;
|
||||
OldCompilerMode:=TCompilerMode(CompilerModeSwitches^.GetCurrSelParamID());
|
||||
if Desktop^.ExecView(D)=cmOK then
|
||||
begin
|
||||
SwitchesMode:=TSwitchMode(RB^.Value);
|
||||
UpdateEditorsCompilerMode(OldCompilerMode);
|
||||
end;
|
||||
Dispose(D, Done);
|
||||
UpdateMode;
|
||||
UpdateTarget;
|
||||
@ -77,6 +82,7 @@ var R,R2,R3,TabR,TabIR: TRect;
|
||||
Label31,Label41,
|
||||
Label51,Label52,Label53: PLabel;
|
||||
TargetHeight,ProcessorHeight: sw_integer;
|
||||
OldCompilerMode: TCompilerMode;
|
||||
begin
|
||||
{decide height of dialog view}
|
||||
GetExtent(R);
|
||||
@ -372,6 +378,7 @@ begin
|
||||
InsertButtons(D);
|
||||
if Desktop^.ExecView(D)=cmOK then
|
||||
begin
|
||||
OldCompilerMode:= TCompilerMode(CompilerModeSwitches^.GetCurrSelParamID());
|
||||
for I:=0 to SyntaxSwitches^.ItemCount-1 do
|
||||
SyntaxSwitches^.SetBooleanItem(I,CB1^.Mark(I));
|
||||
CompilerModeSwitches^.SetCurrSel(RB2^.Value);
|
||||
@ -390,10 +397,32 @@ begin
|
||||
BrowserSwitches^.SetCurrSel(RB4^.Value);
|
||||
ConditionalSwitches^.SetStringItem(0,IL^.Data^);
|
||||
CustomArg[SwitchesMode]:=IL2^.Data^;
|
||||
UpdateEditorsCompilerMode(OldCompilerMode);
|
||||
end;
|
||||
Dispose(D, Done);
|
||||
end;
|
||||
|
||||
procedure TIDEApp.UpdateEditorsCompilerMode(OldMode:TCompilerMode);
|
||||
|
||||
procedure UpdateEditor(P: PView);
|
||||
begin
|
||||
if assigned(P) and (TypeOf(P^)=TypeOf(TSourceWindow)) then
|
||||
begin
|
||||
PSourceWindow(P)^.Editor^.UpdateAttrs(0,attrForceFull);
|
||||
PSourceWindow(P)^.ReDraw;
|
||||
end;
|
||||
end;
|
||||
|
||||
var NewMode:TCompilerMode;
|
||||
begin
|
||||
NewMode:=TCompilerMode(CompilerModeSwitches^.GetCurrSelParamID());
|
||||
if (OldMode in [moFpc,moObjfpc]) and not (NewMode in [moFpc,moObjfpc]) then
|
||||
Desktop^.ForEach(TCallbackProcParam(@UpdateEditor))
|
||||
else
|
||||
if not (OldMode in [moFpc,moObjfpc]) and (NewMode in [moFpc,moObjfpc]) then
|
||||
Desktop^.ForEach(TCallbackProcParam(@UpdateEditor));
|
||||
end;
|
||||
|
||||
procedure TIDEApp.MemorySizes;
|
||||
var R,R2,R3: TRect;
|
||||
D: PCenterDialog;
|
||||
|
@ -130,10 +130,19 @@ type
|
||||
Align: TAlign;
|
||||
end;
|
||||
|
||||
const cMaxNestnessChanges = 20;
|
||||
type
|
||||
TNestnessPoints = array[0..cMaxNestnessChanges-1] of record X,Y:sw_integer;NC:boolean; end;
|
||||
|
||||
PSourceEditor = ^TSourceEditor;
|
||||
TSourceEditor = object(TFileEditor)
|
||||
CompileStamp : longint;
|
||||
CodeCompleteTip: PFPToolTip;
|
||||
{for nested comments managment}
|
||||
NestedComments : boolean;
|
||||
FixedNestedComments : TPoint;
|
||||
NestnessPoints:TNestnessPoints;
|
||||
NestPos : sw_integer;
|
||||
constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar:
|
||||
PScrollBar; AIndicator: PIndicator;const AFileName: string);
|
||||
{$ifndef NODEBUG}
|
||||
@ -146,6 +155,9 @@ type
|
||||
function IsAsmReservedWord(const S: string): boolean; virtual;
|
||||
function GetSpecSymbolCount(SpecClass: TSpecSymbolClass): integer; virtual;
|
||||
function GetSpecSymbol(SpecClass: TSpecSymbolClass; Index: integer): pstring; virtual;
|
||||
function ParseSourceNestedComments(X,Y : sw_integer): boolean; virtual;
|
||||
function IsNestedComments(X,Y : sw_integer): boolean; virtual;
|
||||
function NestedCommentsChangeCheck(CurLine : sw_integer):boolean; virtual;
|
||||
{ CodeTemplates }
|
||||
function TranslateCodeTemplate(var Shortcut: string; ALines: PUnsortedStringCollection): boolean; virtual;
|
||||
function SelectCodeTemplate(var ShortCut: string): boolean; virtual;
|
||||
@ -573,8 +585,8 @@ uses
|
||||
fpintf, { superseeds version_string of version unit }
|
||||
{$endif USE_EXTERNAL_COMPILER}
|
||||
{$ifdef VESA}Vesa,{$endif}
|
||||
FPSwitch,FPSymbol,FPDebug,FPVars,FPUtils,FPCompil,FPHelp,
|
||||
FPTools,FPIDE,FPCodTmp,FPCodCmp;
|
||||
FPSymbol,FPDebug,FPVars,FPUtils,FPCompil,FPHelp,
|
||||
FPTools,FPIDE,FPCodTmp,FPCodCmp,FPSwitch;
|
||||
|
||||
const
|
||||
RSourceEditor: TStreamRec = (
|
||||
@ -1283,6 +1295,8 @@ begin
|
||||
inherited Init(Bounds,AHScrollBar,AVScrollBar,AIndicator,EC,AFileName);
|
||||
SetStoreUndo(true);
|
||||
CompileStamp:=0;
|
||||
FixedNestedComments.Y:=2000001;
|
||||
NestedComments:=false;
|
||||
end;
|
||||
|
||||
Const
|
||||
@ -1293,8 +1307,8 @@ Const
|
||||
2,{ssCommentSuffix}
|
||||
1,{ssStringPrefix}
|
||||
1,{ssStringSuffix}
|
||||
1,{ssDirectivePrefix}
|
||||
1,{ssDirectiveSuffix}
|
||||
2,{ssDirectivePrefix}
|
||||
{2,}{ssDirectiveSuffix}
|
||||
1,{ssAsmPrefix}
|
||||
1 {ssAsmSuffix}
|
||||
);
|
||||
@ -1308,8 +1322,10 @@ Const
|
||||
FreePascalCommentSuffix2 : string[2] = '*)';
|
||||
FreePascalStringPrefix : string[1] = '''';
|
||||
FreePascalStringSuffix : string[1] = '''';
|
||||
FreePascalDirectivePrefix : string[2] = '{$';
|
||||
FreePascalDirectiveSuffix : string[1] = '}';
|
||||
FreePascalDirectivePrefix1 : string[2] = '{$';
|
||||
FreePascalDirectivePrefix2 : string[3] = '(*$';
|
||||
//FreePascalDirectiveSuffix1 : string[1] = '}';
|
||||
//FreePascalDirectiveSuffix2 : string[2] = '*)';
|
||||
FreePascalAsmPrefix : string[3] = 'ASM';
|
||||
FreePascalAsmSuffix : string[3] = 'END';
|
||||
|
||||
@ -1347,9 +1363,15 @@ begin
|
||||
ssAsmSuffix :
|
||||
GetSpecSymbol:=@FreePascalAsmSuffix;
|
||||
ssDirectivePrefix :
|
||||
GetSpecSymbol:=@FreePascalDirectivePrefix;
|
||||
ssDirectiveSuffix :
|
||||
GetSpecSymbol:=@FreePascalDirectiveSuffix;
|
||||
case Index of
|
||||
0 : GetSpecSymbol:=@FreePascalDirectivePrefix1;
|
||||
1 : GetSpecSymbol:=@FreePascalDirectivePrefix2;
|
||||
end;
|
||||
{ssDirectiveSuffix :
|
||||
case Index of
|
||||
0 : GetSpecSymbol:=@FreePascalDirectiveSuffix1;
|
||||
1 : GetSpecSymbol:=@FreePascalDirectiveSuffix2;
|
||||
end;}
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -1363,6 +1385,331 @@ begin
|
||||
IsAsmReservedWord:=IsFPAsmReservedWord(S);
|
||||
end;
|
||||
|
||||
function TSourceEditor.ParseSourceNestedComments(X,Y : sw_integer): boolean;
|
||||
const cModeNestedComments : array [TCompilerMode] of boolean =
|
||||
(false,true{fpc},true{objfpc},false,false,false,false,false,false,false);
|
||||
|
||||
function CompilerModeToNestedComments(AMode: String; ACurrentNestedComments:boolean):boolean;
|
||||
var SourceCompilerMode : TCompilerMode;
|
||||
begin
|
||||
SourceCompilerMode:=moNone;
|
||||
case length(AMode) of
|
||||
2 : if AMode='tp' then
|
||||
SourceCompilerMode:=moTp;
|
||||
3 : if AMode='fpc' then
|
||||
SourceCompilerMode:=moFpc
|
||||
else if AMode='iso' then
|
||||
SourceCompilerMode:=moIso;
|
||||
6 : if AMode='objfpc' then
|
||||
SourceCompilerMode:=moObjFpc
|
||||
else if AMode='delphi' then
|
||||
SourceCompilerMode:=moDelphi
|
||||
else if AMode='macpas' then
|
||||
SourceCompilerMode:=moMacPas;
|
||||
13: if AMode='delphiunicode' then
|
||||
SourceCompilerMode:=moDelphiUnicode;
|
||||
14: if AMode='extendedpascal' then
|
||||
SourceCompilerMode:=moExtendedPascal;
|
||||
end;
|
||||
if SourceCompilerMode=moNone then
|
||||
CompilerModeToNestedComments:=ACurrentNestedComments
|
||||
else
|
||||
CompilerModeToNestedComments:=cModeNestedComments[SourceCompilerMode];
|
||||
end;
|
||||
|
||||
procedure RegisterNestnessPoint( LineNr, X : sw_integer);
|
||||
begin
|
||||
NestnessPoints[NestPos].X:=X;
|
||||
NestnessPoints[NestPos].Y:=LineNr;
|
||||
NestnessPoints[NestPos].NC:=NestedComments;
|
||||
inc(NestPos);
|
||||
if NestPos=cMaxNestnessChanges then NestPos:=0;
|
||||
end;
|
||||
|
||||
var CurrentCompilerMode : TCompilerMode;
|
||||
CurX,CurY:sw_integer;
|
||||
S : sw_astring;
|
||||
crWord,prWord : sw_astring;
|
||||
ch,prCh,prprCh : AnsiChar;
|
||||
CommentStartX,CommentStartY:sw_integer;
|
||||
WordNpk : sw_integer;
|
||||
inCompilerDirective : boolean;
|
||||
inLineComment : boolean;
|
||||
inCurlyBracketComment : boolean;
|
||||
inBracketComment : boolean;
|
||||
inString : boolean;
|
||||
CommentDepth: sw_integer;
|
||||
CompilerDirective: sw_integer;
|
||||
ResultIsSet : boolean;
|
||||
begin
|
||||
CurrentCompilerMode:=TCompilerMode(CompilerModeSwitches^.GetCurrSelParamID);
|
||||
NestedComments:=cModeNestedComments[CurrentCompilerMode];
|
||||
ParseSourceNestedComments:=NestedComments;
|
||||
ResultIsSet:=false;
|
||||
RegisterNestnessPoint(0,0);
|
||||
if (not IsFlagSet(efSyntaxHighlight)) then
|
||||
begin {not ment to be syntax highlighted }
|
||||
FixedNestedComments.Y:=0;
|
||||
FixedNestedComments.X:=0;
|
||||
exit;
|
||||
end;
|
||||
FixedNestedComments.Y:=2000001;
|
||||
CurX:=0;
|
||||
CurY:=0;
|
||||
inCompilerDirective:=false;
|
||||
inLineComment:=false;
|
||||
inCurlyBracketComment:=false;
|
||||
inBracketComment:=false;
|
||||
inString:=false;
|
||||
CommentDepth:=0;
|
||||
CompilerDirective:=0;
|
||||
WordNpk:=0;
|
||||
NestPos:=0;
|
||||
while CurY<GetLineCount do
|
||||
begin
|
||||
S:=GetLineText(CurY)+' ';
|
||||
prCh:=#0;prprCh:=#0;
|
||||
CurX:=0;
|
||||
while CurX < length(S) do
|
||||
begin
|
||||
inc(CurX);
|
||||
ch := S[CurX];
|
||||
{-- comment part --}
|
||||
if not (inCompilerDirective or inLineComment or inCurlyBracketComment or inBracketComment or inString) then
|
||||
if (ch = '{') then
|
||||
begin
|
||||
inCurlyBracketComment:=true;
|
||||
CommentDepth:=0;
|
||||
CommentStartX:=CurX;
|
||||
CommentStartY:=CurY;
|
||||
end else
|
||||
if (ch = '*') and (prCh='(') then
|
||||
begin
|
||||
inBracketComment:=true;
|
||||
CommentDepth:=0;
|
||||
CommentStartX:=CurX;
|
||||
CommentStartY:=CurY;
|
||||
end;
|
||||
if (ch = '{') and inCurlyBracketComment then
|
||||
inc(CommentDepth);
|
||||
if (ch = '*') and (prCh='(') and inBracketComment then
|
||||
begin
|
||||
inc(CommentDepth);
|
||||
if CurX < length(S) then if S[CurX+1] = ')' then
|
||||
dec(CommentDepth); {in comment (*) is not begin comment but end}
|
||||
end;
|
||||
if (ch = '$') and (prCh='{') and inCurlyBracketComment and (CommentDepth=1) then
|
||||
begin
|
||||
inCompilerDirective:=true;
|
||||
CompilerDirective:=1;
|
||||
WordNpk:=0;
|
||||
end;
|
||||
if (ch = '$') and (prCh='*') and (prprCh='(') and inBracketComment and (CommentDepth=1) then
|
||||
begin
|
||||
inCompilerDirective:=true;
|
||||
CompilerDirective:=2;
|
||||
WordNpk:=0;
|
||||
end;
|
||||
if not (inCompilerDirective or inLineComment or inCurlyBracketComment or inBracketComment or inString) then
|
||||
if (ch = '/') and (prCh = '/') then
|
||||
inLineComment:=true;
|
||||
{-- string part --}
|
||||
if not (inCompilerDirective or inLineComment or inCurlyBracketComment or inBracketComment or inString) then
|
||||
if (ch = '''') then
|
||||
inString:=true;
|
||||
if (ch = '''') and inString then
|
||||
inString:=false;
|
||||
{-- word part --}
|
||||
if ch in ['a'..'z','.','_','A'..'Z','0'..'9'] then
|
||||
crWord:=crWord+ch
|
||||
else begin
|
||||
if length(crWord)>0 then
|
||||
begin
|
||||
crWord:=LowcaseStr(crWord);
|
||||
if inCompilerDirective then
|
||||
begin
|
||||
inc(WordNpk);
|
||||
if WordNpk=2 then
|
||||
begin
|
||||
if (prWord='mode') then
|
||||
begin
|
||||
NestedComments:=CompilerModeToNestedComments(crWord,NestedComments);
|
||||
RegisterNestnessPoint(CurY,CurX-1);
|
||||
end else
|
||||
if (prWord='modeswitch') and (crWord='nestedcomments') then
|
||||
begin
|
||||
if ch='-' then
|
||||
NestedComments:=false
|
||||
else
|
||||
NestedComments:=true;
|
||||
RegisterNestnessPoint(CurY,CurX-1);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if not (inCompilerDirective or inLineComment or inCurlyBracketComment or inBracketComment or inString) then
|
||||
begin
|
||||
if (crWord='uses')
|
||||
or (crWord='type')
|
||||
or (crWord='var')
|
||||
or (crWord='const')
|
||||
or (crWord='begin')
|
||||
or (crWord='implementation')
|
||||
or (crWord='function')
|
||||
or (crWord='procedure')
|
||||
then
|
||||
begin
|
||||
FixedNestedComments.Y:=CurY;
|
||||
FixedNestedComments.X:=CurX-1;
|
||||
if not ResultIsSet then
|
||||
ParseSourceNestedComments:=NestedComments;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
prWord:=crWord;
|
||||
crWord:='';
|
||||
end;
|
||||
{ --- comment close part ---- }
|
||||
if (ch = '}') and inCurlyBracketComment then
|
||||
begin
|
||||
dec(CommentDepth);
|
||||
if not NestedComments then
|
||||
CommentDepth:=0;
|
||||
if CommentDepth=0 then
|
||||
inCurlyBracketComment:=false;
|
||||
end;
|
||||
if (ch = ')') and (prCh='*') and inBracketComment then
|
||||
begin
|
||||
if (CommentStartY<>CurY) or ((CommentStartY=CurY) and ((CurX-CommentStartX)>3)) then
|
||||
begin
|
||||
dec(CommentDepth);
|
||||
if not NestedComments then
|
||||
CommentDepth:=0;
|
||||
if CommentDepth=0 then
|
||||
inBracketComment:=false;
|
||||
end;
|
||||
end;
|
||||
if (ch = '}') and inCompilerDirective and not inCurlyBracketComment then
|
||||
inCompilerDirective:=false;
|
||||
if (ch = ')') and (prCh='*') and inCompilerDirective and not inBracketComment then
|
||||
inCompilerDirective:=false;
|
||||
{ --- result --- }
|
||||
if (CurY=Y) and ((CurX-1)=X) then
|
||||
begin
|
||||
ParseSourceNestedComments:=NestedComments;
|
||||
ResultIsSet:=true;
|
||||
end;
|
||||
prprCh:=prCh;
|
||||
prCh:=ch;
|
||||
end; {end while one line}
|
||||
if inLineComment then
|
||||
inLineComment:=false;
|
||||
inc(CurY); {next line}
|
||||
if CurY=200 then break; {give up on line 200, it might not be a pascal source after all}
|
||||
end; {end while all lines}
|
||||
FixedNestedComments.Y:=CurY; { full(200 lines) parse was done }
|
||||
FixedNestedComments.X:=CurX;
|
||||
end;
|
||||
|
||||
function TSourceEditor.IsNestedComments(X,Y : sw_integer): boolean;
|
||||
var iPos : sw_integer;
|
||||
lastNC : boolean;
|
||||
begin
|
||||
if (FixedNestedComments.Y<Y) or ((FixedNestedComments.Y=Y) and (FixedNestedComments.X<=X)) then
|
||||
begin {we are at point where comment nestness is determined }
|
||||
IsNestedComments:=NestedComments;
|
||||
end else
|
||||
begin
|
||||
lastNC:=NestedComments;
|
||||
if NestPos>0 then
|
||||
for iPos:=0 to NestPos-1 do
|
||||
begin
|
||||
if (NestnessPoints[iPos].Y>Y) or ((NestnessPoints[iPos].Y=Y) and (NestnessPoints[iPos].X>=X)) then
|
||||
break;
|
||||
lastNC:=NestnessPoints[iPos].NC;
|
||||
end;
|
||||
IsNestedComments:=lastNC;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TSourceEditor.NestedCommentsChangeCheck(CurLine : sw_integer):boolean;
|
||||
|
||||
function CheckTantedLine(LineNr : sw_integer):boolean;
|
||||
function OneInTantetList (AWord : string):boolean;
|
||||
begin
|
||||
OneInTantetList:=false;
|
||||
if AWord='$mode' then OneInTantetList:=true else
|
||||
if AWord='nestedcomments' then OneInTantetList:=true;
|
||||
end;
|
||||
var S : sw_astring;
|
||||
CurX : sw_integer;
|
||||
ch, fo : AnsiChar;
|
||||
crWord : String;
|
||||
el : boolean;
|
||||
begin
|
||||
CheckTantedLine:=false;
|
||||
S:=GetLineText(LineNr);
|
||||
crWord:='';
|
||||
For CurX:=1 to length(S) do
|
||||
begin
|
||||
if length(crWord)=255 then crWord:=''; {overflow}
|
||||
ch:=LowCase(S[CurX]);
|
||||
el:=true;
|
||||
if ch in ['$','a'..'z'] then
|
||||
begin
|
||||
crWord:=crWord+ch;
|
||||
el:=false;
|
||||
end;
|
||||
if (el or (CurX=length(S))) and (crWord<>'') then
|
||||
begin
|
||||
if OneInTantetList(crWord) then
|
||||
begin
|
||||
CheckTantedLine:=true;
|
||||
break;
|
||||
end;
|
||||
crWord:='';
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
var Points : TNestnessPoints;
|
||||
iPos,iFrom,oNest : sw_integer;
|
||||
begin
|
||||
NestedCommentsChangeCheck:=false;
|
||||
if (FixedNestedComments.Y>=CurLine) then
|
||||
begin
|
||||
if FixedNestedComments.Y>=2000000 then
|
||||
begin
|
||||
ParseSourceNestedComments(0,CurLine+1);
|
||||
NestedCommentsChangeCheck:=true;
|
||||
end else
|
||||
begin
|
||||
Points:=NestnessPoints;
|
||||
iFrom:=-1;oNest:=NestPos;
|
||||
if NestPos>0 then
|
||||
for iPos:=0 to NestPos-1 do
|
||||
if Points[iPos].Y=CurLine then
|
||||
if iFrom<0 then begin iFrom:=iPos;break; end;
|
||||
if (iFrom>=0) or CheckTantedLine(CurLine) then
|
||||
begin {we have something to checkup}
|
||||
ParseSourceNestedComments(0,CurLine+1);
|
||||
if oNest=NestPos then
|
||||
begin
|
||||
for iPos:=0 to NestPos-1 do
|
||||
begin
|
||||
if Points[iPos].NC<>NestnessPoints[iPos].NC then
|
||||
begin
|
||||
NestedCommentsChangeCheck:=true;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
end else
|
||||
NestedCommentsChangeCheck:=true;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TSourceEditor.TranslateCodeTemplate(var Shortcut: string; ALines: PUnsortedStringCollection): boolean;
|
||||
begin
|
||||
TranslateCodeTemplate:=FPTranslateCodeTemplate(ShortCut,ALines);
|
||||
@ -4720,9 +5067,15 @@ begin
|
||||
ssAsmSuffix :
|
||||
GetSpecSymbol:=@FreePascalAsmSuffix;
|
||||
ssDirectivePrefix :
|
||||
GetSpecSymbol:=@FreePascalDirectivePrefix;
|
||||
ssDirectiveSuffix :
|
||||
GetSpecSymbol:=@FreePascalDirectiveSuffix;
|
||||
case Index of
|
||||
0 : GetSpecSymbol:=@FreePascalDirectivePrefix1;
|
||||
1 : GetSpecSymbol:=@FreePascalDirectivePrefix2;
|
||||
end;
|
||||
{ssDirectiveSuffix :
|
||||
case Index of
|
||||
0 : GetSpecSymbol:=@FreePascalDirectiveSuffix1;
|
||||
1 : GetSpecSymbol:=@FreePascalDirectiveSuffix2;
|
||||
end;}
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -266,6 +266,8 @@ type
|
||||
BeginsWithDirective,
|
||||
EndsWithDirective : boolean;
|
||||
BeginCommentType,EndCommentType : byte;
|
||||
BeginCommentDepth,EndCommentDepth : sw_integer;
|
||||
BeginNestedComments,EndNestedComments : byte;
|
||||
Fold: PFold;
|
||||
constructor Init(AEditor: PCustomCodeEditor);
|
||||
destructor Done; virtual;
|
||||
@ -345,7 +347,7 @@ type
|
||||
|
||||
TSpecSymbolClass =
|
||||
(ssCommentPrefix,ssCommentSingleLinePrefix,ssCommentSuffix,ssStringPrefix,ssStringSuffix,
|
||||
ssDirectivePrefix,ssDirectiveSuffix,ssAsmPrefix,ssAsmSuffix);
|
||||
ssDirectivePrefix{,ssDirectiveSuffix},ssAsmPrefix,ssAsmSuffix);
|
||||
|
||||
TEditorBookMark = record
|
||||
Valid : boolean;
|
||||
@ -510,6 +512,8 @@ type
|
||||
{a}procedure SetSyntaxCompleted(SC: boolean); virtual;
|
||||
{a}function GetLastSyntaxedLine: sw_integer; virtual;
|
||||
{a}procedure SetLastSyntaxedLine(ALine: sw_integer); virtual;
|
||||
function IsNestedComments(X,Y : sw_integer): boolean; virtual;
|
||||
function NestedCommentsChangeCheck(CurLine : sw_integer):boolean; virtual;
|
||||
function IsFlagSet(AFlag: longint): boolean;{$ifdef USEINLINE}inline;{$endif}
|
||||
function GetReservedColCount: sw_integer; virtual;
|
||||
{a}function GetTabSize: integer; virtual;
|
||||
@ -2108,8 +2112,12 @@ function TCustomCodeEditorCore.UpdateAttrs(FromLine: sw_integer; Attrs: byte): s
|
||||
var MinLine: sw_integer;
|
||||
procedure CallIt(P: PEditorBinding);
|
||||
var I: sw_integer;
|
||||
AAttrs:byte;
|
||||
begin
|
||||
I:=DoUpdateAttrs(P^.Editor,FromLine,Attrs);
|
||||
AAttrs:=Attrs;
|
||||
if P^.Editor^.NestedCommentsChangeCheck(FromLine) then
|
||||
AAttrs:=Attrs or attrForceFull;
|
||||
I:=DoUpdateAttrs(P^.Editor,FromLine,AAttrs);
|
||||
if (I<MinLine) or (MinLine=-1) then MinLine:=I;
|
||||
end;
|
||||
begin
|
||||
@ -2122,7 +2130,11 @@ function TCustomCodeEditorCore.UpdateAttrsRange(FromLine, ToLine: sw_integer; At
|
||||
var MinLine: sw_integer;
|
||||
procedure CallIt(P: PEditorBinding);
|
||||
var I: sw_integer;
|
||||
AAttrs:byte;
|
||||
begin
|
||||
AAttrs:=Attrs;
|
||||
if P^.Editor^.NestedCommentsChangeCheck(FromLine) then
|
||||
AAttrs:=Attrs or attrForceFull;
|
||||
I:=DoUpdateAttrsRange(P^.Editor,FromLine,ToLine,Attrs);
|
||||
if (I<MinLine) or (MinLine=-1) then MinLine:=I;
|
||||
end;
|
||||
@ -2139,7 +2151,11 @@ type
|
||||
ccHash,ccSymbol);
|
||||
var
|
||||
SymbolIndex: Sw_integer;
|
||||
CurLineNr: Sw_integer;
|
||||
CurrentCommentType : Byte;
|
||||
CurrentCommentDepth : sw_integer;
|
||||
NestedComments,LookForNestedComments : boolean;
|
||||
CommentStartX,CommentStartY : sw_integer;
|
||||
FirstCC,LastCC: TCharClass;
|
||||
InAsm,InComment,InSingleLineComment,InDirective,InString: boolean;
|
||||
X,ClassStart: Sw_integer;
|
||||
@ -2235,6 +2251,18 @@ var
|
||||
begin
|
||||
IsCommentPrefix:=MatchesAnySpecSymbol(ssCommentPrefix,pmLeft);
|
||||
end;
|
||||
|
||||
function IsMatchingCommentPrefix: boolean;
|
||||
var tmpIs : boolean;
|
||||
begin {looking for nested comments with matching prefix}
|
||||
tmpIs:=(MatchesAnySpecSymbol(ssCommentPrefix,pmLeft));
|
||||
if tmpIs
|
||||
and (CurrentCommentType=2) {bad, we are making assumption that this is comment opener (* }
|
||||
and (LineText[X+1]=')') { looking into next char is bad aproach but it is working }
|
||||
then
|
||||
tmpIs:=false; { in comment this "(*)" is not start of new nested comment but end }
|
||||
IsMatchingCommentPrefix:= tmpIs and (CurrentCommentType=SymbolIndex);
|
||||
end;
|
||||
{** **}
|
||||
function IsSingleLineCommentPrefix: boolean;
|
||||
begin
|
||||
@ -2242,9 +2270,13 @@ var
|
||||
end;
|
||||
|
||||
function IsCommentSuffix: boolean;
|
||||
var tmpIs : boolean;
|
||||
begin
|
||||
IsCommentSuffix:=(MatchesAnySpecSymbol(ssCommentSuffix,pmRight))
|
||||
tmpIs:=(MatchesAnySpecSymbol(ssCommentSuffix,pmRight))
|
||||
and (CurrentCommentType=SymbolIndex);
|
||||
if tmpIs then
|
||||
tmpIs:=(CurLineNr<>CommentStartY) or ((CurLineNr=CommentStartY) and ((X-length(MatchingSymbol))-CommentStartX>=0));
|
||||
IsCommentSuffix:=tmpIs;
|
||||
end;
|
||||
|
||||
function IsStringPrefix: boolean;
|
||||
@ -2259,13 +2291,15 @@ var
|
||||
|
||||
function IsDirectivePrefix: boolean;
|
||||
begin
|
||||
IsDirectivePrefix:=MatchesAnySpecSymbol(ssDirectivePrefix,pmLeft);
|
||||
IsDirectivePrefix:=MatchesAnySpecSymbol(ssDirectivePrefix,pmLeft)
|
||||
and (CurrentCommentType=SymbolIndex); {yes - matching comment type}
|
||||
end;
|
||||
|
||||
{ Directive is treated as comment. Comment suffix will close directive.
|
||||
function IsDirectiveSuffix: boolean;
|
||||
begin
|
||||
IsDirectiveSuffix:=MatchesAnySpecSymbol(ssDirectiveSuffix,pmRight);
|
||||
end;
|
||||
end;}
|
||||
|
||||
function IsAsmPrefix(const WordS: string): boolean;
|
||||
{ var
|
||||
@ -2409,9 +2443,9 @@ var
|
||||
if InComment and IsCommentSuffix then
|
||||
Inc(EX) else
|
||||
if InString and IsStringSuffix then
|
||||
Inc(EX) else
|
||||
Inc(EX) {else
|
||||
if InDirective and IsDirectiveSuffix then
|
||||
Inc(EX);
|
||||
Inc(EX)};
|
||||
end;
|
||||
if CC=ccRealNumber then
|
||||
Inc(EX);
|
||||
@ -2427,35 +2461,58 @@ var
|
||||
ccNumber :
|
||||
if (LastCC<>ccAlpha) then;
|
||||
ccSymbol :
|
||||
if (InComment=true) and (CurrentCommentType=1) and
|
||||
if (InComment=true) and (CurrentCommentDepth=1) and
|
||||
(InDirective=false) and IsDirectivePrefix then
|
||||
begin
|
||||
InDirective:=true;
|
||||
InComment:=false;
|
||||
{InComment:=false;} { treat compiler directive as comment }
|
||||
{CurrentCommentType:=0;}
|
||||
Dec(ClassStart,length(MatchingSymbol)-1);
|
||||
end
|
||||
else if (InComment=false) and
|
||||
else {if (InComment=false) and
|
||||
(InDirective=true) and IsDirectiveSuffix then
|
||||
InDirective:=false
|
||||
else if (InComment=false) and
|
||||
else }if (InComment=false) and
|
||||
(InString=false) and (InDirective=false) and IsCommentPrefix then
|
||||
begin
|
||||
InComment:=true;
|
||||
LookForNestedComments:=true;
|
||||
CurrentCommentType:=SymbolIndex;
|
||||
CurrentCommentDepth:=1;
|
||||
InSingleLineComment:=IsSingleLineCommentPrefix;
|
||||
CommentStartX:=X;
|
||||
CommentStartY:=CurLineNr;
|
||||
{InString:=false; }
|
||||
Dec(ClassStart,length(MatchingSymbol)-1);
|
||||
{ Remove (* from SymbolConcat to avoid problem with (*) PM }
|
||||
{ fixes part of bug 1617 }
|
||||
{ but removed proper directive prefix detection ... }
|
||||
{ Well. Added false positive end suffix detection. Do not remove. M
|
||||
EndComment:=Editor^.GetSpecSymbol(ssCommentSuffix,SymbolIndex);
|
||||
if MatchingSymbol[length(MatchingSymbol)]=EndComment^[1] then
|
||||
Delete(SymbolConcat,1,length(MatchingSymbol));
|
||||
Delete(SymbolConcat,1,length(MatchingSymbol));}
|
||||
end
|
||||
else if InComment and IsMatchingCommentPrefix then
|
||||
begin
|
||||
inc(CurrentCommentDepth);
|
||||
if LookForNestedComments then
|
||||
begin { once per every nested comment test IsNestedCommments }
|
||||
LookForNestedComments:=false;
|
||||
NestedComments:=Editor^.IsNestedComments(X,CurLineNr);
|
||||
end;
|
||||
end
|
||||
else if InComment and IsCommentSuffix then
|
||||
begin
|
||||
InComment:=false;
|
||||
InString:=false;
|
||||
dec(CurrentCommentDepth);
|
||||
if not NestedComments then
|
||||
CurrentCommentDepth:=0;
|
||||
if CurrentCommentDepth=0 then
|
||||
begin
|
||||
InComment:=false;
|
||||
CurrentCommentType:=0;
|
||||
InDirective:=false; {not in comment then not in Directive}
|
||||
InString:=false;
|
||||
end;
|
||||
end
|
||||
else if (InComment=false) and (InString=false) and IsStringPrefix then
|
||||
begin
|
||||
@ -2471,8 +2528,7 @@ var
|
||||
end;
|
||||
end;
|
||||
|
||||
var CurLineNr: Sw_integer;
|
||||
Line,NextLine,PrevLine{,OldLine}: PCustomLine;
|
||||
var Line,NextLine,PrevLine{,OldLine}: PCustomLine;
|
||||
PrevLI,LI,nextLI: PEditorLineInfo;
|
||||
begin
|
||||
if (not Editor^.IsFlagSet(efSyntaxHighlight)) or (FromLine>=GetLineCount) then
|
||||
@ -2503,6 +2559,7 @@ begin
|
||||
PrevLine:=GetLine(CurLineNr-1)
|
||||
else
|
||||
PrevLine:=nil;
|
||||
CommentStartY:=CurLineNr-1; { use in detection for false positive commment: (*) }
|
||||
repeat
|
||||
Line:=GetLine(CurLineNr);
|
||||
if Assigned(PrevLine) then PrevLI:=PrevLine^.GetEditorInfo(Editor) else PrevLI:=nil;
|
||||
@ -2513,6 +2570,9 @@ begin
|
||||
InAsm:=PrevLI^.EndsWithAsm;
|
||||
InComment:=PrevLI^.EndsWithComment and not PrevLI^.EndsInSingleLineComment;
|
||||
CurrentCommentType:=PrevLI^.EndCommentType;
|
||||
CurrentCommentDepth:=PrevLI^.EndCommentDepth;
|
||||
NestedComments:=(PrevLI^.EndNestedComments and 1)=1;
|
||||
LookForNestedComments:=(PrevLI^.EndNestedComments and 2)=2;
|
||||
InDirective:=PrevLI^.EndsWithDirective;
|
||||
end
|
||||
else
|
||||
@ -2520,7 +2580,10 @@ begin
|
||||
InAsm:=false;
|
||||
InComment:=false;
|
||||
CurrentCommentType:=0;
|
||||
CurrentCommentDepth:=0;
|
||||
InDirective:=false;
|
||||
NestedComments:=false;
|
||||
LookForNestedComments:=false;
|
||||
end;
|
||||
{ OldLine:=Line;}
|
||||
if (not Editor^.IsFlagSet(efKeepLineAttr)) then
|
||||
@ -2529,6 +2592,9 @@ begin
|
||||
LI^.BeginsWithComment:=InComment;
|
||||
LI^.BeginsWithDirective:=InDirective;
|
||||
LI^.BeginCommentType:=CurrentCommentType;
|
||||
LI^.BeginCommentDepth:=CurrentCommentDepth;
|
||||
LI^.BeginNestedComments:=byte(NestedComments) and 1;
|
||||
LI^.BeginNestedComments:=LI^.BeginNestedComments or ((byte(LookForNestedComments)and 1) shl 1);
|
||||
end
|
||||
else
|
||||
begin
|
||||
@ -2536,6 +2602,9 @@ begin
|
||||
InComment:=LI^.BeginsWithComment;
|
||||
InDirective:=LI^.BeginsWithDirective;
|
||||
CurrentCommentType:=LI^.BeginCommentType;
|
||||
CurrentCommentDepth:=LI^.BeginCommentDepth;
|
||||
NestedComments:=(LI^.BeginNestedComments and 1)=1;
|
||||
LookForNestedComments:=(LI^.BeginNestedComments and 2)=2;
|
||||
end;
|
||||
LineText:=GetLineText(CurLineNr);
|
||||
Format:=CharStr(chr(coTextColor),length(LineText));
|
||||
@ -2554,6 +2623,9 @@ begin
|
||||
LI^.EndsWithAsm:=InAsm;
|
||||
LI^.EndsWithComment:=InComment;
|
||||
LI^.EndsInSingleLineComment:=InSingleLineComment;
|
||||
LI^.EndNestedComments:=byte(NestedComments) and 1;
|
||||
LI^.EndNestedComments:=LI^.EndNestedComments or ((byte(LookForNestedComments)and 1) shl 1);
|
||||
LI^.EndCommentDepth:=CurrentCommentDepth;
|
||||
LI^.EndCommentType:=CurrentCommentType;
|
||||
LI^.EndsWithDirective:=InDirective;
|
||||
Inc(CurLineNr);
|
||||
@ -2577,6 +2649,8 @@ begin
|
||||
(NextLI^.BeginsWithComment=LI^.EndsWithComment) and
|
||||
(NextLI^.BeginsWithDirective=LI^.EndsWithDirective) and
|
||||
(NextLI^.BeginCommentType=LI^.EndCommentType) and
|
||||
(NextLI^.BeginNestedComments=LI^.EndNestedComments) and
|
||||
(NextLI^.BeginCommentDepth=LI^.EndCommentDepth) and
|
||||
(Length(NextLI^.GetFormat)>0) then
|
||||
Break;
|
||||
{$ifdef TEST_PARTIAL_SYNTAX}
|
||||
@ -2796,6 +2870,16 @@ begin
|
||||
Abstract;
|
||||
end;
|
||||
|
||||
function TCustomCodeEditor.IsNestedComments(X,Y : sw_integer): boolean;
|
||||
begin
|
||||
IsNestedComments:=false; {default behavior is no nested comments}
|
||||
end;
|
||||
|
||||
function TCustomCodeEditor.NestedCommentsChangeCheck(CurLine : sw_integer):boolean;
|
||||
begin
|
||||
NestedCommentsChangeCheck:=false;
|
||||
end;
|
||||
|
||||
function TCustomCodeEditor.IsFlagSet(AFlag: longint): boolean;{$ifdef USEINLINE}inline;{$endif}
|
||||
begin
|
||||
IsFlagSet:=(GetFlags and AFlag)=AFlag;
|
||||
|
Loading…
Reference in New Issue
Block a user