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