FB II Compiler

PG PRO

Debugging

Memory

System

Mathematics

Resources

Disk I/O

Windows

Controls

Menus

Mouse

Keyboard

Text

Fonts

Drawing

Sound

Clipboard

Printing

Communication

ASM

Made with FB

DISK I/O

Handle a plug-ins folder


The code to find plugIns in a 'plugIn' folder. If you want to test this, put it in a folder
* Create a folder named 'PlugIns' also in the folder
* Open ResEdit, create a new resource
* Use the File Info menu command in ResEdit to set the 'type' to 'PLuG'
* Create any dumb ressource in this file (i.e. an empty string)
* Save the file in the plugIns folder
* Give a it a name
* Duplicate it a few times
* Add other folders, text files etc to the PlugIns folder.
* Run the code below.
Warning:
The PlugIns folder may not be an alias (but if someone wants to add the code for...) however a plugIn ('type' of 'PLuG') may be an alias - it works, no code needed!
If you re-use this code you can customise the name of the folder and the resource type.
Possible uses:
* in a caving game, put all the caves in a folder named 'levels'
* in a graphic adventure game, put the sounds and picts that are too heavy in the main app in a separate 'Game Data' folder
* in a URL manager create a folder named URLs, and then invite the user to put an alias of it on their desktop. When the URL manager is launched it scans the folder and imports the URLs.
* invent your own uses - but do let me know
thanks to you all - too many to mention by name but you all know who you are ;-)

jonathan

'----------------CODE--
' beware of lines that your mail client may break
COMPILE 0, _dimmedVarsOnly
'
' This is adapted from the 'ProcessAllFolderItems.bas' file
' that is with the FB examples. It has been adapted so that
' it looks for a file names 'PlugIns' in the same folder as
' your app, and at the moment just loads the names of all the
' files it finds there.
' You should also check that the files in the folder are of
' the expected type. Users have been known to put lots of
' things in such a folder, particularly read me files that
' come with a plug-in.
'
'=== necessary constants ==='
_cInfoPBRecSize = 108
_WDPBRecSize = 52
_folderAttribBit = 4
'=== vars necessary for the demo ==='
' these are just for the demo - you don't have to keep
' the stuff in a handle, nor use this sort of constants.
DIM gMyPlugInArrayHndl&
'
DIM RECORD plugInRec
  DIM 31 piName$ 'filenames are limited to 31 chars
  DIM piRes%
  DIM piDCODnum% 'my plugIns are in DCODs, and yours?
DIM END RECORD .piRec
' this is just used to give me the record info as constants!
' i won't be using it.
END GLOBALS
'/--------
GOTO "main"
'/--------
CLEAR LOCAL MODE
LOCAL FN processFile(
folderVolume%,folderDirID&,fileName$,recPtr&,itemNum%)
' Warning from the original File
' This is where you should process the specified file. Note thet
' you SHOULD NOT rename the file. If you do, the ProcessFolder
' routine may become confused, and process files incorrectly (either
' by sending you the same file more than once, or by not sending you
' a file at all).
' If for some reason you really do need to rename the files, the way
' to do this is either to write the file to a different folder under
' a different name, or to read all the files in the source folder into
' a list in memory before processing them.
'
' The address of the pointer has been pushed up here in order that you
' fill it with the info you need. It has already been sized...
  DIM tempAdr&, tempValue%
  tempAdr&;4 = recPtr&
  tempAdr& = tempAdr& + (itemNum% *_piRec) +2
' leave first 2 bytes for counting the number of items
' and add one to length to cover the pascal type str$
  BLOCKMOVE @fileName$, tempAdr&, LEN( fileName$)+1
' increase the counter
' first grab it from the handle
  tempAdr&;4 = recPtr&
  tempValue%;2 = tempAdr&
  INC( tempValue%)
' now put it back
  % tempAdr&, tempValue%
'
  PRINT "Processing file: ";fileName$;" in folder:";folderVolume%;folderDirID&
END FN
'/-------------
' Info from original file:
' This routine processes all files in the specified folder. The folder may
' be specified using a working directory reference number, or, preferably,
' using a true volume number and a directory ID.
CLEAR LOCAL MODE
LOCAL FN processFolder( folderVolume%, folderDirID&, recPtr&)
  DIM pB.cInfoPBRecSize
  DIM 255 fileName$
  DIM err%
  DIM i%, itemCount%, fileCount%

  DEF BLOCKFILL( @pB, _cInfoPBRecSize, 0)
  pB.ioNamePtr& = @fileName$
  pB.ioVRefNum% = folderVolume%
  pB.ioFDirIndex% = 0
  pB.ioDirID& = folderDirID&
  err% = FN GETCATINFO (@pB)
  LONG IF( err% = _noErr)
    itemCount% = pB.ioDrNmFls%
' i have allowed for 99 at the moment...
    LONG IF( itemCount% < 100)
      FOR i% = 1 TO itemCount%
        pB.ioDirID& = folderDirID&
        pB.ioFDirIndex% = i%
        err% = FN GETCATINFO (@pB)
        LONG IF( err% = _noErr)
          LONG IF( PEEK ( @pB + _ioFlAttrib) AND _folderAttribBit%) = 0
' the next line checks that the file is of the right type
            LONG IF( pB.ioFlUsrWds.fdType& = _"PLuG")
' don't use itemCount% to count files as it will count folders too!
              FN processFile( folderVolume%,folderDirID&,fileName$,recPtr&,fileCount%)
' increase for next time
              INC( fileCount%)
            END IF
          XELSE
' if you are interested in the contents of folders within folders
' then you should come here...
'PRINT"*";folderVolume%, folderDirID&, fileName$
          END IF
        END IF
      NEXT
    XELSE
' we come here if there were too many items! - say so
      err% = _zTrue
    END IF
  END IF
END FN = err%
'/-------------
CLEAR LOCAL MODE
LOCAL FN getWDVolAndDirID%( WDRefNum%, @VolPtr&, @DirIDPtr&)
  DIM WDInfoPB.WDPBRecSize
  DIM 255 WDName$
  DIM err%
' prepare the block with zeros
  DEF BLOCKFILL( @WDInfoPB, _WDPBRecSize, 0)
  WDName$ = ""
  WDInfoPB.ioCompletion& = _nil ' make the call synchrone
  WDInfoPB.ioNamePtr& = @WDName$ ' pointer for name
  WDInfoPB.ioVRefNum% = WDRefNum% ' pass the working directory number
  WDInfoPB.ioWDIndex% = 0
  WDInfoPB.ioWDProcID& = 0
  WDInfoPB.ioWDVRefNum% = WDRefNum%
  err% = FN GETWDINFO( @WDInfoPB)
  % VolPtr&, WDInfoPB.ioWDVRefNum%
  & DirIDPtr&, WDInfoPB.ioWDDirID&
END FN = err%
'/-------------
CLEAR LOCAL MODE
'----- come here before changing the default folder -----
LOCAL FN seekBlessedFolder( folderName$, recPtr&)
  DIM WDRefNum%
  DIM folderVolume%
  DIM folderDirectory&
  DIM err%, oldDefault%
'
' before starting, grab the current folder to restore on leaving
' like with grafports and resources...
  oldDefault% = FOLDER( "", 0)
' get the refnum of the targetted folder in the current default folder
  WDRefNum% = FOLDER( folderName$, SYSTEM( _aplVol))
' translate to an orthodox working directory reference number
  err% = FN getWDVolAndDirID%( WDRefNum%, folderVolume%, folderDirectory&)
' use working directory reference number to specify folder to process
'
' you can use either of these two following lines, just
' remm out the other one and look at the difference
  err% = FN processFolder( WDRefNum%, 0, recPtr&)
'err% = FN processFolder( folderVolume%, folderDirectory&)
' now restore the initial folder
  oldDefault% = FOLDER( "", oldDefault%)
END FN
'/-------------
"main"
' This is just roughing things together to show what happens
' you may use a handle like i have here, or you may find a better
' mechanism. Don't use a global, as that would defeat the object of
' having used LOCAL MODE...
'
DIM temp%, i%, tempAdr&
'
' temp% is set large, I don't allow 99 plug-ins later I can come back
' and resize the handle or do something else with it
temp% = 99 *_piRec
gMyPlugInArrayHndl& = FN NEWHANDLE( temp%)
DEF CLEARHANDLE( gMyPlugInArrayHndl&)
temp% = FN HLOCK( gMyPlugInArrayHndl&)
'
' put up a window just to see the results
WINDOW 1, "", (0,0)-(420,600)
TEXT _monaco, 9
' pass the name of your plug ins's folder here
' this is the only call you need! the rest is
' fluff to show the results.
FN seekBlessedFolder( "PlugIns", gMyPlugInArrayHndl&)
'
' now just do something to show that we have the info in the handle
PRINT"----------------------"
temp% = {[ gMyPlugInArrayHndl& ]}
FOR i% = 0 TO ( temp% -1)
  tempAdr&;4 = [@gMyPlugInArrayHndl&]
  tempAdr& = tempAdr& + (i% *_piRec) +2
  PRINT PSTR$( tempAdr&)
NEXT
' keep the window on screen so you can see it!
DO
UNTIL LEN(INKEY$)
' remember to do this before leaving
' good housekeeping
temp% = FN HUNLOCK( gMyPlugInArrayHndl&)
temp% = FN DISPOSHANDLE( gMyPlugInArrayHndl&)
'-------------END OF CODE -----------------------------