summaryrefslogtreecommitdiff
path: root/pith/flag.c
diff options
context:
space:
mode:
authorEduardo Chappa <echappa@gmx.com>2013-02-03 00:59:38 -0700
committerEduardo Chappa <echappa@gmx.com>2013-02-03 00:59:38 -0700
commit094ca96844842928810f14844413109fc6cdd890 (patch)
treee60efbb980f38ba9308ccb4fb2b77b87bbc115f3 /pith/flag.c
downloadalpine-094ca96844842928810f14844413109fc6cdd890.tar.xz
Initial Alpine Version
Diffstat (limited to 'pith/flag.c')
-rw-r--r--pith/flag.c758
1 files changed, 758 insertions, 0 deletions
diff --git a/pith/flag.c b/pith/flag.c
new file mode 100644
index 00000000..b1bbf9c4
--- /dev/null
+++ b/pith/flag.c
@@ -0,0 +1,758 @@
+#if !defined(lint) && !defined(DOS)
+static char rcsid[] = "$Id: flag.c 1142 2008-08-13 17:22:21Z hubert@u.washington.edu $";
+#endif
+
+/*
+ * ========================================================================
+ * Copyright 2006-2007 University of Washington
+ * Copyright 2013 Eduardo Chappa
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+/*======================================================================
+ flag.c
+ Implements Pine message flag management routines
+ ====*/
+
+
+#include "../pith/headers.h"
+#include "../pith/flag.h"
+#include "../pith/pineelt.h"
+#include "../pith/icache.h"
+#include "../pith/mailindx.h"
+#include "../pith/mailcmd.h"
+#include "../pith/msgno.h"
+#include "../pith/thread.h"
+#include "../pith/sort.h"
+#include "../pith/news.h"
+#include "../pith/sequence.h"
+
+
+/*
+ * Internal prototypes
+ */
+void flag_search(MAILSTREAM *, int, MsgNo, MSGNO_S *, long (*)(MAILSTREAM *));
+long flag_search_sequence(MAILSTREAM *, MSGNO_S *, long, int);
+
+
+
+/*----------------------------------------------------------------------
+ Return sequence number based on given index that are search-worthy
+
+ Args: stream --
+ msgmap --
+ msgno --
+ flags -- flags for msgline_hidden
+
+ Result: 0 : index not search-worthy
+ -1 : index out of bounds
+ 1 - stream->nmsgs : sequence number to flag search
+
+ ----*/
+long
+flag_search_sequence(MAILSTREAM *stream, MSGNO_S *msgmap, long int msgno, int flags)
+{
+ long rawno = msgno;
+
+ return((msgno > stream->nmsgs
+ || msgno <= 0
+ || (msgmap && !(rawno = mn_m2raw(msgmap, msgno))))
+ ? -1L /* out of range! */
+ : ((get_lflag(stream, NULL, rawno, MN_EXLD)
+ || (msgmap && msgline_hidden(stream, msgmap, msgno, flags)))
+ ? 0L /* NOT interesting! */
+ : rawno));
+}
+
+
+
+/*----------------------------------------------------------------------
+ Perform mail_search based on flag bits
+
+ Args: stream --
+ flags --
+ start --
+ msgmap --
+
+ Result: if no set_* specified, call mail_search to light the searched
+ bit for all the messages matching the given flags. If set_start
+ specified, it is an index (possibly into set_msgmap) telling
+ us where to search for invalid flag state hence when we
+ return everything with the searched bit is interesting and
+ everything with the valid bit lit is believably valid.
+
+ ----*/
+void
+flag_search(MAILSTREAM *stream, int flags, MsgNo set_start, MSGNO_S *set_msgmap,
+ long int (*ping)(MAILSTREAM *))
+{
+ long n, i, new;
+ char *seq;
+ SEARCHPGM *pgm;
+ SEARCHSET *full_set = NULL, **set;
+ MESSAGECACHE *mc;
+ extern MAILSTREAM *mm_search_stream;
+
+ if(!stream)
+ return;
+
+ new = sp_new_mail_count(stream);
+
+ /* Anything we don't already have flags for? */
+ if(set_start){
+ /*
+ * Use elt's sequence bit to coalesce runs in ascending
+ * sequence order...
+ */
+ for(i = 1L; i <= stream->nmsgs; i++)
+ if((mc = mail_elt(stream, i)) != NULL)
+ mc->sequence = 0;
+
+ for(i = set_start;
+ (n = flag_search_sequence(stream, set_msgmap, i, MH_ANYTHD)) >= 0L;
+ (flags & F_SRCHBACK) ? i-- : i++)
+ if(n > 0L && n <= stream->nmsgs
+ && (mc = mail_elt(stream, n)) && !mc->valid)
+ mc->sequence = 1;
+
+ /* Unroll searchset in ascending sequence order */
+ set = &full_set;
+ for(i = 1L; i <= stream->nmsgs; i++)
+ if((mc = mail_elt(stream, i)) && mc->sequence){
+ if(*set){
+ if(((*set)->last ? (*set)->last : (*set)->first)+1L == i)
+ (*set)->last = i;
+ else
+ set = &(*set)->next;
+ }
+
+ if(!*set){
+ *set = mail_newsearchset();
+ (*set)->first = i;
+ }
+ }
+
+ /*
+ * No search-worthy messsages?, prod the server for
+ * any flag updates and clear the searched bits...
+ */
+ if(full_set){
+ if(full_set->first == 1
+ && full_set->last == stream->nmsgs
+ && full_set->next == NULL)
+ mail_free_searchset(&full_set);
+ }
+ else{
+ for(i = 1L; i <= stream->nmsgs; i++)
+ if((mc = mail_elt(stream, i)) != NULL)
+ mc->searched = 0;
+
+ if(ping)
+ (*ping)(stream); /* prod server for any flag updates */
+
+ if(!(flags & F_NOFILT) && new != sp_new_mail_count(stream)){
+ process_filter_patterns(stream, sp_msgmap(stream),
+ sp_new_mail_count(stream));
+
+ refresh_sort(stream, sp_msgmap(stream), SRT_NON);
+ flag_search(stream, flags, set_start, set_msgmap, ping);
+ }
+
+ return;
+ }
+ }
+
+ if((!is_imap_stream(stream) || modern_imap_stream(stream))
+ && !(IS_NEWS(stream))){
+ pgm = mail_newsearchpgm();
+
+ if(flags & F_SEEN)
+ pgm->seen = 1;
+
+ if(flags & F_UNSEEN)
+ pgm->unseen = 1;
+
+ if(flags & F_DEL)
+ pgm->deleted = 1;
+
+ if(flags & F_UNDEL)
+ pgm->undeleted = 1;
+
+ if(flags & F_ANS)
+ pgm->answered = 1;
+
+ if(flags & F_UNANS)
+ pgm->unanswered = 1;
+
+ if(flags & F_FLAG)
+ pgm->flagged = 1;
+
+ if(flags & F_UNFLAG)
+ pgm->unflagged = 1;
+
+ if(flags & (F_FWD | F_UNFWD)){
+ STRINGLIST **slpp;
+
+ for(slpp = (flags & F_FWD) ? &pgm->keyword : &pgm->unkeyword;
+ *slpp;
+ slpp = &(*slpp)->next)
+ ;
+
+ *slpp = mail_newstringlist();
+ (*slpp)->text.data = (unsigned char *) cpystr(FORWARDED_FLAG);
+ (*slpp)->text.size = (unsigned long) strlen(FORWARDED_FLAG);
+ }
+
+ if(flags & F_RECENT)
+ pgm->recent = 1;
+
+ if(flags & F_OR_SEEN){
+ SEARCHPGM *pgm2 = mail_newsearchpgm();
+ pgm2->or = mail_newsearchor();
+ pgm2->or->first = pgm;
+ pgm2->or->second = mail_newsearchpgm();
+ pgm2->or->second->seen = 1;
+ pgm = pgm2;
+ }
+
+ if(flags & F_OR_UNSEEN){
+ SEARCHPGM *pgm2 = mail_newsearchpgm();
+ pgm2->or = mail_newsearchor();
+ pgm2->or->first = pgm;
+ pgm2->or->second = mail_newsearchpgm();
+ pgm2->or->second->unseen = 1;
+ pgm = pgm2;
+ }
+
+ if(flags & F_OR_DEL){
+ SEARCHPGM *pgm2 = mail_newsearchpgm();
+ pgm2->or = mail_newsearchor();
+ pgm2->or->first = pgm;
+ pgm2->or->second = mail_newsearchpgm();
+ pgm2->or->second->deleted = 1;
+ pgm = pgm2;
+ }
+
+ if(flags & F_OR_UNDEL){
+ SEARCHPGM *pgm2 = mail_newsearchpgm();
+ pgm2->or = mail_newsearchor();
+ pgm2->or->first = pgm;
+ pgm2->or->second = mail_newsearchpgm();
+ pgm2->or->second->undeleted = 1;
+ pgm = pgm2;
+ }
+
+ if(flags & F_OR_FLAG){
+ SEARCHPGM *pgm2 = mail_newsearchpgm();
+ pgm2->or = mail_newsearchor();
+ pgm2->or->first = pgm;
+ pgm2->or->second = mail_newsearchpgm();
+ pgm2->or->second->flagged = 1;
+ pgm = pgm2;
+ }
+
+ if(flags & F_OR_UNFLAG){
+ SEARCHPGM *pgm2 = mail_newsearchpgm();
+ pgm2->or = mail_newsearchor();
+ pgm2->or->first = pgm;
+ pgm2->or->second = mail_newsearchpgm();
+ pgm2->or->second->unflagged = 1;
+ pgm = pgm2;
+ }
+
+ if(flags & F_OR_ANS){
+ SEARCHPGM *pgm2 = mail_newsearchpgm();
+ pgm2->or = mail_newsearchor();
+ pgm2->or->first = pgm;
+ pgm2->or->second = mail_newsearchpgm();
+ pgm2->or->second->answered = 1;
+ pgm = pgm2;
+ }
+
+ if(flags & F_OR_UNANS){
+ SEARCHPGM *pgm2 = mail_newsearchpgm();
+ pgm2->or = mail_newsearchor();
+ pgm2->or->first = pgm;
+ pgm2->or->second = mail_newsearchpgm();
+ pgm2->or->second->unanswered = 1;
+ pgm = pgm2;
+ }
+
+ if(flags & (F_OR_FWD | F_OR_UNFWD)){
+ STRINGLIST **slpp;
+ SEARCHPGM *pgm2 = mail_newsearchpgm();
+ pgm2->or = mail_newsearchor();
+ pgm2->or->first = pgm;
+ pgm2->or->second = mail_newsearchpgm();
+
+ for(slpp = (flags & F_OR_FWD)
+ ? &pgm2->or->second->keyword
+ : &pgm2->or->second->unkeyword;
+ *slpp;
+ slpp = &(*slpp)->next)
+ ;
+
+ *slpp = mail_newstringlist();
+ (*slpp)->text.data = (unsigned char *) cpystr(FORWARDED_FLAG);
+ (*slpp)->text.size = (unsigned long) strlen(FORWARDED_FLAG);
+
+ pgm = pgm2;
+ }
+
+ if(flags & F_OR_RECENT){
+ SEARCHPGM *pgm2 = mail_newsearchpgm();
+ pgm2->or = mail_newsearchor();
+ pgm2->or->first = pgm;
+ pgm2->or->second = mail_newsearchpgm();
+ pgm2->or->second->recent = 1;
+ pgm = pgm2;
+ }
+
+ pgm->msgno = full_set;
+
+ pine_mail_search_full(mm_search_stream = stream, NULL,
+ pgm, SE_NOPREFETCH | SE_FREE);
+
+ if(!(flags & F_NOFILT) && new != sp_new_mail_count(stream)){
+ process_filter_patterns(stream, sp_msgmap(stream),
+ sp_new_mail_count(stream));
+
+ flag_search(stream, flags, set_start, set_msgmap, ping);
+ }
+ }
+ else{
+ if(full_set){
+ /* sequence bits of interesting msgs set */
+ mail_free_searchset(&full_set);
+ }
+ else{
+ /* light sequence bits of interesting msgs */
+ for(i = 1L;
+ (n = flag_search_sequence(stream, set_msgmap, i, MH_ANYTHD)) >= 0L;
+ i++)
+ if(n > 0L && n <= stream->nmsgs
+ && (mc = mail_elt(stream, n)) && !mc->valid)
+ mc->sequence = 1;
+ else
+ mc->sequence = 0;
+ }
+
+ for(i = 1L; i <= stream->nmsgs; i++)
+ if((mc = mail_elt(stream, i)) != NULL)
+ mc->searched = 0;
+
+ if((seq = build_sequence(stream, NULL, NULL)) != NULL){
+ pine_mail_fetch_flags(stream, seq, 0L);
+ fs_give((void **) &seq);
+ }
+ }
+}
+
+
+
+/*----------------------------------------------------------------------
+ count messages on stream with specified system flag attributes
+
+ Args: stream -- The stream/folder to look at message status
+ flags -- flags on folder/stream to examine
+
+ Result: count of messages flagged as requested
+
+ Task: return count of message flagged as requested while being
+ as server/network friendly as possible.
+
+ Strategy: run thru flags to make sure they're all valid. If any
+ invalid, do a search starting with the invalid message.
+ If all valid, ping the server to let it know we're
+ receptive to flag updates. At this
+
+ ----------------------------------------------------------------------*/
+long
+count_flagged(MAILSTREAM *stream, long int flags)
+{
+ long n, count;
+ MESSAGECACHE *mc;
+
+ if(!stream)
+ return(0L);
+
+ flag_search(stream, flags, 1, NULL, pine_mail_ping);
+
+ /* Paw thru once more since all should be updated */
+ for(n = 1L, count = 0L; n <= stream->nmsgs; n++)
+ if((((mc = mail_elt(stream, n)) && mc->searched)
+ || (mc && mc->valid && FLAG_MATCH(flags, mc, stream)))
+ && !get_lflag(stream, NULL, n, MN_EXLD)){
+ mc->searched = 1; /* caller may be interested! */
+ count++;
+ }
+
+ return(count);
+}
+
+
+
+/*----------------------------------------------------------------------
+ Find the first message with the specified flags set
+
+ Args: flags -- Flags in messagecache to match on
+ stream -- The stream/folder to look at message status
+
+ Result: Message number of first message with specified flags set or the
+ number of the last message if none found.
+ ----------------------------------------------------------------------*/
+MsgNo
+first_sorted_flagged(long unsigned int flags, MAILSTREAM *stream, long int set_start, int opts)
+{
+ MsgNo i, n, start_with, winner = 0L;
+ MESSAGECACHE *mc;
+ int last;
+ MSGNO_S *msgmap;
+
+ msgmap = sp_msgmap(stream);
+
+ last = (opts & FSF_LAST);
+
+ /* set_start only affects which search bits we light */
+ start_with = set_start ? set_start
+ : (flags & F_SRCHBACK)
+ ? mn_get_total(msgmap) : 1L;
+ flag_search(stream, flags, start_with, msgmap, NULL);
+
+ for(i = start_with;
+ (n = flag_search_sequence(stream, msgmap, i,
+ (opts & FSF_SKIP_CHID) ? 0 : MH_ANYTHD)) >= 0L;
+ (flags & F_SRCHBACK) ? i-- : i++)
+ if(n > 0L && n <= stream->nmsgs
+ && (((mc = mail_elt(stream, n)) && mc->searched)
+ || (mc && mc->valid && FLAG_MATCH(flags, mc, stream)))){
+ winner = i;
+ if(!last)
+ break;
+ }
+
+ if(winner == 0L && flags != F_UNDEL && flags != F_NONE){
+ dprint((4,
+ "First_sorted_flagged didn't find a winner, look for undeleted\n"));
+ winner = first_sorted_flagged(F_UNDEL, stream, 0L,
+ opts | (mn_get_revsort(msgmap) ? 0 : FSF_LAST));
+ }
+
+ if(winner == 0L && flags != F_NONE){
+ dprint((4,
+ "First_sorted_flagged didn't find an undeleted, look for visible\n"));
+ winner = first_sorted_flagged(F_NONE, stream, 0L,
+ opts | (mn_get_revsort(msgmap) ? 0 : FSF_LAST));
+ }
+
+ dprint((4,
+ "First_sorted_flagged returning winner = %ld\n", winner));
+ return(winner ? winner
+ : (mn_get_revsort(msgmap)
+ ? 1L : mn_get_total(msgmap)));
+}
+
+
+
+/*----------------------------------------------------------------------
+ Find the next message with specified flags set
+
+ Args: flags -- Flags in messagecache to match on
+ stream -- The stream/folder to look at message status
+ start -- Start looking after this message
+ opts -- These bits are both input and output. On input the bit
+ NSF_TRUST_FLAGS tells us whether we need to ping or not.
+ On input, the bit NSF_SEARCH_BACK tells us that we want to
+ know about matches <= start if we don't find any > start.
+ On output, NSF_FLAG_MATCH is set if we matched a message.
+ Returns: Message number of the matched message, if any; else the start # or
+ the max_msgno if the mailbox changed dramatically.
+ ----------------------------------------------------------------------*/
+MsgNo
+next_sorted_flagged(long unsigned int flags, MAILSTREAM *stream, long int start, int *opts)
+{
+ MsgNo i, n, dir;
+ MESSAGECACHE *mc;
+ int rev, fss_flags = 0;
+ MSGNO_S *msgmap;
+
+ msgmap = sp_msgmap(stream);
+
+ /*
+ * Search for the next thing the caller's interested in...
+ */
+
+ fss_flags = (opts && *opts & NSF_SKIP_CHID) ? 0 : MH_ANYTHD;
+ rev = (opts && *opts & NSF_SEARCH_BACK);
+ dir = (rev ? -1L : 1L);
+
+ flag_search(stream, flags | (rev ? F_SRCHBACK : 0), start + dir,
+ msgmap,
+ (opts && ((*opts) & NSF_TRUST_FLAGS)) ? NULL : pine_mail_ping);
+
+ for(i = start + dir;
+ (n = flag_search_sequence(stream, msgmap,
+ i, fss_flags)) >= 0L;
+ i += dir)
+ if(n > 0L && n <= stream->nmsgs
+ && (((mc = mail_elt(stream, n)) && mc->searched)
+ || (mc && mc->valid && FLAG_MATCH(flags, mc, stream)))){
+ /* actually found a msg matching the flags */
+ if(opts)
+ (*opts) |= NSF_FLAG_MATCH;
+
+ return(i);
+ }
+
+
+ return(MIN(start, mn_get_total(msgmap)));
+}
+
+
+
+/*----------------------------------------------------------------------
+ get the requested LOCAL flag bits for the given pine message number
+
+ Accepts: msgs - pointer to message manipulation struct
+ n - message number to get
+ f - bitmap of interesting flags
+ Returns: non-zero if flag set, 0 if not set or no elt (error?)
+
+ NOTE: this can be used to test system flags
+ ----*/
+int
+get_lflag(MAILSTREAM *stream, MSGNO_S *msgs, long int n, int f)
+{
+ MESSAGECACHE *mc;
+ PINELT_S *pelt;
+ unsigned long rawno;
+
+ rawno = msgs ? mn_m2raw(msgs, n) : n;
+ if(!stream || rawno < 1L || rawno > stream->nmsgs)
+ return(0);
+
+ mc = mail_elt(stream, rawno);
+ if(!mc || (pelt = (PINELT_S *) mc->sparep) == NULL)
+ return(f ? 0 : 1);
+
+ return((!f)
+ ? !(pelt->hidden || pelt->excluded || pelt->selected ||
+ pelt->colhid || pelt->collapsed || pelt->searched)
+ : (((f & MN_HIDE) ? pelt->hidden : 0)
+ || ((f & MN_EXLD) ? pelt->excluded : 0)
+ || ((f & MN_SLCT) ? pelt->selected : 0)
+ || ((f & MN_STMP) ? pelt->tmp : 0)
+ || ((f & MN_USOR) ? pelt->unsorted : 0)
+ || ((f & MN_COLL) ? pelt->collapsed : 0)
+ || ((f & MN_CHID) ? pelt->colhid : 0)
+ || ((f & MN_CHID2) ? pelt->colhid2 : 0)
+ || ((f & MN_SRCH) ? pelt->searched : 0)));
+}
+
+
+
+/*----------------------------------------------------------------------
+ set the requested LOCAL flag bits for the given pine message number
+
+ Accepts: msgs - pointer to message manipulation struct
+ n - message number to set
+ f - bitmap of interesting flags
+ v - value (on or off) flag should get
+ Returns: our index number of first
+
+ NOTE: this isn't to be used for setting IMAP system flags
+ ----*/
+int
+set_lflag(MAILSTREAM *stream, MSGNO_S *msgs, long int n, int f, int v)
+{
+ MESSAGECACHE *mc;
+ long rawno = 0L;
+ PINETHRD_S *thrd, *topthrd = NULL;
+ PINELT_S **peltp, *pelt;
+
+ if(n < 1L || n > mn_get_total(msgs))
+ return(0L);
+
+ if((rawno=mn_m2raw(msgs, n)) > 0L && stream && rawno <= stream->nmsgs
+ && (mc = mail_elt(stream, rawno))){
+ int was_invisible, is_invisible;
+ int chk_thrd_cnt = 0, thrd_was_visible, was_hidden, is_hidden;
+
+ if((*(peltp = (PINELT_S **) &mc->sparep) == NULL)){
+ *peltp = (PINELT_S *) fs_get(sizeof(PINELT_S));
+ memset(*peltp, 0, sizeof(PINELT_S));
+ }
+
+ pelt = (*peltp);
+
+ was_invisible = (pelt->hidden || pelt->colhid) ? 1 : 0;
+
+ if((chk_thrd_cnt = ((msgs->visible_threads >= 0L)
+ && THRD_INDX_ENABLED() && (f & MN_HIDE) && (pelt->hidden != v))) != 0){
+ thrd = fetch_thread(stream, rawno);
+ if(thrd && thrd->top){
+ if(thrd->top == thrd->rawno)
+ topthrd = thrd;
+ else
+ topthrd = fetch_thread(stream, thrd->top);
+ }
+
+ if(topthrd){
+ thrd_was_visible = thread_has_some_visible(stream, topthrd);
+ was_hidden = pelt->hidden ? 1 : 0;
+ }
+ }
+
+ if((f & MN_HIDE) && pelt->hidden != v){
+ pelt->hidden = v;
+ msgs->flagged_hid += (v) ? 1L : -1L;
+
+ if(pelt->hidden && THREADING() && !THRD_INDX()
+ && stream == ps_global->mail_stream
+ && ps_global->thread_disp_style == THREAD_MUTTLIKE)
+ clear_index_cache_for_thread(stream, fetch_thread(stream, rawno),
+ sp_msgmap(stream));
+ }
+
+ if((f & MN_CHID) && pelt->colhid != v){
+ pelt->colhid = v;
+ msgs->flagged_chid += (v) ? 1L : -1L;
+ }
+
+ if((f & MN_CHID2) && pelt->colhid2 != v){
+ pelt->colhid2 = v;
+ msgs->flagged_chid2 += (v) ? 1L : -1L;
+ }
+
+ if((f & MN_COLL) && pelt->collapsed != v){
+ pelt->collapsed = v;
+ msgs->flagged_coll += (v) ? 1L : -1L;
+ }
+
+ if((f & MN_USOR) && pelt->unsorted != v){
+ pelt->unsorted = v;
+ msgs->flagged_usor += (v) ? 1L : -1L;
+ }
+
+ if((f & MN_EXLD) && pelt->excluded != v){
+ pelt->excluded = v;
+ msgs->flagged_exld += (v) ? 1L : -1L;
+ }
+
+ if((f & MN_SLCT) && pelt->selected != v){
+ pelt->selected = v;
+ msgs->flagged_tmp += (v) ? 1L : -1L;
+ }
+
+ if((f & MN_SRCH) && pelt->searched != v){
+ pelt->searched = v;
+ msgs->flagged_srch += (v) ? 1L : -1L;
+ }
+
+ if((f & MN_STMP) && pelt->tmp != v){
+ pelt->tmp = v;
+ msgs->flagged_stmp += (v) ? 1L : -1L;
+ }
+
+ is_invisible = (pelt->hidden || pelt->colhid) ? 1 : 0;
+
+ if(was_invisible != is_invisible)
+ msgs->flagged_invisible += (v) ? 1L : -1L;
+
+ /*
+ * visible_threads keeps track of how many of the max_thrdno threads
+ * are visible and how many are MN_HIDE-hidden.
+ */
+ if(chk_thrd_cnt && topthrd
+ && (was_hidden != (is_hidden = pelt->hidden ? 1 : 0))){
+ if(!thrd_was_visible && !is_hidden){
+ /* it is visible now, increase count by one */
+ msgs->visible_threads++;
+ }
+ else if(thrd_was_visible && is_hidden){
+ /* thread may have been hidden, check */
+ if(!thread_has_some_visible(stream, topthrd))
+ msgs->visible_threads--;
+ }
+ /* else no change */
+ }
+ }
+
+ return(1);
+}
+
+
+/*
+ * Copy value of flag from to flag to.
+ */
+void
+copy_lflags(MAILSTREAM *stream, MSGNO_S *msgmap, int from, int to)
+{
+ unsigned long i;
+ int hide;
+
+ hide = ((to == MN_SLCT) && (any_lflagged(msgmap, MN_HIDE) > 0L));
+
+ set_lflags(stream, msgmap, to, 0);
+
+ if(any_lflagged(msgmap, from))
+ for(i = 1L; i <= mn_get_total(msgmap); i++)
+ if(get_lflag(stream, msgmap, i, from))
+ set_lflag(stream, msgmap, i, to, 1);
+ else if(hide)
+ set_lflag(stream, msgmap, i, MN_HIDE, 1);
+}
+
+
+/*
+ * Set flag f to value v in all message.
+ */
+void
+set_lflags(MAILSTREAM *stream, MSGNO_S *msgmap, int f, int v)
+{
+ unsigned long i;
+
+ if((v == 0 && any_lflagged(msgmap, f)) || v )
+ for(i = 1L; i <= mn_get_total(msgmap); i++)
+ set_lflag(stream, msgmap, i, f, v);
+}
+
+
+
+/*----------------------------------------------------------------------
+ return whether the given flag is set somewhere in the folder
+
+ Accepts: msgs - pointer to message manipulation struct
+ f - flag bitmap to act on
+ Returns: number of messages with the given flag set.
+ NOTE: the sum, if multiple flags tested, is bogus
+ ----*/
+long
+any_lflagged(MSGNO_S *msgs, int f)
+{
+ if(!msgs)
+ return(0L);
+
+ if(f == MN_NONE)
+ return(!(msgs->flagged_hid || msgs->flagged_exld || msgs->flagged_tmp ||
+ msgs->flagged_coll || msgs->flagged_chid || msgs->flagged_srch));
+ else if(f == (MN_HIDE | MN_CHID))
+ return(msgs->flagged_invisible); /* special non-bogus case */
+ else
+ return(((f & MN_HIDE) ? msgs->flagged_hid : 0L)
+ + ((f & MN_EXLD) ? msgs->flagged_exld : 0L)
+ + ((f & MN_SLCT) ? msgs->flagged_tmp : 0L)
+ + ((f & MN_SRCH) ? msgs->flagged_srch : 0L)
+ + ((f & MN_STMP) ? msgs->flagged_stmp : 0L)
+ + ((f & MN_COLL) ? msgs->flagged_coll : 0L)
+ + ((f & MN_USOR) ? msgs->flagged_usor : 0L)
+ + ((f & MN_CHID) ? msgs->flagged_chid : 0L)
+ + ((f & MN_CHID2) ? msgs->flagged_chid2 : 0L));
+}