NHDT->ANH, nethack->anethack, nhdat->anhdat
[aNetHack.git] / sys / mac / macfile.c
blob991ec41884ae8818a557e1855e7a2159af40a78e
1 /* aNetHack 0.0.1 macfile.c $ANH-Date: 1432512798 2015/05/25 00:13:18 $ $ANH-Branch: master $:$ANH-Revision: 1.11 $ */
2 /* Copyright (c) Jon W{tte, Hao-Yang Wang, Jonathan Handler 1992. */
3 /* aNetHack may be freely redistributed. See license for details. */
4 /*
5 * macfile.c
6 * MAC file I/O routines
7 */
9 #include "hack.h"
10 #include "macwin.h"
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
21 #include "dlb.h"
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.
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 */
31 #define FIRST_HF 32000 /* file ID of first HandleFile */
32 #define MAX_HF 6 /* Max # of open HandleFiles */
34 #define APP_NAME_RES_ID (-16396)
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;
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));
50 HandleFile theHandleFiles[MAX_HF];
51 MacDirs theDirs; /* also referenced in macwin.c */
53 static HandleFile *
54 IsHandleFile(int fd)
56 HandleFile *hfp = NULL;
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;
64 return hfp;
67 static int
68 OpenHandleFile(const unsigned char *name, long fileType)
70 int i;
71 Handle h;
72 Str255 s;
74 for (i = 0; i < MAX_HF; i++) {
75 if (theHandleFiles[i].data == 0L)
76 break;
79 if (i >= MAX_HF)
80 return -1;
82 h = GetNamedResource(fileType, name);
83 if (!h)
84 return (-1);
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;
91 return (i + FIRST_HF);
94 static int
95 CloseHandleFile(int fd)
97 if (!IsHandleFile(fd)) {
98 return -1;
100 fd -= FIRST_HF;
101 ReleaseResource(theHandleFiles[fd].data);
102 theHandleFiles[fd].data = 0L;
103 return (0);
106 static int
107 ReadHandleFile(int fd, void *ptr, unsigned len)
109 unsigned maxBytes;
110 Handle h;
112 if (!IsHandleFile(fd))
113 return -1;
115 fd -= FIRST_HF;
116 maxBytes = theHandleFiles[fd].size - theHandleFiles[fd].mark;
117 if (len > maxBytes)
118 len = maxBytes;
120 h = theHandleFiles[fd].data;
122 HLock(h);
123 BlockMove(*h + theHandleFiles[fd].mark, ptr, len);
124 HUnlock(h);
125 theHandleFiles[fd].mark += len;
127 return (len);
130 static long
131 SetHandleFilePos(int fd, short whence, long pos)
133 long curpos;
135 if (!IsHandleFile(fd))
136 return -1;
138 fd -= FIRST_HF;
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;
153 if (curpos < 0)
154 curpos = 0;
155 else if (curpos > theHandleFiles[fd].size)
156 curpos = theHandleFiles[fd].size;
158 theHandleFiles[fd].mark = curpos;
160 return curpos;
163 void
164 C2P(const char *c, unsigned char *p)
166 int len = strlen(c), i;
168 if (len > 255)
169 len = 255;
171 for (i = len; i > 0; i--)
172 p[i] = c[i - 1];
173 p[0] = len;
176 void
177 P2C(const unsigned char *p, char *c)
179 int idx = *p++;
180 for (; idx > 0; idx--)
181 *c++ = *p++;
182 *c = '\0';
185 static void
186 replace_resource(Handle new_res, ResType its_type, short its_id,
187 Str255 its_name)
189 Handle old_res;
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);
199 AddResource(new_res, its_type, its_id, its_name);
203 maccreat(const char *name, long fileType)
205 return macopen(name, O_RDWR | O_CREAT | O_TRUNC, fileType);
209 macopen(const char *name, int flags, long fileType)
211 short refNum;
212 short perm;
213 Str255 s;
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;
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;
231 C2P(plname, plnamep);
232 name = (Handle)NewString(plnamep);
233 if (name)
234 replace_resource(name, 'STR ', PLAYER_NAME_RES_ID,
235 "\pPlayer Name");
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");
245 CloseResFile(resRef);
248 #endif
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.
255 if ((flags & O_RDONLY) == O_RDONLY) {
256 perm = fsRdPerm;
258 if ((flags & O_WRONLY) == O_WRONLY) {
259 perm = fsWrPerm;
261 if ((flags & O_RDWR) == O_RDWR) {
262 perm = fsRdWrPerm;
264 if (HOpen(theDirs.dataRefNum, theDirs.dataDirID, s, perm, &refNum)) {
265 return OpenHandleFile(s, fileType);
267 if (flags & O_TRUNC) {
268 if (SetEOF(refNum, 0L)) {
269 FSClose(refNum);
270 return -1;
273 return refNum;
277 macclose(int fd)
279 if (IsHandleFile(fd)) {
280 CloseHandleFile(fd);
281 } else {
282 if (FSClose(fd)) {
283 return -1;
285 FlushVol((StringPtr) 0, theDirs.dataRefNum);
287 return 0;
291 macread(int fd, void *ptr, unsigned len)
293 long amt = len;
295 if (IsHandleFile(fd)) {
296 return ReadHandleFile(fd, ptr, amt);
297 } else {
298 short err = FSRead(fd, &amt, ptr);
300 return ((err == noErr) || (err == eofErr && len)) ? amt : -1;
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)
309 int idx = 0;
310 char c;
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;
319 ptr [idx] = '\0';
320 return ptr;
322 #endif /* 0 */
325 macwrite(int fd, void *ptr, unsigned len)
327 long amt = len;
329 if (IsHandleFile(fd))
330 return -1;
331 if (FSWrite(fd, &amt, ptr) == noErr)
332 return (amt);
333 else
334 return (-1);
337 long
338 macseek(int fd, long where, short whence)
340 short posMode;
341 long curPos;
343 if (IsHandleFile(fd)) {
344 return SetHandleFilePos(fd, whence, where);
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;
359 if (SetFPos(fd, posMode, where) == noErr && GetFPos(fd, &curPos) == noErr)
360 return (curPos);
361 else
362 return (-1);
366 macunlink(const char *name)
368 Str255 pname;
370 C2P(name, pname);
371 return (HDelete(theDirs.dataRefNum, theDirs.dataDirID, pname) == noErr
373 : -1);
376 /* ---------------------------------------------------------------------- */
378 boolean
379 rsrc_dlb_init(void)
381 return TRUE;
384 void
385 rsrc_dlb_cleanup(void)
389 boolean
390 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;
397 C2P(name, pname);
398 dp->fd = OpenHandleFile(pname, 'File'); /* automatically read-only */
399 return dp->fd >= 0;
403 rsrc_dlb_fclose(dlb *dp)
405 return CloseHandleFile(dp->fd);
409 rsrc_dlb_fread(char *buf, int size, int quan, dlb *dp)
411 int nread;
413 if (size < 0 || quan < 0)
414 return 0;
415 nread = ReadHandleFile(dp->fd, buf, (unsigned) size * (unsigned) quan);
417 return nread / size; /* # of whole pieces (== quan in normal case) */
421 rsrc_dlb_fseek(dlb *dp, long pos, int whence)
423 return SetHandleFilePos(dp->fd, whence, pos);
426 char *
427 rsrc_dlb_fgets(char *buf, int len, dlb *dp)
429 HandleFile *hfp = IsHandleFile(dp->fd);
430 char *p;
431 int bytesLeft, n = 0;
433 if (hfp && hfp->mark < hfp->size) {
434 bytesLeft = hfp->size - hfp->mark;
435 if (bytesLeft < len)
436 len = bytesLeft;
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;
448 HUnlock(hfp->data);
450 hfp->mark += n;
451 if (n != 0)
452 buf[n] = '\0'; /* null terminate result */
455 return n ? buf : NULL;
459 rsrc_dlb_fgetc(dlb *dp)
461 HandleFile *hfp = IsHandleFile(dp->fd);
462 int ret;
464 if (!hfp || hfp->size <= hfp->mark)
465 return EOF;
467 ret = *(unsigned char *) (*hfp->data + hfp->mark);
468 hfp->mark++;
469 return ret;
472 long
473 rsrc_dlb_ftell(dlb *dp)
475 HandleFile *hfp = IsHandleFile(dp->fd);
477 if (!hfp)
478 return 0;
479 return hfp->mark;