home *** CD-ROM | disk | FTP | other *** search
- /* This file, along with several ancillary functions in another */
- /* function file, lets you set the date and time using requesters. */
- /* The actual setting takes place via the AmigaDos call Date, */
- /* accessed by the AmigaDos function Execute(). */
-
- /* If someone knows how to write the date and time 'directly' */
- /* to the machine, I'd like to know. The date and time info */
- /* must be stored at some memory location, after all!! */
-
- /* Some include files... */
- #include <exec/types.h>
- #include <exec/exec.h>
- #include <intuition/intuition.h>
- #include <libraries/dos.h>
- #include <lattice/stdio.h>
-
- /* Gadget ID numbers... */
- #define IDMINUTE 0
- #define IDHOUR 1
- #define IDYEAR 2
- #define IDDAY 3
- #define IDMONTH 4
- #define IDSETTIME 5
-
- /* Some time zero values... */
- #define BASEYEAR 1986
-
- /* Maximum of number years spanned by the year gadget. */
- #define MAXYEARS 30
-
- /* The library base addresses for Intuition's magic... */
- int *GfxBase;
- struct IntuitionBase *IntuitionBase;
-
- /* A lookup table of month names... */
- static char *MName[]={"January","February","March","April","May","June",
- "July","August","September","October","November","December"};
-
- /* Intuition functions used elsewhere, declared external here to */
- /* keep the compiler happy about returned types. */
- struct Window *SetWindow;
- struct IntuiMessage *GetMsg(),*IDCMPmesg;
- struct Window *OpenWindow(),*CloseWindow();
- struct MenuItem *ItemAddress();
-
- /* User functions defined in Date.C and used here. */
- void FromDosDate(),ToDosDate();
- int LegalDays();
-
- /* Some AmigaDos functions... */
- int Execute();
- void DateStamp();
-
- /* Text used to identify the various gadgets in the requester. */
- static struct IntuiText MinuteText = {0,1,JAM2,0,-8,NULL,"Minute Select",NULL};
- static struct IntuiText HourText = {0,1,JAM2,0,-8,NULL,"Hour Select",NULL};
- static struct IntuiText YearText = {0,1,JAM2,0,-8,NULL,"Year Select",NULL};
- static struct IntuiText DayText = {0,1,JAM2,0,-8,NULL,"Day Select",NULL};
- static struct IntuiText MonthText = {0,1,JAM2,0,-8,NULL,"Month Select",NULL};
- static struct IntuiText SetTimeText = {0,1,JAM2,0,-8,NULL,"Set Time and Date",NULL};
-
- /* When using the Pot(entiometer) gadgets (I call them sliders) */
- /* you need to give Intuition data areas in which to draw the */
- /* default knobs. You could define your own image to be used */
- /* as a knob, but I'm too lazy for that. */
- static struct Image Knob1,Knob2,Knob3,Knob4,Knob5;
-
- /* The set requester uses one boolean gadget (to actually SET the */
- /* time). Here are the relative x,y coordinate pairs that define */
- /* the size and shape of the box enclosing the select region. */
- static USHORT BoxData[] = {
- 0,0,
- 0,10,
- 30,10,
- 30,0,
- 0,0
- };
-
- /* Here is Border structure that makes the border implied by BoxData */
- /* meaningful to Intuition. COMPLEMENT is a flag which forces the */
- /* border to be drawn by complementing the color at each point the */
- /* border passes through. */
- static struct Border Box1 = {
- 0,0,
- 2,2,COMPLEMENT,
- 5,
- &BoxData,
- NULL
- };
-
- /* These next structures define the visual characteristics of the */
- /* various sliders. The '0,0' datapair is, as I recall, where the */
- /* initial position and percent of full scale occupied by the slider */
- /* is specified. The actual values are set later on in the program. */
- static struct PropInfo MinuteInfo = {
- AUTOKNOB | FREEHORIZ ,
- 0,0,
- NULL,NULL,
- NULL,NULL,NULL,NULL,NULL,NULL
- };
-
- static struct PropInfo HourInfo = {
- AUTOKNOB | FREEHORIZ ,
- 0,0,
- NULL,NULL,
- NULL,NULL,NULL,NULL,NULL,NULL
- };
-
- static struct PropInfo YearInfo = {
- AUTOKNOB | FREEHORIZ ,
- 0,0,
- NULL,NULL,
- NULL,NULL,NULL,NULL,NULL,NULL
- };
-
- static struct PropInfo DayInfo = {
- AUTOKNOB | FREEHORIZ ,
- 0,0,
- NULL,NULL,
- NULL,NULL,NULL,NULL,NULL,NULL
- };
-
- static struct PropInfo MonthInfo = {
- AUTOKNOB | FREEHORIZ ,
- 0,0,
- NULL,NULL,
- NULL,NULL,NULL,NULL,NULL,NULL
- };
-
- /* These next structures define the various gadgets. Note that all */
- /* of the sliders -- but not the boolean gadget -- are set to */
- /* follow mouse events and to immediately notify the program when */
- /* they are selected by the user. The follow function is needed */
- /* because we want to continuously update the displayed date and */
- /* time to give feedback. Please note that the gadgets are linked */
- /* together as a list. */
- static struct Gadget MinuteGadget = {
- NULL,
- 5,20,360,10,
- GADGHNONE | GADGIMAGE,
- GADGIMMEDIATE | FOLLOWMOUSE ,
- PROPGADGET | REQGADGET,
- (APTR)&Knob1 ,
- NULL,
- &MinuteText,
- NULL,
- (APTR)&MinuteInfo,
- IDMINUTE,
- NULL
- };
-
- static struct Gadget HourGadget = {
- &MinuteGadget,
- 5,40,360,10,
- GADGHNONE | GADGIMAGE,
- GADGIMMEDIATE | FOLLOWMOUSE ,
- PROPGADGET | REQGADGET,
- (APTR)&Knob2 ,
- NULL,
- &HourText,
- NULL,
- (APTR)&HourInfo,
- IDHOUR,
- NULL
- };
-
- static struct Gadget YearGadget = {
- &HourGadget,
- 5,60,360,10,
- GADGHNONE | GADGIMAGE,
- GADGIMMEDIATE | FOLLOWMOUSE ,
- PROPGADGET | REQGADGET,
- (APTR)&Knob3 ,
- NULL,
- &YearText,
- NULL,
- (APTR)&YearInfo,
- IDYEAR,
- NULL
- };
-
- static struct Gadget DayGadget = {
- &YearGadget,
- 5,80,372,10,
- GADGHNONE | GADGIMAGE,
- GADGIMMEDIATE | FOLLOWMOUSE ,
- PROPGADGET | REQGADGET,
- (APTR)&Knob4 ,
- NULL,
- &DayText,
- NULL,
- (APTR)&DayInfo,
- IDDAY,
- NULL
- };
-
- static struct Gadget MonthGadget = {
- &DayGadget,
- 5,100,360,10,
- GADGHNONE | GADGIMAGE,
- GADGIMMEDIATE | FOLLOWMOUSE ,
- PROPGADGET | REQGADGET,
- (APTR)&Knob5 ,
- NULL,
- &MonthText,
- NULL,
- (APTR)&MonthInfo,
- IDMONTH,
- NULL
- };
-
- /* This gadget differs from the above because it is a boolean */
- /* gadget and not a slider. Note that it has a flag which */
- /* tells Intuition to get rid of the requester. */
- static struct Gadget SetTime = {
- &MonthGadget,
- 5,120,30,10,
- GADGHCOMP ,
- GADGIMMEDIATE | ENDGADGET ,
- BOOLGADGET | REQGADGET,
- (APTR)&Box1 ,
- NULL,
- &SetTimeText,
- NULL,
- NULL,
- IDSETTIME,
- NULL
- };
-
- /* Here is the requester data structure. Note that it 'stores' the */
- /* gadgets defined above by pointing to the start of the linked list */
- /* of gadgets. */
- static struct Requester SetReq= {
- NULL,
- 5,40,
- 390,140,
- NULL,NULL,
- &SetTime,
- NULL,
- NULL,
- NULL,
- 0,
- NULL,
- {NULL},
- {NULL},
- NULL,
- {NULL}
- };
-
- /* This function takes the current settings of the date/time */
- /* variables and formats/displays the information at the top */
- /* of the window in which the requester appears. */
- void DisplayDateTime(Month,Day,Year,Hour,Minute)
- int Month,Day,Year,Hour,Minute;
- {
- /* We need to reserve space for the sprintf() function to */
- /* write into. */
-
- static char DispString[]=" ";
- char *DayModifier="th",*HalfDay="a.m.";
-
- /* This section of code assigns the correct ending to the */
- /* day number (e.g., '1st', '2nd', etc.). */
-
- if(Day>=10 && Day<20)
- DayModifier="th";
- else
- {
- switch(Day%10)
- {
- case 1:
- DayModifier="st";
- break;
- case 2:
- DayModifier="nd";
- break;
- case 3:
- DayModifier="rd";
- break;
- default:
- DayModifier="th";
- break;
- }
- }
-
- /* Here we set the a.m./p.m. 'flag'. Note that we adjust */
- /* the value of Hour, which arrives in 24 hour military */
- /* format, to be consistent with a 12 hour a.m./p.m. format. */
-
- if((Hour>=0 && Hour<12) || Hour==24)
- {
- HalfDay="a.m.";
- if(Hour==0 || Hour==24)
- Hour=12;
- }
- else
- {
- HalfDay="p.m.";
- if(Hour!=12)
- Hour-=12;
- }
-
- /* Here's where we glom all the info together to form a string. */
- /* Note that the string is then padded to always make it the same */
- /* length. This makes sure you always completely write-over */
- /* whatever stuff you wrote previously. */
-
- sprintf(&DispString,"%s %d%s, %d %d:%02d %s",MName[Month],Day,DayModifier,Year,Hour,Minute,HalfDay);
- while(strlen(&DispString)<32)
- strcat(&DispString," ");
-
- /* Here's where we actually write the string to the window. */
- Move(SetWindow->RPort,5,20);
- Text(SetWindow->RPort,&DispString,32);
- }
-
- /* This function returns a value meaningful to humans from whatever */
- /* unsigned 16 bit value is sent by Intuition to describe the current */
- /* location of the slider. */
- int GetPotVal(PickedGadget)
- struct Gadget *PickedGadget;
- {
- static int PotMult[]={60,24,MAXYEARS,31,12};
- int temp;
- USHORT PotVal;
- struct PropInfo *PickedProp;
-
- /* Here we get a pointer to the currently selected gadget. */
- /* I tried to do this all in one step but for some reason */
- /* it didn't work... */
- PickedProp=(struct PropInfo *)PickedGadget->SpecialInfo;
-
- /* The unsigned value representing the gadget's location. */
- PotVal=(PickedProp->HorizPot);
-
- /* This converts the unsigned value to meaningful data. */
- temp=(PotVal*PotMult[PickedGadget->GadgetID])>>16;
- return(temp);
- }
-
- /* This function lets us exit gracefully, with some indication */
- /* of what went wrong (if anything did). Normally I wouldn't */
- /* include this, since printf's expand a program file a LOT, */
- /* but I used sprintf() up above so why not... */
- void Cleanup(Level)
- int Level;
- {
- /* Level is an error code. See main() for context. */
- if(Level>3)
- CloseWindow(SetWindow);
- if(Level>2)
- CloseLibrary(IntuitionBase);
- if(Level>1)
- CloseLibrary(GfxBase);
- switch(Level)
- {
- case 1:
- printf("Graphics library would not open.\n");
- break;
- case 2:
- printf("Intuition library would not open.\n");
- break;
- case 3:
- printf("Window would not open.\n");
- break;
- case 4:
- printf("Requester would not open.\n");
- break;
- }
- exit(0);
- }
-
- /* The main banana. */
- main()
- {
- int temp,*ChgVal,Minute,Hour,Year,Day,Month;
- static char SetCmd[]=" ";
- ULONG class;
- struct Gadget *CurGadget;
-
- /* Information needed by Intuition to open the window in which */
- /* the requester appears. Note that you also need to set the */
- /* window to pass mouse motion and gadget selection reports. */
- /* REQCLEAR means 'Hey, Intuition, tell us when the requester */
- /* got sent away', i.e., when user wants to set date/time.*/
-
- static struct NewWindow newSetWindow = {
- 10,10,
- 500,180,
- 0,1,
- GADGETDOWN | MOUSEMOVE | REQCLEAR,
- WINDOWDRAG | SMART_REFRESH | NOCAREREFRESH | ACTIVATE,
- NULL,
- NULL,
- "AmigaDOS Time and Date Setting Screen",
- NULL,
- NULL,
- NULL,NULL,
- NULL,NULL,
- WBENCHSCREEN
- };
-
- /* A data structure needed by the AmigaDos date/time function */
-
- struct DateStamp DosDate;
-
- /* Here we open the various libraries. Note error codes passed */
- /* to Cleanup() if something goes wrong. */
-
- if((GfxBase=(int *)OpenLibrary("graphics.library",1))==NULL)
- Cleanup(1);
- if((IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",1))==NULL)
- Cleanup(2);
- if((SetWindow=OpenWindow(&newSetWindow))==NULL)
- Cleanup(3);
-
- /* Get the current date and time from AmigaDos. Unfortunately, */
- /* it comes back in a very unuseful form. So we pass it through */
- /* the FromDosDate function, which converts it into a more useful */
- /* format. Afterwards, we subtract one from the month number */
- /* because the MName array expects a value range of 0..11 */
-
- DateStamp(&DosDate);
- FromDosDate(&DosDate,&Month,&Day,&Year,&Hour,&Minute,&temp);
- --Month;
-
- /* Bump the minute counter if we are more than 30 seconds into */
- /* the current minute. */
-
- if(temp>=30)
- ++Minute;
-
- /* Here we set the size of the slider controls. */
-
- MinuteInfo.HorizBody=0xFFFF/60;
- HourInfo.HorizBody=0xFFFF/24;
- YearInfo.HorizBody=0xFFFF/30;
- DayInfo.HorizBody=0xFFFF/31;
- MonthInfo.HorizBody=0xFFFF/12;
-
- /* Here we set the current date and time into the sliders so */
- /* that they will start out in the 'correct' positions. */
-
- MinuteInfo.HorizPot=MinuteInfo.HorizBody*Minute;
- HourInfo.HorizPot=HourInfo.HorizBody*Hour;
- YearInfo.HorizPot=YearInfo.HorizBody*(Year-BASEYEAR);
- DayInfo.HorizPot=DayInfo.HorizBody*Day;
- MonthInfo.HorizPot=MonthInfo.HorizBody*Month;
-
- /* Before going into the event processing loop, show the */
- /* date and time as returned by AmigaDos */
-
- DisplayDateTime(Month,Day,Year,Hour,Minute);
-
- /* Here we try and set up the requester. */
-
- if(Request(&SetReq,SetWindow)==FALSE)
- Cleanup(4);
-
- /* The event processing loop. We run it forever. Actually, */
- /* only until the requester goes away. */
-
- for(;;)
- {
-
- /* Put the program to bed until Intuition sends us a message. */
- /* That funny argument in the function says 'wait until a */
- /* certain bit in the message area turns on' (which signifies */
- /* a message). The particular bit -- the Intuition Direct */
- /* Communication Message Port bit (I did NOT make up that name)*/
- /* -- is mp_SigBit's into the (32?) bit message area. You */
- /* get the value of mp_SigBit, which is set by Intuition when */
- /* it opens your window, from a data structure pointed to by */
- /* the window data structure. */
-
- Wait(1<<SetWindow->UserPort->mp_SigBit);
-
- /* Here we process messages so long as they continue to arrive. */
- /* After that, we go back to sleep. */
-
- while(IDCMPmesg=GetMsg(SetWindow->UserPort))
- {
-
- /* Messages come in different classes -- and you need to */
- /* reply to them ASAP, particularly mouse movement */
- /* messages, because Intuition holds onto all messages */
- /* until you reply to them. Which can burn up a LOT of */
- /* memory. Actually, I think there are some occasions */
- /* where you can not reply -- but I KNOW there are also */
- /* some where not replying calls in the Guru! */
-
- class=IDCMPmesg->Class;
- ReplyMsg(IDCMPmesg);
-
- /* We have only 2 classes of events -- but Intuition views */
- /* them as three. The 2 which are one so far as this */
- /* program is concerned are 'gadget picked' and 'mouse */
- /* moved'. The reason these are the 'same' class here is */
- /* that whenever the mouse moves we want to see if we need */
- /* to update the displayed date/time (i.e., the user may */
- /* have dragged the slider. */
-
- if(class==GADGETDOWN || class==MOUSEMOVE)
- {
- if(class==GADGETDOWN)
- CurGadget=(struct Gadget *)(IDCMPmesg->IAddress);
-
- /* Ignore the message that the user wants to set date */
- /* and time, since it is also heralded by a 'requester */
- /* went away' message. */
-
- if(CurGadget->GadgetID<IDSETTIME || class==MOUSEMOVE)
- {
-
- /* Otherwise, get the current setting and do whatever */
- /* special processing is needed. We store the setting */
- /* in ChgVal so that we can compare it to the last */
- /* similar setting -- thus avoiding writing to the */
- /* screen except when absolutely necessary. This */
- /* reduces flicker. 'ChgVal' is the base value which */
- /* we will be comparing to.value. 'Temp' is the */
- /* <possibly> changed value just returned. */
-
- temp=GetPotVal(CurGadget);
- switch(CurGadget->GadgetID)
- {
- case IDMINUTE:
- ChgVal=&Minute;
- break;
- case IDHOUR:
- ChgVal=&Hour;
- break;
- case IDYEAR:
- ChgVal=&Year;
-
- /* We need to add BASEYEAR to the returned value. */
-
- temp+=BASEYEAR;
-
- /* If the year changed, get the current day setting */
- /* and see if we need to adjust for leap years. */
-
- if(temp!=Year)
- {
- Day=GetPotVal(&DayGadget)+1;
- Day=LegalDays(Month,Day,temp);
- }
- break;
- case IDDAY:
- ChgVal=&Day;
- temp+=1;
-
- /* Make sure we 'max out' in 28/29/30 day months. */
-
- temp=LegalDays(Month,temp,Year);
- break;
- case IDMONTH:
- ChgVal=&Month;
-
- /* If the month changed, we need to make sure we */
- /* don't have to change the displayed day due to */
- /* the different lengths of months. */
-
- if(temp!=Month)
- {
- Day=GetPotVal(&DayGadget)+1;
- Day=LegalDays(temp,Day,Year);
- }
- break;
- }
-
- /* Only display date and time if something changed. */
-
- if(*ChgVal!=temp)
- {
- *ChgVal=temp;
- DisplayDateTime(Month,Day,Year,Hour,Minute);
- }
- }
- }
-
- /* If the requester went away, set the date and time and */
- /* end the program. */
-
- if(class==REQCLEAR)
- {
-
- /* Build the command string... */
-
- sprintf(&SetCmd,"date %.2d-%.3s-%d %d:%02d",Day,MName[Month],Year%100,Hour,Minute);
-
- /* and Execute() it! */
-
- Execute(&SetCmd,0,0);
- Cleanup(5);
- }
- } /* End of handling IDCMP message */
- } /* End of set event processing */
- }
-