mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-11 11:07:56 +02:00
376 lines
11 KiB
ObjectPascal
376 lines
11 KiB
ObjectPascal
{
|
|
/***************************************************************************
|
|
condef.pas - Conditional Defines
|
|
----------------------------------
|
|
|
|
***************************************************************************/
|
|
|
|
***************************************************************************
|
|
* *
|
|
* This source is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This code is distributed in the hope that it will be useful, but *
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
|
* General Public License for more details. *
|
|
* *
|
|
* A copy of the GNU General Public License is available on the World *
|
|
* Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
|
|
* obtain it by writing to the Free Software Foundation, *
|
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
* *
|
|
***************************************************************************
|
|
}
|
|
unit ConDef;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
(* Utility to assist in inserting conditional defines. For example, to convert
|
|
OnCreate := @CreateHandler
|
|
to:
|
|
OnCreate := {$IFDEF FPC} @ {$ENDIF} CreateHandler
|
|
select @ and then use Edit, Insert $IFDEF (default shortcut Ctrl+Shift+D),
|
|
select "FPC,NONE" and hit return. If you select one or more complete lines
|
|
then the conditional defines are put on sepearate lines as in:
|
|
{$IFDEF DEBUG}
|
|
Writeln('State= ', State)
|
|
{$ENDIF}
|
|
The choices are listed in abbreviated form so:
|
|
MSWINDOWS,UNIX => {$IFDEF MSWINDOWS} ... {$ENDIF} {$IFDEF UNIX} ... {$ENDIF}
|
|
FPC,ELSE => {$IFDEF FPC} ... {$ELSE} ... {$ENDIF}
|
|
DEBUG,NONE => {$IFDEF DEBUG} ... {$ENDIF}
|
|
This tool is most useful when you need to put several identical conditionals
|
|
in a file, You can add to the possible conditionals by selecting or typing
|
|
the required symbols in "First test" and /or "Second test" and using the
|
|
Add button. Your additons are saved in the condef.xml file in the lazarus
|
|
configuration directory.
|
|
*)
|
|
|
|
uses
|
|
Classes, SysUtils, Graphics, Controls, Forms, LCLProc, Dialogs,
|
|
StdCtrls, Buttons, FileUtil, ButtonPanel,
|
|
Laz_XMLCfg,
|
|
IDEHelpIntf,
|
|
LazarusIDEStrConsts, IDEProcs;
|
|
|
|
type
|
|
|
|
{ TCondForm }
|
|
|
|
TCondForm = class(TForm)
|
|
AddBtn: TBitBtn;
|
|
AddInverse: TButton;
|
|
ButtonPanel: TButtonPanel;
|
|
FirstLabel: TLabel;
|
|
FirstTest: TComboBox;
|
|
ListBox: TListBox;
|
|
NewTestGroupBox: TGroupBox;
|
|
RemoveBtn: TBitBtn;
|
|
SecondLabel: TLabel;
|
|
SecondTest: TComboBox;
|
|
procedure AddBtnClick(Sender: TObject);
|
|
procedure AddInverseCLICK(Sender: TObject);
|
|
procedure HelpButtonClick(Sender: TObject);
|
|
procedure CondFormCLOSE(Sender: TObject; var CloseAction: TCloseAction);
|
|
procedure CondFormCREATE(Sender: TObject);
|
|
procedure ListBoxDblClick(Sender: TObject);
|
|
procedure RemoveBtnClick(Sender: TObject);
|
|
procedure ListBoxKeyDown(Sender: TObject; var Key: Word;
|
|
Shift: TShiftState);
|
|
procedure FormShow(Sender: TObject);
|
|
public
|
|
Choice, First, Second, FS: string;
|
|
procedure DeleteSelected;
|
|
procedure SaveChoices;
|
|
function CreateXMLConfig: TXMLConfig;
|
|
end;
|
|
|
|
|
|
function ShowConDefDlg: string;
|
|
function AddConditional(Text: string; IsPascal: Boolean):string;
|
|
|
|
implementation
|
|
|
|
{$R *.lfm}
|
|
|
|
uses
|
|
LCLType, LazConf;
|
|
|
|
function ShowConDefDlg: string;
|
|
var
|
|
DialogResult: Integer;
|
|
CondForm: TCondForm;
|
|
begin
|
|
Result := '';
|
|
CondForm := TCondForm.Create(nil);
|
|
try
|
|
CondForm.ActiveControl := CondForm.ListBox;
|
|
DialogResult := CondForm.ShowModal;
|
|
if DialogResult <> mrOK then
|
|
Result := ''
|
|
else
|
|
Result := CondForm.FS;
|
|
finally
|
|
CondForm.Free;
|
|
end
|
|
end;
|
|
|
|
procedure TCondForm.AddBtnClick(Sender: TObject);
|
|
begin
|
|
ListBox.Items.Add(FirstTest.Text+','+SecondTest.Text);
|
|
end;
|
|
|
|
procedure TCondForm.AddInverseCLICK(Sender: TObject);
|
|
begin
|
|
ListBox.Items.Add('!'+FirstTest.Text+','+SecondTest.Text);
|
|
end;
|
|
|
|
procedure TCondForm.HelpButtonClick(Sender: TObject);
|
|
begin
|
|
LazarusHelp.ShowHelpForIDEControl(Self);
|
|
end;
|
|
|
|
procedure TCondForm.CondFormCLOSE(Sender: TObject; var CloseAction: TCloseAction);
|
|
var
|
|
SChanged: Boolean;
|
|
i: Integer;
|
|
procedure SUpdate(var s: string; n: string);
|
|
begin
|
|
if s <> n then begin
|
|
SChanged := True;
|
|
s := n;
|
|
end;
|
|
end;
|
|
begin
|
|
SChanged := False;
|
|
with ListBox do begin
|
|
SUpdate(Choice,Items.CommaText);
|
|
if ItemIndex >= 0 then begin
|
|
FS := Items[ItemIndex];
|
|
i := Pos(',', FS);
|
|
if i > 0 then begin
|
|
SUpdate(First, Copy(FS, 1, i-1));
|
|
SUpdate(Second, Copy(FS, i+1, Length(FS)));
|
|
end
|
|
end;
|
|
end;
|
|
if SChanged then
|
|
SaveChoices;
|
|
end;
|
|
|
|
procedure TCondForm.CondFormCREATE(Sender: TObject);
|
|
var
|
|
i: Integer;
|
|
XMLConfig: TXMLConfig;
|
|
begin
|
|
NewTestGroupBox.Caption := rsCreateNewDefine;
|
|
Caption := rsConditionalDefines;
|
|
AddBtn.Caption := liswlAdd;
|
|
AddInverse.Caption := rsAddInverse;
|
|
RemoveBtn.Caption := rsRemove;
|
|
ButtonPanel.HelpButton.OnClick := @HelpButtonClick;
|
|
try
|
|
XMLConfig:=CreateXMLConfig;
|
|
try
|
|
Choice := XMLConfig.GetValue('condef/Choice', '"MSWINDOWS,UNIX","MSWINDOWS,ELSE","FPC,NONE","FPC,ELSE","DEBUG,NONE"');
|
|
First := XMLConfig.GetValue('condef/First', 'MSWINDOWS');
|
|
Second := XMLConfig.GetValue('condef/Second', 'UNIX');
|
|
finally
|
|
XMLConfig.Free;
|
|
end;
|
|
except
|
|
on E: Exception do begin
|
|
debugln('TCondForm.CondFormCREATE ',E.Message);
|
|
end;
|
|
end;
|
|
with ListBox do begin
|
|
Items.CommaText := Choice;
|
|
i := Items.IndexOf(First+','+Second);
|
|
if i < 0 then begin
|
|
Items.Add(First+','+Second);
|
|
ItemIndex := 0;
|
|
end else
|
|
ItemIndex := i;
|
|
end;
|
|
end;
|
|
|
|
procedure TCondForm.ListBoxDblClick(Sender: TObject);
|
|
begin
|
|
ModalResult := mrOK;
|
|
end;
|
|
|
|
procedure TCondForm.RemoveBtnClick(Sender: TObject);
|
|
begin
|
|
DeleteSelected;
|
|
end;
|
|
|
|
procedure TCondForm.ListBoxKeyDown(Sender: TObject; var Key: Word;
|
|
Shift: TShiftState);
|
|
begin
|
|
if Key = VK_DELETE then begin
|
|
DeleteSelected;
|
|
Key := 0;
|
|
end;
|
|
end;
|
|
|
|
procedure TCondForm.FormShow(Sender: TObject);
|
|
begin
|
|
if SecondTest.Items.Count < 10 then
|
|
SecondTest.Items.AddStrings(FirstTest.Items);
|
|
end;
|
|
|
|
procedure TCondForm.DeleteSelected;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
with ListBox.Items do
|
|
for i := Count-1 downto 0 do
|
|
if ListBox.Selected[i] then
|
|
Delete(i);
|
|
end;
|
|
|
|
procedure TCondForm.SaveChoices;
|
|
var
|
|
XMLConfig: TXMLConfig;
|
|
begin
|
|
try
|
|
InvalidateFileStateCache;
|
|
XMLConfig:=CreateXMLConfig;
|
|
try
|
|
XMLConfig.SetValue('condef/Choice', Choice);
|
|
XMLConfig.SetValue('condef/First', First);
|
|
XMLConfig.SetValue('condef/Second', Second);
|
|
XMLConfig.Flush;
|
|
finally
|
|
XMLConfig.Free;
|
|
end;
|
|
except
|
|
on E: Exception do begin
|
|
debugln('TCondForm.SaveChoices ',E.Message);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TCondForm.CreateXMLConfig: TXMLConfig;
|
|
var
|
|
ConfFileName: String;
|
|
begin
|
|
Result:=nil;
|
|
ConfFileName:=SetDirSeparators(GetPrimaryConfigPath+'/condef.xml');
|
|
try
|
|
if (not FileExistsUTF8(ConfFileName)) then
|
|
Result:=TXMLConfig.CreateClean(ConfFileName)
|
|
else
|
|
Result:=TXMLConfig.Create(ConfFileName);
|
|
except
|
|
on E: Exception do begin
|
|
debugln('TCondForm.CreateXMLConfig ',E.Message);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function AddConditional(Text: string; IsPascal: Boolean):string;
|
|
var
|
|
cond, s, f: string;
|
|
p, p1: Integer;
|
|
IsElse, IsTwo, HasNewline: Boolean;
|
|
Tail, Indent: string;
|
|
function ifdef(s:string):string;
|
|
begin
|
|
if (s <>'') and (s[1] = '!') then begin
|
|
if IsPascal then
|
|
Result := 'N'
|
|
else
|
|
Result := 'n';
|
|
s := Copy(s,2,Length(s)-1);
|
|
end;
|
|
if IsPascal then
|
|
Result := '{$IF' + Result + 'DEF ' + s + '}'
|
|
else
|
|
Result := '#if' + Result + 'def ' + s;
|
|
end;
|
|
begin
|
|
Result := Text;
|
|
cond := ShowConDefDlg;
|
|
p := Pos(',',cond);
|
|
if p <= 0 then Exit;
|
|
f := Copy(Cond, 1, p-1);
|
|
s := Copy(Cond, p+1, Length(Cond));
|
|
IsElse := CompareText(s, 'ELSE') = 0;
|
|
IsTwo := CompareText(s, 'NONE') <> 0;
|
|
HasNewline := Pos(#10, Text) > 0;
|
|
if HasNewline then begin
|
|
p := 1;
|
|
{ leave leading newlines unchanged (outside $IFDEF) }
|
|
while (p <= Length(Text)) and (Text[p] in [#10,#13]) do Inc(p);
|
|
Result := Copy(Text,1,p-1);
|
|
p1 := p;
|
|
{ Work out current indentation, to line up $IFDEFS }
|
|
while (p <= Length(Text)) and (Text[p] in [#9,' ']) do Inc(p);
|
|
Indent := Copy(Text, p1, p-p1);
|
|
Text := Copy(Text,p,Length(Text));
|
|
p := Length(Text);
|
|
{ Tailing whitespace is left outside $IFDEF }
|
|
while (p>0) and (Text[p] in [' ',#9,#10,#13]) do Dec(p);
|
|
Tail := Copy(Text, p+1, Length(Text));
|
|
SetLength(Text,p);
|
|
end else begin
|
|
Result := '';
|
|
Tail := '';
|
|
Indent := '';
|
|
end;
|
|
if IsPascal then begin
|
|
f := ifdef(f);
|
|
s := ifdef(s);
|
|
if HasNewline then begin
|
|
Result := Result + Indent + f + LineEnding + Indent + Text + LineEnding;
|
|
if IsElse then
|
|
Result := Result + Indent + '{$ELSE}' + LineEnding
|
|
else begin
|
|
Result := Result + Indent + '{$ENDIF}';
|
|
if IsTwo then
|
|
Result := Result + LineEnding + Indent + s + LineEnding;
|
|
end;
|
|
if IsTwo then
|
|
Result := Result + Indent + Text + LineEnding + Indent + '{$ENDIF}';
|
|
Result := Result + Tail;
|
|
end else begin
|
|
Result := Result + f + ' ' + Text;
|
|
if IsElse then
|
|
Result := Result + ' {$ELSE} '
|
|
else begin
|
|
Result := Result + ' {$ENDIF}';
|
|
if IsTwo then
|
|
Result := Result + ' ' + s + ' ';
|
|
end;
|
|
if IsTwo then
|
|
Result := Result + Text + ' {$ENDIF}';
|
|
end;
|
|
end else begin
|
|
Result := Result + ifdef(f) + LineEnding + indent + Text + LineEnding;
|
|
if IsElse then
|
|
Result := Result + '#else' + LineEnding
|
|
else begin
|
|
Result := Result + '#endif /* ' + f + ' */' + LineEnding;
|
|
if IsTwo then
|
|
Result := Result + ifdef(s) + LineEnding;
|
|
end;
|
|
if IsTwo then begin
|
|
Result := Result + indent + Text + LineEnding + '#endif /* ';
|
|
if IsElse then
|
|
Result := Result + f
|
|
else
|
|
Result := Result + s;
|
|
Result := Result + ' */' + LineEnding;
|
|
end;
|
|
Result := Result + Tail;
|
|
end;
|
|
end;
|
|
|
|
end.
|