OSDN Git Service

Initial Import
[nethackexpress/trunk.git] / sys / mac / macfile.c
1 /*      SCCS Id: @(#)macfile.c  3.1     93/01/24                  */
2 /* Copyright (c) Jon W{tte, Hao-Yang Wang, Jonathan Handler 1992. */
3 /* NetHack may be freely redistributed.  See license for details. */
4 /*
5  * macfile.c
6  * MAC file I/O routines
7  */
8
9 #include "hack.h"
10 #include "macwin.h"
11
12 #ifndef __MACH__
13 #include <files.h>
14 #include <errors.h>
15 #include <resources.h>
16 #include <memory.h>
17 #include <TextUtils.h>
18 #include <ToolUtils.h>
19 #endif
20
21 #include "dlb.h"
22
23 /*
24  * We should get the default dirID and volRefNum (from name) from prefs and
25  * the situation at startup... For now, this will have to do.
26  */
27
28
29 /* The HandleFiles are resources built into the application which are treated
30    as read-only files: if we fail to open a file we look for a resource */
31    
32 #define FIRST_HF 32000   /* file ID of first HandleFile */
33 #define MAX_HF 6                 /* Max # of open HandleFiles */
34
35 #define APP_NAME_RES_ID         (-16396)
36
37 typedef struct handlefile {
38         long            type;  /* Resource type */
39         short           id;     /* Resource id */
40         long            mark;  /* Current position */
41         long            size;  /* total size */
42         Handle          data;  /* The resource, purgeable */
43 } HandleFile;
44
45 static  HandleFile *FDECL(IsHandleFile,(int));
46 static int FDECL(OpenHandleFile,(const unsigned char *, long));
47 static int FDECL(CloseHandleFile,(int));
48 static int FDECL(ReadHandleFile,(int, void *, unsigned));
49 static long FDECL(SetHandleFilePos,(int, short, long));
50
51 HandleFile theHandleFiles [MAX_HF];
52 MacDirs theDirs;                /* also referenced in macwin.c */
53
54
55 static HandleFile *
56 IsHandleFile(int fd)
57 {
58         HandleFile *hfp = NULL;
59
60         if (fd >= FIRST_HF && fd < FIRST_HF+MAX_HF) {
61                 /* in valid range, check for data */
62                 hfp = &theHandleFiles[fd-FIRST_HF];
63                 if (!hfp->data) hfp = NULL;
64         }
65         return hfp;
66 }
67
68
69 static int
70 OpenHandleFile (const unsigned char *name, long fileType)
71 {
72         int i;
73         Handle h;
74         Str255 s;
75
76         for (i = 0; i < MAX_HF; i ++) {
77                 if (theHandleFiles[i].data == 0L) break;
78         }
79         
80         if (i >= MAX_HF)
81                 return -1;
82
83         h = GetNamedResource (fileType, name);
84         if (!h) return (-1);
85         
86         theHandleFiles[i].data = h;
87         theHandleFiles[i].size = GetHandleSize (h);
88         GetResInfo (h, &theHandleFiles[i].id, (void*) &theHandleFiles[i].type, s);
89         theHandleFiles[i].mark = 0L;
90
91         return(i + FIRST_HF);
92 }
93
94
95 static int
96 CloseHandleFile (int fd)
97 {
98         if (!IsHandleFile (fd)) {
99            return -1;
100         }
101         fd -= FIRST_HF;
102         ReleaseResource (theHandleFiles[fd].data);
103         theHandleFiles[fd].data = 0L;
104         return(0);
105 }
106
107
108 static int
109 ReadHandleFile (int fd, void *ptr, unsigned len)
110 {
111         unsigned maxBytes;
112         Handle h;
113
114         if (!IsHandleFile (fd)) return -1;
115         
116         fd -= FIRST_HF;
117         maxBytes = theHandleFiles[fd].size - theHandleFiles[fd].mark;
118         if (len > maxBytes) len = maxBytes;
119         
120         h = theHandleFiles[fd].data;
121         
122         HLock(h);
123         BlockMove (*h + theHandleFiles[fd].mark, ptr, len);
124         HUnlock(h);
125         theHandleFiles[fd].mark += len;
126         
127         return(len);
128 }
129
130
131 static long
132 SetHandleFilePos (int fd, short whence, long pos)
133 {
134         long curpos;
135         
136         if (!IsHandleFile (fd)) return -1;
137         
138         fd -= FIRST_HF;
139         
140         curpos = theHandleFiles [fd].mark;
141         switch (whence) {
142                 case SEEK_CUR : 
143                         curpos += pos;
144                         break;
145                 case SEEK_END : 
146                         curpos = theHandleFiles[fd].size  - pos;
147                         break;
148                 default : /* set */
149                         curpos = pos;
150                         break;
151         }
152
153         if (curpos < 0)
154                 curpos = 0;
155         else if (curpos > theHandleFiles [fd].size)
156                 curpos = theHandleFiles [fd].size;
157         
158         theHandleFiles [fd].mark = curpos;
159         
160         return curpos;
161 }
162
163
164 void
165 C2P (const char *c, unsigned char *p)
166 {
167         int len = strlen (c), i;
168
169         if (len > 255) len = 255;
170
171         for (i = len; i > 0; i--)
172                 p[i] = c[i-1];
173         p[0] = len;
174 }
175
176 void
177 P2C (const unsigned char *p, char *c)
178 {
179         int idx = *p++;
180         for (; idx > 0; idx--)
181                 *c++ = *p++;
182         *c = '\0';
183 }
184
185
186 static void
187 replace_resource(Handle new_res, ResType its_type, short its_id, Str255 its_name)
188 {
189         Handle old_res;
190
191         SetResLoad(false);
192         old_res = Get1Resource(its_type, its_id);
193         SetResLoad(true);
194         if (old_res) {
195                 RemoveResource(old_res);
196                 DisposeHandle(old_res);
197         }
198
199         AddResource(new_res, its_type, its_id, its_name);
200 }
201
202
203 int
204 maccreat (const char *name, long fileType){
205         return macopen (name, O_RDWR | O_CREAT | O_TRUNC, fileType);
206 }
207
208
209 int
210 macopen (const char *name, int flags, long fileType)
211 {
212         short refNum;
213         short perm;
214         Str255 s;
215
216         C2P (name, s);
217         if (flags & O_CREAT) {
218                 if (HCreate (theDirs.dataRefNum, theDirs.dataDirID, s ,
219                         TEXT_CREATOR, fileType) && (flags & O_EXCL)) {
220                         return -1;
221                 }
222
223                 if (fileType == SAVE_TYPE) {
224                         short resRef;
225                         HCreateResFile(theDirs.dataRefNum, theDirs.dataDirID, s);
226                         resRef = HOpenResFile(theDirs.dataRefNum, theDirs.dataDirID, s,
227                                                                   fsRdWrPerm);
228                         if (resRef != -1) {
229                                 Handle name;
230                                 Str255 plnamep;
231
232                                 C2P(plname, plnamep);
233                                 name = (Handle)NewString(plnamep);
234                                 if (name)
235                                         replace_resource(name, 'STR ', PLAYER_NAME_RES_ID,
236                                                                         "\pPlayer Name");
237
238                                 /* The application name resource.  See IM VI, page 9-21. */
239                                 name = (Handle)GetString(APP_NAME_RES_ID);
240                                 if (name) {
241                                         DetachResource(name);
242                                         replace_resource(name, 'STR ', APP_NAME_RES_ID,
243                                                                          "\pApplication Name");
244                                 }
245
246                                 CloseResFile(resRef);
247                         }
248                 }
249
250         }
251         /*
252          * Here, we should check for file type, maybe a SFdialog if
253          * we fail with default, etc. etc. Besides, we should use HOpen
254          * and permissions.
255          */
256         if ((flags & O_RDONLY) == O_RDONLY) {
257                 perm = fsRdPerm;
258         }
259         if ((flags & O_WRONLY) == O_WRONLY) {
260                 perm = fsWrPerm;
261         }
262         if ((flags & O_RDWR) == O_RDWR) {
263                 perm = fsRdWrPerm;
264         }
265         if (HOpen (theDirs.dataRefNum, theDirs.dataDirID, s, perm, &refNum)) {
266                 return OpenHandleFile (s, fileType);
267         }
268         if (flags & O_TRUNC) {
269                 if (SetEOF (refNum, 0L)) {
270                         FSClose (refNum);
271                         return -1;
272                 }
273         }
274         return refNum;
275 }
276
277
278 int
279 macclose (int fd)
280 {
281         if (IsHandleFile (fd)) {
282                 CloseHandleFile (fd);
283         } else {
284                 if (FSClose (fd)) {
285                         return -1;
286                 }
287                 FlushVol ((StringPtr) 0, theDirs . dataRefNum);
288         }
289         return 0;
290 }
291
292
293 int
294 macread (int fd, void *ptr, unsigned len)
295 {
296         long amt = len;
297         
298         if (IsHandleFile (fd)) {
299                 return ReadHandleFile (fd, ptr, amt);
300         } else {
301                 short err = FSRead (fd, &amt, ptr);
302
303                 return ((err == noErr) || (err == eofErr && len)) ? amt : -1;
304         }
305 }
306
307
308 #if 0 /* this function isn't used, if you use it, uncomment prototype in macwin.h */
309 char *
310 macgets (int fd, char *ptr, unsigned len)
311 {
312         int idx = 0;
313         char c;
314
315         while (-- len > 0) {
316                 if (macread (fd, ptr + idx, 1) <= 0)
317                         return (char *)0;
318                 c = ptr[idx++];
319                 if (c  == '\n' || c == '\r')
320                         break;
321         }
322         ptr [idx] = '\0';
323         return ptr;
324 }
325 #endif /* 0 */
326
327
328 int
329 macwrite (int fd, void *ptr, unsigned len)
330 {
331         long amt = len;
332
333         if (IsHandleFile (fd)) return -1;
334         if (FSWrite(fd, &amt, ptr) == noErr)
335                 return (amt);
336         else
337                 return (-1);
338 }
339
340
341 long
342 macseek (int fd, long where, short whence)
343 {
344         short posMode;
345         long curPos;
346
347         if (IsHandleFile (fd)) {
348                 return SetHandleFilePos (fd, whence, where);
349         }
350
351         switch (whence) {
352                 default :
353                         posMode = fsFromStart;
354                         break;
355                 case SEEK_CUR :
356                         posMode = fsFromMark;
357                         break;
358                 case SEEK_END :
359                         posMode = fsFromLEOF;
360                         break;
361         }
362
363         if (SetFPos(fd, posMode, where) == noErr && GetFPos(fd, &curPos) == noErr)
364                 return (curPos);
365         else
366                 return(-1);
367 }
368
369
370 int
371 macunlink(const char *name)
372 {
373         Str255 pname;
374
375
376         C2P(name, pname);
377         return (HDelete(theDirs.dataRefNum, theDirs.dataDirID, pname) == noErr ? 0 : -1);
378 }
379
380
381
382 /* ---------------------------------------------------------------------- */
383
384 boolean rsrc_dlb_init(void) {
385         return TRUE;
386 }
387
388 void rsrc_dlb_cleanup(void) {
389 }
390
391 boolean rsrc_dlb_fopen(dlb *dp, const char *name, const char *mode) {
392 #if defined(__SC__) || defined(__MRC__)
393 # pragma unused(mode)
394 #endif
395         Str255 pname;
396         
397         C2P(name, pname);
398         dp->fd = OpenHandleFile(pname, 'File'); /* automatically read-only */
399         return dp->fd >= 0;
400 }
401
402 int rsrc_dlb_fclose(dlb *dp) {
403         return CloseHandleFile(dp->fd);
404 }
405
406 int rsrc_dlb_fread(char *buf, int size, int quan, dlb *dp) {
407         int nread;
408
409         if (size < 0 || quan < 0) return 0;
410         nread = ReadHandleFile(dp->fd, buf, (unsigned)size * (unsigned)quan);
411         
412         return nread/size;      /* # of whole pieces (== quan in normal case) */
413 }
414
415 int rsrc_dlb_fseek(dlb *dp, long pos, int whence) {
416         return SetHandleFilePos(dp->fd, whence, pos);
417 }
418
419 char *rsrc_dlb_fgets(char *buf, int len, dlb *dp) {
420         HandleFile *hfp = IsHandleFile(dp->fd);
421         char *p;
422         int bytesLeft, n = 0;
423
424         if (hfp && hfp->mark < hfp->size) {
425                 bytesLeft = hfp->size - hfp->mark;
426                 if (bytesLeft < len)
427                         len = bytesLeft;
428
429                 HLock(hfp->data);
430                 for (n = 0, p = *hfp->data+hfp->mark; n < len; n++, p++) {
431                         buf[n] = *p;
432                         if (*p == '\r') buf[n] = '\n';
433                         if (buf[n] == '\n') {
434                                 n++;            /* we want the return in the buffer */
435                                 break;
436                         }
437                 }
438                 HUnlock(hfp->data);
439
440                 hfp->mark += n;
441                 if (n != 0)
442                         buf[n] = '\0';  /* null terminate result */
443         }
444
445         return n ? buf : NULL;
446 }
447
448 int rsrc_dlb_fgetc(dlb *dp) {
449         HandleFile *hfp = IsHandleFile(dp->fd);
450         int ret;
451
452         if (!hfp || hfp->size <= hfp->mark) return EOF;
453
454         ret = *(unsigned char *)(*hfp->data + hfp->mark);
455         hfp->mark++;
456         return ret;
457 }
458
459 long rsrc_dlb_ftell(dlb *dp) {
460         HandleFile *hfp = IsHandleFile(dp->fd);
461
462         if (!hfp) return 0;
463         return hfp->mark;
464 }
465