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

Manage international preferences


there is a classic solution: blessed folders

these are things like 'extensions' 'tableau de bord' 'dossier menu pomme' that clutter my system folder. (BTW those are probably 'Extensions' 'Control Panels' and 'Apple Menu Folder' to you).

If folks just had a single language system and used software only in that language then you could hard code the names... but of course, there are all sorts of reasons folks can have the system in one language and apps in another, and even more than one other! [I even had a mac with a french system and an American finder... gives for strange messages sometimes]

So apple devised a way of identifying the 'blessed' folders other than by name. There are tons of them.. even temporary memory is a blessed folder!

But... what happened before this system? Well folks just used the names, so in the sample code in the FB books the seeking out of preference files uses a hard coded method. Staz did include a sample 'new way' of doing things at some point, but it seems that most folks used the books, not the code - including yourself tedd as Quarters made a 'Preferences' folder in my system!

I did code a DCOD - PLU_Prefs that did the work for folks...
Here is the source code: remember however... it was intended as a compact DCOD and not as sample code: To confuse matters, this is the version that isn't a DCOD, but this is how i tested before lumping it into a DCOD! You'll probably have to clean this up as the mail clients will mangle it a little... It also needs a 'STR#' id 4800 with entry 1 - the pref type... usually 'pref' entry 2 - the name of your application

a 'STR ' id -16397 with the info that the document will present when double-clicked and a 'pref' resource with an ID of 4800 giving the default application prefs.
'/------------------------------------------------ INFO -------
' preparation for a PrefStuff DCOD
' CALL "PrefStuff",0,(switch%,recAdr&,recLen%,resNum%)
' returns _noErr -> all ok
' or _rsrcNotFndErr, _osErr, etc.
' which should be considered fatal errs
'/--------------------------------------------------------------
' version alpha 5
' this successfully sets type = "pref" so that the sys icon appears
' & creator to "****" so that dble-clicking on icon doesn't start app
' and adds "STR " num -16397 so that double clicking gives correct
' message - youpee - 21/12/96
'/--------------------------------------------------------------
' switch% - call to _prefsRead,_prefsWrite,_prefsDefault
' recAdr& - address of record containing prefs
' recLen% - length of record containing prefs
' resNum% - number of pref resource
'           the type of the pref resource is contained in
'           a STR# bearing this same number

RESOURCES "MaMwS.rsrc"
',"APPLmA=9Fw","CODE",1,"Code Segment"
COMPILE 0, _STRresource_dimmedVarsOnly              '_appendRes

'
'RESOURCES "", "rsrcRSED","DCOD", 4800, "PLU/Prefs"
'str consts into not into STR# resource as i want this self contained
'only dimmed vars
'COMPILE 0, _dimmedVarsOnly_appendRes
'OUTPUT FILE "MaMwS.rsrc"              'saves time
'/------------------------------------------ CONSTANTS --------
_prefResNum     = 4800
_prefsDefault   =    1
_prefsRead      =    2
_prefsWrite     =    3
'/-------------------------------------------- GLOBALS --------
'DIM switch%                           'determines what was called
DIM result%                                         'returns err code
DIM resType&                                        'contains 4 letter resource type
DIM 31 prefName$                                    'name of doc in prefs folder
'DIM resNum%                           'passed id for STR# & pref rsrc
'DIM recAdr&                           'passed adr of pref record
'DIM recLen%                           'length of passed pref record
DIM curRes                                          'to backup and restore on leaving
DIM tempRes                                         'for use in FN
DIM resHndl&                                        'hndl for different resource
DIM totalStrings;0,createFlag                       'num strings in STR# & temp flag
DIM prefVRefNum                                     'volRefNum for prefs file
DIM prefDirID&                                      'directory ID for prefs file
DIM FSSpec.70                                       'FSSpec record
DIM crea&,type&                                     'info for FSSpec record
'DIM FSSpecAdr&
DIM tag                                             'misc vars
END GLOBALS
'/------------------------------------------ VARIABLES --------

'/-------------------------------------- END OF HEADER --------
GOTO "main"

LOCAL FN doCopyRes(sourceRes,destRes,myType&,myName$,myResNum)
    DIM osErr,prefAttrbs
    DIM hndl&
    '
    osErr = _noErr
    
    CALL USERESFILE(sourceRes)                      'get app resources
    hndl& = FN GET1RESOURCE(myType&,myResNum)       'get hndl to pref res
    LONG IF hndl&                                   'if ok
        prefAttrbs = FN GETRESATTRS(hndl&)          'get attrbs
        CALL DETACHRESOURCE(hndl&)                  'disconnect from app-ready for copy
        CALL USERESFILE(destRes)                    'set to prefs file
        'osErr = FN HNOPURGE(resHndl&)            'stop it disappearing during
        CALL ADDRESOURCE(hndl&,myType&,myResNum,myName$)
        IF FN RESERROR = 0 THEN CALL SETRESATTRS(hndl&,prefAttrbs)
        IF FN RESERROR = 0 THEN CALL CHANGEDRESOURCE(hndl&)
        IF FN RESERROR = 0 THEN CALL WRITERESOURCE(hndl&)
        'osErr = FN HPURGE(resHndl&)              'purgeable again
        osErr = FN RESERROR
        CALL RELEASERESOURCE(hndl&)
        hndl& = &DEADBEEF                           'will fail if reused—take out in final
        CALL CLOSERESFILE(destRes)
        CALL USERESFILE(sourceRes)                  'put back in place
    XELSE
        osErr = _resNotFound
    END IF
END FN = osErr
'
' these next two are copied and inspired by routines posted by
' RickJBrown, in answer to someone else's question about alias.
'
' puts tpgether a FSSpec record and returns a -43 error as, of
' course, the file doesn't exist yet - just ignore error, but
' record is ok for next call
' Call as follows
'  osErr = FN FSMakeFSSpec (volRefNum%, dirID&, fileName$, @spec)
' where spec is a 70 byte record
' and other information is standard - obtained from findFolder
' in this case
'
LOCAL FN FSMakeFSSpec(vRefNum,dirID&,fileName$,FSSpecAdr&)
    DIM osErr, fileNameAdr&
    fileNameAdr& = @fileName$
    ` CLR.W   -(SP)
    ` MOVE.W  ^vRefNum, -(SP)
    ` MOVE.L  ^dirID&, -(SP)
    ` MOVE.L  ^fileNameAdr&, -(SP)
    ` MOVE.L  ^FSSpecAdr&, -(SP)
    ` MOVE.W  #$0001, D0
    ` DC.W    $AA52
    ` MOVE.W (SP)+,^osErr
END FN = osErr

'/------------------------------------------ FUNCTIONS --------
' for the moment, implement as a FN
'ENTERPROC% (switch%,recAdr&,recLen%,resNum%)

LOCAL FN prefStuff(switch%,recAdr&,recLen%,resNum%)
    '
    result = _noErr                                 'default initialization
    prefVRefNum = 0                                 '       -->>--
    curRes = FN CURRESFILE                          'get active resource file
    '
    DEFSTR LONG
    resHndl&=FN GETRESOURCE(_"STR#",resNum)         'hndle to resource
    LONG IF resHndl& > 0                            'make sure handle valid
        totalStrings={[resHndl&]}                   '1st word in
        hndl=totalStrings%
        LONG IF totalStrings > 1                    'are there at least 2?
            resType& = CVI(STR#(resNum,1))          'get from STR#
            prefName$ = STR#(resNum,2)              'get from STR#
        XELSE
            result = _resNotFound                   'say the error
            'it would be better to have a _strNotFound error here
            'so there is no confusion as to where the error is
            'but i can't find one...
        END IF
        CALL RELEASERESOURCE(resHndl&)              'release resource from mem
        resHndl& = &DEADBEEF                        'will fail if reused—take out in final
    XELSE
        result = _resNotFound                       'say the error
    END IF
    DEFSTR WORD                                     'restore to default
    IF result <> _noErr THEN GOTO "PLU:End"         'if error then get out
    '
    'get the volRefNum & DirID of prefs folder
    'not needed if just getting default from app
    'this needed to complete Spec record
    '
    LONG IF switch <> _prefsDefault
        result = FN FINDFOLDER(_kOnSystemDisk,_kPreferencesFolderType,_kCreateFolder, ¨
                               prefVRefNum, prefDirID&)
    END IF
    ' if bad then just get out
    IF result <> _noErr THEN GOTO "PLU:End"
    '
    SELECT switch
        CASE _prefsDefault
            GOSUB "PLU:defaultPrefs"
        CASE _prefsRead
            'Look for pref file in system prefs folder. If not found create it and
            'copy in default prefs - on return recAdr& contains default prefs.
            '
            GOSUB "PLU:openResFile"
            LONG IF result = _noErr
                LONG IF createFlag = 0
                    CALL USERESFILE(tempRes)        'set to prefs file
                    resHndl& = FN GET1RESOURCE(resType&,resNum)'get hndl& to resource
                    LONG IF resHndl&                'we got it, copy into record
                        BLOCKMOVE [resHndl&], recAdr&, recLen%
                        CALL RELEASERESOURCE(resHndl&)
                        resHndl& = &DEADBEEF        'will fail if reused—take out in final
                    XELSE
                        result = _resNotFound
                    END IF
                    '
                    CALL CLOSERESFILE(tempRes)
                XELSE
                    'as i just created the prefs file, i must copy default ones in
                    'first open res fork and try and get a refence number on pref file
                    tempRes = FN HOPENRESFILE(prefVRefNum,prefDirID&,prefName$,_fsRdWrPerm)
                    result = FN RESERROR
                    'copy pref resource from app to prefs
                    IF result = _noErr THEN ¨ 
                            result = FN doCopyRes(curRes,tempRes,resType&,prefName$,resNum)
                    'if ok then init default prefs
                    IF result = _noErr THEN GOSUB "PLU:defaultPrefs"
                END IF
            END IF
        CASE _prefsWrite
            'Look for prefs file in System Prefs folder. If not found create it
            'and copy current prefs from recAdr& unchanged. On return recAdr& unchanged
            GOSUB "PLU:openResFile"
            LONG IF result = 0
                CALL USERESFILE(tempRes)            'set to prefs res
                resHndl& = FN GET1RESOURCE(resType&,resNum)
                LONG IF resHndl&                    'we got it, go copy record in
                    BLOCKMOVE recAdr&, [resHndl&], recLen%
                    CALL CHANGEDRESOURCE(resHndl&)
                    CALL WRITERESOURCE(resHndl&)
                    CALL RELEASERESOURCE(resHndl&)
                    resHndl& = &DEADBEEF            'will fail if reused—take out in final
                XELSE
                    result = _resNotFound
                END IF
                CALL CLOSERESFILE(tempRes)
            END IF
    END SELECT
    '
    GOTO "PLU:End"                                  'jump over subroutines
    '----------------------------------------- SUBROUTINES ------
    "PLU:openResFile"
    '------------------------------------------------------------
    'This opens the resource file - if it fails it assumes that it
    'doesn't exist and creates it. Only then does it give an error
    'createFlag is a flag to let me know if i created the prefs
    'in which case i need to use the default prefs if i'm reading in
    createFlag = 0
    'opens the res file and gives me the refernce number
    tempRes = FN HOPENRESFILE(prefVRefNum,prefDirID&,prefName$,_fsRdWrPerm)
    'if the error is 1, then i couldn't open - i assume then that the
    'file doesn't exist and set about creating it
    LONG IF tempRes = -1
        'set the type and creator info, and info on default system script
        crea& = _"****" : type& = _"pref" : tag = _smSystemScript
        'call to make the spec record - this returns a -43 err which is ignored
        result = FN FSMakeFSSpec(prefVRefNum,prefDirID&,prefName$,@FSSpec)
        'this is the real work - it creates a file with a resource fork in the
        'right place, with the correct type and creator, name etc.
        CALL FSPCREATERESFILE(#@FSSpec,crea&,type&,tag)
        'check if all went ok
        result = FN RESERROR
        'and continue if still ok
        LONG IF result = _noErr
            'no, again try to open the resource fork and get a reference number
            tempRes = FN HOPENRESFILE(prefVRefNum,prefDirID&,prefName$,_fsRdWrPerm)
            'this "STR " gives information if the user dble-clicks the prefs file
            'set up the information for the copy, using vars that i no longer need
            type& = _"STR " : tag = -16397
            'copy in the resource from app
            result = FN doCopyRes(curRes,tempRes,type&,prefName$,tag)
            'it's not too important if this fails - so i won't abort
            'set the flag saying creation went ok
            createFlag = 1
        END IF
    END IF
    RETURN
    '------------------------------------------------------------
    "PLU:defaultPrefs"
    '------------------------------------------------------------
    'This copies default prefs from your pref resource in your app.
    'The type of the resource (for example 'PRFN') must be in first
    'string of the STR# resource with its resNumber identical to the
    'resNum passed on entry. The resNumber of this resource will
    'also be identical to this number.
    resHndl& = FN GET1RESOURCE(resType&,resNum)
    LONG IF resHndl&
        BLOCKMOVE [resHndl&], recAdr&, recLen%
        CALL RELEASERESOURCE(resHndl&)
        resHndl& = &DEADBEEF                        'will fail if reused—take out in final
    XELSE
        result = _resNotFound
    END IF
    RETURN
    '------------------------------------------------------------
    "PLU:End"
    CALL USERESFILE(curRes)                         'put back in place
END FN = result

'EXITPROC% = result                    'return result
'RETURN                                'get out

'------------------------------------------------------------

"main"
WINDOW 1
DIM fred,test
DIM RECORD testRec
    DIM foo1
    DIM foo2
    DIM foo3
    DIM foo4
    DIM foo5
    DIM foo6
    DIM foo7
    DIM foo8
    DIM foo9
    DIM foo10
DIM END RECORD .testRec
DIM my.testRec

my.foo1 = 1
my.foo2 =2
my.foo3 =3
my.foo4 =4
my.foo5 =5
my.foo6 =6
my.foo7 =7
my.foo8 =8
my.foo9 =9
my.foo10 =10
test = _prefsRead
FN prefStuff(test,@my,_testRec,_prefResNum)
'CALL "PLU/Prefs",0, fred%,(%test,@my,%_testRec,%_prefResNum)
'CALL "DCOD", 4800, fred%,(%test,@my,%_testRec,%_prefResNum)

PRINT HEX$(my.foo1)
PRINT HEX$(my.foo2)
PRINT HEX$(my.foo3)
PRINT HEX$(my.foo4)
PRINT HEX$(my.foo5)
PRINT HEX$(my.foo6)
PRINT HEX$(my.foo7)
PRINT HEX$(my.foo8)
PRINT HEX$(my.foo9)
PRINT HEX$(my.foo10)

PRINT fred

DO
UNTIL LEN(INKEY$)
Jonathan