/* * GEARS : Bicycle gear ratio Calculator * * Version 1 * * by Joel Swank 9-19-89 * */ /********* INCLUDES ************************ */ #include #include #include #include #include #include #include "fio.h" /* Data in helpwin.h */ extern struct IntuiText prfailtxt ; extern struct IntuiText badfiletxt ; extern struct IntuiText fiofailtxt ; extern struct IntuiText winfailtxt ; extern struct IntuiText lockfailtxt ; extern struct IntuiText geartxt ; extern struct IntuiText infailtxt ; extern struct IntuiText infailtxt2 ; extern struct IntuiText oktxt ; extern struct IntuiText cantxt ; extern struct IntuiText retrytxt ; extern struct NewWindow NewWindowStructureHelp; extern struct NewWindow NewWindowStructure3; extern char gear_buff[]; /* Data in doargs.c */ extern char filename[]; /* Defines for setting/clearing GADGDISABLED flag */ #define OffGad(gad) (gad).Flags = gad.Flags | GADGDISABLED #define OnGad(gad) (gad).Flags = gad.Flags & ~(GADGDISABLED) #define OffMenu(item) (item).Flags = item.Flags & ~(CHECKED) #define OnMenu(item) (item).Flags = item.Flags | CHECKED extern struct IntuitionBase *IntuitionBase ; extern struct GfxBase *GfxBase ; extern struct DosLibrary *DosBase ; struct Screen *OpenScreen(); struct Screen *Sc = NULL; struct ViewPort vP; struct Window *wG = NULL; struct Window *wF = NULL; struct RastPort *rpG; struct IntuiMessage *message; /* the message from the IDCMP */ struct Window *OpenWindow(); void *OpenLibrary(); struct IntuiMessage *GetMsg(); struct MenuItem *ItemAddress(); struct FileIOSupport *FIOSupp = NULL; /* fileio support stuff */ struct FileIOSupport *GetFileIOSupport(); struct FileLock *Lock(); char save_title[] = "Select File to SAVE"; char load_title[] = "Select File to LOAD"; /* get the PowerWindows 2.0 code */ #include "gearscreen.h" /* internal data areas */ int front = 2; /* number of front gears */ int rear = 6; /* number of rear gears */ float ratios[21]; /* storage for ratios */ float front_gear[3];/* storage for front gears */ float rear_gear[7]; /* storage for rear gears */ int av[21]; /* indices for sort */ char cbuf[21][8]; /* storage for gear combos */ int count = 0; /* count of ratios */ int diameter = 27; /* wheel diameter from args */ long color[8]; /* savearea for colors */ struct ColorMap *cm; /* pointer to screen colors */ char rearmsg[] = "Bad Rear Gear: "; char frontmsg[] = "Bad Front Gear: "; main(argc,argv) int argc; char *argv[]; { UWORD code; ULONG class; APTR object; FILE *fp; /* Open the libraries */ IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 0L); if (IntuitionBase == NULL) { done(11); } GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0L); if (GfxBase == NULL) { done(10); } DosBase = (struct DosLibrary *)OpenLibrary("dos.library", 0); if (DosBase == NULL) { done(16); } /* Get the arguments */ filename[0] = '\0'; if (argc == 0) getWBargs(); else getCLIargs(argc,argv); Diameter_GadSInfo.LongInt = diameter; sprintf(Diameter_GadSIBuff,"%d",diameter); /* Open my screen */ Sc = OpenScreen(&NewScreenStructure); if ( Sc == NULL ) { done(15); } vP = Sc->ViewPort; LoadRGB4(&vP,&Palette,PaletteColorCount); /* tie windows to my screen */ NewWindowStructureHelp.Screen = Sc; NewWindowStructure3.Screen = Sc; NewWindowStructure1.Screen = Sc; wG = OpenWindow(&NewWindowStructure1); /* open main window */ if ( wG == NULL ) { done(12); } rpG = wG->RPort; /* get a rastport pointer for the window */ PrintIText(rpG,&IntuiTextList1,0L,0L); /* write window text */ SetMenuStrip(wG,&MenuList1); /* attach my Menu */ if (filename[0] != '\0') { while ((fp = fopen(filename,"r")) == NULL) { infailtxt2.IText = (UBYTE *) filename; if (AutoRequest(wG,&infailtxt,&retrytxt,&cantxt, 0L,0L,reqlen(filename),75L)) continue; } if (fp != NULL) { read_file(fp); fclose(fp); } } /* Wait for some User interaction */ while(1) { WaitPort(wG->UserPort); while( (message = (struct IntuiMessage *) GetMsg(wG->UserPort) ) != NULL) { code = message->Code; /* MENUNUM */ object = message->IAddress; /* Gadget */ class = message->Class; /* IDCMP Flags */ ReplyMsg(message); /* Free the sender */ switch (class) { case CLOSEWINDOW : done(0); /* close gadget clicked */ case GADGETUP: if (object == (APTR) &Calc_Gad) { calc_it(); display_it(); break; } /* add more gadget checks here */ break; case MENUPICK: /* menu selection made */ /* I get a NULL message whenever the user brings up the menu but doesn't select anything */ if (code != MENUNULL) do_pick((USHORT)code); break; } } } } /* * Cleanup and exit */ done(how) int how; { if (FIOSupp) ReleaseFileIO(FIOSupp); if (wG) ClearMenuStrip(wG); if (wG) CloseWindow(wG); if (Sc) CloseScreen(Sc); if (DosBase) CloseLibrary(DosBase); if (GfxBase != NULL) CloseLibrary(GfxBase); if (IntuitionBase != NULL) CloseLibrary(IntuitionBase); exit(how); /* exit codes * 0 User requested * 10 graphics lib open fail * 11 intuition lib open fail * 12 main window open fail * 13 _abort() called * 14 Bad CLI args * 15 Custom Screen open Fail * 16 Dos lib open fail */ } /* * do_pick : handle chain of menu selections */ do_pick(menunum) USHORT menunum; { struct MenuItem *item, *ItemAddress(); while (menunum != MENUNULL) { switch(MENUNUM(menunum)) { case 0: /* Project Menu */ switch(ITEMNUM(menunum)) { case 0: /* Load */ do_load(); break; case 1: /* Save */ do_save(); break; case 2: /* Print */ do_print(); break; case 3: /* Colors */ ClearMenuStrip(wG); DoColorWindow(Sc,170,15,0,TRUE); SetMenuStrip(wG,&MenuList1); /* re-attach my Menu */ break; case 4: /* Help */ help(); break; case 5: /* About */ about(); break; case 6: /* Quit */ done(0); } break; case 1: /* Gears Menu */ switch(ITEMNUM(menunum)) { case 0: /* Front Gear selection */ /* Three mutually excluded items. intuition keeps track, I have to enable/disable integer input gadgets and redraw the window */ switch(SUBNUM(menunum)) { case 0: /* 1 */ front = 1; break; case 1: /* 2 */ front = 2; break; case 2: /* 3 */ front = 3; break; } break; case 1: /* Rear Gear selection */ /* Five mutually excluded items. intuition keeps track, I have to enable/disable integer input gadgets and redraw the window */ switch(SUBNUM(menunum)) { case 0: /* 3 */ rear = 3; break; case 1: /* 4 */ rear = 4; break; case 2: /* 5 */ rear = 5; break; case 3: /* 6 */ rear = 6; break; case 4: /* 7 */ rear = 7; break; } break; } set_gads(); redraw_scr(); break; default: /* What's this garbage ? */ menunum = MENUNULL; } /* end switch MENUNUM */ /* Get chain to next selection. NextSelect contains another item when the user makes multiple menu selections */ item = ItemAddress(&MenuList1,(long) menunum); menunum = item->NextSelect; } } /* * Calculate and display gear table */ calc_it() { int i,j; if (!check_gears()) return; /* validate the gears */ count = 0; /* Calculate the ratios */ for (i=0; i 40.0) { sprintf(gear_buff,"%s%2.0f",rearmsg,rear_gear[i]); AutoRequest(wG,&geartxt,0L,&oktxt,0L,0L,300L,75L); return(FALSE); } for (i=0;i 80.0) { sprintf(gear_buff,"%s%2.0f",frontmsg,front_gear[i]); AutoRequest(wG,&geartxt,0L,&oktxt,0L,0L,300L,75L); return(FALSE); } return(TRUE); } /* * Set Disabled bit on all gear string gadgets */ set_gads() { if (front > 1) OnGad(Front2_Gad); else OffGad(Front2_Gad); if (front > 2) OnGad(Front3_Gad); else OffGad(Front3_Gad); if (rear > 3) OnGad(Rear4_Gad); else OffGad(Rear4_Gad); if (rear > 4) OnGad(Rear5_Gad); else OffGad(Rear5_Gad); if (rear > 5) OnGad(Rear6_Gad); else OffGad(Rear6_Gad); if (rear > 6) OnGad(Rear7_Gad); else OffGad(Rear7_Gad); } /* * Set the menus according to front and rear */ set_menus() { if (rear == 3) OnMenu(SubItem1); else OffMenu(SubItem1); if (rear == 4) OnMenu(SubItem2); else OffMenu(SubItem2); if (rear == 5) OnMenu(SubItem3); else OffMenu(SubItem3); if (rear == 6) OnMenu(SubItem4); else OffMenu(SubItem4); if (rear == 7) OnMenu(SubItem5); else OffMenu(SubItem5); if (front == 1) OnMenu(SubItem6); else OffMenu(SubItem6); if (front == 2) OnMenu(SubItem7); else OffMenu(SubItem7); if (front == 3) OnMenu(SubItem8); else OffMenu(SubItem8); } /* * Display ratios in main window * (Assumes calc_it has been done) */ #define XPOS 170 #define LINESIZE 9 char header[] = "Gear Wheel Size Spacing"; char disp_buff[100], temp_buff[30]; display_it() { int ypos = 20, i, j; SetAPen(rpG,7L); /* set draw color */ Move(rpG,XPOS,ypos); Text(rpG,header,sizeof(header)-1); ypos += LINESIZE; for (i=0; i0) { sprintf(temp_buff," %6.2f",ratios[j] - ratios[av[i-1]]); strcat(disp_buff,temp_buff); } if (i>1) { sprintf(temp_buff," %6.2f",ratios[j] - ratios[av[i-2]]); strcat(disp_buff,temp_buff); } if (i>2) { sprintf(temp_buff," %6.2f",ratios[j] - ratios[av[i-3]]); strcat(disp_buff,temp_buff); } } /* * Load data from an ASCII file */ do_load() { FILE *fp; select_file(0); if (filename[0] == '\0') return; while ((fp = fopen(filename,"r")) == NULL) { infailtxt2.IText = (UBYTE *) filename; if (AutoRequest(wG,&infailtxt,&retrytxt,&cantxt, 0L,0L,reqlen(filename),75L)) continue; return; } read_file(fp); fclose(fp); } /* * Read in data from open file */ read_file(fp) FILE *fp; { int i; char x; int fr = front; int re = rear; i = fscanf(fp,"%d, %d",&front,&rear); if (i != 2 || rear < 3 || rear >7 || front < 1 || front >3) { infailtxt2.IText = (UBYTE *) filename; AutoRequest(wG,&badfiletxt,0L,&oktxt,0L,0L,reqlen(filename),75L); front = fr; rear = re; return(FALSE); } fscanf(fp,", %d ,",&Diameter_GadSInfo.LongInt); sprintf(Diameter_GadSIBuff,"%d",Diameter_GadSInfo.LongInt); fscanf(fp,"%c",&x); if (x == 'm') inmm_Gad.Flags |= SELECTED; if (x == 'i') inmm_Gad.Flags &= ~SELECTED; for (i=0;iViewPort.ColorMap; if (cm) for (i = 0; i < 8; i++) fprintf(fp,",%d",GetRGB4(cm, (long) i)); fprintf(fp,"\n"); fclose(fp); } /* * Redraw Window */ redraw_scr() { RemoveGList(wG,&GadgetList1,-1L); /* remove all gadgets */ SetAPen(rpG,0L); /* clear the window */ RectFill(rpG,2L,11L,(long)(wG->Width-3),(long)(wG->Height-2)); AddGList(wG,&GadgetList1,0L,-1L,NULL); /* put back gadgets */ RefreshGList(&GadgetList1,wG,NULL,-1L); /* redraw the gadgets */ PrintIText(rpG,&IntuiTextList1,0L,0L); /* write window text */ SetAPen(rpG,7L); /* set draw color */ } /* * Select a file */ select_file(io) int io; { struct Window *OpenWindow(), *wF = NULL; struct FileLock *lock = NULL; ClearMenuStrip(wG); if (NULL == FIOSupp) if (NULL == (FIOSupp = GetFileIOSupport())) { AutoRequest(wG,&fiofailtxt,0L,&cantxt,0L,0L,300L,75L) ; SetMenuStrip(wG,&MenuList1); /* re-attach my Menu */ return; } /* set up title for file requester */ if (io == 0) FIOSupp->ReqTitle = (UBYTE *) load_title; else FIOSupp->ReqTitle = (UBYTE *) save_title; wF = OpenWindow(&NewWindowStructure3); /* open the window */ if ( wF == NULL ) { AutoRequest(wG,&winfailtxt,0L,&oktxt,0L,0L,300L,75L); SetMenuStrip(wG,&MenuList1); /* re-attach my Menu */ return; } filename[0] = '\0'; if (GetFileIOName(FIOSupp,wF)) BuildFileIOPathname(FIOSupp,filename); if (wF) CloseWindow(wF); if (lock) UnLock(lock); SetMenuStrip(wG,&MenuList1); /* attach my Menu */ } /* * Calculate size of requester needed for given filename */ reqlen(filename) char *filename; { int r; r = TextLength(rpG,filename,strlen(filename))+50; if (r < 300) r = 300; if (r > 640) r = 640; return (r) ; } /* * * Quick Sort routine. From Matt Dillon/Steve Drews Shell * */ QuickSort(av, n) int av[]; int n; { int b; if (n > 0) { b = QSplit(av, n); QuickSort(av, b); QuickSort(av+b+1, n - b - 1); } } /* * QSplit called as a second routine so I don't waste stack on QuickSort's * recursivness. */ QSplit(av, n) int av[]; int n; { int i, b; int element, scr; element = av[0]; for (b = 0, i = 1; i < n; ++i) { if (ratios[av[i]] < ratios[element]) { ++b; scr = av[i]; av[i] = av[b]; av[b] = scr; } } scr = av[0]; av[0] = av[b]; av[b] = scr; return (b); } #ifdef AZTEC_C _abort() { done(13); } #endif