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