* split tasks view into its own file
authorWilfried Göesgens <willi@citadel.org>
Thu, 20 Aug 2009 20:13:41 +0000 (20:13 +0000)
committerWilfried Göesgens <willi@citadel.org>
Thu, 20 Aug 2009 20:13:41 +0000 (20:13 +0000)
* re-arange readloop() so it presents a stable API to its views

16 files changed:
webcit/Makefile.in
webcit/availability.c
webcit/calendar.c
webcit/calendar_view.c
webcit/event.c
webcit/messages.c
webcit/messages.h
webcit/msg_renderers.c
webcit/notes.c
webcit/smtpqueue.c
webcit/summary.c
webcit/tasks.c [new file with mode: 0644]
webcit/useredit.c
webcit/vcard_edit.c
webcit/webcit.h
webcit/wiki.c

index f6a90d416c4aa112f758cc49332dfcaf6173024c..4940c49aa9e28875e225f21750828f84e1c08614 100644 (file)
@@ -46,7 +46,7 @@ webcit: webserver.o context_loop.o ical_dezonify.o \
        roomops.o messages.o msg_renderers.o userlist.o paging.o sysmsgs.o \
        useredit.o vcard_edit.o preferences.o html2html.o listsub.o \
        graphics.o netconf.o siteconfig.o subst.o \
-       calendar.o calendar_tools.o calendar_view.o event.o smtpqueue.o \
+       calendar.o calendar_tools.o calendar_view.o tasks.o event.o smtpqueue.o \
        availability.o iconbar.o crypto.o inetconf.o notes.o wiki.o \
        groupdav_main.o groupdav_get.o groupdav_propfind.o fmt_date.o \
        groupdav_options.o autocompletion.o gettext.o tabs.o sieve.o \
@@ -61,7 +61,7 @@ webcit: webserver.o context_loop.o ical_dezonify.o \
        roomops.o messages.o msg_renderers.o userlist.o paging.o sysmsgs.o \
        useredit.o locate_host.o siteconfig.o subst.o vcard_edit.o floors.o \
        graphics.o netconf.o preferences.o html2html.o openid.o \
-       summary.o calendar.o calendar_tools.o calendar_view.o event.o wiki.o \
+       summary.o calendar.o calendar_tools.o calendar_view.o tasks.o event.o wiki.o \
        availability.o ical_dezonify.o iconbar.o crypto.o inetconf.o notes.o \
        groupdav_main.o groupdav_get.o groupdav_propfind.o groupdav_delete.o \
        groupdav_options.o autocompletion.o tabs.o smtpqueue.o sieve.o \
index 67b5139d3f03057b091aee5ab931452a3e944f53..8f1e399505d1b1df6ee776751a5af2246a8bc1ea 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "webcit.h"
 #include "webserver.h"
+#include "calendar.h"
 
 /*
  * Utility function to fetch a VFREEBUSY type of thing for any specified user.
index 539c530fadf832f2f4e26aef6b63ac935974cdcf..f0baec2dc70c3027a564e51cdc2a2956cf04792f 100644 (file)
@@ -6,7 +6,7 @@
 
 #include "webcit.h"
 #include "webserver.h"
-
+#include "calendar.h"
 
 /*
  * Process a calendar object.  At this point it's already been deserialized by cal_process_attachment()
@@ -396,7 +396,7 @@ void delete_cal(void *vCal)
  * any iCalendar objects and store them in a hash table.  Later on, the second phase will
  * use this hash table to render the calendar for display.
  */
-void display_individual_cal(icalcomponent *cal, long msgnum, char *from, int unread, struct calview *calv)
+void display_individual_cal(icalcomponent *cal, long msgnum, char *from, int unread, calview *calv)
 {
        icalproperty *ps = NULL;
        struct icaltimetype dtstart, dtend;
@@ -579,415 +579,6 @@ void display_individual_cal(icalcomponent *cal, long msgnum, char *from, int unr
 
 
 
-/*
- * Display a task by itself (for editing)
- */
-void display_edit_individual_task(icalcomponent *supplied_vtodo, long msgnum, char *from,
-                       int unread, struct calview *calv)
-{
-       icalcomponent *vtodo;
-       icalproperty *p;
-       struct icaltimetype IcalTime;
-       time_t now;
-       int created_new_vtodo = 0;
-       icalproperty_status todoStatus;
-
-       now = time(NULL);
-
-       if (supplied_vtodo != NULL) {
-               vtodo = supplied_vtodo;
-
-               /*
-                * It's safe to convert to UTC here because there are no recurrences to worry about.
-                */
-               ical_dezonify(vtodo);
-
-               /*
-                * If we're looking at a fully encapsulated VCALENDAR
-                * rather than a VTODO component, attempt to use the first
-                * relevant VTODO subcomponent.  If there is none, the
-                * NULL returned by icalcomponent_get_first_component() will
-                * tell the next iteration of this function to create a
-                * new one.
-                */
-               if (icalcomponent_isa(vtodo) == ICAL_VCALENDAR_COMPONENT) {
-                       display_edit_individual_task(
-                               icalcomponent_get_first_component(
-                                       vtodo, ICAL_VTODO_COMPONENT
-                                       ), 
-                               msgnum, from, unread, calv
-                               );
-                       return;
-               }
-       }
-       else {
-               vtodo = icalcomponent_new(ICAL_VTODO_COMPONENT);
-               created_new_vtodo = 1;
-       }
-       
-       /* TODO: Can we take all this and move it into a template?       */
-       output_headers(1, 1, 1, 0, 0, 0);
-       wprintf("<!-- start task edit form -->");
-       p = icalcomponent_get_first_property(vtodo, ICAL_SUMMARY_PROPERTY);
-       /* Get summary early for title */
-       wprintf("<div class=\"box\">\n");
-       wprintf("<div class=\"boxlabel\">");
-       wprintf(_("Edit task"));
-       wprintf("- ");
-       if (p != NULL) {
-               escputs((char *)icalproperty_get_comment(p));
-       }
-       wprintf("</div>");
-       
-       wprintf("<div class=\"boxcontent\">\n");
-       wprintf("<FORM METHOD=\"POST\" action=\"save_task\">\n");
-       wprintf("<div style=\"display: none;\">\n       ");
-       wprintf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
-       wprintf("<INPUT TYPE=\"hidden\" NAME=\"msgnum\" VALUE=\"%ld\">\n", msgnum);
-       wprintf("<INPUT TYPE=\"hidden\" NAME=\"return_to_summary\" VALUE=\"%d\">\n",
-               ibstr("return_to_summary"));
-       wprintf("</div>");
-       wprintf("<table class=\"calendar_background\"><tr><td>");
-       wprintf("<TABLE STYLE=\"border: none;\">\n");
-
-       wprintf("<TR><TD>");
-       wprintf(_("Summary:"));
-       wprintf("</TD><TD>"
-               "<INPUT TYPE=\"text\" NAME=\"summary\" "
-               "MAXLENGTH=\"64\" SIZE=\"64\" VALUE=\"");
-       p = icalcomponent_get_first_property(vtodo, ICAL_SUMMARY_PROPERTY);
-       if (p != NULL) {
-               escputs((char *)icalproperty_get_comment(p));
-       }
-       wprintf("\"></TD></TR>\n");
-
-       wprintf("<TR><TD>");
-       wprintf(_("Start date:"));
-       wprintf("</TD><TD>");
-       p = icalcomponent_get_first_property(vtodo, ICAL_DTSTART_PROPERTY);
-       wprintf("<INPUT TYPE=\"CHECKBOX\" NAME=\"nodtstart\" ID=\"nodtstart\" VALUE=\"NODTSTART\" ");
-       if (p == NULL) {
-               wprintf("CHECKED=\"CHECKED\"");
-       }
-       wprintf(">");
-       wprintf(_("No date"));
-       
-       wprintf(" ");
-       wprintf("<span ID=\"dtstart_date\">");
-       wprintf(_("or"));
-       wprintf(" ");
-       if (p != NULL) {
-               IcalTime = icalproperty_get_dtstart(p);
-       }
-       else
-               IcalTime = icaltime_current_time_with_zone(get_default_icaltimezone());
-       display_icaltimetype_as_webform(&IcalTime, "dtstart", 0);
-
-       wprintf("<INPUT TYPE=\"CHECKBOX\" NAME=\"dtstart_time_assoc\" ID=\"dtstart_time_assoc\" VALUE=\"yes\"");
-       if (!IcalTime.is_date) {
-               wprintf("CHECKED=\"CHECKED\"");
-       }
-       wprintf(">");
-       wprintf(_("Time associated"));
-       wprintf("</span></TD></TR>\n");
-
-       wprintf("<TR><TD>");
-       wprintf(_("Due date:"));
-       wprintf("</TD><TD>");
-       p = icalcomponent_get_first_property(vtodo, ICAL_DUE_PROPERTY);
-       wprintf("<INPUT TYPE=\"CHECKBOX\" NAME=\"nodue\" ID=\"nodue\" VALUE=\"NODUE\"");
-       if (p == NULL) {
-               wprintf("CHECKED=\"CHECKED\"");
-       }
-       wprintf(">");
-       wprintf(_("No date"));
-       wprintf(" ");
-       wprintf("<span ID=\"due_date\">\n");
-       wprintf(_("or"));
-       wprintf(" ");
-       if (p != NULL) {
-               IcalTime = icalproperty_get_due(p);
-       }
-       else
-               IcalTime = icaltime_current_time_with_zone(get_default_icaltimezone());
-       display_icaltimetype_as_webform(&IcalTime, "due", 0);
-
-       wprintf("<INPUT TYPE=\"CHECKBOX\" NAME=\"due_time_assoc\" ID=\"due_time_assoc\" VALUE=\"yes\"");
-       if (!IcalTime.is_date) {
-               wprintf("CHECKED=\"CHECKED\"");
-       }
-       wprintf(">");
-       wprintf(_("Time associated"));
-       wprintf("</span></TD></TR>\n");
-       todoStatus = icalcomponent_get_status(vtodo);
-       wprintf("<TR><TD>\n");
-       wprintf(_("Completed:"));
-       wprintf("</TD><TD>");
-       wprintf("<INPUT TYPE=\"CHECKBOX\" NAME=\"status\" VALUE=\"COMPLETED\"");
-       if (todoStatus == ICAL_STATUS_COMPLETED) {
-               wprintf(" CHECKED=\"CHECKED\"");
-       } 
-       wprintf(" >");
-       wprintf("</TD></TR>");
-       /* start category field */
-       p = icalcomponent_get_first_property(vtodo, ICAL_CATEGORIES_PROPERTY);
-       wprintf("<TR><TD>");
-       wprintf(_("Category:"));
-       wprintf("</TD><TD>");
-       wprintf("<INPUT TYPE=\"text\" NAME=\"category\" MAXLENGTH=\"32\" SIZE=\"32\" VALUE=\"");
-       if (p != NULL) {
-               escputs((char *)icalproperty_get_categories(p));
-       }
-       wprintf("\">");
-       wprintf("</TD></TR>\n   ");
-       /* end category field */
-       wprintf("<TR><TD>");
-       wprintf(_("Description:"));
-       wprintf("</TD><TD>");
-       wprintf("<TEXTAREA NAME=\"description\" "
-               "ROWS=\"10\" COLS=\"80\">\n"
-               );
-       p = icalcomponent_get_first_property(vtodo, ICAL_DESCRIPTION_PROPERTY);
-       if (p != NULL) {
-               escputs((char *)icalproperty_get_comment(p));
-       }
-       wprintf("</TEXTAREA></TD></TR></TABLE>\n");
-
-       wprintf("<SPAN STYLE=\"text-align: center;\">"
-               "<INPUT TYPE=\"submit\" NAME=\"save_button\" VALUE=\"%s\">"
-               "&nbsp;&nbsp;"
-               "<INPUT TYPE=\"submit\" NAME=\"delete_button\" VALUE=\"%s\">\n"
-               "&nbsp;&nbsp;"
-               "<INPUT TYPE=\"submit\" NAME=\"cancel_button\" VALUE=\"%s\">\n"
-               "</SPAN>\n",
-               _("Save"),
-               _("Delete"),
-               _("Cancel")
-               );
-       wprintf("</td></tr></table>");
-       wprintf("</FORM>\n");
-       wprintf("</div></div></div>\n");
-       wprintf("<!-- end task edit form -->");
-       wDumpContent(1);
-
-       if (created_new_vtodo) {
-               icalcomponent_free(vtodo);
-       }
-}
-
-/*
- * Save an edited task
- *
- * supplied_vtodo      the task to save
- * msgnum              number of the mesage in our db
- */
-void save_individual_task(icalcomponent *supplied_vtodo, long msgnum, char* from, int unread,
-                               struct calview *calv)
-{
-       char buf[SIZ];
-       int delete_existing = 0;
-       icalproperty *prop;
-       icalcomponent *vtodo, *encaps;
-       int created_new_vtodo = 0;
-       int i;
-       int sequence = 0;
-       struct icaltimetype t;
-
-       if (supplied_vtodo != NULL) {
-               vtodo = supplied_vtodo;
-               /**
-                * If we're looking at a fully encapsulated VCALENDAR
-                * rather than a VTODO component, attempt to use the first
-                * relevant VTODO subcomponent.  If there is none, the
-                * NULL returned by icalcomponent_get_first_component() will
-                * tell the next iteration of this function to create a
-                * new one.
-                */
-               if (icalcomponent_isa(vtodo) == ICAL_VCALENDAR_COMPONENT) {
-                       save_individual_task(
-                               icalcomponent_get_first_component(
-                                       vtodo, ICAL_VTODO_COMPONENT), 
-                               msgnum, from, unread, calv
-                               );
-                       return;
-               }
-       }
-       else {
-               vtodo = icalcomponent_new(ICAL_VTODO_COMPONENT);
-               created_new_vtodo = 1;
-       }
-
-       if (havebstr("save_button")) {
-
-               /** Replace values in the component with ones from the form */
-
-               while (prop = icalcomponent_get_first_property(vtodo,
-                                                              ICAL_SUMMARY_PROPERTY), prop != NULL) {
-                       icalcomponent_remove_property(vtodo, prop);
-                       icalproperty_free(prop);
-               }
-               if (havebstr("summary")) {
-
-                       icalcomponent_add_property(vtodo,
-                                                  icalproperty_new_summary(bstr("summary")));
-               } else {
-                       icalcomponent_add_property(vtodo,
-                                                  icalproperty_new_summary(_("Untitled Task")));
-               }
-       
-               while (prop = icalcomponent_get_first_property(vtodo,
-                                                              ICAL_DESCRIPTION_PROPERTY), prop != NULL) {
-                       icalcomponent_remove_property(vtodo, prop);
-                       icalproperty_free(prop);
-               }
-               if (havebstr("description")) {
-                       icalcomponent_add_property(vtodo,
-                                                  icalproperty_new_description(bstr("description")));
-               }
-       
-               while (prop = icalcomponent_get_first_property(vtodo,
-                                                              ICAL_DTSTART_PROPERTY), prop != NULL) {
-                       icalcomponent_remove_property(vtodo, prop);
-                       icalproperty_free(prop);
-               }
-               if (IsEmptyStr(bstr("nodtstart"))) {
-                       if (yesbstr("dtstart_time")) {
-                               icaltime_from_webform(&t, "dtstart");
-                       }
-                       else {
-                               icaltime_from_webform_dateonly(&t, "dtstart");
-                       }
-                       icalcomponent_add_property(vtodo,
-                                                  icalproperty_new_dtstart(t)
-                               );
-               }
-               while(prop = icalcomponent_get_first_property(vtodo,
-                                                             ICAL_STATUS_PROPERTY), prop != NULL) {
-                       icalcomponent_remove_property(vtodo,prop);
-                       icalproperty_free(prop);
-               }
-               while(prop = icalcomponent_get_first_property(vtodo,
-                                                             ICAL_PERCENTCOMPLETE_PROPERTY), prop != NULL) {
-                       icalcomponent_remove_property(vtodo,prop);
-                       icalproperty_free(prop);
-               }
-
-               if (havebstr("status")) {
-                       icalproperty_status taskStatus = icalproperty_string_to_status(bstr("status"));
-                       icalcomponent_set_status(vtodo, taskStatus);
-                       icalcomponent_add_property(vtodo,
-                               icalproperty_new_percentcomplete(
-                                       (strcasecmp(bstr("status"), "completed") ? 0 : 100)
-                               )
-                       );
-               }
-               else {
-                       icalcomponent_add_property(vtodo, icalproperty_new_percentcomplete(0));
-               }
-               while (prop = icalcomponent_get_first_property(vtodo,
-                                                              ICAL_CATEGORIES_PROPERTY), prop != NULL) {
-                       icalcomponent_remove_property(vtodo,prop);
-                       icalproperty_free(prop);
-               }
-               if (!IsEmptyStr(bstr("category"))) {
-                       prop = icalproperty_new_categories(bstr("category"));
-                       icalcomponent_add_property(vtodo,prop);
-               }
-               while (prop = icalcomponent_get_first_property(vtodo,
-                                                              ICAL_DUE_PROPERTY), prop != NULL) {
-                       icalcomponent_remove_property(vtodo, prop);
-                       icalproperty_free(prop);
-               }
-               if (IsEmptyStr(bstr("nodue"))) {
-                       if (yesbstr("due_time")) {
-                               icaltime_from_webform(&t, "due");
-                       }
-                       else {
-                               icaltime_from_webform_dateonly(&t, "due");
-                       }
-                       icalcomponent_add_property(vtodo,
-                                                  icalproperty_new_due(t)
-                               );
-               }
-               /** Give this task a UID if it doesn't have one. */
-               lprintf(9, "Give this task a UID if it doesn't have one.\n");
-               if (icalcomponent_get_first_property(vtodo,
-                                                    ICAL_UID_PROPERTY) == NULL) {
-                       generate_uuid(buf);
-                       icalcomponent_add_property(vtodo,
-                                                  icalproperty_new_uid(buf)
-                               );
-               }
-
-               /* Increment the sequence ID */
-               lprintf(9, "Increment the sequence ID\n");
-               while (prop = icalcomponent_get_first_property(vtodo,
-                                                              ICAL_SEQUENCE_PROPERTY), (prop != NULL) ) {
-                       i = icalproperty_get_sequence(prop);
-                       lprintf(9, "Sequence was %d\n", i);
-                       if (i > sequence) sequence = i;
-                       icalcomponent_remove_property(vtodo, prop);
-                       icalproperty_free(prop);
-               }
-               ++sequence;
-               lprintf(9, "New sequence is %d.  Adding...\n", sequence);
-               icalcomponent_add_property(vtodo,
-                                          icalproperty_new_sequence(sequence)
-                       );
-
-               /*
-                * Encapsulate event into full VCALENDAR component.  Clone it first,
-                * for two reasons: one, it's easier to just free the whole thing
-                * when we're done instead of unbundling, but more importantly, we
-                * can't encapsulate something that may already be encapsulated
-                * somewhere else.
-                */
-               lprintf(9, "Encapsulating into a full VCALENDAR component\n");
-               encaps = ical_encapsulate_subcomponent(icalcomponent_new_clone(vtodo));
-
-               /* Serialize it and save it to the message base */
-               serv_puts("ENT0 1|||4");
-               serv_getln(buf, sizeof buf);
-               if (buf[0] == '4') {
-                       serv_puts("Content-type: text/calendar");
-                       serv_puts("");
-                       serv_puts(icalcomponent_as_ical_string(encaps));
-                       serv_puts("000");
-
-                       /*
-                        * Probably not necessary; the server will see the UID
-                        * of the object and delete the old one anyway, but
-                        * just in case...
-                        */
-                       delete_existing = 1;
-               }
-               icalcomponent_free(encaps);
-       }
-
-       /**
-        * If the user clicked 'Delete' then explicitly delete the message.
-        */
-       if (havebstr("delete_button")) {
-               delete_existing = 1;
-       }
-
-       if ( (delete_existing) && (msgnum > 0L) ) {
-               serv_printf("DELE %ld", lbstr("msgnum"));
-               serv_getln(buf, sizeof buf);
-       }
-
-       if (created_new_vtodo) {
-               icalcomponent_free(vtodo);
-       }
-
-       /* Go back to wherever we came from */
-       if (ibstr("return_to_summary") == 1) {
-               summary();
-       }
-       else {
-               readloop(readfwd);
-       }
-}
 
 
 
@@ -996,7 +587,7 @@ void process_ical_object(long msgnum, int unread,
                         char *FlatIcal, 
                         icalcomponent_kind which_kind,
                         IcalCallbackFunc CallBack,
-                        struct calview *calv
+                        calview *calv
        ) 
 {
        icalcomponent *cal, *c;
@@ -1039,7 +630,7 @@ void process_ical_object(long msgnum, int unread,
 void load_ical_object(long msgnum, int unread,
                      icalcomponent_kind which_kind,
                      IcalCallbackFunc CallBack,
-                     struct calview *calv,
+                     calview *calv,
                      int RenderAsync
        ) 
 {
@@ -1169,55 +760,15 @@ void load_ical_object(long msgnum, int unread,
 /*
  * Display a calendar item
  */
-void load_calendar_item(message_summary *Msg, int unread, struct calview *c) {
-       load_ical_object(Msg->msgnum, unread, (-1), display_individual_cal, c, 1);
-}
-
-/*
- * Display task view
- */
-void display_task(message_summary *Msg, int unread) {
-       load_ical_object(Msg->msgnum, unread, ICAL_VTODO_COMPONENT, display_individual_cal, NULL, 0);
-}
-
-/*
- * Display the editor component for a task
- */
-void display_edit_task(void) {
-       long msgnum = 0L;
-                       
-       /* Force change the room if we have to */
-       if (havebstr("taskrm")) {
-               gotoroom(sbstr("taskrm"));
-       }
-
-       msgnum = lbstr("msgnum");
-       if (msgnum > 0L) {
-               /* existing task */
-               load_ical_object(msgnum, 0,
-                                ICAL_VTODO_COMPONENT,
-                                display_edit_individual_task,
-                                NULL, 0
-               );
-       }
-       else {
-               /* new task */
-               display_edit_individual_task(NULL, 0L, "", 0, NULL);
-       }
-}
-
-/*
- * save an edited task
- */
-void save_task(void) {
-       long msgnum = 0L;
-       msgnum = lbstr("msgnum");
-       if (msgnum > 0L) {
-               load_ical_object(msgnum, 0, ICAL_VTODO_COMPONENT, save_individual_task, NULL, 0);
-       }
-       else {
-               save_individual_task(NULL, 0L, "", 0, NULL);
-       }
+int calendar_LoadMsgFromServer(SharedMessageStatus *Stat, 
+                              void **ViewSpecific, 
+                              message_summary* Msg, 
+                              int is_new, 
+                              int i)
+{
+       calview *c = (calview*) *ViewSpecific;
+       load_ical_object(Msg->msgnum, is_new, (-1), display_individual_cal, c, 1);
+       return 0;
 }
 
 /*
@@ -1300,18 +851,48 @@ void do_freebusy(void)
 
 
 
+int calendar_Cleanup(void **ViewSpecific)
+{
+       calview *c;
+       
+       c = (calview *) *ViewSpecific;
+
+       wDumpContent(1);
+       free (c);
+       *ViewSpecific = NULL;
+
+       return 0;
+}
+
 
 void 
 InitModule_CALENDAR
 (void)
 {
+       RegisterReadLoopHandlerset(
+               VIEW_CALENDAR,
+               calendar_GetParamsGetServerCall,
+               NULL,
+               calendar_LoadMsgFromServer,
+               calendar_RenderView_or_Tail,
+               calendar_Cleanup);
+
+       RegisterReadLoopHandlerset(
+               VIEW_CALBRIEF,
+               calendar_GetParamsGetServerCall,
+               NULL,
+               calendar_LoadMsgFromServer,
+               calendar_RenderView_or_Tail,
+               calendar_Cleanup);
+
+
+
        RegisterPreference("daystart", _("Calendar day view begins at:"), PRF_INT, NULL);
        RegisterPreference("dayend", _("Calendar day view ends at:"), PRF_INT, NULL);
        RegisterPreference("weekstart", _("Week starts on:"), PRF_INT, NULL);
 
        WebcitAddUrlHandler(HKEY("freebusy"), do_freebusy, COOKIEUNNEEDED|ANONYMOUS|FORCE_SESSIONCLOSE);
        WebcitAddUrlHandler(HKEY("display_edit_task"), display_edit_task, 0);
-       WebcitAddUrlHandler(HKEY("save_task"), save_task, 0);
        WebcitAddUrlHandler(HKEY("display_edit_event"), display_edit_event, 0);
        WebcitAddUrlHandler(HKEY("save_event"), save_event, 0);
        WebcitAddUrlHandler(HKEY("respond_to_request"), respond_to_request, 0);
index 6d71049a9b406e8120eb57017ad6220daa9a5a24..48ac994666d7fa64fe4b77293b809b101fd4d569 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "webcit.h"
 #include "webserver.h"
+#include "calendar.h"
 
 /* These define how high the hour rows are in the day view */
 #define TIMELINE       30
@@ -1425,12 +1426,27 @@ int calendar_summary_view(void) {
 /*
  * Parse the URL variables in order to determine the scope and display of a calendar view
  */
-void parse_calendar_view_request(struct calview *c) {
+int calendar_GetParamsGetServerCall(SharedMessageStatus *Stat, 
+                                   void **ViewSpecific, 
+                                   long oper, 
+                                   char *cmd, 
+                                   long len)
+{
+       calview *c;
        time_t now;
        struct tm tm;
-       char calview[32];
+       char cv[32];
+
        int span = 3888000;
 
+       c = (calview*) malloc(sizeof(calview));
+       memset(c, 0, sizeof(calview));
+       *ViewSpecific = (void*)c;
+
+       Stat->load_seen = 1;
+       strcpy(cmd, "MSGS ALL");
+       Stat->maxmsgs = 32767;
+       
        /* In case no date was specified, go with today */
        now = time(NULL);
        localtime_r(&now, &tm);
@@ -1445,20 +1461,20 @@ void parse_calendar_view_request(struct calview *c) {
 
        /* How would you like that cooked? */
        if (havebstr("calview")) {
-               strcpy(calview, bstr("calview"));
+               strcpy(cv, bstr("calview"));
        }
        else {
-               strcpy(calview, "month");
+               strcpy(cv, "month");
        }
 
        /* Display the selected view */
-       if (!strcasecmp(calview, "day")) {
+       if (!strcasecmp(cv, "day")) {
                c->view = calview_day;
        }
-       else if (!strcasecmp(calview, "week")) {
+       else if (!strcasecmp(cv, "week")) {
                c->view = calview_week;
        }
-       else if (!strcasecmp(calview, "summary")) {     /* shouldn't ever happen, but just in case */
+       else if (!strcasecmp(cv, "summary")) {  /* shouldn't ever happen, but just in case */
                c->view = calview_day;
        }
        else {
@@ -1487,6 +1503,7 @@ void parse_calendar_view_request(struct calview *c) {
 
        c->lower_bound = now - span;
        c->upper_bound = now + span;
+       return 200;
 }
 
 
@@ -1494,8 +1511,12 @@ void parse_calendar_view_request(struct calview *c) {
 /*
  * Render a calendar view from data previously loaded into memory
  */
-void render_calendar_view(struct calview *c)
+int calendar_RenderView_or_Tail(SharedMessageStatus *Stat, 
+                               void **ViewSpecific, 
+                               long oper)
 {
+       calview *c = (calview*) *ViewSpecific;
+
        if (c->view == calview_day) {
                calendar_day_view(c->year, c->month, c->day);
        }
@@ -1513,173 +1534,10 @@ void render_calendar_view(struct calview *c)
 
        /* Free the in-memory list of calendar items */
        DeleteHash(&WC->disp_cal_items);
-}
-
-
-/*
- * Helper function for do_tasks_view().  Returns the due date/time of a vtodo.
- */
-time_t get_task_due_date(icalcomponent *vtodo, int *is_date) {
-       icalproperty *p;
-
-       if (vtodo == NULL) {
-               return(0L);
-       }
-
-       /*
-        * If we're looking at a fully encapsulated VCALENDAR
-        * rather than a VTODO component, recurse into the data
-        * structure until we get a VTODO.
-        */
-       if (icalcomponent_isa(vtodo) == ICAL_VCALENDAR_COMPONENT) {
-               return get_task_due_date(
-                       icalcomponent_get_first_component(
-                               vtodo, ICAL_VTODO_COMPONENT
-                               ), is_date
-                       );
-       }
-
-       p = icalcomponent_get_first_property(vtodo, ICAL_DUE_PROPERTY);
-       if (p != NULL) {
-               struct icaltimetype t = icalproperty_get_due(p);
-
-               if (is_date)
-                       *is_date = t.is_date;
-               return(icaltime_as_timet(t));
-       }
-       else {
-               return(0L);
-       }
-}
-
-
-/*
- * Compare the due dates of two tasks (this is for sorting)
- */
-int task_due_cmp(const void *vtask1, const void *vtask2) {
-       disp_cal * Task1 = (disp_cal *)GetSearchPayload(vtask1);
-       disp_cal * Task2 = (disp_cal *)GetSearchPayload(vtask2);
-
-       time_t t1;
-       time_t t2;
-
-       t1 =  get_task_due_date(Task1->cal, NULL);
-       t2 =  get_task_due_date(Task2->cal, NULL);
-       if (t1 < t2) return(-1);
-       if (t1 > t2) return(1);
-       return(0);
-}
-
-/*
- * qsort filter to move completed tasks to bottom of task list
- */
-int task_completed_cmp(const void *vtask1, const void *vtask2) {
-       disp_cal * Task1 = (disp_cal *)GetSearchPayload(vtask1);
-/*     disp_cal * Task2 = (disp_cal *)GetSearchPayload(vtask2); */
-
-       icalproperty_status t1 = icalcomponent_get_status((Task1)->cal);
-       /* icalproperty_status t2 = icalcomponent_get_status(((struct disp_cal *)task2)->cal); */
-       
-       if (t1 == ICAL_STATUS_COMPLETED) 
-               return 1;
        return 0;
 }
 
 
 
-/*
- * do the whole task view stuff
- */
-void do_tasks_view(void) {
-       long hklen;
-       const char *HashKey;
-       void *vCal;
-       disp_cal *Cal;
-       HashPos *Pos;
-       int nItems;
-       time_t due;
-       char buf[SIZ];
-       icalproperty *p;
-       wcsession *WCC = WC;
-
-       wprintf("<div class=\"fix_scrollbar_bug\">"
-               "<table class=\"calendar_view_background\"><tbody id=\"taskview\">\n<tr>\n"
-               "<th>");
-       wprintf(_("Completed?"));
-       wprintf("</th><th>");
-       wprintf(_("Name of task"));
-       wprintf("</th><th>");
-       wprintf(_("Date due"));
-       wprintf("</th><th>");
-       wprintf(_("Category"));
-       wprintf(" (<select id=\"selectcategory\"><option value=\"showall\">%s</option></select>)</th></tr>\n",
-               _("Show All"));
-
-       nItems = GetCount(WC->disp_cal_items);
-
-       /* Sort them if necessary
-       if (nItems > 1) {
-               SortByPayload(WC->disp_cal_items, task_due_cmp);
-       }
-       * this shouldn't be neccessary, since we sort by the start time.
-       */
-
-       /* And then again, by completed */
-       if (nItems > 1) {
-               SortByPayload(WC->disp_cal_items, 
-                             task_completed_cmp);
-       }
-
-       Pos = GetNewHashPos(WCC->disp_cal_items, 0);
-       while (GetNextHashPos(WCC->disp_cal_items, Pos, &hklen, &HashKey, &vCal)) {
-               icalproperty_status todoStatus;
-               int is_date;
 
-               Cal = (disp_cal*)vCal;
-               wprintf("<tr><td>");
-               todoStatus = icalcomponent_get_status(Cal->cal);
-               wprintf("<input type=\"checkbox\" name=\"completed\" value=\"completed\" ");
-               if (todoStatus == ICAL_STATUS_COMPLETED) {
-                       wprintf("checked=\"checked\" ");
-               }
-               wprintf("disabled=\"disabled\">\n</td><td>");
-               p = icalcomponent_get_first_property(Cal->cal,
-                       ICAL_SUMMARY_PROPERTY);
-               wprintf("<a href=\"display_edit_task?msgnum=%ld?taskrm=", Cal->cal_msgnum);
-               urlescputs(ChrPtr(WC->wc_roomname));
-               wprintf("\">");
-               /* wprintf("<img align=middle "
-               "src=\"static/taskmanag_16x.gif\" border=0>&nbsp;"); */
-               if (p != NULL) {
-                       escputs((char *)icalproperty_get_comment(p));
-               }
-               wprintf("</a>\n");
-               wprintf("</td>\n");
-
-               due = get_task_due_date(Cal->cal, &is_date);
-               wprintf("<td><span");
-               if (due > 0) {
-                       webcit_fmt_date(buf, SIZ, due, is_date ? DATEFMT_RAWDATE : DATEFMT_FULL);
-                       wprintf(">%s",buf);
-               }
-               else {
-                       wprintf(">");
-               }
-               wprintf("</span></td>");
-               wprintf("<td>");
-               p = icalcomponent_get_first_property(Cal->cal,
-                       ICAL_CATEGORIES_PROPERTY);
-               if (p != NULL) {
-                       escputs((char *)icalproperty_get_categories(p));
-               }
-               wprintf("</td>");
-               wprintf("</tr>");
-       }
-
-       wprintf("</tbody></table></div>\n");
-
-       /* Free the list */
-       DeleteHash(&WC->disp_cal_items);
-       DeleteHashPos(&Pos);
-}
 
index 1200917651a162cba4c4ad9b2c93e2d827c739b9..d1c7bbc6be69b444398b3f5d1120dccf0cf3c9c8 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "webcit.h"
 #include "webserver.h"
+#include "calendar.h"
 
 /*
  * Display an event by itself (for editing)
@@ -13,7 +14,7 @@
  * msgnum              reference on the citserver
  */
 void display_edit_individual_event(icalcomponent *supplied_vevent, long msgnum, char *from,
-       int unread, struct calview *calv)
+       int unread, calview *calv)
 {
        icalcomponent *vevent;
        icalproperty *p;
@@ -765,7 +766,7 @@ void display_edit_individual_event(icalcomponent *supplied_vevent, long msgnum,
  * msgnum:             the index on the citserver
  */
 void save_individual_event(icalcomponent *supplied_vevent, long msgnum, char *from,
-                       int unread, struct calview *calv) {
+                       int unread, calview *calv) {
        char buf[SIZ];
        icalproperty *prop;
        icalcomponent *vevent, *encaps;
index 73fb0f37ccef7852ef1ca0f9d1fb53a462ca9bb2..3c543934546edd44b71707e8251c07aca667c816 100644 (file)
@@ -12,6 +12,7 @@
 HashList *MsgHeaderHandler = NULL;
 HashList *MsgEvaluators = NULL;
 HashList *MimeRenderHandler = NULL;
+HashList *ReadLoopHandler = NULL;
 int dbg_analyze_msg = 0;
 
 #define SUBJ_COL_WIDTH_PCT             50      /* Mailbox view column width */
@@ -569,41 +570,37 @@ message_summary *ReadOneMessageSummary(StrBuf *RawMessage, const char *DefaultSu
  * load message pointers from the server for a "read messages" operation
  *
  * servcmd:            the citadel command to send to the citserver
- * with_headers:       also include some of the headers with the message numbers (more expensive)
  */
-int load_msg_ptrs(const char *servcmd, int with_headers, long *lowest_found, long *highest_found)
+int load_msg_ptrs(const char *servcmd, SharedMessageStatus *Stat)
 {
        StrBuf* FoundCharset = NULL;
         wcsession *WCC = WC;
        message_summary *Msg;
        StrBuf *Buf, *Buf2;
-       int nummsgs = 0;
-       int maxload = 0;
        long len;
        int n;
        int skipit;
        const char *Ptr = NULL;
 
-       if (lowest_found) *lowest_found = LONG_MAX;
-       if (highest_found) *highest_found = LONG_MIN;
+       Stat->lowest_found = LONG_MAX;
+       Stat->highest_found = LONG_MIN;
 
        if (WCC->summ != NULL) {
                DeleteHash(&WCC->summ);
        }
        WCC->summ = NewHash(1, Flathash);
-       maxload = 10000;
        
        Buf = NewStrBuf();
        serv_puts(servcmd);
        StrBuf_ServGetln(Buf);
        if (GetServerStatus(Buf, NULL) != 1) {
                FreeStrBuf(&Buf);
-               return (nummsgs);
+               return (Stat->nummsgs);
        }
        Buf2 = NewStrBuf();
        while (len = StrBuf_ServGetln(Buf), ((len != 3) || strcmp(ChrPtr(Buf), "000")!= 0))
        {
-               if (nummsgs < maxload) {
+               if (Stat->nummsgs < Stat->maxload) {
                        skipit = 0;
                        Ptr = NULL;
                        Msg = (message_summary*)malloc(sizeof(message_summary));
@@ -612,12 +609,12 @@ int load_msg_ptrs(const char *servcmd, int with_headers, long *lowest_found, lon
                        Msg->msgnum = StrBufExtractNext_long(Buf, &Ptr, '|');
                        Msg->date = StrBufExtractNext_long(Buf, &Ptr, '|');
 
-                       if (nummsgs == 0) {
-                               if ((lowest_found) && (Msg->msgnum < *lowest_found)) {
-                                       *lowest_found = Msg->msgnum;
+                       if (Stat->nummsgs == 0) {
+                               if (Msg->msgnum < Stat->lowest_found) {
+                                       Stat->lowest_found = Msg->msgnum;
                                }
-                               if ((highest_found) && (Msg->msgnum > *highest_found)) {
-                                       *highest_found = Msg->msgnum;
+                               if (Msg->msgnum > Stat->highest_found) {
+                                       Stat->highest_found = Msg->msgnum;
                                }
                        }
 
@@ -631,7 +628,7 @@ int load_msg_ptrs(const char *servcmd, int with_headers, long *lowest_found, lon
                         * nummsgs should be the same order as the message date.
                         */
                        if (Msg->date == 0) {
-                               Msg->date = nummsgs;
+                               Msg->date = Stat->nummsgs;
                                if (StrLength(Buf) < 32) 
                                        skipit = 1;
                        }
@@ -680,11 +677,11 @@ int load_msg_ptrs(const char *servcmd, int with_headers, long *lowest_found, lon
                        n = Msg->msgnum;
                        Put(WCC->summ, (const char *)&n, sizeof(n), Msg, DestroyMessageSummary);
                }
-               nummsgs++;
+               Stat->nummsgs++;
        }
        FreeStrBuf(&Buf2);
        FreeStrBuf(&Buf);
-       return (nummsgs);
+       return (Stat->nummsgs);
 }
 
 
@@ -701,97 +698,6 @@ inline message_summary* GetMessagePtrAt(int n, HashList *Summ)
 }
 
 
-/* startmsg is an index within the message list.
- * starting_from is the Citadel message number to be supplied to a "MSGS GT" operation
- */
-long DrawMessageDropdown(StrBuf *Selector, long maxmsgs, long startmsg, int nMessages, long starting_from)
-{
-       StrBuf *TmpBuf;
-       wcsession *WCC = WC;
-       void *vMsg;
-       int lo, hi;
-       long ret;
-       long hklen;
-       const char *key;
-       int done = 0;
-       int nItems;
-       HashPos *At;
-       long vector[16];
-       WCTemplputParams SubTP;
-
-       memset(&SubTP, 0, sizeof(WCTemplputParams));
-       SubTP.Filter.ContextType = CTX_LONGVECTOR;
-       SubTP.Context = &vector;
-       TmpBuf = NewStrBufPlain(NULL, SIZ);
-       At = GetNewHashPos(WCC->summ, nMessages);
-       nItems = GetCount(WCC->summ);
-       ret = nMessages;
-       vector[0] = 7;
-       vector[2] = 1;
-       vector[1] = startmsg;
-       vector[3] = 0;
-       vector[7] = starting_from;
-
-       while (!done) {
-               vector[3] = abs(nMessages);
-               lo = GetHashPosCounter(At);
-               if (nMessages > 0) {
-                       if (lo + nMessages >= nItems) {
-                               hi = nItems - 1;
-                               vector[3] = nItems - lo;
-                               if (startmsg == lo) 
-                                       ret = vector[3];
-                       }
-                       else {
-                               hi = lo + nMessages - 1;
-                       }
-               } else {
-                       if (lo + nMessages < -1) {
-                               hi = 0;
-                       }
-                       else {
-                               if ((lo % abs(nMessages)) != 0) {
-                                       int offset = (lo % abs(nMessages) *
-                                                     (nMessages / abs(nMessages)));
-                                       hi = lo + offset;
-                                       vector[3] = abs(offset);
-                                       if (startmsg == lo)
-                                                ret = offset;
-                               }
-                               else
-                                       hi = lo + nMessages;
-                       }
-               }
-               done = !GetNextHashPos(WCC->summ, At, &hklen, &key, &vMsg);
-               
-               /*
-                * Bump these because although we're thinking in zero base, the user
-                * is a drooling idiot and is thinking in one base.
-                */
-               vector[4] = lo + 1;
-               vector[5] = hi + 1;
-               vector[6] = lo;
-               FlushStrBuf(TmpBuf);
-               dbg_print_longvector(vector);
-               DoTemplate(HKEY("select_messageindex"), TmpBuf, &SubTP);
-               StrBufAppendBuf(Selector, TmpBuf, 0);
-       }
-       vector[6] = 0;
-       FlushStrBuf(TmpBuf);
-       if (maxmsgs == 9999999) {
-               vector[1] = 1;
-               ret = maxmsgs;
-       }
-       else
-               vector[1] = 0;          
-       vector[2] = 0;
-       dbg_print_longvector(vector);
-       DoTemplate(HKEY("select_messageindex_all"), TmpBuf, &SubTP);
-       StrBufAppendBuf(Selector, TmpBuf, 0);
-       FreeStrBuf(&TmpBuf);
-       DeleteHashPos(&At);
-       return ret;
-}
 
 void load_seen_flags(void)
 {
@@ -830,6 +736,17 @@ void load_seen_flags(void)
 
 extern readloop_struct rlid[];
 
+typedef struct _RoomRenderer{
+       int RoomType;
+
+       GetParamsGetServerCall_func GetParamsGetServerCall;
+       PrintViewHeader_func PrintViewHeader;
+       LoadMsgFromServer_func LoadMsgFromServer;
+       RenderView_or_Tail_func RenderView_or_Tail;
+       View_Cleanup_func ViewCleanup;
+} RoomRenderer;
+
+
 /*
  * command loop for reading messages
  *
@@ -837,328 +754,124 @@ extern readloop_struct rlid[];
  */
 void readloop(long oper)
 {
-       StrBuf *MessageDropdown = NULL;
-       StrBuf *BBViewToolBar = NULL;
+       RoomRenderer *ViewMsg;
+       void *vViewMsg;
        void *vMsg;
        message_summary *Msg;
        char cmd[256] = "";
-       char buf[SIZ];
-       int a = 0;
-       int with_headers = 0;
-       int nummsgs;
-       long startmsg = 0;
-       int maxmsgs = 0;
-       long *displayed_msgs = NULL;
-       int num_displayed = 0;
-       int is_singlecard = 0;
-       struct calview calv;
        int i;
-       int lowest_displayed = (-1);
-       int highest_displayed = 0;
-       addrbookent *addrbook = NULL;
-       int num_ab = 0;
-       int bbs_reverse = 0;
        wcsession *WCC = WC;
        HashPos *at;
        const char *HashKey;
        long HKLen;
-       int care_for_empty_list = 0;
-       int load_seen = 0;
-       int sortit = 0;
-       int defaultsortorder = 0;
        WCTemplputParams SubTP;
-       char *ab_name;
-       const StrBuf *Mime;
-       long lowest_found = (-1);
-       long highest_found = (-1);
+       SharedMessageStatus Stat;
+       void *ViewSpecific;
 
        if (havebstr("is_summary") && (1 == (ibstr("is_summary"))))
                WCC->wc_view = VIEW_MAILBOX;
 
+       memset(&Stat, 0, sizeof(SharedMessageStatus));
+       Stat.maxload = 10000;
+       Stat.lowest_found = (-1);
+       Stat.highest_found = (-1);
+       GetHash(ReadLoopHandler, IKEY(WCC->wc_view), &vViewMsg);
+       if (vViewMsg == NULL) {
+               WCC->wc_view = VIEW_BBS;
+               GetHash(ReadLoopHandler, IKEY(WCC->wc_view), &vViewMsg);
+       }
+       if (vViewMsg == NULL)
+               return;///TODO: print message
+
+       ViewMsg = (RoomRenderer*) vViewMsg;
        if (!WCC->is_ajax) {
                output_headers(1, 1, 1, 0, 0, 0);
        } else if (WCC->wc_view == VIEW_MAILBOX) {
                jsonMessageListHdr();
        }
 
-       switch (WCC->wc_view) {
-       case VIEW_WIKI:
-               sprintf(buf, "wiki?room=%s&page=home", ChrPtr(WCC->wc_roomname));
-               http_redirect(buf);
+       switch(ViewMsg->GetParamsGetServerCall(
+                      &Stat,
+                      &ViewSpecific,
+                      oper,
+                      cmd, sizeof(cmd)))
+       {
+       case 400:
+       case 404:
+
                return;
-       case VIEW_CALBRIEF:
-       case VIEW_CALENDAR:
-               load_seen = 1;
-               strcpy(cmd, "MSGS ALL");
-               maxmsgs = 32767;
-               parse_calendar_view_request(&calv);
-               break;
-       case VIEW_TASKS:
-               strcpy(cmd, "MSGS ALL");
-               maxmsgs = 32767;
-               break;
-       case VIEW_NOTES:
-               strcpy(cmd, "MSGS ALL");
-               maxmsgs = 32767;
-               wprintf("<div id=\"new_notes_here\"></div>\n");
-               break;
-       case VIEW_ADDRESSBOOK:
-               is_singlecard = ibstr("is_singlecard");
-               if (is_singlecard != 1) {
-                       if (oper == do_search) {
-                               snprintf(cmd, sizeof(cmd), "MSGS SEARCH|%s", bstr("query"));
-                       }
-                       else {
-                               strcpy(cmd, "MSGS ALL");
-                       }
-                       maxmsgs = 9999999;
-                       break;
-               }
-               break;
-       case VIEW_MAILBOX: 
-         if (!WCC->is_ajax) {
-           new_summary_view();
-           return;
-         } else {
-               defaultsortorder = 2;
-               sortit = 1;
-               load_seen = 1;
-               care_for_empty_list = 0;
-               with_headers = 1;
-               /* Generally using maxmsgs|startmsg is not required
-                  in mailbox view, but we have a 'safemode' for clients
-                  (*cough* Exploder) that simply can't handle too many */
-               if (havebstr("maxmsgs")) maxmsgs = ibstr("maxmsgs");
-               else maxmsgs = 9999999;
-               if (havebstr("startmsg")) startmsg = lbstr("startmsg");
-               snprintf(cmd, sizeof(cmd), "MSGS %s|%s||1",
-                        (oper == do_search) ? "SEARCH" : "ALL",
-                        (oper == do_search) ? bstr("query") : ""
-                       );
-         }
-               break;
-       case VIEW_BBS:
+       case 300: /* the callback hook should do the work for us here, since he knows what to do. */
+               return;
+       case 200:
        default:
-               defaultsortorder = 1;
-               startmsg = -1;
-               sortit = 1;
-               care_for_empty_list = 1;
-
-               rlid[oper].cmd(cmd, sizeof(cmd));
-
-               if (havebstr("maxmsgs"))
-                       maxmsgs = ibstr("maxmsgs");
-               if (maxmsgs == 0) maxmsgs = DEFAULT_MAXMSGS;
-
-               if (havebstr("startmsg")) {
-                       startmsg = lbstr("startmsg");
-               }
-               
-       }
-
-       nummsgs = load_msg_ptrs(cmd, with_headers, &lowest_found, &highest_found);
-       if (nummsgs == 0) {
-               if (care_for_empty_list) {
-                       wprintf("<div class=\"nomsgs\"><br><em>");
-                       switch (oper) {
-                       case readnew:
-                               wprintf(_("No new messages."));
-                               break;
-                       case readold:
-                               wprintf(_("No old messages."));
-                               break;
-                       default:
-                               wprintf(_("No messages here."));
-                       }
-                       wprintf("</em><br></div>\n");
-                       goto DONE;
-               }
-
+               break;
        }
+       if (!IsEmptyStr(cmd))
+               Stat.nummsgs = load_msg_ptrs(cmd, &Stat);
 
-       if (sortit) {
+       if (Stat.sortit) {
                CompareFunc SortIt;
                memset(&SubTP, 0, sizeof(WCTemplputParams));
                SubTP.Filter.ContextType = CTX_NONE;
                SubTP.Context = NULL;
                SortIt =  RetrieveSort(&SubTP, NULL, 0,
-                                      HKEY("date"), defaultsortorder);
+                                      HKEY("date"), Stat.defaultsortorder);
                if (SortIt != NULL)
                        SortByPayload(WCC->summ, SortIt);
-               if (WCC->wc_view == VIEW_BBS) {
-                       if (lbstr("SortOrder") == 2) {
-                               bbs_reverse = 1;
-                               num_displayed = -DEFAULT_MAXMSGS;
-                       }
-                       else {
-                               bbs_reverse = 0;
-                               num_displayed = DEFAULT_MAXMSGS;
-                       }
-               }
        }
-       if (startmsg < 0) startmsg = (bbs_reverse) ? nummsgs - 1 : 0;
+       if (Stat.startmsg < 0) 
+               Stat.startmsg = (Stat.reverse) ? Stat.nummsgs - 1 : 0;
 
-       if (load_seen) load_seen_flags();
+       if (Stat.load_seen) load_seen_flags();
        
         /*
         * Print any inforation above the message list...
         */
-       switch (WCC->wc_view) {
-       case VIEW_BBS:
-               BBViewToolBar = NewStrBufPlain(NULL, SIZ);
-               MessageDropdown = NewStrBufPlain(NULL, SIZ);
-
-               maxmsgs = DrawMessageDropdown(MessageDropdown, maxmsgs, startmsg,
-                                               num_displayed, lowest_found-1);
-               if (num_displayed < 0) {
-                       startmsg += maxmsgs;
-                       if (num_displayed != maxmsgs)                           
-                               maxmsgs = abs(maxmsgs) + 1;
-                       else
-                               maxmsgs = abs(maxmsgs);
+       if (ViewMsg->PrintViewHeader != NULL)
+               ViewMsg->PrintViewHeader(&Stat, &ViewSpecific);
 
-               }
-               memset(&SubTP, 0, sizeof(WCTemplputParams));
-               SubTP.Filter.ContextType = CTX_STRBUF;
-               SubTP.Context = MessageDropdown;
-               DoTemplate(HKEY("msg_listselector_top"), BBViewToolBar, &SubTP);
-               StrBufAppendBuf(WCC->WBuf, BBViewToolBar, 0);
-               FlushStrBuf(BBViewToolBar);
-               break;
-       }
-       WCC->startmsg =  startmsg;
-       WCC->maxmsgs = maxmsgs;
+       WCC->startmsg =  Stat.startmsg;
+       WCC->maxmsgs = Stat.maxmsgs;
        WCC->num_displayed = 0;
 
        /* Put some helpful data in vars for mailsummary_json */
-       svputlong("READLOOP:TOTALMSGS", nummsgs);
-       svputlong("READLOOP:STARTMSG", startmsg);
+       svputlong("READLOOP:TOTALMSGS", Stat.nummsgs);
+       svputlong("READLOOP:STARTMSG", Stat.startmsg);
        svputlong("WCVIEW", WCC->wc_view);
 
        /*
         * iterate over each message. if we need to load an attachment, do it here. 
         */
-       if (WCC->wc_view == VIEW_MAILBOX) goto NO_MSG_LOOP;
-       at = GetNewHashPos(WCC->summ, 0);
-       num_displayed = i = 0;
-       while (GetNextHashPos(WCC->summ, at, &HKLen, &HashKey, &vMsg)) {
-               Msg = (message_summary*) vMsg;          
-               if ((Msg->msgnum >= startmsg) && (num_displayed <= maxmsgs)) {                  
-                       switch (WCC->wc_view) {
-                       case VIEW_WIKI:
-                               break;
-                       case VIEW_CALBRIEF: /* load the mime attachments for special tasks... */
-                       case VIEW_CALENDAR:
-                               load_calendar_item(Msg, Msg->is_new, &calv);
-                               break;
-                       case VIEW_TASKS:
-                               display_task(Msg, Msg->is_new);
-                               break;
-                       case VIEW_NOTES:
-                               display_note(Msg, Msg->is_new);
-                               break;
-                       case VIEW_ADDRESSBOOK:
-                               ab_name = NULL;
-                               fetch_ab_name(Msg, &ab_name);
-                               if (ab_name == NULL) 
-                                       break;
-                               ++num_ab;
-                               addrbook = realloc(addrbook,
-                                                  (sizeof(addrbookent) * num_ab) );
-                               safestrncpy(addrbook[num_ab-1].ab_name, ab_name,
-                                           sizeof(addrbook[num_ab-1].ab_name));
-                               addrbook[num_ab-1].ab_msgnum = Msg->msgnum;
-                               free(ab_name);
-                               break;
-                       case VIEW_BBS: /* Tag the mails we want to show in bbview... */
-                       default:
-                               if (displayed_msgs == NULL) {
-                                       displayed_msgs = malloc(sizeof(long) *
-                                                               (maxmsgs<nummsgs ? maxmsgs + 1 : nummsgs + 1));
-                               }
-                               if ((i >= startmsg) && (i < startmsg + maxmsgs)) {
-                                       displayed_msgs[num_displayed] = Msg->msgnum;
-                                       if (lowest_displayed < 0) lowest_displayed = a;
-                                       highest_displayed = a;
-                       
-                                       num_displayed++;
-                               }
-                       }
-               } 
-               i++;
+
+       if ((ViewMsg->LoadMsgFromServer != NULL) && 
+           (!IsEmptyStr(cmd)))
+       {
+               at = GetNewHashPos(WCC->summ, 0);
+               Stat.num_displayed = i = 0;
+               while ( GetNextHashPos(WCC->summ, at, &HKLen, &HashKey, &vMsg)) {
+                       Msg = (message_summary*) vMsg;          
+                       if ((Msg->msgnum >= Stat.startmsg) && (Stat.num_displayed <= Stat.maxmsgs)) {
+                               ViewMsg->LoadMsgFromServer(&Stat, &ViewSpecific, Msg, Msg->is_new, i);
+                       } 
+                       i++;
+               }
+               DeleteHashPos(&at);
        }
-       DeleteHashPos(&at);
 
-NO_MSG_LOOP:
        /*
         * Done iterating the message list. now tasks we want to do after.
         */
-       switch (WCC->wc_view) {
-       case VIEW_MAILBOX:
-         DoTemplate(HKEY("mailsummary_json"),NULL, &SubTP);
-         break;
-       case VIEW_BBS:
-               if (displayed_msgs != NULL) {
-                       /* if we do a split bbview in the future, begin messages div here */
-                       
-                       for (a=0; a<num_displayed; ++a) {
-                               read_message(WCC->WBuf, HKEY("view_message"), displayed_msgs[a], NULL, &Mime);
-                       }
-                       
-                       /* if we do a split bbview in the future, end messages div here */
-                       
-                       free(displayed_msgs);
-                       displayed_msgs = NULL;
-               }
-               memset(&SubTP, 0, sizeof(WCTemplputParams));
-               SubTP.Filter.ContextType = CTX_STRBUF;
-               SubTP.Context = MessageDropdown;
-               DoTemplate(HKEY("msg_listselector_bottom"), BBViewToolBar, &SubTP);
-               StrBufAppendBuf(WCC->WBuf, BBViewToolBar, 0);
+       if (ViewMsg->RenderView_or_Tail != NULL)
+               ViewMsg->RenderView_or_Tail(&Stat, &ViewSpecific, oper);
 
-               FreeStrBuf(&BBViewToolBar);
-               FreeStrBuf(&MessageDropdown);
-       }
+       if (ViewMsg->ViewCleanup != NULL)
+               ViewMsg->ViewCleanup(&ViewSpecific);
 
-       
-DONE:
-       switch (WCC->wc_view) {
-       case VIEW_WIKI:
-               break;
-       case VIEW_CALBRIEF:
-       case VIEW_CALENDAR:
-               render_calendar_view(&calv);
-               break;
-       case VIEW_TASKS:
-               do_tasks_view();        /* Render the task list */
-               break;
-       case VIEW_NOTES:
-               break;
-       case VIEW_ADDRESSBOOK:
-               if (is_singlecard)
-                       read_message(WC->WBuf, HKEY("view_message"), lbstr("startmsg"), NULL, &Mime);
-               else
-                       do_addrbook_view(addrbook, num_ab);     /* Render the address book */
-               break;
-       case VIEW_MAILBOX: 
-       case VIEW_BBS:
-       default:
-               break;
-       }
-       /* Note: wDumpContent() will output one additional </div> tag. */
-       if (WCC->wc_view != VIEW_MAILBOX) {
-               /* We ought to move this out into template */
-               wDumpContent(1);
-       } else {
-               end_burst();
-       }
        WCC->startmsg = 0;
        WCC->maxmsgs = 0;
        if (WCC->summ != NULL) {
                DeleteHash(&WCC->summ);
        }
-       if (addrbook != NULL) free(addrbook);
-       FreeStrBuf(&BBViewToolBar);
 }
 
 
@@ -1940,13 +1653,6 @@ void jsonMessageListHdr(void)
        begin_burst();
 }
 
-/* Spit out the new summary view. This is basically a static page, so clients can cache the layout, all the dirty work is javascript :) */
-void new_summary_view(void) {
-       begin_burst();
-       DoTemplate(HKEY("msg_listview"),NULL,&NoCtx);
-       DoTemplate(HKEY("trailing"),NULL,&NoCtx);
-       end_burst();
-}
 
 /* Output message list in JSON format */
 void jsonMessageList(void) {
@@ -1958,6 +1664,30 @@ void jsonMessageList(void) {
        WC->is_ajax = 0;
 }
 
+void RegisterReadLoopHandlerset(
+       int RoomType,
+       GetParamsGetServerCall_func GetParamsGetServerCall,
+       PrintViewHeader_func PrintViewHeader,
+       LoadMsgFromServer_func LoadMsgFromServer,
+       RenderView_or_Tail_func RenderView_or_Tail,
+       View_Cleanup_func ViewCleanup
+       )
+{
+       RoomRenderer *Handler;
+
+       Handler = (RoomRenderer*) malloc(sizeof(RoomRenderer));
+
+       Handler->RoomType = RoomType;
+       Handler->GetParamsGetServerCall = GetParamsGetServerCall;
+       Handler->PrintViewHeader = PrintViewHeader;
+       Handler->LoadMsgFromServer = LoadMsgFromServer;
+       Handler->RenderView_or_Tail = RenderView_or_Tail;
+       Handler->ViewCleanup = ViewCleanup;
+
+       Put(ReadLoopHandler, IKEY(RoomType), Handler, NULL);
+
+}
+
 void 
 InitModule_MSG
 (void)
index 29ed7b3b5f6428dcea482191541a34341aa0ea36..69f5e90aee77b065f0d977d76d2f24ebc4a44e34 100644 (file)
@@ -1,7 +1,7 @@
 
 extern HashList *MsgHeaderHandler;
 extern HashList *MimeRenderHandler;
-
+extern HashList *ReadLoopHandler;
 typedef struct wc_mime_attachment wc_mime_attachment;
 typedef void (*RenderMimeFunc)(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset);
 typedef struct _RenderMimeFuncStruct {
@@ -93,4 +93,104 @@ int load_message(message_summary *Msg,
                 StrBuf **Error);
 
 
-int load_msg_ptrs(const char *servcmd, int with_headers, long *lowest_found, long *highest_found);
+
+
+typedef struct _SharedMessageStatus{
+       long load_seen;        /** should read information be loaded */
+       long sortit;           /** should we sort it using the standard sort API? */
+       long defaultsortorder; /** if we should sort it, which direction should be the default? */
+
+       long maxload;          /** how many headers should we accept from the server? defaults to 10k */
+       long maxmsgs;          /** how many message bodies do you want to load at most?*/
+       long reverse;          /** should the load-range be reversed? */
+
+       long startmsg;         /** which is the start message ????? */
+       long nummsgs;          /** How many messages are available to your view? */
+       long num_displayed;    /** counted up for LoadMsgFromServer */ /* TODO: unclear who should access this and why */
+
+       long lowest_found;     /** smallest Message ID found;  */
+       long highest_found;    /** highest Message ID found;  */
+
+}SharedMessageStatus;
+
+int load_msg_ptrs(const char *servcmd, SharedMessageStatus *Stat);
+
+typedef int (*GetParamsGetServerCall_func)(SharedMessageStatus *Stat, 
+                                          void **ViewSpecific, 
+                                          long oper, 
+                                          char *cmd, 
+                                          long len);
+
+typedef int (*PrintViewHeader_func)(SharedMessageStatus *Stat, void **ViewSpecific);
+
+typedef int (*LoadMsgFromServer_func)(SharedMessageStatus *Stat, 
+                                     void **ViewSpecific, 
+                                     message_summary* Msg, 
+                                     int is_new, 
+                                     int i);
+
+typedef int (*RenderView_or_Tail_func)(SharedMessageStatus *Stat, 
+                                      void **ViewSpecific, 
+                                      long oper);
+typedef int (*View_Cleanup_func)(void **ViewSpecific);
+
+void RegisterReadLoopHandlerset(
+       /**
+        * RoomType: which View definition are you going to be called for
+        */
+       int RoomType,
+
+       /**
+        * GetParamsGetServerCall should do the following:
+        *  * allocate your private context structure
+        *  * evaluate your commandline arguments, put results to your private struct.
+        *  * fill cmd with the command to load the message pointer list:
+        *    * might depend on bstr/oper depending on your needs
+        *    * might stay empty if no list should loaded and LoadMsgFromServer 
+        *      is skipped.
+        *  * influence the behaviour by presetting values on SharedMessageStatus
+        */
+       GetParamsGetServerCall_func GetParamsGetServerCall,
+
+       /**
+        * PrintViewHeader is here to print informations infront of your messages.
+        * The message list is already loaded & sorted (if) so you can evaluate 
+        * its result on the SharedMessageStatus struct.
+        */
+       PrintViewHeader_func PrintViewHeader,
+
+       /**
+        * LoadMsgFromServer is called for every message in the message list:
+        *  * which is 
+        *    * after 'startmsg'  
+        *    * up to 'maxmsgs' after your 'startmsg'
+        *  * it should load and parse messages from citserer.
+        *  * depending on your needs you might want to print your message here...
+        *  * if cmd was empty, its skipped alltogether.
+        */
+       LoadMsgFromServer_func LoadMsgFromServer,
+
+       /**
+        * RenderView_or_Tail is called last; 
+        *  * if you used PrintViewHeader to print messages, you might want to print 
+        *    trailing information here
+        *  * if you just pre-loaded your messages, put your render code here.
+        */
+       RenderView_or_Tail_func RenderView_or_Tail,
+
+       /**
+        * ViewCleanup should just clear your private data so all your mem can go back to 
+        * VALgrindHALLA.
+        * it also should release the content for delivery via end_burst() or wDumpContent(1);
+        */
+       View_Cleanup_func ViewCleanup
+       );
+/*
+GetParamsGetServerCall
+
+PrintViewHeader
+
+LoadMsgFromServer
+
+RenderView_or_Tail
+*/
index f17ae54150530cf52a6ea6fb50bf68d01c0d9aae..55411e22860ca66eab9acb336aa717a09b6a1822 100644 (file)
@@ -1070,6 +1070,98 @@ void tmplput_MIME_Length(StrBuf *Target, WCTemplputParams *TP)
        StrBufAppendPrintf(Target, "%ld", mime->length);
 }
 
+/* startmsg is an index within the message list.
+ * starting_from is the Citadel message number to be supplied to a "MSGS GT" operation
+ */
+long DrawMessageDropdown(StrBuf *Selector, long maxmsgs, long startmsg, int nMessages, long starting_from)
+{
+       StrBuf *TmpBuf;
+       wcsession *WCC = WC;
+       void *vMsg;
+       int lo, hi;
+       long ret;
+       long hklen;
+       const char *key;
+       int done = 0;
+       int nItems;
+       HashPos *At;
+       long vector[16];
+       WCTemplputParams SubTP;
+
+       memset(&SubTP, 0, sizeof(WCTemplputParams));
+       SubTP.Filter.ContextType = CTX_LONGVECTOR;
+       SubTP.Context = &vector;
+       TmpBuf = NewStrBufPlain(NULL, SIZ);
+       At = GetNewHashPos(WCC->summ, nMessages);
+       nItems = GetCount(WCC->summ);
+       ret = nMessages;
+       vector[0] = 7;
+       vector[2] = 1;
+       vector[1] = startmsg;
+       vector[3] = 0;
+       vector[7] = starting_from;
+
+       while (!done) {
+               vector[3] = abs(nMessages);
+               lo = GetHashPosCounter(At);
+               if (nMessages > 0) {
+                       if (lo + nMessages >= nItems) {
+                               hi = nItems - 1;
+                               vector[3] = nItems - lo;
+                               if (startmsg == lo) 
+                                       ret = vector[3];
+                       }
+                       else {
+                               hi = lo + nMessages - 1;
+                       }
+               } else {
+                       if (lo + nMessages < -1) {
+                               hi = 0;
+                       }
+                       else {
+                               if ((lo % abs(nMessages)) != 0) {
+                                       int offset = (lo % abs(nMessages) *
+                                                     (nMessages / abs(nMessages)));
+                                       hi = lo + offset;
+                                       vector[3] = abs(offset);
+                                       if (startmsg == lo)
+                                                ret = offset;
+                               }
+                               else
+                                       hi = lo + nMessages;
+                       }
+               }
+               done = !GetNextHashPos(WCC->summ, At, &hklen, &key, &vMsg);
+               
+               /*
+                * Bump these because although we're thinking in zero base, the user
+                * is a drooling idiot and is thinking in one base.
+                */
+               vector[4] = lo + 1;
+               vector[5] = hi + 1;
+               vector[6] = lo;
+               FlushStrBuf(TmpBuf);
+               dbg_print_longvector(vector);
+               DoTemplate(HKEY("select_messageindex"), TmpBuf, &SubTP);
+               StrBufAppendBuf(Selector, TmpBuf, 0);
+       }
+       vector[6] = 0;
+       FlushStrBuf(TmpBuf);
+       if (maxmsgs == 9999999) {
+               vector[1] = 1;
+               ret = maxmsgs;
+       }
+       else
+               vector[1] = 0;          
+       vector[2] = 0;
+       dbg_print_longvector(vector);
+       DoTemplate(HKEY("select_messageindex_all"), TmpBuf, &SubTP);
+       StrBufAppendBuf(Selector, TmpBuf, 0);
+       FreeStrBuf(&TmpBuf);
+       DeleteHashPos(&At);
+       return ret;
+}
+
 HashList *iterate_get_registered_Attachments(StrBuf *Target, WCTemplputParams *TP)
 {
        return WC->attachments;
@@ -1112,15 +1204,247 @@ readloop_struct rlid[] = {
        { {HKEY("readfwd")},   servcmd_readfwd},
        { {HKEY("readnew")},   servcmd_readnew},
        { {HKEY("readold")},   servcmd_readold},
-       { {HKEY("readgt")},   servcmd_readgt}
+       { {HKEY("readgt")},    servcmd_readgt}
 };
 
+/* Spit out the new summary view. This is basically a static page, so clients can cache the layout, all the dirty work is javascript :) */
+void new_summary_view(void) {
+       begin_burst();
+       DoTemplate(HKEY("msg_listview"),NULL,&NoCtx);
+       DoTemplate(HKEY("trailing"),NULL,&NoCtx);
+       end_burst();
+}
+
+
+int mailview_GetParamsGetServerCall(SharedMessageStatus *Stat, 
+                                   void **ViewSpecific, 
+                                   long oper, 
+                                   char *cmd, 
+                                   long len)
+{
+       if (!WC->is_ajax) {
+               new_summary_view();
+               return 200;
+       } else {
+               Stat->defaultsortorder = 2;
+               Stat->sortit = 1;
+               Stat->load_seen = 1;
+               /* Generally using maxmsgs|startmsg is not required
+                  in mailbox view, but we have a 'safemode' for clients
+                  (*cough* Exploder) that simply can't handle too many */
+               if (havebstr("maxmsgs"))  Stat->maxmsgs  = ibstr("maxmsgs");
+               else                      Stat->maxmsgs  = 9999999;
+               if (havebstr("startmsg")) Stat->startmsg = lbstr("startmsg");
+               snprintf(cmd, len, "MSGS %s|%s||1",
+                        (oper == do_search) ? "SEARCH" : "ALL",
+                        (oper == do_search) ? bstr("query") : ""
+                       );
+       }
+       return 200;
+}
+
+int mailview_RenderView_or_Tail(SharedMessageStatus *Stat, 
+                               void **ViewSpecific, 
+                               long oper)
+{
+       WCTemplputParams SubTP;
+
+       DoTemplate(HKEY("mailsummary_json"),NULL, &SubTP);
+       return 0;
+}
+
+int mailview_Cleanup(void **ViewSpecific)
+{
+       /* Note: wDumpContent() will output one additional </div> tag. */
+       /* We ought to move this out into template */
+       if (WC->is_ajax) 
+               end_burst();
+       else
+               wDumpContent(1);
+       return 0;
+}
+
+
+
+typedef struct _bbsview_stuct {
+       StrBuf *BBViewToolBar;
+       StrBuf *MessageDropdown;
+       long *displayed_msgs;
+       int a;
+}bbsview_struct;
+
+int bbsview_GetParamsGetServerCall(SharedMessageStatus *Stat, 
+                                  void **ViewSpecific, 
+                                  long oper, 
+                                  char *cmd, 
+                                  long len)
+{
+       bbsview_struct *VS;
+
+       VS = (bbsview_struct*) malloc(sizeof(bbsview_struct));
+       memset(VS, 0, sizeof(bbsview_struct));
+       *ViewSpecific = (void*)VS;
+       Stat->defaultsortorder = 1;
+       Stat->startmsg = -1;
+       Stat->sortit = 1;
+       
+       rlid[oper].cmd(cmd, len);
+       
+       if (havebstr("maxmsgs"))
+               Stat->maxmsgs = ibstr("maxmsgs");
+       if (Stat->maxmsgs == 0) Stat->maxmsgs = DEFAULT_MAXMSGS;
+       
+       if (havebstr("startmsg")) {
+               Stat->startmsg = lbstr("startmsg");
+       }
+       if (lbstr("SortOrder") == 2) {
+               Stat->reverse = 1;
+               Stat->num_displayed = -DEFAULT_MAXMSGS;
+       }
+       else {
+               Stat->reverse = 0;
+               Stat->num_displayed = DEFAULT_MAXMSGS;
+       }
+
+       return 200;
+}
+
+int bbsview_PrintViewHeader(SharedMessageStatus *Stat, void **ViewSpecific)
+{
+       bbsview_struct *VS;
+       WCTemplputParams SubTP;
+
+       VS = (bbsview_struct*)*ViewSpecific;
+
+       VS->BBViewToolBar = NewStrBufPlain(NULL, SIZ);
+       VS->MessageDropdown = NewStrBufPlain(NULL, SIZ);
+
+       /*** startmsg->maxmsgs = **/DrawMessageDropdown(VS->MessageDropdown, 
+                                                       Stat->maxmsgs, 
+                                                       Stat->startmsg,
+                                                       Stat->num_displayed, 
+                                                       Stat->lowest_found-1);
+       if (Stat->num_displayed < 0) {
+               Stat->startmsg += Stat->maxmsgs;
+               if (Stat->num_displayed != Stat->maxmsgs)                               
+                       Stat->maxmsgs = abs(Stat->maxmsgs) + 1;
+               else
+                       Stat->maxmsgs = abs(Stat->maxmsgs);
+
+       }
+       memset(&SubTP, 0, sizeof(WCTemplputParams));
+       SubTP.Filter.ContextType = CTX_STRBUF;
+       SubTP.Context = VS->MessageDropdown;
+       DoTemplate(HKEY("msg_listselector_top"), VS->BBViewToolBar, &SubTP);
+       StrBufAppendBuf(WC->WBuf, VS->BBViewToolBar, 0);
+       FlushStrBuf(VS->BBViewToolBar);
+       return 200;
+}
+
+int bbsview_LoadMsgFromServer(SharedMessageStatus *Stat, 
+                             void **ViewSpecific, 
+                             message_summary* Msg, 
+                             int is_new, 
+                             int i)
+{
+       bbsview_struct *VS;
+
+       VS = (bbsview_struct*)*ViewSpecific;
+       if (VS->displayed_msgs == NULL) {
+               VS->displayed_msgs = malloc(sizeof(long) *
+                                           ((Stat->maxmsgs < Stat->nummsgs) ? 
+                                            Stat->maxmsgs + 1 : 
+                                            Stat->nummsgs + 1));
+       }
+       if ((i >= Stat->startmsg) && (i < Stat->startmsg + Stat->maxmsgs)) {
+               VS->displayed_msgs[Stat->num_displayed] = Msg->msgnum;
+               Stat->num_displayed++;
+       }
+       return 200;
+}
 
 
+int bbsview_RenderView_or_Tail(SharedMessageStatus *Stat, 
+                              void **ViewSpecific, 
+                              long oper)
+{
+       wcsession *WCC = WC;
+       bbsview_struct *VS;
+       WCTemplputParams SubTP;
+       const StrBuf *Mime;
+
+       VS = (bbsview_struct*)*ViewSpecific;
+       if (Stat->nummsgs == 0) {
+               wprintf("<div class=\"nomsgs\"><br><em>");
+               switch (oper) {
+               case readnew:
+                       wprintf(_("No new messages."));
+                       break;
+               case readold:
+                       wprintf(_("No old messages."));
+                       break;
+               default:
+                       wprintf(_("No messages here."));
+               }
+               wprintf("</em><br></div>\n");
+       }
+       else 
+       {
+               if (VS->displayed_msgs != NULL) {
+                       /* if we do a split bbview in the future, begin messages div here */
+                       int a;/// todo  
+                       for (a=0; a < Stat->num_displayed; ++a) {
+                               read_message(WCC->WBuf, HKEY("view_message"), VS->displayed_msgs[a], NULL, &Mime);
+                       }
+                       
+                       /* if we do a split bbview in the future, end messages div here */
+                       
+                       free(VS->displayed_msgs);
+                       VS->displayed_msgs = NULL;
+               }
+               memset(&SubTP, 0, sizeof(WCTemplputParams));
+               SubTP.Filter.ContextType = CTX_STRBUF;
+               SubTP.Context = VS->MessageDropdown;
+               DoTemplate(HKEY("msg_listselector_bottom"), VS->BBViewToolBar, &SubTP);
+               StrBufAppendBuf(WCC->WBuf, VS->BBViewToolBar, 0);
+       }
+       return 0;
+
+}
+
+
+int bbsview_Cleanup(void **ViewSpecific)
+{
+       bbsview_struct *VS;
+
+       VS = (bbsview_struct*)*ViewSpecific;
+       end_burst();
+       FreeStrBuf(&VS->BBViewToolBar);
+       FreeStrBuf(&VS->MessageDropdown);
+       free(VS);
+       return 0;
+}
+
 void 
 InitModule_MSGRENDERERS
 (void)
 {
+       RegisterReadLoopHandlerset(
+               VIEW_MAILBOX,
+               mailview_GetParamsGetServerCall,
+               NULL, /// TODO: is this right?
+               NULL, //// ""
+               mailview_RenderView_or_Tail,
+               mailview_Cleanup);
+
+       RegisterReadLoopHandlerset(
+               VIEW_BBS,
+               bbsview_GetParamsGetServerCall,
+               bbsview_PrintViewHeader,
+               bbsview_LoadMsgFromServer,
+               bbsview_RenderView_or_Tail,
+               bbsview_Cleanup);
+
        RegisterSortFunc(HKEY("date"), 
                         NULL, 0,
                         summcmp_date,
@@ -1253,6 +1577,7 @@ ServerStartModule_MSGRENDERERS
 {
        MsgHeaderHandler = NewHash(1, NULL);
        MimeRenderHandler = NewHash(1, NULL);
+       ReadLoopHandler = NewHash(1, NULL);
 }
 
 void 
@@ -1261,6 +1586,7 @@ ServerShutdownModule_MSGRENDERERS
 {
        DeleteHash(&MsgHeaderHandler);
        DeleteHash(&MimeRenderHandler);
+       DeleteHash(&ReadLoopHandler);
 }
 
 
index a8e02b04ca42577acea228288e07b81c912763e8..d9a50bc68791217c8ccab47a00cedde5a0b3237b 100644 (file)
@@ -296,13 +296,19 @@ void ajax_update_note(void) {
  *
  * msgnum = Message number on the local server of the note to be displayed
  */
-void display_note(message_summary *Msg, int unread) {
+////TODO: falscher hook
+int notes_LoadMsgFromServer(SharedMessageStatus *Stat, 
+                           void **ViewSpecific, 
+                           message_summary* Msg, 
+                           int is_new, 
+                           int i)
+{
        struct vnote *v;
        WCTemplputParams TP;
 
        memset(&TP, 0, sizeof(WCTemplputParams));
        TP.Filter.ContextType = CTX_VNOTE;
-       v = vnote_new_from_msg(Msg->msgnum, unread);
+       v = vnote_new_from_msg(Msg->msgnum, is_new);
        if (v) {
                TP.Context = v;
                DoTemplate(HKEY("vnoteitem"),
@@ -322,6 +328,7 @@ void display_note(message_summary *Msg, int unread) {
 
                vnote_free(v);
        }
+       return 0;
 }
 
 
@@ -408,10 +415,41 @@ void tmpl_vcard_put_uid(StrBuf *Target, WCTemplputParams *TP)
        StrBufAppendBufPlain(Target, v->uid, -1, 0);
 }
 
+
+
+
+int notes_GetParamsGetServerCall(SharedMessageStatus *Stat, 
+                                void **ViewSpecific, 
+                                long oper, 
+                                char *cmd, 
+                                long len)
+{
+       strcpy(cmd, "MSGS ALL");
+       Stat->maxmsgs = 32767;
+       wprintf("<div id=\"new_notes_here\"></div>\n");
+       return 200;
+
+}
+
+int notes_Cleanup(void **ViewSpecific)
+{
+       end_burst();
+       return 0;
+}
+
+
 void 
 InitModule_NOTES
 (void)
 {
+       RegisterReadLoopHandlerset(
+               VIEW_NOTES,
+               notes_GetParamsGetServerCall,
+               NULL,
+               notes_LoadMsgFromServer,
+               NULL,
+               notes_Cleanup);
+
        WebcitAddUrlHandler(HKEY("add_new_note"), add_new_note, 0);
        WebcitAddUrlHandler(HKEY("ajax_update_note"), ajax_update_note, 0);
 
index 2e74064ec9f5386c76e8a336f5cb90ed1d7ed196..503dc63932ce3865457ff3ee391b52f06a4b5fdf 100644 (file)
@@ -169,7 +169,9 @@ void display_smtpqueue_inner_div(void) {
        int i;
        int num_msgs;
        StrBuf *Buf;
+       SharedMessageStatus Stat;
 
+       memset(&Stat, 0, sizeof(SharedMessageStatus));
        /* Check to see if we can go to the __CitadelSMTPspoolout__ room.
         * If not, we don't have access to the queue.
         */
@@ -178,7 +180,7 @@ void display_smtpqueue_inner_div(void) {
        FreeStrBuf(&Buf);
        if (!strcasecmp(ChrPtr(WCC->wc_roomname), "__CitadelSMTPspoolout__")) {
 
-               num_msgs = load_msg_ptrs("MSGS ALL", 0, NULL, NULL);
+               num_msgs = load_msg_ptrs("MSGS ALL", &Msg);
                if (num_msgs > 0) {
                         wprintf("<table class=\"mailbox_summary\" rules=rows "
                                "cellpadding=2 style=\"width:100%%;\">"
index ae2588da2651a541f7dd5523afe3757bc4c2a874..fb34a85837a4fa08f84fd1a6c091933ceb891750 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include "webcit.h"
+#include "calendar.h"
 
 /*
  * Display today's date in a friendly format
@@ -84,7 +85,9 @@ void tasks_section(void) {
        message_summary *Msg;
        wcsession *WCC = WC;
        StrBuf *Buf;
+       SharedMessageStatus Stat;
 
+       memset(&Stat, 0, sizeof(SharedMessageStatus));
        Buf = NewStrBufPlain(HKEY("_TASKS_"));
        gotoroom(Buf);
        FreeStrBuf(&Buf);
@@ -92,14 +95,14 @@ void tasks_section(void) {
                num_msgs = 0;
        }
        else {
-               num_msgs = load_msg_ptrs("MSGS ALL", 0, NULL, NULL);
+               num_msgs = load_msg_ptrs("MSGS ALL", &Stat);
        }
 
        if (num_msgs > 0) {
                at = GetNewHashPos(WCC->summ, 0);
                while (GetNextHashPos(WCC->summ, at, &HKLen, &HashKey, &vMsg)) {
                        Msg = (message_summary*) vMsg;          
-                       display_task(Msg, 0);
+                       tasks_LoadMsgFromServer(NULL, NULL, Msg, 0, 0);
                }
                DeleteHashPos(&at);
        }
@@ -116,6 +119,7 @@ void tasks_section(void) {
  * Calendar section
  */
 void calendar_section(void) {
+       char cmd[SIZ];
        int num_msgs = 0;
        HashPos *at;
        const char *HashKey;
@@ -123,9 +127,12 @@ void calendar_section(void) {
        void *vMsg;
        message_summary *Msg;
        wcsession *WCC = WC;
-       struct calview c;
+       calview c;
        StrBuf *Buf;
+       void *v = &c;
+       SharedMessageStatus Stat;
 
+       memset(&Stat, 0, sizeof(SharedMessageStatus));
        Buf = NewStrBufPlain(HKEY("_CALENDAR_"));
        gotoroom(Buf);
        FreeStrBuf(&Buf);
@@ -133,16 +140,19 @@ void calendar_section(void) {
                num_msgs = 0;
        }
        else {
-               num_msgs = load_msg_ptrs("MSGS ALL", 0, NULL, NULL);
+               num_msgs = load_msg_ptrs("MSGS ALL", &Stat);
        }
-
-       parse_calendar_view_request(&c);
+       calendar_GetParamsGetServerCall(&Stat, 
+                                       &c,
+                                       readnew, 
+                                       cmd, 
+                                       sizeof(cmd));
 
        if (num_msgs > 0) {
                at = GetNewHashPos(WCC->summ, 0);
                while (GetNextHashPos(WCC->summ, at, &HKLen, &HashKey, &vMsg)) {
                        Msg = (message_summary*) vMsg;          
-                       load_calendar_item(Msg, 0, &c);
+                       calendar_LoadMsgFromServer(NULL, &v, Msg, 0, 0);
                }
                DeleteHashPos(&at);
        }
diff --git a/webcit/tasks.c b/webcit/tasks.c
new file mode 100644 (file)
index 0000000..fecdb67
--- /dev/null
@@ -0,0 +1,676 @@
+#include "webcit.h"
+#include "calendar.h"
+#include "webserver.h"
+
+/*
+ * qsort filter to move completed tasks to bottom of task list
+ */
+int task_completed_cmp(const void *vtask1, const void *vtask2) {
+       disp_cal * Task1 = (disp_cal *)GetSearchPayload(vtask1);
+/*     disp_cal * Task2 = (disp_cal *)GetSearchPayload(vtask2); */
+
+       icalproperty_status t1 = icalcomponent_get_status((Task1)->cal);
+       /* icalproperty_status t2 = icalcomponent_get_status(((struct disp_cal *)task2)->cal); */
+       
+       if (t1 == ICAL_STATUS_COMPLETED) 
+               return 1;
+       return 0;
+}
+
+
+/*
+ * Helper function for do_tasks_view().  Returns the due date/time of a vtodo.
+ */
+time_t get_task_due_date(icalcomponent *vtodo, int *is_date) {
+       icalproperty *p;
+
+       if (vtodo == NULL) {
+               return(0L);
+       }
+
+       /*
+        * If we're looking at a fully encapsulated VCALENDAR
+        * rather than a VTODO component, recurse into the data
+        * structure until we get a VTODO.
+        */
+       if (icalcomponent_isa(vtodo) == ICAL_VCALENDAR_COMPONENT) {
+               return get_task_due_date(
+                       icalcomponent_get_first_component(
+                               vtodo, ICAL_VTODO_COMPONENT
+                               ), is_date
+                       );
+       }
+
+       p = icalcomponent_get_first_property(vtodo, ICAL_DUE_PROPERTY);
+       if (p != NULL) {
+               struct icaltimetype t = icalproperty_get_due(p);
+
+               if (is_date)
+                       *is_date = t.is_date;
+               return(icaltime_as_timet(t));
+       }
+       else {
+               return(0L);
+       }
+}
+
+/*
+ * Compare the due dates of two tasks (this is for sorting)
+ */
+int task_due_cmp(const void *vtask1, const void *vtask2) {
+       disp_cal * Task1 = (disp_cal *)GetSearchPayload(vtask1);
+       disp_cal * Task2 = (disp_cal *)GetSearchPayload(vtask2);
+
+       time_t t1;
+       time_t t2;
+
+       t1 =  get_task_due_date(Task1->cal, NULL);
+       t2 =  get_task_due_date(Task2->cal, NULL);
+       if (t1 < t2) return(-1);
+       if (t1 > t2) return(1);
+       return(0);
+}
+
+/*
+ * do the whole task view stuff
+ */
+int tasks_RenderView_or_Tail(SharedMessageStatus *Stat, 
+                             void **ViewSpecific, 
+                             long oper)
+{
+       long hklen;
+       const char *HashKey;
+       void *vCal;
+       disp_cal *Cal;
+       HashPos *Pos;
+       int nItems;
+       time_t due;
+       char buf[SIZ];
+       icalproperty *p;
+       wcsession *WCC = WC;
+
+       wprintf("<div class=\"fix_scrollbar_bug\">"
+               "<table class=\"calendar_view_background\"><tbody id=\"taskview\">\n<tr>\n"
+               "<th>");
+       wprintf(_("Completed?"));
+       wprintf("</th><th>");
+       wprintf(_("Name of task"));
+       wprintf("</th><th>");
+       wprintf(_("Date due"));
+       wprintf("</th><th>");
+       wprintf(_("Category"));
+       wprintf(" (<select id=\"selectcategory\"><option value=\"showall\">%s</option></select>)</th></tr>\n",
+               _("Show All"));
+
+       nItems = GetCount(WC->disp_cal_items);
+
+       /* Sort them if necessary
+       if (nItems > 1) {
+               SortByPayload(WC->disp_cal_items, task_due_cmp);
+       }
+       * this shouldn't be neccessary, since we sort by the start time.
+       */
+
+       /* And then again, by completed */
+       if (nItems > 1) {
+               SortByPayload(WC->disp_cal_items, 
+                             task_completed_cmp);
+       }
+
+       Pos = GetNewHashPos(WCC->disp_cal_items, 0);
+       while (GetNextHashPos(WCC->disp_cal_items, Pos, &hklen, &HashKey, &vCal)) {
+               icalproperty_status todoStatus;
+               int is_date;
+
+               Cal = (disp_cal*)vCal;
+               wprintf("<tr><td>");
+               todoStatus = icalcomponent_get_status(Cal->cal);
+               wprintf("<input type=\"checkbox\" name=\"completed\" value=\"completed\" ");
+               if (todoStatus == ICAL_STATUS_COMPLETED) {
+                       wprintf("checked=\"checked\" ");
+               }
+               wprintf("disabled=\"disabled\">\n</td><td>");
+               p = icalcomponent_get_first_property(Cal->cal,
+                       ICAL_SUMMARY_PROPERTY);
+               wprintf("<a href=\"display_edit_task?msgnum=%ld?taskrm=", Cal->cal_msgnum);
+               urlescputs(ChrPtr(WC->wc_roomname));
+               wprintf("\">");
+               /* wprintf("<img align=middle "
+               "src=\"static/taskmanag_16x.gif\" border=0>&nbsp;"); */
+               if (p != NULL) {
+                       escputs((char *)icalproperty_get_comment(p));
+               }
+               wprintf("</a>\n");
+               wprintf("</td>\n");
+
+               due = get_task_due_date(Cal->cal, &is_date);
+               wprintf("<td><span");
+               if (due > 0) {
+                       webcit_fmt_date(buf, SIZ, due, is_date ? DATEFMT_RAWDATE : DATEFMT_FULL);
+                       wprintf(">%s",buf);
+               }
+               else {
+                       wprintf(">");
+               }
+               wprintf("</span></td>");
+               wprintf("<td>");
+               p = icalcomponent_get_first_property(Cal->cal,
+                       ICAL_CATEGORIES_PROPERTY);
+               if (p != NULL) {
+                       escputs((char *)icalproperty_get_categories(p));
+               }
+               wprintf("</td>");
+               wprintf("</tr>");
+       }
+
+       wprintf("</tbody></table></div>\n");
+
+       /* Free the list */
+       DeleteHash(&WC->disp_cal_items);
+       DeleteHashPos(&Pos);
+       return 0;
+}
+
+
+/*
+ * Display a task by itself (for editing)
+ */
+void display_edit_individual_task(icalcomponent *supplied_vtodo, long msgnum, char *from,
+                       int unread, calview *calv)
+{
+       icalcomponent *vtodo;
+       icalproperty *p;
+       struct icaltimetype IcalTime;
+       time_t now;
+       int created_new_vtodo = 0;
+       icalproperty_status todoStatus;
+
+       now = time(NULL);
+
+       if (supplied_vtodo != NULL) {
+               vtodo = supplied_vtodo;
+
+               /*
+                * It's safe to convert to UTC here because there are no recurrences to worry about.
+                */
+               ical_dezonify(vtodo);
+
+               /*
+                * If we're looking at a fully encapsulated VCALENDAR
+                * rather than a VTODO component, attempt to use the first
+                * relevant VTODO subcomponent.  If there is none, the
+                * NULL returned by icalcomponent_get_first_component() will
+                * tell the next iteration of this function to create a
+                * new one.
+                */
+               if (icalcomponent_isa(vtodo) == ICAL_VCALENDAR_COMPONENT) {
+                       display_edit_individual_task(
+                               icalcomponent_get_first_component(
+                                       vtodo, ICAL_VTODO_COMPONENT
+                                       ), 
+                               msgnum, from, unread, calv
+                               );
+                       return;
+               }
+       }
+       else {
+               vtodo = icalcomponent_new(ICAL_VTODO_COMPONENT);
+               created_new_vtodo = 1;
+       }
+       
+       /* TODO: Can we take all this and move it into a template?       */
+       output_headers(1, 1, 1, 0, 0, 0);
+       wprintf("<!-- start task edit form -->");
+       p = icalcomponent_get_first_property(vtodo, ICAL_SUMMARY_PROPERTY);
+       /* Get summary early for title */
+       wprintf("<div class=\"box\">\n");
+       wprintf("<div class=\"boxlabel\">");
+       wprintf(_("Edit task"));
+       wprintf("- ");
+       if (p != NULL) {
+               escputs((char *)icalproperty_get_comment(p));
+       }
+       wprintf("</div>");
+       
+       wprintf("<div class=\"boxcontent\">\n");
+       wprintf("<FORM METHOD=\"POST\" action=\"save_task\">\n");
+       wprintf("<div style=\"display: none;\">\n       ");
+       wprintf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
+       wprintf("<INPUT TYPE=\"hidden\" NAME=\"msgnum\" VALUE=\"%ld\">\n", msgnum);
+       wprintf("<INPUT TYPE=\"hidden\" NAME=\"return_to_summary\" VALUE=\"%d\">\n",
+               ibstr("return_to_summary"));
+       wprintf("</div>");
+       wprintf("<table class=\"calendar_background\"><tr><td>");
+       wprintf("<TABLE STYLE=\"border: none;\">\n");
+
+       wprintf("<TR><TD>");
+       wprintf(_("Summary:"));
+       wprintf("</TD><TD>"
+               "<INPUT TYPE=\"text\" NAME=\"summary\" "
+               "MAXLENGTH=\"64\" SIZE=\"64\" VALUE=\"");
+       p = icalcomponent_get_first_property(vtodo, ICAL_SUMMARY_PROPERTY);
+       if (p != NULL) {
+               escputs((char *)icalproperty_get_comment(p));
+       }
+       wprintf("\"></TD></TR>\n");
+
+       wprintf("<TR><TD>");
+       wprintf(_("Start date:"));
+       wprintf("</TD><TD>");
+       p = icalcomponent_get_first_property(vtodo, ICAL_DTSTART_PROPERTY);
+       wprintf("<INPUT TYPE=\"CHECKBOX\" NAME=\"nodtstart\" ID=\"nodtstart\" VALUE=\"NODTSTART\" ");
+       if (p == NULL) {
+               wprintf("CHECKED=\"CHECKED\"");
+       }
+       wprintf(">");
+       wprintf(_("No date"));
+       
+       wprintf(" ");
+       wprintf("<span ID=\"dtstart_date\">");
+       wprintf(_("or"));
+       wprintf(" ");
+       if (p != NULL) {
+               IcalTime = icalproperty_get_dtstart(p);
+       }
+       else
+               IcalTime = icaltime_current_time_with_zone(get_default_icaltimezone());
+       display_icaltimetype_as_webform(&IcalTime, "dtstart", 0);
+
+       wprintf("<INPUT TYPE=\"CHECKBOX\" NAME=\"dtstart_time_assoc\" ID=\"dtstart_time_assoc\" VALUE=\"yes\"");
+       if (!IcalTime.is_date) {
+               wprintf("CHECKED=\"CHECKED\"");
+       }
+       wprintf(">");
+       wprintf(_("Time associated"));
+       wprintf("</span></TD></TR>\n");
+
+       wprintf("<TR><TD>");
+       wprintf(_("Due date:"));
+       wprintf("</TD><TD>");
+       p = icalcomponent_get_first_property(vtodo, ICAL_DUE_PROPERTY);
+       wprintf("<INPUT TYPE=\"CHECKBOX\" NAME=\"nodue\" ID=\"nodue\" VALUE=\"NODUE\"");
+       if (p == NULL) {
+               wprintf("CHECKED=\"CHECKED\"");
+       }
+       wprintf(">");
+       wprintf(_("No date"));
+       wprintf(" ");
+       wprintf("<span ID=\"due_date\">\n");
+       wprintf(_("or"));
+       wprintf(" ");
+       if (p != NULL) {
+               IcalTime = icalproperty_get_due(p);
+       }
+       else
+               IcalTime = icaltime_current_time_with_zone(get_default_icaltimezone());
+       display_icaltimetype_as_webform(&IcalTime, "due", 0);
+
+       wprintf("<INPUT TYPE=\"CHECKBOX\" NAME=\"due_time_assoc\" ID=\"due_time_assoc\" VALUE=\"yes\"");
+       if (!IcalTime.is_date) {
+               wprintf("CHECKED=\"CHECKED\"");
+       }
+       wprintf(">");
+       wprintf(_("Time associated"));
+       wprintf("</span></TD></TR>\n");
+       todoStatus = icalcomponent_get_status(vtodo);
+       wprintf("<TR><TD>\n");
+       wprintf(_("Completed:"));
+       wprintf("</TD><TD>");
+       wprintf("<INPUT TYPE=\"CHECKBOX\" NAME=\"status\" VALUE=\"COMPLETED\"");
+       if (todoStatus == ICAL_STATUS_COMPLETED) {
+               wprintf(" CHECKED=\"CHECKED\"");
+       } 
+       wprintf(" >");
+       wprintf("</TD></TR>");
+       /* start category field */
+       p = icalcomponent_get_first_property(vtodo, ICAL_CATEGORIES_PROPERTY);
+       wprintf("<TR><TD>");
+       wprintf(_("Category:"));
+       wprintf("</TD><TD>");
+       wprintf("<INPUT TYPE=\"text\" NAME=\"category\" MAXLENGTH=\"32\" SIZE=\"32\" VALUE=\"");
+       if (p != NULL) {
+               escputs((char *)icalproperty_get_categories(p));
+       }
+       wprintf("\">");
+       wprintf("</TD></TR>\n   ");
+       /* end category field */
+       wprintf("<TR><TD>");
+       wprintf(_("Description:"));
+       wprintf("</TD><TD>");
+       wprintf("<TEXTAREA NAME=\"description\" "
+               "ROWS=\"10\" COLS=\"80\">\n"
+               );
+       p = icalcomponent_get_first_property(vtodo, ICAL_DESCRIPTION_PROPERTY);
+       if (p != NULL) {
+               escputs((char *)icalproperty_get_comment(p));
+       }
+       wprintf("</TEXTAREA></TD></TR></TABLE>\n");
+
+       wprintf("<SPAN STYLE=\"text-align: center;\">"
+               "<INPUT TYPE=\"submit\" NAME=\"save_button\" VALUE=\"%s\">"
+               "&nbsp;&nbsp;"
+               "<INPUT TYPE=\"submit\" NAME=\"delete_button\" VALUE=\"%s\">\n"
+               "&nbsp;&nbsp;"
+               "<INPUT TYPE=\"submit\" NAME=\"cancel_button\" VALUE=\"%s\">\n"
+               "</SPAN>\n",
+               _("Save"),
+               _("Delete"),
+               _("Cancel")
+               );
+       wprintf("</td></tr></table>");
+       wprintf("</FORM>\n");
+       wprintf("</div></div></div>\n");
+       wprintf("<!-- end task edit form -->");
+       wDumpContent(1);
+
+       if (created_new_vtodo) {
+               icalcomponent_free(vtodo);
+       }
+}
+
+/*
+ * Save an edited task
+ *
+ * supplied_vtodo      the task to save
+ * msgnum              number of the mesage in our db
+ */
+void save_individual_task(icalcomponent *supplied_vtodo, long msgnum, char* from, int unread,
+                         calview *calv)
+{
+       char buf[SIZ];
+       int delete_existing = 0;
+       icalproperty *prop;
+       icalcomponent *vtodo, *encaps;
+       int created_new_vtodo = 0;
+       int i;
+       int sequence = 0;
+       struct icaltimetype t;
+
+       if (supplied_vtodo != NULL) {
+               vtodo = supplied_vtodo;
+               /**
+                * If we're looking at a fully encapsulated VCALENDAR
+                * rather than a VTODO component, attempt to use the first
+                * relevant VTODO subcomponent.  If there is none, the
+                * NULL returned by icalcomponent_get_first_component() will
+                * tell the next iteration of this function to create a
+                * new one.
+                */
+               if (icalcomponent_isa(vtodo) == ICAL_VCALENDAR_COMPONENT) {
+                       save_individual_task(
+                               icalcomponent_get_first_component(
+                                       vtodo, ICAL_VTODO_COMPONENT), 
+                               msgnum, from, unread, calv
+                               );
+                       return;
+               }
+       }
+       else {
+               vtodo = icalcomponent_new(ICAL_VTODO_COMPONENT);
+               created_new_vtodo = 1;
+       }
+
+       if (havebstr("save_button")) {
+
+               /** Replace values in the component with ones from the form */
+
+               while (prop = icalcomponent_get_first_property(vtodo,
+                                                              ICAL_SUMMARY_PROPERTY), prop != NULL) {
+                       icalcomponent_remove_property(vtodo, prop);
+                       icalproperty_free(prop);
+               }
+               if (havebstr("summary")) {
+
+                       icalcomponent_add_property(vtodo,
+                                                  icalproperty_new_summary(bstr("summary")));
+               } else {
+                       icalcomponent_add_property(vtodo,
+                                                  icalproperty_new_summary(_("Untitled Task")));
+               }
+       
+               while (prop = icalcomponent_get_first_property(vtodo,
+                                                              ICAL_DESCRIPTION_PROPERTY), prop != NULL) {
+                       icalcomponent_remove_property(vtodo, prop);
+                       icalproperty_free(prop);
+               }
+               if (havebstr("description")) {
+                       icalcomponent_add_property(vtodo,
+                                                  icalproperty_new_description(bstr("description")));
+               }
+       
+               while (prop = icalcomponent_get_first_property(vtodo,
+                                                              ICAL_DTSTART_PROPERTY), prop != NULL) {
+                       icalcomponent_remove_property(vtodo, prop);
+                       icalproperty_free(prop);
+               }
+               if (IsEmptyStr(bstr("nodtstart"))) {
+                       if (yesbstr("dtstart_time")) {
+                               icaltime_from_webform(&t, "dtstart");
+                       }
+                       else {
+                               icaltime_from_webform_dateonly(&t, "dtstart");
+                       }
+                       icalcomponent_add_property(vtodo,
+                                                  icalproperty_new_dtstart(t)
+                               );
+               }
+               while(prop = icalcomponent_get_first_property(vtodo,
+                                                             ICAL_STATUS_PROPERTY), prop != NULL) {
+                       icalcomponent_remove_property(vtodo,prop);
+                       icalproperty_free(prop);
+               }
+               while(prop = icalcomponent_get_first_property(vtodo,
+                                                             ICAL_PERCENTCOMPLETE_PROPERTY), prop != NULL) {
+                       icalcomponent_remove_property(vtodo,prop);
+                       icalproperty_free(prop);
+               }
+
+               if (havebstr("status")) {
+                       icalproperty_status taskStatus = icalproperty_string_to_status(bstr("status"));
+                       icalcomponent_set_status(vtodo, taskStatus);
+                       icalcomponent_add_property(vtodo,
+                               icalproperty_new_percentcomplete(
+                                       (strcasecmp(bstr("status"), "completed") ? 0 : 100)
+                               )
+                       );
+               }
+               else {
+                       icalcomponent_add_property(vtodo, icalproperty_new_percentcomplete(0));
+               }
+               while (prop = icalcomponent_get_first_property(vtodo,
+                                                              ICAL_CATEGORIES_PROPERTY), prop != NULL) {
+                       icalcomponent_remove_property(vtodo,prop);
+                       icalproperty_free(prop);
+               }
+               if (!IsEmptyStr(bstr("category"))) {
+                       prop = icalproperty_new_categories(bstr("category"));
+                       icalcomponent_add_property(vtodo,prop);
+               }
+               while (prop = icalcomponent_get_first_property(vtodo,
+                                                              ICAL_DUE_PROPERTY), prop != NULL) {
+                       icalcomponent_remove_property(vtodo, prop);
+                       icalproperty_free(prop);
+               }
+               if (IsEmptyStr(bstr("nodue"))) {
+                       if (yesbstr("due_time")) {
+                               icaltime_from_webform(&t, "due");
+                       }
+                       else {
+                               icaltime_from_webform_dateonly(&t, "due");
+                       }
+                       icalcomponent_add_property(vtodo,
+                                                  icalproperty_new_due(t)
+                               );
+               }
+               /** Give this task a UID if it doesn't have one. */
+               lprintf(9, "Give this task a UID if it doesn't have one.\n");
+               if (icalcomponent_get_first_property(vtodo,
+                                                    ICAL_UID_PROPERTY) == NULL) {
+                       generate_uuid(buf);
+                       icalcomponent_add_property(vtodo,
+                                                  icalproperty_new_uid(buf)
+                               );
+               }
+
+               /* Increment the sequence ID */
+               lprintf(9, "Increment the sequence ID\n");
+               while (prop = icalcomponent_get_first_property(vtodo,
+                                                              ICAL_SEQUENCE_PROPERTY), (prop != NULL) ) {
+                       i = icalproperty_get_sequence(prop);
+                       lprintf(9, "Sequence was %d\n", i);
+                       if (i > sequence) sequence = i;
+                       icalcomponent_remove_property(vtodo, prop);
+                       icalproperty_free(prop);
+               }
+               ++sequence;
+               lprintf(9, "New sequence is %d.  Adding...\n", sequence);
+               icalcomponent_add_property(vtodo,
+                                          icalproperty_new_sequence(sequence)
+                       );
+
+               /*
+                * Encapsulate event into full VCALENDAR component.  Clone it first,
+                * for two reasons: one, it's easier to just free the whole thing
+                * when we're done instead of unbundling, but more importantly, we
+                * can't encapsulate something that may already be encapsulated
+                * somewhere else.
+                */
+               lprintf(9, "Encapsulating into a full VCALENDAR component\n");
+               encaps = ical_encapsulate_subcomponent(icalcomponent_new_clone(vtodo));
+
+               /* Serialize it and save it to the message base */
+               serv_puts("ENT0 1|||4");
+               serv_getln(buf, sizeof buf);
+               if (buf[0] == '4') {
+                       serv_puts("Content-type: text/calendar");
+                       serv_puts("");
+                       serv_puts(icalcomponent_as_ical_string(encaps));
+                       serv_puts("000");
+
+                       /*
+                        * Probably not necessary; the server will see the UID
+                        * of the object and delete the old one anyway, but
+                        * just in case...
+                        */
+                       delete_existing = 1;
+               }
+               icalcomponent_free(encaps);
+       }
+
+       /**
+        * If the user clicked 'Delete' then explicitly delete the message.
+        */
+       if (havebstr("delete_button")) {
+               delete_existing = 1;
+       }
+
+       if ( (delete_existing) && (msgnum > 0L) ) {
+               serv_printf("DELE %ld", lbstr("msgnum"));
+               serv_getln(buf, sizeof buf);
+       }
+
+       if (created_new_vtodo) {
+               icalcomponent_free(vtodo);
+       }
+
+       /* Go back to wherever we came from */
+       if (ibstr("return_to_summary") == 1) {
+               summary();
+       }
+       else {
+               readloop(readfwd);
+       }
+}
+
+/*
+ * Display task view
+ */
+int tasks_LoadMsgFromServer(SharedMessageStatus *Stat, 
+                           void **ViewSpecific, 
+                           message_summary* Msg, 
+                           int is_new, 
+                           int i)
+{
+       /* Not (yet?) needed here? calview *c = (calview *) *ViewSpecific; */
+
+       load_ical_object(Msg->msgnum, is_new, ICAL_VTODO_COMPONENT, display_individual_cal, NULL, 0);
+       return 0;
+}
+
+/*
+ * Display the editor component for a task
+ */
+void display_edit_task(void) {
+       long msgnum = 0L;
+                       
+       /* Force change the room if we have to */
+       if (havebstr("taskrm")) {
+               gotoroom(sbstr("taskrm"));
+       }
+
+       msgnum = lbstr("msgnum");
+       if (msgnum > 0L) {
+               /* existing task */
+               load_ical_object(msgnum, 0,
+                                ICAL_VTODO_COMPONENT,
+                                display_edit_individual_task,
+                                NULL, 0
+               );
+       }
+       else {
+               /* new task */
+               display_edit_individual_task(NULL, 0L, "", 0, NULL);
+       }
+}
+
+/*
+ * save an edited task
+ */
+void save_task(void) {
+       long msgnum = 0L;
+       msgnum = lbstr("msgnum");
+       if (msgnum > 0L) {
+               load_ical_object(msgnum, 0, ICAL_VTODO_COMPONENT, save_individual_task, NULL, 0);
+       }
+       else {
+               save_individual_task(NULL, 0L, "", 0, NULL);
+       }
+}
+
+
+
+int tasks_GetParamsGetServerCall(SharedMessageStatus *Stat, 
+                                void **ViewSpecific, 
+                                long oper, 
+                                char *cmd, 
+                                long len)
+{
+       strcpy(cmd, "MSGS ALL");
+       Stat->maxmsgs = 32767;
+       return 200;
+}
+
+
+int tasks_Cleanup(void **ViewSpecific)
+{
+       end_burst();
+/* Tasks doesn't need the calview struct... 
+       free (*ViewSpecific);
+       *ViewSpecific = NULL;
+       */
+       return 0;
+}
+
+void 
+InitModule_TASKS
+(void)
+{
+       RegisterReadLoopHandlerset(
+               VIEW_TASKS,
+               tasks_GetParamsGetServerCall,
+               NULL,
+               tasks_LoadMsgFromServer,
+               tasks_RenderView_or_Tail,
+               tasks_Cleanup);
+       WebcitAddUrlHandler(HKEY("save_task"), save_task, 0);
+}
index 1396fdebcccc8dae409b69d712a3e8b59e875d8a..7d0c6cc8f74167fa046fe37dbcc315c68be29dd5 100644 (file)
@@ -419,12 +419,15 @@ long locate_user_vcard_in_this_room(message_summary **VCMsg, wc_mime_attachment
        int already_tried_creating_one = 0;
        StrBuf *FoundCharset = NewStrBuf();
        StrBuf *Error = NULL;
+       SharedMessageStatus Stat;
+
 
        Buf = NewStrBuf();
 TRYAGAIN:
+       memset(&Stat, 0, sizeof(SharedMessageStatus));
        Done = 0;
        /* Search for the user's vCard */
-       if (load_msg_ptrs("MSGS ALL||||1", 1, NULL, NULL) > 0) {
+       if (load_msg_ptrs("MSGS ALL||||1", &Stat) > 0) {
                at = GetNewHashPos(WCC->summ, 0);
                while (GetNextHashPos(WCC->summ, at, &HKLen, &HashKey, &vMsg)) {
                        Msg = (message_summary*) vMsg;          
index e05bb11c20c13669cebc61583f2a57a067b8c543..11a059b87ff557ab743fe8a5f5c4695e848a67d8 100644 (file)
@@ -3,7 +3,7 @@
  */
 
 #include "webcit.h"
-
+#include "calendar.h"
 
 /*
  * Record compare function for sorting address book indices
@@ -1241,12 +1241,102 @@ void display_vcard_photo_img(void)
        free(photosrc);
 }
 
+typedef struct _vcardview_struct {
+       long is_singlecard;
+       addrbookent *addrbook;
+       long num_ab;
+
+} vcardview_struct;
+
+int vcard_GetParamsGetServerCall(SharedMessageStatus *Stat, 
+                                void **ViewSpecific, 
+                                long oper, 
+                                char *cmd, 
+                                long len)
+{
+       vcardview_struct *VS;
+
+       VS = (vcardview_struct*) malloc (sizeof(vcardview_struct));
+       memset(VS, 0, sizeof(vcardview_struct));
+       *ViewSpecific = (void*)VS;
+
+       VS->is_singlecard = ibstr("is_singlecard");
+       if (VS->is_singlecard != 1) {
+               if (oper == do_search) {
+                       snprintf(cmd, len, "MSGS SEARCH|%s", bstr("query"));
+               }
+               else {
+                       strcpy(cmd, "MSGS ALL");
+               }
+               Stat->maxmsgs = 9999999;
+       }
+       return 200;
+}
+
+int vcard_LoadMsgFromServer(SharedMessageStatus *Stat, 
+                           void **ViewSpecific, 
+                           message_summary* Msg, 
+                           int is_new, 
+                           int i)
+{
+       vcardview_struct *VS;
+       char *ab_name;
+
+       VS = (vcardview_struct*) *ViewSpecific;
+
+       ab_name = NULL;
+       fetch_ab_name(Msg, &ab_name);
+       if (ab_name == NULL) 
+               return 0;
+       ++VS->num_ab;
+       VS->addrbook = realloc(VS->addrbook,
+                              (sizeof(addrbookent) * VS->num_ab) );
+       safestrncpy(VS->addrbook[VS->num_ab-1].ab_name, ab_name,
+                   sizeof(VS->addrbook[VS->num_ab-1].ab_name));
+       VS->addrbook[VS->num_ab-1].ab_msgnum = Msg->msgnum;
+       free(ab_name);
+       return 0;
+}
+
 
+int vcard_RenderView_or_Tail(SharedMessageStatus *Stat, void **ViewSpecific, long oper)
+{
+       const StrBuf *Mime;
+       vcardview_struct *VS;
+
+       VS = (vcardview_struct*) *ViewSpecific;
+       if (VS->is_singlecard)
+               read_message(WC->WBuf, HKEY("view_message"), lbstr("startmsg"), NULL, &Mime);
+       else
+               do_addrbook_view(VS->addrbook, VS->num_ab);     /* Render the address book */
+       return 0;
+}
+
+int vcard_Cleanup(void **ViewSpecific)
+{
+       vcardview_struct *VS;
+
+       VS = (vcardview_struct*) *ViewSpecific;
+       end_burst();
+       if ((VS != NULL) && 
+           (VS->addrbook != NULL))
+               free(VS->addrbook);
+       if (VS != NULL) 
+               free(VS);
+       return 0;
+}
 
 void 
 InitModule_VCARD
 (void)
 {
+       RegisterReadLoopHandlerset(
+               VIEW_ADDRESSBOOK,
+               vcard_GetParamsGetServerCall,
+               NULL,
+               vcard_LoadMsgFromServer,
+               vcard_RenderView_or_Tail,
+               vcard_Cleanup);
        WebcitAddUrlHandler(HKEY("edit_vcard"), edit_vcard, 0);
        WebcitAddUrlHandler(HKEY("submit_vcard"), submit_vcard, 0);
        WebcitAddUrlHandler(HKEY("vcardphoto"), display_vcard_photo_img, NEED_URL);
index 7b3d90c28d160f7ac9c360fbe1f9f4b52f104659..da0e0c717b24f11bb70370e68d15b78cbdf8a741 100644 (file)
@@ -91,7 +91,6 @@
 #include "paramhandling.h"
 #include "preferences.h"
 
-
 #ifdef HAVE_OPENSSL
 /* Work around RedHat's b0rken OpenSSL includes */
 #define OPENSSL_NO_KRB5
@@ -581,27 +580,6 @@ enum {
 };
 
 
-/*
- * calview contains data passed back and forth between the message fetching loop
- * and the calendar view renderer.
- */
-enum {
-       calview_month,
-       calview_day,
-       calview_week,
-       calview_brief,
-       calview_summary
-};
-
-struct calview {
-       int view;
-       int year;
-       int month;
-       int day;
-       time_t lower_bound;
-       time_t upper_bound;
-};
-
 #ifndef num_parms
 #define num_parms(source)              num_tokens(source, '|') 
 #endif
@@ -785,13 +763,9 @@ void output_html(const char *, int, int, StrBuf *, StrBuf *);
 void do_listsub(void);
 ssize_t write(int fd, const void *buf, size_t count);
 void cal_process_attachment(wc_mime_attachment *Mime);
-void load_calendar_item(message_summary *Msg, int unread, struct calview *c);
 void display_calendar(message_summary *Msg, int unread);
-void display_task(message_summary *Msg, int unread);
 void display_note(message_summary *Msg, int unread);
 void updatenote(void);
-void parse_calendar_view_request(struct calview *c);
-void render_calendar_view(struct calview *c);
 void do_tasks_view(void);
 int calendar_summary_view(void);
 void free_march_list(wcsession *wcf);
@@ -813,11 +787,6 @@ icaltimezone *get_default_icaltimezone(void);
 void display_icaltimetype_as_webform(struct icaltimetype *, char *, int);
 void icaltime_from_webform(struct icaltimetype *result, char *prefix);
 void icaltime_from_webform_dateonly(struct icaltimetype *result, char *prefix);
-void display_edit_individual_event(icalcomponent *supplied_vtodo, long msgnum, char *from,
-       int unread, struct calview *calv);
-void save_individual_event(icalcomponent *supplied_vtodo, long msgnum, char *from,
-       int unread, struct calview *calv);
-void ical_dezonify(icalcomponent *cal);
 void partstat_as_string(char *buf, icalproperty *attendee);
 icalcomponent *ical_encapsulate_subcomponent(icalcomponent *subcomp);
 void check_attendee_availability(icalcomponent *supplied_vevent);
@@ -902,7 +871,6 @@ extern char *hourname[];    /* Names of hours (12am, 1am, etc.) */
 
 void http_datestring(char *buf, size_t n, time_t xtime);
 
-typedef void (*IcalCallbackFunc)(icalcomponent *, long, char*, int, struct calview *);
 
 /* These should be empty, but we have them for testing */
 #define DEFAULT_HTTPAUTH_USER  ""
index ca904d1a483ae727bf6534be308cbad515b4d931..efc3c88902a9b19bbe5bb264799f3b118ae5e546 100644 (file)
@@ -99,10 +99,33 @@ void display_wiki_page(void)
        wDumpContent(1);
 }
 
+int wiki_GetParamsGetServerCall(SharedMessageStatus *Stat, 
+                                          void **ViewSpecific, 
+                                          long oper, 
+                                          char *cmd, 
+                                          long len)
+{
+       char buf[SIZ];
+       sprintf(buf, "wiki?room=%s&page=home", ChrPtr(WC->wc_roomname));
+       http_redirect(buf);
+       return 300;
+}
+
 void 
 InitModule_WIKI
 (void)
 {
+       RegisterReadLoopHandlerset(
+               VIEW_WIKI,
+               wiki_GetParamsGetServerCall,
+               NULL,
+               NULL,
+               NULL,
+               NULL
+               );
+
        WebcitAddUrlHandler(HKEY("wiki"), display_wiki_page, 0);
        return ;
 }
+
+