/* NetHack 3.6 macfile.c $NHDT-Date: 1432512798 2015/05/25 00:13:18 $ $NHDT-Branch: master $:$NHDT-Revision: 1.11 $ */ /* Copyright (c) Jon W{tte, Hao-Yang Wang, Jonathan Handler 1992. */ /* NetHack may be freely redistributed. See license for details. */ /* * macfile.c * MAC file I/O routines */ #include "hack.h" #include "macwin.h" #ifndef __MACH__ #include #include #include #include #include #include #endif #include "dlb.h" /* * We should get the default dirID and volRefNum (from name) from prefs and * the situation at startup... For now, this will have to do. */ /* The HandleFiles are resources built into the application which are treated as read-only files: if we fail to open a file we look for a resource */ #define FIRST_HF 32000 /* file ID of first HandleFile */ #define MAX_HF 6 /* Max # of open HandleFiles */ #define APP_NAME_RES_ID (-16396) typedef struct handlefile { long type; /* Resource type */ short id; /* Resource id */ long mark; /* Current position */ long size; /* total size */ Handle data; /* The resource, purgeable */ } HandleFile; static HandleFile *FDECL(IsHandleFile, (int)); static int FDECL(OpenHandleFile, (const unsigned char *, long)); static int FDECL(CloseHandleFile, (int)); static int FDECL(ReadHandleFile, (int, void *, unsigned)); static long FDECL(SetHandleFilePos, (int, short, long)); HandleFile theHandleFiles[MAX_HF]; MacDirs theDirs; /* also referenced in macwin.c */ static HandleFile * IsHandleFile(int fd) { HandleFile *hfp = NULL; if (fd >= FIRST_HF && fd < FIRST_HF + MAX_HF) { /* in valid range, check for data */ hfp = &theHandleFiles[fd - FIRST_HF]; if (!hfp->data) hfp = NULL; } return hfp; } static int OpenHandleFile(const unsigned char *name, long fileType) { int i; Handle h; Str255 s; for (i = 0; i < MAX_HF; i++) { if (theHandleFiles[i].data == 0L) break; } if (i >= MAX_HF) return -1; h = GetNamedResource(fileType, name); if (!h) return (-1); theHandleFiles[i].data = h; theHandleFiles[i].size = GetHandleSize(h); GetResInfo(h, &theHandleFiles[i].id, (void *) &theHandleFiles[i].type, s); theHandleFiles[i].mark = 0L; return (i + FIRST_HF); } static int CloseHandleFile(int fd) { if (!IsHandleFile(fd)) { return -1; } fd -= FIRST_HF; ReleaseResource(theHandleFiles[fd].data); theHandleFiles[fd].data = 0L; return (0); } static int ReadHandleFile(int fd, void *ptr, unsigned len) { unsigned maxBytes; Handle h; if (!IsHandleFile(fd)) return -1; fd -= FIRST_HF; maxBytes = theHandleFiles[fd].size - theHandleFiles[fd].mark; if (len > maxBytes) len = maxBytes; h = theHandleFiles[fd].data; HLock(h); BlockMove(*h + theHandleFiles[fd].mark, ptr, len); HUnlock(h); theHandleFiles[fd].mark += len; return (len); } static long SetHandleFilePos(int fd, short whence, long pos) { long curpos; if (!IsHandleFile(fd)) return -1; fd -= FIRST_HF; curpos = theHandleFiles[fd].mark; switch (whence) { case SEEK_CUR: curpos += pos; break; case SEEK_END: curpos = theHandleFiles[fd].size - pos; break; default: /* set */ curpos = pos; break; } if (curpos < 0) curpos = 0; else if (curpos > theHandleFiles[fd].size) curpos = theHandleFiles[fd].size; theHandleFiles[fd].mark = curpos; return curpos; } void C2P(const char *c, unsigned char *p) { int len = strlen(c), i; if (len > 255) len = 255; for (i = len; i > 0; i--) p[i] = c[i - 1]; p[0] = len; } void P2C(const unsigned char *p, char *c) { int idx = *p++; for (; idx > 0; idx--) *c++ = *p++; *c = '\0'; } static void replace_resource(Handle new_res, ResType its_type, short its_id, Str255 its_name) { Handle old_res; SetResLoad(false); old_res = Get1Resource(its_type, its_id); SetResLoad(true); if (old_res) { RemoveResource(old_res); DisposeHandle(old_res); } AddResource(new_res, its_type, its_id, its_name); } int maccreat(const char *name, long fileType) { return macopen(name, O_RDWR | O_CREAT | O_TRUNC, fileType); } int macopen(const char *name, int flags, long fileType) { short refNum; short perm; Str255 s; C2P(name, s); if (flags & O_CREAT) { if (HCreate(theDirs.dataRefNum, theDirs.dataDirID, s, TEXT_CREATOR, fileType) && (flags & O_EXCL)) { return -1; } #if 0 /* Fails during makedefs */ if (fileType == SAVE_TYPE) { short resRef; HCreateResFile(theDirs.dataRefNum, theDirs.dataDirID, s); resRef = HOpenResFile(theDirs.dataRefNum, theDirs.dataDirID, s, fsRdWrPerm); if (resRef != -1) { Handle name; Str255 plnamep; C2P(g.plname, plnamep); name = (Handle)NewString(plnamep); if (name) replace_resource(name, 'STR ', PLAYER_NAME_RES_ID, "\pPlayer Name"); /* The application name resource. See IM VI, page 9-21. */ name = (Handle)GetString(APP_NAME_RES_ID); if (name) { DetachResource(name); replace_resource(name, 'STR ', APP_NAME_RES_ID, "\pApplication Name"); } CloseResFile(resRef); } } #endif } /* * Here, we should check for file type, maybe a SFdialog if * we fail with default, etc. etc. Besides, we should use HOpen * and permissions. */ if ((flags & O_RDONLY) == O_RDONLY) { perm = fsRdPerm; } if ((flags & O_WRONLY) == O_WRONLY) { perm = fsWrPerm; } if ((flags & O_RDWR) == O_RDWR) { perm = fsRdWrPerm; } if (HOpen(theDirs.dataRefNum, theDirs.dataDirID, s, perm, &refNum)) { return OpenHandleFile(s, fileType); } if (flags & O_TRUNC) { if (SetEOF(refNum, 0L)) { FSClose(refNum); return -1; } } return refNum; } int macclose(int fd) { if (IsHandleFile(fd)) { CloseHandleFile(fd); } else { if (FSClose(fd)) { return -1; } FlushVol((StringPtr) 0, theDirs.dataRefNum); } return 0; } int macread(int fd, void *ptr, unsigned len) { long amt = len; if (IsHandleFile(fd)) { return ReadHandleFile(fd, ptr, amt); } else { short err = FSRead(fd, &amt, ptr); return ((err == noErr) || (err == eofErr && len)) ? amt : -1; } } #if 0 /* this function isn't used, if you use it, uncomment prototype in \ macwin.h */ char * macgets (int fd, char *ptr, unsigned len) { int idx = 0; char c; while (-- len > 0) { if (macread (fd, ptr + idx, 1) <= 0) return (char *)0; c = ptr[idx++]; if (c == '\n' || c == '\r') break; } ptr [idx] = '\0'; return ptr; } #endif /* 0 */ int macwrite(int fd, void *ptr, unsigned len) { long amt = len; if (IsHandleFile(fd)) return -1; if (FSWrite(fd, &amt, ptr) == noErr) return (amt); else return (-1); } long macseek(int fd, long where, short whence) { short posMode; long curPos; if (IsHandleFile(fd)) { return SetHandleFilePos(fd, whence, where); } switch (whence) { default: posMode = fsFromStart; break; case SEEK_CUR: posMode = fsFromMark; break; case SEEK_END: posMode = fsFromLEOF; break; } if (SetFPos(fd, posMode, where) == noErr && GetFPos(fd, &curPos) == noErr) return (curPos); else return (-1); } int macunlink(const char *name) { Str255 pname; C2P(name, pname); return (HDelete(theDirs.dataRefNum, theDirs.dataDirID, pname) == noErr ? 0 : -1); } /* ---------------------------------------------------------------------- */ boolean rsrc_dlb_init(void) { return TRUE; } void rsrc_dlb_cleanup(void) { } boolean rsrc_dlb_fopen(dlb *dp, const char *name, const char *mode) { #if defined(__SC__) || defined(__MRC__) #pragma unused(mode) #endif Str255 pname; C2P(name, pname); dp->fd = OpenHandleFile(pname, 'File'); /* automatically read-only */ return dp->fd >= 0; } int rsrc_dlb_fclose(dlb *dp) { return CloseHandleFile(dp->fd); } int rsrc_dlb_fread(char *buf, int size, int quan, dlb *dp) { int nread; if (size < 0 || quan < 0) return 0; nread = ReadHandleFile(dp->fd, buf, (unsigned) size * (unsigned) quan); return nread / size; /* # of whole pieces (== quan in normal case) */ } int rsrc_dlb_fseek(dlb *dp, long pos, int whence) { return SetHandleFilePos(dp->fd, whence, pos); } char * rsrc_dlb_fgets(char *buf, int len, dlb *dp) { HandleFile *hfp = IsHandleFile(dp->fd); char *p; int bytesLeft, n = 0; if (hfp && hfp->mark < hfp->size) { bytesLeft = hfp->size - hfp->mark; if (bytesLeft < len) len = bytesLeft; HLock(hfp->data); for (n = 0, p = *hfp->data + hfp->mark; n < len; n++, p++) { buf[n] = *p; if (*p == '\r') buf[n] = '\n'; if (buf[n] == '\n') { n++; /* we want the return in the buffer */ break; } } HUnlock(hfp->data); hfp->mark += n; if (n != 0) buf[n] = '\0'; /* null terminate result */ } return n ? buf : NULL; } int rsrc_dlb_fgetc(dlb *dp) { HandleFile *hfp = IsHandleFile(dp->fd); int ret; if (!hfp || hfp->size <= hfp->mark) return EOF; ret = *(unsigned char *) (*hfp->data + hfp->mark); hfp->mark++; return ret; } long rsrc_dlb_ftell(dlb *dp) { HandleFile *hfp = IsHandleFile(dp->fd); if (!hfp) return 0; return hfp->mark; }