mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-12 18:49:16 +02:00
Merged revision 30573 from http://svn.freepascal.org/svn/fpc/trunk
------------------------------------------------------------------------ r30573 | pierre | 2015-04-13 18:40:27 +0200 (Mon, 13 Apr 2015) | 1 line Changed paths: M /trunk/ide/wini.pas Use pascal style doubling of quote char instead of C style escaping for ini file ------------------------------------------------------------------------ git-svn-id: branches/fixes_3_0@31754 -
This commit is contained in:
parent
88d00ef331
commit
81a6f3ea2a
@ -612,7 +612,7 @@ begin
|
|||||||
{ Files }
|
{ Files }
|
||||||
{ avoid keeping old files }
|
{ avoid keeping old files }
|
||||||
INIFile^.DeleteSection(secFiles);
|
INIFile^.DeleteSection(secFiles);
|
||||||
INIFile^.SetEntry(secFiles,ieOpenExts,'"'+OpenExts+'"');
|
INIFile^.SetEntry(secFiles,ieOpenExts,EscapeIniText(OpenExts));
|
||||||
for I:=1 to High(RecentFiles) do
|
for I:=1 to High(RecentFiles) do
|
||||||
begin
|
begin
|
||||||
if I<=RecentFileCount then
|
if I<=RecentFileCount then
|
||||||
@ -678,17 +678,17 @@ begin
|
|||||||
{ Help }
|
{ Help }
|
||||||
S:='';
|
S:='';
|
||||||
HelpFiles^.ForEach(@ConcatName);
|
HelpFiles^.ForEach(@ConcatName);
|
||||||
INIFile^.SetEntry(secHelp,ieHelpFiles,'"'+S+'"');
|
INIFile^.SetEntry(secHelp,ieHelpFiles,EscapeIniText(S));
|
||||||
{ Editor }
|
{ Editor }
|
||||||
INIFile^.SetIntEntry(secEditor,ieDefaultTabSize,DefaultTabSize);
|
INIFile^.SetIntEntry(secEditor,ieDefaultTabSize,DefaultTabSize);
|
||||||
INIFile^.SetIntEntry(secEditor,ieDefaultIndentSize,DefaultIndentSize);
|
INIFile^.SetIntEntry(secEditor,ieDefaultIndentSize,DefaultIndentSize);
|
||||||
INIFile^.SetIntEntry(secEditor,ieDefaultEditorFlags,DefaultCodeEditorFlags);
|
INIFile^.SetIntEntry(secEditor,ieDefaultEditorFlags,DefaultCodeEditorFlags);
|
||||||
INIFile^.SetEntry(secEditor,ieDefaultSaveExt,DefaultSaveExt);
|
INIFile^.SetEntry(secEditor,ieDefaultSaveExt,DefaultSaveExt);
|
||||||
{ Highlight }
|
{ Highlight }
|
||||||
INIFile^.SetEntry(secHighlight,ieHighlightExts,'"'+HighlightExts+'"');
|
INIFile^.SetEntry(secHighlight,ieHighlightExts,EscapeIniText(HighlightExts));
|
||||||
INIFile^.SetEntry(secHighlight,ieTabsPattern,'"'+TabsPattern+'"');
|
INIFile^.SetEntry(secHighlight,ieTabsPattern,EscapeIniText(TabsPattern));
|
||||||
{ SourcePath }
|
{ SourcePath }
|
||||||
INIFile^.SetEntry(secSourcePath,ieSourceList,'"'+SourceDirs+'"');
|
INIFile^.SetEntry(secSourcePath,ieSourceList,EscapeIniText(SourceDirs));
|
||||||
{ Mouse }
|
{ Mouse }
|
||||||
INIFile^.SetIntEntry(secMouse,ieDoubleClickDelay,DoubleDelay);
|
INIFile^.SetIntEntry(secMouse,ieDoubleClickDelay,DoubleDelay);
|
||||||
INIFile^.SetIntEntry(secMouse,ieReverseButtons,byte(MouseReverse));
|
INIFile^.SetIntEntry(secMouse,ieReverseButtons,byte(MouseReverse));
|
||||||
@ -718,9 +718,9 @@ begin
|
|||||||
begin
|
begin
|
||||||
S:=IntToStr(I);
|
S:=IntToStr(I);
|
||||||
GetToolParams(I-1,S1,S2,S3,W);
|
GetToolParams(I-1,S1,S2,S3,W);
|
||||||
if S1<>'' then S1:='"'+S1+'"';
|
if S1<>'' then S1:=EscapeIniText(S1);
|
||||||
if S2<>'' then S2:='"'+S2+'"';
|
if S2<>'' then S2:=EscapeIniText(S2);
|
||||||
if S3<>'' then S3:='"'+S3+'"';
|
if S3<>'' then S3:=EscapeIniText(S3);
|
||||||
INIFile^.SetEntry(secTools,ieToolName+S,S1);
|
INIFile^.SetEntry(secTools,ieToolName+S,S1);
|
||||||
INIFile^.SetEntry(secTools,ieToolProgram+S,S2);
|
INIFile^.SetEntry(secTools,ieToolProgram+S,S2);
|
||||||
INIFile^.SetEntry(secTools,ieToolParams+S,S3);
|
INIFile^.SetEntry(secTools,ieToolParams+S,S3);
|
||||||
|
140
ide/wini.pas
140
ide/wini.pas
@ -23,11 +23,13 @@ type
|
|||||||
PINIEntry = ^TINIEntry;
|
PINIEntry = ^TINIEntry;
|
||||||
TINIEntry = object(TObject)
|
TINIEntry = object(TObject)
|
||||||
constructor Init(const ALine: string);
|
constructor Init(const ALine: string);
|
||||||
|
constructor Init(const ATag,AValue,AComment: string);
|
||||||
function GetText: string;
|
function GetText: string;
|
||||||
function GetTag: string;
|
function GetTag: string;
|
||||||
function GetComment: string;
|
function GetComment: string;
|
||||||
function GetValue: string;
|
function GetValue: string;
|
||||||
procedure SetValue(const S: string);
|
procedure SetValue(const S: string);
|
||||||
|
procedure SetComment(const S: string);
|
||||||
destructor Done; virtual;
|
destructor Done; virtual;
|
||||||
private
|
private
|
||||||
TagHash : Cardinal;
|
TagHash : Cardinal;
|
||||||
@ -44,6 +46,7 @@ type
|
|||||||
constructor Init(const AName: string);
|
constructor Init(const AName: string);
|
||||||
function GetName: string;
|
function GetName: string;
|
||||||
function AddEntry(const S: string): PINIEntry;
|
function AddEntry(const S: string): PINIEntry;
|
||||||
|
function AddEntry(const Tag,Value,Comment: string): PINIEntry;
|
||||||
function SearchEntry(Tag: string): PINIEntry; virtual;
|
function SearchEntry(Tag: string): PINIEntry; virtual;
|
||||||
procedure DeleteEntry(Tag: string);
|
procedure DeleteEntry(Tag: string);
|
||||||
procedure ForEachEntry(EnumProc: pointer); virtual;
|
procedure ForEachEntry(EnumProc: pointer); virtual;
|
||||||
@ -68,6 +71,7 @@ type
|
|||||||
procedure ForEachEntry(const Section: string; EnumProc: pointer); virtual;
|
procedure ForEachEntry(const Section: string; EnumProc: pointer); virtual;
|
||||||
function GetEntry(const Section, Tag, Default: string): string; virtual;
|
function GetEntry(const Section, Tag, Default: string): string; virtual;
|
||||||
procedure SetEntry(const Section, Tag, Value: string); virtual;
|
procedure SetEntry(const Section, Tag, Value: string); virtual;
|
||||||
|
procedure SetEntry(const Section, Tag, Value,Comment: string); virtual;
|
||||||
function GetIntEntry(const Section, Tag: string; Default: longint): longint; virtual;
|
function GetIntEntry(const Section, Tag: string; Default: longint): longint; virtual;
|
||||||
procedure SetIntEntry(const Section, Tag: string; Value: longint); virtual;
|
procedure SetIntEntry(const Section, Tag: string; Value: longint); virtual;
|
||||||
procedure DeleteSection(const Section: string); virtual;
|
procedure DeleteSection(const Section: string); virtual;
|
||||||
@ -83,11 +87,38 @@ const MainSectionName : string[40] = 'MainSection';
|
|||||||
CommentChar : char = ';';
|
CommentChar : char = ';';
|
||||||
ValidStrDelimiters: set of char = ['''','"'];
|
ValidStrDelimiters: set of char = ['''','"'];
|
||||||
|
|
||||||
|
function EscapeIniText(S : string) : String;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
WUtils;
|
WUtils;
|
||||||
|
|
||||||
|
function EscapeIniText(S : string) : String;
|
||||||
|
var
|
||||||
|
delimiter : char;
|
||||||
|
i: integer;
|
||||||
|
begin
|
||||||
|
delimiter:=#0;
|
||||||
|
while delimiter < #255 do
|
||||||
|
begin
|
||||||
|
if (delimiter in ValidStrDelimiters) and
|
||||||
|
(pos(delimiter,S)=0) then
|
||||||
|
break;
|
||||||
|
delimiter:=succ(delimiter);
|
||||||
|
end;
|
||||||
|
if delimiter=#255 then
|
||||||
|
begin
|
||||||
|
{ we use " delimiter, but the text also contains double quotes,
|
||||||
|
which need to be escaped, by doubling it }
|
||||||
|
delimiter:='"';
|
||||||
|
for i:=length(s) downto 1 do
|
||||||
|
if (s[i]=delimiter) then
|
||||||
|
s:=copy(s,1,i-1)+delimiter+copy(s,i+1,length(s));
|
||||||
|
end;
|
||||||
|
EscapeIniText:=delimiter+s+delimiter;
|
||||||
|
end;
|
||||||
|
|
||||||
{$IFOPT Q+}
|
{$IFOPT Q+}
|
||||||
{$Q-}
|
{$Q-}
|
||||||
{$DEFINE REENABLE_Q}
|
{$DEFINE REENABLE_Q}
|
||||||
@ -120,11 +151,18 @@ begin
|
|||||||
Split;
|
Split;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
constructor TINIEntry.Init(const ATag,AValue,AComment: string);
|
||||||
|
begin
|
||||||
|
inherited Init;
|
||||||
|
Tag:=NewStr(ATag);
|
||||||
|
Value:=NewStr(AValue);
|
||||||
|
Comment:=NewStr(AComment);
|
||||||
|
Text:=NewStr(GetText);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
function TINIEntry.GetText: string;
|
function TINIEntry.GetText: string;
|
||||||
var S,CoS: string;
|
var S,CoS: string;
|
||||||
delimiter : char;
|
|
||||||
i : longint;
|
|
||||||
begin
|
begin
|
||||||
if Text=nil then
|
if Text=nil then
|
||||||
begin
|
begin
|
||||||
@ -135,26 +173,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
{ if Value contains CommentChar, we need to add delimiters }
|
{ if Value contains CommentChar, we need to add delimiters }
|
||||||
if pos(CommentChar,S)>0 then
|
if pos(CommentChar,S)>0 then
|
||||||
begin
|
S:=EscapeIniText(S);
|
||||||
delimiter:=#0;
|
|
||||||
while delimiter < #255 do
|
|
||||||
begin
|
|
||||||
if (delimiter in ValidStrDelimiters) and
|
|
||||||
(pos(delimiter,S)=0) then
|
|
||||||
break;
|
|
||||||
delimiter:=succ(delimiter);
|
|
||||||
end;
|
|
||||||
if delimiter=#255 then
|
|
||||||
delimiter:='"';
|
|
||||||
{ we use \", but we also need to escape \ itself }
|
|
||||||
for i:=length(s) downto 1 do
|
|
||||||
if (s[i]=delimiter) then
|
|
||||||
s:=copy(s,1,i-1)+'\'+delimiter+copy(s,i+1,length(s))
|
|
||||||
else if (s[i]='\') then
|
|
||||||
s:=copy(s,1,i-1)+'\\'+copy(s,i+1,length(s));
|
|
||||||
|
|
||||||
s:=delimiter+s+delimiter;
|
|
||||||
end;
|
|
||||||
S:=S+' '+CommentChar+' '+CoS;
|
S:=S+' '+CommentChar+' '+CoS;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -192,6 +211,17 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TINIEntry.SetComment(const S: string);
|
||||||
|
begin
|
||||||
|
if (GetComment<>S) then
|
||||||
|
begin
|
||||||
|
if Text<>nil then DisposeStr(Text); Text:=nil;
|
||||||
|
if Comment<>nil then DisposeStr(Comment);
|
||||||
|
Comment:=NewStr(S);
|
||||||
|
Modified:=true;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TINIEntry.Split;
|
procedure TINIEntry.Split;
|
||||||
var S,ValueS: string;
|
var S,ValueS: string;
|
||||||
@ -201,7 +231,8 @@ var S,ValueS: string;
|
|||||||
InString: boolean;
|
InString: boolean;
|
||||||
Delimiter: char;
|
Delimiter: char;
|
||||||
begin
|
begin
|
||||||
S:=GetText; Delimiter:=#0;
|
S:=GetText;
|
||||||
|
Delimiter:=#0;
|
||||||
P:=Pos('=',S); P2:=Pos(CommentChar,S);
|
P:=Pos('=',S); P2:=Pos(CommentChar,S);
|
||||||
if (P2<>0) and (P2<P) then
|
if (P2<>0) and (P2<P) then
|
||||||
P:=0;
|
P:=0;
|
||||||
@ -219,15 +250,14 @@ begin
|
|||||||
Delimiter:=C;
|
Delimiter:=C;
|
||||||
InString:=true;
|
InString:=true;
|
||||||
end
|
end
|
||||||
{ if Value is delimited with ' or ", handle escaping }
|
else if (C=Delimiter) then
|
||||||
else if (Delimiter<>#0) and (C='\') and (P2<length(S)) then
|
|
||||||
begin
|
begin
|
||||||
inc(P2);
|
{ Delimiter inside escaped Value are simply doubled }
|
||||||
C:=S[P2];
|
if (P2+1<length(S)) and (S[P2+1]=Delimiter) then
|
||||||
ValueS:=ValueS+C;
|
ValueS:=ValueS+Delimiter
|
||||||
|
else
|
||||||
|
InString:=not InString;
|
||||||
end
|
end
|
||||||
else if C=Delimiter then
|
|
||||||
InString:=not InString
|
|
||||||
else if (C=CommentChar) and (InString=false) then
|
else if (C=CommentChar) and (InString=false) then
|
||||||
Break
|
Break
|
||||||
else
|
else
|
||||||
@ -280,10 +310,47 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function TINISection.AddEntry(const S: string): PINIEntry;
|
function TINISection.AddEntry(const S: string): PINIEntry;
|
||||||
|
var
|
||||||
|
E: PINIEntry;
|
||||||
|
Tag : String;
|
||||||
|
begin
|
||||||
|
if pos('=',S)>0 then
|
||||||
|
begin
|
||||||
|
Tag:=copy(S,1,pos('=',S)-1);
|
||||||
|
E:=SearchEntry(Tag);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
E:=nil;
|
||||||
|
if not assigned(E) then
|
||||||
|
begin
|
||||||
|
New(E, Init(S));
|
||||||
|
Entries^.Insert(E);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
if assigned(E^.Text) then
|
||||||
|
DisposeStr(E^.Text);
|
||||||
|
E^.Text:=NewStr(S);
|
||||||
|
E^.Split;
|
||||||
|
end;
|
||||||
|
AddEntry:=E;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TINISection.AddEntry(const Tag,Value,Comment: string): PINIEntry;
|
||||||
var E: PINIEntry;
|
var E: PINIEntry;
|
||||||
begin
|
begin
|
||||||
New(E, Init(S));
|
E:=SearchEntry(Tag);
|
||||||
Entries^.Insert(E);
|
if not assigned(E) then
|
||||||
|
begin
|
||||||
|
New(E, Init(Tag,Value,Comment));
|
||||||
|
Entries^.Insert(E);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
E^.SetValue(Value);
|
||||||
|
if Comment<>'' then
|
||||||
|
E^.SetComment(Comment);
|
||||||
|
end;
|
||||||
AddEntry:=E;
|
AddEntry:=E;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -511,7 +578,7 @@ begin
|
|||||||
GetEntry:=S;
|
GetEntry:=S;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TINIFile.SetEntry(const Section, Tag, Value: string);
|
procedure TINIFile.SetEntry(const Section, Tag, Value,Comment: string);
|
||||||
var E: PINIEntry;
|
var E: PINIEntry;
|
||||||
P: PINISection;
|
P: PINISection;
|
||||||
begin
|
begin
|
||||||
@ -525,13 +592,18 @@ begin
|
|||||||
New(P, Init(Section));
|
New(P, Init(Section));
|
||||||
Sections^.Insert(P);
|
Sections^.Insert(P);
|
||||||
end;
|
end;
|
||||||
E:=P^.AddEntry(Tag+'='+Value);
|
E:=P^.AddEntry(Tag,Value,Comment);
|
||||||
E^.Modified:=true;
|
E^.Modified:=true;
|
||||||
end;
|
end;
|
||||||
if E<>nil then
|
if E<>nil then
|
||||||
E^.SetValue(Value);
|
E^.SetValue(Value);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TINIFile.SetEntry(const Section, Tag, Value: string);
|
||||||
|
begin
|
||||||
|
SetEntry(Section,Tag,Value,'');
|
||||||
|
end;
|
||||||
|
|
||||||
function TINIFile.GetIntEntry(const Section, Tag: string; Default: longint): longint;
|
function TINIFile.GetIntEntry(const Section, Tag: string; Default: longint): longint;
|
||||||
var L: longint;
|
var L: longint;
|
||||||
begin
|
begin
|
||||||
|
Loading…
Reference in New Issue
Block a user