home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 500-599 / ff535.lzh / Format / Format.c < prev    next >
C/C++ Source or Header  |  1991-08-26  |  48KB  |  2,166 lines

  1. /* $Revision Header * Header built automatically - do not edit! *************
  2.  *
  3.  *    (C) Copyright 1990 by Olaf Barthel & MXM
  4.  *
  5.  *    Name .....: Format.c
  6.  *    Created ..: Wednesday 29-May-91 17:06
  7.  *    Revision .: 1
  8.  *
  9.  *    Date            Author          Comment
  10.  *    =========       ========        ====================
  11.  *    06-Jun-91    Olsen        Kept the panel from being created
  12.  *                    twice.
  13.  *    29-May-91    Olsen        Created this file!
  14.  *
  15.  * $Revision Header ********************************************************/
  16.  
  17.     /* A handy keyboard shortcut. */
  18.  
  19. struct Shortcut
  20. {
  21.     UBYTE    Key;
  22.     SHORT    GadgetID,GadgetType;
  23. };
  24.  
  25.     /* A custom node, contains both the DeviceNode and the change
  26.      * count of a disk drive.
  27.      */
  28.  
  29. struct DevNode
  30. {
  31.     struct Node         VanillaNode;
  32.     struct DeviceNode    *DevNode;
  33.     ULONG             ChangeCount;
  34. };
  35.  
  36.     /* Gadget IDs. */
  37.  
  38. enum    {    GAD_DRIVES,GAD_SIZE,GAD_NAME,GAD_WHOLEDISK,GAD_VERIFY,
  39.         GAD_CREATEICONS,GAD_INSTALLDISK,GAD_AUTOSTART,
  40.         GAD_EJECTDISK,GAD_USEFFS,GAD_STATUS,GAD_START,
  41.         GAD_STOP };
  42.  
  43.     /* Size of the Format window. */
  44.  
  45. #define WIDTH    556
  46. #define HEIGHT    125
  47.  
  48.     /* Shell interface. */
  49.  
  50. enum    {    ARG_DRIVE,ARG_NAME,ARG_FFS,ARG_NOICONS,ARG_QUICK,ARG_NOVERIFY,ARG_INSTALL,ARG_EJECT };
  51.  
  52. #define NUM_ARGS    ARG_EJECT + 1
  53. #define ARG_TEMPLATE    "DRIVE/K/A,NAME/K,FFS/S,NOICONS/S,QUICK/S,NOVERIFY/S,INSTALL/S,EJECT/S"
  54.  
  55.     /* Just another macro. */
  56.  
  57. #define SetWait(Window)    SetPointer((Window),&Stopwatch[0],16,16,-6,0)
  58.  
  59.     /* A set of keyboard macros. */
  60.  
  61. struct Shortcut Shortcuts[] =
  62. {
  63.     'N',    GAD_NAME,        STRING_KIND,
  64.     'F',    GAD_WHOLEDISK,        CHECKBOX_KIND,
  65.     'V',    GAD_VERIFY,        CHECKBOX_KIND,
  66.     'C',    GAD_CREATEICONS,    CHECKBOX_KIND,
  67.     'I',    GAD_INSTALLDISK,    CHECKBOX_KIND,
  68.     'A',    GAD_AUTOSTART,        CHECKBOX_KIND,
  69.     'E',    GAD_EJECTDISK,        CHECKBOX_KIND,
  70.     'U',    GAD_USEFFS,        CHECKBOX_KIND
  71. };
  72.  
  73.     /* Global library identifiers. */
  74.  
  75. extern struct ExecBase    *SysBase;
  76. struct IntuitionBase    *IntuitionBase;
  77. struct GfxBase        *GfxBase;
  78. struct Library        *GadToolsBase;
  79. struct Library        *IconBase;
  80. struct Library        *WorkbenchBase;
  81.  
  82.     /* Part of the Workbench interface. */
  83.  
  84. struct MsgPort        *WBenchPort;
  85. struct AppWindow    *WBenchWindow;
  86.  
  87.     /* Graphics & Intuition data. */
  88.  
  89. struct Screen        *DefaultScreen;
  90. APTR             VisualInfo;
  91. struct TextFont        *Topaz;
  92. struct Gadget        *GadgetList;
  93. struct Gadget        *GadgetArray[GAD_STOP + 1];
  94. struct Window        *Window;
  95.  
  96.     /* List of filing devices. */
  97.  
  98. struct List        *DevList;
  99.  
  100.     /* Some more global data and flags. */
  101.  
  102. UBYTE            *DiskName;
  103. struct DeviceNode    *LastNode;
  104. BYTE             Formatting;
  105. BYTE             WholeDisk,Verify,CreateIcons,InstallDisk,AutoStart,EjectDisk,UseFFS;
  106. BYTE             FromShell;
  107.  
  108.     /* The default font. */
  109.  
  110. struct TextAttr DefaultFont =
  111. {
  112.     (UBYTE *)"topaz.font",
  113.     8,
  114.     FS_NORMAL,
  115.     FPF_ROMFONT
  116. };
  117.  
  118.     /* The stopwatch sprite pointer. */
  119.  
  120. UWORD __chip Stopwatch[(2 + 16) * 2] =
  121. {
  122.     0x0000,0x0000,
  123.  
  124.     0x0400,0x07C0,
  125.     0x0000,0x07C0,
  126.     0x0100,0x0380,
  127.     0x0000,0x07E0,
  128.     0x07C0,0x1FF8,
  129.     0x1FF0,0x3FEC,
  130.     0x3FF8,0x7FDE,
  131.     0x3FF8,0x7FBE,
  132.     0x7FFC,0xFF7F,
  133.     0x7EFC,0xFFFF,
  134.     0x7FFC,0xFFFF,
  135.     0x3FF8,0x7FFE,
  136.     0x3FF8,0x7FFE,
  137.     0x1FF0,0x3FFC,
  138.     0x07C0,0x1FF8,
  139.     0x0000,0x07E0,
  140.  
  141.     0x0000,0x0000
  142. };
  143.  
  144.     /* Run-dump of a standard filing system bootblock. */
  145.  
  146. ULONG Bootblock_OFS[13] =
  147. {
  148.     0x444F5300,0xC0200F19,0x00000370,0x43FA0018,
  149.     0x4EAEFFA0,0x4A80670A,0x20402068,0x00167000,
  150.     0x4E7570FF,0x60FA646F,0x732E6C69,0x62726172,
  151.     0x79000000
  152. };
  153.  
  154.     /* Run-dump of an FFS bootblock (the checksum's different). */
  155.  
  156. ULONG Bootblock_FFS[13] =
  157. {
  158.     0x444F5301,0xC0200F18,0x00000370,0x43FA0018,
  159.     0x4EAEFFA0,0x4A80670A,0x20402068,0x00167000,
  160.     0x4E7570FF,0x60FA646F,0x732E6C69,0x62726172,
  161.     0x79000000
  162. };
  163.  
  164.     /* Disable the SAS/C ^C trapping. */
  165.  
  166. int CXBRK(VOID) { return(0); }
  167.  
  168.     /* UpdateInfo():
  169.      *
  170.      *    Check the checkbox gadgets and set the formatting
  171.      *    flags accordingly.
  172.      */
  173.  
  174. VOID
  175. UpdateInfo()
  176. {
  177.     if(!FromShell)
  178.     {
  179.         if(GadgetArray[GAD_WHOLEDISK] -> Flags & GFLG_SELECTED)
  180.             WholeDisk = TRUE;
  181.         else
  182.             WholeDisk = FALSE;
  183.  
  184.         if(GadgetArray[GAD_VERIFY] -> Flags & GFLG_SELECTED)
  185.             Verify = TRUE;
  186.         else
  187.             Verify = FALSE;
  188.  
  189.         if(GadgetArray[GAD_CREATEICONS] -> Flags & GFLG_SELECTED)
  190.             CreateIcons = TRUE;
  191.         else
  192.             CreateIcons = FALSE;
  193.  
  194.         if(GadgetArray[GAD_INSTALLDISK] -> Flags & GFLG_SELECTED)
  195.             InstallDisk = TRUE;
  196.         else
  197.             InstallDisk = FALSE;
  198.  
  199.         if(GadgetArray[GAD_AUTOSTART] -> Flags & GFLG_SELECTED)
  200.             AutoStart = TRUE;
  201.         else
  202.             AutoStart = FALSE;
  203.  
  204.         if(GadgetArray[GAD_EJECTDISK] -> Flags & GFLG_SELECTED)
  205.             EjectDisk = TRUE;
  206.         else
  207.             EjectDisk = FALSE;
  208.  
  209.         if(GadgetArray[GAD_USEFFS] -> Flags & GFLG_SELECTED)
  210.             UseFFS = TRUE;
  211.         else
  212.             UseFFS = FALSE;
  213.     }
  214. }
  215.  
  216.     /* CloseDrive(struct IOExtTD *DevRequest):
  217.      *
  218.      *    Close a disk driver opened using OpenDrive.
  219.      */
  220.  
  221. VOID
  222. CloseDrive(struct IOExtTD *DevRequest)
  223. {
  224.     CloseDevice(DevRequest);
  225.  
  226.     DeleteMsgPort(DevRequest -> iotd_Req . io_Message . mn_ReplyPort);
  227.  
  228.     DeleteIORequest(DevRequest);
  229. }
  230.  
  231.     /* OpenDrive(struct DeviceNode *DevNode):
  232.      *
  233.      *    Open a filing system driver 
  234.      */
  235.  
  236. struct IOExtTD *
  237. OpenDrive(struct DeviceNode *DevNode)
  238. {
  239.     struct FileSysStartupMsg    *Startup = (struct FileSysStartupMsg *)BADDR(DevNode -> dn_Startup);
  240.     struct MsgPort            *DevPort;
  241.     struct IOExtTD            *DevRequest;
  242.  
  243.     if(DevPort = CreateMsgPort())
  244.     {
  245.         if(DevRequest = (struct IOExtTD *)CreateIORequest(DevPort,sizeof(struct IOExtTD)))
  246.         {
  247.             if(!OpenDevice(&((UBYTE *)BADDR(Startup -> fssm_Device))[1],Startup -> fssm_Unit,DevRequest,Startup -> fssm_Flags))
  248.                 return(DevRequest);
  249.  
  250.             DeleteIORequest(DevRequest);
  251.         }
  252.  
  253.         DeleteMsgPort(DevPort);
  254.     }
  255.  
  256.     return(NULL);
  257. }
  258.  
  259.     /* GetChangedDrive():
  260.      *
  261.      *    Walk through the list of filing devices and obtain
  262.      *    the change count of each drive. Return the device
  263.      *    which has recently had a disk-change.
  264.      */
  265.  
  266. struct DevNode *
  267. GetChangedDrive()
  268. {
  269.     struct DevNode    *ChangedDrive = NULL;
  270.     struct DevNode    *SomeNode;
  271.     struct IOExtTD    *DevRequest;
  272.  
  273.     SomeNode = (struct DevNode *)DevList -> lh_Head;
  274.  
  275.         /* Walk through the list.. */
  276.  
  277.     while(SomeNode -> VanillaNode . ln_Succ)
  278.     {
  279.             /* Open the driver. */
  280.  
  281.         if(DevRequest = OpenDrive(SomeNode -> DevNode))
  282.         {
  283.             DevRequest -> iotd_Req . io_Command = TD_CHANGENUM;
  284.  
  285.                 /* Obtain the disk change count. */
  286.  
  287.             if(!DoIO(DevRequest))
  288.             {
  289.                     /* Is it different from the
  290.                      * value last obtained?
  291.                      */
  292.  
  293.                 if(SomeNode -> ChangeCount != DevRequest -> iotd_Req . io_Actual)
  294.                 {
  295.                     ChangedDrive = SomeNode;
  296.  
  297.                     SomeNode -> ChangeCount = DevRequest -> iotd_Req . io_Actual;
  298.                 }
  299.             }
  300.  
  301.             CloseDrive(DevRequest);
  302.         }
  303.  
  304.         SomeNode = (struct DevNode *)SomeNode -> VanillaNode . ln_Succ;
  305.     }
  306.  
  307.     return(ChangedDrive);
  308. }
  309.  
  310.     /* FindDevices():
  311.      *
  312.      *    Scan the DosList for block-mapped filing devices.
  313.      */
  314.  
  315. struct List *
  316. FindDevices()
  317. {
  318.     struct DosList        *DosList;
  319.     struct DeviceNode    *DevNode;
  320.     struct List        *SomeList;
  321.     struct DevNode        *SomeNode;
  322.     UBYTE            *Pointer;
  323.     SHORT             i;
  324.  
  325.         /* Allocate a list for the DevNode entries. */
  326.  
  327.     if(SomeList = (struct List *)AllocVec(sizeof(struct List),MEMF_PUBLIC|MEMF_CLEAR))
  328.     {
  329.         NewList(SomeList);
  330.  
  331.             /* Lock the DosList for reading. */
  332.  
  333.         DosList = LockDosList(LDF_DEVICES|LDF_READ);
  334.  
  335.             /* Scan the list for device entries. */
  336.  
  337.         while(DosList = NextDosEntry(DosList,LDF_DEVICES|LDF_READ))
  338.         {
  339.                 /* Swap the entry type. */
  340.  
  341.             DevNode = (struct DeviceNode *)DosList;
  342.  
  343.                 /* Kludge: RAW:, PRT:, PAR: have dn_Startup
  344.                  * set to a nonzero value.
  345.                  */
  346.  
  347.             if(DevNode -> dn_Startup > 1000 && (DevNode -> dn_Task || DevNode -> dn_Handler || DevNode -> dn_SegList))
  348.             {
  349.                 Pointer = (UBYTE *)BADDR(DevNode -> dn_Name);
  350.  
  351.                     /* If it has a name, add it to the list. */
  352.  
  353.                 if(Pointer[0])
  354.                 {
  355.                     if(SomeNode = AllocVec(sizeof(struct DevNode) + Pointer[0] + 2,MEMF_PUBLIC|MEMF_CLEAR))
  356.                     {
  357.                         SomeNode -> VanillaNode . ln_Name = (UBYTE *)(SomeNode + 1);
  358.  
  359.                         for(i = 0 ; i < Pointer[0] ; i++)
  360.                             SomeNode -> VanillaNode . ln_Name[i] = Pointer[i + 1];
  361.  
  362.                         SomeNode -> VanillaNode . ln_Name[Pointer[0]    ]    = ':';
  363.                         SomeNode -> VanillaNode . ln_Name[Pointer[0] + 1]    = 0;
  364.                         SomeNode -> DevNode                    = DevNode;
  365.  
  366.                         AddTail(SomeList,SomeNode);
  367.                     }
  368.                 }
  369.             }
  370.         }
  371.  
  372.         UnLockDosList(LDF_DEVICES|LDF_READ);
  373.     }
  374.  
  375.     return(SomeList);
  376. }
  377.  
  378.     /* FreeDevices(struct List *SomeList):
  379.      *
  380.      *    Free the list of devices obtained through FindDevices.
  381.      */
  382.  
  383. VOID
  384. FreeDevices(struct List *SomeList)
  385. {
  386.     struct Node *SomeNode,*NextNode;
  387.  
  388.     SomeNode = SomeList -> lh_Head;
  389.  
  390.     while(SomeNode -> ln_Succ)
  391.     {
  392.         NextNode = SomeNode -> ln_Succ;
  393.  
  394.         FreeVec(SomeNode);
  395.  
  396.         SomeNode = NextNode;
  397.     }
  398.  
  399.     FreeVec(SomeList);
  400. }
  401.  
  402.     /* CreateAllGadgets():
  403.      *
  404.      *    Create all the gadgets for the Format window.
  405.      */
  406.  
  407. struct Gadget *
  408. CreateAllGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge)
  409. {
  410.     struct Gadget        *Gadget;
  411.     struct NewGadget     NewGadget;
  412.     UWORD             Counter = 0,LeftEdge;
  413.  
  414.     if(Gadget = CreateContext(GadgetList))
  415.     {
  416.         if(DevList = FindDevices())
  417.             GetChangedDrive();
  418.  
  419.         NewGadget . ng_Width        = 268;
  420.         NewGadget . ng_Height        = 60;
  421.         NewGadget . ng_GadgetText    = "Drives";
  422.         NewGadget . ng_TextAttr        = &DefaultFont;
  423.         NewGadget . ng_VisualInfo    = VisualInfo;
  424.         NewGadget . ng_GadgetID        = Counter;
  425.         NewGadget . ng_Flags        = PLACETEXT_LEFT;
  426.         NewGadget . ng_LeftEdge        = LeftEdge = (strlen(NewGadget . ng_GadgetText) + 2) * 8 + 1;
  427.         NewGadget . ng_TopEdge        = 1 + TopEdge;
  428.  
  429.         GadgetArray[Counter++] = Gadget = CreateGadget(LISTVIEW_KIND,Gadget,&NewGadget,
  430.             GTLV_Labels,        DevList,
  431.             GTLV_Selected,        DevList ? 0 : ~0,
  432.             GTLV_ShowSelected,    NULL,
  433.         TAG_DONE);
  434.  
  435.         NewGadget . ng_GadgetText    = "Size";
  436.         NewGadget . ng_Height        = 12;
  437.         NewGadget . ng_GadgetID        = Counter;
  438.         NewGadget . ng_TopEdge        = Gadget -> TopEdge + Gadget -> Height + 13;
  439.  
  440.         GadgetArray[Counter++] = Gadget = CreateGadget(TEXT_KIND,Gadget,&NewGadget,
  441.             GTTX_Text,        "   -- Tracks   --.--- MBytes",
  442.             GTTX_Border,        TRUE,
  443.         TAG_DONE);
  444.  
  445.         NewGadget . ng_GadgetText    = "_Name";
  446.         NewGadget . ng_Height        = 14;
  447.         NewGadget . ng_GadgetID        = Counter;
  448.         NewGadget . ng_TopEdge        = Gadget -> TopEdge + Gadget -> Height + 1;
  449.  
  450.         GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
  451.             GTST_MaxChars,    31,
  452.             GTST_String,    "Empty",
  453.             GT_Underscore,    '_',
  454.         TAG_DONE);
  455.  
  456.         NewGadget . ng_GadgetText    = "_Format Whole Disk";
  457.         NewGadget . ng_Width        = 244;
  458.         NewGadget . ng_Height        = 12;
  459.         NewGadget . ng_GadgetID        = Counter;
  460.         NewGadget . ng_Flags        = PLACETEXT_RIGHT;
  461.         NewGadget . ng_LeftEdge        = LeftEdge + 272;
  462.         NewGadget . ng_TopEdge        = 1 + TopEdge;
  463.  
  464.         GadgetArray[Counter++] = Gadget = CreateGadget(CHECKBOX_KIND,Gadget,&NewGadget,
  465.             GT_Underscore,    '_',
  466.             GTCB_Checked,    TRUE,
  467.         TAG_DONE);
  468.  
  469.         NewGadget . ng_GadgetText    = "_Verify Writes";
  470.         NewGadget . ng_Width        = 244;
  471.         NewGadget . ng_Height        = 12;
  472.         NewGadget . ng_GadgetID        = Counter;
  473.         NewGadget . ng_TopEdge        = Gadget -> TopEdge + Gadget -> Height + 1;
  474.  
  475.         GadgetArray[Counter++] = Gadget = CreateGadget(CHECKBOX_KIND,Gadget,&NewGadget,
  476.             GT_Underscore,    '_',
  477.             GTCB_Checked,    TRUE,
  478.         TAG_DONE);
  479.  
  480.         NewGadget . ng_GadgetText    = "_Create Icons";
  481.         NewGadget . ng_Width        = 244;
  482.         NewGadget . ng_Height        = 12;
  483.         NewGadget . ng_GadgetID        = Counter;
  484.         NewGadget . ng_TopEdge        = Gadget -> TopEdge + Gadget -> Height + 1;
  485.  
  486.         GadgetArray[Counter++] = Gadget = CreateGadget(CHECKBOX_KIND,Gadget,&NewGadget,
  487.             GT_Underscore,    '_',
  488.             GTCB_Checked,    TRUE,
  489.         TAG_DONE);
  490.  
  491.         NewGadget . ng_GadgetText    = "_Install Disk";
  492.         NewGadget . ng_Width        = 244;
  493.         NewGadget . ng_Height        = 12;
  494.         NewGadget . ng_GadgetID        = Counter;
  495.         NewGadget . ng_TopEdge        = Gadget -> TopEdge + Gadget -> Height + 1;
  496.  
  497.         GadgetArray[Counter++] = Gadget = CreateGadget(CHECKBOX_KIND,Gadget,&NewGadget,
  498.             GT_Underscore,    '_',
  499.         TAG_DONE);
  500.  
  501.         NewGadget . ng_GadgetText    = "_Auto Start";
  502.         NewGadget . ng_Width        = 244;
  503.         NewGadget . ng_Height        = 12;
  504.         NewGadget . ng_GadgetID        = Counter;
  505.         NewGadget . ng_TopEdge        = Gadget -> TopEdge + Gadget -> Height + 1;
  506.  
  507.         GadgetArray[Counter++] = Gadget = CreateGadget(CHECKBOX_KIND,Gadget,&NewGadget,
  508.             GT_Underscore,    '_',
  509.         TAG_DONE);
  510.  
  511.         NewGadget . ng_GadgetText    = "_Eject Disk";
  512.         NewGadget . ng_Width        = 244;
  513.         NewGadget . ng_Height        = 12;
  514.         NewGadget . ng_GadgetID        = Counter;
  515.         NewGadget . ng_TopEdge        = Gadget -> TopEdge + Gadget -> Height + 1;
  516.  
  517.         GadgetArray[Counter++] = Gadget = CreateGadget(CHECKBOX_KIND,Gadget,&NewGadget,
  518.             GT_Underscore,    '_',
  519.         TAG_DONE);
  520.  
  521.         NewGadget . ng_GadgetText    = "_Use Fast Filing System";
  522.         NewGadget . ng_Width        = 244;
  523.         NewGadget . ng_Height        = 12;
  524.         NewGadget . ng_GadgetID        = Counter;
  525.         NewGadget . ng_TopEdge        = Gadget -> TopEdge + Gadget -> Height + 1;
  526.  
  527.         GadgetArray[Counter++] = Gadget = CreateGadget(CHECKBOX_KIND,Gadget,&NewGadget,
  528.             GT_Underscore,    '_',
  529.         TAG_DONE);
  530.  
  531.         NewGadget . ng_GadgetText    = "Status";
  532.         NewGadget . ng_Width        = 268;
  533.         NewGadget . ng_Height        = 12;
  534.         NewGadget . ng_Flags        = 0;
  535.         NewGadget . ng_GadgetID        = Counter;
  536.         NewGadget . ng_LeftEdge        = LeftEdge;
  537.         NewGadget . ng_TopEdge        = Gadget -> TopEdge + Gadget -> Height + 2;
  538.  
  539.         GadgetArray[Counter++] = Gadget = CreateGadget(TEXT_KIND,Gadget,&NewGadget,
  540.             GTTX_Text,        "Idle",
  541.             GTTX_Border,        TRUE,
  542.         TAG_DONE);
  543.  
  544.         NewGadget . ng_GadgetText    = "Start (_S)";
  545.         NewGadget . ng_Width        = 133;
  546.         NewGadget . ng_Height        = 12;
  547.         NewGadget . ng_Flags        = 0;
  548.         NewGadget . ng_GadgetID        = Counter;
  549.         NewGadget . ng_LeftEdge        = LeftEdge;
  550.         NewGadget . ng_TopEdge        = Gadget -> TopEdge + Gadget -> Height + 1;
  551.  
  552.         GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  553.             GT_Underscore,    '_',
  554.         TAG_DONE);
  555.  
  556.         NewGadget . ng_GadgetText    = "Stop (_S)";
  557.         NewGadget . ng_Width        = 133;
  558.         NewGadget . ng_Height        = 12;
  559.         NewGadget . ng_GadgetID        = Counter;
  560.         NewGadget . ng_LeftEdge        = LeftEdge + 135;
  561.  
  562.         GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  563.             GT_Underscore,    '_',
  564.             GA_Disabled,    TRUE,
  565.         TAG_DONE);
  566.     }
  567.  
  568.     return(Gadget);
  569. }
  570.  
  571.     /* CloseAll(LONG ReturnCode):
  572.      *
  573.      *    Return all resources obtained at startup and exit
  574.      *    gracefully.
  575.      */
  576.  
  577. VOID
  578. CloseAll(LONG ReturnCode)
  579. {
  580.     if(WBenchWindow)
  581.         RemoveAppWindow(WBenchWindow);
  582.  
  583.     if(WBenchPort)
  584.     {
  585.         struct Message *Massage;
  586.  
  587.         while(Massage = GetMsg(WBenchPort))
  588.             ReplyMsg(Massage);
  589.  
  590.         DeleteMsgPort(WBenchPort);
  591.     }
  592.  
  593.     if(WorkbenchBase)
  594.         CloseLibrary(WorkbenchBase);
  595.  
  596.     if(Window)
  597.         CloseWindow(Window);
  598.  
  599.     if(GadgetList)
  600.         FreeGadgets(GadgetList);
  601.  
  602.     if(VisualInfo)
  603.         FreeVisualInfo(VisualInfo);
  604.  
  605.     if(DefaultScreen)
  606.         UnlockPubScreen(NULL,DefaultScreen);
  607.  
  608.     if(DevList)
  609.         FreeDevices(DevList);
  610.  
  611.     if(IconBase)
  612.         CloseLibrary(IconBase);
  613.  
  614.     if(GadToolsBase)
  615.         CloseLibrary(GadToolsBase);
  616.  
  617.     if(GfxBase)
  618.         CloseLibrary(GfxBase);
  619.  
  620.     if(IntuitionBase)
  621.         CloseLibrary(IntuitionBase);
  622.  
  623.     exit(ReturnCode);
  624. }
  625.  
  626.     /* OpenAll():
  627.      *
  628.      *    Obtain all resourced required to run this program.
  629.      */
  630.  
  631. VOID
  632. OpenAll()
  633. {
  634.     if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37)))
  635.         CloseAll(RETURN_FAIL + 1);
  636.  
  637.     if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",37)))
  638.         CloseAll(RETURN_FAIL + 2);
  639.  
  640.     if(!(GadToolsBase = (struct Library *)OpenLibrary("gadtools.library",37)))
  641.         CloseAll(RETURN_FAIL + 3);
  642.  
  643.     IconBase = OpenLibrary("icon.library",37);
  644.  
  645.     if(!(Topaz = (struct TextFont *)OpenFont(&DefaultFont)))
  646.         CloseAll(RETURN_FAIL + 4);
  647.  
  648.     if(!(DefaultScreen = (struct Screen *)LockPubScreen(NULL)))
  649.         CloseAll(RETURN_FAIL + 5);
  650.  
  651.     if(!(VisualInfo = GetVisualInfo(DefaultScreen,TAG_DONE)))
  652.         CloseAll(RETURN_FAIL + 6);
  653.  
  654.     if(!CreateAllGadgets(&GadgetArray[0],&GadgetList,VisualInfo,DefaultScreen -> WBorTop + DefaultScreen -> Font -> ta_YSize + 1))
  655.         CloseAll(RETURN_FAIL + 7);
  656.  
  657.     if(!(Window = OpenWindowTags(NULL,
  658.         WA_Width,    WIDTH,
  659.         WA_Height,    HEIGHT + DefaultScreen -> Font -> ta_YSize - 8,
  660.  
  661.         WA_Activate,    TRUE,
  662.         WA_DragBar,    TRUE,
  663.         WA_DepthGadget,    TRUE,
  664.         WA_CloseGadget,    TRUE,
  665.         WA_RMBTrap,    TRUE,
  666.  
  667.         WA_IDCMP,    IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY | IDCMP_DISKINSERTED | CHECKBOXIDCMP | BUTTONIDCMP | LISTVIEWIDCMP,
  668.  
  669.         WA_Title,    "Format v1.1 © Copyright 1991 by MXM",
  670.     TAG_DONE)))
  671.         CloseAll(RETURN_FAIL + 8);
  672.  
  673.     if(WorkbenchBase = OpenLibrary("workbench.library",37))
  674.     {
  675.         if(!(WBenchPort = CreateMsgPort()))
  676.             CloseAll(RETURN_FAIL + 9);
  677.  
  678.         WBenchWindow = AddAppWindow(0,0,Window,WBenchPort,NULL);
  679.     }
  680.  
  681.     SetFont(Window -> RPort,Topaz);
  682.  
  683.     AddGList(Window,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
  684.     RefreshGList(GadgetList,Window,NULL,(UWORD)-1);
  685.     GT_RefreshWindow(Window,NULL);
  686.  
  687.     UpdateInfo();
  688. }
  689.  
  690.     /* LockWindow(struct Window *Window):
  691.      *
  692.      *    Disable all gadgets in the Format window and set the
  693.      *    stopwatch mouse pointer.
  694.      */
  695.  
  696. VOID
  697. LockWindow(struct Window *Window)
  698. {
  699.     SetWait(Window);
  700.  
  701.     GT_SetGadgetAttrs(GadgetArray[GAD_NAME],Window,NULL,
  702.         GA_Disabled,    TRUE,
  703.     TAG_DONE);
  704.  
  705.     GT_SetGadgetAttrs(GadgetArray[GAD_WHOLEDISK],Window,NULL,
  706.         GA_Disabled,    TRUE,
  707.     TAG_DONE);
  708.  
  709.     GT_SetGadgetAttrs(GadgetArray[GAD_USEFFS],Window,NULL,
  710.         GA_Disabled,    TRUE,
  711.     TAG_DONE);
  712.  
  713.     GT_SetGadgetAttrs(GadgetArray[GAD_START],Window,NULL,
  714.         GA_Disabled,    TRUE,
  715.     TAG_DONE);
  716.  
  717.     GT_SetGadgetAttrs(GadgetArray[GAD_STOP],Window,NULL,
  718.         GA_Disabled,    FALSE,
  719.     TAG_DONE);
  720. }
  721.  
  722.     /* UnLockWindow(struct Window *Window):
  723.      *
  724.      *    Re-enable the gadgets in the Format window and clear
  725.      *    the mouse pointer.
  726.      */
  727.  
  728. VOID
  729. UnLockWindow(struct Window *Window)
  730. {
  731.     ClearPointer(Window);
  732.  
  733.     GT_SetGadgetAttrs(GadgetArray[GAD_NAME],Window,NULL,
  734.         GA_Disabled,    FALSE,
  735.     TAG_DONE);
  736.  
  737.     GT_SetGadgetAttrs(GadgetArray[GAD_WHOLEDISK],Window,NULL,
  738.         GA_Disabled,    FALSE,
  739.     TAG_DONE);
  740.  
  741.     GT_SetGadgetAttrs(GadgetArray[GAD_USEFFS],Window,NULL,
  742.         GA_Disabled,    FALSE,
  743.     TAG_DONE);
  744.  
  745.     GT_SetGadgetAttrs(GadgetArray[GAD_STOP],Window,NULL,
  746.         GA_Disabled,    TRUE,
  747.     TAG_DONE);
  748.  
  749.     GT_SetGadgetAttrs(GadgetArray[GAD_START],Window,NULL,
  750.         GA_Disabled,    FALSE,
  751.     TAG_DONE);
  752. }
  753.  
  754.     /* GetUsedBlocks(struct DosEnvec *DosEnvec,BYTE UseFFS):
  755.      *
  756.      *    Calculate the number of blocks which will be
  757.      *    occupied if a filing system is formatted.
  758.      */
  759.  
  760. ULONG
  761. GetUsedBlocks(struct DosEnvec *DosEnvec,BYTE UseFFS)
  762. {
  763.     ULONG Blocks,BitmapBlocks,ExtensionBlocks = 0;
  764.  
  765.         /* Number of blocks available for the
  766.          * filing system.
  767.          */
  768.  
  769.     Blocks = (DosEnvec -> de_HighCyl - DosEnvec -> de_LowCyl + 1) * DosEnvec -> de_BlocksPerTrack * DosEnvec -> de_Surfaces;
  770.  
  771.         /* Calculate the number of bitmap blocks. */
  772.  
  773.     BitmapBlocks = (((Blocks + 31) / 32) + 126) / 127;
  774.  
  775.         /* The old filing system only allows 25 bitmap
  776.          * blocks.
  777.          */
  778.  
  779.     if(UseFFS && BitmapBlocks > 25)
  780.         BitmapBlocks = 25;
  781.     else
  782.     {
  783.             /* If there are more than 25 bitmap blocks,
  784.              * calculate the number of bitmap extension
  785.              * blocks required to chain them.
  786.              */
  787.  
  788.         if(BitmapBlocks > 25)
  789.             ExtensionBlocks = (BitmapBlocks - 25 + 126) / 127;
  790.     }
  791.  
  792.     return(DosEnvec -> de_Reserved + BitmapBlocks + ExtensionBlocks + 1);
  793. }
  794.  
  795.     /* SizeInfo(struct DeviceNode *DevNode):
  796.      *
  797.      *    Give a brief size info on a given filing system.
  798.      */
  799.  
  800. VOID
  801. SizeInfo(struct DeviceNode *DevNode)
  802. {
  803.     if(Formatting)
  804.     {
  805.         struct DevNode    *SomeNode;
  806.         SHORT         i = 0;
  807.  
  808.             /* This is a nuisance: you cannot disable
  809.              * gadtools listviews. As a fix we will
  810.              * simply ignore any clicks in this area
  811.              * and revert to the previously selected
  812.              * entry.
  813.              */
  814.  
  815.         SomeNode = (struct DevNode *)DevList -> lh_Head;
  816.  
  817.         while(SomeNode -> VanillaNode . ln_Succ)
  818.         {
  819.             if(SomeNode -> DevNode != LastNode)
  820.             {
  821.                 i++;
  822.  
  823.                 SomeNode = (struct DevNode *)SomeNode -> VanillaNode . ln_Succ;
  824.             }
  825.             else
  826.                 break;
  827.         }
  828.  
  829.         GT_SetGadgetAttrs(GadgetArray[GAD_DRIVES],Window,NULL,
  830.             GTLV_Selected,    i,
  831.         TAG_DONE);
  832.     }
  833.     else
  834.     {
  835.         struct DosEnvec    *DosEnvec;
  836.         ULONG         Blocks;
  837.         UBYTE         Buffer[60];
  838.  
  839.         UpdateInfo();
  840.  
  841.             /* Neat casting, innit? */
  842.  
  843.         DosEnvec = (struct DosEnvec *)BADDR(((struct FileSysStartupMsg *)BADDR(DevNode -> dn_Startup)) -> fssm_Environ);
  844.  
  845.             /* Determine the number of blocks which are actually
  846.              * not in use.
  847.              */
  848.  
  849.         Blocks = (DosEnvec -> de_HighCyl - DosEnvec -> de_LowCyl + 1) * DosEnvec -> de_Surfaces * DosEnvec -> de_SectorPerBlock * DosEnvec -> de_BlocksPerTrack - GetUsedBlocks(DosEnvec,UseFFS);
  850.  
  851.             /* Multiply by the verbatim size of a DOS block. */
  852.  
  853.         if(UseFFS)
  854.             Blocks = Blocks * (DosEnvec -> de_SizeBlock << 2) / 1000;
  855.         else
  856.             Blocks = Blocks * 488 / 1000;
  857.  
  858.         SPrintf(Buffer,"%5ld Tracks %4ld.%03ld MBytes",DosEnvec -> de_HighCyl - DosEnvec -> de_LowCyl + 1,Blocks / 1000,Blocks % 1000);
  859.  
  860.         GT_SetGadgetAttrs(GadgetArray[GAD_SIZE],Window,NULL,
  861.             GTTX_Text,    Buffer,
  862.         TAG_DONE);
  863.  
  864.         LastNode = DevNode;
  865.     }
  866. }
  867.  
  868.     /* ShowInfo(UBYTE *Format,...):
  869.      *
  870.      *    Show a text in the status field of the Format window.
  871.      */
  872.  
  873. VOID
  874. ShowInfo(UBYTE *Format,...)
  875. {
  876.     UBYTE    Buffer[60];
  877.     va_list    VarArgs;
  878.  
  879.     va_start(VarArgs,Format);
  880.     VSPrintf(Buffer,Format,VarArgs);
  881.     va_end(VarArgs);
  882.  
  883.     if(FromShell)
  884.         Printf("\33[A%s\33[K\n",Buffer);
  885.     else
  886.     {
  887.         GT_SetGadgetAttrs(GadgetArray[GAD_STATUS],Window,NULL,
  888.             GTTX_Text,    Buffer,
  889.         TAG_DONE);
  890.     }
  891. }
  892.  
  893.     /* MyEasyRequest():
  894.      *
  895.      *    Varargs version of the EasyRequest call.
  896.      */
  897.  
  898. SHORT __stdargs
  899. MyEasyRequest(struct Window *Window,UBYTE *Text,UBYTE *Gadgets,...)
  900. {
  901.     struct EasyStruct __aligned    Easy;
  902.     SHORT                Result;
  903.     ULONG                IDCMP = NULL;
  904.     va_list                 VarArgs;
  905.  
  906.     Easy . es_StructSize    = sizeof(struct EasyStruct);
  907.     Easy . es_Flags        = NULL;
  908.     Easy . es_Title        = (UBYTE *)"Format Request";
  909.     Easy . es_TextFormat    = (UBYTE *)Text;
  910.     Easy . es_GadgetFormat    = (UBYTE *)Gadgets;
  911.  
  912.     va_start(VarArgs,Gadgets);
  913.     Result = EasyRequestArgs(Window,&Easy,&IDCMP,VarArgs);
  914.     va_end(VarArgs);
  915.  
  916.     return(Result);
  917. }
  918.  
  919.     /* HandleInput():
  920.      *
  921.      *    Tiny subroutine which handles all the input coming
  922.      *    while we are formatting.
  923.      */
  924.  
  925. BYTE
  926. HandleInput()
  927. {
  928.     BYTE Finished = FALSE;
  929.  
  930.     if(FromShell)
  931.     {
  932.         if(SetSignal(0,0) & SIGBREAKF_CTRL_C)
  933.         {
  934.             SetSignal(0,SIGBREAKF_CTRL_C);
  935.  
  936.             Finished = TRUE;
  937.  
  938.             Printf("\n***BREAK: Format\n\n");
  939.         }
  940.     }
  941.     else
  942.     {
  943.         if(WBenchPort)
  944.         {
  945.             if(SetSignal(0,0) & (1 << WBenchPort -> mp_SigBit))
  946.             {
  947.                 struct Message *Massage;
  948.  
  949.                 SetSignal(0,(1 << WBenchPort -> mp_SigBit));
  950.  
  951.                 while(Massage = GetMsg(WBenchPort))
  952.                     ReplyMsg(Massage);
  953.             }
  954.         }
  955.  
  956.         if(SetSignal(0,0) & (1 << Window -> UserPort -> mp_SigBit))
  957.         {
  958.             struct IntuiMessage    *Massage;
  959.             ULONG             Class,Code;
  960.             struct Gadget        *Gadget;
  961.  
  962.             SetSignal(0,(1 << Window -> UserPort -> mp_SigBit));
  963.  
  964.             while(Massage = (struct IntuiMessage *)GT_GetIMsg(Window -> UserPort))
  965.             {
  966.                 Class    = Massage -> Class;
  967.                 Code    = Massage -> Code;
  968.                 Gadget    = (struct Gadget *)Massage -> IAddress;
  969.  
  970.                 GT_ReplyIMsg(Massage);
  971.  
  972.                 if(Class == IDCMP_GADGETUP)
  973.                 {
  974.                     UpdateInfo();
  975.  
  976.                     if(Gadget -> GadgetID == GAD_STOP)
  977.                         Finished = TRUE;
  978.  
  979.                     if(Gadget -> GadgetID == GAD_DRIVES)
  980.                         SizeInfo(NULL);
  981.                 }
  982.  
  983.                 if(Class == IDCMP_VANILLAKEY)
  984.                 {
  985.                     if(toupper(Code) == 'S')
  986.                         Finished = TRUE;
  987.                     else
  988.                     {
  989.                         SHORT i;
  990.  
  991.                         for(i = 0 ; i < (sizeof(Shortcuts) / sizeof(struct Shortcut)) ; i++)
  992.                         {
  993.                             if(Shortcuts[i] . Key == toupper(Code))
  994.                             {
  995.                                 if(Shortcuts[i] . GadgetType == CHECKBOX_KIND)
  996.                                 {
  997.                                     if(!(GadgetArray[Shortcuts[i] . GadgetID] -> Flags & GFLG_DISABLED))
  998.                                     {
  999.                                         GT_SetGadgetAttrs(GadgetArray[Shortcuts[i] . GadgetID],Window,NULL,
  1000.                                             GTCB_Checked,    (GadgetArray[Shortcuts[i] . GadgetID] -> Flags & GFLG_SELECTED) ? FALSE : TRUE,
  1001.                                         TAG_DONE);
  1002.  
  1003.                                         UpdateInfo();
  1004.                                     }
  1005.                                 }
  1006.                             }
  1007.                         }
  1008.                     }
  1009.                 }
  1010.             }
  1011.         }
  1012.     }
  1013.  
  1014.     return(Finished);
  1015. }
  1016.  
  1017.     /* Initialize():
  1018.      *
  1019.      *    Initialize a filing system, check if there is a disk in the
  1020.      *    drive and if it's write enabled. Format the whole disk if
  1021.      *    necessary.
  1022.      */
  1023.  
  1024. BYTE
  1025. Initialize(struct DevNode *DriveNode,struct IOExtTD *DevRequest)
  1026. {
  1027.         /* Is there a disk in the drive? */
  1028.  
  1029.     FOREVER
  1030.     {
  1031.         DevRequest -> iotd_Req . io_Command = TD_CHANGESTATE;
  1032.  
  1033.         if(!DoIO(DevRequest))
  1034.         {
  1035.             if(DevRequest -> iotd_Req . io_Actual)
  1036.             {
  1037.                 if(FromShell)
  1038.                 {
  1039.                     Printf("No disk present in drive.\n",DriveNode -> VanillaNode . ln_Name);
  1040.  
  1041.                     return(FALSE);
  1042.                 }
  1043.                 else
  1044.                 {
  1045.                     if(!MyEasyRequest(Window,"No disk present in drive\n%s","Retry|Cancel",DriveNode -> VanillaNode . ln_Name))
  1046.                         return(FALSE);
  1047.                 }
  1048.             }
  1049.             else
  1050.                 break;
  1051.         }
  1052.         else
  1053.             break;
  1054.     }
  1055.  
  1056.         /* Is the disk write enabled? */
  1057.  
  1058.     FOREVER
  1059.     {
  1060.         DevRequest -> iotd_Req . io_Command = TD_PROTSTATUS;
  1061.  
  1062.         if(!DoIO(DevRequest))
  1063.         {
  1064.             if(DevRequest -> iotd_Req . io_Actual)
  1065.             {
  1066.                 if(FromShell)
  1067.                 {
  1068.                     Printf("Disk in drive %s is write protected.\n",DriveNode -> VanillaNode . ln_Name);
  1069.  
  1070.                     return(FALSE);
  1071.                 }
  1072.                 else
  1073.                 {
  1074.                     if(!MyEasyRequest(Window,"Disk in drive\n%s\nis write protected.","Retry|Cancel",DriveNode -> VanillaNode . ln_Name))
  1075.                         return(FALSE);
  1076.                 }
  1077.             }
  1078.             else
  1079.                 break;
  1080.         }
  1081.         else
  1082.             break;
  1083.     }
  1084.  
  1085.         /* Are we to format the whole disk? */
  1086.  
  1087.     if(WholeDisk)
  1088.     {
  1089.         ULONG        *Track1,*Track2,*Src,*Dst;
  1090.         ULONG         SizeTrack,i,j;
  1091.         struct DosEnvec    *DosEnvec;
  1092.         ULONG         LowTrack,NumTracks;
  1093.         BYTE         Result = TRUE,Match;
  1094.  
  1095.         DosEnvec = (struct DosEnvec *)BADDR(((struct FileSysStartupMsg *)BADDR(DriveNode -> DevNode -> dn_Startup)) -> fssm_Environ);
  1096.  
  1097.             /* Determine the size of a disk track. */
  1098.  
  1099.         SizeTrack = (DosEnvec -> de_SizeBlock << 2) * DosEnvec -> de_Surfaces * DosEnvec -> de_BlocksPerTrack;
  1100.  
  1101.             /* Allocate a write track... */
  1102.  
  1103.         if(Track1 = (ULONG *)AllocVec(SizeTrack,DosEnvec -> de_BufMemType|MEMF_CLEAR))
  1104.         {
  1105.                 /* ...and a verification track. */
  1106.  
  1107.             if(Track2 = (ULONG *)AllocVec(SizeTrack,DosEnvec -> de_BufMemType))
  1108.             {
  1109.                     /* Look up the first track and the number of
  1110.                      * tracks to format.
  1111.                      */
  1112.  
  1113.                 LowTrack    = DosEnvec -> de_LowCyl * SizeTrack;
  1114.                 NumTracks    = DosEnvec -> de_HighCyl - DosEnvec -> de_LowCyl + 1;
  1115.  
  1116.                     /* Run down the number of tracks to format. */
  1117.  
  1118.                 for(i = 0 ; i < NumTracks ; i++)
  1119.                 {
  1120.                     if(HandleInput())
  1121.                     {
  1122.                         Result = FALSE;
  1123.  
  1124.                         break;
  1125.                     }
  1126.  
  1127. Retry:                    ShowInfo("Formatting %ld, %ld To Go",i,NumTracks - i - 1);
  1128.  
  1129.                         /* Format a track. */
  1130.  
  1131.                     DevRequest -> iotd_Req . io_Command    = TD_FORMAT;
  1132.                     DevRequest -> iotd_Req . io_Data    = Track1;
  1133.                     DevRequest -> iotd_Req . io_Offset    = LowTrack;
  1134.                     DevRequest -> iotd_Req . io_Length    = SizeTrack;
  1135.  
  1136.                     if(DoIO(DevRequest))
  1137.                     {
  1138.                         if(FromShell)
  1139.                         {
  1140.                             Printf("Error %ld occured while formatting track %ld.\n",DevRequest -> iotd_Req . io_Error,i);
  1141.  
  1142.                             Result = FALSE;
  1143.  
  1144.                             break;
  1145.                         }
  1146.                         else
  1147.                         {
  1148.                             if(MyEasyRequest(Window,"Error %ld occured while formatting track %ld.","Rewrite|Abort",DevRequest -> iotd_Req . io_Error,i))
  1149.                                 goto Retry;
  1150.                             else
  1151.                             {
  1152.                                 Result = FALSE;
  1153.  
  1154.                                 break;
  1155.                             }
  1156.                         }
  1157.                     }
  1158.  
  1159.                         /* Check for abort. */
  1160.  
  1161.                     if(HandleInput())
  1162.                     {
  1163.                         Result = FALSE;
  1164.  
  1165.                         break;
  1166.                     }
  1167.  
  1168.                         /* If verification is enabled,
  1169.                          * reread the track.
  1170.                          */
  1171.  
  1172.                     if(Verify)
  1173.                     {
  1174.                         DevRequest -> iotd_Req . io_Command = CMD_UPDATE;
  1175.  
  1176.                         if(DoIO(DevRequest))
  1177.                         {
  1178.                             if(FromShell)
  1179.                             {
  1180.                                 Printf("Error %ld occured while formatting track %ld.\n",DevRequest -> iotd_Req . io_Error,i);
  1181.  
  1182.                                 Result = FALSE;
  1183.  
  1184.                                 break;
  1185.                             }
  1186.                             else
  1187.                             {
  1188.                                 if(MyEasyRequest(Window,"Error %ld occured while formatting track %ld.","Rewrite|Abort",DevRequest -> iotd_Req . io_Error,i))
  1189.                                     goto Retry;
  1190.                                 else
  1191.                                 {
  1192.                                     Result = FALSE;
  1193.  
  1194.                                     break;
  1195.                                 }
  1196.                             }
  1197.                         }
  1198.  
  1199. Retry2:                        ShowInfo("Verifying  %ld, %ld To Go",i,NumTracks - i - 1);
  1200.  
  1201.                         DevRequest -> iotd_Req . io_Command    = CMD_READ;
  1202.                         DevRequest -> iotd_Req . io_Data    = Track2;
  1203.                         DevRequest -> iotd_Req . io_Offset    = LowTrack;
  1204.                         DevRequest -> iotd_Req . io_Length    = SizeTrack;
  1205.  
  1206.                         if(DoIO(DevRequest))
  1207.                         {
  1208.                             if(FromShell)
  1209.                             {
  1210.                                 Printf("Error %ld occured while verifying track %ld.\n",DevRequest -> iotd_Req . io_Error,i);
  1211.  
  1212.                                 Result = FALSE;
  1213.  
  1214.                                 break;
  1215.                             }
  1216.                             else
  1217.                             {
  1218.                                 if(MyEasyRequest(Window,"Error %ld occured while verifying track %ld.","Reread|Abort",DevRequest -> iotd_Req . io_Error,i))
  1219.                                     goto Retry2;
  1220.                                 else
  1221.                                 {
  1222.                                     Result = FALSE;
  1223.  
  1224.                                     break;
  1225.                                 }
  1226.                             }
  1227.                         }
  1228.  
  1229.                         Match = TRUE;
  1230.  
  1231.                         j = SizeTrack >> 2;
  1232.  
  1233.                         Src = Track1;
  1234.                         Dst = Track2;
  1235.  
  1236.                             /* Compare both
  1237.                              * tracks. If the
  1238.                              * data compared in
  1239.                              * this loop was
  1240.                              * residing in
  1241.                              * chip ram, we
  1242.                              * could use the
  1243.                              * blitter to do
  1244.                              * the job.
  1245.                              */
  1246.  
  1247.                         while(j--)
  1248.                         {
  1249.                             if(*Src++ != *Dst++)
  1250.                             {
  1251.                                 Match = FALSE;
  1252.                                 break;
  1253.                             }
  1254.                         }
  1255.  
  1256.                             /* Are both tracks equal? */
  1257.  
  1258.                         if(!Match)
  1259.                         {
  1260.                             if(FromShell)
  1261.                             {
  1262.                                 Printf("Verification error on track %ld.\n",i);
  1263.  
  1264.                                 Result = FALSE;
  1265.  
  1266.                                 break;
  1267.                             }
  1268.                             else
  1269.                             {
  1270.                                 if(MyEasyRequest(Window,"Verification error on track %ld.","Rewrite|Abort",i))
  1271.                                     goto Retry2;
  1272.                                 else
  1273.                                 {
  1274.                                     Result = FALSE;
  1275.  
  1276.                                     break;
  1277.                                 }
  1278.                             }
  1279.                         }
  1280.                     }
  1281.  
  1282.                     LowTrack += SizeTrack;
  1283.                 }
  1284.  
  1285.                 FreeVec(Track2);
  1286.             }
  1287.  
  1288.             FreeVec(Track1);
  1289.         }
  1290.  
  1291.         return(Result);
  1292.     }
  1293.     else
  1294.         return(TRUE);
  1295. }
  1296.  
  1297.     /* Install():
  1298.      *
  1299.      *    Handle the rest of the initialization, write the root block,
  1300.      *    the bitmap blocks and install the disk if necessary.
  1301.      */
  1302.  
  1303. BYTE
  1304. Install(struct DevNode *DriveNode,struct IOExtTD *DevRequest)
  1305. {
  1306.     struct DosEnvec    *DosEnvec;
  1307.     ULONG        *Block;
  1308.     UBYTE        *Name;
  1309.  
  1310.     ShowInfo("Preparing Disk");
  1311.  
  1312.     DosEnvec = (struct DosEnvec *)BADDR(((struct FileSysStartupMsg *)BADDR(DriveNode -> DevNode -> dn_Startup)) -> fssm_Environ);
  1313.  
  1314.     if(HandleInput())
  1315.         return(FALSE);
  1316.  
  1317.     if(DiskName)
  1318.         Name = DiskName;
  1319.     else
  1320.         Name = ((struct StringInfo *)GadgetArray[GAD_NAME] -> SpecialInfo) -> Buffer;
  1321.  
  1322.     if(HandleInput())
  1323.         return(FALSE);
  1324.  
  1325.         /* Tell the handler to initialize the underlying data media. */
  1326.  
  1327.     if(!Format(DriveNode -> VanillaNode . ln_Name,Name[0] ? Name : "Empty",UseFFS ? ID_FFS_DISK : ID_DOS_DISK))
  1328.     {
  1329.         if(FromShell)
  1330.             Printf("Failed to format drive %s.\n",DriveNode -> VanillaNode . ln_Name);
  1331.         else
  1332.             MyEasyRequest(Window,"Failed to format drive\n%s","Proceed",DriveNode -> VanillaNode . ln_Name);
  1333.  
  1334.         return(FALSE);
  1335.     }
  1336.  
  1337.         /* Are we to install the disk and is there enough space left
  1338.          * to install it?
  1339.          */
  1340.  
  1341.     if(DosEnvec -> de_Reserved > 0 && InstallDisk)
  1342.     {
  1343.             /* Allocate a bootblock-sized chunk. */
  1344.  
  1345.         if(Block = (ULONG *)AllocVec((DosEnvec -> de_SizeBlock << 2) * DosEnvec -> de_Reserved,DosEnvec -> de_BufMemType|MEMF_CLEAR))
  1346.         {
  1347.             ShowInfo("Installing Disk");
  1348.  
  1349.                 /* Install the approriate bootblock type. */
  1350.  
  1351.             if(UseFFS)
  1352.                 CopyMem(Bootblock_FFS,Block,sizeof(Bootblock_FFS));
  1353.             else
  1354.                 CopyMem(Bootblock_OFS,Block,sizeof(Bootblock_OFS));
  1355.  
  1356.             DevRequest -> iotd_Req . io_Command    = CMD_WRITE;
  1357.             DevRequest -> iotd_Req . io_Data    = Block;
  1358.             DevRequest -> iotd_Req . io_Length    = (DosEnvec -> de_SizeBlock << 2) * DosEnvec -> de_Reserved;
  1359.             DevRequest -> iotd_Req . io_Offset    = DosEnvec -> de_LowCyl * DosEnvec -> de_Surfaces * (DosEnvec -> de_SizeBlock << 2);
  1360.  
  1361.             if(DoIO(DevRequest))
  1362.             {
  1363.                 if(FromShell)
  1364.                     Printf("Error %ld occured while writing the boot block.\n",DevRequest -> iotd_Req . io_Error);
  1365.                 else
  1366.                     MyEasyRequest(Window,"Error %ld occured while writing the boot block.","Proceed",DevRequest -> iotd_Req . io_Error);
  1367.  
  1368.                 FreeVec(Block);
  1369.  
  1370.                 return(FALSE);
  1371.             }
  1372.  
  1373.             FreeVec(Block);
  1374.         }
  1375.     }
  1376.  
  1377.     if(EjectDisk)
  1378.     {
  1379.         DevRequest -> iotd_Req . io_Command = TD_EJECT;
  1380.  
  1381.         DoIO(DevRequest);
  1382.     }
  1383.  
  1384.     return(TRUE);
  1385. }
  1386.  
  1387.     /* FormatDrive(struct DevNode *DriveNode,BYTE Query):
  1388.      *
  1389.      *    Format a filing system, handle the user-interface part.
  1390.      */
  1391.  
  1392. VOID
  1393. FormatDrive(struct DevNode *DriveNode,BYTE Query)
  1394. {
  1395.     struct DosEnvec    *DosEnvec;
  1396.     ULONG         Blocks;
  1397.  
  1398.     DosEnvec = (struct DosEnvec *)BADDR(((struct FileSysStartupMsg *)BADDR(DriveNode -> DevNode -> dn_Startup)) -> fssm_Environ);
  1399.  
  1400.     Blocks = (DosEnvec -> de_HighCyl - DosEnvec -> de_LowCyl + 1) * DosEnvec -> de_Surfaces * DosEnvec -> de_BlocksPerTrack;
  1401.  
  1402.     Formatting = TRUE;
  1403.  
  1404.     if(!FromShell)
  1405.         LockWindow(Window);
  1406.  
  1407.     UpdateInfo();
  1408.  
  1409.         /* Is the user trying to format filing system larger than
  1410.          * 52 MBytes using the old filing system?
  1411.          */
  1412.  
  1413.     if(Blocks > 101600 && !UseFFS)
  1414.     {
  1415.         if(FromShell)
  1416.             Printf("You cannot format partitions larger than approximately 52 MBytes\nusing the old filing system. Use Fast File System instead.\n");
  1417.         else
  1418.             MyEasyRequest(Window,"You cannot format partitions larger than\napproximately  52  MBytes  using the old\nfiling  system.   Use  Fast  File System\ninstead.","Proceed");
  1419.     }
  1420.     else
  1421.     {
  1422.         SHORT Result;
  1423.  
  1424.             /* Give the user a last chance to abort the
  1425.              * formatting.
  1426.              */
  1427.  
  1428.         if(Query)
  1429.         {
  1430.                 /* Display a special text if the
  1431.                  * data media to be formatted is not
  1432.                  * a standard 3½" disk.
  1433.                  */
  1434.  
  1435.             if(Blocks > 1760)
  1436.             {
  1437.                 DisplayBeep(Window -> WScreen);
  1438.  
  1439.                 Result = MyEasyRequest(Window,"                Caution!\n\n\
  1440. Drive  %s   is  not  a  standard-sized\n\
  1441. floppy disk drive but rather a hard-disk\n\
  1442. or high-density-floppy-disk drive.\n\n\
  1443.        OK to format disk in drive\n\
  1444.        %s\n\
  1445.        (all data will be erased)?","OK|OK-Quick|Cancel",DriveNode -> VanillaNode . ln_Name,DriveNode -> VanillaNode . ln_Name);
  1446.             }
  1447.             else
  1448.                 Result = MyEasyRequest(Window,"OK to format disk in drive\n%s\n(all data will be erased)?","OK|OK-Quick|Cancel",DriveNode -> VanillaNode . ln_Name);
  1449.  
  1450.             if(Result == 2)
  1451.             {
  1452.                 GT_SetGadgetAttrs(GadgetArray[GAD_WHOLEDISK],Window,NULL,
  1453.                     GTCB_Checked,    FALSE,
  1454.                 TAG_DONE);
  1455.  
  1456.                 WholeDisk = FALSE;
  1457.             }
  1458.         }
  1459.         else
  1460.             Result = 1;
  1461.  
  1462.         UpdateInfo();
  1463.  
  1464.             /* Start to format the disk. */
  1465.  
  1466.         if(Result)
  1467.         {
  1468.             struct MsgPort *Proc;
  1469.  
  1470.             ShowInfo("Preparing to format drive %s",DriveNode -> VanillaNode . ln_Name);
  1471.  
  1472.                 /* Tell the filing system to sleep. */
  1473.  
  1474.             if(Proc = DeviceProc(DriveNode -> VanillaNode . ln_Name))
  1475.             {
  1476.                 if(DoPkt1(Proc,ACTION_INHIBIT,DOSTRUE))
  1477.                 {
  1478.                     struct IOExtTD    *DevRequest;
  1479.                     BYTE         Success = FALSE;
  1480.  
  1481.                     if(DevRequest = OpenDrive(DriveNode -> DevNode))
  1482.                     {
  1483.                         ShowInfo("Initializing Disk");
  1484.  
  1485.                         if(Initialize(DriveNode,DevRequest))
  1486.                             Success = Install(DriveNode,DevRequest);
  1487.  
  1488.                         CloseDrive(DevRequest);
  1489.                     }
  1490.                     else
  1491.                     {
  1492.                         if(FromShell)
  1493.                             Printf("Failed to open unit driver for drive %s.",DriveNode -> VanillaNode . ln_Name);
  1494.                         else
  1495.                             MyEasyRequest(Window,"Failed to open unit driver for drive %s.","Proceed",DriveNode -> VanillaNode . ln_Name);
  1496.                     }
  1497.  
  1498.                         /* Reenable the filing system. */
  1499.  
  1500.                     DoPkt1(Proc,ACTION_INHIBIT,DOSFALSE);
  1501.  
  1502.                         /* Are we to create icons? */
  1503.  
  1504.                     if(Success && CreateIcons && IconBase)
  1505.                     {
  1506.                         struct DiskObject    *Object;
  1507.                         UBYTE             Buffer[60];
  1508.  
  1509.                         ShowInfo("Creating Icons");
  1510.  
  1511.                             /* Create a disk icon. */
  1512.  
  1513.                         if(Object = GetDefDiskObject(WBDISK))
  1514.                         {
  1515.                             SPrintf(Buffer,"%sDisk",DriveNode -> VanillaNode . ln_Name);
  1516.  
  1517.                             Success = PutDiskObject(Buffer,Object);
  1518.  
  1519.                             FreeDiskObject(Object);
  1520.                         }
  1521.  
  1522.                             /* Create a trashcan icon. */
  1523.  
  1524.                         if(Success)
  1525.                         {
  1526.                             if(Object = GetDefDiskObject(WBGARBAGE))
  1527.                             {
  1528.                                 SPrintf(Buffer,"%sTrashcan",DriveNode -> VanillaNode . ln_Name);
  1529.  
  1530.                                 if(PutDiskObject(Buffer,Object))
  1531.                                     UnLock(CreateDir(Buffer));
  1532.  
  1533.                                 FreeDiskObject(Object);
  1534.                             }
  1535.                         }
  1536.                     }
  1537.  
  1538.                     if(!FromShell)
  1539.                         ShowInfo("Done!");
  1540.                 }
  1541.             }
  1542.         }
  1543.     }
  1544.  
  1545.     if(!FromShell)
  1546.     {
  1547.         ShowInfo("Idle");
  1548.  
  1549.         UnLockWindow(Window);
  1550.     }
  1551.  
  1552.     Formatting = FALSE;
  1553. }
  1554.  
  1555.     /* FormatFromWB(struct WBArg *Arg):
  1556.      *
  1557.      *    Grab a Workbench argument pointer and try to format
  1558.      *    the associated filing system.
  1559.      */
  1560.  
  1561. VOID
  1562. FormatFromWB(struct WBArg *Arg)
  1563. {
  1564.     struct DevNode    *SomeNode;
  1565.     SHORT         i = 0;
  1566.     UBYTE         DriverName[256];
  1567.  
  1568.         /* If it has got a lock take the name of the
  1569.          * associated filing system, else take a look
  1570.          * at the name passed to us.
  1571.          */
  1572.  
  1573.     if(Arg -> wa_Lock)
  1574.     {
  1575.         struct FileLock *FileLock = BADDR(Arg -> wa_Lock);
  1576.  
  1577.         strcpy(DriverName,((struct Task *)FileLock -> fl_Task -> mp_SigTask) -> tc_Node . ln_Name);
  1578.         strcat(DriverName,":");
  1579.     }
  1580.     else
  1581.         strcpy(DriverName,Arg -> wa_Name);
  1582.  
  1583.     SomeNode = (struct DevNode *)DevList -> lh_Head;
  1584.  
  1585.         /* Look for the node corresponding to the name. */
  1586.  
  1587.     while(SomeNode -> VanillaNode . ln_Succ)
  1588.     {
  1589.         if(stricmp(DriverName,SomeNode -> VanillaNode . ln_Name))
  1590.         {
  1591.             i++;
  1592.             SomeNode = (struct DevNode *)SomeNode -> VanillaNode . ln_Succ;
  1593.         }
  1594.         else
  1595.             break;
  1596.     }
  1597.  
  1598.         /* Did we find a device of that name? */
  1599.  
  1600.     if(SomeNode -> VanillaNode . ln_Succ)
  1601.     {
  1602.         GT_SetGadgetAttrs(GadgetArray[GAD_DRIVES],Window,NULL,
  1603.             GTLV_Selected,    i,
  1604.         TAG_DONE);
  1605.  
  1606.         GT_SetGadgetAttrs(GadgetArray[GAD_USEFFS],Window,NULL,
  1607.             GTCB_Checked,    ((struct DosEnvec *)BADDR(((struct FileSysStartupMsg *)BADDR(SomeNode -> DevNode -> dn_Startup)) -> fssm_Environ)) -> de_DosType == ID_FFS_DISK ? TRUE : FALSE,
  1608.         TAG_DONE);
  1609.  
  1610.         SizeInfo(SomeNode -> DevNode);
  1611.  
  1612.         FormatDrive(SomeNode,TRUE);
  1613.     }
  1614.     else
  1615.         MyEasyRequest(Window,"Drive %s is not a block-mapped\ndisk filing system.","Proceed",DriverName);
  1616. }
  1617.  
  1618.     /* main(int argc,char **argv):
  1619.      *
  1620.      *    The main routine (what else?).
  1621.      */
  1622.  
  1623. VOID
  1624. main(int argc,char **argv)
  1625. {
  1626.     struct IntuiMessage    *Massage;
  1627.     ULONG             Class,Code;
  1628.     struct Gadget        *Gadget;
  1629.     BYTE             Terminated = FALSE;
  1630.     SHORT             i;
  1631.     struct DevNode        *DriveNode;
  1632.     extern struct ExecBase    *SysBase;
  1633.  
  1634.         /* Check to see if it's below our preferred
  1635.          * revision number.
  1636.          */
  1637.  
  1638.     if(SysBase -> LibNode . lib_Version < 37)
  1639.         exit(RETURN_FAIL);
  1640.  
  1641.         /* We were run from Workbench, have a look at the
  1642.          * startup packet being passed.
  1643.          */
  1644.  
  1645.     if(!argc)
  1646.     {
  1647.         extern struct WBStartup *WBenchMsg;
  1648.  
  1649.             /* We are asked to format data media. */
  1650.  
  1651.         if(WBenchMsg -> sm_NumArgs > 1)
  1652.         {
  1653.             OpenAll();
  1654.  
  1655.                 /* Run down the list of
  1656.                  * arguments.
  1657.                  */
  1658.  
  1659.             for(i = 1 ; i < WBenchMsg -> sm_NumArgs ; i++)
  1660.                 FormatFromWB(&WBenchMsg -> sm_ArgList[i]);
  1661.  
  1662.             CloseAll(RETURN_OK);
  1663.         }
  1664.     }
  1665.  
  1666.         /* If the argument count is below two, then we're
  1667.          * probably to display the shiny gadtools panel.
  1668.          */
  1669.  
  1670.     if(argc < 2)
  1671.     {
  1672.         ULONG SignalSet;
  1673.  
  1674.             /* Open the libs and create the panel. */
  1675.  
  1676.         OpenAll();
  1677.  
  1678.             /* Pick up the first filing system in the list. */
  1679.  
  1680.         DriveNode = (struct DevNode *)DevList -> lh_Head;
  1681.  
  1682.             /* Toggle the `Use FFS' button if necessary. */
  1683.  
  1684.         GT_SetGadgetAttrs(GadgetArray[GAD_USEFFS],Window,NULL,
  1685.             GTCB_Checked,    ((struct DosEnvec *)BADDR(((struct FileSysStartupMsg *)BADDR(DriveNode -> DevNode -> dn_Startup)) -> fssm_Environ)) -> de_DosType == ID_FFS_DISK ? TRUE : FALSE,
  1686.         TAG_DONE);
  1687.  
  1688.             /* Display the size of the data media. */
  1689.  
  1690.         SizeInfo(DriveNode -> DevNode);
  1691.  
  1692.             /* Go into loop waiting for input... */
  1693.  
  1694.         while(!Terminated)
  1695.         {
  1696.                 /* Piece the signal mask to wait
  1697.                  * for together.
  1698.                  */
  1699.  
  1700.             SignalSet = (1 << Window -> UserPort -> mp_SigBit);
  1701.  
  1702.                 /* Wait for any messages sent by Workbench. */
  1703.  
  1704.             if(WBenchPort)
  1705.                 SignalSet |= (1 << WBenchPort -> mp_SigBit);
  1706.  
  1707.             SignalSet = Wait(SignalSet);
  1708.  
  1709.                 /* Have a look at the Workbench port. */
  1710.  
  1711.             if(WBenchPort)
  1712.             {
  1713.                 struct AppMessage *AppMassage;
  1714.  
  1715.                     /* Remove the application window
  1716.                      * messages.
  1717.                      */
  1718.  
  1719.                 while(AppMassage = (struct AppMessage *)GetMsg(WBenchPort))
  1720.                 {
  1721.                         /* Format the associated media. */
  1722.  
  1723.                     for(i = 0 ; i < AppMassage -> am_NumArgs ; i++)
  1724.                         FormatFromWB(&AppMassage -> am_ArgList[i]);
  1725.  
  1726.                     ReplyMsg(&AppMassage -> am_Message);
  1727.                 }
  1728.             }
  1729.  
  1730.                 /* Remove all the messages pending
  1731.                  * at the panel window.
  1732.                  */
  1733.  
  1734.             while(!Terminated && (Massage = (struct IntuiMessage *)GT_GetIMsg(Window -> UserPort)))
  1735.             {
  1736.                 Class    = Massage -> Class;
  1737.                 Code    = Massage -> Code;
  1738.                 Gadget    = (struct Gadget *)Massage -> IAddress;
  1739.  
  1740.                 GT_ReplyIMsg(Massage);
  1741.  
  1742.                     /* Terminate the program? */
  1743.  
  1744.                 if(Class == IDCMP_CLOSEWINDOW)
  1745.                     Terminated = TRUE;
  1746.  
  1747.                     /* A disk has been inserted and
  1748.                      * we're probably autostart-enabled.
  1749.                      */
  1750.  
  1751.                 if(Class == IDCMP_DISKINSERTED)
  1752.                 {
  1753.                     struct DevNode *Node;
  1754.  
  1755.                         /* To insure that all the
  1756.                          * disk change counts are
  1757.                          * kept even, even if auto-
  1758.                          * start is not enabled we
  1759.                          * will call the checkup
  1760.                          * routine and abort if
  1761.                          * autostart is not enabled.
  1762.                          * If were not playing the
  1763.                          * game this way, we could
  1764.                          * accidentally assume that
  1765.                          * a disk changed long ago
  1766.                          * before autostart was
  1767.                          * enabled was a candidat
  1768.                          * for formatting...
  1769.                          */
  1770.  
  1771.                     if((Node = GetChangedDrive()) && AutoStart)
  1772.                     {
  1773.                         struct DevNode *SomeNode;
  1774.  
  1775.                             /* Try to find the
  1776.                              * index of the
  1777.                              * DevNode whose
  1778.                              * device we are to
  1779.                              * initialize (to
  1780.                              * keep the listview
  1781.                              * happy).
  1782.                              */
  1783.  
  1784.                         i = 0;
  1785.  
  1786.                         SomeNode = (struct DevNode *)DevList -> lh_Head;
  1787.  
  1788.                         while(SomeNode -> VanillaNode . ln_Succ)
  1789.                         {
  1790.                             if(SomeNode != Node)
  1791.                             {
  1792.                                 i++;
  1793.                                 SomeNode = (struct DevNode *)SomeNode -> VanillaNode . ln_Succ;
  1794.                             }
  1795.                             else
  1796.                                 break;
  1797.                         }
  1798.  
  1799.                         DriveNode = SomeNode;
  1800.  
  1801.                             /* Display the
  1802.                              * size of the
  1803.                              * data media.
  1804.                              */
  1805.  
  1806.                         SizeInfo(SomeNode -> DevNode);
  1807.  
  1808.                             /* Display the
  1809.                              * approriate listview
  1810.                              * entry.
  1811.                              */
  1812.  
  1813.                         GT_SetGadgetAttrs(GadgetArray[GAD_DRIVES],Window,NULL,
  1814.                             GTLV_Selected,    i,
  1815.                         TAG_DONE);
  1816.  
  1817.                             /* Bring the screen
  1818.                              * to the front...
  1819.                              */
  1820.  
  1821.                         MoveScreen(Window -> WScreen,-Window -> WScreen -> LeftEdge,-Window -> WScreen -> TopEdge);
  1822.                         ScreenToFront(Window -> WScreen);
  1823.  
  1824.                             /* Flash the display. */
  1825.  
  1826.                         DisplayBeep(Window -> WScreen);
  1827.  
  1828.                             /* Bring the window to
  1829.                              * the front.
  1830.                              */
  1831.  
  1832.                         WindowToFront(Window);
  1833.  
  1834.                         LockWindow(Window);
  1835.  
  1836.                             /* Wait two seconds
  1837.                              * before actually
  1838.                              * starting the
  1839.                              * formatting process.
  1840.                              * This little break
  1841.                              * will (hopefully!)
  1842.                              * allow the user to
  1843.                              * abort the
  1844.                              * initialization of
  1845.                              * precious data media.
  1846.                              */
  1847.  
  1848.                         for(i = 0 ; i < 2 ; i++)
  1849.                         {
  1850.                             ShowInfo("%ld seconds to format %s",2 - i,DriveNode -> VanillaNode . ln_Name);
  1851.  
  1852.                             if(HandleInput())
  1853.                             {
  1854.                                 Node = NULL;
  1855.  
  1856.                                 break;
  1857.                             }
  1858.  
  1859.                             Delay(TICKS_PER_SECOND);
  1860.                         }
  1861.  
  1862.                             /* Format the drive
  1863.                              * or don't...
  1864.                              */
  1865.  
  1866.                         if(Node)
  1867.                             FormatDrive(DriveNode,FALSE);
  1868.                         else
  1869.                         {
  1870.                             UnLockWindow(Window);
  1871.  
  1872.                             ShowInfo("Idle");
  1873.                         }
  1874.                     }
  1875.                 }
  1876.  
  1877.                     /* The user hit one of the gadgets
  1878.                      * displayed in the panel.
  1879.                      */
  1880.  
  1881.                 if(Class == IDCMP_GADGETUP)
  1882.                 {
  1883.                     UpdateInfo();
  1884.  
  1885.                         /* Start formatting? */
  1886.  
  1887.                     if(Gadget -> GadgetID == GAD_START)
  1888.                         FormatDrive(DriveNode,TRUE);
  1889.  
  1890.                         /* Select another disk
  1891.                          * drive?
  1892.                          */
  1893.  
  1894.                     if(Gadget -> GadgetID == GAD_DRIVES)
  1895.                     {
  1896.                         struct DevNode *SomeNode;
  1897.  
  1898.                         i = 0;
  1899.  
  1900.                         SomeNode = (struct DevNode *)DevList -> lh_Head;
  1901.  
  1902.                         while(SomeNode -> VanillaNode . ln_Succ)
  1903.                         {
  1904.                             if(i++ != Code)
  1905.                                 SomeNode = (struct DevNode *)SomeNode -> VanillaNode . ln_Succ;
  1906.                             else
  1907.                                 break;
  1908.                         }
  1909.  
  1910.                         DriveNode = SomeNode;
  1911.  
  1912.                         GT_SetGadgetAttrs(GadgetArray[GAD_USEFFS],Window,NULL,
  1913.                             GTCB_Checked,    ((struct DosEnvec *)BADDR(((struct FileSysStartupMsg *)BADDR(SomeNode -> DevNode -> dn_Startup)) -> fssm_Environ)) -> de_DosType == ID_FFS_DISK ? TRUE : FALSE,
  1914.                         TAG_DONE);
  1915.  
  1916.                         SizeInfo(SomeNode -> DevNode);
  1917.                     }
  1918.  
  1919.                         /* Toggle the effects
  1920.                          * of the FFS gadget.
  1921.                          */
  1922.  
  1923.                     if(Gadget -> GadgetID == GAD_USEFFS)
  1924.                         SizeInfo(LastNode);
  1925.                 }
  1926.  
  1927.                     /* The following block handles
  1928.                      * the keyboard shortcuts available.
  1929.                      * Most important among these
  1930.                      * are `S' (= Start/Stop formatting)
  1931.                      * and Escape (= terminate the
  1932.                      * program.
  1933.                      */
  1934.  
  1935.                 if(Class == IDCMP_VANILLAKEY)
  1936.                 {
  1937.                     if(toupper(Code) == 'S')
  1938.                         FormatDrive(DriveNode,TRUE);
  1939.                     else
  1940.                     {
  1941.                         if(Code == '\033')
  1942.                             Terminated = TRUE;
  1943.                         else
  1944.                         {
  1945.                             for(i = 0 ; i < (sizeof(Shortcuts) / sizeof(struct Shortcut)) ; i++)
  1946.                             {
  1947.                                 if(Shortcuts[i] . Key == toupper(Code))
  1948.                                 {
  1949.                                     switch(Shortcuts[i] . GadgetType)
  1950.                                     {
  1951.                                         case STRING_KIND:    ActivateGadget(GadgetArray[Shortcuts[i] . GadgetID],Window,NULL);
  1952.                                                     break;
  1953.  
  1954.                                         case CHECKBOX_KIND:    if(!(GadgetArray[Shortcuts[i] . GadgetID] -> Flags & GFLG_DISABLED))
  1955.                                                     {
  1956.                                                         GT_SetGadgetAttrs(GadgetArray[Shortcuts[i] . GadgetID],Window,NULL,
  1957.                                                             GTCB_Checked,    (GadgetArray[Shortcuts[i] . GadgetID] -> Flags & GFLG_SELECTED) ? FALSE : TRUE,
  1958.                                                         TAG_DONE);
  1959.  
  1960.                                                         UpdateInfo();
  1961.  
  1962.                                                         if(Shortcuts[i] . GadgetID == GAD_USEFFS)
  1963.                                                             SizeInfo(LastNode);
  1964.                                                     }
  1965.  
  1966.                                                     break;
  1967.  
  1968.                                         default:        break;
  1969.                                     }
  1970.  
  1971.                                     break;
  1972.                                 }
  1973.                             }
  1974.                         }
  1975.                     }
  1976.                 }
  1977.             }
  1978.         }
  1979.     }
  1980.     else
  1981.     {
  1982.         UBYTE **Arg;
  1983.  
  1984.             /* Let's come to the Shell interface,
  1985.              * start by allocating the argument vector
  1986.              * table to pass to ReadArgs.
  1987.              */
  1988.  
  1989.         if(Arg = (UBYTE **)AllocVec(sizeof(UBYTE *) * NUM_ARGS,MEMF_PUBLIC | MEMF_CLEAR))
  1990.         {
  1991.             struct RDArgs *ArgsPtr;
  1992.  
  1993.                 /* Perform command line parsing. */
  1994.  
  1995.             if(ArgsPtr = ReadArgs(ARG_TEMPLATE,(LONG *)Arg,NULL))
  1996.             {
  1997.                 struct DevNode *SomeNode;
  1998.  
  1999.                     /* Let it be known: no GUI this
  2000.                      * time!
  2001.                      */
  2002.  
  2003.                 FromShell = TRUE;
  2004.  
  2005.                     /* Set up the list of legal
  2006.                      * filing devices.
  2007.                      */
  2008.  
  2009.                 if(DevList = FindDevices())
  2010.                 {
  2011.                         /* Try to find the device
  2012.                          * we are to format.
  2013.                          */
  2014.  
  2015.                     SomeNode = (struct DevNode *)DevList -> lh_Head;
  2016.  
  2017.                     while(SomeNode -> VanillaNode . ln_Succ)
  2018.                     {
  2019.                         if(!stricmp(SomeNode -> VanillaNode . ln_Name,Arg[ARG_DRIVE]))
  2020.                             break;
  2021.                         else
  2022.                             SomeNode = (struct DevNode *)SomeNode -> VanillaNode . ln_Succ;
  2023.                     }
  2024.  
  2025.                         /* Did we find the device? */
  2026.  
  2027.                     if(SomeNode -> VanillaNode . ln_Succ)
  2028.                     {
  2029.                         struct MsgPort    *Proc;
  2030.                         UBYTE         TinyBuffer[5];
  2031.  
  2032.                             /* Turn up the driver behind the
  2033.                              * data media.
  2034.                              */
  2035.  
  2036.                         if(Proc = DeviceProc(DriveNode -> VanillaNode . ln_Name))
  2037.                         {
  2038.                                 /* Disable the restart validation process. */
  2039.  
  2040.                             if(DoPkt1(Proc,ACTION_INHIBIT,DOSTRUE))
  2041.                             {
  2042.                                     /* Prompt for <return> */
  2043.  
  2044.                                 Printf("Insert disk to be formatted in drive %s and press RETURN",SomeNode -> VanillaNode . ln_Name);
  2045.                                 Flush(((struct Process *)SysBase -> ThisTask) -> pr_CIS);
  2046.  
  2047.                                 FGets(((struct Process *)SysBase -> ThisTask) -> pr_COS,TinyBuffer,5);
  2048.  
  2049.                                     /* Abort the process? */
  2050.  
  2051.                                 if(SetSignal(0,0) & SIGBREAKF_CTRL_C)
  2052.                                 {
  2053.                                     SetSignal(0,SIGBREAKF_CTRL_C);
  2054.  
  2055.                                     DoPkt1(Proc,ACTION_INHIBIT,DOSFALSE);
  2056.  
  2057.                                     Printf("\n*** BREAK: Format\a\n\n");
  2058.  
  2059.                                     FreeArgs(ArgsPtr);
  2060.                                     FreeVec(Arg);
  2061.  
  2062.                                     CloseAll(RETURN_WARN);
  2063.                                 }
  2064.  
  2065.                                     /* Make sure that we will get a
  2066.                                      * valid disk name ("" expands
  2067.                                      * to `Empty').
  2068.                                      */
  2069.  
  2070.                                 if(Arg[ARG_NAME])
  2071.                                     DiskName = Arg[ARG_NAME];
  2072.                                 else
  2073.                                     DiskName = "";
  2074.  
  2075.                                     /* See if by default FFS is
  2076.                                      * enabled.
  2077.                                      */
  2078.  
  2079.                                 UseFFS = ((struct DosEnvec *)BADDR(((struct FileSysStartupMsg *)BADDR(SomeNode -> DevNode -> dn_Startup)) -> fssm_Environ)) -> de_DosType == ID_FFS_DISK ? TRUE : FALSE;
  2080.  
  2081.                                     /* Transform the remaining
  2082.                                      * arguments into flags.
  2083.                                      */
  2084.  
  2085.                                 if(Arg[ARG_FFS])
  2086.                                     UseFFS = TRUE;
  2087.  
  2088.                                 if(!Arg[ARG_NOICONS])
  2089.                                     CreateIcons = TRUE;
  2090.  
  2091.                                 if(!Arg[ARG_QUICK])
  2092.                                     WholeDisk = TRUE;
  2093.  
  2094.                                 if(!Arg[ARG_NOVERIFY])
  2095.                                     Verify = TRUE;
  2096.  
  2097.                                 if(Arg[ARG_INSTALL])
  2098.                                     InstallDisk = TRUE;
  2099.  
  2100.                                 if(Arg[ARG_EJECT])
  2101.                                     EjectDisk = TRUE;
  2102.  
  2103.                                     /* Turn off the console cursor. */
  2104.  
  2105.                                 Printf("\33[0 p\n");
  2106.  
  2107.                                     /* Format the drive. */
  2108.  
  2109.                                 FormatDrive(SomeNode,FALSE);
  2110.  
  2111.                                     /* Turn the console cursor back on. */
  2112.  
  2113.                                 Printf("\33[ p");
  2114.  
  2115.                                     /* Reenable the disk validation process. */
  2116.  
  2117.                                 DoPkt1(Proc,ACTION_INHIBIT,DOSFALSE);
  2118.                             }
  2119.                         }
  2120.                     }
  2121.                     else
  2122.                     {
  2123.                         Printf("Format: Cannot format drive %s.\a\n",SomeNode -> VanillaNode . ln_Name);
  2124.  
  2125.                         FreeArgs(ArgsPtr);
  2126.                         FreeVec(Arg);
  2127.  
  2128.                         CloseAll(RETURN_FAIL);
  2129.                     }
  2130.                 }
  2131.                 else
  2132.                 {
  2133.                     Printf("Format: Out of memory!\a\n");
  2134.  
  2135.                     FreeArgs(ArgsPtr);
  2136.                     FreeVec(Arg);
  2137.  
  2138.                     CloseAll(RETURN_FAIL);
  2139.                 }
  2140.  
  2141.                 FreeArgs(ArgsPtr);
  2142.             }
  2143.             else
  2144.             {
  2145.                 PrintFault(IoErr(),"Format\a");
  2146.  
  2147.                 FreeVec(Arg);
  2148.  
  2149.                 CloseAll(RETURN_FAIL);
  2150.             }
  2151.  
  2152.             FreeVec(Arg);
  2153.         }
  2154.         else
  2155.         {
  2156.             Printf("Format: Out of memory!\a\n");
  2157.  
  2158.             CloseAll(RETURN_FAIL);
  2159.         }
  2160.     }
  2161.  
  2162.     CloseAll(RETURN_OK);
  2163. }
  2164.  
  2165.     /* Et c'est tout! */
  2166.