home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 1 / FishNMoreVol1.bin / more / drive_utils / benchmark / diskspeed / diskspeed.c < prev    next >
C/C++ Source or Header  |  1990-02-03  |  18KB  |  663 lines

  1. /*
  2.  *                          DiskSpeed v3.0
  3.  *                                by
  4.  *                           Michael Sinz
  5.  *
  6.  *             Copyright (c) 1989 by MKSoft Development
  7.  *
  8.  *            MKSoft Development
  9.  *            163 Appledore Drive
  10.  *            Downingtown, PA 19335
  11.  *
  12.  * Yes, this is yet another disk speed testing program, but with a few
  13.  * differences.  It was designed to give the most accurate results of the
  14.  * true disk performance in the system.  For this reason many of
  15.  * DiskSpeed's results may look either lower or higher than current disk
  16.  * performance tests.
  17.  *
  18.  * This program was thrown together in a few hours because I needed more
  19.  * accurate and consistent results for disk performance as seen from the
  20.  * application's standpoint.  This program has now served its purpose and
  21.  * I am now giving it to the rest of the Amiga world to play with as long
  22.  * as all of the files remain together in unmodified form.  (That is, the
  23.  * files DiskSpeed, DiskSpeed.info, DiskSpeed.c, DiskSpeedWindow.c,
  24.  * DiskSpeedWindow.h, MakeBoxes.c, MakeBoxes.h, StandardGadgets.c,
  25.  * StandardGadgets.h, RenderInfo.c, RenderInfo.h, DiskSpeed.doc, and
  26.  * MakeFile)
  27.  *
  28.  * Version 2.0 of this program added a few features and cleaned up the
  29.  * user interface.  I hope you like this...
  30.  *
  31.  * Version 3.0 of this program added the performance stress and cleaned up
  32.  * some parts of the older code.  (Fix to RenderInfo.c)
  33.  *
  34.  ******************************************************************************
  35.  *                                          *
  36.  *    Reading legal mush can turn your brain into guacamole!              *
  37.  *                                          *
  38.  *        So here is some of that legal mush:                  *
  39.  *                                          *
  40.  * Permission is hereby granted to distribute this program's source          *
  41.  * executable, and documentation for non-commercial purposes, so long as the  *
  42.  * copyright notices are not removed from the sources, executable or          *
  43.  * documentation.  This program may not be distributed for a profit without   *
  44.  * the express written consent of the author Michael Sinz.              *
  45.  *                                          *
  46.  * This program is not in the public domain.                      *
  47.  *                                          *
  48.  * Fred Fish is expressly granted permission to distribute this program's     *
  49.  * source and executable as part of the "Fred Fish freely redistributable     *
  50.  * Amiga software library."                              *
  51.  *                                          *
  52.  * Permission is expressly granted for this program and it's source to be     *
  53.  * distributed as part of the Amicus Amiga software disks, and the          *
  54.  * First Amiga User Group's Hot Mix disks.                      *
  55.  *                                          *
  56.  ******************************************************************************
  57.  *
  58.  * Main code and testing sections...
  59.  */
  60.  
  61. #include    <EXEC/Types.h>
  62. #include    <EXEC/Memory.h>
  63. #include    <Intuition/Intuition.h>
  64. #include    <Libraries/DOS.h>
  65. #include    <Libraries/DOSextens.h>
  66. #include    <Graphics/RastPort.h>
  67. #include    <Devices/Timer.h>
  68.  
  69. #include    <PROTO/All.h>
  70.  
  71. #include    <string.h>
  72.  
  73. #include    "RenderInfo.h"
  74. #include    "DiskSpeedWindow.h"
  75.  
  76. extern    struct    IntuitionBase    *IntuitionBase;
  77. extern    struct    GfxBase        *GfxBase;
  78.     struct    Library        *TimerBase;
  79.  
  80. #define    TIMESCALER        256L
  81. #define    SEEK_READ_SIZE        300L
  82.  
  83. #define    IO_BUFFER_SIZE        262144L
  84.  
  85. /* Define the file name limits for file create/delete/open/scan */
  86. #define    FINAL    'R'
  87.  
  88. static char ErrorText1[28]    ="Can't create test directory";
  89. static char ErrorText2[16]    ="Bad device name";
  90. static char ErrorText3[24]    ="Can't open results file";
  91. static char ErrorText4[19]    ="Can't open printer";
  92.  
  93. static char PrinterFile[5]    ="PRT:";
  94. static char ResultFile[18]    ="DiskSpeed.Results";
  95. static char DirectoryName[22]    =" Disk Test Directory ";
  96. static char FileNameRoot[22]    =" -- DiskTest File -- ";
  97.  
  98. static char Testing_String[10]    =">Testing<";
  99.  
  100. /* The Wait pointer I use... */
  101. USHORT __chip WaitPointer[48] =
  102. {
  103.     0x0000, 0x0000,    0x6700, 0xC700,    0xCFA0, 0xCFA0,    0xBFF0, 0x3FF0,
  104.     0x70F8, 0x7FF8,    0x7DFC, 0x7FFC,    0xFBFC, 0xFFFC,    0x70FC, 0x7FFC,
  105.     0x7FFE, 0x7FFE,    0x7F0E, 0x7FFE,    0x3FDF, 0x3FFF,    0x7FBE, 0x7FFE,
  106.     0x3F0E, 0x3FFE,    0x1FFC, 0x1FFC,    0x07F8, 0x07F8,    0x01E0, 0x01E0,
  107.     0x0780, 0x0780,    0x0FE0, 0x0FE0,    0x0740, 0x0740,    0x0000, 0x0000,
  108.     0x0070, 0x0070,    0x0078, 0x0078,    0x0030, 0x0030,    0x0000, 0x0000,
  109. };
  110.  
  111. /*
  112.  * These two defines set up and clear the WaitPointer...
  113.  */
  114. #define    SetWait(x)    SetPointer(x,WaitPointer,22L,16L,NULL,NULL)
  115. #define    ClearWait(x)    ClearPointer(x)
  116.  
  117. /*
  118.  * This does a requester on the window to tell the user something...
  119.  */
  120. VOID TellUser(struct MyWindow *MyWindow,char *Text)
  121. {
  122. register    struct    IntuiMessage    *msg;
  123. register        SHORT        flag=TRUE;
  124.  
  125.     MyWindow->ReqIText.LeftEdge=(MyWindow->Req.Width>>1)-(strlen(Text)<<2);
  126.     MyWindow->ReqIText.IText=Text;
  127.  
  128.     Request(&(MyWindow->Req),MyWindow->Window);
  129.     while (flag)
  130.     {
  131.         WaitPort(MyWindow->Window->UserPort);
  132.         while (msg=(struct IntuiMessage *)GetMsg(MyWindow->Window->UserPort))
  133.         {
  134.             if (msg->Class==GADGETUP)
  135.             {
  136.                 if (((struct Gadget *)(msg->IAddress))->GadgetID==GADGET_REQ) flag=FALSE;
  137.             }
  138.             ReplyMsg((struct Message *)msg);
  139.         }
  140.     }
  141.     EndRequest(&(MyWindow->Req),MyWindow->Window);
  142. }
  143.  
  144. /*
  145.  * Returns FALSE if the user clicked on the CLOSE gadget...
  146.  */
  147. SHORT Check_Quit(struct MyWindow *MyWindow)
  148. {
  149. register    struct    IntuiMessage    *msg;
  150. register        SHORT        flag=TRUE;
  151.  
  152.     while(msg=(struct IntuiMessage *)GetMsg(MyWindow->Window->UserPort))
  153.     {
  154.         if (msg->Class==CLOSEWINDOW) flag=FALSE;
  155.         ReplyMsg((struct Message *)msg);
  156.     }
  157.     return(flag);
  158. }
  159.  
  160. /*
  161.  * Clears a string entry to spaces...
  162.  */
  163. VOID Clear_Entry(char *String)
  164. {
  165. register    SHORT    t;
  166.  
  167.     for (t=0;t<9;t++) String[t]=' ';
  168.     String[9]='\0';
  169. }
  170.  
  171. /*
  172.  * Sets a string entry to the string >Testing< and does a
  173.  * PrintIText() to display it...
  174.  */
  175. VOID Set_Testing(SHORT ResultNum,struct MyWindow *MyWindow)
  176. {
  177.     strcpy(MyWindow->MyResults[ResultNum].text,Testing_String);
  178.     PrintIText(MyWindow->Window->RPort,&(MyWindow->MyResults[ResultNum].IntuiText),NULL,NULL);
  179. }
  180.  
  181. /*
  182.  * Sets a string entry to the value passed and does a PrintIText()
  183.  * to display it...
  184.  */
  185. VOID Set_Entry(SHORT ResultNum,LONG Value,struct MyWindow *MyWindow)
  186. {
  187. register    SHORT    t;
  188. register    SHORT    tmp;
  189. register    char    *String;
  190.  
  191.     String=MyWindow->MyResults[ResultNum].text;
  192.     Clear_Entry(String);
  193.     t=9;
  194.     while (Value)
  195.     {
  196.         tmp=Value%10;
  197.         Value=Value/10;
  198.         String[--t]=(char)(tmp)+'0';
  199.     }
  200.     if (!String[t]) String[--t]='0';
  201.     PrintIText(MyWindow->Window->RPort,&(MyWindow->MyResults[ResultNum].IntuiText),NULL,NULL);
  202. }
  203.  
  204. /*
  205.  * This gets the starting time...
  206.  */
  207. VOID Timer_Start(struct MyWindow *MyWindow)
  208. {
  209. register    struct    timerequest    *Time_Req;
  210.  
  211.     Time_Req=&(MyWindow->TimeReq);
  212.  
  213.     Time_Req->tr_node.io_Command=TR_GETSYSTIME;
  214.     Time_Req->tr_node.io_Flags=IOF_QUICK;
  215.     DoIO((struct IORequest *)Time_Req);
  216.     MyWindow->StartTime=Time_Req->tr_time;
  217. }
  218.  
  219. /*
  220.  * This gets the ending time and finds out what the per second speed is...
  221.  * It also does a RefreshGadgets() to display the text...
  222.  */
  223. VOID Timer_Stop(struct MyWindow *MyWindow,SHORT ResultNum,LONG Number)
  224. {
  225. register    struct    timerequest    *Time_Req;
  226. register        LONG        Value;
  227.  
  228.     Time_Req=&(MyWindow->TimeReq);
  229.  
  230.     Time_Req->tr_node.io_Command=TR_GETSYSTIME;
  231.     Time_Req->tr_node.io_Flags=IOF_QUICK;
  232.     DoIO((struct IORequest *)Time_Req);
  233.     MyWindow->StopTime=Time_Req->tr_time;
  234.  
  235.     SubTime(&(MyWindow->StopTime),&(MyWindow->StartTime));
  236.  
  237.     /* Now calculate Value based on Number and the time... */
  238.     Value=(Number*TIMESCALER) /
  239.         (    (MyWindow->StopTime.tv_secs*TIMESCALER) +
  240.             (MyWindow->StopTime.tv_micro/(1000000L/TIMESCALER))
  241.         );
  242.  
  243.     Set_Entry(ResultNum,Value,MyWindow);
  244. }
  245.  
  246. /*
  247.  * File create test...
  248.  * This creates a bunch of files in our test directory...
  249.  * The delete test deletes these files...
  250.  */
  251. VOID Do_FileCreate_Test(struct MyWindow *MyWindow)
  252. {
  253. register    char    *t1;
  254. register    char    *t2;
  255. register    BPTR    file;
  256. register    LONG    count=0;
  257.  
  258.     t1=FileNameRoot+1;
  259.     t2=t1+1;
  260.  
  261.     Set_Testing(RESULTS_CREATE,MyWindow);
  262.     Timer_Start(MyWindow);
  263.     for (*t1='A';*t1<FINAL;(*t1)++) for (*t2='A';*t2<FINAL;(*t2)++)
  264.     {
  265.         if (file=Open(FileNameRoot,MODE_NEWFILE)) Close(file);
  266.         count++;
  267.     }
  268.     Timer_Stop(MyWindow,RESULTS_CREATE,count);
  269. }
  270.  
  271. /*
  272.  * File Open/Close test...
  273.  * This Opens/Closes a bunch of files in our test directory...
  274.  */
  275. VOID Do_OpenClose_Test(struct MyWindow *MyWindow)
  276. {
  277. register    char    *t1;
  278. register    char    *t2;
  279. register    BPTR    file;
  280. register    LONG    count=0;
  281.  
  282.     t1=FileNameRoot+1;
  283.     t2=t1+1;
  284.  
  285.     Set_Testing(RESULTS_OPEN_CLOSE,MyWindow);
  286.     Timer_Start(MyWindow);
  287.     for (*t1='A';*t1<FINAL;(*t1)++) for (*t2='A';*t2<FINAL;(*t2)++)
  288.     {
  289.         if (file=Open(FileNameRoot,MODE_OLDFILE)) Close(file);
  290.         count++;
  291.     }
  292.     Timer_Stop(MyWindow,RESULTS_OPEN_CLOSE,count);
  293. }
  294.  
  295. /*
  296.  * Directory scan test...  This is done by scanning the directory we
  297.  * just created in the create test... (Three times...)
  298.  */
  299. VOID Do_DirScan_Test(struct MyWindow *MyWindow)
  300. {
  301. register    struct    FileInfoBlock    *FIB;
  302. register        BPTR        lock;
  303. register        LONG        count=0;
  304. register        SHORT        loop;
  305.  
  306.     lock=CurrentDir(NULL);    /* Get our directory lock... */
  307.     if (FIB=AllocMem(sizeof(struct FileInfoBlock),MEMF_PUBLIC))
  308.     {
  309.         Set_Testing(RESULTS_DIR_SCAN,MyWindow);
  310.         Timer_Start(MyWindow);
  311.         for (loop=0;loop<3;loop++)
  312.         {
  313.             Examine(lock,FIB);
  314.             while (ExNext(lock,FIB)) count++;
  315.         }
  316.         Timer_Stop(MyWindow,RESULTS_DIR_SCAN,count);
  317.  
  318.         FreeMem(FIB,sizeof(struct FileInfoBlock));
  319.     }
  320.     CurrentDir(lock);    /* Return the locked directory... */
  321. }
  322.  
  323. /*
  324.  * File delete test...  We delete the files created in the create test...
  325.  */
  326. VOID Do_FileDelete_Test(struct MyWindow *MyWindow)
  327. {
  328. register    char    *t1;
  329. register    char    *t2;
  330. register    LONG    count=0;
  331.  
  332.     t1=FileNameRoot+1;
  333.     t2=t1+1;
  334.  
  335.     Set_Testing(RESULTS_DELETE,MyWindow);
  336.     Timer_Start(MyWindow);
  337.     for (*t1='A';*t1<FINAL;(*t1)++) for (*t2='A';*t2<FINAL;(*t2)++)
  338.     {
  339.         DeleteFile(FileNameRoot);
  340.         count++;
  341.     }
  342.     Timer_Stop(MyWindow,RESULTS_DELETE,count);
  343. }
  344.  
  345. /*
  346.  * This does the seek/read test...
  347.  */
  348. VOID Do_SeekRead_Test(struct MyWindow *MyWindow,char *Buffer)
  349. {
  350. register    short    t;
  351. register    LONG    count=0;
  352. register    LONG    pos;
  353. register    BPTR    bigfile;
  354.  
  355.     if (bigfile=Open(FileNameRoot,MODE_NEWFILE))
  356.     {
  357.         Set_Testing(RESULTS_SEEK_READ,MyWindow);
  358.         Write(bigfile,Buffer,IO_BUFFER_SIZE);
  359.         Timer_Start(MyWindow);
  360.         for (t=0;t<200;t++)
  361.         {
  362.             Seek(bigfile,0L,OFFSET_BEGINNING);
  363.             Read(bigfile,Buffer,SEEK_READ_SIZE);
  364.             count++;
  365.  
  366.             pos=Seek(bigfile,-(2*SEEK_READ_SIZE),OFFSET_END);
  367.             Read(bigfile,Buffer,SEEK_READ_SIZE);
  368.             count++;
  369.  
  370.             Seek(bigfile,-(pos>>1),OFFSET_CURRENT);
  371.             Read(bigfile,Buffer,SEEK_READ_SIZE);
  372.             count++;
  373.         }
  374.         Timer_Stop(MyWindow,RESULTS_SEEK_READ,count);
  375.         Close(bigfile);
  376.         DeleteFile(FileNameRoot);
  377.     }
  378. }
  379.  
  380. /*
  381.  * This does the testing at a set buffer size...
  382.  */
  383. SHORT Do_File_Test(LONG BufSize,struct MyWindow *MyWindow,UBYTE *Buffer,SHORT ResultNum)
  384. {
  385. register    SHORT    flag=TRUE;
  386. register    SHORT    t;
  387. register    SHORT    loop;
  388. register    LONG    count;
  389. register    LONG    numblocks;
  390. register    BPTR    bigfile;
  391.  
  392.     if (bigfile=Open(FileNameRoot,MODE_NEWFILE))
  393.     {
  394.         numblocks=IO_BUFFER_SIZE/BufSize;
  395.         if (flag&=Check_Quit(MyWindow))
  396.         {
  397.             count=0;
  398.             Set_Testing(ResultNum,MyWindow);
  399.             Timer_Start(MyWindow);
  400.             for (t=0;t<(1<<(MyWindow->TestFlag));t++)
  401.             {
  402.                 Close(bigfile);
  403.                 bigfile=Open(FileNameRoot,MODE_NEWFILE);
  404.                 for (loop=0;loop<numblocks;loop++) count+=Write(bigfile,Buffer,BufSize);
  405.             }
  406.             Timer_Stop(MyWindow,ResultNum++,count);
  407.         }
  408.         if (flag&=Check_Quit(MyWindow))
  409.         {
  410.             count=0;
  411.             Set_Testing(ResultNum,MyWindow);
  412.             Timer_Start(MyWindow);
  413.             for (t=0;t<(2<<(MyWindow->TestFlag));t++)
  414.             {
  415.                 Seek(bigfile,NULL,OFFSET_BEGINNING);
  416.                 for (loop=0;loop<numblocks;loop++) count+=Write(bigfile,Buffer,BufSize);
  417.             }
  418.             Timer_Stop(MyWindow,ResultNum++,count);
  419.         }
  420.         if (flag&=Check_Quit(MyWindow))
  421.         {
  422.             count=0;
  423.             Set_Testing(ResultNum,MyWindow);
  424.             Timer_Start(MyWindow);
  425.             for (t=0;t<(3<<(MyWindow->TestFlag));t++)
  426.             {
  427.                 Seek(bigfile,NULL,OFFSET_BEGINNING);
  428.                 for (loop=0;loop<numblocks;loop++) count+=Read(bigfile,Buffer,BufSize);
  429.             }
  430.             Timer_Stop(MyWindow,ResultNum++,count);
  431.         }
  432.         Close(bigfile);
  433.         DeleteFile(FileNameRoot);
  434.     }
  435.     return(flag);
  436. }
  437.  
  438. /*
  439.  * This is the master test routine...  It calles the ones above...
  440.  */
  441. VOID Do_Disk_Test(struct MyWindow *MyWindow)
  442. {
  443. register        BPTR    lock;
  444. register        BPTR    mydir;
  445. register        SHORT    flag=TRUE;
  446. register        UBYTE    *Buffer;
  447. register        SHORT    loop;
  448. register    struct    Gadget    *gad;
  449.  
  450.     for (loop=0;loop<NUM_GADGETS;loop++)
  451.     {
  452.         gad=&(MyWindow->MyGadgets[loop].Gadget);
  453.         RemoveGadget(MyWindow->Window,gad);
  454.         gad->Flags|=GADGDISABLED;
  455.         AddGadget(MyWindow->Window,gad,NULL);
  456.         RefreshGList(gad,MyWindow->Window,NULL,1L);
  457.     }
  458.  
  459.     if (lock=Lock(MyWindow->DeviceName,ACCESS_READ))
  460.     {
  461.         lock=CurrentDir(lock);
  462.         if (mydir=CreateDir(DirectoryName))
  463.         {
  464.             mydir=CurrentDir(mydir);
  465.  
  466.             for (loop=0;loop<NUM_RESULTS;loop++)
  467.             {
  468.                 Clear_Entry(MyWindow->MyResults[loop].text);
  469.             }
  470.             RefreshGList(&(MyWindow->Detail),MyWindow->Window,NULL,1L);
  471.  
  472.             Stress_On(MyWindow);
  473.  
  474.             if (flag&=Check_Quit(MyWindow))
  475.             {
  476.                 Do_FileCreate_Test(MyWindow);
  477.                 if (flag&=Check_Quit(MyWindow)) Do_OpenClose_Test(MyWindow);
  478.                 if (flag&=Check_Quit(MyWindow)) Do_DirScan_Test(MyWindow);
  479.                 Do_FileDelete_Test(MyWindow);
  480.             }
  481.             if (Buffer=AllocMem(IO_BUFFER_SIZE,MEMF_PUBLIC))
  482.             {
  483.                 if (flag&=Check_Quit(MyWindow)) Do_SeekRead_Test(MyWindow,Buffer);
  484.  
  485.                 if (flag&=Check_Quit(MyWindow)) flag&=Do_File_Test(512L,MyWindow,Buffer,RESULTS_512_CREATE);
  486.                 if (flag&=Check_Quit(MyWindow)) flag&=Do_File_Test(4096L,MyWindow,Buffer,RESULTS_4096_CREATE);
  487.                 if (flag&=Check_Quit(MyWindow)) flag&=Do_File_Test(32768L,MyWindow,Buffer,RESULTS_32768_CREATE);
  488.                 if (flag&=Check_Quit(MyWindow)) flag&=Do_File_Test(262144L,MyWindow,Buffer,RESULTS_262144_CREATE);
  489.  
  490.                 FreeMem(Buffer,IO_BUFFER_SIZE);
  491.             }
  492.  
  493.             Stress_Off(MyWindow);
  494.  
  495.             mydir=CurrentDir(mydir);
  496.             UnLock(mydir);
  497.             DeleteFile(DirectoryName);
  498.         }
  499.         else
  500.         {    /* Tell user he messed up... */
  501.             TellUser(MyWindow,ErrorText1);
  502.         }
  503.  
  504.         lock=CurrentDir(lock);
  505.         UnLock(lock);
  506.     }
  507.     else
  508.     {    /* Tell user he messed up... */
  509.         TellUser(MyWindow,ErrorText2);
  510.     }
  511.  
  512.     for (loop=0;loop<NUM_GADGETS;loop++)
  513.     {
  514.         gad=&(MyWindow->MyGadgets[loop].Gadget);
  515.         RemoveGadget(MyWindow->Window,gad);
  516.         gad->Flags&=~GADGDISABLED;
  517.         AddGadget(MyWindow->Window,gad,NULL);
  518.     }
  519.     RefreshGadgets(gad,MyWindow->Window,NULL);
  520. }
  521.  
  522. /*
  523.  * This function will open the file, append to the end of it the
  524.  * test results and close it...
  525.  */
  526. VOID Save_To_File(struct MyWindow *MyWindow)
  527. {
  528. register    BPTR    TheFile;
  529.  
  530.  
  531.     TheFile=Open(ResultFile,MODE_OLDFILE);
  532.     if (!TheFile) TheFile=Open(ResultFile,MODE_NEWFILE);
  533.     if (TheFile)
  534.     {
  535.         Seek(TheFile,0L,OFFSET_END);
  536.         Write_Results(MyWindow,TheFile);
  537.         Close(TheFile);
  538.     }
  539.     else
  540.     {    /* Tell the user the file did not open... */
  541.         TellUser(MyWindow,ErrorText3);
  542.     }
  543. }
  544.  
  545. /*
  546.  * This function will open the printer, append to the end of it the
  547.  * test results and close it...
  548.  */
  549. VOID Save_To_Printer(struct MyWindow *MyWindow)
  550. {
  551. register    BPTR    TheFile;
  552.  
  553.     if (TheFile=Open(PrinterFile,MODE_NEWFILE))
  554.     {
  555.         Write_Results(MyWindow,TheFile);
  556.         Close(TheFile);
  557.     }
  558.     else
  559.     {    /* Tell the user the file did not open... */
  560.         TellUser(MyWindow,ErrorText4);
  561.     }
  562. }
  563.  
  564. VOID main(VOID)
  565. {
  566. register    struct    MyWindow    *MyWindow;
  567. register    struct    Window        *Window;
  568. register    struct    IntuiMessage    *msg;
  569. register    struct    Gadget        *gad;
  570. register    struct    timerequest    *Time_Req;
  571. register        SHORT        QuitFlag=0;
  572. register    struct    Process        *pr;
  573. register        APTR        Old_WindowPtr;
  574. register        SHORT        loop;
  575. register        LONG        oldpri;
  576.         struct    RenderInfo    RenderInfo;
  577.  
  578.     pr=(struct Process *)FindTask(NULL);
  579.     Old_WindowPtr=pr->pr_WindowPtr;
  580.     pr->pr_WindowPtr=(APTR)(-1);
  581.     oldpri=SetTaskPri((struct Task *)pr,1L);
  582.  
  583.     if (IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",33L))
  584.     {
  585.         if (GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",33L))
  586.         {
  587.             FillIn_RenderInfo(&RenderInfo);
  588.             if (MyWindow=OpenMyWindow(&RenderInfo))
  589.             {
  590.                 Window=MyWindow->Window;
  591.                 Time_Req=&(MyWindow->TimeReq);
  592.                 if (!OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)Time_Req,NULL))
  593.                 {
  594.                     Time_Req->tr_node.io_Message.mn_ReplyPort=Window->UserPort;
  595.                     TimerBase=(struct Library *)Time_Req->tr_node.io_Device;
  596.                     while (!QuitFlag)
  597.                     {
  598.                         WaitPort(Window->UserPort);
  599.                         if (msg=(struct IntuiMessage *)GetMsg(Window->UserPort))
  600.                         {
  601.                             if (msg->Class==CLOSEWINDOW) QuitFlag=TRUE;
  602.                             else if (msg->Class==ACTIVEWINDOW) ActivateGadget(&(MyWindow->DeviceGadget),Window,NULL);
  603.                             else if (msg->Class==GADGETDOWN)
  604.                             {
  605.                                 gad=(struct Gadget *)msg->IAddress;
  606.                                 if (gad->Flags & SELECTED)
  607.                                 {
  608.                                     MyWindow->TestFlag=gad->GadgetID;
  609.                                     for (loop=0;loop<3;loop++)
  610.                                     {
  611.                                         gad=&(MyWindow->MyGadgets[loop].Gadget);
  612.                                         if (MyWindow->TestFlag!=gad->GadgetID)
  613.                                         {
  614.                                             if (gad->Flags & SELECTED)
  615.                                             {
  616.                                                 RemoveGadget(Window,gad);
  617.                                                 gad->Flags&=~SELECTED;
  618.                                                 AddGadget(Window,gad,NULL);
  619.                                                 RefreshGList(gad,Window,NULL,1L);
  620.                                             }
  621.                                         }
  622.                                     }
  623.                                 }
  624.                                 else
  625.                                 {
  626.                                     RemoveGadget(Window,gad);
  627.                                     gad->Flags|=SELECTED;
  628.                                     AddGadget(Window,gad,NULL);
  629.                                     RefreshGList(gad,Window,NULL,1L);
  630.                                 }
  631.                             }
  632.                             else if (msg->Class==GADGETUP)
  633.                             {
  634.                                 SetWait(Window);
  635.                                 gad=(struct Gadget *)msg->IAddress;
  636.                                 switch (gad->GadgetID)
  637.                                 {
  638.                                 case GADGET_STRING:    ActivateGadget((struct Gadget *)gad->UserData,Window,NULL);
  639.                                             break;
  640.                                 case GADGET_START:    Do_Disk_Test(MyWindow);
  641.                                             break;
  642.                                 case GADGET_SAVE:    Save_To_File(MyWindow);
  643.                                             break;
  644.                                 case GADGET_PRINT:    Save_To_Printer(MyWindow);
  645.                                             break;
  646.                                 }
  647.                                 ClearWait(Window);
  648.                             }
  649.                             ReplyMsg((struct Message *)msg);
  650.                         }
  651.                     }
  652.                     CloseDevice((struct IORequest *)Time_Req);
  653.                 }
  654.                 CloseMyWindow(MyWindow);
  655.             }
  656.             CloseLibrary((struct Library *)GfxBase);
  657.         }
  658.         CloseLibrary((struct Library *)IntuitionBase);
  659.     }
  660.     oldpri=SetTaskPri((struct Task *)pr,oldpri);
  661.     pr->pr_WindowPtr=Old_WindowPtr;
  662. }
  663.