/* SCCS Id: @(#)macfile.c 3.1 93/01/24 */ /* 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 (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(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); } } } /* * 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; }