home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 2: PC / frozenfish_august_1995.bin / bbs / d07xx / d0727.lha / Format / Source / Format.c next >
C/C++ Source or Header  |  1992-09-04  |  28KB  |  1,112 lines

  1.  
  2. /**************************************************************************/
  3. /*                  Format                  */
  4. /*                   Version 1.00                  */
  5. /*                                      */
  6. /* This is a replacement for the AmigaDOS "Format" command.  It sports    */
  7. /* (for the Workbench user) more friendly user-interface, although it is  */
  8. /* virtually identical to the standard Format command where the CLI      */
  9. /* interface is concerned.                          */
  10. /*                                      */
  11. /* This program is Copyright 1992 by Dave Schreiber, All Rights Reserved. */
  12. /* This program may not be sold for more than a small copying and shipping*/
  13. /* and handling fee, except by written permission of Dave Schreiber.      */
  14. /*                                      */
  15. /* Version list:                              */
  16. /*    1.00 - First release (August 31, 1992)                              */
  17. /**************************************************************************/
  18.  
  19.  
  20. /*System header files*/
  21. #include <exec/types.h>
  22. #include <exec/exec.h>
  23. #include <intuition/intuition.h>
  24. #include <dos/dos.h>
  25. #include <dos/filehandler.h>
  26. #include <workbench/startup.h>
  27. #include <libraries/gadtools.h>
  28. #include <workbench/icon.h>
  29. #include <devices/trackdisk.h>
  30. #include <dos/rdargs.h>
  31.  
  32. /*Prototypes for system functions*/
  33. #include <proto/exec.h>
  34. #include <proto/intuition.h>
  35. #include <proto/dos.h>
  36. #include <proto/gadtools.h>
  37. #include <proto/icon.h>
  38. #include <proto/graphics.h>
  39.  
  40. /*Other headers*/
  41. #include "Format.h"
  42. #include "GUI.h"
  43.  
  44. /*These hold the user's selections*/
  45. /*They are initialized in main()*/
  46. BOOL FFS;
  47. BOOL QuickFmt;
  48. BOOL Verify;
  49. BOOL Icon;
  50.  
  51. /*This holds the pointer to the Workbench startup message, if we're started*/
  52. /*from Workbench*/
  53. extern struct WBStartup *WBenchMsg;
  54.  
  55. /*Library base pointers*/
  56. struct IntuitionBase *IntuitionBase;
  57. struct GfxBase *GfxBase;
  58. struct Library *GadToolsBase,*IconBase;
  59.  
  60. /*This is initialized in GUI.c and holds the location and size*/
  61. /*of the progress indicator box in the status window*/
  62. extern Rect box;
  63.  
  64. BPTR StdErr=NULL;
  65.  
  66. /*For use with the CLI "Version" command*/
  67. char *Version = "$VER: NewFormat V1.00 (31.8.92)";
  68.  
  69. /*The entry point for the program (_main to keep a CLI window from opening*/
  70. /*when the program is run from Workbench)*/
  71. _main()
  72. {
  73.    UWORD disk;
  74.    char volumeName[256];
  75.    prepResult stat;
  76.    char statusString[80];
  77.  
  78.    /*Open the various shared libraries that are needed*/
  79.    IntuitionBase=(struct Library *)OpenLibrary("intuition.library",37L);
  80.    GfxBase=(struct Library *)OpenLibrary("graphics.library",37L);
  81.    IconBase=(struct Library *)OpenLibrary("icon.library",37L);
  82.    GadToolsBase=(struct Library *)OpenLibrary("gadtools.library",37L);
  83.  
  84.    /*Check to see that they all opened, and exit if any did not*/
  85.    if(IntuitionBase==NULL || GfxBase==NULL || IconBase==NULL ||
  86.      GadToolsBase==NULL)
  87.       cleanup(100);
  88.  
  89.    if(WBenchMsg!=NULL)
  90.    {
  91.       /*If we're running from Workbench, and the user did not select*/
  92.       /*a drive, print an error and exit*/
  93.       if(WBenchMsg->sm_NumArgs==1)
  94.       {
  95.      printError("Please select a drive to format and try again.",NULL,NULL);
  96.      cleanup(100);
  97.       }
  98.  
  99.       /*Get the visual info, etc.*/
  100.       SetupScreen();
  101.  
  102.       /*For every selected disk...*/
  103.       for(disk=1;disk<WBenchMsg->sm_NumArgs && stat!=eQuit;disk++)
  104.       {
  105.      /*This will hold the disk's new name*/
  106.      char newName[36];
  107.  
  108.      /*Initialize the format settings*/
  109.      FFS=FALSE;
  110.      QuickFmt=FALSE;
  111.      Verify=TRUE;
  112.      Icon=TRUE;
  113.  
  114.      /*Get the volume/device name of the disk to format*/
  115.      getVolumeName(volumeName,WBenchMsg->sm_ArgList,disk);
  116.  
  117.      /*If there is no lock to the volume, that means it is */
  118.      /*unformatted, so just use the name given to us by Workbench*/
  119.      if(WBenchMsg->sm_ArgList[disk].wa_Lock==NULL)
  120.         strcpy(volumeName,WBenchMsg->sm_ArgList[disk].wa_Name);
  121.  
  122.      /*Open the options window*/
  123.      if((stat=OpenPrepWindow(volumeName))==0)
  124.      {
  125.         /*Get the user's input*/
  126.         stat=getPrepInput();
  127.  
  128.         /*And close the window*/
  129.         ClosePrepWindow();
  130.  
  131.         /*If the user selected 'OK'*/
  132.         if(stat==eOK)
  133.         {
  134.            /*Get the new name of the disk*/
  135.            strcpy(newName,((struct StringInfo *)
  136.              (PrepGadgets[GD_NameGadget]->SpecialInfo))->Buffer);
  137.  
  138.            /*Ask the user for verification*/
  139.            if(askAreYouSure(volumeName,
  140.              (WBenchMsg->sm_ArgList[disk].wa_Lock!=NULL)))
  141.            {
  142.  
  143.           /*If everything's OK, open the status window*/
  144.           if((stat=OpenStatusWindow(statusString))==0)
  145.           {
  146.              /*And format the disk*/
  147.              formatVolume(&(WBenchMsg->sm_ArgList[disk].wa_Lock),
  148.                    volumeName,newName,FFS,QuickFmt,Verify,Icon,
  149.                 statusString);
  150.  
  151.              /*We're done, so close the status window*/
  152.              CloseStatusWindow();
  153.           }
  154.            }
  155.         }
  156.      }
  157.       }
  158.       /*Free the visual info, etc.*/
  159.       CloseDownScreen();
  160.    }
  161.    else     /*We've been run from the CLI*/
  162.    {
  163.       char driveName[64];
  164.       BPTR driveLock;
  165.       struct Process *process;
  166.       APTR oldWdw;
  167.       char temp[32];
  168.       char temp2[4];
  169.       DriveLayout junk;
  170.  
  171.       /*Open a 'stderr' I/O channel to the shell*/
  172.       /*(the normal stderr was not opened since we used _main() ) */
  173.       StdErr=Open("CONSOLE:",MODE_OLDFILE);
  174.  
  175.       /*Make sure requestors don't open*/
  176.       process=(struct Process *)FindTask(0L);
  177.       oldWdw=process->pr_WindowPtr;
  178.       process->pr_WindowPtr=(APTR)(-1);
  179.  
  180.       /*Get the command-line arguments*/
  181.       parseArgs(driveName,volumeName,&FFS,&Icon,&QuickFmt,&Verify);
  182.  
  183.       /*Get a lock on the selected drive*/
  184.       /*(note:  NULL is a valid return value;  it means that the disk we*/
  185.       /*want to format is itself unformatted)*/
  186.       driveLock=Lock(driveName,ACCESS_READ);
  187.  
  188.       strcpy(temp,driveName);
  189.  
  190.       /*Get the volume/drive name*/
  191.       if(volumeToDevName(driveLock,temp,&junk))
  192.       {
  193.      /*Wait for the user to tell us to go ahead*/
  194.      Write(Output(),"Insert the disk to be formatted in drive ",41);
  195.      Write(Output(),temp,strlen(temp));
  196.      Write(Output()," and press RETURN ",18);
  197.      Read(Input(),temp2,1);
  198.  
  199.      /*Format the disk*/
  200.      formatVolume(&driveLock,temp,volumeName,FFS,QuickFmt,Verify,Icon,
  201.             statusString);
  202.       }
  203.       else
  204.      Write(Output(),"Cannot find the specified drive!\n",33);
  205.  
  206.       Close(StdErr);
  207.  
  208.       /*Restore the old contents of this pointer*/
  209.       process->pr_WindowPtr=(APTR)(-1);
  210.  
  211.       Write(Output(),"\n",1);
  212.    }
  213.    cleanup(0);
  214.    return(0);
  215. }
  216.  
  217. /*This functions handles the low-level format, the high-level format, the*/
  218. /*creation of icons, etc.*/
  219. void formatVolume(BPTR *volumeLock,char *volumeName,char *newName,BOOL ffs,
  220.           BOOL quick,BOOL verify,BOOL icon,char *statString)
  221. {
  222.    struct IOExtTD *io1;
  223.    BOOL fmtResult=TRUE;
  224.    int result;
  225.    char deviceName[64];
  226.    DriveLayout layout;
  227.    struct MsgPort *devPort;
  228.    BOOL writeProtCont=TRUE;
  229.  
  230.    /*If the volume lock is NULL, assume that the volumeName string holds*/
  231.    /*a valid device pointer*/
  232.    if(*volumeLock==NULL)
  233.       strcpy(deviceName,volumeName);
  234.  
  235.    /*Get the drive name (if possible)*/
  236.    if(!volumeToDevName(*volumeLock,deviceName,&layout))
  237.    {
  238.       printError("Can't find the drive!",NULL,NULL);
  239.       return;
  240.    }
  241.  
  242.    /*This port will be used to communicate with the filesystem*/
  243.    devPort=DeviceProc(deviceName);
  244.    if(devPort==NULL)
  245.    {
  246.       printError("Can't find the drive",NULL,NULL);
  247.       return;
  248.    }
  249.  
  250.    /*Inhibit the drive*/
  251.    DoPkt(devPort,ACTION_INHIBIT,DOSTRUE,NULL,NULL,NULL);
  252.  
  253.    /*If we got a lock to the volume that we're going to format it, destroy*/
  254.    /*it, since the volume that it points to is about to be erased anyway*/
  255.    if(*volumeLock!=NULL)
  256.    {
  257.       UnLock(*volumeLock);
  258.       *volumeLock=NULL;
  259.    }
  260.  
  261.    /*Open the disk device*/
  262.    if((io1=OpenDrive(layout.devName,layout.unit,layout.flags))!=NULL)
  263.    {
  264.       /*Determine the write protect status*/
  265.       io1->iotd_Req.io_Data=NULL;
  266.       io1->iotd_Req.io_Length=0;
  267.       io1->iotd_Req.io_Command=TD_PROTSTATUS;
  268.       DoIO((struct IOReq *)io1);
  269.  
  270.       /*Loop while the disk stays protected and user keeps pressing Retry*/
  271.       while(io1->iotd_Req.io_Actual!=0 &&
  272.          (writeProtCont=alertIsWriteProtected(volumeName)))
  273.      DoIO((struct IOReq *)io1);
  274.  
  275.       /*If the disk is not write-protected*/
  276.       if(writeProtCont)
  277.       {
  278.      /*Do a full format if the user didn't select the 'Quick' option*/
  279.      if(!quick)
  280.         fmtResult=doFullFormat(&layout,statString,volumeName,io1);
  281.  
  282.      /*If the format was successful*/
  283.      if(fmtResult)
  284.      {
  285.         /*Write an extra carriage return, if run from the CLI*/
  286.         if(WBenchMsg==NULL)
  287.            Write(Output(),"\n",1);
  288.  
  289.         /*Tell the user that we're doing the high-level format*/
  290.         fmtResult=!updateStatWindow("Formatting disk...",1000);
  291.  
  292.         /*If the user hasn't clicked on 'Stop', do the high-level format*/
  293.         if(fmtResult)
  294.            result=Format(deviceName,newName,
  295.                        ffs ? ID_FFS_DISK : ID_DOS_DISK);
  296.      }
  297.       }
  298.       else
  299.      printError("Cannot format volume",volumeName,
  300.             "because the disk is write protected");
  301.       /*Close the disk device*/
  302.       CloseDrive(io1);
  303.    }
  304.    else
  305.    {
  306.       printError("Couldn't access the device",NULL,NULL);
  307.       return;
  308.    }
  309.  
  310.    /*Uninhibit the drive*/
  311.    DoPkt(devPort,ACTION_INHIBIT,DOSFALSE,NULL,NULL,NULL);
  312.  
  313.    /*Wait for the drive to come on line*/
  314.    Delay(50);
  315.  
  316.    /*If the disk was never unprotected, return*/
  317.    if(!writeProtCont)
  318.       return;
  319.  
  320.    /*If the format was successful and the user wants icons created*/
  321.    if(icon && result==DOSTRUE)
  322.    {
  323.       struct DiskObject *trashIcon;
  324.       BPTR trashLock;
  325.  
  326.       /*Update the user*/
  327.       fmtResult=!updateStatWindow("Creating Trashcan  ",1000);
  328.  
  329.       /*If she didn't press 'Stop'*/
  330.       if(fmtResult)
  331.       {
  332.      /*Create the trashcan name (<volume>:Trashcan)*/
  333.      strcpy(deviceName,newName);
  334.      strcat(deviceName,":");
  335.      strcat(deviceName,"Trashcan");
  336.  
  337.      /*Create the trashcan directory*/
  338.      trashLock=CreateDir(deviceName);
  339.  
  340.      /*If it was successfully created*/
  341.      if(trashLock!=NULL)
  342.      {
  343.         UnLock(trashLock);
  344.         /*Get the trashcan icon*/
  345.         trashIcon=GetDefDiskObject(WBGARBAGE);
  346.  
  347.         /*If there wasn't an error*/
  348.         if(trashIcon!=NULL)
  349.         {
  350.            /*Write the icon to disk*/
  351.            if(!PutDiskObject(deviceName,trashIcon))
  352.           printError("There was an error while creating the trashcan",
  353.                  NULL,NULL);
  354.  
  355.            /*and free it*/
  356.            FreeDiskObject(trashIcon);
  357.         }
  358.         else
  359.            printError("There was an error while creating the trashcan",
  360.                   NULL,NULL);
  361.      }
  362.      else
  363.         printError("There was an error while creating the trashcan directory",
  364.                NULL,NULL);
  365.       }
  366.    }
  367.    return;
  368. }
  369.  
  370. /*This function does a full (low-level) format of a disk*/
  371. BOOL doFullFormat(DriveLayout *layout,char *statString,char *devName,
  372.              struct IOExtTD *io1)
  373. {
  374.    ULONG *write;
  375.    ULONG trackSize,sectorPos,numTracks;
  376.    LONG track;
  377.    int c;
  378.    UBYTE error=2;
  379.    BOOL errorB=FALSE;
  380.  
  381.    /*Get the size of a track (#surfaces*#blocks*#longwordsPerTrack*4*/
  382.    trackSize=layout->surfaces*layout->blockSize*4*layout->BPT;
  383.  
  384.    /*Allocate enough memory for one track*/
  385.    write=AllocMem(trackSize,layout->memType|MEMF_CLEAR);
  386.    if(write!=NULL)
  387.    {
  388.       /*Initialize the IORequest*/
  389.       io1->iotd_Req.io_Data=write;
  390.       io1->iotd_Req.io_Length=trackSize;
  391.  
  392.       /*Get the starting byte position in the volume*/
  393.       sectorPos=layout->lowCyl*trackSize;
  394.  
  395.       /*Get the number of tracks to format*/
  396.       numTracks=layout->highCyl-layout->lowCyl+1;
  397.  
  398.       /*Clear the status window*/
  399.       error=(updateStatWindow(" ",0)) ? 0 : error;
  400.  
  401.       /*For each track*/
  402.       for(track=0;track<numTracks && error!=0;track++)
  403.       {
  404.      /*Setup to format the disk*/
  405.      io1->iotd_Req.io_Command=TD_FORMAT;
  406.      io1->iotd_Req.io_Offset=sectorPos;
  407.  
  408.      /*Update the status window*/
  409.      strcpy(statString,"Formatting cylinder ");
  410.      stci_d(&statString[20],track+layout->lowCyl);
  411.      strcat(statString,", ");
  412.      stci_d(&statString[strlen(statString)],numTracks-track-1);
  413.      strcat(statString," to go  ");
  414.  
  415.      error=(updateStatWindow(statString,track*1000/numTracks)) ?0:error;
  416.  
  417.      /*If the user didn't press 'Stop'*/
  418.      if(error!=0)
  419.      {
  420.         error=(DoIO((struct IOReq *)io1)) ? 0 : error;
  421.         if(error==0)
  422.            printError("A formatting error occured",NULL,NULL);
  423.      }
  424.  
  425.      /*If we're suppossed to verify, and the user didn't press 'Stop'*/
  426.      if(Verify && error!=0)
  427.      {
  428.         /*Setup the same IORequest to do a read*/
  429.         io1->iotd_Req.io_Command=CMD_READ;
  430.  
  431.         /*Update the status*/
  432.         strcpy(statString," Verifying cylinder ");
  433.         stci_d(&statString[20],track+layout->lowCyl);
  434.         strcat(statString,", ");
  435.         stci_d(&statString[strlen(statString)],numTracks-track-1);
  436.         strcat(statString," to go  ");
  437.  
  438.         error=(updateStatWindow(statString,
  439.                ( (1+(track*2))*1000)/(2*numTracks) )) ? 0 : error;
  440.  
  441.         /*If the user hasn't pressed 'Stop'*/
  442.         if(error!=0)
  443.         {
  444.            /*Do the read*/
  445.            if(DoIO((struct IOReq *)io1))
  446.            {
  447.           if(--error==0)
  448.              printError("A verify error occurred",NULL,NULL);
  449.           errorB=TRUE;
  450.            }
  451.         }
  452.  
  453.         /*Check the data that was read back.*/
  454.         for(c=0;c<trackSize>>2 && error!=0;c++)
  455.         {
  456.            /*If there was an error*/
  457.            if(write[c]!=0L)
  458.            {
  459.           /*Record the fact*/
  460.           if(!errorB)
  461.           {
  462.              errorB=TRUE;
  463.              if(--error==0)
  464.             /*Print an error message*/
  465.             printError("A verify error occurred",NULL,NULL);
  466.           }
  467.           write[c]=0L;
  468.            }
  469.         }
  470.         if(!errorB && error!=2)
  471.            error=2;
  472.      }
  473.      /*Get the byte position of the next track*/
  474.      if(errorB)
  475.      {
  476.         errorB=FALSE;
  477.         track--;
  478.      }
  479.      else
  480.         sectorPos+=trackSize;
  481.       }
  482.  
  483.       /*We're done, so free the track memory*/
  484.       FreeMem(write,trackSize);
  485.    }
  486.    else
  487.       printError("Couldn't allocate write buffer",NULL,NULL);
  488.  
  489.    return(error!=0);
  490. }
  491.  
  492. /*Used in askAreYouSure()*/
  493. struct EasyStruct areYouSure=
  494. {
  495.    sizeof(struct EasyStruct),
  496.    0,
  497.    "Format Request...",
  498.    "Are you sure you want to format volume\n%s\n(the contents of the disk will be destroyed)?",
  499.    "Yes|No"
  500. };
  501.  
  502. /*Ask the user if she really wants to format the disk*/
  503. BOOL askAreYouSure(char *volumeName,BOOL truncColon)
  504. {
  505.    char name[36];
  506.    APTR args[2];
  507.    UBYTE result;
  508.  
  509.    /*Get the device name*/
  510.    strcpy(name,volumeName);
  511.  
  512.    /*Truncate the trailing colon if so specified*/
  513.    if(truncColon)
  514.       name[strlen(name)-1]=NULL;
  515.  
  516.    /*Setup the device name as the argument to the requestor*/
  517.    args[0]=name;
  518.    args[1]=NULL;
  519.  
  520.    /*Put up the requestor*/
  521.    result=EasyRequestArgs(NULL,&areYouSure,NULL,args);
  522.  
  523.    /*Return the result*/
  524.    return(result==1);
  525. }
  526.  
  527. /*Used in askAreYouSure()*/
  528. struct EasyStruct writeProtected=
  529. {
  530.    sizeof(struct EasyStruct),
  531.    0,
  532.    "Format Request...",
  533.    "Volume\n%s\nis write protected",
  534.    "Retry|Cancel"
  535. };
  536.  
  537. /*Alert the user to the fact that the disk is write protected, and give*/
  538. /*the user a chance to unprotect the disk*/
  539. BOOL alertIsWriteProtected(char *devName)
  540. {
  541.    APTR args[2];
  542.    BYTE result;
  543.  
  544.    /*Setup the device name as the argument to the requestor*/
  545.    args[0]=devName;
  546.    args[1]=NULL;
  547.  
  548.    /*Put up the requestor*/
  549.    result=EasyRequestArgs(NULL,&writeProtected,NULL,args);
  550.  
  551.    /*Return the result*/
  552.    return(result==1);
  553. }
  554.  
  555. /*This is used to print errors*/
  556. struct EasyStruct errorReq=
  557. {
  558.    sizeof(struct EasyStruct),
  559.    0,
  560.    "Format Request...",
  561.    NULL,
  562.    "Ok"
  563. };
  564.  
  565. char *oneLine="%s";
  566. char *twoLine="%s\n%s";
  567. char *threeLine="%s\n%s\n%s";
  568.  
  569. /*Print one, two, or three lines of error messages in an EasyRequestor*/
  570. /*or to 'StdErr'*/
  571. void printError(char *first,char *second,char *third)
  572. {
  573.    APTR args[4];
  574.    args[0]=args[3]=NULL;
  575.  
  576.    /*If we're running from the CLI*/
  577.    if(WBenchMsg==NULL)
  578.    {
  579.       /*And a StdErr handle was opened successfully*/
  580.       if(StdErr!=NULL)
  581.       {
  582.      char LF=0x0A;
  583.  
  584.      /*Print the first line*/
  585.      if(first!=NULL)
  586.      {
  587.         Write(StdErr,first,strlen(first));
  588.         Write(StdErr," ",1);
  589.      }
  590.  
  591.      /*Print the second line*/
  592.      if(second!=NULL)
  593.      {
  594.         Write(StdErr,second,strlen(second));
  595.         Write(StdErr," ",1);
  596.      }
  597.  
  598.      /*Print the third line*/
  599.      if(third!=NULL)
  600.      {
  601.         Write(StdErr,third,strlen(third));
  602.         Write(StdErr," ",1);
  603.      }
  604.  
  605.      /*Print the terminating carriage return*/
  606.      Write(StdErr,&LF,1);
  607.       }
  608.    }
  609.    else  /*Otherwise, we're running from Workbench, so put up the requestor*/
  610.    {
  611.       /*Three lines*/
  612.       if(third!=NULL)
  613.       {
  614.      args[2]=third;
  615.      args[1]=second;
  616.      args[0]=first;
  617.      errorReq.es_TextFormat=threeLine;
  618.       }
  619.       else if(second!=NULL)   /*Two lines*/
  620.       {
  621.      args[1]=second;
  622.      args[0]=first;
  623.      errorReq.es_TextFormat=twoLine;
  624.       }
  625.       else if(first!=NULL)    /*One line*/
  626.       {
  627.      args[0]=first;
  628.      errorReq.es_TextFormat=oneLine;
  629.       }
  630.       /*Put up the requestor*/
  631.       EasyRequestArgs(NULL,&errorReq,NULL,args);
  632.    }
  633.  
  634.    return;
  635. }
  636.  
  637. /*Get the name of a volume, given a lock to that volume*/
  638. void getVolumeName(char *name,struct WBArg *argList,UWORD disk)
  639. {
  640.    /*Get the name*/
  641.    if(NameFromLock(argList[disk].wa_Lock,name,256)==DOSFALSE)
  642.       /*Or return <unknown> if the name couldn't be determined*/
  643.       strcpy(name,"<unknown>");
  644.  
  645.    return;
  646. }
  647.  
  648. /*Exit from the program, closing any open libraries*/
  649. void cleanup(ULONG err)
  650. {
  651.    if(IntuitionBase!=NULL)
  652.       CloseLibrary((struct Library *)IntuitionBase);
  653.  
  654.    if(GfxBase!=NULL)
  655.       CloseLibrary((struct Library *)GfxBase);
  656.  
  657.    if(GadToolsBase!=NULL)
  658.       CloseLibrary(GadToolsBase);
  659.  
  660.    if(IconBase!=NULL)
  661.       CloseLibrary(IconBase);
  662.  
  663.    exit(err);
  664. }
  665.  
  666. /*Get input from the original window*/
  667. prepResult getPrepInput(void)
  668. {
  669.    struct IntuiMessage *mesg;
  670.    ULONG class;
  671.    ULONG code;
  672.    struct Gadget *gadget;
  673.    struct TagItem tags[2];
  674.  
  675.    /*Setup tags that will be used to toggle the states of checkbox gadgets*/
  676.    tags[0].ti_Tag=GTCB_Checked;
  677.    tags[1].ti_Tag=TAG_DONE;
  678.    tags[1].ti_Data=NULL;
  679.  
  680.    /*Loop until the user presses 'OK' or 'Cancel'*/
  681.    for(;;)
  682.    {
  683.       /*Wait for input*/
  684.       Wait(1<<PrepWnd->UserPort->mp_SigBit);
  685.  
  686.       /*Get the input*/
  687.       mesg=GT_GetIMsg(PrepWnd->UserPort);
  688.  
  689.       /*Loop while there are messages to be processed*/
  690.       while(mesg!=NULL)
  691.       {
  692.      /*Get the message type, etc.*/
  693.      class=mesg->Class;
  694.      code=mesg->Code;
  695.      gadget=(struct Gadget *)mesg->IAddress;
  696.  
  697.      /*Reply to the message*/
  698.      GT_ReplyIMsg(mesg);
  699.  
  700.      /*Act on the message*/
  701.      switch(class)
  702.      {
  703.         /*User clicked on close gadget.  Treat it as a click on 'Cancel'*/
  704.         case CLOSEWINDOW:
  705.            return(eQuit);
  706.  
  707.         /*User pressed a gadget*/
  708.         case GADGETUP:
  709.            switch(gadget->GadgetID)
  710.            {
  711.           /*Checkbox gadgets*/
  712.           /*(each toggles the appropriate status flag)*/
  713.           case GD_FFSGadget:
  714.              FFS=!FFS;
  715.              break;
  716.           case GD_IconGadget:
  717.              Icon=!Icon;
  718.              break;
  719.           case GD_QuickFmtGadget:
  720.              QuickFmt=!QuickFmt;
  721.              break;
  722.           case GD_VerifyGadget:
  723.              Verify=!Verify;
  724.              break;
  725.  
  726.           /*OK*/
  727.           case GD_OKGadget:
  728.              return(eOK);
  729.  
  730.           /*Cancel*/
  731.           case GD_CancelGadget:
  732.              return(eCancel);
  733.            }
  734.            break;
  735.  
  736.         /*Keypress (gadget equivalents)*/
  737.         case VANILLAKEY:
  738.            switch(code)
  739.            {
  740.           /*Disk name*/
  741.           case 'n':
  742.           case 'N':
  743.              ActivateGadget(PrepGadgets[GD_NameGadget],
  744.                      PrepWnd,NULL);
  745.              break;
  746.  
  747.           /*FFS*/
  748.           case 'f':
  749.           case 'F':
  750.              tags[0].ti_Data=(FFS=!FFS);
  751.  
  752.              /*Toggle the checkmark state of the gadget*/
  753.              GT_SetGadgetAttrsA(PrepGadgets[GD_FFSGadget],
  754.                     PrepWnd,NULL, tags);
  755.              break;
  756.  
  757.           /*Verify*/
  758.           case 'v':
  759.           case 'V':
  760.              tags[0].ti_Data=(Verify=!Verify);
  761.  
  762.              GT_SetGadgetAttrsA(PrepGadgets[GD_VerifyGadget],
  763.                     PrepWnd,NULL, tags);
  764.              break;
  765.  
  766.           /*Quick Format*/
  767.           case 'q':
  768.           case 'Q':
  769.              tags[0].ti_Data=(QuickFmt=!QuickFmt);
  770.  
  771.              GT_SetGadgetAttrsA(PrepGadgets[GD_QuickFmtGadget],
  772.                     PrepWnd,NULL, tags);
  773.              break;
  774.  
  775.           /*Create icons*/
  776.           case 'r':
  777.           case 'R':
  778.              tags[0].ti_Data=(Icon=!Icon);
  779.  
  780.              GT_SetGadgetAttrsA(PrepGadgets[GD_IconGadget],
  781.                     PrepWnd,NULL, tags);
  782.              break;
  783.  
  784.           /*Cancel*/
  785.           case 'c':
  786.           case 'C':
  787.              return(eCancel);
  788.  
  789.           /*OK*/
  790.           case 'o':
  791.           case 'O':
  792.              return(eOK);
  793.            }
  794.         break;
  795.      }
  796.      /*Get the next message*/
  797.      mesg=GT_GetIMsg(PrepWnd->UserPort);
  798.       }
  799.    }
  800.    return(FALSE);
  801. }
  802.  
  803. /*Convert a volume name to a device name, and get information*/
  804. /*on the layout of the disk*/
  805. BOOL volumeToDevName(BPTR volumeLock,char *dev,DriveLayout *layout)
  806. {
  807.    BOOL stat;
  808.    struct DosList *dosList;
  809.    struct DeviceNode *devNode;
  810.    char name[36];
  811.    char *temp;
  812.    int c;
  813.    BPTR tempLock=NULL;
  814.    struct DosEnvec *driveEnv;
  815.    struct Process *process;
  816.    APTR oldWdw;
  817.  
  818.    /*Disable requestors during the execution of this function*/
  819.    process=(struct Process *)FindTask(0L);
  820.    oldWdw=process->pr_WindowPtr;
  821.    process->pr_WindowPtr=(APTR)(-1);
  822.  
  823.    /*Get the DOS device list*/
  824.    dosList=LockDosList(LDF_DEVICES|LDF_READ);
  825.  
  826.    /*Go through each entry*/
  827.    while(dosList = NextDosEntry(dosList,LDF_DEVICES|LDF_READ))
  828.    {
  829.       devNode=(struct DeviceNode *)dosList;
  830.  
  831.       /*If the node in the list is a volume*/
  832.       if(devNode->dn_Startup > 1000 &&
  833.       (devNode->dn_Task || devNode->dn_Handler || devNode->dn_SegList))
  834.       {
  835.      /*Get the name of the device*/
  836.      temp=(char *)BADDR(devNode->dn_Name);
  837.  
  838.      for(c=0;c<temp[0];c++)
  839.         name[c]=temp[c+1];
  840.  
  841.      name[c]=':';
  842.      name[c+1]=0;
  843.  
  844.      /*Get the information on the device*/
  845. /*       driveEnv=(struct DosEnvec *)
  846.         BADDR(((struct FileSysStartupMsg *)
  847.           BADDR(devNode->dn_Startup))->fssm_Environ);*/
  848.  
  849.      /*If the volume lock is NULL, the 'dev' is assumed to be the*/
  850.      /*name of a device holding an unformatted disk, so compare the*/
  851.      /*name to the name of the current node*/
  852.      if(volumeLock==NULL)
  853.         stat=(stricmp(dev,name)==0);
  854.      else
  855.      {
  856.         /*Otherwise, since 'dev' could hold a volume rather than*/
  857.         /*device name, get a lock on it and compare it to the lock*/
  858.         /*on the device that was given;  if they're the same, we've*/
  859.         /*found the drive*/
  860.  
  861.         tempLock=Lock(name,ACCESS_READ);
  862.         stat=(SameLock(tempLock,volumeLock)==LOCK_SAME);
  863.      }
  864.  
  865.      /*If we've found the drive, get the information on it*/
  866.      if(stat)
  867.      {
  868.         struct FileSysStartupMsg *startup;
  869.         char *devName;
  870.  
  871.         /*Get a pointer to the structure that holds the needed info*/
  872.         startup=(struct FileSysStartupMsg *)BADDR(devNode->dn_Startup);
  873.         driveEnv=(struct DosEnvec *)BADDR(startup->fssm_Environ);
  874.  
  875.         /*Get the information*/
  876.         layout->unit=startup->fssm_Unit;
  877.  
  878.         devName=(char *)BADDR(startup->fssm_Device);
  879.  
  880.         /*Copy the device name to layout->devName*/
  881.         for(c=0;c<devName[0];c++)
  882.            layout->devName[c]=devName[c+1];
  883.         layout->devName[c+1]=0;
  884.  
  885.         layout->flags=startup->fssm_Flags;
  886.  
  887.         layout->memType=driveEnv->de_BufMemType;
  888.  
  889.         layout->lowCyl=driveEnv->de_LowCyl;
  890.         layout->highCyl=driveEnv->de_HighCyl;
  891.         layout->surfaces=driveEnv->de_Surfaces;
  892.         layout->BPT=driveEnv->de_BlocksPerTrack;
  893.         layout->blockSize=driveEnv->de_SizeBlock;
  894.  
  895.         /*Copy the device name back to 'dev'*/
  896.         strcpy(dev,name);
  897.  
  898.         /*UnLock the drive lock, if it exists*/
  899.         if(tempLock!=NULL)
  900.            UnLock(tempLock);
  901.  
  902.         /*Unlock the DOS list*/
  903.         UnLockDosList(LDF_DEVICES|LDF_READ);
  904.  
  905.         /*Restore the requester pointer*/
  906.         process->pr_WindowPtr=oldWdw;
  907.  
  908.         /*And return TRUE*/
  909.         return(TRUE);
  910.      }
  911.  
  912.      /*We didn't find the drive, so unlock the lock and try again*/
  913.      if(tempLock!=NULL)
  914.         UnLock(tempLock);
  915.       }
  916.    }
  917.  
  918.    /*We didn't find the drive in the list, so unlock the list*/
  919.    UnLockDosList(LDF_DEVICES|LDF_READ);
  920.  
  921.    /*Restore the requester pointer*/
  922.    process->pr_WindowPtr=oldWdw;
  923.  
  924.    /*And return*/
  925.    return(FALSE);
  926. }
  927.  
  928. /*Create a communications port linking this process to the drive*/
  929. struct IOExtTD *OpenDrive(char *driveDevName,ULONG unit,ULONG flags)
  930. {
  931.    struct MsgPort *diskPort;
  932.    struct IOExtTD *diskRequest;
  933.  
  934.    /*Create the message port*/
  935.    if((diskPort = CreateMsgPort())!=NULL)
  936.    {
  937.       /*Create the IORequest*/
  938.       diskRequest=
  939.     (struct IOExtTD *)CreateIORequest(diskPort,sizeof(struct IOExtTD));
  940.       if(diskRequest!=NULL)
  941.       {
  942.      /*Open the device, and return the IORequest if the device*/
  943.      /*opened successfully*/
  944.      if(!OpenDevice(driveDevName,unit,(struct IORequest *)diskRequest,flags))
  945.         return(diskRequest);
  946.  
  947.      /*The device didn't open, so clean up*/
  948.      DeleteIORequest(diskRequest);
  949.       }
  950.  
  951.       DeleteMsgPort(diskPort);
  952.    }
  953.  
  954.    /*Return NULL to indicate that an error occurred*/
  955.    return(NULL);
  956. }
  957.  
  958. /*Close an open device and delete the accompanying port, etc.*/
  959. void CloseDrive(struct IOExtTD *diskRequest)
  960. {
  961.    CloseDevice((struct IORequest *)diskRequest);
  962.    DeleteMsgPort(diskRequest->iotd_Req.io_Message.mn_ReplyPort);
  963.    DeleteIORequest(diskRequest);
  964. }
  965.  
  966. /*Convert a CSTR to a BSTR*/
  967. BSTR makeBSTR(char *in,char *out)
  968. {
  969.    int c;
  970.  
  971.    out[0]=strlen(in);
  972.    for(c=0;c<out[0];c++)
  973.       out[c+1]=in[c];
  974.  
  975.    return(MKBADDR(out));
  976. }
  977.  
  978. LONG args[6]=
  979. {
  980.    NULL,NULL,0,0,0,0
  981. };
  982.  
  983. /*Get the command-line arguments given by the user, by using ReadArgs()*/
  984. void parseArgs(char *drive,char *newName,BOOL *ffs,BOOL *icons,BOOL *quick,
  985.            BOOL *verify)
  986. {
  987.    APTR r;
  988.  
  989.    /*Get the arguments*/
  990.    r=ReadArgs("DRIVE/K/A,NAME/K/A,FFS/S,NOICONS/S,QUICK/S,NOVERIFY/S",args,
  991.            NULL);
  992.  
  993.    /*If the user didn't specify a drive name, print an error*/
  994.    if(args[0]==NULL)
  995.    {
  996.       printError("You need to specify a drive to format",NULL,NULL);
  997.       if(r!=NULL)
  998.      FreeArgs(r);
  999.       cleanup(200);
  1000.    }
  1001.    else
  1002.       strcpy(drive,(char *)args[0]);
  1003.  
  1004.    /*Likewise for a name for the newly formatted volume*/
  1005.    if(args[1]==NULL)
  1006.    {
  1007.       printError("You need to specify a name for the volume",NULL,NULL);
  1008.       cleanup(200);
  1009.    }
  1010.    else
  1011.       strcpy(newName,(char *)args[1]);
  1012.  
  1013.    /*Get the four togglable settings*/
  1014.    *ffs=(args[2]!=0);
  1015.    *icons=(args[3]==0);
  1016.    *quick=(args[4]!=0);
  1017.    *verify=(args[5]==0);
  1018.  
  1019.    /*We're done, so free the ReadArgs result*/
  1020.    FreeArgs(r);
  1021.  
  1022.    /*And return*/
  1023.    return;
  1024. }
  1025.  
  1026. /*Update the status window (from Workbench), or CLI output (from the CLI)*/
  1027. /*If running from the CLI, this also checks to see if the user has pressed*/
  1028. /*control-C*/
  1029. BOOL updateStatWindow(char *string,UWORD percent)
  1030. {
  1031.    UWORD width;
  1032.    ULONG class;
  1033.    UWORD code;
  1034.    struct TagItem tags[3];
  1035.    static char Message[80];
  1036.  
  1037.    struct IntuiMessage *mesg;
  1038.  
  1039.    /*If this is NULL, we're running from the CLI*/
  1040.    if(WBenchMsg==NULL)
  1041.    {
  1042.       /*Write the string to the CLI, followed by a carriage return (but*/
  1043.       /*not a line feed)*/
  1044.       char CR=0x0d;
  1045.       Write(Output(),string,strlen(string));
  1046.       Write(Output(),&CR,1);
  1047.  
  1048.       /*Check to see if the user pressed Control-C*/
  1049.       if( (SetSignal(0,0) & SIGBREAKF_CTRL_C) == SIGBREAKF_CTRL_C)
  1050.       {
  1051.      /*If he did, print "***Break" and return TRUE, to signal that*/
  1052.      /*the user aborted the formatting process*/
  1053.      Write(Output(),"\n***Break\n",10);
  1054.      return(TRUE);
  1055.       }
  1056.       /*Otherwise, continue*/
  1057.       return(FALSE);
  1058.    }
  1059.  
  1060.    /*This code is used to update the status window that is displayed when*/
  1061.    /*the user runs NewFormat from the Workbench*/
  1062.  
  1063.    /*This puts the message into the text-display gadget*/
  1064.    /*This copy is so that the caller can change the contents of 'string'*/
  1065.    /*upon return (which can't be done without the copy, since GadTools*/
  1066.    /*won't copy the contents of 'string' to an internal buffer*/
  1067.    strcpy(Message,string);
  1068.    tags[0].ti_Tag=GTTX_Text;
  1069.    tags[0].ti_Data=(ULONG)Message;
  1070.  
  1071.    tags[1].ti_Tag=TAG_DONE;
  1072.    tags[1].ti_Data=NULL;
  1073.  
  1074.    GT_SetGadgetAttrsA(StatusGadgets[GD_StatusGadget],
  1075.        StatusWnd,NULL, tags);
  1076.  
  1077.    /*Fill the status box with the current percentage of completion*/
  1078.    SetAPen(StatusWnd->RPort,3);
  1079.    width=box.left+((box.width-3)*percent)/1000;
  1080.    RectFill(StatusWnd->RPort,box.left+2,box.top+1,width,box.top+box.height-2);
  1081.  
  1082.    /*Check user input*/
  1083.    mesg=GT_GetIMsg(StatusWnd->UserPort);
  1084.  
  1085.    /*Loop while there are messages*/
  1086.    while(mesg!=NULL)
  1087.    {
  1088.       class=mesg->Class;
  1089.       code=mesg->Code;
  1090.       GT_ReplyIMsg(mesg);
  1091.  
  1092.       switch(class)
  1093.       {
  1094.      /*Return TRUE (user abort) if the user pressed 's', 'S'*/
  1095.      case IDCMP_VANILLAKEY:
  1096.         if(code=='s' || code=='S')
  1097.            return(TRUE);
  1098.         break;
  1099.  
  1100.      /*Or if the user pressed the 'Stop' gadget*/
  1101.      case IDCMP_GADGETUP:
  1102.         return(TRUE);
  1103.       }
  1104.       /*Get the next message*/
  1105.       mesg=GT_GetIMsg(StatusWnd->UserPort);
  1106.    }
  1107.    return(FALSE);
  1108. }
  1109.  
  1110. /*End of Format.c*/
  1111.  
  1112.