4 * Handles the HTML display of calendar items.
10 /* These define how high the hour rows are in the day view */
12 #define EXTRATIMELINE (TIMELINE / 2)
14 void embeddable_mini_calendar(int year
, int month
)
16 struct tm starting_tm
;
20 time_t previous_month
;
22 time_t colheader_time
;
23 struct tm colheader_tm
;
24 char colheader_label
[32];
29 snprintf(div_id
, sizeof div_id
, "mini_calendar_%d", rand() );
31 /* Determine what day to start. If an impossible value is found, start on Sunday.
33 get_pref_long("weekstart", &weekstart
, 17);
34 if (weekstart
> 6) weekstart
= 0;
37 * Now back up to the 1st of the month...
39 memset(&starting_tm
, 0, sizeof(struct tm
));
41 starting_tm
.tm_year
= year
- 1900;
42 starting_tm
.tm_mon
= month
- 1;
43 starting_tm
.tm_mday
= 1;
44 thetime
= mktime(&starting_tm
);
46 memcpy(&tm
, &starting_tm
, sizeof(struct tm
));
47 while (tm
.tm_mday
!= 1) {
48 thetime
= thetime
- (time_t)86400; /* go back 24 hours */
49 localtime_r(&thetime
, &tm
);
52 /* Determine previous and next months ... for links */
53 previous_month
= thetime
- (time_t)864000L; /* back 10 days */
54 next_month
= thetime
+ (time_t)(31L * 86400L); /* ahead 31 days */
56 /* Now back up until we're on the user's preferred start day */
57 localtime_r(&thetime
, &tm
);
58 while (tm
.tm_wday
!= weekstart
) {
59 thetime
= thetime
- (time_t)86400; /* go back 24 hours */
60 localtime_r(&thetime
, &tm
);
63 wprintf("<div class=\"mini_calendar\" id=\"%s\">\n", div_id
);
65 /* Previous month link */
66 localtime_r(&previous_month
, &tm
);
67 wprintf("<a href=\"javascript:minical_change_month(%d,%d);\">«</a>",
68 (int)(tm
.tm_year
)+1900, tm
.tm_mon
+ 1);
70 wc_strftime(colheader_label
, sizeof colheader_label
, "%B", &starting_tm
);
71 wprintf(" "
72 "<span class=\"mini_calendar_month_label\">"
75 " ", colheader_label
, year
);
78 localtime_r(&next_month
, &tm
);
79 wprintf("<a href=\"javascript:minical_change_month(%d,%d);\">»</a>",
80 (int)(tm
.tm_year
)+1900, tm
.tm_mon
+ 1);
82 wprintf("<table border=0 cellpadding=1 cellspacing=1 class=\"mini_calendar_days\">"
84 colheader_time
= thetime
;
86 colheader_time
= thetime
+ (i
* 86400) ;
87 localtime_r(&colheader_time
, &colheader_tm
);
88 wc_strftime(colheader_label
, sizeof colheader_label
, "%A", &colheader_tm
);
89 wprintf("<th>%c</th>", colheader_label
[0]);
95 /* Now do 35 or 42 days */
96 for (i
= 0; i
< 42; ++i
) {
97 localtime_r(&thetime
, &tm
);
101 /* Before displaying Sunday, start a new row */
106 if (tm
.tm_mon
== month
-1) {
107 snprintf(url
, sizeof url
, "readfwd?calview=day&year=%d&month=%d&day=%d",
108 tm
.tm_year
+1900, tm
.tm_mon
+1, tm
.tm_mday
);
109 wprintf("<td><a href=\"%s\">%d</a></td>", url
, tm
.tm_mday
);
112 wprintf("<td> </td>");
115 /* After displaying one week, end the row */
122 thetime
+= (time_t)86400; /* ahead 24 hours */
125 wprintf("</table>" /* end of inner table */
128 StrBufAppendPrintf(WC
->trailing_javascript
,
129 " function minical_change_month(year, month) { \n"
130 " p = 'year=' + year + '&month=' + month \n"
131 " + '&r=' + CtdlRandomString(); \n"
132 " new Ajax.Updater('%s', 'mini_calendar', \n"
133 " { method: 'get', parameters: p, evalScripts: true } ); \n"
142 * ajax embedder for the above mini calendar
144 void ajax_mini_calendar(void)
146 embeddable_mini_calendar( ibstr("year"), ibstr("month"));
151 * Display one day of a whole month view of a calendar
153 void calendar_month_view_display_events(int year
, int month
, int day
)
160 icalproperty
*p
= NULL
;
161 icalproperty
*q
= NULL
;
162 struct icaltimetype t
;
163 struct icaltimetype end_t
;
164 struct icaltimetype today_start_t
;
165 struct icaltimetype today_end_t
;
166 struct icaltimetype today_t
;
167 struct tm starting_tm
;
169 int all_day_event
= 0;
175 if (GetCount(WCC
->disp_cal_items
) == 0) {
176 wprintf("<br /><br /><br />\n");
181 * Create an imaginary event which spans the 24 hours of today. Any events which
182 * overlap with this one take place at least partially in this day. We have to
183 * convert it from a struct tm in order to make it UTC.
185 memset(&starting_tm
, 0, sizeof(struct tm
));
186 starting_tm
.tm_year
= year
- 1900;
187 starting_tm
.tm_mon
= month
- 1;
188 starting_tm
.tm_mday
= day
;
189 starting_tm
.tm_hour
= 0;
190 starting_tm
.tm_min
= 0;
191 today_start_t
= icaltime_from_timet_with_zone(mktime(&starting_tm
), 0, icaltimezone_get_utc_timezone());
192 today_start_t
.is_utc
= 1;
194 memset(&ending_tm
, 0, sizeof(struct tm
));
195 ending_tm
.tm_year
= year
- 1900;
196 ending_tm
.tm_mon
= month
- 1;
197 ending_tm
.tm_mday
= day
;
198 ending_tm
.tm_hour
= 23;
199 ending_tm
.tm_min
= 59;
200 today_end_t
= icaltime_from_timet_with_zone(mktime(&ending_tm
), 0, icaltimezone_get_utc_timezone());
201 today_end_t
.is_utc
= 1;
204 * Create another one without caring about the timezone for all day events.
206 today_t
= icaltime_null_date();
208 today_t
.month
= month
;
212 * Now loop through our list of events to see which ones occur today.
214 Pos
= GetNewHashPos(WCC
->disp_cal_items
, 0);
215 while (GetNextHashPos(WCC
->disp_cal_items
, Pos
, &hklen
, &HashKey
, &vCal
)) {
216 Cal
= (disp_cal
*)vCal
;
218 q
= icalcomponent_get_first_property(Cal
->cal
, ICAL_DTSTART_PROPERTY
);
220 t
= icalproperty_get_dtstart(q
);
223 memset(&t
, 0, sizeof t
);
225 q
= icalcomponent_get_first_property(Cal
->cal
, ICAL_DTEND_PROPERTY
);
227 end_t
= icalproperty_get_dtend(q
);
230 memset(&end_t
, 0, sizeof end_t
);
232 if (t
.is_date
) all_day_event
= 1;
236 show_event
= ical_ctdl_is_overlap(t
, end_t
, today_t
, icaltime_null_time());
240 show_event
= ical_ctdl_is_overlap(t
, end_t
, today_start_t
, today_end_t
);
244 * If we determined that this event occurs today, then display it.
247 p
= icalcomponent_get_first_property(Cal
->cal
, ICAL_SUMMARY_PROPERTY
);
251 wprintf("<table border=0 cellpadding=2><TR>"
252 "<td bgcolor=\"#CCCCDD\">"
256 wprintf("<font size=\"-1\">"
257 "<a class=\"event%s\" href=\"display_edit_event?"
258 "msgnum=%ld?calview=month?year=%d?month=%d?day=%d\""
260 (Cal
->unread
)?"_unread":"_read",
265 wprintf("<i>%s: %s</i><br />", _("From"), Cal
->from
);
266 wprintf("<i>%s</i> ", _("Summary:"));
267 escputs((char *)icalproperty_get_comment(p
));
270 q
= icalcomponent_get_first_property(
272 ICAL_LOCATION_PROPERTY
);
274 wprintf("<i>%s</i> ", _("Location:"));
275 escputs((char *)icalproperty_get_comment(q
));
280 * Only show start/end times if we're actually looking at the VEVENT
281 * component. Otherwise it shows bogus dates for e.g. timezones
283 if (icalcomponent_isa(Cal
->cal
) == ICAL_VEVENT_COMPONENT
) {
285 q
= icalcomponent_get_first_property(Cal
->cal
, ICAL_DTSTART_PROPERTY
);
289 t
= icalproperty_get_dtstart(q
);
290 q
= icalcomponent_get_first_property(Cal
->cal
, ICAL_DTEND_PROPERTY
);
292 end_t
= icalproperty_get_dtend(q
);
296 * events with starting date/time equal
297 * ending date/time might get only
298 * DTSTART but no DTEND
308 /* end given, have to adjust it */
309 icaltime_adjust(&end_t
, -1, 0, 0, 0);
311 memset(&d_tm
, 0, sizeof d_tm
);
312 d_tm
.tm_year
= t
.year
- 1900;
313 d_tm
.tm_mon
= t
.month
- 1;
314 d_tm
.tm_mday
= t
.day
;
315 wc_strftime(buf
, sizeof buf
, "%x", &d_tm
);
317 if (no_end
|| !icaltime_compare(t
, end_t
)) {
318 wprintf("<i>%s</i> %s<br>",
322 wprintf("<i>%s</i> %s<br>",
323 _("Starting date:"), buf
);
324 d_tm
.tm_year
= end_t
.year
- 1900;
325 d_tm
.tm_mon
= end_t
.month
- 1;
326 d_tm
.tm_mday
= end_t
.day
;
327 wc_strftime(buf
, sizeof buf
, "%x", &d_tm
);
328 wprintf("<i>%s</i> %s<br>",
329 _("Ending date:"), buf
);
333 tt
= icaltime_as_timet(t
);
334 webcit_fmt_date(buf
, tt
, DATEFMT_BRIEF
);
335 if (no_end
|| !icaltime_compare(t
, end_t
)) {
336 wprintf("<i>%s</i> %s<br>",
337 _("Date/time:"), buf
);
340 wprintf("<i>%s</i> %s<br>",
341 _("Starting date/time:"), buf
);
342 tt
= icaltime_as_timet(end_t
);
343 webcit_fmt_date(buf
, tt
, DATEFMT_BRIEF
);
344 wprintf("<i>%s</i> %s<br>", _("Ending date/time:"), buf
);
352 q
= icalcomponent_get_first_property(Cal
->cal
, ICAL_DESCRIPTION_PROPERTY
);
354 wprintf("<i>%s</i> ", _("Notes:"));
355 escputs((char *)icalproperty_get_comment(q
));
361 icalproperty_get_comment(p
));
362 wprintf("</a></font><br />\n");
365 wprintf("</td></tr></table>");
379 * Display one day of a whole month view of a calendar
381 void calendar_month_view_brief_events(time_t thetime
, const char *daycolor
) {
395 struct icaltimetype t
;
397 int month
, day
, year
;
398 int all_day_event
= 0;
402 time_format
= get_time_format_cached ();
404 if (time_format
== WC_TIMEFORMAT_24
) timeformat
="%k:%M";
405 else timeformat
="%I:%M %p";
407 localtime_r(&thetime
, &today_tm
);
408 month
= today_tm
.tm_mon
+ 1;
409 day
= today_tm
.tm_mday
;
410 year
= today_tm
.tm_year
+ 1900;
412 Pos
= GetNewHashPos(WCC
->disp_cal_items
, 0);
413 while (GetNextHashPos(WCC
->disp_cal_items
, Pos
, &hklen
, &HashKey
, &vCal
)) {
414 Cal
= (disp_cal
*)vCal
;
415 p
= icalcomponent_get_first_property(Cal
->cal
, ICAL_DTSTART_PROPERTY
);
417 t
= icalproperty_get_dtstart(p
);
418 event_tt
= icaltime_as_timet(t
);
420 if (t
.is_date
) all_day_event
= 1;
421 else all_day_event
= 0;
424 gmtime_r(&event_tts
, &event_tms
);
427 localtime_r(&event_tts
, &event_tms
);
429 /* \todo epoch &! daymask */
430 if ((event_tms
.tm_year
== today_tm
.tm_year
)
431 && (event_tms
.tm_mon
== today_tm
.tm_mon
)
432 && (event_tms
.tm_mday
== today_tm
.tm_mday
)) {
438 p
= icalcomponent_get_first_property(
440 ICAL_SUMMARY_PROPERTY
);
441 e
= icalcomponent_get_first_property(
443 ICAL_DTEND_PROPERTY
);
444 if ((p
!= NULL
) && (e
!= NULL
)) {
447 t
= icalproperty_get_dtend(e
);
448 event_tte
= icaltime_as_timet(t
);
449 localtime_r(&event_tte
, &event_tme
);
450 difftime
=(event_tte
-event_tts
)/60;
451 hours
=(int)(difftime
/ 60);
452 minutes
=difftime
% 60;
453 wprintf("<tr><td bgcolor='%s'>%i:%2i</td><td bgcolor='%s'>"
455 "<a class=\"event%s\" href=\"display_edit_event?msgnum=%ld?calview=calbrief?year=%s?month=%s?day=%s\">",
458 (Cal
->unread
)?"_unread":"_read",
467 icalproperty_get_comment(p
));
468 /* \todo: allso ammitime format */
469 wc_strftime(&sbuf
[0], sizeof(sbuf
), timeformat
, &event_tms
);
470 wc_strftime(&ebuf
[0], sizeof(sbuf
), timeformat
, &event_tme
);
472 wprintf("</a></font></td>"
473 "<td bgcolor='%s'>%s</td><td bgcolor='%s'>%s</td></tr>",
490 * view one month. pretty view
492 void calendar_month_view(int year
, int month
, int day
) {
493 struct tm starting_tm
;
497 time_t previous_month
;
499 time_t colheader_time
;
500 struct tm colheader_tm
;
501 char colheader_label
[32];
505 * Determine what day to start. If an impossible value is found, start on Sunday.
507 get_pref_long("weekstart", &weekstart
, 17);
508 if (weekstart
> 6) weekstart
= 0;
511 * Now back up to the 1st of the month...
513 memset(&starting_tm
, 0, sizeof(struct tm
));
515 starting_tm
.tm_year
= year
- 1900;
516 starting_tm
.tm_mon
= month
- 1;
517 starting_tm
.tm_mday
= day
;
518 thetime
= mktime(&starting_tm
);
520 memcpy(&tm
, &starting_tm
, sizeof(struct tm
));
521 while (tm
.tm_mday
!= 1) {
522 thetime
= thetime
- (time_t)86400; /* go back 24 hours */
523 localtime_r(&thetime
, &tm
);
526 /* Determine previous and next months ... for links */
527 previous_month
= thetime
- (time_t)864000L; /* back 10 days */
528 next_month
= thetime
+ (time_t)(31L * 86400L); /* ahead 31 days */
530 /* Now back up until we're on the user's preferred start day */
531 localtime_r(&thetime
, &tm
);
532 while (tm
.tm_wday
!= weekstart
) {
533 thetime
= thetime
- (time_t)86400; /* go back 24 hours */
534 localtime_r(&thetime
, &tm
);
537 /* Outer table (to get the background color) */
538 wprintf("<div class=\"fix_scrollbar_bug\">"
539 "<table class=\"calendar\"> \n <tr><td>");
541 wprintf("<table width=100%% border=0 cellpadding=0 cellspacing=0><tr>\n");
543 wprintf("<td align=center>");
545 localtime_r(&previous_month
, &tm
);
546 wprintf("<a href=\"readfwd?calview=month?year=%d?month=%d?day=1\">",
547 (int)(tm
.tm_year
)+1900, tm
.tm_mon
+ 1);
548 wprintf("<img align=middle src=\"static/prevdate_32x.gif\" border=0></A>\n");
550 wc_strftime(colheader_label
, sizeof colheader_label
, "%B", &starting_tm
);
551 wprintf(" "
552 "<font size=+1 color=\"#FFFFFF\">"
555 " ", colheader_label
, year
);
557 localtime_r(&next_month
, &tm
);
558 wprintf("<a href=\"readfwd?calview=month?year=%d?month=%d?day=1\">",
559 (int)(tm
.tm_year
)+1900, tm
.tm_mon
+ 1);
560 wprintf("<img align=middle src=\"static/nextdate_32x.gif\" border=0></A>\n");
562 wprintf("</td></tr></table>\n");
564 /* Inner table (the real one) */
565 wprintf("<table width=100%% border=0 cellpadding=1 cellspacing=1 "
566 "bgcolor=#204B78 id=\"inner_month\"><tr>");
567 colheader_time
= thetime
;
568 for (i
=0; i
<7; ++i
) {
569 colheader_time
= thetime
+ (i
* 86400) ;
570 localtime_r(&colheader_time
, &colheader_tm
);
571 wc_strftime(colheader_label
, sizeof colheader_label
, "%A", &colheader_tm
);
572 wprintf("<th align=center width=14%%>"
573 "<font color=\"#FFFFFF\">%s</font></th>", colheader_label
);
579 /* Now do 35 or 42 days */
580 localtime_r(&thetime
, &tm
);
581 for (i
= 0; i
<42; ++i
) {
583 /* Before displaying the first day of the week, start a new row */
588 wprintf("<td class=\"cal%s\"><div class=\"day\">",
589 ((tm
.tm_mon
!= month
-1) ? "out" :
590 ((tm
.tm_wday
==0 || tm
.tm_wday
==6) ? "weekend" :
593 if ((i
==0) || (tm
.tm_mday
== 1)) {
594 wc_strftime(colheader_label
, sizeof colheader_label
, "%B", &tm
);
595 wprintf("%s ", colheader_label
);
597 wprintf("<a href=\"readfwd?calview=day?year=%d?month=%d?day=%d\">"
604 /* put the data here, stupid */
605 calendar_month_view_display_events(
613 /* After displaying the last day of the week, end the row */
618 thetime
+= (time_t)86400; /* ahead 24 hours */
619 localtime_r(&thetime
, &tm
);
621 if ( ((i
% 7) == 6) && (tm
.tm_mon
!= month
-1) && (tm
.tm_mday
< 15) ) {
622 i
= 100; /* break out of the loop */
626 wprintf("</table>" /* end of inner table */
627 "</td></tr></table>" /* end of outer table */
631 * Initialize the bubble tooltips.
633 * Yes, this is as stupid as it looks. Instead of just making the call
634 * to btt_enableTooltips() straight away, we have to create a timer event
635 * and let it initialize as an event after 1 millisecond. This is to
636 * work around a bug in Internet Explorer that causes it to crash if we
637 * manipulate the innerHTML of various DOM nodes while the page is still
638 * being rendered. See http://www.shaftek.org/blog/archives/000212.html
639 * for more information.
641 StrBufAppendPrintf(WC
->trailing_javascript
,
642 " setTimeout(\"btt_enableTooltips('inner_month')\", 1); \n"
647 * view one month. brief view
649 void calendar_brief_month_view(int year
, int month
, int day
) {
650 struct tm starting_tm
;
654 time_t previous_month
;
656 char month_label
[32];
658 /* Determine what day to start.
659 * First, back up to the 1st of the month...
661 memset(&starting_tm
, 0, sizeof(struct tm
));
662 starting_tm
.tm_year
= year
- 1900;
663 starting_tm
.tm_mon
= month
- 1;
664 starting_tm
.tm_mday
= day
;
665 thetime
= mktime(&starting_tm
);
667 memcpy(&tm
, &starting_tm
, sizeof(struct tm
));
668 while (tm
.tm_mday
!= 1) {
669 thetime
= thetime
- (time_t)86400; /* go back 24 hours */
670 localtime_r(&thetime
, &tm
);
673 /* Determine previous and next months ... for links */
674 previous_month
= thetime
- (time_t)864000L; /* back 10 days */
675 next_month
= thetime
+ (time_t)(31L * 86400L); /* ahead 31 days */
677 /* Now back up until we're on a Sunday */
678 localtime_r(&thetime
, &tm
);
679 while (tm
.tm_wday
!= 0) {
680 thetime
= thetime
- (time_t)86400; /* go back 24 hours */
681 localtime_r(&thetime
, &tm
);
684 /* Outer table (to get the background color) */
685 wprintf("<div class=\"fix_scrollbar_bug\">"
686 "<table width=100%% border=0 cellpadding=0 cellspacing=0 "
687 "bgcolor=#204B78><TR><TD>\n");
689 wprintf("<table width=100%% border=0 cellpadding=0 cellspacing=0><tr>\n");
691 wprintf("<td align=center>");
693 localtime_r(&previous_month
, &tm
);
694 wprintf("<a href=\"readfwd?calview=month?year=%d?month=%d?day=1\">",
695 (int)(tm
.tm_year
)+1900, tm
.tm_mon
+ 1);
696 wprintf("<img align=middle src=\"static/prevdate_32x.gif\" border=0></A>\n");
698 wc_strftime(month_label
, sizeof month_label
, "%B", &tm
);
699 wprintf(" "
700 "<font size=+1 color=\"#FFFFFF\">"
703 " ", month_label
, year
);
705 localtime_r(&next_month
, &tm
);
706 wprintf("<a href=\"readfwd?calview=month?year=%d?month=%d?day=1\">",
707 (int)(tm
.tm_year
)+1900, tm
.tm_mon
+ 1);
708 wprintf("<img align=middle src=\"static/nextdate_32x.gif\" border=0></A>\n");
710 wprintf("</td></tr></table>\n");
712 /* Inner table (the real one) */
713 wprintf("<table width=100%% border=0 cellpadding=1 cellspacing=1 "
714 "bgcolor=#EEEECC><TR>");
716 wprintf("<tr><td colspan=\"100%%\">\n");
719 for (i
= 0; i
< 35; ++i
) {
720 char weeknumber
[255];
721 char weekday_name
[32];
723 localtime_r(&thetime
, &tm
);
726 /* Before displaying Sunday, start a new CELL */
728 wc_strftime(&weeknumber
[0], sizeof(weeknumber
), "%U", &tm
);
729 wprintf("<table border='0' bgcolor=\"#EEEECC\" width='100%%'> <tr><th colspan='4'>%s %s</th></tr>"
730 " <tr><td>%s</td><td width=70%%>%s</td><td>%s</td><td>%s</td></tr>\n",
740 daycolor
=((tm
.tm_mon
!= month
-1) ? "DDDDDD" :
741 ((tm
.tm_wday
==0 || tm
.tm_wday
==6) ? "EEEECC" :
745 wc_strftime(weekday_name
, sizeof weekday_name
, "%A", &tm
);
746 wprintf("<tr><td bgcolor='%s' colspan='1' align='left'> %s,%i."
747 "</td><td bgcolor='%s' colspan='3'><hr></td></tr>\n",
749 weekday_name
,tm
.tm_mday
,
752 /* put the data of one day here, stupid */
753 calendar_month_view_brief_events(thetime
, daycolor
);
756 /* After displaying Saturday, end the row */
758 wprintf("</td></tr></table>\n");
761 thetime
+= (time_t)86400; /* ahead 24 hours */
764 wprintf("</table>" /* end of inner table */
765 "</td></tr></table>" /* end of outer table */
770 * Calendar week view -- not implemented yet, this is a stub function
772 void calendar_week_view(int year
, int month
, int day
) {
773 wprintf("<center><i>week view FIXME</i></center><br />\n");
779 * Display events for a particular hour of a particular day.
780 * (Specify hour < 0 to show "all day" events)
782 * dstart and dend indicate which hours our "daytime" begins and end
784 void calendar_day_view_display_events(time_t thetime
,
796 icalproperty
*p
= NULL
;
797 icalproperty
*q
= NULL
;
803 int all_day_event
= 0;
804 int ongoing_event
= 0;
807 struct icaltimetype t
;
808 struct icaltimetype end_t
;
809 struct icaltimetype today_start_t
;
810 struct icaltimetype today_end_t
;
811 struct icaltimetype today_t
;
812 struct tm starting_tm
;
823 if (GetCount(WCC
->disp_cal_items
) == 0) {
824 /* nothing to display */
828 /* Create an imaginary event which spans the current day. Any events which
829 * overlap with this one take place at least partially in this day.
831 memset(&starting_tm
, 0, sizeof(struct tm
));
832 starting_tm
.tm_year
= year
- 1900;
833 starting_tm
.tm_mon
= month
- 1;
834 starting_tm
.tm_mday
= day
;
835 starting_tm
.tm_hour
= 0;
836 starting_tm
.tm_min
= 0;
837 today_start_t
= icaltime_from_timet_with_zone(mktime(&starting_tm
), 0, icaltimezone_get_utc_timezone());
838 today_start_t
.is_utc
= 1;
840 memset(&ending_tm
, 0, sizeof(struct tm
));
841 ending_tm
.tm_year
= year
- 1900;
842 ending_tm
.tm_mon
= month
- 1;
843 ending_tm
.tm_mday
= day
;
844 ending_tm
.tm_hour
= 23;
845 ending_tm
.tm_min
= 59;
846 today_end_t
= icaltime_from_timet_with_zone(mktime(&ending_tm
), 0, icaltimezone_get_utc_timezone());
847 today_end_t
.is_utc
= 1;
850 * Create another one without caring about the timezone for all day events.
852 today_t
= icaltime_null_date();
854 today_t
.month
= month
;
857 /* Now loop through our list of events to see which ones occur today.
859 Pos
= GetNewHashPos(WCC
->disp_cal_items
, 0);
860 while (GetNextHashPos(WCC
->disp_cal_items
, Pos
, &hklen
, &HashKey
, &vCal
)) {
861 Cal
= (disp_cal
*)vCal
;
866 q
= icalcomponent_get_first_property(Cal
->cal
, ICAL_DTSTART_PROPERTY
);
868 t
= icalproperty_get_dtstart(q
);
869 event_tt
= icaltime_as_timet(t
);
870 localtime_r(&event_tt
, &event_te
);
873 memset(&t
, 0, sizeof t
);
876 if (t
.is_date
) all_day_event
= 1;
878 q
= icalcomponent_get_first_property(Cal
->cal
, ICAL_DTEND_PROPERTY
);
880 end_t
= icalproperty_get_dtend(q
);
883 /* no end given means end = start */
884 memcpy(&end_t
, &t
, sizeof(struct icaltimetype
));
889 show_event
= ical_ctdl_is_overlap(t
, end_t
, today_t
, icaltime_null_time());
890 if (icaltime_compare(t
, end_t
)) {
892 * the end date is non-inclusive so adjust it by one
893 * day because our test is inclusive, note that a day is
894 * not to much because we are talking about all day
897 icaltime_adjust(&end_t
, -1, 0, 0, 0);
902 show_event
= ical_ctdl_is_overlap(t
, end_t
, today_start_t
, today_end_t
);
905 event_tte
= icaltime_as_timet(end_t
);
906 localtime_r(&event_tte
, &event_tm
);
908 /* If we determined that this event occurs today, then display it.
910 p
= icalcomponent_get_first_property(Cal
->cal
,ICAL_SUMMARY_PROPERTY
);
912 if ((show_event
) && (p
!= NULL
)) {
914 if ((event_te
.tm_mday
!= day
) || (event_tm
.tm_mday
!= day
)) ongoing_event
= 1;
916 if (all_day_event
&& notime_events
)
918 wprintf("<li class=\"event_framed%s\"> "
919 "<a href=\"display_edit_event?"
920 "msgnum=%ld?calview=day?year=%d?month=%d?day=%d\" "
921 " class=\"event_title\" "
923 (Cal
->unread
)?"_unread":"_read",
924 Cal
->cal_msgnum
, year
, month
, day
);
925 wprintf("<i>%s</i><br />", _("All day event"));
926 wprintf("<i>%s: %s</i><br />", _("From"), Cal
->from
);
927 wprintf("<i>%s</i> ", _("Summary:"));
928 escputs((char *) icalproperty_get_comment(p
));
930 q
= icalcomponent_get_first_property(Cal
->cal
,ICAL_LOCATION_PROPERTY
);
932 wprintf("<i>%s</i> ", _("Location:"));
933 escputs((char *)icalproperty_get_comment(q
));
936 if (!icaltime_compare(t
, end_t
)) { /* one day only */
937 webcit_fmt_date(buf
, event_tt
, DATEFMT_LOCALEDATE
);
938 wprintf("<i>%s</i> %s<br>", _("Date:"), buf
);
941 webcit_fmt_date(buf
, event_tt
, DATEFMT_LOCALEDATE
);
942 wprintf("<i>%s</i> %s<br>", _("Starting date:"), buf
);
943 webcit_fmt_date(buf
, event_tte
, DATEFMT_LOCALEDATE
);
944 wprintf("<i>%s</i> %s<br>", _("Ending date:"), buf
);
946 q
= icalcomponent_get_first_property(Cal
->cal
,ICAL_DESCRIPTION_PROPERTY
);
948 wprintf("<i>%s</i> ", _("Notes:"));
949 escputs((char *)icalproperty_get_comment(q
));
953 escputs((char *) icalproperty_get_comment(p
));
954 wprintf("</a> <span>(");
955 wprintf(_("All day event"));
956 wprintf(")</span></li>\n");
958 else if (ongoing_event
&& notime_events
)
960 wprintf("<li class=\"event_framed%s\"> "
961 "<a href=\"display_edit_event?"
962 "msgnum=%ld&calview=day?year=%d?month=%d?day=%d\" "
963 " class=\"event_title\" "
965 (Cal
->unread
)?"_unread":"_read",
966 Cal
->cal_msgnum
, year
, month
, day
);
967 wprintf("<i>%s</i><br />", _("Ongoing event"));
968 wprintf("<i>%s: %s</i><br />", _("From"), Cal
->from
);
969 wprintf("<i>%s</i> ", _("Summary:"));
970 escputs((char *) icalproperty_get_comment(p
));
972 q
= icalcomponent_get_first_property(Cal
->cal
,ICAL_LOCATION_PROPERTY
);
974 wprintf("<i>%s</i> ", _("Location:"));
975 escputs((char *)icalproperty_get_comment(q
));
978 webcit_fmt_date(buf
, event_tt
, DATEFMT_BRIEF
);
979 wprintf("<i>%s</i> %s<br>", _("Starting date/time:"), buf
);
980 webcit_fmt_date(buf
, event_tte
, DATEFMT_BRIEF
);
981 wprintf("<i>%s</i> %s<br>", _("Ending date/time:"), buf
);
982 q
= icalcomponent_get_first_property(Cal
->cal
,ICAL_DESCRIPTION_PROPERTY
);
984 wprintf("<i>%s</i> ", _("Notes:"));
985 escputs((char *)icalproperty_get_comment(q
));
989 escputs((char *) icalproperty_get_comment(p
));
990 wprintf("</a> <span>(");
991 wprintf(_("Ongoing event"));
992 wprintf(")</span></li>\n");
994 else if (!all_day_event
&& !notime_events
)
998 if (event_te
.tm_mday
!= day
) event_te
.tm_hour
= 0;
999 if (event_tm
.tm_mday
!= day
) event_tm
.tm_hour
= 24;
1001 /* Calculate the location of the top of the box */
1002 if (event_te
.tm_hour
< dstart
) {
1003 startmin
= diffmin
= event_te
.tm_min
/ 6;
1004 top
= (event_te
.tm_hour
* EXTRATIMELINE
) + startmin
;
1006 else if ((event_te
.tm_hour
>= dstart
) && (event_te
.tm_hour
<= dend
)) {
1007 startmin
= diffmin
= (event_te
.tm_min
/ 2);
1008 top
= (dstart
* EXTRATIMELINE
) + ((event_te
.tm_hour
- dstart
) * TIMELINE
) + startmin
;
1010 else if (event_te
.tm_hour
>dend
) {
1011 startmin
= diffmin
= event_te
.tm_min
/ 6;
1012 top
= (dstart
* EXTRATIMELINE
) + ((dend
- dstart
- 1) * TIMELINE
) + ((event_tm
.tm_hour
- dend
+ 1) * EXTRATIMELINE
) + startmin
;
1015 /* should never get here */
1018 /* Calculate the location of the bottom of the box */
1019 if (event_tm
.tm_hour
< dstart
) {
1020 endmin
= diffmin
= event_tm
.tm_min
/ 6;
1021 bottom
= (event_tm
.tm_hour
* EXTRATIMELINE
) + endmin
;
1023 else if ((event_tm
.tm_hour
>= dstart
) && (event_tm
.tm_hour
<= dend
)) {
1024 endmin
= diffmin
= (event_tm
.tm_min
/ 2);
1025 bottom
= (dstart
* EXTRATIMELINE
) + ((event_tm
.tm_hour
- dstart
) * TIMELINE
) + endmin
;
1027 else if (event_tm
.tm_hour
>dend
) {
1028 endmin
= diffmin
= event_tm
.tm_min
/ 6;
1029 bottom
= (dstart
* EXTRATIMELINE
) + ((dend
- dstart
+ 1) * TIMELINE
) + ((event_tm
.tm_hour
- dend
- 1) * EXTRATIMELINE
) + endmin
;
1032 /* should never get here */
1035 wprintf("<dd class=\"event_framed%s\" "
1036 "style=\"position: absolute; "
1037 "top:%dpx; left:%dpx; "
1038 "height:%dpx; \" >",
1039 (Cal
->unread
)?"_unread":"_read",
1040 top
, (gap
* 40), (bottom
-top
)
1042 wprintf("<a href=\"display_edit_event?"
1043 "msgnum=%ld?calview=day?year=%d?month=%d?day=%d?hour=%d\" "
1044 "class=\"event_title\" "
1046 Cal
->cal_msgnum
, year
, month
, day
, t
.hour
);
1047 wprintf("<i>%s: %s</i><br />", _("From"), Cal
->from
);
1048 wprintf("<i>%s</i> ", _("Summary:"));
1049 escputs((char *) icalproperty_get_comment(p
));
1051 q
= icalcomponent_get_first_property(Cal
->cal
,ICAL_LOCATION_PROPERTY
);
1053 wprintf("<i>%s</i> ", _("Location:"));
1054 escputs((char *)icalproperty_get_comment(q
));
1057 if (!icaltime_compare(t
, end_t
)) { /* one day only */
1058 webcit_fmt_date(buf
, event_tt
, DATEFMT_BRIEF
);
1059 wprintf("<i>%s</i> %s<br>", _("Date/time:"), buf
);
1062 webcit_fmt_date(buf
, event_tt
, DATEFMT_BRIEF
);
1063 wprintf("<i>%s</i> %s<br>", _("Starting date/time:"), buf
);
1064 webcit_fmt_date(buf
, event_tte
, DATEFMT_BRIEF
);
1065 wprintf("<i>%s</i> %s<br>", _("Ending date/time:"), buf
);
1067 q
= icalcomponent_get_first_property(Cal
->cal
,ICAL_DESCRIPTION_PROPERTY
);
1069 wprintf("<i>%s</i> ", _("Notes:"));
1070 escputs((char *)icalproperty_get_comment(q
));
1075 escputs((char *) icalproperty_get_comment(p
));
1076 wprintf("</a></dd>\n");
1080 DeleteHashPos(&Pos
);
1086 void calendar_day_view(int year
, int month
, int day
) {
1088 struct icaltimetype today
, yesterday
, tomorrow
;
1095 int timeline
= TIMELINE
;
1096 int extratimeline
= EXTRATIMELINE
;
1101 time_format
= get_time_format_cached ();
1102 get_pref_long("daystart", &daystart
, 8);
1103 get_pref_long("dayend", &dayend
, 17);
1105 /* when loading daystart/dayend, replace missing, corrupt, or impossible values with defaults */
1106 if ((daystart
< 0) || (dayend
< 2) || (daystart
>= 23) || (dayend
> 23) || (dayend
<= daystart
)) {
1112 memset(&d_tm
, 0, sizeof d_tm
);
1113 d_tm
.tm_year
= year
- 1900;
1114 d_tm
.tm_mon
= month
- 1;
1116 today_t
= mktime(&d_tm
);
1118 /* Figure out the dates for "yesterday" and "tomorrow" links */
1120 memset(&today
, 0, sizeof(struct icaltimetype
));
1122 today
.month
= month
;
1126 memcpy(&yesterday
, &today
, sizeof(struct icaltimetype
));
1128 yesterday
= icaltime_normalize(yesterday
);
1130 memcpy(&tomorrow
, &today
, sizeof(struct icaltimetype
));
1132 tomorrow
= icaltime_normalize(tomorrow
);
1134 wprintf("<div class=\"fix_scrollbar_bug\">");
1136 /* Inner table (the real one) */
1137 wprintf("<table class=\"calendar\" id=\"inner_day\"><tr> \n");
1139 /* Innermost cell (contains hours etc.) */
1140 wprintf("<td class=\"events_of_the_day\" >");
1141 wprintf("<dl class=\"events\" >");
1143 /* Now the middle of the day... */
1145 extrahourlabel
= extratimeline
- 2;
1146 hourlabel
= extrahourlabel
* 150 / 100;
1147 if (hourlabel
> (timeline
- 2)) hourlabel
= timeline
- 2;
1149 for (hour
= 0; hour
< daystart
; ++hour
) { /* could do HEIGHT=xx */
1150 wprintf("<dt class=\"extrahour\" "
1152 "position: absolute; "
1153 "top: %dpx; left: 0px; "
1157 "<a href=\"display_edit_event?msgnum=0"
1158 "?calview=day?year=%d?month=%d?day=%d?hour=%d?minute=0\">",
1159 (hour
* extratimeline
),
1162 year
, month
, day
, hour
1165 if (time_format
== WC_TIMEFORMAT_24
) {
1166 wprintf("%2d:00</a> ", hour
);
1169 wprintf("%d:00%s</a> ",
1170 ((hour
== 0) ? 12 : (hour
<= 12 ? hour
: hour
-12)),
1171 (hour
< 12 ? "am" : "pm")
1178 gap
= daystart
* extratimeline
;
1180 for (hour
= daystart
; hour
<= dayend
; ++hour
) { /* could do HEIGHT=xx */
1181 wprintf("<dt class=\"hour\" "
1183 "position: absolute; "
1184 "top: %ldpx; left: 0px; "
1188 "<a href=\"display_edit_event?msgnum=0?calview=day"
1189 "?year=%d?month=%d?day=%d?hour=%d?minute=0\">",
1190 gap
+ ((hour
- daystart
) * timeline
),
1193 year
, month
, day
, hour
1196 if (time_format
== WC_TIMEFORMAT_24
) {
1197 wprintf("%2d:00</a> ", hour
);
1200 wprintf("%d:00%s</a> ",
1201 (hour
<= 12 ? hour
: hour
-12),
1202 (hour
< 12 ? "am" : "pm")
1209 gap
= gap
+ ((dayend
- daystart
+ 1) * timeline
);
1211 for (hour
= (dayend
+ 1); hour
< 24; ++hour
) { /* could do HEIGHT=xx */
1212 wprintf("<dt class=\"extrahour\" "
1214 "position: absolute; "
1215 "top: %ldpx; left: 0px; "
1219 "<a href=\"display_edit_event?msgnum=0?calview=day"
1220 "?year=%d?month=%d?day=%d?hour=%d?minute=0\">",
1221 gap
+ ((hour
- dayend
- 1) * extratimeline
),
1224 year
, month
, day
, hour
1227 if (time_format
== WC_TIMEFORMAT_24
) {
1228 wprintf("%2d:00</a> ", hour
);
1231 wprintf("%d:00%s</a> ",
1232 (hour
<= 12 ? hour
: hour
-12),
1233 (hour
< 12 ? "am" : "pm")
1240 /* Display events with start and end times on this day */
1241 calendar_day_view_display_events(today_t
, year
, month
, day
, 0, daystart
, dayend
);
1244 wprintf("</td>"); /* end of innermost table */
1246 /* Display extra events (start/end times not present or not today) in the middle column */
1247 wprintf("<td class=\"extra_events\">");
1251 /* Display all-day events */
1252 calendar_day_view_display_events(today_t
, year
, month
, day
, 1, daystart
, dayend
);
1256 wprintf("</td>"); /* end extra on the middle */
1258 wprintf("<td width=20%% align=center valign=top>"); /* begin stuff-on-the-right */
1260 /* Begin todays-date-with-left-and-right-arrows */
1261 wprintf("<table border=0 width=100%% "
1262 "cellspacing=0 cellpadding=0 bgcolor=\"#FFFFFF\">\n");
1266 wprintf("<td align=center>");
1267 wprintf("<a href=\"readfwd?calview=day?year=%d?month=%d?day=%d\">",
1268 yesterday
.year
, yesterday
.month
, yesterday
.day
);
1269 wprintf("<img align=middle src=\"static/prevdate_32x.gif\" border=0></A>");
1272 wc_strftime(d_str
, sizeof d_str
,
1274 "<font size=+2>%B</font><br />"
1275 "<font size=+3>%d</font><br />"
1276 "<font size=+2>%Y</font><br />"
1280 wprintf("%s", d_str
);
1283 wprintf("<td align=center>");
1284 wprintf("<a href=\"readfwd?calview=day?year=%d?month=%d?day=%d\">",
1285 tomorrow
.year
, tomorrow
.month
, tomorrow
.day
);
1286 wprintf("<img align=middle src=\"static/nextdate_32x.gif\""
1287 " border=0></a>\n");
1290 wprintf("</tr></table>\n");
1291 /* End todays-date-with-left-and-right-arrows */
1293 /* Embed a mini month calendar in this space */
1294 wprintf("<br />\n");
1295 embeddable_mini_calendar(year
, month
);
1297 wprintf("</font></center>\n");
1299 wprintf("</td></tr>"); /* end stuff-on-the-right */
1301 wprintf("</table>" /* end of inner table */
1304 StrBufAppendPrintf(WC
->trailing_javascript
,
1305 " setTimeout(\"btt_enableTooltips('inner_day')\", 1); \n"
1311 * Display today's events. Returns the number of items displayed.
1313 int calendar_summary_view(void) {
1315 const char *HashKey
;
1320 struct icaltimetype t
;
1325 int all_day_event
= 0;
1326 char timestring
[SIZ
];
1327 wcsession
*WCC
= WC
;
1328 int num_displayed
= 0;
1330 if (GetCount(WC
->disp_cal_items
) == 0) {
1335 localtime_r(&now
, &today_tm
);
1337 Pos
= GetNewHashPos(WCC
->disp_cal_items
, 0);
1338 while (GetNextHashPos(WCC
->disp_cal_items
, Pos
, &hklen
, &HashKey
, &vCal
)) {
1339 Cal
= (disp_cal
*)vCal
;
1340 p
= icalcomponent_get_first_property(Cal
->cal
, ICAL_DTSTART_PROPERTY
);
1342 t
= icalproperty_get_dtstart(p
);
1343 event_tt
= icaltime_as_timet(t
);
1350 fmt_time(timestring
, event_tt
);
1352 if (all_day_event
) {
1353 gmtime_r(&event_tt
, &event_tm
);
1356 localtime_r(&event_tt
, &event_tm
);
1359 if ( (event_tm
.tm_year
== today_tm
.tm_year
)
1360 && (event_tm
.tm_mon
== today_tm
.tm_mon
)
1361 && (event_tm
.tm_mday
== today_tm
.tm_mday
)
1364 p
= icalcomponent_get_first_property(Cal
->cal
, ICAL_SUMMARY_PROPERTY
);
1368 if (WCC
->wc_view
== VIEW_TASKS
) {
1369 wprintf("<a href=\"display_edit_task"
1371 "?return_to_summary=1"
1375 escputs(ChrPtr(WCC
->wc_roomname
));
1379 wprintf("<a href=\"display_edit_event"
1387 today_tm
.tm_year
+ 1900,
1388 today_tm
.tm_mon
+ 1,
1391 escputs(ChrPtr(WCC
->wc_roomname
));
1394 escputs((char *) icalproperty_get_comment(p
));
1395 if (!all_day_event
) {
1396 wprintf(" (%s)", timestring
);
1398 wprintf("</a><br />\n");
1404 DeleteHashPos(&Pos
);
1405 DeleteHash(&WC
->disp_cal_items
);
1406 return(num_displayed
);
1410 * Parse the URL variables in order to determine the scope and display of a calendar view
1412 void parse_calendar_view_request(struct calview
*c
) {
1418 /* In case no date was specified, go with today */
1420 localtime_r(&now
, &tm
);
1421 c
->year
= tm
.tm_year
+ 1900;
1422 c
->month
= tm
.tm_mon
+ 1;
1423 c
->day
= tm
.tm_mday
;
1425 /* Now see if a date was specified */
1426 if (havebstr("year")) c
->year
= ibstr("year");
1427 if (havebstr("month")) c
->month
= ibstr("month");
1428 if (havebstr("day")) c
->day
= ibstr("day");
1430 /* How would you like that cooked? */
1431 if (havebstr("calview")) {
1432 strcpy(calview
, bstr("calview"));
1435 strcpy(calview
, "month");
1438 /* Display the selected view */
1439 if (!strcasecmp(calview
, "day")) {
1440 c
->view
= calview_day
;
1442 else if (!strcasecmp(calview
, "week")) {
1443 c
->view
= calview_week
;
1445 else if (!strcasecmp(calview
, "summary")) { /* shouldn't ever happen, but just in case */
1446 c
->view
= calview_day
;
1449 if (WC
->wc_view
== VIEW_CALBRIEF
) {
1450 c
->view
= calview_brief
;
1453 c
->view
= calview_month
;
1457 /* Now try and set the lower and upper bounds so that we don't
1458 * burn too many cpu cycles parsing data way in the past or future
1461 tm
.tm_year
= c
->year
- 1900;
1462 tm
.tm_mon
= c
->month
- 1;
1463 tm
.tm_mday
= c
->day
;
1466 if (c
->view
== calview_month
) span
= 3888000;
1467 if (c
->view
== calview_brief
) span
= 3888000;
1468 if (c
->view
== calview_week
) span
= 604800;
1469 if (c
->view
== calview_day
) span
= 86400;
1470 if (c
->view
== calview_summary
) span
= 86400;
1472 c
->lower_bound
= now
- span
;
1473 c
->upper_bound
= now
+ span
;
1479 * Render a calendar view from data previously loaded into memory
1481 void render_calendar_view(struct calview
*c
)
1483 if (c
->view
== calview_day
) {
1484 calendar_day_view(c
->year
, c
->month
, c
->day
);
1486 else if (c
->view
== calview_week
) {
1487 calendar_week_view(c
->year
, c
->month
, c
->day
);
1490 if (WC
->wc_view
== VIEW_CALBRIEF
) {
1491 calendar_brief_month_view(c
->year
, c
->month
, c
->day
);
1494 calendar_month_view(c
->year
, c
->month
, c
->day
);
1498 /* Free the in-memory list of calendar items */
1499 DeleteHash(&WC
->disp_cal_items
);
1504 * Helper function for do_tasks_view(). Returns the due date/time of a vtodo.
1506 time_t get_task_due_date(icalcomponent
*vtodo
, int *is_date
) {
1509 if (vtodo
== NULL
) {
1514 * If we're looking at a fully encapsulated VCALENDAR
1515 * rather than a VTODO component, recurse into the data
1516 * structure until we get a VTODO.
1518 if (icalcomponent_isa(vtodo
) == ICAL_VCALENDAR_COMPONENT
) {
1519 return get_task_due_date(
1520 icalcomponent_get_first_component(
1521 vtodo
, ICAL_VTODO_COMPONENT
1526 p
= icalcomponent_get_first_property(vtodo
, ICAL_DUE_PROPERTY
);
1528 struct icaltimetype t
= icalproperty_get_due(p
);
1531 *is_date
= t
.is_date
;
1532 return(icaltime_as_timet(t
));
1541 * Compare the due dates of two tasks (this is for sorting)
1543 int task_due_cmp(const void *vtask1
, const void *vtask2
) {
1544 disp_cal
* Task1
= (disp_cal
*)GetSearchPayload(vtask1
);
1545 disp_cal
* Task2
= (disp_cal
*)GetSearchPayload(vtask2
);
1550 t1
= get_task_due_date(Task1
->cal
, NULL
);
1551 t2
= get_task_due_date(Task2
->cal
, NULL
);
1552 if (t1
< t2
) return(-1);
1553 if (t1
> t2
) return(1);
1558 * qsort filter to move completed tasks to bottom of task list
1560 int task_completed_cmp(const void *vtask1
, const void *vtask2
) {
1561 disp_cal
* Task1
= (disp_cal
*)GetSearchPayload(vtask1
);
1562 /* disp_cal * Task2 = (disp_cal *)GetSearchPayload(vtask2); */
1564 icalproperty_status t1
= icalcomponent_get_status((Task1
)->cal
);
1565 /* icalproperty_status t2 = icalcomponent_get_status(((struct disp_cal *)task2)->cal); */
1567 if (t1
== ICAL_STATUS_COMPLETED
)
1575 * do the whole task view stuff
1577 void do_tasks_view(void) {
1579 const char *HashKey
;
1587 wcsession
*WCC
= WC
;
1589 wprintf("<div class=\"fix_scrollbar_bug\">"
1590 "<table class=\"calendar_view_background\"><tbody id=\"taskview\">\n<tr>\n"
1592 wprintf(_("Completed?"));
1593 wprintf("</th><th>");
1594 wprintf(_("Name of task"));
1595 wprintf("</th><th>");
1596 wprintf(_("Date due"));
1597 wprintf("</th><th>");
1598 wprintf(_("Category"));
1599 wprintf(" (<select id=\"selectcategory\"><option value=\"showall\">%s</option></select>)</th></tr>\n",
1602 nItems
= GetCount(WC
->disp_cal_items
);
1604 /* Sort them if necessary
1606 SortByPayload(WC->disp_cal_items, task_due_cmp);
1608 * this shouldn't be neccessary, since we sort by the start time.
1611 /* And then again, by completed */
1613 SortByPayload(WC
->disp_cal_items
,
1614 task_completed_cmp
);
1617 Pos
= GetNewHashPos(WCC
->disp_cal_items
, 0);
1618 while (GetNextHashPos(WCC
->disp_cal_items
, Pos
, &hklen
, &HashKey
, &vCal
)) {
1619 icalproperty_status todoStatus
;
1622 Cal
= (disp_cal
*)vCal
;
1623 wprintf("<tr><td>");
1624 todoStatus
= icalcomponent_get_status(Cal
->cal
);
1625 wprintf("<input type=\"checkbox\" name=\"completed\" value=\"completed\" ");
1626 if (todoStatus
== ICAL_STATUS_COMPLETED
) {
1627 wprintf("checked=\"checked\" ");
1629 wprintf("disabled=\"disabled\">\n</td><td>");
1630 p
= icalcomponent_get_first_property(Cal
->cal
,
1631 ICAL_SUMMARY_PROPERTY
);
1632 wprintf("<a href=\"display_edit_task?msgnum=%ld?taskrm=", Cal
->cal_msgnum
);
1633 urlescputs(ChrPtr(WC
->wc_roomname
));
1635 /* wprintf("<img align=middle "
1636 "src=\"static/taskmanag_16x.gif\" border=0> "); */
1638 escputs((char *)icalproperty_get_comment(p
));
1643 due
= get_task_due_date(Cal
->cal
, &is_date
);
1644 wprintf("<td><span");
1646 webcit_fmt_date(buf
, due
, is_date
? DATEFMT_RAWDATE
: DATEFMT_FULL
);
1652 wprintf("</span></td>");
1654 p
= icalcomponent_get_first_property(Cal
->cal
,
1655 ICAL_CATEGORIES_PROPERTY
);
1657 escputs((char *)icalproperty_get_categories(p
));
1663 wprintf("</tbody></table></div>\n");
1666 DeleteHash(&WC
->disp_cal_items
);
1667 DeleteHashPos(&Pos
);