home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / System / Sample 2.4 Think C distribution / scan.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-26  |  23.5 KB  |  855 lines  |  [TEXT/KAHL]

  1. /*______________________________________________________________________
  2.  
  3.     scan.c - Scanning Module
  4.     
  5.     Copyright © 1988, 1989, 1990 Northwestern University.  Permission is granted
  6.     to use this code in your own projects, provided you give credit to both
  7.     John Norstad and Northwestern University in your about box or document.
  8.     
  9.     This module takes care of various tasks involving scanning.
  10. _____________________________________________________________________*/
  11.  
  12. #include <string.h>
  13.  
  14. #include "utl.h"
  15. #include "rep.h"
  16. #include "vol.h"
  17. #include "rez.h"
  18. #include "scn.h"
  19. #include "gff.h"
  20. #include "glob.h"
  21. #include "mssg.h"
  22. #include "misc.h"
  23. #include "prog.h"
  24. #include "main.h"
  25. #include "scan.h"
  26.  
  27. #define nil 0
  28.  
  29. /*______________________________________________________________________
  30.  
  31.     Global Variables.
  32. _____________________________________________________________________*/
  33.  
  34.  
  35. static short        InsertedVRefNum;    /* vol ref num of inserted disk */
  36. static Boolean        BadDisk;                /* true if uninitialized disk inserted */
  37.  
  38. /*______________________________________________________________________
  39.  
  40.     scan_CheckCancel - Check for Cancel of Scan in Progress.
  41.     
  42.     Exit:            function result = true if canceled, else false.
  43.     
  44.     This routine is called by the scanning routines to see if the operation 
  45.     has been canceled (command-period or for a click on the cancel
  46.     button).
  47. _____________________________________________________________________*/
  48.  
  49.  
  50. Boolean scan_CheckCancel(void)
  51.  
  52. {
  53.     prog_Event();
  54.     return Canceled;
  55. }
  56.  
  57. /*______________________________________________________________________
  58.  
  59.     scan_CheckFull - Check to See if the Report is Full.
  60.     
  61.     Entry:        report = report handle.
  62.                     slop = number of bytes to guarantee free.
  63.                     
  64.     Exit:            function result = true if cancel button selected or error
  65.                     saving report.
  66. _____________________________________________________________________*/
  67.  
  68.  
  69. Boolean scan_CheckFull (Handle report, short slop)
  70.  
  71. {
  72.     short                item;                    /* alert item number */
  73.     Str255            line1;                /* unplugged message */
  74.     Str255            line2;                /* plugged message */
  75.     Str255            vName;                /* vol name */
  76.  
  77.     if (rep_Full(report, slop)) {
  78.         if (!Prefs.scanningStation) {
  79.             misc_Notify(requiresAttn, true);
  80.             item = utl_StopAlert(repFullID, nil, 2);
  81.             switch (item) {
  82.                 case 1:        /* Save */
  83.                     if (!main_Save()) return true;
  84.                     break;
  85.                 case 2:        /* Cancel */
  86.                     return true;
  87.                 case 3:        /* Clear */
  88.                     break;
  89.             };
  90.             misc_Update();
  91.         };
  92.         misc_ClearReport();
  93.         misc_Update();
  94.         rep_Append(report, (Str255 *)"\p", false, false);
  95.         rep_Append(report, (Str255 *)"\p===========================================",
  96.             true, true);
  97.         rep_Append(report, (Str255 *)"\p", true, true);
  98.         GetIndString(line1, strListID, repContStr);
  99.         vol_GetName(&vName);
  100.         utl_PlugParams(&line1, &line2, &vName, nil, nil, nil);
  101.         rep_Append(report, &line2, true, true);
  102.         rep_Append(report, (Str255 *)"\p", true, true);
  103.     };
  104.     return Canceled;
  105. };
  106.  
  107. /*______________________________________________________________________
  108.  
  109.     DrawVolList - Draw Volume List in Dialog.
  110.     
  111.     Entry:    dlog = pointer to volume list dialog.
  112.                 itemNo = item number of volume list rectangle.
  113. _____________________________________________________________________*/
  114.  
  115.  
  116. static pascal void DrawVolList (WindowPtr dlog, short itemNo)
  117.  
  118. {
  119.     short                    itemType;    /* type of dialog item */
  120.     Handle                itemHandle;    /* handle to dialog item */
  121.     Rect                    itemBox;        /* rectangle enclosing dialog item */
  122.     ListHandle            volList;        /* volume list */    
  123.     
  124.     volList = (ListHandle)((WindowPeek)dlog)->refCon;
  125.     LUpdate(dlog->visRgn , volList);
  126.     GetDItem(dlog, itemNo, &itemType, &itemHandle, &itemBox);
  127.     FrameRect(&itemBox);
  128. }
  129.  
  130. /*______________________________________________________________________
  131.  
  132.     OutlineOK - Outline OK button in Dialog.
  133.     
  134.     Entry:    dlog = pointer to volume list dialog.
  135.                 itemNo = item number of outline OK button useritem.
  136. _____________________________________________________________________*/
  137.  
  138.  
  139. static pascal void OutlineOK (WindowPtr dlog, short itemNo)
  140.  
  141. {
  142.     short                    itemType;    /* type of OK button item */
  143.     Handle                itemHandle;    /* handle to OK button item */
  144.     Rect                    itemBox;        /* rectangle enclosing OK button item */    
  145.     
  146.     GetDItem(dlog, 1, &itemType, &itemHandle, &itemBox);
  147.     PenSize(3, 3);
  148.     InsetRect(&itemBox, -4, -4);
  149.     FrameRoundRect(&itemBox, 16, 16);
  150.     PenSize(1, 1);
  151. }
  152.  
  153. /*______________________________________________________________________
  154.  
  155.     VolListFilter - Filter Proc for Volume List Dialog.
  156.     
  157.     Entry:    dlog = pointer to volume list dialog.
  158.                 theEvent = pointer to event record.
  159.                 
  160.     Exit:        itemHit = 3 if hit in volume list rectangle.
  161.                           = 1 if enter or return key pressed or double-click.
  162.                           = 2 if command period or escape pressed.
  163.                 function result = true if hit in volume list rectangle
  164.                     or enter or return key or command period or escape pressed.
  165. _____________________________________________________________________*/
  166.  
  167. static pascal Boolean VolListFilter (WindowPtr dlog, EventRecord *theEvent,
  168.     short *itemHit)
  169.     
  170. {
  171.     short            key;            /* ascii code of key pressed */
  172.     Point            where;        /* location of mouse down */
  173.     short            itemType;    /* type of dialog item */
  174.     Handle        itemHandle;    /* handle to dialog item */
  175.     Rect            itemBox;        /* rectangle enclosing dialog item */    
  176.     ListHandle    volList;        /* volume list */
  177.     Cell            dClickCell;    /* cell double-clicked on */
  178.  
  179.     SetPort(dlog);
  180.     switch (theEvent->what) {
  181.         case mouseDown:
  182.             where = theEvent->where;
  183.             GlobalToLocal(&where);
  184.             GetDItem(dlog, 3, &itemType, &itemHandle, &itemBox);
  185.             if (PtInRect(where, &itemBox)) {
  186.                 volList = (ListHandle)((WindowPeek)dlog)->refCon;
  187.                 if (LClick(where, theEvent->modifiers, volList)) {
  188.                     /* double click - select clicked cell and return 1 */
  189.                     *(long *)&dClickCell = LLastClick(volList);
  190.                     LSetSelect(true, dClickCell, volList);
  191.                     *itemHit = 1;
  192.                     return true;
  193.                 } else {
  194.                     /* single click = return 3 */
  195.                     *itemHit = 3;
  196.                     return true;
  197.                 };
  198.             };
  199.             break;
  200.         case keyDown:
  201.         case autoKey:
  202.             key = theEvent->message & charCodeMask;
  203.             if (key == returnKey || key == enterKey) {
  204.                 *itemHit = 1;
  205.                 utl_FlashButton(dlog, 1);
  206.                 return true;
  207.             };
  208.             if ((key == '.' && theEvent->modifiers & cmdKey) ||
  209.                 (key == escapeKey)) {
  210.                 *itemHit = 2;
  211.                 utl_FlashButton(dlog, 2);
  212.                 return true;
  213.             };
  214.             break;
  215.     };
  216.     return false;
  217. }
  218.  
  219. /*______________________________________________________________________
  220.  
  221.     FolderFilter - Folder Filter Function for Modified Get File Dialog.
  222.     
  223.     Entry:    pBlock = pointer to GetFileInfo param block.
  224.                 
  225.     Exit:        function result = true if file, false if folder.
  226.     
  227.     This function is used by the scan_DoScan function below to process the
  228.     "Folder" menu item in the Scan and Disinfect menus.  It
  229.     filters out all but the folder names in the modified get file
  230.     dialog.
  231. _____________________________________________________________________*/
  232.  
  233.  
  234. static pascal Boolean FolderFilter (ParmBlkPtr pBlock)
  235.  
  236. {
  237.     return (pBlock->fileParam.ioFlAttrib & 0x10) == 0;
  238. }
  239.  
  240.  
  241. /*______________________________________________________________________
  242.  
  243.     Enumerate - Enumerate file.
  244.     
  245.     
  246.     Entry:        pBlock = pointer to PBGetCatInfo param block.
  247.                     folderList = handle to folder list.
  248.                     refCon = report handle.
  249.                     mfs = true if mfs volume.
  250.                     
  251.     Exit:            function result = true if scan should be canceled.
  252. _____________________________________________________________________*/
  253.  
  254.  
  255. static Boolean Enumerate (CInfoPBRec *pBlock, scn_FListElHandle folderList, 
  256.     long refCon, Boolean mfs)
  257.  
  258. {
  259.     Str255            line;                /* report line */
  260.     unsigned char    *p;                /* ptr to current position in report line */
  261.     static char     *fullpath;        /* pointer to full path name */
  262.     
  263.     /* Check to see if the report is full. */
  264.     
  265.     if (scan_CheckFull(Report, 3000)) return true;
  266.     
  267.     /* Bump counters. */
  268.     
  269.     TotFiles++;
  270.     mssg_BumpCounter(0);
  271.     
  272.     /* Put three spaces in the report line for each folder level. */
  273.     
  274.     p = &line[1];
  275.     folderList = (**folderList).next;
  276.     while (folderList=(**folderList).next) {
  277.         *p++ = ' ';
  278.         *p++ = ' ';
  279.         *p++ = ' ';
  280.     };
  281.     
  282.     /* Copy file or folder name to report line */
  283.     
  284.     memcpy(p, pBlock->hFileInfo.ioNamePtr+1, *pBlock->hFileInfo.ioNamePtr);
  285.     p += *pBlock->hFileInfo.ioNamePtr;
  286.     
  287.     /* Append (ƒ) for folders. */
  288.     
  289.     if (((pBlock->hFileInfo.ioFlAttrib >> 4) & 1) == 1) {
  290.         *p++ = ' ';
  291.         *p++ = '(';
  292.         *p++ = 'ƒ';
  293.         *p++ = ')';
  294.  
  295.     };
  296.     
  297.     /* Store report line length. */
  298.     
  299.     *line = p - (&line[1]);
  300.     
  301.     /* Write the line to the report. */
  302.     
  303.     rep_Append(Report, &line, true, true);
  304.     return false;
  305. }
  306.  
  307. /*______________________________________________________________________
  308.  
  309.     scan_DoScan - Process a Scan or Disinfect Operation.
  310.     
  311.     Entry:        scanKind = type of scan (volScan, foldScan, fileScan, 
  312.                         etc.)
  313.                     scanOp = scanning operation (checkOp or disinfectOp).
  314. _____________________________________________________________________*/
  315.  
  316.  
  317. void scan_DoScan (ScanKind scanKind, ScanOp scanOp)
  318.  
  319. {
  320.     unsigned char        saveHilite[numControls];
  321.                                             /* saved control hilite states */
  322.     short                    i;                /* loop index */
  323.     short                    vRefNum;        /* vol ref num of vol containing object
  324.                                                 being scanned */
  325.     long                    dirID;        /* dir id of folder if folder scan */
  326.     char                    *fName;        /* ptr to file name if file scan */
  327.     short                    fVRefNum;    /* wd or vol ref num of folder or vol
  328.                                                 containing file if file scan */
  329.     scn_DoFilePtr        doFile;        /* ptr to do file function for scan */                                                
  330.     Boolean                infected;    /* true if infected file found */
  331.     Boolean                sysInfected;  /* true if infected file found in
  332.                                                   currently active system folder */
  333.     Handle                h;                /* handle to DLOG resource */
  334.     Point                    where;        /* loctn of get file or folder dialog */
  335.     SFReply                reply;        /* reply from gff_Get */
  336.     Boolean                wait;            /* true to wait for disk insertion */
  337.     short                    volInx;        /* index in VCB queue */
  338.     HParamBlockRec        vBlock;        /* vol info param block */
  339.     ParamBlockRec        fBlock;        /* file info param block */
  340.     DrvQEl                *curDrive;    /* ptr to drive queue element */
  341.     unsigned char        flagByte;    /* drive queue el flag byte */
  342.     short                    driveNum;    /* drive number */
  343.     Boolean                firstDisk;    /* true if asking for first disk */
  344.     OSErr                    rCode;        /* result code */
  345.     WDPBRec                wdBlock;        /* working directory info param block */
  346.     FCBPBRec                fcbBlock;    /* FCB info param block */
  347.     char                    sysFileName[32];    /* system file name */
  348.     DialogPtr            dlog;            /* pointer to vol list dialog */
  349.     Rect                    dlogRect;    /* dialog rectangle */
  350.     short                    itemHit;        /* item number hit in vol list dialog */
  351.     short                    itemType;    /* type of dialog item */
  352.     Handle                itemHandle;    /* handle to dialog item */
  353.     Rect                    itemBox;        /* rectangle enclosing dialog item */
  354.     ListHandle            volList;        /* volume list */
  355.     Rect                    rView;        /* rectangle enclosing volume list */
  356.     Rect                    dataBounds;    /* vol list dimensions */
  357.     Point                    volPt;        /* vol list cell */
  358.     char                    volName[30];    /* vol name */
  359.     Handle                vrn;            /* handle to list of vRefNums */
  360.     short                    vrnSize;        /* size of list of vRefNums */
  361.     short                    vrnInx;        /* cur index in list of vRefNums */
  362.     short                    lastVrn;        /* index in list of vRefNums following last
  363.                                                 entry */
  364.     GrafPtr                thePort;        /* saved grafport */
  365.     short                    strInx;        /* index of STR# resource string */
  366.     char                    scanOpWord[20];    /* "scanned" or "disinfected" */
  367.     Str255                prompt1;        /* unplugged prompt string for get
  368.                                                 file/folder dialog */
  369.     Str255                prompt2;        /* plugged prompt string for get 
  370.                                                 file/folder dialog */
  371.     
  372.     static char            *desktopName = "\pDesktop";        /* Finder Desktop file name */
  373.     
  374.     /* Remember the scan kind in a global variable, and initialize 
  375.         Canceled to false. */
  376.     
  377.     CurScanKind = scanKind;
  378.     Canceled = false;
  379.     
  380.     /* Get currently selected volume. */
  381.  
  382.     (void) vol_GetSel(&vRefNum);
  383.     
  384.     /* Get pointer to do file function. */
  385.     
  386.     switch (scanOp) {
  387.         case checkOp:
  388.             doFile = Enumerate;
  389.             break;
  390.     };
  391.     
  392.     /* Initialize depending on type of scan.  Present open file, open folder,
  393.         or open file/folder dialog if necessary.  Get the following info:
  394.         
  395.         vRefNum = vol ref num of vol containing object to be scanned.
  396.         dirID = dir id of folder if folder scan.
  397.         fName = pointer to file name if file scan.
  398.         fVRefNum = vol or wd ref num of vol or folder containing file
  399.             if file scan. */
  400.         
  401.     dirID = 0;
  402.     fName = "\p";
  403.     fVRefNum = 0;
  404.     wait = false;
  405.     
  406.     if (scanKind == fileScan || scanKind == foldScan || 
  407.         scanKind == fileFoldScan || scanKind == volSetScan) {
  408.         switch (scanOp) {
  409.             case checkOp:
  410.                 strInx = scannedWord;
  411.                 break;
  412.         };
  413.         GetIndString((StringPtr)scanOpWord, strListID, strInx);
  414.     };
  415.     
  416.     switch (scanKind) {
  417.     
  418.         case allScan:
  419.         
  420.             volInx = 0;
  421.             break;
  422.             
  423.         case volScan:
  424.         
  425.             break;
  426.             
  427.         case fileScan:
  428.         case foldScan:
  429.         case fileFoldScan:
  430.         
  431.             /* Set standard file dialog default vol to currently selected vol. */
  432.             
  433.             if (-vRefNum != SFSaveDisk) {
  434.                 SFSaveDisk = -vRefNum;
  435.                 if (!OldRom) CurDirStore = fsRtDirID;
  436.             };
  437.             
  438.             /* Load the proper get file dialog and center it. */
  439.             
  440.             h = GetResource('DLOG', 
  441.                 (scanKind == fileScan) ? getFileID : getFFID);
  442.             HNoPurge(h);
  443.             utl_CenterDlogRect(*(Rect**)h, MenuPick);
  444.             where = **(Point**)h;
  445.             
  446.             /* Present the dialog. */
  447.             
  448.             switch (scanKind) {
  449.                 case fileScan:
  450.                     strInx = getFilePrompt;
  451.                     break;
  452.                 case foldScan:
  453.                     strInx = getFoldPrompt;
  454.                     break;
  455.                 case fileFoldScan:
  456.                     strInx = getFFPrompt;
  457.                     break;
  458.             };
  459.             GetIndString(prompt1, strListID, strInx);
  460.             utl_PlugParams(&prompt1, &prompt2, (Str255 *)scanOpWord, nil, nil, nil);
  461.             switch (scanKind) {
  462.                 case fileScan:
  463.                     SFPGetFile(where, prompt2, nil, -1, nil, nil, &reply,
  464.                         getFileID, nil);
  465.                     break;
  466.                 case foldScan:
  467.                     gff_Get(&where, &prompt2, (FilterProc)FolderFilter, -1, nil, &reply, getFFID);
  468.                     break;
  469.                 case fileFoldScan:
  470.                     gff_Get(&where, &prompt2, nil, -1, nil, &reply, getFFID);
  471.                     break;
  472.             };
  473.             misc_Update();
  474.             
  475.             /* Clean up and get out if the user clicked on the cancel button. */
  476.             
  477.             HPurge(h);
  478.             if (!reply.good) return;
  479.             
  480.             /* Set CurScanKind = kind of scan (file or folder), and
  481.                 set other variables. */
  482.                 
  483.             switch (scanKind) {
  484.                 case fileScan:
  485.                     /* call GetWDInfo to get vRefNum = ref num of vol containing 
  486.                         file */
  487.                     wdBlock.ioNamePtr = nil;
  488.                     wdBlock.ioVRefNum = reply.vRefNum;
  489.                     wdBlock.ioWDIndex = 0;
  490.                     wdBlock.ioWDProcID = 0;
  491.                     PBGetWDInfo(&wdBlock, false);
  492.                     vRefNum = wdBlock.ioWDVRefNum;
  493.                     fName = (char *)reply.fName;
  494.                     fVRefNum = reply.vRefNum;
  495.                     break;
  496.                 case foldScan:
  497.                     if (reply.fType == fsRtDirID) CurScanKind = volScan;
  498.                     vRefNum = reply.vRefNum;
  499.                     break;
  500.                 case fileFoldScan:
  501.                     CurScanKind = *reply.fName ? fileScan : foldScan;
  502.                     if (CurScanKind == fileScan) {
  503.                         vRefNum = reply.version;
  504.                         fName = (char *)reply.fName;
  505.                         fVRefNum = reply.vRefNum;
  506.                     } else {
  507.                         if (reply.fType == fsRtDirID) CurScanKind = volScan;
  508.                         vRefNum = reply.vRefNum;
  509.                     };
  510.             };
  511.             if (CurScanKind == foldScan) dirID = reply.fType;
  512.             break;
  513.             
  514.         case autoScan:
  515.         
  516.             /* Check drives 1 and 2 (internal and external floppy drives).
  517.                 Eject them if they are not empty.  See IM IV-181.
  518.                 
  519.                 Set wait=true and firstDisk=true to wait for insertion
  520.                 of first disk. */
  521.                 
  522.             firstDisk = wait = true;
  523.             curDrive = (DrvQEl*)(GetDrvQHdr())->qHead;
  524.             while (curDrive) {
  525.                 driveNum = curDrive->dQDrive;
  526.                 if (driveNum == 1 || driveNum == 2) {
  527.                     flagByte = *((Ptr)curDrive-3);
  528.                     if (flagByte && flagByte < 0xfc) {
  529.                         misc_CheckEject(driveNum);
  530.                         Eject(nil, driveNum);
  531.                     };
  532.                 };
  533.                 curDrive = (DrvQEl*)curDrive->qLink;
  534.             };
  535.             break;
  536.             
  537.         case sysFileScan:
  538.         
  539.             CurScanKind = fileScan;
  540.             vRefNum = SysVol;
  541.             fVRefNum = utl_GetSysWD();
  542.             fcbBlock.ioVRefNum = 0;
  543.             fcbBlock.ioFCBIndx = 0;
  544.             fcbBlock.ioRefNum = SysRefNum;
  545.             fcbBlock.ioNamePtr = (StringPtr)sysFileName;
  546.             PBGetFCBInfo(&fcbBlock, false);
  547.             fName = sysFileName;
  548.             break;
  549.             
  550.         case sysFoldScan:
  551.         
  552.             vRefNum = SysVol;
  553.             if (utl_VolIsMFS(vRefNum) || SysDirID == fsRtDirID) {
  554.                 CurScanKind = volScan;
  555.             } else {
  556.                 CurScanKind = foldScan;
  557.                 dirID = SysDirID;
  558.             };
  559.             break;
  560.             
  561.         case volSetScan:
  562.         
  563.             /* Initialize the dialog. */
  564.             
  565.             GetPort(&thePort);
  566.             dlog = GetNewDialog(volListID, nil, (WindowPtr)-1);
  567.             dlogRect = dlog->portRect;
  568.             utl_CenterDlogRect(&dlogRect, MenuPick);
  569.             MoveWindow(dlog, dlogRect.left, dlogRect.top, false);
  570.             GetDItem(dlog, 3, &itemType, &itemHandle, &rView);
  571.             SetDItem(dlog, 3, itemType, (Handle)DrawVolList, &rView);
  572.             GetDItem(dlog, 4, &itemType, &itemHandle, &itemBox);
  573.             SetDItem(dlog, 4, itemType, (Handle)OutlineOK, &itemBox);
  574.             GetDItem(dlog, 5, &itemType, &itemHandle, &itemBox);
  575.             GetIText(itemHandle, prompt1);
  576.             utl_PlugParams(&prompt1, &prompt2, (Str255 *)scanOpWord, nil, nil, nil);
  577.             SetIText(itemHandle, prompt2);
  578.             
  579.             /* Initialize an empty volume list. */
  580.             
  581.             InsetRect(&rView, 1, 1);
  582.             rView.right -= 15;
  583.             SetRect(&dataBounds, 0, 0, 1, 0);
  584.             SetPt(&volPt, 0, 0);
  585.             volList = LNew (&rView, &dataBounds, volPt, 0, dlog, 
  586.                 false, false, false, true);
  587.             (**volList).selFlags = lNoExtend | lUseSense;
  588.             ((WindowPeek)dlog)->refCon = (long)volList;
  589.             
  590.             /* Fill the volume list with the names of all the online volumes.
  591.                 Also record their vRefNums in the vrn array. */
  592.                 
  593.             vrn = NewHandle(20);
  594.             vrnSize = 20;
  595.             vrnInx = 0;
  596.             volInx = 0;
  597.             vBlock.volumeParam.ioNamePtr = (StringPtr)volName;
  598.             while (true) {
  599.                 vBlock.volumeParam.ioVolIndex = ++volInx;
  600.                 vBlock.volumeParam.ioVRefNum = 0;
  601.                 if (PBHGetVInfo(&vBlock, false)) break;
  602.                 if (vBlock.volumeParam.ioVDrvInfo) {
  603.                     LAddRow(1, volPt.v, volList);
  604.                     LSetCell(volName+1, *volName, volPt, volList);
  605.                     volPt.v++;
  606.                     if (vrnInx >= vrnSize) {
  607.                         vrnSize += 20;
  608.                         SetHandleSize(vrn, vrnSize);
  609.                     };
  610.                     *(short*)(*vrn + vrnInx) = vBlock.volumeParam.ioVRefNum;
  611.                     vrnInx += 2;
  612.                 };
  613.             };
  614.             
  615.             /* Show the window and process events. */
  616.             
  617.             LDoDraw(true, volList);
  618.             ShowWindow((WindowPtr)dlog);
  619.             do {
  620.                 ModalDialog((FilterProc)VolListFilter, &itemHit);
  621.             } while (itemHit != OK && itemHit != Cancel);
  622.             
  623.             /* Collapse the list of vRefNums to just those that have
  624.                 been selected by the user. */
  625.             
  626.             vrnInx = 0;
  627.             volPt.v = 0;
  628.             while (LGetSelect(true, &volPt, volList)) {
  629.                 *(short*)(*vrn + vrnInx) = *(short*)(*vrn + (volPt.v<<1));
  630.                 vrnInx += 2;
  631.                 volPt.v++;
  632.             };
  633.             lastVrn = vrnInx;
  634.             vrnInx = 0;
  635.             
  636.             /* Dispose of the volume list and the dialog, leaving just the
  637.                 vRefNum list. */
  638.             
  639.             LDispose(volList);
  640.             DisposDialog(dlog);
  641.             SetPort(thePort);
  642.             misc_Update();
  643.             
  644.             /* If the cancel button was pressed, or if there are no selected
  645.                 volumes in the list, dispose of the vRefNum list and return. */
  646.                 
  647.             if (itemHit == Cancel || !lastVrn) {
  648.                 DisposHandle(vrn);
  649.                 return;
  650.             };
  651.             break;
  652.             
  653.         case desktopScan:
  654.         
  655.             volInx = 0;
  656.             CurScanKind = fileScan;
  657.             break;
  658.             
  659.     };
  660.     
  661.     HiliteMenu(0);
  662.     
  663.     /* Set selected volume and process resulting update event. */
  664.     
  665.     vol_SetSel(vRefNum, true);
  666.     misc_Update();    
  667.     Scanning = true;
  668.  
  669.     /* Save old hilite states for all buttons.  Unhilite all buttons
  670.         except for Cancel and Quit.  Also unhilite the report scroll bar. */
  671.  
  672.     for (i=0; i<numControls; i++) {
  673.         saveHilite[i] = (**Controls[i]).contrlHilite;
  674.         if (i+firstControl == cancelID || i+firstControl == quitID) {
  675.             HiliteControl(Controls[i], 0);
  676.         } else {
  677.             HiliteControl(Controls[i], 255);
  678.         };
  679.     };
  680.     main_SetPort();
  681.     rep_Activate(Report, false);
  682.                 
  683.     /* Main loop - do one volume at a time. */
  684.     
  685.     while (true) {
  686.     
  687.         /* If wait=true wait for the user to insert the next floppy. */
  688.         
  689.         if (wait) {
  690.             main_WaitInsert(firstDisk, &vRefNum, &Canceled);
  691.             firstDisk = false;
  692.             if (Canceled) {
  693.                 vol_Verify();
  694.                 break;
  695.             };
  696.             vol_SetSel(vRefNum, false);
  697.             misc_Update();
  698.         };
  699.         
  700.         /* If allScan advance to next volume.  If desktopScan advance to
  701.             next volume which contains a desktop file. */
  702.         
  703.         if (scanKind == allScan || scanKind == desktopScan) {
  704.             vBlock.volumeParam.ioNamePtr = nil;
  705.             while (true) {
  706.                 vBlock.volumeParam.ioVolIndex = ++volInx;
  707.                 vBlock.volumeParam.ioVRefNum = 0;
  708.                 if (rCode = PBHGetVInfo(&vBlock, false)) break;
  709.                 if (!vBlock.volumeParam.ioVDrvInfo) continue;
  710.                 if (scanKind == allScan) break;
  711.                 /* check to see if Desktop file exists. */
  712.                 fBlock.fileParam.ioNamePtr = (StringPtr)desktopName;
  713.                 fBlock.fileParam.ioVRefNum = vBlock.volumeParam.ioVRefNum;
  714.                 fBlock.fileParam.ioFVersNum = 0;
  715.                 fBlock.fileParam.ioFDirIndex = 0;
  716.                 if (PBGetFInfo(&fBlock, false)) continue;
  717.                 fName = desktopName;
  718.                 fVRefNum = vBlock.volumeParam.ioVRefNum;
  719.                 break;
  720.             };
  721.             if (rCode) break;
  722.             vRefNum = vBlock.volumeParam.ioVRefNum;
  723.             vol_SetSel(vRefNum, false);
  724.             misc_Update();
  725.         };
  726.         
  727.         /* If volSetScan advance to next selected volume. */
  728.         
  729.         if (scanKind == volSetScan) {
  730.             if (vrnInx >= lastVrn) break;
  731.             vRefNum = *(short*)(*vrn + vrnInx);
  732.             vrnInx += 2;
  733.             vol_SetSel(vRefNum, false);
  734.             misc_Update();
  735.         };
  736.         
  737.         /* Check for report full. */
  738.         
  739.         if (scan_CheckFull(Report, 6000)) break; 
  740.             
  741.         /* Output report header. */
  742.         
  743.         mssg_Begin(false, dirID, 
  744.             (Str255 *)fName, fVRefNum, vRefNum, RectList[counterRect].top,
  745.             RectList[counterRect].right);
  746.             
  747.         /* Find out if volume is local (for Zig). */
  748.         
  749.         vBlock.volumeParam.ioNamePtr = nil;
  750.         vBlock.volumeParam.ioVRefNum = vRefNum;
  751.         vBlock.volumeParam.ioVolIndex = 0;
  752.         PBHGetVInfo(&vBlock, false);
  753.         VolIsLocal = vBlock.volumeParam.ioVFSID == 0;
  754.         
  755.         /* Scan the volume. */
  756.         
  757.         Canceled = scn_Vol(vRefNum, dirID, (Str255 *)fName, fVRefNum, doFile,
  758.             (long)Report, scan_CheckCancel, &RectList[foldNameRect], 
  759.             &RectList[fileNameRect], &RectList[thermRect], systemFont, 0); 
  760.         
  761.         /* Redraw the thermometer frame. */
  762.         
  763.         FrameRect(&RectList[thermRect]);
  764.         
  765.         /* Output report summary. */
  766.         
  767.         mssg_End(false, Canceled, &infected, &sysInfected);
  768.         
  769.         /* Break out of loop if not allScan or autoScan or volSetScan or desktopScan, 
  770.             or if canceled. */
  771.         
  772.         if (scanKind != allScan && scanKind != autoScan && 
  773.             scanKind != volSetScan && scanKind != desktopScan) break;
  774.         if (Canceled) break;
  775.         
  776.         /* If autoscan, eject floppy.  Also unmount it if it's not the
  777.             current system volume or the volume containing the current 
  778.             application.  Set wait=true to wait for the user to insert the
  779.             next floppy. */
  780.             
  781.         if (scanKind == autoScan) {
  782.             misc_CheckEject(vRefNum);
  783.             Eject(nil, vRefNum);
  784.             if (vRefNum != utl_GetSysVol() && vRefNum != utl_GetApplVol()) 
  785.                 UnmountVol(nil, vRefNum);
  786.             wait = true;
  787.         };
  788.     
  789.     };
  790.     
  791.     Scanning = false;
  792.     
  793.     /* Restore saved hilite states. 
  794.         Disable the Disinfect button if requested by vrep_Repair.
  795.         Also hilite the scroll bar. */
  796.     
  797.     for (i=0; i<numControls; i++) {
  798.         HiliteControl(Controls[i], saveHilite[i]);
  799.     };
  800.     rep_Activate(Report, true);
  801.     
  802.     /* Verify the current volume. */
  803.     
  804.     vol_Verify();
  805.     
  806.     /* If volSetScan, dispose of vRefNum list. */
  807.  
  808.     if (scanKind == volSetScan) {
  809.         DisposHandle(vrn);
  810.     };
  811.     misc_SetCursor();
  812. }
  813.  
  814. /*______________________________________________________________________
  815.  
  816.     scan_DoButton - Process a Mouse Down on One of the Two Scanning Buttons
  817.     
  818.     Entry:        scanOp = scanning operation (checkOp or disinfectOp).
  819.                     modifiers = command key modifiers.
  820. _____________________________________________________________________*/
  821.  
  822.  
  823. void scan_DoButton (ScanOp scanOp, short modifiers)
  824.  
  825. {
  826.     Boolean                optionDown;    /* true if option key held down */
  827.     Boolean                cmdDown;        /* true if command key held down */
  828.     short                    scanKind;    /* kind of scan */
  829.  
  830.     /* Check for modifier keys. */
  831.     
  832.     optionDown = (modifiers & optionKey) != 0;
  833.     cmdDown = (modifiers & cmdKey) != 0;
  834.     
  835.     /* Determine kind of scan. */
  836.     
  837.     if (optionDown) {
  838.         if (cmdDown) {
  839.             scanKind = allScan;                /* option and command */
  840.         } else {
  841.             scanKind = fileFoldScan;        /* option */
  842.         };
  843.     } else {
  844.         if (cmdDown) {
  845.             scanKind = autoScan;                /* command */
  846.         } else {
  847.             scanKind = volScan;                /* no modifer keys */
  848.         };
  849.     };
  850.     
  851.     /* Call scan_DoScan to do the scan. */
  852.     
  853.     scan_DoScan(scanKind, scanOp);
  854. }
  855.