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