home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
sibdemo3.zip
/
SOURCE.DAT
/
SOURCE
/
SPCC
/
CLASSES.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1998-05-20
|
231KB
|
7,392 lines
{╔══════════════════════════════════════════════════════════════════════════╗
║ ║
║ Sibyl Portable Component Classes ║
║ ║
║ Copyright (C) 1995,97 SpeedSoft Germany, All rights reserved. ║
║ ║
╚══════════════════════════════════════════════════════════════════════════╝}
Unit Classes;
Interface
Uses Dos,SysUtils;
{$IFDEF OS2}
Uses PmWin,BseDos;
{$ENDIF}
{$IFDEF Win95}
Uses WinUser,WinBase;
{$ENDIF}
//TStream Seek origins
Const
soFromBeginning = 0;
soFromCurrent = 1;
soFromEnd = 2;
Type
EStreamError=Class(Exception);
EFCreateError=Class(EStreamError);
EFOpenError=Class(EStreamError);
TStream=Class(TObject)
Private
Function GetSize:LongInt;Virtual;
Function GetPosition:LongInt;
Procedure SetPosition(NewPos:LongInt);
Procedure Error(ResourceId:Word);Virtual;
Public
Procedure ReadBuffer(Var Buffer;Count:LongInt);
Procedure WriteBuffer(Const Buffer;Count:LongInt);
Function CopyFrom(Source: TStream; Count: LongInt): LongInt;
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;
Function EndOfData: Boolean; Virtual;
Function ReadLn: String; Virtual;
Procedure WriteLn(Const S: String); Virtual;
Public
Property Position:LongInt Read GetPosition Write SetPosition;
Property Size:LongInt Read GetSize;
End;
Const
{FileStream Open modes}
fmCreate = $FFFF; (* Delphi *)
Stream_Create = fmCreate; (* compatibility only *)
Stream_Open = fmInOut; (* compatibility only *)
Stream_OpenRead = fmOpenRead Or fmShareDenyWrite;
Type
THandleStream= Class(TStream)
Private
FHandle: LongInt;
Public
Constructor Create(AHandle: LongInt);
Function Read(Var Buffer; Count: LongInt): LongInt; Override;
Function Write(Const Buffer; Count: LongInt): LongInt; Override;
Function Seek(Offset: LongInt; Origin: Word): LongInt; Override;
Public
Property Handle: LongInt Read FHandle;
End;
Type
TFileStream=Class(TStream)
Private
PStreamFile:File;
Public
Constructor Create(Const FileName:String;Mode:LongWord);
Destructor Destroy;Override;
Function Read(Var Buffer;Count:LongInt):LongInt;Override;
Function Write(Const Buffer;Count:LongInt):LongInt;Override;
Function Seek(Offset:LongInt;Origin:Word):LongInt;Override;
End;
TMemoryStream=Class(TStream)
Private
FBuffer: PByteArray;
FSize, FCapacity, FPosition: LongInt;
Procedure SetCapacity(NewCapacity: LongInt);
Protected
Property Capacity:LongInt Read FCapacity Write SetCapacity;
Public
Destructor Destroy;Override;
Function Read(Var Buffer;Count:LongInt):LongInt;Override;
Function Write(Const Buffer; Count: LongInt):LongInt;Override;
Function Seek(Offset: LongInt; Origin: Word):LongInt;Override;
Procedure LoadFromStream(Stream: TStream);
Procedure LoadFromFile(Const FileName:String);
Procedure SaveToStream(Stream: TStream);
Procedure SaveToFile(Const FileName:String);
Procedure SetSize(NewSize: LongInt);
Procedure Clear;
Public
Property Memory: PByteArray Read FBuffer;
End;
Const
MaxListSize = MaxLongInt Div SizeOf(Pointer);
{ A notify event Is A method variable, I.E. A Procedure
variable For Objects. Some Classes allow the specification
Of Objects To be notified Of changes. }
Type
TComponent=Class;
{$M+}
TNotifyEvent = Procedure(Sender:TObject) Of Object;
{$M-}
EListError = Class(Exception);
{TList Class}
TList = Class;
PPointerList = ^TPointerList;
TPointerList = Array[0..MaxListSize-1] Of Pointer;
TListSortCompare = Function(Item1,Item2: Pointer):LongInt;
TFreeListItem = Procedure(Sender:TObject;Item:Pointer) Of Object;
TList = Class
Private
FList:PPointerList;
FCount:LongInt;
FCapacity:LongInt;
FGrowth:LongInt;
FOnFreeItem:TFreeListItem;
Function Get(Index:LongInt):Pointer;
Procedure Put(Index:LongInt;Item:Pointer);
Procedure SetCount(NewCount:LongInt);
Protected
Procedure Error; Virtual;
Procedure Grow; Virtual;
Procedure SetCapacity(NewCapacity:LongInt); Virtual;
Procedure FreeItem(Item:Pointer); Virtual;
Public
Destructor Destroy; Override;
Procedure Clear; Virtual;
Function Add(Item:Pointer):LongInt;
Procedure Delete(Index:LongInt);
Function Remove(Item:Pointer):LongInt;
Procedure Cut(Index1,Index2:LongInt);
Procedure Insert(Index:LongInt;Item:Pointer);
Procedure Exchange(Index1,Index2:LongInt);
Procedure Move(CurIndex,NewIndex:LongInt);
Function IndexOf(Item:Pointer):LongInt;
Function First:Pointer;
Function Last:Pointer;
Function Expand:TList;
Procedure Pack;
Procedure Sort(Compare: TListSortCompare);
Public
Property Capacity:LongInt Read FCapacity Write SetCapacity;
Property Count:LongInt Read FCount Write SetCount;
Property Growth:LongInt Read FGrowth Write FGrowth;
Property Items[Index:LongInt]:Pointer Read Get Write Put; Default;
Property List:PPointerList Read FList;
Property OnFreeItem:TFreeListItem Read FOnFreeItem Write FOnFreeItem;
End;
{TChainList Class}
PChainListItem = ^TChainListItem;
TChainListItem = Record
Prev:PChainListItem;
Item:Pointer;
Next:PChainListItem;
End;
TChainList = Class(TObject)
Private
FList:PChainListItem;
FListEnd:PChainListItem;
FCount:LongInt;
FOnFreeItem:TFreeListItem;
Private
Function Index2PLE(Index:LongInt):PChainListItem;
Function Item2PLE(Item:Pointer):PChainListItem;
Function PLE2Index(ple:PChainListItem):LongInt;
Function Item2Index(Item:Pointer):LongInt;
Procedure Connect(ple1,ple2:PChainListItem);
Function Get(Index:LongInt):Pointer;
Procedure Put(Index:LongInt;Item:Pointer);
Protected
Procedure Error; Virtual;
Procedure FreeItem(Item:Pointer); Virtual;
Public
Destructor Destroy; Override;
Procedure Clear; Virtual;
Function Add(Item:Pointer):LongInt;
Function Remove(Item:Pointer):LongInt;
Procedure Delete(Index:LongInt);
Function First:Pointer;
Function Last:Pointer;
Function IndexOf(Item:Pointer):LongInt;
Procedure Insert(Index:LongInt;Item:Pointer);
Procedure Move(CurIndex,NewIndex:LongInt);
Procedure Exchange(Index1,Index2:LongInt);
Procedure Pack;
Public
Property Count:LongInt Read FCount;
Property Items[Index:LongInt]:Pointer Read Get Write Put; Default;
Property OnFreeItem:TFreeListItem Read FOnFreeItem Write FOnFreeItem;
End;
{ TStrings Is an Abstract base Class For storing a
Number Of Strings. Every String can be associated
With A Value As well As With an Object. So, If you
want To Store simple Strings, Or collections Of
keys And values, Or collection Of named Objects,
TStrings Is the Abstract ancestor you should
derive your Class from. }
Type
EStringListError = Class(Exception);
TStrings = Class(TObject)
Private
FUpdateSemaphore: LongInt;
FPreventFree: Boolean;
Function GetValue(Const Name: String): String;
Procedure SetValue(Const Name, Value: String);
Function FindValue(Const Name: String; Var Value: String): LongInt;
Function GetName(Index: LongInt): String;
Protected
Function Get(Index: LongInt): String; Virtual; Abstract;
Function GetCount: LongInt; Virtual; Abstract;
Function GetObject(Index: LongInt): TObject; Virtual;
Procedure Put(Index: LongInt; Const S: String); Virtual;
Procedure PutObject(Index: LongInt; AObject: TObject); Virtual;
Procedure SetUpdateState(Updating: Boolean); Virtual;
Function GetTextStr: AnsiString; Virtual;
Procedure SetTextStr(Const Value: AnsiString); Virtual;
Public
Function Add(Const S: String): LongInt; Virtual;
Function AddObject(Const S: String; AObject: TObject): LongInt; Virtual;
Procedure AddStrings(AStrings: TStrings); Virtual;
Procedure Append(Const S: String);
Procedure Assign(AStrings: TStrings); Virtual;
Procedure BeginUpdate;
Procedure Clear; Virtual; Abstract;
Procedure Delete(Index: LongInt); Virtual; Abstract;
Procedure EndUpdate;
Function Equals(AStrings: TStrings): Boolean;
Procedure Exchange(Index1, Index2: LongInt); Virtual;
Function GetText: PChar;Virtual;
Function IndexOf(Const S: String): LongInt; Virtual;
Function IndexOfName(Const Name: String): LongInt;
Function IndexOfObject(AObject: TObject): LongInt;
Procedure Insert(Index: LongInt; Const S: String); Virtual; Abstract;
Procedure InsertObject(Index: LongInt; Const S: String; AObject: TObject); Virtual;
Procedure LoadFromFile(Const FileName: String);
Procedure SetText(Text: PChar);Virtual;
Procedure LoadFromStream(Stream: TStream); Virtual;
Procedure Move(CurIndex, NewIndex: LongInt); Virtual;
Procedure SaveToFile(Const FileName: String);
Procedure SaveToStream(Stream: TStream); Virtual;
Public
Property Names[Index: LongInt]: String Read GetName;
Property Count: LongInt Read GetCount;
Property Objects[Index: LongInt]: TObject Read GetObject Write PutObject;
Property values[Const Name: String]: String Read GetValue Write SetValue;
Property Strings[Index: LongInt]: String Read Get Write Put; Default;
Property Text:AnsiString Read GetTextStr Write SetTextStr;
End;
{ TStringList Is A concrete Class derived
from TStrings. TStringList stores its Items
In A Private field Of Type TList. It's very
fast, since it performs binary Search For
retrieving Objects by Name. you can specify
whether you want TStringList To be sorted Or
unsorted As well As Case-sensitive Or Not.
you can also specify the way A TStringList
Object handles duplicate entries.
TStringList Is able To notify the user when
the list's Data changes Or has been changed.
Use the properties OnChange And OnChanged. }
Type
TDuplicates = (dupIgnore, dupAccept, dupError);
TFreeStringListItem = Procedure(Sender:TObject;AObject:TObject) Of Object;
Type
TStringList = Class(TStrings)
Private
FList: TList;
FSorted: Boolean;
FDuplicates: TDuplicates;
FCaseSensitive: Boolean;
FOnChange: TNotifyEvent;
FOnChanging: TNotifyEvent;
FOnFreeItem: TFreeStringListItem;
FLockChange:Boolean;
Procedure BottomUpHeapSort;
Procedure SetSorted(Value: Boolean);
Procedure SetCaseSensitive(Value: Boolean);
Protected
Procedure changed; Virtual;
Procedure Changing; Virtual;
Function Get(Index: LongInt): String; Override;
Function GetCount: LongInt; Override;
Function GetObject(Index: LongInt): TObject; Override;
Procedure Put(Index: LongInt; Const S: String); Override;
Procedure PutObject(Index: LongInt; AObject: TObject); Override;
Procedure SetUpdateState(Updating: Boolean); Override;
Procedure FreeItem(AObject: TObject);Virtual;
Public
Constructor Create;
Destructor Destroy; Override;
Function Add(Const S: String): LongInt; Override;
Procedure Clear; Override;
Procedure Delete(Index: LongInt); Override;
Procedure Exchange(Index1, Index2: LongInt); Override;
Function Find(Const S: String; Var Index: LongInt): Boolean; Virtual;
Function IndexOf(Const S: String): LongInt; Override;
Procedure Insert(Index: LongInt; Const S: String); Override;
Procedure Sort; Virtual;
Property Duplicates: TDuplicates Read FDuplicates Write FDuplicates;
Property CaseSensitive: Boolean Read FCaseSensitive Write SetCaseSensitive;
Property sorted: Boolean Read FSorted Write SetSorted;
Property OnChange: TNotifyEvent Read FOnChange Write FOnChange;
Property OnChanging: TNotifyEvent Read FOnChanging Write FOnChanging;
Property OnFreeItem: TFreeStringListItem Read FOnFreeItem Write FOnFreeItem;
End;
{ StrItem Is A space-efficient way To Store an Object
associated With A String. it Is used inside TStringList. }
Type
PStrItem = ^TStrItem;
TStrItem = Record
FObject: TObject;
FString: String;
End;
Function NewStrItem(Const AString: String; AObject: TObject): PStrItem;
Procedure DisposeStrItem(P: PStrItem);
Type
{ TBits implements A Boolean Array. entries are
numbered 0 .. Size - 1, As usual. Bits allows
Read / Write access To entries. OpenBit returns
Index Of First True bit, Or -1 If none Is True. }
PBitsArray = ^TBitsArray;
TBitsArray = Array[0..MaxLongInt Div 4] Of LongWord;
EBitsError = Class(Exception);
TBits = Class
Private
FBits: PBitsArray;
FSize: LongInt;
Procedure Error;
Function GetBit(Index: LongInt): Boolean;
Procedure SetBit(Index: LongInt; bit: Boolean);
Procedure SetSize(NewSize: LongInt);
Public
Destructor Destroy; Override;
Function OpenBit: LongInt;
Property Bits[Index: LongInt]: Boolean Read GetBit Write SetBit; Default;
Property Size: LongInt Read FSize Write SetSize;
End;
Type
//General types
HWindow=LongWord;
PMessage=^TMessage;
{$M+}
TMessage=Record
{$M-}
Msg:LongWord;
ReceiverClass: TObject;
Receiver: HWindow;
Handled: LongBool; {True If the Message was Handled}
Case Integer Of
0: ( Param1: LongWord;
Param2: LongWord;
Result: LongWord);
1: ( WParam: LongWord;
LParam: LongWord;
MsgResult: LongWord);
2: ( Param1Lo: Word;
Param1Hi: Word;
Param2Lo: Word;
Param2Hi: Word;
ResultLo: Word;
ResultHi: Word);
3: ( Param1LoByteLo:Byte;
Param1LoByteHi:Byte;
Param1HiByteLo:Byte;
Param1HiByteHi:Byte;
Param2LoByteLo:Byte;
Param2LoByteHi:Byte;
Param2HiByteLo:Byte;
Param2HiByteHi:Byte;
ResultLoByteLo:Byte;
ResultLoByteHi:Byte;
ResultHiByteLo:Byte;
ResultHiByteHi:Byte);
End;
HDC=LongWord;
HPalette=LongWord;
{$M+}
TColor=LongInt;
{$M-}
PPoint=^TPoint;
{$M+}
TPoint=Record
X,Y:LongInt;
End;
{$M-}
PRect=^TRect;
{$M+}
TRect=Record
Case LongInt Of
0: (Left,Bottom,Right,Top:LongInt);
1: (LeftBottom,RightTop:TPoint);
End;
{$M-}
PSize=^TSize;
{$M+}
TSize=Record
CX,CY:LongInt;
End;
TRGB=Record
Blue:Byte;
Green:Byte;
Red:Byte;
Fill:Byte;
End;
{$M-}
Const
{$M+}
{Default RGB color values}
clBlack = TColor($00000000);
clMaroon = TColor($00800000);
clGreen = TColor($00008000);
clOlive = TColor($00808000);
clNavy = TColor($00000080);
clPurple = TColor($00800080);
clTeal = TColor($00008080);
clGray = TColor($00808080);
clSilver = TColor($00C6C6C6);
clRed = TColor($00FF0000);
clLime = TColor($0000FF00);
clYellow = TColor($00FFFF00);
clBlue = TColor($000000FF);
clFuchsia = TColor($00FF00FF);
clAqua = TColor($0000FFFF);
clLtGray = TColor($00CCCCCC);
clDkGray = TColor($00808080);
clWhite = TColor($00FFFFFF);
{System Colors}
clScrollbar = TColor(0 Or $80000000);
clBackGround = TColor(1 Or $80000000);
clActiveCaption = TColor(2 Or $80000000);
clInactiveCaption = TColor(3 Or $80000000);
clMenu = TColor(4 Or $80000000);
clWindow = TColor(5 Or $80000000);
clWindowFrame = TColor(6 Or $80000000);
clMenuText = TColor(7 Or $80000000);
clWindowText = TColor(8 Or $80000000);
clCaptionText = TColor(9 Or $80000000);
clActiveBorder = TColor(10 Or $80000000);
clInactiveBorder = TColor(11 Or $80000000);
clAppWorkSpace = TColor(12 Or $80000000);
clHighlight = TColor(13 Or $80000000);
clHighlightText = TColor(14 Or $80000000);
clBtnFace = TColor(15 Or $80000000);
clBtnShadow = TColor(16 Or $80000000);
clGrayText = TColor(17 Or $80000000);
clBtnText = TColor(18 Or $80000000);
clInactiveCaptionText = TColor(19 Or $80000000);
clBtnHighlight = TColor(20 Or $80000000);
cl3DDkShadow = TColor(21 Or $80000000);
cl3DLight = TColor(22 Or $80000000);
clInfoText = TColor(23 Or $80000000);
clInfo = TColor(24 Or $80000000);
clBtnDefault = TColor(25 Or $80000000);
clDlgWindow = TColor(26 Or $80000000);
clEntryField = TColor(27 Or $80000000);
clStaticText = TColor(28 Or $80000000);
{$M-}
Type
TColorName = Record
Name: String[20];
Value: LongInt;
End;
Const
MaxDefaultColors = 18;
DefaultColors: Array[1..MaxDefaultColors] Of TColorName = (
(Name:'clBlack'; Value:clBlack),
(Name:'clMaroon'; Value:clMaroon),
(Name:'clGreen'; Value:clGreen),
(Name:'clOlive'; Value:clOlive),
(Name:'clNavy'; Value:clNavy),
(Name:'clPurple'; Value:clPurple),
(Name:'clTeal'; Value:clTeal),
(Name:'clGray'; Value:clGray),
(Name:'clSilver'; Value:clSilver),
(Name:'clRed'; Value:clRed),
(Name:'clLime'; Value:clLime),
(Name:'clYellow'; Value:clYellow),
(Name:'clBlue'; Value:clBlue),
(Name:'clFuchsia'; Value:clFuchsia),
(Name:'clAqua'; Value:clAqua),
(Name:'clLtGray'; Value:clLtGray),
(Name:'clDkGray'; Value:clDkGray),
(Name:'clWhite'; Value:clWhite));
MaxSystemColors = 29;
SystemColors: Array[1..MaxSystemColors] Of TColorName = (
(Name:'clScrollbar'; Value:clScrollbar),
(Name:'clBackGround'; Value:clBackGround),
(Name:'clActiveCaption'; Value:clActiveCaption),
(Name:'clInactiveCaption'; Value:clInactiveCaption),
(Name:'clMenu'; Value:clMenu),
(Name:'clWindow'; Value:clWindow),
(Name:'clWindowFrame'; Value:clWindowFrame),
(Name:'clMenuText'; Value:clMenuText),
(Name:'clWindowText'; Value:clWindowText),
(Name:'clCaptionText'; Value:clCaptionText),
(Name:'clActiveBorder'; Value:clActiveBorder),
(Name:'clInactiveBorder'; Value:clInactiveBorder),
(Name:'clAppWorkSpace'; Value:clAppWorkSpace),
(Name:'clHighLight'; Value:clHighlight),
(Name:'clHighLightText'; Value:clHighlightText),
(Name:'clBtnFace'; Value:clBtnFace),
(Name:'clBtnShadow'; Value:clBtnShadow),
(Name:'clGrayText'; Value:clGrayText),
(Name:'clBtnText'; Value:clBtnText),
(Name:'clInactiveCaptionText'; Value:clInactiveCaptionText),
(Name:'clBtnHighlight'; Value:clBtnHighlight),
(Name:'cl3DDkShadow'; Value:cl3DDkShadow),
(Name:'cl3DLight'; Value:cl3DLight),
(Name:'clInfoText'; Value:clInfoText),
(Name:'clInfo'; Value:clInfo),
(Name:'clBtnDefault'; Value:clBtnDefault),
(Name:'clDlgWindow'; Value:clDlgWindow),
(Name:'clEntryField'; Value:clEntryField),
(Name:'clStaticText'; Value:clStaticText));
Function ColorName(ColorValue:TColor):String;
Function ColorValue(ColorName:String):TColor;
Type
TResourceName=String[32];
TResourceStream=Class(TMemoryStream)
Private
FHeaderPos:LongInt;
FResourceList:TList;
SCUStream:TStream;
Public
Function NewResourceEntry(Const ResName:TResourceName;
Var Data;DataLen:LongInt):Boolean;
Function WriteResourcesToStream(Stream:TMemoryStream):Boolean;
Destructor Destroy;Override;
End;
{Standard Resource Names For NewResourceEntry}
Const
rnGlyph = 'rnGlyph';
rnBitmap = 'rnBitmap';
rnPicture = 'rnPicture';
rnPictureLeaf = 'rnPictureLeaf';
rnPictureOpen = 'rnPictureOpen';
rnPictureClosed = 'rnPictureClosed';
rnFont = 'rnFont';
rnTabFont = 'rnTabFont';
rnLines = 'rnLines';
rnItems = 'rnItems';
rnTabs = 'rnTabs';
rnDBServer = 'rnDBServer';
rnDBDataBase = 'rnDBDataBase';
rnDBTable = 'rnDBTable';
rnDBQuery = 'rnDBQuery';
rnDBDataField = 'rnDBDataField';
rnGridSizes = 'rnGridSize';
rnFileName = 'rnFileName';
rnIcon = 'rnIcon';
rnDBGridCols = 'rnDBGridCols';
rnStatusPanels = 'rnStatusPanels';
rnHeaders = 'rnHeaders';
rnBitmapList = 'rnBitmapList';
rnScrollExtents = 'rnScrollExtents';
Type
TComponentState=Set Of (csDesigning,csReading,csWriting,csDestroying,
csLoaded,csForm,csDetail,csReferenceControl,
csReference,csAcceptsControls,csHandleLinks,
csHasMainMenu,csLoading);
TDesignerState=Set Of (dsFormVisible,dsNoRealSizing,
dsNoSourceCode,dsStored,dsAutoCreate);
TOperation=(opInsert,opRemove);
TGetChildProc=Procedure(Child:TComponent) Of Object;
ESCUError=Class(Exception);
TPersistent=Class(TObject)
Private
Procedure AssignError(Source:TPersistent);
Protected
Procedure AssignTo(Dest:TPersistent);Virtual;
Public
Procedure Assign(Source:TPersistent);Virtual;
End;
TPersistentClass = class of TPersistent;
TComponent=Class(TPersistent)
Private
FLanguages:Pointer;
FName:PString;
FUnitName:PString;
FTypeName:PString;
FOwner:TComponent;
FComponentState:TComponentState;
FDesignerState:TDesignerState;
FCreateFromSCU:Boolean;
FComponents:TList;
FFreeNotifyList:TList;
FMethods:Pointer;
FTag:LongInt;
FWriteComponentCount:LongInt;
SCUStream:TMemoryStream;
SCUResStream:TResourceStream;
SCUWriteError:Boolean;
FReference:TComponent;
Function GetComponentCount:LongInt;
Function GetComponent(AIndex:LongInt):TComponent;
Function GetComponentIndex:LongInt;
Procedure SetComponentIndex(Index:LongInt);
Function GetName:String;
Procedure SetName(Const NewName:String);
Function GetUnitName:String;
Function GetTypeName:String;
Procedure SetTypeName(NewName:String);
Function GetDesigned:Boolean;
Procedure SetupSCU;
Function ReadPropertiesSCU(COwner:TComponent;Namep,Resourcep:Pointer;Var ClassPointer:Pointer):Boolean;
Function ReadComponentsSCU(NameTable,ResourceTable:Pointer;Var ClassP:Pointer):Boolean;
Procedure ReadResourceSCU(ResourceTable:Pointer;Var ClassP:Pointer);
Procedure WriteComponent(Child:TComponent);
Procedure ReadSCU(Data:Pointer);
Protected
Procedure SetupComponent;Virtual;
Procedure Loaded;Virtual;
Procedure LoadedFromSCU(SCUParent:TComponent);Virtual;
Procedure LoadingFromSCU(SCUParent:TComponent);Virtual;
Procedure GetChildren(Proc:TGetChildProc);Virtual;
Function HasParent:Boolean;Virtual;
Procedure UpdateLinkList(Const PropertyName:String;LinkList:TList);Virtual; //For Component links
Public
Constructor Create(AOwner:TComponent);Virtual;
Destructor Destroy;Override;
Procedure InsertComponent(AComponent:TComponent);Virtual;
Procedure RemoveComponent(AComponent:TComponent);Virtual;
Function IndexOfComponent(AComponent:TComponent):LongInt;
Procedure DestroyComponents;
Function FindComponent(Const AName:String):TComponent;
Procedure ReadSCUResource(Const ResName:TResourceName;Var Data;DataLen:LongInt);Virtual;
Function WriteSCUResource(Stream:TResourceStream):Boolean;Virtual;
Procedure ReadFromStream(SCUStream:TStream);
Procedure WriteToStream(SCUStream:TStream);
Procedure Notification(AComponent:TComponent;Operation:TOperation);Virtual;
Procedure FreeNotification(AComponent:TComponent);Virtual;
Procedure SetDesigning(Value:Boolean);Virtual;
Procedure GetDesignerPopupEvents(AString:TStringList);Virtual;
Procedure DesignerPopupEvent(Id:LongInt);Virtual;
Property Owner:TComponent Read FOwner write FOwner;
Property Components[Index:LongInt]:TComponent Read GetComponent;
Property ComponentCount:LongInt Read GetComponentCount;
Property ComponentIndex:LongInt Read GetComponentIndex Write SetComponentIndex;
Property ComponentState:TComponentState Read FComponentState Write FComponentState;
Property DesignerState:TDesignerState Read FDesignerState Write FDesignerState; stored;
Property UnitName:String Read GetUnitName;
Property TypeName:String Read GetTypeName Write SetTypeName;
Property Designed:Boolean Read GetDesigned;
Property FreeNotifyList:TList Read FFreeNotifyList;
Property Methods:Pointer Read FMethods Write FMethods; {undocumented}
Published
Property Name:String Read GetName Write SetName;
Property Tag:LongInt Read FTag Write FTag;
End;
TComponentClass=Class Of TComponent;
TCollection = Class;
TCollectionItem = Class
Private
FCollection:TCollection;
Private
Function GetIndex:LongInt;
Procedure SetCollection(NewValue:TCollection);
Protected
Procedure SetIndex(NewIndex:LongInt);Virtual;
Procedure changed(AllItems:Boolean);
Public
Procedure Assign(Source:TCollectionItem);Virtual;Abstract;
Constructor Create(ACollection: TCollection);Virtual;
Destructor Destroy;Override;
Public
Property collection:TCollection Read FCollection Write SetCollection;
Property Index:LongInt Read GetIndex Write SetIndex;
End;
TCollectionItemClass=Class Of TCollectionItem;
TCollection=Class(TComponent)
Private
FItemClass:TCollectionItemClass;
FItems:TList;
FUpdateCount:LongInt;
Private
Function GetCount:LongInt;
Procedure InsertItem(Item:TCollectionItem);
Procedure RemoveItem(Item:TCollectionItem);
Protected
Procedure changed;
Function GetItem(Index:LongInt):TCollectionItem;
Procedure SetItem(Index:LongInt;Value:TCollectionItem);
Public
Procedure Update(Item:TCollectionItem);Virtual;
Procedure SetupComponent;Override;
Destructor Destroy;Override;
Function Add:TCollectionItem;
Procedure Assign(Source:TCollection);Virtual;
Procedure BeginUpdate;
Procedure Clear;
Procedure EndUpdate;
Public
Property Count:LongInt Read GetCount;
Property Items[Index:LongInt]:TCollectionItem Read GetItem Write SetItem;
Property ItemClass:TCollectionItemClass Read FItemClass Write FItemClass;
End;
TStringSelectList=Class(TComponent)
Private
FList:TStringList;
FSelected:String;
Protected
Procedure SetStringItem(NewValue:String);Virtual;
Procedure SetupComponent;Override;
Public
Destructor Destroy;Override;
Function GetItems:TStringList;Virtual;
Property SelectedItem:String Read FSelected Write SetStringItem;
Property Items:TStringList Read GetItems;
End;
{$M+}
TThreadPriority=(tpIdle,tpLowest,tpLower,tpNormal,tpHigher,tpHighest,tpTimeCritical);
{$M-}
TThreadMethod=Procedure Of Object;
TThread=Class
Private
FOnTerminate:TNotifyEvent;
FHandle:LongWord;
FPriority:TThreadPriority;
FFreeOnTerminate:Boolean;
FTerminated:Boolean;
FReturnValue:LongInt;
FSuspended:Boolean;
FFinished:Boolean;
FThreadId:LongWord;
FParameter:Pointer;
FMethod:TThreadMethod;
Procedure SetSuspended(NewValue:Boolean);
Procedure SetPriority(NewValue:TThreadPriority);
Procedure SyncTerminate;
Procedure MsgIdle;
Protected
Procedure DoTerminate;Virtual;
Procedure Execute;Virtual;Abstract;
Public
Constructor Create(CreateSuspended:Boolean);
Constructor ExtCreate(CreateSuspended:Boolean;StackSize:LongWord;
Priority:TThreadPriority;Param:Pointer);
Destructor Destroy;Override;
Function WaitFor:LongInt;
Procedure Terminate;
Procedure Suspend;
Procedure Resume;
Procedure Kill;
Procedure Synchronize(method:TThreadMethod);
Procedure ProcessMsgs;
Property Terminated:Boolean Read FTerminated;
Property ReturnValue:LongInt Read FReturnValue Write FReturnValue;
Property ThreadId:LongWord Read FThreadId;
Property Handle:LongWord Read FHandle;
Property Priority:TThreadPriority Read FPriority Write SetPriority;
Property Parameter:Pointer Read FParameter Write FParameter;
Property Suspended:Boolean Read FSuspended Write SetSuspended;
Property FreeOnTerminate:Boolean Read FFreeOnTerminate Write FFreeOnTerminate;
Property OnTerminate:TNotifyEvent Read FOnTerminate Write FOnTerminate;
End;
Procedure RegisterClasses(Const ComponentClasses: Array Of TComponentClass);
Function SearchClassByName(Const Name:String):TComponentClass;
Function CallReadProp(Objekt:TObject;FuncAddr:Pointer;Typ:Byte;
TypLen:LongInt;Value:Pointer):Boolean;
Function CallWriteProp(Objekt:TObject;ProcAddr:Pointer;Typ:Byte;
TypLen:LongInt;Value:Pointer):Boolean;
Type
PSCUFileFormat=^TSCUFileFormat;
TSCUFileFormat=Record
Version:String[5];
ObjectOffset,ObjectLen:LongInt;
NameTableOffset,NameTableLen:LongInt;
ResourceOffset,ResourceLen:LongInt;
ObjectCount:LongInt;
UseEntry:LongInt; {used by project management}
NextEntry:Pointer;
{auch System ändern (AddSCUData) und Compiler.PAS}
End;
PFormListItem=^TFormListItem;
TFormListItem=Record
Form:TComponent;
FormName:String[64];
UnitName:String;
AutoCreate:Boolean;
SCUPointer:Pointer;
SCUSize:LongInt;
End;
Function WritePropertiesToStream(FormList:TList):TMemoryStream;
Function WritePropertiesToFile(FileName:String;FormList:TList):Boolean;
Type
TMsgDlgBtn=(mbYes,mbNo,mbOk,mbCancel,mbAbort,mbRetry,mbIgnore,mbAll,mbHelp);
TMsgDlgButtons=Set Of TMsgDlgBtn;
TMsgDlgType=(mtWarning,mtError,mtInformation,mtConfirmation,mtCustom,mtCritical);
TMsgDlgReturn=LongWord;
Const
mrBase = $8000; //cmBase
mrOk = mrBase+50; //cmOk
mrCancel = mrBase+51; //cmCancel
mrYes = mrBase+53; //cmYes
mrNo = mrBase+54; //cmNo
mrIgnore = mrBase+58; //cmIgnore
mrRetry = mrBase+57; //cmRetry
mrAbort = mrBase+56; //cmAbort
mrNone = 0; //cmNull
mrAll = mrBase+59; //cmAll
Const
mbYesNo=[mbYes,mbNo];
mbYesNoCancel=[mbYes,mbNo,mbCancel];
mbOkCancel=[mbOk,mbCancel];
mbAbortRetryIgnore=[mbAbort,mbRetry,mbIgnore];
Function MessageBox2(Const Msg:String;Typ:TMsgDlgType;Buttons:TMsgDlgButtons):TMsgDlgReturn;
Function ErrorBox2(Const Msg:String):TMsgDlgReturn;
Function GetExperts:TList; {noch raus?}
Var RegisteredClasses:TList;
PropertyEditDialogs:TList;
LibExperts:TList;
LibExpertInstances:TList;
Type
TPropertyEditorReturn=(edOk,edCancel,edList,edNoEditor);
TPropertyEditor=Class(TComponent)
Private
FPropertyOwner:TComponent;
FPropertyName:String;
FList:TStringList;
Public
Function Execute(Var Value;ValueLen:LongInt):TPropertyEditorReturn;Virtual;Abstract;
Public
Property PropertyOwner:TComponent Read FPropertyOwner;
Property PropertyName:String Read FPropertyName;
Property List:TStringList Read FList;
End;
TPropertyEditorClass=Class Of TPropertyEditor;
{$HINTS OFF}
TStringPropertyEditor=Class(TPropertyEditor)
Public
Function Execute(Var Value:String;ValueLen:LongInt):TPropertyEditorReturn;Virtual;Abstract;
End;
TShortIntPropertyEditor=Class(TPropertyEditor)
Public
Function Execute(Var Value:ShortInt):TPropertyEditorReturn;Virtual;Abstract;
End;
TIntegerPropertyEditor=Class(TPropertyEditor)
Public
Function Execute(Var Value:Integer):TPropertyEditorReturn;Virtual;Abstract;
End;
TLongIntPropertyEditor=Class(TPropertyEditor)
Public
Function Execute(Var Value:LongInt):TPropertyEditorReturn;Virtual;Abstract;
End;
TClassPropertyEditorReturn=(peOk,peCancel,peClear,peNoEditor);
TClassPropertyEditor=Class(TPropertyEditor)
Private
Property PropertyOwner;
Property PropertyName;
Property List;
Public
Function Execute(Var ClassToEdit:TObject):TClassPropertyEditorReturn;Virtual;
End;
TClassPropertyEditorClass=Class Of TClassPropertyEditor;
{$HINTS ON}
EClassNotFound=Class(Exception);
Procedure RegisterClass(Const ComponentClass:TComponentClass);
Function GetClass(Const ClassName:String):TComponentClass;
Function FindClass(Const ClassName:String):TComponentClass;
Procedure UnRegisterClass(AClass:TComponentClass);
Procedure UnRegisterClasses(Const AClasses:Array of TComponentClass);
Procedure AddPropertyEditor(OwnerClass:TClass;PropertyName:String;PropertyEditor:TPropertyEditorClass);
Function CallPropertyEditor(Owner:TComponent;PropertyName:String;Var Value;ValueLen:LongInt;
Var List:TStringList):TPropertyEditorReturn;
Function PropertyEditorAvailable(OwnerClass:TClass;PropertyName:String):Boolean;
Procedure AddClassPropertyEditor(ClassToEdit:TClass;PropertyEditor:TClassPropertyEditorClass);
Function CallClassPropertyEditor(Var ClassToEdit:TObject):TClassPropertyEditorReturn;
Function ClassPropertyEditorAvailable(ClassName:String):Boolean;
Procedure AddDesignerPopupEvent(AString:TStringList;Caption:String;Id:LongInt);
Function GetTempFileName:String;
Function InDesigner:Boolean;
Implementation
//!!!!!!!!!! bei Änderungen auch Language Manager und SIB_DLG ändern!!!!!!!!!!!!!!!!!!!
Type
PLanguageMessages=^TLanguageMessages;
TLanguageMessages=Record
Name:PString; //Language Name
StringTableLen:LongWord;
StringTable:Pointer;
Next:PLanguageMessages;
End;
PLanguageComponent=^TLanguageComponent;
TLanguageComponent=Record
Name:PString;
OriginalInstance:TComponent;
Instance:TComponent;
ValueScope:Byte;
ValueTyp:Byte;
ValueRead:TPropertyReadWriteRecord;
ValueWrite:TPropertyReadWriteRecord;
ValueSize:LongWord;
ValueLen:LongWord;
Value:Pointer;
ControlLeft,ControlBottom:LongInt;
ControlWidth,ControlHeight:LongInt;
OrigControlLeft,OrigControlBottom:LongInt;
OrigControlWidth,OrigControlHeight:LongInt;
Next:PLanguageComponent;
End;
PLanguageItem=^TLanguageItem;
TLanguageItem=Record
Name:PString;
Components:PLanguageComponent;
Menus:PLanguageComponent;
StringTables:PLanguageComponent;
Next:PLanguageItem;
End;
//!!!!!!!!!! bei Änderungen auch Language Manager ändern!!!!!!!!!!!!!!!!!!!
PLanguageInfo=^TLanguageInfo;
TLanguageInfo=Record
CurrentLanguageName:PString; //only Copy !!
CurrentLanguageComponents:PLanguageComponent; //only Copy !
CurrentLanguageMenus:PLanguageComponent; //only Copy !
CurrentLanguageStringTables:PLanguageComponent; //only Copy
Items:PLanguageItem;
End;
//!!!!!!!!!! bei Änderungen auch Language Manager und SIB_DLG ändern!!!!!!!!!!!!!!!!!!!
//////////////////////////////////////////////////////////////////////////////////////////////////////////
Var LanguageMessages:PLanguageMessages;
AppLanguage:String;
Procedure DestroyMessages;
Var dummy:PLanguageMessages;
Begin
While LanguageMessages<>NIL Do
Begin
dummy:=LanguageMessages^.Next;
If LanguageMessages^.Name<>Nil Then
FreeMem(LanguageMessages^.Name,length(LanguageMessages^.Name^)+1);
If LanguageMessages^.StringTable<>Nil Then
FreeMem(LanguageMessages^.StringTable,LanguageMessages^.StringTableLen);
Dispose(LanguageMessages);
LanguageMessages:=dummy;
End;
LanguageMessages:=Nil;
AppLanguage:='Default';
End;
Type TLanguageComponentKinds=(Captions,Menus,StringTables);
Procedure SetupLanguageComponents(Component:TComponent;Items:PLanguageComponent;Kind:TLanguageComponentKinds);
Var
WriteTyp,ReadTyp:Byte;
WriteOffset,ReadOffset:LongWord;
ValueTyp:Byte;
Info:TPropertyTypeInfo;
S,s1:String;
T:LongInt;
Temp,Temp1:TComponent;
p2:^LongWord;
B:Byte;
C:TObject;
Procedure WriteInt(Const Name:String;Value:LongInt);
Var Info:TPropertyTypeInfo;
Begin
If Temp.GetPropertyTypeInfo(Name,Info) Then
Begin
//Info available
Case Info.Write.Kind Of
1:
Begin
p2:=Pointer(Temp);
Inc(p2,Info.Write.VarOffset);
System.Move(Value,p2^,Info.Size);
End;
2,3:
Begin
CallWriteProp(Temp,Pointer(Info.Write.VarOffset),
Info.Typ,Info.Size,@Value);
End;
End; //Case
End;
End;
Label skip;
Begin
While Items<>Nil Do //process All Language Components
Begin
If ((Items^.ValueTyp<>0)And(Items^.ValueWrite.Kind<>0)And(Items^.Instance<>Nil)) Then //Read And Write information are Valid
Begin
ValueTyp:=Items^.ValueTyp;
WriteTyp:=Items^.ValueWrite.Kind;
WriteOffset:=Items^.ValueWrite.VarOffset;
ReadTyp:=Items^.ValueRead.Kind;
ReadOffset:=Items^.ValueRead.VarOffset;
Temp:=Items^.Instance;
End
Else
Begin
Temp:=Component;
S:=Items^.Name^;
B:=Pos('.',S);
While B<>0 Do
Begin
s1:=Copy(S,1,B-1);
Delete(S,1,B);
Temp1:=Nil;
For T:=0 To Temp.ComponentCount-1 Do
Begin
Temp1:=Temp.Components[T];
If Temp1.Name=s1 Then
Begin
Temp:=Temp1;
break; //found !
End;
Temp1:=Nil;
End;
If Temp1=Nil Then Goto skip; //Not found
B:=Pos('.',S);
End;
If Not Temp.GetPropertyTypeInfo(S,Info) Then Goto skip;
Items^.Instance:=Temp;
Items^.ValueRead:=Info.Read;
Items^.ValueWrite:=Info.Write;
Items^.ValueSize:=Info.Size;
Items^.ValueTyp:=Info.Typ;
ValueTyp:=Info.Typ;
WriteTyp:=Info.Write.Kind;
WriteOffset:=Info.Write.VarOffset;
ReadTyp:=Info.Read.Kind;
ReadOffset:=Info.Read.VarOffset;
End;
If ((ValueTyp=PropType_Class)And(Kind=StringTables)) Then
Begin
Case ReadTyp Of
0:Goto skip;
1:
Begin
p2:=Pointer(Temp);
Inc(p2,ReadOffset);
System.Move(p2^,C,4);
End;
2,3:
Begin
CallReadProp(Temp,Pointer(ReadOffset),
ValueTyp,4,@C);
End;
Else Goto skip;
End; //Case
If Not (C Is TStrings) Then Goto skip;
TStrings(C).SetText(Pointer(Items^.Value));
Goto skip;
End
Else If ((ValueTyp<>PropType_String)And(ValueTyp<>PropType_CString)) Then Goto skip;
//Info available
Case WriteTyp Of
1:
Begin
p2:=Pointer(Temp);
Inc(p2,WriteOffset);
System.Move(Items^.Value^,p2^,Items^.ValueLen);
End;
2,3:
Begin
CallWriteProp(Temp,Pointer(WriteOffset),
ValueTyp,
Items^.ValueLen,Items^.Value);
End;
Else Goto skip;
End; //Case
If Kind=Captions Then
If Not (csForm In Temp.ComponentState) Then
Begin
//Write Language specific Position
WriteInt('Left',Items^.ControlLeft);
WriteInt('Bottom',Items^.ControlBottom);
WriteInt('Width',Items^.ControlWidth);
WriteInt('Height',Items^.ControlHeight);
End;
skip:
Items:=Items^.Next;
End;
End;
Procedure GetLanguage(Component:TComponent;Var Language:String);
Var Info:PLanguageInfo;
Begin
Info:=PLanguageInfo(Component.FLanguages);
If ((Info=Nil)Or(Info^.CurrentLanguageName=Nil)) Then Language:='Default'
Else Language:=Info^.CurrentLanguageName^;
End;
Procedure UpdateLanguageComponents(Items:PLanguageComponent;Kind:TLanguageComponentKinds);
Var
ReadTyp:Byte;
ReadOffset:LongWord;
ValueTyp:Byte;
Temp:TComponent;
p2:^LongWord;
C:TObject;
P:PChar;
S:String;
Procedure ReadInt(Const Name:String;Var Value:LongInt);
Var Info:TPropertyTypeInfo;
Begin
If Temp.GetPropertyTypeInfo(Name,Info) Then
Begin
//Info available
Case Info.Read.Kind Of
1:
Begin
p2:=Pointer(Temp);
Inc(p2,Info.Read.VarOffset);
System.Move(p2^,Value,Info.Size);
End;
2,3:
Begin
CallReadProp(Temp,Pointer(Info.Read.VarOffset),
Info.Typ,Info.Size,@Value);
End;
End; //Case
End;
End;
Label skip;
Begin
While Items<>Nil Do //process All Language Components
Begin
If ((Items^.ValueTyp<>0)And(Items^.ValueRead.Kind>0)And(Items^.Instance<>Nil)) Then
Begin
ValueTyp:=Items^.ValueTyp;
ReadTyp:=Items^.ValueWrite.Kind;
ReadOffset:=Items^.ValueRead.VarOffset;
Temp:=Items^.Instance;
If not (Temp Is TComponent) Then continue;
Try
If ((ValueTyp=PropType_Class)And(Kind=StringTables)) Then
Begin
Case ReadTyp Of
0:Goto skip;
1:
Begin
p2:=Pointer(Temp);
Inc(p2,ReadOffset);
System.Move(p2^,C,4);
End;
2,3:
Begin
CallReadProp(Temp,Pointer(ReadOffset),
ValueTyp,4,@C);
End;
Else Goto skip;
End; //Case
If Not (C Is TStrings) Then Goto skip;
P:=TStrings(C).GetText;
If Items^.ValueLen>0 Then FreeMem(Items^.Value,Items^.ValueLen);
If P=Nil Then
Begin
Items^.ValueLen:=0;
Items^.Value:=Nil;
End
Else
Begin
Items^.ValueLen:=Length(P^)+1;
GetMem(Items^.Value,Items^.ValueLen);
Move(P^,Items^.Value^,Items^.ValueLen);
StrDispose(P);
End;
Goto skip;
End
Else If ValueTyp<>PropType_String Then Goto skip;
//Info available
S:='';
Case ReadTyp Of
1:
Begin
p2:=Pointer(Temp);
Inc(p2,ReadOffset);
System.Move(p2^,S,Items^.ValueSize);
End;
2,3:
Begin
CallReadProp(Temp,Pointer(ReadOffset),
ValueTyp,
Items^.ValueSize,@S);
End;
Else Goto skip;
End; //Case
If Items^.ValueLen>0 Then FreeMem(Items^.Value,Items^.ValueLen);
Items^.ValueLen:=Length(S)+1;
GetMem(Items^.Value,Items^.ValueLen);
Move(S,Items^.Value^,Items^.ValueLen);
If Kind=Captions Then
If Not (csForm In Temp.ComponentState) Then
Begin
//Write Language specific Position
ReadInt('Left',Items^.ControlLeft);
ReadInt('Bottom',Items^.ControlBottom);
ReadInt('Width',Items^.ControlWidth);
ReadInt('Height',Items^.ControlHeight);
End;
Except
End;
End;
skip:
Items:=Items^.Next;
End;
End;
Procedure SetLanguage(Component:TComponent;Language:String);
Var Info:PLanguageInfo;
Item:PLanguageItem;
S,s1,s2:String;
Begin
Info:=PLanguageInfo(Component.FLanguages);
If Info=Nil Then Exit;
S:=Language;
UpcaseStr(S);
If Info^.CurrentLanguageName<>Nil Then
Begin
s1:=Info^.CurrentLanguageName^;
UpcaseStr(s1);
If S=s1 Then If S<>'DEFAULT' Then
Begin
Item:=Info^.Items;
While Item<>Nil Do
Begin
s1:=Item^.Name^;
UpcaseStr(s1);
If S=s1 Then Exit; //the Item Is present And Set !
Item:=Item^.Next;
End;
S:='DEFAULT';
End;
//Update old Language
s1:=Info^.CurrentLanguageName^;
UpcaseStr(s1);
Item:=Info^.Items;
While Item<>Nil Do
Begin
s2:=Item^.Name^;
UpcaseStr(s2);
If s1=s2 Then
Begin
UpdateLanguageComponents(Item^.Components,Captions);
UpdateLanguageComponents(Item^.Menus,Menus);
UpdateLanguageComponents(Item^.StringTables,StringTables);
break;
End;
Item:=Item^.Next;
End;
End;
Item:=Info^.Items;
While Item<>Nil Do
Begin
s1:=Item^.Name^;
UpcaseStr(s1);
If S=s1 Then
Begin
SetupLanguageComponents(Component,Item^.Components,Captions);
SetupLanguageComponents(Component,Item^.Menus,Menus);
SetupLanguageComponents(Component,Item^.StringTables,StringTables);
Info^.CurrentLanguageName:=Item^.Name;
Info^.CurrentLanguageComponents:=Item^.Components;
Info^.CurrentLanguageMenus:=Item^.Menus;
Info^.CurrentLanguageStringTables:=Item^.StringTables;
Exit;
End;
Item:=Item^.Next;
End;
End;
Procedure GetAppLanguage(Var Language:String);
Begin
Language:=AppLanguage;
End;
Procedure SetAppLanguage(Const Language:String);
Begin
AppLanguage:=Language;
End;
Const
{$IFDEF OS2}
SCUVersion:String[5] = 'SCU01';
{$ENDIF}
{$IFDEF Win95}
SCUVersion:String[5] = 'SCW01';
{$ENDIF}
Var
InsideCompLib:Boolean;
InsideWriteSCU:Boolean;
InsideWriteSCUAdr:^Boolean;
InsideDesigner:Boolean;
InsideLanguageDesigner:Boolean;
Type
PIDE_OwnerList=^TIDE_OwnerList;
TIDE_OwnerList=Record
PropertyName:PString;
Objekt:TComponent;
End;
PIDE_Methods=^TIDE_Methods;
TIDE_Methods=Record
Name:PString;
Params:PString;
Owners:TList;
Next:PIDE_Methods;
End;
Function GetTempFileName:String;
Var Hour,Minute,Second,Sec100:Word;
S,dir:String;
Begin
If GetTime(Hour,Minute,Second,Sec100) = 0 Then
Begin
S := 'tmp'+ tostr(Minute)+tostr(Second)+tostr(Sec100) +'.tmp';
End
Else S := 'tmp0001.tmp';
dir := GetEnv('TMP');
If dir = '' Then dir := GetEnv('TEMP');
If dir = '' Then
Begin
{$I-}
GetDir(0,dir);
{$I+}
End;
If dir[Length(dir)] <> '\' Then dir := dir + '\';
Result := dir + S;
End;
Function InDesigner:Boolean;
Begin
Result:=InsideDesigner;
End;
Function ColorName(ColorValue:TColor):String;
Var T:LongInt;
Begin
For T := 1 To MaxDefaultColors Do
Begin
If DefaultColors[T].Value = ColorValue Then
Begin
Result := DefaultColors[T].Name;
Exit;
End;
End;
For T := 1 To MaxSystemColors Do
Begin
If SystemColors[T].Value = ColorValue Then
Begin
Result := SystemColors[T].Name;
Exit;
End;
End;
Result := tostr(ColorValue);
End;
Function ColorValue(ColorName:String):TColor;
Var T:LongInt;
C:Integer;
S:String;
Begin
UpcaseStr(ColorName);
For T := 1 To MaxDefaultColors Do
Begin
S := DefaultColors[T].Name;
UpcaseStr(S);
If S = ColorName Then
Begin
Result := DefaultColors[T].Value;
Exit;
End;
End;
For T := 1 To MaxSystemColors Do
Begin
S := SystemColors[T].Name;
UpcaseStr(S);
If S = ColorName Then
Begin
Result := SystemColors[T].Value;
Exit;
End;
End;
Val(ColorName,Result,C);
If C <> 0 Then Result := 0;
End;
{
╔═══════════════════════════════════════════════════════════════════════════╗
║ ║
║ Speed-Pascal/2 Version 2.0 ║
║ ║
║ Speed-Pascal Component Classes (SPCC) ║
║ ║
║ This section: TStream Class Implementation ║
║ ║
║ (C) 1995,97 SpeedSoft. All rights reserved. Disclosure probibited ! ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════╝
}
Function TStream.CopyFrom(Source:TStream;Count:LongInt):LongInt;
Var
ActBufSize,T:LongInt;
StreamBuffer:Pointer;
Const
MaxBufSize = $FFFF;
Begin
If Count = 0 Then
Begin
Count := Source.Size;
Source.Position := 0;
End;
Result := Count;
If Count > MaxBufSize Then ActBufSize:=MaxBufSize
Else ActBufSize := Count;
GetMem(StreamBuffer,ActBufSize);
Try
While Count<>0 Do
Begin
If Count>ActBufSize Then T:=ActBufSize
Else T:=Count;
Source.ReadBuffer(StreamBuffer^,T);
WriteBuffer(StreamBuffer^,T);
Dec(Count,T);
End;
Finally
FreeMem(StreamBuffer, ActBufSize);
End;
End;
Function TStream.GetSize:LongInt;
Var
OldPos:LongInt;
Result:LongInt;
Begin
OldPos:=GetPosition;
Result:=Seek(0,Seek_End);
SetPosition(OldPos);
GetSize:=Result;
End;
Function TStream.EndOfData: Boolean;
Begin
Result := (Position >= Size);
End;
Function TStream.GetPosition:LongInt;
Begin
GetPosition:=Seek(0,Seek_Current);
End;
Procedure TStream.SetPosition(NewPos:LongInt);
Begin
Seek(NewPos,Seek_Begin);
End;
Procedure TStream.ReadBuffer(Var Buffer;Count:LongInt);
Begin
If Count=0 Then Exit; {Nothing To Read}
If Read(Buffer,Count)<>Count Then Error(SStreamReadErrorText);
End;
Procedure TStream.WriteBuffer(Const Buffer;Count:LongInt);
Begin
If Count=0 Then Exit;
If Write(Buffer,Count)<>Count Then Error(SStreamWriteErrorText);
End;
Procedure TStream.Error;
Begin
Raise EStreamError.Create(LoadNLSStr(ResourceId));
End;
Function TStream.ReadLn: String;
Var
Buffer: cstring[260];
OldPos, Count, Temp: LongInt;
Begin
OldPos := Position;
Count := Read(Buffer[0], 257);
Buffer[Count] := #0;
Temp := 0;
While Not (Buffer[Temp] In [#10, #13, #26])
And (Temp < Count) And (Temp < 255) Do Inc (Temp);
Move(Buffer[0], Result[1], Temp);
Result[0]:=Chr(Temp);
Inc(Temp);
If (Buffer[Temp - 1] = #13) And (Buffer[Temp] = #10) Then Inc(Temp);
Position := OldPos + Temp;
End;
Procedure TStream.WriteLn(Const S: String);
Var
CRLF: Word;
Begin
CRLF := $0A0D;
WriteBuffer(S[1], Length(S));
WriteBuffer(CRLF, 2);
End;
{
╔═══════════════════════════════════════════════════════════════════════════╗
║ ║
║ Speed-Pascal/2 Version 2.0 ║
║ ║
║ Speed-Pascal Component Classes (SPCC) ║
║ ║
║ This section: THandleStream Class Implementation ║
║ ║
║ (C) 1995,97 SpeedSoft. All rights reserved. Disclosure probibited ! ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════╝
}
Constructor THandleStream.Create(AHandle: LongInt);
Begin
FHandle := AHandle;
End;
Function THandleStream.Read(Var Buffer; Count: LongInt): LongInt;
Begin
Result := FileRead(Handle, Buffer, Count);
If Result = -1 Then Result := 0;
End;
Function THandleStream.Write(Const Buffer; Count: LongInt): LongInt;
Var Temp:^Byte;
Begin
Temp:=@Buffer;
Result := FileWrite(Handle, Temp^, Count);
If Result = -1 Then Result := 0;
End;
Function THandleStream.Seek(Offset: LongInt; Origin: Word): LongInt;
Begin
Result := FileSeek(Handle, Offset, Origin);
If Result < 0 Then Error(SStreamSeekErrorText);
End;
{
╔═══════════════════════════════════════════════════════════════════════════╗
║ ║
║ Speed-Pascal/2 Version 2.0 ║
║ ║
║ Speed-Pascal Component Classes (SPCC) ║
║ ║
║ This section: TFileStream Class Implementation ║
║ ║
║ (C) 1995,97 SpeedSoft. All rights reserved. Disclosure probibited ! ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════╝
}
Constructor TFileStream.Create(Const FileName:String;Mode:LongWord);
Var
SaveMode: LongWord;
Begin
Inherited Create;
SaveMode := FileMode;
If Mode = fmCreate Then FileMode := fmOpenReadWrite Or fmShareExclusive
Else FileMode := Mode;
Try
Assign(PStreamFile,FileName);
If Mode = fmCreate Then
Begin
{$I-}
Rewrite(PStreamFile,1);
{$I+}
If InOutRes<>0 Then Raise EFCreateError.Create(LoadNLSStr(SStreamCreateErrorText));
End
Else
Begin
{$I-}
Reset(PStreamFile,1);
{$I+}
If InOutRes<>0 Then Raise EFOpenError.Create(LoadNLSStr(SStreamOpenErrorText));
End;
Finally
FileMode := SaveMode;
End;
End;
Destructor TFileStream.Destroy;
Begin
{$I-}
Close(PStreamFile);
{$I+}
Inherited Destroy;
End;
Function TFileStream.Read(Var Buffer;Count:LongInt):LongInt;
Var
Result:LongWord;
Begin
{$I-}
BlockRead(PStreamFile,Buffer,Count,Result);
{$I+}
If InOutRes<>0 Then Error(SStreamReadErrorText);
Read:=Result;
End;
Function TFileStream.Write(Const Buffer;Count:LongInt):LongInt;
Var
pb:Pointer;
Result:LongWord;
Begin
pb:=@Buffer;
{$I-}
BlockWrite(PStreamFile,pb^,Count,Result);
{$I+}
If InOutRes<>0 Then Error(SStreamWriteErrorText);
Write:=Result;
End;
Function TFileStream.Seek(Offset:LongInt;Origin:Word):LongInt;
Var
SaveSeekMode:LongWord;
Begin
SaveSeekMode:=SeekMode;
SeekMode:=Origin;
{$I-}
System.Seek(PStreamFile,Offset);
{$I+}
If InOutRes<>0 Then Error(SStreamSeekErrorText);
SeekMode:=SaveSeekMode;
{$I-}
Seek:=FilePos(PStreamFile);
{$I+}
If InOutRes<>0 Then Error(SStreamSeekErrorText);
End;
{
╔═══════════════════════════════════════════════════════════════════════════╗
║ ║
║ Speed-Pascal/2 Version 2.0 ║
║ ║
║ Speed-Pascal Component Classes (SPCC) ║
║ ║
║ This section: TMemoryStream Class Implementation ║
║ ║
║ (C) 1995,97 SpeedSoft. All rights reserved. Disclosure probibited ! ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════╝
}
Const
MemoryDelta = 8192;
Destructor TMemoryStream.Destroy;
Begin
Clear;
Inherited Destroy;
End;
Function TMemoryStream.Read(Var Buffer; Count: LongInt): LongInt;
Begin
If Count > 0 Then
Begin
Result := FSize - FPosition;
If Count < Result Then Result := Count;
Move(FBuffer^[FPosition], Buffer, Result);
Inc(FPosition, Result);
End
Else Result := 0;
End;
Function TMemoryStream.Write(Const Buffer; Count: LongInt): LongInt;
Var
NewPos, Needed: LongInt;
Begin
If Count > 0 Then
Begin
NewPos := FPosition + Count;
If NewPos > FSize Then
Begin
FSize := NewPos;
If NewPos > FCapacity Then
Begin
Needed := (NewPos - FCapacity + MemoryDelta - 1) Div MemoryDelta;
SetCapacity(FCapacity + Needed * MemoryDelta);
End;
End;
Move(Buffer, FBuffer^[FPosition], Count);
FPosition := NewPos;
End;
Result := Count;
End;
Function TMemoryStream.Seek(Offset: LongInt; Origin: Word): LongInt;
Begin
Case Origin Of
soFromBeginning: Result := Offset;
soFromCurrent: Result := FPosition + Offset;
soFromEnd: Result := FSize - Offset;
End;
If (Result < 0) Or (Result > FSize) Then Error(SStreamSeekErrorText)
Else FPosition := Result;
End;
Procedure TMemoryStream.LoadFromStream(Stream: TStream);
Var
ToDo: LongInt;
Begin
Stream.Position := 0;
ToDo := Stream.Size;
SetSize(ToDo);
If ToDo <> 0 Then Stream.ReadBuffer(FBuffer^[0], ToDo);
End;
Procedure TMemoryStream.LoadFromFile(Const FileName:String);
Var
Source: TFileStream;
Begin
Source := TFileStream.Create(FileName, Stream_OpenRead);
Try
LoadFromStream(Source);
Finally
Source.Destroy;
End;
End;
Procedure TMemoryStream.SaveToStream(Stream: TStream);
Begin
If FSize <> 0 Then Stream.WriteBuffer(FBuffer^[0], FSize);
End;
Procedure TMemoryStream.SaveToFile(Const FileName:String);
Var
Dest: TFileStream;
Begin
Dest := TFileStream.Create(FileName, Stream_Create);
Try
SaveToStream(Dest);
Finally
Dest.Destroy;
End;
End;
Procedure TMemoryStream.SetCapacity(NewCapacity: LongInt);
Begin
If FCapacity=NewCapacity Then Exit;
FBuffer := ReAllocMem(FBuffer, FCapacity, NewCapacity);
FCapacity := NewCapacity;
If FSize > FCapacity Then FSize := FCapacity;
If FPosition > FSize Then FPosition := FSize;
End;
Procedure TMemoryStream.SetSize(NewSize: LongInt);
Begin
Clear;
SetCapacity(NewSize);
FSize := NewSize;
End;
Procedure TMemoryStream.Clear;
Begin
SetCapacity(0);
End;
{
╔═══════════════════════════════════════════════════════════════════════════╗
║ ║
║ Speed-Pascal/2 Version 2.0 ║
║ ║
║ Speed-Pascal Component Classes (SPCC) ║
║ ║
║ This section: TList Class Implementation ║
║ ║
║ (C) 1995,97 SpeedSoft. All rights reserved. Disclosure probibited ! ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════╝
}
Procedure TList.Error;
Begin
Raise EListError.Create(LoadNLSStr(SListErrorText));
End;
Function TList.Get(Index:LongInt):Pointer;
Begin
Result := Nil;
If (Index < 0) Or (Index >= FCount) Then Error
Else Result := FList^[Index];
End;
Procedure TList.Put(Index:LongInt;Item:Pointer);
Begin
If (Index < 0) Or (Index >= FCount) Then Error
Else FList^[Index] := Item;
End;
Procedure TList.Grow;
Var gr:LongInt;
Begin
If FGrowth <= 0 Then
Begin
If FCapacity < 128 Then gr := 16
Else gr := FCapacity Shr 3;
End
Else gr := FGrowth;
SetCapacity(FCapacity + gr);
End;
Procedure TList.SetCapacity(NewCapacity:LongInt);
Var NewList:PPointerList;
Begin
If (NewCapacity > MaxListSize) Or (NewCapacity < FCount) Then Error
Else
If NewCapacity <> FCapacity Then
Begin
If NewCapacity > 0 Then
Begin
GetMem(NewList, NewCapacity*SizeOf(Pointer));
If FCount > 0 Then System.Move(FList^,NewList^,
FCount*SizeOf(Pointer));
End
Else NewList := Nil;
If FList<>Nil Then FreeMem(FList, FCapacity*SizeOf(Pointer));
FCapacity := NewCapacity;
FList := NewList;
End;
End;
Procedure TList.SetCount(NewCount:LongInt);
Var I:LongInt;
Begin
If NewCount=FCount Then Exit;
If (NewCount > MaxListSize) Or (NewCount < 0) Then Error
Else
Begin
If NewCount > FCapacity Then SetCapacity(NewCount);
If NewCount < FCount Then
Begin
For I := NewCount To FCount-1 Do FreeItem(FList^[I]);
End
Else FillChar(FList^[FCount], (NewCount-FCount)*SizeOf(Pointer),0);
FCount := NewCount;
End;
End;
{--- Public part ------------------------------------------------------------}
(* Clear the whole List And Destroy the List Object *)
Destructor TList.Destroy;
Begin
Clear;
Inherited Destroy;
End;
(* Clear the whole List And Release the allocated Memory *)
Procedure TList.Clear;
Begin
SetCount(0);
SetCapacity(0);
End;
(* Append A New Item At the End Of the List And return the New Index *)
Function TList.Add(Item:Pointer):LongInt;
Begin
If FCount = FCapacity Then Grow;
FList^[FCount] := Item;
Inc(FCount);
Result := FCount-1;
End;
(* Delete the Item And decrement the Count Of elements In the List *)
Procedure TList.Delete(Index:LongInt);
Begin
If (Index < 0) Or (Index >= FCount) Then Error
Else
Begin
FreeItem(FList^[Index]);
Dec(FCount);
If Index <> FCount Then System.Move(FList^[Index + 1],FList^[Index],
(FCount-Index)*SizeOf(Pointer));
End;
End;
(* Remove the Item And decrement the Count Of elements In the List *)
Function TList.Remove(Item:Pointer):LongInt;
Begin
Result := IndexOf(Item);
If Result <> -1 Then Delete(Result);
End;
(* Release the Memory allocated by the Item *)
Procedure TList.FreeItem(Item:Pointer);
Begin
If FOnFreeItem <> Nil Then FOnFreeItem(Self,Item);
End;
(* Cut the specified Range out Of the List (including both indices) *)
Procedure TList.Cut(Index1,Index2:LongInt);
Var I,Swap:LongInt;
Begin
If (Index1 < 0) Or (Index1 >= FCount) Or
(Index2 < 0) Or (Index2 >= FCount) Then Error
Else
Begin
If Index2 < Index1 Then
Begin
Swap := Index1;
Index1 := Index2;
Index2 := Swap;
End;
For I := Index1 To Index2 Do FreeItem(FList^[I]);
If Index2 <> FCount-1 Then System.Move(FList^[Index2+1],FList^[Index1],
(FCount-Index2)*SizeOf(Pointer));
Dec(FCount,Index2-Index1+1);
End;
End;
(* Insert A New Item At the specified Position In the List *)
Procedure TList.Insert(Index:LongInt;Item:Pointer);
Begin
If (Index < 0) Or (Index > FCount) Then Error
Else
Begin
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;
End;
(* Exchange two Items In the List *)
Procedure TList.Exchange(Index1,Index2:LongInt);
Var Item:Pointer;
Begin
Item := Get(Index1);
Put(Index1, Get(Index2));
Put(Index2, Item);
End;
(* Move an Item To A New Position In the List *)
Procedure TList.Move(CurIndex,NewIndex:LongInt);
Var Item:Pointer;
Begin
If (CurIndex < 0) Or (CurIndex >= FCount) Or
(NewIndex < 0) Or (NewIndex >= FCount) Then Error
Else
If CurIndex <> NewIndex Then
Begin
Item := FList^[CurIndex];
If CurIndex < NewIndex
Then System.Move(FList^[CurIndex+1], FList^[CurIndex],
(NewIndex-CurIndex)*SizeOf(Pointer))
Else System.Move(FList^[NewIndex], FList^[NewIndex+1],
(CurIndex-NewIndex)*SizeOf(Pointer));
FList^[NewIndex] := Item;
End;
End;
(* return the Index Of an Item *)
Function TList.IndexOf(Item:Pointer):LongInt;
Begin
For Result := 0 To FCount-1 Do
If FList^[Result] = Item Then Exit;
Result := -1;
End;
(* return the First Item In the List *)
Function TList.First:Pointer;
Begin
Result := Get(0);
End;
(* return the Last Item In the List *)
Function TList.Last:Pointer;
Begin
Result := Get(FCount-1);
End;
(* Expand the List If Capacity Is reached *)
Function TList.Expand:TList;
Begin
If FCount = FCapacity Then Grow;
Result := Self;
End;
(* Remove All Nil elements In the List *)
Procedure TList.Pack;
Var I:LongInt;
Begin
For I := FCount-1 DownTo 0 Do
If FList^[I] = Nil Then Delete(I);
End;
Procedure TList.Sort(Compare: TListSortCompare);
Procedure Swap(I, K: LongInt);
Var
Item: Pointer;
Begin
Item := FList^[I];
FList^[I] := FList^[K];
FList^[K] := Item;
End;
Procedure Reheap(I, K: LongInt);
Var
J: LongInt;
Begin
J := I;
While J Shl 1 < K Do
Begin
If Compare(FList^[J Shl 1 - 1], FList^[J Shl 1 + 1 - 1]) > 0 Then J := J Shl 1
Else J := J Shl 1 + 1;
End;
If J Shl 1 = K Then J := K;
While Compare(FList^[I - 1], FList^[J - 1]) > 0 Do J := J Shr 1;
Swap(I - 1, J - 1);
J := J Shr 1;
While J >= I Do
Begin
Swap(I - 1, J - 1);
J := J Shr 1;
End;
End;
Var
I, C: LongInt;
Begin
C := Count;
For I := C Shr 1 DownTo 1 Do Reheap(I, C);
For I := C DownTo 2 Do
Begin
Swap(0, I - 1);
Reheap(1, I - 1);
End;
End;
{
╔═══════════════════════════════════════════════════════════════════════════╗
║ ║
║ Speed-Pascal/2 Version 2.0 ║
║ ║
║ Speed-Pascal Component Classes (SPCC) ║
║ ║
║ This section: TChainList Class Implementation ║
║ ║
║ (C) 1995,97 SpeedSoft. All rights reserved. Disclosure probibited ! ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════╝
}
Procedure TChainList.Error;
Begin
Raise EListError.Create(LoadNLSStr(SListErrorText));
End;
Function TChainList.Index2PLE(Index:LongInt):PChainListItem;
Var I:LongInt;
Begin
If (Index < 0) Or (Index >= FCount) Then Result := Nil
Else
Begin
Result := FList;
For I := 0 To Index-1 Do Result := Result^.Next;
If Result = Nil Then Exit;
End;
End;
Function TChainList.Item2PLE(Item:Pointer):PChainListItem;
Begin
Result := FList;
While Result <> Nil Do
Begin
If Result^.Item = Item Then Exit;
Result := Result^.Next;
End;
End;
Function TChainList.PLE2Index(ple:PChainListItem):LongInt;
Var ple1:PChainListItem;
Begin
Result := -1;
ple1 := FList;
While ple1 <> Nil Do
Begin
Inc(Result);
If ple1 = ple Then Exit;
ple1 := ple1^.Next;
End;
Result := -1;
End;
Function TChainList.Item2Index(Item:Pointer):LongInt;
Var ple:PChainListItem;
Begin
Result := -1;
ple := FList;
While ple <> Nil Do
Begin
Inc(Result);
If ple^.Item = Item Then Exit;
ple := ple^.Next;
End;
Result := -1;
End;
Procedure TChainList.Connect(ple1,ple2:PChainListItem);
Begin
If ple1 <> Nil Then ple1^.Next := ple2
Else FList := ple2;
If ple2 <> Nil Then ple2^.Prev := ple1
Else FListEnd := ple1;
End;
Function TChainList.Get(Index:LongInt):Pointer;
Var ple:PChainListItem;
Begin
ple := Index2PLE(Index);
If ple = Nil Then Error;
Result := ple^.Item;
End;
Procedure TChainList.Put(Index:LongInt;Item:Pointer);
Var ple:PChainListItem;
Begin
ple := Index2PLE(Index);
If ple = Nil Then Error;
ple^.Item := Item;
End;
Destructor TChainList.Destroy;
Begin
Clear;
Inherited Destroy;
End;
Procedure TChainList.Clear;
Var I:LongInt;
ple,plenext:PChainListItem;
Begin
ple := FList;
For I := 0 To FCount-1 Do
Begin
FreeItem(ple^.Item);
plenext := ple^.Next;
Dispose(ple);
ple := plenext;
End;
FCount := 0;
FList := Nil;
FListEnd := Nil;
End;
Function TChainList.Add(Item:Pointer):LongInt;
Var plenew:PChainListItem;
Begin
New(plenew);
plenew^.Item := Item;
plenew^.Next := Nil;
Connect(FListEnd,plenew);
FListEnd := plenew;
Result := FCount;
Inc(FCount);
End;
Function TChainList.Remove(Item:Pointer):LongInt;
Var I:LongInt;
ple:PChainListItem;
Begin
ple := FList;
For I := 0 To FCount-1 Do
Begin
If ple^.Item = Item Then
Begin
FreeItem(ple^.Item);
Result := I;
Connect(ple^.Prev,ple^.Next);
Dispose(ple);
Dec(FCount);
Exit;
End;
ple := ple^.Next;
End;
Result := -1;
End;
Procedure TChainList.Delete(Index:LongInt);
Var ple:PChainListItem;
Begin
ple := Index2PLE(Index);
If ple = Nil Then Error;
FreeItem(ple^.Item);
Connect(ple^.Prev,ple^.Next);
Dispose(ple);
Dec(FCount);
End;
Procedure TChainList.FreeItem(Item:Pointer);
Begin
If FOnFreeItem <> Nil Then FOnFreeItem(Self,Item);
End;
Function TChainList.First:Pointer;
Var ple:PChainListItem;
Begin
ple := FList;
If ple = Nil Then Error;
Result := ple^.Item;
End;
Function TChainList.Last:Pointer;
Var ple:PChainListItem;
Begin
ple := FListEnd;
If ple = Nil Then Error;
Result := ple^.Item;
End;
Function TChainList.IndexOf(Item:Pointer):LongInt;
Begin
Result := Item2Index(Item);
End;
Procedure TChainList.Insert(Index:LongInt;Item:Pointer);
Var ple,plenew:PChainListItem;
Begin
If Index < 0 Then Error;
If Index > FCount Then Error;
ple := Index2PLE(Index);
If ple <> Nil Then
Begin
New(plenew);
plenew^.Item := Item;
Connect(ple^.Prev,plenew);
Connect(plenew,ple);
Inc(FCount);
End
Else Add(Item);
End;
Procedure TChainList.Move(CurIndex,NewIndex:LongInt);
Var TempItem:Pointer;
Begin
If CurIndex < 0 Then Error;
If CurIndex >= FCount Then Error;
If NewIndex < 0 Then Error;
If NewIndex >= FCount Then Error;
If CurIndex = NewIndex Then Exit;
TempItem := Get(CurIndex);
Delete(CurIndex);
Insert(NewIndex,TempItem);
End;
Procedure TChainList.Exchange(Index1,Index2:LongInt);
Var ple1,ple2:PChainListItem;
TempItem:Pointer;
Begin
ple1 := Index2PLE(Index1);
ple2 := Index2PLE(Index2);
If (ple1 = Nil) Or (ple2 = Nil) Then Error;
TempItem := ple1^.Item;
ple1^.Item := ple2^.Item;
ple2^.Item := TempItem;
End;
Procedure TChainList.Pack;
Var I:LongInt;
ple,plenext:PChainListItem;
Begin
ple := FList;
For I := 0 To FCount-1 Do
Begin
plenext := ple^.Next;
If ple^.Item = Nil Then
Begin
Connect(ple^.Prev,ple^.Next);
Dispose(ple);
Dec(FCount);
End;
ple := plenext;
End;
End;
{ --- Utility FUNCTIONs For TStrItem --- }
Function NewStrItem(Const AString: String; AObject: TObject): PStrItem;
Begin
GetMem(Result, SizeOf(TObject) + Length(AString) + 1);
Result^.FObject := AObject;
Result^.FString := AString;
End;
Procedure DisposeStrItem(P: PStrItem);
Begin
FreeMem(P, SizeOf(TObject) + Length(P^.FString) + 1);
End;
{ --- TStrings --- }
Procedure TStrings.Append(Const S: String);
Begin
Add(S);
End;
Procedure TStrings.Put(Index: LongInt; Const S: String);
Var Temp:TObject;
Begin
Temp := GetObject(Index);
Delete(Index);
InsertObject(Index, S, Temp);
End;
{$HINTS OFF}
Function TStrings.GetObject(Index: LongInt): TObject;
Begin
Result := Nil;
End;
Procedure TStrings.PutObject(Index: LongInt; AObject: TObject);
Begin
End;
{$HINTS ON}
Function TStrings.Add(Const S: String): LongInt;
Begin
Result := Count;
Insert(Result, S);
End;
Function TStrings.AddObject(Const S: String; AObject: TObject): LongInt;
Begin
Result := Add(S);
PutObject(Result, AObject);
End;
Procedure TStrings.AddStrings(AStrings: TStrings);
Var
I: LongInt;
Begin
BeginUpdate;
Try
For I := 0 To AStrings.Count - 1 Do
AddObject(AStrings.Get(I), AStrings.GetObject(I));
Finally
EndUpdate;
End;
End;
Procedure TStrings.Assign(AStrings: TStrings);
Begin
If AStrings=Self Then Exit;
BeginUpdate;
Try
Clear;
If AStrings<>Nil Then AddStrings(AStrings);
Finally
EndUpdate;
End;
End;
Procedure TStrings.BeginUpdate;
Begin
If FUpdateSemaphore = 0 Then SetUpdateState(True);
Inc(FUpdateSemaphore);
End;
Procedure TStrings.EndUpdate;
Begin
Dec(FUpdateSemaphore);
If FUpdateSemaphore = 0 Then SetUpdateState(False);
End;
Function TStrings.Equals(AStrings: TStrings): Boolean;
Var
N: LongInt;
Begin
Result := False;
If Count <> AStrings.Count Then Exit;
For N := 0 To Count - 1 Do If Get(N) <> AStrings.Get(N) Then Exit;
Result := True;
End;
Procedure TStrings.Exchange(Index1, Index2: LongInt);
Var
S: String;
O: TObject;
Begin
S := Get(Index1);
O := GetObject(Index1);
Put(Index1, Get(Index2));
PutObject(Index1, GetObject(Index2));
Put(Index2, S);
PutObject(Index2, O);
End;
Function TStrings.GetName(Index: LongInt): String;
Var
P: Integer;
Begin
Result := Get(Index);
P := Pos('=', Result);
System.Delete(Result, P, Length(Result) - P + 1);
End;
Procedure SingleLineToBuffer(Const S: String; Var P: PChar);
Begin
Move(S[1], P[0], Length(S));
Inc(P, Length(S));
P[0] := #13;
P[1] := #10;
Inc(P, 2);
End;
Function TStrings.GetText: PChar;
Var
N, BufSize: LongInt;
BufPtr: PChar;
Begin
BufSize := 1;
For N := 0 To Count - 1 Do Inc(BufSize, Length(Get(N)) + 2);
Result := StrAlloc(BufSize);
BufPtr := Result;
For N := 0 To Count - 1 Do SingleLineToBuffer(Get(N), BufPtr);
BufPtr[0] := #0;
End;
Function TStrings.GetTextStr: AnsiString;
Var
N, BufSize: LongInt;
BufPtr: PChar;
Begin
BufSize := 0;
For N := 0 To Count - 1 Do Inc(BufSize, Length(Get(N)) + 2);
SetLength(Result, BufSize);
BufPtr := PChar(Result);
For N := 0 To Count - 1 Do SingleLineToBuffer(Get(N), BufPtr);
End;
Function TStrings.GetValue(Const Name: String): String;
Begin
FindValue(Name, Result);
End;
Function TStrings.FindValue(Const Name: String; Var Value: String): LongInt;
Var
P: Integer;
Begin
For Result := 0 To Count - 1 Do
Begin
Value := Get(Result);
P := Pos('=', Value);
If P <> 0 Then
Begin
If CompareText(Copy(Value, 1, P - 1), Name) = 0 Then
Begin
System.Delete(Value, 1, P);
Exit;
End;
End;
End;
Result := -1;
Value := '';
End;
Function TStrings.IndexOfName(Const Name: String): LongInt;
Var
P: Integer;
S: String;
Begin
For Result := 0 To Count - 1 Do
Begin
S := Get(Result);
P := Pos('=', S);
If CompareText(Copy(S, 1, P - 1), Name) = 0 Then Exit;
End;
Result := -1;
End;
Function TStrings.IndexOf(Const S: String): LongInt;
Begin
For Result := 0 To Count-1 Do If CompareText(Get(Result), S) = 0 Then Exit;
Result := -1;
End;
Function TStrings.IndexOfObject(AObject: TObject): LongInt;
Begin
For Result := 0 To Count-1 Do If GetObject(Result) = AObject Then Exit;
Result := -1;
End;
Procedure TStrings.InsertObject(Index: LongInt; Const S: String; AObject: TObject);
Begin
Insert(Index, S);
PutObject(Index, AObject);
End;
Procedure TStrings.LoadFromFile(Const FileName: String);
Var
Source: TFileStream;
Begin
Try
Source := TFileStream.Create(FileName, Stream_OpenRead);
Except
Source.Destroy;
Raise;
End;
Try
LoadFromStream(Source);
Finally
Source.Destroy;
End;
End;
Procedure TStrings.LoadFromStream(Stream: TStream);
Begin
BeginUpdate;
Clear;
Try
While Not Stream.EndOfData Do Add(Stream.ReadLn);
Finally
EndUpdate;
End;
End;
Procedure TStrings.Move(CurIndex, NewIndex: LongInt);
Var
O: TObject;
S: String;
Begin
If CurIndex = NewIndex Then Exit;
S := Get(CurIndex);
O := GetObject(CurIndex);
FPreventFree := True;
Delete(CurIndex);
InsertObject(NewIndex, S, O);
FPreventFree := False;
End;
Procedure TStrings.SaveToFile(Const FileName: String);
Var
Dest: TFileStream;
Begin
Try
Dest := TFileStream.Create(FileName, Stream_Create);
Except
Dest.Destroy;
Raise;
End;
Try
SaveToStream(Dest);
Finally
Dest.Destroy;
End;
End;
Procedure TStrings.SaveToStream(Stream: TStream);
Var
N: LongInt;
Begin
For N := 0 To Count - 1 Do Stream.WriteLn(Get(N));
End;
Procedure TStrings.SetText(Text: PChar);
Function SingleLineFromBuffer(Var P: PChar): String;
Var
I: Integer;
Q: PChar;
Begin
I := 0;
Q := P;
While Not (Q[0] In [#13, #10, #26, #0]) And (I < 255) Do
Begin
Inc(Q);
Inc(I);
End;
StrMove(@Result[1], P, I);
SetLength(Result, I);
P := Q;
If P[0] = #13 Then Inc(P);
If P[0] = #10 Then Inc(P);
End;
Begin
BeginUpdate;
Try
Clear;
If Text<>Nil Then While Not (Text[0] In [#0, #26]) Do
Begin
Add(SingleLineFromBuffer(Text));
End;
Finally
EndUpdate;
End;
End;
Procedure TStrings.SetTextStr(Const Value: AnsiString);
Begin
SetText(PChar(Value));
End;
{$HINTS OFF}
Procedure TStrings.SetUpdateState(Updating: Boolean);
Begin
End;
{$HINTS ON}
Procedure TStrings.SetValue(Const Name, Value: String);
Var
I: LongInt;
S: String;
Begin
I := FindValue(Name, S);
If I < 0 Then
Begin
If Length(Value) <> 0 Then Add(Name + '=' + Value)
End
Else
Begin
If Length(Value) <> 0 Then Put(I, Name + '=' + Value)
Else Delete(I);
End;
End;
{ --- TStringList --- }
Constructor TStringList.Create;
Begin
Inherited Create;
FList := TList.Create;
FCaseSensitive := False;
End;
Destructor TStringList.Destroy;
Begin
{ Die folgenden zwei Zeilen später wieder ändern }
Pointer(FOnChanging) := Nil;
Pointer(FOnChange) := Nil;
Clear;
FList.Destroy;
FList := Nil;
Inherited Destroy;
End;
Function TStringList.Add(Const S: String): LongInt;
Begin
If FSorted Then
Begin
If Find(S, Result) Then
Begin
Case FDuplicates Of
dupIgnore: Exit;
dupError: Raise EStringListError.Create(LoadNLSStr(SStringListDupeErrorText));
End;
End;
End
Else Result := Count;
Changing;
FList.Insert(Result, NewStrItem(S, Nil));
changed;
End;
Procedure TStringList.changed;
Begin
If (FUpdateSemaphore = 0) And (FOnChange <> Nil) Then FOnChange(Self);
End;
Procedure TStringList.Changing;
Begin
If (FUpdateSemaphore = 0) And (FOnChanging <> Nil) Then FOnChanging(Self);
End;
Procedure TStringList.Clear;
Var
N: LongInt;
Begin
If Count > 0 Then
Begin
Changing;
FLockChange:=True;
For N := Count - 1 DownTo 0 Do Delete(N);
FLockChange:=False;
changed;
End;
End;
Procedure TStringList.Delete(Index: LongInt);
Begin
If FLockChange Then
Begin
FreeItem(GetObject(Index));
DisposeStrItem(FList.Get(Index));
FList.Delete(Index);
End
Else
Begin
Changing;
If Not FPreventFree Then FreeItem(GetObject(Index));
DisposeStrItem(FList.Get(Index));
FList.Delete(Index);
changed;
End;
End;
Procedure TStringList.FreeItem(AObject:TObject);
Begin
If FOnFreeItem <> Nil Then FOnFreeItem(Self,AObject);
End;
Procedure TStringList.Exchange(Index1, Index2: LongInt);
Begin
Changing;
FList.Exchange(Index1, Index2);
changed;
End;
Function TStringList.Find(Const S: String; Var Index: LongInt): Boolean;
Var
Low, High: LongInt;
CMP: Integer;
DoCompare: Function(Const S, T: String): Integer;
Begin
If CaseSensitive Then DoCompare := CompareStr
Else DoCompare := CompareText;
If sorted Then
Begin
{ binary Search }
Low := 0;
High := GetCount - 1;
Index := 0;
CMP := -1;
While (CMP <> 0) And (Low <= High) Do
Begin
Index := (Low + High) Div 2;
CMP := DoCompare(S, Get(Index));
If CMP < 0 Then High := Index -1
Else If CMP > 0 Then Low := Index + 1;
End;
If Low = Index + 1 Then Inc(Index);
Result := (CMP = 0);
End
Else
Begin
{ Linear Search }
Index := 0;
While (Index < Count) And (DoCompare(Get(Index), S) <> 0) Do Inc(Index);
Result := (Index < Count);
End;
End;
Function TStringList.Get(Index: LongInt): String;
Begin
Result := PStrItem(FList.Get(Index))^.FString;
End;
Function TStringList.GetCount: LongInt;
Begin
Result := FList.Count;
End;
Function TStringList.GetObject(Index: LongInt): TObject;
Begin
Result := PStrItem(FList.Get(Index))^.FObject;
End;
Function TStringList.IndexOf(Const S: String): LongInt;
Begin
If Not Find(S, Result) Then Result := -1;
End;
Procedure TStringList.Insert(Index: LongInt; Const S: String);
Begin
Changing;
If FSorted Then Raise EListError.Create(LoadNLSStr(SStringListInsertErrorText))
Else FList.Insert(Index, NewStrItem(S, Nil));
changed;
End;
Procedure TStringList.Put(Index: LongInt; Const S: String);
Var TempObj:TObject;
pstr:PStrItem;
Begin
Changing;
pstr := FList.Get(Index);
TempObj := pstr^.FObject;
DisposeStrItem(pstr);
FList.Put(Index, NewStrItem(S, TempObj));
changed;
End;
Procedure TStringList.PutObject(Index: LongInt; AObject: TObject);
Var
P: PStrItem;
Begin
P := FList.Get(Index);
P^.FObject := AObject;
End;
Procedure TStringList.BottomUpHeapSort;
Var
DoCompare: Function (Const S, T: String): Integer;
Procedure Reheap(I, K: LongInt);
Var
J: LongInt;
Begin
J := I;
While J Shl 1 < K Do
Begin
If DoCompare(Get(J Shl 1 - 1), Get(J Shl 1 + 1 - 1)) > 0 Then J := J Shl 1
Else J := J Shl 1 + 1;
End;
If J Shl 1 = K Then J := K;
While DoCompare(Get(I - 1), Get(J - 1)) > 0 Do J := J Shr 1;
FList.Exchange(I - 1, J - 1);
J := J Shr 1;
While J >= I Do
Begin
FList.Exchange(I - 1, J - 1);
J := J Shr 1;
End;
End;
Var
I, C: LongInt;
Begin
If CaseSensitive Then DoCompare := CompareStr
Else DoCompare := CompareText;
C := Count;
For I := C Shr 1 DownTo 1 Do Reheap(I, C);
For I := C DownTo 2 Do
Begin
FList.Exchange(0, I - 1);
Reheap(1, I - 1);
End;
End;
Procedure TStringList.SetCaseSensitive(Value: Boolean);
Var
old: Boolean;
Begin
Changing;
old := FCaseSensitive;
FCaseSensitive := Value;
If FSorted And (FCaseSensitive <> old) Then Sort;
changed;
End;
Procedure TStringList.SetSorted(Value: Boolean);
Begin
Changing;
If (Not FSorted) And Value Then Sort;
FSorted := Value;
changed;
End;
Procedure TStringList.SetUpdateState(Updating: Boolean);
Begin
If Updating Then Changing
Else changed;
End;
Procedure TStringList.Sort;
Begin
If Count > 1 Then
Begin
Changing;
BottomUpHeapSort;
changed;
End;
End;
{
╔═══════════════════════════════════════════════════════════════════════════╗
║ ║
║ Speed-Pascal/2 Version 2.0 ║
║ ║
║ Speed-Pascal Component Classes (SPCC) ║
║ ║
║ This section: Some useful FUNCTIONs ║
║ ║
║ (C) 1995,97 SpeedSoft. All rights reserved. Disclosure probibited ! ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════╝
}
Function MessageBox2(Const Msg:String;Typ:TMsgDlgType;Buttons:TMsgDlgButtons):TMsgDlgReturn;
Var C,Title:cstring;
iFlags:LongWord;
mresult:LongWord;
Begin
C:=Msg;
{$IFDEF OS2}
iFlags:=MB_MOVEABLE OR MB_APPLMODAL;
If Typ=mtError Then
Begin
Title:=LoadNLSStr(SError);
iFlags:=iFlags Or MB_ERROR;
End
Else If Typ=mtCritical Then
Begin
Title:=LoadNLSStr(SCriticalError);
iFlags:=iFlags Or MB_CRITICAL;
End
Else If Typ=mtInformation Then
Begin
Title:=LoadNLSStr(sInformation);
iFlags:=iFlags Or MB_INFORMATION;
End
Else If Typ=mtWarning Then
Begin
Title:=LoadNLSStr(SWarning);
iFlags:=iFlags Or MB_WARNING;
End
Else If Typ=mtConfirmation Then
Begin
Title:=LoadNLSStr(SMessage);
iFlags:=iFlags Or MB_ICONQUESTION;
End
Else
Begin
Title:=ParamStr(0);
iFlags:=iFlags Or MB_NOICON;
End;
If Buttons*[mbOk]<>[] Then
Begin
If Buttons*[mbCancel]<>[] Then iFlags:=iFlags Or MB_OKCANCEL
Else iFlags:=iFlags Or MB_OK;
End
Else If Buttons*[mbCancel]<>[] Then
Begin
If Buttons*mbYesNo<>[] Then iFlags:=iFlags Or MB_YESNOCANCEL
Else If Buttons*[mbRetry]<>[] Then iFlags:=iFlags Or MB_RETRYCANCEL
Else iFlags:=iFlags Or MB_CANCEL;
End
Else If Buttons*[mbYes]<>[] Then
Begin
If Buttons*[mbNo]<>[] Then iFlags:=iFlags Or MB_YESNO
Else iFlags:=iFlags Or MB_OK;
End;
If Buttons*mbAbortRetryIgnore<>[] Then iFlags:=iFlags Or MB_ABORTRETRYIGNORE;
InitPM;
mresult:=WinMessageBox(HWND_DESKTOP,HWND_DESKTOP,C,Title,0,iFlags);
Case mresult Of
MBID_OK:Result:=mrOk;
MBID_CANCEL:Result:=mrCancel;
MBID_YES:Result:=mrYes;
MBID_NO:Result:=mrNo;
MBID_IGNORE:Result:=mrIgnore;
MBID_ABORT:Result:=mrAbort;
MBID_RETRY:Result:=mrRetry;
Else Result:=mrCancel;
End; {Case}
{$ENDIF}
{$IFDEF Win95}
iFlags:=MB_TASKMODAL;
If Typ=mtError Then
Begin
Title:=LoadNLSStr(SError);
iFlags:=iFlags Or MB_ICONHAND;
End
Else If Typ=mtCritical Then
Begin
Title:=LoadNLSStr(SCriticalError);
iFlags:=iFlags Or MB_ICONHAND;
End
Else If Typ=mtInformation Then
Begin
Title:=LoadNLSStr(sInformation);
iFlags:=iFlags Or MB_ICONEXCLAMATION;
End
Else If Typ=mtWarning Then
Begin
Title:=LoadNLSStr(SWarning);
iFlags:=iFlags Or MB_ICONEXCLAMATION;
End
Else If Typ=mtConfirmation Then
Begin
Title:=LoadNLSStr(SMessage);
iFlags:=iFlags Or MB_ICONQUESTION;
End
Else
Begin
Title:=ParamStr(0);
End;
If Buttons*[mbOk]<>[] Then
Begin
If Buttons*[mbCancel]<>[] Then iFlags:=iFlags Or MB_OKCANCEL
Else iFlags:=iFlags Or MB_OK;
End
Else If Buttons*[mbCancel]<>[] Then
Begin
If Buttons*mbYesNo<>[] Then iFlags:=iFlags Or MB_YESNOCANCEL
Else If Buttons*[mbRetry]<>[] Then iFlags:=iFlags Or MB_RETRYCANCEL
Else iFlags:=iFlags Or MB_OK; //MB_CANCEL only Not present
End
Else If Buttons*[mbYes]<>[] Then
Begin
If Buttons*[mbNo]<>[] Then iFlags:=iFlags Or MB_YESNO
Else iFlags:=iFlags Or MB_OK;
End;
If Buttons*mbAbortRetryIgnore<>[] Then iFlags:=iFlags Or MB_ABORTRETRYIGNORE;
mresult:=WinUser.MessageBox(0,C,Title,iFlags);
Case mresult Of
IDOK:Result:=mrOk;
IDCANCEL:Result:=mrCancel;
IDYES:Result:=mrYes;
IDNO:Result:=mrNo;
IDIGNORE:Result:=mrIgnore;
IDABORT:Result:=mrAbort;
IDRETRY:Result:=mrRetry;
Else Result:=mrCancel;
End; {Case}
{$ENDIF}
End;
Function ErrorBox2(Const Msg:String):TMsgDlgReturn;
Begin
Beep(1000,200);
Result:=MessageBox2(Msg,mtError,[mbOk]);
End;
{
╔═══════════════════════════════════════════════════════════════════════════╗
║ ║
║ Speed-Pascal/2 Version 2.0 ║
║ ║
║ Speed-Pascal Component Classes (SPCC) ║
║ ║
║ This section: SCU File format types And records ║
║ ║
║ (C) 1995,97 SpeedSoft. All rights reserved. Disclosure probibited ! ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════╝
}
Type
PResourceEntry=^TResourceEntry;
TResourceEntry=Record
ResName:TResourceName;
DataOffset:LongInt;
DataLen:LongInt;
End;
Function CompareResMem(Var Buf1,Buf2;Size:LongWord):Boolean;
Var R:Boolean;
Begin
Asm
CLD
MOV ESI,Buf1
MOV EDI,Buf2
MOV ECX,Size
CLD
REP
CMPSB
SETE AL
MOV R,AL
End;
Result:=R;
End;
{$HINTS OFF}
Function TResourceStream.NewResourceEntry(Const ResName:TResourceName;
Var Data;DataLen:LongInt):Boolean;
Var dummy:PResourceEntry;
SavePos,T,HeadPos:LongInt;
P:Pointer;
Label L;
Begin
Result:=False;
If DataLen=0 Then Exit;
SavePos:=Position;
HeadPos:=8; {Initial Resource Header}
If FResourceList<>Nil Then
Begin
For T:=0 To FResourceList.Count-1 Do
Begin
dummy:=FResourceList.Items[T];
If dummy^.ResName=ResName Then
If dummy^.DataLen=DataLen Then
Begin
Position:=dummy^.DataOffset;
P:=Pointer(FBuffer);
Inc(P,Position);
If CompareResMem(P^,Data,DataLen) Then
Begin
Position:=SavePos;
SavePos:=dummy^.DataOffset;
Goto L;
End;
End;
Inc(HeadPos,SizeOf(TResourceEntry)); {Length Of Info}
End;
End;
Position:=SavePos;
If Write(Data,DataLen)=0 Then Exit;
//reserve A Header entry
HeadPos:=FHeaderPos;
Inc(FHeaderPos,SizeOf(TResourceEntry)); {Length Of Info}
New(dummy);
dummy^.ResName:=ResName;
dummy^.DataOffset:=SavePos;
dummy^.DataLen:=DataLen;
If FResourceList=Nil Then FResourceList.Create;
FResourceList.Add(dummy);
L:
//Write Position Of Resource
If SCUStream.Write(HeadPos,4)=0 Then Exit;
Result:=True;
End;
{$HINTS ON}
Function TResourceStream.WriteResourcesToStream(Stream:TMemoryStream):Boolean;
Var T,t1:LongInt;
PatchOffset,StartPos:LongInt;
dummy:PResourceEntry;
P:Pointer;
Begin
Result:=False;
If FResourceList=Nil Then
Begin
T:=0; //no resources
If Stream.Write(T,4)=0 Then Exit;
Result:=True;
Exit;
End;
StartPos:=Stream.Position;
T:=FResourceList.Count; //Count Of Resource entries
If Stream.Write(T,4)=0 Then Exit;
PatchOffset:=Stream.Position;
T:=0;
If Stream.Write(T,4)=0 Then Exit; // Resource Data Offset patched later
For T:=0 To FResourceList.Count-1 Do
Begin
dummy:=FResourceList.Items[T];
If Stream.Write(dummy^,SizeOf(TResourceEntry))=0 Then Exit;
End;
//patch Offset To Resource Data
T:=Stream.Position;
Stream.Position:=PatchOffset;
t1:=T-StartPos;
If Stream.Write(t1,4)=0 Then Exit;
Stream.Position:=T;
//Write Resource Data
P:=Memory;
If Stream.Write(P^,Size)=0 Then Exit;
Result:=True;
End;
Destructor TResourceStream.Destroy;
Var T:LongInt;
dummy:PResourceEntry;
Begin
If FResourceList<>Nil Then
Begin
For T:=0 To FResourceList.Count-1 Do
Begin
dummy:=FResourceList.Items[T];
Dispose(dummy);
End;
FResourceList.Destroy;
FResourceList := Nil;
End;
Inherited Destroy;
End;
Type
TPropertyTyp=(TPropString,TPropSet,TPropLongInt,TPropEnum,
TPropClass);
PSCUPropInit=^TSCUPropInit;
TSCUPropInit=Record
PropertyName:String;
PropertySize:LongInt;
PropertyTyp:TPropertyTyp;
PropertyValue:Pointer;
End;
PSCUDesc=^TSCUDesc;
TSCUDesc=Record
NextEntryOffset:LongInt;
ClassName:String; //subclassed Class Name
BaseClassName:String; //base Class Name For designer
PropertyCount:LongInt; //Count Of properties To initialize
properties:PSCUPropInit;
End;
{
╔═══════════════════════════════════════════════════════════════════════════╗
║ ║
║ Speed-Pascal/2 Version 2.0 ║
║ ║
║ Speed-Pascal Component Classes (SPCC) ║
║ ║
║ This section: TPersistent Class Implementation ║
║ ║
║ (C) 1995,97 SpeedSoft. All rights reserved. Disclosure probibited ! ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════╝
}
Procedure TPersistent.AssignError(Source:TPersistent);
Var Msg:String;
Begin
If Source=Nil Then Msg:='Nil'
Else Msg:=Source.ClassName;
Raise EConvertError.Create('Convert '+ClassName+' to '+Msg+'.');
End;
Procedure TPersistent.AssignTo(Dest:TPersistent);
Begin
Dest.AssignError(Self);
End;
Procedure TPersistent.Assign(Source:TPersistent);
Begin
If Source<>Nil Then Source.AssignTo(Self)
Else AssignError(nil);
End;
{
╔═══════════════════════════════════════════════════════════════════════════╗
║ ║
║ Speed-Pascal/2 Version 2.0 ║
║ ║
║ Speed-Pascal Component Classes (SPCC) ║
║ ║
║ This section: TComponent Class Implementation ║
║ ║
║ (C) 1995,97 SpeedSoft. All rights reserved. Disclosure probibited ! ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════╝
}
Const //OldStyleFormat:Boolean=False;
LastSCUForm:TComponent=Nil;
Function GetClassNameFromSCU(NameTable:Pointer;Namep:LongWord):String;
Var ps:^String;
Begin
ps:=NameTable;
Inc(ps,Namep);
Result:=ps^;
End;
Function GetParentSCUFormDesign(Component:TComponent):TComponent;
Var AOwner:TComponent;
Begin
Result:=Nil;
AOwner:=Component;
//Search For First parent that has Is A Form And TypeName match
While AOwner <> Nil Do
Begin
//If AOwner.IDESCU_Data<>Nil Then
If csForm In AOwner.ComponentState Then
Begin
Result:=AOwner;
Exit;
End;
AOwner:=AOwner.FOwner;
End;
Result := Nil; //Error
End;
Function GetParentSCUFormRuntime(Component:TComponent;Name:String):TComponent;
Var AOwner:TComponent;
S:String;
Begin
Result:=Nil;
AOwner:=Component;
UpcaseStr(Name);
//Search For First parent that has TypeName match
While AOwner <> Nil Do
Begin
S:=AOwner.ClassName;
UpcaseStr(S);
If S=Name Then
Begin
Result:=AOwner;
Exit;
End;
AOwner:=AOwner.FOwner;
End;
Result := Nil; //Error
End;
Procedure InsertSCUMethod(AParent,Objekt:TComponent;
ProcName,ProcParams,PropertyName:String);
Var Methods:PIDE_Methods;
S,s2:String[64];
s1,s3:String;
Own:PIDE_OwnerList;
Label L;
Begin
S:=ProcName;
UpcaseStr(S);
s1:=ProcParams;
UpcaseStr(s1);
s2:=PropertyName;
UpcaseStr(s2);
//look If method Is still here
Methods:=AParent.FMethods;
While Methods<>Nil Do
Begin
s3:=Methods^.Name^;
UpcaseStr(s3);
If s3=S Then //ProcNames match
Begin
s3:=Methods^.Params^;
UpcaseStr(s3);
If s3=s1 Then //Parameters match --> only Add To List
Begin
Goto L;
End;
End;
Methods:=Methods^.Next;
End;
//Insert New Item
New(Methods);
Methods^.Next:=AParent.FMethods;
AParent.FMethods:=Methods;
AssignStr(Methods^.Name,ProcName);
AssignStr(Methods^.Params,ProcParams);
Methods^.Owners.Create;
L:
New(Own);
AssignStr(Own^.PropertyName,PropertyName);
Own^.Objekt:=Objekt;
Methods^.Owners.Add(Own);
End;
Function GetSCUProcParamsFromName(Objekt:TComponent;PropertyName:String):String;
Var p1:^LongWord;
B:Byte;
S,s1:String;
ps:^String;
pParent:Pointer;
Scope:Byte;
NameIndex:LongInt;
NameTable:^String;
Label L,ex,again;
Begin
//Search PropertyName
UpcaseStr(PropertyName);
p1:=Objekt.ClassInfo;
again:
//overread Object Size
Inc(p1,4);
pParent:=Pointer(p1^);
Inc(p1,8); //onto First Property Name
p1:=Pointer(p1^);
Inc(p1,4); //overread End Ptr
NameTable:=Pointer(p1^); //Name Table Of Class
Inc(p1,4); //overread Name Table poinzer
NameIndex:=p1^ And 255;
Inc(p1);
While NameIndex<>0 Do
Begin
s1[0]:=Chr(NameIndex);
Move(p1^,s1[1],NameIndex);
Inc(p1,NameIndex);
Scope:=p1^ And 255;
Inc(p1);
If Scope And 16=16 Then //stored ??
Begin
UpcaseStr(s1);
If s1=PropertyName Then //found
Begin
p1:=Pointer(p1^); //Type information
//overread Property access Info
If p1^ And 255<>0 Then Inc(p1,5)
Else Inc(p1);
If p1^ And 255<>0 Then Inc(p1,5)
Else Inc(p1);
//overread Property Type len
Inc(p1,4);
//Get Property Type
B:=p1^ And 255;
If Not (B In [PropType_ProcVar,PropType_FuncVar]) Then Goto ex; //Error
Inc(p1);
Goto L;
End;
End;
Inc(p1,4); //overread Type information Pointer
NameIndex:=p1^ And 255;
Inc(p1);
End;
If pParent<>Nil Then
Begin
p1:=pParent;
Inc(p1,4);
p1:=Pointer(p1^); //ClassInfo
Goto again;
End;
ex:
Result:='?';
Exit; //Not found;
L:
NameIndex:=p1^;
Inc(p1,4);
S:='';
While NameIndex<>0 Do
Begin
If S<>'' Then S:=S+';';
ps:=NameTable+NameIndex;
s1:=ps^;
B:=p1^ And 255;
Inc(p1);
Case B Of
1:s1:='VAR '+s1;
2:;
3:s1:='CONST '+s1;
End;
S:=S+s1;
NameIndex:=p1^; //TypeName
Inc(p1,4);
If NameIndex<>0 Then
Begin
ps:=NameTable+NameIndex;
s1:=ps^;
S:=S+':'+s1;
End;
NameIndex:=p1^;
Inc(p1,4);
End; //While
If S<>'' Then Result:='('+S+');'
Else Result:=S;
End;
Type PPropertyLink=^TPropertyLink;
TPropertyLink=Record
SelfPtr:TComponent;
Owner:TComponent;
WriteTyp:Byte;
WriteOffset:LongInt;
//WriteName:String[64];
LinkName:String[64];
Next:PPropertyLink;
End;
Const PropertyLinks:PPropertyLink=Nil;
Function GetPropertyTypeInfo2(Instance:TComponent;PropertyName:String;Var Info:TPropertyTypeInfo):Boolean;
Var L,C:^LongWord;
ps:^String;
S:String;
Label weiter;
Begin
Result:=False;
UpcaseStr(PropertyName);
L:=Pointer(Instance);
L:=Pointer(L^); //VMT address
While L<>Nil Do
Begin
Inc(L,4);
L:=Pointer(L^); //Class Info
C:=L;
Inc(L,12);
L:=Pointer(L^); //Property Info
Inc(L,4);
Info.NameTable:=Pointer(L^);
Inc(L,4); //Start Of properties
ps:=Pointer(L);
While ps^[0]<>#0 Do
Begin
If ps^[0]=PropertyName[0] Then //found !!
Begin
S:=ps^;
UpcaseStr(S);
If S=PropertyName Then
Begin
Result:=True;
Inc(L,Ord(ps^[0])+1); //skip Name
Info.Scope:=L^ And 255;
Inc(L);
L:=Pointer(L^); //Type And access Info
If ((Info.Scope And 24=0)Or(L=Nil)) Then
Begin
L:=Pointer(ps);
Goto weiter; //Search also parent !
End;
Info.PropInfo:=Pointer(L);
Info.Read.Kind:=L^ And 255;
Inc(L);
If Info.Read.Kind<>0 Then
Begin
Info.Read.VarOffset:=L^;
Inc(L,4);
End;
Info.Write.Kind:=L^ And 255;
Inc(L);
If Info.Write.Kind<>0 Then
Begin
Info.Write.VarOffset:=L^;
Inc(L,4);
End;
Info.Size:=L^;
Inc(L,4);
Info.TypeInfo:=Pointer(L);
Info.Typ:=L^ And 255;
Exit;
End;
End;
weiter:
Inc(L,Ord(ps^[0])+6); //skip This entry
ps:=Pointer(L);
End;
Inc(C,4);
L:=Pointer(C^); //parent VMT Or Nil
End;
End;
Function GetReference(Owner:TComponent):TComponent;
Begin
Result:=Owner.FReference;
End;
Procedure SetReference(Owner,Ref:TComponent);
Begin
Owner.FReference:=Ref;
End;
{$HINTS OFF}
Procedure TComponent.UpdateLinkList(Const PropertyName:String;LinkList:TList);
Begin
//LinkList Is A List Of TComponent Instances that the Inspector
//will display For the specified Property, you may only Remove Items !
End;
{$HINTS ON}
Type SCUTypes=(SCUNull,SCUByte,SCUWord,SCULongWord,SCUShortInt,SCUInteger,SCULongInt,SCUSingle,
SCUDouble,SCUExtended,SCUByteBool,SCUWordBool,SCULongBool,SCUString,
SCUCString,SCURecord,SCUSet4,SCUSet32,SCUEnum,SCUProcVar,SCUFuncVar,SCUClassVar,
SCULink,SCUClass,SCUChar,SCUBinary);
{$HINTS OFF}
Function TComponent.ReadPropertiesSCU(COwner:TComponent;Namep,Resourcep:Pointer;Var ClassPointer:Pointer):Boolean;
Var P,p2:^LongInt;
B:Byte;
tt,TypeLen:LongInt;
Typ:Byte;
WriteTyp:Byte;
WriteOffset,PropNameOffset:LongInt;
Value,Temp:Pointer;
TypeName,ProcName,PropertyName:String[64];
ProcParams:String;
ActComponentClass:TComponentClass;
Proc:Pointer;
AParent:TComponent;
dummy:PPropertyLink;
Error:Boolean;
Info:TPropertyTypeInfo;
InheritedComp:TComponent;
SectionLen:LongWord;
SCUTyp:SCUTypes;
Label L,err;
Begin
Result:=False;
P:=ClassPointer;
SectionLen:=P^;
Inc(P,4); //overread Property section len
L:
Error:=False;
B:=P^ And 255; //properties avail ?
Inc(P);
If ((B=1)Or(B=2)) Then
Begin
//there follows A Property entry - we are At Name Index
PropNameOffset:=P^;
Inc(P,4);
SCUTyp:=SCUNull;
System.Move(P^,SCUTyp,1);
Inc(P);
If ((SCUTyp=SCURecord)Or(SCUTyp=SCUBinary)) Then
Begin
System.Move(P^,TypeLen,4);
Inc(P,4);
End;
PropertyName:=GetClassNameFromSCU(Namep,PropNameOffset);
If Not GetPropertyTypeInfo2(Self,PropertyName,Info) Then
Begin
//evtll schon beim Rausschreiben skippen
ErrorBox2(FmtLoadNLSStr(SPropertyNotFound,[PropertyName,ClassName])+' !'#13+
LoadNLSStr(SPropertySkipped));
Case SCUTyp Of
SCUByte,SCUShortInt,SCUByteBool,SCUChar:Inc(P,1);
SCUWord,SCUInteger,SCUWordBool:Inc(P,2);
SCULongWord,SCULongInt,SCULongBool,SCUSingle:Inc(P,4);
SCUDouble:Inc(P,8);
SCUExtended:Inc(P,10);
SCUString:Inc(P,(P^ And 255)+1);
SCUCString:
Begin
While (P^ And 255)<>0 Do Inc(P);
Inc(P); //skip #0
End;
SCULink:Inc(P,4); //Name Index
SCURecord,SCUBinary:Inc(P,TypeLen);
SCUSet4:Inc(P,4);
SCUSet32:Inc(P,32);
SCUEnum:Inc(P,4);
SCUProcVar,SCUFuncVar:Inc(P,12); //Owner,method,Property Name Index
{SCUClassVar:Inc(P,4);
SCUClass:Inc(P,4);}
Else Goto err; //Error !
End;
Goto L; //Until All properties Read
err:
Inc(ClassPointer,SectionLen);
Result:=True;
Exit;
End;
TypeLen:=Info.Size;
Typ:=Info.Typ;
WriteTyp:=Info.Write.Kind;
WriteOffset:=Info.Write.VarOffset;
Case WriteTyp Of
1,2,3:;
Else If Typ<>PropType_Class Then
Begin
ErrorBox2(FmtLoadNLSStr(SPropertyReadOnly,[PropertyName])+'. '+
LoadNLSStr(SPropertySkipped)+'.');
Error:=True;
End;
End; {Case}
If B=2 Then //Link
Begin
Typ:=PropType_Link;
End;
If Typ=PropType_String Then //String
Begin
B:=P^ And 255;
TypeLen:=B+1;
End;
Case Typ Of
PropType_Class: //Class
Begin
//Get Value Of the Property
Case Info.Read.Kind Of
1:
Begin
GetMem(Value,TypeLen);
p2:=Pointer(Self);
Inc(p2,Info.Read.VarOffset);
Move(p2^,Value^,TypeLen);
End;
2,3:
Begin
GetMem(Value,TypeLen);
If Not CallReadProp(Self,Pointer(Info.Read.VarOffset),Typ,TypeLen,Value) Then
Begin
ErrorBox2('SCU Error 3: '+FmtLoadNLSStr(SCouldNotReadFromProperty,[PropertyName])+'.');
FreeMem(Value,TypeLen);
Exit;
End;
End;
Else
Begin
ErrorBox2(FmtLoadNLSStr(SCouldNotReadFromProperty,[PropertyName])+'.');
Goto err;
End;
End;
System.Move(Value^,InheritedComp,4);
If InheritedComp=Nil Then
Begin
ErrorBox2('Property '+Name+'.'+PropertyName+' is NIL');
FreeMem(Value,TypeLen);
Goto err;
End;
If Not InheritedComp.ReadPropertiesSCU(COwner,Namep,Resourcep,P) Then
Begin
ErrorBox2('Property '+Name+'.'+PropertyName+' could not be initialized');
FreeMem(Value,TypeLen);
Goto err;
End;
Error:=True; {!!}
End;
PropType_ProcVar,PropType_FuncVar: //ProcVar,FuncVar
Begin
tt:=P^;
Inc(P,4);
TypeName:='T'+GetClassNameFromSCU(Namep,tt);
tt:=P^;
Inc(P,4);
ProcName:=GetClassNameFromSCU(Namep,tt);
tt:=P^;
Inc(P,4);
PropertyName:=GetClassNameFromSCU(Namep,tt);
If TypeLen<>8 Then Exit; //Of Object !!
GetMem(Value,TypeLen);
If ((InsideDesigner)Or(InsideLanguageDesigner)) Then
Begin
//Owner IDESCU_Data suchen !
AParent:=GetParentSCUFormDesign(Self);
If AParent=Nil Then Exit; //Error
//Proc In AParent IDESCU_Data einfügen
ProcParams:=GetSCUProcParamsFromName(Self,PropertyName);
If ProcParams='?' Then
Begin
ErrorBox2(FmtLoadNLSStr(SPropError,[PropertyName]));
Error:=True;
End
Else InsertSCUMethod(AParent,Self,ProcName,ProcParams,PropertyName);
FillChar(Value^,TypeLen,0); {!!}
End
Else
Begin
//Search For TypeName.ProcName
//dazu In SetupSCU alle Forms mit RegisterClasses registrieren
ActComponentClass:=SearchClassByName(TypeName);
If ActComponentClass=Nil Then
Begin
ErrorBox2('SCU Error 1: '+FmtLoadNLSStr(SComponentNotFound,[TypeName])+'.'#13+
LoadNLSStr(SUseRegisterClasses));
Error:=True;
End
Else
Begin
//Get Object For that method
AParent:=GetParentSCUFormRuntime(Self,TypeName);
If AParent=Nil Then
Begin
ErrorBox2(FmtLoadNLSStr(SSCUErrorInClass,[TypeName]));
Error:=True;
End
Else
Begin
Proc:=AParent.MethodAddress(ProcName);
If Proc=Nil Then
Begin
ErrorBox2(FmtLoadNLSStr(SMethodNotFound,[ProcName,ClassName]));
Error:=True;
End
Else
Begin
//Proc Adresse setzen
Move(Proc,Value^,4);
Inc(Value,4);
//method Object Pointer setzen
Move(AParent,Value^,4);
Dec(Value,4);
End;
End;
End;
End;
End;
PropType_Link: //Link
Begin
If ComponentState*[csForm]<>[] Then
If PropertyName='Menu' Then
Begin
Include(ComponentState,csHasMainMenu);
End;
//Name Of Property To Link
tt:=P^;
Inc(P,4);
PropertyName:=GetClassNameFromSCU(Namep,tt);
If PropertyLinks=Nil Then
Begin
New(PropertyLinks);
dummy:=PropertyLinks;
dummy^.Next:=Nil;
End
Else
Begin
New(dummy);
dummy^.Next:=PropertyLinks;
PropertyLinks:=dummy;
End;
dummy^.SelfPtr:=Self;
dummy^.Owner:=COwner;
dummy^.WriteTyp:=WriteTyp;
dummy^.WriteOffset:=WriteOffset;
dummy^.LinkName:=PropertyName;
Goto L; //dont Write here
End;
Else
Begin
GetMem(Value,TypeLen);
Move(P^,Value^,TypeLen);
Inc(P,TypeLen);
End;
End; {Case}
If Not Error Then
Case WriteTyp Of
1:
Begin
p2:=Pointer(Self);
Inc(p2,WriteOffset);
Move(Value^,p2^,TypeLen);
End;
2,3:
Begin
If Not CallWriteProp(Self,Pointer(WriteOffset),Typ,TypeLen,Value) Then
Begin
ErrorBox2('SCU Error 3: '+FmtLoadNLSStr(SCouldNotWriteToProperty,[PropertyName])+' !');
End;
End;
Else Goto err; //Some Error
End;
FreeMem(Value,TypeLen);
Goto L; //Until All properties Read
End
Else If B<>0 Then Exit; //Some Error
ClassPointer:=P;
Result:=True;
End;
{$HINTS ON}
Procedure TComponent.ReadResourceSCU(ResourceTable:Pointer;Var ClassP:Pointer);
Var DataOfs:LongWord;
P:^LongWord;
ps:PString;
ResName:TResourceName;
Data:Pointer;
DataLen:LongInt;
pp:^LongWord;
DOfs:LongWord;
reshead:LongWord;
Label L;
Begin
L:
pp:=ClassP;
Inc(ClassP,4);
reshead:=pp^;
If reshead=0 Then Exit; {no resources For This Component}
P:=ResourceTable+4; //onto Resource Data Offset
DataOfs:=P^;
P:=ResourceTable;
Inc(P,reshead); {Offset To Resource Header}
{process Resource Header}
ps := PString(P);
ResName := TResourceName(ps^);
Inc(P,SizeOf(TResourceName));
Data:=ResourceTable;
DOfs:=P^;
Inc(Data,DataOfs+DOfs); //Start Of Resource information
Inc(P,4);
DataLen:=P^;
Inc(P,4);
//Load resources For This Component
ReadSCUResource(ResName,Data^,DataLen);
Goto L; {Until no more resources For This}
End;
Procedure HandlePropertyLinks(Component:TComponent);
Var dummy,Next:PPropertyLink;
P,p2:Pointer;
T,t1:LongInt;
Comp,Comp1,Comp2:TComponent;
S:String;
Label found,again;
Begin
dummy:=PropertyLinks;
While dummy<>Nil Do
Begin
UpcaseStr(dummy^.LinkName);
P:=Nil;
Comp1:=Component;
again:
For T:=0 To Comp1.ComponentCount-1 Do
Begin
Comp:=Comp1.Components[T];
If csReferenceControl In Comp.ComponentState Then continue;
If Comp Is TComponent Then
Begin
S:=Comp.Name;
UpcaseStr(S);
If S=dummy^.LinkName Then
Begin
P:=@Comp;
Goto found;
End;
End;
For t1:=0 To Comp.ComponentCount-1 Do
Begin
Comp2:=Comp.Components[t1];
If csReferenceControl In Comp2.ComponentState Then continue;
If Comp2 Is TComponent Then
Begin
S:=Comp2.Name;
UpcaseStr(S);
If S=dummy^.LinkName Then
Begin
P:=@Comp2;
Goto found;
End;
End;
End;
End;
Comp1:=Comp1.Owner;
If Comp1<>Nil Then Goto again;
found:
If P<>Nil Then
Begin
Case dummy^.WriteTyp Of
1:
Begin
p2:=Pointer(dummy^.SelfPtr);
Inc(p2,dummy^.WriteOffset);
Move(P^,p2^,4);
End;
2,3: //method call (direct Or VMT)
Begin
If Not CallWriteProp(dummy^.SelfPtr,Pointer(dummy^.WriteOffset),PropType_Unsigned,4,P) Then
Begin
End;
End;
End; {Case}
End;
dummy:=dummy^.Next;
End;
dummy:=PropertyLinks;
While dummy<>Nil Do
Begin
If dummy^.SelfPtr=Nil Then
Begin
ErrorBox2('SCU Error: '+FmtLoadNLSStr(SLinkNotFound,[dummy^.LinkName])+' !');
End;
If ((dummy^.SelfPtr<>Nil)And(dummy^.SelfPtr.FComponentState*[csLoaded]=[])) Then
Begin
dummy^.SelfPtr.LoadedFromSCU(dummy^.Owner);
dummy^.SelfPtr.Loaded;
End;
Next:=dummy^.Next;
Dispose(dummy);
dummy:=Next;
End;
PropertyLinks:=Nil;
End;
Function TComponent.ReadComponentsSCU(NameTable,ResourceTable:Pointer;Var ClassP:Pointer):Boolean;
Var ChildCount,T:LongInt;
NameIndex,NameIndex1:LongInt;
ComponentClass:TComponentClass;
Component:TComponent;
S,s1:String[64];
ClassPointer:^LongWord;
B:Byte;
P:Pointer;
RemoveReferenceButton:Boolean;
ChildIsReferenceButton:Boolean;
SavePropertyLinks,dummy:PPropertyLink;
idx:LongInt;
Ref:TComponent;
LastReference:TComponent;
Procedure SkipChildComponents;
Var t1,Count:LongInt;
B:Byte;
Begin
Count:=ClassPointer^;
Inc(ClassPointer,4);
For t1:=1 To Count Do //skip All Child Components
Begin
Inc(ClassPointer,4); //skip Name Index
B:=ClassPointer^ And 255;
Inc(ClassPointer);
If B=1 Then {runtime Class Name differs from Inspector Class Name}
Begin
Inc(ClassPointer,4); //skip NameIndex
End;
{overread Property section}
Inc(ClassPointer,ClassPointer^);
{overread Components section}
SkipChildComponents; //overread All Child Components
{overread Resource section}
While ClassPointer^<>0 Do Inc(ClassPointer,4);
Inc(ClassPointer,4); {overread 0}
End;
End;
Label skip,skipIt;
Begin
Result:=False;
SavePropertyLinks:=PropertyLinks;
PropertyLinks:=Nil;
ClassPointer:=ClassP;
ChildCount:=ClassPointer^;
Inc(ClassPointer,4);
LastReference:=Nil;
For T:=1 To ChildCount Do
Begin
NameIndex:=ClassPointer^;
Inc(ClassPointer,4);
S:=GetClassNameFromSCU(NameTable,NameIndex); {Of the New Child}
RemoveReferenceButton := False;
ChildIsReferenceButton := False;
If S = 'TReferenceWindow' Then
Begin
ChildIsReferenceButton := True;
If Not InsideDesigner Then RemoveReferenceButton := True;
End;
s1 := '';
{check If runtime Class Name Is avail}
B:=ClassPointer^ And 255;
Inc(ClassPointer);
If B=1 Then {runtime Class Name differs from Inspector Class Name}
Begin
NameIndex1:=ClassPointer^;
Inc(ClassPointer,4);
s1:=GetClassNameFromSCU(NameTable,NameIndex1);
{Use runtime Class Name To Create the Class}
If Not ((InsideDesigner)Or(InsideLanguageDesigner)) Then
If s1 <> '' Then S := s1; {!!}
End;
{note: runtime Class Names MUST be registered In Form Unit Or
main Program Of an Application !!}
If RemoveReferenceButton Then ComponentClass:=SearchClassByName('TCONTROL')
Else ComponentClass:=SearchClassByName(S);
If ComponentClass=Nil Then
Begin
ErrorBox2('SCU Error 2: '+FmtLoadNLSStr(SComponentNotFound,[S])+'.'#13 +
LoadNLSStr(SUseRegisterClasses)+' !');
Goto skipIt;
End;
{C R E A T E the Child Object}
FCreateFromSCU := True;
Component := ComponentClass.Create(LastSCUForm);
FCreateFromSCU := False;
{zur Sicherheit}
If ChildIsReferenceButton Then
If Not RemoveReferenceButton Then
Begin {Predecessor Is the Reference -> Set the flag}
idx := LastSCUForm.IndexOfComponent(LastReference);
If idx >= 0 Then
Begin
Ref := LastSCUForm.Components[idx];
Include(Ref.ComponentState, csReference); {!}
End;
End;
Component.SetDesigning(InsideDesigner Or InsideLanguageDesigner);
Component.LoadingFromSCU(Self);
If ((InsideDesigner)Or(InsideLanguageDesigner)) Then
{Set TypeName And IDESCU_Data}
If s1<>'' Then
Begin
Component.TypeName:=s1;
Component.FMethods:=Nil; {no Methods defined}
End;
If RemoveReferenceButton Then
Begin
Component.Destroy; {besser gar nicht erst erzeugen}
skipIt:
{overread Property section}
Inc(ClassPointer,ClassPointer^);
{overread Components section}
SkipChildComponents; //overread All Child Components
{overread Resource section}
While ClassPointer^<>0 Do Inc(ClassPointer,4);
Inc(ClassPointer,4); {overread 0}
continue;
End
Else
Begin
If Not Component.ReadPropertiesSCU(Self,NameTable,ResourceTable,ClassPointer) Then Exit;
If Not Component.ReadComponentsSCU(NameTable,ResourceTable,ClassPointer) Then Exit;
Component.ReadResourceSCU(ResourceTable,ClassPointer);
End;
If Not ((InsideDesigner)Or(InsideLanguageDesigner)) Then
Begin
{Set Object variable If present}
P := LastSCUForm.FieldAddress(Component.Name);
If P <> Nil Then Move(Component,P^,4);
End;
//If This Component expects A Link Then we don't call Loaded unless the
//Link Is established
dummy:=PropertyLinks;
While dummy<>Nil Do
Begin
If dummy^.SelfPtr=Component Then Goto skip;
dummy:=dummy^.Next;
End;
If Component.FComponentState*[csLoaded]=[] Then
Begin
If ChildIsReferenceButton Then
Begin
//Set the Reference
Component.FReference:=LastReference;
Include(LastReference.ComponentState,csReference);
Component.LoadedFromSCU(Self);
End
Else Component.LoadedFromSCU(Self);
Component.Loaded;
End;
skip:
//This Is the Last Reference Window
//we have To Store it because it may contain Child Items...
LastReference:=Component;
End;
If PropertyLinks<>Nil Then
Begin
dummy:=PropertyLinks;
While dummy^.Next<>Nil Do dummy:=dummy^.Next;
dummy^.Next:=SavePropertyLinks; {Append}
End
Else PropertyLinks:=SavePropertyLinks;
ClassP:=ClassPointer;
Result:=True;
End;
Function SearchClassSCU(Data:Pointer;NameToFind:String;ObjectCount:LongInt;ClassUnit:String):Pointer;
Var dummy:^LongWord;
len:LongWord;
Count:LongInt;
ps:^String;
S,D,N,E:String;
Label L;
Begin
Result:=Nil;
Count:=0;
UpcaseStr(ClassUnit);
L:
If Count>=ObjectCount Then Exit;
dummy:=Data;
len:=dummy^; //len Of This entry
Inc(dummy,4); //onto Inspector Class Name
Inc(dummy,(dummy^ And 255)+1); //overread Inspector Name
ps:=Pointer(dummy); //runtime Class Name
S:=ps^;
UpcaseStr(S);
If S=NameToFind Then
Begin
Inc(ps,Length(S)+1); //ON Unit Name
S:=ps^;
UpcaseStr(S);
FSplit(S,D,N,E);
If N=ClassUnit Then
Begin
Result:=Data;
Exit;
End;
End;
Inc(Data,len); //Next entry
Inc(Count);
Goto L;
End;
Procedure TComponent.SetupSCU;
Var
SaveSCU:Pointer;
OldInsideDesigner:Boolean;
Begin
If SCUPointer=Nil Then Exit;
If ComponentState * [csForm] = [] Then Exit;
OldInsideDesigner:=InsideDesigner;
SaveSCU:=SCUPointer;
SCUPointer:=Nil; //prevent recursion
Try
ReadSCU(SaveSCU);
Except
On E:Exception Do
If ((InsideDesigner)Or(InsideLanguageDesigner)) Then ErrorBox2('Illegal SCU format:'+E.Message);
End;
SCUPointer:=SaveSCU;
InsideDesigner:=OldInsideDesigner;
End;
{$HINTS OFF}
Procedure TComponent.ReadSCUResource(Const ResName:TResourceName;Var Data;DataLen:LongInt);
Begin
End;
Function TComponent.WriteSCUResource(Stream:TResourceStream):Boolean;
Begin
Result:=True;
End;
Procedure TComponent.LoadedFromSCU(SCUParent:TComponent);
Begin
Exclude(FComponentState, csReading);
Exclude(FComponentState, csLoading);
Include(FComponentState, csLoaded);
End;
Procedure TComponent.LoadingFromSCU(SCUParent:TComponent);
Begin
Include(FComponentState, csReading);
Include(FComponentState, csLoading);
Exclude(FComponentState, csLoaded);
End;
{$HINTS ON}
Procedure TComponent.Loaded;
Begin
End;
Procedure TComponent.SetupComponent;
Begin
//Name := 'Component';
Name := Copy(ClassName,2,255);
Tag := 0;
If Designed Then Include(ComponentState,csReference);
End;
Constructor TComponent.Create(AOwner:TComponent);
Begin
//Inherited Create;
If InsideWriteSCUAdr^ Then Include(ComponentState, csWriting);
If AOwner Is TComponent Then AOwner.InsertComponent(Self);
SetupComponent;
End;
Procedure SetupFormSCU(Form:TComponent);
Begin
If SCUPointer <> Nil Then Form.SetupSCU;
End;
Procedure TComponent.Notification(AComponent:TComponent;Operation:TOperation);
Var I:LongInt;
Begin
If (FFreeNotifyList <> Nil) And (Operation = opRemove) Then
Begin
FFreeNotifyList.Remove(AComponent);
If FFreeNotifyList.Count = 0 Then
Begin
FFreeNotifyList.Destroy;
FFreeNotifyList := Nil;
End;
End;
For I := 0 To ComponentCount-1 Do
Begin
Components[I].Notification(AComponent,Operation);
End;
End;
Procedure TComponent.FreeNotification(AComponent:TComponent);
Begin
If FFreeNotifyList = Nil Then FFreeNotifyList.Create;
If FFreeNotifyList.IndexOf(AComponent) < 0 Then
Begin
FFreeNotifyList.Add(AComponent);
AComponent.FreeNotification(Self);
End;
End;
Function GetLanguages(Component:TComponent):PLanguageInfo;
Begin
Result:=Component.FLanguages;
End;
Procedure SetLanguages(Component:TComponent;Info:PLanguageInfo);
Begin
Component.FLanguages:=Info;
End;
Procedure FreeLanguage(Var LangComp:PLanguageComponent);
Var NextLangComp:PLanguageComponent;
Begin
While LangComp<>Nil Do
Begin
FreeMem(LangComp^.Name,Length(LangComp^.Name^)+1);
If LangComp^.ValueLen>0 Then
FreeMem(LangComp^.Value,LangComp^.ValueLen);
NextLangComp:=LangComp^.Next;
Dispose(LangComp);
LangComp:=NextLangComp;
End;
End;
Destructor TComponent.Destroy;
Var Meth,Last:PIDE_Methods;
T:LongInt;
Own:PIDE_OwnerList;
I:LongInt;
LangItem,NextLangItem:PLanguageItem;
Begin
{inform All linked Components}
If FFreeNotifyList <> Nil Then
Begin
For I := 0 To FFreeNotifyList.Count-1 Do
Begin
TComponent(FFreeNotifyList[I]).Notification(Self,opRemove);
End;
FFreeNotifyList.Destroy;
FFreeNotifyList := Nil;
End;
Meth:=FMethods;
While Meth<>Nil Do
Begin
DisposeStr(Meth^.Name);
DisposeStr(Meth^.Params);
If Meth^.Owners<>Nil Then
Begin
For T:=0 To Meth^.Owners.Count-1 Do
Begin
Own:=Meth^.Owners.Items[T];
DisposeStr(Own^.PropertyName);
End;
Meth^.Owners.Destroy;
End;
Last:=Meth^.Next;
Dispose(Meth);
Meth:=Last;
End;
FMethods := Nil;
//Free registered languages
If FLanguages<>Nil Then
Begin
LangItem:=PLanguageInfo(FLanguages)^.Items;
FreeMem(FLanguages,SizeOf(TLanguageInfo));
FLanguages:=Nil;
While LangItem<>Nil Do
Begin
FreeMem(LangItem^.Name,Length(LangItem^.Name^)+1);
FreeLanguage(LangItem^.Components);
FreeLanguage(LangItem^.Menus);
FreeLanguage(LangItem^.StringTables);
NextLangItem:=LangItem^.Next;
Dispose(LangItem);
LangItem:=NextLangItem;
End;
End;
DestroyComponents;
If FOwner <> Nil Then FOwner.RemoveComponent(Self);
DisposeStr(FName);
FName := Nil;
DisposeStr(FUnitName);
FUnitName := Nil;
DisposeStr(FTypeName);
FTypeName := Nil;
Inherited Destroy;
End;
Procedure TComponent.DestroyComponents;
Var I:LongInt;
Component:TComponent;
Begin
If FComponents <> Nil Then
Begin
I := ComponentCount;
While I > 0 Do
Begin
Component := Components[I-1];
RemoveComponent(Component);
Component.Destroy;
I := ComponentCount;
End;
FComponents.Destroy;
FComponents := Nil;
End;
End;
Function TComponent.GetComponentIndex:LongInt;
Begin
Result := -1;
If FOwner = Nil Then Exit;
If FOwner.FComponents = Nil Then Exit;
Result := FOwner.FComponents.IndexOf(Self);
End;
Procedure TComponent.SetComponentIndex(Index:LongInt);
Var I:LongInt;
Begin
If FOwner = Nil Then Exit;
I := FOwner.IndexOfComponent(Self);
If I < 0 Then Exit;
If Index = I Then Exit;
If Index < 0 Then Index := 0;
If Index >= FOwner.FComponents.Count
Then Index := FOwner.FComponents.Count -1;
FOwner.FComponents.Move(I,Index);
End;
Function TComponent.GetComponentCount:LongInt;
Begin
If FComponents=Nil Then Result:=0
Else Result:=FComponents.Count;
End;
Function TComponent.GetComponent(AIndex:LongInt):TComponent;
Begin
If (FComponents=Nil) Or (AIndex<0) Or (AIndex>=FComponents.Count)
Then Result:=Nil
Else Result:=FComponents.Items[AIndex];
End;
Function TComponent.GetName:String;
Begin
If FName<>Nil Then Result:=FName^
Else Result:='';
End;
Procedure TComponent.SetName(Const NewName:String);
Begin
AssignStr(FName,NewName);
End;
Function TComponent.GetUnitName:String;
Begin
If FUnitName <> Nil Then Result := FUnitName^
Else Result := '';
End;
Function TComponent.GetTypeName:String;
Begin
If FTypeName <> Nil Then Result := FTypeName^
Else Result := '';
End;
Procedure TComponent.SetTypeName(NewName:String);
Begin
AssignStr(FTypeName,NewName);
End;
Function TComponent.GetDesigned:Boolean;
Begin
Result := FComponentState * [csDesigning] <> [];
End;
Procedure TComponent.InsertComponent(AComponent:TComponent);
Begin
If FComponents = Nil Then FComponents.Create;
FComponents.Add(AComponent);
AComponent.FOwner := Self;
AComponent.SetDesigning(Designed); {!}
Notification(AComponent,opInsert);
End;
Procedure TComponent.RemoveComponent(AComponent:TComponent);
Begin
Notification(AComponent,opRemove);
If FComponents = Nil Then Exit;
FComponents.Remove(AComponent);
End;
Function TComponent.IndexOfComponent(AComponent:TComponent):LongInt;
Begin
Result := -1;
If FComponents = Nil Then Exit;
Result := FComponents.IndexOf(AComponent);
End;
Function TComponent.FindComponent(Const AName:String):TComponent;
Var I:LongInt;
Begin
Result := Nil;
For I := 0 To ComponentCount-1 Do
If Components[I].Name = AName Then
Begin
Result := Components[I];
break;
End;
End;
Procedure TComponent.SetDesigning(Value:Boolean);
Var I:LongInt;
Begin
If Value Then Include(FComponentState, csDesigning)
Else Exclude(FComponentState, csDesigning);
For I := 0 To ComponentCount-1 Do Components[I].SetDesigning(Value);
End;
Procedure AddDesignerPopupEvent(AString:TStringList;Caption:String;Id:LongInt);
Begin
If AString Is TStringList Then AString.AddObject(Caption, TObject(Id));
End;
{event from the designer PopupMenu}
{$HINTS OFF}
Procedure TComponent.GetDesignerPopupEvents(AString:TStringList);
Begin
End;
Procedure TComponent.DesignerPopupEvent(Id:LongInt);
Begin
End;
{$HINTS ON}
{
╔═══════════════════════════════════════════════════════════════════════════╗
║ ║
║ Speed-Pascal/2 Version 2.0 ║
║ ║
║ Speed-Pascal Component Classes (SPCC) ║
║ ║
║ This section: General FUNCTIONs Implementation ║
║ ║
║ (C) 1995,97 SpeedSoft. All rights reserved. Disclosure probibited ! ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════╝
}
Const
SearchCompLibComponentByName:Function(Const Name:String):TComponentClass=Nil;
CallCompLibClassPropertyEditor:Function(Var ClassToEdit:TObject):TClassPropertyEditorReturn=Nil;
CallCompLibPropertyEditor:Function(Owner:TComponent;PropertyName:String;Var Value;ValueLen:LongInt;
Var List:TStringList):TPropertyEditorReturn=Nil;
CallCompLibPropertyEditorAvailable:Function(OwnerClass:TClass;PropertyName:String):Boolean=Nil;
CallCompLibClassPropertyEditorAvailable:Function(ClassName:String):Boolean=Nil;
Var
NameTable:TList;
Function NameTableAdd(P:PString):LongInt;
Var T:LongInt;
Ofs:LongInt;
pp:PString;
Begin
Ofs:=0;
For T:=0 To NameTable.Count-1 Do
Begin
pp:=NameTable.Items[T];
If pp^=P^ Then
Begin
Result:=Ofs;
Exit;
End;
Inc(Ofs,Length(pp^)+1);
End;
NameTable.Add(P);
Result:=Ofs;
End;
Function SearchClassByName(Const Name:String):TComponentClass;
Var T:LongInt;
Comp:TComponentClass;
S,s1:String;
Begin
Result := Nil;
S := Name;
UpcaseStr(S);
For T := 0 To RegisteredClasses.Count-1 Do
Begin
Comp := RegisteredClasses.Items[T];
s1 := Comp.ClassName;
UpcaseStr(s1);
If s1 = S Then
Begin
Result := Comp;
Exit;
End;
End;
{Search In registered Components Of the complib}
If @SearchCompLibComponentByName<>Nil
Then Result := SearchCompLibComponentByName(Name);
End;
Procedure RegisterClass(Const ComponentClass:TComponentClass);
Var Comp:TComponentClass;
t1:LongInt;
Begin
For t1:=0 To RegisteredClasses.Count-1 Do
Begin
Comp:=RegisteredClasses.Items[t1];
If Comp.ClassName=ComponentClass.ClassName Then exit;
End;
RegisteredClasses.Add(ComponentClass);
End;
Function GetClass(Const ClassName:String):TComponentClass;
Begin
Result:=SearchClassByName(ClassName);
End;
Function FindClass(Const ClassName:String):TComponentClass;
Begin
Result:=GetClass(ClassName);
If Result=Nil Then Raise EClassNotFound.Create(ClassName);
End;
Procedure UnRegisterClass(AClass:TComponentClass);
Var t1:LongInt;
Comp:TComponentClass;
Label again;
Begin
again:
For t1:=0 To RegisteredClasses.Count-1 Do
Begin
Comp:=RegisteredClasses.Items[t1];
If Comp.ClassName=AClass.ClassName Then
Begin
RegisteredClasses.Remove(Comp);
goto again;
End;
End;
End;
Procedure UnRegisterClasses(Const AClasses:Array of TComponentClass);
Var t:LongInt;
Begin
For t:=0 To High(AClasses) Do UnRegisterClass(AClasses[t]);
End;
Procedure RegisterClasses(Const ComponentClasses: Array Of TComponentClass);
Var T,t1:LongInt;
Comp,Comp1:TComponentClass;
Label l1;
Begin
For T:=0 To High(ComponentClasses) Do
Begin
Comp1:=ComponentClasses[T];
For t1:=0 To RegisteredClasses.Count-1 Do
Begin
Comp:=RegisteredClasses.Items[t1];
If Comp.ClassName=Comp1.ClassName Then Goto l1;
End;
RegisteredClasses.Add(Comp1);
l1:
End;
End;
{copies actual Value Of Property To Value.
Value MUST be allocated With At least TypLen Bytes !}
Function CallReadProp(Objekt:TObject;FuncAddr:Pointer;Typ:Byte;
TypLen:LongInt;Value:Pointer):Boolean;
Var
FResult:LongInt;
Func:Function(SelfObj:TObject):LongInt;
FuncVar:Function(VarRef:Pointer;SelfObj:TObject):LongInt;
Begin
Result:=False;
If FuncAddr=Nil Then Exit; //method Not found
If ((Typ=PropType_Set)And(TypLen=4)) Then Typ:=PropType_Unsigned;
If LongWord(FuncAddr)<65535 Then //VMT call
Begin
Case Typ Of
PropType_Unsigned,PropType_Signed,PropType_Class,
PropType_Enum,PropType_Boolean,PropType_Char,PropType_ClassVar:
Begin
Asm
PUSH DWord Ptr Objekt //Self
MOV EAX,FuncAddr //VMT Index
CALLN32 System.!VmtCall
MOV FResult,EAX
End;
Move(FResult,Value^,TypLen);
End;
PropType_Float,PropType_String,PropType_Set,PropType_CString,
PropType_ProcVar,PropType_FuncVar,PropType_Record:
Begin
Asm
PUSH DWord Ptr Value //Var Parameter Of return Value
PUSH DWord Ptr Objekt //Self
MOV EAX,FuncAddr //VMT Index
CALLN32 System.!VmtCall
End;
End;
Else Exit; //Some Error
End; {Case}
End
Else
Begin
Case Typ Of
PropType_Unsigned,PropType_Signed,PropType_Class,
PropType_Enum,PropType_Boolean,PropType_Char,PropType_ClassVar:
Begin
Func:=FuncAddr;
FResult:=Func(Objekt);
Move(FResult,Value^,TypLen);
End;
PropType_Float,PropType_String,PropType_Set,PropType_CString,
PropType_ProcVar,PropType_FuncVar,PropType_Record:
Begin
FuncVar:=FuncAddr;
FResult:=FuncVar(Value,Objekt);
End;
Else Exit; //Some Error
End; {Case}
End;
Result:=True;
End;
{copies actual Value Of Value To the Property.
Value MUST be allocated With At least TypLen Bytes !}
Function CallWriteProp(Objekt:TObject;ProcAddr:Pointer;Typ:Byte;
TypLen:LongInt;Value:Pointer):Boolean;
Var
Proc:Procedure(Value:LongWord;SelfObj:TObject);
ProcVar:Procedure(Value:Pointer;SelfObj:TObject);
pb:^LongWord;
pw:^Word;
pl:^LongWord;
L:LongWord;
Begin
Result:=False;
If ProcAddr=Nil Then Exit; //method Not found
If TypLen In [1,2,3,4] Then
If Not (Typ In [PropType_String,PropType_CString]) Then Typ:=PropType_Unsigned;
If LongWord(ProcAddr)<65535 Then //VMT call
Begin
Case Typ Of
PropType_Unsigned,PropType_Signed,PropType_Class,
PropType_Enum,PropType_Boolean,PropType_Char,PropType_ClassVar:
Begin
Case TypLen Of
1:
Begin
pb:=Value;
L:=pb^;
End;
2:
Begin
pw:=Value;
L:=pw^;
End;
3:
Begin
L:=0;
Move(pl^,L,3);
End;
4:
Begin
pl:=Value;
L:=pl^;
End;
Else Exit; //no Valid Type Size For Val
End; {Case}
Asm
PUSH DWord Ptr L //Value To Set
PUSH DWord Ptr Objekt //Self
MOV EAX,ProcAddr //VMT Index
CALLN32 System.!VmtCall
End;
End;
PropType_Float,PropType_String,PropType_Set,PropType_CString,
PropType_ProcVar,PropType_FuncVar,PropType_Record:
Begin
Asm
PUSH DWord Ptr Value //Var Parameter Of Data To Assign
PUSH DWord Ptr Objekt //Self
MOV EAX,ProcAddr //VMT Index
CALLN32 System.!VmtCall
End;
End;
Else Exit; //Some Error
End; {Case}
End
Else
Begin
Case Typ Of
PropType_Unsigned,PropType_Signed,PropType_Class,
PropType_Enum,PropType_Boolean,PropType_Char,PropType_ClassVar:
Begin
Proc:=ProcAddr;
Case TypLen Of
1:
Begin
pb:=Value;
L:=pb^;
End;
2:
Begin
pw:=Value;
L:=pw^;
End;
3:
Begin
L:=0;
Move(pl^,L,3);
End;
4:
Begin
pl:=Value;
L:=pl^;
End;
Else Exit; //no Valid Type Size For Val
End; {Case}
Proc(L,Objekt);
End;
PropType_Float,PropType_String,PropType_Set,PropType_CString,
PropType_ProcVar,PropType_FuncVar,PropType_Record:
Begin
ProcVar:=ProcAddr;
ProcVar(Value,Objekt);
End;
Else Exit; //Some Error
End; {Case}
End;
Result:=True;
End;
Var PropertyNameTable:Pointer;
Const SCUUnsignedTypes:Array[1..4] Of SCUTypes=(SCUByte,SCUWord,SCUNull,SCULongWord);
SCUSignedTypes:Array[1..4] Of SCUTypes=(SCUShortInt,SCUInteger,SCUNull,SCULongInt);
SCUFloatTypes:Array[4..10] Of SCUTypes=(SCUSingle,SCUNull,SCUNull,SCUNull,SCUDouble,SCUNull,SCUExtended);
SCUBooleanTypes:Array[1..4] Of SCUTypes=(SCUByteBool,SCUWordBool,SCUNull,SCULongBool);
Function WriteProperties(Stream:TMemoryStream;p1:Pointer;Objekt:TComponent;
pParent:Pointer):Boolean; Forward;
Function WritePropertyValues(Stream:TMemoryStream;P:Pointer;Objekt:TComponent;
Namep:Pointer;ReferenceObjekt:TComponent):Boolean;
Var Typep,p1,p2:^LongInt;
Typ,B:Byte;
tt,TypLen:LongInt;
ReadTyp,WriteTyp:Byte;
S:String;
ps:^String;
Value,ReferenceValue:^LongInt;
ValueLen:LongInt;
ReadOffset,WriteOffset:LongInt;
s3:String;
ReadAddr,WriteAddr:Pointer;
ValidProp:Boolean;
AOwner:TComponent;
Methods:PIDE_Methods;
Own:PIDE_OwnerList;
MyComp:TComponent;
pParent1:Pointer;
Label L,lll,lll1,ex,weiter;
Begin
Result:=False;
ValidProp:=True;
p1:=P;
MyComp:=Nil;
ReadTyp:=p1^ And 255;
Inc(p1);
Case ReadTyp Of
0:; //Not avail
1: //Var Offset
Begin
ReadOffset:=p1^;
Inc(p1,4);
End;
2,3: //Procedure Or Function (direct Or VMT call)
Begin
ReadAddr:=Pointer(p1^);
Inc(p1,4);
End;
Else Goto ex; //Some Error
End;
WriteTyp:=p1^ And 255;
Inc(p1);
Case WriteTyp Of
0:; //Not avail
1: //Var Offset
Begin
WriteOffset:=p1^;
Inc(p1,4);
End;
2,3: //Procedure Or Function (direct Or VMT call)
Begin
WriteAddr:=Pointer(p1^);
Inc(p1,4);
End;
Else Goto ex; //Some Error
End;
//determine Type Of the Property
TypLen:=p1^;
ValueLen:=TypLen;
GetMem(Value,TypLen);
GetMem(ReferenceValue,TypLen);
Inc(p1,4);
Typ:=p1^ And 255; //Property Type
Typep:=p1;
//Write Value Of the Property
Case ReadTyp Of
0:; //Not avail
1: //Var Offset
Begin
p2:=Pointer(Objekt);
Inc(p2,ReadOffset);
Move(p2^,Value^,TypLen);
p2:=Pointer(ReferenceObjekt);
Inc(p2,ReadOffset);
Move(p2^,ReferenceValue^,TypLen);
End;
2,3: //Procedure Or Function (direct Or VMT call)
Begin
If Not CallReadProp(Objekt,ReadAddr,Typ,TypLen,Value) Then Goto ex;
If Not CallReadProp(ReferenceObjekt,ReadAddr,Typ,TypLen,ReferenceValue) Then Goto ex;
End;
Else Goto ex; //Some Error
End;
If ReadTyp In [1,2,3] Then
Begin
If Typ In [PropType_ProcVar,PropType_FuncVar,
PropType_Class,PropType_ClassVar] Then //ON... properties
//ClassVar And
//Classes
Begin
Own:=Nil;
If Value^=0 Then
Begin
If Typ In [PropType_ProcVar,PropType_FuncVar] Then //ON properties
Begin
//Search Owner
AOwner:=Objekt;
ps:=Namep;
S:=ps^;
UpcaseStr(S);
lll:
While AOwner<>Nil Do
Begin
Methods:=AOwner.FMethods;
While Methods<>Nil Do
Begin
For tt:=0 To Methods^.Owners.Count-1 Do
Begin
Own:=Methods^.Owners.Items[tt];
s3:=Own^.PropertyName^;
UpcaseStr(s3);
If S=s3 Then
If Own^.Objekt=TComponent(Objekt) Then
Begin //found
Goto lll1;
End;
End;
Methods:=Methods^.Next;
End;
weiter:
AOwner:=AOwner.FOwner;
Goto lll;
End; //While AOwner<>Nil
Goto L; //Not found --> dont Write
End
Else Goto L; //dont Write
End;
If Typ=PropType_Class Then {Class}
Begin
MyComp:=Pointer(Value^);
If MyComp<>Nil Then
If MyComp Is TComponent Then
If MyComp.Designed Then
If MyComp.ComponentState * [csHandleLinks] <> [] Then
Begin
Typ:=PropType_Link; //Link
Goto lll1;
End;
If MyComp Is TComponent Then
If MyComp.DesignerState*[dsStored]<>[] Then
Begin
p1:=Pointer(PropertyNameTable);
p2:=Pointer(MyComp); //Object address
If p2<>Nil Then
Begin
//Write properties Of the Class
B:=1;
If Stream.Write(B,1)=0 Then Goto ex;
tt:=NameTableAdd(Namep); //Name Of the Property
If Stream.Write(tt,4)=0 Then Goto ex;
{Type Info For the Property}
B:=Ord(SCUClass);
If Stream.Write(B,1)=0 Then Goto ex;
p2:=Pointer(p2^); //VMT address
Inc(p2,4);
p2:=Pointer(p2^); //Class Info
Inc(p2,4);
pParent1:=Pointer(p2^); //parent Class VMT Or Nil
Inc(p2,8);
p2:=Pointer(p2^); //Property Info
If Not WriteProperties(Stream,p2,MyComp,pParent1) Then Goto ex;
PropertyNameTable:=Pointer(p1);
End;
End;
End;
//dont Write TBitmap here (Extra Data In BitButton Or Picture)
Goto L; //don't Write Class/ClassVar
End
Else
Begin
//only Write If Value Is different from Default Value
If Typ=PropType_String Then ValueLen:=(Value^ And 255)+1; //String
If ValueLen>TypLen Then ValueLen:=TypLen;
If CompareResMem(Value^,ReferenceValue^,ValueLen) Then Goto L;
End;
lll1:
//the Value differs from the Default Value And MUST be written
If Typ=PropType_Link Then B:=2
Else B:=1;
If Stream.Write(B,1)=0 Then Goto ex;
tt:=NameTableAdd(Namep); //Name Of the Property
If Stream.Write(tt,4)=0 Then Goto ex;
tt:=0;
Case Typ Of
PropType_Unsigned:B:=Ord(SCUUnsignedTypes[ValueLen]);
PropType_Signed:B:=Ord(SCUSignedTypes[ValueLen]);
PropType_Float:B:=Ord(SCUFloatTypes[ValueLen]);
PropType_Set:
Begin
If ValueLen=4 Then B:=Ord(SCUSet4)
Else B:=Ord(SCUSet32);
End;
PropType_CString:B:=Ord(SCUCString);
PropType_Record:
Begin
B:=Ord(SCURecord);
If Stream.Write(B,1)=0 Then Goto ex;
tt:=ValueLen;
If Stream.Write(tt,4)=0 Then Goto ex;
End;
PropType_Class:B:=Ord(SCUClass);
PropType_String:B:=Ord(SCUString);
PropType_Enum:B:=Ord(SCUEnum);
PropType_Boolean:B:=Ord(SCUBooleanTypes[ValueLen]);
PropType_Char:B:=Ord(SCUChar);
PropType_ClassVar:B:=Ord(SCUClassVar);
PropType_ProcVar:B:=Ord(SCUProcVar);
PropType_FuncVar:B:=Ord(SCUFuncVar);
PropType_Link:B:=Ord(SCULink);
Else
Begin
B:=Ord(SCUBinary);
If Stream.Write(B,1)=0 Then Goto ex;
tt:=ValueLen;
If Stream.Write(tt,4)=0 Then Goto ex;
End;
End;
If tt=0 Then If Stream.Write(B,1)=0 Then Goto ex; //Not For records
Case Typ Of
PropType_ProcVar,PropType_FuncVar: //Events
Begin
//Owner Type Name
If AOwner.FName=Nil Then AOwner.Name:=AOwner.ClassName;
tt:=NameTableAdd(AOwner.FName);
If Stream.Write(tt,4)=0 Then Goto ex;
//method Name
tt:=NameTableAdd(Methods^.Name);
If Stream.Write(tt,4)=0 Then Goto ex;
//Property Name
tt:=NameTableAdd(Namep);
If Stream.Write(tt,4)=0 Then Goto ex;
End;
PropType_Link: //Link
Begin
//Link field Name
If MyComp=Nil Then Goto ex;
If MyComp.FName=Nil Then MyComp.Name:=MyComp.ClassName;
tt:=NameTableAdd(MyComp.FName);
If Stream.Write(tt,4)=0 Then Goto ex;
End;
Else //others
Begin
If Typ=PropType_String Then ValueLen:=(Value^ And 255)+1; //String
If ValueLen>TypLen Then ValueLen:=TypLen;
If Stream.Write(Value^,ValueLen)=0 Then Goto ex;
End;
End; {Case}
End
Else Goto ex; //Some Error
L:
Result:=True;
ex:
FreeMem(Value,TypLen);
FreeMem(ReferenceValue,TypLen);
End;
Function WriteProperties(Stream:TMemoryStream;p1:Pointer;Objekt:TComponent;
pParent:Pointer):Boolean;
Var Namep,P,pp,p2:^LongInt;
B:Byte;
NameLen:LongInt;
len,OldPos,EndPos:LongInt;
ReferenceObjekt:TComponent;
ObjektClass:TComponentClass;
Scope:Byte;
Label L,ex;
Begin
Result:=False;
P:=p1;
ObjektClass:=Objekt.ClassType;
InsideWriteSCUAdr^:=True;
ReferenceObjekt:=Nil;
Try
ReferenceObjekt:=ObjektClass.Create({Objekt.FOwner}Nil);
Include(ReferenceObjekt.ComponentState, csWriting);
InsideWriteSCUAdr^:=False;
OldPos:=Stream.Position;
len:=0; //patched later
If Stream.Write(len,4)=0 Then Goto ex;
Inc(P,4); //onto Property Name Table
PropertyNameTable:=Pointer(P^);
Inc(P,4); //onto First Name
L:
NameLen:=P^ And 255;
Namep:=Pointer(P);
If NameLen<>0 Then
Begin
Inc(P,NameLen+1); //overread Name
Scope:=P^ And 255;
Inc(P);
If Scope And 16=0 Then //Not stored
Begin
Inc(P,4);
Goto L;
End;
//Property Is stored, Find out If we need To Write the Value Of it To the SCU Stream
p2:=Pointer(P^); //Property Type And access Info
If p2<>Nil Then
If Not WritePropertyValues(Stream,p2,Objekt,Namep,ReferenceObjekt) Then Goto ex; //Some Error
Inc(P,4); //Until All properties written
Goto L;
End;
If pParent<>Nil Then
Begin
pp:=pParent; //parent VMT Info
Inc(pp,4);
pp:=Pointer(pp^); //ClassInfo
Inc(pp,4);
pParent:=Pointer(pp^); //parent Class VMT Or Nil
Inc(pp,8);
pp:=Pointer(pp^); //Property Pointer
P:=pp;
p1:=P;
Inc(P,4); //onto Property Name Table
PropertyNameTable:=Pointer(P^);
Inc(P,4); //onto First Name
Goto L; //Write parent properties
End;
B:=0;
If Stream.Write(B,1)=0 Then Goto ex;
EndPos:=Stream.Position;
len:=EndPos-OldPos;
Stream.Position:=OldPos;
If Stream.Write(len,4)=0 Then Goto ex;
Stream.Position:=EndPos;
Result:=True;
ex:
Finally
If ReferenceObjekt<>Nil Then ReferenceObjekt.Destroy;
InsideWriteSCUAdr^:=False;
End;
End;
Function WriteNameTable(Stream:TMemoryStream):Boolean;
Var T:LongInt;
pp:PString;
Begin
Result:=False;
For T:=0 To NameTable.Count-1 Do
Begin
pp:=NameTable.Items[T];
If Stream.Write(pp^,Length(pp^)+1)=0 Then Exit;
End;
NameTable.Destroy; {!!}
Result:=True;
End;
Function WriteObjectComponents(Stream:TMemoryStream;ResStream:TResourceStream;
Objekt:TComponent):Boolean;
Var Count:LongInt;
PatchStreamPos:LongInt;
CurStreamPos:LongInt;
Begin
Result := False;
Objekt.SCUStream := Stream;
Objekt.SCUResStream := ResStream;
PatchStreamPos := Stream.Position;
Count := 0;
If Stream.Write(Count,4) = 0 Then Exit; {Write dummy, patch it later}
Objekt.FWriteComponentCount := 0;
Objekt.GetChildren(Objekt.WriteComponent);
Count := Objekt.FWriteComponentCount;
Objekt.SCUStream := Nil;
Objekt.SCUResStream := Nil;
CurStreamPos := Stream.Position;
Stream.Position := PatchStreamPos;
If Stream.Write(Count,4) = 0 Then Exit;
Stream.Position := CurStreamPos;
Result := Not Objekt.SCUWriteError;
End;
{Write SCU information Of the Child Component}
Procedure TComponent.WriteComponent(Child:TComponent);
Const Zero:LongInt=0;
Var pp,pp1,pParent1:^LongInt;
tt:LongInt;
B:Byte;
Ok:Boolean;
err:String[40];
Label ex;
Begin
If csReferenceControl In Child.ComponentState Then
Begin //Write the referenced Component before Self
If Child.FReference <> Nil Then WriteComponent(Child.FReference);
End;
Ok:=False;
err:='Stream write error';
Try
SCUWriteError := True;
If SCUStream = Nil Then Goto ex;
If SCUResStream = Nil Then Goto ex;
pp:=Pointer(Child);
pp:=Pointer(pp^); //VMT Info
Inc(pp,4);
pp:=Pointer(pp^); //ClassInfo
pp1:=pp;
Inc(pp,4);
pParent1:=Pointer(pp^); //parent Class VMT Or Nil
Inc(pp,8);
pp:=Pointer(pp^); //Property Pointer
//Write Inspector Class Name
Inc(pp1,16); //onto ClassName
tt:=NameTableAdd(Pointer(pp1));
If SCUStream.Write(tt,4)=0 Then Goto ex;
//Write runtime Class Name
If Child.FTypeName=Nil Then
Begin
B:=0; //runtime And Inspector Type Name are identical
If SCUStream.Write(B,1)=0 Then Goto ex;
End
Else
Begin
B:=1; //runtime Name Is different from Inspector Name
If SCUStream.Write(B,1)=0 Then Goto ex;
tt:=NameTableAdd(Child.FTypeName);
If SCUStream.Write(tt,4)=0 Then Goto ex;
End;
If Not WriteProperties(SCUStream,pp,Child,pParent1) Then
Begin
err:='WriteProperties error';
Goto ex; //Some Error
End;
//Write Components that are owned by the Object
If Not WriteObjectComponents(SCUStream,SCUResStream,Child) Then
Begin
err:='WriteObjectComponents error';
Goto ex;
End;
//Write Extra Data For that Component
If Not Child.WriteSCUResource(SCUResStream) Then
Begin
err:='WriteSCUResource error';
Goto ex;
End;
If SCUStream.Write(Zero,4)=0 Then Goto ex; {no more resources}
SCUWriteError := False;
Inc(FWriteComponentCount);
Ok:=True;
Except
err:=err+' due to exception';
End;
ex:
If Not Ok Then
Begin
Raise ESCUError.Create('SCU write error for '+Child.ClassName+': '+err);
End;
End;
Procedure TComponent.WriteToStream(SCUStream:TStream);
Const Zero:LongInt=0;
Var Stream:TMemoryStream;
ResourceStream:TResourceStream;
P,p1,pParent:^LongInt;
FileDesc:TSCUFileFormat;
Begin
Stream.Create;
Stream.Capacity:=32768;
ResourceStream.Create;
ResourceStream.Capacity:=32768;
ResourceStream.SCUStream:=Stream;
ResourceStream.FHeaderPos:=8; {Initial Resource Header}
NameTable.Create; {wo zerstört??}
FillChar(FileDesc,SizeOf(TSCUFileFormat),0);
FileDesc.Version:=SCUVersion;
If Stream.Write(FileDesc,SizeOf(TSCUFileFormat))=0 Then //SCU Header
Raise ESCUError.Create('Stream write error');
FileDesc.ObjectOffset:=Stream.Position;
FileDesc.ObjectCount:=1; //Count Of Objects
P:=Pointer(Self);
P:=Pointer(P^); //VMT Info
Inc(P,4);
P:=Pointer(P^); //ClassInfo
p1:=P;
Inc(P,4);
pParent:=Pointer(P^); //parent Class VMT Or Nil
Inc(P,8);
P:=Pointer(P^); //Property Pointer
Inc(p1,16); //onto ClassName
If Not WriteProperties(Stream,P,Self,pParent) Then
Raise ESCUError.Create('WriteProperties failed');
//Write Components that are owned by the Object
If Not WriteObjectComponents(Stream,ResourceStream,Self) Then
Raise ESCUError.Create('WriteObjectComponents failed');
If Not WriteSCUResource(ResourceStream) Then
Raise ESCUError.Create('WriteSCUResource failed');
If Stream.Write(Zero,4)=0 Then
Raise ESCUError.Create('Stream Write Error'); {no more resources}
FileDesc.ObjectLen:=Stream.Position-FileDesc.ObjectOffset;
//patch Name Table
FileDesc.NameTableOffset:=Stream.Position;
If Not WriteNameTable(Stream) Then
Raise ESCUError.Create('Stream write error');
FileDesc.NameTableLen:=Stream.Position-FileDesc.NameTableOffset;
FileDesc.ResourceOffset:=Stream.Position;
{Write Resource information}
If Not ResourceStream.WriteResourcesToStream(Stream) Then
Raise ESCUError.Create('Stream write error');
ResourceStream.Destroy;
FileDesc.ResourceLen:=Stream.Position-FileDesc.ResourceOffset;
Stream.Position:=0; //patch Header
If Stream.Write(FileDesc,SizeOf(TSCUFileFormat))=0 Then
Raise ESCUError.Create('Stream write error');
//Copy Stream
SCUStream.WriteBuffer(Stream.FBuffer^,Stream.FSize);
Stream.Destroy;
End;
Procedure TComponent.ReadSCU(Data:Pointer);
Var
ClassPointer,P,p1:^LongWord;
dummy:PSCUFileFormat;
NameTable:^LongWord;
ResourceTable:^LongWord;
ActComponentClass:TComponentClass;
S,s1:String;
ObjectCount:LongInt;
ps:^String;
OldInsideDesigner:Boolean;
LanguageInfo:^LongWord;
MessageInfo:^LongWord;
Flags:Byte;
T:LongInt;
CurrentLanguage:String;
LangItem:PLanguageItem;
Msgs:PLanguageMessages;
MsgLen:LongWord;
Procedure ReadLanguage(Var Components:PLanguageComponent);
Var
LangComp:PLanguageComponent;
ps:^String;
Begin
Components:=Nil;
While (LanguageInfo^ And 255)<>0 Do //Read All Components entries
Begin
Inc(LanguageInfo); //skip 1
If Components=Nil Then
Begin
New(Components);
LangComp:=Components;
End
Else
Begin
LangComp:=Components;
While LangComp^.Next<>Nil Do LangComp:=LangComp^.Next;
New(LangComp^.Next);
LangComp:=LangComp^.Next;
End;
LangComp^.Next:=Nil;
ps:=Pointer(LanguageInfo);
GetMem(LangComp^.Name,Length(ps^)+1);
LangComp^.Name^:=ps^;
Inc(LanguageInfo,Length(ps^)+1);
LangComp^.ValueTyp:=LanguageInfo^ And 255;
Inc(LanguageInfo);
LangComp^.ValueLen:=LanguageInfo^;
Inc(LanguageInfo,4);
GetMem(LangComp^.Value,LangComp^.ValueLen);
Move(LanguageInfo^,LangComp^.Value^,LangComp^.ValueLen);
Inc(LanguageInfo,LangComp^.ValueLen);
LangComp^.ControlLeft:=LanguageInfo^;
Inc(LanguageInfo,4);
LangComp^.ControlBottom:=LanguageInfo^;
Inc(LanguageInfo,4);
LangComp^.ControlWidth:=LanguageInfo^;
Inc(LanguageInfo,4);
LangComp^.ControlHeight:=LanguageInfo^;
Inc(LanguageInfo,4);
End;
Inc(LanguageInfo); //skip 0
End;
Label loadit,Next,skip;
Begin
OldInsideDesigner:=InsideDesigner;
dummy:=Data;
PropertyLinks:=Nil;
MessageInfo:=NIL;
LanguageInfo:=NIL;
While dummy<>Nil Do
Begin
NameTable:=Pointer(dummy);
Inc(NameTable,dummy^.NameTableOffset);
ResourceTable:=Pointer(dummy);
Inc(ResourceTable,dummy^.ResourceOffset);
P:=Pointer(dummy);
Inc(P,dummy^.ObjectOffset);
S:=ClassName;
UpcaseStr(S);
If ((((InsideDesigner)Or(InsideLanguageDesigner)))And(S='TFORMEDITOR')) Then
Begin
//always Use the Class entry defined by dummy^.UseEntry !
p1:=Pointer(dummy);
Inc(p1,SizeOf(TSCUFileFormat));
ObjectCount:=0;
LanguageInfo:=Nil;
MessageInfo:=Nil;
While ObjectCount<>dummy^.UseEntry+1 Do
Begin
Flags:=p1^ And 255; //1- auto Create, 2- Language Info avail
Inc(p1); //skip flag
Inc(p1,(p1^ And 255)+1); //skip Form Name
Inc(p1,(p1^ And 255)+1); //skip Form Unit Name
Inc(p1,(p1^ And 255)+1); //skip Form TypeName
//If Message information Is available For This Form (only For First) remember And skip it !
If (Flags And 8)<>0 Then
Begin
MessageInfo:=Pointer(p1);
Inc(p1,p1^);
End;
//If Language information Is available For This Form, remember And skip
LanguageInfo:=Pointer(p1);
If Flags And 2<>0 Then Inc(p1,p1^); //skip Language Info
Inc(ObjectCount);
End;
If (Flags And 2)=0 Then LanguageInfo:=Nil; //no languages avail
If (Flags And 4)<>0 Then LanguageInfo:=Nil; //locked !!
ObjectCount:=0;
While ObjectCount<>dummy^.UseEntry Do
Begin
Inc(P,{4+}P^); //overread This entry
Inc(ObjectCount);
End;
ClassPointer:=P;
Inc(P,4); //Set ON Inspector Class Name
Inc(P,(P^ And 255)+1); //overread Inspector Name
Inc(P,(P^ And 255)+1); //overread runtime Class Name
ps:=Pointer(P); //Unit Name For This Form
AssignStr(FUnitName,ps^);
Goto loadit;
End
Else
Begin
//don't Read any Classes when inside designer !
//If (InsideDesigner And (Not InsideCompLib)) Then Exit;
If InsideCompLib Then InsideDesigner:=False;
//Search For Class named S inside area P With dummy^.ObjectCount
//entries And Set ClassPointer To Object Data Start
//Use also ClassUnit For Reference
ClassPointer:=SearchClassSCU(P,S,dummy^.ObjectCount,ClassUnit);
If ClassPointer=Nil Then Goto Next; //no Class found
//look If Language Info Is avail
p1:=Pointer(dummy);
Inc(p1,SizeOf(TSCUFileFormat));
For T:=1 To dummy^.ObjectCount Do
Begin
Flags:=p1^ And 255;
Inc(p1); //skip flag
Inc(p1,(p1^ And 255)+1); //skip Form Name
Inc(p1,(p1^ And 255)+1); //skip Form Unit Name
If (Flags And 2)<>0 Then //Language Info avail ???
Begin
ps:=Pointer(p1);
Inc(p1,(p1^ And 255)+1); //skip Form Type Name
//If Message information Is available For This Form (only For First) skip it !
If (Flags And 8)<>0 Then Inc(p1,p1^);
s1:=ps^;
UpcaseStr(s1);
If S=s1 Then //found !
Begin
LanguageInfo:=Pointer(p1);
If (Flags And 4)<>0 Then LanguageInfo:=Nil; //locked !!
Goto loadit;
End
Else Inc(p1,p1^); //only skip Info
End
Else
Begin
Inc(p1,(p1^ And 255)+1); //skip Form Type Name
//If Message information Is available For This Form (only For First) skip it !
If (Flags And 8)<>0 Then Inc(p1,p1^);
End;
End;
LanguageInfo:=Nil; //Not found
loadit:
Inc(ClassPointer,4); //Set ON Inspector Class Name
Inc(ClassPointer,(ClassPointer^ And 255)+1); //overread Inspector Name
Inc(ClassPointer,(ClassPointer^ And 255)+1); //overread runtime Class Name
Inc(ClassPointer,(ClassPointer^ And 255)+1); //overread Unit Name
ActComponentClass:=ClassType;
RegisterClasses([ActComponentClass]); //Form registrieren
If ((InsideDesigner)Or(InsideLanguageDesigner)) Then
Begin
FMethods:=Nil; //no Methods defined
End;
LastSCUForm:=Self;
LoadingFromSCU(Nil);
//Build Message lists
If MessageInfo<>Nil Then
Begin
Inc(MessageInfo,4); //skip Size
ps:=Pointer(MessageInfo);
AppLanguage:=ps^;
Inc(MessageInfo,Length(ps^)+1);
ps:=Pointer(MessageInfo);
While Length(ps^)<>0 Do
Begin
//look If the Language Is installed, skip If True
If LanguageMessages=Nil Then
Begin
New(LanguageMessages);
Msgs:=LanguageMessages;
End
Else
Begin
Msgs:=LanguageMessages;
While Msgs^.Next<>Nil Do
Begin
If Msgs^.Name^=ps^ Then
Begin
Inc(MessageInfo,Length(ps^));
MsgLen:=MessageInfo^;
Inc(MessageInfo,4);
Inc(MessageInfo,MsgLen);
Goto skip;
End;
Msgs:=Msgs^.Next;
End;
If Msgs^.Name^=ps^ Then
Begin
Inc(MessageInfo,Length(ps^)+1);
MsgLen:=MessageInfo^;
Inc(MessageInfo,4);
Inc(MessageInfo,MsgLen);
Goto skip;
End;
New(Msgs^.Next);
Msgs:=Msgs^.Next;
End;
GetMem(Msgs^.Name,Length(ps^)+1);
Msgs^.Name^:=ps^;
Inc(MessageInfo,Length(ps^)+1);
Msgs^.StringTableLen:=MessageInfo^;
Inc(MessageInfo,4);
GetMem(Msgs^.StringTable,Msgs^.StringTableLen);
Move(MessageInfo^,Msgs^.StringTable^,Msgs^.StringTableLen);
Inc(MessageInfo,Msgs^.StringTableLen);
skip:
ps:=Pointer(MessageInfo);
End;
End;
//Build Language lists
If LanguageInfo<>Nil Then
Begin
Inc(LanguageInfo,4); //skip Size
GetMem(FLanguages,SizeOf(TLanguageInfo));
ps:=Pointer(LanguageInfo);
CurrentLanguage:=ps^; //To determine Language !
Inc(LanguageInfo,Length(CurrentLanguage)+1);
While (LanguageInfo^ And 255)<>0 Do //Read All entries
Begin
Inc(LanguageInfo); //skip 1
If PLanguageInfo(FLanguages)^.Items=Nil Then
Begin
New(LangItem);
PLanguageInfo(FLanguages)^.Items:=LangItem;
End
Else
Begin
LangItem:=PLanguageInfo(FLanguages)^.Items;
While LangItem^.Next<>Nil Do LangItem:=LangItem^.Next;
New(LangItem^.Next);
LangItem:=LangItem^.Next;
End;
LangItem^.Next:=Nil;
ps:=Pointer(LanguageInfo);
GetMem(LangItem^.Name,Length(ps^)+1);
LangItem^.Name^:=ps^;
Inc(LanguageInfo,Length(ps^)+1);
ReadLanguage(LangItem^.Components);
ReadLanguage(LangItem^.Menus);
ReadLanguage(LangItem^.StringTables);
End; //While
Inc(LanguageInfo); //skip 0
If PLanguageInfo(FLanguages)^.Items=Nil Then //no Items
Begin
FreeMem(FLanguages,SizeOf(TLanguageInfo));
FLanguages:=Nil;
End
Else
Begin
//Set Current Language into Form^.LanguageInfo
LangItem:=PLanguageInfo(FLanguages)^.Items;
While LangItem<>Nil Do
Begin
If LangItem^.Name^=CurrentLanguage Then //found
Begin
PLanguageInfo(FLanguages)^.CurrentLanguageName:=LangItem^.Name;
PLanguageInfo(FLanguages)^.CurrentLanguageComponents:=LangItem^.Components;
PLanguageInfo(FLanguages)^.CurrentLanguageMenus:=LangItem^.Menus;
PLanguageInfo(FLanguages)^.CurrentLanguageStringTables:=LangItem^.StringTables;
break;
End;
LangItem:=LangItem^.Next;
End;
If PLanguageInfo(FLanguages)^.CurrentLanguageName=Nil Then
Begin
//Not found - Use First available Language
LangItem:=PLanguageInfo(FLanguages)^.Items;
PLanguageInfo(FLanguages)^.CurrentLanguageName:=LangItem^.Name;
PLanguageInfo(FLanguages)^.CurrentLanguageComponents:=LangItem^.Components;
PLanguageInfo(FLanguages)^.CurrentLanguageMenus:=LangItem^.Menus;
PLanguageInfo(FLanguages)^.CurrentLanguageStringTables:=LangItem^.StringTables;
End;
End;
End;
If Not ReadPropertiesSCU(Self,NameTable,ResourceTable,ClassPointer) Then
Begin
InsideDesigner:=OldInsideDesigner;
Raise ESCUError.Create('ReadPropertiesSCU error');
End;
SetDesigning(InsideDesigner Or InsideLanguageDesigner);
//check For Child Components
If Not ReadComponentsSCU(NameTable,ResourceTable,ClassPointer) Then
Begin
InsideDesigner:=OldInsideDesigner;
Raise ESCUError.Create('ReadComponentsSCU error');
End;
//links For the Form
HandlePropertyLinks(Self);
ReadResourceSCU(ResourceTable,ClassPointer);
If FLanguages<>Nil Then
If PLanguageInfo(FLanguages)^.CurrentLanguageName<>Nil Then
SetLanguage(Self,PLanguageInfo(FLanguages)^.CurrentLanguageName^);
//If there's only the Default Language Left, Erase it !
If FLanguages<>Nil Then
If PLanguageInfo(FLanguages)^.Items<>Nil Then
If PLanguageInfo(FLanguages)^.Items^.Next=Nil Then
If PLanguageInfo(FLanguages)^.Items^.Name^='Default' Then
Begin
FreeLanguage(PLanguageInfo(FLanguages)^.Items^.Components);
FreeLanguage(PLanguageInfo(FLanguages)^.Items^.Menus);
FreeLanguage(PLanguageInfo(FLanguages)^.Items^.StringTables);
FreeMem(PLanguageInfo(FLanguages)^.Items^.Name,Length(PLanguageInfo(FLanguages)^.Items^.Name^)+1);
Dispose(PLanguageInfo(FLanguages)^.Items);
FreeMem(FLanguages,SizeOf(TLanguageInfo));
FLanguages:=Nil;
End;
{For the Form}
LoadedFromSCU(Nil);
Loaded;
InsideDesigner:=OldInsideDesigner;
Exit;
End;
Next:
dummy:=dummy^.NextEntry;
End;
InsideDesigner:=OldInsideDesigner;
End;
Procedure TComponent.ReadFromStream(SCUStream:TStream);
Var
ClassMem,ClassPointer:^LongWord;
OldPos:LongInt;
OldInsideDesigner:Boolean;
FileDesc:TSCUFileFormat;
len:LongInt;
NameTable:^LongWord;
ResourceTable:^LongWord;
Begin
Try
ClassPointer:=Nil;
OldInsideDesigner:=InsideDesigner;
If InsideCompLib Then InsideDesigner:=False;
OldPos:=SCUStream.Position;
SCUStream.ReadBuffer(FileDesc,SizeOf(FileDesc));
SCUStream.Position:=OldPos;
len:=SizeOf(FileDesc)+FileDesc.ObjectLen+FileDesc.NameTableLen+FileDesc.ResourceLen;
GetMem(ClassPointer,len);
ClassMem:=ClassPointer;
SCUStream.ReadBuffer(ClassPointer^,len);
NameTable:=Pointer(ClassPointer);
Inc(NameTable,FileDesc.NameTableOffset);
ResourceTable:=Pointer(ClassPointer);
Inc(ResourceTable,FileDesc.ResourceOffset);
Inc(ClassPointer,FileDesc.ObjectOffset);
LastSCUForm:=Owner;
SetDesigning(InsideDesigner Or InsideLanguageDesigner);
LoadingFromSCU(LastSCUForm);
If Not ReadPropertiesSCU(LastSCUForm,NameTable,ResourceTable,ClassPointer) Then
Raise ESCUError.Create('SCU error');
If Not ReadComponentsSCU(NameTable,ResourceTable,ClassPointer) Then
Raise ESCUError.Create('SCU error');
ReadResourceSCU(ResourceTable,ClassPointer);
LoadedFromSCU(LastSCUForm);
Finally
InsideDesigner:=OldInsideDesigner;
If ClassMem<>Nil Then FreeMem(ClassMem,len);
End;
End;
{$HINTS OFF}
Procedure TComponent.GetChildren(Proc:TGetChildProc);
Begin
End;
{$HINTS ON}
Function TComponent.HasParent:Boolean;
Begin
Result := False;
End;
Function WritePropertiesToStream(FormList:TList):TMemoryStream;
Const Zero:LongInt=0;
bt:Byte=1;
bf:Byte=0;
Var P,p1:^LongInt;
pParent:^LongInt;
S:String;
tt,tt1,Pos1:LongInt;
FormItem:PFormListItem;
Stream:TMemoryStream;
ResourceStream:TResourceStream;
FileDesc:TSCUFileFormat;
C:TComponent;
D,N,E:String;
bb:Byte;
LangItem:PLanguageItem;
LangPos,LangTemp:LongInt;
dummy:PLanguageMessages;
Function WriteLanguage(LangComp:PLanguageComponent):Boolean;
Var Ende:Byte;
Begin
Result:=False;
While LangComp<>Nil Do
Begin
If Stream.Write(bt,1)=0 Then Exit; //one more entry
If Stream.Write(LangComp^.Name^,Length(LangComp^.Name^)+1)=0 Then Exit;
If Stream.Write(LangComp^.ValueTyp,1)=0 Then Exit;
If Stream.Write(LangComp^.ValueLen,4)=0 Then Exit;
If Stream.Write(LangComp^.Value^,LangComp^.ValueLen)=0 Then Exit;
If Stream.Write(LangComp^.ControlLeft,4)=0 Then Exit;
If Stream.Write(LangComp^.ControlBottom,4)=0 Then Exit;
If Stream.Write(LangComp^.ControlWidth,4)=0 Then Exit;
If Stream.Write(LangComp^.ControlHeight,4)=0 Then Exit;
LangComp:=LangComp^.Next;
End;
Ende:=0;
If Stream.Write(Ende,1)=0 Then Exit; //no more entries
Result:=True;
End;
Label err;
Begin
Result:=Nil; //Some Error
Stream.Create;
Stream.Capacity:=32768;
ResourceStream.Create;
ResourceStream.Capacity:=32768;
ResourceStream.SCUStream:=Stream;
ResourceStream.FHeaderPos:=8; {Initial Resource Header}
NameTable.Create;
FillChar(FileDesc,SizeOf(TSCUFileFormat),0);
FileDesc.Version:=SCUVersion;
If Stream.Write(FileDesc,SizeOf(TSCUFileFormat))=0 Then //SCU Header
Begin
err:
Stream.Destroy;
ResourceStream.Destroy;
Result:=Nil;
Exit; //Some Error
End;
Try
For tt:=0 To FormList.Count-1 Do
Begin
FormItem:=FormList.Items[tt];
C:=Pointer(FormItem^.Form);
If C = Nil Then Goto err; {need Form}
bb:=0;
If C.DesignerState*[dsAutoCreate]<>[] Then bb:=bb Or 1; //auto-created Form
If C.FLanguages<>Nil Then bb:=bb Or 2; //Multi Language
//!!!!!!!!!! 4 Is reserved For locking Language !!!!!!!!!!!!!!!!!!!
//note: Messages are global To an Application, Not To A Form !!!!
If ((tt=0)And(LanguageMessages<>Nil)) Then bb:=bb Or 8; //Messages avail
If Stream.Write(bb,1)=0 Then Goto err;
S:=FormItem^.FormName+#0;
UpcaseStr(S);
If Stream.Write(S,Length(S)+1)=0 Then Goto err;
S:=FormItem^.UnitName;
FSplit(S,D,N,E);
N:=N+#0;
UpcaseStr(N);
If Stream.Write(N,Length(N)+1)=0 Then Goto err;
If FormItem^.FormName<>'' Then S:='T'+FormItem^.FormName
Else S:=FormItem^.Form.ClassName;
If Stream.Write(S,Length(S)+1)=0 Then Goto err; //runtime Class Name
//Language Messages are only evaluated by Application.Create by examining the SCU Pointer !!!
If ((tt=0)And(LanguageMessages<>Nil)) Then
Begin
//Write Language Message information
LangPos:=Stream.Position; //save Position
If Stream.Write(LangPos,4)=0 Then Goto err; //Size: patched later
If Stream.Write(AppLanguage,Length(AppLanguage)+1)=0 Then Goto err;
dummy:=LanguageMessages;
While dummy<>Nil Do
Begin
If Stream.Write(dummy^.Name^,Length(dummy^.Name^)+1)=0 Then Goto err;
If Stream.Write(dummy^.StringTableLen,4)=0 Then Goto err;
If dummy^.StringTableLen>0 Then
If Stream.Write(dummy^.StringTable^,dummy^.StringTableLen)=0 Then Goto err;
dummy:=dummy^.Next;
End;
If Stream.Write(bf,1)=0 Then Goto err; //no more entries
LangTemp:=Stream.Position;
Stream.Position:=LangPos; //patch Size
LangPos:=LangTemp-LangPos;
If Stream.Write(LangPos,4)=0 Then Goto err;
Stream.Position:=LangTemp; //restore old Position
End;
If C.FLanguages<>Nil Then
Begin
//Write Language information
LangPos:=Stream.Position; //save Position
If Stream.Write(LangPos,4)=0 Then Goto err; //Size: patched later
If PLanguageInfo(C.FLanguages)^.CurrentLanguageName<>Nil Then
Begin
If Stream.Write(PLanguageInfo(C.FLanguages)^.CurrentLanguageName^,
Length(PLanguageInfo(C.FLanguages)^.CurrentLanguageName^)+1)=0 Then Goto err;
End
Else
Begin
S:='Default';
If Stream.Write(S,Length(S)+1)=0 Then Goto err;
End;
LangItem:=PLanguageInfo(C.FLanguages)^.Items;
While LangItem<>Nil Do
Begin
If Stream.Write(bt,1)=0 Then Goto err; //one more entry
If Stream.Write(LangItem^.Name^,Length(LangItem^.Name^)+1)=0 Then Goto err;
If Not WriteLanguage(LangItem^.Components) Then Goto err;
If Not WriteLanguage(LangItem^.Menus) Then Goto err;
If Not WriteLanguage(LangItem^.StringTables) Then Goto err;
LangItem:=LangItem^.Next;
End;
If Stream.Write(bf,1)=0 Then Goto err; //no more entries
LangTemp:=Stream.Position;
Stream.Position:=LangPos; //patch Size
LangPos:=LangTemp-LangPos;
If Stream.Write(LangPos,4)=0 Then Goto err;
Stream.Position:=LangTemp; //restore old Position
End;
End;
FileDesc.ObjectOffset:=Stream.Position;
FileDesc.ObjectCount:=FormList.Count; //Count Of Objects
For tt:=0 To FormList.Count-1 Do
Begin
Pos1:=Stream.Position;
tt1:=0;
If Stream.Write(tt1,4)=0 Then Goto err; //Length Of Object Info
//- patched later
FormItem:=FormList.Items[tt];
P:=Pointer(FormItem^.Form);
P:=Pointer(P^); //VMT Info
Inc(P,4);
P:=Pointer(P^); //ClassInfo
p1:=P;
Inc(P,4);
pParent:=Pointer(P^); //parent Class VMT Or Nil
Inc(P,8);
P:=Pointer(P^); //Property Pointer
Inc(p1,16); //onto ClassName
Move(p1^,S,(p1^ And 255)+1); //Inspector Class Name
If Stream.Write(S,Length(S)+1)=0 Then Goto err; //Inspector Class Name
If FormItem^.FormName<>'' Then S:='T'+FormItem^.FormName
Else S:=FormItem^.Form.ClassName;
If Stream.Write(S,Length(S)+1)=0 Then Goto err; //runtime Class Name
If Stream.Write(FormItem^.UnitName,Length(FormItem^.UnitName)+1)=0 Then Goto err;
If Not WriteProperties(Stream,P,TComponent(FormItem^.Form),pParent) Then Goto err;
//Write Components that are owned by the Object
If Not WriteObjectComponents(Stream,ResourceStream,TComponent(FormItem^.Form)) Then Goto err;
If Not FormItem^.Form.WriteSCUResource(ResourceStream) Then Goto err;
If Stream.Write(Zero,4)=0 Then Goto err; {no more resources}
tt1:=Stream.Position;
Stream.Position:=Pos1;
Pos1:=tt1-Pos1;
Stream.Write(Pos1,4); //patch len Of Object Info For This entry
Stream.Position:=tt1;
End; //For
FileDesc.ObjectLen:=Stream.Position-FileDesc.ObjectOffset;
//patch Name Table
FileDesc.NameTableOffset:=Stream.Position;
If Not WriteNameTable(Stream) Then Goto err;
FileDesc.NameTableLen:=Stream.Position-FileDesc.NameTableOffset;
FileDesc.ResourceOffset:=Stream.Position;
{Write Resource information}
If Not ResourceStream.WriteResourcesToStream(Stream) Then Goto err;
ResourceStream.Destroy;
FileDesc.ResourceLen:=Stream.Position-FileDesc.ResourceOffset;
{ab hier nichts mehr schreiben, sonst System.AddSCUData ändern}
tt:=Stream.Position; //save Position
Stream.Position:=0; //patch Header
If Stream.Write(FileDesc,SizeOf(TSCUFileFormat))=0 Then Goto err;
Stream.Position:=tt; //restore Position
Except
ON ex:Exception Do
Begin
ErrorBox2(ex.Message);
Stream.Destroy;
ResourceStream.Destroy;
Stream:=Nil;
End;
End;
Result:=Stream;
End;
Function WritePropertiesToFile(FileName:String;FormList:TList):Boolean;
Var Stream:TMemoryStream;
Begin
Stream:=WritePropertiesToStream(FormList);
If Stream=Nil Then
Begin
Result:=False;
Exit;
End;
Result:=True;
Try
Stream.SaveToFile(FileName);
Except
ON ex:Exception Do
Begin
ErrorBox2(ex.Message);
Result:=False;
End;
End;
Stream.Destroy;
End;
{
╔═══════════════════════════════════════════════════════════════════════════╗
║ ║
║ Speed-Pascal/2 Version 2.0 ║
║ ║
║ Speed-Pascal Component Classes (SPCC) ║
║ ║
║ This section: TStringItem Class Implementation ║
║ ║
║ (C) 1995,97 SpeedSoft. All rights reserved. Disclosure probibited ! ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════╝
}
Procedure TStringSelectList.SetupComponent;
Begin
Inherited SetupComponent;
FList.Create;
FList.sorted:=True;
Include(ComponentState, csDetail);
End;
Procedure TStringSelectList.SetStringItem(NewValue:String);
Begin
FSelected:=NewValue;
End;
Destructor TStringSelectList.Destroy;
Begin
FList.Destroy;
FList := Nil;
Inherited Destroy;
End;
Function TStringSelectList.GetItems:TStringList;
Begin
Result:=FList;
End;
{
╔═══════════════════════════════════════════════════════════════════════════╗
║ ║
║ Speed-Pascal/2 Version 2.0 ║
║ ║
║ Speed-Pascal Component Classes (SPCC) ║
║ ║
║ This section: TBits Class Implementation ║
║ ║
║ (C) 1995,97 SpeedSoft. All rights reserved. Disclosure probibited ! ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════╝
}
Destructor TBits.Destroy;
Begin
FreeMem(FBits, (FSize + 31) Shr 5);
FBits := Nil;
Inherited Destroy;
End;
Procedure TBits.Error;
Begin
Raise EBitsError.Create(LoadNLSStr(SEBitsErrorText));
End;
Function TBits.GetBit(Index: LongInt): Boolean;
Var
Place: Cardinal;
Begin
If (Index < 0) Or (Index >= FSize) Then Error;
Place := 1 Shl (Index And 31);
Index := Index Shr 5;
Result := (FBits^[Index] And Place) <> 0;
End;
Function TBits.OpenBit: LongInt;
Var
I, J, K: LongInt;
B: Cardinal;
Begin
I := 0;
J := (FSize + 31) Shr 5;
While (I < J) And (FBits^[I] = 0) Do Inc(I);
If I < J Then
Begin
K := 1;
Result := I Shl 5;
B := FBits^[I];
While (B And K) = 0 Do
Begin
K := K Shl 1;
Inc(Result);
End;
If Result >= FSize Then Result := -1;
End
Else Result := -1;
End;
Procedure TBits.SetBit(Index: LongInt; bit: Boolean);
Var
Place: Cardinal;
Begin
If (Index < 0) Or (Index >= FSize) Then Error;
Place := 1 Shl (Index And 31);
Index := Index Shr 5;
If bit Then FBits^[Index] := FBits^[Index] Or Place
Else FBits^[Index] := FBits^[Index] And Not Place;
End;
Procedure TBits.SetSize(NewSize: LongInt);
Begin
If NewSize < 0 Then Error;
If FSize = 0 Then FBits := AllocMem((NewSize + 31) Shr 3)
Else FBits := ReAllocMem(FBits, (FSize + 31) Shr 3, (NewSize + 31) Shr 3);
FSize := NewSize;
End;
{
╔═══════════════════════════════════════════════════════════════════════════╗
║ ║
║ Speed-Pascal/2 Version 2.0 ║
║ ║
║ Speed-Pascal Component Classes (SPCC) ║
║ ║
║ This section: TPropertyEditClassDialog Class Implementation ║
║ ║
║ (C) 1995,97 SpeedSoft. All rights reserved. Disclosure probibited ! ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════╝
}
Type
PPropertyEditClassItem=^TPropertyEditClassItem;
TPropertyEditClassItem=Record
ClassToEdit: TClass; //Editor Class (Class editors) Or parent Class (others)
PropertyName:String[64]; //Property Name For normal editors
ClassPropertyEditor: TClassPropertyEditorClass; //<>Nil For Class Property editors
PropertyEditor:TPropertyEditorClass; //<>Nil For normal Property editors
End;
{$HINTS OFF}
Function TClassPropertyEditor.Execute(Var ClassToEdit:TObject):TClassPropertyEditorReturn;
Begin
Result:=peCancel; //Not Handled
End;
{$HINTS ON}
Procedure AddPropertyEditor(OwnerClass:TClass;PropertyName:String;PropertyEditor:TPropertyEditorClass);
Var T:LongInt;
dummy:PPropertyEditClassItem;
Begin
UpcaseStr(PropertyName);
For T:=0 To PropertyEditDialogs.Count-1 Do
Begin
dummy:=PropertyEditDialogs.Items[T];
If dummy^.PropertyEditor<>Nil Then //normal Property Editor ??
If OwnerClass=dummy^.ClassToEdit Then
If dummy^.PropertyName=PropertyName Then
Begin
//replace existing
dummy^.PropertyEditor:=PropertyEditor;
Exit;
End;
End;
New(dummy);
dummy^.ClassToEdit:=OwnerClass;
dummy^.PropertyName:=PropertyName;
dummy^.PropertyEditor:=PropertyEditor;
PropertyEditDialogs.Add(dummy);
End;
Function CallPropertyEditor(Owner:TComponent;PropertyName:String;Var Value;ValueLen:LongInt;
Var List:TStringList):TPropertyEditorReturn;
Var T:LongInt;
dummy:PPropertyEditClassItem;
Editor:TPropertyEditor;
S:String;
Label go;
Begin
Result:=edNoEditor;
UpcaseStr(PropertyName);
For T:=0 To PropertyEditDialogs.Count-1 Do
Begin
dummy:=PropertyEditDialogs.Items[T];
If dummy^.PropertyEditor<>Nil Then //normal Property Editor ??
If Owner.ClassType=dummy^.ClassToEdit Then
If dummy^.PropertyName=PropertyName Then
Begin
go:
Editor:=dummy^.PropertyEditor.Create(Nil);
Editor.FOwner:=Owner;
Editor.FPropertyName:=PropertyName;
List.Create;
Editor.FList:=List;
Try
If Editor Is TStringPropertyEditor Then
Begin
System.Move(Value,S,ValueLen);
Result:=TStringPropertyEditor(Editor).Execute(S,ValueLen);
System.Move(S,Value,ValueLen);
End
Else If Editor Is TShortIntPropertyEditor Then
Result:=TShortIntPropertyEditor(Editor).Execute(ShortInt(Value))
Else If Editor Is TIntegerPropertyEditor Then
Result:=TIntegerPropertyEditor(Editor).Execute(Integer(Value))
Else If Editor Is TLongIntPropertyEditor Then
Result:=TLongIntPropertyEditor(Editor).Execute(LongInt(Value))
Else Result:=Editor.Execute(Value,ValueLen);
List:=Editor.FList;
Editor.Destroy;
Except
Result:=edNoEditor;
End;
Exit;
End;
End;
For T:=0 To PropertyEditDialogs.Count-1 Do
Begin
dummy:=PropertyEditDialogs.Items[T];
If dummy^.PropertyEditor<>Nil Then //normal Property Editor ??
If Owner Is dummy^.ClassToEdit Then
If dummy^.PropertyName=PropertyName Then
Begin
Goto go;
End;
End;
{Search In registered Property editors Of the complib}
If @CallCompLibPropertyEditor<>Nil
Then Result := CallCompLibPropertyEditor(Owner,PropertyName,Value,ValueLen,List);
End;
Function PropertyEditorAvailable(OwnerClass:TClass;PropertyName:String):Boolean;
Var T:LongInt;
dummy:PPropertyEditClassItem;
Begin
Result:=False;
UpcaseStr(PropertyName);
For T:=0 To PropertyEditDialogs.Count-1 Do
Begin
dummy:=PropertyEditDialogs.Items[T];
If dummy^.PropertyEditor<>Nil Then //normal Property Editor ??
If dummy^.PropertyName=PropertyName Then
If OwnerClass Is dummy^.ClassToEdit Then
Begin
Result:=True;
Exit;
End;
End;
If @CallCompLibPropertyEditorAvailable<>Nil Then
Result:=CallCompLibPropertyEditorAvailable(OwnerClass,PropertyName);
End;
Procedure AddClassPropertyEditor(ClassToEdit:TClass;PropertyEditor:TClassPropertyEditorClass);
Var T:LongInt;
dummy:PPropertyEditClassItem;
Begin
For T:=0 To PropertyEditDialogs.Count-1 Do
Begin
dummy:=PropertyEditDialogs.Items[T];
If dummy^.ClassPropertyEditor<>Nil Then //Class Property Editor ??
If dummy^.ClassToEdit=ClassToEdit Then
Begin
//replace existing
dummy^.ClassPropertyEditor:=PropertyEditor;
Exit;
End;
End;
New(dummy);
dummy^.ClassToEdit:=ClassToEdit;
dummy^.ClassPropertyEditor:=PropertyEditor;
PropertyEditDialogs.Add(dummy);
End;
Function ClassPropertyEditorAvailable(ClassName:String):Boolean;
Var
s1:String;
AOwner:TClass;
Function process(Const s1:String):Boolean;
Var T:LongInt;
dummy:PPropertyEditClassItem;
S:String;
Begin
Result:=False;
For T:=0 To PropertyEditDialogs.Count-1 Do
Begin
dummy:=PropertyEditDialogs.Items[T];
If dummy^.ClassPropertyEditor<>Nil Then //Class Property Editor ???
Begin
S:=dummy^.ClassToEdit.ClassName;
UpcaseStr(S);
If S=s1 Then
Begin
Result:=True;
Exit;
End;
End;
End;
End;
Label L,ex;
Begin
Result:=False;
s1:=ClassName;
UpcaseStr(s1);
If process(s1) Then
Begin
Result:=True;
Exit;
End;
//check If it Is Some derived Object
AOwner:=SearchClassByName(ClassName);
If AOwner=Nil Then goto ex;
L:
AOwner:=AOwner.ClassParent;
If AOwner<>Nil Then
Begin
s1:=AOwner.ClassName;
UpcaseStr(s1);
If process(s1) Then Result:=True
Else Goto L;
End;
ex:
If @CallComplibClassPropertyEditorAvailable<>Nil Then
Result:=Result Or CallCompLibClassPropertyEditorAvailable(ClassName);
End;
Function CallClassPropertyEditor(Var ClassToEdit:TObject):TClassPropertyEditorReturn;
Var
s1:String;
AOwner:TClass;
res:TClassPropertyEditorReturn;
Function process(Const s1:String):Boolean;
Var T:LongInt;
dummy:PPropertyEditClassItem;
Editor:TClassPropertyEditor;
S:String;
Begin
Result:=False;
For T:=0 To PropertyEditDialogs.Count-1 Do
Begin
dummy:=PropertyEditDialogs.Items[T];
If dummy^.ClassPropertyEditor<>Nil Then //Is it A Class Property Editor ??
Begin
S:=dummy^.ClassToEdit.ClassName;
UpcaseStr(S);
If S=s1 Then
Begin
Editor:=dummy^.ClassPropertyEditor.Create(Nil);
res:=Editor.Execute(ClassToEdit);
Editor.Destroy;
Result:=True;
Exit;
End;
End;
End;
End;
Begin
Result:=peNoEditor;
s1:=ClassToEdit.ClassName;
UpcaseStr(s1);
If process(s1) Then
Begin
Result:=res;
Exit;
End;
{Search In registered Property editors Of the complib}
If @CallCompLibClassPropertyEditor<>Nil
Then Result := CallCompLibClassPropertyEditor(ClassToEdit);
If Result<>peNoEditor Then exit;
//check If it Is Some derived Object
AOwner := ClassToEdit.ClassType;
While AOwner.ClassParent <> Nil Do
Begin
AOwner:=AOwner.ClassParent;
s1:=AOwner.ClassName;
UpcaseStr(s1);
If process(s1) Then
Begin
Result:=res;
Exit;
End;
End;
Result:=peNoEditor;
End;
///////////////////////////////////////////////////////////////////////////
Function GetExperts:TList;
Begin
Result:=LibExperts;
End;
{
╔═══════════════════════════════════════════════════════════════════════════╗
║ ║
║ Speed-Pascal/2 Version 2.0 ║
║ ║
║ Speed-Pascal Component Classes (SPCC) ║
║ ║
║ This section: TThread Class Implementation ║
║ ║
║ (C) 1995,97 SpeedSoft. All rights reserved. Disclosure probibited ! ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════╝
}
Procedure TThread.SetSuspended(NewValue:Boolean);
Begin
If NewValue Then Suspend
Else Resume;
End;
Const
{$IFDEF OS2}
PArray:Array[TThreadPriority] Of LongWord=
(PRTYC_IDLETIME,PRTYC_REGULAR,PRTYC_REGULAR,PRTYC_REGULAR,PRTYC_REGULAR,
PRTYC_REGULAR,PRTYC_TIMECRITICAL);
PDelta:Array[tpIdle..tpTimeCritical] Of LongWord=
(0,-31,-16,0,16,31,0);
{$ENDIF}
{$IFDEF Win95}
PArray:Array[TThreadPriority] Of LongWord=
(THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL,
THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL,THREAD_PRIORITY_HIGHEST,
THREAD_PRIORITY_TIME_CRITICAL);
{$ENDIF}
Procedure TThread.SetPriority(NewValue:TThreadPriority);
Begin
FPriority:=NewValue;
{$IFDEF OS2}
If ThreadId<>0 Then DosSetPriority(2,PArray[NewValue],PDelta[NewValue],ThreadId);
{$ENDIF}
{$IFDEF Win95}
SetThreadPriority(FHandle,PArray[NewValue]);
{$ENDIF}
End;
Procedure TThread.SyncTerminate;
Begin
FOnTerminate(Self);
End;
Procedure TThread.DoTerminate;
Begin
If FOnTerminate<>Nil Then Synchronize(SyncTerminate);
End;
Function ThreadLayer(Param:TThread):LongInt;
{$IFDEF OS2}
Var PAppHandle:LongWord;
PAppQueueHandle:LongWord;
{$ENDIF}
Var FreeTerm:Boolean;
Begin
{$IFDEF OS2}
Param.FThreadId:=System.GetThreadId;
If ApplicationType=1 Then
Begin
PAppHandle := WinInitializeAPI(0);
PAppQueueHandle := WinCreateMsgQueueAPI(PAppHandle,0);
End;
{$ENDIF}
Param.Priority:=Param.FPriority;
Param.Execute;
Result:=Param.ReturnValue;
FreeTerm:=Param.FreeOnTerminate;
Param.FFinished:=True;
Param.DoTerminate;
If FreeTerm Then Param.Destroy;
{$IFDEF OS2}
If ApplicationType=1 Then
Begin
WinDestroyMsgQueueAPI(PAppQueueHandle);
WinTerminateAPI(PAppHandle);
End;
{$ENDIF}
System.EndThread(Result);
End;
Const ThreadWindow:LongWord=0;
WM_EXECUTEPROC=WM_USER+1;
Var ThreadDefWndProc:Function(Win,Msg,para1,para2:LongWord):LongWord;APIENTRY;
MsgProc:Procedure;
ProcessProc:Procedure;
Procedure TThread.MsgIdle;
Begin
ProcessProc;
End;
Function ThreadWndProc(Win:LongWord;Msg,para1,para2:LongWord):LongWord;APIENTRY;
Var Thread:TThread;
Begin
If Msg=WM_EXECUTEPROC Then
Begin
Thread:=TThread(para1);
Thread.FMethod;
Result:=0;
End
Else
Begin
If @ThreadDefWndProc<>Nil Then Result:=ThreadDefWndProc(Win,Msg,para1,para2)
Else
Begin
{$IFDEF OS2}
Result:=WinDefWindowProc(Win,Msg,para1,para2);
{$ENDIF}
{$IFDEF Win95}
Result:=DefWindowProc(Win,Msg,para1,para2);
{$ENDIF}
End;
End;
End;
Constructor TThread.ExtCreate(CreateSuspended:Boolean;StackSize:LongWord;Priority:TThreadPriority;
Param:Pointer);
Var Options:LongWord;
Begin
If ((ApplicationType=1)And(ThreadWindow=0)) Then
Begin
ThreadDefWndProc:=Nil;
{$IFDEF OS2}
ThreadWindow:=WinCreateWCWindow(HWND_DESKTOP,
WC_BUTTON,
'',
0, //flStyle
0,0, //leave This ON 0 - Set by .Show
0,0, //Position And Size
HWND_DESKTOP, //parent
HWND_TOP, //Insert behind
1, //Window Id
Nil, //CtlData
Nil); //Presparams
ThreadDefWndProc:=Pointer(WinSubClassWindow(ThreadWindow,@ThreadWndProc));
{$ENDIF}
{$IFDEF Win95}
ThreadWindow:=CreateWindow('BUTTON',
'',
0,
0,0,
0,0,
HWND_DESKTOP,
1,
DllModule,
Nil);
ThreadDefWndProc:=Pointer(SetWindowLong(ThreadWindow,GWL_WNDPROC,LongInt(@ThreadWndProc)));
{$ENDIF}
End;
//Inherited Create;
FSuspended:=CreateSuspended;
Options:=0;
If FSuspended Then Options:=Options Or THREAD_SUSPENDED;
FPriority:=Priority;
FParameter:=Param;
FHandle:=BeginThread(Nil,StackSize,@ThreadLayer,Pointer(Self),Options,FThreadId);
End;
Constructor TThread.Create(CreateSuspended: Boolean);
Begin
TThread.ExtCreate(CreateSuspended,65535,tpNormal,Nil);
End;
Destructor TThread.Destroy;
Begin
If ((Not FFinished)And(Not FSuspended)) Then
Begin
Terminate;
WaitFor;
End
Else If FSuspended Then
Begin
FFreeOnTerminate:=False;
System.KillThread(FHandle);
End;
{$IFDEF Win95}
If FHandle<>0 Then CloseHandle(FHandle);
{$ENDIF}
Inherited Destroy;
End;
Function TThread.WaitFor:LongInt;
Var FreeIt:Boolean;
Begin
FreeIt:=FFreeOnTerminate;
FFreeOnTerminate:=False;
Repeat
If ((ApplicationType=1)And(MsgProc<>Nil)) Then MsgProc
Else Delay(50);
Until FFinished;
Result:=ReturnValue;
If FreeIt Then Self.Destroy;
End;
Procedure TThread.Terminate;
Begin
FTerminated:=True;
End;
Procedure TThread.Suspend;
Begin
FSuspended:=True;
{$IFDEF OS2}
DosSuspendThread(FHandle);
{$ENDIF}
{$IFDEF Win95}
SuspendThread(FHandle);
{$ENDIF}
End;
Procedure TThread.Resume;
Begin
{$IFDEF OS2}
If DosResumeThread(FHandle)=0 Then FSuspended:=False;
{$ENDIF}
{$IFDEF Win95}
If ResumeThread(FHandle) = 1 Then FSuspended:=False;
{$ENDIF}
End;
//nach Möglichkeit nicht benutzen (statt dessen Terminate !), "abwürgen" des Threads
//falls keine Möglichkeit zur Abfrage von "Terminated" besteht
Procedure TThread.Kill;
Var FreeTerm:Boolean;
Begin
Suspend;
System.KillThread(FHandle);
FreeTerm:=FreeOnTerminate;
FFinished:=True;
DoTerminate;
If FreeTerm Then Self.Destroy;
End;
Procedure TThread.ProcessMsgs;
Begin
If ProcessProc<>Nil Then Synchronize(MsgIdle);
End;
Procedure TThread.Synchronize(method:TThreadMethod);
Begin
//If @method<>@MsgIdle Then ProcessMsgs;
//MsgIdle;
If ThreadWindow<>0 Then
Begin
FMethod:=method;
{$IFDEF OS2}
WinSendMsg(ThreadWindow,WM_EXECUTEPROC,LongWord(Self),0);
{$ENDIF}
{$IFDEF Win95}
SendMessage(ThreadWindow,WM_EXECUTEPROC,LongWord(Self),0);
{$ENDIF}
End
Else method;
End;
{
╔═══════════════════════════════════════════════════════════════════════════╗
║ ║
║ Speed-Pascal/2 Version 2.0 ║
║ ║
║ Speed-Pascal Component Classes (SPCC) ║
║ ║
║ This section: TCollectionItem Class Implementation ║
║ ║
║ (C) 1995,97 SpeedSoft. All rights reserved. Disclosure probibited ! ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════╝
}
Function TCollectionItem.GetIndex:LongInt;
Begin
If FCollection=Nil Then Result:=-1
Else Result:=FCollection.FItems.IndexOf(Self);
End;
Procedure TCollectionItem.SetCollection(NewValue:TCollection);
Begin
If NewValue=FCollection Then Exit;
If FCollection<>Nil Then FCollection.RemoveItem(Self);
If NewValue<>Nil Then NewValue.InsertItem(Self);
End;
Procedure TCollectionItem.changed(AllItems:Boolean);
Begin
If FCollection<>Nil Then If FCollection.FUpdateCount=0 Then
Begin
If AllItems Then FCollection.Update(Nil)
Else FCollection.Update(Self);
End;
End;
Procedure TCollectionItem.SetIndex(NewIndex:LongInt);
Begin
If NewIndex=Index Then Exit
Else If Index>=0 Then
Begin
FCollection.FItems.Move(Index,NewIndex);
changed(True);
End;
End;
Constructor TCollectionItem.Create(ACollection: TCollection);
Begin
Inherited Create;
collection:=ACollection;
End;
Destructor TCollectionItem.Destroy;
Begin
collection:=Nil;
Inherited Destroy;
End;
{
╔═══════════════════════════════════════════════════════════════════════════╗
║ ║
║ Speed-Pascal/2 Version 2.0 ║
║ ║
║ Speed-Pascal Component Classes (SPCC) ║
║ ║
║ This section: TCollection Class Implementation ║
║ ║
║ (C) 1995,97 SpeedSoft. All rights reserved. Disclosure probibited ! ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════╝
}
Function TCollection.GetCount:LongInt;
Begin
Result:=FItems.Count;
End;
Procedure TCollection.InsertItem(Item:TCollectionItem);
Begin
If Not (Item Is FItemClass) Then Raise EListError.Create(LoadNLSStr(SCollectionErrorText))
Else
Begin
FItems.Add(Item);
Item.FCollection:=Self;
changed;
End;
End;
Procedure TCollection.RemoveItem(Item:TCollectionItem);
Begin
FItems.Remove(Item);
Item.FCollection:=Nil;
changed;
End;
Procedure TCollection.changed;
Begin
If FUpdateCount=0 Then Update(Nil);
End;
Function TCollection.GetItem(Index:LongInt):TCollectionItem;
Begin
Result:=TCollectionItem(FItems[Index]);
End;
Procedure TCollection.SetItem(Index:LongInt;Value:TCollectionItem);
Var dummy:TCollectionItem;
Begin
dummy:=TCollectionItem(FItems[Index]);
dummy.Assign(Value);
End;
{$HINTS OFF}
Procedure TCollection.Update(Item:TCollectionItem);
Begin
End;
{$HINTS ON}
Procedure TCollection.SetupComponent;
Begin
Inherited SetupComponent;
Name:='Collection';
FItemClass:=TCollectionItem;
FItems.Create;
Include(ComponentState,csDetail);
End;
Destructor TCollection.Destroy;
Begin
FUpdateCount:=1;
Clear;
FItems.Destroy;
Inherited Destroy;
End;
Function TCollection.Add:TCollectionItem;
Begin
Result:=FItemClass.Create(Self);
End;
Procedure TCollection.Assign(Source:TCollection);
Var dummy:TCollectionItem;
T:LongInt;
Begin
If ((Source=Nil)Or(Source=Self)) Then Exit;
BeginUpdate;
Try
Clear;
For T:=0 To Source.Count-1 Do
Begin
dummy:=Self.Add;
dummy.Assign(Source.Items[T]);
End;
Finally
EndUpdate;
End;
End;
Procedure TCollection.BeginUpdate;
Begin
Inc(FUpdateCount);
End;
Procedure TCollection.EndUpdate;
Begin
Dec(FUpdateCount);
changed;
End;
Procedure TCollection.Clear;
Var T:LongInt;
dummy:TCollectionItem;
Begin
If FItems.Count=0 Then Exit;
BeginUpdate;
Try
For T:=FItems.Count-1 DownTo 0 Do
Begin
dummy:=FItems[T];
dummy.Destroy;
End;
FItems.Clear;
Finally
EndUpdate;
End;
End;
Begin
LanguageMessages:=Nil;
AppLanguage:='Default';
MsgProc:=Nil;
ProcessProc:=Nil;
InsideCompLib:=False;
InsideWriteSCU:=False;
InsideWriteSCUAdr:=@InsideWriteSCU;
InsideDesigner:=False;
InsideLanguageDesigner:=False;
RegisteredClasses.Create;
PropertyEditDialogs.Create;
LibExperts.Create;
LibExpertInstances.Create;
End.