/*========================================================================= Star4.c -- This module builds and submits a requester in response to the user's choice of 'Set Parameters' from the parameters menu of the Star Chart program. The requester lets the user modify the longitude, latitude, date, time and observed horizon for their observing location. Credits for Star Chart: Robert L. Hill of the Orange County, CA. Amiga Friends User Group wrote the original version of StarChart in AmigaBasic The star data and many of the main functions of this version are derived from that program. Ray R. Larson wrote the c version 1.0 of StarChart, 'intuitionizing' and enhancing the speed and functions of the original. Copyright (c) 1986 by Ray R. Larson This program may be freely distributed and copied, but may not be sold without the permission of the author. If you modify or enhance it, please include the above credits (and please send me a copy!). Ray R. Larson 6425 Central Ave. #304 El Cerrito, CA 94530 BitNet LARSON@UCBCMSA =========================================================================*/ /*------------Header file for all of the standard stuff----*/ /*-------------plus definitions of global structures-------*/ #include "star.h" /* Definitions for Gadget ID numbers (see Star3.c) */ #define LONGDEGGAD 0 #define LONGMINGAD 1 #define LATDEGGAD 2 #define YEARGAD 3 #define MONGAD 4 #define DAYGAD 5 #define HOURGAD 6 #define MINGAD 7 #define SECGAD 8 #define NORTHGAD 9 #define SOUTHGAD 10 #define CANGAD 11 #define OKGAD 12 /* another macro */ #define ABS(x) ((x<0)?(-(x)):(x)) /**************************************************************************** * Global Structures ***************************************************************************/ /* the newwindow structure used in GT */ extern struct NewWindow nw; extern struct Window *w; extern SHORT SecondsCount; extern struct ParamStruct Parms; extern SHORT Dd[],DSum[]; /* tables of days per month- in starglb.c */ /**************************************************************************** * External function definitions ***************************************************************************/ extern struct IntuiMessage *GetMsg(); /**************************************************************************** * Requester structure and global pointer to it's gadget list. ***************************************************************************/ struct Requester ParamRequester; struct ParamStruct workParms; extern struct Gadget *ParamGads, north, south, day; /* Integer string gadgets - defined in star3.c */ extern struct Gadget sec, min, hour, day, mon, year, LatDeg, LongMin, LongDeg; /********************************************************************** * Border Definitions for the requester **********************************************************************/ SHORT Req_Pairs2[] = { 1, 1, 358, 1, 358, 188, 1, 188, 1, 1 }; SHORT Req_Pairs1[] = { 0, 0, 362, 0, 362, 192, 0, 192, 0, 0 }; struct Border Req_bord_2 = { 2, 2, /* LeftEdge, TopEdge */ 1, 7, JAM1, /* FrontPen, BackPen, DrawMode*/ 5, /* Count of XY pairs */ (SHORT *)&Req_Pairs2, /* XY pairs */ NULL /* Next Border */ }; struct Border Req_bord_1 = { 0, 0, /* LeftEdge, TopEdge */ 7, 3, JAM1, /* FrontPen, BackPen, DrawMode*/ 5, /* Count of XY pairs */ (SHORT *)&Req_Pairs1, /* XY pairs */ &Req_bord_2 /* Next Border */ }; extern struct TextAttr TxtAt_BU; struct IntuiText Req_Text = { 2, 7, /* FrontPen, BackPen */ JAM2, /* DrawMode */ 50, 1, /* LeftEdge, TopEdge */ &TxtAt_BU, /* ITextFont Pointer */ /* The IText */ (UBYTE *)" Parameters for Star Chart ", NULL /* NextText */ }; extern struct TextAttr TxtAt_B; struct IntuiText Error_Text = { 3, 2, /* FrontPen, BackPen */ JAM2, /* DrawMode */ 0, 0, /* LeftEdge, TopEdge */ &TxtAt_B, /* ITextFont Pointer */ /* The IText */ (UBYTE *)"?", NULL /* NextText */ }; /**************************************************************************** * The Code part of the GetParam module. ***************************************************************************/ GetParams() { BOOL cancelchosen; LONG iflags; struct RastPort *reqrp; /* fix the IDCMP flags to report requester set and clear */ iflags = nw.IDCMPFlags; iflags |= REQCLEAR; ModifyIDCMP(w,iflags); /* initialize the text Param requester */ InitParamReq(); /* Put up the requester */ Request(&ParamRequester,w); /* set the north/south imagery */ reqrp = ParamRequester.ReqLayer->rp; if(workParms.Horizon == 0) { SetDrMd(reqrp, COMPLEMENT); RectFill(reqrp,94L,153L,158L,169L); SetDrMd(reqrp, JAM1); } else { SetDrMd(reqrp, COMPLEMENT); RectFill(reqrp,206L,153L,274L,169L); SetDrMd(reqrp, JAM1); } /* let the user fill in the parameters and wait for a cancel or ok. */ cancelchosen = WaitParamReq(reqrp); /* if the user cancelled, just return -- otherwise set Parms and */ /* re-calculate and redisplay the star chart. */ if (cancelchosen) return(0); /* figure out current siderial time, etc. and update the Parms struct */ CalcParams(&workParms); Parms = workParms; /* recalculate star positions and display them. */ DisplayStars(); DisplayAllText(); } /* GetParams */ /* * Init the Itext Param requester */ InitParamReq() { struct RastPort *reqrp; InitRequester(&ParamRequester); ParamRequester.LeftEdge = 110; ParamRequester.TopEdge = 2; ParamRequester.Width = 363; ParamRequester.Height = 193; ParamRequester.ReqGadget = ParamGads; ParamRequester.ReqText = &Req_Text; ParamRequester.BackFill = 2; ParamRequester.Flags = 0; ParamRequester.ReqBorder = &Req_bord_1; /* copy the parms structure */ workParms = Parms; InitStringGad(&sec,SecondsCount); InitStringGad(&min,workParms.Minute); InitStringGad(&hour,workParms.Hour); InitStringGad(&day,workParms.Day); InitStringGad(&mon,workParms.Month); InitStringGad(&year,workParms.Year); InitStringGad(&LatDeg,workParms.Latitude); InitStringGad(&LongMin,workParms.LongitudeMin); InitStringGad(&LongDeg,workParms.LongitudeDeg); } /* InitParamReq */ InitStringGad(gad,val) struct Gadget *gad; SHORT val; { struct StringInfo *si; si = (struct StringInfo *)gad->SpecialInfo; sprintf(si->Buffer,"%d",val); si->NumChars = (LONG)strlen(si->Buffer); *(si->UndoBuffer) = '\0'; } /**************************************************************************** * WaitParamReq - permit user to change the values in the parameter gadgets * and check the values they install until either the * CANCEL gadget is clicked or the OK gadget is clicked AND * there are no outstanding input errors ***************************************************************************/ BOOL WaitParamReq(reqrp) struct RastPort *reqrp; { ULONG class = GADGETDOWN; USHORT Param = 0; USHORT selected = 0; struct IntuiMessage *message; struct Gadget *gadget, *lastgad; BOOL cancelflag = FALSE; LONG errorflag = 0L, checkvals(); lastgad = NULL; while (class != REQCLEAR) { if ((message=(struct IntuiMessage *) GetMsg(w->UserPort)) == 0L) { Wait(1L<UserPort->mp_SigBit); continue; } class = message->Class; gadget = (struct Gadget *) message->IAddress; ReplyMsg(message); switch (class) { case GADGETDOWN: /* check to see if the user clicked on a new */ /* gadget withou hitting return on the old one */ /* if so, treat this like a gadgetup for the */ /* previous gadget. */ if (lastgad == NULL) errorflag = checkvals(reqrp,gadget,errorflag,class); else errorflag = checkvals(reqrp,lastgad,errorflag,class); lastgad = gadget; break; case GADGETUP: switch (gadget->GadgetID) { case NORTHGAD: if(workParms.Horizon != 0) { SetDrMd(reqrp, COMPLEMENT); RectFill(reqrp,94L,153L,158L,169L); RectFill(reqrp,206L,153L,274L,169L); SetDrMd(reqrp, JAM1); } workParms.Horizon = 0; break; case SOUTHGAD: if(workParms.Horizon != 1) { SetDrMd(reqrp, COMPLEMENT); RectFill(reqrp,94L,153L,158L,169L); RectFill(reqrp,206L,153L,274L,169L); SetDrMd(reqrp, JAM1); } workParms.Horizon = 1; break; case CANGAD : cancelflag = TRUE; break; case OKGAD : if (errorflag == 0) EndRequest(&ParamRequester,w); else DisplayBeep(w->WScreen); break; default: errorflag = checkvals(reqrp,gadget,errorflag,class); } /* end of GADGETUP switch */ } /* end of CLASS switch */ }/* end of while loop */ return(cancelflag); } /* WaitParamReq */ /**************************************************************************** * checkvals - verify that the values returned by the integer gadgets are * in the appropriate range for the parameter. ***************************************************************************/ LONG checkvals(reqrp,checkgad,errorflag,class) struct RastPort *reqrp; struct Gadget *checkgad; LONG errorflag; ULONG class; { struct StringInfo *si; BOOL inputerror = FALSE; LONG checknum, pendingerror; if (checkgad == NULL) return(errorflag); pendingerror = errorflag; si = (struct StringInfo *)checkgad->SpecialInfo; if (si == NULL) return(errorflag); /* this is kind of a kludge, but necessary since Intuition will have set */ /* LongInt to zero, IF the user clicks on a gadget THEN clicks on */ /* another, without hitting return on the old one and not modifying the */ /* contents of the string buffer, the LongInt value for the gadget is */ /* reported as zero. */ if (class == GADGETUP) checknum = si->LongInt; else checknum = atol(si->Buffer); /* check the values input */ switch (checkgad->GadgetID) { case LONGDEGGAD: if (INRANGE(checknum,-180L,180L)) { workParms.LongitudeDeg = checknum; errorflag &= ~(1L << LONGDEGGAD); break; } else inputerror = TRUE; break; case LONGMINGAD: if (INRANGE(checknum,0L,59L)) { workParms.LongitudeMin = checknum; errorflag &= ~(1L << LONGMINGAD); break; } else inputerror = TRUE; break; case LATDEGGAD: if (INRANGE(checknum,0L,90L)) { workParms.Latitude = checknum; errorflag &= ~(1L << LATDEGGAD); break; } else inputerror = TRUE; break; case YEARGAD: if (INRANGE(checknum,1900L,2100L)) { workParms.Year = checknum; errorflag &= ~(1L << YEARGAD); break; } else inputerror = TRUE; break; case MONGAD: if (INRANGE(checknum,1L,12L)) { workParms.Month = checknum; errorflag &= ~(1L << MONGAD); if ((INRANGE(workParms.Day,1,Dd[workParms.Month])) == 0) { checkgad = &day; si = (struct StringInfo *)checkgad->SpecialInfo; inputerror = TRUE; break; } break; } else inputerror = TRUE; break; case DAYGAD: if (INRANGE(checknum,1L,(LONG)Dd[workParms.Month])) { workParms.Day = checknum; errorflag &= ~(1L << DAYGAD); break; } else inputerror = TRUE; break; case HOURGAD: if (INRANGE(checknum,0L,23L)) { workParms.Hour = checknum; errorflag &= ~(1L << HOURGAD); break; } else inputerror = TRUE; break; case MINGAD: if (INRANGE(checknum,0L,59L)) { workParms.Minute = checknum; errorflag &= ~(1L << MINGAD); break; } else inputerror = TRUE; break; case SECGAD: if (INRANGE(checknum,0L,59L)) { SecondsCount = checknum; errorflag &= ~(1L << SECGAD); break; } else inputerror = TRUE; break; } /* end of Gadget id switch */ if (inputerror == TRUE) /* put a "?" next to the gadget */ { errorflag |= (1L << checkgad->GadgetID); DisplayBeep(w->WScreen); PrintIText(reqrp,&Error_Text, (LONG)(checkgad->LeftEdge - 10),(LONG)checkgad->TopEdge); } if ((pendingerror != errorflag) && (inputerror == FALSE)) { /* user must have fixed an error, so turn off the ? */ pendingerror = errorflag; Error_Text.FrontPen = 2; PrintIText(reqrp,&Error_Text, (LONG)(checkgad->LeftEdge - 10),(LONG)checkgad->TopEdge); Error_Text.FrontPen = 3; } return(errorflag); } /* end of checkvals */ /************************************************************************* * CalcParams - Calculate local siderial time (Lst) and Greenwich * siderial time based on the current work parameters. ************************************************************************/ CalcParams(p) struct ParamStruct *p; { FLOAT workhours, LocalOffset, MeanLocTime; FLOAT CalcGst(); /* calcGst is in starglb.c */ SHORT degrees, temp; degrees = ABS(p->LongitudeDeg) % 15; workhours = (FLOAT)degrees + ((FLOAT)p->LongitudeMin / 60.0); LocalOffset = (workhours * 4.0)/60.0; /* get Greenwich time */ p->Gst = CalcGst(p->Day,p->Month); workhours = (FLOAT)p->Hour + ((FLOAT)p->Minute / 60.0); if(p->LongitudeDeg < 0) MeanLocTime = workhours + LocalOffset; else MeanLocTime = workhours - LocalOffset; /* local siderial time */ p->Lst = MeanLocTime + p->Gst; if (p->Lst > 24.0) p->Lst -= 24.0; if (p->Lst < 0) p->Lst += 24; /* set siderial times in the workparms */ temp = (SHORT)(p->Lst * 60.0); p->Hr = temp / 60; p->Mn = temp % 60; }