Back to index

webcit  8.12-dfsg
calendar_view.c
Go to the documentation of this file.
00001 /*
00002  * Handles the HTML display of calendar items.
00003  *
00004  * Copyright (c) 1996-2012 by the citadel.org team
00005  *
00006  * This program is open source software.  You can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License, version 3.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  */
00014 
00015 #include "webcit.h"
00016 #include "webserver.h"
00017 #include "calendar.h"
00018 
00019 /* These define how high the hour rows are in the day view */
00020 #define TIMELINE     30
00021 #define EXTRATIMELINE       (TIMELINE / 2)
00022 
00023 void embeddable_mini_calendar(int year, int month)
00024 {
00025        struct tm starting_tm;
00026        struct tm tm;
00027        time_t thetime;
00028        int i;
00029        time_t previous_month;
00030        time_t next_month;
00031        time_t colheader_time;
00032        struct tm colheader_tm;
00033        char colheader_label[32];
00034        long weekstart = 0;
00035        char url[256];
00036        char div_id[256];
00037 
00038        snprintf(div_id, sizeof div_id, "mini_calendar_%d", rand() );
00039 
00040        /* Determine what day to start.  If an impossible value is found, start on Sunday.
00041        */
00042        get_pref_long("weekstart", &weekstart, 17);
00043        if (weekstart > 6) weekstart = 0;
00044 
00045        /*
00046        * Now back up to the 1st of the month...
00047        */
00048        memset(&starting_tm, 0, sizeof(struct tm));
00049 
00050        starting_tm.tm_year = year - 1900;
00051        starting_tm.tm_mon = month - 1;
00052        starting_tm.tm_mday = 1;
00053        thetime = mktime(&starting_tm);
00054 
00055        memcpy(&tm, &starting_tm, sizeof(struct tm));
00056        while (tm.tm_mday != 1) {
00057               thetime = thetime - (time_t)86400; /* go back 24 hours */
00058               localtime_r(&thetime, &tm);
00059        }
00060 
00061        /* Determine previous and next months ... for links */
00062        previous_month = thetime - (time_t)864000L;      /* back 10 days */
00063        next_month = thetime + (time_t)(31L * 86400L);   /* ahead 31 days */
00064 
00065        /* Now back up until we're on the user's preferred start day */
00066        localtime_r(&thetime, &tm);
00067        while (tm.tm_wday != weekstart) {
00068               thetime = thetime - (time_t)86400; /* go back 24 hours */
00069               localtime_r(&thetime, &tm);
00070        }
00071 
00072        wc_printf("<div class=\"mini_calendar\" id=\"%s\">\n", div_id);
00073 
00074        /* Previous month link */
00075        localtime_r(&previous_month, &tm);
00076        wc_printf("<a href=\"javascript:minical_change_month(%d,%d);\">&laquo;</a>", 
00077               (int)(tm.tm_year)+1900, tm.tm_mon + 1);
00078 
00079        wc_strftime(colheader_label, sizeof colheader_label, "%B", &starting_tm);
00080        wc_printf("&nbsp;&nbsp;"
00081               "<span class=\"mini_calendar_month_label\">"
00082               "%s %d"
00083               "</span>"
00084               "&nbsp;&nbsp;", colheader_label, year);
00085 
00086        /* Next month link */
00087        localtime_r(&next_month, &tm);
00088        wc_printf("<a href=\"javascript:minical_change_month(%d,%d);\">&raquo;</a>",
00089               (int)(tm.tm_year)+1900, tm.tm_mon + 1);
00090 
00091        wc_printf("<table border=\"0\" cellpadding=\"1\" cellspacing=\"1\" class=\"mini_calendar_days\">"
00092               "<tr>");
00093        colheader_time = thetime;
00094        for (i=0; i<7; ++i) {
00095               colheader_time = thetime + (i * 86400) ;
00096               localtime_r(&colheader_time, &colheader_tm);
00097               wc_strftime(colheader_label, sizeof colheader_label, "%A", &colheader_tm);
00098               wc_printf("<th>%c</th>", colheader_label[0]);
00099 
00100        }
00101        wc_printf("</tr>\n");
00102 
00103 
00104         /* Now do 35 or 42 days */
00105         for (i = 0; i < 42; ++i) {
00106                 localtime_r(&thetime, &tm);
00107 
00108                 if (i < 35) {
00109 
00110                      /* Before displaying Sunday, start a new row */
00111                      if ((i % 7) == 0) {
00112                             wc_printf("<tr>");
00113                      }
00114 
00115                      if (tm.tm_mon == month-1) {
00116                             snprintf(url, sizeof url, "readfwd?calview=day?year=%d?month=%d?day=%d",
00117                                    tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday);
00118                             wc_printf("<td><a href=\"%s\">%d</a></td>", url, tm.tm_mday);
00119                      }
00120                      else {
00121                             wc_printf("<td> </td>");
00122                      }
00123 
00124                      /* After displaying one week, end the row */
00125                      if ((i % 7) == 6) {
00126                             wc_printf("</tr>\n");
00127                      }
00128 
00129               }
00130 
00131               thetime += (time_t)86400;          /* ahead 24 hours */
00132        }
00133 
00134        wc_printf("</table>"               /* end of inner table */
00135               "</div>\n");
00136 
00137        StrBufAppendPrintf(WC->trailing_javascript,
00138               "      function minical_change_month(year, month) {                                 \n"
00139               "             p = 'year=' + year + '&month=' + month                                \n"
00140               "                    + '&r=' + CtdlRandomString();                                    \n"
00141               "             new Ajax.Updater('%s', 'mini_calendar',                        \n"
00142               "                    { method: 'get', parameters: p, evalScripts: true } );         \n"
00143               "      }                                                                     \n"
00144               "",
00145               div_id
00146        );
00147 
00148 }
00149 
00150 /*
00151  * ajax embedder for the above mini calendar 
00152  */
00153 void ajax_mini_calendar(void) 
00154 {
00155        embeddable_mini_calendar( ibstr("year"), ibstr("month"));
00156 }
00157 
00158 
00159 /*
00160  * Display one day of a whole month view of a calendar
00161  */
00162 void calendar_month_view_display_events(int year, int month, int day)
00163 {
00164        long hklen;
00165        const char *HashKey;
00166        void *vCal;
00167        HashPos *Pos;
00168        disp_cal *Cal;
00169        icalproperty *p = NULL;
00170        icalproperty *q = NULL;
00171        struct icaltimetype t;
00172        struct icaltimetype end_t;
00173        struct icaltimetype today_start_t;
00174        struct icaltimetype today_end_t;
00175        struct icaltimetype today_t;
00176        struct tm starting_tm;
00177        struct tm ending_tm;
00178        int all_day_event = 0;
00179        int show_event = 0;
00180        char buf[256];
00181        wcsession *WCC = WC;
00182        time_t tt;
00183 
00184        if (GetCount(WCC->disp_cal_items) == 0) {
00185               wc_printf("<br>\n");
00186               return;
00187        }
00188 
00189        /*
00190         * Create an imaginary event which spans the 24 hours of today.  Any events which
00191         * overlap with this one take place at least partially in this day.  We have to
00192         * convert it from a struct tm in order to make it UTC.
00193         */
00194        memset(&starting_tm, 0, sizeof(struct tm));
00195        starting_tm.tm_year = year - 1900;
00196        starting_tm.tm_mon = month - 1;
00197        starting_tm.tm_mday = day;
00198        starting_tm.tm_hour = 0;
00199        starting_tm.tm_min = 0;
00200        today_start_t = icaltime_from_timet_with_zone(mktime(&starting_tm), 0, icaltimezone_get_utc_timezone());
00201        today_start_t.is_utc = 1;
00202 
00203        memset(&ending_tm, 0, sizeof(struct tm));
00204        ending_tm.tm_year = year - 1900;
00205        ending_tm.tm_mon = month - 1;
00206        ending_tm.tm_mday = day;
00207        ending_tm.tm_hour = 23;
00208        ending_tm.tm_min = 59;
00209        today_end_t = icaltime_from_timet_with_zone(mktime(&ending_tm), 0, icaltimezone_get_utc_timezone());
00210        today_end_t.is_utc = 1;
00211 
00212        /*
00213         * Create another one without caring about the timezone for all day events.
00214         */
00215        today_t = icaltime_null_date();
00216        today_t.year = year;
00217        today_t.month = month;
00218        today_t.day = day;
00219 
00220        /*
00221         * Now loop through our list of events to see which ones occur today.
00222         */
00223        Pos = GetNewHashPos(WCC->disp_cal_items, 0);
00224        while (GetNextHashPos(WCC->disp_cal_items, Pos, &hklen, &HashKey, &vCal)) {
00225               Cal = (disp_cal*)vCal;
00226               all_day_event = 0;
00227               q = icalcomponent_get_first_property(Cal->cal, ICAL_DTSTART_PROPERTY);
00228               if (q != NULL) {
00229                      t = icalproperty_get_dtstart(q);
00230               }
00231               else {
00232                      memset(&t, 0, sizeof t);
00233               }
00234               q = icalcomponent_get_first_property(Cal->cal, ICAL_DTEND_PROPERTY);
00235               if (q != NULL) {
00236                      end_t = icalproperty_get_dtend(q);
00237               }
00238               else {
00239                      memset(&end_t, 0, sizeof end_t);
00240               }
00241               if (t.is_date) all_day_event = 1;
00242 
00243               if (all_day_event)
00244               {
00245                      show_event = ical_ctdl_is_overlap(t, end_t, today_t, icaltime_null_time());
00246               }
00247               else
00248               {
00249                      show_event = ical_ctdl_is_overlap(t, end_t, today_start_t, today_end_t);
00250               }
00251 
00252               /*
00253                * If we determined that this event occurs today, then display it.
00254                */
00255               if (show_event) {
00256 
00257                      /* time_t logtt = icaltime_as_timet(t);
00258                      syslog(LOG_DEBUG, "Match on %04d-%02d-%02d for event %x%s on %s",
00259                             year, month, day,
00260                             (int)Cal, ((all_day_event) ? " (all day)" : ""),
00261                             ctime(&logtt)
00262                      ); */
00263 
00264                      p = icalcomponent_get_first_property(Cal->cal, ICAL_SUMMARY_PROPERTY);
00265                      if (p == NULL) {
00266                             p = icalproperty_new_summary(_("Untitled Event"));
00267                             icalcomponent_add_property(Cal->cal, p);
00268                      }
00269                      if (p != NULL) {
00270 
00271                             if (all_day_event) {
00272                                    wc_printf("<table border=\"0\" cellpadding=\"2\"><TR>"
00273                                           "<td bgcolor=\"#CCCCDD\">"
00274                                           );
00275                             }
00276 
00277 
00278                             wc_printf("<font size=\"-1\">"
00279                                    "<a class=\"event%s\" href=\"display_edit_event?"
00280                                    "msgnum=%ld?calview=month?year=%d?month=%d?day=%d\">"
00281                                    ,
00282                                    (Cal->unread)?"_unread":"_read",
00283                                    Cal->cal_msgnum,
00284                                    year, month, day
00285                             );
00286 
00287                             escputs((char *) icalproperty_get_comment(p));
00288 
00289                             wc_printf("<span class=\"tooltip\"><span class=\"btttop\"></span><span class=\"bttmiddle\">");
00290 
00291                             wc_printf("<i>%s: %s</i><br>", _("From"), Cal->from);
00292                             wc_printf("<i>%s</i> ",          _("Summary:"));
00293                             escputs((char *)icalproperty_get_comment(p));
00294                             wc_printf("<br>");
00295 
00296                             q = icalcomponent_get_first_property(
00297                                    Cal->cal,
00298                                    ICAL_LOCATION_PROPERTY);
00299                             if (q) {
00300                                    wc_printf("<i>%s</i> ", _("Location:"));
00301                                    escputs((char *)icalproperty_get_comment(q));
00302                                    wc_printf("<br>");
00303                             }
00304 
00305                             /*
00306                              * Only show start/end times if we're actually looking at the VEVENT
00307                              * component.  Otherwise it shows bogus dates for e.g. timezones
00308                              */
00309                             if (icalcomponent_isa(Cal->cal) == ICAL_VEVENT_COMPONENT) {
00310 
00311                                    q = icalcomponent_get_first_property(Cal->cal, ICAL_DTSTART_PROPERTY);
00312                                    if (q != NULL) {
00313                                           int no_end = 0;
00314 
00315                                           t = icalproperty_get_dtstart(q);
00316                                           q = icalcomponent_get_first_property(Cal->cal, ICAL_DTEND_PROPERTY);
00317                                           if (q != NULL) {
00318                                                  end_t = icalproperty_get_dtend(q);
00319                                           }
00320                                           else {
00321                                                  /*
00322                                                   * events with starting date/time equal
00323                                                   * ending date/time might get only
00324                                                   * DTSTART but no DTEND
00325                                                   */
00326                                                  no_end = 1;
00327                                           }
00328 
00329                                           if (t.is_date) {
00330                                                  /* all day event */
00331                                                  struct tm d_tm;
00332 
00333                                                  if (!no_end) {
00334                                                         /* end given, have to adjust it */
00335                                                         icaltime_adjust(&end_t, -1, 0, 0, 0);
00336                                                  }
00337                                                  memset(&d_tm, 0, sizeof d_tm);
00338                                                  d_tm.tm_year = t.year - 1900;
00339                                                  d_tm.tm_mon = t.month - 1;
00340                                                  d_tm.tm_mday = t.day;
00341                                                  wc_strftime(buf, sizeof buf, "%x", &d_tm);
00342 
00343                                                  if (no_end || !icaltime_compare(t, end_t)) {
00344                                                         wc_printf("<i>%s</i> %s<br>",
00345                                                                _("Date:"), buf);
00346                                                  }
00347                                                  else {
00348                                                         wc_printf("<i>%s</i> %s<br>",
00349                                                                _("Starting date:"), buf);
00350                                                         d_tm.tm_year = end_t.year - 1900;
00351                                                         d_tm.tm_mon = end_t.month - 1;
00352                                                         d_tm.tm_mday = end_t.day;
00353                                                         wc_strftime(buf, sizeof buf, "%x", &d_tm);
00354                                                         wc_printf("<i>%s</i> %s<br>",
00355                                                                _("Ending date:"), buf);
00356                                                  }
00357                                           }
00358                                           else {
00359                                                  tt = icaltime_as_timet(t);
00360                                                  webcit_fmt_date(buf, 256, tt, DATEFMT_BRIEF);
00361                                                  if (no_end || !icaltime_compare(t, end_t)) {
00362                                                         wc_printf("<i>%s</i> %s<br>",
00363                                                                _("Date/time:"), buf);
00364                                                  }
00365                                                  else {
00366                                                         wc_printf("<i>%s</i> %s<br>",
00367                                                                _("Starting date/time:"), buf);
00368                                                         tt = icaltime_as_timet(end_t);
00369                                                         webcit_fmt_date(buf, 256, tt, DATEFMT_BRIEF);
00370                                                         wc_printf("<i>%s</i> %s<br>", _("Ending date/time:"), buf);
00371                                                  }
00372 
00373                                           }
00374                                    }
00375 
00376                             }
00377 
00378                             q = icalcomponent_get_first_property(Cal->cal, ICAL_DESCRIPTION_PROPERTY);
00379                             if (q) {
00380                                    wc_printf("<i>%s</i> ", _("Notes:"));
00381                                    escputs((char *)icalproperty_get_comment(q));
00382                                    wc_printf("<br>");
00383                             }
00384 
00385                             wc_printf("</span><span class=\"bttbottom\"></span></span>");
00386                             wc_printf("</a></font><br>\n");
00387 
00388                             if (all_day_event) {
00389                                    wc_printf("</td></tr></table>");
00390                             }
00391 
00392                      }
00393 
00394               }
00395 
00396 
00397        }
00398        DeleteHashPos(&Pos);
00399 }
00400 
00401 
00402 /*
00403  * Display one day of a whole month view of a calendar
00404  */
00405 void calendar_month_view_brief_events(time_t thetime, const char *daycolor) {
00406        long hklen;
00407        const char *HashKey;
00408        void *vCal;
00409        HashPos *Pos;
00410        time_t event_tt;
00411        time_t event_tts;
00412        time_t event_tte;
00413        wcsession *WCC = WC;
00414        struct tm event_tms;
00415        struct tm event_tme;
00416        struct tm today_tm;
00417        icalproperty *p;
00418        icalproperty *e;
00419        struct icaltimetype t;
00420        disp_cal *Cal;
00421        int all_day_event = 0;
00422        char *timeformat;
00423        int time_format;
00424 
00425        time_format = get_time_format_cached ();
00426 
00427        if (time_format == WC_TIMEFORMAT_24) timeformat="%k:%M";
00428        else timeformat="%I:%M %p";
00429 
00430        localtime_r(&thetime, &today_tm);
00431 
00432        Pos = GetNewHashPos(WCC->disp_cal_items, 0);
00433        while (GetNextHashPos(WCC->disp_cal_items, Pos, &hklen, &HashKey, &vCal)) {
00434               Cal = (disp_cal*)vCal;
00435               p = icalcomponent_get_first_property(Cal->cal, ICAL_DTSTART_PROPERTY);
00436               if (p != NULL) {
00437                      t = icalproperty_get_dtstart(p);
00438                      event_tt = icaltime_as_timet(t);
00439                      event_tts=event_tt;
00440                      if (t.is_date) all_day_event = 1;
00441                      else all_day_event = 0;
00442 
00443                      if (all_day_event) {
00444                             gmtime_r(&event_tts, &event_tms);
00445                      }
00446                      else {
00447                             localtime_r(&event_tts, &event_tms);
00448                      }
00449                      /* \todo epoch &! daymask */
00450                      if ((event_tms.tm_year == today_tm.tm_year)
00451                             && (event_tms.tm_mon == today_tm.tm_mon)
00452                      && (event_tms.tm_mday == today_tm.tm_mday)) {
00453 
00454 
00455                      char sbuf[255];
00456                      char ebuf[255];
00457 
00458                      p = icalcomponent_get_first_property(
00459                             Cal->cal,
00460                             ICAL_SUMMARY_PROPERTY);
00461                      if (p == NULL) {
00462                             p = icalproperty_new_summary(_("Untitled Event"));
00463                             icalcomponent_add_property(Cal->cal, p);
00464                      }
00465                      e = icalcomponent_get_first_property(
00466                             Cal->cal, 
00467                             ICAL_DTEND_PROPERTY);
00468                      if ((p != NULL) && (e != NULL)) {
00469                             time_t difftime;
00470                             int hours, minutes;
00471                             t = icalproperty_get_dtend(e);
00472                             event_tte = icaltime_as_timet(t);
00473                             localtime_r(&event_tte, &event_tme);
00474                             difftime=(event_tte-event_tts)/60;
00475                             hours=(int)(difftime / 60);
00476                             minutes=difftime % 60;
00477                             wc_printf("<tr><td bgcolor='%s'>%i:%2i</td><td bgcolor='%s'>"
00478                                    "<font size=\"-1\">"
00479                                    "<a class=\"event%s\" href=\"display_edit_event?msgnum=%ld?calview=calbrief?year=%s?month=%s?day=%s\">",
00480                                    daycolor,
00481                                    hours, minutes,
00482                                    (Cal->unread)?"_unread":"_read",
00483                                    daycolor,
00484                                    Cal->cal_msgnum,
00485                                    bstr("year"),
00486                                    bstr("month"),
00487                                    bstr("day")
00488                                    );
00489 
00490                             escputs((char *)
00491                                    icalproperty_get_comment(p));
00492                             /* \todo: allso ammitime format */
00493                             wc_strftime(&sbuf[0], sizeof(sbuf), timeformat, &event_tms);
00494                             wc_strftime(&ebuf[0], sizeof(sbuf), timeformat, &event_tme);
00495 
00496                             wc_printf("</a></font></td>"
00497                                    "<td bgcolor='%s'>%s</td><td bgcolor='%s'>%s</td></tr>",
00498                                    daycolor,
00499                                    sbuf,
00500                                    daycolor,
00501                                    ebuf);
00502                             }
00503 
00504                      }
00505 
00506 
00507               }
00508        }
00509        DeleteHashPos(&Pos);
00510 }
00511 
00512 
00513 /*
00514  * view one month. pretty view
00515  */
00516 void calendar_month_view(int year, int month, int day) {
00517        struct tm starting_tm;
00518        struct tm tm;
00519        struct tm today_tm;
00520        time_t thetime;
00521        int i;
00522        time_t previous_month;
00523        time_t next_month;
00524        time_t colheader_time;
00525        time_t today_timet;
00526        struct tm colheader_tm;
00527        char colheader_label[32];
00528        long weekstart = 0;
00529 
00530        /*
00531         * Make sure we know which day is today.
00532         */
00533        today_timet = time(NULL);
00534        localtime_r(&today_timet, &today_tm);
00535 
00536        /*
00537         * Determine what day to start.  If an impossible value is found, start on Sunday.
00538         */
00539        get_pref_long("weekstart", &weekstart, 17);
00540        if (weekstart > 6) weekstart = 0;
00541 
00542        /*
00543         * Now back up to the 1st of the month...
00544         */
00545        memset(&starting_tm, 0, sizeof(struct tm));
00546 
00547        starting_tm.tm_year = year - 1900;
00548        starting_tm.tm_mon = month - 1;
00549        starting_tm.tm_mday = day;
00550        thetime = mktime(&starting_tm);
00551 
00552        memcpy(&tm, &starting_tm, sizeof(struct tm));
00553        while (tm.tm_mday != 1) {
00554               thetime = thetime - (time_t)86400; /* go back 24 hours */
00555               localtime_r(&thetime, &tm);
00556        }
00557 
00558        /* Determine previous and next months ... for links */
00559        previous_month = thetime - (time_t)864000L;      /* back 10 days */
00560        next_month = thetime + (time_t)(31L * 86400L);   /* ahead 31 days */
00561 
00562        /* Now back up until we're on the user's preferred start day */
00563        localtime_r(&thetime, &tm);
00564        while (tm.tm_wday != weekstart) {
00565               thetime = thetime - (time_t)86400; /* go back 24 hours */
00566               localtime_r(&thetime, &tm);
00567        }
00568 
00569        /* Outer table (to get the background color) */
00570        wc_printf("<table class=\"calendar\"> \n <tr><td>"); 
00571 
00572        wc_printf("<table width=\"100%%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr>\n");
00573 
00574        wc_printf("<td align=\"center\">");
00575 
00576        localtime_r(&previous_month, &tm);
00577        wc_printf("<a href=\"readfwd?calview=month?year=%d?month=%d?day=1\">",
00578               (int)(tm.tm_year)+1900, tm.tm_mon + 1);
00579        wc_printf("<img alt=\"%s\" align=\"middle\" src=\"static/webcit_icons/essen/32x32/back.png\" border=\"0\"></a>\n", _("previous"));
00580 
00581        wc_strftime(colheader_label, sizeof colheader_label, "%B", &starting_tm);
00582        wc_printf("&nbsp;&nbsp;"
00583               "<font size=\"+1\" color=\"#FFFFFF\">"
00584               "%s %d"
00585               "</font>"
00586               "&nbsp;&nbsp;", colheader_label, year);
00587 
00588        localtime_r(&next_month, &tm);
00589        wc_printf("<a href=\"readfwd?calview=month?year=%d?month=%d?day=1\">",
00590               (int)(tm.tm_year)+1900, tm.tm_mon + 1);
00591        wc_printf("<img alt=\"%s\" align=\"middle\" src=\"static/webcit_icons/essen/32x32/forward.png\" border=\"0\"></A>\n", _("next"));
00592 
00593        wc_printf("</td></tr></table>\n");
00594 
00595        /* Inner table (the real one) */
00596        wc_printf("<table width=\"100%%\" border=\"0\" cellpadding=\"1\" cellspacing=\"1\" "
00597               "bgcolor='#204B78' id=\"inner_month\"><tr>");
00598        wc_printf("<th align=\"center\" width=\"2%%\"></th>");
00599        colheader_time = thetime;
00600        for (i=0; i<7; ++i) {
00601               colheader_time = thetime + (i * 86400) ;
00602               localtime_r(&colheader_time, &colheader_tm);
00603               wc_strftime(colheader_label, sizeof colheader_label, "%A", &colheader_tm);
00604               wc_printf("<th align=\"center\" width=\"14%%\">"
00605                      "<font color=\"#FFFFFF\">%s</font></th>", colheader_label);
00606 
00607        }
00608        wc_printf("</tr>\n");
00609 
00610 
00611         /* Now do 35 or 42 days */
00612        localtime_r(&thetime, &tm);
00613         for (i = 0; i<42; ++i) {
00614 
00615               /* Before displaying the first day of the week, start a new row */
00616               if ((i % 7) == 0) {
00617                      wc_printf("<tr><td class=\"week_of_year\">");
00618                      wc_strftime(colheader_label, sizeof colheader_label, "%V", &tm);
00619                         wc_printf("%s ", colheader_label);
00620               }
00621 
00622               wc_printf("<td class=\"cal%s\"><div class=\"day\">",
00623                      ((tm.tm_mon != month-1) ? "out" :
00624                             (((tm.tm_year == today_tm.tm_year) && (tm.tm_mon == today_tm.tm_mon) && (tm.tm_mday == today_tm.tm_mday)) ? "today" :
00625                             ((tm.tm_wday==0 || tm.tm_wday==6) ? "weekend" :
00626                                    "day")))
00627                      );
00628               if ((i==0) || (tm.tm_mday == 1)) {
00629                      wc_strftime(colheader_label, sizeof colheader_label, "%B", &tm);
00630                      wc_printf("%s ", colheader_label);
00631               }
00632               wc_printf("<a href=\"readfwd?calview=day?year=%d?month=%d?day=%d\">"
00633                      "%d</a></div>",
00634                      tm.tm_year + 1900,
00635                      tm.tm_mon + 1,
00636                      tm.tm_mday,
00637                      tm.tm_mday);
00638 
00639               /* put the data here, stupid */
00640               calendar_month_view_display_events(
00641                      tm.tm_year + 1900,
00642                      tm.tm_mon + 1,
00643                      tm.tm_mday
00644                      );
00645 
00646               wc_printf("</td>");
00647 
00648               /* After displaying the last day of the week, end the row */
00649               if ((i % 7) == 6) {
00650                      wc_printf("</tr>\n");
00651               }
00652 
00653               thetime += (time_t)86400;          /* ahead 24 hours */
00654               localtime_r(&thetime, &tm);
00655 
00656               if ( ((i % 7) == 6) && (tm.tm_mon != month-1) && (tm.tm_mday < 15) ) {
00657                      i = 100;      /* break out of the loop */
00658               }
00659        }
00660 
00661        wc_printf("</table>"               /* end of inner table */
00662               "</td></tr></table>\n"             /* end of outer table */
00663        );
00664 }
00665 
00666 /*
00667  * view one month. brief view
00668  */
00669 void calendar_brief_month_view(int year, int month, int day) {
00670        struct tm starting_tm;
00671        struct tm tm;
00672        time_t thetime;
00673        int i;
00674        time_t previous_month;
00675        time_t next_month;
00676        char month_label[32];
00677 
00678        /* Determine what day to start.
00679         * First, back up to the 1st of the month...
00680         */
00681        memset(&starting_tm, 0, sizeof(struct tm));
00682        starting_tm.tm_year = year - 1900;
00683        starting_tm.tm_mon = month - 1;
00684        starting_tm.tm_mday = day;
00685        thetime = mktime(&starting_tm);
00686 
00687        memcpy(&tm, &starting_tm, sizeof(struct tm));
00688        while (tm.tm_mday != 1) {
00689               thetime = thetime - (time_t)86400; /* go back 24 hours */
00690               localtime_r(&thetime, &tm);
00691        }
00692 
00693        /* Determine previous and next months ... for links */
00694        previous_month = thetime - (time_t)864000L;      /* back 10 days */
00695        next_month = thetime + (time_t)(31L * 86400L);   /* ahead 31 days */
00696 
00697        /* Now back up until we're on a Sunday */
00698        localtime_r(&thetime, &tm);
00699        while (tm.tm_wday != 0) {
00700               thetime = thetime - (time_t)86400; /* go back 24 hours */
00701               localtime_r(&thetime, &tm);
00702        }
00703 
00704        /* Outer table (to get the background color) */
00705        wc_printf("<table width=\"100%%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" "
00706               "bgcolor=#204B78><tr><td>\n");
00707 
00708        wc_printf("<table width=\"100%%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr>\n");
00709 
00710        wc_printf("<td align=\"center\">");
00711 
00712        localtime_r(&previous_month, &tm);
00713        wc_printf("<a href=\"readfwd?calview=month?year=%d?month=%d?day=1\">",
00714               (int)(tm.tm_year)+1900, tm.tm_mon + 1);
00715        wc_printf("<img alt=\"%s\" align=\"middle\" src=\"static/webcit_icons/essen/32x32/back.png\" border=\"0\"></a>\n", _("previous"));
00716 
00717        wc_strftime(month_label, sizeof month_label, "%B", &tm);
00718        wc_printf("&nbsp;&nbsp;"
00719               "<font size=\"+1\" color=\"#FFFFFF\">"
00720               "%s %d"
00721               "</font>"
00722               "&nbsp;&nbsp;", month_label, year);
00723 
00724        localtime_r(&next_month, &tm);
00725        wc_printf("<a href=\"readfwd?calview=month?year=%d?month=%d?day=1\">",
00726               (int)(tm.tm_year)+1900, tm.tm_mon + 1);
00727        wc_printf("<img alt=\"%s\" align=\"middle\" src=\"static/webcit_icons/essen/32x32/forward.png\" border=\"0\"></a>\n", _("next"));
00728 
00729        wc_printf("</td></tr></table>\n");
00730 
00731        /* Inner table (the real one) */
00732        wc_printf("<table width=\"100%%\" border=\"0\" cellpadding=\"1\" cellspacing=\"1\" "
00733               "bgcolor=#EEEECC><TR>");
00734        wc_printf("</tr>\n");
00735        wc_printf("<tr><td colspan=\"100%%\">\n");
00736 
00737        /* Now do 35 days */
00738        for (i = 0; i < 35; ++i) {
00739               char weeknumber[255];
00740               char weekday_name[32];
00741               char *daycolor;
00742               localtime_r(&thetime, &tm);
00743 
00744 
00745               /* Before displaying Sunday, start a new CELL */
00746               if ((i % 7) == 0) {
00747                      wc_strftime(&weeknumber[0], sizeof(weeknumber), "%U", &tm);
00748                      wc_printf("<table border='0' bgcolor=\"#EEEECC\" width='100%%'> <tr><th colspan='4'>%s %s</th></tr>"
00749                             "   <tr><td>%s</td><td width='70%%'>%s</td><td>%s</td><td>%s</td></tr>\n",
00750                             _("Week"),
00751                             weeknumber,
00752                             _("Hours"),
00753                             _("Subject"),
00754                             _("Start"),
00755                             _("End")
00756                             );
00757               }
00758 
00759               daycolor=((tm.tm_mon != month-1) ? "DDDDDD" :
00760                      ((tm.tm_wday==0 || tm.tm_wday==6) ? "EEEECC" :
00761                             "FFFFFF"));
00762 
00763               /* Day Header */
00764               wc_strftime(weekday_name, sizeof weekday_name, "%A", &tm);
00765               wc_printf("<tr><td bgcolor='%s' colspan='1' align='left'> %s,%i."
00766                      "</td><td bgcolor='%s' colspan='3'><hr></td></tr>\n",
00767                      daycolor,
00768                      weekday_name,tm.tm_mday,
00769                      daycolor);
00770 
00771               /* put the data of one day  here, stupid */
00772               calendar_month_view_brief_events(thetime, daycolor);
00773 
00774 
00775               /* After displaying Saturday, end the row */
00776               if ((i % 7) == 6) {
00777                      wc_printf("</td></tr></table>\n");
00778               }
00779 
00780               thetime += (time_t)86400;          /* ahead 24 hours */
00781        }
00782 
00783        wc_printf("</table>"               /* end of inner table */
00784               "</td></tr></table>\n"             /* end of outer table */
00785        );
00786 }
00787 
00788 /*
00789  * Calendar week view -- not implemented yet, this is a stub function
00790  */
00791 void calendar_week_view(int year, int month, int day) {
00792        wc_printf("<center><i>week view FIXME</i></center><br>\n");
00793 }
00794 
00795 
00796 /*
00797  * display one day
00798  * Display events for a particular hour of a particular day.
00799  * (Specify hour < 0 to show "all day" events)
00800  *
00801  * dstart and dend indicate which hours our "daytime" begins and end
00802  */
00803 void calendar_day_view_display_events(time_t thetime,
00804        int year,
00805        int month,
00806        int day,
00807        int notime_events,
00808        int dstart,
00809        int dend)
00810 {
00811        long hklen;
00812        const char *HashKey;
00813        void *vCal;
00814        HashPos *Pos;
00815        icalproperty *p = NULL;
00816        icalproperty *q = NULL;
00817        time_t event_tt;
00818        time_t event_tte;
00819        struct tm event_te;
00820        struct tm event_tm;
00821        int show_event = 0;
00822        int all_day_event = 0;
00823        int ongoing_event = 0;
00824        wcsession *WCC = WC;
00825        disp_cal *Cal;
00826        struct icaltimetype t;
00827        struct icaltimetype end_t;
00828        struct icaltimetype today_start_t;
00829        struct icaltimetype today_end_t;
00830        struct icaltimetype today_t;
00831        struct tm starting_tm;
00832        struct tm ending_tm;
00833        int top = 0;
00834        int bottom = 0;
00835        int gap = 1;
00836        int startmin = 0;
00837        int diffmin = 0;
00838        int endmin = 0;
00839 
00840         char buf[256];
00841 
00842        if (GetCount(WCC->disp_cal_items) == 0) {
00843               /* nothing to display */
00844               return;
00845        }
00846 
00847        /* Create an imaginary event which spans the current day.  Any events which
00848         * overlap with this one take place at least partially in this day.
00849         */
00850        memset(&starting_tm, 0, sizeof(struct tm));
00851        starting_tm.tm_year = year - 1900;
00852        starting_tm.tm_mon = month - 1;
00853        starting_tm.tm_mday = day;
00854        starting_tm.tm_hour = 0;
00855        starting_tm.tm_min = 0;
00856        today_start_t = icaltime_from_timet_with_zone(mktime(&starting_tm), 0, icaltimezone_get_utc_timezone());
00857        today_start_t.is_utc = 1;
00858 
00859        memset(&ending_tm, 0, sizeof(struct tm));
00860        ending_tm.tm_year = year - 1900;
00861        ending_tm.tm_mon = month - 1;
00862        ending_tm.tm_mday = day;
00863        ending_tm.tm_hour = 23;
00864        ending_tm.tm_min = 59;
00865        today_end_t = icaltime_from_timet_with_zone(mktime(&ending_tm), 0, icaltimezone_get_utc_timezone());
00866        today_end_t.is_utc = 1;
00867 
00868        /*
00869         * Create another one without caring about the timezone for all day events.
00870         */
00871        today_t = icaltime_null_date();
00872        today_t.year = year;
00873        today_t.month = month;
00874        today_t.day = day;
00875 
00876        /* Now loop through our list of events to see which ones occur today.
00877         */
00878        Pos = GetNewHashPos(WCC->disp_cal_items, 0);
00879        while (GetNextHashPos(WCC->disp_cal_items, Pos, &hklen, &HashKey, &vCal)) {
00880               Cal = (disp_cal*)vCal;
00881 
00882               all_day_event = 0;
00883               ongoing_event=0;
00884 
00885               q = icalcomponent_get_first_property(Cal->cal, ICAL_DTSTART_PROPERTY);
00886               if (q != NULL) {
00887                      t = icalproperty_get_dtstart(q);
00888                      event_tt = icaltime_as_timet(t);
00889                      localtime_r(&event_tt, &event_te);
00890               }
00891               else {
00892                      memset(&t, 0, sizeof t);
00893               }
00894 
00895               if (t.is_date) all_day_event = 1;
00896 
00897               q = icalcomponent_get_first_property(Cal->cal, ICAL_DTEND_PROPERTY);
00898               if (q != NULL) {
00899                      end_t = icalproperty_get_dtend(q);
00900               }
00901               else {
00902                      /* no end given means end = start */
00903                      memcpy(&end_t, &t, sizeof(struct icaltimetype));
00904               }
00905 
00906               if (all_day_event)
00907               {
00908                      show_event = ical_ctdl_is_overlap(t, end_t, today_t, icaltime_null_time());
00909                      if (icaltime_compare(t, end_t)) {
00910                             /*
00911                              * the end date is non-inclusive so adjust it by one
00912                              * day because our test is inclusive, note that a day is
00913                              * not to much because we are talking about all day
00914                              * events
00915                              */
00916                             icaltime_adjust(&end_t, -1, 0, 0, 0);
00917                      }
00918               }
00919               else
00920               {
00921                      show_event = ical_ctdl_is_overlap(t, end_t, today_start_t, today_end_t);
00922               }
00923 
00924               event_tte = icaltime_as_timet(end_t);
00925               localtime_r(&event_tte, &event_tm);
00926 
00927               /* If we determined that this event occurs today, then display it.
00928                */
00929               p = icalcomponent_get_first_property(Cal->cal,ICAL_SUMMARY_PROPERTY);
00930               if (p == NULL) {
00931                      p = icalproperty_new_summary(_("Untitled Event"));
00932                      icalcomponent_add_property(Cal->cal, p);
00933               }
00934 
00935               if ((show_event) && (p != NULL)) {
00936 
00937                      if ((event_te.tm_mday != day) || (event_tm.tm_mday != day)) ongoing_event = 1; 
00938 
00939                      if (all_day_event && notime_events)
00940                      {
00941                             wc_printf("<li class=\"event_framed%s\"> "
00942                                    "<a href=\"display_edit_event?"
00943                                    "msgnum=%ld?calview=day?year=%d?month=%d?day=%d\" "
00944                                    " class=\"event_title\">"
00945                                    ,
00946                                    (Cal->unread)?"_unread":"_read",
00947                                         Cal->cal_msgnum, year, month, day
00948                             );
00949                                 escputs((char *) icalproperty_get_comment(p));
00950                             wc_printf("<span class=\"tooltip\"><span class=\"btttop\"></span><span class=\"bttmiddle\">");
00951                                 wc_printf("<i>%s</i><br>",      _("All day event"));
00952                             wc_printf("<i>%s: %s</i><br>",  _("From"), Cal->from);
00953                                 wc_printf("<i>%s</i> ",           _("Summary:"));
00954                                 escputs((char *) icalproperty_get_comment(p));
00955                                 wc_printf("<br>");
00956                             q = icalcomponent_get_first_property(Cal->cal,ICAL_LOCATION_PROPERTY);
00957                                 if (q) {
00958                                         wc_printf("<i>%s</i> ", _("Location:"));
00959                                         escputs((char *)icalproperty_get_comment(q));
00960                                         wc_printf("<br>");
00961                             }
00962                             if (!icaltime_compare(t, end_t)) { /* one day only */
00963                                    webcit_fmt_date(buf, 256, event_tt, DATEFMT_LOCALEDATE);
00964                                    wc_printf("<i>%s</i> %s<br>", _("Date:"), buf);
00965                             }
00966                             else {
00967                                    webcit_fmt_date(buf, 256, event_tt, DATEFMT_LOCALEDATE);
00968                                    wc_printf("<i>%s</i> %s<br>", _("Starting date:"), buf);
00969                                    webcit_fmt_date(buf, 256, event_tte, DATEFMT_LOCALEDATE);
00970                                    wc_printf("<i>%s</i> %s<br>", _("Ending date:"), buf);
00971                             }
00972                             q = icalcomponent_get_first_property(Cal->cal,ICAL_DESCRIPTION_PROPERTY);
00973                                 if (q) {
00974                                         wc_printf("<i>%s</i> ", _("Notes:"));
00975                                         escputs((char *)icalproperty_get_comment(q));
00976                                         wc_printf("<br>");
00977                                 }
00978                             wc_printf("</span><span class=\"bttbottom\"></span></span>");
00979                                 wc_printf("</a> <span>(");
00980                                 wc_printf(_("All day event"));
00981                                 wc_printf(")</span></li>\n");
00982                      }
00983                      else if (ongoing_event && notime_events) 
00984                      {
00985                             wc_printf("<li class=\"event_framed%s\"> "
00986                                    "<a href=\"display_edit_event?"
00987                                    "msgnum=%ld&calview=day?year=%d?month=%d?day=%d\" "
00988                                    " class=\"event_title\">" 
00989                                    ,
00990                                    (Cal->unread)?"_unread":"_read",
00991                                    Cal->cal_msgnum, year, month, day
00992                             );
00993                             escputs((char *) icalproperty_get_comment(p));
00994                             wc_printf("<span class=\"tooltip\"><span class=\"btttop\"></span><span class=\"bttmiddle\">");
00995                                 wc_printf("<i>%s</i><br>",     _("Ongoing event"));
00996                             wc_printf("<i>%s: %s</i><br>", _("From"), Cal->from);
00997                                 wc_printf("<i>%s</i> ",          _("Summary:"));
00998                                 escputs((char *) icalproperty_get_comment(p));
00999                                 wc_printf("<br>");
01000                                 q = icalcomponent_get_first_property(Cal->cal,ICAL_LOCATION_PROPERTY);
01001                                 if (q) {
01002                                         wc_printf("<i>%s</i> ", _("Location:"));
01003                                         escputs((char *)icalproperty_get_comment(q));
01004                                         wc_printf("<br>");
01005                                                         }
01006                                 webcit_fmt_date(buf, 256, event_tt, DATEFMT_BRIEF);
01007                                 wc_printf("<i>%s</i> %s<br>", _("Starting date/time:"), buf);
01008                                 webcit_fmt_date(buf, 256, event_tte, DATEFMT_BRIEF);
01009                                 wc_printf("<i>%s</i> %s<br>", _("Ending date/time:"), buf);
01010                                 q = icalcomponent_get_first_property(Cal->cal,ICAL_DESCRIPTION_PROPERTY);
01011                                 if (q) {
01012                                         wc_printf("<i>%s</i> ", _("Notes:"));
01013                                         escputs((char *)icalproperty_get_comment(q));
01014                                         wc_printf("<br>");
01015                                 }
01016                                 wc_printf("</span><span class=\"bttbottom\"></span></span>");
01017                             wc_printf("</a> <span>(");
01018                             wc_printf(_("Ongoing event"));
01019                             wc_printf(")</span></li>\n");
01020                      }
01021                      else if (!all_day_event && !notime_events)
01022                      {
01023                             gap++;
01024 
01025                             if (event_te.tm_mday != day) event_te.tm_hour = 0;
01026                             if (event_tm.tm_mday != day) event_tm.tm_hour = 24;
01027 
01028                             /* Calculate the location of the top of the box */
01029                             if (event_te.tm_hour < dstart) {
01030                                    startmin = diffmin = event_te.tm_min / 6;
01031                                    top = (event_te.tm_hour * EXTRATIMELINE) + startmin;
01032                             }
01033                             else if ((event_te.tm_hour >= dstart) && (event_te.tm_hour <= dend)) {
01034                                    startmin = diffmin = (event_te.tm_min / 2);
01035                                    top = (dstart * EXTRATIMELINE) + ((event_te.tm_hour - dstart) * TIMELINE) + startmin;
01036                             }
01037                             else if (event_te.tm_hour >dend) {
01038                                    startmin = diffmin = event_te.tm_min / 6;
01039                                    top = (dstart * EXTRATIMELINE) + ((dend - dstart - 1) * TIMELINE) + ((event_tm.tm_hour - dend + 1) * EXTRATIMELINE) + startmin ;
01040                             }
01041                             else {
01042                                    /* should never get here */
01043                             }
01044 
01045                             /* Calculate the location of the bottom of the box */
01046                             if (event_tm.tm_hour < dstart) {
01047                                    endmin = diffmin = event_tm.tm_min / 6;
01048                                    bottom = (event_tm.tm_hour * EXTRATIMELINE) + endmin;
01049                             }
01050                             else if ((event_tm.tm_hour >= dstart) && (event_tm.tm_hour <= dend)) {
01051                                    endmin = diffmin = (event_tm.tm_min / 2);
01052                                    bottom = (dstart * EXTRATIMELINE) + ((event_tm.tm_hour - dstart) * TIMELINE) + endmin ;
01053                             }
01054                             else if (event_tm.tm_hour >dend) {
01055                                    endmin = diffmin = event_tm.tm_min / 6;
01056                                    bottom = (dstart * EXTRATIMELINE) + ((dend - dstart + 1) * TIMELINE) + ((event_tm.tm_hour - dend - 1) * EXTRATIMELINE) + endmin;
01057                             }
01058                             else {
01059                                    /* should never get here */
01060                             }
01061 
01062                             wc_printf("<dd  class=\"event_framed%s\" "
01063                                    "style=\"position: absolute; "
01064                                    "top:%dpx; left:%dpx; "
01065                                    "height:%dpx; \" >",
01066                                    (Cal->unread)?"_unread":"_read",
01067                                    top, (gap * 40), (bottom-top)
01068                                    );
01069                             wc_printf("<a href=\"display_edit_event?"
01070                                    "msgnum=%ld?calview=day?year=%d?month=%d?day=%d?hour=%d\" "
01071                                    "class=\"event_title\">"
01072                                    ,
01073                                    Cal->cal_msgnum, year, month, day, t.hour
01074                             );
01075                             escputs((char *) icalproperty_get_comment(p));
01076                             wc_printf("<span class=\"tooltip\"><span class=\"btttop\"></span><span class=\"bttmiddle\">");
01077                             wc_printf("<i>%s: %s</i><br>", _("From"), Cal->from);
01078                                 wc_printf("<i>%s</i> ",          _("Summary:"));
01079                                 escputs((char *) icalproperty_get_comment(p));
01080                                 wc_printf("<br>");
01081                                 q = icalcomponent_get_first_property(Cal->cal,ICAL_LOCATION_PROPERTY);
01082                                 if (q) {
01083                                         wc_printf("<i>%s</i> ", _("Location:"));
01084                                         escputs((char *)icalproperty_get_comment(q));
01085                                         wc_printf("<br>");
01086                                                         }
01087                             if (!icaltime_compare(t, end_t)) { /* one day only */
01088                                    webcit_fmt_date(buf, 256, event_tt, DATEFMT_BRIEF);
01089                                    wc_printf("<i>%s</i> %s<br>", _("Date/time:"), buf);
01090                             }
01091                             else {
01092                                    webcit_fmt_date(buf, 256, event_tt, DATEFMT_BRIEF);
01093                                    wc_printf("<i>%s</i> %s<br>", _("Starting date/time:"), buf);
01094                                    webcit_fmt_date(buf, 256, event_tte, DATEFMT_BRIEF);
01095                                    wc_printf("<i>%s</i> %s<br>", _("Ending date/time:"), buf);
01096                             }
01097                             q = icalcomponent_get_first_property(Cal->cal,ICAL_DESCRIPTION_PROPERTY);
01098                                 if (q) {
01099                                         wc_printf("<i>%s</i> ", _("Notes:"));
01100                                         escputs((char *)icalproperty_get_comment(q));
01101                                         wc_printf("<br>");
01102                                 }
01103                             wc_printf("</span><span class=\"bttbottom\"></span></span>");
01104                             wc_printf("</a></dd>\n");
01105                      }
01106               }
01107        }
01108        DeleteHashPos(&Pos);
01109 }
01110 
01111 /*
01112  * view one day
01113  */
01114 void calendar_day_view(int year, int month, int day) {
01115        int hour;
01116        struct icaltimetype today, yesterday, tomorrow;
01117        long daystart;
01118        long dayend;
01119        struct tm d_tm;
01120        char d_str[160];
01121        int time_format;
01122        time_t today_t;
01123        int timeline = TIMELINE;
01124        int extratimeline = EXTRATIMELINE;
01125        int gap = 0;
01126        int hourlabel;
01127        int extrahourlabel;
01128 
01129        time_format = get_time_format_cached ();
01130        get_pref_long("daystart", &daystart, 8);
01131        get_pref_long("dayend", &dayend, 17);
01132 
01133        /* when loading daystart/dayend, replace missing, corrupt, or impossible values with defaults */
01134        if ((daystart < 0) || (dayend < 2) || (daystart >= 23) || (dayend > 23) || (dayend <= daystart)) {
01135               daystart = 9;
01136               dayend = 17;
01137        }
01138 
01139        /* Today's date */
01140        memset(&d_tm, 0, sizeof d_tm);
01141        d_tm.tm_year = year - 1900;
01142        d_tm.tm_mon = month - 1;
01143        d_tm.tm_mday = day;
01144        today_t = mktime(&d_tm); 
01145 
01146        /* Figure out the dates for "yesterday" and "tomorrow" links */
01147 
01148        memset(&today, 0, sizeof(struct icaltimetype));
01149        today.year = year;
01150        today.month = month;
01151        today.day = day;
01152        today.is_date = 1;
01153 
01154        memcpy(&yesterday, &today, sizeof(struct icaltimetype));
01155        --yesterday.day;
01156        yesterday = icaltime_normalize(yesterday);
01157 
01158        memcpy(&tomorrow, &today, sizeof(struct icaltimetype));
01159        ++tomorrow.day;
01160        tomorrow = icaltime_normalize(tomorrow);
01161 
01162        /* Inner table (the real one) */
01163        wc_printf("<table class=\"calendar\" id=\"inner_day\"><tr> \n");
01164 
01165        /* Innermost cell (contains hours etc.) */
01166        wc_printf("<td class=\"events_of_the_day\" >");
01167               wc_printf("<dl class=\"events\" >");
01168 
01169        /* Now the middle of the day... */
01170 
01171        extrahourlabel = extratimeline - 2;
01172        hourlabel = extrahourlabel * 150 / 100;
01173        if (hourlabel > (timeline - 2)) hourlabel = timeline - 2;
01174 
01175        for (hour = 0; hour < daystart; ++hour) { /* could do HEIGHT=xx */
01176               wc_printf("<dt class=\"extrahour\">"
01177                      "<a href=\"display_edit_event?msgnum=0"
01178                      "?calview=day?year=%d?month=%d?day=%d?hour=%d?minute=0\">",
01179 /* TODO: what have these been used for?
01180                      (hour * extratimeline ),
01181                      extratimeline,
01182                      extrahourlabel,
01183 */
01184                      year, month, day, hour
01185                      );
01186 
01187               if (time_format == WC_TIMEFORMAT_24) {
01188                      wc_printf("%2d:00</a> ", hour);
01189               }
01190               else {
01191                      wc_printf("%d:00%s</a> ",
01192                             ((hour == 0) ? 12 : (hour <= 12 ? hour : hour-12)),
01193                             (hour < 12 ? "am" : "pm")
01194                             );
01195               }
01196 
01197               wc_printf("</dt>");
01198        }
01199 
01200        gap = daystart * extratimeline;
01201 
01202         for (hour = daystart; hour <= dayend; ++hour) {       /* could do HEIGHT=xx */
01203                 wc_printf("<dt class=\"hour\">"
01204                         "<a href=\"display_edit_event?msgnum=0?calview=day"
01205                         "?year=%d?month=%d?day=%d?hour=%d?minute=0\">",
01206 /*TODO: what have these been used for?
01207                         gap + ((hour - daystart) * timeline ),
01208                      timeline,
01209                      hourlabel,
01210 */
01211                         year, month, day, hour
01212                      );
01213 
01214                 if (time_format == WC_TIMEFORMAT_24) {
01215                         wc_printf("%2d:00</a> ", hour);
01216                 }
01217                 else {
01218                         wc_printf("%d:00%s</a> ",
01219                                 (hour <= 12 ? hour : hour-12),
01220                                 (hour < 12 ? "am" : "pm")
01221                                           );
01222                 }
01223 
01224                 wc_printf("</dt>");
01225         }
01226 
01227        gap = gap + ((dayend - daystart + 1) * timeline);
01228 
01229         for (hour = (dayend + 1); hour < 24; ++hour) {       /* could do HEIGHT=xx */
01230                 wc_printf("<dt class=\"extrahour\">"
01231                         "<a href=\"display_edit_event?msgnum=0?calview=day"
01232                         "?year=%d?month=%d?day=%d?hour=%d?minute=0\">",
01233 /*TODO: what have these been used for?
01234                         gap + ((hour - dayend - 1) * extratimeline ),
01235                      extratimeline,
01236                      extrahourlabel,
01237 */
01238                         year, month, day, hour
01239                 );
01240 
01241                 if (time_format == WC_TIMEFORMAT_24) {
01242                         wc_printf("%2d:00</a> ", hour);
01243                 }
01244                 else {
01245                         wc_printf("%d:00%s</a> ",
01246                                 (hour <= 12 ? hour : hour-12),
01247                                 (hour < 12 ? "am" : "pm")
01248                         );
01249                 }
01250 
01251                 wc_printf("</dt>");
01252         }
01253 
01254        /* Display events with start and end times on this day */
01255        calendar_day_view_display_events(today_t, year, month, day, 0, daystart, dayend);
01256 
01257               wc_printf("</dl>");
01258        wc_printf("</td>");                /* end of innermost table */
01259 
01260        /* Display extra events (start/end times not present or not today) in the middle column */
01261         wc_printf("<td class=\"extra_events\">");
01262 
01263         wc_printf("<ul>");
01264 
01265         /* Display all-day events */
01266        calendar_day_view_display_events(today_t, year, month, day, 1, daystart, dayend);
01267 
01268         wc_printf("</ul>");
01269 
01270        wc_printf("</td>");  /* end extra on the middle */
01271 
01272        wc_printf("<td width='20%%' align=\"center\" valign=top>");    /* begin stuff-on-the-right */
01273 
01274        /* Begin todays-date-with-left-and-right-arrows */
01275        wc_printf("<table border=\"0\" width=\"100%%\" "
01276               "cellspacing=\"0\" cellpadding=\"0\" bgcolor=\"#FFFFFF\">\n");
01277        wc_printf("<tr>");
01278 
01279        /* Left arrow */
01280        wc_printf("<td align=\"center\">");
01281        wc_printf("<a href=\"readfwd?calview=day?year=%d?month=%d?day=%d\">",
01282               yesterday.year, yesterday.month, yesterday.day);
01283        wc_printf("<img alt=\"previous\" align=\"middle\" src=\"static/webcit_icons/essen/32x32/back.png\" border=\"0\"></a>");
01284        wc_printf("</td>");
01285 
01286        wc_strftime(d_str, sizeof d_str,
01287               "<td align=\"center\">"
01288               "<font size='+2'>%A</font><br>"
01289               "<font size='+2'>%B</font><br>"
01290               "<font size='+3'>%d</font><br>"
01291               "<font size='+2'>%Y</font><br>"
01292               "</td>",
01293               &d_tm
01294               );
01295        wc_printf("%s", d_str);
01296 
01297        /* Right arrow */
01298        wc_printf("<td align=\"center\">");
01299        wc_printf("<a href=\"readfwd?calview=day?year=%d?month=%d?day=%d\">",
01300               tomorrow.year, tomorrow.month, tomorrow.day);
01301        wc_printf("<img alt=\"%s\" align=\"middle\" src=\"static/webcit_icons/essen/32x32/forward.png\""
01302               " border=\"0\"></a>\n", _("next"));
01303        wc_printf("</td>");
01304 
01305        wc_printf("</tr></table>\n");
01306        /* End todays-date-with-left-and-right-arrows */
01307 
01308        /* Embed a mini month calendar in this space */
01309        wc_printf("<br>\n");
01310        embeddable_mini_calendar(year, month);
01311 
01312        wc_printf("</td></tr>");                  /* end stuff-on-the-right */
01313        wc_printf("</table>\n");                  /* end of inner table */
01314 }
01315 
01316 
01317 /*
01318  * Display today's events.  Returns the number of items displayed.
01319  */
01320 int calendar_summary_view(void) {
01321        long hklen;
01322        const char *HashKey;
01323        void *vCal;
01324        HashPos *Pos;
01325        disp_cal *Cal;
01326        icalproperty *p;
01327        struct icaltimetype t;
01328        time_t event_tt;
01329        struct tm event_tm;
01330        struct tm today_tm;
01331        time_t now;
01332        int all_day_event = 0;
01333        char timestring[SIZ];
01334        wcsession *WCC = WC;
01335        int num_displayed = 0;
01336 
01337        if (GetCount(WC->disp_cal_items) == 0) {
01338               return(0);
01339        }
01340 
01341        now = time(NULL);
01342        localtime_r(&now, &today_tm);
01343 
01344        Pos = GetNewHashPos(WCC->disp_cal_items, 0);
01345        while (GetNextHashPos(WCC->disp_cal_items, Pos, &hklen, &HashKey, &vCal)) {
01346               Cal = (disp_cal*)vCal;
01347               p = icalcomponent_get_first_property(Cal->cal, ICAL_DTSTART_PROPERTY);
01348               if (p != NULL) {
01349                      t = icalproperty_get_dtstart(p);
01350                      event_tt = icaltime_as_timet(t);
01351                      if (t.is_date) {
01352                             all_day_event = 1;
01353                      }
01354                      else {
01355                             all_day_event = 0;
01356                      }
01357                      fmt_time(timestring, SIZ, event_tt);
01358 
01359                      if (all_day_event) {
01360                             gmtime_r(&event_tt, &event_tm);
01361                      }
01362                      else {
01363                             localtime_r(&event_tt, &event_tm);
01364                      }
01365 
01366                      if ( (event_tm.tm_year == today_tm.tm_year)
01367                             && (event_tm.tm_mon == today_tm.tm_mon)
01368                             && (event_tm.tm_mday == today_tm.tm_mday)
01369                      ) {
01370 
01371                             p = icalcomponent_get_first_property(Cal->cal, ICAL_SUMMARY_PROPERTY);
01372                             if (p == NULL) {
01373                                    p = icalproperty_new_summary(_("Untitled Task"));
01374                                    icalcomponent_add_property(Cal->cal, p);
01375                             }
01376                             if (p != NULL)
01377                             {
01378                                    if (WCC->CurRoom.view == VIEW_TASKS) {
01379                                           wc_printf("<a href=\"display_edit_task"
01380                                                  "?msgnum=%ld"
01381                                                  "?return_to_summary=1"
01382                                                  "?go=",
01383                                                  Cal->cal_msgnum
01384                                           );
01385                                           escputs(ChrPtr(WCC->CurRoom.name));
01386                                           wc_printf("\">");
01387                                    }
01388                                    else {
01389                                           wc_printf("<a href=\"display_edit_event"
01390                                                  "?msgnum=%ld"
01391                                                  "?calview=summary"
01392                                                  "?year=%d"
01393                                                  "?month=%d"
01394                                                  "?day=%d"
01395                                                  "?go=",
01396                                                  Cal->cal_msgnum,
01397                                                  today_tm.tm_year + 1900,
01398                                                  today_tm.tm_mon + 1,
01399                                                  today_tm.tm_mday
01400                                           );
01401                                           escputs(ChrPtr(WCC->CurRoom.name));
01402                                           wc_printf("\">");
01403                                    }
01404                                    escputs((char *) icalproperty_get_comment(p));
01405                                    if (!all_day_event) {
01406                                           wc_printf(" (%s)", timestring);
01407                                    }
01408                                    wc_printf("</a><br>\n");
01409                                    ++num_displayed;
01410                             }
01411                      }
01412               }
01413        }
01414        DeleteHashPos(&Pos);
01415        DeleteHash(&WC->disp_cal_items);
01416        return(num_displayed);
01417 }
01418 
01419 /*
01420  * Parse the URL variables in order to determine the scope and display of a calendar view
01421  */
01422 int calendar_GetParamsGetServerCall(SharedMessageStatus *Stat,
01423                                 void **ViewSpecific,
01424                                 long oper,
01425                                 char *cmd,
01426                                 long len,
01427                                 char *filter,
01428                                 long flen)
01429 {
01430        wcsession *WCC = WC;
01431        calview *c;
01432        time_t now;
01433        struct tm tm;
01434        char cv[32];
01435 
01436        int span = 3888000;
01437 
01438        c = (calview*) malloc(sizeof(calview));
01439        memset(c, 0, sizeof(calview));
01440        *ViewSpecific = (void*)c;
01441 
01442        Stat->load_seen = 1;
01443        strcpy(cmd, "MSGS ALL");
01444        Stat->maxmsgs = 32767;
01445 
01446        /* In case no date was specified, go with today */
01447        now = time(NULL);
01448        localtime_r(&now, &tm);
01449        c->year = tm.tm_year + 1900;
01450        c->month = tm.tm_mon + 1;
01451        c->day = tm.tm_mday;
01452 
01453        /* Now see if a date was specified */
01454        if (havebstr("year")) c->year = ibstr("year");
01455        if (havebstr("month")) c->month = ibstr("month");
01456        if (havebstr("day")) c->day = ibstr("day");
01457 
01458        /* How would you like that cooked? */
01459        if (havebstr("calview")) {
01460               strcpy(cv, bstr("calview"));
01461        }
01462        else {
01463               strcpy(cv, "month");
01464        }
01465 
01466        /* Display the selected view */
01467        if (!strcasecmp(cv, "day")) {
01468               c->view = calview_day;
01469        }
01470        else if (!strcasecmp(cv, "week")) {
01471               c->view = calview_week;
01472        }
01473        else if (!strcasecmp(cv, "summary")) {    /* shouldn't ever happen, but just in case */
01474               c->view = calview_day;
01475        }
01476        else {
01477               if (WCC->CurRoom.view == VIEW_CALBRIEF) {
01478                      c->view = calview_brief;
01479               }
01480               else {
01481                      c->view = calview_month;
01482               }
01483        }
01484 
01485        /* Now try and set the lower and upper bounds so that we don't
01486         * burn too many cpu cycles parsing data way in the past or future
01487         */
01488 
01489        tm.tm_year = c->year - 1900;
01490        tm.tm_mon = c->month - 1;
01491        tm.tm_mday = c->day;
01492        now = mktime(&tm);
01493 
01494        if (c->view == calview_month)      span = 3888000;
01495        if (c->view == calview_brief)      span = 3888000;
01496        if (c->view == calview_week)       span = 604800;
01497        if (c->view == calview_day) span = 86400;
01498        if (c->view == calview_summary)    span = 86400;
01499 
01500        c->lower_bound = now - span;
01501        c->upper_bound = now + span;
01502        return 200;
01503 }
01504 
01505 
01506 
01507 /*
01508  * Render a calendar view from data previously loaded into memory
01509  */
01510 int calendar_RenderView_or_Tail(SharedMessageStatus *Stat,
01511                             void **ViewSpecific,
01512                             long oper)
01513 {
01514        wcsession *WCC = WC;
01515        calview *c = (calview*) *ViewSpecific;
01516 
01517        if (c->view == calview_day) {
01518               calendar_day_view(c->year, c->month, c->day);
01519        }
01520        else if (c->view == calview_week) {
01521               calendar_week_view(c->year, c->month, c->day);
01522        }
01523        else {
01524               if (WCC->CurRoom.view == VIEW_CALBRIEF) {
01525                      calendar_brief_month_view(c->year, c->month, c->day);
01526               }
01527               else {
01528                      calendar_month_view(c->year, c->month, c->day);
01529               }
01530        }
01531 
01532        /* Free the in-memory list of calendar items */
01533        DeleteHash(&WC->disp_cal_items);
01534        return 0;
01535 }
01536 
01537 void 
01538 InitModule_CALENDAR_VIEW
01539 (void)
01540 {
01541        WebcitAddUrlHandler(HKEY("mini_calendar"), "", 0, ajax_mini_calendar, AJAX);
01542 }