X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Fmessages.c;h=d4036a13386df7b803d25f1703e1f97fe79a06c1;hb=be00863d58a61c8ee070e346fb0ac70c5b7f6a8e;hp=6ea3c8fc00ff0fcb621283a4ffcd15c4f36bc79f;hpb=1cbc91b714f7fcf7cc564fb3d67c1ca0239cc21f;p=citadel.git
diff --git a/webcit/messages.c b/webcit/messages.c
index 6ea3c8fc0..d4036a133 100644
--- a/webcit/messages.c
+++ b/webcit/messages.c
@@ -13,6 +13,8 @@
#define SENDER_COL_WIDTH_PCT 30 /**< Mailbox view column width */
#define DATE_PLUS_BUTTONS_WIDTH_PCT 20 /**< Mailbox view column width */
+void display_enter(void);
+
/*
* Address book entry (keep it short and sweet, it's just a quickie lookup
* which we can use to get to the real meat and bones later)
@@ -104,10 +106,11 @@ void utf8ify_rfc822_string(char *buf) {
}
}
if (illegal_non_rfc2047_encoding) {
- char default_header_charset[128];
- get_preference("default_header_charset", default_header_charset, sizeof default_header_charset);
- if ( (strcasecmp(default_header_charset, "UTF-8")) && (strcasecmp(default_header_charset, "us-ascii")) ) {
- ic = ctdl_iconv_open("UTF-8", default_header_charset);
+ StrBuf *default_header_charset;
+ get_preference("default_header_charset", &default_header_charset);
+ if ( (strcasecmp(ChrPtr(default_header_charset), "UTF-8")) &&
+ (strcasecmp(ChrPtr(default_header_charset), "us-ascii")) ) {
+ ic = ctdl_iconv_open("UTF-8", ChrPtr(default_header_charset));
if (ic != (iconv_t)(-1) ) {
ibuf = malloc(1024);
isav = ibuf;
@@ -300,14 +303,15 @@ int webcit_rfc2047encode(char *target, int maxlen, char *source, long SourceLen)
if (!need_to_encode) {
memcpy (target, source, SourceLen);
+ target[SourceLen] = '\0';
return SourceLen;
}
if (sizeof (headerStr + SourceLen + 2) > maxlen)
return -1;
memcpy (target, headerStr, sizeof (headerStr));
- len = sizeof (headerStr);
- for (i=0; (i < SourceLen) && (len < maxlen) ; ++i) {
+ len = sizeof (headerStr) - 1;
+ for (i=0; (i < SourceLen) && (len + 3< maxlen) ; ++i) {
ch = (unsigned char) source[i];
if ((ch < 32) || (ch > 126) || (ch == 61)) {
sprintf(&target[len], "=%02X", ch);
@@ -331,20 +335,23 @@ int webcit_rfc2047encode(char *target, int maxlen, char *source, long SourceLen)
-/**
- * \brief Look for URL's embedded in a buffer and make them linkable. We use a
- * target window in order to keep the BBS session in its own window.
- * \param buf the message buffer
+/*
+ * Look for URL's embedded in a buffer and make them linkable. We use a
+ * target window in order to keep the Citadel session in its own window.
*/
-void url(char *buf)
+void url(char *buf, size_t bufsize)
{
- int len;
+ int len, UrlLen, Offset, TrailerLen, outpos;
char *start, *end, *pos;
char urlbuf[SIZ];
- char outbuf[1024];
+ char outbuf[SIZ];
start = NULL;
len = strlen(buf);
+ if (len > bufsize) {
+ lprintf(1, "URL: content longer than buffer!");
+ return;
+ }
end = buf + len;
for (pos = buf; (pos < end) && (start == NULL); ++pos) {
if (!strncasecmp(pos, "http://", 7))
@@ -375,17 +382,35 @@ void url(char *buf)
end = pos;
}
}
+
+ UrlLen = end - start;
+ if (UrlLen > sizeof(urlbuf)){
+ lprintf(1, "URL: content longer than buffer!");
+ return;
+ }
+ memcpy(urlbuf, start, UrlLen);
+ urlbuf[UrlLen] = '\0';
+
+ Offset = start - buf;
+ if ((Offset != 0) && (Offset < sizeof(outbuf)))
+ memcpy(outbuf, buf, Offset);
+ outpos = snprintf(&outbuf[Offset], sizeof(outbuf) - Offset,
+ "%ca href=%c%s%c TARGET=%c%s%c%c%s%c/A%c",
+ LB, QU, urlbuf, QU, QU, TARGET, QU, RB, urlbuf, LB, RB);
+ if (outpos >= sizeof(outbuf) - Offset) {
+ lprintf(1, "URL: content longer than buffer!");
+ return;
+ }
- strncpy(urlbuf, start, end - start);
- urlbuf[end - start] = '\0';
-
- if (start != buf)
- strncpy(outbuf, buf, start - buf );
- sprintf(&outbuf[start-buf], "%ca href=%c%s%c TARGET=%c%s%c%c%s%c/A%c",
- LB, QU, urlbuf, QU, QU, TARGET, QU, RB, urlbuf, LB, RB);
- strcat(outbuf, end);
- if ( strlen(outbuf) < 250 )
- strcpy(buf, outbuf);
+ TrailerLen = len - (end - start);
+ if (TrailerLen > 0)
+ memcpy(outbuf + Offset + outpos, end, TrailerLen);
+ if (Offset + outpos + TrailerLen > bufsize) {
+ lprintf(1, "URL: content longer than buffer!");
+ return;
+ }
+ memcpy (buf, outbuf, Offset + outpos + TrailerLen);
+ *(buf + Offset + outpos + TrailerLen) = '\0';
}
@@ -467,8 +492,9 @@ void fetchname_parsed_vcard(struct vCard *v, char *storename) {
* understand in a simple two-column name/value format.
* \param v the vCard to display
* \param full display all items of the vcard?
+ * \param msgnum Citadel message pointer
*/
-void display_parsed_vcard(struct vCard *v, int full) {
+void display_parsed_vcard(struct vCard *v, int full, long msgnum) {
int i, j;
char buf[SIZ];
char *name;
@@ -637,6 +663,14 @@ void display_parsed_vcard(struct vCard *v, int full) {
wprintf("\n");
}
}
+ /* else if (!strcasecmp(firsttoken, "photo") && full && pass == 2) {
+ // Only output on second pass
+ wprintf("
");
+ wprintf(_("Photo:"));
+ wprintf(" | ");
+ wprintf("",msgnum);
+ wprintf(" |
\n");
+ } */
else if (!strcasecmp(firsttoken, "version")) {
/* ignore */
}
@@ -711,8 +745,10 @@ void display_parsed_vcard(struct vCard *v, int full) {
* \param alpha what???
* \param full should we usse all lines?
* \param storename where to store???
+ * \param msgnum Citadel message pointer
*/
-void display_vcard(char *vcard_source, char alpha, int full, char *storename) {
+void display_vcard(char *vcard_source, char alpha, int full, char *storename,
+ long msgnum) {
struct vCard *v;
char *name;
char buf[SIZ];
@@ -735,7 +771,7 @@ void display_vcard(char *vcard_source, char alpha, int full, char *storename) {
|| ((isalpha(alpha)) && (tolower(alpha) == tolower(this_alpha)) )
|| ((!isalpha(alpha)) && (!isalpha(this_alpha)))
) {
- display_parsed_vcard(v, full);
+ display_parsed_vcard(v, full,msgnum);
}
vcard_free(v);
@@ -777,6 +813,7 @@ void read_message(long msgnum, int printable_view, char *section) {
char reply_to[512] = "";
char reply_all[4096] = "";
char reply_references[1024] = "";
+ char reply_inreplyto[256] = "";
char now[64] = "";
int format_type = 0;
int nhdr = 0;
@@ -849,15 +886,10 @@ void read_message(long msgnum, int printable_view, char *section) {
safestrncpy(m_subject, &buf[5], sizeof m_subject);
}
if (!strncasecmp(buf, "msgn=", 5)) {
- safestrncpy(reply_references, &buf[5], sizeof reply_references);
+ safestrncpy(reply_inreplyto, &buf[5], sizeof reply_inreplyto);
}
if (!strncasecmp(buf, "wefw=", 5)) {
- int rrlen = strlen(reply_references);
- if (rrlen > 0) {
- strcpy(&reply_references[rrlen++], "|");
- }
- safestrncpy(&reply_references[rrlen], &buf[5],
- (sizeof(reply_references) - rrlen) );
+ safestrncpy(reply_references, &buf[5], sizeof reply_references);
}
if (!strncasecmp(buf, "cccc=", 5)) {
int len;
@@ -1000,7 +1032,16 @@ void read_message(long msgnum, int printable_view, char *section) {
}
- /** Generate a reply-to address */
+ /* Trim down excessively long lists of thread references. We eliminate the
+ * second one in the list so that the thread root remains intact.
+ */
+ int rrtok = num_tokens(reply_references, '|');
+ int rrlen = strlen(reply_references);
+ if ( ((rrtok >= 3) && (rrlen > 900)) || (rrtok > 10) ) {
+ remove_token(reply_references, 1, '|');
+ }
+
+ /* Generate a reply-to address */
if (!IsEmptyStr(rfca)) {
if (!IsEmptyStr(from)) {
snprintf(reply_to, sizeof(reply_to), "%s <%s>", from, rfca);
@@ -1030,6 +1071,8 @@ void read_message(long msgnum, int printable_view, char *section) {
/** start msg buttons */
+ char Urlsep = '?';
+
if (!printable_view) {
wprintf("\n",msgnum);
@@ -1037,19 +1080,23 @@ void read_message(long msgnum, int printable_view, char *section) {
if ( (WC->wc_view == VIEW_MAILBOX) || (WC->wc_view == VIEW_BBS) ) {
wprintf("is_mailbox) {
- wprintf("?replyquote=%ld", msgnum);
+ wprintf("%creplyquote=%ld", Urlsep, msgnum);
+ Urlsep = '&';
}
- wprintf("?recp=");
+ wprintf("%crecp=", Urlsep);
+ Urlsep = '&';
urlescputs(reply_to);
if (!IsEmptyStr(m_subject)) {
- wprintf("?subject=");
- if (strncasecmp(m_subject, "Re:", 3)) wprintf("Re:%20");
+ wprintf("%csubject=", Urlsep);
+ if (strncasecmp(m_subject, "Re:", 3)) wprintf("Re:%%20");
urlescputs(m_subject);
}
+ wprintf("%creferences=", Urlsep);
if (!IsEmptyStr(reply_references)) {
- wprintf("?references=");
urlescputs(reply_references);
+ urlescputs("|");
}
+ urlescputs(reply_inreplyto);
wprintf("\">[%s] ", _("Reply"));
}
@@ -1058,17 +1105,19 @@ void read_message(long msgnum, int printable_view, char *section) {
if (!WC->is_mailbox) {
wprintf("[%s] ", _("ReplyQuoted"));
}
}
@@ -1077,26 +1126,28 @@ void read_message(long msgnum, int printable_view, char *section) {
if (WC->wc_view == VIEW_MAILBOX) {
wprintf("[%s] ", _("ReplyAll"));
}
/* Forward */
if (WC->wc_view == VIEW_MAILBOX) {
- wprintf("[%s] ", _("Forward"));
}
@@ -1245,22 +1296,22 @@ void read_message(long msgnum, int printable_view, char *section) {
bq = 0;
}
wprintf("");
- url(buf);
+ url(buf, sizeof(buf));
escputs(buf);
wprintf("
\n");
}
wprintf("
");
}
- else /** HTML is fun, but we've got to strip it first */
- if (!strcasecmp(mime_content_type, "text/html")) {
- output_html(mime_charset, (WC->wc_view == VIEW_WIKI ? 1 : 0));
+ /* HTML is fun, but we've got to strip it first */
+ else if (!strcasecmp(mime_content_type, "text/html")) {
+ output_html(mime_charset, (WC->wc_view == VIEW_WIKI ? 1 : 0), msgnum);
}
- /** Unknown weirdness */
+ /* Unknown weirdness */
else {
wprintf(_("I don't know how to display %s"), mime_content_type);
- wprintf("
\n", mime_content_type);
+ wprintf("
\n");
while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) { }
}
@@ -1277,7 +1328,7 @@ ENDBODY: /* If there are attached submessages, display them now... */
}
- /** Afterwards, offer links to download attachments 'n' such */
+ /* Afterwards, offer links to download attachments 'n' such */
if ( (num_attach_links > 0) && (!section[0]) ) {
for (i=0; iwc_roomname[11], USERCONFIGROOM))
|| (WC->wc_view == VIEW_ADDRESSBOOK)
) {
- wprintf("",
+ wprintf("",
msgnum, vcard_partnum);
wprintf("[%s]", _("edit"));
}
- /** In all cases, display the full card */
- display_vcard(part_source, 0, 1, NULL);
+ /* In all cases, display the full card */
+ display_vcard(part_source, 0, 1, NULL,msgnum);
}
}
- /** Handler for calendar parts */
+ /* Handler for calendar parts */
if (!IsEmptyStr(cal_partnum)) {
part_source = load_mimepart(msgnum, cal_partnum);
if (part_source != NULL) {
- cal_process_attachment(part_source,
- msgnum, cal_partnum);
+ cal_process_attachment(part_source, msgnum, cal_partnum);
}
}
@@ -1323,7 +1372,7 @@ ENDBODY: /* If there are attached submessages, display them now... */
wprintf("\n");
- /** end everythingamundo table */
+ /* end everythingamundo table */
if (!printable_view) {
wprintf("\n");
}
@@ -1341,41 +1390,40 @@ ENDBODY: /* If there are attached submessages, display them now... */
-/**
- * \brief Unadorned HTML output of an individual message, suitable
+/*
+ * Unadorned HTML output of an individual message, suitable
* for placing in a hidden iframe, for printing, or whatever
*
- * \param msgnum_as_string Message number, as a string instead of as a long int
+ * msgnum_as_string == Message number, as a string instead of as a long int
*/
-void embed_message(char *msgnum_as_string) {
+void embed_message(void) {
long msgnum = 0L;
- msgnum = atol(msgnum_as_string);
- begin_ajax_response();
+ msgnum = StrTol(WC->UrlFragment1);
read_message(msgnum, 0, "");
- end_ajax_response();
}
-/**
- * \brief Printable view of a message
+/*
+ * Printable view of a message
*
- * \param msgnum_as_string Message number, as a string instead of as a long int
+ * msgnum_as_string == Message number, as a string instead of as a long int
*/
-void print_message(char *msgnum_as_string) {
+void print_message(void) {
long msgnum = 0L;
- msgnum = atol(msgnum_as_string);
+ msgnum = StrTol(WC->UrlFragment1);
output_headers(0, 0, 0, 0, 0, 0);
- wprintf("Content-type: text/html\r\n"
+ hprintf("Content-type: text/html\r\n"
"Server: %s\r\n"
"Connection: close\r\n",
PACKAGE_STRING);
begin_burst();
- wprintf("\r\n\r\n\n"
- "Printable view\n"
+ wprintf("\r\n\n");
+ escputs(WC->wc_fullname);
+ wprintf("\n"
"\n"
);
@@ -1385,21 +1433,34 @@ void print_message(char *msgnum_as_string) {
wDumpContent(0);
}
-
+/*
+ * Mobile browser view of message
+ *
+ * @param msg_num_as_string Message number as a string instead of as a long int
+ */
+void mobile_message_view(void) {
+ long msgnum = 0L;
+ msgnum = StrTol(WC->UrlFragment1);
+ output_headers(1, 0, 0, 0, 0, 1);
+ begin_burst();
+ do_template("msgcontrols", NULL);
+ read_message(msgnum,1, "");
+ wDumpContent(0);
+}
/**
* \brief Display a message's headers
*
* \param msgnum_as_string Message number, as a string instead of as a long int
*/
-void display_headers(char *msgnum_as_string) {
+void display_headers(void) {
long msgnum = 0L;
char buf[1024];
- msgnum = atol(msgnum_as_string);
+ msgnum = StrTol(WC->UrlFragment1);
output_headers(0, 0, 0, 0, 0, 0);
- wprintf("Content-type: text/plain\r\n"
+ hprintf("Content-type: text/plain\r\n"
"Server: %s\r\n"
"Connection: close\r\n",
PACKAGE_STRING);
@@ -1634,8 +1695,8 @@ void pullquote_message(long msgnum, int forward_attachments, int include_headers
while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
int len;
len = strlen(buf);
- if (buf[len-1] == '\n') buf[--len] = 0;
- if (buf[len-1] == '\r') buf[--len] = 0;
+ if ((len > 0) && (buf[len-1] == '\n')) buf[--len] = 0;
+ if ((len > 0) && (buf[len-1] == '\r')) buf[--len] = 0;
#ifdef HAVE_ICONV
if (ic != (iconv_t)(-1) ) {
@@ -1664,7 +1725,7 @@ void pullquote_message(long msgnum, int forward_attachments, int include_headers
bq = 0;
}
wprintf("");
- url(buf);
+ url(buf, sizeof(buf));
msgescputs1(buf);
wprintf("
");
}
@@ -1677,7 +1738,7 @@ void pullquote_message(long msgnum, int forward_attachments, int include_headers
strcat(buf, "\n");
msgescputs(buf);
}
- }
+ }//// TODO: charset? utf8?
/** Unknown weirdness ... don't know how to handle this content type */
else {
@@ -1754,11 +1815,10 @@ ENDBODY:
*/
void display_summarized(int num) {
char datebuf[64];
-
wprintf("",
WC->summ[num].msgnum,
- (WC->summ[num].is_new ? "bold" : "normal"),
+ ((WC->summ[num].is_new) ? "bold" : "normal"),
WC->summ[num].msgnum
);
@@ -1778,8 +1838,26 @@ void display_summarized(int num) {
wprintf("
\n");
}
-
-
+/**
+ * \brief Output a message row for the mobile view
+ * \param The row number
+ */
+void display_mobile_summary(int num) {
+ char datebuf[64];
+ wprintf("\n",
+ WC->summ[num].msgnum,
+ (WC->summ[num].is_new ? "bold" : "normal"),
+ WC->summ[num].msgnum
+ );
+ wprintf("%s",WC->summ[num].from);
+ wprintf("");
+ webcit_fmt_date(datebuf, WC->summ[num].date, 1); /* brief */
+ escputs(datebuf);
+ wprintf("
");
+ escputs(WC->summ[num].subj);
+ wprintf("
",WC->summ[num].msgnum);
+}
/**
* \brief display the adressbook overview
@@ -1826,7 +1904,7 @@ void display_addressbook(long msgnum, char alpha) {
if (vcard_source != NULL) {
/** Display the summary line */
- display_vcard(vcard_source, alpha, 0, NULL);
+ display_vcard(vcard_source, alpha, 0, NULL,msgnum);
/** If it's my vCard I can edit it */
if ( (!strcasecmp(WC->wc_roomname, USERCONFIGROOM))
@@ -1834,7 +1912,7 @@ void display_addressbook(long msgnum, char alpha) {
|| (WC->wc_view == VIEW_ADDRESSBOOK)
) {
wprintf("",
+ "msgnum=%ld&partnum=%s\">",
msgnum, vcard_partnum);
wprintf("[%s]", _("edit"));
}
@@ -1917,7 +1995,7 @@ void fetch_ab_name(long msgnum, char *namebuf) {
if (vcard_source != NULL) {
/* Grab the name off the card */
- display_vcard(vcard_source, 0, 0, namebuf);
+ display_vcard(vcard_source, 0, 0, namebuf,msgnum);
free(vcard_source);
}
@@ -2040,7 +2118,7 @@ void do_addrbook_view(struct addrbookent *addrbook, int num_ab) {
wprintf("");
- wprintf("", bstr("alpha"));
vcard_n_prettyize(addrbook[i].ab_name);
@@ -2049,9 +2127,20 @@ void do_addrbook_view(struct addrbookent *addrbook, int num_ab) {
++displayed;
}
+ /* Placeholders for empty columns at end */
+ if ((num_ab % 4) != 0) {
+ for (i=0; i<(4-(num_ab % 4)); ++i) {
+ wprintf(" | | ");
+ }
+ }
+
wprintf("\n");
end_tab((num_pages-1), num_pages);
+ begin_tab(num_pages, num_pages);
+ /* FIXME there ought to be something here */
+ end_tab(num_pages, num_pages);
+
for (i=0; isumm[nummsgs-1].msgnum = WC->msgarr[nummsgs-1];
safestrncpy(WC->summ[nummsgs-1].subj,
_("(no subject)"), sizeof WC->summ[nummsgs-1].subj);
- if (!IsEmptyStr(fullname)) {
- /** Handle senders with RFC2047 encoding */
- utf8ify_rfc822_string(fullname);
- safestrncpy(WC->summ[nummsgs-1].from,
- fullname, sizeof WC->summ[nummsgs-1].from);
- }
if (!IsEmptyStr(subject)) {
/** Handle subjects with RFC2047 encoding */
utf8ify_rfc822_string(subject);
@@ -2131,40 +2216,44 @@ int load_msg_ptrs(char *servcmd, int with_headers)
}
sbjlen = Ctdl_Utf8StrLen(WC->summ[nummsgs-1].subj);
if (sbjlen > 75) {
- char *ptr;
ptr = Ctdl_Utf8StrCut(WC->summ[nummsgs-1].subj, 72);
strcpy(ptr, "...");
}
- if (!IsEmptyStr(nodename)) {
- if ( ((WC->room_flags & QR_NETWORK)
- || ((strcasecmp(nodename, serv_info.serv_nodename)
- && (strcasecmp(nodename, serv_info.serv_fqdn)))))
- ) {
- strcat(WC->summ[nummsgs-1].from, " @ ");
- strcat(WC->summ[nummsgs-1].from, nodename);
- }
+ if (!IsEmptyStr(fullname)) {
+ /** Handle senders with RFC2047 encoding */
+ utf8ify_rfc822_string(fullname);
+ safestrncpy(WC->summ[nummsgs-1].from,
+ fullname, sizeof WC->summ[nummsgs-1].from);
+ }
+ if ((!IsEmptyStr(nodename)) &&
+ ( ((WC->room_flags & QR_NETWORK)
+ || ((strcasecmp(nodename, serv_info.serv_nodename)
+ && (strcasecmp(nodename, serv_info.serv_fqdn)))))))
+ {
+ strcat(WC->summ[nummsgs-1].from, " @ ");
+ strcat(WC->summ[nummsgs-1].from, nodename);
+
+ }
+ sbjlen = Ctdl_Utf8StrLen(WC->summ[nummsgs-1].from);
+ if (sbjlen > 25) {
+ ptr = Ctdl_Utf8StrCut(WC->summ[nummsgs-1].from, 23);
+ strcpy(ptr, "...");
}
WC->summ[nummsgs-1].date = datestamp;
-
- /** Handle senders with RFC2047 encoding */
- utf8ify_rfc822_string(WC->summ[nummsgs-1].from);
- if (strlen(WC->summ[nummsgs-1].from) > 25) {
- strcpy(&WC->summ[nummsgs-1].from[22], "...");
- }
}
}
}
return (nummsgs);
}
-/**
- * \brief qsort() compatible function to compare two longs in descending order.
- *
- * \param s1 first number to compare
- * \param s2 second number to compare
+
+typedef int (*QSortFunction) (const void*, const void*);
+
+/*
+ * qsort() compatible function to compare two longs in descending order.
*/
int longcmp_r(const void *s1, const void *s2) {
long l1;
@@ -2179,11 +2268,8 @@ int longcmp_r(const void *s1, const void *s2) {
}
-/**
- * \brief qsort() compatible function to compare two message summary structs by ascending subject.
- *
- * \param s1 first item to compare
- * \param s2 second item to compare
+/*
+ * qsort() compatible function to compare two message summary structs by ascending subject.
*/
int summcmp_subj(const void *s1, const void *s2) {
struct message_summary *summ1;
@@ -2194,11 +2280,8 @@ int summcmp_subj(const void *s1, const void *s2) {
return strcasecmp(summ1->subj, summ2->subj);
}
-/**
- * \brief qsort() compatible function to compare two message summary structs by descending subject.
- *
- * \param s1 first item to compare
- * \param s2 second item to compare
+/*
+ * qsort() compatible function to compare two message summary structs by descending subject.
*/
int summcmp_rsubj(const void *s1, const void *s2) {
struct message_summary *summ1;
@@ -2209,11 +2292,8 @@ int summcmp_rsubj(const void *s1, const void *s2) {
return strcasecmp(summ2->subj, summ1->subj);
}
-/**
- * \brief qsort() compatible function to compare two message summary structs by ascending sender.
- *
- * \param s1 first item to compare
- * \param s2 second item to compare
+/*
+ * qsort() compatible function to compare two message summary structs by ascending sender.
*/
int summcmp_sender(const void *s1, const void *s2) {
struct message_summary *summ1;
@@ -2224,11 +2304,8 @@ int summcmp_sender(const void *s1, const void *s2) {
return strcasecmp(summ1->from, summ2->from);
}
-/**
- * \brief qsort() compatible function to compare two message summary structs by descending sender.
- *
- * \param s1 first item to compare
- * \param s2 second item to compare
+/*
+ * qsort() compatible function to compare two message summary structs by descending sender.
*/
int summcmp_rsender(const void *s1, const void *s2) {
struct message_summary *summ1;
@@ -2239,11 +2316,8 @@ int summcmp_rsender(const void *s1, const void *s2) {
return strcasecmp(summ2->from, summ1->from);
}
-/**
- * \brief qsort() compatible function to compare two message summary structs by ascending date.
- *
- * \param s1 first item to compare
- * \param s2 second item to compare
+/*
+ * qsort() compatible function to compare two message summary structs by ascending date.
*/
int summcmp_date(const void *s1, const void *s2) {
struct message_summary *summ1;
@@ -2257,11 +2331,8 @@ int summcmp_date(const void *s1, const void *s2) {
else return 0;
}
-/**
- * \brief qsort() compatible function to compare two message summary structs by descending date.
- *
- * \param s1 first item to compare
- * \param s2 second item to compare
+/*
+ * qsort() compatible function to compare two message summary structs by descending date.
*/
int summcmp_rdate(const void *s1, const void *s2) {
struct message_summary *summ1;
@@ -2276,11 +2347,88 @@ int summcmp_rdate(const void *s1, const void *s2) {
}
+enum {
+ eUp,
+ eDown,
+ eNone
+};
+
+const char* SortIcons[3] = {
+ "static/up_pointer.gif",
+ "static/down_pointer.gif",
+ "static/sort_none.gif"
+};
+
+ enum {/// SortByEnum
+ eDate,
+ eRDate,
+ eSubject,
+ eRSubject,
+ eSender,
+ eRSender,
+ eReverse,
+ eUnSet
+};
+
+/* SortEnum to plain string representation */
+static const char* SortByStrings[] = {
+ "date",
+ "rdate",
+ "subject",
+ "rsubject",
+ "sender",
+ "rsender",
+ "reverse",
+ "unset"
+};
+
+/* SortEnum to sort-Function Table */
+const QSortFunction SortFuncs[eUnSet] = {
+ summcmp_date,
+ summcmp_rdate,
+ summcmp_subj,
+ summcmp_rsubj,
+ summcmp_sender,
+ summcmp_rsender,
+ summcmp_rdate
+};
+
+/* given a SortEnum, which icon should we choose? */
+const int SortDateToIcon[eUnSet] = { eUp, eDown, eNone, eNone, eNone, eNone, eNone};
+const int SortSubjectToIcon[eUnSet] = { eNone, eNone, eUp, eDown, eNone, eNone, eNone};
+const int SortSenderToIcon[eUnSet] = { eNone, eNone, eNone, eNone, eUp, eDown, eNone};
+
+/* given a SortEnum, which would be the "opposite" search option? */
+const int DateInvertSortString[eUnSet] = { eRDate, eDate, eDate, eDate, eDate, eDate, eDate};
+const int SubjectInvertSortString[eUnSet] = { eSubject, eSubject, eRSubject, eUnSet, eSubject, eSubject, eSubject};
+const int SenderInvertSortString[eUnSet] = { eSender, eSender, eSender, eSender, eRSender, eUnSet, eSender};
+
+
+/*
+ * Translates sortoption String to its SortEnum representation
+ * returns the enum matching the string; defaults to RDate
+ */
+//SortByEnum
+int StrToESort (const StrBuf *sortby)
+{
+ int result = eDate;
+
+ if (!IsEmptyStr(ChrPtr(sortby))) while (result < eUnSet){
+ if (!strcasecmp(ChrPtr(sortby),
+ SortByStrings[result]))
+ return result;
+ result ++;
+ }
+ return eRDate;
+}
+
+
-/**
- * \brief command loop for reading messages
+
+/*
+ * command loop for reading messages
*
- * \param oper Set to "readnew" or "readold" or "readfwd" or "headers"
+ * Set oper to "readnew" or "readold" or "readfwd" or "headers"
*/
void readloop(char *oper)
{
@@ -2305,40 +2453,37 @@ void readloop(char *oper)
int highest_displayed = 0;
struct addrbookent *addrbook = NULL;
int num_ab = 0;
- char *sortby = NULL;
- char sortpref_name[128];
- char sortpref_value[128];
- char *subjsort_button;
- char *sendsort_button;
- char *datesort_button;
+ const StrBuf *sortby = NULL;
+ //SortByEnum
+ int SortBy = eRDate;
+ const StrBuf *sortpref_value;
int bbs_reverse = 0;
struct wcsession *WCC = WC; /* This is done to make it run faster; WC is a function */
if (WCC->wc_view == VIEW_WIKI) {
- sprintf(buf, "wiki?room=%s?page=home", WCC->wc_roomname);
+ sprintf(buf, "wiki?room=%s&page=home", WCC->wc_roomname);
http_redirect(buf);
return;
}
- startmsg = atol(bstr("startmsg"));
- maxmsgs = atoi(bstr("maxmsgs"));
- is_summary = atoi(bstr("is_summary"));
+ startmsg = lbstr("startmsg");
+ maxmsgs = ibstr("maxmsgs");
+ is_summary = (ibstr("is_summary") && !WCC->is_mobile);
if (maxmsgs == 0) maxmsgs = DEFAULT_MAXMSGS;
- snprintf(sortpref_name, sizeof sortpref_name, "sort %s", WCC->wc_roomname);
- get_preference(sortpref_name, sortpref_value, sizeof sortpref_value);
+ sortpref_value = get_room_pref("sort");
- sortby = bstr("sortby");
- if ( (!IsEmptyStr(sortby)) && (strcasecmp(sortby, sortpref_value)) ) {
- set_preference(sortpref_name, sortby, 1);
+ sortby = sbstr("sortby");
+ if ( (!IsEmptyStr(ChrPtr(sortby))) &&
+ (strcasecmp(ChrPtr(sortby), ChrPtr(sortpref_value)) != 0)) {
+ set_room_pref("sort", NewStrBufDup(sortby), 1);
+ sortpref_value = NULL;
+ sortpref_value = sortby;
}
- if (IsEmptyStr(sortby)) sortby = sortpref_value;
-
- /** mailbox sort */
- if (IsEmptyStr(sortby)) sortby = "rdate";
- /** message board sort */
- if (!strcasecmp(sortby, "reverse")) {
+ SortBy = StrToESort(sortpref_value);
+ /* message board sort */
+ if (SortBy == eReverse) {
bbs_reverse = 1;
}
else {
@@ -2347,7 +2492,7 @@ void readloop(char *oper)
output_headers(1, 1, 1, 0, 0, 0);
- /**
+ /*
* When in summary mode, always show ALL messages instead of just
* new or old. Otherwise, show what the user asked for.
*/
@@ -2364,7 +2509,7 @@ void readloop(char *oper)
strcpy(cmd, "MSGS ALL");
}
- if ((WCC->wc_view == VIEW_MAILBOX) && (maxmsgs > 1)) {
+ if ((WCC->wc_view == VIEW_MAILBOX) && (maxmsgs > 1) && !WCC->is_mobile) {
is_summary = 1;
if (!strcmp(oper, "do_search")) {
snprintf(cmd, sizeof(cmd), "MSGS SEARCH|%s", bstr("query"));
@@ -2392,15 +2537,23 @@ void readloop(char *oper)
);
startmsg = 1;
maxmsgs = 9999999;
+ }
+ if (WCC->is_mobile) {
+ maxmsgs = 20;
+ snprintf(cmd, sizeof(cmd), "MSGS %s|%s||1",
+ (!strcmp(oper, "do_search") ? "SEARCH" : "ALL"),
+ (!strcmp(oper, "do_search") ? bstr("query") : "")
+ );
+ SortBy = eRDate;
}
- /**
+ /*
* Are we doing a summary view? If so, we need to know old messages
* and new messages, so we can do that pretty boldface thing for the
* new messages.
*/
strcpy(old_msgs, "");
- if ((is_summary) || (WCC->wc_default_view == VIEW_CALENDAR)){
+ if ((is_summary) || (WCC->wc_default_view == VIEW_CALENDAR) || WCC->is_mobile){
serv_puts("GTSN");
serv_getln(buf, sizeof buf);
if (buf[0] == '2') {
@@ -2408,7 +2561,7 @@ void readloop(char *oper)
}
}
- is_singlecard = atoi(bstr("is_singlecard"));
+ is_singlecard = ibstr("is_singlecard");
if (WCC->wc_default_view == VIEW_CALENDAR) { /**< calendar */
is_calendar = 1;
@@ -2427,11 +2580,10 @@ void readloop(char *oper)
}
if (is_notes) {
- wprintf("%s
\n", _("Click on any note to edit it."));
wprintf("\n");
}
- nummsgs = load_msg_ptrs(cmd, is_summary);
+ nummsgs = load_msg_ptrs(cmd, (is_summary || WCC->is_mobile));
if (nummsgs == 0) {
if ((!is_tasks) && (!is_calendar) && (!is_notes) && (!is_addressbook)) {
@@ -2449,7 +2601,7 @@ void readloop(char *oper)
goto DONE;
}
- if ((is_summary) || (WCC->wc_default_view == VIEW_CALENDAR)){
+ if ((is_summary) || (WCC->wc_default_view == VIEW_CALENDAR) || WCC->is_mobile){
for (a = 0; a < nummsgs; ++a) {
/** Are you a new message, or an old message? */
if (is_summary) {
@@ -2472,62 +2624,11 @@ void readloop(char *oper)
}
}
- if (is_summary) {
- if (!strcasecmp(sortby, "subject")) {
- qsort(WCC->summ, WCC->num_summ,
- sizeof(struct message_summary), summcmp_subj);
- }
- else if (!strcasecmp(sortby, "rsubject")) {
- qsort(WCC->summ, WCC->num_summ,
- sizeof(struct message_summary), summcmp_rsubj);
- }
- else if (!strcasecmp(sortby, "sender")) {
- qsort(WCC->summ, WCC->num_summ,
- sizeof(struct message_summary), summcmp_sender);
- }
- else if (!strcasecmp(sortby, "rsender")) {
- qsort(WCC->summ, WCC->num_summ,
- sizeof(struct message_summary), summcmp_rsender);
- }
- else if (!strcasecmp(sortby, "date")) {
- qsort(WCC->summ, WCC->num_summ,
- sizeof(struct message_summary), summcmp_date);
- }
- else if (!strcasecmp(sortby, "rdate")) {
- qsort(WCC->summ, WCC->num_summ,
- sizeof(struct message_summary), summcmp_rdate);
- }
- }
-
- if (!strcasecmp(sortby, "subject")) {
- subjsort_button = "" ;
- }
- else if (!strcasecmp(sortby, "rsubject")) {
- subjsort_button = "" ;
- }
- else {
- subjsort_button = "" ;
+ if (is_summary || WCC->is_mobile) {
+ qsort(WCC->summ, WCC->num_summ,
+ sizeof(struct message_summary), SortFuncs[SortBy]);
}
- if (!strcasecmp(sortby, "sender")) {
- sendsort_button = "" ;
- }
- else if (!strcasecmp(sortby, "rsender")) {
- sendsort_button = "" ;
- }
- else {
- sendsort_button = "" ;
- }
-
- if (!strcasecmp(sortby, "date")) {
- datesort_button = "" ;
- }
- else if (!strcasecmp(sortby, "rdate")) {
- datesort_button = "" ;
- }
- else {
- datesort_button = "" ;
- }
if (is_summary) {
@@ -2545,9 +2646,9 @@ void readloop(char *oper)
""
""
);
- wprintf("%s %s | "
- "%s %s | "
- "%s %s"
+ wprintf(" | %s | \n"
+ "%s | \n"
+ "%s \n"
" "
"\n"
,
SUBJ_COL_WIDTH_PCT,
- _("Subject"), subjsort_button,
+ _("Subject"),
+ SortByStrings[SubjectInvertSortString[SortBy]],
+ SortIcons[SortSubjectToIcon[SortBy]],
SENDER_COL_WIDTH_PCT,
- _("Sender"), sendsort_button,
+ _("Sender"),
+ SortByStrings[SenderInvertSortString[SortBy]],
+ SortIcons[SortSenderToIcon[SortBy]],
DATE_PLUS_BUTTONS_WIDTH_PCT,
- _("Date"), datesort_button,
+ _("Date"),
+ SortByStrings[DateInvertSortString[SortBy]],
+ SortIcons[SortDateToIcon[SortBy]],
_("Delete")
);
wprintf(" |
\n");
-
wprintf(""
"
\n"
-
""
"
\n"); /**< end of 'fix_scrollbar_bug' div */
wprintf("
"); /**< end of 'message_list' div */
-
+
/** Here's the grab-it-to-resize-the-message-list widget */
wprintf(""
@@ -2746,6 +2847,8 @@ void readloop(char *oper)
);
wprintf("
"); /**< The preview pane will initially be empty */
+ } else if (WCC->is_mobile) {
+ wprintf("
");
}
/**
@@ -2762,7 +2865,7 @@ void readloop(char *oper)
if (is_bbview) {
/** begin bbview scroller */
wprintf("