mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-11-01 07:29:30 +01:00
MG: codecompletion now checks for filebreaks, savefile now checks for filedate
git-svn-id: trunk@1828 -
This commit is contained in:
parent
c775c0e5d4
commit
0e368232da
@ -129,13 +129,13 @@ function FindFirstNonSpaceCharInLine(const Source: string;
|
||||
Position: integer): integer;
|
||||
function GetLineIndent(const Source: string; Position: integer): integer;
|
||||
function FindLineEndOrCodeInFrontOfPosition(const Source: string;
|
||||
Position: integer; NestedComments: boolean): integer;
|
||||
Position, MinPosition: integer; NestedComments: boolean): integer;
|
||||
function FindLineEndOrCodeAfterPosition(const Source: string;
|
||||
Position: integer; NestedComments: boolean): integer;
|
||||
Position, MaxPosition: integer; NestedComments: boolean): integer;
|
||||
function FindFirstLineEndInFrontOfInCode(const Source: string;
|
||||
Position: integer; NestedComments: boolean): integer;
|
||||
Position, MinPosition: integer; NestedComments: boolean): integer;
|
||||
function FindFirstLineEndAfterInCode(const Source: string;
|
||||
Position: integer; NestedComments: boolean): integer;
|
||||
Position, MaxPosition: integer; NestedComments: boolean): integer;
|
||||
function ReplacementNeedsLineEnd(const Source: string;
|
||||
FromPos, ToPos, NewLength, MaxLineLength: integer): boolean;
|
||||
function CountNeededLineEndsToAddForward(const Src: string;
|
||||
@ -1159,7 +1159,7 @@ begin
|
||||
end;
|
||||
|
||||
function FindLineEndOrCodeAfterPosition(const Source: string;
|
||||
Position: integer; NestedComments: boolean): integer;
|
||||
Position, MaxPosition: integer; NestedComments: boolean): integer;
|
||||
{ search forward for a line end or code
|
||||
ignore line ends in comments
|
||||
Result is Position of Start of Line End
|
||||
@ -1214,6 +1214,7 @@ var SrcLen: integer;
|
||||
|
||||
begin
|
||||
SrcLen:=length(Source);
|
||||
if SrcLen>MaxPosition then SrcLen:=MaxPosition;
|
||||
Result:=Position;
|
||||
if Result=0 then exit;
|
||||
while (Result<=SrcLen) do begin
|
||||
@ -1234,7 +1235,7 @@ begin
|
||||
end;
|
||||
|
||||
function FindLineEndOrCodeInFrontOfPosition(const Source: string;
|
||||
Position: integer; NestedComments: boolean): integer;
|
||||
Position, MinPosition: integer; NestedComments: boolean): integer;
|
||||
{ search backward for a line end or code
|
||||
ignore line ends in comments or at the end of comment lines
|
||||
(comment lines are lines without code and at least one comment)
|
||||
@ -1264,61 +1265,74 @@ function FindLineEndOrCodeInFrontOfPosition(const Source: string;
|
||||
2: comment */ |
|
||||
3: a:=1;
|
||||
}
|
||||
procedure ReadComment(var P: integer);
|
||||
var SrcStart: integer;
|
||||
|
||||
function ReadComment(var P: integer): boolean;
|
||||
// false if compiler directive
|
||||
var OldP: integer;
|
||||
begin
|
||||
OldP:=P;
|
||||
case Source[P] of
|
||||
'}':
|
||||
begin
|
||||
dec(P);
|
||||
while (P>=1) and (Source[P]<>'{') do begin
|
||||
while (P>=SrcStart) and (Source[P]<>'{') do begin
|
||||
if NestedComments and (Source[P] in ['}',')']) then
|
||||
ReadComment(P)
|
||||
else
|
||||
dec(P);
|
||||
end;
|
||||
Result:=not ((P>=SrcStart) and (Source[P+1]='$'));
|
||||
dec(P);
|
||||
end;
|
||||
')':
|
||||
begin
|
||||
dec(P);
|
||||
if (P>=1) and (Source[P]='*') then begin
|
||||
if (P>=SrcStart) and (Source[P]='*') then begin
|
||||
dec(P);
|
||||
while (P>1)
|
||||
while (P>SrcStart)
|
||||
and ((Source[P-1]<>'(') or (Source[P]<>'*')) do begin
|
||||
if NestedComments and (Source[P] in ['}',')']) then
|
||||
ReadComment(P)
|
||||
else
|
||||
dec(P);
|
||||
end;
|
||||
Result:=not ((P>=SrcStart) and (Source[P+1]='$'));
|
||||
dec(P,2);
|
||||
end;
|
||||
end else
|
||||
Result:=true;
|
||||
end;
|
||||
else
|
||||
Result:=true;
|
||||
end;
|
||||
if not Result then P:=OldP+1;
|
||||
end;
|
||||
|
||||
var TestPos: integer;
|
||||
OnlySpace: boolean;
|
||||
begin
|
||||
if Position<=1 then begin
|
||||
Result:=1;
|
||||
SrcStart:=MinPosition;
|
||||
if SrcStart<1 then SrcStart:=1;
|
||||
if Position<=SrcStart then begin
|
||||
Result:=SrcStart;
|
||||
exit;
|
||||
end;
|
||||
Result:=Position-1;
|
||||
if Result>length(Source) then Result:=length(Source);
|
||||
while (Result>0) do begin
|
||||
while (Result>=SrcStart) do begin
|
||||
case Source[Result] of
|
||||
'}',')':
|
||||
ReadComment(Result);
|
||||
if not ReadComment(Result) then exit;
|
||||
#10,#13:
|
||||
begin
|
||||
// line end in code found
|
||||
if (Result>1) and (Source[Result-1] in [#10,#13])
|
||||
if (Result>SrcStart) and (Source[Result-1] in [#10,#13])
|
||||
and (Source[Result]<>Source[Result-1]) then dec(Result);
|
||||
// test if it is a comment line (a line without code and at least one
|
||||
// comment)
|
||||
TestPos:=Result-1;
|
||||
OnlySpace:=true;
|
||||
while (TestPos>1) do begin
|
||||
while (TestPos>SrcStart) do begin
|
||||
if (Source[TestPos]='/') and (Source[TestPos-1]='/') then begin
|
||||
// this is a comment line end -> search further
|
||||
dec(TestPos);
|
||||
@ -1347,10 +1361,11 @@ begin
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if Result<SrcStart then Result:=SrcStart;
|
||||
end;
|
||||
|
||||
function FindFirstLineEndAfterInCode(const Source: string;
|
||||
Position: integer; NestedComments: boolean): integer;
|
||||
Position, MaxPosition: integer; NestedComments: boolean): integer;
|
||||
{ search forward for a line end
|
||||
ignore line ends in comments
|
||||
Result is Position of Start of Line End
|
||||
@ -1405,6 +1420,7 @@ var SrcLen: integer;
|
||||
|
||||
begin
|
||||
SrcLen:=length(Source);
|
||||
if SrcLen>MaxPosition then SrcLen:=MaxPosition;
|
||||
Result:=Position;
|
||||
while (Result<=SrcLen) do begin
|
||||
case Source[Result] of
|
||||
@ -1419,18 +1435,21 @@ begin
|
||||
end;
|
||||
|
||||
function FindFirstLineEndInFrontOfInCode(const Source: string;
|
||||
Position: integer; NestedComments: boolean): integer;
|
||||
Position, MinPosition: integer; NestedComments: boolean): integer;
|
||||
{ search backward for a line end
|
||||
ignore line ends in comments
|
||||
Result will be at the Start of the Line End
|
||||
}
|
||||
var
|
||||
SrcStart: integer;
|
||||
|
||||
procedure ReadComment(var P: integer);
|
||||
begin
|
||||
case Source[P] of
|
||||
'}':
|
||||
begin
|
||||
dec(P);
|
||||
while (P>=1) and (Source[P]<>'{') do begin
|
||||
while (P>=SrcStart) and (Source[P]<>'{') do begin
|
||||
if NestedComments and (Source[P] in ['}',')']) then
|
||||
ReadComment(P)
|
||||
else
|
||||
@ -1441,9 +1460,9 @@ function FindFirstLineEndInFrontOfInCode(const Source: string;
|
||||
')':
|
||||
begin
|
||||
dec(P);
|
||||
if (P>=1) and (Source[P]='*') then begin
|
||||
if (P>=SrcStart) and (Source[P]='*') then begin
|
||||
dec(P);
|
||||
while (P>1)
|
||||
while (P>SrcStart)
|
||||
and ((Source[P-1]<>'(') or (Source[P]<>'*')) do begin
|
||||
if NestedComments and (Source[P] in ['}',')']) then
|
||||
ReadComment(P)
|
||||
@ -1459,17 +1478,19 @@ function FindFirstLineEndInFrontOfInCode(const Source: string;
|
||||
var TestPos: integer;
|
||||
begin
|
||||
Result:=Position;
|
||||
while (Result>0) do begin
|
||||
SrcStart:=MinPosition;
|
||||
if SrcStart<1 then SrcStart:=1;
|
||||
while (Result>=SrcStart) do begin
|
||||
case Source[Result] of
|
||||
'}',')':
|
||||
ReadComment(Result);
|
||||
#10,#13:
|
||||
begin
|
||||
// test if it is a '//' comment
|
||||
if (Result>1) and (Source[Result-1] in [#10,#13])
|
||||
if (Result>SrcStart) and (Source[Result-1] in [#10,#13])
|
||||
and (Source[Result]<>Source[Result-1]) then dec(Result);
|
||||
TestPos:=Result-1;
|
||||
while (TestPos>1) do begin
|
||||
while (TestPos>SrcStart) do begin
|
||||
if (Source[TestPos]='/') and (Source[TestPos-1]='/') then begin
|
||||
// this is a comment line end -> search further
|
||||
break;
|
||||
|
||||
@ -25,7 +25,6 @@
|
||||
|
||||
TCodeBuffer is an descendent of TSourceLog and manages a single file.
|
||||
|
||||
ToDo:
|
||||
}
|
||||
unit CodeCache;
|
||||
|
||||
@ -113,7 +112,8 @@ type
|
||||
FGlobalWriteLockIsSet: boolean;
|
||||
FGlobalWriteLockStep: integer;
|
||||
function OnScannerGetSource(Sender: TObject; Code: pointer): TSourceLog;
|
||||
function OnScannerLoadSource(Sender: TObject; const AFilename: string): pointer;
|
||||
function OnScannerLoadSource(Sender: TObject; const AFilename: string;
|
||||
OnlyIfExists: boolean): pointer;
|
||||
function OnScannerGetFileName(Sender: TObject; Code: pointer): string;
|
||||
function OnScannerCheckFileOnDisk(Code: pointer): boolean;
|
||||
procedure OnScannerIncludeCode(ParentCode, IncludeCode: pointer);
|
||||
@ -379,9 +379,12 @@ begin
|
||||
end;
|
||||
|
||||
function TCodeCache.OnScannerLoadSource(Sender: TObject;
|
||||
const AFilename: string): pointer;
|
||||
const AFilename: string; OnlyIfExists: boolean): pointer;
|
||||
begin
|
||||
Result:=LoadFile(AFilename);
|
||||
if OnlyIfExists and (not FileExists(AFilename)) then
|
||||
Result:=FindFile(AFilename)
|
||||
else
|
||||
Result:=LoadFile(AFilename);
|
||||
if Result<>nil then
|
||||
OnScannerCheckFileOnDisk(Result);
|
||||
end;
|
||||
|
||||
@ -915,14 +915,12 @@ begin
|
||||
if InsertNode<>nil then begin
|
||||
// insert after InsertNode
|
||||
Indent:=GetLineIndent(Src,InsertNode.StartPos);
|
||||
InsertPos:=FindFirstLineEndAfterInCode(Src,InsertNode.EndPos,
|
||||
Scanner.NestedComments);
|
||||
InsertPos:=FindFirstLineEndAfterInCode(InsertNode.EndPos);
|
||||
end else begin
|
||||
// insert as first variable/proc
|
||||
Indent:=GetLineIndent(Src,ClassSectionNode.StartPos)
|
||||
+ASourceChangeCache.BeautifyCodeOptions.Indent;
|
||||
InsertPos:=FindFirstLineEndAfterInCode(Src,ClassSectionNode.StartPos,
|
||||
Scanner.NestedComments);
|
||||
InsertPos:=FindFirstLineEndAfterInCode(ClassSectionNode.StartPos);
|
||||
end;
|
||||
end;
|
||||
CurCode:=ANodeExt.ExtTxt1;
|
||||
@ -1251,8 +1249,8 @@ var
|
||||
or (ImplementationNode.LastChild.Desc<>ctnBeginBlock) then
|
||||
InsertPos:=ImplementationNode.EndPos
|
||||
else begin
|
||||
InsertPos:=FindLineEndOrCodeInFrontOfPosition(Src,
|
||||
ImplementationNode.LastChild.StartPos,Scanner.NestedComments);
|
||||
InsertPos:=FindLineEndOrCodeInFrontOfPosition(
|
||||
ImplementationNode.LastChild.StartPos);
|
||||
end;
|
||||
end else begin
|
||||
// class is not in interface section
|
||||
@ -1386,8 +1384,7 @@ begin
|
||||
|
||||
// set default insert position
|
||||
Indent:=GetLineIndent(Src,LastExistingProcBody.StartPos);
|
||||
InsertPos:=FindLineEndOrCodeAfterPosition(Src,
|
||||
LastExistingProcBody.EndPos,Scanner.NestedComments);
|
||||
InsertPos:=FindLineEndOrCodeAfterPosition(LastExistingProcBody.EndPos);
|
||||
|
||||
// check for all defined class methods (MissingNode), if there is a body
|
||||
MissingNode:=ClassProcs.FindHighest;
|
||||
@ -1415,12 +1412,10 @@ begin
|
||||
Indent:=GetLineIndent(Src,ANode.StartPos);
|
||||
if cmp>0 then begin
|
||||
// insert behind ExistingNode
|
||||
InsertPos:=FindLineEndOrCodeAfterPosition(Src,
|
||||
ANode.EndPos,Scanner.NestedComments);
|
||||
InsertPos:=FindLineEndOrCodeAfterPosition(ANode.EndPos);
|
||||
end else begin
|
||||
// insert in front of ExistingNode
|
||||
InsertPos:=FindLineEndOrCodeInFrontOfPosition(Src,
|
||||
ANode.StartPos,Scanner.NestedComments);
|
||||
InsertPos:=FindLineEndOrCodeInFrontOfPosition(ANode.StartPos);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -1451,16 +1446,14 @@ begin
|
||||
// see above (note 1) for ANodeExt2.Data
|
||||
ANode:=TCodeTreeNodeExtension(ANodeExt2.Data).Node;
|
||||
Indent:=GetLineIndent(Src,ANode.StartPos);
|
||||
InsertPos:=FindLineEndOrCodeAfterPosition(Src,
|
||||
ANode.EndPos,Scanner.NestedComments);
|
||||
InsertPos:=FindLineEndOrCodeAfterPosition(ANode.EndPos);
|
||||
end else if NextAVLNode<>nil then begin
|
||||
// there is a NextAVLNode behind -> insert in front of body
|
||||
ANodeExt2:=TCodeTreeNodeExtension(NextAVLNode.Data);
|
||||
// see above (note 1) for ANodeExt2.Data
|
||||
ANode:=TCodeTreeNodeExtension(ANodeExt2.Data).Node;
|
||||
Indent:=GetLineIndent(Src,ANode.StartPos);
|
||||
InsertPos:=FindLineEndOrCodeInFrontOfPosition(Src,
|
||||
ANode.StartPos,Scanner.NestedComments);
|
||||
InsertPos:=FindLineEndOrCodeInFrontOfPosition(ANode.StartPos);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
@ -1609,12 +1602,11 @@ var CleanCursorPos, Indent, insertPos: integer;
|
||||
if (ImplementationNode.LastChild=nil)
|
||||
or (ImplementationNode.LastChild.Desc<>ctnBeginBlock) then
|
||||
// insert at end of code
|
||||
InsertPos:=FindLineEndOrCodeInFrontOfPosition(Src,
|
||||
ImplementationNode.EndPos,Scanner.NestedComments)
|
||||
InsertPos:=FindLineEndOrCodeInFrontOfPosition(ImplementationNode.EndPos)
|
||||
else begin
|
||||
// insert in front of main program begin..end.
|
||||
InsertPos:=FindLineEndOrCodeInFrontOfPosition(Src,
|
||||
ImplementationNode.LastChild.StartPos,Scanner.NestedComments);
|
||||
InsertPos:=FindLineEndOrCodeInFrontOfPosition(
|
||||
ImplementationNode.LastChild.StartPos);
|
||||
end;
|
||||
|
||||
// build nice proc
|
||||
|
||||
@ -114,6 +114,9 @@ type
|
||||
var Caret:TCodeXYPosition; var NewTopLine: integer): boolean; // true=ok, false=invalid CleanPos
|
||||
procedure GetLineInfo(ACleanPos: integer;
|
||||
var ALineStart, ALineEnd, AFirstAtomStart, ALastAtomEnd: integer);
|
||||
function FindLineEndOrCodeAfterPosition(StartPos: integer): integer;
|
||||
function FindLineEndOrCodeInFrontOfPosition(StartPos: integer): integer;
|
||||
function FindFirstLineEndAfterInCode(StartPos: integer): integer;
|
||||
|
||||
function UpdateNeeded(OnlyInterfaceNeeded: boolean): boolean;
|
||||
procedure BeginParsing(DeleteNodes, OnlyInterfaceNeeded: boolean); virtual;
|
||||
@ -1591,6 +1594,56 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCustomCodeTool.FindLineEndOrCodeAfterPosition(StartPos: integer
|
||||
): integer;
|
||||
{ Searches a nice position in the cleaned source after StartPos.
|
||||
It will skip any space or comments (not directives) till next
|
||||
line end or compiler directive or code or include file end.
|
||||
}
|
||||
var
|
||||
LinkIndex, LinkEnd: integer;
|
||||
begin
|
||||
LinkIndex:=Scanner.LinkIndexAtCleanPos(StartPos);
|
||||
LinkEnd:=Scanner.LinkCleanedEndPos(LinkIndex);
|
||||
if LinkEnd>StartPos then
|
||||
Result:=BasicCodeTools.FindLineEndOrCodeAfterPosition(Src,
|
||||
StartPos,LinkEnd-1,Scanner.NestedComments)
|
||||
else
|
||||
Result:=StartPos;
|
||||
end;
|
||||
|
||||
function TCustomCodeTool.FindLineEndOrCodeInFrontOfPosition(StartPos: integer
|
||||
): integer;
|
||||
{ Searches a nice position in the cleaned source in front of StartPos.
|
||||
It will skip any space or comments (not directives) till next
|
||||
line end or compiler directive or code or include file end.
|
||||
}
|
||||
var
|
||||
LinkIndex, LinkStart: integer;
|
||||
begin
|
||||
LinkIndex:=Scanner.LinkIndexAtCleanPos(StartPos);
|
||||
LinkStart:=Scanner.Links[LinkIndex].CleanedPos;
|
||||
Result:=BasicCodeTools.FindLineEndOrCodeInFrontOfPosition(Src,
|
||||
StartPos,LinkStart,Scanner.NestedComments);
|
||||
end;
|
||||
|
||||
function TCustomCodeTool.FindFirstLineEndAfterInCode(StartPos: integer
|
||||
): integer;
|
||||
{ Searches a line end or code break in the cleaned source after StartPos.
|
||||
It will skip any line ends in comments.
|
||||
}
|
||||
var
|
||||
LinkIndex, LinkEnd: integer;
|
||||
begin
|
||||
LinkIndex:=Scanner.LinkIndexAtCleanPos(StartPos);
|
||||
LinkEnd:=Scanner.LinkCleanedEndPos(LinkIndex);
|
||||
if LinkEnd>StartPos then
|
||||
Result:=BasicCodeTools.FindFirstLineEndAfterInCode(Src,
|
||||
StartPos,LinkEnd-1,Scanner.NestedComments)
|
||||
else
|
||||
Result:=StartPos;
|
||||
end;
|
||||
|
||||
function TCustomCodeTool.UpdateNeeded(OnlyInterfaceNeeded: boolean): boolean;
|
||||
begin
|
||||
{$IFDEF CTDEBUG}
|
||||
|
||||
@ -840,7 +840,8 @@ function TFindDeclarationTool.FindUnitSource(const AnUnitName,
|
||||
{$IFDEF ShowTriedFiles}
|
||||
writeln('TFindDeclarationTool.FindUnitSource.LoadFile ',AFilename);
|
||||
{$ENDIF}
|
||||
NewCode:=TCodeBuffer(Scanner.OnLoadSource(Self,ExpandFilename(AFilename)));
|
||||
NewCode:=TCodeBuffer(Scanner.OnLoadSource(
|
||||
Self,ExpandFilename(AFilename),true));
|
||||
Result:=NewCode<>nil;
|
||||
end;
|
||||
|
||||
@ -974,7 +975,7 @@ begin
|
||||
if AnUnitInFilename<>'' then begin
|
||||
// unitname in 'filename'
|
||||
if FilenameIsAbsolute(AnUnitInFilename) then begin
|
||||
Result:=TCodeBuffer(Scanner.OnLoadSource(Self,AnUnitInFilename));
|
||||
Result:=TCodeBuffer(Scanner.OnLoadSource(Self,AnUnitInFilename,true));
|
||||
end else begin
|
||||
// search AnUnitInFilename in searchpath
|
||||
Result:=SearchFileInPath(UnitSrcSearchPath,AnUnitInFilename);
|
||||
|
||||
@ -54,8 +54,8 @@ type
|
||||
//----------------------------------------------------------------------------
|
||||
TOnGetSource = function(Sender: TObject; Code: Pointer): TSourceLog
|
||||
of object;
|
||||
TOnLoadSource = function(Sender: TObject; const AFilename: string): pointer
|
||||
of object;
|
||||
TOnLoadSource = function(Sender: TObject; const AFilename: string;
|
||||
OnlyIfExists: boolean): pointer of object;
|
||||
TOnGetSourceStatus = procedure(Sender: TObject; Code: Pointer;
|
||||
var ReadOnly: boolean) of object;
|
||||
TOnDeleteSource = procedure(Sender: TObject; Code: Pointer; Pos, Len: integer)
|
||||
@ -249,8 +249,10 @@ type
|
||||
function LinkIndexAtCleanPos(ACleanPos: integer): integer;
|
||||
function LinkIndexAtCursorPos(ACursorPos: integer; ACode: Pointer): integer;
|
||||
function LinkSize(Index: integer): integer;
|
||||
function LinkCleanedEndPos(Index: integer): integer;
|
||||
function FindFirstSiblingLink(LinkIndex: integer): integer;
|
||||
function FindParentLink(LinkIndex: integer): integer;
|
||||
//function FindFirstLinkIndexOfCodeInCleanPos
|
||||
|
||||
function CleanedSrc: string;
|
||||
function CursorToCleanPos(ACursorPos: integer; ACode: pointer;
|
||||
@ -259,7 +261,7 @@ type
|
||||
// 1=CursorPos beyond scanned code
|
||||
function CleanedPosToCursor(ACleanedPos: integer; var ACursorPos: integer;
|
||||
var ACode: Pointer): boolean;
|
||||
|
||||
|
||||
function WholeRangeIsWritable(CleanStartPos, CleanEndPos: integer): boolean;
|
||||
procedure FindCodeInRange(CleanStartPos, CleanEndPos: integer;
|
||||
UniqueSortedCodeList: TList);
|
||||
@ -531,15 +533,21 @@ begin
|
||||
Result:=CleanedLen-Links[Index].CleanedPos;
|
||||
end;
|
||||
|
||||
function TLinkScanner.FindFirstSiblingLink(LinkIndex: integer): integer;
|
||||
{ find link of the start of the code
|
||||
e.g. The resulting link SrcPos is always 1
|
||||
if LinkIndex is in the main code, the result will be 0
|
||||
if LinkIndex is in an include file, the result will be the first link of
|
||||
the include file. If the include file is included multiple times, it is
|
||||
treated as if they are different files.
|
||||
function TLinkScanner.LinkCleanedEndPos(Index: integer): integer;
|
||||
begin
|
||||
Result:=Links[Index].CleanedPos+LinkSize(Index);
|
||||
end;
|
||||
|
||||
ToDo: if include file include itself, directly or indirectly
|
||||
function TLinkScanner.FindFirstSiblingLink(LinkIndex: integer): integer;
|
||||
{ find link at the start of the code
|
||||
e.g. The resulting link SrcPos is always 1
|
||||
|
||||
if LinkIndex is in the main code, the result will be 0
|
||||
if LinkIndex is in an include file, the result will be the first link of
|
||||
the include file. If the include file is included multiple times, it is
|
||||
treated as if they are different files.
|
||||
|
||||
ToDo: if include file includes itself, directly or indirectly
|
||||
}
|
||||
var
|
||||
LastIndex: integer;
|
||||
@ -1893,14 +1901,13 @@ begin
|
||||
if Path<>'' then Path:=ExpandFilename(Path);
|
||||
FileNameOnly:=ExtractFilename(AFilename);
|
||||
Result:=nil;
|
||||
if FileExists(Path+FileNameOnly) then
|
||||
Result:=FOnLoadSource(Self,Path+FileNameOnly);
|
||||
Result:=FOnLoadSource(Self,Path+FileNameOnly,true);
|
||||
FileNameOnly:=lowercase(FileNameOnly);
|
||||
if (Result=nil) and (FileExists(Path+FileNameOnly)) then
|
||||
Result:=FOnLoadSource(Self,Path+FileNameOnly);
|
||||
if (Result=nil) then
|
||||
Result:=FOnLoadSource(Self,Path+FileNameOnly,true);
|
||||
FileNameOnly:=UpperCaseStr(FileNameOnly);
|
||||
if (Result=nil) and (FileExists(Path+FileNameOnly)) then
|
||||
Result:=FOnLoadSource(Self,Path+FileNameOnly);
|
||||
if (Result=nil) then
|
||||
Result:=FOnLoadSource(Self,Path+FileNameOnly,true);
|
||||
end;
|
||||
|
||||
function TLinkScanner.SearchIncludeFile(const AFilename: string;
|
||||
@ -1956,11 +1963,11 @@ begin
|
||||
if Result then exit;
|
||||
end else begin
|
||||
// main source has relative filename (= virtual)
|
||||
NewCode:=FOnLoadSource(Self,AFilename);
|
||||
NewCode:=FOnLoadSource(Self,AFilename,true);
|
||||
if NewCode=nil then
|
||||
NewCode:=FOnLoadSource(Self,lowercase(AFilename));
|
||||
NewCode:=FOnLoadSource(Self,lowercase(AFilename),true);
|
||||
if NewCode=nil then
|
||||
NewCode:=FOnLoadSource(Self,UpperCaseStr(AFilename));
|
||||
NewCode:=FOnLoadSource(Self,UpperCaseStr(AFilename),true);
|
||||
Result:=(NewCode<>nil);
|
||||
if Result then exit;
|
||||
end;
|
||||
|
||||
@ -835,8 +835,7 @@ begin
|
||||
// if there is a comment in front of the top position, it probably belongs
|
||||
// to the destination code
|
||||
// -> adjust the topline position, so that the comment is visible
|
||||
NewTopLineCleanPos:=FindLineEndOrCodeInFrontOfPosition(Src,
|
||||
NewTopLineCleanPos,Scanner.NestedComments);
|
||||
NewTopLineCleanPos:=FindLineEndOrCodeInFrontOfPosition(NewTopLineCleanPos);
|
||||
if (NewTopLineCleanPos>=1) and (Src[NewTopLineCleanPos] in [#13,#10])
|
||||
then begin
|
||||
inc(NewTopLineCleanPos);
|
||||
|
||||
@ -128,10 +128,10 @@ begin
|
||||
InsertAtom.StartPos:=ResourceCode.SourceLength+1;
|
||||
InsertAtom.EndPos:=ResourceCode.SourceLength+1;
|
||||
end;
|
||||
InsertAtom.StartPos:=FindLineEndOrCodeInFrontOfPosition(Src,
|
||||
InsertAtom.StartPos,false)+1;
|
||||
InsertAtom.EndPos:=FindLineEndOrCodeAfterPosition(Src,
|
||||
InsertAtom.EndPos,false);
|
||||
InsertAtom.StartPos:=BasicCodeTools.FindLineEndOrCodeInFrontOfPosition(Src,
|
||||
InsertAtom.StartPos,1,false)+1;
|
||||
InsertAtom.EndPos:=BasicCodeTools.FindLineEndOrCodeAfterPosition(Src,
|
||||
InsertAtom.EndPos,SrcLen,false);
|
||||
NewResData:=ResourceData;
|
||||
i:=length(NewResData);
|
||||
while (i>1) and (NewResData[i] in [' ',#10,#13]) do
|
||||
@ -164,7 +164,8 @@ begin
|
||||
Result:=true;
|
||||
OldAtom:=FindLazarusResource(ResourceCode,ResourceName);
|
||||
if (OldAtom.StartPos<1) then exit;
|
||||
OldAtom.EndPos:=FindLineEndOrCodeAfterPosition(Src,OldAtom.EndPos,false);
|
||||
OldAtom.EndPos:=BasicCodeTools.FindLineEndOrCodeAfterPosition(Src,
|
||||
OldAtom.EndPos,SrcLen,false);
|
||||
ResourceCode.Delete(OldAtom.StartPos,OldAtom.EndPos);
|
||||
end;
|
||||
|
||||
|
||||
@ -649,10 +649,9 @@ begin
|
||||
SourceChangeCache.MainScanner:=Scanner;
|
||||
OldPosition:=FindLazarusResourceInBuffer(ResourceCode,ResourceName);
|
||||
if OldPosition.StartPos>0 then begin
|
||||
OldPosition.StartPos:=FindLineEndOrCodeInFrontOfPosition(Src,
|
||||
OldPosition.StartPos,Scanner.NestedComments);
|
||||
OldPosition.EndPos:=FindFirstLineEndAfterInCode(Src,OldPosition.EndPos,
|
||||
Scanner.NestedComments);
|
||||
OldPosition.StartPos:=FindLineEndOrCodeInFrontOfPosition(
|
||||
OldPosition.StartPos);
|
||||
OldPosition.EndPos:=FindFirstLineEndAfterInCode(OldPosition.EndPos);
|
||||
if not SourceChangeCache.Replace(gtNone,gtNone,
|
||||
OldPosition.StartPos,OldPosition.EndPos,'') then exit;
|
||||
end;
|
||||
@ -798,16 +797,13 @@ begin
|
||||
if FromPos<1 then exit;
|
||||
SourceChangeCache.MainScanner:=Scanner;
|
||||
Indent:=GetLineIndent(Src,FromPos);
|
||||
FromPos:=FindLineEndOrCodeInFrontOfPosition(Src,FromPos,
|
||||
Scanner.NestedComments);
|
||||
FromPos:=FindLineEndOrCodeInFrontOfPosition(FromPos);
|
||||
SourceChangeCache.Replace(gtNewLine,gtNewLine,FromPos,FromPos,
|
||||
SourceChangeCache.BeautifyCodeOptions.BeautifyStatement(
|
||||
'Application.CreateForm('+AClassName+','+AVarName+');',Indent));
|
||||
end else begin
|
||||
FromPos:=FindLineEndOrCodeInFrontOfPosition(Src,OldPosition.StartPos,
|
||||
Scanner.NestedComments);
|
||||
ToPos:=FindFirstLineEndAfterInCode(Src,OldPosition.EndPos,
|
||||
Scanner.NestedComments);
|
||||
FromPos:=FindLineEndOrCodeInFrontOfPosition(OldPosition.StartPos);
|
||||
ToPos:=FindFirstLineEndAfterInCode(OldPosition.EndPos);
|
||||
SourceChangeCache.MainScanner:=Scanner;
|
||||
SourceChangeCache.Replace(gtNewLine,gtNewLine,FromPos,ToPos,
|
||||
SourceChangeCache.BeautifyCodeOptions.BeautifyStatement(
|
||||
@ -824,10 +820,8 @@ begin
|
||||
Result:=false;
|
||||
if FindCreateFormStatement(-1,'*',UpperVarName,Position)=-1 then
|
||||
exit;
|
||||
FromPos:=FindLineEndOrCodeInFrontOfPosition(Src,Position.StartPos,
|
||||
Scanner.NestedComments);
|
||||
ToPos:=FindFirstLineEndAfterInCode(Src,Position.EndPos,
|
||||
Scanner.NestedComments);
|
||||
FromPos:=FindLineEndOrCodeInFrontOfPosition(Position.StartPos);
|
||||
ToPos:=FindFirstLineEndAfterInCode(Position.EndPos);
|
||||
SourceChangeCache.MainScanner:=Scanner;
|
||||
SourceChangeCache.Replace(gtNone,gtNone,FromPos,ToPos,'');
|
||||
Result:=SourceChangeCache.Apply;
|
||||
@ -889,11 +883,10 @@ begin
|
||||
if FindCreateFormStatement(Position,'*','*',StatementPos)=-1 then
|
||||
break;
|
||||
Position:=StatementPos.EndPos;
|
||||
StatementPos.StartPos:=FindLineEndOrCodeInFrontOfPosition(Src,
|
||||
StatementPos.StartPos,Scanner.NestedComments);
|
||||
StatementPos.StartPos:=FindLineEndOrCodeInFrontOfPosition(
|
||||
StatementPos.StartPos);
|
||||
InsertPos:=StatementPos.StartPos;
|
||||
StatementPos.EndPos:=FindFirstLineEndAfterInCode(Src,
|
||||
StatementPos.EndPos,Scanner.NestedComments);
|
||||
StatementPos.EndPos:=FindFirstLineEndAfterInCode(StatementPos.EndPos);
|
||||
SourceChangeCache.Replace(gtNone,gtNone,
|
||||
StatementPos.StartPos,StatementPos.EndPos,'');
|
||||
until false;
|
||||
@ -984,8 +977,7 @@ begin
|
||||
Indent:=GetLineIndent(Src,SectionNode.StartPos)
|
||||
+SourceChangeCache.BeautifyCodeOptions.Indent;
|
||||
end;
|
||||
InsertPos:=FindLineEndOrCodeInFrontOfPosition(Src,SectionNode.EndPos,
|
||||
Scanner.NestedComments);
|
||||
InsertPos:=FindLineEndOrCodeInFrontOfPosition(SectionNode.EndPos);
|
||||
SourceChangeCache.Replace(gtNewLine,gtNewLine,InsertPos,InsertPos,
|
||||
SourceChangeCache.BeautifyCodeOptions.BeautifyStatement(
|
||||
VarName+':'+VarType+';',Indent)
|
||||
@ -1018,10 +1010,8 @@ begin
|
||||
if VarNode.FirstChild<>nil then begin
|
||||
// variable definition has the form 'VarName: VarType;'
|
||||
// -> delete whole line
|
||||
FromPos:=FindLineEndOrCodeInFrontOfPosition(Src,VarNode.StartPos,
|
||||
Scanner.NestedComments);
|
||||
ToPos:=FindFirstLineEndAfterInCode(Src,VarNode.EndPos,
|
||||
Scanner.NestedComments);
|
||||
FromPos:=FindLineEndOrCodeInFrontOfPosition(VarNode.StartPos);
|
||||
ToPos:=FindFirstLineEndAfterInCode(VarNode.EndPos);
|
||||
end else begin
|
||||
// variable definition has the form 'VarName, NextVarName: VarType;'
|
||||
// -> delete only 'VarName, '
|
||||
|
||||
16
ide/main.pp
16
ide/main.pp
@ -3695,7 +3695,7 @@ begin
|
||||
|
||||
// if nothing modified then a simple Save can be skipped
|
||||
if ([sfSaveToTestDir,sfSaveAs]*Flags=[])
|
||||
and (not ActiveUnitInfo.Modified) then begin
|
||||
and (not ActiveUnitInfo.NeedsSaveToDisk) then begin
|
||||
Result:=mrOk;
|
||||
exit;
|
||||
end;
|
||||
@ -5253,10 +5253,11 @@ begin
|
||||
Project1.GetUnitsChangedOnDisk(AnUnitList);
|
||||
if AnUnitList=nil then exit;
|
||||
Result:=ShowDiskDiffsDialog(AnUnitList);
|
||||
if Result in [mrYesToAll] then begin
|
||||
for i:=0 to AnUnitList.Count-1 do begin
|
||||
CurUnit:=TUnitInfo(AnUnitList[i]);
|
||||
writeln('AAA1 REVERTING ',CurUnit.Filename);
|
||||
if Result in [mrYesToAll] then
|
||||
Result:=mrOk;
|
||||
for i:=0 to AnUnitList.Count-1 do begin
|
||||
CurUnit:=TUnitInfo(AnUnitList[i]);
|
||||
if Result in [mrYesToAll] then begin
|
||||
if CurUnit.EditorIndex>=0 then begin
|
||||
Result:=DoOpenEditorFile('',CurUnit.EditorIndex,[ofRevert]);
|
||||
end else if CurUnit.IsMainUnit then begin
|
||||
@ -5264,6 +5265,8 @@ writeln('AAA1 REVERTING ',CurUnit.Filename);
|
||||
end else
|
||||
Result:=mrIgnore;
|
||||
if Result=mrAbort then exit;
|
||||
end else begin
|
||||
CurUnit.IgnoreCurrentFileDateOnDisk;
|
||||
end;
|
||||
Result:=mrOk;
|
||||
end;
|
||||
@ -6858,6 +6861,9 @@ end.
|
||||
|
||||
{ =============================================================================
|
||||
$Log$
|
||||
Revision 1.336 2002/08/07 09:55:26 lazarus
|
||||
MG: codecompletion now checks for filebreaks, savefile now checks for filedate
|
||||
|
||||
Revision 1.335 2002/08/05 08:56:54 lazarus
|
||||
MG: TMenuItems can now be enabled and disabled
|
||||
|
||||
|
||||
@ -79,8 +79,9 @@ type
|
||||
fFormName: string; // classname is always T<FormName>
|
||||
// this attribute contains the formname even if the unit is not loaded
|
||||
fHasResources: boolean; // source has resource file
|
||||
FIgnoreFileDateOnDiskValid: boolean;
|
||||
FIgnoreFileDateOnDisk: longint;
|
||||
fIsPartOfProject: boolean;
|
||||
fLastCheckedFileAge: longint;
|
||||
fLoaded: Boolean; // loaded in the source editor
|
||||
fModified: boolean;
|
||||
fOnFileBackup: TOnFileBackup;
|
||||
@ -134,8 +135,10 @@ type
|
||||
procedure IncreaseAutoRevertLock;
|
||||
procedure DecreaseAutoRevertLock;
|
||||
function IsAutoRevertLocked: boolean;
|
||||
function ChangedOnDisk: boolean;
|
||||
function ChangedOnDisk(CompareOnlyLoadSaveTime: boolean): boolean;
|
||||
procedure IgnoreCurrentFileDateOnDisk;
|
||||
function ShortFilename: string;
|
||||
function NeedsSaveToDisk: boolean;
|
||||
|
||||
{ Properties }
|
||||
property Breakpoints: TProjectBreakPointList
|
||||
@ -423,8 +426,10 @@ begin
|
||||
,MB_ABORTRETRYIGNORE);
|
||||
if Result=mrAbort then exit;
|
||||
if Result=mrIgnore then Result:=mrOk;
|
||||
end else
|
||||
end else begin
|
||||
Result:=mrOk;
|
||||
FIgnoreFileDateOnDiskValid:=true;
|
||||
end;
|
||||
until Result<>mrRetry;
|
||||
Result:=mrOk;
|
||||
end;
|
||||
@ -476,6 +481,7 @@ begin
|
||||
exit;
|
||||
end else begin
|
||||
Source:=NewSource;
|
||||
FIgnoreFileDateOnDiskValid:=true;
|
||||
Result:=mrOk;
|
||||
end;
|
||||
until Result<>mrRetry;
|
||||
@ -503,6 +509,7 @@ begin
|
||||
fForm := nil;
|
||||
fFormName := '';
|
||||
fHasResources := false;
|
||||
FIgnoreFileDateOnDiskValid:=false;
|
||||
fIsPartOfProject := false;
|
||||
Loaded := false;
|
||||
fModified := false;
|
||||
@ -679,12 +686,22 @@ begin
|
||||
Result:=fAutoRevertLockCount>0;
|
||||
end;
|
||||
|
||||
function TUnitInfo.ChangedOnDisk: boolean;
|
||||
function TUnitInfo.ChangedOnDisk(CompareOnlyLoadSaveTime: boolean): boolean;
|
||||
begin
|
||||
Result:=(Source<>nil) and (Source.FileOnDiskHasChanged)
|
||||
and (fLastCheckedFileAge<>Source.FileDateOnDisk);
|
||||
if Result then
|
||||
fLastCheckedFileAge:=Source.FileDateOnDisk;
|
||||
Result:=(Source<>nil) and (Source.FileOnDiskHasChanged);
|
||||
if Result
|
||||
and (not CompareOnlyLoadSaveTime)
|
||||
and FIgnoreFileDateOnDiskValid
|
||||
and (FIgnoreFileDateOnDisk=Source.FileDateOnDisk) then
|
||||
Result:=false;
|
||||
end;
|
||||
|
||||
procedure TUnitInfo.IgnoreCurrentFileDateOnDisk;
|
||||
begin
|
||||
if Source<>nil then begin
|
||||
FIgnoreFileDateOnDiskValid:=true;
|
||||
FIgnoreFileDateOnDisk:=Source.FileDateOnDisk;
|
||||
end
|
||||
end;
|
||||
|
||||
function TUnitInfo.ShortFilename: string;
|
||||
@ -696,12 +713,19 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TUnitInfo.NeedsSaveToDisk: boolean;
|
||||
begin
|
||||
Result:=IsVirtual or Modified or ChangedOnDisk(true)
|
||||
or (not FileExists(Filename));
|
||||
end;
|
||||
|
||||
procedure TUnitInfo.SetSource(ABuffer: TCodeBuffer);
|
||||
begin
|
||||
if fSource=ABuffer then exit;
|
||||
if (fSource<>nil) and IsAutoRevertLocked then
|
||||
fSource.UnlockAutoDiskRevert;
|
||||
fSource:=ABuffer;
|
||||
FIgnoreFileDateOnDiskValid:=false;
|
||||
if (fSource<>nil) then begin
|
||||
if IsAutoRevertLocked then
|
||||
fSource.LockAutoDiskRevert;
|
||||
@ -1657,7 +1681,7 @@ begin
|
||||
AnUnitList:=nil;
|
||||
AnUnitInfo:=fFirstAutoRevertLockedUnit;
|
||||
while (AnUnitInfo<>nil) do begin
|
||||
if AnUnitInfo.ChangedOnDisk then begin
|
||||
if AnUnitInfo.ChangedOnDisk(false) then begin
|
||||
if AnUnitList=nil then
|
||||
AnUnitList:=TList.Create;
|
||||
AnUnitList.Add(AnUnitInfo);
|
||||
@ -1852,6 +1876,9 @@ end.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.71 2002/08/07 09:55:28 lazarus
|
||||
MG: codecompletion now checks for filebreaks, savefile now checks for filedate
|
||||
|
||||
Revision 1.70 2002/08/01 14:10:30 lazarus
|
||||
MG: started file access monitoring for loaded files
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
// included by menus.pp
|
||||
{******************************************************************************
|
||||
TMainMenu
|
||||
******************************************************************************
|
||||
@ -15,6 +16,21 @@
|
||||
* *
|
||||
*****************************************************************************
|
||||
}
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
Method: TMainMenu.ItemChanged
|
||||
Params: none
|
||||
Returns: Nothing
|
||||
|
||||
Called whenever
|
||||
------------------------------------------------------------------------------}
|
||||
procedure TMainMenu.ItemChanged;
|
||||
begin
|
||||
{MenuChanged(nil, nil, False);
|
||||
if FWindowHandle <> 0 then
|
||||
SendMessage(FWindowHandle, CM_MENUCHANGED, 0, 0);}
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
Method: TMainMenu.Create
|
||||
Params: AOwner: the owner of the class
|
||||
@ -28,10 +44,14 @@ begin
|
||||
FCompStyle := csMainMenu;
|
||||
end;
|
||||
|
||||
// included by menus.pp
|
||||
|
||||
{ =============================================================================
|
||||
|
||||
$Log$
|
||||
Revision 1.4 2002/08/07 09:55:30 lazarus
|
||||
MG: codecompletion now checks for filebreaks, savefile now checks for filedate
|
||||
|
||||
Revision 1.3 2002/05/10 06:05:53 lazarus
|
||||
MG: changed license to LGPL
|
||||
|
||||
|
||||
@ -17,6 +17,10 @@
|
||||
* *
|
||||
*****************************************************************************
|
||||
}
|
||||
const
|
||||
SMenuNotFound = 'Sub-menu is not in menu';
|
||||
SMenuIndexError = 'Menu index out of range';
|
||||
SMenuItemIsNil = 'MenuItem is nil';
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
Method: TMenuItem.Add
|
||||
@ -92,8 +96,19 @@ end;
|
||||
Description of the procedure for the class.
|
||||
------------------------------------------------------------------------------}
|
||||
procedure TMenuItem.Delete(Index: Integer);
|
||||
var
|
||||
Cur: TMenuItem;
|
||||
begin
|
||||
//TODO: Complete
|
||||
if (Index < 0) or (FItems = nil) or (Index >= GetCount) then
|
||||
raise EMenuError.Create(SMenuIndexError);
|
||||
Cur := TMenuItem(FItems[Index]);
|
||||
if Cur=nil then
|
||||
raise EMenuError.Create(SMenuItemIsNil);
|
||||
FItems.Delete(Index);
|
||||
Cur.FParent := nil;
|
||||
Cur.FOnChange := nil;
|
||||
DestroyHandle;
|
||||
MenuChanged(Count = 0);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
@ -107,6 +122,7 @@ destructor TMenuItem.Destroy;
|
||||
var
|
||||
i : integer;
|
||||
begin
|
||||
DestroyHandle;
|
||||
if assigned (FItems) then begin
|
||||
i := FItems.Count-1;
|
||||
while i>=0 do begin
|
||||
@ -196,6 +212,17 @@ begin
|
||||
Result := TMenuItem(FItems[Index]);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
function TMenuItem.GetMenuIndex: Integer;
|
||||
|
||||
Get position of this menuitem in its menu
|
||||
------------------------------------------------------------------------------}
|
||||
function TMenuItem.GetMenuIndex: Integer;
|
||||
begin
|
||||
Result := -1;
|
||||
if FParent <> nil then Result := FParent.IndexOf(Self);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
Function: TMenuItem.GetParent
|
||||
Params: none
|
||||
@ -298,12 +325,30 @@ begin
|
||||
if not HandleAllocated then CreateHandle;
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
procedure TMenuItem.DestroyHandle;
|
||||
|
||||
Free the Handle
|
||||
------------------------------------------------------------------------------}
|
||||
procedure TMenuItem.DestroyHandle;
|
||||
var i: integer;
|
||||
begin
|
||||
if not HandleAllocated then exit;
|
||||
if assigned (FItems) then begin
|
||||
i := FItems.Count-1;
|
||||
while i>=0 do begin
|
||||
TMenuItem(FItems[i]).DestroyHandle;
|
||||
dec(i);
|
||||
end;
|
||||
InterfaceObject.IntSendMessage3(LM_DESTROY, Self, nil);
|
||||
end;
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
Method: TMenuItem.HasParent
|
||||
Params:
|
||||
Returns: True - the item has a parent responsible for streaming
|
||||
|
||||
|
||||
------------------------------------------------------------------------------}
|
||||
function TMenuItem.HasParent : Boolean;
|
||||
begin
|
||||
@ -333,12 +378,11 @@ begin
|
||||
Item.GroupIndex := TMenuItem(FItems[Index - 1]).GroupIndex;
|
||||
VerifyGroupIndex(Index, Item.GroupIndex);
|
||||
|
||||
// check if we are the main menu
|
||||
// mainmenuitems have csMenu style
|
||||
// if FMenu <> nil then Item.FCompStyle := csMenu;
|
||||
|
||||
Item.FParent := Self;
|
||||
Item.FOnChange := @SubItemChanged;
|
||||
FItems.Insert(Index, Item);
|
||||
|
||||
if HandleAllocated then Item.HandleNeeded;
|
||||
MenuChanged(FItems.Count = 1);
|
||||
end;
|
||||
|
||||
@ -367,20 +411,34 @@ var
|
||||
Source: TMenuItem;
|
||||
begin
|
||||
if (Parent = nil) and (Owner is TMenu) then
|
||||
Source := nil else
|
||||
Source := nil
|
||||
else
|
||||
Source := Self;
|
||||
if Assigned(FOnChange) then FOnChange(Self, Source, Rebuild);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
Method: TMenuItem.Remove
|
||||
Params: Item:
|
||||
Returns: Nothing
|
||||
procedure TMenuItem.SetChildOrder(Child: TComponent; Order: Integer);
|
||||
|
||||
Reposition the MenuItem
|
||||
------------------------------------------------------------------------------}
|
||||
procedure TMenuItem.SetChildOrder(Child: TComponent; Order: Integer);
|
||||
begin
|
||||
(Child as TMenuItem).MenuIndex := Order;
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
procedure TMenuItem.Remove(Item: TMenuItem);
|
||||
|
||||
|
||||
------------------------------------------------------------------------------}
|
||||
procedure TMenuItem.Remove(Item: TMenuItem);
|
||||
var
|
||||
I: Integer;
|
||||
begin
|
||||
// ToDo
|
||||
I := IndexOf(Item);
|
||||
if I<0 then raise EMenuError.Create(SMenuNotFound);
|
||||
Delete(I);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
@ -447,14 +505,57 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
procedure TMenuItem.SetMenuIndex(const AValue: Integer);
|
||||
|
||||
Reposition the MenuItem
|
||||
------------------------------------------------------------------------------}
|
||||
procedure TMenuItem.SetMenuIndex(AValue: Integer);
|
||||
var
|
||||
OldParent: TMenuItem;
|
||||
ParentCount: Integer;
|
||||
begin
|
||||
if FParent <> nil then
|
||||
begin
|
||||
ParentCount := FParent.Count;
|
||||
if AValue < 0 then AValue := 0;
|
||||
if AValue >= ParentCount then AValue := ParentCount - 1;
|
||||
if AValue <> MenuIndex then
|
||||
begin
|
||||
OldParent := FParent;
|
||||
OldParent.Remove(Self);
|
||||
OldParent.Insert(AValue, Self);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
procedure TMenuItem.SetRadioItem(const AValue: Boolean);
|
||||
|
||||
Sets the 'RadioItem' property of the group of menuitems with the same
|
||||
GroupIndex. If RadioItem is true only one menuitem is checked at a time.
|
||||
------------------------------------------------------------------------------}
|
||||
procedure TMenuItem.SetRadioItem(const AValue: Boolean);
|
||||
var
|
||||
i: integer;
|
||||
Item: TMenuItem;
|
||||
begin
|
||||
if FRadioItem <> AValue then
|
||||
begin
|
||||
FRadioItem := AValue;
|
||||
if FChecked and FRadioItem then
|
||||
TurnSiblingsOff;
|
||||
MenuChanged(True);
|
||||
if (GroupIndex<>0) and (FParent<>nil) then begin
|
||||
for I := 0 to FParent.Count - 1 do begin
|
||||
Item := FParent[I];
|
||||
if (Item <> Self)
|
||||
and (Item.GroupIndex = GroupIndex) then
|
||||
Item.FRadioItem:=FRadioItem;
|
||||
end;
|
||||
end;
|
||||
if (FParent <> nil) and not (csReading in ComponentState)
|
||||
and (HandleAllocated) then
|
||||
RadioMenuItemGroup(Handle,FRadioItem);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -576,12 +677,31 @@ begin
|
||||
InterfaceObject.IntSendMessage3(LM_SETSHORTCUT, Self, @Msg);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
procedure TMenuItem.SubItemChanged(Sender: TObject; Source: TMenuItem;
|
||||
Rebuild: Boolean);
|
||||
|
||||
Is Called whenever one of the childs has changed.
|
||||
------------------------------------------------------------------------------}
|
||||
procedure TMenuItem.SubItemChanged(Sender: TObject; Source: TMenuItem;
|
||||
Rebuild: Boolean);
|
||||
begin
|
||||
if Rebuild and HandleAllocated then
|
||||
; // RebuildHandle;
|
||||
if Parent <> nil then
|
||||
Parent.SubItemChanged(Self, Source, False)
|
||||
else if Owner is TMainMenu then
|
||||
TMainMenu(Owner).ItemChanged;
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
Method: TMenuItem.TurnSiblingsOff
|
||||
Params: none
|
||||
Returns: Nothing
|
||||
|
||||
Unchecks all siblings.
|
||||
In contrary to Delphi this will not use SetChecked, because this is up to the
|
||||
interface. This procedure just sets the private variables.
|
||||
------------------------------------------------------------------------------}
|
||||
procedure TMenuItem.TurnSiblingsOff;
|
||||
var
|
||||
@ -627,6 +747,9 @@ end;
|
||||
{ =============================================================================
|
||||
|
||||
$Log$
|
||||
Revision 1.19 2002/08/07 09:55:30 lazarus
|
||||
MG: codecompletion now checks for filebreaks, savefile now checks for filedate
|
||||
|
||||
Revision 1.18 2002/08/06 20:05:19 lazarus
|
||||
MG: added actnlist.pp
|
||||
|
||||
@ -709,6 +832,9 @@ end;
|
||||
|
||||
|
||||
$Log$
|
||||
Revision 1.19 2002/08/07 09:55:30 lazarus
|
||||
MG: codecompletion now checks for filebreaks, savefile now checks for filedate
|
||||
|
||||
Revision 1.18 2002/08/06 20:05:19 lazarus
|
||||
MG: added actnlist.pp
|
||||
|
||||
|
||||
@ -453,6 +453,11 @@ begin
|
||||
Result := InterfaceObject.PostMessage(hWnd, Msg, wParam, lParam);
|
||||
end;
|
||||
|
||||
function RadioMenuItemGroup(hMenu: HMENU; bRadio: Boolean): Boolean;
|
||||
begin
|
||||
Result := InterfaceObject.RadioMenuItemGroup(hMenu,bRadio);
|
||||
end;
|
||||
|
||||
function RealizePalette(DC: HDC): Cardinal;
|
||||
begin
|
||||
Result := InterfaceObject.RealizePalette(DC);
|
||||
@ -1099,6 +1104,9 @@ end;
|
||||
{ =============================================================================
|
||||
|
||||
$Log$
|
||||
Revision 1.35 2002/08/07 09:55:30 lazarus
|
||||
MG: codecompletion now checks for filebreaks, savefile now checks for filedate
|
||||
|
||||
Revision 1.34 2002/08/05 10:45:03 lazarus
|
||||
MG: TMenuItem.Caption can now be set after creation
|
||||
|
||||
|
||||
@ -142,6 +142,7 @@ function Polyline(DC: HDC; Points: PPoint; NumPts: Integer): boolean; {$IFDEF IF
|
||||
function PostMessage(hWnd: HWND; Msg: Cardinal; wParam: LongInt; lParam: LongInt): Boolean; {$IFDEF IF_BASE_MEMBER}virtual;{$ENDIF}
|
||||
//function PtInRect --> independent
|
||||
|
||||
function RadioMenuItemGroup(hMenu: HMENU; bRadio: Boolean): Boolean; {$IFDEF IF_BASE_MEMBER}virtual;{$ENDIF}
|
||||
function RealizePalette(DC: HDC): Cardinal; {$IFDEF IF_BASE_MEMBER}virtual;{$ENDIF}
|
||||
function Rectangle(DC: HDC; X1, Y1, X2, Y2: Integer): Boolean; {$IFDEF IF_BASE_MEMBER}virtual;{$ENDIF}
|
||||
function RectVisible(dc : hdc; ARect: TRect) : Boolean; {$IFDEF IF_BASE_MEMBER}virtual;{$ENDIF}
|
||||
@ -271,6 +272,9 @@ function UnionRect(var DestRect: TRect; const SrcRect1, SrcRect2: TRect): Boolea
|
||||
{ =============================================================================
|
||||
|
||||
$Log$
|
||||
Revision 1.30 2002/08/07 09:55:30 lazarus
|
||||
MG: codecompletion now checks for filebreaks, savefile now checks for filedate
|
||||
|
||||
Revision 1.29 2002/08/05 10:45:03 lazarus
|
||||
MG: TMenuItem.Caption can now be set after creation
|
||||
|
||||
|
||||
@ -3664,9 +3664,22 @@ begin
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
Function: RadioMenuItemGroup
|
||||
Params: hMenu: HMENU; bRadio: Boolean
|
||||
Returns: Nothing
|
||||
|
||||
Change the group of menuitems to 'radio' or to checked.
|
||||
------------------------------------------------------------------------------}
|
||||
function TgtkObject.RadioMenuItemGroup(hMenu: HMENU; bRadio: Boolean): Boolean;
|
||||
begin
|
||||
// ToDo
|
||||
Result := false;
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
Function: RealizePalette
|
||||
Params: none
|
||||
Params: DC: HDC
|
||||
Returns: Nothing
|
||||
|
||||
|
||||
@ -3680,7 +3693,7 @@ end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
Function: Rectangle
|
||||
Params: none
|
||||
Params: DC: HDC; X1, Y1, X2, Y2: Integer
|
||||
Returns: Nothing
|
||||
|
||||
The Rectangle function draws a rectangle. The rectangle is outlined by using
|
||||
@ -4838,6 +4851,9 @@ end;
|
||||
{ =============================================================================
|
||||
|
||||
$Log$
|
||||
Revision 1.87 2002/08/07 09:55:30 lazarus
|
||||
MG: codecompletion now checks for filebreaks, savefile now checks for filedate
|
||||
|
||||
Revision 1.86 2002/08/05 10:45:06 lazarus
|
||||
MG: TMenuItem.Caption can now be set after creation
|
||||
|
||||
|
||||
@ -114,6 +114,7 @@ function Polygon(DC: HDC; Points: PPoint; NumPts: Integer; Winding: boolean): bo
|
||||
function Polyline(DC: HDC; Points: PPoint; NumPts: Integer): boolean; override;
|
||||
function PostMessage(hWnd: HWND; Msg: Cardinal; wParam: LongInt; lParam: LongInt): Boolean; override;
|
||||
|
||||
function RadioMenuItemGroup(hMenu: HMENU; bRadio: Boolean): Boolean; override;
|
||||
function RealizePalette(DC: HDC): Cardinal; override;
|
||||
function Rectangle(DC: HDC; X1, Y1, X2, Y2: Integer): Boolean; override;
|
||||
function RectVisible(dc : hdc; ARect: TRect) : Boolean; override;
|
||||
@ -158,6 +159,9 @@ Function WindowFromPoint(Point : TPoint) : HWND; override;
|
||||
{ =============================================================================
|
||||
|
||||
$Log$
|
||||
Revision 1.34 2002/08/07 09:55:31 lazarus
|
||||
MG: codecompletion now checks for filebreaks, savefile now checks for filedate
|
||||
|
||||
Revision 1.33 2002/08/05 10:45:08 lazarus
|
||||
MG: TMenuItem.Caption can now be set after creation
|
||||
|
||||
|
||||
13
lcl/menus.pp
13
lcl/menus.pp
@ -115,6 +115,7 @@ type
|
||||
FOnClick: TNotifyEvent;
|
||||
function GetCount: Integer;
|
||||
function GetItem(Index: Integer): TMenuItem;
|
||||
function GetMenuIndex: Integer;
|
||||
function GetParent: TMenuItem;
|
||||
function IsCaptionStored: boolean;
|
||||
function IsCheckedStored: boolean;
|
||||
@ -125,13 +126,17 @@ type
|
||||
procedure SetChecked(AValue: Boolean);
|
||||
procedure SetDefault(AValue: Boolean);
|
||||
procedure SetEnabled(AValue: Boolean);
|
||||
procedure SetMenuIndex(AValue: Integer);
|
||||
procedure SetRadioItem(const AValue: Boolean);
|
||||
procedure ShortcutChanged(const OldValue, Value : TShortcut);
|
||||
procedure SubItemChanged(Sender: TObject; Source: TMenuItem;
|
||||
Rebuild: Boolean);
|
||||
procedure TurnSiblingsOff;
|
||||
procedure VerifyGroupIndex(Position: Integer; Value: Byte);
|
||||
protected
|
||||
property ActionLink: TMenuActionLink read FActionLink write FActionLink;
|
||||
procedure CreateHandle; virtual;
|
||||
procedure DestroyHandle; virtual;
|
||||
procedure DoClicked(var msg); message LM_ACTIVATE; //'activate';
|
||||
function GetHandle: HMenu;
|
||||
Procedure SetImageIndex(value : Integer);
|
||||
@ -139,6 +144,7 @@ type
|
||||
procedure SetShortCut(AValue : TShortCut);
|
||||
procedure SetVisible(AValue: Boolean);
|
||||
procedure MenuChanged(Rebuild : Boolean);
|
||||
procedure SetChildOrder(Child: TComponent; Order: Integer); override;
|
||||
procedure SetParentComponent(AValue : TComponent); override;
|
||||
procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
|
||||
public
|
||||
@ -157,8 +163,10 @@ type
|
||||
property Count: Integer read GetCount;
|
||||
property Handle: HMenu read GetHandle write FHandle;
|
||||
property Items[Index: Integer]: TMenuItem read GetItem; default;
|
||||
property MenuIndex: Integer read GetMenuIndex write SetMenuIndex;
|
||||
property Parent: TMenuItem read GetParent;
|
||||
published
|
||||
//property Bitmap: TBitmap read GetBitmap write SetBitmap;
|
||||
property Caption: String read FCaption write SetCaption stored IsCaptionStored;
|
||||
property Checked: Boolean read FChecked write SetChecked stored IsCheckedStored default False;
|
||||
property Default: Boolean read FDefault write SetDefault default False;
|
||||
@ -198,6 +206,8 @@ type
|
||||
end;
|
||||
|
||||
TMainMenu = class(TMenu)
|
||||
protected
|
||||
procedure ItemChanged;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
published
|
||||
@ -401,6 +411,9 @@ end.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.18 2002/08/07 09:55:30 lazarus
|
||||
MG: codecompletion now checks for filebreaks, savefile now checks for filedate
|
||||
|
||||
Revision 1.17 2002/08/06 20:05:38 lazarus
|
||||
MG: added stored funcitons
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user