/**********************************************************************
This file is part of Crack dot Com's free source code release of
Golgotha.
for
information about compiling & licensing issues visit this URL
If that doesn't help, contact Jonathan Clark at golgotha_source@usa.net (Subject should have "GOLG" in it) ***********************************************************************/ #include#include #include #include #include "file/file.hh" #include "threads/threads.hh" #include "file/buf_file.hh" #include "file/get_dir.hh" #include "video/display.hh" extern i4_critical_section_class i4_file_lock; // Mac Specific Global Variables short mac_volume; long mac_directory; OSType mac_creator; OSType mac_filetype; // Asynchronous File Support Variables static i4_file_class::async_callback current_read_callback; static void *current_read_context; static HParamBlockRec read_pb; static IOCompletionUPP read_complete_upp; static i4_file_class::async_callback current_write_callback; static void *current_write_context; static HParamBlockRec write_pb; static IOCompletionUPP write_complete_upp; //////////////////////////////////////////////////////////////////////// // // Mac internal routines // long GetCurDirID() { return LMGetCurDirStore(); } // gets current id of the current directory short GetCurVRefNum() { return LMGetSFSaveDisk(); } // get current reference number of the current mac voume //////////////////////////////////////////////////////////////////////// // // Normal Mac File Class // class i4_mac_file_class : public i4_file_class //{{{ { protected: short ioRefNum; public: i4_mac_file_class(short ref) : ioRefNum(ref) {} virtual w32 read (void *buffer, w32 count) // perform normal read through Synchronous HFS routines //{{{ { OSErr err; i4_file_lock.lock(); w32 ret=count; err = ::FSRead(ioRefNum,(long*)&ret,buffer); if (err && err != eofErr) ret = 0; i4_file_lock.unlock(); return ret; } //}}} virtual w32 write(void *buffer, w32 count) // perform normal write through Synchronous HFS routines //{{{ { OSErr err; i4_file_lock.lock(); w32 ret=count; err = ::FSWrite(ioRefNum,(long*)&ret,buffer); if (err && err != eofErr) ret = 0; i4_file_lock.unlock(); return ret; } //}}} virtual w32 seek (w32 offset) // perform normal seek through Synchronous HFS routines //{{{ { OSErr err; i4_file_lock.lock(); w32 ret=offset; err = ::SetFPos(ioRefNum,fsFromStart,(long)offset); if (err && err != eofErr) ret = 0; i4_file_lock.unlock(); return ret; } //}}} virtual w32 size () // get logical file size through Synchronous HFS routines //{{{ { i4_file_lock.lock(); w32 len = 0; ::GetEOF(ioRefNum, (long*)&len); i4_file_lock.unlock(); return len; } //}}} virtual w32 tell () // get logical file position through Synchronous HFS routines //{{{ { i4_file_lock.lock(); w32 ret=0; ::GetFPos(ioRefNum,(long*)&ret); i4_file_lock.unlock(); return ret; } //}}} virtual i4_bool async_read (void *buffer, w32 count, async_callback call, void *context=0); virtual i4_bool async_write(void *buffer, w32 count, async_callback call, void *context=0); ~i4_mac_file_class() //{{{ { i4_file_lock.lock(); ::FSClose(ioRefNum); //::FlushVol(0,mac_volume); i4_file_lock.unlock(); } //}}} }; //}}} static void mac_read_complete(HParmBlkPtr blk) // callback routine for MAC PB device interface //{{{ { (*current_read_callback)(blk->ioParam.ioActCount,current_read_context); current_read_callback = 0; current_read_context = 0; } //}}} static void mac_write_complete(HParmBlkPtr blk) // callback routine for MAC PB device interface //{{{ { (*current_write_callback)(blk->ioParam.ioActCount,current_write_context); current_write_callback = 0; current_write_context = 0; } //}}} i4_bool i4_mac_file_class::async_read (void *buffer, w32 count, i4_file_class::async_callback call, void *context) //{{{ { #if 0 // use default read for testing purposes i4_bool ret = read(buffer,count); (*call)(ret,context); return i4_T; #else OSErr err; read_pb.ioParam.ioCompletion = read_complete_upp; read_pb.ioParam.ioRefNum = ioRefNum; read_pb.ioParam.ioBuffer = (Ptr)buffer; read_pb.ioParam.ioReqCount = count; read_pb.ioParam.ioPosMode = fsAtMark; current_read_callback = call; current_read_context = context; // call asynchronous read through PB device interface err = PBReadAsync( (ParmBlkPtr)&read_pb ); if ( err != noErr) return i4_F; return i4_T; #endif } //}}} i4_bool i4_mac_file_class::async_write (void *buffer, w32 count, i4_file_class::async_callback call, void *context) //{{{ { #if 1 // use default write for testing purposes i4_bool ret = write(buffer,count); (*call)(ret,context); return i4_T; #else OSErr err; write_pb.ioParam.ioCompletion = write_complete_upp; write_pb.ioParam.ioRefNum = ioRefNum; write_pb.ioParam.ioBuffer = (Ptr)buffer; write_pb.ioParam.ioReqCount = count; write_pb.ioParam.ioPosMode = fsAtMark; current_write_callback = call; current_write_context = context; // call asynchronous write through PB device interface err = PBWriteAsync( (ParmBlkPtr)&write_pb ); if ( err != noErr) return i4_F; return i4_T; #endif } //}}} //////////////////////////////////////////////////////////////////////// // // OS Name functions // Str255 MacName; StringPtr mac_os_string(const i4_const_str &name) // convert C string i4 name into Pascal string to use in Macintosh interfaces //{{{ { i4_const_str::iterator p=name.begin(); int s=1, s2; char ch; if (p!=name.end()) { if (p.get().value() == '/') ++p; else MacName[s++] = ':'; } while (p!=name.end()) { if (p.get().value()=='/') { MacName[s++]=':'; ++p; } s2 = s; ch = 0; while (p!=name.end()) { ch = p.get().value(); if (ch == '/') break; MacName[s++]= ch; ++p; } MacName[s] = 0; if (MacName[s2] == '.') if (MacName[s2+1] == '.') { MacName[s2] = ':'; s = s2+1; if (ch=='/') ++p; } else if (MacName[s2+1] == 0) if (ch=='/') ++p; } MacName[s]=0; MacName[0] = s-1; return MacName; } //}}} char *i4_os_string(const i4_const_str &name) // convert C string i4 name into C string Mac style filename, mainly for debugging //{{{ { return ((char*)mac_os_string(name))+1; } //}}} //////////////////////////////////////////////////////////////////////// // // File Manager Methods // i4_file_manager_class::i4_file_manager_class() //{{{ { mac_volume = 0; // GetCurVRefNum(); mac_directory = GetCurDirID(); read_complete_upp = NewIOCompletionProc(mac_read_complete); write_complete_upp = NewIOCompletionProc(mac_write_complete); } //}}} i4_file_class *i4_file_manager_class::default_open(const i4_const_str &name, w32 flags) //{{{ { OSErr err; i4_file_lock.lock(); i4_bool no_buffer=i4_F; if (flags & NO_BUFFER) { flags=(file_flags)(flags & (~NO_BUFFER)); no_buffer=i4_T; } SignedByte mac_flags; switch (flags) { case READ: mac_flags = fsRdPerm; break; case WRITE: case APPEND: case WRITE|APPEND: mac_flags = fsWrPerm; break; case WRITE|READ: mac_flags = fsRdWrPerm; break; default: i4_warning("i4_file_class::Bad open flags!"); i4_file_lock.unlock(); return NULL; } if ((flags & WRITE) && !(flags & APPEND)) { // If rewriting file, delete & create file ::HDelete( mac_volume, mac_directory, mac_os_string(name) ); if (::HCreate(mac_volume, mac_directory, mac_os_string(name), mac_creator, mac_filetype ) != noErr) { i4_warning("i4_file_class::create failed for %s\n",i4_os_string(name)); i4_file_lock.unlock(); return NULL; } } short FRef; // Attempt to open file, synchronously, for now err = ::HOpen(mac_volume, mac_directory, mac_os_string(name), mac_flags, &FRef); if ( err != noErr) { i4_warning("i4_file_class::open failed for %s\n",i4_os_string(name)); i4_file_lock.unlock(); return NULL; } i4_file_class *ret_fp; if (!no_buffer) ret_fp=new i4_buffered_file_class(new i4_mac_file_class(FRef), 0x1000, 0); else ret_fp=new i4_mac_file_class(FRef); // if append, seek to end if (flags & APPEND) ret_fp->seek(ret_fp->size()); i4_file_lock.unlock(); return ret_fp; } //}}} i4_bool i4_file_manager_class::default_unlink(const i4_const_str &name) //{{{ { return ::HDelete(mac_volume, mac_directory, mac_os_string(name))==noErr; } //}}} i4_bool i4_file_manager_class::default_get_status(const i4_const_str &name, i4_file_status_struct &return_stat) //{{{ { HParamBlockRec stat; OSErr err; // search from current directory and volume stat.fileParam.ioVRefNum = mac_volume; stat.fileParam.ioFVersNum = 0; stat.fileParam.ioFDirIndex = 0; stat.fileParam.ioNamePtr = mac_os_string(name); stat.fileParam.ioDirID = mac_directory; err = PBHGetFInfoSync(&stat); if (err) return i4_F; return_stat.last_modified = stat.fileParam.ioFlMdDat; return i4_T; } //}}} i4_bool i4_file_manager_class::default_mkdir(const i4_const_str &name) //{{{ { long id; return ::DirCreate(mac_volume, mac_directory, mac_os_string(name), &id)==noErr; } //}}} i4_bool i4_file_manager_class::default_get_directory(const i4_const_str &path, i4_str **&files, w32 &tfiles, i4_str **&dirs, w32 &tdirs) // returns i4_F if path is bad (tfiles and tdirs will be 0 as well) //{{{ { return ::i4_get_directory(path, files,tfiles, dirs,tdirs); } //}}} //{{{ Emacs Locals // Local Variables: // folded-file: t // End: //}}}