]> code.citadel.org Git - citadel.git/blobdiff - webcit/messages.c
* Add text/calendar to the MSGP list. Also added some DLAT debugging.
[citadel.git] / webcit / messages.c
index 3291e45ac3fc4a0f9c9219e6865fc2b39936e3e5..96510d1883e2bd04b1a7db12da708306b8b90e8b 100644 (file)
@@ -12,6 +12,7 @@
 HashList *MsgHeaderHandler = NULL;
 HashList *MsgEvaluators = NULL;
 HashList *MimeRenderHandler = NULL;
+int analyze_msg = 0;
 
 #define SUBJ_COL_WIDTH_PCT             50      /**< Mailbox view column width */
 #define SENDER_COL_WIDTH_PCT           30      /**< Mailbox view column width */
@@ -33,6 +34,9 @@ int summcmp_rdate(const void *s1, const void *s2);
 
 typedef void (*MsgPartEvaluatorFunc)(message_summary *Sum, StrBuf *Buf);
 
+typedef struct _MsgPartEvaluatorStruct {
+       MsgPartEvaluatorFunc f;
+}MsgPartEvaluatorStruct;
 
 
 /*----------------------------------------------------------------------------*/
@@ -60,6 +64,7 @@ int read_message(StrBuf *Target, const char *tmpl, long tmpllen, long msgnum, in
        int state=0;
        long len;
        const char *Key;
+       WCTemplputParams SubTP;
 
        Buf = NewStrBuf();
        lprintf(1, "----------%s---------MSG4 %ld|%s--------------\n", tmpl, msgnum, ChrPtr(PartNum));
@@ -109,7 +114,9 @@ int read_message(StrBuf *Target, const char *tmpl, long tmpllen, long msgnum, in
                        StrBufExtract_token(HdrToken, Buf, 0, '=');
                        StrBufCutLeft(Buf, StrLength(HdrToken) + 1);
                        
-                       lprintf(1, ":: [%s] = [%s]\n", ChrPtr(HdrToken), ChrPtr(Buf));
+#ifdef TECH_PREVIEW
+                       if (analyze_msg) lprintf(1, ":: [%s] = [%s]\n", ChrPtr(HdrToken), ChrPtr(Buf));
+#endif
                        /* look up one of the examine_* functions to parse the content */
                        if (GetHash(MsgHeaderHandler, SKEY(HdrToken), &vHdr) &&
                            (vHdr != NULL)) {
@@ -134,7 +141,9 @@ int read_message(StrBuf *Target, const char *tmpl, long tmpllen, long msgnum, in
                                StrBufExtract_token(HdrToken, Buf, 0, ':');
                                if (StrLength(HdrToken) > 0) {
                                        StrBufCutLeft(Buf, StrLength(HdrToken) + 1);
-                                       lprintf(1, ":: [%s] = [%s]\n", ChrPtr(HdrToken), ChrPtr(Buf));
+#ifdef TECH_PREVIEW
+                                       if (analyze_msg) lprintf(1, ":: [%s] = [%s]\n", ChrPtr(HdrToken), ChrPtr(Buf));
+#endif
                                        /* the examine*'s know how to do with mime headers too... */
                                        if (GetHash(MsgHeaderHandler, SKEY(HdrToken), &vHdr) &&
                                            (vHdr != NULL)) {
@@ -149,7 +158,7 @@ int read_message(StrBuf *Target, const char *tmpl, long tmpllen, long msgnum, in
                        if (Msg->MsgBody->size_known > 0) {
                                StrBuf_ServGetBLOB(Msg->MsgBody->Data, Msg->MsgBody->length);
                                state ++;
-                                       /// todo: check next line, if not 000, append following lines
+                               /*/ todo: check next line, if not 000, append following lines */
                        }
                        else if (1){
                                if (StrLength(Msg->MsgBody->Data) > 0)
@@ -174,9 +183,9 @@ int read_message(StrBuf *Target, const char *tmpl, long tmpllen, long msgnum, in
        /* look up the renderer, that will convert this mimeitem into the htmlized form */
        if (GetHash(MimeRenderHandler, SKEY(Buf), &vHdr) &&
            (vHdr != NULL)) {
-               RenderMimeFunc Render;
-               Render = (RenderMimeFunc)vHdr;
-               Render(Msg->MsgBody, NULL, FoundCharset);
+               RenderMimeFuncStruct *Render;
+               Render = (RenderMimeFuncStruct*)vHdr;
+               Render->f(Msg->MsgBody, NULL, FoundCharset);
        }
 
        if (StrLength(Msg->reply_references)> 0) {
@@ -205,8 +214,8 @@ int read_message(StrBuf *Target, const char *tmpl, long tmpllen, long msgnum, in
        else 
        {
                if ((StrLength(Msg->OtherNode)>0) && 
-                   (strcasecmp(ChrPtr(Msg->OtherNode), serv_info.serv_nodename)) &&
-                   (strcasecmp(ChrPtr(Msg->OtherNode), serv_info.serv_humannode)) ) 
+                   (strcasecmp(ChrPtr(Msg->OtherNode), ChrPtr(serv_info.serv_nodename))) &&
+                   (strcasecmp(ChrPtr(Msg->OtherNode), ChrPtr(serv_info.serv_humannode)) ))
                {
                        if (Msg->reply_to == NULL)
                                Msg->reply_to = NewStrBuf();
@@ -231,8 +240,10 @@ int read_message(StrBuf *Target, const char *tmpl, long tmpllen, long msgnum, in
                evaluate_mime_part(Msg, Mime);
        }
        DeleteHashPos(&it);
-
-       DoTemplate(tmpl, tmpllen, Target, Msg, CTX_MAILSUM);
+       memset(&SubTP, 0, sizeof(WCTemplputParams));
+       SubTP.ContextType = CTX_MAILSUM;
+       SubTP.Context = Msg;
+       DoTemplate(tmpl, tmpllen, Target, &SubTP);
 
        DestroyMessageSummary(Msg);
        FreeStrBuf(&FoundCharset);
@@ -331,7 +342,7 @@ void display_headers(void) {
 message_summary *ReadOneMessageSummary(StrBuf *RawMessage, const char *DefaultSubject, long MsgNum) 
 {
        void                 *vEval;
-       MsgPartEvaluatorFunc  Eval;
+       MsgPartEvaluatorStruct  *Eval;
        message_summary      *Msg;
        StrBuf *Buf;
        const char *buf;
@@ -358,9 +369,9 @@ message_summary *ReadOneMessageSummary(StrBuf *RawMessage, const char *DefaultSu
                ebuf = strchr(ChrPtr(Buf), '=');
                nBuf = ebuf - buf;
                if (GetHash(MsgEvaluators, buf, nBuf, &vEval) && vEval != NULL) {
-                       Eval = (MsgPartEvaluatorFunc) vEval;
+                       Eval = (MsgPartEvaluatorStruct*) vEval;
                        StrBufCutLeft(Buf, nBuf + 1);
-                       Eval(Msg, Buf);
+                       Eval->f(Msg, Buf);
                }
                else lprintf(1, "Don't know how to handle Message Headerline [%s]", ChrPtr(Buf));
        }
@@ -387,6 +398,7 @@ int load_msg_ptrs(char *servcmd, int with_headers)
        int maxload = 0;
        long len;
        int n;
+       int skipit;
 
        if (WCC->summ != NULL) {
                if (WCC->summ != NULL)
@@ -402,59 +414,69 @@ int load_msg_ptrs(char *servcmd, int with_headers)
                FreeStrBuf(&Buf);
                return (nummsgs);
        }
-// TODO                        if (with_headers) { //// TODO: Have Attachments?
        Buf2 = NewStrBuf();
        while (len = StrBuf_ServGetln(Buf),
               ((len != 3)  ||
                strcmp(ChrPtr(Buf), "000")!= 0))
        {
                if (nummsgs < maxload) {
+                       skipit = 0;
                        Msg = (message_summary*)malloc(sizeof(message_summary));
                        memset(Msg, 0, sizeof(message_summary));
 
                        Msg->msgnum = StrBufExtract_long(Buf, 0, '|');
                        Msg->date = StrBufExtract_long(Buf, 1, '|');
-
-                       Msg->from = NewStrBufPlain(NULL, StrLength(Buf));
-                       StrBufExtract_token(Buf2, Buf, 2, '|');
-                       if (StrLength(Buf2) != 0) {
-                               /** Handle senders with RFC2047 encoding */
-                               StrBuf_RFC822_to_Utf8(Msg->from, Buf2, WCC->DefaultCharset, FoundCharset);
+                       /* 
+                        * as citserver probably gives us messages in forward date sorting
+                        * nummsgs should be the same order as the message date.
+                        */
+                       if (Msg->date == 0) {
+                               Msg->date = nummsgs;
+                               if (StrLength(Buf) < 32) 
+                                       skipit = 1;
                        }
+                       if (!skipit) {
+                               Msg->from = NewStrBufPlain(NULL, StrLength(Buf));
+                               StrBufExtract_token(Buf2, Buf, 2, '|');
+                               if (StrLength(Buf2) != 0) {
+                                       /** Handle senders with RFC2047 encoding */
+                                       StrBuf_RFC822_to_Utf8(Msg->from, Buf2, WCC->DefaultCharset, FoundCharset);
+                               }
                        
-                       /** Nodename */
-                       StrBufExtract_token(Buf2, Buf, 3, '|');
-                       if ((StrLength(Buf2) !=0 ) &&
-                           ( ((WCC->room_flags & QR_NETWORK)
-                              || ((strcasecmp(ChrPtr(Buf2), serv_info.serv_nodename)
-                                   && (strcasecmp(ChrPtr(Buf2), serv_info.serv_fqdn)))))))
-                       {
-                               StrBufAppendBufPlain(Msg->from, HKEY(" @ "), 0);
-                               StrBufAppendBuf(Msg->from, Buf2, 0);
-                       }
+                               /** Nodename */
+                               StrBufExtract_token(Buf2, Buf, 3, '|');
+                               if ((StrLength(Buf2) !=0 ) &&
+                                   ( ((WCC->room_flags & QR_NETWORK)
+                                      || ((strcasecmp(ChrPtr(Buf2), ChrPtr(serv_info.serv_nodename))
+                                           && (strcasecmp(ChrPtr(Buf2), ChrPtr(serv_info.serv_fqdn))))))))
+                               {
+                                       StrBufAppendBufPlain(Msg->from, HKEY(" @ "), 0);
+                                       StrBufAppendBuf(Msg->from, Buf2, 0);
+                               }
 
-                       /** Not used:
-                       StrBufExtract_token(Msg->inetaddr, Buf, 4, '|');
-                       */
+                               /** Not used:
+                                   StrBufExtract_token(Msg->inetaddr, Buf, 4, '|');
+                               */
 
-                       Msg->subj = NewStrBufPlain(NULL, StrLength(Buf));
-                       StrBufExtract_token(Buf2,  Buf, 5, '|');
-                       if (StrLength(Buf2) == 0)
-                               StrBufAppendBufPlain(Msg->subj, _("(no subj)"), -1,0);
-                       else {
-                               StrBuf_RFC822_to_Utf8(Msg->subj, Buf2, WCC->DefaultCharset, FoundCharset);
-                               if ((StrLength(Msg->subj) > 75) && 
-                                   (StrBuf_Utf8StrLen(Msg->subj) > 75)) {
-                                       StrBuf_Utf8StrCut(Msg->subj, 72);
-                                       StrBufAppendBufPlain(Msg->subj, HKEY("..."), 0);
+                               Msg->subj = NewStrBufPlain(NULL, StrLength(Buf));
+                               StrBufExtract_token(Buf2,  Buf, 5, '|');
+                               if (StrLength(Buf2) == 0)
+                                       StrBufAppendBufPlain(Msg->subj, _("(no subj)"), -1,0);
+                               else {
+                                       StrBuf_RFC822_to_Utf8(Msg->subj, Buf2, WCC->DefaultCharset, FoundCharset);
+                                       if ((StrLength(Msg->subj) > 75) && 
+                                           (StrBuf_Utf8StrLen(Msg->subj) > 75)) {
+                                               StrBuf_Utf8StrCut(Msg->subj, 72);
+                                               StrBufAppendBufPlain(Msg->subj, HKEY("..."), 0);
+                                       }
                                }
-                       }
 
 
-                       if ((StrLength(Msg->from) > 25) && 
-                           (StrBuf_Utf8StrLen(Msg->from) > 25)) {
-                               StrBuf_Utf8StrCut(Msg->from, 23);
-                               StrBufAppendBufPlain(Msg->from, HKEY("..."), 0);
+                               if ((StrLength(Msg->from) > 25) && 
+                                   (StrBuf_Utf8StrLen(Msg->from) > 25)) {
+                                       StrBuf_Utf8StrCut(Msg->from, 23);
+                                       StrBufAppendBufPlain(Msg->from, HKEY("..."), 0);
+                               }
                        }
                        n = Msg->msgnum;
                        Put(WCC->summ, (const char *)&n, sizeof(n), Msg, DestroyMessageSummary);
@@ -480,78 +502,83 @@ inline message_summary* GetMessagePtrAt(int n, HashList *Summ)
 }
 
 
-long DrawMessageDropdown(StrBuf *Selector, long maxmsgs, long startmsg)
+long DrawMessageDropdown(StrBuf *Selector, long maxmsgs, long startmsg, int nMessages)
 {
        StrBuf *TmpBuf;
        wcsession *WCC = WC;
-       message_summary* Msg;
-       int lo, hi, n;
-       int i = 0;
-       long StartMsg = 0;
-       long ret;
        void *vMsg;
+       int lo, hi;
+       long ret;
        long hklen;
        const char *key;
        int done = 0;
        int nItems;
        HashPos *At;
        long vector[16];
-       int nMessages = (lbstr("SortOrder") == 1)? DEFAULT_MAXMSGS : -DEFAULT_MAXMSGS;
+       WCTemplputParams SubTP;
 
+       memset(&SubTP, 0, sizeof(WCTemplputParams));
+       SubTP.ContextType = CTX_LONGVECTOR;
+       SubTP.Context = &vector;
        TmpBuf = NewStrBuf();
        At = GetNewHashPos(WCC->summ, nMessages);
        nItems = GetCount(WCC->summ);
-       ret = abs(nMessages);
+       ret = nMessages;
        vector[0] = 7;
+       vector[2] = 1;
        vector[1] = startmsg;
-       vector[2] = maxmsgs;
        vector[3] = 0;
-       vector[4] = 1;
 
        while (!done) {
+               vector[3] = abs(nMessages);
                lo = GetHashPosCounter(At);
                if (nMessages > 0) {
-                       if (lo + nMessages > nItems) {
-                               hi = nItems;
+                       if (lo + nMessages >= nItems) {
+                               hi = nItems - 1;
+                               vector[3] = nItems - lo;
+                               if (startmsg == lo) 
+                                       ret = vector[3];
                        }
                        else {
-                               hi = lo + nMessages;
+                               hi = lo + nMessages - 1;
                        }
                } else {
-                       if (lo + nMessages <= 0) {
-                               hi = 1;
+                       if (lo + nMessages < -1) {
+                               hi = 0;
                        }
                        else {
-                               if (lo % abs(nMessages) != 0)
-                                       hi = lo + (lo % abs(nMessages) *
-                                                   (nMessages / abs(nMessages)));
+                               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);
-               Msg = (message_summary*) vMsg;
-               n = (Msg==NULL)? 0 : Msg->msgnum;
-               if (i == 0)
-                       StartMsg = n;
-               if ((vector[1] == n) && (lo - hi + 1 != nMessages)) {
-                       ret = abs(lo - hi + 1);
-               }
+               
+               /**
+                * 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;
-               vector[6] = n;
+               vector[5] = hi + 1;
+               vector[6] = lo;
                FlushStrBuf(TmpBuf);
                dbg_print_longvector(vector);
-               DoTemplate(HKEY("select_messageindex"), TmpBuf, &vector, CTX_LONGVECTOR);
+               DoTemplate(HKEY("select_messageindex"), TmpBuf, &SubTP);
                StrBufAppendBuf(Selector, TmpBuf, 0);
-               i++;
        }
-       vector[6] = StartMsg;
+       vector[6] = 0;
        FlushStrBuf(TmpBuf);
        vector[1] = lbstr("maxmsgs") == 9999999;
        vector[2] = 0;
        dbg_print_longvector(vector);
-       DoTemplate(HKEY("select_messageindex_all"), TmpBuf, &vector, CTX_LONGVECTOR);
+       DoTemplate(HKEY("select_messageindex_all"), TmpBuf, &SubTP);
        StrBufAppendBuf(Selector, TmpBuf, 0);
        FreeStrBuf(&TmpBuf);
        DeleteHashPos(&At);
@@ -563,14 +590,15 @@ void load_seen_flags(void)
        message_summary *Msg;
        const char *HashKey;
        long HKLen;
-       StrBuf *OldMsg = NewStrBuf();;
-       wcsession *WCC = WC;
        HashPos *at;
        void *vMsg;
+       StrBuf *OldMsg;
+       wcsession *WCC = WC;
 
+       OldMsg = NewStrBuf();
        serv_puts("GTSN");
        StrBuf_ServGetln(OldMsg);
-       if (ChrPtr(OldMsg)[0] == '2') {
+       if (GetServerStatus(OldMsg, NULL) == 2) {
                StrBufCutLeft(OldMsg, 4);
        }
        else {
@@ -608,16 +636,15 @@ void readloop(long oper)
        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_summary = 0;
        int is_singlecard = 0;
        struct calview calv;
-
-       int is_bbview = 0;
+       int i;
        int lowest_displayed = (-1);
        int highest_displayed = 0;
        addrbookent *addrbook = NULL;
@@ -630,12 +657,18 @@ void readloop(long oper)
        int care_for_empty_list = 0;
        int load_seen = 0;
        int sortit = 0;
+       int defaultsortorder = 0;
+       WCTemplputParams SubTP;
+
+       if (havebstr("is_summary") && (1 == (ibstr("is_summary"))))
+               WCC->wc_view = VIEW_MAILBOX;
 
        switch (WCC->wc_view) {
        case VIEW_WIKI:
-               sprintf(buf, "wiki?room=%s&page=home", WCC->wc_roomname);
+               sprintf(buf, "wiki?room=%s&page=home", ChrPtr(WCC->wc_roomname));
                http_redirect(buf);
                return;
+       case VIEW_CALBRIEF:
        case VIEW_CALENDAR:
                load_seen = 1;
                strcpy(cmd, "MSGS ALL|||1");
@@ -664,65 +697,41 @@ void readloop(long oper)
                        break;
                }
                break;
+       case VIEW_MAILBOX: 
+               defaultsortorder = 2;
+               sortit = 1;
+               load_seen = 1;
+               care_for_empty_list = 1;
+               with_headers = 1;
+               if (WCC->is_mobile) maxmsgs = 20;
+               else maxmsgs = 9999999;
+               snprintf(cmd, sizeof(cmd), "MSGS %s|%s||1",
+                        (oper == do_search) ? "SEARCH" : "ALL",
+                        (oper == do_search) ? bstr("query") : ""
+                       );
+               break;
+       case VIEW_BBS:
        default:
+               defaultsortorder = 1;
+               startmsg = -1;
+               sortit = 1;
                care_for_empty_list = 1;
-               startmsg = lbstr("startmsg");
-               if (havebstr("maxmsgs"))
-                       maxmsgs = ibstr("maxmsgs");
-               is_summary = (ibstr("is_summary") && !WCC->is_mobile);
-               if (maxmsgs == 0) maxmsgs = DEFAULT_MAXMSGS;
-               
 
-               
-                /*
-                * When in summary mode, always show ALL messages instead of just
-                * new or old.  Otherwise, show what the user asked for.
-                */
                rlid[oper].cmd(cmd, sizeof(cmd));
-               
-               if ((WCC->wc_view == VIEW_MAILBOX) && (maxmsgs > 1) && !WCC->is_mobile) {
-                       is_summary = 1;
-                       if (oper != do_search) {
-                               strcpy(cmd, "MSGS ALL");
-                       }
-               }
+               SetAccessCommand(oper);
 
-               is_bbview = !is_summary;
-               if (is_summary) {                       /**< fetch header summary */
-                       load_seen = 1;
-                       snprintf(cmd, sizeof(cmd), "MSGS %s|%s||1",
-                                (oper == do_search) ? "SEARCH" : "ALL",
-                                (oper == do_search) ? bstr("query") : ""
-                               );
-                       startmsg = 1;
-                       maxmsgs = 9999999;
-               } 
+               if (havebstr("maxmsgs"))
+                       maxmsgs = ibstr("maxmsgs");
+               if (maxmsgs == 0) maxmsgs = DEFAULT_MAXMSGS;
 
-               if (is_bbview) {
-                       SetAccessCommand(oper);
-                       if (havebstr("SortOrder")) {
-                               bbs_reverse = lbstr("SortOrder") == 2;
-                       }
-                       else {
-                               StrBuf *Buf = NewStrBufPlain(HKEY("1"));
-                               putbstr("SortOrder", Buf);
-                               Buf = NewStrBufPlain(HKEY("date"));
-                               putbstr("SortBy", Buf);
-                               bbs_reverse = 0;
-                       }
-               }
-               sortit = is_summary || WCC->is_mobile;
-               if (WCC->is_mobile) {
-                       maxmsgs = 20;
-                       snprintf(cmd, sizeof(cmd), "MSGS %s|%s||1",
-                                ((oper == do_search) ? "SEARCH" : "ALL"),
-                                ((oper == do_search) ? bstr("query") : "")
-                               );
+               if (havebstr("startmsg")) {
+                       startmsg = lbstr("startmsg");
                }
+               
        }
        output_headers(1, 1, 1, 0, 0, 0);
 
-       nummsgs = load_msg_ptrs(cmd, (is_summary || WCC->is_mobile));
+       nummsgs = load_msg_ptrs(cmd, with_headers);
        if (nummsgs == 0) {
                if (care_for_empty_list) {
                        wprintf("<div align=\"center\"><br /><em>");
@@ -744,49 +753,69 @@ void readloop(long oper)
 
        if (sortit) {
                CompareFunc SortIt;
-               SortIt =  RetrieveSort(CTX_MAILSUM, NULL, 
-                                      HKEY("date"), 2);
+               memset(&SubTP, 0, sizeof(WCTemplputParams));
+               SubTP.ContextType = CTX_NONE;
+               SubTP.Context = NULL;
+               SortIt =  RetrieveSort(&SubTP, NULL, 
+                                      HKEY("date"), defaultsortorder);
                if (SortIt != NULL)
                        SortByPayload(WCC->summ, SortIt);
-       }
-
-       if (is_bbview && (startmsg == 0L)) {
-               if (bbs_reverse) {
-                       Msg = GetMessagePtrAt((nummsgs >= maxmsgs) ? (nummsgs - maxmsgs) : 0, WCC->summ);
-                       startmsg = (Msg==NULL)? 0 : Msg->msgnum;
-               }
-               else {
-                       Msg = GetMessagePtrAt(0, WCC->summ);
-                       startmsg = (Msg==NULL)? 0 : Msg->msgnum;
+               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 (load_seen) load_seen_flags();
-       if (is_summary) do_template("summary_header", NULL);
        
-
         /**
-        * If we're not currently looking at ALL requested
-        * messages, then display the selector bar
+        * If we're to print s.th. above the message list...
         */
-       if (is_bbview)  {
+       switch (WCC->wc_view) {
+       case VIEW_MAILBOX: 
+               do_template("summary_header", NULL);
+               break;
+       case VIEW_BBS:
                BBViewToolBar = NewStrBuf();
                MessageDropdown = NewStrBuf();
 
-               maxmsgs = DrawMessageDropdown(MessageDropdown, maxmsgs, startmsg);
-               
-               DoTemplate(HKEY("msg_listselector_top"), BBViewToolBar, MessageDropdown, CTX_STRBUF);
+               maxmsgs = DrawMessageDropdown(MessageDropdown, maxmsgs, startmsg, num_displayed);
+               if (num_displayed < 0) {
+                       startmsg += maxmsgs;
+                       if (num_displayed != maxmsgs)                           
+                               maxmsgs = abs(maxmsgs) + 1;
+                       else
+                               maxmsgs = abs(maxmsgs);
+
+               }
+               memset(&SubTP, 0, sizeof(WCTemplputParams));
+               SubTP.ContextType = CTX_STRBUF;
+               SubTP.Context = MessageDropdown;
+               DoTemplate(HKEY("msg_listselector_top"), BBViewToolBar, &SubTP);
                StrBufAppendBuf(WCC->WBuf, BBViewToolBar, 0);
                FlushStrBuf(BBViewToolBar);
+               break;
        }
                        
+       /*
+        * iterate over each message. if we need to load an attachment, do it here. 
+        */
        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)) {                   
+               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;
@@ -805,73 +834,70 @@ void readloop(long oper)
                                            sizeof(addrbook[num_ab-1].ab_name));
                                addrbook[num_ab-1].ab_msgnum = Msg->msgnum;
                                break;
+                       case VIEW_MAILBOX: /* here we just need the abstract, so render it now. */
+                               memset(&SubTP, 0, sizeof(WCTemplputParams));
+                               SubTP.ContextType = CTX_MAILSUM;
+                               SubTP.Context = Msg;
+                               DoTemplate(HKEY("section_mailsummary"), NULL, &SubTP);
+                       
+                               num_displayed++;
+                               break;
+                       case VIEW_BBS: /* Tag the mails we want to show in bbview... */
                        default:
-                               /** Display the message */
-                               if (is_summary) {
-                                       DoTemplate(HKEY("section_mailsummary"), NULL, Msg, CTX_MAILSUM);
+                               if (displayed_msgs == NULL) {
+                                       displayed_msgs = malloc(sizeof(long) *
+                                                               (maxmsgs<nummsgs ? maxmsgs + 1 : nummsgs + 1));
                                }
-                               else {
-                                       if (displayed_msgs == NULL) {
-                                               displayed_msgs = malloc(sizeof(long) *
-                                                                       (maxmsgs<nummsgs ? maxmsgs : nummsgs));
-                                       }
+                               if ((i >= startmsg) && (i < startmsg + maxmsgs)) {
                                        displayed_msgs[num_displayed] = Msg->msgnum;
-                               }
-                       
-                               if (lowest_displayed < 0) lowest_displayed = a;
-                               highest_displayed = a;
+                                       if (lowest_displayed < 0) lowest_displayed = a;
+                                       highest_displayed = a;
                        
-                               num_displayed++;
+                                       num_displayed++;
+                               }
                        }
                }
+               i++;
        }
        DeleteHashPos(&at);
 
-       /** Output loop */
-       if (displayed_msgs != NULL) {
-               if (bbs_reverse) {
-                       ////TODOqsort(displayed_msgs, num_displayed, sizeof(long), qlongcmp_r);
-               }
-
-               /** 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], 0, NULL);
-               }
-
-               /** if we do a split bbview in the future, end messages div here */
-
-               free(displayed_msgs);
-               displayed_msgs = NULL;
-       }
-
-       if (is_summary) {
-               do_template("summary_trailer", NULL);
-       }
-
-       /**
-        * Bump these because although we're thinking in zero base, the user
-        * is a drooling idiot and is thinking in one base.
-        */
-       ++lowest_displayed;
-       ++highest_displayed;
 
-       /**
-        * If we're not currently looking at ALL requested
-        * messages, then display the selector bar
+       /*
+        * Done iterating the message list. now tasks we want to do after.
         */
-       if (is_bbview) {
-               DoTemplate(HKEY("msg_listselector_bottom"), BBViewToolBar, MessageDropdown, CTX_STRBUF);
+       switch (WCC->wc_view) {
+       case VIEW_MAILBOX: 
+               do_template("summary_trailer", NULL);
+               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], 0, NULL);
+                       }
+                       
+                       /** 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.ContextType = CTX_STRBUF;
+               SubTP.Context = MessageDropdown;
+               DoTemplate(HKEY("msg_listselector_bottom"), BBViewToolBar, &SubTP);
                StrBufAppendBuf(WCC->WBuf, BBViewToolBar, 0);
 
                FreeStrBuf(&BBViewToolBar);
                FreeStrBuf(&MessageDropdown);
        }
+
        
 DONE:
        switch (WCC->wc_view) {
        case VIEW_WIKI:
                break;
+       case VIEW_CALBRIEF:
        case VIEW_CALENDAR:
                render_calendar_view(&calv);
                break;
@@ -883,6 +909,8 @@ DONE:
        case VIEW_ADDRESSBOOK:
                do_addrbook_view(addrbook, num_ab);     /** Render the address book */
                break;
+       case VIEW_MAILBOX: 
+       case VIEW_BBS:
        default:
                break;
        }
@@ -916,12 +944,12 @@ void post_mime_to_server(void) {
        char *txtmail = NULL;
 
        sprintf(top_boundary, "Citadel--Multipart--%s--%04x--%04x",
-               serv_info.serv_fqdn,
+               ChrPtr(serv_info.serv_fqdn),
                getpid(),
                ++seq
        );
        sprintf(alt_boundary, "Citadel--Multipart--%s--%04x--%04x",
-               serv_info.serv_fqdn,
+               ChrPtr(serv_info.serv_fqdn),
                getpid(),
                ++seq
        );
@@ -1021,7 +1049,7 @@ void post_message(void)
        wcsession *WCC = WC;
        
        if (havebstr("force_room")) {
-               gotoroom(bstr("force_room"));
+               gotoroom(sbstr("force_room"));
        }
 
        if (havebstr("display_name")) {
@@ -1095,7 +1123,7 @@ void post_message(void)
                const StrBuf *Bcc = NULL;
                const StrBuf *Wikipage = NULL;
                const StrBuf *my_email_addr = NULL;
-               StrBuf *CmdBuf = NULL;;
+               StrBuf *CmdBuf = NULL;
                StrBuf *references = NULL;
 
                if (havebstr("references"))
@@ -1214,7 +1242,7 @@ void display_enter(void)
        now = time(NULL);
 
        if (havebstr("force_room")) {
-               gotoroom(bstr("force_room"));
+               gotoroom(sbstr("force_room"));
        }
 
        display_name = sbstr("display_name");
@@ -1246,7 +1274,7 @@ void display_enter(void)
         * message" command really means "add new entry."
         */
        if (WCC->wc_default_view == VIEW_ADDRESSBOOK) {
-               do_edit_vcard(-1, "", "", WCC->wc_roomname);
+               do_edit_vcard(-1, "", "", ChrPtr(WCC->wc_roomname));
                return;
        }
 
@@ -1278,7 +1306,7 @@ void display_enter(void)
                const StrBuf *Cc = NULL;
                const StrBuf *Bcc = NULL;
                const StrBuf *Wikipage = NULL;
-               StrBuf *CmdBuf = NULL;;
+               StrBuf *CmdBuf = NULL;
                const char CMD[] = "ENT0 0|%s|%d|0||%s||%s|%s|%s";
                
                Recp = sbstr("recp");
@@ -1314,7 +1342,7 @@ void display_enter(void)
                        }
                }
                else if (buf[0] != '2') {       /** Any other error means that we cannot continue */
-                       wprintf("<em>%s</em><br />\n", &buf[4]);/// -> important message
+                       wprintf("<em>%s</em><br />\n", &buf[4]);/*TODO -> important message */
                        return;
                }
        }
@@ -1323,7 +1351,7 @@ void display_enter(void)
 
        begin_burst();
        output_headers(1, 0, 0, 0, 1, 0);
-       DoTemplate(HKEY("edit_message"), NULL, NULL, CTX_NONE);
+       DoTemplate(HKEY("edit_message"), NULL, &NoCtx);
        end_burst();
 
        return;
@@ -1545,9 +1573,11 @@ void MimeLoadData(wc_mime_attachment *Mime)
 {
        char buf[SIZ];
        off_t bytes;
-//// TODO: is there a chance the contenttype is different  to the one we know? 
+/* TODO: is there a chance the contenttype is different  to the one we know?    */
+       lprintf(9, "< DLAT %ld|%s\n", Mime->msgnum, ChrPtr(Mime->PartNum));     // FIXME temporary, remove
        serv_printf("DLAT %ld|%s", Mime->msgnum, ChrPtr(Mime->PartNum));
        serv_getln(buf, sizeof buf);
+       lprintf(9, "> %s\n", buf);                                              // FIXME temporary, remove
        if (buf[0] == '6') {
                bytes = extract_long(&buf[4], 0);
 
@@ -1558,7 +1588,7 @@ void MimeLoadData(wc_mime_attachment *Mime)
        }
        else {
                FlushStrBuf(Mime->Data);
-               /// TODO XImportant message
+               /* TODO XImportant message */
        }
 }
 
@@ -1599,6 +1629,26 @@ void
 InitModule_MSG
 (void)
 {
+       RegisterPreference(HKEY("use_sig"), 
+                          _("Attach signature to email messages?"), 
+                          PRF_YESNO, 
+                          NULL);
+       RegisterPreference(HKEY("signature"), _("Use this signature:"), PRF_QP_STRING, NULL);
+       RegisterPreference(HKEY("default_header_charset"), 
+                          _("Default character set for email headers:"), 
+                          PRF_STRING, 
+                          NULL);
+       RegisterPreference(HKEY("defaultfrom"), _("Preferred email address"), PRF_STRING, NULL);
+       RegisterPreference(HKEY("defaultname"), 
+                          _("Preferred display name for email messages"), 
+                          PRF_STRING, 
+                          NULL);
+       RegisterPreference(HKEY("defaulthandle"), 
+                          _("Preferred display name for bulletin board posts"), 
+                          PRF_STRING, 
+                          NULL);
+       RegisterPreference(HKEY("mailbox"),_("Mailbox view mode"), PRF_STRING, NULL);
+
        WebcitAddUrlHandler(HKEY("readnew"), h_readnew, NEED_URL);
        WebcitAddUrlHandler(HKEY("readold"), h_readold, NEED_URL);
        WebcitAddUrlHandler(HKEY("readfwd"), h_readfwd, NEED_URL);