📄 ueditdefines.pas
字号:
//show all aliases separated by a semicolon and a space
EditUnitAliases.Text := FDefines.PostUnitAliasesAsString;
//show additional search paths
ListBoxSearchPath.Items := FDefines.PostSearchPath;
end;
{Saves the set compiler options from the form to ~[link FDefines]. }
procedure TFormDefines.SaveData;
{Sets a list by a simple comma separated text.
~param List the list to set
~param Text the text to assign to the list }
procedure SetText(List: TStringList; Text: String);
var Index :Integer; //index of a character in the text
pc :PChar; //runner thorugh the text
begin
Index := pos(#0, Text); //remove invalid character
if Index <> -1 then
Delete(Text, Index, high(length(Text)));
if Text <> '' then //string not empty?
begin
UniqueString(Text);
pc := Pointer(Text);
while (pc^ <> #0) do //run through the string
begin
if pc^ <= ' ' then //and delete all spaces
pc^ := ',';
inc(pc); //next character
end;
end;
List.CommaText := Text; //assign the text
repeat //remove all empty entries
Index := List.IndexOf(''); //may have been created by deleting the spaces
if Index <> -1 then
List.Delete(Index);
until Index = -1;
end;
{Parses the constants for the conditional compiling.
~param Text the text with the declaration of the constants }
procedure ParseConstants(Text: String);
var Data :TPascalFile; //the file to parse the constants
Parser :TCodeParser; //parser of the constants
Token :String; //each token
i :Integer; //counter through the constants
Ident :TIdentifier; //each constant
begin
Data := TPascalFile.Create;
try
Data.SetContent(Text); //parse the text
Parser := TCodeParser.Create(Data); //create the parser
Parser.SetContentToParse(Data.Lines); //pre-parse the text
Text := '';
Parser.PushPosition; //save the tokens
while Parser.GetToken(Token) do //get all tokens in the text
Text := Text + ' ' + Token;
Parser.PopPosition; //use the read tokens
Text := Trim(Text);
//make sure a ';' follows
if (Text <> '') and (Text[length(Text)] <> ';') and (Text <> 'const') then
begin
Data.Lines.Append('//}'); //end any maybe open comments
Data.Lines.Append('//*)');
Data.Lines.Append(';'); //add the semicolon
MemoConstants.Lines := Data.Lines; //show the new text
Data.SetContent(Data.Lines.Text); //re-parse the text
Parser.SetContentToParse(Data.Lines); //pre-parse the text
end;
Parser.ParseImplementations; //parse all constants
//clear constants
FDefines.ConditionalCompilingConstants.RemoveAll;
for i := 0 to Data.Idents.Count - 1 do //for each parsed constant
begin
Ident := Data.Idents[i]; //get and check it
if Ident.ClassType <> TConstant then
raise Exception.CreateFmtHelp('Identifier "%s" is not a constant (%s)!',
[Ident.Name, Ident.ClassName],
MemoConstants.HelpContext);
if assigned(TConstant(Ident).ConstType) then
raise Exception.CreateFmtHelp('Constant "%s" has a type, constants for conditional compiling have to be true, untyped constants!',
[Ident.Name], MemoConstants.HelpContext);
Ident := Ident.Clone; //create a copy
try
Ident.InFile := nil; //don't keep a reference
Ident.EffectiveFile := nil; //to the parser
Ident.EffectiveForwardFile := nil;
FDefines.ConditionalCompilingConstants.AddIdent(Ident); //add constant
except
Ident.Free;
raise;
end;
end;
finally
Data.Free; //free the file and parser
end;
end;
//mapping from check box to values of changing the compiler options
const TranslatePostOption: array[TCheckBoxState] of TPostOption =
(poUnset, poSet, poNothing);
var c :Char; //counter through all compiler options
PreOpts :TCompilerOptions; //compiler options before parsing CFG
PostOpts :TPostOptions; //compiler options after parsing CFG
begin
for c := 'A' to 'Z' do //set all compiler options
PreOpts[c] := CheckListBoxPre.Checked[ord(c) - ord('A')];
FDefines.PreOptions := PreOpts;
for c := 'A' to 'Z' do
PostOpts[c] := TranslatePostOption[CheckListBoxPost.State[ord(c) - ord('A')]];
FDefines.PostOptions := PostOpts;
SetText(FDefines.PreDefines, EditPreDefs.Text); //set compiler symbols
SetText(FDefines.PostDefines, EditPostDefs.Text);
SetText(FDefines.PostUnDefines, EditPostUnDefs.Text);
FDefines.AutoParse := CheckBoxAuto.Checked;
//parse the constants
ParseConstants('const ' + MemoConstants.Text);
//save additional search paths
FDefines.PostSearchPath.Assign(ListBoxSearchPath.Items);
//set the unit aliases
FDefines.PostUnitAliasesAsString := EditUnitAliases.Text;
end;
{Called when the form is closed.
~param Sender the sender of the event, the form
~param Action action to do on this event }
procedure TFormDefines.FormClose(Sender: TObject; var Action: TCloseAction);
var Settings :TFormSettings; //to save the settings of the form
begin
SaveData; //save all data to return it
//get object to save the settings in
Settings := TFormSettings(TFormSettings.GetSettings(ClassName));
if assigned(Settings) then
Settings.GetValuesFromForm(Self); //save current settings
end;
{Called when another TabSheet of the ~[link PageControl] is selected
~param Sender the sender of the event, ~[link PageControl] }
procedure TFormDefines.PageControlChange(Sender: TObject);
begin
{$IFNDEF LINUX}
//(un-)register to accept dragging of files
DragAcceptFiles(Handle, PageControl.ActivePage = TabSheetMoreSettings);
{$ENDIF}
end;
{Called when the version of Delphi/Kylix is changed.
~param Sender the sender of the event, RadioGroupVersion }
procedure TFormDefines.RadioGroupVersionClick(Sender: TObject);
var Versions :Integer; //counter through all possible versions
Index :Integer; //index of a compiler symbol of version
Ver :Integer; //internal compiler version
begin
if RadioGroupVersion.ItemIndex <> UnknownVersion then
begin
FDefines.PreDefines.CommaText := EditPreDefs.Text;
for Versions := 0 to 999 do //delete all possible versions
begin
Index := FDefines.PreDefines.IndexOf(Format('VER%u', [Versions]));
if Index <> -1 then
FDefines.PreDefines.Delete(Index);
end;
//get internal compiler version
Ver := VersionNumbers[RadioGroupVersion.ItemIndex];
FDefines.PreDefines.Append(Format('VER%u', [Ver])); //define the symbol
//state of .NET follows of version of Delphi?
if not (RadioGroupVersion.ItemIndex in DotNetPossibleVersions) then
begin
CheckBoxDotNET.OnClick := nil;
//set the state
CheckBoxDotNET.Checked := RadioGroupVersion.ItemIndex = DotNetVersion;
CheckBoxDotNET.OnClick := CheckBoxClick;
end;
//adjust the compiler symbols to the chosen Delphi/Kylix version
AdjustDefines(FDefines.PreDefines, Ver,
RadioGroupVersion.ItemIndex in KylixVersions);
EditPreDefs.Text := FDefines.PreDefines.CommaText; //show symbols
end;
//in Kylix, PIC possible?
CheckBoxPIC.Enabled := FDefines.PreDefines.IndexOf('LINUX') <> -1;
if not CheckBoxPIC.Enabled and CheckBoxPIC.Checked then
CheckBoxPIC.Checked := False;
//allow .NET?
CheckBoxDotNET.Enabled := RadioGroupVersion.ItemIndex in
[UnknownVersion] + DotNetPossibleVersions;
end;
{Called when a check box is changed.
~param Sender the sender of the event, the check box }
procedure TFormDefines.CheckBoxClick(Sender: TObject);
//the symbols to define/undefine
const Symbol: array[0..2] of String = ('CONSOLE', 'PIC', 'DECLARE_GPL');
begin
FDefines.PreDefines.CommaText := EditPreDefs.Text; //set the current symbols
assert((Sender is TCheckBox) and (TCheckBox(Sender).Tag in [0..3]));
if TCheckBox(Sender).Tag = 3 then //un-/define symbol(s)
begin
ChangeDefines(FDefines.PreDefines, ['CLR', 'CIL', 'MANAGEDCODE'],
TCheckBox(Sender).Checked);
ChangeDefines(FDefines.PreDefines, ['WIN32', 'MSWINDOWS'],
not TCheckBox(Sender).Checked);
end
else
ChangeDefine(FDefines.PreDefines, Symbol[TCheckBox(Sender).Tag],
TCheckBox(Sender).Checked);
EditPreDefs.Text := FDefines.PreDefines.CommaText; //show symbols
end;
{Called when the text field of the defined compiler symbols is changed.
~param Sender the sender of the event, the text field }
procedure TFormDefines.EditPreDefsChange(Sender: TObject);
begin
FDefines.PreDefines.CommaText := EditPreDefs.Text; //set the compiler symbols
//show which symbols are defined
CheckBoxConsole.Checked := FDefines.PreDefines.IndexOf('CONSOLE') <> -1;
CheckBoxPIC.Checked := FDefines.PreDefines.IndexOf('PIC') <> -1;
CheckBoxDotNET.Checked := FDefines.PreDefines.IndexOf('CLR') <> -1;
CheckBoxGPL.Checked := FDefines.PreDefines.IndexOf('DECLARE_GPL') <> -1;
end;
{Called when the button to load from a .cfg/.conf file is clicked.
~param Sender the sender of the event, the button }
procedure TFormDefines.BitBtnLoadFromCFGClick(Sender: TObject);
var PostOpts :TPostOptions; //compiler options after parsing CFG
Defines :TDefines; //set compiler options etc.
begin
with TOpenDialog.Create(nil) do //create a file open - dialog
try
DefaultExt := 'CFG';
Filter := 'Delphi/Kylix Project Configuration Files (*.cfg;*.conf)|*.cfg;*.conf|Delphi Project Configuration Files (*.cfg)|*.cfg|Kylix Project Configuration Files (*.conf)|*.conf|all files (*)|*';
InitialDir := GetCurrentDir;
Options := [ofHideReadOnly, ofFileMustExist, ofPathMustExist,
ofEnableSizing, ofShowHelp];
HelpContext := BitBtnLoadFromCFG.HelpContext;
Title := 'Load Delphi/Kylix Project Config File';
if Execute then //show the dialog; file chosen?
begin
SaveData; //save current data
//clear post defines
FillChar(PostOpts, SizeOf(PostOpts), poNothing);
FDefines.PostOptions := PostOpts;
FDefines.PostDefines.Clear;
FDefines.PostUnDefines.Clear;
Defines := TDefines.Create;
try
//load defines from the .cfg/.conf file
Defines.SetOptionsWithCFGFile(FDefines, FileName);
FDefines.PreOptions := Defines.Options; //assign the read value
FDefines.PreDefines.Assign(Defines.Defines);
FDefines.PostSearchPath.Assign(Defines.SearchPath);
FDefines.PostUnitAliases.Assign(Defines.UnitAliases);
finally
Defines.Free; //free the read values
end;
ShowData; //show the new values
end; //if Execute
finally
Free; //free the dialog
end;
end;
{Called when the button to select and add a directory to the list is clicked.
~param Sender the sender of the event, ~[link ButtonAdd] }
procedure TFormDefines.ButtonAddClick(Sender: TObject);
var Dir :String; //the selected diorectory
begin
Dir := GetCurrentDir; //get the current path and show dialog
if AskForDirectory('Select directory to parse:', Dir) and
DirectoryExists(Dir) then //existing directory selected?
begin
Dir := Dir + PathDelimiter;
Dir := ExtractShortPathName(ExpandFileName(Dir)); //get unique path
ListBoxSearchPath.Items.Add(Dir); //add the directory
end;
end;
{Called when the button to remove the selected directory from the list box is
clicked or when the list box is double clicked.
~param Sender the sender of the event, ~[link ButtonRemove] or
~[link ListBoxSearchPath] }
procedure TFormDefines.ButtonRemoveClick(Sender: TObject);
begin
if (ListBoxSearchPath.ItemIndex <> -1) and
(ListBoxSearchPath.Items.Count <> 0) then
//remove the selected file
ListBoxSearchPath.Items.Delete(ListBoxSearchPath.ItemIndex);
end;
{Called when the button to clear the list of directories is clicked.
~param Sender the sender of the event, ~[link ButtonClear] }
procedure TFormDefines.ButtonClearClick(Sender: TObject);
begin
ListBoxSearchPath.Clear; //clear the list
end;
{Called when a key is pressed in the list box.
~param Sender the sender of the event, ~[link ListBoxSearchPath]
~param Key the pressed key
~param Shift the state of special modifying keys }
procedure TFormDefines.ListBoxSearchPathKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if (Shift = []) and //delete key pressed?
{$IFNDEF LINUX}
(Key = VK_DELETE) then
{$ELSE}
(Key = Key_Delete) then
{$ENDIF}
ButtonRemoveClick(Sender); //delete the entry
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -