Sie sind auf Seite 1von 12

Project Name : PERPETUAL CALENDAR

Author : MANOJ PRAVAKAR SAHA

Studen ID : 052 058 045

FEATURES :

This is a very simple program which has one main window and multiple windows(widgets)
packed into it.

The calendar widget shows the calendar of the current or selected month and year in
structured form.
This widget contains two spinbuttons - one for month and another for year. So the user can
easily switch between months and years by simply ckicking the upward or downward arrows
of the spinbuttons.

Inside the main window widget there is 'Quit' button. User can terminate the program any
time by pressing this button.
Program can also be terminated by pressing the close (X) button, packed at the top-right of
the window, or by any shortcuts valid for Genome Desktop.
The main window is a non-resizeable one. So,only minimzation and unminimization of the
window is possible.

USER MANUAL :

This program is as simple as any other calendar program. Just click on the spin buttons or use
arrow keys or input your desired month and year manually and see the result on the screen.

INSIDE THE CODE:

The whole code is written in a very simple way, so that even a beginner, familiar with the
basic concepts of C and GTK can understand the whole code.
While writing the code modular programming concept is applied.
This progarm is written to work in Genome Desktop Environment only. So,
GTK+ (GIMP Toolkit) is used through its C interface.
Mathematical Reasoning:

In doing the project the first and main problem was to generate the dates of a given month
and year in a efficient way. Instead of manually calculating the days and assing them to some
variables I approached in a mathematical way. A simple formula, which is valid for 0 to 9999,
is used to calculate the first day of the week for a given month in a given year.

first_day_of_the_week=(century+y+(y/4)+month+1)%7;
where century = (3-century's_figure)*2; century's_figure=(year/100)%4;
y=year%100 and
month is
January 0 (in leap year 6)
February 3 (in leap year 2)
March 3 August 2
April 6 September 5
May 1 October 0
June 4 November 3
July 6 December 5

The corresponding numbers of the days of the week are

Sunday 0
Monday 1
Tuesday 2
Wednesday 3
Thursday 4
Friday 5
Saturday 6

These calculations are done in a function named calculation().


By using this result a calendar is generated for a given month and year.
The Gregorian calendar was first introduced in 1752 and there is a possiblity that this system
won't persist beyond 2100. So I delimit the years between 1752 to 2100, including these two.

While manipulating the calendar problems like leap year and total days of a month are solved
by using two simple functions, leap_year() and total_days_of_month(), for calculaing the
leap year, which returns 1 if the year is a leap year or 0 otherwise, and from this information
and others, the total days of the month is calculated by simple selection statements.

This program also show the number of weeks of a year. This thing is done in the function
called calculation().

The built-in tm structure inside the header <time.h> is used to call the current date from the
system clock.

Graphical User Interface (GUI) Manipualtion:

This program is written to work in a GENOME Desktop Environment irrespective of the


platform. So, GTK+ (GIMP Toolkit), version 2.x, is used to manipulate the Graphical User
Interface.
The whole program uses some built-in GTK+ widgets (window), instead of creating a whole
new bunch of widgets.

Every widget is declared as a pointer to GtkWidget or GObject (in object oriented


programming concept these two are referred as class and in C - structure) before usage. Then
the corresponding functions are used to manipulate the widgets.

Some functions like delete_event(), get_value_year(), get_value_mon() are written to do


certain tasks when a corresponding event occur.

The main window is a non-resizeable window of 350 x 250 pixels. Inside the main window
all the other widgets are packed into a fixed container, which is a window or widget itself.
The fixed container allows the widgets to be placed at a fixed position within it's window.

There are two spin buttons inside the main window for taking input, one for the month and
another for the year. The two spin buttons are set to take only numeric value as input to avoid
any unreferenced behavior if any unprecedented value is given. The two spin buttons call two
funtions get_value_year/mon() and dar() every time they receive a signal from the user.

The main problem was to print the caledar in a structured form. At first only one textview
window was created but to solve the problem of alingment of columns 64 independent
textview widgets are used. By using two for loops 64 textview windows are created to show
the weekdays, dates and week numbers. The function used for this purpose is named dar(). A
funtion named space() place the weekdays, dates and week numbers into strings and
gtk_text_buffer_set_text() shows the string into specific location.

An additional 'Quit' button is placed into the main window to terminate the program any time.

Known Bugs:

The equation through which the week number is obtained is not the absolute one. So it
generate some errornous results sometimes, though the calendar is alright.

This program uses no error repotring tools to detect if an error occurs.

The program is not a very efficient one. Some selction statements which have to be checked
only once in a whole oparetion is checked for every opeartion. So it do not generate the
expected results that much fast and if data is given as input very fast it hangs out.
From the very beginning of this program global variables are used to store the values instead
of passing arguments. For this reason a function with same kind of definitions is used twice
in the program to perform some additional tasks.

CODE :

#include<gtk/gtk.h>
#include<stdio.h>
#include<time.h>

/*-------------------------------------------------------------------*/
/* declares global variables for calculation */
/*-------------------------------------------------------------------*/
int first_day_of_month, leap, m, week0;
int n=31,j=0,k,l=0,u_1,u_10,r,q,i;
static int in=1;
char s[8];
int x;
int y;
int dd;
/*-------------------------------------------------------------------*/
/* decalre pointers to different widgets */
/*-------------------------------------------------------------------*/
GtkWidget *spin_year;
GtkWidget *spin_mon;
GtkWidget *text;
GtkTextBuffer *buf;
GtkWidget *fixed; //declares pointer to the fixed container

int t=0;
struct tm *ptr; //decalres a pointer to the structure tm
time_t t0; //declares a variable for the structure time_t
int month,month_day,weekday,yearday,year,second,minute,hour;
int total_days_of_month(void);

/*-------------------------------------------------------------------*/
/* calculates whether the given year is a leap year or not */
/*-------------------------------------------------------------------*/
int leap_year(int year){

int m1;
if (year%400==0) m1=1;
else if (year%100==0) m1=0;
else if (year%4==0) m1=1;
else m1=0;

return m1;
}
/*-------------------------------------------------------------------*/
/* Calculation */
/*-------------------------------------------------------------------*/

void day_of_week (int year1, int month1)


{
int century, century_figure;
leap=leap_year(year1);//pass control to leap year program

switch(month1)//manipulating month data for next calculation


{
case 1:
if(leap) m=6;
else m=0;
break;
case 2:
if(leap) m=2;
else m=3;
break;
case 3: m=3; break;
case 4: m=6; break;
case 5: m=1; break;
case 6: m=4; break;
case 7: m=6; break;
case 8: m=2; break;
case 9: m=5; break;
case 10: m=0; break;
case 11: m=3; break;
case 12: m=5; break;
}
/*-------------------------------------------------------------------*/
/* calculating the 1st day of the month */
/*-------------------------------------------------------------------*/
century_figure = ( year / 100 ) % 4;
century = ( 3 - century_figure )*2;
y = year % 100;
first_day_of_month = ( century + y + ( y / 4 ) + m + 1) % 7;

int day_of_week1 (int year1, int month1)


{
int leap1, first_day_of_month1, m1, y1, century1, century_figure1;

//pass control to leap year program


leap1=leap_year(year1);

//manipulating month data for next calculation


switch(month1)
{
case 1:
if(leap1) m1=6;
else m1=0;
break;
case 2:
if(leap1) m1=2;
else m1=3;
break;
case 3: m1=3; break;
case 4: m1=6; break;
case 5: m1=1; break;
case 6: m1=4; break;
case 7: m1=6; break;
case 8: m1=2; break;
case 9: m1=5; break;
case 10: m1=0; break;
case 11: m1=3; break;
case 12: m1=5; break;
}
/*-------------------------------------------------------------------*/
/* calculating the 1st day of the month */
/*-------------------------------------------------------------------*/
century_figure1 = ( year1 / 100 ) % 4;
century1 = ( 3 - century_figure1 )*2;
y1= year1 % 100;

first_day_of_month1 = ( century1 + y1 + ( y1 / 4 ) + m1 + 1) % 7;

return first_day_of_month1;
}

void calculation(void)
{
float week;
day_of_week(year,month);

/*-------------------------------------------------------------------*/
/* calculating the first week number of the month */
/*-------------------------------------------------------------------*/
switch(month){

case 1:
if (first_day_of_month>=5) week=52+leap;
else week=1;
break;
case 2:
if(first_day_of_month>4) week=(first_day_of_month+31+leap+1)/7;
else week=(first_day_of_month+31+leap )/7+1;
break;
case 3:
if (first_day_of_month>4) week=(first_day_of_month+59+leap)/7;
else week=(first_day_of_month+59+leap + 1)/7;
break;
case 4:
if (first_day_of_month>4) week=(first_day_of_month+90+leap)/7;
else week=(first_day_of_month+90+leap + 1)/7;
break;
case 5:
if (first_day_of_month>4) week=(first_day_of_month+120+leap)/7;
else week=(first_day_of_month+120+leap + 1)/7;
break;
case 6:
if (first_day_of_month>4) week=(first_day_of_month+151+leap)/7;
else week=(first_day_of_month+151+leap + 1)/7;
break;
case 7:
if (first_day_of_month>4) week=(first_day_of_month+181+leap)/7;
else week=(first_day_of_month+181+leap + 1)/7;
break;
case 8:
if (first_day_of_month>4) week=(first_day_of_month+212+leap)/7;
else week=(first_day_of_month+212+leap + 1)/7;
break;
case 9:
if (first_day_of_month>4) week=(first_day_of_month+243+leap)/7;
else week=(first_day_of_month+243+leap + 1)/7;
break;
case 10:
if (first_day_of_month>4) week=(first_day_of_month+273+leap)/7;
else week=(first_day_of_month+273+leap + 1)/7;
break;
case 11:
if (first_day_of_month>4) week=(first_day_of_month+304+leap)/7;
else week=(first_day_of_month+304+leap + 1)/7;
break;
case 12:

if(first_day_of_month>=5)week=(first_day_of_month+334+leap+1)/7;
else week=(first_day_of_month+334+leap)/7+1;
break;
}

week0 = week;
}

/*-------------------------------------------------------------------*/
/* calculating total days of the month */
/*-------------------------------------------------------------------*/
int total_days_of_month(void)
{
int total_days;

if (month==1) total_days=31;
else if (leap==0 && month==2) total_days=28;
else if (leap==1 && month==2) total_days=29;
else if (month==3) total_days=31;
else if (month==4 ) total_days=30;
else if (month==5 ) total_days=31;
else if (month==6 ) total_days=30;
else if (month==7 ) total_days=31;
else if (month==8 ) total_days=31;
else if (month==9 ) total_days=30;
else if (month==10) total_days=31;
else if (month==11) total_days=30;
else total_days=31;

return total_days;
}

/*-------------------------------------------------------------------*/
/* manipulating string to be printed */
/*-------------------------------------------------------------------*/

void space(int ee, int ff)


{
int cal;
int a, b, c, d;
int total_weeks, total_weeks_pre_year;
int tot_day;

a = day_of_week1 ( year, 1 );
b = day_of_week1( year, 12);

if ( month == 12 && ( a ==4 || b == 4 ) )


total_weeks = 53;
if ( month == 12 && ! ( a == 4 || b == 4 ) )
total_weeks = 52;

c = day_of_week1 (year - 1, 1);


d = day_of_week1 (year - 1, 1);

if ( month == 1 && ( c == 4|| d == 4 ) )


total_weeks_pre_year = 53;
if ( month == 1 && ! ( c == 4|| d == 4 ) )
total_weeks_pre_year = 52;

if(ee==0){

switch(ff){
case 2: s[2]='n'; s[1]='u'; s[0]='S'; break;
case 3: s[2]='n'; s[1]='o'; s[0]='M'; break;
case 4: s[2]='e'; s[1]='u'; s[0]='T'; break;
case 5: s[2]='d'; s[1]='e'; s[0]='W'; break;
case 6: s[2]='u'; s[1]='h'; s[0]='T'; break;
case 7: s[2]='i'; s[1]='r'; s[0]='F'; break;
case 8: s[2]='t'; s[1]='a'; s[0]='S'; break;

}
}
else{

tot_day = total_days_of_month();

if(ee>0 && ff==1) {

if ( month == 12 && week0 > total_weeks )


week0=1;
if( month ==1 && first_day_of_month >= 5 && ee == 1 )
week0 = total_weeks_pre_year;
if( month ==1 && first_day_of_month >= 5 && ee == 2 )
week0 = 1;

r=week0%10;
q=week0/10;

if (q==0) u_10=(char)' ';


else if (q==1) u_10=(char)'1';
else if (q==2) u_10=(char)'2';
else if (q==3) u_10=(char)'3';
else if (q==4) u_10=(char)'4';
else u_10=(char)'5';

switch(r){
case 0:u_1=48;break;
case 1:u_1=49;break;
case 2:u_1=50;break;
case 3:u_1=51;break;
case 4:u_1=52;break;
case 5:u_1=53;break;
case 6:u_1=54;break;
case 7:u_1=55;break;
case 8:u_1=56;break;
case 9:u_1=57;break;
}

s[0]=' ';
s[1]=u_10;
s[2]=u_1;
s[3]=' ';
s[4]='\0';

week0++;

} //end of if

else if(ee==1 && ff<(first_day_of_month+2)) s[0]='\0';

else {
if ( in > tot_day )
{
s[0]='\0';
if ( ee == 6 && ff == 8 ) in=1;
return;
} //end of insder if
r=in%10;
q=in/10;
if (q==0) u_10=(char)' ';
else if (q==1) u_10=(char)'1';
else if (q==2) u_10=(char)'2';
else u_10=(char)'3';

switch(r){
case 0:u_1=48;break;
case 1:u_1=49;break;
case 2:u_1=50;break;
case 3:u_1=51;break;
case 4:u_1=52;break;
case 5:u_1=53;break;
case 6:u_1=54;break;
case 7:u_1=55;break;
case 8:u_1=56;break;
case 9:u_1=57;break;
}

s[0]=' ';
s[1]=u_10;
s[2]=u_1;
s[3]=' ';s[4]='\0';

in++;
}//else if in else
}//end of main if-else
}//end of pro

/*-------------------------------------------------------------------*/
/* it is a callback function. */
/* GTK will make main() to terminate if delete event occurs */
/*-------------------------------------------------------------------*/
static gboolean delete_event( GtkWidget *widget, GdkEvent *event, gpointer
data){
gtk_main_quit();
return FALSE;
}
/*-------------------------------------------------------------------*/
/* gets the current value at the spinbutton for year */
/*-------------------------------------------------------------------*/

static int get_value_year(void){

year=gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin_year));

}
/*-----------------------------------------------------------------------*/
/* gets the current value at the spinbutton for month */
/*-----------------------------------------------------------------------*/

static int get_value_mon(void){

month=gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin_mon));

/*-------------------------------------------------------------------*/
/* printing the calendar on the screen */
/*-------------------------------------------------------------------*/

void dar(void)
{
int it=0,jt=0,count=0;

calculation();

for(it=0;it<=6;it++){

count++;
x=10;y=10;
y=y+(count*22);

for(jt=1;jt<=8;jt++){
x=x+30;
space(it,jt);

text=gtk_text_view_new();
gtk_fixed_put (GTK_FIXED (fixed), text, x, y);
gtk_widget_set_size_request (text,30,22);
gtk_text_view_set_editable (GTK_TEXT_VIEW (text), FALSE);
gtk_text_view_set_accepts_tab (GTK_TEXT_VIEW (text),
FALSE);
if(i==0) {
gtk_text_view_set_justification (GTK_TEXT_VIEW(text),
GTK_JUSTIFY_CENTER);
}
else {
gtk_text_view_set_justification (GTK_TEXT_VIEW(text),
GTK_JUSTIFY_RIGHT);
}
gtk_text_view_get_justification (GTK_TEXT_VIEW(text));
gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (text),
FALSE);
gtk_text_buffer_set_text (gtk_text_view_get_buffer
(GTK_TEXT_VIEW (text)),s, -1);
gtk_widget_show(text);
}
}
return;
}

/*-------------------------------------------------------------------*/
/* beginning of main() */
/*-------------------------------------------------------------------*/

int main( int argc,


char *argv[])
{

GtkWidget *window; //declares pointer to the main window


GtkWidget *button_quit; //declares pointer to button_quit
GtkObject *spinbutton_adj;
GtkObject *spin_year_adj;

double t;

gtk_init (&argc,&argv); //calls system settings

//time functions & structure


//calls current system date
t0=time(NULL);
ptr=localtime(&t0);
month_day = ptr->tm_mday;
month = ptr->tm_mon+1;
year = ptr->tm_year+1900;
weekday = ptr->tm_wday;
yearday = ptr->tm_yday;
hour = ptr->tm_hour;
minute = ptr->tm_min;
second = ptr->tm_sec;

/*-------------------------------------------------------------------*/
/* creates the main window & set attributes for it */
/*-------------------------------------------------------------------*/
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_widget_set_size_request (window, 350, 250);
gtk_window_set_title( GTK_WINDOW(window),"Calender");
gtk_window_resize (GTK_WINDOW (window),350,250);
gtk_window_set_resizable(GTK_WINDOW(window),FALSE);
g_signal_connect(G_OBJECT(window), "delete_event",
G_CALLBACK(delete_event), NULL);
/*-------------------------------------------------------------------*/
/* creats a fixed container which contains widgets in fixed position */
/*-------------------------------------------------------------------*/
fixed=gtk_fixed_new();
gtk_container_add( GTK_CONTAINER(window), fixed);
gtk_widget_show(fixed);
/*-------------------------------------------------------------------*/
/* creates the "Quit" button & set attributes for it */
/*-------------------------------------------------------------------*/
button_quit=gtk_button_new_with_label("Quit");
g_signal_connect(G_OBJECT(button_quit), "clicked",
G_CALLBACK(delete_event),(gpointer) fixed);
gtk_fixed_put(GTK_FIXED(fixed),button_quit,300,200);

/*-------------------------------------------------------------------*/
/* creating multiple textview for showing date,weekday & weeknumber */
/*-------------------------------------------------------------------*/

dar();

spinbutton_adj = gtk_adjustment_new (month, 1, 12, 1, 10, 10);


spin_mon= gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton_adj), 1,
0);
gtk_fixed_put (GTK_FIXED (fixed), spin_mon, 106, 188);
gtk_widget_set_size_request (spin_mon, 41, 23);
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spin_mon), TRUE);
gtk_spin_button_get_update_policy (GTK_SPIN_BUTTON (spin_mon));
gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spin_mon), TRUE);
g_signal_connect(G_OBJECT(spin_mon),"value_changed",
G_CALLBACK(get_value_mon),(gpointer)spin_mon);
g_signal_connect(G_OBJECT(spin_mon),"value_changed",
G_CALLBACK(dar),NULL);

spin_year_adj = gtk_adjustment_new (year, 1752, 2100, 1, 10, 10);


spin_year = gtk_spin_button_new (GTK_ADJUSTMENT(spin_year_adj),1, 0);

//put spin_year in a fixed position in the main window

gtk_fixed_put (GTK_FIXED (fixed), spin_year, 164, 188);

//requests the size for spin_year

gtk_widget_set_size_request (spin_year, 50, 23);


gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spin_year), TRUE);
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spin_year), TRUE);
g_signal_connect(G_OBJECT(spin_year),"value_changed",
G_CALLBACK(get_value_year),(gpointer) spin_year);
g_signal_connect(G_OBJECT(spin_year),"value_changed",
G_CALLBACK(dar),NULL);
gtk_widget_show (spin_mon); //shows the spinbutton for
month
gtk_widget_show (spin_year); //shows the spinbutton for
year
gtk_widget_show(button_quit); //shows "Quit" button
gtk_widget_show (window); //shows the main window
/*-------------------------------------------------------------------*/
/* waiting for X events(such as button or key presses), timeouts or */
/* file IO notifications to occur */
/*-------------------------------------------------------------------*/
gtk_main();

return 0;

} // end of main()

Das könnte Ihnen auch gefallen