Browse Source

* Patch from Ondrej Pokorny to make ini files encoding aware (bug ID 32452)

git-svn-id: trunk@37852 -
michael 7 years ago
parent
commit
6e5093a6cc
1 changed files with 70 additions and 29 deletions
  1. 70 29
      packages/fcl-base/src/inifiles.pp

+ 70 - 29
packages/fcl-base/src/inifiles.pp

@@ -153,14 +153,18 @@ type
   Private
     FBoolFalseStrings: TStringArray;
     FBoolTrueStrings: TStringArray;
+    FEncoding: TEncoding;
     FFileName: string;
     FOptions: TIniFileOptions;
+    FOwnsEncoding: Boolean;
     FSectionList: TIniFileSectionList;
     function GetOption(AIndex: TIniFileOption): Boolean;
     procedure SetOption(AIndex: TIniFileOption; AValue: Boolean);
     procedure SetOptions(AValue: TIniFileOptions);
   public
     FormatSettings: TFormatSettings;
+    constructor Create(const AFileName: string; ADefaultEncoding: TEncoding; AOptions : TIniFileOptions = []);
+    constructor Create(const AFileName: string; ADefaultEncoding: TEncoding; AOwnsEncoding: Boolean; AOptions : TIniFileOptions = []);
     constructor Create(const AFileName: string; AOptions : TIniFileOptions = []); virtual;
     constructor Create(const AFileName: string; AEscapeLineFeeds : Boolean); virtual;
     destructor Destroy; override;
@@ -192,6 +196,7 @@ type
     procedure DeleteKey(const Section, Ident: String); virtual; abstract;
     procedure UpdateFile; virtual; abstract;
     function ValueExists(const Section, Ident: string): Boolean; virtual;
+    property Encoding: TEncoding read FEncoding;
     property FileName: string read FFileName;
     Property Options : TIniFileOptions Read FOptions Write SetOptions;
     property EscapeLineFeeds: boolean index ifoEscapeLineFeeds Read GetOption ;deprecated 'Use options instead';
@@ -200,6 +205,7 @@ type
     Property FormatSettingsActive : Boolean index ifoFormatSettingsActive Read GetOption Write SetOption;deprecated  'Use options instead';
     Property BoolTrueStrings : TStringArray Read FBoolTrueStrings Write FBoolTrueStrings;
     Property BoolFalseStrings : TStringArray Read FBoolFalseStrings Write FBoolFalseStrings;
+    Property OwnsEncoding: Boolean Read FOwnsEncoding;
   end;
 
   { TIniFile }
@@ -215,6 +221,7 @@ type
     Procedure MaybeDeleteSection(ASection : TIniFileSection);
     procedure SetCacheUpdates(const AValue: Boolean);
   protected
+    procedure ReadIniValues;
     procedure MaybeUpdateFile;
     property Dirty : Boolean Read FDirty;
   public
@@ -599,9 +606,29 @@ begin
     Create(AFileName,[])
 end;
 
+constructor TCustomIniFile.Create(const AFileName: string;
+  ADefaultEncoding: TEncoding; AOwnsEncoding: Boolean;
+  AOptions: TIniFileOptions);
+begin
+  FEncoding := ADefaultEncoding;
+  FOwnsEncoding := AOwnsEncoding;
+  Create(AFileName, AOptions);
+end;
+
+constructor TCustomIniFile.Create(const AFileName: string;
+  ADefaultEncoding: TEncoding; AOptions: TIniFileOptions);
+begin
+  FEncoding := ADefaultEncoding;
+  if FEncoding <> nil then
+    FOwnsEncoding := not TEncoding.IsStandardEncoding(FEncoding);
+  Create(AFileName, AOptions);
+end;
+
 destructor TCustomIniFile.Destroy;
 begin
   FSectionList.Free;
+  if FOwnsEncoding then
+    FEncoding.Free;
   inherited Destroy;
 end;
 
@@ -902,26 +929,14 @@ end;
 { TIniFile }
 
 
-constructor TIniFile.Create(const AFileName: string; AOptions : TIniFileOptions = []);
-var
-  slLines: TStringList;
+constructor TIniFile.Create(const AFileName: string; AOptions: TIniFileoptions);
 begin
   FBOM := '';
   If Not (self is TMemIniFile) then
     StripQuotes:=True;
   inherited Create(AFileName,AOptions);
   FStream := nil;
-  slLines := TStringList.Create;
-  try
-    if FileExists(FFileName) then
-      begin
-      // read the ini file values
-      slLines.LoadFromFile(FFileName);
-      FillSectionList(slLines);
-      end
-  finally
-    slLines.Free;
-  end;
+  ReadIniValues;
 end;
 
 constructor TIniFile.Create(AStream: TStream; AEscapeLineFeeds : Boolean);
@@ -933,7 +948,7 @@ begin
     Create(AStream,[]);
 end;
 
-constructor TIniFile.Create(AStream: TStream; AOptions : TIniFileOptions = []);
+constructor TIniFile.Create(AStream: TStream; AOptions: TIniFileoptions);
 
 var
   slLines: TStringList;
@@ -952,7 +967,7 @@ begin
   end;
 end;
 
-destructor TIniFile.destroy;
+destructor TIniFile.Destroy;
 begin
   If FDirty and FCacheUpdates then
     try
@@ -1233,7 +1248,7 @@ begin
   ASection.Free;
 end;
 
-Procedure TIniFile.MaybeDeleteSection(ASection : TIniFileSection);
+procedure TIniFile.MaybeDeleteSection(ASection: TIniFileSection);
 
 begin
   If Asection.Empty then
@@ -1306,7 +1321,10 @@ begin
       If D <> '' Then
         if not ForceDirectories(D) then
           Raise EInoutError.CreateFmt(SErrCouldNotCreatePath,[D]);
-      slLines.SaveToFile(FFileName);
+      if FEncoding=nil then
+        slLines.SaveToFile(FFileName)
+      else
+        slLines.SaveToFile(FFileName, FEncoding);
       end
     else if FStream <> nil then
       begin
@@ -1328,6 +1346,38 @@ begin
     UpdateFile;
 end;
 
+procedure TIniFile.ReadIniValues;
+var
+  slLines: TStringList;
+begin
+  FSectionList.Clear;
+
+  if FileExists(FFileName) then
+  begin
+    slLines := TStringList.Create;
+    try
+      // read the ini file values
+      if FEncoding=nil then
+        slLines.LoadFromFile(FFileName)
+      else
+      begin
+        slLines.DefaultEncoding := FEncoding;
+        slLines.LoadFromFile(FFileName, nil);
+        if FEncoding <> slLines.Encoding then
+        begin
+          if FOwnsEncoding then
+            FEncoding.Free;
+          FEncoding := slLines.Encoding;
+          FOwnsEncoding := not TEncoding.IsStandardEncoding(FEncoding);
+        end;
+      end;
+      FillSectionList(slLines);
+    finally
+      slLines.Free;
+    end;
+  end;
+end;
+
 { TMemIniFile }
 
 constructor TMemIniFile.Create(const AFileName: string; AEscapeLineFeeds : Boolean = False);
@@ -1372,20 +1422,11 @@ begin
 end;
 
 procedure TMemIniFile.Rename(const AFileName: string; Reload: Boolean);
-var
-  slLines: TStringList;
 begin
   FFileName := AFileName;
   FStream := nil;
-  if Reload then begin
-    slLines := TStringList.Create;
-    try
-      slLines.LoadFromFile(FFileName);
-      FillSectionList(slLines);
-    finally
-      slLines.Free;
-    end;
-  end;
+  if Reload then
+    ReadIniValues;
 end;
 
 procedure TMemIniFile.SetStrings(List: TStrings);