home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / pcmagazi / 1992 / 04 / finddupe.cpp < prev    next >
C/C++ Source or Header  |  1992-02-05  |  7KB  |  255 lines

  1. // finddupe.cpp
  2.  
  3. #include<malloc.h>
  4. #include<dir.h>
  5. #include"sort.h"
  6. #include"msgbox.h"
  7. #include"finddupe.h"
  8. #include"makepath.h"
  9.  
  10. FindDupe::FindDupe(Window *S, Window *P)
  11.     {
  12.     Path = P;
  13.     Status = S;
  14.     numFound = 0;
  15.     }
  16.  
  17. int _Cdecl compare(const void far *e1, const void far *e2)
  18.     {
  19.     return _fstrcmp((*(char far * far*)e1),(*(char far * far*)e2));
  20.     }
  21.  
  22. void FindDupe::PostResults(char *dspec, struct ffblk *f)
  23.     {
  24.     if(PutDirectoryToTemp(dspec))
  25.         DispPath(dspec);
  26.  
  27.     PutIndexToTemp(f->ff_name);
  28.  
  29.     PutDataToTemp(&f->ff_ftime);
  30.     Status->Puts(f->ff_name);
  31.     numFound++;
  32.     }
  33.  
  34.  
  35. void FindDupe::DispPath(char *path)
  36.     {
  37.     char formatbuffer[80];
  38.  
  39.     SetWords((void far *)formatbuffer,0,WordSize(formatbuffer));
  40.     Path->Clear();
  41.     sprintf(formatbuffer,path);
  42.     Path->AtSay(0,0,strupr(formatbuffer));
  43.     }
  44.  
  45.  
  46. BOOL FindDupe::FindDuplicates(char *searchdirs)
  47.     {
  48.     TempIndex.Open("wb");
  49.     TempData.Open("wb");
  50.  
  51.     int i;
  52.     BOOL term;
  53.     SetEatKey();
  54.     strcpy(filespec,"*.*");
  55.  
  56.     char oldtitle[40];
  57.     Status->GetTitle(oldtitle);
  58.  
  59.     Status->SetTitle("Scanning...");
  60.  
  61.     if(GetArgCount() > 0)
  62.         for(i = 0; i < GetArgCount(); i++)
  63.             {
  64. //            strcpy(dirspec,GetArg(i));
  65.             makepath(dirspec,GetArg(i));
  66.             if(!(isalpha(*dirspec)))
  67.                 continue;
  68.             if(dirspec[1] != ':' && dirspec[2] != '\\')
  69.                 continue;
  70.             strcpy(dirspec,dirspec);
  71.  
  72.             Path->SetTitle(dirspec);
  73.  
  74.             if(term = Run(dirspec,filespec))
  75.                 break;
  76.             }
  77.     else
  78.         {
  79.         char *q = searchdirs;
  80.         while(*q)
  81.             {
  82.             char *p = strchr(q,' ');
  83.             if(p)
  84.                 {
  85.                 *p = '\0';
  86.                 p++;
  87.                 }
  88.             strcpy(dirspec,q);
  89.             if(!(isalpha(*dirspec)))
  90.                 continue;
  91.             if(dirspec[1] != ':' && dirspec[2] != '\\')
  92.                 continue;
  93.             strcpy(dirspec,dirspec);
  94.  
  95.             Path->SetTitle(dirspec);
  96.  
  97.             if(term = Run(dirspec,filespec))
  98.                 break;
  99.             q = p;
  100.             }
  101.         }
  102.  
  103.     Status->SetTitle(oldtitle);
  104.     TempIndex.Close();
  105.     TempData.Close();
  106.  
  107.     if(term || !numFound)
  108.         {
  109.         TempIndex.Delete();
  110.         TempData.Delete();
  111.         return terminate(numFound ? "Terminated by user." : "None found");
  112.         }
  113.  
  114.     Status->Puts("Scanning complete...");
  115.     TempIndex.Open("rb");
  116.     long indexsize = TempIndex.Size();
  117.     char huge *farbuffer = (char huge *)farmalloc(indexsize);
  118.  
  119.     if(!farbuffer)
  120.         {
  121.         TempIndex.Delete();
  122.         TempData.Delete();
  123.         return terminate("Can\'t allocate far buffer");
  124.         }
  125.  
  126.     int bytesread;
  127.     long offset = 0L;
  128.  
  129.     const BUFFERSIZE = 5000;
  130.     char *nearbuffer = new char[BUFFERSIZE];
  131.     Status->Puts("Loading temp files...");
  132.     while(bytesread = TempIndex._fRead(BUFFERSIZE,&farbuffer[offset],nearbuffer))
  133.         offset += bytesread;
  134.     delete nearbuffer;
  135.     if(offset != indexsize)
  136.         {
  137.         TempIndex.Delete();
  138.         TempData.Delete();
  139.         return terminate("Temp file not read");
  140.         }
  141.  
  142.     unsigned maxrecords = (unsigned)(indexsize/sizeof(OUTBUF));
  143.     unsigned currec;
  144.  
  145.     char far * far *entrytable = (char far * far *)farmalloc((maxrecords*sizeof(char far * far *)));
  146.     if(!entrytable)
  147.         {
  148.         TempIndex.Delete();
  149.         TempData.Delete();
  150.         return terminate("Can\'t allocate pointer table");
  151.         }
  152.  
  153.     Status->Puts("Preparing for sorting...");
  154.  
  155.     for( offset = 0L, currec = 0; currec < maxrecords; currec++, offset += sizeof(OUTBUF))
  156.         entrytable[currec] = (char far *)(&farbuffer[offset]);
  157.     entrytable[maxrecords] = "";
  158. #ifdef TESTING
  159.     Status->Puts("\n");
  160.     for(int i = 0; i < 10; i++)
  161.         Status->Printf("table[%02d]=%Fp %Fs\n",i,entrytable[i],entrytable[i]);
  162. #endif
  163.     Status->Puts("Sorting records...");
  164.     Sort qs;
  165.     qs.QuickSort(entrytable,maxrecords,sizeof(char far * far *),compare);
  166.     Status->Puts("complete.");
  167.  
  168. #ifdef TESTING
  169.     Status->Puts("\n");
  170.     for(int i = 0; i < 10; i++)
  171.         Status->Printf("table[%02d]=%Fp %Fs\n",i,entrytable[i],entrytable[i]);
  172. #endif
  173.     TempIndex.Close();              // close old index file
  174.  
  175.     Status->Puts("Sifting duplicates...");
  176.  
  177.     int WasMatch = FALSE;
  178.     numFound = 0;
  179.     for(currec = 0; currec < maxrecords; currec++)
  180.         {
  181.             // if current entry matches the next one, WasMatch = TRUE
  182.         if(!_fstrcmp(entrytable[currec],entrytable[currec+1]))
  183.             {
  184.             WasMatch = TRUE;
  185.             numFound++;
  186.             }
  187.         else    // else they didn't match...
  188.             {
  189.             if(!WasMatch)   // and the previous one didn't match -- OUT!
  190.                 *entrytable[currec] = '\0';
  191.             else            // or if the previous one DID match
  192.                 WasMatch = FALSE;               // set for no match on next
  193.             }
  194.         }
  195.  
  196.     if(!numFound)
  197.         {
  198.         TempIndex.Delete();
  199.         TempData.Delete();
  200.         return FALSE;
  201.         }
  202.  
  203.     IndexFile.Open("wb");           // create new index file
  204.     DataFile.Open("wb");            // create the new data file
  205.     TempData.Open("rb");            // open old one for reading
  206.  
  207.     OUTBUF far *entry = (OUTBUF far *)entrytable[0];
  208.  
  209.     Status->Printf("Writing %s...",DataFile.GetName());
  210.         // write out a data file record for each valid index record
  211.     for(offset = 0L, currec = 0; currec < maxrecords; currec++, offset += sizeof(OUTBUF))
  212.         {
  213.         entry = (OUTBUF far *)&farbuffer[offset];
  214.  
  215.         if(*(entry->buf))
  216.             {
  217.             GetData(&TempData,entry->offset);
  218.             PutDirectoryToData(!currec ? TRUE : FALSE);
  219.             entry->offset = DataFile.CurPosition();
  220.             PutDataFile();
  221.             }
  222.         }
  223.     Status->Printf("and %s...",IndexFile.GetName());
  224.  
  225.         // write remaining valid entries (the duplicates) to the index file
  226.     char nearbuffer2[sizeof(OUTBUF)];
  227.     for(currec = 0; currec < maxrecords; currec++)
  228.         if(*entrytable[currec])
  229.             IndexFile._fWrite(sizeof(OUTBUF),entrytable[currec],nearbuffer2);
  230.  
  231.     farfree(entrytable);
  232.     farfree(farbuffer);
  233.     DataFile.Close();
  234.     IndexFile.Close();
  235.     Status->Puts("Deleting temp files...");
  236.  
  237.     TempIndex.Delete();
  238.     TempData.Delete();
  239.     Status->Puts("Done!");
  240.     return TRUE;
  241.     }
  242.  
  243. //#define MAIN
  244. #if defined(MAIN)
  245. void main(void)
  246.     {
  247.     FindDupe myApp;    // check arguments, setup movedir
  248.  
  249.     myApp.FindDuplicates();
  250.     }
  251. #endif
  252.  
  253.  
  254.  
  255.