home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #1 / NN_1993_1.iso / spool / comp / sys / mac / programm / 21065 < prev    next >
Encoding:
Internet Message Format  |  1993-01-09  |  6.9 KB

  1. Path: sparky!uunet!spool.mu.edu!olivea!mintaka.lcs.mit.edu!ogicse!news.u.washington.edu!stein.u.washington.edu!jesjones
  2. From: jesjones@stein.u.washington.edu (Jesse Jones)
  3. Newsgroups: comp.sys.mac.programmer
  4. Subject: Re: code for Finding Prefs File (long)
  5. Summary: A slick Prefs module written in Modula-2
  6. Message-ID: <1ilnplINNbck@shelley.u.washington.edu>
  7. Date: 9 Jan 93 05:28:21 GMT
  8. References: <D2150096.mv05jr@sproul.sproul.com>
  9. Organization: University of Washington, Seattle
  10. Lines: 224
  11. NNTP-Posting-Host: stein.u.washington.edu
  12.  
  13.  
  14.    There has been some discussion lately about how to handle a preferences
  15. file, so I thought I'd post my code. It's nothing astounding, but I think
  16. it has some advantages over the previously posted code:
  17.  
  18.    1) FindFolder and the high level file manager routines are used so
  19.       the code is quit a bit easier to follow.
  20.    2) The GetPref procedure is passed a procedure parameter that is used to
  21.       return a default preference if the preference is missing from the
  22.       Prefs file.
  23.    3) Individual preferences are referenced by the ResType, resource name,
  24.       and version number. If the version numbers don't match the default
  25.       preference is returned.
  26.       
  27.  
  28.    --Jesse
  29.    
  30.    
  31.    Here is the interface for the Prefs module. It's written in SemperSoft
  32. Modula-2. HANDLE is compatible with any pointer to pointer and Mstring is
  33. a 256-byte string terminated with zero.
  34.  
  35. DEFINITION MODULE Prefs;   (* By Jesse Jones, 1992 *)
  36.  
  37.  
  38. FROM SYSTEM     IMPORT HANDLE;
  39. FROM Types      IMPORT Str255, Mstring;
  40.  
  41.  
  42. TYPE
  43.    PrefsProc = PROCEDURE(): HANDLE;
  44.    
  45. VAR
  46.    PrefsName: Str255;         (* Name of the Preferences file. *)
  47.  
  48.  
  49. PROCEDURE GetPref (rType, rName: Mstring; vers: INTEGER; default: PrefsProc): HANDLE;
  50.    (* default is called if Prefs not present or version <> vers. *)
  51.  
  52. PROCEDURE SetPref (rType, rName: Mstring; vers: INTEGER; data: HANDLE);
  53.    (* Change or add a preference. *)
  54.  
  55. PROCEDURE PrefPresent (rType, rName: Mstring; vers: INTEGER): BOOLEAN;
  56.  
  57. PROCEDURE DeletePref (rType, rName: Mstring);
  58.  
  59.  
  60. END Prefs.
  61.  
  62.    And here is the implementation of the Prefs module.
  63.  
  64. IMPLEMENTATION MODULE Prefs;
  65.  
  66. (* Import list deleted *)
  67.  
  68.    (* Version numbers are saved in PVRS resources. These resources contain a
  69.       single integer for the version number and are referenced by name, with
  70.       the name being the concatenation of the preference resource type and
  71.       the preference's name. *)
  72. PROCEDURE GetVersion (rType, rName: Mstring): INTEGER;
  73.    VAR 
  74.       data: IntHandle;
  75.       str : Str255;
  76.       vers: INTEGER;
  77.       err : OSErr;
  78. BEGIN
  79.    str := StrToPStr(Concat(rType, rName));
  80.    data := Get1NamedResource('PVRS', str);
  81.    err := ResError();
  82.    IF (err = resNotFound) OR (data = NIL) THEN
  83.       vers := -1;
  84.    ELSIF ErrCheck(err) THEN
  85.       vers := data^^;
  86.    ELSE
  87.       vers := -1;
  88.    END;
  89.    RETURN vers;
  90. END GetVersion;
  91.  
  92. PROCEDURE SetVersion (rType, rName: Mstring; version: INTEGER);
  93.    VAR 
  94.       data : IntHandle;
  95.       str  : Mstring;
  96.       err  : OSErr;
  97.       dummy: BOOLEAN;
  98. BEGIN
  99.    str := Concat(rType, rName);
  100.    data := Get1NamedResource('PVRS', StrToPStr(str));
  101.    err := ResError();
  102.    IF (err = resNotFound) OR (data = NIL) THEN
  103.       data := CreateHandle(SIZE(INTEGER));
  104.       data^^ := version;
  105.       dummy := InsertResource('PVRS', str, 0, data, TRUE);
  106.    ELSIF ErrCheck(err) THEN
  107.       data^^ := version;
  108.       dummy := ChangeResource(data);
  109.    END;
  110. END SetVersion;
  111.  
  112. PROCEDURE OpenPrefs (VAR refNum: INTEGER; perm: SignedByte): BOOLEAN;
  113.    VAR
  114.       vRef : INTEGER;
  115.       dir  : LONGINT;
  116.       err  : OSErr;
  117.       dummy: BOOLEAN;
  118. BEGIN
  119.    err := FindPrefsFolder(vRef, dir);                           (* find (or create) prefs folder *)
  120.    IF ErrCheck(err) THEN
  121.       refNum := HOpenResFile(vRef, dir, PrefsName, perm);      (* open prefs file *)
  122.       err := ResError();
  123.       IF err = fnfErr THEN                                       (* if prefs file is missing *)
  124.          HCreateResFile(vRef, dir, PrefsName);                  (* then create it *)
  125.          refNum := HOpenResFile(vRef, dir, PrefsName, perm);   (* and open the new file *)
  126.          err := ResError();
  127.          dummy := ErrCheck(err);
  128.       END;
  129.    END;
  130.    RETURN err = noErr;
  131. END OpenPrefs;
  132.  
  133. PROCEDURE GetPref (rType, rName: Mstring; vers: INTEGER; default: PrefsProc): HANDLE;
  134.    VAR
  135.       refNum: INTEGER;
  136.       data  : HANDLE;
  137.       err   : OSErr;
  138. BEGIN
  139.    IF OpenPrefs(refNum, fsRdPerm) THEN
  140.       IF GetVersion(rType, rName) <> vers THEN
  141.          data := default();
  142.       ELSE
  143.          data := Get1NamedResource(StrToOS(rType), StrToPStr(rName));
  144.          err := ResError();
  145.          IF (err = resNotFound) OR (data = NIL) THEN
  146.             data := default();
  147.          ELSIF ErrCheck(err) THEN
  148.             DetachResource(data);
  149.             HNoPurge(data);
  150.          ELSE
  151.             data := default();
  152.          END;
  153.       END;
  154.       CloseResFile(refNum);
  155.    ELSE
  156.       data := default();
  157.    END;
  158.    Assert(data <> NIL);
  159.    RETURN data;
  160. END GetPref;
  161.  
  162. PROCEDURE PrefPresent (rType, rName: Mstring; vers: INTEGER): BOOLEAN;
  163.    VAR
  164.       refNum: INTEGER;
  165.       data  : HANDLE;
  166.       found : BOOLEAN;
  167.       err   : OSErr;
  168. BEGIN
  169.    found := FALSE;
  170.    IF OpenPrefs(refNum, fsRdPerm) THEN
  171.       IF GetVersion(rType, rName) >= vers THEN
  172.          data := Get1NamedResource(StrToOS(rType), StrToPStr(rName));
  173.          err := ResError();
  174.          IF (err <> resNotFound) AND (data <> NIL) THEN
  175.             found := ErrCheck(err);
  176.          END;
  177.       END;
  178.       CloseResFile(refNum);
  179.    END;
  180.    RETURN found;
  181. END PrefPresent;
  182.  
  183.    (* SetPref is the only routine to actually add a preference to the
  184.       Prefs file. Note that the preferences are purgable. *)
  185. PROCEDURE SetPref (rType, rName: Mstring; vers: INTEGER; data: HANDLE);
  186.    VAR
  187.       refNum: INTEGER;
  188.       old   : HANDLE;
  189.       err   : OSErr;
  190.       done  : BOOLEAN;
  191. BEGIN
  192.    done := FALSE;
  193.    Assert(data <> NIL);
  194.    IF OpenPrefs(refNum, fsRdWrPerm) THEN
  195.       old := Get1NamedResource(StrToOS(rType), StrToPStr(rName));
  196.       err := ResError();
  197.       IF (err = resNotFound) OR (old = NIL) THEN
  198.          done := InsertResource(rType, rName, 0, data, TRUE);   
  199.       ELSIF ErrCheck(err) THEN
  200.          RemoveResource(old);
  201.          done := InsertResource(rType, rName, 0, data, TRUE);
  202.       END;
  203.       IF done THEN 
  204.          SetVersion(rType, rName, vers);
  205.          DetachResource(data);
  206.       END;
  207.       CloseResFile(refNum);
  208.    END;
  209. END SetPref;
  210.  
  211. PROCEDURE DeletePref (rType, rName: Mstring);
  212.    VAR
  213.       refNum: INTEGER;
  214.       old   : HANDLE;
  215.       err   : OSErr;
  216. BEGIN
  217.    IF OpenPrefs(refNum, fsRdWrPerm) THEN
  218.       old := Get1NamedResource(StrToOS(rType), StrToPStr(rName));
  219.       err := ResError();
  220.       IF (err = resNotFound) OR (old = NIL) THEN
  221.          (* do nothing *)
  222.       ELSIF ErrCheck(err) THEN
  223.          RemoveResource(old);
  224.       END;
  225.       CloseResFile(refNum);
  226.    END;
  227. END DeletePref;
  228.  
  229.  
  230. BEGIN
  231.    PrefsName := "";
  232. END Prefs.
  233.  
  234.    InsertResource, ChangeResource, and RemoveResource are some handy resource
  235. manipulation routines I wrote a while back. I'll post them in a seperate
  236. message.
  237.