home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / fish / libraries / fileio_463 / fileio.lzh / BASIC / BasicFileIO (.txt) next >
AmigaBASIC Source Code  |  1991-02-08  |  18KB  |  399 lines

  1.  'As you probably already know; AmigaBasic SUCKS! It can't handle structures.
  2.  'Yet another shoddy Microsoft product. Actually, this is about the fifth
  3.  'basic program I've ever written. The other four were done in a 15 week
  4.  'course some years back in college. I'm an assembly programmer, and usually
  5.  'I don't touch this crap, but someone had to write an example. The code is
  6.  'probably not too efficient, but it's the first basic program I've written
  7.  'in years, the first in AmigaBasic, and was done in about 2 hours (I had to
  8.  'read the AmigaBasic instruction book. Really.) I cannot begin to tell you
  9.  'how excruciating the AmigaBasic editor is to an assembly programmer.
  10.  
  11.  CLS
  12.  LOCATE 1,8
  13.  PRINT "Demo AmigaBasic program using the FileIO requester library."
  14.  LOCATE 2,11
  15.  PRINT "Literally hacked together by Jeff Glatt (dissidents)"
  16.  
  17.  DEFLNG a-Z  'IMPORTANT! All variables are longs (for the library calls)
  18.  
  19.  'requester.bmap and exec.bmap must be in the current directory
  20.  LIBRARY "requester.library"
  21.  LIBRARY "exec.library"
  22.  
  23.  DECLARE FUNCTION AllocMem() LIBRARY
  24.  
  25.  DECLARE FUNCTION DoFileIOWindow() LIBRARY  'These are in the FileIO lib.
  26.  DECLARE FUNCTION GetFullPathname() LIBRARY 'Other functions in the lib do
  27.  DECLARE FUNCTION GetFileIO() LIBRARY       'not return values, and so do not
  28.  DECLARE FUNCTION AutoFileMessage() LIBRARY 'need declaring
  29.  DECLARE FUNCTION AutoPrompt3() LIBRARY
  30.  DECLARE FUNCTION TypeFilename() LIBRARY
  31.  DECLARE FUNCTION UserEntry() LIBRARY
  32.  DECLARE FUNCTION PromptUserEntry() LIBRARY
  33.  DECLARE FUNCTION GetRawkey() LIBRARY
  34.  DECLARE FUNCTION DecodeRawkey() LIBRARY
  35.  DECLARE FUNCTION RetrieveEntry() LIBRARY
  36.  
  37.  'First we must get a buffer for the pathname. The FileIO's DoFileIOWindow()
  38.  'will copy the complete pathname there. The complete path looks just like
  39.  'a CLI line:
  40.  
  41.  '  Diskname:TopDrawer/SubDrawer...etc...BottomDrawer/Filename
  42.  
  43.  'Of course, the user may only select a disk or drawer, but no filename, and
  44.  'so the final "/Filename" will not be there. Also, the Filename might not
  45.  'be in any drawers, and so it will appear directly after the diskname. If
  46.  'this format looks weird to you, you need to learn about the CLI.
  47.  'We'll get our buffer from Exec via AllocMem(). 
  48.   
  49.  MEMF.PUBLIC = 1 : MEMF.CLEAR = 65536 : BUFSIZE = 202
  50.  BufferPtr=AllocMem(BUFSIZE,MEMF.PUBLIC+MEMF.CLEAR) 'A buffer to copy the pathname to
  51.  IF BufferPtr = 0 THEN GOTO NoMem1 
  52.  
  53.  'Now we need to get a buffer if we want to allow the user to utilize the
  54.  'extention match feature.
  55.  BUFSIZE2 = 24
  56.  ExtPtr=AllocMem(BUFSIZE2,MEMF.PUBLIC+MEMF.CLEAR)
  57.  IF ExtPtr = 0 THEN GOTO NoMem2 
  58.  
  59.  FileIO=GetFileIO(0)  'Get the address of the FileIO structure
  60.                        'Actually you don't need to pass the 0, but AmigaBasic seems to want something...
  61.  
  62.  IF FileIO = 0 THEN GOTO CloseUp1 '0 means that you don't have a FileIO.
  63.  
  64.  'Set the FileIO's Buffer field to our allocated PathBuffer's address
  65.  POKEL FileIO+248,BufferPtr
  66.  
  67.  POKEL FileIO+222,ExtPtr 'Set the address of the extention string
  68.  
  69.  'Set the title that will displayed in the FileIO window. This can be changed
  70.  'for each call so that you might have the title read "Save File" during a
  71.  'save routine, for example.
  72.  
  73.  WindowTitle$ = "FileIO Basic Example"
  74.  POKEL FileIO+244,SADD(WindowTitle$)
  75.  
  76.  'Set the fore pen, back pen, and draw mode for title bar routines to some
  77.  'defaults. We always need to do this in case the requester is in use by
  78.  'another program and we get automatic title bar file entry. To demo this,
  79.  'run this program twice simultaneously with one of them having the file
  80.  'requester displayed. Note that the title bar entry appears in the 2nd
  81.  'window. This is because only 1 task can be displaying the FileIO requester
  82.  'at a time. Other simultaneous calls get redirected to the title bar entry.
  83.  
  84.  POKE  FileIO+261,1  'JAM2 DrawMode
  85.  POKE  FileIO+262,1  'PenA = Color1
  86.  POKE  FileIO+263,0  'PenB = Color0
  87.  DIM   Pathname$(202)
  88.  DIM   Filename$(30)
  89.  DIM   VolName$(30)
  90.  DIM   DrawerName$(132)
  91.   
  92. Again:
  93.   multNames = 0
  94.  
  95.  'First I'll demo 2 things you can do with the Flags field of the FileIO. The
  96.  'FileIO is a structure, and our variable name FileIO is just the start (base)
  97.  'of that structure (block of memory). We can access any field of the FileIO
  98.  'by PEEKing and POKEing various fields. You should POKE a value into the
  99.  'FileIO, and retrieve a value by PEEKing. Some fields are larger than 1 byte
  100.  'and you must use PEEKW, PEEKL, POKEW, POKEL. You need to know how far away
  101.  'the field is from the base of the structure. The flags field is the the first
  102.  'field, so to access it we PEEK or POKE to FileIO+0. The previous initialization
  103.  'we did for the window title was at an offset of 244 from the base, and was
  104.  'a LONGWORD (4 bytes). That's why I added the L to POKE.
  105.  
  106.  'Since the user can always set these features up for himself via the 10
  107.  'functions keys (see the doc), normally you wouldn't bother with the Flags
  108.  'field unless you had something particular in mind...but for a demo...
  109.  
  110.  LOCATE 3,1
  111.  'See if the user wants only those filenames that end in a certain extention
  112.  'Actually, the user can change this string after the requester opens via F4
  113.  'so you should never assume that the returned filename will indeed end in
  114.  'this string. If the user changes it, he probably knows what he's doing. Ha, ha.
  115.  INPUT "Do you want only those filenames with a certain extention (y or n)";Ans$
  116.  IF Ans$ <> "y" THEN GOTO SkipExt
  117.  INPUT "Type the extention, 14 chars max (i.e., .device)";EXT$
  118.  extsize=LEN(EXT$)
  119.  IF extsize = 0  THEN GOTO SkipExt
  120.  IF extsize > 13 THEN GOTO SkipExt 'too long
  121. 'Enable the extention match feature of the FileIO
  122.   POKEW FileIO+0,4            'Turn on extention match feature only
  123.   POKEW FileIO+226,extsize    'Get the length of the string
  124.   'Copy the user string to the extention buffer
  125.   FOR i = 0 TO 13
  126.     char$ = EXT$(i)
  127.     value = ASC(char$)
  128.     IF value > 64 AND value < 91 THEN value=value+32 'must be lower case
  129.     POKE(ExtPtr+i),value    
  130.   NEXT i 
  131.   POKE(ExtPtr+extsize),0
  132.   GOTO   Multiple  
  133. SkipExt:
  134.   'Otherwise, at least suppress the .info files
  135.   POKEW FileIO+0,128
  136.   
  137. Multiple:
  138.   'Ask about multiple filename selection
  139.   INPUT "Multiple Filename selection";Ans$
  140.   IF Ans$ <> "y" THEN GOTO DoIO
  141.   value = PEEKW(FileIO+0)
  142.   value = value OR 64
  143.   POKEW(FileIO+0),value
  144.   multNames = 1
  145.     
  146. DoIO:
  147.  Result=DoFileIOWindow(FileIO,0)  'do the FileIO selection on WB screen  
  148.  
  149.  IF Result <> -1 THEN GOTO CheckError    '-1 means the user selected CANCEL.
  150.  message$ = "User selected CANCEL."+CHR$(0)
  151.  CALL AutoMessageLen(SADD(message$),WINDOW(7),21) '21 is the number of chars in Message$ not counting the CHR$(0)
  152.  GOTO CloseUp2
  153.  
  154. CheckError:
  155.  '0 means the FileIO window couldn't open due (probably due to lack of mem).
  156.  'Too bad! You'll have to get the filename some other way. Maybe an INPUT statement?
  157.  IF Result <> 0 THEN GOTO GotPathname              
  158.  'Message number 0 in the FileIO lib says "Out of memory for this operation" 
  159.  Result=AutoFileMessage(0,WINDOW(7))
  160.  INPUT "Type path: ";Pathname$
  161.  CALL ParseString(FileIO,SADD(Pathname$))
  162.  GOTO CopyFN
  163.  
  164. GotPathname:       'We got a selection from the user!
  165.  'Now, our PathBuffer$ has the complete pathname of the last chosen item.
  166.  'The FileIO's Filename buffer has just the Filename separated from the disk
  167.  'and drawer names (which are also separated into their own FileIO buffers)!
  168.  'If no multiple filename select, let's copy out each of these buffers so
  169.  'that we can print the separate pieces, plus copy the complete path. If
  170.  'multiple select, the disk and drawer names are gotten from their respective
  171.  'buffers, but we'll call the FileIO function, RetrieveEntry(), to get and
  172.  'display each filename.
  173.  
  174.   fileEntry = 0
  175.  
  176. CopyDrawer: 'Copy out all the drawers 
  177.   DrawerName$ = ""
  178.   FOR i = 0 TO 132
  179.     value = PEEK(FileIO+32+i)
  180.     IF value = 0 THEN GOTO CopyVol
  181.     char$ = CHR$(value)
  182.     DrawerName$ = DrawerName$+char$    
  183.   NEXT i
  184.  
  185. CopyVol: 'Copy out the diskname 
  186.   VolName$ = ""
  187.   FOR i = 0 TO 30
  188.     value = PEEK(FileIO+164+i)
  189.     IF value = 0 THEN GOTO CopyFN
  190.     char$ = CHR$(value)
  191.     VolName$ = VolName$+char$    
  192.   NEXT i
  193.  
  194. CopyFN:
  195.   Filename$ = ""
  196.   IF multNames = 0 THEN GOTO RegName
  197.   fileEntry = RetrieveEntry(VARPTR(fileEntry),FileIO)
  198.   IF fileEntry = 0 THEN GOTO Retry  'No more multiple filenames
  199.   'get the fileEntry's EntryString (i.e. filename)
  200.   entry = PEEKL(fileEntry+8)
  201.   FOR i = 0 TO 30
  202.     value = PEEK(entry+5+i)
  203.     IF value = 0 THEN GOTO DoneFN
  204.     char$ = CHR$(value)
  205.     Filename$ = Filename$+char$    
  206.   NEXT i  
  207. DoneFN:
  208.   Pathname$ = VolName$ + DrawerName$ + Filename$
  209.   GOTO PrintPath
  210.  
  211. RegName:
  212.  'Copy out the Filename to Filename$.
  213.   FOR i = 0 TO 30
  214.     value = PEEK(FileIO+2+i)
  215.     IF value = 0 THEN GOTO CopyPath
  216.     char$ = CHR$(value)
  217.     Filename$ = Filename$+char$    
  218.   NEXT i
  219.  
  220. CopyPath:
  221.   Pathname$ = ""
  222.   FOR i = 0 TO 202
  223.     value = PEEK(BufferPtr+i)
  224.     IF value = 0 THEN GOTO PrintPath
  225.     char$ = CHR$(value)
  226.     Pathname$ = Pathname$+char$    
  227.   NEXT i 
  228.  
  229. PrintPath:   'Print out all the info available in the FileIO
  230.  'display our complete path in a requester first
  231.  CALL AutoMessage(SADD(Pathname$),WINDOW(7))
  232.  
  233.  CLS
  234.  LOCATE 8,1
  235.  'Let's print out the disk, drawers, and filename.
  236.  PRINT "The Diskname is ",VolName$
  237.  PRINT "The Drawernames are ",DrawerName$
  238.  PRINT "The Filename is ",Filename$ 'Note that there is no Filename if the
  239.                                     'user selected only a disc or drawer.
  240.   
  241.  'Let's get the amount of free disk space on the disk that the user chose.
  242.  'This could be important if we were trying to save something to this disk
  243.  'and there wasn't enough room. Also, if the user typed in a disc or drawer
  244.  'that didn't exist or he refused to place that disc in the drive, the
  245.  'returned default disc is ":" which is the current directory.
  246.  PRINT "Free disk space: ",PEEKL(FileIO+236)," bytes."
  247.  
  248.  'Now if this is a loadable file, the FileIO has it's size. If it's only a
  249.  'disc name or dir, or the file doesn't exist, then the size = 0. If multiple
  250.  'select, then we need to examine the fileEntry's size. Note that we ignore
  251.  'whatever the user may have typed in the Filename gadget, as we only care
  252.  'about displaying those filenames that he (multiple) clicked on. 
  253.  IF multNames = 0 THEN GOTO RegSize
  254.  mysize = PEEKL(entry+0)
  255.  GOTO DoSize
  256. RegSize:
  257.  extsize=LEN(Filename$)              'Did the user finally select a file?
  258.  IF extsize = 0 THEN GOTO DiscOrDir  'Must be a disk or drawer only 
  259.  mysize = PEEKL(FileIO+240)
  260.  IF mysize = 0 THEN GOTO NoExist  'Aha! User typed in a Filename that doesn't yet exist
  261. DoSize:
  262.  PRINT "Size of file:    ",mysize," bytes."
  263.  
  264.  ' Now, you might want to do a load or save routine using this user selected
  265.  ' pathname. You can check the FileIO's FILE.BYTESIZE (FileIO+240) field to see if the
  266.  ' user actually selected an existing file, or typed in a new, non-existant
  267.  ' name. For example, say that the user selected a directory but not a file
  268.  ' within the directory. The returned pathname might be
  269.  '            DF0:SomeDrawerName
  270.  ' In this case, the FILE.BYTESIZE field would be 0 and if you tried to "load"
  271.  ' the file, you would get a DOS error message. Likewise, if the user types
  272.  ' in a non-existant file name, this field is also 0, but you can open the
  273.  ' file for writing (save). If the user's selected pathname is the name of
  274.  ' an object file (not just a dir or disk), then this is the only time that
  275.  ' FILE.BYTESIZE will not be 0. In fact, it will be the size of the file. In
  276.  ' conclusion, if you were doing a load routine, you would do the following
  277.  ' steps at this point:
  278.  ' 1). Check if there is some name in the FileIO's Filename field. If not,
  279.  '     this means that the user selected a disk or drawer only. Abort the load.
  280.  ' 2). Check to see if the FILE.BYTESIZE field is 0. If it is 0, then the
  281.  '     user has typed in a file that doesn't exist (in whichever dir that he
  282.  '     finally chose). Display a message that says "File doesn't exist".
  283.  ' 3). If the FILE.BYTESIZE is not 0, then you can open the file for reading
  284.  '     and copy this many bytes into memory. Since AmigaBasic doesn't have a
  285.  '     facility for loading blocks of bytes, I recommend the DOS library.
  286.  '
  287.  '    LIBRARY "dos.library"
  288.  '    LIBRARY "intuition.library"   
  289.  '    DECLARE  FUNCTION  Open() LIBRARY
  290.  '    DECLARE  FUNCTION  Read() LIBRARY
  291.  '    DECLARE  FUNCTION  Write() LIBRARY 
  292.  
  293.  '    Filehandle=Open(BufferPtr,1005&)
  294.  '    IF Filehandle <> 0 THEN GOTO GotIt 
  295.  '        Message$ = "Cannot locate this file!"+CHR$(0) 'Oops Can't find it.
  296.  '        CALL AutoMessageLen(SADD(Message$),WINDOW(7),24&)
  297.  '        GOTO BadLoad
  298.  'GotIt:
  299.  '    CALL SetWaitPointer(WINDOW(7))
  300.  '    Bytes=PEEKL(FileIO+240)
  301.  '    DIM DataBuffer(Bytes)   'read the file into this 1-D array
  302.  '    Result=Read(Filehandle,VARPTR(DataBuffer(0)),Bytes)
  303.  '    CALL Close(Filehandle)
  304.  '    CALL ClearPointer(WINDOW(7))  'must have intuition open
  305.  '    IF Result = Bytes THEN GOTO GoodLoad 
  306.  '      boolean=AutoFileMessage(2&,WINDOW(7)) 'tell the user that an error occured
  307.  '      GOTO BadLoad
  308.  'GoodLoad:
  309.  
  310.  '    You can now "pull out" data from DataBuffer as you need it (like we
  311.  '    extracted data from FileIO except perhaps you might not want to
  312.  '    convert the value to ascii via CHR$).
  313.   
  314.  ' If you were doing a save routine to disk, you would do the following:
  315.  ' 1). Check if there is some name in the FileIO's Filename field. If not,
  316.  '     this means that the user selected a disk or drawer only. Abort the save.
  317.  ' 2). Check if FILE.BYTESIZE is not 0. If not 0, inform the user that this
  318.  '     file already exists and if you save using this name, you will write
  319.  '     over the other file. Ask the user if he wants to do the save anyway.
  320.  ' 3). If FILE.BYTESIZE is 0, this file doesn't already exist. Check that the
  321.  '     free disk space is greater than the number of bytes that we want to
  322.  '     save, or else we'll run out of room during the save.
  323.  '
  324.  '  Let's say that you stored the data in a big 1-D array called DataTank
  325.  '  and the number of bytes you want to save is 32.
  326.  '
  327.  '  Bytes=32&
  328.  '  Filehandle=Open(BufferPtr,1006&)
  329.  '  IF Filehandle <> 0 THEN GOTO CreateIt 
  330.  '        Message$ = "Cannot create the file!"+CHR$(0) 'Oops Can't save it.
  331.  '        CALL AutoMessageLen(SADD(Message$),WINDOW(7),23&)
  332.  '        GOTO BadSave
  333.  '  CALL SetWaitPointer(WINDOW(7))
  334.  '  Result=Write(Filehandle,VARPTR(DataTank(0)),Bytes)
  335.  '  CALL Close(Filehandle)
  336.  '  CALL ClearPointer(WINDOW(7)) 
  337.  '  IF Result = Bytes THEN GOTO GoodSave
  338.  '      boolean=AutoFileMessage(2&,WINDOW(7)) 'tell the user that an error occured
  339.  '      GOTO BadSave
  340.  'GoodSave:
  341.  
  342.   'If multiple filenames, go back to see if another one was selected
  343.   IF multNames = 1 THEN GOTO CopyFN
  344.  
  345. Retry:
  346.  message$  = "This has been a test of the FileIO library." + CHR$(0)
  347.  Message2$ = "Do you want to retry?" + CHR$(0)
  348.  boolean=AutoPrompt3(SADD(message$),SADD(Message2$),0,WINDOW(7))
  349.  CLS
  350.  IF boolean = 1 THEN GOTO Again
  351.  
  352.  'Note how the lib automatically spaces these messages symmetrically
  353.  
  354.  message$ = "Example program and asm lib by Jeff Glatt" + CHR$(0)
  355.  Message2$ = "(dissidents)" + CHR$(0)
  356.  Message3$ = "Original FileIO by RJ Mical" + CHR$(0)
  357.  boolean=AutoPrompt3(SADD(message$),SADD(Message2$),SADD(Message3$),WINDOW(7))  
  358.  
  359. CloseUp2: 
  360.  
  361.  CALL ResetTitle(FileIO,WINDOW(7)) 'Maybe we changed it for the error msgs.
  362.  CALL ReleaseFileIO(FileIO)        'Free the FileIO structure
  363.   
  364. CloseUp1:
  365.  CALL  FreeMem(ExtPtr,BUFSIZE2)
  366.  
  367. NoMem2:
  368.  CALL  FreeMem(BufferPtr,BUFSIZE)
  369.  
  370. NoMem1: 
  371.  LIBRARY CLOSE
  372.  END
  373.  
  374.  ' For these 2 errors, let's see how the SetTitle function works. This will
  375.  ' display in the window's title bar string1 followed by string2, but unlike
  376.  ' a requester, returns control back to the program. When we finally call
  377.  ' ResetTitle, the original title is restored. We can call SetTitle without
  378.  ' needing a ResetTitle inbetween and vica versa. Notice how this message
  379.  ' appears in the window and requester title bars. Subsequent calls to these
  380.  ' error routines (answer "Yes" to the again requester and cause another
  381.  ' error) will change the title bar further. Yet, when we finally call
  382.  ' ResetTitle upon exit, the initial title is restored. As you can see, these
  383.  ' routines are good for posting error msgs that don't halt the program (like
  384.  ' requesters) but remain visible for as long as they are needed.
  385.  
  386. DiscOrDir:
  387.   message$ = "Dir only - "+CHR$(0)
  388.  'String2 will be our Pathname
  389.   CALL SetTitle(SADD(message$),SADD(Pathname$),FileIO,WINDOW(7))
  390.   GOTO Retry
  391.  
  392. NoExist:
  393.   message$ = "This file doesn't exist."+CHR$(0)
  394.   'Note how we indicate that we don't want String2. You must have string1
  395.   'though, even it were just a space.
  396.   CALL SetTitle(SADD(message$),0,FileIO,WINDOW(7))
  397.   GOTO Retry
  398.  
  399.