home *** CD-ROM | disk | FTP | other *** search
AmigaBASIC Source Code | 1989-04-05 | 15.7 KB | 355 lines |
- 'As you probably already know; AmigaBasic SUCKS! It can't handle structures.
- 'Yet another shoddy Microsoft product. Actually, this is about the fifth
- 'basic program I've ever written. The other four were done in a 15 week
- 'course some years back in college. I'm an assembly programmer, and usually
- 'I don't touch this crap, but someone had to write an example. The code is
- 'probably not too efficient, but it's the first basic program I've written
- 'in years, the first in AmigaBasic, and was done in about 2 hours (I had to
- 'read the AmigaBasic instruction book. Really.) I cannot begin to tell you
- 'how excruciating the AmigaBasic editor is to an assembly programmer.
-
- CLS
- LOCATE 1,8
- PRINT "Demo AmigaBasic program using the FileIO requester library."
- LOCATE 2,11
- PRINT "Literally hacked together by Jeff Glatt (dissidents)"
-
- DEFLNG a-Z 'IMPORTANT! All variables are longs (for the library calls)
-
- 'requester.bmap and exec.bmap must be in the current directory
- LIBRARY "requester.library"
- LIBRARY "exec.library"
-
- DECLARE FUNCTION AllocMem() LIBRARY
-
- DECLARE FUNCTION DoFileIOWindow() LIBRARY 'These are in the FileIO lib.
- DECLARE FUNCTION GetFullPathname() LIBRARY 'Other functions in the lib do
- DECLARE FUNCTION GetFileIO() LIBRARY 'not return values, and so do not
- DECLARE FUNCTION AutoFileMessage() LIBRARY 'need declaring
- DECLARE FUNCTION AutoPrompt3() LIBRARY
- DECLARE FUNCTION TypeFilename() LIBRARY
- DECLARE FUNCTION UserEntry() LIBRARY
- DECLARE FUNCTION PromptUserEntry() LIBRARY
- DECLARE FUNCTION GetRawkey() LIBRARY
- DECLARE FUNCTION DecodeRawkey() LIBRARY
-
- 'First we must get a buffer for the pathname. The FileIO's DoFileIOWindow()
- 'will copy the complete pathname there. The complete path looks just like
- 'a CLI line:
-
- ' Diskname:TopDrawer/SubDrawer...etc...BottomDrawer/Filename
-
- 'Of course, the user may only select a disk or drawer, but no filename, and
- 'so the final "/Filename" will not be there. Also, the Filename might not
- 'be in any drawers, and so it will appear directly after the diskname. If
- 'this format looks weird to you, you need to learn about the CLI.
- 'We'll get our buffer from Exec via AllocMem().
-
- MEMF.PUBLIC = 1 : MEMF.CLEAR = 65536 : BUFSIZE = 202
- BufferPtr=AllocMem(BUFSIZE,MEMF.PUBLIC+MEMF.CLEAR) 'A buffer to copy the pathname to
- IF BufferPtr = 0 THEN GOTO NoMem1
-
- 'Now we need to get a buffer if we want to allow the user to utilize the
- 'extention match feature.
- BUFSIZE2 = 24
- ExtPtr=AllocMem(BUFSIZE2,MEMF.PUBLIC+MEMF.CLEAR)
- IF ExtPtr = 0 THEN GOTO NoMem2
-
- FileIO=GetFileIO(0) 'Get the address of the FileIO structure
- 'Actually you don't need to pass the 0, but AmigaBasic seems to want something...
-
- IF FileIO = 0 THEN GOTO CloseUp1 '0 means that you don't have a FileIO.
-
- 'Set the FileIO's Buffer field to our allocated PathBuffer's address
- POKEL FileIO+248,BufferPtr
-
- POKEL FileIO+222,ExtPtr 'Set the address of the extention string
-
- 'Set the title that will displayed in the FileIO window. This can be changed
- 'for each call so that you might have the title read "Save File" during a
- 'save routine, for example.
-
- WindowTitle$ = "FileIO Basic Example"
- POKEL FileIO+244,SADD(WindowTitle$)
-
- 'Set the fore pen, back pen, and draw mode for title bar routines to some
- 'defaults. We always need to do this in case the requester is in use by
- 'another program and we get automatic title bar file entry. To demo this,
- 'run this program twice simultaneously with one of them having the file
- 'requester displayed. Note that the title bar entry appears in the 2nd
- 'window. This is because only 1 task can be displaying the FileIO requester
- 'at a time. Other simultaneous calls get redirected to the title bar entry.
-
- POKE FileIO+261,1 'JAM2 DrawMode
- POKE FileIO+262,1 'PenA = Color1
- POKE FileIO+263,0 'PenB = Color0
- DIM Pathname$(202)
- DIM Filename$(30)
- DIM VolName$(30)
- DIM DrawerName$(132)
-
- Again:
-
- 'First I'll demo 2 things you can do with the Flags field of the FileIO. The
- 'FileIO is a structure, and our variable name FileIO is just the start (base)
- 'of that structure (block of memory). We can access any field of the FileIO
- 'by PEEKing and POKEing various fields. You should POKE a value into the
- 'FileIO, and retrieve a value by PEEKing. Some fields are larger than 1 byte
- 'and you must use PEEKW, PEEKL, POKEW, POKEL. You need to know how far away
- 'the field is from the base of the structure. The flags field is one byte
- 'away, so to access it we PEEK or POKE to FileIO+1. The previous initialization
- 'we did for the window title was at an offset of 244 from the base, and was
- 'a LONGWORD (4 bytes). That's why I added the L to POKE.
-
- 'Since the user can always set these features up for himself via the 10
- 'functions keys (see the doc), normally you wouldn't bother with the Flags
- 'field unless you had something particular in mind...but for a demo...
-
- LOCATE 3,1
- 'See if the user wants only those filenames that end in a certain extention
- 'Actually, the user can change this string after the requester opens via F4
- 'so you should never assume that the returned filename will indeed end in
- 'this string. If the user changes it, he probably knows what he's doing. Ha, ha.
- INPUT "Do you want only those filenames with a certain extention (y or n)";Ans$
- IF Ans$ <> "y" THEN GOTO SkipExt
- INPUT "Type the extention, 14 chars max (i.e., .device)";EXT$
- extsize=LEN(EXT$)
- IF extsize = 0 THEN GOTO SkipExt
- IF extsize > 13 THEN GOTO SkipExt 'too long
- 'Enable the extention match feature of the FileIO
- POKE FileIO+1,4 'Turn on extention match feature only
- POKEW FileIO+226,extsize 'Get the length of the string
- 'Copy the user string to the extention buffer
- EXT$ = UCASE$(EXT$) 'must be upper case
- FOR i = 0 TO 13
- char$ = EXT$(i)
- value = ASC(char$)
- POKE(BufferPtr+i),value
- NEXT i
- POKE(BufferPtr+14),0
- GOTO DoIO
-
- SkipExt: 'Otherwise, at least suppress the .info files
- POKE FileIO+1,128
-
- DoIO:
- Result=DoFileIOWindow(FileIO,0) 'do the FileIO selection on WB screen
-
- IF Result <> -1 THEN GOTO CheckError '-1 means the user selected CANCEL.
- message$ = "User selected CANCEL."+CHR$(0)
- CALL AutoMessageLen(SADD(message$),WINDOW(7),21) '21 is the number of chars in Message$ not counting the CHR$(0)
- GOTO CloseUp2
-
- CheckError:
- '0 means the FileIO window couldn't open due (probably due to lack of mem).
- 'Too bad! You'll have to get the filename some other way. Maybe an INPUT statement?
- IF Result <> 0 THEN GOTO GotPathname
- 'Message number 0 in the FileIO lib says "Out of memory for this operation"
- Result=AutoFileMessage(0,WINDOW(7))
- INPUT "Type path: ";Pathname$
- ParseString(FileIO,SADD(Pathname$))
-
- GotPathname: 'We got a selection from the user!
- 'Now, our PathBuffer$ has the complete pathname. The FileIO's Filename
- 'buffer has just the Filename separated from the disk and drawer names
- '(which are also separated into their own FileIO buffers). Let's copy out
- 'each of these buffers so that we can print the separate pieces, plus copy
- 'the complete path.
-
- Pathname$ = ""
- FOR i = 0 TO 202
- value = PEEK(BufferPtr+i)
- IF value = 0 THEN GOTO CopyFN
- char$ = CHR$(value)
- Pathname$ = Pathname$+char$
- NEXT i
-
- CopyFN:
- Filename$ = ""
- 'Copy out the Filename to Filename$.
- FOR i = 0 TO 30
- value = PEEK(FileIO+2+i)
- IF value = 0 THEN GOTO CopyDrawer
- char$ = CHR$(value)
- Filename$ = Filename$+char$
- NEXT i
-
- CopyDrawer: 'Copy out all the drawers
- DrawerName$ = ""
- FOR i = 0 TO 132
- value = PEEK(FileIO+32+i)
- IF value = 0 THEN GOTO CopyVol
- char$ = CHR$(value)
- DrawerName$ = DrawerName$+char$
- NEXT i
-
- CopyVol: 'Copy out the diskname
- VolName$ = ""
- FOR i = 0 TO 30
- value = PEEK(FileIO+164+i)
- IF value = 0 THEN GOTO PrintPath
- char$ = CHR$(value)
- VolName$ = VolName$+char$
- NEXT i
-
- PrintPath: 'Print out all the info available in the FileIO
- LOCATE 7,1
-
- noExt:
- CALL AutoMessage(SADD(Pathname$),WINDOW(7)) 'display our complete path in a
- 'requester first
-
- PRINT
- 'Let's print out the disk, drawers, and filename.
- PRINT "The Diskname is ",VolName$
- PRINT "The Drawernames are ",DrawerName$
- PRINT "The Filename is ",Filename$ 'Note that there is no Filename if the
- 'user selected only a disc or drawer.
-
- 'Let's get the amount of free disk space on the disk that the user chose.
- 'This could be important if we were trying to save something to this disk
- 'and there wasn't enough room. Also, if the user typed in a disc or drawer
- 'that didn't exist or he refused to place that disc in the drive, the
- 'returned default disc is ":" which is the current directory.
- PRINT "Free disk space: ",PEEKL(FileIO+236)," bytes."
-
- 'Now if this is a loadable file, the FileIO has it's size. If it's only a
- 'disc name or dir, or the file doesn't exist, then the size = 0.
- extsize=LEN(Filename$) 'Did the user finally select a file?
- IF extsize = 0 THEN GOTO DiscOrDir 'Must be a disk or drawer only
- IF PEEKL(FileIO+240) = 0 THEN GOTO NoExist 'Aha! User typed in a Filename that doesn't yet exist
- PRINT "Size of file: ",PEEKL(FileIO+240)," bytes."
-
- ' Now, you might want to do a load or save routine using this user selected
- ' pathname. You can check the FileIO's FILE.BYTESIZE (FileIO+240) field to see if the
- ' user actually selected an existing file, or typed in a new, non-existant
- ' name. For example, say that the user selected a directory but not a file
- ' within the directory. The returned pathname might be
- ' DF0:SomeDrawerName
- ' In this case, the FILE.BYTESIZE field would be 0 and if you tried to "load"
- ' the file, you would get a DOS error message. Likewise, if the user types
- ' in a non-existant file name, this field is also 0, but you can open the
- ' file for writing (save). If the user's selected pathname is the name of
- ' an object file (not just a dir or disk), then this is the only time that
- ' FILE.BYTESIZE will not be 0. In fact, it will be the size of the file. In
- ' conclusion, if you were doing a load routine, you would do the following
- ' steps at this point:
- ' 1). Check if there is some name in the FileIO's Filename field. If not,
- ' this means that the user selected a disk or drawer only. Abort the load.
- ' 2). Check to see if the FILE.BYTESIZE field is 0. If it is 0, then the
- ' user has typed in a file that doesn't exist (in whichever dir that he
- ' finally chose). Display a message that says "File doesn't exist".
- ' 3). If the FILE.BYTESIZE is not 0, then you can open the file for reading
- ' and copy this many bytes into memory. Since AmigaBasic doesn't have a
- ' facility for loading blocks of bytes, I recommend the DOS library.
- '
- ' LIBRARY "dos.library"
- ' LIBRARY "intuition.library"
- ' DECLARE FUNCTION Open() LIBRARY
- ' DECLARE FUNCTION Read() LIBRARY
- ' DECLARE FUNCTION Write() LIBRARY
-
- ' Filehandle=Open(BufferPtr,1005&)
- ' IF Filehandle <> 0 THEN GOTO GotIt
- ' Message$ = "Cannot locate this file!"+CHR$(0) 'Oops Can't find it.
- ' CALL AutoMessageLen(SADD(Message$),WINDOW(7),24&)
- ' GOTO BadLoad
- 'GotIt:
- ' SetWaitPointer(WINDOW(7))
- ' Bytes=PEEKL(FileIO+240)
- ' DIM DataBuffer(Bytes) 'read the file into this 1-D array
- ' Error=Read(Filehandle,VARPTR(DataBuffer(0)),Bytes)
- ' CALL Close(Filehandle)
- ' ClearPointer(WINDOW(7)) 'must have intuition open
- ' IF Error = Bytes THEN GOTO GoodLoad
- ' boolean=AutoFileMessage(2&,WINDOW(7)) 'tell the user that an error occured
- ' GOTO BadLoad
- 'GoodLoad:
-
- ' You can now "pull out" data from DataBuffer as you need it (like we
- ' extracted data from FileIO except perhaps you might not want to
- ' convert the value to ascii via CHR$).
-
- ' If you were doing a save routine to disk, you would do the following:
- ' 1). Check if there is some name in the FileIO's Filename field. If not,
- ' this means that the user selected a disk or drawer only. Abort the save.
- ' 2). Check if FILE.BYTESIZE is not 0. If not 0, inform the user that this
- ' file already exists and if you save using this name, you will write
- ' over the other file. Ask the user if he wants to do the save anyway.
- ' 3). If FILE.BYTESIZE is 0, this file doesn't already exist. Check that the
- ' free disk space is greater than the number of bytes that we want to
- ' save, or else we'll run out of room during the save.
- '
- ' Let's say that you stored the data in a big 1-D array called DataTank
- ' and the number of bytes you want to save is 32.
- '
- ' Bytes=32&
- ' Filehandle=Open(BufferPtr,1006&)
- ' IF Filehandle <> 0 THEN GOTO CreateIt
- ' Message$ = "Cannot create the file!"+CHR$(0) 'Oops Can't save it.
- ' CALL AutoMessageLen(SADD(Message$),WINDOW(7),23&)
- ' GOTO BadSave
- ' SetWaitPointer(WINDOW(7))
- ' Error=Write(Filehandle,VARPTR(DataTank(0)),Bytes)
- ' CALL Close(Filehandle)
- ' ClearPointer(WINDOW(7))
- ' IF Error = Bytes THEN GOTO GoodSave
- ' boolean=AutoFileMessage(2&,WINDOW(7)) 'tell the user that an error occured
- ' GOTO BadSave
- 'GoodSave:
-
- Retry:
- message$ = "This has been a test of the FileIO library." + CHR$(0)
- Message2$ = "Do you want to retry?" + CHR$(0)
- boolean=AutoPrompt3(SADD(message$),SADD(Message2$),0,WINDOW(7))
- CLS
- IF boolean = 1 THEN GOTO Again
-
- 'Note how the lib automatically spaces these messages symmetrically
-
- message$ = "Example program and asm lib by Jeff Glatt" + CHR$(0)
- Message2$ = "(dissidents)" + CHR$(0)
- Message3$ = "Original FileIO by RJ Mical" + CHR$(0)
- boolean=AutoPrompt3(SADD(message$),SADD(Message2$),SADD(Message3$),WINDOW(7))
-
- CloseUp2:
-
- CALL ResetTitle(FileIO,WINDOW(7)) 'Maybe we changed it for the error msgs.
- CALL ReleaseFileIO(FileIO) 'Free the FileIO structure
-
- CloseUp1:
- CALL FreeMem(ExtPtr,BUFSIZE2)
-
- NoMem2:
- CALL FreeMem(BufferPtr,BUFSIZE)
-
- NoMem1:
- LIBRARY CLOSE
- END
-
- ' For these 2 errors, let's see how the SetTitle function works. This will
- ' display in the window's title bar string1 followed by string2, but unlike
- ' a requester, returns control back to the program. When we finally call
- ' ResetTitle, the original title is restored. We can call SetTitle without
- ' needing a ResetTitle inbetween and vica versa. Notice how this message
- ' appears in the window and requester title bars. Subsequent calls to these
- ' error routines (answer "Yes" to the again requester and cause another
- ' error) will change the title bar further. Yet, when we finally call
- ' ResetTitle upon exit, the initial title is restored. As you can see, these
- ' routines are good for posting error msgs that don't halt the program (like
- ' requesters) but remain visible for as long as they are needed.
-
- DiscOrDir:
- message$ = "Dir only - "+CHR$(0)
- 'String2 will be our Pathname
- CALL SetTitle(SADD(message$),SADD(Pathname$),FileIO,WINDOW(7))
- GOTO Retry
-
- NoExist:
- message$ = "This file doesn't exist."+CHR$(0)
- 'Note how we indicate that we don't want String2. You must have string1
- 'though, even it were just a space.
- CALL SetTitle(SADD(message$),0,FileIO,WINDOW(7))
- GOTO Retry
-
-