Browse Source

--- Merging r32768 into '.':
U packages/fcl-base/src/inifiles.pp
--- Recording mergeinfo for merge of r32768 into '.':
U .
--- Merging r32769 into '.':
A packages/fcl-base/examples/inifmt.pp
--- Recording mergeinfo for merge of r32769 into '.':
G .
--- Merging r32961 into '.':
G packages/fcl-base/src/inifiles.pp
U packages/fcl-base/examples/README.txt
A packages/fcl-base/examples/testini.pp
--- Recording mergeinfo for merge of r32961 into '.':
G .

# revisions: 32768,32769,32961

git-svn-id: branches/fixes_3_0@33352 -

marco 9 years ago
parent
commit
a7d3acd6ab

+ 2 - 0
.gitattributes

@@ -1907,6 +1907,7 @@ packages/fcl-base/examples/fpdoc.dtd -text
 packages/fcl-base/examples/fpexprpars.txt svneol=native#text/plain
 packages/fcl-base/examples/fstream.pp svneol=native#text/plain
 packages/fcl-base/examples/htdump.pp svneol=native#text/plain
+packages/fcl-base/examples/inifmt.pp svneol=native#text/plain
 packages/fcl-base/examples/intl/Makefile svneol=native#text/plain
 packages/fcl-base/examples/intl/README.txt svneol=native#text/plain
 packages/fcl-base/examples/intl/restest.cs.mo -text
@@ -1954,6 +1955,7 @@ packages/fcl-base/examples/testcont.pp svneol=native#text/plain
 packages/fcl-base/examples/testexprpars.pp svneol=native#text/plain
 packages/fcl-base/examples/testez.pp svneol=native#text/plain
 packages/fcl-base/examples/testhres.pp svneol=native#text/plain
+packages/fcl-base/examples/testini.pp svneol=native#text/plain
 packages/fcl-base/examples/testmime.pp svneol=native#text/plain
 packages/fcl-base/examples/testnres.pp svneol=native#text/plain
 packages/fcl-base/examples/testol.pp svneol=native#text/plain

+ 1 - 0
packages/fcl-base/examples/README.txt

@@ -73,3 +73,4 @@ poolmm2.pp   Test for pooledmm (nonfree) (VS)
 testweb.pp   Test for fpcgi (MVC)
 daemon.pp    Test for daemonapp (MVC)
 testtimer.pp Test for TFPTimer (MVC)
+testini.pp   Test/Demo for inifiles, ReadSectionValues.

+ 71 - 0
packages/fcl-base/examples/inifmt.pp

@@ -0,0 +1,71 @@
+program inifmt;
+
+{$mode objfpc}{$H+}
+
+uses
+  {$IFDEF UNIX}{$IFDEF UseCThreads}
+  cthreads,
+  {$ENDIF}{$ENDIF}
+  Classes, IniFiles, SysUtils
+  { you can add units after this };
+
+var
+  ini: TCustomIniFile;
+  x: Double;
+  t: TTime;
+  d: TDate;
+  dt: TDateTime;
+  iniName: String = 'test.ini';
+  L: TStringList;
+  i: Integer;
+
+begin
+  x := 1.2345;
+  t := time();
+  d := date();
+  dt := now();
+
+  ini := TMemIniFile.Create(iniName);
+  ini.FormatSettings.DecimalSeparator := '|';
+  ini.FormatSettingsActive := true;
+  ini.WriteFloat('Data', 'float', 1.2345);
+  ini.WriteTime('Data', 'time', t);
+  ini.WriteDate('Data', 'date', d);
+  ini.WriteDateTime('Data', 'datetime', dt);
+  ini.Free;
+
+  WriteLn('-----------------------------------------------------------');
+  WriteLn('Ini file (direct file content)');
+  WriteLn('-----------------------------------------------------------');
+  L := TStringList.Create;
+  L.LoadfromFile(ininame);
+  for i:=0 to L.Count-1 do
+    WriteLn(L[i]);
+  L.Free;
+  WriteLn;
+
+  ini := TMemIniFile.Create(iniName);
+  ini.FormatSettings.DecimalSeparator := '|';
+  ini.FormatSettingsActive := true;
+  x := ini.ReadFloat('Data', 'float', 0);
+  t := ini.ReadTime('Data', 'time', 0);
+  d := ini.ReadDate('Data', 'date', 0);
+  dt := ini.ReadDateTime('Data', 'datetime', 0);
+  ini.Free;
+
+  WriteLn('------------------------------------------------------------------');
+  WriteLn('Read input data from ini file (output using DefaultFormatSettings)');
+  WriteLn('------------------------------------------------------------------');
+  WriteLn('float = ', FloatToStr(x));
+  WriteLn('time = ', TimeToStr(t));
+  WriteLn('date = ', DateToStr(d));
+  WriteLn('date/time = ', DateTimeToStr(dt));
+  WriteLn;
+
+  {$IFDEF MSWINDOWS}
+  WriteLn('Press [ENTER] to quit...');
+  ReadLn;
+  {$ENDIF}
+end.
+
+

+ 61 - 0
packages/fcl-base/examples/testini.pp

@@ -0,0 +1,61 @@
+program testini;
+
+{$mode objfpc}{$H+}
+
+uses
+  inifiles, classes;
+
+var
+  i: Integer;
+  ini: TMemIniFile;
+  lines: TStrings;
+
+begin
+  lines:=TStringList.Create();
+  try
+    lines.Add('[main]');
+    lines.Add('key_a=1');
+    lines.Add(';comment');
+    lines.Add('key_b   =2');
+    lines.Add('not_valid');
+    lines.Add('key_c=   3');
+    lines.Add('key_d="3"');
+    WriteLn('ini file source:');
+    for i:=0 to lines.Count-1 do 
+      WriteLn('  ', lines[i]);
+    ini:=TMemIniFile.Create('');
+    try
+      ini.options:=ini.options+[ifoStripQuotes];
+      ini.SetStrings(lines);
+      lines.Clear();
+      ini.ReadSectionValues('main', lines,[]);
+      WriteLn('ReadSectionValues (no options):');
+      for i:=0 to lines.Count-1 do 
+        WriteLn('  ', lines[i]);
+      lines.Clear();
+      ini.ReadSectionValues('main', lines,[svoIncludeComments]);
+      WriteLn('ReadSectionValues (with comments, no invalid):');
+      for i:=0 to lines.Count-1 do
+        WriteLn('  ', lines[i]);
+      lines.Clear();
+      ini.ReadSectionValues('main', lines,[svoIncludeInvalid]);
+      WriteLn('ReadSectionValues (without comments, with invalid):');
+      for i:=0 to lines.Count-1 do
+        WriteLn('  ', lines[i]);
+      lines.Clear();
+      ini.ReadSectionValues('main', lines,[svoIncludeComments,svoIncludeInvalid]);
+      WriteLn('ReadSectionValues (with comments, with invalid):');
+      for i:=0 to lines.Count-1 do
+        WriteLn('  ', lines[i]);
+      Lines.Clear;
+      ini.ReadSectionValues('main', lines,[svoIncludeQuotes]);
+      WriteLn('ReadSectionValues (with quotes):');
+      for i:=0 to lines.Count-1 do
+        WriteLn('  ', lines[i]);
+    finally
+      ini.Free();
+    end;
+  finally
+    lines.Free();
+  end
+end.

+ 227 - 55
packages/fcl-base/src/inifiles.pp

@@ -134,17 +134,31 @@ type
     property Items[Index: integer]: TIniFileSection read GetItem; default;
   end;
 
+  TIniFileOption = (ifoStripComments,    // Strip comments when reading file
+                    ifoStripInvalid,     // Strip invalid lines when reading file.
+                    ifoEscapeLineFeeds, // Escape linefeeds when reading file.
+                    ifoCaseSensitive,   // Use Case sensitive section/key names
+                    ifoStripQuotes,     // Strip quotes when reading string values.
+                    ifoFormatSettingsActive); // Use format settings when writing date/float etc.
+  TIniFileOptions = Set of TIniFileOption;
+
+  TSectionValuesOption = (svoIncludeComments,svoIncludeInvalid, svoIncludeQuotes);
+  TSectionValuesOptions = set of TSectionValuesOption;
+
   { TCustomIniFile }
 
   TCustomIniFile = class
   Private
     FFileName: string;
+    FOptions: TIniFileOptions;
     FSectionList: TIniFileSectionList;
-    FEscapeLineFeeds: boolean;
-    FCaseSensitive : Boolean;
-    FStripQuotes : Boolean;
+    function GetOption(AIndex: TIniFileOption): Boolean;
+    procedure SetOption(AIndex: TIniFileOption; AValue: Boolean);
+    procedure SetOptions(AValue: TIniFileOptions);
   public
-    constructor Create(const AFileName: string; AEscapeLineFeeds : Boolean = False); virtual;
+    FormatSettings: TFormatSettings;
+    constructor Create(const AFileName: string; AOptions : TIniFileOptions = []); virtual;
+    constructor Create(const AFileName: string; AEscapeLineFeeds : Boolean); virtual;
     destructor Destroy; override;
     function SectionExists(const Section: string): Boolean; virtual;
     function ReadString(const Section, Ident, Default: string): string; virtual; abstract;
@@ -167,15 +181,18 @@ type
     procedure WriteBinaryStream(const Section, Name: string; Value: TStream); virtual;
     procedure ReadSection(const Section: string; Strings: TStrings); virtual; abstract;
     procedure ReadSections(Strings: TStrings); virtual; abstract;
-    procedure ReadSectionValues(const Section: string; Strings: TStrings); virtual; abstract;
+    procedure ReadSectionValues(const Section: string; Strings: TStrings; Options : TSectionValuesOptions); virtual;    overload;
+    procedure ReadSectionValues(const Section: string; Strings: TStrings); virtual;overload;
     procedure EraseSection(const Section: string); virtual; abstract;
     procedure DeleteKey(const Section, Ident: String); virtual; abstract;
     procedure UpdateFile; virtual; abstract;
     function ValueExists(const Section, Ident: string): Boolean; virtual;
     property FileName: string read FFileName;
-    property EscapeLineFeeds: boolean read FEscapeLineFeeds;
-    Property CaseSensitive : Boolean Read FCaseSensitive Write FCaseSensitive;
-    Property StripQuotes : Boolean Read FStripQuotes Write FStripQuotes;
+    Property Options : TIniFileOptions Read FOptions Write SetOptions;
+    property EscapeLineFeeds: boolean index ifoEscapeLineFeeds Read GetOption ;deprecated 'Use options instead';
+    Property CaseSensitive : Boolean index ifoCaseSensitive Read GetOption Write SetOption; deprecated  'Use options instead';
+    Property StripQuotes : Boolean index ifoStripQuotes Read GetOption Write SetOption; deprecated 'Use options instead';
+    Property FormatSettingsActive : Boolean index ifoFormatSettingsActive Read GetOption Write SetOption;deprecated  'Use options instead';
   end;
 
   { TIniFile }
@@ -194,15 +211,16 @@ type
     procedure MaybeUpdateFile;
     property Dirty : Boolean Read FDirty;
   public
-    constructor Create(const AFileName: string; AEscapeLineFeeds : Boolean = False); overload; override;
-    constructor Create(AStream: TStream; AEscapeLineFeeds : Boolean = False); overload;
+    constructor Create(const AFileName: string; AOptions : TIniFileoptions = []); overload; override;
+    constructor Create(AStream: TStream; AOptions : TIniFileoptions = []); overload;
+    constructor Create(AStream: TStream; AEscapeLineFeeds : Boolean); overload; deprecated 'Use Options argument instead';
     destructor Destroy; override;
     function ReadString(const Section, Ident, Default: string): string; override;
     procedure WriteString(const Section, Ident, Value: String); override;
     procedure ReadSection(const Section: string; Strings: TStrings); override;
     procedure ReadSectionRaw(const Section: string; Strings: TStrings);
     procedure ReadSections(Strings: TStrings); override;
-    procedure ReadSectionValues(const Section: string; Strings: TStrings); override;
+    procedure ReadSectionValues(const Section: string; Strings: TStrings; AOptions : TSectionValuesOptions = []); overload; override;
     procedure EraseSection(const Section: string); override;
     procedure DeleteKey(const Section, Ident: String); override;
     procedure UpdateFile; override;
@@ -507,11 +525,54 @@ end;
 
 { TCustomIniFile }
 
-constructor TCustomIniFile.Create(const AFileName: string; AEscapeLineFeeds : Boolean = False);
+
+function TCustomIniFile.GetOption(AIndex: TIniFileOption): Boolean;
+begin
+  Result:=AIndex in FOptions;
+end;
+
+
+procedure TCustomIniFile.SetOption(AIndex: TIniFileOption; AValue: Boolean);
+begin
+  if AIndex in [ifoStripComments,ifoStripInvalid] then
+    Raise Exception.Create('Flags ifoStripComments or ifoStripInvalid must be set/unset in the constructor');
+  if AValue then
+    Include(FOptions,AIndex)
+  else
+    Exclude(FOptions,AIndex)
+end;
+
+procedure TCustomIniFile.SetOptions(AValue: TIniFileOptions);
+begin
+  if FOptions=AValue then Exit;
+  FOptions:=AValue;
+end;
+
+constructor TCustomIniFile.Create(const AFileName: string; AOptions : TIniFileOptions = []);
 begin
   FFileName := AFileName;
   FSectionList := TIniFileSectionList.Create;
-  FEscapeLineFeeds := AEscapeLineFeeds;
+  FOptions:=AOptions;
+  FormatSettings := DefaultFormatSettings;
+  with FormatSettings do begin
+    DecimalSeparator := '.';
+    ThousandSeparator := ',';
+    ListSeparator := ';';
+    DateSeparator := '/';
+    TimeSeparator := ':';
+    ShortDateFormat := 'yyyy/mm/dd';
+    ShortTimeFormat := 'hh:nn';
+    LongTimeFormat := 'hh:nn:ss';
+  end;
+end;
+
+constructor TCustomIniFile.Create(const AFileName: string;
+  AEscapeLineFeeds: Boolean);
+begin
+  if AEscapeLineFeeds then
+    Create(AFileName,[ifoEscapeLineFeeds])
+  else
+    Create(AFileName,[])
 end;
 
 destructor TCustomIniFile.Destroy;
@@ -570,45 +631,71 @@ end;
 function TCustomIniFile.ReadDate(const Section, Ident: string; Default: TDateTime): TDateTime;
 
 begin
-  Result := StrToDateDef(ReadString(Section, Ident, ''),Default);
+  if FormatSettingsActive then begin
+    if not TryStrToDate(ReadString(Section, Ident, ''), Result, FormatSettings) then
+      Result := Default;
+  end else
+    Result := StrToDateDef(ReadString(Section, Ident, ''),Default);
 end;
 
 function TCustomIniFile.ReadDateTime(const Section, Ident: string; Default: TDateTime): TDateTime;
 
 begin
-  Result := StrToDateTimeDef(ReadString(Section, Ident, ''),Default);
+  if FormatSettingsActive then begin
+    if not TryStrToDateTime(ReadString(Section, Ident, ''), Result, FormatSettings) then
+      Result := Default;
+  end else
+    Result := StrToDateTimeDef(ReadString(Section, Ident, ''),Default);
 end;
 
 function TCustomIniFile.ReadFloat(const Section, Ident: string; Default: Double): Double;
 
 begin
-  Result:=StrToFloatDef(ReadString(Section, Ident, ''),Default);
+  if FormatSettingsActive then
+    Result:=StrToFloatDef(ReadString(Section, Ident, ''),Default, FormatSettings)
+  else
+    Result:=StrToFloatDef(ReadString(Section, Ident, ''),Default);
 end;
 
 function TCustomIniFile.ReadTime(const Section, Ident: string; Default: TDateTime): TDateTime;
 
 begin
-  Result := StrToTimeDef(ReadString(Section, Ident, ''),Default);
+  if FormatSettingsActive then
+    Result := StrToTimeDef(ReadString(Section, Ident, ''),Default, FormatSettings.TimeSeparator)
+  else
+    Result := StrToTimeDef(ReadString(Section, Ident, ''),Default);
 end;
 
 procedure TCustomIniFile.WriteDate(const Section, Ident: string; Value: TDateTime);
 begin
-  WriteString(Section, Ident, DateToStr(Value));
+  if FormatSettingsActive then
+    WriteString(Section, Ident, DateToStr(Value, FormatSettings))
+  else
+    WriteString(Section, Ident, DateToStr(Value));
 end;
 
 procedure TCustomIniFile.WriteDateTime(const Section, Ident: string; Value: TDateTime);
 begin
-  WriteString(Section, Ident, DateTimeToStr(Value));
+  if FormatSettingsActive then
+    WriteString(Section, Ident, DateTimeToStr(Value, FormatSettings))
+  else
+    WriteString(Section, Ident, DateTimeToStr(Value));
 end;
 
 procedure TCustomIniFile.WriteFloat(const Section, Ident: string; Value: Double);
 begin
-  WriteString(Section, Ident, FloatToStr(Value));
+  if FormatSettingsActive then
+    WriteString(Section, Ident, FloatToStr(Value, FormatSettings))
+  else
+    WriteString(Section, Ident, FloatToStr(Value));
 end;
 
 procedure TCustomIniFile.WriteTime(const Section, Ident: string; Value: TDateTime);
 begin
-  WriteString(Section, Ident, TimeToStr(Value));
+  if FormatSettingsActive then
+    WriteString(Section, Ident, TimeToStr(Value, FormatSettings))
+  else
+    WriteString(Section, Ident, TimeToStr(Value));
 end;
 
 function TCustomIniFile.ValueExists(const Section, Ident: string): Boolean;
@@ -658,7 +745,8 @@ begin
     end;
 end;
 
-procedure TCustomInifile.WriteBinaryStream(const Section, Name: string; Value: TStream);
+procedure TCustomIniFile.WriteBinaryStream(const Section, Name: string;
+  Value: TStream);
 
 
 Var
@@ -693,16 +781,54 @@ begin
   end;
 end;
 
+procedure TCustomIniFile.ReadSectionValues(const Section: string; Strings: TStrings; Options: TSectionValuesOptions);
+
+type
+  TOldSectionValues = Procedure (const Section: string; Strings: TStrings) of object;
+
+var
+  CurrSV,
+  TCustomSV: TOldSectionValues;
+  CurrClass   : TClass;
+
+begin
+  if (Options<>[]) then
+    Raise Exception.Create('Options not supported, options must be empty');
+  // Redirect calls to old implementation, if it is overridden.
+  CurrSV:=nil;
+  CurrClass:=Classtype;
+  while (CurrClass<>nil) and (CurrClass<>TCustomIniFile) do
+   CurrClass:=CurrClass.Classparent;
+  if CurrClass<>nil then
+    begin
+    CurrSV:[email protected];
+    TCustomSV:=@TCustomIniFile(@CurrClass).ReadSectionValues;
+    if TMethod(TCustomSV).Code=TMethod(CurrSV).Code then
+      CurrSV:=nil;
+   end;
+  if Assigned(CurrSV) then
+    ReadSectionValues(Section,Strings)
+  else
+    Raise Exception.Create('ReadSectionValues not overridden');
+end;
+
+procedure TCustomIniFile.ReadSectionValues(const Section: string;
+  Strings: TStrings);
+begin
+  ReadSectionValues(Section,Strings,[]);
+end;
+
 { TIniFile }
 
-constructor TIniFile.Create(const AFileName: string; AEscapeLineFeeds : Boolean = False);
+
+constructor TIniFile.Create(const AFileName: string; AOptions : TIniFileOptions = []);
 var
   slLines: TStringList;
 begin
   FBOM := '';
   If Not (self is TMemIniFile) then
     StripQuotes:=True;
-  inherited Create(AFileName,AEscapeLineFeeds);
+  inherited Create(AFileName,AOptions);
   FStream := nil;
   slLines := TStringList.Create;
   try
@@ -717,12 +843,23 @@ begin
   end;
 end;
 
-constructor TIniFile.Create(AStream: TStream; AEscapeLineFeeds : Boolean = False);
+constructor TIniFile.Create(AStream: TStream; AEscapeLineFeeds : Boolean);
+
+begin
+  if AEscapeLineFeeds then
+    Create(AStream,[ifoEscapeLineFeeds])
+  else
+    Create(AStream,[]);
+end;
+
+constructor TIniFile.Create(AStream: TStream; AOptions : TIniFileOptions = []);
+
 var
   slLines: TStringList;
+
 begin
   FBOM := '';
-  inherited Create('',AEscapeLineFeeds);
+  inherited Create('',AOptions);
   FStream := AStream;
   slLines := TStringList.Create;
   try
@@ -778,10 +915,13 @@ var
     end;
   end;
 
+Var
+  addKey : Boolean;
+
 begin
   oSection := nil;
   FSectionList.Clear;
-  if FEscapeLineFeeds then
+  if EscapeLineFeeds then
     RemoveBackslashes;
   if (AStrings.Count > 0) and (copy(AStrings.Strings[0],1,Length(Utf8Bom)) = Utf8Bom) then
   begin
@@ -792,37 +932,51 @@ begin
     sLine := Trim(AStrings[i]);
     if sLine > '' then
       begin
-      if IsComment(sLine) and (oSection = nil) then begin
+      if IsComment(sLine) and (oSection = nil) then
+        begin
         // comment at the beginning of the ini file
-        oSection := TIniFileSection.Create(sLine);
-        FSectionList.Add(oSection);
+        if Not (ifoStripComments in Options) then
+          begin
+          oSection := TIniFileSection.Create(sLine);
+          FSectionList.Add(oSection);
+          end;
         continue;
-      end;
-      if (Copy(sLine, 1, 1) = Brackets[0]) and (Copy(sLine, length(sLine), 1) = Brackets[1]) then begin
+        end;
+      if (Copy(sLine, 1, 1) = Brackets[0]) and (Copy(sLine, length(sLine), 1) = Brackets[1]) then
+        begin
         // regular section
         oSection := TIniFileSection.Create(Copy(sLine, 2, Length(sLine) - 2));
         FSectionList.Add(oSection);
-      end else if oSection <> nil then begin
-        if IsComment(sLine) then begin
+        end
+      else if oSection <> nil then
+        begin
+        if IsComment(sLine) then
+          begin
+          AddKey:=Not (ifoStripComments in Options);
           // comment within a section
           sIdent := sLine;
           sValue := '';
-        end else begin
+          end
+        else
+          begin
           // regular key
           j:=Pos(Separator, sLine);
           if j=0 then
            begin
-             sIdent:='';
-             sValue:=sLine
+           AddKey:=Not (ifoStripInvalid in Options);
+           sIdent:='';
+           sValue:=sLine
            end
           else
            begin
-             sIdent:=Trim(Copy(sLine, 1,  j - 1));
-             sValue:=Trim(Copy(sLine, j + 1, Length(sLine) - j));
+           AddKey:=True;
+           sIdent:=Trim(Copy(sLine, 1,  j - 1));
+           sValue:=Trim(Copy(sLine, j + 1, Length(sLine) - j));
            end;
         end;
-        oSection.KeyList.Add(TIniFileKey.Create(sIdent, sValue));
-      end;
+        if AddKey then
+          oSection.KeyList.Add(TIniFileKey.Create(sIdent, sValue));
+        end;
       end;
   end;
 end;
@@ -942,31 +1096,49 @@ begin
   end;
 end;
 
-procedure TIniFile.ReadSectionValues(const Section: string; Strings: TStrings);
+procedure TIniFile.ReadSectionValues(const Section: string; Strings: TStrings; AOptions : TSectionValuesOptions = []);
 var
   oSection: TIniFileSection;
   s: string;
   i,J: integer;
+  KeyIsComment,IncludeComments,IncludeInvalid,DoStripQuotes : boolean;
+  K : TIniFileKey;
+
 begin
+  IncludeComments:=(svoIncludeComments in AOptions) Or (ifoStripComments in Options);
+  IncludeInvalid:=(svoIncludeInvalid in AOptions) Or (ifoStripInvalid in Options);
+  DoStripQuotes:=StripQuotes and Not (svoIncludeQuotes in AOptions);
   Strings.BeginUpdate;
   try
     Strings.Clear;
     oSection := FSectionList.SectionByName(Section,CaseSensitive);
-    if oSection <> nil then with oSection.KeyList do
-      for i := 0 to Count-1 do begin
-        s := Items[i].Value;
-      If StripQuotes then
+    if oSection = nil then
+      Exit;
+    for i := 0 to oSection.KeyList.Count-1 do
+      begin
+      K:=oSection.KeyList.Items[i];
+      if IncludeInvalid or (K.Ident<>'') then
         begin
-          J:=Length(s);
-          // Joost, 2-jan-2007: The check (J>1) is there for the case that
-          // the value consist of a single double-quote character. (see
-          // mantis bug 6555)
-          If (J>1) and ((s[1] in ['"','''']) and (s[J]=s[1])) then
-             s:=Copy(s,2,J-2);
+        s := K.Value;
+        KeyIsComment:=IsComment(K.Ident);
+        if IncludeComments Or Not KeyIsComment then
+          begin
+          If DoStripQuotes then
+            begin
+            J:=Length(s);
+            // Joost, 2-jan-2007: The check (J>1) is there for the case that
+            // the value consist of a single double-quote character. (see
+            // mantis bug 6555)
+            If (J>1) and ((s[1] in ['"','''']) and (s[J]=s[1])) then
+               s:=Copy(s,2,J-2);
+            end;
+          if KeyIsComment then
+            S:=K.Ident
+          else if k.ident<>'' then
+            s:=K.Ident+Separator+s;
+          Strings.Add(s);
+          end;
         end;
-        if Items[i].Ident<>'' then
-          s:=Items[i].Ident+Separator+s;
-        Strings.Add(s);
       end;
   finally
     Strings.EndUpdate;