* straighten the calendar service define / switch /configure
[citadel.git] / webcit / calendar_view.c
1 /*
2  * $Id$
3  */
4 /**
5  * \defgroup CalHtmlHandles Handles the HTML display of calendar items.
6  * \ingroup Calendaring
7  */
8 /*@{*/
9 #include "webcit.h"
10 #include "webserver.h"
11
12 #ifdef WEBCIT_WITH_CALENDAR_SERVICE
13
14 /****************************************************************************/
15
16 /**
17  * \brief Display one day of a whole month view of a calendar
18  * \param thetime the month we want to see 
19  */
20 void calendar_month_view_display_events(time_t thetime) {
21         int i;
22         time_t event_tt;
23         time_t event_tt_stripped;
24         time_t event_tte;
25         struct tm event_tm;
26         struct tm today_tm;
27         icalproperty *p = NULL;
28         icalproperty *pe = NULL;
29         icalproperty *q = NULL;
30         struct icaltimetype t;
31         int month, day, year;
32         int all_day_event = 0;
33         int multi_day_event = 0;
34         int fill_day_event = 0;
35         int show_event = 0;
36         time_t tt;
37         char buf[256];
38
39         if (WC->num_cal == 0) {
40                 wprintf("<br /><br /><br />\n");
41                 return;
42         }
43
44         localtime_r(&thetime, &today_tm);
45         month = today_tm.tm_mon + 1;
46         day = today_tm.tm_mday;
47         year = today_tm.tm_year + 1900;
48
49         for (i=0; i<(WC->num_cal); ++i) {
50                 fill_day_event = 0;
51                 multi_day_event = 0;
52                 p = icalcomponent_get_first_property(WC->disp_cal[i].cal,
53                                                 ICAL_DTSTART_PROPERTY);
54                 pe = icalcomponent_get_first_property(WC->disp_cal[i].cal,
55                                                       ICAL_DTEND_PROPERTY);
56                 if (p != NULL) {
57                         t = icalproperty_get_dtstart(p);
58                         event_tt = icaltime_as_timet(t);
59                         if (t.is_date) all_day_event = 1;
60                         else all_day_event = 0;
61
62                         if (all_day_event) {
63                                 gmtime_r(&event_tt, &event_tm); 
64                                 event_tm.tm_sec = 0;
65                                 event_tm.tm_min = 0;
66                                 event_tm.tm_hour = 0; 
67                                 // are we today?
68                                 event_tt_stripped = mktime (&event_tm);
69                                 show_event = thetime == event_tt_stripped;
70                         }
71                         else {
72                                 localtime_r(&event_tt, &event_tm);
73                                 // we're not interested in the hours. 
74                                 // we just want the date for easy comparison.
75                                 event_tm.tm_min = 0;
76                                 event_tm.tm_hour = 0; 
77                                 event_tt_stripped = mktime (&event_tm);
78                                 if (pe != NULL)  // do we have a span?
79                                 {
80                                         struct tm event_ttm;
81                                         time_t event_end_stripped;
82
83                                         t = icalproperty_get_dtend(pe);
84                                         event_tte = icaltime_as_timet(t);                                       
85                                         gmtime_r(&event_tte, &event_ttm); 
86                                         event_ttm.tm_sec = 0;
87                                         event_ttm.tm_min = 0;
88                                         event_ttm.tm_hour = 0;
89                                         event_end_stripped = mktime(&event_ttm);
90
91                                         // do we span ore than one day?
92                                         multi_day_event = event_tt_stripped != event_end_stripped;
93
94                                         // are we in the range of the event?
95                                         show_event = ((event_tt_stripped <= thetime) && 
96                                                       (event_end_stripped >= thetime));
97
98                                         // are we not start or end day?
99                                         fill_day_event = ((event_tt_stripped < thetime) && 
100                                                       (event_end_stripped > thetime));
101                                 }
102                                 else {
103                                         // are we today?
104                                         show_event = event_tt_stripped == thetime;
105                                 }
106                         }
107
108                         if (show_event) {
109                                 p = icalcomponent_get_first_property(
110                                                         WC->disp_cal[i].cal,
111                                                         ICAL_SUMMARY_PROPERTY);
112                                 if (p != NULL) {
113
114                                         if (all_day_event) {
115                                                 wprintf("<table border=0 cellpadding=2><TR>"
116                                                         "<td bgcolor=\"#CCCCDD\">"
117                                                 );
118                                         }
119
120                                         wprintf("<font size=-1>"
121                                                 "<a href=\"display_edit_event?"
122                                                 "msgnum=%ld&calview=%s&year=%s&month=%s&day=%s\""
123                                                 " btt_tooltext=\"",
124                                                 WC->disp_cal[i].cal_msgnum,
125                                                 bstr("calview"),
126                                                 bstr("year"),
127                                                 bstr("month"),
128                                                 bstr("day")
129                                         );
130
131                                         wprintf("<i>%s</i> ", _("Summary:"));
132                                         escputs((char *)icalproperty_get_comment(p));
133                                         wprintf("<br />");
134
135                                         q = icalcomponent_get_first_property(
136                                                         WC->disp_cal[i].cal,
137                                                         ICAL_LOCATION_PROPERTY);
138                                         if (q) {
139                                                 wprintf("<i>%s</i> ", _("Location:"));
140                                                 escputs((char *)icalproperty_get_comment(q));
141                                                 wprintf("<br />");
142                                         }
143
144                                         /**
145                                          * Only show start/end times if we're actually looking at the VEVENT
146                                          * component.  Otherwise it shows bogus dates for e.g. timezones
147                                          */
148                                         if (icalcomponent_isa(WC->disp_cal[i].cal) == ICAL_VEVENT_COMPONENT) {
149                                 
150                                                 q = icalcomponent_get_first_property(WC->disp_cal[i].cal,
151                                                                                 ICAL_DTSTART_PROPERTY);
152                                                 if (q != NULL) {
153                                                         t = icalproperty_get_dtstart(q);
154                                 
155                                                         if (t.is_date) {
156                                                                 struct tm d_tm;
157                                                                 char d_str[32];
158                                                                 memset(&d_tm, 0, sizeof d_tm);
159                                                                 d_tm.tm_year = t.year - 1900;
160                                                                 d_tm.tm_mon = t.month - 1;
161                                                                 d_tm.tm_mday = t.day;
162                                                                 wc_strftime(d_str, sizeof d_str, "%x", &d_tm);
163                                                                 wprintf("<i>%s</i> %s<br>",
164                                                                         _("Date:"), d_str);
165                                                         }
166                                                         else {
167                                                                 tt = icaltime_as_timet(t);
168                                                                 fmt_date(buf, tt, 1);
169                                                                 wprintf("<i>%s</i> %s<br>",
170                                                                         _("Starting date/time:"), buf);
171
172                                                                 /* Embed the 'show end date/time' loop inside here so it
173                                                                  * only executes if this is NOT an all day event.
174                                                                  */
175                                                                 q = icalcomponent_get_first_property(WC->disp_cal[i].cal,
176                                                                                                         ICAL_DTEND_PROPERTY);
177                                                                 if (q != NULL) {
178                                                                         t = icalproperty_get_dtend(q);
179                                                                         tt = icaltime_as_timet(t);
180                                                                         fmt_date(buf, tt, 1);
181                                                                         wprintf("<i>%s</i> %s<br>",
182                                                                                 _("Ending date/time:"), buf);
183                                                                 }
184
185                                                         }
186                                                 }
187                                         
188                                         }
189
190                                         q = icalcomponent_get_first_property(
191                                                         WC->disp_cal[i].cal,
192                                                         ICAL_DESCRIPTION_PROPERTY);
193                                         if (q) {
194                                                 wprintf("<i>%s</i> ", _("Notes:"));
195                                                 escputs((char *)icalproperty_get_comment(q));
196                                                 wprintf("<br />");
197                                         }
198
199                                         wprintf("\">");
200                                         escputs((char *)
201                                                 icalproperty_get_comment(p));
202                                         wprintf("</a></font><br />\n");
203
204                                         if (all_day_event) {
205                                                 wprintf("</td></tr></table>");
206                                         }
207
208                                 }
209
210                         }
211
212
213                 }
214         }
215 }
216
217
218 /**
219  * \brief Display one day of a whole month view of a calendar
220  * \param thetime the month we want to see 
221  */
222 void calendar_month_view_brief_events(time_t thetime, const char *daycolor) {
223         int i;
224         time_t event_tt;
225         time_t event_tts;
226         time_t event_tte;
227         struct tm event_tms;
228         struct tm event_tme;
229         struct tm today_tm;
230         icalproperty *p;
231         icalproperty *e;
232         struct icaltimetype t;
233         int month, day, year;
234         int all_day_event = 0;
235         char *timeformat;
236         int time_format;
237         
238         time_format = get_time_format_cached ();
239
240         if (time_format == WC_TIMEFORMAT_24) timeformat="%k:%M";
241         else timeformat="%I:%M %p";
242
243         localtime_r(&thetime, &today_tm);
244         month = today_tm.tm_mon + 1;
245         day = today_tm.tm_mday;
246         year = today_tm.tm_year + 1900;
247
248         for (i=0; i<(WC->num_cal); ++i) {
249                 p = icalcomponent_get_first_property(WC->disp_cal[i].cal,
250                                                 ICAL_DTSTART_PROPERTY);
251                 if (p != NULL) {
252                         t = icalproperty_get_dtstart(p);
253                         event_tt = icaltime_as_timet(t);
254                         event_tts=event_tt;
255                         if (t.is_date) all_day_event = 1;
256                         else all_day_event = 0;
257
258                         if (all_day_event) {
259                                 gmtime_r(&event_tts, &event_tms);
260                         }
261                         else {
262                                 localtime_r(&event_tts, &event_tms);
263                         }
264                         /** \todo epoch &! daymask */
265                         if ((event_tms.tm_year == today_tm.tm_year)
266                            && (event_tms.tm_mon == today_tm.tm_mon)
267                            && (event_tms.tm_mday == today_tm.tm_mday)) {
268                                 
269                                 
270                                 char sbuf[255];
271                                 char ebuf[255];
272
273                                 p = icalcomponent_get_first_property(
274                                                         WC->disp_cal[i].cal,
275                                                         ICAL_SUMMARY_PROPERTY);
276                                 e = icalcomponent_get_first_property(
277                                                         WC->disp_cal[i].cal, 
278                                                         ICAL_DTEND_PROPERTY);
279                                 if ((p != NULL) && (e != NULL)) {
280                                         time_t difftime;
281                                         int hours, minutes;
282                                         t = icalproperty_get_dtend(e);
283                                         event_tte = icaltime_as_timet(t);
284                                         localtime_r(&event_tte, &event_tme);
285                                         difftime=(event_tte-event_tts)/60;
286                                         hours=(int)(difftime / 60);
287                                         minutes=difftime % 60;
288                                         wprintf("<tr><td bgcolor='%s'>%i:%2i</td><td bgcolor='%s'>"
289                                                         "<font size=-1>"
290                                                         "<a href=\"display_edit_event?msgnum=%ld&calview=%s&year=%s&month=%s&day=%s\">",
291                                                         daycolor,
292                                                         hours, minutes,
293                                                         daycolor,
294                                                         WC->disp_cal[i].cal_msgnum,
295                                                         bstr("calview"),
296                                                         bstr("year"),
297                                                         bstr("month"),
298                                                         bstr("day")
299                                                         );
300
301                                         escputs((char *)
302                                                         icalproperty_get_comment(p));
303                                         /** \todo: allso ammitime format */
304                                         wc_strftime(&sbuf[0], sizeof(sbuf), timeformat, &event_tms);
305                                         wc_strftime(&ebuf[0], sizeof(sbuf), timeformat, &event_tme);
306
307                                         wprintf("</a></font></td>"
308                                                         "<td bgcolor='%s'>%s</td><td bgcolor='%s'>%s</td></tr>",
309                                                         daycolor,
310                                                         sbuf,
311                                                         daycolor,
312                                                         ebuf);
313                                         
314                                 }
315                                 
316                         }
317                         
318                         
319                 }
320         }
321 }
322
323
324 /**
325  * \brief view one month. pretty view
326  * \param year the year
327  * \param month the month
328  * \param day the actual day we want to see
329  */
330 void calendar_month_view(int year, int month, int day) {
331         struct tm starting_tm;
332         struct tm tm;
333         time_t thetime;
334         int i;
335         time_t previous_month;
336         time_t next_month;
337         time_t colheader_time;
338         struct tm colheader_tm;
339         char colheader_label[32];
340         int chg_month = 0;
341
342         /** Determine what day to start.
343          * First, back up to the 1st of the month...
344          */
345         memset(&starting_tm, 0, sizeof(struct tm));
346         starting_tm.tm_year = year - 1900;
347         starting_tm.tm_mon = month - 1;
348         starting_tm.tm_mday = day;
349         thetime = mktime(&starting_tm);
350
351         memcpy(&tm, &starting_tm, sizeof(struct tm));
352         while (tm.tm_mday != 1) {
353                 thetime = thetime - (time_t)86400;      /* go back 24 hours */
354                 localtime_r(&thetime, &tm);
355         }
356
357         /** Determine previous and next months ... for links */
358         previous_month = thetime - (time_t)864000L;     /* back 10 days */
359         next_month = thetime + (time_t)(31L * 86400L);  /* ahead 31 days */
360
361         /** Now back up until we're on a Sunday */
362         localtime_r(&thetime, &tm);
363         while (tm.tm_wday != 0) {
364                 thetime = thetime - (time_t)86400;      /* go back 24 hours */
365                 localtime_r(&thetime, &tm);
366         }
367
368         /** Outer table (to get the background color) */
369         wprintf("<div class=\"fix_scrollbar_bug\">"
370                 "<table class=\"calendar\"> \n <tr><td>"); 
371
372         wprintf("<table width=100%% border=0 cellpadding=0 cellspacing=0><tr>\n");
373
374         wprintf("<td align=center>");
375
376         localtime_r(&previous_month, &tm);
377         wprintf("<a href=\"readfwd?calview=month&year=%d&month=%d&day=1\">",
378                 (int)(tm.tm_year)+1900, tm.tm_mon + 1);
379         wprintf("<img align=middle src=\"static/prevdate_32x.gif\" border=0></A>\n");
380
381         wc_strftime(colheader_label, sizeof colheader_label, "%B", &starting_tm);
382         wprintf("&nbsp;&nbsp;"
383                 "<font size=+1 color=\"#FFFFFF\">"
384                 "%s %d"
385                 "</font>"
386                 "&nbsp;&nbsp;", colheader_label, year);
387
388         localtime_r(&next_month, &tm);
389         wprintf("<a href=\"readfwd?calview=month&year=%d&month=%d&day=1\">",
390                 (int)(tm.tm_year)+1900, tm.tm_mon + 1);
391         wprintf("<img align=middle src=\"static/nextdate_32x.gif\" border=0></A>\n");
392
393         wprintf("</td></tr></table>\n");
394
395         /** Inner table (the real one) */
396         wprintf("<table width=100%% border=0 cellpadding=1 cellspacing=1 "
397                 "bgcolor=#204B78 id=\"inner_month\"><tr>");
398         colheader_time = thetime;
399         for (i=0; i<7; ++i) {
400                 colheader_time = thetime + (i * 86400) ;
401                 localtime_r(&colheader_time, &colheader_tm);
402                 wc_strftime(colheader_label, sizeof colheader_label, "%A", &colheader_tm);
403                 wprintf("<td align=center width=14%%>"
404                         "<font color=\"#FFFFFF\">%s</font></th>", colheader_label);
405
406         }
407         wprintf("</tr>\n");
408
409
410         /** Now do 35 or 42 days */
411         for (i = 0; i < 42; ++i) {
412                 localtime_r(&thetime, &tm);
413
414                 if ((i < 35) || (chg_month == 0)) {
415
416                         if ((i > 27) && ((tm.tm_mday == 1) || (tm.tm_mday == 31))) {
417                                 chg_month = 1;
418                         }
419                         if (i > 35) {
420                                 chg_month = 0;
421                         }
422
423                         /** Before displaying Sunday, start a new row */
424                         if ((i % 7) == 0) {
425                                 wprintf("<tr>");
426                         }
427
428                         wprintf("<td class=\"cal%s\"><div class=\"day\">",
429                                 ((tm.tm_mon != month-1) ? "out" :
430                                 ((tm.tm_wday==0 || tm.tm_wday==6) ? "weekend" :
431                                 "day"))
432                         );
433                         if ((i==0) || (tm.tm_mday == 1)) {
434                                 wc_strftime(colheader_label, sizeof colheader_label, "%B", &tm);
435                                 wprintf("%s ", colheader_label);
436                         }
437                         wprintf("<a href=\"readfwd?calview=day&year=%d&month=%d&day=%d\">"
438                                 "%d</a></div>",
439                                 tm.tm_year + 1900,
440                                 tm.tm_mon + 1,
441                                 tm.tm_mday,
442                                 tm.tm_mday);
443
444                         /** put the data here, stupid */
445                         calendar_month_view_display_events(thetime);
446
447                         wprintf("</td>");
448
449                         /** After displaying Saturday, end the row */
450                         if ((i % 7) == 6) {
451                                 wprintf("</tr>\n");
452                         }
453
454                 }
455
456                 thetime += (time_t)86400;               /** ahead 24 hours */
457         }
458
459         wprintf("</table>"                      /** end of inner table */
460                 "</td></tr></table>"            /** end of outer table */
461                 "</div>\n");
462
463         /**
464          * Initialize the bubble tooltips.
465          *
466          * Yes, this is as stupid as it looks.  Instead of just making the call
467          * to btt_enableTooltips() straight away, we have to create a timer event
468          * and let it initialize as an event after 1 millisecond.  This is to
469          * work around a bug in Internet Explorer that causes it to crash if we
470          * manipulate the innerHTML of various DOM nodes while the page is still
471          * being rendered.  See http://www.shaftek.org/blog/archives/000212.html
472          * for more information.
473          */ 
474         wprintf("<script type=\"text/javascript\">"
475                 " setTimeout(\"btt_enableTooltips('inner_month')\", 1); "
476                 "</script>\n"
477         );
478 }
479
480 /**
481  * \brief view one month. brief view
482  * \param year the year
483  * \param month the month
484  * \param day the actual day we want to see
485  */
486 void calendar_brief_month_view(int year, int month, int day) {
487         struct tm starting_tm;
488         struct tm tm;
489         time_t thetime;
490         int i;
491         time_t previous_month;
492         time_t next_month;
493         char month_label[32];
494
495         /** Determine what day to start.
496          * First, back up to the 1st of the month...
497          */
498         memset(&starting_tm, 0, sizeof(struct tm));
499         starting_tm.tm_year = year - 1900;
500         starting_tm.tm_mon = month - 1;
501         starting_tm.tm_mday = day;
502         thetime = mktime(&starting_tm);
503
504         memcpy(&tm, &starting_tm, sizeof(struct tm));
505         while (tm.tm_mday != 1) {
506                 thetime = thetime - (time_t)86400;      /* go back 24 hours */
507                 localtime_r(&thetime, &tm);
508         }
509
510         /** Determine previous and next months ... for links */
511         previous_month = thetime - (time_t)864000L;     /* back 10 days */
512         next_month = thetime + (time_t)(31L * 86400L);  /* ahead 31 days */
513
514         /** Now back up until we're on a Sunday */
515         localtime_r(&thetime, &tm);
516         while (tm.tm_wday != 0) {
517                 thetime = thetime - (time_t)86400;      /* go back 24 hours */
518                 localtime_r(&thetime, &tm);
519         }
520
521         /** Outer table (to get the background color) */
522         wprintf("<div class=\"fix_scrollbar_bug\">"
523                 "<table width=100%% border=0 cellpadding=0 cellspacing=0 "
524                 "bgcolor=#204B78><TR><TD>\n");
525
526         wprintf("<table width=100%% border=0 cellpadding=0 cellspacing=0><tr>\n");
527
528         wprintf("<td align=center>");
529
530         localtime_r(&previous_month, &tm);
531         wprintf("<a href=\"readfwd?calview=month&year=%d&month=%d&day=1\">",
532                 (int)(tm.tm_year)+1900, tm.tm_mon + 1);
533         wprintf("<img align=middle src=\"static/prevdate_32x.gif\" border=0></A>\n");
534
535         wc_strftime(month_label, sizeof month_label, "%B", &tm);
536         wprintf("&nbsp;&nbsp;"
537                 "<font size=+1 color=\"#FFFFFF\">"
538                 "%s %d"
539                 "</font>"
540                 "&nbsp;&nbsp;", month_label, year);
541
542         localtime_r(&next_month, &tm);
543         wprintf("<a href=\"readfwd?calview=month&year=%d&month=%d&day=1\">",
544                 (int)(tm.tm_year)+1900, tm.tm_mon + 1);
545         wprintf("<img align=middle src=\"static/nextdate_32x.gif\" border=0></A>\n");
546
547         wprintf("</td></tr></table>\n");
548
549         /** Inner table (the real one) */
550         wprintf("<table width=100%% border=0 cellpadding=1 cellspacing=1 "
551                 "bgcolor=#EEEECC><TR>");
552         wprintf("</tr>\n");
553         wprintf("<tr><td colspan=\"100%\">\n");
554
555         /** Now do 35 days */
556         for (i = 0; i < 35; ++i) {
557                 char weeknumber[255];
558                 char weekday_name[32];
559                 char *daycolor;
560                 localtime_r(&thetime, &tm);
561
562
563                 /** Before displaying Sunday, start a new CELL */
564                 if ((i % 7) == 0) {
565                         wc_strftime(&weeknumber[0], sizeof(weeknumber), "%U", &tm);
566                         wprintf("<table border='0' bgcolor=\"#EEEECC\" width='100%'> <tr><th colspan='4'>%s %s</th></tr>"
567                                         "   <tr><td>%s</td><td width=70%%>%s</td><td>%s</td><td>%s</td></tr>\n",
568                                         _("Week"), 
569                                         weeknumber,
570                                         _("Hours"),
571                                         _("Subject"),
572                                         _("Start"),
573                                         _("End")
574                                         );
575                 }
576                 
577                 daycolor=((tm.tm_mon != month-1) ? "DDDDDD" :
578                                   ((tm.tm_wday==0 || tm.tm_wday==6) ? "EEEECC" :
579                                    "FFFFFF"));
580                 
581                 /** Day Header */
582                 wc_strftime(weekday_name, sizeof weekday_name, "%A", &tm);
583                 wprintf("<tr><td bgcolor='%s' colspan='1' align='left'> %s,%i."
584                                 "</td><td bgcolor='%s' colspan='3'><hr></td></tr>\n",
585                                 daycolor,
586                                 weekday_name,tm.tm_mday,
587                                 daycolor);
588
589                 /** put the data of one day  here, stupid */
590                 calendar_month_view_brief_events(thetime, daycolor);
591
592
593                 /** After displaying Saturday, end the row */
594                 if ((i % 7) == 6) {
595                         wprintf("</td></tr></table>\n");
596                 }
597
598                 thetime += (time_t)86400;               /** ahead 24 hours */
599         }
600
601         wprintf("</table>"                      /** end of inner table */
602                 "</td></tr></table>"            /** end of outer table */
603                 "</div>\n");
604 }
605
606 /** 
607  * \brief view one week
608  * this should view just one week, but it's not here yet.
609  * \todo ny implemented
610  * \param year the year
611  * \param month the month
612  * \param day the day which we want to see the week around
613  */
614 void calendar_week_view(int year, int month, int day) {
615         wprintf("<center><i>week view FIXME</i></center><br />\n");
616 }
617
618
619 /**
620  * \brief display one day
621  * Display events for a particular hour of a particular day.
622  * (Specify hour < 0 to show "all day" events)
623  * \param year the year
624  * \param month the month
625  * \param day the day
626  * \param hour the hour we want to start displaying?????
627  */
628 void calendar_day_view_display_events(int year, int month,
629                                         int day, int hour) {
630         int i;
631         icalproperty *p;
632         icalproperty *pe = NULL;
633         struct icaltimetype t;
634         struct icaltimetype te;
635         time_t event_tt;
636         time_t event_tte;
637         struct tm event_te;
638         struct tm event_tm;
639         int all_day_event = 0;
640
641         if (WC->num_cal == 0) {
642                 // \todo FIXME wprintf("<br /><br /><br />\n");
643                 return;
644         }
645
646         for (i=0; i<(WC->num_cal); ++i) {
647                 p = icalcomponent_get_first_property(WC->disp_cal[i].cal,
648                                                 ICAL_DTSTART_PROPERTY);
649                 pe = icalcomponent_get_first_property(WC->disp_cal[i].cal,
650                                                       ICAL_DTEND_PROPERTY);
651                 if (p != NULL) {
652                         t = icalproperty_get_dtstart(p);
653                         event_tt = icaltime_as_timet(t);
654                         if (t.is_date) {
655                                 all_day_event = 1;
656                         }
657                         else {
658                                 all_day_event = 0;
659                         }
660
661                         if (all_day_event) {
662                                 gmtime_r(&event_tt, &event_tm);
663                                 gmtime_r(&event_tt, &event_te);
664                         }
665                         else {
666                                 localtime_r(&event_tt, &event_tm);
667                                 if (pe != NULL)
668                                 {
669                                         te = icalproperty_get_dtend(pe);
670                                         event_tte = icaltime_as_timet(te);
671                                         localtime_r(&event_tte, &event_te);
672                                 }
673                                 else 
674                                         localtime_r(&event_tt, &event_te);
675                         }
676
677                         if (((event_tm.tm_year <= (year-1900))
678                              && (event_tm.tm_mon <= (month-1))
679                              && (event_tm.tm_mday <= day)
680                              && (event_te.tm_year >= (year-1900))
681                              && (event_te.tm_mon >= (month-1))
682                              && (event_te.tm_mday >= day))
683                             && (
684                                  // are we in the start hour?
685                                     ((event_tm.tm_mday == day)
686                                      && (event_tm.tm_hour == hour) 
687                                      && (!t.is_date)) 
688                                  // are we an all day event?
689                                     || ((hour<0)&&(t.is_date))
690                                  // does it span multible days and we're not at the start day?
691                                     || ((hour<0)
692                                         && (event_tm.tm_mday < day) 
693                                         && (event_te.tm_mday >= day))
694                                     ))
695                         {
696                                 p = icalcomponent_get_first_property(
697                                                         WC->disp_cal[i].cal,
698                                                         ICAL_SUMMARY_PROPERTY);
699                                 if (p != NULL) {
700
701                                         if (all_day_event) {
702                                                 wprintf("<table border=1 cellpadding=2><TR>"
703                                                         "<td bgcolor=\"#CCCCCC\">"
704                                                 );
705                                         }
706
707                                         wprintf("<font size=-1>"
708                                                 "<a href=\"display_edit_event?msgnum=%ld&calview=day&year=%d&month=%d&day=%d\">",
709                                                 WC->disp_cal[i].cal_msgnum,
710                                                 year, month, day
711                                         );
712                                         escputs((char *)
713                                                 icalproperty_get_comment(p));
714                                         wprintf("</a></font><br />\n");
715
716                                         if (all_day_event) {
717                                                 wprintf("</td></tr></table>");
718                                         }
719                                 }
720
721                         }
722
723
724                 }
725         }
726 }
727
728
729 /**
730  * \brief view one day
731  * \param year the year
732  * \param month the month 
733  * \param day the day we want to display
734  */
735 void calendar_day_view(int year, int month, int day) {
736         int hour;
737         struct icaltimetype today, yesterday, tomorrow;
738         int daystart = 8;
739         int dayend = 17;
740         char daystart_str[16], dayend_str[16];
741         struct tm d_tm;
742         char d_str[128];
743         int time_format;
744         
745         time_format = get_time_format_cached ();
746         get_preference("daystart", daystart_str, sizeof daystart_str);
747         if (!IsEmptyStr(daystart_str)) daystart = atoi(daystart_str);
748         get_preference("dayend", dayend_str, sizeof dayend_str);
749         if (!IsEmptyStr(dayend_str)) dayend = atoi(dayend_str);
750         
751
752         /** Figure out the dates for "yesterday" and "tomorrow" links */
753
754         memset(&today, 0, sizeof(struct icaltimetype));
755         today.year = year;
756         today.month = month;
757         today.day = day;
758         today.is_date = 1;
759
760         memcpy(&yesterday, &today, sizeof(struct icaltimetype));
761         --yesterday.day;
762         yesterday = icaltime_normalize(yesterday);
763
764         memcpy(&tomorrow, &today, sizeof(struct icaltimetype));
765         ++tomorrow.day;
766         tomorrow = icaltime_normalize(tomorrow);
767
768
769         /** Outer table (to get the background color) */
770         wprintf("<div class=\"fix_scrollbar_bug\">"
771                 "<table width=100%% border=0 cellpadding=0 cellspacing=0 "
772                 "bgcolor=#204B78><tr><td>\n");
773
774         /** Inner table (the real one) */
775         wprintf("<table width=100%% border=0 cellpadding=1 cellspacing=1 "
776                 "bgcolor=#204B78><tr>\n");
777
778         /** Innermost table (contains hours etc.) */
779         wprintf("<td width=80%%>"
780                 "<table width=100%% border=0 cellpadding=1 cellspacing=1 "
781                 "bgcolor=#204B78>\n");
782
783         /** Display events before 8:00 (hour=-1 is all-day events) */
784         wprintf("<tr>"
785                 "<td bgcolor=\"#CCCCDD\" valign=middle width=10%%></td>"
786                 "<td bgcolor=\"#FFFFFF\" valign=top>");
787         for (hour = (-1); hour <= (daystart-1); ++hour) {
788                 calendar_day_view_display_events(year, month, day, hour);
789         }
790         wprintf("</td></tr>\n");
791
792         /** Now the middle of the day... */     
793         for (hour = daystart; hour <= dayend; ++hour) { /* could do HEIGHT=xx */
794                 wprintf("<tr height=30><td bgcolor=\"#CCCCDD\" align=middle "
795                         "valign=middle width=10%%>");
796                 wprintf("<a href=\"display_edit_event?msgnum=0"
797                         "&year=%d&month=%d&day=%d&hour=%d&minute=0\">",
798                         year, month, day, hour
799                 );
800
801                 if (time_format == WC_TIMEFORMAT_24) {
802                         wprintf("%2d:00</a> ", hour);
803                 }
804                 else {
805                         wprintf("%d:00%s</a> ",
806                                 (hour <= 12 ? hour : hour-12),
807                                 (hour < 12 ? "am" : "pm")
808                         );
809                 }
810
811                 wprintf("</td><td bgcolor=\"#FFFFFF\" valign=top>");
812
813                 /* put the data here, stupid */
814                 calendar_day_view_display_events(year, month, day, hour);
815
816                 wprintf("</td></tr>\n");
817         }
818
819         /** Display events after 5:00... */
820         wprintf("<tr>"
821                 "<td bgcolor=\"#CCCCDD\" valign=middle width=10%%></td>"
822                 "<td bgcolor=\"#FFFFFF\" valign=top>");
823         for (hour = (dayend+1); hour <= 23; ++hour) {
824                 calendar_day_view_display_events(year, month, day, hour);
825         }
826         wprintf("</td></tr>\n");
827
828
829         wprintf("</table>"                      /* end of innermost table */
830                 "</td>"
831         );
832
833         wprintf("<td width=20%% valign=top>");  /* begin stuff-on-the-right */
834
835
836         /** Begin todays-date-with-left-and-right-arrows */
837         wprintf("<table border=0 width=100%% "
838                 "cellspacing=0 cellpadding=0 bgcolor=\"#FFFFFF\">\n");
839         wprintf("<tr>");
840
841         /** Left arrow */       
842         wprintf("<td align=center>");
843         wprintf("<a href=\"readfwd?calview=day&year=%d&month=%d&day=%d\">",
844                 yesterday.year, yesterday.month, yesterday.day);
845         wprintf("<img align=middle src=\"static/prevdate_32x.gif\" border=0></A>");
846         wprintf("</td>");
847
848         /** Today's date */
849         memset(&d_tm, 0, sizeof d_tm);
850         d_tm.tm_year = year - 1900;
851         d_tm.tm_mon = month - 1;
852         d_tm.tm_mday = day;
853         wc_strftime(d_str, sizeof d_str,
854                 "<td align=center>"
855                 "<font size=+2>%B</font><br />"
856                 "<font size=+3>%d</font><br />"
857                 "<font size=+2>%Y</font><br />"
858                 "</td>",
859                 &d_tm
860         );
861         wprintf("%s", d_str);
862
863         /** Right arrow */
864         wprintf("<td align=center>");
865         wprintf("<a href=\"readfwd?calview=day&year=%d&month=%d&day=%d\">",
866                 tomorrow.year, tomorrow.month, tomorrow.day);
867         wprintf("<img align=middle src=\"static/nextdate_32x.gif\""
868                 " border=0></A>\n");
869         wprintf("</td>");
870
871         wprintf("</tr></table>\n");
872         /** End todays-date-with-left-and-right-arrows */
873
874         /** \todo In the future we might want to put a month-o-matic here */
875
876         wprintf("</font></center>\n");
877
878         wprintf("</td>");                       /** end stuff-on-the-right */
879
880
881
882         wprintf("</tr></table>"                 /** end of inner table */
883                 "</td></tr></table></div>"      /** end of outer table */
884         );
885
886
887
888 }
889
890 /**
891  * \brief Display today's events.
892  */
893 void calendar_summary_view(void) {
894         int i;
895         icalproperty *p;
896         struct icaltimetype t;
897         time_t event_tt;
898         struct tm event_tm;
899         struct tm today_tm;
900         time_t now;
901         int all_day_event = 0;
902         char timestring[SIZ];
903
904         if (WC->num_cal == 0) {
905                 return;
906         }
907
908         now = time(NULL);
909         localtime_r(&now, &today_tm);
910
911         for (i=0; i<(WC->num_cal); ++i) {
912                 p = icalcomponent_get_first_property(WC->disp_cal[i].cal,
913                                                 ICAL_DTSTART_PROPERTY);
914                 if (p != NULL) {
915                         t = icalproperty_get_dtstart(p);
916                         event_tt = icaltime_as_timet(t);
917                         if (t.is_date) {
918                                 all_day_event = 1;
919                         }
920                         else {
921                                 all_day_event = 0;
922                         }
923                         fmt_time(timestring, event_tt);
924
925                         if (all_day_event) {
926                                 gmtime_r(&event_tt, &event_tm);
927                         }
928                         else {
929                                 localtime_r(&event_tt, &event_tm);
930                         }
931
932                         if ( (event_tm.tm_year == today_tm.tm_year)
933                            && (event_tm.tm_mon == today_tm.tm_mon)
934                            && (event_tm.tm_mday == today_tm.tm_mday)
935                            ) {
936
937
938                                 p = icalcomponent_get_first_property(
939                                                         WC->disp_cal[i].cal,
940                                                         ICAL_SUMMARY_PROPERTY);
941                                 if (p != NULL) {
942                                         escputs((char *)
943                                                 icalproperty_get_comment(p));
944                                         wprintf(" (%s)<br />\n", timestring);
945                                 }
946                         }
947                 }
948         }
949         free_calendar_buffer();
950 }
951
952
953 /**
954  * \brief clean up ical memory
955  * \todo this could get troubel with future ical versions
956  */
957 void free_calendar_buffer(void) {
958         int i;
959         if (WC->num_cal) for (i=0; i<(WC->num_cal); ++i) {
960                 icalcomponent_free(WC->disp_cal[i].cal);
961         }
962         WC->num_cal = 0;
963         free(WC->disp_cal);
964         WC->disp_cal = NULL;
965 }
966
967
968
969 /**
970  * \brief do the whole calendar page
971  * view any part of the calender. decide which way, etc.
972  */
973 void do_calendar_view(void) {
974         time_t now;
975         struct tm tm;
976         int year, month, day;
977         char calview[SIZ];
978
979         /** In case no date was specified, go with today */
980         now = time(NULL);
981         localtime_r(&now, &tm);
982         year = tm.tm_year + 1900;
983         month = tm.tm_mon + 1;
984         day = tm.tm_mday;
985
986         /** Now see if a date was specified */
987         if (!IsEmptyStr(bstr("year"))) year = atoi(bstr("year"));
988         if (!IsEmptyStr(bstr("month"))) month = atoi(bstr("month"));
989         if (!IsEmptyStr(bstr("day"))) day = atoi(bstr("day"));
990
991         /** How would you like that cooked? */
992         if (!IsEmptyStr(bstr("calview"))) {
993                 strcpy(calview, bstr("calview"));
994         }
995         else {
996                 strcpy(calview, "month");
997         }
998
999         /** Display the selected view */
1000         if (!strcasecmp(calview, "day")) {
1001                 calendar_day_view(year, month, day);
1002         }
1003         else if (!strcasecmp(calview, "week")) {
1004                 calendar_week_view(year, month, day);
1005         }
1006         else {
1007                 if (WC->wc_view == VIEW_CALBRIEF) {
1008                         calendar_brief_month_view(year, month, day);
1009                 }
1010                 else {
1011                         calendar_month_view(year, month, day);
1012                 }
1013         }
1014
1015         /** Free the calendar stuff */
1016         free_calendar_buffer();
1017
1018 }
1019
1020
1021 /**
1022  * \brief get task due date
1023  * Helper function for do_tasks_view().  
1024  * \param vtodo a task to get the due date
1025  * \return the date/time due.
1026  */
1027 time_t get_task_due_date(icalcomponent *vtodo) {
1028         icalproperty *p;
1029
1030         if (vtodo == NULL) {
1031                 return(0L);
1032         }
1033
1034         /**
1035          * If we're looking at a fully encapsulated VCALENDAR
1036          * rather than a VTODO component, recurse into the data
1037          * structure until we get a VTODO.
1038          */
1039         if (icalcomponent_isa(vtodo) == ICAL_VCALENDAR_COMPONENT) {
1040                 return get_task_due_date(
1041                         icalcomponent_get_first_component(
1042                                 vtodo, ICAL_VTODO_COMPONENT
1043                         )
1044                 );
1045         }
1046
1047         p = icalcomponent_get_first_property(vtodo, ICAL_DUE_PROPERTY);
1048         if (p != NULL) {
1049                 return(icaltime_as_timet(icalproperty_get_due(p)));
1050         }
1051         else {
1052                 return(0L);
1053         }
1054 }
1055
1056
1057 /**
1058  * \brief Compare the due dates of two tasks (this is for sorting)
1059  * \param task1 first task to compare
1060  * \param task2 second task to compare
1061  */
1062 int task_due_cmp(const void *task1, const void *task2) {
1063         time_t t1;
1064         time_t t2;
1065
1066         t1 =  get_task_due_date(((struct disp_cal *)task1)->cal);
1067         t2 =  get_task_due_date(((struct disp_cal *)task2)->cal);
1068
1069         if (t1 < t2) return(-1);
1070         if (t1 > t2) return(1);
1071         return(0);
1072 }
1073
1074
1075
1076
1077 /**
1078  * \brief do the whole task view stuff
1079  */
1080 void do_tasks_view(void) {
1081         int i;
1082         time_t due;
1083         int bg = 0;
1084         char buf[SIZ];
1085         icalproperty *p;
1086
1087         wprintf("<div class=\"fix_scrollbar_bug\">"
1088                 "<table class=\"calendar_view_background\">\n<tr>\n"
1089                 "<th>");
1090         wprintf(_("Name of task"));
1091         wprintf("</th><th>");
1092         wprintf(_("Date due"));
1093         wprintf("</th></tr>\n"
1094         );
1095
1096         /** Sort them if necessary */
1097         if (WC->num_cal > 1) {
1098                 qsort(WC->disp_cal,
1099                         WC->num_cal,
1100                         sizeof(struct disp_cal),
1101                         task_due_cmp
1102                 );
1103         }
1104
1105         if (WC->num_cal) for (i=0; i<(WC->num_cal); ++i) {
1106
1107                 bg = 1 - bg;
1108                 wprintf("<tr bgcolor=\"#%s\"><td>",
1109                         (bg ? "DDDDDD" : "FFFFFF")
1110                 );
1111
1112                 p = icalcomponent_get_first_property(WC->disp_cal[i].cal,
1113                                                         ICAL_SUMMARY_PROPERTY);
1114                 wprintf("<a href=\"display_edit_task?msgnum=%ld&taskrm=",
1115                         WC->disp_cal[i].cal_msgnum );
1116                 urlescputs(WC->wc_roomname);
1117                 wprintf("\">");
1118                 wprintf("<img align=middle "
1119                         "src=\"static/taskmanag_16x.gif\" border=0>&nbsp;");
1120                 if (p != NULL) {
1121                         escputs((char *)icalproperty_get_comment(p));
1122                 }
1123                 wprintf("</a>\n");
1124                 wprintf("</td>\n");
1125
1126                 due = get_task_due_date(WC->disp_cal[i].cal);
1127                 fmt_date(buf, due, 0);
1128                 wprintf("<td><font");
1129                 if (due < time(NULL)) {
1130                         wprintf(" color=\"#FF0000\"");
1131                 }
1132                 wprintf(">%s</font></td></tr>\n", buf);
1133         }
1134
1135         wprintf("</table></div>\n");
1136
1137         /** Free the list */
1138         free_calendar_buffer();
1139
1140 }
1141
1142 #else   /* WEBCIT_WITH_CALENDAR_SERVICE */
1143
1144 /**\brief stub for non-libical builds */
1145 void do_calendar_view(void) {
1146         wprintf("<center><i>");
1147         wprintf(_("The calendar view is not available."));
1148         wprintf("</i></center><br />\n");
1149 }
1150
1151 /**\brief stub for non-libical builds */
1152 void do_tasks_view(void) {      
1153         wprintf("<center><I>");
1154         wprintf(_("The tasks view is not available."));
1155         wprintf("</i></center><br />\n");
1156 }
1157
1158
1159 #endif  /* WEBCIT_WITH_CALENDAR_SERVICE */
1160
1161 /** @} */