'
' NeoLib - DOS Module
'
' Features:
'  4 subs
'  11 functions
' For a total of: 15 routines
'
' Specially designed and coded for AAP's QBCPC
' Official Library of the QuickBASIC Caliber Programming Compo (Summer & Autumn 2003)
'

DECLARE FUNCTION neoDOSsearchFile$ (FileMask AS STRING)
DECLARE FUNCTION neoDOSsearchDir$ (DirMask AS STRING)
DECLARE FUNCTION neoDOSgetOpenedDateTime$ (FileHandle AS INTEGER)
DECLARE FUNCTION neoDOSisDir% (FileName AS STRING)
DECLARE FUNCTION neoDOSisFile% (FileName AS STRING)
DECLARE FUNCTION neoDOSgetFileAttributes% (FileName AS STRING)
DECLARE FUNCTION neoDOSgetFullPath$ (FileName AS STRING)
DECLARE FUNCTION neoDOSgetCurrentDrive$ ()
DECLARE FUNCTION neoDOSgetCurrentDir$ ()
DECLARE FUNCTION neoDOSgetTime$ ()
DECLARE FUNCTION neoDOSgetCurrentEXE$ ()

DECLARE SUB neoDOSsearchFileThrough (FileMask AS STRING, Root AS STRING, TempFile AS STRING, FileOpenMode AS INTEGER)
DECLARE SUB neoDOSsetFileAttributes (FileName AS STRING, FileAttributes AS INTEGER)
DECLARE SUB neoDOSdisableDrive (DriveLetter AS STRING)
DECLARE SUB neoDOSenableDrive (DriveLetter AS STRING)

DEFINT A-Z
'$DYNAMIC
'$INCLUDE: 'QB.BI'

DIM SHARED Regs AS RegType
DIM SHARED RegsX AS RegTypeX

CONST DELETEONEXISTING = 1, APPENDONEXISTING = 2
CONST FILEREADONLY = 1, FILEHIDDEN = 2, FILESYSTEM = 4, FILEVOLUMELABEL = 8, FILEDIRECTORY = 16
CONST FILEARCHIVE = 32, FILESHARABLE = 128

'/////////////////////////////////////////////////////////////////////////////
' FUNCTIONS
'/////////////////////////////////////////////////////////////////////////////
FUNCTION neoDOSgetCurrentEXE$
        'gets the full path and filename of the currently running EXE
	Regs.ax = &H6200
	INTERRUPT &H21, Regs, Regs

	DEF SEG = Regs.bx
	DEF SEG = PEEK(44) + 256& * PEEK(45)

	Offset = 0
	DO UNTIL PEEK(Offset) = 0 AND PEEK(Offset + 1) = 0
		Offset = Offset + 1
	LOOP

	Offset = Offset + 4
	DO UNTIL PEEK(Offset) = 0
		Filename$ = Filename$ + CHR$(PEEK(Offset))
		Offset = Offset + 1
	LOOP

	DEF SEG
	neoDOSgetCurrentEXE$ = Filename$
END FUNCTION

FUNCTION neoDOSgetCurrentDrive$
	'gets the current drive (1 character)

	'use int 21h, ax=1900
	Regs.ax = &H1900
        INTERRUPT &H21, Regs, Regs
        neoDOSgetCurrentDrive$ = CHR$((Regs.ax AND &HFF) + ASC("A"))
END FUNCTION

FUNCTION neoDOSgetCurrentDir$
	'gets the current directory on the current drive

	'use int 21h, ax=4700
	DIM Buffer AS STRING * 64
        RegsX.ax = &H4700
        RegsX.dx = 0
        RegsX.ds = VARSEG(Buffer)
        RegsX.si = VARPTR(Buffer)
        INTERRUPTX &H21, RegsX, RegsX
        neoDOSgetCurrentDir$ = RTRIM$(Buffer)
END FUNCTION

FUNCTION neoDOSsearchFile$ (FileMask AS STRING) STATIC
	'searches for a file
	'- FileMask: specifies the mask of the file to search for
	'	     => String: search for that file (e.g. "*.BMP")
	'	     => Null String: search for the next file with previous attributes

        DIM DTA AS STRING * 44

        RegsX.ax = &H1A00
        RegsX.dx = VARPTR(DTA)
        RegsX.ds = -1
        INTERRUPTX &H21, RegsX, RegsX	'set disk transfer address

	IF FileMask <> "" THEN
		RegsX.ax = &H4E00
		RegsX.cx = 0
		RegsX.ds = -1
		FileMaskZ$ = FileMask$ + CHR$(0)
		RegsX.dx = SADD(FileMaskZ$)
        ELSE
		RegsX.ax = &H4F00
        END IF
        INTERRUPTX &H21, RegsX, RegsX
        IF RegsX.flags AND 1 THEN
                neoDOSsearchFile$ = ""
        ELSE
        	WhereIsEnd = INSTR(31, DTA, CHR$(0))
                ans$ = MID$(DTA, 31, WhereIsEnd - 30)
                IF ans$ <> "" THEN ans$ = LEFT$(ans$, LEN(ans$) - 1)
                neoDOSsearchFile$ = ans$
        END IF
END FUNCTION

FUNCTION neoDOSsearchDir$ (DirMask AS STRING) STATIC
	'searches for a directory
        '- DirMask: mask of the directory to find
        '           => String: search for that directory (e.g. "NEO*LIB")
        '	    => Null String: search for the next directory using previous mask

        DIM DTA AS STRING * 44

        RegsX.ax = &H1A00
        RegsX.dx = VARPTR(DTA)
        RegsX.ds = -1
        INTERRUPTX &H21, RegsX, RegsX	'set disk transfer address

	IF DirMask <> "" THEN
		RegsX.ax = &H4E00
		RegsX.cx = 16
		RegsX.ds = -1
		DirMaskZ$ = DirMask$ + CHR$(0)
		RegsX.dx = SADD(DirMaskZ$)
        ELSE
		RegsX.ax = &H4F00
		RegsX.cx = 16
        END IF
        INTERRUPTX &H21, RegsX, RegsX
        IF RegsX.flags AND 1 THEN
                neoDOSsearchDir$ = ""
        ELSE
        	WhereIsEnd = INSTR(31, DTA, CHR$(0))
                ans$ = MID$(DTA, 31, WhereIsEnd - 30)
                IF ans$ <> "" THEN ans$ = LEFT$(ans$, LEN(ans$) - 1)
                neoDOSsearchDir$ = ans$
        END IF
END FUNCTION

FUNCTION neoDOSgetOpenedDateTime$ (FileHandle AS INTEGER)
	'gets the last edited date/time of a file
	'- FileHandle: the handle of the file to obtain info from

        Regs.ax = &H5700
        Regs.bx = FileHandle
        INTERRUPT &H21, Regs, Regs
        IF Regs.flags AND 1 THEN neoDOSgetOpenedDateTime$ = "": EXIT FUNCTION
        date% = Regs.dx
        time% = Regs.cx
        day% = date% AND 31
        month% = (date% AND 480) / 32
        year% = (date% AND 65024&) / 512 + 1980
        seconds% = (time% AND 31) * 2
        minutes% = (time% AND 2016) / 32
        hours% = (time% AND 63488&) / 2048
        answer$ = ""
        answer$ = STRING$(3 - LEN(STR$(day%)), "0") + LTRIM$(STR$(day%))
	answer$ = answer$ + "/" + STRING$(3 - LEN(STR$(month%)), "0") + LTRIM$(STR$(month%))
        answer$ = answer$ + "/" + LTRIM$(STR$(year%))
        answer$ = answer$ + " - " + STRING$(3 - LEN(STR$(hours%)), "0") + LTRIM$(STR$(hours%))
        answer$ = answer$ + ":" + STRING$(3 - LEN(STR$(minutes%)), "0") + LTRIM$(STR$(minutes%))
        answer$ = answer$ + ":" + STRING$(3 - LEN(STR$(seconds%)), "0") + LTRIM$(STR$(seconds%))
        neoDOSgetOpenedDateTime$ = answer$
END FUNCTION

FUNCTION neoDOSisDir% (FileName AS STRING)
	'checks if the specified *file* is a directory
	'- FileName: file to check on
	'Returns 0 or -1 whether it is a directory

	RegsX.ax = &H4300
        FileNameZ$ = FileName + CHR$(0)
        RegsX.ds = -1
        RegsX.dx = SADD(FileNameZ$)
        INTERRUPTX &H21, RegsX, RegsX
        IF RegsX.cx AND 16 THEN neoDOSisDir% = NOT(0) ELSE neoDOSisDir% = 0
END FUNCTION

FUNCTION neoDOSisFile% (FileName AS STRING)
	'checks if the specified *file* is a file
	'- FileName: file to check on
	'Returns 0 or -1 whether it is a file

	RegsX.ax = &H4300
	FileNameZ$ = FileName + CHR$(0)
	RegsX.ds = -1
	RegsX.dx = SADD(FileNameZ$)
	INTERRUPTX &H21, RegsX, RegsX
	IF RegsX.cx AND 16 THEN neoDOSisFile% = 0 ELSE neoDOSisFile% = NOT(0)
END FUNCTION

FUNCTION neoDOSgetFileAttributes (FileName AS STRING)
	'returns the attributes of a specified file
	'- FileName: file to get attributes from
	'Returns: a bit-combination of attributes (see constants that begin with 'FILE')

        RegsX.ax = &H4300
        FileNameZ$ = FileName + CHR$(0)
        RegsX.ds = -1
        RegsX.dx = SADD(FileNameZ$)
        INTERRUPTX &H21, RegsX, RegsX
        IF RegsX.flags AND 1 THEN neoDOSgetFileAttributes = 0: EXIT FUNCTION
	neoDOSgetFileAttributes = RegsX.cx
END FUNCTION

FUNCTION neoDOSgetFullPath$ (FileName AS STRING)
	'gets the full path of a file
	'- FileName: the file to get the full path from
	'Returns: a string holding the full path

        DIM FLA AS STRING * 128
        RegsX.ax = &H6000
        RegsX.es = -1
        RegsX.di = VARPTR(FLA)
        FileNameZ$ = FileName + CHR$(0)
        RegsX.ds = -1
        RegsX.si = SADD(FileNameZ$)
        INTERRUPTX &H21, RegsX, RegsX
        IF RegsX.flags AND 1 THEN neoDOSgetFullPath$ = FileName: EXIT FUNCTION
        IF INSTR(FLA, CHR$(0)) = 0 THEN
        	FLAz$ = FLA
        ELSE
        	FLAz$ = LEFT$(FLA, INSTR(FLA, CHR$(0)) - 1)
        END IF
        neoDOSgetFullPath$ = FLAz$
END FUNCTION

FUNCTION neoDOSgetTime$
	'gets the time in 1/100 seconds significantly
	'Returns: a time-string

	Regs.ax = &H2C00
	INTERRUPT &H21, Regs, Regs

	hour% = (Regs.cx AND &HFF00&) \ &H100
	minute% = (Regs.cx AND &HFF)
	second% = (Regs.dx AND &HFF00&) \ &H100
	hundreds% = (Regs.dx AND &HFF)
	neoDOSgetTime$ = LTRIM$(STR$(hour%)) + ":" + LTRIM$(STR$(minute%)) + ":" + LTRIM$(STR$(second%)) + "." + LTRIM$(STR$(hundreds%))
END FUNCTION


'/////////////////////////////////////////////////////////////////////////////
' SUBS
'/////////////////////////////////////////////////////////////////////////////
SUB neoDOSsearchFileThrough(FileMask AS STRING, Root AS STRING, TempFile AS STRING, FileOpenMode AS INTEGER)

	'first get the current directory
	'now get the current drive
        'get current dir
        OldCurrentDir$ = neoDOSgetCurrentDrive$ + ":\" + neoDOSgetCurrentDir$
        DrD$ = neoDOSgetCurrentDrive$

	'now find stuff
	FF = FREEFILE
	ffound# = 0
	SELECT CASE FileOpenMode
		CASE DELETEONEXISTING
			OPEN TempFile FOR OUTPUT AS #FF
		CASE APPENDONEXISTING
			OPEN TempFile FOR APPEND AS #FF
		CASE ELSE
			OPEN TempFile FOR OUTPUT AS #FF
	END SELECT

	FE = FREEFILE
	OPEN "C:\NEODOS!.TMP" FOR OUTPUT AS #FE
	CLOSE #FE
		CHDIR Root
        	IF MID$(Root, 2, 1) = ":" THEN SHELL LEFT$(Root, 2)
		file$ = neoDOSsearchFile(FileMask)
		IF RIGHT$(Root, 1) = "\" THEN RootZ$ = Root ELSE RootZ$ = Root + "\"
		IF RIGHT$(Root, 1) = "\" THEN RootC$ = LEFT$(Root, LEN(Root) - 1) ELSE RootC$ = Root
		'first seek all files in the root dir
        	DO UNTIL file$ = ""
        		PRINT #FF, RootZ$ + file$
        		ffound# = ffound# + 1
        		file$ = neoDOSsearchFile("")
        	LOOP
        	'dirshad$ = Root + CHR$(255)
        	padnow$	= ""
        	'PRINT answer$, dirshad$

		DO
		againdo:
			d$ = neoDOSsearchDir("*")
			DO UNTIL (d$ <> "." AND d$ <> ".."): d$ = neoDOSsearchDir(""): LOOP
			IF d$ = "" THEN
        			IF padnow$ = "" THEN EXIT DO
        			IF padnow$ <> "" THEN
	                        	CHDIR ".."
        	                	FOR x = LEN(padnow$) TO 1 STEP -1
                        			IF MID$(padnow$, x, 1) = "\" THEN EXIT FOR
                        		NEXT x
                        		padnow$ = LEFT$(padnow$, x - 1)
                        		GOTO againdo
        			END IF
        		END IF
        		OPEN "C:\NEODOS!.TMP" FOR INPUT AS #FE
        			fond% = 0
        			WHILE NOT EOF(FE)
        				LINE INPUT #FE, dat$
        				IF padnow$ + "\" + d$ = UCASE$(RTRIM$(dat$)) THEN fond% = 1
        			WEND
        		CLOSE #FE
        		IF fond% = 1 THEN
	                        found = 0
                        	d$ = neoDOSsearchDir("")
                        	DO UNTIL d$ = ""
                        		IF d$ <> "." AND d$ <> ".." THEN
                        			OPEN "C:\NEODOS!.TMP" FOR INPUT AS #FE
        						fond% = 0
        						WHILE NOT EOF(FE)
        							LINE INPUT #FE, dat$
        							IF padnow$ + "\" + d$ = UCASE$(RTRIM$(dat$)) THEN fond% = 1
        						WEND
        					CLOSE #FE
        					IF fond% = 0 THEN
                        				found = -1
                        				EXIT DO
                        			END IF
                        		END IF
                        		d$ = neoDOSsearchDir("")
                        	LOOP
                        	IF NOT found THEN
                                	IF padnow$ = "" THEN EXIT DO
                                	IF padnow$ <> "" THEN
                                		CHDIR ".."
                                		FOR x = LEN(padnow$) TO 1 STEP -1
                        				IF MID$(padnow$, x, 1) = "\" THEN EXIT FOR
                        			NEXT x
                        			padnow$ = LEFT$(padnow$, x - 1)
                        			GOTO againdo
                        		END IF
                        	END IF
        		END IF
        		padnow$ = padnow$ + "\" + d$
        		OPEN "C:\NEODOS!.TMP" FOR APPEND AS #FE
        			PRINT #FE, padnow$
        		CLOSE #FE

        		RegsX.ax = &H4300
        		FileNam$ = d$ + CHR$(0)
        		RegsX.ds = -1
        		RegsX.dx = SADD(FileNam$)
                        INTERRUPTX &H21, RegsX, RegsX
                        IF RegsX.cx AND 16 THEN
                                IF LEN(padnow$) >= 63 THEN
                                	FOR x = LEN(padnow$) TO 1 STEP -1
                        			IF MID$(padnow$, x, 1) = "\" THEN EXIT FOR
                        		NEXT x
                        		padnow$ = LEFT$(padnow$, x - 1)
                                	GOTO againdo
                                END IF
        			CHDIR d$	'it is a directory
        		ELSE	'no dir!
        			FOR x = LEN(padnow$) TO 1 STEP -1
                        		IF MID$(padnow$, x, 1) = "\" THEN EXIT FOR
                        	NEXT x
                        	padnow$ = LEFT$(padnow$, x - 1)
                        	GOTO againdo
        		END IF

        		file$ = neoDOSsearchFile(FileMask)
        		DO UNTIL file$ = ""
        			PRINT #FF, RootC$ + padnow$ + "\" + file$
        			ffound# = ffound# + 1
        			file$ = neoDOSsearchFile("")
        		LOOP
        	LOOP
        CLOSE #FF
        KILL "C:\NEODOS!.TMP"

        'change back to current dir
        SHELL DrD$ + ":"
        CHDIR OldCurrentDir$
END SUB

SUB neoDOSsetFileAttributes (FileName AS STRING, FileAttributes AS INTEGER)
	RegsX.ax = &H4301
	FileNameZ$ = FileName + CHR$(0)
	RegsX.ds = -1
	RegsX.dx = SADD(FileNameZ$)
        RegsX.cx = FileAttributes
        INTERRUPTX &H21, RegsX, RegsX
END SUB

SUB neoDOSdisableDrive (DriveLetter AS STRING)
	Regs.ax = &H5F08
	Regs.dx = ASC(UCASE$(DriveLetter)) - ASC("A")
	INTERRUPT &H21, Regs, Regs
END SUB

SUB neoDOSenableDrive (DriveLetter AS STRING)
	Regs.ax = &H5F07
	Regs.dx = ASC(UCASE$(DriveLetter)) - ASC("A")
	INTERRUPT &H21, Regs, Regs
END SUB


