LONG FILENAMES FROM DOS, by Alex Warren · firstname.lastname@example.org
One of the very nice things that Microsoft did for us with Windows 95 was add support for ridiculously long filenames, up to 256 characters in length, if I remember correctly. No longer do we have to put up with cryptic filenames such as "LETMRB01.DOC" - instead we be can more creative and save files with names like "Letter to Mr Brown draft 1 about the boiler that exploded last March which still hasn't ruddy well been fixed yet even though I've phoned them three times I mean I despair I really really do something ought to be done about it.doc" and other such silly things.
At least... almost. We can use long filenames from our Windows apps, but what if we want to use long filenames from our QuickBasic programs? If we try
OPEN "THE SILLY LONG FILENAME.TXT" FOR INPUT AS #1
we get a "Bad Filename" error. But if you look at the version of EDIT included with DOS 7, it's clearly a DOS program... but look! Look at all those lovely long filenames! Isn't it amazing! Isn't it? Oh well...
Yes, it is possible - we can access long filename functions from DOS (well, a Windows 95 DOS session anyway). But it's not very easy to do in QuickBasic - though it can be done. Really. If you look in the ABC Packets you'll hopefully see that I posted some code a few months back which will do just that, from QB. A newer version of the program (v1.5) is contained within this fanzine, in 11lfndos.bas
If you run this rather un-user-friendly program from Windows 95 (it won't work with QBasic, you'll need QB4.5 or better loaded with /L) you'll see that it works.
How? Well, it's all quite simple really, though it took me a while to figure it out - maybe because I'm stupid, I dunno... anyway: basically, all each subroutine does is call interrupt 21h (that means the hexadecimal number 21) with the required service (specified by inregs.ax) and the required tags (specified by the other inregs thingies). Usually these tags include a string, and to pass a string to an interrupt you need to use a pointer to that string. A pointer is basically a number referring to a specific part of the computer's memory, and is a concept that will familiar to the C++ programmers amongst us, though it's not often used in BASIC unless you're writing more complex programs using C++ libraries and such. If you look at the information for interrupts you see in books and on Ralf Brown's list, you'll see things such as "DS:DX - ASCIZ pathname". This means a string where DS (i.e, inregs.ds) specifies the segment in memory of the string, and DX specifies the string's location within that segment. ASCIZ just means a string with a null character at the end - you can get one of these in BASIC by using CHR$(0).
In QB, we can get the segment of the string using VARSEG and the string's location within that segment with VARPTR. This appears to work for fixed-length strings only - if you want to do the same with a variable length string you must use SADD in place of VARPTR.
For example, if pathname is a string containing a pathname, we can pass it to the interrupt using this:
inregs.ds = VARSEG(pathname)
inregs.dx = VARPTR(pathname)
Note that other services may want the pathname/filename to be in other places instead of DS:DX, so check your documentation. (If you have the time you can download the entire of Ralf Brown's interrupts list from his website - it's about 8mb).
So, this program should be enough to get you started using long filenames from QB. It wouldn't be too hard to make a library from it if you wanted to, and it would be quite a useful library to have. However, these long filename functions obviously won't work in anything less than Windows 95. There are equivalent functions though, that work with short filenames. It would be a good idea to make a library that detected whether LFN functions were available, and if not then replace the LFN services with the equivalent SFN service. This is (almost) really easy - the equivalent of an LFN service 71xxh is xx00h, so all you would need to do hopefully would be to add that to the int21 subroutine. (To detect whether LFN functions are available, look at the program - this detects for LFN functions when it starts). That would keep users of Windows and users of DOS (however rare they are these days) happy. Also, bear in mind that LFN functions require Windows to be running - if you are running in MS-DOS mode (not in an MS-DOS window from Win95) then the LFN functions won't work.