1 /*	SCCS Id: @(#)macfile.c	3.1	93/01/24		  */
2 /* Copyright (c) Jon W{tte, Hao-Yang Wang, Jonathan Handler 1992. */
3 /* NetHack may be freely redistributed.  See license for details. */
4 /*
5  * macfile.c
6  * MAC file I/O routines
7  */
8 
9 #include "hack.h"
10 #include "macwin.h"
11 
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
20 
21 #include "dlb.h"
22 
23 /*
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.
26  */
27 
28 
29 /* The HandleFiles are resources built into the application which are treated
30    as read-only files: if we fail to open a file we look for a resource */
31 
32 #define FIRST_HF 32000   /* file ID of first HandleFile */
33 #define MAX_HF 6		 /* Max # of open HandleFiles */
34 
35 #define APP_NAME_RES_ID		(-16396)
36 
37 typedef struct handlefile {
38 	long		type;  /* Resource type */
39 	short		id;	/* Resource id */
40 	long		mark;  /* Current position */
41 	long		size;  /* total size */
42 	Handle		data;  /* The resource, purgeable */
43 } HandleFile;
44 
45 static  HandleFile *FDECL(IsHandleFile,(int));
46 static int FDECL(OpenHandleFile,(const unsigned char *, long));
47 static int FDECL(CloseHandleFile,(int));
48 static int FDECL(ReadHandleFile,(int, void *, unsigned));
49 static long FDECL(SetHandleFilePos,(int, short, long));
50 
51 HandleFile theHandleFiles [MAX_HF];
52 MacDirs theDirs;		/* also referenced in macwin.c */
53 
54 
55 static HandleFile *
IsHandleFile(int fd)56 IsHandleFile(int fd)
57 {
58 	HandleFile *hfp = NULL;
59 
60 	if (fd >= FIRST_HF && fd < FIRST_HF+MAX_HF) {
61 		/* in valid range, check for data */
62 		hfp = &theHandleFiles[fd-FIRST_HF];
63 		if (!hfp->data) hfp = NULL;
64 	}
65 	return hfp;
66 }
67 
68 
69 static int
OpenHandleFile(const unsigned char * name,long fileType)70 OpenHandleFile (const unsigned char *name, long fileType)
71 {
72 	int i;
73 	Handle h;
74 	Str255 s;
75 
76 	for (i = 0; i < MAX_HF; i ++) {
77 		if (theHandleFiles[i].data == 0L) break;
78 	}
79 
80 	if (i >= MAX_HF)
81 		return -1;
82 
83 	h = GetNamedResource (fileType, name);
84 	if (!h) return (-1);
85 
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;
90 
91 	return(i + FIRST_HF);
92 }
93 
94 
95 static int
CloseHandleFile(int fd)96 CloseHandleFile (int fd)
97 {
98 	if (!IsHandleFile (fd)) {
99 	   return -1;
100 	}
101 	fd -= FIRST_HF;
102 	ReleaseResource (theHandleFiles[fd].data);
103 	theHandleFiles[fd].data = 0L;
104 	return(0);
105 }
106 
107 
108 static int
ReadHandleFile(int fd,void * ptr,unsigned len)109 ReadHandleFile (int fd, void *ptr, unsigned len)
110 {
111 	unsigned maxBytes;
112 	Handle h;
113 
114 	if (!IsHandleFile (fd)) return -1;
115 
116 	fd -= FIRST_HF;
117 	maxBytes = theHandleFiles[fd].size - theHandleFiles[fd].mark;
118 	if (len > maxBytes) len = maxBytes;
119 
120 	h = theHandleFiles[fd].data;
121 
122 	HLock(h);
123 	BlockMove (*h + theHandleFiles[fd].mark, ptr, len);
124 	HUnlock(h);
125 	theHandleFiles[fd].mark += len;
126 
127 	return(len);
128 }
129 
130 
131 static long
SetHandleFilePos(int fd,short whence,long pos)132 SetHandleFilePos (int fd, short whence, long pos)
133 {
134 	long curpos;
135 
136 	if (!IsHandleFile (fd)) return -1;
137 
138 	fd -= FIRST_HF;
139 
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;
151 	}
152 
153 	if (curpos < 0)
154 		curpos = 0;
155 	else if (curpos > theHandleFiles [fd].size)
156 		curpos = theHandleFiles [fd].size;
157 
158 	theHandleFiles [fd].mark = curpos;
159 
160 	return curpos;
161 }
162 
163 
164 void
C2P(const char * c,unsigned char * p)165 C2P (const char *c, unsigned char *p)
166 {
167 	int len = strlen (c), i;
168 
169 	if (len > 255) len = 255;
170 
171 	for (i = len; i > 0; i--)
172 		p[i] = c[i-1];
173 	p[0] = len;
174 }
175 
176 void
P2C(const unsigned char * p,char * c)177 P2C (const unsigned char *p, char *c)
178 {
179 	int idx = *p++;
180 	for (; idx > 0; idx--)
181 		*c++ = *p++;
182 	*c = '\0';
183 }
184 
185 
186 static void
replace_resource(Handle new_res,ResType its_type,short its_id,Str255 its_name)187 replace_resource(Handle new_res, ResType its_type, short its_id, Str255 its_name)
188 {
189 	Handle old_res;
190 
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);
197 	}
198 
199 	AddResource(new_res, its_type, its_id, its_name);
200 }
201 
202 
203 int
maccreat(const char * name,long fileType)204 maccreat (const char *name, long fileType){
205 	return macopen (name, O_RDWR | O_CREAT | O_TRUNC, fileType);
206 }
207 
208 
209 int
macopen(const char * name,int flags,long fileType)210 macopen (const char *name, int flags, long fileType)
211 {
212 	short refNum;
213 	short perm;
214 	Str255 s;
215 
216 	C2P (name, s);
217 	if (flags & O_CREAT) {
218 		if (HCreate (theDirs.dataRefNum, theDirs.dataDirID, s ,
219 			TEXT_CREATOR, fileType) && (flags & O_EXCL)) {
220 			return -1;
221 		}
222 
223 		if (fileType == SAVE_TYPE) {
224 			short resRef;
225 			HCreateResFile(theDirs.dataRefNum, theDirs.dataDirID, s);
226 			resRef = HOpenResFile(theDirs.dataRefNum, theDirs.dataDirID, s,
227 								  fsRdWrPerm);
228 			if (resRef != -1) {
229 				Handle name;
230 				Str255 plnamep;
231 
232 				C2P(plname, plnamep);
233 				name = (Handle)NewString(plnamep);
234 				if (name)
235 					replace_resource(name, 'STR ', PLAYER_NAME_RES_ID,
236 									"\pPlayer Name");
237 
238 				/* The application name resource.  See IM VI, page 9-21. */
239 				name = (Handle)GetString(APP_NAME_RES_ID);
240 				if (name) {
241 					DetachResource(name);
242 					replace_resource(name, 'STR ', APP_NAME_RES_ID,
243 									 "\pApplication Name");
244 				}
245 
246 				CloseResFile(resRef);
247 			}
248 		}
249 
250 	}
251 	/*
252 	 * Here, we should check for file type, maybe a SFdialog if
253 	 * we fail with default, etc. etc. Besides, we should use HOpen
254 	 * and permissions.
255 	 */
256 	if ((flags & O_RDONLY) == O_RDONLY) {
257 		perm = fsRdPerm;
258 	}
259 	if ((flags & O_WRONLY) == O_WRONLY) {
260 		perm = fsWrPerm;
261 	}
262 	if ((flags & O_RDWR) == O_RDWR) {
263 		perm = fsRdWrPerm;
264 	}
265 	if (HOpen (theDirs.dataRefNum, theDirs.dataDirID, s, perm, &refNum)) {
266 		return OpenHandleFile (s, fileType);
267 	}
268 	if (flags & O_TRUNC) {
269 		if (SetEOF (refNum, 0L)) {
270 			FSClose (refNum);
271 			return -1;
272 		}
273 	}
274 	return refNum;
275 }
276 
277 
278 int
macclose(int fd)279 macclose (int fd)
280 {
281 	if (IsHandleFile (fd)) {
282 		CloseHandleFile (fd);
283 	} else {
284 		if (FSClose (fd)) {
285 			return -1;
286 		}
287 		FlushVol ((StringPtr) 0, theDirs . dataRefNum);
288 	}
289 	return 0;
290 }
291 
292 
293 int
macread(int fd,void * ptr,unsigned len)294 macread (int fd, void *ptr, unsigned len)
295 {
296 	long amt = len;
297 
298 	if (IsHandleFile (fd)) {
299 		return ReadHandleFile (fd, ptr, amt);
300 	} else {
301 		short err = FSRead (fd, &amt, ptr);
302 
303 		return ((err == noErr) || (err == eofErr && len)) ? amt : -1;
304 	}
305 }
306 
307 
308 #if 0 /* this function isn't used, if you use it, uncomment prototype in macwin.h */
309 char *
310 macgets (int fd, char *ptr, unsigned len)
311 {
312         int idx = 0;
313         char c;
314 
315         while (-- len > 0) {
316                 if (macread (fd, ptr + idx, 1) <= 0)
317                         return (char *)0;
318                 c = ptr[idx++];
319                 if (c  == '\n' || c == '\r')
320                         break;
321         }
322         ptr [idx] = '\0';
323         return ptr;
324 }
325 #endif /* 0 */
326 
327 
328 int
macwrite(int fd,void * ptr,unsigned len)329 macwrite (int fd, void *ptr, unsigned len)
330 {
331 	long amt = len;
332 
333 	if (IsHandleFile (fd)) return -1;
334 	if (FSWrite(fd, &amt, ptr) == noErr)
335 		return (amt);
336 	else
337 		return (-1);
338 }
339 
340 
341 long
macseek(int fd,long where,short whence)342 macseek (int fd, long where, short whence)
343 {
344 	short posMode;
345 	long curPos;
346 
347 	if (IsHandleFile (fd)) {
348 		return SetHandleFilePos (fd, whence, where);
349 	}
350 
351 	switch (whence) {
352 		default :
353 			posMode = fsFromStart;
354 			break;
355 		case SEEK_CUR :
356 			posMode = fsFromMark;
357 			break;
358 		case SEEK_END :
359 			posMode = fsFromLEOF;
360 			break;
361 	}
362 
363 	if (SetFPos(fd, posMode, where) == noErr && GetFPos(fd, &curPos) == noErr)
364 		return (curPos);
365 	else
366 		return(-1);
367 }
368 
369 
370 int
macunlink(const char * name)371 macunlink(const char *name)
372 {
373 	Str255 pname;
374 
375 
376 	C2P(name, pname);
377 	return (HDelete(theDirs.dataRefNum, theDirs.dataDirID, pname) == noErr ? 0 : -1);
378 }
379 
380 
381 
382 /* ---------------------------------------------------------------------- */
383 
rsrc_dlb_init(void)384 boolean rsrc_dlb_init(void) {
385 	return TRUE;
386 }
387 
rsrc_dlb_cleanup(void)388 void rsrc_dlb_cleanup(void) {
389 }
390 
rsrc_dlb_fopen(dlb * dp,const char * name,const char * mode)391 boolean 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;
396 
397 	C2P(name, pname);
398 	dp->fd = OpenHandleFile(pname, 'File');	/* automatically read-only */
399 	return dp->fd >= 0;
400 }
401 
rsrc_dlb_fclose(dlb * dp)402 int rsrc_dlb_fclose(dlb *dp) {
403 	return CloseHandleFile(dp->fd);
404 }
405 
rsrc_dlb_fread(char * buf,int size,int quan,dlb * dp)406 int rsrc_dlb_fread(char *buf, int size, int quan, dlb *dp) {
407 	int nread;
408 
409 	if (size < 0 || quan < 0) return 0;
410 	nread = ReadHandleFile(dp->fd, buf, (unsigned)size * (unsigned)quan);
411 
412 	return nread/size;	/* # of whole pieces (== quan in normal case) */
413 }
414 
rsrc_dlb_fseek(dlb * dp,long pos,int whence)415 int rsrc_dlb_fseek(dlb *dp, long pos, int whence) {
416 	return SetHandleFilePos(dp->fd, whence, pos);
417 }
418 
rsrc_dlb_fgets(char * buf,int len,dlb * dp)419 char *rsrc_dlb_fgets(char *buf, int len, dlb *dp) {
420 	HandleFile *hfp = IsHandleFile(dp->fd);
421 	char *p;
422 	int bytesLeft, n = 0;
423 
424 	if (hfp && hfp->mark < hfp->size) {
425 		bytesLeft = hfp->size - hfp->mark;
426 		if (bytesLeft < len)
427 			len = bytesLeft;
428 
429 		HLock(hfp->data);
430 		for (n = 0, p = *hfp->data+hfp->mark; n < len; n++, p++) {
431 			buf[n] = *p;
432 			if (*p == '\r') buf[n] = '\n';
433 			if (buf[n] == '\n') {
434 				n++;		/* we want the return in the buffer */
435 				break;
436 			}
437 		}
438 		HUnlock(hfp->data);
439 
440 		hfp->mark += n;
441 		if (n != 0)
442 			buf[n] = '\0';	/* null terminate result */
443 	}
444 
445 	return n ? buf : NULL;
446 }
447 
rsrc_dlb_fgetc(dlb * dp)448 int rsrc_dlb_fgetc(dlb *dp) {
449 	HandleFile *hfp = IsHandleFile(dp->fd);
450 	int ret;
451 
452 	if (!hfp || hfp->size <= hfp->mark) return EOF;
453 
454 	ret = *(unsigned char *)(*hfp->data + hfp->mark);
455 	hfp->mark++;
456 	return ret;
457 }
458 
rsrc_dlb_ftell(dlb * dp)459 long rsrc_dlb_ftell(dlb *dp) {
460 	HandleFile *hfp = IsHandleFile(dp->fd);
461 
462 	if (!hfp) return 0;
463 	return hfp->mark;
464 }
465 
466