home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
007.lha
/
settime
/
timeset.c
< prev
next >
Wrap
C/C++ Source or Header
|
1986-11-10
|
18KB
|
600 lines
/* 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 */
}