classes.inc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785
  1. {
  2. $Id$
  3. This file is part of the Free Component Library (FCL)
  4. Copyright (c) 1999-2000 by Michael Van Canneyt and Florian Klaempfl
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {**********************************************************************
  12. * Class implementations are in separate files. *
  13. **********************************************************************}
  14. {
  15. Include all message strings
  16. Add a language with IFDEF LANG_NAME
  17. just befor the final ELSE. This way English will always be the default.
  18. }
  19. {$IFDEF LANG_GERMAN}
  20. {$i constsg.inc}
  21. {$ELSE}
  22. {$IFDEF LANG_SPANISH}
  23. {$i constss.inc}
  24. {$ELSE}
  25. {$i constse.inc}
  26. {$ENDIF}
  27. {$ENDIF}
  28. { Utility routines }
  29. {$i util.inc}
  30. { TBits implementation }
  31. {$i bits.inc}
  32. { TReader implementation }
  33. { $i reader.inc}
  34. { TWriter implementations }
  35. {$i writer.inc}
  36. {$i twriter.inc}
  37. { TFiler implementation }
  38. {$i filer.inc}
  39. { All streams implementations: }
  40. { Tstreams THandleStream TFileStream TResourcseStreams TStringStream }
  41. { TCustomMemoryStream TMemoryStream }
  42. {$i streams.inc}
  43. { TParser implementation}
  44. {$i parser.inc}
  45. { TCollection and TCollectionItem implementations }
  46. {$i collect.inc}
  47. { TList and TThreadList implementations }
  48. {$i lists.inc}
  49. { TStrings and TStringList implementations }
  50. {$i stringl.inc}
  51. { TThread implementation }
  52. {$i thread.inc}
  53. { TPersistent implementation }
  54. {$i persist.inc }
  55. { TComponent implementation }
  56. {$i compon.inc}
  57. { Class and component registration routines }
  58. {$I cregist.inc}
  59. {**********************************************************************
  60. * Miscellaneous procedures and functions *
  61. **********************************************************************}
  62. { Point and rectangle constructors }
  63. function Point(AX, AY: Integer): TPoint;
  64. begin
  65. with Result do
  66. begin
  67. X := AX;
  68. Y := AY;
  69. end;
  70. end;
  71. function SmallPoint(AX, AY: SmallInt): TSmallPoint;
  72. begin
  73. with Result do
  74. begin
  75. X := AX;
  76. Y := AY;
  77. end;
  78. end;
  79. function Rect(ALeft, ATop, ARight, ABottom: Integer): TRect;
  80. begin
  81. with Result do
  82. begin
  83. Left := ALeft;
  84. Top := ATop;
  85. Right := ARight;
  86. Bottom := ABottom;
  87. end;
  88. end;
  89. function Bounds(ALeft, ATop, AWidth, AHeight: Integer): TRect;
  90. begin
  91. with Result do
  92. begin
  93. Left := ALeft;
  94. Top := ATop;
  95. Right := ALeft + AWidth;
  96. Bottom := ATop + AHeight;
  97. end;
  98. end;
  99. { Object filing routines }
  100. procedure RegisterIntegerConsts(IntegerType: Pointer; IdentToInt: TIdentToInt;
  101. IntToIdent: TIntToIdent);
  102. begin
  103. end;
  104. function IdentToInt(const Ident: string; var Int: Longint; const Map: array of TIdentMapEntry): Boolean;
  105. begin
  106. IdentToInt:=false;
  107. end;
  108. function IntToIdent(Int: Longint; var Ident: string; const Map: array of TIdentMapEntry): Boolean;
  109. begin
  110. IntToIdent:=false;
  111. end;
  112. function InitInheritedComponent(Instance: TComponent; RootAncestor: TClass): Boolean;
  113. begin
  114. InitInheritedComponent:=false;
  115. end;
  116. function InitComponentRes(const ResName: string; Instance: TComponent): Boolean;
  117. begin
  118. InitComponentRes:=false;
  119. end;
  120. function ReadComponentRes(const ResName: string; Instance: TComponent): TComponent;
  121. begin
  122. ReadComponentRes:=nil;
  123. end;
  124. function ReadComponentResEx(HInstance: THandle; const ResName: string): TComponent;
  125. begin
  126. ReadComponentResEx:=nil;
  127. end;
  128. function ReadComponentResFile(const FileName: string; Instance: TComponent): TComponent;
  129. begin
  130. ReadComponentResFile:=nil;
  131. end;
  132. procedure WriteComponentResFile(const FileName: string; Instance: TComponent);
  133. begin
  134. end;
  135. procedure GlobalFixupReferences;
  136. begin
  137. end;
  138. procedure GetFixupReferenceNames(Root: TComponent; Names: TStrings);
  139. begin
  140. end;
  141. procedure GetFixupInstanceNames(Root: TComponent;
  142. const ReferenceRootName: string; Names: TStrings);
  143. begin
  144. end;
  145. procedure RedirectFixupReferences(Root: TComponent; const OldRootName,
  146. NewRootName: string);
  147. begin
  148. end;
  149. procedure RemoveFixupReferences(Root: TComponent; const RootName: string);
  150. begin
  151. end;
  152. procedure RemoveFixups(Instance: TPersistent);
  153. begin
  154. end;
  155. procedure BeginGlobalLoading;
  156. begin
  157. end;
  158. procedure NotifyGlobalLoading;
  159. begin
  160. end;
  161. procedure EndGlobalLoading;
  162. begin
  163. end;
  164. function CollectionsEqual(C1, C2: TCollection): Boolean;
  165. begin
  166. CollectionsEqual:=false;
  167. end;
  168. { Object conversion routines }
  169. procedure ObjectBinaryToText(Input, Output: TStream);
  170. procedure OutStr(s: String);
  171. begin
  172. if Length(s) > 0 then
  173. Output.Write(s[1], Length(s));
  174. end;
  175. procedure OutLn(s: String);
  176. begin
  177. OutStr(s + #10);
  178. end;
  179. procedure OutString(s: String);
  180. var
  181. res, NewStr: String;
  182. i: Integer;
  183. InString, NewInString: Boolean;
  184. begin
  185. res := '';
  186. InString := False;
  187. for i := 1 to Length(s) do begin
  188. NewInString := InString;
  189. case s[i] of
  190. #0..#31: begin
  191. if InString then
  192. NewInString := False;
  193. NewStr := '#' + IntToStr(Ord(s[i]));
  194. end;
  195. '''':
  196. if InString then NewStr := ''''''
  197. else NewStr := '''''''';
  198. else begin
  199. if not InString then
  200. NewInString := True;
  201. NewStr := s[i];
  202. end;
  203. end;
  204. if NewInString <> InString then begin
  205. NewStr := '''' + NewStr;
  206. InString := NewInString;
  207. end;
  208. res := res + NewStr;
  209. end;
  210. if InString then res := res + '''';
  211. OutStr(res);
  212. end;
  213. function ReadInt(ValueType: TValueType): LongInt;
  214. begin
  215. case ValueType of
  216. vaInt8: Result := ShortInt(Input.ReadByte);
  217. vaInt16: Result := SmallInt(Input.ReadWord);
  218. vaInt32: Result := LongInt(Input.ReadDWord);
  219. end;
  220. end;
  221. function ReadInt: LongInt;
  222. begin
  223. Result := ReadInt(TValueType(Input.ReadByte));
  224. end;
  225. function ReadSStr: String;
  226. var
  227. len: Byte;
  228. begin
  229. len := Input.ReadByte;
  230. SetLength(Result, len);
  231. Input.Read(Result[1], len);
  232. end;
  233. procedure ReadPropList(indent: String);
  234. procedure ProcessValue(ValueType: TValueType; Indent: String);
  235. procedure Stop(s: String);
  236. begin
  237. WriteLn(s);
  238. Halt;
  239. end;
  240. procedure ProcessBinary;
  241. var
  242. ToDo, DoNow, i: LongInt;
  243. lbuf: array[0..31] of Byte;
  244. s: String;
  245. begin
  246. ToDo := Input.ReadDWord;
  247. OutLn('{');
  248. while ToDo > 0 do begin
  249. DoNow := ToDo;
  250. if DoNow > 32 then DoNow := 32;
  251. Dec(ToDo, DoNow);
  252. s := Indent + ' ';
  253. Input.Read(lbuf, DoNow);
  254. for i := 0 to DoNow - 1 do
  255. s := s + IntToHex(lbuf[i], 2);
  256. OutLn(s);
  257. end;
  258. OutLn(indent + '}');
  259. end;
  260. var
  261. s: String;
  262. len: LongInt;
  263. IsFirst: Boolean;
  264. ext: Extended;
  265. begin
  266. OutStr('(' + IntToStr(Ord(Valuetype)) + ') ');
  267. case ValueType of
  268. vaList: begin
  269. OutStr('(');
  270. IsFirst := True;
  271. while True do begin
  272. ValueType := TValueType(Input.ReadByte);
  273. if ValueType = vaNull then break;
  274. if IsFirst then begin
  275. OutLn('');
  276. IsFirst := False;
  277. end;
  278. OutStr(Indent + ' ');
  279. ProcessValue(ValueType, Indent + ' ');
  280. end;
  281. OutLn(Indent + ')');
  282. end;
  283. vaInt8: OutLn(IntToStr(ShortInt(Input.ReadByte)));
  284. vaInt16: OutLn( IntToStr(SmallInt(Input.ReadWord)));
  285. vaInt32: OutLn(IntToStr(LongInt(Input.ReadDWord)));
  286. vaExtended: begin
  287. Input.Read(ext, SizeOf(ext));
  288. OutLn(FloatToStr(ext));
  289. end;
  290. vaString: begin
  291. OutString(ReadSStr);
  292. OutLn('');
  293. end;
  294. vaIdent: OutLn(ReadSStr);
  295. vaFalse: OutLn('False');
  296. vaTrue: OutLn('True');
  297. vaBinary: ProcessBinary;
  298. vaSet: begin
  299. OutStr('[');
  300. IsFirst := True;
  301. while True do begin
  302. s := ReadSStr;
  303. if Length(s) = 0 then break;
  304. if not IsFirst then OutStr(', ');
  305. IsFirst := False;
  306. OutStr(s);
  307. end;
  308. OutLn(']');
  309. end;
  310. vaLString: Stop('!!LString!!');
  311. vaNil: Stop('nil');
  312. vaCollection: begin
  313. OutStr('<');
  314. while Input.ReadByte <> 0 do begin
  315. OutLn(Indent);
  316. Input.Seek(-1, soFromCurrent);
  317. OutStr(indent + ' item');
  318. ValueType := TValueType(Input.ReadByte);
  319. if ValueType <> vaList then
  320. OutStr('[' + IntToStr(ReadInt(ValueType)) + ']');
  321. OutLn('');
  322. ReadPropList(indent + ' ');
  323. OutStr(indent + ' end');
  324. end;
  325. OutLn('>');
  326. end;
  327. {vaSingle: begin OutLn('!!Single!!'); exit end;
  328. vaCurrency: begin OutLn('!!Currency!!'); exit end;
  329. vaDate: begin OutLn('!!Date!!'); exit end;
  330. vaWString: begin OutLn('!!WString!!'); exit end;}
  331. else
  332. Stop(IntToStr(Ord(ValueType)));
  333. end;
  334. end;
  335. begin
  336. while Input.ReadByte <> 0 do begin
  337. Input.Seek(-1, soFromCurrent);
  338. OutStr(indent + ReadSStr + ' = ');
  339. ProcessValue(TValueType(Input.ReadByte), Indent);
  340. end;
  341. end;
  342. procedure ReadObject(indent: String);
  343. var
  344. b: Byte;
  345. ObjClassName, ObjName: String;
  346. ChildPos: LongInt;
  347. begin
  348. // Check for FilerFlags
  349. b := Input.ReadByte;
  350. if (b and $f0) = $f0 then begin
  351. if (b and 2) <> 0 then ChildPos := ReadInt;
  352. end else begin
  353. b := 0;
  354. Input.Seek(-1, soFromCurrent);
  355. end;
  356. ObjClassName := ReadSStr;
  357. ObjName := ReadSStr;
  358. OutStr(Indent);
  359. if (b and 1) <> 0 then OutStr('inherited')
  360. else OutStr('object');
  361. OutStr(' ');
  362. if ObjName <> '' then
  363. OutStr(ObjName + ': ');
  364. OutStr(ObjClassName);
  365. if (b and 2) <> 0 then OutStr('[' + IntToStr(ChildPos) + ']');
  366. OutLn('');
  367. ReadPropList(indent + ' ');
  368. while Input.ReadByte <> 0 do begin
  369. Input.Seek(-1, soFromCurrent);
  370. ReadObject(indent + ' ');
  371. end;
  372. OutLn(indent + 'end');
  373. end;
  374. type
  375. PLongWord = ^LongWord;
  376. const
  377. signature: PChar = 'TPF0';
  378. begin
  379. if Input.ReadDWord <> PLongWord(Pointer(signature))^ then
  380. raise EReadError.Create('Illegal stream image' {###SInvalidImage});
  381. ReadObject('');
  382. end;
  383. procedure ObjectTextToBinary(Input, Output: TStream);
  384. var
  385. parser: TParser;
  386. procedure WriteString(s: String);
  387. begin
  388. Output.WriteByte(Length(s));
  389. Output.Write(s[1], Length(s));
  390. end;
  391. procedure WriteInteger(value: LongInt);
  392. begin
  393. if (value >= -128) and (value <= 127) then begin
  394. Output.WriteByte(Ord(vaInt8));
  395. Output.WriteByte(Byte(value));
  396. end else if (value >= -32768) and (value <= 32767) then begin
  397. Output.WriteByte(Ord(vaInt16));
  398. Output.WriteWord(Word(value));
  399. end else begin
  400. Output.WriteByte(ord(vaInt32));
  401. Output.WriteDWord(LongWord(value));
  402. end;
  403. end;
  404. procedure ProcessProperty; forward;
  405. procedure ProcessValue;
  406. var
  407. flt: Extended;
  408. s: String;
  409. stream: TMemoryStream;
  410. begin
  411. case parser.Token of
  412. toInteger: WriteInteger(parser.TokenInt);
  413. toFloat: begin
  414. Output.WriteByte(Ord(vaExtended));
  415. flt := Parser.TokenFloat;
  416. Output.Write(flt, SizeOf(flt));
  417. end;
  418. toString: begin
  419. s := parser.TokenString;
  420. while parser.NextToken = '+' do begin
  421. parser.NextToken; // Get next string fragment
  422. parser.CheckToken(toString);
  423. s := s + parser.TokenString;
  424. end;
  425. Output.WriteByte(Ord(vaString));
  426. WriteString(s);
  427. end;
  428. toSymbol:
  429. if CompareText(parser.TokenString, 'True') = 0 then
  430. Output.WriteByte(Ord(vaTrue))
  431. else if CompareText(parser.TokenString, 'False') = 0 then
  432. Output.WriteByte(Ord(vaFalse))
  433. else if CompareText(parser.TokenString, 'nil') = 0 then
  434. Output.WriteByte(Ord(vaNil))
  435. else begin
  436. Output.WriteByte(Ord(vaIdent));
  437. WriteString(parser.TokenString);
  438. end;
  439. // Set
  440. '[': begin
  441. parser.NextToken;
  442. Output.WriteByte(Ord(vaSet));
  443. if parser.Token <> ']' then
  444. while True do begin
  445. parser.CheckToken(toSymbol);
  446. WriteString(parser.TokenString);
  447. parser.NextToken;
  448. if parser.Token = ']' then break;
  449. parser.CheckToken(',');
  450. parser.NextToken;
  451. end;
  452. Output.WriteByte(0);
  453. end;
  454. // List
  455. '(': begin
  456. parser.NextToken;
  457. Output.WriteByte(Ord(vaList));
  458. while parser.Token <> ')' do ProcessValue;
  459. Output.WriteByte(0);
  460. end;
  461. // Collection
  462. '<': begin
  463. parser.NextToken;
  464. Output.WriteByte(Ord(vaCollection));
  465. while parser.Token <> '>' do begin
  466. parser.CheckTokenSymbol('item');
  467. parser.NextToken;
  468. // ConvertOrder
  469. Output.WriteByte(Ord(vaList));
  470. while not parser.TokenSymbolIs('end') do ProcessProperty;
  471. parser.NextToken; // Skip 'end'
  472. Output.WriteByte(0);
  473. end;
  474. Output.WriteByte(0);
  475. end;
  476. // Binary data
  477. '{': begin
  478. Output.WriteByte(Ord(vaBinary));
  479. stream := TMemoryStream.Create;
  480. try
  481. parser.HexToBinary(stream);
  482. Output.WriteDWord(stream.Size);
  483. Output.Write(Stream.Memory^, stream.Size);
  484. finally
  485. stream.Free;
  486. end;
  487. end;
  488. else WriteLn('Token: "', parser.Token, '" ', Ord(parser.Token));
  489. end;
  490. parser.NextToken;
  491. end;
  492. procedure ProcessProperty;
  493. var
  494. name: String;
  495. begin
  496. // Get name of property
  497. parser.CheckToken(toSymbol);
  498. name := parser.TokenString;
  499. while True do begin
  500. parser.NextToken;
  501. if parser.Token <> '.' then break;
  502. parser.NextToken;
  503. parser.CheckToken(toSymbol);
  504. name := name + '.' + parser.TokenString;
  505. end;
  506. // WriteLn(name);
  507. WriteString(name);
  508. parser.CheckToken('=');
  509. parser.NextToken;
  510. ProcessValue;
  511. end;
  512. procedure ProcessObject;
  513. var
  514. IsInherited: Boolean;
  515. ObjectName, ObjectType: String;
  516. begin
  517. if parser.TokenSymbolIs('OBJECT') then
  518. IsInherited := False
  519. else begin
  520. parser.CheckTokenSymbol('INHERITED');
  521. IsInherited := True;
  522. end;
  523. parser.NextToken;
  524. parser.CheckToken(toSymbol);
  525. ObjectName := '';
  526. ObjectType := parser.TokenString;
  527. parser.NextToken;
  528. if parser.Token = ':' then begin
  529. parser.NextToken;
  530. parser.CheckToken(toSymbol);
  531. ObjectName := ObjectType;
  532. ObjectType := parser.TokenString;
  533. parser.NextToken;
  534. end;
  535. WriteString(ObjectType);
  536. WriteString(ObjectName);
  537. // Convert property list
  538. while not (parser.TokenSymbolIs('END') or
  539. parser.TokenSymbolIs('OBJECT') or
  540. parser.TokenSymbolIs('INHERITED')) do
  541. ProcessProperty;
  542. Output.WriteByte(0); // Terminate property list
  543. // Convert child objects
  544. while not parser.TokenSymbolIs('END') do ProcessObject;
  545. parser.NextToken; // Skip end token
  546. Output.WriteByte(0); // Terminate property list
  547. end;
  548. const
  549. signature: PChar = 'TPF0';
  550. begin
  551. parser := TParser.Create(Input);
  552. try
  553. Output.Write(signature[0], 4);
  554. ProcessObject;
  555. finally
  556. parser.Free;
  557. end;
  558. end;
  559. procedure ObjectResourceToText(Input, Output: TStream);
  560. begin
  561. Input.ReadResHeader;
  562. ObjectBinaryToText(Input, Output);
  563. end;
  564. procedure ObjectTextToResource(Input, Output: TStream);
  565. var
  566. StartPos, SizeStartPos, BinSize: LongInt;
  567. parser: TParser;
  568. name: String;
  569. begin
  570. // Get form type name
  571. StartPos := Input.Position;
  572. parser := TParser.Create(Input);
  573. try
  574. if not parser.TokenSymbolIs('OBJECT') then parser.CheckTokenSymbol('INHERITED');
  575. parser.NextToken;
  576. parser.CheckToken(toSymbol);
  577. parser.NextToken;
  578. parser.CheckToken(':');
  579. parser.NextToken;
  580. parser.CheckToken(toSymbol);
  581. name := parser.TokenString;
  582. finally
  583. parser.Free;
  584. Input.Position := StartPos;
  585. end;
  586. // Write resource header
  587. name := UpperCase(name);
  588. Output.WriteByte($ff);
  589. Output.WriteByte(10);
  590. Output.WriteByte(0);
  591. Output.Write(name[1], Length(name) + 1); // Write null-terminated form type name
  592. Output.WriteWord($1030);
  593. SizeStartPos := Output.Position;
  594. Output.WriteDWord(0); // Placeholder for data size
  595. ObjectTextToBinary(Input, Output); // Convert the stuff!
  596. BinSize := Output.Position - SizeStartPos - 4;
  597. Output.Position := SizeStartPos;
  598. Output.WriteDWord(BinSize); // Insert real resource data size
  599. end;
  600. { Utility routines }
  601. function LineStart(Buffer, BufPos: PChar): PChar;
  602. begin
  603. Result := BufPos;
  604. while Result > Buffer do begin
  605. Dec(Result);
  606. if Result[0] = #10 then break;
  607. end;
  608. end;
  609. {
  610. $Log$
  611. Revision 1.16 2000-01-07 01:24:33 peter
  612. * updated copyright to 2000
  613. Revision 1.15 2000/01/06 01:20:32 peter
  614. * moved out of packages/ back to topdir
  615. Revision 1.2 2000/01/04 18:07:16 michael
  616. + Streaming implemented
  617. Revision 1.1 2000/01/03 19:33:06 peter
  618. * moved to packages dir
  619. Revision 1.13 1999/10/19 11:27:03 sg
  620. * Added DFM<->ASCII conversion procedures
  621. Revision 1.12 1999/09/30 19:31:42 fcl
  622. * Implemented LineStart (sg)
  623. Revision 1.11 1999/09/11 21:59:31 fcl
  624. * Moved class and registration functions to cregist.inc (sg)
  625. Revision 1.10 1999/04/13 08:52:29 michael
  626. + Moved strings.inc to stringl.inc, to avoid conflict with strings unit
  627. Revision 1.9 1999/04/08 10:18:50 peter
  628. * makefile updates
  629. }