#include	"compiler.h"
#include	"dosio.h"
static	char	curpath[MAX_PATH] = ":";
static	char	*curfilep = curpath + 1;
#define ISKANJI(c)	(((((c) ^ 0x20) - 0xa1) & 0xff) < 0x3c)
void dosio_init(void) { }
void dosio_term(void) { }
											// ファイル操作
FILEH file_open(const char *path) {
	FILEH	ret;
	FSSpec	fss;
	Str255	fname;
	mkstr255(fname, path);
	FSMakeFSSpec(0, 0, fname, &fss);
	if ((FSpOpenDF(&fss, fsRdWrPerm, &ret) == noErr) ||
		(FSpOpenDF(&fss, fsRdPerm, &ret) == noErr)) {
		SetFPos(ret, fsFromStart, 0);
		return(ret);
	}
	return(-1);
}
FILEH file_open_rb(const char *path) {
	FILEH	ret;
	FSSpec	fss;
	Str255	fname;
	mkstr255(fname, path);
	FSMakeFSSpec(0, 0, fname, &fss);
	if ((FSpOpenDF(&fss, fsRdWrShPerm, &ret) == noErr) ||
		(FSpOpenDF(&fss, fsRdPerm, &ret) == noErr)) {
		SetFPos(ret, fsFromStart, 0);
		return(ret);
	}
	return(-1);
}
FILEH file_create(const char *path) {
	FILEH	ret;
	FSSpec	fss;
	Str255	fname;
	OSType	creator = kUnknownType;
	OSType	fileType = kUnknownType;
	mkstr255(fname, path);
	FSMakeFSSpec(0, 0, fname, &fss);
	FSpDelete(&fss);
	if (FSpCreate(&fss, creator, fileType, smSystemScript) == noErr) {
		if ((FSpOpenDF(&fss, fsRdPerm | fsWrPerm, &ret) == noErr) ||
			(FSpOpenDF(&fss, fsRdPerm, &ret) == noErr)) {
			SetFPos(ret, fsFromStart, 0);
			return(ret);
		}
	}
	return(-1);
}
long file_seek(FILEH handle, long pointer, int method) {
	SInt32	pos;
	SInt32	setp;
	setp = pointer;
	switch(method) {
		case FSEEK_SET:
			break;
		case FSEEK_CUR:
			if (GetFPos(handle, &pos) != noErr) {
				return(-1);
			}
			setp += pos;
			break;
		case FSEEK_END:
			if (GetEOF(handle, &pos) != noErr) {
				return(-1);
			}
			setp += pos;
			break;
		default:
			return(-1);
	}
	SetFPos(handle, fsFromStart, setp);
	if (GetFPos(handle, &pos) != noErr) {
		return(-1);
	}
	return((long)pos);
}
UINT file_read(FILEH handle, void *data, UINT length) {
	long	size;
	OSErr	err;
	size = length;
	err = FSRead(handle, &size, (char *)data);
	if ((err == noErr) || (err == eofErr)) {
		return(size);
	}
	return(0);
}
UINT file_write(FILEH handle, const void *data, UINT length) {
	if (length) {
		long size = length;
		if (FSWrite(handle, &size, (char *)data) == noErr) {
			return(size);
		}
	}
	else {
		SInt32 pos;
		if (GetFPos(handle, &pos) == noErr) {
			SetEOF(handle, pos);
		}
	}
	return(0);
}
short file_close(FILEH handle) {
	FSClose(handle);
	return(0);
}
UINT file_getsize(FILEH handle) {
	SInt32 pos;
	if (GetEOF(handle, &pos) == noErr) {
		return((UINT)pos);
	}
	else {
		return(0);
	}
}
static void cnvdatetime(UTCDateTime *dt, DOSDATE *dosdate, DOSTIME *dostime) {
	LocalDateTime	ldt;
	DateTimeRec		dtr;
	ZeroMemory(&dtr, sizeof(dtr));
	ConvertUTCToLocalDateTime(dt, &ldt);
	SecondsToDate(ldt.lowSeconds, &dtr);
	if (dosdate) {
		dosdate->year = dtr.year;
		dosdate->month = (UINT8)dtr.month;
		dosdate->day = (UINT8)dtr.day;
	}
	if (dostime) {
		dostime->hour = (UINT8)dtr.hour;
		dostime->minute = (UINT8)dtr.minute;
		dostime->second = (UINT8)dtr.second;
	}
}
short file_getdatetime(FILEH handle, DOSDATE *dosdate, DOSTIME *dostime) {
#ifdef TARGET_API_MAC_CARBON
	FSRef			ref;
	FSCatalogInfo	fsci;
	if ((FSGetForkCBInfo(handle, 0, NULL, NULL, NULL, &ref, NULL) != noErr) ||
		(FSGetCatalogInfo(&ref, kFSCatInfoContentMod, &fsci, NULL, NULL, NULL)
																!= noErr)) {
		return(-1);
	}
	cnvdatetime(&fsci.contentModDate, dosdate, dostime);
	return(0);
#else
	(void)handle;
	(void)dosdate;
	(void)dostime;
	return(-1);
#endif
}
short file_delete(const char *path) {
	FSSpec	fss;
	Str255	fname;
	mkstr255(fname, path);
	FSMakeFSSpec(0, 0, fname, &fss);
	FSpDelete(&fss);
	return(0);
}
short file_attr(const char *path) {
	Str255			fname;
	FSSpec			fss;
	FSRef			fsr;
	FSCatalogInfo	fsci;
	short			ret;
	mkstr255(fname, path);
	if ((FSMakeFSSpec(0, 0, fname, &fss) != noErr) ||
		(FSpMakeFSRef(&fss, &fsr) != noErr) ||
		(FSGetCatalogInfo(&fsr, kFSCatInfoNodeFlags, &fsci,
										NULL, NULL, NULL) != noErr)) {
		return(-1);
	}
	if (fsci.nodeFlags & kFSNodeIsDirectoryMask) {
		ret = FILEATTR_DIRECTORY;
	}
	else {
		ret = FILEATTR_ARCHIVE;
	}
	if (fsci.nodeFlags & kFSNodeLockedMask) {
		ret |= FILEATTR_READONLY;
	}
	return(ret);
}
short file_dircreate(const char *path) {
	FSSpec	fss;
	Str255	fname;
	long	ret;
	mkstr255(fname, path);
	FSMakeFSSpec(0, 0, fname, &fss);
	if (FSpDirCreate(&fss, smSystemScript, &ret) == noErr) {
		return(0);
	}
	return(-1);
}
											// カレントファイル操作
void file_setcd(const char *exepath) {
	file_cpyname(curpath, exepath, sizeof(curpath));
	curfilep = file_getname(curpath);
	*curfilep = '\0';
}
char *file_getcd(const char *path) {
	*curfilep = '\0';
	file_catname(curpath, path, sizeof(curpath));
	return(curpath);
}
FILEH file_open_c(const char *path) {
	*curfilep = '\0';
	file_catname(curpath, path, sizeof(curpath));
	return(file_open(curpath));
}
FILEH file_open_rb_c(const char *path) {
	*curfilep = '\0';
	file_catname(curpath, path, sizeof(curpath));
	return(file_open_rb(curpath));
}
FILEH file_create_c(const char *path) {
	*curfilep = '\0';
	file_catname(curpath, path, sizeof(curpath));
	return(file_create(curpath));
}
short file_delete_c(const char *path) {
	*curfilep = '\0';
	file_catname(curpath, path, sizeof(curpath));
	return(file_delete(curpath));
}
short file_attr_c(const char *path) {
	*curfilep = '\0';
	file_catname(curpath, path, sizeof(curpath));
	return(file_attr(curpath));
}
typedef struct {
	BOOL			eoff;
	FSIterator		fsi;
	FSCatalogInfo	fsci;
	HFSUniStr255	name;
} _FLHDL, *FLHDL;
static void char2str(char *dst, int size, const UniChar *uni, int unicnt) {
	CFStringRef	cfsr;
	cfsr = CFStringCreateWithCharacters(NULL, uni, unicnt);
	CFStringGetCString(cfsr, dst, size, CFStringGetSystemEncoding());
	CFRelease(cfsr);
}
void *file_list1st(const char *dir, FLINFO *fli) {
	FLISTH		ret;
	Str255		fname;
	FSSpec		fss;
	FSRef		fsr;
	FSIterator	fsi;
	mkstr255(fname, dir);
	if ((FSMakeFSSpec(0, 0, fname, &fss) != noErr) ||
		(FSpMakeFSRef(&fss, &fsr) != noErr) ||
		(FSOpenIterator(&fsr, kFSIterateFlat, &fsi) != noErr)) {
		goto ff1_err1;
	}
	ret = _MALLOC(sizeof(_FLHDL), dir);
	if (ret == NULL) {
		goto ff1_err2;
	}
	((FLHDL)ret)->eoff = FALSE;
	((FLHDL)ret)->fsi = fsi;
	if (file_listnext(ret, fli) == SUCCESS) {
		return(ret);
	}
ff1_err2:
	FSCloseIterator(fsi);
ff1_err1:
	return(NULL);
}
BOOL file_listnext(FLISTH hdl, FLINFO *fli) {
	FLHDL		flhdl;
	ItemCount	count;
	OSStatus	r;
	UTCDateTime	*dt;
	flhdl = (FLHDL)hdl;
	if ((flhdl == NULL) || (flhdl->eoff)) {
		goto ffn_err;
	}
	r = FSGetCatalogInfoBulk(flhdl->fsi, 1, &count, NULL,
						kFSCatInfoNodeFlags | kFSCatInfoDataSizes |
						kFSCatInfoAllDates,
						&flhdl->fsci, NULL, NULL, &flhdl->name);
	if (r != noErr) {
		flhdl->eoff = TRUE;
		if (r != errFSNoMoreItems) {
			goto ffn_err;
		}
	}
	if (count != 1) {
		flhdl->eoff = TRUE;
		goto ffn_err;
	}
	if (fli) {
		fli->caps = FLICAPS_SIZE | FLICAPS_ATTR | FLICAPS_DATE | FLICAPS_TIME;
		if (flhdl->fsci.nodeFlags & kFSNodeIsDirectoryMask) {
			fli->attr = FILEATTR_DIRECTORY;
			fli->size = 0;
			dt = &flhdl->fsci.createDate;
		}
		else {
			fli->attr = FILEATTR_ARCHIVE;
			fli->size = (UINT32)flhdl->fsci.dataLogicalSize;
			dt = &flhdl->fsci.contentModDate;
		}
		cnvdatetime(dt, &fli->date, &fli->time);
		char2str(fli->path, sizeof(fli->path),
								flhdl->name.unicode, flhdl->name.length);
	}
	return(SUCCESS);
ffn_err:
	return(FAILURE);
}
void file_listclose(FLISTH hdl) {
	if (hdl) {
		FSCloseIterator(((FLHDL)hdl)->fsi);
		_MFREE(hdl);
	}
}
BOOL getLongFileName(char *dst, const char *path) {
	FSSpec			fss;
	Str255			fname;
	FSRef			fref;
	HFSUniStr255	name;
	if (*path == '\0') {
		return(false);
	}
	mkstr255(fname, path);
	FSMakeFSSpec(0, 0, fname, &fss);
	FSpMakeFSRef(&fss, &fref);
	if (FSGetCatalogInfo(&fref, kFSCatInfoNone, NULL, &name, NULL, NULL)
																!= noErr) {
		return(false);
	}
	char2str(dst, 512, name.unicode, name.length);
	if (!dst) {
		return(false);
	}
	return(true);
}
void file_catname(char *path, const char *sjis, int maxlen) {
	char	*p;
	p = path + strlen(path);
	milstr_ncat(path, sjis, maxlen);
	while(1) {
		if (ISKANJI(*p)) {
			if (*(p+1) == '\0') {
				break;
			}
			p++;
		}
		else if ((*p == '/') || (*p == '\\')) {
			*p = ':';
		}
		else if (*p == '\0') {
			break;
		}
		p++;
	}
}
char *file_getname(const char *path) {
	const char 	*ret;
	ret = path;
	while(*path != '\0') {
		if (*path++ == ':') {
			ret = path;
		}
	}
	return((char *)ret);
}
void file_cutname(char *path) {
	char 	*p;
	p = file_getname(path);
	p[0] = '\0';
}
char *file_getext(const char *path) {
	char	*p;
	char	*q;
	p = file_getname(path);
	q = NULL;
	while(*p != '\0') {
		if (*p++ == '.') {
			q = p;
		}
	}
	if (!q) {
		q = p;
	}
	return(q);
}
void file_cutext(char *path) {
	char	*p;
	char	*q;
	p = file_getname(path);
	q = NULL;
	while(*p != '\0') {
		if (*p == '.') {
			q = p;
		}
		p++;
	}
	if (q) {
		*q = '\0';
	}
}
void file_cutseparator(char *path) {
	int		pos;
	pos = strlen(path) - 1;
	if ((pos > 0) && (path[pos] == ':')) {
		path[pos] = '\0';
	}
}
void file_setseparator(char *path, int maxlen) {
	int		pos;
	pos = strlen(path) - 1;
	if ((pos < 0) || (path[pos] == ':') || ((pos + 2) >= maxlen)) {
		return;
	}
	path[++pos] = ':';
	path[++pos] = '\0';
}
RetroPC.NET-CVS <cvs@retropc.net>