        The CBIN package is a small collection of BIN routines that
can be LOADed and CALLed by dBase III Plus.  They also work with
FoxBase+.  The name "CBIN" comes from the fact that the routines are
written, not in assembler as in usual for BIN routines, but in the C
programming language.  Russell Freeland modified the start-up code
for Wizard C to work with dBase; Andrew Schulman wrote much of the
C code.

        Whereas large packages such as dBase Tools for C or Tom
Rettig's Library require that you load (and learn!) a large software
package simply in order to perform a few functions, the CBIN routines
operate independently of one another.  Learn and load the ones you
need, and you don't have to bother with a 100K memory-resident
program hogging your PC's memory.
        
        For more information, contact either:

        Andrew Schulman						Russell Freeland                
        12 Humboldt Street					1780 SW 43                      
        Cambridge MA 02140					Fort Lauderdale FL 33064        

		We would appreciate hearing from you:  bug reports would be
particularly appreciated right now.  Also, suggestions for other BIN
routines that you would find useful in your everyday work.  Finally,
any monetary contribution you could make would be appreciated.  We have
big plans for more CBIN utilities, so it's worth your while to become
a CBIN supporter.

        In the following descriptions of the BIN routines, note that
all BINs must be LOADed into dBase III Plus before they can be
CALLed.  You can do a RELEASE MODULE when you are done with it.

        Also note that some of the BIN files have to be called twice:
once to "seed" them with necessary information they need, and again
to get back the information you need.  




        WRITE: Write characters to file or to printer (even chr(0))
        -----

Setup:      F = "<filename> <mode>[+]"
            CALL WRITE WITH F
            
            <filename> : any valid DOS filename or PRN: (for printer)
            <mode> : x (for hexadecimal)
                     d (for decimal)
            [+] : optional + sign indicates append to file, not overwrite

Return from setup:  
            if F = "-1" then file could not be opened; otherwise F will
            contain DOS file handle, e.g., "04"

Use (after setup):
            CALL WRITE WITH "<bytes...>"
            
            <bytes>: if hexadecimal mode was selected, hex designation
                     for characters; if decimal mode was selected, chr()
                     designation.
                     Multiple occurrences of characters are designated
                     with (bytes,number), where number will always be a
                     decimal count.
					 Strings (cannot include spaces) are delimited with 
					 apostrophes:  'hello'
                     (See examples below)

Close file:
            CALL WRITE WITH "(!)"

Examples:
            To create a DBF file without using CREATE (more useful
DBF files can then be constructed using COPY TO STRUCTURE EXTENDED
and CREATE FROM commands):

            LOAD WRITE
            F = "FOO.DBF X"
            CALL WRITE WITH F           && open the file
            IF (F <> "-1")              && check if okay
                * write characters out to file
                CALL WRITE WITH "3 (0,7) 41 0 4f (0,21) 46 (4f,2) (0,8)"
                CALL WRITE WITH "43 (0,4) 4e (0,15) d 1a"
            ENDIF
            CALL WRITE WITH "(!)"       && close the file
			USE FOO						&& do something with it
            
            Note that even though FOO.DBF was opened in hex mode,
(0,21) writes 21 copies of chr(0) out to the file, not 33.  In hex
mode, only the characters themselves are in hex; counts are always in
decimal.  
            
            To set an Epson printer to italic, print the word "Hello" and
return to roman (does not work in FoxBase+):
            
            CALL WRITE WITH "PRN: X"
            CALL WRITE WITH "1b '4' 'Hello' 1b '5' (!)"


        READ:  Read a character from a file
        ----

Setup:          F = "<filename>"
                CALL READ WITH F

                <filename>:  : any valid DOS filename

No value returned by setup.

To call (after setup):
                C = SPACE(1)
                CALL READ WITH C

Return from call:
                The next available character in file is returned in
                passed variable.  If end-of-file is reached, or otherwise
                character can not be retrieved, chr(255) is returned.
                
Close file:     CALL READ WITH CHR(255)
    
Problems:       That READ is not parallel to WRITE is clearly a problem.
                This will be fixed in future versions.  This version simply
                illustrates that you can have relatively fast character-at-a-
                time access to files from within dBase.  Future versions
                will let you access multiple characters at a time, and will
                allow you to retrieve the next word from a file (similar to
                the C function strtok()).

Examples:       
                * TESTREAD.PRG
                PARAMETER FILE
                LOAD READ
                CALL READ WITH "&FILE"			&& open the file
                ? UPPER(FILE)
                ?
				C = SPACE(1)
                DO WHILE (C <> CHR(255))		&& while not end-of-file
                    CALL READ WITH C			&& get a char into C
                    ?? C						&& display it
                ENDDO
                CALL READ WITH CHR(255)			&& close the file

				DO TESTREAD WITH "CBIN.TXT"		&& display this file
                
                This example merely displays a file on the screen.
Presumably you would want to do something with the characters inside the
do-while loop, other than just display them.


        PEEK:  Examine PC memory
        ----

To call:        M = "<segment> <offset> [count]"
                CALL PEEK WITH M

                <segment>:<offset> : address
                [count] : optional number of bytes to retrieve

Return from call:
                After calling PEEK, M will contain the contents of
                PC memory address segment:offset.  The number of bytes
                depends retrieved depends on the optional [count]
                parameter AND ON THE LENGTH OF THE STRING PASSED IN.
                
                Note that the information retrieved overwrites the
                information passed in.  It is assumed that the information
                passed in is needed by the routine, not by the user.  

Problems and Comments:
                PEEK is very limited right now, as you need routines
                to retrieve valid addresses for you that can then be
                passed to PEEK.  PEEK should have a "mode" in which the
                information retrieved for you is returned in a form
                that can then be passed back to PEEK.  Any decent book
                on BASIC gives many illustrations of the wonderful
                non-portable tricks that can be done with a properly-
                written PEEK.
				Valid dBase addresses can be retrieved with VARPTR.
				(See below)

Example:
                M = "68c1 d 11"			
                CALL PEEK WITH M
                ? M
                "Hello world"


        POKE : Fondle PC memory
        ----

To call:        CALL POKE WITH "<segment> <offset> <bytes...> [switch]"

                <segment>:<offset> : address
                <bytes...> : arbitrary number of bytes
                [switch] : optional:  -d means that <bytes...> are in
                    decimal, -a means ascii, default is hex.
                (See examples)
                
No value returned by call.

Problems and Comments:
                POKE suffers from the same problems as PEEK.
                Also note that PEEK and READ should be very similar
                in operation; and that POKE and WRITE should match
                each other as well.

Example:        The following examples all POKE "Hello" into the
                same address in memory:

                CALL POKE WITH "68c1 d 48 65 6c 6c 6e"
                CALL POKE WITH "68C1 000D H E L L O -A"
                CALL POKE WITH "68c1 000d 72 101 108 108 111 -d"
                
                Note that even when the <bytes...> are in decimal, addresses
                are always in hexadecimal.  This is the convention in
                addressing memory.


        VARPTR -- Take address of dBase variable
        ------
        
Setup:              X = <dBase memvar>
                    CALL VARPTR WITH X

No value returned by setup.

To use:             Y = <storage for return value>
                    CALL VARPTR WITH Y

Notes:				The segment returned is dBase's data segment.  
					The dBase III Plus memvar symbol table can be found
					near <segment>:0004 (however, this is not the case
					in FoxBase+).

Example:
                    X = "Hello world"
                    CALL VARPTR WITH X
                    Y = SPACE(10)
                    CALL VARPTR WITH Y
                    ? Y
                    68c1 d

                    Y = y + " 11" + SPACE(5)
                    CALL PEEK WITH Y
                    ? Y
                    Hello world



		INTER -- do DOS or BIOS interrupt from dBase (yow!)
        ----- 
        
To use:				Using this one is complex enough that a dBase PRG
					front end, INTER.PRG, has been provided.  If you
					want to call INTER.BIN directly, see how INTER.PRG
					is coded.  Otherwise, just call INTER.PRG or include
					it in your standard procedure file.  The syntax for
					call INTER.PRG is:

					DO INTER WITH INTNO,AX,BX,CX,DX

Note:				Remember that if one of the "high" registers must be
					loaded (for instance, BH), the value must be multiplied
					by 256.  See the sample program, TESTINT.PRG

Return:				See the sample program, TESTINT.PRG
					



		BEEP -- Sound the PC speaker
        ---- 
        
To use:				CALL BEEP WITH <pitch>,<duration>

Notes:				See the sample program, BACH.PRG, for an example
					of how to call beep.  The Bach transcription into
					computer gibberish comes, more or less, from the
					Framework II Developer's Toolkit.  The BEEP routines
					were derived from routines published in the February
					1987 PC TECH JOURNAL with important corrections in
					the July 1987 letters column.



		RAND -- Generate pseudorandom number
        ---- 

Setup:				X = <dBase NUMERIC memory variable>
					CALL RAND WITH X

To use:				X = <dBase NUMERIC memory variable>
					CALL RAND WITH X

Notes:				Unlike the other BIN routines, RAND takes and
					returns a single dBase numeric memory variable,
					and NOT its string representation.

Example:
					. load rand
					. seed = val(substr(time(),7,2))
					. call rand with seed
					. x = 0
					. call rand with x
					. ? x
						   346
					. call rand with x
					. ? x
						   130
					. call rand with x
					. ? x
						 10982
					. call rand with x
					. ? x
						  1090



		FILEFIND -- Wildcard searches for files, directories
        -------- 
        
Setup:				F = "(!)<pattern> <attribute> <extra space>"
					CALL FILEFIND WITH F

To use:				F = "<enough space to hold file name>"
					CALL FILEFIND WITH F

Notes:				Each time you call FILEFIND, it will retrieve
					the next DOS file matching the pattern with which
					you "seeded" it.  To tell FILEFIND you're starting
					"seeding" a new pattern, preface with pattern with
					"(!)".
					The attributes are passed as string representations
					of the following numbers:
					0 - normal files
					1 - read-only files
					2 - hidden files
					4 - system files
					8 - volume label
					16 - directory
					32 - archive

Example:			F = "\*.* 16" + SPACE(15)
					CALL FILEFIND WITH F
					DO WHILE (F <> "-1")		&& until the well runs dry...
						? F
						F = SPACE(15)
						CALL FILEFIND WITH F
					ENDDO

					This finds all directories and normal files off
					the main root.

					F = "(!)" + "*.BIN" + STR(0) + SPACE(15)
					DO WHILE (F <> "-1")
						? F
						F = SPACE(15)
						CALL FILEFIND WITH F
					ENDDO

					Can you figure out what this does?



	SRCHPATH -- Search DOS path for file
	--------

	See Russell's SRCHPATH.PRG, and all will be revealed unto you.


								-- Andrew Schulman
								   6 July 1987

P.S.  Again the authors of CBIN implore you to send feedback
	  and/or contributions.



					


        
