home *** CD-ROM | disk | FTP | other *** search
/ ftp.mactech.com 2010 / ftp.mactech.com.tar / ftp.mactech.com / online / source / c / compilers / Tickle-4.0.sit.hqx / Tickle-4.0 / src / floppycopy.c < prev    next >
Text File  |  1993-11-18  |  30KB  |  1,074 lines

  1.  
  2. /*
  3. ** This source code was written by Tim Endres
  4. ** Email: time@ice.com.
  5. ** USMail: 8840 Main Street, Whitmore Lake, MI  48189
  6. **
  7. ** Some portions of this application utilize sources
  8. ** that are copyrighted by ICE Engineering, Inc., and
  9. ** ICE Engineering retains all rights to those sources.
  10. **
  11. ** Neither ICE Engineering, Inc., nor Tim Endres, 
  12. ** warrants this source code for any reason, and neither
  13. ** party assumes any responsbility for the use of these
  14. ** sources, libraries, or applications. The user of these
  15. ** sources and binaries assumes all responsbilities for
  16. ** any resulting consequences.
  17. */
  18.  
  19. #ifdef MPW3
  20. #    pragma segment FloppyCopy
  21. #endif
  22.  
  23. #include "tickle.h"
  24. #include "tge.h"
  25. #include <DiskInit.h>
  26. #include <OSEvents.h>
  27.  
  28. extern int    errno;
  29.  
  30. #define MAX_DIR_STK                32
  31. #define POP_DIR()                ( dir_stk[--dir_stk_ptr] )
  32. #define POP_INFO()                ( dir_info_stk[--dir_info_stk_ptr] )
  33. #define CURRENT_DIR()            ( (dir_stk_ptr > 0) ? dir_stk[dir_stk_ptr - 1] : 2 )
  34.  
  35. #define PUSH_DIR(DIR)            ( dir_stk[dir_stk_ptr++] = (DIR) )
  36. #define PUSH_DIR_INFO(INFO)        ( dir_info_stk[dir_info_stk_ptr++] = (INFO) )
  37.  
  38. int            curr_drive_number = 1;
  39. int            to_vref;
  40. long        to_dirid;
  41. int            vref_to_unmount = 0;
  42. int            file_count_count = 0;
  43.  
  44. long        *dir_stk;
  45. int            dir_stk_ptr = 0;
  46. CInfoPBRec    *dir_info_stk;
  47. int            dir_info_stk_ptr = 0;
  48.  
  49. int            total_count = 0;
  50. int            current_count = 0;
  51. int            vol_count = 1;
  52. char        vol_prefix[32];
  53. char        vol_genname[32];
  54.  
  55.  
  56. copy_to_floppies()
  57. {
  58. short            from_vref, floppy_vref;
  59. long            from_dirid;
  60. char            from_path[256];
  61. int                result;
  62. ParamBlockRec    vpb;
  63. CInfoPBRec        cpb;
  64. extern void        SProgressCopyFiles();
  65. extern void        SProgressCounting();
  66.  
  67.     dir_stk = (long *) NewPtr(MAX_DIR_STK * sizeof(long));
  68.     dir_info_stk = (CInfoPBRec *) NewPtr(MAX_DIR_STK * sizeof(CInfoPBRec));
  69.     if (dir_stk == (long *)0 || dir_info_stk == (CInfoPBRec *)0) {
  70.         if (dir_stk != (long *)0)
  71.             DisposPtr((Ptr) dir_stk);
  72.         if (dir_info_stk != (CInfoPBRec *)0)
  73.             DisposPtr((Ptr) dir_info_stk);
  74.         message_alert("Not enough memory to save the directory information.");
  75.         return;
  76.         }
  77.     
  78.     dir_stk_ptr = 0;
  79.     dir_info_stk_ptr = 0;
  80.     vol_count = 1;
  81.  
  82.     yield_menus(YIELD_ON);
  83.     
  84.     if (! GetFolderPathName("Direcory To Copy...", from_path, &from_vref, &from_dirid))
  85.         {
  86.         yield_menus(YIELD_OFF);
  87.         DisposPtr((Ptr) dir_stk);
  88.         DisposPtr((Ptr) dir_info_stk);
  89.         return;
  90.         }
  91.     
  92.     /* Feedback("We're copying WDRef %d Path '%s'\n", from_vref, from_path); */
  93.     
  94.     cpb.hFileInfo.ioCompletion = 0;                /* Synchronous */
  95.     cpb.hFileInfo.ioNamePtr = vol_prefix; vol_prefix[0] = 0;
  96.     cpb.hFileInfo.ioVRefNum = from_vref;        /* Returned here */
  97.     cpb.hFileInfo.ioFDirIndex = -1;                /* Get the directory in ioDirID */
  98.     cpb.hFileInfo.ioDirID = from_dirid;            /* same offset as ioFlNum */
  99.     result = PBGetCatInfo(&cpb, (Boolean)0);    /* Synchronous */
  100.     if (result == noErr)
  101.         p2cstr(vol_prefix);
  102.     else
  103.         strcpy(vol_prefix, "Untitled");
  104.     
  105.     if (! GetInputLine("Volume Names Prefix: (Max 20 chars)", vol_prefix))
  106.         {
  107.         yield_menus(YIELD_OFF);
  108.         DisposPtr((Ptr) dir_stk);
  109.         DisposPtr((Ptr) dir_info_stk);
  110.         return;
  111.         }
  112.         
  113.     file_count_count = 0;
  114.     StartProgressWindow("\pCount Files", 0, -1, 0, SProgressCounting);
  115.     
  116.     total_count = file_count(from_vref, from_dirid);
  117.     
  118.     StopProgressWindow();
  119.  
  120.     if (total_count == CANCEL) {
  121.         Feedback("Copy canceled by user.");
  122.         yield_menus(YIELD_OFF);
  123.         DisposPtr((Ptr) dir_stk);
  124.         DisposPtr((Ptr) dir_info_stk);
  125.         return;
  126.         }
  127.     if (total_count == FAILURE) {
  128.         Feedback("Error counting the files to be copied.");
  129.         yield_menus(YIELD_OFF);
  130.         DisposPtr((Ptr) dir_stk);
  131.         DisposPtr((Ptr) dir_info_stk);
  132.         return;
  133.         }
  134.     
  135.     current_count = 0;
  136.     Feedback("Total files and folders to copy = %d.", total_count);
  137.     
  138.     /* Feedback("VOL Prfix <%s> ", vol_prefix); */
  139.         
  140.     StartProgressWindow("\pCopy Files", 0, total_count, 0, SProgressCopyFiles);
  141.  
  142.     vpb.volumeParam.ioCompletion = (ProcPtr)0;
  143.     vpb.volumeParam.ioNamePtr = NULL;
  144.     vpb.volumeParam.ioVRefNum = 1;        /* drive number... */
  145.     PBUnmountVol(&vpb);
  146.     
  147.     vpb.volumeParam.ioCompletion = (ProcPtr)0;
  148.     vpb.volumeParam.ioNamePtr = NULL;
  149.     vpb.volumeParam.ioVRefNum = 2;        /* drive number... */
  150.     PBUnmountVol(&vpb);
  151.     
  152.     SFEject(1);
  153.     SFEject(2);
  154.  
  155.     if (! GetFloppy(&floppy_vref))
  156.         {
  157.         StopProgressWindow();
  158.         yield_menus(YIELD_OFF);
  159.         DisposPtr((Ptr) dir_stk);
  160.         DisposPtr((Ptr) dir_info_stk);
  161.         return;
  162.         }
  163.     
  164.     to_vref = floppy_vref;
  165.     vref_to_unmount = to_vref;
  166.     
  167.     to_dirid = 2;
  168.     result = do_floppy_copy(from_path, ":", from_vref, from_dirid);
  169.     
  170.     StopProgressWindow();
  171.  
  172.     SysBeep(0);
  173.     
  174.     if (result == SUCCESS)
  175.         Feedback("Copy of '%s:' completed.", from_path);
  176.     else if (result == CANCEL)
  177.         Feedback("Copy of '%s:' canceled by user.", from_path);
  178.     else
  179.         message_alert("Copy of '%s' failed.", from_path);
  180.     
  181.     if (in_back_ground)
  182.         {
  183.         notify_SICN(NOTIFY_COPY_COMPLETE);
  184.         }
  185.     yield_menus(YIELD_OFF);
  186.     
  187.     DisposPtr((Ptr) dir_stk);
  188.     DisposPtr((Ptr) dir_info_stk);
  189.     InitCursor();
  190.     }
  191.  
  192. GetFloppy(floppy_vref)
  193. short    *floppy_vref;
  194. {
  195. int                myerr, result = 0;
  196. char            volname[32];
  197. char            prompt[128];
  198. ParamBlockRec    pb;
  199. ParamBlockRec    vpb;
  200. HParamBlockRec    hpb;
  201. DialogPtr        mydialog;
  202.  
  203.     notify_SICN(NOTIFY_NEED_DISK);
  204.     
  205. get_another:
  206.  
  207.     if (vref_to_unmount != 0) {
  208.         vpb.volumeParam.ioCompletion = (ProcPtr)0;
  209.         vpb.volumeParam.ioNamePtr = NULL;
  210.         vpb.volumeParam.ioVRefNum = vref_to_unmount;
  211.         PBUnmountVol(&vpb);
  212.         vref_to_unmount = 0;
  213.         }
  214.     
  215.     SFEject(curr_drive_number);
  216.     
  217.     DoYield();
  218.     DoYield();
  219.     
  220.     sprintf(prompt, "Insert a floppy for '%.20s #%d'.", vol_prefix, vol_count);
  221.     if (! SFGetFloppy(prompt)) {
  222.         clear_notify_q(NOTIFY_NEED_DISK);
  223.         return 0;
  224.         }
  225.     
  226.     DoYield();
  227.     DoYield();
  228.  
  229.     pb.volumeParam.ioCompletion = (ProcPtr)0;
  230.     pb.volumeParam.ioNamePtr = NULL;
  231.     pb.volumeParam.ioVRefNum = curr_drive_number;    /* Drive number influence! */
  232.     myerr = PBMountVol(&pb);
  233.     /* Feedback("PBMountVol(#1)=%d", myerr); */
  234.     if (myerr != noErr)
  235.         {
  236.         if (! AskYesNo("Floppy unreadable. Initialize?", 0))
  237.             goto get_another;
  238.         
  239.         mydialog = GetNewDialog(4010, NULL, (WindowPtr)-1);
  240.         if (mydialog != NULL) {
  241.             SetPort(mydialog);
  242.             DrawDialog(mydialog);
  243.             }
  244.         
  245.         myerr = DIFormat(curr_drive_number);
  246.         
  247.         if (myerr == noErr) {
  248.         
  249.             if (mydialog != NULL)
  250.                 DisposDialog(mydialog);
  251.             mydialog = GetNewDialog(4009, NULL, (WindowPtr)-1);
  252.             if (mydialog != NULL) {
  253.                 SetPort(mydialog);
  254.                 DrawDialog(mydialog);
  255.                 }
  256.             
  257.             myerr = DIVerify(curr_drive_number);
  258.             
  259.             if (myerr == noErr) {
  260.             
  261.                 if (mydialog != NULL)
  262.                     DisposDialog(mydialog);
  263.                 mydialog = GetNewDialog(4008, NULL, (WindowPtr)-1);
  264.                 if (mydialog != NULL) {
  265.                     SetPort(mydialog);
  266.                     DrawDialog(mydialog);
  267.                     }
  268.                 
  269.                 sprintf(vol_genname, "%.20s #%d", vol_prefix, vol_count);
  270.                 c2pstr(vol_genname);
  271.                 myerr = DIZero(curr_drive_number, vol_genname);
  272.                 
  273.                 if (myerr != noErr)
  274.                     message_alert("Error #%d creating floppy directory.", myerr);
  275.                 }
  276.             else
  277.                 message_alert("Error #%d verifying floppy format.", myerr);
  278.             }
  279.         else
  280.             message_alert("Error #%d formatting floppy.", myerr);
  281.  
  282.         if (mydialog != NULL)
  283.             DisposDialog(mydialog);
  284.  
  285.         if (myerr != noErr)
  286.             goto get_another;
  287.         }
  288.     else {
  289.         vref_to_unmount = pb.volumeParam.ioVRefNum;
  290.         }
  291.     
  292.     if (myerr == noErr) {
  293.         hpb.volumeParam.ioCompletion = 0;
  294.         hpb.volumeParam.ioNamePtr = volname;
  295.         hpb.volumeParam.ioVRefNum = pb.volumeParam.ioVRefNum;
  296.         hpb.volumeParam.ioVolIndex = 0;
  297.         myerr = PBHGetVInfo(&hpb, FALSE);
  298.         if (myerr != noErr) {
  299.             message_alert("Error #%d obtaining volume info (floppy).", myerr);
  300.             goto get_another;
  301.             }
  302.         else if ((hpb.volumeParam.ioVAtrb & 0x8080) != 0) {
  303.             message_alert("This floppy is locked.");
  304.             vref_to_unmount = hpb.volumeParam.ioVRefNum;
  305.             
  306.             goto get_another;
  307.             }
  308.         else {
  309.             *floppy_vref = hpb.volumeParam.ioVRefNum;
  310.             vref_to_unmount = hpb.volumeParam.ioVRefNum;
  311.             
  312.             if (hpb.volumeParam.ioVFilCnt > 1 || hpb.volumeParam.ioVDirCnt > 1) {
  313.                 if (! AskYesNo("Floppy has data. Overwrite data?", 0))
  314.                     goto get_another;
  315.                 
  316.                 pb.volumeParam.ioCompletion = (ProcPtr)0;
  317.                 pb.volumeParam.ioNamePtr = NULL;
  318.                 pb.volumeParam.ioVRefNum = hpb.volumeParam.ioVRefNum;
  319.                 myerr = PBUnmountVol(&pb);
  320.                 /* Feedback("UNMOUNT returns %d ", myerr); */
  321.                 if (myerr != noErr)
  322.                     message_note("Error #%d UNmounting floppy volume.", myerr);
  323.                 else
  324.                     vref_to_unmount = 0;
  325.  
  326.                 DoYield();
  327.                 DoYield();
  328.  
  329.                 mydialog = GetNewDialog(4008, NULL, (WindowPtr)-1);
  330.                 if (mydialog != NULL) {
  331.                     SetPort(mydialog);
  332.                     DrawDialog(mydialog);
  333.                     }
  334.                 
  335.                 sprintf(vol_genname, "%.20s #%d", vol_prefix, vol_count);
  336.                 c2pstr(vol_genname);
  337.             
  338.                 myerr = DIZero(curr_drive_number, vol_genname);
  339.                 /* Feedback("DIZERO returns %d ", myerr); */
  340.                 
  341.                 if (mydialog != NULL)
  342.                     DisposDialog(mydialog);
  343.                 
  344.                 if (myerr != noErr) {
  345.                     message_alert("Floppy erase failed. Error #%d.", myerr);
  346.                     goto get_another;
  347.                     }
  348.  
  349.                 DoYield();
  350.                 DoYield();
  351.                 }
  352.             
  353.             if (myerr != noErr && myerr != volOnLinErr) {
  354.                 message_alert("Error #%d mounting floppy volume.", myerr);
  355.                 goto get_another;
  356.                 }
  357.             else {
  358.                 result = 1;
  359.                 vol_count++;
  360.                 }
  361.             }
  362.         }
  363.     else {
  364.         message_alert("Error #%d mounting floppy volume.", myerr);
  365.         goto get_another;
  366.         }
  367.     
  368.     clear_notify_q(NOTIFY_NEED_DISK);
  369.     return result;
  370.     }
  371.  
  372. do_floppy_copy(from_path, partial_path, from_vref, from_dirid)
  373. char        *from_path;
  374. char        *partial_path;
  375. int            from_vref;
  376. long        from_dirid;
  377. {
  378. short            done, index, myresult, floppy_vref, myerr, stk, need_floppy;
  379. long            new_dirid, bytes_needed, blks_needed;
  380. CInfoPBRec        cpb;
  381. ParamBlockRec    pb;
  382. HParamBlockRec    hpb;
  383. HParamBlockRec    vpb;
  384. char            *ptr1, *ptr2;
  385. char            myname[48],
  386.                 thisfolder[48],
  387.                 tmpname[48],
  388.                 sub_folder_name[256];
  389.  
  390.     DoYield();
  391.     
  392.     /*Feedback("DoFloppyCopy: from '%s' part '%s' fvref %d fdir %ld tvref %d tdir %ld ",
  393.     **        from_path, partial_path, from_vref, from_dirid, to_vref, to_dirid);
  394.     */
  395.     
  396.     cpb.hFileInfo.ioCompletion = 0;                /* Synchronous */
  397.     cpb.hFileInfo.ioNamePtr = thisfolder; thisfolder[0] = 0;
  398.     cpb.hFileInfo.ioVRefNum = from_vref;        /* Returned here */
  399.     cpb.hFileInfo.ioFDirIndex = -1;                /* Get the directory in ioDirID */
  400.     cpb.hFileInfo.ioDirID = from_dirid;            /* same offset as ioFlNum */
  401.     myresult = PBGetCatInfo(&cpb, (Boolean)0);    /* Synchronous */
  402.     
  403.     /* Feedback("DoFloppyCopy: result %d FolderName <%.*s> ",
  404.     **            myresult, thisfolder[0], &thisfolder[1]);
  405.     */
  406.     
  407.     hpb.fileParam.ioCompletion = 0;
  408.     hpb.fileParam.ioNamePtr = thisfolder;
  409.     hpb.fileParam.ioVRefNum = to_vref;
  410.     hpb.fileParam.ioDirID = to_dirid;    
  411.     myresult = PBDirCreate(&hpb, (Boolean)0);
  412.     if (myresult != noErr && myresult != dupFNErr) {
  413.         p2cstr(thisfolder);
  414.         message_alert("Error #%d creating '%s' directory.", myresult, thisfolder);
  415.         return FAILURE;
  416.         }
  417.     else {
  418.         new_dirid = hpb.fileParam.ioDirID;
  419.         PUSH_DIR(new_dirid);
  420.         
  421.         cpb.hFileInfo.ioCompletion = 0;                /* Synchronous */
  422.         cpb.hFileInfo.ioNamePtr = myname; myname[0] = 0;
  423.         cpb.hFileInfo.ioFDirIndex = -1;                /* Get the directory in ioDirID */
  424.         cpb.hFileInfo.ioVRefNum = from_vref;        /* Returned here */
  425.         cpb.hFileInfo.ioDirID = from_dirid;            /* same offset as ioFlNum */
  426.         myresult = PBGetCatInfo(&cpb, (Boolean)0);    /* Synchronous */
  427.         /* Feedback("FLDR: PBGETCatInfo(%d)=%d", from_dirid, myresult); */
  428.         if (myresult == noErr) {
  429.             PUSH_DIR_INFO(cpb);
  430.  
  431.             cpb.hFileInfo.ioFDirIndex = -1;                    /* Set the directory in ioDirID */
  432.             cpb.hFileInfo.ioNamePtr = NULL;
  433.             cpb.hFileInfo.ioVRefNum = to_vref;
  434.             cpb.hFileInfo.ioDirID = new_dirid;                /* same offset as ioFlNum */
  435.             myresult = PBSetCatInfo(&cpb, (Boolean)0);        /* Synchronous */
  436.             /* Feedback("FLDR: PBSETCatInfo(%d)=%d", hpb.fileParam.ioDirID, myresult); */
  437.             }
  438.         }
  439.     
  440.     need_floppy = 0;
  441.     cancel_current_op = 0;
  442.     for (index=1, done=false ; ! done && ! cancel_current_op ; index++) {
  443.     
  444.         if (CheckCmdPeriod())
  445.             return CANCEL;
  446.         
  447.         DoYield();
  448.         
  449.         /*
  450.         **
  451.         **     GET INFO
  452.         ** 
  453.         */
  454.         vpb.volumeParam.ioCompletion = 0;
  455.         vpb.volumeParam.ioNamePtr = NULL;
  456.         vpb.volumeParam.ioVRefNum = to_vref;
  457.         vpb.volumeParam.ioVolIndex = 0;
  458.         myresult = PBHGetVInfo(&vpb, (Boolean)0);
  459.         if (myresult != noErr) {
  460.             Feedback("DoFloppyCopy: PBHGetVInfo()=%d ", myresult);
  461.             message_alert("DoFloppyCopy: PBHGetVInfo()=%d ", myresult);
  462.             return FAILURE;
  463.             }
  464.         
  465.         /*
  466.         **
  467.         **     COMPUTE NEEDED SIZE
  468.         ** 
  469.         */
  470.         
  471.         cpb.hFileInfo.ioCompletion = 0;                    /* Synchronous */
  472.         cpb.hFileInfo.ioNamePtr = myname; myname[0] = 0;
  473.         cpb.hFileInfo.ioVRefNum = from_vref;            /* Returned here */
  474.         cpb.hFileInfo.ioFDirIndex = index;                /* Get the ith file/directory */
  475.         cpb.hFileInfo.ioDirID = from_dirid;                /* same offset as ioFlNum */
  476.         myresult = PBGetCatInfo(&cpb, (Boolean)false);    /* Synchronous */
  477.         if (cpb.hFileInfo.ioResult == fnfErr)
  478.             {
  479.             return SUCCESS;
  480.             }
  481.         if (cpb.hFileInfo.ioResult != noErr)
  482.             {
  483.             /* This is an ERROR. */
  484.             p2cstr(myname);
  485.             Feedback("Error #%d PBGetCatInfo(%d)", cpb.hFileInfo.ioResult, index);
  486.             return FAILURE;
  487.             }
  488.         else if ((cpb.hFileInfo.ioFlAttrib & ioDirMask) > 0)
  489.             {
  490.             /* This is a DIRECTORY. */
  491.             blks_needed = 1;
  492.             bytes_needed = vpb.volumeParam.ioVAlBlkSiz;
  493.             }
  494.         else
  495.             {
  496.             /* This is a FILE. */
  497.             hpb.fileParam.ioCompletion = 0;
  498.             hpb.fileParam.ioFDirIndex = 0;
  499.             hpb.fileParam.ioNamePtr = myname;
  500.             hpb.fileParam.ioVRefNum = from_vref;
  501.             hpb.fileParam.ioDirID = from_dirid;
  502.             hpb.fileParam.ioFVersNum = 0;
  503.             myerr = PBHGetFInfo(&hpb, (Boolean)0);
  504.             if (myerr != noErr) {
  505.                 Feedback("PBHGetFInfo(%.*s)=%d ", myname[0], &myname[1], myerr);
  506.                 return FAILURE;
  507.                 }
  508.             else {
  509.                 bytes_needed = hpb.fileParam.ioFlLgLen + hpb.fileParam.ioFlRLgLen;
  510.                 blks_needed = (hpb.fileParam.ioFlLgLen + (vpb.volumeParam.ioVAlBlkSiz - 1))
  511.                                 / vpb.volumeParam.ioVAlBlkSiz;
  512.                 blks_needed += (hpb.fileParam.ioFlRLgLen + (vpb.volumeParam.ioVAlBlkSiz - 1))
  513.                                 / vpb.volumeParam.ioVAlBlkSiz;
  514.                 blks_needed += 2;    /* This sometimes catches small catalog/extent increases... */
  515.                 } /* Got file info... */
  516.                 
  517.             } /* got a file... */
  518.         
  519.         DoYield();
  520.         
  521.         /* Feedback("NEED: Bytes %ld Blks %ld FREE %ld Sz %ld ",
  522.         **            bytes_needed, blks_needed,
  523.         **            vpb.volumeParam.ioVFrBlk, vpb.volumeParam.ioVAlBlkSiz);
  524.         */
  525.         /*
  526.         **
  527.         **     CHECK NEEDED SPACE
  528.         ** 
  529.         */
  530.  
  531.         if (need_floppy || blks_needed > vpb.volumeParam.ioVFrBlk) {
  532.             /* Need new floppy!!!! */
  533.             /* Feedback("NEED: NOT ENOUGH Get floppy. "); */
  534.             pb.volumeParam.ioCompletion = (ProcPtr)0;
  535.             pb.volumeParam.ioNamePtr = NULL;
  536.             pb.volumeParam.ioVRefNum = to_vref;
  537.             myerr = PBUnmountVol(&pb);
  538.             /* Feedback("NEED: UnMount = %d. ", myerr); */
  539.             if (! GetFloppy(&floppy_vref))
  540.                 {
  541.                 return CANCEL;
  542.                 }
  543.                 
  544.             to_vref = floppy_vref;
  545.             new_dirid = 2;
  546.             need_floppy = 0;
  547.             vref_to_unmount = to_vref;
  548.             /* Feedback("NEED: CREATING PATH <%s>. ", partial_path); */
  549.             
  550.             for (stk=0, ptr1 = partial_path ; *ptr1 != '\0' ; ) {
  551.                 if (*ptr1 == ':')
  552.                     ptr1++;
  553.                 for (ptr2 = tmpname; *ptr1 != '\0' && *ptr1 != ':' ;  )
  554.                     *ptr2++ = *ptr1++;
  555.                 if (*ptr1 == ':')
  556.                     ptr1++;
  557.                 *ptr2 = '\0';
  558.                 if (tmpname[0] != '\0') {
  559.                     c2pstr(tmpname);
  560.                     hpb.fileParam.ioCompletion = 0;
  561.                     hpb.fileParam.ioNamePtr = tmpname;
  562.                     hpb.fileParam.ioVRefNum = to_vref;
  563.                     hpb.fileParam.ioDirID = new_dirid;    
  564.                     myresult = PBDirCreate(&hpb, (Boolean)0);
  565.                     if (myresult != noErr) {
  566.                         p2cstr(tmpname);
  567.                         Feedback("Error #%d Floppy CreateDir(%s)", myresult, tmpname);
  568.                         message_note("Error #%d Floppy CreateDir(%s)", myresult, tmpname);
  569.                         return FAILURE;
  570.                         }
  571.                     else {
  572.                         new_dirid = hpb.fileParam.ioDirID;
  573.                         /* Feedback("NEED: CREATED FOLDER <%.*s> ID %ld. ",
  574.                         **            tmpname[0], &tmpname[1], new_dirid);
  575.                         */
  576.                         if (stk < dir_info_stk_ptr) {
  577.                             dir_info_stk[stk].hFileInfo.ioFDirIndex = -1;                /* Set the directory in ioDirID */
  578.                             dir_info_stk[stk].hFileInfo.ioNamePtr = NULL;
  579.                             dir_info_stk[stk].hFileInfo.ioVRefNum = to_vref;
  580.                             dir_info_stk[stk].hFileInfo.ioDirID = new_dirid;            /* same offset as ioFlNum */
  581.                             myresult = PBSetCatInfo(&dir_info_stk[stk], (Boolean)0);    /* Synchronous */
  582.                             if (myresult != noErr)
  583.                                 Feedback("NEED: Error #%d PBSetCatinfo(%.*s, %ld). ",
  584.                                             myresult, tmpname[0], &tmpname[1], new_dirid);
  585.                             }
  586.                         
  587.                         dir_stk[stk++] = new_dirid;
  588.                         }
  589.                     
  590.                     } /* tmpname has characters, create dir... */
  591.                 
  592.                 } /* for walk of partial path to create directories */
  593.                 
  594.             hpb.fileParam.ioCompletion = 0;
  595.             hpb.fileParam.ioNamePtr = thisfolder;
  596.             hpb.fileParam.ioVRefNum = to_vref;
  597.             hpb.fileParam.ioDirID = new_dirid;    
  598.             myresult = PBDirCreate(&hpb, (Boolean)0);
  599.             if (myresult != noErr) {
  600.                 p2cstr(thisfolder);
  601.                 Feedback("Error #%d Floppy CreateDir(%s)", myresult, thisfolder);
  602.                 message_note("Error #%d Floppy CreateDir(%s)", myresult, thisfolder);
  603.                 return FAILURE;
  604.                 }
  605.             else {
  606.                 new_dirid = hpb.fileParam.ioDirID;
  607.                 /* Feedback("NEED: CREATED FOLDER <%.*s> ID %ld. ",
  608.                 **            thisfolder[0], &thisfolder[1], new_dirid);
  609.                 */
  610.                 if (stk < dir_info_stk_ptr) {
  611.                     dir_info_stk[stk].hFileInfo.ioFDirIndex = -1;                /* Set the directory in ioDirID */
  612.                     dir_info_stk[stk].hFileInfo.ioNamePtr = NULL;
  613.                     dir_info_stk[stk].hFileInfo.ioVRefNum = to_vref;
  614.                     dir_info_stk[stk].hFileInfo.ioDirID = new_dirid;            /* same offset as ioFlNum */
  615.                     myresult = PBSetCatInfo(&dir_info_stk[stk], (Boolean)0);    /* Synchronous */
  616.                     if (myresult != noErr)
  617.                         Feedback("NEED: Error #%d PBSetCatinfo(%.*s, %ld). ",
  618.                                     myresult, thisfolder[0], &thisfolder[1], new_dirid);
  619.                     }
  620.                 
  621.                 dir_stk[stk++] = new_dirid;
  622.                 }
  623.             
  624.             /* Feedback("NEED: CREATED PATH <%s> todir %ld. ", partial_path, new_dirid);
  625.             ** Feedback("NEED: stk = %d dir_stk_ptr = %d dir_info_stk_ptr = %d ",
  626.             **            stk, dir_stk_ptr, dir_info_stk_ptr);
  627.             */
  628.             } /* Not enough blocks for file... */
  629.         
  630.         
  631.         /*
  632.         **
  633.         **     PROCESS OBJECT
  634.         ** 
  635.         */
  636.  
  637.         if ((cpb.hFileInfo.ioFlAttrib & ioDirMask) > 0)
  638.             {
  639.             /* This is a DIRECTORY. */
  640.             /* Feedback("DIR: PARTIAL <%s> THIS <%.*s>. ",
  641.             **            partial_path, thisfolder[0], &thisfolder[1]);
  642.             */
  643.             sprintf(sub_folder_name, "%s%s%.*s", partial_path,
  644.                     ( (partial_path[strlen(partial_path)-1] == ':') ? "" : ":" ),
  645.                     thisfolder[0], &thisfolder[1]);
  646.             
  647.             UpdateProgress(++current_count);
  648.  
  649.             to_dirid = new_dirid;
  650.             myresult = do_floppy_copy(from_path, sub_folder_name,
  651.                                         from_vref, cpb.hFileInfo.ioDirID);
  652.             to_dirid = CURRENT_DIR();
  653.             
  654.             switch (myresult) {
  655.                 /*case FAILURE:*/
  656.                 case CANCEL:
  657.                     return myresult;
  658.                     break;
  659.                 }
  660.             
  661.             /* Feedback("DIR: RETURNED THIS <%.*s>. ", thisfolder[0], &thisfolder[1]); */
  662.             }
  663.         else
  664.             {
  665.             /* This is a FILE. */
  666.             /* Feedback("COPY FILE '%.*s' fv %d fd %ld tv %d td %ld ",
  667.             **            myname[0], &myname[1], from_vref, from_dirid,
  668.             **            to_vref, hpb.fileParam.ioDirID);
  669.             */
  670.             
  671.             Feedback("Copying '%.*s'...", myname[0], &myname[1]);
  672.             
  673.             myresult = CopyFile(myname, from_vref, from_dirid, to_vref, new_dirid);
  674.             
  675.             UpdateProgress(++current_count);
  676.  
  677.             if (myresult != noErr) {
  678.                 if (myresult == dirFulErr || myresult == dskFulErr) {
  679.                     need_floppy = 1;
  680.                     index--;                /* Do this one again... */
  681.                     }
  682.                 else {
  683.                     message_alert("Error #%d copying file '%.*s'.",
  684.                                     myresult, myname[0], &myname[1]);
  685.                     return FAILURE;
  686.                     }
  687.                 }
  688.             
  689.             } /* got a file... */
  690.  
  691.         /*
  692.         **
  693.         **     END OF MAJOR LOOP
  694.         ** 
  695.         */
  696.         
  697.         } /* for file in directory... */
  698.     
  699.     return SUCCESS;
  700.     }
  701.  
  702. #define my_disk_item    69
  703.  
  704. file_count(from_vref, from_dirid)
  705. int            from_vref;
  706. long        from_dirid;
  707. {
  708. short            done, index, myresult;
  709. int                count = 0;
  710. CInfoPBRec        cpb;
  711. char            myname[48];
  712. char            thisfolder[48];
  713. extern void        SProgressCounting();
  714.  
  715.     DoYield();
  716.     
  717.     /*Feedback("DoFloppyCopy: from '%s' part '%s' fvref %d fdir %ld tvref %d tdir %ld ",
  718.     **        from_path, partial_path, from_vref, from_dirid, to_vref, to_dirid);
  719.     */
  720.     
  721.     cpb.hFileInfo.ioCompletion = 0;                /* Synchronous */
  722.     cpb.hFileInfo.ioNamePtr = thisfolder; thisfolder[0] = 0;
  723.     cpb.hFileInfo.ioVRefNum = from_vref;        /* Returned here */
  724.     cpb.hFileInfo.ioFDirIndex = -1;                /* Get the directory in ioDirID */
  725.     cpb.hFileInfo.ioDirID = from_dirid;            /* same offset as ioFlNum */
  726.     myresult = PBGetCatInfo(&cpb, (Boolean)0);    /* Synchronous */
  727.     
  728.     for (index=1, done=false ; ! done && ! cancel_current_op ; index++) {
  729.     
  730.         if (CheckCmdPeriod()) {
  731.             return CANCEL;
  732.             }
  733.         
  734.         DoYield();
  735.         
  736.         cpb.hFileInfo.ioCompletion = 0;                    /* Synchronous */
  737.         cpb.hFileInfo.ioNamePtr = myname; myname[0] = 0;
  738.         cpb.hFileInfo.ioVRefNum = from_vref;            /* Returned here */
  739.         cpb.hFileInfo.ioFDirIndex = index;                /* Get the ith file/directory */
  740.         cpb.hFileInfo.ioDirID = from_dirid;                /* same offset as ioFlNum */
  741.         myresult = PBGetCatInfo(&cpb, (Boolean)false);    /* Synchronous */
  742.         if (cpb.hFileInfo.ioResult != noErr)
  743.             {
  744.             /* This is an ERROR. */
  745.             if (cpb.hFileInfo.ioResult != fnfErr) {
  746.                 Feedback("Error #%d PBGetCatInfo(%d)", cpb.hFileInfo.ioResult, index);
  747.                 return FAILURE;
  748.                 }
  749.             else
  750.                 done = 1;
  751.             }
  752.         else if ((cpb.hFileInfo.ioFlAttrib & ioDirMask) > 0)
  753.             {
  754.             /* This is a DIRECTORY. */
  755.             UpdateProgress(++file_count_count);
  756.             count += file_count(from_vref, cpb.hFileInfo.ioDirID) + 1;
  757.             }
  758.         else
  759.             {
  760.             /* This is a FILE. */
  761.             if ((++file_count_count & 8) != 0)
  762.                 UpdateProgress(file_count_count);
  763.             count++;
  764.             } /* got a file... */
  765.  
  766.         } /* for file in directory... */
  767.     
  768.     return count;
  769.     }
  770.  
  771. #define my_disk_item    69
  772.  
  773. pascal Boolean DiskFilter(mydialog, myevent, itemhit)
  774. DialogPtr        mydialog;
  775. EventRecord        *myevent;
  776. short            *itemhit;
  777. {
  778. #pragma unused (mydialog)
  779. int            myascii;
  780. EventRecord    local_event;
  781.  
  782.     if (myevent->what == keyDown) {
  783.         myascii = myevent->message & 255;
  784.         if (myascii == '\015' || myascii == '\003') {
  785.             *itemhit = ((DialogRecord *) mydialog)->aDefItem;
  786.             return true;
  787.             }
  788.         else if (myascii == 0x1B) {
  789.             *itemhit = ((DialogRecord *) mydialog)->aDefItem;
  790.             return true;
  791.             }
  792.         }
  793.     else if (GetOSEvent(diskMask, &local_event)) {
  794.         if (local_event.what == diskEvt) {
  795.             curr_drive_number = local_event.message & 0x00007FFF;
  796.             *itemhit = my_disk_item;
  797.             return true;
  798.             }
  799.         else
  800.             return false;
  801.         }
  802.     else
  803.         return false;
  804.     }
  805.  
  806. #define d_get_floppy_id            4004
  807. #define d_floppy_prompt_item    2
  808.  
  809. SFGetFloppy(prompt)
  810. char        *prompt;
  811. {
  812. GrafPtr        saveport;
  813. DialogPtr    mydialog;
  814. short        itemhit, done;
  815. int            status;
  816. pascal Boolean        DiskFilter();
  817.  
  818.     GetPort(&saveport);
  819.     mydialog = GetNewDialog(d_get_floppy_id, NULL, (WindowPtr)-1);
  820.     
  821.     MySetText(mydialog, d_floppy_prompt_item, prompt);
  822.     
  823.     for (done=false; ! done; ) {
  824.         SetPort(mydialog);
  825.         FrameButton(mydialog, 1);
  826.         ModalDialog(DiskFilter, &itemhit);
  827.         if (itemhit == my_disk_item) {
  828.             done = true; status = 1;
  829.             }
  830.         else if (itemhit == ok) {        /* *Really* Cancel. */
  831.             done = true; status = 0;
  832.             }
  833.         }
  834.     
  835.     DisposDialog(mydialog);
  836.  
  837.     SetPort(saveport);
  838.     return status;
  839.     }
  840.  
  841. SFEject(drive)
  842. int        drive;
  843. {
  844. IOParam    pb;
  845.  
  846.     pb.ioCompletion = (ProcPtr)0;        /* */
  847.     pb.ioNamePtr = NULL;                /* */
  848.     pb.ioVRefNum = drive;                /* ioVRefNum ≈ ioDrvNum. 1 = internal drive */
  849.  
  850.     PBEject((ParmBlkPtr)&pb);
  851.     if (pb.ioResult != noErr && pb.ioResult != nsDrvErr) {
  852.         Feedback("Error #%d trying to eject floppy in drive #%d.\n",
  853.                     pb.ioResult, drive);
  854.         /* message_alert("Error #%d trying to eject floppy in drive #%d.\n",
  855.                             pb.ioResult, drive); */
  856.         }
  857.     }
  858.  
  859.  
  860. CopyFile(name, from_vref, from_dirid, to_vref, to_dirid)
  861. char        *name;            /* Pascal */
  862. int            from_vref;
  863. long        from_dirid;
  864. int            to_vref;
  865. long        to_dirid;
  866. {
  867. short            ferr, terr, myerr;
  868. int                result = noErr;
  869. HParamBlockRec    fparm, tparm;
  870.  
  871.     SetVol(NULL, from_vref);
  872.     fparm.ioParam.ioCompletion = 0;
  873.     fparm.ioParam.ioNamePtr = name;
  874.     fparm.ioParam.ioVRefNum = from_vref;
  875.     fparm.ioParam.ioVersNum = 0;
  876.     fparm.ioParam.ioPermssn = fsRdPerm;
  877.     fparm.ioParam.ioMisc = NULL;
  878.     fparm.fileParam.ioDirID = from_dirid;
  879.     ferr = PBHOpen(&fparm, false);
  880.     if (ferr != noErr) {
  881.         Feedback("Error #%d opening FROM DATA '%.*s'", ferr, name[0], &name[1]);
  882.         message_alert("Error #%d opening FROM DATA '%.*s'", ferr, name[0], &name[1]);
  883.         result = ferr;
  884.         }
  885.     else if (! cancel_current_op) {
  886.         SetVol(NULL, to_vref);
  887.         tparm.ioParam.ioCompletion = 0;
  888.         tparm.ioParam.ioNamePtr = name;
  889.         tparm.ioParam.ioVRefNum = to_vref;
  890.         tparm.ioParam.ioVersNum = 0;
  891.         tparm.ioParam.ioPermssn = fsWrPerm;
  892.         tparm.ioParam.ioMisc = NULL;
  893.         tparm.fileParam.ioDirID = to_dirid;
  894.         terr = PBHCreate(&tparm, false);
  895.         if (terr != noErr && terr != dupFNErr) {
  896.             Feedback("Error #%d creating TO DATA '%.*s'", terr, name[0], &name[1]);
  897.             message_alert("Error #%d creating TO DATA '%.*s'", terr, name[0], &name[1]);
  898.             result = terr;
  899.             }
  900.         else {
  901.             terr = PBHOpen(&tparm, false);
  902.             if (terr != noErr) {
  903.                 Feedback("Error #%d opening TO DATA '%.*s'", terr, name[0], &name[1]);
  904.                 message_alert("Error #%d opening TO DATA '%.*s'", terr, name[0], &name[1]);
  905.                 result = terr;
  906.                 }
  907.             else {
  908.                 if ((myerr=Copy(&fparm, &tparm)) != noErr) {
  909.                     Feedback("Error #%d COPYING DATA '%.*s'", myerr, name[0], &name[1]);
  910.                     message_alert("Error #%d COPYING DATA '%.*s'", myerr, name[0], &name[1]);
  911.                     }
  912.                 else {
  913.                     myerr = PBGetEOF((ParmBlkPtr)&fparm, false);
  914.                     if (myerr == noErr) {
  915.                         tparm.ioParam.ioMisc = fparm.ioParam.ioMisc;
  916.                         myerr = PBSetEOF((ParmBlkPtr)&tparm, false);
  917.                         if (myerr != noErr) {
  918.                             Feedback("Error #%d setting EOF DATA '%.*s'", myerr, name[0], &name[1]);
  919.                             message_alert("Error #%d setting EOF DATA '%.*s'", myerr, name[0], &name[1]);
  920.                             result = myerr;
  921.                             }
  922.                         }
  923.                     else {
  924.                         Feedback("Error #%d getting EOF DATA '%.*s'", myerr, name[0], &name[1]);
  925.                         message_alert("Error #%d getting EOF DATA '%.*s'", myerr, name[0], &name[1]);
  926.                         result = myerr;
  927.                         }
  928.                     }
  929.                 
  930.                 PBClose((ParmBlkPtr)&tparm, false);
  931.                 }
  932.             
  933.             PBClose((ParmBlkPtr)&fparm, false);
  934.             
  935.             if (result == noErr && ! cancel_current_op) {
  936.                 SetVol(NULL, from_vref);
  937.                 fparm.ioParam.ioCompletion = 0;
  938.                 fparm.ioParam.ioNamePtr = name;
  939.                 fparm.ioParam.ioVRefNum = from_vref;
  940.                 fparm.ioParam.ioVersNum = 0;
  941.                 fparm.ioParam.ioPermssn = fsRdPerm;
  942.                 fparm.ioParam.ioMisc = NULL;
  943.                 fparm.fileParam.ioDirID = from_dirid;
  944.                 ferr = PBHOpenRF(&fparm, false);
  945.                 if (ferr != noErr) {
  946.                     Feedback("Error #%d opening FROM RSRC '%.*s'", ferr, name[0], &name[1]);
  947.                     message_alert("Error #%d opening FROM RSRC '%.*s'", ferr, name[0], &name[1]);
  948.                     result = ferr;
  949.                     }
  950.                 else {
  951.                     SetVol(NULL, to_vref);
  952.                     tparm.ioParam.ioCompletion = 0;
  953.                     tparm.ioParam.ioNamePtr = name;
  954.                     tparm.ioParam.ioVRefNum = to_vref;
  955.                     tparm.ioParam.ioVersNum = 0;
  956.                     tparm.ioParam.ioPermssn = fsWrPerm;
  957.                     tparm.ioParam.ioMisc = NULL;
  958.                     tparm.fileParam.ioDirID = to_dirid;
  959.                     terr = PBHOpenRF(&tparm, false);
  960.                     if (terr != noErr) {
  961.                         Feedback("Error #%d opening TO RSRC '%.*s'", terr, name[0], &name[1]);
  962.                         message_alert("Error #%d opening TO RSRC '%.*s'", terr, name[0], &name[1]);
  963.                         result = terr;
  964.                         }
  965.                     else if (! cancel_current_op) {
  966.                         if ((myerr=Copy(&fparm, &tparm)) != noErr) {
  967.                             Feedback("Error #%d COPYING RSRC '%.*s'", myerr, name[0], &name[1]);
  968.                             message_alert("Error #%d COPYING RSRC '%.*s'", myerr, name[0], &name[1]);
  969.                             result = myerr;
  970.                             }
  971.                         else {
  972.                             myerr = PBGetEOF((ParmBlkPtr)&fparm, false);
  973.                             if (myerr == noErr) {
  974.                                 tparm.ioParam.ioMisc = fparm.ioParam.ioMisc;
  975.                                 myerr = PBSetEOF((ParmBlkPtr)&tparm, false);
  976.                                 if (myerr != noErr) {
  977.                                     Feedback("Error #%d setting EOF RSRC '%.*s'", myerr, name[0], &name[1]);
  978.                                     message_alert("Error #%d setting EOF RSRC '%.*s'", myerr, name[0], &name[1]);
  979.                                     result = myerr;
  980.                                     }
  981.                                 }
  982.                             else {
  983.                                 Feedback("Error #%d getting EOF RSRC '%.*s'", myerr, name[0], &name[1]);
  984.                                 message_alert("Error #%d getting EOF RSRC '%.*s'", myerr, name[0], &name[1]);
  985.                                 result = myerr;
  986.                                 }
  987.                             }
  988.                         
  989.                         PBClose((ParmBlkPtr)&tparm, false);
  990.                         }
  991.                     
  992.                     PBClose((ParmBlkPtr)&fparm, false);
  993.                     }
  994.                 } /* if (result == noErr) */
  995.             
  996.             if (result == noErr && ! cancel_current_op) {
  997.                 SetVol(NULL, from_vref);
  998.                 fparm.ioParam.ioCompletion = 0;
  999.                 fparm.fileParam.ioFDirIndex = 0;
  1000.                 fparm.ioParam.ioNamePtr = name;
  1001.                 fparm.ioParam.ioVRefNum = from_vref;
  1002.                 fparm.fileParam.ioDirID = from_dirid;
  1003.                 fparm.ioParam.ioVersNum = 0;
  1004.                 myerr = PBHGetFInfo(&fparm, false);
  1005.                 if (myerr != noErr) {
  1006.                     Feedback("Error #%d Getting File info '%.*s'",
  1007.                                 myerr, name[0], &name[1]);
  1008.                     }
  1009.                 else {
  1010.                     fparm.ioParam.ioVRefNum = to_vref;
  1011.                     fparm.fileParam.ioDirID = to_dirid;
  1012.                     SetVol(NULL, to_vref);
  1013.                     myerr = PBHSetFInfo(&fparm, false);
  1014.                     if (myerr != noErr)
  1015.                         Feedback("Error #%d Setting File info '%.*s'",
  1016.                                     myerr, name[0], &name[1]);
  1017.                     }
  1018.                 } /* if (result == noErr) */
  1019.             
  1020.             } /* else PBHCreate(to) succeeded... */
  1021.         
  1022.         } /* else PBHOpen(from) succeeded... */
  1023.     
  1024.     FlushVol(NULL, to_vref);
  1025.  
  1026.     return result;
  1027.     }
  1028.  
  1029. #define    INPARAM        inparm->ioParam
  1030. #define    OUTPARAM    outparm->ioParam
  1031.  
  1032. Copy(inparm, outparm)
  1033. HParamBlockRec    *inparm;
  1034. HParamBlockRec    *outparm;
  1035. {
  1036. short    done, myerr;
  1037. char    mybuffer[512];
  1038.  
  1039.     for (done=false; ! done && ! cancel_current_op ; ) {
  1040.         
  1041.         DoYield();
  1042.         
  1043.         INPARAM.ioReqCount = (long)512;
  1044.         INPARAM.ioBuffer = mybuffer;
  1045.         INPARAM.ioPosMode = fsAtMark;
  1046.         myerr = PBRead((ParmBlkPtr)inparm, (Boolean)false);
  1047.         if (myerr != noErr && myerr != eofErr)
  1048.             return myerr;
  1049.         
  1050.         if (myerr == eofErr)
  1051.             done = true;
  1052.         
  1053.         DoYield();
  1054.         
  1055.         OUTPARAM.ioReqCount = INPARAM.ioActCount;
  1056.         OUTPARAM.ioBuffer = mybuffer;
  1057.         OUTPARAM.ioPosMode = fsAtMark;
  1058.         myerr = PBWrite((ParmBlkPtr)outparm, (Boolean)false);
  1059.         if (myerr != noErr)
  1060.             return myerr;
  1061.         
  1062.         if (INPARAM.ioActCount != OUTPARAM.ioActCount) {
  1063.             Feedback("Error, output does not match size of input [%d : %d].",
  1064.                             INPARAM.ioActCount, OUTPARAM.ioActCount);
  1065.             message_alert("Error, output does not match size of input [%d : %d].",
  1066.                             INPARAM.ioActCount, OUTPARAM.ioActCount);
  1067.             done = true;
  1068.             }
  1069.         }
  1070.     
  1071.     return noErr;
  1072.     }
  1073.  
  1074.