bufdataset.inc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Michael Van Canneyt, member of the
  4. Free Pascal development team
  5. BufDataset implementation
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. { ---------------------------------------------------------------------
  13. TBufDataSet
  14. ---------------------------------------------------------------------}
  15. constructor TBufDataset.Create(AOwner : TComponent);
  16. begin
  17. Inherited Create(AOwner);
  18. SetLength(FUpdateBuffer,0);
  19. BookmarkSize := sizeof(TBufBookmark);
  20. // temporary set it here
  21. FPacketRecords := 10;
  22. end;
  23. destructor TBufDataset.Destroy;
  24. begin
  25. inherited destroy;
  26. end;
  27. Function TBufDataset.GetCanModify: Boolean;
  28. begin
  29. Result:= False;
  30. end;
  31. function TBufDataset.AllocRecordBuffer: PChar;
  32. begin
  33. result := AllocMem(FRecordsize + sizeof(TBufBookmark));
  34. result^ := #1; // this 'deletes' the record
  35. end;
  36. procedure TBufDataset.FreeRecordBuffer(var Buffer: PChar);
  37. begin
  38. ReAllocMem(Buffer,0);
  39. end;
  40. procedure TBufDataset.InternalOpen;
  41. begin
  42. CalcRecordSize;
  43. FBRecordcount := 0;
  44. FBDeletedRecords := 0;
  45. FBBuffercount := 0;
  46. FBCurrentrecord := -1;
  47. FOpen:=True;
  48. FIsEOF := false;
  49. FIsbOF := true;
  50. end;
  51. procedure TBufDataset.InternalClose;
  52. var i : integer;
  53. begin
  54. FOpen:=False;
  55. CancelUpdates;
  56. for i := 0 to FBRecordCount-1 do FreeRecordBuffer(FBBuffers[i]);
  57. If FBBufferCount > 0 then ReAllocMem(FBBuffers,0);
  58. FBRecordcount := 0;
  59. FBBuffercount := 0;
  60. FBCurrentrecord := -1;
  61. FIsEOF := true;
  62. FIsbOF := true;
  63. end;
  64. procedure TBufDataset.InternalFirst;
  65. begin
  66. FBCurrentRecord := -1;
  67. FIsEOF := false;
  68. end;
  69. procedure TBufDataset.InternalLast;
  70. begin
  71. repeat
  72. until getnextpacket < FPacketRecords;
  73. FIsBOF := false;
  74. FBCurrentRecord := FBRecordcount;
  75. end;
  76. procedure unSetDeleted(NullMask : pbyte); //inline;
  77. begin
  78. NullMask[0] := NullMask[0] and not 1;
  79. end;
  80. procedure SetDeleted(NullMask : pbyte); //inline;
  81. begin
  82. NullMask[0] := NullMask[0] or 1;
  83. end;
  84. function GetDeleted(NullMask : pbyte) : boolean; //inline;
  85. begin
  86. result := (NullMask[0] and 1) = 1;
  87. end;
  88. procedure unSetFieldIsNull(NullMask : pbyte;x : longint); //inline;
  89. begin
  90. inc(x);
  91. NullMask[x div 8] := (NullMask[x div 8]) and not (1 shl (x mod 8));
  92. end;
  93. procedure SetFieldIsNull(NullMask : pbyte;x : longint); //inline;
  94. begin
  95. inc(x);
  96. NullMask[x div 8] := (NullMask[x div 8]) or (1 shl (x mod 8));
  97. end;
  98. function GetFieldIsNull(NullMask : pbyte;x : longint) : boolean; //inline;
  99. begin
  100. inc(x);
  101. result := ord(NullMask[x div 8]) and (1 shl (x mod 8)) > 0
  102. end;
  103. function TBufDataset.GetRecord(Buffer: PChar; GetMode: TGetMode; DoCheck: Boolean): TGetResult;
  104. var x : longint;
  105. RecUpdBuf : PRecUpdateBuffer;
  106. FieldUpdBuf : PFieldUpdateBuffer;
  107. NullMask : pbyte;
  108. begin
  109. Result := grOK;
  110. case GetMode of
  111. gmPrior :
  112. if FIsBOF then
  113. result := grBOF
  114. else if FBCurrentRecord <= 0 then
  115. begin
  116. Result := grBOF;
  117. FBCurrentRecord := -1;
  118. end
  119. else
  120. begin
  121. Dec(FBCurrentRecord);
  122. FIsEof := false;
  123. end;
  124. gmCurrent :
  125. if (FBCurrentRecord < 0) or (FBCurrentRecord >= FBRecordCount) then
  126. Result := grError;
  127. gmNext :
  128. if FIsEOF then
  129. result := grEOF
  130. else if FBCurrentRecord >= (FBRecordCount - 1) then
  131. begin
  132. if getnextpacket > 0 then
  133. begin
  134. Inc(FBCurrentRecord);
  135. FIsBof := false;
  136. end
  137. else
  138. begin
  139. FIsEOF := true;
  140. result:=grEOF;
  141. end
  142. end
  143. else
  144. begin
  145. Inc(FBCurrentRecord);
  146. FIsBof := false;
  147. end;
  148. end;
  149. if Result = grOK then
  150. begin
  151. if GetDeleted(pbyte(FBBuffers[FBCurrentRecord])) then
  152. begin
  153. if getmode = gmCurrent then
  154. if DoCheck then
  155. begin
  156. Result := grError;
  157. DatabaseError(SDeletedRecord);
  158. exit;
  159. end
  160. else
  161. getmode := gmnext;
  162. Result := GetRecord(Buffer,getmode,DoCheck);
  163. exit
  164. end;
  165. with PBufBookmark(Buffer + RecordSize)^ do
  166. begin
  167. BookmarkData := FBCurrentRecord;
  168. BookmarkFlag := bfCurrent;
  169. end;
  170. move(FBBuffers[FBCurrentRecord]^,buffer^,RecordSize);
  171. // Cached Updates:
  172. If GetRecordUpdateBuffer(FBCurrentRecord,RecUpdBuf) then
  173. begin
  174. NullMask := pbyte(buffer);
  175. inc(buffer,FNullmaskSize);
  176. for x := 0 to FieldDefs.count-1 do
  177. begin
  178. if GetFieldUpdateBuffer(x,RecUpdBuf,FieldUpdBuf) then
  179. If not FieldUpdBuf^.IsNull then
  180. begin
  181. unSetFieldIsNull(NullMask,x);
  182. move(FieldUpdBuf^.NewValue^,buffer^,GetFieldSize(FieldDefs[x]));
  183. end
  184. else
  185. SetFieldIsNull(NullMask,x);
  186. Inc(Buffer, GetFieldSize(FieldDefs[x]));
  187. end;
  188. end;
  189. end
  190. else if (Result = grError) and doCheck then
  191. DatabaseError('No record');
  192. end;
  193. function TBufDataset.GetRecordUpdateBuffer(rno : integer;var RecUpdBuf : PRecUpdateBuffer) : boolean;
  194. var r : integer;
  195. begin
  196. Result := False;
  197. for r := 0 to high(FUpdateBuffer) do
  198. if (FUpdateBuffer[r].RecordNo = rno) and (@FUpdateBuffer[r] <> FEditBuf) then // Neglect the edit-buffer
  199. begin
  200. RecUpdBuf := @FUpdateBuffer[r];
  201. Result := True;
  202. Break;
  203. end;
  204. end;
  205. function TBufDataset.GetFieldUpdateBuffer(fieldno : integer;RecUpdBuf : PRecUpdateBuffer;var FieldUpdBuf : pFieldUpdateBuffer) : boolean;
  206. var f : integer;
  207. begin
  208. Result := False;
  209. for f := 0 to High(RecUpdBuf^.FieldsUpdateBuffer) do
  210. if RecUpdBuf^.FieldsUpdateBuffer[f].FieldNo = fieldno then
  211. begin
  212. FieldUpdBuf := @RecUpdBuf^.FieldsUpdateBuffer[f];
  213. Result := True;
  214. Break;
  215. end;
  216. end;
  217. procedure TBufDataset.InternalSetToRecord(Buffer: PChar);
  218. begin
  219. FBCurrentRecord := PBufBookmark(Buffer + RecordSize)^.BookmarkData;
  220. FIsEOF := False;
  221. FIsBOF := False;
  222. end;
  223. procedure TBufDataset.SetBookmarkData(Buffer: PChar; Data: Pointer);
  224. begin
  225. PBufBookmark(Buffer + RecordSize)^.BookmarkData := PInteger(Data)^;
  226. end;
  227. procedure TBufDataset.SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag);
  228. begin
  229. PBufBookmark(Buffer + RecordSize)^.BookmarkFlag := Value;
  230. end;
  231. procedure TBufDataset.GetBookmarkData(Buffer: PChar; Data: Pointer);
  232. begin
  233. PInteger(Data)^ := PBufBookmark(Buffer + RecordSize)^.BookmarkData;
  234. end;
  235. function TBufDataset.GetBookmarkFlag(Buffer: PChar): TBookmarkFlag;
  236. begin
  237. Result := PBufBookmark(Buffer + RecordSize)^.BookmarkFlag;
  238. end;
  239. procedure TBufDataset.InternalGotoBookmark(ABookmark: Pointer);
  240. begin
  241. FBCurrentRecord := Plongint(ABookmark)^;
  242. FIsEOF := False;
  243. FIsBOF := False;
  244. end;
  245. function TBufDataset.getnextpacket : integer;
  246. var i : integer;
  247. b : boolean;
  248. begin
  249. i := 0;
  250. if FPacketRecords > 0 then
  251. begin
  252. if FBBufferCount < FBRecordCount+FPacketRecords then
  253. begin
  254. FBBufferCount := FBBuffercount + FPacketRecords;
  255. ReAllocMem(FBBuffers,FBBuffercount*SizeOf(PChar));
  256. end;
  257. repeat
  258. FBBuffers[FBRecordCount+i] := AllocRecordBuffer;
  259. b := (loadbuffer(FBBuffers[FBRecordCount+i])<>grOk);
  260. inc(i);
  261. until (i = FPacketRecords) or b;
  262. if b then
  263. begin
  264. dec(i);
  265. FreeRecordBuffer(FBBuffers[FBRecordCount+i]);
  266. end;
  267. FBRecordCount := FBRecordCount + i;
  268. end;
  269. result := i;
  270. end;
  271. function TBufDataset.GetFieldSize(FieldDef : TFieldDef) : longint;
  272. begin
  273. case FieldDef.DataType of
  274. ftString,
  275. ftFixedChar: result := FieldDef.Size + 1;
  276. ftSmallint,
  277. ftInteger,
  278. ftword : result := sizeof(longint);
  279. ftBoolean : result := sizeof(wordbool);
  280. ftBCD : result := sizeof(currency);
  281. ftFloat : result := sizeof(double);
  282. ftTime,
  283. ftDate,
  284. ftDateTime : result := sizeof(TDateTime)
  285. else Result := 10
  286. end;
  287. end;
  288. function TBufDataset.LoadBuffer(Buffer : PChar): TGetResult;
  289. var NullMask : pbyte;
  290. x : longint;
  291. begin
  292. if not Fetch then
  293. begin
  294. Result := grEOF;
  295. Exit;
  296. end;
  297. NullMask := pointer(buffer);
  298. fillchar(Nullmask^,FNullmaskSize,0);
  299. inc(buffer,FNullmaskSize);
  300. for x := 0 to FieldDefs.count-1 do
  301. begin
  302. if not LoadField(FieldDefs[x],buffer) then
  303. SetFieldIsNull(NullMask,x);
  304. inc(buffer,GetFieldSize(FieldDefs[x]));
  305. end;
  306. Result := grOK;
  307. end;
  308. function TBufDataset.GetFieldData(Field: TField; Buffer: Pointer;
  309. NativeFormat: Boolean): Boolean;
  310. begin
  311. Result := GetFieldData(Field, Buffer);
  312. end;
  313. function TBufDataset.GetFieldData(Field: TField; Buffer: Pointer): Boolean;
  314. var
  315. x : longint;
  316. CurrBuff : pchar;
  317. begin
  318. Result := False;
  319. If Field.Fieldno > 0 then // If = 0, then calculated field or something similar
  320. begin
  321. if state = dsOldValue then
  322. begin
  323. if FApplyingUpdates then
  324. CurrBuff := FBBuffers[fbcurrentrecord] // This makes it possible for ApplyUpdates to get values from deleted records
  325. else
  326. CurrBuff := FBBuffers[GetRecNo];
  327. end
  328. else
  329. begin
  330. CurrBuff := ActiveBuffer;
  331. if not assigned(CurrBuff) or GetDeleted(pbyte(CurrBuff)) then
  332. begin
  333. result := false;
  334. exit;
  335. end;
  336. end;
  337. if GetFieldIsnull(pbyte(CurrBuff),Field.Fieldno-1) then
  338. begin
  339. result := false;
  340. exit;
  341. end;
  342. inc(Currbuff,FNullmaskSize);
  343. for x := 0 to FieldDefs.count-1 do
  344. begin
  345. if (Field.FieldName = FieldDefs[x].Name) then
  346. begin
  347. // a nil-buffer is allowed for the fields.isNull function
  348. if assigned(buffer) then Move(CurrBuff^, Buffer^, GetFieldSize(FieldDefs[x]));
  349. Result := True;
  350. Break;
  351. end
  352. else Inc(CurrBuff, GetFieldSize(FieldDefs[x]));
  353. end;
  354. end;
  355. end;
  356. procedure TBufDataset.SetFieldData(Field: TField; Buffer: Pointer;
  357. NativeFormat: Boolean);
  358. begin
  359. SetFieldData(Field,Buffer);
  360. end;
  361. procedure TBufDataset.SetFieldData(Field: TField; Buffer: Pointer);
  362. var
  363. x : longint;
  364. CurrBuff : pointer;
  365. NullMask : pbyte;
  366. FieldUpdBuf : PFieldUpdateBuffer;
  367. begin
  368. if not (state in [dsEdit, dsInsert]) then
  369. begin
  370. DatabaseErrorFmt(SNotInEditState,[NAme],self);
  371. exit;
  372. end;
  373. If Field.Fieldno > 0 then // If = 0, then calculated field or something
  374. begin
  375. CurrBuff := ActiveBuffer;
  376. NullMask := CurrBuff;
  377. inc(Currbuff,FNullmaskSize);
  378. for x := 0 to FieldDefs.count-1 do
  379. begin
  380. if (Field.FieldName = FieldDefs[x].Name) then
  381. begin
  382. if assigned(buffer) then
  383. begin
  384. Move(Buffer^, CurrBuff^, GetFieldSize(FieldDefs[x]));
  385. unSetFieldIsNull(NullMask,x);
  386. end
  387. else
  388. SetFieldIsNull(NullMask,x);
  389. // cached updates
  390. with FEditBuf^ do
  391. begin
  392. if not GetFieldUpdateBuffer(x,FEditBuf,FieldUpdBuf) then
  393. begin
  394. SetLength(FieldsUpdateBuffer,length(FieldsUpdateBuffer)+1);
  395. FieldUpdBuf := @FieldsUpdateBuffer[high(FieldsUpdateBuffer)];
  396. GetMem(FieldUpdBuf^.NewValue,GetFieldSize(FieldDefs[x]));
  397. FieldUpdBuf^.FieldNo := x;
  398. end;
  399. if assigned(buffer) then
  400. begin
  401. Move(Buffer^, FieldUpdBuf^.NewValue^, GetFieldSize(FieldDefs[x]));
  402. FieldUpdBuf^.IsNull := False;
  403. end
  404. else FieldUpdBuf^.IsNull := True;
  405. end;
  406. Break;
  407. end
  408. else Inc(CurrBuff, GetFieldSize(FieldDefs[x]));
  409. end;
  410. if not (State in [dsCalcFields, dsFilter, dsNewValue]) then
  411. DataEvent(deFieldChange, Ptrint(Field));
  412. end;
  413. end;
  414. procedure TBufDataset.InternalEdit;
  415. begin
  416. if not GetRecordUpdateBuffer(recno,FEditBuf) then
  417. begin
  418. If not assigned(FEditBuf) then
  419. begin
  420. SetLength(FUpdateBuffer,length(FUpdateBuffer)+1);
  421. FEditBuf := @FUpdateBuffer[high(FUpdateBuffer)];
  422. end;
  423. FEditBuf^.UpdateKind := ukModify;
  424. FEditBuf^.RecordNo := getrecno;
  425. end;
  426. end;
  427. procedure TBufDataset.InternalInsert;
  428. begin
  429. if FBRecordCount > FBBufferCount-1 then
  430. begin
  431. inc(FBBufferCount);
  432. ReAllocMem(FBBuffers,FBBuffercount*SizeOf(PChar));
  433. end;
  434. inc(FBRecordCount);
  435. FBCurrentRecord := FBRecordCount -1;
  436. FBBuffers[FBCurrentRecord] := AllocRecordBuffer;
  437. fillchar(FBBuffers[FBCurrentRecord]^,FNullmaskSize,255);
  438. unSetDeleted(pbyte(FBBuffers[FBCurrentRecord]));
  439. fillchar(ActiveBuffer^,FNullmaskSize,255);
  440. unSetDeleted(pbyte(ActiveBuffer));
  441. // cached updates:
  442. If not assigned(FEditBuf) then
  443. begin
  444. SetLength(FUpdateBuffer,length(FUpdateBuffer)+1);
  445. FEditBuf := @FUpdateBuffer[high(FUpdateBuffer)];
  446. end;
  447. FEditBuf^.RecordNo := FBCurrentRecord;
  448. FEditBuf^.UpdateKind := ukInsert;
  449. with PBufBookmark(ActiveBuffer + RecordSize)^ do
  450. begin
  451. BookmarkData := FBCurrentRecord;
  452. BookmarkFlag := bfInserted;
  453. end;
  454. end;
  455. procedure TBufDataset.InternalDelete;
  456. var tel : integer;
  457. begin
  458. SetDeleted(pbyte(FBBuffers[FBCurrentRecord]));
  459. SetDeleted(pbyte(ActiveBuffer));
  460. inc(FBDeletedRecords);
  461. if GetRecordUpdateBuffer(recno,FEditBuf) and (FEditBuf^.UpdateKind = ukInsert) then
  462. begin
  463. if assigned(FEditBuf^.FieldsUpdateBuffer) then
  464. for tel := 0 to high(FEditBuf^.FieldsUpdateBuffer) do
  465. if not FEditBuf^.FieldsUpdateBuffer[tel].IsNull then
  466. freemem(FEditBuf^.FieldsUpdateBuffer[tel].NewValue);
  467. setlength(FEditBuf^.FieldsUpdateBuffer,0);
  468. FEditBuf^.RecordNo := -1;
  469. end
  470. else
  471. begin
  472. If not assigned(FEditBuf) then
  473. begin
  474. SetLength(FUpdateBuffer,length(FUpdateBuffer)+1);
  475. FEditBuf := @FUpdateBuffer[high(FUpdateBuffer)];
  476. end;
  477. FEditBuf^.RecordNo := FBCurrentRecord;
  478. FEditBuf^.UpdateKind := ukDelete;
  479. end;
  480. FEditBuf := nil;
  481. end;
  482. function TBufDataset.ApplyRecUpdate(UpdateKind : TUpdateKind) : boolean;
  483. begin
  484. Result := False;
  485. end;
  486. procedure TBufDataset.CancelUpdates;
  487. var r,f : integer;
  488. begin
  489. for r := 0 to high(FUpdateBuffer) do
  490. begin
  491. if FUpdateBuffer[r].RecordNo > -1 then
  492. if FUpdateBuffer[r].UpdateKind = ukDelete then
  493. begin
  494. dec(FBDeletedRecords);
  495. unSetDeleted(pbyte(FBBuffers[FUpdateBuffer[r].RecordNo]));
  496. end
  497. else if FUpdateBuffer[r].UpdateKind = ukInsert then
  498. begin
  499. inc(FBDeletedRecords);
  500. SetDeleted(pbyte(FBBuffers[FUpdateBuffer[r].RecordNo]));
  501. end;
  502. for f := 0 to high(FUpdateBuffer[r].FieldsUpdateBuffer) do
  503. FreeMem(FUpdateBuffer[r].FieldsUpdateBuffer[f].newvalue);
  504. end;
  505. SetLength(FUpdateBuffer,0);
  506. if FOpen then Resync([]);
  507. end;
  508. procedure TBufDataset.ApplyUpdates;
  509. var SaveBookmark : Integer;
  510. r,i : Integer;
  511. buffer : PChar;
  512. x : integer;
  513. FieldUpdBuf : PFieldUpdateBuffer;
  514. NullMask : pbyte;
  515. begin
  516. CheckBrowseMode;
  517. if IsEmpty then exit;
  518. SaveBookMark := GetRecNo;
  519. r := 0;
  520. while r < Length(FUpdateBuffer) do
  521. begin
  522. if (@FUpdateBuffer[r] <> FEditBuf) and // Neglect edit-buffer
  523. (FUpdateBuffer[r].RecordNo <> -1) then // And the 'deleted' buffers
  524. begin
  525. FApplyingUpdates := true;
  526. if FUpdateBuffer[r].UpdateKind = ukDelete then
  527. InternalGotoBookmark(@(FUpdateBuffer[r].RecordNo))
  528. else
  529. begin
  530. InternalGotoBookMark(@FUpdateBuffer[r].RecordNo);
  531. Resync([rmExact,rmCenter]);
  532. end;
  533. if ApplyRecUpdate(FUpdateBuffer[r].UpdateKind) then
  534. begin
  535. buffer := FBBuffers[FUpdateBuffer[r].RecordNo];
  536. NullMask := pbyte(buffer);
  537. inc(buffer,FNullmaskSize);
  538. for x := 0 to FieldDefs.count-1 do
  539. begin
  540. if GetFieldUpdateBuffer(x,@FUpdateBuffer[r],FieldUpdBuf) then
  541. If not FieldUpdBuf^.IsNull then
  542. begin
  543. unSetFieldIsNull(NullMask,x);
  544. move(FieldUpdBuf^.NewValue^,buffer^,GetFieldSize(FieldDefs[x]));
  545. FreeMem(FieldUpdBuf^.NewValue);
  546. end
  547. else
  548. SetFieldIsNull(NullMask,x);
  549. Inc(Buffer, GetFieldSize(FieldDefs[x]));
  550. end;
  551. for i := r to high(FUpdateBuffer)-1 do
  552. FUpdateBuffer[i] := FupdateBuffer[i+1];
  553. dec(r);
  554. SetLength(FUpdateBuffer,high(FUpdateBuffer));
  555. end;
  556. FApplyingUpdates := False;
  557. end;
  558. inc(r);
  559. end;
  560. if not GetDeleted(pbyte(FBBuffers[savebookmark])) then
  561. begin
  562. InternalGotoBookMark(@SaveBookMark);
  563. Resync([rmExact,rmCenter]);
  564. end;
  565. end;
  566. procedure TBufDataset.InternalPost;
  567. begin
  568. if state in [dsEdit, dsInsert] then
  569. begin
  570. if Length(FUpdateBuffer[High(FUpdateBuffer)].FieldsUpdateBuffer) > 0 then
  571. FEditBuf := nil;
  572. end;
  573. end;
  574. procedure TBufDataset.InternalCancel;
  575. var tel : integer;
  576. begin
  577. if state in [dsEdit, dsInsert] then
  578. begin
  579. if state = dsInsert then
  580. begin
  581. SetDeleted(pbyte(FBBuffers[FBCurrentRecord]));
  582. SetDeleted(pbyte(ActiveBuffer));
  583. inc(FBDeletedRecords);
  584. end;
  585. FEditBuf^.RecordNo := -1;
  586. // clear the fieldbuffers
  587. if assigned(FEditBuf^.FieldsUpdateBuffer) then
  588. for tel := 0 to high(FEditBuf^.FieldsUpdateBuffer) do
  589. if not FEditBuf^.FieldsUpdateBuffer[tel].IsNull then
  590. freemem(FEditBuf^.FieldsUpdateBuffer[tel].NewValue);
  591. setlength(FEditBuf^.FieldsUpdateBuffer,0);
  592. end;
  593. end;
  594. procedure TBufDataset.CalcRecordSize;
  595. var x : longint;
  596. begin
  597. FNullmaskSize := 1+((FieldDefs.count) div 8);
  598. FRecordSize := FNullmaskSize;
  599. for x := 0 to FieldDefs.count-1 do
  600. inc(FRecordSize, GetFieldSize(FieldDefs[x]));
  601. end;
  602. function TBufDataset.GetRecordSize : Word;
  603. begin
  604. result := FRecordSize;
  605. end;
  606. procedure TBufDataset.InternalInitRecord(Buffer: PChar);
  607. begin
  608. FillChar(Buffer^, FRecordSize, #0);
  609. end;
  610. procedure TBufDataset.SetRecNo(Value: Longint);
  611. begin
  612. GotoBookmark(@value);
  613. end;
  614. function TBufDataset.GetRecNo: Longint;
  615. begin
  616. GetBookmarkData(ActiveBuffer,@Result);
  617. end;
  618. function TBufDataset.IsCursorOpen: Boolean;
  619. begin
  620. Result := FOpen;
  621. end;
  622. Function TBufDataset.GetRecordCount: Longint;
  623. begin
  624. Result := FBRecordCount-FBDeletedRecords;
  625. end;