home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / database / c2dbase1.zip / C2DBASE.DOC next >
Text File  |  1985-11-28  |  72KB  |  1,683 lines

  1.                                     
  2.                                     
  3.                                     
  4.                                     
  5.                                     
  6.                                     
  7.                                     
  8.                                     
  9.                                     
  10.                                     
  11.                                     
  12.                                     
  13.                                     
  14.                           THE C2DBASE FUNCTIONS
  15.                                version 1.0
  16.                                 11/28/85
  17.                                     
  18.                                    by
  19.                                     
  20.                                     
  21.                            COMPUSCAN SOFTWARE
  22.                                     
  23. INTRODUCTION . . . . . . . . . . . . . . . . . . . . . . . .    1
  24. OVERVIEW . . . . . . . . . . . . . . . . . . . . . . . . . .    2
  25.    FILES IN PACKAGE  . . . . . . . . . . . . . . . . . . . .    2
  26.    MODIFICATIONS & REVISIONS . . . . . . . . . . . . . . . .    2
  27.    THE DBASE FILE STRUCTURE  . . . . . . . . . . . . . . . .    2
  28.    THE DBINFO STRUCTURE  . . . . . . . . . . . . . . . . . .    3
  29.    IMMEDIATE ERROR EXIT POINTS . . . . . . . . . . . . . . .    4
  30.    CDBUTIL - THE DBASE UTILITY PROGRAM . . . . . . . . . . .    4
  31.    KNOWN BUGS  . . . . . . . . . . . . . . . . . . . . . . .    5
  32. REGISTRATION . . . . . . . . . . . . . . . . . . . . . . . .    5
  33.    WHY REGISTER  . . . . . . . . . . . . . . . . . . . . . .    5
  34.    HOW TO REGISTER . . . . . . . . . . . . . . . . . . . . .    6
  35. FUNCTION DESCRIPTIONS  . . . . . . . . . . . . . . . . . . .    6
  36.    INTRO . . . . . . . . . . . . . . . . . . . . . . . . . .    6
  37.    DBHEADER  . . . . . . . . . . . . . . . . . . . . . . . .    7
  38.    DBSTAT  . . . . . . . . . . . . . . . . . . . . . . . . .    7
  39.    RECREAD   . . . . . . . . . . . . . . . . . . . . . . . .    8
  40.    RECLIST   . . . . . . . . . . . . . . . . . . . . . . . .    8
  41.    RECWRITE  . . . . . . . . . . . . . . . . . . . . . . . .    9
  42.    NDXREAD   . . . . . . . . . . . . . . . . . . . . . . . .   10
  43.    NDXSTAT   . . . . . . . . . . . . . . . . . . . . . . . .   10
  44.    MEMOREAD  . . . . . . . . . . . . . . . . . . . . . . . .   11
  45.    TEXTFIND  . . . . . . . . . . . . . . . . . . . . . . . .   11
  46.    MEMOADD   . . . . . . . . . . . . . . . . . . . . . . . .   12
  47.    ONOFFDBT  . . . . . . . . . . . . . . . . . . . . . . . .   13
  48.    DBTPACK . . . . . . . . . . . . . . . . . . . . . . . . .   14
  49.    PASS  . . . . . . . . . . . . . . . . . . . . . . . . . .   15
  50.    DBCLOSE   . . . . . . . . . . . . . . . . . . . . . . . .   15
  51. CDBUTIL  . . . . . . . . . . . . . . . . . . . . . . . . . .   16
  52.    CDBUTIL MODES . . . . . . . . . . . . . . . . . . . . . .   16
  53.       GENERAL  . . . . . . . . . . . . . . . . . . . . . . .   16
  54.       FUNCTION CALLING PROCEDURE . . . . . . . . . . . . . .   16
  55.       DISPLAY FILE INFORMATION . . . . . . . . . . . . . . .   17
  56.       UNFILTERED RECORD COUNT  . . . . . . . . . . . . . . .   17
  57.       UNFILTERED COUNT TO MEMORY VARIABLE  . . . . . . . . .   17
  58.       RECORD LISTING . . . . . . . . . . . . . . . . . . . .   18
  59.       MEMO FIELD DISPLAY . . . . . . . . . . . . . . . . . .   19
  60.       KEY PHRASE SEARCH THROUGH MEMO FIELD . . . . . . . . .   20
  61.       PROGRAMM-CONTROLLED MEMO WRITING . . . . . . . . . . .   21
  62.       SEPARATE .DBT FROM .DBF  . . . . . . . . . . . . . . .   21
  63.       PACK MEMO FILE . . . . . . . . . . . . . . . . . . . .   22
  64.    SOURCE  . . . . . . . . . . . . . . . . . . . . . . . . .   22
  65.       MAIN . . . . . . . . . . . . . . . . . . . . . . . . .   22
  66.       FUNCTION 1 . . . . . . . . . . . . . . . . . . . . . .   24
  67.       FUNCTION 2 . . . . . . . . . . . . . . . . . . . . . .   25
  68.       FUNCTION 3 . . . . . . . . . . . . . . . . . . . . . .   25
  69.       FUNCTION 4 . . . . . . . . . . . . . . . . . . . . . .   25
  70.       FUNCTION 5 . . . . . . . . . . . . . . . . . . . . . .   26
  71.       FUNCTION 6 . . . . . . . . . . . . . . . . . . . . . .   27
  72.       FUNCTION 7 . . . . . . . . . . . . . . . . . . . . . .   29
  73.       FUNCTION 8 . . . . . . . . . . . . . . . . . . . . . .   29
  74.       FUNCTION 9 . . . . . . . . . . . . . . . . . . . . . .   30
  75.    CDBUTIL.PRC FOR DBASE III . . . . . . . . . . . . . . . .   30
  76.       EXPLANATION  . . . . . . . . . . . . . . . . . . . . .   30
  77.       PROGRAM  . . . . . . . . . . . . . . . . . . . . . . .   31
  78. INTRODUCTION
  79.  
  80.         ASHTON-TATE's  DBASE  III  has  brought  some  of  the  power of
  81. large-scale  dbms  to  the PC.  The C2DBASE functions add  a little more
  82. power and flexibility to this modern  micro-dbms.  C2dDBASE is meant for
  83. those  who are familiar  with  the C language,  and  can write auxillary
  84. programs  for  specific  purposes.  With  the  C2DBASE  functions,  a  C
  85. programmer can:
  86.         
  87.         -Use  the files  created  by  DBASE  III  outside  of  the DBASE
  88.         environment.
  89.         
  90.         -Extract  file  statistics  without DBASE  (i.e.   record cound,
  91.         field names, index fields, etc.).
  92.         
  93.         -Write  C  programs  that  bring  information   into  the  DBASE
  94.         environment    (i.e.     mathematical   functions,   peripheral
  95.         status,etc.).
  96.         
  97.         -Display memo fields as you meant them to be  displayed, without
  98.         being limited by DBASE's limited formatting.
  99.        
  100.         -Perform very fast keyphrase searching through memo fields  in a
  101.         database.  This capability brings to life the power of the memo
  102.         field.  
  103.        
  104.         -Separate a .DBT  file from its associated  .DBF  file.  This is
  105.         very useful where the .DBT file has been  corrupted. DBASE will
  106.         not use a .DBF when it cannot find or read the .DBT.
  107.        
  108.         -Squeeze out the wasted disk space inside a .DBT file. For those
  109.         who edit  memo  fields  frequently,  the amount of wasted space
  110.         inside the .DBT file would surprise you.
  111.         
  112.         These are a  few of the  more obvious advantages to  the C2DBASE
  113. functions.   Once you understand  what  these  functions  are,  your own
  114. creatively will provide you will many more advanatages and uses.
  115.         
  116.         C2DBASE  may be  used  inside  or  outside of  DBASE.  When used
  117. inside,  the DBASE command RUN is used to evoke the C program containing
  118. the C2DBASE functions required to perform the task.
  119.         Used outside of DBASE,  these functions can  productively access
  120. all  of  the files created and used  by  DBASE.   With this version, the
  121. information that can be extracted from an .NDX file is limited,  but all
  122. other file type are supported completely.
  123.         
  124.         The  C2DBASE  functions  are  distributed  under  the  Shareware
  125. concept.  The author assumes no responsibility for the damage a reckless
  126. programmer can do to his  client's database.   Indeed, such a programmer
  127. does not need these function to perform such damage. 
  128.  
  129.  
  130. OVERVIEW
  131.  
  132. FILES IN PACKAGE
  133.  
  134.         The files distributed with this package are listed below. If you
  135. are missing any of these files,  the package you received is incomplete.
  136. Upon registration,  you will be sent a complete up-to-date program disk,
  137. and printed documentation.
  138.         
  139.         DBASE.LIB -  This is the compiled library of  C2DBASE functions.
  140. It has been compiled using Lattice version 2.14 with the S-memory model.
  141. Obtaining  the  source  code  for  these  functions  will  allow  you to
  142. re-compile using another memory model.
  143.         
  144.         DBASE.H -  This C header file must appear in any C program which
  145. uses  the C2DBASE functions.   (i.e #include dbase.h).   It contains the
  146. definitions  these functions  require,  including  the  important DBINFO
  147. structure  definition  (see  below  for  more  information   about  this
  148. structure).
  149.         
  150.         CDBUTIL.C  -  The  source  code  for  the  demonstration/utility
  151. program.
  152.         
  153.         CDBUTIL.EXE  -   The   executible  program   using  the  C2DBASE
  154. functions.
  155.         
  156.         CDBUTIL.PRC -  An illustrative DBASE procedure file  showing how
  157. the C2DBASE functions may be used inside of DBASE III.
  158.         
  159.         C2DBASE.DOC - This documentation file
  160.  
  161.     In addition to the above files,  users of the registered package
  162. will find the following files on the program diskette:
  163.  
  164.     C2DBSORC.DOC - Source code for all C2DBASE functions
  165.  
  166.     USER.HLP -  Miscellaneous information,  helpful tips and support
  167. telephone numbers.
  168.  
  169.  
  170. MODIFICATIONS & REVISIONS
  171.  
  172. NONE
  173.  
  174.  
  175. THE DBASE FILE STRUCTURE
  176.  
  177.         Although you do  not need  to  know about the  file structure of
  178. DBASE,  a few words  may  be  in  order.   DBASE  reserves  several file
  179. extensions for its specific  use.   The  ones that are relevant  to this
  180. package are:
  181.         
  182.         .DBF - a DBASE database file containing records of fixed length,
  183. and  predefined  fields.   A file header contains  information about the
  184. database.
  185.         
  186.         .DBT -  a  file  containing the text held  in memo fields  for a
  187. given .DBF  file.   The .DBF  and .DBT  files will always have  the same
  188. filename. (i.e. DATA.DBF & DATA.DBT)
  189.         
  190.         .NDX -  an index file sorted on a key relevant to  the .DBF file
  191. to which it is associated.   Each record in this file points to a record
  192. in the .DBF file.   The .DBF file will appear to be in the order  of the
  193. .NDX file.
  194.         
  195.         .MEM  -  These  files contain names and values  of  DBASE memory
  196. variables.   They may contain information for up to 256 memory variable.
  197. The C2DBASE function  "pass"  writes a .MEM file to pass  information to
  198. DBASE.   However,  this  version  writes  .MEM  files  holding  a single
  199. character variable.   Later versions will have  increased flexibility in
  200. this area.
  201.         
  202.         .PRG  -   these  are  program  command  files   DBASE  uses  for
  203. instruction. 
  204.  
  205.  
  206. THE DBINFO STRUCTURE
  207.  
  208.         In  order  to  efficiently  use  the  C2DBASE  functions,  it is
  209. necessary to become familiar with the structure used  to  hold all DBASE
  210. information.   This structure is more completely defined in  the dbase.h
  211. header  file.   (This header must be  included in any program  using the
  212. C2DBASE  functions.)  Most of  the  ingredients  of  this  structure are
  213. automatically handled within the functions themselves, and should not be
  214. touched by the programmer.  The following is a list of those elements of
  215. the structure that are relevant to the C programmer.
  216.         
  217.         (Note:
  218.         static   struct   dbinfo   dbase;    
  219.         /*DBASE information structure-must be static*/   )
  220.         
  221.         dbase.error -  This variable  will  usually be zero if  a called
  222. C2DBASE  function  was successfully  executed.   If  an  error occurs, a
  223. non-zero code will help to clarify what the error was. Each function has
  224. its own set of error codes.  Refer to the documentation of each function
  225. for the list  of  error codes relevant  to  a  particular  function. The
  226. dbase.error variable should be checked after each function call if there
  227. is  a posibility  of  an  error.   In all  function  documentation, this
  228. variable is denoted as dbase->error.
  229.         
  230.         dbase.ndxnum  -  This integer is  equal to  the number  of index
  231. files in use with  the .DBF.   C2DBASE assigns each index  file a number
  232. from one to ten.   The first index specified receives a  '1' assignment,
  233. the  second a '2',  and so on.   To refer to an  index file  inside of a
  234. C2DBASE function it is only necessary to refer to its number.  Of course
  235. other ways to  refer to index  files are supported,  but this particular
  236. method proved convenient for me.
  237.         
  238.         dbase.ndxfile[n]  -  This is  an array  of structures containing
  239. information  pertinent  to  index  (.NDX)   files  that  may  have  been
  240. specified.   Up to  10  index files may be  specied for each  .DBF file.
  241. However,  this version of  the  C2DBASE  functions  does  not completely
  242. support all aspects of the index files.   The ndxfile structure includes
  243. the following element -
  244.         dbase.ndxfile[n].name      - 35 characters
  245.         dbase.ndxfile[n].fldnum    - number of fields index in this .NDX
  246.         dbase.ndxfile[n].fields[10]-up to 10 field names, 11 bytes each
  247.         
  248.         dbase.info - This is an array of miscellaneous information about
  249. the .DBF file. Some of the relevant element of this structure are -
  250.             dbase.info.year - character\
  251.             dbase.info.month- character >last date of update
  252.             dbase.info.day  - character/
  253.             dbase.info.quan -number of record in .DBF (long integer)
  254.             dbase.info.reclgth- bytes per record
  255.         
  256.         dbase.fieldnum -  An integer value equal to the number of fields
  257. per record in the .DBF.  The maximum number of fields is set by MAXFIELD
  258. in the header file. (Presently 30)
  259.         
  260.         dbase.field[n] -  This is an array of structures containing .DBF
  261. field information.  The maximum legal value of n is the number of fields
  262. per record for the .DBF  file -  dbase.fieldnum. Each structure contains
  263. the following elements -
  264.             dbase.field[n].name   - 11 characters
  265.             dbase.field[n].type   - field type (C, D, N, or M)
  266.             dbase.field[n].length - field length (up to 255 bytes)
  267.             dbase.field[n].decimal- decimanl places if numeric
  268.  
  269.  
  270. IMMEDIATE ERROR EXIT POINTS
  271.  
  272. N O T E:
  273.         The C2DBASE functions generally pass control back  to the callin
  274. function  when they have  completed,  even in the case of an  error. the
  275. function reclist, onoffdbt, and pass have have error detection code that
  276. result in an immediate program exit if particular types of errors occur.
  277. Refer to the documentation for these functions for further information.
  278.  
  279.  
  280. CDBUTIL - THE DBASE UTILITY PROGRAM
  281.  
  282.         This  package  includes  the  C  program  CDBUTIL,   which  will
  283. hopefully serve as example of how to program with the C2DBASE functions.
  284. It uses many of the functions,  and provides enough useful functionality
  285. to whet the appetite of the non-programmer familiar with  DBASE.  It has
  286. a  somewhat  cumbersome  command  line  invocation  structure,  but  the
  287. documentation should  be  clear enough  for  most  people  familiar with
  288. command line arguments.   The program  source is included  and should be
  289. examined by those wanting to use the functions. 
  290.         Each mode of this utility program performs  a specific  task and
  291. requires a specific  argument list.   This information is  provided in a
  292. help  screen  which is  called up when  CDBUTIL is  executed without any
  293. arguments.  Examine this screen whenever you need to be refreshed on the
  294. modes of the CDBUTIL program.
  295.  
  296.  
  297. KNOWN BUGS
  298.  
  299.         This version of  C2DBASE (another  is  on  the  way)  has  a few
  300. limitations,  which may be considered bugs by some.  If you are aware of
  301. these  limitations,  you should  have  no trouble  using these functions
  302. reliably.
  303.         
  304. MEMO FIELDS:
  305.         The  first limitation  has to  do with memo  fields.  Unless you
  306. increase the value of MEMOMAX in the dbase.h header file, and re-compile
  307. the code,  the maximum length of any memo field should be less than 2048
  308. bytes.   Beyond this,  trucation  occurs,  or searching is not performed
  309. depending on the function.  
  310.         More importantly perhap is the limitation of only one memo field
  311. per record.   If  there are more  than one  memo field in a  record, the
  312. C2DBASE functions only process the first one.  This oversight on my part
  313. will be corrected in a later version.
  314.         
  315. INDEX FILE USAGE:
  316.         At  present,  .DBF files  cannot be presented in  indexed order.
  317. For example,  the reclist function cannot list records in indexed order.
  318. In fact,  the only thing you can do with index files,  at this point, is
  319. display  information contained in  their header  (i.e.   indexed fields,
  320. index record length, etc.).
  321.         
  322. MULTI-TASKING ENVIRONMENTS:
  323.         I have  had a few difficulties  running these functions  in some
  324. MS-DOS multi-tasking environements.  When I have enough time to sit down
  325. and understand  the problem,  or  if  the problem  causes  enough  of an
  326. outcry,  I will correct. I may be wrong, but not many of you are running
  327. under such environments.
  328.  
  329.  
  330. REGISTRATION
  331.  
  332. WHY REGISTER
  333.  
  334.         My expectation is that this package will appeal to a unique few.
  335. Those who know  and delight in  both the  C language and  DBASE III, are
  336. rare enough.   Of thoses people,  this package will not  interest all of
  337. them.    If  you  find  yourself  even  marginally   interested  in  the
  338. capabilities that this package provides,  consider yourself  unique. One
  339. of  the responsibilities  of this uniqueness  is that you  register this
  340. package. 
  341.         Registration gives you several tangible and intangible benefits.
  342. Some of the intangibles include giving support to  others like yourself,
  343. and encouraging the Freeware  concept of  software  development.  By now
  344. you are familiar with what that is,  and why it is the  only alternative
  345. to high-priced software. 
  346.         Some of the more tangible benefits of registration are:
  347.         
  348.         -All  the source  code  for the C2DBASE  functions  are  sent to
  349.         registered users.   Aside  from  giving you the  power to modify
  350.         these functions,  there is a lot  to learn about  DBASE III from
  351.         the examination of this source code.
  352.         
  353.         -The  unregistered  documentation  file  is  incomplete  and not
  354.         paginated.  Although the amount left out is not a lot,  it could
  355.         prove helpful if you are attempting to modify  the functions, or
  356.         recompile for any reason.  The pages refered to in  the table of
  357.         contents are not coordinated with the text of the file. This was
  358.         done for convenience. Registered users will receive the complete
  359.         documentation in printed form.
  360.         
  361.         -During the evolution of the C2DBASE functions, registered users
  362.         will  continue  to receive  free updates of newer  versions. The
  363.         following  improvements  are  planned  for  the  not-too-distant
  364.         future:
  365.             -better support for .NDX files and indexing functions
  366.             -multiple variables returned with the 'pass' function
  367.             -support for multiple memo fields
  368.             -database recovery provisions
  369.             -improved CDBUTIL modes
  370.         
  371.         -Only registered users may contact  me for support  of any kind.
  372.         I will be very happy to  hear  from those who  are interested in
  373.         this package.  I know you are interested if you register. If you
  374.         are  having  any trouble incorporating these  functions  in your
  375.         programs,  or have  any suggestions  on  improving  them, please
  376.         write,  or call the number listed in your  registration package.
  377.         (  I may even be  convinced to provide  customized functions for
  378.         registered users.)
  379.  
  380.  
  381. HOW TO REGISTER
  382.  
  383.         To register  this package,  send your name and  mailing address,
  384. along with $15 to:
  385.         
  386.             COMPSCAN
  387.             60 East Water Street
  388.             North Andover, Mass 01845
  389.         
  390.         You will  receive the newest  version  of  the  C2DBASE package,
  391. printed  documentation,  including  source  code  for  all  the  library
  392. functions,  additional tips helpful if you wish to modify  the functions
  393. in any way,and hotline telephone numbers for support.
  394.         If you intend to use this package,  register it at your earliest
  395. convenience so that support is available to you,  if and when you should
  396. need it.
  397.  
  398.  
  399. FUNCTION DESCRIPTIONS
  400.  
  401. INTRO
  402.  
  403.         What follows is a function description for each of the functions
  404. found in DBASE.LIB.   As you read them,  let your creative  juices flow,
  405. and see how you may use each of them to solve some problem or  other, or
  406. otherwise make things more convenient for you.
  407.  
  408.  
  409. DBHEADER 
  410.  
  411. SYNOPSIS:
  412.         dbheader(dbfile,dbase)
  413.  
  414.         char *dbfile;                   /*file to be examined*/
  415.         struct dbinfo *dbase;           /*structure to be filled*/
  416.         ----------------------------------------------------------------
  417.         This routine  reads  a  dbase  file  header  and  determines the
  418. database  file  information,  which  includes  memo  flag,date,number of
  419. records,record length, file name, field names and type.  
  420.                 -filename (dbfile) may include directory paths.
  421.                 -.DBF extension MUST be included in filename.
  422.                 -Maximum record length is 512 bytes (dbase.h).
  423.                 -Maximum fields per record is 30 (dbase.h).
  424.         The routine initializes a structure (dbase) containing the dbase
  425. file information (see dbase.h -  structure dbinfo) and returns the level
  426. 1 file number for further use.  This routine should be the first routine
  427. used  to  interface with a  .DBF file,  and it should be  used only once
  428. since  it  resets  a number of variables in  the structure.   The dbinfo
  429. structure  error  variable  should  be  checked  for  a  non-zero  value
  430. indicating an error was detected.  The error code meanings are: 
  431.                 1 = no .DBF extension in filename
  432.                 2 = cannot open dbfile
  433.                 3=not recognized  as  a  DBASE  file,  despite  the .DBF
  434. extension
  435.                 4 = cannot open associated .DBT file
  436.                 5 = not assigned yet
  437.         NOTE: .DBT file must be in same directory as the .DBF file
  438.         */
  439.  
  440.  
  441. DBSTAT 
  442.  
  443. SYNOPSIS:
  444.         dbstat(info)
  445.         struct dbinfo *info;
  446.     ----------------------------------------------------------------
  447.         This routine displays ( on stdout) the status information of the
  448. .DBF  file  whose characteristics are passed  in  the  struct  info. The
  449. information includes any index files that have been previously linked to
  450. the .DBF file with the function NDXREAD.
  451.  
  452.  
  453.  
  454. RECREAD 
  455.  
  456. SYNOPSIS:
  457.         char *recread(dbase,recnum)
  458.         struct dbinfo *dbase;    /*file information structure*/
  459.         long recnum;        /*record number to return*/ 
  460.     ----------------------------------------------------------------
  461.         This  routine reads the records of  the  file  whose information
  462. parameters  are in  the dbase structure.   A pointer to the  contents of
  463. record number "recnum"  (which must be a LONG integer) is returned.  The
  464. record contents are contained in a character buffer which must be parsed
  465. for  the record  fields by the calling routine.   If recnum  specifies a
  466. record that is not in the database,  the returned pointer will  be NULL,
  467. and dbase->error will be non-zero.   The meaning of the  error codes are
  468. as follows; 
  469.                         1 = record not in database
  470.                         2 = code not yet assigned
  471.                 Please  note  that  this  function  returns  a character
  472. pointer and must be declared as such in the calling program. 
  473.  
  474.  
  475. RECLIST 
  476.  
  477. SYNOPSIS:
  478.         reclist(dbase,start,end)
  479.         struct dbinfo *dbase;
  480.         long start,end;      /*starting & ending records to list
  481.     ---------------------------------------------------------------
  482.     This routine prints (on stdout) the unindexed records of a dbase
  483. .DBF file described in the structure info.   It  takes three parameters,
  484. the first being the ubiquitous  DBINFO structure pointer,  the second is
  485. the record number (LONG) where the listing is to start, and the third is
  486. the record  number  (also LONG)  where  the listing is  to  end.  Ending
  487. numbers  larger  than  the  number  of  records  in   the  database  are
  488. interpreted as the largest record number.   A starting  record number of
  489. zero will be interpreted as a 1.
  490.     This function does a complete program exit  (with ERRORLEVEL set
  491. to 1)  if it is  requested to  list a record number  that is not  in the
  492. database. 
  493.  
  494.  
  495. RECWRITE 
  496.  
  497. SYNOPSIS:
  498.         recwrite(dbase,record,string)
  499.         struct dbinfo *dbase;
  500.         long record;        /*record number to write*/
  501.         char *string;        /*record string to write*/
  502.     ----------------------------------------------------------------
  503.         This function writes a record to the .DBF file specified  by the
  504. DBASE structure pointer. If the record specified by the passed parameter
  505. 'record'  (which is a LONG  integer)  is less than the  total number  of
  506. records in the .DBF file, then record number 'record' is replaced by the
  507. character  string  'string'.  If 'record'  is larger than  the number of
  508. records in the database,  then a new record is appended, and  the record
  509. number is incremented.  Please note that  this version  does not support
  510. index files,  so this function should only be used on databases that are
  511. not indexed,  or where  the indexed fields  will not be changed  and the
  512. number of records will remain the same.  It is the responsibility of the
  513. programmer  to  make  cetrtain that this  is so.  The programmer is also
  514. responsible to make  certain that  'record'  is correct for the database
  515. being used.  Please be  careful.  You could screw up the  .DBF file with
  516. this one if these cautions are not observed.
  517.         Upon successful completion,  the function returns a  zero if the
  518. record  was replaced,  and  a one if  the record was  appended.  In both
  519. cases,  the dbase->error variable  will be zero.   If an error  has been
  520. detected, a -1 will be returned and the error variable will be non-zero,
  521. with the following error codes;
  522.         1 = Cannot reopen .DBF file.
  523.         2 =Premature end-of-file or file positioning error
  524.         3 =.DBF write error
  525.  
  526.  
  527. NDXREAD 
  528.  
  529. SYNOPSIS:
  530.         ndxread(dbase,ndxfile)
  531.         struct dbinfo *dbase;
  532.         char *ndxfile;          /*.NDX filename*/
  533.     ----------------------------------------------------------------
  534.     This routine  opens a .NDX  file,  checks it for various errors,
  535. and  fills  the   "dbase"   structure  with  the  pertinent  information
  536. concerning the named .NDX file  -  "ndxfile",which must contain the full
  537. path (default directory assumed  if path is  missing)  of the file to be
  538. read  (including  extension).   The  maximum  number  of  indexed fields
  539. allowed is presently 10  (MAXFIELD/3).   The structure for the .NDX file
  540. information will  be found in the dbase.h header  file.   If successful,
  541. the variable dbase.error will  be  equal to zero,  the "dbase" structure
  542. will  be updated  with the index  file information and  the order number
  543. (from 1 to 10) of the index file will be returned.  (NOTE: the subscript
  544. number  of  the .NDX  file  in the  'dbase'  structure will be the order
  545. number minus 1.) If an error condition is detected the "dbase" structure
  546. will not be updated and dbase.error will  be  non-zero.   The meaning of
  547. the various codes are; 
  548.         1 = named file does not have .NDX extension
  549.         2 = cannot open named .NDX file 
  550.         3 = .NDX file is indexed on fields that are not in the .DBF file
  551.         4 =
  552. NOTE: The 'dbase' structure can contain up to 10 index files.
  553.  
  554. DBASE  NOTE:  DBASE  allows  indexing  on  complex keys  -i.e.  INDEX ON
  555. LEN(TRIM(SUBSTR(character  field))).   This  C2DBASE function
  556. can only handle one DBASE modifier  on  the field -  i.e. LEN(field) not
  557. LEN(TRIM(field)).   Fields with multiple function modifiers will be seen
  558. as a mismatching field, and cause an error 3.
  559.  
  560.  
  561. NDXSTAT 
  562.  
  563. SYNOPSIS:
  564.         ndxstat(dbase,ndxorder)
  565.         struct dbinfo *dbase;
  566.         int    ndxorder;
  567.     ----------------------------------------------------------------
  568.         This function displays  (on stdout)  information about the index
  569. file associated with the  index order number  "ndxorder".  This function
  570. is called by "DBSTAT".  If the function executes succesfully, the return
  571. value will be zero,  dbase->error will be zero, and the information will
  572. be displayed.  If it is not succesful, no information will be displayed,
  573. the return value will be non-zero,  and an error code will  be placed in
  574. dbase->error.  The error codes are:
  575.               1=ndxorder exceeds the number of index files with the .DBF
  576.               2=error code not yet assigned
  577.  
  578.  
  579. MEMOREAD 
  580.  
  581. SYNOPSIS:
  582.         char *memoread(dbase,rec)
  583.         struct dbinfo *dbase;
  584.         long rec;        /*record number to read*/
  585.     ----------------------------------------------------------------
  586.         This routine returns a pointer to  the  .DBT  memo  text  of the
  587. record specified in the passed parameter  "rec"  (which must be a LONG).
  588. The  function  must  be declared as  a character pointer in  the calling
  589. function.   The record  is  assumed to  have  only one  memo field.  The
  590. "dbase"  parameter is the dbinfo structure of the .DBF file,  which must
  591. have been previously filled using the "dbheader"  function.  The largest
  592. memo field which can be read is 2048  bytes, which should be good enough
  593. for most applications.   If a larger field is needed  change the MEMOMAX
  594. variable in "dbase.h".   The routine returns a char pointer  to the memo
  595. field string, unless an error is detected.  An error detection returns a
  596. NULL pointer and sets  "dbase->error"  to  one of  several  error codes.
  597. These are; 
  598.         1 = .DBF file does not have associated .DBT file
  599.         2 = record has no  memo field (no .DBT)
  600.         3 = record has an empty memo field pointer
  601.         4 = error reading .DBT file
  602.         5 = memo text too long (valid pointer returned anyway)
  603.         6 = not assigned yet
  604.         
  605.         NOTE:  This function can only handle .DBT files which contain no
  606. more than 65535 memos.
  607.         
  608.         NOTE:  This  function  also  contains  another  function  called
  609. memptr, which returns the unsigned value of the memo field pointer.
  610.  
  611.  
  612. TEXTFIND 
  613.  
  614. SYNOPSIS:
  615.         textfind(dbase, record, string)
  616.         struct     dbinfo    *dbase;
  617.         long    record;        /*record number to search*/
  618.         char    *string;    /*string to search for*/
  619.     ----------------------------------------------------------------
  620.         This function  looks at  the record  content and  memo  text (if
  621. applicable)  for  the specified record,  given  as  a LONG  integer, and
  622. searches for 'string'.   If found,  the function returns a one  (1).  If
  623. the search  is unsucessful,  a zero (0)  is returned.  Capitalization is
  624. ignored  ("abc"  =  "ABC").   If the function detects an error,  a -1 is
  625. returned,  and dbase->error will  be non-zero,  with the following error
  626. codes presently specified;
  627.             2 = search string is NULL
  628.             3 = error reading .DBT file
  629.         
  630.         As is presently the case in all the C2DBASE  functions that deal
  631. with memo fields,  only one such field  per record is assumed.   If more
  632. than one exist, only the first memo field will be processed.
  633.  
  634.  
  635. MEMOADD 
  636.  
  637. SYNOPSIS:
  638.         memoadd(dbase,rec,text)
  639.         struct dbinfo *dbase;
  640.         long rec;        /*record number*/
  641.         char *text;        /*pointer to memo text*/
  642.     ---------------------------------------------------------------
  643.         This function replaces the memo field of the record "rec", which
  644. must be a LONG  integer,  with an ASCII text file,  specified in "text".
  645. The  original  memo  field pointer is  returned by this  function (as an
  646. unsigned integer)  upon successful completion.  If an error is detected,
  647. a -1  is returned and the error variable -  dbase->error- will be set to
  648. one of the following error codes:
  649.             1=record  does  not  have  a  memo  field  
  650.             2=cannot open specified text file
  651.             3=cannot re-open .DBT file
  652.             4=code not yet assigned
  653.         
  654.         As is presently the case in all the C2DBASE functions  that deal
  655. with memo fields,  only one such field per record  is  assumed.  If more
  656. than one exist, only the first memo field will be processed.
  657.         
  658.         NOTE:  The maximum  file length that  can be read into  the .DBT
  659. file is 2048 bytes for each record.  Any text beyond this length will be
  660. truncated and a warning  message  will  be  displayed  on  stdout.  This
  661. should be  sufficient  for most  applications.   If  more  than  this is
  662. required, increase MEMOMAX in the dbase.h header file.
  663.         
  664.         NOTE:  This function may be used to input memo  field data under
  665. program control (something DBASE presently has no provisions for). Using
  666. the run command,  your favorite editor can be evoked to create  the text
  667. file,  then this function is used to bring that text file  into the .DBT
  668. file and set the memo pointer of the record. (see CDBUTIL)
  669.         
  670.         NOTE:  a -1  is the same as 65535,  so a check should be made on
  671. the error variable to see if it is non-zero (unless,  of course, you are
  672. sure their isn't 65535 memos in the .DBT).
  673.  
  674.  
  675. ONOFFDBT
  676.  
  677. SYNOPSIS:
  678.         onoffdbt(dbase,mode)
  679.         struct dbinfo    *dbase;
  680.         int mode;     /* 0 removes .DBT, 1 attaches .DBT*/
  681.     ----------------------------------------------------------------
  682.         This function  is  useful  if  a .DBT file becomes  corrupted or
  683. otherwise unuseable.   DBASEIII will not allow  a .DBF file that  has an
  684. associated .DBT  file to be  used if the .DBT  file is not  available or
  685. otherwise unreadable.   There may be occaisions where the .DBF  file may
  686. have to be used without the .DBT file as may be  the case  when the .DBT
  687. file  has become  corrupted or  damaged.   This function  will  turn the
  688. DBASE.DBT search function on and off.   If the .DBF  file is to  be used
  689. without its associated  .DBT,  the mode parameter should  be zero.  This
  690. can be reversed (  if the .DBT latter becomes  available, or something),
  691. by running this function with a mode of one. 
  692.         .DBF  files  that  originally  had  no  memo  fields,  cannot be
  693. associated with a .DBT file, and running this function in mode one, will
  694. leave these files unaffected.
  695.         In mode one,  this function verifies  the existence of  the .DBT
  696. file in the same directory as  the .DBF file.   If it is not  found, and
  697. error results and the .DBF is not changed.
  698.         A zero is returned upon successful completion, otherwise a -1 is
  699. return with one of the following error codes in dbase->error;
  700.             1 = could not find .DBT file (mode one)
  701.             2 = database has no .DBT file (mode one)
  702.             3 = invalid mode number passed
  703.         
  704.         NOTE:  A write  error on the  .DBF file will  cause an immediate
  705. exit from the program with an dos ERRORLEVEL of 4.
  706.  
  707.  
  708. DBTPACK
  709.  
  710. SYNOPSIS:
  711.         dbtpack(dbase)
  712.         struct dbinfo *dbase;
  713.     ---------------------------------------------------------------
  714.         DBASEIII deal with memo files (.DBT) fairly inefficiently.  Each
  715. record in the .DBF file,  if it has a memo field, points to a particular
  716. offset into the .DBT file.  When you change, delete, or otherwise modify
  717. a memo  field,  the old one is  still left  intact,  but a new one (your
  718. modified memo)  is appended  to the bottom of  the file,  and the record
  719. pointer updated.   If you are in the habit of making a lot of changes to
  720. your memo fields (which becomes a more reasonable thing to do  since you
  721. now have  these functions),  the .DBT file  may contain a lot  of wasted
  722. disk space.   This function  writes  a new .DBT  file,  copying only the
  723. relevant  text  to  it.   The old .DBT file is  left intact with  a .BAK
  724. extension.   The only way you can accomplish with  DBASE III is  to copy
  725. your database over entirely,  which consumes more disk  space since both
  726. the .DBF and the .DBT  gets  duplicated.  Try this function on a  few of
  727. your .DBT files and see the difference in disk size.
  728.         
  729.         The only required parameter to this function is a pointer to the
  730. dbinfo structure.   If successful it returns a zero,  otherwise  a -1 is
  731. returned, and 'dbase->error' will be one of the following error codes;
  732.             1 = database has no .DBT file
  733.             2 = Cannot open original .DBT file
  734.             3 = Cannot create new .DBT file
  735.             4 = Error writing to new .DBT file
  736.             5 = Error updating .DBF file
  737.             6 = TBDL
  738.         
  739.         As is presently the case in all the C2DBASE  functions that deal
  740. with memo fields,  only one such field  per record is assumed.   If more
  741. than one exist, only the first memo field will be processed.
  742.         
  743.         NOTE:  Memo  text  fields  longer than MEMOMAX  (presently 2048)
  744. bytes,  with be truncated to that length.   MEMOMAX,  the #define in the
  745. header file may be increased, if this poses a problem.
  746.         
  747.         NOTE:  Make sure  there is  enough disk space  before performing
  748. this function.  The most free space that will be needed will be equal to
  749. the size of the original .DBT file.
  750.         
  751.         NOTE: If you feel a bit queasy about using this function on your
  752. valuable  database files,  make a copy of them  first,  test out the new
  753. files, then you can dispose of the originals. Always wise to be safe.
  754.  
  755.  
  756. PASS 
  757.  
  758. SYNOPSIS:
  759.         pass(param,dir)
  760.         char *param;    /*string variable to pass to DBASE */
  761.         char *dir;    /*directory to write RETURN.MEM file*/
  762.     ----------------------------------------------------------------
  763.         This function,  along with a few DBASE program statments, passes
  764. one parameter to DBASE's memory variable area.   This is done by writing
  765. the variable 'param',  which must be a character string pointer (numbers
  766. must  be  converted to  character strings),  to a file  in the directory
  767. specified  by  the string  pointer 'dir'  (dir=NULL will default  to the
  768. current directory).  This file will be called RETURN.MEM.  The parameter
  769. is recovered from DBASE by the program statement: 
  770.                         RESTORE FROM RETURN ADDITIVE 
  771.         The  parameter  will  be  named  RETPARAM,   and  will  then  be
  772. accessible (privately)  to the DBASE program that  called  the function.
  773. To make the passed parameter generally available (global), the following
  774. program statement should appear before the C function is called; 
  775.                         PUBLIC RETPARAM
  776.                 If the creation of RETURN.MEM  is successful,  a zero is
  777. returned by this function.   Otherwise an error message is displayed and
  778. the program exits immediately. 
  779.         
  780.         NOTE:  Since the "\"  character always gets interpreted as "ESC"
  781. in 'C',the forward slash -  "/"  - must be substituted in its place when
  782. specifying the directory for the 'dir' parameter.
  783.         
  784.         NOTE:  if this function is used  repeatedly in a  DBASE program,
  785. either delete RETURN.MEM before each use, or SET SAFETY OFF to avoid the
  786. overwrite message and prompt.
  787.         
  788.         PROGRAMMER'S NOTE: This function uses the global structure cmem,
  789. which is of type cmemvar. (see dbase.h for details)
  790.          
  791.  
  792.  
  793. DBCLOSE 
  794.  
  795. SYNOPSIS:
  796.         dbclose(dbase)
  797.         struct dbinfo *dbase;
  798.     ----------------------------------------------------------------
  799.         This function closes all  the files associated  with the C2DBASE
  800. functions and the .DBF file that  are currently open.   It should always
  801. be  the  last  C2DBASE  function  called,  so  as  to  prevent accidents
  802. happening (which open files are prone to have).The only passed parameter
  803. to this function is the pointer to the dbinfo structure.
  804.  
  805.  
  806. CDBUTIL
  807.  
  808. CDBUTIL MODES
  809.  
  810. GENERAL
  811.  
  812.         The CDBUTIL program has been provided for two reasons. First and
  813. foremost,  as an example of how to use the C2DBASE functions - hence the
  814. inclusion  of  the source  code.   No special programmig techniques were
  815. used,  nothing especially witty or stupendous. But it is a good place to
  816. start  learning how  to use these  functions.   If you are serious about
  817. DBASE III, but don't like it's limitations, and if you are familiar with
  818. the  'C'  language,  then you can turn DBASE III into  DBASE  IV (enough
  819. superlatives).   The CDBUTIL program will also  be very useful  to those
  820. who haven't the knowledge and/or the inclination (there  are  those, God
  821. luv'em)  to get into programming.   The program, with its modes, extends
  822. the capabilities of DBASE III enough to  be appreciated,  but to get the
  823. full  power of  C2DBASE,  you need to be  able to write C  programs. For
  824. those of you who aren't already familiar with the language,  this may be
  825. some small incentive to learn.
  826.         The CDBUTIL program may be  used inside or  outside of DBASEIII.
  827. If it  is being used inside  of DBASEIII,  it is best  to incorporate it
  828. into .PRG and .PRC command files to extend the capabilities of DBASEIII.
  829. An example of such a .PRC file is also included with this package.
  830.         Certain modes (such as packing a memo file) should only be used,
  831. when not in DBASE.   Other modes (such as listing record)  make no sense
  832. to use inside of DBASE.   They are provided  to give you access  to your
  833. databases without DBASE.   Still  other modes (such as  keyword searchs,
  834. programmed-controlled memo writing, count to memory variable, etc.) only
  835. make  sense when  using them inside of  DBASE.   I have experienced some
  836. small  difficulty in running CDBUTIL in  a multitasking  environment. My
  837. present guess is  that  the 20  file limit set for  MS-DOS was exceeded.
  838. These difficulties disappeared when I re-instated regular DOS.
  839.         The  CDBUTIL program should  reside  in  the  directory  you are
  840. using, unless it is in your PATH, or you have a utility which allows you
  841. to run programs from other directories.
  842.         Any time CDBUTIL performs an error exit, the DOS ERRORLEVEL will
  843. be set to 1.
  844.         The CDBUTIL modes only scratch the surface of  the possibilities
  845. of C2DBASE.  Creativity will extend the flexibility and power with which
  846. you can manipulate your databases. 
  847.  
  848.  
  849. FUNCTION CALLING PROCEDURE
  850.  
  851.         CDBUTIL  is a collection of  useful functions  gathered into one
  852. program.   The  modes are numbered,  and  each mode expects  a specified
  853. argument list.   "CDBUTIL  ?",  "CDBUTIL HELP",  or just plain "CDBUTIL"
  854. will  display a list  of  the  modes  available  and  the  argument list
  855. required.   The  included  modes are  discussed  in  more  detail below.
  856. Parameters indicated with <  >  are required, while parameters indicated
  857. with [ ] are optional.The  source code for the CDBUTIL  program  is also
  858. included as an example of how to program with the C2DBASE functions.
  859.  
  860.  
  861. DISPLAY FILE INFORMATION
  862.  
  863. MODE 1 - DISPLAY FILE INFORMATION
  864. =====================================
  865.         CALLING STATEMENT- CDBUTIL 1 <DBFfile> [NDXfile NDXfile...]
  866.         
  867.         This  mode  displays  the database information  of the specified
  868. file.   The  display is  self-explanatory.   NDXfiles  (optional) may be
  869. specified in the calling statement.   The complete pathname may  be used
  870. to  examine  files  in  foreign  directories.    If  NDXfiles  are  also
  871. specified,  their extensions  are assumed to  be  .NDX  if  they are not
  872. present.   They are also assumed to be in the same directory as the .DBF
  873. file, and their PATH should not be specified.  If one of the index files
  874. cannot be found, the mode aborts and no display is given.
  875.         This mode should be used outside of DBASE III.
  876.  
  877.  
  878. UNFILTERED RECORD COUNT
  879.  
  880. MODE 2 - UNFILTERED RECORD COUNT
  881. ================================
  882.         CALLING STATEMENT - CDBUTIL 2 <DBfile>
  883.         
  884.         If there are large databases in your work,  and periodically you
  885. need to know how many records are contained therein, you can use DBASE's
  886. COUNT command, which could take awhile (minutes with databases in excess
  887. of  1000  records).   Or you could use mode 2  or 3  of CDBUTIL.  mode 2
  888. displays the unfiltered record count on the terminal screen.  This count
  889. will  include all records,  including  thosed  marked  for  deletion, or
  890. filtered out-of-sight.  Pathnames are allowed, and the .DBF extension is
  891. assumed. 
  892.         This mode may be used inside or outside of DBASE III.
  893.  
  894.  
  895. UNFILTERED COUNT TO MEMORY VARIABLE
  896.  
  897. MODE 3 - UNFILTERED COUNT TO MEMORY VARIABLE
  898. ============================================
  899.     CALLING STATEMENT - CDBUTIL 3 <DBFfile>
  900.  
  901.         This mode is the same as mode 2  except that the count result is
  902. placed in a .MEM file,  in the same directory as the .DBF file,  so that
  903. it may be  RESTORED  (ADDITIVE),  and made available to  DBASE III.  For
  904. further   details   please   examine   the   CDBUTIL.PRC   program,  the
  905. documentation on the C2DBASE "pass"  function,  and the  DBASE manual on
  906. .MEM files.Although the "pass" function is a bit limited in this version
  907. of C2DBASE, this CDBUTIL mode is an example of how external programs may
  908. brings results and answers into DBASE III for processing.   If you would
  909. like to  extend  the mathematical capability of  DBASE,  and can code up
  910. what you want in 'C',  then DBASE is mathmatically limited  only by your
  911. creativety and knowledge.
  912.         
  913.         NOTE:  The maximum number of records that can be  processed with
  914. this CDBUTIL mode  is  65535.   This is  a  limitation  of  CDBUTIL, not
  915. C2DBASE.
  916.  
  917.  
  918. RECORD LISTING
  919.  
  920. MODE 4 -  RECORD LISTING
  921. ========================
  922.         CALLING STATEMENT - CDBUTIL 4 <DBfile> [rec. range]
  923.         
  924.         This mode lists the records of a database file.  All the records
  925. contained in the file will be  listed unless the optional  [rec.  range]
  926. is given, in which case only those records (inclusively) will be listed.
  927. The records are listed in numerical order.
  928.         The .DBF extension is assumed if not present, and a pathname may
  929. be given for  the .DBF file.
  930.         As presently programmed,  records longer than 80 bytes will wrap
  931. around the screen,  similar to DBASE III. I find this annoying, and will
  932. probably  program some  formatting  options,  or  specific field request
  933. capabilities into  CDBUTIL in  the next  version.   Since the source for
  934. CDBUTIL is given, you may do the same if you don't feel like waiting for
  935. me.
  936.         DBASE gives a better listing of .DBF records,  so this mode need
  937. only be used when outside of DBASE to view database records.
  938.  
  939.  
  940. MEMO FIELD DISPLAY
  941.  
  942. MODE 5 - MEMO FIELD DISPLAY
  943. ===============================
  944.         CALLING STATEMENT - CDBUTIL 5 <DBFfile> <rec#> [[+],[-],[-rec#]]
  945.         
  946.         This mode simply illustrates the use of  the  'memoread' C2DBASE
  947. function.  With this, and a few other C2DBASE functions, the memo fields
  948. in DBASE III can really be put to use.   This memo field display CDBUTIL
  949. mode only begins to tap the power,  and is provided as  much for example
  950. as for usefulness.
  951.         CDBUTIL mode 5 displays the memo field for the record specified.
  952. If  the .DBF  specified  does  not  have  a  memo  field,  an  exit with
  953. ERRORLEVEL 1  is performed.  If the record specified has no memo text in
  954. its field, a message is displayed saying so.
  955.         If a '+'  appears after the record number (i.e. 1745+), then all
  956. records  starting  with  the one specified will  have  their  memo field
  957. displayed.   If a '-' appears after the record number (i.e.  135-), then
  958. all records starting with  the first and ending  with  the one specified
  959. will  have  their memo field  displayed.If a starting and  ending record
  960. number is given (i.e.  657-700), then the memo fields for those records,
  961. inclusive,  will be displayed.  Of course, starting number must be lower
  962. than ending number, or else...
  963.         DBASE III gives very  little control  over how the  memo text is
  964. displayed.   Unless the report generator is  used,  you are limited to a
  965. display of  50  columns with an unjustified right edge.   This  is so no
  966. matter how the text  is  actually  formatted.   If you use  another word
  967. processor to write the text,  and format it as you desire, you are still
  968. limited  to  DBASE's format.   The report  generator  gives  a  bit more
  969. flexibility,  but not much.  With this mode of CDBUTIL, the display will
  970. appear formatted as you typed it.
  971.         Please  read  the   documentation   for   'memoread'  for  other
  972. restrictions and limitations on using this  mode.   Refer to CDBUTIL.PRC
  973. on how to use this mode inside of DBASE III.
  974.         
  975.         NOTE: DBASE III version 1.2 allows much greater flexibility over
  976. the formatting  of  displayed memo  fields.   If you  have this version,
  977. check  out this capability before  you use this  mode.   you may like it
  978. better.
  979.  
  980.  
  981. KEY PHRASE SEARCH THROUGH MEMO FIELD
  982.  
  983. MODE 6 - KEY PHRASE SEARCH THROUGH MEMO FIELDS
  984. ==============================================
  985.         CALLING STATEMENT - CDBUTIL 6 <DBFfile> <phrase> [rec. range]
  986.         
  987.         Here's where  we begin to see what  we  can do with some  of the
  988. C2DBASE  functions.   DBASE III provides no  capability to use  the memo
  989. field beyond simple text holders.  With DBASE III, you cannot search the
  990. memo field for keywords,  and  you cannot  do  a  listing  based  on the
  991. contents of the memo field.
  992.         This mode of CDBUTIL searches the memo fields of a database, and
  993. lists (on stdout)  all  records whose memo  field  contains  the keyword
  994. <phrase>.   If a record range is provided (optional), it is given in the
  995. form xxx-xxx (i.e 546-601).   In this case only those  records specified
  996. in the range will be searched for the keyword.   For each record examied
  997. that does not contain the keyword or keyphrase, a dot is printed to give
  998. the user some feedback that the program is proceeding.
  999.         The keyword search is not case specific.   It will find  a match
  1000. on both upper and lower case.
  1001.         Since  a  space  between  words  on  the  command  line  will be
  1002. interpreted as  a  different  argument,  spaces  are  designated  by the
  1003. underscore character '_'.  In other words, in order to find "the phrase"
  1004. it  must  be  written as  "the_phrase".   To find "one two  three" it is
  1005. necessary  to specify  it as "one_two_three".   This inconvenience comes
  1006. about from DOS's commandline parsing.  In a latter version, I expect the
  1007. calling statement for this mode to be made more convenient.
  1008.         With a little imagination and creativity,  the memo field can be
  1009. made to perform some very useful work.
  1010.  
  1011.  
  1012. PROGRAMM-CONTROLLED MEMO WRITING
  1013.  
  1014. MODE 7 - PROGRAMM-CONTROLLED MEMO WRITING
  1015. =========================================
  1016.         CALLING STATMENT - CDBUTIL 7 <DBFfile> <rec#> <textfile> [del]
  1017.         
  1018.         Presently DBASEIII provides  no way  to write in the  memo field
  1019. under program control.   To edit the memo field,  you must  be in record
  1020. edit mode (possible under program control), manaully place the cursor on
  1021. the  field,   then  press  ctrl-pgdn.   When  writing  applications  for
  1022. end-users,  this may be cumbersome,  or inconvenient. This CDBUTIL mode,
  1023. along with  the appropriate statements  in  a  .PRG  or  .PRC  file (see
  1024. CDBUTIL.PRC), and an external word-processor, provides the capability of
  1025. writing memo fields under program control.
  1026.         This capability is a two-step process.  First a textfile must be
  1027. created on disk  keeping in mind any size  restrictions  coming from the
  1028. 'memoadd'  C2DBASE function.   This may be done by using the RUN command
  1029. to invoke your wordprocessor (i.e.   RUN ED file.txt).  Once the file is
  1030. on disk,  CDBUTIL mode 7  will bring it neatly  into the  .DBT file, and
  1031. update the specified record.  Refer to the CDBUTIL.PRC documentation for
  1032. further clarification.
  1033.         To  use mode  7,  the required  parameters  are as  shown above.
  1034. Pathnames  for both  the DBFfile  and  the  textfile  is  permitted. The
  1035. DBFfile extension  may  be  ommitted,  but  the  textfile  must  have an
  1036. extension.   The record number must exist in the database.   If "del" is
  1037. specified  (optional),   the   textfile  is  deleted   after  successful
  1038. incorporation into the .DBT file.
  1039.         You now have a choice in how you create your memo fields.  DBASE
  1040. III's ^Kr,  when you are in its word processor, will also read in a text
  1041. file from disk, but first you have to be in the word processor. This may
  1042. not be much of an  inconvenience at all.   It is probably  better to use
  1043. DBASE's own facilities when it does not interferre with what you want to
  1044. do or the convenience with which you do it.
  1045.  
  1046.  
  1047. SEPARATE .DBT FROM .DBF
  1048.  
  1049. MODE 8 - DISCONNECT/CONNECT .DBT FILE
  1050. =====================================
  1051.         CALLING STATEMENT - <DBFfile> <submode>
  1052.         
  1053.         This  mode  implements  the C2DBASE 'onoffdbt'  function. Please
  1054. read the documentation for this function in  order to  understand how to
  1055. use this DBUTIL mode.   The submode is zero when you want to divorce the
  1056. .DBT file  from  the .DBF  file.   The submode is  one when  you want to
  1057. establish that connection again.  If this sound fuzzy, refer to the text
  1058. on the 'onoffdbt' function.
  1059.         This mode should only be used outside of DBASE III.
  1060.  
  1061.  
  1062. PACK MEMO FILE
  1063.  
  1064. MODE 9 - PACKING .DBT FILE
  1065. ==========================
  1066.         CALLING STATEMENT - <DBFfile>
  1067.         
  1068.         This  mode  implements  the C2DBASE  'dbtpack'  function. Please
  1069. refer to the documentation on this function to understand what this mode
  1070. is doing, when to use it, and the limitations which must be observed.
  1071.         This mode should only be used outside of DBASE III.
  1072.  
  1073.  
  1074. #include "\lattice\h\glfstdio.h"        /*greenleaf  header*/
  1075. #include "\lattice\h\dbase.h"
  1076. #include "\lattice\h\fcntl.h"        /*Lattice Header*/
  1077. #include "\lattice\h\ctype.h"        /*Lattice header*/
  1078. #include "\lattice\h\disk.h"        /*Greenleaf header file*/
  1079. /*modify the above PATHs for your own system*/
  1080.  
  1081. static char *help[]={
  1082. "DBASE UTILITIES PROGRAM version 1.0  Lee Mowatt - 10/85",
  1083. " To perform a particular function, the command line or the RUN string",
  1084. "takes the following generalized form;",
  1085. "        CDBUTIL <func#> <.DBF file> [argument list]",
  1086. "               (from DOS)",
  1087. "                or",
  1088. "        RUN CDBUTIL <func#> <.DBF file> [argument list]",
  1089. "            (from inside DBASE III)",
  1090. "\n",
  1091. "FUNC. #        FUNCTION            ARGUMENT LIST",
  1092. "======================================================================",
  1093. " 1      Database information       <DBFfile> [NDXfile NDXfile...]",
  1094. " 2      Unfiltered record count    <DBFfile>",
  1095. " 3      Count to memory variable   <DBFfile>",
  1096. " 4      Record listing             <DBFfile> [rec.range]",
  1097. " 5      Memo field display         <DBFfile> <rec#> [[+],[-],[-rec#]]",
  1098. " 6      memo field searching       <DBFfile> <phrase> [rec. range]",
  1099. " 7      memo field from textfile   <DBFfile> <rec#> <textfile> [del]",
  1100. " 8      disconnect/connect .DBT    <DBFfile> <0 or 1> ",
  1101. "                                              (0=disconnect, 1=connect)",
  1102. " 9      Pack a .DBT file           <DBFfile>",
  1103. " NOTE: [rec. range] is given in the form start#-end# (i.e. 12-234)",
  1104. NULL
  1105. };
  1106.  
  1107. struct commlist
  1108.     {
  1109.     int argnum;                    /*# of args on commandline excluding  CDBUTIL*/
  1110.     char *args[20];                /*in-program argument string pointers*/
  1111.     };
  1112.  
  1113. /*the following defines help in reading the function source code*/
  1114. #define    FUNC        files->args[0]
  1115. #define    DBFILE        files->args[1]
  1116. #define NDXFILE(x)    files->args[x+1]
  1117. #define RECNUM        files->args[2]
  1118. #define PHRASE        files->args[2]
  1119. #define RANGE        files->args[3]
  1120. #define SUBMODE        files->args[2]
  1121. #define TXT            files->args[3]
  1122.  
  1123. main(argc,argv)
  1124.  
  1125. int argc;            /*number of arguments*/
  1126. char *argv[];        /*argument string pointers*/
  1127.     
  1128. {
  1129. struct commlist arglist;        /*argument structure*/
  1130. int loop,count;                    /*general purpose integer variables*/
  1131. int function;                    /*C2DBASE function number*/
  1132. int fnum;                        /*DBF file number*/
  1133. static struct dbinfo db;        /*DBASE information structure-must be static*/
  1134. char *ext=".dbf";                /*DBF file extension*/
  1135. char *path;                        /*file path name*/
  1136. char *stpchr();                    /*Lattice function*/
  1137.  
  1138. if  ((argc==1)  || (isdigit(argv[1][0]) == 0))
  1139.     {
  1140.     for (loop=0;help[loop] != NULL;loop++)
  1141.         printf("%s\n",help[loop]);
  1142.     exit(0);
  1143.     }
  1144. for (loop=0;loop<argc-1;loop++)
  1145.     arglist.args[loop]=argv[loop+1];
  1146. arglist.argnum=argc-1;             /*program name not included in argument list*/
  1147.  
  1148. path[0]=NULL;
  1149. strcat(path,argv[2]);
  1150. if (stpchr(argv[2],'.') == NULL)    /*add DBF extension if not present*/
  1151.     strcat(path,ext);
  1152. fnum=dbheader(path, &db);       /*fill information structure*/
  1153. if (db.error != 0)                    /*check for error*/
  1154.         {
  1155.         switch (db.error)
  1156.                 {
  1157.                 case 1:
  1158.                         printf("\7Filename MUST have .DBF extension\n");
  1159.                         exit(1); break;
  1160.                 case 2:
  1161.                         printf("\7Cannot open %s\n",path);
  1162.                         exit(1); break;
  1163.                 case 3:
  1164.                         printf("\7Not a DBASE .DBF file\n");
  1165.                         exit(1); break;
  1166.                 case 4:
  1167.                         printf("\7Cannot open associated .DBT file.\n");
  1168.                         exit(1);break;
  1169.                 default:
  1170.                         printf("Unknown error code - %d\n",db.error);
  1171.                         exit(1); break;
  1172.                 }
  1173.         }
  1174.  
  1175. stcd_i(argv[1],&function);        /*convert decimal string to integer*/
  1176. switch (function)
  1177.     {
  1178.     case 1:
  1179.         func1(&db,&arglist);break;
  1180.     case 2:
  1181.         func2(&db,&arglist);break;
  1182.     case 3:
  1183.         func3(&db,&arglist);break;
  1184.     case 4:
  1185.         func4(&db,&arglist);break;
  1186.     case 5:
  1187.         func5(&db,&arglist);break;
  1188.     case 6:
  1189.         func6(&db,&arglist);break;
  1190.     case 7:
  1191.         func7(&db,&arglist);break;
  1192.     case 8:
  1193.         func8(&db,&arglist);break;
  1194.     case 9:
  1195.         func9(&db,&arglist);break;
  1196.     default:
  1197.         printf("\7Unknown CDBUTIL function number\n");break;
  1198.     }
  1199. dbclose(&db);
  1200. }
  1201.  
  1202.  
  1203. /**********************************************************************/
  1204. func1(dbase,files)            /*display file information*/
  1205.  
  1206. struct dbinfo *dbase;
  1207. struct commlist *files;
  1208.  
  1209. {
  1210. int loop;
  1211. char *stpchr();                /*Lattice function*/
  1212. char *string,*temp;            /*general purpose caharacter pointer*/
  1213. char *path;                    /*pathname*/
  1214. char c=0x5c;                /*ascii number for '\'*/
  1215. char *ext=".ndx";            /*index extensionto be appended if not present*/
  1216.  
  1217. for (loop=3;loop<=files->argnum;loop++)            /*process index files*/
  1218.     {
  1219.     if ((string=stpchr(DBFILE,c)) != NULL)    /*PATH processing*/
  1220.         {
  1221.          while ((temp=stpchr(string,c)) != NULL)
  1222.             string=temp+1;                     /*find last '\'*/
  1223.         stccpy(path,DBFILE,(string-DBFILE+1));
  1224.         }
  1225.     strcat(path,NDXFILE(loop-2));
  1226.     if (stpchr(path,'.') == NULL)
  1227.         strcat(path,ext);
  1228.     ndxread(dbase,path);
  1229.     /*test for errors*/
  1230.     if (dbase->error !=0)
  1231.         {
  1232.         switch (dbase->error)
  1233.             {
  1234.             case 1:
  1235.                 printf("\7Index file must have .NDX extension\n");
  1236.                 exit(1);break;
  1237.             case 2:
  1238.                 printf("\7Cannot open %s\n",path);
  1239.                 exit(1);break;
  1240.             case 3:
  1241.                 printf("\7Wrong index file for database being used\n");
  1242.                 exit(1);break;
  1243.             default:
  1244.                 printf("\7Unknown ndxread error code-%d\n",dbase->error);
  1245.                 exit(1);break;
  1246.             }
  1247.         }
  1248.     }
  1249. dbstat(dbase);            /*display files information*/
  1250. }
  1251.  
  1252.  
  1253. /**********************************************************************/
  1254. func2(dbase,files)                    /*unfiltered record count to screen*/
  1255.  
  1256. struct dbinfo *dbase;
  1257. struct commlist *files;
  1258.  
  1259. {
  1260. printf("%ld records in %s\n",dbase->info.quan,dbase->filname);
  1261. }
  1262.  
  1263.  
  1264. /**********************************************************************/
  1265. func3(dbase,files)
  1266.  
  1267. struct dbinfo *dbase;
  1268. struct commlist *files;
  1269.  
  1270. {
  1271. char count[10];                        /*string of record count*/
  1272. char c=0x5c;                        /*ascii number for '\'*/
  1273. char *string,*temp;                    /*general purpose string variables*/
  1274. char path[35];                            /*directory to write .MEM file*/
  1275. char *stpchr();                        /*Lattice function*/
  1276.  
  1277. stci_d(count,(int)(dbase->info.quan),10);    /*convert record number to string*/
  1278.  
  1279. if ((string=stpchr(DBFILE,c)) != NULL)    /*PATH processing*/
  1280.     {
  1281.     while ((temp=stpchr(string,c)) != NULL)
  1282.         string=temp+1;                     /*find last '\'*/
  1283.     stccpy(path,DBFILE,(string-DBFILE));
  1284.     }
  1285.  
  1286. pass(count,path);
  1287. }
  1288.  
  1289.  
  1290. /**********************************************************************/
  1291. func4(dbase,files)                /* record listing*/
  1292.  
  1293. struct dbinfo *dbase;
  1294. struct commlist *files;
  1295.  
  1296. {
  1297. char *range;
  1298. long start,end,strtol();
  1299. char *string,*record,*stpchr();
  1300. char *temp;
  1301.  
  1302. if ((files->argnum < 3) || (isdigit(files->args[2][0]) == 0))  
  1303.     {start=1L;    end=dbase->info.quan;}    /*no range specified,do all records*/
  1304.   else
  1305.     {
  1306.     range=files->args[2];
  1307.     string=stpchr(range,'-');
  1308.     strxlf(record,range,(string-range));
  1309.     start=strtol(record,&temp,10);
  1310.     strxrt(record,range,strlen(range)-(string-range+1));
  1311.     end=strtol(record,&temp,10);
  1312.     }
  1313.  
  1314. reclist(dbase,start,end);
  1315. }
  1316.  
  1317.  
  1318. /**********************************************************************/
  1319. func5(dbase,files)
  1320.  
  1321. struct dbinfo *dbase;
  1322. struct commlist *files;
  1323. {
  1324. char *memoread();                /*C2DBASE function*/
  1325. char *memotext;                    /*text pointer*/
  1326. char *memoname;                    /*name of memo field*/
  1327. char *stpchr();                    /*Lattice function*/
  1328. long rec,start,end;                /*record numbers*/
  1329. int fieldspace;                    /*length of memo text*/
  1330. int count;                        /*general purpose integer variable*/
  1331. long strtol();                    /*Lattice function*/
  1332. char *temp,*record;
  1333.  
  1334. for (count=0; count<dbase->fieldnum; count++)  /*check that there is a memo field*/
  1335.         {
  1336.         if (dbase->field[count].type == 'M')
  1337.                 memoname=dbase->field[count].name;
  1338.         }
  1339. memoread(dbase,1L);              /*see if this function returns an error*/
  1340. if ( (dbase->error == 1) || (dbase->error == 2) ) /*no memo fields to be read*/
  1341.         {
  1342.         printf("No memo field in this database\n");
  1343.         exit(1);
  1344.         }
  1345. if (stpchr(RECNUM,'+') !=NULL)
  1346.     {
  1347.     start=strtol(RECNUM,&memotext,10);        /*record specified*/
  1348.     end=dbase->info.quan;
  1349.     }
  1350.   else
  1351.     {
  1352.     if ((temp=stpchr(RECNUM,'-')) != NULL)
  1353.         {
  1354.         if (strlen(RECNUM) > (temp-RECNUM+1))                /*range specified*/
  1355.             {
  1356.             strxlf(record,RECNUM,(RECNUM - temp));
  1357.             start=strtol(record,&memotext,10);
  1358.             strxrt(record,RECNUM,strlen(RECNUM)-(temp-RECNUM+1));
  1359.             end=strtol(record,&memotext,10);
  1360.             }
  1361.           else
  1362.             {
  1363.             start=0L;
  1364.             end=strtol(RECNUM,&memotext,10);
  1365.             }
  1366.         }
  1367.       else
  1368.         {
  1369.         start=strtol(RECNUM,&memotext,10);
  1370.         end=start;
  1371.         }
  1372.     }
  1373. for (rec=start;rec<=end;rec++)
  1374.     {
  1375.     memotext=memoread(dbase,rec);
  1376.     if ((dbase->error == 0) || (dbase->error == 5))
  1377.         {
  1378.         printf("\n***%s for record %ld***\n",memoname,rec);
  1379.         fieldspace=strlen(memotext);
  1380.         for (count=0;count<fieldspace;count++)
  1381.             bdos(6,memotext[count]);
  1382.         printf("\n");
  1383.         if (dbase->error == 5)
  1384.             printf("Display truncated.Memo text longer than 2048 characters\n");
  1385.         }
  1386.       else
  1387.         {
  1388.         switch (dbase->error)
  1389.             {
  1390.             case 3:
  1391.                 printf("no memo text for record %ld\n",rec);break;
  1392.             case 4:
  1393.                 printf("error reading .DBT file\n");break;
  1394.             default:
  1395.                 printf("Unknown memoread error -#%d\n",dbase->error);
  1396.                 break;
  1397.             }
  1398.         }
  1399.     }
  1400. }
  1401.  
  1402.  
  1403. /**********************************************************************/
  1404. func6(dbase,files)
  1405.  
  1406. struct dbinfo *dbase;
  1407. struct commlist *files;
  1408. {
  1409. char *memoread();
  1410. long rec,start,end;                /*record numbers*/
  1411. char *temp,*string,*record;        /*general purpose string variable*/
  1412. char *stpchr();
  1413. long strtol();                    /*Lattice function*/
  1414. int find,found=FALSE;            /*find status of textfind function*/
  1415. int loop,count;
  1416.  
  1417. memoread(dbase,1L);              /*see if this function returns an error*/
  1418. if ( (dbase->error == 1) || (dbase->error == 2) ) /*no memo fields to be read*/
  1419.         {
  1420.         printf("No memo field in this database\n");
  1421.         exit(1);
  1422.         }
  1423.  
  1424. count=strlen(PHRASE);
  1425. for (loop=0;loop<count;loop++)
  1426.     {
  1427.     if (PHRASE[loop] == '_')
  1428.         PHRASE[loop] = 0x20;
  1429.     }
  1430.  
  1431. if ((files->argnum < 4) || (isdigit(RANGE[0]) == 0))     /*no range specified*/
  1432.     {start=1L;    end=dbase->info.quan;}
  1433.   else
  1434.     {                                                    /*range given*/
  1435.     string=stpchr(RANGE,'-');
  1436.     strxlf(record,RANGE,(string-RANGE));
  1437.     start=strtol(record,&temp,10);
  1438.     strxrt(record,RANGE,strlen(RANGE)-(string-RANGE+1));
  1439.     end=strtol(record,&temp,10);
  1440.     }
  1441.  
  1442. printf("search for %s\n",PHRASE);
  1443. for (rec=start;rec<=end;rec++)
  1444.     {
  1445.     find=textfind(dbase,rec,PHRASE);
  1446.     switch (find)
  1447.         {
  1448.         case 1:
  1449.             found=TRUE;
  1450.             printf("\nRecord %ld ",rec);
  1451.             break;
  1452.         case 0:
  1453.             printf(".");break;
  1454.         case -1:
  1455.             if (dbase->error == 2)
  1456.                 {
  1457.                 printf("Error- search string is NULL\n");
  1458.                 exit(1);
  1459.                 }
  1460.               else
  1461.                 {
  1462.                 if (dbase->error == 3)
  1463.                     printf("Error reading .DBT file.\n");
  1464.                 }
  1465.             break;
  1466.         default:
  1467.             printf("Unknown error\n"); break;
  1468.         }
  1469.     }
  1470. printf("\n");
  1471. }
  1472.  
  1473.  
  1474. /**********************************************************************/
  1475. func7(dbase,files)
  1476.  
  1477. struct dbinfo *dbase;
  1478. struct commlist *files;
  1479. {
  1480. unsigned memoadd();                /*C2DBASE function*/
  1481. static long rec;                /*record number*/
  1482. long strtol();                    /*Lattice function*/
  1483. char *stpchr();                    /*Lattice function*/
  1484. struct DISKTABLE text;            /*structure for Greenleaf function 'dos2delete*/
  1485.                                 /*found in disk.h header*/
  1486.  
  1487. rec=strtol(RECNUM);
  1488. if (stpchr(TXT,'.') ==NULL)        /* test for proper arguments*/
  1489.     {printf("\7Command line error\n");    exit(1);}
  1490.  
  1491. if (memoadd(dbase,rec,TXT) == -1)
  1492.     {
  1493.     switch (dbase->error)
  1494.         {
  1495.         case 0:
  1496.             break;
  1497.         case 1:
  1498.             printf("\7Record does not have a memo field.\n");    break;
  1499.         case 2:
  1500.             printf("\7Cannot open %s\n",TXT);    break;
  1501.         case 3:
  1502.             printf("\7Cannot re-open .DBT file\n");    break;
  1503.         default:
  1504.             printf("\7Unknown error\n");    break;
  1505.         }
  1506.     }
  1507.   else
  1508.     {
  1509.     if ((files->args[4] == "del") || (files->args[4]=="DEL"))
  1510.         {
  1511.         text.string=TXT;
  1512.         dos2delete(&text);            /*delete text file*/
  1513.         }
  1514.     }
  1515. }
  1516.  
  1517.  
  1518. /**********************************************************************/
  1519. func8(dbase,files)
  1520.  
  1521. struct dbinfo *dbase;
  1522. struct commlist *files;
  1523. {
  1524. onoffdbt(dbase,SUBMODE);
  1525. }
  1526.  
  1527.  
  1528. /**********************************************************************/
  1529. func9(dbase,files)
  1530.  
  1531. struct dbinfo *dbase;
  1532. struct commlist *files;
  1533. {
  1534. if (dbtpack(dbase) != 0)
  1535.     {
  1536.     switch (dbase->error)
  1537.         {
  1538.         case 1:
  1539.             printf("\7Database has no .DBT file\n");    break;
  1540.         case 2:
  1541.             printf("\7Cannot open original .DBT file\n");    break;
  1542.         case 3:
  1543.             printf("\7Cannot create new .DBT file\n");    break;
  1544.         case 4:
  1545.             Printf("\7Error writing to new .DBT file\n");    break;
  1546.         case 5:
  1547.             printf("\7Error updating .DBF file\n");        break;
  1548.         default:
  1549.             printf("\7Unknown DBTPACK error code\n");    break;
  1550.         }
  1551.     }
  1552. }
  1553.             
  1554.  
  1555.  
  1556. CDBUTIL.PRC FOR DBASE III
  1557.  
  1558. EXPLANATION
  1559.  
  1560.         This .PRC  illustrates how to  make DBASE  III sub-programs that
  1561. make  the C2DBASE functions available to  DBASE.   To use this  file you
  1562. must use the SET PROCEDURE TO  command to  tell  DBASE to  search it for
  1563. called procedures,  and the CDBUTIL.EXE program must  be  in the current
  1564. directory or in one of the directories specified by the PATH.  Once this
  1565. is done,  the procedures in this file may be called just as if  the were
  1566. .PRG files on disk.
  1567.         This  set  of  sub-programs  are  only  meant  for  illustration
  1568. purposes only,  although you may find  them  superficially  useful. They
  1569. demonstrate  one  way  the  C  programs  you  create  using  the C2DBASE
  1570. functions may interface to DBASE III.
  1571.         Examine the file listings  of both CDBUTIL.PRC and  CDBUTIL.C to
  1572. get a better idea as to how to  interface to the  C2DBASE functions from
  1573. both inside and outside of DBASE III.  (The .PRC may only be used inside
  1574. DBASE and is only used to evok the real proogram, CDBUTIL.EXE, which may
  1575. also be used  outside of  DBASE.)  Please note that if you  are going to
  1576. recompile the source code for CDBUTIL.C, the directory references in the
  1577. .PRC and .C files are specific to the COMPUSCAN hard  disk.  They should
  1578. be changed to reflect your system.   Also, since the source for both the
  1579. CDBUTIL.C and CDBUTIL.PRC are  available  to  you,  you  may  modify the
  1580. programs to suit your specific needs.   One thing you must not change is
  1581. the credits.   All  references to Lee Mowatt  and COMPUSCAN  must remain
  1582. untouched.
  1583.         
  1584.         The best  way to  use CDBUTIL.PRC is  to  reserve  a  few memory
  1585. variables  devoted to  the arguments required  by  the  procedures. Each
  1586. procedure requires  certain arguments,  which  may  be  easily specified
  1587. using  memory  variables.   The arguments required mimick  the CDBUTIL.C
  1588. modes,  so  if  you reserve memory  variables called  DBFFILE, RECRANGE,
  1589. PHRASE, etc, it becomes very easy to say DO RECCOUNT WITH DBFFILE, or DO
  1590. STRFIND WITH DBFFILE,PHRASE,RECRANGE.   Of course, you must assign these
  1591. variables to the proper text before you use them in this way. It will be
  1592. necessary to read the DBASE III manual if what  is being said here  is a
  1593. little confusing to you.  Also being familiar with the CDBUTIL.EXE modes
  1594. with help a lot in  using this  functions inside of DBASE  III.  Further
  1595. insight  into  the arguments passed  will  be  had by  understanding the
  1596. calling statements for that program.
  1597.         
  1598.         From  inside  of  DBASE the following  procedures  are available
  1599. after the SET PROCEDURE TO statement is executed;
  1600.         
  1601.         RECCOUNT -  This procedure simply displays the unfiltered record
  1602. count  of  the  specified  database.   It  must  be  passed  a parameter
  1603. containing a valid .DBF filename.  (i.e. DO RECCOUNT WITH "\direct\file"
  1604. or DO RECCOUNT WITH DBFFILE).
  1605.         MEMCOUNT -  This procedure puts the unfiltered record count in a
  1606. memory  variable called MEMCOUNT.   Its arguments are the  .DBF filename
  1607. (see RECCOUNT)  and the memory variable that  will be used  to store the
  1608. count.   (i.e.   DO MEMCOUNT WITH DBFFILE, <MEMVAR>, where <MEMVAR> is a
  1609. memory variable of the user's choice.)
  1610.         MEMDISP -  Displays the memo  field for  the  specified records.
  1611. Its  first argument  is  DBFFILE,  while its second  argument  must be a
  1612. string representing a valid record  number,  record range,or starting or
  1613. ending record number.  This procedure is particularly useful if you wish
  1614. to  view  the memo  field in  a format  that  is not  supported by DBASE
  1615. III.See  the documentation on  CDBUTIL.C  mode  5  for  a  more complete
  1616. description of these arguments. 
  1617.         STRFIND  -  This  procedure  duplicates  CDBUTIL.C  mode  6.  It
  1618. requires 3 parameters, DBFFILE, PHRASE, and RECRANGE.
  1619.         
  1620.         WARNING:  When CDBUTIL performs an operation on a file, the file
  1621. it is operating on the is file that is presently stored on disk, NOT THE
  1622. FILE STORED  IN MEMORY.   If you have  made changes or additions  to the
  1623. file  in  memory,  write it out to disk using the USE  or  COPY commands
  1624. before using a CDBUTIL function.
  1625.  
  1626.  
  1627.  PROGRAM
  1628.  
  1629.  *****************
  1630.  PROCEDURE RECOUNT
  1631.  *****************
  1632.  *THIS PROCEDURE PROVIDES A FAST ALTERNATIVE TO DBASE'S COUNT  COMMAND.  iT GIVES
  1633.  *AN UNFILTERED COUNT OF THE NUMBER OF RECORD IN A .DBF FILE.  (NORMALLY, YOU CAN
  1634.  *HIDE CERTAIN RECORDS FROM  DBASE BY  USING THE 'SET  FILTER  TO'  COMMAND. THIS
  1635.  *WOULD CHANGE THE RECORD COUNT. THIS PROCEDURE INCLUDES THOSE HIDDEN RECORDS.)
  1636.    PARAMETERS FILE
  1637.    RUN CDBUTIL.EXE 2 &FILE
  1638.  RETURN
  1639.  
  1640.  ******************
  1641.  PROCEDURE MEMCOUNT
  1642.  ******************
  1643.  *THIS PROCEDURE IS THE SAME AS RECOUNT,  EXCEPT THAT THE RECORD  COUNT IS PASSED
  1644.  *TO A USER SPECIFIED MEMORY VARIABLE.
  1645.    PARAMETERS FILE,RCOUNT
  1646.    RUN CDBUTIL.EXE 3 &FILE
  1647.    *ESTABLISH FULL PATHNAME OF .MEM FILE
  1648.    TEMP=SUBSTR(FILE,1)
  1649.    SLASH=AT("\",TEMP)
  1650.    POSITION=0
  1651.    DO WHILE SLASH > 0
  1652.      POSITION=POSITION+SLASH
  1653.      TEMP=SUBSTR(FILE,1+POSITION)
  1654.      SLASH=AT("\",TEMP)
  1655.    ENDDO
  1656.    MEMFILE=SUBSTR(FILE,1,POSITION)+'RETURN'
  1657.    RESTORE FROM &MEMFILE ADDITIVE
  1658.    RCOUNT=VAL(RETPARAM)
  1659.    *RETPARAM IS ALWAYS RESTORED AS A STRING  
  1660.  RETURN
  1661.  
  1662.  *****************
  1663.  PROCEDURE MEMDISP
  1664.  *****************
  1665.  *THIS PROCEDURE DISPLAYS THE MEMO FIELD(S) SPECIFIED IN THE VARIABLE RECRANGE
  1666.  *RECRANGE MUST BE A STRING REPRESENTING A RECORD NUMBER, RECORD RANGE, OR 
  1667.  *STARTING OR ENDING RECORD NUMBER.
  1668.    PARAMETERS FILE,RECRANGE
  1669.    RUN CDBUTIL.EXE 5 &FILE &RECRANGE
  1670.  RETURN
  1671.  
  1672.  ******************
  1673.  PROCEDURE STRFIND
  1674.  ******************
  1675.  *THIS PROCEDURE SEARCHES THROUGH RECORDS TO FIND A KEYPHRASE. THE RECORDS
  1676.  *SEARCHED ARE SPECIFIED IN THE THIRD VARIABLE RECRANGE AND MUST BE A STRING
  1677.  *OR STRING VARIABLE REPRESENTING THE RECORD OR RECORD RANGE. THE KEYPHRASE 
  1678.  *IS GIVEN IN THE SECOND VARIABLE, AND THE FILE TO BE SEARCHED IS GIVEN IN
  1679.  *THE FIRST VARIABLE.
  1680.    PARAMETERS FILE, PHRASE, RECRANGE
  1681.    RUN CDBUTIL.EXE 6 &FILE &PHRASE &RECRANGE
  1682.  RETURN
  1683.