home *** CD-ROM | disk | FTP | other *** search
/ BMUG PD-ROM A / PD-ROM A.iso / Utility / Virus Checkers / Disinfectant 2.5.1 / Source Code for 2.4 / Source Code / scan.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-03  |  23.4 KB  |  856 lines  |  [TEXT/MPS ]

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