/* * DiskSpeed v1.0 * by * Michael Sinz * * Copyright (c) 1989 by MKSoft Development * * * Yes, this is yet another disk speed testing program, but with a few * differences. It was designed to give the most accurate results of the * true disk performance in the system. For this reason many of * DiskSpeed's results may look either lower or higher than current disk * performance tests. * * This program was thrown together in a few hours because I needed more * accurate and consistant results for disk performance as seen from the * application's standpoint. This program has now served its purpose and * I am now giving it to the rest of the Amiga world to play with as long * as all of the files remain together in unmodified form. (That is, the * files DiskSpeed, DiskSpeed.info, DiskSpeed.c, DiskSpeed.doc, and * MakeFile) * ****************************************************************************** * * * Reading legal mush can turn your bain into guacamole! * * * * So here is some of that legal mush: * * * * Permission is hereby granted to distribute this program's source * * executable, and documentation for non-comercial purposes, so long as the * * copyright notices are not removed from the sources, executable or * * documentation. This program may not be distributed for a profit without * * the express written consent of the author Michael Sinz. * * * * This program is not in the public domain. * * * * Fred Fish is expressly granted permission to distribute this program's * * source and executable as part of the "Fred Fish freely redistributable * * Amiga software library." * * * * Permission is expressly granted for this program and it's source to be * * distributed as part of the Amicus Amiga software disks, and the * * First Amiga User Group's Hot Mix disks. * * * ****************************************************************************** */ #include #include #include #include #include #include #include #include extern struct IntuitionBase *IntuitionBase; struct Library *TimerBase; #define TIMESCALER 256L #define SEEK_READ_SIZE 64L #define REQ_GAD 7 #define TEXT_BUFFER_SIZE 1024L static char FileUnit[8] ="files/s"; static char Text1[8] ="bytes/s"; static char Text2[12] ="32768 byte:"; static char Text3[11] ="4096 byte:"; static char Text4[10] ="512 byte:"; static char Text5[16] ="Raw Write Speed"; static char Text6[15] ="Raw Read Speed"; static char Text7[13] ="Seek & Read:"; static char Text8[16] ="Directory Scan:"; static char Text9[13] ="File Delete:"; static char Text10[13] ="File Create:"; static char Text11[7] ="Drive:"; static char MenuText1[12] ="Version 1.0"; static char MenuText2[17] ="Copyright © 1989"; static char MenuText3[16] ="By Michael Sinz"; static char MenuText4[5] ="Test"; static char MenuText5[5] ="Save"; static char MenuText6[6] ="Print"; static char MenuText7[23] ="MKSoft Disk Speed Test"; static char MenuText8[8] ="Project"; static char MenuText9[5] ="Quit"; static char ErrorText1[28] ="Can't create test directory"; static char ErrorText2[16] ="Bad device name"; static char ErrorText3[24] ="Can't open results file"; static char ErrorText4[19] ="Can't open printer"; static char WindowText[60] ="Disk Speed Test 1.0 Copyright © 1989 by MKSoft Development"; static char WorkingText[12] =" Working..."; static char PrinterFile[5] ="PRT:"; static char ResultFile[18] ="DiskSpeed.Results"; static char DirectoryName[22] =" Disk Test Directory "; static char FileNameRoot[22] =" -- DiskTest File -- "; static char File_Create[12]; static char File_Delete[12]; static char Directory_Scan[12]; static char Seek_And_Read[12]; static char Read_512[12]; static char Read_4096[12]; static char Read_32768[12]; static char Write_512[12]; static char Write_4096[12]; static char Write_32768[12]; static UBYTE Device[32]; static char fontnam[11] ="topaz.font"; static struct TextAttr TOPAZ60 ={fontnam,TOPAZ_SIXTY,0,0}; static struct TextAttr TOPAZ80 ={fontnam,TOPAZ_EIGHTY,0,0}; static SHORT BorderVectors1[10] ={0,0,230,0,230,40,0,40,0,0}; static SHORT BorderVectors[10] ={0,0,177,0,177,9,0,9,0,0}; static struct Border Border6 ={4-56,24-13,1,0,JAM1,5,BorderVectors1,NULL}; static struct Border Border5 ={5-56,25-13,2,0,JAM1,5,BorderVectors1,&Border6}; static struct Border Border4 ={4-56,67-13,1,0,JAM1,5,BorderVectors1,&Border5}; static struct Border Border3 ={5-56,68-13,2,0,JAM1,5,BorderVectors1,&Border4}; static struct Border Border2 ={4-56,111-13,1,0,JAM1,5,BorderVectors1,&Border3}; static struct Border Border1 ={5-56,112-13,2,0,JAM1,5,BorderVectors1,&Border2}; static struct Border Border ={-1,-1,1,0,JAM1,5,BorderVectors,&Border1}; static struct IntuiText IText25 ={1,0,JAM2,48,129,&TOPAZ60,Write_32768,NULL}; static struct IntuiText IText24 ={1,0,JAM2,48,120,&TOPAZ60,Write_4096,&IText25}; static struct IntuiText IText23 ={1,0,JAM2,48,111,&TOPAZ60,Write_512,&IText24}; static struct IntuiText IText22 ={1,0,JAM2,48,85,&TOPAZ60,Read_32768,&IText23}; static struct IntuiText IText21 ={1,0,JAM2,48,76,&TOPAZ60,Read_4096,&IText22}; static struct IntuiText IText20 ={1,0,JAM2,48,67,&TOPAZ60,Read_512,&IText21}; static struct IntuiText IText19 ={1,0,JAM2,78,41,&TOPAZ80,Seek_And_Read,&IText20}; static struct IntuiText IText18 ={1,0,JAM2,78,23,&TOPAZ80,Directory_Scan,&IText19}; static struct IntuiText IText17 ={1,0,JAM2,78,32,&TOPAZ80,File_Delete,&IText18}; static struct IntuiText IText16 ={1,0,JAM2,78,14,&TOPAZ80,File_Create,&IText17}; static struct IntuiText IText15 ={3,0,JAM2,120,101,&TOPAZ80,Text1,&IText16}; static struct IntuiText IText14 ={3,0,JAM2,120,57,&TOPAZ80,Text1,&IText15}; static struct IntuiText IText13 ={1,0,JAM2,-49,129,&TOPAZ80,Text2,&IText14}; static struct IntuiText IText12 ={1,0,JAM2,-41,120,&TOPAZ80,Text3,&IText13}; static struct IntuiText IText11 ={1,0,JAM2,-33,111,&TOPAZ80,Text4,&IText12}; static struct IntuiText IText10 ={1,0,JAM2,-49,101,&TOPAZ60,Text5,&IText11}; static struct IntuiText IText9 ={1,0,JAM2,-49,85,&TOPAZ80,Text2,&IText10}; static struct IntuiText IText8 ={1,0,JAM2,-41,76,&TOPAZ80,Text3,&IText9}; static struct IntuiText IText7 ={1,0,JAM2,-33,67,&TOPAZ80,Text4,&IText8}; static struct IntuiText IText6 ={1,0,JAM2,-49,57,&TOPAZ60,Text6,&IText7}; static struct IntuiText IText5 ={1,0,JAM2,-50,41,&TOPAZ80,Text7,&IText6}; static struct IntuiText IText4 ={1,0,JAM2,-49,23,&TOPAZ80,Text8,&IText5}; static struct IntuiText IText3 ={1,0,JAM2,-49,32,&TOPAZ80,Text9,&IText4}; static struct IntuiText IText2 ={1,0,JAM2,-49,14,&TOPAZ80,Text10,&IText3}; static struct IntuiText IText1 ={1,0,JAM2,-50,0,&TOPAZ80,Text11,&IText2}; static struct IntuiText MText1 ={3,1,COMPLEMENT,61,1,&TOPAZ80,MenuText1,NULL}; static struct IntuiText MText2 ={3,1,COMPLEMENT,41,1,&TOPAZ80,MenuText2,NULL}; static struct IntuiText MText3 ={3,1,COMPLEMENT,45,1,&TOPAZ80,MenuText3,NULL}; static struct IntuiText MText4 ={3,1,COMPLEMENT,0,1,&TOPAZ80,MenuText4,NULL}; static struct IntuiText MText5 ={3,1,COMPLEMENT,0,1,&TOPAZ80,MenuText5,NULL}; static struct IntuiText MText6 ={3,1,COMPLEMENT,0,1,&TOPAZ80,MenuText6,NULL}; static struct IntuiText MText7 ={3,1,COMPLEMENT,0,1,&TOPAZ80,MenuText9,NULL}; static struct StringInfo GadgetSInfo ={Device,NULL,0,31,0,0,0,0,0,0,0,0,NULL}; static struct Gadget MyGadget ={NULL,56,13,176,8,NULL,RELVERIFY,STRGADGET,(APTR)&Border,NULL,&IText1,NULL,(APTR)&GadgetSInfo,NULL,NULL}; static struct MenuItem MenuItem3 ={NULL,0,20,216,10,ITEMTEXT|ITEMENABLED|HIGHNONE,0,(APTR)&MText1,NULL,NULL,NULL,MENUNULL}; static struct MenuItem MenuItem2 ={&MenuItem3,0,10,216,10,ITEMTEXT|ITEMENABLED|HIGHNONE,0,(APTR)&MText2,NULL,NULL,NULL,MENUNULL}; static struct MenuItem MenuItem1 ={&MenuItem2,0,0,216,10,ITEMTEXT|ITEMENABLED|HIGHNONE,0,(APTR)&MText3,NULL,NULL,NULL,MENUNULL}; static struct MenuItem MenuItem7 ={NULL,0,45,80,10,COMMSEQ|ITEMTEXT|ITEMENABLED|HIGHCOMP,0,(APTR)&MText7,NULL,'Q',NULL,MENUNULL}; static struct MenuItem MenuItem6 ={&MenuItem7,0,30,80,10,COMMSEQ|ITEMTEXT|ITEMENABLED|HIGHCOMP,0,(APTR)&MText6,NULL,'P',NULL,MENUNULL}; static struct MenuItem MenuItem5 ={&MenuItem6,0,15,80,10,COMMSEQ|ITEMTEXT|ITEMENABLED|HIGHCOMP,0,(APTR)&MText5,NULL,'S',NULL,MENUNULL}; static struct MenuItem MenuItem4 ={&MenuItem5,0,0,80,10,COMMSEQ|ITEMTEXT|ITEMENABLED|HIGHCOMP,0,(APTR)&MText4,NULL,'T',NULL,MENUNULL}; static struct Menu Menu2 ={NULL,80,0,220,0,MENUENABLED,MenuText7,&MenuItem1}; static struct Menu MyMenu ={&Menu2,0,0,70,0,MENUENABLED,MenuText8,&MenuItem4}; static struct NewWindow NewWindowStructure ={110,11,240,156,0,1,GADGETUP|CLOSEWINDOW|ACTIVEWINDOW|MENUPICK,WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE|ACTIVATE|NOCAREREFRESH,&MyGadget,NULL,WindowText,NULL,NULL,0,0,0,0,WBENCHSCREEN}; static SHORT MyReqVec[10] ={0,0, 0,40, 231,40, 231,0, 0,0}; static struct Border MyReqBorder ={0,0,2,0,JAM1,5,MyReqVec,NULL}; static struct IntuiText MyReqText ={0,1,JAM1,0,16,&TOPAZ80,NULL,NULL}; static struct Gadget MyReqGadget ={NULL,0,0,232,41,GADGHCOMP,RELVERIFY,BOOLGADGET|REQGADGET,(APTR)&MyReqBorder,NULL,&MyReqText,NULL,NULL,REQ_GAD,NULL}; /* * This does a requester on the window to tell the user something... */ VOID TellUser(struct Window *Window,char *Text) { register struct Requester *myReq; register struct IntuiMessage *msg; register SHORT flag=TRUE; if (myReq=AllocMem(sizeof(struct Requester),MEMF_PUBLIC|MEMF_CLEAR)) { myReq->LeftEdge=3; myReq->TopEdge=24; myReq->Width=232; myReq->Height=41; myReq->BackFill=1; /* Pen colour 1 */ myReq->ReqGadget=&MyReqGadget; MyReqText.LeftEdge=116-(4*strlen(Text)); MyReqText.IText=Text; Request(myReq,Window); while (flag) { WaitPort(Window->UserPort); while (msg=(struct IntuiMessage *)GetMsg(Window->UserPort)) { if (msg->Class==GADGETUP) { if (((struct Gadget *)(msg->IAddress))->GadgetID==REQ_GAD) flag=FALSE; } ReplyMsg((struct Message *)msg); } } EndRequest(myReq,Window); FreeMem(myReq,sizeof(struct Requester)); } } /* * Returns FALSE if the user clicked on the CLOSE gadget... */ SHORT Check_Quit(struct Window *Window) { register struct IntuiMessage *msg; register SHORT flag=TRUE; while(msg=(struct IntuiMessage *)GetMsg(Window->UserPort)) { if (msg->Class==CLOSEWINDOW) flag=FALSE; ReplyMsg((struct Message *)msg); } return(flag); } /* * Clears a string entry to spaces... */ VOID Clear_Entry(char *String) { register SHORT t; for (t=0;t<11;t++) String[t]=' '; String[11]='\0'; } /* * Sets a string entry to the value passed and does a RefreshGadgets() * to display it... */ VOID Set_Entry(char *String,LONG Value,struct Window *Window) { register SHORT t; register SHORT tmp; t=11; while (Value) { tmp=Value%10; Value=Value/10; String[--t]=(char)(tmp)+'0'; } if (!String[t]) String[--t]='0'; RefreshGadgets(&MyGadget,Window,NULL); } /* * This gets the starting time... */ VOID Timer_Start(struct Window *Window) { register struct timerequest *Time_Req; Time_Req=(struct timerequest *)Window->UserData; Time_Req->tr_node.io_Command=TR_GETSYSTIME; Time_Req->tr_node.io_Flags=IOF_QUICK; DoIO((struct IORequest *)Time_Req); } /* * This gets the ending time and finds out what the per second speed is... * It also does a RefreshGadgets() to display the text... */ VOID Timer_Stop(struct Window *Window,char *Text,LONG Number) { register struct timerequest *Time_Req; register LONG Value; struct timeval StartTime; Time_Req=(struct timerequest *)Window->UserData; StartTime=Time_Req->tr_time; /* Store start time... */ Time_Req->tr_node.io_Command=TR_GETSYSTIME; Time_Req->tr_node.io_Flags=IOF_QUICK; DoIO((struct IORequest *)Time_Req); SubTime(&Time_Req->tr_time,&StartTime); /* Now calculate Value based on Number and the time... */ Value=(Number*TIMESCALER) / ( (Time_Req->tr_time.tv_secs*TIMESCALER) + (Time_Req->tr_time.tv_micro/(1000000L/TIMESCALER)) ); Set_Entry(Text,Value,Window); } /* * File create test... * This creates a bunch of files in our test directory... * The delete test deletes these files... */ VOID Do_FileCreate_Test(struct Window *Window) { register char *t1; register char *t2; register BPTR file; register LONG count=0; t1=FileNameRoot+1; t2=t1+1; Timer_Start(Window); for (*t1='A';*t1<'Q';(*t1)++) for (*t2='A';*t2<'Q';(*t2)++) { if (file=Open(FileNameRoot,MODE_NEWFILE)) Close(file); count++; } Timer_Stop(Window,File_Create,count); } /* * Directory scan test... This is done by scanning the directory we * just created in the create test... (Twice...) */ VOID Do_DirScan_Test(struct Window *Window) { register struct FileInfoBlock *FIB; register BPTR lock; register LONG count=0; lock=CurrentDir(NULL); /* Get our directory lock... */ if (FIB=AllocMem(sizeof(struct FileInfoBlock),MEMF_PUBLIC)) { Timer_Start(Window); Examine(lock,FIB); while (ExNext(lock,FIB)) count++; Examine(lock,FIB); while (ExNext(lock,FIB)) count++; Timer_Stop(Window,Directory_Scan,count); FreeMem(FIB,sizeof(struct FileInfoBlock)); } CurrentDir(lock); /* Return the locked directory... */ } /* * File delete test... We delete the files created in the create test... */ VOID Do_FileDelete_Test(struct Window *Window) { register char *t1; register char *t2; register LONG count=0; t1=FileNameRoot+1; t2=t1+1; Timer_Start(Window); for (*t1='A';*t1<'Q';(*t1)++) for (*t2='A';*t2<'Q';(*t2)++) { DeleteFile(FileNameRoot); count++; } Timer_Stop(Window,File_Delete,count); } /* * This does the seek/read test... */ VOID Do_SeekRead_Test(struct Window *Window,char *Buffer,BPTR bigfile) { register short t; register LONG count=0; register LONG pos; Timer_Start(Window); for (t=0;t<150;t++) { Seek(bigfile,0L,OFFSET_BEGINNING); Read(bigfile,Buffer,SEEK_READ_SIZE); count++; pos=Seek(bigfile,-(2*SEEK_READ_SIZE),OFFSET_END); Read(bigfile,Buffer,SEEK_READ_SIZE); count++; Seek(bigfile,-(pos>>1),OFFSET_CURRENT); Read(bigfile,Buffer,SEEK_READ_SIZE); count++; } Timer_Stop(Window,Seek_And_Read,count); } /* * This routine does the write timings... * To reduce the number of Seek() commands, the complete file is written * multiple times in a loop... */ VOID Do_Write_Test(char *Text,LONG Size,struct Window *Window,char *Buffer,BPTR bigfile) { register short t; register short x; register LONG count=0; register LONG numread; numread=Seek(bigfile,0L,OFFSET_END)/Size; Timer_Start(Window); for (t=0;t<6;t++) { Seek(bigfile,0L,OFFSET_BEGINNING); for (x=0;x1) if (Write(bigfile,Buffer,32768L)<32768L) flag=FALSE; if (flag&=Check_Quit(Window)) Do_SeekRead_Test(Window,Buffer,bigfile); if (flag&=Check_Quit(Window)) Do_Read_Test(Read_512,512L,Window,Buffer,bigfile); if (flag&=Check_Quit(Window)) Do_Read_Test(Read_4096,4096L,Window,Buffer,bigfile); if (flag&=Check_Quit(Window)) Do_Read_Test(Read_32768,32768L,Window,Buffer,bigfile); if (flag&=Check_Quit(Window)) Do_Write_Test(Write_512,512L,Window,Buffer,bigfile); if (flag&=Check_Quit(Window)) Do_Write_Test(Write_4096,4096L,Window,Buffer,bigfile); if (flag&=Check_Quit(Window)) Do_Write_Test(Write_32768,32768L,Window,Buffer,bigfile); FreeMem(Buffer,32768L); } Close(bigfile); DeleteFile(FileNameRoot); } } mydir=CurrentDir(mydir); UnLock(mydir); DeleteFile(DirectoryName); } else { /* Tell user he messed up... */ TellUser(Window,ErrorText1); } lock=CurrentDir(lock); UnLock(lock); } else { /* Tell user he messed up... */ TellUser(Window,ErrorText2); } } /* * This define is for the Write_Results routine... */ #define MYCAT(z,y,x) for (y=x;*y;*z++=*y++) #define MYCATNEWLINE(x) *x++='\n' #define MYCATTAB(x) *x++='\t' #define MYCATSPACE(x) *x++=' ' /* * This routine builds a string of the results and then writes it to * the file passed... */ VOID Write_Results(BPTR TheFile) { register char *t; register char *h; register char *Buffer; if (t=Buffer=AllocMem(TEXT_BUFFER_SIZE,MEMF_PUBLIC|MEMF_CLEAR)) { /* Title and device name */ MYCATNEWLINE(t); MYCAT(t,h,WindowText); MYCATNEWLINE(t); MYCATNEWLINE(t); MYCAT(t,h,Text11); MYCATTAB(t); MYCAT(t,h,Device); MYCATNEWLINE(t); MYCATNEWLINE(t); /* File Create */ MYCAT(t,h,Text10); MYCATTAB(t); MYCAT(t,h,File_Create); MYCATSPACE(t); MYCAT(t,h,FileUnit); MYCATNEWLINE(t); /* File Delete */ MYCAT(t,h,Text9); MYCATTAB(t); MYCAT(t,h,File_Delete); MYCATSPACE(t); MYCAT(t,h,FileUnit); MYCATNEWLINE(t); MYCATNEWLINE(t); /* Directory Scan */ MYCAT(t,h,Text8); MYCATTAB(t); MYCAT(t,h,Directory_Scan); MYCATSPACE(t); MYCAT(t,h,FileUnit); MYCATNEWLINE(t); MYCATNEWLINE(t); /* Seek and Read */ MYCAT(t,h,Text7); MYCATTAB(t); MYCAT(t,h,Seek_And_Read); MYCATNEWLINE(t); MYCATNEWLINE(t); /* Read 512 */ MYCAT(t,h,Text6); MYCATTAB(t); MYCAT(t,h,Text4); MYCATTAB(t); MYCAT(t,h,Read_512); MYCATSPACE(t); MYCAT(t,h,Text1); MYCATNEWLINE(t); /* Read 4096 */ MYCAT(t,h,Text6); MYCATTAB(t); MYCAT(t,h,Text3); MYCATTAB(t); MYCAT(t,h,Read_4096); MYCATSPACE(t); MYCAT(t,h,Text1); MYCATNEWLINE(t); /* Read 32768 */ MYCAT(t,h,Text6); MYCATTAB(t); MYCAT(t,h,Text2); MYCATTAB(t); MYCAT(t,h,Read_32768); MYCATSPACE(t); MYCAT(t,h,Text1); MYCATNEWLINE(t); MYCATNEWLINE(t); /* Write 512 */ MYCAT(t,h,Text5); MYCATTAB(t); MYCAT(t,h,Text4); MYCATTAB(t); MYCAT(t,h,Write_512); MYCATSPACE(t); MYCAT(t,h,Text1); MYCATNEWLINE(t); /* Write 4096 */ MYCAT(t,h,Text5); MYCATTAB(t); MYCAT(t,h,Text3); MYCATTAB(t); MYCAT(t,h,Write_4096); MYCATSPACE(t); MYCAT(t,h,Text1); MYCATNEWLINE(t); /* Write 32768 */ MYCAT(t,h,Text5); MYCATTAB(t); MYCAT(t,h,Text2); MYCATTAB(t); MYCAT(t,h,Write_32768); MYCATSPACE(t); MYCAT(t,h,Text1); MYCATNEWLINE(t); /* End of buffer... */ MYCATNEWLINE(t); MYCATNEWLINE(t); /* Now, all we have to do is write the sucker... */ Write(TheFile,Buffer,t-Buffer); FreeMem(Buffer,TEXT_BUFFER_SIZE); } } /* * This function will open the file, append to the end of it the * test results and close it... */ VOID Save_To_File(struct Window *Window) { register BPTR TheFile; TheFile=Open(ResultFile,MODE_OLDFILE); if (!TheFile) TheFile=Open(ResultFile,MODE_NEWFILE); if (TheFile) { Seek(TheFile,0L,OFFSET_END); Write_Results(TheFile); Close(TheFile); } else { /* Tell the user the file did not open... */ TellUser(Window,ErrorText3); } } /* * This function will open the printer, append to the end of it the * test results and close it... */ VOID Save_To_Printer(struct Window *Window) { register BPTR TheFile; if (TheFile=Open(PrinterFile,MODE_NEWFILE)) { Seek(TheFile,0L,OFFSET_END); Write_Results(TheFile); Close(TheFile); } else { /* Tell the user the file did not open... */ TellUser(Window,ErrorText4); } } VOID main(VOID) { register struct Window *Window; register struct IntuiMessage *msg; register struct timerequest *Time_Req; register SHORT QuitFlag=0; register USHORT thismenu; register struct Process *pr; register APTR Old_WindowPtr; pr=(struct Process *)FindTask(NULL); Old_WindowPtr=pr->pr_WindowPtr; pr->pr_WindowPtr=(APTR)(-1); if (Time_Req=AllocMem(sizeof(struct timerequest),MEMF_PUBLIC|MEMF_CLEAR)) { if (IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",33L)) { if (!OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)Time_Req,NULL)) { Time_Req->tr_node.io_Message.mn_ReplyPort=&(pr->pr_MsgPort); TimerBase=(struct Library *)Time_Req->tr_node.io_Device; if (Window=OpenWindow(&NewWindowStructure)) { SetWindowTitles(Window,WindowText,WindowText); Window->UserData=(BYTE *)Time_Req; SetMenuStrip(Window,&MyMenu); while (!QuitFlag) { WaitPort(Window->UserPort); while (msg=(struct IntuiMessage *)GetMsg(Window->UserPort)) { if (msg->Class==CLOSEWINDOW) QuitFlag=TRUE; else if (msg->Class==ACTIVEWINDOW) ActivateGadget(&MyGadget,Window,NULL); else if (msg->Class==MENUPICK) { OffGadget(&MyGadget,Window,NULL); ClearMenuStrip(Window); SetWindowTitles(Window,WorkingText,WindowText); thismenu=msg->Code; while (MENUNULL!=thismenu) { if (0==MENUNUM(thismenu)) { switch (ITEMNUM(thismenu)) { case 0: /* Do disk test */ Do_Disk_Test(Window); break; case 1: /* Save result file */ Save_To_File(Window); break; case 2: /* Print result file */ Save_To_Printer(Window); break; case 3: /* Quit... */ QuitFlag=TRUE; break; } } thismenu=ItemAddress(&MyMenu,(long)thismenu)->NextSelect; } SetWindowTitles(Window,WindowText,WindowText); SetMenuStrip(Window,&MyMenu); OnGadget(&MyGadget,Window,NULL); } ReplyMsg((struct Message *)msg); } } ClearMenuStrip(Window); CloseWindow(Window); } CloseDevice((struct IORequest *)Time_Req); } CloseLibrary((struct Library *)IntuitionBase); } FreeMem(Time_Req,sizeof(struct timerequest)); } pr->pr_WindowPtr=Old_WindowPtr; }