'=========================================================================== ' Subject: FILE/DIRECTORY SELECTOR Date: 06-30-00 (15:25) ' Author: Antoni Gual Code: QB, QBasic, PDS ' Origin: agual@eic.ictnet.es Packet: DOS.ABC '=========================================================================== DECLARE FUNCTION DiskReady% (d$) DECLARE FUNCTION SelectAFile$ (header$, ext$) ' ' Here are two useful routines for QBasic and QB ' without a single line of assembler: ' ' Self-contained drive check routine ' by Antoni Gual agual@eic.ictnet.es ' from a batch by Tom Lavedas ' ' User friendly file select routine ' by Antoni Gual agual@eic.ictnet.es ' Rewritten completely from a layout by William Yu ' ' enjoy it! ' CONST false = 0, true = NOT false '------------------------------demo----------------------------------------- SCREEN 0: COLOR 7, 1: WIDTH , 50: CLS GOTO sel LOCATE 1, 1: PRINT CHR$(201); STRING$(78, 205); CHR$(187); FOR i = 2 TO 23 LOCATE i, 1: PRINT CHR$(186); : LOCATE , 80: PRINT CHR$(186); NEXT LOCATE 24, 1: PRINT CHR$(200); STRING$(78, 205); CHR$(188); COLOR 14 LOCATE 2, 31: PRINT "DiskReady Sub DEMO" COLOR 7 LOCATE 5, 32: PRINT "Testing drives..."; FOR i = ASC("A") TO ASC("L") a$ = CHR$(i) b = DiskReady(a$) LOCATE i - 58, 2 SELECT CASE b CASE 0: PRINT "Bingo!: Drive "; a$; ": is not yet broken!"; CASE 1: PRINT "Where am I supposed to read data? Air? Put something in drive "; a$; "!"; CASE 2: PRINT "It's a joke? You did'nt pay enough for your PC to have a drive named "; a$; ":"; CASE 3: PRINT "You're supposed to be working hard! What's all that rock'n roll in drive "; a$; ":?"; END SELECT NEXT LOCATE 22, 22: PRINT "Press any key to go to SelectAFile Sub Demo.."; SLEEP sel: SCREEN 0: COLOR 7, 1: WIDTH , 50: CLS LOCATE 6: PRINT "Current dir is ": SHELL "CD" LOCATE 8: PRINT "And if you press a key you will be prompted to select a file!" PCOPY 0, 1 a$ = INPUT$(1) a$ = SelectAFile$("Select any file: I will do absolutely nothing with it!", "txt") PCOPY 1, 0 IF LEN(a$) THEN LOCATE 10: PRINT "You selected: "; a$ OPEN a$ FOR BINARY AS #1: SHELL "echo I opened it and i found It has " + STR$(LOF(1)) + " bytes" CLOSE ELSE LOCATE 10: PRINT "You exit SelectAFile without selecting anithing" END IF SHELL "echo And Current dir is still": SHELL "CD" PRINT "press any key": a$ = INPUT$(1) SCREEN 0: COLOR 7, 1: WIDTH , 25: CLS a$ = SelectAFile$("Here We Go Again!", "*") LOCATE 10: PRINT "You selected: "; a$ END DEFINT A-Z FUNCTION DiskReady (d$) ' 'Self-contained drive check routine 'by Antoni Gual agual@eic.ictnet.es 'from a batch by Tom Lavedas ' ' Use as you want, only give me credit ' 'returns: 0 if drive exists and it's ready ' 1 if drive is not ready ' 2 if drive does not exist ' 3 if drive exists and disk is an audio CD ' 'supposed to run in any dos from MSDOS 3.1. Tested in Win 95 and DOS 6.2 'detects RAM disks and it's supposed to detect network units 'Does not use interrupt calls! 'uses temporary files in path set in variable TEMP so it's supposed to exist '--------------------------------------------------------------------------- tempfile$ = ENVIRON$("TEMP") + "\temp.txt" drive$ = LEFT$(UCASE$(d$), 1) + ":" IF drive$ = "B:" THEN OUT &H70, &H10 IF (INP(&H71) AND 7) = 0 THEN DiskReady = 2: EXIT FUNCTION END IF t$ = "c:\}{.bat" f = FREEFILE z$ = CHR$(34) OPEN t$ FOR OUTPUT AS #f PRINT #f, "@echo off" PRINT #f, "ctty nul" PRINT #f, "%comspec% /f /c vol %1 |find /c /I " + z$ + "vol" + z$ + "|choice /n/c210 >" + tempfile$ PRINT #f, "if errorlevel 3 goto End" PRINT #f, "%comspec% /f /c dir %1\!dummy!.@@@ | find /c " + z$ + "Dir" + z$ + " |choice/n/c10 >>" + tempfile$ PRINT #f, "if errorlevel 2 goto End" PRINT #f, "dir %1\!dummy!.@@@ | find /c " + z$ + "Audio CD" + z$ + " >>c:\temp.txt" PRINT #f, ":End" PRINT #f, "ctty con" CLOSE f SHELL t$ + " " + drive$ OPEN tempfile$ FOR INPUT AS #f a$ = "" WHILE NOT EOF(f): LINE INPUT #f, b$: a$ = a$ + b$: WEND CLOSE f SELECT CASE a$ CASE "0" DiskReady = 2 CASE "10" DiskReady = 1 CASE "210", "110" DiskReady = 0 CASE "211" DiskReady = 3 END SELECT KILL t$: KILL tempfile$ END FUNCTION FUNCTION SelectAFile$ (header$, ext$) ' ' User friendly file selector routine.Returns full path of a file ' by Antoni Gual agual@eic.ictnet.es ' Fully reprogrammed from a layout by William Yu ' ' Use as you want, only give me credit ' ' FEATURES: ' Does'nt use any interrupt call.(Very slow checking drives) ' Should not display DOS error messages when disk not ready ' Tested in Win 95/98 and DOS 6.1-Win 3.11. ' Auto detects num of screen lines set by main program. ' Tested with QBasic ' Not self contained, needs DiskReady routine ' No mouse! ' Returns to current dir before exiting ' In W95/98 displays LFN, but returns 8.3 format ' (QB file functions can't handle LFN) ' ' REMARKS: ' For non Win 9x users: It Runs faster if temp path is set to a RAM drive! ' Creates some auxiliar files: To do it, uses path in temp system variable ' To use it with DOS < 5.0 try changing constant DOS to 3 (Sorry..I.Can't test it) ' To avoid drive checking each time the routine is run, read comment ' 6 lines above EXIT FUNCTION '------------------------------------------------------------------------- 'PUT DOS TO 3 IF THE PROGRAM HAS TO RUN UNDER DOS BELOW 5.0 DIM z$ CONST dos = 5 'keys CONST kpgup = -&H49, kpgdn = -&H51 CONST kleft = -&H4B, kright = -&H4D, kup = -&H48, kdown = -&H50 CONST kenter = &HD, kesc = &H1B q$ = CHR$(34) 'colors CONST fgiuns = 7, bgiuns = 0, fgauns = 15, bgauns = 0 CONST fgisel = 12, bgisel = 0, fgasel = 15, bgasel = 4 'auxiliar files pth$ = ENVIRON$("TEMP") + "\" IF pth$ = "\" THEN PRINT "Sorry. The file selection routine requires TEMP variable to be set" EXIT FUNCTION END IF DIM auxf$(1 TO 3): auxf$(3) = pth$ + "}{drive.lst": auxf$(2) = pth$ + "}{dir.lst" auxf$(1) = pth$ + "}{file.lst" tempfile$ = pth$ + "temp.txt" 'Detect Nr of lines of screen DEF SEG = &H40 scrl = PEEK(&H84) + 1 DEF SEG DIM wd(0 TO 4, 1 TO 3) 'vertical window sizes CONST wintop = 8 winbot = scrl - 7: winheight = winbot - wintop + 1 'indexs CONST wdxpos = 0, wdwdth = 1, wdtop = 2, wdcur = 3, wdcount = 4 GOSUB detectwindows 'init wd(wdxpos, 1) = 8: wd(wdxpos, 2) = 38: wd(wdxpos, 3) = 68 IF win THEN wd(wdwdth, 1) = 24: wd(wdwdth, 2) = 24: wd(wdwdth, 3) = 6 ELSE wd(wdwdth, 1) = 12: wd(wdwdth, 2) = 8: wd(wdwdth, 3) = 6 END IF wd(wdtop, 1) = 1: wd(wdtop, 2) = 1: wd(wdtop, 3) = 1 'strings with windows width DIM t$(1 TO 3): FOR i = 1 TO 3: t$(i) = SPACE$(wd(wdwdth, i)): NEXT h$ = SPACE$(64) 'prepare command strings IF dos = 5 THEN IF win THEN x$ = " /Z" dosdirs$ = "DIR /AD /ON /B >" + auxf$(2) dosfiles$ = "DIR *." + ext$ + " /A-D /ON /B >" + auxf$(1) ELSE dosdirs$ = "DIR *.* |FIND " + q$ + "" + q$ + " >" + auxf$(2) dosfiles$ = "DIR *." + ext$ + " | FIND " + q$ + ":" + q$ + "|FIND /V " + q$ + "" + q$ + "|FIND /V " + q$ + ":\" + q$ + " >" + auxf$(1) END IF temp = INSTR(ext$, "."): IF temp THEN ext$ = MID$(ext$, temp + 1) 'check all possible drives and build a drive list file$ = auxf$(3): GOSUB filexist IF exist = false THEN f = FREEFILE: OPEN auxf$(3) FOR OUTPUT AS #f COLOR 7, 0: CLS : PRINT "Checking existing drives: please wait!" FOR i = ASC("A") TO ASC("Z") IF DiskReady(CHR$(i)) <> 2 THEN LSET t$(3) = "-[" + CHR$(i) + ":]-" PRINT #f, t$(3) END IF NEXT CLOSE #f END IF f = FREEFILE: OPEN auxf$(3) FOR INPUT AS #f w1 = 3: GOSUB ITEMCOUNT CLOSE f 'init screen SCREEN 0: COLOR 7, 1: CLS COLOR 14: LOCATE 1, 40 - LEN(header$) \ 2: PRINT header$; 'top rectangle LOCATE 3, 4: COLOR 9, 0: PRINT CHR$(218); STRING$(72, 196); CHR$(191) LOCATE 4, 4: PRINT CHR$(179); STRING$(72, 0); CHR$(179) LOCATE 5, 4: PRINT CHR$(192); STRING$(72, 196); CHR$(217) 'other rectangles FOR x1 = 1 TO 3: GOSUB rect: NEXT COLOR 14, 1: LOCATE scrl - 2, 2 PRINT "Up/Dn Pgup/PgDn Move cursor, Left/Right Change Panel, Enter Select, Esc Quit"; 'clear keyboard buffer WHILE LEN(INKEY$): WEND 'cursor will start in files' window actwin = 1 GOSUB CURDIR startdir$ = MID$(CURDIR$, 1, LEN(CURDIR$) - 1) updatedrive: f = FREEFILE: OPEN auxf$(3) FOR INPUT AS #f w1 = 3: GOSUB updatewin CLOSE f 'update dir list updatedir: GOSUB CURDIR SHELL dosdirs$ f = FREEFILE IF dos = 5 THEN OPEN auxf$(2) FOR APPEND AS #f: PRINT #f, ".": IF LEN(CURDIR$) > 3 THEN PRINT #f, ".." CLOSE f END IF OPEN auxf$(2) FOR INPUT AS #f w1 = 2: GOSUB ITEMCOUNT: GOSUB updatewin CLOSE f 'update file list SHELL dosfiles$ f = FREEFILE: OPEN auxf$(1) FOR INPUT AS #f w1 = 1: GOSUB ITEMCOUNT: GOSUB updatewin IF wd(wdcount, 1) = 0 THEN actwin = 2: w1 = 2: GOSUB updatewin CLOSE f 'keys loop 'program will stay in this loop unless window change or press enter or esc movecursor: w1 = actwin OPEN auxf$(actwin) FOR INPUT AS #f DO GOSUB updatewin DO: V$ = INKEY$: LOOP UNTIL LEN(V$) V = ASC(RIGHT$(V$, 1)): IF ASC(V$) = 0 THEN V = -V SELECT CASE V CASE kup: wd(wdcur, w1) = wd(wdcur, w1) - 1 IF wd(wdcur, w1) < 1 THEN wd(wdcur, w1) = 1 CASE kdown: wd(wdcur, w1) = wd(wdcur, w1) + 1 IF wd(wdcur, w1) > wd(wdcount, w1) THEN wd(wdcur, w1) = wd(wdcount, w1) CASE kpgup: wd(wdcur, w1) = wd(wdcur, w1) - winheight IF wd(wdcur, w1) < 1 THEN wd(wdcur, w1) = 1 CASE kpgdn: wd(wdcur, w1) = wd(wdcur, w1) + winheight IF wd(wdcur, w1) > wd(wdcount, w1) THEN wd(wdcur, w1) = wd(wdcount, w1) 'change active window CASE kleft: IF actwin > 1 THEN IF actwin <> 2 OR wd(wdcount, 1) > 0 THEN actwin = actwin - 1: GOSUB updatewin: CLOSE #f: GOTO movecursor END IF END IF 'change active window CASE kright: IF actwin < 3 THEN actwin = actwin + 1: GOSUB updatewin: CLOSE #f: GOTO movecursor END IF 'select file in file window, change dir or drive in other windows CASE kenter: WHILE DiskReady(newdrive$) = 1 err$ = "Disk " + newdrive$ + " not ready [R]etry/[C]ancel?": GOSUB errmsg IF a$ <> "R" THEN CLOSE f: SHELL "C:": GOTO updatedrive WEND SELECT CASE actwin 'select file and exit CASE 1: IF LEN(newfile$) THEN CLOSE f: TMP$ = CURDIR$ + newfile$ IF win THEN 'truename fails with filenames so i use it only with dir name doscmd$ = "TRUENAME |find " + q$ + ":\" + q$ + ">" + tempfile$ SHELL doscmd$ OPEN tempfile$ FOR INPUT AS f: LINE INPUT #f, TP$: CLOSE f TMP$ = TP$: IF LEN(TMP$) > 3 THEN TMP$ = TMP$ + "\" KILL tempfile$ doscmd$ = "DIR /A-D " + q$ + newfile$ + q$ + "|FIND " + q$ + ":" + q$ + "|FIND /V " + q$ + ":\" + q$ + ">" + "tempfile$" SHELL doscmd$ OPEN tempfile$ FOR INPUT AS f: LINE INPUT #f, TP$: CLOSE f t$ = SPACE$(12): LSET t$ = TP$: MID$(t$, 9) = "." TMP$ = TMP$ + RTRIM$(t$) END IF SelectAFile$ = TMP$: EXIT DO ELSE actwin = actwin + 1: GOSUB updatewin END IF 'change dir CASE 2: IF newdir$ <> "." THEN IF (LEN(CURDIR$) > 3) OR (newdir$ <> "..") THEN CLOSE f: SHELL "CD " + newdir$: GOTO updatedir END IF END IF 'change drive CASE 3: CLOSE f: SHELL newdrive$: GOTO updatedrive END SELECT CASE kesc: CLOSE #f: SelectAFile$ = "": EXIT DO END SELECT LOOP KILL auxf$(1) KILL auxf$(2) 'KILL auxf$(3) 'this file (}{drive.lst) keeps the list of valid drives ' to avoid drive testing each time the routine is run ' put a REM in this line and erase the file at program's end. ' (Or don't erase it, if your drives are all fixed) IF win THEN z$ = q$ ELSE z$ = "" SHELL z$ + startdir$ + "\" SHELL "cd " + z$ + startdir$ CLS EXIT FUNCTION '---------------------------gosubs------------------------------------------ 'update window W1 from the contents of already opened file f updatewin: SEEK #f, 1 IF actwin = w1 THEN isactive = true ELSE isactive = false IF wd(wdcur, w1) < wd(wdtop, w1) THEN wd(wdtop, w1) = wd(wdcur, w1) IF wd(wdcur, w1) > (wd(wdtop, w1) + winheight - 1) THEN wd(wdtop, w1) = wd(wdcur, w1) - winheight + 1 i = 1: j = wintop: k = wd(wdleft, w1) WHILE NOT EOF(f) AND j <= winbot LINE INPUT #f, a$ IF i >= wd(wdtop, w1) THEN LSET t$(w1) = a$ IF i = wd(wdcur, w1) THEN IF isactive THEN COLOR fgasel, bgasel ELSE COLOR fgisel, bgisel SELECT CASE w1 CASE 1: newfile$ = RTRIM$(a$) 'IF LEN(NEWFILE$) > 9 THEN MID$(NEWFILE$, 9) = "." CASE 2: newdir$ = RTRIM$(a$): IF win THEN newdir$ = q$ + newdir$ CASE 3: newdrive$ = MID$(t$(w1), 3, 2) END SELECT ELSE IF isactive THEN COLOR fgauns, bgauns ELSE COLOR fgiuns, bgiuns END IF LOCATE j, k: PRINT t$(w1); : j = j + 1 END IF i = i + 1 WEND LSET t$(w1) = "": COLOR fgiuns, bgiuns FOR j1 = j TO winbot LOCATE j1, k: PRINT t$(w1) NEXT RETURN 'GUI: draw a shadowed rectangle, dimensions in wd(?,x1) rect: COLOR 9, 7: LOCATE wintop - 1, wd(wdxpos, x1) - 1 PRINT CHR$(218); STRING$(wd(wdwdth, x1), 196); CHR$(191) FOR j = wintop TO winbot LOCATE j, wd(wdxpos, x1) - 1 PRINT CHR$(179); STRING$(wd(wdwdth, x1), 32); CHR$(179) NEXT j LOCATE winbot + 1, wd(wdxpos, x1) - 1 PRINT CHR$(192); STRING$(wd(wdwdth, x1), 196); CHR$(217) FOR j = wintop TO winbot + 1 LOCATE j, wd(wdxpos, x1) + wd(wdwdth, x1) + 1: COLOR 0 PRINT STRING$(2, 219) NEXT j LOCATE winbot + 2, wd(wdxpos, x1) + 2: PRINT STRING$(wd(wdwdth, x1) + 1, 219) RETURN 'save current dir and drive to recover it after routine's end CURDIR: SHELL "CD > c:\curr.dir" f = FREEFILE: OPEN "c:\curr.dir" FOR INPUT AS #f LINE INPUT #f, CURDIR$ IF LEN(CURDIR$) <> 3 THEN CURDIR$ = CURDIR$ + "\" curdrive$ = LEFT$(CURDIR$, 1) CLOSE f: KILL "c:\curr.dir" OPEN auxf$(3) FOR INPUT AS #f i = 0 DO: i = i + 1: LINE INPUT #f, a$: LOOP UNTIL INSTR(a$, curdrive$) CLOSE f wd(wdcur, 3) = i LSET h$ = CURDIR$ + "*." + ext$ LOCATE 4, 6: COLOR 10: PRINT h$; RETURN 'detect Windows 95: if detected, use LFN detectwindows: doscmd$ = "ver >" + tempfile$ SHELL doscmd$ f1 = FREEFILE: OPEN tempfile$ FOR INPUT AS #f1: win = false WHILE NOT EOF(f1) AND win = false LINE INPUT #f1, a$ IF INSTR(a$, "Windows") THEN win = true WEND CLOSE f1 RETURN 'check if a file exists filexist: f = FREEFILE: OPEN file$ FOR BINARY AS #f IF LOF(f) = 0 THEN exist = false: CLOSE #f: KILL file$ ELSE exist = true: CLOSE #f RETURN 'count items in list file ITEMCOUNT: j = 0: WHILE NOT EOF(f): LINE INPUT #f, a$: j = j + 1: WEND wd(wdcount, w1) = j: wd(wdcur, w1) = 1 RETURN 'displays an eror message and waits for a key errmsg: LSET h$ = err$ LOCATE 4, 6: COLOR 12: PRINT h$; a$ = UCASE$(INPUT$(1)): LSET h$ = "": LOCATE 4, 6: PRINT h$ RETURN END FUNCTION