>>> "File is in use by another"

The message "File is in use by another" results from an attempt to USE a
read-only database file with single-user dBASE Administrator.

To avoid this situation, use PROTECT to prevent editing of database files
rather than making the files read-only.


>>> 43-Line Mode Using the Enhanced Graphics Adapter

Users of dBASE III PLUS who have the IBM Enhanced Graphics Adapter and
Display will notice that this hardware is supported but not documented.  If
you enter the full-screen configuration SET at the dot prompt and select
the Color menu, you will notice that instead of "Color" or "Monochrome,"
"EColor25" and "EColor43" will be shown.   You can toggle between the
regular 25-line mode and the IBM Enhanced Graphic Adapter's special 43-line
mode by pressing the Return key.

Once in the 43-line mode, dBASE III uses all 43 lines of the screen in all
display modes.  This includes regular display commands such as LIST or
DISPLAY, as well as full-screen commands such as APPEND, EDIT, BROWSE,
@..SAY, @..GET. Unfortunately, no command in dBASE III PLUS can toggle
modes, other than the full-screen SET command.

In order to take advantage of this undocumented feature, set the switch
settings on the IBM Enhanced Graphic Adapter should be as follows:

               SWITCHES
      1       2       3       4
     Off      On      On     Off

For more information on using of the IBM Enhanced Graphic Adapter, consult
the manual provided with the card.


>>> @...GET...PICTURE

BY J. MIKE HEDBLOM

Issuing @...GET on logical fields produces different displays when READ is
executed,  depending on the presence of "@L" PICTURE function and the
version of dBASE III PLUS.   If a logical field has an assigned value,
@...GET displays that value.  However, if the field  has not been assigned
a value, in version 1.0, @...GET displays a "?" and @...GET...PICTURE  "@L"
displays "T."  Version 1.1 displays a "?" when the PICTURE function is
present, but  shows a blank if the PICTURE function is not used.  


>>> @...SAY & Overstriking

It is possible to produce overstriking on a printer with the @...SAY
command in dBASE III PLUS. The documentation warns that, after executing
SET DEVICE TO PRINT, an @...SAY command with row or column coordinates less
than the coordinates of the previous @...SAY will cause a page eject. This
is true of row coordinates. However, it is possible to @...SAY at a lesser
column coordinate in the same row or even at the same coordinate. For
example, the following commands produce underlined output.

   SET DEVICE TO PRINT
   @ 10,20 SAY "UNDERLINE"
   @ 10,20 SAY "_________"
   SET DEVICE TO SCREEN



>>> @...SAY 

When sending control codes to the printer with @...SAY, control codes are
counted as characters by dBASE III PLUS although these characters are not
printed by the printer.  This causes the print position coordinates for
following @...SAY commands to the same line to be offset left by the number
of control code characters sent to the printer.  For instance, if one
control character is sent to row 5, the column coordinate on row 5 will be
less by one.

   @ 5,0 SAY CHR(15)
   @ 5,12 SAY "Test"

will print "Test" starting at column 11.  The control codes for the
following example are for the C-Itoh 8510A printer.

   SET DEVICE TO PRINT
   @ 5,5 SAY CHR(27) + '!' + 'Test' + CHR(27) + '"'
                 ^------^-----------------^------^
                        |--- Each character takes one space.
                        This prints the word "Test" in boldface and sets
                        the type back to normal.

   @ 5,50 SAY "Test"  <------- Prints at column 46.
   @ 6,50 SAY "Test"  <------- Prints at column 50.




>>> @..SAY/GET

With SET SCOREBOARD ON, an @...SAY to line 0 in a format file will not
write in the scoreboard area, but an @...GET will read from this area. 
This is consistent with previous versions of dBASE III.  However, the
larger size of the SCOREBOARD area in dBASE III PLUS increases the
likelihood of conflict between SET SCOREBOARD ON and @...SAY...GET.


>>> @...PICTURE

When you use @...PICTURE with negative numbers, you need a template
position for the minus sign.  If you don't have one and the number fills
the number of template digits you define an overflow will display. 
Including the "@(" PICTURE function to surround negative values with
parentheses also requires a position for the minus sign, although the
symbol is not used.  The length of the template must be at least the length
of the number plus one for the sign.  For example,

   mvar = -100
   @ 5,20 SAY mvar PICTURE "999"
   @ 6,20 SAY mvar PICTURE "@( 999"

each display an overflow.  However,

   @ 5,20 SAY mvar PICTURE "9999"
   @ 6,20 SAY mvar PICTURE "@( 9999"

correctly display, "-100" and "(100)," respectively.


>>> ACCEPT/WAIT

When a function key is SET to a literal character string, the ACCEPT TO
command accepts the assigned string, while WAIT TO does not. Instead, the
WAIT command takes the decimal ASCII representation of the function key
itself. For example,

     SET FUNCTION 10 TO 'A'
     WAIT TO mem
     ACCEPT TO mem1

If F10 is pressed in response to the WAIT and ACCEPT commands, DISPLAY
MEMORY shows a graphic character representing the ASCII code of the F10 key
in mem and an "A" in mem1.

For reference, here are the values stored when these keys are pressed in
response to the WAIT command.

  Key Pressed     Value     Function
  ===========     =====     ========
  F1              0         HELP
  F2              255       ASSIST
  F3              254       LIST
  F4              253       DIR
  F5              252       DISPLAY STRUCTURE
  F6              251       DISPLAY STATUS
  F7              250       DISPLAY MEMORY
  F8              249       DISPLAY
  F9              248       APPEND
  F10             247       EDIT
  SPACE           32        SPACE
  BACKSPACE       127       BACKSPACE

All other keys that send nondisplay characters (including Alt,
control keys, and shifted keypad characters) send an ASCII 0.


>>> ACCESS DISK [dBASE III PLUS - Multi-User]

Because of a disk manufacturing error in which a unique access code was not
recorded on System Disk #1 and System Disk #1 Back-up of dBASE III PLUS,
Ashton-Tate implemented an exchange policy for the affected products.  The
serial numbers of the affected products are 2500001 through 2533960. Copies
of dBASE III PLUS with other serial numbers are fully functional and are
not affected.

The defect involves only local area network use.  It does not affect
functionality or data integrity of dBASE III PLUS when used in its
stand-alone, single-user mode.  The problem was created when a special
access code that permits dBASE III PLUS to be networked with other copies
of dBASE III PLUS  was not placed on System Disk #1 and System Disk #1
Back-up.  All other disks packaged with the product are not affected.


>>> Accessing Filenames with No Extensions

In dBASE III PLUS, you can now access and create files with no extensions. 
To access or create such a file, use the double period (..) in place of the
extension.  For example, you can access an external file with no extension
in the APPEND FROM command.  Virtually all dBASE III PLUS commands that
operate on files support this capability.

The following list of command lines show a number of ways to work with
these files.

   * ---Import a file with no extension.
   APPEND FROM Yourfile.. SDF

   * ---Export a file with no extension.
   COPY TO Yourfile.. SDF

   * ---Open a database file with no extension.
   USE Yourfile..

   * ---Rename a file with no extension.
   RENAME Yourfile.. TO Yourfile.TXT

Note that DIR does not respect the (..) notation.  You must instead use the
standard wildcard notation.


>>> APPEND FROM

Beginning with the Developer's Release of dBASE III, APPEND FROM
[DELIMITED] will import delimited files without delimiters. Formerly,
delimited files without delimiters would be erroneously APPENDed into the
current database file.


>>> APPEND FROM DELIMITED

APPEND FROM <Filename> DELIMITED WITH BLANK does not recognize blank fields
and left-justifies the APPENDed data.  When a blank field is APPENDed, the
field is filled with data from the next field in the record.  The data in
the fields following the blank field are shifted into preceding fields. 
Leading blanks are removed from all APPENDed data.  To illustrate,


     .LIST
     Record#  Field1   Field2   Field3
           1  March    March    March
           2  April             April
           3  May      May        May
           4  June     June      June  

    . COPY TO Test TYPE DELIMITED WITH BLANK
    . ZAP
    . APPEND FROM Test TYPE DELIMITED WITH BLANK
    . LIST
     Record#  Field1   Field2   Field3
           1  March    March    March
           2  April    April
           3  May      May      May
           4  June     June     June


In record 2, the data from Field3 shifted to Field2.  This occurs in both
versions 1.0 and 1.1 of dBASE III PLUS.


>>> Applications Generator

The Applications Generator does not reset the SET commands it changes to
their original values when terminating.  This means that subsequent
operations affected by the status of any SET commmand could be compromised
unless you reset it.  Most noticeably, SET SAFETY is changed to OFF.   

The following is a list of the SET commands the Applications Generator
changes and the status when you leave the Applications Generator:

   Command     Setting
   -------------------
   BELL		ON
   CONFIRM	ON
   ESCAPE	     OFF
   FIELDS	     OFF
   HEADINGS	OFF
   SAFETY	     OFF
   STATUS	     ON
   TALK		ON

To workaround this, create a command file that calls the Applications
Generator and then resets the current status of all critical SET commands. 
When you need to run the Applications Generator, DO this command file
instead.

This occurs in both versions of dBASE III PLUS.


>>> ASSIST/RETRIEVE

On page L1-24 of the original dBASE III PLUS documentation,
ASSIST Retrieve:List:Construct a field list is incorrectly
documented as displaying an arrow next to selected fields. An
arrow does briefly flash next to the selected fields but does not
remain on screen.

The documentation also states that fields can be deselected by
pressing Return on the previously selected field. Selected fields
are dimmed, indicating that they cannot be deselected.


>>> ASSIST

There is no way to close files from ASSIST.  To close files opened in
ASSIST, select ASSIST Set Up:Quit dBASE III, or execute a CLEAR ALL or
appropriate CLOSE command from the dot prompt after leaving ASSIST.


>>> ASSIST and Subdirectories

If you are an ASSIST user, you may have found that you cannot change
directories in ASSIST.  The following program, Subdir.PRG, allows you to
provide support for subdirectories by running ASSIST from a menu that
includes choices for changing directories.

Whenever you want to enter ASSIST, type DO Subdir and choose the directory
where you want to work.  When you are situated, choose the option for
ASSIST and away you go.  After you leave ASSIST, you must also quit Subdir
by pressing Esc.  Subdir then CLOSEs all the DATABASES you may have opened.

If you want Subdir to come up automatically whenever you bring up dBASE III
PLUS, add the command line

  COMMAND=DO Subdir;

to your Config.DB file.

The program operates by selecting subdirectories from the current default
directory you boot dBASE III PLUS from.  After it loads (this can take some
time), you can move forward to all of the subdirectories under the current
one and back.  You can run ASSIST from any selected subdirectory.

Subdir has, in addition, a number of small but significant features.  For
example, it displays the volume label for the current drive.  It has row
and column coordinates that may be modified to change the display location
of the menu window.  It also displays the default directory name, so you
always know where you started.

There are some limitations to be aware of:

1. Subdir only displays the first 9 subdirectories it encounters, no matter
how many there are in the default directory.

2. It does not allow the user to navigate anywhere on the disk.

3. It does not display sub-subdirectories.


Program Code

  * Program ...: Subdir.PRG
  * Author ....: Stephen Goodman and Olivier Biggerstaff
  * Date ......: April 1, 1987
  * Note(s) ...: Executes a menu that allows you to change your DOS
  *              directories in association with ASSIST.
  *
  SET TALK OFF
  SET BELL OFF
  SET SAFETY OFF
  SET TITLE OFF
  CLEAR
  *
  * ---This portion creates a database file to hold the
  * ---names of the subdirectories in the current directory.
  @ 12,2 SAY "Reading directory - Please wait"
  RUN DIR > Sysdir.TXT
  SET CATALOG TO Sysdir
  SELECT 10
  COPY STRUCTURE EXTENDED TO Tempfile
  SET CATALOG TO
  SELECT 1
  USE Tempfile
  ZAP
  APPEND BLANK
  REPLACE field_name WITH "Textdata",;
          field_type WITH "C",;
          field_len WITH 80
  USE
  CREATE SYSDIR FROM Tempfile
  APPEND FROM Sysdir.TXT SDF
  DELETE FILE Tempfile.DBF
  DELETE FILE Sysdir.TXT
  DELETE FILE Sysdir.CAT
  *
  * ---The drive and volume label are saved to variables.
  GOTO 2
  drive = SUBSTR(Textdata, 18, 1) + ":"
  title = TRIM("Available Directories" + ;
            IIF(SUBSTR(Textdata, 23, 1) = " ", "", " for " + ;
                SUBSTR(Textdata, 23)))
  *
  * ---The current directory is the default.
  GOTO 3
  d_default = drive + TRIM(SUBSTR(Textdata, 18))
  *
  * ---Delete all non-subdirectory entries.
  DELETE FOR SUBSTR(Textdata, 1, 1) = ".";
        .OR. SUBSTR(Textdata, 14, 5) <> "<DIR>"
  PACK
  *
  * ---Read the database file into memory variables.
  dot = .F.
  GOTO TOP
  DO WHILE .NOT. EOF()
     datanum      = LTRIM(STR(RECNO()))
     data&datanum = SUBSTR(Textdata, 1, 8)
     IF SUBSTR(Textdata, 10, 1) <> " "
        data&datanum = data&datanum + "." + SUBSTR(Textdata, 10, 3)
        dot = .T.
     ENDIF
     SKIP
  ENDDO
  *
  * ---The maximum number of subdirectories is 9.
  maximum = LTRIM(STR(MIN(9, RECCOUNT())))
  USE
  DELETE FILE Sysdir.DBF
  maxlength = LEN(d_default) + 11 + IIF(dot, 0, 4)
  maxlength = MAX(LEN(title), maxlength) + 6
  line = CHR(199) + REPLICATE(CHR(196), maxlength - 2) + CHR(182)
  default = .T.
  choice  = " "
  mchoice = " "
  DO WHILE .T.
     choice = " "
     CLEAR
     row = 6
     col = 4
         *
     * ---Draw a double lined box with 2 lines in it.
     @  row - 2, col - 3 TO VAL(maximum) + 12, maxlength DOUBLE
     @  row + 1, col - 3 SAY line
     @  row - 1, col     SAY title
         *
     * ---If there are no subdirectories, say so.
     IF maximum = "0"
        @ row, col SAY "None in "+d_default
     ELSE
        @ row + 5, col - 3 SAY line
        @ row, col - 1     SAY IIF(default, CHR(175), " ") + "Default is " +
  d_default
     ENDIF
     @ row + 2, col SAY "A. Run ASSIST"
     @ row + 3, col SAY "B. Go to Default"
     @ row + 4, col SAY "E. Exit"
         *
     * ---Display the subdirectory names in the box.
     datanum = "1"
     DO WHILE datanum <= maximum
        @ row + VAL(datanum) + 5, col SAY datanum + ". Directory " +
  data&datanum
        datanum = LTRIM(STR(VAL(datanum) + 1))
     ENDDO
     IF .NOT. default .AND. mchoice $ "123456789"
        @ row + VAL(mchoice) + 5, col - 1 SAY CHR(175)
     ENDIF
     @ row + VAL(datanum) + 7, col SAY "Enter selection: "
     choice = " "
     mcol = COL()
     DO WHILE .NOT. (choice $ "ABE" .OR. (choice >= "1" .AND. choice <=
  maximum))
        choice = " "
        @ row + VAL(datanum) + 7,mcol + 1 GET choice;
                                          PICTURE "!"
        READ
     ENDDO
         *
     * ---Change directory, run ASSIST, or exit to dBASE III PLUS.
     DO CASE
     CASE choice = "A"
        ASSIST
     CASE choice = "B"
        CLEAR
        RUN CD &d_default
        default = .T.
     CASE choice = "E"
        EXIT
     CASE choice >= "1" .AND. choice <= maximum
        mchoice = choice
        CLEAR
        d_choice = data&choice
        IF LEN(d_default) = 3
           RUN CD \&d_choice
        ELSE
           RUN CD &d_default\&d_choice
        ENDIF
        default = .F.
    ENDCASE
  ENDDO
  *
  * ---Close up and return to the default directory.
  CLEAR
  CLOSE DATABASES
  RUN CD &d_default
  SET TALK ON
  SET SAFETY ON
  SET TITLE ON
  RETURN
  * EOP Subdir.PRG



>>> ASSIST

In ASSIST, it is not possible to specify the .NOT. (or FALSE) of
a logical field in a search condition. When a logical field is
specified as the search condition, ASSIST uses .T. as the search
condition. This is true of versions 1.0 and 1.1 of dBASE III
PLUS.



>>> ASSIST

1. In any of the submenus of the Update, Position, Retrieve, or
   Organize menus that support the building of search conditions, when
   building a condition for a date type field, non-date entries are
   accepted as an argument for the CTOD() function without an error
   message.  In the Developer"s Release and earlier versions this would
   fail to locate any date field.  But since the CTOD() function in dBASE
   III PLUS converts non-date entries to blank dates, searching for
   non-date entries on date fields with dBASE III PLUS will position the
   record pointer at the first blank date encountered.  If there are no
   blank dates in the database file, dBASE III PLUS will not locate any
   records.

2. With versions of dBASE III greater than 1.1, it is not possible to build
   a search condition for blank spaces from ASSIST.  The Developer"s
   Release would return the user to ASSIST without comment when this was
   attempted.  dBASE III PLUS will attempt to execute the command.
   However, when it constructs the command line, blank spaces are
   excluded.  For example, requesting ASSIST to

      LIST FOR <Field> = "    "

   actually executes:

     LIST FOR <Field> = ""



   Since all conditions are true when compared to a null string, this is
   identical to:

      LIST ALL


>>> BROWSE

The Ctrl-Home and F10 keys behave slightly differently in BROWSE.
Both keys call the menu bar to the screen, but only Ctrl-Home
removes it. This is true of both versions of dBASE III PLUS.



>>> BROWSE

BROWSE is extremely slow paging through a database file if the
file is indexed and the index contains many identical entries.
The wait to move from one page to the next is better measured in
minutes than seconds and may appear to have locked the machine.
The amount of time necessary is proportional to the amount of
records with identical keys in the index file. This occurs in
both versions of dBASE III PLUS.



>>> BROWSE

The status bar is a part of BROWSE and cannot be removed with SET
STATUS OFF. The state of the status bar prior to BROWSE is
restored when BROWSE is exited. 


>>> CALL

Including the memory variable alias (M->) in the WITH clause of the CALL
command returns the error message "Not a character expression." if the data
type of the memory variable you pass is numeric.  The variable is passed
correctly if the M-> alias is not included.  Since, however, CALL...WITH
assumes a character expression or a memory variable of any type, when you
pass a memory variable and a field with the same name exists, dBASE III
PLUS always passes the memory variable reference to the WITH clause.

This occurs in both versions of dBASE III PLUS.


>>> CASE

When using the CASE structure to branch control within your command files,
there are two distinct behaviors if the either the DO CASE or ENDCASE
statements are missing from the construct.

1. If a CASE statement is not preceded by a DO CASE statement, commands
   following the CASE statement and preceding the ENDCASE statement will
   not execute.  In the following example, the LIST and WAIT commands do
   not execute but the DISPLAY MEMORY statement does.

     DO WHILE .T.
        USE Test
        CASE
           LIST  <--------|
           WAIT  <--------| Commands do not execute.
       ENDCASE
       DISPLAY MEMORY  <---------- Command executes.
     ENDDO

2. A CASE structure without a terminating ENDCASE will terminate execution
   of a command file and return control to the dot prompt without an error
   message when the first true CASE statement executes.


>>> CHR(0) to Printer

BY CHUCK LITZELL

dBASE III PLUS is unable to send CHR(0) to the printer. Since
dBASE uses CHR(0) internally to mark the end of strings, it
processes right up to, but does not include, the CHR(0).

This is a problem only if you need to send control codes that
include CHR(0) to the printer. Many printers ignore the high bit
when processing escape codes. Therefore, sending CHR(128) in
place of CHR(0) might work because CHR(128) is the equivalent of
CHR(0) with bit seven turned on.

If CHR(128) does not produce the desired results with your
printer, however, you can use the following DEBUG script to
create a .BIN file that will send CHR(0) to your printer. Using a
text editor or the dBASE MODIFY FILE command, create a text file,
named Prnull.DBG, with the lines that follow. Note the empty line
five lines from the bottom; it's important!

   N    PRNULL.BIN
   A    100
   PUSH AX
   PUSH DX
   XOR  DX, DX
   MOV  AX, 0500
   INT  21
   POP  DX
   POP  AX
   RETF
   
   RCX
   C
   W
   Q


To create Prnull.BIN, you must have access to DEBUG.COM, which
you will find on your DOS Supplemental Program diskette. Change
to the drive and directory in which you want to create Prnull.BIN
and enter

   DEBUG < Prnull.DBG

This command will create Prnull.BIN. If you don't get the DOS
prompt rather quickly, there is an error in your DEBUG script.
Press Return until you see a dash (DEBUG's prompt), and type Q 
and then press Return to quit DEBUG. When Prnull.BIN has been
successfully created you can erase Prnull.DBG.

Using Prnull.BIN from within dBASE III PLUS is simple. First LOAD
Prnull. Any time you need to print a CHR(0), just CALL Prnull.
The following example sets the form length to seven inches on an
Epson FX-80 printer. 

   * Set Form Length to 7 inches
   *      on Epson FX-80 printer
   * (ESC C NUL 7)
   LOAD Prnull
   SET PRINT ON
   SET CONSOLE OFF
   ?? CHR(27) + "C"
   CALL Prnull
   ?? CHR(7)
   SET PRINT OFF
   SET CONSOLE ON
   RELEASE MODULE Prnull



>>> CHR()

CHR(138) and CHR(141), "" and "" respectively, produce
unexpected results when displayed on the screen and cause .PRG
files containing these characters to appear corrupted when edited
with MODIFY COMMAND.  Displaying CHR(138) causes the rest of the
characters on that line to be suppressed.  CHR(141) displays
following characters on the next line.  This occurs because dBASE
III PLUS interprets CHR(138) and CHR(141) as a linefeed and a
carriage return, respectively.

The dBASE III PLUS MODIFY COMMAND editor strips off the eighth
data bit of all characters except CHR(141) when files are
loaded.  When CHR(138) is loaded into MODIFY COMMAND, it is
transformed into CHR(10).  Because CHR(10) is the MODIFY COMMAND
end-of-line marker, data after the CHR(138) is not displayed. 
Executing a program file that formerly contained CHR(138)
produces various errors when executed, depending on the command
affected.  When CHR(141) is loaded into the editor, characters
following are displayed on the next line and the line status, on
the right side of the screen, reveals that the line is
continued.  The CHR(141) remains in the file unless it is deleted
or overwritten.  This occurs in both versions 1.0 and 1.1 of
dBASE III PLUS.  


>>> CLEAR

CLEAR is incorrectly documented on page U5-50 of the original
documentation as positioning the cursor in the upper left-hand
corner of the screen at coordinates 0,0. CLEAR positions the
cursor to the lower left-hand corner of the screen at coordinates
24,0 if SET STATUS is OFF, or coordinates 21,0 if SET STATUS is
ON.


>>> Compaq 386 DOS

Running dBASE III PLUS on a Compaq 386 requires Compaq 386 DOS, not
standard MS-DOS.  To check whether a machine is running Compaq 386 DOS,
enter the DOS MODE command at the operating system using the AUTO parameter
(a valid parameter of Compaq 386 DOS only).  For example, at the operating
system, type

       C> MODE AUTO

If the error message "Invalid parameter" is returned, the machine is running
the wrong version of DOS.  Running the wrong DOS may cause problems with
system I/O.


>>> CONFIG.DB

The Command section of the original Using dBASE III PLUS manual
says, "SET STATUS is normally ON."  However, STATUS actually
defaults to OFF unless STATUS=ON is included in the CONFIG.DB
file. The CONFIG.DB file included with the original dBASE III
PLUS disks contains the line STATUS=ON.


>>> CONFIG.DB

Using the keyword COMMAND in the CONFIG.DB or loading dBASE III PLUS with
DBASE <Filename> alters the initial sign on.  If this keyword is not
included in the CONFIG.DB file and the command DBASE is used to call the
program up, dBASE III PLUS will display the license agreement on the screen
and immediately present the dot prompt.  However, if COMMAND = <command> is
included in CONFIG.DB or if dBASE III PLUS is invoked with a command
filename on the DOS command line, the sign-on message will remain on the
screen for approximately ten seconds or until Return is pressed before
executing the command from CONFIG.DB or DOing the specified file.


>>> COPY STRUCTURE EXTENDED

Sometimes you may want to make a copy of a database file structure without
making an exact duplicate as you would with the COPY STRUCTURE command.  As
a typical situation, you might have database file that is usable, but you
think has a corrupted header.  You would like to COPY the database file
with a new header and not have to recreate the structure by hand.  With
COPY STRUCTURE EXTENDED, this task can be accomplished quite easily. The
following block of code shows just exactly how.

   * ---Create new file.
   USE <old file>
   COPY STRUCTURE EXTENDED TO <extended file>
   CLOSE DATABASE
   CREATE <new file> FROM <extended file>
   * ---COPY old file data to new file.
   USE <new file>
   APPEND FROM <old file>
   CLOSE DATABASE

1. Description

dBASE III PLUS and its predecessors, the Developer's Release, version 1.1,
and version 1.0, do not allow you to COPY a DELIMITED file without
delimiters and commas separating fields. Using the WITH BLANK option, you
can get an text file without delimiters but you also get a text file
without commas separating fields.  A standard delimited file looks like
this:

   "field1","field2",12,.T.
   ^      ^         ^
   |      |         |
   |      |          ----------- Field separator.
    ---------------------------- Delimiter that bounds character

fields.

If the external processor that you are interfacing only supports comma
separated text files without delimiters, you can use the following command
file to create one.  The resulting text file will be in the following form:

   field1,field2,12,.T.

To run this program, type the following command line in a command file or
at the dot prompt:

        DO Cpdelim WITH "<database filename>","<index filename>",;
                                "<filter condition>","<output filename>"

The resulting file will have a (.TXT) extension.

2. Program Example

  * Program ...: Cpdelim.PRG 
  * Author ....: Christopher White 
  * Date ......: May 1, 1986 
  * Note(s) ...: Program to COPY to a DELIMITED file without delimiters. 
  * 
  PARAMETERS dbf, ndx, condition, txtfile 
  * ---Set environment. 
  SET TALK OFF 
  SET SAFETY OFF 
  * ---Open database file to copy and define the working set of 
  * ---records. 
  filexp = dbf + IIF("" <> TRIM(ndx)," INDEX " + ndx,"") 
  USE &filexp
  SET FILTER TO &condition 
  GO TOP 
  * ---Create a structure extended file. 
  COPY STRUCTURE EXTENDED TO Temp 
  SELECT B 
  USE Temp 
  * ---Find the last field is that not a memo field. 
  lastrec = RECCOUNT() 
  GO BOTTOM 
  DO WHILE Field_type = "M" .AND. (.NOT. BOF())
     lastrec = lastrec - 1
     SKIP -1 
  ENDDO 
  * ---Open output text file. 
  SET ALTERNATE TO &txtfile 
  SET ALTERNATE ON 
  * ---Output records. 
  SELECT A 
  DO WHILE .NOT. EOF()
     SELECT B
     GO TOP
     * ---Output fields.
     DO WHILE .NOT. EOF()
        fld_nme = TRIM("A->" + Field_name)
        DO CASE
        CASE field_type = "C"
           * ---Character field.
           ?? TRIM(&fld_nme)
        CASE field_type = "D"
           * ---Date field.
           ?? STR( YEAR(&fld_nme),4 ) +;
              RIGHT( STR(100 + MONTH(&fld_nme),3),2 ) +;
              RIGHT( STR(100 +   DAY(&fld_nme),3),2 )
        CASE field_type = "N"
           * ---Numeric field.
           ?? LTRIM(STR(&fld_nme,Field_len,Field_dec))
        CASE field_type = "L"
           * ---Logical field.
           ?? &fld_nme
        ENDCASE
        * ---Insert field separator.
        ?? IIF(RECNO() = lastrec,"",",")
        SKIP
     ENDDO
     * ---Insert record separator.
     ?
     * ---Get next output record.
     SELECT A
     SKIP 
  ENDDO 
  * ---Clean up. 
  CLOSE ALTERNATE 
  CLOSE DATABASES 
  ERASE Temp.DBF
  RETURN 
  * EOP Cpdelim.PRG


>>> CREATE LABEL

The correct upper limit for Options:Labels across page is 5, not 15 as
documented on pages  L6-19 and U5-64 of the dBASE III PLUS documentation. 
This is corrected in the second  edition.

   Elapsed. PRG
  * Program ....: Elapsed.PRG
  * Author .....: Chuck Litzell
  * Date .......: October 1, 1987
  * Version ....: dBASE III Plus 
  * Note(s) ....: Calculates elapsed time between a starting date and time
  *               and an ending date and time.
  *               Returns result in fifth parameter as a character string in
  *               the format HH:MM:SS
  *
  *               The program is called with the following syntax:
  *
  *                 DO Elapsed WITH sdate, stime, edate, etime, result
  *
  *                 sdate   ::= starting date, date expression
  *                 stime   ::= starting time as HH:MM:SS;
  *                             character expression
  *                 edate   ::= ending date, date expression
  *                 etime   ::= ending time as HH:MM:SS;
  *                             character expression
  *                 result  ::= character memvar, difference is stored
  *                             in this variable as HH:MM:SS
  *
  PARAMETERS sdate, stime, edate, etime, result
  * ---Proportion of a day for an hour, minute and second.
  hour = 1 / 24
  min  = hour / 60
  sec  = min / 60
  
  * ---Get starting date + time in dstart.
  dstart = sdate + VAL(stime) * hour +;
                   VAL(SUBSTR(stime, AT(":", stime) + 1, 2)) * min +;
                   VAL(RIGHT(stime, 2)) * sec
  
  * ---Get ending date + time in dend.
  dend = edate + VAL(etime) * hour +;
                 VAL(SUBSTR(etime, AT(":", etime) + 1, 2)) * min +;
                 VAL(RIGHT(etime, 2)) * sec
  
  timedif = ABS(dend - dstart)
  result  = IIF(dend < dstart, "-", "")
  rhour   = INT(timedif / hour)
  rmin    = INT((timedif - rhour * hour) / min)
  rsec    = ROUND((timedif - rhour * hour - rmin * min) / sec,0)
  result  = result + LTRIM(STR(rhour)) + ":" +;
                     RIGHT(STR(rmin + 100, 3), 2) + ":" +;
                     RIGHT(STR(rsec + 100, 3), 2)
  RETURN
  * ---EOP: Elapsed.PRG.
  
  
  Projtime.PRG
  * Program ....: Projtime.PRG
  * Author .....: Chuck Litzell
  * Date .......: October 1, 1987
  * Version ....: dBASE III Plus Versions, 1.0 and 1.1
  * Note(s) ....: Calculates future date and time by adding a number of
  *               days, hours, minutes and seconds to a given date and time.
  *
  *               The program is called with the following syntax:
  *
  *                 DO Projtime WITH sdate, stime, days, timex, rdate, rtime
  *
  *                 sdate   ::= starting date, date expression
  *                 stime   ::= starting time as HH:MM:SS;
  *                             character expression
  *                 days    ::= number of days to add
  *                 timex   ::= time to add expressed as HH:MM:SS;
  *                             character expression
  *                 rdate   ::= date memvar, receives calculated future date
  *                 rtime   ::= character memvar, receives calculated
  *                             future time expressed as HH:MM:SS
  *
  *
  PARAMETERS sdate, stime, days, timex, rdate, rtime
  
  * ---Proportion of a day for an hour, minute and second.
  hour = 1 / 24
  min  = hour / 60
  sec  = min / 60
  
  * ---Get starting date and time in dwork.
  dwork = sdate + VAL(stime) * hour +;
                  VAL(SUBSTR(stime, AT(":", stime) + 1, 2)) * min +;
                  VAL(RIGHT(stime, 2)) * sec
  
  * ---Add days and time offset.
  dwork = dwork + days + ;
                  VAL(timex) * hour +;
                  VAL(SUBSTR(timex, AT(":", timex) + 1, 2)) * min +;
                  VAL(RIGHT(timex, 2)) * sec
  
  * ---Store integer portion of ending date in rdate.
  * ---This construct removes the decimals that have
  * ---been added to rdate.
  rdate = CTOD(DTOC(dwork))
  
  * ---Get decimal portion of ending date in twork.
  twork = dwork - rdate
  
  * ---Convert twork to a character string.
  rhour = INT(twork / hour)
  rmin  = INT((twork - rhour * hour) / min)
  rsec  = ROUND((twork - rhour * hour - rmin * min) / sec, 0)
  rtime = LTRIM(STR(rhour)) + ":" +;
          RIGHT(STR(rmin + 100, 3), 2) + ":" +;
          RIGHT(STR(rsec + 100, 3), 2)
  RETURN
  * ---EOP: Projtime.PRG.


>>> CREATE FROM

The CREATE FROM command is used to create a database file from a database
file that contains the target database file structure as records.  This a
very useful but not well understood aspect of dBASE III PLUS.  It can be
used as a vehicle for transferring file structures from other processors
such as spreadsheets, word processors, and mainframes.  As an example, your
mainframe consultant could add the target dBASE III database file structure
as a delimited file to the download package he sends you.  It then would be
an easy matter to CREATE the target database file structure FROM the
extended structure definition, and then APPEND FROM the downloaded
delimited data file.  Quite nicely this would free you from knowing or
having to CREATE the target database file structure yourself.

If this prospect intrigues you, the structure of the delimited extended
file must be as follows:

   Field  Field Name  Type       Width    Dec
       1  Field_name  Character     10
       2  Field_type  Character      1
       3  Field_len   Numeric        3
       4  Field_dec   Numeric        3
   ** Total **                      28

Each record of the delimited extended file must have fields equivalent to the
one listed above.  The file should be a standard delimited file obeying all the
rules of the delimited file structure.  The following demonstrates what a
typical delimited extended file looks like.

          ---------------- Field name
                |       --------- Data type
         |      |    ----- Field length
         |      |   |
         v      v   v v -- Number of decimal places if numeric
   "Field_one","C",15
   "Field_two","N",10,2

To import this structure into dBASE III PLUS and translate it into a database
file structure, perform the following steps.

   * ---Create mechanism for structure translation.
   USE <any file>
   COPY STRUCTURE EXTENDED TO Temp
   USE Temp
   ZAP
   * ---Bring the structure to translate into the mechanism.
   APPEND FROM <your structure> DELIMITED
   USE
   * ---Translate your structure into a database file.
   CREATE <your file> FROM Temp
   ERASE Temp.DBF


>>> CREATE REPORT

In CREATE REPORT, the Columns:Decimal places value defaults to
the number of decimal places specified by SET DECIMALS TO when
SET FIXED is ON; ignoring the number of decimal places specified
in the file structure. The documentation for CREATE REPORT
incorrectly states that the Columns:Decimal places value defaults
to the number of decimal places specified in the file structure.
This is true of both versions of dBASE III PLUS.




==============================

   CTOOLS SECTION

>>> Array Save and Restore [cTools Programmers Library]

The Graphics Library uses a binary save of an array, unlike The Programmer's
Library, which uses a text save.  The dBASE Tools for C Incentive Disk allows
you to use a text save with The Graphics Library.


>>> Linking the Graphics Library [cTools Programmers Library]

There have been several requests either to include portions of the Graphics
Library in the Programmer's Library at link time or exclude portions of the
Graphics Library that require source code.  Neither one is possible but you
can load both libraries at once as long as you have 640K of memory.


>>> Scaling [cTools Programmers Library]

The Graphics Library does not currently include parameters to allow manual Y
axis scaling (as in Framework II).  You can, however, write a dBASE III PLUS
using the low-level graphic functions to draw a graph.


   END CTOOLS SECTION

==============================


>>> Date Fields

The date data type uses the Gregorian system of timekeeping in that only
those centesimal  years divisible by 400 are leap years. See the table at
right for examples. This is true for every  version of dBASE III PLUS.

  Year      Number of Days
  2000      366
  1900      365
  1800      365
  1700      365
  1600      366
  1500      365


>>> Date and Time Calculations

BY CHUCK LITZELL

dBASE III PLUS stores Date data types differently in memory variables than
in database  fields.  In a database field, dates are stored as eight digits
in the format YYYYMMDD.   When a date is stored to a memory variable,
however, it is stored as a floating point  number.  The actual value stored
is an offset, in days, from a base date.  This method of  representing
dates makes date math possible.

Since a date memory variable is a floating point number, it should be
possible to store  decimals to the date as well as integers.  Typing these
lines at the dot prompt confirms this:

  . mdate = DATE()
  . ? mdate
  10/01/87
  . mdate = mdate + .5
  . ? mdate
  10/01/87
  . mdate = mdate + .5
  . ? mdate
  10/02/87

Adding .5 to mdate increments the date by one-half day, or 12 hours. 
Adding it a second  time advances the date to the next day.  Applications
that need to perform date and time  calculations can take advantage of this
additional capacity of date memory variables.   The procedures, Elapsed.PRG
(Figure 1) and Projtime.PRG (Figure 2), demonstrate how  times, represented
as a fraction of a day, can be combined with date memory variables in 
calculations.  Elapsed calculates the elapsed time between two dates and
times, and Projtime  calculates the date and time after a given increment
to a given date and time.

Both procedures accept dates and times as input parameters.  Times are
represented as  character strings in a format similar to the result of the
TIME() function, except that the  number of hours may be more than two
digits.  "12:30:15," "1:00:05," and "4521:18:37" are  all handled correctly
by these procedures. However, "12:5:5," "7:30," and "18:12:5," are not 
valid.  The minutes and days must be two digits, and there must be two
colons appropriately  positioned within the string. Here's an example of
how to use Elapsed:

  mtime = ""
  DO Elapsed WITH CTOD("10/01/87"), "12:15:45",;
     CTOD("12/13/87"),  "17:00:00", mtime
  ? mtime
  1756:44:15
  and here's an example of how to use Projtime:
  mdate = CTOD("  /  /  ")
  mtime = ""
  DO Projtime WITH CTOD("12/31/87"), "23:59:59",;
     0, "00:00:01", mdate, mtime
  ? mdate, mtime
  01/01/88 0:00:00


>>> dBCODE

dBCODE does not trap illegal characters in filenames when
encoding command files.  Executing a dBCODEd command file that
references an illegal filename produces the error message
"Unrecognized phrase/keyword in command." [36] or "File does not
exist." [1].


>>> .DBF File Header

The dBASE III PLUS database file header is one byte shorter than that
created by all other versions of dBASE III.  Earlier versions put an
"extra" byte (00H) between the header and the beginning of the data.  dBASE
III PLUS no longer includes this byte and the data begins immediately
following the last byte of the header (0DH).  The number of bytes in the
header (bytes 8 and 9) reflect the smaller header size.

dBASE III PLUS has no problem reading files from earlier versions as long
as bytes 8 and 9 correctly reflect the actual size of the header.

This procedure will create a file one byte smaller than the original file:

  * ---This is a 1.1 created file.
  USE Test
  COPY TO Test1
  DIR                && Test1 is one byte smaller than Test.


>>> Demonstration Disk (RunTime+)

In the Developer's Release of dBASE III, the dBRUN programs from the
Demonstration Disk are not compatible with the full system. Code crunched
with DBC.COM from the Demonstration Disk can only be run with dBRUN from
the Demonstration Disk.  Code crunched with DBC.COM from the Developer's
Disk can only be run with the full dBASE III system or the dBRUN disk,
purchased separately.

 The error message:

     No database is in USE.  Enter filename:

 is a common indicator that the incorrect dBRUN or dBC is being used.


>>> DIRECTORY

DIRECTORY is an undocumented dBASE III PLUS command that performs
identically to the dBASE DIR command. 


>>> DO

dBASE III PLUS allows recursive calls of program files. A program
can call a subprogram and that subprogram can call the
originating program until too many files are open.  For example,

     * A_prog.PRG          * B_prog.PRG
     DO B_prog             DO A_prog

A program may also call itself. The following program continues
to open files until the "Too many files are open." [6] error
message is returned.

   * Test.PRG
   DO Test

It is possible to do this in all versions of dBASE III PLUS.


>>> DO <Procedure>

If you SET PROCEDURE TO a file on a drive other than the default, DO
<Procedure> requires  that the drive designator not be included in the
command.  The commands

  SET PROCEDURE TO A:Test
  DO A:Test1

will cause dBASE III to look for the command file Test1.PRG on drive A:. 
The proper syntax  is

  SET PROCEDURE TO A:Test
  DO Test1

This is true for all versions of dBASE III PLUS. 


>>> DO WHILE

In versions of dBASE III earlier than the Developer's Release, the DO WHILE
command will stop evaluating it's condition as soon as the expression is
complete, ignoring characters beyond that point.  This makes it possible
for conditions with a seemingly invalid expression to be executed.  For
example,

   DO WHILE EOF() = .T.
   DO WHILE EOF() = .F.   both equal   DO WHILE EOF()

and,

   DO WHILE .T. = EOF()   equals       DO WHILE .T.
   DO WHILE .F. = EOF()   equals       DO WHILE .F.

In the Developer's Release and dBASE III PLUS the above conditions will
return the error message, "Invalid operator."


>>> Documentation Error

1. Page 5-25 of the Networking section of the dBASE III PLUS Reference
Manual shows the following command line.

                CASE ERROR() = 158

This command is supposed to trap the "File is in use by another"
condition.  The error number, however, is incorrect and the command line
should read:

                CASE ERROR() = 108

2. There are coding errors on pages 4-18, 5-27, and 5-30 of the Networking
section of the dBASE III PLUS Reference Manual.  The command line,

                IF TIME = 250

purports to test if an attempt to lock a database file failed.  It is not,
however, a reliable coding method and should be changed to

                IF .NOT. FLOCK()

3. On page 4-18 of the Networking section of the dBASE III PLUS Reference
Manual, the command

                times = 1

should be inserted immediately before the SKIP command.  The routine on the
following page is an error handling routine executed if SKIP encounters a
locked record and expects the variable, times, to be reset each time it is
called.

4. On page 5-30 of the Networking section of the dBASE III PLUS Reference
Manual, the UNLOCK command should be placed after the READ command.


>>> EDIT RECORD <n>

In dBASE III versions 1.0 and 1.1, EDIT RECORD <n> and EDIT <n> behave
identically.   They both enter the full-screen edit mode at the record
indicated.  PgUp and PgDn take the  user to the previous and following
records respectively.  In the Developer's Release and  dBASEIIIPLUS, EDIT
<n> acts the same as in version 1.0 and 1.1; however, EDIT RECORD  <n>
allows editing of the specified record only.  PgUp and PgDn return the user
to the dot  prompt.  This is true of both versions of dBASE III PLUS.


>>> EOF()

When you execute REINDEX or PACK on an indexed database file the the record
pointer is positioned to the end-of-file and EOF() returns a true (.T.). 
By contrast, INDEX ON and PACK position the record pointer to the first
record when used on non-indexed database files.

This occurs in both versions of dBASE III PLUS.


>>> ERROR()

The following error messages cannot be trapped by ON ERROR in any version
of dBASE III PLUS, although they do return the error number specified.

   14     No find.
   25     Record not inserted.
   39     Numeric overflow (data was lost).
   49     File has been deleted.
   52     No database in USE.
   56     Disk full when writing file:
   72     ALTERNATE could not be opened.
   73     ^^ Expected ON or OFF.
   74     ^--- Truncated.
   81     Invalid date.
   82     ** Not Found **
   86     ^-- Keyword not found.
   89     Cannot erase a file which is open.
  113     Index interrupted. Index will be damaged if not completed.
  129     Unable to LOCK.
  132     Unauthorized login.
  144     Unauthorized duplicate.
  145     Error in configuration value.
  150     Help text not found.

The following error message cannot be trapped by ON ERROR in version 1.0 of
dBASE III PLUS, but can be trapped in version 1.1.

  149     Master catalog is empty.


>>> Error Messages

The error message "Invalid DIF vector - DBF field mismatch [116]" is
undocumented in the original dBASE III PLUS documentation.  This error
message occurs when APPENDing FROM a DIF file and data in that file
conflicts with the DIF header.


>>> Error Messages by Number

The following is a list of dBASE III PLUS error messages in numeric order.

    1 File does not exist.
    2 Unassigned file no.
    3 File is already open.
    4 End-of-file encountered.
    5 Record is out of range.
    6 Too many files are open.
    7 File already exists.
    8 Unbalanced parenthesis.
    9 Data type mismatch.
   10 Syntax error.
   11 Invalid function argument.
   12 Variable not found.
   13 ALIAS not found.
   14 No find.
   15 Not a dBASE database.
   16 *** Unrecognized command verb.
   17 Cannot select requested database.
   18 Line exceeds maximum of 254 characters.
   19 Index file does not match database.
   20 Record is not in index.
   21 Out of memory variable memory.
   22 Out of memory variable slots.
   23 Index is too big (100 char maximum).
   24 ALIAS name already in use.
   25 Record not inserted.
   26 Database is not indexed.
   27 Not a numeric expression.
   28 Too many indices.
   29 File is not accessible.
   30 Position is off the screen.
   31 Invalid function name.
   33 Structure invalid.
   34 Operation with Memo field invalid.
   35 Unterminated string.
   36 Unrecognized phrase/keyword in command.
   37 Not a Logical expression.
   38 Beginning of file encountered.
   39 Numeric overflow (data was lost).
   41 .DBT file cannot be opened.
   42 CONTINUE without LOCATE.
   43 Insufficient memory.
   44 Cyclic relation.
   45 Not a character expression.
   46 Illegal value.
   47 No fields to process.
   48 Field not found.
   50 Report file invalid.
   51 End of file or error on keyboard input.
   52 No database in USE.
   53 There are no files of the type requested in this drive
      or catalog.
   54 Label file invalid.
   55 Memory Variable file is invalid.
   56 Disk full when writing file:
   57 ***Execution error on CHR() : Out of range.
   58 ***Execution error on LOG() : Zero or negative.
   59 ***Execution error on SPACE() : Too large.
   60 ***Execution error on SPACE() : Negative.
   61 ***Execution error on SQRT() : Negative.
   62 ***Execution error on SUBSTR() : Start point out of
         range.
   63 ***Execution error on STR() : Out of range.
   65 Internal error : Unknown command code:
   66 Internal error : CMDSET():
   67 Internal error : EVAL work area overflow
   68 Internal error : Illegal opcode.
   70 ** WARNING ** Data will probably be lost. Confirm (Y/N).
   72 ALTERNATE could not be opened.
   73 ^^ Expected ON or OFF.
   74 ^--- Truncated.
   75 ^--- Out of range.
   76 ***Execution error on - : Concatenation string too large.
   77 ***Execution error on + : Concatenation string too large.
   78 ***Execution error on ^ or ** : Negative base,
         fractional exponent.
   79 ***Execution error on STORE : String too large.
   81 Invalid date.
   82 ** Not Found **
   86 ^-- Keyword not found.
   87 ***Execution error on NDX() : invalid index number.
   88 ***Execution error on REPLICATE() : String too large.
   89 Cannot erase a file which is open.
   90 Operation with Logical field invalid.
   91 File was not LOADed.
   92 Unable to load COMMAND.COM.
   93 No PARAMETER statement found.
   94 Wrong number of parameters.
   95 Valid only in programs.
   96 Mismatched DO WHILE and ENDDO.
   99 Invalid DOS SET option.
  101 Not suspended.
  102 ***Execution error on STUFF() : String too large
  103 DOs nested too deep.
  104 Unknown function key.
  105 Table is full.
  106 Invalid index number.
  107 Invalid operator.
  108 File is in use by another.
  109 Record is in use by another.
  110 Exclusive open of file is required.
  111 Cannot write to a read-only file.
  112 Index expression is too big (220 char maximum).
  113 Index interrupted. Index will be deleted if not completed.
  114 Index damaged. REINDEX should be done before using data.
  115 Invalid DIF File Header.
  116 Invalid DIF vector - DBF field mismatch.
  117 Invalid DIF Type Indicator.
  118 Invalid DIF character.
  119 Invalid SYLK File Header.
  120 Invalid SYLK Dimension Bounds
  121 Invalid SYLK File Format.
  122 Data Catalog has not been established.
  123 Invalid printer port.
  124 Invalid printer redirection.
  125 Printer not ready.
  126 Printer is either not connected or turned off.
  127 Not a valid VIEW file.
  128 Unable to SKIP.
  129 Unable to LOCK.
  130 Record is not locked.
  131 Database is encrypted.
  132 Unauthorized login.
  133 Unauthorized access level.
  134 Not a QUERY file.
  136 Unsupported path given.
  137 Maximum record length exceeded.
  138 No fields were found to copy.
  139 Cannot JOIN a file with itself.
  140 Not a PFS file.
  141 Fields list too complicated.
  142 Relation record is in use by others.
  143 Query not valid for this environment.
  146 Maximum path length exceeded.
  147 Cannot append in column order.
  148 Network server busy.
  149 Master catalog is empty.

Note also that the following error is not documented.

  146 Maximum path length exceeded.


>>> "EVAL Work area" Messages

The dBASE III PLUS "EVAL work area" is used by any expression in any
command that allows any type of expression or condition. Commands that
contain a condition or expression invoke the expression evaluator and use
the evaluation workarea. The error message "Internal error: EVAL work area
overflow" occurs when a command is too complex to be evaluated within the
workarea's allocated space. This is true of all versions of dBASE III PLUS.



>>> Exclusive .OR.

dBASE's .OR. is nonexclusive.  In other words, it returns true (.T.) in any
case except when both conditions you are comparing are false (.F.).  

Exclusive .OR. (normally called XOR) returns true (.T.) only if the two
conditions you are comparing are different.  

To XOR two conditions, you can use the following formula (where term_a and
term_b represent two logical values):

? (term_a .AND. .NOT. term_b) .OR. (.NOT. term_a .AND. term_b)

The following code fragment prints out all the possible values for XOR:

 x = "(term_a .AND. .NOT. term_b) .OR. (.NOT. term_a .AND. term_b)"
 term_a = .T.
 term_b = .T.
 ? ".T. XOR .T. = " + IIF(&x,".T.",".F.")
 term_a = .T.
 term_b = .F.
 ? ".T. XOR .F. = " + IIF(&x,".T.",".F.")
 term_a = .F.
 term_b = .T.
 ? ".F. XOR .T. = " + IIF(&x,".T.",".F.")
 term_a = .F.
 term_b = .F.
 ? ".F. XOR .F. = " + IIF(&x,".T.",".F.")
  The printout shows:

 .T. XOR .T. = .F.
 .T. XOR .F. = .T.
 .F. XOR .T. = .T.
 .F. XOR .F. = .F.


>>> "***Execution error on SUBSTR(): Start point out of range."

If you are using the SUBSTR() function with memory variables or with an
expression whose value might be null or shorter in length than the starting
position argument of the SUBSTR() function, you will get the error message
"***Execution error on SUBSTR(): Start point out of range."  This is not a
terminal error condition as is the case with a syntax error.  The SUBSTR()
function terminates gracefully, returning a null as the result.  The
execution error, however, does present a problem.  If SET CONSOLE is ON and
the execution error occurs, the error message will echo to the screen,
disturbing your display.  If SET PRINT is ON or the substring expression is
part of any command that is sending output with the TO PRINT clause, the
error message will echo to the printer.  This is particularly a problem
with REPORT and LABEL FORMs.

There are three strategies you can use to suppress the display of the error
message.  The use of each depends on what commands are being used with the
substring expression.

1. If you are assigning memory variables or using @...SAY to send the
result of the substring expression to the screen or printer, you can SET
CONSOLE OFF to suppress the error message.

2. If you are using a TO PRINT command such as LABEL FORM TO PRINT, use the
IIF() function as the starting position expression to return a zero if the
length of the character string is less than the start position you really
want.  SUBSTR() always returns a null string if the starting position is
zero.  For example, the following expression returns a null string if the
length of the memory variable "x" is less than three.

     SUBSTR(x, IIF(LEN(x) < 3, 0, 3), 6)

Use a SUBSTR() with this form to suppress the execution error message.

3. Lastly, you can use ON ERROR to trap execution errors.  Define the
argument of the ON ERROR condition as a dummy expression such as,

      ON ERROR dummy = 0

before you execute a command that causes the execution error.  Be aware
that this approach is limited since you may need the ON ERROR condition for
other purposes.  In addition, branching to a command file in order to trap
a range of error conditions terminates REPORT or LABEL FORMs.


>>> EXPORT

The error messages produced by EXPORT and their causes are not documented. 
They are  not trapped by ON ERROR.  The messages are

1. "Too many @ commands on one page of format file." This error occurs when
there are  more than 200 @ commands in the format file used for EXPORT.

2. "Format files must be in row major order to be exported."  This error
occurs if the <Row>  and/or <Col> coordinates have values that are less
than previously given coordinates.  For  example,

  @ 10,1 SAY 'A'
  @  5,1 SAY 'B'

3. "PFS does not allow row numbers higher than 20."  Any <Row> value higher
than 20  produces this error.

This is corrected in the second edition of the documentation. 


>>> EXP()

The range of the numeric expression of the EXP() function is between

   -708.3964185322642 and 709.7827128933841

Values outside this range exceed the numeric accuracy of dBASE III PLUS and
produce an internal numeric overflow.  For example, using EXP() to evaluate
the exponent of the LOG() of a number should return the original value.  In
the following exmaple, a value outside of the range does return itself.

   * ---Correct result.
   ? LOG(EXP(709))
   709.00
   
   * ---Incorrect result.
   ? LOG(EXP(710))
   11356.52

Evaluating the LOG() of the EXP() of a number below -708.3964185322641
produces the error message "Execution error on LOG() : Zero or negative"
[58].  

This occurs in both versions of dBASE III PLUS.


>>> F1 Key

The F1 function key can be used to exit an active @...GET if the @...GET is
not within a format file opened with SET FORMAT TO. Changes made prior to
pressing F1 are saved as if Ctrl-W were pressed.

However, even though F1 exits and saves the data, it does not produce
exit-key values that are consistent with other dBASE III PLUS write
operations. Write operations always save the data and produce an exit-key 
value that READKEY() interprets as data changed, regardless of whether data
have been altered. When F1 is used to exit a full-screen operation,
READKEY() returns either 36 for no change in data or 292 when data have
changed. To be consistent, F1 should not produce 36 since it means
non-updated data.

Pressing F1 in an active screen format moves the cursor to the beginning of
the current field without exiting the screen. This occurs in all versions
of dBASE III PLUS.



>>> File Extensions

In Table 1 is a list of default filename extensions created by dBASE III
PLUS along with  their descriptions and the commands which may be used to
create them.  Only extensions  that remain on disk once dBASE III PLUS has
terminated normally are included.  

Temporary files created, then erased, by dBASE III PLUS are not included.

Note that DBC.COM and DBL.COM also create files with .PRG extensions.  See
the Runtime  section of the manual for more information on DBC and DBL.

When dCONVERT is used to convert dBASE II files, the old file is renamed
with a "B" for  the last letter of the extension (.??B.)

Following is a list of commands with their descriptions that create a file
with no default  extension. 

  Command        Description
  
  EXPORT TO...   Creates a PFS
  TYPE PFS       file.
  
  MODIFY/CREATE  Creates a text
  FILE           file.
  
  COPY TO...     Creates a 
  TYPE SYLK      Multiplan spreadsheet.


>>> Floating Dollar Signs

dBASE III PLUS does not directly support the display of numbers
right-justified with a floating dollar sign.  To achieve a floating dollar
sign to either print or display numeric data, you can use the following
expression.

  RIGHT(SPACE(<length of number>) + "$" + ;
        LTRIM(TRANSFORM(<number>, "999,999,999,999.99"), <length of
number>)

This expression can be used wherever dBASE III PLUS accepts the result of a
character expression.  This includes @...SAY, ??, LABEL and REPORT FORMS.


>>> For 256K Machines

dBASE III PLUS runs with PC-DOS version 2.xx if you have 256K installed
memory in your computer.  If you have a minimum of 384K of installed
memory, dBASE III PLUS runs with PC-DOS version 3.xx as well as version
2.xx.

For 256K operation, two files are provided, CONFI256.SYS and CONFI256.DB,
on System Disk #1.  These two files set system parameters for maximum
overall performance of dBASE III PLUS in a 256K environment.

The CONFI256.SYS file contains:

   FILES = 20
   BUFFERS = 4

Copy the CONFI256.SYS file to the root directory of the disk you boot DOS
from or the directory set by the DOS COMSPEC command and rename it to
CONFIG.SYS.  If CONFIG.SYS already exists, modify the file to include FILES
= 20 and BUFFERS = 4.

The CONFI256.DB file contains:
    COMMAND = ASSIST
    STATUS = ON
    BUCKET = 1
    GETS = 35
    MVARSIZ = 3
    HISTORY = 10
    TYPEAHEAD = 10

Copy CONFI256.DB into be placed in the same directory as DBASE.COM and
rename it to CONFIG.DB.

The CONFI256.DB settings reduce the memory-intensive parameters allowing
dBASE III PLUS to work in a 256K environment.  The smaller settings place
the following limitations on dBASE III PLUS.

MVARSIZ is reduced to 3,000 bytes which is half the normal default size of
6,000 bytes.  This reduces the amount of space available for memory
variables and may cause incompatibilities with programs written with
earlier versions of dBASE III.  Refer to the SAVE and RESTORE commands for
ways to optimize use of memory variable space.

BUCKET size is reduced to 1,024 bytes, half the normal default size.  This
reduces the amount of memory available for the PICTURE and RANGE options of
the @...GET command, and may cause incompatibilities with programs written
with earlier versions of dBASE III.

CREATE SCREEN is limited to one screen, with a maximum of 35 pending GETs.
Format files created on machines with more memory may not work when moved
to a 256K machine.  The limitation of 35 pending GETs may also cause
incompatibilities with programs written with earlier versions of dBASE III.

The RUN command is not supported on computers with 256K of memory.  dBASE
III PLUS requires 256K, the RUN command requires additional memory for
COMMAND.COM plus the memory required by the external program.  This is
consistent with earlier versions of dBASE III.

The "Insufficient memory" message is an indication that some memory must be
released to allow dBASE III PLUS to continue with the operation.  When
using dBASE III PLUS with 256K RAM this message may result from a
combination of factors and varies with the size and number of database
files, index files, format files, and the HISTORY and TYPEAHEAD buffer
sizes.

If the "Insufficient memory" message is received:

1. Ensure that you are using the correct CONFIG.SYS and CONFIG.DB
   files, as listed above for 256K operation.

2. Close one or more open files and then proceed.

Increasing the amount of RAM in your computer will significantly enhance
the performance of dBASE III PLUS.


>>> GETENV()

You can use DOS environmental variables to set and hold locational pointers
to various directories for the purpose of installing application systems. 
Many modern programs are now so large they require the use of
subdirectories to control the location of information.  In view of this,
many use the DOS environmental variable technique to accomplish the needed
control.

In order to gain the same power with dBASE III PLUS and your programs, use
GETENV() to return the contents of environmental variables that each hold a
directory pointer for a specific set of files.  Remember that GETENV() can
return not only system variables that DOS uses, such as PATH or COMSPEC,
but also environmental variables that you assign in DOS.  You can assign
these variables from anywhere in DOS, but many programs that use this
directory pointer system initialize the environmental variables in the
AUTOEXEC.BAT.

This type of a system in dBASE III PLUS would consist of creating three
basic classes of files (.PRG, .DBF, and .NDX) with three potential
locations.  You could, of course, have many more, but these serve the
purposes of example.

To set this up, you need first to create the environmental variables in DOS
with a series SET command lines as follows:

  SET DB_DIR=<database file directory path>
  SET PRG_DIR=<program file directory path>
       SET NDX_DIR=<index file directory path>

In the initialization area of your main application program you need to
define a series of memory variables using GETENV() that correspond to the
DOS environmental variables you have set up.  For example,

       db_dir  = GETENV("DB_DIR")
       prg_dir = GETENV("PRG_DIR")
       ndx_dir = GETENV("NDX_DIR")

Now that you have the directory pointers variables for each class of file,
you can use them to either SET the dBASE III PLUS PATH to the list of valid
directories or you can them explicitly in file access commands.  For
example,

       SET PATH TO &db_dir., &ndx_dir., &prg_dir.

or

  USE &db_dir.\<database file> INDEX &ndx_dir.\<index file>

and

  DO &prg_dir.\<program name>

One of the problems you may encounter using this technique is not having
enough environment space for your variable definitions.  This can happen
if, for example, you have a long PATH statement.  You can, however, change
the size of the DOS environment if you are running under PC/MS-DOS 3.1 and
above with the undocumented CONFIG.SYS command SHELL.  The general syntax
of the SHELL command is as follows:

SHELL=C:<path>\<command processor> C:<path>\ /P/E:<number of paragraphs>

When you wish to use SHELL, place it in your CONFIG.SYS file along with the
traditional FILES and BUFFERS settings.  To set up the SHELL command line,
specify the path to your command processor, the name of your command
processor (usually COMMAND.COM), the path again, a space, the /P and /E:
switches (no spaces between them) and the number of 16-byte paragraphs to
allocate to the environment space.  If you do not specify the number of
paragraphs, the default is 8 or a total of 128 bytes.  If you do specify a
/E: setting, the acceptable range is 11 to 63.

Be aware that the order and spacing of the SHELL command arguments are
vital.

Reference:

DeVoney, Chris. Using PC DOS. Indianapolis, Indiana: Que Corporation, 1986.
pps. 487-488.


>>> HELP

It is not documented that the HELP command requires a file handle. When
HELP is executed, dBASE III PLUS opens the file HELP.DBS. If the maximum
number of files (15) are already open, the error message "Too many files
are open." [6] is produced when HELP is executed.


>>> HELP.DBS

There are two HELP.DBS files shipped with dBASE III PLUS version 1.1; one
each on System disk #1 and System disk #2.  The file on System disk #2 is
for dBASE III PLUS single-user systems.  The file on System disk #1 is for
dBASE III PLUS Administrator.  


>>> ID.EXE

When terminate-and-stay-resident (TSR) programs are loaded and ID.EXE is
run, a Ctrl-C may be required at the "Check over your responses. Would you
like to re-edit them? (Y/N)." prompt.  In one instance, the order in which
the TSR programs were loaded affected the outcome of ID.EXE TSR programs
should be removed from memory before running ID.EXE


>>> IIF()

dBASE III PLUS parses the entire IIF() statement before executing the
function.  If either parameter of the IIF() function is erroneous, then the
entire function returns an error.  For example,

  mem = "dBASE"
  ? IIF(.T., mem, SUBSTR(mem, 10, 3))

returns the error message "***Execution error on SUBSTR() : Start point out
of range" even though the false condition is never executed.  The IIF()
function requires that each argument be a valid expression.

This is true for versions 1.0 and 1.1 of dBASE III PLUS.


>>> IMPORT

IMPORTing a PFS file from a drive other than the default creates the  new
.DBF, .FMT, and  .VUE files on the drive containing the PFS file, not the
default drive.  This occurs in  versions 1.0 and 1.1 of dBASE III PLUS.


>>> INDEXing Street Addresses

If you have a name and address database file, you might need to INDEX your
database file in street order.  The basic requirement is to create an index
file that keeps all like streets together, and orders the addresses by
numeric value within each street.  The reason for this is that INDEXing ON
the street alone will not give you a very meaningful order.  An additional
requirement is to assign all blank and "P.O. Box" addresses a value that
groups them at the top or bottom of the index so that you can easily skip
over them.

The following commands use IIF() in combination with other string functions
to create an index key that will produce an index file in street order. 
When you use these commands, enter the assignments to the memory variables
"ae" and "af" first, and then enter the INDEX command on one continuous
command line. As you type the INDEX command line, be sure to ignore
embedded blanks and semicolons within the INDEX expression to keep the
expression length less than the 220-character limit that dBASE III PLUS
imposes.

  * ---INDEXing street names.
  ae = [SUBSTR(Street, 1, AT(" ",Street) - 1)]
  af = [SUBSTR(Street, AT(" ",Street) + 1, 5)]
  INDEX ON IIF(     "BOX"  $ &ae.;
               .OR. "P.O." $ &ae.;
               .OR. LEN(TRIM(Street)) = 0,;
               " ",;
               &af. + RIGHT(STR(100000 + VAL(&ae),6),5);
           );
        TO Address


>>> INDEX File Size

To calculate the size of a dBASE III PLUS index file created with INDEX or
REINDEX, use the following program, Ndxsize.PRG.  The variable, keyexplen,
refers to the length of the index file's key expression and must be
provided. Keyexplen is 8 when using numeric or date type keys and is
rounded up to the nearest multiple of four on character type keys.  To
execute Ndxsize, use the following general syntax:

  USE <your database file>
  klen    = <length of index key>
  ret_val = 0
  DO Ndxsize WITH klen, ret_val

  * Program ...: Ndxsize.PRG
  * Author ....: Paul Redmond
  * Date ......: January 1, 1987
  * Note(s) ...: Calculates the optimal size of an index file after
  *              an INDEX or REINDEX.
  *
  PARAMETERS keyexplen, answer
  PRIVATE ALL
  blkkeycnt = INT(504 / (keyexplen + 8))
  blkleft   = RECCOUNT() / blkkeycnt
  blkcnt    = blkleft + 2
  blkkeycnt = blkkeycnt + 1
  DO WHILE blkleft > blkkeycnt
     blkleft = INT((blkleft - 1) / blkkeycnt) + 1
     blkcnt  = blkcnt + blkleft
  ENDDO
  answer = blkcnt * 512
  * EOP Ndxsize.PRG

Note that the size of the index file changes if an APPEND is used with an
indexed database file.  INDEX and REINDEX optimize the index file; this
formula approximates the optimum index file size.  This algorithm is
relevant to both versions 1.0 and 1.1 of dBASE III PLUS.


>>> INKEY()

The list of alternate keys on pages U6-29 [Original] and U6-41 [Revised
6/86] is incomplete. Alternate keys not documented are:


  Special Key       Alternate Key
  -------------------------------
  Rightarrow      | Alt-<4>
  Leftarrow       | Alt-R
  Uparrow         | Alt-<5>
  Dnarrow         | Alt-O
  Ctrl-Rightarrow | Alt-<2>
  Ins             | Alt-U
  Del             | Alt-<7>
  Home            | Alt-<1>
  End             | Alt-<6>
  PgDn            | Ctrl-@, Alt-<3>
  Ctrl-End        | Alt-I
  Esc             | Ctrl-[
  Ctrl-PgUp       | Alt-S
  Ctrl-PgDn       | Alt-A
  F1              | Ctrl-\

Numbers enclosed in <> denote keys on the numeric keypad only.  All keys
can be duplicated by entering their ASCII key codes on the numeric keypad
while holding down the Alt key.

Though this list is included in the documentation under INKEY(), the
alternate keys are applicable throughout dBASE III PLUS.  For example, in
BROWSE Ctrl-\ toggles the cursor control keys menu instead of invoking
HELP, as F1 does.

Ctrl-Q is incorrectly documented as the alternate key for Esc; Ctrl-[ is
the alternate key for Esc.  In data-entry screens Ctrl-Q and Esc act the
same in that they both abort the entry screen without writing the changes. 
However, during LIST or DISPLAY Ctrl-Q resumes scrolling after Ctrl-S has
paused the output. Esc aborts the operation entirely.  INKEY() returns 27
for Esc and Ctrl-[, while Ctrl-Q returns 17.


>>> INKEY()

1. The INKEY() function in the Developer's Release and dBASE III PLUS seems
to return the wrong answer after a WAIT command has been executed.  For
example,

   WAIT
   i = INKEY()
   ? i

The memory variable "i" will always contain the value zero no matter what
key was last pressed.  The reason for this is that WAIT pauses and waits
for a key value from the keyboard or type-ahead buffer.  Once the key is
sensed, it is taken from the buffer.  The INKEY() function also looks at
this buffer for a key, but finds that the last key has been taken by the
WAIT command and so returns a zero value.

The correct method to poll the keyboard for a key press is to use either
the WAIT command or the INKEY() function but not both in combination.  For
example,             

  * ---Use the WAIT command.              
  WAIT TO choice
  DO CASE                 
     CASE choice = 19                        
        ...
     CASE choice = 27                        
        ...             
  ENDCASE
  
  ---Use the INKEY() function.                  
  key = INKEY()
  DO WHILE key = 0                        
     key = INKEY()           
  ENDDO
  DO CASE                 
     CASE key = 19                   
        ...             
     CASE key = 27                    
        ...             
  ENDCASE

2. The following program can be used to help you determine the key code for
   each key pressed.

  SET ESCAPE OFF                  
  SET TALK OFF            
  esc = 27
  DO WHILE .T.                    
     key = INKEY()
     DO WHILE key = 0                                
        key = INKEY()
     ENDDO                   
     ? key                   
     IF key = esc
        EXIT                    
     ENDIF           
  ENDDO           
  SET TALK ON
  SET ESCAPE ON           
  RETURN


>>> INKEY()

INKEY() returns the following codes for function keys:

  Key          Normal   Ctrl      Alt
  ===============================
   F1    28              94             104
   F2    -1              95             105
   F3    -2              96             106
   F4    -3              97             107
   F5    -4              98             108
   F6    -5              99             109
   F7    -6             100             110
   F8    -7             101             111
   F9    -8             102             112
   F10           -9             103             113



>>> INPUT

The INPUT command behaves differently in different versions of dBASE III.
In versions 1.0 and 1.1, it accepts a carriage return as a valid response
and does not create a variable. If one exists, it is left intact.  Control
is then returned to the calling program or the dot prompt.  In the
Developer's Release and dBASE III PLUS, however, INPUT does not accept a
carriage return as a valid response.  It scrolls the screen up one line and
awaits valid input each time a carriage return is entered and control is
not returned to the calling program or dot prompt until a valid input is
accepted.


>>> INSTALL.BAT

The files required to run dBASE III PLUS version 1.1 are not
documented.  They are:

     DBASE.EXE
     DBASE.OVL
     DBASEINL.OVL
     DBASE.MSG
     CONFIG.SYS    (In the root directory of the boot disk.)

Additional files needed by dBASE III PLUS (version 1.1) to
function fully but not required to load are:

     HELP.DBS
     ASSIST.HLP
     CONFIG.DB


>>> Interactive Mode

In dBASE III PLUS, you cannot continue command lines issued at the dot
prompt with a semicolon.  Previous versions supported this feature.

To continue a line beyond the width of the screen keep typing and the
command will scroll left.  In dBASE III PLUS, the command line is an
editable 254 character, single line, horizontal scroll space.  All keys
that are valid in full-screen modes are valid at command line.


>>> Justifying and Centering Strings

BY CHUCK LITZELL

Frequently, there is a  need to center or right justify a message on the
screen or in a report. The usual method is to add to the left of the string
the number of spaces required to offset the message to the desired
position. The dBASE III PLUS code to accomplish this is short, though
somewhat complicated owing to the mathematics involved.

Use this expression to center a string:

   string = IIF(width > LEN(string),;
        SPACE((width - LEN(string)) / 2),;
        "") + string

To right justify a string, use

   string = IIF(width > LEN(string),;
        SPACE(width - LEN(string)),;
        "") + string`

Often, reports and screen displays have headings that include a
left-justified string, a centered string, and a right-justified string.
Title.PRG (Figure 1) is a procedure that builds such a heading. The three
strings are passed as parameters, along with the width of the desired
heading. The resulting string is returned in the first parameter.

    * Program ...: Title.PRG
    * Versions ..: dBASE III PLUS v1.0, 1.1
    * Note(s) ...: Generates a report or screen title line with text
    *              left justified, centered and right justified.
    *              The result is returned in the first parameter, ltext.
    *
    *              The calling program must ensure that the width 
    *              specified is sufficient to contain the three 
    *              strings without overlap.  No error will result 
    *              if there is overlap, but the result string will be
    *              erroneous.
    *
    *              Example:
    *                 pagen  = 1
    *                 header = DTOC(DATE())
    *                 DO Title WITH header, "Employee Master Report",;
    *                               "Page " + LTRIM(STR(pagen)), 80
    *                 @ 1, 0 SAY header
    *
    PARAMETERS ltext, ctext, rtext, width
    *
    *          ltext  ::=  text to be left justified.
    *          ctext  ::=  text to be centered.
    *          rtext  ::=  text to be right justified.
    *          width  ::=  width of output string.
    *
      tmpstr = RIGHT(SPACE(width) + TRIM(rtext), width)
      tmpstr = STUFF(tmpstr, (width - LEN(TRIM(RTRIM(ctext)))) / 2,;
               LEN(TRIM(RTRIM(ctext))), TRIM(RTRIM(ctext)))
      ltext  = STUFF(tmpstr, 1, LEN(TRIM(RTRIM(ltext))), TRIM(RTRIM(ltext)))
      RETURN
    * EOP Title.PRG




>>> LIST

The LIST command is designed to display "Record in use by another" if a
record is locked by a different workstation with RLOCK().  This performs
according to expectation unless record number 1 is locked with RLOCK(), in
which case blank data is displayed for the record.

There is no work-around for this situation.


>>> LIST PROCEDURE

Often, when you are modifying an existing application where you have merged
a number of command files into a procedure file, you may want to get a list
of procedures.  You can do this easily using the DOS utility, FIND.EXE. 
FIND is a very fast, free text-search program that searches for a specified
string anywhere in a file, returning the lines where the search argument is
found. Optionally, FIND will return line numbers as well.  Unfortunately,
searches are case-sensitive and case is not a configurable option.  You
can, however, use this to your advantage by making the use of the command
verb PROCEDURE always uppercase and any other uses in comments and in the
SET and CLOSE PROCEDURE commands some combination of case and word length
to make the PROCEDURE declaration unique.

To list procedures from the DOS prompt use the following command line,

  FIND "PROCEDURE" <procedure file name>

You can, off course, RUN this command line from within dBASE III PLUS or
you can create a command file that calls FIND and constructs the FIND
command like the following,

  PROCEDURE Proc_file
  RUN FIND "PROCEDURE" &Proc_file..PRG
  RETURN

If you want to include line numbers in the listing add /N to the FIND
command line.


>>> LOAD

The explanation of "Table is full" (Using, pages 5-121 and 8-15) states
that you have attempted  to LOAD more than five files.  It actually occurs
if you try to LOAD more than 16 files.  Five  files was the limitation of
the Developer's Release.  This is corrected in the second edition of  the
documentation. 


>>> LOCATE/CONTINUE

To use CONTINUE, a search or scope condition must be specified in the
preceding LOCATE command, although a LOCATE without a FOR or WHILE
condition does not cause an error and positions the record pointer at the
top of the file.  However, following that LOCATE with CONTINUE returns the
error message "CONTINUE without LOCATE".

ASSIST does not prevent users from selecting Continue in this way.  In
ASSIST, executing Position:Locate with no condition positions the record
pointer at the top of the file and activates Position:Continue.  Choosing
Position:Continue returns the error message "CONTINUE without LOCATE."

This occurs in versions 1.0 and 1.1 of dBASE III PLUS.


>>> LOOP

The command verb LOOP does not appear in the second edition documentation
index. An explanation of LOOP can be found on page U5-114 under the DO
WHILE command.



>>> MENUBAR.BIN

The documentation for MENUBAR.BIN in the dBASE Programmer's Utilities
states that the  light bar can be moved within the menu with the eight
cursor-movement keys and that  Return and Esc are used to select items from
the menu.  However, it is not documented that  the cursor-movement keys can
be used to select items, as well as navigate through the menu.   When Ctrl
is used in conjunction with a cursor key, the item under the cursor is
selected  and the menu is exited without moving the cursor.  These keys and
their functions are  shown in Table 2. The key code returned by MENUBAR
corresponds to the INKEY() key  codes.

  Extension   Description       Commands
  
  BAK         Backup            MODIFY COMMAND
                                MODIFY STRUCTURE
  CAT         Catalog           CREATE CATALOG
                                SET CATALOG TO
  DBF         Database file     COPY STRUCTURE TO
                                COPY TO
                                COPY...STRUCTURE EXTENDED
                                CREATE
                                CREATE FROM
                                IMPORT
                                JOIN
                                TOTAL
                                SORT
  DBT         Memo field file   CREATE
                                MODIFY STRUCTURE
                                COPY TO
  DIF         VisiCalc file     COPY TO...TYPE DIF
  FMT         Format file       CREATE SCREEN
                                IMPORT
  FRM         Report design 
              file              CREATE REPORT
  LBL         Label design file CREATE LABEL
  MEM         Memory variable 
              file              SAVE
  NDX         Index file        INDEX
  PRG         Program, 
              procedure         MODIFY COMMAND
  QRY         Query file        CREATE QUERY
  SCR         Screen design 
              file              CREATE SCREEN
  TBK         Memo file backup  MODIFY STRUCTURE
  TXT         Text file         COPY TO...TYPE DELIMITED
                                COPY TO...TYPE SDF
                                CREATE SCREEN (text image)
                                SET ALTERNATE
                                <Command> TO FILE
  WKS         Lotus 1-2-3 file  COPY TO...TYPE WKS
  VUE         View file         CREATE VIEW
                                IMPORT


>>> MODIFY STRUCTURE

1. MODIFY STRUCTURE generates the error "NET 803: Network path not found"
if the database file is in the root directory of any physical drive or
logical drive.  Even if network drive F: is attached to the subdirectory
\DBASE on the file server, it is still belongs to the logical root
directory of drive F:.  The work-around is to move the file to a
subdirectory or

                COPY TO Temp
                MODIFY STRUCTURE

After receiving the "NET 803" error message, the user must press A to
abort.  The database file structure will have been modified but zero
records will remain in file, then

                APPEND FROM Temp

2. MODIFY STRUCTURE generates the error "File is already open" if the
database structure contains a memo field and there are no records in the
file.

The work-around is to add one blank record to file.


>>> Precedence of File Attributes

Page 3-24 of the Networking section of the dBASE III PLUS Reference Manual
states that "File and field privileges can be used to override the file
access read/write attribute established at the operating system or network
shell level."  This is incorrect.  Attributes of directories and files
established at the network level always have precedence over the dBASE
Administrator Protect mechanism.


>>> Printing

dBASE III PLUS handles printing differently from earlier versions of dBASE
III.  Earlier versions of dBASE III relied on DOS to handle printer status
errors.  All error messages were generated and handled by DOS.  dBASE III
PLUS uses a different DOS call to send characters to the printer port. 
This new routine is faster but also returns a printer port time-out error
quicker. dBASE III PLUS checks the port status at initialization; errors
occurring after initialization are handled by DOS.  Because of these
differences, it is possible to get error messages in dBASE III PLUS when
none would not occur in dBASE III.  The differences are:

1. When the print device is activated, dBASE III PLUS checks the printer
port for two specific conditions: "Invalid printer port" and "Printer is
either not connected or turned off."  If neither condition is true but an
error is still detected, dBASE III PLUS defaults to the "Printer not ready"
error message.  For example, on a parallel printer, pin 12 is used to
signal a "paper out" condition.  If pin 12 is missing or broken on a cable,
dBASE III PLUS checks the status of the printer port, finds an error
condition that does not meet one of the two specific conditions that are
tested, and returns the default error message, "Printer not ready."
"Invalid printer port" occurs when redirecting the printer to an invalid
port, such as LPT4.

"Printer is either not connected or turned off" may occur when redirecting
the printer to a valid COM port and attempting to print when that port does
not have a printer attached to it.

2. Because different DOS versions have different time-out intervals for the
printer port, some DOS versions time out while waiting for the print buffer
to empty.  This will generate the DOS error message "Printer not ready.
Retry? (Y/N)."  This situation can be corrected by issuing the DOS command

   MODE LPT1:,,P

The "P" parameter at the end of the command line above instructs DOS to
infinitely retry the printer port.  This prevents the port from timing
out.  Error conditions (such as paper out or printer not connected) may
appear to hang the machine while DOS infinitely retries the port.  Unless
the error condition is resolved, a warm boot is required to terminate the
process.


>>> READKEY()

If you terminate a full-screen operation in dBASE III PLUS with a Ctrl-W or
Ctrl-End, READKEY() always returns 270, regardless of whether the contents
were altered or not.  In the Developer's Release, READKEY() returned a
value of 14 if the field or variable was not changed.  Additionally,
READKEY() always returns a value of 12 when you terminate a full-screen
operation with Esc or Ctrl-Q.


>>> RENAME

The RENAME command can move files between directories on the same disk
drive.  When the new filename includes a path different from the original
filename, RENAME moves the file to the directory specified by the new
path.  For example,

     RENAME \DBASE\Test.TXT TO \DOS\Test.TXT

Test.TXT is moved from \DBASE to \DOS, provided that the directory \DOS
exists on the same disk drive.  When renaming a file in a directory other
than the default, the path of the destination filename is required.  If the
destination path is ignored, dBASE III PLUS moves the file to the default
directory.  When the destination drive is different from the source drive,
dBASE III PLUS returns the error message "File already exists." [7].

This is inconsistent with DOS, which renames files without moving them. The
error message "Invalid parameter" is produced when a destination path is
included in the DOS RENAME command.


>>> REPLACE

REPLACEing a field of a database file from another work area when the
record pointer is at  EOF() increments the record counter and appends a
record to the file when the record  pointer is moved to the new record. 
For example,

  USE Test1
  GO BOTTOM
  SKIP               && Sets EOF() true.
  SELECT B
  USE Test2
  REPLACE Test1->Name WITH "XXXX"
  SELECT A
  GO RECNO()

adds a new record to Test1 and the contents of Name are "XXXX".  

Issuing multiple REPLACEs to a database file when EOF() is true increments
the record  counter for each REPLACE executed; however, data is added to
the current record only.  Do  not trust this method for appending records. 
This process occurs because the record counter is  increased; but, the
original data on the disk is not erased in the fields REPLACEd.  This 
means that the information on the disk in the region of the new record
becomes part of  that record.  When the data on the disk is from a
previously DELETEd and PACKed record,  the new record is marked for
deletion.  Other characters such as nulls and end-of-file  markers can
become embedded in the record.  This will corrupt the database file and
cause  unpredictable results.  

When  the field REPLACEd is an index key field, the results are slightly
different.   Performing a SEEK or FIND on the new expression returns the
error message "No find"  until REINDEX is issued.

Multiple REPLACEs to the EOF() add only the last expression REPLACEd after
REINDEX is  issued, all other data is lost.  DISPLAY STRUCTURE, GO BOTTOM,
and RECCOUNT() reveal  a record count consistent with the number of
REPLACEs executed.  COUNT displays the  number of records added previously
to the REPLACE command until REINDEX is issued.   Attempting to GO/GOTO the
new records produces the error message "Record is out of  range" [5].  SKIP
moves the record pointer through these records as if they were available.  
To reset the database file record count after multiple REPLACEs, issue
PACK.  This occurs in  both versions of dBASE III PLUS.

  Key           Function
  
  Return        Select the item under the light bar.
  Esc           Select the item under the light bar.
  Home          Move the light bar to the first column, first row.
  PgUp          Move the light bar to the first column, last row.
  End           Move the light bar to the last column, first row.
  PgDn          Move the light bar to the last column, last row.
  Ctrl-Home     Select the item under the light bar.
  Ctrl-PgUp     Select the item under the light bar.
  Ctrl-End      Select the item under the light bar.
  Ctrl-PgDn     Select the item under the light bar.


>>> REPLACE

In addition to the ability to change the contents of fields in work areas
other than the currently selected one by creating a global field pool with
SET FIELDS TO <field list> and then REPLACEing into the remote area, you
can also REPLACE into the remote area by specifying the alias before the
target field name.  For example,

   * ---REPLACE with SET FIELDS.
   SELECT 1
   USE Fileone
   SELECT 2
   USE Filetwo
   SET FIELDS TO Fileone->Fieldone, Fieldtwo
   REPLACE Fieldone WITH Fieldtwo

   * ---REPLACE without a fields list.
   SELECT 1
   USE Fileone
   SELECT 2
   USE Filetwo
   REPLACE Fileone->Fieldone WITH Fieldtwo


>>> REPLICATE()

Once the error message "Execution error on REPLICATE(): String too large."
[88] is produced, it does not reoccur until a valid numeric expression is
included in REPLICATE(). For example,

   * ---The next line produces the error.
   mvar = REPLICATE("A",32766)   
   * ---In the next line no error is produced.
   mvar = REPLICATE("A",32767)    
   mvar = REPLICATE("A",10)
   * ---The next line produces the error.
   mvar = REPLICATE("A",32767)   

The result of REPLICATE() is a null string whenever the second argument is
too large, regardless of whether an error message is returned. This is true
of versions 1.0 and 1.1 of dBASE III PLUS.



>>> REPORT FORM

CREATE REPORT Options:Double space report causes double spacing between
records only. All other portions of the REPORT FORM, including wrapped
fields, are single spaced. This is true of both versions of dBASE III PLUS.




>>> REPORT FORM

In both versions 1.0 and 1.1 of dBASE III PLUS, the width of a REPORT FORM
total is determined by the value of Contents:Column width.  There are
several conditions to consider:

1. With a total width greater than the Contents:Column width, the decimal
portion of the total is truncated to accommodate the integer portion.  

2. When the integer portion of the total exceeds the Contents:Column width,
the total displays in scientific notation.  

3. If the value of the total is greater than 9E+98, an overflow displays.


>>> REPORT FORM (Memo Fields)

If you plan to print a memo field from another work area in a REPORT FORM,
including the alias as a part of the memo field name will not display the
memo field information when you execute the REPORT FORM.  You must instead
include a SET FIELDS TO command before you CREATE REPORT and not include
the memo field alias name in Columns:Field contents.  If you select the
memo field from the field list displayed by F10, delete the automatically
inserted alias before you exit the Column:Fields contents.

When you are ready to run your report, be sure to SET FIELDS TO the list of
fields you are using first or you will get the error message "Syntax error
in field expression" when you execute the REPORT FORM.  

In the following exmaple, Test1.DBF contains the memo field Notes. 

   * ---CREATE a REPORT to printing memo fields from a
   * ---nonactive work area. 
   SELECT 2
   USE Test1 INDEX Test1
   SELECT 1
   USE Test2
   SET FIELDS TO Name, Address, Test1->Notes
   CREATE REPORT Test1

In Columns:Field contents enter Notes and do not include the alias name.  

This situation occurs in both versions of dBASE III PLUS.


>>> REPORT FORM PLAIN

The following are some undocumented notes on REPORT FORM PLAIN.  These
situations arise in both versions 1.0 and 1.1 of dBASE III PLUS.

1. Selecting PLAIN always reserves the first two lines of the first page of
the report for a heading, even when the headings are blank.

2. Setting the Options:Lines per page equal to the printer form length
causes alternate blank pages to be printed when the report is run.  This
happens because a form feed, CHR(12), is printed at the end of each page. 
When Options:Lines per page equals the form length, the CHR(12) is printed
at the top of each new page causing a blank to be printed between printed
pages. 

3. Setting Options:Lines per page equal to one less than the form length
prints a blank row between pages.  This occurs because the CHR(12) is
printed at the beginning of the last line on a page, skipping that line.  

>>> REPORT FORM TO PRINT

To imbed printer control characters in Options:Page title, Group: headings,
or Column:Heading, enter the control characters from the numeric keypad
with an Alt-<key sequence> and add 128 to the ASCII value.  The high order
value is necessary as dBASE III PLUS filters low value ASCII characters as
control keys.  

This procedure works only on printers that can strip off the eighth data
bit with the printer set to strip off the eighth bit.  Stripping off the
eighth bit causes characters whose ASCII values are greater than 127 to be
interpreted as 128 less than their actual value.

To enter an Alt-<key sequence>, hold down Alt and enter the ASCII decimal
value of the control code on the numeric keypad.  For example, to enter
CHR(15), enter Alt-143 (15 + 128 = 143).  This works in both versions of
dBASE III PLUS.


>>> RETURN

With the ON ESCAPE active, pressing Esc at a WAIT, INPUT, or ACCEPT command
causes the program to resume at the line following the WAIT, INPUT, or
ACCEPT command with no error messages.

In version 1.0, pressing Esc in response to an INPUT statement with SET
ESCAPE OFF hangs the system, while an Esc at a WAIT statement returns to
the dot prompt.



>>> RESTORE

The dBASE III Reference Manual for all versions incorrectly states about
the RESTORE command that any memory variables STOREd as PUBLIC remain
PUBLIC if the ADDITIVE option is used.  The ADDITIVE option to RESTORE will
allow the user to RESTORE variables as PUBLIC only if they are declared
PUBLIC before the RESTORE FROM <Filename> ADDITIVE command is issued.  If
the variables are not explicitly declared PUBLIC, they will be RESTOREd as
PRIVATE variables, regardless of their status when STOREd and SAVEd.  For
example,

   PUBLIC one, two
   STORE 1 TO one, two
   SAVE TO Mem
   CLEAR ALL
   RESTORE FROM Mem ADDITIVE  <-- Variables are RESTOREd
                                  without being redeclared PUBLIC.

will create PRIVATE variables "one" and "two," while,

   PUBLIC one, two
   STORE 1 TO one, two
   SAVE TO Mem
   CLEAR ALL
   PUBLIC one, two            <-- Variable is redeclared PUBLIC.
   RESTORE FROM Mem ADDITIVE

creates PUBLIC variables "one" and "two."


>>> RUN / !

RUN / ! produces the error message "Insufficient memory" [43] if the
maximum number of  files (15) are open.  To use RUN / !, a file handle must
be available.  However, when  ADDFILES.BIN from the dBASE Programmers
Utilities is loaded and used to open the  maximum 20 files, RUN / !
executes without error.  This is true for every version of dBASE  III PLUS.



>>> Scientific Notation

dBASE III PLUS has a limited ability to handle scientific notation.
Scientific notation is a number followed by the letter "e" followed by an
integer, where the integer is a power of ten that is multiplied by the
first number.  For example,

  1e4  = 1 * 10^4  = 10000
  -1e4 = -1 * 10^4 = -10000

dBASE III PLUS can use this notation for variable initialization, field
entry, APPENDing from text files, and in all numeric expressions.

Variable initialization: The command

    mem = 1e4

or

    mem1 = "1e4"       mem  = VAL(mem1)

stores 10000 to memory variable "mem."

Field entry: The command

       REPLACE <field name> WITH 1e4

stores 10000 to <field name>.

APPENDing FROM text files: If an SDF text file contains the number 1e4,
APPENDing it into a database file puts 1e4 into a numeric field--not 10000
as might be expected.  Numeric expressions involving this field generate
valid answers.  This method is the only one you can use because scientific
notation cannot be entered during full-screen editing.  To convert fields
in scientific notation to decimal, use this command syntax:

  REPLACE ALL <field name> WITH <field name>

dBASE III PLUS has a numeric accuracy of 15.9 digits, 13 digits when
comparing non-zero numbers.  Operations that exceed the accuracy may
produce the error message "Numeric overflow (data was lost)."

Numeric expressions:

 ? 1e4 * 3

  displays 30000.


>>> Converting Numbers to Scientific Notation

Although dBASE III PLUS allows you to convert numbers from scientific
notation to numbers in {decimal} notation (See...), it does not allow you
convert decimal notation to scientific notation.  The following programs,
Sci.PRG, converts numbers in decimal format to scientific notation.

To use Sci.PRG, call it with the following general syntax:

  ret_val = ""
  DO Sci WITH <number>, <decimals>, ret_val

where the arguments are defined as follows:

  number   ::= integer to be converted
  decimals ::= number of decimal places
  ret_val  ::= character variable to accept return value

Also included is a sample program, SciTest.PRG, that demonstrates how to
use Sci.PRG to list a set of numbers from a database file in scientific
notation.



  * Program ...: Sci.PRG
  * Author ....: Kenneth N. Getz
  * Date ......: March 1, 1987
  * Version ...: dBASE III PLUS
  * Note(s) ...: Converts x to scientific notation correct to decimal number
  *                                       of decimal places.  Works for any positive number within
  *                                       dBASE III PLUS limits.
  *
  PRIVATE ALL
  PARAMETERS x, dec, ret_val
  y = LOG(ABS(x)) / LOG(10)                               && Find order of magnitude.
  y = IIF(INT(y) = y, INT(y) + 1, INT(y))
  y = IIF(ABS(x) < 1,y - 1,y)
  z = x / 10^y                                                            && Normalize the number (0 < z < 10).
  order = 10^dec                                                          && Find order of rounding accuracy.
  fudge = IIF(x < 0, -.5, .5)
  q = INT( z * order + fudge)/order
  ret_val = LTRIM(STR(q,15,dec)) + "E" + IIF(ABS(x) < 1,"-","+") +
  LTRIM(STR(ABS(y)))
  RETURN
  * EOP Sci.PRG



  * Program ...: SciTest.PRG
  * Author ....: Kenneth N. Getz
  * Date ......: March 1, 1987
  * Version ...: dBASE III PLUS
  * Note(s) ...: A test program for Sci.PRG.  Uses the database SciTest.DBF
  *
  PRIVATE ALL
  PARAMETERS decimals
  STORE SPACE(30) TO ret_val
  USE Scitest
  DO WHILE .NOT. EOF()
          ? num
          DO Sci WITH num, decimals, ret_val
          ?? IIF(num < 0, SPACE(10), SPACE(11)) + ret_val
          SKIP
  ENDDO
  RETURN
  * EOP SciTest.PRG


>>> Semicolon

In dBASE III PLUS, you cannot continue commands issued at the dot prompt
with a semicolon.  The dBASE III PLUS command line is a 254-character
horizontal scroll space.  Previous versions of dBASE III allowed you to
continue a dot prompt command line with a semicolon.


>>> SET ALTERNATE TO

You can use the following program, Cpsep.PRG to COPY a database file to a
flat ASCII file with no separators between either fields or records.  Such
a file differs from the SDF format in that each record is not separated
with a carriage return/line feed pair.

  * Program ...: Cpsep.PRG
  * Author ....: Quinn Wildman
  * Date ......: January 1, 1987
  * Note(s) ...: Creates a text file image of a database file with
  *              no record separators.
  *
  SET TALK ON
  ACCEPT "Enter name of text file: " TO txtfile
  ACCEPT "Enter name of database file: " TO dbfile
  USE &dbfile
  SET ALTERNATE TO &txtfile
  SET ALTERNATE ON
  DO WHILE .NOT. EOF()
     cnt = 1
     DO WHILE LEN( FIELD( cnt )) <> 0
        macro = FIELD( cnt )
        ?? &macro
        cnt = cnt + 1
     ENDDO
     SKIP
  ENDDO
  SET ALTERNATE OFF
  CLOSE ALTERNATE
  CLEAR ALL
  SET TALK ON
  * EOP Cpsep.PRG

>>> SET CATALOG ON

If you assign an ALIAS when you USE a database file, the catalog does not
store the ALIAS but instead stores the filename as the ALIAS.  For example,

    SET CATALOG TO <filename>
    USE Test1 ALIAS Testfile
    SELECT 10
    LIST
       ^------ This show the ALIAS as "Test1,"
               not "Testfile."


>>> SET CATALOG ON

With an active Catalog and SET CATALOG ON, creating a new index or issuing
SET INDEX TO an existing index file does not prompt for a file title
description as documented in the Using dBASE III PLUS manual.  Instead,
dBASE III PLUS places the index key expression in the Catalog field Title.


>>> SET CATALOG TO ?

Attempting to open a catalog file that has the same name as an open
database file or assigned alias name produces the error message "ALIAS name
already in use." [24].  To avoid the error message, assign a different
alias to the database file or close the database file before executing SET
CATALOG TO.  For example,


     USE Test
     SET CATALOG TO Test


produces the error message.  This occurs in both versions 1.0 and 1.1 of
dBASE III PLUS. 


>>> SET COLOR

The SET COLOR TO command changed somewhat in the Developer's Release and
dBASE III PLUS.  Formerly, colors could be referenced by number or letter
code.  With the Developer's Release and dBASE III PLUS, only letter codes
are accepted. Additionally, there are several new options.  Black can now
be referenced with the letter code N, inverse video with the letter code I,
and the screen can be blanked with the code X.  The following table shows
all the default color attributes for dBASE III from version 1.0 through
dBASE III PLUS.

Color Attribute Table
 
                                           Developer's Release
                    dBASE III              dBASE III PLUS
  Color             Letter   Number        Letter Only
  
  Black             <space>    0      |    N or <space> 
  Blue              B          1      |    B 
  Green             G          2      |    G 
  Cyan              BG         3      |    BG 
  Red               R          4      |    R 
  Magenta           BR         5      |    BR 
  Brown             GR         6      |    GR 
  White             W or RB    7      |    W or RB
  
  Other
  
  Blank                               |    X 
  Blinking          *                 |    * 
  High intensity    +                 |    + 
  Inverse video                       |    I 
  Underline         U                 |    U

Three other capabilities are added to color in dBASE III PLUS. First, there
is a new function, ISCOLOR(), that returns a true value (.T.), if your
monitor is in color mode.  Second, SET COLOR supports a toggle syntax,
ON/OFF, to toggle your monitor between color and monochrome modes, if your
machine supports both. Lastly, a background option is added for machines
that cannot set the background of individual characters with the standard
and enhanced options.


>>> SET COLOR TO

It is not documented that the U and I arguments of SET COLOR TO, which are
for monochrome monitors, set the color to black when used on a color
monitor. For example, on a color monitor

   SET COLOR TO U/I

is equivalent to 

   SET COLOR TO N/N



>>> SET COLOR TO

Using an attribute (high intensity or blinking) of colors with SET COLOR TO
applies to the foreground setting only and has no effect on background
colors.  In fact, if you assign an attribute to a background color, dBASE
III PLUS passes the attribute to the foreground color instead.  Because of
this, the colors gray (N+) and yellow (GR+) appear as black and brown
respectively when used for background settings.  

Keep in mind that for color settings there are three basic settings
(display, enhanced, and border) and that within each one there are both
foreground and background colors.

   SET COLOR TO [[<standard>][,<enhanced>][,<border>]]

where 

   standard  ::= [<foreground>][/<background>]
   enhanced  ::= [<foreground>][/<background>]
   border    ::= [<foreground>][/<background>]
    and

   foreground ::= [<letter>[{attribute}]]
   background ::= <letter>
    It appears that the attribute although it affects the color is a
function of the setting.  Each setting, therefore, can have only one
attribute which is applied to the foreground color.  This behavior is in
contrast to dBASE III version 1.0 and 1.1, where attempting to assign an
attribute to a background color did not pass the attribute to the
foreground color. 


>>> SET DATE FRENCH

The format of date variable display varies between versions 1.1 and the
Developer's Release and dBASE III PLUS, when SET DATE is FRENCH.  For
example,

                       dBASE III         Developer's Release
                       Version 1.1       dBASE III PLUS

     SET DATE FRENCH    DD.MM.YY          DD/MM/YY

The Developer's Release and the dBASE III PLUS displays are identical to
SET DATE BRITISH.


>>> SET DELETED ON

SET DELETED ON can affect the FIND command when there is more than one
record in the database file with the same index key.  For example, suppose
there are two "Johnsons" in the database file.  The first is marked for
deletion and the second is locked with RLOCK() at a different workstation. 
If SET DELETED is ON, and you try to FIND "Johnson", you will get the
message "No find" instead of the expected "Record is in use by another." 
Under any other circumstance, a FIND on a record locked with RLOCK()
returns the message "Record is in use by another" and positions the record
pointer to that record.

There is no work-around at this time.


>>> SET ESCAPE OFF

Esc terminates an active READ regardless of the status of SET ESCAPE in
both versions of dBASE III PLUS.

Documentation Index

The index for the second edition of the documentation contains incorrect
page references. The specific references are shown in Figure 2.

   Item                               Incorrect           Correct
   --------------------------------------------------------------
   Function keys (Page X-17)          U5-224 - U5-225     U5-234
   Memo field (Page X-20)
        adjusting width for output    U5-234              U5-243
        editing in programs           P5-16               P5-26


>>> SET FIELDS TO

Issuing the SET FIELDS TO <Field list> command automatically SETs FIELDS
ON, regardless of the FIELDS status prior to issuing the SET FIELDS TO
command.

The dBASE III PLUS Reference Manual states on page 5-169 of the Using
section, under the SET FIELDS TO command, "The list of fields is not active
unless the SET FIELDS command is ON."  This statement implies that the
command SET FIELDS ON must be executed explicitly to activate the current
field list after creating it.  Anytime the command SET FIELDS is executed
either to create a fields list or to add to one, FIELDS are SET ON.


>>> SET FILTER TO

It is not documented in any of the dBASE III PLUS reference manuals that
certain commands ignore the SET FILTER TO condition.  Specifically, the
commands DISPLAY (current record), DISPLAY RECORD <n>, GO/GOTO, or any
command with the scope RECORD <n> or NEXT <n>.  For example, if the SET
FILTER TO condition excludes record five and GOTO 5 is executed, a
subsequent DISPLAY reveals the contents of the record.


>>> SET HISTORY OFF

Page U5-180 of the original documentation incorrectly states, "The command
SET HISTORY OFF disables the history feature so that prior commands can't
be recalled."  Page U5-237 of the revised documentation incorrectly states,
"The command SET HISTORY OFF clears the history buffer."

The command SET HISTORY OFF suppresses the storage of commands into the
history buffer.  Commands entered in HISTORY prior to SET HISTORY OFF may
still be displayed, edited, and re-executed.  To clear the history buffer
of commands, SET HISTORY TO 0.


>>> SET ORDER TO

You must reposition the record pointer after executing SET ORDER TO in
dBASE III PLUS.  The easiest way to do this is to issue the command:

   GO RECNO()

This will cause the record pointer to reposition itself to the current
record position updating the internal record pointer.  If, however, EOF()
returns true (.T.), this won't work.  In this case, use the following
command:

   GO IIF(EOF(), RECCOUNT(), RECNO())


>>> SET PATH TO

The original documentation does not include the path length limitations for
the SET PATH TO command.  The path is limited to 60 characters.  Exceeding
that limit will produce the error message "Maximum path length exceeded"
[146].


>>> SET PROCEDURE TO

Beginning in Developer's Release, you can have a command file that SETs
PROCEDURE to itself, effectively allowing you to create single file
applications such as those you could create with dBCODEing and dBLINKing.

Additionally, you can CLOSE the PROCEDURE within the calling program.  Be
sure, however, you do not CLOSE PROCEDURE within any of the procedures or
dBASE III PLUS will return the error message "File is already open."

For example,

  * ---Sayhello.PRG
  SET PROCEDURE TO Sayhello                    && SETs PROCEDURE TO itself.
  DO Proc1
  DO Proc2
  CLOSE PROCEDURE
  RETURN

  PROCEDURE Proc1
  ? "Hi there, I'm procedure number One and I love black beans."
  RETURN

  PROCEDURE Proc2
  ? "Howdy, I'm procedure number Two and I'm a Taurus."
  RETURN
  * EOP Sayhello.PRG

In dBASE III version 1.1, doing this returned the error message "File is
already open."


>>> SET RELATION TO

The description of "Cyclic relation" under Error Messages contains the line
"SET  RELATION, without any parameters, disconnects all relations from the
currently selected  work area."  But SET RELATION with no arguments
produces a "Syntax error."  The proper  command is SET RELATION TO with no
argument.  This is corrected in the second edition  of the documentation.


>>> SET RELATION TO

Throughout the documentation for dBASE III PLUS, there is some ambiguity
about the various ways you can link database files with SET RELATION TO.

SET RELATION TO relates two database files in three different ways.

1. You can relate two database files with a key expression allowing you to
create connections between database files based on value.  It is important
to stress that you are not confined to a single common field.  The linking
expression can be any legitimate dBASE III PLUS expression.  To work, the
key expression must return a value from the source work area that matches a
value in the master index file of the target work area.  Because the
relation is created by an expression, you can take two dissimilar database
file structures that contain common values and create a relation between
them.  In exactly the same way, you can create a relation between database
files that have common fields.  In both cases, the mechanism is the same:
the relation is created by an expression.

2. Another way to relate database files is by record number.  This type of
relation allows you to link two database files having no common field
values but have a one-to-one relation based on physical position.  Record
one in the source corresponds to record one in the target file and so on.
Generally, you will use this formulation to create a virtual database file
where you need a number of fields greater than the dBASE III PLUS limit of
128 per database file.

When the record pointer moves in the source database file, the record
pointer in the target moves to the same record number as the source
record.  For example,

        * ---Setup and syntax with a physical relation.
        SELECT B
        USE File2
        SELECT A
        USE File1 INDEX File1
        SET RELATION TO RECNO() INTO File2
        * ---List records from File1 and File2.
        DO WHILE .NOT. EOF()
                ? Field1, Field2, File2->Field1, File2->Field2
                * ---Advance File1 and File2 pointer.
                SKIP
        ENDDO

        * ---Setup and syntax with no relation.
        SELECT B
        USE File2
        SELECT A
        USE File1 INDEX File1
        * ---List records from File1 and File2.
        DO WHILE .NOT. EOF()
                ? Field1, Field2, File2->Field1, File2->Field2
                * ---Advance the File1 pointer.
                SKIP
                * ---Advance the File2 pointer.
                recpos = RECNO()
                SELECT B
                GO recpos
                SELECT A
        ENDDO

In order to build various index sort orders, put all of your key fields in
the master database file as the diagram below indicates.  This is important
since a relation based on RECNO() precludes the use of an index file in the
target work area.

                Master -----> Sub1 ------> Sub2                 (Keys)
 (Non-keys)   (Non-keys)

3. The last type of relation is a physical link between database files
based on a numeric expression.     If the linking expression evaluates to
numeric and the target database file is not INDEXed, then the target record
pointer moves to the record number returned by the linking expression each
time the source database file pointer moves.

For example, the following linking expression relates two unINDEXed
database files so each pair of adjacent records in the source database file
points to a single record in the target file.

   IIF(MOD(RECNO(),2)=1,INT(RECNO()/2)+1,INT(RECNO()/2))

Record numbers one and two in the source point to record number one in the
target, three and four in the source point to two in the target, and so on.

This type of relation can be used to build virtual data structures based on
a link that is a combination of value and physical location.

In general, it is important to your mastery of dBASE to understand the
truly dynamic nature of relating database files with SET RELATION TO.

For more information on SET RELATION TO, refer to the page D3-11 of the
April 1985 issue of TechNotes.


>>> SET RELATION TO

In versions 1.0 and 1.1 of dBASE III, a relation could be released with the
command SET RELATION.  In the Developer's Release and dBASE III PLUS, this
command returns a syntax error although it releases the RELATION.  The
proper and supported command syntax to release a relation is SET RELATION
TO.


>>> SET SCOREBOARD/SET STATUS

The SET SCOREBOARD ON/OFF and SET STATUS ON/OFF commands will clear the
entire screen when issued in dBASE III PLUS.  In previous versions, SET
SCOREBOARD ON/OFF would affect only the SCOREBOARD area of the screen.


>>> SET VIEW TO

If any change has been made to any of the component parts of a view,
invoking that view file with SET VIEW TO will return an error message.  The
specific message will depend on the error in the view file.

For example, if the name of field in the fields of the view has been
changed by MODIFYing the STRUCTURE of one of the constituent database
files, issuing the SET VIEW TO command will return "Variable not found."
Once this condition has occurred, there is no way to open the view file and
modify it, as MODIFY VIEW will return the same error message.  The file
must be deleted and re-created, or the environment must be made consistent
with the view file once more.


>>> STORE

Attempting to STORE a string containing "&&" to a memory variable produces
the error message "Unterminated string" when executed.  This is because the
double ampersands are interpreted as an in-line comment, effectively
removing the closing quotation mark from the command line.  To work around
this, split the character expression between the ampersands into two
expressions and concatenate them when assigning them to the memory
variable.  For example, the following is a successful instance of embedding
"&&" in a string.

   STORE "Before the &" + "& and after." TO mvar


>>> Tandy printers

Some older Tandy printers do not recognize CHR(12) as a form feed
character.  To correct  this problem, install the device driver LPDRVR.SYS
in CONFIG.SYS.  LPDRVR.SYS is  provided with Tandy DOS 3.x.  LPDRVR.SYS
keeps track of the number of carriage  return/line feeds sent to the
printer.  When a form feed is transmitted, LPDRVR.SYS  sends the remaining
number of carriage return/line feeds necessary to reach the top of the 
next page.  To install LPDRVR.SYS, add the following line to CONFIG.SYS:
DEVICE = LPDRVR.SYS

If LPDRVR.SYS is not available, it may be obtained from Tandy.  The phone
number for  hardware support is (817)338-2394 and the phone number for
software support: (817)338-2390  and (817)338-2392 or leave a message at
their main switchboard, (817)390-3011.


>>> TRANSFORM()

In both versions 1.0 and 1.1 of dBASE III PLUS, including a  TRANSFORM()
expression with a PICTURE function in the CREATE REPORT Columns:Contents
may require resetting Contents:Width to a value greater than the default. 
When the expression to be TRANSFORMed is numeric, using the default
Contents:Width of 10 forces the displays to wrap to a second line. 
Increasing the Contents:Width corrects the problem.  

The following is a list of functions and the corresponding minimum values:

   Function				            Width
   -----------------------------------------------
   TRANSFORM(<field name>, "@C")		  16
   TRANSFORM(<field name>, "@X")		  16
   TRANSFORM(<field name>, "@(")		  15
   TRANSFORM(<field name>, "@Z")		  13
   TRANSFORM(<field name>, "@B")	LEN(<field name>)


>>> Trapping the Esc Key

In dBASE III PLUS, version 1.1, SET ESCAPE OFF is ignored by the WAIT,
INPUT, and ACCEPT commands. If the user presses Esc in response to any of
these commands, dBASE III PLUS responds with the "Cancel, Ignore, or
Suspend?" message, and the user can cancel the application program.

The work-around is to add an ON ESCAPE command to the application:

   ON ESCAPE DO Esc_back

Esc_back.PRG needs just one line:



>>> UNINSTAL.BAT

UNINSTAL.BAT deletes CONFIG.SYS, if it exists, in the target drive default
directory.  This is potentially dangerous if the default directory of the
target disk is the root directory.  Some systems, such as older Bernoulli
drives, require CONFIG.SYS to boot.  Use caution when uninstalling dBASE
III PLUS from a root directory.

>>> UPDATE

If you are trying to UPDATE one database file from another and the relation
between them is many-to-one, you may have found that the UPDATE command
does not support this formulation.  The UPDATE command only updates the
first instance in the target database file.  This means that the UPDATE
command is useful only when the relation between the source and the target
database files is one-to-one.  To update your many-instance file from the
single-instance file, use the REPLACE command in combination with SET
RELATION.  For example,

   SELECT 2
   USE <source> INDEX <source index>
   SELECT 1
   USE <target> INDEX <target index>
   SET RELATION TO <key> INTO <source>
   REPLACE ALL <target field1> WITH <source>-><field1>,;
                        <target field2> WITH <source>-><field2>,;
                        <target field3> WITH <source>-><field3>
 

>>> USE

If byte 15 of a .DBF file header contains a value other than a null, USEing
the file in dBASE III PLUS produces the error message "Database is
encrypted."  This byte is used by the dBASE Administrator to mark a file as
encrypted.  Earlier versions of dBASE III ignored this byte.  If you
encounter this error message when USEing a database file in single-user
mode, run NEWHEAD.BAS or use DEBUG to change the byte back to a null.  Note
that in order to use DEBUG, your database file must be smaller in size than
the amount of free memory available prior to running DEBUG.


