X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Fbbsview_renderer.c;h=67f42b12fb025aa4f9d7079bbcefcb2d5247c5bf;hb=HEAD;hp=45b67fb6ec75fdbdd8880ea237aa6fdcb5dfc604;hpb=48d3253378cdaf1270b3377c845cb5820657af34;p=citadel.git diff --git a/webcit/bbsview_renderer.c b/webcit/bbsview_renderer.c index 45b67fb6e..d06045d0b 100644 --- a/webcit/bbsview_renderer.c +++ b/webcit/bbsview_renderer.c @@ -1,48 +1,40 @@ /* - * $Id$ - * * BBS View renderer module for WebCit * * Note: we briefly had a dynamic UI for this. I thought it was cool, but * it was not received well by the user community. If you want to play - * with it, go get r8256 of bbsview_renderer.c and have fun. - * - * Copyright (c) 1996-2010 by the citadel.org team + * with it, go get commit dcf99fe61379b78436c387ea3f89ebfd4ffaf635 of + * bbsview_renderer.c and have fun. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. + * Copyright (c) 1996-2012 by the citadel.org team * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is open source software. You can redistribute it and/or + * modify it under the terms of the GNU General Public License, version 3. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. */ #define RANGE 5 #include "webcit.h" -#include "webserver.h" -#include "groupdav.h" + +#include "dav.h" /* * Data which gets passed around between the various functions in this module * - * We do this weird "pivot point" thing instead of starting the page numbers at 0 or 1 so that - * the border between old and new messages always falls on a page boundary. We'll renumber them - * to page numbers starting at 1 when presenting them to the user. */ struct bbsview { long *msgs; /* Array of msgnums for messages we are displaying */ int num_msgs; /* Number of msgnums stored in 'msgs' */ + long lastseen; /* The number of the last seen message in this room */ int alloc_msgs; /* Currently allocated size of array */ - long pivot_msgnum; /* Page numbers are relative to this message number */ int requested_page; /* Which page number did the user request? */ + int num_pages; /* Total number of pages in this room */ + long start_reading_at; /* Start reading at the page containing this message */ }; @@ -57,13 +49,15 @@ long bbsview_get_last_seen(void) serv_puts("GTSN"); serv_getln(buf, sizeof buf); if (buf[0] == '2') { + char *colon_pos; + char *comma_pos; - char *comma_pos = strchr(buf, ','); /* kill first comma and everything to its right */ + comma_pos = strchr(buf, ','); /* kill first comma and everything to its right */ if (comma_pos) { *comma_pos = 0; } - char *colon_pos = strchr(buf, ':'); /* kill first colon and everything to its left */ + colon_pos = strchr(buf, ':'); /* kill first colon and everything to its left */ if (colon_pos) { strcpy(buf, ++colon_pos); } @@ -81,29 +75,41 @@ int bbsview_GetParamsGetServerCall(SharedMessageStatus *Stat, void **ViewSpecific, long oper, char *cmd, - long len) + long len, + char *filter, + long flen) { struct bbsview *BBS = malloc(sizeof(struct bbsview)); memset(BBS, 0, sizeof(struct bbsview)); *ViewSpecific = BBS; - Stat->startmsg = -1; /* not used here */ + Stat->startmsg = (-1); /* not used here */ Stat->sortit = 1; /* not used here */ Stat->num_displayed = DEFAULT_MAXMSGS; /* not used here */ BBS->requested_page = 0; + BBS->lastseen = bbsview_get_last_seen(); + BBS->start_reading_at = 0; - if (havebstr("page")) { - BBS->requested_page = ibstr("page"); - } - - if (havebstr("pivot")) { - BBS->pivot_msgnum = ibstr("pivot"); + /* By default, the requested page is the first one. */ + if (havebstr("start_reading_at")) { + BBS->start_reading_at = lbstr("start_reading_at"); + BBS->requested_page = (-4); } - else if (oper == 2) { /* 2 == "read all" (otherwise we pivot at the beginning of new msgs) */ - BBS->pivot_msgnum = 0; /* start from the top */ + + /* However, if we are asked to start with a specific message number, make sure + * we start on the page containing that message + */ + + /* Or, if a specific page was requested, make sure we go there */ + else if (havebstr("page")) { + BBS->requested_page = ibstr("page"); } - else { - BBS->pivot_msgnum = bbsview_get_last_seen(); + + /* Otherwise, if this is a "read new" operation, make sure we start on the page + * containing the first new message + */ + else if (oper == 3) { + BBS->requested_page = (-3); } if (havebstr("maxmsgs")) { @@ -132,12 +138,14 @@ int bbsview_LoadMsgFromServer(SharedMessageStatus *Stat, if (BBS->alloc_msgs == 0) { BBS->alloc_msgs = 1000; BBS->msgs = malloc(BBS->alloc_msgs * sizeof(long)); + memset(BBS->msgs, 0, (BBS->alloc_msgs * sizeof(long)) ); } /* Check our buffer size */ if (BBS->num_msgs >= BBS->alloc_msgs) { BBS->alloc_msgs *= 2; BBS->msgs = realloc(BBS->msgs, (BBS->alloc_msgs * sizeof(long))); + memset(&BBS->msgs[BBS->num_msgs], 0, ((BBS->alloc_msgs - BBS->num_msgs) * sizeof(long)) ); } BBS->msgs[BBS->num_msgs++] = Msg->msgnum; @@ -167,104 +175,194 @@ int bbsview_RenderView_or_Tail(SharedMessageStatus *Stat, int i; int seq; const StrBuf *Mime; - int pivot_index = 0; - int page_offset = 0; int start_index = 0; int end_index = 0; + int go_to_the_very_end = 0; - /* Cut the message list down to the requested size */ if (Stat->nummsgs > 0) { - lprintf(9, "sorting %d messages\n", BBS->num_msgs); + syslog(LOG_DEBUG, "sorting %d messages\n", BBS->num_msgs); qsort(BBS->msgs, (size_t)(BBS->num_msgs), sizeof(long), bbsview_sortfunc); + } - /* Cut it down to 20 messages (or whatever value Stat->maxmsgs is set to) */ - - if (BBS->num_msgs > Stat->maxmsgs) { + if ((BBS->num_msgs % Stat->maxmsgs) == 0) { + BBS->num_pages = BBS->num_msgs / Stat->maxmsgs; + } + else { + BBS->num_pages = (BBS->num_msgs / Stat->maxmsgs) + 1; + } - /* Locate the pivot point in our message index */ - for (i=0; i<(BBS->num_msgs); ++i) { - if (BBS->msgs[i] <= BBS->pivot_msgnum) { - pivot_index = i; + /* If the requested page number is -4, + * it means "whichever page on which msg#xxxxx starts" + * Change to the page number which contains that message. + */ + if (BBS->requested_page == (-4)) { + if (BBS->num_msgs == 0) { + BBS->requested_page = 0; + } + else { + for (i=0; inum_msgs; ++i) { + if ( + (BBS->msgs[i] >= BBS->start_reading_at) + && (BBS->requested_page == (-4)) + ) { + BBS->requested_page = (i / Stat->maxmsgs) ; } } + } + } - page_offset = (pivot_index / Stat->maxmsgs) + 2; + /* If the requested page number is -3, + * it means "whichever page on which new messages start" + * Change that to an actual page number now. + */ + if (BBS->requested_page == (-3)) { + if (BBS->num_msgs == 0) { + /* + * The room is empty; just start at the top and leave it there. + */ + BBS->requested_page = 0; + } + else if ( + (BBS->num_msgs > 0) + && (BBS->lastseen <= BBS->msgs[0]) + ) { + /* + * All messages are new; this is probably the user's first visit to the room, + * so start at the last page instead of showing ancient history. + */ + BBS->requested_page = BBS->num_pages - 1; + go_to_the_very_end = 1; + } + else { + /* + * Some messages are old and some are new. Go to the start of new messages. + */ + for (i=0; inum_msgs; ++i) { + if ( + (BBS->msgs[i] > BBS->lastseen) + && ( (i == 0) || (BBS->msgs[i-1] <= BBS->lastseen) ) + ) { + BBS->requested_page = (i / Stat->maxmsgs) ; + } + } + } + } + /* Still set to -3 ? If so, that probably means that there are no new messages, + * so we'll go to the *end* of the final page. + */ + if (BBS->requested_page == (-3)) { + if (BBS->num_msgs == 0) { + BBS->requested_page = 0; + } + else { + BBS->requested_page = BBS->num_pages - 1; } } - start_index = pivot_index + (BBS->requested_page * Stat->maxmsgs) ; + /* keep the requested page within bounds */ + if (BBS->requested_page < 0) BBS->requested_page = 0; + if (BBS->requested_page >= BBS->num_pages) BBS->requested_page = BBS->num_pages - 1; + + start_index = BBS->requested_page * Stat->maxmsgs; if (start_index < 0) start_index = 0; end_index = start_index + Stat->maxmsgs - 1; - for (seq = 0; seq < 3; ++seq) { /* cheap and sleazy way of rendering the funbar twice */ + for (seq = 0; seq < 3; ++seq) { /* cheap & sleazy way of rendering the page numbers twice */ - if (seq == 1) { + if ( (seq == 1) && (Stat->nummsgs > 0)) { /* display the selected range of messages */ - if (Stat->nummsgs > 0) { - wc_printf("\n"); - for (i=start_index; (i<=end_index && i<=BBS->num_msgs); ++i) { - if (BBS->msgs[i] > 0L) { - read_message(WC->WBuf, HKEY("view_message"), BBS->msgs[i], NULL, &Mime); + for (i=start_index; (i<=end_index && inum_msgs); ++i) { + if ( + (BBS->msgs[i] > BBS->lastseen) + && ( (i == 0) || (BBS->msgs[i-1] <= BBS->lastseen) ) + ) { + /* new messages start here */ + do_template("start_of_new_msgs"); + if (!go_to_the_very_end) { + StrBufAppendPrintf(WC->trailing_javascript, "location.href=\"#newmsgs\";\n"); + } + } + if (BBS->msgs[i] > 0L) { + read_message(WC->WBuf, HKEY("view_message"), BBS->msgs[i], NULL, &Mime, NULL); + } + if ( + (i == (BBS->num_msgs - 1)) + && (BBS->msgs[i] <= BBS->lastseen) + ) { + /* no new messages */ + do_template("no_new_msgs"); + if (!go_to_the_very_end) { + StrBufAppendPrintf(WC->trailing_javascript, "location.href=\"#nonewmsgs\";\n"); } } - wc_printf("
\n"); } } - else { - /* Display the range selecto-bar */ + + else if ( (seq == 0) || (seq == 2) ) { + int first; + int last; + /* Display the selecto-bar with the page numbers */ wc_printf("
"); + if (seq == 2) { + wc_printf(""); + } wc_printf(_("Go to page: ")); + if (seq == 2) { + wc_printf(""); + } - int first = 1; - int last = (BBS->num_msgs / Stat->maxmsgs) + 2 ; + first = 0; + last = BBS->num_pages - 1; - for (i=1; i<=last; ++i) { + for (i=0; i<=last; ++i) { if ( (i == first) || (i == last) - || ((i - page_offset) == BBS->requested_page) + || (i == BBS->requested_page) || ( - ((BBS->requested_page - (i - page_offset)) < RANGE) - && ((BBS->requested_page - (i - page_offset)) > (0 - RANGE)) + ((BBS->requested_page - i) < RANGE) + && ((BBS->requested_page - i) > (0 - RANGE)) ) ) { if ( (i == last) - && (last - (BBS->requested_page + page_offset) > RANGE) + && (last - BBS->requested_page > RANGE) ) { wc_printf("... "); } - if ((i - page_offset) == BBS->requested_page) { + if (i == BBS->requested_page) { wc_printf("["); } else { - wc_printf("", - BBS->pivot_msgnum, - i - page_offset + wc_printf("CurRoom.name)); + wc_printf("?start_reading_at=%ld\">", + BBS->msgs[i*Stat->maxmsgs] ); + /* wc_printf("?page=%d\">", i); */ wc_printf(""); } if ( (i == first) - && ((BBS->requested_page + page_offset) > (RANGE + 1)) + && (BBS->requested_page > (RANGE + 1)) ) { wc_printf(_("First")); } else if ( (i == last) - && (last - (BBS->requested_page + page_offset) > RANGE) + && (last - BBS->requested_page > RANGE) ) { wc_printf(_("Last")); } else { - wc_printf("%d", i); + wc_printf("%d", i + 1); /* change to one-based for display */ } - if ((i - page_offset) == BBS->requested_page) { + if (i == BBS->requested_page) { wc_printf("]"); } else { @@ -273,7 +371,7 @@ int bbsview_RenderView_or_Tail(SharedMessageStatus *Stat, } if ( (i == first) - && ((BBS->requested_page + page_offset) > (RANGE + 1)) + && (BBS->requested_page > (RANGE + 1)) ) { wc_printf(" ..."); } @@ -286,6 +384,9 @@ int bbsview_RenderView_or_Tail(SharedMessageStatus *Stat, } } + if (go_to_the_very_end) { + StrBufAppendPrintf(WC->trailing_javascript, "location.href=\"#end_of_msgs\";\n"); + } return(0); } @@ -312,9 +413,11 @@ InitModule_BBSVIEWRENDERERS VIEW_BBS, bbsview_GetParamsGetServerCall, NULL, + NULL, NULL, bbsview_LoadMsgFromServer, bbsview_RenderView_or_Tail, - bbsview_Cleanup + bbsview_Cleanup, + NULL ); }