home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Boston 2
/
boston-2.iso
/
DOS
/
PROGRAM
/
CLIPPER
/
NFTROFF
/
3.TR
< prev
next >
Wrap
Text File
|
1993-12-01
|
32KB
|
1,833 lines
.de }n
.bp
.sp .5i
..
.wh -.8i }n
.sp .5i
.po -.4i
.ll 7.5i
.ps 9
.vs 9
.in 0i
.ta 1.63265i
.sp 2
.ne 20
.ps +3
.vs +3
FT_CHDIR() Change the current directory
.br
.ta
.in 0.08i
.ps -3
.vs -3
.sp 2
\fBFT_CHDIR()
Change the current directory
.in 0i
.br
\l'6.24i'
.br
.sp
.in 0.08i
\fBSyntax
.sp
.in 0.4i
\fBFT_CHDIR( <cDirName> ) -> nResult
.sp
.in 0.08i
\fBArguments
.sp
.in 0.4i
\fB<cDirName>\fR is the name of the desired directory\.
.sp
.in 0.08i
\fBReturns
.sp
.in 0.4i
.ta 0.24i
0 if successful
.br
.ta
.ta 0.24i
3 if path not found
.br
.ta
99 if invalid parameters passed
.sp
.in 0.08i
\fBDescription
.sp
.in 0.4i
Use this function if you prefer to change the active directory
instead of relying on the SET PATH command\.
.sp
The source code is written to adhere to Turbo Assembler\'s IDEAL mode\.
To use another assembler, you will need to rearrange the PROC and
SEGMENT directives, and also the ENDP and ENDS directives (a very
minor task)\.
.sp
.in 0.08i
\fBExamples
.sp
.in 0.4i
.br
FT_CHDIR( "C:\\CLIPPER" )
.br
FT_CHDIR( "\\" )
.br
FT_CHDIR( "\.\.\\SOURCE" )
.sp
.in 0.08i
\fBSource:\fR CHDIR\.ASM
.sp
\fBAuthor:\fR Ted Means
.in 0i
.ta 1.63265i
.sp 2
.ne 20
.ps +3
.vs +3
FT_DEFAULT() Retrieve and optionally change the current default drive
.br
.ta
.in 0.08i
.ps -3
.vs -3
.sp 2
\fBFT_DEFAULT()
Retrieve and optionally change the current default drive
.in 0i
.br
\l'6.24i'
.br
.sp
.in 0.08i
\fBSyntax
.sp
.in 0.4i
\fBFT_DEFAULT( [ <cDrive> ] ) -> cDrive
.sp
.in 0.08i
\fBArguments
.sp
.in 0.4i
\fB<cDrive>\fR is optional, and if specified is the new default drive\.
.sp
.in 0.08i
\fBReturns
.sp
.in 0.4i
The current default drive\. If a change of default drive is requested,
the return value is the drive AFTER the change is made\. This allows
you to make sure you specified a valid drive (i\.e\. if you attempt to
change the default drive, and the function returns a different drive
letter than the one you specified, then the drive does not exist)\.
.sp
.in 0.08i
\fBDescription
.sp
.in 0.4i
Useful any time you need to know or change the default drive\.
.sp
The source code is written to adhere to Turbo Assembler\'s IDEAL mode\.
To use another assembler, you will need to rearrange the PROC and
SEGMENT directives, and also the ENDP and ENDS directives (a very
minor task)\.
.sp
.in 0.08i
\fBExamples
.sp
.in 0.4i
.ta 1.92i
cDrive := FT_DEFAULT() && Get the current drive
.br
.ta
.ta 1.92i
FT_DEFAULT("C") && Switch to drive C
.br
.ta
.sp
IF FT_DEFAULT("E") != "E"
.in 0.64i
Qout( "Drive E does not exist!" )
.in 0.4i
ENDIF
.sp
.in 0.08i
\fBSource:\fR DEFAULT\.ASM
.sp
\fBAuthor:\fR Ted Means
.in 0i
.ta 1.63265i
.sp 2
.ne 20
.ps +3
.vs +3
FT_DOSVER Return the current DOS major and minor version as a string
.br
.ta
.in 0.08i
.ps -3
.vs -3
.sp 2
\fBFT_DOSVER
Return the current DOS major and minor version as a string
.in 0i
.br
\l'6.24i'
.br
.sp
.in 0.08i
\fBSyntax
.sp
.in 0.4i
\fBFT_DOSVER() -> <cVersion>
.sp
.in 0.08i
\fBArguments
.sp
.in 0.4i
None
.sp
.in 0.08i
\fBReturns
.sp
.in 0.4i
A character string with the major version number first, a
period ("\."), then the minor version number (e\.g\., "3\.30")
.sp
.in 0.08i
\fBDescription
.sp
.sp
.in 0.4i
FT_DOSVER() invokes DOS interrupt 21h, service 30 in order to
return the current DOS version\. It does this by setting up
an array corresponding to machine registers and then calling
the toolkit function FT_INT86()\.
.sp
It returns a character string corresponding to the DOS
version, as follows: The major version, a period ("\."), then
the minor version\.
.sp
.sp
.sp
.in 0.08i
\fBExamples
.sp
.sp
.in 0.48i
.br
FUNCTION main()
.br
RETURN QOut( "Dos version: " + FT_DOSVER() )
.sp
.sp
.in 0.08i
\fBSource:\fR DOSVER\.PRG
.sp
\fBAuthor:\fR Glenn Scott
.in 0i
.ta 1.63265i
.sp 2
.ne 20
.ps +3
.vs +3
FT_DSKFREE() Return the amount of available disk space
.br
.ta
.in 0.08i
.ps -3
.vs -3
.sp 2
\fBFT_DSKFREE()
Return the amount of available disk space
.in 0i
.br
\l'6.24i'
.br
.sp
.in 0.08i
\fBSyntax
.sp
.in 0.4i
\fBFT_DSKFREE( [ <cDrive> ] ) -> nSpaceAvail
.sp
.in 0.08i
\fBArguments
.sp
.in 0.4i
\fB<cDrive>\fR is the fixed disk to query\. If no parameter is passed
the operation will be performed on the default drive\. Do not
include the ":"\.
.sp
.in 0.08i
\fBReturns
.sp
.in 0.4i
Integer representing the available disk space in bytes\.
.sp
.in 0.08i
\fBDescription
.sp
.in 0.4i
Function to return the available space on the passed
drive letter or the default drive if no drive is passed\.
.sp
Uses FT_INT86() through the internal function _ftDiskInfo()\.
.sp
.in 0.08i
\fBExamples
.sp
.in 0.4i
.ta 1.28i
? FT_DSKFREE() // Returns free space on default drive\.
.br
.ta
.sp
.in 0.08i
\fBSource:\fR DISKFUNC\.PRG
.sp
\fBAuthor:\fR Robert A\. DiFalco
.in 0i
.ta 1.63265i
.sp 2
.ne 20
.ps +3
.vs +3
FT_DSKSIZE() Return the maximum capacity of a fixed disk
.br
.ta
.in 0.08i
.ps -3
.vs -3
.sp 2
\fBFT_DSKSIZE()
Return the maximum capacity of a fixed disk
.in 0i
.br
\l'6.24i'
.br
.sp
.in 0.08i
\fBSyntax
.sp
.in 0.4i
\fBFT_DSKSIZE( [ <cDrive> ] ) -> nMaxCapacity
.sp
.in 0.08i
\fBArguments
.sp
.in 0.4i
\fB<cDrive>\fR is the fixed disk to query\. If no drive is sent, the
operation will be performed on the default drive\. Send without
the ":"\.
.sp
.in 0.08i
\fBReturns
.sp
.in 0.4i
An integer representing the maximum disk capacity in bytes\.
.sp
.in 0.08i
\fBDescription
.sp
.in 0.4i
Function utilizing FT_INT86() to return Maximum Disk Size\.
Uses FT_INT86() through the internal function _ftDiskInfo()\.
.sp
.in 0.08i
\fBExamples
.sp
.in 0.4i
.ta 1.6i
.br
? FT_DSKSIZE() // Maximum capacity for default drive
.br
.ta
.br
? FT_DSKSIZE( "D" ) // Maximum capacity for Drive D:
.sp
.in 0.08i
\fBSource:\fR DISKFUNC\.PRG
.sp
\fBAuthor:\fR Robert A\. DiFalco
.in 0i
.ta 1.63265i
.sp 2
.ne 20
.ps +3
.vs +3
FT_FLOPTST() Test diskette drive status
.br
.ta
.in 0.08i
.ps -3
.vs -3
.sp 2
\fBFT_FLOPTST()
Test diskette drive status
.in 0i
.br
\l'6.24i'
.br
.sp
.in 0.08i
\fBSyntax
.sp
.in 0.48i
\fBFT_FLOPTST( <nDrive> ) -> nStatus
.sp
.in 0.08i
\fBArguments
.sp
.in 0.48i
\fB<nDrive>\fR is the diskette drive number, 0 = A:, 1 = B:
.sp
.in 0.08i
\fBReturns
.sp
.in 0.48i
.br
-1 - Wrong Parameters
.in 0.56i
.br
0 - Drive Loaded and ready to read or write
.br
1 - Drive Door Open or Diskette inserted upside down
.br
2 - Diskette is unformatted
.br
3 - Write protected
.br
4 - Undetermined
.sp
.in 0.08i
\fBDescription
.sp
.in 0.48i
FT_FLOPTST() is designed as a full replacement for ISDRIVE()\. Where
ISDRIVE() returns just \.T\. or \.F\. depending if the diskette drive is
ready or not, FT_FLOPTST() returns a numeric code designating the
diskette drive\'s status\.
.sp
FT_FLOPTST() is particularly useful in backup and restore programs
that need to test the floppy drive before writing/reading from a
floppy disk\.
.sp
.in 0.08i
\fBExamples
.sp
.in 0.48i
.br
iStatus := FT_FLOPTST( 1 )
.sp
.br
DO CASE
.in 0.72i
.br
CASE iStatus == 1
.in 0.96i
.br
Qout( "The door to drive A is open\." )
.in 0.72i
.br
CASE iStatus == 2
.in 0.96i
.br
Qout( "The diskette in drive A is not formatted\." )
.in 0.72i
.br
CASE iStatus == 3
.in 0.96i
.br
Qout( "The diskette in drive A is write-protected\." )
.in 0.72i
.br
CASE iStatus == 4
.in 0.96i
.br
Qout( "Something is wrong with drive A, but I don\'t know what\." )
.in 0.48i
.br
ENDCASE
.sp
.in 0.08i
\fBSource:\fR FLOPTST\.ASM
.sp
\fBAuthor:\fR Joseph LaCour
.in 0i
.ta 1.63265i
.sp 2
.ne 20
.ps +3
.vs +3
FT_HANDCNT() Count number of available DOS (not network) file handles
.br
.ta
.in 0.08i
.ps -3
.vs -3
.sp 2
\fBFT_HANDCNT()
Count number of available DOS (not network) file handles
.in 0i
.br
\l'6.24i'
.br
.sp
.in 0.08i
\fBSyntax
.sp
.in 0.32i
\fBFT_HANDCNT() -> nHandles
.sp
.in 0.08i
\fBArguments
.sp
.in 0.32i
None
.sp
.in 0.08i
\fBReturns
.sp
.in 0.32i
numeric, long integer
.sp
.in 0.08i
\fBDescription
.sp
.in 0.32i
FT_HANDCNT() finds the internal DOS Device Control Blocks used for
storing file information and counts the number of DCB entries\. The
DCB is set up by reading the FILES= line in CONFIG\.SYS, and there
is one DCB entry for each file handle\.
.sp
NOTE: For Novell networks, the number of network file handles is
.in 0.8i
controlled by SHELL\.CFG\. To date, I know where this information
is stored after SHELL\.CFG has been read, but have not come up
with a reliable way to retrieve the information\. There is no
public variable associated with the storage location, and the
location can change from version to version of NETx\.EXE\.
Novell Tech Support\'s response, though friendly, was "Nope, we
don\'t know of a way for you to do it, either\. Good luck\."
.sp
.in 0.08i
\fBExamples
.sp
.in 0.32i
.br
nHandles := FT_HANDCNT()
.br
? "This PC has " + LTRIM( STR( nHandles ) ) + " set by CONFIG\.SYS\."
.sp
.in 0.08i
\fBSource:\fR HANDCNT\.ASM
.sp
\fBAuthor:\fR Bob Clarke
.in 0i
.ta 1.63265i
.sp 2
.ne 20
.ps +3
.vs +3
FT_INP() Retrieve a byte from a specified I/O port
.br
.ta
.in 0.08i
.ps -3
.vs -3
.sp 2
\fBFT_INP()
Retrieve a byte from a specified I/O port
.in 0i
.br
\l'6.24i'
.br
.sp
.in 0.08i
\fBSyntax
.sp
.in 0.48i
\fBFT_INP( <nPort> ) -> nValue
.sp
.in 0.08i
\fBArguments
.sp
.in 0.4i
\fB<nPort>\fR is the port from which to retrieve the byte\. If it is
invalid in any way, the function will return zero\.
.sp
.in 0.08i
\fBReturns
.sp
.in 0.4i
The byte retrieved\.
.sp
.in 0.08i
\fBDescription
.sp
.in 0.4i
It may sometimes be useful to read a byte from a port without having
to resort to C or assembler\. This function allows you to do so\.
.sp
The source code is written to adhere to Turbo Assembler\'s IDEAL mode\.
To use another assembler, you will need to rearrange the PROC and
SEGMENT directives, and also the ENDP and ENDS directives (a very
minor task)\.
.sp
.in 0.08i
\fBExamples
.sp
.in 0.4i
.ta 1.92i
byte := FT_INP( 100 ) // read a byte from port 100 (064h)
.br
.ta
.sp
.in 0.08i
\fBSource:\fR INP\.ASM
.sp
\fBAuthor:\fR Ted Means
.in 0i
.sp
.in 1.5i
.ti -1.5i
.ta 1.5i
.ft B
See Also:
.ft R
FT_OUTP()
.ta 1.63265i
.in 0i
.sp 2
.ne 20
.ps +3
.vs +3
FT_INT86() Execute a software interrupt
.br
.ta
.in 0.08i
.ps -3
.vs -3
.sp 2
\fBFT_INT86()
Execute a software interrupt
.in 0i
.br
\l'6.24i'
.br
.sp
.in 0.08i
\fBSyntax
.sp
.in 0.48i
\fBFT_INT86( <nInterruptNumber>, <aRegisterValues> ) -> lResult
.sp
.in 0.08i
\fBArguments
.sp
.in 0.48i
\fB<nInterruptNumber>\fR is the interrupt to execute\.
.sp
\fB<aRegisterValues>\fR is an array that contains values to be loaded
into the various CPU registers\. The correspondence between
registers and array elements is as follows:
.sp
.in 1.2i
.ta 1.04i 1.36i
aElement[1] == AX register
.br
.ta
.ta 1.04i 1.36i
aElement[2] == BX register
.br
.ta
.ta 1.04i 1.36i
aElement[3] == CX register
.br
.ta
.ta 1.04i 1.36i
aElement[4] == DX register
.br
.ta
.ta 1.04i 1.36i
aElement[5] == SI register
.br
.ta
.ta 1.04i 1.36i
aElement[6] == DI register
.br
.ta
.ta 1.04i 1.36i
aElement[7] == BP register
.br
.ta
.ta 1.04i 1.36i
aElement[8] == DS register
.br
.ta
.ta 1.04i 1.36i
aElement[9] == ES register
.br
.ta
.ta 1.36i
aElement[10] == Flags register
.br
.ta
.sp
.in 0.08i
\fBReturns
.sp
.in 0.48i
\.T\. if all parameters valid and the function was able
.in 0.8i
to execute the desired interrupt\.
.in 0.48i
\.F\. if invalid parameters passed\.
.sp
.in 0.4i
In addition, the array elements will contain whatever values were in
the CPU registers immediately after the interrupt was executed\. If
either of the string parameters were altered by the interrupt, these
changes will be reflected as well\.
.sp
.in 0.08i
\fBDescription
.sp
.in 0.4i
It is occasionally useful to be able to call interrupts directly from
Clipper, without having to write a separate routine in C or ASM\. This
function allows you that capability\.
.sp
Given Clipper\'s high-level orientation, this function is necessarily
somewhat messy to use\. First, declare an array of ten elements to
hold the eight values for the CPU registers and two string parameters\.
Then initialize the array elements with the values that you want the
CPU registers to contain when the interrupt is executed\. You need not
initialize all the elements\. For example, if the interrupt requires
you to specify values for AX, DX, and DS, you would only need to
initialize elements 1, 4, and 8\.
.sp
Once you have done the required register setup, call FT_INT86(),
passing the interrupt number and the register array as parameters\.
The function will load the CPU with your specified values, execute the
interrupt, and then store the contents of the CPU registers back into
your array\. This will allow you to evaluate the results of the
interrupt\.
.sp
Some interrupt services require you to pass the address of a string in
a pair of registers\. This function is capable of handling these sorts
of situations, but it will take a little work on your part\. If you need
to pass a string that uses the DS register, store the string in element
.ta 0.32i
8; if you need to pass a string that uses the ES register, store the
.br
.ta
string in element 9\. FT_INT86() will detect that you\'ve supplied a
string instead of a numeric value and will behave accordingly\.
.sp
That takes care of obtaining the segment portion of the pointer\. To
specify which register is to contain the offset, use the values REG_DS
and REG_ES which are defined in the FTINT86\.CH file\. When one of these
values is found in an array element, it alerts FT_Int86() to use the
offset portion of a pointer instead of a numeric value\. REG_DS tells
FT_Int86() to use the offset of the string in element 8, while REG_ES
tells FT_Int86() to use the offset of the string in element 9\.
.sp
All the CPU registers are sixteen bits in size\. Some, however, are
also split into two 8-bit registers\. This function is only capable of
receiving and returning registers that are 16 bits in size\. To split
a 16-bit register into two 8-bit values, you can use the
pseudo-functions HighByte() and LowByte(), contained in the \.CH file\.
.sp
To alter an 8-bit number so it will appear in the high-order byte of a
register when passed to the FT_INT86() function, use the MakeHI()
pseudo-function contained in the \.CH file\.
.sp
This function is a shell for __ftint86(), which is written in assembler
and does the actual work of executing the interrupt\. __ftint86() is
callable from C, so feel free to incorporate it into any C routines
for which it might be useful\. The source for __ftint86() can be found
in the file AINT86\.ASM\.
.sp
.in 0.08i
\fBExamples
.sp
.sp
.in 0.4i
.br
* This example shows how to call the DOS "create file" service\. Take
.br
* special note of how to set up string parameters\.
.sp
.br
#include "FTINT86\.CH"
.sp
.ta 2.32i
.br
local aRegs[10] && Declare the register array
.br
.ta
.ta 2.32i
.br
aRegs[ AX ] := makehi(60) && DOS service, create file
.br
.ta
.ta 2.32i
.br
aRegs[ CX ] := 0 && Specify file attribute
.br
.ta
.sp
.br
* Pay attention here, this is crucial\. Note how to set up the string
.br
* so it appears in DS:DX\.
.sp
.br
aRegs[ DS ] := "C:\\MISC\\MYFILE\.XXX"
.br
aRegs[ DX ] := REG_DS
.ta 2.32i
.br
FT_INT86( 33, aRegs) && Make the call to the DOS interrupt
.br
.ta
.sp
.sp
.br
* This example shows how to call the DOS "get current directory"
.br
* service\. This one also uses a string parameter, but note that it
.br
* uses a different offset register\.
.sp
.br
#include "FTINT86\.CH"
.sp
.br
local aRegs[10]
.br
aRegs[ AX ] := makehi(71)
.ta 2.16i
.br
aRegs[ DX ] := 0 // Choose default drive
.br
.ta
.sp
.br
* This service requires a 64-byte buffer whose address is in DS:SI\. DOS
.br
* will fill the buffer with the current directory\.
.sp
.br
aRegs[ DS ] := space(64)
.br
aRegs[ SI ] := REG_DS
.br
FT_INT86( 33, aRegs)
.sp
.ta 1.6i
.br
? aRegs[ DS ] // Display the directory name
.br
.ta
.sp
.sp
.sp
.br
* For the sake of completeness, here\'s an example that doesn\'t use a
.br
* string\. This one changes the video mode\.
.sp
.br
#include "FTINT86\.CH"
.sp
.br
local aRegs[10]
.sp
.ta 2.16i
.br
aRegs[ AX ] := 16 && Choose hi-res graphics
.br
.ta
.br
FT_INT86( 16, aRegs)
.sp
.in 0.08i
\fBHeader File:\fR FTINT86\.CH
.sp
\fBSource:\fR CINT86\.C
.sp
\fBAuthor:\fR Ted Means
.in 0i
.ta 1.63265i
.sp 2
.ne 20
.ps +3
.vs +3
FT_ISPRINT() Check printer status
.br
.ta
.in 0.08i
.ps -3
.vs -3
.sp 2
\fBFT_ISPRINT()
Check printer status
.in 0i
.br
\l'6.24i'
.br
.sp
.in 0.08i
\fBSyntax
.sp
.in 0.4i
\fBFT_ISPRINT( [ <cDevice> ] ) -> lResult
.sp
.in 0.08i
\fBArguments
.sp
.in 0.4i
\fB<cDevice>\fR is optional and is the device to test (LPT2, COM1, etc\.)\.
If omitted, the function will default to the PRN device\.
.sp
.in 0.08i
\fBReturns
.sp
.in 0.4i
\.T\. if device is ready for output\.
\.F\. if one of the following conditions occurs:
.in 0.8i
.ta 0.32i
1) The device is not ready\.
.br
.ta
.ta 0.32i
2) The device does not exist\.
.br
.ta
.ta 0.32i
3) DOS couldn\'t open the device for some reason
.br
.ta
.in 1.12i
(such as no file handles available)\.
.sp
.in 0.08i
\fBDescription
.sp
.in 0.4i
The Clipper IsPrinter() function is somewhat limited because it only
works with LPT1\. Furthermore, it talks directly to the hardware, so
if you have redirected LPT1 via the DOS MODE command, the IsPrinter()
function will return erroneous results\.
.sp
This function offers a better alternative\. Instead of talking to the
hardware, it issues a DOS call that checks to see if the device is
ready or not\. That gives DOS an opportunity to deal with any
redirections, and since you pass the device name as a parameter, you
can test any device, not just LPT1 (note that the function defaults
to PRN if you fail to pass a valid parameter)\.
.sp
The function also temporarily traps the DOS critical error handler so
you don\'t get any nasty error messages if the device isn\'t ready\. It
restores the old critical error handler before exiting\.
.sp
Note that although this function is mainly designed for testing
printers, you can also check to see if a drive is ready\. Since DOS
thinks the NUL device exists on every drive, you can pass a drive
letter followed by NUL as a parameter\. If DOS is able to open the
NUL device, then the drive is ready, otherwise the door is open or
something else is wrong\.
.sp
The source code is written to adhere to Turbo Assembler\'s IDEAL mode\.
To use another assembler, you will need to rearrange the PROC and
SEGMENT directives, and also the ENDP and ENDS directives (a very
minor task)\.
.sp
.in 0.08i
\fBExamples
.sp
.in 0.4i
IF ! FT_ISPRINT()
.in 0.64i
Qout( "PRN is not ready!" )
.in 0.4i
ENDIF
.sp
IF ! FT_ISPRINT( "COM2" )
.in 0.64i
Qout( "Check the device on COM2\. Something is wrong\." )
.in 0.4i
ENDIF
.sp
IF ! FT_ISPRINT( "A:\\NUL" )
.in 0.64i
Qout( "Oops, better check drive A!" )
.in 0.4i
ENDIF
.sp
.in 0.08i
\fBSource:\fR ISPRINT\.ASM
.sp
\fBAuthor:\fR Ted Means
.in 0i
.ta 1.63265i
.sp 2
.ne 20
.ps +3
.vs +3
FT_ISSHARE() Determine if DOS "Share" is installed
.br
.ta
.in 0.08i
.ps -3
.vs -3
.sp 2
\fBFT_ISSHARE()
Determine if DOS "Share" is installed
.in 0i
.br
\l'6.24i'
.br
.sp
.in 0.08i
\fBSyntax
.sp
.in 0.48i
\fBFT_ISSHARE() -> nRetCode
.sp
.in 0.08i
\fBArguments
.sp
.in 0.48i
None
.sp
.in 0.08i
\fBReturns
.sp
.in 0.48i
nRetcode will be set as follows on exit:
.sp
.in 0.8i
0 if SHARE not loaded but ok to load
1 if SHARE not loaded and not ok to load
.in 0.64i
255 if SHARE loaded
.sp
.in 0.08i
\fBDescription
.sp
.in 0.48i
Uses DOS interrupt 2Fh (MultiPlex interrupt), service 10h
to determine if DOS SHARE\.COM is loaded\.
.sp
.in 0.08i
\fBExamples
.sp
.in 0.4i
IF FT_ISSHARE() != 255
.in 0.64i
Qout("SHARE must be loaded!")
.in 0.4i
ENDIF
.sp
.in 0.08i
\fBSource:\fR ISSHARE\.PRG
.sp
\fBAuthor:\fR Glenn Scott (from Tom Leylan C source)
.in 0i
.sp
.in 1.5i
.ti -1.5i
.ta 1.5i
.ft B
See Also:
.ft R
FT_INT86()
.ta 1.63265i
.in 0i
.sp 2
.ne 20
.ps +3
.vs +3
FT_MKDIR() Create a subdirectory
.br
.ta
.in 0.08i
.ps -3
.vs -3
.sp 2
\fBFT_MKDIR()
Create a subdirectory
.in 0i
.br
\l'6.24i'
.br
.sp
.in 0.08i
\fBSyntax
.sp
.in 0.4i
.ta 0.88i
\fBFT_MKDIR( <cDirName> ) -> nResult
.br
.ta
.sp
.in 0.08i
\fBArguments
.sp
.in 0.4i
\fB<cDirName>\fR is the name of the directory to create\.
.sp
.in 0.08i
\fBReturns
.sp
.in 0.48i
.ta 0.24i
0 if successful
.br
.ta
.ta 0.24i
3 if Path Not Found
.br
.ta
.ta 0.24i
5 if Access Denied or directory already exists
.br
.ta
.in 0.4i
.ta 0.32i
99 if invalid parameters passed
.br
.ta
.sp
.in 0.08i
\fBDescription
.sp
.in 0.4i
Use this function to create the subdirectories needed by your
application\. It might be especially useful in an installation
program\.
.sp
The source code is written to adhere to Turbo Assembler\'s IDEAL mode\.
To use another assembler, you will need to rearrange the PROC and
SEGMENT directives, and also the ENDP and ENDS directives (a very
minor task)\.
.sp
.in 0.08i
\fBExamples
.sp
.in 0.4i
.br
FT_MKDIR( "C:\\CLIPPER" )
.br
FT_MKDIR( "\\EXAMPLE" )
.br
FT_MKDIR( "\.\.\\SOURCE" )
.sp
.in 0.08i
\fBSource:\fR MKDIR\.ASM
.sp
\fBAuthor:\fR Ted Means
.in 0i
.ta 1.63265i
.sp 2
.ne 20
.ps +3
.vs +3
FT_OUTP() Write a byte to a specified I/O port
.br
.ta
.in 0.08i
.ps -3
.vs -3
.sp 2
\fBFT_OUTP()
Write a byte to a specified I/O port
.in 0i
.br
\l'6.24i'
.br
.sp
.in 0.08i
\fBSyntax
.sp
.in 0.4i
\fBFT_OUTP( <nPort>, <nValue> ) -> lResult
.sp
.in 0.08i
\fBArguments
.sp
.in 0.48i
\fB<nPort>\fR is the port from which to retrieve the byte\.
.sp
\fB<nValue>\fR is the value between 0 and 255 to write to the port\.
.sp
.in 0.08i
\fBReturns
.sp
.in 0.4i
\.T\. if all parameters were valid and the byte was written to
.in 0.72i
the port\.
.in 0.4i
\.F\. if invalid parameters were passed\.
.sp
.in 0.08i
\fBDescription
.sp
.in 0.4i
It may sometimes be useful to write a byte to a port without having
to resort to C or assembler\. This function allows you to do so\.
.sp
The source code is written to adhere to Turbo Assembler\'s IDEAL mode\.
To use another assembler, you will need to rearrange the PROC and
SEGMENT directives, and also the ENDP and ENDS directives (a very
minor task)\.
.sp
.in 0.08i
\fBExamples
.sp
.in 0.4i
.ta 2.16i
lOk := FT_OUTP( 100, 0 ) // send a Chr(0) to port 100 (064h)
.br
.ta
.sp
.in 0.08i
\fBSource:\fR OUTP\.ASM
.sp
\fBAuthor:\fR Ted Means
.in 0i
.sp
.in 1.5i
.ti -1.5i
.ta 1.5i
.ft B
See Also:
.ft R
FT_INP()
.ta 1.63265i
.in 0i
.sp 2
.ne 20
.ps +3
.vs +3
FT_PEEK() Retrieve a byte from a specified memory location\.
.br
.ta
.in 0.08i
.ps -3
.vs -3
.sp 2
\fBFT_PEEK()
Retrieve a byte from a specified memory location\.
.in 0i
.br
\l'6.24i'
.br
.sp
.in 0.08i
\fBSyntax
.sp
.in 0.4i
\fBFT_PEEK( <nSegment>, <nOffset> ) -> nValue
.sp
.in 0.08i
\fBArguments
.sp
.in 0.4i
\fB<nSegment>\fR is the segment of the desired memory address\.
.sp
.ta 0.88i
\fB<nOffset>\fR is the offset of the desired memory address\.
.br
.ta
.sp
.in 0.08i
\fBReturns
.sp
.in 0.4i
<nValue> will be a value from 0 to 255 if all parameters were valid and
.in 1.12i
the function was able to retrieve the desired byte\.
.in 0.4i
<nValue> will be -1 if invalid parameters were passed\.
.sp
.in 0.08i
\fBDescription
.sp
.in 0.4i
Use this function if you have a need to examine a specific memory
location\. The function will return the byte at the specified
address as a numeric value\. If you need this value as a character,
use the Chr() function to convert it\.
.sp
This function was written for version 5\.1 of MicroSoft C\. You may
have to modify the source code to use another compiler\.
.sp
.in 0.08i
\fBExamples
.sp
.in 0.4i
.ta 2.88i
local nVMode := FT_PEEK( 0, 1097 ) // Get the current video mode
.br
.ta
.sp
.in 0.08i
\fBSource:\fR PEEK\.C
.sp
\fBAuthor:\fR Ted Means
.in 0i
.ta 1.63265i
.sp 2
.ne 20
.ps +3
.vs +3
FT_POKE() Write a byte to a specified memory location
.br
.ta
.in 0.08i
.ps -3
.vs -3
.sp 2
\fBFT_POKE()
Write a byte to a specified memory location
.in 0i
.br
\l'6.24i'
.br
.sp
.in 0.08i
\fBSyntax
.sp
.in 0.4i
\fBFT_POKE( <nSegment>, <nOffset>, <nValue> ) -> lResult
.sp
.in 0.08i
\fBArguments
.sp
.in 0.4i
\fB<nSegment>\fR is the segment of the desired memory address\.
.sp
.ta 0.88i
\fB<nOffset>\fR is the offset of the desired memory address\.
.br
.ta
.sp
.ta 0.88i
\fB<nValue>\fR is the value to write to the desired memory address\.
.br
.ta
.sp
.in 0.08i
\fBReturns
.sp
.in 0.4i
<lResult> will be \.T\. if all parameters were valid and the function was
.in 1.2i
able to write the desired byte\.
.in 0.4i
<lResult> will be \.F\. if invalid parameters were passed\.
.sp
.in 0.08i
\fBDescription
.sp
.in 0.4i
Use this function if you have a need to change the value at a specific
memory location\. The function will write the specified byte to the
specified address\. The value must be passed as a numeric; if the byte
you wish to use is stored as a character, use the Asc() function
to convert it\.
.sp
This function was written for version 5\.1 of MicroSoft C\. You may
have to modify the source code to use another compiler\.
.sp
.in 0.08i
\fBExamples
.sp
.in 0.4i
.ta 1.84i
FT_POKE( 0, 1047, 64) // Turn CapsLock on
.br
.ta
.sp
.in 0.08i
\fBSource:\fR POKE\.C
.sp
\fBAuthor:\fR Ted Means
.in 0i
.ta 1.63265i
.sp 2
.ne 20
.ps +3
.vs +3
FT_REBOOT() Force a warm or cold boot
.br
.ta
.in 0.08i
.ps -3
.vs -3
.sp 2
\fBFT_REBOOT()
Force a warm or cold boot
.in 0i
.br
\l'6.24i'
.br
.sp
.in 0.08i
\fBSyntax
.sp
.in 0.48i
\fBFT_REBOOT( <nBootType> ) -> NIL
.sp
.in 0.08i
\fBArguments
.sp
.in 0.48i
\fB<nBootType>\fR is used to indicate the type of reboot\. A value of zero
will cause a cold boot, while any other value will cause a warm boot\.
.sp
.in 0.08i
\fBReturns
.sp
.in 0.48i
NIL
.sp
.in 0.08i
\fBDescription
.sp
.in 0.48i
This function is valuable if you need to reboot the PC for some
reason; e\.g\. an installation routine that modifies CONFIG\.SYS or
AUTOEXEC\.BAT\.
.sp
The source code is written to adhere to Turbo Assembler\'s IDEAL mode\.
To use another assembler, you will need to rearrange the PROC and
SEGMENT directives, and also the ENDP and ENDS directives (a very
minor task)\.
.sp
.in 0.08i
\fBExamples
.sp
.in 0.48i
.br
#define COLD 0
.br
#define WARM 1
.sp
.br
// Issue a warm boot
.sp
.br
FT_Reboot(WARM)
.sp
.sp
.in 0.08i
\fBSource:\fR REBOOT\.ASM
.sp
\fBAuthor:\fR Ted Means
.in 0i
.ta 1.63265i
.sp 2
.ne 20
.ps +3
.vs +3
FT_RMDIR() Delete a subdirectory
.br
.ta
.in 0.08i
.ps -3
.vs -3
.sp 2
\fBFT_RMDIR()
Delete a subdirectory
.in 0i
.br
\l'6.24i'
.br
.sp
.in 0.08i
\fBSyntax
.sp
.in 0.48i
\fBFT_RMDIR( <cDirName> ) -> nResult
.sp
.in 0.08i
\fBArguments
.sp
.in 0.48i
\fB<cDirName>\fR is the name of the directory to delete\.
.sp
.in 0.08i
\fBReturns
.sp
.in 0.56i
.ta 0.24i
0 if successful
.br
.ta
.ta 0.24i
3 if Path Not Found
.br
.ta
.ta 0.24i
5 if Access Denied (directory not empty)
.br
.ta
.in 0.48i
.ta 0.32i
16 if attempt to delete current directory\.
.br
.ta
.ta 0.32i
99 if invalid parameters passed
.br
.ta
.sp
.in 0.08i
\fBDescription
.sp
.in 0.4i
This function is useful if you need to remove a subdirectory for
some reason\.
.sp
The source code is written to adhere to Turbo Assembler\'s IDEAL mode\.
To use another assembler, you will need to rearrange the PROC and
SEGMENT directives, and also the ENDP and ENDS directives (a very
minor task)\.
.sp
.in 0.08i
\fBExamples
.sp
.in 0.4i
.br
FT_RMDIR( "C:\\CLIPPER" )
.br
FT_RMDIR( "\\EXAMPLE" )
.br
FT_RMDIR( "\.\.\\SOURCE" )
.sp
.in 0.08i
\fBSource:\fR RMDIR\.ASM
.sp
\fBAuthor:\fR Ted Means
.in 0i
.ta 1.63265i
.sp 2
.ne 20
.ps +3
.vs +3
FT_SETDATE() Set the DOS system date
.br
.ta
.in 0.08i
.ps -3
.vs -3
.sp 2
\fBFT_SETDATE()
Set the DOS system date
.in 0i
.br
\l'6.24i'
.br
.sp
.in 0.08i
\fBSyntax
.sp
.in 0.4i
\fBFT_SETDATE( <dDate> ) -> <lResult>
.sp
.in 0.08i
\fBArguments
.sp
.in 0.4i
\fB<dDate>\fR is a Clipper date variable that you want to set the current
DOS system date to\.
.sp
It is up to you to send in a valid date\. The
year must be within the range 1980 through 2099\. If DOS
thinks the date is not valid, it won\'t change the date\.
.sp
.sp
.in 0.08i
\fBReturns
.sp
.in 0.4i
<lResult> is simply the result of FT_INT86(), passed back
to your program\.
.sp
.sp
.in 0.08i
\fBDescription
.sp
.in 0.4i
FT_SETDATE() uses NANFOR\.LIB\'s FT_INT86() function to invoke
the DOS Set Date service (Interrupt 33, service 43)\.
.sp
.sp
.in 0.08i
\fBExamples
.sp
.sp
.in 0.16i
The following program takes a date from the command line and sets
the DOS system date:
.sp
.in 0.24i
FUNCTION main( cDate )
.sp
.in 0.48i
.br
cDate := iif( cDate == nil, dtoc( date() ), cDate )
.ta 2.8i
.br
QOut( "Setting date to: " + cDate + "\.\.\. " )
.br
.ta
.br
FT_SETDATE( ctod( cDate ) )
.br
Qout( "Today is now: " + dtoc( date() ) )
.sp
.in 0.24i
RETURN ( nil )
.sp
.sp
.in 0.08i
\fBSource:\fR SETDATE\.PRG
.sp
\fBAuthor:\fR Glenn Scott
.in 0i
.ta 1.63265i
.sp 2
.ne 20
.ps +3
.vs +3
FT_SETTIME() Set the DOS system time
.br
.ta
.in 0.08i
.ps -3
.vs -3
.sp 2
\fBFT_SETTIME()
Set the DOS system time
.in 0i
.br
\l'6.24i'
.br
.sp
.in 0.08i
\fBSyntax
.sp
.in 0.4i
\fBFT_SETTIME( <cTime> ) -> <lResult>
.sp
.in 0.08i
\fBArguments
.sp
.in 0.4i
\fB<cTime>\fR is a string in the form \fB<hh:mm:ss>\fR that you want to set
the current DOS system time to\.
.sp
Use 24-hour time\. It is up to you to send in a valid time\. If
DOS doesn\'t think it is valid, it won\'t reset the time anyway\.
.sp
.in 0.08i
\fBReturns
.sp
.in 0.4i
<lResult> is simply the result of FT_INT86(), passed back
to your program\.
.sp
.sp
.in 0.08i
\fBDescription
.sp
.in 0.4i
FT_SETTIME() uses NANFOR\.LIB\'s FT_INT86() function to invoke
the DOS Set Time service (Interrupt 33, service 45)\.
.sp
.sp
.in 0.08i
\fBExamples
.sp
.sp
.in 0.16i
The following program takes a time string from the command line and sets
the DOS system time:
.sp
.in 0.24i
FUNCTION main( cTime )
.sp
.in 0.48i
.br
cTime := iif( cTime == nil, time(), cTime )
.ta 2.8i
.br
QOut( "Setting time to: " + cTime + "\.\.\. " )
.br
.ta
.br
FT_SETTIME( cTime )
.br
Qout( "Time is now: " + time() )
.sp
.in 0.24i
RETURN ( nil )
.sp
.sp
.in 0.08i
\fBSource:\fR SETTIME\.PRG
.sp
\fBAuthor:\fR Glenn Scott
.in 0i
.ta 1.63265i
.sp 2
.ne 20
.ps +3
.vs +3
FT_SYSMEM() Determine the amount of conventional memory installed
.br
.ta
.in 0.08i
.ps -3
.vs -3
.sp 2
\fBFT_SYSMEM()
Determine the amount of conventional memory installed
.in 0i
.br
\l'6.24i'
.br
.sp
.in 0.08i
\fBSyntax
.sp
.in 0.4i
\fBFT_SYSMEM() -> nMemSize
.sp
.in 0.08i
\fBArguments
.sp
.in 0.4i
None
.sp
.in 0.08i
\fBReturns
.sp
.in 0.4i
A numeric corresponding to the number of K memory\.
.sp
.in 0.08i
\fBDescription
.sp
.in 0.4i
FT_SYSMEM() simply reports the amount of conventional memory
(up to 640K) installed\.
.sp
FT_SYSMEM() uses DOS interrupt 12h to get this information\.
For information, refer to Peter Norton\'s _Programmer\'s Guide
to the IBM PC_ (Brady)\.
.sp
.sp
.in 0.08i
\fBExamples
.sp
.in 0.4i
QOut( "Conventional memory installed: " + Str( FT_SYSMEM() ) + "K" )
.sp
.in 0.08i
\fBSource:\fR SYSMEM\.PRG
.sp
\fBAuthor:\fR Glenn Scott
.in 0i
.ta 1.63265i
.sp 2
.ne 20
.ps +3
.vs +3
FT_TEMPFIL() Create a file with a unique name
.br
.ta
.in 0.08i
.ps -3
.vs -3
.sp 2
\fBFT_TEMPFIL()
Create a file with a unique name
.in 0i
.br
\l'6.24i'
.br
.sp
.in 0.08i
\fBSyntax
.sp
.in 0.4i
\fBFT_TEMPFIL( [ <cPath> ] [, <lHide> ] ) -> cFileSpec
.sp
.in 0.08i
\fBArguments
.sp
.in 0.4i
\fB<cPath>\fR is the directory where you want to create the temporary
file\. If you omit this argument, the root of the current drive
is assumed ("\\")\.
.sp
If \fB<lHide>\fR is \.T\., then the file will be created with the hidden
attribute set\. The default is \.F\.
.sp
.in 0.08i
\fBReturns
.sp
.in 0.4i
<cFileSpec> should be your path, including the name of the newly
created unique file\. Use this with FOPEN(), etc\.
.sp
.in 0.08i
\fBDescription
.sp
.in 0.4i
This function uses DOS Interrupt 21, service 5Ah (Create temporary
file) to create a unique filename in a directory you specify\.
There will be no extension\. After the file is created, you may
then fopen() it and do any i/o you need (see the test driver
in the source code)\.
.sp
This function requires FT_INT86()\.
.sp
.in 0.08i
\fBExamples
.sp
.in 0.4i
Create a unique file in the root of the current drive:
.sp
.in 0.96i
myFile := FT_TEMPFIL()
.sp
.in 0.4i
Create a unique file in the current directory and hide it:
.sp
.in 0.96i
myFile := FT_TEMPFIL("\.\\", \.t\.)
.sp
.in 0.4i
Create a unique file on another drive, but do not hide it:
.sp
.in 0.96i
myFile := FT_TEMPFIL("e:\\nanfor\\src\\")
.sp
.in 0.08i
\fBSource:\fR TEMPFILE\.PRG
.sp
\fBAuthor:\fR Glenn Scott