home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format 85 / af085a.adf / archives / af85a1.lzx / VolumeWatch / volumewatch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1978-07-26  |  10.3 KB  |  414 lines

  1. /*
  2.     VolumeWatch
  3.     -----------
  4.  
  5.     whooa! again a 2 hours production ;-)
  6.  
  7.     - should have been used BOOPSI objects for the frames
  8.  
  9.     Copyright ©1996 by Daniel Balster. Freeware!
  10. */
  11.  
  12. #include <exec/exec.h>
  13. #include <proto/exec.h>
  14. #include <dos/dos.h>
  15. #include <proto/dos.h>
  16. #include <intuition/intuition.h>
  17. #include <devices/timer.h>
  18. #include <proto/intuition.h>
  19. #include <proto/graphics.h>
  20.  
  21. #include <stdio.h>
  22. #include <string.h>
  23.  
  24. #define SCANFLAGS LDF_VOLUMES|LDF_READ
  25. #define TEMPLATE "PUBSCREEN/K,WIDTH/K/N,LEFT/K/N,TOP/K/N,INTERVAL/K/N,NOFULL/S,QUIET/S"
  26.  
  27. #define LOCALETEMP "%ld%% full, %ld%c free, %ld%c used"
  28. //#define LOCALETEMP "%ld%% voll, %ld%c frei, %ld%c benutzt"
  29.  
  30. UBYTE *version = "$VER: VolumeWatch 1.1 (29.01.96) Copyright ©1996 by Daniel Balster";
  31.  
  32. struct {
  33.     STRPTR pubscreen;
  34.     ULONG  *Width, *Left, *Top, *interval;
  35.     ULONG  nofull;
  36.     ULONG quiet;
  37. } args = {0};
  38.  
  39. struct VolumeInfo
  40. {
  41.     struct Node node;        // to link
  42.     WORD pad;                // force the next one to a 32bit boundary
  43.     struct InfoData data;    // Info'ed
  44.     UBYTE *name;            // AllocVec'ed
  45. };
  46.  
  47. SHORT zoom[4] = { 0,0,100,14 };
  48.  
  49. char *units = "KMG";    // Kilo-Mega-Giga
  50.  
  51. // *** timer
  52.  
  53. struct MsgPort        *time_mp = 0;
  54. struct timerequest    *time_ior = 0;
  55.  
  56. #define TIMESIGNAL (1l<<time_mp->mp_SigBit)
  57.  
  58. int inittimer()
  59. {
  60.     if (time_mp = CreateMsgPort())
  61.     {
  62.         if (time_ior = (struct timerequest*) CreateIORequest (time_mp,sizeof(struct timerequest)))
  63.         {
  64.             if (OpenDevice ("timer.device",UNIT_MICROHZ,time_ior,0)==0)
  65.             {
  66.                 time_ior->tr_node.io_Command    = TR_ADDREQUEST;
  67.                 time_ior->tr_node.io_Flags    = IOF_QUICK;
  68.                 time_ior->tr_time.tv_secs    = 1;
  69.                 time_ior->tr_time.tv_micro    = 0;
  70.                 SendIO (time_ior);
  71.  
  72.                 return 1;
  73.             }
  74.         }
  75.     }
  76.     
  77.     return 0;
  78. }
  79.  
  80. VOID freetimer()
  81. {
  82.     if (time_mp)
  83.     {
  84.         if (time_ior)
  85.         {
  86.             AbortIO (time_ior);
  87.             WaitIO (time_ior);
  88.             CloseDevice (time_ior);
  89.             DeleteIORequest ((struct IORequest*) time_ior);
  90.         }
  91.         DeleteMsgPort (time_mp);
  92.     }
  93. }
  94.  
  95. VOID WindowMagic (struct Window *win, struct List *list, UWORD items)
  96. {
  97.     if (win)
  98.     {
  99.         struct RastPort *RP = win->RPort;
  100.         ULONG height,width;
  101.         struct VolumeInfo *vinfo;
  102.         struct TextExtent te;
  103.         int i,j,x,y;
  104.         ULONG free,inuse,percent,total;
  105.         char buf[80], unit1, unit2;
  106.         LONG sigs;
  107.         BOOL waiting = TRUE;
  108.         BYTE dark,light,fill,hilight,backfill;
  109.         struct DrawInfo *dri;
  110.  
  111.         if (win->Flags & WFLG_ZOOMED) return;
  112.  
  113.         if (dri = GetScreenDrawInfo(win->WScreen))
  114.         {
  115.             SetFont(RP,dri->dri_Font);
  116.  
  117.             dark     = dri->dri_Pens[SHADOWPEN];
  118.             light    = dri->dri_Pens[SHINEPEN];
  119.             fill     = dri->dri_Pens[FILLPEN];
  120.             hilight  = dri->dri_Pens[TEXTPEN];
  121.             backfill = dri->dri_Pens[BACKGROUNDPEN];
  122.  
  123.             FreeScreenDrawInfo(win->WScreen,dri);
  124.         }
  125.         else    // old method...
  126.         {
  127.             dark     = 1;
  128.             light    = 2;
  129.             fill     = 3;
  130.             hilight  = 1;
  131.             backfill = 0;
  132.         
  133.             SetFont(RP,win->WScreen->RastPort.Font);
  134.         }
  135.         
  136.         height = (items*RP->TxHeight*3) + win->BorderTop + win->BorderBottom;
  137.         width = (win->Width-(win->BorderLeft+win->BorderRight))/2;
  138.  
  139.         if (win->Height != height)
  140.         {
  141.             ChangeWindowBox(win,win->LeftEdge,win->TopEdge,win->Width,height);
  142.  
  143.             while (waiting)
  144.             {
  145.                 sigs = Wait(SIGBREAKF_CTRL_D|(1L << win->UserPort->mp_SigBit));
  146.  
  147.                 if (sigs & SIGBREAKF_CTRL_D) waiting = FALSE;
  148.  
  149.                 if (sigs & (1L << win->UserPort->mp_SigBit))
  150.                 {
  151.                     struct IntuiMessage *imsg;
  152.  
  153.                     while (imsg = (struct IntuiMessage*) GetMsg(win->UserPort))
  154.                     {
  155.                         switch (imsg->Class)
  156.                         {
  157.                             case IDCMP_CHANGEWINDOW:
  158.                                 waiting = FALSE;
  159.                                 break;
  160.                             default:
  161.                                 break;
  162.                         } // switch
  163.                         ReplyMsg((struct Message*)imsg);
  164.                     } // while
  165.                 } // if WindowSignal
  166.             } // while
  167.         } // if 
  168.  
  169.         // a list parser
  170.         i=0;
  171.         for (vinfo = (struct VolumeInfo*)list->lh_Head;vinfo->node.ln_Succ;vinfo=(struct VolumeInfo*)vinfo->node.ln_Succ)
  172.         {
  173.             x = win->BorderLeft+4;
  174.             y = win->BorderTop+i+(RP->TxHeight/2);
  175.  
  176.             SetABPenDrMd(RP,hilight,backfill,JAM2);
  177.             SetSoftStyle(RP,2,7);
  178.             // width is the half window width (minus borders) and each 4 pixels left and right
  179.             Move (RP,x,y+RP->TxBaseline);
  180.             Text (RP,vinfo->name,TextFit(RP,vinfo->name,strlen(vinfo->name)-1,&te,NULL,1,width-8,32737));
  181.             SetAPen(RP,backfill);
  182.             RectFill(RP,RP->cp_x,y,x+width-4,y+RP->TxHeight-1);
  183.  
  184.             x += width;        // drift to the right
  185.  
  186.             total = vinfo->data.id_NumBlocks*vinfo->data.id_BytesPerBlock;
  187.             inuse = vinfo->data.id_NumBlocksUsed*vinfo->data.id_BytesPerBlock;
  188.             free  = total-inuse;
  189.             percent = (vinfo->data.id_NumBlocksUsed*100)/vinfo->data.id_NumBlocks;
  190.  
  191.             // well, this is ugly; should have used locale.lib ;-(
  192.             
  193.             j=0; unit2 = 'K'; inuse &=~ 0x3ff;
  194.             while (inuse >= 1024)
  195.             {
  196.                 inuse /= 1024;
  197.                 unit2 = units[j++];
  198.             } // while
  199.             j=0; unit1 = 'K'; free &=~ 0x3ff;
  200.             while (free >= 1024)
  201.             {
  202.                 free /= 1024;
  203.                 unit1 = units[j++];
  204.             } // while
  205.             
  206.             sprintf(buf,LOCALETEMP,percent,free,unit1,inuse,unit2);
  207.  
  208.             SetABPenDrMd(RP,hilight,backfill,JAM2);
  209.             SetSoftStyle(RP,0,7);
  210.             // width is the half window width (minus borders) and each 4 pixels left and right
  211.             Move (RP,win->BorderLeft+4,y+RP->TxBaseline+4+RP->TxHeight);
  212.             Text (RP,buf,TextFit(RP,buf,strlen(buf),&te,NULL,1,win->Width-(8+win->BorderLeft+win->BorderRight),32737));
  213.  
  214.             SetAPen(RP,backfill);
  215.             RectFill(RP,RP->cp_x,y+4+RP->TxHeight,win->Width-(win->BorderLeft+win->BorderRight),y+4+(2*RP->TxHeight)-1);
  216.             
  217.             SetAPen(RP,dark);
  218.             Move (RP,x+width-8-1,y);
  219.             Draw (RP,x,y);
  220.             Draw (RP,x,y+RP->TxHeight);
  221.             SetAPen(RP,light);
  222.             Move (RP,x+1,y+RP->TxHeight);
  223.             Draw (RP,x+width-8,y+RP->TxHeight);
  224.             Draw (RP,x+width-8,y);
  225.             SetAPen(RP,fill);
  226.             RectFill(RP,x+1,y+1,x+(((width-10)*percent)/100)+1,y+RP->TxHeight-1);
  227.             SetAPen(RP,backfill);
  228.             if ((((width-10)*percent)/100)!=width-10) RectFill(RP,x+(((width-10)*percent)/100)+1,y+1,x+(width-10),y+RP->TxHeight-1);
  229.             
  230.             i += RP->TxHeight*3;
  231.         } // for
  232.     } // if
  233. }
  234.  
  235. int main ()
  236. {
  237.     struct RDArgs *rda;
  238.     VOID *mypool;
  239.     struct Process *proc = (struct Process*) FindTask(NULL);
  240.     APTR old;
  241.     
  242.     old = proc->pr_WindowPtr;
  243.     proc->pr_WindowPtr = -1;
  244.  
  245.     if (rda = ReadArgs(TEMPLATE,(LONG*)&args,NULL))
  246.     {
  247.         struct Screen *scr;
  248.         struct Window *win;
  249.  
  250.         if (!args.quiet) PutStr(
  251. "*** VolumeWatch 1.1 ***\n"
  252. "Copyright © 1996 by Daniel Balster\n"
  253. "All Rights Reserved.\n");
  254.  
  255.  
  256.         if (args.interval) if (!(inittimer())) goto toobad;
  257.  
  258.         // if no pubscreen is given as argument, default is used
  259.         if (scr = LockPubScreen(args.pubscreen))
  260.         {
  261.             zoom[0] = args.Left ? *args.Left : ~0,
  262.             zoom[1] = args.Top ? *args.Top : ~0,
  263.             zoom[2] = args.Width ? *args.Width : scr->Width/5;
  264.             zoom[3] = scr->BarHeight+1;
  265.  
  266.             win = OpenWindowTags(NULL,
  267.                 WA_PubScreen        , scr,
  268.                 WA_Width            , args.Width ? *args.Width : scr->Width/5,
  269.                 WA_Left            , args.Left ? *args.Left : ~0,
  270.                 WA_Top            , args.Top ? *args.Top : ~0,
  271.                 WA_Height            , scr->BarHeight+1,
  272.                 WA_CloseGadget        , TRUE,
  273.                 WA_DepthGadget        , TRUE,
  274.                 WA_DragBar        , TRUE,
  275.                 WA_RMBTrap        , TRUE,
  276.                 WA_Zoom            , zoom,
  277.                 WA_Title            , "VolumeWatch",
  278.                 WA_IDCMP            , IDCMP_CLOSEWINDOW |
  279.                                   IDCMP_DISKINSERTED |
  280.                                   IDCMP_MOUSEBUTTONS |
  281.                                   IDCMP_CHANGEWINDOW |
  282.                                   IDCMP_DISKREMOVED,
  283.                 TAG_DONE);
  284.  
  285.             // we don't need to hold the screen any longer
  286.             UnlockPubScreen(NULL,scr);
  287.             
  288.             if (win)
  289.             {
  290.                 if (mypool = CreatePool(MEMF_PUBLIC|MEMF_CLEAR,4096,4096))
  291.                 {
  292.                     struct List mylist;
  293.                     struct DosList *dlist;
  294.                     struct VolumeInfo *vinfo;
  295.                     BPTR mylock;
  296.                     BOOL running = TRUE;
  297.                     UWORD entries;
  298.                     LONG signals;
  299.  
  300.                     while (running)
  301.                     {
  302.                         NewList(&mylist);
  303.                         entries = 0;
  304.  
  305.                         dlist = LockDosList(SCANFLAGS);
  306.                         while (dlist = NextDosEntry(dlist,SCANFLAGS))
  307.                         {
  308.                             UBYTE *name = BADDR(dlist->dol_Name);
  309.                             ULONG length = (ULONG)name[0];
  310.                             BOOL fail = TRUE;
  311.                         
  312.                             if (vinfo = AllocPooled(mypool,sizeof(*vinfo)))
  313.                             {
  314.                                 if (vinfo->name = AllocPooled(mypool,length+2))
  315.                                 {
  316.                                     CopyMem(++name,vinfo->name,length);
  317.                                     vinfo->name[length] = ':';
  318.                                     
  319.                                     if (mylock = Lock(vinfo->name,ACCESS_READ))
  320.                                     {
  321.                                         if (Info(mylock,&vinfo->data))
  322.                                         {
  323.                                             if (args.nofull)
  324.                                             {
  325.                                                 if (vinfo->data.id_NumBlocks != vinfo->data.id_NumBlocksUsed)
  326.                                                 {
  327.                                                     AddHead(&mylist,(struct Node*)vinfo);
  328.                                                     entries++;
  329.                                                     fail = FALSE;
  330.                                                 } // if
  331.                                             } // if
  332.                                             else
  333.                                             {
  334.                                                 AddHead(&mylist,(struct Node*)vinfo);
  335.                                                 entries++;
  336.                                                 fail = FALSE;
  337.                                             } // if..else
  338.                                         } // if Info
  339.                                         UnLock(mylock);
  340.                                     } // if Lock
  341.                                     if (fail) FreePooled(mypool,vinfo->name,strlen(vinfo->name)+1);
  342.                                 } // if AllocPooled
  343.                                 if (fail) FreePooled(mypool,vinfo,sizeof(*vinfo));
  344.                             } // if AllocPooled
  345.                         } // while NextDosEntry
  346.  
  347.                         WindowMagic(win,&mylist,entries);
  348.  
  349.                         // cleanup 
  350.                         while (!IsListEmpty(&mylist))
  351.                         {
  352.                             if (vinfo = (struct VolumeInfo*) RemHead(&mylist))
  353.                             {
  354.                                 // note: we have added a nonzero character, so the length is now +1, not +2
  355.                                 if (vinfo->name) FreePooled(mypool,vinfo->name,strlen(vinfo->name)+1);
  356.                                 FreePooled(mypool,vinfo,sizeof(*vinfo));
  357.                             } // if RemHead
  358.                         } // while IsListEmpty
  359.  
  360.                         UnLockDosList(SCANFLAGS);
  361.                         
  362.                         signals = Wait(TIMESIGNAL|SIGBREAKF_CTRL_C|(1L << win->UserPort->mp_SigBit));
  363.  
  364.                         if (signals & SIGBREAKF_CTRL_C) running = FALSE;
  365.  
  366.                         if (!(win->Flags & WFLG_ZOOMED)) if (time_mp) if (signals & TIMESIGNAL)
  367.                         {
  368.                             time_ior->tr_node.io_Command    = TR_ADDREQUEST;
  369.                             time_ior->tr_node.io_Flags    = IOF_QUICK;
  370.                             time_ior->tr_time.tv_secs    = *args.interval;
  371.                             time_ior->tr_time.tv_micro    = 0;
  372.                             SendIO (time_ior);
  373.                         }
  374.  
  375.                         if (signals & (1L << win->UserPort->mp_SigBit))
  376.                         {
  377.                             struct IntuiMessage *imsg;
  378.                             
  379.                             while (imsg = (struct IntuiMessage*) GetMsg(win->UserPort))
  380.                             {
  381.                                 switch (imsg->Class)
  382.                                 {
  383.                                     case IDCMP_CLOSEWINDOW:
  384.                                         running = FALSE;
  385.                                         break;
  386.                             // no need 
  387.                             //        case IDCMP_DISKINSERTED:
  388.                             //        case IDCMP_DISKREMOVED:
  389.                             //            break;
  390.                                     default:
  391.                                         break;
  392.                                 }
  393.                                 ReplyMsg((struct Message*)imsg);
  394.                             }
  395.                         } // if WindowSignal
  396.  
  397.                     } // while
  398.                     DeletePool(mypool);
  399.                 } // if CreatePool
  400.                 if (win) CloseWindow (win);
  401.             } // if OpenWindow
  402.         } // if LockPubScreen
  403.  
  404.     toobad:
  405.         freetimer();    // bad style ?
  406.  
  407.         FreeArgs(rda);
  408.     } // if ReadArgs
  409.     
  410.     proc->pr_WindowPtr = old;
  411.  
  412.     return 0;
  413. }
  414.