{ This file is part of the Free Component Library (FCL) Copyright (c) 1999-2000 by Michael Van Canneyt and Florian Klaempfl See the file COPYING.FPC, included in this distribution, for details about the copyright. This program 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. **********************************************************************} {$mode objfpc} {$h+} {$IFNDEF FPC_DOTTEDUNITS} unit inicol; {$ENDIF FPC_DOTTEDUNITS} interface {$IFDEF FPC_DOTTEDUNITS} Uses System.SysUtils,System.Classes,System.IniFiles; {$ELSE FPC_DOTTEDUNITS} Uses SysUtils,Classes,Inifiles; {$ENDIF FPC_DOTTEDUNITS} Type { TIniCollectionItem } TIniCollectionItem = Class(TCollectionItem) protected function GetSectionName: String; virtual; abstract; procedure SetSectionName(const Value: String ); virtual; abstract; Public Procedure SaveToIni(Ini: TCustomInifile; Section : String); Virtual; Abstract; Procedure LoadFromIni(Ini: TCustomInifile; Section : String); Virtual; Abstract; Procedure SaveToFile(const FileName : String; const Section : String); Procedure LoadFromFile(const FileName :String ; const Section : String); Property SectionName : String Read GetSectionName Write SetSectionName; end; TIniCollection = Class(TCollection) private FFileName: String; FGlobalSection: String; protected FPrefix:String ; // Descendent must set this. FSectionPrefix : String; // Descendent must set this too. Public Procedure Load; Procedure Save; Procedure SaveToIni(Ini: TCustomInifile; Section : String); virtual; Procedure SaveToFile(const AFileName : String; const Section : String); Procedure LoadFromIni(Ini: TCustomInifile; Section : String); virtual; Procedure LoadFromFile(const AFileName, Section : String); Property Prefix : String Read FPrefix; Property SectionPrefix : String Read FSectionPrefix; Property FileName : String Read FFileName Write FFileName; Property GlobalSection : String Read FGlobalSection Write FGlobalSection; end; { TNamedIniCollectionItem } TNamedIniCollectionItem = Class(TIniCollectionItem) private procedure SetName(const AValue:String); Protected FName : String; FUserData : TObject; Protected Procedure SetCollection(Value : TCollection); override; function GetSectionName: String; override; procedure SetSectionName(const Value:String ); override; Public Property UserData : TObject Read FUserData Write FUserData; Published Property Name : String Read FName Write SetName; end; { TNamedIniCollection } TNamedIniCollection = Class(TIniCollection) private function GetNamedItem(Index: Integer): TNamedIniCollectionItem; procedure SetNamedItem(Index: Integer; const AValue: TNamedIniCollectionItem); Public Function IndexOfUserData(UserData : TObject) : Integer; Function IndexOfName(Const AName :String ) : Integer; Function FindByName(Const AName :String ) : TNamedIniCollectionItem; Function FindByUserData(UserData : TObject) : TNamedIniCollectionItem; Property NamedItems [Index: Integer] : TNamedIniCollectionItem Read GetNamedItem Write SetNamedItem; default; end; EIniCol = Class(Exception); Const KeyCount = 'Count'; SGlobal = 'Global'; implementation { TIniCollectionItem } resourcestring SErrNoFileName = '%s: No filename specified.'; SErrNoSection = '%s: No [global] section specified.'; SErrDuplicateName = 'Duplicate names "%s" not allowed in collection'; procedure TIniCollectionItem.LoadFromFile(const FileName, Section: String); Var Ini : TMemInifile; begin Ini:=TMemInifile.Create(FileName); Try LoadFromIni(Ini,Section); Finally Ini.Free; end; end; procedure TIniCollectionItem.SaveToFile(const FileName, Section: String); Var Ini : TMemInifile; begin Ini:=TMemInifile.Create(FileName); Try SaveToIni(Ini,Section); Ini.UpdateFile; Finally Ini.Free; end; end; { TIniCollection } procedure TIniCollection.Load; begin If (FFileName='') then Raise EIniCol.CreateFmt(SErrNoFileName,[ClassName]); If (GlobalSection='') then Raise EIniCol.CreateFmt(SErrNoSection,[ClassName]); LoadFromFile(FFileName,GlobalSection) end; procedure TIniCollection.LoadFromFile(const AFileName, Section: String); Var Ini : TMemIniFile; begin Ini:=TMemInifile.Create(AFileName); Try LoadFromIni(Ini,Section); FFileName:=AFileName; FGlobalSection:=Section; Finally ini.Free; end; end; procedure TIniCollection.LoadFromIni(Ini: TCustomInifile; Section:String); Var ACount,I : Integer; N,SP :String ; begin Clear; SP:=FSectionPrefix; If (SP<>'') then SP:=SP+'_'; ACount:=Ini.ReadInteger(Section,KeyCount,0); For I:=1 to ACount do begin N:=Ini.ReadString(Section,Prefix+IntToStr(I),''); If (N<>'') then With Add as TIniCollectionItem do begin SectionName:=N; LoadFromIni(Ini,SP+N); end; end; end; procedure TIniCollection.Save; begin If (FFileName='') then Raise EIniCol.CreateFmt(SErrNoFileName,[ClassName]); If (GlobalSection='') then Raise EIniCol.CreateFmt(SErrNoSection,[ClassName]); SaveToFile(FFileName,GlobalSection) end; procedure TIniCollection.SaveToFile(const AFileName, Section: String); Var Ini : TMemIniFile; begin Ini:=TMemInifile.Create(AFileName); Try Ini.CacheUpdates:=True; SaveToIni(Ini,Section); Ini.UpdateFile; finally Ini.Free; end; end; procedure TIniCollection.SaveToIni(Ini: TCustomInifile; Section: String); Var S,V,SP : String; I : Integer; CI : TIniCollectionItem; begin SP:=FSectionPrefix; if (SP<>'') then SP:=SP+'_'; Ini.WriteInteger(Section,KeyCount,Count); For I:=0 to Count-1 do begin CI:=(Items[i]) as TIniCollectionItem; With CI do begin V:=SectionName; S:=Prefix+IntToStr(I+1); Ini.WriteString(Section,S,V); CI.SaveToIni(Ini,SP+V); end; end; end; { --------------------------------------------------------------------- TNamedIniCollectionItem ---------------------------------------------------------------------} procedure TNamedIniCollectionItem.SetName(const AValue: String); begin If (CompareText(AValue,FName)<>0) then begin If (AValue<>'') and (Collection<>Nil) and (Collection is TNamedIniCollection) then If TNamedIniCollection(Collection).IndexOfName(AValue)<>-1 then Raise EIniCol.CreateFmt(SErrDuplicateName,[AValue]); end; FName:=AValue; end; procedure TNamedIniCollectionItem.SetCollection(Value: TCollection); begin If (Value<>Collection) then begin If (Value<>Nil) and (Value is TNamedIniCollection) Then If TNamedIniCollection(Value).IndexOfName(Self.Name)<>-1 then Raise EIniCol.CreateFmt(SErrDuplicateName,[Self.Name]); end; inherited SetCollection(Value); end; function TNamedIniCollectionItem.GetSectionName:String ; begin Result:=FName; end; procedure TNamedIniCollectionItem.SetSectionName(const Value: String); begin FName:=Value; // Skip check. Ini files have only 1 named section end; { --------------------------------------------------------------------- TNamedIniCollection ---------------------------------------------------------------------} function TNamedIniCollection.GetNamedItem(Index: Integer): TNamedIniCollectionItem; begin Result:=Items[Index] as TNamedIniCollectionItem; end; procedure TNamedIniCollection.SetNamedItem(Index: Integer; const AValue: TNamedIniCollectionItem); begin Items[Index]:=AValue; end; function TNamedIniCollection.IndexOfUserData(UserData: TObject): Integer; begin If (UserData=Nil) then Result:=-1 else begin Result:=Count-1; While (Result>=0) and (GetNamedItem(Result).UserData<>UserData) do Dec(Result); end; end; function TNamedIniCollection.IndexOfName(const AName: String): Integer; begin Result:=Count-1; While (Result>=0) and (CompareText(GetNamedItem(Result).Name,AName)<>0) do Dec(Result); end; function TNamedIniCollection.FindByName(const AName : String): TNamedIniCollectionItem; Var I : Integer; begin I:=IndexOfName(AName); If (I=-1) then Result:=Nil else Result:=GetNamedItem(I); end; function TNamedIniCollection.FindByUserData(UserData: TObject): TNamedIniCollectionItem; Var I : Integer; begin I:=IndexOfUserData(UserData); If (I=-1) then Result:=Nil else Result:=GetNamedItem(I); end; end.