OSDN Git Service

import nethack-3.6.0
[jnethack/source.git] / sys / mac / macfile.c
1 /* NetHack 3.6  macfile.c       $NHDT-Date: 1432512798 2015/05/25 00:13:18 $  $NHDT-Branch: master $:$NHDT-Revision: 1.11 $ */
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 /* The HandleFiles are resources built into the application which are treated
29    as read-only files: if we fail to open a file we look for a resource */
30
31 #define FIRST_HF 32000 /* file ID of first HandleFile */
32 #define MAX_HF 6       /* Max # of open HandleFiles */
33
34 #define APP_NAME_RES_ID (-16396)
35
36 typedef struct handlefile {
37     long type;   /* Resource type */
38     short id;    /* Resource id */
39     long mark;   /* Current position */
40     long size;   /* total size */
41     Handle data; /* The resource, purgeable */
42 } HandleFile;
43
44 static HandleFile *FDECL(IsHandleFile, (int));
45 static int FDECL(OpenHandleFile, (const unsigned char *, long));
46 static int FDECL(CloseHandleFile, (int));
47 static int FDECL(ReadHandleFile, (int, void *, unsigned));
48 static long FDECL(SetHandleFilePos, (int, short, long));
49
50 HandleFile theHandleFiles[MAX_HF];
51 MacDirs theDirs; /* also referenced in macwin.c */
52
53 static HandleFile *
54 IsHandleFile(int fd)
55 {
56     HandleFile *hfp = NULL;
57
58     if (fd >= FIRST_HF && fd < FIRST_HF + MAX_HF) {
59         /* in valid range, check for data */
60         hfp = &theHandleFiles[fd - FIRST_HF];
61         if (!hfp->data)
62             hfp = NULL;
63     }
64     return hfp;
65 }
66
67 static int
68 OpenHandleFile(const unsigned char *name, long fileType)
69 {
70     int i;
71     Handle h;
72     Str255 s;
73
74     for (i = 0; i < MAX_HF; i++) {
75         if (theHandleFiles[i].data == 0L)
76             break;
77     }
78
79     if (i >= MAX_HF)
80         return -1;
81
82     h = GetNamedResource(fileType, name);
83     if (!h)
84         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 static int
95 CloseHandleFile(int fd)
96 {
97     if (!IsHandleFile(fd)) {
98         return -1;
99     }
100     fd -= FIRST_HF;
101     ReleaseResource(theHandleFiles[fd].data);
102     theHandleFiles[fd].data = 0L;
103     return (0);
104 }
105
106 static int
107 ReadHandleFile(int fd, void *ptr, unsigned len)
108 {
109     unsigned maxBytes;
110     Handle h;
111
112     if (!IsHandleFile(fd))
113         return -1;
114
115     fd -= FIRST_HF;
116     maxBytes = theHandleFiles[fd].size - theHandleFiles[fd].mark;
117     if (len > maxBytes)
118         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 static long
131 SetHandleFilePos(int fd, short whence, long pos)
132 {
133     long curpos;
134
135     if (!IsHandleFile(fd))
136         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 void
164 C2P(const char *c, unsigned char *p)
165 {
166     int len = strlen(c), i;
167
168     if (len > 255)
169         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 static void
186 replace_resource(Handle new_res, ResType its_type, short its_id,
187                  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 int
203 maccreat(const char *name, long fileType)
204 {
205     return macopen(name, O_RDWR | O_CREAT | O_TRUNC, fileType);
206 }
207
208 int
209 macopen(const char *name, int flags, long fileType)
210 {
211     short refNum;
212     short perm;
213     Str255 s;
214
215     C2P(name, s);
216     if (flags & O_CREAT) {
217         if (HCreate(theDirs.dataRefNum, theDirs.dataDirID, s, TEXT_CREATOR,
218                     fileType) && (flags & O_EXCL)) {
219             return -1;
220         }
221 #if 0 /* Fails during makedefs */
222                 if (fileType == SAVE_TYPE) {
223                         short resRef;
224                         HCreateResFile(theDirs.dataRefNum, theDirs.dataDirID, s);
225                         resRef = HOpenResFile(theDirs.dataRefNum, theDirs.dataDirID, s,
226                                                                   fsRdWrPerm);
227                         if (resRef != -1) {
228                                 Handle name;
229                                 Str255 plnamep;
230
231                                 C2P(plname, plnamep);
232                                 name = (Handle)NewString(plnamep);
233                                 if (name)
234                                         replace_resource(name, 'STR ', PLAYER_NAME_RES_ID,
235                                                                         "\pPlayer Name");
236
237                                 /* The application name resource.  See IM VI, page 9-21. */
238                                 name = (Handle)GetString(APP_NAME_RES_ID);
239                                 if (name) {
240                                         DetachResource(name);
241                                         replace_resource(name, 'STR ', APP_NAME_RES_ID,
242                                                                          "\pApplication Name");
243                                 }
244
245                                 CloseResFile(resRef);
246                         }
247                 }
248 #endif
249     }
250     /*
251      * Here, we should check for file type, maybe a SFdialog if
252      * we fail with default, etc. etc. Besides, we should use HOpen
253      * and permissions.
254      */
255     if ((flags & O_RDONLY) == O_RDONLY) {
256         perm = fsRdPerm;
257     }
258     if ((flags & O_WRONLY) == O_WRONLY) {
259         perm = fsWrPerm;
260     }
261     if ((flags & O_RDWR) == O_RDWR) {
262         perm = fsRdWrPerm;
263     }
264     if (HOpen(theDirs.dataRefNum, theDirs.dataDirID, s, perm, &refNum)) {
265         return OpenHandleFile(s, fileType);
266     }
267     if (flags & O_TRUNC) {
268         if (SetEOF(refNum, 0L)) {
269             FSClose(refNum);
270             return -1;
271         }
272     }
273     return refNum;
274 }
275
276 int
277 macclose(int fd)
278 {
279     if (IsHandleFile(fd)) {
280         CloseHandleFile(fd);
281     } else {
282         if (FSClose(fd)) {
283             return -1;
284         }
285         FlushVol((StringPtr) 0, theDirs.dataRefNum);
286     }
287     return 0;
288 }
289
290 int
291 macread(int fd, void *ptr, unsigned len)
292 {
293     long amt = len;
294
295     if (IsHandleFile(fd)) {
296         return ReadHandleFile(fd, ptr, amt);
297     } else {
298         short err = FSRead(fd, &amt, ptr);
299
300         return ((err == noErr) || (err == eofErr && len)) ? amt : -1;
301     }
302 }
303
304 #if 0  /* this function isn't used, if you use it, uncomment prototype in \
305           macwin.h */
306 char *
307 macgets (int fd, char *ptr, unsigned len)
308 {
309         int idx = 0;
310         char c;
311
312         while (-- len > 0) {
313                 if (macread (fd, ptr + idx, 1) <= 0)
314                         return (char *)0;
315                 c = ptr[idx++];
316                 if (c  == '\n' || c == '\r')
317                         break;
318         }
319         ptr [idx] = '\0';
320         return ptr;
321 }
322 #endif /* 0 */
323
324 int
325 macwrite(int fd, void *ptr, unsigned len)
326 {
327     long amt = len;
328
329     if (IsHandleFile(fd))
330         return -1;
331     if (FSWrite(fd, &amt, ptr) == noErr)
332         return (amt);
333     else
334         return (-1);
335 }
336
337 long
338 macseek(int fd, long where, short whence)
339 {
340     short posMode;
341     long curPos;
342
343     if (IsHandleFile(fd)) {
344         return SetHandleFilePos(fd, whence, where);
345     }
346
347     switch (whence) {
348     default:
349         posMode = fsFromStart;
350         break;
351     case SEEK_CUR:
352         posMode = fsFromMark;
353         break;
354     case SEEK_END:
355         posMode = fsFromLEOF;
356         break;
357     }
358
359     if (SetFPos(fd, posMode, where) == noErr && GetFPos(fd, &curPos) == noErr)
360         return (curPos);
361     else
362         return (-1);
363 }
364
365 int
366 macunlink(const char *name)
367 {
368     Str255 pname;
369
370     C2P(name, pname);
371     return (HDelete(theDirs.dataRefNum, theDirs.dataDirID, pname) == noErr
372                 ? 0
373                 : -1);
374 }
375
376 /* ---------------------------------------------------------------------- */
377
378 boolean
379 rsrc_dlb_init(void)
380 {
381     return TRUE;
382 }
383
384 void
385 rsrc_dlb_cleanup(void)
386 {
387 }
388
389 boolean
390 rsrc_dlb_fopen(dlb *dp, const char *name, const char *mode)
391 {
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
403 rsrc_dlb_fclose(dlb *dp)
404 {
405     return CloseHandleFile(dp->fd);
406 }
407
408 int
409 rsrc_dlb_fread(char *buf, int size, int quan, dlb *dp)
410 {
411     int nread;
412
413     if (size < 0 || quan < 0)
414         return 0;
415     nread = ReadHandleFile(dp->fd, buf, (unsigned) size * (unsigned) quan);
416
417     return nread / size; /* # of whole pieces (== quan in normal case) */
418 }
419
420 int
421 rsrc_dlb_fseek(dlb *dp, long pos, int whence)
422 {
423     return SetHandleFilePos(dp->fd, whence, pos);
424 }
425
426 char *
427 rsrc_dlb_fgets(char *buf, int len, dlb *dp)
428 {
429     HandleFile *hfp = IsHandleFile(dp->fd);
430     char *p;
431     int bytesLeft, n = 0;
432
433     if (hfp && hfp->mark < hfp->size) {
434         bytesLeft = hfp->size - hfp->mark;
435         if (bytesLeft < len)
436             len = bytesLeft;
437
438         HLock(hfp->data);
439         for (n = 0, p = *hfp->data + hfp->mark; n < len; n++, p++) {
440             buf[n] = *p;
441             if (*p == '\r')
442                 buf[n] = '\n';
443             if (buf[n] == '\n') {
444                 n++; /* we want the return in the buffer */
445                 break;
446             }
447         }
448         HUnlock(hfp->data);
449
450         hfp->mark += n;
451         if (n != 0)
452             buf[n] = '\0'; /* null terminate result */
453     }
454
455     return n ? buf : NULL;
456 }
457
458 int
459 rsrc_dlb_fgetc(dlb *dp)
460 {
461     HandleFile *hfp = IsHandleFile(dp->fd);
462     int ret;
463
464     if (!hfp || hfp->size <= hfp->mark)
465         return EOF;
466
467     ret = *(unsigned char *) (*hfp->data + hfp->mark);
468     hfp->mark++;
469     return ret;
470 }
471
472 long
473 rsrc_dlb_ftell(dlb *dp)
474 {
475     HandleFile *hfp = IsHandleFile(dp->fd);
476
477     if (!hfp)
478         return 0;
479     return hfp->mark;
480 }