* Bug fix: Memory corruption when alpine searches for a string that is
[alpine.git] / pith / flag.c
blobdab36ceafde0e06913ef01904487f4fa0bfcd712
1 #if !defined(lint) && !defined(DOS)
2 static char rcsid[] = "$Id: flag.c 1142 2008-08-13 17:22:21Z hubert@u.washington.edu $";
3 #endif
5 /*
6 * ========================================================================
7 * Copyright 2013-2021 Eduardo Chappa
8 * Copyright 2006-2007 University of Washington
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
19 /*======================================================================
20 flag.c
21 Implements Pine message flag management routines
22 ====*/
25 #include "../pith/headers.h"
26 #include "../pith/flag.h"
27 #include "../pith/pineelt.h"
28 #include "../pith/icache.h"
29 #include "../pith/mailindx.h"
30 #include "../pith/mailcmd.h"
31 #include "../pith/msgno.h"
32 #include "../pith/thread.h"
33 #include "../pith/sort.h"
34 #include "../pith/news.h"
35 #include "../pith/sequence.h"
39 * Internal prototypes
41 void flag_search(MAILSTREAM *, int, MsgNo, MSGNO_S *, long (*)(MAILSTREAM *));
42 long flag_search_sequence(MAILSTREAM *, MSGNO_S *, long, int);
46 /*----------------------------------------------------------------------
47 Return sequence number based on given index that are search-worthy
49 Args: stream --
50 msgmap --
51 msgno --
52 flags -- flags for msgline_hidden
54 Result: 0 : index not search-worthy
55 -1 : index out of bounds
56 1 - stream->nmsgs : sequence number to flag search
58 ----*/
59 long
60 flag_search_sequence(MAILSTREAM *stream, MSGNO_S *msgmap, long int msgno, int flags)
62 long rawno = msgno;
64 return((msgno > stream->nmsgs
65 || msgno <= 0
66 || (msgmap && !(rawno = mn_m2raw(msgmap, msgno))))
67 ? -1L /* out of range! */
68 : ((get_lflag(stream, NULL, rawno, MN_EXLD)
69 || (msgmap && msgline_hidden(stream, msgmap, msgno, flags)))
70 ? 0L /* NOT interesting! */
71 : rawno));
76 /*----------------------------------------------------------------------
77 Perform mail_search based on flag bits
79 Args: stream --
80 flags --
81 start --
82 msgmap --
84 Result: if no set_* specified, call mail_search to light the searched
85 bit for all the messages matching the given flags. If set_start
86 specified, it is an index (possibly into set_msgmap) telling
87 us where to search for invalid flag state hence when we
88 return everything with the searched bit is interesting and
89 everything with the valid bit lit is believably valid.
91 ----*/
92 void
93 flag_search(MAILSTREAM *stream, int flags, MsgNo set_start, MSGNO_S *set_msgmap,
94 long int (*ping)(MAILSTREAM *))
96 long n, i, new;
97 char *seq;
98 SEARCHPGM *pgm;
99 SEARCHSET *full_set = NULL, **set;
100 MESSAGECACHE *mc;
101 extern MAILSTREAM *mm_search_stream;
103 if(!stream)
104 return;
106 new = sp_new_mail_count(stream);
108 /* Anything we don't already have flags for? */
109 if(set_start){
111 * Use elt's sequence bit to coalesce runs in ascending
112 * sequence order...
114 for(i = 1L; i <= stream->nmsgs; i++)
115 if((mc = mail_elt(stream, i)) != NULL)
116 mc->sequence = 0;
118 for(i = set_start;
119 (n = flag_search_sequence(stream, set_msgmap, i, MH_ANYTHD)) >= 0L;
120 (flags & F_SRCHBACK) ? i-- : i++)
121 if(n > 0L && n <= stream->nmsgs
122 && (mc = mail_elt(stream, n)) && !mc->valid)
123 mc->sequence = 1;
125 /* Unroll searchset in ascending sequence order */
126 set = &full_set;
127 for(i = 1L; i <= stream->nmsgs; i++)
128 if((mc = mail_elt(stream, i)) && mc->sequence){
129 if(*set){
130 if(((*set)->last ? (*set)->last : (*set)->first)+1L == i)
131 (*set)->last = i;
132 else
133 set = &(*set)->next;
136 if(!*set){
137 *set = mail_newsearchset();
138 (*set)->first = i;
143 * No search-worthy messages?, prod the server for
144 * any flag updates and clear the searched bits...
146 if(full_set){
147 if(full_set->first == 1
148 && full_set->last == stream->nmsgs
149 && full_set->next == NULL)
150 mail_free_searchset(&full_set);
152 else{
153 for(i = 1L; i <= stream->nmsgs; i++)
154 if((mc = mail_elt(stream, i)) != NULL)
155 mc->searched = 0;
157 if(ping)
158 (*ping)(stream); /* prod server for any flag updates */
160 if(!(flags & F_NOFILT) && new != sp_new_mail_count(stream)){
161 process_filter_patterns(stream, sp_msgmap(stream),
162 sp_new_mail_count(stream));
164 refresh_sort(stream, sp_msgmap(stream), SRT_NON);
165 flag_search(stream, flags, set_start, set_msgmap, ping);
168 return;
172 if((!is_imap_stream(stream) || modern_imap_stream(stream))
173 && !(IS_NEWS(stream))){
174 pgm = mail_newsearchpgm();
176 if(flags & F_SEEN)
177 pgm->seen = 1;
179 if(flags & F_UNSEEN)
180 pgm->unseen = 1;
182 if(flags & F_DEL)
183 pgm->deleted = 1;
185 if(flags & F_UNDEL)
186 pgm->undeleted = 1;
188 if(flags & F_ANS)
189 pgm->answered = 1;
191 if(flags & F_UNANS)
192 pgm->unanswered = 1;
194 if(flags & F_FLAG)
195 pgm->flagged = 1;
197 if(flags & F_UNFLAG)
198 pgm->unflagged = 1;
200 if(flags & (F_FWD | F_UNFWD)){
201 STRINGLIST **slpp;
203 for(slpp = (flags & F_FWD) ? &pgm->keyword : &pgm->unkeyword;
204 *slpp;
205 slpp = &(*slpp)->next)
208 *slpp = mail_newstringlist();
209 (*slpp)->text.data = (unsigned char *) cpystr(FORWARDED_FLAG);
210 (*slpp)->text.size = (unsigned long) strlen(FORWARDED_FLAG);
213 if(flags & F_RECENT)
214 pgm->recent = 1;
216 if(flags & F_OR_SEEN){
217 SEARCHPGM *pgm2 = mail_newsearchpgm();
218 pgm2->or = mail_newsearchor();
219 pgm2->or->first = pgm;
220 pgm2->or->second = mail_newsearchpgm();
221 pgm2->or->second->seen = 1;
222 pgm = pgm2;
225 if(flags & F_OR_UNSEEN){
226 SEARCHPGM *pgm2 = mail_newsearchpgm();
227 pgm2->or = mail_newsearchor();
228 pgm2->or->first = pgm;
229 pgm2->or->second = mail_newsearchpgm();
230 pgm2->or->second->unseen = 1;
231 pgm = pgm2;
234 if(flags & F_OR_DEL){
235 SEARCHPGM *pgm2 = mail_newsearchpgm();
236 pgm2->or = mail_newsearchor();
237 pgm2->or->first = pgm;
238 pgm2->or->second = mail_newsearchpgm();
239 pgm2->or->second->deleted = 1;
240 pgm = pgm2;
243 if(flags & F_OR_UNDEL){
244 SEARCHPGM *pgm2 = mail_newsearchpgm();
245 pgm2->or = mail_newsearchor();
246 pgm2->or->first = pgm;
247 pgm2->or->second = mail_newsearchpgm();
248 pgm2->or->second->undeleted = 1;
249 pgm = pgm2;
252 if(flags & F_OR_FLAG){
253 SEARCHPGM *pgm2 = mail_newsearchpgm();
254 pgm2->or = mail_newsearchor();
255 pgm2->or->first = pgm;
256 pgm2->or->second = mail_newsearchpgm();
257 pgm2->or->second->flagged = 1;
258 pgm = pgm2;
261 if(flags & F_OR_UNFLAG){
262 SEARCHPGM *pgm2 = mail_newsearchpgm();
263 pgm2->or = mail_newsearchor();
264 pgm2->or->first = pgm;
265 pgm2->or->second = mail_newsearchpgm();
266 pgm2->or->second->unflagged = 1;
267 pgm = pgm2;
270 if(flags & F_OR_ANS){
271 SEARCHPGM *pgm2 = mail_newsearchpgm();
272 pgm2->or = mail_newsearchor();
273 pgm2->or->first = pgm;
274 pgm2->or->second = mail_newsearchpgm();
275 pgm2->or->second->answered = 1;
276 pgm = pgm2;
279 if(flags & F_OR_UNANS){
280 SEARCHPGM *pgm2 = mail_newsearchpgm();
281 pgm2->or = mail_newsearchor();
282 pgm2->or->first = pgm;
283 pgm2->or->second = mail_newsearchpgm();
284 pgm2->or->second->unanswered = 1;
285 pgm = pgm2;
288 if(flags & (F_OR_FWD | F_OR_UNFWD)){
289 STRINGLIST **slpp;
290 SEARCHPGM *pgm2 = mail_newsearchpgm();
291 pgm2->or = mail_newsearchor();
292 pgm2->or->first = pgm;
293 pgm2->or->second = mail_newsearchpgm();
295 for(slpp = (flags & F_OR_FWD)
296 ? &pgm2->or->second->keyword
297 : &pgm2->or->second->unkeyword;
298 *slpp;
299 slpp = &(*slpp)->next)
302 *slpp = mail_newstringlist();
303 (*slpp)->text.data = (unsigned char *) cpystr(FORWARDED_FLAG);
304 (*slpp)->text.size = (unsigned long) strlen(FORWARDED_FLAG);
306 pgm = pgm2;
309 if(flags & F_OR_RECENT){
310 SEARCHPGM *pgm2 = mail_newsearchpgm();
311 pgm2->or = mail_newsearchor();
312 pgm2->or->first = pgm;
313 pgm2->or->second = mail_newsearchpgm();
314 pgm2->or->second->recent = 1;
315 pgm = pgm2;
318 pgm->msgno = full_set;
320 pine_mail_search_full(mm_search_stream = stream, NULL,
321 pgm, SE_NOPREFETCH | SE_FREE);
323 if(!(flags & F_NOFILT) && new != sp_new_mail_count(stream)){
324 process_filter_patterns(stream, sp_msgmap(stream),
325 sp_new_mail_count(stream));
327 flag_search(stream, flags, set_start, set_msgmap, ping);
330 else{
331 if(full_set){
332 /* sequence bits of interesting msgs set */
333 mail_free_searchset(&full_set);
335 else{
336 /* light sequence bits of interesting msgs */
337 for(i = 1L;
338 (n = flag_search_sequence(stream, set_msgmap, i, MH_ANYTHD)) >= 0L;
339 i++)
340 if(n > 0L && n <= stream->nmsgs
341 && (mc = mail_elt(stream, n)) != NULL)
342 mc->sequence = !mc->valid ? 1 : 0;
345 for(i = 1L; i <= stream->nmsgs; i++)
346 if((mc = mail_elt(stream, i)) != NULL)
347 mc->searched = 0;
349 if((seq = build_sequence(stream, NULL, NULL)) != NULL){
350 pine_mail_fetch_flags(stream, seq, 0L);
351 fs_give((void **) &seq);
358 /*----------------------------------------------------------------------
359 count messages on stream with specified system flag attributes
361 Args: stream -- The stream/folder to look at message status
362 flags -- flags on folder/stream to examine
364 Result: count of messages flagged as requested
366 Task: return count of message flagged as requested while being
367 as server/network friendly as possible.
369 Strategy: run thru flags to make sure they're all valid. If any
370 invalid, do a search starting with the invalid message.
371 If all valid, ping the server to let it know we're
372 receptive to flag updates. At this
374 ----------------------------------------------------------------------*/
375 long
376 count_flagged(MAILSTREAM *stream, long int flags)
378 long n, count;
379 MESSAGECACHE *mc;
381 if(!stream)
382 return(0L);
384 flag_search(stream, flags, 1, NULL, pine_mail_ping);
386 /* Paw thru once more since all should be updated */
387 for(n = 1L, count = 0L; n <= stream->nmsgs; n++)
388 if((((mc = mail_elt(stream, n)) && mc->searched)
389 || (mc && mc->valid && FLAG_MATCH(flags, mc, stream)))
390 && !get_lflag(stream, NULL, n, MN_EXLD)){
391 mc->searched = 1; /* caller may be interested! */
392 count++;
395 return(count);
400 /*----------------------------------------------------------------------
401 Find the first message with the specified flags set
403 Args: flags -- Flags in messagecache to match on
404 stream -- The stream/folder to look at message status
406 Result: Message number of first message with specified flags set or the
407 number of the last message if none found.
408 ----------------------------------------------------------------------*/
409 MsgNo
410 first_sorted_flagged(long unsigned int flags, MAILSTREAM *stream, long int set_start, int opts)
412 MsgNo i, n, start_with, winner = 0L;
413 MESSAGECACHE *mc;
414 int last;
415 MSGNO_S *msgmap;
417 msgmap = sp_msgmap(stream);
419 last = (opts & FSF_LAST);
421 /* set_start only affects which search bits we light */
422 start_with = set_start ? set_start
423 : (flags & F_SRCHBACK)
424 ? mn_get_total(msgmap) : 1L;
425 flag_search(stream, flags, start_with, msgmap, NULL);
427 for(i = start_with;
428 (n = flag_search_sequence(stream, msgmap, i,
429 (opts & FSF_SKIP_CHID) ? 0 : MH_ANYTHD)) >= 0L;
430 (flags & F_SRCHBACK) ? i-- : i++)
431 if(n > 0L && n <= stream->nmsgs
432 && (((mc = mail_elt(stream, n)) && mc->searched)
433 || (mc && mc->valid && FLAG_MATCH(flags, mc, stream)))){
434 winner = i;
435 if(!last)
436 break;
439 if(winner == 0L && flags != F_UNDEL && flags != F_NONE){
440 dprint((4,
441 "First_sorted_flagged didn't find a winner, look for undeleted\n"));
442 winner = first_sorted_flagged(F_UNDEL, stream, 0L,
443 opts | (mn_get_revsort(msgmap) ? 0 : FSF_LAST));
446 if(winner == 0L && flags != F_NONE){
447 dprint((4,
448 "First_sorted_flagged didn't find an undeleted, look for visible\n"));
449 winner = first_sorted_flagged(F_NONE, stream, 0L,
450 opts | (mn_get_revsort(msgmap) ? 0 : FSF_LAST));
453 dprint((4,
454 "First_sorted_flagged returning winner = %ld\n", winner));
455 return(winner ? winner
456 : (mn_get_revsort(msgmap)
457 ? 1L : mn_get_total(msgmap)));
462 /*----------------------------------------------------------------------
463 Find the next message with specified flags set
465 Args: flags -- Flags in messagecache to match on
466 stream -- The stream/folder to look at message status
467 start -- Start looking after this message
468 opts -- These bits are both input and output. On input the bit
469 NSF_TRUST_FLAGS tells us whether we need to ping or not.
470 On input, the bit NSF_SEARCH_BACK tells us that we want to
471 know about matches <= start if we don't find any > start.
472 On output, NSF_FLAG_MATCH is set if we matched a message.
473 Returns: Message number of the matched message, if any; else the start # or
474 the max_msgno if the mailbox changed dramatically.
475 ----------------------------------------------------------------------*/
476 MsgNo
477 next_sorted_flagged(long unsigned int flags, MAILSTREAM *stream, long int start, int *opts)
479 MsgNo i, n, dir;
480 MESSAGECACHE *mc;
481 int rev, fss_flags = 0;
482 MSGNO_S *msgmap;
484 msgmap = sp_msgmap(stream);
487 * Search for the next thing the caller's interested in...
490 fss_flags = (opts && *opts & NSF_SKIP_CHID) ? 0 : MH_ANYTHD;
491 rev = (opts && *opts & NSF_SEARCH_BACK);
492 dir = (rev ? -1L : 1L);
494 flag_search(stream, flags | (rev ? F_SRCHBACK : 0), start + dir,
495 msgmap,
496 (opts && ((*opts) & NSF_TRUST_FLAGS)) ? NULL : pine_mail_ping);
498 for(i = start + dir;
499 (n = flag_search_sequence(stream, msgmap,
500 i, fss_flags)) >= 0L;
501 i += dir)
502 if(n > 0L && n <= stream->nmsgs
503 && (((mc = mail_elt(stream, n)) && mc->searched)
504 || (mc && mc->valid && FLAG_MATCH(flags, mc, stream)))){
505 /* actually found a msg matching the flags */
506 if(opts)
507 (*opts) |= NSF_FLAG_MATCH;
509 return(i);
513 return(MIN(start, mn_get_total(msgmap)));
518 /*----------------------------------------------------------------------
519 get the requested LOCAL flag bits for the given pine message number
521 Accepts: msgs - pointer to message manipulation struct
522 n - message number to get
523 f - bitmap of interesting flags
524 Returns: non-zero if flag set, 0 if not set or no elt (error?)
526 NOTE: this can be used to test system flags
527 ----*/
529 get_lflag(MAILSTREAM *stream, MSGNO_S *msgs, long int n, int f)
531 MESSAGECACHE *mc;
532 PINELT_S *pelt;
533 unsigned long rawno;
535 rawno = msgs ? mn_m2raw(msgs, n) : n;
536 if(!stream || rawno < 1L || rawno > stream->nmsgs)
537 return(0);
539 mc = mail_elt(stream, rawno);
540 if(!mc || (pelt = (PINELT_S *) mc->sparep) == NULL)
541 return(f ? 0 : 1);
543 return((!f)
544 ? !(pelt->hidden || pelt->excluded || pelt->selected ||
545 pelt->colhid || pelt->collapsed || pelt->searched)
546 : (((f & MN_HIDE) ? pelt->hidden : 0)
547 || ((f & MN_EXLD) ? pelt->excluded : 0)
548 || ((f & MN_SLCT) ? pelt->selected : 0)
549 || ((f & MN_STMP) ? pelt->tmp : 0)
550 || ((f & MN_USOR) ? pelt->unsorted : 0)
551 || ((f & MN_COLL) ? pelt->collapsed : 0)
552 || ((f & MN_CHID) ? pelt->colhid : 0)
553 || ((f & MN_CHID2) ? pelt->colhid2 : 0)
554 || ((f & MN_SRCH) ? pelt->searched : 0)));
559 /*----------------------------------------------------------------------
560 set the requested LOCAL flag bits for the given pine message number
562 Accepts: msgs - pointer to message manipulation struct
563 n - message number to set
564 f - bitmap of interesting flags
565 v - value (on or off) flag should get
566 Returns: our index number of first
568 NOTE: this isn't to be used for setting IMAP system flags
569 ----*/
571 set_lflag(MAILSTREAM *stream, MSGNO_S *msgs, long int n, int f, int v)
573 MESSAGECACHE *mc;
574 long rawno = 0L;
575 PINETHRD_S *thrd, *topthrd = NULL;
576 PINELT_S **peltp, *pelt;
578 if(n < 1L || n > mn_get_total(msgs))
579 return(0L);
581 if((rawno=mn_m2raw(msgs, n)) > 0L && stream && rawno <= stream->nmsgs
582 && (mc = mail_elt(stream, rawno))){
583 int was_invisible, is_invisible;
584 int chk_thrd_cnt = 0, thrd_was_visible = 0, was_hidden = 0, is_hidden;
586 if(*(peltp = (PINELT_S **) &mc->sparep) == NULL){
587 *peltp = (PINELT_S *) fs_get(sizeof(PINELT_S));
588 memset(*peltp, 0, sizeof(PINELT_S));
591 pelt = (*peltp);
593 was_invisible = (pelt->hidden || pelt->colhid) ? 1 : 0;
595 if((chk_thrd_cnt = ((msgs->visible_threads >= 0L)
596 && THRD_INDX_ENABLED() && (f & MN_HIDE) && (pelt->hidden != v))) != 0){
597 thrd = fetch_thread(stream, rawno);
598 if(thrd && thrd->top){
599 if(thrd->top == thrd->rawno)
600 topthrd = thrd;
601 else
602 topthrd = fetch_thread(stream, thrd->top);
605 if(topthrd){
606 thrd_was_visible = thread_has_some_visible(stream, topthrd);
607 was_hidden = pelt->hidden ? 1 : 0;
611 if((f & MN_HIDE) && pelt->hidden != v){
612 pelt->hidden = v;
613 msgs->flagged_hid += (v) ? 1L : -1L;
615 if(pelt->hidden && THREADING() && !THRD_INDX()
616 && stream == ps_global->mail_stream
617 && ps_global->thread_disp_style == THREAD_MUTTLIKE)
618 clear_index_cache_for_thread(stream, fetch_thread(stream, rawno),
619 sp_msgmap(stream));
622 if((f & MN_CHID) && pelt->colhid != v){
623 pelt->colhid = v;
624 msgs->flagged_chid += (v) ? 1L : -1L;
627 if((f & MN_CHID2) && pelt->colhid2 != v){
628 pelt->colhid2 = v;
629 msgs->flagged_chid2 += (v) ? 1L : -1L;
632 if((f & MN_COLL) && pelt->collapsed != v){
633 pelt->collapsed = v;
634 msgs->flagged_coll += (v) ? 1L : -1L;
637 if((f & MN_USOR) && pelt->unsorted != v){
638 pelt->unsorted = v;
639 msgs->flagged_usor += (v) ? 1L : -1L;
642 if((f & MN_EXLD) && pelt->excluded != v){
643 pelt->excluded = v;
644 msgs->flagged_exld += (v) ? 1L : -1L;
647 if((f & MN_SLCT) && pelt->selected != v){
648 pelt->selected = v;
649 msgs->flagged_tmp += (v) ? 1L : -1L;
652 if((f & MN_SRCH) && pelt->searched != v){
653 pelt->searched = v;
654 msgs->flagged_srch += (v) ? 1L : -1L;
657 if((f & MN_STMP) && pelt->tmp != v){
658 pelt->tmp = v;
659 msgs->flagged_stmp += (v) ? 1L : -1L;
662 is_invisible = (pelt->hidden || pelt->colhid) ? 1 : 0;
664 if(was_invisible != is_invisible)
665 msgs->flagged_invisible += (v) ? 1L : -1L;
668 * visible_threads keeps track of how many of the max_thrdno threads
669 * are visible and how many are MN_HIDE-hidden.
671 if(chk_thrd_cnt && topthrd
672 && (was_hidden != (is_hidden = pelt->hidden ? 1 : 0))){
673 if(!thrd_was_visible && !is_hidden){
674 /* it is visible now, increase count by one */
675 msgs->visible_threads++;
677 else if(thrd_was_visible && is_hidden){
678 /* thread may have been hidden, check */
679 if(!thread_has_some_visible(stream, topthrd))
680 msgs->visible_threads--;
682 /* else no change */
686 return(1);
691 * Copy value of flag from to flag to.
693 void
694 copy_lflags(MAILSTREAM *stream, MSGNO_S *msgmap, int from, int to)
696 unsigned long i;
697 int hide;
699 hide = ((to == MN_SLCT) && (any_lflagged(msgmap, MN_HIDE) > 0L));
701 set_lflags(stream, msgmap, to, 0);
703 if(any_lflagged(msgmap, from)){
704 for(i = 1L; i <= mn_get_total(msgmap); i++)
705 if(get_lflag(stream, msgmap, i, from))
706 set_lflag(stream, msgmap, i, to, 1);
707 else if(hide)
708 set_lflag(stream, msgmap, i, MN_HIDE, 1);
714 * Set flag f to value v in all message.
716 void
717 set_lflags(MAILSTREAM *stream, MSGNO_S *msgmap, int f, int v)
719 unsigned long i;
721 if((v == 0 && any_lflagged(msgmap, f)) || v )
722 for(i = 1L; i <= mn_get_total(msgmap); i++)
723 set_lflag(stream, msgmap, i, f, v);
728 /*----------------------------------------------------------------------
729 return whether the given flag is set somewhere in the folder
731 Accepts: msgs - pointer to message manipulation struct
732 f - flag bitmap to act on
733 Returns: number of messages with the given flag set.
734 NOTE: the sum, if multiple flags tested, is bogus
735 ----*/
736 long
737 any_lflagged(MSGNO_S *msgs, int f)
739 if(!msgs)
740 return(0L);
742 if(f == MN_NONE)
743 return(!(msgs->flagged_hid || msgs->flagged_exld || msgs->flagged_tmp ||
744 msgs->flagged_coll || msgs->flagged_chid || msgs->flagged_srch));
745 else if(f == (MN_HIDE | MN_CHID))
746 return(msgs->flagged_invisible); /* special non-bogus case */
747 else
748 return(((f & MN_HIDE) ? msgs->flagged_hid : 0L)
749 + ((f & MN_EXLD) ? msgs->flagged_exld : 0L)
750 + ((f & MN_SLCT) ? msgs->flagged_tmp : 0L)
751 + ((f & MN_SRCH) ? msgs->flagged_srch : 0L)
752 + ((f & MN_STMP) ? msgs->flagged_stmp : 0L)
753 + ((f & MN_COLL) ? msgs->flagged_coll : 0L)
754 + ((f & MN_USOR) ? msgs->flagged_usor : 0L)
755 + ((f & MN_CHID) ? msgs->flagged_chid : 0L)
756 + ((f & MN_CHID2) ? msgs->flagged_chid2 : 0L));