home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / nethack-3.1 / sys / mac / macfile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-25  |  10.0 KB  |  477 lines

  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.  
  11. #include <files.h>
  12. #include <errors.h>
  13. #include <resources.h>
  14. #include <memory.h>
  15. #include <ToolUtils.h>
  16.  
  17. /*
  18.  * We should get the default dirID and volRefNum (from name) from prefs and
  19.  * the situation at startup... For now, this will have to do.
  20.  */
  21.  
  22.  
  23. /* The HandleFiles are resources built into the application which are treated
  24.    as read-only files: if we fail to open a file we look for a resource */
  25.    
  26. #define FIRST_HF 32000   /* file ID of first HandleFile */
  27. #define MAX_HF 6         /* Max # of open HandleFiles */
  28.  
  29. #define APP_NAME_RES_ID        (-16396)
  30. #define PLAYER_NAME_RES_ID    1001
  31.  
  32. int FDECL(maccreat,(const char *, long));
  33. int FDECL(macopen,(const char *, int, long));
  34. int FDECL(macclose,(int));
  35. int FDECL(macread,(int, void *, unsigned));
  36. int FDECL(macwrite,(int, void *, unsigned));
  37. long FDECL(macseek,(int, long, short));
  38.  
  39. static short FDECL(IsHandleFile,(int));
  40. static int FDECL(OpenHandleFile,(const unsigned char *, long));
  41. static int FDECL(CloseHandleFile,(int));
  42. static int FDECL(ReadHandleFile,(int, void *, unsigned));
  43. static long FDECL(SetHandleFilePos,(int, short, long));
  44. static void FDECL(C2P,(const char *, unsigned char *));
  45.  
  46. typedef struct handlefile {
  47.     long        type ;  /* Resource type */
  48.     short        id ;    /* Resource id */
  49.     long        mark ;  /* Current position */
  50.     long        size ;  /* total size */
  51.     Handle        data ;  /* The resource, purgeable */
  52. } HandleFile ;
  53.  
  54. HandleFile theHandleFiles [ MAX_HF ] ;
  55.  
  56. static short
  57. IsHandleFile ( int fd )
  58. {
  59.     return (fd >= FIRST_HF) && 
  60.            (fd < FIRST_HF + MAX_HF) && 
  61.            (theHandleFiles[ fd - FIRST_HF ].data) ;
  62. }
  63.  
  64.  
  65. static int
  66. OpenHandleFile ( const unsigned char * name , long fileType )
  67. {
  68.     int i ;
  69.     OSErr err;
  70.     Handle h ;
  71.     Str255 s ;
  72.  
  73.     for ( i = 0 ; i < MAX_HF ; i ++ ) {
  74.         if ( theHandleFiles[i].data == 0L ) break ;
  75.     }
  76.     
  77.     if ( i >= MAX_HF ) {
  78.         error("Ran out of HandleFiles");
  79.         return -1 ;
  80.     }
  81.  
  82.     h = GetNamedResource ( fileType , name ) ;
  83.     err = ResError();
  84.     if (err == resNotFound) return -1;  /* Don't complain, this might be normal */
  85.     if ( ! itworked(err) ) return -1;
  86.     
  87.     theHandleFiles[i].data = h;
  88.     theHandleFiles[i].size = GetHandleSize ( h ) ;
  89.     GetResInfo ( h, & theHandleFiles[i].id, ( void* ) & theHandleFiles[i].type, s ) ;
  90.     theHandleFiles[i].mark = 0L ;
  91.  
  92.     HPurge( h ) ;
  93.     return(i + FIRST_HF);
  94. }
  95.  
  96.  
  97. static int
  98. CloseHandleFile ( int fd )
  99. {
  100.     if ( ! IsHandleFile ( fd ) ) {
  101.        error("CloseHandleFile: isn't a handle");
  102.        return -1 ;
  103.     }
  104.     fd -= FIRST_HF ;
  105.     ReleaseResource ( theHandleFiles[fd].data ) ;
  106.     theHandleFiles[fd].data = 0L ;
  107.     return(0);
  108. }
  109.  
  110.  
  111. static int
  112. ReadHandleFile ( int fd , void * ptr , unsigned len )
  113. {
  114.     unsigned maxBytes ;
  115.     Handle h ;
  116.  
  117.     if ( ! IsHandleFile ( fd ) ) return -1;
  118.     
  119.     fd -= FIRST_HF ;
  120.     maxBytes = theHandleFiles[fd].size - theHandleFiles[fd].mark ;
  121.     if ( len > maxBytes ) len = maxBytes ;
  122.     
  123.     h = theHandleFiles[fd].data ;
  124.     LoadResource ( h ) ;
  125.     if ( ! itworked(ResError()) ) return (-1);
  126.     
  127.     HLock(h);
  128.     BlockMove ( *h , ptr , len );
  129.     HUnlock(h);
  130.     theHandleFiles[fd].mark += len ;
  131.  
  132. /*    comment("ReadHandleFile ",len); */
  133.     
  134.     return(len);
  135. }
  136.  
  137.  
  138. static long
  139. SetHandleFilePos ( int fd , short whence , long pos )
  140. {
  141.     long curpos;
  142.     
  143.     if ( ! IsHandleFile ( fd ) ) return -1;
  144.     
  145.     fd -= FIRST_HF ;
  146.     
  147.     curpos = theHandleFiles [ fd ].mark;
  148.     switch ( whence ) {
  149.     case SEEK_CUR : 
  150.         curpos += pos ;
  151.         break ;
  152.     case SEEK_END : 
  153.         curpos = theHandleFiles[fd].size  - pos ;
  154.         break ;
  155.     default : /* set */
  156.         curpos = pos ;
  157.         break ;
  158.     }
  159.  
  160.     if ( curpos < 0 ) curpos = 0 ;
  161.     
  162.     if ( curpos > theHandleFiles [ fd ].size ) curpos = theHandleFiles [ fd ].size ;
  163.     
  164.     theHandleFiles [ fd ].mark = curpos;
  165.     
  166.     return curpos ;
  167. }
  168.  
  169.  
  170. static void
  171. C2P ( const char * c , unsigned char * p )
  172. {
  173.     long len = strlen ( c ) ;
  174.  
  175.     if ( len > 255 ) len = 255 ;
  176.  
  177.     p[0] = len & 0xff ;
  178.     while (*c) *++p = *c++;
  179. }
  180.  
  181. static void
  182. P2C ( const unsigned char * p , char * c )
  183. {
  184.     int idx = p[0];
  185.     c[idx] = '\0';
  186.     while (idx > 0) {
  187.         c[idx-1] = p[idx];
  188.         --idx;
  189.     }
  190. }
  191.  
  192.  
  193. static void
  194. replace_resource(Handle new_res, ResType its_type, short its_id,
  195.                  Str255 its_name) {
  196.     Handle old_res;
  197.     SetResLoad(false);
  198.     old_res = Get1Resource(its_type, its_id);
  199.     SetResLoad(true);
  200.     if (old_res) {
  201.         RmveResource(old_res);
  202.         DisposHandle(old_res);
  203.     }
  204.  
  205.     AddResource(new_res, its_type, its_id, its_name);
  206. }
  207.  
  208.  
  209. int
  210. maccreat ( const char * name , long fileType )
  211. {
  212.     return macopen ( name , O_RDWR | O_CREAT | O_TRUNC , fileType ) ;
  213. }
  214.  
  215.  
  216. int
  217. macopen ( const char * name , int flags , long fileType )
  218. {
  219.     short refNum ;
  220.     short perm ;
  221.     Str255 s ;
  222.  
  223.     C2P ( name , s ) ;
  224.     if ( flags & O_CREAT ) {
  225.         if ( HCreate ( theDirs.dataRefNum , theDirs.dataDirID , s ,
  226.             MAC_CREATOR , fileType ) && ( flags & O_EXCL ) ) {
  227.             return -1 ;
  228.         }
  229.  
  230.         if (fileType == SAVE_TYPE) {
  231.             short resRef;
  232.             HCreateResFile(theDirs.dataRefNum, theDirs.dataDirID, s);
  233.             resRef = HOpenResFile(theDirs.dataRefNum, theDirs.dataDirID, s,
  234.                                   fsRdWrPerm);
  235.             if (resRef != -1) {
  236.                 Handle name;
  237.                 Str255 plnamep;
  238.  
  239.                 C2P(plname, plnamep);
  240.                 name = (Handle)NewString(plnamep);
  241.                 if (name)
  242.                     replace_resource(name, 'STR ', PLAYER_NAME_RES_ID,
  243.                                     "\pPlayer Name");
  244.  
  245.                 /* The application name resource.  See IM VI, page 9-21. */
  246.                 name = (Handle)GetString(APP_NAME_RES_ID);
  247.                 if (name) {
  248.                     DetachResource(name);
  249.                     replace_resource(name, 'STR ', APP_NAME_RES_ID,
  250.                                      "\pApplication Name");
  251.                 }
  252.  
  253.                 CloseResFile(resRef);
  254.             }
  255.         }
  256.  
  257.     }
  258.     /*
  259.      * Here, we should check for file type, maybe a SFdialog if
  260.      * we fail with default, etc. etc. Besides, we should use HOpen
  261.      * and permissions.
  262.      */
  263.     if ( ( flags & O_RDONLY ) == O_RDONLY ) {
  264.         perm = fsRdPerm ;
  265.     }
  266.     if ( ( flags & O_WRONLY ) == O_WRONLY ) {
  267.         perm = fsWrPerm ;
  268.     }
  269.     if ( ( flags & O_RDWR ) == O_RDWR ) {
  270.         perm = fsRdWrPerm ;
  271.     }
  272.     if ( HOpen ( theDirs.dataRefNum , theDirs.dataDirID , s ,
  273.         perm , & refNum ) ) {
  274.         return OpenHandleFile ( s , fileType ) ;
  275.     }
  276.     if ( flags & O_TRUNC ) {
  277.         if ( SetEOF ( refNum , 0L ) ) {
  278.             FSClose ( refNum ) ;
  279.             return -1 ;
  280.         }
  281.     }
  282.     return refNum ;
  283. }
  284.  
  285.  
  286. int
  287. macclose ( int fd )
  288. {
  289.     if ( IsHandleFile ( fd ) ) {
  290.         CloseHandleFile ( fd ) ;
  291.     } else {
  292.         if ( FSClose ( fd ) ) {
  293.             return -1 ;
  294.         }
  295.         FlushVol ( NULL , theDirs . dataRefNum ) ;
  296.     }
  297.     return 0 ;
  298. }
  299.  
  300.  
  301. int
  302. macread ( int fd , void * ptr , unsigned len )
  303. {
  304.     long amt = len;
  305.     
  306.     if ( IsHandleFile ( fd ) ) {
  307.  
  308.         return ReadHandleFile ( fd , ptr , amt ) ;
  309.     } else {
  310.  
  311.         short err = FSRead ( fd , & amt , ptr ) ;
  312.         if ( err == eofErr && len ) {
  313.  
  314.             return amt ;
  315.         }
  316.         if  ( itworked ( err ) ) {
  317.  
  318.             return ( amt ) ;
  319.  
  320.         } else {
  321.  
  322.             return -1 ;
  323.         }
  324.     }
  325. }
  326.  
  327.  
  328. int
  329. macwrite ( int fd , void * ptr , unsigned len )
  330. {
  331.     long amt = len ;
  332.  
  333.     if ( IsHandleFile ( fd ) ) return -1 ;
  334.     
  335.     if ( itworked( FSWrite ( fd , & amt , ptr ) ) ) return(amt) ;
  336.         else return(-1) ;
  337. }
  338.  
  339.  
  340. long
  341. macseek ( int fd , long where , short whence )
  342. {
  343.     short posMode ;
  344.     long curPos ;
  345.  
  346.     if ( IsHandleFile ( fd ) ) {
  347.         return SetHandleFilePos ( fd , whence , where ) ;
  348.     }
  349.  
  350.     switch ( whence ) {
  351.     default :
  352.         posMode = fsFromStart ;
  353.         break ;
  354.     case SEEK_CUR :
  355.         posMode = fsFromMark ;
  356.         break ;
  357.     case SEEK_END :
  358.         posMode = fsFromLEOF ;
  359.         break ;
  360.     }
  361.  
  362.     if ( itworked( SetFPos ( fd , posMode, where ) )  &&
  363.          itworked( GetFPos ( fd , &curPos )) )
  364.             return(curPos);
  365.        
  366.     return(-1);
  367. }
  368.  
  369.  
  370. static OSErr
  371. copy_file(short src_vol, long src_dir, short dst_vol, long dst_dir,
  372.           Str255 fName,
  373.           pascal OSErr (*opener)(short vRefNum, long dirID,
  374.                                  ConstStr255Param fileName,
  375.                                  char permission, short *refNum)) {
  376.     short src_ref, dst_ref;
  377.     OSErr err = (*opener)(src_vol, src_dir, fName, fsRdPerm, &src_ref);
  378.     if (err == noErr) {
  379.         err = (*opener)(dst_vol, dst_dir, fName, fsWrPerm, &dst_ref);
  380.         if (err == noErr) {
  381.  
  382.             long file_len;
  383.             err = GetEOF(src_ref, &file_len);
  384.             if (err == noErr) {
  385.                 Handle buf;
  386.                 long count = MaxBlock();
  387.                 if (count > file_len)
  388.                     count = file_len;
  389.  
  390.                 buf = NewHandle(count);
  391.                 err = MemError();
  392.                 if (err == noErr) {
  393.  
  394.                     while (count > 0) {
  395.                         OSErr rd_err = FSRead(src_ref, &count, *buf);
  396.                         err = FSWrite(dst_ref, &count, *buf);
  397.                         if (err == noErr)
  398.                             err = rd_err;
  399.                         file_len -= count;
  400.                     }
  401.                     if (file_len == 0)
  402.                         err = noErr;
  403.  
  404.                     DisposHandle(buf);
  405.  
  406.                 }
  407.             }
  408.             FSClose(dst_ref);
  409.         }
  410.         FSClose(src_ref);
  411.     }
  412.  
  413.     return err;
  414. }
  415.  
  416. static void
  417. force_hdelete(short vol, long dir, Str255 fName) {
  418.     HRstFLock(vol, dir, fName);
  419.     HDelete  (vol, dir, fName);
  420. }
  421.  
  422. void
  423. finder_file_request(void) {
  424.     short finder_msg, file_count;
  425.     CountAppFiles(&finder_msg, &file_count);
  426.     if (finder_msg == appOpen && file_count == 1) {
  427.         OSErr    err;
  428.         AppFile src;
  429.         short    src_vol;
  430.         long    src_dir, nul = 0;
  431.         GetAppFiles(1, &src);
  432.         err = GetWDInfo(src.vRefNum, &src_vol, &src_dir, &nul);
  433.         if (err == noErr && src.fType == SAVE_TYPE) {
  434.  
  435.             if ( src_vol != theDirs.dataRefNum ||
  436.                  src_dir != theDirs.dataDirID &&
  437.                  CatMove(src_vol, src_dir, src.fName,
  438.                          theDirs.dataDirID, "\p:") != noErr) {
  439.  
  440.                 HCreate(theDirs.dataRefNum, theDirs.dataDirID, src.fName,
  441.                         MAC_CREATOR, SAVE_TYPE);
  442.                 err = copy_file(src_vol, src_dir, theDirs.dataRefNum,
  443.                                 theDirs.dataDirID, src.fName, &HOpen); /* HOpenDF is only there under 7.0 */
  444.                 if (err == noErr)
  445.                     err = copy_file(src_vol, src_dir, theDirs.dataRefNum,
  446.                                     theDirs.dataDirID, src.fName, &HOpenRF);
  447.                 if (err == noErr)
  448.                     force_hdelete(src_vol, src_dir, src.fName);
  449.                 else
  450.                     HDelete(theDirs.dataRefNum, theDirs.dataDirID, src.fName);
  451.             }
  452.  
  453.             if (err == noErr) {
  454.                 short ref = HOpenResFile(theDirs.dataRefNum, theDirs.dataDirID,
  455.                                          src.fName, fsRdPerm);
  456.                 if (ref != -1) {
  457.                     Handle name = Get1Resource('STR ', PLAYER_NAME_RES_ID);
  458.                     if (name) {
  459.  
  460.                         Str255 save_f_p;
  461.                         P2C(*(StringHandle)name, plname);
  462.                         set_savefile_name();
  463.                         C2P(SAVEF, save_f_p);
  464.                         force_hdelete(theDirs.dataRefNum, theDirs.dataDirID,
  465.                                       save_f_p);
  466.                         if (HRename(theDirs.dataRefNum, theDirs.dataDirID,
  467.                                     src.fName, save_f_p) == noErr)
  468.                             ClrAppFiles(1);
  469.  
  470.                     }
  471.                     CloseResFile(ref);
  472.                 }
  473.             }
  474.         }
  475.     }
  476. }
  477.