home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / utilities / disk / gdu1_1.lha / GDu / GDu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-27  |  9.2 KB  |  368 lines

  1. #define MADE_VIA_MY_SHELL /*
  2. local f
  3. strrhead f . $_srcfile
  4. cc $f; ln -t $f -Lc
  5. return $_maxerr
  6. *
  7. *    $Id: GDu.c 1.2 1994/10/26 22:35:31 RK Exp RK $
  8. *    $Log: GDu.c $
  9. *    Revision 1.2  1994/10/26  22:35:31  RK
  10. *    FreeVec(Fib)-Bug fixed / New Options: -num -links
  11. *    Dir-request / can be called from WB
  12. *
  13. *    Revision 1.1  1994/10/16  16:43:53  RK
  14. *    Initial revision
  15. *
  16. *    GDu - graphically display disk usage
  17. *    Copyright (C) 1994  Rainer Köhler
  18. *
  19. *    This program is free software; you can redistribute it and/or modify
  20. *    it under the terms of the GNU General Public License as published by
  21. *    the Free Software Foundation; either version 1, or (at your option)
  22. *    any later version.
  23. *
  24. *    This program is distributed in the hope that it will be useful,
  25. *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  26. *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27. *    GNU General Public License for more details.
  28. *
  29. *    You should have received a copy of the GNU General Public License
  30. *    along with this program; if not, write to the Free Software
  31. *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  32. */
  33.  
  34. #include <exec/types.h>
  35. #include <exec/memory.h>
  36. #include <graphics/gfx.h>
  37. #include <graphics/text.h>
  38. #include <intuition/intuition.h>
  39. #include <libraries/dos.h>
  40. #include <libraries/dosextens.h>
  41. #include <libraries/asl.h>
  42. #include <functions.h>
  43. #include <stdlib.h>
  44. #include <string.h>
  45. #include <stdio.h>
  46.  
  47. static char Version[]= "$VER: GDu 1.1 (26.10.94)";
  48.  
  49. #define WIDTH    (12*8)
  50.  
  51. #define Fib_Type  Fib->fib_DirEntryType        /** Fasse Dich kurz! **/
  52.  
  53. struct Library *IntuitionBase, *GfxBase, *AslBase;
  54. struct Window *Win;
  55. struct RastPort *RPort;
  56.  
  57. char *MyName= "GDu";
  58. long ForeGround=1, BackGround=0;
  59. BOOL Quiet= FALSE, SortSize= FALSE, ShowLinks= FALSE;
  60.  
  61. struct Dir
  62. {    struct Dir *Next;
  63.     struct Dir *Prev;
  64.     struct Dir *Parent;
  65.     struct Dir *Subdir;
  66.     char    Name[30];
  67.     ULONG    FileSize;
  68.     ULONG    Total;
  69.     USHORT    Top;
  70. } RootNode, *BaseNode;
  71.  
  72.  
  73. void _wb_parse() {}
  74.  
  75. char Indentation[100];
  76.  
  77.  
  78. static long AddObj( struct Dir *Parent, BPTR lock)    /** recursive! **/
  79. {
  80.     struct FileInfoBlock *Fib;
  81.     struct Dir *Node, *Next, *Last;
  82.     BPTR cwd, sublock;
  83.     long objsz, totsz=1;    /** 1 for UserDir-Block **/
  84.     long indent;
  85.  
  86.   if( !(Fib= AllocVec(sizeof(struct FileInfoBlock),MEMF_PUBLIC)))
  87.     return 0;
  88.  
  89.   cwd= CurrentDir(lock);
  90.   if( Examine(lock,Fib))
  91.   { if( !Quiet)
  92.     Printf("%s %s...\233K\r",(long)Indentation,Fib->fib_FileName);
  93.  
  94.     if( Fib->fib_DirEntryType < 0)    /** oops, a file **/
  95.     {    objsz  = Fib->fib_NumBlocks;
  96.     objsz += (objsz+71)/72;        /** File Header bzw. List Blocks **/
  97.     Parent->FileSize += objsz;
  98.     }
  99.     else
  100.     {    if( !(Node= malloc(sizeof(struct Dir))))
  101.     {    PutStr("Out of Memory!\n");    goto abort;    }
  102.  
  103.     strcpy( Node->Name, Fib->fib_FileName);
  104.     Node->Parent= Parent;
  105.     Node->Subdir= NULL;
  106.     Node->FileSize= 0;
  107.     Node->Total = 1;    /** 1 für Dir-Block **/
  108.  
  109.     indent= strlen(Indentation);    strcpy( &Indentation[indent],"  ");
  110.  
  111.     while( ExNext(lock,Fib) && !(SetSignal(0L,0L) & SIGBREAKF_CTRL_C))
  112.     {
  113.       if( ShowLinks ||
  114.         Fib_Type==ST_ROOT || Fib_Type==ST_USERDIR || Fib_Type==ST_FILE)
  115.       {
  116.         if( sublock= Lock(Fib->fib_FileName,ACCESS_READ))
  117.         {    AddObj( Node,sublock);
  118.         UnLock( sublock);
  119.         }
  120.       }
  121.     }
  122.     objsz= Node->Total;    Indentation[indent]= 0;
  123.  
  124.     if( Next= Parent->Subdir)
  125.     {    Last= NULL;
  126.         while( Next && (SortSize? Next->Total > objsz
  127.                     : strcmp(Next->Name,Node->Name)<0))
  128.         {    Last= Next;    Next= Next->Next;    }
  129.  
  130.         Node->Prev= Last;
  131.         Node->Next= Next;
  132.         if(Next) Next->Prev= Node;
  133.         if(Last) Last->Next= Node;
  134.         else     Parent->Subdir= Node;
  135.     }
  136.     else
  137.     {    Node->Next= Node->Prev= NULL;    Parent->Subdir= Node;    }
  138.     }
  139.     Parent->Total += objsz;
  140.   }
  141. abort:    CurrentDir(cwd); FreeVec(Fib);    return 1;
  142. }
  143.  
  144.  
  145. void DrawObj( struct Dir *Node, long left, long top, long height)
  146. {
  147.     long total= Node->Total, subheight;
  148.  
  149.   Node->Top= top;
  150.  
  151.   if( height > RPort->TxHeight<<1)
  152.   {    Move(RPort,left+2,top+(height>>1));
  153.     Text(RPort,Node->Name,strlen(Node->Name));
  154.  
  155.     sprintf( Indentation,"(%ld)",total);
  156.     Move(RPort,left+2,top+(height>>1)+RPort->TxHeight);
  157.     Text(RPort,Indentation,strlen(Indentation));
  158.   }
  159.  
  160.   Move(RPort,left,top+height);    left += WIDTH;
  161.   Draw(RPort,left,top+height); Draw(RPort,left,top); Draw(RPort,left-WIDTH,top);
  162.  
  163.   if(left > Win->Width-Win->BorderRight)  return;
  164.  
  165.   for( Node= Node->Subdir;  Node;  Node= Node->Next)
  166.   {    subheight= height * Node->Total / total;
  167.     DrawObj(Node,left,top,subheight);
  168.     top += subheight;
  169.   }
  170. }
  171.  
  172. void DrawAll(void)
  173. {
  174.     struct Window *W= Win;
  175.  
  176.   SetAPen( RPort,BackGround);
  177.   RectFill(RPort,W->BorderLeft,W->BorderTop,
  178.         W->Width-W->BorderRight-1, W->Height-W->BorderBottom-1);
  179.  
  180.   SetAPen(RPort,ForeGround);    SetBPen(RPort,BackGround);
  181.   DrawObj( BaseNode, W->BorderLeft,W->BorderTop,
  182.         W->Height - W->BorderTop - W->BorderBottom -1);
  183. }
  184.  
  185.  
  186. struct Dir *FindNode(long x, long y)
  187. {
  188.     struct Dir *Node= BaseNode;
  189.  
  190.   x /= WIDTH;
  191.   if(x<=0)  return Node->Parent;
  192.  
  193.   while( Node->Subdir && x)
  194.     for( Node= Node->Subdir, --x;
  195.      Node->Next && Node->Next->Top<y;  Node= Node->Next) ;
  196.  
  197.   return Node;
  198. }
  199.  
  200.  
  201. struct
  202. {    Tag ti_Tag;
  203.     void *ti_Data;
  204. }
  205. AslTags[]=
  206. {    ASL_Hail, "Select root of directory tree",
  207.     ASL_OKText, "Display",
  208.     ASL_ExtFlags1, (void *)FIL1F_NOFILES,
  209.     TAG_DONE
  210. };
  211.  
  212. char *DirRequest(void)
  213. {    struct FileRequester *FReq;
  214.     char *DirName= NULL;
  215.  
  216.   if( !(AslBase= OpenLibrary("asl.library",37L)))
  217.   {    Printf("%s: Can't open asl.library!\n",(long)MyName);    }
  218.   else
  219.   {
  220.     if( !(FReq= (void *)AllocAslRequest(ASL_FileRequest,(void *)AslTags)))
  221.     {    Printf("%s: Can't create file requester!\n",(long)MyName);    }
  222.     else
  223.     {    if( AslRequest(FReq,NULL))
  224.     {    if( DirName= malloc( strlen(FReq->rf_Dir)+1))
  225.             strcpy( DirName,FReq->rf_Dir);
  226.     }
  227.     FreeAslRequest(FReq);
  228.     }
  229.     CloseLibrary(AslBase);
  230.   }
  231.   return DirName;
  232. }
  233.  
  234. ULONG WinTags[]=
  235. {    WA_Title,NULL,    WA_PubScreenName,NULL,
  236.     TAG_IGNORE,0, TAG_IGNORE,0, TAG_IGNORE,-1, TAG_IGNORE,-1,  /* l,t,w,h */
  237.     WA_IDCMP, IDCMP_CLOSEWINDOW|IDCMP_NEWSIZE|
  238.         IDCMP_REFRESHWINDOW|IDCMP_MOUSEBUTTONS|IDCMP_RAWKEY,
  239.     WA_SizeGadget,TRUE, WA_DragBar,TRUE, WA_DepthGadget,TRUE,
  240.     WA_CloseGadget,TRUE, WA_SimpleRefresh,TRUE,
  241.     WA_MinWidth,42, WA_MinHeight,42,    TAG_DONE
  242. };
  243.  
  244. main(int argc, char **argv)
  245. {
  246.     char *RootName;
  247.     BPTR RootLock;
  248.     BOOL ende= FALSE;
  249.     long argi, res=20;
  250.  
  251.   MyName= argv[0];
  252.  
  253.   if( argc>=2 && argv[1][0]=='?')
  254.   {    Printf("Usage: %s [-quiet] [-links] [-num] [-window x y w h] [-fg num] [-bg num] [dir]\n",
  255.             (long)MyName);
  256.     return 0;
  257.   }
  258.   if( !(IntuitionBase= OpenLibrary("intuition.library",36))
  259.     ||  !(GfxBase= OpenLibrary("graphics.library",36)))    exit(36);
  260.  
  261.   for( argi=1;  argi<argc;  ++argi)
  262.   {        char *arg= argv[argi];
  263.  
  264.     if( !strcmp( arg,"-fg"))
  265.     {    if( 0 >= StrToLong( argv[++argi], &ForeGround))
  266.             ForeGround=1;
  267.     }
  268.     else
  269.     if( !strcmp( arg,"-bg"))
  270.     {    StrToLong( argv[++argi], &BackGround);    }
  271.     else
  272.     if( !strncmp( arg,"-w",2))        /** "-window" **/
  273.     { if( 0<StrToLong( argv[++argi], (LONG *)&WinTags[2*2+1]))  /* left */
  274.             WinTags[2*2]= WA_Left;
  275.       if( 0<StrToLong( argv[++argi], (LONG *)&WinTags[3*2+1]))  /* top */
  276.             WinTags[3*2]= WA_Top;
  277.       if( 0<StrToLong( argv[++argi], (LONG *)&WinTags[4*2+1]))  /* width */
  278.             WinTags[4*2]= WA_Width;
  279.       if( 0<StrToLong( argv[++argi], (LONG *)&WinTags[5*2+1]))  /* height */
  280.             WinTags[5*2]= WA_Height;
  281.     }
  282.     else if( !strncmp( arg,"-n",2))  SortSize= TRUE;
  283.     else if( !strncmp( arg,"-l",2))  ShowLinks= TRUE;
  284.     else if( !strncmp( arg,"-q",2))  Quiet= TRUE;
  285.     else break;
  286.   }
  287.   if( argi>=argc)
  288.   {    if( !(RootName= DirRequest()))    goto clean1;    }
  289.   else    RootName= argv[argi];
  290.  
  291.   if( !(RootLock= Lock(RootName,ACCESS_READ)))
  292.   {    Printf("%s not found\n",(long)RootName);  goto clean1;  }
  293.  
  294.   RootNode.Total= 1;    RootNode.FileSize= 0;
  295.   strncpy( RootNode.Name,RootName,30);
  296.  
  297.   Indentation[0]= 0;    AddObj( &RootNode,RootLock);    UnLock(RootLock);
  298.  
  299.   if( SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
  300.   {    Printf("\233K%s: User Abort\n",(long)MyName);  goto clean1;    }
  301.  
  302.   if( !Quiet)  PutStr("\233K\n");
  303.  
  304.   WinTags[1]= (ULONG) RootName;
  305.  
  306.   if( !(Win= OpenWindowTagList(NULL,(void *)WinTags)))
  307.   {    PutStr("GDu: Can't open Window!\n");    goto clean1;    }
  308.  
  309.   RPort= Win->RPort;    BaseNode= RootNode.Subdir;
  310.   DrawAll();
  311.  
  312.   do{    struct IntuiMessage *Msg;
  313.     struct Dir *Node;
  314.     USHORT m_code;
  315.     ULONG m_class;
  316.     SHORT m_X,m_Y;
  317.  
  318.     while( Msg= (void *) GetMsg(Win->UserPort))
  319.     { m_class= Msg->Class;    m_code= Msg->Code;
  320.       m_X = Msg->MouseX;    m_Y = Msg->MouseY;
  321.       ReplyMsg((void *)Msg);
  322.  
  323.       switch(m_class)
  324.       { case IDCMP_MOUSEBUTTONS:
  325.         m_code ^= 128;        /** up in down **/
  326.         case IDCMP_RAWKEY:
  327.         if(m_code>128)    break;    /** don't redraw on up-event **/
  328.         switch(m_code)
  329.         { case SELECTDOWN:
  330.             Node= FindNode(m_X-Win->BorderLeft,m_Y);  break;
  331.           case CURSORUP:
  332.             Node= BaseNode->Prev;    break;
  333.           case CURSORDOWN:
  334.             Node= BaseNode->Next;    break;
  335.           case CURSORLEFT:
  336.             Node= BaseNode->Parent;    break;
  337.           case CURSORRIGHT:
  338.             Node= BaseNode->Subdir;    break;
  339.           case 0x41:        /** BS    **/
  340.           case 0x3A:        /** '/'(usa) bzw. '-'(d) **/
  341.             Node= RootNode.Subdir;
  342.             break;
  343.           case 0x45:        /** ESC **/
  344.           case KEYCODE_Q:
  345.             ende= TRUE;
  346.           default:
  347.             Node= NULL;    break;
  348.         }
  349.         if( Node==NULL || Node== &RootNode)    break;
  350.         BaseNode= Node;
  351.         case IDCMP_NEWSIZE:
  352.         DrawAll();
  353.         break;
  354.         case IDCMP_REFRESHWINDOW:
  355.         BeginRefresh(Win);    DrawAll();    EndRefresh(Win,TRUE);
  356.         break;
  357.         case IDCMP_CLOSEWINDOW:
  358.         ende= TRUE;
  359.       }
  360.     }
  361.     }while( !ende);
  362.  
  363.     res= 0;
  364.     CloseWindow(Win);
  365. clean1:    CloseLibrary(GfxBase);    CloseLibrary(IntuitionBase);
  366.     return res;
  367. }
  368.