blob: 8b77012788ca7899a06cfcf938be7fbe92741cd1 [file] [log] [blame]
Jack Jansen8a99a8a1997-09-08 13:26:36 +00001#
2# General parser/loaders for preferences files and such
3#
Jack Jansen5a6fdcd2001-08-25 12:15:04 +00004from Carbon import Res
Jack Jansen8a99a8a1997-09-08 13:26:36 +00005import macfs
6import struct
7import MACFS
8
9READ=1
10READWRITE=3
11Error = "Preferences.Error"
12
13debug = 0
14
15class NullLoader:
16 def __init__(self, data=None):
17 self.data = data
18
19 def load(self):
20 if self.data is None:
21 raise Error, "No default given"
22 return self.data
23
24 def save(self, data):
25 raise Error, "Cannot save to default value"
26
27 def delete(self, deep=0):
28 if debug:
29 print 'Attempt to delete default value'
30 raise Error, "Cannot delete default value"
31
32_defaultdefault = NullLoader()
33
34class ResLoader:
35 def __init__(self, filename, resid, resnum=None, resname=None, default=_defaultdefault):
36 self.filename = filename
37 self.fss = macfs.FSSpec(self.filename)
38 self.resid = resid
39 self.resnum = resnum
40 self.resname = resname
41 self.default = default
42 self.data = None
43
44 def load(self):
45 oldrh = Res.CurResFile()
46 try:
47 rh = Res.FSpOpenResFile(self.fss, READ)
48 except Res.Error:
49 self.data = self.default.load()
50 return self.data
51 try:
52 if self.resname:
53 handle = Res.Get1NamedResource(self.resid, self.resname)
54 else:
55 handle = Res.Get1Resource(self.resid, self.resnum)
56 except Res.Error:
57 self.data = self.default.load()
58 else:
59 if debug:
60 print 'Loaded', (self.resid, self.resnum, self.resname), 'from', self.fss.as_pathname()
61 self.data = handle.data
62 Res.CloseResFile(rh)
63 Res.UseResFile(oldrh)
64 return self.data
65
66 def save(self, data):
67 if self.data is None or self.data != data:
68 oldrh = Res.CurResFile()
69 rh = Res.FSpOpenResFile(self.fss, READWRITE)
70 try:
71 handle = Res.Get1Resource(self.resid, self.resnum)
72 except Res.Error:
73 handle = Res.Resource(data)
74 handle.AddResource(self.resid, self.resnum, '')
75 if debug:
76 print 'Added', (self.resid, self.resnum), 'to', self.fss.as_pathname()
77 else:
78 handle.data = data
79 handle.ChangedResource()
80 if debug:
81 print 'Changed', (self.resid, self.resnum), 'in', self.fss.as_pathname()
82 Res.CloseResFile(rh)
83 Res.UseResFile(oldrh)
84
85 def delete(self, deep=0):
86 if debug:
87 print 'Deleting in', self.fss.as_pathname(), `self.data`, deep
88 oldrh = Res.CurResFile()
89 rh = Res.FSpOpenResFile(self.fss, READWRITE)
90 try:
91 handle = Res.Get1Resource(self.resid, self.resnum)
92 except Res.Error:
93 if deep:
94 if debug: print 'deep in', self.default
95 self.default.delete(1)
96 else:
97 handle.RemoveResource()
98 if debug:
99 print 'Deleted', (self.resid, self.resnum), 'from', self.fss.as_pathname()
100 self.data = None
101 Res.CloseResFile(rh)
102 Res.UseResFile(oldrh)
103
104class AnyResLoader:
105 def __init__(self, resid, resnum=None, resname=None, default=_defaultdefault):
106 self.resid = resid
107 self.resnum = resnum
108 self.resname = resname
109 self.default = default
110 self.data = None
111
112 def load(self):
113 try:
114 if self.resname:
115 handle = Res.GetNamedResource(self.resid, self.resname)
116 else:
117 handle = Res.GetResource(self.resid, self.resnum)
118 except Res.Error:
119 self.data = self.default.load()
120 else:
121 self.data = handle.data
122 return self.data
123
124 def save(self, data):
125 raise Error, "Cannot save AnyResLoader preferences"
126
127 def delete(self, deep=0):
128 raise Error, "Cannot delete AnyResLoader preferences"
129
130class StructLoader:
131 def __init__(self, format, loader):
132 self.format = format
133 self.loader = loader
134
135 def load(self):
136 data = self.loader.load()
137 return struct.unpack(self.format, data)
138
139 def save(self, data):
140 data = apply(struct.pack, (self.format,)+data)
141 self.loader.save(data)
142
143 def delete(self, deep=0):
144 self.loader.delete(deep)
145
146class PstringLoader:
147 def __init__(self, loader):
148 self.loader = loader
149
150 def load(self):
151 data = self.loader.load()
152 len = ord(data[0])
153 return data[1:1+len]
154
155 def save(self, data):
156 if len(data) > 255:
157 raise Error, "String too big for pascal-style"
158 self.loader.save(chr(len(data))+data)
159
160 def delete(self, deep=0):
161 self.loader.delete(deep)
162
163class VersionLoader(StructLoader):
164 def load(self):
165 while 1:
166 data = self.loader.load()
167 if debug:
168 print 'Versionloader:', `data`
169 try:
170 rv = struct.unpack(self.format, data)
171 rv = self.versioncheck(rv)
172 return rv
173 except (struct.error, Error):
174 self.delete(1)
175
176 def versioncheck(self, data):
177 return data
178
179class StrListLoader:
180 def __init__(self, loader):
181 self.loader = loader
182
183 def load(self):
184 data = self.loader.load()
185 num, = struct.unpack('h', data[:2])
186 data = data[2:]
187 rv = []
188 for i in range(num):
189 strlen = ord(data[0])
190 if strlen < 0: strlen = strlen + 256
191 str = data[1:strlen+1]
192 data = data[strlen+1:]
193 rv.append(str)
194 return rv
195
196 def save(self, list):
197 rv = struct.pack('h', len(list))
198 for str in list:
199 rv = rv + chr(len(str)) + str
200 self.loader.save(rv)
201
202 def delete(self, deep=0):
203 self.loader.delete(deep)
204
205def preferencefile(filename, creator=None, type=None):
206 create = creator != None and type != None
207 vrefnum, dirid = macfs.FindFolder(MACFS.kOnSystemDisk, 'pref', create)
Just van Rossum26a69db1999-02-02 15:49:03 +0000208 fss = macfs.FSSpec((vrefnum, dirid, ":Python:" + filename))
Jack Jansen8a99a8a1997-09-08 13:26:36 +0000209 oldrf = Res.CurResFile()
210 if create:
211 try:
212 rh = Res.FSpOpenResFile(fss, READ)
213 except Res.Error:
214 Res.FSpCreateResFile(fss, creator, type, MACFS.smAllScripts)
215 else:
216 Res.CloseResFile(rh)
217 Res.UseResFile(oldrf)
218 return fss
219