classes.inc 17 KB

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