home *** CD-ROM | disk | FTP | other *** search
/ Black Box 4 / BlackBox.cdr / progbas / qbtree55.arj / QBTREE55.PRN < prev    next >
Encoding:
Text File  |  1991-07-31  |  117.1 KB  |  3,308 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.                             A B-Tree Access Method
  11.                         for QuickBASIC/PDS Programmers
  12.  
  13.  
  14.  
  15.                                  QBTree v5.50
  16.  
  17.                                   31-July-91
  18.                            (C)1989-1991 Cornel Huth
  19.  
  20.  
  21.  
  22.  
  23.  
  24.       The QBTree package is a shareware product. You may try QBTree to
  25.       see if it fits your needs on a trial basis only. You may copy and
  26.       distribute this shareware package freely. If you plan to use it
  27.       after the trial, print and then fill out the !ORDER.FRM on the
  28.       distribution disk and send it along with full payment to:
  29.  
  30.            Cornel Huth
  31.            ATTN: QBTree 5.50 REGISTRATION
  32.            6402 Ingram Rd.
  33.            San Antonio, TX  78238
  34.  
  35.       All BASIC source code for the QBTree interface will be sent upon
  36.       receipt of the completed registration form.
  37.  
  38.       QBTree requires QuickBASIC 4.00+ or BASIC 7.0+. For file sharing
  39.       and record locking functions and for accessing more than 15 files
  40.       at one time DOS 3.1+ is needed
  41.  
  42.       Read this documentation before trying to use QBTree since much has
  43.       changed from previous versions, especially: all network routines,
  44.       OpenFile(), and FileExists().
  45.  
  46.       --This file has been mechanically reproduced from the DTP source
  47.       of the documentation with manual touchup. Page numbers, table of
  48.       contents, and other facilatators have not been incorporated into
  49.       this reproduction.
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.       OVERVIEW
  58.       
  59.       QBTree is a low-level file manager for Microsoft QuickBASIC and 
  60.       BASIC 7 Professional Development System compilers. It is based on 
  61.       the B-Tree sorting method and provides fast and efficient database 
  62.       functions for the QB/PDS programmer. 
  63.       
  64.       Some features of QBTree are:
  65.       
  66.       1) Maintain up to 250 key and data files at one time.
  67.       2) Find any key and data record quickly - any key in a million in 
  68.       at most 5 disk accesses.
  69.       3) Forward and reverse sequential inorder access to the data file 
  70.       using just one key file(ISAM).
  71.       4) Automatic data file maintenance where deleted records are made 
  72.       available for reuse.
  73.       5) Automatic key file balancing.
  74.       6) DOS-compatible file and record locking network support.
  75.       7) Routines to support key file maintenance with any data file
  76.       format the programmer specifies.
  77.       
  78.       QBTree has evolved significantly over the past few years. Network 
  79.       support, Dbase compatibility (in the QBXDBF package, available
  80.       with registration), and fast, compact B-Tree indexing all combined
  81.       in one package and at one low price. Compare this to other packages
  82.       at $200-$600+. But best of all, QBTree was designed specifically for
  83.       QuickBASIC and PDS compilers. There is no separate TSR to be loaded
  84.       nor is there a cryptic language interface. You'll find QBTree easy
  85.       to use, just like QuickBASIC, with only a few of the routines needed
  86.       to start creating database applications. From there, as you gain
  87.       experience, you'll find that even sophisticated database applications
  88.       will become easy to design and quick to code. 
  89.       
  90.  
  91.  
  92.  
  93.  
  94.  
  95.       INSTALLATION --Shareware try-before-you-buy version.
  96.  
  97.       The following files should be found in this shareware package:
  98.  
  99.       !ORDER.FRM     Order form
  100.                      -- this form must be used when ordering
  101.       QBTREE55.PRN   this documentation suitable for printing
  102.       QBTREE45.QLB   QLB for QuickBASIC 4.5
  103.       QBTREE4B.QLB   QLB for QuickBASIC 4.00b
  104.       QBTREE71.QLB   QLB for BASIC PDS 7.1
  105.       QBTREE.BI      declares
  106.       XBTREE1.BAS    example QBTree source file
  107.       XBTREE2.BAS    example QBtree source file
  108.       XDATA1.DAT     data file used by XBTREE1.BAS and XDBF1.EXE
  109.       XDBF1.TXT      information of XDBF1.EXE
  110.       XDBF1.EXE      example QBXDBF (dBASE) executable file
  111.  
  112.       To evaluate the QBTree package simply startup your environment
  113.       with the appropriate QBTree QLB:
  114.  
  115.       C>QB /lQBTREE4B  or  C>QB /lQBTREE45  or  C>QBX /lQBTREE71
  116.  
  117.       All functionality of the registered versions is found in these
  118.       QLBs. However, you cannot create executable programs without
  119.       registering. The QuickBASIC versions of QBTree were compiled with
  120.       their respective compiler using /o as the the compiler switch. The
  121.       BASIC PDS version was compiled using /o/Fs as the compiler switches.
  122.       If you are still using the buggy QuickBASIC 4.00 (original release)
  123.       send $5.00 and I'll ship a version 4.00 QLB to you.
  124.  
  125.  
  126.       Sample Go:
  127.  
  128.       Start QB with the appropriate QLB. Load the XBTREE1.BAS source file.
  129.       Press shift-F5. That's it. Be sure you have 'QBTREE.BI' accessible and
  130.       XDATA1.DAT in the current directory.
  131.  
  132.  
  133.       Remember, registration is required for continued use. In addition,
  134.       registering QBTree allows you to order QBXDBF for only $5.00 more.
  135.  
  136.       QBXDBF is similar to QBTree but uses the dBASE .DBF file format.
  137.       There are many features built-in to QBXDBF that are not available
  138.       in QBTree. For example, keys are entered once when the key file is
  139.       created, e.g., kx$=UPPER(SUBSTR(LASTNAME,1,1))+SUBSTR(SSN,6,4).
  140.       Duplicate keys are handled automatically. Up to 1023 fields per
  141.       record. A very fast reindex module (12,000 recs/min). Much more.
  142.  
  143.       In short, whereas QBTree is a low-level file manager, QBXDBF is a
  144.       mid-level file manager. It's not as versatile as QBTree (after all,
  145.       QBXDBF was written in QBTree) but it is well suited to the task of
  146.       database programming.
  147.  
  148.       Please, use the !ORDER.FRM to place your order.
  149.  
  150.  
  151.  
  152.  
  153.  
  154.  
  155.       INSTALLATION -Registered version.
  156.       
  157.       There are 3 libraries distributed with QBTree. QBTREE.LIB is for 
  158.       QuickBASIC compilers, QBTREEF.LIB and QBTREEN.LIB are for BASIC 7 
  159.       compilers. Your source code needs to REM $INCLUDE: 'QBTREE.BI'.
  160.       
  161.       To install for QuickBASIC:  The BASIC interface portion of 
  162.       QBTREE.LIB was compiled with BC 4.50 (/O) and is intended for use 
  163.       with QuickBASIC 4.xx.
  164.       
  165.       To use QBTree in the QB environment create a QLB:
  166.           
  167.           C>link /qu QBTREE.LIB<+other.lib>,qb.qlb,nul,bqlb45
  168.            
  169.       When you create an EXE file of your program, add QBTREE.LIB to the 
  170.       library prompt from LINK.
  171.       
  172.       If you have a version of QB other than 4.5 you should recompile the 
  173.       BASIC source, update the library, and create a QLB:
  174.            
  175.           C>ren BTREEZ.BAS BTREE.BAS
  176.           C>bc BTREE.BAS /O;
  177.           C>lib QBTREE -+BTREE;
  178.           C>link /qu QBTREE.LIB,qb.qlb,nul,bqlb4x
  179.            (where x=0 for 4.00, x=1 for 4.00b)
  180.            
  181.       To install for BASIC 7/PDS:  The BASIC interface portion of 
  182.       QBTREEF.LIB was compiled with BC 7.10 (/O/Fs) and is intended for 
  183.       use with BASIC 7.xx and QBX using far-string support. QBTREEN.LIB 
  184.       (/O/Ot) is intended for use with BASIC 7.xx using near-string support.
  185.       
  186.       To use QBTree in the QBX environment create a QLB:
  187.            
  188.           C>link /qu QBTREEF.LIB<+other.lib>,qbx.qlb,nul,qbxqlb;
  189.       
  190.       When you create an EXE file of your program, add QBTREEF.LIB (or 
  191.       QBTREEN.LIB) to the library prompt from LINK.
  192.       
  193.       If you have a version of BASIC other than 7.1 you should recompile 
  194.       the BASIC source, update the libraries, and create a QLB:
  195.            
  196.           C>ren BTREEZ.BAS BTREEF.BAS
  197.           C>bc BTREEF.BAS /O/Fs;
  198.           C>lib QBTREEF -+BTREEF;
  199.  
  200.           C>ren BTREEF.BAS BTREEN.BAS
  201.           C>bc BTREEN.BAS /O/Ot;
  202.           C>lib QBTREEN -+BTREEN;
  203.  
  204.           C>link /qu QBTREEF.LIB,qbx.qlb,nul,qbxqlb;
  205.       
  206.  
  207.  
  208.  
  209.  
  210.  
  211.       FUNCTION SUMMARY
  212.       
  213.       All QBTree routines are FUNCTIONs and return an integer code which 
  214.       is detailed in APPENDIX D. ERROR CODES.
  215.       
  216.        1) AddKey(kfile,dfile,Qkey$)
  217.        2) AddKeyRecord(kfile,dfile,Qkey$,Qrec$)
  218.        3) CloseDataFile(dfileno)
  219.        4) CloseKeyFile(kfileno)
  220.        5) CreateDataFile(filename$,recl)
  221.        6) CreateKeyFile(filename$,keyl)
  222.        7) DeleteKey(kfile,Qkey$)
  223.        8) DeleteKeyRecord(kfile,dfile,Qkey$)
  224.        9) ExitQBTree()
  225.       10) FlushDataFile(dfileno,dup)
  226.       11) FlushKeyFile(kfileno,dup)
  227.       12) FreeDataFile()
  228.       13) FreeKeyFile()
  229.       14) GetDirect(dfileno,recno&,Qrec$)
  230.       15) GetEqual(kfile,dfile,Qkey$,Qrec$)
  231.       16) GetFirst(kfile,dfile,Qkey$,Qrec$)
  232.       17) GetGT(kfile,dfile,Qkey$,Qrec$)
  233.       18) GetGTE(kfile,dfile,Qkey$,Qrec$)
  234.       19) GetLast(kfile,dfile,Qkey$,Qrec$)
  235.       20) GetLT(kfile,dfile,Qkey$,Qrec$)
  236.       21) GetLTE(kfile,dfile,Qkey$,Qrec$)
  237.       22) GetNext(kfile,dfile,Qkey$,Qrec$)
  238.       23) GetPosition(kfileno,recno&)
  239.       24) GetPrev(kfile,dfile,Qkey$,Qrec$)
  240.       25) InitQBTree(MKF,MDF)
  241.       26) LockDataHeader(dfileno)
  242.       27) LockKeyFile(kfileno)
  243.       28) LockRecord(dfileno,recno&)
  244.       29) OpenDataFile(filename$,dfileno,asmode)
  245.       30) OpenKeyFile(filename$,kfileno,asmode)
  246.       31) RetrieveEqual(kfile,Qkey$,Qrecno&)
  247.       32) RetrieveFirst(kfile,Qkey$,Qrecno&)
  248.       33) RetrieveGT(kfile,dfile,Qkey$,Qrecno&)
  249.       34) RetrieveGTE(kfile,dfile,Qkey$,Qrecno&)
  250.       35) RetrieveLast(kfile,Qkey$,Qrecno&)
  251.       36) RetrieveLT(kfile,dfile,Qkey$,Qrecno&)
  252.       37) RetrieveLTE(kfile,dfile,Qkey$,Qrecno&)
  253.       38) RetrieveNext(kfile,Qkey$,Qrecno&)
  254.       39) RetrievePrev(kfile,Qkey$,Qrecno&)
  255.       40) QBTreeVer(ver)
  256.       41) StatDataFile(dfileno,recl,recs&,bfileno)
  257.       42) StatKeyFile(kfileno,keyl,keys&,bfileno)
  258.       43) StoreKey(kfile,Qkey$,Qrecno&) 
  259.       44) UnlockDataHeader(dfileno)
  260.       45) UnlockKeyFile(kfileno) 
  261.       46) UnlockRecord(dfileno,recno&)
  262.       47) UpdateRecord(dfile,Qrec$)
  263.  
  264.       
  265.  
  266.  
  267.  
  268.  
  269.  
  270.       AddKey
  271.       
  272.       TYPE       FUNCTION
  273.       
  274.       SYNTAX     stat=AddKey(kfile,dfile,Qkey$)
  275.        
  276.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  277.                  dfile - INTEGER.Number used as fileno in OpenDataFile().
  278.                  Qkey$ - STRING.Key to add to kfile. This key will index 
  279.                  the current data record in dfile.
  280.       
  281.       USE        Add the key to kfile using the current data record as 
  282.                  this key's data record. This lets you have more than one 
  283.                  index file per data file.
  284.                  For instance, you would like to index a data file on 
  285.                  both name and social security number: First, use 
  286.                  AddKeyRecord() to insert the name key in the name key 
  287.                  file and add the data record to the data file. 
  288.                  Immediately after, use AddKey() to insert the SSN key in 
  289.                  the SSN key file. Both the name key and SSN key point to 
  290.                  the same data record. Any individual data record can now 
  291.                  be found by using either the name key file or the SSN key 
  292.                  file. 
  293.       
  294.       RULES      The key must be unique.
  295.                  Qkey$ must not begin with an ASCII 0 or 255.
  296.                  If an error code is returned by AddKey() you must reset 
  297.                  the current data record before retrying the function. 
  298.                  This is because any error causes QBTree to invalidate the 
  299.                  current data record pointer.
  300.                  For instance, if the key you are adding already exists 
  301.                  in the key file, error 201 is returned. After making the 
  302.                  key unique, you must reset the current data record by 
  303.                  REACCESSING it using GetEqual() with the appropriate key, 
  304.                  otherwise error 206 is returned.
  305.       
  306.       NOTES      QBTree is case-sensative. Convert all added keys (not 
  307.                  data records) to the same case unless there is a reason 
  308.                  not to.
  309.       
  310.       RETURN     Errors 201, 206, 219, 222, 223, and DOS.
  311.                  
  312.       EXAMPLE    stat = AddKeyRecord(0,0,Qname$,Qdatarec$)
  313.                  IF stat = 0 THEN
  314.                     stat = AddKey(1,0,QSSN$)
  315.                     IF stat = 201 THEN
  316.                        'see Appendix C. Non-unique Keys for 
  317.                        'method to create unique keys
  318.                        UQSSN$ = DoMakeKeyUnique$(1,0,QSSN$)
  319.                        'reaccess data record to reset pointer
  320.                        stat2 = GetEqual(0,0,Qname$,nul$)
  321.                        'add the 'unique' key
  322.                        stat = AddKey(1,0,UQSSN$)
  323.       
  324.  
  325.  
  326.  
  327.  
  328.  
  329.       AddKeyRecord
  330.       
  331.       TYPE       FUNCTION
  332.       
  333.       SYNTAX     stat=AddKeyRecord(kfile,dfile,Qkey$,Qrec$)
  334.       
  335.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  336.                  dfile - INTEGER.Number used as fileno in OpenDataFile().
  337.                  Qkey$ - STRING.Key to add to kfile. This key will index 
  338.                  Qrec$ in the data file.
  339.                  Qrec$ - STRING.Data record to add to dfile.
  340.       
  341.       USE        Add the key to kfile and add the data record to dfile. 
  342.                  Once added, using GetEqual() with this key returns this 
  343.                  data record.
  344.       
  345.       RULES      The key must be unique.
  346.                  Qkey$ must not begin with an ASCII 0 or 255.
  347.                  
  348.       NOTES      QBTree is case-sensative. Convert all added keys (not 
  349.                  data records) to the same case unless there is a reason 
  350.                  not to.
  351.                  
  352.       RETURN     Errors 201, 219, 222, 223, and DOS.
  353.       
  354.       EXAMPLE    Qdatarec$ = "KEYPART DATARECORDPART"
  355.                  Qname$ = LEFT$(Qdatarec$,8)
  356.                  stat = AddKeyRecord(0,0,Qname$,Qdatarec$)
  357.                  IF stat = 201 THEN
  358.                     'see Appendix C. Non-unique Keys for 
  359.                     'method to create unique keys
  360.                     UQname$ = DoMakeKeyUnique$(0,0,Qname$)
  361.                     'add the 'unique' key
  362.                     stat = AddKeyRecord(0,0,UQname$,Qdatarec$)
  363.                  
  364.       
  365.  
  366.  
  367.  
  368.  
  369.  
  370.       CloseDataFile
  371.       
  372.       TYPE       FUNCTION
  373.       
  374.       SYNTAX     stat=CloseDataFile(dfile)
  375.       
  376.       PARAMETERS dfile - INTEGER.Number used as fileno in OpenDataFile().
  377.       
  378.       USE        Write the data header from memory to disk and release 
  379.                  the handle used by dfile. Tell DOS to close the file and 
  380.                  update the directory entry.
  381.                  
  382.       RULES      None.
  383.  
  384.       NOTES      See FlushDataFile.
  385.                  
  386.       RETURN     Errors 219, 222, and DOS.
  387.       
  388.       EXAMPLE    'done with data file 0, close it
  389.                  stat = CloseDataFile(0)
  390.                  
  391.       
  392.  
  393.  
  394.  
  395.  
  396.  
  397.       CloseKeyFile
  398.       
  399.       TYPE       FUNCTION
  400.                  
  401.       SYNTAX     stat=CloseKeyFile(kfile)
  402.       
  403.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  404.       
  405.       USE        Write the key header from memory to disk and release the 
  406.                  handle used by kfile. Tell DOS to close the file and 
  407.                  update the directory entry.
  408.                  
  409.       RULES      None.
  410.       
  411.       NOTES      See FlushKeyFile.
  412.       
  413.       RETURN     Errors 219, 222, and DOS.
  414.       
  415.       EXAMPLE    'done with key file 0, close it
  416.                  stat = CloseKeyFile(0)
  417.                  
  418.       
  419.  
  420.  
  421.  
  422.  
  423.  
  424.       CreateDataFile
  425.       
  426.       TYPE       FUNCTION
  427.       
  428.       SYNTAX     stat = CreateDataFile(filename$,reclen)
  429.       
  430.       PARAMETERS filename$ - STRING.Pathname of data file to create.
  431.                  reclen - INTEGER.Length of data record.
  432.       
  433.       USE        Create a new data file with the given record length. 
  434.                  This does not leave the file open - you must 
  435.                  OpenDataFile() to use it.
  436.       
  437.       RULES      filename$ must be <= 64 characters; reclen must be >= 3 
  438.                  and <= 2048.
  439.       
  440.       NOTES      Both filename$ and reclen maximum lengths can be 
  441.                  changed, see the BASIC source file for information on 
  442.                  doing this.
  443.                  
  444.       RETURN     Errors 220, 230, 233, and DOS.
  445.       
  446.       EXAMPLE    filename$ = "F:\HIST\AR91.DAT"
  447.                  reclen = 128
  448.                  stat = CreateDataFile(filename$,reclen)
  449.                  
  450.       
  451.  
  452.  
  453.  
  454.  
  455.  
  456.       CreateKeyFile
  457.       
  458.       TYPE       FUNCTION
  459.       
  460.       SYNTAX     stat = CreateKeyFile(filename$,keylen)
  461.       
  462.       PARAMETERS filename$ - STRING.Pathname of key file to create.
  463.                  keylen - INTEGER.Length of key.
  464.                  
  465.       USE        Create a new key file with the given key length. This 
  466.                  does not leave the file open - you must OpenKeyFile() to 
  467.                  use it.
  468.       
  469.       RULES      filename$ must be <= 64 characters; keylen must be <= 64 
  470.                  bytes.
  471.       
  472.       NOTES      filename$ maximum length can be changed, see the BASIC 
  473.                  source file for information on doing this.
  474.       
  475.       RETURN     Errors 221, 230, 233, and DOS.
  476.       
  477.       EXAMPLE    filename$ = "F:\HIST\AR91ANUM.KEY"
  478.                  keylen = 17
  479.                  stat = CreateKeyFile(filename$,keylen)
  480.                  
  481.       
  482.  
  483.  
  484.  
  485.  
  486.  
  487.       DeleteKey
  488.       
  489.       TYPE       FUNCTION
  490.                  
  491.       SYNTAX     stat = DeleteKey(kfile,Qkey$)
  492.       
  493.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  494.                  Qkey$ - STRING.Key to remove from kfile.
  495.       
  496.       USE        Remove the key Qkey$ from kfile.
  497.       
  498.       RULES      Qkey$ must not begin with an ASCII 0 or 255.
  499.       
  500.       NOTES      Let's say you have a customer data file with two key 
  501.                  files used to index it, one by name, the other by 
  502.                  customer code, and you want to remove a customer from 
  503.                  this database. You would use DeleteKey() on one of the 
  504.                  key files, and DeleteKeyRecord() on the remaining key 
  505.                  file (and data file). If you use DeleteKey() on both key 
  506.                  files you would be unable to remove the data record. 
  507.       
  508.       RETURN     Errors 200, 204, 219, 222, 223, and DOS.
  509.       
  510.       EXAMPLE    fileK0$ = "C:\CUSTNAME.KEY"
  511.                  fileK1$ = "C:\CUSTCODE.KEY"
  512.                  fileD0$ = "C:\CUSTDATA.DAT"
  513.                  '[code to open files deleted]
  514.                  DelName$ = "Sioux," + "Leslie"
  515.                  DelCode$ = "100500"
  516.                  stat = DeleteKey(0,DelName$)
  517.                  IF stat = 0 THEN
  518.                     stat = DeleteKeyRecord(1,0,DelCode$)
  519.                  
  520.       
  521.  
  522.  
  523.  
  524.  
  525.  
  526.       DeleteKeyRecord
  527.       
  528.       TYPE       FUNCTION
  529.                  
  530.       SYNTAX     stat = DeleteKeyRecord(kfile,dfile,Qkey$)
  531.       
  532.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  533.                  dfile - INTEGER.Number used as fileno in OpenDataFile().
  534.                  Qkey$ - STRING.Key to remove from kfile.
  535.                  
  536.       USE        Remove the key Qkey$ from kfile and also remove the data 
  537.                  record that Qkey$ indexes from dfile.
  538.       
  539.       RULES      Qkey$ must not begin with an ASCII 0 or 255.
  540.       
  541.       NOTES      Let's say you have a customer data file with two key 
  542.                  files used to index it, one by name, the other by 
  543.                  customer code, and would like to remove a customer from 
  544.                  this database. You would use DeleteKey() on one of the 
  545.                  key files, and DeleteKeyRecord() on the remaining key 
  546.                  file (and data file).
  547.       
  548.       RETURN     Errors 200, 204, 219, 222, 223, and DOS.
  549.       
  550.       EXAMPLE    fileK0$ = "C:\CUSTNAME.KEY"
  551.                  fileK1$ = "C:\CUSTCODE.KEY"
  552.                  fileD0$ = "C:\CUSTDATA.DAT"
  553.                  '[code to open files deleted for space]
  554.                  DelName$ = "Sioux," + "Leslie"
  555.                  DelCode$ = "100500"
  556.                  stat = DeleteKey(0,DelName$)
  557.                  IF stat = 0 THEN
  558.                     stat = DeleteKeyRecord(1,0,DelCode$)
  559.                  
  560.       
  561.  
  562.  
  563.  
  564.  
  565.  
  566.       ExitQBTree
  567.       
  568.       TYPE       FUNCTION
  569.                  
  570.       SYNTAX     stat = ExitQBTree
  571.       
  572.       PARAMETERS None.
  573.       
  574.       USE        Close all QBTree files and release the RAM used by the 
  575.                  buffers. Use is optional.
  576.       
  577.       RULES      None.
  578.       
  579.       NOTES      Once ExitQBTree() is called you must InitQBTree() before 
  580.                  using any other QBTree function. This is the only way you 
  581.                  can release the RAM used by the data buffers other than 
  582.                  exiting your program.
  583.       
  584.       RETURN     Error 233.
  585.       
  586.       EXAMPLE    PRINT "done."
  587.                  nul = ExitQBTree
  588.                  END
  589.                  
  590.       
  591.  
  592.  
  593.  
  594.  
  595.  
  596.       FlushDataFile
  597.       
  598.       TYPE       FUNCTION
  599.       
  600.       SYNTAX     stat = FlushDataFile(dfile,dup)
  601.       
  602.       PARAMETERS dfile - INTEGER.Number used as fileno in OpenDataFile().
  603.                  dup - INTEGER.Non-zero to force a directory update.
  604.       
  605.       USE        Flush the data file by writing the data file header in 
  606.                  RAM to the data file header on disk. If dup is non-zero 
  607.                  then also update the directory entry. 
  608.       
  609.       RULES      If any part of dfile has been locked with either 
  610.                  LockDataHeader() or LockRecord() then dup must be zero. 
  611.                  If not, a locking violation error will occur when you 
  612.                  unlock.
  613.                  
  614.       NOTES      If DOS 3.3+ is detected, the header is written as above 
  615.                  but the directory information is updated using the DOS 
  616.                  commit function (func 68h), regardless the value of dup. 
  617.                  When programming for network environments, always use 
  618.                  dup=0. 
  619.                  Flushing buffers should be done whenever processing can 
  620.                  handle the delay. Once a file has been flushed (and no 
  621.                  further changes have been made), a power-outage can bring 
  622.                  your system down with no ill-effects to the QBTree file - 
  623.                  all will be intact. Closing and then reopening the file 
  624.                  will have the same effect as this routine but will incur 
  625.                  a much higher overhead.
  626.       
  627.       RETURN     Errors 219, 222, 225, and DOS.
  628.                  
  629.       EXAMPLE    IF IsOnNetwork THEN dup = 0 ELSE dup = -1
  630.                  stat = FlushDataFile(dfile,dup)
  631.                  
  632.       
  633.  
  634.  
  635.  
  636.  
  637.  
  638.       FlushKeyFile
  639.       
  640.       TYPE       FUNCTION
  641.                  
  642.       SYNTAX     stat = FlushKeyFile(kfile,dup)
  643.                  
  644.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  645.                  dup - INTEGER.Non-zero to force a directory update.
  646.       
  647.       USE        Flush the key file by writing the key file header in RAM 
  648.                  to the key file header on disk. If dup is non-zero then 
  649.                  also update the directory entry. 
  650.       
  651.       RULES      If kfile has been locked with LockKeyFile() then dup 
  652.                  should be zero.
  653.       
  654.       NOTES      If DOS 3.3+ is detected, the header is written as above 
  655.                  but the directory information is updated using the DOS 
  656.                  commit function (func 68h), regardless the value of dup. 
  657.                  When programming for network environments, always use 
  658.                  dup=0. 
  659.                  Flushing buffers should be done whenever processing can 
  660.                  handle the delay. Once a file has been flushed (and no 
  661.                  further changes have been made), a power-outage can bring 
  662.                  your system down with no ill-effects to the QBTree file - 
  663.                  all will be intact. Closing and then reopening the file 
  664.                  will have the same effect as this routine but will incur 
  665.                  a much higher overhead.
  666.                  
  667.       RETURN     Errors 219, 222, 225, and DOS.
  668.       
  669.       EXAMPLE    IF IsOnNetwork THEN dup = 0 ELSE dup = -1
  670.                  stat = FlushKeyFile(kfile,dup)
  671.                  
  672.       
  673.  
  674.  
  675.  
  676.  
  677.  
  678.       FreeDataFile
  679.       
  680.       TYPE       FUNCTION
  681.       
  682.       SYNTAX     fileno = FreeDataFile
  683.       
  684.       PARAMETERS None.
  685.                  
  686.       USE        Obtain a free QBTree data file handle.
  687.       
  688.       RULES      None.
  689.       
  690.       NOTES      The handle returned will be a number between 0 and MDF 
  691.                  where MDF is specified in InitQBTREE().
  692.                  This function is analagous to QB's FREEFILE.
  693.       
  694.       RETURN     Available free data file handle or -1 if none are 
  695.                  available.
  696.       
  697.       EXAMPLE    dfileno = FreeDataFile
  698.                  IF dfileno < 0 THEN DoNoDataHandlesAvailable
  699.                  stat = OpenDataFile(dfname$,dfileno,asmode)
  700.                  
  701.       
  702.  
  703.  
  704.  
  705.  
  706.  
  707.       FreeKeyFile
  708.       
  709.       TYPE       FUNCTION
  710.                  
  711.       SYNTAX     fileno = FreeKeyFile
  712.       
  713.       PARAMETERS None.
  714.       
  715.       USE        Obtain a free QBTree key file handle.
  716.       
  717.       RULES      None.
  718.       
  719.       NOTES      The handle returned will be a number between 0 and MKF 
  720.                  where MKF is specified in InitQBTREE().
  721.                  This function is analagous to QB's FREEFILE.
  722.       
  723.       RETURN     Available free key file handle or -1 if none are 
  724.                  available.
  725.       
  726.       EXAMPLE    kfileno = FreeKeyFile
  727.                  IF kfileno < 0 THEN DoNoKeyHandlesAvailable
  728.                  stat = OpenKeyFile(kfname$,kfileno,asmode)
  729.                  
  730.       
  731.  
  732.  
  733.  
  734.  
  735.  
  736.       GetDirect
  737.       
  738.       TYPE       FUNCTION
  739.       
  740.       SYNTAX     stat = GetDirect(dfile,recno&,Qrec$)
  741.       
  742.       PARAMETERS dfile - INTEGER.Number used as fileno in OpenDataFile().
  743.                  recno& - LONG.Number of record to get.
  744.                  Qrec$ - STRING.The data record at recno& is placed in 
  745.                  this variable.
  746.       
  747.       USE        Get a data record from the data file without using any 
  748.                  index file. recno& = 1 gets the very first data record in 
  749.                  dfile, 2 gets then next, and so on. 
  750.                  
  751.       RULES      recno& must be > 0 and <= the last possible record.
  752.       
  753.       NOTES      This function can be used to get records from the data 
  754.                  file to reindex a key file. Error 224 is returned if you 
  755.                  try to get a record past the absolute end of file.
  756.                  
  757.       RETURN     Errors 219, 222, 224, and DOS.
  758.       
  759.       EXAMPLE    INPUT "Retrieve which record number ";recno&
  760.                  stat = GetDirect(0,recno&,Qrec$)
  761.                  IF stat = 0 THEN
  762.                     PRINT "Record=";Qrec$
  763.                  
  764.       
  765.  
  766.  
  767.  
  768.  
  769.  
  770.       GetEqual
  771.       
  772.       TYPE       FUNCTION
  773.       
  774.       SYNTAX     stat = GetEqual(kfile,dfile,Qkey$,Qrec$)
  775.       
  776.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  777.                  dfile - INTEGER.Number used as fileno in OpenDataFile().
  778.                  Qkey$ - STRING.The key (or partial key) to search for.
  779.                  Qrec$ - STRING.The data record for the found key is 
  780.                  placed in this variable.
  781.       
  782.       USE        Search for the key Qkey$ in kfile. If it's found, return 
  783.                  the data record that it's pointing to in Qrec$. If it's 
  784.                  not found the QBTree tracking pointers are positioned so 
  785.                  that by using GetNext() or GetPrev() the key records 
  786.                  after or before could be found.
  787.                  
  788.       RULES      Qkey$ must not begin with an ASCII 0 or 255.
  789.                  
  790.       NOTES      For partial searches use a key that you want to start 
  791.                  the search on.
  792.                  For instance, to find all surnames starting with a key 
  793.                  of KING in your database, use a Qkey$ = "KING". Even if 
  794.                  there is no exact match with GetEqual() you can still get 
  795.                  all other records starting with KING, e.g., KINGMAN, 
  796.                  KINGSTON, etc., by using the GetNext() routine while 
  797.                  LEFT$(Qkey$,4) = "KING", or until the end of file is 
  798.                  reached.
  799.       
  800.       RETURN     Errors 200, 202, 204, 219, 222, 223, and DOS.
  801.       
  802.       EXAMPLE    INPUT "Get which key ";Qkey$
  803.                  stat = GetEqual(0,0,Qkey$,Qrec$)
  804.                  IF stat = 0 THEN 
  805.                     PRINT "Record=";Qrec$
  806.                  
  807.       
  808.  
  809.  
  810.  
  811.  
  812.  
  813.       GetFirst
  814.       
  815.       TYPE       FUNCTION
  816.       
  817.       SYNTAX     stat = GetFirst(kfile,dfile,Qkey$,Qrec$)
  818.       
  819.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  820.                  dfile - INTEGER.Number used as fileno in OpenDataFile().
  821.                  Qkey$ - STRING.The first key in kfile is placed in this 
  822.                  variable.
  823.                  Qrec$ - STRING.The data record for the first key is 
  824.                  placed in this variable.
  825.       
  826.       USE        Get the first key in kfile and return it in Qkey$. Also 
  827.                  get that key's data record and return it in Qrec$. Since 
  828.                  QBTree sorts on ASCII values, the first key will be the 
  829.                  key with the lowest ASCII value.
  830.       
  831.       RULES      None.
  832.       
  833.       NOTES      For sequential in-order processing of the entire data 
  834.                  file in kfile order, you would want to start at the very 
  835.                  first key; this function does just that. After processing 
  836.                  this first key and record, use GetNext() and continue 
  837.                  processing until end of file (error 202).
  838.       
  839.       RETURN     Errors 204, 219, 222, and DOS.
  840.       
  841.       EXAMPLE    stat = GetFirst(0,0,Qkey$,Qrec$)
  842.                  IF stat = 0 THEN 
  843.                     PRINT "First key="; Qkey$
  844.                  
  845.       
  846.  
  847.  
  848.  
  849.  
  850.  
  851.       GetGT
  852.       
  853.       TYPE       FUNCTION
  854.       
  855.       SYNTAX     stat = GetGT(kfile,dfile,Qkey$,Qrec$)
  856.       
  857.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  858.                  dfile - INTEGER.Number used as fileno in OpenDataFile().
  859.                  Qkey$ - STRING.Get the next key greater than Qkey$ in 
  860.                  kfile and also place it in this variable.
  861.                  Qrec$ - STRING.The data record for this GT key is placed 
  862.                  in this variable.
  863.                  
  864.       USE        Get the next key in kfile that is greater than Qkey$ and 
  865.                  return it in Qkey$. Also get that key's data record and 
  866.                  return it in Qrec$.
  867.       
  868.       RULES      None.
  869.       
  870.       NOTES      The original value in Qkey$ is replaced with the next GT 
  871.                  key.
  872.       
  873.       RETURN     Errors 202, 204, 219, 222, and DOS.
  874.       
  875.       EXAMPLE    INPUT "Get first key greater than ";lastkey$
  876.                  stat = GetGT(0,0,lastkey$,Qrec$)
  877.                  IF stat = 0 THEN
  878.                     PRINT "First greater key=";lastkey$
  879.                  
  880.       
  881.  
  882.  
  883.  
  884.  
  885.  
  886.       GetGTE
  887.       
  888.       TYPE       FUNCTION
  889.       
  890.       SYNTAX     stat = GetGTE(kfile,dfile,Qkey$,Qrec$)
  891.       
  892.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  893.                  dfile - INTEGER.Number used as fileno in OpenDataFile().
  894.                  Qkey$ - STRING.Get the next key greater or equal to 
  895.                  Qkey$ in kfile and also place it in this variable.
  896.                  Qrec$ - STRING.The data record for this GTE key is 
  897.                  placed in this variable.
  898.       
  899.       USE        Get the next key in kfile that is greater or equal to 
  900.                  Qkey$ and return it in Qkey$. Also get that key's data 
  901.                  record and return it in Qrec$.
  902.       
  903.       RULES      None.
  904.       
  905.       NOTES      The original value in Qkey$ is replaced with the next 
  906.                  GTE key.
  907.       
  908.       RETURN     Errors 202, 204, 219, 222, and DOS.
  909.       
  910.       EXAMPLE    INPUT "Get first key GTE to ";lastkey$
  911.                  stat = GetGTE(0,0,lastkey$,Qrec$)
  912.                  IF stat = 0 THEN
  913.                     PRINT "First key GTE=";lastkey$
  914.                  
  915.       
  916.  
  917.  
  918.  
  919.  
  920.  
  921.       GetLast
  922.       
  923.       TYPE       FUNCTION
  924.       
  925.       SYNTAX     stat = GetLast(kfile,dfile,Qkey$,Qrec$)
  926.       
  927.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  928.                  dfile - INTEGER.Number used as fileno in OpenDataFile().
  929.                  Qkey$ - STRING.The last key in kfile is placed in this 
  930.                  variable.
  931.                  Qrec$ - STRING.The data record for the last key is 
  932.                  placed in this variable.
  933.       
  934.       USE        Get the last key in kfile and return it in Qkey$. Also 
  935.                  get that key's data record and return it in Qrec$. Since 
  936.                  QBTree sorts on ASCII values, the last key will be the 
  937.                  key with the highest ASCII value.
  938.       
  939.       RULES      None.
  940.       
  941.       NOTES      For sequential reverse-order processing of the entire 
  942.                  data file in kfile order, you would want to start at the 
  943.                  very last key; this function does just that. After 
  944.                  processing this last key and record, use GetPrev() and 
  945.                  continue processing until top of file (error 203).
  946.                  
  947.       RETURN     Errors 204, 219, 222, and DOS.
  948.       
  949.       EXAMPLE    stat = GetLast(0,0,Qkey$,Qrec$)
  950.                  IF stat = 0 THEN
  951.                     PRINT "Last key="; Qkey$
  952.                  
  953.       
  954.  
  955.  
  956.  
  957.  
  958.  
  959.       GetLT
  960.       
  961.       TYPE       FUNCTION
  962.       
  963.       SYNTAX     stat = GetLT(kfile,dfile,Qkey$,Qrec$)
  964.  
  965.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  966.                  dfile - INTEGER.Number used as fileno in OpenDataFile().
  967.                  Qkey$ - STRING.Get the previous key less than Qkey$ in 
  968.                  kfile and also place it in this variable.
  969.                  Qrec$ - STRING.The data record for this LT key is placed 
  970.                  in this variable.
  971.       
  972.       USE        Get the previous key in kfile that is less than Qkey$ 
  973.                  and return it in Qkey$. Also get that key's data record 
  974.                  and return it in Qrec$.
  975.       
  976.       RULES      None.
  977.       
  978.       NOTES      The original value in Qkey$ is replaced with the 
  979.                  previous LT key.
  980.       
  981.       RETURN     Errors 203, 204, 219, 222, and DOS.
  982.                  
  983.       EXAMPLE    INPUT "Get key less than ";lastkey$
  984.                  stat = GetLT(0,0,lastkey$,Qrec$)
  985.                  IF stat = 0 THEN
  986.                     PRINT "Last less than key=";lastkey$
  987.                  
  988.       
  989.  
  990.  
  991.  
  992.  
  993.  
  994.       GetLTE
  995.       
  996.       TYPE       FUNCTION
  997.       
  998.       SYNTAX     stat = GetLTE(kfile,dfile,Qkey$,Qrec$)
  999.       
  1000.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  1001.                  dfile - INTEGER.Number used as fileno in OpenDataFile().
  1002.                  Qkey$ - STRING.Get the previous key less or equal to 
  1003.                  Qkey$ in kfile and also place it in this variable.
  1004.                  Qrec$ - STRING.The data record for this LTE key is 
  1005.                  placed in this variable.
  1006.                  
  1007.       USE        Get the previous key in kfile that is less or equal to 
  1008.                  Qkey$ and return it in Qkey$. Also get that key's data 
  1009.                  record and return it in Qrec$.
  1010.       
  1011.       RULES      None.
  1012.       
  1013.       NOTES      The original value in Qkey$ is replaced with the 
  1014.                  previous LTE key.
  1015.       
  1016.       RETURN     Errors 203, 204, 219, 222, and DOS.
  1017.       
  1018.       EXAMPLE    INPUT "Get key LTE to ";lastkey$
  1019.                  stat = GetLTE(0,0,lastkey$,Qrec$)
  1020.                  IF stat = 0 THEN
  1021.                     PRINT "Last LTE=";lastkey$
  1022.                  
  1023.       
  1024.  
  1025.  
  1026.  
  1027.  
  1028.  
  1029.       GetNext
  1030.       
  1031.       TYPE       FUNCTION
  1032.       
  1033.       SYNTAX     stat = GetNext(kfile,dfile,Qkey$,Qrec$)
  1034.       
  1035.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  1036.                  dfile - INTEGER.Number used as fileno in OpenDataFile().
  1037.                  Qkey$ - STRING.The next key in kfile is placed in this 
  1038.                  variable.
  1039.                  Qrec$ - STRING.The data record for this next key is 
  1040.                  placed in this variable.
  1041.       
  1042.       USE        Get the next key in kfile and return it in Qkey$. Also 
  1043.                  get that key's data record and return it in Qrec$. Use 
  1044.                  this function to process the key file sequentially 
  1045.                  in-order. 
  1046.       
  1047.       RULES      None.
  1048.       
  1049.       NOTES      This function is usually used after a GetFirst() or 
  1050.                  GetEqual(). If you are searching for a key based on a 
  1051.                  partial key, use GetEqual() with the partial key and 
  1052.                  continue searching with GetNext() until you either find 
  1053.                  the key you want, determine that it's not in the key 
  1054.                  file, or reach the end of file.
  1055.                  
  1056.       RETURN     Errors 202, 204, 219, 222, and DOS.
  1057.       
  1058.       EXAMPLE    partkey$ = "73ST"
  1059.                  stat = GetEqual(0,0,partkey$,Qrec$)
  1060.                  IF stat = 200 THEN 
  1061.                     DO
  1062.                        stat = GetNext(0,0,Qkey$,Qrec$)
  1063.                        IF stat = 0 THEN 
  1064.                           IsKey = AskIfWantedKey(Qkey$)
  1065.                           IF IsKey THEN EXIT DO
  1066.                        ENDIF
  1067.                     LOOP WHILE stat = 0
  1068.                  
  1069.       
  1070.  
  1071.  
  1072.  
  1073.  
  1074.  
  1075.       GetPosition
  1076.       
  1077.       TYPE       FUNCTION
  1078.       
  1079.       SYNTAX     stat = GetPosition(kfile,recno&)
  1080.       
  1081.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  1082.                  recno& - LONG.The current record number last used by 
  1083.                  kfile is placed in this variable.
  1084.       
  1085.       USE        Get the last data record number accessed by kfile. This 
  1086.                  record number is updated everytime you use any of the Add 
  1087.                  or Get functions (excluding GetDirect), or UpdateRecord().
  1088.       
  1089.       RULES      None.
  1090.       
  1091.       NOTES      This function is a special-use routine. If you construct 
  1092.                  relational-based file structures only then this function 
  1093.                  would not be needed. However, there are times, when for 
  1094.                  reasons of speed or simplicity, that you need to sidestep 
  1095.                  relational ideals.
  1096.                  Let's say we have 2 key files, k1 and k2, both pointing 
  1097.                  to the same data record in the single data file, d1. We 
  1098.                  want to delete a key in k1 and its data record in d1, and 
  1099.                  also delete the key in k2 that is pointing to that same 
  1100.                  record in d1. We know there is a key in k2 that points to 
  1101.                  that record in d1. The problem is that, since we don't 
  1102.                  have the key of k2 imbedded in the record, we don't have 
  1103.                  enough information in k2 to allow us to find the key to 
  1104.                  delete by using any of the Get() routines. What we need 
  1105.                  to do is GetEqual() the key to delete in k1, and then do 
  1106.                  a GetPosition() on k1 and save the record number 
  1107.                  returned. Then we do a GetFirst() of k2, do a 
  1108.                  GetPosition(), check to see if it's the same record 
  1109.                  number as the k1 key, and if so, we found the k2 key to 
  1110.                  delete. If it's not the same, we use 
  1111.                  GetNext()/GetPosition() until we find it. When we find a 
  1112.                  match, we use DeleteKey() on the k2 key returned by 
  1113.                  GetNext(), and then DeleteKeyRecord() the k1 key we know 
  1114.                  about. Both keys and the data record are now deleted.
  1115.                  See LockRecord() for another use of this function.
  1116.       
  1117.       RETURN     Error 219, 222.
  1118.       
  1119.       EXAMPLE    stat = GetFirst(k1,d1,Qkey$,Qrec$)
  1120.                  PRINT "First key in k1 is using record#";
  1121.                  stat = GetPosition(k1,recno&)
  1122.                  PRINT recno&
  1123.                  
  1124.       
  1125.  
  1126.  
  1127.  
  1128.  
  1129.  
  1130.       GetPrev
  1131.       
  1132.       TYPE       FUNCTION
  1133.       
  1134.       SYNTAX     stat = GetPrev(kfile,dfile,Qkey$,Qrec$)
  1135.       
  1136.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  1137.                  dfile - INTEGER.Number used as fileno in OpenDataFile().
  1138.                  Qkey$ - STRING.The previous key in kfile is placed in 
  1139.                  this variable.
  1140.                  Qrec$ - STRING.The data record for this previous key is 
  1141.                  placed in this variable.
  1142.                  
  1143.       USE        Get the previous key in kfile and return it in Qkey$. 
  1144.                  Also get that key's data record and return it in Qrec$. 
  1145.                  Use this function to process the key file sequentially in 
  1146.                  reverse-order. 
  1147.       
  1148.       RULES      None.
  1149.       
  1150.       NOTES      This function is usually used after a GetLast() or 
  1151.                  GetEqual(). If you are searching for a key based on a 
  1152.                  partial key, use GetEqual() with the partial key and 
  1153.                  continue searching with GetPrev() until you either find 
  1154.                  the key you want, determine that it's not in the key 
  1155.                  file, or reach the top of file.
  1156.       
  1157.       RETURN     Errors 203, 204, 219, 222, and DOS.
  1158.  
  1159.       EXAMPLE    partkey$ = "73STZZZZ"
  1160.                  stat = GetEqual(0,0,partkey$,Qrec$)
  1161.                  IF stat = 200 THEN 
  1162.                     DO
  1163.                        stat = GetPrev(0,0,Qkey$,Qrec$)
  1164.                        IF stat = 0 THEN 
  1165.                           IsKey = AskIfWantedKey(Qkey$)
  1166.                           IF IsKey THEN EXIT DO
  1167.                        ENDIF
  1168.                     LOOP WHILE stat = 0
  1169.                  
  1170.       
  1171.  
  1172.  
  1173.  
  1174.  
  1175.  
  1176.       InitQBTree
  1177.       
  1178.       TYPE       FUNCTION
  1179.       
  1180.       SYNTAX     stat = InitQBTree(MKF,MDF)
  1181.       
  1182.       PARAMETERS MKF - INTEGER.Maximum number of key files that you plan 
  1183.                  on using this session (0-based).
  1184.                  MDF - INTEGER.Maximum number of data files that you plan 
  1185.                  on using this session (0-based).
  1186.       
  1187.       USE        Initialize the QBTree file system and allocate the  
  1188.                  required buffers.
  1189.       
  1190.       RULES      This function must be called before any other QBTree 
  1191.                  function.
  1192.       
  1193.       NOTES      QBTree sets aside buffers for each file  request you make
  1194.                  with MKF and MDF. These buffers are created dynamically, 
  1195.                  e.g., REDIM keybuff(0 TO MKF) AS keynodeTYPE, where each 
  1196.                  element in the array is reserved for a separate file. 
  1197.                  Using QBTree functions without having first called this 
  1198.                  function may cause various BASIC run-time errors.
  1199.                  QBTree lets you open and use up to 250 files at one time 
  1200.                  using DOS 3+. However, the FILES= statement in CONFIG.SYS 
  1201.                  will be the limiting factor in how many you can actually 
  1202.                  use. The internal routine SFTFiles() can be used to 
  1203.                  determine what the FILES= is.
  1204.       
  1205.       RETURN     Errors 225, 234.
  1206.                  
  1207.       EXAMPLE    'need 30 key and 10 data files this session
  1208.                  stat = InitQBTree(29,9)
  1209.                  'can OpenKeyFile(file$,numkey,asmode) where numkey
  1210.                  'is 0-29 and OpenDataFile(file$,numdat,asmode)
  1211.                  'where numdat is 0-9.
  1212.                  
  1213.       
  1214.  
  1215.  
  1216.  
  1217.  
  1218.  
  1219.       LockDataHeader
  1220.       
  1221.       TYPE       FUNCTION
  1222.       
  1223.       SYNTAX     stat = LockDataHeader(dfile)
  1224.       
  1225.       PARAMETERS dfile - INTEGER.Number used as fileno in OpenDataFile().
  1226.                  
  1227.       USE        Network. Lock the data header of dfile so that no other 
  1228.                  process may read or write it.
  1229.       
  1230.       RULES      SHARE.EXE must be installed.
  1231.                  You must unlock the data header when you no longer need 
  1232.                  exclusive access to it. If your program terminates 
  1233.                  without unlocking active locks, the result is undefined.
  1234.       
  1235.       NOTES      This function is not needed if dfile's asmode=&H12.
  1236.                  This function is needed only if the data file is being 
  1237.                  used on a network and you need to ensure that no other 
  1238.                  process will change things while you are working on the 
  1239.                  file. In addition to locking the data header, you may 
  1240.                  also need to lock a specific record in dfile or even all 
  1241.                  the records in dfile using LockRecord().
  1242.                  Anytime you use AddKeyRecord() or DeleteKeyRecord() you 
  1243.                  must first lock the data header and then lock all 
  1244.                  records. 
  1245.                  This function will automatically call LoadDataHeader(), 
  1246.                  an internal routine, to refresh the data file header 
  1247.                  information from disk.
  1248.                  
  1249.       RETURN     Errors 219, 222, and DOS.
  1250.       
  1251.       EXAMPLE    stat = OpenDataFile(datfile$,0,asmode)
  1252.                  IF stat = 0 THEN
  1253.                     FOR retries = 1 to MaxRetries
  1254.                        stat = LockDataHeader(0)
  1255.                        IF stat = 0 THEN
  1256.                           EXIT FOR
  1257.                        ELSE
  1258.                           RetryDelayAbit
  1259.                        ENDIF
  1260.                     NEXT
  1261.                     IF stat THEN DoAccessError stat
  1262.                  
  1263.       
  1264.  
  1265.  
  1266.  
  1267.  
  1268.  
  1269.       LockKeyFile
  1270.       
  1271.       TYPE       FUNCTION
  1272.       
  1273.       SYNTAX     stat = LockKeyFile(kfile)
  1274.       
  1275.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  1276.       
  1277.       USE        Network. Lock the key file so that no other process may 
  1278.                  read or write it.
  1279.       
  1280.       RULES      SHARE.EXE must be installed.
  1281.                  You must unlock the key file when you no longer need 
  1282.                  exclusive access to it. If your program terminates 
  1283.                  without unlocking active locks, the result is undefined.
  1284.       
  1285.       NOTES      This function is not needed if kfile's asmode=&H12.
  1286.                  This function is needed only if the key file is being 
  1287.                  used on a network and there's a possibility that another 
  1288.                  process may access it.
  1289.                   This locks the file by locking all bytes within it.
  1290.                  Anytime you use AddKey(), AddKeyRecord(), DeleteKey(), 
  1291.                  DeleteKeyRecord(), or StoreKey() you must first lock the 
  1292.                  key file. 
  1293.                  This function will automatically call LoadKeyHeader(), 
  1294.                  an internal routine, to refresh the key file header 
  1295.                  information from disk.
  1296.       
  1297.       RETURN     Errors 219, 222, and DOS.
  1298.       
  1299.       EXAMPLE    stat = OpenKeyFile(keyfile$,0,asmode)
  1300.                  IF stat = 0 THEN
  1301.                     FOR retries = 1 to MaxRetries
  1302.                        stat = LockKeyFile(0)
  1303.                        IF stat = 0 THEN
  1304.                           EXIT FOR
  1305.                        ELSE
  1306.                           RetryDelayAbit
  1307.                        ENDIF
  1308.                     NEXT
  1309.                     IF stat THEN DoAccessError stat
  1310.                  
  1311.       
  1312.  
  1313.  
  1314.  
  1315.  
  1316.  
  1317.       LockRecord
  1318.       
  1319.       TYPE       FUNCTION
  1320.       
  1321.       SYNTAX     stat = LockRecord(dfile,recno&)
  1322.       
  1323.       PARAMETERS dfile - INTEGER.Number used as fileno in OpenDataFile().
  1324.                  recno& - LONG.Record number in dfile to lock, or if 0, 
  1325.                  lock all records in dfile.
  1326.       
  1327.       USE        Network. Lock the record(s) in dfile so that no other 
  1328.                  process may read or write it.
  1329.       
  1330.       RULES      SHARE.EXE must be installed.
  1331.                  You must unlock the record when you no longer need 
  1332.                  exclusive access to it. If you lock multiple records by 
  1333.                  calling LockRecord() multiple times then each record 
  1334.                  needs to be unlocked using UnlockRecord() an equal number 
  1335.                  of times. If your program terminates without unlocking 
  1336.                  active locks, the result is undefined.
  1337.                  
  1338.       NOTES      This function is not needed if dfile's asmode=&H12.
  1339.                  This function is needed only if the data file is being 
  1340.                  used on a network and you need to ensure that no other 
  1341.                  process will change the current record you're working on. 
  1342.                  In addition to locking a specific record you may need to 
  1343.                  lock the data header.
  1344.                  Anytime you use AddKeyRecord() or DeleteKeyRecord() you 
  1345.                  must lock the data header and lock all records (recno&=0) 
  1346.                  in addition to using LockKeyFile().
  1347.                  If you are using one of the Get() functions to access 
  1348.                  the data file and plan on using UpdateRecord(), use 
  1349.                  GetPosition() after the Get() function to determine which 
  1350.                  record you need to lock before performing the update.
  1351.       
  1352.       RETURN     Errors 219, 222, and DOS.
  1353.       
  1354.       EXAMPLE    stat = OpenDataFile(datfile$,0,asmode)
  1355.                  IF stat = 0 THEN
  1356.                     FOR retries = 1 to MaxRetries
  1357.                        stat = LockDataHeader(0)
  1358.                        IF stat = 0 THEN
  1359.                           EXIT FOR
  1360.                        ELSE
  1361.                           RetryDelayAbit
  1362.                        ENDIF
  1363.                     NEXT
  1364.                     IF stat = 0 THEN stat = LockRecord(0,0)
  1365.                  
  1366.       
  1367.  
  1368.  
  1369.  
  1370.  
  1371.  
  1372.       OpenDataFile
  1373.       
  1374.       TYPE       FUNCTION
  1375.       
  1376.       SYNTAX     stat = OpenDataFile(filename$,fileno,asmode)
  1377.  
  1378.       PARAMETERS filename$ - STRING.Pathname of data file to open.
  1379.                  fileno - INTEGER.Number to associate the data file with 
  1380.                  for future operations. Valid range is 0 to MDF.
  1381.                  asmode - INTEGER.Network. When asmode (Access/Sharing 
  1382.                  mode) is:
  1383.                  &H42 open with shared R/W access (others R/W access),
  1384.                     2 open in DOS 2.x compatible R/W mode (not for networks),
  1385.                  &H12 open with exclusive R/W access (others have no access),
  1386.                  &H22 open with exclusive W access (others have read access),
  1387.                  &H32 open with exclusive R access (others have write access),
  1388.                       any valid DOS value permitted.
  1389.       
  1390.       USE        Open an existing QBTree data file with the mode 
  1391.                  determined by asmode.
  1392.                  
  1393.       RULES      fileno can be any unused fileno 0 to MDF. See InitQBTREE.
  1394.                  SHARE.EXE must be installed to use any of the exclusive 
  1395.                  access modes as well as any QBTree locking function (a 
  1396.                  LAN is not required).
  1397.       
  1398.       NOTES      For simplified network programming where the file can be 
  1399.                  opened for exclusive use set asmode to &H12. As long as 
  1400.                  the file remains open no other process may access any 
  1401.                  part of it. Using asmode = &H12 means that you do not 
  1402.                  need to use any of the other network support functions to 
  1403.                  successfully share the file on a network. If you need to 
  1404.                  use specific record locks set asmode to &H42. For 
  1405.                  non-network programs use asmode=2.
  1406.                  The fileno actually represent the data buffer index that 
  1407.                  this file will be using.
  1408.                  
  1409.       RETURN     Errors 219, 227, 228, 233, and DOS.
  1410.                  
  1411.      EXAMPLE     dfile = 0
  1412.                  asmode = &H42
  1413.                  stat = OpenDataFile(filename$,dfile,asmode)
  1414.                  
  1415.       
  1416.  
  1417.  
  1418.  
  1419.  
  1420.  
  1421.       OpenKeyFile
  1422.       
  1423.       TYPE       FUNCTION
  1424.       
  1425.       SYNTAX     stat = OpenKeyFile(filename$,fileno,asmode)
  1426.       
  1427.       PARAMETERS filename$ - STRING.Pathname of key file to open.
  1428.                  fileno - INTEGER.Number to associate the key file with 
  1429.                  for future operations. Valid range is 0 to MKF.
  1430.                  asmode - INTEGER.Network. When asmode (Access/Sharing 
  1431.                  mode) is:
  1432.                  &H42 open with shared R/W access (others R/W access),
  1433.                     2 open in DOS 2.x compatible R/W mode (not for networks),
  1434.                  &H12 open with exclusive R/W access (others have no access),
  1435.                  &H22 open with exclusive W access (others have read access),
  1436.                  &H32 open with exclusive R access (others have write access),
  1437.                       any valid DOS value permitted.
  1438.       
  1439.       USE        Open an existing QBTree key file with the mode 
  1440.                  determined by asmode.
  1441.                  
  1442.       RULES      fileno can be any unused fileno 0 to MKF. See 
  1443.                  InitQBTREE. 
  1444.                  SHARE.EXE must be installed to use any of the exclusive 
  1445.                  access modes as well as any QBTree locking function (a 
  1446.                  LAN is not required).
  1447.                  
  1448.       NOTES      For simplified network programming where the file can be 
  1449.                  opened for exclusive use set asmode to &H12. As long as 
  1450.                  the file remains open no other process may access any 
  1451.                  part of it. Using asmode = &H12 means that you do not 
  1452.                  need to use any of the other network support functions to 
  1453.                  successfully share the file on a network. If you need to 
  1454.                  use specific record locks set asmode to &H42. For 
  1455.                  non-network programs use asmode=2.
  1456.                  The fileno actually represent the key buffer index that 
  1457.                  this file will be using.
  1458.                  
  1459.       RETURN     Errors 219, 227, 228, 233, and DOS.
  1460.  
  1461.      EXAMPLE     kfile = 0
  1462.                  asmode = &H42
  1463.                  stat = OpenKeyFile(filename$,kfile,asmode)
  1464.                  
  1465.       
  1466.  
  1467.  
  1468.  
  1469.  
  1470.  
  1471.       RetrieveEqual
  1472.       
  1473.       TYPE       FUNCTION
  1474.       
  1475.       SYNTAX     stat = RetrieveEqual(kfile,Qkey$,Qrecno&)
  1476.                  
  1477.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  1478.                  Qkey$ - STRING.The key (or partial key) to search for.
  1479.                  Qrecno& - LONG.The record number that Qkey$ indexes is 
  1480.                  placed in this variable.
  1481.       
  1482.       USE        Search for the key Qkey$ in kfile. If it is found, 
  1483.                  return the record number that was set for this key by 
  1484.                  StoreKey(). If it's not found the QBTree tracking 
  1485.                  pointers are positioned so that by using RetrieveNext() 
  1486.                  or RetrievePrev() the keys after or before could be found.
  1487.                  
  1488.       RULES      Qkey$ must not begin with an ASCII 0 or 255.
  1489.                  
  1490.       NOTES      For partial searches use a key that you want to start 
  1491.                  the search on.
  1492.                  For instance, to find all surnames starting with KING in 
  1493.                  your database, use a Qkey$ = "KING". Even if there is no 
  1494.                  exact match with RetrieveEqual() you can still get all 
  1495.                  other keys starting with KING, e.g., KINGMAN, KINGSTON, 
  1496.                  etc., by using the RetrieveNext() routine while 
  1497.                  LEFT$(Qkey$,4) = "KING", or until the end of file is 
  1498.                  reached.
  1499.                  Unlike the Get() functions, the Retrieve() functions 
  1500.                  operate only on key files. Any data file handling is left 
  1501.                  to you using whatever data file format you need.
  1502.                  
  1503.       RETURN     Errors 200, 202, 204, 219, 222, 223, and DOS.
  1504.       
  1505.       EXAMPLE    stat = RetrieveEqual(0,Qkey$,Qrecno&)
  1506.                  IF stat = 200 THEN 
  1507.                     stat = RetrieveNext(0,Qkey$,Qrecno&)
  1508.                  
  1509.       
  1510.  
  1511.  
  1512.  
  1513.  
  1514.  
  1515.       RetrieveFirst
  1516.       
  1517.       TYPE       FUNCTION
  1518.       
  1519.       SYNTAX     stat = RetrieveFirst(kfile,Qkey$,Qrecno&)
  1520.       
  1521.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  1522.                  Qkey$ - STRING.The first key in kfile is placed in this 
  1523.                  variable.
  1524.                  Qrecno& - LONG.The record number that the first key 
  1525.                  indexes is placed in this variable.
  1526.       
  1527.       USE        Get the first key in kfile and return it in Qkey$. Also 
  1528.                  get that key's record number and return it in Qrecno&. 
  1529.                  Since QBTree sorts on ASCII values, the first key will be 
  1530.                  the key with the lowest ASCII value.
  1531.                  
  1532.       RULES      None.
  1533.       
  1534.       NOTES      For sequential in-order processing of the entire key 
  1535.                  file, you would want to start at the very first key; this 
  1536.                  function does just that. After processing this first key, 
  1537.                  use RetrieveNext() and continue processing until end of 
  1538.                  file (error 202).
  1539.       
  1540.       RETURN     Errors 204, 219, 222, and DOS.
  1541.       
  1542.       EXAMPLE    stat = RetrieveFirst(0,Qkey$,Qrecno&)
  1543.                  IF stat = 0 THEN 
  1544.                     PRINT "First key "; Qkey$
  1545.                     PRINT "indexes record number"; Qrecno&
  1546.                  
  1547.       
  1548.  
  1549.  
  1550.  
  1551.  
  1552.  
  1553.       RetrieveGT
  1554.       
  1555.       TYPE       FUNCTION
  1556.       
  1557.       SYNTAX     stat = RetrieveGT(kfile,Qkey$,Qrecno&)
  1558.       
  1559.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  1560.                  Qkey$ - STRING.Get the next key greater than Qkey$ in 
  1561.                  kfile and also place it in this variable.
  1562.                  Qrecno& - LONG.The record number that the next GT key 
  1563.                  indexes is placed in this variable.
  1564.       
  1565.       USE        Get the next key in kfile that is greater than Qkey$ and 
  1566.                  return it in Qkey$. Also get that key's data record 
  1567.                  number and return it in Qrecno&.
  1568.       
  1569.       RULES      None.
  1570.       
  1571.       NOTES      The original value in Qkey$ is replaced with the next GT 
  1572.                  key.
  1573.                  
  1574.       RETURN     Errors 202, 204, 219, 222, and DOS.
  1575.       
  1576.       EXAMPLE    stat = RetrieveGT(0,lastkey$,Qrecno&)
  1577.                  IF stat = 0 THEN
  1578.                     PRINT "Rec# of first greater key=";Qrecno&
  1579.                  
  1580.       
  1581.  
  1582.  
  1583.  
  1584.  
  1585.  
  1586.       RetrieveGTE
  1587.       
  1588.       TYPE       FUNCTION
  1589.       
  1590.       SYNTAX     stat = RetrieveGTE(kfile,Qkey$,Qrecno&)
  1591.       
  1592.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  1593.                  Qkey$ - STRING.Get the next key greater or equal to 
  1594.                  Qkey$ in kfile and also place it in this variable.
  1595.                  Qrecno& - LONG.The record number that the next GTE key 
  1596.                  indexes is placed in this variable.
  1597.       
  1598.       USE        Get the next key in kfile that is greater or equal to 
  1599.                  Qkey$ and return it in Qkey$. Also get that key's data 
  1600.                  record number and return it in Qrecno&.
  1601.                  
  1602.       RULES      None.
  1603.       
  1604.       NOTES      The original value in Qkey$ is replaced with the next 
  1605.                  GTE key.
  1606.       
  1607.       RETURN     Errors 202, 204, 219, 222, and DOS.
  1608.       
  1609.       EXAMPLE    stat = RetrieveGTE(0,lastkey$,Qrecno&)
  1610.                  IF stat = 0 THEN
  1611.                     PRINT "Rec# for first GTE=";Qrecno&
  1612.                  
  1613.       
  1614.  
  1615.  
  1616.  
  1617.  
  1618.  
  1619.       RetrieveLast
  1620.       
  1621.       TYPE       FUNCTION
  1622.       
  1623.       SYNTAX     stat = RetrieveLast(kfile,Qkey$,Qrecno&)
  1624.       
  1625.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  1626.                  Qkey$ - STRING.The last key in kfile is placed in this 
  1627.                  variable.
  1628.                  Qrecno& - LONG.The record number that the last key 
  1629.                  indexes is placed in this variable.
  1630.       
  1631.       USE        Get the last key in kfile and return it in Qkey$. Also 
  1632.                  get that key's record number and return it in Qrecno&. 
  1633.                  Since QBTree sorts on ASCII values, the last key will be 
  1634.                  the key with the highest ASCII value.
  1635.       
  1636.       RULES      None.
  1637.       
  1638.       NOTES      For sequential reverse-order processing of the entire 
  1639.                  key file, you would want to start at the very last key; 
  1640.                  this function does just that. After processing this last 
  1641.                  key, use RetrievePrev() and continue processing until top 
  1642.                  of file (error 203).
  1643.                  
  1644.       RETURN     Errors 204, 219, 222, and DOS.
  1645.       
  1646.       EXAMPLE    stat = RetrieveLast(0,Qkey$,Qrecno&)
  1647.                  IF stat = 0 THEN 
  1648.                     PRINT "Last key "; Qkey$
  1649.                     PRINT "indexes record number"; Qrecno&
  1650.                  
  1651.       
  1652.  
  1653.  
  1654.  
  1655.  
  1656.  
  1657.       RetrieveLT
  1658.       
  1659.       TYPE       FUNCTION
  1660.       
  1661.       SYNTAX     stat = RetrieveLT(kfile,Qkey$,Qrecno&)
  1662.       
  1663.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  1664.                  Qkey$ - STRING.Get the previous key less than Qkey$ in 
  1665.                  kfile and also place it in this variable.
  1666.                  Qrecno& - LONG.The record number that the previous LT 
  1667.                  key indexes is placed in this variable.
  1668.       
  1669.       USE        Get the previous key in kfile that is less than Qkey$ 
  1670.                  and return it in Qkey$. Also get that key's data record 
  1671.                  number and return it in Qrecno&.
  1672.                  
  1673.       RULES      None.
  1674.       
  1675.       NOTES      The original value in Qkey$ is replaced with the 
  1676.                  previous LT key.
  1677.       
  1678.       RETURN     Errors 203, 204, 219, 222, and DOS.
  1679.                  
  1680.       EXAMPLE    stat = RetrieveLT(0,lastkey$,Qrecno&)
  1681.                  IF stat = 0 THEN
  1682.                     PRINT "Rec# to last less than key=";Qrecno&
  1683.                  
  1684.       
  1685.  
  1686.  
  1687.  
  1688.  
  1689.  
  1690.       RetrieveLTE
  1691.       
  1692.       TYPE       FUNCTION
  1693.       
  1694.       SYNTAX     stat = RetrieveLTE(kfile,Qkey$,Qrecno&)
  1695.       
  1696.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  1697.                  Qkey$ - STRING.Get the previous key less or equal to 
  1698.                  Qkey$ in kfile and also place it in this variable.
  1699.                  Qrecno& - LONG.The record number that the previous LTE 
  1700.                  key indexes is placed in this variable.
  1701.       
  1702.       USE        Get the previous key in kfile that is less or equal to 
  1703.                  Qkey$ and return it in Qkey$. Also get that key's data 
  1704.                  record number and return it in Qrecno&.
  1705.       
  1706.       RULES      None.
  1707.       
  1708.       NOTES      The original value in Qkey$ is replaced with the 
  1709.                  previous LTE key.
  1710.       
  1711.       RETURN     Errors 203, 204, 219, 222, and DOS.
  1712.       
  1713.       EXAMPLE    stat = RetrieveLTE(0,lastkey$,Qrecno&)
  1714.                  IF stat = 0 THEN
  1715.                     PRINT "Rec# to last LTE key=";Qrecno&
  1716.                  
  1717.       
  1718.  
  1719.  
  1720.  
  1721.  
  1722.  
  1723.       RetrieveNext
  1724.       
  1725.       TYPE       FUNCTION
  1726.       
  1727.       SYNTAX     stat = RetrieveNext(kfile,Qkey$,Qrecno&)
  1728.       
  1729.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  1730.                  Qkey$ - STRING.The next key in kfile is placed in this 
  1731.                  variable.
  1732.                  Qrecno& - LONG.The record number that the next key 
  1733.                  indexes is placed in this variable.
  1734.       
  1735.       USE        Get the next key in kfile and return it in Qkey$. Also 
  1736.                  get that key's record number and return it in Qrecno&. 
  1737.                  Use this function to process the key file sequentially 
  1738.                  in-order. 
  1739.                  
  1740.       RULES      None.
  1741.                  
  1742.       NOTES      This function is usually used after a RetrieveFirst() or 
  1743.                  RetrieveEqual(). If you are searching for a key based on 
  1744.                  a partial key, use RetrieveEqual() with the partial key 
  1745.                  and continue searching with RetrieveNext() until you 
  1746.                  either find the key you want, determine that it's not in 
  1747.                  the key file, or reach the end of file.
  1748.       
  1749.       RETURN     Errors 202, 204, 219, 222, and DOS.
  1750.       
  1751.       EXAMPLE    partkey$ = "73ST"
  1752.                  stat = RetrieveEqual(0,partkey$,Qrecno&)
  1753.                  IF stat = 200 THEN 
  1754.                     DO
  1755.                        stat = RetrieveNext(0,Qkey$,Qrecno&)
  1756.                        IF stat = 0 THEN 
  1757.                           IsKey = AskIfWantedKey(Qkey$)
  1758.                           IF IsKey THEN EXIT DO
  1759.                        ENDIF
  1760.                     LOOP WHILE stat = 0
  1761.                  
  1762.       
  1763.  
  1764.  
  1765.  
  1766.  
  1767.  
  1768.       RetrievePrev
  1769.       
  1770.       TYPE       FUNCTION
  1771.       
  1772.       SYNTAX     stat = RetrievePrev(kfile,Qkey$,Qrecno&)
  1773.       
  1774.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  1775.                  Qkey$ - STRING.The previous key in kfile is placed in 
  1776.                  this variable.
  1777.                  Qrecno& - LONG.The record number that the previous key 
  1778.                  indexes is placed in this variable.
  1779.       
  1780.       USE        Get the previous key in kfile and return it in Qkey$. 
  1781.                  Also get that key's record number and return it in 
  1782.                  Qrecno&. Use this function to process the key file 
  1783.                  sequentially in reverse-order. 
  1784.       
  1785.       RULES      None.
  1786.       
  1787.       NOTES      This function is usually used after a RetrieveLast() or 
  1788.                  RetrieveEqual(). If you are searching for a key based on 
  1789.                  a partial key, use RetrieveEqual() with the partial key 
  1790.                  and continue searching with RetrievePrev() until you 
  1791.                  either find the key you want, determine that it's not in 
  1792.                  the key file, or reach the top of file.
  1793.                  
  1794.       
  1795.       RETURN     Errors 203, 204, 219, 222, and DOS.
  1796.       
  1797.       EXAMPLE    partkey$ = "73STZZZZ"
  1798.                  stat = RetrieveEqual(0,partkey$,Qrecno&)
  1799.                  IF stat = 200 THEN 
  1800.                     DO
  1801.                        stat = RetrievePrev(0,Qkey$,Qrecno&)
  1802.                        IF stat = 0 THEN 
  1803.                           IsKey = AskIfWantedKey(Qkey$)
  1804.                           IF IsKey THEN EXIT DO
  1805.                        ENDIF
  1806.                     LOOP WHILE stat = 0
  1807.                  
  1808.       
  1809.  
  1810.  
  1811.  
  1812.  
  1813.  
  1814.       QBTreeVer
  1815.       
  1816.       TYPE       FUNCTION
  1817.       
  1818.       SYNTAX     stat = QBTreeVer(version)
  1819.       
  1820.       PARAMETERS version - INTEGER.The version of QBTree in use is placed 
  1821.                  in this variable.
  1822.       
  1823.       USE        Return the version of QBTree in use.
  1824.       
  1825.       RULES      None.
  1826.       
  1827.       NOTES      Returns the version X 100. Version 5.50 returns version 
  1828.                  as 550.
  1829.       
  1830.       RETURN     Always 0.
  1831.       
  1832.       EXAMPLE    nul = QBTreeVer(version)
  1833.                  PRINT USING "QBTree version ##.##"; version/100
  1834.                  
  1835.       
  1836.  
  1837.  
  1838.  
  1839.  
  1840.  
  1841.       StatDataFile
  1842.       
  1843.       TYPE       FUNCTION
  1844.       
  1845.       SYNTAX     stat = StatDataFile(dfile,reclen,recs&,bfileno)
  1846.       
  1847.       PARAMETERS dfile - INTEGER.Number used as fileno in OpenDataFile().
  1848.                  reclen - INTEGER.The record length of dfile is returned 
  1849.                  in this variable.
  1850.                  recs& - LONG.The number of active records in dfile is 
  1851.                  placed in this variable.
  1852.                  bfileno - INTEGER.The DOS file handle for dfile is 
  1853.                  placed in this variable.
  1854.       
  1855.       USE        Obtain basic information on the opened data file.
  1856.       
  1857.       RULES      None.
  1858.       
  1859.       NOTES      None.
  1860.       
  1861.       RETURN     Errors 219, 222.
  1862.       
  1863.       EXAMPLE    stat = StatDataFile(0,reclen,recs&,bfileno)
  1864.                  IF stat = 0 THEN PRINT "Rec length="; reclen
  1865.                  
  1866.       
  1867.  
  1868.  
  1869.  
  1870.  
  1871.  
  1872.       StatKeyFile
  1873.       
  1874.       TYPE       FUNCTION
  1875.       
  1876.       SYNTAX     stat = StatKeyFile(kfile,keylen,keys&,bfileno)
  1877.       
  1878.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  1879.                  keylen - INTEGER.The key length of kfile is returned in 
  1880.                  this variable.
  1881.                  keys& - LONG.The number of active keys in kfile is 
  1882.                  placed in this variable.
  1883.                  bfileno - INTEGER.The DOS file handle for kfile is 
  1884.                  placed in this variable.
  1885.       
  1886.       USE        Obtain basic information on the opened key file.
  1887.       
  1888.       RULES      None.
  1889.       
  1890.       NOTES      None.
  1891.       
  1892.       RETURN     Errors 219, 222.
  1893.       
  1894.       EXAMPLE    stat = StatKeyFile(0,keylen,keys&,bfileno)
  1895.                  IF stat = 0 THEN PRINT "Key length="; keylen
  1896.                  
  1897.       
  1898.  
  1899.  
  1900.  
  1901.  
  1902.  
  1903.       StoreKey
  1904.       
  1905.       TYPE       FUNCTION
  1906.       
  1907.       SYNTAX     stat=StoreKey(kfile,Qkey$,Qrecno&)
  1908.       
  1909.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  1910.                  Qkey$ - STRING.Key to add to kfile.
  1911.                  Qrecno& - LONG.The record number of the data record in 
  1912.                  your data file that Qkey$ indexes.
  1913.       
  1914.       USE        Store the key to the key file and associate with it 
  1915.                  Qrecno&.
  1916.       
  1917.       RULES      The key must be unique.
  1918.                  Qkey$ must not begin with an ASCII 0 or 255.
  1919.                  Qrecno& must be >= 0 and <= 16,777,215.
  1920.                  
  1921.       NOTES      QBTree is case-sensitive so it is recommended that keys 
  1922.                  be made upper-case (or lower) unless there is a reason 
  1923.                  not to do this. 
  1924.                  The difference between StoreKey() and AddKey(Record)() 
  1925.                  is that StoreKey() does not do any data file handling. 
  1926.                  Whereas the AddKey() routines handle both the key and 
  1927.                  data file by automatically inserting keys, assigning 
  1928.                  record numbers, and reading and writing the data records, 
  1929.                  StoreKey() just handles inserting keys. The record 
  1930.                  numbers associated with those keys (and retrieved with 
  1931.                  one of the Retrieve() routines) are assigned by you.
  1932.       
  1933.       RETURN     Errors 201, 219, 222, 223, 224 and DOS.
  1934.       
  1935.       EXAMPLE    Qkey$ = LEFT$(datarecord$,keylen)
  1936.                  Qrecno& = GetNextFreeRecord&(userdfile)
  1937.                  stat = StoreKey(0,Qkey$,Qrecno&)
  1938.                  
  1939.       
  1940.  
  1941.  
  1942.  
  1943.  
  1944.  
  1945.       UnlockDataHeader
  1946.       
  1947.       TYPE       FUNCTION
  1948.       
  1949.       SYNTAX     stat = UnlockDataHeader(dfile)
  1950.       
  1951.       PARAMETERS dfile - INTEGER.Number used as fileno in OpenDataFile().
  1952.       
  1953.       USE        Network. Flush the internal buffers and unlock the data 
  1954.                  header of dfile so that other processes may read or write 
  1955.                  it.
  1956.       
  1957.       RULES      SHARE.EXE must be installed.
  1958.                  After locking the data header you must unlock it when 
  1959.                  you no longer need exclusive access to it. If your 
  1960.                  program terminates without unlocking active locks, the 
  1961.                  result is undefined.
  1962.       
  1963.       NOTES      This function is not needed if dfile's asmode=&H12.
  1964.                  This function first calls FlushDataFile(dfile,0) and 
  1965.                  then releases the lock.
  1966.       
  1967.       RETURN     Errors 219, 222, and DOS.
  1968.       
  1969.       EXAMPLE    '[see LockDataHeader for lock and open code]
  1970.                  stat = UnlockDataHeader(dfile)
  1971.                  IF stat = 0 THEN 
  1972.                     PRINT "Data header is unlocked"
  1973.                  
  1974.       
  1975.  
  1976.  
  1977.  
  1978.  
  1979.  
  1980.       UnlockKeyFile
  1981.       
  1982.       TYPE       FUNCTION
  1983.       
  1984.       SYNTAX     stat = UnlockKeyFile(kfile)
  1985.       
  1986.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  1987.       
  1988.       USE        Network. Flush the internal buffers and unlock the key 
  1989.                  file so that other processes may read or write it.
  1990.       
  1991.       RULES      SHARE.EXE must be installed.
  1992.                  After you lock a key file you must unlock it when you no 
  1993.                  longer need exclusive access to it. If your program 
  1994.                  terminates without unlocking active locks, the result is 
  1995.                  undefined.
  1996.       
  1997.       NOTES      This function is not needed if kfile's asmode=&H12.
  1998.                  This function first calls FlushKeyFile(kfile,0) and then 
  1999.                  releases the lock.
  2000.                  
  2001.       RETURN     Errors 219, 222, and DOS.
  2002.                  
  2003.       EXAMPLE    '[see LockKeyFile() for lock and open code]
  2004.                  stat = UnlockKeyFile(kfile)
  2005.                  IF stat = 0 THEN
  2006.                     PRINT "Key file is unlocked"
  2007.                  
  2008.       
  2009.  
  2010.  
  2011.  
  2012.  
  2013.  
  2014.       UnlockRecord
  2015.       
  2016.       TYPE       FUNCTION
  2017.                  
  2018.       SYNTAX     stat = UnlockRecord(dfile,recno&)
  2019.                  
  2020.       PARAMETERS dfile - INTEGER.Number used as fileno in OpenDataFile().
  2021.                  recno& - LONG.Record number in dfile to unlock, or if 0, 
  2022.                  unlock all records in dfile.
  2023.       
  2024.       USE        Network. Unlock the record(s) in dfile so that other 
  2025.                  processes may read or write it.
  2026.       
  2027.       RULES      SHARE.EXE must be installed.
  2028.                  After you lock a record you must unlock it when you no 
  2029.                  longer need exclusive access to it. If you lock multiple 
  2030.                  records by calling LockRecord() multiple times then each 
  2031.                  record needs to be unlocked using UnlockRecord() an equal 
  2032.                  number of times. If your program terminates without 
  2033.                  unlocking active locks, the result is undefined.
  2034.                  
  2035.       NOTES      This function is not needed if dfile's asmode=&H12.
  2036.       
  2037.       RETURN     Errors 219, 222, and DOS.
  2038.                  
  2039.       EXAMPLE    '[see LockRecord() for lock code]
  2040.                  stat = UnlockRecord(dfile,recno&)
  2041.                  IF stat = 0 THEN
  2042.                     PRINT "record";recno&;" is unlocked"
  2043.                  
  2044.       
  2045.  
  2046.  
  2047.  
  2048.  
  2049.  
  2050.       UpdateRecord
  2051.       
  2052.       TYPE       FUNCTION
  2053.       
  2054.       SYNTAX     stat = UpdateRecord(dfile,Qrec$)
  2055.       
  2056.       PARAMETERS dfile - INTEGER.Number used as fileno in OpenDataFile().
  2057.                  Qrec$ - STRING.Data record to update the current data 
  2058.                  record with.
  2059.       
  2060.       USE        After finding a key with one of the Get() functions you 
  2061.                  can update that record using this function.
  2062.       
  2063.       RULES      UpdateRecord() does not affect the key file so you must 
  2064.                  not change the key portion of the data record. 
  2065.                  You must UpdateRecord() immediately after finding a key 
  2066.                  with one of the Get() functions (Equal, First, Last, 
  2067.                  Next, Prev, GT, GTE, LT, LTE) otherwise you may 
  2068.                  inadvertently change the current data record and update 
  2069.                  the wrong record. 
  2070.       
  2071.       NOTES      If you are changing the key portion of the data record 
  2072.                  you should not use UpdateRecord(). Instead, first 
  2073.                  AddKeyRecord() the newly updated key and data record, and 
  2074.                  if successful, continue with DeleteKeyRecord() of the old 
  2075.                  key and data record.
  2076.       
  2077.       RETURN     Errors 206, 219, 222, and DOS.
  2078.       
  2079.       EXAMPLE    stat = GetEqual(0,0,Qkey$,Qrec$)
  2080.                  IF stat = 0 THEN
  2081.                     MID$(Qrec$,10,3) = "OLD"
  2082.                     stat = UpdateRecord(0,Qrec$)
  2083.                  
  2084.       
  2085.  
  2086.  
  2087.  
  2088.  
  2089.  
  2090.       APPENDIX A. SUPPORT FUNCTIONS
  2091.       
  2092.       These functions are used in support of QBTree and can also be used 
  2093.       by you in your programs. All are FUNCTIONs except GetDiskInfo and 
  2094.       MemCopy.
  2095.       
  2096.        1) ExpandDataFile(dfileno,norecs&)
  2097.        2) ExpandKeyFile(kfileno,nokeys&)
  2098.        3) FileExists(filename$)
  2099.        4) GetDefaultDrive()
  2100.        5) GetDiskInfo(drive$,ACL,MCL,BPS,SPCL,freebytes&)
  2101.        6) GetDosVersion()
  2102.        7) GetXEInfo(class,action,locus)
  2103.        8) LoadDataHeader(dfileno)
  2104.        9) LoadKeyHeader(kfileno)
  2105.       10) SFTFiles()
  2106.       11) CreateFile(filenameZ$,attribute)
  2107.       12) OpenDevice(filenameZ$,mode,handle,flen&)
  2108.       13) ReadDevice(handle,start&,bytes&,vseg,voff)
  2109.       14) WriteDevice(handle,start&,bytes&,vseg,voff)
  2110.       15) CloseDevice(handle)
  2111.       16) DeleteFile(filenameZ$)
  2112.       17) RenameFile(oldfileZ$,newfileZ$)
  2113.       18) MemCopy(seg1,off1,seg2,off2,bytes)
  2114.       
  2115.  
  2116.  
  2117.  
  2118.  
  2119.  
  2120.       ExpandDataFile
  2121.       
  2122.       TYPE       FUNCTION
  2123.       
  2124.       SYNTAX     stat=ExpandDataFile(dfileno,norecs&)
  2125.       
  2126.       PARAMETERS dfileno - INTEGER.Number used as fileno in 
  2127.                  OpenDataFile().
  2128.                  norecs& - LONG.The number of records to expand dfileno 
  2129.                  by.
  2130.                  
  2131.       USE        Expand the physical size of dfileno so that it can 
  2132.                  contain at least norecs& more records without file 
  2133.                  fragmentation.
  2134.       
  2135.       RULES      None.
  2136.       
  2137.       NOTES      This routine is optional.
  2138.                  Two uses of this routine are: 1) tell DOS to allocate 
  2139.                  disk space for norecs& more records beforehand to 
  2140.                  minimize file fragmentation, and 2) ensure that your 
  2141.                  program will have room for norecs& more records, now and 
  2142.                  in the future. In other words, if you know your program 
  2143.                  will ultimately need room for 60,000 records then you 
  2144.                  could reserve the space all at once.
  2145.                  Deleted records are included when calculating the number 
  2146.                  of records to add. For instance, let's say you add 100 
  2147.                  records to a new file and then delete 30 of them. Then, 
  2148.                  you decide to expand the data file by 100 records. 
  2149.                  ExpandDataFile() knows that there are 30 deleted records 
  2150.                  available so it physically expands the data file by 70 
  2151.                  records, not 100.
  2152.                  Existing data in the newly added record space is not 
  2153.                  cleared.
  2154.                  The space added will be as contiguous as the current 
  2155.                  state of fragmentation on the disk. If the disk is highly 
  2156.                  fragmented then this routine will get highly-fragmented 
  2157.                  space from DOS.
  2158.       
  2159.       RETURN     Errors 209, 219, 222, 224, and DOS.
  2160.       
  2161.       EXAMPLE    INPUT "Records to expand data file ";xrecs&
  2162.                  stat=ExpandDataFile(dfileno,xrecs&)
  2163.                  
  2164.       
  2165.  
  2166.  
  2167.  
  2168.  
  2169.  
  2170.       ExpandKeyFile
  2171.       
  2172.       TYPE       FUNCTION
  2173.       
  2174.       SYNTAX     stat=ExpandKeyFile(kfileno,nokeys&)
  2175.       
  2176.       PARAMETERS kfileno - INTEGER.Number used as fileno in OpenKeyFile().
  2177.                  nokeys& - LONG.The number of keys to expand kfileno by.
  2178.       
  2179.       USE        Expand the physical size of kfileno so that it can 
  2180.                  contain at least nokeys& more keys without file 
  2181.                  fragmentation.
  2182.                  
  2183.       RULES      None.
  2184.                  
  2185.       NOTES      This routine is optional.
  2186.                  Two uses of this routine are: 1) tell DOS to allocate 
  2187.                  disk space for nokeys& more keys beforehand to minimize 
  2188.                  file fragmentation, and 2) ensure that your program will 
  2189.                  have room for nokeys& more keys, now and in the future. 
  2190.                  In other words, if you know your program will ultimately 
  2191.                  need room for 60,000 keys then you could reserve the 
  2192.                  space all at once.
  2193.                  Keys that have been deleted are included when 
  2194.                  calculating the number of keys to add. For instance, 
  2195.                  let's say you add 100 keys to a new file and then delete 
  2196.                  40 of them. Then, you decide to expand the key file by 
  2197.                  100 keys. ExpandKeyFile() knows that approximately 40% of 
  2198.                  the keys have been deleted so it physically expands the 
  2199.                  key file by 60 keys, not 100.
  2200.                  QBTree is approximately 67% efficient in using node 
  2201.                  space. This is factored in when calculating the space 
  2202.                  required to allocate nokeys& more keys and thus the 
  2203.                  expansion is an approximation.
  2204.                  Existing data in the newly added key space is not 
  2205.                  cleared.
  2206.                  The space added will be as contiguous as the current 
  2207.                  state of fragmentation on the disk. If the disk is highly 
  2208.                  fragmented then this routine will get highly-fragmented 
  2209.                  space from DOS. 
  2210.       
  2211.       RETURN     Errors 208, 219, 222, 224, and DOS.
  2212.       
  2213.       EXAMPLE    INPUT "Keys to expand key file ";xkeys&
  2214.                  stat=ExpandKeyFile(kfileno,xkeys&)
  2215.                  
  2216.       
  2217.  
  2218.  
  2219.  
  2220.  
  2221.  
  2222.       FileExists
  2223.       
  2224.       TYPE       FUNCTION
  2225.       
  2226.       SYNTAX     stat=FileExists(filename$)
  2227.       
  2228.       PARAMETERS filename$ - STRING.Pathname of file to verify exists.
  2229.  
  2230.       USE        Determine if filename$ exists and can be accessed.
  2231.                  
  2232.       RULES      None.
  2233.       
  2234.       NOTES      This function returns -1 if the file exists. Other 
  2235.                  return values are DOS error codes.
  2236.                  For instance, if the file is currently locked, 5 is 
  2237.                  returned (access denied). To determine if a file exists 
  2238.                  or not, check for a return value of -1 (exists and is 
  2239.                  accessible), or 2 (file does not exist).
  2240.       
  2241.       RETURN     -1 if file is accessible,
  2242.                   2 if file does not exist,
  2243.                  or other DOS errors.
  2244.       
  2245.       EXAMPLE    stat=FileExists("C:\HIST\AR91.KEY")
  2246.                  IF stat=2 THEN
  2247.                     DoCreateNewKeyFile
  2248.                  ELSEIF stat=-1 THEN
  2249.                     DoFileAlreadyExistsError
  2250.                  ELSE
  2251.                     DoHandleFileAccessError stat
  2252.                  
  2253.       
  2254.  
  2255.  
  2256.  
  2257.  
  2258.  
  2259.       GetDefaultDrive
  2260.       
  2261.       TYPE       FUNCTION
  2262.       
  2263.       SYNTAX     CurrDrive=GetDefaultDrive
  2264.       
  2265.       PARAMETERS None.
  2266.       
  2267.       USE        Determine the current default DOS drive.
  2268.       
  2269.       RULES      None.
  2270.       
  2271.       NOTES      This function returns the ASCII representation of the 
  2272.                  current default DOS drive.
  2273.                  For instance, if the current drive is C:, 
  2274.                  GetDefaultDrive returns the ASCII representation of C, or 
  2275.                  67. To convert this to a string use CHR$().
  2276.                  
  2277.       RETURN     ASCII representation of current DOS drive letter.
  2278.       
  2279.       EXAMPLE    CurrDrive$=CHR$(GetDefaultDrive)
  2280.                  PRINT "Current drive=";CurrDrive$+":"
  2281.                  
  2282.       
  2283.  
  2284.  
  2285.  
  2286.  
  2287.  
  2288.       GetDiskInfo
  2289.       
  2290.       TYPE       SUB
  2291.       
  2292.       SYNTAX     GetDiskInfo(drive$,ACL,MCL,BPS,SPCL,freebytes&)
  2293.       
  2294.       PARAMETERS drive$ - STRING.Drive letter to get disk info from 
  2295.                  (first character significant).
  2296.                  ACL - INTEGER.The number of available clusters on drive$ 
  2297.                  is placed in this variable.
  2298.                  MCL - INTEGER.The number of total, or maximum, clusters 
  2299.                  on drive$ is placed in this variable.
  2300.                  BPS - INTEGER.The number of bytes per sector for drive$ 
  2301.                  is placed in this variable.
  2302.                  SPCL - INTEGER.The number of sectors per cluster for 
  2303.                  drive$ is placed in this variable.
  2304.                  freebytes& - LONG.The number of free bytes left on 
  2305.                  drive$ is placed in this variable.
  2306.                  
  2307.       USE        Obtain information for the given DOS drive.
  2308.       
  2309.       RULES      None.
  2310.       
  2311.       NOTES      This function uses DOS function 36h to get information 
  2312.                  on drive$.
  2313.                  For information on the default drive use drive$ = "@".
  2314.                  freebytes& = -1 if drive$ is not a valid DOS drive.
  2315.                  
  2316.       RETURN     None.
  2317.                  
  2318.       EXAMPLE    GetDiskInfo("C:",ACL,MCL,BPS,SPCL,freebytes&)
  2319.                  PRINT "Bytes remaining on drive C:=";freebytes&
  2320.                  
  2321.       
  2322.  
  2323.  
  2324.  
  2325.  
  2326.  
  2327.       GetDosVersion
  2328.       
  2329.       TYPE       FUNCTION
  2330.       
  2331.       SYNTAX     DOSver=GetDosVersion
  2332.       
  2333.       PARAMETERS None.
  2334.       
  2335.       USE        Determine the DOS version in use.
  2336.       
  2337.       RULES      None.
  2338.       
  2339.       NOTES      This function returns the DOS version that your program 
  2340.                  is running on x100. 
  2341.                  For instance, if the system is running on DOS 3.31 
  2342.                  GetDosVersion returns 331.
  2343.                  
  2344.       RETURN     DOS version x100.
  2345.       
  2346.       EXAMPLE    DOSver=GetDosVersion
  2347.                  PRINT USING "DOS version ##.##";DOSver/100
  2348.                  
  2349.       
  2350.  
  2351.  
  2352.  
  2353.  
  2354.  
  2355.       GetXEInfo
  2356.       
  2357.       TYPE       FUNCTION
  2358.       
  2359.       SYNTAX     Xerror=GetXEInfo(class,action,locus)
  2360.       
  2361.       PARAMETERS class - INTEGER.The error class code is placed in this 
  2362.                  variable.
  2363.                  action - INTEGER.The recommended action code is placed 
  2364.                  in this variable.
  2365.                  locus - INTEGER.The error locus code is placed in this 
  2366.                  variable.
  2367.                  
  2368.       USE        Obtain detailed error information after a previous DOS 
  2369.                  error.
  2370.       
  2371.       RULES      Requires DOS 3+.
  2372.                  
  2373.       NOTES      Use this function after a QBTree function returns a DOS 
  2374.                  error.
  2375.                  See Appendix D, DOS Error Codes, for a listing of all 
  2376.                  DOS error, class, action, and locus code descriptions.
  2377.       
  2378.       RETURN     Extended DOS error code.
  2379.  
  2380.       EXAMPLE    stat=OpenKeyFile(filename$,0)
  2381.                  IF stat>0 AND stat<200 THEN 
  2382.                     Xerr=GetXEInfo(class,action,locus)
  2383.                     PRINT "Extended error:";ExtendErrMsg$(Xerr)
  2384.                     PRINT "Error class:";ClassErrMsg$(class)
  2385.                     PRINT "Recommend:";RecommendMsg$(action)
  2386.                     PRINT "Error locus:";LocusMsg$(locus)
  2387.                  
  2388.       
  2389.  
  2390.  
  2391.  
  2392.  
  2393.  
  2394.       LoadDataHeader
  2395.       
  2396.       TYPE       FUNCTION
  2397.       
  2398.       SYNTAX     stat = LoadDataHeader(dfile)
  2399.       
  2400.       PARAMETERS dfile - INTEGER.Number used as fileno in OpenDataFile().
  2401.       
  2402.       USE        Network. Load from disk the data header of dfile.
  2403.       
  2404.       RULES      If there is any possibility that another process has 
  2405.                  changed the data file in such a manner as to alter the 
  2406.                  data header since the open, you must call this function 
  2407.                  before performing any R/W operation on the data file. 
  2408.                  
  2409.       NOTES      This function is not needed if dfile's asmode=&H12.
  2410.                  This function is needed only if the data file is being 
  2411.                  used on a network and there's a possibility that another 
  2412.                  process altered the data header.
  2413.                  For instance, let's say you open dfile but don't lock 
  2414.                  it. Another process (program) on the network also opens 
  2415.                  its, adds 10 new records to it, and closes it. Now, the 
  2416.                  data header you have in RAM (loaded when dfile was 
  2417.                  opened) no longer matches the data header on disk. Before 
  2418.                  reading or writing to dfile you need to LoadDataHeader() 
  2419.                  to obtain the valid header data.
  2420.                  This function is called by LockDataHeader.
  2421.       
  2422.       RETURN     Errors 219, 222, and DOS.
  2423.       
  2424.       EXAMPLE    stat = LoadDataHeader(0)
  2425.                  
  2426.       
  2427.  
  2428.  
  2429.  
  2430.  
  2431.  
  2432.       LoadKeyHeader
  2433.       
  2434.       TYPE       FUNCTION
  2435.                  
  2436.       SYNTAX     stat = LoadKeyHeader(kfile)
  2437.       
  2438.       PARAMETERS kfile - INTEGER.Number used as fileno in OpenKeyFile().
  2439.       
  2440.       USE        Network. Load from disk the key header of kfile.
  2441.       
  2442.       RULES      If there is any possibility that another process has 
  2443.                  changed the key file in such a manner as to alter the key 
  2444.                  header since the open, you must call this function before 
  2445.                  performing any R/W operation on the key file.
  2446.       
  2447.       NOTES      This function is not needed if kfile's asmode=&H12.
  2448.                  This function is needed only if the key file is being 
  2449.                  used on a network and there's a possibility that another 
  2450.                  process altered the key header.
  2451.                  For instance, let's say you open kfile but don't lock 
  2452.                  it. Another process (program) on the network also opens 
  2453.                  its, adds 10 new keys to it, and closes it. Now, the key 
  2454.                  header you have in RAM (loaded when kfile was opened) no 
  2455.                  longer matches the key header on disk. Before reading or 
  2456.                  writing to kfile you need to LoadKeyHeader() to obtain 
  2457.                  the valid header data.
  2458.                  This function is called by LockKeyFile().
  2459.                  If you were sequentially accessing the file using 
  2460.                  GetNext() or GetPrev() and you UnlockKeyFile() you will 
  2461.                  need to maintain the last key found so you can restore to 
  2462.                  that key when you continue processing.
  2463.       
  2464.       RETURN     Errors 219, 222, and DOS.
  2465.       
  2466.       EXAMPLE    stat = LoadKeyHeader(0)
  2467.                  
  2468.       
  2469.  
  2470.  
  2471.  
  2472.  
  2473.  
  2474.       SFTFiles
  2475.       
  2476.       TYPE       FUNCTION
  2477.       
  2478.       SYNTAX     MaxFiles=SFTFiles
  2479.       
  2480.       PARAMETERS None.
  2481.       
  2482.       USE        Determine the number of file slots allocated in the 
  2483.                  System Files Table.
  2484.       
  2485.       RULES      None.
  2486.       
  2487.       NOTES      This function returns the number after FILES= in 
  2488.                  CONFIG.SYS.
  2489.                  For instance, if you have FILES=30 in your CONFIG.SYS 
  2490.                  file, SFTFiles() returns 30.
  2491.                  This uses an undocumented DOS function. See the BASIC 
  2492.                  source for more.
  2493.       
  2494.       RETURN     The maximum number of DOS system-wide handles.
  2495.       
  2496.       EXAMPLE    MinFiles=40+4
  2497.                  Files=SFTFiles
  2498.                  IF Files<MinFiles THEN
  2499.                     PRINT "Set FILES=44 in CONFIG.SYS"
  2500.                  
  2501.       
  2502.  
  2503.  
  2504.  
  2505.  
  2506.  
  2507.       CreateFile
  2508.       
  2509.       TYPE       FUNCTION
  2510.       
  2511.       SYNTAX     stat=CreateFile(filenameZ$,attribute)
  2512.                  
  2513.       PARAMETERS filenameZ$ - STRING.Pathname of file to create.
  2514.                  attribute - INTEGER, BYVAL.DOS directectory attribute to 
  2515.                  give the file.
  2516.                  
  2517.       USE        Create a new file using DOS function 3Ch. 
  2518.       
  2519.       RULES      filenameZ$ must not already exist.
  2520.                  filenameZ$ must end with a CHR$(0).
  2521.                  
  2522.       NOTES      By using these file functions you can save 15K in EXE 
  2523.                  file size by not needing BASIC's file functions.
  2524.                  attribute can take the following values:
  2525.                     0 normal
  2526.                     1 read-only
  2527.                     2 hidden
  2528.                     4 system
  2529.                  
  2530.       RETURN     -1 if filenameZ$ either has zero length or is not ASCIIZ,
  2531.                  Errors DOS.
  2532.       
  2533.       EXAMPLE    filename$ = "F:\AR91\CONFIG.QBT"
  2534.                  stat=CreateFile(filename$+CHR$(0),0)
  2535.                  
  2536.       
  2537.  
  2538.  
  2539.  
  2540.  
  2541.  
  2542.       OpenDevice
  2543.       
  2544.       TYPE       FUNCTION
  2545.                  
  2546.       SYNTAX     stat=OpenDevice(filenameZ$,mode,handle,flen&)
  2547.       
  2548.       PARAMETERS filenameZ$ - STRING.Pathname of file/device to open.
  2549.                  mode - INTEGER, BYVAL.Open mode.
  2550.                  handle - INTEGER.The DOS handle for this file is placed 
  2551.                  in this variable.
  2552.                  flen& - LONG.The length of the file at time of open is 
  2553.                  placed in this variable.
  2554.                  
  2555.       USE        Open a file/device using DOS function 3Dh.
  2556.       
  2557.       RULES      filenameZ$ must exist.
  2558.                  filenameZ$ must end with a CHR$(0).
  2559.                  
  2560.       NOTES      By using these file functions you can save 15K in EXE 
  2561.                  file size by not needing BASIC's file functions.
  2562.                  mode values are (bit-mapped):
  2563.                  bit 7 = inheritance flag (DOS 3+)
  2564.                    4-6 = sharing mode (DOS 3+)
  2565.                      3 = reserved (should=0)
  2566.                    0-2 = access type
  2567.                  For read/write non-network access to a file use mode=2. 
  2568.                  For exact uses of mode consult a DOS programmer reference.
  2569.                  
  2570.       RETURN     -1 if filenameZ$ either has zero length or is not ASCIIZ,
  2571.                  Errors DOS.
  2572.       
  2573.       EXAMPLE    stat=OpenDevice("TEST.DAT"+CHR$(0),2,han,flen&)
  2574.                  IF stat=0 THEN
  2575.                     PRINT "DOS handle=";han
  2576.                     PRINT "File length=";flen&
  2577.                  
  2578.       
  2579.  
  2580.  
  2581.  
  2582.  
  2583.  
  2584.       ReadDevice
  2585.       
  2586.       TYPE       FUNCTION
  2587.       
  2588.       SYNTAX     stat=ReadDevice(handle,start&,bytes&,vseg,voff)
  2589.  
  2590.       PARAMETERS handle - INTEGER, BYVAL.DOS handle to read from.
  2591.                  start& - LONG, BYVAL.If block device then byte offset 
  2592.                  into file to start reading from.
  2593.                  bytes& - LONG, BYVAL.Number of bytes to read from the 
  2594.                  device.
  2595.                  vseg - INTEGER, BYVAL.Segment of buffer.
  2596.                  voff - INTEGER, BYVAL.Offset of buffer.
  2597.                  
  2598.       USE        Read from a DOS device to RAM using DOS function 3Fh.
  2599.       
  2600.       RULES      handle must be open.
  2601.       
  2602.       NOTES      The first byte is 0.
  2603.                  To continue reading from the last position+1 use start& 
  2604.                  = -1.
  2605.                  By using these file functions you can save 15K in EXE 
  2606.                  file size by not needing BASIC's file functions.
  2607.                  You can read/write to DOS's predefined handles without 
  2608.                  first needing to open them (they're already open):
  2609.                     0 STDIN  (CON)
  2610.                     1 STDOUT (CON)
  2611.                     2 STDERR (CON)
  2612.                     3 STDAUX (AUX)
  2613.                     4 STDLST (PRN)
  2614.       
  2615.       RETURN     Errors DOS.
  2616.       
  2617.       EXAMPLE    REDIM buffer(1 TO 16384) AS INTEGER
  2618.                  vs=VARSEG(buffer(1))
  2619.                  vo=VARPTR(buffer(1))
  2620.                  stat=OpenDevice("TEST.DAT"+CHR$(0),2,han,flen&)
  2621.                  'read 32K of the file at a time
  2622.                  IF stat=0 THEN
  2623.                     stat=ReadDevice(han,0,32768,vs,vo)
  2624.                     DoProcessBuffer vs,vo
  2625.                     DO WHILE stat=0
  2626.                        vs=vs+(32768\16)
  2627.                        stat=ReadDevice(han,-1,32768&,vs,vo)
  2628.                        DoProcessBuffer vs,vo
  2629.                     LOOP
  2630.                  
  2631.       
  2632.  
  2633.  
  2634.  
  2635.  
  2636.  
  2637.       WriteDevice
  2638.       
  2639.       TYPE       FUNCTION
  2640.       
  2641.       SYNTAX     stat=WriteDevice(han,start&,bytes&,vseg,voff)
  2642.                  
  2643.       PARAMETERS handle - INTEGER, BYVAL.DOS handle to write to.
  2644.                  start& - LONG, BYVAL.If block device then byte offset 
  2645.                  into file to start writing to.
  2646.                  bytes& - LONG, BYVAL.Number of bytes to write to the 
  2647.                  device.
  2648.                  vseg - INTEGER, BYVAL.Segment of buffer.
  2649.                  voff - INTEGER, BYVAL.Offset of buffer.
  2650.                  
  2651.       USE        Write from RAM to a DOS device using DOS function 40h.
  2652.                  
  2653.       RULES      handle must be open.
  2654.                  
  2655.       NOTES      The first byte is 0.
  2656.                  To continue writing to the last position+1 use start& = 
  2657.                  -1.
  2658.                  By using these file functions you can save 15K in EXE 
  2659.                  file size by not needing BASIC's file functions.
  2660.                  You can read/write to DOS's predefined handles without 
  2661.                  first needing to open them (they're already open):
  2662.                     0 STDIN  (CON)
  2663.                     1 STDOUT (CON)
  2664.                     2 STDERR (CON)
  2665.                     3 STDAUX (AUX)
  2666.                     4 STDLST (PRN)
  2667.       
  2668.       RETURN     Errors DOS.
  2669.       
  2670.       EXAMPLE    REDIM buffer(1 TO 16384) AS INTEGER
  2671.                  vs=VARSEG(buffer(1))
  2672.                  vo=VARPTR(buffer(1))
  2673.                  stat=OpenDevice("TEST.DAT"+CHR$(0),2,han,flen&)
  2674.                  'write 5 32K blocks of the file
  2675.                  FOR i=1 TO 5
  2676.                     DoSetupBuffer vs,vo
  2677.                     stat=WriteDevice(han,-1,32768&,vs,vo)
  2678.                     IF stat THEN EXIT FOR
  2679.                     vs=vs+(32768\16)
  2680.                  NEXT
  2681.                  
  2682.       
  2683.  
  2684.  
  2685.  
  2686.  
  2687.  
  2688.       CloseDevice
  2689.       
  2690.       TYPE       FUNCTION
  2691.       
  2692.       SYNTAX     stat=CloseDevice(handle)
  2693.  
  2694.       PARAMETERS handle - INTEGER.The DOS handle to close.
  2695.                  
  2696.       USE        Close a DOS device using DOS function 3Eh.
  2697.       
  2698.       RULES      Handles 0-4 cannot be closed.
  2699.       
  2700.       NOTES      By using these file functions you can save 15K in EXE 
  2701.                  file size by not needing BASIC's file functions.
  2702.       
  2703.       RETURN     Errors DOS.
  2704.       
  2705.       EXAMPLE    stat=OpenDevice("TEST.DAT"+CHR$(0),2,han,flen&)
  2706.                  IF stat=0 THEN
  2707.                     PRINT "DOS handle=";han
  2708.                     PRINT "File length=";flen&
  2709.                     stat=CloseDevice(han)
  2710.                  
  2711.       
  2712.  
  2713.  
  2714.  
  2715.  
  2716.  
  2717.       DeleteFile
  2718.       
  2719.       TYPE       FUNCTION
  2720.       
  2721.       SYNTAX     stat=DeleteFile(filenameZ$)
  2722.       
  2723.       PARAMETERS filenameZ$ - STRING.Pathname of file to delete.
  2724.       
  2725.       USE        Delete a file using DOS function 41h. Similar to BASIC's 
  2726.                  KILL.
  2727.       
  2728.       RULES      filenameZ$ must exist.
  2729.                  filenameZ$ must end with a CHR$(0).
  2730.       
  2731.       NOTES      By using these file functions you can save 15K in EXE 
  2732.                  file size by not needing BASIC's file functions.
  2733.       
  2734.       RETURN     -1 if filenameZ$ either has zero length or is not ASCIIZ,
  2735.                  Errors DOS.
  2736.       
  2737.       EXAMPLE    IF FileExists(fileZ$) = -1 THEN
  2738.                     stat=DeleteFile(fileZ$)
  2739.                  
  2740.       
  2741.  
  2742.  
  2743.  
  2744.  
  2745.  
  2746.       RenameFile
  2747.       
  2748.       TYPE       FUNCTION
  2749.                  
  2750.       SYNTAX     stat=RenameFile(oldfileZ$,newfileZ$)
  2751.       
  2752.       PARAMETERS oldfileZ$ - STRING.Pathname of original file.
  2753.                  newfileZ$ - STRING.Filename to replace original with.
  2754.       
  2755.       USE        Rename a file using DOS function 56h. Similar to BASIC's 
  2756.                  NAME.
  2757.       
  2758.       RULES      oldfileZ$ must exist. newfileZ$ must not exist.
  2759.                  oldfileZ$ and newfileZ$ must end with a CHR$(0).
  2760.       
  2761.       NOTES      By using these file functions you can save 15K in EXE 
  2762.                  file size by not needing BASIC's file functions.
  2763.       
  2764.       RETURN     -1 if oldfileZ$ or newfileZ$ either have zero length or 
  2765.                  aren't ASCIIZ,
  2766.                  Errors DOS.
  2767.       
  2768.       EXAMPLE    IF FileExists(fileZ$) = -1 THEN
  2769.                     stat=RenameFile(fileZ$,newfileZ$)
  2770.                  
  2771.       
  2772.  
  2773.  
  2774.  
  2775.  
  2776.  
  2777.       MemCopy
  2778.       
  2779.       TYPE       SUB
  2780.       
  2781.       SYNTAX     MemCopy(fromseg,fromoff,toseg,tooff,bytes)
  2782.                  
  2783.       PARAMETERS FromSeg - INTEGER, BYVAL.The source segment to copy from.
  2784.                  FromOff - INTEGER, BYVAL.The source offset to copy from.
  2785.                  ToSeg - INTEGER, BYVAL.The destination segment to copy 
  2786.                  to.
  2787.                  ToOff - INTEGER, BYVAL.The destination offset to copy to.
  2788.                  bytes - INTEGER, BYVAL.The number of bytes to copy.
  2789.  
  2790.       
  2791.       USE        Copy memory from/to QB TYPE variable to/from a QBTree 
  2792.                  variable-length string.
  2793.       
  2794.       RULES      Memory addresses must not overlap.
  2795.       
  2796.       NOTES      None.
  2797.       
  2798.       RETURN     Errors DOS.
  2799.       
  2800.       EXAMPLE    'See APPENDIX C. Using TYPE Variables.
  2801.                  
  2802.       
  2803.  
  2804.  
  2805.  
  2806.  
  2807.  
  2808.       APPENDIX B. TECHNICAL SPECIFICATIONS
  2809.       
  2810.       Technical Specifications:
  2811.  
  2812.       Key length   : 1-64 bytes (ASCII sort), fixed-length
  2813.       Record length: 3-2048 bytes, fixed-length (to 32767 with source)
  2814.       Node size    : 512 bytes
  2815.       Keys per node: 7-84 keys, (512-3)\(key length+5)
  2816.       Max keys/file: 5.5 million keys (65534 nodes)
  2817.       Max recs/file: 16.7 million records
  2818.       Max key files: 250 (total combined files <=250 DOS 3+)
  2819.       Max data file: 250 (total combined files <=15 DOS 2)
  2820.  
  2821.       Key file header format (first sector (512 bytes) of key file):
  2822.       
  2823.       filetype  char ; 0 file type, "*"
  2824.       rootnode  int  ; 1 sector in file of root node
  2825.       nokeyslo  int  ; 3 number of keys (low word)
  2826.       nokeyshi  byte ; 5 - (high byte)
  2827.       keyavsec  int  ; 6 key node available list
  2828.       nxkeysec  int  ; 8 next free node/sector
  2829.       keylen    byte ;10 length of key
  2830.       maxkeys   byte ;11 maximum keys per node
  2831.       internal  byte ;12-511 internal use
  2832.       
  2833.       Data file header format (first 32 bytes of data file):
  2834.       
  2835.       filetype  char ; 0 file type, "S"
  2836.       reclen    int  ; 1 length of record
  2837.       norecslo  int  ; 3 number of records (low word)
  2838.       norecshi  byte ; 5 - (high byte)
  2839.       datavlo   int  ; 6 data available list (low word)
  2840.       datavhi   byte ; 8 - (high byte)
  2841.       nxdalo    int  ; 9 next data record avail (low word)
  2842.       nxdahi    byte ;11 - (high byte)
  2843.       internal  byte ;12-31 reserved
  2844.  
  2845.       Some structures above use a 24-bit value. These use 3 bytes 
  2846.       (word+byte) to store information. For example, the value of the 
  2847.       datavlo/hi structure in the data file header is:
  2848.       
  2849.       DataAvailRec&=1&*datavlo+(datavhi*65536)
  2850.       
  2851.  
  2852.  
  2853.  
  2854.  
  2855.       Key Record Format:
  2856.       
  2857.       There is an internal first key with a null value that logically 
  2858.       marks the top of the key file.
  2859.       
  2860.       Beginning each node is a count key byte. This is the count of valid 
  2861.       keys on that node. Then for each key is a 16-bit previous node 
  2862.       pointer, the key itself, the 24-bit data record pointer for that 
  2863.       key, and a 16-bit next node pointer (node pointers are zero at the 
  2864.       leaf nodes).
  2865.       
  2866.       02  00 00  000000  00 00 00  00 00  KEY001  01 00 00  00 00 ... 
  2867.        1.   2.     3.       4.       5.     6.       7.       8.   9.
  2868.       
  2869.       1. Key count for that node
  2870.       2. Node back pointer (for non-leaf nodes)
  2871.       3. The internal null key
  2872.       4. The 24-bit data record pointer (low word/hi byte)
  2873.       5. Forward ptr/back ptr (for non-leaf nodes)
  2874.       6. First logical key (here 'KEY001')
  2875.       7. Its data pointer (record number in data file)
  2876.       8. Its forward pointer (for non-leaf nodes)
  2877.       9. Repeat 6 to 8 for each key on node.
  2878.       
  2879.       QBTree makes some allowances on the strict B-TREE and ISAM 
  2880.       definitions. For all practical purposes, consider QBTree superior to 
  2881.       the text-book implementations of these.
  2882.       
  2883.       Data Record Format:
  2884.       
  2885.       Straight data after the header. Logical record #1 follows the 
  2886.       header. Records that are deleted have the first 3 bytes used as a 
  2887.       link in the records available list. datavlo/hi in the header points 
  2888.       to the last deleted record (or 0 0 0 if none). The first 3 bytes of 
  2889.       THAT deleted record point to the previously deleted record, and so 
  2890.       on. When 3 zero bytes form the pointer, THAT record is the last in 
  2891.       the list of deletes that can be reused. Any additional records added 
  2892.       will then will expand the file.
  2893.       
  2894.       By reserving the first 3 bytes of the data record it would be easy 
  2895.       to reindex a datafile. Set the bytes to all ASCII 255. You then use 
  2896.       GetDirect(), check to see if the 3 bytes are still 255s, and if so, 
  2897.       AddKeyRecord() to a new key and data file. If those 3 bytes are not 
  2898.       255s, you know that that record is deleted. 
  2899.       
  2900.       A more difficult method is to track the datavlo/hi singly-linked 
  2901.       list to scan for deleted records. It's more complex but doesn't 
  2902.       require you to reserve 3 bytes. Briefly, start by reading the 
  2903.       FLUSHED data header to get the datavlo/hi structure. This structure
  2904.  
  2905.  
  2906.  
  2907.  
  2908.  
  2909.  
  2910.       points to the last deleted record, or, if 0 there are no deleted
  2911.       records available in the file. Assuming it is not 0, (let's say it's 
  2912.       record 5), flag that this record (5) is deleted. Use GetDirect() to 
  2913.       read record 5. If the first 3 bytes in record 5 are not 0, continue 
  2914.       the process, flagging each record that is deleted. When you reach 
  2915.       the last deleted record, the first 3 bytes will be 0. You now know 
  2916.       what records to skip when you scan through the data file using 
  2917.       GetDirect() and AddKeyRecord().
  2918.       
  2919.       By using GetDirect() with StoreKey() it is possible to reindex a 
  2920.       data file without having to reconstruct the data file. The benefit 
  2921.       of removing deleted data records is lost, however.
  2922.       
  2923.  
  2924.  
  2925.  
  2926.  
  2927.  
  2928.       Resource Allocation:
  2929.       
  2930.       Storage for the data buffers and headers are allocated at run-time 
  2931.       in far memory. This means that very little string space is used by 
  2932.       QBTree. Data allocation is as follows (arrays are stored in far 
  2933.       memory):
  2934.       
  2935.       2 integer arrays (0 to MKF) + (0 to MDF) for file handles.
  2936.       1 key hdr array (0 to MKF) for key file headers, ea 64 bytes.
  2937.       1 data hdr array (0 to MDF) for data file headers, ea 32 bytes.
  2938.       1 key node array (0 to MKF) for node buffers, ea 512 bytes.
  2939.       1 data buffer array (0 to MDF) for data record I/O (size allocated 
  2940.       is 2048 bytes each but can be changed with source).
  2941.       1 long integer array (0 to MKF) to track current record numbers.
  2942.       2 integer arrays (0 to MKF) + (0 to MDF) to track file drives.
  2943.       1 type variable for interfacing with QBTree low-level, 34 bytes.
  2944.       ... and other miscellaneous variables totalling about 2500 bytes.
  2945.       
  2946.  
  2947.  
  2948.  
  2949.  
  2950.  
  2951.       APPENDIX C. WORK AROUNDS.
  2952.       
  2953.       Using TYPE Variables:
  2954.       
  2955.       QBTree uses a simple variable, namely a variable-length string, to 
  2956.       get and put data in the data file. To use QB TYPE variables, you may 
  2957.       want to use this method: Setup your TYPE variable, then allocate 
  2958.       enough space in a variable-length string to copy to and from it.
  2959.       
  2960.       TYPE dataTYPE
  2961.        TAG AS STRING * 4
  2962.        SSN AS STRING * 9
  2963.        AGE AS INTEGER
  2964.        XXX AS STRING * 1
  2965.       END TYPE '16
  2966.  
  2967.       DIM SSNage AS dataTYPE
  2968.       SSNage.TAG = ""
  2969.       SSNage.SSN = ssn$
  2970.       SSNage.AGE = age
  2971.       DIM SHARED work$
  2972.  
  2973.       work$ = SPACE$(LEN(SSNage))
  2974.       FromSeg = VARSEG(SSNage)
  2975.       FromOff = VARPTR(SSNage)
  2976.       ToSeg = VARSEG(work$)   'QBX/Fs use SSEG
  2977.       ToOff = SADD(work$)     'string address
  2978.       count = LEN(work$)      
  2979.       MemCopy FromSeg,FromOff,ToSeg,ToOff,count
  2980.  
  2981.       'You now have the TYPE variable data in a var-len
  2982.       'string that can be used as the Qrec$.
  2983.  
  2984.       Qkey$ = mid$(work$,2,9)
  2985.       Qrec$ = work$
  2986.       stat = AddKeyRecord(0,0,Qkey$,Qrec$)
  2987.  
  2988.       'To put Qrec$ in the typed variable,
  2989.       'reverse the From/To assignments:
  2990.  
  2991.       stat = GetEqual(0,0,Qkey$,Qrec$)
  2992.       FromSeg = VARSEG(Qrec$) 'QBX/Fs use SSEG
  2993.       FromOff = SADD(Qrec$)
  2994.       ToSeg = VARSEG(SSNage)
  2995.       ToOff = VARPTR(SSNage)
  2996.       count = LEN(SSNage)
  2997.       MemCopy FromSeg,FromOff,ToSeg,ToOff,count
  2998.       PRINT SSNage.SSN; SSNage.age
  2999.  
  3000.       'MemCopy is included in the QBTREEx.LIB and QBTREE.BI.
  3001.       'The copy goes from low memory to high.
  3002.       
  3003.  
  3004.  
  3005.  
  3006.       Non-unique Keys:
  3007.       
  3008.       QBTree doesn't allow duplicate keys (this may be an inconvenience 
  3009.       in some database programming) but this can easily be worked around 
  3010.       by adding to each key an additional two bytes. These bytes would act 
  3011.       to differentiate up to 65536 'identical' keys. A well-designed 
  3012.       relational database would not have this problem by definition, but 
  3013.       this work-around is presented just in case you need it.
  3014.       
  3015.       When retrieving 'identical' enumerated keys you normally would need 
  3016.       to start at the first enumerated key with GetEqual() using an 
  3017.       enumerator of 0 and continue searching using GetNext() until the 
  3018.       desired record is found.
  3019.       
  3020.       Note: For proper sorting, you must have the most significant byte 
  3021.       of the enumerator first and the least significant last.
  3022.       
  3023.       Note: Retrieved keys and records will be returned with their full 
  3024.       length retained. Be sure the enumerator occupies the last 2 bytes. 
  3025.       Don't just append the enumerator onto a key.
  3026.       
  3027.       This code accesses an existing key/record (Qkey$/Qrec$) from 
  3028.       kfile=0 dfile=0 and adds a new key to kfile=1. This new key in 
  3029.       kfile=1 will index the same data record in dfile=0 as Qkey$ in 
  3030.       kfile=0. Similar code could be used when using AddKeyRecord().
  3031.       
  3032.       DIM LV AS STRING * 2, HV AS STRING * 2
  3033.       LV=CHR$(0)+CHR$(0)      'lowest enumerator
  3034.       HV=CHR$(255)+CHR$(255)  'highest enumerator
  3035.       Qkey$="TESTKEY-K0"+LV   '10-byte key+2-byte enumerator  
  3036.       NewKey$="NEW_KEY-K1"    '10-byte key, no enumerator yet
  3037.       stat=GetEqual(0,0,Qkey$,Qrec$)
  3038.       'accessed test key, now add new key to kfile=1
  3039.       IF stat = 0 THEN
  3040.          stat=AddKey(1,0,NewKey$+LV) 'use LV enumerator
  3041.       ELSE
  3042.          STOP
  3043.       ENDIF
  3044.       IF stat = 201 THEN
  3045.          'NewKey$+LV exists so reset data pointer
  3046.          stat=GetEqual(0,0,Qkey$,Qrec$)
  3047.          'get absolute last NewKey$ (won't be found, stat=200)
  3048.          stat=GetEqual(1,0,NewKey$+HV,Zrec$)
  3049.          'backup and get the last valid one, Zkey$=key and enumerator
  3050.          stat=GetPrev(1,0,Zkey$,Zrec$)
  3051.          'enumerator is in little-Endian order so reverse bytes,
  3052.          'make it a number, add 1, convert back to string,
  3053.          'little-Endian it, and add the enumerated key
  3054.          enum$ = RIGHT$(ZKey$,2)
  3055.          enum$ = RIGHT$(enum$,1)+LEFT$(enum$,1)
  3056.          enum = CVI(enum$)
  3057.          enum = enum + 1     
  3058.          enum$ = MKI$(enum)
  3059.          enum$ = RIGHT$(enum$,1)+LEFT$(enum$,1)
  3060.          stat = AddKey(1,0,NewKey$+enum$)
  3061.       
  3062.  
  3063.  
  3064.  
  3065.       APPENDIX D. ERROR CODES.
  3066.       
  3067.       QSAM generated error codes (200-218):
  3068.       
  3069.         0  No error - the operation was successful.
  3070.       
  3071.       200  Key not found - the key is not in the index file.
  3072.       
  3073.       201  Key already exists - duplicate keys are not allowed in QBTree. 
  3074.       If this error occurs with AddKey(), you must re-establish a valid 
  3075.       data pointer by re-accessing the original key/record before trying 
  3076.       again.
  3077.       
  3078.       202  End of file - reached the end of file.
  3079.       
  3080.       203  Top of file - reached the top of file.
  3081.       
  3082.       204  Empty file - there are no keys in the index file.
  3083.       
  3084.       205  Reserved - previously disk full error. This error is now 
  3085.       indicated by DOS error -2 - disk full or unexpected end of file.
  3086.       
  3087.       206  Data pointer invalid - a valid QBTree key access must occur 
  3088.       right before a data record can be UpdateRecord() or a key can be 
  3089.       AddKey().
  3090.       
  3091.       207  Reserved.
  3092.       
  3093.       208  Node exceeds limit - more than 65534 nodes used by index file.
  3094.       
  3095.       209  Record exceeds limit - more than 16777215 records used by data 
  3096.       file.
  3097.       
  3098.       210  Corrupt index - index file is probably corrupt.
  3099.       
  3100.       211  Invalid function - an invalid QSAM function was called.
  3101.       
  3102.       212-218  Reserved.
  3103.       
  3104.       BTREE.BAS generated error codes (219-239):
  3105.       
  3106.       219  File number invalid - the file number used is greater than the 
  3107.       highest allocated in InitQBTREE().
  3108.       
  3109.       220  Data record length invalid - length must be from 3-2048 bytes 
  3110.       when creating a QBTree data file.
  3111.       
  3112.       221  Key length invalid - length must be from 1-64 bytes when 
  3113.       creating a key file.
  3114.       
  3115.       222  File not open - the fileno for a key or data file operation is 
  3116.       not open.
  3117.       
  3118.       223  Invalid null key assignment - a null key cannot be used. Null 
  3119.       is defined in QBTree as either ASCII 0 or ASCII 255 in the first
  3120.       character of a key.
  3121.  
  3122.  
  3123.  
  3124.  
  3125.  
  3126.       
  3127.       224  Invalid record number - a record number less than 1 or a 
  3128.       record number greater than the maximum records possible was used. 
  3129.       
  3130.       225  No handles available - no DOS handles are available. Use a 
  3131.       greater value in config.sys FILES= (FILES=20). Max FILES=255 with 
  3132.       DOS 3+ or FILES=20 with DOS 2.
  3133.       
  3134.       226  Reserved.
  3135.       
  3136.       227  File number already open - the fileno is already in use.
  3137.       
  3138.       228  File not QBTree - the filename in OpenFile() is not recognized 
  3139.       as a QBTree file.
  3140.       
  3141.       229  Reserved.
  3142.       
  3143.       230  File already exists - the CreateFile() filename already exists.
  3144.       
  3145.       231  File not found - the filename$ specified in OpenFile() does 
  3146.       not exist or is not valid.
  3147.       
  3148.       232  Reserved.
  3149.       
  3150.       233  Init not active - using QBTree Create() and Open() routines 
  3151.       without having called InitQBTREE().
  3152.       
  3153.       234  Init already active - calling InitQBTREE() more than once.
  3154.       
  3155.       235-255  Reserved.
  3156.       
  3157.       Error numbers are not exclusively generated by the module 
  3158.       indicated. It is possible for BTREE to issue error 208, for instance.
  3159.       
  3160.  
  3161.  
  3162.  
  3163.  
  3164.       
  3165.       DOS Error Codes:
  3166.       
  3167.       Possible stat return codes in decimal.
  3168.       
  3169.        -2 disk full or unexpected end of file
  3170.        -1 bad filename
  3171.         0 no error
  3172.         1 function not supported
  3173.         2 file not found
  3174.         3 path not found
  3175.         4 too many open files
  3176.         5 access denied
  3177.         6 handle invalid
  3178.         7 MCBs destroyed
  3179.         8 not enough memory
  3180.         9 memory block address invalid
  3181.        10 environment invalid
  3182.        11 format invalid
  3183.        12 access code invalid
  3184.        13 data invalid
  3185.           reserved-0Eh
  3186.        15 disk drive invalid
  3187.        16 cannot remove current directory
  3188.        17 not same device
  3189.        18 no more files
  3190.        19 disk write protected
  3191.        20 unknown unit
  3192.        21 drive not ready
  3193.        22 unknown command
  3194.        23 data error (CRC)
  3195.        24 bad request structure length
  3196.        25 seek error
  3197.        26 unknown medium type
  3198.        27 sector not found
  3199.        28 printer out of paper
  3200.        29 write fault
  3201.        30 read fault
  3202.        31 general failure
  3203.        32 sharing violation
  3204.        33 lock violation
  3205.        34 disk change invalid
  3206.        35 FCB unavailable
  3207.        36 sharing buffer overflow
  3208.           reserved-25h
  3209.           reserved-26h
  3210.           reserved-27h
  3211.           reserved-28h
  3212.           reserved-29h
  3213.           reserved-2Ah
  3214.           reserved-2Bh
  3215.       
  3216.  
  3217.  
  3218.  
  3219.  
  3220.  
  3221.  
  3222.           reserved-2Ch
  3223.           reserved-2Dh
  3224.           reserved-2Eh
  3225.           reserved-2Fh
  3226.           reserved-30h
  3227.           reserved-31h
  3228.        50 network request not supported
  3229.        51 remote computer not listening
  3230.        52 duplicate name on network
  3231.        53 network name not found
  3232.        54 network busy
  3233.        55 network device no longer exists
  3234.        56 NETBIOS command limit exceeded
  3235.        57 network adapter hardware error
  3236.        58 incorrect response from network
  3237.        59 unexpected network error
  3238.        60 incompatible remote adapter
  3239.        61 print queue full
  3240.        62 queue not full
  3241.        63 not enough space to print file
  3242.        64 network name deleted
  3243.        65 access denied
  3244.        66 network device type incorrect
  3245.        67 network name not found
  3246.        68 network name limit exceeded
  3247.        69 NETBIOS session limit exceeded
  3248.        70 temporarily paused
  3249.        71 network request not accepted
  3250.        72 print/disk redirection paused
  3251.           reserved-49h
  3252.           reserved-4Ah
  3253.           reserved-4Bh
  3254.           reserved-4Ch
  3255.           reserved-4Dh
  3256.           reserved-4Eh
  3257.           reserved-4Fh
  3258.        80 file exists
  3259.        81 reserved-51h
  3260.        82 cannot make
  3261.        83 fail on INT24
  3262.        84 out of structures
  3263.        85 already assigned
  3264.        86 invalid password
  3265.        87 invalid parameter
  3266.        88 network write fault
  3267.       
  3268.       DOS Class Codes:
  3269.       
  3270.         1 out of resources
  3271.         2 temporary situation
  3272.         3 authorization
  3273.       
  3274.  
  3275.  
  3276.  
  3277.  
  3278.  
  3279.  
  3280.         4 internal
  3281.         5 hardware failure
  3282.         6 system failure
  3283.         7 application error
  3284.         8 not found
  3285.         9 bad format
  3286.        10 locked
  3287.        11 media failure
  3288.        12 already exists
  3289.        13 unknown
  3290.  
  3291.       DOS Action Codes:
  3292.       
  3293.         1 retry
  3294.         2 delay retry
  3295.         3 reenter input
  3296.         4 abort
  3297.         5 immediate exit
  3298.         6 ignore
  3299.         7 user intervention
  3300.       
  3301.       DOS Locus Codes:
  3302.       
  3303.         1 unknown
  3304.         2 block device
  3305.         3 reserved
  3306.         4 serial device
  3307.         5 memory
  3308.