------------------------------------------------------------------------
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:
pierre 2015-09-17 22:26:28 +00:00
parent 88d00ef331
commit 81a6f3ea2a
2 changed files with 114 additions and 42 deletions

View File

@ -612,7 +612,7 @@ begin
{ Files }
{ avoid keeping old files }
INIFile^.DeleteSection(secFiles);
INIFile^.SetEntry(secFiles,ieOpenExts,'"'+OpenExts+'"');
INIFile^.SetEntry(secFiles,ieOpenExts,EscapeIniText(OpenExts));
for I:=1 to High(RecentFiles) do
begin
if I<=RecentFileCount then
@ -678,17 +678,17 @@ begin
{ Help }
S:='';
HelpFiles^.ForEach(@ConcatName);
INIFile^.SetEntry(secHelp,ieHelpFiles,'"'+S+'"');
INIFile^.SetEntry(secHelp,ieHelpFiles,EscapeIniText(S));
{ Editor }
INIFile^.SetIntEntry(secEditor,ieDefaultTabSize,DefaultTabSize);
INIFile^.SetIntEntry(secEditor,ieDefaultIndentSize,DefaultIndentSize);
INIFile^.SetIntEntry(secEditor,ieDefaultEditorFlags,DefaultCodeEditorFlags);
INIFile^.SetEntry(secEditor,ieDefaultSaveExt,DefaultSaveExt);
{ Highlight }
INIFile^.SetEntry(secHighlight,ieHighlightExts,'"'+HighlightExts+'"');
INIFile^.SetEntry(secHighlight,ieTabsPattern,'"'+TabsPattern+'"');
INIFile^.SetEntry(secHighlight,ieHighlightExts,EscapeIniText(HighlightExts));
INIFile^.SetEntry(secHighlight,ieTabsPattern,EscapeIniText(TabsPattern));
{ SourcePath }
INIFile^.SetEntry(secSourcePath,ieSourceList,'"'+SourceDirs+'"');
INIFile^.SetEntry(secSourcePath,ieSourceList,EscapeIniText(SourceDirs));
{ Mouse }
INIFile^.SetIntEntry(secMouse,ieDoubleClickDelay,DoubleDelay);
INIFile^.SetIntEntry(secMouse,ieReverseButtons,byte(MouseReverse));
@ -718,9 +718,9 @@ begin
begin
S:=IntToStr(I);
GetToolParams(I-1,S1,S2,S3,W);
if S1<>'' then S1:='"'+S1+'"';
if S2<>'' then S2:='"'+S2+'"';
if S3<>'' then S3:='"'+S3+'"';
if S1<>'' then S1:=EscapeIniText(S1);
if S2<>'' then S2:=EscapeIniText(S2);
if S3<>'' then S3:=EscapeIniText(S3);
INIFile^.SetEntry(secTools,ieToolName+S,S1);
INIFile^.SetEntry(secTools,ieToolProgram+S,S2);
INIFile^.SetEntry(secTools,ieToolParams+S,S3);

View File

@ -23,11 +23,13 @@ type
PINIEntry = ^TINIEntry;
TINIEntry = object(TObject)
constructor Init(const ALine: string);
constructor Init(const ATag,AValue,AComment: string);
function GetText: string;
function GetTag: string;
function GetComment: string;
function GetValue: string;
procedure SetValue(const S: string);
procedure SetComment(const S: string);
destructor Done; virtual;
private
TagHash : Cardinal;
@ -44,6 +46,7 @@ type
constructor Init(const AName: string);
function GetName: string;
function AddEntry(const S: string): PINIEntry;
function AddEntry(const Tag,Value,Comment: string): PINIEntry;
function SearchEntry(Tag: string): PINIEntry; virtual;
procedure DeleteEntry(Tag: string);
procedure ForEachEntry(EnumProc: pointer); virtual;
@ -68,6 +71,7 @@ type
procedure ForEachEntry(const Section: string; EnumProc: pointer); virtual;
function GetEntry(const Section, Tag, Default: string): 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;
procedure SetIntEntry(const Section, Tag: string; Value: longint); virtual;
procedure DeleteSection(const Section: string); virtual;
@ -83,11 +87,38 @@ const MainSectionName : string[40] = 'MainSection';
CommentChar : char = ';';
ValidStrDelimiters: set of char = ['''','"'];
function EscapeIniText(S : string) : String;
implementation
uses
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+}
{$Q-}
{$DEFINE REENABLE_Q}
@ -120,11 +151,18 @@ begin
Split;
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;
var S,CoS: string;
delimiter : char;
i : longint;
begin
if Text=nil then
begin
@ -135,26 +173,7 @@ begin
begin
{ if Value contains CommentChar, we need to add delimiters }
if pos(CommentChar,S)>0 then
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
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:=EscapeIniText(S);
S:=S+' '+CommentChar+' '+CoS;
end
end
@ -192,6 +211,17 @@ begin
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;
var S,ValueS: string;
@ -201,7 +231,8 @@ var S,ValueS: string;
InString: boolean;
Delimiter: char;
begin
S:=GetText; Delimiter:=#0;
S:=GetText;
Delimiter:=#0;
P:=Pos('=',S); P2:=Pos(CommentChar,S);
if (P2<>0) and (P2<P) then
P:=0;
@ -219,15 +250,14 @@ begin
Delimiter:=C;
InString:=true;
end
{ if Value is delimited with ' or ", handle escaping }
else if (Delimiter<>#0) and (C='\') and (P2<length(S)) then
else if (C=Delimiter) then
begin
inc(P2);
C:=S[P2];
ValueS:=ValueS+C;
{ Delimiter inside escaped Value are simply doubled }
if (P2+1<length(S)) and (S[P2+1]=Delimiter) then
ValueS:=ValueS+Delimiter
else
InString:=not InString;
end
else if C=Delimiter then
InString:=not InString
else if (C=CommentChar) and (InString=false) then
Break
else
@ -280,10 +310,47 @@ begin
end;
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;
begin
New(E, Init(S));
Entries^.Insert(E);
E:=SearchEntry(Tag);
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;
end;
@ -511,7 +578,7 @@ begin
GetEntry:=S;
end;
procedure TINIFile.SetEntry(const Section, Tag, Value: string);
procedure TINIFile.SetEntry(const Section, Tag, Value,Comment: string);
var E: PINIEntry;
P: PINISection;
begin
@ -525,13 +592,18 @@ begin
New(P, Init(Section));
Sections^.Insert(P);
end;
E:=P^.AddEntry(Tag+'='+Value);
E:=P^.AddEntry(Tag,Value,Comment);
E^.Modified:=true;
end;
if E<>nil then
E^.SetValue(Value);
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;
var L: longint;
begin