123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266 |
- {
- $Id$
- 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.
- **********************************************************************}
- {**********************************************************************
- * Class implementations are in separate files. *
- **********************************************************************}
- var
- ClassList : TThreadlist;
- ClassAliasList : TStringList;
- {
- Include all message strings
- Add a language with IFDEF LANG_NAME
- just befor the final ELSE. This way English will always be the default.
- }
- {$IFDEF LANG_GERMAN}
- {$i constsg.inc}
- {$ELSE}
- {$IFDEF LANG_SPANISH}
- {$i constss.inc}
- {$ELSE}
- {$i constse.inc}
- {$ENDIF}
- {$ENDIF}
- { Utility routines }
- {$i util.inc}
- { TBits implementation }
- {$i bits.inc}
- { All streams implementations: }
- { Tstreams THandleStream TFileStream TResourcseStreams TStringStream }
- { TCustomMemoryStream TMemoryStream }
- {$i streams.inc}
- { TParser implementation}
- {$i parser.inc}
- { TCollection and TCollectionItem implementations }
- {$i collect.inc}
- { TList and TThreadList implementations }
- {$i lists.inc}
- { TStrings and TStringList implementations }
- {$i stringl.inc}
- {$ifndef VER1_0}
- { TThread implementation }
- {$i tthread.inc}
- {$endif}
- { TPersistent implementation }
- {$i persist.inc }
- { TComponent implementation }
- {$i compon.inc}
- { TBasicAction implementation }
- {$i action.inc}
- { TDataModule implementation }
- {$i dm.inc}
- { Class and component registration routines }
- {$I cregist.inc}
- { Interface related stuff }
- {$ifdef HASINTF}
- {$I intf.inc}
- {$endif HASINTF}
- {**********************************************************************
- * Miscellaneous procedures and functions *
- **********************************************************************}
- { Point and rectangle constructors }
- function Point(AX, AY: Integer): TPoint;
- begin
- with Result do
- begin
- X := AX;
- Y := AY;
- end;
- end;
- function SmallPoint(AX, AY: SmallInt): TSmallPoint;
- begin
- with Result do
- begin
- X := AX;
- Y := AY;
- end;
- end;
- function Rect(ALeft, ATop, ARight, ABottom: Integer): TRect;
- begin
- with Result do
- begin
- Left := ALeft;
- Top := ATop;
- Right := ARight;
- Bottom := ABottom;
- end;
- end;
- function Bounds(ALeft, ATop, AWidth, AHeight: Integer): TRect;
- begin
- with Result do
- begin
- Left := ALeft;
- Top := ATop;
- Right := ALeft + AWidth;
- Bottom := ATop + AHeight;
- end;
- end;
- { Object filing routines }
- var
- IntConstList: TThreadList;
- type
- TIntConst = class
- IntegerType: PTypeInfo; // The integer type RTTI pointer
- IdentToIntFn: TIdentToInt; // Identifier to Integer conversion
- IntToIdentFn: TIntToIdent; // Integer to Identifier conversion
- constructor Create(AIntegerType: PTypeInfo; AIdentToInt: TIdentToInt;
- AIntToIdent: TIntToIdent);
- end;
- constructor TIntConst.Create(AIntegerType: PTypeInfo; AIdentToInt: TIdentToInt;
- AIntToIdent: TIntToIdent);
- begin
- IntegerType := AIntegerType;
- IdentToIntFn := AIdentToInt;
- IntToIdentFn := AIntToIdent;
- end;
- procedure RegisterIntegerConsts(IntegerType: Pointer; IdentToIntFn: TIdentToInt;
- IntToIdentFn: TIntToIdent);
- begin
- IntConstList.Add(TIntConst.Create(IntegerType, IdentToIntFn, IntToIdentFn));
- end;
- function FindIntToIdent(AIntegerType: Pointer): TIntToIdent;
- var
- i: Integer;
- begin
- with IntConstList.LockList do
- try
- for i := 0 to Count - 1 do
- if TIntConst(Items[i]).IntegerType = AIntegerType then
- exit(TIntConst(Items[i]).IntToIdentFn);
- Result := nil;
- finally
- IntConstList.UnlockList;
- end;
- end;
- function FindIdentToInt(AIntegerType: Pointer): TIdentToInt;
- var
- i: Integer;
- begin
- with IntConstList.LockList do
- try
- for i := 0 to Count - 1 do
- with TIntConst(Items[I]) do
- if TIntConst(Items[I]).IntegerType = AIntegerType then
- exit(IdentToIntFn);
- Result := nil;
- finally
- IntConstList.UnlockList;
- end;
- end;
- function IdentToInt(const Ident: String; var Int: LongInt;
- const Map: array of TIdentMapEntry): Boolean;
- var
- i: Integer;
- begin
- for i := Low(Map) to High(Map) do
- if CompareText(Map[i].Name, Ident) = 0 then
- begin
- Int := Map[i].Value;
- exit(True);
- end;
- Result := False;
- end;
- function IntToIdent(Int: LongInt; var Ident: String;
- const Map: array of TIdentMapEntry): Boolean;
- var
- i: Integer;
- begin
- for i := Low(Map) to High(Map) do
- if Map[i].Value = Int then
- begin
- Ident := Map[i].Name;
- exit(True);
- end;
- Result := False;
- end;
- function GlobalIdentToInt(const Ident: String; var Int: LongInt):boolean;
- var
- i : Integer;
- begin
- with IntConstList.LockList do
- try
- for i := 0 to Count - 1 do
- if TIntConst(Items[I]).IdentToIntFn(Ident, Int) then
- Exit(True);
- Result := false;
- finally
- IntConstList.UnlockList;
- end;
- end;
- { TPropFixup }
- type
- TPropFixup = class
- FInstance: TPersistent;
- FInstanceRoot: TComponent;
- FPropInfo: PPropInfo;
- FRootName: string;
- FName: string;
- constructor Create(AInstance: TPersistent; AInstanceRoot: TComponent;
- APropInfo: PPropInfo; const ARootName, AName: String);
- function MakeGlobalReference: Boolean;
- end;
- var
- GlobalFixupList: TThreadList;
- constructor TPropFixup.Create(AInstance: TPersistent; AInstanceRoot: TComponent;
- APropInfo: PPropInfo; const ARootName, AName: String);
- begin
- FInstance := AInstance;
- FInstanceRoot := AInstanceRoot;
- FPropInfo := APropInfo;
- FRootName := ARootName;
- FName := AName;
- end;
- function TPropFixup.MakeGlobalReference: Boolean;
- var
- i: Integer;
- s, p: PChar;
- begin
- i := Pos('.', FName);
- if i = 0 then
- exit(False);
- FRootName := Copy(FName, 1, i - 1);
- FName := Copy(FName, i + 1, Length(FName));
- Result := True;
- end;
- Type
- TInitHandler = Class(TObject)
- AHandler : TInitComponentHandler;
- AClass : TComponentClass;
- end;
- Var
- InitHandlerList : TList;
- procedure RegisterInitComponentHandler(ComponentClass: TComponentClass; Handler: TInitComponentHandler);
- Var
- I : Integer;
- H: TInitHandler;
- begin
- If (InitHandlerList=Nil) then
- InitHandlerList:=TList.Create;
- H:=TInitHandler.Create;
- H.Aclass:=ComponentClass;
- H.AHandler:=Handler;
- With InitHandlerList do
- begin
- I:=0;
- While (I<Count) and not H.AClass.InheritsFrom(TInitHandler(Items[i]).AClass) do
- Inc(I);
- InitHandlerList.Insert(I,H);
- end;
- end;
- function InitInheritedComponent(Instance: TComponent; RootAncestor: TClass): Boolean;
- Var
- I : Integer;
- begin
- I:=0;
- Result:=False;
- With InitHandlerList do
- begin
- I:=0;
- // Instance is the normally the lowest one, so that one should be used when searching.
- While Not result and (I<Count) do
- begin
- If (Instance.InheritsFrom(TInitHandler(Items[i]).AClass)) then
- Result:=TInitHandler(Items[i]).AHandler(Instance,RootAncestor);
- Inc(I);
- end;
- end;
- end;
- function InitComponentRes(const ResName: String; Instance: TComponent): Boolean;
- begin
- { !!!: Too Win32-specific }
- InitComponentRes := False;
- end;
- function ReadComponentRes(const ResName: String; Instance: TComponent): TComponent;
- begin
- { !!!: Too Win32-specific }
- ReadComponentRes := nil;
- end;
- function ReadComponentResEx(HInstance: THandle; const ResName: String): TComponent;
- begin
- { !!!: Too Win32-specific in VCL }
- ReadComponentResEx := nil;
- end;
- function ReadComponentResFile(const FileName: String; Instance: TComponent): TComponent;
- var
- FileStream: TStream;
- begin
- FileStream := TFileStream.Create(FileName, fmOpenRead {!!!:or fmShareDenyWrite});
- try
- Result := FileStream.ReadComponentRes(Instance);
- finally
- FileStream.Free;
- end;
- end;
- procedure WriteComponentResFile(const FileName: String; Instance: TComponent);
- var
- FileStream: TStream;
- begin
- FileStream := TFileStream.Create(FileName, fmCreate);
- try
- FileStream.WriteComponentRes(Instance.ClassName, Instance);
- finally
- FileStream.Free;
- end;
- end;
- procedure GlobalFixupReferences;
- var
- GlobalList, DoneList, ToDoList: TList;
- I, Index: Integer;
- Root: TComponent;
- Instance: TPersistent;
- Reference: Pointer;
- begin
- if not Assigned(FindGlobalComponent) then
- exit;
- {!!!: GlobalNameSpace.BeginWrite;
- try}
- GlobalList := GlobalFixupList.LockList;
- try
- if GlobalList.Count > 0 then
- begin
- ToDoList := nil;
- DoneList := TList.Create;
- ToDoList := TList.Create;
- try
- i := 0;
- while i < GlobalList.Count do
- with TPropFixup(GlobalList[i]) do
- begin
- Root := FindGlobalComponent(FRootName);
- if Assigned(Root) or (GetOrdProp(FInstance, FPropInfo) <> 0) then
- begin
- if Assigned(Root) then
- begin
- Reference := FindNestedComponent(Root, FName);
- SetOrdProp(FInstance, FPropInfo, Longint(Reference));
- end;
- // Move component to list of done components, if necessary
- if (DoneList.IndexOf(FInstance) < 0) and
- (ToDoList.IndexOf(FInstance) >= 0) then
- DoneList.Add(FInstance);
- GlobalList.Delete(i);
- Free; // ...the fixup
- end else
- begin
- // Move component to list of components to process, if necessary
- Index := DoneList.IndexOf(FInstance);
- if Index <> -1 then
- DoneList.Delete(Index);
- if ToDoList.IndexOf(FInstance) < 0 then
- ToDoList.Add(FInstance);
- Inc(i);
- end;
- end;
- for i := 0 to DoneList.Count - 1 do
- begin
- Instance := TPersistent(DoneList[I]);
- if Instance.InheritsFrom(TComponent) then
- Exclude(TComponent(Instance).FComponentState, csFixups);
- end;
- finally
- ToDoList.Free;
- DoneList.Free;
- end;
- end;
- finally
- GlobalFixupList.UnlockList;
- end;
- {finally
- GlobalNameSpace.EndWrite;
- end;}
- end;
- function IsStringInList(const AString: String; AList: TStrings): Boolean;
- var
- i: Integer;
- begin
- for i := 0 to AList.Count - 1 do
- if CompareText(AList[i], AString) = 0 then
- exit(True);
- Result := False;
- end;
- procedure GetFixupReferenceNames(Root: TComponent; Names: TStrings);
- var
- i: Integer;
- CurFixup: TPropFixup;
- begin
- with GlobalFixupList.LockList do
- try
- for i := 0 to Count - 1 do
- begin
- CurFixup := TPropFixup(Items[i]);
- if ((not Assigned(Root)) or (CurFixup.FInstanceRoot = Root)) and
- not IsStringInList(CurFixup.FRootName, Names) then
- Names.Add(CurFixup.FRootName);
- end;
- finally
- GlobalFixupList.UnlockList;
- end;
- end;
- procedure GetFixupInstanceNames(Root: TComponent;
- const ReferenceRootName: string; Names: TStrings);
- var
- i: Integer;
- CurFixup: TPropFixup;
- begin
- with GlobalFixupList.LockList do
- try
- for i := 0 to Count - 1 do
- begin
- CurFixup := TPropFixup(Items[i]);
- if (CurFixup.FInstanceRoot = Root) and
- (UpperCase(ReferenceRootName) = UpperCase(CurFixup.FRootName)) and
- not IsStringInList(CurFixup.FName, Names) then
- Names.Add(CurFixup.FName);
- end;
- finally
- GlobalFixupList.UnlockList;
- end;
- end;
- procedure RedirectFixupReferences(Root: TComponent; const OldRootName,
- NewRootName: string);
- var
- i: Integer;
- CurFixup: TPropFixup;
- begin
- with GlobalFixupList.LockList do
- try
- for i := 0 to Count - 1 do
- begin
- CurFixup := TPropFixup(Items[i]);
- if ((not Assigned(Root)) or (CurFixup.FInstanceRoot = Root)) and
- (UpperCase(OldRootName) = UpperCase(CurFixup.FRootName)) then
- CurFixup.FRootName := NewRootName;
- end;
- GlobalFixupReferences;
- finally
- GlobalFixupList.Unlocklist;
- end;
- end;
- procedure RemoveFixupReferences(Root: TComponent; const RootName: string);
- var
- i: Integer;
- CurFixup: TPropFixup;
- begin
- if not Assigned(GlobalFixupList) then
- exit;
- with GlobalFixupList.LockList do
- try
- for i := Count - 1 downto 0 do
- begin
- CurFixup := TPropFixup(Items[i]);
- if ((not Assigned(Root)) or (CurFixup.FInstanceRoot = Root)) and
- ((Length(RootName) = 0) or
- (UpperCase(RootName) = UpperCase(CurFixup.FRootName))) then
- begin
- Delete(i);
- CurFixup.Free;
- end;
- end;
- finally
- GlobalFixupList.UnlockList;
- end;
- end;
- procedure RemoveFixups(Instance: TPersistent);
- var
- i: Integer;
- CurFixup: TPropFixup;
- begin
- if not Assigned(GlobalFixupList) then
- exit;
- with GlobalFixupList.LockList do
- try
- for i := Count - 1 downto 0 do
- begin
- CurFixup := TPropFixup(Items[i]);
- if (CurFixup.FInstance = Instance) then
- begin
- Delete(i);
- CurFixup.Free;
- end;
- end;
- finally
- GlobalFixupList.UnlockList;
- end;
- end;
- function FindNestedComponent(Root: TComponent; const NamePath: string): TComponent;
- var
- Current, Found: TComponent;
- s, p: PChar;
- Name: String;
- begin
- Result := nil;
- if Length(NamePath) > 0 then
- begin
- Current := Root;
- p := PChar(NamePath);
- while p[0] <> #0 do
- begin
- s := p;
- while not (p^ in ['.', '-', #0]) do
- Inc(p);
- SetString(Name, s, p - s);
- Found := Current.FindComponent(Name);
- if (not Assigned(Found)) and (UpperCase(Name) = 'OWNER') then
- Found := Current;
- if not Assigned(Found) then exit;
- // Remove the dereference operator from the name
- if p[0] = '.' then
- Inc(P);
- if p[0] = '-' then
- Inc(P);
- if p[0] = '>' then
- Inc(P);
- Current := Found;
- end;
- end;
- Result := Current;
- end;
- {!!!: Should be threadvar - doesn't work for all platforms yet!}
- var
- GlobalLoaded, GlobalLists: TList;
- procedure BeginGlobalLoading;
- begin
- if not Assigned(GlobalLists) then
- GlobalLists := TList.Create;
- GlobalLists.Add(GlobalLoaded);
- GlobalLoaded := TList.Create;
- end;
- { Notify all global components that they have been loaded completely }
- procedure NotifyGlobalLoading;
- var
- i: Integer;
- begin
- for i := 0 to GlobalLoaded.Count - 1 do
- TComponent(GlobalLoaded[i]).Loaded;
- end;
- procedure EndGlobalLoading;
- begin
- { Free the memory occupied by BeginGlobalLoading }
- GlobalLoaded.Free;
- GlobalLoaded := TList(GlobalLists.Last);
- GlobalLists.Delete(GlobalLists.Count - 1);
- if GlobalLists.Count = 0 then
- begin
- GlobalLists.Free;
- GlobalLists := nil;
- end;
- end;
- function CollectionsEqual(C1, C2: TCollection): Boolean;
- begin
- // !!!: Implement this
- CollectionsEqual:=false;
- end;
- { Object conversion routines }
- procedure ObjectBinaryToText(Input, Output: TStream);
- procedure OutStr(s: String);
- begin
- if Length(s) > 0 then
- Output.Write(s[1], Length(s));
- end;
- procedure OutLn(s: String);
- begin
- OutStr(s + #10);
- end;
- procedure OutString(s: String);
- var
- res, NewStr: String;
- i: Integer;
- InString, NewInString: Boolean;
- begin
- res := '';
- InString := False;
- for i := 1 to Length(s) do begin
- NewInString := InString;
- case s[i] of
- #0..#31: begin
- if InString then
- NewInString := False;
- NewStr := '#' + IntToStr(Ord(s[i]));
- end;
- '''':
- if InString then NewStr := ''''''
- else NewStr := '''''''';
- else begin
- if not InString then
- NewInString := True;
- NewStr := s[i];
- end;
- end;
- if NewInString <> InString then begin
- NewStr := '''' + NewStr;
- InString := NewInString;
- end;
- res := res + NewStr;
- end;
- if InString then res := res + '''';
- OutStr(res);
- end;
- function ReadInt(ValueType: TValueType): LongInt;
- begin
- case ValueType of
- vaInt8: Result := ShortInt(Input.ReadByte);
- vaInt16: Result := SmallInt(Input.ReadWord);
- vaInt32: Result := LongInt(Input.ReadDWord);
- end;
- end;
- function ReadInt: LongInt;
- begin
- Result := ReadInt(TValueType(Input.ReadByte));
- end;
- function ReadSStr: String;
- var
- len: Byte;
- begin
- len := Input.ReadByte;
- SetLength(Result, len);
- Input.Read(Result[1], len);
- end;
- procedure ReadPropList(indent: String);
- procedure ProcessValue(ValueType: TValueType; Indent: String);
- procedure Stop(s: String);
- begin
- WriteLn(s);
- Halt;
- end;
- procedure ProcessBinary;
- var
- ToDo, DoNow, i: LongInt;
- lbuf: array[0..31] of Byte;
- s: String;
- begin
- ToDo := Input.ReadDWord;
- OutLn('{');
- while ToDo > 0 do begin
- DoNow := ToDo;
- if DoNow > 32 then DoNow := 32;
- Dec(ToDo, DoNow);
- s := Indent + ' ';
- Input.Read(lbuf, DoNow);
- for i := 0 to DoNow - 1 do
- s := s + IntToHex(lbuf[i], 2);
- OutLn(s);
- end;
- OutLn(indent + '}');
- end;
- var
- s: String;
- len: LongInt;
- IsFirst: Boolean;
- ext: Extended;
- begin
- case ValueType of
- vaList: begin
- OutStr('(');
- IsFirst := True;
- while True do begin
- ValueType := TValueType(Input.ReadByte);
- if ValueType = vaNull then break;
- if IsFirst then begin
- OutLn('');
- IsFirst := False;
- end;
- OutStr(Indent + ' ');
- ProcessValue(ValueType, Indent + ' ');
- end;
- OutLn(Indent + ')');
- end;
- vaInt8: OutLn(IntToStr(ShortInt(Input.ReadByte)));
- vaInt16: OutLn( IntToStr(SmallInt(Input.ReadWord)));
- vaInt32: OutLn(IntToStr(LongInt(Input.ReadDWord)));
- vaExtended: begin
- Input.Read(ext, SizeOf(ext));
- OutLn(FloatToStr(ext));
- end;
- vaString: begin
- OutString(ReadSStr);
- OutLn('');
- end;
- vaIdent: OutLn(ReadSStr);
- vaFalse: OutLn('False');
- vaTrue: OutLn('True');
- vaBinary: ProcessBinary;
- vaSet: begin
- OutStr('[');
- IsFirst := True;
- while True do begin
- s := ReadSStr;
- if Length(s) = 0 then break;
- if not IsFirst then OutStr(', ');
- IsFirst := False;
- OutStr(s);
- end;
- OutLn(']');
- end;
- vaLString:
- Stop('!!LString!!');
- vaNil:
- OutLn('nil');
- vaCollection: begin
- OutStr('<');
- while Input.ReadByte <> 0 do begin
- OutLn(Indent);
- Input.Seek(-1, soFromCurrent);
- OutStr(indent + ' item');
- ValueType := TValueType(Input.ReadByte);
- if ValueType <> vaList then
- OutStr('[' + IntToStr(ReadInt(ValueType)) + ']');
- OutLn('');
- ReadPropList(indent + ' ');
- OutStr(indent + ' end');
- end;
- OutLn('>');
- end;
- {vaSingle: begin OutLn('!!Single!!'); exit end;
- vaCurrency: begin OutLn('!!Currency!!'); exit end;
- vaDate: begin OutLn('!!Date!!'); exit end;
- vaWString: begin OutLn('!!WString!!'); exit end;}
- else
- Stop(IntToStr(Ord(ValueType)));
- end;
- end;
- begin
- while Input.ReadByte <> 0 do begin
- Input.Seek(-1, soFromCurrent);
- OutStr(indent + ReadSStr + ' = ');
- ProcessValue(TValueType(Input.ReadByte), Indent);
- end;
- end;
- procedure ReadObject(indent: String);
- var
- b: Byte;
- ObjClassName, ObjName: String;
- ChildPos: LongInt;
- begin
- // Check for FilerFlags
- b := Input.ReadByte;
- if (b and $f0) = $f0 then begin
- if (b and 2) <> 0 then ChildPos := ReadInt;
- end else begin
- b := 0;
- Input.Seek(-1, soFromCurrent);
- end;
- ObjClassName := ReadSStr;
- ObjName := ReadSStr;
- OutStr(Indent);
- if (b and 1) <> 0 then OutStr('inherited')
- else OutStr('object');
- OutStr(' ');
- if ObjName <> '' then
- OutStr(ObjName + ': ');
- OutStr(ObjClassName);
- if (b and 2) <> 0 then OutStr('[' + IntToStr(ChildPos) + ']');
- OutLn('');
- ReadPropList(indent + ' ');
- while Input.ReadByte <> 0 do begin
- Input.Seek(-1, soFromCurrent);
- ReadObject(indent + ' ');
- end;
- OutLn(indent + 'end');
- end;
- type
- PLongWord = ^LongWord;
- const
- signature: PChar = 'TPF0';
- begin
- if Input.ReadDWord <> PLongWord(Pointer(signature))^ then
- raise EReadError.Create('Illegal stream image' {###SInvalidImage});
- ReadObject('');
- end;
- procedure ObjectTextToBinary(Input, Output: TStream);
- var
- parser: TParser;
- procedure WriteString(s: String);
- begin
- Output.WriteByte(Length(s));
- if Length(s) > 0 then
- Output.Write(s[1], Length(s));
- end;
- procedure WriteInteger(value: LongInt);
- begin
- if (value >= -128) and (value <= 127) then begin
- Output.WriteByte(Ord(vaInt8));
- Output.WriteByte(Byte(value));
- end else if (value >= -32768) and (value <= 32767) then begin
- Output.WriteByte(Ord(vaInt16));
- Output.WriteWord(Word(value));
- end else begin
- Output.WriteByte(ord(vaInt32));
- Output.WriteDWord(LongWord(value));
- end;
- end;
- procedure ProcessProperty; forward;
- procedure ProcessValue;
- var
- flt: Extended;
- s: String;
- stream: TMemoryStream;
- begin
- case parser.Token of
- toInteger:
- begin
- WriteInteger(parser.TokenInt);
- parser.NextToken;
- end;
- toFloat:
- begin
- Output.WriteByte(Ord(vaExtended));
- flt := Parser.TokenFloat;
- Output.Write(flt, SizeOf(flt));
- parser.NextToken;
- end;
- toString:
- begin
- s := parser.TokenString;
- while parser.NextToken = '+' do
- begin
- parser.NextToken; // Get next string fragment
- parser.CheckToken(toString);
- s := s + parser.TokenString;
- end;
- Output.WriteByte(Ord(vaString));
- WriteString(s);
- end;
- toSymbol:
- begin
- if CompareText(parser.TokenString, 'True') = 0 then
- Output.WriteByte(Ord(vaTrue))
- else if CompareText(parser.TokenString, 'False') = 0 then
- Output.WriteByte(Ord(vaFalse))
- else if CompareText(parser.TokenString, 'nil') = 0 then
- Output.WriteByte(Ord(vaNil))
- else
- begin
- Output.WriteByte(Ord(vaIdent));
- WriteString(parser.TokenComponentIdent);
- end;
- Parser.NextToken;
- end;
- // Set
- '[':
- begin
- parser.NextToken;
- Output.WriteByte(Ord(vaSet));
- if parser.Token <> ']' then
- while True do
- begin
- parser.CheckToken(toSymbol);
- WriteString(parser.TokenString);
- parser.NextToken;
- if parser.Token = ']' then
- break;
- parser.CheckToken(',');
- parser.NextToken;
- end;
- Output.WriteByte(0);
- parser.NextToken;
- end;
- // List
- '(':
- begin
- parser.NextToken;
- Output.WriteByte(Ord(vaList));
- while parser.Token <> ')' do
- ProcessValue;
- Output.WriteByte(0);
- parser.NextToken;
- end;
- // Collection
- '<':
- begin
- parser.NextToken;
- Output.WriteByte(Ord(vaCollection));
- while parser.Token <> '>' do
- begin
- parser.CheckTokenSymbol('item');
- parser.NextToken;
- // ConvertOrder
- Output.WriteByte(Ord(vaList));
- while not parser.TokenSymbolIs('end') do
- ProcessProperty;
- parser.NextToken; // Skip 'end'
- Output.WriteByte(0);
- end;
- Output.WriteByte(0);
- parser.NextToken;
- end;
- // Binary data
- '{':
- begin
- Output.WriteByte(Ord(vaBinary));
- stream := TMemoryStream.Create;
- try
- parser.HexToBinary(stream);
- Output.WriteDWord(stream.Size);
- Output.Write(Stream.Memory^, stream.Size);
- finally
- stream.Free;
- end;
- parser.NextToken;
- end;
- else
- parser.Error(SInvalidProperty);
- end;
- end;
- procedure ProcessProperty;
- var
- name: String;
- begin
- // Get name of property
- parser.CheckToken(toSymbol);
- name := parser.TokenString;
- while True do begin
- parser.NextToken;
- if parser.Token <> '.' then break;
- parser.NextToken;
- parser.CheckToken(toSymbol);
- name := name + '.' + parser.TokenString;
- end;
- WriteString(name);
- parser.CheckToken('=');
- parser.NextToken;
- ProcessValue;
- end;
- procedure ProcessObject;
- var
- IsInherited: Boolean;
- ObjectName, ObjectType: String;
- begin
- if parser.TokenSymbolIs('OBJECT') then
- IsInherited := False
- else begin
- parser.CheckTokenSymbol('INHERITED');
- IsInherited := True;
- end;
- parser.NextToken;
- parser.CheckToken(toSymbol);
- ObjectName := '';
- ObjectType := parser.TokenString;
- parser.NextToken;
- if parser.Token = ':' then begin
- parser.NextToken;
- parser.CheckToken(toSymbol);
- ObjectName := ObjectType;
- ObjectType := parser.TokenString;
- parser.NextToken;
- end;
- WriteString(ObjectType);
- WriteString(ObjectName);
- // Convert property list
- while not (parser.TokenSymbolIs('END') or
- parser.TokenSymbolIs('OBJECT') or
- parser.TokenSymbolIs('INHERITED')) do
- ProcessProperty;
- Output.WriteByte(0); // Terminate property list
- // Convert child objects
- while not parser.TokenSymbolIs('END') do ProcessObject;
- parser.NextToken; // Skip end token
- Output.WriteByte(0); // Terminate property list
- end;
- const
- signature: PChar = 'TPF0';
- begin
- parser := TParser.Create(Input);
- try
- Output.Write(signature[0], 4);
- ProcessObject;
- finally
- parser.Free;
- end;
- end;
- procedure ObjectResourceToText(Input, Output: TStream);
- begin
- Input.ReadResHeader;
- ObjectBinaryToText(Input, Output);
- end;
- procedure ObjectTextToResource(Input, Output: TStream);
- var
- StartPos, SizeStartPos, BinSize: LongInt;
- parser: TParser;
- name: String;
- begin
- // Get form type name
- StartPos := Input.Position;
- parser := TParser.Create(Input);
- try
- if not parser.TokenSymbolIs('OBJECT') then parser.CheckTokenSymbol('INHERITED');
- parser.NextToken;
- parser.CheckToken(toSymbol);
- parser.NextToken;
- parser.CheckToken(':');
- parser.NextToken;
- parser.CheckToken(toSymbol);
- name := parser.TokenString;
- finally
- parser.Free;
- Input.Position := StartPos;
- end;
- // Write resource header
- name := UpperCase(name);
- Output.WriteByte($ff);
- Output.WriteByte(10);
- Output.WriteByte(0);
- Output.Write(name[1], Length(name) + 1); // Write null-terminated form type name
- Output.WriteWord($1030);
- SizeStartPos := Output.Position;
- Output.WriteDWord(0); // Placeholder for data size
- ObjectTextToBinary(Input, Output); // Convert the stuff!
- BinSize := Output.Position - SizeStartPos - 4;
- Output.Position := SizeStartPos;
- Output.WriteDWord(BinSize); // Insert real resource data size
- end;
- { Utility routines }
- function LineStart(Buffer, BufPos: PChar): PChar;
- begin
- Result := BufPos;
- while Result > Buffer do begin
- Dec(Result);
- if Result[0] = #10 then break;
- end;
- end;
- procedure CommonInit;
- begin
- InitHandlerList:=Nil;
- IntConstList := TThreadList.Create;
- GlobalFixupList := TThreadList.Create;
- ClassList := TThreadList.Create;
- ClassAliasList := TStringList.Create;
- end;
- procedure CommonCleanup;
- var
- i: Integer;
- begin
- // !!!: GlobalNameSpace.BeginWrite;
- with IntConstList.LockList do
- try
- for i := 0 to Count - 1 do
- TIntConst(Items[I]).Free;
- finally
- IntConstList.UnlockList;
- end;
- IntConstList.Free;
- ClassList.Free;
- ClassAliasList.Free;
- RemoveFixupReferences(nil, '');
- GlobalFixupList.Free;
- GlobalFixupList := nil;
- GlobalLists.Free;
- ComponentPages.Free;
- {!!!: GlobalNameSpace.Free;
- GlobalNameSpace := nil;}
- InitHandlerList.Free;
- InitHandlerList:=Nil;
- end;
- { TFiler implementation }
- {$i filer.inc}
- { TReader implementation }
- {$i reader.inc}
- { TWriter implementations }
- {$i writer.inc}
- {$i twriter.inc}
- {
- $Log$
- Revision 1.2 2003-12-15 08:57:24 michael
- Patch from Darek Mazur for reading idents from property stream
- Revision 1.3 2003/12/15 08:55:56 michael
- Patch from Darek Mazur for reading idents from property stream
- Revision 1.2 2003/11/19 15:51:54 peter
- * tthread disabled for 1.0.x
- Revision 1.1 2003/10/06 21:01:06 peter
- * moved classes unit to rtl
- Revision 1.14 2003/06/04 17:40:44 michael
- + Minor fix by Mattias Gaertner
- Revision 1.13 2003/06/04 15:27:24 michael
- + TDataModule en InitInheritedComponent erbij voor Delphi 6 compatibility
- Revision 1.12 2003/04/19 14:29:25 michael
- + Fix from Mattias Gaertner, closes memory leak
- Revision 1.11 2002/12/02 12:04:07 sg
- * Fixed handling of zero-length strings (classes.inc: When converting
- empty strings from text forms to binary forms; reader.inc: When reading
- an empty string from a binary serialization)
- Revision 1.10 2002/09/07 15:15:24 peter
- * old logs removed and tabs fixed
- Revision 1.9 2002/07/16 13:32:51 florian
- + skeleton for TInterfaceList added
- Revision 1.8 2002/01/06 21:54:49 peter
- * action classes added
- }
|