INTRODUCTION Btv.pas is a fully object oriented Turbo Pascal 6.0,7.0 programming interface for Novell's Btrieve database manager. Through OOP techniques Btv.pas greatly simplifies the interface to Btrieve for Turbo Pascal programs. Included in this package are full working examples that demonstrate the ease and power of the BTV interface. Also included is a complete application for recovering damaged files. Just a few of the features are : * Over 40 functions for Btrieve * Create, easy file definition and creation * Clone, create an empty copy of a file * Recover, recover records from a damaged file * Save, save all records to a DOS file compatible with BUTIL * Load, read records from a file created by Save or BUTIL * Create Supplemental Indexes * Supports multiple and segmented keys * Supports alternate collating sequences * Supports variable length records * Automatic padding and justification of string keys * Supports full transaction processing * Supports full network record and file locking * Automatic integrated error handling * Supports DOS, Windows, and Protected Mode programs * Encapsulates extended operations In writing this documentation I have assumed the reader is knowledgeable about the workings of Btrieve and the basics of object oriented programming in Turbo Pascal. This document is not meant to explain or serve as a tutorial on either of these subjects. I think you will find the source code itself fairly well documented. I strongly recommend that you look it over. If you have any questions, suggestions for improvement, or problems, please do not hesitate to contact me. Richard Hansen PO Box 18571 Saint Paul, MN 55118-0571 USA CompuServe : 70242,3367 Internet : 70242.3367@compuserve.com Fido Net : 1:282/115 If you need more information on Btrieve, you may want to get a copy of the following book: "The Ilustrated Guide to Btrieve" ISBN 0-9623397-7-6 MIDI America 2103 N. Decatur Rd., Suite 160 Decatur, GA 30033 USA (404) 634-3334 Btv.pas Copyright 1992 Richard W. Hansen, all rights reserved. Btrieve Copyright Novell, Inc. Butil Copyright Novell, Inc. DEFINITION OF SHAREWARE Shareware distribution gives users a chance to try software before buying it. If you try a Shareware program and continue using it, you are expected to register. Individual programs differ on details -- some request registration while others require it, some specify a maximum trial period. With registration, you get anything from the simple right to continue using the software to an updated program with printed manual. Copyright laws apply to both Shareware and commercial software, and the copyright holder retains all rights, with a few specific exceptions as stated below. Shareware authors are accomplished programmers, just like commercial authors, and the programs are of comparable quality. (In both cases, there are good programs and bad ones!) The main difference is in the method of distribution. The author specifically grants the right to copy and distribute the software, either to all and sundry or to a specific group. For example, some authors require written permission before a commercial disk vendor may copy their Shareware. Shareware is a distribution method, not a type of software. You should find software that suits your needs and pocketbook, whether it's commercial or Shareware. The Shareware system makes fitting your needs easier, because you can try before you buy. And because the overhead is low, prices are low also. Shareware has the ultimate money-back guarantee -- if you don't use the product, you don't pay for it. DISCLAIMER - AGREEMENT Users of Btv.pas must accept this disclaimer of warranty: "Btv.pas is supplied as is. The author disclaims all warranties, expressed or implied, including, without limitation, the warranties of merchantability and of fitness for any purpose. The author assumes no liability for damages, direct or consequential, which may result from the use of Btv.pas." Btv.pas is "shareware" and is provided at no charge to the user for evaluation. Feel free to share it with your friends, but do not give it away altered or as part of any other source code package. If you find this source code useful and continue to use Btv.pas after a reasonable trial period, you must register it. The registration fee will license one copy for use on any one computer at any one time. You must treat this software just like a book. An example is that this software may be used by any number of people and may be freely moved from one computer location to another, so long as there is no possibility of it being used at one location while it's being used at another. Just as a book cannot be read by two different persons at the same time. Commercial users of Btv.pas must register and pay for their copies of Btv.pas within 30 days of first use or their license is withdrawn. You may use Btv.pas in your software projects, but you may only distribute it in executable form. No royalties are required for programs you develop using licensed copies of Btv.pas. Anyone distributing Btv.pas for any kind of remuneration must first contact Richard Hansen for authorization. This authorization will be automatically granted to distributors recognized by the ASP as adhering to its guidelines for shareware distributors, and such distributors may begin offering Btv.pas immediately (However Richard Hansen must still be advised so that the distributor can be kept up-to-date with the latest version of Btv.pas.). REGISTRATION You may register by check, money order, credit card, or online on the CompuServe information service. All registrations are $50.00 plus $5.00 shipping and handling. Registered users get the latest version, printed documentation, full source for all BTV.PAS units, and the full version of the Btrieve message file "BTRIEVE.MSG" that contains all Btrieve error and operation code messages. Checks or money orders are prefered. If paying in U.S. dollars, the check must be drawn on a drawn on a U.S. bank. You can also register online on CompuServe. Type GO SWREG, and follow the prompts. The Registration Id for CompuServe is 759. All Compuserve registrations are $55.00, including shipping and handling. You may place an order by Master Card, VISA, American Express, or Discover by contacting Public Software Library at (800) 242-4PSL (from overseas (713) 524-6394), by FAX at (713) 524-6398, or on CompuServe at 71355,470. These numbers are for credit card orders only! Please, do not call these numbers for any type of technical assistance. The Registration Id for PSL is 10905. All PSL registrations are $55.00, including shipping and handling. Site licenses and multiple copy discounts are available. Remember a registered copy is required for each programmer using BTV.PAS. Please contact me with any comments, suggestions, problems, bugs, or questions. Richard Hansen PO Box 18571 Saint Paul, MN 55118-0571 USA CompuServe : 70242,3367 InterNet : 70242.3367@compuserve.com FidoNet : 1:282/115 OVERVIEW There are three objects that make up the BTV OOP interface to Btrieve. The most important of these is the BtrieveFile object. BtrieveFile contains all the routines for opening and creating files, reading, writing and deleting records, etc. BtrieveFile contains a pointer to a data buffer that can be automatically allocated and deallocated by the object if you desire. Next, is the ErrorHandler object, this object controls error handling for the file. Most Btrieve error may be turned on or off for trapping by the error handler object (Note: With the release of the Windows version of Btrieve, all errors will longer fit in a set of 0..255). This frees you from the need to check for errors after each operation, but still allows for full error processing. Each file object has a pointer to an error handler, this error handler can be the same or different for each file you open. If an error is turned on the error handler will call an error display routine, and based on a return code from it, will continue, abort, or retry an operation. Last, there is the DisplayObject. This object handles the display of any errors encountered. It is called by the error handler, and returns an action code, possibly based on some user response, to the error handler. This action code will cause the error handler to either abort the program, retry the operation, or continue processing. Target Platform IMPORTANT PLEASE NOTE!!!!! BTV.PAS is compatible with DOS, Windows, and protected mode programs. Your code should compile without changes, at least for Btrieve access, for any of the three targets. All necessary compilation changes are handled by IFDEF conditional compilation directives in the source code. The IFDEFs work in conjunction with the standard Borland Pascal conditional symbols of VER70, MSDOS, WINDOWS, and DPMI. You do not need to define any of these symbols. With Borland Pascal 7.0, for future compatibility, you may want to replace the DOS unit with the WINDOS unit. There is a small problem with the protected mode version. BTV.PAS compiles but does not run correctly under the 7.0 release, dated 10/27/92. BTV.PAS does, however, compile and run fine under the 7.01 maintenance release, dated 03/09/93. The 7.01 update is available from Borland International for $10.00. Please contact Borland International for more details. Declarations const bOpen = 0; bGetKey = 50; These constants define all the available Btrieve operations. bOkay = 0; ... bLastError = bInternalTTSerr; These define all the status codes returned by Btrieve. In addition there are constants for file open modes, locking, key types, file flags, etc. MaxSegments = 24; Defines the maximum total number of key segments allowed for file. If none of your files will ever have this many segments then redefine it to some smaller size and save a few bytes of memory. MaxBuffSize : Word = 16 * 1024; This initialized variable defines the maximum size that will be automatically allocated for a file data buffer. There is no need to redefine this if you are using fixed length records, since only as much memory as needed will actually be allocated. If you are using variable length records and are sure they will be smaller than 16K bytes, then you can redefine this as needed before opening the file. {.$DEFINE BCHECK} If this compiler directive is defined, a check for Btrieve will be made during program initialization. If the record manager is not present the program will be halted. {.$DEFINE BTRIEVE50} Define this to make all opcodes new to Btrieve version 5.0 available. type PProgress = ^TProgress; TProgress = Object Constructor Init; Procedure Display(Count : LongInt); Virtual; end; Defines an object with a method to display the progress of Recover, Load and Save operations. Count is the current record count, the display routine will be called every ten records. AllErrors = bInvalidOp..bLastError; ErrorSet = Set of AllErrors; These two define a set of most possible Btrieve errors. Note: With the introduction of Btrieve for Windows, some status codes are greater than 255, and will not fit in the normal error set. ErrorAction = (erAbort, erDone, erRetry); Enumerates the possible responses to a Btrieve error. One of these three actions must be returned by your error display routine. If erAbort is returned the program will be halted, if erDone is returned the program will continue, if erRetry is returned the Btrieve operation that generated the error will be executed again. PErrorDisplay = ^ErrorDisplay; ErrorDisplay = Object Constructor Init; Destructor Done; Virtual; Function Display(Error : Integer; ErrorMsg : String; OpCode : Integer; OpCodeMsg : String; FileName : PathStr ): ErrorAction; Virtual; end; ErrorDisplay is the object that will display errors to the user. This is an ABSTRACT object and can never be used as is, you must define a descendant object that does what you want in each program. The error handler will pass an error number, error description, operation, operation description, and the full file path to your object. Your object should display the error and return an action code. This action code can be based on user input, or the type of error and operation. PErrorHandler = ^ErrorHandler; ErrorHandler = Object RetryCount : Word; MaxRetry : Word; RetryDelay : Word; TrappedErrors : ErrorSet; ErrDisplay : PErrorDisplay; ErrorsON : Boolean; Constructor Init(DisplayObject : PErrorDisplay); Destructor Done; Virtual; Procedure AddErrors(ErrorCodes : ErrorSet); Procedure ClearRetry; Function ErrorDispacther(ErrorCode : Integer; OpCode : Integer; FileName : PathStr): ErrorAction; Virtual; Function Error(Status : Integer; OpCode : Byte; FileName : PathStr): Boolean; Virtual; Function ErrorMsg(ErrorCode : Integer): String; Virtual; Procedure ErrorsOnOff(State : Boolean); Function GetDelay: Word; Procedure GetErrors(var ErrorCodes : ErrorSet); Function GetMaxRetry: Word; Function OpMsg(OpCode : Integer): String; Virtual; Procedure RemoveErrors(ErrorCodes : ErrorSet); Procedure SetDelay(Seconds : Word); Procedure SetErrors(ErrorCodes : ErrorSet); Procedure SetMaxRetry(Retry : Word); end; This is the error handler object used to trap Btrieve errors. It can be used as defined, but returns minimal error messages. Most errors can be set to be trapped or not by the error handler. By default all errors except end of file are trapped. All trapped errors will be routed through the error display object assigned to the handler when it is initialized. Untrapped errors must be handled directly in your program code. NOTE: With the introduction of Btrieve for Windows, some status codes are greater than 255, and will not fit in the error set. Since they cannot be toggled singly, you should call ErrorsOnOff to remove error trapping for those errors greater than 255. ErrorHandler is the parent object for the DefErrorHandler and DiskErrorHandler objects. DefErrorHandler holds all error messages in memory, while DiskErrorHandler keeps them in a Btrieve file. Normally, you would want to use either a DefErrorHandler or DiskErrorHandler to have descriptive error messages. Locking errors (record in use, file in use) are a special case. These errors, which happen only on networked systems, automatically cause the operation to be retried a preset number of times. No error will be generated until the maximum number of retries, set by you, have been attempted. This feature can save some programming work on your part if you are writing an application that uses the networked version of Btrieve. If this all sounds complicated, don't worry, it really isn't that bad. Please take a look at the example code to see how easy it is to setup the error handling. My feelings on error checking are that the more automatic it is the better. In Btv.pas a little work up front leads to considerably less coding later. You only need to do this stuff once, no matter how many files you open. Once you get the error handling setup, you can pretty much forget about it in the rest of your program. It gets even easier if you create a standard error handling Unit and reuse it in all your programs. PBtrieveFile = ^BtrieveFile; The BtrieveFile object is the heart of Btv.pas. It contains all the routines for manipulating Btrieve files. It is a fairly complex object; but, it greatly simplifies your interaction with Btrieve files. You will create one of these objects for each file you want to access in a program. To open a file, you execute two object methods. First, you init the object passing a file path, an error handler (can be nil), and a pointer to a data buffer and the data buffer size. Any number of files can share a single error handler. If you pass a nil pointer for the data buffer, a buffer will be allocated for you. Next, you call Open with an open mode (Read Only, Exclusive, or Accelerated ) and file owner name. Creating a file is almost as easy. Init is called the same as for Open. Next, for each key segment needed, you execute the AddKeySegment method passing the key position, size, key type, etc. This will define each key segment you need for the file. After all keys are defined make a call to Create. This method takes the file flags, record size, page size, etc. as parameters and Creates a new file. Create does not open the file, so finish off with a call to the Open method. Reading and writing records is just as simple. For a read by key you must first make a call to MakeKey, to build the key buffer. Then call Get, supplying the opcode for the type of read you want and the locking state. The data will be passed back in the file buffer setup on initialization. For the step operation you just call Get passing the correct opcode. If you want to maintain your own key buffer, you can do that too. After initializing the file, but before opening it, add your external key buffer by calling AddKeyBuffer. Once you call AddKeyBuffer, no calls to MakeKey are needed and none should be made. Before a key read, you just fill your key buffer as needed and call Get. To write a new record, fill the buffer you setup and execute the Insert method. To change a record, first read it with a call to Get. Make any changes to the buffer and call Update. Procedure CheckForBtrieve; This global system level procedure can be called to check for the presence of Btrieve. It halts the program if Btrieve is not loaded. This is the same routine called during program initialization, if that feature is enabled (if BCHECK is defined). GetBtrieveVersion(..); Is a global system level procedure for determining the Btrieve version number. UnloadBtrieve; This is another global system level procedure. It can be called to unload the Btrieve Record Manager. Like the other global procedures, it can be called without creating a BtrieveFileObject. BtrieveFile OBJECT ============================================================================== This is the main object in BTV.PAS. It is a fully fuctional Btrieve file object. BtrieveFile is the parent object for XBtrieveFile, which handles Btrieve extended IO operations. Fields ------------------------------------------------------------------------------ AllocateData AllocateData : Boolean; This field is set by Init and used by Open and Done. If the data buffer pointer passed to Init is nil, AllocateData is set to TRUE and file buffer memory will be automatically allocated and deallocated. AllocateKey AllocateKey : Boolean; This field is set to TRUE by Init and used by Open and Done. If the AddKeyBuffer method is called AllocateKey is set to FALSE and key buffer memory will not be automatically allocated and deallocated. AltPath AltPath : PathStr; Holds the name and path of an alternate collating sequence for the file. BytesRead BytesRead : Word; Is the number of bytes input from the file on the last read operation. BytesToWrite BytesToWrite: Word; Holds the number of bytes in the buffer that will be output to the file on the next write operation. For fixed length records it defaults to the size of the file record and should not be changed. For variable length records it should be set before each record is written. You set the BytesToWrite by calling SetOutputSize. CurIndex Index : Word; CurIndex is the current Key number (access path) used for the reads and writes. CurrentKeySize CurrentKeySize : Byte; Used internally to find the largest key. Data Data : Pointer; Points to the file buffer. DataSize DataSize : Word; DataSize is the size of the file buffer pointed to by Data. ErrHandler ErrHandler : PErrorHandler; A pointer to the ErrorHandler object that will control all error checking. If ErrHandler is nil no error checking is done. FileOpen FileOpen : Boolean; Will be set to TRUE if the file is opened successfully. FillValue FillValue : Byte; FillValue is the value used to fill the data and key buffers in the ClearBuffer and ClearKey methods. IndexCount IndexCnt : Byte; Number of keys in the file. Key Key : Pointer; Points to the file key buffer. KeyList KeyList : KeyDefArray; Holds a definition record for each key segment in the file. KeySize KeySize : Byte; Size of the key buffer pointed to by KeySize. KeyStart KeyStart : Array[0..MaxSegments - 1] of Byte; Holds a list of the offsets of the first segment of each key. Path Path : PathStr; Path contains the name and path of the file. PosBlock PosBlock : Array[1..PosBlockSize] of Byte; The Btrieve position block. ReadKeyDefs ReadKeyDefs : Boolean; Indicates whether the key definitions have been setup manually or should be read from the file. SegmentCnt SegmentCnt : Byte; The total number of segments in all keys. Status Status : Integer; The status of the last Btrieve operation. VariableLen VariableLen : Boolean; Set to TRUE if the file holds variable length records. SISegments SISegments : Byte; Used in setting up a supplemental index. Methods ------------------------------------------------------------------------------ Init Constructor Init(FilePath : PathStr; var ErrorObject : PErrorHandler; DataBuf : Pointer; DataBufSize : Word); Initializes the file name and path, sets the pointer to the error handler object. If ErrorObject is nil no error checking is done, it is all up to the programmer in this case. If DataBuf is nil, then AllocateData is set to TRUE and memory for the file buffer will be allocated and deallocated automatically. The size of the data buffer allocated, depends on whether or not the file has variable length records. If the file has fixed length records, the data buffer is allocated to the exact size of the records in the file. If the file has variable length records, the data buffer is allocated to the value of the MaxBuffSize variable stored in the file BTVCONST.PAS. If DataBuf is not nil, then DataBufSize must be the size of the buffer pointed to by DataBuf. DataBuffSize must also be large enough to hold the largest record in the file, whether the file has fixed or variable length records. See Open, Create, Done, ErrorHandler object. Done Destructor Done; Virtual; If AllocateKey is TRUE, disposes of key buffer memory. If AllocateData is TRUE, disposes of the data buffer memory. See Init AbortTransaction Procedure AbortTransaction; Aborts the current Btrieve transaction. See EndTransaction, StartTransaction AddAltSequence Procedure AddAltSequence(AltSeqPath : PathStr); Defines an alternate collating sequence file that will be loaded and passed to Btrieve on during file creation. This method only needs to be called once, before Create if an alternate collating sequence is desired. AddAltSequence can also be call before adding a supplemental index. However; it should not be called before adding a supplemental index, if an alternate collating sequence was added when the file was created. See Create AddErrors Procedure AddErrors(ErrorCodes : ErrorSet); Call AddErrors to add a set of error codes to those handled by the file's error handler. Use it in conjunction with RemoveErrors to turn an error/on and off for automatic trapping. AddErrors just makes a call to the error handler AddErrors method, so it is here mostly for convenience. You could just as well add errors by dereferencing the ErrHandler pointer. But this is one of the most often made calls to the error handler. See RemoveErrors, ErrHandler, ErrorsOnOff, GetErrors, SetErrors, ErrorHandler AddKeyBuffer Procedure AddKeyBuffer(KeyBuf : Pointer; KeyBufSize : Byte); If you do not want to use MakeKey to setup your keys for file reads, you can use AddKeyBuffer to set up an external programmer defined key buffer. This external key buffer will generally be a record defined to match a key in the file. This external key buffer will be passed to Btrieve on all key reads. AddKeyBuffer must be called after Init, but before Open. After a key buffer is added it is the programmer's responsibility to make sure the key is setup properly before each file read. Once, you have called AddKeyBuffer, you CANNOT call MakeKey. The key buffer may be changed as needed by multiple calls to AddKeyBuffer. AddKeySegment Procedure AddKeySegment(Position : Word; Size : Word; Flags : Word; KeyType : Byte; NullValue : Byte; Justify : Byte); AddKeySegment is used to manually define keys for the file. When creating a file the keys must be setup by calls to AddKeySegment. Keys do not have to be defined before opening a file. On an Open if no calls to AddKeySegment have been made, then the key information will be read from the file itself. Except for Justify, the parameters are the same as defined by Btrieve. Position is the position of the segment in the file. It is the same as Btrieve expects, remember they start at one not zero. Size is the number of bytes in the key segment you are defining. Flags are the usual flags such as modifiable, duplicate, etc. KeyType can be any valid type understood by Btrieve. NullValue will normally be set to zero. Please check your Btrieve manual for more information on defining keys. Justify is a special parameter that makes the use of key strings simpler. Any string key segment can be automatically padded to the left or right with to its defined size. If Justify is set to bLJustify a string will be padded to it's full length with spaces. If Justify is bRJustify then a string key will be left padded to its defined size with spaces. Set Justify to bNormal to leave your key strings as passed. While this padding is not absolutely necessary, it does make strings easier to use. Since the same padding is done to the keys used to read from or write to the file, you will never need to worry about trailing or leading spaces on your string keys. A note about the Btrieve String type and justification. When justifying String keys, as opposed to LStrings or ZStrings, make sure to clear your key or data buffer to zeros. When you call MakeKey be sure to pass your key data in a zero filled buffer. This is especially important for right justified strings, so the end of the actual valid data can be found. The end of the string is considered any data byte that has a value less than 32. To define the keys for a file, just make repeated calls to AddKeySegment. Make one call for each segment needed. You must make these calls in order, just as if you were building the key data buffer directly. Add the segments that make up key one first, then the segments for key two, then the segments for key three, etc. The segments for each key must also be added in order, segment one, segment two, etc. The data will be stored in KeyList and passed to Btrieve on a Create. A typical call would look like : F.AddKeySegment(1,10, bModifiable + bExtended, bLstring, 0, False); This key starts at position 1 in the file, is modifiable, is a lstring and is the last segment in its key path, it has a null value of zero, and is not right justified. See bXXXXX constants, Create AddSupplKeySegment Procedure AddSupplKeySegment(Position : Word; Size : Word; Flags : Word; KeyType : Byte; NullValue : Byte; Justify: Byte); This functions the same as AddKeySegment but is used to define a supplemental index. You can only define one key at a time. See bXXXXX constants, CreateIndex, AddKeySegment bResult Function bResult: Integer; This function returns the last error status from Btrieve. Unlike the Turbo Pascal IoResult function; a call to bResult does not reset the status, so multiple calls can be made to this function. ChangeBufferSize Procedure ChangeBufferSize(Size : Word); This method should only be used for files with variable length records where the file buffer is allocated by the automatically by the BtrieveFile object. Use it in that rare instance when you need to change the size of the file buffer. See Data, Init ClearBuffer Procedure ClearBuffer; Clears the data buffer (the memory pointed to by the Data field). Uses FillValue to fill the buffer to its defined size. See ClearKey, SetFillValue ClearKey Procedure ClearKey; Clears the key buffer, (the memory pointed to by the Key field). Uses FillValue to fill the buffer to its defined size. See ClearBuffer, SetFillValue ClearOwner Procedure ClearOwner; If an owner has been assigned to a file, this method will clear it. The file must be opened before invoking this method. See SetOwner Clone Procedure Clone(NewFilePath : PathStr; Mode : Integer); Clone will create an empty copy of the file on the specified file path. Mode indicates whether the file should be over written if it already exists. See bXXXXX constants Close Procedure Close; Closes an open file. See Done Copy Function Copy(OutFile: PBtrieveFile; DisplayObj: PProgress): Integer; Copy all records to a new Btrieve file. OutFile is a pointer to the Btrieve output file. OutFile must be inited, but does not need to be opened. DisplayObj is a pointer to a method that can be called to display the progress of Copy. DisplayObj can be nil, in that case no calls will be made. If the input file is damaged, you should use Recover, not Copy to copy records. See Load, Recover, Save Create Procedure Create(Flags : Word; RecordSize : Word; PageSize : Word; Pages : Word; Mode : Integer); Create a new file. Flags are the normal Btrieve file flags such as truncate, variable length, or key only. RecordSize is the record size, or the size of the fixed length portion of a variable length record. PageSize is the page size you want for the file; as usual, it must be a multiple of 512 bytes, up to 4096 bytes. Pages is the number of pages Btrieve should preallocate to the file. Mode indicates whether the file should be over written if it already exists. A typical call could be : F.Create(bNormal, 100, 512, 0, bNoOverWrite); This file would have no special features like variable length records, is 100 bytes long, has a 512 byte page size, has no preallocated pages, and will not over write an existing file on the same path. NOTE: Before calling Create you must define ALL the keys by calling AddKeySegment. See bXXXXX constants, AddKeySegment, Init CreateIndex Procedure CreateIndex; Adds a new supplemental index to the file. First, you must set up the new index by calling AddSupplKeySegment. If you are adding more than one new index, create each one separately. See AddSupplKeySegment Delete Procedure Delete; Deletes the current record from the file. You must have previously read a record to set the current positioning. See Get, GetDirect DropIndex Procedure DropIndex(Index : Integer); Removes the supplemental index specified by the Index parameter from the file. EndTransaction Procedure EndTransaction; Ends the current Btrieve transaction. See AbortTransaction, StartTransaction Error Function Error(ErrStatus: Integer; OpCode : Byte; FileName : PathStr): Boolean; This method is intended mainly for internal use. If the error handler is not nil, Error just makes a call to its error handler's Error procedure. ErrorsOnOff Procedure ErrorsOnOff(State : Boolean); Toggles all error trapping on or off for the object. Calls ErrHandler^.ErrorsOnOff to set the current error trapping state. When error trapping is off, all error must be handled by the programmer. Note: With the introduction of Btrieve for Windows, some status codes are greater than 255, and will not fit in the error set. Since they cannot be toggled singly, you should call ErrorsOnOff to remove error trapping for these errors. See AddErrors, GetErrors, RemoveErrors, SetErrors FillKeyBuffer Procedure FillKeyBuffer(var Buff; Size : Byte); This method copies data directly into the key buffer. Buff points to a block of memroy to copy, Size is the number of bytes to copy to the key buffer. You may call this method instead of MakeKey. FixKeyStrings Procedure FixKeyStrings; Justifies all key strings when writing a record. Intended for BtrieveFile internal use only. Get Procedure Get(Op : Word; Lock : Word); Reads a record from the file. This procedure will execute get or step reads. Op is the type of read to attempt, such as equal to the key, greater than the key, less than the key, step first, step last, next record, or previous record. Lock is a standard Btrieve locking type. Please see your Btrieve manual for more information on record locking. If you are reading by key value, before calling Get, you must set up the key buffer. This can be accomplished by calling MakeKey or FillKeyBuffer, or through an external programmer defined key buffer. See bXXXXX constants, MakeKey, SetKeyPath, FillKeyBuffer, AddKeyBuffer GetDirect Procedure GetDirect(Lock : Word; Position : LongInt); Read a record from the file using a physical record position. Lock is a standard Btrieve locking type. Position is the position of the desired record, you should must get Position by a previous call to GetPosition. You may call SetKeyPath to establish the index that will be active after the read. Please see your Btrieve manual for more information on record locking. See bXXXXX constants, GetPosition, SetKeyPath GetErrors Procedure GetErrors(var ErrorCodes : ErrorSet); Returns the set of trapped error codes currently used by the error handler. See AddErrors, GetErrors, ErrorsOnOff, RemoveErrors, SetErrors, bXXXXX constants GetFillValue Function GetFillValue: Byte; Returns the current value used to clear the data and key buffers. GetPosition Function GetPosition: LongInt; Returns the position of the current record in the file. You must have previously read a record to establish positioning. Use the value returned as the Position parameter on a call to GetDirect. See Get, GetDirect Insert Procedure Insert; Adds a new record to the file. You must fill the file buffer and call this method. When writing variable length records be sure to set the actual number of bytes of data by a call to SetOutputSize. See SetOutputSize, Update IsOpen Function IsOpen: Boolean; Returns TRUE if the file is open. Load Function Load(InputFilePath : PathStr; DisplayObj : PProgress): Integer; Reads records from a DOS file and inserts them into the file. This operates the same as Butil with the -Load option. The file being read must be in the same format as Butil generates with the -Recover option. Load will read the files generated by the Save method. InputFilePath is the name of the DOS file to read from. DisplayObj is a pointer to a method that can be called to display the progress of Load. Recover. DisplayObj can be nil. Load will return a non-zero value if any errors occur. If there is an error, you can check the value of bResult to tell which file had a problem. If bResult returns zero, then the DOS file had an error. If the error returned is bLoadInputErr, then the DOS file is not in the correct format. See Save MakeKey Procedure MakeKey(V1 : Pointer; V2 : Pointer; V3 : Pointer; V4 : Pointer; V5 : Pointer; V6 : Pointer); Virtual; Use this method to build a key before reading a record. The V1..V6 parameters are the addresses of the data values that will make up the key. These parameters must be specified in the same order as in the current index. Six key parameters should be enough for most situations, but you can easily override MakeKey to provide for more or less. Any unused parameters should be passed with a value of nil. A typical call might be : F.MakeKey(@State, @City, nil, nil, nil, nil); This call sets up a key made of two segments. It passes nil pointers for the four unused segment parameters. You may need to call SetKeyPath to establish the index that you want to use. See AddKeyBuffer, SetKeyPath, bXXXXX constants NumberOfRecords Function NumberOfRecords: LongInt; Returns the NumberOfRecords, actually depending on version, this may really be the largest number of records ever in the file. Open Procedure Open(Mode : Integer; Owner : String); Opens the file. Mode is the file access mode such as accelerated, exclusive, read only or verify. It will normally be set to zero. Owner is the eight character file owner name (password). Unless you have set an owner name with a call to SetOwner, this should be a null string. See bXXXXX constants, SetOwner, Init Recover Function Recover(NewFilePath: PathStr; DisplayObj: PProgress): Integer; Recover writes the contents of the file to a DOS file. For optimum results the file should be opened in Read Only mode. NewFilePath is the name of the DOS file to create. DisplayObj is a pointer to a method that can be called to display the progress of Recover. DisplayObj can be nil, in that case no calls will be made. This method operates the same as Butil with the -Recover option. The file being written is in the same format as Butil needs for its -Load option. Recover will return a non-zero value if any errors occur. If there is an error, you can check the value of bResult to tell which file had a problem. If bResult returns zero, then the DOS file had an error. See Copy, Load, Save RemoveErrors Procedure RemoveErrors(ErrorCodes : ErrorSet); Use RemoveErrors to remove a set of error codes from those handled by the file's error handler. Use it in conjunction with AddErrors to turn an error on and off for automatic trapping. RemoveErrors just makes a call to the error handler RemoveErrors method, so it is here mostly for convenience. You could just as well remove errors by dereferencing the ErrHandler pointer. But this is one of the most often used calls for the error handler. See AddErrors, ErrorsOnOff, ErrHandler, SetErrors, ErrorHandler, bXXXXX constants Reset Procedure Reset; Resets all resources held by a workstation. ResetStation Procedure ResetStation(Connection : Word); Resets all resources held by a workstation. Connection is the Netware connection number for the desired station. Save Function Save(NewFilePath : PathStr; DisplayObj : PProgress): Integer; Writes all the records that can be read to a DOS file. The file should be opened in Read Only mode. This method operates the same as Butil with the -Recover option. The file being written is in the same format as Butil needs for its -Load option. Save generates a file that can be read by the Load method. NewFilePath is the name of the DOS file to create. DisplayObj is a pointer to a method that can be called to display the progress of Save. DisplayObj can be nil, in that case no call will be made. Save will return a non-zero value if any errors occur. If there is an error, you can check the value of bResult to tell which file had a problem. If bResult returns zero, then the DOS file had an error. See Copy, Load, Recover SetErrors Procedure SetErrors(ErrorCodes : ErrorSet); Set the trapped errors currently used by the error handler. See AddErrors, ErrorsOnOff, GetErrors, RemoveErrors, SetErrors, bXXXXX constants SetFillValue Procedure SetFillValue(Value : Byte); Sets current value used to clear the data and key buffers. SetKeyPath Procedure SetKeyPath(Number : Word); Sets the key number (access path) that will be used for all reads and writes. SetOutputSize Procedure SetOutputSize(Size : Word); SetOutputSize sets the length of the data buffer before writing a record to the file. The data buffer size defaults to the size of the record defined in the file. It is only necessary to call SetOutputSize for variable length records. SetOwner Procedure SetOwner(Owner : String; Mode : Integer); Owner is the eight character file owner name. Mode is the security restrictions desired on future access to the file. Please consult your Btrieve manual for more information on these restrictions. See bXXXXX constants, ClearOwner StartTransaction Procedure StartTransaction(Lock : Word); Start a Btrieve transaction. See AbortTransaction, EndTransaction Stat Procedure Stat(var FData : FileSpec); Returns the file statistics. Unload Procedure Unload; Unloads Btrieve from memory. UnlockAll Procedure UnlockAll(Lock : Word); Unlocks all locked records in the file. Lock identifies the type of locks that are active. Less than or equal to 200 indicates single locks, greater than 200 indicates multiple record locks. Please see your Btrieve manual for more information on record locking. See bXXXXX constants Update Procedure Update; Updates an existing record in the file. When writing variable length records be sure to set the actual number of bytes of data by a calling SetOutputSize first. See SetOutputSize, Insert Version Procedure Version(var Ver : Word; var Rev : Word; var OSFlag : Char); Returns the Btrieve version number that is running. Ver is the full version number, Rev is the revision number, OSFlag indicates the operating system. XBtrieveFile OBJECT ============================================================================== XBtrieveFile is a direct descendant of the BtrieveFile object. XBtrieveFile implements functionality for the Extended Get, Step, and Insert operations. These extended operation are only available with Btrieve version 5.10 and greater. Extended Gets and Steps can be complicated to setup. For best results, you should read the Btrieve documentation. After that, experiment a little to see how Extended Gets work. A couple things to remember, field offsets for extended gets are always zero based and you must always have valid file positioning established before you execute an XGet. This means that some type of read operation must have been performed prior to calling XGet. At the minimum, a Get First, Step First, Get Last, or Step Last should have been done. You may want to do a read that will set positioning to the record just before/after the first record you desire. This will help to keep you from exceeding your maximum reject count. The "and" and "or" operators used in a filter with the Btrieve extended get and step operations are interpreted in strict left to right order. Take, for example, the following file which contains records of first and last names that will return a different set of records with an extended get depending on the order of the operators: RECORDS: Sally Fields Fred Fields Fred Smith Sally Jones Sally Smith Fred Jones FILTER AND RECORDS RETURNED (with key path = FN): FN=Fred and LN=Smith or FN=Sally FN=Sally or FN=Fred and LN=Smith returns: returns: Fred Smith Fred Smith Sally Fields Sally Jones Sally Smith Btrieve evalutates an expression in the filter. If the expression when applied to the current record is true and the next operator is an 'or', this record is accepted as meeting the filter condition. If the expression is true and the next operator is an 'and', Btrieve will continue to evaluate each expression until an 'or' is reached, or one of the expressions evaluates to false, or the end of the filter. If an expression is false and the next operator is an 'and', the record is rejected. If the expression is false and the next operator is 'or' Btrieve will continue and evaluate with the next expression in the filter. Current Expression Next Operator Action ------------------ ------------- ------ True or Accept False or Continue True and Continue False and Reject True (end) Accept False (end) Reject The general calling sequence for an extended Get/Step is : XInit() - setup the data buffer and size SetRejectCount() - set the maximum records to extract from the file SetExtractCount() - set the maximum number of records to reject AddFilterCondition()- add filtering conditions AddFieldToExtract() - add fields to extract from each file record XGet() - execute the Get/Step operation Extract each record from the data buffer XDone / XReset - free resources or reset for next Get/Step operation The general calling sequence for an extended Insert is : XInit() - setup the data buffer and size Add each record to the data buffer XInsert() - execute the Insert XDone - free resources Suppose we have records in a Btrieve file defined as : MyRec = record LastName : String[15]; FirstName : String[15]; ID : String[5]; .... end; Asume that LastName/FirstName and ID have been defined as key 0 and key 1 respectively. Retrieving full records with last names in the range "JOHNSON" through "JONES" would be something like : var Buffer : Array[1..30] of MyRec; Name : String[15]; begin XInit(@Buffer, SizeOf(Buffer)); SetRejectCount(1000); { leave room for the extra bytes Btrieve returns } SetExtractCount(25); Name := 'JOHNSON'; AddFilterCondition(bLstring, 16, 0, bXGetGreatEqual+bXNoCaseCompare, bXLogicAND, @Name); Name := 'JONES'; AddFilterCondition(bLstring, 16, 0, bXGetLessEqual+bXNoCaseCompare, bXDone, @Name); { set file postioning if needed } .... XGet(bXGetNext); { process the data } .... XDone; end; Retrieving just the first and last name fields from records with last names greater than "SMITH" would be something like : type BufferRec = record LastName : String[15]; FirstName : String[15]; end; var Buffer : Array[1..30] of BufferRec; Name : String[15]; begin XInit(@Buffer, SizeOf(Buffer)); SetRejectCount(1000); { leave room for the extra bytes Btrieve returns } SetExtractCount(25); Name := 'SMITH'; AddFilterCondition(bLstring, 16, 0, bXGetGreat+bXNoCaseCompare, bXDone, @Name); AddFieldToExtract(16, 0); AddFieldToExtract(16, 16); { set file postioning if needed } .... XGet(bXGetNext); { process the data } .... XDone; end; Fields ------------------------------------------------------------------------------ Filters Filters : PCollection; A collection of the filtering conditions used in the next extended get or step operation. Extractors Extractors : PCollection; A collection of the fields to extract and return from records on the next get or step. MaxSkip MaxSkip : Word; Maximum number of records that can be skipped on a get or step. MaxExtract MaxExtract : Word; Maximum number of records that should be returned on an extended get or step. XData XData : PBytes; Pointer to the data buffer used with get, step, and insert. XData is set by a call to XInit. XDataSize XDataSize : Word; Size of the data buffer pointed to by XData. XDataSize is set by a call to XInit. XOffset XOffset : Word; Current position in the XData buffer. XOffset is used by ExtractNextRec to return the next record from the data buffer. XCount XCount : Word; The number of records returned so far by calls to ExtractNextRec. XRecCount XRecCount : Word; Number of records read by extended get or step. Methods ------------------------------------------------------------------------------ Init Constructor Init(FilePath: PathStr; ErrorObject: PErrorHandler; DataBuf: Pointer; DataBufSize: Word); Initialize the Btrieve file object. Calls BtrieveFile.Init to initialize the parent objects data. See BtrieveFile.Init Done Destructor Done; Virtual; Calls XDone to make sure all memory used by the extended operations is freed, then calls BtrieveFile.Done. See BtrieveFile.Done AddFieldToExtract Procedure AddFieldToExtract(FieldSize: Word; FieldOffset : Word); Adds a field to be extracted from a record to the extract list. FieldSize is the size of the field in bytes and FieldOffset is the offset of the field in the record. Remember, field offsets for extended gets are always zero based. If you don't make any calls to AddFieldToExtract, XGet will return the entire record. See XGet AddFilterCondition Procedure AddFilterCondition(FieldType: Byte; FieldSize: Word; FieldOffset: Word; ComparisonType: Byte; LogicType: Byte; var ComparisonValue); Adds a filtering condition used by XGet to the filter list. Multiple filtering conditions can be setup. You do not need to call AddFilterCondition, if no filtering is desired. FieldType may be any valid Btrieve data type. FieldSize is the size of the field in bytes. FieldOffset is the offset of the field in the file record. Remember, field offsets for extended gets are zero based. ComparisonType specifies the comparison expression type. It can specify a comparison for equality, greater than, less than, not equal, greater than or equal, or less than or equal. The numeric values are 1,2,3,4,5, and 6 respectively. If strings are being compared, add 32 to ComparisonType to compare using the file's alternate collating sequence, or add 128 to compare without case sensitivity. Add 64 if the second operand is another field in the record. LogicType specifies the AND/OR logic for this condition and the next one added. Set it to zero for the last term in the filtering conditio list. A value of one indicates AND and a value of two indicates OR. ComparisonValue is a pointer to some data to be used in the comparison. If comparing to another field in the record it should be set to nil. If it is not nil, it must point to data of the same type and size as specified by the FieldType and FieldSize parameters. The data pointed to by ComparisonValue must be valid at the time of the call to AddFilterCondition, since it will be copied by AddFilterCondition. See XGet, bXXXXX constants ExtractNextRec Function ExtractNextRec(var DataBuf; DataOnly: Boolean): Boolean; After XGet, ExtractNextRec extracts each record in order from the buffer and copies it to the memory pointed to by the DataBuff parameter. Btrieve normally returns an unformatted buffer with multiple records after an extended get or step operation. ExtractNextRec is an easy way to get each record out of that buffer. ExtractNextRec returns True if there was a record to extract and False if all records have been processed. The raw data returned by Btrieve includes the length of each record extracted from the file. If you do not want the length set DataOnly to True. If you want the length, make sure to include an integer or word as the first field in your record pointed to by DataBuff and pass False in DataOnly. See XGet SetExtractCount Procedure SetExtractCount(ExtractCount: Word); Sets the maximum number of records to read from the file. The extract count defaults to one. See XGet SetRejectCount Procedure SetRejectCount(RejectCount: Word); Sets the maximum number of records to skip on each get or step when trying to satisfy the filtering conditions. The reject count defaults to one. See XGet XDone Procedure XDone; Cleanups and frees memory used by XGet. It is very important that you call this routine, it is the only way to free resources used by the extended operations, short of calling the Done destructor. XInit Procedure XInit(XDataBuf: Pointer; XDataBufSize : Word); Does setup before an XGet or XInsert. Call XInit before each new XGet or XInsert, prior to adding filtering conditions and/or extract fields. If you do repeated XGets, because there are more records to return than will fit in the data buffer, you should call XInit only once before the first of the repeated XGet operations. XGet Procedure XGet(Op : Word); Execute an extended Get or Step oeration. Uses the Data buffer set by calling XInit, the filtering conditions set by calling AddFilterCondition, and the extract fields set by calling AddFieldToExtract. Op can be either 36, 37, 38, or 39. See AddFieldToExtract, AddFilterCondition, SetExtractCount, SetRejectCount, XInit, bXXXXX constants XInsert Function XInsert: Word; Adds the records stored in the data buffer to the file. XReset Procedure XReset; Resets extractor and filter data between unique XGet operations. If you are doing a set of XGets with differing filter or extract conditions you must call XReset between XGet calls prior to setting the new filter and extract conditions. ErrorHandler OBJECT ============================================================================== This is the parent obejct for DefErrorHandler and DiskErrorHandler. ErrorHandler returns minimal message strings. While DefErrorHandler and DiskErrorHandler return full descriptive message strings. Fields ------------------------------------------------------------------------------ ErrorDisplay ErrorDisplay : PErrorDisplay; Pointer to the object that will be called to display errors. If ErrorDisplay is nil, no errors will be displayed. ErrorsON ErrorsON : Boolean; RetryCount RetryCount : Word; The number of times an operation has been attempted so far. RetryCount is only used on lock errors. MaxRetry MaxRetry : Word; The maximum number of retries allowed. RetryDelay RetryDelay : Word; Delay between retries on error. TrappedErrors TrappedErrors : ErrorSet; Set of all trapped errors. Any error in this set will be checked for by ErrorHandler and passed to an error display routine. This set defaults to all errors except End Of File. NOTE: With the introduction of Btrieve for Windows, some status codes are greater than 255, and will not fit in the error set. Since they cannot be toggled singly, you should call ErrorsOnOff to remove error trapping for those errors greater than 255. Methods ------------------------------------------------------------------------------ Init Constructor Init(var DisplayObject: PErrorDisplay); Initialize the error handler. DisplayObject is the object that will be called to display errors. If DisplayObject is nil, no errors will be displayed. See Done, ErrorDisplay object Done Destructor Done; Virtual; Destroys the object. See Init AddErrors Procedure AddErrors(ErrorCodes : ErrorSet); Add the errors in the set ErrorCodes to the set of trapped errors. See ErrorSet, TrappedErrors, SetErrors, GetErrors, RemoveErrors, bXXXXX constants ClearRetry Procedure ClearRetry; Clears the current number of retries. See SetDelay, GetDelay, RetryCount, ClearRetry, MaxRetry, GetMaxRetry ErrorDispatcher Function ErrorDispacther(ErrorCode : Integer; OpCode : Byte; FileName : PathStr): ErrorAction; Virtual; ErrorDispatcher is called by the Error method. The error code, error description, operation code, operation description, and file path name will be passed to the error display object. The error display object will return an action code, erAbort, erDone, or erRetry. On erAbort the program will be immediately halted. erDone will cause the error state to be cleared, so the operation will return to your program code. erRetry will leave the error state to TRUE, so the operation can be retried. See Error, ErrorDisplay object, ErrorAction, bXXXXX constants Error Function Error(Status : Integer; OpCode : Byte; FileName : PathStr): Boolean; Virtual; If Status is in the set of trapped errors (zero cannot be added to the set) or is greater than bLastError, Error calls the ErrorDispatcher method. The status will be passed to the ErrorDisplay object through the ErrorDispatcher routine. In the case of file or record lock errors (84, 85), no error will be generated until the operation has been tried the number of times stored in RetryCount. If the action code returned by the error dispatcher is erDone, Error will return FALSE to the calling routine, indicating no more errors. If the action code is erRetry then, TRUE is returned, so the calling routine will execute the operation again. If a Status is not in the set of trapped errors, unless it is greater than bLastError, FALSE is always returned. In this case the program must check the file status function bResult for errors. See ErrorDispatcher, ErrorDisplay object, ErrorAction, bXXXXX constants ErrorMsg Function ErrorMsg(ErrorCode : Integer): String; Virtual; Returns a string describing the error associated with ErrorCode. See bXXXXX constants ErrorsOnOff Procedure ErrorsOnOff(State : Boolean); Toggles all error trapping on or off. When error trapping is off all errors must be handled by the programmer. This is an easy way to turn of error handling for a few Btrieve IO operations. GetDelay Function GetDelay: Word; Returns the current seconds delay between retries. See GetDelay, RetryCount GetErrors Procedure GetErrors(var ErrorCodes : ErrorSet); Returns the full set of trapped error codes. See TrappedErrors, SetErrors, AddErrors, RemoveErrors, ErrorSet, bXXXXX constants GetMaxRetry Function GetMaxRetry: Word; Return the maximum number of retries. See RetryCount, ClearRetry, MaxRetry, SetMaxRetry OpMsg Function OpMsg(OpCode : Integer): String; Virtual; Returns a string describing the operation associated with OpCode. See bXXXXX constants RemoveErrors Procedure RemoveErrors(ErrorCodes : ErrorSet); Remove the errors in the set ErrorCodes from the set of trapped errors. See TrappedErrors, SetErrors, GetErrors, AddErrors, ErrorSet, bXXXXX constants. SetDelay Procedure SetDelay(Seconds : Word); Set the seconds of delay between retries. This delay is only used for lock errors. See GetDelay, RetryCount SetErrors Procedure SetErrors(ErrorCodes : ErrorSet); Setup the full set of trapped errors. See SetErrors, GetErrors, AddErrors, RemoveErrors, ErrorSet, bXXXXX constants SetMaxRetry Procedure SetMaxRetry(Retry : Word); Set the maximum number of retries. See RetryCount, ClearRetry, MaxRetry, GetMaxRetry DefErrorHandler OBJECT ============================================================================== DefErrorHandler descends from the ErrorHandler object. It holds all message strings in memory. ErrorMsg and OpMsg return descriptive message strings. Methods ------------------------------------------------------------------------------ ErrorMsg Function ErrorMsg(ErrorCode : Integer): String; Virtual; Returns a string describing the error associated with ErrorCode. See bXXXXX constants OpMsg Function OpMsg(OpCode : Integer): String; Virtual; Returns a string describing the operation associated with OpCode. See bXXXXX constants DiskErrorHandler OBJECT ============================================================================== DiskErrorHandler descends from the ErrorHandler object. It holds all message strings in a Btrieve file. ErrorMsg and OpMsg return descriptive message strings. There is a Btrieve file, "BTRIEVE.MSG", (supplied with the registered version BTV) that contains messages for all the status and op codes in Btrieve up to version 5.15. The record layout of "BTRIEVE.MSG" is as follows: BtrieveMsgRec = record ID : Integer; Name : String[80]; MsgText : Array[0..900] of Char; end; ID is the status or op code. The status code records are numbered from zero in the file. To fit all messages into one file, the op code record IDs are offset by 4000. So, op code zero is stored as opcode 4000 in the file. Name is a short description of the status or op code. MsgText is a longer description, and may contain further explanation and, for status codes, some possible corrective actions. Both ErrorMsg and OpMsg return the Name field as the message string. You will find that Name and MsgText follow the Btrieve SDK manual very closely. You may use the supplied message file or one of your own creation. If you create your own file, make sure it has the same layout as "BTRIEVE.MSG". There is a Windows program included, "BTVERR.EXE", for editing message files. Methods ------------------------------------------------------------------------------ Init Constructor Init(DisplayObject : PErrorDisplay; ErrorPath : PathStr); Calls ErrorHandler.Init then opens the Btrieve message file specified by the ErrorPath parameter. Done Destructor Done; Virtual; Calls ErrorHandler.Done then closes the message file. ErrorMsg Function ErrorMsg(ErrorCode : Integer): String; Virtual; Returns a string describing the error associated with ErrorCode. If the message file is not open, or any errors occur, the message generated by the ancestor ErrorHandler is returned. See bXXXXX constants OpMsg Function OpMsg(OpCode : Integer): String; Virtual; Returns a string describing the operation associated with OpCode. If the message file is not open, or any errors occur, the message generated by the ancestor ErrorHandler is returned. See bXXXXX constants ErrorDisplay OBJECT ============================================================================== ErrorDisplay displays error messages for errors handled by the ErrorHandler object or its descendants. Methods ------------------------------------------------------------------------------ Init Constructor Init; Initialize the object. See Done Done Destructor Done; Virtual; Destroys the object. See Init Display Function Display(Error : Integer; ErrorMsg : String; OpCode : Byte; OpCodeMsg : String; FileName : PathStr): ErrorAction; Virtual; This routine is called by the error handler, for any errors that are in the set of trapped errors or greater than bLastError. Error is the Btrieve status code, ErrorMsg a description of the error code. OpCode is the operation that generated the error. OpCodeMsg is a description of the operation. FileName is the full path name for the file. This routine must return an action code that will tell the error handler what to do next. Here is an example of a what typical error display method might look like : Function TheErrorDisplay.Display(Error : Integer; ErrorMsg : String OpCode : Byte; OpCodeMsg : String; FileName : PathStr): ErrorAction; var Ch : Char; begin GotoXY(1,1); { show what happened } Writeln(''); Writeln(FileName); Writeln(ErrorMsg); Writeln(OpCodeMsg); Case Error of { a couple errors to abort on } bFileNotOpen, bFileNotFound, bNotLoaded : begin Writeln('Press a key ...'); Ch := ReadKey; Display := erAbort; end; else { we will let user decide what to do here } begin Writeln('Do you wish to try again (Y/N)?'); Ch := UpCase(ReadKey); if (Ch = 'Y') then Display := erRetry else Display := erDone; end; end; end; As you can see, you have full control of what happens after an error. You can use the opcode and error to classify errors and control the error handler actions. Pass back erAbort to halt the program, erRetry to make another attempt, or erDone to continue and return the error to your program. TProgress OBJECT ============================================================================== Methods ------------------------------------------------------------------------------ Init Constructor Init; Display Procedure Display(Count : LongInt); This method is called by Recover, Save, and Load to display the progress of the operation. You must define a new descendant object with a working Display method. Before calling Recover, Save, or Load, initialize an object of your new type. Then pass a pointer to your object. Your Display method will be called every ten records plus one final time when the operation is complete.