/* dograf.c : subroutine to draw graph By Joel Swank September 3, 1988 Version 1.0 */ #include #include #include #include #include #include #include #include /************* * Hooks to the rest of the program *************/ extern char nodatamsg[]; extern char tempbuf[]; extern char filename[]; #define MenuList1 Menu1 extern struct Menu Menu1; extern struct Window *Wind; extern struct RastPort *rp; extern struct IntuiText oktxt; extern int numrecs; extern int fileread; /* save areas for graphing data */ int yrsave[1000]; /* save year of each entry */ float costsave[1000]; /* save averaged cost data of each entry */ float milesave[1000]; /* save averaged mile data of each entry */ float pricesave[1000]; /* save price data of each entry */ float odsave[1000]; /* save odometer data of each entry */ float rawcost[1000]; /* save cost data of each entry */ /* flags for which grafs to display */ extern int cpm; extern int ppg; extern int mpg; extern int syr; /* for requested start year */ extern int eyr; /* for requested end year */ /* Local data */ /* * Data describing the NEXT gadget * */ SHORT BorderVectorsM[] = { 0,0, 42,0, 42,15, 0,15, 0,0 }; struct Border BorderM = { -2,-1, /* XY origin relative to container TopLeft */ 1,2,JAM2, /* front pen, back pen and drawmode */ 5, /* number of XY vectors */ BorderVectorsM, /* pointer to XY vectors */ NULL /* next border in list */ }; struct IntuiText ITextM = { 1,2,JAM2, /* front and back text pens, drawmode and fill byte */ 5,4, /* XY origin relative to container TopLeft */ NULL, /* font pointer or NULL for default */ (UBYTE *)"NEXT", /* pointer to text */ NULL /* next IntuiText structure */ }; struct Gadget GadgetM = { NULL, /* next gadget */ 5,142, /* origin XY of hit box relative to window TopLeft */ 39,14, /* hit box width and height */ NULL, /* gadget flags */ RELVERIFY, /* activation flags */ BOOLGADGET, /* gadget type flags */ (APTR)&BorderM, /* gadget border or image to be rendered */ NULL, /* alternate imagery for selection */ &ITextM, /* first IntuiText structure */ 0L, /* gadget mutual-exclude long word */ NULL, /* SpecialInfo structure */ NULL, /* user-definable data */ NULL /* pointer to user-definable data */ }; /* * Data describing the DONE gadget * */ SHORT BorderVectorsM1[] = { 0,0, 42,0, 42,15, 0,15, 0,0 }; struct Border BorderM1 = { -2,-1, /* XY origin relative to container TopLeft */ 1,2,JAM2, /* front pen, back pen and drawmode */ 5, /* number of XY vectors */ BorderVectorsM1, /* pointer to XY vectors */ NULL /* next border in list */ }; struct IntuiText ITextM1 = { 1,2,JAM2, /* front and back text pens, drawmode and fill byte */ 5,4, /* XY origin relative to container TopLeft */ NULL, /* font pointer or NULL for default */ (UBYTE *)"DONE", /* pointer to text */ NULL /* next IntuiText structure */ }; struct Gadget GadgetM1 = { NULL, /* next gadget */ 5,50, /* origin XY of hit box relative to window TopLeft */ 39,14, /* hit box width and height */ NULL, /* gadget flags */ RELVERIFY, /* activation flags */ BOOLGADGET, /* gadget type flags */ (APTR)&BorderM1, /* gadget border or image to be rendered */ NULL, /* alternate imagery for selection */ &ITextM1, /* first IntuiText structure */ 0L, /* gadget mutual-exclude long word */ NULL, /* SpecialInfo structure */ NULL, /* user-definable data */ NULL /* pointer to user-definable data */ }; float vertscale, horizscale; float max, min; /* main max and min */ float vsize; /* verticle range */ char textbuf[80]; char titlebuf[80]; int first = TRUE; int prevyear = 0; /* detecting year change */ long yval, xval; /* * draw_graph : draw requested graphs */ draw_graph() { long i; /* put up grafing gadgets */ AddGadget(Wind,&GadgetM,(USHORT) ~0); AddGadget(Wind,&GadgetM1,(USHORT) ~0); /* disable all menu items except quit & print */ for (i=0; i<6; i++) { if (i == 4) continue; /* skip print */ OffMenu(Wind, (USHORT) SHIFTITEM(i)); } /* add mouse reporting to window */ ReportMouse(TRUE,Wind); /* do requested graphs */ while (1) { if (ppg) { if (do_graph('p') == 0) break; } if (cpm) { if (do_graph('c') == 0) break; } if (mpg) { if (do_graph('m') == 0) break; } } /* delete mouse reporting from window */ ReportMouse(FALSE,Wind); /* remove grafing gadgets */ RemoveGadget(Wind,&GadgetM); RemoveGadget(Wind,&GadgetM1); /* enable all menu items */ for (i=0; i<7; i++) { if (!fileread) /* if no file read . . . */ { if (i=1) continue; /* skip draw and avgs */ if (i=2) continue; } OnMenu(Wind, (USHORT) SHIFTITEM(i)); } clr_grf(); } /* * do_graph : draw one graph from 'mode' and stored data */ do_graph(mode) char mode; /* what to graph, p=price/gal, m=mile/gal, c=cost/mile */ { struct IntuiMessage *msg; char *patptr; char *patpt2; int i, ystart = -1; int yend, year; int mousex, mx, my; register count; clr_grf(); /************************************************* Select data, and find max/min *************************************************/ max = 0; min = 1e10; for (count=0; count eyr) break; } if (syr != -1) { if (year < syr) continue; } if (ystart == -1) ystart = count; /* remenber first */ /* find the max and min */ switch (mode) { case 'c': if (costsave[count] > 0) { if (costsave[count] > max) max = costsave[count]; if (costsave[count] < min) min = costsave[count]; } break; case 'm': if(milesave[count] > 0) { if (milesave[count] > max) max = milesave[count]; if (milesave[count] < min) min = milesave[count]; } break; case 'p': if (pricesave[count] > max) max = pricesave[count]; if (pricesave[count] < min) min = pricesave[count]; break; } } yend = count; if (ystart == -1 || yend-ystart < 2) { AutoRequest(Wind,&nodatamsg,0L,&oktxt,0L,0L,300L,75L); return(0); } /************************************************* Calculate scale factors *************************************************/ switch (mode) { case 'c': strcpy(titlebuf,"Cents per Mile of Travel - File "); break; case 'm': strcpy(titlebuf,"Miles per Gallon of Gasoline - File "); break; case 'p': strcpy(titlebuf,"Dollars per Gallon of Gasoline - File "); break; } vsize = (max - min) *1.1; vertscale = 180.0/vsize; horizscale = 570.0/ (float) (yend-ystart); strcat(titlebuf,filename); SetWindowTitles(Wind,(UBYTE *) titlebuf, -1L); /* if (!wb) { printf("Vert scale = %f\n",vertscale); printf("Horiz scale = %f\n",horizscale); printf("Max = %f\n",max); printf("Min = %f\n",min); } */ /************************************************* draw axis and vertical labels *************************************************/ Move(rp,50L,15L); Draw(rp,50L,183L); Draw(rp,635,183L); Move(rp,50L,105L); Draw(rp,635,105L); switch (mode) { case 'c': patptr = "%5.2f"; patpt2 = "%5.2f cents/mi"; break; case 'm': patptr = "%5.2f"; patpt2 = "%5.2f mi/gal"; break; case 'p': patptr = "%5.3f"; patpt2 = "$%5.3f $/gal"; break; } /* dray Y axis labels */ Move(rp,5L,18L); sprintf(textbuf,patptr,min+vsize); Text(rp,(UBYTE *) textbuf, (long) strlen(textbuf)); Move(rp,5L,107L); sprintf(textbuf,patptr,min+vsize/2); Text(rp,(UBYTE *) textbuf, (long) strlen(textbuf)); Move(rp,5L,187L); sprintf(textbuf,patptr,min); Text(rp,(UBYTE *) textbuf, (long) strlen(textbuf)); /* draw min and max values */ Move(rp,65L,30L); sprintf(tempbuf,patpt2,max); strcpy(textbuf,"Maximum = "); strcat(textbuf,tempbuf); Text(rp,(UBYTE *) textbuf, (long) strlen(textbuf)); Move(rp,400L,170L); sprintf(tempbuf,patpt2,min); strcpy(textbuf,"Minimum = "); strcat(textbuf,tempbuf); Text(rp,(UBYTE *) textbuf, (long) strlen(textbuf)); /************************************************* MAIN Drawing Routine *************************************************/ first = TRUE; prevyear = 0; for (count=ystart ; count< yend; count++) { year = yrsave[count]; switch (mode) { case 'c': if (costsave[count] == 0) yval = 0; else yval = 180L - (long) ((costsave[count] - min) * vertscale); break; case 'm': if (milesave[count] == 0) yval = 0; else yval = 180L - (long) ((milesave[count] - min) * vertscale); break; case 'p': yval = 180L - (long) ((pricesave[count] - min) * vertscale); break; } xval = (long) ( ((float) (count-ystart)) * horizscale)+50; if (yval != 0) /* don't draw zero entrys */ { if (first) { Move(rp,xval, yval); first = FALSE; } else Draw(rp,xval, yval); } /* printf("X=%ld, y=%ld\n",xval,yval); */ if (year != prevyear) /* draw horiz label */ { sprintf(textbuf,"%2d",year%100); Move(rp,xval-TextLength(rp,textbuf, (long) strlen(textbuf))/2, 196L); Text(rp,(UBYTE *) textbuf, (long) strlen(textbuf)); Move(rp,xval,180L); /* tick marks */ Draw(rp,xval,186L); Move(rp,xval, yval); } prevyear = year; } /* redraw Gadgets */ RefreshGadgets(&GadgetM,Wind,0L); RefreshGadgets(&GadgetM1,Wind,0L); /************************************************* WAIT for Close, NEXT or DONE Gadget and manage the mouse reporting *************************************************/ while (1) { int menunum; struct MenuItem *item, *ItemAddress(); Wait( 1L << Wind->UserPort->mp_SigBit); /* wait on mesg */ while(msg = (struct IntuiMessage *) GetMsg(Wind->UserPort)) { switch(msg->Class) { case CLOSEWINDOW: ReplyMsg(msg); done(0); case GADGETUP: ReplyMsg(msg); if (msg->IAddress == &GadgetM) return(1); /* next graf */ if (msg->IAddress == &GadgetM1) return(0); /* next file */ continue; case MENUPICK: /* only print and quit are allowed */ menunum = msg->Code; ReplyMsg(msg); while (menunum != MENUNULL) { switch(ITEMNUM(menunum)) { case 4: do_print(); break; case 6: done(0); } item = ItemAddress(&MenuList1,menunum); menunum = item->NextSelect; } continue; case MOUSEMOVE: mx = msg->MouseX; my = msg->MouseY; ReplyMsg(msg); if (mx<50 || my>180) continue; /* off grafics area */ if (mx != mousex) /* if x has changed */ { int index; float val; mousex =mx; /* get data value for current mouse X */ index = (int) ( ((float) mx - 50) / horizscale) - ystart; if (index < ystart || index >= yend) continue; switch (mode) { case 'c': val = costsave[index]; break; case 'm': val = milesave[index]; break; case 'p': val = pricesave[index]; break; } /* Draw the value */ Move(rp,65L,20L); sprintf(tempbuf,patpt2,val); strcpy(textbuf,"Mouse @ "); strcat(textbuf,tempbuf); Text(rp,(UBYTE *) textbuf, (long) strlen(textbuf)); } continue; } ReplyMsg(msg); } } }