home *** CD-ROM | disk | FTP | other *** search
-
- {*******************************************************}
- { }
- { Delphi Visual Component Library }
- { }
- { Copyright (c) 1995,96 Borland International }
- { }
- {*******************************************************}
-
- unit Classes;
-
- {$R-}
-
- interface
-
- uses SysUtils, Windows;
-
- const
-
- { Maximum TList size }
-
- MaxListSize = Maxint div 16;
-
- { TStream seek origins }
-
- soFromBeginning = 0;
- soFromCurrent = 1;
- soFromEnd = 2;
-
- { TFileStream create mode }
-
- fmCreate = $FFFF;
-
- { TParser special tokens }
-
- toEOF = Char(0);
- toSymbol = Char(1);
- toString = Char(2);
- toInteger = Char(3);
- toFloat = Char(4);
-
- type
-
- { Text alignment types }
-
- TAlignment = (taLeftJustify, taRightJustify, taCenter);
- TLeftRight = taLeftJustify..taRightJustify;
-
- { Types used by standard events }
-
- TShiftState = set of (ssShift, ssAlt, ssCtrl,
- ssLeft, ssRight, ssMiddle, ssDouble);
-
- THelpContext = -MaxLongint..MaxLongint;
-
- { Standard events }
-
- TNotifyEvent = procedure(Sender: TObject) of object;
- THelpEvent = function (Command: Word; Data: Longint;
- var CallHelp: Boolean): Boolean of object;
- TGetStrProc = procedure(const S: string) of object;
-
- { Exception classes }
-
- EStreamError = class(Exception);
- EFCreateError = class(EStreamError);
- EFOpenError = class(EStreamError);
- EFilerError = class(EStreamError);
- EReadError = class(EFilerError);
- EWriteError = class(EFilerError);
- EClassNotFound = class(EFilerError);
- EMethodNotFound = class(EFilerError);
- EInvalidImage = class(EFilerError);
- EResNotFound = class(Exception);
- EListError = class(Exception);
- EBitsError = class(Exception);
- EStringListError = class(Exception);
- EComponentError = class(Exception);
- EParserError = class(Exception);
-
- { Forward class declarations }
-
- TStream = class;
- TFiler = class;
- TReader = class;
- TWriter = class;
- TComponent = class;
-
- { TList class }
-
- PPointerList = ^TPointerList;
- TPointerList = array[0..MaxListSize - 1] of Pointer;
- TListSortCompare = function (Item1, Item2: Pointer): Integer;
-
- TList = class(TObject)
- private
- FList: PPointerList;
- FCount: Integer;
- FCapacity: Integer;
- protected
- procedure Error; virtual;
- function Get(Index: Integer): Pointer;
- procedure Grow; virtual;
- procedure Put(Index: Integer; Item: Pointer);
- procedure SetCapacity(NewCapacity: Integer);
- procedure SetCount(NewCount: Integer);
- public
- destructor Destroy; override;
- function Add(Item: Pointer): Integer;
- procedure Clear;
- procedure Delete(Index: Integer);
- procedure Exchange(Index1, Index2: Integer);
- function Expand: TList;
- function First: Pointer;
- function IndexOf(Item: Pointer): Integer;
- procedure Insert(Index: Integer; Item: Pointer);
- function Last: Pointer;
- procedure Move(CurIndex, NewIndex: Integer);
- function Remove(Item: Pointer): Integer;
- procedure Pack;
- procedure Sort(Compare: TListSortCompare);
- property Capacity: Integer read FCapacity write SetCapacity;
- property Count: Integer read FCount write SetCount;
- property Items[Index: Integer]: Pointer read Get write Put; default;
- property List: PPointerList read FList;
- end;
-
- { TBits class }
-
- TBits = class
- private
- FSize: Integer;
- FBits: Pointer;
- procedure Error;
- procedure SetSize(Value: Integer);
- procedure SetBit(Index: Integer; Value: Boolean);
- function GetBit(Index: Integer): Boolean;
- public
- destructor Destroy; override;
- function OpenBit: Integer;
- property Bits[Index: Integer]: Boolean read GetBit write SetBit; default;
- property Size: Integer read FSize write SetSize;
- end;
-
- { TPersistent abstract class }
-
- {$M+}
-
- TPersistent = class(TObject)
- private
- procedure AssignError(Source: TPersistent);
- protected
- procedure AssignTo(Dest: TPersistent); virtual;
- procedure DefineProperties(Filer: TFiler); virtual;
- public
- procedure Assign(Source: TPersistent); virtual;
- end;
-
- {$M-}
-
- { TPersistent class reference type }
-
- TPersistentClass = class of TPersistent;
-
- { TCollection class }
-
- TCollection = class;
-
- TCollectionItem = class(TPersistent)
- private
- FCollection: TCollection;
- function GetIndex: Integer;
- procedure SetCollection(Value: TCollection);
- protected
- procedure Changed(AllItems: Boolean);
- procedure SetIndex(Value: Integer); virtual;
- public
- constructor Create(Collection: TCollection); virtual;
- destructor Destroy; override;
- property Collection: TCollection read FCollection write SetCollection;
- property Index: Integer read GetIndex write SetIndex;
- end;
-
- TCollectionItemClass = class of TCollectionItem;
-
- TCollection = class(TPersistent)
- private
- FItemClass: TCollectionItemClass;
- FItems: TList;
- FUpdateCount: Integer;
- function GetCount: Integer;
- procedure InsertItem(Item: TCollectionItem);
- procedure RemoveItem(Item: TCollectionItem);
- protected
- procedure Changed;
- function GetItem(Index: Integer): TCollectionItem;
- procedure SetItem(Index: Integer; Value: TCollectionItem);
- procedure Update(Item: TCollectionItem); virtual;
- public
- constructor Create(ItemClass: TCollectionItemClass);
- destructor Destroy; override;
- function Add: TCollectionItem;
- procedure Assign(Source: TPersistent); override;
- procedure BeginUpdate;
- procedure Clear;
- procedure EndUpdate;
- property Count: Integer read GetCount;
- property Items[Index: Integer]: TCollectionItem read GetItem write SetItem;
- end;
-
- { TStrings class }
-
- TStrings = class(TPersistent)
- private
- FUpdateCount: Integer;
- function GetCommaText: string;
- function GetName(Index: Integer): string;
- function GetValue(const Name: string): string;
- procedure ReadData(Reader: TReader);
- procedure SetCommaText(const Value: string);
- procedure SetValue(const Name, Value: string);
- procedure WriteData(Writer: TWriter);
- protected
- procedure DefineProperties(Filer: TFiler); override;
- function Get(Index: Integer): string; virtual; abstract;
- function GetCount: Integer; virtual; abstract;
- function GetObject(Index: Integer): TObject; virtual;
- function GetTextStr: string; virtual;
- procedure Put(Index: Integer; const S: string); virtual;
- procedure PutObject(Index: Integer; AObject: TObject); virtual;
- procedure SetTextStr(const Value: string); virtual;
- procedure SetUpdateState(Updating: Boolean); virtual;
- public
- function Add(const S: string): Integer; virtual;
- function AddObject(const S: string; AObject: TObject): Integer; virtual;
- procedure Append(const S: string);
- procedure AddStrings(Strings: TStrings); virtual;
- procedure Assign(Source: TPersistent); override;
- procedure BeginUpdate;
- procedure Clear; virtual; abstract;
- procedure Delete(Index: Integer); virtual; abstract;
- procedure EndUpdate;
- function Equals(Strings: TStrings): Boolean;
- procedure Exchange(Index1, Index2: Integer); virtual;
- function GetText: PChar; virtual;
- function IndexOf(const S: string): Integer; virtual;
- function IndexOfName(const Name: string): Integer;
- function IndexOfObject(AObject: TObject): Integer;
- procedure Insert(Index: Integer; const S: string); virtual; abstract;
- procedure InsertObject(Index: Integer; const S: string;
- AObject: TObject);
- procedure LoadFromFile(const FileName: string); virtual;
- procedure LoadFromStream(Stream: TStream); virtual;
- procedure Move(CurIndex, NewIndex: Integer); virtual;
- procedure SaveToFile(const FileName: string); virtual;
- procedure SaveToStream(Stream: TStream); virtual;
- procedure SetText(Text: PChar); virtual;
- property CommaText: string read GetCommaText write SetCommaText;
- property Count: Integer read GetCount;
- property Names[Index: Integer]: string read GetName;
- property Objects[Index: Integer]: TObject read GetObject write PutObject;
- property Values[const Name: string]: string read GetValue write SetValue;
- property Strings[Index: Integer]: string read Get write Put; default;
- property Text: string read GetTextStr write SetTextStr;
- end;
-
- { TStringList class }
-
- TDuplicates = (dupIgnore, dupAccept, dupError);
-
- PStringItem = ^TStringItem;
- TStringItem = record
- FString: string;
- FObject: TObject;
- end;
-
- PStringItemList = ^TStringItemList;
- TStringItemList = array[0..MaxListSize] of TStringItem;
-
- TStringList = class(TStrings)
- private
- FList: PStringItemList;
- FCount: Integer;
- FCapacity: Integer;
- FSorted: Boolean;
- FDuplicates: TDuplicates;
- FOnChange: TNotifyEvent;
- FOnChanging: TNotifyEvent;
- procedure ExchangeItems(Index1, Index2: Integer);
- procedure Grow;
- procedure QuickSort(L, R: Integer);
- procedure InsertItem(Index: Integer; const S: string);
- procedure SetCapacity(NewCapacity: Integer);
- procedure SetSorted(Value: Boolean);
- protected
- procedure Changed; virtual;
- procedure Changing; virtual;
- function Get(Index: Integer): string; override;
- function GetCount: Integer; override;
- function GetObject(Index: Integer): TObject; override;
- procedure Put(Index: Integer; const S: string); override;
- procedure PutObject(Index: Integer; AObject: TObject); override;
- procedure SetUpdateState(Updating: Boolean); override;
- public
- destructor Destroy; override;
- function Add(const S: string): Integer; override;
- procedure Clear; override;
- procedure Delete(Index: Integer); override;
- procedure Exchange(Index1, Index2: Integer); override;
- function Find(const S: string; var Index: Integer): Boolean; virtual;
- function IndexOf(const S: string): Integer; override;
- procedure Insert(Index: Integer; const S: string); override;
- procedure Sort; virtual;
- property Duplicates: TDuplicates read FDuplicates write FDuplicates;
- property Sorted: Boolean read FSorted write SetSorted;
- property OnChange: TNotifyEvent read FOnChange write FOnChange;
- property OnChanging: TNotifyEvent read FOnChanging write FOnChanging;
- end;
-
- { TStream abstract class }
-
- TStream = class(TObject)
- private
- function GetPosition: Longint;
- procedure SetPosition(Pos: Longint);
- function GetSize: Longint;
- public
- function Read(var Buffer; Count: Longint): Longint; virtual; abstract;
- function Write(const Buffer; Count: Longint): Longint; virtual; abstract;
- function Seek(Offset: Longint; Origin: Word): Longint; virtual; abstract;
- procedure ReadBuffer(var Buffer; Count: Longint);
- procedure WriteBuffer(const Buffer; Count: Longint);
- function CopyFrom(Source: TStream; Count: Longint): Longint;
- function ReadComponent(Instance: TComponent): TComponent;
- function ReadComponentRes(Instance: TComponent): TComponent;
- procedure WriteComponent(Instance: TComponent);
- procedure WriteComponentRes(const ResName: string; Instance: TComponent);
- procedure WriteDescendent(Instance, Ancestor: TComponent);
- procedure WriteDescendentRes(const ResName: string; Instance, Ancestor: TComponent);
- procedure ReadResHeader;
- property Position: Longint read GetPosition write SetPosition;
- property Size: Longint read GetSize;
- end;
-
- { THandleStream class }
-
- THandleStream = class(TStream)
- private
- FHandle: Integer;
- public
- constructor Create(AHandle: Integer);
- function Read(var Buffer; Count: Longint): Longint; override;
- function Write(const Buffer; Count: Longint): Longint; override;
- function Seek(Offset: Longint; Origin: Word): Longint; override;
- property Handle: Integer read FHandle;
- end;
-
- { TFileStream class }
-
- TFileStream = class(THandleStream)
- public
- constructor Create(const FileName: string; Mode: Word);
- destructor Destroy; override;
- end;
-
- { TCustomMemoryStream abstract class }
-
- TCustomMemoryStream = class(TStream)
- private
- FMemory: Pointer;
- FSize, FPosition: Longint;
- protected
- procedure SetPointer(Ptr: Pointer; Size: Longint);
- public
- function Read(var Buffer; Count: Longint): Longint; override;
- function Seek(Offset: Longint; Origin: Word): Longint; override;
- procedure SaveToStream(Stream: TStream);
- procedure SaveToFile(const FileName: string);
- property Memory: Pointer read FMemory;
- end;
-
- { TMemoryStream }
-
- TMemoryStream = class(TCustomMemoryStream)
- private
- FCapacity: Longint;
- procedure SetCapacity(NewCapacity: Longint);
- protected
- function Realloc(var NewCapacity: Longint): Pointer; virtual;
- property Capacity: Longint read FCapacity write SetCapacity;
- public
- destructor Destroy; override;
- procedure Clear;
- procedure LoadFromStream(Stream: TStream);
- procedure LoadFromFile(const FileName: string);
- procedure SetSize(NewSize: Longint);
- function Write(const Buffer; Count: Longint): Longint; override;
- end;
-
- { TResourceStream }
-
- TResourceStream = class(TCustomMemoryStream)
- private
- HResInfo: HRSRC;
- HGlobal: THandle;
- procedure Initialize(Instance: THandle; Name, ResType: PChar);
- public
- constructor Create(Instance: THandle; const ResName: string; ResType: PChar);
- constructor CreateFromID(Instance: THandle; ResID: Integer; ResType: PChar);
- destructor Destroy; override;
- function Write(const Buffer; Count: Longint): Longint; override;
- end;
-
- { TFiler }
-
- TValueType = (vaNull, vaList, vaInt8, vaInt16, vaInt32, vaExtended,
- vaString, vaIdent, vaFalse, vaTrue, vaBinary, vaSet, vaLString,
- vaNil, vaCollection);
-
- TFilerFlag = (ffInherited, ffChildPos);
- TFilerFlags = set of TFilerFlag;
-
- TReaderProc = procedure(Reader: TReader) of object;
- TWriterProc = procedure(Writer: TWriter) of object;
- TStreamProc = procedure(Stream: TStream) of object;
-
- TFiler = class(TObject)
- private
- FStream: TStream;
- FBuffer: Pointer;
- FBufSize: Integer;
- FBufPos: Integer;
- FBufEnd: Integer;
- FRoot: TComponent;
- FAncestor: TPersistent;
- FIgnoreChildren: Boolean;
- public
- constructor Create(Stream: TStream; BufSize: Integer);
- destructor Destroy; override;
- procedure DefineProperty(const Name: string;
- ReadData: TReaderProc; WriteData: TWriterProc;
- HasData: Boolean); virtual; abstract;
- procedure DefineBinaryProperty(const Name: string;
- ReadData, WriteData: TStreamProc;
- HasData: Boolean); virtual; abstract;
- procedure FlushBuffer; virtual; abstract;
- property Root: TComponent read FRoot write FRoot;
- property Ancestor: TPersistent read FAncestor write FAncestor;
- property IgnoreChildren: Boolean read FIgnoreChildren write FIgnoreChildren;
- end;
-
- { TReader }
-
- TFindMethodEvent = procedure(Reader: TReader; const MethodName: string;
- var Address: Pointer; var Error: Boolean) of object;
- TSetNameEvent = procedure(Reader: TReader; Component: TComponent;
- var Name: string) of object;
- TReadComponentsProc = procedure(Component: TComponent) of object;
- TReaderError = procedure(Reader: TReader; const Message: string; var Handled: Boolean) of object;
-
- TReader = class(TFiler)
- private
- FOwner: TComponent;
- FParent: TComponent;
- FFixups: TList;
- FLoaded: TList;
- FOnFindMethod: TFindMethodEvent;
- FOnSetName: TSetNameEvent;
- FOnError: TReaderError;
- FCanHandleExcepts: Boolean;
- FPropName: string;
- procedure CheckValue(Value: TValueType);
- procedure DoFixupReferences;
- procedure FreeFixups;
- function GetPosition: Longint;
- procedure PropertyError;
- procedure ReadBuffer;
- procedure ReadCollection(Collection: TCollection);
- procedure ReadData(Instance: TComponent);
- procedure ReadDataInner(Instance: TComponent);
- procedure ReadProperty(AInstance: TPersistent);
- procedure ReadPropValue(Instance: TPersistent; PropInfo: Pointer);
- function ReadSet(SetType: Pointer): Integer;
- procedure SetPosition(Value: Longint);
- procedure SkipSetBody;
- procedure SkipValue;
- procedure SkipProperty;
- procedure SkipComponent(SkipHeader: Boolean);
- protected
- function Error(const Message: string): Boolean; virtual;
- function FindMethod(Root: TComponent; const MethodName: string): Pointer; virtual;
- function NextValue: TValueType;
- procedure SetName(Component: TComponent; var Name: string); virtual;
- public
- destructor Destroy; override;
- procedure BeginReferences;
- procedure DefineProperty(const Name: string;
- ReadData: TReaderProc; WriteData: TWriterProc;
- HasData: Boolean); override;
- procedure DefineBinaryProperty(const Name: string;
- ReadData, WriteData: TStreamProc;
- HasData: Boolean); override;
- function EndOfList: Boolean;
- procedure EndReferences;
- procedure FixupReferences;
- procedure FlushBuffer; override;
- procedure Read(var Buf; Count: Longint);
- function ReadBoolean: Boolean;
- function ReadChar: Char;
- function ReadComponent(Component: TComponent): TComponent;
- procedure ReadComponents(AOwner, AParent: TComponent;
- Proc: TReadComponentsProc);
- function ReadFloat: Extended;
- function ReadIdent: string;
- function ReadInteger: Longint;
- procedure ReadListBegin;
- procedure ReadListEnd;
- procedure ReadPrefix(var Flags: TFilerFlags; var AChildPos: Integer);
- function ReadRootComponent(Root: TComponent): TComponent;
- procedure ReadSignature;
- function ReadStr: string;
- function ReadString: string;
- function ReadValue: TValueType;
- property Owner: TComponent read FOwner write FOwner;
- property Parent: TComponent read FParent write FParent;
- property Position: Longint read GetPosition write SetPosition;
- property OnError: TReaderError read FOnError write FOnError;
- property OnFindMethod: TFindMethodEvent read FOnFindMethod write FOnFindMethod;
- property OnSetName: TSetNameEvent read FOnSetName write FOnSetName;
- end;
-
- { TWriter }
-
- TWriter = class(TFiler)
- private
- FRootAncestor: TComponent;
- FPropPath: string;
- FAncestorList: TList;
- FAncestorPos: Integer;
- FChildPos: Integer;
- procedure AddAncestor(Component: TComponent);
- function GetPosition: Longint;
- procedure SetPosition(Value: Longint);
- procedure WriteBinary(WriteData: TStreamProc);
- procedure WriteBuffer;
- procedure WriteData(Instance: TComponent); virtual; // linker optimization
- procedure WritePrefix(Flags: TFilerFlags; AChildPos: Integer);
- procedure WriteProperty(Instance: TPersistent; PropInfo: Pointer);
- procedure WriteProperties(Instance: TPersistent);
- procedure WritePropName(const PropName: string);
- procedure WriteValue(Value: TValueType);
- public
- destructor Destroy; override;
- procedure DefineProperty(const Name: string;
- ReadData: TReaderProc; WriteData: TWriterProc;
- HasData: Boolean); override;
- procedure DefineBinaryProperty(const Name: string;
- ReadData, WriteData: TStreamProc;
- HasData: Boolean); override;
- procedure FlushBuffer; override;
- procedure Write(const Buf; Count: Longint);
- procedure WriteBoolean(Value: Boolean);
- procedure WriteCollection(Value: TCollection);
- procedure WriteComponent(Component: TComponent);
- procedure WriteChar(Value: Char);
- procedure WriteDescendent(Root: TComponent; AAncestor: TComponent);
- procedure WriteFloat(Value: Extended);
- procedure WriteIdent(const Ident: string);
- procedure WriteInteger(Value: Longint);
- procedure WriteListBegin;
- procedure WriteListEnd;
- procedure WriteRootComponent(Root: TComponent);
- procedure WriteSignature;
- procedure WriteStr(const Value: string);
- procedure WriteString(const Value: string);
- property Position: Longint read GetPosition write SetPosition;
- property RootAncestor: TComponent read FRootAncestor write FRootAncestor;
- end;
-
- { TParser }
-
- TParser = class(TObject)
- private
- FStream: TStream;
- FOrigin: Longint;
- FBuffer: PChar;
- FBufPtr: PChar;
- FBufEnd: PChar;
- FSourcePtr: PChar;
- FSourceEnd: PChar;
- FTokenPtr: PChar;
- FStringPtr: PChar;
- FSourceLine: Integer;
- FSaveChar: Char;
- FToken: Char;
- procedure ReadBuffer;
- procedure SkipBlanks;
- public
- constructor Create(Stream: TStream);
- destructor Destroy; override;
- procedure CheckToken(T: Char);
- procedure CheckTokenSymbol(const S: string);
- procedure Error(Ident: Integer);
- procedure ErrorFmt(Ident: Integer; const Args: array of const);
- procedure ErrorStr(const Message: string);
- procedure HexToBinary(Stream: TStream);
- function NextToken: Char;
- function SourcePos: Longint;
- function TokenComponentIdent: String;
- function TokenFloat: Extended;
- function TokenInt: Longint;
- function TokenString: string;
- function TokenSymbolIs(const S: string): Boolean;
- property SourceLine: Integer read FSourceLine;
- property Token: Char read FToken;
- end;
-
- { TThread }
-
- EThread = class(Exception);
-
- TThreadMethod = procedure of object;
- TThreadPriority = (tpIdle, tpLowest, tpLower, tpNormal, tpHigher, tpHighest,
- tpTimeCritical);
-
- TThread = class
- private
- FHandle: THandle;
- FThreadID: THandle;
- FTerminated: Boolean;
- FSuspended: Boolean;
- FMainThreadWaiting: Boolean;
- FFreeOnTerminate: Boolean;
- FFinished: Boolean;
- FReturnValue: Integer;
- FOnTerminate: TNotifyEvent;
- FMethod: TThreadMethod;
- FSynchronizeException: TObject;
- procedure CallOnTerminate;
- function GetPriority: TThreadPriority;
- procedure SetPriority(Value: TThreadPriority);
- procedure SetSuspended(Value: Boolean);
- protected
- procedure DoTerminate; virtual;
- procedure Execute; virtual; abstract;
- procedure Synchronize(Method: TThreadMethod);
- property ReturnValue: Integer read FReturnValue write FReturnValue;
- property Terminated: Boolean read FTerminated;
- public
- constructor Create(CreateSuspended: Boolean);
- destructor Destroy; override;
- procedure Resume;
- procedure Suspend;
- procedure Terminate;
- function WaitFor: Integer;
- property FreeOnTerminate: Boolean read FFreeOnTerminate write FFreeOnTerminate;
- property Handle: THandle read FHandle;
- property Priority: TThreadPriority read GetPriority write SetPriority;
- property Suspended: Boolean read FSuspended write SetSuspended;
- property ThreadID: THandle read FThreadID;
- property OnTerminate: TNotifyEvent read FOnTerminate write FOnTerminate;
- end;
-
- { TComponent class }
-
- TOperation = (opInsert, opRemove);
- TComponentState = set of (csLoading, csReading, csWriting, csDestroying,
- csDesigning, csAncestor, csUpdating, csFixups);
- TComponentStyle = set of (csInheritable, csCheckPropAvail);
- TGetChildProc = procedure (Child: TComponent) of object;
-
- TComponentName = type string;
-
- TComponent = class(TPersistent)
- private
- FOwner: TComponent;
- FName: TComponentName;
- FTag: Longint;
- FComponents: TList;
- FFreeNotifies: TList;
- FDesignInfo: Longint;
- FComponentState: TComponentState;
- function GetComponent(AIndex: Integer): TComponent;
- function GetComponentCount: Integer;
- function GetComponentIndex: Integer;
- procedure Insert(AComponent: TComponent);
- procedure ReadLeft(Reader: TReader);
- procedure ReadTop(Reader: TReader);
- procedure Remove(AComponent: TComponent);
- procedure SetComponentIndex(Value: Integer);
- procedure SetReference(Enable: Boolean);
- procedure WriteLeft(Writer: TWriter);
- procedure WriteTop(Writer: TWriter);
- protected
- FComponentStyle: TComponentStyle;
- procedure ChangeName(const NewName: TComponentName);
- procedure DefineProperties(Filer: TFiler); override;
- procedure GetChildren(Proc: TGetChildProc); dynamic;
- function GetChildOwner: TComponent; dynamic;
- function GetChildParent: TComponent; dynamic;
- procedure Loaded; virtual;
- procedure Notification(AComponent: TComponent;
- Operation: TOperation); virtual;
- procedure ReadState(Reader: TReader); virtual;
- procedure SetAncestor(Value: Boolean);
- procedure SetDesigning(Value: Boolean);
- procedure SetName(const NewName: TComponentName); virtual;
- procedure SetChildOrder(Child: TComponent; Order: Integer); dynamic;
- procedure SetParentComponent(Value: TComponent); dynamic;
- procedure Updating; dynamic;
- procedure Updated; dynamic;
- procedure ValidateRename(AComponent: TComponent;
- const CurName, NewName: string); virtual;
- procedure WriteState(Writer: TWriter); virtual;
- public
- constructor Create(AOwner: TComponent); virtual;
- destructor Destroy; override;
- procedure DestroyComponents;
- procedure Destroying;
- function FindComponent(const AName: string): TComponent;
- function GetParentComponent: TComponent; dynamic;
- function HasParent: Boolean; dynamic;
- procedure FreeNotification(AComponent: TComponent);
- procedure InsertComponent(AComponent: TComponent);
- procedure RemoveComponent(AComponent: TComponent);
- property Components[Index: Integer]: TComponent read GetComponent;
- property ComponentCount: Integer read GetComponentCount;
- property ComponentIndex: Integer read GetComponentIndex write SetComponentIndex;
- property ComponentState: TComponentState read FComponentState;
- property ComponentStyle: TComponentStyle read FComponentStyle;
- property DesignInfo: Longint read FDesignInfo write FDesignInfo;
- property Owner: TComponent read FOwner;
- published
- property Name: TComponentName read FName write SetName stored False;
- property Tag: Longint read FTag write FTag default 0;
- end;
-
- { TComponent class reference type }
-
- TComponentClass = class of TComponent;
-
- { Component registration handlers }
-
- const
- RegisterComponentsProc: procedure(const Page: string;
- ComponentClasses: array of TComponentClass) = nil;
- RegisterNoIconProc: procedure(ComponentClasses: array of TComponentClass) = nil;
-
- { Point and rectangle constructors }
-
- function Point(AX, AY: Integer): TPoint;
- function SmallPoint(AX, AY: SmallInt): TSmallPoint;
- function Rect(ALeft, ATop, ARight, ABottom: Integer): TRect;
- function Bounds(ALeft, ATop, AWidth, AHeight: Integer): TRect;
-
- { Class registration routines }
-
- procedure RegisterClass(AClass: TPersistentClass);
- procedure RegisterClasses(AClasses: array of TPersistentClass);
- procedure RegisterClassAlias(AClass: TPersistentClass; const Alias: string);
- procedure UnRegisterClass(AClass: TPersistentClass);
- procedure UnRegisterClasses(AClasses: array of TPersistentClass);
- function FindClass(const ClassName: string): TPersistentClass;
- function GetClass(const ClassName: string): TPersistentClass;
-
- { Component registration routines }
-
- procedure RegisterComponents(const Page: string;
- ComponentClasses: array of TComponentClass);
- procedure RegisterNoIcon(ComponentClasses: array of TComponentClass);
-
- { Object filing routines }
-
- type
- TIdentToInt = function(const Ident: string; var Int: Longint): Boolean;
- TIntToIdent = function(Int: Longint; var Ident: string): Boolean;
- TFindGlobalComponent = function(const Name: string): TComponent;
-
- var
- MainThreadID: THandle;
- FindGlobalComponent: TFindGlobalComponent;
-
- procedure RegisterIntegerConsts(IntegerType: Pointer; IdentToInt: TIdentToInt;
- IntToIdent: TIntToIdent);
- function InitInheritedComponent(Instance: TComponent; RootAncestor: TClass): Boolean;
- function InitComponentRes(const ResName: string; Instance: TComponent): Boolean;
- function ReadComponentRes(const ResName: string; Instance: TComponent): TComponent;
- function ReadComponentResFile(const FileName: string; Instance: TComponent): TComponent;
- procedure WriteComponentResFile(const FileName: string; Instance: TComponent);
-
- procedure GlobalFixupReferences;
- procedure GetFixupReferenceNames(Root: TComponent; Names: TStrings);
- procedure GetFixupInstanceNames(Root: TComponent;
- const ReferenceRootName: string; Names: TStrings);
- procedure RedirectFixupReferences(Root: TComponent; const OldRootName,
- NewRootName: string);
- procedure RemoveFixupReferences(Root: TComponent; const RootName: string);
-
- procedure BeginGlobalLoading;
- procedure NotifyGlobalLoading;
- procedure EndGlobalLoading;
-
- function CollectionsEqual(C1, C2: TCollection): Boolean;
-
- { Object conversion routines }
-
- procedure ObjectBinaryToText(Input, Output: TStream);
- procedure ObjectTextToBinary(Input, Output: TStream);
-
- procedure ObjectResourceToText(Input, Output: TStream);
- procedure ObjectTextToResource(Input, Output: TStream);
-
- { Utility routines }
-
- function LineStart(Buffer, BufPos: PChar): PChar;
-
- implementation
-
- uses Consts, TypInfo;
-
- const
- FilerSignature: array[1..4] of Char = 'TPF0';
-
- var
- ClassList: TList = nil;
- ClassAliasList: TStringList = nil;
- IntConstList: TList = nil;
-
- type
- TIntegerSet = set of 0..SizeOf(Integer) * 8 - 1;
-
- { 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;
-
- { Class registration routines }
-
- type
- PFieldClassTable = ^TFieldClassTable;
- TFieldClassTable = packed record
- Count: Smallint;
- Classes: array[0..8191] of TPersistentClass;
- end;
-
- function GetFieldClassTable(AClass: TClass): PFieldClassTable; assembler;
- asm
- MOV EAX,[EAX-40].Integer
- OR EAX,EAX
- JE @@1
- MOV EAX,[EAX+2].Integer
- @@1:
- end;
-
- procedure ClassNotFound(const ClassName: string);
- begin
- raise EClassNotFound.Create(FmtLoadStr(SClassNotFound, [ClassName]));
- end;
-
- function GetClass(const ClassName: string): TPersistentClass;
- var
- I: Integer;
- begin
- for I := 0 to ClassList.Count - 1 do
- begin
- Result := ClassList[I];
- if Result.ClassNameIs(ClassName) then Exit;
- end;
- I := ClassAliasList.IndexOf(ClassName);
- if I >= 0 then
- begin
- Result := TPersistentClass(ClassAliasList.Objects[I]);
- Exit;
- end;
- Result := nil;
- end;
-
- function FindClass(const ClassName: string): TPersistentClass;
- begin
- Result := GetClass(ClassName);
- if Result = nil then ClassNotFound(ClassName);
- end;
-
- function FindFieldClass(Instance: TObject;
- const ClassName: string): TPersistentClass;
- var
- I: Integer;
- ClassTable: PFieldClassTable;
- ClassType: TClass;
- begin
- ClassType := Instance.ClassType;
- while ClassType <> TPersistent do
- begin
- ClassTable := GetFieldClassTable(ClassType);
- if ClassTable <> nil then
- for I := 0 to ClassTable^.Count - 1 do
- begin
- Result := ClassTable^.Classes[I];
- if CompareText(Result.ClassName, ClassName) = 0 then Exit;
- end;
- ClassType := ClassType.ClassParent;
- end;
- Result := FindClass(ClassName);
- end;
-
- procedure RegisterClass(AClass: TPersistentClass);
- var
- ClassName: string;
- begin
- while ClassList.IndexOf(AClass) = -1 do
- begin
- ClassName := AClass.ClassName;
- if GetClass(ClassName) <> nil then
- raise EFilerError.CreateResFmt(SDuplicateClass, [ClassName]);
- ClassList.Add(AClass);
- if AClass = TPersistent then Break;
- AClass := TPersistentClass(AClass.ClassParent);
- end;
- end;
-
- procedure RegisterClasses(AClasses: array of TPersistentClass);
- var
- I: Integer;
- begin
- for I := Low(AClasses) to High(AClasses) do RegisterClass(AClasses[I]);
- end;
-
- procedure RegisterClassAlias(AClass: TPersistentClass; const Alias: string);
- begin
- RegisterClass(AClass);
- ClassAliasList.AddObject(Alias, TObject(AClass));
- end;
-
- procedure UnRegisterClass(AClass: TPersistentClass);
- begin
- ClassList.Remove(AClass);
- end;
-
- procedure UnRegisterClasses(AClasses: array of TPersistentClass);
- var
- I: Integer;
- begin
- for I := Low(AClasses) to High(AClasses) do UnRegisterClass(AClasses[I]);
- end;
-
- { Component registration routines }
-
- procedure RegisterComponents(const Page: string;
- ComponentClasses: array of TComponentClass);
- begin
- if Assigned(RegisterComponentsProc) then
- RegisterComponentsProc(Page, ComponentClasses)
- else
- raise EComponentError.CreateRes(SRegisterError);
- end;
-
- procedure RegisterNoIcon(ComponentClasses: array of TComponentClass);
- begin
- if Assigned(RegisterNoIconProc) then
- RegisterNoIconProc(ComponentClasses)
- else
- raise EComponentError.CreateRes(SRegisterError);
- end;
-
- { Component filing }
-
- type
- TIntConst = class
- IntegerType: PTypeInfo;
- IdentToInt: TIdentToInt;
- IntToIdent: TIntToIdent;
- constructor Create(AIntegerType: PTypeInfo; AIdentToInt: TIdentToInt;
- AIntToIdent: TIntToIdent);
- end;
-
- constructor TIntConst.Create(AIntegerType: PTypeInfo; AIdentToInt: TIdentToInt;
- AIntToIdent: TIntToIdent);
- begin
- IntegerType := AIntegerType;
- IdentToInt := AIdentToInt;
- IntToIdent := AIntToIdent;
- end;
-
- procedure RegisterIntegerConsts(IntegerType: Pointer; IdentToInt: TIdentToInt;
- IntToIdent: TIntToIdent);
- begin
- IntConstList.Add(TIntConst.Create(IntegerType, IdentToInt, IntToIdent));
- end;
-
- function InternalReadComponentRes(const ResName: string; var Instance: TComponent): Boolean;
- var
- HRsrc: THandle;
- begin { avoid possible EResNotFound exception }
- HRsrc := FindResource(HInstance, PChar(ResName), RT_RCDATA);
- Result := HRsrc <> 0;
- if not Result then Exit;
- FreeResource(HRsrc);
- with TResourceStream.Create(HInstance, ResName, RT_RCDATA) do
- try
- Instance := ReadComponent(Instance);
- finally
- Free;
- end;
- Result := True;
- end;
-
- var
- GlobalLoaded: TList;
- GlobalLists: TList;
-
- procedure BeginGlobalLoading;
- begin
- GlobalLists.Add(GlobalLoaded);
- GlobalLoaded := TList.Create;
- end;
-
- procedure NotifyGlobalLoading;
- var
- I: Integer;
- begin
- for I := 0 to GlobalLoaded.Count - 1 do
- TComponent(GlobalLoaded[I]).Loaded;
- end;
-
- procedure EndGlobalLoading;
- begin
- GlobalLoaded.Free;
- GlobalLoaded := GlobalLists.Last;
- GlobalLists.Delete(GlobalLists.Count - 1);
- end;
-
- function InitInheritedComponent(Instance: TComponent; RootAncestor: TClass): Boolean;
-
- function InitComponent(ClassType: TClass): Boolean;
- begin
- Result := False;
- if (ClassType = TComponent) or (ClassType = RootAncestor) then Exit;
- Result := InitComponent(ClassType.ClassParent);
- Result := InternalReadComponentRes(ClassType.ClassName, Instance) or Result;
- end;
-
- begin
- BeginGlobalLoading;
- try
- Result := InitComponent(Instance.ClassType);
- NotifyGlobalLoading;
- finally
- EndGlobalLoading;
- end;
- end;
-
- function InitComponentRes(const ResName: string; Instance: TComponent): Boolean;
- begin
- Result := InternalReadComponentRes(ResName, Instance);
- end;
-
- function ReadComponentRes(const ResName: string; Instance: TComponent): TComponent;
- begin
- if InternalReadComponentRes(ResName, Instance) then
- Result := Instance else
- raise EResNotFound.CreateResFmt(SResNotFound, [ResName]);
- end;
-
- function ReadComponentResFile(const FileName: string; Instance: TComponent): TComponent;
- var
- Stream: TStream;
- begin
- Stream := TFileStream.Create(FileName, fmOpenRead);
- try
- Result := Stream.ReadComponentRes(Instance);
- finally
- Stream.Free;
- end;
- end;
-
- procedure WriteComponentResFile(const FileName: string; Instance: TComponent);
- var
- Stream: TStream;
- begin
- Stream := TFileStream.Create(FileName, fmCreate);
- try
- Stream.WriteComponentRes(Instance.ClassName, Instance);
- finally
- Stream.Free;
- end;
- end;
-
- function CompareMem(P1, P2: Pointer; Length: Integer): Boolean; assembler;
- asm
- PUSH ESI
- PUSH EDI
- MOV ESI,P1
- MOV EDI,P2
- MOV EDX,ECX
- XOR EAX,EAX
- AND EDX,3
- SHR ECX,2
- REPE CMPSD
- JNE @@2
- MOV ECX,EDX
- REPE CMPSB
- JNE @@2
- @@1: INC EAX
- @@2: POP EDI
- POP ESI
- end;
-
- function StreamsEqual(S1, S2: TMemoryStream): Boolean;
- begin
- Result := (S1.Size = S2.Size) and CompareMem(S1.Memory, S2.Memory, S1.Size);
- end;
-
- function CollectionsEqual(C1, C2: TCollection): Boolean;
- var
- S1, S2: TMemoryStream;
-
- procedure WriteCollection(Stream: TStream; Collection: TCollection);
- var
- Writer: TWriter;
- begin
- Writer := TWriter.Create(Stream, 1024);
- try
- Writer.WriteCollection(Collection);
- finally
- Writer.Free;
- end;
- end;
-
- begin
- Result := False;
- if C1.ClassType <> C2.ClassType then Exit;
- if C1.Count <> C2.Count then Exit;
- S1 := TMemoryStream.Create;
- try
- WriteCollection(S1, C1);
- S2 := TMemoryStream.Create;
- try
- WriteCollection(S2, C2);
- Result := StreamsEqual(S1, S2);
- finally
- S2.Free;
- end;
- finally
- S1.Free;
- end;
- end;
-
- { Utility routines }
-
- function LineStart(Buffer, BufPos: PChar): PChar; assembler;
- asm
- PUSH EDI
- MOV EDI,EDX
- MOV ECX,EDX
- SUB ECX,EAX
- SUB ECX,1
- JBE @@1
- MOV EDX,EAX
- DEC EDI
- MOV AL,0AH
- STD
- REPNE SCASB
- CLD
- MOV EAX,EDX
- JNE @@1
- LEA EAX,[EDI+2]
- @@1: POP EDI
- end;
-
- procedure ListError(Ident: Integer);
- begin
- raise EListError.CreateRes(Ident);
- end;
-
- procedure ListIndexError;
- begin
- ListError(SListIndexError);
- end;
-
- { TList }
-
- destructor TList.Destroy;
- begin
- Clear;
- end;
-
- function TList.Add(Item: Pointer): Integer;
- begin
- Result := FCount;
- if Result = FCapacity then Grow;
- FList^[Result] := Item;
- Inc(FCount);
- end;
-
- procedure TList.Clear;
- begin
- SetCount(0);
- SetCapacity(0);
- end;
-
- procedure TList.Delete(Index: Integer);
- begin
- if (Index < 0) or (Index >= FCount) then Error;
- Dec(FCount);
- if Index < FCount then
- System.Move(FList^[Index + 1], FList^[Index],
- (FCount - Index) * SizeOf(Pointer));
- end;
-
- procedure TList.Error;
- begin
- ListIndexError;
- end;
-
- procedure TList.Exchange(Index1, Index2: Integer);
- var
- Item: Pointer;
- begin
- if (Index1 < 0) or (Index1 >= FCount) or
- (Index2 < 0) or (Index2 >= FCount) then Error;
- Item := FList^[Index1];
- FList^[Index1] := FList^[Index2];
- FList^[Index2] := Item;
- end;
-
- function TList.Expand: TList;
- begin
- if FCount = FCapacity then Grow;
- Result := Self;
- end;
-
- function TList.First: Pointer;
- begin
- Result := Get(0);
- end;
-
- function TList.Get(Index: Integer): Pointer;
- begin
- if (Index < 0) or (Index >= FCount) then Error;
- Result := FList^[Index];
- end;
-
- procedure TList.Grow;
- var
- Delta: Integer;
- begin
- if FCapacity > 8 then Delta := 16 else
- if FCapacity > 4 then Delta := 8 else
- Delta := 4;
- SetCapacity(FCapacity + Delta);
- end;
-
- function TList.IndexOf(Item: Pointer): Integer;
- begin
- Result := 0;
- while (Result < FCount) and (FList^[Result] <> Item) do Inc(Result);
- if Result = FCount then Result := -1;
- end;
-
- procedure TList.Insert(Index: Integer; Item: Pointer);
- begin
- if (Index < 0) or (Index > FCount) then Error;
- if FCount = FCapacity then Grow;
- if Index < FCount then
- System.Move(FList^[Index], FList^[Index + 1],
- (FCount - Index) * SizeOf(Pointer));
- FList^[Index] := Item;
- Inc(FCount);
- end;
-
- function TList.Last: Pointer;
- begin
- Result := Get(FCount - 1);
- end;
-
- procedure TList.Move(CurIndex, NewIndex: Integer);
- var
- Item: Pointer;
- begin
- if CurIndex <> NewIndex then
- begin
- if (NewIndex < 0) or (NewIndex >= FCount) then Error;
- Item := Get(CurIndex);
- Delete(CurIndex);
- Insert(NewIndex, Item);
- end;
- end;
-
- procedure TList.Put(Index: Integer; Item: Pointer);
- begin
- if (Index < 0) or (Index >= FCount) then Error;
- FList^[Index] := Item;
- end;
-
- function TList.Remove(Item: Pointer): Integer;
- begin
- Result := IndexOf(Item);
- if Result <> -1 then Delete(Result);
- end;
-
- procedure TList.Pack;
- var
- I: Integer;
- begin
- for I := FCount - 1 downto 0 do if Items[I] = nil then Delete(I);
- end;
-
- procedure TList.SetCapacity(NewCapacity: Integer);
- begin
- if (NewCapacity < FCount) or (NewCapacity > MaxListSize) then Error;
- if NewCapacity <> FCapacity then
- begin
- ReallocMem(FList, NewCapacity * SizeOf(Pointer));
- FCapacity := NewCapacity;
- end;
- end;
-
- procedure TList.SetCount(NewCount: Integer);
- begin
- if (NewCount < 0) or (NewCount > MaxListSize) then Error;
- if NewCount > FCapacity then SetCapacity(NewCount);
- if NewCount > FCount then
- FillChar(FList^[FCount], (NewCount - FCount) * SizeOf(Pointer), 0);
- FCount := NewCount;
- end;
-
- procedure QuickSort(SortList: PPointerList; L, R: Integer;
- SCompare: TListSortCompare);
- var
- I, J: Integer;
- P, T: Pointer;
- begin
- repeat
- I := L;
- J := R;
- P := SortList^[(L + R) shr 1];
- repeat
- while SCompare(SortList^[I], P) < 0 do Inc(I);
- while SCompare(SortList^[J], P) > 0 do Dec(J);
- if I <= J then
- begin
- T := SortList^[I];
- SortList^[I] := SortList^[J];
- SortList^[J] := T;
- Inc(I);
- Dec(J);
- end;
- until I > J;
- if L < J then QuickSort(SortList, L, J, SCompare);
- L := I;
- until I >= R;
- end;
-
- procedure TList.Sort(Compare: TListSortCompare);
- begin
- if (FList <> nil) and (Count > 0) then
- QuickSort(FList, 0, Count - 1, Compare);
- end;
-
- { TBits }
-
- const
- BitsPerInt = SizeOf(Integer) * 8;
-
- type
- TBitEnum = 0..BitsPerInt - 1;
- TBitSet = set of TBitEnum;
- PBitArray = ^TBitArray;
- TBitArray = array[0..4096] of TBitSet;
-
- destructor TBits.Destroy;
- begin
- SetSize(0);
- inherited Destroy;
- end;
-
- procedure TBits.Error;
- begin
- raise EBitsError.CreateRes(SBitsIndexError);
- end;
-
- procedure TBits.SetSize(Value: Integer);
- var
- NewMem: Pointer;
- NewMemSize: Integer;
- OldMemSize: Integer;
-
- function Min(X, Y: Integer): Integer;
- begin
- Result := X;
- if X > Y then Result := Y;
- end;
-
- begin
- if Value <> Size then
- begin
- if Value < 0 then Error;
- NewMemSize := ((Value + BitsPerInt - 1) div BitsPerInt) * SizeOf(Integer);
- OldMemSize := ((Size + BitsPerInt - 1) div BitsPerInt) * SizeOf(Integer);
- if NewMemSize <> OldMemSize then
- begin
- NewMem := nil;
- if NewMemSize <> 0 then
- begin
- GetMem(NewMem, NewMemSize);
- FillChar(NewMem^, NewMemSize, 0);
- end;
- if OldMemSize <> 0 then
- begin
- if NewMem <> nil then
- Move(FBits^, NewMem^, Min(OldMemSize, NewMemSize));
- FreeMem(FBits, OldMemSize);
- end;
- FBits := NewMem;
- end;
- FSize := Value;
- end;
- end;
-
-
- procedure TBits.SetBit(Index: Integer; Value: Boolean); assembler;
- asm
- CMP Index,[EAX].FSize
- JAE @@Size
-
- @@1: MOV EAX,[EAX].FBits
- OR Value,Value
- JZ @@2
- BTS [EAX],Index
- RET
-
- @@2: BTR [EAX],Index
- RET
-
- @@Size: CMP Index,0
- JL TBits.Error
- PUSH Self
- PUSH Index
- PUSH ECX {Value}
- INC Index
- CALL TBits.SetSize
- POP ECX {Value}
- POP Index
- POP Self
- JMP @@1
- end;
-
- function TBits.GetBit(Index: Integer): Boolean; assembler;
- asm
- CMP Index,[EAX].FSize
- JAE TBits.Error
- MOV EAX,[EAX].FBits
- BT [EAX],Index
- SBB EAX,EAX
- AND EAX,1
- end;
-
-
- function TBits.OpenBit: Integer;
- var
- I: Integer;
- B: TBitSet;
- J: TBitEnum;
- E: Integer;
- begin
- E := (Size + BitsPerInt - 1) div BitsPerInt - 1;
- for I := 0 to E do
- if PBitArray(FBits)^[I] <> [0..BitsPerInt - 1] then
- begin
- B := PBitArray(FBits)^[I];
- for J := Low(J) to High(J) do
- begin
- if not (J in B) then
- begin
- Result := I * BitsPerInt + J;
- if Result >= Size then Result := Size;
- Exit;
- end;
- end;
- end;
- Result := Size;
- end;
-
- { TPersistent }
-
- procedure TPersistent.Assign(Source: TPersistent);
- begin
- if Source <> nil then Source.AssignTo(Self) else AssignError(nil);
- end;
-
- procedure TPersistent.AssignError(Source: TPersistent);
- var
- SourceName: string;
- begin
- if Source <> nil then
- SourceName := Source.ClassName else
- SourceName := 'nil';
- raise EConvertError.CreateResFmt(SAssignError, [SourceName, ClassName]);
- end;
-
- procedure TPersistent.AssignTo(Dest: TPersistent);
- begin
- Dest.AssignError(Self);
- end;
-
- procedure TPersistent.DefineProperties(Filer: TFiler);
- begin
- end;
-
- { TCollectionItem }
-
- constructor TCollectionItem.Create(Collection: TCollection);
- begin
- SetCollection(Collection);
- end;
-
- destructor TCollectionItem.Destroy;
- begin
- SetCollection(nil);
- end;
-
- procedure TCollectionItem.Changed(AllItems: Boolean);
- var
- Item: TCollectionItem;
- begin
- if (FCollection <> nil) and (FCollection.FUpdateCount = 0) then
- begin
- if AllItems then Item := nil else Item := Self;
- FCollection.Update(Item);
- end;
- end;
-
- function TCollectionItem.GetIndex: Integer;
- begin
- if FCollection <> nil then
- Result := FCollection.FItems.IndexOf(Self) else
- Result := -1;
- end;
-
- procedure TCollectionItem.SetCollection(Value: TCollection);
- begin
- if FCollection <> Value then
- begin
- if FCollection <> nil then FCollection.RemoveItem(Self);
- if Value <> nil then Value.InsertItem(Self);
- end;
- end;
-
- procedure TCollectionItem.SetIndex(Value: Integer);
- var
- CurIndex: Integer;
- begin
- CurIndex := GetIndex;
- if (CurIndex >= 0) and (CurIndex <> Value) then
- begin
- FCollection.FItems.Move(CurIndex, Value);
- Changed(True);
- end;
- end;
-
- { TCollection }
-
- constructor TCollection.Create(ItemClass: TCollectionItemClass);
- begin
- FItemClass := ItemClass;
- FItems := TList.Create;
- end;
-
- destructor TCollection.Destroy;
- begin
- FUpdateCount := 1;
- if FItems <> nil then Clear;
- FItems.Free;
- end;
-
- function TCollection.Add: TCollectionItem;
- begin
- Result := FItemClass.Create(Self);
- end;
-
- procedure TCollection.Assign(Source: TPersistent);
- var
- I: Integer;
- begin
- if Source is TCollection then
- begin
- BeginUpdate;
- try
- Clear;
- for I := 0 to TCollection(Source).Count - 1 do
- Add.Assign(TCollection(Source).Items[I]);
- finally
- EndUpdate;
- end;
- Exit;
- end;
- inherited Assign(Source);
- end;
-
- procedure TCollection.BeginUpdate;
- begin
- Inc(FUpdateCount);
- end;
-
- procedure TCollection.Changed;
- begin
- if FUpdateCount = 0 then Update(nil);
- end;
-
- procedure TCollection.Clear;
- begin
- if FItems.Count > 0 then
- begin
- BeginUpdate;
- try
- while FItems.Count > 0 do TCollectionItem(FItems.Last).Free;
- finally
- EndUpdate;
- end;
- end;
- end;
-
- procedure TCollection.EndUpdate;
- begin
- Dec(FUpdateCount);
- Changed;
- end;
-
- function TCollection.GetCount: Integer;
- begin
- Result := FItems.Count;
- end;
-
- function TCollection.GetItem(Index: Integer): TCollectionItem;
- begin
- Result := FItems[Index];
- end;
-
- procedure TCollection.InsertItem(Item: TCollectionItem);
- begin
- if not (Item is FItemClass) then ListError(SInvalidProperty);
- FItems.Add(Item);
- Item.FCollection := Self;
- Changed;
- end;
-
- procedure TCollection.RemoveItem(Item: TCollectionItem);
- begin
- FItems.Remove(Item);
- Item.FCollection := nil;
- Changed;
- end;
-
- procedure TCollection.SetItem(Index: Integer; Value: TCollectionItem);
- begin
- TCollectionItem(FItems[Index]).Assign(Value);
- end;
-
- procedure TCollection.Update(Item: TCollectionItem);
- begin
- end;
-
- { TStrings }
-
- function TStrings.Add(const S: string): Integer;
- begin
- Result := GetCount;
- Insert(Result, S);
- end;
-
- function TStrings.AddObject(const S: string; AObject: TObject): Integer;
- begin
- Result := Add(S);
- PutObject(Result, AObject);
- end;
-
- procedure TStrings.Append(const S: string);
- begin
- Add(S);
- end;
-
- procedure TStrings.AddStrings(Strings: TStrings);
- var
- I: Integer;
- begin
- BeginUpdate;
- try
- for I := 0 to Strings.Count - 1 do
- AddObject(Strings[I], Strings.Objects[I]);
- finally
- EndUpdate;
- end;
- end;
-
- procedure TStrings.Assign(Source: TPersistent);
- begin
- if Source is TStrings then
- begin
- BeginUpdate;
- try
- Clear;
- AddStrings(TStrings(Source));
- finally
- EndUpdate;
- end;
- Exit;
- end;
- inherited Assign(Source);
- end;
-
- procedure TStrings.BeginUpdate;
- begin
- if FUpdateCount = 0 then SetUpdateState(True);
- Inc(FUpdateCount);
- end;
-
- procedure TStrings.DefineProperties(Filer: TFiler);
-
- function DoWrite: Boolean;
- begin
- if Filer.Ancestor <> nil then
- begin
- Result := True;
- if Filer.Ancestor is TStrings then
- Result := not Equals(TStrings(Filer.Ancestor))
- end
- else Result := Count > 0;
- end;
-
- begin
- Filer.DefineProperty('Strings', ReadData, WriteData, DoWrite);
- end;
-
- procedure TStrings.EndUpdate;
- begin
- Dec(FUpdateCount);
- if FUpdateCount = 0 then SetUpdateState(False);
- end;
-
- function TStrings.Equals(Strings: TStrings): Boolean;
- var
- I, Count: Integer;
- begin
- Result := False;
- Count := GetCount;
- if Count <> Strings.GetCount then Exit;
- for I := 0 to Count - 1 do if Get(I) <> Strings.Get(I) then Exit;
- Result := True;
- end;
-
- procedure TStrings.Exchange(Index1, Index2: Integer);
- var
- TempObject: TObject;
- TempString: string;
- begin
- TempString := Strings[Index1];
- TempObject := Objects[Index1];
- Strings[Index1] := Strings[Index2];
- Objects[Index1] := Objects[Index2];
- Strings[Index2] := TempString;
- Objects[Index2] := TempObject;
- end;
-
- function TStrings.GetCommaText: string;
- var
- P, S, T: PChar;
- I, L, Count: Integer;
- Quotes: Boolean;
- Text: array[0..4095] of Char;
- begin
- Count := GetCount;
- if (Count = 1) and (Get(0) = '') then Result := '""' else
- begin
- T := Text;
- for I := 0 to Count - 1 do
- begin
- if I <> 0 then
- begin
- T^ := ',';
- Inc(T);
- end;
- S := PChar(Get(I));
- L := 0;
- Quotes := False;
- P := S;
- while P^ <> #0 do
- begin
- if not Quotes and ((P^ <= ' ') or (P^ = '"') or (P^ = ',')) then
- begin
- Inc(L, 2);
- Quotes := True;
- end;
- if P^ = '"' then Inc(L);
- Inc(L);
- Inc(P);
- end;
- if T + L >= Text + SizeOf(Text) then Break;
- if Quotes then
- begin
- T^ := '"';
- Inc(T);
- end;
- P := S;
- while P^ <> #0 do
- begin
- if P^ = '"' then
- begin
- T^ := '"';
- Inc(T);
- end;
- T^ := P^;
- Inc(T);
- Inc(P);
- end;
- if Quotes then
- begin
- T^ := '"';
- Inc(T);
- end;
- end;
- SetString(Result, Text, T - Text);
- end;
- end;
-
- function TStrings.GetName(Index: Integer): string;
- var
- P: Integer;
- begin
- Result := Get(Index);
- P := Pos('=', Result);
- if P <> 0 then
- SetLength(Result, P-1) else
- SetLength(Result, 0);
- end;
-
- function TStrings.GetObject(Index: Integer): TObject;
- begin
- Result := nil;
- end;
-
- function TStrings.GetText: PChar;
- begin
- Result := StrNew(PChar(GetTextStr));
- end;
-
- function TStrings.GetTextStr: string;
- var
- I, L, Size, Count: Integer;
- P: PChar;
- S: string;
- begin
- Count := GetCount;
- Size := 0;
- for I := 0 to Count - 1 do Inc(Size, Length(Get(I)) + 2);
- SetString(Result, nil, Size);
- P := Pointer(Result);
- for I := 0 to Count - 1 do
- begin
- S := Get(I);
- L := Length(S);
- if L <> 0 then
- begin
- System.Move(Pointer(S)^, P^, L);
- Inc(P, L);
- end;
- P^ := #13;
- Inc(P);
- P^ := #10;
- Inc(P);
- end;
- end;
-
- function TStrings.GetValue(const Name: string): string;
- var
- I: Integer;
- begin
- I := IndexOfName(Name);
- if I >= 0 then
- Result := Copy(Get(I), Length(Name) + 2, MaxInt) else
- Result := '';
- end;
-
- function TStrings.IndexOf(const S: string): Integer;
- begin
- for Result := 0 to GetCount - 1 do
- if AnsiCompareText(Get(Result), S) = 0 then Exit;
- Result := -1;
- end;
-
- function TStrings.IndexOfName(const Name: string): Integer;
- var
- P: Integer;
- S: string;
- begin
- for Result := 0 to GetCount - 1 do
- begin
- S := Get(Result);
- P := Pos('=', S);
- if (P <> 0) and (AnsiCompareText(Copy(S, 1, P - 1), Name) = 0) then Exit;
- end;
- Result := -1;
- end;
-
- function TStrings.IndexOfObject(AObject: TObject): Integer;
- begin
- for Result := 0 to GetCount - 1 do
- if GetObject(Result) = AObject then Exit;
- Result := -1;
- end;
-
- procedure TStrings.InsertObject(Index: Integer; const S: string;
- AObject: TObject);
- begin
- Insert(Index, S);
- PutObject(Index, AObject);
- end;
-
- procedure TStrings.LoadFromFile(const FileName: string);
- var
- Stream: TStream;
- begin
- Stream := TFileStream.Create(FileName, fmOpenRead);
- try
- LoadFromStream(Stream);
- finally
- Stream.Free;
- end;
- end;
-
- procedure TStrings.LoadFromStream(Stream: TStream);
- var
- Size: Integer;
- S: string;
- begin
- BeginUpdate;
- try
- Size := Stream.Size - Stream.Position;
- SetString(S, nil, Size);
- Stream.Read(Pointer(S)^, Size);
- SetTextStr(S);
- finally
- EndUpdate;
- end;
- end;
-
- procedure TStrings.Move(CurIndex, NewIndex: Integer);
- var
- TempObject: TObject;
- TempString: string;
- begin
- if CurIndex <> NewIndex then
- begin
- TempString := Get(CurIndex);
- TempObject := GetObject(CurIndex);
- Delete(CurIndex);
- InsertObject(NewIndex, TempString, TempObject);
- end;
- end;
-
- procedure TStrings.Put(Index: Integer; const S: string);
- var
- TempObject: TObject;
- begin
- TempObject := GetObject(Index);
- Delete(Index);
- InsertObject(Index, S, TempObject);
- end;
-
- procedure TStrings.PutObject(Index: Integer; AObject: TObject);
- begin
- end;
-
- procedure TStrings.ReadData(Reader: TReader);
- begin
- Reader.ReadListBegin;
- Clear;
- while not Reader.EndOfList do Add(Reader.ReadString);
- Reader.ReadListEnd;
- end;
-
- procedure TStrings.SaveToFile(const FileName: string);
- var
- Stream: TStream;
- begin
- Stream := TFileStream.Create(FileName, fmCreate);
- try
- SaveToStream(Stream);
- finally
- Stream.Free;
- end;
- end;
-
- procedure TStrings.SaveToStream(Stream: TStream);
- var
- S: string;
- begin
- S := GetText;
- Stream.WriteBuffer(Pointer(S)^, Length(S));
- end;
-
- procedure TStrings.SetCommaText(const Value: string);
- var
- P, P1, P2: PChar;
- S: string;
- Text: array[0..4095] of Char;
- begin
- BeginUpdate;
- try
- Clear;
- StrLCopy(Text, PChar(Value), SizeOf(Text) - 1);
- P := Text;
- while (P^ <> #0) and (P^ <= ' ') do Inc(P);
- if P^ <> #0 then
- while True do
- begin
- P1 := P;
- if P^ = '"' then
- begin
- P2 := P;
- Inc(P);
- while P^ <> #0 do
- begin
- if P^ = '"' then
- begin
- Inc(P);
- if P^ <> '"' then Break;
- end;
- P2^ := P^;
- Inc(P2);
- Inc(P);
- end;
- end else
- begin
- while (P^ > ' ') and (P^ <> ',') do Inc(P);
- P2 := P;
- end;
- SetString(S, P1, P2 - P1);
- Add(S);
- while (P^ <> #0) and (P^ <= ' ') do Inc(P);
- if P^ = #0 then Break;
- if P^ = ',' then
- begin
- Inc(P);
- while (P^ <> #0) and (P^ <= ' ') do Inc(P);
- end;
- end;
- finally
- EndUpdate;
- end;
- end;
-
- procedure TStrings.SetValue(const Name, Value: string);
- var
- I: Integer;
- begin
- I := IndexOfName(Name);
- if Value <> '' then
- begin
- if I < 0 then I := Add('');
- Put(I, Name + '=' + Value);
- end else
- begin
- if I >= 0 then Delete(I);
- end;
- end;
-
- procedure TStrings.SetText(Text: PChar);
- begin
- SetTextStr(Text);
- end;
-
- procedure TStrings.SetTextStr(const Value: string);
- var
- P, Start: PChar;
- S: string;
- begin
- BeginUpdate;
- try
- Clear;
- P := Pointer(Value);
- if P <> nil then
- while P^ <> #0 do
- begin
- Start := P;
- while not (P^ in [#0, #10, #13]) do Inc(P);
- SetString(S, Start, P - Start);
- Add(S);
- if P^ = #13 then Inc(P);
- if P^ = #10 then Inc(P);
- end;
- finally
- EndUpdate;
- end;
- end;
-
- procedure TStrings.SetUpdateState(Updating: Boolean);
- begin
- end;
-
- procedure TStrings.WriteData(Writer: TWriter);
- var
- I: Integer;
- begin
- Writer.WriteListBegin;
- for I := 0 to Count - 1 do Writer.WriteString(Get(I));
- Writer.WriteListEnd;
- end;
-
- { TStringList }
-
- destructor TStringList.Destroy;
- begin
- FOnChange := nil;
- FOnChanging := nil;
- if FCount <> 0 then Finalize(FList^[0], FCount);
- FCount := 0;
- SetCapacity(0);
- end;
-
- function TStringList.Add(const S: string): Integer;
- begin
- if not Sorted then
- Result := FCount
- else
- if Find(S, Result) then
- case Duplicates of
- dupIgnore: Exit;
- dupError: ListError(SDuplicateString);
- end;
- InsertItem(Result, S);
- end;
-
- procedure TStringList.Changed;
- begin
- if (FUpdateCount = 0) and Assigned(FOnChange) then FOnChange(Self);
- end;
-
- procedure TStringList.Changing;
- begin
- if (FUpdateCount = 0) and Assigned(FOnChanging) then FOnChanging(Self);
- end;
-
- procedure TStringList.Clear;
- begin
- if FCount <> 0 then
- begin
- Changing;
- Finalize(FList^[0], FCount);
- FCount := 0;
- SetCapacity(0);
- Changed;
- end;
- end;
-
- procedure TStringList.Delete(Index: Integer);
- begin
- if (Index < 0) or (Index >= FCount) then ListIndexError;
- Changing;
- Finalize(FList^[Index]);
- Dec(FCount);
- if Index < FCount then
- System.Move(FList^[Index + 1], FList^[Index],
- (FCount - Index) * SizeOf(TStringItem));
- Changed;
- end;
-
- procedure TStringList.Exchange(Index1, Index2: Integer);
- begin
- if (Index1 < 0) or (Index1 >= FCount) or
- (Index2 < 0) or (Index2 >= FCount) then ListIndexError;
- Changing;
- ExchangeItems(Index1, Index2);
- Changed;
- end;
-
- procedure TStringList.ExchangeItems(Index1, Index2: Integer);
- var
- Temp: Integer;
- Item1, Item2: PStringItem;
- begin
- Item1 := @FList^[Index1];
- Item2 := @FList^[Index2];
- Temp := Integer(Item1^.FString);
- Integer(Item1^.FString) := Integer(Item2^.FString);
- Integer(Item2^.FString) := Temp;
- Temp := Integer(Item1^.FObject);
- Integer(Item1^.FObject) := Integer(Item2^.FObject);
- Integer(Item2^.FObject) := Temp;
- end;
-
- function TStringList.Find(const S: string; var Index: Integer): Boolean;
- var
- L, H, I, C: Integer;
- begin
- Result := False;
- L := 0;
- H := FCount - 1;
- while L <= H do
- begin
- I := (L + H) shr 1;
- C := AnsiCompareText(FList^[I].FString, S);
- if C < 0 then L := I + 1 else
- begin
- H := I - 1;
- if C = 0 then
- begin
- Result := True;
- if Duplicates <> dupAccept then L := I;
- end;
- end;
- end;
- Index := L;
- end;
-
- function TStringList.Get(Index: Integer): string;
- begin
- if (Index < 0) or (Index >= FCount) then ListIndexError;
- Result := FList^[Index].FString;
- end;
-
- function TStringList.GetCount: Integer;
- begin
- Result := FCount;
- end;
-
- function TStringList.GetObject(Index: Integer): TObject;
- begin
- if (Index < 0) or (Index >= FCount) then ListIndexError;
- Result := FList^[Index].FObject;
- end;
-
- procedure TStringList.Grow;
- var
- Delta: Integer;
- begin
- if FCapacity > 8 then Delta := 16 else
- if FCapacity > 4 then Delta := 8 else
- Delta := 4;
- SetCapacity(FCapacity + Delta);
- end;
-
- function TStringList.IndexOf(const S: string): Integer;
- begin
- if not Sorted then Result := inherited IndexOf(S) else
- if not Find(S, Result) then Result := -1;
- end;
-
- procedure TStringList.Insert(Index: Integer; const S: string);
- begin
- if Sorted then ListError(SSortedListError);
- if (Index < 0) or (Index > FCount) then ListIndexError;
- InsertItem(Index, S);
- end;
-
- procedure TStringList.InsertItem(Index: Integer; const S: string);
- begin
- Changing;
- if FCount = FCapacity then Grow;
- if Index < FCount then
- System.Move(FList^[Index], FList^[Index + 1],
- (FCount - Index) * SizeOf(TStringItem));
- with FList^[Index] do
- begin
- Pointer(FString) := nil;
- FObject := nil;
- FString := S;
- end;
- Inc(FCount);
- Changed;
- end;
-
- procedure TStringList.Put(Index: Integer; const S: string);
- begin
- if Sorted then ListError(SSortedListError);
- if (Index < 0) or (Index >= FCount) then ListIndexError;
- Changing;
- FList^[Index].FString := S;
- Changed;
- end;
-
- procedure TStringList.PutObject(Index: Integer; AObject: TObject);
- begin
- if (Index < 0) or (Index >= FCount) then ListIndexError;
- Changing;
- FList^[Index].FObject := AObject;
- Changed;
- end;
-
- procedure TStringList.QuickSort(L, R: Integer);
- var
- I, J: Integer;
- P: string;
- begin
- repeat
- I := L;
- J := R;
- P := FList^[(L + R) shr 1].FString;
- repeat
- while AnsiCompareText(FList^[I].FString, P) < 0 do Inc(I);
- while AnsiCompareText(FList^[J].FString, P) > 0 do Dec(J);
- if I <= J then
- begin
- ExchangeItems(I, J);
- Inc(I);
- Dec(J);
- end;
- until I > J;
- if L < J then QuickSort(L, J);
- L := I;
- until I >= R;
- end;
-
- procedure TStringList.SetCapacity(NewCapacity: Integer);
- begin
- ReallocMem(FList, NewCapacity * SizeOf(TStringItem));
- FCapacity := NewCapacity;
- end;
-
- procedure TStringList.SetSorted(Value: Boolean);
- begin
- if FSorted <> Value then
- begin
- if Value then Sort;
- FSorted := Value;
- end;
- end;
-
- procedure TStringList.SetUpdateState(Updating: Boolean);
- begin
- if Updating then Changing else Changed;
- end;
-
- procedure TStringList.Sort;
- begin
- if not Sorted and (FCount > 1) then
- begin
- Changing;
- QuickSort(0, FCount - 1);
- Changed;
- end;
- end;
-
- { TStream }
-
- function TStream.GetPosition: Longint;
- begin
- Result := Seek(0, 1);
- end;
-
- procedure TStream.SetPosition(Pos: Longint);
- begin
- Seek(Pos, 0);
- end;
-
- function TStream.GetSize: Longint;
- var
- Pos: Longint;
- begin
- Pos := Seek(0, 1);
- Result := Seek(0, 2);
- Seek(Pos, 0);
- end;
-
- procedure TStream.ReadBuffer(var Buffer; Count: Longint);
- begin
- if (Count <> 0) and (Read(Buffer, Count) <> Count) then
- raise EReadError.CreateRes(SReadError);
- end;
-
- procedure TStream.WriteBuffer(const Buffer; Count: Longint);
- begin
- if (Count <> 0) and (Write(Buffer, Count) <> Count) then
- raise EWriteError.CreateRes(SWriteError);
- end;
-
- function TStream.CopyFrom(Source: TStream; Count: Longint): Longint;
- const
- MaxBufSize = $F000;
- var
- BufSize, N: Integer;
- Buffer: PChar;
- begin
- if Count = 0 then
- begin
- Source.Position := 0;
- Count := Source.Size;
- end;
- Result := Count;
- if Count > MaxBufSize then BufSize := MaxBufSize else BufSize := Count;
- GetMem(Buffer, BufSize);
- try
- while Count <> 0 do
- begin
- if Count > BufSize then N := BufSize else N := Count;
- Source.ReadBuffer(Buffer^, N);
- WriteBuffer(Buffer^, N);
- Dec(Count, N);
- end;
- finally
- FreeMem(Buffer, BufSize);
- end;
- end;
-
- function TStream.ReadComponent(Instance: TComponent): TComponent;
- var
- Reader: TReader;
- begin
- Reader := TReader.Create(Self, 4096);
- try
- Result := Reader.ReadRootComponent(Instance);
- finally
- Reader.Free;
- end;
- end;
-
- procedure TStream.WriteComponent(Instance: TComponent);
- begin
- WriteDescendent(Instance, nil);
- end;
-
- procedure TStream.WriteDescendent(Instance, Ancestor: TComponent);
- var
- Writer: TWriter;
- begin
- Writer := TWriter.Create(Self, 4096);
- try
- Writer.WriteDescendent(Instance, Ancestor);
- finally
- Writer.Free;
- end;
- end;
-
- function TStream.ReadComponentRes(Instance: TComponent): TComponent;
- begin
- ReadResHeader;
- Result := ReadComponent(Instance);
- end;
-
- procedure TStream.WriteComponentRes(const ResName: string; Instance: TComponent);
- begin
- WriteDescendentRes(ResName, Instance, nil);
- end;
-
- procedure TStream.WriteDescendentRes(const ResName: string; Instance,
- Ancestor: TComponent);
- var
- HeaderSize: Integer;
- Origin, ImageSize: Longint;
- Header: array[0..79] of Char;
- begin
- Byte((@Header[0])^) := $FF;
- Word((@Header[1])^) := 10;
- HeaderSize := StrLen(StrUpper(StrPLCopy(@Header[3], ResName, 63))) + 10;
- Word((@Header[HeaderSize - 6])^) := $1030;
- Longint((@Header[HeaderSize - 4])^) := 0;
- WriteBuffer(Header, HeaderSize);
- Origin := Position;
- WriteDescendent(Instance, Ancestor);
- ImageSize := Position - Origin;
- Position := Origin - 4;
- WriteBuffer(ImageSize, SizeOf(Longint));
- Position := Origin + ImageSize;
- end;
-
- procedure TStream.ReadResHeader;
- var
- ReadCount: Longint;
- Header: array[0..79] of Char;
- begin
- FillChar(Header, SizeOf(Header), 0);
- ReadCount := Read(Header, SizeOf(Header) - 1);
- if (Byte((@Header[0])^) = $FF) and (Word((@Header[1])^) = 10) then
- Seek(StrLen(Header + 3) + 10 - ReadCount, 1)
- else
- raise EInvalidImage.CreateRes(SInvalidImage);
- end;
-
- { THandleStream }
-
- constructor THandleStream.Create(AHandle: Integer);
- begin
- FHandle := AHandle;
- end;
-
- function THandleStream.Read(var Buffer; Count: Longint): Longint;
- begin
- Result := FileRead(FHandle, Buffer, Count);
- if Result = -1 then Result := 0;
- end;
-
- function THandleStream.Write(const Buffer; Count: Longint): Longint;
- begin
- Result := FileWrite(FHandle, Buffer, Count);
- if Result = -1 then Result := 0;
- end;
-
- function THandleStream.Seek(Offset: Longint; Origin: Word): Longint;
- begin
- Result := FileSeek(FHandle, Offset, Origin);
- end;
-
- { TFileStream }
-
- constructor TFileStream.Create(const FileName: string; Mode: Word);
- begin
- if Mode = fmCreate then
- begin
- FHandle := FileCreate(FileName);
- if FHandle < 0 then
- raise EFCreateError.CreateResFmt(SFCreateError, [FileName]);
- end else
- begin
- FHandle := FileOpen(FileName, Mode);
- if FHandle < 0 then
- raise EFOpenError.CreateResFmt(SFOpenError, [FileName]);
- end;
- end;
-
- destructor TFileStream.Destroy;
- begin
- if FHandle >= 0 then FileClose(FHandle);
- end;
-
-
- { TCustomMemoryStream }
-
- procedure TCustomMemoryStream.SetPointer(Ptr: Pointer; Size: Longint);
- begin
- FMemory := Ptr;
- FSize := Size;
- end;
-
- function TCustomMemoryStream.Read(var Buffer; Count: Longint): Longint;
- begin
- if (FPosition >= 0) and (Count >= 0) then
- begin
- Result := FSize - FPosition;
- if Result > 0 then
- begin
- if Result > Count then Result := Count;
- Move(Pointer(Longint(FMemory) + FPosition)^, Buffer, Result);
- Inc(FPosition, Result);
- Exit;
- end;
- end;
- Result := 0;
- end;
-
- function TCustomMemoryStream.Seek(Offset: Longint; Origin: Word): Longint;
- begin
- case Origin of
- 0: FPosition := Offset;
- 1: Inc(FPosition, Offset);
- 2: FPosition := FSize + Offset;
- end;
- Result := FPosition;
- end;
-
- procedure TCustomMemoryStream.SaveToStream(Stream: TStream);
- begin
- if FSize <> 0 then Stream.WriteBuffer(FMemory^, FSize);
- end;
-
- procedure TCustomMemoryStream.SaveToFile(const FileName: string);
- var
- Stream: TStream;
- begin
- Stream := TFileStream.Create(FileName, fmCreate);
- try
- SaveToStream(Stream);
- finally
- Stream.Free;
- end;
- end;
-
- { TMemoryStream }
-
- const
- MemoryDelta = $2000; { Must be a power of 2 }
-
- destructor TMemoryStream.Destroy;
- begin
- Clear;
- inherited Destroy;
- end;
-
- procedure TMemoryStream.Clear;
- begin
- SetCapacity(0);
- FSize := 0;
- FPosition := 0;
- end;
-
- procedure TMemoryStream.LoadFromStream(Stream: TStream);
- var
- Count: Longint;
- begin
- Stream.Position := 0;
- Count := Stream.Size;
- SetSize(Count);
- if Count <> 0 then Stream.ReadBuffer(FMemory^, Count);
- end;
-
- procedure TMemoryStream.LoadFromFile(const FileName: string);
- var
- Stream: TStream;
- begin
- Stream := TFileStream.Create(FileName, fmOpenRead);
- try
- LoadFromStream(Stream);
- finally
- Stream.Free;
- end;
- end;
-
- procedure TMemoryStream.SetCapacity(NewCapacity: Longint);
- begin
- SetPointer(Realloc(NewCapacity), FSize);
- FCapacity := NewCapacity;
- end;
-
- procedure TMemoryStream.SetSize(NewSize: Longint);
- begin
- Clear;
- SetCapacity(NewSize);
- FSize := NewSize;
- end;
-
- function TMemoryStream.Realloc(var NewCapacity: Longint): Pointer;
- begin
- if NewCapacity > 0 then
- NewCapacity := (NewCapacity + (MemoryDelta - 1)) and not (MemoryDelta - 1);
- Result := Memory;
- if NewCapacity <> FCapacity then
- begin
- if NewCapacity = 0 then
- begin
- GlobalFreePtr(Memory);
- Result := nil;
- end else
- begin
- if Capacity = 0 then
- Result := GlobalAllocPtr(HeapAllocFlags, NewCapacity)
- else
- Result := GlobalReallocPtr(Memory, NewCapacity, HeapAllocFlags);
- if Result = nil then raise EStreamError.CreateRes(SMemoryStreamError);
- end;
- end;
- end;
-
- function TMemoryStream.Write(const Buffer; Count: Longint): Longint;
- var
- Pos: Longint;
- begin
- if (FPosition >= 0) and (Count >= 0) then
- begin
- Pos := FPosition + Count;
- if Pos > 0 then
- begin
- if Pos > FSize then
- begin
- if Pos > FCapacity then
- SetCapacity(Pos);
- FSize := Pos;
- end;
- System.Move(Buffer, Pointer(Longint(FMemory) + FPosition)^, Count);
- FPosition := Pos;
- Result := Count;
- Exit;
- end;
- end;
- Result := 0;
- end;
-
- { TResourceStream }
-
- constructor TResourceStream.Create(Instance: THandle; const ResName: string;
- ResType: PChar);
- begin
- inherited Create;
- Initialize(Instance, PChar(ResName), ResType);
- end;
-
- constructor TResourceStream.CreateFromID(Instance: THandle; ResID: Integer;
- ResType: PChar);
- begin
- inherited Create;
- Initialize(Instance, PChar(ResID), ResType);
- end;
-
- procedure TResourceStream.Initialize(Instance: THandle; Name, ResType: PChar);
-
- procedure Error;
- begin
- raise EResNotFound.Create(FmtLoadStr(SResNotFound, [Name]));
- end;
-
- begin
- HResInfo := FindResource(Instance, Name, ResType);
- if HResInfo = 0 then Error;
- HGlobal := LoadResource(Instance, HResInfo);
- if HGlobal = 0 then Error;
- SetPointer(LockResource(HGlobal), SizeOfResource(Instance, HResInfo));
- end;
-
- destructor TResourceStream.Destroy;
- begin
- UnlockResource(HGlobal);
- FreeResource(HResInfo);
- inherited Destroy;
- end;
-
- function TResourceStream.Write(const Buffer; Count: Longint): Longint;
- begin
- raise EStreamError.CreateRes(SCantWriteResourceStreamError);
- end;
-
- { TFiler }
-
- constructor TFiler.Create(Stream: TStream; BufSize: Integer);
- begin
- FStream := Stream;
- GetMem(FBuffer, BufSize);
- FBufSize := BufSize;
- end;
-
- destructor TFiler.Destroy;
- begin
- if FBuffer <> nil then FreeMem(FBuffer, FBufSize);
- end;
-
- { TPropFixup }
-
- type
- TPropFixup = class
- FInstance: TPersistent;
- FInstanceRoot: TComponent;
- FPropInfo: PPropInfo;
- FRootName: string;
- FName: string;
- constructor Create(Instance: TPersistent; InstanceRoot: TComponent;
- PropInfo: PPropInfo; const RootName, Name: string);
- end;
-
- var
- GlobalFixupList: TList;
-
- constructor TPropFixup.Create(Instance: TPersistent; InstanceRoot: TComponent;
- PropInfo: PPropInfo; const RootName, Name: string);
- begin
- FInstance := Instance;
- FInstanceRoot := InstanceRoot;
- FPropInfo := PropInfo;
- FRootName := RootName;
- FName := Name;
- end;
-
- procedure GlobalFixupReferences;
- var
- FinishedList: TList;
- NotFinishedList: TList;
- I: Integer;
- Root: TComponent;
- Instance: TPersistent;
-
- procedure AddFinished(Instance: TPersistent);
- begin
- if (FinishedList.IndexOf(Instance) < 0) and
- (NotFinishedList.IndexOf(Instance) >= 0) then
- FinishedList.Add(Instance);
- end;
-
- procedure AddNotFinished(Instance: TPersistent);
- var
- Index: Integer;
- begin
- Index := FinishedList.IndexOf(Instance);
- if Index <> -1 then FinishedList.Delete(Index);
- if NotFinishedList.IndexOf(Instance) < 0 then
- NotFinishedList.Add(Instance);
- end;
-
- begin
- if Assigned(FindGlobalComponent) and (GlobalFixupList.Count > 0) then
- begin
- FinishedList := TList.Create;
- try
- NotFinishedList := TList.Create;
- try
- I := 0;
- while I < GlobalFixupList.Count do
- with TPropFixup(GlobalFixupList[I]) do
- begin
- Root := FindGlobalComponent(FRootName);
- if (Root <> nil) or (GetOrdProp(FInstance, FPropInfo) <> 0) then
- begin
- if Root <> nil then
- SetOrdProp(FInstance, FPropInfo,
- Longint(Root.FindComponent(FName)));
- AddFinished(FInstance);
- GlobalFixupList.Delete(I);
- Free;
- end else
- begin
- AddNotFinished(FInstance);
- Inc(I);
- end;
- end;
- finally
- NotFinishedList.Free;
- end;
- for I := 0 to FinishedList.Count - 1 do
- begin
- Instance := FinishedList[I];
- if Instance is TComponent then
- Exclude(TComponent(Instance).FComponentState, csFixups);
- end;
- finally
- FinishedList.Free;
- end;
- end;
- end;
-
- function NameInStrings(Strings: TStrings; const Name: string): Boolean;
- var
- I: Integer;
- begin
- Result := True;
- for I := 0 to Strings.Count - 1 do
- if CompareText(Name, Strings[I]) = 0 then Exit;
- Result := False;
- end;
-
- procedure GetFixupReferenceNames(Root: TComponent; Names: TStrings);
- var
- I: Integer;
- Fixup: TPropFixup;
- begin
- for I := 0 to GlobalFixupList.Count - 1 do
- begin
- Fixup := GlobalFixupList[I];
- if ((Root = nil) or (Fixup.FInstanceRoot = Root)) and
- not NameInStrings(Names, Fixup.FRootName) then
- Names.Add(Fixup.FRootName);
- end;
- end;
-
- procedure RedirectFixupReferences(Root: TComponent; const OldRootName,
- NewRootName: string);
- var
- I: Integer;
- Fixup: TPropFixup;
- begin
- for I := 0 to GlobalFixupList.Count - 1 do
- begin
- Fixup := GlobalFixupList[I];
- if ((Root = nil) or (Fixup.FInstanceRoot = Root)) and
- (CompareText(OldRootName, Fixup.FRootName) = 0) then
- Fixup.FRootName := NewRootName;
- end;
- GlobalFixupReferences;
- end;
-
- procedure RemoveFixupReferences(Root: TComponent; const RootName: string);
- var
- I: Integer;
- Fixup: TPropFixup;
- begin
- for I := GlobalFixupList.Count - 1 downto 0 do
- begin
- Fixup := GlobalFixupList[I];
- if ((Root = nil) or (Fixup.FInstanceRoot = Root)) and
- ((RootName = '') or (CompareText(RootName, Fixup.FRootName) = 0)) then
- begin
- GlobalFixupList.Delete(I);
- Fixup.Free;
- end;
- end;
- end;
-
- procedure GetFixupInstanceNames(Root: TComponent;
- const ReferenceRootName: string; Names: TStrings);
- var
- I: Integer;
- Fixup: TPropFixup;
- begin
- for I := 0 to GlobalFixupList.Count - 1 do
- begin
- Fixup := GlobalFixupList[I];
- if (Fixup.FInstanceRoot = Root) and
- (CompareText(ReferenceRootName, Fixup.FRootName) = 0) and
- not NameInStrings(Names, Fixup.FName) then
- Names.Add(Fixup.FName);
- end;
- end;
-
- { TReader }
-
- procedure ReadError(Ident: Integer);
- begin
- raise EReadError.CreateRes(Ident);
- end;
-
- procedure PropValueError;
- begin
- ReadError(SInvalidPropertyValue);
- end;
-
- procedure PropertyNotFound;
- begin
- ReadError(SUnknownProperty);
- end;
-
- function EnumValue(EnumType: PTypeInfo; const EnumName: string): Integer;
- begin
- Result := GetEnumValue(EnumType, EnumName);
- if Result = -1 then PropValueError;
- end;
-
- destructor TReader.Destroy;
- begin
- FStream.Seek(Integer(FBufPos) - Integer(FBufEnd), 1);
- inherited Destroy;
- end;
-
- procedure TReader.BeginReferences;
- begin
- FLoaded := TList.Create;
- try
- FFixups := TList.Create;
- except
- FLoaded.Free;
- raise;
- end;
- end;
-
- procedure TReader.CheckValue(Value: TValueType);
- begin
- if ReadValue <> Value then
- begin
- Dec(FBufPos);
- SkipValue;
- PropValueError;
- end;
- end;
-
- procedure TReader.DefineProperty(const Name: string;
- ReadData: TReaderProc; WriteData: TWriterProc; HasData: Boolean);
- begin
- if CompareText(Name, FPropName) = 0 then
- begin
- ReadData(Self);
- FPropName := '';
- end;
- end;
-
- procedure TReader.DefineBinaryProperty(const Name: string;
- ReadData, WriteData: TStreamProc; HasData: Boolean);
- var
- Stream: TMemoryStream;
- Count: Longint;
- begin
- if CompareText(Name, FPropName) = 0 then
- begin
- if ReadValue <> vaBinary then
- begin
- Dec(FBufPos);
- SkipValue;
- FCanHandleExcepts := True;
- PropValueError;
- end;
- Stream := TMemoryStream.Create;
- try
- Read(Count, SizeOf(Count));
- Stream.SetSize(Count);
- Read(Stream.Memory^, Count);
- FCanHandleExcepts := True;
- ReadData(Stream);
- finally
- Stream.Free;
- end;
- FPropName := '';
- end;
- end;
-
- function TReader.EndOfList: Boolean;
- begin
- Result := ReadValue = vaNull;
- Dec(FBufPos);
- end;
-
- procedure TReader.EndReferences;
- begin
- FreeFixups;
- FLoaded.Free;
- FLoaded := nil;
- end;
-
- function TReader.Error(const Message: string): Boolean;
- begin
- Result := False;
- if Assigned(FOnError) then FOnError(Self, Message, Result);
- end;
-
- function TReader.FindMethod(Root: TComponent;
- const MethodName: string): Pointer;
- var
- Error: Boolean;
- begin
- Result := Root.MethodAddress(MethodName);
- Error := Result = nil;
- if Assigned(FOnFindMethod) then FOnFindMethod(Self, MethodName, Result, Error);
- if Error then PropValueError;
- end;
-
- procedure TReader.DoFixupReferences;
- var
- I: Integer;
- begin
- if FFixups <> nil then
- try
- for I := 0 to FFixups.Count - 1 do
- with TPropFixup(FFixups[I]) do
- SetOrdProp(FInstance, FPropInfo,
- Longint(FRoot.FindComponent(FName)));
- finally
- FreeFixups;
- end;
- end;
-
- procedure TReader.FixupReferences;
- var
- I: Integer;
- begin
- DoFixupReferences;
- GlobalFixupReferences;
- for I := 0 to FLoaded.Count - 1 do TComponent(FLoaded[I]).Loaded;
- end;
-
- procedure TReader.FlushBuffer;
- begin
- FStream.Position := FStream.Position - (FBufEnd - FBufPos);
- FBufPos := 0;
- FBufEnd := 0;
- end;
-
- procedure TReader.FreeFixups;
- var
- I: Integer;
- begin
- if FFixups <> nil then
- begin
- for I := 0 to FFixups.Count - 1 do TPropFixup(FFixups[I]).Free;
- FFixups.Free;
- FFixups := nil;
- end;
- end;
-
- function TReader.GetPosition: Longint;
- begin
- Result := FStream.Position + FBufPos;
- end;
-
- function TReader.NextValue: TValueType;
- begin
- Result := ReadValue;
- Dec(FBufPos);
- end;
-
- procedure TReader.PropertyError;
- begin
- SkipValue;
- PropertyNotFound;
- end;
-
- procedure TReader.Read(var Buf; Count: Longint); assembler;
- asm
- PUSH ESI
- PUSH EDI
- PUSH EBX
- MOV EDI,EDX
- MOV EBX,ECX
- MOV ESI,EAX
- JMP @@6
- @@1: MOV ECX,[ESI].TReader.FBufEnd
- SUB ECX,[ESI].TReader.FBufPos
- JA @@2
- MOV EAX,ESI
- CALL TReader.ReadBuffer
- MOV ECX,[ESI].TReader.FBufEnd
- @@2: CMP ECX,EBX
- JB @@3
- MOV ECX,EBX
- @@3: PUSH ESI
- SUB EBX,ECX
- MOV EAX,[ESI].TReader.FBuffer
- ADD EAX,[ESI].TReader.FBufPos
- ADD [ESI].TReader.FBufPos,ECX
- MOV ESI,EAX
- MOV EDX,ECX
- SHR ECX,2
- CLD
- REP MOVSD
- MOV ECX,EDX
- AND ECX,3
- REP MOVSB
- POP ESI
- @@6: OR EBX,EBX
- JNE @@1
- POP EBX
- POP EDI
- POP ESI
- end;
-
- procedure TReader.ReadBuffer;
- begin
- FBufEnd := FStream.Read(FBuffer^, FBufSize);
- if FBufEnd = 0 then raise EReadError.CreateRes(SReadError);
- FBufPos := 0;
- end;
-
- function TReader.ReadBoolean: Boolean;
- begin
- Result := ReadValue = vaTrue;
- end;
-
- function TReader.ReadChar: Char;
- begin
- CheckValue(vaString);
- Read(Result, 1);
- if Ord(Result) <> 1 then
- begin
- Dec(FBufPos);
- ReadStr;
- PropValueError;
- end;
- Read(Result, 1);
- end;
-
- procedure TReader.ReadCollection(Collection: TCollection);
- var
- Item: TPersistent;
- Index: Integer;
- begin
- Index := 0;
- Collection.BeginUpdate;
- try
- while not EndOfList do
- begin
- if NextValue in [vaInt8, vaInt16, vaInt32] then Index := ReadInteger;
- while Collection.Count <= Index do Collection.Add;
- Item := Collection.Items[Index];
- ReadListBegin;
- while not EndOfList do ReadProperty(Item);
- ReadListEnd;
- Inc(Index);
- end;
- ReadListEnd;
- finally
- Collection.EndUpdate;
- end;
- end;
-
- function TReader.ReadComponent(Component: TComponent): TComponent;
- var
- CompClass, CompName: string;
- Flags: TFilerFlags;
- Position: Integer;
-
- function ComponentCreated: Boolean;
- begin
- Result := not (ffInherited in Flags) and (Component = nil);
- end;
-
- function Recover(var Component: TComponent): Boolean;
- begin
- Result := False;
- if not (ExceptObject is Exception) then Exit;
- if ComponentCreated then Component.Free;
- Component := nil;
- SkipComponent(False);
- Result := Error(Exception(ExceptObject).Message);
- end;
-
- procedure CreateComponent;
- begin
- try
- Result := TComponentClass(FindFieldClass(Root, CompClass)).Create(Owner);
- Include(Result.FComponentState, csLoading);
- except
- if not Recover(Result) then raise;
- end;
- end;
-
- procedure SetCompName;
- begin
- try
- Result.SetParentComponent(Parent);
- SetName(Result, CompName);
- except
- if not Recover(Result) then raise;
- end;
- end;
-
- procedure FindExistingComponent;
- begin
- try
- Result := Root.FindComponent(CompName);
- if Result = nil then
- raise EReadError.CreateResFmt(SAncestorNotFound, [CompName]);
- except
- if not Recover(Result) then raise;
- end;
- end;
-
- begin
- ReadPrefix(Flags, Position);
- CompClass := ReadStr;
- CompName := ReadStr;
- Result := Component;
- if Result = nil then
- if ffInherited in Flags then
- FindExistingComponent else
- CreateComponent;
- if Result <> nil then
- try
- Include(Result.FComponentState, csLoading);
- if not (ffInherited in Flags) then SetCompName;
- if Result = nil then Exit;
- Include(Result.FComponentState, csReading);
- Result.ReadState(Self);
- Exclude(Result.FComponentState, csReading);
- if ffChildPos in Flags then Parent.SetChildOrder(Result, Position);
- FLoaded.Add(Result);
- except
- if ComponentCreated then Result.Free;
- raise;
- end;
- end;
-
- procedure TReader.ReadData(Instance: TComponent);
- begin
- if FFixups = nil then
- begin
- FFixups := TList.Create;
- try
- ReadDataInner(Instance);
- DoFixupReferences;
- finally
- FreeFixups;
- end;
- end else
- ReadDataInner(Instance);
- end;
-
- procedure TReader.ReadDataInner(Instance: TComponent);
- var
- OldParent, OldOwner: TComponent;
- begin
- while not EndOfList do ReadProperty(Instance);
- ReadListEnd;
- OldParent := Parent;
- OldOwner := Owner;
- Parent := Instance.GetChildParent;
- try
- Owner := Instance.GetChildOwner;
- if not Assigned(Owner) then Owner := Root;
- while not EndOfList do ReadComponent(nil);
- ReadListEnd;
- finally
- Parent := OldParent;
- Owner := OldOwner;
- end;
- end;
-
- function TReader.ReadFloat: Extended;
- begin
- if ReadValue = vaExtended then Read(Result, SizeOf(Result)) else
- begin
- Dec(FBufPos);
- Result := ReadInteger;
- end;
- end;
-
- function TReader.ReadIdent: string;
- var
- L: Byte;
- begin
- case ReadValue of
- vaIdent:
- begin
- Read(L, SizeOf(Byte));
- SetString(Result, PChar(nil), L);
- Read(Result[1], L);
- end;
- vaFalse:
- Result := 'False';
- vaTrue:
- Result := 'True';
- vaNil:
- Result := 'nil';
- else
- PropValueError;
- end;
- end;
-
- function TReader.ReadInteger: Longint;
- var
- S: Shortint;
- I: Smallint;
- begin
- case ReadValue of
- vaInt8:
- begin
- Read(S, SizeOf(Shortint));
- Result := S;
- end;
- vaInt16:
- begin
- Read(I, SizeOf(I));
- Result := I;
- end;
- vaInt32:
- Read(Result, SizeOf(Result));
- else
- PropValueError;
- end;
- end;
-
- procedure TReader.ReadListBegin;
- begin
- CheckValue(vaList);
- end;
-
- procedure TReader.ReadListEnd;
- begin
- CheckValue(vaNull);
- end;
-
- procedure TReader.ReadPrefix(var Flags: TFilerFlags; var AChildPos: Integer);
- var
- Prefix: Byte;
- begin
- Flags := [];
- if Byte(NextValue) and $F0 = $F0 then
- begin
- Prefix := Byte(ReadValue);
- Byte(Flags) := Prefix and $0F;
- if ffChildPos in Flags then AChildPos := ReadInteger;
- end;
- end;
-
- procedure TReader.ReadProperty(AInstance: TPersistent);
- var
- I, J, L: Integer;
- Instance: TPersistent;
- PropInfo: PPropInfo;
- PropValue: TObject;
- PropPath: string;
-
- procedure HandleException(E: Exception);
- var
- Name: string;
- begin
- Name := '';
- if AInstance is TComponent then
- Name := TComponent(AInstance).Name;
- if Name = '' then Name := AInstance.ClassName;
- raise EReadError.CreateResFmt(SPropertyException,
- [Name, PropPath, E.Message]);
- end;
-
- procedure PropPathError;
- begin
- SkipValue;
- ReadError(SInvalidPropertyPath);
- end;
-
- begin
- try
- PropPath := ReadStr;
- try
- I := 1;
- L := Length(PropPath);
- Instance := AInstance;
- FCanHandleExcepts := True;
- while True do
- begin
- J := I;
- while (I <= L) and (PropPath[I] <> '.') do Inc(I);
- FPropName := Copy(PropPath, J, I - J);
- if I > L then Break;
- PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
- if PropInfo = nil then PropertyError;
- PropValue := nil;
- if PropInfo^.PropType^.Kind = tkClass then
- PropValue := TObject(GetOrdProp(Instance, PropInfo));
- if not (PropValue is TPersistent) then PropPathError;
- Instance := TPersistent(PropValue);
- Inc(I);
- end;
- PropInfo := GetPropInfo(Instance.ClassInfo, FPropName);
- if PropInfo <> nil then ReadPropValue(Instance, PropInfo) else
- begin
- { Cannot reliably recover from an error in a defined property }
- FCanHandleExcepts := False;
- Instance.DefineProperties(Self);
- FCanHandleExcepts := True;
- if FPropName <> '' then PropertyError;
- end;
- except
- on E: Exception do HandleException(E);
- end;
- except
- on E: Exception do
- if not FCanHandleExcepts or not Error(E.Message) then raise;
- end;
- end;
-
- procedure TReader.ReadPropValue(Instance: TPersistent; PropInfo: Pointer);
- const
- NilMethod: TMethod = (Code: nil; Data: nil);
- var
- PropType: PTypeInfo;
- Method: TMethod;
-
- procedure SetIntIdent(Instance: TPersistent; PropInfo: Pointer;
- const Ident: string);
- var
- I: Integer;
- V: Longint;
- begin
- for I := 0 to IntConstList.Count - 1 do
- with TIntConst(IntConstList[I]) do
- if PPropInfo(PropInfo)^.PropType = IntegerType then
- if IdentToInt(Ident, V) then
- begin
- SetOrdProp(Instance, PropInfo, V);
- Exit;
- end;
- PropValueError;
- end;
-
- procedure SetObjectIdent(Instance: TPersistent; PropInfo: Pointer;
- const Ident: string);
- var
- RootName, Name: string;
- P: Integer;
- Fixup: TPropFixup;
- begin
- RootName := '';
- Name := Ident;
- P := Pos('.', Ident);
- if P <> 0 then
- begin
- RootName := Copy(Ident, 1, P - 1);
- Name := Copy(Ident, P + 1, MaxInt);
- end;
- Fixup := TPropFixup.Create(Instance, Root, PropInfo, RootName, Name);
- if RootName = '' then
- FFixups.Add(Fixup) else
- GlobalFixupList.Add(Fixup);
- end;
-
- begin
- if PPropInfo(PropInfo)^.SetProc = nil then ReadError(SReadOnlyProperty);
- PropType := PPropInfo(PropInfo)^.PropType;
- case PropType^.Kind of
- tkInteger:
- if NextValue = vaIdent then
- SetIntIdent(Instance, PropInfo, ReadIdent) else
- SetOrdProp(Instance, PropInfo, ReadInteger);
- tkChar:
- SetOrdProp(Instance, PropInfo, Ord(ReadChar));
- tkEnumeration:
- SetOrdProp(Instance, PropInfo, EnumValue(PropType, ReadIdent));
- tkFloat:
- SetFloatProp(Instance, PropInfo, ReadFloat);
- tkString, tkLString:
- SetStrProp(Instance, PropInfo, ReadString);
- tkSet:
- SetOrdProp(Instance, PropInfo, ReadSet(PropType));
- tkClass:
- case NextValue of
- vaNil:
- begin
- ReadValue;
- SetOrdProp(Instance, PropInfo, 0)
- end;
- vaCollection:
- begin
- ReadValue;
- ReadCollection(TCollection(GetOrdProp(Instance, PropInfo)));
- end
- else
- SetObjectIdent(Instance, PropInfo, ReadIdent);
- end;
- tkMethod:
- if NextValue = vaNil then
- begin
- ReadValue;
- SetMethodProp(Instance, PropInfo, NilMethod);
- end
- else
- begin
- Method.Code := FindMethod(Root, ReadIdent);
- Method.Data := Root;
- if Method.Code <> nil then SetMethodProp(Instance, PropInfo, Method);
- end;
- end;
- end;
-
- function TReader.ReadRootComponent(Root: TComponent): TComponent;
-
- function FindUniqueName(const Name: string): string;
- var
- I: Integer;
- begin
- I := 0;
- Result := '';
- if Assigned(FindGlobalComponent) then
- begin
- Result := Name;
- while FindGlobalComponent(Result) <> nil do
- begin
- Inc(I);
- Result := Format('%s_%d', [Name, I]);
- end;
- end;
- end;
-
- var
- I: Integer;
- Flags: TFilerFlags;
- begin
- ReadSignature;
- Result := nil;
- try
- ReadPrefix(Flags, I);
- if Root = nil then
- begin
- Result := TComponentClass(FindClass(ReadStr)).Create(nil);
- Result.Name := ReadStr;
- end else
- begin
- Result := Root;
- ReadStr; { Ignore class name }
- if csDesigning in Result.ComponentState then
- ReadStr else
- Result.Name := FindUniqueName(ReadStr);
- end;
- FRoot := Result;
- if GlobalLoaded <> nil then
- FLoaded := GlobalLoaded else
- FLoaded := TList.Create;
- try
- FLoaded.Add(FRoot);
- FOwner := FRoot;
- Include(FRoot.FComponentState, csLoading);
- Include(FRoot.FComponentState, csReading);
- FRoot.ReadState(Self);
- Exclude(FRoot.FComponentState, csReading);
- if GlobalLoaded = nil then
- for I := 0 to FLoaded.Count - 1 do TComponent(FLoaded[I]).Loaded;
- finally
- if GlobalLoaded = nil then FLoaded.Free;
- FLoaded := nil;
- end;
- GlobalFixupReferences;
- except
- RemoveFixupReferences(Root, '');
- if Root = nil then Result.Free;
- raise;
- end;
- end;
-
- procedure TReader.ReadComponents(AOwner, AParent: TComponent;
- Proc: TReadComponentsProc);
- var
- Component: TComponent;
- begin
- Root := AOwner;
- Owner := AOwner;
- Parent := AParent;
- BeginReferences;
- try
- while not EndOfList do
- begin
- ReadSignature;
- Component := ReadComponent(nil);
- Proc(Component);
- end;
- FixupReferences;
- finally
- EndReferences;
- end;
- end;
-
- function TReader.ReadSet(SetType: Pointer): Integer;
- var
- EnumType: PTypeInfo;
- EnumName: string;
- begin
- try
- if ReadValue <> vaSet then PropValueError;
- EnumType := GetTypeData(SetType)^.CompType;
- Result := 0;
- while True do
- begin
- EnumName := ReadStr;
- if EnumName = '' then Break;
- Include(TIntegerSet(Result), EnumValue(EnumType, EnumName));
- end;
- except
- SkipSetBody;
- raise;
- end;
- end;
-
- procedure TReader.ReadSignature;
- var
- Signature: Longint;
- begin
- Read(Signature, SizeOf(Signature));
- if Signature <> Longint(FilerSignature) then ReadError(SInvalidImage);
- end;
-
- function TReader.ReadStr: string;
- var
- L: Byte;
- begin
- Read(L, SizeOf(Byte));
- SetString(Result, PChar(nil), L);
- Read(Result[1], L);
- end;
-
- function TReader.ReadString: string;
- var
- L: Integer;
- begin
- L := 0;
- case ReadValue of
- vaString:
- Read(L, SizeOf(Byte));
- vaLString:
- Read(L, SizeOf(Integer));
- else
- PropValueError;
- end;
- SetString(Result, PChar(nil), L);
- Read(Pointer(Result)^, L);
- end;
-
- function TReader.ReadValue: TValueType;
- begin
- Read(Result, SizeOf(Result));
- end;
-
- procedure TReader.SetPosition(Value: Longint);
- begin
- FStream.Position := Value;
- FBufPos := 0;
- FBufEnd := 0;
- end;
-
- procedure TReader.SkipSetBody;
- begin
- while ReadStr <> '' do begin end;
- end;
-
- procedure TReader.SkipValue;
-
- procedure SkipList;
- begin
- while not EndOfList do SkipValue;
- ReadListEnd;
- end;
-
- procedure SkipBytes(Count: Longint);
- var
- Bytes: array[0..255] of Char;
- begin
- while Count > 0 do
- if Count > SizeOf(Bytes) then
- begin
- Read(Bytes, SizeOf(Bytes));
- Dec(Count, SizeOf(Bytes));
- end
- else
- begin
- Read(Bytes, Count);
- Count := 0;
- end;
- end;
-
- procedure SkipBinary;
- var
- Count: Longint;
- begin
- Read(Count, SizeOf(Count));
- SkipBytes(Count);
- end;
-
- begin
- case ReadValue of
- vaNull: begin end;
- vaList: SkipList;
- vaInt8: SkipBytes(1);
- vaInt16: SkipBytes(2);
- vaInt32: SkipBytes(4);
- vaExtended: SkipBytes(SizeOf(Extended));
- vaString, vaIdent: ReadStr;
- vaFalse, vaTrue: begin end;
- vaBinary: SkipBinary;
- vaSet: SkipSetBody;
- end;
- end;
-
- procedure TReader.SkipProperty;
- begin
- ReadStr; { Skips property name }
- SkipValue;
- end;
-
- procedure TReader.SkipComponent(SkipHeader: Boolean);
- var
- Flags: TFilerFlags;
- Position: Integer;
- begin
- if SkipHeader then
- begin
- ReadPrefix(Flags, Position);
- ReadStr;
- ReadStr;
- end;
- while not EndOfList do SkipProperty;
- ReadListEnd;
- while not EndOfList do SkipComponent(True);
- ReadListEnd;
- end;
-
- procedure TReader.SetName(Component: TComponent; var Name: string);
- begin
- if Assigned(FOnSetName) then FOnSetName(Self, Component, Name);
- Component.Name := Name;
- end;
-
- { TWriter }
-
- destructor TWriter.Destroy;
- begin
- WriteBuffer;
- inherited Destroy;
- end;
-
- procedure TWriter.AddAncestor(Component: TComponent);
- begin
- FAncestorList.Add(Component);
- end;
-
- procedure TWriter.DefineProperty(const Name: string;
- ReadData: TReaderProc; WriteData: TWriterProc; HasData: Boolean);
- begin
- if HasData then
- begin
- WritePropName(Name);
- WriteData(Self);
- end;
- end;
-
- procedure TWriter.DefineBinaryProperty(const Name: string;
- ReadData, WriteData: TStreamProc; HasData: Boolean);
- begin
- if HasData then
- begin
- WritePropName(Name);
- WriteBinary(WriteData);
- end;
- end;
-
- function TWriter.GetPosition: Longint;
- begin
- Result := FStream.Position + FBufPos;
- end;
-
- procedure TWriter.FlushBuffer;
- begin
- WriteBuffer;
- end;
-
- procedure TWriter.SetPosition(Value: Longint);
- var
- StreamPosition: Longint;
- begin
- StreamPosition := FStream.Position;
- { Only flush the buffer if the repostion is outside the buffer range }
- if (Value < StreamPosition) or (Value > StreamPosition + FBufPos) then
- begin
- WriteBuffer;
- FStream.Position := Value;
- end
- else FBufPos := Value - StreamPosition;
- end;
-
- procedure TWriter.Write(const Buf; Count: Longint); assembler;
- asm
- PUSH ESI
- PUSH EDI
- PUSH EBX
- MOV ESI,EDX
- MOV EBX,ECX
- MOV EDI,EAX
- JMP @@6
- @@1: MOV ECX,[EDI].TWriter.FBufSize
- SUB ECX,[EDI].TWriter.FBufPos
- JA @@2
- MOV EAX,EDI
- CALL TWriter.WriteBuffer
- MOV ECX,[EDI].TWriter.FBufSize
- @@2: CMP ECX,EBX
- JB @@3
- MOV ECX,EBX
- @@3: SUB EBX,ECX
- PUSH EDI
- MOV EAX,[EDI].TWriter.FBuffer
- ADD EAX,[EDI].TWriter.FBufPos
- ADD [EDI].TWriter.FBufPos,ECX
- @@5: MOV EDI,EAX
- MOV EDX,ECX
- SHR ECX,2
- CLD
- REP MOVSD
- MOV ECX,EDX
- AND ECX,3
- REP MOVSB
- POP EDI
- @@6: OR EBX,EBX
- JNE @@1
- POP EBX
- POP EDI
- POP ESI
- end;
-
- procedure TWriter.WriteBinary(WriteData: TStreamProc);
- var
- Stream: TMemoryStream;
- Count: Longint;
- begin
- Stream := TMemoryStream.Create;
- try
- WriteData(Stream);
- WriteValue(vaBinary);
- Count := Stream.Size;
- Write(Count, SizeOf(Count));
- Write(Stream.Memory^, Count);
- finally
- Stream.Free;
- end;
- end;
-
- procedure TWriter.WriteBuffer;
- begin
- FStream.WriteBuffer(FBuffer^, FBufPos);
- FBufPos := 0;
- end;
-
- procedure TWriter.WriteBoolean(Value: Boolean);
- begin
- if Value then
- WriteValue(vaTrue) else
- WriteValue(vaFalse);
- end;
-
- procedure TWriter.WriteChar(Value: Char);
- begin
- WriteString(Value);
- end;
-
- procedure TWriter.WriteCollection(Value: TCollection);
- var
- I: Integer;
- begin
- WriteValue(vaCollection);
- for I := 0 to Value.Count - 1 do
- begin
- WriteListBegin;
- WriteProperties(Value.Items[I]);
- WriteListEnd;
- end;
- WriteListEnd;
- end;
-
- procedure TWriter.WriteComponent(Component: TComponent);
-
- function FindAncestor(const Name: string): TComponent;
- var
- I: Integer;
- begin
- for I := 0 to FAncestorList.Count - 1 do
- begin
- Result := FAncestorList[I];
- if CompareText(Result.Name, Name) = 0 then Exit;
- end;
- Result := nil;
- end;
-
- begin
- Include(Component.FComponentState, csWriting);
- if Assigned(FAncestorList) then
- Ancestor := FindAncestor(Component.Name);
- Component.WriteState(Self);
- Exclude(Component.FComponentState, csWriting);
- end;
-
- procedure TWriter.WriteData(Instance: TComponent);
- var
- PreviousPosition, PropertiesPosition: Longint;
- OldAncestorList: TList;
- OldAncestorPos, OldChildPos: Integer;
- Flags: TFilerFlags;
- begin
- if FBufSize - FBufPos < Length(Instance.ClassName) +
- Length(Instance.Name) + 1+5+3 then WriteBuffer;
- { Prefix + vaInt + integer + 2 end lists }
- PreviousPosition := Position;
- Flags := [];
- if Ancestor <> nil then Include(Flags, ffInherited);
- if (FAncestorList <> nil) and (FAncestorPos < FAncestorList.Count) and
- ((Ancestor = nil) or (FAncestorList[FAncestorPos] <> Ancestor)) then
- Include(Flags, ffChildPos);
- WritePrefix(Flags, FChildPos);
- WriteStr(Instance.ClassName);
- WriteStr(Instance.Name);
- PropertiesPosition := Position;
- if (FAncestorList <> nil) and (FAncestorPos < FAncestorList.Count) then
- begin
- if Ancestor <> nil then Inc(FAncestorPos);
- Inc(FChildPos);
- end;
- WriteProperties(Instance);
- WriteListEnd;
- OldAncestorList := FAncestorList;
- OldAncestorPos := FAncestorPos;
- OldChildPos := FChildPos;
- try
- FAncestorList := nil;
- FAncestorPos := 0;
- FChildPos := 0;
- if not IgnoreChildren then
- try
- if (FAncestor <> nil) and (FAncestor is TComponent) then
- begin
- FAncestorList := TList.Create;
- TComponent(FAncestor).GetChildren(AddAncestor);
- end;
- Instance.GetChildren(WriteComponent);
- finally
- FAncestorList.Free;
- end;
- finally
- FAncestorList := OldAncestorList;
- FAncestorPos := OldAncestorPos;
- FChildPos := OldChildPos;
- end;
- WriteListEnd;
- if (Instance <> Root) and (Flags = [ffInherited]) and
- (Position = PropertiesPosition + (1 + 1)) then { (1 + 1) is two end lists }
- Position := PreviousPosition;
- end;
-
- procedure TWriter.WriteDescendent(Root: TComponent; AAncestor: TComponent);
- begin
- FRootAncestor := AAncestor;
- FAncestor := AAncestor;
- FRoot := Root;
- WriteSignature;
- WriteComponent(Root);
- end;
-
- procedure TWriter.WriteFloat(Value: Extended);
- begin
- WriteValue(vaExtended);
- Write(Value, SizeOf(Extended));
- end;
-
- procedure TWriter.WriteIdent(const Ident: string);
- begin
- if CompareText(Ident, 'False') = 0 then WriteValue(vaFalse) else
- if CompareText(Ident ,'True') = 0 then WriteValue(vaTrue) else
- if CompareText(Ident, 'nil') = 0 then WriteValue(vaNil) else
- begin
- WriteValue(vaIdent);
- WriteStr(Ident);
- end;
- end;
-
- procedure TWriter.WriteInteger(Value: Longint);
- begin
- if (Value >= -128) and (Value <= 127) then
- begin
- WriteValue(vaInt8);
- Write(Value, SizeOf(Shortint));
- end else
- if (Value >= -32768) and (Value <= 32767) then
- begin
- WriteValue(vaInt16);
- Write(Value, SizeOf(Smallint));
- end else
- begin
- WriteValue(vaInt32);
- Write(Value, SizeOf(Longint));
- end;
- end;
-
- procedure TWriter.WriteListBegin;
- begin
- WriteValue(vaList);
- end;
-
- procedure TWriter.WriteListEnd;
- begin
- WriteValue(vaNull);
- end;
-
- procedure TWriter.WritePrefix(Flags: TFilerFlags; AChildPos: Integer);
- var
- Prefix: Byte;
- begin
- if Flags <> [] then
- begin
- Prefix := $F0 or Byte(Flags);
- Write(Prefix, SizeOf(Prefix));
- if ffChildPos in Flags then WriteInteger(AChildPos);
- end;
- end;
-
- procedure TWriter.WriteProperties(Instance: TPersistent);
- var
- I, Count: Integer;
- PropInfo: PPropInfo;
- PropList: PPropList;
- begin
- Count := GetTypeData(Instance.ClassInfo)^.PropCount;
- if Count > 0 then
- begin
- GetMem(PropList, Count * SizeOf(Pointer));
- try
- GetPropInfos(Instance.ClassInfo, PropList);
- for I := 0 to Count - 1 do
- begin
- PropInfo := PropList^[I];
- if IsStoredProp(Instance, PropInfo) then
- WriteProperty(Instance, PropInfo);
- end;
- finally
- FreeMem(PropList, Count * SizeOf(Pointer));
- end;
- end;
- Instance.DefineProperties(Self);
- end;
-
- procedure TWriter.WriteProperty(Instance: TPersistent; PropInfo: Pointer);
- var
- PropType: PTypeInfo;
-
- function AncestorValid: Boolean;
- begin
- Result := (Ancestor <> nil) and ((Instance.ClassType = Ancestor.ClassType) or
- (Instance = Root));
- end;
-
- procedure WritePropPath;
- begin
- WritePropName(PPropInfo(PropInfo)^.Name);
- end;
-
- procedure WriteSet(Value: Longint);
- var
- I: Integer;
- BaseType: PTypeInfo;
- begin
- BaseType := GetTypeData(PropType)^.CompType;
- WriteValue(vaSet);
- for I := 0 to SizeOf(TIntegerSet) * 8 - 1 do
- if I in TIntegerSet(Value) then WriteStr(GetEnumName(BaseType, I));
- WriteStr('');
- end;
-
- procedure WriteIntProp(IntType: PTypeInfo; Value: Longint);
- var
- I: Integer;
- Ident: string;
- begin
- for I := 0 to IntConstList.Count - 1 do
- with TIntConst(IntConstList[I]) do
- if IntType = IntegerType then
- if IntToIdent(Value, Ident) then
- begin
- WriteIdent(Ident);
- Exit;
- end
- else Break;
- WriteInteger(Value);
- end;
-
- procedure WriteCollectionProp(Collection: TCollection);
- var
- SavePropPath: string;
- begin
- WritePropPath;
- SavePropPath := FPropPath;
- try
- FPropPath := '';
- WriteCollection(Collection);
- finally
- FPropPath := SavePropPath;
- end;
- end;
-
- procedure WriteOrdProp;
- var
- Value: Longint;
-
- function IsDefaultValue: Boolean;
- begin
- if AncestorValid then
- Result := Value = GetOrdProp(Ancestor, PropInfo) else
- Result := Value = PPropInfo(PropInfo)^.Default;
- end;
-
- begin
- Value := GetOrdProp(Instance, PropInfo);
- if not IsDefaultValue then
- begin
- WritePropPath;
- case PropType^.Kind of
- tkInteger:
- WriteIntProp(PPropInfo(PropInfo)^.PropType, Value);
- tkChar:
- WriteChar(Chr(Value));
- tkSet:
- WriteSet(Value);
- tkEnumeration:
- WriteIdent(GetEnumName(PropType, Value));
- end;
- end;
- end;
-
- procedure WriteFloatProp;
- var
- Value: Extended;
-
- function IsDefaultValue: Boolean;
- begin
- if AncestorValid then
- Result := Value = GetFloatProp(Ancestor, PropInfo) else
- Result := Value = 0;
- end;
-
- begin
- Value := GetFloatProp(Instance, PropInfo);
- if not IsDefaultValue then
- begin
- WritePropPath;
- WriteFloat(Value);
- end;
- end;
-
- procedure WriteStrProp;
- var
- Value: string;
-
- function IsDefault: Boolean;
- begin
- if AncestorValid then
- Result := Value = GetStrProp(Ancestor, PropInfo) else
- Result := Value = '';
- end;
-
- begin
- Value := GetStrProp(Instance, PropInfo);
- if not IsDefault then
- begin
- WritePropPath;
- WriteString(Value);
- end;
- end;
-
- procedure WriteObjectProp;
- var
- Value: TObject;
- OldAncestor: TPersistent;
- SavePropPath, ComponentValue: string;
-
- function IsDefault: Boolean;
- var
- AncestorValue: TObject;
- begin
- AncestorValue := nil;
- if AncestorValid then
- begin
- AncestorValue := TObject(GetOrdProp(Ancestor, PropInfo));
- if (AncestorValue <> nil) and (TComponent(AncestorValue).Owner = FRootAncestor) and
- (Value <> nil) and (TComponent(Value).Owner = Root) and
- (CompareText(TComponent(AncestorValue).Name, TComponent(Value).Name) = 0) then
- AncestorValue := Value;
- end;
- Result := Value = AncestorValue;
- end;
-
- function GetComponentValue(Component: TComponent): string;
- begin
- if Component.Owner = Root then
- Result := Component.Name
- else if Component.Owner <> nil then
- Result := Component.Owner.Name + '.' + Component.Name
- else Result := '';
- end;
-
- begin
- Value := TObject(GetOrdProp(Instance, PropInfo));
- if (Value = nil) and not IsDefault then
- begin
- WritePropPath;
- WriteValue(vaNil);
- end
- else if Value is TPersistent then
- if Value is TComponent then
- begin
- if not IsDefault then
- begin
- ComponentValue := GetComponentValue(TComponent(Value));
- if ComponentValue <> '' then
- begin
- WritePropPath;
- WriteIdent(ComponentValue);
- end
- end
- end else if Value is TCollection then
- begin
- if not AncestorValid or
- not CollectionsEqual(TCollection(Value),
- TCollection(GetOrdProp(Ancestor, PropInfo))) then
- WriteCollectionProp(TCollection(Value));
- end else
- begin
- OldAncestor := Ancestor;
- SavePropPath := FPropPath;
- FPropPath := FPropPath + PPropInfo(PropInfo)^.Name + '.';
- if AncestorValid then
- Ancestor := TPersistent(GetOrdProp(Ancestor, PropInfo));
- WriteProperties(TPersistent(Value));
- Ancestor := OldAncestor;
- FPropPath := SavePropPath;
- end
- end;
-
- procedure WriteMethodProp;
- var
- Value: TMethod;
-
- function IsDefaultValue: Boolean;
- var
- DefaultCode: Pointer;
- begin
- DefaultCode := nil;
- if AncestorValid then DefaultCode := GetMethodProp(Ancestor, PropInfo).Code;
- Result := (Value.Code = DefaultCode) or
- ((Value.Code <> nil) and (Root.MethodName(Value.Code) = ''));
- end;
-
- begin
- Value := GetMethodProp(Instance, PropInfo);
- if not IsDefaultValue then
- begin
- WritePropPath;
- if Value.Code = nil then
- WriteValue(vaNil) else
- WriteIdent(Root.MethodName(Value.Code));
- end;
- end;
-
- begin
- if PPropInfo(PropInfo)^.SetProc <> nil then
- begin
- PropType := PPropInfo(PropInfo)^.PropType;
- case PropType^.Kind of
- tkInteger, tkChar, tkEnumeration, tkSet: WriteOrdProp;
- tkFloat: WriteFloatProp;
- tkString, tkLString: WriteStrProp;
- tkClass: WriteObjectProp;
- tkMethod: WriteMethodProp;
- end;
- end;
- end;
-
- procedure TWriter.WritePropName(const PropName: string);
- begin
- WriteStr(FPropPath + PropName);
- end;
-
- procedure TWriter.WriteRootComponent(Root: TComponent);
- begin
- WriteDescendent(Root, nil);
- end;
-
- procedure TWriter.WriteSignature;
- begin
- Write(FilerSignature, SizeOf(FilerSignature));
- end;
-
- procedure TWriter.WriteStr(const Value: string);
- var
- L: Integer;
- begin
- L := Length(Value);
- if L > 255 then L := 255;
- Write(L, SizeOf(Byte));
- Write(Value[1], L);
- end;
-
- procedure TWriter.WriteString(const Value: string);
- var
- L: Integer;
- begin
- L := Length(Value);
- if L <= 255 then
- begin
- WriteValue(vaString);
- Write(L, SizeOf(Byte));
- end else
- begin
- WriteValue(vaLString);
- Write(L, SizeOf(Integer));
- end;
- Write(Pointer(Value)^, L);
- end;
-
- procedure TWriter.WriteValue(Value: TValueType);
- begin
- Write(Value, SizeOf(Value));
- end;
-
- { TParser }
-
- const
- ParseBufSize = 4096;
-
- procedure BinToHex(Buffer, Text: PChar; BufSize: Integer); assembler;
- asm
- PUSH ESI
- PUSH EDI
- MOV ESI,EAX
- MOV EDI,EDX
- MOV EDX,0
- JMP @@1
- @@0: DB '0123456789ABCDEF'
- @@1: LODSB
- MOV DL,AL
- AND DL,0FH
- MOV AH,@@0.Byte[EDX]
- MOV DL,AL
- SHR DL,4
- MOV AL,@@0.Byte[EDX]
- STOSW
- DEC ECX
- JNE @@1
- POP EDI
- POP ESI
- end;
-
- function HexToBin(Text, Buffer: PChar; BufSize: Integer): Integer; assembler;
- asm
- PUSH ESI
- PUSH EDI
- PUSH EBX
- MOV ESI,EAX
- MOV EDI,EDX
- MOV EBX,EDX
- MOV EDX,0
- JMP @@1
- @@0: DB 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
- DB -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
- DB -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
- DB -1,10,11,12,13,14,15
- @@1: LODSW
- CMP AL,'0'
- JB @@2
- CMP AL,'f'
- JA @@2
- MOV DL,AL
- MOV AL,@@0.Byte[EDX-'0']
- CMP AL,-1
- JE @@2
- SHL AL,4
- CMP AH,'0'
- JB @@2
- CMP AH,'f'
- JA @@2
- MOV DL,AH
- MOV AH,@@0.Byte[EDX-'0']
- CMP AH,-1
- JE @@2
- OR AL,AH
- STOSB
- DEC ECX
- JNE @@1
- @@2: MOV EAX,EDI
- SUB EAX,EBX
- POP EBX
- POP EDI
- POP ESI
- end;
-
- constructor TParser.Create(Stream: TStream);
- begin
- FStream := Stream;
- GetMem(FBuffer, ParseBufSize);
- FBuffer[0] := #0;
- FBufPtr := FBuffer;
- FBufEnd := FBuffer + ParseBufSize;
- FSourcePtr := FBuffer;
- FSourceEnd := FBuffer;
- FTokenPtr := FBuffer;
- FSourceLine := 1;
- NextToken;
- end;
-
- destructor TParser.Destroy;
- begin
- if FBuffer <> nil then
- begin
- FStream.Seek(Longint(FTokenPtr) - Longint(FBufPtr), 1);
- FreeMem(FBuffer, ParseBufSize);
- end;
- end;
-
- procedure TParser.CheckToken(T: Char);
- begin
- if Token <> T then
- case T of
- toSymbol:
- Error(SIdentifierExpected);
- toString:
- Error(SStringExpected);
- toInteger, toFloat:
- Error(SNumberExpected);
- else
- ErrorFmt(SCharExpected, [T]);
- end;
- end;
-
- procedure TParser.CheckTokenSymbol(const S: string);
- begin
- if not TokenSymbolIs(S) then ErrorFmt(SSymbolExpected, [S]);
- end;
-
- procedure TParser.Error(Ident: Integer);
- begin
- ErrorStr(LoadStr(Ident));
- end;
-
- procedure TParser.ErrorFmt(Ident: Integer; const Args: array of const);
- begin
- ErrorStr(FmtLoadStr(Ident, Args));
- end;
-
- procedure TParser.ErrorStr(const Message: string);
- begin
- raise EParserError.CreateResFmt(SParseError, [Message, FSourceLine]);
- end;
-
- procedure TParser.HexToBinary(Stream: TStream);
- var
- Count: Integer;
- Buffer: array[0..255] of Char;
- begin
- SkipBlanks;
- while FSourcePtr^ <> '}' do
- begin
- Count := HexToBin(FSourcePtr, Buffer, SizeOf(Buffer));
- if Count = 0 then Error(SInvalidBinary);
- Stream.Write(Buffer, Count);
- Inc(FSourcePtr, Count * 2);
- SkipBlanks;
- end;
- NextToken;
- end;
-
- function TParser.NextToken: Char;
- var
- I: Integer;
- P, S: PChar;
- begin
- SkipBlanks;
- P := FSourcePtr;
- FTokenPtr := P;
- case P^ of
- 'A'..'Z', 'a'..'z', '_':
- begin
- Inc(P);
- while P^ in ['A'..'Z', 'a'..'z', '0'..'9', '_'] do Inc(P);
- Result := toSymbol;
- end;
- '#', '''':
- begin
- S := P;
- while True do
- case P^ of
- '#':
- begin
- Inc(P);
- I := 0;
- while P^ in ['0'..'9'] do
- begin
- I := I * 10 + (Ord(P^) - Ord('0'));
- Inc(P);
- end;
- S^ := Chr(I);
- Inc(S);
- end;
- '''':
- begin
- Inc(P);
- while True do
- begin
- case P^ of
- #0, #10, #13:
- Error(SInvalidString);
- '''':
- begin
- Inc(P);
- if P^ <> '''' then Break;
- end;
- end;
- S^ := P^;
- Inc(S);
- Inc(P);
- end;
- end;
- else
- Break;
- end;
- FStringPtr := S;
- Result := toString;
- end;
- '$':
- begin
- Inc(P);
- while P^ in ['0'..'9', 'A'..'F', 'a'..'f'] do Inc(P);
- Result := toInteger;
- end;
- '-', '0'..'9':
- begin
- Inc(P);
- while P^ in ['0'..'9'] do Inc(P);
- Result := toInteger;
- while P^ in ['0'..'9', '.', 'e', 'E', '+', '-'] do
- begin
- Inc(P);
- Result := toFloat;
- end;
- end;
- else
- Result := P^;
- if Result <> toEOF then Inc(P);
- end;
- FSourcePtr := P;
- FToken := Result;
- end;
-
- procedure TParser.ReadBuffer;
- var
- Count: Integer;
- begin
- Inc(FOrigin, FSourcePtr - FBuffer);
- FSourceEnd[0] := FSaveChar;
- Count := FBufPtr - FSourcePtr;
- if Count <> 0 then Move(FSourcePtr[0], FBuffer[0], Count);
- FBufPtr := FBuffer + Count;
- Inc(FBufPtr, FStream.Read(FBufPtr[0], FBufEnd - FBufPtr));
- FSourcePtr := FBuffer;
- FSourceEnd := FBufPtr;
- if FSourceEnd = FBufEnd then
- begin
- FSourceEnd := LineStart(FBuffer, FSourceEnd - 1);
- if FSourceEnd = FBuffer then Error(SLineTooLong);
- end;
- FSaveChar := FSourceEnd[0];
- FSourceEnd[0] := #0;
- end;
-
- procedure TParser.SkipBlanks;
- begin
- while True do
- begin
- case FSourcePtr^ of
- #0:
- begin
- ReadBuffer;
- if FSourcePtr^ = #0 then Exit;
- Continue;
- end;
- #10:
- Inc(FSourceLine);
- #33..#255:
- Exit;
- end;
- Inc(FSourcePtr);
- end;
- end;
-
- function TParser.SourcePos: Longint;
- begin
- Result := FOrigin + (FTokenPtr - FBuffer);
- end;
-
- function TParser.TokenFloat: Extended;
- begin
- Result := StrToFloat(TokenString);
- end;
-
- function TParser.TokenInt: Longint;
- begin
- Result := StrToInt(TokenString);
- end;
-
- function TParser.TokenString: string;
- var
- L: Integer;
- begin
- if FToken = toString then
- L := FStringPtr - FTokenPtr else
- L := FSourcePtr - FTokenPtr;
- SetString(Result, FTokenPtr, L);
- end;
-
- function TParser.TokenSymbolIs(const S: string): Boolean;
- begin
- Result := (Token = toSymbol) and (CompareText(S, TokenString) = 0);
- end;
-
- function TParser.TokenComponentIdent: String;
- var
- P: PChar;
- begin
- CheckToken(toSymbol);
- P := FSourcePtr;
- while P^ = '.' do
- begin
- Inc(P);
- if not (P^ in ['A'..'Z', 'a'..'z', '_']) then
- Error(SIdentifierExpected);
- repeat
- Inc(P)
- until not (P^ in ['A'..'Z', 'a'..'z', '0'..'9', '_']);
- end;
- FSourcePtr := P;
- Result := TokenString;
- end;
-
- { Binary to text conversion }
-
- procedure ObjectBinaryToText(Input, Output: TStream);
- var
- NestingLevel: Integer;
- SaveSeparator: Char;
- Reader: TReader;
- Writer: TWriter;
-
- procedure WriteIndent;
- const
- Blanks: array[0..1] of Char = ' ';
- var
- I: Integer;
- begin
- for I := 1 to NestingLevel do Writer.Write(Blanks, SizeOf(Blanks));
- end;
-
- procedure WriteStr(const S: string);
- begin
- Writer.Write(S[1], Length(S));
- end;
-
- procedure NewLine;
- begin
- WriteStr(#13#10);
- WriteIndent;
- end;
-
- procedure ConvertValue; forward;
-
- procedure ConvertHeader;
- var
- ClassName, ObjectName: string;
- Flags: TFilerFlags;
- Position: Integer;
- begin
- Reader.ReadPrefix(Flags, Position);
- ClassName := Reader.ReadStr;
- ObjectName := Reader.ReadStr;
- WriteIndent;
- if ffInherited in Flags then
- WriteStr('inherited ')
- else
- WriteStr('object ');
- if ObjectName <> '' then
- begin
- WriteStr(ObjectName);
- WriteStr(': ');
- end;
- WriteStr(ClassName);
- if ffChildPos in Flags then
- begin
- WriteStr(' [');
- WriteStr(IntToStr(Position));
- WriteStr(']');
- end;
- WriteStr(#13#10);
- end;
-
- procedure ConvertBinary;
- const
- BytesPerLine = 32;
- var
- MultiLine: Boolean;
- I: Integer;
- Count: Longint;
- Buffer: array[0..BytesPerLine - 1] of Char;
- Text: array[0..BytesPerLine * 2 - 1] of Char;
- begin
- Reader.ReadValue;
- WriteStr('{');
- Inc(NestingLevel);
- Reader.Read(Count, SizeOf(Count));
- MultiLine := Count >= BytesPerLine;
- while Count > 0 do
- begin
- if MultiLine then NewLine;
- if Count >= 32 then I := 32 else I := Count;
- Reader.Read(Buffer, I);
- BinToHex(Buffer, Text, I);
- Writer.Write(Text, I * 2);
- Dec(Count, I);
- end;
- Dec(NestingLevel);
- WriteStr('}');
- end;
-
- procedure ConvertProperty; forward;
-
- procedure ConvertValue;
- var
- I, J, L: Integer;
- S: string;
- begin
- case Reader.NextValue of
- vaList:
- begin
- Reader.ReadValue;
- WriteStr('(');
- Inc(NestingLevel);
- while not Reader.EndOfList do
- begin
- NewLine;
- ConvertValue;
- end;
- Reader.ReadListEnd;
- Dec(NestingLevel);
- WriteStr(')');
- end;
- vaInt8, vaInt16, vaInt32:
- WriteStr(IntToStr(Reader.ReadInteger));
- vaExtended:
- WriteStr(FloatToStr(Reader.ReadFloat));
- vaString, vaLString:
- begin
- S := Reader.ReadString;
- L := Length(S);
- if L = 0 then WriteStr('''''') else
- begin
- I := 1;
- repeat
- if (S[I] >= ' ') and (S[I] <> '''') then
- begin
- J := I;
- repeat Inc(I) until (I > L) or (S[I] < ' ') or (S[I] = '''');
- WriteStr('''');
- Writer.Write(S[J], I - J);
- WriteStr('''');
- end else
- begin
- WriteStr('#');
- WriteStr(IntToStr(Ord(S[I])));
- Inc(I);
- end;
- until I > L;
- end;
- end;
- vaIdent, vaFalse, vaTrue, vaNil:
- WriteStr(Reader.ReadIdent);
- vaBinary:
- ConvertBinary;
- vaSet:
- begin
- Reader.ReadValue;
- WriteStr('[');
- I := 0;
- while True do
- begin
- S := Reader.ReadStr;
- if S = '' then Break;
- if I > 0 then WriteStr(', ');
- WriteStr(S);
- Inc(I);
- end;
- WriteStr(']');
- end;
- vaCollection:
- begin
- Reader.ReadValue;
- WriteStr('<');
- Inc(NestingLevel);
- while not Reader.EndOfList do
- begin
- NewLine;
- WriteStr('item');
- if Reader.NextValue in [vaInt8, vaInt16, vaInt32] then
- begin
- WriteStr(' [');
- ConvertValue;
- WriteStr(']');
- end;
- WriteStr(#13#10);
- Reader.CheckValue(vaList);
- Inc(NestingLevel);
- while not Reader.EndOfList do ConvertProperty;
- Reader.ReadListEnd;
- Dec(NestingLevel);
- WriteIndent;
- WriteStr('end');
- end;
- Reader.ReadListEnd;
- Dec(NestingLevel);
- WriteStr('>');
- end;
- end;
- end;
-
- procedure ConvertProperty;
- begin
- WriteIndent;
- WriteStr(Reader.ReadStr);
- WriteStr(' = ');
- ConvertValue;
- WriteStr(#13#10);
- end;
-
- procedure ConvertObject;
- begin
- ConvertHeader;
- Inc(NestingLevel);
- while not Reader.EndOfList do ConvertProperty;
- Reader.ReadListEnd;
- while not Reader.EndOfList do ConvertObject;
- Reader.ReadListEnd;
- Dec(NestingLevel);
- WriteIndent;
- WriteStr('end'#13#10);
- end;
-
- begin
- NestingLevel := 0;
- Reader := TReader.Create(Input, 4096);
- SaveSeparator := DecimalSeparator;
- DecimalSeparator := '.';
- try
- Writer := TWriter.Create(Output, 4096);
- try
- Reader.ReadSignature;
- ConvertObject;
- finally
- Writer.Free;
- end;
- finally
- DecimalSeparator := SaveSeparator;
- Reader.Free;
- end;
- end;
-
- { Text to binary conversion }
-
- procedure ObjectTextToBinary(Input, Output: TStream);
- var
- SaveSeparator: Char;
- Parser: TParser;
- Writer: TWriter;
-
- function ConvertOrderModifier: Integer;
- begin
- Result := -1;
- if Parser.Token = '[' then
- begin
- Parser.NextToken;
- Parser.CheckToken(toInteger);
- Result := Parser.TokenInt;
- Parser.NextToken;
- Parser.CheckToken(']');
- Parser.NextToken;
- end;
- end;
-
- procedure ConvertHeader(IsInherited: Boolean);
- var
- ClassName, ObjectName: string;
- Flags: TFilerFlags;
- Position: Integer;
- begin
- Parser.CheckToken(toSymbol);
- ClassName := Parser.TokenString;
- ObjectName := '';
- if Parser.NextToken = ':' then
- begin
- Parser.NextToken;
- Parser.CheckToken(toSymbol);
- ObjectName := ClassName;
- ClassName := Parser.TokenString;
- Parser.NextToken;
- end;
- Flags := [];
- Position := ConvertOrderModifier;
- if IsInherited then
- Include(Flags, ffInherited);
- if Position > 0 then
- Include(Flags, ffChildPos);
- Writer.WritePrefix(Flags, Position);
- Writer.WriteStr(ClassName);
- Writer.WriteStr(ObjectName);
- end;
-
- procedure ConvertProperty; forward;
-
- procedure ConvertValue;
- var
- Order: Integer;
- begin
- case Parser.Token of
- toSymbol:
- Writer.WriteIdent(Parser.TokenComponentIdent);
- toString:
- Writer.WriteString(Parser.TokenString);
- toInteger:
- Writer.WriteInteger(Parser.TokenInt);
- toFloat:
- Writer.WriteFloat(Parser.TokenFloat);
- '[':
- begin
- Parser.NextToken;
- Writer.WriteValue(vaSet);
- if Parser.Token <> ']' then
- while True do
- begin
- Parser.CheckToken(toSymbol);
- Writer.WriteStr(Parser.TokenString);
- if Parser.NextToken = ']' then Break;
- Parser.CheckToken(',');
- Parser.NextToken;
- end;
- Writer.WriteStr('');
- end;
- '(':
- begin
- Parser.NextToken;
- Writer.WriteListBegin;
- while Parser.Token <> ')' do ConvertValue;
- Writer.WriteListEnd;
- end;
- '{':
- Writer.WriteBinary(Parser.HexToBinary);
- '<':
- begin
- Parser.NextToken;
- Writer.WriteValue(vaCollection);
- while Parser.Token <> '>' do
- begin
- Parser.CheckTokenSymbol('item');
- Parser.NextToken;
- Order := ConvertOrderModifier;
- if Order <> -1 then Writer.WriteInteger(Order);
- Writer.WriteListBegin;
- while not Parser.TokenSymbolIs('end') do ConvertProperty;
- Writer.WriteListEnd;
- Parser.NextToken;
- end;
- Writer.WriteListEnd;
- end;
- else
- Parser.Error(SInvalidProperty);
- end;
- Parser.NextToken;
- end;
-
- procedure ConvertProperty;
- var
- PropName: string;
- begin
- Parser.CheckToken(toSymbol);
- PropName := Parser.TokenString;
- Parser.NextToken;
- while Parser.Token = '.' do
- begin
- Parser.NextToken;
- Parser.CheckToken(toSymbol);
- PropName := PropName + '.' + Parser.TokenString;
- Parser.NextToken;
- end;
- Writer.WriteStr(PropName);
- Parser.CheckToken('=');
- Parser.NextToken;
- ConvertValue;
- end;
-
- procedure ConvertObject;
- var
- InheritedObject: Boolean;
- begin
- InheritedObject := False;
- if Parser.TokenSymbolIs('INHERITED') then
- InheritedObject := True else
- Parser.CheckTokenSymbol('OBJECT');
- Parser.NextToken;
- ConvertHeader(InheritedObject);
- while not Parser.TokenSymbolIs('END') and
- not Parser.TokenSymbolIs('OBJECT') and
- not Parser.TokenSymbolIs('INHERITED') do ConvertProperty;
- Writer.WriteListEnd;
- while not Parser.TokenSymbolIs('END') do ConvertObject;
- Writer.WriteListEnd;
- Parser.NextToken;
- end;
-
- begin
- Parser := TParser.Create(Input);
- SaveSeparator := DecimalSeparator;
- DecimalSeparator := '.';
- try
- Writer := TWriter.Create(Output, 4096);
- try
- Writer.WriteSignature;
- ConvertObject;
- finally
- Writer.Free;
- end;
- finally
- DecimalSeparator := SaveSeparator;
- Parser.Free;
- end;
- end;
-
- { Resource to text conversion }
-
- procedure ObjectResourceToText(Input, Output: TStream);
- begin
- Input.ReadResHeader;
- ObjectBinaryToText(Input, Output);
- end;
-
- { Text to resource conversion }
-
- procedure ObjectTextToResource(Input, Output: TStream);
- var
- Len: Byte;
- Tmp: Longint;
- MemoryStream: TMemoryStream;
- MemorySize: Longint;
- Header: array[0..79] of Char;
- begin
- MemoryStream := TMemoryStream.Create;
- try
- ObjectTextToBinary(Input, MemoryStream);
- MemorySize := MemoryStream.Size;
- FillChar(Header, SizeOf(Header), 0);
- MemoryStream.Position := SizeOf(Longint); { Skip header }
- MemoryStream.Read(Len, 1);
-
- { Skip over object prefix if it is present }
- if Len and $F0 = $F0 then
- begin
- if ffChildPos in TFilerFlags((Len and $F0)) then
- begin
- MemoryStream.Read(Len, 1);
- case TValueType(Len) of
- vaInt8: Len := 1;
- vaInt16: Len := 2;
- vaInt32: Len := 4;
- end;
- MemoryStream.Read(Tmp, Len);
- end;
- MemoryStream.Read(Len, 1);
- end;
-
- MemoryStream.Read(Header[3], Len);
- StrUpper(@Header[3]);
- Byte((@Header[0])^) := $FF;
- Word((@Header[1])^) := 10;
- Word((@Header[Len + 4])^) := $1030;
- Longint((@Header[Len + 6])^) := MemorySize;
- Output.Write(Header, Len + 10);
- Output.Write(MemoryStream.Memory^, MemorySize);
- finally
- MemoryStream.Free;
- end;
- end;
-
- { Thread management routines }
-
- const
- CM_EXECPROC = $8FFF;
-
- type
- PRaiseFrame = ^TRaiseFrame;
- TRaiseFrame = record
- NextRaise: PRaiseFrame;
- ExceptAddr: Pointer;
- ExceptObject: TObject;
- ExceptionRecord: PExceptionRecord;
- end;
-
- var
- ThreadWindow: HWND;
- ThreadCount: Integer;
-
- function ThreadWndProc(Window: HWND; Message, wParam, lParam: Longint): Longint; stdcall;
- begin
- case Message of
- CM_EXECPROC:
- with TThread(lParam) do
- begin
- Result := 0;
- try
- FSynchronizeException := nil;
- FMethod;
- except
- if RaiseList <> nil then
- begin
- FSynchronizeException := PRaiseFrame(RaiseList)^.ExceptObject;
- PRaiseFrame(RaiseList)^.ExceptObject := nil;
- end;
- end;
- end;
- else
- Result := DefWindowProc(Window, Message, wParam, lParam);
- end;
- end;
-
- var
- ThreadWindowClass: TWndClass = (
- style: 0;
- lpfnWndProc: @ThreadWndProc;
- cbClsExtra: 0;
- cbWndExtra: 0;
- hInstance: 0;
- hIcon: 0;
- hCursor: 0;
- hbrBackground: 0;
- lpszMenuName: nil;
- lpszClassName: 'TThreadWindow');
-
- procedure AddThread;
-
- function AllocateWindow: HWND;
- var
- TempClass: TWndClass;
- ClassRegistered: Boolean;
- begin
- ThreadWindowClass.hInstance := HInstance;
- ClassRegistered := GetClassInfo(HInstance, ThreadWindowClass.lpszClassName,
- TempClass);
- if not ClassRegistered or (TempClass.lpfnWndProc <> @ThreadWndProc) then
- begin
- if ClassRegistered then
- Windows.UnregisterClass(ThreadWindowClass.lpszClassName, HInstance);
- Windows.RegisterClass(ThreadWindowClass);
- end;
- Result := CreateWindow(ThreadWindowClass.lpszClassName, '', 0,
- 0, 0, 0, 0, 0, 0, HInstance, nil);
- end;
-
- begin
- if ThreadCount = 0 then
- ThreadWindow := AllocateWindow;
- Inc(ThreadCount);
- end;
-
- procedure RemoveThread;
- begin
- Dec(ThreadCount);
- if ThreadCount = 0 then DestroyWindow(ThreadWindow);
- end;
-
- { TThread }
-
- function ThreadProc(Thread: TThread): Integer;
- var
- FreeThread: Boolean;
- begin
- Thread.Execute;
- FreeThread := Thread.FFreeOnTerminate;
- Result := Thread.FReturnValue;
- Thread.FFinished := True;
- Thread.DoTerminate;
- if FreeThread then Thread.Free;
- EndThread(Result);
- end;
-
- constructor TThread.Create(CreateSuspended: Boolean);
- var
- Flags: Integer;
- begin
- inherited Create;
- AddThread;
- FSuspended := CreateSuspended;
- Flags := 0;
- if CreateSuspended then Flags := CREATE_SUSPENDED;
- FHandle := BeginThread(nil, 0, @ThreadProc, Pointer(Self), Flags, FThreadID);
- end;
-
- destructor TThread.Destroy;
- begin
- if not FFinished and not Suspended then
- begin
- Terminate;
- WaitFor;
- end;
- if FHandle <> 0 then CloseHandle(FHandle);
- inherited Destroy;
- RemoveThread;
- end;
-
- procedure TThread.CallOnTerminate;
- begin
- FOnTerminate(Self);
- end;
-
- procedure TThread.DoTerminate;
- begin
- if Assigned(FOnTerminate) then Synchronize(CallOnTerminate);
- end;
-
- const
- Priorities: array [TThreadPriority] of Integer =
- (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL,
- THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL,
- THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL);
-
- function TThread.GetPriority: TThreadPriority;
- var
- P: Integer;
- I: TThreadPriority;
- begin
- P := GetThreadPriority(FHandle);
- Result := tpNormal;
- for I := Low(TThreadPriority) to High(TThreadPriority) do
- if Priorities[I] = P then Result := I;
- end;
-
- procedure TThread.SetPriority(Value: TThreadPriority);
- begin
- SetThreadPriority(FHandle, Priorities[Value]);
- end;
-
- procedure TThread.Synchronize(Method: TThreadMethod);
- begin
- if FMainThreadWaiting then
- raise EThread.CreateRes(SMainThreadWaiting);
- FSynchronizeException := nil;
- FMethod := Method;
- SendMessage(ThreadWindow, CM_EXECPROC, 0, Longint(Self));
- if Assigned(FSynchronizeException) then raise FSynchronizeException;
- end;
-
- procedure TThread.SetSuspended(Value: Boolean);
- begin
- if Value <> FSuspended then
- if Value then
- Suspend else
- Resume;
- end;
-
- procedure TThread.Suspend;
- begin
- FSuspended := True;
- SuspendThread(FHandle);
- end;
-
- procedure TThread.Resume;
- begin
- if ResumeThread(FHandle) = 1 then FSuspended := False;
- end;
-
- procedure TThread.Terminate;
- begin
- FTerminated := True;
- end;
-
- function TThread.WaitFor: Integer;
- begin
- if GetCurrentThreadID = MainThreadID then FMainThreadWaiting := True;
- WaitForSingleObject(FHandle, INFINITE);
- GetExitCodeThread(FHandle, Result);
- end;
-
- { TComponent }
-
- constructor TComponent.Create(AOwner: TComponent);
- begin
- FComponentStyle := [csInheritable];
- if AOwner <> nil then AOwner.InsertComponent(Self);
- end;
-
- destructor TComponent.Destroy;
- var
- I: Integer;
- begin
- if FFreeNotifies <> nil then
- begin
- for I := 0 to FFreeNotifies.Count - 1 do
- TComponent(FFreeNotifies[I]).Notification(Self, opRemove);
- FFreeNotifies.Free;
- FFreeNotifies := nil;
- end;
- Destroying;
- DestroyComponents;
- if FOwner <> nil then FOwner.RemoveComponent(Self);
- end;
-
- procedure TComponent.FreeNotification(AComponent: TComponent);
- begin
- if (Owner = nil) or (AComponent.Owner <> Owner) then
- begin
- if not Assigned(FFreeNotifies) then FFreeNotifies := TList.Create;
- if FFreeNotifies.IndexOf(AComponent) < 0 then
- begin
- FFreeNotifies.Add(AComponent);
- AComponent.FreeNotification(Self);
- end;
- end;
- end;
-
- procedure TComponent.ReadLeft(Reader: TReader);
- begin
- LongRec(FDesignInfo).Lo := Reader.ReadInteger;
- end;
-
- procedure TComponent.ReadTop(Reader: TReader);
- begin
- LongRec(FDesignInfo).Hi := Reader.ReadInteger;
- end;
-
- procedure TComponent.WriteLeft(Writer: TWriter);
- begin
- Writer.WriteInteger(LongRec(FDesignInfo).Lo);
- end;
-
- procedure TComponent.WriteTop(Writer: TWriter);
- begin
- Writer.WriteInteger(LongRec(FDesignInfo).Hi);
- end;
-
- procedure TComponent.Insert(AComponent: TComponent);
- begin
- if FComponents = nil then FComponents := TList.Create;
- FComponents.Add(AComponent);
- AComponent.FOwner := Self;
- end;
-
- procedure TComponent.Remove(AComponent: TComponent);
- begin
- AComponent.FOwner := nil;
- FComponents.Remove(AComponent);
- if FComponents.Count = 0 then
- begin
- FComponents.Free;
- FComponents := nil;
- end;
- end;
-
- procedure TComponent.InsertComponent(AComponent: TComponent);
- begin
- ValidateRename(AComponent, '', AComponent.FName);
- Insert(AComponent);
- AComponent.SetReference(True);
- if csDesigning in ComponentState then
- AComponent.SetDesigning(True);
- Notification(AComponent, opInsert);
- end;
-
- procedure TComponent.RemoveComponent(AComponent: TComponent);
- begin
- Notification(AComponent, opRemove);
- AComponent.SetReference(False);
- Remove(AComponent);
- AComponent.SetDesigning(False);
- ValidateRename(AComponent, AComponent.FName, '');
- end;
-
- procedure TComponent.DestroyComponents;
- var
- Instance: TComponent;
- begin
- while FComponents <> nil do
- begin
- Instance := FComponents.Last;
- Remove(Instance);
- Instance.Destroy;
- end;
- end;
-
- procedure TComponent.Destroying;
- var
- I: Integer;
- begin
- if not (csDestroying in FComponentState) then
- begin
- Include(FComponentState, csDestroying);
- if FComponents <> nil then
- for I := 0 to FComponents.Count - 1 do
- TComponent(FComponents[I]).Destroying;
- end;
- end;
-
- procedure TComponent.Notification(AComponent: TComponent;
- Operation: TOperation);
- var
- I: Integer;
- begin
- if (FFreeNotifies <> nil) and (Operation = opRemove) then
- begin
- FFreeNotifies.Remove(AComponent);
- if FFreeNotifies.Count = 0 then
- begin
- FFreeNotifies.Free;
- FFreeNotifies := nil;
- end;
- end;
- if FComponents <> nil then
- for I := 0 to FComponents.Count - 1 do
- TComponent(FComponents[I]).Notification(AComponent, Operation);
- end;
-
- procedure TComponent.DefineProperties(Filer: TFiler);
- var
- Ancestor: TComponent;
-
- function DoWriteLeft: Boolean;
- begin
- if Ancestor <> nil then
- Result := LongRec(FDesignInfo).Lo <> LongRec(Ancestor.FDesignInfo).Lo
- else
- Result := LongRec(FDesignInfo).Lo <> 0;
- end;
-
- function DoWriteTop: Boolean;
- begin
- if Ancestor <> nil then
- Result := LongRec(FDesignInfo).Hi <> LongRec(Ancestor.FDesignInfo).Hi
- else
- Result := LongRec(FDesignInfo).Hi <> 0;
- end;
-
- begin
- Ancestor := TComponent(Filer.Ancestor);
- Filer.DefineProperty('Left', ReadLeft, WriteLeft, DoWriteLeft);
- Filer.DefineProperty('Top', ReadTop, WriteTop, DoWriteTop);
- end;
-
- function TComponent.HasParent: Boolean;
- begin
- Result := False;
- end;
-
- procedure TComponent.GetChildren(Proc: TGetChildProc);
- begin
- end;
-
- function TComponent.GetChildOwner: TComponent;
- begin
- Result := nil;
- end;
-
- function TComponent.GetChildParent: TComponent;
- begin
- Result := Self;
- end;
-
- procedure TComponent.SetChildOrder(Child: TComponent; Order: Integer);
- begin
- end;
-
- function TComponent.GetParentComponent: TComponent;
- begin
- Result := nil;
- end;
-
- procedure TComponent.SetParentComponent(Value: TComponent);
- begin
- end;
-
- procedure TComponent.Updating;
- begin
- Include(FComponentState, csUpdating);
- end;
-
- procedure TComponent.Updated;
- begin
- Exclude(FComponentState, csUpdating);
- end;
-
- procedure TComponent.Loaded;
- begin
- Exclude(FComponentState, csLoading);
- end;
-
- procedure TComponent.ReadState(Reader: TReader);
- begin
- Reader.ReadData(Self);
- end;
-
- procedure TComponent.WriteState(Writer: TWriter);
- begin
- Writer.WriteData(Self);
- end;
-
- procedure TComponent.ValidateRename(AComponent: TComponent;
- const CurName, NewName: string);
- begin
- if (AComponent <> nil) and (CompareText(CurName, NewName) <> 0) and
- (FindComponent(NewName) <> nil) then
- raise EComponentError.CreateResFmt(SDuplicateName, [NewName]);
- if (csDesigning in ComponentState) and (Owner <> nil) then
- Owner.ValidateRename(AComponent, CurName, NewName);
- end;
-
- function TComponent.FindComponent(const AName: string): TComponent;
- var
- I: Integer;
- begin
- if (AName <> '') and (FComponents <> nil) then
- for I := 0 to FComponents.Count - 1 do
- begin
- Result := FComponents[I];
- if CompareText(Result.FName, AName) = 0 then Exit;
- end;
- Result := nil;
- end;
-
- procedure TComponent.SetName(const NewName: TComponentName);
- begin
- if FName <> NewName then
- begin
- if (NewName <> '') and not IsValidIdent(NewName) then
- raise EComponentError.CreateResFmt(SInvalidName, [NewName]);
- if FOwner <> nil then
- FOwner.ValidateRename(Self, FName, NewName) else
- ValidateRename(nil, FName, NewName);
- SetReference(False);
- ChangeName(NewName);
- SetReference(True);
- end;
- end;
-
- procedure TComponent.ChangeName(const NewName: TComponentName);
- begin
- FName := NewName;
- end;
-
- function TComponent.GetComponentIndex: Integer;
- begin
- if (FOwner <> nil) and (FOwner.FComponents <> nil) then
- Result := FOwner.FComponents.IndexOf(Self) else
- Result := -1;
- end;
-
- function TComponent.GetComponent(AIndex: Integer): TComponent;
- begin
- if FComponents = nil then ListError(SListIndexError);
- Result := FComponents[AIndex];
- end;
-
- function TComponent.GetComponentCount: Integer;
- begin
- if FComponents <> nil then
- Result := FComponents.Count else
- Result := 0;
- end;
-
- procedure TComponent.SetComponentIndex(Value: Integer);
- var
- I, Count: Integer;
- begin
- if FOwner <> nil then
- begin
- I := FOwner.FComponents.IndexOf(Self);
- if I >= 0 then
- begin
- Count := FOwner.FComponents.Count;
- if Value < 0 then Value := 0;
- if Value >= Count then Value := Count - 1;
- if Value <> I then
- begin
- FOwner.FComponents.Delete(I);
- FOwner.FComponents.Insert(Value, Self);
- end;
- end;
- end;
- end;
-
- procedure TComponent.SetAncestor(Value: Boolean);
- var
- I: Integer;
- begin
- if Value then
- Include(FComponentState, csAncestor) else
- Exclude(FComponentState, csAncestor);
- for I := 0 to ComponentCount - 1 do
- Components[I].SetAncestor(Value);
- end;
-
- procedure TComponent.SetDesigning(Value: Boolean);
- var
- I: Integer;
- begin
- if Value then
- Include(FComponentState, csDesigning) else
- Exclude(FComponentState, csDesigning);
- for I := 0 to ComponentCount - 1 do Components[I].SetDesigning(Value);
- end;
-
- procedure TComponent.SetReference(Enable: Boolean);
- var
- Field: ^TComponent;
- begin
- if FOwner <> nil then
- begin
- Field := FOwner.FieldAddress(FName);
- if Field <> nil then
- if Enable then Field^ := Self else Field^ := nil;
- end;
- end;
-
- procedure FreeIntConstList;
- var
- I: Integer;
- begin
- for I := 0 to IntConstList.Count - 1 do
- TIntConst(IntConstList[I]).Free;
- IntConstList.Free;
- end;
-
- initialization
- ClassList := TList.Create;
- ClassAliasList := TStringList.Create;
- IntConstList := TList.Create;
- GlobalFixupList := TList.Create;
- MainThreadID := GetCurrentThreadID;
- GlobalLists := TList.Create;
-
- finalization
- ClassList.Free;
- ClassAliasList.Free;
- FreeIntConstList;
- RemoveFixupReferences(nil, '');
- GlobalFixupList.Free;
- GlobalLists.Free;
-
- end.
-