home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!spool.mu.edu!olivea!mintaka.lcs.mit.edu!ogicse!news.u.washington.edu!stein.u.washington.edu!jesjones
- From: jesjones@stein.u.washington.edu (Jesse Jones)
- Newsgroups: comp.sys.mac.programmer
- Subject: Re: code for Finding Prefs File (long)
- Summary: A slick Prefs module written in Modula-2
- Message-ID: <1ilnplINNbck@shelley.u.washington.edu>
- Date: 9 Jan 93 05:28:21 GMT
- References: <D2150096.mv05jr@sproul.sproul.com>
- Organization: University of Washington, Seattle
- Lines: 224
- NNTP-Posting-Host: stein.u.washington.edu
-
-
- There has been some discussion lately about how to handle a preferences
- file, so I thought I'd post my code. It's nothing astounding, but I think
- it has some advantages over the previously posted code:
-
- 1) FindFolder and the high level file manager routines are used so
- the code is quit a bit easier to follow.
- 2) The GetPref procedure is passed a procedure parameter that is used to
- return a default preference if the preference is missing from the
- Prefs file.
- 3) Individual preferences are referenced by the ResType, resource name,
- and version number. If the version numbers don't match the default
- preference is returned.
-
-
- --Jesse
-
-
- Here is the interface for the Prefs module. It's written in SemperSoft
- Modula-2. HANDLE is compatible with any pointer to pointer and Mstring is
- a 256-byte string terminated with zero.
-
- DEFINITION MODULE Prefs; (* By Jesse Jones, 1992 *)
-
-
- FROM SYSTEM IMPORT HANDLE;
- FROM Types IMPORT Str255, Mstring;
-
-
- TYPE
- PrefsProc = PROCEDURE(): HANDLE;
-
- VAR
- PrefsName: Str255; (* Name of the Preferences file. *)
-
-
- PROCEDURE GetPref (rType, rName: Mstring; vers: INTEGER; default: PrefsProc): HANDLE;
- (* default is called if Prefs not present or version <> vers. *)
-
- PROCEDURE SetPref (rType, rName: Mstring; vers: INTEGER; data: HANDLE);
- (* Change or add a preference. *)
-
- PROCEDURE PrefPresent (rType, rName: Mstring; vers: INTEGER): BOOLEAN;
-
- PROCEDURE DeletePref (rType, rName: Mstring);
-
-
- END Prefs.
-
- And here is the implementation of the Prefs module.
-
- IMPLEMENTATION MODULE Prefs;
-
- (* Import list deleted *)
-
- (* Version numbers are saved in PVRS resources. These resources contain a
- single integer for the version number and are referenced by name, with
- the name being the concatenation of the preference resource type and
- the preference's name. *)
- PROCEDURE GetVersion (rType, rName: Mstring): INTEGER;
- VAR
- data: IntHandle;
- str : Str255;
- vers: INTEGER;
- err : OSErr;
- BEGIN
- str := StrToPStr(Concat(rType, rName));
- data := Get1NamedResource('PVRS', str);
- err := ResError();
- IF (err = resNotFound) OR (data = NIL) THEN
- vers := -1;
- ELSIF ErrCheck(err) THEN
- vers := data^^;
- ELSE
- vers := -1;
- END;
- RETURN vers;
- END GetVersion;
-
- PROCEDURE SetVersion (rType, rName: Mstring; version: INTEGER);
- VAR
- data : IntHandle;
- str : Mstring;
- err : OSErr;
- dummy: BOOLEAN;
- BEGIN
- str := Concat(rType, rName);
- data := Get1NamedResource('PVRS', StrToPStr(str));
- err := ResError();
- IF (err = resNotFound) OR (data = NIL) THEN
- data := CreateHandle(SIZE(INTEGER));
- data^^ := version;
- dummy := InsertResource('PVRS', str, 0, data, TRUE);
- ELSIF ErrCheck(err) THEN
- data^^ := version;
- dummy := ChangeResource(data);
- END;
- END SetVersion;
-
- PROCEDURE OpenPrefs (VAR refNum: INTEGER; perm: SignedByte): BOOLEAN;
- VAR
- vRef : INTEGER;
- dir : LONGINT;
- err : OSErr;
- dummy: BOOLEAN;
- BEGIN
- err := FindPrefsFolder(vRef, dir); (* find (or create) prefs folder *)
- IF ErrCheck(err) THEN
- refNum := HOpenResFile(vRef, dir, PrefsName, perm); (* open prefs file *)
- err := ResError();
- IF err = fnfErr THEN (* if prefs file is missing *)
- HCreateResFile(vRef, dir, PrefsName); (* then create it *)
- refNum := HOpenResFile(vRef, dir, PrefsName, perm); (* and open the new file *)
- err := ResError();
- dummy := ErrCheck(err);
- END;
- END;
- RETURN err = noErr;
- END OpenPrefs;
-
- PROCEDURE GetPref (rType, rName: Mstring; vers: INTEGER; default: PrefsProc): HANDLE;
- VAR
- refNum: INTEGER;
- data : HANDLE;
- err : OSErr;
- BEGIN
- IF OpenPrefs(refNum, fsRdPerm) THEN
- IF GetVersion(rType, rName) <> vers THEN
- data := default();
- ELSE
- data := Get1NamedResource(StrToOS(rType), StrToPStr(rName));
- err := ResError();
- IF (err = resNotFound) OR (data = NIL) THEN
- data := default();
- ELSIF ErrCheck(err) THEN
- DetachResource(data);
- HNoPurge(data);
- ELSE
- data := default();
- END;
- END;
- CloseResFile(refNum);
- ELSE
- data := default();
- END;
- Assert(data <> NIL);
- RETURN data;
- END GetPref;
-
- PROCEDURE PrefPresent (rType, rName: Mstring; vers: INTEGER): BOOLEAN;
- VAR
- refNum: INTEGER;
- data : HANDLE;
- found : BOOLEAN;
- err : OSErr;
- BEGIN
- found := FALSE;
- IF OpenPrefs(refNum, fsRdPerm) THEN
- IF GetVersion(rType, rName) >= vers THEN
- data := Get1NamedResource(StrToOS(rType), StrToPStr(rName));
- err := ResError();
- IF (err <> resNotFound) AND (data <> NIL) THEN
- found := ErrCheck(err);
- END;
- END;
- CloseResFile(refNum);
- END;
- RETURN found;
- END PrefPresent;
-
- (* SetPref is the only routine to actually add a preference to the
- Prefs file. Note that the preferences are purgable. *)
- PROCEDURE SetPref (rType, rName: Mstring; vers: INTEGER; data: HANDLE);
- VAR
- refNum: INTEGER;
- old : HANDLE;
- err : OSErr;
- done : BOOLEAN;
- BEGIN
- done := FALSE;
- Assert(data <> NIL);
- IF OpenPrefs(refNum, fsRdWrPerm) THEN
- old := Get1NamedResource(StrToOS(rType), StrToPStr(rName));
- err := ResError();
- IF (err = resNotFound) OR (old = NIL) THEN
- done := InsertResource(rType, rName, 0, data, TRUE);
- ELSIF ErrCheck(err) THEN
- RemoveResource(old);
- done := InsertResource(rType, rName, 0, data, TRUE);
- END;
- IF done THEN
- SetVersion(rType, rName, vers);
- DetachResource(data);
- END;
- CloseResFile(refNum);
- END;
- END SetPref;
-
- PROCEDURE DeletePref (rType, rName: Mstring);
- VAR
- refNum: INTEGER;
- old : HANDLE;
- err : OSErr;
- BEGIN
- IF OpenPrefs(refNum, fsRdWrPerm) THEN
- old := Get1NamedResource(StrToOS(rType), StrToPStr(rName));
- err := ResError();
- IF (err = resNotFound) OR (old = NIL) THEN
- (* do nothing *)
- ELSIF ErrCheck(err) THEN
- RemoveResource(old);
- END;
- CloseResFile(refNum);
- END;
- END DeletePref;
-
-
- BEGIN
- PrefsName := "";
- END Prefs.
-
- InsertResource, ChangeResource, and RemoveResource are some handy resource
- manipulation routines I wrote a while back. I'll post them in a seperate
- message.
-