#include "calendar.h" int get_datetype(int day){return datetype[day][0];} /*------------------------------------------------------ * checkicalversion -----------------------------------------------------*/ void checkicalversion() { GtkWidget* dialog; GtkWidget* label; char* msg = "\n\nWARNING:\nIt is highly recommended to upgrade to libical 0.24!\nOtherwise wmCalendar will not work stable!\n"; if(!strcmp(ICAL_VERSION, "0.23")){ printf(msg); dialog = gtk_dialog_new_with_buttons ("Warning", NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_NONE, NULL); label = gtk_label_new (msg); g_signal_connect_swapped (GTK_OBJECT (dialog), "response", G_CALLBACK (gtk_widget_destroy), GTK_OBJECT (dialog)); gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label); gtk_signal_connect (GTK_OBJECT (dialog), "destroy", GTK_SIGNAL_FUNC(gtk_main_quit ), NULL); gtk_widget_show_all (dialog); gtk_main(); } } void move(GtkWidget *widget, GdkEventButton *event) { xr = event->x; yr = event->y; } void move2(GtkWidget *widget, GdkEventMotion *event) { gtk_widget_set_uposition((GtkWidget*)gtk_widget_get_toplevel(widget),event->x_root - xr , event->y_root - yr); } void kill (GtkWidget * widget) { gtk_widget_destroy ((GtkWidget*)gtk_widget_get_toplevel(widget)); gtk_main_quit (); } /*------------------------------------------------------ * calendar -----------------------------------------------------*/ void calendar(){ int value; char* line; const char* text; const char* transp=""; struct stat filestat; icalproperty *prop, *reocc; icalparser *parser; icalcomponent *c, *d; FILE *stream; struct icaltimetype t1, t2; if(get_debug())printf("check for new calendar data\n"); stream = fopen((const char*)get_icsfile(),"r"); if(stream == 0) return; fstat(fileno(stream), &filestat); if(filestat.st_mtime == modtime){ fclose(stream); return; } if(get_debug())printf("read calendar data\n"); deleteCalObjs(); modtime = filestat.st_mtime; parser = icalparser_new(); /* Tell the parser what input routie it should use. */ icalparser_set_gen_data(parser, stream); do{ line = icalparser_get_line(parser, read_stream); c = icalparser_add_line(parser, line); free(line); if(c != 0){ for(d = icalcomponent_get_first_component(c, ICAL_ANY_COMPONENT);d != 0; d = icalcomponent_get_next_component(c, ICAL_ANY_COMPONENT)){ /* get date */ t1 = icalcomponent_get_dtstart(d); t2 = icalcomponent_get_dtend(d); if(icaltime_is_null_time(t2)){ t2 = t1; icaltime_adjust(&t2, 1,0,0,0); } /* get transparency */ prop = icalcomponent_get_first_property(d, ICAL_TRANSP_PROPERTY ); reocc = icalcomponent_get_first_property(d, ICAL_RRULE_PROPERTY); if(prop) transp = icalproperty_get_value_as_string(prop); if(!strcmp(transp, "OPAQUE")) value = 1; else if(!strcmp(transp, "TRANSPARENT")) value = 2; else value = 1 ; /* get desciption */ prop = icalcomponent_get_first_property(d, ICAL_SUMMARY_PROPERTY); if(prop) { text = icalproperty_get_value_as_string(prop); addCalObj(t1, t2, value, text, d); if(get_debug())printf("read: %d.%d.%d - %d.%d.%d %s\n", t1.day, t1.month, t1.year, t2.day, t2.month, t2.year, text); } icalcomponent_free(d); } icalcomponent_free(c); } } while(line != 0); icalparser_free(parser); fclose(stream); } /*------------------------------------------------------ * showDay -----------------------------------------------------*/ void showDay(struct icaltimetype dt){ static GtkWidget *dayView; static GtkWidget *table; static GtkWidget *label1; static GtkWidget *event_box; static GtkWidget *event_box2; char buf[28]; char buf2[28]; struct tm *timptr = NULL; time_t tt = icaltime_as_timet(dt); timptr = gmtime(&tt); event_box = gtk_event_box_new (); gtk_widget_show (event_box); event_box2 = gtk_event_box_new (); gtk_widget_show (event_box2); /* create titlebartext */ strftime(buf, 26, "%A, %x", timptr); sprintf(buf2, "%s",buf); /* Create a new window with no boarder and day as titlebar*/ dayView = gtk_window_new(GTK_WINDOW_TOPLEVEL); // xr =yr =0; gtk_window_set_position(GTK_WINDOW (dayView),GTK_WIN_POS_MOUSE); gtk_window_set_policy(GTK_WINDOW (dayView), FALSE, FALSE, FALSE); gtk_window_set_decorated (GTK_WINDOW (dayView), FALSE); gtk_window_set_title(GTK_WINDOW (dayView), buf); /* create a table */ table = gtk_table_new(1, 4, FALSE); gtk_table_set_row_spacings ((GtkTable*)table, 4); gtk_table_set_col_spacings ((GtkTable*)table, 15); gtk_table_set_col_spacing ((GtkTable*)table,2, 0); gtk_table_attach_defaults (GTK_TABLE(table), event_box, 0, 3, 1, 2); gtk_table_attach_defaults (GTK_TABLE(table), event_box2, 3, 4, 1, 2); label1 = gtk_label_new (NULL); gtk_label_set_markup ((GtkLabel*)label1, buf2); gtk_container_add (GTK_CONTAINER (event_box), label1); gtk_table_set_row_spacing ((GtkTable*)table,0, 1); gtk_table_set_row_spacing ((GtkTable*)table,1, 1); gtk_widget_show (label1); label1 = gtk_label_new (" X "); gtk_container_add (GTK_CONTAINER (event_box2), label1); gtk_widget_show (label1); /* fill table with events and draw window if there are any events */ if(dayevents(dt, table)){ gtk_widget_show (dayView); gtk_widget_show (table); gtk_container_add (GTK_CONTAINER (dayView), table); gtk_signal_connect(GTK_OBJECT (event_box), "motion_notify_event", GTK_SIGNAL_FUNC (move2), NULL); gtk_signal_connect(GTK_OBJECT (event_box), "button_press_event", GTK_SIGNAL_FUNC (move), NULL); gtk_signal_connect(GTK_OBJECT (event_box2), "button_press_event", (GtkSignalFunc) kill, GTK_OBJECT(dayView)); gtk_widget_realize(dayView); // gtk_window_set_position(GTK_WINDOW (dayView),GTK_WIN_POS_CENTER_ON_PARENT); gtk_main (); } } /*------------------------------------------------------ * dayevents -----------------------------------------------------*/ int dayevents(struct icaltimetype dt, GtkWidget *table){ static GtkWidget *label1; struct calobj* it; struct icaltimetype t1, t2; icalproperty *prop; int j; /* tablerow */ char buftime1[30]; char buftime2[30]; char buf[1024]; struct tm *timptr = NULL; time_t tt; GtkWidget *separator; j = 2; it = calRoot; while(it){ if(eventOnDay(dt, it)){ t1 = it->start; t2 = it->end; separator = gtk_hseparator_new (); gtk_widget_show (separator); gtk_table_attach_defaults (GTK_TABLE(table),separator, 0, 4, j, j+1); j++; if(daysEqual(t1, t2)){ /* single event */ /* create time entry */ tt = icaltime_as_timet(t1); timptr = gmtime(&tt); strftime(buftime1, 26, "%X", timptr); tt = icaltime_as_timet(t2); timptr = gmtime(&tt); strftime(buftime2, 26, "%X", timptr); sprintf(buf,"%s - %s",buftime1, buftime2); label1 = gtk_label_new (NULL); gtk_label_set_markup ((GtkLabel*)label1, buf); gtk_table_attach_defaults (GTK_TABLE(table), label1, 1, 2, j, j+1); gtk_widget_show (label1); /* create description entry */ label1 = gtk_label_new (it->text); gtk_table_attach_defaults (GTK_TABLE(table), label1, 2, 3, j, j+1); gtk_widget_show (label1); j++; } else { /* multiday event or allday event*/ t2.day--; /* endtime always on the first day after the event ... */ if(t2.day == 0){ t2.month--; if(t2.month == 0){ t2.month = 12; t2.year--; } t2.day = icaltime_days_in_month(t2.month, t2.year); } if(t2.day < dt.day && t2.month == dt.month && t2.year == dt.year) continue; /* event ended the day before ... */ if(daysEqual(t1,t2)){ /* allday event */ /* create description entry */ sprintf(buf, "all day event"); } else{ /* multiday event */ /* create description with start and enddate */ tt = icaltime_as_timet(t1); timptr = gmtime(&tt); strftime(buftime1, 26, "%a, %x", timptr); tt = icaltime_as_timet(t2); timptr = gmtime(&tt); strftime(buftime2, 26, "%a, %x", timptr); sprintf(buf, "%s - %s", buftime1, buftime2); } label1 = gtk_label_new (NULL); gtk_label_set_markup ((GtkLabel*)label1, buf); gtk_table_attach_defaults (GTK_TABLE(table), label1, 1, 2, j, j+1); gtk_widget_show (label1); prop = icalcomponent_get_first_property(it->comp, ICAL_LOCATION_PROPERTY); if(prop) sprintf(buf, "%s\n%s", it->text, icalproperty_get_location(prop)); else sprintf(buf, "%s", it->text); label1 = gtk_label_new (buf); gtk_label_set_justify(GTK_LABEL(label1),GTK_JUSTIFY_CENTER ); gtk_table_attach_defaults (GTK_TABLE(table), label1, 2, 3, j, j+1); gtk_widget_show (label1); j++; } } it = it->next; } label1 = gtk_label_new (NULL); gtk_table_attach_defaults (GTK_TABLE(table), label1, 2, 3, j+1, j+2); gtk_table_set_row_spacing (GTK_TABLE(table),j, 0); if(j==2) /* no entries for this day */ return FALSE; return TRUE; } /*------------------------------------------------------ * deleteCalObjs -----------------------------------------------------*/ void deleteCalObjs(){ int i; struct calObj* help; while(calRoot){ help = (struct calObj*) calRoot->next; free(calRoot->text); free(calRoot->comp); free(calRoot); calRoot = help; } for(i = 0; i < 32; i++) datetype[i][1] = 0; } /*------------------------------------------------------ * addCalObj -----------------------------------------------------*/ void addCalObj(struct icaltimetype start, struct icaltimetype end, int type, const char *text, icalcomponent * d){ struct calobj *newobj; icalcomponent *newcomp = malloc(sizeof(struct calobj)); char* buf = malloc (strlen(text) + 1); newcomp = icalcomponent_new_clone(d); strcpy(buf,text); newobj = malloc(sizeof(struct calobj)); newobj->comp = newcomp; newobj->start = start; newobj->end = end; newobj->type = type; newobj->text = buf; newobj->next = calRoot; calRoot = newobj; } /*------------------------------------------------------ * getDayType -----------------------------------------------------*/ int getDayType(struct icaltimetype dt){ int jd; jd = civil_jdn(dt); if(datetype[jd % 31][1] == jd) return datetype[jd % 31][0]; return calcDayType(dt); } /*------------------------------------------------------ * isExluded -----------------------------------------------------*/ int isExluded(icalcomponent *comp, struct icaltimetype dt){ icalproperty *prop; prop = icalcomponent_get_first_property(comp, ICAL_EXDATE_PROPERTY); while(prop){ if(daysEqual(icalproperty_get_exdate(prop), dt)) return 1; prop = icalcomponent_get_next_property(comp, ICAL_EXDATE_PROPERTY); } return 0; } /*------------------------------------------------------ * eventOnDay -----------------------------------------------------*/ int eventOnDay(struct icaltimetype dt, struct calobj* it) { icalrecur_iterator* ritr; icalproperty *rrule; struct icaltimetype next; if((daysEarlierEqual(dt, it->start) && daysLater(dt, it->end)) || (daysEqual(dt, it->start) && daysEqual(dt, it->end))) return 1; rrule = icalcomponent_get_first_property((icalcomponent*)it->comp, ICAL_RRULE_PROPERTY); if(rrule){ if(daysEarlierEqual(dt, it->start)){ ritr = icalrecur_iterator_new( icalproperty_get_rrule(rrule), it->start); if(ritr) next = icalrecur_iterator_next(ritr); while(daysEarlierEqual(dt, next) && !icaltime_is_null_time(next)){ if(daysEqual(dt, next) && !isExluded((icalcomponent*)it->comp, dt)) { free(ritr); return 1; } next = icalrecur_iterator_next(ritr); } free(ritr); } } return 0; } /*------------------------------------------------------ * calcDayType -----------------------------------------------------*/ int calcDayType(struct icaltimetype dt){ int jd; struct calobj* it; jd = civil_jdn(dt); datetype[jd % 31][1] = jd; datetype[jd % 31][0] = 0; it = calRoot; while(it){ if(eventOnDay(dt, it)) if(datetype[jd % 31][0] != 1) datetype[jd % 31][0] = it->type; it = it->next; } return datetype[jd % 31][0]; }