home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 5 / 05.iso / a / a072 / 1.img / FLEXFILE.EXE / FLEXFILE.DOC < prev    next >
Encoding:
Text File  |  1991-09-19  |  206.7 KB  |  6,102 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.                                FlexFile■
  7.                  (C) Copyright 1990 Ganahl Software
  8.                           All Rights Reserved
  9.  
  10.  
  11.  
  12.  
  13.            Note: This software is a commercial product and is not
  14.            to be copied except for archival purposes.
  15.  
  16.  
  17.  
  18.  
  19.  
  20.    GANAHL Software
  21.    P.O. Box 4275
  22.    Deerfield Beach, Fl 33442
  23.    Tel: (305) 566-1796
  24.    Fax: (305) 566-3517
  25.  
  26.  
  27.  
  28.    Licensing agreement
  29.  
  30.    Use of FlexFile constitutes your acceptance of these terms and
  31.    conditions and your agreement to abide by them.
  32.  
  33.    I have read and agreed to the terms of the Ganahl Software
  34.    License Agreement.  I understand that I am not entitled to
  35.    make any copies of the distribution diskette except for
  36.    archival purposes.  I understand that I may compile this
  37.    software into complete, executable programs and distribute
  38.    those programs without royalty to Ganahl Software.  I
  39.    understand that I may not distribute this software in any
  40.    other way.  I understand that I may not make any copies of the
  41.    documentation for any purpose.
  42.  
  43.    You must signify your consent to this License Agreement by
  44.    signing and returning the enclosed registration card.  If you
  45.    do not agree to the terms of the License Agreement, you must
  46.    return the software with its documentation and destroy any
  47.    copies of the software that you have made.
  48.  
  49.  
  50.  
  51.    Money Back Guarantee
  52.  
  53.    You may return the FlexFile Software product for any reason
  54.    within thirty days of receipt for a refund.  If you choose to
  55.    return FlexFile within this thirty day return period, you must
  56.    destroy any copies of FlexFile that you have made as well as
  57.    any programs (including those that you have distributed) which
  58.    use FlexFile software in any fashion.
  59.  
  60.  
  61.    Warrantee
  62.  
  63.    Ganahl Software warrants the physical diskette and physical
  64.    documentation enclosed herein to be free of defects in materials
  65.    and workmanship for a period of 30 days from the date of
  66.    purchase.  In the event of notification within this warranty
  67.    period of defects in material or workmanship, Ganahl Software
  68.    will replace the defective diskette or documentation.  The remedy
  69.    for breach of this warranty shall be limited to replacement or
  70.    refund of the purchased price and shall not encompass any other
  71.    damages, including but not limited to loss of profit, special
  72.    incidental, consequential, or other similar claims.
  73.  
  74.  
  75.    Ganahl Software specifically disclaims all other warranties,
  76.    expressed or implied, including but not limited to implied
  77.    warranties of merchantability and fitness for a particular
  78.    purpose.  In no event shall Ganahl Software be liable for any
  79.    loss of profit or any other commercial damage, including but
  80.    not limited to special incidental, consequential or other
  81.    damages.
  82.  
  83.  
  84.  
  85.  
  86.  
  87.                    FlexFile Support Policy
  88.  
  89.  
  90.    Who may receive support
  91.  
  92.    Only registered users of FlexFile may receive support.  To
  93.    register simply fill out the registration card that is
  94.    enclosed with the FlexFile package that you receive, fill
  95.    out the information, and send it directly to Ganahl Software.
  96.  
  97.    What you must do
  98.  
  99.    Before contacting our Customer Support please have the
  100.    following information on hand:
  101.  
  102.            1. Your product's serial number and version number (on
  103.               the inside front or back cover of your manual).
  104.            2. FlexFile library used (FlexFile.lib or Flex_87.lib).
  105.            3. Computer make and model.
  106.            4. DOS version.
  107.            5. Network software if applicable.
  108.            6. Clipper version (e.g. S'87, Clipper 5.0, etc.)
  109.  
  110.  
  111.    How to Contact Ganahl Software Technical support
  112.  
  113.    The best method for support of any Clipper product (including
  114.    Clipper itself) is on CompuServe's Nanforum or DBA (Data Based
  115.    Advisor's forum).  Simply post messages to the user ID
  116.    76477,2177.
  117.  
  118.    The reason this is the best support is because you benifit
  119.    from the other users of FlexFile who frequent the forum, the
  120.    Ganahl Software Support folks, and Brice deGanahl (FlexFile's
  121.    Author).
  122.  
  123.    Otherwise either write or call between 9:am and 5:pm (EST)
  124.  
  125.            Ganahl Software
  126.            P.O. Box 4275
  127.            Deerfield Beach, Florida  33442
  128.            Support: (305) 941-5199
  129.            Sales:   (305) 566-1796
  130.            Fax:     (305) 566-3517
  131.  
  132.  
  133.  
  134.     Credits
  135.  
  136.  
  137.     The quality of this project has been enhanced tremendously
  138.     with the help of some exceptional friends.  Specifically, I
  139.     would like to thank Don Caton, Gary Herbstman, Sandy Leaf,
  140.     Terry O'Neill and John Thorla.  Without these folks, there
  141.     would be no FlexFile.
  142.  
  143.     Don Caton selflessly offered innumerable hours, consulting on
  144.     both technical and practical issues in the creation
  145.     FlexFile's design.  In addition, he has relentlessly tested
  146.     the software, dug up insidious bugs, and has been generous
  147.     beyond belief.
  148.  
  149.     Gary Herbstman provided a major influence in the technical
  150.     design of the VLF engine and provided some of its tightest
  151.     code.
  152.  
  153.     Sandy Leaf covered the gamut from business advisor to
  154.     advertising agent. Without Sandy's considerable attention to
  155.     schedule, FlexFile would have been completed anyway... in a
  156.     year or two.
  157.  
  158.     Terry O'Neill took this documentation from a pile of
  159.     scribbled notes to a coherent, comprehensive and clean User
  160.     Manual.  His sense of perfection spilled out of the
  161.     documentation and into the code where he has corrected and
  162.     simplified many of the library's functions.
  163.  
  164.     John Thorla has been an inspiration, an advisor, and a
  165.     friend.  This thanks to John is extended to all the folks at
  166.     his company, Direct Link Software, who have continually
  167.     provided me with encouragement, product testing, need for
  168.     functionality, ideas for marketing, proof reading and a
  169.     multitude of laughs when they were most needed.  Specific
  170.     thanks go to Dave Peters and Randy Robalewsky.
  171.  
  172.     Brice  de Ganahl
  173.     President, Ganahl Software
  174.  
  175.  
  176.  
  177.  
  178.  
  179.                        Overview
  180.  
  181.  
  182.    Variable Length Fields
  183.  
  184.    FlexFile is a very focused dual purpose tool kit for Clipper
  185.    programmers.  Its first and main purpose is to provide a
  186.    complete replacement for Clipper's memo-fields with a more
  187.    powerful and more efficient Variable Length Field engine.  We
  188.    are certain that it will relieve you of the confinement
  189.    imposed by Clipper's memo-fields, but also, we believe it may
  190.    change the way you think about your data base structures in
  191.    general.
  192.  
  193.    FlexFile was designed to be immediately familiar to the
  194.    Clipper programmer. To accomplish this goal, many of the
  195.    function names can only be distinguished from their Clipper
  196.    counterpart by a V_ prefix.  For example, V_USE() opens a DBV
  197.    file in the currently V_SELECT()ed work area.
  198.  
  199.    The similarities extend into the structural use of FlexFile's
  200.    Variable Length Fields (VLF) as well.  FlexFile's version of a
  201.    memo-field (which we will refer to as a pointer-field) is a
  202.    six byte character type field in a DBF file. FlexFile uses
  203.    this pointer-field to store a pointer to variable length data
  204.    in a .DBV file (FlexFile's version of a .DBT file).  These
  205.    similarities allow any Clipper REPLACE syntax which works on
  206.    memo-fields to remain almost unchanged when used with
  207.    FlexFile.  This claim carries in network environments as well.
  208.  
  209.    The benefits and use of FlexFile's Variable Length Fields are
  210.    discussed in detail in the Reference "Variable Length Fields".
  211.    Pay special attention to the section on FlexFile's extended
  212.    features.
  213.  
  214.  
  215.  
  216.    Arrays
  217.  
  218.    FlexFile's strongly typed arrays provide a utility which defy
  219.    the products name.  Instead of being flexible, these arrays
  220.    are purposefully rigid.  The utility of these arrays is
  221.    twofold.  First and foremost, they use far less space than
  222.    their Clipper counterpart.  For example, any Clipper array of
  223.    1,000 elements would require a minimum of 14,000 bytes from
  224.    Clipper's free pool of memory.  A FlexFile array of 1,000
  225.    integers, on the other hand, would require only 2,000 bytes
  226.    from Clipper's free pool of memory.
  227.  
  228.    Typically, large strongly typed arrays are used for scientific
  229.    or statistical matrixes.  For this reason, FlexFile provides a
  230.    host of functions which globally manipulate or query these
  231.    large arrays.
  232.  
  233.  
  234.  
  235.  
  236.    Linking FlexFile into an application
  237.  
  238.    FlexFile is compatible with all the linkers that it has been
  239.    tested with.  The entire library can be overlayed with
  240.    Blinker(tm) or WarpLink(tm) or RTLink Plus(tm).
  241.  
  242.    The procedure for linking is the same as for any other library
  243.    listed in your link file or on the link command line.  For
  244.    example:
  245.  
  246.     link test.obj,,,c:\lib\clipper c:\lib\flexfile
  247.  
  248.    Each FlexFile function begins with either a V_ or an A_
  249.    depicting use with the Variable Length Field manager or the
  250.    array manager, respectively.  The prefix to each function was
  251.    chosen to avoid conflict with other libraries.  If you find a
  252.    conflict with another library, you must place FlexFile before
  253.    the other library in the link list in order to use the
  254.    FlexFile function.  If you find a conflict please contact us
  255.    so that we may avoid them in future releases.
  256.  
  257.  
  258.  
  259.  
  260.  
  261.                     Variable Length Fields
  262.  
  263.    The enhancements to memo-fields
  264.  
  265.    FlexFile addresses the four major problems that plague
  266.    Clipper's implementation of memo-fields.
  267.  
  268.    First, FlexFile reuses all unused space.  If your user edits a
  269.    memo (or deletes elements of an array) making it smaller,
  270.    FlexFile is aware of every byte of the excess space and will
  271.    use it later for new data.  This feature totally eliminates
  272.    the file bloat that characterizes Clipper's DBT files.
  273.    (Clipper frequently abandons space no longer needed by
  274.    memo-field data, and once abandoned, not even packing the file
  275.    can regain the space.)
  276.  
  277.    Second, FlexFile does not allocate space in blocks.  Instead,
  278.    each item stored requires only the space for its own length
  279.    plus a six byte header that FlexFile uses for management.
  280.    This is in great contrast to Clipper's memo-fields that
  281.    require a fixed block size of 512 bytes.  This feature alone
  282.    will save disk space at an average of 256 bytes per record.
  283.  
  284.    Third, the size of FlexFile's Variable Length Field (VLF)
  285.    files are limited only by your disk space.  This is in
  286.    contrast to Clipper's size limit on a DBT file of 16M.
  287.  
  288.    Finally, FlexFile can store any valid Clipper data.  This
  289.    includes arrays, character strings, dates, numerics and
  290.    logicals.  In addition, the content of character data is not
  291.    limited as it is in Clipper.  It is, therefore, possible to
  292.    store SAVESCREEN() variables or any other binary data that you
  293.    use.
  294.  
  295.  
  296.  
  297.  
  298.    FlexFile's Extended Features
  299.  
  300.    Through FlexFile's ability to save an array to a field, your
  301.    DBF's can become three dimensional (actually multi-dimensional
  302.    with Clipper 5.0).  Looking at it another way, each record can
  303.    now have a variable number of fields.  This new feature allows
  304.    far greater flexibility in designing a database system.
  305.  
  306.    Lets take the simple example of storing a telephone number.
  307.    In a customer data base, next to the name and address we store
  308.    the telephone number.  But is one telephone number enough?
  309.    Most businesses require at least a voice line and a fax line.
  310.    Then again, there is that one guy who has got two voice lines,
  311.    a fax line, a data line, and a whole bunch more at his house.
  312.  
  313.    So, do we build in five or ten telephone fields in the
  314.    customer file?  Certainly this situation would not warrant a
  315.    second file and an index with a relation. Usually, we tell our
  316.    client (very nicely) to live with a maximum of two.
  317.  
  318.    With FlexFile, however, the answer is simple.  Save an array
  319.    of telephone numbers.  Those customers who have one or two
  320.    telephone numbers use only the space for one or two telephone
  321.    numbers.  Those that have ten can have ten. There are no
  322.    indexes or relations to maintain and you can extend this
  323.    concept into those perplexing data item which your client
  324.    defines as requiring "usually two or three, but sometimes
  325.    twenty or more".
  326.  
  327.    FlexFile also allows the programmer to store any valid Clipper
  328.    data type to a field.  At first look, this alternative seems
  329.    less than impressive.  Why would you want to store a logical
  330.    value, which takes only one byte per record in a DBF file, by
  331.    using a six byte pointer-field in the DBF to point to an
  332.    object which requires a six byte header in the DBV.  The
  333.    advantage does not come from saving any one type, but rather,
  334.    from being able to store different types to the same field.
  335.    This is particularly advantageous in data driven applications.
  336.    For example, if you give your clients user defined fields,
  337.    they can change the type of a field and you won't have to
  338.    worry about carrying extra fields for each type "Just in
  339.    Case".
  340.  
  341.  
  342.  
  343.  
  344.    USEing DBV files
  345.  
  346.    The use of FlexFile's DBV files was designed to parallel the
  347.    use of DBF type files.  Specifically, the system is made up of
  348.    work areas that are used to manage the VLF files in exactly
  349.    the same manner as Clipper uses work areas to manage DBF
  350.    files.  This method avoids the need to keep track of
  351.    "handles", and allows the use of aliases.
  352.  
  353.    For example, you can V_SELECT(1) and then V_USE() a file in
  354.    area one, and then V_SELECT(0) the next available work area
  355.    and V_USE() another file there.  It should be noted that
  356.    FlexFile's work areas are mutually exclusive from Clippers DBF
  357.    work areas.  For example, you can V_SELECT(1) and V_USE() a
  358.    file in VLF area one, and simultaneously, SELECT 1 and USE a
  359.    file in DBF area one with no conflicts.
  360.  
  361.    The FlexFile system offers an unlimited number of work areas,
  362.    however, you must decide what your maximum number of work
  363.    areas will be before you open the first DBV type file.  The
  364.    reason for this is to allow the system to create one
  365.    contiguous block of memory for the management of the files
  366.    instead of fragmenting memory with little blocks each time you
  367.    open a new file.  At any point that you have all DBV files
  368.    closed you can readjust this maximum number of work areas by
  369.    using the V_FILES() function.
  370.  
  371.  
  372.    Creating DBV files
  373.  
  374.    The simplest thing to do in FlexFile is to create a DBV type
  375.    file.  Simply V_USE() a file that does not exist and you will
  376.    have a DBV file open and ready to go.
  377.  
  378.  
  379.    How to Manage Your Data with FlexFile
  380.  
  381.    Another great use for FlexFile is to hold data that is not
  382.    repetitive and structured;  the DBF file structure is not at
  383.    all accommodating in this area.  For example, almost every
  384.    Clipper application requires system data such as a color
  385.    scheme, default directories, default drive for temporary
  386.    files, printer definitions, and other randomly sized
  387.    non-repetitive data.  Storing this data is now a trivial
  388.    matter.
  389.  
  390.    In this case, the design could be as simple as a two field DBF
  391.    file with an index, and one FlexFile VLF file.  The DBF
  392.    structure might look like:
  393.  
  394.        Structure for database: C:\FF\SYSTEM.DBF
  395.        Number of data records:      20
  396.        Date of last update   : 10/05/90
  397.        Field  Field Name  Type       Width    Dec
  398.            1  VAR_NAME    Character     10
  399.            2  VLF_FLD     Character      6
  400.        ** Total **                      17
  401.  
  402.    The key field <var_name> will hold the name of a Clipper
  403.    variable that you use; the six byte character field <vlf_fld>
  404.    FlexFile will use to hold a pointer to <var_name>'s value.
  405.    Following from the above description, start-up code for an
  406.    application might look like:
  407.  
  408.        // Declare the system wide public variables that you use.
  409.        PUBLICaColors,;       // Array variable for colors
  410.              cDefaultDir,;   // A user defined default directory
  411.              dYearEnd        // A user defined year end date.
  412.  
  413.        //  Open the DBF, its index, and the VLF
  414.        USE System.dbf INDEX System.ntx
  415.        V_USE( "System.dbv" )
  416.  
  417.        //  Seek your colors array and retrieve it.
  418.        //  Note that this Clipper 5.0 syntax for arrays is slightly
  419.        //  different than the S'87 syntax.  See the V_FILLARR() function.
  420.        SEEK "aColors"
  421.        aColors = V_ARETRIEVE( vlf_fld )
  422.  
  423.        //  Seek the record that holds a "Default" directory.
  424.        SEEK "cDefaultDir"
  425.        cDefaultDir = V_RETRIEVE( vlf_fld )
  426.  
  427.        //  Dates can be stored as easily as anything else.
  428.        SEEK "dYearEnd"
  429.        dYearEnd = V_RETRIEVE( vlf_fld )
  430.  
  431.    Of course, for this code to work you must have previously save
  432.    data to these records.  The next section on FlexFile's
  433.    pointers gives an in depth view into storing the data,
  434.    retrieving it and replacing old data with new.
  435.  
  436.  
  437.  
  438.    FlexFile's Pointers
  439.  
  440.  
  441.    The key to maintaining secure data with FlexFile is fully
  442.    understanding the pointers that FlexFile uses to access data.
  443.    Clipper's memo-fields maintains a similar set of pointers but
  444.    Clipper hides them from the programmer as well as the user.
  445.    If you try to assign a Clipper memo-field pointer directly to
  446.    a variable as in:
  447.  
  448.    var = system->mem_fld      // Clipper memo-field
  449.  
  450.  
  451.    Clipper intercepts the call and automatically goes to the DBT
  452.    file and fetches the data that <mem_fld> points to.  With
  453.    FlexFile, this assignment would put the pointer into <var>
  454.    instead of the data.  So, the equivalent code using flexfile
  455.    is:
  456.  
  457.        var = V_RETRIEVE( system->vlf_fld )    // FlexFile VLF
  458.  
  459.  
  460.    What we are doing here is passing the V_RETRIEVE() function a
  461.    pointer to the data and V_RETRIEVE() is kindly passing us back
  462.    data that was stored there.
  463.  
  464.    The same principal applies to saving data... with a twist.
  465.    When Clipper saves data to a memo-field, it allocates disk
  466.    space in 512 byte chunks and sticks a pointer to the allocated
  467.    space in the memo-field of the DBF file.  For example,
  468.  
  469.        // Clipper hogs 512 bytes with this one.
  470.        REPLACE system->mem_fld WITH "This will take 512 bytes"
  471.  
  472.    Clipper allocates 512 bytes of disk space, puts the 24 bytes
  473.    of data in the front of the new space, and puts a pointer to
  474.    the block in <mem_fld>.  If, without moving the record
  475.    pointer, we say
  476.  
  477.        // Clipper abandons the first mess and requires 1024 more.
  478.        REPLACE system->mem_fld WITH SPACE( 513 )
  479.  
  480.    then Clipper will abandon the first 512 byte block
  481.    (permanently), and allocate 1024 bytes for the new data.  The
  482.    old pointer to the 512 byte block is lost and the file space
  483.    is gone forever.
  484.  
  485.    FlexFile is smarter than this.  Using FlexFile, we would save
  486.    the 24 byte string with:
  487.  
  488.  
  489.        // FlexFile neatly allocates 30 bytes of disk space.
  490.        REPLACE system->vlf_fld WITH ;
  491.           V_REPLACE( "This will take  30 bytes", system->vlf_fld )
  492.  
  493.    If we follow the pointer in this example, we can see what
  494.    FlexFile is going to do.  The first thing that we notice is
  495.    that we not only pass to the V_REPLACE() function the new
  496.    data, but also, we give it the old pointer.
  497.  
  498.    Because this function will operate from right to left, first
  499.    it will look at the right most <vlf_fld> to see if it is
  500.    pointing to any old data.  If it is not, then the function
  501.    proceeds to look through an internal table for other vacated
  502.    space. We will assume for this example that this is the first
  503.    V_REPLACE(). Therefore, there is no available space that has
  504.    already been release by other data, so the new string is
  505.    appended to the end of the file.
  506.  
  507.    To do this FlexFile will allocate 30 bytes of disk space, 24
  508.    bytes for the data and six bytes to keep some information that
  509.    it uses for management.
  510.  
  511.    Now we continue the example by replacing the thirty bytes with
  512.    513 bytes of spaces:
  513.  
  514.        // FlexFile releases 30 bytes and stores 519.
  515.        REPLACE system->vlf_fld WITH ;
  516.              V_REPLACE( SPACE( 513 ), system->vlf_fld )
  517.  
  518.    This time, FlexFile sees that the old pointer has something in
  519.    it, and so releases it.  Then it seeks internally for an
  520.    available 519 byte space to put the new information.  There is
  521.    none, so it tags this at the end of the file as well.
  522.  
  523.    There are two very important advantages you can see from this
  524.    example.  First, only the size of the data was required to
  525.    keep the data, and second, the next piece of data that you
  526.    store that is thirty bytes or less will be stored in the
  527.    vacated space.
  528.  
  529.    The thirty byte space that is available brings up an important
  530.    point.  We have run tests where one VLF file undergoes
  531.    millions of V_REPLACE()s.  The data ranged in random sizes
  532.    from one byte to ten thousand bytes.  The amount of vacant
  533.    space tended to level off at about 20% of the fully pack
  534.    file's size and at that point the VLF file stops growing,
  535.    period.
  536.  
  537.  
  538.  
  539.  
  540.    Disaster Recovery
  541.  
  542.    One of FlexFile's advantages is that it is very robust against common
  543.    disaster situations such as power loss.  Your DBV file may get damaged
  544.    during such a calamity, however, the damage done is local to the write
  545.    that was in progress when the interuption occurred.  That is, there is
  546.    no immediate ripple effect from a damaged section of a DBV to non
  547.    damaged sections.
  548.  
  549.    On the other hand, if your file gets damaged and you continue to use it,
  550.    you CAN cause more damage.  Therefore, you should prepare your code for
  551.    such an occurance (you can always rely on backups, but sometimes clients
  552.    simply fail to do their job of backing up regularly).
  553.  
  554.    If V_REPLACE() or V_DELETE() return a logical value (as opposed to a
  555.    character value) and/or V_ERROR() reports a 6200, 6500, 6700 or 9000
  556.    class of error, the DBV file may be corrupt.  (Syntax errors in calling
  557.    FlexFile functions can also cause these errors so check your syntax
  558.    first.)
  559.  
  560.    When you are certain that your syntax is not causing the problem, you
  561.    should rebuild the DBV file.  Rebuilding is a simple process and is
  562.    outlined by the following code.  The code is based on a DBF file called
  563.    "dbf_file.dbf" which has a six byte character field (a FlexFile
  564.    pointer-field) called <vlf>.  We then open the existing DBV and create a
  565.    new DBV into which to copy the old data.  Finally, we erase the old DBV
  566.    and rename the new one back to the old.
  567.  
  568.    Before any code such as this is implemented you should back up the files
  569.    involved.
  570.  
  571.  
  572.    // Open the controlling DBF and the DBV (with an alias of "OLD")
  573.    USE dbf_file
  574.    V_USE( "dbv_file", "old" )
  575.  
  576.    // Open a new DBV to recieve the copyable data (with an alias of "NEW").
  577.    V_SELECT(0)
  578.    V_USE( "tempdbv", "new" )
  579.  
  580.    DO WHILE !EOF()
  581.  
  582.       IF V_TYPE( dbf_file->vlf, "old" ) == 'U'
  583.          QOUT( "This record is damaged." )
  584.          WAIT
  585.          LOOP
  586.       ENDIF
  587.  
  588.       // If the type is Char, Num, Log, Date, or FlexFile array
  589.       IF V_TYPE( dbf_file->vlf, "old" ) $ "CNLDF"
  590.  
  591.          // Get the value from the DBV.
  592.          var = V_RETRIEVE( dbf_file->vlf, "old" )
  593.  
  594.          // Write the value to the new DBV.
  595.          dbf_file->vlf := V_REPLACE( var, space(6), "new" )
  596.  
  597.       // else the type must be an array.
  598.       ELSE
  599.  
  600.          // Get the array from the DBV
  601.          var = V_ARETRIEVE( dbf_file->vlf, "old" )
  602.  
  603.          // Write the array to the new DBV
  604.          dbf_file->vlf := V_AREPLACE( var, space(6), "new" )
  605.  
  606.       ENDIF
  607.  
  608.       SKIP
  609.  
  610.    ENDDO
  611.  
  612.    FERASE( "dbv_file.dbv" )
  613.    FRENAME( "tempdbv.dbv", "dbv_file.dbv" )
  614.  
  615.  
  616.  
  617.    The other form of "disaster" that is fairly common is to loose a DBF
  618.    file that has pointer-fields into a DBV.  This is a very serious
  619.    situation because there is nothing in the DBV which points back into the
  620.    DBF.  However, there is a new function V_WALK_DBV() that allows the
  621.    programmer to step from field to field through the DBV file.  The steps
  622.    go from physical field to physical field and so the logical order of the
  623.    file is lost.  However, in extreme situations this function may be
  624.    helpful.  See V_WALK_DBV() for more information.
  625.  
  626.  
  627.  
  628.  
  629.               Saving and Retrieving Clipper's arrays
  630.  
  631.  
  632.   ┌─────────────────────────Warning───────────────────────────────────┐
  633.   │   Arrays saved with FlexFile's S87 library version 1.01 and       │
  634.   │   earlier cannot be retrieved directly with FlexFile's Clipper    │
  635.   │   5.0 V_ARETRIEV() function.  Instead, see the documentation on   │
  636.   │   V_FILLARR() and V_FILLEN().  Arrays saved with later versions   │
  637.   │   of FlexFile are compatible between the two version as long as   │
  638.   │   the array is one dimensional.                                   │
  639.   └───────────────────────────────────────────────────────────────────┘
  640.  
  641.    Saving and retrieving Clipper S'87 arrays
  642.  
  643.    To save a an array using the S'87 version of the library
  644.    (Flex_S87.lib), you treat the array like any other variable.
  645.    For example,
  646.  
  647.        && Declare an array
  648.        DECLARE arr[100]
  649.  
  650.        && Put some junk in it.
  651.        afill( arr, "Solid waste" )
  652.  
  653.        && Save the array (assume a DBF and DBV are open).
  654.        REPLACE vlf WITH V_REPLACE( arr, vlf )
  655.  
  656.    To retrieve that same array in S'87 takes more than one line of code.
  657.    Remember that V_LEN() returns the total number of elements in
  658.    a S'87 array.
  659.  
  660.        && Assume that we are still on the same record in
  661.        && the DBF but we do not already have a declared array.
  662.        && First we need to DECLARE the array to be the size of
  663.        && the array we stored above.
  664.        DECLARE newarr[ V_LEN(vlf) ]
  665.  
  666.        && Now we fill the array.
  667.        V_FILLARR( newarr, vlf )
  668.  
  669.    Although that was slightly awkward that is all there is to it.
  670.  
  671.  
  672.    Saving and retrieving Clipper 5.0 arrays
  673.  
  674.    To save an array with the Clipper 5.0 library (FlexFile.lib)
  675.    you treat the array like you would any other Clipper variable
  676.    except that instead of using V_REPLACE() and V_RETRIEVE() you
  677.    need to use V_AREPLACE() and V_ARETRIEV().  Remember
  678.    V_ARETRIEV() can only be used on arrays that were saved with
  679.    V_AREPLACE() (see the warning above).
  680.  
  681.  
  682.  
  683.  
  684.    Indexing on Variable Length Fields
  685.  
  686.    There are several issues that must be addressed by the programmer in
  687.    order to create and maintain an index on part (or all) of a FlexFile
  688.    Variable Length Field.
  689.  
  690.    First, creating an index is as easy as:
  691.  
  692.       INDEX ON V_RET( vlf_fld, "ALIAS_1", 1, 15 ) TO NTX_FILE.NTX
  693.  
  694.    This would create an index on the first fifteen characters of a FlexFile
  695.    VLF. However, every element of a clipper index must be the same length
  696.    and the above example does not guarantee this.  (If V_RETRIEVE() returns
  697.    a string of less than 15 characters, you will corrupt your index.)  So,
  698.    you should PAD() the return from V_RETRIEVE() with spaces as in:
  699.  
  700.       INDEX ON PAD( V_RET(.....), 15 ) TO NTX_FILE.NTX
  701.  
  702.    The second issue is to note that only data of the same type can be
  703.    indexed in this manner.  Accordingly, make sure that the character data
  704.    is not binary data.  If a CHR(0) is found in the first 15 characters of
  705.    the above example, Clipper will consider that to indicate the end of the
  706.    string.  This will make the string's length different from other strings
  707.    in the index and, thereby, corrupt the index.
  708.  
  709.    The last issue is described below, but is more complex. However, it is
  710.    not necessary to understand why, as long as you always abide by the
  711.    rule:  You must always have a REPLACE command that does not have a
  712.    V_REPLACE in its syntax before REPLACEs that contain V_REPLACE(). For
  713.    example,
  714.  
  715.       && INCORRECT....will corrupt the index if the index relys on either
  716.       && the data pointed to by vlf_1 or vlf_2.
  717.       REPLACE vlf_1 WITH V_REPLACE( "testing", vlf_1 )
  718.       REPLACE vlf_2 WITH V_REPLACE( "testing", vlf_2 )
  719.       SKIP
  720.  
  721.       && CORRECT....the first replace is a "dummy" but maintains integrity.
  722.       REPLACE any_fld WITH any_fld
  723.       REPLACE vlf_1 WITH V_REPLACE( "testing", vlf_1 )
  724.       REPLACE vlf_2 WITH V_REPLACE( "testing", vlf_2 )
  725.       SKIP
  726.  
  727.    First, the only reason I placed two V_REPLACE()s in the example is to
  728.    show that only one "dummy" replace is necessary before any number of
  729.    imbedded V_REPLACE()s.  Remember that anything that causes the index to
  730.    be updated (such as COMMIT, SKIP, SEEK, etc.) require that a new "dummy"
  731.    replace be used before attempting another REPLACE with imbedded
  732.    V_REPLACE()s.  For example,
  733.  
  734.       && CORRECT
  735.       REPLACE any_fld WITH any_fld
  736.       REPLACE vlf_1 WITH V_REPLACE( "testing", vlf_1 )
  737.       REPLACE vlf_2 WITH V_REPLACE( "testing", vlf_2 )
  738.       SKIP
  739.  
  740.       && INCORRECT....will corrupt the index without another "dummy"
  741.       && replace after the COMMIT.  Assuming, of course, that vlf_2
  742.       && is included in the index key.
  743.       REPLACE any_fld WITH any_fld
  744.       REPLACE vlf_1 WITH V_REPLACE( "testing", vlf_1 )
  745.       COMMIT
  746.       REPLACE vlf_2 WITH V_REPLACE( "testing", vlf_2 )
  747.  
  748.  
  749.    Ok, so what is going on?  Understanding the sequence of events that
  750.    occurs during a REPLACE is critical to understanding the apparent
  751.    paradox in the examples above.
  752.  
  753.    Remembering that the arguments of a function or command are all
  754.    evaluated before the function itself is called, the syntax
  755.  
  756.       REPLACE vlf_fld WITH V_REP( "Testing an indexed replace", vlf_fld )
  757.    
  758.    first executes FlexFile's V_REPLACE() and then executes Clipper's
  759.    REPLACE.
  760.  
  761.    This affects indexing because Clipper always evaluates the index key
  762.    twice.  Once at the begining of the first of one or more REPLACEs (to
  763.    remember which index key has to be removed from the index) and the
  764.    second after any of several "commit" commands such as COMMIT, SKIP,
  765.    SEEK, GOTO, etc. (to calculate and insert a new index key).  However, if
  766.    FlexFile already deleted the old information pointed to by vlf_fld
  767.    before CLIPPER began to execute the REPLACE code, then the first
  768.    evaluation of the index key occurs after its data has already been
  769.    deleted by FlexFile.
  770.  
  771.    I realize this is confusing so I will try again in steps:
  772.  
  773.                                        ┌─ step 2  ┌─ step 1
  774.                                        │          │
  775.       REPLACE vlf_fld WITH V_REPLACE( "testing", vlf_fld )
  776.       │                    │
  777.       └─ step 4            └─ step 3
  778.          step 5
  779.  
  780.    1. FlexFile deletes the data associated with the pointer-field vlf_fld
  781.    that is in the file before the REPLACE.
  782.  
  783.    2. FlexFile puts away the text "testing" in an appropriate location.
  784.  
  785.    3. FlexFile returns a six byte pointer-field which is immediately passed
  786.    to REPLACE.  This pointer-field is different than that of step 1 and
  787.    this new pointer-field is not yet in the file (it is being stored in
  788.    memory for the moment).
  789.  
  790.    4. Clipper begins executing its REPLACE code with the string passed to
  791.    it from step 3.
  792.  
  793.    5. Clipper evaluates the index and stores the evaluated value in a
  794.    buffer.  This sets up the error.  The index key should evaluate to the
  795.    data pointed to by the vlf_fld which is still in the file. However,
  796.    FlexFile deleted that data in step 1. Therefore, the V_RETRIEVE() in the
  797.    index key will return a null string and your PAD function will change
  798.    this to 15 bytes of spaces.
  799.  
  800.    No Clipper error actually occurs until the first COMMIT, SKIP, SEEK,
  801.    etc.  It is at this point that Clipper does the work on the index.  The
  802.    first thing Clipper does is delete the old index key (which was put into
  803.    a memory buffer in step 5).  However, Clipper will not be able to find
  804.    an index key which matches the 15 spaces in the memory buffer and,
  805.    therefore, assumes that the index is corrupted.
  806.  
  807.    So, the way to resolve this is to have a "dummy" replace that will force
  808.    Clipper to evaluate the index key BEFORE FlexFile deletes the key.  The
  809.    thing that may be confusing is that Clipper does not care which field is
  810.    in the first REPLACE.  It is simply a fact that the first REPLACE
  811.    evaluates the "before" index key regardless of whether the REPLACE even
  812.    affects the index key.  It is also a fact that no other index action
  813.    occurs until a "commit" type command.  At that point the "before" key is
  814.    deleted from the index and the "after" key is inserted into the index.
  815.  
  816.  
  817.  
  818.  
  819.    FlexFile Networking
  820.  
  821.    FlexFile typically requires no special network considerations
  822.    beyond Clipper's RLOCK() and FLOCK().  That is to say, if you
  823.    acquire an RLOCK() on a record in a DBF file that has a
  824.    pointer-field, no other user will have write access to that
  825.    record.  Because Clipper insists on an RLOCK() being acquired
  826.    before a REPLACE when a file is used non-exclusively, this
  827.    will suffice to protect the information to which the
  828.    pointer-field is related.
  829.  
  830.    FlexFile's internal tables lock and unlock automatically, and
  831.    require no programmer consideration.
  832.  
  833.    There is an additional network features which was incorporated
  834.    into FlexFile in order to aid the programmer in implementing
  835.    network compatible code.
  836.  
  837.    Every time a pointer is replaced with a new pointer, the new
  838.    pointer is guaranteed to have a different value even though it
  839.    may be pointing to the same position within the file.
  840.  
  841.    For example, if you have variable length data that is 30 bytes
  842.    long, residing at offset 5000 in the DBV file, and you replace
  843.    that data with new data that is also 30 bytes long, it is
  844.    highly probable that FlexFile will put the new data exactly
  845.    where the old data was (at offset 5000).  However, the
  846.    pointer-field that the V_REPLACE() function returns will be
  847.    different than the one that pointed to the data before the
  848.    REPLACE.
  849.  
  850.    This feature was implemented so that the programmer can assign
  851.    the pointer- field to a variable, then, without locking the
  852.    DBF record in which the pointer- field is located, modify the
  853.    pointer's data in memory.  Then when the user is ready to
  854.    replace the old data with the modified data, the programmer
  855.    can compare the pointer-field in memory with the DBF's
  856.    pointer-field in order to ascertain whether the data was
  857.    modified by another user while the current user was working on
  858.    the copy of it in memory.  For example:
  859.  
  860.        // Open the DBF and its related DBV
  861.        USE Shareit.dbf
  862.        IF V_USE( 'Shareit.dbv' ) == -1
  863.           ? "I could not open the Shareit.dbf file."
  864.           ? "I encountered error: " + STR( V_ERROR() )
  865.           QUIT
  866.        ENDIF
  867.  
  868.        // Save the pointer <vlf> to a variable
  869.        save_vlf = shareit->vlf
  870.  
  871.        // Retrieve the data from the DBV file into a memory var.
  872.        // The DBF lock is momentary.
  873.        DO WHILE !RLOCK()
  874.        ENDDO
  875.        memo_data = V_RETRIEVE( vlf )
  876.        UNLOCK
  877.  
  878.        // Edit the data.
  879.        memo_data = MEMOEDIT(memo_data...)
  880.  
  881.        // Lock the record and replace the data if the
  882.        // data has not been modified since the pointer was
  883.        // saved.  Again, the lock is momentary.
  884.        DO WHILE !RLOCK()
  885.        ENDDO
  886.  
  887.        IF save_vlf == shareit->vlf
  888.           REPLACE vlf WITH V_REPLACE( memo_data, vlf )
  889.        ELSE
  890.           ? "Data has been modified by another user!"
  891.           INKEY(0)
  892.        ENDIF
  893.        UNLOCK
  894.  
  895.    Although the Clipper locking technique shown is crude (at
  896.    best), the comparison of the saved version of the pointer with
  897.    the DBF pointer-field is a technique that many programmers
  898.    prefer.  The advantage is, of course, that you only need to
  899.    obtain two momentary locks rather than one long lock (during
  900.    which your user invariably goes on a lunch break).  The
  901.    disadvantage is that sometimes the user will have to retype an
  902.    entry.
  903.  
  904.    FlexFile's internal locking uses the DOS 3.x locking
  905.    mechanism.  Therefore, if you are using a lower version of DOS
  906.    or do not have SHARE.EXE loaded, FlexFile will ignore any
  907.    attempts to lock the file and proceed as if the lock was
  908.    successful.
  909.  
  910.  
  911.  
  912.  
  913.  
  914.    ARRAYS
  915.  
  916.    FlexFile supports an implementation of strongly typed
  917.    multi-dimensional arrays.  This array system is not to be
  918.    looked at as a replacement for the Clipper array system.
  919.    Clipper's array system is very powerful and it should not be
  920.    construed that FlexFile arrays will supersede the Clipper
  921.    system. Rather, FlexFile arrays should be used when the array
  922.    structure is regular, all the elements are of the same type,
  923.    and the array is very large.
  924.  
  925.    UNDER NO CIRCUMSTANCE SHOULD YOU USE FLEXFILE'S "S"TRING TYPE ARRAY IN
  926.    CLIPPER 5.0X.  EACH STRING ELEMENT OF THE ARRAY IS NOT HANDLED BY THE
  927.    VMM SYSTEM, AND, THEREFORE, THE CLIPPER COUNTERPART WILL TAKE LESS
  928.    MEMORY.  ALL OTHER FLEXFILE ARRAYS CAN BE SWAPPED, WHEN NECESSARY, BY
  929.    CLIPPER'S VMM SYSTEM.
  930.  
  931.    Why Use FlexFile Arrays
  932.  
  933.    FlexFile arrays are the only arrays to use if your array must
  934.    exceed Clipper's limit of 4029 elements.  For example, a
  935.    FlexFile array of logicals allows over 500,000 elements.  In
  936.    addition, each element of FlexFile array is at least six bytes
  937.    smaller than its Clipper counter part and at most thirteen
  938.    bytes and 7 bits smaller.  See Appendix B for a list of the
  939.    sizes of each type of FlexFile array.
  940.  
  941.    Clipper sees Flexfile arrays as regular variables.  Therefore,
  942.    you pass a Flexfile arrays by value (unless you
  943.    pass-by-reference using the @ symbol) and you can return a
  944.    FlexFile array as though it were a simple Clipper variable.
  945.    Because these arrays are typically large, it is best to pass
  946.    them by reference in order to avoid duplicating their content
  947.    in memory.
  948.  
  949.    The one exception to this is FlexFile's string type arrays.
  950.    These arrays pose a unique problem which is discuss below (See
  951.    FlexFile String Arrays).
  952.  
  953.  
  954.  
  955.  
  956.    Array indexes
  957.  
  958.    A "subscript" or an "index" refers to a particular element of
  959.    an array.  For example, Clipper refers to the third element of
  960.    a single dimensional array as ArrayName[3].  In this case, [3]
  961.    is a subscript of the array ArrayName.
  962.  
  963.    Subscripts may be passed using either of two different
  964.    methods.  Both methods are valid at any time.  The method to
  965.    use depends largely on whether your array is single or
  966.    multi-dimensional.
  967.  
  968.    If the array is a single dimensional array, then you define
  969.    and index position into that array exactly as you would
  970.    imagine.  For example, if you want to store 98.6 to the fifth
  971.    element of a single dimensional floating point type array, the
  972.    following line would be fine:
  973.  
  974.  
  975.        nTemperature = 98.6
  976.        nPatient = 5
  977.        A_STORE( aTemps, nTemperature, nPatient )
  978.  
  979.  
  980.    However, if the array is multi-dimensional it is necessary to
  981.    pass the index via the A_() function.  For example,  if you
  982.    want to store the temperature of the fifth patient on the
  983.    third day:
  984.  
  985.       A_STORE( aTemps, 98.6, A_( 5, 3 ) )
  986.  
  987.  
  988.    It is not wise to try to figure out the actual integer offset
  989.    of an element even though FlexFile would accept it; FlexFile
  990.    does this very fast on its own.  In addition, remember element
  991.    A_( 5, 3 ) is not the same element as A_(3, 5), and rarely, if
  992.    ever, will either array index refer to the fifteenth element
  993.    as it is laid out in memory.
  994.  
  995.  
  996.  
  997.  
  998.    Understanding FlexFile Arrays
  999.  
  1000.    FlexFile arrays are similar to the arrays in languages such as
  1001.    C or Pascal. The array is one block of memory (with the
  1002.    exception of string arrays), and each element in the array
  1003.    must be of the same type.
  1004.  
  1005.    There is an analogy relating multi-dimensional arrays to a set
  1006.    of encyclopedias that helps in understanding and describing
  1007.    their use.  This analogy is especially helpful in
  1008.    understanding arrays that span into the fourth dimension.
  1009.  
  1010.    Imagine that you have a character array.  First, do not
  1011.    confuse character arrays and string arrays.  A string array is
  1012.    an array of pointers that point to strings of varying length
  1013.    that reside in random positions in memory.  The string array
  1014.    is actually an array of pointers and not an array of strings.
  1015.    Each element points to a string of any length.
  1016.  
  1017.    A character array is a matrix of one byte storage locations
  1018.    where each byte can hold one ASCII character.  In the analogy
  1019.    of the encyclopedias, each letter is an element, a group of
  1020.    letters that form words make up one row of text.  That one
  1021.    line implies the first dimension.  Likewise, A group of lines
  1022.    that makes up one page implies the second dimension, a group
  1023.    of pages that makes up one volume implies the third dimension,
  1024.    and all the volumes in the set of encyclopedias implies the
  1025.    fourth dimensions.  We could continue the analogy into the
  1026.    fifth dimension: a set of Britannica's next to The World Book
  1027.    set implies a magnitude of two in the fifth dimension.
  1028.  
  1029.    You will often see, in the Array Function Reference chapter,
  1030.    the concept of "wrapping".  For example, A_SCAN() will wrap at
  1031.    the end of one line to the beginning of the next, and at the
  1032.    end of one page it will wrap to the top of the next page.  All
  1033.    functions that work with wrapping look at the array as it is
  1034.    laid out in memory.
  1035.  
  1036.    It is important to dimension your arrays with this
  1037.    understanding in mind:  the last dimension listed in the
  1038.    declaration varies the smallest step in memory.  To declare
  1039.    the array for an encyclopedia you would want to declare it as
  1040.    follows:
  1041.  
  1042.        vols := 26
  1043.        pages := 150
  1044.        lines := 80
  1045.        chars := 95
  1046.        WorldBook = A_DECLARE( 'C', vols, pages, lines, chars )
  1047.  
  1048.    This declaration of a character array is actually illegal
  1049.    because the array would exceed memory, however, it is
  1050.    important to see how and why the dimensions are in the order
  1051.    they are in.  The <chars> variable is last in order to insure
  1052.    that each character is next to its proper neighbor in memory.
  1053.    As far as A_STORE()ing and A_RETRIEVE()ing each character, the
  1054.    layout makes little difference.  However, when you need to do
  1055.    something like an A_FILL() (for a blank line), this layout
  1056.    becomes critical.
  1057.  
  1058.    Lets say, for example, we want the fifth and sixth lines on
  1059.    the fifteenth page of the fourth volume to be filled with
  1060.    spaces.
  1061.  
  1062.       A_FILL( WorldBook, ' ', A_( 4, 15, 5, 1 ), 2 * lines )
  1063.  
  1064.  
  1065.    This function fills the 160 characters following the specified
  1066.    location.  Because the fill always begins at a point in memory
  1067.    and moves to the next set of contiguous positions in memory,
  1068.    it becomes critical how the array was declared.  For example,
  1069.    if we switch the order of the <lines> and <chars> in the
  1070.    declaration, and then perform the A_FILL(), the fill would put
  1071.    one space on each line for 160 lines instead of one space for
  1072.    each character for 160 characters.
  1073.  
  1074.    FlexFile String arrays (pointer arrays)
  1075.  
  1076.    Arrays of strings in FlexFile pose a peculiar problem.  When
  1077.    the array is declared, FlexFile allocates memory for four
  1078.    bytes per element.  These four bytes originally point to
  1079.    nothing (null).  When you A_STORE() a string to an element,
  1080.    however, new memory is allocated for the string.  This memory
  1081.    does not reside within the array, but rather, at some random
  1082.    location in memory. FlexFile knows where this is because it
  1083.    stores a pointer in the array which points to the new data.
  1084.  
  1085.    A problem arises because the array itself is a Clipper
  1086.    variable and has the scope of a Clipper variable.  If you
  1087.    release this variable or allow it to fall out of scope,
  1088.    Clipper does not know that it was pointing to your strings,
  1089.    and so, Clipper releases the array of pointers without
  1090.    releasing the strings that it points to.  In order to avoid
  1091.    this, it is necessary to A_KILL() a string array before
  1092.    allowing it to fall out of scope or be released.
  1093.  
  1094.  
  1095.  
  1096.  V_ALIAS()
  1097.  Return the alias of the current or a specified DBV work area
  1098. ───────────────────────────────────────────────────────────────────────────────
  1099.  
  1100.  Syntax
  1101.  
  1102.     V_ALIAS( [<nDBVArea>] )   ->    cDBVAlias
  1103.  
  1104.  Arguments
  1105.  
  1106.     <nDBVArea> is any valid DBV work area.
  1107.  
  1108.  Returns
  1109.  
  1110.     V_ALIAS() returns the alias of the DBV work area <nDBVArea>. If no
  1111.     <nDBVArea> is specified, then the alias of the current work area
  1112.     is returned.
  1113.  
  1114.  Description
  1115.  
  1116.     V_ALIAS() is used to return the name of a DBV work area. This name
  1117.     is either the name of the DBV file or the name specified as the
  1118.     second parameter in the V_USE() function. If there is no DBV file
  1119.     open in the <nDBVArea>, V_ALIAS() will return a null string ("").
  1120.  
  1121.     Any function which accepts a DBV area as a parameter can also
  1122.     accept an alias in place of the area.
  1123.  
  1124.     The alias is always returned in capital letters regardless of how
  1125.     it was passed to V_USE().
  1126.  
  1127.  Notes
  1128.  
  1129.   ■ Do not confuse Clipper's alias names with FlexFile's; they are
  1130.     mutually exclusive. For example, you can have a DBF file with an
  1131.     alias of "MYFILE" and simultaneously have a DBV file with the same
  1132.     alias.
  1133.  
  1134.  Examples
  1135.  
  1136.     // Open two DBV files in two new areas.
  1137.     V_SELECT(1)
  1138.     V_USE( "file1", "file_one" )// Creates if not existing
  1139.     V_SELECT(2)
  1140.     V_USE( "file2" )         // Creates if not existing
  1141.  
  1142.     ? V_ALIAS()              //  Returns: file2
  1143.     ? V_ALIAS(1)             //  Returns: FILE_ONE
  1144.  
  1145.  
  1146. See Also: V_SELECT() V_USE() V_FILES() V_FILE()
  1147.  
  1148.  
  1149. ───────────────────────────────────────────────────────────────────────────────
  1150.  V_BUFFERS()
  1151.  Declare or retrieve the number of DBV file buffers
  1152. ───────────────────────────────────────────────────────────────────────────────
  1153.  
  1154.  Syntax
  1155.  
  1156.     V_BUFFERS( [<nBuffers>] )    ->    nBuffers
  1157.  
  1158.  Arguments
  1159.  
  1160.     <nBuffers> is an integer value indicating a number of 1K buffers.
  1161.     The default (which is also the minimum value) is 3 buffers.
  1162.  
  1163.  Returns
  1164.  
  1165.     V_BUFFERS() returns an integer indicating the previous setting of
  1166.     the number of 1K buffers.
  1167.  
  1168.  Description
  1169.  
  1170.     FlexFile manages all file input and output through a set of 1K
  1171.     buffers. Because there is such a diversity in buffered I/O from
  1172.     machine to machine, FlexFile offers the ability to customize the
  1173.     amount of space used for this purpose.
  1174.  
  1175.     If you are running with a disk cache or are tight on memory, leave
  1176.     the buffers at their default (and minimum) value of 3. If you have
  1177.     the space and would like to increase performance, increase the
  1178.     number of buffers.
  1179.  
  1180.  Notes
  1181.  
  1182.   ■ The buffers may only be changed when no DBV files are in use.
  1183.  
  1184.  Examples
  1185.  
  1186.     // Set FlexFile's buffers to 5K
  1187.     V_BUFFERS(5)
  1188.  
  1189.     V_USE( "file" )       // Open a file.
  1190.  
  1191.     // This line has no effect because files are open.
  1192.     V_BUFFERS(10)
  1193.  
  1194.     ? V_BUFFERS()         // Result: 5
  1195.  
  1196.  
  1197. See Also: V_FILES() V_USE()
  1198.  
  1199.  
  1200. ───────────────────────────────────────────────────────────────────────────────
  1201.  V_CLOSE()
  1202.  Close a DBV type file
  1203. ───────────────────────────────────────────────────────────────────────────────
  1204.  
  1205.  Syntax
  1206.  
  1207.     V_CLOSE( [<nWorkArea> | <cAlias>] )
  1208.  
  1209.  Arguments
  1210.  
  1211.     <nWorkArea> or <cAlias> is the DBV area or alias to close. If none
  1212.     is specified the file in the current DBV area is closed.
  1213.  
  1214.  Returns
  1215.  
  1216.     None.
  1217.  
  1218.  Description
  1219.  
  1220.     V_CLOSE() closes a FlexFile DBV type file. This is equivalent to
  1221.     V_USE() with no arguments.
  1222.  
  1223.  Notes
  1224.  
  1225.   ■ This function does not affect and is not affected by any
  1226.     Clipper data base functions or commands.
  1227.  
  1228.  Examples
  1229.  
  1230. // Open a DBV type file in FlexFile's area 1.
  1231. V_SELECT(1)
  1232. V_USE( "file" )
  1233.  
  1234. // Select a second area just for the heck of it.
  1235. V_SELECT(2)
  1236.  
  1237. // Close the file in area one.
  1238. V_CLOSE(1)
  1239.  
  1240. // Close a file (if one is open) in area 2
  1241. V_CLOSE()
  1242.  
  1243. See Also: V_USE() V_CLOSEALL()
  1244.  
  1245.  
  1246. ───────────────────────────────────────────────────────────────────────────────
  1247.  V_CLOSEALL()
  1248.  Close all open DBV type files
  1249. ───────────────────────────────────────────────────────────────────────────────
  1250.  
  1251.  Syntax
  1252.  
  1253.     V_CLOSEALL()
  1254.  
  1255.  Arguments
  1256.  
  1257.     None.
  1258.  
  1259.  Returns
  1260.  
  1261.     None.
  1262.  
  1263.  Description
  1264.  
  1265.     V_CLOSEALL() closes all open DBV type files in all open DBV work
  1266.     areas. In addition, the cache described by V_BUFFERS() and
  1267.     V_FILES() is released.
  1268.  
  1269.  Notes
  1270.  
  1271.   ■ This function does not affect and is not affected by any
  1272.     Clipper data base functions or commands.
  1273.  
  1274.  Examples
  1275.  
  1276. // Open a DBV type file in FlexFile's area 1.
  1277. V_SELECT(1)
  1278. V_USE( "file" )
  1279.  
  1280. // Open a second file in the next available area.
  1281. V_USE( "file2", , "NEW" )
  1282.  
  1283. // Close all open files.
  1284. V_CLOSEALL()
  1285.  
  1286. See Also: V_CLOSE() V_USE()
  1287.  
  1288.  
  1289. ───────────────────────────────────────────────────────────────────────────────
  1290.  V_COMMIT()
  1291.  Commit the DOS buffers to disk.
  1292. ───────────────────────────────────────────────────────────────────────────────
  1293.  
  1294.  Syntax
  1295.  
  1296.     V_COMMIT( [<nArea> | <cAlias>] )   ->   lSuccess
  1297.  
  1298.  Arguments
  1299.  
  1300.     <nArea> or <nAlias> is the DBV work area or alias whose buffers
  1301.     will be flushed.  Omitting this parameter causes all open DBV file
  1302.     buffers to be flushed.
  1303.  
  1304.  Returns
  1305.  
  1306.     V_COMMIT() returns a (.T.) on success.  Otherwise, it returns
  1307.     (.F.).
  1308.  
  1309.  Description
  1310.  
  1311.     DOS "buffers" disk I/O in order to speed up disk access.  The
  1312.     downside to this feature is that the data in the buffers can be
  1313.     lost if the machine "hangs" or is powered down before the buffers
  1314.     are copied to disk.  This problem was addressed in DOS version 3.3
  1315.     and later by allowing a call which forces DOS's buffers to be
  1316.     written to disk.  V_COMMIT() makes this call to DOS as described
  1317.     below.
  1318.  
  1319.     By default, FlexFile automatically commits all DOS buffers after
  1320.     every write operation. If you like this behavior, you should never
  1321.     need to call V_COMMIT().  This is the safest method but also the
  1322.     slowest.  In order to change this default behavior, the
  1323.     V_SET_COMMIT() function can be passed a logical (.T.) or (.F.) to
  1324.     turn on/off the automatic flushing feature. If automatic flushing
  1325.     is turned off, you must call V_COMMIT() explicitly in order to
  1326.     flush the DOS buffers as described below.
  1327.  
  1328.     If no parameter is passed, V_COMMIT() flushes all open DBV work
  1329.     areas to disk.
  1330.  
  1331.     If a numeric DBV work area or a character alias is passed,
  1332.     V_COMMIT() will flush the buffers associated with the work area
  1333.     specified.
  1334.  
  1335.         ┌──────────────────────── WARNING ─────────────────────────┐
  1336.         │ V_COMMIT and V_SET_COMMIT() are based on functions       │
  1337.         │ provided in DOS 3.3 and later.  Calls made to these      │
  1338.         │ functions on an earlier version of DOS will have no      │
  1339.         │ affect.                                                  │
  1340.         └──────────────────────────────────────────────────────────┘
  1341.  
  1342.  Example
  1343.  
  1344.     // Turn off automatic flushing in order to speed up operation.
  1345.     V_USE( "temp" )
  1346.     V_SET_COMMIT(.f.)
  1347.  
  1348.     DO WHILE !EOF()
  1349.        IF DELETED()
  1350.           REPLACE vlf_fld WITH V_DELETE( vlf_fld )
  1351.        ENDIF
  1352.        SKIP
  1353.     ENDDO
  1354.     PACK
  1355.  
  1356.     // Flush the buffers and turn automatic flushing back on.
  1357.     V_COMMIT()
  1358.     V_SET_COMMIT(.T.)
  1359.  
  1360.  
  1361. See also: V_SET_COMMIT() V_REPLACE() V_DELETE()
  1362.  
  1363.  
  1364.  
  1365. ───────────────────────────────────────────────────────────────────────────────
  1366.  V_DECRYPT()
  1367.  Decrypt a variable that has been encrypted with V_ENCRYPT()
  1368. ───────────────────────────────────────────────────────────────────────────────
  1369.  
  1370.  Syntax
  1371.  
  1372.     V_DECRYPT( <cEncrypted_string> )   ->    cOriginal
  1373.  
  1374.  Arguments
  1375.  
  1376.     <cEncrypted_string> is a variable previously encrypted with
  1377.     the V_ENCRYPT() function.
  1378.  
  1379.  Returns
  1380.  
  1381.     V_DECRYPT() returns a string as it was before a call to V_ENCRYPT().
  1382.  
  1383.  Description
  1384.  
  1385.     V_DECRYPT() will decrypt a string that has been previously encrypted
  1386.     with the V_ENCRYPT() function.  The string will only be decrypted
  1387.     properly if the V_SETKEY() function has been called with the same key
  1388.     that was in effect when the V_ENCRYPT() originally scrambled the
  1389.     <cEncrypted_string>.
  1390.  
  1391.  Examples
  1392.  
  1393.     LOCAL cSecure, cOriginal
  1394.  
  1395.     // Set the key to my dog's name.
  1396.     V_SETKEY( "Tally" )
  1397.  
  1398.     // Encrypt a character string.  Store the result in <cSecure>.
  1399.     cSecure = V_ENCRYPT( "Just try to decode <cSecure> without my dog." )
  1400.  
  1401.     // Later, decode the secured string with the help of my golden.
  1402.     // The call to V_SETKEY() is redundant because the program has not
  1403.     // terminated and it has not been set to a different V_SETKEY().
  1404.     V_SETKEY( "Tally" )
  1405.     cOriginal = V_DECRYPT( cSecure )
  1406.  
  1407.  
  1408. See Also: V_SETKEY() V_ENCRYPT()
  1409.  
  1410.  
  1411.  
  1412. ───────────────────────────────────────────────────────────────────────────────
  1413.  V_DELETE()
  1414.  Delete one field from a DBV file
  1415. ───────────────────────────────────────────────────────────────────────────────
  1416.  
  1417.  Syntax
  1418.  
  1419.     V_DELETE(    <cPointer>,
  1420.                  [<nArea> | <cAlias>] )    ->    cNull
  1421.  
  1422.  Arguments
  1423.  
  1424.     <cPointer> is a six byte pointer-field (FlexFile's version of a
  1425.     memo-field).
  1426.  
  1427.     <nArea> or <nAlias> is the DBV work area or alias with which
  1428.     <cPointer> is related.
  1429.  
  1430.  Returns
  1431.  
  1432.     V_DELETE() returns a null string ("").
  1433.  
  1434.  Description
  1435.  
  1436.     V_DELETE() releases the space pointed to by <cPointer>. This space
  1437.     is then available for use by the next call to V_REPLACE() or any
  1438.     other function that requires DBV space. It is important to
  1439.     remember that there is no V_RECALL(). That is, once a DBV has been
  1440.     V_DELETE()d, that field is no longer recoverable.
  1441.  
  1442.     When you delete a record in a DBF file and you want to be able to
  1443.     recall that record (and its related VLF), do not use V_DELETE().
  1444.     Instead, just DELETE the record in the DBF. When you are ready to
  1445.     PACK the DBF, run a routine similar to the example below.
  1446.  
  1447.       ┌──────────────────────── WARNING ─────────────────────────┐
  1448.       │ V_DELETE() deletes the data associated with <cPointer>.  │
  1449.       │ Attempting to use <cPointer> after this function deletes │
  1450.       │ the data that it points to can corrupt the DBV file.     │
  1451.       └──────────────────────────────────────────────────────────┘
  1452.  
  1453.  Notes
  1454.  
  1455.   ■ V_DELETE() is permanent; there is no V_RECALL().
  1456.  
  1457.   ■ V_DELETE() is not necessary before a V_REPLACE(). The second
  1458.     parameter of V_REPLACE() is a pointer whose data space will be
  1459.     released before the REPLACE.
  1460.  
  1461.  Examples
  1462.  
  1463.     // Open a DBF and its related DBV
  1464.     USE dbf_file
  1465.     V_USE( "dbv_file" )
  1466.  
  1467.     // Store some data in the DBV and a pointer to the
  1468.     // data in a six byte pointer-field in the DBF
  1469.     REPLACE vlf WITH V_REPLACE( "This string is doomed", vlf )
  1470.  
  1471.     // Now delete that string.
  1472.     REPLACE vlf WITH V_DELETE( vlf )
  1473.  
  1474.     // Note: It is important to erase the pointer stored in
  1475.     //       vlf once its data has been deleted.  Because
  1476.     //       V_DELETE() returns a null string, REPLACEing <vlf> 
  1477.     //       guarantees that the pointer-field vlf will be
  1478.     //       destroyed.
  1479.  
  1480. See Also: V_REPLACE() V_STUFF()
  1481.  
  1482.  
  1483.  
  1484. ───────────────────────────────────────────────────────────────────────────────
  1485.  V_ENCRYPT()
  1486.  Encrypt a Clipper string variable
  1487. ───────────────────────────────────────────────────────────────────────────────
  1488.  
  1489.  Syntax
  1490.  
  1491.     V_ENCRYPT( <cString> )   ->    cGobbleTgook
  1492.  
  1493.  Arguments
  1494.  
  1495.     <cString> is any valid Clipper character string.
  1496.  
  1497.  Returns
  1498.  
  1499.     V_ENCRYPT() returns an ecrypted string with the same length as
  1500.     the original.
  1501.  
  1502.  Description
  1503.  
  1504.     V_ENCRYPT() encrypts a Clipper string based on the current key setting
  1505.     (see V_SETKEY()).  The string can later be V_DECRYPT()ed by using the
  1506.     same V_SETKEY() setting.
  1507.  
  1508.     V_ENCRYPT() encrypts a Clipper string so that it is not human readable.
  1509.     The encryption algorithm has not been designed to any particular
  1510.     specification, however, as the author of the algorithm, I would not
  1511.     want to be faced with the task of decrypting a string without the
  1512.     <key> with which it was encrypted (see V_SETKEY()).
  1513.  
  1514.  Examples
  1515.  
  1516.     LOCAL cSecure, cOriginal
  1517.  
  1518.     // Set the key to my dog's name.
  1519.     V_SETKEY( "Tally" )
  1520.  
  1521.     // Encrypt a character string.  Store the result in <cSecure>.
  1522.     cSecure = V_ENCRYPT( "Just try to decode <cSecure> without my dog." )
  1523.  
  1524.     // Later, decode the secured string with the help of my golden.
  1525.     // The call to V_SETKEY() is redundant because the program has not
  1526.     // terminated and it has not been set to a different V_SETKEY().
  1527.     V_SETKEY( "Tally" )
  1528.     cOriginal = V_DECRYPT( cSecure )
  1529.  
  1530.  
  1531. See Also: V_SETKEY() V_DECRYPT()
  1532.  
  1533.  
  1534.  
  1535. ───────────────────────────────────────────────────────────────────────────────
  1536.  V_ERROR()
  1537.  Report specific error codes from the DBV system
  1538. ───────────────────────────────────────────────────────────────────────────────
  1539.  
  1540.  Syntax
  1541.  
  1542.     V_ERROR()   ->    nErrorCode
  1543.  
  1544.  Arguments
  1545.  
  1546.     None.
  1547.  
  1548.  Returns
  1549.  
  1550.     V_ERROR() returns the FlexFile error code as a numeric integer.
  1551.  
  1552.  Description
  1553.  
  1554.     V_ERROR() is an error reporting function that will return the most
  1555.     recent error code that FlexFile set. If a failed operation has no
  1556.     FlexFile error code check the DOS error code by using Clipper's
  1557.     DOSERROR() function.
  1558.  
  1559.     For a complete list of error codes and their descriptions refer to
  1560.     Appendix B.
  1561.  
  1562.  Examples
  1563.  
  1564.     // Trying to V_REPLACE() data in an area that does not have a
  1565.     // file open causes an error.
  1566.     V_FILES(4)
  1567.     USE dbf_file       // Valid DBF file is opened.
  1568.     V_SELECT( 4 )      // No DBV file is open in area 4.
  1569.  
  1570.     // V_REPLACE() will return (.F.) because there is no file
  1571.     // open in area 4.  Because vlf is a six byte character
  1572.     // field, a runtime "data type mismatch" is produced.
  1573.     REPLACE vlf WITH V_REPLACE("Data type mismatch", vlf)
  1574.  
  1575.     //  In errorsys.prg...
  1576.     ? V_ERROR()     //  Returns 7301.
  1577.                     // Appendix B: DBV file not open.
  1578.  
  1579.  
  1580. See Also: errcodes.ngo:"Error Codes Introduction"
  1581.  
  1582.  
  1583.  
  1584. ───────────────────────────────────────────────────────────────────────────────
  1585.  V_EXCLUSIV()
  1586.  Establish exclusive or shared use of a DBV type file
  1587. ───────────────────────────────────────────────────────────────────────────────
  1588.  
  1589.  Syntax
  1590.  
  1591.     V_EXCLUSIV( <lToggle> )  ->    lSetting
  1592.  
  1593.  Arguments
  1594.  
  1595.     <lToggle> is a logical value. If <lToggle> is (.T.), then
  1596.     subsequent files opened with V_USE() will be opened exclusively.
  1597.  
  1598.     If <lToggle> is (.F.), then subsequent files opened with V_USE()
  1599.     will be opened in shared mode.
  1600.  
  1601.  Returns
  1602.  
  1603.     The current setting of V_EXCLUSIV().
  1604.  
  1605.  Description
  1606.  
  1607.     In a network environment, V_EXCLUSIV() determines whether the
  1608.     V_USE() function specified without the <lExclusive> parameter will
  1609.     be opened in shared or exclusive mode. If <lToggle> is (.T.) (the
  1610.     default), other users cannot V_USE() the same file until it has
  1611.     been closed.
  1612.  
  1613.     If <lToggle> is (.F.), all subsequent files opened by V_USE() without the
  1614.     <lExclusive> parameter will be opened in shared mode. Access by
  1615.     other users must be controlled programmatically. Typically, this
  1616.     can be done with Clipper's RLOCK() and FLOCK() functions. That is,
  1617.     if the pointer to a DBV is kept in a DBF file, then RLOCK()ing the
  1618.     record containing the pointer will prevent other users from
  1619.     accessing that field.
  1620.  
  1621.     Refer to Network Programming for more information.
  1622.  
  1623.  Notes
  1624.  
  1625.   ■ Error handling: Attempting to V_USE() a file which has been
  1626.     opened exclusively by another user causes V_USE() to return a -1.
  1627.     V_ERROR() will return an error code indicating this condition.
  1628.  
  1629.  Examples
  1630.  
  1631.     // Set up the environment so that all files are opened
  1632.     // in shared mode.
  1633.     #define EXCLUSIVE (.T.)
  1634.     V_EXCLUSIV( !EXCLUSIVE )
  1635.     
  1636.     // This file will be opened in shared mode.
  1637.     IF V_USE( "mainfile" ) == -1
  1638.        ? "Error: " + str( V_ERROR(), 4 )
  1639.        QUIT
  1640.     ENDIF
  1641.  
  1642.     // This V_USE() overrides the global V_EXCLUSIV() setting
  1643.     // and opens the file exclusively.
  1644.     V_USE( "tempfile", , "NEW", EXCLUSIVE )
  1645.  
  1646.     // Close all files.
  1647.     V_CLOSEALL()
  1648.  
  1649. See Also: V_USE() network.ngo:"Network Programming"
  1650.  
  1651.  
  1652.  
  1653. ───────────────────────────────────────────────────────────────────────────────
  1654.  V_FILE2VLF()
  1655.  Copy a DOS file into a VLF
  1656. ───────────────────────────────────────────────────────────────────────────────
  1657.  
  1658.  Syntax
  1659.  
  1660.     V_FILE2VLF(  <cFileName>,
  1661.                  <cOldPointer> )  ->     cNewPointer
  1662.  
  1663.  Arguments
  1664.  
  1665.     <cFileName> is the name of a disk file optionally including the
  1666.     path and drive designators.
  1667.  
  1668.     <cOldPointer> is a required six byte pointer-field or variable in
  1669.     which you have previously stored a pointer to variable length
  1670.     data. Passing six spaces causes FlexFile to assume that there is
  1671.     no old data to be released before the new <exp> data is saved.
  1672.  
  1673.  Returns
  1674.  
  1675.     V_FILE2VLF() returns a pointer which should be stored in the
  1676.     pointer- field with which the copied file is to be associated.
  1677.  
  1678.     V_FILE2VLF() returns (.F.) on error.  This causes the error system
  1679.     to be invoked with a "Data Type Mismatch".  Use V_ERROR() to fetch
  1680.     the specific error value (see Appendix B for a table of error
  1681.     descriptions).
  1682.  
  1683.     A typical error from this function is "File not found".  It is,
  1684.     therefore, the responsibility of the programmer to test for this
  1685.     condition before executing V_FILE2VLF().
  1686.  
  1687.  
  1688.  Description
  1689.  
  1690.     V_FILE2VLF() provides a mechanism for copying a DOS disk file into
  1691.     a VLF.  This is particularly handy in converting an application
  1692.     which has used Clipper's MEMOWRITE() function.
  1693.  
  1694.     V_FILE2VLF() is also handy for copying graphics images from disk
  1695.     files into a DBV file. When used in conjunction with V_VLF2FILE()
  1696.     a system can be implemented to handle graphics images which is
  1697.     compatible with the file based graphics systems such as DGE,
  1698.     SilverPaint, Flipper and the like.
  1699.  
  1700.     ┌────────────────────────── WARNING ──────────────────────────┐
  1701.     │ V_FILE2VLF() deletes the data associated with <cOldPointer> │
  1702.     │ before returning <cNewPointer>.  Attempting to use          │
  1703.     │ <cOldPointer> after this function deletes the data that it  │
  1704.     │ points to can corrupt the DBV file.                         │
  1705.     └─────────────────────────────────────────────────────────────┘
  1706.  
  1707.  Notes
  1708.  
  1709.   ■ No additional memory is required to copy a file into a VLF. It
  1710.     is, therefore, possible to import a file larger than 65K
  1711.     (Clipper's variable size limit).
  1712.  
  1713.   ■ V_TYPE() will return "C" (character) for any VLF that has been
  1714.     created by V_FILE2VLF(). This implies that V_RETRIEVE() will
  1715.     return a character string.
  1716.  
  1717.  Examples
  1718.  
  1719.     // Open a DBF file and its related DBV file
  1720.     // The dbf_file has a 12 byte field called "exe_name"
  1721.     // and the usual 6 byte field called "vlf"
  1722.     USE dbf_file
  1723.     ZAP
  1724.     INDEX ON exe_name TO dbf_file
  1725.     V_USE( "dbv_file" )
  1726.  
  1727.     // This may seem silly, but lets store the Clipper compiler
  1728.     // in the DBV file.
  1729.     APPEND BLANK
  1730.     REPLACE exe_name WITH "CLIPPER.EXE"
  1731.  
  1732.     // This will copy the Clipper.exe into a VLF.
  1733.     REPLACE vlf WITH V_FILE2VLF( exe_name, vlf )
  1734.  
  1735.     // Later when we want to execute Clipper (you better have
  1736.     // lots of memory).
  1737.     SEEK "CLIPPER.EXE"
  1738.     ? V_VLF2FILE( "TEMP.EXE",  vlf )
  1739.     ? V_ERROR()
  1740.  
  1741.     RUN temp
  1742.  
  1743.  
  1744. See Also: V_DBV2FILE() V_RETRIEVE()
  1745.  
  1746.  
  1747.  
  1748. ───────────────────────────────────────────────────────────────────────────────
  1749.  V_FILENAME()
  1750.  Return the file name of a file opened in a specified area
  1751. ───────────────────────────────────────────────────────────────────────────────
  1752.  
  1753.  Syntax
  1754.  
  1755.     V_FILENAME( [<nArea> | <cAlias>] )    ->    cFileName
  1756.  
  1757.  Arguments
  1758.  
  1759.     <nArea> or <cAlias> refers to the number or name of the target DBV
  1760.     work area.  If not specified, V_FILENAME() returns the file name
  1761.     from the currently selected DBV work area.
  1762.  
  1763.  Returns
  1764.  
  1765.     V_FILENAME() returns the DOS file name of the DBV file opened in
  1766.     the specified area.  If no file is open in the specified area,
  1767.     V_FILENAME() returns a null string ( "" ).
  1768.  
  1769.  Description
  1770.  
  1771.     V_FILENAME() is used to retrieve the DOS file name that refers to
  1772.     the DBV file. This name will not include the drive or path
  1773.     designators.
  1774.  
  1775.     This function is provided specifically for debugging where it is
  1776.     sometimes insufficient to only have access to the alias.
  1777.  
  1778.  Examples
  1779.  
  1780.     // Show the name of the file (not the alias)
  1781.     V_SELECT(1)
  1782.     V_USE( "pic_file.dbv", "pictures" )
  1783.  
  1784.     ? V_FILENAME()        //  Returns: PIC_FILE.DBV
  1785.     ? V_ALIAS()           //  Returns: PICTURES
  1786.     
  1787.     V_SELECT(2)
  1788.     ? V_FILENAME( "PICTURES" )//  Returns: PIC_FILE.DBV
  1789.     
  1790.     
  1791. See Also: V_ALIAS()
  1792.  
  1793.  
  1794.  
  1795. ───────────────────────────────────────────────────────────────────────────────
  1796.  V_FILES()
  1797.  Set the maximum number of DBV files to be in use concurrently
  1798. ───────────────────────────────────────────────────────────────────────────────
  1799.  
  1800.  Syntax
  1801.  
  1802.     V_FILES( [<nMaxFiles>] )    ->    nCurrentMax
  1803.  
  1804.  Arguments
  1805.  
  1806.     <nMaxFiles> is the maximum number of DBV type files that can be in
  1807.     V_USE() concurrently. If none is specified, V_FILES() will simply
  1808.     return the current setting.
  1809.  
  1810.  Returns
  1811.  
  1812.     V_FILES() returns the current setting of the maximum file count.
  1813.  
  1814.  Description
  1815.  
  1816.     V_FILES() offers the programmer the opportunity to set the maximum
  1817.     number of files that the program will have in use at any one time.
  1818.     This feature allows FlexFile to keep the memory used for the file
  1819.     headers in a contiguous block which avoids memory fragmentation.
  1820.  
  1821.     Each file requires 84 bytes for the header information. Therefore,
  1822.     multiply the <nMaxFiles> by 84 in order to calculate the total
  1823.     memory requirement for the files opened in your system.
  1824.  
  1825.  Notes
  1826.  
  1827.   ■ The maximum number of files cannot be changed unless all DBV files are
  1828.     closed.
  1829.  
  1830.   ■ This function is independent of the V_BUFFERS() setting.
  1831.  
  1832.  Examples
  1833.  
  1834.     // Set FlexFile's maximum file count to 2 files
  1835.     V_FILES(2)
  1836.  
  1837.     V_USE( "file1" )         // Open first file.
  1838.     V_USE( "file2", ,"NEW" ) // Open second file
  1839.                              // in a new area.
  1840.  
  1841.     // Attempt to open a third file in a new area fails.
  1842.     IF V_USE( "file3", ,"NEW" ) == -1
  1843.        ? "Too many files in use."
  1844.        ? V_ERROR()        // Result: 8001
  1845.     ENDIF
  1846.  
  1847.     // This line has no effect because files are open.
  1848.     V_FILES(5)
  1849.  
  1850.     ? V_FILES()           // Result: 2
  1851.  
  1852.  
  1853. See Also: V_BUFFERS() V_USE()
  1854.  
  1855.  
  1856.  
  1857. ───────────────────────────────────────────────────────────────────────────────
  1858.  V_FILLARR()
  1859.  Fill a Clipper array with contents stored to a DBV file
  1860. ───────────────────────────────────────────────────────────────────────────────
  1861.  
  1862.           See V_ARETRIEV() for retrieving Clipper 5.0 arrays
  1863.  
  1864.  Syntax
  1865.  
  1866.     V_FILLARR(   <aTarget>,
  1867.                  <cPointer>,
  1868.                  [<nArea> | <cAlias>] )
  1869.  
  1870.  Arguments
  1871.  
  1872.     <aTarget> is the Clipper array to be filled.
  1873.  
  1874.     <cPointer> is a six byte pointer-field that points to the DBV
  1875.     containing a Clipper type array.
  1876.  
  1877.     <cAlias> or <nArea> is a DBV file alias or area specified when the
  1878.     file was V_USE()d. If omitted, the pointer will point into the
  1879.     currently selected DBV area.
  1880.  
  1881.  Returns
  1882.  
  1883.     None.  However, <aTarget> is modified.
  1884.  
  1885.  Description
  1886.  
  1887.     V_FILLARR() is used to fill a Clipper S87 type array. The <aTarget>
  1888.     array must exist and will be filled until <aTarget> has no remaining
  1889.     elements or the array pointed to by <cPointer> has no more elements
  1890.     (which ever limit is reached first).
  1891.  
  1892.     Use the V_LEN() function to dimension the array immediately before
  1893.     V_FILLARR() (see examples below).
  1894.  
  1895.     The ability to save Clipper arrays is one of the most powerful
  1896.     features of FlexFile. Essentially, it simulates Variable Length
  1897.     Records as well as creating a three dimensional effect in your
  1898.     data base files.
  1899.  
  1900.     For example, picture a student master DBF file with the fields
  1901.     LastName, FirstName, Addr, Major, and Minor. If you decide to
  1902.     expand the file and include the sports, clubs and associations
  1903.     that the student is involved in, you have two choices. You can
  1904.     create a new related file (with a new index), or you can insert
  1905.     several new fields in the master DBF for each category, limiting
  1906.     the entries possible in any one category and wasting space on
  1907.     students who do not have entries in one or more of the categories.
  1908.  
  1909.     With FlexFile, however, you can add just one field in the master
  1910.     file and save an array of any length to this field. Not only do
  1911.     you eliminate a file, its index, and its relation, but also, one
  1912.     function call can load arrays with the new data eliminating the
  1913.     need to code "scatter" and "gather" routines.
  1914.  
  1915.  Notes
  1916.  
  1917.   ■ You must use this function from within a Clipper 5.0 application
  1918.     only to retrieve an array which was stored with a FlexFile S87
  1919.     library version 1.01 or less (version 1.01 was dated 2/18/91).
  1920.     See V_FILLEN() for an example of a conversion routine.
  1921.  
  1922.   ■ It is not necessary to use this routine to retrieve a FlexFile
  1923.     type array.
  1924.  
  1925.  Examples
  1926.  
  1927.     && S'87 compiler only. See V_ARETRIEV() for Clipper 5.0
  1928.  
  1929.     && Open a DBF and a related DBV file
  1930.     USE dbf_file
  1931.     V_USE( "dbv_file" )
  1932.  
  1933.     DECLARE aNames[3]
  1934.     aNames[1] = "Tania"
  1935.     aNames[2] = "Mary"
  1936.     aNames[3] = "Allison"
  1937.  
  1938.     && Store the array to the DBV file and its pointer to the DBF
  1939.     REPLACE vlf WITH V_REPLACE( aNames, vlf )
  1940.  
  1941.     && Declare the new array to the proper size.
  1942.     DECLARE aNewNames[ V_LEN( vlf ) ]
  1943.  
  1944.     && Fill the array with the data.
  1945.     V_FILLARR( aNewNames, vlf )
  1946.  
  1947.     && Show that it worked
  1948.     ? aNewNames[1]        && Result: Tania
  1949.  
  1950.  
  1951.  
  1952. See Also: V_FILLEN() V_ARETRIEV() V_AREPLACE() V_REPLACE() V_LEN()
  1953.  
  1954.  
  1955.  
  1956.  
  1957. ───────────────────────────────────────────────────────────────────────────────
  1958.  V_FILLLEN()
  1959.  Return the length of a S'87 array.
  1960. ───────────────────────────────────────────────────────────────────────────────
  1961.  
  1962.           See V_ARETRIEV() for retrieving Clipper 5.0 arrays
  1963.  
  1964.  Syntax
  1965.  
  1966.     V_FILLEN( <cPointer>, [<nArea> | <cAlias>] )
  1967.  
  1968.  Arguments
  1969.  
  1970.     <cPointer> is a six byte pointer-field that points to the DBV
  1971.     containing a Clipper type array that was created by an application
  1972.     compiled with the S'87 compiler and linked with Flex_87.lib version
  1973.     1.01 or earlier (version 1.01 was dated 2/18/91).
  1974.  
  1975.     <cAlias> or <nArea> is a DBV file alias or area specified when the
  1976.     file was V_USE()d. If omitted, the pointer will point into the
  1977.     currently selected DBV area.
  1978.  
  1979.  Returns
  1980.  
  1981.     The length of the array as it was stored.
  1982.  
  1983.  Description
  1984.  
  1985.     V_FILLEN() is used in conjunction with V_FILLARR() in order to convert
  1986.     an array which was saved by a previous version of FlexFile.  Only use
  1987.     this function pair to retrieve arrays created with the S'87 compiler
  1988.     into an application which is compiled with the Clipper 5.0 compiler.
  1989.  
  1990.     Use the V_FILLEN() function to dimension the array immediately before
  1991.     V_FILLARR() (see examples below).
  1992.  
  1993.  Notes
  1994.  
  1995.   ■ This is a compatibility function only and should be used only to
  1996.     convert arrays that were saved with earlier versions of FlexFile to
  1997.     new format.
  1998.  
  1999.   ■ It is not necessary to use this routine to retrieve a FlexFile
  2000.     type array.
  2001.  
  2002.  Examples
  2003.  
  2004.     && Clipper 5.0 compiler retrieving an array saved with
  2005.     && FlexFile version 1.01 or earlier.
  2006.     LOCAL aNewNames
  2007.  
  2008.     && Open a DBF and a related DBV file
  2009.     USE dbf_file
  2010.     V_USE( "dbv_file" )
  2011.  
  2012.     && Declare the new array to the proper size.
  2013.     DECLARE aNewNames[ V_FILLEN( vlf ) ]
  2014.  
  2015.     && Fill the array with the data.
  2016.     V_FILLARR( aNewNames, vlf )
  2017.  
  2018.     && Save it back for future easy use.
  2019.     dbf_file->vlf := V_AREPLACE( aNewNames, dbf_file->vlf )
  2020.  
  2021.     && Now it is easy to get at:
  2022.     aNewNames := V_ARETRIEVE( dbf_file->vlf )
  2023.  
  2024.  
  2025. See Also: V_ARETRIEV() V_AREPLACE() V_REPLACE() V_LEN()
  2026.  
  2027.  
  2028.  
  2029. ───────────────────────────────────────────────────────────────────────────────
  2030.  V_GETWNDRC()
  2031.  Return the rows or columns from a Proclip window stored in a DBV file
  2032. ───────────────────────────────────────────────────────────────────────────────
  2033.  
  2034.  Syntax
  2035.  
  2036.     V_GETWNDRC( <cPointer>, <cRowOrCol> )    ->    nValue
  2037.  
  2038.  Arguments
  2039.  
  2040.     <cPointer> is a six byte pointer-field (FlexFile's version of a
  2041.     memo-field).
  2042.  
  2043.     <cRowOrCol> is either an 'R' or a 'C' (non case sensitive)
  2044.     requesting the row or column respectively.
  2045.  
  2046.  Returns
  2047.  
  2048.     V_GETWNDRC() returns the rows or columns of a Proclip window in a
  2049.     DBV file much like Proclip's WNDVROWS() and WNDVCOLS() would.
  2050.  
  2051.  Description
  2052.  
  2053.     V_GETWNDRC() is used to query a Proclip window that has been saved
  2054.     to a DBV. The rows and columns are the virtual rows and columns
  2055.     and not the rows and columns of a viewport that may have been
  2056.     active when the window was V_REPLACE()d.
  2057.  
  2058.  
  2059.  Examples
  2060.  
  2061.     // Create a proclip window
  2062.     pc_handle = WNDCREATE( 5, 10 )
  2063.  
  2064.     // Save the window to a DBV file
  2065.     REPLACE vlf WITH V_REPLACE( pc_handle, , , 'P' )
  2066.  
  2067.     // Show the rows and columns of the window.
  2068.     ? V_GETWNDRC( vlf, 'R' ) // Result: 5
  2069.     ? V_GETWNDRC( vlf, 'C' ) // Result: 10
  2070.  
  2071.  
  2072. See Also: V_REPLACE() V_TYPE()
  2073.  
  2074. ───────────────────────────────────────────────────────────────────────────────
  2075.  V_HANDLE()
  2076.  Return the DOS file handle for a DBV file.
  2077. ───────────────────────────────────────────────────────────────────────────────
  2078.  
  2079.  Syntax
  2080.  
  2081.     V_HANDLE( [<nArea> | <cAlias>] )      ->   nHandle
  2082.  
  2083.  Arguments
  2084.  
  2085.     <nArea> or <cAlias> refers to the number or name of the target DBV
  2086.     work area. If not specified, the current DBV work area is assumed.
  2087.  
  2088.  Returns
  2089.  
  2090.     V_HANDLE() returns a numeric integer whose value is the DOS file handle
  2091.     for the specified DBV work area.
  2092.  
  2093.  Description
  2094.  
  2095.     V_HANDLE() can be used in conjunction with Clipper's Fxxxx() class of
  2096.     low level file functions.  Great care must be taken when using FWRITE()
  2097.     to assure that the bounds of the VLF are not overwritten.  It is far
  2098.     safer and usually sufficient to use V_RETRIEVE() and V_POKE() to manage
  2099.     low level access to a VLF.
  2100.  
  2101.       ┌───────────────────────── WARNING ───────────────────────────┐
  2102.       │ Extreme care must be taken when using FWRITE() on a DBV     │
  2103.       │ type file.  Overwriting the bounds of a VLF by one byte can │
  2104.       │ corrupt the entire file.                                    │
  2105.       └─────────────────────────────────────────────────────────────┘
  2106.  
  2107.  
  2108.  Examples
  2109.  
  2110.     #include "fileio.ch"
  2111.     LOCAL buffer
  2112.  
  2113.     // Open a DBF file and its related DBV file
  2114.     USE dbf_file
  2115.     V_USE( "dbv_file" )
  2116.  
  2117.     FSEEK( V_HANDLE(), V_PTR( vlf_fld ), FS_SET )
  2118.  
  2119.     buffer = SPACE( V_LEN( vlf_fld ) )
  2120.     FREAD( V_HANDLE(), @buffer, LEN(BUFFER) )
  2121.  
  2122.     // The above code will fetch a VLF without file locking or
  2123.     // error checking just like the following one line of code:
  2124.     //         buffer = V_RETRIEVE( vlf_fld )
  2125.  
  2126.  
  2127. See Also: V_POKE() V_RETRIEVE() V_PTR() V_LEN()
  2128.  
  2129. ────────────────────────────────────────────────────────────────────────────────
  2130.  V_ISOPEN()
  2131.  Determine if a file is open in an area.
  2132. ────────────────────────────────────────────────────────────────────────────────
  2133.  
  2134.  Syntax
  2135.  
  2136.     V_ISOPEN( [<nArea> | <cAlias>] )      ->   lStatus
  2137.  
  2138.  Arguments
  2139.  
  2140.     <nArea> or <cAlias> refers to the number or name of the target DBV
  2141.     work area. If not specified, the current DBV work area is assumed.
  2142.  
  2143.  Returns
  2144.  
  2145.     V_ISOPEN() returns (.T.) if there is a file open in the current or
  2146.     specified DBV work area.  Otherwise, it returns (.F.).
  2147.  
  2148.     If a character alias is passed, V_ISOPEN() will return true if the
  2149.     alias is valid in any DBV work area.  If the character alias is
  2150.     not valid for any DBV work area, V_ISOPEN() will return (.F.).
  2151.  
  2152.  Description
  2153.  
  2154.     V_ISOPEN() tests the current or specified area returning a logical
  2155.     (.T.) if a file was found to be open in that area.  This function
  2156.     is important because the behavior of V_SELECT() does not allow
  2157.     this test as SELECT() does in Clipper (see V_SELECT()).
  2158.  
  2159.  Examples
  2160.  
  2161.     V_FILES(5)                    // Set maximum open files to five
  2162.     V_USE( "file1" )              // Open files in areas one and three.
  2163.     V_SELECT(3)
  2164.     V_USE( "file2" )
  2165.  
  2166.     FOR x = 1 TO 5
  2167.        ? V_ISOPEN(x), x           // Results: .T. for x=1 and x=3
  2168.     NEXT
  2169.  
  2170.     IF V_ISOPEN( "bogus" ) .OR. !V_ISOPEN( "file1" )
  2171.        ? "This is unreachable code."
  2172.     ELSE
  2173.        ? "Every thing went as expected!"
  2174.     ENDIF
  2175.  
  2176.  
  2177. See also: V_SELECT(), V_ALIAS(), V_USE()
  2178.  
  2179.  
  2180. ───────────────────────────────────────────────────────────────────────────────
  2181.  V_LEN()
  2182.  Return the length of data stored in a DBV
  2183. ───────────────────────────────────────────────────────────────────────────────
  2184.  
  2185.  Syntax
  2186.  
  2187.      V_LEN(  <cPointer>,
  2188.              <nArea> | <cAlias> )   ->   nCount
  2189.  
  2190.  Arguments
  2191.  
  2192.     <cPointer> is a six byte pointer-field (FlexFile's version of a
  2193.     memo-field).
  2194.  
  2195.     <nArea> or <cAlias> refers to the number or name of the target DBV
  2196.     work area. If not specified, the current DBV work area is assumed.
  2197.  
  2198.  
  2199.  Returns
  2200.  
  2201.     V_LEN() returns the length of a character string or the number of
  2202.     elements in an array as a numeric integer.  V_LEN() returns only
  2203.     the number of elements in the first dimension of a Clipper 5.0
  2204.     array.
  2205.  
  2206.  Description
  2207.  
  2208.     With a character string, V_LEN() returns the number of bytes of
  2209.     the data associated with <cPointer>. This count will include any
  2210.     imbedded null bytes (CHR(0)).
  2211.  
  2212.     With an array, V_LEN() returns the number of elements of the array.
  2213.  
  2214.     For all other data types, V_LEN() returns 0.
  2215.  
  2216.  
  2217.  Examples
  2218.  
  2219.     // Declare and assign two local variables to be used.
  2220.     LOCAL cString, aNames := { "Sandra", "Beth", "Pirko" }
  2221.     cString = "This is a test"
  2222.  
  2223.     // Open a DBF file and its related DBV file
  2224.     USE dbf_file
  2225.     V_USE( "dbv_file" )
  2226.  
  2227.     // Store a string to record 1 and an array to record 2
  2228.     REPLACE vlf WITH V_REPLACE( cString, vlf )
  2229.     SKIP
  2230.     REPLACE vlf WITH V_AREPLACE( aNames, vlf )
  2231.  
  2232.     GO TOP
  2233.     ? V_LEN( vlf )        // Result: 14
  2234.     SKIP
  2235.     ? V_LEN( vlf )        // Result: 3
  2236.     
  2237.  
  2238.  
  2239. See Also: V_TYPE() V_REPLACE() V_RETRIEVE() V_FILLARR()
  2240.  
  2241.  
  2242.  
  2243. ───────────────────────────────────────────────────────────────────────────────
  2244.  V_POKE()
  2245.  Write character data into a character type VLF
  2246. ───────────────────────────────────────────────────────────────────────────────
  2247.  
  2248.  Syntax
  2249.  
  2250.     V_POKE(  <cPointer>,
  2251.              <cData>,
  2252.              [<nOffset>] )
  2253.  
  2254.  Arguments
  2255.  
  2256.     <cPointer> is a six byte pointer-field (FlexFile's version of a
  2257.     memo-field).
  2258.  
  2259.     <cData> is a character string to be written into the data pointed
  2260.     to by <cPointer>.  If the length of <cData> is greater than
  2261.     V_LEN(<cPointer>) - <nOffset>, the data will be trucated.
  2262.  
  2263.     <nOffset> is the offset within the data pointed to by <cPointer>
  2264.     at which to begin writing <cData>.  If not specified, <nOffset>
  2265.     defaults to 1.
  2266.  
  2267.  Returns
  2268.  
  2269.     None.
  2270.  
  2271.  Description
  2272.  
  2273.     V_POKE() is used when you want to overwrite some or all of a
  2274.     character type VLF.  V_POKE() is different than V_STUFF() in that
  2275.     it does not change or return <cPointer>.  Instead, V_POKE()
  2276.     modifies the data directly on the disk at its present location.
  2277.  
  2278.     V_POKE() is different than V_REPLACE() in that it cannot extend
  2279.     the length of the data pointed to by <cPointer> nor can it release
  2280.     any space associated with <cPointer>.
  2281.  
  2282.  Notes
  2283.  
  2284.   ■ V_POKE() is most useful when you know that the new data is the
  2285.     same length (or a subset) of the old data.
  2286.  
  2287.  Examples
  2288.  
  2289.     // Open a DBF and a related DBV file.
  2290.     USE Main.dbf
  2291.     V_USE( "Main.dbv" )
  2292.  
  2293.     // Replace can store any length data.
  2294.     APPEND BLANK
  2295.     REPLACE vlf_fld WITH V_REPLACE( "ABCDEFGH", vlf_fld )
  2296.  
  2297.     // Poke some data into the file.
  2298.     V_POKE( vlf_fld, "test", 3 )
  2299.     ? V_RETRIEVE( vlf_fld )// Result: ABtestGH
  2300.  
  2301.     // Try to write past the end of the fields current length.
  2302.     V_POKE( vlf_fld, "You cannot do much harm", 3 )
  2303.     ? V_RETRIEVE( vlf_fld )// Result: ABYou ca
  2304.  
  2305.  
  2306.  
  2307. See Also: V_REPLACE() V_STUFF()
  2308.  
  2309.  
  2310.  
  2311. ───────────────────────────────────────────────────────────────────────────────
  2312.  V_PTR()
  2313.  Return the absolute offset (file pointer) of data stored in a DBV file
  2314. ───────────────────────────────────────────────────────────────────────────────
  2315.  
  2316.  Syntax
  2317.  
  2318.     V_PTR( <cPointer> )   ->   nOffset
  2319.  
  2320.  Arguments
  2321.  
  2322.     <cPointer> is a six byte pointer-field (FlexFile's version of a
  2323.     memo-field).
  2324.  
  2325.  Returns
  2326.  
  2327.     V_PTR() returns the absolute offset of data pointed to by
  2328.     <cPointer> in the DBV file associated with <cPointer>.
  2329.  
  2330.  Description
  2331.  
  2332.     For those who use Clipper's FOPEN() class of functions and who
  2333.     would like direct access to the data in a DBV type file, FlexFile
  2334.     provides V_PTR(). However, it is far safer to use V_RETRIEVE() and
  2335.     V_POKE().
  2336.  
  2337.     It must be noted that extreme care should be exercised when
  2338.     writing data into the DBV file. You should never write data that
  2339.     begins before V_PTR() or data which extends beyond V_LEN().
  2340.  
  2341.     ┌───────────────────────── WARNING ───────────────────────────┐
  2342.     │ Extreme care must be taken when using FWRITE() on a DBV     │
  2343.     │ type file.  Overwriting the bounds of a VLF by one byte can │
  2344.     │ corrupt the entire file.                                    │
  2345.     └─────────────────────────────────────────────────────────────┘
  2346.  
  2347.  
  2348.  Examples
  2349.  
  2350.     // Open a DBF file and its related DBV file.
  2351.     USE dbf_file
  2352.     V_USE( "dbv_file" )
  2353.  
  2354.     ? V_PTR( vlf )  // Result if the data related to vlf
  2355.                     // is 11,222 bytes from the beginning
  2356.                     // of dbv_file.dbv: 11222
  2357.  
  2358.  
  2359. See Also: V_RETRIEVE() V_POKE()
  2360.  
  2361.  
  2362.  
  2363. ───────────────────────────────────────────────────────────────────────────────
  2364.  V_REPLACE() / V_REP()
  2365.  Replace data stored in a DBV file with new data
  2366. ───────────────────────────────────────────────────────────────────────────────
  2367.  
  2368.  Syntax
  2369.  
  2370.     V_REPLACE(   <exp>,
  2371.                  <cOldPointer>,
  2372.                  [<cAlias> | <nArea>],
  2373.                  [<cDataType>])     ->      cNewPointer
  2374.  
  2375.  Arguments
  2376.  
  2377.     <exp> is any valid clipper variable including single or
  2378.     multi-dimensional arrays, FlexFile arrays, MemoEdit() strings,
  2379.     SaveScreen() strings, any binary data stored in a Clipper
  2380.     variable, as well as numerics, dates, and logicals, and Proclip
  2381.     windows.
  2382.  
  2383.     <cOldPointer> is a required six byte pointer-field or variable in
  2384.     which you have previously stored a pointer to variable length
  2385.     data. Passing six spaces causes FlexFile to assume that there is
  2386.     no old data to be released before the new <exp> data is saved.
  2387.     Refer to the discussion below for further explanation.
  2388.  
  2389.     <cAlias> or <nArea> is a DBV file alias or area specified with
  2390.     V_USE() or V_SELECT(). If omitted, the replace will occur in the
  2391.     current DBV area.
  2392.  
  2393.     <cDataType> is an expression which describes the data type of
  2394.     <exp>. FlexFile will assume Clipper's data type if this parameter
  2395.     is omitted. Only the first character of <cDataType> is significant
  2396.     (e.g. "C" is equivalent to "Character" ).
  2397.  
  2398.     This parameter is almost never necessary in this release of FlexFile.
  2399.     This is because the type of the data being saved is usually
  2400.     non-ambiguous. However, when saving either FlexFile's own strongly
  2401.     typed arrays or Proclip(tm) windows, it is necessary to tell FlexFile
  2402.     what you are saving.
  2403.  
  2404.     This is because FlexFile strongly typed arrays appear to Clipper as
  2405.     character data and Proclip window handles appear to Clipper as numeric
  2406.     values.  So, for example, if you save a Proclip window handle without
  2407.     providing this parameter, FlexFile will save the handle instead of
  2408.     the contents of the window.
  2409.  
  2410.  
  2411.     Table: V_REPLACE() data type codes
  2412.  
  2413.            ┌──────────────────────────────────────────────┐
  2414.            │ Character            Description             │
  2415.            ├──────────────────────────────────────────────┤
  2416.            │     C          Clipper character data        │
  2417.            │     N          Clipper numeric               │
  2418.            │     L          Clipper logical               │
  2419.            │     D          Clipper date                  │
  2420.            │     A          Clipper array                 │
  2421.            │     P          Proclip window handle         │
  2422.            │     F          FlexFile strongly typed array │
  2423.            └──────────────────────────────────────────────┘
  2424.  
  2425.  Returns
  2426.  
  2427.     V_REPLACE() returns a pointer which should be stored in the
  2428.     pointer- field with which the variable length data is to be
  2429.     associated.
  2430.  
  2431.     V_REPLACE() returns (.F.) on error.  This causes the error system
  2432.     to be invoked with a "Data Type Mismatch".  Use V_ERROR() to fetch
  2433.     the specific error value (see Appendix B for a table of error
  2434.     descriptions).
  2435.  
  2436.  Description
  2437.  
  2438.     V_REPLACE() stores the variable length data defined by <exp> and
  2439.     returns a six byte pointer <cNewPointer>. This pointer is the only
  2440.     way FlexFile will ever be able to access the <exp> data; if this
  2441.     pointer is lost the data in the DBV file will be inaccessible.
  2442.  
  2443.     It is highly recommended, therefore, that the V_REPLACE() function
  2444.     be imbedded in the same line of code as the Clipper REPLACE
  2445.     command (see examples below). <cNewPointer> will then be stored
  2446.     directly into a six byte pointer-field in the related DBF file.
  2447.  
  2448.     V_REPLACE() first deletes the data associated with <cOldPointer>
  2449.     freeing up the space, if any, that it was occupying. V_REPLACE()
  2450.     then looks for the smallest available space to put the <exp> new
  2451.     data. Finally, it returns <cNewPointer> to be used at any time by
  2452.     V_RETRIEVE(), V_REPLACE(), V_LEN(), etc. In most cases, you will
  2453.     be storing the <cNewPointer> in a DBF file (highly recommended).
  2454.  
  2455.     In designing the associated DBF structure, you will define a
  2456.     pseudo memo-field which will be a six byte (or more) character
  2457.     type field. FlexFile refers to these fields as pointer-fields.
  2458.     When a FlexFile pointer is stored in this field, the field will
  2459.     have six bytes of ASCII characters from the "irrational" range
  2460.     (128-255). This may appear as "garbage", but is actually a very
  2461.     compact encoded structure. It is encoded only to insure that nulls
  2462.     are never stored in your DBF file. After creating this field you
  2463.     can ignore it exactly as you would a DBT memo-field.
  2464.  
  2465.     The V_REPLACE() function replaces data in the current DBV area or
  2466.     the <nArea>/<cAlias> area if specified. Attempting to use
  2467.     <cOldPointer> which points into one DBV file to delete/replace
  2468.     data in any other DBV file can be dangerous. Although there is a
  2469.     degree of protection against this kind of programmer error, it is
  2470.     possible that random data will be deleted from the target area
  2471.     corrupting that file.
  2472.  
  2473.  
  2474.     Incorrect: <fld1> is pointing to data in DBV area 1 but being used
  2475.     to refer to data in DBV area 2.
  2476.  
  2477.     V_SELECT(1)
  2478.     REPLACE fld1 WITH V_REPLACE( "No problem yet", fld1 )
  2479.           │
  2480.           └─────────────────────────────────────────────────┐
  2481.     V_SELECT(2)                                             │
  2482.     REPLACE fld1 WITH V_REPLACE( "File corruption possible", fld1)
  2483.  
  2484.  
  2485.     Correct: <fld1> is being used consistently in DBV area 1.
  2486.  
  2487.     V_SELECT(1)
  2488.     REPLACE fld1 WITH V_REPLACE( "Much better", fld1 )
  2489.           └──────────────────────────────┐
  2490.                                          │
  2491.     REPLACE fld1 WITH V_REPLACE( "Best", fld1 )
  2492.  
  2493.  
  2494.  
  2495.     ┌────────────────────────── WARNING ──────────────────────────┐
  2496.     │ V_REPLACE() deletes the data associated with <cOldPointer>  │
  2497.     │ before returning <cNewPointer>.  Attempting to use          │
  2498.     │ <cOldPointer> after this function deletes the data that it  │
  2499.     │ points to can corrupt the DBV file.                         │
  2500.     └─────────────────────────────────────────────────────────────┘
  2501.  
  2502.  Notes
  2503.  
  2504.   ■ All file sharing within the DBV file is handled automatically.
  2505.     It is the programmers responsibility to handle any one
  2506.     pointer-field exactly as you would any DBF field (i.e. use
  2507.     Clippers FLOCK()/RLOCK() functions). If a record is successfully
  2508.     locked with Clippers RLOCK() function, the pointer-field will be
  2509.     inaccessible to other users until the current task releases it.
  2510.  
  2511.   ■ If you use comparison of data in your networking code you are
  2512.     guaranteed that the pointer stored in the DBF field will be
  2513.     different after a replace even if the <cNewPointer> points to the
  2514.     same disk location as <cOldPointer>. It is, therefore, not
  2515.     necessary to compare the data itself (to see if it has been
  2516.     changed by one user while another user is working with it), but
  2517.     rather, it suffices to compare the pointers themselves.
  2518.  
  2519.   ■ V_REPLACE( "", vlf ) is not equivalent to V_DELETE( vlf ). In
  2520.     the first case, an entry will still exist in the DBV file and
  2521.     V_REPLACE() will return a valid pointer.  This entry will hold the
  2522.     type of the data and the length of the data. In the second case,
  2523.     the entry is removed from the file. Because FlexFile de-fragments
  2524.     the file as it deletes old data, the second method is preferred
  2525.     when you no longer need the data.
  2526.  
  2527.  Examples
  2528.  
  2529.     // Example 1: exclusive
  2530.     // Assume the DBF file is indexed on the field scr_name
  2531.     // Assume the DBF file has a pointer-field scr_vlf.
  2532.     LOCAL cScr
  2533.  
  2534.     // Open a DBF, an NTX and a related DBV file
  2535.     USE dbf_file INDEX dbf_file
  2536.     V_USE( "dbv_file" )
  2537.  
  2538.     // Save a screen segment to a variable.
  2539.     cScr = SAVESCREEN( 5, 5, 10, 50 )
  2540.  
  2541.     // Make a name for the screen and append the screen to
  2542.     // the dbv_file.dbv.
  2543.     APPEND BLANK
  2544.     REPLACE scr_name WITH "main_menu"
  2545.     REPLACE scr_vlf WITH V_REPLACE( cScr, scr_vlf )
  2546.  
  2547.     // Later, restore the screen segment.
  2548.     CLEAR
  2549.     SEEK "main_menu"
  2550.     RESTSCREEN( 5, 5, 10, 50, V_RETRIEVE( scr_vlf ) )
  2551.  
  2552.  
  2553.     Network example on next page.
  2554.     // Example 2: Network example
  2555.     // Assume the file has a pointer-field memo_vlf
  2556.     LOCAL ptr, cStr
  2557.  
  2558.     // Set exclusive off for Clipper and FlexFile.
  2559.     SET EXCLUSIVE OFF
  2560.     V_EXCLUSIV( .F. )
  2561.  
  2562.     // Open the files
  2563.     USE dbf_file INDEX dbf_file
  2564.     IF V_USE( "dbv_file" ) == -1
  2565.        ? "File not available at this time."
  2566.        QUIT
  2567.     ENDIF
  2568.  
  2569.     // Make up some data; append it to the files.
  2570.     APPEND BLANK
  2571.     WHILE NETERR()
  2572.        APPEND BLANK
  2573.     ENDDO
  2574.  
  2575.     // Lock the record an put some test data in the vlf.
  2576.     WHILE !RLOCK()
  2577.     ENDDO
  2578.     REPLACE dbf_file->memo_vlf WITH V_REPLACE( "Testing",
  2579.                              dbf_file->memo_vlf )
  2580.     UNLOCK
  2581.  
  2582.     // Remember the pointer for an "updated" test (see below).
  2583.     ptr = memo_vlf
  2584.  
  2585.     // Edit the existing data.  Note: the file is not locked.
  2586.     cStr = MEMOEDIT( V_RETRIEVE( memo_vlf ), 5, 5, 20, 50 )
  2587.  
  2588.     // Lock the record before the replace.
  2589.     WHILE !RLOCK()
  2590.     ENDDO
  2591.  
  2592.     // Test for an update between when we assigned memo_vlf to
  2593.     // ptr and now.
  2594.     IF ptr != dbf_file->memo_vlf
  2595.        ? "This memo field has been updated by another user."
  2596.        ? "It cannot be saved."
  2597.     ELSE
  2598.        REPLACE memo_vlf WITH V_REPLACE( cStr, memo_vlf )
  2599.     ENDIF
  2600.  
  2601.     UNLOCK
  2602.  
  2603.     // Close the files.
  2604.     USE
  2605.     V_USE()
  2606.  
  2607.  
  2608. See Also: V_USE() V_RETRIEVE() V_POKE() V_AREPLACE()
  2609.  
  2610.  
  2611.  
  2612. ───────────────────────────────────────────────────────────────────────────────
  2613.  V_AREPLACE() / V_AREP()
  2614.  Replace a VLF with a Clipper 5.0 type array
  2615. ───────────────────────────────────────────────────────────────────────────────
  2616.  
  2617.          Use V_REPLACE() with S'87 arrays
  2618.  
  2619.  Syntax
  2620.  
  2621.     V_AREPLACE(   <aTarget>,
  2622.                   <cOldPointer>,
  2623.                   [<cAlias> | <nArea>] )   ->   cNewPointer
  2624.  
  2625.  Arguments
  2626.  
  2627.     <aTarget> is any valid Clipper 5.0 array.  The array may
  2628.     contain nested arrays (i.e. multi-dimensional) which will be saved
  2629.     as well.
  2630.  
  2631.     <cOldPointer> is a required six byte pointer-field or variable in
  2632.     which you have previously stored a pointer to variable length
  2633.     data. Passing six spaces causes FlexFile to assume that there is
  2634.     no old data to be released before the new <aTarget> data is saved.
  2635.     Refer to the discussion below for further explanation.
  2636.  
  2637.     <cAlias> or <nArea> is a DBV file alias or area specified with
  2638.     V_USE() or V_SELECT(). If omitted, the replace will occur in the
  2639.     current DBV area.
  2640.  
  2641.  Returns
  2642.  
  2643.     V_AREPLACE() returns a pointer which should be stored in the
  2644.     pointer-field with which the array is to be associated.
  2645.  
  2646.     V_AREPLACE() returns (.F.) on error.  This causes the error system
  2647.     to be invoked with a "Data Type Mismatch".  Use V_ERROR() to fetch
  2648.     the specific error value (see Appendix B for a table of error
  2649.     descriptions).
  2650.  
  2651.  Description
  2652.  
  2653.     V_AREPLACE() stores the array defined by <aTarget> and returns a
  2654.     six byte pointer <cNewPointer>. This pointer is the only way
  2655.     FlexFile will ever be able to access the <aTarget> data; if this
  2656.     pointer is lost the array in the DBV file will be inaccessible.
  2657.  
  2658.     It is highly recommended, therefore, that the V_AREPLACE() function
  2659.     be imbedded in the same line of code as the Clipper REPLACE
  2660.     command (see examples below). <cNewPointer> will then be stored
  2661.     directly into a six byte pointer-field in the related DBF file.
  2662.  
  2663.     V_AREPLACE() first deletes the data associated with <cOldPointer>
  2664.     freeing up the space, if any, that it was occupying. V_AREPLACE()
  2665.     then looks for the smallest available space to put the
  2666.     <aTarget> array. Finally, it returns <cNewPointer> to be
  2667.     used at any time by V_ARETRIEV() or V_AREPLACE(). In most cases,
  2668.     you will be storing the <cNewPointer> in a DBF file (highly
  2669.     recommended).
  2670.  
  2671.     In designing the associated DBF structure, you will define a
  2672.     pseudo memo-field which will be a six byte (or more) character
  2673.     type field. FlexFile refers to these fields as pointer-fields.
  2674.     When a FlexFile pointer is stored in this field, the field will
  2675.     have six bytes of ASCII characters from the "irrational" range
  2676.     (128-255). This may appear as "garbage", but is actually a very
  2677.     compact encoded structure. It is encoded only to insure that nulls
  2678.     are never stored in your DBF file. After creating this field you
  2679.     can ignore it exactly as you would a DBT memo-field.
  2680.  
  2681.     The V_AREPLACE() function replaces data in the current DBV area or
  2682.     the <nArea>/<cAlias> area if specified. Attempting to use
  2683.     <cOldPointer> which points into one DBV file to delete/replace
  2684.     data in any other DBV file can be dangerous. Although there is a
  2685.     degree of protection against this kind of programmer error, it is
  2686.     possible that random data will be deleted from the target area
  2687.     corrupting that file.
  2688.  
  2689.     ┌────────────────────────── WARNING ──────────────────────────┐
  2690.     │ V_AREPLACE() deletes the data associated with <cOldPointer> │
  2691.     │ before returning <cNewPointer>.  Attempting to use          │
  2692.     │ <cOldPointer> after this function deletes the data that it  │
  2693.     │ points to can corrupt the DBV file.                         │
  2694.     └─────────────────────────────────────────────────────────────┘
  2695.  
  2696.  Examples
  2697.  
  2698.     LOCAL ray
  2699.  
  2700.     // Open the DBF file and its associated DBV file
  2701.     USE dbf_file         // Has a 6 byte pointer-field: vlf.
  2702.     V_USE( "dbv_file" )  // Is created if it does not exist.
  2703.  
  2704.     ray = array( 20 )    // Declare a Clipper 5.0 array
  2705.  
  2706.     afill( ray, "junk" ) // Fill the array with some junk.
  2707.  
  2708.     ray[10] = array(25)  // Nest an array within the first array
  2709.  
  2710.     // Put some variable type data in the nested array
  2711.     ray[10][1] = 1
  2712.     ray[10][2] = .t.
  2713.     ray[10][3] = 5.56
  2714.     ray[10][4] = date()
  2715.     ray[10][8] = "check it out"
  2716.  
  2717.     // Store the array in DBV file and its pointer in
  2718.     // the DBF.
  2719.     APPEND BLANK
  2720.     REPLACE vlf WITH V_AREPLACE( ray, vlf )
  2721.  
  2722.  
  2723.  
  2724. See Also: V_USE() V_ARETRIEV()
  2725.  
  2726.  
  2727.  
  2728. ───────────────────────────────────────────────────────────────────────────────
  2729.  V_RETRIEVE() / V_RET()
  2730.  Return data that has been stored in a DBV file
  2731. ───────────────────────────────────────────────────────────────────────────────
  2732.  
  2733.  Syntax
  2734.  
  2735.     V_RETRIEVE(  <cPointer>,
  2736.                  [<nArea> | <cAlias>],
  2737.                  [<nStart>],
  2738.                  [<nCount>] )    ->    Data
  2739.  
  2740.  Arguments
  2741.  
  2742.     <cPointer> is a six byte pointer-field (FlexFile's version of a
  2743.     memo-field).
  2744.  
  2745.     <nArea> or <cAlias> refers to the number or name of the target DBV
  2746.     work area. If not specified, the current DBV work area is assumed.
  2747.  
  2748.     <nStart> is the starting position in <cPointer>'s data. If
  2749.     <nStart> is positive, it counts from the beginning of the data
  2750.     pointed to by <cPointer>. If <nStart> is negative, it counts from
  2751.     the end of the data pointed to by <cPointer>.
  2752.  
  2753.     <nCount> is how many bytes of data to retrieve. If omitted,
  2754.     <nCount> begins at <nStart> and goes to the end of the data. If
  2755.     <nCount> is larger than the data, the excess is ignored.
  2756.  
  2757.  Returns
  2758.  
  2759.     V_RETRIEVE() will return the data pointed to by <cPointer>. On
  2760.     error, V_RETRIEVE() will return an empty value of the type stored
  2761.     or a logical (.F.) if no type can be determined. Use V_ERROR() to
  2762.     fetch the error code associated with a failed RETRIEVE().
  2763.  
  2764.  Description
  2765.  
  2766.     V_RETRIEVE() retrieves data stored in a DBV type file. The data
  2767.     retrieved will have the same type as the data that was stored
  2768.     during the V_REPLACE() (with the notable exception of Clipper
  2769.     arrays which are discussed below and Proclip windows which use the
  2770.     V_WNDCREAT() function).
  2771.  
  2772.  Notes
  2773.   ■ Clipper arrays stored using the V_REPLACE() or V_AREPLACE()
  2774.     functions cannot be retrieved with V_RETRIEVE(). Instead, use
  2775.     V_FILLARR() for Summer 87 type arrays and V_ARETRIEV() for
  2776.     Clipper 5.0 arrays.
  2777.  
  2778.   ■ <nStart> and <nCount> only apply to character data.  They will
  2779.     be ignored for any other data types.
  2780.  
  2781.   ■ If a numeric value was stored to a VLF (directly or as part of an
  2782.     array), the value returned will be equivalent to the value stored, but
  2783.     if you display the value without a PICTURE clause, it will show the
  2784.     number of decimals according to the value of SET DECIMAL TO (which is
  2785.     not necesarily the same number of decimals that were visable when the
  2786.     value that was saved).
  2787.  
  2788.  
  2789.  Examples
  2790.  
  2791.     // Open the DBF file and its associated DBV file
  2792.     #define CR_LF  ( CHR(13) + CHR(10) )
  2793.     LOCAL cStr
  2794.     USE dbf_file       // Has a 6 byte pointer-field: vlf.
  2795.     V_USE( "dbv_file" )// Is created if it does not exist.
  2796.  
  2797.     cStr ="And the silken, sad, uncertain,"+ CR_LF +;
  2798.           "rustling of each purple curtain,"+ CR_LF +;
  2799.           "thrilled me, filled me,"       + CR_LF +;
  2800.           "with fantastic terrors never felt before."
  2801.  
  2802.     // Store the string in DBV file and its pointer in
  2803.     // the DBF.
  2804.     APPEND BLANK
  2805.     REPLACE author WITH "Poe"
  2806.     REPLACE poem WITH "The Raven"
  2807.     REPLACE vlf WITH V_REPLACE( cStr, vlf )
  2808.  
  2809.     // Edit the string using V_RETRIEVE().
  2810.     cStr = MEMOEDIT( V_RETRIEVE( vlf ), 0, 0, 10, 45 )
  2811.  
  2812.     // Save the edited poem.
  2813.     REPLACE vlf WITH V_REPLACE( cStr, vlf )
  2814.  
  2815.  
  2816.  
  2817. See Also: V_FILLARR() V_REPLACE() V_STUFF() V_LEN()
  2818.  
  2819.  
  2820.  
  2821. ───────────────────────────────────────────────────────────────────────────────
  2822.  V_ARETRIEV() / V_ARET()
  2823.  Return a Clipper 5.0 type array which was stored in a DBV file
  2824. ───────────────────────────────────────────────────────────────────────────────
  2825.  
  2826.     See V_FILLARR() and V_FILLEN() for retrieving arrays that were
  2827.     stored by an earlier version of the S'87 FlexFile library.
  2828.  
  2829.  Syntax
  2830.  
  2831.     V_ARETRIEV(  <cPointer>, [<nArea> | <cAlias>] )  ->  Array
  2832.  
  2833.  Arguments
  2834.  
  2835.     <cPointer> is a six byte pointer-field (FlexFile's version of a
  2836.     memo-field).
  2837.  
  2838.     <nArea> or <cAlias> refers to the number or name of the target DBV
  2839.     work area. If not specified, the current DBV work area is assumed.
  2840.  
  2841.  Returns
  2842.  
  2843.     V_ARETRIEV() will return the array pointed to by <cPointer>. On
  2844.     error, V_ARETRIEV() will return (.F.).  Use V_ERROR() to fetch the
  2845.     error code associated with a failed V_ARETRIEV().
  2846.  
  2847.  Description
  2848.  
  2849.     V_ARETRIEV() retrieves Clipper 5.0 type arrays stored in a DBV
  2850.     file. It works on the same principal as the V_RETRIEVE() function.
  2851.     The function retrieves the array and all nested arrays as they
  2852.     were saved by V_AREPLACE().
  2853.  
  2854.  Notes
  2855.  
  2856.     If you have a DBV file which contains an array which was saved by
  2857.     FlexFile S'87 version 1.01 or less, you must use the V_FILLARR()
  2858.     function to convert the array to one compatible with this function.
  2859.  
  2860.     All arrays stored with FlexFile's S87 version 1.02 or greater (and,
  2861.     of course, any arrays stored with FlexFile's 5.0 versions) are
  2862.     compatible with this function.
  2863.  
  2864.  Examples
  2865.  
  2866.     LOCAL ray
  2867.  
  2868.     // Open the DBF file and its associated DBV file.
  2869.     // Assume the array stored in the V_AREPLACE() example.
  2870.     USE dbf_file         // Has a 6 byte pointer-field: vlf.
  2871.     V_USE( "dbv_file" )  // Already contains a stored array
  2872.  
  2873.     // Retrieve the array (and its nested array).
  2874.     ray = V_ARETRIEV( vlf )
  2875.  
  2876. See Also: V_AREPLACE()
  2877.  
  2878.  
  2879.  
  2880. ───────────────────────────────────────────────────────────────────────────────
  2881.  V_SELECT()
  2882.  Determine or select the DBV work area of a specified DBV alias
  2883. ───────────────────────────────────────────────────────────────────────────────
  2884.  
  2885.     V_SELECT( [<nNewArea>] | [<cAlias>] )      nOldArea
  2886.  
  2887.  Arguments
  2888.  
  2889.     <nNewArea> or <cAlias> is the new DBV area (or the new area associated
  2890.     with <cAlias>).
  2891.  
  2892.  Returns
  2893.  
  2894.     V_SELECT() returns the old area if the area is successfully
  2895.     changed or if no parameters are passed. On error (i.e. an area
  2896.     beyond the bounds of the V_FILES() setting), V_SELECT() will
  2897.     return a 0 and the DBV area will remain unchanged.
  2898.  
  2899.  Description
  2900.  
  2901.     V_SELECT() provides the functionality of a combination of
  2902.     Clipper's SELECT command and SELECT() function.  Specifically, it
  2903.     is used to change and/or fetch the active DBV work area.
  2904.  
  2905.     If no parameters are passed V_SELECT() parallels the Clipper
  2906.     SELECT() by returning the current DBV area. If, however, a valid
  2907.     DBV area or alias is passed, V_SELECT() will change the current
  2908.     DBV area as Clipper's SELECT command would and then returns the
  2909.     old DBV area as Clipper's SELECT() function would.  This
  2910.     functionality is slightly different than Clipper's SELECT() which
  2911.     returns the area of the alias but does not actually change the
  2912.     selected area.  If you need to test for the existance of an open
  2913.     file in a DBV work area, use the V_ISOPEN() function.
  2914.  
  2915.     V_SELECT() always returns a DBV area number regardless of whether
  2916.     the parameter passed was an alias or an area.
  2917.  
  2918.  Notes
  2919.  
  2920.   ■ Do not confuse Clipper's selected work area with FlexFile's;
  2921.     they are mutually exclusive. For example, you can have a DBF file
  2922.     open in area 2 and simultaneously have a DBV file open in
  2923.     V_SELECT() == 2. Likewise, SELECT <n> has no effect on the
  2924.     currently selected DBV area.
  2925.  
  2926.   ■ Remember that your maximum number of open files must be set by
  2927.     the V_FILES() function before V_USE()in your first DBV file. The
  2928.     valid DBV areas will then be from 1 to the value you passed to
  2929.     V_FILES(). See V_FILES() for more on defining the maximum number
  2930.     of work areas.
  2931.  
  2932.  Examples
  2933.  
  2934.     // Open three DBV files in three new areas.
  2935.     LOCAL nSelect
  2936.  
  2937.     nSelect = V_SELECT(1)    // Save current area and
  2938.                              // select area 1
  2939.     V_USE( "file1", "file_one" )// Creates if not existing
  2940.     V_SELECT(2)
  2941.     V_USE( "file2" )
  2942.     V_SELECT(0)              // Select the next area
  2943.     V_USE( "file3" )
  2944.     
  2945.     ? V_ALIAS()              //  Returns: FILE3
  2946.     ? V_ALIAS(1)             //  Returns: FILE_ONE
  2947.  
  2948.     V_SELECT( nSelect )      // Restore the first area.
  2949.  
  2950.  
  2951. See Also: V_ALIAS() V_USE() V_ISOPEN() V_FILES()
  2952.  
  2953.  
  2954. ───────────────────────────────────────────────────────────────────────────────
  2955.  V_SET_COMMIT()
  2956.  Set DOS buffer flushing automatically on/off
  2957. ───────────────────────────────────────────────────────────────────────────────
  2958.  Syntax
  2959.  
  2960.     V_SET_COMMIT( [<lToggle>] )   ->   lOldSetting
  2961.  
  2962.  Arguments
  2963.  
  2964.     <lToggle> is a logical expression which, if true, will turn on
  2965.     automatic buffer flushing.  If false,  it will turn off automatic
  2966.     buffer flushing.  If omitted, no change will be made and the
  2967.     function can be used simply to query the current setting.
  2968.  
  2969.  Returns
  2970.  
  2971.     V_SET_COMMIT() returns the old setting of the switch.
  2972.  
  2973.  Description
  2974.  
  2975.     DOS "buffers" disk I/O in order to speed up disk access.  The
  2976.     downside to this feature is that the data in the buffers can be
  2977.     lost if the machine "hangs" or is powered down before the buffers
  2978.     are copied to disk.  This problem was addressed in DOS version 3.3
  2979.     and later by allowing a call which forces DOS's buffers to be
  2980.     written to disk.  V_SET_COMMIT() sets DOS buffer flushing on
  2981.     automatic if a logical (.T.) is passed or turns off the automatic
  2982.     buffer flushing if a logical (.F.) is passed.  In the latter case,
  2983.     use V_COMMIT() to flush buffers manually.
  2984.  
  2985.         ┌──────────────────────── WARNING ─────────────────────────┐
  2986.         │ V_COMMIT and V_SET_COMMIT() are based on functions       │
  2987.         │ provided in DOS 3.3 and later.  Calls made to these      │
  2988.         │ functions on an earlier version of DOS will have no      │
  2989.         │ affect.                                                  │
  2990.         └──────────────────────────────────────────────────────────┘
  2991.  
  2992.  
  2993.  Example
  2994.  
  2995.     // Turn off automatic flushing in order to speed up operation.
  2996.     V_USE( "temp" )
  2997.     V_SET_COMMIT(.f.)
  2998.  
  2999.     DO WHILE !EOF()
  3000.        IF DELETED()
  3001.           REPLACE vlf_fld WITH V_DELETE( vlf_fld )
  3002.        ENDIF
  3003.        SKIP
  3004.     ENDDO
  3005.     PACK
  3006.  
  3007.     // Flush the buffers and turn automatic flushing back on.
  3008.     V_COMMIT()
  3009.     V_SET_COMMIT(.T.)
  3010.  
  3011.  
  3012. See also: V_COMMIT()
  3013.  
  3014.  
  3015. ───────────────────────────────────────────────────────────────────────────────
  3016.  V_SETKEY()
  3017.  Set a key or password for FlexFile encryption
  3018. ───────────────────────────────────────────────────────────────────────────────
  3019.  
  3020.  Syntax
  3021.  
  3022.     V_SETKEY( <cPassWord> )   ->    NIL
  3023.  
  3024.  Arguments
  3025.  
  3026.     <cPassWord> is any ten character string.  It must be at least one
  3027.     character and will be truncated to 10 if more characters are supplied.
  3028.  
  3029.  Returns
  3030.  
  3031.     NIL
  3032.  
  3033.  Description
  3034.  
  3035.     V_SETKEY() affects the return values of V_ENCRYPT() and V_DECRYPT().
  3036.     Essentially, <cPassWord> is a password that is used to encrypt a string
  3037.     and must be the same in order to decrypt the string.  Once set, the
  3038.     <cPassWord> is stored statically in memory.
  3039.  
  3040.     So, for example, you can set a password when your user starts a system
  3041.     (and enters his/her password) and use that password for the remainder
  3042.     of the session.  All strings V_ENCRYPT()ed with a particular
  3043.     <cPassWord> can only be V_DECRYPT()ed by using the same <cPassWord>.
  3044.  
  3045.  Examples
  3046.  
  3047.     LOCAL cSecure, cOriginal, cJunk
  3048.  
  3049.     // Set the key to my dog's name.
  3050.     V_SETKEY( "Tally" )
  3051.  
  3052.     // Encrypt a character string.  Store the result in <cSecure>.
  3053.     cSecure = V_ENCRYPT( "Just try to decode <cSecure> without my dog." )
  3054.  
  3055.     // Later, decode the secured string with the help of my golden.
  3056.     // Note that the <cPassWord> is being changed.
  3057.     V_SETKEY( "Junk" )
  3058.  
  3059.     // Because the <cPassWord> has been changed, the resulting string
  3060.     // will be unreadable.
  3061.     cJunk = V_DECRYPT( cSecure )
  3062.  
  3063.     // Now we change the <cPassWord> back to what was used during
  3064.     // the V_ENCRYPT()ion and the string will be properly restored.
  3065.     V_SETKEY( "Tally" )
  3066.     cOriginal = V_DECRYPT( cSecure )
  3067.  
  3068.  
  3069. See Also: V_ENCRYPT() V_DECRYPT()
  3070.  
  3071.  
  3072.  
  3073. ───────────────────────────────────────────────────────────────────────────────
  3074.  V_STUFF()
  3075.  Delete and insert new data into an existing VLF
  3076. ───────────────────────────────────────────────────────────────────────────────
  3077.  
  3078.  Syntax
  3079.  
  3080.     V_STUFF( <cOldPointer>,
  3081.              <nStart>,
  3082.              <nDelete>,
  3083.              <cNewString> )    ->    cNewPointer
  3084.  
  3085.  Arguments
  3086.  
  3087.     <cOldPointer> Is the pointer (usually stored in a DBF field),
  3088.     which points to the source string into which <cNewString> will be
  3089.     V_STUFF()ed.
  3090.  
  3091.     <nStart> is the starting position in the VLF where <cNewString>
  3092.     will be inserted.
  3093.  
  3094.     <nDelete> is the number of characters to delete from <cNewString>
  3095.     starting at <nStart>. Deletions are performed before insertions.
  3096.  
  3097.     <cNewString> is a string which will be inserted at the <nStart>
  3098.     position after the deletion of <nDelete> characters.
  3099.  
  3100.  Returns
  3101.  
  3102.     V_STUFF() returns a pointer which should be stored in the field
  3103.     with which the modified variable length data is to be associated.
  3104.  
  3105.     V_STUFF() returns (.F.) on error.  This causes the error system to
  3106.     be invoked with a "Data Type Mismatch".  Use V_ERROR() to fetch
  3107.     the specific error value (see Appendix B for a table of error
  3108.     descriptions).
  3109.  
  3110.  Description
  3111.  
  3112.     The V_STUFF() function works on VLFs much as Clipper's STUFF()
  3113.     works on strings. Working on VLFs, V_STUFF() will delete <nDelete>
  3114.     characters from the string pointed to by <cOldPointer> and then
  3115.     insert <cNewString> at the <nStart> position. V_STUFF() can,
  3116.     therefore, perform the following seven functions:
  3117.  
  3118.   ■ Insert: If <nDelete> is zero, V_STUFF() will not delete any
  3119.     characters before inserting <cNewString> at the <nStart> position.
  3120.     This effectively makes V_STUFF() an insert function.
  3121.  
  3122.   ■ Replace: If <nDelete> equals LEN( <cNewString> ), then
  3123.     V_STUFF() will effectively replace the data beginning at the
  3124.     <nStart> position. If the <cNewString> is always the same length
  3125.     as <nDelete> or if the comparison for equivalent length is easily
  3126.     tested, it is faster (less disk I/O) to use V_POKE().
  3127.  
  3128.   ■ Delete: If LEN( <cNewString> ) == 0 or <cNewString> is not
  3129.     passed, V_STUFF() will effectively delete <nDelete> characters
  3130.     beginning at the <nStart> position.
  3131.  
  3132.   ■ Replace and Insert: If <cNewString> is longer than <nDelete>,
  3133.     V_STUFF() will replace <nDelete> characters of the data pointed to
  3134.     by <cOldPointer> and insert the remaining length of <cNewString>.
  3135.  
  3136.   ■ Replace and Delete: If <cNewString> is shorter than <nDelete>,
  3137.     V_STUFF() will replace <nDelete> characters of the data pointed to
  3138.     by <cOldPointer> and then delete the remaining <nDelete>
  3139.     characters making the data shorter.
  3140.  
  3141.   ■ Replace and Delete rest: If <nDelete> is greater than or equal
  3142.     to the number of characters remaining after the <nStart> position
  3143.     of the data pointed to by <cOldPointer>, the old data is
  3144.     effectively trimmed at the <nStart> position before the
  3145.     <cNewString> is inserted.
  3146.  
  3147.   ■ Append: If <nStart> is equal to or greater than the length of
  3148.     the data pointed to by <cOldPointer>, the <nDelete> parameter is
  3149.     ignored and the <cNewString> data is appended to the end.
  3150.  
  3151.     ┌────────────────────────── WARNING ──────────────────────────┐
  3152.     │ V_STUFF() deletes the data associated with <cOldPointer>    │
  3153.     │ before returning <cNewPointer>.  Attempting to use          │
  3154.     │ <cOldPointer> after this function deletes the data that it  │
  3155.     │ points to can corrupt the DBV file.                         │
  3156.     └─────────────────────────────────────────────────────────────┘
  3157.  
  3158.  Notes
  3159.  
  3160.     The big advantage to V_STUFF() is that its operation is disk based
  3161.     rather than memory based. This is, however, a double edged sword.
  3162.     On the one hand, it offers the ability to create a VLF that is
  3163.     larger than 65K (Clipper's largest character string size). On the
  3164.     other hand, if you are not aware that <cNewPointer> points to data
  3165.     that is larger than 65K, you may be surprised when V_RETRIEVE() or
  3166.     similar functions trim their return value to 65K.  Although
  3167.     V_RETRIEVE() can only return a maximum length of 65K, it can pick
  3168.     up any portion of a longer string as long as the portion itself is
  3169.     no longer than 65K (see V_REPLACE()).
  3170.  
  3171.     In all cases, V_STUFF() will move the data pointed to by
  3172.     <cOldPointer> to a new location in the DBV file. It is, therefore,
  3173.     less disk intensive to use V_POKE() where possible. V_POKE() does
  3174.     not delete or insert, but simply overwrites data leaving it at the
  3175.     same disk location within the DBV file.
  3176.  
  3177.  Examples
  3178.  
  3179.     // Open a DBF file and its associated DBV file.
  3180.     USE dbf_file
  3181.     V_USE( "dbv_file" )
  3182.  
  3183.     // Put a string away.
  3184.     cStr = "ABCDEF"
  3185.     REPLACE vlf WITH V_REPLACE( cStr, vlf )
  3186.  
  3187.     // Insert.
  3188.     REPLACE vlf WITH V_STUFF( vlf, 2, 0, 'xyz' )
  3189.     ? V_RETRIEVE( vlf )      // Result: AxyzBCDEF
  3190.  
  3191.     // Replace.
  3192.     REPLACE vlf WITH V_STUFF( vlf, 2, 3, 'qrs' )
  3193.     ? V_RETRIEVE( vlf )      // Result: AqrsBCDEF
  3194.  
  3195.     // Delete.
  3196.     REPLACE vlf WITH V_STUFF( vlf, 2, 3, '' )
  3197.     ? V_RETRIEVE( vlf )      // Result: ABCDEF
  3198.  
  3199.     // Replace and Insert.
  3200.     REPLACE vlf WITH V_STUFF( vlf, 2, 2, 'xyz' )
  3201.     ? V_RETRIEVE( vlf )      // Result: AxyzDEF
  3202.  
  3203.     // Replace and delete.
  3204.     REPLACE vlf WITH V_STUFF( vlf, 2, 4, 'qrs' )
  3205.     ? V_RETRIEVE( vlf )      // Result: AqrsEF
  3206.  
  3207.     // Replace and delete rest.
  3208.     REPLACE vlf WITH V_STUFF( vlf, 2, 10, 'xyz' )
  3209.     ? V_RETRIEVE( vlf )      // Result: Axyz
  3210.  
  3211.     // Append.
  3212.     REPLACE vlf WITH V_STUFF( vlf, 10, 0, 'qrs' )
  3213.     ? V_RETRIEVE( vlf )      // Result: Axyzqrs
  3214.  
  3215. See Also: V_POKE() V_REPLACE() V_LEN() V_MEMOLINE()
  3216.  
  3217.  
  3218.  
  3219. ───────────────────────────────────────────────────────────────────────────────
  3220.  V_TIMEOUT()
  3221.  Advanced feature allows setting the internal lock timeout value
  3222. ───────────────────────────────────────────────────────────────────────────────
  3223.  
  3224.  Syntax
  3225.  
  3226.     V_TIMEOUT( [<nTimeOut>] )    ->    nOldSetting
  3227.  
  3228.  Arguments
  3229.  
  3230.     <nTimeOut> is the time interval (in seconds) before FlexFile will
  3231.     abort a function that is attempting an internal lock. The default
  3232.     value is forever.
  3233.  
  3234.  Returns
  3235.  
  3236.     V_TIMEOUT() returns the current timeout value.
  3237.  
  3238.  Description
  3239.  
  3240.     V_TIMEOUT() should not usually be necessary. If you are using
  3241.     Clipper's RLOCK() and FLOCK() functions to manage the DBF file,
  3242.     and you are keeping FlexFile's pointers in the DBF (this is the
  3243.     preferred method), then this function is not necessary.
  3244.  
  3245.     If you want FlexFile to timeout during an operation, then use this
  3246.     function to set the timeout value in seconds. Passing zero as
  3247.     <nTimeOut> will set the timeout value back to its default
  3248.     (forever).
  3249.  
  3250.     If you set the timeout to something other than zero, you must test
  3251.     the error code following a call to any of the FlexFile functions
  3252.     in the table below. The test is made by comparing V_ERROR() to
  3253.     zero or 5200. If the operation's lock timed out, V_ERROR() will
  3254.     return 5200, if the operation was successful, V_ERROR() will
  3255.     return zero. (See the example below.)
  3256.  
  3257.     Functions affected by V_TIMEOUT(): V_DELETE(), V_FILE2DBV(),
  3258.     V_REPLACE(), V_STUFF(), V_DBV2FILE()
  3259.  
  3260.  Examples
  3261.  
  3262.     // Setup defines and variables
  3263.     #define EXCLUSIVE_ (.T.)
  3264.     LOCAL error_no
  3265.  
  3266.     // Set the timeout to 3 seconds.
  3267.     V_TIMEOUT(3)
  3268.  
  3269.     // Open a DBF file and its related DBV file.
  3270.     USE dbf_file
  3271.     IF V_USE( "dbv_file", , , !EXCLUSIVE_ ) == -1
  3272.        error_no = V_ERROR()
  3273.        IF error_no == 5200
  3274.           ? "Attempt to lock header failed after 3 seconds"
  3275.           RETURN .F.
  3276.        ELSE
  3277.           ? "Error: " + str( error_no, 4 )
  3278.           RETURN .F.
  3279.        ENDIF
  3280.     ENDIF
  3281.  
  3282.  
  3283.  
  3284. See Also: V_USE() V_REPLACE()
  3285.  
  3286. ───────────────────────────────────────────────────────────────────────────────
  3287.  V_TOPPTR()
  3288.  Read/Replace FlexFile data without a DBF file.
  3289. ───────────────────────────────────────────────────────────────────────────────
  3290.  
  3291.  Syntax
  3292.  
  3293.     V_TOPPTR( [<cPointer>], [<cAlias> | <nArea>] )
  3294.  
  3295.  Arguments
  3296.  
  3297.     <cPointer> (optional) is the six byte character string returned by
  3298.     either V_REPLACE() or V_AREPLACE().  If not specified, V_TOPPTR() will
  3299.     return the current pointer stored in the header of the DBV file (see
  3300.     discussion below).
  3301.  
  3302.     <cAlias> or <nArea> is a DBV file alias or area specified with
  3303.     V_USE() or V_SELECT(). If omitted, the Top-Pointer will be accessed in
  3304.     the current DBV area.
  3305.  
  3306.  Description
  3307.  
  3308.     V_TOPPTR() is a special function which allows the storage of one (and
  3309.     only one) Variable Length Field without having a separate DBF file in
  3310.     which to keep the pointer to that field.
  3311.  
  3312.     Usually, you replace a six byte character field (FlexFile's version of
  3313.     a memo-field) in a DBF file with a pointer to data which is stored in a
  3314.     DBV file.  V_TOPPTR() allows you to store one pointer in the header of
  3315.     the DBV file.  This pointer can then be accessed by calling V_TOPPTR()
  3316.     with no parameters.  For example,
  3317.  
  3318.          V_ARETRIEVE( V_TOPPTR() )
  3319.  
  3320.     would retrieve an array which was previously stored with V_AREPLACE()
  3321.     and whose pointer was stored by V_TOPPTR().
  3322.  
  3323.     A good example of the use of this function is in storing parameters
  3324.     that your application requires at startup:  Things like colors, default
  3325.     paths, printer definitions, etc.
  3326.  
  3327.     Many routines have been written to handle this kind of data.  MEM files
  3328.     are used by some, while others use a large DBF field and parse out the
  3329.     various data into variables.  The fact is that MEM files are not
  3330.     "network ready" and the DBF file is not efficient to handle data that
  3331.     is not repetitive in size and type. So an easy solution is to keep an
  3332.     array of these items in a DBV file and point to that array with
  3333.     V_TOPPTR().
  3334.  
  3335.     Using V_TOPPTR() requires a slightly different syntax than a standard
  3336.     replace.  Typically, a DBV replace is made by calling V_AREPLACE() and
  3337.     putting the return pointer in a DBF field as follows:
  3338.  
  3339.          REPLACE vlf WITH V_AREPLACE( aStartUp, vlf )
  3340.  
  3341.     where aStartUp is an array holding your applications startup data.  In
  3342.     contrast, the following syntax is required when storing the
  3343.     pointer-field directly in the DBV:
  3344.  
  3345.          V_TOPPTR( V_AREPLACE( aStartUp, V_TOPPTR() ) )
  3346.  
  3347.     The logic here can best be seen by breaking this last line into several
  3348.     lines of code:
  3349.  
  3350.          // First, get the old pointer stored in the DBV file.
  3351.          cOldPointer = V_TOPPTR()
  3352.  
  3353.          // Then replace the old array with a new one.  Put
  3354.          // the pointer to the new array into the variable
  3355.          // cNewPointer.
  3356.          cNewPointer = V_AREPLACE( aStartUp, cOldPointer )
  3357.  
  3358.          // Finally, store the actual pointer in the DBV.
  3359.          // This will overwrite the old pointer stored there.
  3360.          V_TOPPTR( cNewPointer )
  3361.  
  3362.  Examples
  3363.  
  3364.     LOCAL ray
  3365.  
  3366.     // Open only a DBV file
  3367.     V_USE( "dbv_file" )  // Is created if it does not exist.
  3368.  
  3369.     // Declare an array and put some junk into it.
  3370.     ray = { { "one", "two", "three" }     ,;
  3371.             { 1, 2, 3 )                   ,;
  3372.             { p1, p2, p3 }                 }
  3373.  
  3374.     // Store the array in DBV file and its pointer in
  3375.     // the header of the same DBV.
  3376.     V_TOPPTR( V_AREPLACE( ray, V_TOPPTR() ) )
  3377.  
  3378.  
  3379. See Also: V_REPLACE() V_AREPLACE() V_RETRIEVE() V_ARETRIEVE()
  3380.  
  3381.  
  3382.  
  3383. ───────────────────────────────────────────────────────────────────────────────
  3384.  V_TYPE()
  3385.  Return the type of data stored in a VLF
  3386. ───────────────────────────────────────────────────────────────────────────────
  3387.  
  3388.  Syntax
  3389.  
  3390.     V_TYPE(  <cPointer>,
  3391.              <nArea> | <cAlias> )   ->   cType
  3392.  
  3393.  Arguments
  3394.  
  3395.     <cPointer> is a six byte pointer-field (FlexFile's version of a
  3396.     memo-field).
  3397.  
  3398.     <nArea> or <cAlias> refers to the number or name of the target DBV
  3399.     work area. If not specified, the current DBV work area is assumed.
  3400.  
  3401.  Returns
  3402.  
  3403.     V_TYPE() returns the type of the data that is pointed to by
  3404.     <cPointer>. The possible types and their one character pneumonic
  3405.     are detailed in the table under the V_REPLACE() function.
  3406.  
  3407.  Description
  3408.  
  3409.     V_TYPE() is similar to Clipper's TYPE() function. There are,
  3410.     however, more "types" of data that can be stored to a VLF than in
  3411.     a Clipper memory variable. For example, Clipper see's a Proclip
  3412.     window handle as a numeric. Clipper's TYPE("pw_handle") function
  3413.     would return a 'N'. However, if you save the Proclip window to a
  3414.     VLF (See V_REPLACE()), the V_TYPE() function will return a 'P'.
  3415.  
  3416.  
  3417.  Examples
  3418.  
  3419.     // Setup seven variables of differing types.
  3420.     LOCAL num_var   ,;
  3421.           chr_var   ,;
  3422.           date_var  ,;
  3423.           log_var   ,;
  3424.           arr_var   ,;
  3425.           ffa_var   ,;
  3426.           pcw_var
  3427.  
  3428.     num_var = 5
  3429.     chr_var = "This is a test"
  3430.     date_var= DATE()
  3431.     log_var = (.T.)
  3432.     arr_var = { "Cindy", "Gail", "Edith" }
  3433.     ffa_var = A_DECLARE( 'S', 5, 5 )// FlexFile double type
  3434.     pcw_var = WNDCREATE( 5, 10 ) // Proclip window.
  3435.  
  3436.     // Open a DBF file and its associated DBV file
  3437.     USE dbf_file
  3438.     V_USE( "dbv_file" )
  3439.  
  3440.     // Replace the VLF with five different data types.
  3441.     APPEND BLANK
  3442.     REPLACE vlf WITH V_REPLACE( num_var, vlf )
  3443.     ? V_TYPE( vlf )              // Result: 'N'
  3444.  
  3445.     REPLACE vlf WITH V_REPLACE( chr_var, vlf )
  3446.     ? V_TYPE( vlf )              // Result: 'C'
  3447.  
  3448.     REPLACE vlf WITH V_REPLACE( date_var, vlf )
  3449.     ? V_TYPE( vlf )              // Result: 'D'
  3450.  
  3451.     REPLACE vlf WITH V_REPLACE( log_var, vlf )
  3452.     ? V_TYPE( vlf )              // Result: 'L'
  3453.  
  3454.     // Note: The replace here is V_AREPLACE() for Clipper 5.0
  3455.     REPLACE vlf WITH V_AREPLACE( arr_var, vlf )
  3456.     ? V_TYPE( vlf )              // Result: 'A'
  3457.  
  3458.     // Note: You must declare the type for a V_REPLACE()
  3459.     //    of a flexfile strongly typed array.
  3460.     REPLACE vlf WITH V_REPLACE( ffa_var, vlf, , 'F' )
  3461.     ? V_TYPE( vlf )              // Result: 'F'
  3462.  
  3463.     // Note: You must declare the type for a V_REPLACE()
  3464.     //       of a Proclip window handle.
  3465.     REPLACE vlf WITH V_REPLACE( pcw_var, vlf, , 'P' )
  3466.     ? V_TYPE( vlf )              // Result: 'P'
  3467.  
  3468.  
  3469.  
  3470. See Also: V_REPLACE() V_RETRIEVE() V_LEN()
  3471.  
  3472.  
  3473.  
  3474. ───────────────────────────────────────────────────────────────────────────────
  3475.  V_USE()
  3476.  Open/Create a Variable Length Field file (DBV)
  3477. ───────────────────────────────────────────────────────────────────────────────
  3478.  
  3479.  Syntax
  3480.  
  3481.     V_USE(   [<cFileName>],
  3482.              [<cAlias>],
  3483.              [<cNewArea>],
  3484.              [<lExclusive>] )   ->    nArea
  3485.  
  3486.  Arguments
  3487.  
  3488.     <cFileName> is the name of the file to be opened/created. A .DBV
  3489.     extension is assumed if none is provided. If the file does not
  3490.     exist, one will be created. If <cFileName> is omitted, any file
  3491.     open in the current DBV area will be closed.
  3492.  
  3493.     <cAlias> is a name to be associated with the DBV work area of the
  3494.     file being opened. If this parameter is not passed or a "dummy"
  3495.     argument is passed, the alias defaults to the DBV file name.
  3496.  
  3497.     <cNewArea> is the word "NEW". This has the same affect as issuing
  3498.     a SELECT 0 in Clipper or V_SELECT(0) in FlexFile just before
  3499.     opening the file. In Clipper version 5.0, <cNewArea> has the same
  3500.     effect as the NEW modifier of the USE command. If this parameter
  3501.     is not specified, any DBV file open in the current DBV work area
  3502.     will be closed and the <cFileName> file will be opened in its
  3503.     place.
  3504.  
  3505.     <lExclusive> is a logical expression determining the accessibility
  3506.     of the file by other users in a network environment.  If
  3507.     <lExclusive> is (.T.) and the file is successfully opened, any
  3508.     attempt by another user to V_USE() the <cFileName> file will be
  3509.     denied until the file is V_CLOSED(). If this parameter is omitted,
  3510.     FlexFile will attempt to open the <cFileName> file according to
  3511.     the current setting of V_EXCLUSIV().
  3512.  
  3513.  Returns
  3514.  
  3515.     If successful, V_USE() returns the DBV area in which the file was
  3516.     opened. Otherwise, it will return a -1 and set an error code which
  3517.     may be fetched with V_ERROR(). (See appendix B for a list of error
  3518.     codes.)
  3519.  
  3520.  Description
  3521.  
  3522.     V_USE() opens (or creates if the file does not exist) a file that
  3523.     can store variable length data. Any file which is already open in
  3524.     the DBV area is closed before the <cFileName> file is opened.
  3525.  
  3526.     Although it is far more flexible, using a DBV file is very similar
  3527.     to using memo-fields and a DBT file. It is not required but highly
  3528.     recommended that you have a DBF file open simultaneously with the
  3529.     DBV file. You will then store pointers in fields of the DBF file
  3530.     that point to variable length data in the DBV file. The fields in
  3531.     the DBF file cannot be defined as a <memo> fields but have the
  3532.     same basic functionality.
  3533.  
  3534.     Unlike the DBT file, FlexFile supports one to one, one to many,
  3535.     and many to many relationships between the DBF field pointers and
  3536.     the DBV files. For example, a system could use one DBV file to
  3537.     store all its help text, random memo's, screens and arrays. The
  3538.     pointers to all this data could be stored in several different DBF
  3539.     files. Likewise, one DBF file may point into several DBV files. It
  3540.     is left up to the programmer to keep straight which DBF fields
  3541.     relate to which DBV files.  (Note: it is a critical error to use a
  3542.     pointer which points into one DBV file as a pointer into a
  3543.     different DBV file.)
  3544.  
  3545.     If a DBV file is opened exclusively in a network environment, no
  3546.     other users may access the file until it is V_CLOSED().  Likewise,
  3547.     if the file is currently being used exclusively by another user,
  3548.     attempts to V_USE() that file will fail.  V_USE() returns -1 if
  3549.     the file is not opened and reports the error which can be fetched
  3550.     with V_ERROR().  (See appendix B for a list of error codes.)
  3551.  
  3552.     If the file is opened non-exclusively, other users may access the
  3553.     variable length data simultaneously. However, because all data in
  3554.     a DBV file must be accessed by a pointer which will usually be
  3555.     stored in a DBF file, using standard Clipper locking procedures to
  3556.     protect the DBF record will protect the variable length data
  3557.     exactly as it does any field in the DBF. (See the V_REPLACE()
  3558.     function for more on locking.)
  3559.  
  3560.  Notes
  3561.  
  3562.   ■ V_USE() obeys neither the SET DEFAULT nor the SET PATH
  3563.     settings. Instead, it will use the current DOS default directory
  3564.     or any valid path specified as a part of <cFileName>.
  3565.  
  3566.   ■ Remember that your maximum number of open files must be set by
  3567.     the V_FILES() function before V_USE()ing your first DBV file. The
  3568.     valid DBV areas will then be from 1 to the value you passed to
  3569.     V_FILES(). See V_FILES() for more on defining the active number of
  3570.     files.
  3571.  
  3572.   ■ Opening the same DBV file in two work areas simultaneously is
  3573.     possible, however, don't do it.
  3574.  
  3575.   ■ Do not confuse Clipper's selected work area with FlexFile's;
  3576.     they are mutually exclusive. For example, you can have a DBF file
  3577.     open in area 2 and simultaneously have a DBV file open in
  3578.     V_SELECT() == 2. Likewise, Clipper's SELECT <n> has no effect on
  3579.     the currently selected DBV area.
  3580.  
  3581.  Examples
  3582.  
  3583.     // Assume that no files are open at this point.
  3584.     // Set the maximum number of files to three.
  3585.     #define EXCLUSIVE_ (.T.)
  3586.     V_FILES( 3 )
  3587.  
  3588.     // Open a DBV file with an alias of "MAIN_FILE" in area 1.
  3589.     // If dbv_file.dbv does not exist it will be created.
  3590.     V_SELECT(1)
  3591.     V_USE( "dbv_file", "MAIN_FILE" )
  3592.     ? V_ALIAS()           // Result: MAIN_FILE
  3593.  
  3594.     // Open another file in the next available area.
  3595.     V_USE( "second", , "NEW" )
  3596.     ? V_SELECT()          // Result: 2
  3597.  
  3598.     // Open a third file for use on a network and test to
  3599.     // make certain that the file was properly opened.
  3600.     IF V_USE( "F:\GEN\JUNK\third", , "new", !EXCLUSIVE_ ) == -1
  3601.        ? "Error: " + str( V_ERROR(), 4 )
  3602.        QUIT
  3603.     ENDIF
  3604.  
  3605.     // Close all files.
  3606.     V_CLOSE( 1 )          // Closes file in area 1
  3607.     V_CLOSEALL()          // Closes the other two files.
  3608.  
  3609.  
  3610. See Also: V_CLOSE() V_SELECT()
  3611.  
  3612.  
  3613.  
  3614. ───────────────────────────────────────────────────────────────────────────────
  3615.  V_VLF2FILE()
  3616.  Create a DOS file and fill it with the contents of a VLF
  3617. ───────────────────────────────────────────────────────────────────────────────
  3618.  
  3619.  Syntax
  3620.  
  3621.     V_VLF2FILE(  <cFileName>,
  3622.                  <cPointer>,
  3623.                  <cMode>  )     ->    lSuccess
  3624.  
  3625.  Arguments
  3626.  
  3627.     <cFileName> is the name of a file to append to or overwrite with
  3628.     the data from a VLF associated with <cPointer>.
  3629.  
  3630.     <cPointer> is a six byte pointer-field (FlexFile's version of a
  3631.     memo-field).
  3632.  
  3633.     <cMode> is a character code telling FlexFile to <A>ppend or
  3634.     <O>verwrite any existing file with the same name as <cFileName>.
  3635.     The default mode is <A>ppend.
  3636.  
  3637.  Returns
  3638.  
  3639.     V_VLF2FILE() returns (.T.) if the data was copied successfully,
  3640.     otherwise, it returns (.F.).
  3641.  
  3642.  Description
  3643.  
  3644.     V_VLF2FILE() copies a Variable Length Field from a DBV type file
  3645.     to a DOS file. This is particularly useful when using graphics
  3646.     applications from within Clipper that require individual files for
  3647.     images.
  3648.  
  3649.  
  3650.  Examples
  3651.  
  3652.     // Setup variable
  3653.     LOCAL pic_name
  3654.  
  3655.     // Open a DBF, NTX and DBV library of graphics images.
  3656.     USE ( pic_lib ) INDEX ( pic_lib )
  3657.     V_USE( pic_lib )
  3658.  
  3659.     // Allow the user to enter the name of a graphic image
  3660.     // to view, create a temporary disk file, print the
  3661.     // file to screen.
  3662.  
  3663.     WHILE ( .T. )
  3664.        pic_name = SPACE(11)
  3665.        @ 5, 5 SAY "Enter the image name to view: " GET pic_name
  3666.        SEEK pic_name
  3667.        IF FOUND()
  3668.  
  3669.           // Write DBV data to a temporary file.
  3670.           V_VLF2FILE( "graphic.pic", vlf_ptr )
  3671.  
  3672.           // Use one of the graphic function libraries to retrieve a file.
  3673.           file2graph( 0, "graphic.pic" )
  3674.  
  3675.           INKEY(0)
  3676.  
  3677.        ELSEIF LASTKEY() == 27
  3678.           EXIT
  3679.  
  3680.        ELSE
  3681.           ? "Image not found"
  3682.  
  3683.        ENDIF
  3684.     ENDDO
  3685.  
  3686.  
  3687. See Also: V_FILE2VLF() V_REPLACE() V_DELETE()
  3688.  
  3689.  
  3690. ───────────────────────────────────────────────────────────────────────────────
  3691.  V_WALK_DBV()
  3692.  Step from field to field in a DBV without a DBF.
  3693. ───────────────────────────────────────────────────────────────────────────────
  3694.  
  3695.  Syntax
  3696.  
  3697.     V_WALK_DBV( [<cTopOfFile>], [<cAlias> | <nArea>] )  ->   cPointer
  3698.  
  3699.  Arguments
  3700.  
  3701.     <cTopOfFile> should be the word "First" (only the "F" is significant)
  3702.     to return the pointer to the first field in a DBV.  Any other value
  3703.     (including NIL) will tell V_WALK_DBV() to skip to the next field.
  3704.  
  3705.     <cAlias> or <nArea> is a DBV file alias or area specified with
  3706.     V_USE() or V_SELECT(). If omitted, the operation will occur in the
  3707.     current DBV area.
  3708.  
  3709.  Returns
  3710.  
  3711.     This function returns a pointer to the current VLF. (See discussion
  3712.     below).  The return value is a NULL string ("") when the end of file is
  3713.     reached or when an error is encountered in the DBV.
  3714.  
  3715.  Description
  3716.  
  3717.     V_WALK_DBF() is a disaster recovery function and should rarely if every
  3718.     be needed.  However, if you loose a DBF file and still want to recover
  3719.     the contents of the DBV, this function can be indispensible.
  3720.  
  3721.     When called for the first time or when <cTopOfFile> is given the
  3722.     value "first", V_WALK_DBV() will return a pointer to the first Variable
  3723.     Length Field in the DBV (this is the first physical field).  Any
  3724.     subsequent call to this function (where <cTopOfFile> is not
  3725.     "first"), V_WALK_DBV() will return a pointer to the next physical field
  3726.     in the DBV.
  3727.  
  3728.     Thus, when put in a loop, you can walk through every field in a DBV and
  3729.     retrieve a valid FlexFile pointer for use with V_RETRIEVE(),
  3730.     V_REPLACE(), etc.
  3731.  
  3732.  Examples
  3733.  
  3734.     LOCAL vlf_ptr, str := ""
  3735.  
  3736.     // Open the DBV without opening a DBF.
  3737.     V_USE( "lost_dbf.dbv" )
  3738.  
  3739.     // Put the pointer to the first field in the variable <vlf_ptr>.
  3740.     // The "First" is not necessary here because the first call to this
  3741.     // function starts on the first field anyway, but is included
  3742.     // for clarity.
  3743.     vlf_ptr = V_WALK_DBV( "First" )
  3744.  
  3745.     DO WHILE !EMPTY( vlf_ptr )
  3746.  
  3747.        str = V_RETRIEVE( vlf_ptr )
  3748.        MEMOEDIT( str, 5, 5, 20, 75 )
  3749.  
  3750.        // Get a pointer to the next field (fields are in physical order)
  3751.        vlf_ptr = V_WALK_DBV()
  3752.  
  3753.     ENDDO
  3754.  
  3755.  
  3756.  
  3757. See Also: V_RETRIEVE()
  3758.  
  3759.  
  3760. ───────────────────────────────────────────────────────────────────────────────
  3761.  V_WNDCREAT()
  3762.  Create a Proclip(tm) window from one which was saved to a DBV file.
  3763. ───────────────────────────────────────────────────────────────────────────────
  3764.  
  3765.  Syntax
  3766.  
  3767.     V_WNDCREAT(  <cPointer>, [<cAlias> | <nArea>] )  ->   nPCWhandle
  3768.  
  3769.  Arguments
  3770.  
  3771.     <cPointer> is a six byte pointer-field (FlexFile's version of a
  3772.     memo-field).
  3773.  
  3774.     <cAlias> or <nArea> is a DBV file alias or area specified with
  3775.     V_USE() or V_SELECT(). If omitted, the operation will occur in the
  3776.     current DBV area.
  3777.  
  3778.  Returns
  3779.  
  3780.     If V_WNDCREAT() is successful, it will return a valid Proclip
  3781.     window "handle".  Otherwise, it will return 0.
  3782.  
  3783.  Description
  3784.  
  3785.     V_WNDCREAT() will re-create a Proclip window that was previously
  3786.     stored in a DBV file with the V_REPLACE() function.  The window
  3787.     will have all the attributes of the original window with the single
  3788.     exception that it will not be opened even if it was open when it
  3789.     was saved.
  3790.  
  3791.     In order to open or modify the window, you will need the Proclip
  3792.     library from Genesis Development Corporation.  It is one of the
  3793.     finest windowing libraries available.
  3794.  
  3795.  
  3796.  Examples
  3797.  
  3798.     // Create a Proclip window using the Proclip library.
  3799.     handle = WNDCREATE( 10, 20 )
  3800.  
  3801.     // Put some junk on the window.
  3802.     FOR x = 1 TO 10
  3803.        WNDPRINT( handle, x - 1, 0, "this is a test" )
  3804.     NEXT x
  3805.  
  3806.     // Show the user the window.
  3807.     WNDOPEN( handle )
  3808.  
  3809.     // Save the window to the DBV file open in the current area.
  3810.     // Note the necessity to "type" the replace (i.e. the 4th parameter).
  3811.     REPLACE vlf WITH V_REPLACE( handle, vlf, .t., 'P' )
  3812.  
  3813.     // Close and then destroy the window.
  3814.     WNDCLOSE( vlf )
  3815.     WNDDESTROY( vlf )
  3816.  
  3817.     // Now re-create the same window.
  3818.     handle = V_WNDCREAT( vlf )
  3819.  
  3820.     // Re-display the window
  3821.     WNDSHOW( handle )
  3822.  
  3823.  
  3824.  
  3825. See Also: V_FILE2VLF() V_REPLACE() V_DELETE()
  3826.  
  3827.  
  3828.  
  3829. ───────────────────────────────────────────────────────────────────────────────
  3830.  A_()
  3831.  Return a pointer reference to a multi-dimensional array element
  3832. ───────────────────────────────────────────────────────────────────────────────
  3833.  
  3834.  Syntax
  3835.  
  3836.     A_(   <nElements>,
  3837.           [, <nElements>...] )    ->    nPointer
  3838.  
  3839.  Arguments
  3840.  
  3841.     <nElements> represents the magnitude of each successive dimension
  3842.     in a FlexFile array.
  3843.  
  3844.  Returns
  3845.  
  3846.     A_() returns a character string which FlexFile interprets as a
  3847.     pointer to the specific element.
  3848.  
  3849.  Description
  3850.  
  3851.     Use A_() to simplify passing/receiving multi-dimensional array
  3852.     index references. The need for the function arises because array
  3853.     indexes have as many components as the array has dimensions and
  3854.     the passing of the index to a function can get confusing (both for
  3855.     the programmer and FlexFile's error checking).
  3856.  
  3857.     With Clipper arrays the compiler handles references to a
  3858.     particular element with the familiar syntax [ 1 ][ 1 ][ 1 ] for
  3859.     the first element of a three dimensional array.  Avoiding conflict
  3860.     with this syntax, FlexFile refers to the same element of a
  3861.     FlexFile three dimensional array as A_( 1, 1, 1 ).
  3862.  
  3863.     Although FlexFile functions will accept a numeric integer as an
  3864.     array index designator (it is the preferred method on a FlexFile
  3865.     single dimensional array), you should not use integers as indexes
  3866.     to multi- dimensional arrays.  This is because A_( 3, 5 ) does not
  3867.     refer to the same element as A_(5, 3), and rarely if ever does
  3868.     (3 * 5) point to element A_(3, 5).
  3869.  
  3870.     See the examples for a complete understanding of the use of this
  3871.     function.
  3872.  
  3873.  
  3874.  Examples
  3875.  
  3876.     // Accessing elements of a FlexFile Multi-dimensional array
  3877.     // First declare a two dimensional 5 x 10 array.
  3878.     rows = 5
  3879.     cols = 10
  3880.     aName = A_DECLARE( 'F', rows, cols )
  3881.  
  3882.     // Fill the array starting at the first element a_( 1, 1 ).
  3883.     A_FILL( aName, 98.6, A_( 1, 1 ), rows * cols )
  3884.  
  3885.     // Retrieve a value from a specified element.
  3886.     temp = A_RETRIEVE( aName, A_( 3, 2 ) )
  3887.  
  3888.  
  3889. See Also: A_RETRIEVE() A_STORE()
  3890.  
  3891.  
  3892.  
  3893. ───────────────────────────────────────────────────────────────────────────────
  3894.  A_ADD()
  3895.  Add a new element to the end of an array
  3896. ───────────────────────────────────────────────────────────────────────────────
  3897.  
  3898.  Syntax
  3899.  
  3900.     A_ADD(   @<aTarget>,
  3901.              [<nDimension>] )   ->    lSuccess
  3902.  
  3903.  Arguments
  3904.  
  3905.     <aTarget> is the array to which you are adding new element(s).
  3906.     It MUST be passed-by-reference.  A_ADD() cannot add elements to
  3907.     a binary (logical) type array.
  3908.  
  3909.     <nDimension> is the dimension that will be increased by one.
  3910.     The default is the last dimension in the list of dimensions.
  3911.  
  3912.  Returns
  3913.  
  3914.     A_ADD() returns a (.T.) if successful, otherwise, it returns a
  3915.     (.F.).
  3916.  
  3917.  Description
  3918.  
  3919.     A_ADD() works differently than Clipper's AADD() function. This is
  3920.     because FlexFile arrays are matrices and cannot have "ragged"
  3921.     lengths in any dimension.
  3922.  
  3923.     So, A_ADD() adds one element in a one dimensional array, one row
  3924.     in a two dimensional array, one page in a three dimensional array,
  3925.     and so forth.
  3926.  
  3927.     For example, imagine a two dimensional array containing students
  3928.     grades. Along one axis are the students; along the other are the
  3929.     exams. When the semester begins the professor may not know how
  3930.     many exams there are going to be (or how to handle a new student).
  3931.     If you look at both of these situations you will understand
  3932.     FlexFile's A_ADD().
  3933.  
  3934.     Lets assume that the professor begins with 20 students and plans
  3935.     the course to consist of 5 exams:
  3936.  
  3937.     students = 20 
  3938.     exams = 5 
  3939.     array = A_DECLARE( 'I', students, exams )
  3940.  
  3941.  
  3942.     Later in the course he needs to add a new student.
  3943.  
  3944.     A_ADD( @array, 1 )
  3945.  
  3946.     The second parameter is one to tell A_ADD that we are adding a
  3947.     row of exams for a new student. The value is one because when
  3948.     we declared the array the students were the first array
  3949.     index.
  3950.  
  3951.     Later the professor needs to add another exam for all students:
  3952.  
  3953.     A_ADD( @array, 2 )
  3954.  
  3955.  
  3956.  Examples
  3957.  
  3958.     // Declare a two dimensional unsigned (T)iny integer array
  3959.     LOCAL rows, cols
  3960.     
  3961.     rows = 10
  3962.     cols = 20
  3963.     aTiny = A_DECLARE( "UT", rows, cols )
  3964.     
  3965.     // Increase the columns to 21.
  3966.     A_ADD( @aTiny, 2 )
  3967.  
  3968.  
  3969.  
  3970. See Also: A_SIZE() A_DECLARE()
  3971.  
  3972.  
  3973.  
  3974. ───────────────────────────────────────────────────────────────────────────────
  3975.  A_AVERAGE()
  3976.  Return the average of the contents of a numerical array
  3977. ───────────────────────────────────────────────────────────────────────────────
  3978.  
  3979.  Syntax
  3980.  
  3981.     A_AVERAGE(   <aTarget>,
  3982.                  [<idxPos>],
  3983.                  [<nCount>] )   ->    nAverage
  3984.  
  3985.  Arguments
  3986.  
  3987.     <aTarget> is the FlexFile array on which to perform the average.
  3988.  
  3989.     <idxPos> The index (or subscript) is the position in the target
  3990.     array at which to begin the average. The default is the first
  3991.     element.
  3992.  
  3993.     <nCount> is the number of elements to include in the average. The
  3994.     default is all element starting at <idxPos> to the end of the
  3995.     array.
  3996.  
  3997.  Returns
  3998.  
  3999.     A_AVERAGE() returns the numerical average or mean of the <aTarget>
  4000.     array.  On error, A_AVERAGE() returns 0.
  4001.  
  4002.  Description
  4003.  
  4004.     A_AVERAGE() will average all or a part of a FlexFile numeric
  4005.     array. The numeric types are (D)ouble, (F)loat, (L)ong or (UL),
  4006.     (I)nteger or (UI), and (T)iny or (UT).
  4007.  
  4008.     The averaging begins at the position pointed to by <idxPos> and
  4009.     continues for <nCount> elements. The function will wrap around
  4010.     dimensions if count extends beyond the end of the current row.
  4011.  
  4012.  
  4013.  Examples
  4014.  
  4015.     // Declare a two dimensional (L)ong integer array
  4016.     LOCAL rows, cols
  4017.     
  4018.     rows = 10
  4019.     cols = 20
  4020.     aLong = A_DECLARE( "L", rows, cols )
  4021.     
  4022.     // Fill the 5th row with 100,000 and the 6th row
  4023.     // with 200,000.
  4024.     A_FILL( aLong, 100000, A_( 5, 1 ), cols )
  4025.     A_FILL( aLong, 200000, A_( 6, 1 ), cols )
  4026.     
  4027.     // Take the average of rows 5 and six.
  4028.     ? A_AVERAGE( aLong, A_( 5, 1 ), cols * 2 )  // Result: 150000
  4029.  
  4030.  
  4031.  
  4032. See Also: A_STORE() A_RETRIEVE()
  4033.  
  4034.  
  4035.  
  4036. ───────────────────────────────────────────────────────────────────────────────
  4037.  A_COPY()
  4038.  Copy all or a portion of one array into another existing array
  4039. ───────────────────────────────────────────────────────────────────────────────
  4040.  
  4041.  Syntax
  4042.  
  4043.     A_COPY(  <aSource>,
  4044.              <aTarget>,
  4045.              [<idxPos>],
  4046.              [<nCount>],
  4047.              [<nTargetPos>] )
  4048.  
  4049.  Arguments
  4050.  
  4051.     <aSource> is the array that will be copied from.
  4052.  
  4053.     <aTarget> is the array that will be copied to.
  4054.  
  4055.     <idxPos> is the element in <aSource> where the copy will begin. The
  4056.     default is the first element in the array.
  4057.  
  4058.     <nCount> is the number of elements to copy. The default is all
  4059.     elements starting at <idxPos> until the end of the row in the
  4060.     current dimension.
  4061.  
  4062.     <nTargetPos> is the starting element position in the target array.
  4063.  
  4064.  Returns
  4065.  
  4066.     None.
  4067.  
  4068.  Description
  4069.  
  4070.     A_COPY() copies the contents of one array into another.  This is
  4071.     different than Clipper's ACOPY() which copies references to nested
  4072.     array elements. Because there are no nested array elements in a
  4073.     FlexFile array, the copy includes the smaller of the range
  4074.     specified and the size of the arrays.
  4075.  
  4076.  Examples
  4077.  
  4078.     // Declare a two dimensional (UL)ong integer array
  4079.     LOCAL rows, cols
  4080.     
  4081.     rows = 10
  4082.     cols = 20
  4083.     aSource = A_DECLARE( "UL", rows, cols )
  4084.     aTarget = A_DECLARE( "UL", rows, cols )
  4085.     
  4086.     // Fill the 5th row with 100,000 and the 6th row
  4087.     // with 200,000.
  4088.     A_FILL( aSource, 100000, A_(5, 1), cols )
  4089.     A_FILL( aTarget, 200000, A_(6, 1), cols )
  4090.     
  4091.     // Copy the 5th and 6th rows to the 2nd/3rd row of the target
  4092.     A_COPY( aSource, aTarget, A_(5, 2), cols * 2, A_(2, 1) )
  4093.  
  4094.  
  4095. See Also: A_SIZE() A_INS()
  4096.  
  4097.  
  4098.  
  4099. ───────────────────────────────────────────────────────────────────────────────
  4100.  A_DECLARE()
  4101.  Declare a FlexFile array
  4102. ───────────────────────────────────────────────────────────────────────────────
  4103.  
  4104.  Syntax
  4105.  
  4106.     A_DECLARE(   <cType>,
  4107.                  <nElement>,
  4108.                  [<nElements>...] )    ->     aArray
  4109.  
  4110.  Arguments
  4111.  
  4112.     <cType> is a code for the type of the FlexFile strongly typed
  4113.     array. (See the table below for a list of types and their codes.)
  4114.  
  4115.     <nElements> is the number of elements in each consecutive
  4116.     dimension.  An array can be declared with up to six dimensions.
  4117.  
  4118.  Returns
  4119.  
  4120.     A_DECLARE() returns a fully dimensioned FlexFile array of <cType>.
  4121.  
  4122.  Description
  4123.  
  4124.     A_DECLARE() creates a FlexFile type array.  The various data types
  4125.     that FlexFile implements are listed below.
  4126.  
  4127.     When Clipper returns a value from a function, it makes a copy of
  4128.     the value for the calling function before releasing the value
  4129.     created by the called function.  So, if you declare a FlexFile
  4130.     character array of 60,000 elements, A_DECLARE() will allocate
  4131.     memory for an array of 60,000 character elements (a little over
  4132.     60,000 bytes) and then Clipper will copy that variable requiring
  4133.     two 60,000 byte blocks to execute the function.
  4134.  
  4135.     Although this is not a problem with smaller arrays, it becomes
  4136.     significant with larger ones.  FlexFile addresses this problem by
  4137.     offering an optional syntax for this function.  Just add a new
  4138.     parameter and insert it after the type.  This parameter must be a
  4139.     previously declared character string of any length and it must be
  4140.     passed-by-reference.  The optional syntax is as follows:
  4141.  
  4142.     A_DECLARE( <cType>,
  4143.               @<aLargeArr>,
  4144.                <nElement>,
  4145.               [<nElements>...] )
  4146.  
  4147.  
  4148.     The return value when this syntax is used is undefined.  Instead,
  4149.     FlexFile will modify the <aLargeArr> variable.  Because there is
  4150.     no return value, Clipper will not duplicate the <aLargeArr>
  4151.     variable.
  4152.  
  4153.     Table: Data types
  4154.     ┌──────────────────────────────────────────────────────────────────────┐
  4155.     │ Array Type       Type  Elem/Arr  Byte/Elem Data Range                │
  4156.     ├──────────────────────────────────────────────────────────────────────┤
  4157.     │ Binary (logical)  B    520K      1 bit     .T. or .F.                │
  4158.     │ Character         C    65K       1 byte    Extended ASCII set        │
  4159.     │ Tiny Integer      T    65K       1 byte    -128 to 127               │
  4160.     │ Unsigned Tiny     UT   65K       1 byte    0 to 255                  │
  4161.     │ Integer           I    32K       2 bytes   -32,768 to 32,767         │
  4162.     │ Unsigned Integer  UI   32K       2 bytes   0 to 65,535               │
  4163.     │ Long Integer      L    16K       4 bytes   -2147483648 to 2147483647 │
  4164.     │ Unsigned Long     UL   16K       4 bytes   0 to 4,294,967,295        │
  4165.     │ Floating Point    F    16K       4 bytes   7 digit precision         │
  4166.     │ String            S    16K       4 bytes   n/a                       │
  4167.     │ Double            D    8K        8 bytes   15 digit precision        │
  4168.     └──────────────────────────────────────────────────────────────────────┘
  4169.  
  4170.  Examples
  4171.  
  4172.     // Declare a two dimensional (B)inary array
  4173.     LOCAL rows, cols
  4174.     
  4175.     rows = 10000
  4176.     cols = 20
  4177.     aBinary = A_DECLARE( "B", rows, cols )
  4178.  
  4179.     // Optional syntax. Note: A_DECLARE() has no return value.
  4180.     LOCAL aLargeArr := ''
  4181.  
  4182.     A_DECLARE( "UL", aLargeArr, 10000, 2 ) 
  4183.  
  4184.  
  4185. See Also: A_FILL() A_TYPE()
  4186.  
  4187.  
  4188.  
  4189. ───────────────────────────────────────────────────────────────────────────────
  4190.  A_DEL()
  4191.  Delete one element from an array
  4192. ───────────────────────────────────────────────────────────────────────────────
  4193.  
  4194.  Syntax
  4195.  
  4196.     A_DEL( <aTarget>, [<idxPos>], [<nCount>] )
  4197.  
  4198.  Arguments
  4199.  
  4200.     <aTarget> is the array from which an element will be deleted.
  4201.  
  4202.     <idxPos> is the position in the target array of the element to be
  4203.     deleted.
  4204.  
  4205.     <nCount> is the number of elements to shift. The default is all
  4206.     elements starting at <idxPos> until the end of the row in the
  4207.     current dimension.
  4208.  
  4209.  Returns
  4210.  
  4211.     None.
  4212.  
  4213.  Description
  4214.  
  4215.     A_DEL() is similar to Clipper's ADEL() function. The array element
  4216.     pointed to by <idxPos> is removed and <nCount> elements are
  4217.     shifted up one position. A blank element is inserted at the
  4218.     position created by the shift and filled with the default value
  4219.     based on the type of the array (see A_DECLARE()).
  4220.  
  4221.     FlexFile's multi-dimensional arrays are not nested single
  4222.     dimensional arrays. Therefore, A_DEL()eting an element has no
  4223.     other affect than shifting <nCount> elements up one position.
  4224.  
  4225.     Wrapping will occur if <nCount> goes beyond the current row
  4226.     pointed to by <idxPos>. For example, if you have a two dimensional
  4227.     array with accounts in the first dimension and 12 prior period
  4228.     amounts in the second dimension, and you wanted to operate on the
  4229.     first quarter (i.e. 3 periods), making <nCount> three times the
  4230.     number of accounts will "wrap" around three periods. See the
  4231.     discussion on arrays in chapter 2 for more information on this
  4232.     feature.
  4233.  
  4234.  
  4235.  Examples
  4236.  
  4237.     // Declare a two dimensional (C)haracter array
  4238.     LOCAL rows, cols, x, y, z
  4239.     
  4240.     rows = 10
  4241.     cols = 20
  4242.     z = 1
  4243.     aChar = A_DECLARE( "C", rows, cols )
  4244.     
  4245.     // Fill the array with increasing character values.
  4246.     FOR x = 1 to rows
  4247.        FOR y = 1 to cols
  4248.           z++
  4249.           A_STORE( aChar, chr(z), A_( x, y ) )
  4250.        NEXT
  4251.     NEXT
  4252.  
  4253.     // Delete the ASCII character "" from the first element
  4254.     // and shift all elements from the second element to the
  4255.     // end of the array up one position.  Wrapping will occur.
  4256.     A_DEL( aChar, A_(1, 1), 1 )
  4257.  
  4258.  
  4259.  
  4260. See Also: A_DECLARE() A_INS() A_SCROLL()
  4261.  
  4262.  
  4263.  
  4264. ───────────────────────────────────────────────────────────────────────────────
  4265.  A_DIMS()
  4266.  Return the number of dimensions in an array
  4267. ───────────────────────────────────────────────────────────────────────────────
  4268.  
  4269.  Syntax
  4270.  
  4271.     A_DIMS( <aTarget> )   ->   nDimensions
  4272.  
  4273.  Arguments
  4274.  
  4275.     <aTarget> is the array whose dimensions are being queried.
  4276.  
  4277.  Returns
  4278.  
  4279.     A_DIMS() returns the number of dimensions of <aTarget>.
  4280.  
  4281.  Description
  4282.  
  4283.     A_DIMS() is used to query an array returning the number of
  4284.     dimensions that were used when the array was A_DECLARE()d.
  4285.  
  4286.  
  4287.  Examples
  4288.  
  4289.     // Declare a four dimensional (S)tring array
  4290.     LOCAL books, pages, rows, cols
  4291.     
  4292.     books = 2
  4293.     pages = 10
  4294.     rows = 15
  4295.     cols = 50
  4296.     aString = A_DECLARE( "S", books, pages, rows, cols )
  4297.     
  4298.     ? A_DIMS( aString )          // Result: 4
  4299.  
  4300.  
  4301.  
  4302.  
  4303. See Also: A_DECLARE() A_LEN()
  4304.  
  4305.  
  4306.  
  4307. ───────────────────────────────────────────────────────────────────────────────
  4308.  A_DIVIDE()
  4309.  Divide all elements of an array by a value or an array of values
  4310. ───────────────────────────────────────────────────────────────────────────────
  4311.  
  4312.  Syntax
  4313.  
  4314.     A_DIVIDE(    <aTarget>,
  4315.                  <nDenominator> | <aDenominators>,
  4316.                  [<aSource>] )
  4317.  
  4318.  Arguments
  4319.  
  4320.     <aTarget> is the array to be modified. If <aSource> is not
  4321.     specified then each element of <aTarget> is the numerator of the
  4322.     division.
  4323.  
  4324.     <nDenominator> or <aDenominators> is either a value or an array of
  4325.     values used as the denominator in the division.
  4326.  
  4327.     <aSource> is an optional array of numerators. If not specified,
  4328.     then each element of <aTarget> will be used as the numerator of
  4329.     the division.
  4330.  
  4331.  Returns
  4332.  
  4333.     Although there is no return value, the <aTarget> array is
  4334.     modified.
  4335.  
  4336.  Description
  4337.  
  4338.     A_DIVIDE() provides a means to perform a division of every element
  4339.     in the <aSource> array if specified or the <aTarget> array if not.
  4340.     Each element of the <aSource> or <aTarget> array is divided by the
  4341.     <nDenominator> or element for element by <aDenominator>. The
  4342.     result of the division replaces the value in the <aTarget> array.
  4343.  
  4344.     A_DIVIDE() can be performed on any integer or floating point type
  4345.     array. These include the (T)iny, (I)integer, (L)ong, (F)loat and
  4346.     (D)ouble (both signed and unsigned integers, of course).  Mixing
  4347.     of the various numeric types is permitted, however, the source
  4348.     values are promoted or demoted to the targets type before the
  4349.     operation is executed.
  4350.  
  4351.     Division by zero is trapped and the element in error is replaced
  4352.     with zero.
  4353.  
  4354.  Notes
  4355.  
  4356.   ■ Division by zero is trapped and the element in error is
  4357.   replaced with zero.
  4358.  
  4359.  Examples
  4360.     // Declare three double type arrays for this function.
  4361.     LOCAL rows, cols
  4362.     
  4363.     rows = 10
  4364.     cols = 20
  4365.     aSource = A_DECLARE( "D", rows, cols )
  4366.     aTarget = A_DECLARE( "D", rows, cols )
  4367.     aDenominator = A_DECLARE( "D", rows, cols )
  4368.     
  4369.     // Fill the target array with 10's
  4370.     A_FILL( aTarget, 10, A_(1, 1), rows * cols )
  4371.     
  4372.     // Divide every element in the target array by 2
  4373.     A_DIVIDE( aTarget, 2 )
  4374.     ? A_RETRIEVE( aTarget, A_( 4, 5 ) )    // Result: 5.0
  4375.     
  4376.     // Fill the source array with 10's
  4377.     A_FILL( aSource, 10, A_(1, 1), rows * cols )
  4378.     
  4379.     // Divide every element in the source array by five and
  4380.     // put the result in the target array.
  4381.     A_DIVIDE( aTarget, 5, aSource )
  4382.     ? A_RETRIEVE( aTarget, A_( 4, 5 ) )    // Result: 2.0
  4383.     
  4384.     // Fill the denominator array with 4's
  4385.     // Remember the source array still has all 10's
  4386.     A_FILL( aDenominator, 4, A_(1, 1), rows * cols )
  4387.     
  4388.     // Divide every element in the source array by every element
  4389.     // in the denominator array and put the result in the target
  4390.     // array.
  4391.     A_DIVIDE( aTarget, aDenominator, aSource )
  4392.     ? A_RETRIEVE( aTarget, A_( 4, 5 ) )    // Result: 2.5
  4393.  
  4394.  
  4395. See Also: A_MULTIPLY() A_PLUS() A_MINUS()
  4396.  
  4397.  
  4398.  
  4399.  
  4400. ───────────────────────────────────────────────────────────────────────────────
  4401.  A_ERROR()
  4402.  Report specific error codes from FlexFile's error system
  4403. ───────────────────────────────────────────────────────────────────────────────
  4404.  
  4405.  Syntax
  4406.  
  4407.     A_ERROR()   ->    nErrorValue
  4408.  
  4409.  Arguments
  4410.  
  4411.     None.
  4412.  
  4413.  Returns
  4414.  
  4415.     A_ERROR() returns a FlexFile error code as a numeric integer.
  4416.  
  4417.  Description
  4418.  
  4419.     A_ERROR() is an error function that will return the most recent
  4420.     error code that FlexFile set. If the failed operation has no
  4421.     FlexFile error code check the DOS error code using Clipper's
  4422.     DOSERROR().
  4423.  
  4424.     For a complete list of error codes and their descriptions
  4425.     refer to Appendix B.
  4426.  
  4427.  Examples
  4428.  
  4429.     // Declare a two dimensional array
  4430.     LOCAL aLong
  4431.     aLong = A_DECLARE( 'L', 5, 7 )
  4432.  
  4433.     // Using A_KILL() on a non-string type array is an error.
  4434.     A_KILL( aLong )
  4435.  
  4436.     // Show the error code for a type mismatch.
  4437.     ? A_ERROR()                   // Result: 2001
  4438.  
  4439.  
  4440. See Also: errcodes.ngo:"Error Codes"
  4441.  
  4442.  
  4443.  
  4444. ───────────────────────────────────────────────────────────────────────────────
  4445.  A_FILL()
  4446.  Fill all or a portion of an array with a specified value
  4447. ───────────────────────────────────────────────────────────────────────────────
  4448.  
  4449.  Syntax
  4450.  
  4451.     A_FILL(  <aTarget>,
  4452.              <expValue>,
  4453.              [<idxPos>],
  4454.              [<nCount>] )
  4455.  
  4456.  Arguments
  4457.  
  4458.     <aTarget> is the array which will be filled.
  4459.  
  4460.     <expValue> is an expression which must evaluate to the same type
  4461.     as that of the array. This value will be placed in each element of
  4462.     the fill range.
  4463.  
  4464.     <idxPos> is the first position to in the <aTarget> array to fill.
  4465.     If not specified, the default value is the first element in the array.
  4466.  
  4467.     <nCount> is the number of elements to fill starting at <idxPos>.
  4468.     If not specified, elements are filled to the end of the array.
  4469.  
  4470.  Returns
  4471.  
  4472.     None.
  4473.  
  4474.  Description
  4475.  
  4476.     A_FILL() replaces <nCount> elements in the range beginning at
  4477.     <idxPos> with <expValue>. The value must be of the same type as
  4478.     the array.
  4479.  
  4480.     Wrapping will occur if <nCount> goes beyond the current row
  4481.     pointed to by <idxPos>. For example, if you have a two dimensional
  4482.     array with accounts in the first dimension and 12 prior period
  4483.     amounts in the second dimension, and you wanted to operate on the
  4484.     first quarter (i.e. 3 periods), making <nCount> three times the
  4485.     number of accounts will "wrap" around three periods. See the
  4486.     discussion on arrays in chapter 2 for more information on this
  4487.     feature.
  4488.  
  4489.  
  4490.  Examples
  4491.  
  4492.     // Declare a two dimensional (F)loating point array
  4493.     LOCAL rows, cols
  4494.     
  4495.     rows = 10
  4496.     cols = 20
  4497.     aFloat = A_DECLARE( "F", rows, cols )
  4498.     
  4499.     // Fill the second row of the array with 98.6
  4500.     A_FILL( aFloat, 98.6, A_(2, 1), cols )
  4501.  
  4502.  
  4503. See Also: A_STORE() A_ADD()
  4504.  
  4505.  
  4506.  
  4507. ───────────────────────────────────────────────────────────────────────────────
  4508.  A_INS()
  4509.  Insert an element into an array
  4510. ───────────────────────────────────────────────────────────────────────────────
  4511.  
  4512.  Syntax
  4513.  
  4514.     A_INS( <aTarget>, [<idxPos>], [<nCount>] )
  4515.  
  4516.  Arguments
  4517.  
  4518.     <aTarget> is the array into which an element will be inserted.
  4519.  
  4520.     <idxPos> is the position in the target array of the element to be
  4521.     inserted.
  4522.  
  4523.     <nCount> is the number of elements to shift. The default is all
  4524.     elements starting at <idxPos> until the end of the row in the
  4525.     current dimension.
  4526.  
  4527.  Returns
  4528.  
  4529.     None.
  4530.  
  4531.  Description
  4532.  
  4533.     A_INS() is similar to Clipper's AINS() function. All elements from
  4534.     <idxPos> for <nCount> will be shifted down one element. The last
  4535.     element in <nCount> will be pushed into oblivion. A blank element
  4536.     is inserted at the position created by the shift and filled with
  4537.     the default value based on the type of the array (see
  4538.     A_DECLARE()).
  4539.  
  4540.     FlexFile's multi-dimensional arrays are not nested single
  4541.     dimensional arrays. Therefore, A_INS()erting an element has no
  4542.     other affect than shifting <nCount> elements down one position.
  4543.  
  4544.     Wrapping will occur if <nCount> goes beyond the current row
  4545.     pointed to by <idxPos>. For example, if you have a two dimensional
  4546.     array with accounts in the first dimension and 12 prior period
  4547.     amounts in the second dimension, and you wanted to operate on the
  4548.     first quarter (i.e. 3 periods), making <nCount> three times the
  4549.     number of accounts will "wrap" around three periods. See the
  4550.     discussion on arrays in chapter 2 for more information on this
  4551.     feature.
  4552.  
  4553.  Examples
  4554.  
  4555.     // Declare a two dimensional (C)haracter array
  4556.     LOCAL rows, cols, x, y, z
  4557.     
  4558.     rows = 10
  4559.     cols = 20
  4560.     z = 1
  4561.     aChar = A_DECLARE( "C", rows, cols )
  4562.     
  4563.     // Fill the array with increasing character values.
  4564.     FOR x = 1 to rows
  4565.        FOR y = 1 to cols
  4566.           z++
  4567.           A_STORE( aChar, chr(z), A_( x, y ) )
  4568.        NEXT
  4569.     NEXT
  4570.  
  4571.     // Insert four blank elements (chr(0)'s) at the first element
  4572.     // and shift all elements from the second element to the
  4573.     // end of the array down four positions.  Wrapping will occur.
  4574.     A_INS( aChar, A_(1, 1), 4 )
  4575.  
  4576.  
  4577. See Also: A_DECLARE() A_DEL() A_SCROLL()
  4578.  
  4579.  
  4580.  
  4581. ───────────────────────────────────────────────────────────────────────────────
  4582.  A_KILL()
  4583.  Release memory for all or a range of elements from a string array
  4584. ───────────────────────────────────────────────────────────────────────────────
  4585.  
  4586.  Syntax
  4587.  
  4588.     A_KILL( <aTarget>, [<idxPos>], [<nCount>] )
  4589.  
  4590.  Arguments
  4591.  
  4592.     <aTarget> is the array in which to release elements.
  4593.  
  4594.     <idxPos> is the position in the target array of the first element
  4595.     to be released.  If not specified, A_KILL() begins at the first
  4596.     element in the array.
  4597.  
  4598.     <nCount> is the number of elements to release. The default is all
  4599.     elements starting at <idxPos> until the end of the array. This
  4600.     includes wrapping.
  4601.  
  4602.  Returns
  4603.  
  4604.     None.
  4605.  
  4606.  Description
  4607.  
  4608.     FlexFile's string arrays are actually arrays of pointers. That is,
  4609.     the array consists of four byte elements, each element capable of
  4610.     pointing to a string of data. When declared, each element of the
  4611.     array is undefined.
  4612.  
  4613.     When data is A_STORE()d to an element of a string array, memory is
  4614.     allocated for that data. If the array of pointers falls out of
  4615.     scope before that memory is released, the memory is orphaned and
  4616.     essentially lost until the application is exited.
  4617.  
  4618.     Therefore, you must use A_KILL() to release the data before
  4619.     allowing a FlexFile string array to fall out of scope.
  4620.  
  4621.     ┌────────────────────────── WARNING ───────────────────────────┐
  4622.     │ You must use A_KILL() to release the data from a String type │
  4623.     │ array before allowing the array to fall out of scope.        │
  4624.     └──────────────────────────────────────────────────────────────┘
  4625.  
  4626.  Examples
  4627.  
  4628.     // Use A_KILL() to release a FlexFile string type array
  4629.     // before exiting the function that created it.
  4630.     
  4631.     Phrase( "Miles to go before I sleep" )
  4632.     
  4633.     
  4634.     FUNCTION Phrase( cSomePhrase )
  4635.     
  4636.        LOCAL ffArray
  4637.        // Declare a FlexFile string array.
  4638.        ffArray = A_DECLARE( 'S', 5, 8 )
  4639.     
  4640.        // Put the value into element A_( 3, 3 ).
  4641.        A_STORE( ffArray, cSomePhrase, A_( 3, 3 ) )
  4642.     
  4643.        // Do something with the array.
  4644.        ? A_RETRIEVE( ffArrary, A_(3, 3) )
  4645.     
  4646.        // It is necessary to release the memory
  4647.        // allocated for the string in the array.
  4648.        A_KILL( ffArray )
  4649.     
  4650.     // The array itself is released by Clipper on return
  4651.     RETURN (.T.)
  4652.  
  4653.  
  4654. See Also: A_STORE() A_DECLARE()
  4655.  
  4656.  
  4657.  
  4658. ───────────────────────────────────────────────────────────────────────────────
  4659.  A_LEN()
  4660.  Return the total number of elements in an array or a specified dimension
  4661. ───────────────────────────────────────────────────────────────────────────────
  4662.  
  4663.  Syntax
  4664.  
  4665.     A_LEN( <aTarget>, [<nDimension>] )    ->    nCount
  4666.  
  4667.  Arguments
  4668.  
  4669.     <aTarget> is the array whose elements will be counted.
  4670.  
  4671.     <nDimension> is the dimension whose elements will be counted. If
  4672.     not specified, all elements in the array will be counted.
  4673.  
  4674.  Returns
  4675.  
  4676.     A_LEN() returns the number of elements in the array or any one
  4677.     dimension of the array.
  4678.  
  4679.  Description
  4680.  
  4681.     A_LEN() counts the number of declared elements in an array. If a
  4682.     particular dimension is supplied in <nDimension>, then only the
  4683.     number of elements in that dimension will be reported.
  4684.  
  4685.     For example, if you declare a two dimensional array with thirty
  4686.     students in the first dimension and their grades on five exams in
  4687.     the second, A_LEN() will report thirty elements for the first
  4688.     dimension, five elements in the second dimension or one hundred
  4689.     and fifty elements in the entire array.
  4690.  
  4691.  Examples
  4692.  
  4693.     // Use A_LEN() to scan for the total length of an array.
  4694.     
  4695.     LOCAL ffArray
  4696.     // Declare a FlexFile string array.
  4697.     ffArray = A_DECLARE( 'S', 5, 8 )
  4698.     
  4699.     ? A_LEN( ffArray )      // Result: 40
  4700.     
  4701.     // Now use to show only the length of the second dimension.
  4702.     ? A_LEN( ffArray, 2 )   // Result: 8
  4703.  
  4704.  
  4705. See Also: A_DECLARE() A_ADD() A_SIZE()
  4706.  
  4707.  
  4708.  
  4709. ───────────────────────────────────────────────────────────────────────────────
  4710.  A_MAX()
  4711.  Return the greatest value found in a numeric array
  4712. ───────────────────────────────────────────────────────────────────────────────
  4713.  
  4714.  Syntax
  4715.  
  4716.     A_MAX( <aTarget>, [<idxPos>], [<nCount>] )
  4717.  
  4718.  Arguments
  4719.  
  4720.     <aTarget> is the numeric type array to evaluate.
  4721.  
  4722.     <idxPos> is the position in the target array of the first element
  4723.     to be evaluated.  If not specified, A_MAX() begins its search on
  4724.     the first element of the array.
  4725.  
  4726.     <nCount> is the number of elements to evaluate. The default is all
  4727.     elements starting at <idxPos> until the end of the row in the
  4728.     current dimension.
  4729.  
  4730.  Returns
  4731.  
  4732.     A_MAX() returns an index to the element which has the maximum
  4733.     value found in the specified range.
  4734.  
  4735.  Description
  4736.  
  4737.     A_MAX() evaluates every element in the specified range of a
  4738.     numeric type array and returns an index to the largest element.
  4739.  
  4740.  Examples
  4741.  
  4742.     // Declare a two dimensional (I)nteger array
  4743.     LOCAL rows, cols, x
  4744.     
  4745.     rows = 10
  4746.     cols = 20
  4747.     aInteger = A_DECLARE( "I", rows, cols )
  4748.     
  4749.     // Fill the second row of the array with increasing
  4750.     // integer values 1 - 20
  4751.     FOR x = 1 to 20
  4752.        A_STORE( aInteger, x, A_( 2, x ) )
  4753.     NEXT
  4754.     
  4755.     // Fetch the maximum value in the first half of the
  4756.     // second row.
  4757.     ? A_MAX( aInteger, A_( 2, 1 ), cols / 2 )   // Result: 10
  4758.  
  4759. See Also: A_MIN() A_SCAN()
  4760.  
  4761.  
  4762.  
  4763. ───────────────────────────────────────────────────────────────────────────────
  4764.  A_MIN()
  4765.  Return the smallest value found in a given range of an array
  4766. ───────────────────────────────────────────────────────────────────────────────
  4767.  
  4768.  Syntax
  4769.  
  4770.     A_MIN( <aTarget>, [<idxPos>], [<nCount>] )
  4771.  
  4772.  Arguments
  4773.  
  4774.     <aTarget> is the numeric type array to evaluate.
  4775.  
  4776.     <idxPos> is the position in the target array of the first element
  4777.     to be evaluated.  If not specified, A_MIN() begins its search on
  4778.     the first element in the array.
  4779.  
  4780.     <nCount> is the number of elements to evaluate. The default is all
  4781.     elements starting at <idxPos> until the end of the row in the
  4782.     current dimension.
  4783.  
  4784.  Returns
  4785.  
  4786.     A_MIN() returns an index to the element which has the minimum
  4787.     value found in the specified range.
  4788.  
  4789.  Description
  4790.  
  4791.     A_MIN() evaluates every element in the specified range of a
  4792.     numeric type array and returns an index to that element which has
  4793.     the lowest value.
  4794.  
  4795.  
  4796.  Examples
  4797.  
  4798.     // Declare a two dimensional (UI)nteger array
  4799.     LOCAL rows, cols, x
  4800.     
  4801.     rows = 10
  4802.     cols = 20
  4803.     auInteger = A_DECLARE( "UI", rows, cols )
  4804.     
  4805.     // Fill the second row of the array with increasing
  4806.     // integer values 1 - 20
  4807.     FOR x = 1 to 20
  4808.        A_STORE( auInteger, x, A_( 2, x ) )
  4809.     NEXT
  4810.     
  4811.     // Fetch the minimum value in the first half of the
  4812.     // second row.
  4813.     ? A_MIN( auInteger, A_( 2, 1 ), cols / 2 )   // Result: 1
  4814.  
  4815.  
  4816.  
  4817. See Also: A_MAX() A_SCAN()
  4818.  
  4819.  
  4820.  
  4821. ───────────────────────────────────────────────────────────────────────────────
  4822.  A_MINUS()
  4823.  Subtract all elements of an array by a value or an array of values
  4824. ───────────────────────────────────────────────────────────────────────────────
  4825.  
  4826.  Syntax
  4827.  
  4828.     A_MINUS( <aTarget>,
  4829.              <nValue> | <aValue>,
  4830.              [<aSource>] )
  4831.  
  4832.  Arguments
  4833.  
  4834.     <aTarget> is the array to be modified.  If <aSource> is not
  4835.     specified then each element of <aTarget> will be subtracted by the
  4836.     <nValue> or element by element by <aValue>.
  4837.  
  4838.     <nValue> or <aValue> is either a value or an array of values to be
  4839.     subtracted.
  4840.  
  4841.     <aSource> is an optional array of values.  If specified, then each
  4842.     element of <aTarget> will be filled with the corresponding value
  4843.     in <aSource> subtracted by <aValue> or <nValue>.
  4844.  
  4845.  Returns
  4846.  
  4847.     Although there is no return value, the <aTarget> array is modified.
  4848.  
  4849.  Description
  4850.  
  4851.     A_MINUS() provides a means to perform a subtraction of every
  4852.     element in the <aSource> array if specified or the <aTarget> array
  4853.     if not.  Each element of the <aSource> or <aTarget> array has
  4854.     <nValue> or <aValue> subtracted from it.  The result of the
  4855.     subtraction replaces the value in the <aTarget> array.
  4856.  
  4857.     A_MINUS() can be performed on any integer or floating point type
  4858.     array. These include the (T)iny, (I)nteger, (L)ong, (F)loat and
  4859.     (D)ouble.  Mixing of these types is allowed.
  4860.  
  4861.  Notes
  4862.  
  4863.     If the <aTarget> and the <aSource> arrays are not the same
  4864.     dimensions, the results will be a subtraction element for element
  4865.     as the arrays are aligned in memory.  See chapter two for how
  4866.     arrays are aligned in memory.
  4867.  
  4868.  Examples
  4869.  
  4870.     // Declare three double type arrays for this function.
  4871.     LOCAL rows, cols
  4872.     
  4873.     rows = 10
  4874.     cols = 20
  4875.     aSource = A_DECLARE( "D", rows, cols )
  4876.     aTarget = A_DECLARE( "D", rows, cols )
  4877.     aSubMe  = A_DECLARE( "D", rows, cols )
  4878.     
  4879.     // Fill the target array with 10's
  4880.     A_FILL( aTarget, 10, A_(1, 1), rows * cols )
  4881.     
  4882.     // Subtract 2 from every element in the target array
  4883.     A_MINUS( aTarget, 2 )
  4884.     ? A_RETRIEVE( aTarget, A_( 4, 5 ) )    // Result: 8.0
  4885.     
  4886.     
  4887.     // Fill the source array with 10's
  4888.     A_FILL( aSource, 10, A_(1, 1), rows * cols )
  4889.     
  4890.     // Subtract five from every element in the source array and
  4891.     // put the result in the target array.
  4892.     A_MINUS( aTarget, 5, aSource )
  4893.     ? A_RETRIEVE( aTarget, A_( 4, 5 ) )    // Result: 5.0
  4894.     
  4895.     
  4896.     // Fill the "subtract me" array with 4's
  4897.     // Remember the source array still has all 10's
  4898.     A_FILL( aSubMe, 4, A_(1, 1), rows * cols )
  4899.     
  4900.     // Subtract from every element in the source array the
  4901.     // value in every matching element of the "subtract me"
  4902.     // array and put the result in the target array.
  4903.     A_MINUS( aTarget, aSubMe, aSource )
  4904.     ? A_RETRIEVE( aTarget, A_( 4, 5 ) )    // Result: 6.0
  4905.  
  4906.  
  4907. See Also: A_MULTIPLY() A_PLUS() A_DIVIDE()
  4908.  
  4909.  
  4910.  
  4911. ───────────────────────────────────────────────────────────────────────────────
  4912.  A_MULTIPLY()
  4913.  Multiply all elements of an array by a value or an array of values
  4914. ───────────────────────────────────────────────────────────────────────────────
  4915.  
  4916.  Syntax
  4917.  
  4918.     A_MULTIPLY(  <aTarget>,
  4919.                    [<nValue> | <aValues>],
  4920.                    [<aSource>] )
  4921.  
  4922.  Arguments
  4923.  
  4924.     <aTarget> is the array to be modified.  If <aSource> is not
  4925.     specified then each element of <aTarget> will be multiplied by the
  4926.     <nValue> or element by element by <aValue>.
  4927.  
  4928.     <nValue> or <aValue> is either a value or an array of values to be
  4929.     multiplied.
  4930.  
  4931.     <aSource> is an optional array of values.  If specified, then each
  4932.     element of <aTarget> will be filled with the corresponding value
  4933.     in <aSource> multiplied by <aValue> or <nValue>.
  4934.  
  4935.  Returns
  4936.  
  4937.     Although there is no return value, the <aTarget> array is modified.
  4938.  
  4939.  Description
  4940.  
  4941.     A_MULTIPLY() provides a means to perform a multiplication of every
  4942.     element in the <aSource> array if specified or the <aTarget> array
  4943.     if not. Each element of the <aSource> or <aTarget> array will be
  4944.     multiplied by <nValue> or <aValue>.  The result of the
  4945.     multiplication replaces the value in the <aTarget> array.
  4946.  
  4947.     A_MULTIPLY() can be performed on any integer or floating point
  4948.     type array.  These include the (T)iny, (I)integer, (L)ong, (F)loat
  4949.     and (D)ouble (both signed and unsigned integers, of course).
  4950.     Mixing of these types is allowed, however, if the <aTarget> array
  4951.     is of integer type, decimals will be truncated.
  4952.  
  4953.  Notes
  4954.  
  4955.     If the <aTarget> and the <aSource> arrays are not the same
  4956.     dimensions, the results will be a multiplication element for
  4957.     element as the arrays are aligned in memory.  See chapter two for
  4958.     how arrays are aligned in memory.
  4959.  
  4960.  Examples
  4961.  
  4962.     // Declare three double type arrays for this function.
  4963.     LOCAL rows, cols
  4964.     
  4965.     rows = 10
  4966.     cols = 20
  4967.     aSource = A_DECLARE( "D", rows, cols )
  4968.     aTarget = A_DECLARE( "D", rows, cols )
  4969.     aMultiplier = A_DECLARE( "D", rows, cols )
  4970.     
  4971.     // Fill the target array with 10's
  4972.     A_FILL( aTarget, 10, A_(1, 1), rows * cols )
  4973.     
  4974.     // Multiply every element in the target array by 2
  4975.     A_MULTIPLY( aTarget, 2 )
  4976.     ? A_RETRIEVE( aTarget, A_( 4, 5 ) )    // Result: 20.0
  4977.     
  4978.     
  4979.     // Fill the source array with 10's
  4980.     A_FILL( aSource, 10, A_(1, 1), rows * cols )
  4981.     
  4982.     // Multiply every element in the source array by five and
  4983.     // put the result in the target array.
  4984.     A_MULTIPLY( aTarget, 5, aSource )
  4985.     ? A_RETRIEVE( aTarget, A_( 4, 5 ) )    // Result: 50.0
  4986.     
  4987.     
  4988.     // Fill the multiplier array with 4's
  4989.     // Remember the source array still has all 10's
  4990.     A_FILL( aMultiplier, 4, A_(1, 1), rows * cols )
  4991.     
  4992.     // Multiply every element in the source array by every element
  4993.     // in the multiplier array and put the result in the target
  4994.     // array.
  4995.     A_MULTIPLY( aTarget, aMultiplier, aSource )
  4996.     ? A_RETRIEVE( aTarget, A_( 4, 5 ) )    // Result: 40.0
  4997.  
  4998.  
  4999.  
  5000.  
  5001. See Also: A_DIVIDE() A_PLUS() A_MINUS()
  5002.  
  5003.  
  5004.  
  5005. ───────────────────────────────────────────────────────────────────────────────
  5006.  A_PLUS()
  5007.  Add all elements of an array by a value or an array of values
  5008. ───────────────────────────────────────────────────────────────────────────────
  5009.  
  5010.  Syntax
  5011.  
  5012.     A_PLUS(  <aTarget>,
  5013.              [<nValue> | <aValues>],
  5014.              [<aSource>] )
  5015.  
  5016.  Arguments
  5017.  
  5018.     <aTarget> is the array to be modified.  If <aSource> is not
  5019.     specified then each element of <aTarget> will be added to <nValue>
  5020.     or element by element by <aValue>.
  5021.  
  5022.     <nValue> or <aValue> is either a value or an array of values to be
  5023.     added.
  5024.  
  5025.     <aSource> is an optional array of values.  If specified, then each
  5026.     element of <aTarget> will be filled with the corresponding value
  5027.     in <aSource> added to <aValue> or <nValue>.
  5028.  
  5029.  Returns
  5030.  
  5031.     Although there is no return value, the <aTarget> array is
  5032.     modified.
  5033.  
  5034.  Description
  5035.  
  5036.     A_PLUS() provides a means to perform an addition of every element
  5037.     in the <aSource> array if specified or the <aTarget> array if not.
  5038.     Each element of the <aSource> or <aTarget> array will be added to
  5039.     <nValue> or <aValue>.  The result of the addition is placed in the
  5040.     <aTarget> array.
  5041.  
  5042.     A_PLUS() can be performed on any integer or floating point type
  5043.     array. These include the (T)iny, (I)integer, (L)ong, (F)loat and
  5044.     (D)ouble (both signed and unsigned integers, of course).  Mixing
  5045.     of these types is allowed, however, if the <aTarget> array is of
  5046.     integer type, decimals will be truncated.
  5047.  
  5048.  Notes
  5049.  
  5050.     If the <aTarget> and the <aSource> arrays are not the same
  5051.     dimensions, the results will be an addition element for element as
  5052.     the arrays are aligned in memory.  See chapter two for how arrays
  5053.     are aligned in memory.
  5054.  
  5055.  Examples
  5056.  
  5057.     // Declare three double type arrays for this function.
  5058.     LOCAL rows, cols
  5059.     
  5060.     rows = 10
  5061.     cols = 20
  5062.     aSource = A_DECLARE( "D", rows, cols )
  5063.     aTarget = A_DECLARE( "D", rows, cols )
  5064.     aAddMe  = A_DECLARE( "D", rows, cols )
  5065.     
  5066.     // Fill the target array with 10's
  5067.     A_FILL( aTarget, 10, A_(1, 1), rows * cols )
  5068.     
  5069.     // Add 2 to every element in the target array
  5070.     A_ADD( @aTarget, 2 )
  5071.     ? A_RETRIEVE( aTarget, A_( 4, 5 ) )    // Result: 12.0
  5072.     
  5073.     
  5074.     // Fill the source array with 10's
  5075.     A_FILL( aSource, 10, A_(1, 1), rows * cols )
  5076.     
  5077.     // Add five to every element in the source array and
  5078.     // put the result in the target array.
  5079.     A_ADD( @aTarget, 5, aSource )
  5080.     ? A_RETRIEVE( aTarget, A_( 4, 5 ) )    // Result: 15.0
  5081.     
  5082.     
  5083.     // Fill the "add me" array with 4's
  5084.     // Remember the source array still has all 10's
  5085.     A_FILL( aAddMe, 4, A_(1, 1), rows * cols )
  5086.     
  5087.     // Add to every element in the source array the
  5088.     // value in every matching element of the "add me"
  5089.     // array and put the result in the target array.
  5090.     A_ADD( @aTarget, aAddMe, aSource )
  5091.     ? A_RETRIEVE( aTarget, A_( 4, 5 ) )    // Result: 14.0
  5092.     
  5093.  
  5094.  
  5095. See Also: A_DIVIDE() A_MULTIPLY() A_MINUS()
  5096.  
  5097.  
  5098.  
  5099. ───────────────────────────────────────────────────────────────────────────────
  5100.  A_RETRIEVE()
  5101.  Return the value of a specified element of an array
  5102. ───────────────────────────────────────────────────────────────────────────────
  5103.  
  5104.  Syntax
  5105.  
  5106.     A_RETRIEVE(  <aTarget>,
  5107.                  <idxPos> )    ->    expValue
  5108.  
  5109.  Arguments
  5110.  
  5111.     <aTarget> is the array to return a value from.
  5112.  
  5113.     <idxPos> points to the element whose value is to be returned.
  5114.  
  5115.  Returns
  5116.  
  5117.     A_RETRIEVE() returns the value of the element in <aTarget> pointed
  5118.     to by <idxPos>.  The type of the value will always be the same
  5119.     type as that of the array unless an error is encountered.  In the
  5120.     case of an error, the return value will be (.F.).
  5121.  
  5122.  Description
  5123.  
  5124.     A_RETRIEVE() is used to get the value of an element from a FlexFile
  5125.     array.
  5126.  
  5127.  Notes
  5128.  
  5129.   ■ If a numeric value was stored as a double or float, the value
  5130.     returned will be equivalent to the value stored, but if you display the
  5131.     value without a PICTURE clause, it will show the number of decimals
  5132.     according to the value of SET DECIMAL TO (which is not necesarily the
  5133.     same number of decimals that were visable when the value that was
  5134.     A_STORE()ed).
  5135.  
  5136.  
  5137.  Examples
  5138.  
  5139.     // Declare a two dimensional (UL)ong integer array
  5140.     LOCAL rows, cols
  5141.     
  5142.     rows = 10
  5143.     cols = 20
  5144.     auLong = A_DECLARE( "UL", rows, cols )
  5145.     
  5146.     // Fill the 5th row with 100,000
  5147.     A_FILL( auLong, 123456, A_(5, 1), cols )
  5148.     
  5149.     // Multiply the value in the fifth row, fourth column
  5150.     // by five and print the result.
  5151.     ? A_RETRIEVE( auLong, A_( 5, 4 ) ) * 5      // Result: 617280
  5152.  
  5153. See Also: A_STORE() A_TYPE() A_DECLARE()
  5154.  
  5155.  
  5156.  
  5157. ───────────────────────────────────────────────────────────────────────────────
  5158.  A_SCAN()
  5159.  Scan an array or part of an array for an expression
  5160. ───────────────────────────────────────────────────────────────────────────────
  5161.  
  5162.  Syntax
  5163.  
  5164.     A_SCAN(  <aTarget>,
  5165.              <expSearch>,
  5166.              [<idxPos>],
  5167.              [<nCount>] )    ->    nAbsPos
  5168.  
  5169.  Arguments
  5170.  
  5171.     <aTarget> The array to scan.
  5172.  
  5173.     <expSearch> An expression that evaluates to the same type as the
  5174.     <aTarget> array.
  5175.  
  5176.     <idxPos> is the first position to in the <aTarget> array to be
  5177.     scanned.  If not specified, the default value is the first element
  5178.     of the array.
  5179.  
  5180.     <nCount> is the number of elements to scan starting at <idxPos>.
  5181.     If not specified, elements are searched to the end of the array.
  5182.  
  5183.  Returns
  5184.  
  5185.     A_SCAN() returns an integer which is the absolute index pointer to
  5186.     the first element found that matches .  If no match is found
  5187.     A_SCAN() returns 0.  The <nAbsPos> can and should be used in any
  5188.     further references to that element (see example below).
  5189.  
  5190.  Description
  5191.  
  5192.     A_SCAN() is used to search a FlexFile array for a value.  A_SCAN()
  5193.     will return an error if <expSearch> evaluates to a different type
  5194.     than the <aTarget> array.
  5195.  
  5196.     Wrapping will occur if <nCount> goes beyond the current row
  5197.     pointed to by <idxPos>.  For example, if you have a two
  5198.     dimensional array with accounts represented by the first dimension
  5199.     and 12 prior period amounts in the second dimension, and you
  5200.     wanted to scan the first quarter (i.e.  3 periods) for a value,
  5201.     making <nCount> three times the number of accounts will "wrap"
  5202.     around three periods.  See the discussion on wrapping in the
  5203.     Arrays Chapter.
  5204.  
  5205.  Examples
  5206.  
  5207.     LOCAL ffArray, ptr, rows, cols
  5208.     
  5209.     rows = 5
  5210.     cols = 8
  5211.     
  5212.     // Declare a FlexFile floating point type array.
  5213.     ffArray = A_DECLARE( 'F', 5, 8 )
  5214.     
  5215.     // Store a couple of values.
  5216.     A_STORE( ffArray, 1234.56, A_( 3, 3 ) )
  5217.     A_STORE( ffArray, 789.10, A_(4, 4) )
  5218.     
  5219.     // Scan the entire array...
  5220.     ptr = A_SCAN( ffArray, 789.10 )
  5221.     ? A_RETRIEVE( ffArray, ptr )          // Result: 789.10
  5222.     
  5223.     // Scan starting at the first element in the fourth row.
  5224.     ? A_SCAN( ffArray, 1234.56, A( 4, 1 ) )   // Result: 0
  5225.     
  5226.     // Scan starting at the first element in the third row.
  5227.     ptr = A_SCAN( ffArray, 1234.56, A_( 3, 1 ) )
  5228.     ? A_RETRIEVE( ffArray, ptr )          // Result: 1234.56
  5229.     
  5230.     // Scan starting at the first element in the second row
  5231.     // but only count for one row.
  5232.     ? A_SCAN( ffArray, 1234.56, A_( 2, 1 ), cols )  // Result: 0
  5233.     
  5234.  
  5235.  
  5236. See Also: A_STORE() A_DECLARE() A_RETRIEVE()
  5237.  
  5238.  
  5239.  
  5240. ───────────────────────────────────────────────────────────────────────────────
  5241.  A_SCROLL()
  5242.  Scroll all or part of an array
  5243. ───────────────────────────────────────────────────────────────────────────────
  5244.  
  5245.  Syntax
  5246.  
  5247.     A_SCROLL(    <aTarget>,
  5248.                  [<idxPos>],
  5249.                  [<nCount>],
  5250.                  [<nMagnitude>] )
  5251.  
  5252.  Arguments
  5253.  
  5254.     <aTarget> is the array in which elements will be scrolled.
  5255.  
  5256.     <idxPos> is the first position to in the <aTarget> array to be
  5257.     scrolled.  If not specified, the default value is the first
  5258.     element.
  5259.  
  5260.     <nCount> is the number of elements to be scrolled starting at
  5261.     <idxPos>. If not specified, elements are scrolled to the end of
  5262.     the array.
  5263.  
  5264.     <nMagnitude> indicates how far and in what direction to scroll the
  5265.     array. A positive value scrolls the elements up (toward the
  5266.     beginning); a negative value scrolls the elements down (towards
  5267.     the end).  If no value is specified, the defined range is scrolled
  5268.     one element up.
  5269.  
  5270.  Returns
  5271.  
  5272.     None.
  5273.  
  5274.  Description
  5275.  
  5276.     A_SCROLL() scrolls all or a portion of a FlexFile array
  5277.     <nMagnitude> number of elements.  All elements at the end of the
  5278.     scroll are lost and the new elements are initialized to null.  Do
  5279.     not confuse FlexFile's null with Clipper's NIL.  A numeric null is
  5280.     0, a logical null is (.F.) and a string null is "".
  5281.  
  5282.     Wrapping will occur if <nCount> goes beyond the current row
  5283.     pointed to by <idxPos>.  For example, if you have a two
  5284.     dimensional array with accounts represented by the first dimension
  5285.     and 12 prior period amounts in the second dimension, and you
  5286.     wanted to scroll the first quarter (i.e. 3 periods) up in the
  5287.     array, making <nCount> three times the number of accounts will
  5288.     "wrap" the scroll.  Three periods worth of amounts will be
  5289.     scrolled out of the array and three periods of 0's will be filled.
  5290.     See the discussion on arrays in chapter 2 for more information on
  5291.     this feature.
  5292.  
  5293.  Examples
  5294.  
  5295.     LOCAL ffArray, accounts, periods
  5296.     
  5297.     accounts = 50
  5298.     periods = 12
  5299.     
  5300.     // Declare a FlexFile double precision type array.
  5301.     ffArray = A_DECLARE( 'D', periods, accounts )
  5302.     
  5303.     // Close out a quarter by scrolling three periods.
  5304.     // (i.e. scroll all accounts by 3 periods.)
  5305.     A_SCROLL( ffArray, , , -(accounts * 3) )
  5306.     
  5307.     // Insert a new account just in front of the 7th account.
  5308.     accounts++
  5309.     A_SIZE( @ffArray, periods, accounts )
  5310.     FOR x = 1 to periods
  5311.        A_SCROLL( ffArray, A_( x, 7 ), accounts - 7, -1 )
  5312.     NEXT
  5313.     
  5314.  
  5315.  
  5316. See Also: A_INS() A_DEL() A_SCAN()
  5317.  
  5318.  
  5319.  
  5320. ───────────────────────────────────────────────────────────────────────────────
  5321.  A_SIZE()
  5322.  Dynamically change the size or dimensions of an array
  5323. ───────────────────────────────────────────────────────────────────────────────
  5324.  
  5325.  Syntax
  5326.  
  5327.     A_SIZE(  @<aTarget>,
  5328.              <nElements>,
  5329.              [, <nElements>...] )   ->   lSuccess
  5330.  
  5331.  Arguments
  5332.  
  5333.     <aTarget> is the array to re-size.  It must be passed-by-
  5334.     reference.  A_SIZE() cannot resize binary type arrays.
  5335.  
  5336.     <nElements> are the new dimensions of the array.
  5337.  
  5338.  Returns
  5339.  
  5340.     A_SIZE() returns (.T.) if the function was successful, otherwise,
  5341.     it returns (.F.).   In addition, the aTarget array is modified.
  5342.  
  5343.  Description
  5344.  
  5345.     A_SIZE() modifies the dimensions of the @<aTarget>.  If the
  5346.     array is increased in size, the new elements will be added to the
  5347.     end of the array and assigned to null.  If the array is decreased
  5348.     in size, the data at the end of the array will be lost.
  5349.  
  5350.     You cannot change the number of dimensions with A_SIZE(), rather,
  5351.     you can change only their magnitude.
  5352.  
  5353.  Examples
  5354.  
  5355.     // Declare a two dimensional (L)ong integer array
  5356.     LOCAL rows, cols, x, y, z := 0
  5357.     
  5358.     rows = 10
  5359.     cols = 20
  5360.     aLong = A_DECLARE( "L", rows, cols )
  5361.     
  5362.     // Fill the array with increasing values.
  5363.     FOR x = 1 to rows
  5364.        FOR y = 1 to cols
  5365.           A_STORE( aLong, z++, A_( x, y ) )
  5366.        NEXT
  5367.     NEXT
  5368.     
  5369.     // Increase the size of the array by 10 rows
  5370.     A_SIZE( @aLong, rows + 10, cols )
  5371.     
  5372.     // Show some results.
  5373.     ? A_RETRIEVE( aLong, 10, 20 )      // Result: 200
  5374.     ? A_RETRIEVE( aLong, 11,  1 )      // Result:   0
  5375.     
  5376.  
  5377.  
  5378.  
  5379. See Also: A_ADD() A_DEL() A_INS()
  5380.  
  5381.  
  5382.  
  5383. ───────────────────────────────────────────────────────────────────────────────
  5384.  A_SORT()
  5385.  Sort all or part of an array in ascending or descending order
  5386. ───────────────────────────────────────────────────────────────────────────────
  5387.  
  5388.  Syntax
  5389.  
  5390.     A_SORT(  <aTarget>,
  5391.              [<idxPos>],
  5392.              [<nCount>],
  5393.              [<cOrder>] )
  5394.  
  5395.  Arguments
  5396.  
  5397.     <aTarget> is the array to be sorted.  A_SORT will not sort a Binary
  5398.     "logical" type array.
  5399.  
  5400.     <idxPos> is the position in the <aTarget> array to begin the sort.
  5401.     If not specified, the default value is one.
  5402.  
  5403.     <nCount> is the number of elements beginning at <idxPos> to sort.
  5404.     If not specified, all elements are sorted to the end of the row in
  5405.     the current dimension.
  5406.  
  5407.     <cOrder> is either "Ascending" or "Descending".  Only the first
  5408.     letter is significant.  If not specified, the sort is made
  5409.     "Ascending".
  5410.  
  5411.  Returns
  5412.  
  5413.     None.
  5414.  
  5415.  Description
  5416.  
  5417.     A_SORT() will sort all or part of a FlexFile array.  If <cOrder>
  5418.     is ascending, elements with higher values are stored at the top
  5419.     (beginning) of the array.  If <cOrder> is descending, elements
  5420.     with lower values are stored at the top of the array.
  5421.  
  5422.     Wrapping will occur if <nCount> goes beyond the current row
  5423.     pointed to by <idxPos>.
  5424.  
  5425.  Examples
  5426.  
  5427.     // Declare a two dimensional (C)haracter array
  5428.     LOCAL rows, cols, x, y, z
  5429.     
  5430.     rows = 10
  5431.     cols = 20
  5432.     z = 1
  5433.     aChar = A_DECLARE( "C", rows, cols )
  5434.     
  5435.     // Fill the array with increasing character values.
  5436.     FOR x = 1 to rows
  5437.        FOR y = 1 to cols
  5438.           z++
  5439.           A_STORE( aChar, chr(z), A_( x, y ) )
  5440.        NEXT
  5441.     NEXT
  5442.     
  5443.     // Sort the first row in descending order
  5444.     A_SORT( aChar, A_( 1, 1 ), cols, 'D' )
  5445.     
  5446.     // Show the results
  5447.     ? A_RETRIEVE( aChar, A_( 1, 1 ) )    // Result: 
  5448.     ? A_RETRIEVE( aChar, A_( 1, 20) )    // Result: 
  5449.     
  5450.  
  5451. See Also: A_SCAN()
  5452.  
  5453.  
  5454.  
  5455. ───────────────────────────────────────────────────────────────────────────────
  5456.  A_STORE()
  5457.  Store an expression into an element of an array
  5458. ───────────────────────────────────────────────────────────────────────────────
  5459.  
  5460.  Syntax
  5461.  
  5462.     A_STORE( <aTarget>,
  5463.              <expValue>,
  5464.              <idxPos> )    ->    lSuccess
  5465.  
  5466.  Arguments
  5467.  
  5468.     <aTarget> is the array in which to store <expValue>.
  5469.  
  5470.     <expValue> is any simple Clipper expression that evaluates to the
  5471.     same type as the array.
  5472.  
  5473.     <idxPos> is the index to the element whose value will become
  5474.     <expValue>.
  5475.  
  5476.  Returns
  5477.  
  5478.     A_STORE() returns (.T.) if successful, otherwise, (.F.).
  5479.  
  5480.  Description
  5481.  
  5482.     A_STORE() stores a value in a FlexFile type array.  The value
  5483.     being stored must be of the same type as that of the array.
  5484.     Storing a value with a different type than the array is considered
  5485.     an error and A_STORE() will return (.f.).
  5486.  
  5487.     ┌────────────────────────── WARNING ───────────────────────────┐
  5488.     │ You must use A_KILL() to release the data that has been type │
  5489.     │ A_STORE()d to a string type array before allowing the array  │
  5490.     │ to fall out of scope.                                        │
  5491.     └──────────────────────────────────────────────────────────────┘
  5492.  
  5493.  Examples
  5494.  
  5495.     // Declare a two dimensional (C)haracter array
  5496.     LOCAL rows, cols, x, y, z
  5497.     
  5498.     rows = 10
  5499.     cols = 20
  5500.     z = 1
  5501.     aChar = A_DECLARE( "C", rows, cols )
  5502.     
  5503.     // Fill the array with increasing character values.
  5504.     FOR x = 1 to rows
  5505.        FOR y = 1 to cols
  5506.           z++
  5507.           A_STORE( aChar, chr(z), A_( x, y ) )
  5508.        NEXT
  5509.     NEXT
  5510.     
  5511.     // Print out the results: All ASCII characters from one
  5512.     // to 200.  If you run this program it will beep an sqauk
  5513.     // and generally look ugly.
  5514.     FOR x = 1 to rows
  5515.        FOR y = 1 to cols
  5516.           z++
  5517.           ? A_RETRIEVE( aChar, A_( x, y ) )
  5518.        NEXT
  5519.     NEXT
  5520.     
  5521.  
  5522.  
  5523. See Also: A_KILL() A_FILL() A_RETRIEVE()
  5524.  
  5525.  
  5526.  
  5527. ───────────────────────────────────────────────────────────────────────────────
  5528.  A_TYPE()
  5529.  Return the type of an array
  5530. ───────────────────────────────────────────────────────────────────────────────
  5531.  
  5532.  Syntax
  5533.  
  5534.     A_TYPE( <aTarget> )   ->   cType
  5535.  
  5536.  Arguments
  5537.  
  5538.     <aTarget> is the array whose type is returned.
  5539.  
  5540.  Returns
  5541.  
  5542.     A_TYPE() returns the type of the <aTarget> as a character
  5543.     string.
  5544.  
  5545.  Description
  5546.  
  5547.     A_TYPE() returns the type of a FlexFile array.  If the array is of
  5548.     integer type and was declared as unsigned, then a "U" will precede
  5549.     the type.
  5550.  
  5551.     The return value is a character string such as "L" for a long
  5552.     integer or "UL" for an unsigned long integer.
  5553.  
  5554.     Appendix C lists all the array types and sizes.
  5555.  
  5556.  
  5557.  Examples
  5558.  
  5559.     // Setup seven variables of differing array types.
  5560.     LOCAL aLogical  ,;
  5561.           aChar     ,;
  5562.           aTiny     ,;
  5563.           auTiny    ,;
  5564.           aInteger  ,;
  5565.           auInteger ,;
  5566.           aLong     ,;
  5567.           auLong    ,;
  5568.           aString   ,;
  5569.           aFloat    ,;
  5570.           aDouble
  5571.     
  5572.     // Declare an array for each possible type.
  5573.     aLogical  = A_DECLARE( 'B', 10 )
  5574.     aChar     = A_DECLARE( 'C', 10 )
  5575.     aTiny     = A_DECLARE( 'T', 10 )
  5576.     auTiny    = A_DECLARE( 'UT', 10 )
  5577.     aInteger  = A_DECLARE( 'I', 10 )
  5578.     auInteger = A_DECLARE( 'UI', 10 )
  5579.     aLong     = A_DECLARE( 'L', 10 )
  5580.     auLong    = A_DECLARE( 'UL', 10 )
  5581.     aString   = A_DECLARE( 'S', 10 )
  5582.     aFloat    = A_DECLARE( 'F', 10 )
  5583.     aDouble   = A_DECLARE( 'D', 10 )
  5584.     
  5585.     // Show the type of each array
  5586.     ? A_TYPE( aLogical )              //  Result: B
  5587.     ? A_TYPE( aChar    )              //  Result: C
  5588.     ? A_TYPE( aTiny    )              //  Result: T
  5589.     ? A_TYPE( auTiny   )              //  Result: UT
  5590.     ? A_TYPE( aInteger )              //  Result: I
  5591.     ? A_TYPE( auInteger)              //  Result: UI
  5592.     ? A_TYPE( aLong    )              //  Result: L
  5593.     ? A_TYPE( auLong   )              //  Result: UL
  5594.     ? A_TYPE( aString  )              //  Result: S
  5595.     ? A_TYPE( aFloat   )              //  Result: F
  5596.     ? A_TYPE( aDouble  )              //  Result: D
  5597.     
  5598.  
  5599.  
  5600. See Also: A_DECLARE()
  5601.  
  5602. Error Codes Introduction
  5603.  
  5604.    Changes:
  5605.  
  5606.    The FlexFile error system has been changed significatly in
  5607.    releases after 1.01.  The main differences are that:
  5608.  
  5609.      1. Any call to any FlexFile V_xxx() function will reset
  5610.      the V_ERROR() to zero.  Any call to any A_xxx() function
  5611.      will reset the A_ERROR() to zero.  This prevents an error
  5612.      setting from appearing in a context other than what
  5613.      caused it.
  5614.  
  5615.      2. Two error codes are now maintained.  One for the V_xxx()
  5616.      functions and the other for the A_xxx() functions.
  5617.  
  5618.      3. Calling either V_ERROR() or A_ERROR() no longer resets
  5619.      the error code.  Therefore, you can now make multiple calls
  5620.      to the desired error reporting routine without loosing the
  5621.      error.
  5622.  
  5623.  
  5624.    General Information
  5625.  
  5626.    The FlexFile error system is accessed by either of the two
  5627.    functions A_ERROR() or V_ERROR().  These functions can be
  5628.    accessed from the debugger's expression window or placed
  5629.    directly in your code.  Of course, if you plan to use either
  5630.    function from the debugger you must refer to them with either
  5631.    the EXTERNAL command or explicitly within your code in order
  5632.    for the LINKER to include them in your application.
  5633.  
  5634.    The error functions will report the last error that
  5635.    was trapped by FlexFile as a numeric integer.  For example, if
  5636.    you attempt to V_USE() a file which is already being used
  5637.    exclusivly by another user on a network, V_USE() will return a
  5638.    -1 and V_ERROR() will return 5052.  However, if you do not
  5639.    test the V_ERROR() return value until after you try to
  5640.    V_REPLACE() a value (remember no file was opened), then
  5641.    V_ERROR() will return 7301 indicatating a V_REPLACE() error.
  5642.  
  5643.    Ignore any numbers in the 10's and 1'n place in the return
  5644.    value from the error functions;  these are used by the
  5645.    FlexFile support staff.  So, for example, 7301 and 7302 both
  5646.    refer to the 7300 class of error.
  5647.  
  5648.    These functions, when called, reset the error value to zero
  5649.    which indicates that no error has occurred.
  5650.  
  5651. See Also: V_ERROR() A_ERROR()
  5652.  
  5653. ──────────────────────────────────────────────────────────────────────────────
  5654. Error 0100      Not an array.lib type array.
  5655. ──────────────────────────────────────────────────────────────────────────────
  5656.  
  5657.  
  5658.    A parameter passed is not a FlexFile strongly typed array but
  5659.    should have been.
  5660.  
  5661.    The most usual cause of this problem is that a parameter is
  5662.    out of order in the parameter list of a FlexFile function or a
  5663.    Clipper array was passed instead of a FlexFile type array.
  5664.  
  5665. See Also: A_DECLARE()
  5666.  
  5667. ──────────────────────────────────────────────────────────────────────────────
  5668. Error 0300      Invalid A_DECLARE() dimensions
  5669. ──────────────────────────────────────────────────────────────────────────────
  5670.  
  5671.  
  5672.    An attempt was made to declare an array with greater than six
  5673.    dimensions or zero dimensions.
  5674.  
  5675. See Also: A_DECLARE()
  5676.  
  5677.  
  5678. ──────────────────────────────────────────────────────────────────────────────
  5679. Error 0400      Attempt to address an out of bounds element.
  5680. ──────────────────────────────────────────────────────────────────────────────
  5681.  
  5682.  
  5683.    An attempt was made to address an element which is outside  of
  5684.    the bounds of the FlexFile array.
  5685.  
  5686.    For example,  if you declare a single dimensional array with
  5687.    twenty elements and then try to access the twenty first
  5688.    element (or an element in the second or greater dimension),
  5689.    A_ERROR() will return 400.
  5690.  
  5691. See Also: A_RETRIEVE() A_DECLARE()
  5692.    
  5693.  
  5694. ──────────────────────────────────────────────────────────────────────────────
  5695. Error 0500      Attempt to declare an array larger than 65535 bytes.
  5696. ──────────────────────────────────────────────────────────────────────────────
  5697.  
  5698.  
  5699.    Because the elements of different FlexFile array types require
  5700.    different amounts of space, you must look at each array type
  5701.    to determine the maximum number of elements possible.
  5702.  
  5703.    The limiting factore in FlexFile arrays of every type is 65535
  5704.    bytes.  So, for example, an integer array which requires only
  5705.    two bytes per element will reach this limit when you attempt
  5706.    to declare an integer array of slightly more than 32,000
  5707.    elements.
  5708.  
  5709.    See the reference to A_DECLARE() for a table of array type and
  5710.    required sizes per element.
  5711.  
  5712. See Also: A_DECLARE()
  5713.  
  5714. ──────────────────────────────────────────────────────────────────────────────
  5715. Error 0600      Attempt to declare an array with an invalid type.
  5716. ──────────────────────────────────────────────────────────────────────────────
  5717.  
  5718.  
  5719.    The arrays type must be one that FlexFile recognizes.  These
  5720.    are listed in the A_DECLARE() function reference.
  5721.  
  5722. See Also: A_DECLARE()
  5723.  
  5724. ──────────────────────────────────────────────────────────────────────────────
  5725. Error 0700      Attempt to declare an array with invalid dimensions.
  5726. ──────────────────────────────────────────────────────────────────────────────
  5727.  
  5728.  
  5729.    A FlexFile type array may have a minimum of one and a maximum of
  5730.    six dimensions.
  5731.  
  5732. See Also: A_DECLARE()
  5733.  
  5734. ──────────────────────────────────────────────────────────────────────────────
  5735. Error 0800      Out of memory on an attempt to declare an array
  5736. ──────────────────────────────────────────────────────────────────────────────
  5737.  
  5738.  
  5739.    In S'87 and the initial release of Clipper 5.0 it is a fatal
  5740.    error when an attempt is made to declare an array larger than
  5741.    available memory.  However, this is a bug in 5.0 and when
  5742.    fixed this error will indicate that condition and the error
  5743.    system will be automatically called.
  5744.  
  5745. See Also: A_DECLARE()
  5746.  
  5747. ──────────────────────────────────────────────────────────────────────────────
  5748. Error 2000      Array type incompatible with function called.
  5749. ──────────────────────────────────────────────────────────────────────────────
  5750.  
  5751.  
  5752.    The array function called cannot operate on the type of the
  5753.    array passed.  For example, if you pass A_SORT() a binary type
  5754.    array, no sort will be performed and this error will be set.
  5755.  
  5756. See Also: A_SORT() A_SCAN()
  5757.  
  5758.  
  5759. ──────────────────────────────────────────────────────────────────────────────
  5760. Error 2100      Function called is not valid on binary arrays.
  5761. ──────────────────────────────────────────────────────────────────────────────
  5762.  
  5763.  
  5764.    Binary (logical) arrays are not supported by many of the FlexFile
  5765.    array functions.  For example, you cannot A_SCAN() an array for a
  5766.    logical (.t.) or (.f.) and you cannot A_SORT().  The FlexFile
  5767.    array functions which operate on binary arrays are:
  5768.  
  5769.                 A_STORE()
  5770.                 A_RETRIEVE()
  5771.                 A_LEN()
  5772.                 A_TYPE()
  5773.  
  5774.  
  5775. ──────────────────────────────────────────────────────────────────────────────
  5776. Error 2200      Divide by zero in a FlexFile array math function.
  5777. ──────────────────────────────────────────────────────────────────────────────
  5778.  
  5779.  
  5780.    FlexFile's math functions such as A_DIVIDE() are protected against
  5781.    a programmer error of division by zero.  In the event this error
  5782.    occurs, the division results in a zero value and this error is
  5783.    flagged.
  5784.  
  5785. See Also: A_DIVIDE()
  5786.  
  5787. ──────────────────────────────────────────────────────────────────────────────
  5788. Error 2300      A_COPY() used with incompatable array types
  5789. ──────────────────────────────────────────────────────────────────────────────
  5790.  
  5791.  
  5792.    An attempt was made to use A_COPY() on two different array types.
  5793.    A_COPY() must be performed on arrays of the same type.
  5794.  
  5795.  
  5796. See Also: A_COPY()
  5797.  
  5798. ──────────────────────────────────────────────────────────────────────────────
  5799. Error 3000      Bad or missing parameter in array function.
  5800. ──────────────────────────────────────────────────────────────────────────────
  5801.  
  5802.  
  5803.    A parameter was passed to a FlexFile array function that is not
  5804.    the correct type or a parameter is required that was not passed.
  5805.  
  5806.    The most usual cause of this problem is that a parameter is
  5807.    out of order in the parameter list of a FlexFile function or a
  5808.    parameter was inadvertently omitted.
  5809.  
  5810.  
  5811. ──────────────────────────────────────────────────────────────────────────────
  5812. Error 3100      A_SIZE() error in dimensions.
  5813. ──────────────────────────────────────────────────────────────────────────────
  5814.  
  5815.  
  5816.    A_SIZE() cannot change the number of an arrays dimensions, rather,
  5817.    it can only change the magnitude of each dimension.  An attempt
  5818.    was made to change the number of dimensions.
  5819.  
  5820.  
  5821. See Also: A_SIZE() A_ADD()
  5822.  
  5823. ──────────────────────────────────────────────────────────────────────────────
  5824. Error 5000      Unable to open file.
  5825. ──────────────────────────────────────────────────────────────────────────────
  5826.  
  5827.  
  5828.    This error can result from many different situations:
  5829.  
  5830.       Disk access denied (disk full).
  5831.       Create error.
  5832.       Impropper file name (directory does not exist).
  5833.       File opened exclusively by other user.
  5834.  
  5835.  
  5836. See Also: V_USE() V_VLF2FILE() network.ngo:Network Programming
  5837.  
  5838. ──────────────────────────────────────────────────────────────────────────────
  5839. Error 5200      Attempt to lock header failed.
  5840. ──────────────────────────────────────────────────────────────────────────────
  5841.  
  5842.  
  5843.    This error occurs when V_USE() fails to get a lock on the header
  5844.    of the DBV file.
  5845.  
  5846. See Also: V_USE() "Error 5000"
  5847.  
  5848. ──────────────────────────────────────────────────────────────────────────────
  5849. Error 5300      Out of memory.
  5850. ──────────────────────────────────────────────────────────────────────────────
  5851.  
  5852.  
  5853.    This error occurs when FlexFile fails to allocate memory using
  5854.    Clipper's extend system.  Because FlexFile requires very little
  5855.    memory, this is an unusual error and indicates extremely low memory
  5856.    conditions.
  5857.  
  5858.  
  5859.  
  5860. ──────────────────────────────────────────────────────────────────────────────
  5861. Error 6000      Invalid or missing parameter.
  5862. ──────────────────────────────────────────────────────────────────────────────
  5863.  
  5864.  
  5865.    This error occurs whenever FlexFile detects a parameter of the
  5866.    wrong type or a missing parameter when one is required.
  5867.  
  5868.    The most usual cause of this problem is that a parameter is
  5869.    out of order in the parameter list of a FlexFile function.
  5870.  
  5871. ──────────────────────────────────────────────────────────────────────────────
  5872. Error 6200      Bad pointer-field passed.
  5873. ──────────────────────────────────────────────────────────────────────────────
  5874.  
  5875.  
  5876.    FlexFile generates a six byte character string which points to
  5877.    data stored in a DBV file.  If you attempt to use anything but
  5878.    a FlexFile generated pointer-field in an attempt to access data
  5879.    in a DBV file, this error will be generated.  The single exception
  5880.    to this rule is an empty pointer-field which must be six (or more)
  5881.    spaces.
  5882.  
  5883.  
  5884. ──────────────────────────────────────────────────────────────────────────────
  5885. Error 6300      Invalid data type in v_replace().
  5886. ──────────────────────────────────────────────────────────────────────────────
  5887.  
  5888.  
  5889.    The valid data types for V_REPLACE() are defined in the V_REPLACE()
  5890.    function reference.  If FlexFile encounters a type which is not
  5891.    amoung these valid types, this error will be generated.
  5892.  
  5893.    In addition, if you make the mistake of using a pointer-field which
  5894.    points into one file as a pointer-field for a different file, FlexFile
  5895.    will again generate this error.  This is because the pointer-field
  5896.    is pointing to something other than the header which FlexFile pre-
  5897.    pends to each field.
  5898.  
  5899.  
  5900. ──────────────────────────────────────────────────────────────────────────────
  5901. Error 6400      Proclip(tm) window is not a compatible version.
  5902. ──────────────────────────────────────────────────────────────────────────────
  5903.  
  5904.  
  5905.    An attempt was made to restore a Proclip window which has been
  5906.    stored to a DBV file while using an incompatible (most probably newer)
  5907.    version of Proclip.
  5908.  
  5909.    You will need a newer version of FlexFile to accomodate the new
  5910.    Proclip window type.
  5911.  
  5912.  
  5913. ──────────────────────────────────────────────────────────────────────────────
  5914. Error 6500      VLF length exceeds Clipper's maximum 65535 bytes.
  5915. ──────────────────────────────────────────────────────────────────────────────
  5916.  
  5917.  
  5918.    In certain circumstances it is possible to create a VLF that is
  5919.    larger than 64K.  The V_STUFF() function is capable of increasing
  5920.    the size of a field with no regard for memory, and the V_FILE2VLF()
  5921.    function will easily create fields that are extremely large.
  5922.  
  5923.    If you then attempt to V_RETRIEVE() this data, this error will be
  5924.    set and V_RETRIEVE() will fail.
  5925.  
  5926. See Also: V_RETRIEVE() V_STUFF() dbvfunc.ngo V_REPLACE()
  5927.  
  5928. ──────────────────────────────────────────────────────────────────────────────
  5929. Error 6600      Clipper 5.0 array's cannot be saved with V_REPLACE().
  5930. ──────────────────────────────────────────────────────────────────────────────
  5931.  
  5932.  
  5933.    Use V_AREPLACE() to store Clipper 5.0 arrays.
  5934.  
  5935.  
  5936. See Also: V_AREPLACE()
  5937.  
  5938. ──────────────────────────────────────────────────────────────────────────────
  5939. Error 6700      Error in V_ARETRIEVE().  Array corrupted.
  5940. ──────────────────────────────────────────────────────────────────────────────
  5941.  
  5942.  
  5943.    An attempt was made to retrieve an array from a DBV but the array
  5944.    was found to be corrupted.  V_PACK()ing the file is recommended.
  5945.  
  5946.  
  5947. See Also: V_ARETRIEVE()
  5948.  
  5949. ──────────────────────────────────────────────────────────────────────────────
  5950. Error 7100      Write error.  The disk may be full.
  5951. ──────────────────────────────────────────────────────────────────────────────
  5952.  
  5953.  
  5954.    An attemt to write data failed.  If the file was in use in shared
  5955.    mode, this error can still occur after the lock has been secured.
  5956.    The most likely cause for this error is no remaining disk space.
  5957.  
  5958.  
  5959. ──────────────────────────────────────────────────────────────────────────────
  5960. Error 7200      Record locking time out.
  5961. ──────────────────────────────────────────────────────────────────────────────
  5962.  
  5963.  
  5964.    This is an error code for future versions of FlexFile.
  5965.  
  5966.  
  5967. ──────────────────────────────────────────────────────────────────────────────
  5968. Error 7300      File not open in currently V_SELECTed() area.
  5969. ──────────────────────────────────────────────────────────────────────────────
  5970.  
  5971.    Attempt was made to access a DBV file in a FlexFile work area
  5972.    that does not have a file open.  For example,
  5973.  
  5974.       V_CLOSE()
  5975.       V_REPLACE( "Try and put this away", ptr_fld )
  5976.  
  5977. See Also: V_SELECT() V_ALIAS()
  5978.  
  5979. ──────────────────────────────────────────────────────────────────────────────
  5980. Error 7400      Selected area is out of bounds.  See v_files().
  5981. ──────────────────────────────────────────────────────────────────────────────
  5982.  
  5983.  
  5984.    You can only V_SELECT() an area within the current V_FILES() setting.
  5985.    The default setting for the maximum number of areas is 10.
  5986.  
  5987. See Also: V_FILES() V_SELECT()
  5988.  
  5989. ──────────────────────────────────────────────────────────────────────────────
  5990. Error 7500      Unknown alias.
  5991. ──────────────────────────────────────────────────────────────────────────────
  5992.  
  5993.  
  5994.    An attempt was made to V_SELECT() (or pass a function that accepts
  5995.    an area as a parameter) an illegal or unknown alias.
  5996.  
  5997. See Also: V_ALIAS() V_SELECT() V_USE()
  5998.  
  5999. ─────────────────────────────────────────────────────────────────────────────
  6000. Error 7600      Illegal attempt to reset V_FILES() or V_BUFFERS
  6001. ─────────────────────────────────────────────────────────────────────────────
  6002.  
  6003.  
  6004.    An attempt was made to set V_FILES() or V_BUFFERS() when there was at
  6005.    least one DBV file open.  You must first close all DBV files before
  6006.    attempting to use these functions.
  6007.  
  6008. See Also: V_FILES() V_BUFFERS()
  6009.  
  6010. ─────────────────────────────────────────────────────────────────────────────
  6011. Error 7700      Invalid V_RETRIEVE() substring parameters.
  6012. ─────────────────────────────────────────────────────────────────────────────
  6013.  
  6014.  
  6015.    When using V_RETRIEVE() to retrieve only part of a VLF, the parameters
  6016.    representing the bounds of the string to retrieve were invalid.
  6017.  
  6018. See Also: V_RETRIEVE()
  6019.  
  6020. ──────────────────────────────────────────────────────────────────────────────
  6021. Error 8000      No areas remain.  See v_files() to increase the quantity of areas.
  6022. ──────────────────────────────────────────────────────────────────────────────
  6023.  
  6024.  
  6025.    An attempt was made to V_USE() with the "NEW" modifier or V_SELECT(0)
  6026.    when all available areas are in use.  The solution to this problem
  6027.    is to increase your maximum FlexFile work areas with the V_FILES()
  6028.    function.
  6029.  
  6030. See Also: V_FILES() V_SELECT() V_USE()
  6031.  
  6032. ──────────────────────────────────────────────────────────────────────────────
  6033. Error 8100      Not a VLF type file.
  6034. ──────────────────────────────────────────────────────────────────────────────
  6035.  
  6036.  
  6037.    Attempt was made to V_USE() a file that is not recognizable as a
  6038.    FlexFile type file.
  6039.  
  6040. See Also: V_USE()
  6041.  
  6042. ──────────────────────────────────────────────────────────────────────────────
  6043. Error 8200      File read error.
  6044. ──────────────────────────────────────────────────────────────────────────────
  6045.  
  6046.    This error is possible if an exclusive lock has been imposed
  6047.    by another work station on a network.
  6048.  
  6049. See Also: V_EXCLUSIV()
  6050.  
  6051. ──────────────────────────────────────────────────────────────────────────────
  6052. Error 8300      Unknown data type.  Possibly using a pointer-field from wrong work area.
  6053. ──────────────────────────────────────────────────────────────────────────────
  6054.  
  6055.  
  6056.    The valid data types for V_REPLACE() and V_RETRIEVE() are defined
  6057.    in the V_REPLACE() function reference.  If FlexFile encounters a
  6058.    type which is not amoung these valid types, this error will be
  6059.    generated. For example, using V_RETRIEVE() to try to fetch a Summer
  6060.    87 array will create this error. Use V_FILLARR() instead.
  6061.  
  6062.    In addition, if you make the mistake of using a pointer-field which
  6063.    points into one file as a pointer-field for a different file, FlexFile
  6064.    will again generate this error.  This is because the pointer-field
  6065.    is pointing to something other than the header which FlexFile pre-
  6066.    pends to each field.
  6067.  
  6068.  
  6069. ──────────────────────────────────────────────────────────────────────────────
  6070. Error 8400      Attempt to V_RETRIEVE a Proclip window.
  6071. ──────────────────────────────────────────────────────────────────────────────
  6072.  
  6073.    An attempt was made to V_RETRIEVE() a Proclip window.  Use
  6074.    V_WNDCREAT() to create a Proclip window that has been stored
  6075.    to a DBV file.
  6076.  
  6077.  
  6078. See Also: V_WNDCREAT()
  6079.  
  6080. ──────────────────────────────────────────────────────────────────────────────
  6081. Error 9000      Undetermined error in seek for deleted space.
  6082. ──────────────────────────────────────────────────────────────────────────────
  6083.  
  6084.    Unfortunately, this spells disaster and is usually caused by a
  6085.    corrupted DBV file.  However, the FlexFile scheme is based on
  6086.    a very solid principal.  That is, if your DBF file holding the
  6087.    pointer-fields into the DBV file is intact, the V_RETRIEVE()
  6088.    function will almost invariably still retrieve data from any
  6089.    field that has not yet been corrupted.
  6090.  
  6091.    So, disaster recovery is as simple as creating a new DBV file
  6092.    in a new FlexFile work area and V_REPLACE()ing data into the
  6093.    new area with the data V_RETRIEVE()d from the corrupted area.
  6094.  
  6095.    Remember to test for V_TYPE() on the pointer-field because if
  6096.    it encounters a corrupted portion of the file, it will return
  6097.    an "U"ndefined regardless of the data type stored in that
  6098.    particular field.
  6099.  
  6100.  
  6101.  
  6102.