ea2a3a995f18c78fd548c82c3da923ffc0762577
[citadel.git] / webcit / calendar_view.c
1 /*
2  * $Id$
3  */
4 /**
5  * \defgroup CalHtmlHandles Handles the HTML display of calendar items.
6  */
7 /*@{*/
8 #include "webcit.h"
9 #include "webserver.h"
10
11 #ifndef WEBCIT_WITH_CALENDAR_SERVICE
12
13 /**\brief stub for non-libical builds */
14 void do_calendar_view(void) {
15         wprintf("<CENTER><I>");
16         wprintf(_("The calendar view is not available."));
17         wprintf("</I></CENTER><br />\n");
18 }
19
20 /**\brief stub for non-libical builds */
21 void do_tasks_view(void) {      
22         wprintf("<CENTER><I>");
23         wprintf(_("The tasks view is not available."));
24         wprintf("</I></CENTER><br />\n");
25 }
26
27 #else   /* WEBCIT_WITH_CALENDAR_SERVICE */
28
29 /****************************************************************************/
30
31 /**
32  * \brief Display a whole month view of a calendar
33  * \param thetime the month we want to see 
34  */
35 void calendar_month_view_display_events(time_t thetime) {
36         int i;
37         time_t event_tt;
38         struct tm event_tm;
39         struct tm today_tm;
40         icalproperty *p;
41         struct icaltimetype t;
42         int month, day, year;
43         int all_day_event = 0;
44
45         if (WC->num_cal == 0) {
46                 wprintf("<br /><br /><br />\n");
47                 return;
48         }
49
50         localtime_r(&thetime, &today_tm);
51         month = today_tm.tm_mon + 1;
52         day = today_tm.tm_mday;
53         year = today_tm.tm_year + 1900;
54
55         for (i=0; i<(WC->num_cal); ++i) {
56                 p = icalcomponent_get_first_property(WC->disp_cal[i].cal,
57                                                 ICAL_DTSTART_PROPERTY);
58                 if (p != NULL) {
59                         t = icalproperty_get_dtstart(p);
60                         event_tt = icaltime_as_timet(t);
61
62                         if (t.is_date) all_day_event = 1;
63                         else all_day_event = 0;
64
65                         if (all_day_event) {
66                                 gmtime_r(&event_tt, &event_tm);
67                         }
68                         else {
69                                 localtime_r(&event_tt, &event_tm);
70                         }
71
72                         if ((event_tm.tm_year == today_tm.tm_year)
73                            && (event_tm.tm_mon == today_tm.tm_mon)
74                            && (event_tm.tm_mday == today_tm.tm_mday)) {
75
76                                 p = icalcomponent_get_first_property(
77                                                         WC->disp_cal[i].cal,
78                                                         ICAL_SUMMARY_PROPERTY);
79                                 if (p != NULL) {
80
81                                         if (all_day_event) {
82                                                 wprintf("<TABLE border=0 cellpadding=2><TR>"
83                                                         "<TD BGCOLOR=\"#CCCCDD\">"
84                                                 );
85                                         }
86
87                                         wprintf("<FONT SIZE=-1>"
88                                                 "<a href=\"display_edit_event?msgnum=%ld&calview=%s&year=%s&month=%s&day=%s\">",
89                                                 WC->disp_cal[i].cal_msgnum,
90                                                 bstr("calview"),
91                                                 bstr("year"),
92                                                 bstr("month"),
93                                                 bstr("day")
94                                         );
95                                         escputs((char *)
96                                                 icalproperty_get_comment(p));
97                                         wprintf("</A></FONT><br />\n");
98
99                                         if (all_day_event) {
100                                                 wprintf("</TD></TR></TABLE>");
101                                         }
102
103                                 }
104
105                         }
106
107
108                 }
109         }
110 }
111
112
113 /**
114  * \brief view one day
115  * \param year the year
116  * \param month the month
117  * \param day the actual day we want to see
118  */
119 void calendar_month_view(int year, int month, int day) {
120         struct tm starting_tm;
121         struct tm tm;
122         time_t thetime;
123         int i;
124         time_t previous_month;
125         time_t next_month;
126
127         /** Determine what day to start.
128          * First, back up to the 1st of the month...
129          */
130         memset(&starting_tm, 0, sizeof(struct tm));
131         starting_tm.tm_year = year - 1900;
132         starting_tm.tm_mon = month - 1;
133         starting_tm.tm_mday = day;
134         thetime = mktime(&starting_tm);
135
136         memcpy(&tm, &starting_tm, sizeof(struct tm));
137         while (tm.tm_mday != 1) {
138                 thetime = thetime - (time_t)86400;      /* go back 24 hours */
139                 localtime_r(&thetime, &tm);
140         }
141
142         /** Determine previous and next months ... for links */
143         previous_month = thetime - (time_t)864000L;     /* back 10 days */
144         next_month = thetime + (time_t)(31L * 86400L);  /* ahead 31 days */
145
146         /** Now back up until we're on a Sunday */
147         localtime_r(&thetime, &tm);
148         while (tm.tm_wday != 0) {
149                 thetime = thetime - (time_t)86400;      /* go back 24 hours */
150                 localtime_r(&thetime, &tm);
151         }
152
153         /** Outer table (to get the background color) */
154         wprintf("<div class=\"fix_scrollbar_bug\">"
155                 "<TABLE width=100%% border=0 cellpadding=0 cellspacing=0 "
156                 "bgcolor=#204B78><TR><TD>\n");
157
158         wprintf("<TABLE width=100%% border=0 cellpadding=0 cellspacing=0><tr>\n");
159
160         wprintf("<TD ALIGN=CENTER>");
161
162         localtime_r(&previous_month, &tm);
163         wprintf("<a href=\"readfwd?calview=month&year=%d&month=%d&day=1\">",
164                 (int)(tm.tm_year)+1900, tm.tm_mon + 1);
165         wprintf("<IMG ALIGN=MIDDLE src=\"static/prevdate_32x.gif\" BORDER=0></A>\n");
166
167         wprintf("&nbsp;&nbsp;"
168                 "<FONT SIZE=+1 COLOR=\"#FFFFFF\">"
169                 "%s %d"
170                 "</FONT>"
171                 "&nbsp;&nbsp;", months[month-1], year);
172
173         localtime_r(&next_month, &tm);
174         wprintf("<a href=\"readfwd?calview=month&year=%d&month=%d&day=1\">",
175                 (int)(tm.tm_year)+1900, tm.tm_mon + 1);
176         wprintf("<IMG ALIGN=MIDDLE src=\"static/nextdate_32x.gif\" BORDER=0></A>\n");
177
178         wprintf("</TD></TR></TABLE>\n");
179
180         /** Inner table (the real one) */
181         wprintf("<TABLE width=100%% border=0 cellpadding=1 cellspacing=1 "
182                 "bgcolor=#204B78><TR>");
183         for (i=0; i<7; ++i) {
184                 wprintf("<TD ALIGN=CENTER WIDTH=14%%>"
185                         "<FONT COLOR=\"#FFFFFF\">%s</FONT></TH>", wdays[i]);
186         }
187         wprintf("</TR>\n");
188
189         /** Now do 35 days */
190         for (i = 0; i < 35; ++i) {
191                 localtime_r(&thetime, &tm);
192
193                 /* Before displaying Sunday, start a new row */
194                 if ((i % 7) == 0) {
195                         wprintf("<TR>");
196                 }
197
198                 wprintf("<TD BGCOLOR=\"#%s\" WIDTH=14%% HEIGHT=60 align=left VALIGN=TOP><B>",
199                         ((tm.tm_mon != month-1) ? "DDDDDD" :
200                         ((tm.tm_wday==0 || tm.tm_wday==6) ? "EEEECC" :
201                         "FFFFFF"))
202                 );
203                 if ((i==0) || (tm.tm_mday == 1)) {
204                         wprintf("%s ", months[tm.tm_mon]);
205                 }
206                 wprintf("<a href=\"readfwd?calview=day&year=%d&month=%d&day=%d\">"
207                         "%d</A></B><br />",
208                         tm.tm_year + 1900,
209                         tm.tm_mon + 1,
210                         tm.tm_mday,
211                         tm.tm_mday);
212
213                 /** put the data here, stupid */
214                 calendar_month_view_display_events(thetime);
215
216                 wprintf("</TD>");
217
218                 /** After displaying Saturday, end the row */
219                 if ((i % 7) == 6) {
220                         wprintf("</TR>\n");
221                 }
222
223                 thetime += (time_t)86400;               /** ahead 24 hours */
224         }
225
226         wprintf("</TABLE>"                      /** end of inner table */
227                 "</TD></TR></TABLE>"            /** end of outer table */
228                 "</div>\n");
229 }
230
231 /** 
232  * \brief view one week
233  * this should view just one week, but it's not here yet.
234  * \todo ny implemented
235  * \param year the year
236  * \param month the month
237  * \param day the day which we want to see the week around
238  */
239 void calendar_week_view(int year, int month, int day) {
240         wprintf("<CENTER><I>week view FIXME</I></CENTER><br />\n");
241 }
242
243
244 /**
245  * \brief display one day
246  * Display events for a particular hour of a particular day.
247  * (Specify hour < 0 to show "all day" events)
248  * \param year the year
249  * \param month the month
250  * \param day the day
251  * \param hour the hour we want to start displaying?????
252  */
253 void calendar_day_view_display_events(int year, int month,
254                                         int day, int hour) {
255         int i;
256         icalproperty *p;
257         struct icaltimetype t;
258         time_t event_tt;
259         struct tm *event_tm;
260         int all_day_event = 0;
261
262         if (WC->num_cal == 0) {
263                 // \todo FIXME wprintf("<br /><br /><br />\n");
264                 return;
265         }
266
267         for (i=0; i<(WC->num_cal); ++i) {
268                 p = icalcomponent_get_first_property(WC->disp_cal[i].cal,
269                                                 ICAL_DTSTART_PROPERTY);
270                 if (p != NULL) {
271                         t = icalproperty_get_dtstart(p);
272                         event_tt = icaltime_as_timet(t);
273                         if (t.is_date) {
274                                 all_day_event = 1;
275                         }
276                         else {
277                                 all_day_event = 0;
278                         }
279
280                         if (all_day_event) {
281                                 event_tm = gmtime(&event_tt);
282                         }
283                         else {
284                                 event_tm = localtime(&event_tt);
285                         }
286
287                         if ((event_tm->tm_year == (year-1900))
288                            && (event_tm->tm_mon == (month-1))
289                            && (event_tm->tm_mday == day)
290                            && ( ((event_tm->tm_hour == hour)&&(!t.is_date)) || ((hour<0)&&(t.is_date)) )
291                            ) {
292
293
294                                 p = icalcomponent_get_first_property(
295                                                         WC->disp_cal[i].cal,
296                                                         ICAL_SUMMARY_PROPERTY);
297                                 if (p != NULL) {
298
299                                         if (all_day_event) {
300                                                 wprintf("<TABLE border=1 cellpadding=2><TR>"
301                                                         "<TD BGCOLOR=\"#CCCCCC\">"
302                                                 );
303                                         }
304
305                                         wprintf("<FONT SIZE=-1>"
306                                                 "<a href=\"display_edit_event?msgnum=%ld&calview=day&year=%d&month=%d&day=%d\">",
307                                                 WC->disp_cal[i].cal_msgnum,
308                                                 year, month, day
309                                         );
310                                         escputs((char *)
311                                                 icalproperty_get_comment(p));
312                                         wprintf("</A></FONT><br />\n");
313
314                                         if (all_day_event) {
315                                                 wprintf("</TD></TR></TABLE>");
316                                         }
317                                 }
318
319                         }
320
321
322                 }
323         }
324 }
325
326
327 /**
328  * \brief view one day
329  * \param year the year
330  * \param month the month 
331  * \param day the day we want to display
332  */
333 void calendar_day_view(int year, int month, int day) {
334         int hour;
335         struct icaltimetype today, yesterday, tomorrow;
336         char calhourformat[16];
337         int daystart = 8;
338         int dayend = 17;
339         char daystart_str[16], dayend_str[16];
340
341         get_preference("calhourformat", calhourformat, sizeof calhourformat);
342         get_preference("daystart", daystart_str, sizeof daystart_str);
343         if (strlen(daystart_str) > 0) daystart = atoi(daystart_str);
344         get_preference("dayend", dayend_str, sizeof dayend_str);
345         if (strlen(dayend_str) > 0) dayend = atoi(dayend_str);
346         
347
348         /** Figure out the dates for "yesterday" and "tomorrow" links */
349
350         memset(&today, 0, sizeof(struct icaltimetype));
351         today.year = year;
352         today.month = month;
353         today.day = day;
354         today.is_date = 1;
355
356         memcpy(&yesterday, &today, sizeof(struct icaltimetype));
357         --yesterday.day;
358         yesterday = icaltime_normalize(yesterday);
359
360         memcpy(&tomorrow, &today, sizeof(struct icaltimetype));
361         ++tomorrow.day;
362         tomorrow = icaltime_normalize(tomorrow);
363
364
365         /** Outer table (to get the background color) */
366         wprintf("<div class=\"fix_scrollbar_bug\">"
367                 "<TABLE width=100%% border=0 cellpadding=0 cellspacing=0 "
368                 "bgcolor=#204B78><TR><TD>\n");
369
370         /** Inner table (the real one) */
371         wprintf("<TABLE width=100%% border=0 cellpadding=1 cellspacing=1 "
372                 "bgcolor=#204B78><TR>\n");
373
374         /** Innermost table (contains hours etc.) */
375         wprintf("<TD WIDTH=80%%>"
376                 "<TABLE width=100%% border=0 cellpadding=1 cellspacing=1 "
377                 "bgcolor=#204B78>\n");
378
379         /** Display events before 8:00 (hour=-1 is all-day events) */
380         wprintf("<TR>"
381                 "<TD BGCOLOR=\"#CCCCDD\" VALIGN=MIDDLE WIDTH=10%%></TD>"
382                 "<TD BGCOLOR=\"#FFFFFF\" VALIGN=TOP>");
383         for (hour = (-1); hour <= (daystart-1); ++hour) {
384                 calendar_day_view_display_events(year, month, day, hour);
385         }
386         wprintf("</TD></TR>\n");
387
388         /** Now the middle of the day... */     
389         for (hour = daystart; hour <= dayend; ++hour) { /* could do HEIGHT=xx */
390                 wprintf("<TR HEIGHT=30><TD BGCOLOR=\"#CCCCDD\" ALIGN=MIDDLE "
391                         "VALIGN=MIDDLE WIDTH=10%%>");
392                 wprintf("<a href=\"display_edit_event?msgnum=0"
393                         "&year=%d&month=%d&day=%d&hour=%d&minute=0\">",
394                         year, month, day, hour
395                 );
396
397                 if (!strcasecmp(calhourformat, "24")) {
398                         wprintf("%2d:00</A> ", hour);
399                 }
400                 else {
401                         wprintf("%d:00%s</A> ",
402                                 (hour <= 12 ? hour : hour-12),
403                                 (hour < 12 ? "am" : "pm")
404                         );
405                 }
406
407                 wprintf("</TD><TD BGCOLOR=\"#FFFFFF\" VALIGN=TOP>");
408
409                 /* put the data here, stupid */
410                 calendar_day_view_display_events(year, month, day, hour);
411
412                 wprintf("</TD></TR>\n");
413         }
414
415         /** Display events after 5:00... */
416         wprintf("<TR>"
417                 "<TD BGCOLOR=\"#CCCCDD\" VALIGN=MIDDLE WIDTH=10%%></TD>"
418                 "<TD BGCOLOR=\"#FFFFFF\" VALIGN=TOP>");
419         for (hour = (dayend+1); hour <= 23; ++hour) {
420                 calendar_day_view_display_events(year, month, day, hour);
421         }
422         wprintf("</TD></TR>\n");
423
424
425         wprintf("</TABLE>"                      /* end of innermost table */
426                 "</TD>"
427         );
428
429         wprintf("<TD WIDTH=20%% VALIGN=top>");  /* begin stuff-on-the-right */
430
431
432         /** Begin todays-date-with-left-and-right-arrows */
433         wprintf("<TABLE BORDER=0 WIDTH=100%% "
434                 "CELLSPACING=0 CELLPADDING=0 BGCOLOR=\"#FFFFFF\">\n");
435         wprintf("<TR>");
436
437         /** Left arrow */       
438         wprintf("<TD ALIGN=CENTER>");
439         wprintf("<a href=\"readfwd?calview=day&year=%d&month=%d&day=%d\">",
440                 yesterday.year, yesterday.month, yesterday.day);
441         wprintf("<IMG ALIGN=MIDDLE src=\"static/prevdate_32x.gif\" BORDER=0></A>");
442         wprintf("</TD>");
443
444         /** Today's date */
445         wprintf("<TD ALIGN=CENTER>");
446         wprintf("<FONT SIZE=+2>%s</FONT><br />"
447                 "<FONT SIZE=+3>%d</FONT><br />"
448                 "<FONT SIZE=+2>%d</FONT><br />",
449                 months[month-1], day, year);
450         wprintf("</TD>");
451
452         /** Right arrow */
453         wprintf("<TD ALIGN=CENTER>");
454         wprintf("<a href=\"readfwd?calview=day&year=%d&month=%d&day=%d\">",
455                 tomorrow.year, tomorrow.month, tomorrow.day);
456         wprintf("<IMG ALIGN=MIDDLE src=\"static/nextdate_32x.gif\""
457                 " BORDER=0></A>\n");
458         wprintf("</TD>");
459
460         wprintf("</TR></TABLE>\n");
461         /** End todays-date-with-left-and-right-arrows */
462
463         /** \todo In the future we might want to put a month-o-matic here */
464
465         wprintf("</FONT></CENTER>\n");
466
467         wprintf("</TD>");                       /** end stuff-on-the-right */
468
469
470
471         wprintf("</TR></TABLE>"                 /** end of inner table */
472                 "</TD></TR></TABLE></div>"      /** end of outer table */
473         );
474
475
476
477 }
478
479 /**
480  * \brief Display today's events.
481  */
482 void calendar_summary_view(void) {
483         int i;
484         icalproperty *p;
485         struct icaltimetype t;
486         time_t event_tt;
487         struct tm event_tm;
488         struct tm today_tm;
489         time_t now;
490         int all_day_event = 0;
491         char timestring[SIZ];
492
493         if (WC->num_cal == 0) {
494                 return;
495         }
496
497         now = time(NULL);
498         localtime_r(&now, &today_tm);
499
500         for (i=0; i<(WC->num_cal); ++i) {
501                 p = icalcomponent_get_first_property(WC->disp_cal[i].cal,
502                                                 ICAL_DTSTART_PROPERTY);
503                 if (p != NULL) {
504                         t = icalproperty_get_dtstart(p);
505                         event_tt = icaltime_as_timet(t);
506                         if (t.is_date) {
507                                 all_day_event = 1;
508                         }
509                         else {
510                                 all_day_event = 0;
511                         }
512                         fmt_time(timestring, event_tt);
513
514                         if (all_day_event) {
515                                 gmtime_r(&event_tt, &event_tm);
516                         }
517                         else {
518                                 localtime_r(&event_tt, &event_tm);
519                         }
520
521                         if ( (event_tm.tm_year == today_tm.tm_year)
522                            && (event_tm.tm_mon == today_tm.tm_mon)
523                            && (event_tm.tm_mday == today_tm.tm_mday)
524                            ) {
525
526
527                                 p = icalcomponent_get_first_property(
528                                                         WC->disp_cal[i].cal,
529                                                         ICAL_SUMMARY_PROPERTY);
530                                 if (p != NULL) {
531                                         escputs((char *)
532                                                 icalproperty_get_comment(p));
533                                         wprintf(" (%s)<br />\n", timestring);
534                                 }
535                         }
536                 }
537         }
538         free_calendar_buffer();
539 }
540
541
542 /**
543  * \brief clean up ical memory
544  * \todo this could get troubel with future ical versions
545  */
546 void free_calendar_buffer(void) {
547         int i;
548         if (WC->num_cal) for (i=0; i<(WC->num_cal); ++i) {
549                 icalcomponent_free(WC->disp_cal[i].cal);
550         }
551         WC->num_cal = 0;
552         free(WC->disp_cal);
553         WC->disp_cal = NULL;
554 }
555
556
557
558 /**
559  * \brief do the whole calendar page
560  * view any part of the calender. decide which way, etc.
561  */
562 void do_calendar_view(void) {
563         time_t now;
564         struct tm tm;
565         int year, month, day;
566         char calview[SIZ];
567
568         /** In case no date was specified, go with today */
569         now = time(NULL);
570         localtime_r(&now, &tm);
571         year = tm.tm_year + 1900;
572         month = tm.tm_mon + 1;
573         day = tm.tm_mday;
574
575         /** Now see if a date was specified */
576         if (strlen(bstr("year")) > 0) year = atoi(bstr("year"));
577         if (strlen(bstr("month")) > 0) month = atoi(bstr("month"));
578         if (strlen(bstr("day")) > 0) day = atoi(bstr("day"));
579
580         /** How would you like that cooked? */
581         if (strlen(bstr("calview")) > 0) {
582                 strcpy(calview, bstr("calview"));
583         }
584         else {
585                 strcpy(calview, "month");
586         }
587
588         /** Display the selected view */
589         if (!strcasecmp(calview, "day")) {
590                 calendar_day_view(year, month, day);
591         }
592         else if (!strcasecmp(calview, "week")) {
593                 calendar_week_view(year, month, day);
594         }
595         else {
596                 calendar_month_view(year, month, day);
597         }
598
599         /** Free the calendar stuff */
600         free_calendar_buffer();
601
602 }
603
604
605 /**
606  * \brief get task due date
607  * Helper function for do_tasks_view().  
608  * \param vtodo a task to get the due date
609  * \return the date/time due.
610  */
611 time_t get_task_due_date(icalcomponent *vtodo) {
612         icalproperty *p;
613
614         if (vtodo == NULL) {
615                 return(0L);
616         }
617
618         /**
619          * If we're looking at a fully encapsulated VCALENDAR
620          * rather than a VTODO component, recurse into the data
621          * structure until we get a VTODO.
622          */
623         if (icalcomponent_isa(vtodo) == ICAL_VCALENDAR_COMPONENT) {
624                 return get_task_due_date(
625                         icalcomponent_get_first_component(
626                                 vtodo, ICAL_VTODO_COMPONENT
627                         )
628                 );
629         }
630
631         p = icalcomponent_get_first_property(vtodo, ICAL_DUE_PROPERTY);
632         if (p != NULL) {
633                 return(icaltime_as_timet(icalproperty_get_due(p)));
634         }
635         else {
636                 return(0L);
637         }
638 }
639
640
641 /**
642  * \brief Compare the due dates of two tasks (this is for sorting)
643  * \param task1 first task to compare
644  * \param task2 second task to compare
645  */
646 int task_due_cmp(const void *task1, const void *task2) {
647         time_t t1;
648         time_t t2;
649
650         t1 =  get_task_due_date(((struct disp_cal *)task1)->cal);
651         t2 =  get_task_due_date(((struct disp_cal *)task2)->cal);
652
653         if (t1 < t2) return(-1);
654         if (t1 > t2) return(1);
655         return(0);
656 }
657
658
659
660
661 /**
662  * \brief do the whole task view stuff
663  */
664 void do_tasks_view(void) {
665         int i;
666         time_t due;
667         int bg = 0;
668         char buf[SIZ];
669         icalproperty *p;
670
671         wprintf("<div class=\"fix_scrollbar_bug\">"
672                 "<table border=0 cellspacing=0 width=100%% bgcolor=\"#FFFFFF\">\n<tr>\n"
673                 "<TH>");
674         wprintf(_("Name of task"));
675         wprintf("</TH><TH>");
676         wprintf(_("Date due"));
677         wprintf("</TH></TR>\n"
678         );
679
680         /** Sort them if necessary */
681         if (WC->num_cal > 1) {
682                 qsort(WC->disp_cal,
683                         WC->num_cal,
684                         sizeof(struct disp_cal),
685                         task_due_cmp
686                 );
687         }
688
689         if (WC->num_cal) for (i=0; i<(WC->num_cal); ++i) {
690
691                 bg = 1 - bg;
692                 wprintf("<TR BGCOLOR=\"#%s\"><TD>",
693                         (bg ? "DDDDDD" : "FFFFFF")
694                 );
695
696                 p = icalcomponent_get_first_property(WC->disp_cal[i].cal,
697                                                         ICAL_SUMMARY_PROPERTY);
698                 wprintf("<a href=\"display_edit_task?msgnum=%ld&taskrm=",
699                         WC->disp_cal[i].cal_msgnum );
700                 urlescputs(WC->wc_roomname);
701                 wprintf("\">");
702                 wprintf("<IMG ALIGN=MIDDLE "
703                         "src=\"static/taskmanag_16x.gif\" BORDER=0>&nbsp;");
704                 if (p != NULL) {
705                         escputs((char *)icalproperty_get_comment(p));
706                 }
707                 wprintf("</A>\n");
708                 wprintf("</TD>\n");
709
710                 due = get_task_due_date(WC->disp_cal[i].cal);
711                 fmt_date(buf, due, 0);
712                 wprintf("<TD><FONT");
713                 if (due < time(NULL)) {
714                         wprintf(" COLOR=\"#FF0000\"");
715                 }
716                 wprintf(">%s</FONT></TD></TR>\n", buf);
717         }
718
719         wprintf("</table></div>\n");
720
721         /** Free the list */
722         free_calendar_buffer();
723
724 }
725
726 #endif  /* WEBCIT_WITH_CALENDAR_SERVICE */
727
728 /** @} */