home *** CD-ROM | disk | FTP | other *** search
- UNIT BTP; {Version 1.4 10/27/91 (C) 1991 John C. Leon}
-
- {$A+} {word alignment. Btrieve interface call wants this global directive
- set; is the default compiler setting anyway. }
-
- INTERFACE
- (* ------------------------------------------------------------------------ *)
- (* ------------------------------------------------------------------------ *)
- USES Objects, Memory;
-
- CONST
- { Key Attributes Key Types Open Modes }
- { ------------------ ---------------- --------------- }
- Duplicates = 1; BString = 0; Normal = 0;
- Modifiable = 2; BInteger = 1; Accel = -1;
- Binary = 4; BFloat = 2; ReadOnly = -2;
- Null = 8; BDate = 3; Verify = -3;
- Segmented = 16; BTime = 4; Exclusive = -4;
- AltCol = 32; BDecimal = 5;
- Descending = 64; BMoney = 6;
- Supplemental = 128; BLogical = 7;
- ExtType = 256; BNumeric = 8;
- BBFloat = 9;
- BLString = 10;
- BZString = 11;
- BUnsBinary = 14;
- BAutoInc = 15;
-
- { Btrieve Op Codes Misc }
- { ----------------------------------------- ------------------------- }
- BOpen = 0; BAbortTran = 21; Zero : integer = 0;
- BClose = 1; BGetPos = 22; NotRequired : integer = 0;
- BInsert = 2; BGetDir = 23;
- BUpdate = 3; BStepNext = 24; { Error Codes }
- BDelete = 4; BStop = 25; {-------------------------}
- BGetEqual = 5; BVersion = 26; FileNotOpen = 3;
- BGetNext = 6; BUnlock = 27; InvalidKeyNumber = 6;
- BGetPrev = 7; BReset = 28; DiffKeyNumber = 7;
- BGetGr = 8; BSetOwner = 29; InvalidPosition = 8;
- BGetGrEq = 9; BClrOwner = 30; EndofFile = 9;
- BGetLess = 10; BCrSuppIdx = 31; FileNotFound = 12;
- BGetLessEq = 11; BDropSuppIdx = 32; DataBufferLength = 22;
- BGetFirst = 12; BStepFirst = 33; RejectCount = 60;
- BGetLast = 13; BStepLast = 34; IncorrectDesc = 62;
- BCreate = 14; BStepPrev = 35; FilterLimit = 64;
- BStat = 15; BGetNextExt = 36; IncorrectFldOff = 65;
- BExtend = 16; BGetPrevExt = 37; LostPosition = 82;
- BSetDosDir = 17; BStepNextExt = 38;
- BGetDosDir = 18; BStepPrevExt = 39;
- BBegTran = 19; BInsertExt = 40;
- BEndTran = 20; BGetKey = 50;
-
- { Extended Ops Comp Codes/Bias Extended Ops Logic Constants }
- { ----------------------------- ----------------------------------- }
- Equal : byte = 1; NoFilter : integer = 0;
- GreaterThan: byte = 2; LastTerm : byte = 0;
- LessThan : byte = 3; NextTermAnd: byte = 1;
- NotEqual : byte = 4; NextTermOr : byte = 2;
- GrOrEqual : byte = 5;
- LessOrEqual: byte = 6;
- UseAltColl : byte = 32;
- UseField : byte = 64;
- UseNoCase : byte = 128;
-
- { Other Unit-Specific Constants }
- { --------------------------------- }
- MaxFixedRecLength = 4090; {Btrieve limits fixed record length for std }
- MaxKBufferLength = 255; {files to 4090. Max key size is 255. }
- MaxExtDBufferLength = 32767;
-
- TYPE
-
- (* Data types for TRecMgr object *)
- (* ----------------------------- *)
- TVersion = record
- case integer of
- 1: (Number : word;
- Rev : integer;
- Product: char);
- 2: (Entire : array[1..5] of char);
- end;
- PRecMgr = ^TRecMgr;
- TRecMgr = object(TObject) {Base obj handles abort/begin/end}
- Version: TVersion; {tran, reset, version and stop. }
- VersionString: string;
- constructor Init;
- function BT(OpCode, Key: integer): integer; virtual;
- destructor Done; virtual;
- end;
-
- (* Data types for BFile object *)
- (* --------------------------- *)
- BFileName = array[1..80] of char; {79 + blank pad required by Btrieve}
- PKeySpec = ^KeySpec;
- KeySpec = record {data type for a Btrieve key spec}
- case integer of
- 1: (KeyPos : integer;
- KeyLen : integer;
- KeyFlags : integer;
- NotUsed : array[1..4] of byte;
- ExtKeyType : byte;
- NullValue : byte;
- Reserved : array[1..4] of byte);
- 2: (Entire : array[1..16] of byte);
- end;
- PFileSpec = ^TFileSpec;
- TFileSpec = record
- case integer of
- 1: (RecLen : integer;
- PageSize : integer;
- NumKeys : integer;
- NumRecs : array[1..2] of integer;
- FileFlags : integer;
- Reserved : array[1..2] of char;
- PreAlloc : integer;
- KeyArray : array[0..23] of KeySpec); {24=max # segs}
- 2: (SpecBuf : integer); {used to refer to addr of spec}
- 3: (Entire : array[1..400] of byte);
- end;
- PBFile = ^BFile;
- BFile = object(TObject)
- DFileName : FNameStr; {DOS filename}
- Specs : TFileSpec; {Btrieve file specs}
- NumRecs : longint; {# records at Init time}
- NumSegs : integer; {total # key segs}
- PosBlk : array[1..128] of char; {position block}
- DBufferLen : integer;
- constructor Init(UserFileName:string; OpenMode: integer);
- function BT(OpCode, Key: integer): integer; virtual;
- function Open(OpenMode: integer): integer; virtual;
- function Close: integer; virtual;
- destructor Done; virtual;
- private
- FileName : BFileName; {Btrieve-type filename}
- procedure ConvertName(UserFileName: string);
- end;
-
- (* Data types for BFixed object - descendant of BFile *)
- (* -------------------------------------------------- *)
- TDBuffer = array[1..MaxFixedRecLength] of byte;
- TKBuffer = array[1..MaxKBufferLength] of byte;
- PBFixed = ^BFixed;
- BFixed = object(BFile)
- DBuffer: TDBuffer;
- KBuffer: TKBuffer;
- constructor Init(UserFileName:string; OpenMode: integer);
- function BT(OpCode, Key: integer): integer; virtual;
- destructor Done; virtual;
- end;
-
- (* Data types for BFileExt object - descendant of BFile *)
- (* ---------------------------------------------------- *)
- TCharArray = array[1..255] of char;
- THeader = record
- case integer of
- 1: (DBufferLen : integer;
- Constant : array[1..2] of char);
- 2: (Entire : array[1..4] of byte);
- end;
- TFilter = record
- case integer of
- 1: (MaxSkip : integer;
- NumLogicTerms : integer);
- 2: (Entire : array[1..2] of integer);
- end;
- TLogicTerm = record
- FieldType : byte;
- FieldLen : integer;
- Offset : integer; {0 relative to start of record}
- CompCode : byte;
- Expression : byte; {0 last term,1 AND w/next,2 OR w/next}
- case FieldComp: boolean of
- True : (CompOffset: integer);
- False: (Value: TCharArray);{an arbitrary limitation of}
- end; {255 on length of values }
- PFilterSpec = ^TFilterSpec;
- TFilterSpec = object(TObject)
- LogicTerm: TLogicTerm;
- constructor InitF(FieldType: byte; FieldLen, Offset:
- integer; CompCode, Expression: byte;
- FieldComp: boolean; CompOffset: integer);
- constructor InitV(FieldType: byte; FieldLen, Offset:
- integer; CompCode, Expression: byte;
- FieldComp: boolean; Value: TCharArray);
- destructor Done; virtual;
- end;
- TExtractor = record
- case integer of
- 1: (NumRecords: integer;
- NumFields : integer);
- 2: (Entire : array[1..2] of integer);
- end;
- TExtRepeater= record
- FieldLen: integer;
- Offset : integer;
- end;
- PExtSpec = ^TExtSpec;
- TExtSpec = object(TObject)
- ExtRepeater: TExtRepeater;
- constructor Init(Len, Ofs: integer);
- destructor Done; virtual;
- end;
- PExtDBuffer = ^TExtDBuffer;
- TExtDBuffer = record
- case integer of
- 1: (Header : THeader; {Buffer sent includes these}
- Filter : TFilter); {types at its beginning.}
- 2: (NumRecs : integer; {Buffer rec'd looks}
- Repeater : array[1..32765] of char); {like this.}
- {Repeater structure is: 2 for length of record image, }
- { 4 for currency position of rec, }
- { n for record image itself }
- 3: (Entire : array[1..32767] of byte); {Whole buffer.}
- end;
- PBFileExt = ^BFileExt;
- BFileExt = object(BFile)
- Header : THeader;
- Filter : TFilter;
- FilterSpec : PCollection;
- Extractor : TExtractor;
- ExtractorSpec : PCollection;
- ExtDBuffer : PExtDBuffer;
- constructor Init(UserFileName: string; OpenMode: integer);
- function BTExt(OpCode, Key: integer): integer; virtual;
- destructor Done; virtual;
- private
- procedure SetExtDBufferLen;
- procedure MakeExtDBuffer;
- end;
-
-
- (* PUBLIC/EXPORTED VARS *)
- (* -------------------- *)
- VAR
- BStatus : integer;
- VarNotRequired : integer; {Dummy parameter.}
- VarPosBlk : array[1..128] of char; {Dummy used in ops that don't}
- {pass/return position block. }
-
- (* PUBLIC/EXPORTED FUNCTIONS *)
- (* ------------------------- *)
- {The Btrv function declared here is public, but should not ever be needed. It
- is included in the public declaration only to be complete and give you
- access to the standard call if you should need it.}
-
- function Btrv(Op:integer; var Pos,Data; var DataLen:integer; var KBuf;
- Key:integer): integer;
- function CreateFile(UserFileName:string; UserFileSpec:PFileSpec): integer;
- function LTrim(S: String): String; {LTrim and RTrim were taken from one of }
- function RTrim(S: String): String; {the Turbo Vision .PAS source files. }
-
-
- IMPLEMENTATION
- (* ---------------------------------------------------------------------- *)
- (* ---------------------------------------------------------------------- *)
- uses Dos;{Dos unit needed for the Btrieve interface call (interrupts) }
-
- {$R-} {Range checking off...is TP's default}
- {$B+} {Boolean complete evaluation on...NOT a default, but apparently
- required by the interface call. Is turned off at end of Btrieve
- interface definition}
- {$V-} {Non-strict string var checking...Btrieve wants it so. Strict
- checking is turned back on at the end of the interface definition.}
-
- (* BTRV Function...directly from the Btrieve distribution disks, w/comments
- removed *)
- (* ----------------------------------------------------------------------- *)
- function Btrv(Op:integer; var Pos, Data; var DataLen:integer; var KBuf;
- Key:integer): integer;
- const
- VAR_ID = $6176;
- BTR_INT = $7B;
- BTR2_INT = $2F;
- BTR_OFFSET = $0033;
- MULTI_FUNCTION = $AB;
- ProcId: integer = 0;
- MULTI: boolean = false;
- VSet: boolean = false;
-
- type
- ADDR32 = record
- OFFSET: word;
- SEGMENT: word;
- end;
-
- BTR_PARMS = record
- USER_BUF_ADDR: ADDR32;
- USER_BUF_LEN: integer;
- USER_CUR_ADDR: ADDR32;
- USER_FCB_ADDR: ADDR32;
- USER_FUNCTION: integer;
- USER_KEY_ADDR: ADDR32;
- USER_KEY_LENGTH: BYTE;
- USER_KEY_NUMBER: shortint;
- USER_STAT_ADDR: ADDR32;
- XFACE_ID: integer;
- end;
-
- var
- STAT: integer;
- XDATA: BTR_PARMS;
- REGS: Dos.Registers;
- DONE: boolean;
-
- begin
- REGS.AX := $3500 + BTR_INT;
- INTR ($21, REGS);
- if (REGS.BX <> BTR_OFFSET) then
- STAT := 20
- else
- begin
- if (not VSet) then
- begin
- REGS.AX := $3000;
- INTR ($21, REGS);
- if ((REGS.AX AND $00FF) >= 3) then
- begin
- VSet := true;
- REGS.AX := MULTI_FUNCTION * 256;
- INTR (BTR2_INT, REGS);
- MULTI := ((REGS.AX AND $00FF) = $004D);
- end
- else
- MULTI := false;
- end;
- with XDATA do
- begin
- USER_BUF_ADDR.SEGMENT := SEG (DATA);
- USER_BUF_ADDR.OFFSET := OFS (DATA);
- USER_BUF_LEN := DATALEN;
- USER_FCB_ADDR.SEGMENT := SEG (POS);
- USER_FCB_ADDR.OFFSET := OFS (POS);
- USER_CUR_ADDR.SEGMENT := USER_FCB_ADDR.SEGMENT;
- USER_CUR_ADDR.OFFSET := USER_FCB_ADDR.OFFSET+38;
- USER_FUNCTION := OP;
- USER_KEY_ADDR.SEGMENT := SEG (KBUF);
- USER_KEY_ADDR.OFFSET := OFS (KBUF);
- USER_KEY_LENGTH := 255;
- USER_KEY_NUMBER := KEY;
- USER_STAT_ADDR.SEGMENT := SEG (STAT);
- USER_STAT_ADDR.OFFSET := OFS (STAT);
- XFACE_ID := VAR_ID;
- end;
-
- REGS.DX := OFS (XDATA);
- REGS.DS := SEG (XDATA);
-
- if (NOT MULTI) then
- INTR (BTR_INT, REGS)
- else
- begin
- DONE := FALSE;
- repeat
- REGS.BX := ProcId;
- REGS.AX := 1;
- if (REGS.BX <> 0) then
- REGS.AX := 2;
- REGS.AX := REGS.AX + (MULTI_FUNCTION * 256);
- INTR (BTR2_INT, REGS);
- if ((REGS.AX AND $00FF) = 0) then
- DONE := TRUE
- else begin
- REGS.AX := $0200;
- INTR ($7F, REGS);
- DONE := FALSE;
- end;
- until (DONE);
- if (ProcId = 0) then
- ProcId := REGS.BX;
- end;
- DATALEN := XDATA.USER_BUF_LEN;
- end;
- BTRV := STAT;
- end;
- {$B-}
- {$V+}
-
- (* BRECMGR.INIT Constructor *)
- (* ------------------------ *)
- constructor TRecMgr.Init;
- var
- Counter : integer;
- BNumber,
- BRev : string[2];
- BProduct : string[1];
- begin
- TObject.Init; {assures all data fields zeroed}
- BStatus := Btrv(BVersion, VarPosBlk, Version, Counter, VarNotRequired, Zero);
- str(Version.Number:2, BNumber);
- BNumber := LTrim(BNumber);
- str(Version.Rev:2, BRev);
- BProduct := Version.Product;
- VersionString := BNumber + '.' + BRev + BProduct;
- end;
-
- (* BRECMGR.BT function *)
- (* ------------------- *)
- {Will not handle reset of other workstations as written, as no true key
- buffer is passed. Will handle begin/end/abort transaction, reset & stop.
- Would also handle version op, but is handled by BRecMgr.Init anyway!}
- function TRecMgr.BT(OpCode, Key: integer): integer;
- begin
- BT := Btrv(OpCode, VarPosBlk, VarNotRequired, VarNotRequired,
- VarNotRequired, Key);
- end;
-
- (* BRECMGR Destructor *)
- (* ------------------ *)
- destructor TRecMgr.Done;
- begin
- TObject.Done;
- end;
-
- (* BFILE.INIT Constructor *)
- (* ---------------------- *)
- constructor BFile.Init(UserFileName:string; OpenMode: integer);
- const
- FileBufLen : integer = 400; KeyBufLen : integer = 384;
- var
- Counter, Status : integer;
- NumRecsWord1,
- NumRecsWord2 : word;
- begin
- TObject.Init; {assures all data fields zeroed}
- ConvertName(UserFileName); {Sets fields DFileName and FileName}
- Status := Open(OpenMode);
- if Status = 0 then {if open op successful, do a stat op}
- begin
- Status := Btrv(BStat, PosBlk, Specs.SpecBuf, FileBufLen, KeyBufLen,
- Zero);
- {Btrieve filespecs and key specs are now in the BFile object!}
- if Status = 0 then {if stat successfull, fill object data fields}
- begin
- NumRecsWord1 := Specs.NumRecs[1]; {get rid of sign bit!! by }
- NumRecsWord2 := Specs.NumRecs[2]; {converting 2 ints to words}
- NumRecs := NumRecsWord1 + NumRecsWord2 * 65536;
- NumSegs := Specs.NumKeys;
- for Counter := 0 to 23 do
- if (Specs.KeyArray[Counter].KeyFlags and Segmented) =
- Segmented then inc(NumSegs);
- DBufferLen := Specs.RecLen;
- BStatus := 0; {all went well, return a code 0}
- end
- else
- begin
- BStatus := Status; {Open op succeeded but stat failed; put }
- Status := Close; {error code for bad stat in global var and}
- end; {close the damn file quick!}
- end
- else
- BStatus := Status; {assign err code for bad open to global var}
- end;
-
- (* BFILE.BT function *)
- (* ----------------- *)
- function BFile.BT(OpCode, Key: integer): integer;
- begin
- Abstract;
- end;
-
- (* BFILE.OPEN function *)
- (* ------------------- *)
- function BFile.Open(OpenMode: integer):integer;
- begin
- Open := Btrv(BOpen, PosBlk, VarNotRequired, Specs.RecLen, FileName, OpenMode);
- end;
-
- (* BFILE.CLOSE Function *)
- (* -------------------- *)
- function BFile.Close:integer;
- begin
- Close := Btrv(BClose, PosBlk, VarNotRequired, VarNotRequired,
- VarNotRequired, NotRequired);
- end;
-
- (* BFILE.DONE Destructor *)
- (* --------------------- *)
- destructor BFile.Done;
- begin
- TObject.Done;
- end;
-
- (* BFILE.CONVERTNAME Procedure *)
- (* --------------------------- *)
- {this one is private to BFile}
- procedure BFile.ConvertName(UserFileName: string);
- var Counter : integer;
- begin
- DFileName := UserFileName;
- if length(UserFileName) > 79 then
- DFileName[0] := chr(79); {force short to 79 if needed}
- for Counter := 1 to length(DFileName) do {convert string to array}
- FileName[Counter] := DFileName[Counter];
- FileName[Counter + 1] := ' '; {provide required pad char}
- end;
-
- (* BFIXED.INIT Constructor *)
- (* ----------------------- *)
- constructor BFixed.Init(UserFileName:string; OpenMode: integer);
- begin
- BFile.Init(UserFileName, OpenMode);
- end;
-
- (* BFIXED.BT function *)
- (* ----------------- *)
- function BFixed.BT(OpCode, Key: integer): integer;
- begin
- BT := Btrv(OpCode, PosBlk, DBuffer, Specs.RecLen, KBuffer, Key);
- end;
-
- (* BFIXED.DONE Destructor *)
- (* ---------------------- *)
- destructor BFixed.Done;
- begin
- BFile.Done;
- end;
-
- (* TFILTERSPEC.INITF Constructor *)
- (* ----------------------------- *)
- {Be sure to remember that the offset parameter here is 0 relative to start of
- record!!}
- constructor TFilterSpec.InitF(FieldType: byte; FieldLen, Offset: integer;
- CompCode, Expression: byte; FieldComp: boolean;
- CompOffset: integer);
- begin
- TObject.Init; {assures all data fields zeroed}
- LogicTerm.FieldType := FieldType;
- LogicTerm.FieldLen := FieldLen;
- LogicTerm.Offset := Offset;
- LogicTerm.CompCode := CompCode;
- LogicTerm.Expression := Expression;
- LogicTerm.FieldComp := FieldComp;
- LogicTerm.CompOffset := Offset;
- end;
-
- (* TFILTERSPEC.INITV Constructor *)
- (* ----------------------------- *)
- {Be sure to remember that the offset parameter here is 0 relative to start of
- record!!}
- constructor TFilterSpec.InitV(FieldType: byte; FieldLen, Offset: integer;
- CompCode, Expression: byte; FieldComp: boolean;
- Value: TCharArray);
- begin
- TObject.Init; {assures all data fields zeroed}
- LogicTerm.FieldType := FieldType;
- LogicTerm.FieldLen := FieldLen;
- LogicTerm.Offset := Offset;
- LogicTerm.CompCode := CompCode;
- LogicTerm.Expression:= Expression;
- LogicTerm.FieldComp := FieldComp;
- LogicTerm.Value := Value;
- end;
-
- (* TFILTERSPEC.DONE Destructor *)
- (* --------------------------- *)
- destructor TFilterSpec.Done;
- begin
- TObject.Done;
- end;
-
- (* TEXTSPEC.INIT Constructor *)
- (* ------------------------- *)
- constructor TExtSpec.Init(Len, Ofs: integer);
- begin
- TObject.Init; {assures all data fields zeroed}
- ExtRepeater.FieldLen := Len;
- ExtRepeater.Offset := Ofs;
- end;
-
- (* TEXTSPEC.DONE Destructor *)
- (* ----------------------- *)
- destructor TExtSpec.Done;
- begin
- TObject.Done;
- end;
-
- (* BFILEEXT.INIT Constructor *)
- (* ------------------------- *)
- {always check for a failure!}
- constructor BFileExt.Init(UserFileName: string; OpenMode: integer);
- begin
- BFile.Init(UserFileName, OpenMode);
- Header.Constant[1] := 'E';
- Header.Constant[2] := 'G';
- ExtDBuffer := memallocseg(MaxExtDBufferLength);
- FilterSpec := new(PCollection, Init(2,2));
- ExtractorSpec := new(PCollection, Init(5,2));
- if (ExtDBuffer = nil) or (FilterSpec = nil) or (ExtractorSpec = nil) then
- Fail;
- end;
-
- (* BFILEEXT.DONE Destructor *)
- (* ------------------------ *)
- destructor BFileExt.Done;
- begin
- BFile.Done;
- dispose(ExtDBuffer);
- dispose(ExtractorSpec, Done);
- dispose(FilterSpec, Done);
- end;
-
- (* BFILEEXT.SetExtDBufferLen *)
- (* ------------------------- *)
- {Compute sizes of data buffers sent and returned, to determine proper size to
- specify in call.}
- {Assumes user program has inserted proper items into the collections for
- filter terms and extractor specs.}
- procedure BFileExt.SetExtDBufferLen;
- var
- LengthSent, LengthReturned,
- RecordLengthReturned, RecordImageReturned : integer;
-
- procedure MakeFilterSpecs;
- procedure CalcFilterLengths(FSpec: PFilterSpec); far;
- begin
- with FSpec^ do
- begin
- inc(LengthSent, 7);
- if (LogicTerm.CompCode and UseField) = UseField then
- inc(LengthSent, 2)
- else
- LengthSent := LengthSent + LogicTerm.FieldLen;
- end;
- end;
- begin
- FilterSpec^.ForEach(@CalcFilterLengths);
- end;
-
- procedure MakeExtSpecs;
- procedure CalcExtLengths(ExtSpec: PExtSpec); far;
- begin
- with ExtSpec^ do
- begin
- inc(LengthSent, 4);
- RecordLengthReturned := RecordLengthReturned + ExtRepeater.FieldLen;
- end;
- end;
- begin
- ExtractorSpec^.ForEach(@CalcExtLengths);
- end;
-
- begin
- LengthSent := 8; {4 for header length, 4 for fixed filter length}
-
- {Work on filter logic term portion of spec.}
- if FilterSpec^.Count > 0 then {if any filter terms in the collection}
- MakeFilterSpecs;
-
- {Work on extractor portion of spec.}
- inc(LengthSent, 4); {size of fixed part of extractor}
- RecordLengthReturned := 0;
- MakeExtSpecs; {there must always be at least 1 extractor spec}
-
- {2 for count of recs, 4 for currency pos}
- RecordImageReturned := RecordLengthReturned + 6;
- {2 for count of recs}
- LengthReturned := 2 + (RecordImageReturned * Extractor.NumRecords);
-
- Header.DBufferLen := LengthSent;
-
- if LengthSent >= LengthReturned then
- DBufferLen := LengthSent
- else
- DBufferLen := LengthReturned;
- end;
-
- (* BFILEEXT.MAKEEXTDBUFFER Function *)
- (* -------------------------------- *)
- {Private to BFileExt, called in BFileExt.BT, which is called by each
- descendant's override of BFileExt.BT. Assumes program has already set up
- the collections required.}
- procedure BFileExt.MakeExtDBuffer;
- var
- Offset : integer;
-
- procedure MoveFilterSpecs;
- procedure MoveSingleFilterSpec(FSpec: PFilterSpec); far;
- begin
- with FSpec^ do
- begin
- {move fixed part of logic term}
- move(LogicTerm, ExtDBuffer^.Entire[Offset], 7);
- {now need to move variable part of logic term}
- inc(Offset, 7);
- if (LogicTerm.CompCode and UseField) = UseField then
- begin
- move(LogicTerm.CompOffset, ExtDBuffer^.Entire[Offset],
- sizeof(LogicTerm.CompOffset));
- Offset := Offset + sizeof(LogicTerm.CompOffset);
- end
- else
- begin
- move(LogicTerm.Value, ExtDBuffer^.Entire[Offset],
- LogicTerm.FieldLen);
- Offset := Offset + LogicTerm.FieldLen;
- end;
- end;
- end;
- begin
- FilterSpec^.ForEach(@MoveSingleFilterSpec);
- end;
-
- procedure MoveExtractorSpecs;
- procedure MoveSingleExtractorSpec(ExtSpec: PExtSpec); far;
- begin
- with ExtSpec^ do
- begin
- move(ExtSpec^.ExtRepeater, ExtDBuffer^.Entire[Offset],
- sizeof(ExtSpec^.ExtRepeater));
- Offset := Offset + sizeof(ExtSpec^);
- end;
- end;
- begin
- ExtractorSpec^.ForEach(@MoveSingleExtractorSpec);
- end;
-
- begin
- {Move header definition into buffer.}
- move(Header, ExtDBuffer^.Header, sizeof(Header));
-
- {Move fixed part of filter definition into buffer.}
- move(Filter, ExtDBuffer^.Filter, sizeof(Filter));
- Offset := 1 + sizeof(Header) + sizeof(Filter);
-
- {Read filter logic terms into buffer.}
- if FilterSpec^.Count > 0 then
- MoveFilterSpecs;
-
- {Move fixed part of extractor definition into buffer.}
- move(Extractor, ExtDBuffer^.Entire[Offset], sizeof(Extractor.Entire));
- Offset := Offset + sizeof(Extractor.Entire);
-
- {Move extractor terms into buffer.}
- MoveExtractorSpecs;
- end;
-
- (* BFILEEXT.BTExt function *)
- (* ----------------------- *)
- {In overrides of this function in BFileExt descendants, MUST call
- BFileExt.BTExt, as it sets the buffer length in the header, and puts
- together the 'send' buffer. User program MUST have inserted filter logic
- terms and extractor specs into their respective collections before making
- a Btrieve call.}
- function BFileExt.BTExt(OpCode, Key: integer): integer;
- begin
- SetExtDBufferLen;
- MakeExtDBuffer;
- end;
-
-
- (* CREATE FILE function *)
- (* -------------------- *)
- {Assumes a PFILETYPE variable has been instantiated and assigned its values.}
- {No specific support for null keys, alt col, blank compression, pre-alloc or
- data-only files}
- function CreateFile(UserFileName:string; UserFileSpec:PFileSpec): integer;
- var
- PosBlk : array[1..128] of char;
- CFSpecLength,
- Counter,
- Counter1 : integer;
- BtrieveFileName : BFileName;
- begin
- if length(UserFileName) > 79 then
- UserFileName[0] := chr(79); {force short to 79 if needed}
- for Counter := 1 to length(UserFileName) do {convert string to array}
- BtrieveFileName[Counter] := UserFileName[Counter];
- BtrieveFileName[Counter + 1] := ' '; {provide required pad char}
- CFSpecLength := 16 + (UserFileSpec^.NumKeys * 16);
- {now add 16 to CFSpecLength for every segmented key}
- for Counter := 0 to 23 do
- if (UserFileSpec^.KeyArray[Counter].KeyFlags and Segmented) = Segmented then
- CFSpecLength := CFSpecLength + Segmented;
- UserFileSpec^.Reserved[1] := chr(0);
- UserFileSpec^.Reserved[2] := chr(0);
- CreateFile := Btrv(BCreate, PosBlk, UserFileSpec^.SpecBuf, CFSpecLength,
- BtrieveFileName, Zero);
- end;
-
- {LTrim and RTrim were taken from one of the Turbo Vision .PAS source files!}
- function LTrim(S: String): String;
- var
- I: integer;
- begin
- I := 1;
- while (I < length(S)) and (S[I] = ' ') do inc(I);
- LTrim := copy(S, I, 255);
- end;
-
- function RTrim(S: String): String;
- var
- I: integer;
- begin
- while S[Length(S)] = ' ' do dec(S[0]);
- RTrim := S;
- end;
-
-
- (* IS BTRIEVE LOADED procedure *)
- (* --------------------------- *)
- {this is private to the unit, and is executed only during unit initialization}
- procedure IsBtrieveLoaded;
- var
- VarPosBlk : array[1..128] of char;
- begin
- BStatus := Btrv(BReset, VarPosBlk, VarNotRequired, VarNotRequired,
- VarNotRequired, Zero);
- if BStatus = 20 then
- begin
- writeln('Please load Btrieve before running this program.');
- halt;
- end;
- end;
-
-
- (* INITIALIZATION Section *)
- (* ----------------------------------------------------------------------- *)
- begin
-
- IsBtrieveLoaded;
-
- end.
-
-