Files
nethack/sys/mac/macfile.c
nethack.allison e7b25a1900 more trunk 3.5
2005-01-02 20:55:41 +00:00

467 lines
8.9 KiB
C

/* SCCS Id: @(#)macfile.c 3.5 1993/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 <files.h>
#include <errors.h>
#include <resources.h>
#include <memory.h>
#include <TextUtils.h>
#include <ToolUtils.h>
#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(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;
}