'ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
'³                                                                        ³
'³                          Q B D I S K . B A S                           ³
'³                                                                        ³
'³                   Supplementary Source Code for the                    ³
'³       The QBSCR Screen Routines for QuickBASIC 4.0+ Programmers        ³
'³                              Version 2.0                               ³
'³                                                                        ³
'³                   (C) Copyright 1992 by Tony Martin                    ³
'³                                                                        ³
'ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
'³                                                                        ³
'³  This source code is copyright 1992 by Tony Martin.  You may change    ³
'³  it to suit your programming needs, but you may not distribute any     ³
'³  modified copies of the library itself.  I retain all rights to the    ³
'³  source code and all library modules included with the QBSCR package,  ³
'³  as well as to the example programs.  You may not remove this notice   ³
'³  from any copies of the library itself you distribute.                 ³
'³                                                                        ³
'³  You are granted the right to use this source code for your own pro-   ³
'³  grams, without royalty payments or credits to me (though, if you      ³
'³  feel so inclined to give me credit, feel free to do so).  You MUST    ³
'³  register this software if you release a shareware or commercial       ³
'³  program that uses it.  You may use these routines in any type of      ³
'³  software you create, as long as it is not a programming toolbox or    ³
'³  package of routines OF ANY KIND.                                      ³
'³                                                                        ³
'³  This package is shareware.  If you find it useful or use it in any    ³
'³  software you release, you are requested to send a registration fee of ³
'³  $25.00 (U.S. funds only) to:                                          ³
'³                                                                        ³
'³                            Tony Martin                                 ³
'³                       1611 Harvest Green Ct.                           ³
'³                          Reston, VA 22094                              ³
'³                                                                        ³
'³  All registered users receive an 'official' disk set containing the    ³
'³  latest verison of the QBSCR routines.  For more information, see      ³
'³  the QBSCR documentation.                                              ³
'³                                                                        ³
'ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
'³                                                                        ³
'³  For information on using these routines and incorporating them into   ³
'³  your own programs, see the accompanying documentation.                ³
'³                                                                        ³
'ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

'$INCLUDE: 'qbscr.inc'
'$INCLUDE: 'qb.bi'

CONST FALSE = 0, TRUE = NOT FALSE

COMMON SHARED mouseExists%, mouseState%

SUB FileInfo (fd AS FileInfoType, dta$)

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' This function extracts file information from the 43-byte DTA that is
	' filled in by a call to FirstFile% or NextFile%.  It expects a data
	' object of type FileInfoType to be passed in, which it will fill with
	' the appropriate data.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' Determine a numeric attribute value, as well as a string that represents
	' all applicable attributes for the file.  There will be character in the
	' string for each attribute that applies.  The characters have the follow-
	' ing meanings:
	'
	'               Character   Attribute
	'               ---------   -----------------
	'                   R       Read Only
	'                   H       Hidden file
	'                   S       System file
	'                   V       Volume Label
	'                   D       Subdirectory
	'                   A       Archive
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	fd.fattribute = ASC(MID$(dta$, 22, 1))
	IF fd.fattribute AND ReadOnlyAttr THEN
		attrstr$ = attrstr$ + "R"
	END IF
	IF fd.fattribute AND HiddenAttr THEN
		attrstr$ = attrstr$ + "H"
	END IF
	IF fd.fattribute AND SystemAttr THEN
		attrstr$ = attrstr$ + "S"
	END IF
	IF fd.fattribute AND VolLabelAttr THEN
		attrstr$ = attrstr$ + "V"
	END IF
	IF fd.fattribute AND SubdirAttr THEN
		attrstr$ = attrstr$ + "D"
	END IF
	IF fd.fattribute AND ArchiveAttr THEN
		attrstr$ = attrstr$ + "A"
	END IF
	fd.fattrstr = attrstr$
 
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' Calculate the file's time of creation or last modification.  The time is
	' an unsigned integer, and we must improvise our own by adding 65536
	' to the value to compensate for the sign bit.  Build time string last.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	temptime& = CVI(MID$(dta$, 23, 2))
	IF temptime& < 0 THEN temptime& = temptime& + 65536  ' Adjust for unsigned.
	hour% = (temptime& \ 2048) AND 31     ' Have to mask out the hours,
	minute% = (temptime& \ 32) AND 63     ' minutes, and seconds.
	second% = temptime& AND 31
	fd.ftime = LTRIM$(STR$(hour%)) + ":" + LTRIM$(STR$(minute%)) + ":" + LTRIM$(STR$(second%))
 
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' Calculate date and build a date string.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	tempdate& = CVI(MID$(dta$, 25, 2))
	month% = (tempdate& \ 32) AND 15      ' Have to mask out the month, day,
	day% = tempdate& AND &H31             ' and year (since 1980).
	year% = ((tempdate& \ 512) AND 31) + 1980
	fd.fdate = LTRIM$(STR$(month%)) + "-" + LTRIM$(STR$(day%)) + "-" + LTRIM$(STR$(year%))

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' File size is a simple long integer.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	fd.fsize = CVL(MID$(dta$, 27, 4))
	
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' File name starts at byte 31 in the DTA, and is terminated by an ASCII 0
	' (the NULL character).  We can find the end by looking for the NULL.  If
	' we don't, and just use all 13 characters, we may end with some characters
	' from a previous filename.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	fd.fname = MID$(dta$, 31, INSTR(RIGHT$(dta$, 13), CHR$(0)) - 1)
 
END SUB

FUNCTION FirstFile% (fileName$, attributes%, dta$)

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' This function searches for the first files who's name matches the
	' passed-in fileName$.  Note that fileName$ may have wildcards * and ? in
	' them.  The DTA$ is filled by this function (actually by the call to
	' the DOS service) and is used in later calls to FindNext% and FileInfo%.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' Define a register type for us to use.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	DIM regx AS RegTypeX
	dta$ = SPACE$(43)

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' When DOS performs disk activity, it uses the DTA (Disk Transfer Area)
	' portion of memory.  Usually this is a 128 byte buffer located at offset
	' 80h in the PSP (Program Segment Prefix). If this doesn't make sense,
	' don't worry.  All you need to know is that since, we will be using our
	' own DTA (to store info about the last file search), we must save the
	' current DTA address and restore it when we are done.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	regx.ax = &H2F00        ' Service 2F (Get DTA) in register AH, 00 in AL.
	INTERRUPTX &H21, regx, regx
	oldOffset% = regx.bx    ' Register BX contains offset of current DTA.
	oldSegment% = regx.es   ' Register ES contains segment of current DTA.

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' Now we must define our own DTA for DOS to use.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	regx.ax = &H1A00        ' Service 1A (Set DTA) in register AH, 00 in AL.
	regx.dx = SADD(dta$)    ' Offset of address of dta$.
	regx.ds = VARSEG(dta$)  ' Segment of address of dta$.
	INTERRUPTX &H21, regx, regx
 
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' Set up data before call to function and call the interrupt service.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	tempName$ = fileName$ + CHR$(0)    ' NULL-terminate the filename.
	regx.ax = &H4E00
	regx.cx = attributes%
	regx.dx = SADD(tempName$)
	regx.ds = VARSEG(tempName$)
	INTERRUPTX &H21, regx, regx

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' If the Carry flag is ste, there was an error, i.e., no match was found.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	IF (regx.flags AND 1) THEN    ' ERROR!
		FirstFile% = FALSE          ' Return FALSE - no match found.
	ELSE
		FirstFile% = TRUE           ' Yay!  A match!
	END IF

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' Now that we're done, we have to restore the DOS DTA space we saved at
	' the beginning of the routine.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	regx.ax = &H1A00        ' Service 1A in register AH, 00 in AL.
	regx.dx = oldOffset%    ' Offset of address of original DOS DTA.
	regx.ds = oldSegment%   ' Segment of address of original DOS DTA.
	INTERRUPTX &H21, regx, regx

END FUNCTION

FUNCTION GetDiskFreeSpace& (drive%)

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' This function returns the amount of free disk space (in bytes) of the
	' specified drive.  The drive code passed-in (drive%) has values like this:
	' Drive code: 0=default, 1=A, 2=B, 3=C, etc.  Note that this function
	' returns a LONG INTEGER value.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
 
	DIM reg AS RegType

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' We want service 36h in register AH, and the drive code in register DX.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	reg.ax = &H3600
	reg.dx = drive%
	INTERRUPT &H21, reg, reg

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' Calculate the total butes free. The service 36h returns the disk sectors
	' per cluster in register AX, the total available clusters in register BX,
	' and the bytes per cluster in register CX.  Multiply all three together to
	' get the total free space in bytes. This must be a LONG integer multipli-
	' cation.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	sectorsPerCluster& = reg.ax
	availClusters& = reg.bx
	bytesPerSector& = reg.cx

	GetDiskFreeSpace& = sectorsPerCluster& * availClusters& * bytesPerSector&

END FUNCTION

FUNCTION GetDriveCode%

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' This function determines the current default disk drive and returns its
	' DOS numeric code.  The codes look like 0=A, 1=B, 2=C, etc.  You probably
	' won't be using it a whole lot, but it is used by the NumDrives% function.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
 
	DIM reg AS RegType

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' We want DOS service 19h in register AH.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	reg.ax = &H1900
	INTERRUPT &H21, reg, reg

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' The drive code is returned in the lower half of AX, or AH.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	GetDriveCode% = reg.ax AND &HFF

END FUNCTION

FUNCTION GetDriveLetter$

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' This function returns a single letter, the letter of the current default
	' disk drive.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

	DIM reg AS RegType

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' We want DOS service 19h in register AH.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	reg.ax = &H1900
	INTERRUPT &H21, reg, reg

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' The drive code is returned in the lower half of AX, or AH.  We can easily
	' calculate the letter that represents this drive by adding 65 to it.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	GetDriveLetter$ = CHR$((reg.ax AND &HFF) + 65)

END FUNCTION

FUNCTION GetPath$ (drive%)

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' This function determines the current DOS path.  Not the path specified
	' by the PATH command, but rather the current path the user is logged to.
	' Simplay pass in a drive code, where drive% is like 0=default, 1=A, 2=B,
	' 3=C, etc.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' Must make sure that there are 65 bytes reserved for the path name.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	path$ = SPACE$(65)
	DIM regx AS RegTypeX

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' Place DOS service 47h in register AH, the drive code in register DX, the
	' offset of the address of the path buffer in SI, and the segment of the
	' address of the path buffer in DS.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	regx.ax = &H4700
	regx.dx = drive%
	regx.si = SADD(path$)
	regx.ds = VARSEG(path$)
	INTERRUPTX &H21, regx, regx

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' If the carry flag (first bit position in the flags byte) is set, then
	' there was an error, so return a NULL string ("").  Otherwise, return
	' the string filled in by the DOS service.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	IF (regx.flags AND 1) THEN
		path$ = ""
	END IF
 
	GetPath$ = path$

END FUNCTION

FUNCTION NextFile% (dta$)

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' This function searches for any files who's name matches the data in then
	' passed-in dta$.  Note that the DTA$ is filled by this function (actually
	' by the call to the DOS service) and is used in later calls to FindNext%
	' and FileInfo%.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' Define a register type for us to use.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	DIM regx AS RegTypeX

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' When DOS performs disk activity, it uses the DTA (Disk Transfer Area)
	' portion of memory.  Usually this is a 128 byte buffer located at offset
	' 80h in the PSP (Program Segment Prefix). If this doesn't make sense,
	' don't worry.  All you need to know is that since, we will be using our
	' own DTA (to store info about the last file search), we must save the
	' current DTA address and restore it when we are done.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	regx.ax = &H2F00        ' Service 2F (Get DTA) in register AH, 00 in AL.
	INTERRUPTX &H21, regx, regx
	oldOffset% = regx.bx    ' Register BX contains offset of current DTA.
	oldSegment% = regx.es   ' Register ES contains segment of current DTA.

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' Now we must define our own DTA for DOS to use.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	regx.ax = &H1A00        ' Service 1A (Set DTA) in register AH, 00 in AL.
	regx.dx = SADD(dta$)    ' Offset of address of dta$.
	regx.ds = VARSEG(dta$)  ' Segment of address of dta$.
	INTERRUPTX &H21, regx, regx

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' Set up data before call to function and call the interrupt service.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	regx.ax = &H4F00
	INTERRUPTX &H21, regx, regx

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' If the Carry flag is ste, there was an error, i.e., no match was found.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	IF (regx.flags AND 1) THEN    ' ERROR!
		NextFile% = FALSE          ' Return FALSE - no match found.
	ELSE
		NextFile% = TRUE           ' Yay!  A match!
	END IF

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' Now that we're done, we have to restore the DOS DTA space we saved at
	' the beginning of the routine.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	regx.ax = &H1A00        ' Service 1A in register AH, 00 in AL.
	regx.dx = oldOffset%    ' Offset of address of original DOS DTA.
	regx.ds = oldSegment%   ' Segment of address of original DOS DTA.
	INTERRUPTX &H21, regx, regx

END FUNCTION

FUNCTION NumDrives%

	DIM reg AS RegType

	reg.ax = &HE00
	reg.dx = GetDriveCode%    ' Find out current drive, so we stay there.
	INTERRUPT &H21, reg, reg

	NumDrives% = reg.ax AND &HFF

END FUNCTION

SUB SetDefaultDrive (drive%)
 
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' This routine allows you to set a new default drive.  The drive code that
	' is passed in looks like 0=A, 1=B, 2=C, etc.
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

	DIM reg AS RegType

	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	' DOS service 0Eh in register AH, and the drive code in register DX.
	' It's that simple!
	' ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	reg.ax = &HE00
	reg.dx = drive%
	INTERRUPT &H21, reg, reg

END SUB

