Initial revision
[ssr] / StraySrc / Libraries / Steel / c / prefs
1 /*
2 * prefs
3 *
4 * Preferences loading and saving
5 *
6 * © 1993-1998 Straylight
7 */
8
9 /*----- Licensing note ----------------------------------------------------*
10 *
11 * This file is part of Straylight's Steel library.
12 *
13 * Steel is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2, or (at your option)
16 * any later version.
17 *
18 * Steel is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with Steel. If not, write to the Free Software Foundation,
25 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 */
27
28 #include "prefs.h"
29 #include "os.h"
30 #include "utils.h"
31 #include "msgs.h"
32 #include "choices.h"
33 #include "res.h"
34 #include "kernel.h"
35 #include "werr.h"
36
37 #include <stdio.h>
38 #include <string.h>
39 #include <ctype.h>
40
41 #define unused(x) ((x)=(x))
42
43 static prefs_prefstr *prefs__prefs;
44
45 /*
46 * char *prefs__match(char *a,char *b)
47 *
48 * Use
49 * Checks to see if the first part of a matches b. If it does, it returns
50 * the rest of a.
51 *
52 * Parameters
53 * char *a == an input string
54 * char *b == a keyword
55 *
56 * Returns
57 * The part of a following b, or NULL if no match
58 */
59
60 static char *prefs__match(char *a,char *b)
61 {
62 if (!*a)
63 return (0);
64 while (*b)
65 {
66 if (tolower(*(a++))!=tolower(*(b++)))
67 return (0);
68 }
69 while (*a==' ')
70 a++;
71 if (*a=='=')
72 a++;
73 while (*a==' ')
74 a++;
75 return (a);
76 }
77
78 /*
79 * char *prefs_readBoolean(char *tag,char *args,void *handle)
80 *
81 * Use
82 * Reads a Boolean variable (i.e. one that can be either TRUE or FALSE).
83 */
84
85 char *prefs_readBoolean(char *tag,char *args,void *handle)
86 {
87 unused(tag);
88 if (utils_caselessCmp(args,"true")==0)
89 *(BOOL *)handle=TRUE;
90 else if (utils_caselessCmp(args,"false")==0)
91 *(BOOL *)handle=FALSE;
92 else
93 return (msgs_lookup("prefsRBB:Bad boolean variable '%s' at line %i (must be 'true' or 'false')"));
94 return (0);
95 }
96
97 /*
98 * char *prefs_writeBoolean(char *tag,FILE *fp,void *handle)
99 *
100 * Use
101 * Writes a Boolean variable to the preferences file.
102 */
103
104 char *prefs_writeBoolean(char *tag,FILE *fp,void *handle)
105 {
106 fprintf(fp,"%s=%s\n",tag,*(BOOL *)handle ? "true" : "false");
107 return (0);
108 }
109
110 /*
111 * char *prefs_readNumeric(char *tag,char *args,void *handle)
112 *
113 * Use
114 * Reads a signed integer from the preferences file.
115 */
116
117 char *prefs_readNumeric(char *tag,char *args,void *handle)
118 {
119 unused(tag);
120 sscanf(args,"%d",(int *)handle);
121 return (0);
122 }
123
124 /*
125 * char *prefs_writeNumeric(char *tag,FILE *fp,void *handle)
126 *
127 * Use
128 * Writes a signed integer to the preferences file.
129 */
130
131 char *prefs_writeNumeric(char *tag,FILE *fp,void *handle)
132 {
133 fprintf(fp,"%s=%i\n",tag,*(int *)handle);
134 return (0);
135 }
136
137 /*
138 * char *prefs_readString(char *tag,char *args,void *handle)
139 *
140 * Use
141 * Reads a string from the preferences file. It is assumed that the buffer
142 * pointed to by handle is big enough.
143 */
144
145 char *prefs_readString(char *tag,char *args,void *handle)
146 {
147 char *p;
148 unused(tag);
149 if (*args=='\'')
150 {
151 for (p=++args;*p && *p!='\'';p++)
152 /* blank! */;
153 *p=0;
154 }
155 strcpy((char *)handle,args);
156 return (0);
157 }
158
159 /*
160 * char *prefs_writeString(char *tag,FILE *fp,void *handle)
161 *
162 * Use
163 * Writes a signed integer to the preferences file.
164 */
165
166 char *prefs_writeString(char *tag,FILE *fp,void *handle)
167 {
168 fprintf(fp,"%s='%s'\n",tag,(char *)handle);
169 return (0);
170 }
171
172 /*
173 * void prefs_preferences(prefs_prefstr *p)
174 *
175 * Use
176 * Sets up the prefs system to use the preferences definition specified.
177 * 'p' should be a pointer to an array of prefs_prefstrs, terminated by an
178 * entry with a null 'tag'. The preferences file created will be called
179 * 'Choices' in the current application's directory (<App$Dir>.Choices).
180 *
181 * Parameters
182 * prefs_prefstr *p == pointer to an array of preferences definitions
183 */
184
185 void prefs_preferences(prefs_prefstr *p)
186 {
187 prefs__prefs=p;
188 }
189
190 /*
191 * void prefs_read(void)
192 *
193 * Use
194 * Reads preferences from the preferences file.
195 */
196
197 void prefs_read(void)
198 {
199 FILE *fp;
200 int i;
201 int line=0;
202 char buff[256];
203 char *p;
204 char *args;
205 char *error;
206 char *preffile=choices_name("Choices",FALSE);
207
208 /* --- Make sure the Preferences file exists --- *
209 *
210 * If we can't find the Preferences, we leave the user's buffer unchanged
211 * to allow defaults
212 */
213
214 if (!res_fileExists(preffile))
215 return;
216
217 /* --- Open the Preferences file --- */
218
219 fp=fopen(preffile,"r");
220 if (!fp)
221 {
222 werr(FALSE,
223 msgs_lookup("prefsERP:Error reading preferences. "
224 "Assuming default preferences."));
225 return;
226 }
227
228 /* --- Read the file a line at a time and parse it --- */
229
230 while (fgets(buff,256,fp))
231 {
232 /* --- Bump line count for error messages --- */
233
234 line++;
235
236 /* --- Strip leading spaces --- */
237
238 for (p=buff;isspace(*p);p++)
239 /* blank! */;
240
241 /* --- fgets leaves a return on the end -- kill it --- */
242
243 utils_ctermToNterm(p);
244
245 /* --- Do something about the line --- */
246
247 switch (*p)
248 {
249 /* --- Discard blank lines and comments --- */
250 case 0:
251 case ';':
252 break;
253
254 /* --- Otherwise find the parser for this variable and call it --- */
255
256 default:
257 for (i=0;prefs__prefs[i].tag;i++)
258 {
259 if (args=prefs__match(p,prefs__prefs[i].tag),args)
260 {
261 if (prefs__prefs[i].read)
262 {
263 if (error=prefs__prefs[i].read(prefs__prefs[i].tag,
264 args,
265 prefs__prefs[i].handle),error)
266 {
267 werr(FALSE,error,prefs__prefs[i].tag,line);
268 fclose(fp);
269 return;
270 }
271 }
272 break;
273 }
274 }
275 break;
276 }
277 }
278 fclose(fp);
279 }
280
281 /*
282 * void prefs_write(void)
283 *
284 * Use
285 * Writes preferences out to disk.
286 */
287
288 void prefs_write(void)
289 {
290 int i;
291 FILE *fp=fopen(choices_name("Choices",TRUE),"w");
292 char *error;
293
294 /* --- Complain if we can't write the file --- */
295
296 if (!fp)
297 {
298 werr(FALSE,
299 msgs_lookup("prefsEWP:Error writing preferences: '%s'"),
300 _kernel_last_oserror()->errmess);
301 return;
302 }
303
304 /* --- Go through the entries one by one calling the output fns --- */
305
306 for (i=0;prefs__prefs[i].tag;i++)
307 {
308 if (prefs__prefs[i].tag[0]==';' || prefs__prefs[i].tag[0]=='\n')
309 fprintf(fp,"%s",prefs__prefs[i].tag);
310 else if (!prefs__prefs[i].write)
311 /* blank! */;
312 else if (error=prefs__prefs[i].write(prefs__prefs[i].tag,
313 fp,
314 prefs__prefs[i].handle),error)
315 {
316 werr(FALSE,error,prefs__prefs[i].tag);
317 fclose(fp);
318 return;
319 }
320 }
321
322 /* --- Close the file and exit --- */
323
324 fclose(fp);
325 return;
326 }