1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201 |
- {
- $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}
- { TThread implementation }
- {$i thread.inc}
- { TPersistent implementation }
- {$i persist.inc }
- { TComponent implementation }
- {$i compon.inc}
- { TBasicAction implementation }
- {$i action.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;
- { 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;
- function InitInheritedComponent(Instance: TComponent; RootAncestor: TClass): Boolean;
- function DoInitClass(ClassType: TClass): Boolean;
- begin
- Result := False;
- if (ClassType <> TComponent) and (ClassType <> RootAncestor) then
- begin
- { Init the parent class first }
- Result := DoInitClass(ClassType.ClassParent);
- { !!!: This would work only on Win32, how should we do this multiplatform?
- Result := InternalReadComponentRes(ClassType.ClassName,
- FindResourceHInstance(FindClassHInstance(ClassType)), Instance)
- or Result;}
- Result := False;
- end;
- end;
- begin
- {!!!: GlobalNameSpace.BeginWrite;
- try}
- if (Instance.ComponentState * [csLoading, csInline]) = [] then
- begin
- BeginGlobalLoading;
- try
- Result := DoInitClass(Instance.ClassType);
- NotifyGlobalLoading;
- finally
- EndGlobalLoading;
- end;
- end else
- Result := DoInitClass(Instance.ClassType);
- {finally
- GlobalNameSpace.EndWrite;
- 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));
- 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
- 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;
- {!!!: GlobalNameSpace.Free;
- GlobalNameSpace := nil;}
- end;
- { TFiler implementation }
- {$i filer.inc}
- { TReader implementation }
- {$i reader.inc}
- { TWriter implementations }
- {$i writer.inc}
- {$i twriter.inc}
- {
- $Log$
- 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
- }
|