home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Add-Ons / BBEdit / du 1.0.0 / du.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-16  |  4.8 KB  |  212 lines  |  [TEXT/KAHL]

  1. #include <SetupA4.h>
  2. #include <ExternalInterface.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5.  
  6. #define kMinStackSpace        6000        /* Give up if less than this much stack left */
  7.  
  8. static ExternalCallbackBlock    *cb;
  9.  
  10. static char            buf[256];
  11. static long            lastLine;
  12. static long            blockSize;
  13. static short        doneSoFar;
  14.  
  15. pascal void main(ExternalCallbackBlock *callbacks, WindowPtr w);
  16.  
  17.  
  18. /*
  19.  * Recursive routine to insert the size (in blocks) and name of a directory
  20.  * at the current text location.  Indentation is determined by the recursion
  21.  * level, "level".  Returns a negative number if error (out of stack or
  22.  * user canceled).
  23.  */
  24. static long InsertFolderSize( short vRefNum, long dirID, Str63 dirName,
  25.  short level )
  26. {
  27.     long            thisSize, increment;
  28.     CInfoPBRec        cipbr;                            /* local pb */
  29.     HFileInfo        *fpb = (HFileInfo *)&cipbr;
  30.     DirInfo            *dpb = (DirInfo *) &cipbr;
  31.     short            idx;
  32.     Str255            filename;
  33.     short            err, i;
  34.     long            thisLine;
  35.     long            selStart, selEnd, firstChar;
  36.     Boolean            hasSubDirs = false;
  37.     
  38.     fpb->ioVRefNum = vRefNum;
  39.     fpb->ioNamePtr = filename;
  40.     
  41.     thisSize = 0;
  42.     
  43.     /*
  44.      * Insert directory name at the beginning of current line.
  45.      * (We'll add indentation later.)  Then save current line number
  46.      * and insert a carriage return.
  47.      */
  48.     cb->GetSelection( &selStart, &selEnd, &firstChar );
  49.     thisLine = cb->GetLineNumber( selStart );
  50.     sprintf( &buf[0], "%#s\r", dirName );
  51.     cb->Insert( buf, strlen(buf) );
  52.     
  53.     if( (thisLine+1) > lastLine )
  54.         lastLine = thisLine+1;
  55.     
  56.     /*
  57.      * Index through all files and folders in the directory.
  58.      */
  59.     for( idx=1; TRUE; idx++)
  60.     {
  61.         if( 0 == level )
  62.         {
  63.             doneSoFar = idx * 1000;
  64.         }
  65.         if( cb->DoProgress( doneSoFar ) )        /* Allow abort */
  66.         {
  67.             thisSize = -1;
  68.             break;
  69.         }
  70.         
  71.         fpb->ioDirID = dirID;                    /* must set on each loop */
  72.         fpb->ioFDirIndex = idx;
  73.  
  74.         if( PBGetCatInfo( &cipbr, FALSE ) )
  75.             break;                                /* exit when no more entries */
  76.  
  77.         if (fpb->ioFlAttrib & 16)                /* If it's a folder... */
  78.         {
  79.             /*
  80.              * This entry is a folder.  Check stack space, and if that's okay, recurse.
  81.              */
  82.             hasSubDirs = true;
  83.             if( StackSpace() < kMinStackSpace )
  84.             {
  85.                 cb->Insert( "Out of memory!\r", 15 );
  86.                 thisSize = -1;
  87.                 break;
  88.             }
  89.             increment = InsertFolderSize( vRefNum, dpb->ioDrDirID, filename, level+1 );
  90.             if( increment >= 0 )
  91.             {
  92.                 thisSize += increment;
  93.             }
  94.             else        /* error -- bubble back to top level without doing more work */
  95.             {
  96.                 thisSize = increment;
  97.                 break;
  98.             }
  99.         }
  100.         else
  101.         {
  102.             /*
  103.              * This entry is a file.  Add its resource and data fork physical
  104.              * lengths to the size of the parent folder.
  105.              */
  106.             thisSize += fpb->ioFlPyLen + fpb->ioFlRPyLen;
  107.         }
  108.     }
  109.     
  110.     if( thisSize >= 0 )
  111.     {
  112.         /*
  113.          * Got the size of the parent folder.  Insert indentation spaces and
  114.          * the size, in blocks.
  115.          */
  116.         cb->SetSelection( selStart, selStart, -1 );
  117.         for( i=0; i<(level*2); i++ )
  118.             buf[i] = ' ';
  119.         
  120.         sprintf( &buf[i], "%6ld     ", thisSize/blockSize );
  121.         cb->Insert( buf, strlen(buf) );
  122.         if( hasSubDirs )
  123.         {
  124.             /*
  125.              * If we had to recurse while doing this directory,
  126.              * we need to set the insertion point at the end of the last
  127.              * line we've written, so the next directory at this level
  128.              * will go there.
  129.              */
  130.             selStart = (cb->GetLineEnd( cb->GetLinePos( lastLine ) ) );
  131.             cb->SetSelection( selStart, selStart, -1 );
  132.         }
  133.         else
  134.         {
  135.             selStart = (cb->GetLineStart( cb->GetLinePos( thisLine + 1) ) );
  136.             cb->SetSelection( selStart, selStart, -1 );
  137.         }
  138.     }
  139.     
  140.     return thisSize;
  141. }
  142.  
  143.  
  144. pascal void main(ExternalCallbackBlock *callbacks, WindowPtr w)
  145. {
  146.     short        vRefNum;
  147.     long        dirID;
  148.     ParamBlockRec    vpb;
  149.     CInfoPBRec    cipbr;
  150.     HFileInfo    *fpb;
  151.     DirInfo        *dpb;
  152.     Str255        filename;
  153.     short        i;
  154.     short        iErr;
  155.     
  156.     RememberA0();
  157.     SetUpA4();
  158.     
  159.     fpb = (HFileInfo *)&cipbr;        /* Don't initialize at declaration            */
  160.     dpb = (DirInfo *) &cipbr;        /* (or RememberA0 will remember &cipbr!)    */
  161.     
  162.     cb = callbacks;
  163.     lastLine = 0;
  164.     
  165.     if( callbacks->version >= 3 )
  166.     {
  167.         if( callbacks->GetFolder( "\pPlease find the starting folder.", &vRefNum, &dirID ) )
  168.         {
  169.             w = callbacks->NewDocument();
  170.             if (w)
  171.             {
  172.                 /*
  173.                  * Got a folder and new window.
  174.                  * Find the volume blocksize.
  175.                  */
  176.                 vpb.volumeParam.ioVolIndex = 0;
  177.                 vpb.volumeParam.ioVRefNum = vRefNum;
  178.                 iErr = PBGetVInfo( &vpb, FALSE );
  179.                 if( !iErr )
  180.                 {
  181.                     blockSize = vpb.volumeParam.ioVAlBlkSiz;
  182.                     
  183.                     /*
  184.                      * Get info about top directory, so we can pass its name.
  185.                      */
  186.                     fpb->ioVRefNum = vRefNum;
  187.                     fpb->ioNamePtr = filename;
  188.                     fpb->ioDirID = dirID;
  189.                     fpb->ioFDirIndex = -1;            /* Just get info about the directory */
  190.                     iErr = PBGetCatInfo( &cipbr, FALSE );
  191.                 }
  192.                 if( !iErr )
  193.                 {
  194.                     /*
  195.                      * Here we go.  Call the recursive routine.
  196.                      */
  197.                     cb->StartProgress( "\pdu progress", dpb->ioDrNmFls * 1000L, TRUE );
  198.                     doneSoFar = 0;
  199.                     InsertFolderSize( vRefNum, dirID, filename, 0 );
  200.                     cb->DoneProgress();
  201.                 }
  202.             }
  203.         }
  204.     }
  205.     
  206.     RestoreA4();
  207. }
  208.  
  209.  
  210.  
  211.  
  212.