void msgno_exclude(MAILSTREAM *stream, MSGNO_S *msgmap, long int msgno, int reset_isort) { long i; /*--- clear all flags to keep our counts consistent ---*/ set_lflag(stream, msgmap, msgno, MN_HIDE | MN_CHID | MN_CHID2 | MN_SLCT, 0); set_lflag(stream, msgmap, msgno, MN_EXLD, 1); /* mark excluded */ /* erase knowledge in sort array (shift array down) */ for(i = msgno + 1L; i <= msgmap->max_msgno; i++) msgmap->sort[i-1L] = msgmap->sort[i]; msgmap->max_msgno = MAX(0L, msgmap->max_msgno - 1L); if(reset_isort) msgno_reset_isort(msgmap); msgno_flush_selected(msgmap, msgno); }
/*---------------------------------------------------------------------- Got thru the message mapping table, and remove messages with DELETED flag Accepts: stream -- mail stream to removed message references from msgs -- pointer to message manipulation struct f -- flags to use a purge criteria ----*/ void msgno_exclude_deleted(MAILSTREAM *stream, MSGNO_S *msgs, char *sequence) { long i, rawno; MESSAGECACHE *mc; int need_isort_reset = 0; if(!msgs || msgs->max_msgno < 1L) return; /* * With 3.91 we're using a new strategy for finding and operating * on all the messages with deleted status. The idea is to do a * mail_search for deleted messages so the elt's "searched" bit gets * set, and then to scan the elt's for them and set our local bit * to indicate they're excluded... */ (void) count_flagged(stream, F_DEL); if(sequence) mail_sequence (stream,sequence); /* * Start with the end of the folder and work backwards so that * msgno_exclude doesn't have to shift the entire array each time when * there are lots of deleteds. In fact, if everything is deleted (like * might be the case in a huge newsgroup) then it never has to shift * anything. It is always at the end of the array just eliminating the * last one instead. So instead of an n**2 operation, it is n. */ for(i = msgs->max_msgno; i >= 1L; i--) if((rawno = mn_m2raw(msgs, i)) > 0L && stream && rawno <= stream->nmsgs && (mc = mail_elt(stream, rawno)) && (sequence ? mc->sequence : 1) && ((mc->valid && mc->deleted) || (!mc->valid && mc->searched))){ msgno_exclude(stream, msgs, i, 0); need_isort_reset++; } if(need_isort_reset) msgno_reset_isort(msgs); /* * If we excluded away a zoomed display, unhide everything... */ if(msgs->max_msgno > 0L && any_lflagged(msgs, MN_HIDE) >= msgs->max_msgno) for(i = 1L; i <= msgs->max_msgno; i++) set_lflag(stream, msgs, i, MN_HIDE, 0); }
/*---------------------------------------------------------------------- Straighten out any local flag problems here. We can't take care of them in the mm_exists or mm_expunged callbacks since the flags themselves are in an MESSAGECACHE and we're not allowed to reenter c-client from a callback... Args: stream -- mail stream to operate on msgmap -- messages in that stream to fix up Result: returns with local flags as they should be ----*/ void fixup_flags(MAILSTREAM *stream, MSGNO_S *msgmap) { /* * Deal with the case where expunged away all of the * zoomed messages. Unhide everything in that case... */ if(mn_get_total(msgmap) > 0L){ long i; if(any_lflagged(msgmap, MN_HIDE) >= mn_get_total(msgmap)){ for(i = 1L; i <= mn_get_total(msgmap); i++) set_lflag(stream, msgmap, i, MN_HIDE, 0); mn_set_cur(msgmap, THREADING() ? first_sorted_flagged(F_NONE, stream, 0L, (THREADING() ? 0 : FSF_SKIP_CHID) | FSF_LAST) : mn_get_total(msgmap)); } else if(any_lflagged(msgmap, MN_HIDE)){ /* * if we got here, there are some hidden messages and * some not. Make sure the current message is one * that's not... */ for(i = mn_get_cur(msgmap); i <= mn_get_total(msgmap); i++) if(!msgline_hidden(stream, msgmap, i, 0)){ mn_set_cur(msgmap, i); break; } for(i = mn_get_cur(msgmap); i > 0L; i--) if(!msgline_hidden(stream, msgmap, i, 0)){ mn_set_cur(msgmap, i); break; } } } }
/*---------------------------------------------------------------------- Accepts: stream -- mail stream to removed message references from msgs -- pointer to message manipulation struct flags MI_REFILTERING -- do includes appropriate for refiltering MI_STATECHGONLY -- when refiltering, maybe only re-include messages which have had state changes since they were originally filtered Returns 1 if any new messages are included (indicating that we need to re-sort) 0 if no new messages are included ----*/ int msgno_include(MAILSTREAM *stream, MSGNO_S *msgs, int flags) { long i, slop, old_total, old_size; int exbits, ret = 0; size_t len; MESSAGECACHE *mc; if(!msgs) return(ret); for(i = 1L; i <= stream->nmsgs; i++){ if(!msgno_exceptions(stream, i, "0", &exbits, FALSE)) exbits = 0; if((((flags & MI_REFILTERING) && (exbits & MSG_EX_FILTERED) && !(exbits & MSG_EX_FILED) && (!(flags & MI_STATECHGONLY) || (exbits & MSG_EX_STATECHG))) || (!(flags & MI_REFILTERING) && !(exbits & MSG_EX_FILTERED))) && get_lflag(stream, NULL, i, MN_EXLD)){ old_total = msgs->max_msgno; old_size = msgs->sort_size; slop = (msgs->max_msgno + 1L) % 64; msgs->sort_size = (msgs->max_msgno + 1L) + (64 - slop); len = (size_t) msgs->sort_size * sizeof(long); if(msgs->sort){ if(old_size != msgs->sort_size) fs_resize((void **)&(msgs->sort), len); } else msgs->sort = (long *)fs_get(len); ret = 1; msgs->sort[++msgs->max_msgno] = i; msgs->isort[i] = msgs->max_msgno; set_lflag(stream, msgs, msgs->max_msgno, MN_EXLD, 0); if(flags & MI_REFILTERING){ exbits &= ~(MSG_EX_FILTERED | MSG_EX_TESTED); msgno_exceptions(stream, i, "0", &exbits, TRUE); } if(old_total <= 0L){ /* if no previous messages, */ if(!msgs->select){ /* select the new message */ msgs->sel_size = 8L; len = (size_t)msgs->sel_size * sizeof(long); msgs->select = (long *)fs_get(len); } msgs->sel_cnt = 1L; msgs->sel_cur = 0L; msgs->select[0] = 1L; } } else if((flags & MI_REFILTERING) && (exbits & (MSG_EX_FILTERED | MSG_EX_TESTED)) && !(exbits & MSG_EX_FILED) && (!(exbits & MSG_EX_MANUNDEL) || ((mc = mail_elt(stream, i)) && mc->deleted)) && (!(flags & MI_STATECHGONLY) || (exbits & MSG_EX_STATECHG))){ /* * We get here if the message was filtered by a filter that * just changes status bits (it wasn't excluded), and now also * if the message was merely tested for filtering. It has also * not been manually undeleted. If it was manually undeleted, we * don't want to reprocess the filter, undoing the user's * manual undeleting. Of course, a new pine will re check this * message anyway, so the user had better be using this * manual undeleting only to temporarily save him or herself * from an expunge before Saving or printing or something. * Also, we want to still try filtering if the message has at * all been marked deleted, even if the there was any manual * undeleting, since this directly precedes an expunge, we want * to make sure the filter does the right thing before getting * rid of the message forever. */ exbits &= ~(MSG_EX_FILTERED | MSG_EX_TESTED); msgno_exceptions(stream, i, "0", &exbits, TRUE); } } return(ret); }