home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-09-19 | 206.7 KB | 6,102 lines |
-
-
-
-
-
- FlexFile■
- (C) Copyright 1990 Ganahl Software
- All Rights Reserved
-
-
-
-
- Note: This software is a commercial product and is not
- to be copied except for archival purposes.
-
-
-
-
-
- GANAHL Software
- P.O. Box 4275
- Deerfield Beach, Fl 33442
- Tel: (305) 566-1796
- Fax: (305) 566-3517
-
-
-
- Licensing agreement
-
- Use of FlexFile constitutes your acceptance of these terms and
- conditions and your agreement to abide by them.
-
- I have read and agreed to the terms of the Ganahl Software
- License Agreement. I understand that I am not entitled to
- make any copies of the distribution diskette except for
- archival purposes. I understand that I may compile this
- software into complete, executable programs and distribute
- those programs without royalty to Ganahl Software. I
- understand that I may not distribute this software in any
- other way. I understand that I may not make any copies of the
- documentation for any purpose.
-
- You must signify your consent to this License Agreement by
- signing and returning the enclosed registration card. If you
- do not agree to the terms of the License Agreement, you must
- return the software with its documentation and destroy any
- copies of the software that you have made.
-
-
-
- Money Back Guarantee
-
- You may return the FlexFile Software product for any reason
- within thirty days of receipt for a refund. If you choose to
- return FlexFile within this thirty day return period, you must
- destroy any copies of FlexFile that you have made as well as
- any programs (including those that you have distributed) which
- use FlexFile software in any fashion.
-
-
- Warrantee
-
- Ganahl Software warrants the physical diskette and physical
- documentation enclosed herein to be free of defects in materials
- and workmanship for a period of 30 days from the date of
- purchase. In the event of notification within this warranty
- period of defects in material or workmanship, Ganahl Software
- will replace the defective diskette or documentation. The remedy
- for breach of this warranty shall be limited to replacement or
- refund of the purchased price and shall not encompass any other
- damages, including but not limited to loss of profit, special
- incidental, consequential, or other similar claims.
-
-
- Ganahl Software specifically disclaims all other warranties,
- expressed or implied, including but not limited to implied
- warranties of merchantability and fitness for a particular
- purpose. In no event shall Ganahl Software be liable for any
- loss of profit or any other commercial damage, including but
- not limited to special incidental, consequential or other
- damages.
-
-
-
-
-
- FlexFile Support Policy
-
-
- Who may receive support
-
- Only registered users of FlexFile may receive support. To
- register simply fill out the registration card that is
- enclosed with the FlexFile package that you receive, fill
- out the information, and send it directly to Ganahl Software.
-
- What you must do
-
- Before contacting our Customer Support please have the
- following information on hand:
-
- 1. Your product's serial number and version number (on
- the inside front or back cover of your manual).
- 2. FlexFile library used (FlexFile.lib or Flex_87.lib).
- 3. Computer make and model.
- 4. DOS version.
- 5. Network software if applicable.
- 6. Clipper version (e.g. S'87, Clipper 5.0, etc.)
-
-
- How to Contact Ganahl Software Technical support
-
- The best method for support of any Clipper product (including
- Clipper itself) is on CompuServe's Nanforum or DBA (Data Based
- Advisor's forum). Simply post messages to the user ID
- 76477,2177.
-
- The reason this is the best support is because you benifit
- from the other users of FlexFile who frequent the forum, the
- Ganahl Software Support folks, and Brice deGanahl (FlexFile's
- Author).
-
- Otherwise either write or call between 9:am and 5:pm (EST)
-
- Ganahl Software
- P.O. Box 4275
- Deerfield Beach, Florida 33442
- Support: (305) 941-5199
- Sales: (305) 566-1796
- Fax: (305) 566-3517
-
-
-
- Credits
-
-
- The quality of this project has been enhanced tremendously
- with the help of some exceptional friends. Specifically, I
- would like to thank Don Caton, Gary Herbstman, Sandy Leaf,
- Terry O'Neill and John Thorla. Without these folks, there
- would be no FlexFile.
-
- Don Caton selflessly offered innumerable hours, consulting on
- both technical and practical issues in the creation
- FlexFile's design. In addition, he has relentlessly tested
- the software, dug up insidious bugs, and has been generous
- beyond belief.
-
- Gary Herbstman provided a major influence in the technical
- design of the VLF engine and provided some of its tightest
- code.
-
- Sandy Leaf covered the gamut from business advisor to
- advertising agent. Without Sandy's considerable attention to
- schedule, FlexFile would have been completed anyway... in a
- year or two.
-
- Terry O'Neill took this documentation from a pile of
- scribbled notes to a coherent, comprehensive and clean User
- Manual. His sense of perfection spilled out of the
- documentation and into the code where he has corrected and
- simplified many of the library's functions.
-
- John Thorla has been an inspiration, an advisor, and a
- friend. This thanks to John is extended to all the folks at
- his company, Direct Link Software, who have continually
- provided me with encouragement, product testing, need for
- functionality, ideas for marketing, proof reading and a
- multitude of laughs when they were most needed. Specific
- thanks go to Dave Peters and Randy Robalewsky.
-
- Brice de Ganahl
- President, Ganahl Software
-
-
-
-
-
- Overview
-
-
- Variable Length Fields
-
- FlexFile is a very focused dual purpose tool kit for Clipper
- programmers. Its first and main purpose is to provide a
- complete replacement for Clipper's memo-fields with a more
- powerful and more efficient Variable Length Field engine. We
- are certain that it will relieve you of the confinement
- imposed by Clipper's memo-fields, but also, we believe it may
- change the way you think about your data base structures in
- general.
-
- FlexFile was designed to be immediately familiar to the
- Clipper programmer. To accomplish this goal, many of the
- function names can only be distinguished from their Clipper
- counterpart by a V_ prefix. For example, V_USE() opens a DBV
- file in the currently V_SELECT()ed work area.
-
- The similarities extend into the structural use of FlexFile's
- Variable Length Fields (VLF) as well. FlexFile's version of a
- memo-field (which we will refer to as a pointer-field) is a
- six byte character type field in a DBF file. FlexFile uses
- this pointer-field to store a pointer to variable length data
- in a .DBV file (FlexFile's version of a .DBT file). These
- similarities allow any Clipper REPLACE syntax which works on
- memo-fields to remain almost unchanged when used with
- FlexFile. This claim carries in network environments as well.
-
- The benefits and use of FlexFile's Variable Length Fields are
- discussed in detail in the Reference "Variable Length Fields".
- Pay special attention to the section on FlexFile's extended
- features.
-
-
-
- Arrays
-
- FlexFile's strongly typed arrays provide a utility which defy
- the products name. Instead of being flexible, these arrays
- are purposefully rigid. The utility of these arrays is
- twofold. First and foremost, they use far less space than
- their Clipper counterpart. For example, any Clipper array of
- 1,000 elements would require a minimum of 14,000 bytes from
- Clipper's free pool of memory. A FlexFile array of 1,000
- integers, on the other hand, would require only 2,000 bytes
- from Clipper's free pool of memory.
-
- Typically, large strongly typed arrays are used for scientific
- or statistical matrixes. For this reason, FlexFile provides a
- host of functions which globally manipulate or query these
- large arrays.
-
-
-
-
- Linking FlexFile into an application
-
- FlexFile is compatible with all the linkers that it has been
- tested with. The entire library can be overlayed with
- Blinker(tm) or WarpLink(tm) or RTLink Plus(tm).
-
- The procedure for linking is the same as for any other library
- listed in your link file or on the link command line. For
- example:
-
- link test.obj,,,c:\lib\clipper c:\lib\flexfile
-
- Each FlexFile function begins with either a V_ or an A_
- depicting use with the Variable Length Field manager or the
- array manager, respectively. The prefix to each function was
- chosen to avoid conflict with other libraries. If you find a
- conflict with another library, you must place FlexFile before
- the other library in the link list in order to use the
- FlexFile function. If you find a conflict please contact us
- so that we may avoid them in future releases.
-
-
-
-
-
- Variable Length Fields
-
- The enhancements to memo-fields
-
- FlexFile addresses the four major problems that plague
- Clipper's implementation of memo-fields.
-
- First, FlexFile reuses all unused space. If your user edits a
- memo (or deletes elements of an array) making it smaller,
- FlexFile is aware of every byte of the excess space and will
- use it later for new data. This feature totally eliminates
- the file bloat that characterizes Clipper's DBT files.
- (Clipper frequently abandons space no longer needed by
- memo-field data, and once abandoned, not even packing the file
- can regain the space.)
-
- Second, FlexFile does not allocate space in blocks. Instead,
- each item stored requires only the space for its own length
- plus a six byte header that FlexFile uses for management.
- This is in great contrast to Clipper's memo-fields that
- require a fixed block size of 512 bytes. This feature alone
- will save disk space at an average of 256 bytes per record.
-
- Third, the size of FlexFile's Variable Length Field (VLF)
- files are limited only by your disk space. This is in
- contrast to Clipper's size limit on a DBT file of 16M.
-
- Finally, FlexFile can store any valid Clipper data. This
- includes arrays, character strings, dates, numerics and
- logicals. In addition, the content of character data is not
- limited as it is in Clipper. It is, therefore, possible to
- store SAVESCREEN() variables or any other binary data that you
- use.
-
-
-
-
- FlexFile's Extended Features
-
- Through FlexFile's ability to save an array to a field, your
- DBF's can become three dimensional (actually multi-dimensional
- with Clipper 5.0). Looking at it another way, each record can
- now have a variable number of fields. This new feature allows
- far greater flexibility in designing a database system.
-
- Lets take the simple example of storing a telephone number.
- In a customer data base, next to the name and address we store
- the telephone number. But is one telephone number enough?
- Most businesses require at least a voice line and a fax line.
- Then again, there is that one guy who has got two voice lines,
- a fax line, a data line, and a whole bunch more at his house.
-
- So, do we build in five or ten telephone fields in the
- customer file? Certainly this situation would not warrant a
- second file and an index with a relation. Usually, we tell our
- client (very nicely) to live with a maximum of two.
-
- With FlexFile, however, the answer is simple. Save an array
- of telephone numbers. Those customers who have one or two
- telephone numbers use only the space for one or two telephone
- numbers. Those that have ten can have ten. There are no
- indexes or relations to maintain and you can extend this
- concept into those perplexing data item which your client
- defines as requiring "usually two or three, but sometimes
- twenty or more".
-
- FlexFile also allows the programmer to store any valid Clipper
- data type to a field. At first look, this alternative seems
- less than impressive. Why would you want to store a logical
- value, which takes only one byte per record in a DBF file, by
- using a six byte pointer-field in the DBF to point to an
- object which requires a six byte header in the DBV. The
- advantage does not come from saving any one type, but rather,
- from being able to store different types to the same field.
- This is particularly advantageous in data driven applications.
- For example, if you give your clients user defined fields,
- they can change the type of a field and you won't have to
- worry about carrying extra fields for each type "Just in
- Case".
-
-
-
-
- USEing DBV files
-
- The use of FlexFile's DBV files was designed to parallel the
- use of DBF type files. Specifically, the system is made up of
- work areas that are used to manage the VLF files in exactly
- the same manner as Clipper uses work areas to manage DBF
- files. This method avoids the need to keep track of
- "handles", and allows the use of aliases.
-
- For example, you can V_SELECT(1) and then V_USE() a file in
- area one, and then V_SELECT(0) the next available work area
- and V_USE() another file there. It should be noted that
- FlexFile's work areas are mutually exclusive from Clippers DBF
- work areas. For example, you can V_SELECT(1) and V_USE() a
- file in VLF area one, and simultaneously, SELECT 1 and USE a
- file in DBF area one with no conflicts.
-
- The FlexFile system offers an unlimited number of work areas,
- however, you must decide what your maximum number of work
- areas will be before you open the first DBV type file. The
- reason for this is to allow the system to create one
- contiguous block of memory for the management of the files
- instead of fragmenting memory with little blocks each time you
- open a new file. At any point that you have all DBV files
- closed you can readjust this maximum number of work areas by
- using the V_FILES() function.
-
-
- Creating DBV files
-
- The simplest thing to do in FlexFile is to create a DBV type
- file. Simply V_USE() a file that does not exist and you will
- have a DBV file open and ready to go.
-
-
- How to Manage Your Data with FlexFile
-
- Another great use for FlexFile is to hold data that is not
- repetitive and structured; the DBF file structure is not at
- all accommodating in this area. For example, almost every
- Clipper application requires system data such as a color
- scheme, default directories, default drive for temporary
- files, printer definitions, and other randomly sized
- non-repetitive data. Storing this data is now a trivial
- matter.
-
- In this case, the design could be as simple as a two field DBF
- file with an index, and one FlexFile VLF file. The DBF
- structure might look like:
-
- Structure for database: C:\FF\SYSTEM.DBF
- Number of data records: 20
- Date of last update : 10/05/90
- Field Field Name Type Width Dec
- 1 VAR_NAME Character 10
- 2 VLF_FLD Character 6
- ** Total ** 17
-
- The key field <var_name> will hold the name of a Clipper
- variable that you use; the six byte character field <vlf_fld>
- FlexFile will use to hold a pointer to <var_name>'s value.
- Following from the above description, start-up code for an
- application might look like:
-
- // Declare the system wide public variables that you use.
- PUBLICaColors,; // Array variable for colors
- cDefaultDir,; // A user defined default directory
- dYearEnd // A user defined year end date.
-
- // Open the DBF, its index, and the VLF
- USE System.dbf INDEX System.ntx
- V_USE( "System.dbv" )
-
- // Seek your colors array and retrieve it.
- // Note that this Clipper 5.0 syntax for arrays is slightly
- // different than the S'87 syntax. See the V_FILLARR() function.
- SEEK "aColors"
- aColors = V_ARETRIEVE( vlf_fld )
-
- // Seek the record that holds a "Default" directory.
- SEEK "cDefaultDir"
- cDefaultDir = V_RETRIEVE( vlf_fld )
-
- // Dates can be stored as easily as anything else.
- SEEK "dYearEnd"
- dYearEnd = V_RETRIEVE( vlf_fld )
-
- Of course, for this code to work you must have previously save
- data to these records. The next section on FlexFile's
- pointers gives an in depth view into storing the data,
- retrieving it and replacing old data with new.
-
-
-
- FlexFile's Pointers
-
-
- The key to maintaining secure data with FlexFile is fully
- understanding the pointers that FlexFile uses to access data.
- Clipper's memo-fields maintains a similar set of pointers but
- Clipper hides them from the programmer as well as the user.
- If you try to assign a Clipper memo-field pointer directly to
- a variable as in:
-
- var = system->mem_fld // Clipper memo-field
-
-
- Clipper intercepts the call and automatically goes to the DBT
- file and fetches the data that <mem_fld> points to. With
- FlexFile, this assignment would put the pointer into <var>
- instead of the data. So, the equivalent code using flexfile
- is:
-
- var = V_RETRIEVE( system->vlf_fld ) // FlexFile VLF
-
-
- What we are doing here is passing the V_RETRIEVE() function a
- pointer to the data and V_RETRIEVE() is kindly passing us back
- data that was stored there.
-
- The same principal applies to saving data... with a twist.
- When Clipper saves data to a memo-field, it allocates disk
- space in 512 byte chunks and sticks a pointer to the allocated
- space in the memo-field of the DBF file. For example,
-
- // Clipper hogs 512 bytes with this one.
- REPLACE system->mem_fld WITH "This will take 512 bytes"
-
- Clipper allocates 512 bytes of disk space, puts the 24 bytes
- of data in the front of the new space, and puts a pointer to
- the block in <mem_fld>. If, without moving the record
- pointer, we say
-
- // Clipper abandons the first mess and requires 1024 more.
- REPLACE system->mem_fld WITH SPACE( 513 )
-
- then Clipper will abandon the first 512 byte block
- (permanently), and allocate 1024 bytes for the new data. The
- old pointer to the 512 byte block is lost and the file space
- is gone forever.
-
- FlexFile is smarter than this. Using FlexFile, we would save
- the 24 byte string with:
-
-
- // FlexFile neatly allocates 30 bytes of disk space.
- REPLACE system->vlf_fld WITH ;
- V_REPLACE( "This will take 30 bytes", system->vlf_fld )
-
- If we follow the pointer in this example, we can see what
- FlexFile is going to do. The first thing that we notice is
- that we not only pass to the V_REPLACE() function the new
- data, but also, we give it the old pointer.
-
- Because this function will operate from right to left, first
- it will look at the right most <vlf_fld> to see if it is
- pointing to any old data. If it is not, then the function
- proceeds to look through an internal table for other vacated
- space. We will assume for this example that this is the first
- V_REPLACE(). Therefore, there is no available space that has
- already been release by other data, so the new string is
- appended to the end of the file.
-
- To do this FlexFile will allocate 30 bytes of disk space, 24
- bytes for the data and six bytes to keep some information that
- it uses for management.
-
- Now we continue the example by replacing the thirty bytes with
- 513 bytes of spaces:
-
- // FlexFile releases 30 bytes and stores 519.
- REPLACE system->vlf_fld WITH ;
- V_REPLACE( SPACE( 513 ), system->vlf_fld )
-
- This time, FlexFile sees that the old pointer has something in
- it, and so releases it. Then it seeks internally for an
- available 519 byte space to put the new information. There is
- none, so it tags this at the end of the file as well.
-
- There are two very important advantages you can see from this
- example. First, only the size of the data was required to
- keep the data, and second, the next piece of data that you
- store that is thirty bytes or less will be stored in the
- vacated space.
-
- The thirty byte space that is available brings up an important
- point. We have run tests where one VLF file undergoes
- millions of V_REPLACE()s. The data ranged in random sizes
- from one byte to ten thousand bytes. The amount of vacant
- space tended to level off at about 20% of the fully pack
- file's size and at that point the VLF file stops growing,
- period.
-
-
-
-
- Disaster Recovery
-
- One of FlexFile's advantages is that it is very robust against common
- disaster situations such as power loss. Your DBV file may get damaged
- during such a calamity, however, the damage done is local to the write
- that was in progress when the interuption occurred. That is, there is
- no immediate ripple effect from a damaged section of a DBV to non
- damaged sections.
-
- On the other hand, if your file gets damaged and you continue to use it,
- you CAN cause more damage. Therefore, you should prepare your code for
- such an occurance (you can always rely on backups, but sometimes clients
- simply fail to do their job of backing up regularly).
-
- If V_REPLACE() or V_DELETE() return a logical value (as opposed to a
- character value) and/or V_ERROR() reports a 6200, 6500, 6700 or 9000
- class of error, the DBV file may be corrupt. (Syntax errors in calling
- FlexFile functions can also cause these errors so check your syntax
- first.)
-
- When you are certain that your syntax is not causing the problem, you
- should rebuild the DBV file. Rebuilding is a simple process and is
- outlined by the following code. The code is based on a DBF file called
- "dbf_file.dbf" which has a six byte character field (a FlexFile
- pointer-field) called <vlf>. We then open the existing DBV and create a
- new DBV into which to copy the old data. Finally, we erase the old DBV
- and rename the new one back to the old.
-
- Before any code such as this is implemented you should back up the files
- involved.
-
-
- // Open the controlling DBF and the DBV (with an alias of "OLD")
- USE dbf_file
- V_USE( "dbv_file", "old" )
-
- // Open a new DBV to recieve the copyable data (with an alias of "NEW").
- V_SELECT(0)
- V_USE( "tempdbv", "new" )
-
- DO WHILE !EOF()
-
- IF V_TYPE( dbf_file->vlf, "old" ) == 'U'
- QOUT( "This record is damaged." )
- WAIT
- LOOP
- ENDIF
-
- // If the type is Char, Num, Log, Date, or FlexFile array
- IF V_TYPE( dbf_file->vlf, "old" ) $ "CNLDF"
-
- // Get the value from the DBV.
- var = V_RETRIEVE( dbf_file->vlf, "old" )
-
- // Write the value to the new DBV.
- dbf_file->vlf := V_REPLACE( var, space(6), "new" )
-
- // else the type must be an array.
- ELSE
-
- // Get the array from the DBV
- var = V_ARETRIEVE( dbf_file->vlf, "old" )
-
- // Write the array to the new DBV
- dbf_file->vlf := V_AREPLACE( var, space(6), "new" )
-
- ENDIF
-
- SKIP
-
- ENDDO
-
- FERASE( "dbv_file.dbv" )
- FRENAME( "tempdbv.dbv", "dbv_file.dbv" )
-
-
-
- The other form of "disaster" that is fairly common is to loose a DBF
- file that has pointer-fields into a DBV. This is a very serious
- situation because there is nothing in the DBV which points back into the
- DBF. However, there is a new function V_WALK_DBV() that allows the
- programmer to step from field to field through the DBV file. The steps
- go from physical field to physical field and so the logical order of the
- file is lost. However, in extreme situations this function may be
- helpful. See V_WALK_DBV() for more information.
-
-
-
-
- Saving and Retrieving Clipper's arrays
-
-
- ┌─────────────────────────Warning───────────────────────────────────┐
- │ Arrays saved with FlexFile's S87 library version 1.01 and │
- │ earlier cannot be retrieved directly with FlexFile's Clipper │
- │ 5.0 V_ARETRIEV() function. Instead, see the documentation on │
- │ V_FILLARR() and V_FILLEN(). Arrays saved with later versions │
- │ of FlexFile are compatible between the two version as long as │
- │ the array is one dimensional. │
- └───────────────────────────────────────────────────────────────────┘
-
- Saving and retrieving Clipper S'87 arrays
-
- To save a an array using the S'87 version of the library
- (Flex_S87.lib), you treat the array like any other variable.
- For example,
-
- && Declare an array
- DECLARE arr[100]
-
- && Put some junk in it.
- afill( arr, "Solid waste" )
-
- && Save the array (assume a DBF and DBV are open).
- REPLACE vlf WITH V_REPLACE( arr, vlf )
-
- To retrieve that same array in S'87 takes more than one line of code.
- Remember that V_LEN() returns the total number of elements in
- a S'87 array.
-
- && Assume that we are still on the same record in
- && the DBF but we do not already have a declared array.
- && First we need to DECLARE the array to be the size of
- && the array we stored above.
- DECLARE newarr[ V_LEN(vlf) ]
-
- && Now we fill the array.
- V_FILLARR( newarr, vlf )
-
- Although that was slightly awkward that is all there is to it.
-
-
- Saving and retrieving Clipper 5.0 arrays
-
- To save an array with the Clipper 5.0 library (FlexFile.lib)
- you treat the array like you would any other Clipper variable
- except that instead of using V_REPLACE() and V_RETRIEVE() you
- need to use V_AREPLACE() and V_ARETRIEV(). Remember
- V_ARETRIEV() can only be used on arrays that were saved with
- V_AREPLACE() (see the warning above).
-
-
-
-
- Indexing on Variable Length Fields
-
- There are several issues that must be addressed by the programmer in
- order to create and maintain an index on part (or all) of a FlexFile
- Variable Length Field.
-
- First, creating an index is as easy as:
-
- INDEX ON V_RET( vlf_fld, "ALIAS_1", 1, 15 ) TO NTX_FILE.NTX
-
- This would create an index on the first fifteen characters of a FlexFile
- VLF. However, every element of a clipper index must be the same length
- and the above example does not guarantee this. (If V_RETRIEVE() returns
- a string of less than 15 characters, you will corrupt your index.) So,
- you should PAD() the return from V_RETRIEVE() with spaces as in:
-
- INDEX ON PAD( V_RET(.....), 15 ) TO NTX_FILE.NTX
-
- The second issue is to note that only data of the same type can be
- indexed in this manner. Accordingly, make sure that the character data
- is not binary data. If a CHR(0) is found in the first 15 characters of
- the above example, Clipper will consider that to indicate the end of the
- string. This will make the string's length different from other strings
- in the index and, thereby, corrupt the index.
-
- The last issue is described below, but is more complex. However, it is
- not necessary to understand why, as long as you always abide by the
- rule: You must always have a REPLACE command that does not have a
- V_REPLACE in its syntax before REPLACEs that contain V_REPLACE(). For
- example,
-
- && INCORRECT....will corrupt the index if the index relys on either
- && the data pointed to by vlf_1 or vlf_2.
- REPLACE vlf_1 WITH V_REPLACE( "testing", vlf_1 )
- REPLACE vlf_2 WITH V_REPLACE( "testing", vlf_2 )
- SKIP
-
- && CORRECT....the first replace is a "dummy" but maintains integrity.
- REPLACE any_fld WITH any_fld
- REPLACE vlf_1 WITH V_REPLACE( "testing", vlf_1 )
- REPLACE vlf_2 WITH V_REPLACE( "testing", vlf_2 )
- SKIP
-
- First, the only reason I placed two V_REPLACE()s in the example is to
- show that only one "dummy" replace is necessary before any number of
- imbedded V_REPLACE()s. Remember that anything that causes the index to
- be updated (such as COMMIT, SKIP, SEEK, etc.) require that a new "dummy"
- replace be used before attempting another REPLACE with imbedded
- V_REPLACE()s. For example,
-
- && CORRECT
- REPLACE any_fld WITH any_fld
- REPLACE vlf_1 WITH V_REPLACE( "testing", vlf_1 )
- REPLACE vlf_2 WITH V_REPLACE( "testing", vlf_2 )
- SKIP
-
- && INCORRECT....will corrupt the index without another "dummy"
- && replace after the COMMIT. Assuming, of course, that vlf_2
- && is included in the index key.
- REPLACE any_fld WITH any_fld
- REPLACE vlf_1 WITH V_REPLACE( "testing", vlf_1 )
- COMMIT
- REPLACE vlf_2 WITH V_REPLACE( "testing", vlf_2 )
-
-
- Ok, so what is going on? Understanding the sequence of events that
- occurs during a REPLACE is critical to understanding the apparent
- paradox in the examples above.
-
- Remembering that the arguments of a function or command are all
- evaluated before the function itself is called, the syntax
-
- REPLACE vlf_fld WITH V_REP( "Testing an indexed replace", vlf_fld )
-
- first executes FlexFile's V_REPLACE() and then executes Clipper's
- REPLACE.
-
- This affects indexing because Clipper always evaluates the index key
- twice. Once at the begining of the first of one or more REPLACEs (to
- remember which index key has to be removed from the index) and the
- second after any of several "commit" commands such as COMMIT, SKIP,
- SEEK, GOTO, etc. (to calculate and insert a new index key). However, if
- FlexFile already deleted the old information pointed to by vlf_fld
- before CLIPPER began to execute the REPLACE code, then the first
- evaluation of the index key occurs after its data has already been
- deleted by FlexFile.
-
- I realize this is confusing so I will try again in steps:
-
- ┌─ step 2 ┌─ step 1
- │ │
- REPLACE vlf_fld WITH V_REPLACE( "testing", vlf_fld )
- │ │
- └─ step 4 └─ step 3
- step 5
-
- 1. FlexFile deletes the data associated with the pointer-field vlf_fld
- that is in the file before the REPLACE.
-
- 2. FlexFile puts away the text "testing" in an appropriate location.
-
- 3. FlexFile returns a six byte pointer-field which is immediately passed
- to REPLACE. This pointer-field is different than that of step 1 and
- this new pointer-field is not yet in the file (it is being stored in
- memory for the moment).
-
- 4. Clipper begins executing its REPLACE code with the string passed to
- it from step 3.
-
- 5. Clipper evaluates the index and stores the evaluated value in a
- buffer. This sets up the error. The index key should evaluate to the
- data pointed to by the vlf_fld which is still in the file. However,
- FlexFile deleted that data in step 1. Therefore, the V_RETRIEVE() in the
- index key will return a null string and your PAD function will change
- this to 15 bytes of spaces.
-
- No Clipper error actually occurs until the first COMMIT, SKIP, SEEK,
- etc. It is at this point that Clipper does the work on the index. The
- first thing Clipper does is delete the old index key (which was put into
- a memory buffer in step 5). However, Clipper will not be able to find
- an index key which matches the 15 spaces in the memory buffer and,
- therefore, assumes that the index is corrupted.
-
- So, the way to resolve this is to have a "dummy" replace that will force
- Clipper to evaluate the index key BEFORE FlexFile deletes the key. The
- thing that may be confusing is that Clipper does not care which field is
- in the first REPLACE. It is simply a fact that the first REPLACE
- evaluates the "before" index key regardless of whether the REPLACE even
- affects the index key. It is also a fact that no other index action
- occurs until a "commit" type command. At that point the "before" key is
- deleted from the index and the "after" key is inserted into the index.
-
-
-
-
- FlexFile Networking
-
- FlexFile typically requires no special network considerations
- beyond Clipper's RLOCK() and FLOCK(). That is to say, if you
- acquire an RLOCK() on a record in a DBF file that has a
- pointer-field, no other user will have write access to that
- record. Because Clipper insists on an RLOCK() being acquired
- before a REPLACE when a file is used non-exclusively, this
- will suffice to protect the information to which the
- pointer-field is related.
-
- FlexFile's internal tables lock and unlock automatically, and
- require no programmer consideration.
-
- There is an additional network features which was incorporated
- into FlexFile in order to aid the programmer in implementing
- network compatible code.
-
- Every time a pointer is replaced with a new pointer, the new
- pointer is guaranteed to have a different value even though it
- may be pointing to the same position within the file.
-
- For example, if you have variable length data that is 30 bytes
- long, residing at offset 5000 in the DBV file, and you replace
- that data with new data that is also 30 bytes long, it is
- highly probable that FlexFile will put the new data exactly
- where the old data was (at offset 5000). However, the
- pointer-field that the V_REPLACE() function returns will be
- different than the one that pointed to the data before the
- REPLACE.
-
- This feature was implemented so that the programmer can assign
- the pointer- field to a variable, then, without locking the
- DBF record in which the pointer- field is located, modify the
- pointer's data in memory. Then when the user is ready to
- replace the old data with the modified data, the programmer
- can compare the pointer-field in memory with the DBF's
- pointer-field in order to ascertain whether the data was
- modified by another user while the current user was working on
- the copy of it in memory. For example:
-
- // Open the DBF and its related DBV
- USE Shareit.dbf
- IF V_USE( 'Shareit.dbv' ) == -1
- ? "I could not open the Shareit.dbf file."
- ? "I encountered error: " + STR( V_ERROR() )
- QUIT
- ENDIF
-
- // Save the pointer <vlf> to a variable
- save_vlf = shareit->vlf
-
- // Retrieve the data from the DBV file into a memory var.
- // The DBF lock is momentary.
- DO WHILE !RLOCK()
- ENDDO
- memo_data = V_RETRIEVE( vlf )
- UNLOCK
-
- // Edit the data.
- memo_data = MEMOEDIT(memo_data...)
-
- // Lock the record and replace the data if the
- // data has not been modified since the pointer was
- // saved. Again, the lock is momentary.
- DO WHILE !RLOCK()
- ENDDO
-
- IF save_vlf == shareit->vlf
- REPLACE vlf WITH V_REPLACE( memo_data, vlf )
- ELSE
- ? "Data has been modified by another user!"
- INKEY(0)
- ENDIF
- UNLOCK
-
- Although the Clipper locking technique shown is crude (at
- best), the comparison of the saved version of the pointer with
- the DBF pointer-field is a technique that many programmers
- prefer. The advantage is, of course, that you only need to
- obtain two momentary locks rather than one long lock (during
- which your user invariably goes on a lunch break). The
- disadvantage is that sometimes the user will have to retype an
- entry.
-
- FlexFile's internal locking uses the DOS 3.x locking
- mechanism. Therefore, if you are using a lower version of DOS
- or do not have SHARE.EXE loaded, FlexFile will ignore any
- attempts to lock the file and proceed as if the lock was
- successful.
-
-
-
-
-
- ARRAYS
-
- FlexFile supports an implementation of strongly typed
- multi-dimensional arrays. This array system is not to be
- looked at as a replacement for the Clipper array system.
- Clipper's array system is very powerful and it should not be
- construed that FlexFile arrays will supersede the Clipper
- system. Rather, FlexFile arrays should be used when the array
- structure is regular, all the elements are of the same type,
- and the array is very large.
-
- UNDER NO CIRCUMSTANCE SHOULD YOU USE FLEXFILE'S "S"TRING TYPE ARRAY IN
- CLIPPER 5.0X. EACH STRING ELEMENT OF THE ARRAY IS NOT HANDLED BY THE
- VMM SYSTEM, AND, THEREFORE, THE CLIPPER COUNTERPART WILL TAKE LESS
- MEMORY. ALL OTHER FLEXFILE ARRAYS CAN BE SWAPPED, WHEN NECESSARY, BY
- CLIPPER'S VMM SYSTEM.
-
- Why Use FlexFile Arrays
-
- FlexFile arrays are the only arrays to use if your array must
- exceed Clipper's limit of 4029 elements. For example, a
- FlexFile array of logicals allows over 500,000 elements. In
- addition, each element of FlexFile array is at least six bytes
- smaller than its Clipper counter part and at most thirteen
- bytes and 7 bits smaller. See Appendix B for a list of the
- sizes of each type of FlexFile array.
-
- Clipper sees Flexfile arrays as regular variables. Therefore,
- you pass a Flexfile arrays by value (unless you
- pass-by-reference using the @ symbol) and you can return a
- FlexFile array as though it were a simple Clipper variable.
- Because these arrays are typically large, it is best to pass
- them by reference in order to avoid duplicating their content
- in memory.
-
- The one exception to this is FlexFile's string type arrays.
- These arrays pose a unique problem which is discuss below (See
- FlexFile String Arrays).
-
-
-
-
- Array indexes
-
- A "subscript" or an "index" refers to a particular element of
- an array. For example, Clipper refers to the third element of
- a single dimensional array as ArrayName[3]. In this case, [3]
- is a subscript of the array ArrayName.
-
- Subscripts may be passed using either of two different
- methods. Both methods are valid at any time. The method to
- use depends largely on whether your array is single or
- multi-dimensional.
-
- If the array is a single dimensional array, then you define
- and index position into that array exactly as you would
- imagine. For example, if you want to store 98.6 to the fifth
- element of a single dimensional floating point type array, the
- following line would be fine:
-
-
- nTemperature = 98.6
- nPatient = 5
- A_STORE( aTemps, nTemperature, nPatient )
-
-
- However, if the array is multi-dimensional it is necessary to
- pass the index via the A_() function. For example, if you
- want to store the temperature of the fifth patient on the
- third day:
-
- A_STORE( aTemps, 98.6, A_( 5, 3 ) )
-
-
- It is not wise to try to figure out the actual integer offset
- of an element even though FlexFile would accept it; FlexFile
- does this very fast on its own. In addition, remember element
- A_( 5, 3 ) is not the same element as A_(3, 5), and rarely, if
- ever, will either array index refer to the fifteenth element
- as it is laid out in memory.
-
-
-
-
- Understanding FlexFile Arrays
-
- FlexFile arrays are similar to the arrays in languages such as
- C or Pascal. The array is one block of memory (with the
- exception of string arrays), and each element in the array
- must be of the same type.
-
- There is an analogy relating multi-dimensional arrays to a set
- of encyclopedias that helps in understanding and describing
- their use. This analogy is especially helpful in
- understanding arrays that span into the fourth dimension.
-
- Imagine that you have a character array. First, do not
- confuse character arrays and string arrays. A string array is
- an array of pointers that point to strings of varying length
- that reside in random positions in memory. The string array
- is actually an array of pointers and not an array of strings.
- Each element points to a string of any length.
-
- A character array is a matrix of one byte storage locations
- where each byte can hold one ASCII character. In the analogy
- of the encyclopedias, each letter is an element, a group of
- letters that form words make up one row of text. That one
- line implies the first dimension. Likewise, A group of lines
- that makes up one page implies the second dimension, a group
- of pages that makes up one volume implies the third dimension,
- and all the volumes in the set of encyclopedias implies the
- fourth dimensions. We could continue the analogy into the
- fifth dimension: a set of Britannica's next to The World Book
- set implies a magnitude of two in the fifth dimension.
-
- You will often see, in the Array Function Reference chapter,
- the concept of "wrapping". For example, A_SCAN() will wrap at
- the end of one line to the beginning of the next, and at the
- end of one page it will wrap to the top of the next page. All
- functions that work with wrapping look at the array as it is
- laid out in memory.
-
- It is important to dimension your arrays with this
- understanding in mind: the last dimension listed in the
- declaration varies the smallest step in memory. To declare
- the array for an encyclopedia you would want to declare it as
- follows:
-
- vols := 26
- pages := 150
- lines := 80
- chars := 95
- WorldBook = A_DECLARE( 'C', vols, pages, lines, chars )
-
- This declaration of a character array is actually illegal
- because the array would exceed memory, however, it is
- important to see how and why the dimensions are in the order
- they are in. The <chars> variable is last in order to insure
- that each character is next to its proper neighbor in memory.
- As far as A_STORE()ing and A_RETRIEVE()ing each character, the
- layout makes little difference. However, when you need to do
- something like an A_FILL() (for a blank line), this layout
- becomes critical.
-
- Lets say, for example, we want the fifth and sixth lines on
- the fifteenth page of the fourth volume to be filled with
- spaces.
-
- A_FILL( WorldBook, ' ', A_( 4, 15, 5, 1 ), 2 * lines )
-
-
- This function fills the 160 characters following the specified
- location. Because the fill always begins at a point in memory
- and moves to the next set of contiguous positions in memory,
- it becomes critical how the array was declared. For example,
- if we switch the order of the <lines> and <chars> in the
- declaration, and then perform the A_FILL(), the fill would put
- one space on each line for 160 lines instead of one space for
- each character for 160 characters.
-
- FlexFile String arrays (pointer arrays)
-
- Arrays of strings in FlexFile pose a peculiar problem. When
- the array is declared, FlexFile allocates memory for four
- bytes per element. These four bytes originally point to
- nothing (null). When you A_STORE() a string to an element,
- however, new memory is allocated for the string. This memory
- does not reside within the array, but rather, at some random
- location in memory. FlexFile knows where this is because it
- stores a pointer in the array which points to the new data.
-
- A problem arises because the array itself is a Clipper
- variable and has the scope of a Clipper variable. If you
- release this variable or allow it to fall out of scope,
- Clipper does not know that it was pointing to your strings,
- and so, Clipper releases the array of pointers without
- releasing the strings that it points to. In order to avoid
- this, it is necessary to A_KILL() a string array before
- allowing it to fall out of scope or be released.
-
-
-
- V_ALIAS()
- Return the alias of the current or a specified DBV work area
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_ALIAS( [<nDBVArea>] ) -> cDBVAlias
-
- Arguments
-
- <nDBVArea> is any valid DBV work area.
-
- Returns
-
- V_ALIAS() returns the alias of the DBV work area <nDBVArea>. If no
- <nDBVArea> is specified, then the alias of the current work area
- is returned.
-
- Description
-
- V_ALIAS() is used to return the name of a DBV work area. This name
- is either the name of the DBV file or the name specified as the
- second parameter in the V_USE() function. If there is no DBV file
- open in the <nDBVArea>, V_ALIAS() will return a null string ("").
-
- Any function which accepts a DBV area as a parameter can also
- accept an alias in place of the area.
-
- The alias is always returned in capital letters regardless of how
- it was passed to V_USE().
-
- Notes
-
- ■ Do not confuse Clipper's alias names with FlexFile's; they are
- mutually exclusive. For example, you can have a DBF file with an
- alias of "MYFILE" and simultaneously have a DBV file with the same
- alias.
-
- Examples
-
- // Open two DBV files in two new areas.
- V_SELECT(1)
- V_USE( "file1", "file_one" )// Creates if not existing
- V_SELECT(2)
- V_USE( "file2" ) // Creates if not existing
-
- ? V_ALIAS() // Returns: file2
- ? V_ALIAS(1) // Returns: FILE_ONE
-
-
- See Also: V_SELECT() V_USE() V_FILES() V_FILE()
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_BUFFERS()
- Declare or retrieve the number of DBV file buffers
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_BUFFERS( [<nBuffers>] ) -> nBuffers
-
- Arguments
-
- <nBuffers> is an integer value indicating a number of 1K buffers.
- The default (which is also the minimum value) is 3 buffers.
-
- Returns
-
- V_BUFFERS() returns an integer indicating the previous setting of
- the number of 1K buffers.
-
- Description
-
- FlexFile manages all file input and output through a set of 1K
- buffers. Because there is such a diversity in buffered I/O from
- machine to machine, FlexFile offers the ability to customize the
- amount of space used for this purpose.
-
- If you are running with a disk cache or are tight on memory, leave
- the buffers at their default (and minimum) value of 3. If you have
- the space and would like to increase performance, increase the
- number of buffers.
-
- Notes
-
- ■ The buffers may only be changed when no DBV files are in use.
-
- Examples
-
- // Set FlexFile's buffers to 5K
- V_BUFFERS(5)
-
- V_USE( "file" ) // Open a file.
-
- // This line has no effect because files are open.
- V_BUFFERS(10)
-
- ? V_BUFFERS() // Result: 5
-
-
- See Also: V_FILES() V_USE()
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_CLOSE()
- Close a DBV type file
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_CLOSE( [<nWorkArea> | <cAlias>] )
-
- Arguments
-
- <nWorkArea> or <cAlias> is the DBV area or alias to close. If none
- is specified the file in the current DBV area is closed.
-
- Returns
-
- None.
-
- Description
-
- V_CLOSE() closes a FlexFile DBV type file. This is equivalent to
- V_USE() with no arguments.
-
- Notes
-
- ■ This function does not affect and is not affected by any
- Clipper data base functions or commands.
-
- Examples
-
- // Open a DBV type file in FlexFile's area 1.
- V_SELECT(1)
- V_USE( "file" )
-
- // Select a second area just for the heck of it.
- V_SELECT(2)
-
- // Close the file in area one.
- V_CLOSE(1)
-
- // Close a file (if one is open) in area 2
- V_CLOSE()
-
- See Also: V_USE() V_CLOSEALL()
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_CLOSEALL()
- Close all open DBV type files
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_CLOSEALL()
-
- Arguments
-
- None.
-
- Returns
-
- None.
-
- Description
-
- V_CLOSEALL() closes all open DBV type files in all open DBV work
- areas. In addition, the cache described by V_BUFFERS() and
- V_FILES() is released.
-
- Notes
-
- ■ This function does not affect and is not affected by any
- Clipper data base functions or commands.
-
- Examples
-
- // Open a DBV type file in FlexFile's area 1.
- V_SELECT(1)
- V_USE( "file" )
-
- // Open a second file in the next available area.
- V_USE( "file2", , "NEW" )
-
- // Close all open files.
- V_CLOSEALL()
-
- See Also: V_CLOSE() V_USE()
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_COMMIT()
- Commit the DOS buffers to disk.
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_COMMIT( [<nArea> | <cAlias>] ) -> lSuccess
-
- Arguments
-
- <nArea> or <nAlias> is the DBV work area or alias whose buffers
- will be flushed. Omitting this parameter causes all open DBV file
- buffers to be flushed.
-
- Returns
-
- V_COMMIT() returns a (.T.) on success. Otherwise, it returns
- (.F.).
-
- Description
-
- DOS "buffers" disk I/O in order to speed up disk access. The
- downside to this feature is that the data in the buffers can be
- lost if the machine "hangs" or is powered down before the buffers
- are copied to disk. This problem was addressed in DOS version 3.3
- and later by allowing a call which forces DOS's buffers to be
- written to disk. V_COMMIT() makes this call to DOS as described
- below.
-
- By default, FlexFile automatically commits all DOS buffers after
- every write operation. If you like this behavior, you should never
- need to call V_COMMIT(). This is the safest method but also the
- slowest. In order to change this default behavior, the
- V_SET_COMMIT() function can be passed a logical (.T.) or (.F.) to
- turn on/off the automatic flushing feature. If automatic flushing
- is turned off, you must call V_COMMIT() explicitly in order to
- flush the DOS buffers as described below.
-
- If no parameter is passed, V_COMMIT() flushes all open DBV work
- areas to disk.
-
- If a numeric DBV work area or a character alias is passed,
- V_COMMIT() will flush the buffers associated with the work area
- specified.
-
- ┌──────────────────────── WARNING ─────────────────────────┐
- │ V_COMMIT and V_SET_COMMIT() are based on functions │
- │ provided in DOS 3.3 and later. Calls made to these │
- │ functions on an earlier version of DOS will have no │
- │ affect. │
- └──────────────────────────────────────────────────────────┘
-
- Example
-
- // Turn off automatic flushing in order to speed up operation.
- V_USE( "temp" )
- V_SET_COMMIT(.f.)
-
- DO WHILE !EOF()
- IF DELETED()
- REPLACE vlf_fld WITH V_DELETE( vlf_fld )
- ENDIF
- SKIP
- ENDDO
- PACK
-
- // Flush the buffers and turn automatic flushing back on.
- V_COMMIT()
- V_SET_COMMIT(.T.)
-
-
- See also: V_SET_COMMIT() V_REPLACE() V_DELETE()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_DECRYPT()
- Decrypt a variable that has been encrypted with V_ENCRYPT()
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_DECRYPT( <cEncrypted_string> ) -> cOriginal
-
- Arguments
-
- <cEncrypted_string> is a variable previously encrypted with
- the V_ENCRYPT() function.
-
- Returns
-
- V_DECRYPT() returns a string as it was before a call to V_ENCRYPT().
-
- Description
-
- V_DECRYPT() will decrypt a string that has been previously encrypted
- with the V_ENCRYPT() function. The string will only be decrypted
- properly if the V_SETKEY() function has been called with the same key
- that was in effect when the V_ENCRYPT() originally scrambled the
- <cEncrypted_string>.
-
- Examples
-
- LOCAL cSecure, cOriginal
-
- // Set the key to my dog's name.
- V_SETKEY( "Tally" )
-
- // Encrypt a character string. Store the result in <cSecure>.
- cSecure = V_ENCRYPT( "Just try to decode <cSecure> without my dog." )
-
- // Later, decode the secured string with the help of my golden.
- // The call to V_SETKEY() is redundant because the program has not
- // terminated and it has not been set to a different V_SETKEY().
- V_SETKEY( "Tally" )
- cOriginal = V_DECRYPT( cSecure )
-
-
- See Also: V_SETKEY() V_ENCRYPT()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_DELETE()
- Delete one field from a DBV file
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_DELETE( <cPointer>,
- [<nArea> | <cAlias>] ) -> cNull
-
- Arguments
-
- <cPointer> is a six byte pointer-field (FlexFile's version of a
- memo-field).
-
- <nArea> or <nAlias> is the DBV work area or alias with which
- <cPointer> is related.
-
- Returns
-
- V_DELETE() returns a null string ("").
-
- Description
-
- V_DELETE() releases the space pointed to by <cPointer>. This space
- is then available for use by the next call to V_REPLACE() or any
- other function that requires DBV space. It is important to
- remember that there is no V_RECALL(). That is, once a DBV has been
- V_DELETE()d, that field is no longer recoverable.
-
- When you delete a record in a DBF file and you want to be able to
- recall that record (and its related VLF), do not use V_DELETE().
- Instead, just DELETE the record in the DBF. When you are ready to
- PACK the DBF, run a routine similar to the example below.
-
- ┌──────────────────────── WARNING ─────────────────────────┐
- │ V_DELETE() deletes the data associated with <cPointer>. │
- │ Attempting to use <cPointer> after this function deletes │
- │ the data that it points to can corrupt the DBV file. │
- └──────────────────────────────────────────────────────────┘
-
- Notes
-
- ■ V_DELETE() is permanent; there is no V_RECALL().
-
- ■ V_DELETE() is not necessary before a V_REPLACE(). The second
- parameter of V_REPLACE() is a pointer whose data space will be
- released before the REPLACE.
-
- Examples
-
- // Open a DBF and its related DBV
- USE dbf_file
- V_USE( "dbv_file" )
-
- // Store some data in the DBV and a pointer to the
- // data in a six byte pointer-field in the DBF
- REPLACE vlf WITH V_REPLACE( "This string is doomed", vlf )
-
- // Now delete that string.
- REPLACE vlf WITH V_DELETE( vlf )
-
- // Note: It is important to erase the pointer stored in
- // vlf once its data has been deleted. Because
- // V_DELETE() returns a null string, REPLACEing <vlf>
- // guarantees that the pointer-field vlf will be
- // destroyed.
-
- See Also: V_REPLACE() V_STUFF()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_ENCRYPT()
- Encrypt a Clipper string variable
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_ENCRYPT( <cString> ) -> cGobbleTgook
-
- Arguments
-
- <cString> is any valid Clipper character string.
-
- Returns
-
- V_ENCRYPT() returns an ecrypted string with the same length as
- the original.
-
- Description
-
- V_ENCRYPT() encrypts a Clipper string based on the current key setting
- (see V_SETKEY()). The string can later be V_DECRYPT()ed by using the
- same V_SETKEY() setting.
-
- V_ENCRYPT() encrypts a Clipper string so that it is not human readable.
- The encryption algorithm has not been designed to any particular
- specification, however, as the author of the algorithm, I would not
- want to be faced with the task of decrypting a string without the
- <key> with which it was encrypted (see V_SETKEY()).
-
- Examples
-
- LOCAL cSecure, cOriginal
-
- // Set the key to my dog's name.
- V_SETKEY( "Tally" )
-
- // Encrypt a character string. Store the result in <cSecure>.
- cSecure = V_ENCRYPT( "Just try to decode <cSecure> without my dog." )
-
- // Later, decode the secured string with the help of my golden.
- // The call to V_SETKEY() is redundant because the program has not
- // terminated and it has not been set to a different V_SETKEY().
- V_SETKEY( "Tally" )
- cOriginal = V_DECRYPT( cSecure )
-
-
- See Also: V_SETKEY() V_DECRYPT()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_ERROR()
- Report specific error codes from the DBV system
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_ERROR() -> nErrorCode
-
- Arguments
-
- None.
-
- Returns
-
- V_ERROR() returns the FlexFile error code as a numeric integer.
-
- Description
-
- V_ERROR() is an error reporting function that will return the most
- recent error code that FlexFile set. If a failed operation has no
- FlexFile error code check the DOS error code by using Clipper's
- DOSERROR() function.
-
- For a complete list of error codes and their descriptions refer to
- Appendix B.
-
- Examples
-
- // Trying to V_REPLACE() data in an area that does not have a
- // file open causes an error.
- V_FILES(4)
- USE dbf_file // Valid DBF file is opened.
- V_SELECT( 4 ) // No DBV file is open in area 4.
-
- // V_REPLACE() will return (.F.) because there is no file
- // open in area 4. Because vlf is a six byte character
- // field, a runtime "data type mismatch" is produced.
- REPLACE vlf WITH V_REPLACE("Data type mismatch", vlf)
-
- // In errorsys.prg...
- ? V_ERROR() // Returns 7301.
- // Appendix B: DBV file not open.
-
-
- See Also: errcodes.ngo:"Error Codes Introduction"
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_EXCLUSIV()
- Establish exclusive or shared use of a DBV type file
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_EXCLUSIV( <lToggle> ) -> lSetting
-
- Arguments
-
- <lToggle> is a logical value. If <lToggle> is (.T.), then
- subsequent files opened with V_USE() will be opened exclusively.
-
- If <lToggle> is (.F.), then subsequent files opened with V_USE()
- will be opened in shared mode.
-
- Returns
-
- The current setting of V_EXCLUSIV().
-
- Description
-
- In a network environment, V_EXCLUSIV() determines whether the
- V_USE() function specified without the <lExclusive> parameter will
- be opened in shared or exclusive mode. If <lToggle> is (.T.) (the
- default), other users cannot V_USE() the same file until it has
- been closed.
-
- If <lToggle> is (.F.), all subsequent files opened by V_USE() without the
- <lExclusive> parameter will be opened in shared mode. Access by
- other users must be controlled programmatically. Typically, this
- can be done with Clipper's RLOCK() and FLOCK() functions. That is,
- if the pointer to a DBV is kept in a DBF file, then RLOCK()ing the
- record containing the pointer will prevent other users from
- accessing that field.
-
- Refer to Network Programming for more information.
-
- Notes
-
- ■ Error handling: Attempting to V_USE() a file which has been
- opened exclusively by another user causes V_USE() to return a -1.
- V_ERROR() will return an error code indicating this condition.
-
- Examples
-
- // Set up the environment so that all files are opened
- // in shared mode.
- #define EXCLUSIVE (.T.)
- V_EXCLUSIV( !EXCLUSIVE )
-
- // This file will be opened in shared mode.
- IF V_USE( "mainfile" ) == -1
- ? "Error: " + str( V_ERROR(), 4 )
- QUIT
- ENDIF
-
- // This V_USE() overrides the global V_EXCLUSIV() setting
- // and opens the file exclusively.
- V_USE( "tempfile", , "NEW", EXCLUSIVE )
-
- // Close all files.
- V_CLOSEALL()
-
- See Also: V_USE() network.ngo:"Network Programming"
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_FILE2VLF()
- Copy a DOS file into a VLF
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_FILE2VLF( <cFileName>,
- <cOldPointer> ) -> cNewPointer
-
- Arguments
-
- <cFileName> is the name of a disk file optionally including the
- path and drive designators.
-
- <cOldPointer> is a required six byte pointer-field or variable in
- which you have previously stored a pointer to variable length
- data. Passing six spaces causes FlexFile to assume that there is
- no old data to be released before the new <exp> data is saved.
-
- Returns
-
- V_FILE2VLF() returns a pointer which should be stored in the
- pointer- field with which the copied file is to be associated.
-
- V_FILE2VLF() returns (.F.) on error. This causes the error system
- to be invoked with a "Data Type Mismatch". Use V_ERROR() to fetch
- the specific error value (see Appendix B for a table of error
- descriptions).
-
- A typical error from this function is "File not found". It is,
- therefore, the responsibility of the programmer to test for this
- condition before executing V_FILE2VLF().
-
-
- Description
-
- V_FILE2VLF() provides a mechanism for copying a DOS disk file into
- a VLF. This is particularly handy in converting an application
- which has used Clipper's MEMOWRITE() function.
-
- V_FILE2VLF() is also handy for copying graphics images from disk
- files into a DBV file. When used in conjunction with V_VLF2FILE()
- a system can be implemented to handle graphics images which is
- compatible with the file based graphics systems such as DGE,
- SilverPaint, Flipper and the like.
-
- ┌────────────────────────── WARNING ──────────────────────────┐
- │ V_FILE2VLF() deletes the data associated with <cOldPointer> │
- │ before returning <cNewPointer>. Attempting to use │
- │ <cOldPointer> after this function deletes the data that it │
- │ points to can corrupt the DBV file. │
- └─────────────────────────────────────────────────────────────┘
-
- Notes
-
- ■ No additional memory is required to copy a file into a VLF. It
- is, therefore, possible to import a file larger than 65K
- (Clipper's variable size limit).
-
- ■ V_TYPE() will return "C" (character) for any VLF that has been
- created by V_FILE2VLF(). This implies that V_RETRIEVE() will
- return a character string.
-
- Examples
-
- // Open a DBF file and its related DBV file
- // The dbf_file has a 12 byte field called "exe_name"
- // and the usual 6 byte field called "vlf"
- USE dbf_file
- ZAP
- INDEX ON exe_name TO dbf_file
- V_USE( "dbv_file" )
-
- // This may seem silly, but lets store the Clipper compiler
- // in the DBV file.
- APPEND BLANK
- REPLACE exe_name WITH "CLIPPER.EXE"
-
- // This will copy the Clipper.exe into a VLF.
- REPLACE vlf WITH V_FILE2VLF( exe_name, vlf )
-
- // Later when we want to execute Clipper (you better have
- // lots of memory).
- SEEK "CLIPPER.EXE"
- ? V_VLF2FILE( "TEMP.EXE", vlf )
- ? V_ERROR()
-
- RUN temp
-
-
- See Also: V_DBV2FILE() V_RETRIEVE()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_FILENAME()
- Return the file name of a file opened in a specified area
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_FILENAME( [<nArea> | <cAlias>] ) -> cFileName
-
- Arguments
-
- <nArea> or <cAlias> refers to the number or name of the target DBV
- work area. If not specified, V_FILENAME() returns the file name
- from the currently selected DBV work area.
-
- Returns
-
- V_FILENAME() returns the DOS file name of the DBV file opened in
- the specified area. If no file is open in the specified area,
- V_FILENAME() returns a null string ( "" ).
-
- Description
-
- V_FILENAME() is used to retrieve the DOS file name that refers to
- the DBV file. This name will not include the drive or path
- designators.
-
- This function is provided specifically for debugging where it is
- sometimes insufficient to only have access to the alias.
-
- Examples
-
- // Show the name of the file (not the alias)
- V_SELECT(1)
- V_USE( "pic_file.dbv", "pictures" )
-
- ? V_FILENAME() // Returns: PIC_FILE.DBV
- ? V_ALIAS() // Returns: PICTURES
-
- V_SELECT(2)
- ? V_FILENAME( "PICTURES" )// Returns: PIC_FILE.DBV
-
-
- See Also: V_ALIAS()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_FILES()
- Set the maximum number of DBV files to be in use concurrently
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_FILES( [<nMaxFiles>] ) -> nCurrentMax
-
- Arguments
-
- <nMaxFiles> is the maximum number of DBV type files that can be in
- V_USE() concurrently. If none is specified, V_FILES() will simply
- return the current setting.
-
- Returns
-
- V_FILES() returns the current setting of the maximum file count.
-
- Description
-
- V_FILES() offers the programmer the opportunity to set the maximum
- number of files that the program will have in use at any one time.
- This feature allows FlexFile to keep the memory used for the file
- headers in a contiguous block which avoids memory fragmentation.
-
- Each file requires 84 bytes for the header information. Therefore,
- multiply the <nMaxFiles> by 84 in order to calculate the total
- memory requirement for the files opened in your system.
-
- Notes
-
- ■ The maximum number of files cannot be changed unless all DBV files are
- closed.
-
- ■ This function is independent of the V_BUFFERS() setting.
-
- Examples
-
- // Set FlexFile's maximum file count to 2 files
- V_FILES(2)
-
- V_USE( "file1" ) // Open first file.
- V_USE( "file2", ,"NEW" ) // Open second file
- // in a new area.
-
- // Attempt to open a third file in a new area fails.
- IF V_USE( "file3", ,"NEW" ) == -1
- ? "Too many files in use."
- ? V_ERROR() // Result: 8001
- ENDIF
-
- // This line has no effect because files are open.
- V_FILES(5)
-
- ? V_FILES() // Result: 2
-
-
- See Also: V_BUFFERS() V_USE()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_FILLARR()
- Fill a Clipper array with contents stored to a DBV file
- ───────────────────────────────────────────────────────────────────────────────
-
- See V_ARETRIEV() for retrieving Clipper 5.0 arrays
-
- Syntax
-
- V_FILLARR( <aTarget>,
- <cPointer>,
- [<nArea> | <cAlias>] )
-
- Arguments
-
- <aTarget> is the Clipper array to be filled.
-
- <cPointer> is a six byte pointer-field that points to the DBV
- containing a Clipper type array.
-
- <cAlias> or <nArea> is a DBV file alias or area specified when the
- file was V_USE()d. If omitted, the pointer will point into the
- currently selected DBV area.
-
- Returns
-
- None. However, <aTarget> is modified.
-
- Description
-
- V_FILLARR() is used to fill a Clipper S87 type array. The <aTarget>
- array must exist and will be filled until <aTarget> has no remaining
- elements or the array pointed to by <cPointer> has no more elements
- (which ever limit is reached first).
-
- Use the V_LEN() function to dimension the array immediately before
- V_FILLARR() (see examples below).
-
- The ability to save Clipper arrays is one of the most powerful
- features of FlexFile. Essentially, it simulates Variable Length
- Records as well as creating a three dimensional effect in your
- data base files.
-
- For example, picture a student master DBF file with the fields
- LastName, FirstName, Addr, Major, and Minor. If you decide to
- expand the file and include the sports, clubs and associations
- that the student is involved in, you have two choices. You can
- create a new related file (with a new index), or you can insert
- several new fields in the master DBF for each category, limiting
- the entries possible in any one category and wasting space on
- students who do not have entries in one or more of the categories.
-
- With FlexFile, however, you can add just one field in the master
- file and save an array of any length to this field. Not only do
- you eliminate a file, its index, and its relation, but also, one
- function call can load arrays with the new data eliminating the
- need to code "scatter" and "gather" routines.
-
- Notes
-
- ■ You must use this function from within a Clipper 5.0 application
- only to retrieve an array which was stored with a FlexFile S87
- library version 1.01 or less (version 1.01 was dated 2/18/91).
- See V_FILLEN() for an example of a conversion routine.
-
- ■ It is not necessary to use this routine to retrieve a FlexFile
- type array.
-
- Examples
-
- && S'87 compiler only. See V_ARETRIEV() for Clipper 5.0
-
- && Open a DBF and a related DBV file
- USE dbf_file
- V_USE( "dbv_file" )
-
- DECLARE aNames[3]
- aNames[1] = "Tania"
- aNames[2] = "Mary"
- aNames[3] = "Allison"
-
- && Store the array to the DBV file and its pointer to the DBF
- REPLACE vlf WITH V_REPLACE( aNames, vlf )
-
- && Declare the new array to the proper size.
- DECLARE aNewNames[ V_LEN( vlf ) ]
-
- && Fill the array with the data.
- V_FILLARR( aNewNames, vlf )
-
- && Show that it worked
- ? aNewNames[1] && Result: Tania
-
-
-
- See Also: V_FILLEN() V_ARETRIEV() V_AREPLACE() V_REPLACE() V_LEN()
-
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_FILLLEN()
- Return the length of a S'87 array.
- ───────────────────────────────────────────────────────────────────────────────
-
- See V_ARETRIEV() for retrieving Clipper 5.0 arrays
-
- Syntax
-
- V_FILLEN( <cPointer>, [<nArea> | <cAlias>] )
-
- Arguments
-
- <cPointer> is a six byte pointer-field that points to the DBV
- containing a Clipper type array that was created by an application
- compiled with the S'87 compiler and linked with Flex_87.lib version
- 1.01 or earlier (version 1.01 was dated 2/18/91).
-
- <cAlias> or <nArea> is a DBV file alias or area specified when the
- file was V_USE()d. If omitted, the pointer will point into the
- currently selected DBV area.
-
- Returns
-
- The length of the array as it was stored.
-
- Description
-
- V_FILLEN() is used in conjunction with V_FILLARR() in order to convert
- an array which was saved by a previous version of FlexFile. Only use
- this function pair to retrieve arrays created with the S'87 compiler
- into an application which is compiled with the Clipper 5.0 compiler.
-
- Use the V_FILLEN() function to dimension the array immediately before
- V_FILLARR() (see examples below).
-
- Notes
-
- ■ This is a compatibility function only and should be used only to
- convert arrays that were saved with earlier versions of FlexFile to
- new format.
-
- ■ It is not necessary to use this routine to retrieve a FlexFile
- type array.
-
- Examples
-
- && Clipper 5.0 compiler retrieving an array saved with
- && FlexFile version 1.01 or earlier.
- LOCAL aNewNames
-
- && Open a DBF and a related DBV file
- USE dbf_file
- V_USE( "dbv_file" )
-
- && Declare the new array to the proper size.
- DECLARE aNewNames[ V_FILLEN( vlf ) ]
-
- && Fill the array with the data.
- V_FILLARR( aNewNames, vlf )
-
- && Save it back for future easy use.
- dbf_file->vlf := V_AREPLACE( aNewNames, dbf_file->vlf )
-
- && Now it is easy to get at:
- aNewNames := V_ARETRIEVE( dbf_file->vlf )
-
-
- See Also: V_ARETRIEV() V_AREPLACE() V_REPLACE() V_LEN()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_GETWNDRC()
- Return the rows or columns from a Proclip window stored in a DBV file
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_GETWNDRC( <cPointer>, <cRowOrCol> ) -> nValue
-
- Arguments
-
- <cPointer> is a six byte pointer-field (FlexFile's version of a
- memo-field).
-
- <cRowOrCol> is either an 'R' or a 'C' (non case sensitive)
- requesting the row or column respectively.
-
- Returns
-
- V_GETWNDRC() returns the rows or columns of a Proclip window in a
- DBV file much like Proclip's WNDVROWS() and WNDVCOLS() would.
-
- Description
-
- V_GETWNDRC() is used to query a Proclip window that has been saved
- to a DBV. The rows and columns are the virtual rows and columns
- and not the rows and columns of a viewport that may have been
- active when the window was V_REPLACE()d.
-
-
- Examples
-
- // Create a proclip window
- pc_handle = WNDCREATE( 5, 10 )
-
- // Save the window to a DBV file
- REPLACE vlf WITH V_REPLACE( pc_handle, , , 'P' )
-
- // Show the rows and columns of the window.
- ? V_GETWNDRC( vlf, 'R' ) // Result: 5
- ? V_GETWNDRC( vlf, 'C' ) // Result: 10
-
-
- See Also: V_REPLACE() V_TYPE()
-
- ───────────────────────────────────────────────────────────────────────────────
- V_HANDLE()
- Return the DOS file handle for a DBV file.
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_HANDLE( [<nArea> | <cAlias>] ) -> nHandle
-
- Arguments
-
- <nArea> or <cAlias> refers to the number or name of the target DBV
- work area. If not specified, the current DBV work area is assumed.
-
- Returns
-
- V_HANDLE() returns a numeric integer whose value is the DOS file handle
- for the specified DBV work area.
-
- Description
-
- V_HANDLE() can be used in conjunction with Clipper's Fxxxx() class of
- low level file functions. Great care must be taken when using FWRITE()
- to assure that the bounds of the VLF are not overwritten. It is far
- safer and usually sufficient to use V_RETRIEVE() and V_POKE() to manage
- low level access to a VLF.
-
- ┌───────────────────────── WARNING ───────────────────────────┐
- │ Extreme care must be taken when using FWRITE() on a DBV │
- │ type file. Overwriting the bounds of a VLF by one byte can │
- │ corrupt the entire file. │
- └─────────────────────────────────────────────────────────────┘
-
-
- Examples
-
- #include "fileio.ch"
- LOCAL buffer
-
- // Open a DBF file and its related DBV file
- USE dbf_file
- V_USE( "dbv_file" )
-
- FSEEK( V_HANDLE(), V_PTR( vlf_fld ), FS_SET )
-
- buffer = SPACE( V_LEN( vlf_fld ) )
- FREAD( V_HANDLE(), @buffer, LEN(BUFFER) )
-
- // The above code will fetch a VLF without file locking or
- // error checking just like the following one line of code:
- // buffer = V_RETRIEVE( vlf_fld )
-
-
- See Also: V_POKE() V_RETRIEVE() V_PTR() V_LEN()
-
- ────────────────────────────────────────────────────────────────────────────────
- V_ISOPEN()
- Determine if a file is open in an area.
- ────────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_ISOPEN( [<nArea> | <cAlias>] ) -> lStatus
-
- Arguments
-
- <nArea> or <cAlias> refers to the number or name of the target DBV
- work area. If not specified, the current DBV work area is assumed.
-
- Returns
-
- V_ISOPEN() returns (.T.) if there is a file open in the current or
- specified DBV work area. Otherwise, it returns (.F.).
-
- If a character alias is passed, V_ISOPEN() will return true if the
- alias is valid in any DBV work area. If the character alias is
- not valid for any DBV work area, V_ISOPEN() will return (.F.).
-
- Description
-
- V_ISOPEN() tests the current or specified area returning a logical
- (.T.) if a file was found to be open in that area. This function
- is important because the behavior of V_SELECT() does not allow
- this test as SELECT() does in Clipper (see V_SELECT()).
-
- Examples
-
- V_FILES(5) // Set maximum open files to five
- V_USE( "file1" ) // Open files in areas one and three.
- V_SELECT(3)
- V_USE( "file2" )
-
- FOR x = 1 TO 5
- ? V_ISOPEN(x), x // Results: .T. for x=1 and x=3
- NEXT
-
- IF V_ISOPEN( "bogus" ) .OR. !V_ISOPEN( "file1" )
- ? "This is unreachable code."
- ELSE
- ? "Every thing went as expected!"
- ENDIF
-
-
- See also: V_SELECT(), V_ALIAS(), V_USE()
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_LEN()
- Return the length of data stored in a DBV
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_LEN( <cPointer>,
- <nArea> | <cAlias> ) -> nCount
-
- Arguments
-
- <cPointer> is a six byte pointer-field (FlexFile's version of a
- memo-field).
-
- <nArea> or <cAlias> refers to the number or name of the target DBV
- work area. If not specified, the current DBV work area is assumed.
-
-
- Returns
-
- V_LEN() returns the length of a character string or the number of
- elements in an array as a numeric integer. V_LEN() returns only
- the number of elements in the first dimension of a Clipper 5.0
- array.
-
- Description
-
- With a character string, V_LEN() returns the number of bytes of
- the data associated with <cPointer>. This count will include any
- imbedded null bytes (CHR(0)).
-
- With an array, V_LEN() returns the number of elements of the array.
-
- For all other data types, V_LEN() returns 0.
-
-
- Examples
-
- // Declare and assign two local variables to be used.
- LOCAL cString, aNames := { "Sandra", "Beth", "Pirko" }
- cString = "This is a test"
-
- // Open a DBF file and its related DBV file
- USE dbf_file
- V_USE( "dbv_file" )
-
- // Store a string to record 1 and an array to record 2
- REPLACE vlf WITH V_REPLACE( cString, vlf )
- SKIP
- REPLACE vlf WITH V_AREPLACE( aNames, vlf )
-
- GO TOP
- ? V_LEN( vlf ) // Result: 14
- SKIP
- ? V_LEN( vlf ) // Result: 3
-
-
-
- See Also: V_TYPE() V_REPLACE() V_RETRIEVE() V_FILLARR()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_POKE()
- Write character data into a character type VLF
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_POKE( <cPointer>,
- <cData>,
- [<nOffset>] )
-
- Arguments
-
- <cPointer> is a six byte pointer-field (FlexFile's version of a
- memo-field).
-
- <cData> is a character string to be written into the data pointed
- to by <cPointer>. If the length of <cData> is greater than
- V_LEN(<cPointer>) - <nOffset>, the data will be trucated.
-
- <nOffset> is the offset within the data pointed to by <cPointer>
- at which to begin writing <cData>. If not specified, <nOffset>
- defaults to 1.
-
- Returns
-
- None.
-
- Description
-
- V_POKE() is used when you want to overwrite some or all of a
- character type VLF. V_POKE() is different than V_STUFF() in that
- it does not change or return <cPointer>. Instead, V_POKE()
- modifies the data directly on the disk at its present location.
-
- V_POKE() is different than V_REPLACE() in that it cannot extend
- the length of the data pointed to by <cPointer> nor can it release
- any space associated with <cPointer>.
-
- Notes
-
- ■ V_POKE() is most useful when you know that the new data is the
- same length (or a subset) of the old data.
-
- Examples
-
- // Open a DBF and a related DBV file.
- USE Main.dbf
- V_USE( "Main.dbv" )
-
- // Replace can store any length data.
- APPEND BLANK
- REPLACE vlf_fld WITH V_REPLACE( "ABCDEFGH", vlf_fld )
-
- // Poke some data into the file.
- V_POKE( vlf_fld, "test", 3 )
- ? V_RETRIEVE( vlf_fld )// Result: ABtestGH
-
- // Try to write past the end of the fields current length.
- V_POKE( vlf_fld, "You cannot do much harm", 3 )
- ? V_RETRIEVE( vlf_fld )// Result: ABYou ca
-
-
-
- See Also: V_REPLACE() V_STUFF()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_PTR()
- Return the absolute offset (file pointer) of data stored in a DBV file
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_PTR( <cPointer> ) -> nOffset
-
- Arguments
-
- <cPointer> is a six byte pointer-field (FlexFile's version of a
- memo-field).
-
- Returns
-
- V_PTR() returns the absolute offset of data pointed to by
- <cPointer> in the DBV file associated with <cPointer>.
-
- Description
-
- For those who use Clipper's FOPEN() class of functions and who
- would like direct access to the data in a DBV type file, FlexFile
- provides V_PTR(). However, it is far safer to use V_RETRIEVE() and
- V_POKE().
-
- It must be noted that extreme care should be exercised when
- writing data into the DBV file. You should never write data that
- begins before V_PTR() or data which extends beyond V_LEN().
-
- ┌───────────────────────── WARNING ───────────────────────────┐
- │ Extreme care must be taken when using FWRITE() on a DBV │
- │ type file. Overwriting the bounds of a VLF by one byte can │
- │ corrupt the entire file. │
- └─────────────────────────────────────────────────────────────┘
-
-
- Examples
-
- // Open a DBF file and its related DBV file.
- USE dbf_file
- V_USE( "dbv_file" )
-
- ? V_PTR( vlf ) // Result if the data related to vlf
- // is 11,222 bytes from the beginning
- // of dbv_file.dbv: 11222
-
-
- See Also: V_RETRIEVE() V_POKE()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_REPLACE() / V_REP()
- Replace data stored in a DBV file with new data
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_REPLACE( <exp>,
- <cOldPointer>,
- [<cAlias> | <nArea>],
- [<cDataType>]) -> cNewPointer
-
- Arguments
-
- <exp> is any valid clipper variable including single or
- multi-dimensional arrays, FlexFile arrays, MemoEdit() strings,
- SaveScreen() strings, any binary data stored in a Clipper
- variable, as well as numerics, dates, and logicals, and Proclip
- windows.
-
- <cOldPointer> is a required six byte pointer-field or variable in
- which you have previously stored a pointer to variable length
- data. Passing six spaces causes FlexFile to assume that there is
- no old data to be released before the new <exp> data is saved.
- Refer to the discussion below for further explanation.
-
- <cAlias> or <nArea> is a DBV file alias or area specified with
- V_USE() or V_SELECT(). If omitted, the replace will occur in the
- current DBV area.
-
- <cDataType> is an expression which describes the data type of
- <exp>. FlexFile will assume Clipper's data type if this parameter
- is omitted. Only the first character of <cDataType> is significant
- (e.g. "C" is equivalent to "Character" ).
-
- This parameter is almost never necessary in this release of FlexFile.
- This is because the type of the data being saved is usually
- non-ambiguous. However, when saving either FlexFile's own strongly
- typed arrays or Proclip(tm) windows, it is necessary to tell FlexFile
- what you are saving.
-
- This is because FlexFile strongly typed arrays appear to Clipper as
- character data and Proclip window handles appear to Clipper as numeric
- values. So, for example, if you save a Proclip window handle without
- providing this parameter, FlexFile will save the handle instead of
- the contents of the window.
-
-
- Table: V_REPLACE() data type codes
-
- ┌──────────────────────────────────────────────┐
- │ Character Description │
- ├──────────────────────────────────────────────┤
- │ C Clipper character data │
- │ N Clipper numeric │
- │ L Clipper logical │
- │ D Clipper date │
- │ A Clipper array │
- │ P Proclip window handle │
- │ F FlexFile strongly typed array │
- └──────────────────────────────────────────────┘
-
- Returns
-
- V_REPLACE() returns a pointer which should be stored in the
- pointer- field with which the variable length data is to be
- associated.
-
- V_REPLACE() returns (.F.) on error. This causes the error system
- to be invoked with a "Data Type Mismatch". Use V_ERROR() to fetch
- the specific error value (see Appendix B for a table of error
- descriptions).
-
- Description
-
- V_REPLACE() stores the variable length data defined by <exp> and
- returns a six byte pointer <cNewPointer>. This pointer is the only
- way FlexFile will ever be able to access the <exp> data; if this
- pointer is lost the data in the DBV file will be inaccessible.
-
- It is highly recommended, therefore, that the V_REPLACE() function
- be imbedded in the same line of code as the Clipper REPLACE
- command (see examples below). <cNewPointer> will then be stored
- directly into a six byte pointer-field in the related DBF file.
-
- V_REPLACE() first deletes the data associated with <cOldPointer>
- freeing up the space, if any, that it was occupying. V_REPLACE()
- then looks for the smallest available space to put the <exp> new
- data. Finally, it returns <cNewPointer> to be used at any time by
- V_RETRIEVE(), V_REPLACE(), V_LEN(), etc. In most cases, you will
- be storing the <cNewPointer> in a DBF file (highly recommended).
-
- In designing the associated DBF structure, you will define a
- pseudo memo-field which will be a six byte (or more) character
- type field. FlexFile refers to these fields as pointer-fields.
- When a FlexFile pointer is stored in this field, the field will
- have six bytes of ASCII characters from the "irrational" range
- (128-255). This may appear as "garbage", but is actually a very
- compact encoded structure. It is encoded only to insure that nulls
- are never stored in your DBF file. After creating this field you
- can ignore it exactly as you would a DBT memo-field.
-
- The V_REPLACE() function replaces data in the current DBV area or
- the <nArea>/<cAlias> area if specified. Attempting to use
- <cOldPointer> which points into one DBV file to delete/replace
- data in any other DBV file can be dangerous. Although there is a
- degree of protection against this kind of programmer error, it is
- possible that random data will be deleted from the target area
- corrupting that file.
-
-
- Incorrect: <fld1> is pointing to data in DBV area 1 but being used
- to refer to data in DBV area 2.
-
- V_SELECT(1)
- REPLACE fld1 WITH V_REPLACE( "No problem yet", fld1 )
- │
- └─────────────────────────────────────────────────┐
- V_SELECT(2) │
- REPLACE fld1 WITH V_REPLACE( "File corruption possible", fld1)
-
-
- Correct: <fld1> is being used consistently in DBV area 1.
-
- V_SELECT(1)
- REPLACE fld1 WITH V_REPLACE( "Much better", fld1 )
- └──────────────────────────────┐
- │
- REPLACE fld1 WITH V_REPLACE( "Best", fld1 )
-
-
-
- ┌────────────────────────── WARNING ──────────────────────────┐
- │ V_REPLACE() deletes the data associated with <cOldPointer> │
- │ before returning <cNewPointer>. Attempting to use │
- │ <cOldPointer> after this function deletes the data that it │
- │ points to can corrupt the DBV file. │
- └─────────────────────────────────────────────────────────────┘
-
- Notes
-
- ■ All file sharing within the DBV file is handled automatically.
- It is the programmers responsibility to handle any one
- pointer-field exactly as you would any DBF field (i.e. use
- Clippers FLOCK()/RLOCK() functions). If a record is successfully
- locked with Clippers RLOCK() function, the pointer-field will be
- inaccessible to other users until the current task releases it.
-
- ■ If you use comparison of data in your networking code you are
- guaranteed that the pointer stored in the DBF field will be
- different after a replace even if the <cNewPointer> points to the
- same disk location as <cOldPointer>. It is, therefore, not
- necessary to compare the data itself (to see if it has been
- changed by one user while another user is working with it), but
- rather, it suffices to compare the pointers themselves.
-
- ■ V_REPLACE( "", vlf ) is not equivalent to V_DELETE( vlf ). In
- the first case, an entry will still exist in the DBV file and
- V_REPLACE() will return a valid pointer. This entry will hold the
- type of the data and the length of the data. In the second case,
- the entry is removed from the file. Because FlexFile de-fragments
- the file as it deletes old data, the second method is preferred
- when you no longer need the data.
-
- Examples
-
- // Example 1: exclusive
- // Assume the DBF file is indexed on the field scr_name
- // Assume the DBF file has a pointer-field scr_vlf.
- LOCAL cScr
-
- // Open a DBF, an NTX and a related DBV file
- USE dbf_file INDEX dbf_file
- V_USE( "dbv_file" )
-
- // Save a screen segment to a variable.
- cScr = SAVESCREEN( 5, 5, 10, 50 )
-
- // Make a name for the screen and append the screen to
- // the dbv_file.dbv.
- APPEND BLANK
- REPLACE scr_name WITH "main_menu"
- REPLACE scr_vlf WITH V_REPLACE( cScr, scr_vlf )
-
- // Later, restore the screen segment.
- CLEAR
- SEEK "main_menu"
- RESTSCREEN( 5, 5, 10, 50, V_RETRIEVE( scr_vlf ) )
-
-
- Network example on next page.
- // Example 2: Network example
- // Assume the file has a pointer-field memo_vlf
- LOCAL ptr, cStr
-
- // Set exclusive off for Clipper and FlexFile.
- SET EXCLUSIVE OFF
- V_EXCLUSIV( .F. )
-
- // Open the files
- USE dbf_file INDEX dbf_file
- IF V_USE( "dbv_file" ) == -1
- ? "File not available at this time."
- QUIT
- ENDIF
-
- // Make up some data; append it to the files.
- APPEND BLANK
- WHILE NETERR()
- APPEND BLANK
- ENDDO
-
- // Lock the record an put some test data in the vlf.
- WHILE !RLOCK()
- ENDDO
- REPLACE dbf_file->memo_vlf WITH V_REPLACE( "Testing",
- dbf_file->memo_vlf )
- UNLOCK
-
- // Remember the pointer for an "updated" test (see below).
- ptr = memo_vlf
-
- // Edit the existing data. Note: the file is not locked.
- cStr = MEMOEDIT( V_RETRIEVE( memo_vlf ), 5, 5, 20, 50 )
-
- // Lock the record before the replace.
- WHILE !RLOCK()
- ENDDO
-
- // Test for an update between when we assigned memo_vlf to
- // ptr and now.
- IF ptr != dbf_file->memo_vlf
- ? "This memo field has been updated by another user."
- ? "It cannot be saved."
- ELSE
- REPLACE memo_vlf WITH V_REPLACE( cStr, memo_vlf )
- ENDIF
-
- UNLOCK
-
- // Close the files.
- USE
- V_USE()
-
-
- See Also: V_USE() V_RETRIEVE() V_POKE() V_AREPLACE()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_AREPLACE() / V_AREP()
- Replace a VLF with a Clipper 5.0 type array
- ───────────────────────────────────────────────────────────────────────────────
-
- Use V_REPLACE() with S'87 arrays
-
- Syntax
-
- V_AREPLACE( <aTarget>,
- <cOldPointer>,
- [<cAlias> | <nArea>] ) -> cNewPointer
-
- Arguments
-
- <aTarget> is any valid Clipper 5.0 array. The array may
- contain nested arrays (i.e. multi-dimensional) which will be saved
- as well.
-
- <cOldPointer> is a required six byte pointer-field or variable in
- which you have previously stored a pointer to variable length
- data. Passing six spaces causes FlexFile to assume that there is
- no old data to be released before the new <aTarget> data is saved.
- Refer to the discussion below for further explanation.
-
- <cAlias> or <nArea> is a DBV file alias or area specified with
- V_USE() or V_SELECT(). If omitted, the replace will occur in the
- current DBV area.
-
- Returns
-
- V_AREPLACE() returns a pointer which should be stored in the
- pointer-field with which the array is to be associated.
-
- V_AREPLACE() returns (.F.) on error. This causes the error system
- to be invoked with a "Data Type Mismatch". Use V_ERROR() to fetch
- the specific error value (see Appendix B for a table of error
- descriptions).
-
- Description
-
- V_AREPLACE() stores the array defined by <aTarget> and returns a
- six byte pointer <cNewPointer>. This pointer is the only way
- FlexFile will ever be able to access the <aTarget> data; if this
- pointer is lost the array in the DBV file will be inaccessible.
-
- It is highly recommended, therefore, that the V_AREPLACE() function
- be imbedded in the same line of code as the Clipper REPLACE
- command (see examples below). <cNewPointer> will then be stored
- directly into a six byte pointer-field in the related DBF file.
-
- V_AREPLACE() first deletes the data associated with <cOldPointer>
- freeing up the space, if any, that it was occupying. V_AREPLACE()
- then looks for the smallest available space to put the
- <aTarget> array. Finally, it returns <cNewPointer> to be
- used at any time by V_ARETRIEV() or V_AREPLACE(). In most cases,
- you will be storing the <cNewPointer> in a DBF file (highly
- recommended).
-
- In designing the associated DBF structure, you will define a
- pseudo memo-field which will be a six byte (or more) character
- type field. FlexFile refers to these fields as pointer-fields.
- When a FlexFile pointer is stored in this field, the field will
- have six bytes of ASCII characters from the "irrational" range
- (128-255). This may appear as "garbage", but is actually a very
- compact encoded structure. It is encoded only to insure that nulls
- are never stored in your DBF file. After creating this field you
- can ignore it exactly as you would a DBT memo-field.
-
- The V_AREPLACE() function replaces data in the current DBV area or
- the <nArea>/<cAlias> area if specified. Attempting to use
- <cOldPointer> which points into one DBV file to delete/replace
- data in any other DBV file can be dangerous. Although there is a
- degree of protection against this kind of programmer error, it is
- possible that random data will be deleted from the target area
- corrupting that file.
-
- ┌────────────────────────── WARNING ──────────────────────────┐
- │ V_AREPLACE() deletes the data associated with <cOldPointer> │
- │ before returning <cNewPointer>. Attempting to use │
- │ <cOldPointer> after this function deletes the data that it │
- │ points to can corrupt the DBV file. │
- └─────────────────────────────────────────────────────────────┘
-
- Examples
-
- LOCAL ray
-
- // Open the DBF file and its associated DBV file
- USE dbf_file // Has a 6 byte pointer-field: vlf.
- V_USE( "dbv_file" ) // Is created if it does not exist.
-
- ray = array( 20 ) // Declare a Clipper 5.0 array
-
- afill( ray, "junk" ) // Fill the array with some junk.
-
- ray[10] = array(25) // Nest an array within the first array
-
- // Put some variable type data in the nested array
- ray[10][1] = 1
- ray[10][2] = .t.
- ray[10][3] = 5.56
- ray[10][4] = date()
- ray[10][8] = "check it out"
-
- // Store the array in DBV file and its pointer in
- // the DBF.
- APPEND BLANK
- REPLACE vlf WITH V_AREPLACE( ray, vlf )
-
-
-
- See Also: V_USE() V_ARETRIEV()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_RETRIEVE() / V_RET()
- Return data that has been stored in a DBV file
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_RETRIEVE( <cPointer>,
- [<nArea> | <cAlias>],
- [<nStart>],
- [<nCount>] ) -> Data
-
- Arguments
-
- <cPointer> is a six byte pointer-field (FlexFile's version of a
- memo-field).
-
- <nArea> or <cAlias> refers to the number or name of the target DBV
- work area. If not specified, the current DBV work area is assumed.
-
- <nStart> is the starting position in <cPointer>'s data. If
- <nStart> is positive, it counts from the beginning of the data
- pointed to by <cPointer>. If <nStart> is negative, it counts from
- the end of the data pointed to by <cPointer>.
-
- <nCount> is how many bytes of data to retrieve. If omitted,
- <nCount> begins at <nStart> and goes to the end of the data. If
- <nCount> is larger than the data, the excess is ignored.
-
- Returns
-
- V_RETRIEVE() will return the data pointed to by <cPointer>. On
- error, V_RETRIEVE() will return an empty value of the type stored
- or a logical (.F.) if no type can be determined. Use V_ERROR() to
- fetch the error code associated with a failed RETRIEVE().
-
- Description
-
- V_RETRIEVE() retrieves data stored in a DBV type file. The data
- retrieved will have the same type as the data that was stored
- during the V_REPLACE() (with the notable exception of Clipper
- arrays which are discussed below and Proclip windows which use the
- V_WNDCREAT() function).
-
- Notes
- ■ Clipper arrays stored using the V_REPLACE() or V_AREPLACE()
- functions cannot be retrieved with V_RETRIEVE(). Instead, use
- V_FILLARR() for Summer 87 type arrays and V_ARETRIEV() for
- Clipper 5.0 arrays.
-
- ■ <nStart> and <nCount> only apply to character data. They will
- be ignored for any other data types.
-
- ■ If a numeric value was stored to a VLF (directly or as part of an
- array), the value returned will be equivalent to the value stored, but
- if you display the value without a PICTURE clause, it will show the
- number of decimals according to the value of SET DECIMAL TO (which is
- not necesarily the same number of decimals that were visable when the
- value that was saved).
-
-
- Examples
-
- // Open the DBF file and its associated DBV file
- #define CR_LF ( CHR(13) + CHR(10) )
- LOCAL cStr
- USE dbf_file // Has a 6 byte pointer-field: vlf.
- V_USE( "dbv_file" )// Is created if it does not exist.
-
- cStr ="And the silken, sad, uncertain,"+ CR_LF +;
- "rustling of each purple curtain,"+ CR_LF +;
- "thrilled me, filled me," + CR_LF +;
- "with fantastic terrors never felt before."
-
- // Store the string in DBV file and its pointer in
- // the DBF.
- APPEND BLANK
- REPLACE author WITH "Poe"
- REPLACE poem WITH "The Raven"
- REPLACE vlf WITH V_REPLACE( cStr, vlf )
-
- // Edit the string using V_RETRIEVE().
- cStr = MEMOEDIT( V_RETRIEVE( vlf ), 0, 0, 10, 45 )
-
- // Save the edited poem.
- REPLACE vlf WITH V_REPLACE( cStr, vlf )
-
-
-
- See Also: V_FILLARR() V_REPLACE() V_STUFF() V_LEN()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_ARETRIEV() / V_ARET()
- Return a Clipper 5.0 type array which was stored in a DBV file
- ───────────────────────────────────────────────────────────────────────────────
-
- See V_FILLARR() and V_FILLEN() for retrieving arrays that were
- stored by an earlier version of the S'87 FlexFile library.
-
- Syntax
-
- V_ARETRIEV( <cPointer>, [<nArea> | <cAlias>] ) -> Array
-
- Arguments
-
- <cPointer> is a six byte pointer-field (FlexFile's version of a
- memo-field).
-
- <nArea> or <cAlias> refers to the number or name of the target DBV
- work area. If not specified, the current DBV work area is assumed.
-
- Returns
-
- V_ARETRIEV() will return the array pointed to by <cPointer>. On
- error, V_ARETRIEV() will return (.F.). Use V_ERROR() to fetch the
- error code associated with a failed V_ARETRIEV().
-
- Description
-
- V_ARETRIEV() retrieves Clipper 5.0 type arrays stored in a DBV
- file. It works on the same principal as the V_RETRIEVE() function.
- The function retrieves the array and all nested arrays as they
- were saved by V_AREPLACE().
-
- Notes
-
- If you have a DBV file which contains an array which was saved by
- FlexFile S'87 version 1.01 or less, you must use the V_FILLARR()
- function to convert the array to one compatible with this function.
-
- All arrays stored with FlexFile's S87 version 1.02 or greater (and,
- of course, any arrays stored with FlexFile's 5.0 versions) are
- compatible with this function.
-
- Examples
-
- LOCAL ray
-
- // Open the DBF file and its associated DBV file.
- // Assume the array stored in the V_AREPLACE() example.
- USE dbf_file // Has a 6 byte pointer-field: vlf.
- V_USE( "dbv_file" ) // Already contains a stored array
-
- // Retrieve the array (and its nested array).
- ray = V_ARETRIEV( vlf )
-
- See Also: V_AREPLACE()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_SELECT()
- Determine or select the DBV work area of a specified DBV alias
- ───────────────────────────────────────────────────────────────────────────────
-
- V_SELECT( [<nNewArea>] | [<cAlias>] ) nOldArea
-
- Arguments
-
- <nNewArea> or <cAlias> is the new DBV area (or the new area associated
- with <cAlias>).
-
- Returns
-
- V_SELECT() returns the old area if the area is successfully
- changed or if no parameters are passed. On error (i.e. an area
- beyond the bounds of the V_FILES() setting), V_SELECT() will
- return a 0 and the DBV area will remain unchanged.
-
- Description
-
- V_SELECT() provides the functionality of a combination of
- Clipper's SELECT command and SELECT() function. Specifically, it
- is used to change and/or fetch the active DBV work area.
-
- If no parameters are passed V_SELECT() parallels the Clipper
- SELECT() by returning the current DBV area. If, however, a valid
- DBV area or alias is passed, V_SELECT() will change the current
- DBV area as Clipper's SELECT command would and then returns the
- old DBV area as Clipper's SELECT() function would. This
- functionality is slightly different than Clipper's SELECT() which
- returns the area of the alias but does not actually change the
- selected area. If you need to test for the existance of an open
- file in a DBV work area, use the V_ISOPEN() function.
-
- V_SELECT() always returns a DBV area number regardless of whether
- the parameter passed was an alias or an area.
-
- Notes
-
- ■ Do not confuse Clipper's selected work area with FlexFile's;
- they are mutually exclusive. For example, you can have a DBF file
- open in area 2 and simultaneously have a DBV file open in
- V_SELECT() == 2. Likewise, SELECT <n> has no effect on the
- currently selected DBV area.
-
- ■ Remember that your maximum number of open files must be set by
- the V_FILES() function before V_USE()in your first DBV file. The
- valid DBV areas will then be from 1 to the value you passed to
- V_FILES(). See V_FILES() for more on defining the maximum number
- of work areas.
-
- Examples
-
- // Open three DBV files in three new areas.
- LOCAL nSelect
-
- nSelect = V_SELECT(1) // Save current area and
- // select area 1
- V_USE( "file1", "file_one" )// Creates if not existing
- V_SELECT(2)
- V_USE( "file2" )
- V_SELECT(0) // Select the next area
- V_USE( "file3" )
-
- ? V_ALIAS() // Returns: FILE3
- ? V_ALIAS(1) // Returns: FILE_ONE
-
- V_SELECT( nSelect ) // Restore the first area.
-
-
- See Also: V_ALIAS() V_USE() V_ISOPEN() V_FILES()
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_SET_COMMIT()
- Set DOS buffer flushing automatically on/off
- ───────────────────────────────────────────────────────────────────────────────
- Syntax
-
- V_SET_COMMIT( [<lToggle>] ) -> lOldSetting
-
- Arguments
-
- <lToggle> is a logical expression which, if true, will turn on
- automatic buffer flushing. If false, it will turn off automatic
- buffer flushing. If omitted, no change will be made and the
- function can be used simply to query the current setting.
-
- Returns
-
- V_SET_COMMIT() returns the old setting of the switch.
-
- Description
-
- DOS "buffers" disk I/O in order to speed up disk access. The
- downside to this feature is that the data in the buffers can be
- lost if the machine "hangs" or is powered down before the buffers
- are copied to disk. This problem was addressed in DOS version 3.3
- and later by allowing a call which forces DOS's buffers to be
- written to disk. V_SET_COMMIT() sets DOS buffer flushing on
- automatic if a logical (.T.) is passed or turns off the automatic
- buffer flushing if a logical (.F.) is passed. In the latter case,
- use V_COMMIT() to flush buffers manually.
-
- ┌──────────────────────── WARNING ─────────────────────────┐
- │ V_COMMIT and V_SET_COMMIT() are based on functions │
- │ provided in DOS 3.3 and later. Calls made to these │
- │ functions on an earlier version of DOS will have no │
- │ affect. │
- └──────────────────────────────────────────────────────────┘
-
-
- Example
-
- // Turn off automatic flushing in order to speed up operation.
- V_USE( "temp" )
- V_SET_COMMIT(.f.)
-
- DO WHILE !EOF()
- IF DELETED()
- REPLACE vlf_fld WITH V_DELETE( vlf_fld )
- ENDIF
- SKIP
- ENDDO
- PACK
-
- // Flush the buffers and turn automatic flushing back on.
- V_COMMIT()
- V_SET_COMMIT(.T.)
-
-
- See also: V_COMMIT()
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_SETKEY()
- Set a key or password for FlexFile encryption
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_SETKEY( <cPassWord> ) -> NIL
-
- Arguments
-
- <cPassWord> is any ten character string. It must be at least one
- character and will be truncated to 10 if more characters are supplied.
-
- Returns
-
- NIL
-
- Description
-
- V_SETKEY() affects the return values of V_ENCRYPT() and V_DECRYPT().
- Essentially, <cPassWord> is a password that is used to encrypt a string
- and must be the same in order to decrypt the string. Once set, the
- <cPassWord> is stored statically in memory.
-
- So, for example, you can set a password when your user starts a system
- (and enters his/her password) and use that password for the remainder
- of the session. All strings V_ENCRYPT()ed with a particular
- <cPassWord> can only be V_DECRYPT()ed by using the same <cPassWord>.
-
- Examples
-
- LOCAL cSecure, cOriginal, cJunk
-
- // Set the key to my dog's name.
- V_SETKEY( "Tally" )
-
- // Encrypt a character string. Store the result in <cSecure>.
- cSecure = V_ENCRYPT( "Just try to decode <cSecure> without my dog." )
-
- // Later, decode the secured string with the help of my golden.
- // Note that the <cPassWord> is being changed.
- V_SETKEY( "Junk" )
-
- // Because the <cPassWord> has been changed, the resulting string
- // will be unreadable.
- cJunk = V_DECRYPT( cSecure )
-
- // Now we change the <cPassWord> back to what was used during
- // the V_ENCRYPT()ion and the string will be properly restored.
- V_SETKEY( "Tally" )
- cOriginal = V_DECRYPT( cSecure )
-
-
- See Also: V_ENCRYPT() V_DECRYPT()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_STUFF()
- Delete and insert new data into an existing VLF
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_STUFF( <cOldPointer>,
- <nStart>,
- <nDelete>,
- <cNewString> ) -> cNewPointer
-
- Arguments
-
- <cOldPointer> Is the pointer (usually stored in a DBF field),
- which points to the source string into which <cNewString> will be
- V_STUFF()ed.
-
- <nStart> is the starting position in the VLF where <cNewString>
- will be inserted.
-
- <nDelete> is the number of characters to delete from <cNewString>
- starting at <nStart>. Deletions are performed before insertions.
-
- <cNewString> is a string which will be inserted at the <nStart>
- position after the deletion of <nDelete> characters.
-
- Returns
-
- V_STUFF() returns a pointer which should be stored in the field
- with which the modified variable length data is to be associated.
-
- V_STUFF() returns (.F.) on error. This causes the error system to
- be invoked with a "Data Type Mismatch". Use V_ERROR() to fetch
- the specific error value (see Appendix B for a table of error
- descriptions).
-
- Description
-
- The V_STUFF() function works on VLFs much as Clipper's STUFF()
- works on strings. Working on VLFs, V_STUFF() will delete <nDelete>
- characters from the string pointed to by <cOldPointer> and then
- insert <cNewString> at the <nStart> position. V_STUFF() can,
- therefore, perform the following seven functions:
-
- ■ Insert: If <nDelete> is zero, V_STUFF() will not delete any
- characters before inserting <cNewString> at the <nStart> position.
- This effectively makes V_STUFF() an insert function.
-
- ■ Replace: If <nDelete> equals LEN( <cNewString> ), then
- V_STUFF() will effectively replace the data beginning at the
- <nStart> position. If the <cNewString> is always the same length
- as <nDelete> or if the comparison for equivalent length is easily
- tested, it is faster (less disk I/O) to use V_POKE().
-
- ■ Delete: If LEN( <cNewString> ) == 0 or <cNewString> is not
- passed, V_STUFF() will effectively delete <nDelete> characters
- beginning at the <nStart> position.
-
- ■ Replace and Insert: If <cNewString> is longer than <nDelete>,
- V_STUFF() will replace <nDelete> characters of the data pointed to
- by <cOldPointer> and insert the remaining length of <cNewString>.
-
- ■ Replace and Delete: If <cNewString> is shorter than <nDelete>,
- V_STUFF() will replace <nDelete> characters of the data pointed to
- by <cOldPointer> and then delete the remaining <nDelete>
- characters making the data shorter.
-
- ■ Replace and Delete rest: If <nDelete> is greater than or equal
- to the number of characters remaining after the <nStart> position
- of the data pointed to by <cOldPointer>, the old data is
- effectively trimmed at the <nStart> position before the
- <cNewString> is inserted.
-
- ■ Append: If <nStart> is equal to or greater than the length of
- the data pointed to by <cOldPointer>, the <nDelete> parameter is
- ignored and the <cNewString> data is appended to the end.
-
- ┌────────────────────────── WARNING ──────────────────────────┐
- │ V_STUFF() deletes the data associated with <cOldPointer> │
- │ before returning <cNewPointer>. Attempting to use │
- │ <cOldPointer> after this function deletes the data that it │
- │ points to can corrupt the DBV file. │
- └─────────────────────────────────────────────────────────────┘
-
- Notes
-
- The big advantage to V_STUFF() is that its operation is disk based
- rather than memory based. This is, however, a double edged sword.
- On the one hand, it offers the ability to create a VLF that is
- larger than 65K (Clipper's largest character string size). On the
- other hand, if you are not aware that <cNewPointer> points to data
- that is larger than 65K, you may be surprised when V_RETRIEVE() or
- similar functions trim their return value to 65K. Although
- V_RETRIEVE() can only return a maximum length of 65K, it can pick
- up any portion of a longer string as long as the portion itself is
- no longer than 65K (see V_REPLACE()).
-
- In all cases, V_STUFF() will move the data pointed to by
- <cOldPointer> to a new location in the DBV file. It is, therefore,
- less disk intensive to use V_POKE() where possible. V_POKE() does
- not delete or insert, but simply overwrites data leaving it at the
- same disk location within the DBV file.
-
- Examples
-
- // Open a DBF file and its associated DBV file.
- USE dbf_file
- V_USE( "dbv_file" )
-
- // Put a string away.
- cStr = "ABCDEF"
- REPLACE vlf WITH V_REPLACE( cStr, vlf )
-
- // Insert.
- REPLACE vlf WITH V_STUFF( vlf, 2, 0, 'xyz' )
- ? V_RETRIEVE( vlf ) // Result: AxyzBCDEF
-
- // Replace.
- REPLACE vlf WITH V_STUFF( vlf, 2, 3, 'qrs' )
- ? V_RETRIEVE( vlf ) // Result: AqrsBCDEF
-
- // Delete.
- REPLACE vlf WITH V_STUFF( vlf, 2, 3, '' )
- ? V_RETRIEVE( vlf ) // Result: ABCDEF
-
- // Replace and Insert.
- REPLACE vlf WITH V_STUFF( vlf, 2, 2, 'xyz' )
- ? V_RETRIEVE( vlf ) // Result: AxyzDEF
-
- // Replace and delete.
- REPLACE vlf WITH V_STUFF( vlf, 2, 4, 'qrs' )
- ? V_RETRIEVE( vlf ) // Result: AqrsEF
-
- // Replace and delete rest.
- REPLACE vlf WITH V_STUFF( vlf, 2, 10, 'xyz' )
- ? V_RETRIEVE( vlf ) // Result: Axyz
-
- // Append.
- REPLACE vlf WITH V_STUFF( vlf, 10, 0, 'qrs' )
- ? V_RETRIEVE( vlf ) // Result: Axyzqrs
-
- See Also: V_POKE() V_REPLACE() V_LEN() V_MEMOLINE()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_TIMEOUT()
- Advanced feature allows setting the internal lock timeout value
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_TIMEOUT( [<nTimeOut>] ) -> nOldSetting
-
- Arguments
-
- <nTimeOut> is the time interval (in seconds) before FlexFile will
- abort a function that is attempting an internal lock. The default
- value is forever.
-
- Returns
-
- V_TIMEOUT() returns the current timeout value.
-
- Description
-
- V_TIMEOUT() should not usually be necessary. If you are using
- Clipper's RLOCK() and FLOCK() functions to manage the DBF file,
- and you are keeping FlexFile's pointers in the DBF (this is the
- preferred method), then this function is not necessary.
-
- If you want FlexFile to timeout during an operation, then use this
- function to set the timeout value in seconds. Passing zero as
- <nTimeOut> will set the timeout value back to its default
- (forever).
-
- If you set the timeout to something other than zero, you must test
- the error code following a call to any of the FlexFile functions
- in the table below. The test is made by comparing V_ERROR() to
- zero or 5200. If the operation's lock timed out, V_ERROR() will
- return 5200, if the operation was successful, V_ERROR() will
- return zero. (See the example below.)
-
- Functions affected by V_TIMEOUT(): V_DELETE(), V_FILE2DBV(),
- V_REPLACE(), V_STUFF(), V_DBV2FILE()
-
- Examples
-
- // Setup defines and variables
- #define EXCLUSIVE_ (.T.)
- LOCAL error_no
-
- // Set the timeout to 3 seconds.
- V_TIMEOUT(3)
-
- // Open a DBF file and its related DBV file.
- USE dbf_file
- IF V_USE( "dbv_file", , , !EXCLUSIVE_ ) == -1
- error_no = V_ERROR()
- IF error_no == 5200
- ? "Attempt to lock header failed after 3 seconds"
- RETURN .F.
- ELSE
- ? "Error: " + str( error_no, 4 )
- RETURN .F.
- ENDIF
- ENDIF
-
-
-
- See Also: V_USE() V_REPLACE()
-
- ───────────────────────────────────────────────────────────────────────────────
- V_TOPPTR()
- Read/Replace FlexFile data without a DBF file.
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_TOPPTR( [<cPointer>], [<cAlias> | <nArea>] )
-
- Arguments
-
- <cPointer> (optional) is the six byte character string returned by
- either V_REPLACE() or V_AREPLACE(). If not specified, V_TOPPTR() will
- return the current pointer stored in the header of the DBV file (see
- discussion below).
-
- <cAlias> or <nArea> is a DBV file alias or area specified with
- V_USE() or V_SELECT(). If omitted, the Top-Pointer will be accessed in
- the current DBV area.
-
- Description
-
- V_TOPPTR() is a special function which allows the storage of one (and
- only one) Variable Length Field without having a separate DBF file in
- which to keep the pointer to that field.
-
- Usually, you replace a six byte character field (FlexFile's version of
- a memo-field) in a DBF file with a pointer to data which is stored in a
- DBV file. V_TOPPTR() allows you to store one pointer in the header of
- the DBV file. This pointer can then be accessed by calling V_TOPPTR()
- with no parameters. For example,
-
- V_ARETRIEVE( V_TOPPTR() )
-
- would retrieve an array which was previously stored with V_AREPLACE()
- and whose pointer was stored by V_TOPPTR().
-
- A good example of the use of this function is in storing parameters
- that your application requires at startup: Things like colors, default
- paths, printer definitions, etc.
-
- Many routines have been written to handle this kind of data. MEM files
- are used by some, while others use a large DBF field and parse out the
- various data into variables. The fact is that MEM files are not
- "network ready" and the DBF file is not efficient to handle data that
- is not repetitive in size and type. So an easy solution is to keep an
- array of these items in a DBV file and point to that array with
- V_TOPPTR().
-
- Using V_TOPPTR() requires a slightly different syntax than a standard
- replace. Typically, a DBV replace is made by calling V_AREPLACE() and
- putting the return pointer in a DBF field as follows:
-
- REPLACE vlf WITH V_AREPLACE( aStartUp, vlf )
-
- where aStartUp is an array holding your applications startup data. In
- contrast, the following syntax is required when storing the
- pointer-field directly in the DBV:
-
- V_TOPPTR( V_AREPLACE( aStartUp, V_TOPPTR() ) )
-
- The logic here can best be seen by breaking this last line into several
- lines of code:
-
- // First, get the old pointer stored in the DBV file.
- cOldPointer = V_TOPPTR()
-
- // Then replace the old array with a new one. Put
- // the pointer to the new array into the variable
- // cNewPointer.
- cNewPointer = V_AREPLACE( aStartUp, cOldPointer )
-
- // Finally, store the actual pointer in the DBV.
- // This will overwrite the old pointer stored there.
- V_TOPPTR( cNewPointer )
-
- Examples
-
- LOCAL ray
-
- // Open only a DBV file
- V_USE( "dbv_file" ) // Is created if it does not exist.
-
- // Declare an array and put some junk into it.
- ray = { { "one", "two", "three" } ,;
- { 1, 2, 3 ) ,;
- { p1, p2, p3 } }
-
- // Store the array in DBV file and its pointer in
- // the header of the same DBV.
- V_TOPPTR( V_AREPLACE( ray, V_TOPPTR() ) )
-
-
- See Also: V_REPLACE() V_AREPLACE() V_RETRIEVE() V_ARETRIEVE()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_TYPE()
- Return the type of data stored in a VLF
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_TYPE( <cPointer>,
- <nArea> | <cAlias> ) -> cType
-
- Arguments
-
- <cPointer> is a six byte pointer-field (FlexFile's version of a
- memo-field).
-
- <nArea> or <cAlias> refers to the number or name of the target DBV
- work area. If not specified, the current DBV work area is assumed.
-
- Returns
-
- V_TYPE() returns the type of the data that is pointed to by
- <cPointer>. The possible types and their one character pneumonic
- are detailed in the table under the V_REPLACE() function.
-
- Description
-
- V_TYPE() is similar to Clipper's TYPE() function. There are,
- however, more "types" of data that can be stored to a VLF than in
- a Clipper memory variable. For example, Clipper see's a Proclip
- window handle as a numeric. Clipper's TYPE("pw_handle") function
- would return a 'N'. However, if you save the Proclip window to a
- VLF (See V_REPLACE()), the V_TYPE() function will return a 'P'.
-
-
- Examples
-
- // Setup seven variables of differing types.
- LOCAL num_var ,;
- chr_var ,;
- date_var ,;
- log_var ,;
- arr_var ,;
- ffa_var ,;
- pcw_var
-
- num_var = 5
- chr_var = "This is a test"
- date_var= DATE()
- log_var = (.T.)
- arr_var = { "Cindy", "Gail", "Edith" }
- ffa_var = A_DECLARE( 'S', 5, 5 )// FlexFile double type
- pcw_var = WNDCREATE( 5, 10 ) // Proclip window.
-
- // Open a DBF file and its associated DBV file
- USE dbf_file
- V_USE( "dbv_file" )
-
- // Replace the VLF with five different data types.
- APPEND BLANK
- REPLACE vlf WITH V_REPLACE( num_var, vlf )
- ? V_TYPE( vlf ) // Result: 'N'
-
- REPLACE vlf WITH V_REPLACE( chr_var, vlf )
- ? V_TYPE( vlf ) // Result: 'C'
-
- REPLACE vlf WITH V_REPLACE( date_var, vlf )
- ? V_TYPE( vlf ) // Result: 'D'
-
- REPLACE vlf WITH V_REPLACE( log_var, vlf )
- ? V_TYPE( vlf ) // Result: 'L'
-
- // Note: The replace here is V_AREPLACE() for Clipper 5.0
- REPLACE vlf WITH V_AREPLACE( arr_var, vlf )
- ? V_TYPE( vlf ) // Result: 'A'
-
- // Note: You must declare the type for a V_REPLACE()
- // of a flexfile strongly typed array.
- REPLACE vlf WITH V_REPLACE( ffa_var, vlf, , 'F' )
- ? V_TYPE( vlf ) // Result: 'F'
-
- // Note: You must declare the type for a V_REPLACE()
- // of a Proclip window handle.
- REPLACE vlf WITH V_REPLACE( pcw_var, vlf, , 'P' )
- ? V_TYPE( vlf ) // Result: 'P'
-
-
-
- See Also: V_REPLACE() V_RETRIEVE() V_LEN()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_USE()
- Open/Create a Variable Length Field file (DBV)
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_USE( [<cFileName>],
- [<cAlias>],
- [<cNewArea>],
- [<lExclusive>] ) -> nArea
-
- Arguments
-
- <cFileName> is the name of the file to be opened/created. A .DBV
- extension is assumed if none is provided. If the file does not
- exist, one will be created. If <cFileName> is omitted, any file
- open in the current DBV area will be closed.
-
- <cAlias> is a name to be associated with the DBV work area of the
- file being opened. If this parameter is not passed or a "dummy"
- argument is passed, the alias defaults to the DBV file name.
-
- <cNewArea> is the word "NEW". This has the same affect as issuing
- a SELECT 0 in Clipper or V_SELECT(0) in FlexFile just before
- opening the file. In Clipper version 5.0, <cNewArea> has the same
- effect as the NEW modifier of the USE command. If this parameter
- is not specified, any DBV file open in the current DBV work area
- will be closed and the <cFileName> file will be opened in its
- place.
-
- <lExclusive> is a logical expression determining the accessibility
- of the file by other users in a network environment. If
- <lExclusive> is (.T.) and the file is successfully opened, any
- attempt by another user to V_USE() the <cFileName> file will be
- denied until the file is V_CLOSED(). If this parameter is omitted,
- FlexFile will attempt to open the <cFileName> file according to
- the current setting of V_EXCLUSIV().
-
- Returns
-
- If successful, V_USE() returns the DBV area in which the file was
- opened. Otherwise, it will return a -1 and set an error code which
- may be fetched with V_ERROR(). (See appendix B for a list of error
- codes.)
-
- Description
-
- V_USE() opens (or creates if the file does not exist) a file that
- can store variable length data. Any file which is already open in
- the DBV area is closed before the <cFileName> file is opened.
-
- Although it is far more flexible, using a DBV file is very similar
- to using memo-fields and a DBT file. It is not required but highly
- recommended that you have a DBF file open simultaneously with the
- DBV file. You will then store pointers in fields of the DBF file
- that point to variable length data in the DBV file. The fields in
- the DBF file cannot be defined as a <memo> fields but have the
- same basic functionality.
-
- Unlike the DBT file, FlexFile supports one to one, one to many,
- and many to many relationships between the DBF field pointers and
- the DBV files. For example, a system could use one DBV file to
- store all its help text, random memo's, screens and arrays. The
- pointers to all this data could be stored in several different DBF
- files. Likewise, one DBF file may point into several DBV files. It
- is left up to the programmer to keep straight which DBF fields
- relate to which DBV files. (Note: it is a critical error to use a
- pointer which points into one DBV file as a pointer into a
- different DBV file.)
-
- If a DBV file is opened exclusively in a network environment, no
- other users may access the file until it is V_CLOSED(). Likewise,
- if the file is currently being used exclusively by another user,
- attempts to V_USE() that file will fail. V_USE() returns -1 if
- the file is not opened and reports the error which can be fetched
- with V_ERROR(). (See appendix B for a list of error codes.)
-
- If the file is opened non-exclusively, other users may access the
- variable length data simultaneously. However, because all data in
- a DBV file must be accessed by a pointer which will usually be
- stored in a DBF file, using standard Clipper locking procedures to
- protect the DBF record will protect the variable length data
- exactly as it does any field in the DBF. (See the V_REPLACE()
- function for more on locking.)
-
- Notes
-
- ■ V_USE() obeys neither the SET DEFAULT nor the SET PATH
- settings. Instead, it will use the current DOS default directory
- or any valid path specified as a part of <cFileName>.
-
- ■ Remember that your maximum number of open files must be set by
- the V_FILES() function before V_USE()ing your first DBV file. The
- valid DBV areas will then be from 1 to the value you passed to
- V_FILES(). See V_FILES() for more on defining the active number of
- files.
-
- ■ Opening the same DBV file in two work areas simultaneously is
- possible, however, don't do it.
-
- ■ Do not confuse Clipper's selected work area with FlexFile's;
- they are mutually exclusive. For example, you can have a DBF file
- open in area 2 and simultaneously have a DBV file open in
- V_SELECT() == 2. Likewise, Clipper's SELECT <n> has no effect on
- the currently selected DBV area.
-
- Examples
-
- // Assume that no files are open at this point.
- // Set the maximum number of files to three.
- #define EXCLUSIVE_ (.T.)
- V_FILES( 3 )
-
- // Open a DBV file with an alias of "MAIN_FILE" in area 1.
- // If dbv_file.dbv does not exist it will be created.
- V_SELECT(1)
- V_USE( "dbv_file", "MAIN_FILE" )
- ? V_ALIAS() // Result: MAIN_FILE
-
- // Open another file in the next available area.
- V_USE( "second", , "NEW" )
- ? V_SELECT() // Result: 2
-
- // Open a third file for use on a network and test to
- // make certain that the file was properly opened.
- IF V_USE( "F:\GEN\JUNK\third", , "new", !EXCLUSIVE_ ) == -1
- ? "Error: " + str( V_ERROR(), 4 )
- QUIT
- ENDIF
-
- // Close all files.
- V_CLOSE( 1 ) // Closes file in area 1
- V_CLOSEALL() // Closes the other two files.
-
-
- See Also: V_CLOSE() V_SELECT()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_VLF2FILE()
- Create a DOS file and fill it with the contents of a VLF
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_VLF2FILE( <cFileName>,
- <cPointer>,
- <cMode> ) -> lSuccess
-
- Arguments
-
- <cFileName> is the name of a file to append to or overwrite with
- the data from a VLF associated with <cPointer>.
-
- <cPointer> is a six byte pointer-field (FlexFile's version of a
- memo-field).
-
- <cMode> is a character code telling FlexFile to <A>ppend or
- <O>verwrite any existing file with the same name as <cFileName>.
- The default mode is <A>ppend.
-
- Returns
-
- V_VLF2FILE() returns (.T.) if the data was copied successfully,
- otherwise, it returns (.F.).
-
- Description
-
- V_VLF2FILE() copies a Variable Length Field from a DBV type file
- to a DOS file. This is particularly useful when using graphics
- applications from within Clipper that require individual files for
- images.
-
-
- Examples
-
- // Setup variable
- LOCAL pic_name
-
- // Open a DBF, NTX and DBV library of graphics images.
- USE ( pic_lib ) INDEX ( pic_lib )
- V_USE( pic_lib )
-
- // Allow the user to enter the name of a graphic image
- // to view, create a temporary disk file, print the
- // file to screen.
-
- WHILE ( .T. )
- pic_name = SPACE(11)
- @ 5, 5 SAY "Enter the image name to view: " GET pic_name
- SEEK pic_name
- IF FOUND()
-
- // Write DBV data to a temporary file.
- V_VLF2FILE( "graphic.pic", vlf_ptr )
-
- // Use one of the graphic function libraries to retrieve a file.
- file2graph( 0, "graphic.pic" )
-
- INKEY(0)
-
- ELSEIF LASTKEY() == 27
- EXIT
-
- ELSE
- ? "Image not found"
-
- ENDIF
- ENDDO
-
-
- See Also: V_FILE2VLF() V_REPLACE() V_DELETE()
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_WALK_DBV()
- Step from field to field in a DBV without a DBF.
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_WALK_DBV( [<cTopOfFile>], [<cAlias> | <nArea>] ) -> cPointer
-
- Arguments
-
- <cTopOfFile> should be the word "First" (only the "F" is significant)
- to return the pointer to the first field in a DBV. Any other value
- (including NIL) will tell V_WALK_DBV() to skip to the next field.
-
- <cAlias> or <nArea> is a DBV file alias or area specified with
- V_USE() or V_SELECT(). If omitted, the operation will occur in the
- current DBV area.
-
- Returns
-
- This function returns a pointer to the current VLF. (See discussion
- below). The return value is a NULL string ("") when the end of file is
- reached or when an error is encountered in the DBV.
-
- Description
-
- V_WALK_DBF() is a disaster recovery function and should rarely if every
- be needed. However, if you loose a DBF file and still want to recover
- the contents of the DBV, this function can be indispensible.
-
- When called for the first time or when <cTopOfFile> is given the
- value "first", V_WALK_DBV() will return a pointer to the first Variable
- Length Field in the DBV (this is the first physical field). Any
- subsequent call to this function (where <cTopOfFile> is not
- "first"), V_WALK_DBV() will return a pointer to the next physical field
- in the DBV.
-
- Thus, when put in a loop, you can walk through every field in a DBV and
- retrieve a valid FlexFile pointer for use with V_RETRIEVE(),
- V_REPLACE(), etc.
-
- Examples
-
- LOCAL vlf_ptr, str := ""
-
- // Open the DBV without opening a DBF.
- V_USE( "lost_dbf.dbv" )
-
- // Put the pointer to the first field in the variable <vlf_ptr>.
- // The "First" is not necessary here because the first call to this
- // function starts on the first field anyway, but is included
- // for clarity.
- vlf_ptr = V_WALK_DBV( "First" )
-
- DO WHILE !EMPTY( vlf_ptr )
-
- str = V_RETRIEVE( vlf_ptr )
- MEMOEDIT( str, 5, 5, 20, 75 )
-
- // Get a pointer to the next field (fields are in physical order)
- vlf_ptr = V_WALK_DBV()
-
- ENDDO
-
-
-
- See Also: V_RETRIEVE()
-
-
- ───────────────────────────────────────────────────────────────────────────────
- V_WNDCREAT()
- Create a Proclip(tm) window from one which was saved to a DBV file.
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- V_WNDCREAT( <cPointer>, [<cAlias> | <nArea>] ) -> nPCWhandle
-
- Arguments
-
- <cPointer> is a six byte pointer-field (FlexFile's version of a
- memo-field).
-
- <cAlias> or <nArea> is a DBV file alias or area specified with
- V_USE() or V_SELECT(). If omitted, the operation will occur in the
- current DBV area.
-
- Returns
-
- If V_WNDCREAT() is successful, it will return a valid Proclip
- window "handle". Otherwise, it will return 0.
-
- Description
-
- V_WNDCREAT() will re-create a Proclip window that was previously
- stored in a DBV file with the V_REPLACE() function. The window
- will have all the attributes of the original window with the single
- exception that it will not be opened even if it was open when it
- was saved.
-
- In order to open or modify the window, you will need the Proclip
- library from Genesis Development Corporation. It is one of the
- finest windowing libraries available.
-
-
- Examples
-
- // Create a Proclip window using the Proclip library.
- handle = WNDCREATE( 10, 20 )
-
- // Put some junk on the window.
- FOR x = 1 TO 10
- WNDPRINT( handle, x - 1, 0, "this is a test" )
- NEXT x
-
- // Show the user the window.
- WNDOPEN( handle )
-
- // Save the window to the DBV file open in the current area.
- // Note the necessity to "type" the replace (i.e. the 4th parameter).
- REPLACE vlf WITH V_REPLACE( handle, vlf, .t., 'P' )
-
- // Close and then destroy the window.
- WNDCLOSE( vlf )
- WNDDESTROY( vlf )
-
- // Now re-create the same window.
- handle = V_WNDCREAT( vlf )
-
- // Re-display the window
- WNDSHOW( handle )
-
-
-
- See Also: V_FILE2VLF() V_REPLACE() V_DELETE()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_()
- Return a pointer reference to a multi-dimensional array element
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_( <nElements>,
- [, <nElements>...] ) -> nPointer
-
- Arguments
-
- <nElements> represents the magnitude of each successive dimension
- in a FlexFile array.
-
- Returns
-
- A_() returns a character string which FlexFile interprets as a
- pointer to the specific element.
-
- Description
-
- Use A_() to simplify passing/receiving multi-dimensional array
- index references. The need for the function arises because array
- indexes have as many components as the array has dimensions and
- the passing of the index to a function can get confusing (both for
- the programmer and FlexFile's error checking).
-
- With Clipper arrays the compiler handles references to a
- particular element with the familiar syntax [ 1 ][ 1 ][ 1 ] for
- the first element of a three dimensional array. Avoiding conflict
- with this syntax, FlexFile refers to the same element of a
- FlexFile three dimensional array as A_( 1, 1, 1 ).
-
- Although FlexFile functions will accept a numeric integer as an
- array index designator (it is the preferred method on a FlexFile
- single dimensional array), you should not use integers as indexes
- to multi- dimensional arrays. This is because A_( 3, 5 ) does not
- refer to the same element as A_(5, 3), and rarely if ever does
- (3 * 5) point to element A_(3, 5).
-
- See the examples for a complete understanding of the use of this
- function.
-
-
- Examples
-
- // Accessing elements of a FlexFile Multi-dimensional array
- // First declare a two dimensional 5 x 10 array.
- rows = 5
- cols = 10
- aName = A_DECLARE( 'F', rows, cols )
-
- // Fill the array starting at the first element a_( 1, 1 ).
- A_FILL( aName, 98.6, A_( 1, 1 ), rows * cols )
-
- // Retrieve a value from a specified element.
- temp = A_RETRIEVE( aName, A_( 3, 2 ) )
-
-
- See Also: A_RETRIEVE() A_STORE()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_ADD()
- Add a new element to the end of an array
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_ADD( @<aTarget>,
- [<nDimension>] ) -> lSuccess
-
- Arguments
-
- <aTarget> is the array to which you are adding new element(s).
- It MUST be passed-by-reference. A_ADD() cannot add elements to
- a binary (logical) type array.
-
- <nDimension> is the dimension that will be increased by one.
- The default is the last dimension in the list of dimensions.
-
- Returns
-
- A_ADD() returns a (.T.) if successful, otherwise, it returns a
- (.F.).
-
- Description
-
- A_ADD() works differently than Clipper's AADD() function. This is
- because FlexFile arrays are matrices and cannot have "ragged"
- lengths in any dimension.
-
- So, A_ADD() adds one element in a one dimensional array, one row
- in a two dimensional array, one page in a three dimensional array,
- and so forth.
-
- For example, imagine a two dimensional array containing students
- grades. Along one axis are the students; along the other are the
- exams. When the semester begins the professor may not know how
- many exams there are going to be (or how to handle a new student).
- If you look at both of these situations you will understand
- FlexFile's A_ADD().
-
- Lets assume that the professor begins with 20 students and plans
- the course to consist of 5 exams:
-
- students = 20
- exams = 5
- array = A_DECLARE( 'I', students, exams )
-
-
- Later in the course he needs to add a new student.
-
- A_ADD( @array, 1 )
-
- The second parameter is one to tell A_ADD that we are adding a
- row of exams for a new student. The value is one because when
- we declared the array the students were the first array
- index.
-
- Later the professor needs to add another exam for all students:
-
- A_ADD( @array, 2 )
-
-
- Examples
-
- // Declare a two dimensional unsigned (T)iny integer array
- LOCAL rows, cols
-
- rows = 10
- cols = 20
- aTiny = A_DECLARE( "UT", rows, cols )
-
- // Increase the columns to 21.
- A_ADD( @aTiny, 2 )
-
-
-
- See Also: A_SIZE() A_DECLARE()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_AVERAGE()
- Return the average of the contents of a numerical array
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_AVERAGE( <aTarget>,
- [<idxPos>],
- [<nCount>] ) -> nAverage
-
- Arguments
-
- <aTarget> is the FlexFile array on which to perform the average.
-
- <idxPos> The index (or subscript) is the position in the target
- array at which to begin the average. The default is the first
- element.
-
- <nCount> is the number of elements to include in the average. The
- default is all element starting at <idxPos> to the end of the
- array.
-
- Returns
-
- A_AVERAGE() returns the numerical average or mean of the <aTarget>
- array. On error, A_AVERAGE() returns 0.
-
- Description
-
- A_AVERAGE() will average all or a part of a FlexFile numeric
- array. The numeric types are (D)ouble, (F)loat, (L)ong or (UL),
- (I)nteger or (UI), and (T)iny or (UT).
-
- The averaging begins at the position pointed to by <idxPos> and
- continues for <nCount> elements. The function will wrap around
- dimensions if count extends beyond the end of the current row.
-
-
- Examples
-
- // Declare a two dimensional (L)ong integer array
- LOCAL rows, cols
-
- rows = 10
- cols = 20
- aLong = A_DECLARE( "L", rows, cols )
-
- // Fill the 5th row with 100,000 and the 6th row
- // with 200,000.
- A_FILL( aLong, 100000, A_( 5, 1 ), cols )
- A_FILL( aLong, 200000, A_( 6, 1 ), cols )
-
- // Take the average of rows 5 and six.
- ? A_AVERAGE( aLong, A_( 5, 1 ), cols * 2 ) // Result: 150000
-
-
-
- See Also: A_STORE() A_RETRIEVE()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_COPY()
- Copy all or a portion of one array into another existing array
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_COPY( <aSource>,
- <aTarget>,
- [<idxPos>],
- [<nCount>],
- [<nTargetPos>] )
-
- Arguments
-
- <aSource> is the array that will be copied from.
-
- <aTarget> is the array that will be copied to.
-
- <idxPos> is the element in <aSource> where the copy will begin. The
- default is the first element in the array.
-
- <nCount> is the number of elements to copy. The default is all
- elements starting at <idxPos> until the end of the row in the
- current dimension.
-
- <nTargetPos> is the starting element position in the target array.
-
- Returns
-
- None.
-
- Description
-
- A_COPY() copies the contents of one array into another. This is
- different than Clipper's ACOPY() which copies references to nested
- array elements. Because there are no nested array elements in a
- FlexFile array, the copy includes the smaller of the range
- specified and the size of the arrays.
-
- Examples
-
- // Declare a two dimensional (UL)ong integer array
- LOCAL rows, cols
-
- rows = 10
- cols = 20
- aSource = A_DECLARE( "UL", rows, cols )
- aTarget = A_DECLARE( "UL", rows, cols )
-
- // Fill the 5th row with 100,000 and the 6th row
- // with 200,000.
- A_FILL( aSource, 100000, A_(5, 1), cols )
- A_FILL( aTarget, 200000, A_(6, 1), cols )
-
- // Copy the 5th and 6th rows to the 2nd/3rd row of the target
- A_COPY( aSource, aTarget, A_(5, 2), cols * 2, A_(2, 1) )
-
-
- See Also: A_SIZE() A_INS()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_DECLARE()
- Declare a FlexFile array
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_DECLARE( <cType>,
- <nElement>,
- [<nElements>...] ) -> aArray
-
- Arguments
-
- <cType> is a code for the type of the FlexFile strongly typed
- array. (See the table below for a list of types and their codes.)
-
- <nElements> is the number of elements in each consecutive
- dimension. An array can be declared with up to six dimensions.
-
- Returns
-
- A_DECLARE() returns a fully dimensioned FlexFile array of <cType>.
-
- Description
-
- A_DECLARE() creates a FlexFile type array. The various data types
- that FlexFile implements are listed below.
-
- When Clipper returns a value from a function, it makes a copy of
- the value for the calling function before releasing the value
- created by the called function. So, if you declare a FlexFile
- character array of 60,000 elements, A_DECLARE() will allocate
- memory for an array of 60,000 character elements (a little over
- 60,000 bytes) and then Clipper will copy that variable requiring
- two 60,000 byte blocks to execute the function.
-
- Although this is not a problem with smaller arrays, it becomes
- significant with larger ones. FlexFile addresses this problem by
- offering an optional syntax for this function. Just add a new
- parameter and insert it after the type. This parameter must be a
- previously declared character string of any length and it must be
- passed-by-reference. The optional syntax is as follows:
-
- A_DECLARE( <cType>,
- @<aLargeArr>,
- <nElement>,
- [<nElements>...] )
-
-
- The return value when this syntax is used is undefined. Instead,
- FlexFile will modify the <aLargeArr> variable. Because there is
- no return value, Clipper will not duplicate the <aLargeArr>
- variable.
-
- Table: Data types
- ┌──────────────────────────────────────────────────────────────────────┐
- │ Array Type Type Elem/Arr Byte/Elem Data Range │
- ├──────────────────────────────────────────────────────────────────────┤
- │ Binary (logical) B 520K 1 bit .T. or .F. │
- │ Character C 65K 1 byte Extended ASCII set │
- │ Tiny Integer T 65K 1 byte -128 to 127 │
- │ Unsigned Tiny UT 65K 1 byte 0 to 255 │
- │ Integer I 32K 2 bytes -32,768 to 32,767 │
- │ Unsigned Integer UI 32K 2 bytes 0 to 65,535 │
- │ Long Integer L 16K 4 bytes -2147483648 to 2147483647 │
- │ Unsigned Long UL 16K 4 bytes 0 to 4,294,967,295 │
- │ Floating Point F 16K 4 bytes 7 digit precision │
- │ String S 16K 4 bytes n/a │
- │ Double D 8K 8 bytes 15 digit precision │
- └──────────────────────────────────────────────────────────────────────┘
-
- Examples
-
- // Declare a two dimensional (B)inary array
- LOCAL rows, cols
-
- rows = 10000
- cols = 20
- aBinary = A_DECLARE( "B", rows, cols )
-
- // Optional syntax. Note: A_DECLARE() has no return value.
- LOCAL aLargeArr := ''
-
- A_DECLARE( "UL", aLargeArr, 10000, 2 )
-
-
- See Also: A_FILL() A_TYPE()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_DEL()
- Delete one element from an array
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_DEL( <aTarget>, [<idxPos>], [<nCount>] )
-
- Arguments
-
- <aTarget> is the array from which an element will be deleted.
-
- <idxPos> is the position in the target array of the element to be
- deleted.
-
- <nCount> is the number of elements to shift. The default is all
- elements starting at <idxPos> until the end of the row in the
- current dimension.
-
- Returns
-
- None.
-
- Description
-
- A_DEL() is similar to Clipper's ADEL() function. The array element
- pointed to by <idxPos> is removed and <nCount> elements are
- shifted up one position. A blank element is inserted at the
- position created by the shift and filled with the default value
- based on the type of the array (see A_DECLARE()).
-
- FlexFile's multi-dimensional arrays are not nested single
- dimensional arrays. Therefore, A_DEL()eting an element has no
- other affect than shifting <nCount> elements up one position.
-
- Wrapping will occur if <nCount> goes beyond the current row
- pointed to by <idxPos>. For example, if you have a two dimensional
- array with accounts in the first dimension and 12 prior period
- amounts in the second dimension, and you wanted to operate on the
- first quarter (i.e. 3 periods), making <nCount> three times the
- number of accounts will "wrap" around three periods. See the
- discussion on arrays in chapter 2 for more information on this
- feature.
-
-
- Examples
-
- // Declare a two dimensional (C)haracter array
- LOCAL rows, cols, x, y, z
-
- rows = 10
- cols = 20
- z = 1
- aChar = A_DECLARE( "C", rows, cols )
-
- // Fill the array with increasing character values.
- FOR x = 1 to rows
- FOR y = 1 to cols
- z++
- A_STORE( aChar, chr(z), A_( x, y ) )
- NEXT
- NEXT
-
- // Delete the ASCII character "" from the first element
- // and shift all elements from the second element to the
- // end of the array up one position. Wrapping will occur.
- A_DEL( aChar, A_(1, 1), 1 )
-
-
-
- See Also: A_DECLARE() A_INS() A_SCROLL()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_DIMS()
- Return the number of dimensions in an array
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_DIMS( <aTarget> ) -> nDimensions
-
- Arguments
-
- <aTarget> is the array whose dimensions are being queried.
-
- Returns
-
- A_DIMS() returns the number of dimensions of <aTarget>.
-
- Description
-
- A_DIMS() is used to query an array returning the number of
- dimensions that were used when the array was A_DECLARE()d.
-
-
- Examples
-
- // Declare a four dimensional (S)tring array
- LOCAL books, pages, rows, cols
-
- books = 2
- pages = 10
- rows = 15
- cols = 50
- aString = A_DECLARE( "S", books, pages, rows, cols )
-
- ? A_DIMS( aString ) // Result: 4
-
-
-
-
- See Also: A_DECLARE() A_LEN()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_DIVIDE()
- Divide all elements of an array by a value or an array of values
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_DIVIDE( <aTarget>,
- <nDenominator> | <aDenominators>,
- [<aSource>] )
-
- Arguments
-
- <aTarget> is the array to be modified. If <aSource> is not
- specified then each element of <aTarget> is the numerator of the
- division.
-
- <nDenominator> or <aDenominators> is either a value or an array of
- values used as the denominator in the division.
-
- <aSource> is an optional array of numerators. If not specified,
- then each element of <aTarget> will be used as the numerator of
- the division.
-
- Returns
-
- Although there is no return value, the <aTarget> array is
- modified.
-
- Description
-
- A_DIVIDE() provides a means to perform a division of every element
- in the <aSource> array if specified or the <aTarget> array if not.
- Each element of the <aSource> or <aTarget> array is divided by the
- <nDenominator> or element for element by <aDenominator>. The
- result of the division replaces the value in the <aTarget> array.
-
- A_DIVIDE() can be performed on any integer or floating point type
- array. These include the (T)iny, (I)integer, (L)ong, (F)loat and
- (D)ouble (both signed and unsigned integers, of course). Mixing
- of the various numeric types is permitted, however, the source
- values are promoted or demoted to the targets type before the
- operation is executed.
-
- Division by zero is trapped and the element in error is replaced
- with zero.
-
- Notes
-
- ■ Division by zero is trapped and the element in error is
- replaced with zero.
-
- Examples
- // Declare three double type arrays for this function.
- LOCAL rows, cols
-
- rows = 10
- cols = 20
- aSource = A_DECLARE( "D", rows, cols )
- aTarget = A_DECLARE( "D", rows, cols )
- aDenominator = A_DECLARE( "D", rows, cols )
-
- // Fill the target array with 10's
- A_FILL( aTarget, 10, A_(1, 1), rows * cols )
-
- // Divide every element in the target array by 2
- A_DIVIDE( aTarget, 2 )
- ? A_RETRIEVE( aTarget, A_( 4, 5 ) ) // Result: 5.0
-
- // Fill the source array with 10's
- A_FILL( aSource, 10, A_(1, 1), rows * cols )
-
- // Divide every element in the source array by five and
- // put the result in the target array.
- A_DIVIDE( aTarget, 5, aSource )
- ? A_RETRIEVE( aTarget, A_( 4, 5 ) ) // Result: 2.0
-
- // Fill the denominator array with 4's
- // Remember the source array still has all 10's
- A_FILL( aDenominator, 4, A_(1, 1), rows * cols )
-
- // Divide every element in the source array by every element
- // in the denominator array and put the result in the target
- // array.
- A_DIVIDE( aTarget, aDenominator, aSource )
- ? A_RETRIEVE( aTarget, A_( 4, 5 ) ) // Result: 2.5
-
-
- See Also: A_MULTIPLY() A_PLUS() A_MINUS()
-
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_ERROR()
- Report specific error codes from FlexFile's error system
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_ERROR() -> nErrorValue
-
- Arguments
-
- None.
-
- Returns
-
- A_ERROR() returns a FlexFile error code as a numeric integer.
-
- Description
-
- A_ERROR() is an error function that will return the most recent
- error code that FlexFile set. If the failed operation has no
- FlexFile error code check the DOS error code using Clipper's
- DOSERROR().
-
- For a complete list of error codes and their descriptions
- refer to Appendix B.
-
- Examples
-
- // Declare a two dimensional array
- LOCAL aLong
- aLong = A_DECLARE( 'L', 5, 7 )
-
- // Using A_KILL() on a non-string type array is an error.
- A_KILL( aLong )
-
- // Show the error code for a type mismatch.
- ? A_ERROR() // Result: 2001
-
-
- See Also: errcodes.ngo:"Error Codes"
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_FILL()
- Fill all or a portion of an array with a specified value
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_FILL( <aTarget>,
- <expValue>,
- [<idxPos>],
- [<nCount>] )
-
- Arguments
-
- <aTarget> is the array which will be filled.
-
- <expValue> is an expression which must evaluate to the same type
- as that of the array. This value will be placed in each element of
- the fill range.
-
- <idxPos> is the first position to in the <aTarget> array to fill.
- If not specified, the default value is the first element in the array.
-
- <nCount> is the number of elements to fill starting at <idxPos>.
- If not specified, elements are filled to the end of the array.
-
- Returns
-
- None.
-
- Description
-
- A_FILL() replaces <nCount> elements in the range beginning at
- <idxPos> with <expValue>. The value must be of the same type as
- the array.
-
- Wrapping will occur if <nCount> goes beyond the current row
- pointed to by <idxPos>. For example, if you have a two dimensional
- array with accounts in the first dimension and 12 prior period
- amounts in the second dimension, and you wanted to operate on the
- first quarter (i.e. 3 periods), making <nCount> three times the
- number of accounts will "wrap" around three periods. See the
- discussion on arrays in chapter 2 for more information on this
- feature.
-
-
- Examples
-
- // Declare a two dimensional (F)loating point array
- LOCAL rows, cols
-
- rows = 10
- cols = 20
- aFloat = A_DECLARE( "F", rows, cols )
-
- // Fill the second row of the array with 98.6
- A_FILL( aFloat, 98.6, A_(2, 1), cols )
-
-
- See Also: A_STORE() A_ADD()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_INS()
- Insert an element into an array
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_INS( <aTarget>, [<idxPos>], [<nCount>] )
-
- Arguments
-
- <aTarget> is the array into which an element will be inserted.
-
- <idxPos> is the position in the target array of the element to be
- inserted.
-
- <nCount> is the number of elements to shift. The default is all
- elements starting at <idxPos> until the end of the row in the
- current dimension.
-
- Returns
-
- None.
-
- Description
-
- A_INS() is similar to Clipper's AINS() function. All elements from
- <idxPos> for <nCount> will be shifted down one element. The last
- element in <nCount> will be pushed into oblivion. A blank element
- is inserted at the position created by the shift and filled with
- the default value based on the type of the array (see
- A_DECLARE()).
-
- FlexFile's multi-dimensional arrays are not nested single
- dimensional arrays. Therefore, A_INS()erting an element has no
- other affect than shifting <nCount> elements down one position.
-
- Wrapping will occur if <nCount> goes beyond the current row
- pointed to by <idxPos>. For example, if you have a two dimensional
- array with accounts in the first dimension and 12 prior period
- amounts in the second dimension, and you wanted to operate on the
- first quarter (i.e. 3 periods), making <nCount> three times the
- number of accounts will "wrap" around three periods. See the
- discussion on arrays in chapter 2 for more information on this
- feature.
-
- Examples
-
- // Declare a two dimensional (C)haracter array
- LOCAL rows, cols, x, y, z
-
- rows = 10
- cols = 20
- z = 1
- aChar = A_DECLARE( "C", rows, cols )
-
- // Fill the array with increasing character values.
- FOR x = 1 to rows
- FOR y = 1 to cols
- z++
- A_STORE( aChar, chr(z), A_( x, y ) )
- NEXT
- NEXT
-
- // Insert four blank elements (chr(0)'s) at the first element
- // and shift all elements from the second element to the
- // end of the array down four positions. Wrapping will occur.
- A_INS( aChar, A_(1, 1), 4 )
-
-
- See Also: A_DECLARE() A_DEL() A_SCROLL()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_KILL()
- Release memory for all or a range of elements from a string array
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_KILL( <aTarget>, [<idxPos>], [<nCount>] )
-
- Arguments
-
- <aTarget> is the array in which to release elements.
-
- <idxPos> is the position in the target array of the first element
- to be released. If not specified, A_KILL() begins at the first
- element in the array.
-
- <nCount> is the number of elements to release. The default is all
- elements starting at <idxPos> until the end of the array. This
- includes wrapping.
-
- Returns
-
- None.
-
- Description
-
- FlexFile's string arrays are actually arrays of pointers. That is,
- the array consists of four byte elements, each element capable of
- pointing to a string of data. When declared, each element of the
- array is undefined.
-
- When data is A_STORE()d to an element of a string array, memory is
- allocated for that data. If the array of pointers falls out of
- scope before that memory is released, the memory is orphaned and
- essentially lost until the application is exited.
-
- Therefore, you must use A_KILL() to release the data before
- allowing a FlexFile string array to fall out of scope.
-
- ┌────────────────────────── WARNING ───────────────────────────┐
- │ You must use A_KILL() to release the data from a String type │
- │ array before allowing the array to fall out of scope. │
- └──────────────────────────────────────────────────────────────┘
-
- Examples
-
- // Use A_KILL() to release a FlexFile string type array
- // before exiting the function that created it.
-
- Phrase( "Miles to go before I sleep" )
-
-
- FUNCTION Phrase( cSomePhrase )
-
- LOCAL ffArray
- // Declare a FlexFile string array.
- ffArray = A_DECLARE( 'S', 5, 8 )
-
- // Put the value into element A_( 3, 3 ).
- A_STORE( ffArray, cSomePhrase, A_( 3, 3 ) )
-
- // Do something with the array.
- ? A_RETRIEVE( ffArrary, A_(3, 3) )
-
- // It is necessary to release the memory
- // allocated for the string in the array.
- A_KILL( ffArray )
-
- // The array itself is released by Clipper on return
- RETURN (.T.)
-
-
- See Also: A_STORE() A_DECLARE()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_LEN()
- Return the total number of elements in an array or a specified dimension
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_LEN( <aTarget>, [<nDimension>] ) -> nCount
-
- Arguments
-
- <aTarget> is the array whose elements will be counted.
-
- <nDimension> is the dimension whose elements will be counted. If
- not specified, all elements in the array will be counted.
-
- Returns
-
- A_LEN() returns the number of elements in the array or any one
- dimension of the array.
-
- Description
-
- A_LEN() counts the number of declared elements in an array. If a
- particular dimension is supplied in <nDimension>, then only the
- number of elements in that dimension will be reported.
-
- For example, if you declare a two dimensional array with thirty
- students in the first dimension and their grades on five exams in
- the second, A_LEN() will report thirty elements for the first
- dimension, five elements in the second dimension or one hundred
- and fifty elements in the entire array.
-
- Examples
-
- // Use A_LEN() to scan for the total length of an array.
-
- LOCAL ffArray
- // Declare a FlexFile string array.
- ffArray = A_DECLARE( 'S', 5, 8 )
-
- ? A_LEN( ffArray ) // Result: 40
-
- // Now use to show only the length of the second dimension.
- ? A_LEN( ffArray, 2 ) // Result: 8
-
-
- See Also: A_DECLARE() A_ADD() A_SIZE()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_MAX()
- Return the greatest value found in a numeric array
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_MAX( <aTarget>, [<idxPos>], [<nCount>] )
-
- Arguments
-
- <aTarget> is the numeric type array to evaluate.
-
- <idxPos> is the position in the target array of the first element
- to be evaluated. If not specified, A_MAX() begins its search on
- the first element of the array.
-
- <nCount> is the number of elements to evaluate. The default is all
- elements starting at <idxPos> until the end of the row in the
- current dimension.
-
- Returns
-
- A_MAX() returns an index to the element which has the maximum
- value found in the specified range.
-
- Description
-
- A_MAX() evaluates every element in the specified range of a
- numeric type array and returns an index to the largest element.
-
- Examples
-
- // Declare a two dimensional (I)nteger array
- LOCAL rows, cols, x
-
- rows = 10
- cols = 20
- aInteger = A_DECLARE( "I", rows, cols )
-
- // Fill the second row of the array with increasing
- // integer values 1 - 20
- FOR x = 1 to 20
- A_STORE( aInteger, x, A_( 2, x ) )
- NEXT
-
- // Fetch the maximum value in the first half of the
- // second row.
- ? A_MAX( aInteger, A_( 2, 1 ), cols / 2 ) // Result: 10
-
- See Also: A_MIN() A_SCAN()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_MIN()
- Return the smallest value found in a given range of an array
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_MIN( <aTarget>, [<idxPos>], [<nCount>] )
-
- Arguments
-
- <aTarget> is the numeric type array to evaluate.
-
- <idxPos> is the position in the target array of the first element
- to be evaluated. If not specified, A_MIN() begins its search on
- the first element in the array.
-
- <nCount> is the number of elements to evaluate. The default is all
- elements starting at <idxPos> until the end of the row in the
- current dimension.
-
- Returns
-
- A_MIN() returns an index to the element which has the minimum
- value found in the specified range.
-
- Description
-
- A_MIN() evaluates every element in the specified range of a
- numeric type array and returns an index to that element which has
- the lowest value.
-
-
- Examples
-
- // Declare a two dimensional (UI)nteger array
- LOCAL rows, cols, x
-
- rows = 10
- cols = 20
- auInteger = A_DECLARE( "UI", rows, cols )
-
- // Fill the second row of the array with increasing
- // integer values 1 - 20
- FOR x = 1 to 20
- A_STORE( auInteger, x, A_( 2, x ) )
- NEXT
-
- // Fetch the minimum value in the first half of the
- // second row.
- ? A_MIN( auInteger, A_( 2, 1 ), cols / 2 ) // Result: 1
-
-
-
- See Also: A_MAX() A_SCAN()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_MINUS()
- Subtract all elements of an array by a value or an array of values
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_MINUS( <aTarget>,
- <nValue> | <aValue>,
- [<aSource>] )
-
- Arguments
-
- <aTarget> is the array to be modified. If <aSource> is not
- specified then each element of <aTarget> will be subtracted by the
- <nValue> or element by element by <aValue>.
-
- <nValue> or <aValue> is either a value or an array of values to be
- subtracted.
-
- <aSource> is an optional array of values. If specified, then each
- element of <aTarget> will be filled with the corresponding value
- in <aSource> subtracted by <aValue> or <nValue>.
-
- Returns
-
- Although there is no return value, the <aTarget> array is modified.
-
- Description
-
- A_MINUS() provides a means to perform a subtraction of every
- element in the <aSource> array if specified or the <aTarget> array
- if not. Each element of the <aSource> or <aTarget> array has
- <nValue> or <aValue> subtracted from it. The result of the
- subtraction replaces the value in the <aTarget> array.
-
- A_MINUS() can be performed on any integer or floating point type
- array. These include the (T)iny, (I)nteger, (L)ong, (F)loat and
- (D)ouble. Mixing of these types is allowed.
-
- Notes
-
- If the <aTarget> and the <aSource> arrays are not the same
- dimensions, the results will be a subtraction element for element
- as the arrays are aligned in memory. See chapter two for how
- arrays are aligned in memory.
-
- Examples
-
- // Declare three double type arrays for this function.
- LOCAL rows, cols
-
- rows = 10
- cols = 20
- aSource = A_DECLARE( "D", rows, cols )
- aTarget = A_DECLARE( "D", rows, cols )
- aSubMe = A_DECLARE( "D", rows, cols )
-
- // Fill the target array with 10's
- A_FILL( aTarget, 10, A_(1, 1), rows * cols )
-
- // Subtract 2 from every element in the target array
- A_MINUS( aTarget, 2 )
- ? A_RETRIEVE( aTarget, A_( 4, 5 ) ) // Result: 8.0
-
-
- // Fill the source array with 10's
- A_FILL( aSource, 10, A_(1, 1), rows * cols )
-
- // Subtract five from every element in the source array and
- // put the result in the target array.
- A_MINUS( aTarget, 5, aSource )
- ? A_RETRIEVE( aTarget, A_( 4, 5 ) ) // Result: 5.0
-
-
- // Fill the "subtract me" array with 4's
- // Remember the source array still has all 10's
- A_FILL( aSubMe, 4, A_(1, 1), rows * cols )
-
- // Subtract from every element in the source array the
- // value in every matching element of the "subtract me"
- // array and put the result in the target array.
- A_MINUS( aTarget, aSubMe, aSource )
- ? A_RETRIEVE( aTarget, A_( 4, 5 ) ) // Result: 6.0
-
-
- See Also: A_MULTIPLY() A_PLUS() A_DIVIDE()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_MULTIPLY()
- Multiply all elements of an array by a value or an array of values
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_MULTIPLY( <aTarget>,
- [<nValue> | <aValues>],
- [<aSource>] )
-
- Arguments
-
- <aTarget> is the array to be modified. If <aSource> is not
- specified then each element of <aTarget> will be multiplied by the
- <nValue> or element by element by <aValue>.
-
- <nValue> or <aValue> is either a value or an array of values to be
- multiplied.
-
- <aSource> is an optional array of values. If specified, then each
- element of <aTarget> will be filled with the corresponding value
- in <aSource> multiplied by <aValue> or <nValue>.
-
- Returns
-
- Although there is no return value, the <aTarget> array is modified.
-
- Description
-
- A_MULTIPLY() provides a means to perform a multiplication of every
- element in the <aSource> array if specified or the <aTarget> array
- if not. Each element of the <aSource> or <aTarget> array will be
- multiplied by <nValue> or <aValue>. The result of the
- multiplication replaces the value in the <aTarget> array.
-
- A_MULTIPLY() can be performed on any integer or floating point
- type array. These include the (T)iny, (I)integer, (L)ong, (F)loat
- and (D)ouble (both signed and unsigned integers, of course).
- Mixing of these types is allowed, however, if the <aTarget> array
- is of integer type, decimals will be truncated.
-
- Notes
-
- If the <aTarget> and the <aSource> arrays are not the same
- dimensions, the results will be a multiplication element for
- element as the arrays are aligned in memory. See chapter two for
- how arrays are aligned in memory.
-
- Examples
-
- // Declare three double type arrays for this function.
- LOCAL rows, cols
-
- rows = 10
- cols = 20
- aSource = A_DECLARE( "D", rows, cols )
- aTarget = A_DECLARE( "D", rows, cols )
- aMultiplier = A_DECLARE( "D", rows, cols )
-
- // Fill the target array with 10's
- A_FILL( aTarget, 10, A_(1, 1), rows * cols )
-
- // Multiply every element in the target array by 2
- A_MULTIPLY( aTarget, 2 )
- ? A_RETRIEVE( aTarget, A_( 4, 5 ) ) // Result: 20.0
-
-
- // Fill the source array with 10's
- A_FILL( aSource, 10, A_(1, 1), rows * cols )
-
- // Multiply every element in the source array by five and
- // put the result in the target array.
- A_MULTIPLY( aTarget, 5, aSource )
- ? A_RETRIEVE( aTarget, A_( 4, 5 ) ) // Result: 50.0
-
-
- // Fill the multiplier array with 4's
- // Remember the source array still has all 10's
- A_FILL( aMultiplier, 4, A_(1, 1), rows * cols )
-
- // Multiply every element in the source array by every element
- // in the multiplier array and put the result in the target
- // array.
- A_MULTIPLY( aTarget, aMultiplier, aSource )
- ? A_RETRIEVE( aTarget, A_( 4, 5 ) ) // Result: 40.0
-
-
-
-
- See Also: A_DIVIDE() A_PLUS() A_MINUS()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_PLUS()
- Add all elements of an array by a value or an array of values
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_PLUS( <aTarget>,
- [<nValue> | <aValues>],
- [<aSource>] )
-
- Arguments
-
- <aTarget> is the array to be modified. If <aSource> is not
- specified then each element of <aTarget> will be added to <nValue>
- or element by element by <aValue>.
-
- <nValue> or <aValue> is either a value or an array of values to be
- added.
-
- <aSource> is an optional array of values. If specified, then each
- element of <aTarget> will be filled with the corresponding value
- in <aSource> added to <aValue> or <nValue>.
-
- Returns
-
- Although there is no return value, the <aTarget> array is
- modified.
-
- Description
-
- A_PLUS() provides a means to perform an addition of every element
- in the <aSource> array if specified or the <aTarget> array if not.
- Each element of the <aSource> or <aTarget> array will be added to
- <nValue> or <aValue>. The result of the addition is placed in the
- <aTarget> array.
-
- A_PLUS() can be performed on any integer or floating point type
- array. These include the (T)iny, (I)integer, (L)ong, (F)loat and
- (D)ouble (both signed and unsigned integers, of course). Mixing
- of these types is allowed, however, if the <aTarget> array is of
- integer type, decimals will be truncated.
-
- Notes
-
- If the <aTarget> and the <aSource> arrays are not the same
- dimensions, the results will be an addition element for element as
- the arrays are aligned in memory. See chapter two for how arrays
- are aligned in memory.
-
- Examples
-
- // Declare three double type arrays for this function.
- LOCAL rows, cols
-
- rows = 10
- cols = 20
- aSource = A_DECLARE( "D", rows, cols )
- aTarget = A_DECLARE( "D", rows, cols )
- aAddMe = A_DECLARE( "D", rows, cols )
-
- // Fill the target array with 10's
- A_FILL( aTarget, 10, A_(1, 1), rows * cols )
-
- // Add 2 to every element in the target array
- A_ADD( @aTarget, 2 )
- ? A_RETRIEVE( aTarget, A_( 4, 5 ) ) // Result: 12.0
-
-
- // Fill the source array with 10's
- A_FILL( aSource, 10, A_(1, 1), rows * cols )
-
- // Add five to every element in the source array and
- // put the result in the target array.
- A_ADD( @aTarget, 5, aSource )
- ? A_RETRIEVE( aTarget, A_( 4, 5 ) ) // Result: 15.0
-
-
- // Fill the "add me" array with 4's
- // Remember the source array still has all 10's
- A_FILL( aAddMe, 4, A_(1, 1), rows * cols )
-
- // Add to every element in the source array the
- // value in every matching element of the "add me"
- // array and put the result in the target array.
- A_ADD( @aTarget, aAddMe, aSource )
- ? A_RETRIEVE( aTarget, A_( 4, 5 ) ) // Result: 14.0
-
-
-
- See Also: A_DIVIDE() A_MULTIPLY() A_MINUS()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_RETRIEVE()
- Return the value of a specified element of an array
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_RETRIEVE( <aTarget>,
- <idxPos> ) -> expValue
-
- Arguments
-
- <aTarget> is the array to return a value from.
-
- <idxPos> points to the element whose value is to be returned.
-
- Returns
-
- A_RETRIEVE() returns the value of the element in <aTarget> pointed
- to by <idxPos>. The type of the value will always be the same
- type as that of the array unless an error is encountered. In the
- case of an error, the return value will be (.F.).
-
- Description
-
- A_RETRIEVE() is used to get the value of an element from a FlexFile
- array.
-
- Notes
-
- ■ If a numeric value was stored as a double or float, the value
- returned will be equivalent to the value stored, but if you display the
- value without a PICTURE clause, it will show the number of decimals
- according to the value of SET DECIMAL TO (which is not necesarily the
- same number of decimals that were visable when the value that was
- A_STORE()ed).
-
-
- Examples
-
- // Declare a two dimensional (UL)ong integer array
- LOCAL rows, cols
-
- rows = 10
- cols = 20
- auLong = A_DECLARE( "UL", rows, cols )
-
- // Fill the 5th row with 100,000
- A_FILL( auLong, 123456, A_(5, 1), cols )
-
- // Multiply the value in the fifth row, fourth column
- // by five and print the result.
- ? A_RETRIEVE( auLong, A_( 5, 4 ) ) * 5 // Result: 617280
-
- See Also: A_STORE() A_TYPE() A_DECLARE()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_SCAN()
- Scan an array or part of an array for an expression
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_SCAN( <aTarget>,
- <expSearch>,
- [<idxPos>],
- [<nCount>] ) -> nAbsPos
-
- Arguments
-
- <aTarget> The array to scan.
-
- <expSearch> An expression that evaluates to the same type as the
- <aTarget> array.
-
- <idxPos> is the first position to in the <aTarget> array to be
- scanned. If not specified, the default value is the first element
- of the array.
-
- <nCount> is the number of elements to scan starting at <idxPos>.
- If not specified, elements are searched to the end of the array.
-
- Returns
-
- A_SCAN() returns an integer which is the absolute index pointer to
- the first element found that matches . If no match is found
- A_SCAN() returns 0. The <nAbsPos> can and should be used in any
- further references to that element (see example below).
-
- Description
-
- A_SCAN() is used to search a FlexFile array for a value. A_SCAN()
- will return an error if <expSearch> evaluates to a different type
- than the <aTarget> array.
-
- Wrapping will occur if <nCount> goes beyond the current row
- pointed to by <idxPos>. For example, if you have a two
- dimensional array with accounts represented by the first dimension
- and 12 prior period amounts in the second dimension, and you
- wanted to scan the first quarter (i.e. 3 periods) for a value,
- making <nCount> three times the number of accounts will "wrap"
- around three periods. See the discussion on wrapping in the
- Arrays Chapter.
-
- Examples
-
- LOCAL ffArray, ptr, rows, cols
-
- rows = 5
- cols = 8
-
- // Declare a FlexFile floating point type array.
- ffArray = A_DECLARE( 'F', 5, 8 )
-
- // Store a couple of values.
- A_STORE( ffArray, 1234.56, A_( 3, 3 ) )
- A_STORE( ffArray, 789.10, A_(4, 4) )
-
- // Scan the entire array...
- ptr = A_SCAN( ffArray, 789.10 )
- ? A_RETRIEVE( ffArray, ptr ) // Result: 789.10
-
- // Scan starting at the first element in the fourth row.
- ? A_SCAN( ffArray, 1234.56, A( 4, 1 ) ) // Result: 0
-
- // Scan starting at the first element in the third row.
- ptr = A_SCAN( ffArray, 1234.56, A_( 3, 1 ) )
- ? A_RETRIEVE( ffArray, ptr ) // Result: 1234.56
-
- // Scan starting at the first element in the second row
- // but only count for one row.
- ? A_SCAN( ffArray, 1234.56, A_( 2, 1 ), cols ) // Result: 0
-
-
-
- See Also: A_STORE() A_DECLARE() A_RETRIEVE()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_SCROLL()
- Scroll all or part of an array
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_SCROLL( <aTarget>,
- [<idxPos>],
- [<nCount>],
- [<nMagnitude>] )
-
- Arguments
-
- <aTarget> is the array in which elements will be scrolled.
-
- <idxPos> is the first position to in the <aTarget> array to be
- scrolled. If not specified, the default value is the first
- element.
-
- <nCount> is the number of elements to be scrolled starting at
- <idxPos>. If not specified, elements are scrolled to the end of
- the array.
-
- <nMagnitude> indicates how far and in what direction to scroll the
- array. A positive value scrolls the elements up (toward the
- beginning); a negative value scrolls the elements down (towards
- the end). If no value is specified, the defined range is scrolled
- one element up.
-
- Returns
-
- None.
-
- Description
-
- A_SCROLL() scrolls all or a portion of a FlexFile array
- <nMagnitude> number of elements. All elements at the end of the
- scroll are lost and the new elements are initialized to null. Do
- not confuse FlexFile's null with Clipper's NIL. A numeric null is
- 0, a logical null is (.F.) and a string null is "".
-
- Wrapping will occur if <nCount> goes beyond the current row
- pointed to by <idxPos>. For example, if you have a two
- dimensional array with accounts represented by the first dimension
- and 12 prior period amounts in the second dimension, and you
- wanted to scroll the first quarter (i.e. 3 periods) up in the
- array, making <nCount> three times the number of accounts will
- "wrap" the scroll. Three periods worth of amounts will be
- scrolled out of the array and three periods of 0's will be filled.
- See the discussion on arrays in chapter 2 for more information on
- this feature.
-
- Examples
-
- LOCAL ffArray, accounts, periods
-
- accounts = 50
- periods = 12
-
- // Declare a FlexFile double precision type array.
- ffArray = A_DECLARE( 'D', periods, accounts )
-
- // Close out a quarter by scrolling three periods.
- // (i.e. scroll all accounts by 3 periods.)
- A_SCROLL( ffArray, , , -(accounts * 3) )
-
- // Insert a new account just in front of the 7th account.
- accounts++
- A_SIZE( @ffArray, periods, accounts )
- FOR x = 1 to periods
- A_SCROLL( ffArray, A_( x, 7 ), accounts - 7, -1 )
- NEXT
-
-
-
- See Also: A_INS() A_DEL() A_SCAN()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_SIZE()
- Dynamically change the size or dimensions of an array
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_SIZE( @<aTarget>,
- <nElements>,
- [, <nElements>...] ) -> lSuccess
-
- Arguments
-
- <aTarget> is the array to re-size. It must be passed-by-
- reference. A_SIZE() cannot resize binary type arrays.
-
- <nElements> are the new dimensions of the array.
-
- Returns
-
- A_SIZE() returns (.T.) if the function was successful, otherwise,
- it returns (.F.). In addition, the aTarget array is modified.
-
- Description
-
- A_SIZE() modifies the dimensions of the @<aTarget>. If the
- array is increased in size, the new elements will be added to the
- end of the array and assigned to null. If the array is decreased
- in size, the data at the end of the array will be lost.
-
- You cannot change the number of dimensions with A_SIZE(), rather,
- you can change only their magnitude.
-
- Examples
-
- // Declare a two dimensional (L)ong integer array
- LOCAL rows, cols, x, y, z := 0
-
- rows = 10
- cols = 20
- aLong = A_DECLARE( "L", rows, cols )
-
- // Fill the array with increasing values.
- FOR x = 1 to rows
- FOR y = 1 to cols
- A_STORE( aLong, z++, A_( x, y ) )
- NEXT
- NEXT
-
- // Increase the size of the array by 10 rows
- A_SIZE( @aLong, rows + 10, cols )
-
- // Show some results.
- ? A_RETRIEVE( aLong, 10, 20 ) // Result: 200
- ? A_RETRIEVE( aLong, 11, 1 ) // Result: 0
-
-
-
-
- See Also: A_ADD() A_DEL() A_INS()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_SORT()
- Sort all or part of an array in ascending or descending order
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_SORT( <aTarget>,
- [<idxPos>],
- [<nCount>],
- [<cOrder>] )
-
- Arguments
-
- <aTarget> is the array to be sorted. A_SORT will not sort a Binary
- "logical" type array.
-
- <idxPos> is the position in the <aTarget> array to begin the sort.
- If not specified, the default value is one.
-
- <nCount> is the number of elements beginning at <idxPos> to sort.
- If not specified, all elements are sorted to the end of the row in
- the current dimension.
-
- <cOrder> is either "Ascending" or "Descending". Only the first
- letter is significant. If not specified, the sort is made
- "Ascending".
-
- Returns
-
- None.
-
- Description
-
- A_SORT() will sort all or part of a FlexFile array. If <cOrder>
- is ascending, elements with higher values are stored at the top
- (beginning) of the array. If <cOrder> is descending, elements
- with lower values are stored at the top of the array.
-
- Wrapping will occur if <nCount> goes beyond the current row
- pointed to by <idxPos>.
-
- Examples
-
- // Declare a two dimensional (C)haracter array
- LOCAL rows, cols, x, y, z
-
- rows = 10
- cols = 20
- z = 1
- aChar = A_DECLARE( "C", rows, cols )
-
- // Fill the array with increasing character values.
- FOR x = 1 to rows
- FOR y = 1 to cols
- z++
- A_STORE( aChar, chr(z), A_( x, y ) )
- NEXT
- NEXT
-
- // Sort the first row in descending order
- A_SORT( aChar, A_( 1, 1 ), cols, 'D' )
-
- // Show the results
- ? A_RETRIEVE( aChar, A_( 1, 1 ) ) // Result:
- ? A_RETRIEVE( aChar, A_( 1, 20) ) // Result:
-
-
- See Also: A_SCAN()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_STORE()
- Store an expression into an element of an array
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_STORE( <aTarget>,
- <expValue>,
- <idxPos> ) -> lSuccess
-
- Arguments
-
- <aTarget> is the array in which to store <expValue>.
-
- <expValue> is any simple Clipper expression that evaluates to the
- same type as the array.
-
- <idxPos> is the index to the element whose value will become
- <expValue>.
-
- Returns
-
- A_STORE() returns (.T.) if successful, otherwise, (.F.).
-
- Description
-
- A_STORE() stores a value in a FlexFile type array. The value
- being stored must be of the same type as that of the array.
- Storing a value with a different type than the array is considered
- an error and A_STORE() will return (.f.).
-
- ┌────────────────────────── WARNING ───────────────────────────┐
- │ You must use A_KILL() to release the data that has been type │
- │ A_STORE()d to a string type array before allowing the array │
- │ to fall out of scope. │
- └──────────────────────────────────────────────────────────────┘
-
- Examples
-
- // Declare a two dimensional (C)haracter array
- LOCAL rows, cols, x, y, z
-
- rows = 10
- cols = 20
- z = 1
- aChar = A_DECLARE( "C", rows, cols )
-
- // Fill the array with increasing character values.
- FOR x = 1 to rows
- FOR y = 1 to cols
- z++
- A_STORE( aChar, chr(z), A_( x, y ) )
- NEXT
- NEXT
-
- // Print out the results: All ASCII characters from one
- // to 200. If you run this program it will beep an sqauk
- // and generally look ugly.
- FOR x = 1 to rows
- FOR y = 1 to cols
- z++
- ? A_RETRIEVE( aChar, A_( x, y ) )
- NEXT
- NEXT
-
-
-
- See Also: A_KILL() A_FILL() A_RETRIEVE()
-
-
-
- ───────────────────────────────────────────────────────────────────────────────
- A_TYPE()
- Return the type of an array
- ───────────────────────────────────────────────────────────────────────────────
-
- Syntax
-
- A_TYPE( <aTarget> ) -> cType
-
- Arguments
-
- <aTarget> is the array whose type is returned.
-
- Returns
-
- A_TYPE() returns the type of the <aTarget> as a character
- string.
-
- Description
-
- A_TYPE() returns the type of a FlexFile array. If the array is of
- integer type and was declared as unsigned, then a "U" will precede
- the type.
-
- The return value is a character string such as "L" for a long
- integer or "UL" for an unsigned long integer.
-
- Appendix C lists all the array types and sizes.
-
-
- Examples
-
- // Setup seven variables of differing array types.
- LOCAL aLogical ,;
- aChar ,;
- aTiny ,;
- auTiny ,;
- aInteger ,;
- auInteger ,;
- aLong ,;
- auLong ,;
- aString ,;
- aFloat ,;
- aDouble
-
- // Declare an array for each possible type.
- aLogical = A_DECLARE( 'B', 10 )
- aChar = A_DECLARE( 'C', 10 )
- aTiny = A_DECLARE( 'T', 10 )
- auTiny = A_DECLARE( 'UT', 10 )
- aInteger = A_DECLARE( 'I', 10 )
- auInteger = A_DECLARE( 'UI', 10 )
- aLong = A_DECLARE( 'L', 10 )
- auLong = A_DECLARE( 'UL', 10 )
- aString = A_DECLARE( 'S', 10 )
- aFloat = A_DECLARE( 'F', 10 )
- aDouble = A_DECLARE( 'D', 10 )
-
- // Show the type of each array
- ? A_TYPE( aLogical ) // Result: B
- ? A_TYPE( aChar ) // Result: C
- ? A_TYPE( aTiny ) // Result: T
- ? A_TYPE( auTiny ) // Result: UT
- ? A_TYPE( aInteger ) // Result: I
- ? A_TYPE( auInteger) // Result: UI
- ? A_TYPE( aLong ) // Result: L
- ? A_TYPE( auLong ) // Result: UL
- ? A_TYPE( aString ) // Result: S
- ? A_TYPE( aFloat ) // Result: F
- ? A_TYPE( aDouble ) // Result: D
-
-
-
- See Also: A_DECLARE()
-
- Error Codes Introduction
-
- Changes:
-
- The FlexFile error system has been changed significatly in
- releases after 1.01. The main differences are that:
-
- 1. Any call to any FlexFile V_xxx() function will reset
- the V_ERROR() to zero. Any call to any A_xxx() function
- will reset the A_ERROR() to zero. This prevents an error
- setting from appearing in a context other than what
- caused it.
-
- 2. Two error codes are now maintained. One for the V_xxx()
- functions and the other for the A_xxx() functions.
-
- 3. Calling either V_ERROR() or A_ERROR() no longer resets
- the error code. Therefore, you can now make multiple calls
- to the desired error reporting routine without loosing the
- error.
-
-
- General Information
-
- The FlexFile error system is accessed by either of the two
- functions A_ERROR() or V_ERROR(). These functions can be
- accessed from the debugger's expression window or placed
- directly in your code. Of course, if you plan to use either
- function from the debugger you must refer to them with either
- the EXTERNAL command or explicitly within your code in order
- for the LINKER to include them in your application.
-
- The error functions will report the last error that
- was trapped by FlexFile as a numeric integer. For example, if
- you attempt to V_USE() a file which is already being used
- exclusivly by another user on a network, V_USE() will return a
- -1 and V_ERROR() will return 5052. However, if you do not
- test the V_ERROR() return value until after you try to
- V_REPLACE() a value (remember no file was opened), then
- V_ERROR() will return 7301 indicatating a V_REPLACE() error.
-
- Ignore any numbers in the 10's and 1'n place in the return
- value from the error functions; these are used by the
- FlexFile support staff. So, for example, 7301 and 7302 both
- refer to the 7300 class of error.
-
- These functions, when called, reset the error value to zero
- which indicates that no error has occurred.
-
- See Also: V_ERROR() A_ERROR()
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 0100 Not an array.lib type array.
- ──────────────────────────────────────────────────────────────────────────────
-
-
- A parameter passed is not a FlexFile strongly typed array but
- should have been.
-
- The most usual cause of this problem is that a parameter is
- out of order in the parameter list of a FlexFile function or a
- Clipper array was passed instead of a FlexFile type array.
-
- See Also: A_DECLARE()
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 0300 Invalid A_DECLARE() dimensions
- ──────────────────────────────────────────────────────────────────────────────
-
-
- An attempt was made to declare an array with greater than six
- dimensions or zero dimensions.
-
- See Also: A_DECLARE()
-
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 0400 Attempt to address an out of bounds element.
- ──────────────────────────────────────────────────────────────────────────────
-
-
- An attempt was made to address an element which is outside of
- the bounds of the FlexFile array.
-
- For example, if you declare a single dimensional array with
- twenty elements and then try to access the twenty first
- element (or an element in the second or greater dimension),
- A_ERROR() will return 400.
-
- See Also: A_RETRIEVE() A_DECLARE()
-
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 0500 Attempt to declare an array larger than 65535 bytes.
- ──────────────────────────────────────────────────────────────────────────────
-
-
- Because the elements of different FlexFile array types require
- different amounts of space, you must look at each array type
- to determine the maximum number of elements possible.
-
- The limiting factore in FlexFile arrays of every type is 65535
- bytes. So, for example, an integer array which requires only
- two bytes per element will reach this limit when you attempt
- to declare an integer array of slightly more than 32,000
- elements.
-
- See the reference to A_DECLARE() for a table of array type and
- required sizes per element.
-
- See Also: A_DECLARE()
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 0600 Attempt to declare an array with an invalid type.
- ──────────────────────────────────────────────────────────────────────────────
-
-
- The arrays type must be one that FlexFile recognizes. These
- are listed in the A_DECLARE() function reference.
-
- See Also: A_DECLARE()
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 0700 Attempt to declare an array with invalid dimensions.
- ──────────────────────────────────────────────────────────────────────────────
-
-
- A FlexFile type array may have a minimum of one and a maximum of
- six dimensions.
-
- See Also: A_DECLARE()
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 0800 Out of memory on an attempt to declare an array
- ──────────────────────────────────────────────────────────────────────────────
-
-
- In S'87 and the initial release of Clipper 5.0 it is a fatal
- error when an attempt is made to declare an array larger than
- available memory. However, this is a bug in 5.0 and when
- fixed this error will indicate that condition and the error
- system will be automatically called.
-
- See Also: A_DECLARE()
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 2000 Array type incompatible with function called.
- ──────────────────────────────────────────────────────────────────────────────
-
-
- The array function called cannot operate on the type of the
- array passed. For example, if you pass A_SORT() a binary type
- array, no sort will be performed and this error will be set.
-
- See Also: A_SORT() A_SCAN()
-
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 2100 Function called is not valid on binary arrays.
- ──────────────────────────────────────────────────────────────────────────────
-
-
- Binary (logical) arrays are not supported by many of the FlexFile
- array functions. For example, you cannot A_SCAN() an array for a
- logical (.t.) or (.f.) and you cannot A_SORT(). The FlexFile
- array functions which operate on binary arrays are:
-
- A_STORE()
- A_RETRIEVE()
- A_LEN()
- A_TYPE()
-
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 2200 Divide by zero in a FlexFile array math function.
- ──────────────────────────────────────────────────────────────────────────────
-
-
- FlexFile's math functions such as A_DIVIDE() are protected against
- a programmer error of division by zero. In the event this error
- occurs, the division results in a zero value and this error is
- flagged.
-
- See Also: A_DIVIDE()
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 2300 A_COPY() used with incompatable array types
- ──────────────────────────────────────────────────────────────────────────────
-
-
- An attempt was made to use A_COPY() on two different array types.
- A_COPY() must be performed on arrays of the same type.
-
-
- See Also: A_COPY()
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 3000 Bad or missing parameter in array function.
- ──────────────────────────────────────────────────────────────────────────────
-
-
- A parameter was passed to a FlexFile array function that is not
- the correct type or a parameter is required that was not passed.
-
- The most usual cause of this problem is that a parameter is
- out of order in the parameter list of a FlexFile function or a
- parameter was inadvertently omitted.
-
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 3100 A_SIZE() error in dimensions.
- ──────────────────────────────────────────────────────────────────────────────
-
-
- A_SIZE() cannot change the number of an arrays dimensions, rather,
- it can only change the magnitude of each dimension. An attempt
- was made to change the number of dimensions.
-
-
- See Also: A_SIZE() A_ADD()
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 5000 Unable to open file.
- ──────────────────────────────────────────────────────────────────────────────
-
-
- This error can result from many different situations:
-
- Disk access denied (disk full).
- Create error.
- Impropper file name (directory does not exist).
- File opened exclusively by other user.
-
-
- See Also: V_USE() V_VLF2FILE() network.ngo:Network Programming
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 5200 Attempt to lock header failed.
- ──────────────────────────────────────────────────────────────────────────────
-
-
- This error occurs when V_USE() fails to get a lock on the header
- of the DBV file.
-
- See Also: V_USE() "Error 5000"
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 5300 Out of memory.
- ──────────────────────────────────────────────────────────────────────────────
-
-
- This error occurs when FlexFile fails to allocate memory using
- Clipper's extend system. Because FlexFile requires very little
- memory, this is an unusual error and indicates extremely low memory
- conditions.
-
-
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 6000 Invalid or missing parameter.
- ──────────────────────────────────────────────────────────────────────────────
-
-
- This error occurs whenever FlexFile detects a parameter of the
- wrong type or a missing parameter when one is required.
-
- The most usual cause of this problem is that a parameter is
- out of order in the parameter list of a FlexFile function.
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 6200 Bad pointer-field passed.
- ──────────────────────────────────────────────────────────────────────────────
-
-
- FlexFile generates a six byte character string which points to
- data stored in a DBV file. If you attempt to use anything but
- a FlexFile generated pointer-field in an attempt to access data
- in a DBV file, this error will be generated. The single exception
- to this rule is an empty pointer-field which must be six (or more)
- spaces.
-
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 6300 Invalid data type in v_replace().
- ──────────────────────────────────────────────────────────────────────────────
-
-
- The valid data types for V_REPLACE() are defined in the V_REPLACE()
- function reference. If FlexFile encounters a type which is not
- amoung these valid types, this error will be generated.
-
- In addition, if you make the mistake of using a pointer-field which
- points into one file as a pointer-field for a different file, FlexFile
- will again generate this error. This is because the pointer-field
- is pointing to something other than the header which FlexFile pre-
- pends to each field.
-
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 6400 Proclip(tm) window is not a compatible version.
- ──────────────────────────────────────────────────────────────────────────────
-
-
- An attempt was made to restore a Proclip window which has been
- stored to a DBV file while using an incompatible (most probably newer)
- version of Proclip.
-
- You will need a newer version of FlexFile to accomodate the new
- Proclip window type.
-
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 6500 VLF length exceeds Clipper's maximum 65535 bytes.
- ──────────────────────────────────────────────────────────────────────────────
-
-
- In certain circumstances it is possible to create a VLF that is
- larger than 64K. The V_STUFF() function is capable of increasing
- the size of a field with no regard for memory, and the V_FILE2VLF()
- function will easily create fields that are extremely large.
-
- If you then attempt to V_RETRIEVE() this data, this error will be
- set and V_RETRIEVE() will fail.
-
- See Also: V_RETRIEVE() V_STUFF() dbvfunc.ngo V_REPLACE()
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 6600 Clipper 5.0 array's cannot be saved with V_REPLACE().
- ──────────────────────────────────────────────────────────────────────────────
-
-
- Use V_AREPLACE() to store Clipper 5.0 arrays.
-
-
- See Also: V_AREPLACE()
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 6700 Error in V_ARETRIEVE(). Array corrupted.
- ──────────────────────────────────────────────────────────────────────────────
-
-
- An attempt was made to retrieve an array from a DBV but the array
- was found to be corrupted. V_PACK()ing the file is recommended.
-
-
- See Also: V_ARETRIEVE()
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 7100 Write error. The disk may be full.
- ──────────────────────────────────────────────────────────────────────────────
-
-
- An attemt to write data failed. If the file was in use in shared
- mode, this error can still occur after the lock has been secured.
- The most likely cause for this error is no remaining disk space.
-
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 7200 Record locking time out.
- ──────────────────────────────────────────────────────────────────────────────
-
-
- This is an error code for future versions of FlexFile.
-
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 7300 File not open in currently V_SELECTed() area.
- ──────────────────────────────────────────────────────────────────────────────
-
- Attempt was made to access a DBV file in a FlexFile work area
- that does not have a file open. For example,
-
- V_CLOSE()
- V_REPLACE( "Try and put this away", ptr_fld )
-
- See Also: V_SELECT() V_ALIAS()
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 7400 Selected area is out of bounds. See v_files().
- ──────────────────────────────────────────────────────────────────────────────
-
-
- You can only V_SELECT() an area within the current V_FILES() setting.
- The default setting for the maximum number of areas is 10.
-
- See Also: V_FILES() V_SELECT()
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 7500 Unknown alias.
- ──────────────────────────────────────────────────────────────────────────────
-
-
- An attempt was made to V_SELECT() (or pass a function that accepts
- an area as a parameter) an illegal or unknown alias.
-
- See Also: V_ALIAS() V_SELECT() V_USE()
-
- ─────────────────────────────────────────────────────────────────────────────
- Error 7600 Illegal attempt to reset V_FILES() or V_BUFFERS
- ─────────────────────────────────────────────────────────────────────────────
-
-
- An attempt was made to set V_FILES() or V_BUFFERS() when there was at
- least one DBV file open. You must first close all DBV files before
- attempting to use these functions.
-
- See Also: V_FILES() V_BUFFERS()
-
- ─────────────────────────────────────────────────────────────────────────────
- Error 7700 Invalid V_RETRIEVE() substring parameters.
- ─────────────────────────────────────────────────────────────────────────────
-
-
- When using V_RETRIEVE() to retrieve only part of a VLF, the parameters
- representing the bounds of the string to retrieve were invalid.
-
- See Also: V_RETRIEVE()
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 8000 No areas remain. See v_files() to increase the quantity of areas.
- ──────────────────────────────────────────────────────────────────────────────
-
-
- An attempt was made to V_USE() with the "NEW" modifier or V_SELECT(0)
- when all available areas are in use. The solution to this problem
- is to increase your maximum FlexFile work areas with the V_FILES()
- function.
-
- See Also: V_FILES() V_SELECT() V_USE()
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 8100 Not a VLF type file.
- ──────────────────────────────────────────────────────────────────────────────
-
-
- Attempt was made to V_USE() a file that is not recognizable as a
- FlexFile type file.
-
- See Also: V_USE()
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 8200 File read error.
- ──────────────────────────────────────────────────────────────────────────────
-
- This error is possible if an exclusive lock has been imposed
- by another work station on a network.
-
- See Also: V_EXCLUSIV()
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 8300 Unknown data type. Possibly using a pointer-field from wrong work area.
- ──────────────────────────────────────────────────────────────────────────────
-
-
- The valid data types for V_REPLACE() and V_RETRIEVE() are defined
- in the V_REPLACE() function reference. If FlexFile encounters a
- type which is not amoung these valid types, this error will be
- generated. For example, using V_RETRIEVE() to try to fetch a Summer
- 87 array will create this error. Use V_FILLARR() instead.
-
- In addition, if you make the mistake of using a pointer-field which
- points into one file as a pointer-field for a different file, FlexFile
- will again generate this error. This is because the pointer-field
- is pointing to something other than the header which FlexFile pre-
- pends to each field.
-
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 8400 Attempt to V_RETRIEVE a Proclip window.
- ──────────────────────────────────────────────────────────────────────────────
-
- An attempt was made to V_RETRIEVE() a Proclip window. Use
- V_WNDCREAT() to create a Proclip window that has been stored
- to a DBV file.
-
-
- See Also: V_WNDCREAT()
-
- ──────────────────────────────────────────────────────────────────────────────
- Error 9000 Undetermined error in seek for deleted space.
- ──────────────────────────────────────────────────────────────────────────────
-
- Unfortunately, this spells disaster and is usually caused by a
- corrupted DBV file. However, the FlexFile scheme is based on
- a very solid principal. That is, if your DBF file holding the
- pointer-fields into the DBV file is intact, the V_RETRIEVE()
- function will almost invariably still retrieve data from any
- field that has not yet been corrupted.
-
- So, disaster recovery is as simple as creating a new DBV file
- in a new FlexFile work area and V_REPLACE()ing data into the
- new area with the data V_RETRIEVE()d from the corrupted area.
-
- Remember to test for V_TYPE() on the pointer-field because if
- it encounters a corrupted portion of the file, it will return
- an "U"ndefined regardless of the data type stored in that
- particular field.
-
-
-
-