📄 ushowsourceform.pas
字号:
{Called when the list of parsed file changes.
~param State the state that has been changed }
procedure TFormShowSource.StateFileListChanged(State: TJADDState);
var Index :Integer; //index of the previously selected file
Name :String; //name of the previously selected file
i :Integer; //counter through/index in new files
AFile :TPascalFile; //each file in the new list
begin
//disable, when no files available
ComboBox.Enabled := assigned(State.FileList) and not State.FileList.IsEmpty;
ListBox.Enabled := ComboBox.Enabled;
FPascalMemo.Enabled := ComboBox.Enabled;
ButtonFileStatistics.Enabled := ComboBox.Enabled;
ButtonAllStatistics.Enabled := ComboBox.Enabled;
//data available
if assigned(State.FileList) and not State.FileList.IsEmpty then
begin
Index := ComboBox.ItemIndex; //save selected file
if (Index >= 0) and (Index < ComboBox.Items.Count) then //and its name
Name := ComboBox.Items[Index]
else
Name := '';
ComboBox.Items.Clear; //clear the list
for i := 0 to State.FileList.Count - 1 do //and fill with current files
begin
AFile := State.FileList[i];
ComboBox.Items.AddObject(AFile.InternalFileName, AFile);
end;
for i := 0 to State.FileList.IncludedFileCount - 1 do //included files, too
begin
AFile := State.FileList.Included[i];
ComboBox.Items.AddObject('$INCLUDE ' + ExtractFileName(AFile.FilePath),
AFile);
end;
//file still in the list?
i := ComboBox.Items.IndexOfObject(FPascalMemo.TheFile);
if i = -1 then //in list as the same by object
//make sure its data is re-read in case it is another object just with
FPascalMemo.TheFile := nil //the same address
else
i := ComboBox.Items.IndexOf(Name); //search by name
if i <> -1 then //file still in the list?
ComboBox.ItemIndex := i //re-select it
else
//reselect the entry with the index
if (Index >= 0) and (Index < ComboBox.Items.Count) then
ComboBox.ItemIndex := Index
else
if not State.FileList.IsEmpty then //if it is not empty
ComboBox.ItemIndex := 0; //sleect the first file
end //if assigned(State.FileList) and not State.FileList.IsEmpty
else
begin
ComboBox.Clear; //just clear the lists
ListBox.Clear;
end; //else assigned(State.FileList) and not State.FileList.IsEmpty
ComboBoxChange(State); //cope with the new selection
end;
{Shows the declaration of an identifier in the source code.
~param Identifier the identifier whose declaration should be shown
~param Impl if the final declaration (implementation or the final class
declaration) should be shown }
procedure TFormShowSource.ShowSourceCodeOfIdentifier(Identifier: TIdentifier;
Impl: Boolean);
const PropLength = length('property'); //length of the token "property"
var TheFile :TPascalFile; //file it is declared in
Pos :TPosition; //position of the declaration
i :Integer; //general index variable
{$IFNDEF USESOURCECODEGRID}
S :String; //line of the declaration
Func :String; //tokens in the line for functions
{$ENDIF}
begin
if Impl then //get file and position to show
begin
TheFile := Identifier.EffectiveFile;
Pos := Identifier.EffectivePosition;
end
else
begin
TheFile := Identifier.EffectiveForwardFile;
Pos := Identifier.EffectiveForwardPosition;
end;
//not in currently shown file?
if ComboBox.Items.Objects[ComboBox.ItemIndex] <> TheFile then
begin
i := ComboBox.Items.IndexOfObject(TheFile); //search the file
if i = -1 then //file not found?
begin
assert(false);
TheFile := Identifier.InFile; //use general file and position
i := ComboBox.Items.IndexOfObject(TheFile); //search the file
assert(i <> -1);
end;
if i <> -1 then //file found?
begin
ComboBox.ItemIndex := i; //select the file
ComboBox.OnChange(nil); //and show it
end
else
begin
Assert(False);
// TheFile := Identifier.InFile; //use general file and position
if Impl then
Pos := Identifier.Position
else
Pos := Identifier.ForwardDefPos;
end;
end;
i := ListBox.Items.IndexOfObject(Identifier);
if (i <> -1) and (i <> ListBox.ItemIndex) then
ListBox.ItemIndex := i;
//under Linux the column is not relevant, so don't waste time correcting it
{$IFNDEF USESOURCECODEGRID}
if Identifier is TFunction then //is a function?
begin
S := FPascalMemo.TheFile.Lines[Pos.Row - 1]; //get the line
Delete(S, 1, Pos.Column - 1); //delete before position
//get text of kind of function
Func := FuncNames[TFunction(Identifier).FuncKind];
if LowerCase(copy(S, 1, length(Func))) = Func then //is this token?
begin
inc(Pos.Column, length(Func)); //adjust position to skip it
Delete(S, 1, length(Func));
while (S <> '') and (S[1] = ' ') do //skip all whitespaces
begin
inc(Pos.Column);
Delete(S, 1, 1);
end;
//is a method and class is given?
if (S <> '') and assigned(TFunction(Identifier).MemberOf) and Impl and
(CompareText(copy(S, 1, length(TFunction(Identifier).MemberOf.Name)),
TFunction(Identifier).MemberOf.Name) = 0) then
begin
Delete(S, 1, length(TFunction(Identifier).MemberOf.Name)); //skip class
Func := TrimLeft(S);
if (Func <> '') and (Func[1] = '.') then
begin
Delete(Func, 1, 1); //skip the dot
Func := TrimLeft(Func);
if TrimLeft(Func) <> '' then //adjust the position
inc(Pos.Column, length(TFunction(Identifier).MemberOf.Name) +
(length(S) - length(Func)));
end;
end; //if IsAMethod?
end; //if LowerCase(copy(S, 1, length(Func))) = Func
end //if Ident is TFunction
else
if Identifier is TProperty then //is a property?
begin
S := FPascalMemo.TheFile.Lines[Pos.Row - 1]; //get the line
Delete(S, 1, Pos.Column - 1); //delete before position
//is the token "property" ?
if LowerCase(copy(S, 1, PropLength)) = 'property' then
begin
inc(Pos.Column, PropLength); //adjust position to skip it
Delete(S, 1, PropLength);
while (S <> '') and (S[1] = ' ') do //skip all whitespaces
begin
inc(Pos.Column);
Delete(S, 1, 1);
end;
end; //if LowerCase(copy(S, 1, length('property'))) = 'property'
end; //if Ident is TProperty
{$ENDIF}
//show the position
FPascalMemo.CaretPos := Point(Pos.Column - 1, Pos.Row - 1);
{$IFNDEF USESOURCECODEGRID}
// and select the identifier
FPascalMemo.SelectionStart := Point(Pos.Column - 1 + length(Identifier.Name),
Pos.Row - 1);
FPascalMemo.ScrollToCaret; //make sure it is visible
FPascalMemo.Update; //show the new position and selection
{$ENDIF}
if Impl then //set file and position it is included from
if Identifier.EffectiveFile = Identifier.InFile then
NotIncluded
else
SetIncluded(Identifier.InFile, Identifier.Position)
else
if Identifier.EffectiveForwardFile = Identifier.InFile then
NotIncluded
else
SetIncluded(Identifier.InFile, Identifier.ForwardDefPos);
end;
{Shows the statistics in a dialog.
~param Header header for the list of statistics
~param Statistics the statistics to be shown
~param Helpcontext the help context to use for the dialog }
procedure TFormShowSource.ShowStatistics(Header: String;
Statistics: TStatisticOfPascalFile;
HelpContext: THelpContext);
//captions to show for each value in the statistic
const Captions: array[TPascalFileStatistic] of String =
('Included Files',
'All Included Files',
'Lines',
'Characters',
'Tokens',
'Compiler Directives',
'Skipped Tokens',
'Empty Lines',
'Lines With Comments',
'Lines With Tokens',
'Lines (Without Included)',
'Characters (Without Included)',
'Tokens (Without Included)',
'Compiler Directives (Without Included)',
'Skipped Tokens (Without Included)',
'Empty Lines (Without Included)',
'Lines With Comments (Without Included)',
'Lines With Tokens (Without Included)',
'Type Casts (Known Types)',
'Function Bodys',
'"with" Statements',
'Overloaded Functions',
'GoTo Statements',
'Labels',
'Assembler Blocks');
var Text :String; //the text containing the statistics
value :TPascalFileStatistic; //counter through values
begin
Text := Header;
for value := Low(value) to High(value) do //for each value add its number
Text := Text + LineDelimiter +
Captions[value] + ': ' + IntToStr(Statistics.Numbers[value]);
MessageDlg(Text, mtInformation, [mbOK], HelpContext); //show the message
end;
{Shows the source code at the identifier or position.
~param Ident nil, or the identifier whose declaration should be
shown
~param TheFile if ident is nil, the file to show the source code of
~param Position the position in TheFile to show
~param EffectiveFile if different than TheFile, this file has been
included (maybe indirectly) by TheFile, show source
of this file instead
~param EffectivePosition the position in EffectiveFile to show }
procedure TFormShowSource.ShowSourceCode(Ident: TIdentifier;
TheFile: TPascalFile;
Position: TPosition;
EffectiveFile: TPascalFile;
EffectivePosition: TPosition);
begin
Show; //make sure the window is visible
if assigned(Ident) then //show declaration of identifier?
ShowSourceCodeOfIdentifier(Ident, True) //show it
else
begin
assert(assigned(TheFile));
assert(assigned(EffectiveFile));
//select the file
ComboBox.ItemIndex := ComboBox.Items.IndexOfObject(EffectiveFile);
assert(ComboBox.ItemIndex <> -1);
ComboBoxChange(nil); //and show its source code
//show the position in the file
FPascalMemo.CaretPos := Point(EffectivePosition.Column - 1,
EffectivePosition.Row - 1);
{$IFNDEF USESOURCECODEGRID}
FPascalMemo.ScrollToCaret; //make sure it is visible
FPascalMemo.Update; //show the new position and selection
{$ENDIF}
if TheFile <> EffectiveFile then //file was included?
SetIncluded(TheFile, Position) //set included
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -