-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 CompareFunc 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)
-{////todoo: hash
- int result = eDate;
-
- if (!IsEmptyStr(ChrPtr(sortby))) while (result < eUnSet){
- if (!strcasecmp(ChrPtr(sortby),
- SortByStrings[result]))
- return result;
- result ++;
- }
- return eRDate;
-}
-
-
-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;
- long l2;
-
- l1 = *(long *)GetSearchPayload(s1);
- l2 = *(long *)GetSearchPayload(s2);
-
- if (l1 > l2) return(-1);
- if (l1 < l2) return(+1);
- return(0);
-}
-
-/*
- * qsort() compatible function to compare two longs in descending order.
- */
-int qlongcmp_r(const void *s1, const void *s2) {
- long l1 = (long) s1;
- long l2 = (long) s2;
-
- if (l1 > l2) return(-1);
- if (l1 < l2) return(+1);
- return(0);
-}
-
-
-/*
- * qsort() compatible function to compare two message summary structs by ascending subject.
- */
-int summcmp_subj(const void *s1, const void *s2) {
- message_summary *summ1;
- message_summary *summ2;
-
- summ1 = (message_summary *)GetSearchPayload(s1);
- summ2 = (message_summary *)GetSearchPayload(s2);
- return strcasecmp(ChrPtr(summ1->subj), ChrPtr(summ2->subj));
-}
-
-/*
- * qsort() compatible function to compare two message summary structs by descending subject.
- */
-int summcmp_rsubj(const void *s1, const void *s2) {
- message_summary *summ1;
- message_summary *summ2;
-
- summ1 = (message_summary *)GetSearchPayload(s1);
- summ2 = (message_summary *)GetSearchPayload(s2);
- return strcasecmp(ChrPtr(summ2->subj), ChrPtr(summ1->subj));
-}
-
-/*
- * qsort() compatible function to compare two message summary structs by ascending sender.
- */
-int summcmp_sender(const void *s1, const void *s2) {
- message_summary *summ1;
- message_summary *summ2;
-
- summ1 = (message_summary *)GetSearchPayload(s1);
- summ2 = (message_summary *)GetSearchPayload(s2);
- return strcasecmp(ChrPtr(summ1->from), ChrPtr(summ2->from));
-}
-
-/*
- * qsort() compatible function to compare two message summary structs by descending sender.
- */
-int summcmp_rsender(const void *s1, const void *s2) {
- message_summary *summ1;
- message_summary *summ2;
-
- summ1 = (message_summary *)GetSearchPayload(s1);
- summ2 = (message_summary *)GetSearchPayload(s2);
- return strcasecmp(ChrPtr(summ2->from), ChrPtr(summ1->from));
-}
-
-/*
- * qsort() compatible function to compare two message summary structs by ascending date.
- */
-int summcmp_date(const void *s1, const void *s2) {
- message_summary *summ1;
- message_summary *summ2;
-
- summ1 = (message_summary *)GetSearchPayload(s1);
- summ2 = (message_summary *)GetSearchPayload(s2);
-
- if (summ1->date < summ2->date) return -1;
- else if (summ1->date > summ2->date) return +1;
- else return 0;
-}
-
-/*
- * qsort() compatible function to compare two message summary structs by descending date.
- */
-int summcmp_rdate(const void *s1, const void *s2) {
- message_summary *summ1;
- message_summary *summ2;
-
- summ1 = (message_summary *)GetSearchPayload(s1);
- summ2 = (message_summary *)GetSearchPayload(s2);
-
- if (summ1->date < summ2->date) return +1;
- else if (summ1->date > summ2->date) return -1;
- else return 0;
-}
-
-
-
-
/*
Done = 1;
if (state < 2) {
lprintf(1, _("unexpected end of message"));
- StrBufAppendPrintf(Target, "<i>");
- StrBufAppendPrintf(Target, _("unexpected end of message"));
- StrBufAppendPrintf(Target, " (1)</i><br /><br />\n");
- StrBufAppendPrintf(Target, "</div>\n");
- FreeStrBuf(&Buf);
- FreeStrBuf(&HdrToken);
- DestroyMessageSummary(Msg);
- FreeStrBuf(&FoundCharset);
- return 0;
- }
- else {
- break;
+
+ Msg->MsgBody->ContentType = NewStrBufPlain(HKEY("text/html"));
+ StrBufAppendPrintf(Msg->MsgBody->Data, "<div><i>");
+ StrBufAppendPrintf(Msg->MsgBody->Data, _("unexpected end of message"));
+ StrBufAppendPrintf(Msg->MsgBody->Data, " (1)</i><br /><br />\n");
+ StrBufAppendPrintf(Msg->MsgBody->Data, "</div>\n");
}
+ break;
}
switch (state) {
case 0:/* Citadel Message Headers */
}
-
-
+inline message_summary* GetMessagePtrAt(int n, HashList *Summ)
+{
+ void *vMsg;
+ if (Summ == NULL)
+ return NULL;
+ GetHash(Summ, (const char*)&n, sizeof(n), &vMsg);
+ return (message_summary*) vMsg;
+}
/*
*/
void readloop(char *oper)
{
+ StrBuf *BBViewToolBar = NULL;
void *vMsg;
message_summary *Msg;
char cmd[256] = "";
char old_msgs[SIZ];
int a = 0;
int b = 0;
+ int n;
int nummsgs;
long startmsg;
int maxmsgs;
int highest_displayed = 0;
addrbookent *addrbook = NULL;
int num_ab = 0;
- 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 */
HashPos *at;
const char *HashKey;
long HKLen;
+ int care_for_empty_list = 0;
+ int load_seen = 0;
+ int sortit = 0;
- if (WCC->wc_view == VIEW_WIKI) {
+ switch (WCC->wc_view) {
+ case VIEW_WIKI:
sprintf(buf, "wiki?room=%s&page=home", WCC->wc_roomname);
http_redirect(buf);
return;
- }
-
- startmsg = lbstr("startmsg");
- maxmsgs = ibstr("maxmsgs");
- is_summary = (ibstr("is_summary") && !WCC->is_mobile);
- if (maxmsgs == 0) maxmsgs = DEFAULT_MAXMSGS;
-
- sortpref_value = get_room_pref("sort");
-
- 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;
- }
-
- SortBy = StrToESort(sortpref_value);
- /* message board sort */
- if (SortBy == eReverse) {
- bbs_reverse = 1;
- }
- else {
- bbs_reverse = 0;
- }
-
- 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.
- */
- if (!strcmp(oper, "readnew")) {
- strcpy(cmd, "MSGS NEW");
- }
- else if (!strcmp(oper, "readold")) {
- strcpy(cmd, "MSGS OLD");
- }
- else if (!strcmp(oper, "do_search")) {
- snprintf(cmd, sizeof(cmd), "MSGS SEARCH|%s", bstr("query"));
- }
- else {
+ case VIEW_CALENDAR:
+ load_seen = 1;
+ is_calendar = 1;
+ strcpy(cmd, "MSGS ALL|||1");
+ maxmsgs = 32767;
+ parse_calendar_view_request(&calv);
+ case VIEW_TASKS:
+ is_tasks = 1;
strcpy(cmd, "MSGS ALL");
- }
+ maxmsgs = 32767;
+ case VIEW_NOTES:
+ is_notes = 1;
+ strcpy(cmd, "MSGS ALL");
+ maxmsgs = 32767;
+ wprintf("<div id=\"new_notes_here\"></div>\n");
+ case VIEW_ADDRESSBOOK:
+ is_singlecard = ibstr("is_singlecard");
+ if (maxmsgs > 1) {
+ is_addressbook = 1;
+ if (!strcmp(oper, "do_search")) {
+ snprintf(cmd, sizeof(cmd), "MSGS SEARCH|%s", bstr("query"));
+ }
+ else {
+ strcpy(cmd, "MSGS ALL");
+ }
+ maxmsgs = 9999999;
+ break;
+ }
- 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"));
+ default:
+ care_for_empty_list = 1;
+ startmsg = lbstr("startmsg");
+ 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.
+ */
+ if (!strcmp(oper, "readnew")) {
+ strcpy(cmd, "MSGS NEW");
}
- else {
- strcpy(cmd, "MSGS ALL");
+ else if (!strcmp(oper, "readold")) {
+ strcpy(cmd, "MSGS OLD");
}
- }
-
- if ((WCC->wc_view == VIEW_ADDRESSBOOK) && (maxmsgs > 1)) {
- is_addressbook = 1;
- if (!strcmp(oper, "do_search")) {
+ else if (!strcmp(oper, "do_search")) {
snprintf(cmd, sizeof(cmd), "MSGS SEARCH|%s", bstr("query"));
}
else {
strcpy(cmd, "MSGS ALL");
}
- maxmsgs = 9999999;
+
+ 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"));
+ }
+ else {
+ strcpy(cmd, "MSGS ALL");
+ }
+ }
+
+ is_bbview = !is_summary;
+ if (is_summary) { /**< fetch header summary */
+ load_seen = 1;
+ snprintf(cmd, sizeof(cmd), "MSGS %s|%s||1",
+ (!strcmp(oper, "do_search") ? "SEARCH" : "ALL"),
+ (!strcmp(oper, "do_search") ? bstr("query") : "")
+ );
+ startmsg = 1;
+ maxmsgs = 9999999;
+ }
+ if (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;
+ }
+ }
+ sortit = is_summary || WCC->is_mobile;
}
- if (is_summary) { /**< fetch header summary */
- snprintf(cmd, sizeof(cmd), "MSGS %s|%s||1",
- (!strcmp(oper, "do_search") ? "SEARCH" : "ALL"),
- (!strcmp(oper, "do_search") ? bstr("query") : "")
- );
- startmsg = 1;
- maxmsgs = 9999999;
- }
+
+
+
+
+
+
+ output_headers(1, 1, 1, 0, 0, 0);
+
+ /*
if (WCC->is_mobile) {
maxmsgs = 20;
snprintf(cmd, sizeof(cmd), "MSGS %s|%s||1",
* 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) || WCC->is_mobile){
- serv_puts("GTSN");
- serv_getln(buf, sizeof buf);
- if (buf[0] == '2') {
- strcpy(old_msgs, &buf[4]);
- }
- }
- is_singlecard = ibstr("is_singlecard");
-
- if (WCC->wc_default_view == VIEW_CALENDAR) { /**< calendar */
- is_calendar = 1;
- strcpy(cmd, "MSGS ALL|||1");
- maxmsgs = 32767;
- parse_calendar_view_request(&calv);
- }
- if (WCC->wc_default_view == VIEW_TASKS) { /**< tasks */
- is_tasks = 1;
- strcpy(cmd, "MSGS ALL");
- maxmsgs = 32767;
- }
- if (WCC->wc_default_view == VIEW_NOTES) { /**< notes */
- is_notes = 1;
- strcpy(cmd, "MSGS ALL");
- maxmsgs = 32767;
- }
-
- if (is_notes) {
- wprintf("<div id=\"new_notes_here\"></div>\n");
- }
nummsgs = load_msg_ptrs(cmd, (is_summary || WCC->is_mobile));
if (nummsgs == 0) {
-
- if ((!is_tasks) && (!is_calendar) && (!is_notes) && (!is_addressbook)) {
+ if (care_for_empty_list) {
wprintf("<div align=\"center\"><br /><em>");
if (!strcmp(oper, "readnew")) {
wprintf(_("No new messages."));
goto DONE;
}
- if ((is_summary) || (WCC->wc_default_view == VIEW_CALENDAR) || WCC->is_mobile){
+ if (load_seen){
void *vMsg;
- message_summary *Msg;
+ strcpy(old_msgs, "");
+ serv_puts("GTSN");
+ serv_getln(buf, sizeof buf);
+ if (buf[0] == '2') {
+ strcpy(old_msgs, &buf[4]);
+ }
at = GetNewHashPos();
while (GetNextHashPos(WCC->summ, at, &HKLen, &HashKey, &vMsg)) {
/** Are you a new message, or an old message? */
DeleteHashPos(&at);
}
- if (startmsg == 0L) {
- if (bbs_reverse) {
- startmsg = WCC->msgarr[(nummsgs >= maxmsgs) ? (nummsgs - maxmsgs) : 0];
- }
- else {
- startmsg = WCC->msgarr[0];
- }
- }
-
- if (is_summary || WCC->is_mobile) {
- SortByPayload(WCC->summ, SortFuncs[SortBy]);
+ if (sortit) {
+ CompareFunc SortIt;
+ SortIt = RetrieveSort(CTX_MAILSUM, NULL,
+ HKEY("date"), 2);
+ if (SortIt != NULL)
+ SortByPayload(WCC->summ, SortIt);
}
if (is_summary) {
-
- wprintf("<script language=\"javascript\" type=\"text/javascript\">"
- " document.onkeydown = CtdlMsgListKeyPress; "
- " if (document.layers) { "
- " document.captureEvents(Event.KEYPRESS); "
- " } "
- "</script>\n"
- );
-
- /** note that Date and Delete are now in the same column */
- wprintf("<div id=\"message_list_hdr\">"
- "<div class=\"fix_scrollbar_bug\">"
- "<table cellspacing=0 style=\"width:100%%\">"
- "<tr>"
- );
- wprintf("<th width=%d%%>%s <a href=\"readfwd?startmsg=1?maxmsgs=9999999?is_summary=1?sortby=%s\"><img border=\"0\" src=\"%s\" /></a> </th>\n"
- "<th width=%d%%>%s <a href=\"readfwd?startmsg=1?maxmsgs=9999999?is_summary=1?sortby=%s\"><img border=\"0\" src=\"%s\" /></a> </th>\n"
- "<th width=%d%%>%s <a href=\"readfwd?startmsg=1?maxmsgs=9999999?is_summary=1?sortby=%s\"><img border=\"0\" src=\"%s\" /></a> \n"
- " "
- "<input type=\"submit\" name=\"delete_button\" id=\"delbutton\" "
- " onClick=\"CtdlDeleteSelectedMessages(event)\" "
- " value=\"%s\">"
- "</th>"
- "</tr>\n"
- ,
- SUBJ_COL_WIDTH_PCT,
- _("Subject"),
- SortByStrings[SubjectInvertSortString[SortBy]],
- SortIcons[SortSubjectToIcon[SortBy]],
- SENDER_COL_WIDTH_PCT,
- _("Sender"),
- SortByStrings[SenderInvertSortString[SortBy]],
- SortIcons[SortSenderToIcon[SortBy]],
- DATE_PLUS_BUTTONS_WIDTH_PCT,
- _("Date"),
- SortByStrings[DateInvertSortString[SortBy]],
- SortIcons[SortDateToIcon[SortBy]],
- _("Delete")
- );
- wprintf("</table></div></div>\n");
- wprintf("<div id=\"message_list\">"
-
- "<div class=\"fix_scrollbar_bug\">\n"
- "<table class=\"mailbox_summary\" id=\"summary_headers\" "
- "cellspacing=0 style=\"width:100%%;-moz-user-select:none;\">"
- );
+ do_template("summary_header", NULL);
} else if (WCC->is_mobile) {
wprintf("<div id=\"message_list\">");
}
- /**
- * Set the "is_bbview" variable if it appears that we are looking at
- * a classic bulletin board view.
- */
- if ((!is_tasks) && (!is_calendar) && (!is_addressbook)
- && (!is_notes) && (!is_singlecard) && (!is_summary)) {
- is_bbview = 1;
- }
-
/**
* If we're not currently looking at ALL requested
* messages, then display the selector bar
*/
if (is_bbview) {
+ const char *selected;
+ StrBuf *Selector = NewStrBuf();
+ BBViewToolBar = NewStrBuf();
+///// DoTemplate("bbview_scrollbar");
/** begin bbview scroller */
- wprintf("<form name=\"msgomatictop\" class=\"selector_top\" > \n <p>");
- wprintf(_("Reading #"));//// TODO this isn't used, should it? : , lowest_displayed, highest_displayed);
+ StrBufAppendPrintf(BBViewToolBar, "<form name=\"msgomatictop\" class=\"selector_top\" > \n <p>");
+ StrBufAppendPrintf(BBViewToolBar, _("Reading #"));//// TODO this isn't used, should it? : , lowest_displayed, highest_displayed);
- wprintf("<select name=\"whichones\" size=\"1\" "
- "OnChange=\"location.href=msgomatictop.whichones.options"
- "[selectedIndex].value\">\n");
+ StrBufAppendPrintf(BBViewToolBar, "<select name=\"whichones\" size=\"1\" "
+ "OnChange=\"location.href=msgomatictop.whichones.options"
+ "[selectedIndex].value\">\n");
if (bbs_reverse) {
for (b=nummsgs-1; b>=0; b = b - maxmsgs) {
hi = b + 1;
lo = b - maxmsgs + 2;
if (lo < 1) lo = 1;
- wprintf("<option %s value="
- "\"%s"
- "&startmsg=%ld"
- "&maxmsgs=%d"
- "&is_summary=%d\">"
- "%d-%d</option> \n",
- ((WCC->msgarr[lo-1] == startmsg) ? "selected" : ""),
- oper,
- WCC->msgarr[lo-1],
- maxmsgs,
- is_summary,
- hi, lo);
+
+ Msg = GetMessagePtrAt(lo-1, WCC->summ);
+ n = (Msg==NULL)? 0 : Msg->msgnum;
+ selected = ((n == startmsg) ? "selected" : "");
+
+ StrBufAppendPrintf(Selector,
+ "<option %s value="
+ "\"%s"
+ "&startmsg=%ld"
+ "&maxmsgs=%d"
+ "&is_summary=%d\">"
+ "%d-%d</option> \n",
+ selected,
+ oper,
+
+
+ maxmsgs,
+ is_summary,
+ hi, lo);
}
}
else {
lo = b + 1;
hi = b + maxmsgs + 1;
if (hi > nummsgs) hi = nummsgs;
- wprintf("<option %s value="
- "\"%s"
- "&startmsg=%ld"
- "&maxmsgs=%d"
- "&is_summary=%d\">"
- "%d-%d</option> \n",
- ((WCC->msgarr[b] == startmsg) ? "selected" : ""),
- oper,
- WCC->msgarr[lo-1],
- maxmsgs,
- is_summary,
- lo, hi);
+
+ Msg = GetMessagePtrAt(b, WCC->summ);
+ n = (Msg==NULL)? 0 : Msg->msgnum;
+ selected = ((n == startmsg) ? "selected" : "");
+ Msg = GetMessagePtrAt(lo-1, WCC->summ);
+ StrBufAppendPrintf(Selector,
+ "<option %s value="
+ "\"%s"
+ "&startmsg=%ld"
+ "&maxmsgs=%d"
+ "&is_summary=%d\">"
+ "%d-%d</option> \n",
+ selected,
+ oper,
+ (Msg==NULL)? 0 : Msg->msgnum,
+ maxmsgs,
+ is_summary,
+ lo, hi);
}
}
- wprintf("<option value=\"%s?startmsg=%ld"
- "&maxmsgs=9999999&is_summary=%d\">",
+ StrBufAppendBuf(BBViewToolBar, Selector, 0);
+
+ Msg = GetMessagePtrAt(0, WCC->summ);
+
+ StrBufAppendPrintf(BBViewToolBar, "<option value=\"%s?startmsg=%ld"
+ "&maxmsgs=9999999&is_summary=0\">",
oper,
- WCC->msgarr[0], is_summary);
- wprintf(_("All"));
- wprintf("</option>");
- wprintf("</select> ");
- wprintf(_("of %d messages."), nummsgs);
+ (Msg==NULL)? 0 : Msg->msgnum);
+ StrBufAppendPrintf(BBViewToolBar, _("All"));
+
+ StrBufAppendPrintf(BBViewToolBar, "</option>");
+ StrBufAppendPrintf(BBViewToolBar, "</select> ");
+ StrBufAppendPrintf(BBViewToolBar, _("of %d messages."), nummsgs);
/** forward/reverse */
- wprintf("<input type=\"radio\" %s name=\"direction\" value=\"\""
+ StrBufAppendPrintf(BBViewToolBar, "<input type=\"radio\" %s name=\"direction\" value=\"\""
"OnChange=\"location.href='%s?sortby=forward'\"",
(bbs_reverse ? "" : "checked"),
oper
);
- wprintf(">");
- wprintf(_("oldest to newest"));
- wprintf(" ");
+ StrBufAppendPrintf(BBViewToolBar, ">");
+ StrBufAppendPrintf(BBViewToolBar, _("oldest to newest"));
+ StrBufAppendPrintf(BBViewToolBar, " ");
- wprintf("<input type=\"radio\" %s name=\"direction\" value=\"\""
+ StrBufAppendPrintf(BBViewToolBar, "<input type=\"radio\" %s name=\"direction\" value=\"\""
"OnChange=\"location.href='%s?sortby=reverse'\"",
(bbs_reverse ? "checked" : ""),
oper
);
- wprintf(">");
- wprintf(_("newest to oldest"));
- wprintf("\n");
+ StrBufAppendPrintf(BBViewToolBar, ">");
+ StrBufAppendPrintf(BBViewToolBar, _("newest to oldest"));
+ StrBufAppendPrintf(BBViewToolBar, "\n");
- wprintf("</p></form>\n");
+ StrBufAppendPrintf(BBViewToolBar, "</p></form>\n");
+ StrBufAppendBuf(WCC->WBuf, BBViewToolBar, 0);
/** end bbview scroller */
}
/** Output loop */
if (displayed_msgs != NULL) {
if (bbs_reverse) {
- qsort(displayed_msgs, num_displayed, sizeof(long), qlongcmp_r);
+ ////TODOqsort(displayed_msgs, num_displayed, sizeof(long), qlongcmp_r);
}
/** if we do a split bbview in the future, begin messages div here */
*/
if (is_bbview) {
/** begin bbview scroller */
- wprintf("<form name=\"msgomatic\" class=\"selector_bottom\" > \n <p>");
- wprintf(_("Reading #")); /// TODO: this isn't used: , lowest_displayed, highest_displayed);
-
- wprintf("<select name=\"whichones\" size=\"1\" "
- "OnChange=\"location.href=msgomatic.whichones.options"
- "[selectedIndex].value\">\n");
-
- if (bbs_reverse) {
- for (b=nummsgs-1; b>=0; b = b - maxmsgs) {
- hi = b + 1;
- lo = b - maxmsgs + 2;
- if (lo < 1) lo = 1;
- wprintf("<option %s value="
- "\"%s"
- "&startmsg=%ld"
- "&maxmsgs=%d"
- "&is_summary=%d\">"
- "%d-%d</option> \n",
- ((WCC->msgarr[lo-1] == startmsg) ? "selected" : ""),
- oper,
- WCC->msgarr[lo-1],
- maxmsgs,
- is_summary,
- hi, lo);
- }
- }
- else {
- for (b=0; b<nummsgs; b = b + maxmsgs) {
- lo = b + 1;
- hi = b + maxmsgs + 1;
- if (hi > nummsgs) hi = nummsgs;
- wprintf("<option %s value="
- "\"%s"
- "&startmsg=%ld"
- "&maxmsgs=%d"
- "&is_summary=%d\">"
- "%d-%d</option> \n",
- ((WCC->msgarr[b] == startmsg) ? "selected" : ""),
- oper,
- WCC->msgarr[lo-1],
- maxmsgs,
- is_summary,
- lo, hi);
- }
- }
-
- wprintf("<option value=\"%s&startmsg=%ld"
- "&maxmsgs=9999999&is_summary=%d\">",
- oper,
- WCC->msgarr[0], is_summary);
- wprintf(_("All"));
- wprintf("</option>");
- wprintf("</select> ");
- wprintf(_("of %d messages."), nummsgs);
-
- /** forward/reverse */
- wprintf("<input type=\"radio\" %s name=\"direction\" value=\"\""
- "OnChange=\"location.href='%s&sortby=forward'\"",
- (bbs_reverse ? "" : "checked"),
- oper
- );
- wprintf(">");
- wprintf(_("oldest to newest"));
- wprintf(" ");
- wprintf("<input type=\"radio\" %s name=\"direction\" value=\"\""
- "OnChange=\"location.href='%s&sortby=reverse'\"",
- (bbs_reverse ? "checked" : ""),
- oper
- );
- wprintf(">");
- wprintf(_("newest to oldest"));
- wprintf("\n");
-
- wprintf("</p></form>\n");
- /** end bbview scroller */
+ StrBufAppendBuf(WCC->WBuf, BBViewToolBar, 0);
}
DONE:
WebcitAddUrlHandler(HKEY("mobilemsg"), mobile_message_view, NEED_URL);
WebcitAddUrlHandler(HKEY("msgheaders"), display_headers, NEED_URL);
+
return ;
}
HashList *GlobalNS;
HashList *Iterators;
HashList *Conditionals;
+HashList *SortHash;
int LoadTemplates = 0;
}HashHandler;
void *load_template(StrBuf *filename, StrBuf *Key, HashList *PutThere);
+int EvaluateConditional(StrBuf *Target, WCTemplateToken *Tokens, WCTemplate *pTmpl, void *Context, int Neg, int state, int ContextType);
void RegisterNS(const char *NSName,
long len,
}
}
-
-/**
- * \brief puts string into the template and computes which escape methon we should use
- * \param Source the string we should put into the template
- * \param FormatTypeIndex where should we look for escape types if?
- */
-void StrBufAppendTemplate(StrBuf *Target,
- int nArgs,
- WCTemplateToken *Tokens,
- void *Context, int ContextType,
- const StrBuf *Source, int FormatTypeIndex)
-{
- struct wcsession *WCC;
- StrBuf *Buf;
- char EscapeAs = ' ';
-
- if ((FormatTypeIndex < Tokens->nParameters) &&
- (Tokens->Params[FormatTypeIndex]->Type == TYPE_STR) &&
- (Tokens->Params[FormatTypeIndex]->len == 1)) {
- EscapeAs = *Tokens->Params[FormatTypeIndex]->Start;
- }
-
- switch(EscapeAs)
- {
- case 'H':
- WCC = WC;
- Buf = NewStrBufPlain(NULL, StrLength(Source));
- StrBuf_RFC822_to_Utf8(Buf,
- Source,
- (WCC!=NULL)? WCC->DefaultCharset : NULL,
- NULL);
- StrEscAppend(Target, Buf, NULL, 0, 0);
- FreeStrBuf(&Buf);
- break;
- case 'X':
- StrEscAppend(Target, Source, NULL, 0, 0);
- break;
- default:
- StrBufAppendBuf(Target, Source, 0);
- }
-}
-
-
void GetTemplateTokenString(WCTemplateToken *Tokens,
int N,
const char **Value,
}
+
+/**
+ * \brief puts string into the template and computes which escape methon we should use
+ * \param Source the string we should put into the template
+ * \param FormatTypeIndex where should we look for escape types if?
+ */
+void StrBufAppendTemplate(StrBuf *Target,
+ int nArgs,
+ WCTemplateToken *Tokens,
+ void *Context, int ContextType,
+ const StrBuf *Source, int FormatTypeIndex)
+{
+ struct wcsession *WCC;
+ StrBuf *Buf;
+ char EscapeAs = ' ';
+
+ if ((FormatTypeIndex < Tokens->nParameters) &&
+ (Tokens->Params[FormatTypeIndex]->Type == TYPE_STR) &&
+ (Tokens->Params[FormatTypeIndex]->len == 1)) {
+ EscapeAs = *Tokens->Params[FormatTypeIndex]->Start;
+ }
+
+ switch(EscapeAs)
+ {
+ case 'H':
+ WCC = WC;
+ Buf = NewStrBufPlain(NULL, StrLength(Source));
+ StrBuf_RFC822_to_Utf8(Buf,
+ Source,
+ (WCC!=NULL)? WCC->DefaultCharset : NULL,
+ NULL);
+ StrEscAppend(Target, Buf, NULL, 0, 0);
+ FreeStrBuf(&Buf);
+ break;
+ case 'X':
+ StrEscAppend(Target, Source, NULL, 0, 0);
+ break;
+ default:
+ StrBufAppendBuf(Target, Source, 0);
+ }
+}
+
+
void PutNewToken(WCTemplate *Template, WCTemplateToken *NewToken)
{
if (Template->nTokensUsed + 1 >= Template->TokenSpace) {
-int EvaluateConditional(StrBuf *Target, WCTemplateToken *Tokens, WCTemplate *pTmpl, void *Context, int Neg, int state, int ContextType)
-{
- ConditionalStruct *Cond;
- if ((Tokens->Params[0]->len == 1) &&
- (Tokens->Params[0]->Start[0] == 'X'))
- return (state != 0)?Tokens->Params[1]->lvalue:0;
-
- Cond = (ConditionalStruct *) Tokens->PreEval;
- if (Cond == NULL) {
- lprintf(1, "Conditional [%s] (in '%s' line %ld); unknown![%s]\n",
- Tokens->Params[0]->Start,
- ChrPtr(pTmpl->FileName),
- Tokens->Line,
- ChrPtr(Tokens->FlatToken));
- return 1;
- }
- if (Tokens->nParameters < Cond->nParams) {
- lprintf(1, "Conditional [%s] (in '%s' line %ld); needs %ld Params![%s]\n",
- Tokens->Params[0]->Start,
- ChrPtr(pTmpl->FileName),
- Tokens->Line,
- Cond->nParams,
- ChrPtr(Tokens->FlatToken));
- StrBufAppendPrintf(
- Target,
- "<pre>\nConditional [%s] (in '%s' line %ld); needs %ld Params!\n[%s]\n</pre>\n",
- Tokens->Params[0]->Start,
- ChrPtr(pTmpl->FileName),
- Tokens->Line,
- Cond->nParams,
- ChrPtr(Tokens->FlatToken));
- return 0;
- }
- if (Cond->CondF(Tokens, Context, ContextType) == Neg)
- return Tokens->Params[1]->lvalue;
- return 0;
+/**
+ * \brief Display a variable-substituted template
+ * \param templatename template file to load
+ */
+void *prepare_template(StrBuf *filename, StrBuf *Key, HashList *PutThere)
+{
+ WCTemplate *NewTemplate;
+ NewTemplate = (WCTemplate *) malloc(sizeof(WCTemplate));
+ NewTemplate->Data = NULL;
+ NewTemplate->FileName = NewStrBufDup(filename);
+ NewTemplate->nTokensUsed = 0;
+ NewTemplate->TokenSpace = 0;
+ NewTemplate->Tokens = NULL;
+
+ Put(PutThere, ChrPtr(Key), StrLength(Key), NewTemplate, FreeWCTemplate);
+ return NewTemplate;
}
/**
- * \brief executes one token
- * \param Target buffer to append to
- * \param Token da to process.
- * \param Template we're iterating
- * \param Context Contextpoointer to pass in
- * \param state are we in conditional state?
- * \param ContextType what type of information does context giv us?
+ * \brief Display a variable-substituted template
+ * \param templatename template file to load
*/
-int EvaluateToken(StrBuf *Target, WCTemplateToken *Tokens, WCTemplate *pTmpl, void *Context, int state, int ContextType)
+void *load_template(StrBuf *filename, StrBuf *Key, HashList *PutThere)
{
- HashHandler *Handler;
- void *vVar;
-// much output, since pName is not terminated...
-// lprintf(1,"Doing token: %s\n",Token->pName);
+ int fd;
+ struct stat statbuf;
+ const char *pS, *pE, *pch, *Err;
+ long Line;
+ int pos;
+ WCTemplate *NewTemplate;
- switch (Tokens->Flags) {
- case SV_GETTEXT:
- TmplGettext(Target, Tokens->nParameters, Tokens);
- break;
- case SV_CONDITIONAL: /** Forward conditional evaluation */
- return EvaluateConditional(Target, Tokens, pTmpl, Context, 1, state, ContextType);
- break;
- case SV_NEG_CONDITIONAL: /** Reverse conditional evaluation */
- return EvaluateConditional(Target, Tokens, pTmpl, Context, 0, state, ContextType);
- break;
- case SV_CUST_STR_CONDITIONAL: /** Conditional put custom strings from params */
- if (Tokens->nParameters >= 6) {
- if (EvaluateConditional(Target, Tokens, pTmpl, Context, 0, state, ContextType))
- StrBufAppendBufPlain(Target,
- Tokens->Params[5]->Start,
- Tokens->Params[5]->len,
- 0);
- else
- StrBufAppendBufPlain(Target,
- Tokens->Params[4]->Start,
- Tokens->Params[4]->len,
- 0);
+ fd = open(ChrPtr(filename), O_RDONLY);
+ if (fd <= 0) {
+ lprintf(1, "ERROR: could not open template '%s' - %s\n",
+ ChrPtr(filename), strerror(errno));
+ return NULL;
+ }
+
+ if (fstat(fd, &statbuf) == -1) {
+ lprintf(1, "ERROR: could not stat template '%s' - %s\n",
+ ChrPtr(filename), strerror(errno));
+ return NULL;
+ }
+
+ NewTemplate = (WCTemplate *) malloc(sizeof(WCTemplate));
+ NewTemplate->Data = NewStrBufPlain(NULL, statbuf.st_size);
+ NewTemplate->FileName = NewStrBufDup(filename);
+ NewTemplate->nTokensUsed = 0;
+ NewTemplate->TokenSpace = 0;
+ NewTemplate->Tokens = NULL;
+ if (StrBufReadBLOB(NewTemplate->Data, &fd, 1, statbuf.st_size, &Err) < 0) {
+ close(fd);
+ FreeWCTemplate(NewTemplate);
+ lprintf(1, "ERROR: reading template '%s' - %s<br />\n",
+ ChrPtr(filename), strerror(errno));
+ return NULL;
+ }
+ close(fd);
+
+ Line = 0;
+ pS = pch = ChrPtr(NewTemplate->Data);
+ pE = pS + StrLength(NewTemplate->Data);
+ while (pch < pE) {
+ const char *pts, *pte;
+ int InQuotes = 0;
+ int InDoubleQuotes = 0;
+
+ /** Find one <? > */
+ pos = (-1);
+ for (; pch < pE; pch ++) {
+ if ((*pch=='<')&&(*(pch + 1)=='?'))
+ break;
+ if (*pch=='\n') Line ++;
}
- else {
- lprintf(1, "Conditional [%s] (in '%s' line %ld); needs at least 6 Params![%s]\n",
- Tokens->Params[0]->Start,
- ChrPtr(pTmpl->FileName),
- Tokens->Line,
- ChrPtr(Tokens->FlatToken));
- StrBufAppendPrintf(
- Target,
- "<pre>\nConditional [%s] (in '%s' line %ld); needs 6 Params!\n[%s]\n</pre>\n",
- Tokens->Params[0]->Start,
- ChrPtr(pTmpl->FileName),
- Tokens->Line,
- ChrPtr(Tokens->FlatToken));
+ if (pch >= pE)
+ continue;
+ pts = pch;
+
+ /** Found one? parse it. */
+ for (; pch < pE - 1; pch ++) {
+ if (*pch == '"')
+ InDoubleQuotes = ! InDoubleQuotes;
+ else if (*pch == '\'')
+ InQuotes = ! InQuotes;
+ else if ((!InQuotes && !InDoubleQuotes) &&
+ ((*pch!='\\')&&(*(pch + 1)=='>'))) {
+ pch ++;
+ break;
+ }
}
- break;
- case SV_SUBTEMPL:
- if (Tokens->nParameters == 1)
- DoTemplate(Tokens->Params[0]->Start, Tokens->Params[0]->len, NULL, NULL, ContextType);
- break;
+ if (pch + 1 >= pE)
+ continue;
+ pte = pch;
+ PutNewToken(NewTemplate,
+ NewTemplateSubstitute(NewTemplate->Data, pS, pts, pte, Line, NewTemplate));
+ pch ++;
+ }
+ if (LoadTemplates == 0)
+ Put(PutThere, ChrPtr(Key), StrLength(Key), NewTemplate, FreeWCTemplate);
+ return NewTemplate;
+}
+
+
+///void PrintTemplate(const char *Key, void *vSubst, int odd)
+const char* PrintTemplate(void *vSubst)
+{
+ WCTemplate *Tmpl = vSubst;
+
+ return ChrPtr(Tmpl->FileName);
+
+}
+
+int LoadTemplateDir(const char *DirName, HashList *wireless, HashList *big)
+{
+ StrBuf *FileName;
+ StrBuf *Tag;
+ StrBuf *Dir;
+ DIR *filedir = NULL;
+ struct dirent *filedir_entry;
+ int d_namelen;
+ int d_without_ext;
+ int IsMobile;
+
+ Dir = NewStrBuf();
+ StrBufPrintf(Dir, "%s/t", DirName);
+ filedir = opendir (ChrPtr(Dir));
+ if (filedir == NULL) {
+ FreeStrBuf(&Dir);
+ return 0;
+ }
+
+ FileName = NewStrBuf();
+ Tag = NewStrBuf();
+ while ((filedir_entry = readdir(filedir)))
+ {
+ char *MinorPtr;
+ char *PStart;
+#ifdef _DIRENT_HAVE_D_NAMELEN
+ d_namelen = filedir_entry->d_namelen;
+#else
+ d_namelen = strlen(filedir_entry->d_name);
+#endif
+ d_without_ext = d_namelen;
+ while ((d_without_ext > 0) && (filedir_entry->d_name[d_without_ext] != '.'))
+ d_without_ext --;
+ if ((d_without_ext == 0) || (d_namelen < 3))
+ continue;
+ if ((d_namelen > 1) && filedir_entry->d_name[d_namelen - 1] == '~')
+ continue; /* Ignore backup files... */
+
+ IsMobile = (strstr(filedir_entry->d_name, ".m.html")!= NULL);
+ PStart = filedir_entry->d_name;
+ StrBufPrintf(FileName, "%s/%s", ChrPtr(Dir), filedir_entry->d_name);
+ MinorPtr = strchr(filedir_entry->d_name, '.');
+ if (MinorPtr != NULL)
+ *MinorPtr = '\0';
+ StrBufPlain(Tag, filedir_entry->d_name, MinorPtr - filedir_entry->d_name);
+
+ if (LoadTemplates > 1)
+ lprintf(1, "%s %d %s\n",ChrPtr(FileName), IsMobile, ChrPtr(Tag));
+ if (LoadTemplates == 0)
+ load_template(FileName, Tag, (IsMobile)?wireless:big);
+ else
+ prepare_template(FileName, Tag, (IsMobile)?wireless:big);
+ }
+ closedir(filedir);
+ FreeStrBuf(&FileName);
+ FreeStrBuf(&Tag);
+ FreeStrBuf(&Dir);
+ return 1;
+}
+
+void InitTemplateCache(void)
+{
+ LoadTemplateDir(static_dirs[0],
+ WirelessTemplateCache,
+ TemplateCache);
+ LoadTemplateDir(static_dirs[1],
+ WirelessLocalTemplateCache,
+ LocalTemplateCache);
+}
+
+
+
+/*-----------------------------------------------------------------------------
+ * Filling & processing Templates
+ */
+/**
+ * \brief executes one token
+ * \param Target buffer to append to
+ * \param Token da to process.
+ * \param Template we're iterating
+ * \param Context Contextpoointer to pass in
+ * \param state are we in conditional state?
+ * \param ContextType what type of information does context giv us?
+ */
+int EvaluateToken(StrBuf *Target, WCTemplateToken *Tokens, WCTemplate *pTmpl, void *Context, int state, int ContextType)
+{
+ HashHandler *Handler;
+ void *vVar;
+// much output, since pName is not terminated...
+// lprintf(1,"Doing token: %s\n",Token->pName);
+
+ switch (Tokens->Flags) {
+ case SV_GETTEXT:
+ TmplGettext(Target, Tokens->nParameters, Tokens);
+ break;
+ case SV_CONDITIONAL: /** Forward conditional evaluation */
+ return EvaluateConditional(Target, Tokens, pTmpl, Context, 1, state, ContextType);
+ break;
+ case SV_NEG_CONDITIONAL: /** Reverse conditional evaluation */
+ return EvaluateConditional(Target, Tokens, pTmpl, Context, 0, state, ContextType);
+ break;
+ case SV_CUST_STR_CONDITIONAL: /** Conditional put custom strings from params */
+ if (Tokens->nParameters >= 6) {
+ if (EvaluateConditional(Target, Tokens, pTmpl, Context, 0, state, ContextType))
+ StrBufAppendBufPlain(Target,
+ Tokens->Params[5]->Start,
+ Tokens->Params[5]->len,
+ 0);
+ else
+ StrBufAppendBufPlain(Target,
+ Tokens->Params[4]->Start,
+ Tokens->Params[4]->len,
+ 0);
+ }
+ else {
+ lprintf(1, "Conditional [%s] (in '%s' line %ld); needs at least 6 Params![%s]\n",
+ Tokens->Params[0]->Start,
+ ChrPtr(pTmpl->FileName),
+ Tokens->Line,
+ ChrPtr(Tokens->FlatToken));
+ StrBufAppendPrintf(
+ Target,
+ "<pre>\nConditional [%s] (in '%s' line %ld); needs 6 Params!\n[%s]\n</pre>\n",
+ Tokens->Params[0]->Start,
+ ChrPtr(pTmpl->FileName),
+ Tokens->Line,
+ ChrPtr(Tokens->FlatToken));
+ }
+ break;
+ case SV_SUBTEMPL:
+ if (Tokens->nParameters == 1)
+ DoTemplate(Tokens->Params[0]->Start, Tokens->Params[0]->len, NULL, NULL, ContextType);
+ break;
case SV_PREEVALUATED:
Handler = (HashHandler*) Tokens->PreEval;
if ((Handler->ContextRequired != CTX_NONE) &&
return 0;
}
+
+
void ProcessTemplate(WCTemplate *Tmpl, StrBuf *Target, void *Context, int ContextType)
{
WCTemplate *pTmpl = Tmpl;
}
}
-
-/**
- * \brief Display a variable-substituted template
- * \param templatename template file to load
- */
-void *prepare_template(StrBuf *filename, StrBuf *Key, HashList *PutThere)
-{
- WCTemplate *NewTemplate;
- NewTemplate = (WCTemplate *) malloc(sizeof(WCTemplate));
- NewTemplate->Data = NULL;
- NewTemplate->FileName = NewStrBufDup(filename);
- NewTemplate->nTokensUsed = 0;
- NewTemplate->TokenSpace = 0;
- NewTemplate->Tokens = NULL;
-
- Put(PutThere, ChrPtr(Key), StrLength(Key), NewTemplate, FreeWCTemplate);
- return NewTemplate;
-}
-
-/**
- * \brief Display a variable-substituted template
- * \param templatename template file to load
- */
-void *load_template(StrBuf *filename, StrBuf *Key, HashList *PutThere)
-{
- int fd;
- struct stat statbuf;
- const char *pS, *pE, *pch, *Err;
- long Line;
- int pos;
- WCTemplate *NewTemplate;
-
- fd = open(ChrPtr(filename), O_RDONLY);
- if (fd <= 0) {
- lprintf(1, "ERROR: could not open template '%s' - %s\n",
- ChrPtr(filename), strerror(errno));
- return NULL;
- }
-
- if (fstat(fd, &statbuf) == -1) {
- lprintf(1, "ERROR: could not stat template '%s' - %s\n",
- ChrPtr(filename), strerror(errno));
- return NULL;
- }
-
- NewTemplate = (WCTemplate *) malloc(sizeof(WCTemplate));
- NewTemplate->Data = NewStrBufPlain(NULL, statbuf.st_size);
- NewTemplate->FileName = NewStrBufDup(filename);
- NewTemplate->nTokensUsed = 0;
- NewTemplate->TokenSpace = 0;
- NewTemplate->Tokens = NULL;
- if (StrBufReadBLOB(NewTemplate->Data, &fd, 1, statbuf.st_size, &Err) < 0) {
- close(fd);
- FreeWCTemplate(NewTemplate);
- lprintf(1, "ERROR: reading template '%s' - %s<br />\n",
- ChrPtr(filename), strerror(errno));
- return NULL;
- }
- close(fd);
-
- Line = 0;
- pS = pch = ChrPtr(NewTemplate->Data);
- pE = pS + StrLength(NewTemplate->Data);
- while (pch < pE) {
- const char *pts, *pte;
- int InQuotes = 0;
- int InDoubleQuotes = 0;
-
- /** Find one <? > */
- pos = (-1);
- for (; pch < pE; pch ++) {
- if ((*pch=='<')&&(*(pch + 1)=='?'))
- break;
- if (*pch=='\n') Line ++;
- }
- if (pch >= pE)
- continue;
- pts = pch;
-
- /** Found one? parse it. */
- for (; pch < pE - 1; pch ++) {
- if (*pch == '"')
- InDoubleQuotes = ! InDoubleQuotes;
- else if (*pch == '\'')
- InQuotes = ! InQuotes;
- else if ((!InQuotes && !InDoubleQuotes) &&
- ((*pch!='\\')&&(*(pch + 1)=='>'))) {
- pch ++;
- break;
- }
- }
- if (pch + 1 >= pE)
- continue;
- pte = pch;
- PutNewToken(NewTemplate,
- NewTemplateSubstitute(NewTemplate->Data, pS, pts, pte, Line, NewTemplate));
- pch ++;
- }
- if (LoadTemplates == 0)
- Put(PutThere, ChrPtr(Key), StrLength(Key), NewTemplate, FreeWCTemplate);
- return NewTemplate;
-}
-
-
-///void PrintTemplate(const char *Key, void *vSubst, int odd)
-const char* PrintTemplate(void *vSubst)
-{
- WCTemplate *Tmpl = vSubst;
-
- return ChrPtr(Tmpl->FileName);
-
-}
-
-
/**
* \brief Display a variable-substituted template
* \param templatename template file to load
StaticLocal = LocalTemplateCache;
}
- if (len == 0)
- {
- lprintf (1, "Can't to load a template with empty name!\n");
- StrBufAppendPrintf(Target, "<pre>\nCan't to load a template with empty name!\n</pre>");
- return;
- }
-
- if (!GetHash(StaticLocal, templatename, len, &vTmpl) &&
- !GetHash(Static, templatename, len, &vTmpl)) {
- lprintf (1, "didn't find Template [%s] %ld %ld\n", templatename, len , (long)strlen(templatename));
- StrBufAppendPrintf(Target, "<pre>\ndidn't find Template [%s] %ld %ld\n</pre>",
- templatename, len,
- (long)strlen(templatename));
-/// dbg_PrintHash(Static, PrintTemplate, NULL);
-// PrintHash(Static, VarPrintTransition, PrintTemplate);
- return;
- }
- if (vTmpl == NULL)
- return;
- ProcessTemplate(vTmpl, Target, Context, ContextType);
-}
-
-int LoadTemplateDir(const char *DirName, HashList *wireless, HashList *big)
-{
- StrBuf *FileName;
- StrBuf *Tag;
- StrBuf *Dir;
- DIR *filedir = NULL;
- struct dirent *filedir_entry;
- int d_namelen;
- int d_without_ext;
- int IsMobile;
-
- Dir = NewStrBuf();
- StrBufPrintf(Dir, "%s/t", DirName);
- filedir = opendir (ChrPtr(Dir));
- if (filedir == NULL) {
- FreeStrBuf(&Dir);
- return 0;
- }
-
- FileName = NewStrBuf();
- Tag = NewStrBuf();
- while ((filedir_entry = readdir(filedir)))
- {
- char *MinorPtr;
- char *PStart;
-#ifdef _DIRENT_HAVE_D_NAMELEN
- d_namelen = filedir_entry->d_namelen;
-#else
- d_namelen = strlen(filedir_entry->d_name);
-#endif
- d_without_ext = d_namelen;
- while ((d_without_ext > 0) && (filedir_entry->d_name[d_without_ext] != '.'))
- d_without_ext --;
- if ((d_without_ext == 0) || (d_namelen < 3))
- continue;
- if ((d_namelen > 1) && filedir_entry->d_name[d_namelen - 1] == '~')
- continue; /* Ignore backup files... */
-
- IsMobile = (strstr(filedir_entry->d_name, ".m.html")!= NULL);
- PStart = filedir_entry->d_name;
- StrBufPrintf(FileName, "%s/%s", ChrPtr(Dir), filedir_entry->d_name);
- MinorPtr = strchr(filedir_entry->d_name, '.');
- if (MinorPtr != NULL)
- *MinorPtr = '\0';
- StrBufPlain(Tag, filedir_entry->d_name, MinorPtr - filedir_entry->d_name);
-
- if (LoadTemplates > 1)
- lprintf(1, "%s %d %s\n",ChrPtr(FileName), IsMobile, ChrPtr(Tag));
- if (LoadTemplates == 0)
- load_template(FileName, Tag, (IsMobile)?wireless:big);
- else
- prepare_template(FileName, Tag, (IsMobile)?wireless:big);
+ if (len == 0)
+ {
+ lprintf (1, "Can't to load a template with empty name!\n");
+ StrBufAppendPrintf(Target, "<pre>\nCan't to load a template with empty name!\n</pre>");
+ return;
}
- closedir(filedir);
- FreeStrBuf(&FileName);
- FreeStrBuf(&Tag);
- FreeStrBuf(&Dir);
- return 1;
-}
-void InitTemplateCache(void)
-{
- LoadTemplateDir(static_dirs[0],
- WirelessTemplateCache,
- TemplateCache);
- LoadTemplateDir(static_dirs[1],
- WirelessLocalTemplateCache,
- LocalTemplateCache);
+ if (!GetHash(StaticLocal, templatename, len, &vTmpl) &&
+ !GetHash(Static, templatename, len, &vTmpl)) {
+ lprintf (1, "didn't find Template [%s] %ld %ld\n", templatename, len , (long)strlen(templatename));
+ StrBufAppendPrintf(Target, "<pre>\ndidn't find Template [%s] %ld %ld\n</pre>",
+ templatename, len,
+ (long)strlen(templatename));
+/// dbg_PrintHash(Static, PrintTemplate, NULL);
+// PrintHash(Static, VarPrintTransition, PrintTemplate);
+ return;
+ }
+ if (vTmpl == NULL)
+ return;
+ ProcessTemplate(vTmpl, Target, Context, ContextType);
}
-
-
+/*-----------------------------------------------------------------------------
+ * Iterators
+ */
typedef struct _HashIterator {
HashList *StaticList;
int AdditionalParams;
SubTemplFunc DoSubTemplate;
} HashIterator;
+void RegisterITERATOR(const char *Name, long len,
+ int AdditionalParams,
+ HashList *StaticList,
+ RetrieveHashlistFunc GetHash,
+ SubTemplFunc DoSubTempl,
+ HashDestructorFunc Destructor,
+ int ContextType,
+ int XPectContextType)
+{
+ HashIterator *It = (HashIterator*)malloc(sizeof(HashIterator));
+ It->StaticList = StaticList;
+ It->AdditionalParams = AdditionalParams;
+ It->GetHash = GetHash;
+ It->DoSubTemplate = DoSubTempl;
+ It->Destructor = Destructor;
+ It->ContextType = ContextType;
+ It->XPectContextType = XPectContextType;
+ Put(Iterators, Name, len, It, NULL);
+}
+
void tmpl_iterate_subtmpl(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
{
void *vIt;
}
-
-
-
if (It->StaticList == NULL)
List = It->GetHash(Target, nArgs, Tokens, Context, ContextType);
else
It->Destructor(&List);
}
+
+
+/*-----------------------------------------------------------------------------
+ * Conditionals
+ */
+int EvaluateConditional(StrBuf *Target, WCTemplateToken *Tokens, WCTemplate *pTmpl, void *Context, int Neg, int state, int ContextType)
+{
+ ConditionalStruct *Cond;
+
+ if ((Tokens->Params[0]->len == 1) &&
+ (Tokens->Params[0]->Start[0] == 'X'))
+ return (state != 0)?Tokens->Params[1]->lvalue:0;
+
+ Cond = (ConditionalStruct *) Tokens->PreEval;
+ if (Cond == NULL) {
+ lprintf(1, "Conditional [%s] (in '%s' line %ld); unknown![%s]\n",
+ Tokens->Params[0]->Start,
+ ChrPtr(pTmpl->FileName),
+ Tokens->Line,
+ ChrPtr(Tokens->FlatToken));
+ return 1;
+ }
+
+ if (Tokens->nParameters < Cond->nParams) {
+ lprintf(1, "Conditional [%s] (in '%s' line %ld); needs %ld Params![%s]\n",
+ Tokens->Params[0]->Start,
+ ChrPtr(pTmpl->FileName),
+ Tokens->Line,
+ Cond->nParams,
+ ChrPtr(Tokens->FlatToken));
+ StrBufAppendPrintf(
+ Target,
+ "<pre>\nConditional [%s] (in '%s' line %ld); needs %ld Params!\n[%s]\n</pre>\n",
+ Tokens->Params[0]->Start,
+ ChrPtr(pTmpl->FileName),
+ Tokens->Line,
+ Cond->nParams,
+ ChrPtr(Tokens->FlatToken));
+ return 0;
+ }
+ if (Cond->CondF(Tokens, Context, ContextType) == Neg)
+ return Tokens->Params[1]->lvalue;
+ return 0;
+}
+
int ConditionalVar(WCTemplateToken *Tokens, void *Context, int ContextType)
{
void *vsubst;
return 0;
}
-void RegisterITERATOR(const char *Name, long len,
- int AdditionalParams,
- HashList *StaticList,
- RetrieveHashlistFunc GetHash,
- SubTemplFunc DoSubTempl,
- HashDestructorFunc Destructor,
- int ContextType,
- int XPectContextType)
-{
- HashIterator *It = (HashIterator*)malloc(sizeof(HashIterator));
- It->StaticList = StaticList;
- It->AdditionalParams = AdditionalParams;
- It->GetHash = GetHash;
- It->DoSubTemplate = DoSubTempl;
- It->Destructor = Destructor;
- It->ContextType = ContextType;
- It->XPectContextType = XPectContextType;
- Put(Iterators, Name, len, It, NULL);
-}
void RegisterConditional(const char *Name, long len,
int nParams,
Put(Conditionals, Name, len, Cond, NULL);
}
-
+/*-----------------------------------------------------------------------------
+ * Context Strings
+ */
void tmplput_ContextString(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
{
StrBufAppendTemplate(Target, nArgs, Tokens, Context, ContextType, (StrBuf*)Context, 0);
return strcmp(ChrPtr(TokenText), CompareToken) == 0;
}
+/*-----------------------------------------------------------------------------
+ * Boxed-API
+ */
void tmpl_do_boxed(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
{
Context,
ContextType);
DoTemplate(HKEY("endbox"), Target, Context, ContextType);
- FreeStrBuf(Headline);
+ FreeStrBuf(&Headline);
}
+/*-----------------------------------------------------------------------------
+ * Tabbed-API
+ */
void tmpl_do_tabbed(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
{
}
}
+
+/*-----------------------------------------------------------------------------
+ * Sorting-API
+ */
+
+typedef struct _SortStruct {
+ StrBuf *Name;
+ StrBuf *PrefPrepend;
+ CompareFunc Forward;
+ CompareFunc Reverse;
+
+ long ContextType;
+}SortStruct;
+
+void DestroySortStruct(void *vSort)
+{
+ SortStruct *Sort = (SortStruct*) vSort;
+ FreeStrBuf(&Sort->Name);
+ FreeStrBuf(&Sort->PrefPrepend);
+ free (Sort);
+}
+
+void RegisterSortFunc(const char *name, long len,
+ const char *prepend, long preplen,
+ CompareFunc Forward,
+ CompareFunc Reverse,
+ long ContextType)
+{
+ SortStruct *NewSort = (SortStruct*) malloc(sizeof(SortStruct));
+ NewSort->Name = NewStrBufPlain(name, len);
+ if (prepend != NULL)
+ NewSort->PrefPrepend = NewStrBufPlain(prepend, preplen);
+ else
+ NewSort->PrefPrepend = NULL;
+ NewSort->Forward = Forward;
+ NewSort->Reverse = Reverse;
+ NewSort->ContextType = ContextType;
+ Put(SortHash, name, len, NewSort, DestroySortStruct);
+}
+
+CompareFunc RetrieveSort(long ContextType, const char *OtherPrefix,
+ const char *Default, long ldefault, long DefaultDirection)
+{
+ int isdefault = 0;
+ const StrBuf *BSort;
+ SortStruct *SortBy;
+ void *vSortBy;
+ long SortOrder;
+
+ if (havebstr("SortBy")) {
+ BSort = sbstr("SortBy");
+ }
+ else { /** Try to fallback to our remembered values... */
+ if (OtherPrefix == NULL) {
+ BSort = get_room_pref("sort");
+ }
+ else {
+ ////todo: nail prefprepend to sort, and lookup this!
+ }
+ }
+
+ if (!GetHash(SortHash, SKEY(BSort), &vSortBy) ||
+ (vSortBy == NULL)) {
+ isdefault = 1;
+ if (!GetHash(SortHash, Default, ldefault, &vSortBy) ||
+ (vSortBy == NULL)) {
+ lprintf(1, "Illegal default sort: [%s]\n", Default);
+ wc_backtrace();
+ }
+ }
+ SortBy = (SortStruct*)vSortBy;
+
+ /** Ok, its us, lets see in which direction we should sort... */
+ if (havebstr("SortOrder")) {
+ SortOrder = LBSTR("SortOrder");
+ }
+ else { /** Try to fallback to our remembered values... */
+ if (SortBy->PrefPrepend == NULL) {
+ SortOrder = StrTol(get_room_pref("SortOrder"));
+ }
+ else {
+ ////todo: nail prefprepend to sort, and lookup this!
+ }
+ }
+ switch (SortOrder) {
+ default:
+ case 0:
+ return NULL;
+ case 1:
+ return SortBy->Forward;
+ case 2:
+ return SortBy->Reverse;
+ }
+}
+
+
+enum {
+ eNO_SUCH_SORT,
+ eNOT_SPECIFIED,
+ eINVALID_PARAM,
+ eFOUND
+};
+
+ConstStr SortIcons[] = {
+ {HKEY("static/sort_none.gif")},
+ {HKEY("static/up_pointer.gif")},
+ {HKEY("static/down_pointer.gif")},
+};
+
+ConstStr SortNextOrder[] = {
+ {HKEY("1")},
+ {HKEY("2")},
+ {HKEY("0")},
+};
+
+
+int GetSortMetric(WCTemplateToken *Tokens, SortStruct **Next, SortStruct **Param, long *SortOrder)
+{
+ int bSortError = eNOT_SPECIFIED;
+ const StrBuf *BSort;
+ void *vSort;
+
+ *SortOrder = 0;
+ *Next = NULL;
+ if (!GetHash(SortHash, Tokens->Params[0]->Start, Tokens->Params[0]->len, &vSort) ||
+ (vSort == NULL))
+ return eNO_SUCH_SORT;
+ *Param = (SortStruct*) vSort;
+
+
+ if (havebstr("SortBy")) {
+ BSort = sbstr("SortBy");
+ bSortError = eINVALID_PARAM;
+ }
+ else { /** Try to fallback to our remembered values... */
+ if ((*Param)->PrefPrepend == NULL) {
+ BSort = get_room_pref("sort");
+ }
+ else {
+ ////todo: nail prefprepend to sort, and lookup this!
+ }
+ }
+
+ if (!GetHash(SortHash, SKEY(BSort), &vSort) ||
+ (vSort == NULL))
+ return bSortError;
+
+ *Next = (SortStruct*) vSort;
+
+ /** Ok, its us, lets see in which direction we should sort... */
+ if (havebstr("SortOrder")) {
+ *SortOrder = LBSTR("SortOrder");
+ }
+ else { /** Try to fallback to our remembered values... */
+ if ((*Param)->PrefPrepend == NULL) {
+ *SortOrder = StrTol(get_room_pref("SortOrder"));
+ }
+ else {
+ ////todo: nail prefprepend to sort, and lookup this!
+ }
+ }
+ if (*SortOrder > 2)
+ *SortOrder = 0;
+
+ return eFOUND;
+}
+
+
+void tmplput_SORT_ICON(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
+{
+ long SortOrder;
+ SortStruct *Next;
+ SortStruct *Param;
+ const ConstStr *SortIcon;
+
+ switch (GetSortMetric(Tokens, &Next, &Param, &SortOrder)){
+ case eNO_SUCH_SORT:
+ lprintf(1, "[%s] (in '%s' line %ld); "
+ " Sorter [%s] unknown! [%s]\n",
+ Tokens->pName,
+ ChrPtr(Tokens->FileName),
+ Tokens->Line,
+ Tokens->Params[0]->Start,
+ ChrPtr(Tokens->FlatToken));
+ StrBufAppendPrintf(
+ Target,
+ "<pre>\n [%s] (in '%s' line %ld);"
+ " Sorter [%s] unknown!\n[%s]\n</pre>\n",
+ Tokens->pName,
+ ChrPtr(Tokens->FileName),
+ Tokens->Line,
+ Tokens->Params[0]->Start,
+ ChrPtr(Tokens->FlatToken));
+ break;
+ case eINVALID_PARAM:
+ lprintf(1, "[%s] (in '%s' line %ld); "
+ " Sorter specified by BSTR 'SortBy' [%s] unknown! [%s]\n",
+ Tokens->pName,
+ ChrPtr(Tokens->FileName),
+ Tokens->Line,
+ bstr("SortBy"),
+ ChrPtr(Tokens->FlatToken));
+ case eNOT_SPECIFIED:
+ case eFOUND:
+ if (Next == Param) {
+ SortIcon = &SortIcons[SortOrder];
+ }
+ else { /** Not Us... */
+ SortIcon = &SortIcons[0];
+ }
+ StrBufAppendBufPlain(Target, SortIcon->Key, SortIcon->len, 0);
+ }
+}
+
+void tmplput_SORT_NEXT(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
+{
+ long SortOrder;
+ SortStruct *Next;
+ SortStruct *Param;
+
+ switch (GetSortMetric(Tokens, &Next, &Param, &SortOrder)){
+ case eNO_SUCH_SORT:
+ lprintf(1, "[%s] (in '%s' line %ld); "
+ " Sorter [%s] unknown! [%s]\n",
+ Tokens->pName,
+ ChrPtr(Tokens->FileName),
+ Tokens->Line,
+ Tokens->Params[0]->Start,
+ ChrPtr(Tokens->FlatToken));
+ StrBufAppendPrintf(
+ Target,
+ "<pre>\n [%s] (in '%s' line %ld);"
+ " Sorter [%s] unknown!\n[%s]\n</pre>\n",
+ Tokens->pName,
+ ChrPtr(Tokens->FileName),
+ Tokens->Line,
+ Tokens->Params[0]->Start,
+ ChrPtr(Tokens->FlatToken));
+ break;
+ case eINVALID_PARAM:
+ lprintf(1, "[%s] (in '%s' line %ld); "
+ " Sorter specified by BSTR 'SortBy' [%s] unknown! [%s]\n",
+ Tokens->pName,
+ ChrPtr(Tokens->FileName),
+ Tokens->Line,
+ bstr("SortBy"),
+ ChrPtr(Tokens->FlatToken));
+
+ case eNOT_SPECIFIED:
+ case eFOUND:
+ StrBufAppendBuf(Target, Param->Name, 0);
+
+ }
+}
+
+void tmplput_SORT_ORDER(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
+{
+ long SortOrder;
+ const ConstStr *SortOrderStr;
+ SortStruct *Next;
+ SortStruct *Param;
+
+ switch (GetSortMetric(Tokens, &Next, &Param, &SortOrder)){
+ case eNO_SUCH_SORT:
+ lprintf(1, "[%s] (in '%s' line %ld); "
+ " Sorter [%s] unknown! [%s]\n",
+ Tokens->pName,
+ ChrPtr(Tokens->FileName),
+ Tokens->Line,
+ Tokens->Params[0]->Start,
+ ChrPtr(Tokens->FlatToken));
+ StrBufAppendPrintf(
+ Target,
+ "<pre>\n [%s] (in '%s' line %ld);"
+ " Sorter [%s] unknown!\n[%s]\n</pre>\n",
+ Tokens->pName,
+ ChrPtr(Tokens->FileName),
+ Tokens->Line,
+ Tokens->Params[0]->Start,
+ ChrPtr(Tokens->FlatToken));
+ break;
+ case eINVALID_PARAM:
+ lprintf(1, "[%s] (in '%s' line %ld); "
+ " Sorter specified by BSTR 'SortBy' [%s] unknown! [%s]\n",
+ Tokens->pName,
+ ChrPtr(Tokens->FileName),
+ Tokens->Line,
+ bstr("SortBy"),
+ ChrPtr(Tokens->FlatToken));
+
+ case eNOT_SPECIFIED:
+ case eFOUND:
+ if (Next == Param) {
+ SortOrderStr = &SortNextOrder[SortOrder];
+ }
+ else { /** Not Us... */
+ SortOrderStr = &SortNextOrder[0];
+ }
+ StrBufAppendBufPlain(Target, SortOrderStr->Key, SortOrderStr->len, 0);
+ }
+}
+
+
+
void
InitModule_SUBST
(void)
{
+ RegisterNamespace("SORT:ICON", 1, 1, tmplput_SORT_ICON, CTX_NONE);
+ RegisterNamespace("SORT:ORDER", 1, 1, tmplput_SORT_ORDER, CTX_NONE);
+ RegisterNamespace("SORT:NEXT", 1, 1, tmplput_SORT_NEXT, CTX_NONE);
RegisterNamespace("CONTEXTSTR", 0, 1, tmplput_ContextString, CTX_STRBUF);
RegisterNamespace("ITERATE", 2, 100, tmpl_iterate_subtmpl, CTX_NONE);
RegisterNamespace("DOBOXED", 1, 2, tmpl_do_boxed, CTX_NONE);