home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 5 / ctrom5b.zip / ctrom5b / PROGRAM / BASIC / BLTQ121 / CZ.HLP (.txt) < prev    next >
CZ Help  |  1995-01-05  |  219KB  |  3,881 lines

  1. CZ_HELP!
  2. INDEX
  3. TUTORIAL_INDEX
  4. LICENSE_AGREEMEN
  5. LICENSE_A
  6. PRODUCT_SUPPORT
  7. STARTING_CZ
  8. USING_CZ
  9. USING_CZ_A
  10. USING_CZ_B
  11. ABOUT_CZ
  12. IS_BULLET
  13. IS_A_DATABASE
  14. IS_DBF
  15. IS_A_BTREE
  16. IS_A_NETWORK
  17. IS_FILE_LOCKING
  18. IS_NLS
  19. DESIGN_A_DB
  20. CREATE_A_DB
  21. ADD_TO_THE_DB
  22. QUERY_THE_DB
  23. UPDATE_THE_DB
  24. DELETE_A_RECORD
  25. BC_COMPILE_WITH
  26. LIB_WITH
  27. MAKE_A_QLB
  28. LINK_WITH
  29. CALL_BULLET
  30. SPECS_OVERALL
  31. SPECS_DBF
  32. SPECS_DBF_A
  33. SPECS_DBF_B
  34. SPECS_DBF_C
  35. SPECS_INDEX
  36. SPECS_INDEX_A
  37. SPECS_INDEX_B
  38. SPECS_INDEX_C
  39. SPECS_MEMORY
  40. SPECS_MEMORY_A
  41. SPECS_OS_CALLS
  42. SPECS_LANGUAGES
  43. SPECS_OSES
  44. SPECS_NETWORKS
  45. SPECS_PERFORMANC
  46. SPECS_PERF_A
  47. SPECS_PERF_B
  48. SPECS_PERF_C
  49. SPECS_PERF_D
  50. INITXB
  51. EXITXB
  52. ATEXITXB
  53. MEMORYXB
  54. BREAKXB
  55. BACKUPFILEXB
  56. STATHANDLEXB
  57. GETEXTERRORXB
  58. DVMONCXB
  59. CREATEDXB
  60. OPENDXB
  61. CLOSEDXB
  62. STATDXB
  63. READDHXB
  64. FLUSHDHXB
  65. COPYDHXB
  66. ZAPDHXB
  67. CREATEKXB
  68. CREATEKXB_A
  69. CREATEKXB_B
  70. CREATEKXB_C
  71. CREATEKXB_D
  72. CREATEKXB_E
  73. CREATEKXB_F
  74. OPENKXB
  75. CLOSEKXB
  76. STATKXB
  77. READKHXB
  78. FLUSHKHXB
  79. COPYKHXB
  80. ZAPKHXB
  81. GETDESCRIPTORXB
  82. GETRECORDXB
  83. ADDRECORDXB
  84. UPDATERECORDXB
  85. DELETERECORDXB
  86. UNDELETERECORDXBsp
  87. PACKRECORDSXB
  88. FIRSTKEYXB
  89. EQUALKEYXB
  90. NEXTKEYXB
  91. PREVKEYXB
  92. LASTKEYXB
  93. STOREKEYXB
  94. DELETEKEYXB
  95. BUILDKEYXB
  96. CURRENTKEYXB
  97. GETFIRSTXB
  98. GETEQUALXB
  99. GETNEXTXB
  100. GETPREVXB
  101. GETLASTXB
  102. INSERTXB
  103. UPDATEXB
  104. REINDEXXB
  105. LOCKXB
  106. UNLOCKXB
  107. LOCKKEYXB
  108. UNLOCKKEYXB
  109. LOCKDATAXB
  110. UNLOCKDATAXB
  111. DRIVEREMOTEXB
  112. FILEREMOTEXB
  113. SETRETRIESXB
  114. DELETEFILEDOS
  115. RENAMEFILEDOS
  116. CREATEFILEDOS
  117. ACCESSFILEDOS
  118. OPENFILEDOS
  119. SEEKFILEDOS
  120. READFILEDOS
  121. EXPANDFILEDOS
  122. WRITEFILEDOS
  123. CLOSEFILEDOS
  124. MAKEDIRDOS
  125. ACCESSPACK
  126. BREAKPACK
  127. COPYPACK
  128. CREATEDATAPACK
  129. CREATEKEYPACK
  130. DESCRIPTORPACK
  131. DOSFILEPACK
  132. DVMONPACK
  133. EXITPACK
  134. FIELDDESCTYPE
  135. HANDLEPACK
  136. INITPACK
  137. MEMORYPACK
  138. OPENPACK
  139. REMOTEPACK
  140. SETRETRIESPACK
  141. STATDATAPACK
  142. STATKEYPACK
  143. STATHANDLEPACK
  144. XERRORPACK
  145. ERRORS_BULLET
  146. ERRORS_BULLET_B
  147. ERRORS_BULLET_C
  148. ERRORS_BULLET_D
  149. ERRORS_BASIC
  150. ERRORS_BASIC_B
  151. ERRORS_DOS
  152. ERRORS_DOS_B
  153. ERRORS_DOS_C
  154. INITXBSRC
  155. EXITXBSRC
  156. ATEXITXBSRC
  157. MEMORYXBSRC
  158. BREAKXBSRC
  159. BACKUPFILEXBSRC
  160. STATHANDLEXBSRC
  161. GETEXTERRORXBSRCI
  162. DVMONCXBSRC
  163. CREATEDXBSRC
  164. CREATEDXBSRC_A
  165. OPENDXBSRC
  166. CLOSEDXBSRC
  167. STATDXBSRC
  168. READDHXBSRC
  169. FLUSHDHXBSRC
  170. COPYDHXBSRC
  171. ZAPDHXBSRC
  172. CREATEKXBSRC
  173. CREATEKXBSRC_A
  174. OPENKXBSRC
  175. CLOSEKXBSRC
  176. STATKXBSRC
  177. READKHXBSRC
  178. FLUSHKHXBSRC
  179. COPYKHXBSRC
  180. ZAPKHXBSRC
  181. GETDESCRIPTORXBS
  182. GETRECORDXBSRC
  183. ADDRECORDXBSRC
  184. UPDATERECORDXBSRH
  185. DELETERECORDXBSR
  186. UNDELETERECORDSR
  187. PACKRECORDSXBSRCV
  188. FIRSTKEYXBSRC
  189. EQUALKEYXBSRC
  190. NEXTKEYXBSRC
  191. PREVKEYXBSRC
  192. LASTKEYXBSRC
  193. STOREKEYXBSRC
  194. DELETEKEYXBSRC
  195. BUILDKEYXBSRC
  196. CURRENTKEYXBSRC
  197. GETFIRSTXBSRC
  198. GETEQUALXBSRC
  199. GETNEXTXBSRC
  200. GETPREVXBSRC
  201. GETLASTXBSRC
  202. INSERTXBSRC
  203. UPDATEXBSRC
  204. REINDEXXBSRC
  205. LOCKXBSRC
  206. UNLOCKXBSRC
  207. LOCKKEYXBSRC
  208. UNLOCKKEYXBSRC
  209. LOCKDATAXBSRC
  210. UNLOCKDATAXBSRC
  211. DRIVEREMOTEXBSRC,(
  212. FILEREMOTEXBSRC
  213. SETRETRIESXBSRC
  214. DELETEFILEDOSSRC:.
  215. RENAMEFILEDOSSRC
  216. CREATEFILEDOSSRC
  217. ACCESSFILEDOSSRC
  218. OPENFILEDOSSRC
  219. SEEKFILEDOSSRC
  220. READFILEDOSSRC
  221. EXPANDFILEDOSSRCt<
  222. WRITEFILEDOSSRC
  223. CLOSEFILEDOSSRC
  224. MAKEDIRDOSSRC
  225. ~INDEX            CZ.HLP-BULLET for QB/BASIC PDS
  226.  System 
  227.  Mid-level Record/Key Access 
  228. InitXB        
  229. CreateDXB    CreateKXB    GetDescriptorXB     FirstKeyXB     
  230. ExitXB        
  231. OpenDXB      OpenKXB      GetRecordXB         EqualKeyXB     
  232. AtExitXB      
  233. CloseDXB     CloseKXB     AddRecordXB         NextKeyXB      
  234. MemoryXB      
  235. StatDXB      StatKXB      UpdateRecordXB      PrevKeyXB      
  236. BreakXB       
  237. ReadDHXB     ReadKHXB     DeleteRecordXB      LastKeyXB      
  238. BackupFileXB  
  239. FlushDHXB    FlushKHXB    UndeleteRecordXB    StoreKeyXB     
  240. StatHandleXB  
  241. CopyDHXB     CopyKHXB     PackRecordsXB       DeleteKeyXB    
  242. GetExtErrorXB 
  243. ZapDHXB      ZapKHXB                          BuildKeyXB     
  244. DVmonCXB      
  245.                                               CurrentKeyXB   
  246.  High-level Access 
  247.  Network 
  248. GetFirstXB    InsertXB     
  249. LockXB           UnlockXB        LockKeyXB      
  250. GetEqualXB    UpdateXB     
  251. UnlockKeyXB      LockDataXB      UnlockDataXB   
  252. GetNextXB     ReindexXB    
  253. DriveRemoteXB    FileRemoteXB    SetRetriesXB   
  254. GetPrevXB                  
  255. GetLastXB                  
  256.  Low-level DOS Access 
  257.                            
  258. DeleteFileDOS    OpenFileDOS     WriteFileDOS   
  259.                            
  260. RenameFileDOS    SeekFileDOS     CloseFileDOS   
  261.  Move cursor to index item 
  262. CreateFileDOS    ReadFileDOS     MakeDirDOS     
  263.  and press <Enter>.        
  264. AccessFileDOS    ExpandFileDOS                  
  265. See: TUTORIAL_INDEX
  266. ~TUTORIAL_INDEX   CZ.HLP-BULLET for QB/BASIC PDS
  267.  CZ.COM 
  268.  Using BULLET 
  269.  1.2 
  270. Starting_CZ   
  271. What:              How to:                                   
  272. Using_CZ      
  273.  is_BULLET          design_a_DB         BC_compile_with      
  274. About_CZ      
  275.  is_a_database      create_a_DB         LINK_with            
  276.               
  277.  is_DBF             add_to_the_DB       LIB_with             
  278.  is_a_Btree         query_the_DB        make_a_QLB           
  279.  Error Codes
  280.  is_a_network       update_the_DB      
  281.        
  282. Errors_BULLET 
  283.  is_file_locking    delete_a_record    
  284.  call_BULLET 
  285.        
  286. Errors_BASIC  
  287.  is_NLS                                
  288.        
  289. Errors_DOS    
  290.                     LICENSE_AGREEMENT   Product_Support      
  291.  Structure Pack Types 
  292.  Specifications 
  293. AccessPack       DVmonPack        RemotePack     
  294. Specs_Overall            
  295. BreakPack        ExitPack         SetRetriesPack 
  296. Specs_DBF                
  297. CopyPack         FieldDescTYPE    StatDataPack   
  298. Specs_Index              
  299. CreateDataPack   HandlePack       StatKeyPack    
  300. Specs_Memory             
  301. CreateKeyPack    InitPack         StatHandlePack 
  302. Specs_OS_Calls           
  303. DescriptorPack   MemoryPack       XErrorPack     
  304. Specs_Languages          
  305. DOSFilePack      OpenPack                        
  306. Specs_OSes               
  307.                                                  
  308. Specs_Networks           
  309.                                                  
  310. Specs_Performance        
  311. See: License_Agreement
  312. ~License_Agreement
  313. Before using this software you must agree to the following:
  314.  1. You are not allowed to operate more than one (1) copy of this software
  315.     package at one time per license. This means that if you have 10 programmers
  316.     that COULD possibly use the BULLET library at the same time, you must also
  317.     have ten (10) BULLET licenses.
  318.  2. You are not allowed to distribute non-executable code containing BULLET
  319.     code. This means that you are not allowed to redistribute BULLET code as
  320.     another .LIB, for example. Also, if BULLET code is to be contained in a
  321.     Dynamic Link Library (DLL) then it must be part of a stand-alone product.
  322.     This means that you cannot provide a .DLL containing BULLET code if that
  323.     .DLL is to be used as a programming library for other programmers. If you
  324.     wish to distribute non-executable code containing BULLET code you must
  325.     obtain written permission from the author.
  326.  3. This license grants you the right to use the BULLET library code on a
  327.     royalty-free basis.
  328. See: License_a                                                          -MORE-
  329. ~License_a
  330.  4. BULLET is owned by the author, Cornel Huth, and is protected by United
  331.     States copyright laws and international treaty provisions. You are not
  332.     allowed to make copies of this software except for archival purposes.
  333.  5. You may not rent or lease BULLET. You may not transfer this license without
  334.     the written permission of the author. If this software is an update or
  335.     upgrade, you may not sell or give away previous versions.
  336.  6. You may not reverse engineer, decompile, or disassemble this software.
  337.  7. There are no expressed or implied warranties with this software.
  338.  8. All liabilities in the use of this software rest with the user.
  339.  9. U.S. Government Restricted Rights. This software is provided with
  340.     restricted rights. Use, duplication, or disclosure by the Government is
  341.     subject to restrictions as set forth in subparagraph (c)(1)(ii) of the
  342.     Rights in Technical Data and Computer Software clause at 52.227-7013.
  343.     Manufacturer is Cornel Huth/6402 Ingram Rd/San Antonio, TX 78238.
  344.     This agreement is governed by the laws of the state of Texas.
  345. See: Product_Support
  346. ~Product_Support
  347. Support is available at my BBS, The 40th Floor (8N1).
  348. Hours of Operation
  349. ============================
  350. Fax/BBS: Mon-Fri, 5pm to 9am
  351. Fax/BBS: Sat-Sun, 24 hrs/day
  352. ============================
  353. USA Central // GMT-0600
  354. - Weekend hours are 5pm Friday through 9am Monday
  355. Latest releases of BULLET are available for free download by registered users.
  356. Nominal support is also available through e-mail:
  357. (e-mail) cornel@crl.com
  358. (FTP) ftp.crl.com /users/ro/cornel
  359. (WWW) ftp://ftp.crl.com/users/ro/cornel
  360. Bullet is available for DOS, DOS/Win, OS/2 16-bit, OS/2 32-bit
  361. See: Starting_CZ
  362. ~Starting_CZ
  363. At CZ's initial load it looks into the current directory for CZ.HLP, then in 
  364. the directory of CZ.COM, and last it looks for the pathname specified by the 
  365. DOS variable CZH (SET CZH=C:\DOC\CZ.HLP). Use /f: for alternate locations or 
  366. if CZ has any trouble locating its CZ.HLP file (C>cz /f:D:\BIN\CZ.HLP).      
  367. Load CZ.COM from the DOS command line. Options are:
  368.         /f:helpfile.ext       Use other than default CZ.HLP help file
  369.         /h# where n=1 to 4    Use alternate hot-key from default Alt-F1
  370.             #=1  Ctrl-h
  371.             #=2  F12
  372.             #=3  left+right Shift
  373.             #=4  Alt-left Shift
  374.         /u  uninstall CZ from memory (after initial load)
  375.         /s  temporarily put CZ to sleep by restoring all hooked vectors
  376.         /r  restore CZ from its sleep by rehooking vectors
  377.         /?  quick help
  378.  E.g., C>cz /f:D:\PRG_C\CBULLET.HLP   supply entire pathname when using /f:
  379.        C>cz /h1                       change hot key from Alt-F1 to Ctrl-H
  380. See: Using_CZ
  381. ~Using_CZ
  382. To activate CZ press the hot-key while the cursor is on the word you want to
  383. look up. Information on that word, if any, is displayed. If none is available,
  384. an index of help items in the dictionary is shown. Along the top-right of the
  385. index screens is the control bar. You can quickly move to the control bar by
  386. pressing <Home> or the See: line with <End>. Move the cursor to TUTORIAL_INDEX
  387. to select the second index screen or QUIT to return to whatever you were doing
  388. or over any index item. Then press <Enter> to move to that item's help entry.
  389. <F1> can be used as <Enter>. A mouse can also be used and is recommended.
  390. For example, to find out about CreateDXB, type it in your application and move
  391. the cursor on it. Press the hot-key. The CreateDXB screen is displayed. To see
  392. what pack type it uses, move to CreateDataPack (at Pack:) and press <Enter>.
  393. For a source example, move the cursor to Src: CreateDXBsrc. To go straight to
  394. the index from your application, press the hot-key with the cursor on a blank
  395. space. The <Esc> key returns you to your application.
  396. If there are more screens for the current topic the See: line has the same   
  397. topic name plus a letter, and -MORE- at the end. Move the cursor (or mouse)  
  398. to the topicname text (by using the <End> key) and press <Enter> (or click). 
  399. See: Using_CZ_a                                                         -MORE-
  400. ~Using_CZ_a
  401. CZ.COM can be loaded high but it is ESSENTIAL that you have at least 15K of  
  402. free UMB RAM available. It will load in as little as 4.5K but it will not    
  403. operate correctly. Use MEM/c to see how much Upper Memory RAM is available.  
  404. CZ opens the help file at installation. The help file is opened for Read-Only
  405. access with a Deny None sharing attribute. The file is closed when CZ is
  406. uninstalled (C>cz /u). CZ makes use of its own 256-byte stack.
  407. If you have several CZ help files, rename them to their particular application.
  408. For example:
  409. Rename the QuickBASIC BULLET CZ.HLP to QBULLET.HLP. Put QBULLET.HLP into your
  410. help files directory. Put SET CZH=C:\HELPFILES\QBULLET.HLP in your AUTOEXEC.BAT
  411. file. The next time CZ is installed it uses QBULLET.HLP from C:\HELPFILES.
  412. At anytime you can specify CZ.COM to use another help file. For example, if the
  413. current CZ help file is QBULLET.HLP but you want to use the CBULLET.HLP file,
  414. use C>cz /f:\helpfiles\cbullet.hlp. CBULLET.HLP then becomes the active file
  415. the next time you popup CZ.
  416. See: Using_CZ_b                                                         -MORE-
  417. ~Using_CZ_b
  418. Limitations:
  419. 1) The QB environment may interpret the Alt-F1 keypress after CZ has popped
  420. down. If this is a problem then change the hotkey, e.g., C>cz /h2 to use F12.
  421. 2) In the QB (and QBX) environment the keypad <Enter> key is not recognized by
  422. CZ. Use the main <Enter>. This occurs only in then QB 4.5 and QBX editors.
  423. 3) If, after returning from CZ, the QB environment's menu bar does not respond
  424. to Alt-keys (like an Alt-F), click the left mouse button a few times, or press
  425. F6 to go to the immediate window and execute a SHELL. It's unlikely that you'll
  426. encounter this.
  427. 4) CZ is a stable TSR but like all TSRs in a DOS system, unforseen events can
  428. take place that could conceivably cause the computer to crash. Therefore, it's
  429. recommended that you save your work often (you should do so whether a TSR is
  430. installed or not).
  431. 5) CZ currently doesn't reset the mouse. If you're having mouse trouble, you'll
  432. need to reset your mouse driver (type MOUSE at the C>). Many problems come from
  433. other programs not restoring the mouse cursor to its original state.
  434. See: About_CZ
  435. ~About_CZ
  436.               
  437.               
  438.                      CZ HELP                     
  439.               
  440.                                                  
  441.               
  442.       Context-sensitive Online Help Manager      
  443.               
  444.                                                  
  445.               
  446.                      for the                     
  447.               
  448.                                                  
  449.               
  450.                
  451.               
  452.               
  453.                
  454.                
  455.               
  456.                
  457.                
  458.               
  459.                
  460.                
  461.               
  462.                                                  
  463.               
  464.                 compiler libraries               
  465.               
  466.                                                  
  467.               
  468.        MS-DOS QuickBASIC/BASIC PDS version       
  469.               
  470.                                                  
  471.               
  472.                                                  
  473.               
  474.          Copyright 1992-1995  Cornel Huth        
  475.               
  476.                                                  
  477.               
  478. Ver 1.2          INT2F MuxID=C2          5-Jan-95
  479.               
  480. See: Specs_Overall
  481. ~is_BULLET - What?
  482. BULLET is a program module that handles the details of putting information to
  483. and getting information from your hard disk using a standard data file format
  484. called the Xbase DBF format with very fast and efficient index file routines.
  485. It can be used as-is by most DOS compilers.
  486. BULLET is written in 100% assembly language. Why? Two reasons. First, control.
  487. There's no compiler code or run-time library code in between BULLET and your
  488. data. Second, efficiency. BULLET knows exactly what it requires from the
  489. operating system and when. Result: fast, small, and robust applications.
  490. See: is_a_database
  491. ~is_a_database - What?
  492. A database is a collection of data arranged so that the it can be accessed as
  493. useful information. For example, let's say we have two files. Each consists of
  494. two fields. The first file has codenumber and score. The second file has a
  495. codenumber and name. Separately, the files are merely a collection of data.
  496. Together, however, they tie the name to the score:
  497.         score codenumber   codenumber name
  498.          99     100           100     John
  499.          87     155           105     Paul
  500.          66     125           110     George
  501.           :      :             :       :
  502. Codenumber 100 is John, who scored 99. The other members scores are not in the
  503. abbreviated data file listing.
  504. A database can be a single data file but more often it is a group of related
  505. data files and usually these data files are indexed by keys (in the index file,
  506. also called key file) so that very fast, direct access is possible.
  507. Ringo.
  508. See: is_DBF
  509. ~is_DBF - What?
  510. DBF is the file extension of dBASE III-compatible data files (filename.DBF).
  511. The file format is used by dBASE IV, FoxPro and many other database programs.
  512. Many programs can also use the file format to import/export data using it.
  513. The DBF format is the most common data file format used on PCs.
  514. A DBF-compatible data file consists 3 distinct areas. First is the data header.
  515. This contains information such as the number of records in the file. Second is
  516. the field descriptors. These descriptors define the makeup of each field in the
  517. record. The third is the record area. Each record is a logical unit of data.
  518. For example, a record, all of which are made up of the same fields but with
  519. different data, could (conceptually) look like this:
  520.                field 1         field 2         field 3       field n
  521.            
  522.   record 1 
  523. Johnson         
  524. Larry          
  525. 465310555     ...
  526.            
  527.   record 2 
  528. Aberdeen        
  529. Zara           
  530. 465230555     ...
  531.            
  532.   record n
  533. See: is_a_Btree  Specs_DBF
  534. ~is_a_Btree - What?
  535. A b-tree is a sorting method ideally suited to data structures maintained on a
  536. hard disk. It is very fast on retrieval and is inherently self-balancing during
  537. inserts and deletes. Self-balancing ensures performance remains consistent.
  538. The reason the b-tree is ideally suited to hard disks is that, when looking for
  539. a particular key, most of the time involved in accessing the key is spent by
  540. the hard drive moving to various locations on the disk. The task of a good
  541. access method is to reduce the number of seeks that the disk must perform. The
  542. b-tree accomplishes this by maintaining several keys (perhaps 50) on each node,
  543. with the necessary pointers to previous and following nodes. A b-tree of order
  544. 20 (19 keys per node) can find a key in a file of 1,000,000 keys in a MAXIMUM
  545. of 5 disk accesses, where each disk access visits a node.
  546. 'BASIC program to find *max* seeks needed/avg time
  547. Keys& = 1000000: KeysPerNode = 19: AvgSR = 25
  548. Order = KeysPerNode + 1
  549. max = (LOG((Keys& + 1) / 2) / LOG(Order / 2))
  550. PRINT "Max nodes accessed for"; Keys; "keys & b-tree of order"; Order;
  551. PRINT "is"; max; "nodes"
  552. PRINT "Max disk time based on avg seek+read of"; AvgSR;
  553. PRINT "ms is"; AvgSR / 1000 * max; "seconds"
  554. See: is_a_network  Specs_Index
  555. ~is_a_network - What?
  556. A network is a group of computers able to communicate with one another. Often
  557. called a LAN (local area network), a network allows resources to be shared.
  558. Sharing resources can lead to problems if steps are not taken to ensure that
  559. two computers don't try to share the same resource at the same time. For
  560. example, say two computers try to change the same record in a file on a network
  561. drive. Let's say both users are accessing the number of widgets in inventory.
  562. The first user gets there a micro-second before the second and allocates the
  563. last widget in stock. The second user comes in right after and, since the first
  564. user has not yet updated the inventory, allocates the very same widget. One
  565. widget, two users. When the first user updates the inventory, widgets in
  566. inventory is changed to 0 (previous - 1). The second updates the inventory in
  567. the same manner and sets widgets to 1 less what it was when it started, or 0
  568. also. You see the problem.
  569. In order to successfully share a file on a network, the file must first be
  570. locked to a single user. Once that user has locked the file, he has sole access
  571. to the data within it and he will not experience the scenario above. When the
  572. user has completed the changes, he unlocks the file so that others may use it.
  573. See: is_file_locking
  574. ~is_file_locking - What?
  575. File locking is a means to obtain exclusive access to a file. This is needed in
  576. cases of multiple programs or users accessing a shared file at the same time.
  577. There are several methods to ensure only one process or user has access to a
  578. file. The first method is to open the file so that while the file is open only
  579. your program can access any part of it. This is simple to implement and the
  580. operating system handles the details of this. However, it requires your program
  581. to open/close files all the time since no other process may access the file
  582. while it is open.
  583. Another method is to use byte-level locks. Also managed by the OS, this method
  584. allows for restricting access to any particular region within the file. Which
  585. regions are to be locked is to be determined by your program, however, and it
  586. can be complex to perform multiple locks at the byte, field, or record level.
  587. Another use of the byte-level lock is to specify that all bytes within the file
  588. are to be locked. This greatly simplifies the process of obtaining a lock and
  589. has the advantage over a file access lock of not needing to open/close the file
  590. for each lock. It is very fast and easy to implement. BULLET offers all three
  591. lock types.
  592. See: is_NLS
  593. ~is_NLS - What?
  594. NLS stands for National Language Support. This feature is available in DOS 3.3
  595. and later. BULLET makes use of NLS by getting from DOS the current DOS country
  596. collate-sequence table. The collate table is used to properly sort mixed-case
  597. character strings and also foreign (or non-USA) language character strings
  598. according to that country's alphabet. This is an option but is recommended.
  599. In addition, BULLET provides for a programmer-supplied collate-sequence table.
  600. See: design_a_DB
  601. ~design_a_DB - How to
  602. To design a database, above all else, know what information you require from
  603. it. Having established what you need to know, collect the data that lets you
  604. formulate this into useful information.
  605. For example, you want to track a class of students and determine how well they
  606. achieve on tests. The criterion you use is the test score. You determine that
  607. your data is 1) students, 2) tests, and 3) test scores. Too simplify, you use
  608. a single 20-character field for student, a 1-character field for test number
  609. ("1" to the "n" tests), and a numeric field for test scores (0 to 100).
  610. Since the objective is to track students' scores, arrange the data so that
  611. output consists of each student's score in test order. Do this by specifying an
  612. index file containing an index based on the student's name and test number:
  613.   KeyExpression$ = "STUDENT + TEST"       'combine two character fields
  614. This is the reason that field 2, test number, is a character field. It can more
  615. easily be combined with other character fields than a numeric field. By using
  616. the routines of the database langauge, you can easily create the data and index
  617. files, add data, list student's scores, or make changes to the database. Note:
  618. these How_to examples are meant only to show the basis behind an operation.
  619. See: create_a_DB  CreateKXB
  620. ~create_a_DB - How to
  621. Having defined the database, create it. First, create the datafile based on the
  622. 3 fields you defined in your design. To do this, DIM an array for the field
  623. descriptors for the number of fields (see also CreateDataPack):
  624. DIM FD(1 TO 3) AS FieldDescTYPE
  625. FD(1).FieldName = "STUDENT" + STRING$(10,0)   'must be zero-filled
  626. FD(1).FieldType = "C"
  627. FD(1).FieldLength = CHR$(20)               
  628. FD(1).FieldDC = CHR$(0)                    
  629. The FD() is a structure element  
  630. FD(2).FieldName = "TEST" + STRING$(10,0)   
  631. in CDP (CreateDataPack) as in:   
  632. FD(2).FieldType = "C"                      
  633. CDP.Func=CREATEDXB               
  634. FD(2).FieldLength = CHR$(1)                
  635.   :        :                     
  636. FD(2).FieldDC = CHR$(0)                    
  637. CDP.FieldListPtrOff=VARPTR(FD(1))
  638. FD(3).FieldName = "SCORE" + STRING$(10,0)  
  639. CDP.FieldListPtrSeg=VARSEG(FD(1))
  640. FD(3).FieldType = "N"                      
  641.   :        :                     
  642. FD(3).FieldLength = CHR$(3)                
  643. FD(3).FieldDC = CHR$(0)
  644. Call CreateDXB to create the data file. To create the index file, first open
  645. the data file just created, then call CreateKXB to create the index file. Open
  646. the index file so we can use it (data file is already open).
  647. See: add_to_the_DB  CreateDXB
  648. ~add_to_the_DB - How to
  649. Once you have the database designed and the data and key files created and open
  650. you can start putting the student's test data into it. Note that the DBF-format
  651. requires that all data in a data file be in ASCII format. This means that we
  652. must convert the numeric test score into its ASCII form. BASIC has the STR$()
  653. function to do this. In addition, numbers generally should be right-justified
  654. in their field. BASIC has the RSET statement to do this:
  655. TYPE StudentRecordTYPE 'this structure is exactly how the record is on disk
  656. tag AS STRING * 1      'DBF delete tag used to identify deleted records
  657. sname AS STRING * 20   '--the tag is always present in any DBF record
  658. testn AS STRING * 1    '  don't forget to include it in all your TYPEs
  659. score AS STRING * 3
  660. END TYPE '25
  661. DIM SR AS StudentRecordTYPE
  662.      :
  663.    INPUT "Student name, test number, score:",n$,t$,s%
  664.    SR.sname = n$ : SR.testn = t$ : RSET SR.score = STR$(s%)
  665.    status = DoInsert(SR, keyhandle)
  666. LOOP UNTIL LEN(n$) = 0 OR (status <> 0)
  667. See: query_the_DB  InsertXB
  668. ~query_the_DB - How to
  669. Now that you have data in the database you want to see what's in there. Since
  670. the index file is in "STUDENT+TEST" order, the information we'll be getting
  671. out of the database is in Student name order, with each student's scores in
  672. test number order.
  673. If we want to look at all the students, we can use GetFirstXB to retrieve the
  674. first student's score for the first test. GetNextXB retrieves the next record
  675. (the first student's score for the second test), and so on. When all records
  676. have been retrieve GetNextXB returns an End Of File error code.
  677. If we want to look at a particular student's score only, we can use GetEqualXB
  678. to go directly to a student's first test score. GetNextXB get his next and so
  679. on until GetNextXB retrieves the next student's first test score. You can stop
  680. at this point (student names no longer match).
  681. We might also want to find all students who scored less than 65 on any test. To
  682. do this we can GetFirstXB, check SR.score for < 65 and if so print that record.
  683. Continue by using GetNextXB, printing each record that has a score < 65.
  684. See: update_the_DB  GetFirstXB
  685. ~update_the_DB - How to
  686. To update a particular record in the database we must first locate and identify
  687. it using one of the get routines such as GetEqualXB. The Get() routine return
  688. the record data, and also the physical record number of the record accessed,
  689. into the AccessPack RecNo. Having used one of the Get() routines to read the
  690. data record from disk to memory, you can make any changes to the data record in
  691. memory. E.g., if a student's score needs to be changed from a 69 to a 96, first
  692. find the record (and its RecNo), then update the score field:
  693.    INPUT "Student name, test number",n$,t$
  694.    SR.sname = n$ : SR.testn = t$
  695.    status = DoGetStudentTestScore(SR, keyhandle, Recno&)
  696.    DO UNTIL status <> 200   'student as entered not found, call search routine
  697.       status = DoFindStudentTestScore(SR, keyhandle, RecNo&)
  698.    LOOP
  699.    IF status = 0 THEN
  700.       PRINT "Student:" ; SR.sname ; " old score:" ; SR.score
  701.       INPUT "Enter new score:"; s% : RSET SR.score = STR$(val(s%))
  702.       status = DoUpdateTestScore(SR, keyhandle, Recno&)
  703.    ENDIF
  704. Any change to a key field will initiate a key file update automatically.
  705. See: delete_a_record  UpdateXB
  706. ~delete_a_record - How to
  707. To delete a particular record in the database we must first locate it using
  708. one of the get routines such as GetEqualXB. These Get() routines return the
  709. actual record number of the data record accessed by Get() into the AccessPack
  710. RecNo. Having used one of the Get() routines to find the data record, make a
  711. call to the delete function:
  712.    'delete all of Student's records, 1 record for each test he's taken
  713.    INPUT "Student name to delete",n$
  714.    SR.sname = n$
  715.    status = DoGetStudent(SR, keyhandle, RecNo&)
  716.    DO UNTIL status <> 200   'student as entered not found, call search routine
  717.       status = DoFindStudent(SR, keyhandle,RecNo&)
  718.    LOOP
  719.    DO
  720.       status = DoDeleteRecord(SR, RecNo&)  'does not affect key files
  721.       IF status = 0 THEN status = GetNextChkIfSameStudent(SR,keyhandle,RecNo&)
  722.    LOOP UNTIL status <> 0
  723. The DeleteRecordXB routine does not physically remove the record from the data
  724. file but instead tags it as being "deleted".
  725. See: BC_compile_with  DeleteRecordXB
  726. ~BC_compile_with - How to
  727. To create a stand-alone EXE file, compile your BASIC source as required. No
  728. special compiler switches are required. When your compiler is finished and has
  729. reported no errors during the compile, use the LINK program supplied with your
  730. compiler to resolve any external references in your BASIC program code that are
  731. dependant on the BULLET library code.
  732. For example, if you have a single-module BASIC source file called STUGRADE.BAS,
  733. compile it:
  734.  C>bc STUGRADE /o;
  735. If successful, use the LINK program to build the final EXE:
  736.  C>link STUGRADE,STUGRADE.EXE,nul,BULLET.LIB;
  737. If successful, link creates STUGRADE.EXE ready to be run at the DOS prompt.
  738. The BASIC runtime is also supported by BULLET. Just compile as you normally
  739. would (without the /o, of course).
  740. See: LIB_with
  741. ~LIB_with - How to
  742. BULLET.LIB is composed of many separate assembly language modules. All these
  743. modules have been combined into a single, easy-to-use .LIB library. While it
  744. is possible to combine, or add, other .OBJ files or even other .LIB files to
  745. BULLET.LIB, I do NOT, -NOT-, recommend that you do so.
  746. If you need to use two or more libraries with your programs, no problem, LINK
  747. can handle as many as you have. When LINK prompts you for a library file, just
  748. enter BULLET.LIB followed by any other library you need. For example:
  749.  C>LINK
  750.  Microsoft (R) Segmented-Executable Linker  Version 5.50
  751.  Copyright (C) Microsoft Corp 1984-1990.  All rights reserved.
  752.  Object Modules [.OBJ]: STUGRAD1+STUGRAD2+STUB
  753.  Run File [STUGRAD1.EXE]: STUGRADE.EXE
  754.  List File [NUL.MAP]: nul
  755.  Libraries [.LIB]: BULLET;
  756. Consult your linker programs documentation for specifics.
  757. See: make_a_QLB
  758. ~make_a_QLB - How to
  759. If you use the QuickBASIC environment to program in, you need to build a .QLB
  760. so that you can call the BULLET routines. While QuickBASIC can load only a
  761. single QLB ( C>qb /L quicklib.qlb ), you can combine many LIB and OBJ modules
  762. to create the QLB. For example, to make a QLB of the BULLET.LIB, MOUSE.LIB,
  763. and STUB.OBJ modules:
  764.  C>link /QU BULLET.LIB+MOUSE.LIB+STUB, IDE.QLB, nul, BQLB45.LIB;
  765. Note the extension .LIB on the library modules. This is REQUIRED since LINK
  766. assumes .OBJ by default, as in the case of STUB, above. The quick library,
  767. BQLB45.LIB, is required for the Libraries: prompt. The exact name depends on
  768. the compiler version. Consult your compiler documentation for more.
  769. BASIC PDS note: BASIC PDS requires that all BASIC modules included into a QLB
  770. be compiled using the /Fs compiler switch. This instructs the compiler to
  771. generate code compatible with "far strings". Since BULLET is written entirely
  772. in assembly langauge, this is not an issue. However, if you start QBX.EXE with
  773. /L and get an INVALID FORMAT error, one of the modules in the .QLB file most
  774. likely was a BASIC module that was not compiled with the /Fs switch.
  775. See: LINK_with
  776. ~LINK_with - How to
  777. After successfully compiling your BASIC source code module(s), use the LINK
  778. program to build the EXE program file. For this example let's assume that you
  779. have 2 BASIC source code modules just compiled and their .OBJs available, the
  780. BULLET.LIB library, a stub object file called STUB.OBJ, and MOUSE.LIB.
  781. To build the final stand-alone EXE from this group of files, do the following:
  782.  C>link STUGRAD1+STUGRAD2+STUB,STUGRADE.EXE,nul,BULLET+MOUSE;
  783. The 3 object modules, STUGRAD1, STUGRAD2, and STUB, will have their entire code
  784. included in the EXE program, created as STUGRADE.EXE. The 2 library files,
  785. BULLET.LIB and MOUSE.LIB, will have only the code that is actually referenced
  786. by the 3 object modules included into the EXE program.
  787. If successful, link creates STUGRADE.EXE ready to be run at the DOS prompt.
  788. See: call_BULLET  AtExitXB
  789. ~call_BULLET - How to?
  790. BULLET is called through a single entry point. The only argument passed to it
  791. is a segmented far pointer to the control pack. The first two entries in this
  792. pack are the function to be performed and the function return status. BULLET
  793. is a FUNCTION call returning an INTEGER status value.
  794. Each function (or routine) uses a prescribed pack format. For example, some
  795. routines need only know the handle of the file, along with the function number
  796. itself. So, to flush a data file, for example, you would do the following:
  797.  DIM HP AS HandlePack           'could also DIM SHARED
  798.  HP.Func = FLUSHDHXB            'FLUSHDHXB is defined as a CONST in BULLET.BI
  799.  HP.Handle = File2FlushHandle   'the handle as returned from the Open() routine
  800.  stat = BULLET(HP)              'do the actual call to BULLET
  801. The value of stat is set to the completion code as returned by the FlushDHXB 
  802. routine. It is the same as the value returned in HP.Stat *IN ALL BUT A FEW*  
  803. cases: InsertXB, UpdateXB, ReindexXB, and LockXB. These routines return not  
  804. the actual error code, but rather a transaction index number of the access   
  805. that failed. See those routines for more information.                        
  806. See: is_BULLET  FlushDHXB
  807. ~Specs_Overall
  808. BULLET is dBASE III/III+/IV .DBF-compatible. This format is compatible with a
  809. large base of software programs including the latest database packages such as
  810. dBASE IV and FoxPro. Spreadsheet packages such as Excel and 1-2-3 can directly
  811. import BULLET DBF data files, too. And because of BULLET's versatility, it can
  812. also create very non-standard data files. This may be a useful feature if data
  813. secrecy is of concern.
  814. BULLET requires MS-DOS 3.30 or above. It uses 19K of code/static data space and
  815. requires at least 40K of workspace. 140K of workspace is ideal.
  816. Overall Specifications:
  817.               DBF           (per file)          INDEX
  818.       
  819.     Max records: 16,777,215                Max nodes: 65,535
  820.   Record length: 2-4000 (8192)              Max keys: 4,063,170
  821.      Max fields: 128 (255)                Key length: 1-64
  822.    Field length: 1-254 (255)          Max key fields: 16
  823. Total open index plus data files can be up to 255. Numbers in () indicate
  824. extended specifications.
  825. See: Specs_DBF
  826. ~Specs_DBF
  827. To remain compatible with other dBASE III .DBF platforms you should restrict
  828. your data files to the following specifications:
  829.  File ID byte: 3  (83hex if .DBF has memo field, not currently supported)
  830.  Max record size: 4000 bytes  Max fields/rec: 128   Max field size: 254 bytes
  831.  Allowable field name characters: A-Z and the _ (upper-case)
  832.  Allowable field types:
  833.   C-character, 1-254 bytes
  834.   D-date, 8 bytes, in the format YYYYMMDD (19920531)
  835.   L-logical, 1 byte, either space, "T" or "Y", "F" or "N"
  836.   M-memo, 10 bytes, used as pointer into .DBT file (currently not supported)
  837.   N-numeric, 1-19 bytes, ASCII format, uses explicit decimal if needed...
  838.     ...decimal places may be 0, or 2 to (field size - 3) but no more than 15
  839. Restrict all data in .DBF fields to ASCII. This means you should convert binary
  840. data to the equivalent ASCII representation, e.g., if you have the binary value
  841. 22154, it must first be converted to the string "22154" before you can store it
  842. to the .DBF data file. So, while your in-program code deals with binary data,
  843. your I/O code must convert it to/from ASCII. This is a dBASE-compatibility
  844. issue only. If you can forgo these requirements you can use binary fields, any-
  845. character field names, record sizes to 8192 bytes, and up to 255 fields.
  846. See: Specs_DBF_a                                                        -MORE-
  847. ~Specs_DBF_a
  848. A dBASE III .DBF is composed of 3 sections: the header, the field descriptors,
  849. and the data area.
  850. The header structure (first 32 bytes of file):
  851.     Name     Type   Offset  Meaning
  852.  FileID      byte        0  data file type id, 03 standard (43,63,83,88h)
  853.  LastYR      byte        1  last update year, binary
  854.  LastMo      byte        2  last update month, binary
  855.  LastDA      byte        3  last update day, binary
  856.  NoRecs      long        4  number of records in file
  857.  HdrLen      word        8  length of header, including field descriptors, +1
  858.  RecLen      word       10  length of data record including delete tag
  859.  internal    byte    12-31  reserved
  860. The last update values are updated to the current date whenever the .DBF file
  861. is flushed or closed. Likewise, the NoRecs value is updated whenever a record
  862. is added to the .DBF. The FileID is specified when you create the file, HdrLen
  863. and RecLen are computed and stored when the file is created, too.
  864. See: Specs_DBF_b                                                        -MORE-
  865. ~Specs_DBF_b
  866. The field descriptor format (follows header, one per field):
  867.     Name     Type   Offset  Meaning
  868.  FieldName   char        0  field name 10 ASCII characters, A-Z or _ (0-filled)
  869.         0T   byte       10  field name zero-termintor (must be 0)
  870.  FieldType   char       11  field type (C D L M N)
  871.  internal    long       12  reserved
  872.  FieldLen    byte       16  length of this field
  873.  FieldDC     byte       17  decimal count
  874.  internal    byte    18-31  reserved
  875.       
  876. The unused bytes in the FieldName must be set to zeroes (CHR$(0)).
  877. Each field is described by a 32-byte descriptor. The first field's descriptor
  878. starts right after the header proper, at offset +32. After the last field
  879. descriptor is data byte ASCII 13. (Note: the orginal dBASE III has a 0 byte
  880. following this ASCII 13.) Immediately following this is the actual record data.
  881. See: Specs_DBF_c                                                        -MORE-
  882. ~Specs_DBF_c
  883. The data record format:
  884. The first record is located at offset HdrLen (from the header). The first byte
  885. of each record is a delete tag. This tag is maintained by the BULLET routines.
  886. A space, ASCII 32, means the record is not deleted; an asterisk, ASCII 42,
  887. means the record has been deleted (marked as deleted, often this is used as a
  888. method to temporarily tag records, for whatever purpose).
  889. Following the tag is the data for each field, not delimited (i.e., the fields
  890. run together without anything separating them). The second record is at offset
  891. HdrLen+reclen. The start offset of any record in the file can be computed as
  892. (recordnumber - 1) * reclen + HdrLen. All data is in ASCII form.
  893. An EOF marker (ASCII 26) is placed at the end of the last record.
  894. See: Specs_Index
  895. ~Specs_Index
  896. BULLET uses a proprietary, modified b-tree index method to manage the index
  897. files. The supported key types are:
  898.     Type     Length  Meaning
  899.  Character     1-64  ASCII, NLS, or user-supplied sort table
  900.  Integer          2  signed or unsigned 16-bit value
  901.  Long Int         4  signed or unsigned 32-bit value
  902. In addition to the above types, BULLET allows for unique or duplicate keys in
  903. the index file. If duplicates are allowed, BULLET enumerates each key with an
  904. enumerator word (see FirstKeyXB).
  905. The key may be composed of up to 16 character fields or substrings within those
  906. fields. Numeric fields are considered character fields by BULLET unless the key
  907. is set to binary (see KeyFlags). Integer or LongInt binary keys can be composed
  908. of a single field only. The key expression is specified in text (e.g., "LNAME+
  909. SUBSTR(FNAME,1,1)+MI") and is fully evaluated when the index file is created.
  910. A BULLET index file is composed of 3 sections: the header, the collate-sequence
  911. table, and the node/key entry area.
  912. See: Specs_Index_a                                                      -MORE-
  913. ~Specs_Index_a
  914. The header structure:
  915.     Name     Type   Offset  Meaning
  916.  FileID      byte        0  index file type id, 20
  917.  RootNode    word        1  root node number
  918.  Keys        24bit       3  number of keys in index file
  919.  AvalNode    word        6  node number available for reuse
  920.  FreeNode    word        8  next free node number
  921.  KeyLen      byte       10  key length
  922.  NodeKeys    byte       11  number of keys that fit on a node
  923.  CodePage    word       12  code page ID
  924.  CtryCode    word       14  country code
  925.  internal    byte    16-21  reserved
  926.  KeyFlags    word       22  key flags
  927.  KeyExprn    byte   24-159  key expression
  928.  internal    byte      160  reserved
  929.  KeyXFlds    byte      161  number of fields used by key (1-16)
  930.  KeyXlate    byte  162-225  translated key expression
  931.  internal    byte  226-253  reserved
  932.  CTsize      word      254  collate-sequence table size
  933. See: Specs_Index_b                                                      -MORE-
  934. ~Specs_Index_b
  935. The collate-sequence table structure:
  936.  table      byte   256-511  sort weight table of ASCII character 0-255
  937. Node/key entry structure (first entry is in node #1, file offset 512):
  938.   2A  0A 00  KEY123  7B 00 00  12 00  KEY178  B2 00 00  0C 00 ...
  939.    1.   2.     3.       4.       5.     6.       7.       8.   9.
  940.       
  941.  1. Key count for that node (first byte of each node)
  942.  2. 16-bit node back pointer (for non-leaf nodes, 0 if leaf node)
  943.  3. First key value, "KEY123" in this case
  944.  4. 24-bit data record pointer (low word/hi byte) 7Bh = DBF record number 123
  945.  5. 16-bit node forward ptr/back ptr (for non-leaf nodes, 0 if leaf node)
  946.     --in this case, it indicates that the key following KEY123 is in node# 12h
  947.     --and also that the key before KEY178 is in that node as well
  948.  6. Second key (here "KEY178")
  949.  7. 24-bit data pointer (record number in DBF)
  950.  8. 16-bit forward node pointer (for non-leaf nodes, 0 if leaf node)
  951.  9. Repeat 6 to 8 for each key on node. (node size is 512 bytes)
  952. See: Specs_Index_c                                                      -MORE-
  953. ~Specs_Index_c
  954. As in many b-tree implementations, BULLET's index files maintain an average
  955. load percentage of approximately 66%. This means that in any given node, 66% of
  956. the available space is in use. The free space in the node is attributable to
  957. the constant reshaping of the file as keys are inserted or deleted, causing the
  958. nodes to be split and merged. A split will occur when an insert needs to add a
  959. key to an already full node; a merge will occur when a neighboring node is
  960. small enough to be merged into a just split node. This constant prune-and-graft
  961. of the b-tree results in a node load of about 66% (50% in degenerate cases such
  962. as with already sorted data). It's this aspect of the b-tree that makes it a
  963. consistent performer and a widely-used method of managing index files.
  964. The following formula can be used to determine the number of keys that an index
  965. file can hold:
  966.   MaxKeys = MaxNodes * MaxKeysPerNode * LoadFactor
  967.   MaxKeys = 65535 * 509/(keylen+5) * .66
  968. The load factor can be increased to ~95% by using the ReindexXB routine. This
  969. load factor results in superior retrieval speeds since there are more keys on
  970. each node. Insertion speed will be decreased, however, since splitting will
  971. occur more frequently, though perhaps not noticeably.
  972. See: Specs_Memory
  973. ~Specs_Memory
  974. BULLET allocates memory on an as-needed basis. When linked to an executable
  975. program, BULLET makes use of 17.5K of code space and about 1.5K of static
  976. DGROUP data space. To accomodate the wide variety of compilers, BULLET's API
  977. structure will have the linker included all of the library into your final EXE
  978. program.
  979. All runtime memory allocations are obtained from the operating system. This
  980. means that if your compiler generates code to allocate all the free memory at
  981. startup for its far heap, you need to instruct it to free up some memory for
  982. BULLET's use. In QuickBASIC you can use SETMEM(). You can also use the linker
  983. /CP:n option to limit the amount that the compiler-generated startup code
  984. allocates. The EXEHDR.EXE program can also be used to modify this amount. The
  985. linker /CP: option and the EXEHDR program both modify the EXE header. To
  986. determine if you need to release memory use the MemoryXB routine. It reports
  987. the operating system memory available for use by BULLET.
  988. The amount of memory that BULLET requires is based on which routines are used.
  989. See the next screen for a list of the routines that make malloc calls to the
  990. operating system and how much memory they require.
  991. (Most compilers don't grab all memory as QuickBASIC when it's using $DYNAMIC).
  992. See: Specs_Memory_a  MemoryXB                                           -MORE-
  993. ~Specs_Memory_a
  994. Routines making dynamic memory allocations and amount (within 
  995.  16 bytes):
  996.   Routine           Bytes        Basis
  997. InitXB                  272   permanent, released when program ends (JFTmode=1)
  998. BackupFileXB             32K  temp, released when routine exits
  999. CreateDXB        48+(NF*32)   temp, released when routine exits (NF=NoFields)
  1000. CreateKXB               544   temp, released when routine exits
  1001. OpenDXB     144+((1+NF)*32)   semi-permanent, released when file closed
  1002. OpenKXB                1264   semi-permanent, released when file closed
  1003. PackRecordsXB      RL to 64K  temp, released when routine exits (RL=RecLength)
  1004. ReindexXB        32K to 128K  temp, released when routine exits
  1005. UpdateXB              2K+RL   temp, released when routine exits (RL=RecLength)
  1006. For example, when BackupFileXB is called it attempts to allocate 32K from the
  1007. OS. If 32K is not available, BackupFileXB returns with an error code of 8 (DOS
  1008. error #8, not enough memory). If you won't be using Backup or Reindex, BULLET
  1009. can make do with much less memory (use table above).
  1010. Needed stack space is 4K (max) for ReindexXB. Other routines can operate with
  1011. less than 1K of stack space. In other words, stack use is minimal.
  1012. See: Specs_OS_calls
  1013. ~Specs_OS_calls
  1014. BULLET makes use of the following operating system calls:
  1015. INT21/25 DOS_setvector                  INT21/44/0B DOS_setsharingretrycount
  1016. INT21/2A DOS_getdate                    INT21/48 DOS_malloc
  1017. INT21/30 DOS_version                    INT21/49 DOS_free
  1018. INT21/35 DOS_getvector                  INT21/51 DOS_getpsp
  1019. INT21/39 DOS_makedir                    INT21/56 DOS_renamefile
  1020. INT21/3D DOS_openfile                   INT21/59 DOS_getextendederror
  1021. INT21/3E DOS_closefile                  INT21/5A DOS_createtempfile
  1022. INT21/3F DOS_readfile                   INT21/5B DOS_createnewfile
  1023. INT21/40 DOS_writefile                  INT21/5C DOS_lockunlockfile
  1024. INT21/41 DOS_deletefile                 INT21/65/01 DOS_getextendedcountryinfo
  1025. INT21/42 DOS_movefileptr                INT21/65/06 DOS_getcollatesequencetable
  1026. INT21/44/09 DOS_isdriveremote           INT21/67 DOS_sethandlecount
  1027. INT21/44/0A DOS_isfileremote            INT2F/10/00 DOS_isshareinstalled
  1028. No other operating system calls are made. No BIOS calls are made.
  1029. See: Specs_Languages
  1030. ~Specs_Languages
  1031. BULLET is compatible with most DOS compilers. The only requirements are that
  1032. your compiler allow you to:
  1033.  1. Call a library routine via a FAR call using PASCAL calling convention
  1034.  2. Pass a far pointer (of the parameter pack) on the stack, by value
  1035.  3. Supply far pointers to the various pack parameters
  1036.  4. Be able to return an integer value from the FAR call
  1037.     (this is optional but recommended for the transaction-based routines)
  1038. These requirements can be met with most BASIC, C, and other-language DOS
  1039. compilers.
  1040. CZ online help is currently available in BASIC and C versions. Others are
  1041. pending. You should be able to do well with either of these versions using
  1042. other-language compilers since the only difference is the source code examples.
  1043. See: Specs_OSes
  1044. ~Specs_OSes
  1045. BULLET is currently available only for MS-DOS and compatible operating systems.
  1046. It requires DOS 3.3 or higher.
  1047. To provide efficient memory use, BULLET uses a single-buffer cache per index
  1048. file. The single-buffer cache also provides for very quick network access since
  1049. a minimum amount of memory needs to be flushed when releasing control of BULLET
  1050. files. For maximum speed, however, an external high-performance disk cache can
  1051. be used. Hyperdisk is a good choice (shareware, $50+). A properly configured
  1052. cache can increase BULLET's performance from 10 to 300%. The most improvement
  1053. is with the InsertXB routine. The least is with ReindexXB and PackRecordsXB,
  1054. which do most of their work in temporarily allocated memory. Hyperdisk is about
  1055. the best designed disk cache available for PCs. SmartDRV 4.x is also good.
  1056. If you do not use a disk cache then it's recommended that you set your BUFFERS=
  1057. statement in CONFIG.SYS to at least 20 or 30. Even without a disk cache, BULLET
  1058. is still very fast. Also, be sure to set your FILES= to the number of files
  1059. that you'll be opening at any one time. If you set FILES=20 you can have BULLET
  1060. open 14 files (CZ.COM uses 1 and DOS reserves 5 more). You can set FILES=255
  1061. allowing BULLET to open up to 249 files at one time.
  1062.                  DO NOT set FILES= to a value greater than 255.
  1063. See: Specs_Networks
  1064. ~Specs_Networks
  1065. BULLET currently operates on all DOS-compatible network platforms.
  1066. Be sure to install SHARE.EXE (or compatible) on the server and, if you are
  1067. mutlitasking, on your local machine. If you'll be opening many files you
  1068. should extended the default SHARE file-sharing information space and the number
  1069. of locks that can performed at one time. The DOS 5.0 default is /F:2048 and
  1070. /L:20. This allocates 2K for file-sharing info space and allows 20 consecutive
  1071. locks to be active. If the F: value is too low, error 5 (extended error 32) is
  1072. returned on an open attempt. If you extend the JFT in InitXB and plan to use
  1073. many files, say more than 50, be sure to extend /F: by 2K for every 50
  1074. additional files and set the /L: to the number of files you plan on having
  1075. open. If L: is too low, error 1 (ext err 36) is returned on a lock attempt.
  1076. As an example, if you'll be using 100 files, set FILES=106 in CONFIG.SYS, set
  1077. SHARE /F:4096 /L:106, and IP.JFTmode=1 for InitXB. These values are a minimum.
  1078. If you have more than one process active, you need to account for other apps.
  1079. Note that Windows always returns a "SHARE is installed" using the DOS detection
  1080. routines used by BULLET. To determine if SHARE is actually installed, attempt
  1081. to perform a lock using one of the LockXB routines. An error code indicates
  1082. that SHARE (or compatible) is not installed.
  1083. See: Specs_Performance
  1084. ~Specs_Performance
  1085.  Test: Reindex 1,000 to 1,000,000 records (BB_LAI10.BAS)
  1086.        DBF: extended DBF using binary sort field
  1087.        key: LONG+SIGNED+UNIQUE                        Machine: 486/33 SHO
  1088.  1Meg
  1089.                                                      *
  1090.      
  1091.      
  1092.                                     *
  1093.      
  1094.                    Records  Time  Reindex Rate
  1095.      
  1096.        *           -------  ----  ------------
  1097.  100k
  1098.   *                   1000   < 1  1000+/sec
  1099.      
  1100.                       5000     2    2500
  1101.      
  1102.  *                   10000     4    2500
  1103.      
  1104. *                    25000     7    3571   3500+ records indexed/second!
  1105.      
  1106.                      50000    14    3571   Times in table are in seconds
  1107.   10k
  1108. *                   100000    28    3571
  1109.      
  1110.                     200000    81    2469
  1111.      
  1112. *                   500000   355    1408
  1113.      
  1114.                    1000000  1124     890
  1115.    1k
  1116.      
  1117.  time (secs)  100       200       300       400       18:00     20:00 (min)
  1118. See: Specs_Perf_a                                                       -MORE-
  1119. ~Specs_Perf_a
  1120.  Test: Add 1,000 to 1,000,000 records (BB_LAI10.BAS)
  1121.        DBF: extended DBF using binary sort field
  1122.        key: not indexed                               Machine: 486/33 SHO
  1123.  1Meg
  1124.                                                       *
  1125.      
  1126.      
  1127.                          *
  1128.      
  1129.          *         Records  Time    Add Rate
  1130.      
  1131.                    -------  ----  ------------
  1132.  100k
  1133.     *                 1000   < 1  1000+/sec
  1134.      
  1135.                       5000     2    2500
  1136.      
  1137.   *                  10000     4    2500
  1138.      
  1139. *                    25000    12    2083   2000+ records added/second!
  1140.      
  1141.                      50000    24    2083   Times in table are in seconds
  1142.   10k
  1143. *                   100000    50    2000
  1144.      
  1145.                     200000   103    1942
  1146.      
  1147. *                   500000   262    1908
  1148.      
  1149.                    1000000   529    1890
  1150.    1k
  1151.      
  1152.  time (secs)  100       200       300       400        8:00     10:00 (min)
  1153. See: Specs_Perf_b                                                       -MORE-
  1154. ~Specs_Perf_b
  1155.  Test: Access 1,000 to 1,000,000 keys(*), keys+records(+) (BB_LGK10.BAS)
  1156.        DBF: extended DBF using binary sort field
  1157.        key: LONG+SIGNED+UNIQUE                        Machine: 486/33 SHO
  1158.  1Meg
  1159.                                          *            +
  1160.      
  1161.      
  1162.               *                          +
  1163.      
  1164.     *        +  Keys   Time  Access Rate   Keys+Recs Time  Access Rate
  1165.      
  1166.               -------  ----  -----------   --------- ----  ------------
  1167.  100k
  1168.  *   +           1000   < 1  1000+/sec         1000   < 1  1000+/sec
  1169.      
  1170.                 10000     1    10000          10000     6    1667
  1171.      
  1172.                100000    22     4545         100000    68    1471
  1173.      
  1174.                200000    49     4082         200000   144    1389
  1175.      
  1176.                500000   147     3401         500000   427    1171
  1177.   10k
  1178. *+            1000000   424     2358        1000000   948    1055
  1179.      
  1180.      
  1181.              Times for forward/reverse (Next/Prev) were similar (
  1182.      
  1183. +            Times in table are in seconds
  1184.    1k
  1185.      
  1186.  time (secs)  100       200       300       400       15:00     17:00 (min)
  1187. See: Specs_Perf_c                                                       -MORE-
  1188. ~Specs_Perf_c
  1189.  Test: Insert 1,000 random records to existing data/key files (BB_LAA10.BAS)
  1190.        DBF: extended DBF using binary sort field
  1191.        key: LONG+SIGNED+UNIQUE                        Machine: 486/33 SHO
  1192.  Base records/keys   Inserted   Time / Rate
  1193.  -----------------   --------   ----   ----
  1194.               1000       1000     15     67 records+keys inserted/second
  1195.              10000       1000     18     56 Times in table are in seconds
  1196.             100000       1000     19     53
  1197.             200000       1000     20     50
  1198.  This tests the InsertXB speed. A data file containing the base records and
  1199.  an index file containing the same number of keys has inserted into it 1000
  1200.  random keys and records. The records are added to the end of the data file
  1201.  and the keys are inserted into their appropriate place in the index file.
  1202.  Typically InsertXBs would be done online. The rate of 50 inserts/second at
  1203.  200,000 records would indicate a time of 0.02 seconds per insert on even a
  1204.  very large database (0.015 secs/insert @ 1000 records).
  1205. See: Specs_Perf_d                                                       -MORE-
  1206. ~Specs_Perf_d
  1207.  Test: Update 1,000 records by changing the key field (BB_LAU10.BAS)
  1208.        DBF: extended DBF using binary sort field
  1209.        key: LONG+SIGNED+UNIQUE                        Machine: 486/33 SHO
  1210.  Base records/keys    Updated   Time / Rate
  1211.  -----------------    -------   ----   ----
  1212.               1000       1000     50     20 records+keys updated/second
  1213.              10000       1000     59     17 Times in table are in seconds
  1214.             100000       1000    108      9
  1215.             200000       1000    126      8
  1216.  This tests the UpdateXB speed. A data file containing the base records and
  1217.  an index file containing the same number of keys has the first 1000 keys and
  1218.  records changed. This forces the old data record to be replaced, the old index
  1219.  key to be deleted, and a new key for the record to be inserted in the index
  1220.  file.
  1221.  Typically UpdateXBs would be done online. The rate of 8 updates/second at
  1222.  200,000 records would indicate a time of 0.125 seconds per update on even a
  1223.  very large database (0.05 secs/update @ 1000 records).
  1224. See: Specs_Overall
  1225. ~InitXB
  1226. Pack: InitPack          Src: InitXBsrc          Func:   0/System
  1227. Before using any routine you must initialize the BULLET file system.
  1228. If you want more than the standard number of file handles, set InitPack.JFTmode
  1229. to 1. This expands the current process's Job File Table to allow 255 open files
  1230. maximum.
  1231. On return the DOS version (INT21/30h) is in InitPack.DOSver. Major version in
  1232. the high byte. Minor in the low. The BULLET version (*100) is returned as is
  1233. the address of the ExitXB routine. You can use this address to register ExitXB
  1234. with your own _atexit function if your runtime library does not provide _atexit
  1235. already.
  1236. Note: _atexit is a routine available in most DOS, OS/2, and ANSI runtime
  1237. library code and is called just prior to the program ending. See AtExitXB for
  1238. information on what to do if your library does not have _atexit.
  1239. See: ExitXB
  1240. ~ExitXB
  1241. Pack: ExitPack          Src: ExitXBsrc          Func:   1/System
  1242. Before ending your program you should call ExitXB to close any open BULLET
  1243. files. This also will release any memory still allocated to those files.
  1244. This restores the default keyboard break handlers if they were changed.
  1245. In normal operation you would see to closing all files yourself. However, if
  1246. your program fails to reach the programmed end, it's very possible that files
  1247. may still be left open. It is essential that you properly close all BULLET
  1248. files before ending. There are two methods to achieve this:
  1249. 1. In BASIC use ON ERROR GOTO label, where label is in the main module. The
  1250. code at label would then call ExitXB.
  1251. 2. Use AtExitXB to automatically register ExitXB to be executed in the normal
  1252. shut-down code of the compiler. This method is preferred.
  1253. In the QB environment you can easily stop and restart the executing program
  1254. without having reached the end of the program where you call ExitXB. Previously
  1255. opened BULLET files remain open and memory used remains allocated. Eventually
  1256. you will run out of files or out of memory. Use AtExitXB to prevent this.
  1257. See: AtExitXB
  1258. ~AtExitXB
  1259. Pack: ExitPack          Src: AtExitXBsrc        Func:   2/System
  1260. Used to automatically close all BULLET files, release allocated memory, and
  1261. restore the default Break handlers when your program ends. Your compiler
  1262. generates specific code to be executed in the course of ending your program.
  1263. AtExitXB registers the ExitXB routine to be performed in this compiler-
  1264. generated code.
  1265. This routine is standard in most DOS, OS/2, and ANSI runtime libraries. If   
  1266. yours does not have _atexit, then you must link with the supplied            
  1267. NOATEXIT.OBJ file:                                                           
  1268.                                                                              
  1269. C>link YOURPRG + NOATEXIT, ...                                               
  1270. You can tell if your compiler doesn't supply _atexit at link time. LINK reports
  1271. '_atexit' : unresolved external. Add NOATEXIT.OBJ as described above.
  1272. Be sure that your _atexit routine is for the medium, large, or huge memory
  1273. models since BULLET uses multiple code segments and far calls.
  1274. See: MemoryXB  ExitXB  BreakXB
  1275. ~MemoryXB
  1276. Pack: MemoryPack        Src: MemoryXBsrc        Func:   3/System
  1277. This is the only BULLET routine that can be used before InitXB. It reports the
  1278. largest free block of memory available from the OS. This memory does not
  1279. include fragmented memory or UMB memory that BULLET can and will use.
  1280. Some compilers provide their own memory management and thus will use most or 
  1281. all of the contiguous memory when its program loads. BULLET, however,        
  1282. allocates memory on an as-needed basis, directly from the OS, and releases it
  1283. back to the OS as soon as it is no longer needed. If the memory amount       
  1284. returned by MemoryXB is low, your compiler's startup code has pre-allocated  
  1285. all OS memory. If the memory available from the OS is less than your         
  1286. application needs, you need to instruct your program to release some of the  
  1287. memory back to the OS so BULLET can use it. For QuickBASIC and BASIC PDS, see
  1288. the BASIC function SETMEM().                                                 
  1289. With DOS able to use UMB memory, memory for BULLET requests may be provided
  1290. from this region. You can use StatPack.HereSeg from StatXB to locate from which
  1291. segment address the allocations are being made. Anything above C800h is UMB.
  1292. See: BreakXB  StatXB  OpenDXB  OpenKXB
  1293. ~BreakXB
  1294. Pack: BreakPack         Src: BreakXBsrc         Func:   4/System
  1295. Disables system response to Control-C and Control-Break keys preventing users
  1296. from inadvertently exiting the program without first doing a BULLET shutdown.
  1297. It's REQUIRED that you reinstate the default break handlers with this routine
  1298. before ending your program. ExitXB automatically reinstates the default break
  1299. handlers.                                                                    
  1300. This routine will not disable Control-Alt-Delete (a warm-boot). If the user is
  1301. at this point, he may prefer to exit via a warm-boot rather than reset the
  1302. machine.
  1303. Also, this routine does not prevent QuickBASIC and BASIC PDS from terminating
  1304. a program at an INPUT statement. This is because these versions of BASIC are
  1305. using their own method of INPUT aside from DOS. If AtExitXB has been issued,
  1306. all BULLET files will be properly closed even if *User Break* occurs.
  1307. This routine will not surpress the ^C displayed by DOS. If you don't want the
  1308. ^C to be displayed move the cursor to a location off-screen, say, row 26.
  1309. See: BackupFileXB  ExitXB
  1310. ~BackupFileXB
  1311. Pack: CopyPack          Src: BackupFileXBsrc    Func:   5/System
  1312. Copy an open BULLET key or data file. BULLET repacks and reindexes files in-
  1313. place, requiring less disk space to perform the function. BackupFileXB allows
  1314. you to safely copy a file before doing this.
  1315. This function is recommended prior to packing a data file with PackRecordsXB 
  1316. since the data is very valuable. There is probably little need to do so when 
  1317. reindexing an index file since index files can be constructed very easily    
  1318. from the data file but a CopyKHXB to preserve the key expression is quick    
  1319. and recommended.                                                             
  1320. See: StatHandleXB  PackRecordsXB  ReindexXB
  1321. ~StatHandleXB
  1322. Pack: StatHandlePack    Src: StatHandleXBsrc    Func:   6/System
  1323. Get information on a DOS file handle number to determine if it is a BULLET file
  1324. and if so, if that file is a BULLET key or data file.
  1325. If the returned ID value is 0, the handle is to a BULLET index file. ID=1 then
  1326. the handle is a BULLET .DBF file. ID= -1 then the handle is not a BULLET file.
  1327. See: CreateDXB  StatDXB  StatKXB
  1328. ~GetExtErrorXB
  1329. Pack: XErrorPack        Src: GetExtErrorXBsrc   Func:   7/System
  1330. Get the extended error information for the last operation. This information
  1331. includes the extended error code, the error class, the recommended action, and
  1332. the location of the error. See Errors_DOS for the extended error meaning an
  1333. Errors_DOS_c for the class, action, and locus code meanings.
  1334. Note that on fatal DOS errors, such as an open floppy drive door, the extended
  1335. error code returned is 83 - fail on INT24. This indicates that the INT24
  1336. handler was invoked by DOS and that the INT24 handler told DOS to ignore the
  1337. error. (BULLET invokes its own INT24 handler each time it accesses the DOS file
  1338. system and restores it promptly after the access.) In such cases, this extended
  1339. error code is less informative than the standard return code and, the other
  1340. 'extended' information should be disregarded. (In fatal DOS errors the standard
  1341. return code IS the extended error code.)
  1342. This routine returns the extended error information for the LAST DOS system  
  1343. error. This information remains the same until the next DOS system error.    
  1344. See: CreateDXB  Errors_DOS
  1345. ~DVmonCXB
  1346. Pack: DVmonPack         Src: DVmonCXBsrc        Func:   9/DEBUG
  1347. Control BULLET debug monitor.
  1348. This routine is available only in the debug engine.                          
  1349. The monitor displays in realtime the state of a data file handle, or an index
  1350. and data file handle pair if an index handle is specified. DVmonCXB is best
  1351. used on dual-display systems in which the video output is sent to the secondary
  1352. video monitor. In any case, a 4000-byte screen image is updated in real-time.
  1353. To use the monitor, set mode=1, handle=file to monitor, and VideoSeg=segment
  1354. address of 4000-byte area. The typical VideoSeg would be to video memory. If
  1355. you have a color system as the main monitor and a mono as the secondary, set
  1356. VideoSeg=&HB000. Detail system stats are continually updated to the secondary
  1357. monitor. If you have a single monitor with at least 2 video pages, set VideoSeg
  1358. to your base address plus the page size\16, typically &HB800+(4096\16). If you
  1359. have only a single-page video system, you can allocate a 4000-byte memory area
  1360. and update the video manually by moving it to your video display (80x25).
  1361. See: CreateDXB  StatDXB  StatKXB
  1362. ~CreateDXB
  1363. Pack: CreateDataPack    Src: CreateDXBsrc       Func:  10/Mid-level
  1364. Create a new BULLET .DBF data file. Before using this routine allocate a field
  1365. description array of TYPE FieldDescTYPE for at least as many fields as are in
  1366. the record.
  1367. Conventional dBASE .DBF files have a FileID=3. Other possible FileIDs that you
  1368. may come across are (in hex):
  1369.  43h \__ are special-use Xbase IV DBF files, BULLET can process these file IDs
  1370.  63h /                                    since they are similar to ID type 3
  1371.  83h --- this DBF file has an Xbase III/III+ memo field/file
  1372.  88h --- this DBF file has an Xbase IV memo field/file
  1373. In creating your .DBF files, specify FileID=3 to ensure compatibility across 
  1374. Xbase versions.                                                              
  1375. BULLET makes no special use of the FileID byte.
  1376. See: OpenDXB  FieldDescTYPE  CreateKXB
  1377. ~OpenDXB
  1378. Pack: OpenPack          Src: OpenDXBsrc         Func:  11/Mid-level
  1379. Open an existing .DBF data file for use. You need to specify two things, the
  1380. filename and the DOS file access mode. If the open succeeds, the DOS file
  1381. handle is returned. Use this handle for all further access to this file.
  1382. Each .DBF data file you open allocates 144+((1 + number of fields) * 32) bytes
  1383. for internal use. This memory is not deallocated until you close the file with
  1384. CloseDXB or execute ExitXB.
  1385. You must open the data file before you can open (or create) any of its index
  1386. files.
  1387. See: CloseDXB  OpenKXB
  1388. ~CloseDXB
  1389. Pack: HandlePack        Src: CloseDXBsrc        Func:  12/Mid-level
  1390. Close an existing .DBF data file for use. Closing the file updates the file
  1391. header and deallocates the memory used by this file.
  1392. You MUST close all BULLET files before ending your program or file corruption
  1393. may occur. To ensure that all files are closed in the event of an unscheduled
  1394. program termination, use AtExitXB.                                           
  1395. See: StatDXB  ExitXB  CloseKXB
  1396. ~StatDXB
  1397. Pack: StatDataPack      Src: StatDXBsrc         Func:  13/Mid-level
  1398. Get basic information on the BULLET .DBF data file handle specified.
  1399. Information returned includes the number of records in the file, the record
  1400. length, number of fields per record, and the date the file was last updated.
  1401. Typically, your program will keep track of whether a particular handle belongs
  1402. to a data file or a key file. In cases where this is not possible, call the
  1403. StatHandleXB routine to determine what file type a handle is.
  1404. Note that a just-created data file will have the LastUpdate date set to 0/0/0.
  1405. See: ReadDHXB  StatKXB  StatHandleXB
  1406. ~ReadDHXB
  1407. Pack: HandlePack        Src: ReadDHXBsrc        Func:  14/Mid-level
  1408. Reload the disk copy of the data header for the opened .DBF data file handle
  1409. to the internal copy.
  1410. In single-user, single-tasking systems this routine is not needed. However, in
  1411. a multi-user or multi-tasking system it's possible, and desirable, for two or
  1412. more programs to use the same data file. Consider this scenario: A data file
  1413. has 100 records. Two programs access this data file, both opening it. Program 1
  1414. locks the file, adds a new record, then flushes and unlocks the file. Program 1
  1415. knows that there are now 101 records in the file. However, Program 2 is not
  1416. aware of the changes that Program 1 made--it thinks that there are still 100
  1417. records in the file. This out-of-sync situation is easily remedied by having
  1418. Program 2 reload the data header from the file on disk.
  1419. How does Program 2 know that it needs to reload the header? It doesn't. Instead
  1420. BULLET uses a simple yet effective approach when dealing with such problems.
  1421. Whenever your program locks a file, BULLET automatically reloads the header.
  1422. Whenever you unlock a file, BULLET automatically flushes the header.
  1423. See: FlushDHXB  ReadKHXB  LockXB
  1424. ~FlushDHXB
  1425. Pack: HandlePack        Src: FlushDHXBsrc       Func:  15/Mid-level
  1426. Write the internal copy of the data header for the opened .DBF data file handle
  1427. to disk. The actual write occurs only if the header has been changed.
  1428. This is to ensure that the data header on disk matches exactly the data header
  1429. that is being maintained by BULLET. Also, this routine updates the operating
  1430. system's directory entry for this file.
  1431. Assume the following: A data file with 100 records. Your program opens the data
  1432. file and adds 1 record. Physically, there are 101 records on disk. However, the
  1433. header image of the data file on disk still reads 100 records. This isn't a
  1434. problem, BULLET uses its internal copy of the data header and the internal copy
  1435. does read 101 records. BUT, if there were a system failure now, the disk image
  1436. would not get updated. After the system restart, BULLET opens the file, reads
  1437. the header and thinks that there are 100 records. You lost a record. Now, if
  1438. after that add above, your program issued a FlushDHXB, the header on disk is
  1439. refreshed with the internal copy, keeping the two in-sync. Also, the routine
  1440. updates the DOS directory entry, keeping things neat there as well. Still, it
  1441. doesn't come without cost: flushing will take additional time, therefore, you
  1442. may elect to flush periodically, or whenever the system is idle.
  1443. See: CopyDHXB  ReadDHXB  FlushKHXB  LockXB
  1444. ~CopyDHXB
  1445. Pack: CopyPack          Src: CopyDHXBsrc        Func:  16/Mid-level
  1446. Copy the .DBF file structure of an open data file to another DOS file.
  1447. This routine makes it easy for you to duplicate the structure of an existing
  1448. .DBF file without having to specify all the information needed by CreateDXB.
  1449. The resultant .DBF will be exactly like the source, including number of fields
  1450. and field descriptions. It will contain 0 records.
  1451.      
  1452. See: ZapDHXB  CopyKHXB
  1453. ~ZapDHXB
  1454. Pack: HandlePack        Src: ZapDHXBsrc         Func:  17/Mid-level
  1455. Delete all records for a .DBF data file.
  1456. This routine is similar to CopyDHXB except for one major difference: ALL DATA
  1457. RECORDS IN THE *SOURCE* FILE ARE PHYSICALLY DELETED, so be *careful*.
  1458. If you have a .DBF file with 100 records and use ZapDHXB on it, all 100 records
  1459. will be physically deleted and the file truncated to 0 records. There is no
  1460. return from this routine. All data is gone.
  1461.                            
  1462.                            
  1463. * C A U T I O N *
  1464.                            
  1465.      
  1466. See: CreateKXB  CopyDHXB  ZapKHXB
  1467. ~CreateKXB
  1468. Pack: CreateKeyPack     Src: CreateKXBsrc       Func:  20/Mid-level
  1469. Create a new BULLET key file. Before you can create a key file, you must first
  1470. have opened (and have created if necessary) the BULLET .DBF data file that it
  1471. is to index. (BULLET couples index and data files tightly.)
  1472. To create the key file, you need to provide the key expression, key flags, .DBF
  1473. file link handle, and optionally, the code page ID, country code, and collate
  1474. table.
  1475.                                 Key Expression
  1476. The key expression is an ASCII character string composed of the elements that
  1477. are to make up this index file's key. The key can be composed of any or all of
  1478. the fields in the .DBF data record or sub-strings within any of those fields.
  1479. Two functions are supported in evaluating a key expression. These are SUBSTR()
  1480. and UPPER(). SUBSTR() is similar to BASIC's MID$() in that it extracts part of
  1481. a string starting at a particular position for x number of characters. UPPER()
  1482. is similar to UCASE$() in that it converts all lower-case letters to their
  1483. upper-case equivalent. Since BULLET supports NLS, UPPER() conversion is not
  1484. required for proper sorting of mixed-case text strings.
  1485. See: CreateKXB_a  CreateDXB                                             -MORE-
  1486. ~CreateKXB_a
  1487. All names used in the key expression must be a valid field name in the DBF data
  1488. file. Some sample key expressions given that the .DBF has the following fields:
  1489.  Fields...             Valid key expressions
  1490.      
  1491.  FNAME C 25 0       kx = "LNAME"       (all must be 0-terminated)
  1492.  LNAME C 25 0       kx = "LNAME+FNAME"
  1493.  SSN   C  9 0       kx = "SUBSTR(LNAME,1,4)+SUBSTR(FNAME,1,1)+SUBSTR(SSN,6,4)"
  1494.  DEPT  N  5 0       kx = "UPPER(LNAME+FNAME)"  (for non-NLS index files)
  1495.   :     :           kx = "DEPT+SSN" (N- + C-type is valid for non-binary keys)
  1496.                                     Key Flags
  1497. The key expression is used in conjunction with the key flags to determine the
  1498. type of key generated.
  1499. First, if your index file is to disallow duplicate keys, add 1 to KeyFlag.
  1500. If you have a key composed of a character field(s) or portions thereof, you
  1501. specify a KeyFlag = 2. This instructs BULLET that the sort order is left-to-
  1502. right (proper mixed-case sorting is available, see code page ID).
  1503. See: CreateKXB_b                                                        -MORE-
  1504. ~CreateKXB_b
  1505. If you have a key composed of a numeric field(s) or portions thereof, you can
  1506. also specify a KeyFlag = 2. This instructs BULLET to treat the numeric field
  1507. as a regular character field for sorting. To ensure proper sorting, you must
  1508. decimal-align the +numeric strings in the .DBF data field, i.e., right-justify
  1509. the numeric strings (dBASE .DBF numeric strings are stored as ASCII strings).
  1510. These non-binary numeric fields are just like character fields to BULLET.
  1511. In addition, if you have a key composed of a SINGLE numeric field (fld type N)
  1512. and the field is an integer (NO DECIMAL POINT), you can specify a KeyFlag of 16
  1513. or 32. KeyFlag=16 is for a field known to be in word/integer range; KeyFlag=32
  1514. if the field is known to be in LongInt range. These KeyFlag values instruct
  1515. BULLET to sort the key as a 16/32-bit BINARY value. It also stores the key as a
  1516. 16- or 32-bit value (only 2 or 4 bytes) in the index, eventhough the data field
  1517. is in ASCII (keyflag=16 or 32).
  1518. Although not dBASE compatible, you may use BINARY FIELDS in your data records.
  1519. dBASE always has ASCII data in the data fields, even if the field is numeric.
  1520. For example, an N type field of 8.2 is stored as an ASCII text string in the
  1521. data record, say, a string like " 1100.55". If you want dBASE compatibility
  1522. your field data must also be ASCII. However, if you can forgo this requirement,
  1523. you can use binary values in the fields.
  1524. See: CreateKXB_c                                                        -MORE-
  1525. ~CreateKXB_c
  1526. To do this you must specify a field type of "B" (actually, anything but a "N")
  1527. and, IF IT IS TO BE USED AS A KEY FIELD, also set the 16- or 32-bit KeyFlag.
  1528. Unique and signed may also be flagged. The field length for a "B" field type is
  1529. 2 or 4. Make sure the key flags match (2 if cINTEGER, 4 if cLONG).
  1530. If you specify a binary key flag (for either N or B field types), you must also
  1531. specify whether the field is to be treated as a signed or unsigned value. If
  1532. values less than 0 are possible, add to KeyFlag the hex number &H8000.
  1533.  KeyFlag = cUNIQUE + cCHAR              'unique character key (NLS sort)
  1534.  KeyFlag = cINTEGER + cUNIQUE           'unique unsigned integer (binary sort)
  1535.  KeyFlag = cUNIQUE + cSIGNED + cLONG    'unique signed long
  1536.  KeyFlag = cCHAR                        'character key with duplicates allowed
  1537.  KeyFlag = cCHAR + cINTEGER             'THIS IS AN INVALID KEY FLAGS!
  1538.  KeyFlag = cLONG                        'unsigned long (dups allowed)
  1539. The following values are defined in BULLET.BI (and BULLET.H):
  1540.   cUNIQUE=1, cCHAR=2, cINTEGER=&H10, cLONG=&H20, cNLS=&H4000, cSIGNED=&H8000
  1541. The NLS flag is assigned by BULLET. StatKXB is used to query KeyFlags.
  1542. See: CreateKXB_d                                                        -MORE-
  1543. ~CreateKXB_d
  1544. The key expression you specify may be up to 136 characters, and evaluate out to
  1545. 64 bytes (62 bytes if unique key is not specified). I.e, kx$ = "SUBSTR(..." can
  1546. be up to 136 characters, and that the actual key built from this expression can
  1547. be no longer that 64 bytes, or 62 if you did not specify UNIQUE. In general,
  1548. shorter keys (the key itself, not the expression) offer better performance.
  1549.                          DBF File Link Handle (XBlink)
  1550. Since BULLET evaluates the key expression at CreateKXB, it must have access to
  1551. the DBF file to verify that the key expression is valid. You must therefore
  1552. supply CreateKXB with the OS file handle of the opened DBF data file.
  1553. National Language Support (NLS)
  1554. With DOS 3.3 and later, NLS is available. BULLET uses NLS to build the collate
  1555. sequence table that it uses to ensure proper sorting of mixed-case keys as well
  1556. as the sorting of foreign language alphabets. In order for BULLET to use the
  1557. proper collate table, it must know what code page ID and coutry code to use.
  1558. This table is made part of the index file so that all subsequent access to the
  1559. index file maintains the original sort order, even if the MIS shop is moved to
  1560. another location/computer system using another country code/code page.
  1561. See: CreateKXB_e                                                        -MORE-
  1562. ~CreateKXB_e
  1563.                                 Code Page ID
  1564. To use the default code page ID of the computer in use, specify a code page ID
  1565. of -1. This instructs BULLET to use the collate-sequence table as provided by
  1566. MS-DOS running on the machine. You may also specify the code page ID for BULLET
  1567. to use, but only if support for the code page ID is available on your machine.
  1568. Look in your DOS manual under CUSTOMIZING FOR INTERNATIONAL USE for specific
  1569. code page IDs and country codes. See also the COUNTRY and NLSFUNC commands.
  1570. You may also specify a code page ID = 0 in which case no collate table is used.
  1571.                                 Country Code
  1572. To use the default country code of the computer in use, specify a country code
  1573. of -1. This instructs BULLET to use the collate-sequence table as provided by
  1574. MS-DOS running on the machine. You may also specify the country code for BULLET
  1575. to use, but only if support for the country code is available on your machine.
  1576. Look in your DOS manual under CUSTOMIZING FOR INTERNATIONAL USE for specific
  1577. code page IDs and country codes. See also the COUNTRY and NLSFUNC commands.
  1578. You may also specify a country code = 0 in which case no collate table is used.
  1579. Typically, you set CodePageID = -1, CoutryCode = -1 and CollatePtr = 0.
  1580. See: CreateKXB_f                                                        -MORE-
  1581. ~CreateKXB_f
  1582.                          User-specified Collate Table
  1583. If you are to use a MS-DOS supplied collate table (BOTH codepage ID and country
  1584. codes are non-zero) then you do not need to specify a collate table--DOS will.
  1585. The option to allow a user-specified collate table is to work around some DOS
  1586. versions supplying incorrect collate tables. If you find that the DOS-supplied
  1587. collate table is not valid (it's stored in the second sector of the file) for
  1588. your country, you can supply the table to be used by pointing the CollatePtr
  1589. variables to your in-memory version of a valid collate table. If you want to
  1590. use the DOS-supplied collate table, you MUST set the CollatePtr variables = 0.
  1591. Note: The collate table is a 256-byte table that contains the sort value of
  1592. each character (0-255). For example, the first byte would be 0, second would
  1593. be 1, and so on. Values for characters up to the lower-case letters (ASCII 97)
  1594. are usually as you would expect: "A" has a value of 65. However, the lower-case
  1595. letters have the same value as their upper-case counterparts: "a" also has a
  1596. value of 65. BULLET uses this collate table to ensure proper sorting.
  1597. If you specify EITHER code page ID OR country code = 0 then no collate table
  1598. is used or built. Instead, sorting is done by standard ASCII sort. This is
  1599. somewhat faster but less versatile. Use UPPER() for mixed-case sort if needed.
  1600. See: OpenKXB  CreateKXB
  1601. ~OpenKXB
  1602. Pack: OpenPack          Src: OpenKXBsrc         Func:  21/Mid-level
  1603. Open an existing key file for use.
  1604. Each key file that you open allocates 1264 bytes for internal use. This memory
  1605. is not deallocated until you close the file with CloseKXB or execute ExitXB.
  1606. You must open the data file before you can open its related index file
  1607. because you must supply the handle of the data file that this index files
  1608. indexes.
  1609. See: CloseKXB  OpenDXB
  1610. ~CloseKXB
  1611. Pack: HandlePack        Src: CloseKXBsrc        Func:  22/Mid-level
  1612. Close an open key file. Closing the file updates the file header and
  1613. deallocates the memory used by this file.
  1614. You MUST close all BULLET files before ending your program or file corruption
  1615. may occur. To ensure that all files are closed on the event of an unscheduled
  1616. program termination, use AtExitXB.                                           
  1617. See: StatKXB  ExitXB  CloseDXB
  1618. ~StatKXB
  1619. Pack: StatKeyPack       Src: StatKXBsrc         Func:  23/Mid-level
  1620. Get basic information on a BULLET key file handle specified. Information
  1621. returned includes the number of keys in the file, the key length, the data file
  1622. handle for this key, the last accessed record number of that data file, NLS
  1623. information, and the key flags.
  1624. Typically, your program will keep track of whether a particular handle belongs
  1625. to a key file or a data file. In cases where this is not possible, call the
  1626. StatHandleXB routine to determine what file type a handle is.
  1627. See: ReadKHXB  StatDXB  StatHandleXB
  1628. ~ReadKHXB
  1629. Pack: HandlePack        Src: ReadKHXBsrc        Func:  24/Mid-level
  1630. Reload the disk copy of the key header for the opened key file handle to the
  1631. internal copy.
  1632. In single-user, single-tasking systems this routine is not needed. However, in
  1633. a multi-user or multi-tasking system it's possible, and desirable, for two or
  1634. more programs to use the same data file. Consider this scenario: A key file has
  1635. 100 keys. Two programs access this key file, both opening it. Program 1 locks
  1636. the file, adds a new key, then flushes and unlocks the file. Program 1 knows
  1637. that there are now 101 keys in the file. However, Program 2 is not aware of the
  1638. changes that Program 1 made--it thinks that there are still 100 keys in the
  1639. file. This out-of-sync situation is easily remedied by having Program 2 reload
  1640. the key header from the file on disk.
  1641. How does Program 2 know that it needs to reload the header? It doesn't. Instead
  1642. BULLET uses a simple yet effective approach when dealing with such problems.
  1643. Whenever your program locks a file, BULLET automatically reloads the header.
  1644. Whenever you unlock a file, BULLET automatically flushes the header.
  1645. See: FlushKHXB  ReadDHXB  FlushDHXB  LockXB
  1646. ~FlushKHXB
  1647. Pack: HandlePack        Src: FlushKHXBsrc       Func:  25/Mid-level
  1648. Write the internal copy of the key header for the opened key file handle to
  1649. disk. The actual write occurs only if the header has been changed.
  1650. This is to ensure that the key header on disk matches exactly the key header
  1651. that is being maintained by BULLET. Also, this routine updates the operating
  1652. system's directory entry for this file.
  1653.      
  1654. Assume the following: A data file with 100 keys. Your program opens the key
  1655. file and adds 1 key. Physically, there are 101 keys on disk. However, the
  1656. header image of the data file on disk still reads 100 keys. This isn't a
  1657. problem, BULLET uses its internal copy of the key header and the internal copy
  1658. does read 101 keys. BUT, if there were a system failure now, the disk image
  1659. would not get updated. After the system restart, BULLET opens the file, reads
  1660. the header and thinks that there are 100 keys. You lost a key. Now, if after
  1661. that add above, your program issued a FlushKHXB, the header on disk is
  1662. refreshed with the internal copy, keeping the two in-sync. Also, the routine
  1663. updates the DOS directory entry, keeping things neat there as well. Still, it
  1664. doesn't come without cost: flushing will take additional time, therefore, you
  1665. may elect to flush periodically, or whenever the system is idle.
  1666. See: CopyKHXB  ReadKHXB  FlushDHXB  LockXB
  1667. ~CopyKHXB
  1668. Pack: CopyPack          Src: CopyKHXBsrc        Func:  26/Mid-level
  1669. Copy the key file structure of an open key file to another DOS file.
  1670. This routine makes it easy for you to duplicate the structure of an existing
  1671. key file without having to specify all the information needed by CreateKXB.
  1672. The resultant key file will be exactly like the source, including key flags and
  1673. key expression. It will contain 0 keys.
  1674.      
  1675. See: ZapKHXB  CopyKHXB
  1676. ~ZapKHXB
  1677. Pack: HandlePack        Src: ZapKHXBsrc         Func:  27/Mid-level
  1678. Delete all keys for a key file.
  1679. This routine is similar to CopyKHXB except for one major difference: ALL KEYS
  1680. IN THE *SOURCE* FILE ARE PHYSICALLY DELETED, so be *careful*.
  1681. If you have a key file with 100 keys and use ZapKHXB on it, all 100 keys will
  1682. be physically deleted and the file truncated to 0 keys. There is no return from
  1683. this routine. All data is gone.
  1684.                            
  1685.                            
  1686. * C A U T I O N *
  1687.                            
  1688.      
  1689. See: GetDescriptorXB  CopyKHXB  ZapDHXB
  1690. ~GetDescriptorXB
  1691. Pack: DescriptorPack    Src: GetDescriptorXBsrc Func:  30/Mid-level
  1692. Get the field descriptor information for a field.
  1693. You can specifiy either the fieldname or the field number (position of the
  1694. field within the record where the first field is #1) to get info on.
  1695. The field descriptor contains the following information:
  1696.   FIELDNAME  10 upper-case characters, A-Z and _ allowed, unused space is
  1697.              0-filled and is 0-terminated (11 bytes, ASCII, byte 11 always=0)
  1698.   FIELDTYPE  single ASCII character where C=character, N=numeric, D=date,
  1699.              L=logical, and M=memo field (1 byte, ASCII)
  1700.   FIELDLEN   length of field: C=1-254, N=1-19, D=8 (yyyymmdd), L=1 (T/F/space),
  1701.              M=10, this is total field length (1 byte, binary)
  1702.   FIELDDC    places right of decimal point if N field type, minimum if not 0 is
  1703.              2, can be up to 6 or 8, non-N fields always 0 (1 byte, binary)
  1704. See: GetRecordXB
  1705. ~GetRecordXB
  1706. Pack: AccessPack        Src: GetRecordXBsrc     Func:  31/Mid-level
  1707. Get the physical record from the data file into a data buffer by record number.
  1708. The data buffer is typically a TYPEd variable defined as the .DBF record itself
  1709. is defined. For example, if the DBF record has 2 fields, LNAME and FNAME, then
  1710. variable would be TYPEd as:
  1711.   TYPE RecBuffer
  1712.   tag AS STRING * 1             'the Xbase DBF delete flag (must be included)
  1713.   LastName AS STRING * 25       'same field length as the .DBF LNAME field
  1714.   FirstName AS STRING * 25      'same field length as the .DBF FNAME field
  1715.   END TYPE
  1716. This method of accessing the data file does not use any indexing. Therefore, it
  1717. typically is not used except for special purposes. The preferred method to
  1718. access the data is by one of the keyed Get() routines.
  1719. See: AddRecordXB  GetEqualXB
  1720. ~AddRecordXB
  1721. Pack: AccessPack        Src: AddRecordXBsrc     Func:  32/Mid-level
  1722. Append the record in the data buffer to the end of the DBF file.
  1723. This method of adding a record does not involve any indexing. It is typically
  1724. used to build a data file en masse and do the indexing after the entire .DBF 
  1725. file(s) has been built.                                                      
  1726. If you have several thousand data records to be added at once, this method of
  1727. building the DBF first and then using the ReindexXB routine is often faster
  1728. than using the InsertXB routine for each record to add.
  1729. The AddRecordXB is very fast. 400 recs/sec on an AT machine is typical. Over
  1730. 2000 recs/sec can be added on a fast 486 machine--that's 120,000 records added
  1731. per minute.
  1732. The record number used is determined by BULLET and it is returned in AP.RecNo.
  1733. See: UpdateRecordXB  InsertXB  ReindexXB
  1734. ~UpdateRecordXB
  1735. Pack: AccessPack        Src: UpdateRecordXBsrc  Func:  33/Mid-level
  1736. Write the updated data record to the the physical record number.
  1737. This method of writing the updated record must not be used if any field(s) in
  1738. the record is used as a key field(s) and has been changed.                   
  1739. This method of updating a record is very fast if you know that that update is
  1740. not going to alter any field used as a key in any index file that uses it. You
  1741. must, of course, first get the data record into the record buffer. Then you can
  1742. change it and write the update out to disk with this routine.
  1743. If you need to change a field(s) that is used as a key field or part of one,
  1744. use the UpdateXB routine. UpdateXB not only dynamically updates all related
  1745. index files if you change a key field, it also will undo any and all changes if
  1746. an error occurs in the transaction.
  1747. See: DeleteRecordXB  GetRecordXB  UpdateXB
  1748. ~DeleteRecordXB
  1749. Pack: AccessPack        Src: DeleteRecordXBsrc  Func:  34/Mid-level
  1750. Tag the record at the physical record number as being deleted.
  1751. This does not tag any in-memory copies of the record so be sure to mark any
  1752. such copies as being deleted yourself.                                     
  1753. The first byte of every .DBF record is reserved for the delete tag. This tag
  1754. is a space (ASCII 32) if the record is normal, or a * (ASCII 42) if it's marked
  1755. as being deleted. This delete tag is a reserved field in the DBF record and as
  1756. such is not defined as a formal field with a descriptor, etc. Make sure that
  1757. you define your in-memory buffers to reserve the first byte for the delete tag.
  1758. The Xbase DBF standard doesn't physically remove records marked as deleted from
  1759. the data file. It doesn't mark them as available/reusable either. To physically
  1760. remove records marked as deleted use PackRecordsXB.
  1761. Records can be temporarily marked as deleted then recalled to normal status.
  1762. The Key/Get routines (GetFirstXB, etc.) return the record number needed for
  1763. this routine after each access in AP.RecNo.
  1764. See: UndeleteRecordXB  PackRecordsXB
  1765. ~UndeleteRecordXB
  1766. Pack: AccessPack        Src: UndeleteRecordsrc  Func:  35/Mid-level
  1767. Tag the record at the physical record number as being normal (not deleted).
  1768. This does not tag any in-memory copies of the record so be sure to mark any
  1769. such copies as being normal yourself.                                      
  1770. The first byte of every .DBF record is reserved for the delete tag. This tag
  1771. is a space (ASCII 32) if the record is normal, or a * (ASCII 42) if it's marked
  1772. as being deleted. This delete tag is a reserved field in the DBF record and as
  1773. such is not defined as a formal field with a descriptor, etc. Make sure that
  1774. you define your in-memory buffers to reserve the first byte for the delete tag.
  1775. The Xbase DBF standard does not physically remove records marked as deleted
  1776. from the data file so you can "recall" then back to normal status as easily as
  1777. you marked them deleted.
  1778. See: PackRecordsXB  DeleteRecordXB
  1779. ~PackRecordsXB
  1780. Pack: AccessPack        Src: PackRecordsXBsrc   Func:  36/Mid-level
  1781. Rebuild the open DBF file by physically removing all records marked as deleted.
  1782. Packing occurs in place using the existing file. It's recommended that you   
  1783. use BackupFileXB to copy the current DBF file before using this routine in   
  1784. case of a failure during the pack process.                                   
  1785. The newly packed file is truncated to reflect the current, actual size.
  1786. If there are index files for this .DBF file, they MUST all be reindexed after
  1787. the pack process by using ReindexXB.
  1788. This routine dynamically allocates at least as many bytes as the length of   
  1789. the record. More if available.                                               
  1790. See: FirstKeyXB  DeleteRecordXB  BackupFileXB  ReindexXB
  1791. ~FirstKeyXB
  1792. Pack: AccessPack        Src: FirstKeyXBsrc      Func:  40/Mid-level
  1793. Retrieve the first key in index order from the index file.
  1794. This routine does not access the .DBF file and so does not retrieve the data 
  1795. record. What it does do is locate the first key of the index, returning it,  
  1796. and also returning the record number within the .DBF that the key indexes.   
  1797. To retrieve the data record you can use the GetRecordXB routine. The preferred
  1798. method, however, is to use the GetFirstXB.
  1799. The key returned includes an enumerator if a non-unique index file is involved.
  1800. The enumerator is a little-endian 16-bit value that serves to differentiate  
  1801. up to 65535 "identical", non-unique keys. It is attached to all keys of non- 
  1802. unique index files and occupies the last two bytes of the key.               
  1803. This routine is typically used to position the index file to the first key so
  1804. as to allow forward in-order access to the keys by using NextKeyXB.
  1805. See: EqualKeyXB  GetFirstXB  GetRecordXB
  1806. ~EqualKeyXB
  1807. Pack: AccessPack        Src: EqualKeyXBsrc      Func:  41/Mid-level
  1808. Search for the exact key in the index file.
  1809. This routine does not access the .DBF file and so does not retrieve the data 
  1810. record. What it does do is search for the key in the index, and if found,    
  1811. returns the record number within the .DBF that the key indexes. The key must 
  1812. be an exact match, including enumerator word if a non-unqiue index file.     
  1813. To retrieve the data record you can use the GetRecordXB routine. The preferred
  1814. method, however, is to use the GetEqualXB.
  1815. This routine will only find EXACT matches to the specified key (including the
  1816. enumerator if applicable). However, even if the exact key is not found in the
  1817. index file, the index file is positioned so that the next NextKeyXB retrieves
  1818. the key that would have followed the unmatched specified key. For example,
  1819. if the key to match was "KINGS" (a partial key in this case), EqualKeyXB would
  1820. return a key not found error. If you were to now do a NextKeyXB, the next key
  1821. would be returned, let's say it is "KINGSTON".  If index file is not unique,
  1822. you must append the enumerator bytes (\0\0 for the first, \0\1 next, ...).
  1823. See: NextKeyXB  GetEqualXB  GetRecordXB
  1824. ~NextKeyXB
  1825. Pack: AccessPack        Src: NextKeyXBsrc       Func:  42/Mid-level
  1826. Retrieve the next key in index order from the index file.
  1827. This routine does not access the .DBF file and so does not retrieve the data 
  1828. record. What it does do is retreive the next key of the index, returning it, 
  1829. and also returning the record number within the .DBF that the key indexes.   
  1830. To retrieve the data record you can use the GetRecordXB routine. The preferred
  1831. method, however, is to use the GetNextXB.
  1832. The key returned includes an enumerator if a non-unique index file is involved.
  1833. This routine is typically called after the index file has first been positioned
  1834. to a known key using either FirstKeyXB or EqualKeyXB, or after a previous
  1835. NextKeyXB or even PrevKeyXB. What it basically does is get the key following
  1836. the current key, and then make that key the new current key.
  1837. See: PrevKeyXB  GetNextXB  GetRecordXB
  1838. ~PrevKeyXB
  1839. Pack: AccessPack        Src: PrevKeyXBsrc       Func:  43/Mid-level
  1840. Retrieve the previous key in index order from the index file.
  1841. This routine does not access the .DBF file and so does not retrieve the data 
  1842. record. What it does do is retreive the previous key of the index, returning 
  1843. it and also returning the record number within the .DBF that the key indexes.
  1844. To retrieve the data record you can use the GetRecordXB routine. The preferred
  1845. method, however, is to use the GetPrevXB.
  1846. The key returned includes an enumerator if a non-unique index file is involved.
  1847. This routine is typically called after the index file has first been positioned
  1848. to a known key using either LastKeyXB or EqualKeyXB, or after a previous
  1849. PrevKeyXB or even NextKeyXB. What it basically does is to get the key previous
  1850. the current key, and then make that key the new current key.
  1851. See: LastKeyXB  GetPrevXB  GetRecordXB
  1852. ~LastKeyXB
  1853. Pack: AccessPack        Src: LastKeyXBsrc       Func:  44/Mid-level
  1854. Retrieve the last key in index order from the index file.
  1855. This routine does not access the .DBF file and so does not retrieve the data 
  1856. record. What it does do is locate the last key of the index, returning it,   
  1857. and also returning the record number within the .DBF that the key indexes.   
  1858. To retrieve the data record you can use the GetRecordXB routine. The preferred
  1859. method, however, is to use the GetLastXB.
  1860. This routine is typically used to position the index file to the last key so as
  1861. to allow reverse in-order access to the keys by using PrevKeyXB.
  1862. See: StoreKeyXB  GetLastXB  GetRecordXB
  1863. ~StoreKeyXB
  1864. Pack: AccessPack        Src: StoreKeyXBsrc      Func:  45/Mid-level
  1865. Insert the key into the index file in proper key order.
  1866. This routine does not add the data record to the .DBF file. It only inserts  
  1867. the key and record number into the index file. Use InsertXB, instead.        
  1868. To do a complete data record and key insert, you could use AddRecordXB to add
  1869. the data record to the .DBF, BuildKeyXB to construct the key, then StoreKeyXB
  1870. to insert the key and record number information into the index file. If that
  1871. key already exists and the file allows duplicate keys, you need to attach the
  1872. proper enumerator word and retry StoreKeyXB.
  1873. This is much too much to do. Instead, just use InsertXB. All these details
  1874. including adding the data record and multi-key inserts are performed
  1875. automatically with just the single call.
  1876. See: DeleteKeyXB  InsertXB
  1877. ~DeleteKeyXB
  1878. Pack: AccessPack        Src: DeleteKeyXBsrc     Func:  46/Mid-level
  1879. Physically remove the specified key from the index file.
  1880. This routine requires an EXACT key match for all bytes of the key, including 
  1881. the enumerator word if a non-unique index file is involved.                  
  1882. This routine would seldom be used, typically, since deleted dBASE data records
  1883. are only physically deleted during a PackRecordsXB and the index file is
  1884. rebuilt afterward using ReindexXB.
  1885. See: BuildKeyXB  CurrentKeyXB
  1886. ~BuildKeyXB
  1887. Pack: AccessPack        Src: BuildKeyXBsrc      Func:  47/Mid-level
  1888. Build the key for the specifed data record based on the key expression for the
  1889. index file. If the index file is non-unique, a 0-value enumerator is attached.
  1890. The enumerator is a little-endian 16-bit value that serves to differentiate  
  1891. up to 65535 "identical", non-unique keys. It is attached to all keys of non- 
  1892. unique index files and occupies the last two bytes of the key.               
  1893. This routine, like most of the mid-level routines, typically would not be used
  1894. since the high-level access routines take care of this detail automatically.
  1895. Note: Little-endian in Bullet means that bit-order is from high to low.
  1896. Sometimes called Motorola format.  The first byte is of higher order than
  1897. the second, so \0\0 precedes \0\1 (then \0\2... \1\0, \1\1, \1\2, (so on)).
  1898. See: CurrentKeyXB  StoreKeyXB
  1899. ~CurrentKeyXB
  1900. Pack: AccessPack        Src: CurrentKeyXBsrc    Func:  48/Mid-level
  1901. Retrieve the current key value for the specified key file handle and also the
  1902. data record number that it indexes.
  1903. This routine is useful in that it retrieves on demand the actual key value of
  1904. the last accessed key in the index file (and the data record number). Most
  1905. often you don't need this information so it would be a waste of time and space
  1906. for your program to explicitly track each current key for each index file that
  1907. you have open.
  1908. See: GetFirstXB  ReindexXB  DeleteKeyXB
  1909. ~GetFirstXB
  1910. Pack: AccessPack        Src: GetFirstXBsrc      Func:  60/High-level
  1911. Retrieve the first indexed key and data record.
  1912. The key returned includes an enumerator if a non-unique index file is involved.
  1913. This routine is typically used to process a database in index order starting at
  1914. the first ordered key (and its data record). After processing this first entry,
  1915. subsequent in-order access of the database is achieved by using GetNextXB until
  1916. the end of the database is reached.
  1917. This routine, like all the high-level Get routines, fills in the AP.RecNo of
  1918. the record accessed. In GetFirstXB's case, it fills AP.RecNo with the record
  1919. number pointed to by the first key. Since this is so, the AP pack is primed for
  1920. an UpdateXB after each high-level Get. Other methods to get the record number
  1921. are to use CurrKeyXB or any of the Key routines (KeyFirstXB, etc.).
  1922. See: GetEqualXB  FirstKeyXB  UpdateXB
  1923. ~GetEqualXB
  1924. Pack: AccessPack        Src: GetEqualXBsrc      Func:  61/High-level
  1925. Search for the exact key in the index file and return its data record.
  1926. This routine will only find EXACT matches to the specified key (including the
  1927. enumerator if applicable). However, even if the exact key is not found in the
  1928. index file, the index file is positioned so that the next GetNextXB retrieves
  1929. the key that would have followed the unmatched specified key. For example,
  1930. if the key to match was "KINGS" (a partial key in this case), GetEqualXB would
  1931. return a key not found error. If you were to now do a GetNextXB, the next key
  1932. and data record would be returned, let's say the key is "KINGSTON" and its data
  1933. record is the data record for that key. Another GetNextXB would retrieve the
  1934. key and record after that. (GetPrevXB can be used in this fashion too.)
  1935. This routine, like all the high-level Get routines, fills in the AP.RecNo of
  1936. the record accessed. In GetEqualXB's case, it fills AP.RecNo with the record
  1937. number pointed to by the matched key. Since this is so, the AP pack is primed
  1938. for an UpdateXB after each high-level Get. Other methods to get the record
  1939. number are to use CurrKeyXB or any of the Key routines (KeyEqualXB, etc.).
  1940. See: GetNextXB  EqualKeyXB
  1941. ~GetNextXB
  1942. Pack: AccessPack        Src: GetNextXBsrc       Func:  62/High-level
  1943. Retrieve the next indexed key and its data record.
  1944. The key returned includes an enumerator if a non-unique index file is involved.
  1945. This routine is typically calld after the index file has first been positioned
  1946. to a known key using either GetFirstXB or GetEqualXB, or after a previous
  1947. GetNextXB or even GetPrevXB. What it basically does is get the key and data
  1948. record following the current key, and then make that key the new current key.
  1949. This routine, like all the high-level Get routines, fills in the AP.RecNo of
  1950. the record accessed. In GetNextXB's case, it fills AP.RecNo with the record
  1951. number pointed to by the next key. Since this is so, the AP pack is primed for
  1952. an UpdateXB after each high-level Get. Other methods to get the record number
  1953. are to use CurrKeyXB or any of the Key routines (KeyNextXB, etc.).
  1954. See: GetPrevXB  NextKeyXB
  1955. ~GetPrevXB
  1956. Pack: AccessPack        Src: GetPrevXBsrc       Func:  63/High-level
  1957. Retrieve the previous indexed key and record.
  1958. The key returned includes an enumerator if a non-unique index file is involved.
  1959. This routine is typically called after the index file has first been positioned
  1960. to a known key using either GetLastXB or GetEqualXB, or after a previous
  1961. GetPrevXB or even GetNextXB. What it basically does is to get the key and data
  1962. record previous the current key, and then make that key the new current key.
  1963. This routine, like all the high-level Get routines, fills in the AP.RecNo of
  1964. the record accessed. In GetPrevXB's case, it fills AP.RecNo with the record
  1965. number pointed to by the previous key. Since this is so, the AP pack is primed
  1966. for an UpdateXB after each high-level Get. Other methods to get the record
  1967. number are to use CurrKeyXB or any of the Key routines (KeyPrevXB, etc.).
  1968. See: GetLastXB  PrevKeyXB
  1969. ~GetLastXB
  1970. Pack: AccessPack        Src: GetLastXBsrc       Func:  64/High-level
  1971. Retrieve the last indexed key and record.
  1972. This routine is typically used to process a database in reverse index order
  1973. starting at the last ordered key (and its data record). After processing this
  1974. last entry, subsequent reverse-order access of the database is achieved by
  1975. using GetPrevXB until the top of the database is reached.
  1976. This routine, like all the high-level Get routines, fills in the AP.RecNo of
  1977. the record accessed. In GetLastXB's case, it fills AP.RecNo with the record
  1978. number pointed to by the last key. Since this is so, the AP pack is primed for
  1979. an UpdateXB after each high-level Get. Other methods to get the record number
  1980. are to use CurrKeyXB or any of the Key routines (KeyLastXB, etc.).
  1981. See: InsertXB  LastKeyXB
  1982. ~InsertXB
  1983. Pack: AccessPack        Src: InsertXBsrc        Func:  65/High-level
  1984. Add the data record to data file and insert the related key(s) into the linked
  1985. index file(s).
  1986. This routine is used to add new entries into a database, one at a time. The
  1987. data record is first added to the data file, then for each related index file,
  1988. a key is inserted into the appropriate index file. Up to 32 index files can be
  1989. automatically maintained for each data file.
  1990. This and several other routines are transaction-based. If a failure occurs
  1991. prior to the routine's completion, all changes made to the database by the
  1992. routine will be backed-out and the database (data and related index file(s))
  1993. effectively restored to its original state.
  1994.                                   
  1995. If the routine failed to complete, the function return value is the number of
  1996. the pack that caused the failure. The pack's Stat is checked to determine the
  1997. error code. If the function return value is 0, YOU MUST STILL check the first
  1998. pack's Stat. If it's non-zero, then the failure occured with the data record.
  1999. See: UpdateXB  StoreKeyXB
  2000. ~UpdateXB
  2001. Pack: AccessPack        Src: UpdateXBsrc        Func:  66/High-level
  2002. Modify an existing data record (identified by record number) and automatically
  2003. perform any index file updates needed to keep the index file(s) in sync.
  2004. If any key fields changed between the original record and the new one, this
  2005. routine updates the appropriate index file(s) by replacing the original key(s)
  2006. with new the key(s) based on the updated data record. Up to 32 index files can
  2007. be automatically maintained for each data file. Get routines (GetFirstXB, etc.)
  2008. set the AP.RecNo of the record that UpdateXB uses.
  2009. This and several other routines are transaction-based. If a failure occurs
  2010. prior to the routine's completion, all changes made to the database by the
  2011. routine will be backed-out and the database (data and related index file(s))
  2012. effectively restored to its original state.
  2013. If the routine failed to complete, the function return value is the number of
  2014. the pack that caused the failure. The pack's Stat is checked to determine the
  2015. error code. If the function return value is 0, YOU MUST STILL check the first
  2016. pack's Stat. If it's non-zero, then the failure occured with the data record.
  2017. See: ReindexXB  UpdateRecordXB
  2018. ~ReindexXB
  2019. Pack: AccessPack        Src: ReindexXBsrc       Func:  67/High-level
  2020. Reindex all related index files for a data file.
  2021. The index file(s) must already exist and be open. Any existing key data is
  2022. overwritten by the new key data. In other words, if you have a 10MByte index
  2023. file, ReindexXB uses the same file space building the news keys over the old.
  2024. This results in a less fragmented disk and also minimizes disk space needed.
  2025. You can also create a new, empty index file and reindex to that. This would be
  2026. useful, for instance, if you needed to create a temporary index file--something
  2027. that you'd use for a report, say, then delete after the report.
  2028. This routine creates a TEMPORARY work file in either the current directory or,
  2029. if the DOS environment variable TMP is defined, in the TMP= directory. The size
  2030. of this file is approx. bytes = (RECORDS * (KEYLEN+6)). ReindexXB can operate
  2031. in as little as 32K of available memory and can use up to 128K. The resultant
  2032. index file(s) are optimized for minimum size AND maximum retrieval speed.
  2033. If the routine failed to complete, the function return value is the number of
  2034. the pack that caused the failure. The pack's Stat is checked to determine the
  2035. error code. A return value of zero indicates no error occured.               
  2036. See: LockXB  PackRecordsXB
  2037. ~LockXB
  2038. Pack: AccessPack        Src: LockXBsrc          Func:  80/Network
  2039. Lock all bytes in the index file handle(s) for exclusive use by the current
  2040. process and reload the index file header(s) from disk. Also lock all bytes in
  2041. the related data file and reload the data file header from disk.
  2042. The files must have been opened with the appropriate share attribute and not 
  2043. in compatibility mode. SHARE.EXE MUST be installed or DOS error 1 is issued. 
  2044. This routine is transaction-based and will lock all index files specified in 
  2045. AccessPack and the data file. If any lock fails, all previous locks by this  
  2046. routine are released. The return value indicates which access pack failed, if
  2047. any. This value is used as the index into the AccessPack group for you to    
  2048. identify the error code. See LockXBsrc for determining this exactly.         
  2049. Use the DriveRemoteXB and/or FileRemoteXB to determine if locking is necessary.
  2050. If the files are on a remote drive then it is best to use locking. Locking may
  2051. also be necessary on multitasking local machines accessing shared files.
  2052. This routine is a combination of LockKeyXB and LockDataXB.
  2053. See: UnlockXB  LockKeyXB  LockDataXB  DriveRemoteXB  FileRemoteXB
  2054. ~UnlockXB
  2055. Pack: AccessPack        Src: UnlockXBsrc        Func:  81/Network
  2056. Unlock all bytes in the specified file handle(s) (previously locked) and flush
  2057. the file header(s) to disk (flush done before lock(s) released). Also unlock
  2058. all bytes in the related data file and flush the data file header to disk.
  2059. The files must have been opened with the appropriate share attribute and not 
  2060. in compatibility mode. SHARE.EXE MUST be installed or DOS error 1 is issued. 
  2061. This routine is transaction-based and will unlock all index files specified in
  2062. AccessPack and the data file. If an unlock fails the routine exits with a
  2063. return value indicating which access pack failed. This value is used as the
  2064. index into the AccessPack group for you to identify the error code. Note that
  2065. this routine does not attempt to re-lock those files unlocked successfully if
  2066. an error occurs in the transaction. If an error does occur (unlikely) you will
  2067. need to provide for unlocking the remaining files manually with the UnlockKeyXB
  2068. and UnlockDataXB routines. You should not rely on the operating system to
  2069. automatically unlock files when they're closed.
  2070. This routine is a combination of UnlockKeyXB and UnlockDataXB.
  2071. See: LockKeyXB  UnlockKeyXB  UnlockDataXB
  2072. ~LockKeyXB
  2073. Pack: AccessPack        Src: LockKeyXBsrc       Func:  82/Network
  2074. Lock all bytes in the index file handle(s) for exclusive use by the current
  2075. process and reload the index file header(s) from disk.
  2076. The files must have been opened with the appropriate share attribute and not 
  2077. in compatibility mode. SHARE.EXE MUST be installed or DOS error 1 is issued. 
  2078. This routine is transaction-based and will lock all index files specified in
  2079. AccessPack. If any lock fails, all previous locks by this routine are released.
  2080. The return value indicates which access pack failed, if any. This value is used
  2081. as the index into the AccessPack group for you to identify the error code.
  2082. The advantage of using region locks (LockKeyXB locks the entire file region) to
  2083. control file access is that the file does not need to be opened/closed using
  2084. the Deny Read/Write sharing attribute. Opening the file for Deny None, and
  2085. controlling subsequent access with region locks, allows for faster processing
  2086. since files do not need to be constantly opened and closed, as they would if
  2087. access were controlled by opening with Deny Read/Write.
  2088. See: UnlockKeyXB  LockXB
  2089. ~UnlockKeyXB
  2090. Pack: AccessPack        Src: UnlockKeyXBsrc     Func:  83/Network
  2091. Unlock all bytes in the specified file handle(s) (previously locked) and flush
  2092. the file header(s) to disk (flush done before lock(s) released).
  2093. The files must have been opened with the appropriate share attribute and not 
  2094. in compatibility mode. SHARE.EXE MUST be installed or DOS error 1 is issued. 
  2095. This routine is transaction-based and will unlock all index files specified in
  2096. AccessPack. If an unlock fails the routine exits with a return value indicating
  2097. which access pack failed. This value is used as the index into the AccessPack
  2098. group for you to identify the error code.
  2099. All file locks should be released when exclusive access in no longer needed. 
  2100. It is not recommended that you end your program without having released active
  2101. file locks. This is especially a valid concern for DOS versions prior to 5.0.
  2102. DOS 5 releases locks on files that are closed.
  2103. See: LockDataXB  UnlockXB
  2104. ~LockDataXB
  2105. Pack: AccessPack        Src: LockDataXBsrc      Func:  84/Network
  2106. Lock all bytes in the file handle's data file for exclusive use by the current
  2107. process and reload the data file header from disk. You must set AP.RecNo=0 to
  2108. do this. To lock a single record, set AP.RecNo=record# to lock.
  2109. The files must have been opened with the appropriate share attribute and not 
  2110. in compatibility mode. SHARE.EXE MUST be installed or DOS error 1 is issued. 
  2111. This routine locks the specified data file. If the handle specified is that of
  2112. an index file, that index file's related data file handle is used. For single-
  2113. record locks, AP.Handle must have a data file handle specified. Header loading
  2114. is not performed if locking a single record.
  2115. The advantage of using region locks (LockDataXB locks the entire file region)
  2116. to control file access is that the file does not need to be opened/closed using
  2117. the Deny Read/Write sharing attribute. Opening the file for Deny None, and
  2118. controlling subsequent access with region locks, allows for faster processing
  2119. since files do not need to be constantly opened and closed, as they would if
  2120. access were controlled by opening with Deny Read/Write.
  2121. See: UnlockDataXB
  2122. ~UnlockDataXB
  2123. Pack: AccessPack        Src: UnlockDataXBsrc    Func:  85/Network
  2124. Unlock all bytes in the specified file handle (previously locked) and flush the
  2125. data file header to disk (flush done before lock released). To do this you must
  2126. set AP.RecNo=0. To unlock a single record, set AP.RecNo=record# to unlock.
  2127. The files must have been opened with the appropriate share attribute and not 
  2128. in compatibility mode. SHARE.EXE MUST be installed or DOS error 1 is issued. 
  2129. This routine unlocks the specified data file. If the handle specified is that
  2130. of an index file that index file's related datafile handle is used. For single-
  2131. record unlocks, AP.Handle must have a data file handle specified. Flushing is
  2132. not performed if unlocking a single record.
  2133. All file locks should be released when exclusive access in no longer needed. 
  2134. It is not recommended that you end your program without having released active
  2135. file locks. This is especially a valid concern for DOS versions prior to 5.0.
  2136. DOS 5 releases locks on files that are closed.
  2137. See: DriveRemoteXB
  2138. ~DriveRemoteXB
  2139. Pack: RemotePack        Src: DriveRemoteXBsrc   Func:  86/Network
  2140. Determine if specified drive is remote (default drive=0, A:=1, B=2, C=3...).
  2141. This routine uses INT21/44/sub function 09.
  2142. In addition to returning the IsRemote state, this routine sends back the result
  2143. of the DX register and also the install state of SHARE.EXE.
  2144. The meaning of the bitflags in Flags are (where IsRemote=0):
  2145. Bit   Meaning drive...
  2146.  1   1=uses 32-bit sectoring
  2147.  6   1=accepts Generic IOCTL (for INT21/44/0D,0E,0Fh)
  2148.  7   1=accepts Query IOCTL Device (INT21/44/11h)
  2149.  9   1=is local but shared by other computers in the network
  2150. 11   1=accepts Does-Device-Use-Removable-Media (INT21/44/08)
  2151. 13   1=requires media descriptor in FAT
  2152. 14   1=accepts Receive/Send Control Data from Block Device (INT21/44/04,05)
  2153. 15   1=is Substitution drive (set by the DOS SUBST command)
  2154.      (all other bits=0)
  2155. See: FileRemoteXB  LockXB
  2156. ~FileRemoteXB
  2157. Pack: RemotePack        Src: FileRemoteXBsrc    Func:  87/Network
  2158. Determine if specified handle of file or device is remote.
  2159. This routine uses INT21/44/sub function 0Ah.
  2160. In addition to returning the IsRemote state, this routine sends back the result
  2161. of the DX register and also the install state of SHARE.EXE.
  2162. Flags bit 7=1 then handle is device, =0 then handle is file.
  2163. Bit   Meaning DEVICE...                 Bit   Meaning DEVICE...(cont)
  2164.  0   1=is console input device          13   1=is named pipe
  2165.  1   1=is console output device         15   1=is remote, 0=is local
  2166.  2   1=is null device                        (all other bits=0)
  2167.  3   1=is clock device                  Bit   Meaning FILE...
  2168.  4   1=is special device               0-5   xxxxxx=drive number (0=A...)
  2169.  5   1=is in binary mode, 0=in ASCII     6   1=has not been written to
  2170.  6   0=returns EOF if device is read    12   1=is NoInherit
  2171. 11   1=is network spooler               14   1=date/time not set at close
  2172. 12   1=is NoInherit                     15   1=is remote, 0=is local
  2173.                                              (all other bits=0)
  2174. See: SetRetriesXB  DriveRemoteXB  LockXB
  2175. ~SetRetriesXB
  2176. Pack: SetRetriesPack    Src: SetRetriesXBsrc    Func:  88/Network
  2177. Set the number of times DOS retries disk operations after a failure due to
  2178. file-sharing operations (locked file regions from LockXB routines).
  2179. This routine uses INT21/44/sub function 0Bh.
  2180. By default DOS retries an operation 3 times (without pausing between attempts)
  2181. before returning an error to the application.
  2182. If you change the default values it's recommended that the default state be  
  2183. restored before your application ends (Retries=3, Pause=1).                  
  2184. These values are pretty much determined by trial-and-error. You may find that
  2185. adding a delay between retries returns fewer access-denied errors, but on
  2186. current machines, the delay is in the few millisecond range, tops.
  2187. See: DeleteFileDOS  LockXB
  2188. ~DeleteFileDOS
  2189. Pack: DOSFilePack       Src: DeleteFileDOSsrc   Func: 100/DOS
  2190. Delete the specified file.
  2191. This routine uses DOS INT21/41 (interrupt 21h function 41h).
  2192. See: RenameFileDOS
  2193. ~RenameFileDOS
  2194. Pack: DOSFilePack       Src: RenameFileDOSsrc   Func: 101/DOS
  2195. Rename a file. May also be used to move the file to a new directory within the
  2196. partition.
  2197. This routine uses DOS INT21/56.
  2198. If the specified directory differs from the file's directory, the file's     
  2199. directory entry is moved to the new directory.                               
  2200. For example, if the FilenamePtr filename is C:\LP100\PROJ93A.INF and the
  2201. NewFilenamePtr filename is C:\ARCH\PROJ93A.INA, the file is essentially
  2202. renamed and also moved to the \ARCH directory.
  2203. See: CreateFileDOS
  2204. ~CreateFileDOS
  2205. Pack: DOSFilePack       Src: CreateFileDOSsrc   Func: 102/DOS
  2206. Create a new file.
  2207. This routine uses INT21/3C.
  2208. The specified filename/pathname must NOT already exist.
  2209. The file created is not left open. You must OpenFileDOS to use it.
  2210. The attribute used during the create can be:
  2211.   ATTRIBUTE       VALUE    MEANING
  2212.    Normal              0    normal access permitted to file
  2213.    Read-Only           1    read-only access permitted to file
  2214.    Hidden              2    file does not appear in directory listing
  2215.    System              4    file is a system file
  2216.    Volume              8    FILENAME used as volume label if no current label
  2217.    Archive            20h   file is marked for archiving
  2218. See: AccessFileDOS  OpenFileDOS
  2219. ~AccessFileDOS
  2220. Pack: DOSFilePack       Src: AccessFileDOSsrc   Func: 103/DOS
  2221. Determine if the specified file can be accessed with the specified
  2222. access/sharing mode.
  2223. This routine uses INT21/3D and INT21/3E.
  2224. Basically, a Does-File-Exist routine. It uses the specified access/sharing
  2225. attributes when trying to open the file. For example, if you specify
  2226. DFP.Attr = &H42 (R/W access + Deny None sharing) and use AccessFileDOS on a
  2227. Read-Only DOS file, the return value would be DOS error 5, Access Denied.
  2228. See: OpenFileDOS
  2229. ~OpenFileDOS
  2230. Pack: DOSFilePack       Src: OpenFileDOSsrc     Func: 104/DOS
  2231. Open the specified file with the specified access/sharing mode.
  2232. This routine uses INT21/3D.
  2233.   ACCESS          VALUE    MEANING
  2234.    Read-only           0    open for read-only access
  2235.    Write-only          1    open for write-only access
  2236.    Read/Write          2    open for read/write access
  2237.   SHARE
  2238.    Compatibility       0     any process may share file (not recommended)
  2239.    Deny Read/Write    10h    no other process may share file
  2240.    Deny Write         20h    no other process may share file for write
  2241.    Deny Read          30h    no other process may share file for read
  2242.    Deny None          40h    any process may share file except in Compatibilty
  2243.   INHERIT                                                                 mode
  2244.    NoInheritFlag      80h    if set child processes do not inherit file handles
  2245.                              (child process cannot inherit handle > 20)
  2246. The file access mode is a combination of ACCESS + SHARE + INHERIT.
  2247. See: SeekFileDOS  OpenPack
  2248. ~SeekFileDOS
  2249. Pack: DOSFilePack       Src: SeekFileDOSsrc     Func: 105/DOS
  2250. Position the DOS file pointer of the specified file to the specified position.
  2251. This routine uses INT21/42.
  2252. The position is a 32-bit value and is relative to either the start of the file,
  2253. the current file pointer position, or the end of the file.
  2254.  Method  Meaning
  2255.     0    start move from the start of file (offset is a 32-bit unsigned value)
  2256.     1    start move at the current position (offset a signed value)
  2257.     2    start move at the end of file (offset a signed value)
  2258. For example, to move to the 511th byte of a file (byte 0 being the first), set
  2259. the offset value to 511 and use Method 0. On return, the absolute offset value
  2260. of the new position is returned. This is useful with Method 2 since you can
  2261. specify an offset of 0 and have the file length returned.
  2262. Never position the file pointer to before the start of file.                 
  2263. See: ReadFileDOS
  2264. ~ReadFileDOS
  2265. Pack: DOSFilePack       Src: ReadFileDOSsrc     Func: 106/DOS
  2266. Read from the file or device the specified number of bytes into a buffer.
  2267. This routine uses INT21/3F.
  2268. On block devices (such as disks) input starts at the current file position and
  2269. the file pointer is repositioned to the last byte read +1.
  2270. It is possible to read less than the bytes specified without an error being  
  2271. generated. Compare the bytes to read with the returned bytes read value. If  
  2272. less then end of file was reached during the read, if 0 then file was at EOF.
  2273. By using DOS's predefined handles you can read from the keyboard (STDIN) by
  2274. using the STDIN handle, 0. The input will terminate after all specified bytes
  2275. have been read or after a CR (ASCII 0Dh). If more bytes are entered than were
  2276. requested, the next read will retrieve those excess bytes. Therefore, it's
  2277. suggested that you specify 129 bytes to input (DOS will process 127+CR/LF bytes
  2278. maximum when reading the STDIN device). Post-process the entered data by
  2279. scanning for the CR/LF.
  2280. See: ExpandFileDOS
  2281. ~ExpandFileDOS
  2282. Pack: DOSFilePack       Src: ExpandFileDOSsrc   Func: 107/DOS
  2283. Expands the specified file by the specified number of bytes.
  2284. This routine uses INT21/42 and INT21/40.
  2285. This routine is useful in pre-allocating disk space. By reserving disk space in
  2286. advance you can guarantee that enough disk space will be available for a future
  2287. operation (especially if more than 1 process is running). You'll also be able
  2288. ensure that the disk space that a file does use is as contiguous as possible.
  2289. Database systems are dynamic and their files typically allocate new space on
  2290. an as-needed basis. This dynamic allocation can cause parts of a file to be
  2291. located throughout the disk system, possibly affecting performance drastically.
  2292. By pre-allocating the disk space you can be assured of consistent throughput
  2293. performance since the file is contiguous.
  2294. See: WriteFileDOS
  2295. ~WriteFileDOS
  2296. Pack: DOSFilePack       Src: WriteFileDOSsrc    Func: 108/DOS
  2297. Write to the file or device the specified number of bytes from a buffer.
  2298. This routine uses INT21/40.
  2299. If the number of bytes written is less than the specified bytes, this routine
  2300. returns a -2 error code (or 65554 unsigned).                                 
  2301. On block devices (such as disk) output starts at the current file position, and
  2302. the file pointer is repositioned to the last byte written +1.
  2303. If the specified bytes to write is 0, the file is truncated at the current   
  2304. file pointer position.                                                       
  2305. By using DOS's predefined handles you can write to the screen (STDOUT) by
  2306. using the STDOUT handle, 1.
  2307. See: CloseFileDOS
  2308. ~CloseFileDOS
  2309. Pack: DOSFilePack       Src: CloseFileDOSsrc    Func: 109/DOS
  2310. Close the file flushing any internal buffers, releasing any locked regions, and
  2311. update the directory entry to the correct size, date, and time.
  2312. This routine uses INT21/3E.
  2313. If you have opened a file using the DOS open routine you should close it when
  2314. you no longer need it.
  2315. This routine can be used to close the predefined DOS handles (0-4) and make  
  2316. those handles available for reuse. Typically handles 0 and 1 should not be   
  2317. closed by an application since they are the STDIN and STDOUT that DOS uses   
  2318. for the current application (keyboard and screen).                           
  2319. Since BULLET provides for up to 250 user file handles for your applications it
  2320. isn't necessary for you to eek 3 more file handles by closing handles 2-4.
  2321. See: MakeDirDOS
  2322. ~MakeDirDOS
  2323. Pack: DOSFilePack       Src: MakeDirDOSsrc      Func: 110/DOS
  2324. Create a new subdirectory.
  2325. This routine uses INT21/39.
  2326. See: DeleteFileDOS
  2327. ~AccessPack
  2328.  Src: InsertXBsrc      Func: InsertXB and many more
  2329. TYPE AccessPack        'AP (AP is recommended pack name for DIM, AP.Func=)
  2330. Func AS INTEGER        'varies
  2331. Stat AS INTEGER        'ret:completion status
  2332. Handle AS INTEGER      'OS handle
  2333. RecNo AS LONG          ' in:rec number to get/delete/update (if applicable)
  2334.                        ' in:set to single rec# to lock or set to 0 to lock all
  2335.                        'ret:record number of data record accessed
  2336. RecPtrOff AS INTEGER   'far pointer to record storage buffer
  2337. RecPtrSeg AS INTEGER
  2338. KeyPtrOff AS INTEGER   'far pointer to search key buffer
  2339. KeyPtrSeg AS INTEGER
  2340. NextPtrOff AS INTEGER  'far pointer to next key access pack
  2341. NextPtrSeg AS INTEGER  'or 0:0 if end of link or if N/A
  2342. END TYPE  '22
  2343. The NextPtr variables are only used by InsertXB, UpdateXB, ReindexXB, and the
  2344. LockXB routines. NextPtr is used as a link to the next related access pack,
  2345. if any. Not all entries are used by all routines. Generally, any routine that
  2346. gets/puts user data to the database uses this pack.
  2347. See: BreakPack
  2348. ~BreakPack
  2349.  Src: BreakXBsrc       Func: BreakXB
  2350. TYPE BreakPack             'BP
  2351. Func AS INTEGER            '4
  2352. Stat AS INTEGER            'ret:completion status
  2353. Mode AS INTEGER            '=0 disable Ctrl-C/Ctrl-Break, 1=restore
  2354. END TYPE '6 bytes
  2355. A simple pack.
  2356. See: CopyPack
  2357. ~CopyPack
  2358.  Src: BackupFileXBsrc  Func: BackupFileXB, CopyDHXB, CopyKHXB
  2359. TYPE CopyPack              'CP
  2360. Func AS INTEGER            '5=BackupFileXB,16=CopyDHXB,26=CopyKHXB
  2361. Stat AS INTEGER            'ret:completion status
  2362. Handle AS INTEGER          'handle of BULLET file
  2363. FilenamePtrOff AS INTEGER  'far pointer to filenameZ
  2364. FilenamePtrSeg AS INTEGER  '(filename must end with a CHR$(0)))
  2365. END TYPE '10
  2366. See: CreateDataPack
  2367. ~CreateDataPack
  2368.  Src: CreateDXBsrc     Func: CreateDXB
  2369. TYPE CreateDataPackTYPE    'CDP
  2370. Func AS INTEGER            '10
  2371. Stat AS INTEGER            'ret:completion status
  2372. FilenamePtrOff AS INTEGER  'far pointer to filenameZ to create
  2373. FilenamePtrSeg AS INTEGER  '(filename must end with a CHR$(0))
  2374. NoFields AS INTEGER        'number of fields per record
  2375. FieldListPtrOff AS INTEGER 'far pointer to field list
  2376. FieldListPtrSeg AS INTEGER '(field list is of type FieldDescTYPE )
  2377. FileID AS INTEGER          'file signature byte, usually=3
  2378. END TYPE '16
  2379. The filename pointed at by the FilenamePtr variables should be a fixed-length
  2380. string (e.g., FILEN AS STRING * 80) so that VARSEG/VARPTR can be used to get
  2381. its memory address. The filename must end with a CHR$(0) immediately following
  2382. the last character of the filename: FILEN = YourFilename$ + CHR$(0).
  2383. The FieldListPtr variables point to an array of type FieldDescTYPE. This array
  2384. is dimensioned for as many fields as there are in the record and contains the
  2385. field descriptors, one for each field.
  2386. See: CreateKeyPack  FieldDescTYPE
  2387. ~CreateKeyPack
  2388.  Src: CreateKXBsrc     Func: CreateKXB
  2389. TYPE CreateKeyPack         'CKP
  2390. Func AS INTEGER            '20
  2391. Stat AS INTEGER            'ret:completion status
  2392. FilenamePtrOff AS INTEGER  'far pointer to filenameZ
  2393. FilenamePtrSeg AS INTEGER  '(filename must end with a CHR$(0))
  2394. KeyExpPtrOff AS INTEGER    'far pointer to key expressionZ
  2395. KeyExpPtrSeg AS INTEGER    '(key expression must end with a CHR$(0))
  2396. XBlink AS INTEGER          'BULLET XB data file handle this key file indexes
  2397. KeyFlags AS INTEGER        'bit 0=unique,1=char,4=int,5=long,(E=NLS),F=signed
  2398. CodePageID AS INTEGER      'code page ID for NLS, -1 to use system default
  2399. CountryCode AS INTEGER     'country code number for NLS, -1 to use default
  2400. CollatePtrOff AS INTEGER   'far pointer to programmer-supplied collate table
  2401. CollatePtrSeg AS INTEGER   'or 0:0 if using system-determined NLS table
  2402. END TYPE '24
  2403. Bit 14 in KeyFlags (0Eh) is set by BULLET during CreateKXB if a collate table
  2404. is present.
  2405. See: DescriptorPack  is_NLS
  2406. ~DescriptorPack
  2407.  Src: GetDescriptorXBsrc  Func: GetDescriptorXB
  2408. TYPE DescriptorPack        'DP
  2409. Func AS INTEGER            '30
  2410. Stat AS INTEGER            'ret:completion status
  2411. Handle AS INTEGER          'BULLET data file handle to get information on
  2412. FieldNumber AS INTEGER     'field number to get info on, or if 0 then...
  2413. FD AS FieldDescTYPE        '...search for DP.FD.FieldName
  2414. END TYPE '40
  2415. GetDescriptorXB allows you to get the field descriptor info for a particular
  2416. field number (as in the first field, or the 10th field, etc.) or, if you don't
  2417. know the physical field number, the routine can also get the info for a field
  2418. by field name.
  2419. To get the info for field number, say 5, set DP.FieldNumber = 5. The DP.FD
  2420. structure element is filled in with field 5's information.
  2421. To get the info for a field by fieldname, say LASTNAME, set DP.FieldNumber=0 &
  2422. DP.FD.FieldName = "LASTNAME" + STRING$(11,0)--the fieldname must be zero-filled
  2423. and zero-terminated--adding 11 ASCII zeroes ensures this requirement.
  2424. See: DOSFilePack  FieldDescTYPE
  2425. ~DOSFilePack
  2426.  Src: AccessFileDOSsrc  Func: AccessFileDOS
  2427.                               (all routines ending with DOS)
  2428. TYPE DOSFilePack           'DFP
  2429. Func AS INTEGER            'varies, see DeleteFileDOS for first of DOS routines
  2430. Stat AS INTEGER            'ret:completion status
  2431. FilenamePtrOff AS INTEGER  'far pointer to filenameZ
  2432. FilenamePtrSeg AS INTEGER  '(filename must end with a CHR$(0))
  2433. Handle AS INTEGER          'in: handle to access  ret: handle opened
  2434. ASmode AS INTEGER          'open access/sharing mode
  2435. Bytes AS INTEGER           'in: bytes to read  ret: bytes read
  2436. SeekOffset AS LONG         'seek to file position
  2437. Method AS INTEGER          'seek method
  2438. BufferPtrOff AS INTEGER    'far pointer to read/write buffer
  2439. BufferPtrSeg AS INTEGER
  2440. Attr AS INTEGER            'file create directory entry attribute
  2441. NewNamePtrOff AS INTEGER   'far pointer to new filenameZ for rename
  2442. NewNamePtrSeg AS INTEGER   '(filename must end with a CHR$(0))
  2443. END TYPE '30
  2444. All of the xDOS routines use this pack. Often only a few of the structure
  2445. elements are used by any one of the routines. Set only those needed.
  2446. See: DVmonPack
  2447. ~DVmonPack
  2448.  Src: DVmonCXBsrc      Func: DVmonCXB
  2449. TYPE DVmonPackTYPE         'THIS ROUTINE IS AVAILABLE ONLY IN THE DEBUG ENGINE
  2450. Func AS INTEGER            '9
  2451. Stat AS INTEGER            'ret:completion status
  2452. Mode AS INTEGER            '=0 disable montitoring, =1 enable
  2453. Handle AS INTEGER          'file handle to monitor
  2454. VideoSeg AS INTEGER        'segment to write screen image (e.g., &HB800)
  2455. END TYPE '10 bytes
  2456. This routine is supplied only in the BULLET debug engine. It displays real-time
  2457. monitoring information of a .DBF file or index and .DBF file pair including
  2458. searches, seeks, hits, current record number, current key, key node contents,
  2459. key node pointers, stack state, key and record counts, and other info.
  2460. By using the HereSeg value returned from StatKXB you can locate the searches,
  2461. seeks, and hits data at (DEF SEG=HereSeg: Seeks&=GetLongAt&(517): DEF SEG)
  2462.  +513 Searches AS LONG ;keys searched for since open
  2463.  +517 Seeks AS LONG    ;nodes seeked since open
  2464.  +521 Hits AS LONG     ;seeks satisfied without disk access
  2465. See: ExitPack
  2466. ~ExitPack
  2467.  Src: InitXBsrc        Func: ExitXB, AtExitXB
  2468. TYPE ExitPack              'EP
  2469. Func AS INTEGER            '1=ExitXB, 2=AtExitXB
  2470. Stat AS INTEGER            'ret:completion status
  2471. END TYPE '4 bytes
  2472. See: FieldDescTYPE
  2473. ~FieldDescTYPE
  2474.  Src: CreateDXBsrc     Func: CreateDXB
  2475. TYPE FieldDescTYPE         'this TYPE is used by CreateDataPack ONLY
  2476. FieldName AS STRING * 11   'zero-filled field name (use only ASCII 65-90,95)
  2477. FieldType AS STRING * 1    'C-har,N-umeric,D-ate,L-ogical,M-emo
  2478. FieldDA AS LONG            '=0,reserved
  2479. FieldLength AS STRING * 1  'C=1-254,N=1-19(varies),D=8,L=1,M=10
  2480. FieldDC AS STRING * 1      'decimal places for FieldType=N (0,2-15)
  2481. A1 AS INTEGER              '=0,reserved
  2482. A2 AS INTEGER              '=0,reserved
  2483. filler AS STRING * 10      '=0,reserved
  2484. END TYPE '32
  2485. If you can can forgo dBASE compatility you can use the B field type. This type
  2486. is for fields that contain binary data (all dBASE fields contain ASCII text or
  2487. numeric strings). If you specify a FieldType = "B" for, say an integer field,
  2488. use a FieldLen = 2. If the field is a long integer, use FieldLen = 4. You can
  2489. also use this non-standard field type for indexing. See CreateKXB for more.
  2490. See: HandlePack  CreateDataPack  CreateKXB
  2491. ~HandlePack
  2492.  Src: CloseDXBsrc      Func: CloseDXB, ReadDHXB, FlushDHXB, ZapDHXB
  2493.                              CloseKXB, ReadKHXB, FlushKHXB, ZapKHXB
  2494.                            'HP
  2495. TYPE HandlePack            '12=CloseDXB,14=ReadDHXB,15=FlushDHXB,17=ZapDHXB
  2496. Func AS INTEGER            '22=CloseKXB,24=ReadKHXB,25=FlushKHXB,27=ZapKHXB
  2497. Stat AS INTEGER            'ret:completion status
  2498. Handle AS INTEGER          'handle of BULLET file
  2499. END TYPE '6
  2500. See: InitPack
  2501. ~InitPack
  2502.  Src: InitXBsrc        Func: InitXB
  2503. TYPE InitPack              'IP
  2504. Func AS INTEGER            '0
  2505. Stat AS INTEGER            'ret:completion status
  2506. JFTmode AS INTEGER         'expand JFT if non-zero
  2507. DOSver AS INTEGER          'ret:DOS version
  2508. OSversion AS INTEGER       'ret:BULLET OS version (HB=major, LB=minor)
  2509.                            '(0=DOS, 1=Win16, 2=OS/2-16, 3=OS/2-32)
  2510. Version AS INTEGER         'ret:BULLET version * 100 (120=1.20)
  2511. ExitOff AS INTEGER         'ret:far pointer to ExitXB routine, offset
  2512. ExitSeg AS INTEGER         'ret:segment of ExitXB
  2513. END TYPE '12 bytes
  2514. See: MemoryPack
  2515. ~MemoryPack
  2516.  Src: MemoryXBsrc      Func: MemoryXB
  2517. TYPE MemoryPack            'MP
  2518. Func AS INTEGER            '3
  2519. Stat AS INTEGER            'ret:completion status
  2520. Memory AS LONG             'ret:largest free OS memory block
  2521. END TYPE '8 bytes
  2522. See: OpenPack
  2523. ~OpenPack
  2524.  Src: OpenDXBsrc       Func: OpenDXB, OpenKXB
  2525. TYPE OpenPack              'OP
  2526. Func AS INTEGER            '11=OpenDXB,21=OpenKXB
  2527. Stat AS INTEGER            'ret:completion status
  2528. Handle AS INTEGER          'ret:OS handle of file opened
  2529. FilenamePtrOff AS INTEGER  'far pointer to filenameZ to open
  2530. FilenamePtrSeg AS INTEGER  '(filename must end with a CHR$(0))
  2531. ASmode AS INTEGER          'DOS access-sharing mode (see OpenFileDOS)
  2532. xbHandle AS INTEGER        'if opening key file this is its related data file
  2533. END TYPE '14               '(if opening data file xbHandle is not used)
  2534.                            'Note: you must supply xbHandle on index file opens
  2535. See: RemotePack  OpenFileDOS
  2536. ~RemotePack
  2537.  Src: DriveRemoteXBsrc  Func: DriveRemoteXB, FileRemoteXB
  2538. TYPE RemotePack            'RP
  2539. Func AS INTEGER            '86=DriveRemoteXB,87=FileRemoteXB
  2540. Stat AS INTEGER            'ret:completion status
  2541. Handle AS INTEGER          'handle/drive depending on routine
  2542. IsRemote AS INTEGER        'ret:0=local,1=remote
  2543. Flags AS INTEGER           'ret:dx register as returned by DOS
  2544. IsShare AS INTEGER         'ret:0=SHARE.EXE not loaded
  2545. END TYPE '12
  2546. See: SetRetriesPack
  2547. ~SetRetriesPack
  2548.  Src: SetRetriesXBsrc  Func: SetRetriesXB
  2549. TYPE SetRetriesPack        'SRP
  2550. Func AS INTEGER            '88
  2551. Stat AS INTEGER            'ret:completion status
  2552. Mode AS INTEGER            '0=set DOS default else use Pauses/Retries below
  2553. Pause AS INTEGER           '0-65535 loop counter between retries
  2554. Retries As INTEGER         '0-65535 retries to access locked file
  2555. END TYPE '10
  2556. The default values for Retries is 3 and Pause is 1.
  2557. The Pause value is used as a simple loop counter used to waste time. This loop
  2558. IS dependent on CPU power so values are not portable across different machines.
  2559. See: StatDataPack
  2560. ~StatDataPack
  2561.  Src: StatDXBsrc       Func: StatDXB
  2562. TYPE StatDataPackTYPE      'SDP
  2563. Func AS INTEGER            '13
  2564. Stat AS INTEGER            'ret:completion status
  2565. Handle AS INTEGER          'BULLET data file to get status on
  2566. FileType AS STRING * 1     'ret:1=BULLET XB data file
  2567. Dirty AS STRING * 1        'ret:0=not changed
  2568. Recs AS LONG               'ret:records in file
  2569. RecLen AS INTEGER          'ret:record length
  2570. Fields AS INTEGER          'ret:fields per record ()
  2571. f1 AS STRING * 1           'reserved (1=update DVmon)
  2572. LUyear AS STRING * 1       'ret:binary, year file last updated
  2573. LUmonth AS STRING * 1      'ret:month   --LUs are 0 if DBF newly created
  2574. LUday AS STRING * 1        'ret:day
  2575. HereSeg AS INTEGER         'ret:this file's control segment
  2576. filler AS STRING * 10      'reserved
  2577. END TYPE '32
  2578. See: StatKeyPack
  2579. ~StatKeyPack
  2580.  Src: StatKXBsrc       Func: StatKXB
  2581. TYPE StatKeyPack           'SKP
  2582. Func AS INTEGER            '23
  2583. Stat AS INTEGER            'ret:completion status
  2584. Handle AS INTEGER          'BULLET key file to get status on
  2585. FileType AS STRING * 1     'ret:0=BULLET XB key file
  2586. Dirty AS STRING * 1        'ret:0=not changed
  2587. Keys AS LONG               'ret:keys in file
  2588. KeyLen AS INTEGER          'ret:key length
  2589. XBlink AS INTEGER          'ret:related BULLET XB data file handle
  2590. XBrecno AS LONG            'ret:record number attached to current key
  2591. HereSeg AS INTEGER         'ret:this file's control segment
  2592. CodePageID AS INTEGER      'ret:code page ID number of key file sort
  2593. CountryCode AS INTEGER     'ret:country code number of key file sort
  2594. CollateTableSize AS INTEGER 'ret: size of collate table, 0 or 256
  2595. KeyFlags AS INTEGER        'ret:bit 0=unique,1=char,4=int,5=long,E=NLS,F=signed
  2596. filler AS STRING * 2
  2597. END TYPE '32
  2598. See: StatHandlePack
  2599. ~StatHandlePack
  2600.  Src: StatHandleXBsrc  Func: StatHandleXB
  2601. TYPE StatHandlePack        'SHP
  2602. Func AS INTEGER            '6
  2603. Stat AS INTEGER            'ret:completion status
  2604. Handle AS INTEGER          'file handle to get information on
  2605. ID AS INTEGER              'ret:0=XB index,1=XB data file,-1=not BULLET handle
  2606. END TYPE '8 bytes
  2607. See: XErrorPack
  2608. ~XErrorPack
  2609.  Src: GetExtErrorXBsrc Func: GetExtErrorXB
  2610. TYPE XErrorPack            'XEP
  2611. Func AS INTEGER            '7
  2612. Stat AS INTEGER            'ret:extended error
  2613. Class AS INTEGER           'ret:error class
  2614. Action AS INTEGER          'ret:suggested action
  2615. Location AS INTEGER        'ret:error location
  2616. END TYPE '10 bytes
  2617. See: AccessPack  Errors_DOS
  2618. ~Errors_BULLET    (200-209)
  2619. 200 key not found - The search key for Equal was not matched exactly.
  2620.     Next/Prev routines can be used to continue search from point of mismatch.
  2621. 201 key already exists - Attempted to add a key that already exists in the
  2622.     index file created to allow only unique keys.
  2623. 202 end of file - A Next routine is past the last key of the index file.
  2624. 203 top of file - A Prev routine is before the first key of the index file.
  2625. 204 key file empty - A key access was attempted with no keys in the index file.
  2626. 205 key type unknown - Generally indicates a corrupt index header (keyflags
  2627.     unknown at key insert).
  2628.     reserved,206-207
  2629. 208 no more nodes - The index file has reached full capacity (32MB). ReindexXB
  2630.     can often shrink an index file by 30 to 50%.
  2631. 209 key file corrupt - The index file is corrupt (write attempt to node 0).
  2632. See: Errors_BULLET_b
  2633. ~Errors_BULLET_b  (210-232)
  2634. 210 key file corrupt - The index file is corrupt (internal overflow).
  2635.     reserved,211-219
  2636. 220 incorrect DOS version - BULLET requires DOS 3.3 or later.
  2637. 221 invalid key length - The key is > 62 bytes (or 64 if unique specified).
  2638. 222 file not open - The specified handle is not an open BULLET file.
  2639.        
  2640.     reserved,223
  2641. 224 invalid record number - The specified record number is < 0, past the last
  2642.     record number in the .DBF, or is > 16,777,215.
  2643.     reserved,225-227
  2644. 228 invalid filetype - The specified handle is not the correct type for the
  2645.     operation (i.e., specifying a data file handle for a key file operation).
  2646.     reserved,229-232
  2647. See: Errors_BULLET_c
  2648. ~Errors_BULLET_c  (233-243)
  2649. 233 init not active - InitXB must be called before all others except MemoryXB.
  2650. 234 init already active - InitXB has already been called. Use ExitXB first to
  2651.     call InitXB more than once per process. (Make sure the xxP.Func <> 0.)
  2652. 235 too many indexes - BULLET can handle up to 32 index files per transaction
  2653.     record with the InsertXB and UpdateXB routines. Contact the author if you
  2654.     need to allow for more than 32 index files/transaction record.
  2655.     reserved,236-239
  2656. 240 invalid key expression - The CreateKXB key expression could not be
  2657.     evaluated.
  2658.     reserved,241
  2659. 242 field not found - The fieldname was not found in the descriptor area.
  2660. 243 invalid field count - Too many fields were specified or the specified field
  2661.     number is past the last field.
  2662. See: Errors_BULLET_d
  2663. ~Errors_BULLET_d  (244-255)
  2664.     reserved,244-247
  2665. 250 invalid country info - The specifed country code or code page ID is not
  2666.     valid or not installed (according to DOS).  Also 248 and 249.
  2667. 251 invalid collate table size - The specified country code/code page ID uses
  2668.     a collate-sequence table > 256 bytes (2-byte characters as with Kanji).
  2669. 252 invalid keyflags - The specified keyflags are invalid.
  2670.     reserved,253-254
  2671. 255 evaluation mode shutdown - BULLET evaluation period has completed.
  2672.     You can reinstall to continue evaluation, though you may want to consider
  2673.     your motives for reinstalling since the original evaluation period has
  2674.     expired. This error occurs only after the evaluation period has expired.
  2675.     It is not recommended that you continue to use BULLET after the evaluation
  2676.     period. It is possible for no 255 error to be generated for quite some
  2677.     time since it occurs only under certain load conditions and then only when
  2678.     certain routine sequences are performed. The specified evaluation period of
  2679.     21 days should be adhered to.
  2680. See: Errors_BASIC
  2681. ~Errors_BASIC
  2682.  1 NEXT without FOR                    24 device timeout
  2683.  2 syntax error                        25 device fault
  2684.  3 RETURN without GOSUB                26 FOR without NEXT
  2685.  4 out of DATA                         27 out of paper
  2686.  5 illegal function call               29 WHILE without WEND
  2687.  6 overflow                            30 WEND without WHILE
  2688.  7 out of memory                          reserved,31-32
  2689.  8 label not defined                   33 duplicate label
  2690.  9 subscript out of range                 reserved,34
  2691. 10 duplicate definition                35 subprogram not defined
  2692. 11 division by zero                       reserved,36
  2693. 12 illegal in direct mode              37 argument-count mismatch
  2694. 13 type mismatch                       38 array not defined
  2695. 14 out of string space                    reserved,39
  2696.    reserved,15                         40 variable required
  2697. 16 string formula too complex             reserved,41-49
  2698. 17 cannot continue                     50 FIELD overflow
  2699. 18 function not defined                51 internal error
  2700. 19 no RESUME                           52 bad file name or number
  2701. 20 RESUME without error                53 file not found
  2702.    reserved,21-23                      54 bad file mode
  2703. See: Errors_BASIC_b
  2704. ~Errors_BASIC_b
  2705. 55 file already open                      reserved,77-79
  2706. 56 FIELD statement active              80 feature removed
  2707. 57 device I/O error                    81 invalid name
  2708. 58 file already exists                 82 table not found
  2709. 59 bad record length                   83 index not found
  2710.    reserved,60                         84 invalid column
  2711. 61 disk full                           85 no current record
  2712. 62 input past end of file              86 duplicate value for unique index
  2713. 63 bad record number                   87 invalid operation on null index
  2714. 64 bad file name                       88 database needs repair
  2715.    reserved,65-66                      89 insufficient ISAM buffers
  2716. 67 too many files
  2717. 68 device unavailable
  2718. 69 communication-buffer overflow
  2719. 70 permission denied
  2720. 71 disk not ready
  2721. 72 disk-media error
  2722. 73 feature unavailable
  2723. 74 rename across disks
  2724. 75 path/File access error
  2725. 76 path not found
  2726. See: Errors_DOS
  2727. ~Errors_DOS
  2728. -2 disk full or unexpected end of file (65534)
  2729. -1 bad filename (65535)
  2730.  0 no error
  2731.  1 function not supported              19 disk write protected
  2732.  2 file not found                      20 unknown unit
  2733.  3 path not found                      21 drive not ready
  2734.  4 too many open files                 22 unknown command
  2735.  5 access denied (see Specs_Networks)  23 data error (CRC)
  2736.  6 handle invalid                      24 bad request structure length
  2737.  7 MCBs destroyed                      25 seek error
  2738.  8 not enough memory                   26 unknown medium type
  2739.  9 memory block address invalid        27 sector not found
  2740. 10 environment invalid                 28 printer out of paper
  2741. 11 format invalid                      29 write fault
  2742. 12 access code invalid                 30 read fault
  2743. 13 data invalid                        31 general failure
  2744.    reserved-0Eh                        32 sharing violation
  2745. 15 disk drive invalid                  33 lock violation
  2746. 16 cannot remove current directory     34 disk change invalid/wrong disk
  2747. 17 not same device                     35 FCB unavailable
  2748. 18 no more files                       36 sharing buffer overflow
  2749. See: Errors_DOS_b
  2750. ~Errors_DOS_b
  2751. 37 code page mismatched                58 incorrect response from network
  2752. 38 handle EOF                          59 unexpected network error
  2753. 39 handle disk full                    60 incompatible remote adapter
  2754.    reserved-28h                        61 print queue full
  2755.    reserved-29h                        62 no spool space
  2756.    reserved-2Ah                        63 not enough space to print file
  2757.    reserved-2Bh                        64 network name deleted
  2758.    reserved-2Ch                        65 network access denied
  2759.    reserved-2Dh                        66 network device type incorrect
  2760.    reserved-2Eh                        67 network name not found
  2761.    reserved-2Fh                        68 network name limit exceeded
  2762.    reserved-30h                        69 NETBIOS session limit exceeded
  2763.    reserved-31h                        70 sharing temporarily paused
  2764. 50 network request not supported       71 network request not accepted
  2765. 51 remote computer not listening       72 print/disk redirection paused
  2766. 52 duplicate name on network              reserved-49h
  2767. 53 network pathname not found             reserved-4Ah
  2768. 54 network busy                           reserved-4Bh
  2769. 55 network device no longer exists        reserved-4Ch
  2770. 56 NETBIOS command limit exceeded         reserved-4Dh
  2771. 57 network adapter hardware error         reserved-4Eh
  2772. See: Errors_DOS_c
  2773. ~Errors_DOS_c
  2774.    reserved-4Fh                  
  2775.  DOS Class Codes 
  2776. 80 file exists
  2777. 81 duplicate FCB                 1 out of resources       7 application error
  2778. 82 cannot make                   2 temporary situation    8 not found
  2779. 83 fail on INT24                 3 authorization          9 bad format
  2780. 84 out of structures             4 internal error        10 locked
  2781. 85 already assigned              5 hardware failure      11 media failure
  2782. 86 invalid password              6 system failure        12 already exists
  2783. 87 invalid parameter                                     13 unknown
  2784. 88 network write fault
  2785.    reserved-59h                    DOS Action Codes         DOS Locus Codes
  2786. 90 sys comp not loaded
  2787.                                  1 retry immediately      1 unknown
  2788.                                  2 delay and retry        2 block device
  2789.                                  3 reenter input          3 network
  2790.                                  4 abort ASAP             4 serial device
  2791.                                  5 abort immediately      5 memory
  2792.                                  6 ignore error
  2793.                                  7 user intervention
  2794. See: Errors_BULLET
  2795. ~InitXBsrc
  2796. Func: InitXB           Pack: InitPack           Func:   0/System
  2797. DIM IP AS InitPack
  2798. DIM EP AS ExitPack
  2799. IP.Func = InitXB        'InitXB defined in BULLET.BI
  2800. IP.JFTmode = 1          'expand JFT to 255 handles
  2801. stat = BULLET(IP)
  2802. IF stat = 0 THEN
  2803.    DOSmajor = IP.DOSver\256
  2804.    DOSminor = IP.DOSver MOD 256
  2805.    BULLETver = IP.Version
  2806.    BULLETosVer = IP.OSversion
  2807.    SegExitXB = IP.ExitSeg
  2808.    OffExitXB = IP.ExitOff
  2809.    EP.Func = AtExitXB   'register ExitXB with _atexit shutdown routine
  2810.    stat = BULLET(EP)    '(though failure here is not fatal)
  2811. ENDIF
  2812. IF stat THEN 'error
  2813. See: ExitXBsrc
  2814. ~ExitXBsrc
  2815. Func: ExitXB           Pack: ExitPack           Func:   1/System
  2816. DIM EP AS ExitPack
  2817. EP.Func = ExitXB        'ExitXB defined in BULLET.BI
  2818. stat = BULLET(EP)
  2819. The return value from ExitXB is currently always 0.
  2820. See: AtExitXBsrc
  2821. ~AtExitXBsrc
  2822. Func: AtExitXB         Pack: ExitPack           Func:   2/System
  2823. DIM IP AS InitPack
  2824. DIM EP AS ExitPack
  2825. IP.Func = InitXB
  2826. IP.JFTmode = 1
  2827. stat = BULLET(IP)
  2828. IF stat = 0 THEN
  2829.    DOSmajor = IP.DOSver\256
  2830.    DOSminor = IP.DOSver MOD 256
  2831.    SegExitXB = IP.ExitSeg
  2832.    OffExitXB = IP.ExitOff
  2833.                         'register ExitXB with _atexit shutdown routine
  2834.    EP.Func = AtExitXB   'AtExitXB defined in BULLET.BI
  2835.    stat = BULLET(EP)    'the return value is that returned from the compiler
  2836.                         '_atexit routine, 0=okay, anything else is an error
  2837. ENDIF                   'indicating, for example, the _atexit register is full
  2838. IF stat THEN 'error
  2839. See: MemoryXBsrc
  2840. ~MemoryXBsrc
  2841. Func: MemoryXB         Pack: MemoryPack         Func:   3/System
  2842. DIM MP AS MemoryPack
  2843. WorkSpace& = 50000      'a value at least 40K or so
  2844. MemoryNeeded& = WorkSpace& + (144&+ ((1+NF)*32)) * TotalOpenDataFiles _
  2845.                            + (1264& * TotalOpenKeyFiles)
  2846. MP.Func = MemoryXB
  2847. stat = BULLET(MP)
  2848. IF MP.Memory < MemoryNeeded& THEN
  2849.     QBheap& = SETMEM(-MemoryNeeded& + 4096)  'release what we need+QB fudge
  2850.     MP.Func = MemoryXB
  2851.     stat = BULLET(MP)
  2852.     IF MP.Memory < MemoryNeeded& THEN 'not enough memory
  2853. END IF
  2854. MP.Memory does not reflect memory available through DOS in the UMB area. It's
  2855. possible that all memory requests can be satisfied by UMB RAM. Consult a DOS 5+
  2856. programmer reference for more information on this (see DOS INT21/58 for more).
  2857. In the QuickBASIC/BASIC PDS environment do not call SETMEM(-x) more than once.
  2858. See: BreakXBsrc
  2859. ~BreakXBsrc
  2860. Func: BreakXB          Pack: BreakPack          Func:   4/System
  2861. DIM BP AS BreakPack
  2862. BP.Func = BreakXB       'BreakXB defined in BULLET.BI
  2863. BP.Mode = 0             'disable Ctrl-C/Ctrl-BREAK (do nothing on those keys)
  2864. stat = BULLET(BP)       'stat=0 always
  2865. If BreakXB is called multiple times with the same BP.mode each time, only the
  2866. first is acted on. You can set BP.mode = 1 to restore the default handlers
  2867. (those installed originally) and then again set BP.Mode = 0 to disable them.
  2868. ExitXB calls this routine automatically as part of the BULLET shutdown to
  2869. restore the original default break handlers.
  2870. See: BackupFileXBsrc
  2871. ~BackupFileXBsrc
  2872. Func: BackupFileXB     Pack: CopyPack           Func:   5/System
  2873. DIM AP AS AccessPack            'be sure 32K is available before calling
  2874. DIM CP AS CopyPack              '-- this memory can be given back afterward
  2875. DIM TempStr AS STRING * 80      'used as fixed-length string for VARPTR()
  2876.                                 'so same source QB AND BASIC7 /Fs compatible
  2877. TempStr = NewFilename$          'assign the var-len string to fixed-len str
  2878. CP.Func = BackupFileXB  'defined in BULLET.BI
  2879. CP.Handle = DataHandle  'handle of data file to backup
  2880. CP.FilenamePtrOff = VARPTR(TempStr) 'ALWAYS use VARPTR() on fixed-len string
  2881. CP.FilenamePtrSeg = VARSEG(TempStr) 'ALWAYS use VARSEG() on fixed-len string
  2882. stat = BULLET(CP)       'copy the data file to the file NewFilename$
  2883. IF stat = 0 THEN
  2884.    AP.Func = PackRecordsXB
  2885.    AP.Handle = DataHandle
  2886.    stat = BULLET(AP)
  2887. ENDIF
  2888. IF stat THEN 'error
  2889. See: StatHandleXBsrc
  2890. ~StatHandleXBsrc
  2891. Func: StatHandleXB     Pack: StatHandlePack     Func:   6/System
  2892. DIM SHP AS StatHandlePack
  2893. DIM SKP AS StatKeyPack
  2894. DIM SDP AS StatDataPack
  2895. SHP.Func = StatHandleXB 'defined in BULLET.BI
  2896. SHP.Handle = TheHandleNumber
  2897. stat = BULLET(SHP)
  2898. IF SHP.ID = 0 THEN      'handle belongs to an index file (index file/key file)
  2899.    SKP.Func = StatKXB   'get key stats  -- see StatKXB/StatDXB for more
  2900.    SKP.Handle = PassedHandleNumber      ' on the SKP structure
  2901.    stat = BULLET(SKP)
  2902. ELSEIF SHP.ID = 1 THEN  '.DBF data file
  2903.    'get DBF stats
  2904.    'error not a BULLET file type
  2905. ENDIF
  2906. See: GetExtErrorXBsrc
  2907. ~GetExtErrorXBsrc
  2908. Func: GetExtErrorXB    Pack: XErrorPack         Func:   7/System
  2909. 'an error just occured in the range 1 to 199 as returned in one of the
  2910. 'pack.Stat variables (current max DOS error is 90 (5Ah))
  2911. 'remember, transaction-based routines return a bad pack index in the return
  2912. 'stat value, which you use to check the appropriate pack.Stat variable
  2913. DIM XEP AS XErrorPack
  2914. XEP.Func = GetExtErrorXB 'defined in BULLET.BI
  2915. stat = BULLET(XEP)
  2916. IF stat <> 0 THEN
  2917.    PRINT "Extended Codes --"
  2918.    PRINT "            error: "; XEP.Stat
  2919.    PRINT "      error class: "; XEP.Class
  2920.    PRINT "recommened action: "; XEP.Action
  2921.    PRINT "         location: "; XEP.Location
  2922.    PRINT "No error"
  2923. ENDIF
  2924. See: DVmonCXBsrc  StatKXB
  2925. ~DVmonCXBsrc
  2926. Func: DVmonCXB         Pack: DVmonPack          Func:   9/DEBUG
  2927. 'at this point a data file and a key file have been opened
  2928. 'kf is that key file's DOS handle
  2929. DIM DV AS DVmonPack
  2930. DV.Func = DVmonCXB      'defined in BULLET.BI
  2931. DV.Mode = 1             'enable monitoring
  2932. DV.Handle = kf          'monitor key file handle, kf (and its XBlink data file)
  2933. DV.VideoSeg = &HB800+(4096\16)  'output to color screen, page 1 (pages 0 to ?)
  2934. stat = BULLET(DV)       'stat=0 always even if not DEBUG ENGINE
  2935. For two-monitor systems (with a color monitor as the main system) output should
  2936. be directed to &HB000, the mono monitor's video memory.
  2937. DVmonCXB stands for Dual Video Monitor Control XB.
  2938. See: CreateDXBsrc
  2939. ~CreateDXBsrc
  2940. Func: CreateDXB        Pack: CreateDataPack     Func:  10/Mid-level
  2941. DIM CDP AS CreateDataPack
  2942. DIM TempStr AS STRING * 80      'used as fixed-length string for VARPTR()
  2943. REDIM FD(1 TO 2) AS FieldDescTYPE 'field descriptions for each of the fields...
  2944.                                   '...in the record (record has 2 fields)
  2945. TempStr = filename$ + CHR$(0)   'assign filename to a fixed-len string...
  2946.                                 '...so we can use VARSEG/VARPTR
  2947. 'build FD first for each of the fields in the record
  2948. FD(1).FieldName = "STUDENT" + STRING$(10,0)   'must be zero-filled
  2949. FD(1).FieldType = "C"           'a character field type
  2950. FD(1).FieldLength = CHR$(20)    'up to 20 characters (a byte field--use CHR$())
  2951. FD(1).FieldDC = CHR$(0)         'non-numeric has no decimal places
  2952. FD(2).FieldName = "SCORE" + STRING$(10,0)
  2953. FD(2).FieldType = "N"
  2954. FD(2).FieldLength = CHR$(3)     'dBASE numeric format, allow for "100"
  2955. FD(2).FieldDC = CHR(0)          'no decimal places used for this field
  2956. '(cont)
  2957.                      'for BINARY FieldType="B" see FieldDescTYPE
  2958. See: CreateDXBsrc_a                                                     -MORE-
  2959. ~CreateDXBsrc_a
  2960. 'build the CDP
  2961. CDP.Func = CreateDXB            'defined in BULLET.BI
  2962. CDP.FilenamePtrOff = VARPTR(TempStr) 'point to filenameZ (Z=0-terminated str)
  2963. CDP.FilenamePtrSeg = VARSEG(TempStr)
  2964. CDP.NoFields = 2                'this example has 2 fields
  2965. CDP.FieldListPtrOff = VARPTR(FD(1)) 'point to the first field decription...
  2966. CDP.FieldListPtrSeg = VARPTR(FD(1)) '...defined in the previous screen
  2967. CDP.FileID = 3                  'standard dBASE file ID
  2968. stat = BULLET(CDP)              'create the DBF data file
  2969. IF stat THEN 'error
  2970. Normally this code would be written as a generalized FUNCTION. The CDP could be
  2971. a global allocation (DIM SHARED CDP AS CreateDataPack) and the FD() would also
  2972. be (REDIM [SHARED] FD(1 TO 1) AS FieldDescTYPE) and REDIM'd to needed size when
  2973. used. A possible header:
  2974.  DECLARE FUNCTION CreateDBF% (filename$, NoFields%, FD() AS FieldDescTYPE)
  2975. To create a DBF you'd need just the filename, number of fields, REDIM the FD()
  2976. array (if needed), fill in FD() array, then call the function. Look at the
  2977. source code examples on the distribution disk for more.
  2978. See: OpenDXBsrc  CreateDXBsrc
  2979. ~OpenDXBsrc
  2980. Func: OpenDXB          Pack: OpenPack           Func:  11/Mid-level
  2981. DIM OP AS OpenPack
  2982. DIM TempStr AS STRING * 80      'used as fixed-length string for VARPTR()
  2983. TempStr = filename$ + CHR$(0)   'assign filename to a fixed-len string...
  2984. OP.Func = OpenDXB                   'defined in BULLET.BI
  2985. OP.FilenamePtrOff = VARPTR(TempStr) 'point to filenameZ (Z=0-terminated str)
  2986. OP.FilenamePtrSeg = VARSEG(TempStr)
  2987. OP.ASmode = ReadWrite + DenyNone    'defined in BULLET.BI
  2988. stat = BULLET(OP)
  2989. IF stat THEN 'error
  2990. The ASmode (access/sharing mode) determines how the operating system controls
  2991. access to the file. See OpenFileDOS for the meanings of the various ASmodes.
  2992. See: CloseDXBsrc  OpenFileDOS
  2993. ~CloseDXBsrc
  2994. Func: CloseDXB         Pack: HandlePack         Func:  12/Mid-level
  2995. DIM HP AS HandlePack
  2996. HP.Func = CloseDXB              'defined in BULLET.BI
  2997. HP.Handle = datahandle          'handle of the file to close
  2998. stat = BULLET(HP)
  2999. IF stat THEN 'error
  3000. See: StatDXBsrc
  3001. ~StatDXBsrc
  3002. Func: StatDXB          Pack: StatDataPack       Func:  13/Mid-level
  3003. DIM SDP AS StatDataPack
  3004. SDP.Func = StatDXB          'defined in BULLET.BI
  3005. SDP.Handle = datahandle     'data handle to get stats on
  3006. stat = BULLET(SDP)          'must be a data handle, use StatHandleXB if you...
  3007. IF stat = 0 THEN            '...don't know the type of file a handle's for
  3008.    'SDP.FileType is set to 1
  3009.    'SDP.Dirty is set to 1 if the file has changed (0=not changed)
  3010.    'SDP.Recs = number of records in the DBF file
  3011.    'SDP.RecLen = record length
  3012.    'SDP.Fields = number of fields in the record
  3013.    'SDP.f1 is reserved
  3014.    'SDP.LUyear = year file last updated, binary (year = ASC(SDP.LUyear))
  3015.    'SDP.LUmonth = month, binary
  3016.    'SDP.LUday = day, binary
  3017.    'SDP.HereSeg is set to this handle's control segment (location in memory)
  3018.    'error
  3019. ENDIF
  3020. See: ReadDHXBsrc
  3021. ~ReadDHXBsrc
  3022. Func: ReadDHXB         Pack: HandlePack         Func:  14/Mid-level
  3023. DIM HP AS HandlePack
  3024. HP.Func = ReadDHXB              'defined in BULLET.BI
  3025. HP.Handle = datahandle          'handle of file whose header you want to reload
  3026. stat = BULLET(HP)
  3027. IF stat THEN 'error
  3028. This routine is automatically called by the network lock routines.
  3029. See: FlushDHXBsrc  LockDataXB
  3030. ~FlushDHXBsrc
  3031. Func: FlushDHXB        Pack: HandlePack         Func:  15/Mid-level
  3032. DIM HP AS HandlePack
  3033. HP.Func = FlushDHXB             'defined in BULLET.BI
  3034. HP.Handle = datahandle          'handle of file you want to flush
  3035. stat = BULLET(HP)
  3036. IF stat THEN 'error
  3037. Note that the physical write to disk is performed only if the file has changed
  3038. since the open or last flush.
  3039. This routine is automatically called by the network unlock routines.
  3040. See: CopyDHXBsrc  UnlockDataXB
  3041. ~CopyDHXBsrc
  3042. Func: CopyDHXBsrc      Pack: CopyPack           Func:  16/Mid-level
  3043. DIM CP AS CopyPack
  3044. DIM TempStr AS STRING * 80      'used as fixed-length string for VARPTR()
  3045. TempStr = filename$ + CHR$(0)   'assign filename to a fixed-len string...
  3046. CP.Func = CopyDHXB              'defined in BULLET.BI
  3047. CP.Handle = datahandle          'handle of file to copy from (the source)
  3048. CP.FilenamePtrOff = VARPTR(TempStr) 'far pointer to filenameZ for copy
  3049. CP.FilenamePtrSeg = VARPTR(TempStr) '(the destination)
  3050. stat = BULLET(CP)
  3051. IF stat THEN 'error
  3052. See: ZapDHXBsrc
  3053. ~ZapDHXBsrc
  3054. Func: ZapDHXB          Pack: HandlePack         Func:  17/Mid-level
  3055. DIM HP AS HandlePack
  3056. HP.Func = ZapDHXB               'defined in BULLET.BI
  3057. HP.Handle = datahandle          'handle of file you want !ZAP!
  3058. stat = BULLET(HP)
  3059. IF stat THEN 'error
  3060. Note that this removes ALL data records from the data file.
  3061. See: CreateKXBsrc
  3062. ~CreateKXBsrc
  3063. Func: CreateKXB        Pack: CreateKeyPack      Func:  20/Mid-level
  3064. 'This code assumes that the datafile was created as in CreateDXBsrc, and that
  3065. 'the datafile was opened as in OpenDXBsrc.
  3066. kx$ = "SUBSTR(STUDENT,1,5)"     'key expression, a non-unique, character key
  3067. DIM CKP AS CreateKeyPack
  3068. DIM TempStr AS STRING * 80      'used as fixed-length string for VARPTR()
  3069. DIM TempStr2 AS STRING * 136    'used as fixed-length string for VARPTR()
  3070. TempStr = filename$ + CHR$(0)   'assign filename to a fixed-len string
  3071. TempStr2 = kx$ + CHR$(0)        'same for key expression string
  3072. '(cont)
  3073. See: CreateKXBsrc_a                                                     -MORE-
  3074. ~CreateKXBsrc_a
  3075. CKP.Func = CreateKXB                 'defined in BULLET.BI
  3076. CKP.FilenamePtrOff = VARPTR(TempStr) 'far pointer to filenameZ
  3077. CKP.FilenamePtrSeg = VARSEG(TempStr)
  3078. CKP.KeyExpPtrOff = VARPTR(TempStr2)  'far pointer to key expressionZ
  3079. CKP.KeyExpPtrSeg = VARSEG(TempStr2)
  3080. CKP.XBlink = datahandle              'the datafile handle returned from OpenDXB
  3081. CKP.KeyFlags = cCHAR                 '-KEYFLAGS- are defined in BULLET.BI
  3082. CKP.CodePageID = -1                  'use DOS default code page ID
  3083. CKP.CountryCode = -1                 'use DOS default country code
  3084. CKP.CollatePtrOff = 0                'no user-supplied collate table...
  3085. CKP.CollatePtrSeg = 0                '...
  3086. stat = BULLET(CKP)
  3087. IF stat THEN 'error
  3088. Normally this code would be written as a generalized FUNCTION. The CKP could be
  3089. a global allocation (DIM SHARED CKP AS CreateKeyPack). A possible header:
  3090.  DECLARE FUNCTION CreateNewIndex% (filename$, datahandle, kx$, KeyFlags%)
  3091. To create an index file you'd need just filename, datahandle, key expression,
  3092. and key flags (country code info if not using default), then call the function.
  3093. See: OpenKXBsrc  CreateKXBsrc
  3094. ~OpenKXBsrc
  3095. Func: OpenKXB          Pack: OpenPack           Func:  21/Mid-level
  3096. DIM OP AS OpenPack
  3097. DIM TempStr AS STRING * 80      'used as fixed-length string for VARPTR()
  3098. TempStr = filename$ + CHR$(0)   'assign filename to a fixed-len string...
  3099. OP.Func = OpenKXB                   'defined in BULLET.BI
  3100. OP.FilenamePtrOff = VARPTR(TempStr) 'point to filenameZ (Z=0-terminated str)
  3101. OP.FilenamePtrSeg = VARSEG(TempStr)
  3102. OP.ASmode = ReadWrite + DenyNone    'defined in BULLET.BI
  3103. OP.XBlink = datafilehandle          'OpenKXB needs to know the data file handle
  3104. stat = BULLET(OP)
  3105. IF stat THEN 'error
  3106. The ASmode (access/sharing mode) determines how the operating system controls
  3107. access to the file. See OpenFileDOS for the meanings of the various ASmodes.
  3108. Before you can open an index file you must first open its associated data file.
  3109. See: CloseKXBsrc  OpenFileDOS
  3110. ~CloseKXBsrc
  3111. Func: CloseKXB         Pack: HandlePack         Func:  22/Mid-level
  3112. DIM HP AS HandlePack
  3113. HP.Func = CloseDXB              'defined in BULLET.BI
  3114. HP.Handle = indexhandle         'handle of the file to close
  3115. stat = BULLET(HP)
  3116. IF stat THEN 'error
  3117. See: StatKXBsrc
  3118. ~StatKXBsrc
  3119. Func: StatKXB          Pack: StatKeyPack        Func:  23/Mid-level
  3120. DIM SKP AS StatKeyPack
  3121. SKP.Func = StatKXB          'defined in BULLET.BI
  3122. SKP.Handle = indexhandle    'handle to get stats on
  3123. stat = BULLET(SKP)          'must be index handle, use StatHandleXB if you...
  3124. IF stat = 0 THEN            '...don't know the type of file a handle's for
  3125.    'SKP.FileType is set to 0
  3126.    'SKP.Dirty is set to 1 if the file has changed (0=not changed)
  3127.    'SKP.Keys = number of key in the index file (index file=key file)
  3128.    'SKP.KeyLen = physical key length (1-64 bytes)
  3129.    'SKP.XBlink = datafile handle that this index file is associated with
  3130.    'SKP.XBrecno is set to record number associated with last accessed key
  3131.    'SKP.HereSeg is set to this handle's control segment (location in memory)
  3132.    'SKP.CodePageID returns this index file's permanent code page ID
  3133.    'SKP.CountryCode returns this index file's permanent country code
  3134.    'SKP.CollateTableSize = 0 (no collate table present) or 256 (table present)
  3135.    'SKP.KeyFlags = key flags specifed at CreateKXB (except NLS flag may be set)
  3136. ELSE                                               (NLS flag is bit 14, &H4000)
  3137.    'error
  3138. See: ReadKHXBsrc
  3139. ~ReadKHXBsrc
  3140. Func: ReadKHXB         Pack: HandlePack         Func:  24/Mid-level
  3141. DIM HP AS HandlePack
  3142. HP.Func = ReadKHXB              'defined in BULLET.BI
  3143. HP.Handle = indexhandle         'handle of file whose header you want to reload
  3144. stat = BULLET(HP)
  3145. IF stat THEN 'error
  3146. This routine is automatically called by the network lock routines.
  3147. See: FlushKHXBsrc  LockKeyXB
  3148. ~FlushKHXBsrc
  3149. Func: FlushKHXB        Pack: HandlePack         Func:  25/Mid-level
  3150. DIM HP AS HandlePack
  3151. HP.Func = FlushKHXB             'defined in BULLET.BI
  3152. HP.Handle = indexhandle         'handle of file you want to flush
  3153. stat = BULLET(HP)
  3154. IF stat THEN 'error
  3155. Note that the physical write to disk is performed only if the file has changed
  3156. since the open or last flush.
  3157. This routine is automatically called by the network unlock routines.
  3158. See: CopyKHXBsrc  UnlockKeyXB
  3159. ~CopyKHXBsrc
  3160. Func: CopyKHXBsrc      Pack: CopyPack           Func:  26/Mid-level
  3161. DIM CP AS CopyPack
  3162. DIM TempStr AS STRING * 80      'used as fixed-length string for VARPTR()
  3163. TempStr = filename$ + CHR$(0)   'assign filename to a fixed-len string...
  3164. CP.Func = CopyKHXB              'defined in BULLET.BI
  3165. CP.Handle = indexhandle         'handle of file to copy from (the source)
  3166. CP.FilenamePtrOff = VARPTR(TempStr) 'far pointer to filenameZ for copy
  3167. CP.FilenamePtrSeg = VARPTR(TempStr) '(the destination)
  3168. stat = BULLET(CP)
  3169. IF stat THEN 'error
  3170. See: ZapKHXBsrc
  3171. ~ZapKHXBsrc
  3172. Func: ZapKHXB          Pack: HandlePack         Func:  27/Mid-level
  3173. DIM HP AS HandlePack
  3174. HP.Func = ZapKHXB               'defined in BULLET.BI
  3175. HP.Handle = indexhandle         'handle of file you want !ZAP!
  3176. stat = BULLET(HP)
  3177. IF stat THEN 'error
  3178. Note that this removes ALL keys from the index file.
  3179. See: GetDescriptorXBsrc
  3180. ~GetDescriptorXBsrc
  3181. Func: GetDescriptorXB  Pack: DescriptorPack     Func:  30/Mid-level
  3182. DIM DP AS DescriptorPack
  3183. DP.Func = GetDescriptorXB               'defined in BULLET.BI
  3184. DP.Handle = datahandle                  'handle of file
  3185. IF FieldNumber > 0 THEN
  3186.    DP.FieldNumber = FieldNumber         'field number to get info on
  3187. ELSE                                    'or, if 0, then
  3188.    DP.FieldNumber = 0
  3189.    DP.FD.FieldName = fieldname$ + STRING$(10,0)   'fieldname$ to get info on
  3190. ENDIF
  3191. stat = BULLET(DP)
  3192. IF stat = 0 THEN
  3193.    'DP.FD.FieldName is set to field name
  3194.    'DP.FD.FieldType is set to field type
  3195.    'DP.FD.FieldLen is set to field length
  3196.    'DP.FD.FieldDC is set to field DC
  3197. ELSE         
  3198.    'error    
  3199. The DP.FD.FieldLen (and DP.FD.FieldDC) is a byte string so you 
  3200.              
  3201. need to use a FldLen=ASC(DP.FD.FieldLen) for its integer value 
  3202.              
  3203. See: GetRecordXBsrc
  3204. ~GetRecordXBsrc
  3205. Func: GetRecordXB      Pack: AccessPack         Func:  31/Mid-level
  3206. TYPE RecordTYPE                 'simple DBF record layout
  3207. tag AS STRING * 1  <
  3208. code AS STRING * 4     
  3209. THE FIRST BYTE OF YOUR RECORD TYPES MUST BE TAG! 
  3210. bday AS STRING * 8     
  3211. END TYPE
  3212. DIM RecBuff AS RecordTYPE       'record has 2 fields, code/C/4.0, bday/D/8.0
  3213. DIM AP AS AccessPack
  3214. AP.Func = GetRecordXB           'defined in BULLET.BI
  3215. AP.Handle = datahandle          'handle to get record from
  3216. AP.RecNo = RecnoToGet&          'record number to get
  3217. AP.RecPtrOff = VARPTR(RecBuff)  'read record from disk into RecBuff
  3218. AP.RecPtrSeg = VARSEG(RecBuff)
  3219. stat = BULLET(AP)
  3220. IF stat = 0 THEN
  3221.    PRINT RecBuff.code ; ", " ; RecBuff.bday     'sample output: 4321, 19331122
  3222.    'error
  3223. See: AddRecordXBsrc
  3224. ~AddRecordXBsrc
  3225. Func: AddRecordXB      Pack: AccessPack         Func:  32/Mid-level
  3226. TYPE RecordTYPE                 'simple DBF record layout
  3227. tag AS STRING * 1  <
  3228. code AS STRING * 4     
  3229. THE FIRST BYTE OF YOUR RECORD TYPES MUST BE TAG! 
  3230. bday AS STRING * 8     
  3231. END TYPE
  3232. DIM RecBuff AS RecordTYPE       'record has 2 fields, code/C/4.0, bday/D/8.0
  3233. DIM AP AS AccessPack
  3234. 'be sure to init the tag field to a space (ASCII 32)
  3235. RecBuff.tag = " " : RecBuff.code = "1234" : RecBuff.bday = "19331122"
  3236. AP.Func = AddRecordXB           'defined in BULLET.BI
  3237. AP.Handle = datahandle          'handle to add record to
  3238. AP.RecPtrOff = VARPTR(RecBuff)  'write record from RecBuff to disk...
  3239. AP.RecPtrSeg = VARSEG(RecBuff)  '...at next available record number
  3240. stat = BULLET(AP)
  3241. IF stat = 0 THEN
  3242.    PRINT "Record number used by AddRecordXB was "; AP.RecNo
  3243. ELSE 'error
  3244. See: UpdateRecordXBsrc
  3245. ~UpdateRecordXBsrc
  3246. Func: UpdateRecordXB   Pack: AccessPack         Func:  33/Mid-level
  3247. 'see GetRecordXBsrc for this source example's preliminary code
  3248. AP.Func = GetRecordXB           'first get the record to update
  3249. AP.Handle = datahandle
  3250. AP.RecNo = RecnoToGet&          '
  3251. AP.RecPtrOff = VARPTR(RecBuff)  '
  3252.  Do NOT use UpdateRecordXB to change   
  3253. AP.RecPtrSeg = VARSEG(RecBuff)  '
  3254.  any field(s) used in a key expression.
  3255. stat = BULLET(AP)               '
  3256.  Instead use UpdateXB.                 
  3257. IF stat = 0 THEN                '
  3258.    RecBuff.dbay = "19591122"    'change only non-key portions of record
  3259.    AP.Func = UpdateRecordXB     'defined in BULLET.BI
  3260.    stat = BULLET(AP)            'other AP. values are already set from the Get
  3261.    IF stat THEN                 'though you should reassign AP.RecPtrOff/Seg if
  3262.       'error                    'you perform any BASIC string functions between
  3263. 'BULLET calls (none were in this case).
  3264. NOTE: QB/PDS will move strings
  3265. '--by this I mean to set these again
  3266. after a user-break/Ctrl-Break 
  3267. '  AP.RecPtrOff = VARPTR(RecBuff)
  3268. in the QB/QBX environment !!! 
  3269. '  AP.RecPtrSeg = VARSEG(RecBuff)
  3270. '  stat = BULLET(AP) 'do the update call
  3271. See: DeleteRecordXBsrc  UpdateXB
  3272. ~DeleteRecordXBsrc
  3273. Func: DeleteRecordXB   Pack: AccessPack         Func:  34/Mid-level
  3274. DIM AP AS AccessPack
  3275. AP.Func = DeleteRecordXB        'defined in BULLET.BI
  3276. AP.Handle = datahandle          'handle of record to delete
  3277. AP.RecNo = RecnoToDelete&       'to determine which record number any record
  3278. stat = BULLET(AP)               'is, use one of the keyed access routines
  3279. IF stat THEN 'error
  3280. See: UndeleteRecordsrc (XB)
  3281. ~UndeleteRecordsrc (XB)
  3282. Func: UndeleteRecordXB Pack: AccessPack         Func:  35/Mid-level
  3283. DIM AP AS AccessPack
  3284. AP.Func = UndeleteRecordXB      'defined in BULLET.BI
  3285. AP.Handle = datahandle          'handle of record to undelete
  3286. AP.RecNo = RecnoToUndelete&     'to determine which record number any record
  3287. stat = BULLET(AP)               'is use one of the keyed access routines
  3288. IF stat THEN 'error
  3289. See: PackRecordsXBsrc
  3290. ~PackRecordsXBsrc
  3291. Func: PackRecordsXB    Pack: AccessPack         Func:  36/Mid-level
  3292. DIM AP AS AccessPack
  3293. AP.Func = PackRecordsXB         'defined in BULLET.BI
  3294. AP.Handle = datahandle          'handle of data file to pack
  3295. stat = BULLET(AP)
  3296. IF stat THEN 'error
  3297. See: FirstKeyXBsrc
  3298. ~FirstKeyXBsrc
  3299. Func: FirstKeyXB       Pack: AccessPack         Func:  40/Mid-level
  3300. DIM AP AS AccessPack
  3301. DIM TempStr AS STRING * 64      'used as fixed-length string for VARPTR()
  3302.                                 'needs to be at least key length (MAXKEYLEN=64)
  3303. AP.Func = FirstKeyXB            'defined in BULLET.BI
  3304. AP.Handle = indexhandle         'handle to index file to access key from
  3305. AP.KeyPtrOff = VARPTR(TempStr)  'far pointer to key buffer
  3306. AP.KeyPtrSeg = VARSEG(TempStr)  '(the first key is read from disk and put here)
  3307. stat = BULLET(AP)
  3308. IF stat = 0 THEN
  3309.    'TempStr is filled in with the key (for as many bytes as the key length)
  3310.    'so, if the key is a character type, you could PRINT LEFT$(TempStr,KeyLen)
  3311.    'or, if key is a 32-bit LONG then PRINT CVL(LEFT$(TempStr,4)). When using
  3312.    'the key returned, be aware that if UNIQUE was NOT specified then the
  3313.    'enumerator word is attached to the end of the key (the right two bytes).
  3314.    'Also, AP.RecNo is set to the record number of the first key in the index.
  3315.    'error
  3316. See: EqualKeyXBsrc
  3317. ~EqualKeyXBsrc
  3318. Func: EqualKeyXB       Pack: AccessPack         Func:  41/Mid-level
  3319. DIM AP AS AccessPack
  3320. DIM TempStr AS STRING * 64      'used as fixed-length string for VARPTR()
  3321.                                 'passed key to find, start with enum=0
  3322. TempStr = FindKey$ + CHR$(0) + CHR$(0) + CHR$(0) '2 enumerator bytes + 0-term
  3323. AP.Func = EqualKeyXB            'defined in BULLET.BI
  3324. AP.Handle = indexfile           'handle to index file to find key from
  3325. AP.KeyPtrOff = VARPTR(TempStr)  'far pointer to key buffer
  3326. AP.KeyPtrSeg = VARSEG(TempStr)
  3327. stat = BULLET(AP)
  3328. IF stat = 0 THEN
  3329.    'the key matched exactly (including enumerator, if present)
  3330.    'TempStr is NOT ALTERED
  3331.    'AP.RecNo is set to the record number of that key
  3332. ELSEIF stat = 200 THEN
  3333.    AP.Func = NextKeyXB          'if not found, get following key and check the
  3334.    stat = BULLET(AP)            'key proper (key less the enumerator bytes)
  3335.    IF stat = 0 THEN             '(i.e., it may be proper key but enumerator=1)
  3336.       'see NextKeyXBsrc for continuation
  3337. See: NextKeyXBsrc
  3338. ~NextKeyXBsrc
  3339. Func: NextKeyXB        Pack: AccessPack         Func:  42/Mid-level
  3340. 'see EqualKeyXBsrc for preliminary code
  3341. AP.Func = NextKeyXB             'defined in BULLET.BI
  3342. stat = BULLET(AP)               'KEYLEN assumed to equal actual key length...
  3343. IF stat = 0 THEN                '...as returned by StatKXB
  3344.     IF IndexFileIsNotUnique THEN
  3345.        IF LEFT$(TempStr,KeyLen-2) = FindKey$ THEN 'the next key matches!
  3346.                                                   '(except for the enumerator)
  3347. This code example follows up on the EqualKeyXBsrc example. See EqualKeyXB for
  3348. more information on finding partial keys.
  3349. See: PrevKeyXBsrc  EqualKeyXBsrc
  3350. ~PrevKeyXBsrc
  3351. Func: PrevKeyXB        Pack: AccessPack         Func:  43/Mid-level
  3352. DIM AP AS AccessPack
  3353. DIM TempStr AS STRING * 64      'used as fixed-length string for VARPTR()
  3354. 'assume code has already executed to locate a key--this code then gets the key
  3355. 'before that one
  3356. AP.Func = PrevKeyXB             'defined in BULLET.BI
  3357. AP.Handle = indexfile           'handle to index file to access key from
  3358. AP.KeyPtrOff = VARPTR(TempStr)  'far pointer to key buffer
  3359. AP.KeyPtrSeg = VARSEG(TempStr)  '(the prev key is read from disk and put here)
  3360. stat = BULLET(AP)
  3361. IF stat = 0 THEN
  3362.    'TempStr is filled in with the key (for as many bytes as the key length).
  3363.    'Also, AP.RecNo is set to the record number of the key.
  3364.    'error
  3365. See: LastKeyXBsrc
  3366. ~LastKeyXBsrc
  3367. Func: LastKeyXB        Pack: AccessPack         Func:  44/Mid-level
  3368. DIM AP AS AccessPack
  3369. DIM TempStr AS STRING * 64      'used as fixed-length string for VARPTR()
  3370. AP.Func = LastKeyXB             'defined in BULLET.BI
  3371. AP.Handle = indexfile           'handle to index file to access key from
  3372. AP.KeyPtrOff = VARPTR(TempStr)  'far pointer to key buffer
  3373. AP.KeyPtrSeg = VARSEG(TempStr)  '(the last key is read from disk and put here)
  3374. stat = BULLET(AP)
  3375. IF stat = 0 THEN
  3376.    'TempStr is filled in with the key (for as many bytes as the key length)
  3377.    'AP.RecNo is set to the record number of the last key.
  3378.    'error
  3379. See: StoreKeyXBsrc
  3380. ~StoreKeyXBsrc
  3381. Func: StoreKeyXB       Pack: AccessPack         Func:  45/Mid-level
  3382. DIM AP AS AccessPack
  3383. DIM TempStr AS STRING * 64      'used as fixed-length string for VARPTR()
  3384. 'Assume record has been added to data file (AddRecordXB, returning RecNo2Use)
  3385. 'and key has been built (BuildKeyXB returning KeyToAdd$).
  3386.               
  3387. TempStr = KeyToAdd$ + CHR$(0)   'add the key to a UNIQUE index file
  3388. AP.Func = StoreKeyXB            'defined in BULLET.BI
  3389. AP.Handle = indexfile           'handle to index file to insert key into
  3390. AP.RecNo = RecNo2Use            'associate this record number with key
  3391. AP.KeyPtrOff = VARPTR(TempStr)  'far pointer to key buffer
  3392. AP.KeyPtrSeg = VARSEG(TempStr)  '(the last key is read from disk and put here)
  3393. stat = BULLET(AP)
  3394. IF stat = 0 THEN
  3395.    'key added
  3396. ELSEIF stat = 201 THEN
  3397.    'key already exists, which means you need to construct a unique enumerator--
  3398.    'provided the file wasn't created for UNIQUE keys...INSTEAD USE InsertXB!
  3399. See: DeleteKeyXBsrc  InsertXB
  3400. ~DeleteKeyXBsrc
  3401. Func: DeleteKeyXB      Pack: AccessPack         Func:  46/Mid-level
  3402. DIM AP AS AccessPack
  3403. DIM TempStr AS STRING * 64      'used as fixed-length string for VARPTR()
  3404. TempStr = KeyToDelete$ + CHR$(0)   'delete the key from a UNIQUE index file
  3405.                                    '(else need to supply enumerator also)
  3406. AP.Func = DeleteKeyXB           'defined in BULLET.BI
  3407. AP.Handle = indexfile           'handle to index file of key to delete
  3408. AP.KeyPtrOff = VARPTR(TempStr)  'far pointer to key buffer
  3409. AP.KeyPtrSeg = VARSEG(TempStr)  '(this key is searched for exactly)
  3410. stat = BULLET(AP)               'if exact match found the key is deleted!
  3411. IF stat = 0 THEN
  3412.    'key deleted permanently
  3413. ELSEIF stat = 200 THEN
  3414.    'key as stated was not in the index file--if the index is not UNQIUE then
  3415.    'you must supply the exact enumerator along with the key proper to delete
  3416.    '--you can use the CurrentKeyXB routine to obtain the exact current key
  3417.    'other error
  3418. See: BuildKeyXBsrc
  3419. ~BuildKeyXBsrc
  3420. Func: BuildKeyXB       Pack: AccessPack         Func:  47/Mid-level
  3421. DIM AP AS AccessPack
  3422. DIM TempStr AS STRING * 64      'used as fixed-length string for VARPTR()
  3423. 'Assume record has been built and is ready to be added to the data file. The
  3424. 'record is in the variable RecBuff (a fixed-length TYPE variable, typically).
  3425. AP.Func = BuildKeyXB            'defined in BULLET.BI
  3426. AP.Handle = indexfile           'handle to index file key is to be built for
  3427. AP.RecPtrOff = VARPTR(RecBuff)  'far pointer to data record buffer
  3428. AP.RecPtrSeg = VARSEG(RecBuff)
  3429. AP.KeyPtrOff = VARPTR(TempStr)  'far pointer to key buffer
  3430. AP.KeyPtrSeg = VARSEG(TempStr)  '(the built key is put here)
  3431. stat = BULLET(AP)
  3432. IF stat = 0 THEN
  3433.    'key built okay so can do a AddRecordXB followed by a StoreKeyXB
  3434.    'but, again, InsertXB takes care of all this detail and then some--use it
  3435.    'error
  3436. See: CurrentKeyXBsrc
  3437. ~CurrentKeyXBsrc
  3438. Func: CurrentKeyXB     Pack: AccessPack         Func:  48/Mid-level
  3439. DIM AP AS AccessPack
  3440. DIM TempStr AS STRING * 64      'used as fixed-length string for VARPTR()
  3441. AP.Func = CurrentKeyXB          'defined in BULLET.BI
  3442. AP.Handle = indexfile           'handle to index file
  3443. AP.KeyPtrOff = VARPTR(TempStr)  'far pointer to key buffer
  3444. AP.KeyPtrSeg = VARSEG(TempStr)  '(the current key is put here)
  3445. stat = BULLET(AP)
  3446. IF stat = 0 THEN
  3447.    'TempStr set to current key (valid only for KeyLen bytes)
  3448.    'Also, AP.RecNo is set to the record number of the key.
  3449.    'error
  3450. See: GetFirstXBsrc
  3451. ~GetFirstXBsrc
  3452. Func: GetFirstXB       Pack: AccessPack         Func:  60/High-level
  3453. DIM AP AS AccessPack
  3454. DIM TempStr AS STRING * 64      'used as fixed-length string for VARPTR()
  3455. DIM RecBuff AS RecordTYPE       'see AddRecordXBsrc for record layout
  3456. AP.Func = GetFirstXB            'defined in BULLET.BI
  3457. AP.Handle = indexhandle         'handle to index file to access key from
  3458. AP.RecPtrOff = VARPTR(RecBuff)  'far pointer to record buffer
  3459. AP.RecPtrSeg = VARSEG(RecBuff)  '(the record indexed by the key is put here)
  3460. AP.KeyPtrOff = VARPTR(TempStr)  'far pointer to key buffer
  3461. AP.KeyPtrSeg = VARSEG(TempStr)  '(the first key is read from disk and put here)
  3462. stat = BULLET(AP)
  3463. IF stat = 0 THEN
  3464.    'TempStr is filled in with the key (for as many bytes as the key length)
  3465.    'RecBuff is filled in with the data record
  3466.    'AP.RecNo is set to the record number of the first key in the index.
  3467.    'error
  3468. See: GetEqualXBsrc
  3469. ~GetEqualXBsrc
  3470. Func: GetEqualXB       Pack: AccessPack         Func:  61/High-level
  3471. DIM AP AS AccessPack
  3472. DIM TempStr AS STRING * 64      'used as fixed-length string for VARPTR()
  3473. DIM RecBuff AS RecordTYPE       'see AddRecordXBsrc for record layout
  3474.                                 'passed key to find, start with enum=0
  3475. TempStr = FindKey$ + CHR$(0) + CHR$(0) + CHR$(0) '2 enumerator bytes + 0-term
  3476. AP.Func = GetEqualXB            'defined in BULLET.BI
  3477. AP.Handle = indexfile           'handle to index file to find key from
  3478. AP.RecPtrOff = VARPTR(RecBuff)  'far pointer to record buffer
  3479. AP.RecPtrSeg = VARSEG(RecBuff)  '(the record indexed by the key is put here)
  3480. AP.KeyPtrOff = VARPTR(TempStr)  'far pointer to key buffer
  3481. AP.KeyPtrSeg = VARSEG(TempStr)
  3482. stat = BULLET(AP)
  3483. IF stat = 0 THEN
  3484.    'RecBuff, and AP.RecNo filled as expected (TempStr remains the same)
  3485. ELSEIF stat = 200 THEN
  3486.    AP.Func = GetNextXB          'if not found, can get following key--the next
  3487.    stat = BULLET(AP)            'key would logically follow the key not found
  3488.                                 '--this let's you search based on partial keys
  3489. See: GetNextXBsrc
  3490. ~GetNextXBsrc
  3491. Func: GetNextXB        Pack: AccessPack         Func:  62/High-level
  3492. DIM AP AS AccessPack
  3493. DIM TempStr AS STRING * 64      'used as fixed-length string for VARPTR()
  3494. DIM RecBuff AS RecordTYPE       'see AddRecordXBsrc for record layout
  3495. AP.Func = GetFirstXB            'defined in BULLET.BI
  3496. AP.Handle = indexhandle         'handle to index file to access key from
  3497. AP.RecPtrOff = VARPTR(RecBuff)  'far pointer to record buffer
  3498. AP.RecPtrSeg = VARSEG(RecBuff)  '(the record indexed by the key is put here)
  3499. AP.KeyPtrOff = VARPTR(TempStr)  'far pointer to key buffer
  3500. AP.KeyPtrSeg = VARSEG(TempStr)  '(the first key is read from disk and put here)
  3501. stat = BULLET(AP)
  3502. DO WHILE stat = 0               'print all records in key order
  3503.    PRINT AP.RecNo; RecBuff.code; ", "; RecBuff.bday
  3504.    AP.Func = GetNextXB
  3505.    stat = BULLET(AP)
  3506. IF stat <> 202 THEN             'error 202 means end of file (expected)
  3507.    'error other than expected EOF
  3508. See: GetPrevXBsrc
  3509. ~GetPrevXBsrc
  3510. Func: GetPrevXB        Pack: AccessPack         Func:  63/High-level
  3511. DIM AP AS AccessPack
  3512. DIM TempStr AS STRING * 64      'used as fixed-length string for VARPTR()
  3513. DIM RecBuff AS RecordTYPE       'see AddRecordXBsrc for record layout
  3514. AP.Func = GetLastXB             'defined in BULLET.BI
  3515. AP.Handle = indexhandle         'handle to index file to access key from
  3516. AP.RecPtrOff = VARPTR(RecBuff)  'far pointer to record buffer
  3517. AP.RecPtrSeg = VARSEG(RecBuff)  '(the record indexed by the key is put here)
  3518. AP.KeyPtrOff = VARPTR(TempStr)  'far pointer to key buffer
  3519. AP.KeyPtrSeg = VARSEG(TempStr)  '(the last key is read from disk and put here)
  3520. stat = BULLET(AP)
  3521. DO WHILE stat = 0               'print all records in REVERSE key order
  3522.    PRINT AP.RecNo; RecBuff.code; ", "; RecBuff.bday
  3523.    AP.Func = GetPrevXB
  3524.    stat = BULLET(AP)
  3525. IF stat <> 203 THEN             'error 203 means top of file (expected)
  3526.    'error other than expected TOF
  3527. See: GetLastXBsrc
  3528. ~GetLastXBsrc
  3529. Func: GetLastXB        Pack: AccessPack         Func:  64/High-level
  3530. DIM AP AS AccessPack
  3531. DIM TempStr AS STRING * 64      'used as fixed-length string for VARPTR()
  3532. DIM RecBuff AS RecordTYPE       'see AddRecordXBsrc for record layout
  3533. AP.Func = GetLastXB             'defined in BULLET.BI
  3534. AP.Handle = indexhandle         'handle to index file to access key from
  3535. AP.RecPtrOff = VARPTR(RecBuff)  'far pointer to record buffer
  3536. AP.RecPtrSeg = VARSEG(RecBuff)  '(the record indexed by the key is put here)
  3537. AP.KeyPtrOff = VARPTR(TempStr)  'far pointer to key buffer
  3538. AP.KeyPtrSeg = VARSEG(TempStr)  '(the last key is read from disk and put here)
  3539. stat = BULLET(AP)
  3540. IF stat = 0 THEN
  3541.    'TempStr is filled in with the key (for as many bytes as the key length)
  3542.    'RecBuff is filled in with the data record
  3543.    'AP.RecNo is set to the record number of the last key in the index.
  3544.    'error
  3545. See: InsertXBsrc
  3546. ~InsertXBsrc
  3547. Func: InsertXB         Pack: AccessPack         Func:  65/High-level
  3548. REDIM AP(1 TO 4) AS AccessPack  'array of 3 access packs, 1 for each index file
  3549.                                 'TempStr and RecBuff previously defined
  3550. FOR i = 1 TO 3                  '3=number of related indexes to maintain
  3551.    AP(i).Func = InsertXB
  3552.    AP(i).Handle = indexhandle(i)          'each index file's handle
  3553.    AP(i).RecPtrOff = VARPTR(RecBuff) 
  3554.    AP(i).RecPtrSeg = VARSEG(RecBuff) 
  3555.  see AddRecordXBsrc for RecBuff TYPE 
  3556.    AP(i).KeyPtrOff = VARPTR(TempStr) 
  3557. (be sure you reserved the tag field) 
  3558.    AP(i).KeyPtrSeg = VARSEG(TempStr) 
  3559.    AP(i).NextPtrOff = VARPTR(AP(i + 1))   'point to NEXT access pack
  3560.    AP(i).NextPtrSeg = VARSEG(AP(i + 1))   'AP(1 TO 4) to avoid subscript error
  3561. AP(3).NextPtrOff = 0            'reset last access pack to end-link value
  3562. AP(3).NextPtrSeg = 0
  3563. stat = BULLET(AP(1))
  3564. IF stat = 0 THEN                'if stat=0 must still check AP(1).Stat
  3565.    IF AP(1).Stat <> 0 THEN      'error when adding data record (check first AP)
  3566.    TrueError = AP(stat).Stat    'the returned stat is array index of bad pack
  3567.                                 '(returned stat is 1-based, so 1=first)
  3568. See: UpdateXBsrc
  3569. ~UpdateXBsrc
  3570. Func: UpdateXB         Pack: AccessPack         Func:  66/High-level
  3571. REDIM AP(1 TO 4) AS AccessPack  'array of 3 access packs, 1 for each index file
  3572.                                 'TempStr and RecBuff previously defined
  3573. FOR i = 1 TO 3                  '3=number of related indexes to maintain
  3574.    AP(i).Func = UpdateXB
  3575.    AP(i).Handle = indexhandle(i)          'each index file's handle
  3576.    AP(i).RecNo = RecordNumberToUpdate&    'tell it which record to update
  3577.    AP(i).RecPtrOff = VARPTR(RecBuff)      'RecBuff has new, updated data
  3578.    AP(i).RecPtrSeg = VARSEG(RecBuff)
  3579.    AP(i).KeyPtrOff = VARPTR(TempStr)
  3580.    AP(i).KeyPtrSeg = VARSEG(TempStr)
  3581.    AP(i).NextPtrOff = VARPTR(AP(i + 1))   'point to NEXT access pack
  3582.    AP(i).NextPtrSeg = VARSEG(AP(i + 1))   'AP(1 TO 4) to avoid subscript error
  3583. AP(3).NextPtrOff = 0 : AP(3).NextPtrSeg = 0 'reset last access pack to 0
  3584. stat = BULLET(AP(1))
  3585. IF stat = 0 THEN                'if stat=0 must still check AP(1).Stat
  3586.    IF AP(1).Stat <> 0 THEN      'error when writing data record (check 1st AP)
  3587.    TrueError = AP(stat).Stat    'the returned stat is array index of bad pack
  3588.                                 '(returned stat is 1-based, so 1=first)
  3589. See: ReindexXBsrc
  3590. ~ReindexXBsrc
  3591. Func: ReindexXB        Pack: AccessPack         Func:  67/High-level
  3592. REDIM AP(1 TO 4) AS AccessPack  'array of 3 access packs, 1 for each index file
  3593.                                 'DIM'd to 4 to avoid bad subscript in loop
  3594. FOR i = 1 TO 3                  '3=number of related indexes to reindex
  3595.    AP(i).Func = ReindexXB
  3596.    AP(i).Handle = indexhandle(i)          'each index file's handle
  3597.    AP(i).NextPtrOff = VARPTR(AP(i + 1))   'point to NEXT access pack
  3598.    AP(i).NextPtrSeg = VARSEG(AP(i + 1))   'AP(1 TO 4) to avoid subscript error
  3599. AP(3).NextPtrOff = 0
  3600. AP(3).NextPtrSeg = 0            'reset last access pack to end-link value
  3601. stat = BULLET(AP(1))
  3602. IF stat THEN                    'if stat <> 0 then the...
  3603.    TrueError = AP(stat).Stat    '...returned stat is array index of bad pack
  3604. The reason AP() is REDIM AP(1 TO 4) is so that the AP(i + 1) in the code loop
  3605. doesn't create an invalid subscript error.  Also note that the returned stat 
  3606. value is a 1-based index of the AP() pack that failed.                       
  3607. See: LockXBsrc
  3608. ~LockXBsrc
  3609. Func: LockXB           Pack: AccessPack         Func:  80/Network
  3610. REDIM AP(1 TO 4) AS AccessPack  'array of 3 access packs, 1 for each index file
  3611.                                 'DIM'd to 4 to avoid bad subscript in loop
  3612. FOR i = 1 TO 3                  '3=number of related indexes to Lock
  3613.    AP(i).Func = LockXB
  3614.    AP(i).Handle = indexhandle(i)          'each index file's handle
  3615.    AP(i).NextPtrOff = VARPTR(AP(i + 1))   'point to NEXT access pack
  3616.    AP(i).NextPtrSeg = VARSEG(AP(i + 1))
  3617. NEXT                            'data file handle known internally by BULLET
  3618. AP(3).NextPtrOff = 0
  3619. AP(3).NextPtrSeg = 0            'reset last access pack to end-link value
  3620. stat = BULLET(AP(1))
  3621. IF stat > 3 THEN                'if stat > 3 (> number of packs) then the...
  3622.    TrueError = AP(3).Stat       '...lock failed on data file (check last AP)
  3623. ELSEIF stat <> 0 THEN                                          (|last ReadKHXB)
  3624.    TrueError = AP(stat).Stat    '...lock failed on index file # stat
  3625. The Lock routines use a different method to identify the bad pack when the   
  3626. failure was caused by the data file. See above.                              
  3627. See: UnlockXBsrc
  3628. ~UnlockXBsrc
  3629. Func: UnlockXB         Pack: AccessPack         Func:  81/Network
  3630. REDIM AP(1 TO 4) AS AccessPack  'array of 3 access packs, 1 for each index file
  3631.                                 'DIM'd to 4 to avoid bad subscript in loop
  3632. FOR i = 1 TO 3                  '3=number of related indexes to Lock
  3633.    AP(i).Func = UnlockXB
  3634.    AP(i).Handle = indexhandle(i)          'each index file's handle
  3635.    AP(i).NextPtrOff = VARPTR(AP(i + 1))   'point to NEXT access pack
  3636.    AP(i).NextPtrSeg = VARSEG(AP(i + 1))
  3637. NEXT                            'data file handle known internally by BULLET
  3638. AP(3).NextPtrOff = 0
  3639. AP(3).NextPtrSeg = 0            'reset last access pack to end-link value
  3640. stat = BULLET(AP(1))
  3641. IF stat > 3 THEN                'if stat > 3 (> number of packs) then the...
  3642.    TrueError = AP(3).Stat       '...unlock failed on data file (check last AP)
  3643. ELSEIF stat <> 0 THEN
  3644.    TrueError = AP(stat).Stat    '...unlock failed on index file # stat
  3645. The Lock routines use a different method to identify the bad pack when the   
  3646. failure was caused by the data file. See above.                              
  3647. See: LockKeyXBsrc
  3648. ~LockKeyXBsrc
  3649. Func: LockKeyXB        Pack: AccessPack         Func:  82/Network
  3650. REDIM AP(1 TO 4) AS AccessPack  'array of 3 access packs, 1 for each index file
  3651.                                 'DIM'd to 4 to avoid bad subscript in loop
  3652. FOR i = 1 TO 3                  '3=number of related indexes to Lock
  3653.    AP(i).Func = LockXB
  3654.    AP(i).Handle = indexhandle(i)          'each index file's handle
  3655.    AP(i).NextPtrOff = VARPTR(AP(i + 1))   'point to NEXT access pack
  3656.    AP(i).NextPtrSeg = VARSEG(AP(i + 1))
  3657. AP(3).NextPtrOff = 0
  3658. AP(3).NextPtrSeg = 0            'reset last access pack to end-link value
  3659. stat = BULLET(AP(1))
  3660. IF stat <> 0 THEN
  3661.    TrueError = AP(stat).Stat    'lock failed on index file # stat
  3662.                                 '--if stat > 3 then failed on last internal
  3663.                                 '--ReadKHXB...This is EXTREMELY unlikely
  3664. See: UnlockKeyXBsrc
  3665. ~UnlockKeyXBsrc
  3666. Func: UnlockKeyXB      Pack: AccessPack         Func:  83/Network
  3667. REDIM AP(1 TO 4) AS AccessPack  'array of 3 access packs, 1 for each index file
  3668.                                 'DIM'd to 4 to avoid bad subscript in loop
  3669. FOR i = 1 TO 3                  '3=number of related indexes to Lock
  3670.    AP(i).Func = UnlockKeyXB
  3671.    AP(i).Handle = indexhandle(i)          'each index file's handle
  3672.    AP(i).NextPtrOff = VARPTR(AP(i + 1))   'point to NEXT access pack
  3673.    AP(i).NextPtrSeg = VARSEG(AP(i + 1))
  3674. AP(3).NextPtrOff = 0
  3675. AP(3).NextPtrSeg = 0            'reset last access pack to end-link value
  3676. stat = BULLET(AP(1))
  3677. IF stat <> 0 THEN
  3678.    TrueError = AP(stat).Stat    'unlock failed on index file # stat
  3679. See: LockDataXBsrc
  3680. ~LockDataXBsrc
  3681. Func: LockDataXB       Pack: AccessPack         Func:  84/Network
  3682. DIM AP AS AccessPack
  3683. AP.Func = LockDataXB            'defined in BULLET.BI
  3684. AP.Handle = datahandle          'handle of data file to lock
  3685. AP.RecNo = 0&                   '=0 to lock all or, set to actual record number
  3686. stat = BULLET(AP)               '   to lock as in AP.RecNo = lockThisRec&
  3687. IF stat THEN 'error
  3688. See: UnlockDataXBsrc
  3689. ~UnlockDataXBsrc
  3690. Func: UnlockDataXB     Pack: AccessPack         Func:  85/Network
  3691. DIM AP AS AccessPack
  3692. AP.Func = UnlockDataXB          'defined in BULLET.BI
  3693. AP.Handle = datahandle          'handle of data file to unlock
  3694. AP.RecNo = 0&                   '=0 to unlock all or, set to actual record num
  3695. stat = BULLET(AP)               '   to unlock as in AP.RecNo = lockThisRec&
  3696. IF stat THEN 'error
  3697.                                 'note: you cannot unlock parts of a file with
  3698.                                 '1 single unlock (where AP.RecNo=0). Instead,
  3699.                                 'you must unlock each record individually--
  3700.                                 'that is, if you made any single-record locks
  3701. See: DriveRemoteXBsrc
  3702. ~DriveRemoteXBsrc
  3703. Func: DriveRemoteXB    Pack: RemotePack         Func:  86/Network
  3704. DIM RP AS RemotePack
  3705. RP.Func = DriveRemoteXB         'defined in BULLET.BI
  3706. RP.Handle = drive2check         'drive to check (0=default, 1=A:,2=B:,3=C:...)
  3707. stat = BULLET(RP)
  3708. IF stat = 0 THEN
  3709.    'RP.IsRemote set to 0 if drive local, 1 if remote
  3710.    'RP.Flags set to DX register as returned by DOS
  3711.    'RP.IsShare set to 0 if SHARE.EXE is not loaded, non-zero SHARE installed
  3712.   'error  (like invalid drive)
  3713. See: FileRemoteXBsrc
  3714. ~FileRemoteXBsrc
  3715. Func: FileRemoteXB     Pack: RemotePack         Func:  87/Network
  3716. DIM RP AS RemotePack
  3717. RP.Func = FileRemoteXB          'defined in BULLET.BI
  3718. RP.Handle = filehandle          'file handle to check
  3719. stat = BULLET(RP)
  3720. IF stat = 0 THEN
  3721.    'RP.IsRemote set to 0 if file local, 1 if remote
  3722.    'RP.Flags set to DX register as returned by DOS
  3723.    'RP.IsShare set to 0 if SHARE.EXE is not loaded, non-zero SHARE installed
  3724.   'error  (like invalid handle)
  3725. See: SetRetriesXBsrc
  3726. ~SetRetriesXBsrc
  3727. Func: SetRetriesXB     Pack: SetRetriesPack     Func:  88/Network
  3728. DIM SRP AS SetRetriesPack
  3729. SRP.Func = SetRetriesXB
  3730. SRP.Mode = 1             '1=set to user values, 0=set DOS default
  3731. SRP.Pause = 5000         'do 5,000 loops between retries
  3732. SRP.Retries = 5          'try 5 times before giving up with error
  3733. stat = BULLET(SRP)
  3734. IF stat THEN
  3735.    'error                'it's unlikely an error occurs
  3736. See: DeleteFileDOSsrc
  3737. ~DeleteFileDOSsrc
  3738. Func: DeleteFileDOS    Pack: DOSFilePack        Func: 100/DOS
  3739. DIM DFP AS DOSFilePack
  3740. DIM TempStr AS STRING * 80
  3741. TempStr = file2delete$ + CHR$(0)
  3742. DFP.Func = DeleteFileDOS        'defined in BULLET.BI
  3743. DFP.FilenamePtrOff = VARPTR(TempStr)
  3744. DFP.FilenamePtrSeg = VARSEG(TempStr)
  3745. stat = BULLET(DFP)
  3746. IF stat THEN 'error
  3747. See: RenameFileDOSsrc
  3748. ~RenameFileDOSsrc
  3749. Func: RenameFileDOS    Pack: DOSFilePack        Func: 101/DOS
  3750. DIM DFP AS DOSFilePack
  3751. DIM TempStr AS STRING * 80
  3752. DIM TempStr2 AS STRING * 80
  3753. TempStr = file2rename$ + CHR$(0)
  3754. TempStr2 = newfilename$ + CHR$(0)
  3755. DFP.Func = RenameFileDOS        'defined in BULLET.BI
  3756. DFP.FilenamePtrOff = VARPTR(TempStr)
  3757. DFP.FilenamePtrSeg = VARSEG(TempStr)
  3758. DFP.NewNamePtrOff = VARPTR(TempStr2)
  3759. DFP.NewNamePtrSeg = VARSEG(TempStr2)
  3760. stat = BULLET(DFP)
  3761. IF stat THEN 'error
  3762. See: CreateFileDOSsrc
  3763. ~CreateFileDOSsrc
  3764. Func: CreateFileDOS    Pack: DOSFilePack        Func: 102/DOS
  3765. DIM DFP AS DOSFilePack
  3766. DIM TempStr AS STRING * 80
  3767. TempStr = file2create$ + CHR$(0)
  3768. DFP.Func = CreateFileDOS        'defined in BULLET.BI
  3769. DFP.FilenamePtrOff = VARPTR(TempStr)
  3770. DFP.FilenamePtrSeg = VARSEG(TempStr)
  3771. DFP.Attr = 0                    'normal file directory attribute
  3772. stat = BULLET(DFP)
  3773. IF stat THEN 'error
  3774. See: AccessFileDOSsrc
  3775. ~AccessFileDOSsrc
  3776. Func: AccessFileDOS    Pack: DOSFilePack        Func: 103/DOS
  3777. DIM DFP AS DOSFilePack
  3778. DIM TempStr AS STRING * 80
  3779. TempStr = file2access$ + CHR$(0)
  3780. DFP.Func = AccessFileDOS        'defined in BULLET.BI
  3781. DFP.FilenamePtrOff = VARPTR(TempStr)
  3782. DFP.FilenamePtrSeg = VARSEG(TempStr)
  3783. DFP.ASmode = &H42               'attempt R/W DENY NONE access
  3784. stat = BULLET(DFP)
  3785. IF stat THEN 'error
  3786. See: OpenFileDOSsrc
  3787. ~OpenFileDOSsrc
  3788. Func: OpenFileDOS      Pack: DOSFilePack        Func: 104/DOS
  3789. DIM DFP AS DOSFilePack
  3790. DIM TempStr AS STRING * 80
  3791. TempStr = file2open$ + CHR$(0)
  3792. DFP.Func = OpenFileDOS          'defined in BULLET.BI
  3793. DFP.FilenamePtrOff = VARPTR(TempStr)
  3794. DFP.FilenamePtrSeg = VARSEG(TempStr)
  3795. DFP.ASmode = &H42               'open in R/W DENY NONE access
  3796. stat = BULLET(DFP)
  3797. IF stat = 0 THEN
  3798.    'DFP.Handle set to handle of open file
  3799.    'error
  3800. See: SeekFileDOSsrc
  3801. ~SeekFileDOSsrc
  3802. Func: SeekFileDOS      Pack: DOSFilePack        Func: 105/DOS
  3803. DIM DFP AS DOSFilePack
  3804. DFP.Func = SeekFileDOS          'defined in BULLET.BI
  3805. DFP.Handle = handle
  3806. DFP.SeekOffset = 0&             'position 0 relative EOF (get length of file)
  3807. DFP.Method = 2                  'seek from END of file
  3808. stat = BULLET(DFP)
  3809. IF stat = 0 THEN
  3810.    'DFP.SeekOffset set to absolute current offset
  3811.    '--in this case, the DFP.SeekOffset equals then length of the file
  3812.    'error
  3813. See: ReadFileDOSsrc
  3814. ~ReadFileDOSsrc
  3815. Func: ReadFileDOS      Pack: DOSFilePack        Func: 106/DOS
  3816. DIM DFP AS DOSFilePack
  3817. DIM ReadBuff AS STRING * 512    'sector buffer
  3818. DFP.Func = ReadFileDOS          'defined in BULLET.BI
  3819. DFP.Handle = handle
  3820. DFP.Bytes = Bytes2Read          '16-bit value, in this case 512 since that's
  3821. DFP.BufferPtrOff = VARPTR(ReadBuff)            'the size of ReadBuff
  3822. DFP.BufferPtrSeg = VARSEG(ReadBuff)
  3823. stat = BULLET(DFP)
  3824. IF stat = 0 THEN
  3825.    IF DFP.Bytes <> Bytes2Read THEN              'check if EOF processed
  3826.       'hit EOF before reading all 512 bytes
  3827.    ELSE
  3828.       'ReadBuff filled with 512 bytes of data read from the current disk pos
  3829.       'disk position moved to the last byte read + 1
  3830.    ENDIF
  3831.    'error
  3832. See: ExpandFileDOSsrc
  3833. ~ExpandFileDOSsrc
  3834. Func: ExpandFileDOS    Pack: DOSFilePack        Func: 107/DOS
  3835. DIM DFP AS DOSFilePack
  3836. DFP.Func =  ExpandFileDOS       'defined in BULLET.BI
  3837. DFP.Handle = handle
  3838. DFP.SeekOffset = Bytes2ExpandBy&
  3839. stat = BULLET(DFP)
  3840. IF stat = 0 THEN
  3841.    'file expanded by number of bytes specified
  3842.    'error
  3843. See: WriteFileDOSsrc
  3844. ~WriteFileDOSsrc
  3845. Func: WriteFileDOS     Pack: DOSFilePack        Func: 108/DOS
  3846. DIM DFP AS DOSFilePack
  3847. DIM WriteBuff AS STRING * 512   'sector buffer
  3848. DFP.Func = WriteFileDOS         'defined in BULLET.BI
  3849. DFP.Handle = handle
  3850. DFP.Bytes = Bytes2Write         '16-bit value, in this case 512 since that's
  3851. DFP.BufferPtrOff = VARPTR(WriteBuff)           'the size of WriteBuff
  3852. DFP.BufferPtrSeg = VARSEG(WriteBuff)
  3853. stat = BULLET(DFP)
  3854. IF stat = -2 THEN
  3855.    'disk full
  3856. ELSE IF stat THEN
  3857.    'other error
  3858.    'okay
  3859. Unlike ReadFileDOS, if the number of bytes actually written does not equal
  3860. Bytes2Write, the WriteFileDOS routine returns a DISK FULL error code (-2).
  3861. See: CloseFileDOSsrc
  3862. ~CloseFileDOSsrc
  3863. Func: CloseFileDOS     Pack: DOSFilePack        Func: 109/DOS
  3864. DIM DFP AS DOSFilePack
  3865. DFP.Func = CloseFileDOS         'defined in BULLET.BI
  3866. DFP.Handle =handle2close
  3867. stat = BULLET(DFP)
  3868. IF stat THEN 'error
  3869. See: MakeDirDOSsrc
  3870. ~MakeDirDOSsrc
  3871. Func: MakeDirDOS       Pack: DOSFilePack        Func: 110/DOS
  3872. DIM DFP AS DOSFilePack
  3873. DIM TempStr AS STRING * 80
  3874. TempStr = subdir2make$ + CHR$(0)
  3875. DFP.Func = MakeDirDOS           'defined in BULLET.BI
  3876. DFP.FilenamePtrOff = VARPTR(TempStr)
  3877. DFP.FilenamePtrSeg = VARSEG(TempStr)
  3878. stat = BULLET(DFP)
  3879. IF stat THEN 'error
  3880. See: DeleteFileDOSsrc
  3881.