paradox.pp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959
  1. {
  2. This file is part of the Free Component Library (FCL)
  3. Copyright (c) 1999-2007 by the Free Pascal development team
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. {$mode objfpc}
  11. {$H+}
  12. {
  13. TParadox : Dataset wich can handle paradox files, based on PXLib.
  14. }
  15. unit paradox;
  16. interface
  17. uses
  18. sysutils, classes, db, pxlib, bufdataset_parser;
  19. type
  20. EParadox=class(Exception);
  21. { TParadox }
  22. TParadox = Class(TDataSet)
  23. private
  24. FBlobFileName: String;
  25. FFileName : String;
  26. FPXLibrary : String;
  27. FCurrRecNo : Integer;
  28. FDoc : PPX_Doc;
  29. FFilterBuffer : PChar;
  30. FOffsets : PInteger;
  31. FTableName : String;
  32. FInputEncoding : String;
  33. FTargetEncoding : String;
  34. FParser : TBufDatasetParser;
  35. function GetInputEncoding: String;
  36. function GetTableName: String;
  37. function GetTargetEncoding: String;
  38. procedure OpenBlobFile;
  39. procedure PXAppendRecord(Buffer: Pointer);
  40. function PXFilterRecord(Buffer: PChar): Boolean;
  41. function PXGetActiveBuffer(var Buffer: PChar): Boolean;
  42. procedure RaiseError(Fmt: String; Args: array of const);
  43. procedure SetBlobFileName(const AValue: String);
  44. procedure SetFileName(const AValue: String);
  45. procedure SetInputEncoding(const AValue: String);
  46. procedure SetOpenParams;
  47. procedure SetTableName(const AValue: String);
  48. procedure SetTargetEncoding(const AValue: String);
  49. function GetLibStored : Boolean;
  50. protected
  51. // Mandatory
  52. procedure SetFilterText(const Value: String); override; {virtual;}
  53. procedure SetFiltered(Value: Boolean); override; {virtual;}
  54. procedure ParseFilter(const AFilter: string);
  55. function AllocRecordBuffer: PChar; override;
  56. procedure FreeRecordBuffer(var Buffer: PChar); override;
  57. procedure GetBookmarkData(Buffer: PChar; Data: Pointer); override;
  58. function GetBookmarkFlag(Buffer: PChar): TBookmarkFlag; override;
  59. function GetFieldData(Field: TField; Buffer: Pointer): Boolean; override;
  60. function GetRecord(Buffer: PChar; GetMode: TGetMode; DoCheck: Boolean): TGetResult; override;
  61. function GetRecordSize: Word; override;
  62. procedure InternalAddRecord(Buffer: Pointer; DoAppend: Boolean); override;
  63. procedure InternalClose; override;
  64. procedure InternalDelete; override;
  65. procedure InternalFirst; override;
  66. procedure InternalGotoBookmark(ABookmark: Pointer); override;
  67. procedure InternalInitFieldDefs; override;
  68. procedure InternalInitRecord(Buffer: PChar); override;
  69. procedure InternalLast; override;
  70. procedure InternalOpen; override;
  71. procedure InternalPost; override;
  72. procedure InternalSetToRecord(Buffer: PChar); override;
  73. function IsCursorOpen: Boolean; override;
  74. procedure SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag); override;
  75. procedure SetBookmarkData(Buffer: PChar; Data: Pointer); override;
  76. procedure SetFieldData(Field: TField; Buffer: Pointer); override;
  77. procedure DataConvert(aField: TField; aSource, aDest: Pointer; aToNative: Boolean); override;
  78. function CreateBlobStream(Field: TField; Mode: TBlobStreamMode): TStream; override;
  79. // Optional.
  80. function GetRecordCount: Integer; override;
  81. procedure SetRecNo(Value: Integer); override;
  82. function GetRecNo: Integer; override;
  83. // Exposed properties/procedures
  84. Function GetParam(Const ParamName : String) : String;
  85. Procedure SetParam(Const ParamName,ParamValue : String);
  86. property Doc : PPX_Doc Read FDoc;
  87. public
  88. constructor Create(AOwner:tComponent); override;
  89. destructor Destroy; override;
  90. published
  91. Property PXLibrary : String Read FPXLibrary Write FPXLibrary Stored GetLibStored;
  92. Property FileName : String Read FFileName Write SetFileName;
  93. Property BlobFileName : String Read FBlobFileName Write SetBlobFileName;
  94. Property TableName : String Read GetTableName Write SetTableName;
  95. Property TargetEncoding : String Read GetTargetEncoding Write SetTargetEncoding;
  96. Property InputEncoding : String Read GetInputEncoding Write SetInputEncoding;
  97. property filter;
  98. property Filtered;
  99. Property Active;
  100. Property FieldDefs;
  101. property BeforeOpen;
  102. property AfterOpen;
  103. property BeforeClose;
  104. property AfterClose;
  105. property BeforeInsert;
  106. property AfterInsert;
  107. property BeforeEdit;
  108. property AfterEdit;
  109. property BeforePost;
  110. property AfterPost;
  111. property BeforeCancel;
  112. property AfterCancel;
  113. property BeforeDelete;
  114. property AfterDelete;
  115. property BeforeScroll;
  116. property AfterScroll;
  117. property OnDeleteError;
  118. property OnEditError;
  119. property OnNewRecord;
  120. property OnPostError;
  121. property OnFilterRecord;
  122. end;
  123. // in front of graphic data
  124. TGraphicHeader = packed record
  125. Count: Word; { Always 1 }
  126. HType: Word; { Always $0100 }
  127. Size: Longint; { Size of actual data }
  128. end;
  129. Function PXFieldTypeToFieldType(PXFieldType : Integer) : TFieldType;
  130. Const
  131. SParamInputencoding = 'inputencoding';
  132. SParamTargetencoding = 'targetencoding';
  133. SParamTableName = 'tablename';
  134. implementation
  135. uses ctypes;
  136. ResourceString
  137. SErrFieldTypeNotSupported = 'Fieldtype of Field "%s" not supported: %d.';
  138. SErrBookMarkNotFound = 'Bookmark %d not found.';
  139. SErrNoFileName = 'Filename must not be empty.';
  140. SErrNoBlobFile = 'Blob file "%s" does not exist';
  141. SErrInvalidBlobFile = 'Blob file "%s" is invalid';
  142. SErrFailedToOpenFile = 'Failed to open file "%s" as a paradox file.';
  143. SErrParadoxNotOpen = 'Paradox file not opened';
  144. SErrGetParamFailed = 'Get of parameter %s failed.';
  145. SErrSetParamFailed = 'Set of parameter %s failed.';
  146. Const
  147. PXFieldTypes : Array[1..pxfNumTypes] of TFieldType
  148. = (ftString, ftDate, ftSmallInt, ftInteger,
  149. ftCurrency, ftFloat, ftUnknown { $07},ftunknown { $08},
  150. ftBoolean,ftUnknown { $0A}, ftunknown { $0B}, ftMemo,
  151. ftBlob, ftFmtMemo, ftParadoxOle, ftGraphic,
  152. ftUnknown { $11}, ftUnknown { $12}, ftUnknown { $13}, ftTime,
  153. ftDateTime, ftAutoinc, ftBCD, ftBytes);
  154. {
  155. Buffer layout :
  156. Bookmark : Record number
  157. BookmarkFlag : Flag
  158. Data : Actual data
  159. }
  160. Type
  161. PPXRecInfo = ^TPXRecInfo;
  162. TPXRecInfo = packed record
  163. Bookmark: Longint;
  164. BookmarkFlag: TBookmarkFlag;
  165. end;
  166. PDateTime = ^TDateTime;
  167. Const
  168. DataOffSet = SizeOf(TPXRecInfo);
  169. { ---------------------------------------------------------------------
  170. Utility functions
  171. ---------------------------------------------------------------------}
  172. Function PXFieldTypeToFieldType(PXFieldType : Integer) : TFieldType;
  173. begin
  174. if (PXFieldType<1) or (PXFieldType>pxfNumTypes) then
  175. Result:=ftUnknown
  176. else
  177. Result:=PXFieldTypes[PXFieldType];
  178. end;
  179. Var
  180. PXLibRefcount : Integer = 0;
  181. Procedure UninitPXLib;
  182. begin
  183. If (PXLibRefCount>0) then
  184. begin
  185. Dec(PXLibRefCount);
  186. If (PXLibRefCount=0) then
  187. begin
  188. PX_ShutDown();
  189. FreePXLib;
  190. end;
  191. end;
  192. end;
  193. Procedure InitPXLib(LibName : String);
  194. begin
  195. If (PXLibRefCount=0) then
  196. begin
  197. LoadPXLib(LibName);
  198. PX_Boot();
  199. end;
  200. Inc(PXLibRefCount);
  201. end;
  202. { ---------------------------------------------------------------------
  203. TParadox
  204. ---------------------------------------------------------------------}
  205. constructor TParadox.Create(AOwner:tComponent);
  206. begin
  207. inherited create(aOwner);
  208. FPXLibrary:=pxlibraryname;
  209. end;
  210. Destructor TParadox.Destroy;
  211. begin
  212. Close;
  213. UnInitPXLib;
  214. inherited Destroy;
  215. end;
  216. Procedure TParadox.RaiseError(Fmt : String; Args : Array of const);
  217. begin
  218. Raise EParadox.CreateFmt(Fmt,Args);
  219. end;
  220. Function TParadox.GetLibStored : boolean;
  221. begin
  222. Result:=(FPXLibrary<>pxlibraryname);
  223. end;
  224. procedure TParadox.SetBlobFileName(const AValue: String);
  225. begin
  226. if (FBlobFileName=AValue) then
  227. exit;
  228. CheckInactive;
  229. FBlobFileName:=AValue;
  230. end;
  231. function TParadox.PXFilterRecord(Buffer: PChar): Boolean;
  232. var
  233. SaveState: TDatasetState;
  234. begin
  235. Result:=True;
  236. if not Assigned(OnFilterRecord) and Not Filtered then
  237. Exit;
  238. SaveState:=SetTempState(dsFilter);
  239. Try
  240. FFilterBuffer:=Buffer;
  241. If Assigned(OnFilterRecord) then
  242. OnFilterRecord(Self,Result);
  243. If Result and Filtered and (Filter<>'') then
  244. Result:=Boolean((FParser.ExtractFromBuffer(FFilterBuffer))^);
  245. Finally
  246. RestoreState(SaveState);
  247. end;
  248. end;
  249. {
  250. procedure TParadox.MDSReadRecord(Buffer:PChar;ARecNo:Integer); //Reads a Rec from Stream in Buffer
  251. begin
  252. FStream.Position:=MDSGetRecordOffset(ARecNo);
  253. FStream.ReadBuffer(Buffer^, FRecSize);
  254. end;
  255. procedure TParadox.MDSWriteRecord(Buffer:PChar;ARecNo:Integer); //Writes a Rec from Buffer to Stream
  256. begin
  257. FStream.Position:=MDSGetRecordOffset(ARecNo);
  258. FStream.WriteBuffer(Buffer^, FRecSize);
  259. FFileModified:=True;
  260. end;
  261. procedure TParadox.MDSAppendRecord(Buffer:PChar); //Appends a Rec (from Buffer) to Stream
  262. begin
  263. FStream.Position:=MDSGetRecordOffset(FRecCount);
  264. FStream.WriteBuffer(Buffer^, FRecSize);
  265. FFileModified:=True;
  266. end;
  267. }
  268. function TParadox.PXGetActiveBuffer(var Buffer: PChar): Boolean;
  269. begin
  270. case State of
  271. dsBrowse:
  272. if IsEmpty then
  273. Buffer:=nil
  274. else
  275. Buffer:=ActiveBuffer;
  276. dsEdit,
  277. dsInsert:
  278. Buffer:=ActiveBuffer;
  279. dsFilter:
  280. Buffer:=FFilterBuffer;
  281. else
  282. Buffer:=nil;
  283. end;
  284. Result:=(Buffer<>nil);
  285. end;
  286. procedure TParadox.SetFileName(const AValue: String);
  287. begin
  288. CheckInactive;
  289. FFileName:=AValue;
  290. end;
  291. procedure TParadox.SetInputEncoding(const AValue: String);
  292. begin
  293. If Assigned(FDoc) then
  294. SetParam(SParamInputencoding,AVAlue);
  295. FInputEncoding:=AValue;
  296. end;
  297. procedure TParadox.SetTableName(const AValue: String);
  298. begin
  299. If Assigned(FDoc) then
  300. SetParam(SParamTableName,AVAlue);
  301. FTableName:=AValue;
  302. end;
  303. procedure TParadox.SetTargetEncoding(const AValue: String);
  304. begin
  305. If Assigned(FDoc) then
  306. SetParam(SParamTargetEncoding,AVAlue);
  307. FTargetEncoding:=AValue;
  308. end;
  309. procedure TParadox.SetFilterText(const Value: String);
  310. begin
  311. if (Value<>Filter) then
  312. begin
  313. ParseFilter(Value);
  314. inherited;
  315. if IsCursorOpen and Filtered then
  316. Refresh;
  317. end;
  318. end;
  319. procedure TParadox.SetFiltered(Value: Boolean);
  320. begin
  321. if (Value<>Filtered) then
  322. begin
  323. inherited;
  324. if IsCursorOpen then
  325. Refresh;
  326. end;
  327. end;
  328. //Abstract Overrides
  329. function TParadox.AllocRecordBuffer: PChar;
  330. begin
  331. Result:=Nil;
  332. GetMem(Result,SizeOf(TPXRecInfo)+GetRecordSize);
  333. end;
  334. procedure TParadox.FreeRecordBuffer (var Buffer: PChar);
  335. begin
  336. FreeMem(Buffer);
  337. end;
  338. procedure TParadox.InternalInitRecord(Buffer: PChar);
  339. begin
  340. fillchar((Buffer+DataOffSet)^,GetRecordSize,0);
  341. end;
  342. procedure TParadox.InternalDelete;
  343. begin
  344. If (FCurrRecNo<>-1) then
  345. PX_delete_record(FDoc,FCurrRecNo);
  346. end;
  347. procedure TParadox.InternalInitFieldDefs;
  348. Var
  349. I, CurrOffSet, ACount : Integer;
  350. FN : String;
  351. FS : Integer;
  352. B : Boolean;
  353. FT : TFieldType;
  354. pxf : Ppxfield_t;
  355. begin
  356. pxf:=PX_get_fields(FDoc);
  357. ACount:= PX_get_num_fields(FDoc);
  358. ReallocMem(FOffsets,ACount*SizeOf(Integer));
  359. FillChar(FOffSets^,ACount*SizeOf(Integer),0);
  360. CurrOffSet:=DataOffset;
  361. For I:=0 to ACount-1 do
  362. begin
  363. FOffsets[I]:=CurrOffset;
  364. FN:=strpas(pxf^.px_fname);
  365. FT:=PXFieldTypeToFieldType(pxf^.px_ftype);
  366. If (FT=ftUnKnown) then
  367. RaiseError(SErrFieldTypeNotSupported,[FN,pxf^.px_ftype]);
  368. If (FT in [ftString,ftBlob,ftMemo,ftFmtMemo,ftGraphic,ftParadoxOle,ftBytes]) then
  369. FS:=pxf^.px_flen
  370. else if (Ft=ftBCD) then
  371. FS:=pxf^.px_fdc
  372. else
  373. FS:=0;
  374. B:=False; // No way to detect required paradox fields ?
  375. FieldDefs.Add(FN,ft,FS,B);
  376. Inc(CurrOffset,pxf^.px_flen);
  377. Inc(pxf);
  378. end;
  379. end;
  380. procedure TParadox.InternalFirst;
  381. begin
  382. FCurrRecNo:=-1;
  383. end;
  384. procedure TParadox.InternalLast;
  385. begin
  386. FCurrRecNo:=PX_Get_num_records(FDoc);
  387. end;
  388. procedure TParadox.SetOpenParams;
  389. begin
  390. If (FTargetEncoding<>'') then
  391. SetParam(SParamTargetEncoding,FTargetEncoding);
  392. If (FInputEncoding<>'') then
  393. SetParam(SParamInputEncoding,FInputEncoding);
  394. end;
  395. procedure TParadox.OpenBlobFile;
  396. Var
  397. BFN : string;
  398. begin
  399. BFN:=FBlobFileName;
  400. If (BFN<>'') then
  401. if not FileExists(BFN) then
  402. RaiseError(SErrNoBlobFile,[BFN]);
  403. If (BFN='') then
  404. begin
  405. BFN:=ChangeFileExt(FFileName,'.mb');
  406. If Not FileExists(BFN) then
  407. begin
  408. BFN:=ChangeFileExt(FFileName,'.MB');
  409. If Not FileExists(BFN) then
  410. BFN:='';
  411. end;
  412. end;
  413. If (BFN<>'') then
  414. begin
  415. Writeln('opening blib file',bfn);
  416. if PX_set_blob_file(FDoc,PChar(BFN))<>0 then
  417. RaiseError(SErrInvalidBlobFile,[BFN]);
  418. FBlobFileName:=BFN;
  419. end;
  420. end;
  421. procedure TParadox.InternalOpen;
  422. Var
  423. FN : String;
  424. begin
  425. InitPXLib(FPXLibrary);
  426. If (FFileName='') then
  427. RaiseError(SErrNoFileName,[]);
  428. FN:=FFileName;
  429. FDoc:=PX_New();
  430. try
  431. If (px_open_file(FDoc,PChar(FN))<>0) then
  432. RaiseError(SErrFailedToOpenFile,[FN]);
  433. SetOpenParams;
  434. OpenBlobFile;
  435. InternalInitFieldDefs;
  436. if DefaultFields then
  437. CreateFields;
  438. BindFields(True);
  439. FCurrRecNo:=-1;
  440. except
  441. If Assigned(FDoc) then
  442. begin
  443. PX_Delete(FDoc);
  444. FDoc:=Nil;
  445. end;
  446. Raise;
  447. end;
  448. try
  449. ParseFilter(Filter);
  450. except
  451. On E : Exception do
  452. Filter:='';
  453. end;
  454. end;
  455. procedure TParadox.ParseFilter(const AFilter: string);
  456. begin
  457. // parser created?
  458. if Length(AFilter) > 0 then
  459. begin
  460. if (FParser = nil) and IsCursorOpen then
  461. begin
  462. FParser := TBufDatasetParser.Create(Self);
  463. end;
  464. // have a parser now?
  465. if FParser <> nil then
  466. begin
  467. // set options
  468. FParser.PartialMatch := not (foNoPartialCompare in FilterOptions);
  469. FParser.CaseInsensitive := foCaseInsensitive in FilterOptions;
  470. // parse expression
  471. FParser.ParseExpression(AFilter);
  472. end;
  473. end;
  474. end;
  475. procedure TParadox.InternalClose;
  476. begin
  477. FreeAndNil(FParser);
  478. FreeMem(FOffsets);
  479. FOffSets:=Nil;
  480. FCurrRecNo:=-1;
  481. If Assigned(FDoc) then
  482. begin
  483. PX_close(FDoc);
  484. PX_Delete(FDOc);
  485. end;
  486. FDoc:=Nil;
  487. end;
  488. procedure TParadox.InternalPost;
  489. begin
  490. CheckActive;
  491. if ((State<>dsEdit) and (State<>dsInsert)) then
  492. Exit;
  493. if (State=dsEdit) then
  494. PX_put_recordn(FDoc,ActiveBuffer, FCurrRecNo)
  495. else
  496. InternalAddRecord(ActiveBuffer,True);
  497. end;
  498. function TParadox.IsCursorOpen: Boolean;
  499. begin
  500. Result:=(FDoc<>Nil);
  501. end;
  502. function TParadox.GetRecord(Buffer: PChar; GetMode: TGetMode; DoCheck: Boolean): TGetResult;
  503. var
  504. Accepted: Boolean;
  505. begin
  506. Result:=grOk;
  507. Accepted:=False;
  508. if (GetRecordCount<1) then
  509. begin
  510. Result:=grEOF;
  511. exit;
  512. end;
  513. repeat
  514. case GetMode of
  515. gmCurrent:
  516. if (FCurrRecNo>=GetRecordCount) or (FCurrRecNo<0) then
  517. Result:=grError;
  518. gmNext:
  519. if (FCurrRecNo<GetRecordCount-1) then
  520. Inc(FCurrRecNo)
  521. else
  522. Result:=grEOF;
  523. gmPrior:
  524. if (FCurrRecNo>0) then
  525. Dec(FCurrRecNo)
  526. else
  527. result:=grBOF;
  528. end;
  529. if result=grOK then
  530. begin
  531. PX_get_record(Doc,FCurrRecNo,Buffer+DataOffset);
  532. PPXRecInfo(Buffer)^.Bookmark:=FCurrRecNo;
  533. PPXRecInfo(Buffer)^.BookmarkFlag:=bfCurrent;
  534. if (Filtered) then
  535. Accepted:=PXFilterRecord(Buffer) //Filtering
  536. else
  537. Accepted:=True;
  538. if (GetMode=gmCurrent) and not Accepted then
  539. result:=grError;
  540. end;
  541. until (result<>grOK) or Accepted;
  542. end;
  543. function TParadox.GetFieldData(Field: TField; Buffer: Pointer): Boolean;
  544. var
  545. Buf : PChar;
  546. No,pft,flen : integer;
  547. pxf : PPx_field;
  548. Value : Pchar;
  549. Y,M,D : cint;
  550. longv : Clong;
  551. R : Double;
  552. c : Char;
  553. begin
  554. No:=Field.FieldNo-1;
  555. Buf:=Nil;
  556. result:=(No>=0) and PXGetActiveBuffer(Buf);
  557. if result and (buffer <> nil) then
  558. begin
  559. pxf:=PX_get_field(FDoc,No);
  560. Flen:=pxf^.px_flen; // Field length
  561. pft:=pxf^.px_ftype; // Field type
  562. Assert(PXFieldTypes[pft]=Field.DataType,'Field types do not match');
  563. Inc(Buf,FOffsets[No]); // Move to actual field offset
  564. Case pft of
  565. pxfAlpha:
  566. begin
  567. Result:=PX_get_data_alpha(FDoc,Buf,flen,@value)>0;
  568. If result then
  569. begin
  570. Move(Value^,Buffer^,flen);
  571. doc^.free(doc,value);
  572. end;
  573. end;
  574. pxfDate:
  575. begin
  576. Result:=PX_get_data_long(FDoc,Buf,flen,@longv)>0;
  577. If Result then
  578. begin
  579. // 1721425 is the number of the days between the start of the
  580. // julian calendar (4714 BC) and jan-00-0000 (Paradox base date)
  581. // 2415019 is the number of the days between the start of the
  582. // julian calendar (4714 BC) and dec-30-1899 (TDateTime base date)
  583. PDateTime(Buffer)^:=Longv+1721425-2415019;
  584. end;
  585. end;
  586. pxfShort:
  587. begin
  588. Result:=PX_get_data_short(FDoc,Buf, flen, @D)>0;
  589. If result then
  590. PSmallInt(Buffer)^:=D;
  591. end;
  592. pxfAutoInc,
  593. pxfLong:
  594. begin
  595. Result:=(PX_get_data_long(FDoc,buf,flen,@longv)>0);
  596. If Result then
  597. PInteger(Buffer)^:=Longv;
  598. end;
  599. pxfCurrency,
  600. pxfNumber:
  601. begin
  602. Result:=(PX_get_data_double(FDoc,Buf,Flen,@R)>0);
  603. If Result then
  604. PDouble(Buffer)^:=R;
  605. end;
  606. pxfLogical:
  607. begin
  608. Result:=(PX_get_data_byte(FDoc,Buf,flen,@C)>0);
  609. If result then
  610. PBoolean(Buffer)^:=(C<>#0);
  611. end;
  612. pxfBytes:
  613. begin
  614. Result:=PX_get_data_bytes(FDoc,Buf,FLen,@Value)>0;
  615. If Result then
  616. begin
  617. Move(Value^,Buffer^,FLen);
  618. FDoc^.free(FDoc,value);
  619. end;
  620. end;
  621. pxfMemoBLOb,
  622. pxfBLOb,
  623. pxfFmtMemoBLOb,
  624. pxfOLE,
  625. pxfGraphic:
  626. begin
  627. Result:=True;
  628. Move(Buf^,Buffer^,FLen);
  629. end;
  630. pxfTime:
  631. begin
  632. Result:=(PX_get_data_long(FDoc,Buf,flen,@longv)>0);
  633. If result then
  634. PDateTime(Buffer)^:=longv/MSecsPerDay;
  635. end;
  636. pxfTimestamp:
  637. begin
  638. Result:=(PX_get_data_double(FDoc,buf,flen,@R)>0);
  639. if Result then
  640. begin
  641. R:=R/1000.0;
  642. longv:=trunc(R /86400);
  643. PX_SdnToGregorian(longv+1721425,@Y,@M,@D);
  644. longv:=(Trunc(r) mod 86400);
  645. PDateTime(Buffer)^:=EncodeDate(Y,M,d)+(Longv/MSecsPerday);
  646. end;
  647. end;
  648. pxfBCD:
  649. begin
  650. Result:=(PX_get_data_bcd(FDoc,pcuchar(Buf),pxf^.px_fdc,@Value)>0);
  651. if Result then
  652. begin
  653. PCurrency(Buffer)^:=StrToCurr(StrPas(value));
  654. FDoc^.free(FDoc,value);
  655. end;
  656. end;
  657. else
  658. RaiseError('Unknown type (%d) (%d)',[pxf^.px_ftype, pxf^.px_flen]);
  659. end;
  660. end;
  661. end;
  662. procedure TParadox.SetFieldData(Field: TField; Buffer: Pointer);
  663. var
  664. DestBuffer: PChar;
  665. I: integer;
  666. begin
  667. DestBuffer:=Nil;
  668. I:=Field.FieldNo-1;
  669. if (I >= 0) and PXGetActiveBuffer(DestBuffer) then
  670. begin
  671. dataevent(deFieldChange,ptrint(field));
  672. end;
  673. end;
  674. procedure TParadox.DataConvert(aField: TField; aSource, aDest: Pointer;
  675. aToNative: Boolean);
  676. begin
  677. If AField.DataType in [ftDate,ftTime,ftDateTime] then
  678. PDateTime(aDest)^:=PDateTime(aSource)^
  679. else
  680. inherited DataConvert(aField, aSource, aDest, aToNative);
  681. end;
  682. function TParadox.CreateBlobStream(Field: TField; Mode: TBlobStreamMode
  683. ): TStream;
  684. TYpe
  685. PGraphicHeader = ^TGraphicHeader;
  686. Var
  687. FBuf,Value,V2 : Pchar;
  688. FLen,Res : Integer;
  689. M,D : Cint;
  690. H : PGraphicHeader;
  691. begin
  692. Result:=Nil;
  693. FLen:=Field.Size;
  694. If Mode=bmRead then
  695. begin
  696. FBuf:=GetMem(FLen);
  697. Try
  698. If Not Field.GetData(FBuf,True) then
  699. exit;
  700. if (Field.DataType=ftGraphic) then
  701. Res:=PX_get_data_graphic(FDoc,FBuf,FLen,@M,@D,@Value)
  702. else
  703. Res:=PX_get_data_blob(FDoc,FBuf,FLen,@M,@D,@Value);
  704. If (Res>0) and (Value<>Nil) then
  705. begin
  706. Result:=TMemoryStream.Create;
  707. V2:=Value;
  708. if (Field.DataType=ftGraphic) then
  709. Result.WriteAnsiString('bmp');
  710. Result.WriteBuffer(V2^,D-SizeOf(TGraphicHeader));
  711. Result.Position:=0;
  712. FDoc^.free(FDoc,Value);
  713. end;
  714. Finally
  715. FreeMem(FBuf);
  716. end;
  717. end
  718. else
  719. Result:=TMemoryStream.Create;
  720. end;
  721. function TParadox.GetRecordSize: Word;
  722. begin
  723. Result:=PX_Get_RecordSize(FDoc);
  724. end;
  725. procedure TParadox.InternalGotoBookmark(ABookmark: Pointer);
  726. var
  727. ReqBookmark: integer;
  728. begin
  729. ReqBookmark:=PInteger(ABookmark)^;
  730. if (ReqBookmark>=0) and (ReqBookmark<GetRecordCount) then
  731. FCurrRecNo:=ReqBookmark
  732. else
  733. RaiseError(SErrBookMarkNotFound,[ReqBookmark]);
  734. end;
  735. procedure TParadox.InternalSetToRecord(Buffer: PChar);
  736. var
  737. ReqBookmark: integer;
  738. begin
  739. ReqBookmark:=PPXRecInfo(Buffer)^.Bookmark;
  740. InternalGotoBookmark (@ReqBookmark);
  741. end;
  742. function TParadox.GetBookmarkFlag(Buffer: PChar): TBookmarkFlag;
  743. begin
  744. Result:=PPXRecInfo(Buffer)^.BookmarkFlag;
  745. end;
  746. procedure TParadox.SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag);
  747. begin
  748. PPXRecInfo(Buffer)^.BookmarkFlag := Value;
  749. end;
  750. procedure TParadox.GetBookmarkData(Buffer: PChar; Data: Pointer);
  751. begin
  752. if Data<>nil then
  753. PInteger(Data)^:=PPXRecInfo(Buffer)^.Bookmark;
  754. end;
  755. procedure TParadox.SetBookmarkData(Buffer: PChar; Data: Pointer);
  756. begin
  757. if Data<>nil then
  758. PPXRecInfo(Buffer)^.Bookmark:=PInteger(Data)^
  759. else
  760. PPXRecInfo(Buffer)^.Bookmark:=0;
  761. end;
  762. procedure TParadox.InternalAddRecord(Buffer: Pointer; DoAppend: Boolean);
  763. begin
  764. PXAppendRecord(ActiveBuffer);
  765. InternalLast;
  766. end;
  767. procedure TParadox.PXAppendRecord(Buffer : Pointer);
  768. begin
  769. end;
  770. function TParadox.GetInputEncoding: String;
  771. begin
  772. If Assigned(FDoc) then
  773. Result:=GetParam('inputencoding')
  774. else
  775. Result:=FInputEncoding;
  776. end;
  777. function TParadox.GetTableName: String;
  778. begin
  779. If Assigned(FDoc) then
  780. Result:=GetParam('tablename')
  781. else
  782. Result:=FInputEncoding;
  783. end;
  784. function TParadox.GetTargetEncoding: String;
  785. begin
  786. If Assigned(FDoc) then
  787. Result:=GetParam('targetencoding')
  788. else
  789. Result:=FTargetEncoding;
  790. end;
  791. procedure TParadox.SetRecNo(Value: Integer);
  792. begin
  793. CheckBrowseMode;
  794. if (Value>=1) and (Value<=GetRecordCount) then
  795. begin
  796. FCurrRecNo:=Value-1;
  797. Resync([]);
  798. end;
  799. end;
  800. Function TParadox.GetRecNo: Longint;
  801. begin
  802. UpdateCursorPos;
  803. if (FCurrRecNo<0) then
  804. Result:=1
  805. else
  806. Result:=FCurrRecNo+1;
  807. end;
  808. function TParadox.GetParam(const ParamName: String): String;
  809. Var
  810. V : Pchar;
  811. begin
  812. If Not Assigned(FDoc) then
  813. RaiseError(SErrParadoxNotOpen,[]);
  814. if (PX_Get_parameter(FDoc,Pchar(ParamName),@V)<>0) then
  815. RaiseError(SErrGetParamFailed,[ParamName]);
  816. If (V<>Nil) then
  817. Result:=strpas(V);
  818. end;
  819. procedure TParadox.SetParam(const ParamName, ParamValue: String);
  820. begin
  821. If Not Assigned(FDoc) then
  822. RaiseError(SErrParadoxNotOpen,[]);
  823. if (PX_Set_parameter(FDoc,Pchar(ParamName),PChar(ParamValue))<>0) then
  824. RaiseError(SErrSetParamFailed,[ParamName]);
  825. end;
  826. Function TParadox.GetRecordCount: Longint;
  827. begin
  828. If Assigned(FDoc) then
  829. Result:=PX_Get_num_records(FDoc)
  830. else
  831. Result:=0;
  832. end;
  833. end.