diff -rc pine4.61/pine/args.c pine4.61.fancy/pine/args.c *** pine4.61/pine/args.c Fri Oct 10 14:05:32 2003 --- pine4.61.fancy/pine/args.c Thu Aug 19 13:18:11 2004 *************** *** 74,79 **** --- 74,80 ---- char args_err_non_abs_passfile[] = "argument to \"-passfile\" should be fully-qualified"; char args_err_missing_lu[] = "missing argument for option \"-create_lu\"\nUsage: pine -create_lu "; char args_err_missing_sort[] = "missing argument for option \"-sort\""; + char args_err_missing_thread_sort[] = "missing argument for option \"-threadsort\""; char args_err_missing_flag_arg[] = "missing argument for flag \"%c\""; char args_err_missing_flag_num[] = "Non numeric argument for flag \"%c\""; char args_err_missing_debug_num[] = "Non numeric argument for \"%s\""; *************** *** 117,122 **** --- 118,124 ---- " -z \t\tSuspend - allow use of ^Z suspension", " -r \t\tRestricted - can only send mail to oneself", " -sort \tSort - Specify sort order of folder:", + " -threadsort \tSort - Specify sort order of thread index screen:", "\t\t subject, arrival, date, from, size, /reverse", " -i\t\tIndex - Go directly to index, bypassing main menu", " -I Initial keystrokes to be executed", *************** *** 202,207 **** --- 204,210 ---- char *cmd_list = NULL; char *debug_str = NULL; char *sort = NULL; + char *threadsort = NULL; char *pinerc_file = NULL; char *addrbook_file = NULL; char *ab_sort_descrip = NULL; *************** *** 389,394 **** --- 392,409 ---- goto Loop; } + else if(strcmp(*av, "threadsort") == 0){ + if(--ac){ + threadsort = *++av; + COM_THREAD_SORT_KEY = cpystr(threadsort); + } + else{ + display_args_err(args_err_missing_thread_sort, NULL, 1); + ++usage; + } + + goto Loop; + } else if(strcmp(*av, "url") == 0){ if(args->action == aaFolder && !args->data.folder){ args->action = aaURL; diff -rc pine4.61/pine/init.c pine4.61.fancy/pine/init.c *** pine4.61/pine/init.c Thu Jul 15 10:37:24 2004 --- pine4.61.fancy/pine/init.c Thu Aug 19 13:18:11 2004 *************** *** 214,219 **** --- 214,221 ---- CONF_TXT_T cf_text_sort_key[] = "Sets presentation order of messages in Index. Choices:\n# subject, from, arrival, date, size. Default: \"arrival\"."; + CONF_TXT_T cf_text_thread_sort_key[] = "#Sets presentation order of threads in thread index. Choices:\n#arrival, and thread."; + CONF_TXT_T cf_text_addrbook_sort_rule[] = "Sets presentation order of address book entries. Choices: dont-sort,\n# fullname-with-lists-last, fullname, nickname-with-lists-last, nickname\n# Default: \"fullname-with-lists-last\"."; CONF_TXT_T cf_text_folder_sort_rule[] = "Sets presentation order of folder list entries. Choices: alphabetical,\n# alpha-with-dirs-last, alpha-with-dirs-first.\n# Default: \"alpha-with-directories-last\"."; *************** *** 501,506 **** --- 503,510 ---- cf_text_fcc_name_rule}, {"sort-key", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, cf_text_sort_key}, + {"thread-sort-key", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, + cf_text_thread_sort_key}, {"addrbook-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, cf_text_addrbook_sort_rule}, {"folder-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, *************** *** 1449,1455 **** register struct variable *vars = ps->vars; int obs_header_in_reply, /* the obs_ variables are to */ obs_old_style_reply, /* support backwards compatibility */ ! obs_save_by_sender, i, def_sort_rev; long rvl; PINERC_S *fixedprc = NULL; FeatureLevel obs_feature_level; --- 1453,1459 ---- register struct variable *vars = ps->vars; int obs_header_in_reply, /* the obs_ variables are to */ obs_old_style_reply, /* support backwards compatibility */ ! obs_save_by_sender, i, def_sort_rev, thread_def_sort_rev; long rvl; PINERC_S *fixedprc = NULL; FeatureLevel obs_feature_level; *************** *** 1471,1476 **** --- 1475,1481 ---- GLO_FEATURE_LEVEL = cpystr(DF_FEATURE_LEVEL); GLO_OLD_STYLE_REPLY = cpystr(DF_OLD_STYLE_REPLY); GLO_SORT_KEY = cpystr(DF_SORT_KEY); + GLO_THREAD_SORT_KEY = cpystr(DF_THREAD_SORT_KEY); GLO_SAVED_MSG_NAME_RULE = cpystr(DF_SAVED_MSG_NAME_RULE); GLO_FCC_RULE = cpystr(DF_FCC_RULE); GLO_AB_SORT_RULE = cpystr(DF_AB_SORT_RULE); *************** *** 2287,2293 **** set_current_val(&vars[V_ARCHIVED_FOLDERS], TRUE, TRUE); set_current_val(&vars[V_INCOMING_FOLDERS], TRUE, TRUE); set_current_val(&vars[V_SORT_KEY], TRUE, TRUE); ! if(decode_sort(VAR_SORT_KEY, &ps->def_sort, &def_sort_rev) == -1){ sprintf(tmp_20k_buf, "Sort type \"%.200s\" is invalid", VAR_SORT_KEY); init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf); ps->def_sort = SortArrival; --- 2292,2298 ---- set_current_val(&vars[V_ARCHIVED_FOLDERS], TRUE, TRUE); set_current_val(&vars[V_INCOMING_FOLDERS], TRUE, TRUE); set_current_val(&vars[V_SORT_KEY], TRUE, TRUE); ! if(decode_sort(VAR_SORT_KEY, &ps->def_sort, &def_sort_rev,0) == -1){ sprintf(tmp_20k_buf, "Sort type \"%.200s\" is invalid", VAR_SORT_KEY); init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf); ps->def_sort = SortArrival; *************** *** 2296,2301 **** --- 2301,2317 ---- else ps->def_sort_rev = def_sort_rev; + set_current_val(&vars[V_THREAD_SORT_KEY], TRUE, TRUE); + if(decode_sort(VAR_THREAD_SORT_KEY, &ps->thread_def_sort, + &thread_def_sort_rev, 1) == -1){ + sprintf(tmp_20k_buf, "Sort type \"%s\" is invalid", VAR_THREAD_SORT_KEY); + init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf); + ps->thread_def_sort = SortThread; + ps->thread_def_sort_rev = 0; + } + else + ps->thread_def_sort_rev = thread_def_sort_rev; + cur_rule_value(&vars[V_SAVED_MSG_NAME_RULE], TRUE, TRUE); {NAMEVAL_S *v; int i; for(i = 0; v = save_msg_rules(i); i++) *************** *** 2665,2670 **** --- 2681,2688 ---- F_TAB_TO_NEW, h_config_tab_new_only, PREF_INDX}, {"thread-index-shows-important-color", F_COLOR_LINE_IMPORTANT, h_config_color_thrd_import, PREF_INDX}, + {"enhanced-fancy-thread-support", + F_ENHANCED_THREAD, h_config_enhanced_thread, PREF_INDX}, /* Viewer prefs */ {"enable-msg-view-addresses", *************** *** 6339,6361 **** * argument also means arrival/reverse. */ int ! decode_sort(sort_spec, def_sort, def_sort_rev) char *sort_spec; SortOrder *def_sort; int *def_sort_rev; { char *sep; char *fix_this = NULL; ! int x, reverse; if(!sort_spec || !*sort_spec){ ! *def_sort = SortArrival; *def_sort_rev = 0; return(0); } if(struncmp(sort_spec, "reverse", strlen(sort_spec)) == 0){ ! *def_sort = SortArrival; *def_sort_rev = 1; return(0); } --- 6357,6380 ---- * argument also means arrival/reverse. */ int ! decode_sort(sort_spec, def_sort, def_sort_rev, thread) char *sort_spec; SortOrder *def_sort; int *def_sort_rev; + int thread; { char *sep; char *fix_this = NULL; ! int x = 0, reverse; if(!sort_spec || !*sort_spec){ ! *def_sort = thread ? SortThread : SortArrival; *def_sort_rev = 0; return(0); } if(struncmp(sort_spec, "reverse", strlen(sort_spec)) == 0){ ! *def_sort = thread ? SortThread : SortArrival; *def_sort_rev = 1; return(0); } *************** *** 6378,6390 **** sort_spec, strlen(sort_spec)) == 0) break; if(fix_this) *fix_this = '/'; if(ps_global->sort_types[x] == EndofList) return(-1); ! *def_sort = ps_global->sort_types[x]; *def_sort_rev = reverse; return(0); } --- 6397,6415 ---- sort_spec, strlen(sort_spec)) == 0) break; + if (thread && ps_global->sort_types[x] != SortArrival + && ps_global->sort_types[x] != SortDate + && ps_global->sort_types[x] != SortThread) + for(x = 0; ps_global->sort_types[x] != EndofList; x++); + if(fix_this) *fix_this = '/'; if(ps_global->sort_types[x] == EndofList) return(-1); ! *def_sort = (thread && ps_global->sort_types[x] == SortDate) ! ? SortThread : ps_global->sort_types[x]; *def_sort_rev = reverse; return(0); } diff -rc pine4.61/pine/mailcmd.c pine4.61.fancy/pine/mailcmd.c *** pine4.61/pine/mailcmd.c Tue Jul 13 18:35:15 2004 --- pine4.61.fancy/pine/mailcmd.c Thu Aug 19 13:47:28 2004 *************** *** 92,98 **** void set_keywords_in_msgid_msg PROTO((MAILSTREAM *, MESSAGECACHE *, MAILSTREAM *, char *)); long get_msgno_by_msg_id PROTO((MAILSTREAM *, char *, MSGNO_S *)); ! int select_sort PROTO((struct pine *, int, SortOrder *, int *)); void aggregate_select PROTO((struct pine *, MSGNO_S *, int, CmdWhere,int)); int select_number PROTO((MAILSTREAM *, MSGNO_S *, long, SEARCHSET **)); int select_thrd_number PROTO((MAILSTREAM *, MSGNO_S *, long, --- 92,98 ---- void set_keywords_in_msgid_msg PROTO((MAILSTREAM *, MESSAGECACHE *, MAILSTREAM *, char *)); long get_msgno_by_msg_id PROTO((MAILSTREAM *, char *, MSGNO_S *)); ! int select_sort PROTO((struct pine *, int, SortOrder *, int *, int)); void aggregate_select PROTO((struct pine *, MSGNO_S *, int, CmdWhere,int)); int select_number PROTO((MAILSTREAM *, MSGNO_S *, long, SEARCHSET **)); int select_thrd_number PROTO((MAILSTREAM *, MSGNO_S *, long, *************** *** 109,114 **** --- 109,135 ---- char *currentf_sequence PROTO((MAILSTREAM *, MSGNO_S *, long, long *, int, char **, char **)); char *invalid_elt_sequence PROTO((MAILSTREAM *, MSGNO_S *)); + long top_thread PROTO((MAILSTREAM *, long)); + void move_top_thread PROTO((MAILSTREAM *, MSGNO_S *, long)); + long top_this_thread PROTO((MAILSTREAM *, long)); + void move_top_this_thread PROTO((MAILSTREAM *, MSGNO_S *, long)); + void cmd_delete_this_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *)); + void cmd_delete_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *)); + void cmd_undelete_this_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *)); + void cmd_undelete_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *)); + void cmd_select_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *)); + void kolapse_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, char, int)); + int count_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, long)); + int count_this_thread PROTO((MAILSTREAM *, unsigned long)); + int this_thread_is_kolapsed PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, long)); + int thread_is_kolapsed PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, long)); + int collapse_this_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int, int)); + void collapse_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int)); + int expand_this_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int, int)); + void expand_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int)); + int move_next_this_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int)); + int move_next_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int)); + int move_prev_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int)); char *selected_sequence PROTO((MAILSTREAM *, MSGNO_S *, long *, int)); int any_messages PROTO((MSGNO_S *, char *, char *)); int can_set_flag PROTO((struct pine *, char *, int)); *************** *** 1154,1159 **** --- 1175,1184 ---- if(SORT_IS_THREADED(msgmap)) refresh_sort(stream, msgmap, SRT_NON); + if (msgmap->nmsgs + && F_ON(F_ENHANCED_THREAD, state) && COLL_THRDS()) + kolapse_thread(state, stream, msgmap, '[', 0); + state->mangled_body = 1; state->mangled_header = 1; q_status_message2(SM_ORDER, 0, 4, *************** *** 1266,1271 **** --- 1291,1299 ---- */ if(SORT_IS_THREADED(msgmap)) refresh_sort(stream, msgmap, SRT_NON); + if (msgmap->nmsgs + && F_ON(F_ENHANCED_THREAD, state) && COLL_THRDS()) + kolapse_thread(state, stream, msgmap, '[', 0); } else{ if(del_count) *************** *** 1401,1407 **** if(any_messages(msgmap, NULL, NULL)){ if(any_lflagged(msgmap, MN_SLCT) > 0L){ if(apply_command(state, stream, msgmap, 0, ! AC_NONE, question_line) && F_ON(F_AUTO_UNZOOM, state)) unzoom_index(state, stream, msgmap); } --- 1429,1435 ---- if(any_messages(msgmap, NULL, NULL)){ if(any_lflagged(msgmap, MN_SLCT) > 0L){ if(apply_command(state, stream, msgmap, 0, ! AC_NONE, question_line, 1) && F_ON(F_AUTO_UNZOOM, state)) unzoom_index(state, stream, msgmap); } *************** *** 1414,1431 **** /*-------- Sort command -------*/ case MC_SORT : { int were_threading = THREADING(); SortOrder sort = mn_get_sort(msgmap); int rev = mn_get_revsort(msgmap); dprint(1, (debugfile,"MAIL_CMD: sort\n")); ! if(select_sort(state, question_line, &sort, &rev)){ /* $ command reinitializes threading collapsed/expanded info */ if(SORT_IS_THREADED(msgmap) && !SEP_THRDINDX()) erase_threading_info(stream, msgmap); ! sort_folder(stream, msgmap, sort, rev, SRT_VRB|SRT_MAN); } state->mangled_footer = 1; --- 1442,1466 ---- /*-------- Sort command -------*/ case MC_SORT : + case MC_SORTHREAD : { int were_threading = THREADING(); SortOrder sort = mn_get_sort(msgmap); int rev = mn_get_revsort(msgmap); + int thread = (command == MC_SORT) ? 0 : 1; + if (sort == SortThread) + sort = ps_global->thread_cur_sort; dprint(1, (debugfile,"MAIL_CMD: sort\n")); ! if(select_sort(state, question_line, &sort, &rev, thread)){ /* $ command reinitializes threading collapsed/expanded info */ if(SORT_IS_THREADED(msgmap) && !SEP_THRDINDX()) erase_threading_info(stream, msgmap); ! if (command == MC_SORTHREAD) ! ps_global->thread_cur_sort = sort; ! sort = (command == MC_SORT) ? sort : SortThread; ! sort_folder(stream, msgmap, sort, rev, SRT_VRB|SRT_MAN, 1); } state->mangled_footer = 1; *************** *** 8070,8076 **** /* set default order */ the_sort_order = ps_global->def_sort; ! sort_is_rev = ps_global->def_sort_rev; if(ps_global->mail_stream && nonempty_patterns(rflags, &pstate)){ for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){ --- 8105,8113 ---- /* set default order */ the_sort_order = ps_global->def_sort; ! sort_is_rev = the_sort_order == SortThread ! ? (ps_global->thread_def_sort_rev + ps_global->def_sort_rev) % 2 ! : ps_global->def_sort_rev; if(ps_global->mail_stream && nonempty_patterns(rflags, &pstate)){ for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){ *************** *** 8082,8093 **** if(pat && pat->action && !pat->action->bogus && pat->action->sort_is_set){ the_sort_order = pat->action->sortorder; ! sort_is_rev = pat->action->revsort; } } sort_folder(ps_global->mail_stream, ps_global->msgmap, ! the_sort_order, sort_is_rev, flags); } --- 8119,8136 ---- if(pat && pat->action && !pat->action->bogus && pat->action->sort_is_set){ the_sort_order = pat->action->sortorder; ! sort_is_rev = the_sort_order == SortThread ! ? (ps_global->thread_def_sort_rev + pat->action->revsort) % 2 ! : pat->action->revsort; } } + if (ps_global->thread_cur_sort != SortArrival + && ps_global->thread_cur_sort != SortThread) + ps_global->thread_cur_sort = ps_global->thread_def_sort; + sort_folder(ps_global->mail_stream, ps_global->msgmap, ! the_sort_order, sort_is_rev, flags, 1); } *************** *** 11207,11219 **** ----*/ int ! apply_command(state, stream, msgmap, preloadkeystroke, flags, q_line) struct pine *state; MAILSTREAM *stream; MSGNO_S *msgmap; int preloadkeystroke; int flags; int q_line; { int i = 8, /* number of static entries in sel_opts3 */ rv = 1, --- 11250,11263 ---- ----*/ int ! apply_command(state, stream, msgmap, preloadkeystroke, flags, q_line, display) struct pine *state; MAILSTREAM *stream; MSGNO_S *msgmap; int preloadkeystroke; int flags; int q_line; + int display; { int i = 8, /* number of static entries in sel_opts3 */ rv = 1, *************** *** 11340,11348 **** collapse_or_expand(state, stream, msgmap, F_ON(F_SLASH_COLL_ENTIRE, ps_global) ? 0L ! : mn_get_cur(msgmap)); break; case ':' : select_thread_stmp(state, stream, msgmap); break; --- 11384,11402 ---- collapse_or_expand(state, stream, msgmap, F_ON(F_SLASH_COLL_ENTIRE, ps_global) ? 0L ! : mn_get_cur(msgmap), ! display); break; + case '[' : + collapse_this_thread(state, stream, msgmap, display, 0); + break; + + case ']' : + expand_this_thread(state, stream, msgmap, display, 0); + break; + + case ':' : select_thread_stmp(state, stream, msgmap); break; *************** *** 11840,11845 **** --- 11894,11900 ---- SEARCHSET **msgset; { PINETHRD_S *nthrd, *bthrd; + unsigned long next, branch; if(!(stream && thrd)) return; *************** *** 11848,11861 **** && (!(msgset && *msgset) || in_searchset(*msgset, thrd->rawno))) mm_searched(stream, thrd->rawno); ! if(thrd->next){ ! nthrd = fetch_thread(stream, thrd->next); if(nthrd) set_search_bit_for_thread(stream, nthrd, msgset); } ! if(thrd->branch){ ! bthrd = fetch_thread(stream, thrd->branch); if(bthrd) set_search_bit_for_thread(stream, bthrd, msgset); } --- 11903,11916 ---- && (!(msgset && *msgset) || in_searchset(*msgset, thrd->rawno))) mm_searched(stream, thrd->rawno); ! if(next= get_next(stream, thrd)){ ! nthrd = fetch_thread(stream, next); if(nthrd) set_search_bit_for_thread(stream, nthrd, msgset); } ! if(branch = get_branch(stream, thrd)){ ! bthrd = fetch_thread(stream, branch); if(bthrd) set_search_bit_for_thread(stream, bthrd, msgset); } *************** *** 13050,13063 **** Returns 0 if it was cancelled, 1 otherwise. ----*/ int ! select_sort(state, ql, sort, rev) struct pine *state; int ql; SortOrder *sort; int *rev; { char prompt[200], tmp[3], *p; ! int s, i; int deefault = 'a', retval = 1; HelpType help; ESCKEY_S sorts[14]; --- 13105,13119 ---- Returns 0 if it was cancelled, 1 otherwise. ----*/ int ! select_sort(state, ql, sort, rev, thread) struct pine *state; int ql; SortOrder *sort; int *rev; + int thread; { char prompt[200], tmp[3], *p; ! int s, i, j; int deefault = 'a', retval = 1; HelpType help; ESCKEY_S sorts[14]; *************** *** 13086,13102 **** /*----- String together the prompt ------*/ tmp[1] = '\0'; strcpy(prompt, "Choose type of sort, or 'R' to reverse current sort : "); ! for(i = 0; state->sort_types[i] != EndofList; i++) { ! sorts[i].rval = i; ! p = sorts[i].label = sort_name(state->sort_types[i]); ! while(*(p+1) && islower((unsigned char)*p)) ! p++; ! ! sorts[i].ch = tolower((unsigned char)(tmp[0] = *p)); ! sorts[i].name = cpystr(tmp); ! ! if(mn_get_sort(state->msgmap) == state->sort_types[i]) ! deefault = sorts[i].rval; } sorts[i].ch = 'r'; --- 13142,13168 ---- /*----- String together the prompt ------*/ tmp[1] = '\0'; strcpy(prompt, "Choose type of sort, or 'R' to reverse current sort : "); ! for(i = 0, j = 0; state->sort_types[i] != EndofList; i++) { ! sorts[i].rval = i; ! sorts[i].name = cpystr(""); ! sorts[i].label = ""; ! sorts[i].ch = -2; ! if (!thread || state->sort_types[i] == SortArrival ! || state->sort_types[i] == SortThread){ ! p = sorts[j].label = sort_name(state->sort_types[i]); ! while(*(p+1) && islower((unsigned char)*p)) ! p++; ! sorts[j].ch = tolower((unsigned char)(tmp[0] = *p)); ! sorts[j++].name = cpystr(tmp); ! } ! ! if (thread){ ! if (state->thread_def_sort == state->sort_types[i]) ! deefault = sorts[j-1].rval; ! } ! else ! if(mn_get_sort(state->msgmap) == state->sort_types[i]) ! deefault = sorts[i].rval; } sorts[i].ch = 'r'; *************** *** 13111,13117 **** if(s == 'r') *rev = !mn_get_revsort(state->msgmap); else ! *sort = state->sort_types[s]; if(F_ON(F_SHOW_SORT, ps_global)) ps_global->mangled_header = 1; --- 13177,13183 ---- if(s == 'r') *rev = !mn_get_revsort(state->msgmap); else ! *sort = state->sort_types[thread ? (s == 0 ? 1 : 9) : s]; if(F_ON(F_SHOW_SORT, ps_global)) ps_global->mangled_header = 1; *************** *** 13795,13797 **** --- 13861,14559 ---- return(flag_submenu); } #endif /* _WINDOWS */ + + /* Extra Fancy Thread support */ + + long + top_thread(stream, rawmsgno) + MAILSTREAM *stream; + long rawmsgno; + { + PINETHRD_S *thrd = NULL; + unsigned long rawno; + + if(!stream) + return -1L; + + if(rawmsgno) + thrd = fetch_thread(stream, rawmsgno); + + if(!thrd) + return -1L; + + return F_ON(F_ENHANCED_THREAD, ps_global) + ? (thrd->toploose ? thrd->toploose : thrd->top) + : thrd->top; + } + + void + move_top_thread(stream, msgmap, rawmsgno) + MAILSTREAM *stream; + MSGNO_S *msgmap; + long rawmsgno; + { + mn_set_cur(msgmap,mn_raw2m(msgmap, top_thread(stream, rawmsgno))); + } + + long + top_this_thread(stream, rawmsgno) + MAILSTREAM *stream; + long rawmsgno; + { + PINETHRD_S *thrd = NULL; + unsigned long rawno; + + if(!stream) + return -1L; + + if(rawmsgno) + thrd = fetch_thread(stream, rawmsgno); + + if(!thrd) + return -1L; + + return thrd->top; + } + + void + move_top_this_thread(stream, msgmap, rawmsgno) + MAILSTREAM *stream; + MSGNO_S *msgmap; + long rawmsgno; + { + mn_set_cur(msgmap,mn_raw2m(msgmap, top_this_thread(stream, rawmsgno))); + } + + + void + cmd_delete_this_thread(state, stream, msgmap) + struct pine *state; + MAILSTREAM *stream; + MSGNO_S *msgmap; + { + unsigned long rawno, top, save_kolapsed; + PINETHRD_S *thrd = NULL, *nxthrd; + + if(!stream) + return; + + rawno = mn_m2raw(msgmap, mn_get_cur(msgmap)); + move_top_this_thread(stream, msgmap, rawno); + top = mn_m2raw(msgmap, mn_get_cur(msgmap)); + if(top) + thrd = fetch_thread(stream, top); + + if(!thrd) + return; + + save_kolapsed = this_thread_is_kolapsed(state, stream, msgmap, top); + collapse_this_thread(state, stream, msgmap, 0, 0); + thread_command(state, stream, msgmap, 'd', -FOOTER_ROWS(state), 1); + if (!save_kolapsed) + expand_this_thread(state, stream, msgmap, 0, 0); + } + + void + cmd_delete_thread(state, stream, msgmap) + struct pine *state; + MAILSTREAM *stream; + MSGNO_S *msgmap; + { + unsigned long rawno, top, orig_top, topnxt, save_kolapsed; + PINETHRD_S *thrd = NULL, *nxthrd; + int done = 0, count; + + if(!stream) + return; + + rawno = mn_m2raw(msgmap, mn_get_cur(msgmap)); + move_top_thread(stream, msgmap, rawno); + top = orig_top = mn_m2raw(msgmap, mn_get_cur(msgmap)); + if(top) + thrd = fetch_thread(stream, top); + + if(!thrd) + return; + + while (!done){ + cmd_delete_this_thread(state, stream, msgmap); + if (F_OFF(F_ENHANCED_THREAD, state) + || (move_next_this_thread(state, stream, msgmap, 0) <= 0) + || !(top = mn_m2raw(msgmap, mn_get_cur(msgmap))) + || (orig_top != top_thread(stream, top))) + done++; + } + mn_set_cur(msgmap,mn_raw2m(msgmap, rawno)); + cmd_delete(state, msgmap, 0, MsgIndx); + count = count_thread(state, stream, msgmap, rawno); + q_status_message2(SM_ORDER, 0, 1, "%s message%s marked deleted", + int2string(count), plural(count)); + } + + + + int + thread_is_kolapsed(state, stream, msgmap, rawmsgno) + struct pine *state; + MAILSTREAM *stream; + MSGNO_S *msgmap; + long rawmsgno; + { + int collapsed; + PINETHRD_S *thrd = NULL; + unsigned long rawno, orig, orig_rawno; + + if(!stream) + return -1; + + orig = mn_get_cur(msgmap); + move_top_thread(stream, msgmap, rawmsgno); + rawno = orig_rawno = mn_m2raw(msgmap, mn_get_cur(msgmap)); + if(rawno) + thrd = fetch_thread(stream, rawno); + + if(!thrd) + return -1; + + while(collapsed = this_thread_is_kolapsed(state, stream, msgmap, rawno)) + if (F_OFF(F_ENHANCED_THREAD, state) + || (move_next_this_thread(state, stream, msgmap, 0) <= 0) + || !(rawno = mn_m2raw(msgmap, mn_get_cur(msgmap))) + || (orig_rawno != top_thread(stream, rawno))) + break; + + mn_set_cur(msgmap,orig); /* return home */ + + return collapsed; + } + + /* this function tells us if the thread (or branch in the case of loose threads) + * is collapsed + */ + + int + this_thread_is_kolapsed(state, stream, msgmap, rawmsgno) + struct pine *state; + MAILSTREAM *stream; + MSGNO_S *msgmap; + long rawmsgno; + { + int collapsed; + PINETHRD_S *thrd = NULL; + unsigned long rawno, orig; + + if(!stream) + return -1; + + rawno = rawmsgno; + if(rawno) + thrd = fetch_thread(stream, rawno); + + if(!thrd) + return -1; + + collapsed = get_lflag(stream, NULL, rawno, MN_COLL | MN_CHID); + + if (!thrd->next){ + if (thrd->rawno != top_thread(stream, thrd->rawno)) + collapsed = get_lflag(stream, NULL, rawno, MN_CHID); + else + collapsed = get_lflag(stream, NULL, rawno, MN_COLL); + } + + return collapsed; + } + + int + collapse_this_thread(state, stream, msgmap, display, special) + struct pine *state; + MAILSTREAM *stream; + MSGNO_S *msgmap; + int display; + int special; + { + int collapsed, rv = 1, done = 0; + PINETHRD_S *thrd = NULL, *nthrd; + unsigned long rawno, orig, msgno; + + if(!stream) + return 0; + + rawno = mn_m2raw(msgmap, mn_get_cur(msgmap)); + + if(rawno) + thrd = fetch_thread(stream, rawno); + + if(!thrd) + return rv; + + collapsed = this_thread_is_kolapsed(state, stream, msgmap, rawno); + + if (special && collapsed){ + expand_this_thread(state, stream, msgmap, 0, 0); + collapsed = 0; + } + + clear_index_cache_ent(mn_raw2m(msgmap,rawno)); + + if (!collapsed && thrd->next){ + if (thrd->rawno == top_thread(stream, thrd->rawno)) + collapse_or_expand(state, stream, msgmap, mn_get_cur(msgmap), display); + else{ + set_lflag(stream, msgmap, mn_raw2m(msgmap,thrd->rawno), MN_COLL, 1); + set_thread_subtree(stream, thrd, msgmap, 1, MN_CHID); + } + } + else{ + if (!collapsed && special + && ((F_OFF(F_ENHANCED_THREAD, state) && !thrd->next) + || F_ON(F_ENHANCED_THREAD, state))){ + if (thrd->toploose){ + if (thrd->rawno != thrd->toploose) + set_lflag(stream, msgmap, mn_raw2m(msgmap,thrd->rawno),MN_CHID, + 1); + else + set_lflag(stream, msgmap, mn_raw2m(msgmap,thrd->rawno),MN_COLL, + 1); + } + } + else{ + rv = 0; + if (display) + q_status_message(SM_ORDER, 0, 1, "Thread already collapsed"); + } + } + return rv; + } + + void + collapse_thread(state, stream, msgmap, display) + struct pine *state; + MAILSTREAM *stream; + MSGNO_S *msgmap; + int display; + { + int collapsed, rv = 1, done = 0; + PINETHRD_S *thrd = NULL; + unsigned long orig, orig_top, top; + + if(!stream) + return; + + expand_this_thread(state, stream, msgmap, display, 1); + orig = mn_m2raw(msgmap, mn_get_cur(msgmap)); + move_top_thread(stream, msgmap,orig); + top = orig_top = mn_m2raw(msgmap, mn_get_cur(msgmap)); + + if(top) + thrd = fetch_thread(stream, top); + + if(!thrd) + return; + + while (!done){ + collapse_this_thread(state, stream, msgmap, display, 1); + if (F_OFF(F_ENHANCED_THREAD, state) + || (move_next_this_thread(state, stream, msgmap, 0) <= 0) + || !(top = mn_m2raw(msgmap, mn_get_cur(msgmap))) + || (orig_top != top_thread(stream, top))) + done++; + } + mn_set_cur(msgmap,mn_raw2m(msgmap, orig_top)); + } + + int + expand_this_thread(state, stream, msgmap, display, special) + struct pine *state; + MAILSTREAM *stream; + MSGNO_S *msgmap; + int display; + int special; + { + int collapsed, rv = 1, done = 0; + PINETHRD_S *thrd = NULL, *nthrd; + unsigned long rawno, orig, msgno; + + if(!stream) + return 0; + + orig = mn_m2raw(msgmap, mn_get_cur(msgmap)); + move_top_this_thread(stream, msgmap,orig); + rawno = mn_m2raw(msgmap, mn_get_cur(msgmap)); + + if(rawno) + thrd = fetch_thread(stream, rawno); + + if(!thrd) + return rv; + + collapsed = this_thread_is_kolapsed(state, stream, msgmap, rawno); + + if (special && !collapsed){ + collapse_this_thread(state, stream, msgmap, 0, 0); + collapsed = 1; + } + + clear_index_cache_ent(mn_raw2m(msgmap,rawno)); + + if (collapsed && thrd->next){ + if (thrd->rawno == top_thread(stream, thrd->rawno)) + collapse_or_expand(state, stream, msgmap, mn_get_cur(msgmap), display); + else{ + set_lflag(stream, msgmap, mn_raw2m(msgmap,thrd->rawno), MN_COLL, 0); + set_thread_subtree(stream, thrd, msgmap, 0, MN_CHID); + } + } + else{ + if (collapsed && special + && ((F_OFF(F_ENHANCED_THREAD, state) && !thrd->next) + || F_ON(F_ENHANCED_THREAD, state))){ + if (thrd->toploose) + if (thrd->rawno != thrd->toploose) + set_lflag(stream, msgmap, mn_raw2m(msgmap,thrd->rawno),MN_CHID, 0); + else + set_lflag(stream, msgmap, mn_raw2m(msgmap,thrd->rawno),MN_COLL, 0); + } + else{ + rv = 0; + if (display) + q_status_message(SM_ORDER, 0, 1, "Thread already expanded"); + } + } + return rv; + } + + void + expand_thread(state, stream, msgmap, display) + struct pine *state; + MAILSTREAM *stream; + MSGNO_S *msgmap; + int display; + { + int collapsed, rv = 1, done = 0; + PINETHRD_S *thrd = NULL; + unsigned long orig, orig_top, top; + + if(!stream) + return; + + orig = mn_m2raw(msgmap, mn_get_cur(msgmap)); + top = orig_top = mn_m2raw(msgmap, mn_get_cur(msgmap)); + + if(top) + thrd = fetch_thread(stream, top); + + if(!thrd) + return; + + while (!done){ + expand_this_thread(state, stream, msgmap, display, 1); + if (F_OFF(F_ENHANCED_THREAD, state) + || (move_next_this_thread(state, stream, msgmap, 0) <= 0) + || !(top = mn_m2raw(msgmap, mn_get_cur(msgmap))) + || (orig_top != top_thread(stream, top))) + done++; + } + mn_set_cur(msgmap,mn_raw2m(msgmap, orig_top)); + } + + + void + cmd_undelete_this_thread(state, stream, msgmap) + struct pine *state; + MAILSTREAM *stream; + MSGNO_S *msgmap; + { + unsigned long rawno; + int save_kolapsed; + + rawno = mn_m2raw(msgmap, mn_get_cur(msgmap)); + save_kolapsed = this_thread_is_kolapsed(state, stream, msgmap, rawno); + collapse_this_thread(state, stream, msgmap, 0, 0); + thread_command(state, stream, msgmap, 'u', -FOOTER_ROWS(state), 1); + if (!save_kolapsed) + expand_this_thread(state, stream, msgmap, 0, 0); + } + + void + cmd_undelete_thread(state, stream, msgmap) + struct pine *state; + MAILSTREAM *stream; + MSGNO_S *msgmap; + { + PINETHRD_S *thrd = NULL; + unsigned long rawno, top, orig_top; + int done = 0, count; + + rawno = mn_m2raw(msgmap, mn_get_cur(msgmap)); + move_top_thread(stream, msgmap, rawno); + top = orig_top = mn_m2raw(msgmap, mn_get_cur(msgmap)); + if(top) + thrd = fetch_thread(stream, top); + + if(!thrd) + return; + + while (!done){ + cmd_undelete_this_thread(state, stream, msgmap); + if (F_OFF(F_ENHANCED_THREAD, state) + || (move_next_this_thread(state, stream, msgmap, 0) <= 0) + || !(top = mn_m2raw(msgmap, mn_get_cur(msgmap))) + || (orig_top != top_thread(stream, top))) + done++; + } + mn_set_cur(msgmap,mn_raw2m(msgmap, rawno)); + count = count_thread(state, stream, msgmap, rawno); + q_status_message2(SM_ORDER, 0, 1, "Deletion mark removed from %s message%s", + int2string(count), plural(count)); + } + + void + kolapse_thread(state, stream, msgmap, ch, display) + struct pine *state; + MAILSTREAM *stream; + MSGNO_S *msgmap; + char ch; + int display; + { + PINETHRD_S *thrd = NULL; + unsigned long rawno; + int rv = 1, done = 0; + + if(!stream) + return; + + rawno = mn_m2raw(msgmap, mn_get_cur(msgmap)); + if(rawno) + thrd = fetch_thread(stream, rawno); + + if(!thrd) + return; + + clear_index_cache(); + mn_set_cur(msgmap,1); /* go to the first message */ + while (!done){ + if (ch == '[') + collapse_thread(state, stream, msgmap, display); + else + expand_thread(state, stream, msgmap, display); + if ((rv = move_next_thread(state, stream, msgmap, 0)) <= 0) + done++; + } + + if (rv < 0){ + if (display) + q_status_message(SM_ORDER, 0, 1, (ch == '[') + ? "Error while collapsing thread" + : "Error while expanding thread"); + } + else + if(display) + q_status_message(SM_ORDER, 0, 1, (ch == '[') + ? "All threads collapsed. Use \"}\" to expand them" + : "All threads expanded. Use \"{\" to collapse them"); + + mn_set_cur(msgmap,mn_raw2m(msgmap, top_thread(stream,rawno))); + } + + int + move_next_this_thread(state, stream, msgmap, display) + struct pine *state; + MAILSTREAM *stream; + MSGNO_S *msgmap; + int display; + { + PINETHRD_S *thrd = NULL, *thrdnxt; + unsigned long rawno, top; + int rv = 1; + + if(!stream) + return -1; + + rawno = mn_m2raw(msgmap, mn_get_cur(msgmap)); + if(rawno) + thrd = fetch_thread(stream, rawno); + + if(!thrd) + return -1; + + top = top_thread(stream, rawno); + + thrdnxt = (top == rawno) ? fetch_thread(stream, top) : thrd; + if (thrdnxt->nextthd) + mn_set_cur(msgmap,mn_raw2m(msgmap, thrdnxt->nextthd)); + else{ + rv = 0; + if (display) + q_status_message(SM_ORDER, 0, 1, "No more Threads to advance"); + } + return rv; + } + + int + move_next_thread(state, stream, msgmap, display) + struct pine *state; + MAILSTREAM *stream; + MSGNO_S *msgmap; + int display; + { + int collapsed, rv = 1, done = 0; + PINETHRD_S *thrd = NULL; + unsigned long orig, orig_top, top; + + if(!stream) + return 0; + + orig = mn_m2raw(msgmap, mn_get_cur(msgmap)); + move_top_thread(stream, msgmap,orig); + top = orig_top = mn_m2raw(msgmap, mn_get_cur(msgmap)); + + if(top) + thrd = fetch_thread(stream, top); + + if(!thrd) + return 0; + + while (rv > 0 && !done){ + rv = move_next_this_thread(state, stream, msgmap, display); + if (F_OFF(F_ENHANCED_THREAD, state) + || !(top = mn_m2raw(msgmap, mn_get_cur(msgmap))) + || (orig_top != top_thread(stream, top))) + done++; + } + if (display){ + if (rv > 0 && SEP_THRDINDX()) + q_status_message(SM_ORDER, 0, 2, "Viewing next thread"); + if (!rv) + q_status_message(SM_ORDER, 0, 2, "No more threads to advance"); + } + if(rv <= 0){ + rv = 0; + mn_set_cur(msgmap, mn_raw2m(msgmap, orig)); + } + + return rv; + } + + int + move_prev_thread(state, stream, msgmap, display) + struct pine *state; + MAILSTREAM *stream; + MSGNO_S *msgmap; + int display; + { + PINETHRD_S *thrd = NULL; + unsigned long rawno, top; + int rv = 1; + + if(!stream) + return -1; + + rawno = mn_m2raw(msgmap, mn_get_cur(msgmap)); + if(rawno) + thrd = fetch_thread(stream, rawno); + + if(!thrd) + return -1; + + top = top_thread(stream, rawno); + + if (top != rawno) + mn_set_cur(msgmap,mn_raw2m(msgmap, top)); + else if (thrd->prevthd) + mn_set_cur(msgmap,mn_raw2m(msgmap, top_thread(stream,thrd->prevthd))); + else + rv = 0; + if (display){ + if (rv && SEP_THRDINDX()) + q_status_message(SM_ORDER, 0, 2, "Viewing previous thread"); + if (!rv) + q_status_message(SM_ORDER, 0, 2, "No more threads to go back"); + } + + return rv; + } + + void + cmd_select_thread(state, stream, msgmap) + struct pine *state; + MAILSTREAM *stream; + MSGNO_S *msgmap; + { + unsigned long rawno; + int save_kolapsed; + + rawno = mn_m2raw(msgmap, mn_get_cur(msgmap)); + save_kolapsed = thread_is_kolapsed(state, stream, msgmap, rawno); + collapse_thread(state, stream, msgmap, 0); + thread_command(state, stream, msgmap, ':', -FOOTER_ROWS(state), 1); + if (!save_kolapsed) + expand_thread(state, stream, msgmap, 0); + } + + /* + * This function assumes that it is called at a top of a thread in its + * first call + */ + + int + count_this_thread(stream, rawno) + MAILSTREAM *stream; + unsigned long rawno; + { + unsigned long top, orig_top, topnxt; + PINETHRD_S *thrd = NULL; + int count = 1; + + if(!stream) + return 0; + + if(rawno) + thrd = fetch_thread(stream, rawno); + + if(!thrd) + return 0; + + if (thrd->next) + count += count_this_thread(stream, thrd->next); + + if (thrd->branch) + count += count_this_thread(stream, thrd->branch); + + return count; + } + + int + count_thread(state, stream, msgmap, rawno) + struct pine *state; + MAILSTREAM *stream; + MSGNO_S *msgmap; + long rawno; + { + unsigned long top, orig, orig_top; + PINETHRD_S *thrd = NULL; + int done = 0, count = 0; + + if(!stream) + return 0; + + orig = mn_m2raw(msgmap, mn_get_cur(msgmap)); + move_top_thread(stream, msgmap,rawno); + top = orig_top = top_thread(stream, rawno); + if(top) + thrd = fetch_thread(stream, top); + + if(!thrd) + return 0; + + while (!done){ + count += count_this_thread(stream, top); + if (F_OFF(F_ENHANCED_THREAD, state) + || (move_next_this_thread(state, stream, msgmap, 0) <= 0) + || !(top = mn_m2raw(msgmap, mn_get_cur(msgmap))) + || (orig_top != top_thread(stream, top))) + done++; + } + mn_set_cur(msgmap,mn_raw2m(msgmap, orig)); + return count; + } diff -rc pine4.61/pine/mailindx.c pine4.61.fancy/pine/mailindx.c *** pine4.61/pine/mailindx.c Mon Jun 14 14:59:15 2004 --- pine4.61.fancy/pine/mailindx.c Thu Aug 19 13:34:57 2004 *************** *** 112,119 **** RCOMPOSE_MENU, HOMEKEY_MENU, ENDKEY_MENU, ! NULL_MENU, {"/","Collapse/Expand",{MC_COLLAPSE,1,{'/'}},KS_NONE}, NULL_MENU, NULL_MENU}; INST_KEY_MENU(index_keymenu, index_keys); --- 112,132 ---- RCOMPOSE_MENU, HOMEKEY_MENU, ENDKEY_MENU, ! {"K","Sort Thread",{MC_SORTHREAD,1,{'k'}},KS_NONE}, {"/","Collapse/Expand",{MC_COLLAPSE,1,{'/'}},KS_NONE}, + {"{","Collapse All",{MC_KOLAPSE,1,{'{'}},KS_NONE}, + {"}","Expand All", {MC_EXPTHREAD,1,{'}'}},KS_NONE}, + + HELP_MENU, + OTHER_MENU, + {")","Next Threa",{MC_NEXTHREAD,1,{')'}},KS_NONE}, + {"(","Prev Threa",{MC_PRETHREAD,1,{'('}},KS_NONE}, + {"^D","Delete Thr",{MC_DELTHREAD,1,{ctrl('D')}},KS_NONE}, + {"^U","Undel Thre",{MC_UNDTHREAD,1,{ctrl('U')}},KS_NONE}, + {"^T","Select Thr",{MC_SELTHREAD,1,{ctrl('T')}},KS_NONE}, + NULL_MENU, + {"[","Close Thre",{MC_CTHREAD,1,{'['}},KS_NONE}, + {"]","Open Threa",{MC_OTHREAD,1,{']'}},KS_NONE}, NULL_MENU, NULL_MENU}; INST_KEY_MENU(index_keymenu, index_keys); *************** *** 197,205 **** RCOMPOSE_MENU, HOMEKEY_MENU, ENDKEY_MENU, ! NULL_MENU, {"/","Collapse/Expand",{MC_COLLAPSE,1,{'/'}},KS_NONE}, NULL_MENU, NULL_MENU}; INST_KEY_MENU(thread_keymenu, thread_keys); --- 210,231 ---- RCOMPOSE_MENU, HOMEKEY_MENU, ENDKEY_MENU, ! {"]","Open Threa",{MC_OTHREAD,1,{']'}},KS_NONE}, {"/","Collapse/Expand",{MC_COLLAPSE,1,{'/'}},KS_NONE}, + {")","Next Threa",{MC_NEXTHREAD,1,{')'}},KS_NONE}, + {"(","Prev Threa",{MC_PRETHREAD,1,{'('}},KS_NONE}, + + HELP_MENU, + OTHER_MENU, + NULL_MENU, NULL_MENU, + {"^D","Delete Thr",{MC_DELTHREAD,1,{ctrl('D')}},KS_NONE}, + {"^U","Undel Thre",{MC_UNDTHREAD,1,{ctrl('U')}},KS_NONE}, + {"^T","Select Thr",{MC_SELTHREAD,1,{ctrl('T')}},KS_NONE}, + NULL_MENU, + NULL_MENU, + NULL_MENU, + {"K","Sort Thread",{MC_SORTHREAD,1,{'k'}},KS_NONE}, NULL_MENU}; INST_KEY_MENU(thread_keymenu, thread_keys); *************** *** 318,324 **** HLINE_S *(*format_index_line) PROTO((INDEXDATA_S *)); void (*setup_header_widths) PROTO((void)); ! /* --- 344,350 ---- HLINE_S *(*format_index_line) PROTO((INDEXDATA_S *)); void (*setup_header_widths) PROTO((void)); ! static int erase_thread_info = 1; /* *************** *** 349,354 **** --- 375,388 ---- void index_data_env PROTO((INDEXDATA_S *, ENVELOPE *)); int set_index_addr PROTO((INDEXDATA_S *, char *, ADDRESS *, char *, int, char *)); + unsigned long get_next PROTO((MAILSTREAM *,PINETHRD_S *)); + unsigned long get_branch PROTO((MAILSTREAM *,PINETHRD_S *)); + long get_length_branch PROTO((MAILSTREAM *, long)); + THREADNODE *copy_tree PROTO((THREADNODE *)); + void find_msgmap PROTO((MAILSTREAM *, MSGNO_S *, int, SortOrder, + unsigned)); + void move_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int)); + void relink_threads PROTO((MAILSTREAM *, MSGNO_S *, long *)); int i_cache_size PROTO((long)); int i_cache_width PROTO(()); int ctype_is_fixed_length PROTO((IndexColType)); *************** *** 390,406 **** struct pass_along *sort_thread_flatten PROTO((THREADNODE *, MAILSTREAM *, struct pass_along *, ! PINETHRD_S *, unsigned)); void make_thrdflags_consistent PROTO((MAILSTREAM *, MSGNO_S *, PINETHRD_S *, int)); THREADNODE *collapse_threadnode_tree PROTO((THREADNODE *)); PINETHRD_S *msgno_thread_info PROTO((MAILSTREAM *, unsigned long, PINETHRD_S *, unsigned)); long calculate_visible_threads PROTO((MAILSTREAM *)); void set_thread_subtree PROTO((MAILSTREAM *, PINETHRD_S *, MSGNO_S *, int, int)); void thread_command PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, ! int, int)); void set_flags_for_thread PROTO((MAILSTREAM *, MSGNO_S *, int, PINETHRD_S *, int)); unsigned long count_flags_in_thread PROTO((MAILSTREAM *, PINETHRD_S *, long)); --- 424,442 ---- struct pass_along *sort_thread_flatten PROTO((THREADNODE *, MAILSTREAM *, struct pass_along *, ! PINETHRD_S *, unsigned, int, ! long,long)); void make_thrdflags_consistent PROTO((MAILSTREAM *, MSGNO_S *, PINETHRD_S *, int)); THREADNODE *collapse_threadnode_tree PROTO((THREADNODE *)); + THREADNODE *copy_tree PROTO((THREADNODE *)); PINETHRD_S *msgno_thread_info PROTO((MAILSTREAM *, unsigned long, PINETHRD_S *, unsigned)); long calculate_visible_threads PROTO((MAILSTREAM *)); void set_thread_subtree PROTO((MAILSTREAM *, PINETHRD_S *, MSGNO_S *, int, int)); void thread_command PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, ! int, int, int)); void set_flags_for_thread PROTO((MAILSTREAM *, MSGNO_S *, int, PINETHRD_S *, int)); unsigned long count_flags_in_thread PROTO((MAILSTREAM *, PINETHRD_S *, long)); *************** *** 961,966 **** --- 997,1003 ---- /*---------- Scroll line up ----------*/ case MC_CHARUP : + previtem: (void) process_cmd(state, stream, msgmap, MC_PREVITEM, (style == MsgIndex || style == MultiMsgIndex *************** *** 978,983 **** --- 1015,1021 ---- /*---------- Scroll line down ----------*/ case MC_CHARDOWN : + nextitem: /* * Special Page framing handling here. If we * did something that should scroll-by-a-line, frame *************** *** 1194,1199 **** --- 1232,1238 ---- case MC_THRDINDX : + mc_thrdindx: msgmap->top = msgmap->top_after_thrd; if(unview_thread(state, stream, msgmap)){ ps_global->redrawer = NULL; *************** *** 1243,1249 **** && mp.col == id.plus_col && style != ThreadIndex){ collapse_or_expand(state, stream, msgmap, ! mn_get_cur(msgmap)); } else if (mp.doubleclick){ if(mp.button == M_BUTTON_LEFT){ --- 1282,1288 ---- && mp.col == id.plus_col && style != ThreadIndex){ collapse_or_expand(state, stream, msgmap, ! mn_get_cur(msgmap), 1); } else if (mp.doubleclick){ if(mp.button == M_BUTTON_LEFT){ *************** *** 1337,1345 **** case MC_COLLAPSE : ! thread_command(state, stream, msgmap, ch, -FOOTER_ROWS(state)); break; case MC_DELETE : case MC_UNDELETE : case MC_REPLY : --- 1376,1481 ---- case MC_COLLAPSE : ! thread_command(state, stream, msgmap, ch, -FOOTER_ROWS(state), 1); break; + case MC_CTHREAD : + if (SEP_THRDINDX()) + goto mc_thrdindx; + else + if (THREADING()){ + if (any_messages(ps_global->msgmap, NULL, + "to collapse a thread")) + collapse_thread(state, stream,msgmap, 1); + } + else + q_status_message(SM_ORDER, 0, 1, + "Command available in threaded mode only"); + break; + + case MC_OTHREAD : + if (SEP_THRDINDX()) + goto view_a_thread; + else + if (THREADING()){ + if (any_messages(ps_global->msgmap, NULL, "to expand a thread")) + expand_thread(state, stream,msgmap, 1); + } + else + q_status_message(SM_ORDER, 0, 1, + "Command available in threaded mode only"); + break; + + case MC_NEXTHREAD: + case MC_PRETHREAD: + if (THRD_INDX()){ + if (cmd == MC_NEXTHREAD) + goto nextitem; + else + goto previtem; + } + else + if (THREADING()){ + if (any_messages(ps_global->msgmap, NULL, + "to move to other thread")) + move_thread(state, stream, msgmap, + cmd == MC_NEXTHREAD ? 1 : -1); + } + else + q_status_message(SM_ORDER, 0, 1, + "Command available in threaded mode only"); + break; + + case MC_KOLAPSE: + case MC_EXPTHREAD: + if (SEP_THRDINDX()){ + q_status_message(SM_ORDER, 0, 1, + "Command not available in this screen"); + } + else{ + if (THREADING()){ + if (any_messages(ps_global->msgmap, NULL, + cmd == MC_KOLAPSE ? "to collapse" : "to expand")) + kolapse_thread(state, stream, msgmap, + (cmd == MC_KOLAPSE) ? '[' : ']', 1); + } + else + q_status_message(SM_ORDER, 0, 1, + "Command available in threaded mode only"); + } + break; + + case MC_DELTHREAD: + if (THREADING()){ + if (any_messages(ps_global->msgmap, NULL, "to delete")) + cmd_delete_thread(state, stream, msgmap); + } + else + q_status_message(SM_ORDER, 0, 1, + "Command available in threaded mode only"); + break; + + case MC_UNDTHREAD: + if (THREADING()){ + if (any_messages(ps_global->msgmap, NULL, "to undelete")) + cmd_undelete_thread(state, stream, msgmap); + } + else + q_status_message(SM_ORDER, 0, 1, + "Command available in threaded mode only"); + break; + + + case MC_SELTHREAD: + if (THREADING()){ + if (any_messages(ps_global->msgmap, NULL, "to undelete")) + cmd_select_thread(state, stream, msgmap); + } + else + q_status_message(SM_ORDER, 0, 1, + "Command available in threaded mode only"); + break; + case MC_DELETE : case MC_UNDELETE : case MC_REPLY : *************** *** 1360,1372 **** if(rawno) thrd = fetch_thread(stream, rawno); ! collapsed = thrd && thrd->next ! && get_lflag(stream, NULL, rawno, MN_COLL); } if(collapsed){ thread_command(state, stream, msgmap, ! ch, -FOOTER_ROWS(state)); /* increment current */ if(cmd == MC_DELETE){ advance_cur_after_delete(state, stream, msgmap, --- 1496,1507 ---- if(rawno) thrd = fetch_thread(stream, rawno); ! collapsed = thread_is_kolapsed(ps_global, stream, msgmap, rawno); } if(collapsed){ thread_command(state, stream, msgmap, ! ch, -FOOTER_ROWS(state),1); /* increment current */ if(cmd == MC_DELETE){ advance_cur_after_delete(state, stream, msgmap, *************** *** 2661,2666 **** --- 2796,2802 ---- n = mn_raw2m(msgs, thrd->rawno); while(thrd){ + unsigned long branch; if(!msgline_hidden(stream, msgs, n, 0) && (++m % lines_per_page) == 1L) t = n; *************** *** 2729,2739 **** /* n is the end of this thread */ while(thrd){ n = mn_raw2m(msgs, thrd->rawno); ! if(thrd->branch) ! thrd = fetch_thread(stream, thrd->branch); ! else if(thrd->next) ! thrd = fetch_thread(stream, thrd->next); else thrd = NULL; } --- 2865,2876 ---- /* n is the end of this thread */ while(thrd){ + unsigned long next = 0L, branch = 0L; n = mn_raw2m(msgs, thrd->rawno); ! if(branch = get_branch(stream,thrd)) ! thrd = fetch_thread(stream, branch); ! else if(next = get_next(stream,thrd)) ! thrd = fetch_thread(stream, next); else thrd = NULL; } *************** *** 2886,2891 **** --- 3023,3029 ---- case iSTime: case iKSize: case iSize: + case iSizeThread: (*answer)[column].req_width = 7; break; case iS1Date: *************** *** 2927,2932 **** --- 3065,3071 ---- {"FROMORTONOTNEWS", iFromToNotNews, FOR_INDEX}, {"SIZE", iSize, FOR_INDEX}, {"SIZECOMMA", iSizeComma, FOR_INDEX}, + {"SIZETHREAD", iSizeThread, FOR_INDEX}, {"SIZENARROW", iSizeNarrow, FOR_INDEX}, {"KSIZE", iKSize, FOR_INDEX}, {"SUBJECT", iSubject, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE}, *************** *** 3149,3155 **** */ static IndexColType fixed_ctypes[] = { iMessNo, iStatus, iFStatus, iIStatus, iDate, iSDate, iSDateTime, ! iSTime, iLDate, iS1Date, iS2Date, iS3Date, iS4Date, iDateIso, iDateIsoS, iSize, iSizeComma, iSizeNarrow, iKSize, iDescripSize, iAtt, iTime24, iTime12, iTimezone, iMonAbb, iYear, iYear2Digit, --- 3288,3294 ---- */ static IndexColType fixed_ctypes[] = { iMessNo, iStatus, iFStatus, iIStatus, iDate, iSDate, iSDateTime, ! iSTime, iLDate, iSizeThread, iS1Date, iS2Date, iS3Date, iS4Date, iDateIso, iDateIsoS, iSize, iSizeComma, iSizeNarrow, iKSize, iDescripSize, iAtt, iTime24, iTime12, iTimezone, iMonAbb, iYear, iYear2Digit, *************** *** 3312,3317 **** --- 3451,3457 ---- case iTime12: case iSize: case iKSize: + case iSizeThread: cdesc->actual_length = 7; cdesc->adjustment = Right; break; *************** *** 3373,3379 **** cdesc->ctype != iNothing; cdesc++) if(cdesc->ctype == iSize || cdesc->ctype == iKSize || ! cdesc->ctype == iSizeNarrow || cdesc->ctype == iSizeComma || cdesc->ctype == iDescripSize){ if(cdesc->actual_length == 0){ if((fix=cdesc->width) > 0){ /* had this reserved */ --- 3513,3519 ---- cdesc->ctype != iNothing; cdesc++) if(cdesc->ctype == iSize || cdesc->ctype == iKSize || ! cdesc->ctype == iSizeNarrow || cdesc->ctype == iSizeThread || cdesc->ctype == iSizeComma || cdesc->ctype == iDescripSize){ if(cdesc->actual_length == 0){ if((fix=cdesc->width) > 0){ /* had this reserved */ *************** *** 3766,3775 **** /* find next thread which is visible */ do{ if(mn_get_revsort(msgmap) && thrd->prevthd) thrd = fetch_thread(stream, thrd->prevthd); ! else if(!mn_get_revsort(msgmap) && thrd->nextthd) ! thrd = fetch_thread(stream, thrd->nextthd); else thrd = NULL; } while(thrd --- 3906,3916 ---- /* find next thread which is visible */ do{ + unsigned long branch; if(mn_get_revsort(msgmap) && thrd->prevthd) thrd = fetch_thread(stream, thrd->prevthd); ! else if(!mn_get_revsort(msgmap) && thrd->branch) ! thrd = fetch_thread(stream, thrd->branch); else thrd = NULL; } while(thrd *************** *** 4221,4231 **** hline = get_index_cache(idata->msgno); /* is this a collapsed thread index line? */ if(!idata->bogus && THREADING()){ ! thrd = fetch_thread(idata->stream, idata->rawno); ! collapsed = thrd && thrd->next ! && get_lflag(idata->stream, NULL, ! idata->rawno, MN_COLL); } /* calculate contents of the required fields */ --- 4362,4370 ---- hline = get_index_cache(idata->msgno); /* is this a collapsed thread index line? */ + thrd = fetch_thread(idata->stream, idata->rawno); if(!idata->bogus && THREADING()){ ! collapsed = thrd && thread_is_kolapsed(ps_global, idata->stream, ps_global->msgmap, idata->rawno); } /* calculate contents of the required fields */ *************** *** 4583,4589 **** --- 4722,4752 ---- break; + case iSizeThread: + if (!THREADING()){ + goto getsize; + } else if (collapsed){ + l = count_flags_in_thread(idata->stream, thrd, F_NONE); + sprintf(str, "(%lu)", l); + } + else{ + thrd = fetch_thread(idata->stream, idata->rawno); + if(!thrd) + sprintf(str,"Error"); + else{ + long lengthb; + lengthb = get_length_branch(idata->stream, idata->rawno); + + if (lengthb > 0L) + sprintf(str,"(%lu)", lengthb); + else + sprintf(str," "); + } + } + break; + case iSize: + getsize: /* 0 ... 9999 */ if((l = fetch_size(idata)) < 10*1000L) sprintf(str, "(%lu)", l); *************** *** 6575,6582 **** thdorig = thd = fetch_thread(idata->stream, idata->rawno); border = str + width; if(current_index_state->plus_col >= 0 && !THRD_INDX()){ ! collapsed = thd && thd->next && ! get_lflag(idata->stream, NULL, idata->rawno, MN_COLL); hline = get_index_cache(idata->msgno); hline->plus = collapsed ? ps_global->VAR_THREAD_MORE_CHAR[0] : (thd && thd->next) --- 6738,6745 ---- thdorig = thd = fetch_thread(idata->stream, idata->rawno); border = str + width; if(current_index_state->plus_col >= 0 && !THRD_INDX()){ ! collapsed = this_thread_is_kolapsed(ps_global, idata->stream, ps_global->msgmap, idata->rawno); ! collapsed = collapsed && (count_thread(ps_global,idata->stream, ps_global->msgmap, idata->rawno) != 1); hline = get_index_cache(idata->msgno); hline->plus = collapsed ? ps_global->VAR_THREAD_MORE_CHAR[0] : (thd && thd->next) *************** *** 6898,6905 **** thdorig = thd = fetch_thread(idata->stream, idata->rawno); border = str + width; if(current_index_state->plus_col >= 0 && !THRD_INDX()){ ! collapsed = thd && thd->next && ! get_lflag(idata->stream, NULL, idata->rawno, MN_COLL); hline = get_index_cache(idata->msgno); hline->plus = collapsed ? ps_global->VAR_THREAD_MORE_CHAR[0] : (thd && thd->next) --- 7061,7068 ---- thdorig = thd = fetch_thread(idata->stream, idata->rawno); border = str + width; if(current_index_state->plus_col >= 0 && !THRD_INDX()){ ! collapsed = this_thread_is_kolapsed(ps_global, idata->stream, ps_global->msgmap, idata->rawno); ! collapsed = collapsed && (count_thread (ps_global,idata->stream, ps_global->msgmap, idata->rawno) != 1); hline = get_index_cache(idata->msgno); hline->plus = collapsed ? ps_global->VAR_THREAD_MORE_CHAR[0] : (thd && thd->next) *************** *** 7424,7435 **** causes the sort to happen if it is still needed. ----*/ void ! sort_folder(stream, msgmap, new_sort, new_rev, flags) MAILSTREAM *stream; MSGNO_S *msgmap; SortOrder new_sort; int new_rev; unsigned flags; { long raw_current, i, j; unsigned long *sort = NULL; --- 7587,7599 ---- causes the sort to happen if it is still needed. ----*/ void ! sort_folder(stream, msgmap, new_sort, new_rev, flags, first) MAILSTREAM *stream; MSGNO_S *msgmap; SortOrder new_sort; int new_rev; unsigned flags; + int first; { long raw_current, i, j; unsigned long *sort = NULL; *************** *** 7439,7444 **** --- 7603,7617 ---- int current_rev; MESSAGECACHE *mc; + if (first){ + if (new_sort == SortThread) + find_msgmap(stream, msgmap, flags, + ps_global->thread_cur_sort, new_rev); + else + sort_folder(stream, msgmap, new_sort, new_rev, flags, 0); + return; + } + dprint(2, (debugfile, "Sorting by %s%s\n", sort_name(new_sort), new_rev ? "/reverse" : "")); *************** *** 7801,7806 **** --- 7974,7980 ---- thrd = fetch_head_thread(stream); for(j = msgmap->max_thrdno; thrd && j >= 1L; j--){ + unsigned long branch; thrd->thrdno = j; if(thrd->nextthd) *************** *** 7867,7873 **** MESSAGECACHE *mc; PINELT_S *peltp; ! if(!(stream && stream->spare)) return; ps_global->view_skipped_index = 0; --- 8041,8047 ---- MESSAGECACHE *mc; PINELT_S *peltp; ! if(!(stream && stream->spare) || !erase_thread_info) return; ps_global->view_skipped_index = 0; *************** *** 7929,7935 **** unsigned long msgno, rawno, set_in_thread, in_thread; int bail, this_is_vis; int un_view_thread = 0; ! long raw_current; dprint(2, (debugfile, "sort_thread_callback\n")); --- 8103,8109 ---- unsigned long msgno, rawno, set_in_thread, in_thread; int bail, this_is_vis; int un_view_thread = 0; ! long raw_current, branch; dprint(2, (debugfile, "sort_thread_callback\n")); *************** *** 7948,7956 **** * way. If the dummy node is at the top-level, then its children are * promoted to the top-level as separate threads. */ ! collapsed_tree = collapse_threadnode_tree(tree); ! (void) sort_thread_flatten(collapsed_tree, stream, thrd_flatten_array, ! NULL, THD_TOP); mail_free_threadnode(&collapsed_tree); if(any_lflagged(g_sort.msgmap, MN_HIDE)) --- 8122,8132 ---- * way. If the dummy node is at the top-level, then its children are * promoted to the top-level as separate threads. */ ! collapsed_tree = F_ON(F_ENHANCED_THREAD, ps_global) ? ! copy_tree(tree) : collapse_threadnode_tree(tree); ! (void) sort_thread_flatten(collapsed_tree, ! stream, thrd_flatten_array, ! NULL, THD_TOP, 0, 1L, 0L); mail_free_threadnode(&collapsed_tree); if(any_lflagged(g_sort.msgmap, MN_HIDE)) *************** *** 8115,8126 **** else{ thrd = fetch_head_thread(stream); while(thrd){ /* * The top-level threads aren't hidden by collapse. */ msgno = mn_raw2m(g_sort.msgmap, thrd->rawno); ! if(msgno) ! set_lflag(stream, g_sort.msgmap, msgno, MN_CHID, 0); if(thrd->next){ PINETHRD_S *nthrd; --- 8291,8304 ---- else{ thrd = fetch_head_thread(stream); while(thrd){ + unsigned long raw = thrd->rawno; + unsigned long top = top_thread(stream, raw); /* * The top-level threads aren't hidden by collapse. */ msgno = mn_raw2m(g_sort.msgmap, thrd->rawno); ! if(msgno && !get_lflag(stream, NULL,thrd->rawno, MN_COLL)) ! set_lflag(stream, g_sort.msgmap, msgno, MN_CHID, 0); if(thrd->next){ PINETHRD_S *nthrd; *************** *** 8134,8142 **** MN_COLL)); } ! if(thrd->nextthd) thrd = fetch_thread(stream, thrd->nextthd); ! else thrd = NULL; } } --- 8312,8321 ---- MN_COLL)); } ! while (thrd && top_thread(stream, thrd->rawno) == top ! && thrd->nextthd) thrd = fetch_thread(stream, thrd->nextthd); ! if (!(thrd && thrd->nextthd)) thrd = NULL; } } *************** *** 8157,8166 **** PINETHRD_S *not_this_thread; { PINETHRD_S *thrd = NULL, *nthrd; ! unsigned long msgno; dprint(9, (debugfile, "collapse_threads\n")); thrd = fetch_head_thread(stream); while(thrd){ if(thrd != not_this_thread){ --- 8336,8352 ---- PINETHRD_S *not_this_thread; { PINETHRD_S *thrd = NULL, *nthrd; ! unsigned long msgno, branch; dprint(9, (debugfile, "collapse_threads\n")); + /* if(F_ON(F_ENHANCED_THREAD, ps_global)){*/ + kolapse_thread(ps_global, stream, msgmap, '[', 0); + if (not_this_thread) + expand_thread(ps_global, stream, msgmap, 0); + return; + /* }*/ + thrd = fetch_head_thread(stream); while(thrd){ if(thrd != not_this_thread){ *************** *** 8195,8201 **** int a_parent_is_collapsed; { PINETHRD_S *nthrd, *bthrd; ! unsigned long msgno; if(!thrd) return; --- 8381,8387 ---- int a_parent_is_collapsed; { PINETHRD_S *nthrd, *bthrd; ! unsigned long msgno, next, branch; if(!thrd) return; *************** *** 8213,8220 **** set_lflag(stream, msgmap, msgno, MN_CHID, 0); } ! if(thrd->next){ ! nthrd = fetch_thread(stream, thrd->next); if(nthrd) make_thrdflags_consistent(stream, msgmap, nthrd, a_parent_is_collapsed --- 8399,8406 ---- set_lflag(stream, msgmap, msgno, MN_CHID, 0); } ! if(next = get_next(stream, thrd)){ ! nthrd = fetch_thread(stream, next); if(nthrd) make_thrdflags_consistent(stream, msgmap, nthrd, a_parent_is_collapsed *************** *** 8223,8230 **** MN_COLL)); } ! if(thrd->branch){ ! bthrd = fetch_thread(stream, thrd->branch); if(bthrd) make_thrdflags_consistent(stream, msgmap, bthrd, a_parent_is_collapsed); --- 8409,8416 ---- MN_COLL)); } ! if(branch = get_branch(stream, thrd)){ ! bthrd = fetch_thread(stream, branch); if(bthrd) make_thrdflags_consistent(stream, msgmap, bthrd, a_parent_is_collapsed); *************** *** 8237,8243 **** MAILSTREAM *stream; { PINETHRD_S *thrd = NULL; ! long vis = 0L; thrd = fetch_head_thread(stream); while(thrd){ --- 8423,8429 ---- MAILSTREAM *stream; { PINETHRD_S *thrd = NULL; ! long vis = 0L, branch; thrd = fetch_head_thread(stream); while(thrd){ *************** *** 8254,8300 **** struct pass_along * ! sort_thread_flatten(node, stream, entry, thrd, flags) THREADNODE *node; MAILSTREAM *stream; struct pass_along *entry; PINETHRD_S *thrd; unsigned flags; { long n = 0L; ! PINETHRD_S *newthrd = NULL; if(node){ ! if(node->num){ /* holes happen */ n = (long) (entry - thrd_flatten_array); for(; n > 0; n--) if(thrd_flatten_array[n].rawno == node->num) break; /* duplicate */ ! if(!n) ! entry->rawno = node->num; ! } ! ! /* ! * Build a richer threading structure that will help us paint ! * and operate on threads and subthreads. ! */ ! if(!n && node->num){ ! newthrd = msgno_thread_info(stream, node->num, thrd, flags); ! if(newthrd){ ! entry->thrd = newthrd; ! entry++; ! ! if(node->next) entry = sort_thread_flatten(node->next, stream, entry, ! newthrd, THD_NEXT); ! if(node->branch) entry = sort_thread_flatten(node->branch, stream, entry, ! newthrd, ! (flags == THD_TOP) ? THD_TOP ! : THD_BRANCH); } } } --- 8440,8525 ---- struct pass_along * ! sort_thread_flatten(node, stream, entry, thrd, flags, adopted, top, threadno) THREADNODE *node; MAILSTREAM *stream; struct pass_along *entry; PINETHRD_S *thrd; unsigned flags; + int adopted; + long top; + long threadno; { long n = 0L; ! PINETHRD_S *newthrd = NULL, *save_thread = NULL; if(node){ ! if(node->num){ n = (long) (entry - thrd_flatten_array); + if (adopted == 2) + top = node->num; + for(; n > 0; n--) if(thrd_flatten_array[n].rawno == node->num) break; /* duplicate */ ! if(!n){ ! entry->rawno = node->num; ! newthrd = msgno_thread_info(stream, node->num, thrd, flags); ! if(newthrd){ ! if (adopted == 2) ! threadno = newthrd->thrdno; ! if (adopted){ ! newthrd->toploose = top; ! newthrd->thrdno = threadno; ! } ! entry->thrd = newthrd; ! entry++; ! } ! adopted = adopted ? 1 : 0; ! if (node->next) entry = sort_thread_flatten(node->next, stream, entry, ! newthrd, THD_NEXT, adopted, top, ! threadno); if(node->branch) entry = sort_thread_flatten(node->branch, stream, entry, ! newthrd, ! (flags == THD_TOP) ? THD_TOP: THD_BRANCH, ! adopted, top, threadno); ! } ! } ! else{ ! adopted = 2; ! if(node->next) ! entry = sort_thread_flatten(node->next, stream, entry, ! thrd, THD_TOP, adopted, top, threadno); ! adopted = 0; ! if(node->branch){ ! if(entry){ ! struct pass_along *last_entry = entry; ! int i = 0; ! ! /* ! * Next moved up to replace "tree" in the tree. ! * If next has no branches, then we want to branch off ! * of next. If next has branches, we want to branch off ! * of the last of those branches instead. ! */ ! last_entry--; ! while(last_entry->thrd->parent) ! last_entry--; ! save_thread = last_entry->thrd; ! last_entry += i+1; ! ! last_entry = sort_thread_flatten(node->branch, stream, entry, ! save_thread, ! (flags == THD_TOP) ? THD_TOP: THD_BRANCH, ! adopted, top, threadno); ! } ! else ! entry = sort_thread_flatten(node->branch, stream, entry, ! NULL, THD_TOP, adopted, top, threadno); } } } *************** *** 8302,8307 **** --- 8527,8552 ---- return(entry); } + /* + * Make a copy of c-client's THREAD tree + */ + THREADNODE * + copy_tree(tree) + THREADNODE *tree; + { + THREADNODE *newtree = NULL; + + if(tree){ + newtree = mail_newthreadnode(NULL); + newtree->num = tree->num; + if(tree->next) + newtree->next = copy_tree(tree->next); + + if(tree->branch) + newtree->branch = copy_tree(tree->branch); + } + return(newtree); + } /* * Make a copy of c-client's THREAD tree while eliminating dummy nodes. *************** *** 10037,10048 **** void ! thread_command(state, stream, msgmap, preloadkeystroke, q_line) struct pine *state; MAILSTREAM *stream; MSGNO_S *msgmap; int preloadkeystroke; int q_line; { PINETHRD_S *thrd = NULL; unsigned long rawno, save_branch; --- 10282,10294 ---- void ! thread_command(state, stream, msgmap, preloadkeystroke, q_line, display) struct pine *state; MAILSTREAM *stream; MSGNO_S *msgmap; int preloadkeystroke; int q_line; + int display; { PINETHRD_S *thrd = NULL; unsigned long rawno, save_branch; *************** *** 10091,10097 **** cancel_busy_alarm(0); (void ) apply_command(state, stream, msgmap, preloadkeystroke, flags, ! q_line); /* restore the original flags */ copy_lflags(stream, msgmap, MN_STMP, MN_SLCT); --- 10337,10343 ---- cancel_busy_alarm(0); (void ) apply_command(state, stream, msgmap, preloadkeystroke, flags, ! q_line, display); /* restore the original flags */ copy_lflags(stream, msgmap, MN_STMP, MN_SLCT); *************** *** 10129,10148 **** int v; { PINETHRD_S *nthrd, *bthrd; if(!(stream && thrd && msgmap)) return; set_lflag(stream, msgmap, mn_raw2m(msgmap, thrd->rawno), f, v); ! if(thrd->next){ ! nthrd = fetch_thread(stream, thrd->next); if(nthrd) set_flags_for_thread(stream, msgmap, f, nthrd, v); } ! if(thrd->branch){ ! bthrd = fetch_thread(stream, thrd->branch); if(bthrd) set_flags_for_thread(stream, msgmap, f, bthrd, v); } --- 10375,10395 ---- int v; { PINETHRD_S *nthrd, *bthrd; + unsigned long next = 0L, branch = 0L; if(!(stream && thrd && msgmap)) return; set_lflag(stream, msgmap, mn_raw2m(msgmap, thrd->rawno), f, v); ! if(next = get_next(stream,thrd)){ ! nthrd = fetch_thread(stream, next); if(nthrd) set_flags_for_thread(stream, msgmap, f, nthrd, v); } ! if(branch = get_branch(stream, thrd)){ ! bthrd = fetch_thread(stream, branch); if(bthrd) set_flags_for_thread(stream, msgmap, f, bthrd, v); } *************** *** 10197,10207 **** * index. */ void ! collapse_or_expand(state, stream, msgmap, msgno) struct pine *state; MAILSTREAM *stream; MSGNO_S *msgmap; unsigned long msgno; { int collapsed, adjust_current = 0; PINETHRD_S *thrd = NULL, *nthrd; --- 10444,10455 ---- * index. */ void ! collapse_or_expand(state, stream, msgmap, msgno, display) struct pine *state; MAILSTREAM *stream; MSGNO_S *msgmap; unsigned long msgno; + int display; { int collapsed, adjust_current = 0; PINETHRD_S *thrd = NULL, *nthrd; *************** *** 10237,10243 **** if(!thrd) return; ! collapsed = get_lflag(stream, NULL, thrd->rawno, MN_COLL) && thrd->next; if(collapsed){ msgno = mn_raw2m(msgmap, thrd->rawno); --- 10485,10491 ---- if(!thrd) return; ! collapsed = this_thread_is_kolapsed(ps_global, stream, msgmap, thrd->rawno); if(collapsed){ msgno = mn_raw2m(msgmap, thrd->rawno); *************** *** 10255,10267 **** msgno = mn_raw2m(msgmap, thrd->rawno); if(msgno > 0L && msgno <= mn_get_total(msgmap)){ set_lflag(stream, msgmap, msgno, MN_COLL, 1); ! if(nthrd = fetch_thread(stream, thrd->next)) set_thread_subtree(stream, nthrd, msgmap, 1, MN_CHID); clear_index_cache_ent(msgno); } } ! else q_status_message(SM_ORDER, 0, 1, "No thread to collapse or expand on this line"); --- 10503,10515 ---- msgno = mn_raw2m(msgmap, thrd->rawno); if(msgno > 0L && msgno <= mn_get_total(msgmap)){ set_lflag(stream, msgmap, msgno, MN_COLL, 1); ! if((thrd->next) && (nthrd = fetch_thread(stream, thrd->next))) set_thread_subtree(stream, nthrd, msgmap, 1, MN_CHID); clear_index_cache_ent(msgno); } } ! else if (display) q_status_message(SM_ORDER, 0, 1, "No thread to collapse or expand on this line"); *************** *** 10343,10360 **** unsigned long rawno, count = 0; PINETHRD_S *nthrd, *bthrd; MESSAGECACHE *mc; if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs) return count; ! if(thrd->next){ ! nthrd = fetch_thread(stream, thrd->next); if(nthrd) count += count_flags_in_thread(stream, nthrd, flags); } ! if(thrd->branch){ ! bthrd = fetch_thread(stream, thrd->branch); if(bthrd) count += count_flags_in_thread(stream, bthrd, flags); } --- 10591,10609 ---- unsigned long rawno, count = 0; PINETHRD_S *nthrd, *bthrd; MESSAGECACHE *mc; + unsigned long next = 0L, branch = 0L; if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs) return count; ! if(next = get_next(stream, thrd)){ ! nthrd = fetch_thread(stream, next); if(nthrd) count += count_flags_in_thread(stream, nthrd, flags); } ! if(branch = get_branch(stream, thrd)){ ! bthrd = fetch_thread(stream, branch); if(bthrd) count += count_flags_in_thread(stream, bthrd, flags); } *************** *** 10385,10404 **** MSGNO_S *msgmap; int flags; /* flag to count */ { ! unsigned long rawno, count = 0; PINETHRD_S *nthrd, *bthrd; if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs) return count; ! if(thrd->next){ ! nthrd = fetch_thread(stream, thrd->next); if(nthrd) count += count_lflags_in_thread(stream, nthrd, msgmap, flags); } ! if(thrd->branch){ ! bthrd = fetch_thread(stream, thrd->branch); if(bthrd) count += count_lflags_in_thread(stream, bthrd, msgmap,flags); } --- 10634,10653 ---- MSGNO_S *msgmap; int flags; /* flag to count */ { ! unsigned long rawno, count = 0, next, branch; PINETHRD_S *nthrd, *bthrd; if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs) return count; ! if(next = get_next(stream, thrd)){ ! nthrd = fetch_thread(stream, next); if(nthrd) count += count_lflags_in_thread(stream, nthrd, msgmap, flags); } ! if(branch = get_branch(stream, thrd)){ ! bthrd = fetch_thread(stream, branch); if(bthrd) count += count_lflags_in_thread(stream, bthrd, msgmap,flags); } *************** *** 10420,10426 **** MAILSTREAM *stream; PINETHRD_S *thrd; { ! unsigned long rawno, count = 0; PINETHRD_S *nthrd, *bthrd; if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs) --- 10669,10675 ---- MAILSTREAM *stream; PINETHRD_S *thrd; { ! unsigned long rawno, count = 0, next, branch; PINETHRD_S *nthrd, *bthrd; if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs) *************** *** 10429,10442 **** if(get_lflag(stream, NULL, thrd->rawno, MN_HIDE) == 0) return 1; ! if(thrd->next){ ! nthrd = fetch_thread(stream, thrd->next); if(nthrd && thread_has_some_visible(stream, nthrd)) return 1; } ! if(thrd->branch){ ! bthrd = fetch_thread(stream, thrd->branch); if(bthrd && thread_has_some_visible(stream, bthrd)) return 1; } --- 10678,10691 ---- if(get_lflag(stream, NULL, thrd->rawno, MN_HIDE) == 0) return 1; ! if(next = get_next(stream, thrd)){ ! nthrd = fetch_thread(stream, next); if(nthrd && thread_has_some_visible(stream, nthrd)) return 1; } ! if(branch = get_branch(stream, thrd)){ ! bthrd = fetch_thread(stream, branch); if(bthrd && thread_has_some_visible(stream, bthrd)) return 1; } *************** *** 10511,10530 **** MSGNO_S *msgmap; { int count = 0; PINETHRD_S *nthrd, *bthrd; MESSAGECACHE *mc; if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs) return count; ! if(thrd->next){ ! nthrd = fetch_thread(stream, thrd->next); if(nthrd) count += mark_msgs_in_thread(stream, nthrd, msgmap); } ! if(thrd->branch){ ! bthrd = fetch_thread(stream, thrd->branch); if(bthrd) count += mark_msgs_in_thread(stream, bthrd, msgmap); } --- 10760,10780 ---- MSGNO_S *msgmap; { int count = 0; + long next, branch; PINETHRD_S *nthrd, *bthrd; MESSAGECACHE *mc; if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs) return count; ! if(next = get_next(stream, thrd)){ ! nthrd = fetch_thread(stream, next); if(nthrd) count += mark_msgs_in_thread(stream, nthrd, msgmap); } ! if(branch = get_branch(stream, thrd)){ ! bthrd = fetch_thread(stream, branch); if(bthrd) count += mark_msgs_in_thread(stream, bthrd, msgmap); } *************** *** 10557,10563 **** int flags; /* flags to set or clear */ int v; /* set or clear? */ { ! unsigned long rawno, msgno; PINETHRD_S *nthrd, *bthrd; if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs) --- 10807,10813 ---- int flags; /* flags to set or clear */ int v; /* set or clear? */ { ! unsigned long rawno, msgno, next, branch; PINETHRD_S *nthrd, *bthrd; if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs) *************** *** 10583,10596 **** && v == 1 && get_index_cache(msgno)->line[0]) clear_index_cache_ent(msgno); ! if(thrd->next){ ! nthrd = fetch_thread(stream, thrd->next); if(nthrd) set_thread_lflags(stream, nthrd, msgmap, flags, v); } ! if(thrd->branch){ ! bthrd = fetch_thread(stream, thrd->branch); if(bthrd) set_thread_lflags(stream, bthrd, msgmap, flags, v); } --- 10833,10846 ---- && v == 1 && get_index_cache(msgno)->line[0]) clear_index_cache_ent(msgno); ! if(next = get_next(stream, thrd)){ ! nthrd = fetch_thread(stream, next); if(nthrd) set_thread_lflags(stream, nthrd, msgmap, flags, v); } ! if(branch = get_branch(stream,thrd)){ ! bthrd = fetch_thread(stream, branch); if(bthrd) set_thread_lflags(stream, bthrd, msgmap, flags, v); } *************** *** 10677,10695 **** { char to_us = ' '; PINETHRD_S *nthrd, *bthrd; MESSAGECACHE *mc; if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs) return to_us; ! if(thrd->next){ ! nthrd = fetch_thread(stream, thrd->next); if(nthrd) to_us = to_us_symbol_for_thread(stream, nthrd, consider_flagged); } ! if(to_us == ' ' && thrd->branch){ ! bthrd = fetch_thread(stream, thrd->branch); if(bthrd) to_us = to_us_symbol_for_thread(stream, bthrd, consider_flagged); } --- 10927,10946 ---- { char to_us = ' '; PINETHRD_S *nthrd, *bthrd; + unsigned long next = 0L, branch = 0L; MESSAGECACHE *mc; if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs) return to_us; ! if(next = get_next(stream,thrd)){ ! nthrd = fetch_thread(stream, next); if(nthrd) to_us = to_us_symbol_for_thread(stream, nthrd, consider_flagged); } ! if(to_us == ' ' && (branch = get_branch(stream, thrd))){ ! bthrd = fetch_thread(stream, branch); if(bthrd) to_us = to_us_symbol_for_thread(stream, bthrd, consider_flagged); } *************** *** 10724,10730 **** break; } ! if(to_us != '+' && resent_to_us(&idata)) to_us = '+'; if(to_us == ' ' && F_ON(F_MARK_FOR_CC,ps_global)) --- 10975,10981 ---- break; } ! if(to_us != '+' && !idata.bogus && resent_to_us(&idata)) to_us = '+'; if(to_us == ' ' && F_ON(F_MARK_FOR_CC,ps_global)) *************** *** 10760,10766 **** int flags; /* flags to set or clear */ { int hiding; ! unsigned long rawno, msgno; PINETHRD_S *nthrd, *bthrd; hiding = (flags == MN_CHID) && v; --- 11011,11017 ---- int flags; /* flags to set or clear */ { int hiding; ! unsigned long rawno, msgno, next, branch; PINETHRD_S *nthrd, *bthrd; hiding = (flags == MN_CHID) && v; *************** *** 10772,10778 **** set_lflag(stream, msgmap, msgno, flags, v); ! if(thrd->next && (hiding || !get_lflag(stream,NULL,thrd->rawno,MN_COLL))){ nthrd = fetch_thread(stream, thrd->next); if(nthrd) set_thread_subtree(stream, nthrd, msgmap, v, flags); --- 11023,11030 ---- set_lflag(stream, msgmap, msgno, flags, v); ! if(thrd->next ! && (hiding || !get_lflag(stream,NULL,thrd->rawno,MN_COLL))){ nthrd = fetch_thread(stream, thrd->next); if(nthrd) set_thread_subtree(stream, nthrd, msgmap, v, flags); *************** *** 10816,10823 **** if(rawno) thrd = fetch_thread(stream, rawno); ! if(thrd && thrd->top && thrd->top != thrd->rawno) ! thrd = fetch_thread(stream, thrd->top); if(!thrd) return 0; --- 11068,11075 ---- if(rawno) thrd = fetch_thread(stream, rawno); ! if(thrd && thrd->top && top_thread(stream,thrd->top) != thrd->rawno) ! thrd = fetch_thread(stream, top_thread(stream,thrd->top)); if(!thrd) return 0; *************** *** 10833,10840 **** set_thread_lflags(stream, thrd, msgmap, MN_CHID2, 1); } ! if(current_index_state) ! msgmap->top_after_thrd = current_index_state->msg_at_top; /* * If this is one of those wacky users who like to sort backwards --- 11085,11093 ---- set_thread_lflags(stream, thrd, msgmap, MN_CHID2, 1); } ! /* if(current_index_state) ! msgmap->top_after_thrd = current_index_state->msg_at_top;*/ ! msgmap->top_after_thrd = mn_raw2m(msgmap, thrd->top); /* * If this is one of those wacky users who like to sort backwards *************** *** 10889,10895 **** thrd = fetch_thread(stream, rawno); if(thrd && thrd->top) ! topthrd = fetch_thread(stream, thrd->top); if(!topthrd) return 0; --- 11142,11148 ---- thrd = fetch_thread(stream, rawno); if(thrd && thrd->top) ! topthrd = fetch_thread(stream, top_thread(stream,thrd->top)); if(!topthrd) return 0; *************** *** 11026,11028 **** --- 11279,11567 ---- } } } + + unsigned long + get_branch(stream,thrd) + MAILSTREAM *stream; + PINETHRD_S *thrd; + { + PINETHRD_S *nthrd = NULL; + unsigned long top; + + if (thrd->toploose && thrd->nextthd) + nthrd = fetch_thread(stream, thrd->nextthd); + if (!nthrd) + return thrd->branch; + top = top_thread(stream, thrd->rawno); + return thrd->branch + ? thrd->branch + : (F_ON(F_ENHANCED_THREAD, ps_global) + ? (top == top_thread(stream, nthrd->rawno) ? thrd->nextthd : 0L) + : 0L); + } + + unsigned long + get_next(stream,thrd) + MAILSTREAM *stream; + PINETHRD_S *thrd; + { + return thrd->next; + } + + long + get_length_branch(stream, rawno) + MAILSTREAM *stream; + long rawno; + { + int branchp = 0, done = 0; + long top, count = 1L, raw; + PINETHRD_S *thrd, *pthrd = NULL, *nthrd; + + thrd = fetch_thread(stream, rawno); + + if (!thrd) + return -1L; + + top = thrd->top; + + if (thrd->parent) + pthrd = fetch_thread(stream, thrd->parent); + + if (thrd->rawno == top) + branchp++; + + if (!branchp && !pthrd){ /* what!!?? */ + raw = top; + while (!done){ + pthrd = fetch_thread(stream, raw); + if ((pthrd->next == rawno) || (pthrd->branch == rawno)) + done++; + else{ + if (pthrd->next) + raw = pthrd->next; + else if (pthrd->branch) + raw = pthrd->branch; + } + } + } + + if (pthrd && pthrd->next == thrd->rawno && thrd->branch) + branchp++; + + if (pthrd && pthrd->next && pthrd->next != thrd->rawno){ + nthrd = fetch_thread(stream, pthrd->next); + while (nthrd && nthrd->branch && nthrd->branch != thrd->rawno) + nthrd = fetch_thread(stream, nthrd->branch); + if(nthrd && nthrd->branch && nthrd->branch == thrd->rawno) + branchp++; + } + + if(branchp){ + int entry = 0; + while(thrd && thrd->next){ + entry = 1; + count++; + thrd = fetch_thread(stream, thrd->next); + if (thrd->branch) + break; + } + if (entry && thrd->branch) + count--; + } + return branchp ? (count ? count : 1L) : 0L; + } + + void + find_msgmap(stream, msgmap, flags, ordersort, is_rev) + MAILSTREAM *stream; + MSGNO_S *msgmap; + int flags; + SortOrder ordersort; + unsigned is_rev; + { + int we_cancel; + long *old_arrival,*new_arrival; + long init_thread, end_thread, current; + long k = 1L, j, last_thread = 0L; + long i, tmsg, ntmsg, nthreads; + int nflags = (SRT_VRB | SRT_MAN); + char sort_msg[MAX_SCREEN_COLS+1] = {'\0'}; + PINETHRD_S *thrd, *tthrd, *nthrd; + + erase_thread_info = 0; + current = mn_m2raw(msgmap, mn_get_cur(msgmap)); + + /* now sort by arrival */ + sort_folder(stream, msgmap, ordersort, 0, nflags, 0); + + tmsg = mn_get_total(msgmap) + 1; + + if (tmsg <= 1) + return; + + old_arrival = (long *) fs_get(tmsg * sizeof(long)); + memset(old_arrival, 0, tmsg*sizeof(long)); + for (i= 1L;(i <= mn_get_total(msgmap)) && (old_arrival[i] = msgmap->sort[i]); i++); + + /* now sort by thread */ + sort_folder(stream, msgmap, SortThread, 0, nflags, 0); + ntmsg = mn_get_total(msgmap) + 1; + + if (tmsg != ntmsg){ /* oh oh, something happened,we better try again */ + fs_give((void **)&old_arrival); + find_msgmap(stream, msgmap, flags, ordersort, is_rev); + return; + } + + /* reconstruct the msgmap */ + + new_arrival = (long *) fs_get(tmsg * sizeof(long)); + memset(new_arrival, 0, tmsg*sizeof(long)); + i = mn_get_total(msgmap); + while (new_arrival[1] == 0){ /* think of this as (tmsg > 0) */ + int done = 0; + long n = mn_get_total(msgmap); + + init_thread = top_thread(stream, old_arrival[i]); + thrd = fetch_thread(stream, init_thread); + while ((new_arrival[n] != 0) && !done){ /* compare raw numbers */ + done = (new_arrival[n] == init_thread); + n--; + } + if (!done){ + k = 1L; + mn_set_cur(msgmap, mn_raw2m(msgmap, init_thread)); + if (move_next_thread(ps_global, stream, msgmap, 0) <= 0) + j = mn_get_total(msgmap) - mn_raw2m(msgmap, init_thread) + 1; + else + j = mn_get_cur(msgmap) - mn_raw2m(msgmap, init_thread); + end_thread = mn_raw2m(msgmap, init_thread) + j; + while (k <= j){ + new_arrival[tmsg - k] = msgmap->sort[end_thread - k]; + k++; + } + tmsg -= j; + } + i--; + } + relink_threads(stream, msgmap, new_arrival); + for (i = 1; (i <= mn_get_total(msgmap)) + && (msgmap->sort[i] = new_arrival[i]); i++); + msgno_reset_isort(msgmap); + + fs_give((void **)&new_arrival); + fs_give((void **)&old_arrival); + + + if(is_rev && (mn_get_total(msgmap) > 1L)){ + long *rev_sort; + long i = 1L, l = mn_get_total(msgmap); + + rev_sort = (long *) fs_get((mn_get_total(msgmap)+1L) * sizeof(long)); + memset(rev_sort, 0, (mn_get_total(msgmap)+1L)*sizeof(long)); + while (l > 0L){ + if (top_thread(stream, msgmap->sort[l]) == msgmap->sort[l]){ + long init_thread = msgmap->sort[l]; + long j, k; + + mn_set_cur(msgmap, mn_raw2m(msgmap, init_thread)); + if (move_next_thread(ps_global, stream, msgmap, 0) <= 0) + j = mn_get_total(msgmap) - mn_raw2m(msgmap, init_thread) + 1; + else + j = mn_get_cur(msgmap) - mn_raw2m(msgmap, init_thread); + for (k = 0L; (k < j) && (rev_sort[i+k] = msgmap->sort[l+k]); k++); + i += j; + } + l--; + } + relink_threads(stream, msgmap, rev_sort); + for (i = 1L; i <= mn_get_total(msgmap); i++) + msgmap->sort[i] = rev_sort[i]; + msgno_reset_isort(msgmap); + fs_give((void **)&rev_sort); + } + mn_reset_cur(msgmap, first_sorted_flagged(is_rev ? F_NONE : F_SRCHBACK, + stream, mn_raw2m(msgmap, current), FSF_SKIP_CHID)); + msgmap->top = -1L; + + sp_set_unsorted_newmail(ps_global->mail_stream, 0); + + for(i = 1L; i <= ps_global->mail_stream->nmsgs; i++) + mail_elt(ps_global->mail_stream, i)->spare7 = 0; + + mn_set_sort(msgmap, SortThread); + mn_set_revsort(msgmap, is_rev); + erase_thread_info = 1; + clear_index_cache(); + } + + void + move_thread(state, stream, msgmap, direction) + struct pine *state; + MAILSTREAM *stream; + MSGNO_S *msgmap; + int direction; + { + long new_cursor, old_cursor = mn_get_cur(msgmap); + int rv; + PINETHRD_S *thrd; + + rv = direction > 0 ? move_next_thread(state, stream, msgmap, 1): + move_prev_thread(state, stream, msgmap, 1); + if (rv > 0 && THRD_INDX_ENABLED()){ + new_cursor = mn_get_cur(msgmap); + mn_set_cur(msgmap, old_cursor); + unview_thread(state, stream, msgmap); + thrd = fetch_thread(stream,mn_m2raw(msgmap, new_cursor)); + mn_set_cur(msgmap, new_cursor); + view_thread(state, stream, msgmap, 1); + state->next_screen = SCREEN_FUN_NULL; + } + } + + void + relink_threads(stream, msgmap, new_arrival) + MAILSTREAM *stream; + MSGNO_S *msgmap; + long *new_arrival; + { + long last_thread = 0L; + long i = 0L, j = 1L, k; + PINETHRD_S *thrd, *nthrd; + + while (j <= mn_get_total(msgmap)){ + i++; + thrd = fetch_thread(stream, new_arrival[j]); + if (!thrd) /* sort failed!, better leave from here now!!! */ + break; + thrd->prevthd = last_thread; + thrd->thrdno = i; + thrd->head = new_arrival[1]; + last_thread = thrd->rawno; + mn_set_cur(msgmap, mn_raw2m(msgmap,thrd->top)); + k = mn_get_cur(msgmap); + if (move_next_thread(ps_global, stream, msgmap, 0) <= 0) + j += mn_get_total(msgmap) + 1 - k; + else + j += mn_get_cur(msgmap) - k; + if (!thrd->toploose) + thrd->nextthd = (j <= mn_get_total(msgmap)) ? new_arrival[j] : 0L; + else{ + int done = 0; + while(thrd->nextthd && !done){ + thrd->thrdno = i; + thrd->head = new_arrival[1]; + if (thrd->nextthd) + nthrd = fetch_thread(stream, thrd->nextthd); + else + done++; + if(top_thread(stream, thrd->rawno) == top_thread(stream, nthrd->rawno)) + thrd = nthrd; + else + done++; + } + thrd->nextthd = (j <= mn_get_total(msgmap)) ? new_arrival[j] : 0L; + last_thread = thrd->rawno; + } + } + } diff -rc pine4.61/pine/mailview.c pine4.61.fancy/pine/mailview.c *** pine4.61/pine/mailview.c Wed Jul 14 17:25:10 2004 --- pine4.61.fancy/pine/mailview.c Thu Aug 19 13:18:12 2004 *************** *** 235,245 **** HOMEKEY_MENU, ENDKEY_MENU, RCOMPOSE_MENU, ! NULL_MENU, ! NULL_MENU, ! NULL_MENU, ! NULL_MENU, ! NULL_MENU, NULL_MENU, NULL_MENU}; INST_KEY_MENU(view_keymenu, view_keys); --- 235,245 ---- HOMEKEY_MENU, ENDKEY_MENU, RCOMPOSE_MENU, ! {"(","Prev Threa",{MC_PRETHREAD,1,{'('}},KS_NONE}, ! {")","Next Threa",{MC_NEXTHREAD,1,{')'}},KS_NONE}, ! {"^D","Delete Thr",{MC_DELTHREAD,1,{ctrl('D')}},KS_NONE}, ! {"^U","Undel Thre",{MC_UNDTHREAD,1,{ctrl('U')}},KS_NONE}, ! {"^T","selcT Thre",{MC_SELTHREAD,1,{ctrl('T')}},KS_NONE}, NULL_MENU, NULL_MENU}; INST_KEY_MENU(view_keymenu, view_keys); *************** *** 8082,8087 **** --- 8082,8133 ---- print_to_printer(sparms); break; + case MC_NEXTHREAD: + case MC_PRETHREAD: + if (THREADING()){ + if (any_messages(ps_global->msgmap, NULL, + "to move to other thread")) + move_thread(ps_global, ps_global->mail_stream, ps_global->msgmap, + cmd == MC_NEXTHREAD ? 1 : -1); + done = 1; + } + else + q_status_message(SM_ORDER, 0, 1, + "Command available in threaded mode only"); + break; + + case MC_DELTHREAD: + if (THREADING()){ + if (any_messages(ps_global->msgmap, NULL, "to delete")) + cmd_delete_thread(ps_global, ps_global->mail_stream, ps_global->msgmap); + done = 1; + } + else + q_status_message(SM_ORDER, 0, 1, + "Command available in threaded mode only"); + break; + + case MC_UNDTHREAD: + if (THREADING()){ + if (any_messages(ps_global->msgmap, NULL, "to undelete")) + cmd_undelete_thread(ps_global, ps_global->mail_stream, ps_global->msgmap); + done = 1; + } + else + q_status_message(SM_ORDER, 0, 1, + "Command available in threaded mode only"); + break; + + case MC_SELTHREAD: + if (THREADING()){ + if (any_messages(ps_global->msgmap, NULL, "to undelete")) + cmd_select_thread(ps_global, ps_global->mail_stream, ps_global->msgmap); + done = 1; + } + else + q_status_message(SM_ORDER, 0, 1, + "Command available in threaded mode only"); + break; /* ------- First handle on Line ------ */ case MC_GOTOBOL : diff -rc pine4.61/pine/other.c pine4.61.fancy/pine/other.c *** pine4.61/pine/other.c Fri Jul 2 14:38:16 2004 --- pine4.61.fancy/pine/other.c Thu Aug 19 13:18:12 2004 *************** *** 357,364 **** char *checkbox_pretty_value PROTO((struct pine *, CONF_S *)); char *color_pretty_value PROTO((struct pine *, CONF_S *)); char *radio_pretty_value PROTO((struct pine *, CONF_S *)); ! char *sort_pretty_value PROTO((struct pine *, CONF_S *)); ! char *generalized_sort_pretty_value PROTO((struct pine *, CONF_S *, int)); char *yesno_pretty_value PROTO((struct pine *, CONF_S *)); char *sigfile_pretty_value PROTO((struct pine *, CONF_S *)); void set_radio_pretty_vals PROTO((struct pine *, CONF_S **)); --- 357,364 ---- char *checkbox_pretty_value PROTO((struct pine *, CONF_S *)); char *color_pretty_value PROTO((struct pine *, CONF_S *)); char *radio_pretty_value PROTO((struct pine *, CONF_S *)); ! char *sort_pretty_value PROTO((struct pine *, CONF_S *, int)); ! char *generalized_sort_pretty_value PROTO((struct pine *, CONF_S *, int, int)); char *yesno_pretty_value PROTO((struct pine *, CONF_S *)); char *sigfile_pretty_value PROTO((struct pine *, CONF_S *)); void set_radio_pretty_vals PROTO((struct pine *, CONF_S **)); *************** *** 1513,1519 **** if(lv < (j = strlen(sort_name(ps->sort_types[i])))) lv = j; ! decode_sort(pval, &def_sort, &def_sort_rev); for(j = 0; j < 2; j++){ for(i = 0; ps->sort_types[i] != EndofList; i++){ --- 1513,1519 ---- if(lv < (j = strlen(sort_name(ps->sort_types[i])))) lv = j; ! decode_sort(pval, &def_sort, &def_sort_rev, 0); for(j = 0; j < 2; j++){ for(i = 0; ps->sort_types[i] != EndofList; i++){ *************** *** 1528,1533 **** --- 1528,1583 ---- } } } + else if(vtmp == &ps->vars[V_THREAD_SORT_KEY]){ /* radio case */ + SortOrder thread_def_sort; + int thread_def_sort_rev; + + ctmpa->flags |= CF_NOSELECT; + ctmpa->keymenu = &config_radiobutton_keymenu; + ctmpa->tool = NULL; + + /* put a nice delimiter before list */ + new_confline(&ctmpa)->var = NULL; + ctmpa->varnamep = ctmpb; + ctmpa->keymenu = &config_radiobutton_keymenu; + ctmpa->help = NO_HELP; + ctmpa->tool = radiobutton_tool; + ctmpa->valoffset = 12; + ctmpa->flags |= CF_NOSELECT; + ctmpa->value = cpystr("Set Thread Sort Options"); + + new_confline(&ctmpa)->var = NULL; + ctmpa->varnamep = ctmpb; + ctmpa->keymenu = &config_radiobutton_keymenu; + ctmpa->help = NO_HELP; + ctmpa->tool = radiobutton_tool; + ctmpa->valoffset = 12; + ctmpa->flags |= CF_NOSELECT; + ctmpa->value = cpystr("--- ----------------------"); + + /* find longest value's name */ + for(lv = 0, i = 0; ps->sort_types[i] != EndofList; i++) + if(lv < (j = strlen(sort_name(ps->sort_types[i])))) + lv = j; + + decode_sort(pval, &thread_def_sort, &thread_def_sort_rev, 1); + + for(j = 0; j < 2; j++){ + for(i = 0; ps->sort_types[i] != EndofList; i++){ + if (ps->sort_types[i] == SortArrival + || ps->sort_types[i] == SortThread){ + new_confline(&ctmpa)->var = vtmp; + ctmpa->varnamep = ctmpb; + ctmpa->keymenu = &config_radiobutton_keymenu; + ctmpa->help = config_help(vtmp - ps->vars, 0); + ctmpa->tool = radiobutton_tool; + ctmpa->valoffset = 12; + ctmpa->varmem = i + (j * EndofList); + ctmpa->value = pretty_value(ps, ctmpa); + } + } + } + } else if(vtmp == &ps->vars[V_USE_ONLY_DOMAIN_NAME]){ /* yesno case */ ctmpa->keymenu = &config_yesno_keymenu; ctmpa->tool = yesno_tool; *************** *** 1686,1691 **** --- 1736,1750 ---- } } + pval = PVAL(&ps->vars[V_THREAD_SORT_KEY], ew); + if(vsave[V_THREAD_SORT_KEY].saved_user_val.p && pval + && strcmp(vsave[V_THREAD_SORT_KEY].saved_user_val.p, pval)){ + if(!mn_get_mansort(ps_global->msgmap)){ + clear_index_cache(); + reset_sort_order(SRT_VRB); + } + } + treat_color_vars_as_text = 0; free_saved_config(ps, &vsave, expose_hidden_config); #ifdef _WINDOWS *************** *** 1840,1846 **** CONF_S *ctmp; if(!(cl && *cl && ! ((*cl)->var == &ps->vars[V_SORT_KEY] || standard_radio_var(ps, (*cl)->var) || (*cl)->var == startup_ptr))) return; --- 1899,1906 ---- CONF_S *ctmp; if(!(cl && *cl && ! (((*cl)->var == &ps->vars[V_SORT_KEY]) || ! ((*cl)->var == &ps->vars[V_THREAD_SORT_KEY]) || standard_radio_var(ps, (*cl)->var) || (*cl)->var == startup_ptr))) return; *************** *** 7318,7323 **** --- 7378,7385 ---- return(h_config_fcc_rule); case V_SORT_KEY : return(h_config_sort_key); + case V_THREAD_SORT_KEY : + return(h_config_thread_sort_key); case V_AB_SORT_RULE : return(h_config_ab_sort_rule); case V_FLD_SORT_RULE : *************** *** 9208,9214 **** } set_current_val((*cl)->var, TRUE, TRUE); ! if(decode_sort(ps->VAR_SORT_KEY, &def_sort, &def_sort_rev) != -1){ ps->def_sort = def_sort; ps->def_sort_rev = def_sort_rev; } --- 9270,9276 ---- } set_current_val((*cl)->var, TRUE, TRUE); ! if(decode_sort(ps->VAR_SORT_KEY, &def_sort, &def_sort_rev,0) != -1){ ps->def_sort = def_sort; ps->def_sort_rev = def_sort_rev; } *************** *** 9217,9222 **** --- 9279,9315 ---- ps->mangled_body = 1; /* BUG: redraw it all for now? */ rv = 1; } + else if((*cl)->var == &ps->vars[V_THREAD_SORT_KEY]){ + SortOrder thread_def_sort; + int thread_def_sort_rev; + + thread_def_sort_rev = (*cl)->varmem >= (short) EndofList; + thread_def_sort = (SortOrder) ((*cl)->varmem - (thread_def_sort_rev + * EndofList)); + sprintf(tmp_20k_buf, "%s%s", sort_name(thread_def_sort), + (thread_def_sort_rev) ? "/Reverse" : ""); + + if((*cl)->var->cmdline_val.p) + fs_give((void **)&(*cl)->var->cmdline_val.p); + + if(apval){ + if(*apval) + fs_give((void **)apval); + + *apval = cpystr(tmp_20k_buf); + } + + set_current_val((*cl)->var, TRUE, TRUE); + if(decode_sort(ps->VAR_THREAD_SORT_KEY, &thread_def_sort, + &thread_def_sort_rev, 1) != -1){ + ps->thread_def_sort = thread_def_sort; + ps->thread_def_sort_rev = thread_def_sort_rev; + } + + set_radio_pretty_vals(ps, cl); + ps->mangled_body = 1; /* BUG: redraw it all for now? */ + rv = 1; + } else q_status_message(SM_ORDER | SM_DING, 3, 6, "Programmer botch! Unknown radiobutton type."); *************** *** 10689,10695 **** else if(standard_radio_var(ps, v) || v == startup_ptr) return(radio_pretty_value(ps, cl)); else if(v == &ps->vars[V_SORT_KEY]) ! return(sort_pretty_value(ps, cl)); else if(v == &ps->vars[V_SIGNATURE_FILE]) return(sigfile_pretty_value(ps, cl)); else if(v == &ps->vars[V_USE_ONLY_DOMAIN_NAME]) --- 10782,10790 ---- else if(standard_radio_var(ps, v) || v == startup_ptr) return(radio_pretty_value(ps, cl)); else if(v == &ps->vars[V_SORT_KEY]) ! return(sort_pretty_value(ps, cl, 0)); ! else if(v == &ps->vars[V_THREAD_SORT_KEY]) ! return(sort_pretty_value(ps, cl, 1)); else if(v == &ps->vars[V_SIGNATURE_FILE]) return(sigfile_pretty_value(ps, cl)); else if(v == &ps->vars[V_USE_ONLY_DOMAIN_NAME]) *************** *** 11358,11376 **** char * ! sort_pretty_value(ps, cl) struct pine *ps; CONF_S *cl; { ! return(generalized_sort_pretty_value(ps, cl, 1)); } char * ! generalized_sort_pretty_value(ps, cl, default_ok) struct pine *ps; CONF_S *cl; int default_ok; { char tmp[MAXPATH]; char *pvalnorm, *pvalexc, *pval; --- 11453,11473 ---- char * ! sort_pretty_value(ps, cl, thread) struct pine *ps; CONF_S *cl; + int thread; { ! return(generalized_sort_pretty_value(ps, cl, 1, thread)); } char * ! generalized_sort_pretty_value(ps, cl, default_ok, thread) struct pine *ps; CONF_S *cl; int default_ok; + int thread; { char tmp[MAXPATH]; char *pvalnorm, *pvalexc, *pval; *************** *** 11420,11426 **** } else if(fixed){ pval = v->fixed_val.p; ! decode_sort(pval, &var_sort, &var_sort_rev); is_the_one = (var_sort_rev == line_sort_rev && var_sort == line_sort); sprintf(tmp, "(%c) %s%-*s%*s%s", --- 11517,11523 ---- } else if(fixed){ pval = v->fixed_val.p; ! decode_sort(pval, &var_sort, &var_sort_rev, thread); is_the_one = (var_sort_rev == line_sort_rev && var_sort == line_sort); sprintf(tmp, "(%c) %s%-*s%*s%s", *************** *** 11431,11439 **** is_the_one ? " (value is fixed)" : ""); } else if(is_set_for_this_level){ ! decode_sort(pval, &var_sort, &var_sort_rev); is_the_one = (var_sort_rev == line_sort_rev && var_sort == line_sort); ! decode_sort(pvalexc, &exc_sort, &exc_sort_rev); the_exc_one = (editing_normal_which_isnt_except && pvalexc && exc_sort_rev == line_sort_rev && exc_sort == line_sort); sprintf(tmp, "(%c) %s%-*s%*s%s", --- 11528,11536 ---- is_the_one ? " (value is fixed)" : ""); } else if(is_set_for_this_level){ ! decode_sort(pval, &var_sort, &var_sort_rev, thread); is_the_one = (var_sort_rev == line_sort_rev && var_sort == line_sort); ! decode_sort(pvalexc, &exc_sort, &exc_sort_rev, thread); the_exc_one = (editing_normal_which_isnt_except && pvalexc && exc_sort_rev == line_sort_rev && exc_sort == line_sort); sprintf(tmp, "(%c) %s%-*s%*s%s", *************** *** 11451,11457 **** } else{ if(pvalexc){ ! decode_sort(pvalexc, &exc_sort, &exc_sort_rev); is_the_one = (exc_sort_rev == line_sort_rev && exc_sort == line_sort); sprintf(tmp, "( ) %s%-*s%*s%s", --- 11548,11554 ---- } else{ if(pvalexc){ ! decode_sort(pvalexc, &exc_sort, &exc_sort_rev, thread); is_the_one = (exc_sort_rev == line_sort_rev && exc_sort == line_sort); sprintf(tmp, "( ) %s%-*s%*s%s", *************** *** 11462,11468 **** } else{ pval = v->current_val.p; ! decode_sort(pval, &var_sort, &var_sort_rev); is_the_one = ((pval || default_ok) && var_sort_rev == line_sort_rev && var_sort == line_sort); --- 11559,11565 ---- } else{ pval = v->current_val.p; ! decode_sort(pval, &var_sort, &var_sort_rev, thread); is_the_one = ((pval || default_ok) && var_sort_rev == line_sort_rev && var_sort == line_sort); *************** *** 11660,11665 **** --- 11757,11775 ---- cl->value = pretty_value(ps, cl); } + if (f->id == F_ENHANCED_THREAD && ps->mail_stream + && SORT_IS_THREADED(ps->msgmap)){ + refresh_sort(ps->mail_stream, ps->msgmap, SRT_NON); + if (COLL_THRDS()) /* sortring by thread destroys collapsed info */ + kolapse_thread(ps, ps->mail_stream, ps->msgmap,'[', 0); + if(SEP_THRDINDX() && SORT_IS_THREADED(ps->msgmap) + && sp_viewing_a_thread(ps->mail_stream)){ + unview_thread(ps, ps->mail_stream, ps->msgmap); + view_thread(ps, ps->mail_stream, ps->msgmap, 0); + ps_global->next_screen = SCREEN_FUN_NULL; + } + } + /* * Handle any features that need special attention here... *************** *** 12766,12774 **** else if(revert && var == &ps->vars[V_SORT_KEY]){ int def_sort_rev; ! decode_sort(VAR_SORT_KEY, &ps->def_sort, &def_sort_rev); ps->def_sort_rev = def_sort_rev; } else if(var == &ps->vars[V_THREAD_MORE_CHAR] || var == &ps->vars[V_THREAD_EXP_CHAR] || var == &ps->vars[V_THREAD_LASTREPLY_CHAR]){ --- 12876,12890 ---- else if(revert && var == &ps->vars[V_SORT_KEY]){ int def_sort_rev; ! decode_sort(VAR_SORT_KEY, &ps->def_sort, &def_sort_rev, 0); ps->def_sort_rev = def_sort_rev; } + else if(revert && var == &ps->vars[V_THREAD_SORT_KEY]){ + int thread_def_sort_rev; + + decode_sort(VAR_THREAD_SORT_KEY, &ps->thread_def_sort, &thread_def_sort_rev, 1); + ps->thread_def_sort_rev = thread_def_sort_rev; + } else if(var == &ps->vars[V_THREAD_MORE_CHAR] || var == &ps->vars[V_THREAD_EXP_CHAR] || var == &ps->vars[V_THREAD_LASTREPLY_CHAR]){ *************** *** 17616,17622 **** pval = PVAL(&sort_act_var, ew); if(pval) ! decode_sort(pval, &def_sort, &def_sort_rev); /* allow user to set their default sort order */ new_confline(&ctmp)->var = &sort_act_var; --- 17732,17738 ---- pval = PVAL(&sort_act_var, ew); if(pval) ! decode_sort(pval, &def_sort, &def_sort_rev, 0); /* allow user to set their default sort order */ new_confline(&ctmp)->var = &sort_act_var; *************** *** 17626,17632 **** ctmp->tool = role_sort_tool; ctmp->valoffset = 12; ctmp->varmem = -1; ! ctmp->value = generalized_sort_pretty_value(ps, ctmp, 0); for(j = 0; j < 2; j++){ for(i = 0; ps->sort_types[i] != EndofList; i++){ --- 17742,17748 ---- ctmp->tool = role_sort_tool; ctmp->valoffset = 12; ctmp->varmem = -1; ! ctmp->value = generalized_sort_pretty_value(ps, ctmp, 0, 0); for(j = 0; j < 2; j++){ for(i = 0; ps->sort_types[i] != EndofList; i++){ *************** *** 17638,17644 **** ctmp->valoffset = 12; ctmp->varmem = i + (j * EndofList); ctmp->value = generalized_sort_pretty_value(ps, ctmp, ! 0); } } --- 17754,17760 ---- ctmp->valoffset = 12; ctmp->varmem = i + (j * EndofList); ctmp->value = generalized_sort_pretty_value(ps, ctmp, ! 0, 0); } } *************** *** 18494,18500 **** (*result)->patgrp->stat_8bitsubj = PAT_STAT_EITHER; if(sort_act){ ! decode_sort(sort_act, &def_sort, &def_sort_rev); (*result)->action->sort_is_set = 1; (*result)->action->sortorder = def_sort; (*result)->action->revsort = (def_sort_rev ? 1 : 0); --- 18610,18616 ---- (*result)->patgrp->stat_8bitsubj = PAT_STAT_EITHER; if(sort_act){ ! decode_sort(sort_act, &def_sort, &def_sort_rev, 0); (*result)->action->sort_is_set = 1; (*result)->action->sortorder = def_sort; (*result)->action->revsort = (def_sort_rev ? 1 : 0); diff -rc pine4.61/pine/pine.c pine4.61.fancy/pine/pine.c *** pine4.61/pine/pine.c Wed Jul 14 11:17:13 2004 --- pine4.61.fancy/pine/pine.c Thu Aug 19 13:18:12 2004 *************** *** 251,256 **** --- 251,257 ---- pine_state = (struct pine *)fs_get(sizeof (struct pine)); memset((void *)pine_state, 0, sizeof(struct pine)); ps_global = pine_state; + ps_global->thread_def_sort = SortDate; ps_global->def_sort = SortArrival; ps_global->sort_types[0] = SortSubject; ps_global->sort_types[1] = SortArrival; *************** *** 3906,3919 **** was_invisible = (mc->spare || mc->spare4) ? 1 : 0; if(chk_thrd_cnt = ((msgs->visible_threads >= 0L) && THRD_INDX_ENABLED() && (f & MN_HIDE) && (mc->spare != v))){ - 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){ --- 3907,3921 ---- was_invisible = (mc->spare || mc->spare4) ? 1 : 0; + thrd = fetch_thread(stream, rawno); + if(chk_thrd_cnt = ((msgs->visible_threads >= 0L) && THRD_INDX_ENABLED() && (f & MN_HIDE) && (mc->spare != v))){ if(thrd && thrd->top){ ! if(top_thread(stream,thrd->top) == thrd->rawno) topthrd = thrd; else ! topthrd = fetch_thread(stream, top_thread(stream,thrd->top)); } if(topthrd){ diff -rc pine4.61/pine/pine.h pine4.61.fancy/pine/pine.h *** pine4.61/pine/pine.h Wed Jul 14 17:25:12 2004 --- pine4.61.fancy/pine/pine.h Thu Aug 19 13:28:49 2004 *************** *** 616,621 **** --- 616,622 ---- , V_SAVED_MSG_NAME_RULE , V_FCC_RULE , V_SORT_KEY + , V_THREAD_SORT_KEY , V_AB_SORT_RULE , V_FLD_SORT_RULE , V_GOTO_DEFAULT_RULE *************** *** 862,867 **** --- 863,871 ---- #define VAR_SORT_KEY vars[V_SORT_KEY].current_val.p #define GLO_SORT_KEY vars[V_SORT_KEY].global_val.p #define COM_SORT_KEY vars[V_SORT_KEY].cmdline_val.p + #define VAR_THREAD_SORT_KEY vars[V_THREAD_SORT_KEY].current_val.p + #define GLO_THREAD_SORT_KEY vars[V_THREAD_SORT_KEY].global_val.p + #define COM_THREAD_SORT_KEY vars[V_THREAD_SORT_KEY].cmdline_val.p #define VAR_AB_SORT_RULE vars[V_AB_SORT_RULE].current_val.p #define GLO_AB_SORT_RULE vars[V_AB_SORT_RULE].global_val.p #define VAR_FLD_SORT_RULE vars[V_FLD_SORT_RULE].current_val.p *************** *** 1275,1280 **** --- 1279,1285 ---- F_ALWAYS_SPELL_CHECK, F_QUELL_TIMEZONE, F_COLOR_LINE_IMPORTANT, + F_ENHANCED_THREAD, F_SLASH_COLL_ENTIRE, F_ENABLE_FULL_HDR_AND_TEXT, F_QUELL_FULL_HDR_RESET, *************** *** 1882,1888 **** SortSubject2, SortScore, SortThread, EndofList} SortOrder; #define refresh_sort(S,M,F) sort_folder((S), (M), mn_get_sort(M), \ ! mn_get_revsort(M), (F)) /* * The two structs below hold all knowledge regarding --- 1887,1893 ---- SortSubject2, SortScore, SortThread, EndofList} SortOrder; #define refresh_sort(S,M,F) sort_folder((S), (M), mn_get_sort(M), \ ! mn_get_revsort(M), (F), 1) /* * The two structs below hold all knowledge regarding *************** *** 1925,1937 **** typedef struct pine_thrd { unsigned long rawno; /* raw msgno of this message */ unsigned long thrdno; /* thread number */ - unsigned long flags; unsigned long next; /* msgno of first reply to us */ unsigned long branch; /* like THREADNODE branch, next replier */ unsigned long parent; /* message that this is a reply to */ unsigned long nextthd; /* next thread, only tops have this */ unsigned long prevthd; /* previous thread, only tops have this */ unsigned long top; /* top of this thread */ unsigned long head; /* head of the whole thread list */ } PINETHRD_S; --- 1930,1942 ---- typedef struct pine_thrd { unsigned long rawno; /* raw msgno of this message */ unsigned long thrdno; /* thread number */ unsigned long next; /* msgno of first reply to us */ unsigned long branch; /* like THREADNODE branch, next replier */ unsigned long parent; /* message that this is a reply to */ unsigned long nextthd; /* next thread, only tops have this */ unsigned long prevthd; /* previous thread, only tops have this */ unsigned long top; /* top of this thread */ + unsigned long toploose; /* top of this thread, if is loose */ unsigned long head; /* head of the whole thread list */ } PINETHRD_S; *************** *** 2533,2539 **** iTime24, iTime12, iCurDate, iCurDateIso, iCurDateIsoS, iCurTime24, iCurTime12, iMessNo, iAtt, iMsgID, iSubject, iSubjKey, ! iSize, iSizeComma, iSizeNarrow, iDescripSize, iNewsAndTo, iToAndNews, iNewsAndRecips, iRecipsAndNews, iFromTo, iFromToNotNews, iFrom, iTo, iSender, iCc, iNews, iRecips, iMailbox, iAddress, iInit, iCursorPos, --- 2538,2544 ---- iTime24, iTime12, iCurDate, iCurDateIso, iCurDateIsoS, iCurTime24, iCurTime12, iMessNo, iAtt, iMsgID, iSubject, iSubjKey, ! iSize, iSizeComma, iSizeNarrow, iDescripSize, iSizeThread, iNewsAndTo, iToAndNews, iNewsAndRecips, iRecipsAndNews, iFromTo, iFromToNotNews, iFrom, iTo, iSender, iCc, iNews, iRecips, iMailbox, iAddress, iInit, iCursorPos, *************** *** 2921,2926 **** --- 2926,2944 ---- #define MC_NOT 797 #define MC_COLLAPSE 798 #define MC_CHK_RECENT 799 + #define MC_PRETHREAD 800 + #define MC_CTHREAD 801 + #define MC_OTHREAD 802 + #define MC_KOLAPSE 803 + #define MC_EXPTHREAD 804 + #define MC_DELTHREAD 805 + #define MC_UNDTHREAD 806 + #define MC_SELTHREAD 807 + #define MC_SSUTHREAD 808 + #define MC_DSUTHREAD 809 + #define MC_USUTHREAD 810 + #define MC_SORTHREAD 811 + #define MC_NEXTHREAD 812 /* *************** *** 3753,3758 **** --- 3771,3777 ---- PrivateAffector *affector; } PrivateTop; + #define DF_THREAD_SORT_KEY "thread" typedef enum {OpenFolder, SaveMessage, FolderMaint, GetFcc, Subscribe, PostNews} FolderFun; *************** *** 4168,4173 **** --- 4187,4194 ---- unsigned unseen_in_view:1; unsigned start_in_context:1; /* start fldr_scrn in current cntxt */ unsigned def_sort_rev:1; /* true if reverse sort is default */ + unsigned thread_def_sort_rev:1; /* true if reverse sort is default in thread screen */ + unsigned msgmap_thread_def_sort_rev:1; /* true if reverse sort is being used in thread screen */ unsigned restricted:1; unsigned show_dot_names:1; *************** *** 4304,4309 **** --- 4325,4333 ---- EditWhich ew_for_other_take; SortOrder def_sort, /* Default sort type */ + thread_def_sort, /* Default Sort Type in Thread Screen */ + thread_cur_sort, /* current sort style for threads */ + msgmap_thread_sort, sort_types[22]; int last_expire_year, last_expire_month; *************** *** 4553,4559 **** int write_pinerc PROTO((struct pine *, EditWhich)); int var_in_pinerc PROTO((char *)); void free_pinerc_lines PROTO((PINERC_LINE **)); ! int decode_sort PROTO((char *, SortOrder *, int *)); void dump_global_conf PROTO((void)); void dump_new_pinerc PROTO((char *)); int set_variable PROTO((int, char *, int, int, EditWhich)); --- 4577,4583 ---- int write_pinerc PROTO((struct pine *, EditWhich)); int var_in_pinerc PROTO((char *)); void free_pinerc_lines PROTO((PINERC_LINE **)); ! int decode_sort PROTO((char *, SortOrder *, int *, int)); void dump_global_conf PROTO((void)); void dump_new_pinerc PROTO((char *)); int set_variable PROTO((int, char *, int, int, EditWhich)); *************** *** 4627,4633 **** int process_cmd PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int, CmdWhere, int *)); int apply_command PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int, ! int, int)); int menu_command PROTO((int, struct key_menu *)); void menu_init_binding PROTO((struct key_menu *, int, int, char *, char *, int)); --- 4651,4657 ---- int process_cmd PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int, CmdWhere, int *)); int apply_command PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int, ! int, int, int)); int menu_command PROTO((int, struct key_menu *)); void menu_init_binding PROTO((struct key_menu *, int, int, char *, char *, int)); *************** *** 4723,4729 **** MSGNO_S *, IndexType, int *, int)); char *sort_name PROTO((SortOrder)); void sort_folder PROTO((MAILSTREAM *, MSGNO_S *, ! SortOrder, int, unsigned)); int percent_sorted PROTO((void)); void msgno_init PROTO((MSGNO_S **, long)); void msgno_give PROTO((MSGNO_S **)); --- 4747,4753 ---- MSGNO_S *, IndexType, int *, int)); char *sort_name PROTO((SortOrder)); void sort_folder PROTO((MAILSTREAM *, MSGNO_S *, ! SortOrder, int, unsigned, int)); int percent_sorted PROTO((void)); void msgno_init PROTO((MSGNO_S **, long)); void msgno_give PROTO((MSGNO_S **)); *************** *** 4745,4751 **** void free_pine_elt PROTO((void **)); SEARCHSET *build_searchset PROTO((MAILSTREAM *)); void collapse_or_expand PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, ! unsigned long)); PINETHRD_S *fetch_thread PROTO((MAILSTREAM *, unsigned long)); PINETHRD_S *fetch_head_thread PROTO((MAILSTREAM *)); int view_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int)); --- 4769,4775 ---- void free_pine_elt PROTO((void **)); SEARCHSET *build_searchset PROTO((MAILSTREAM *)); void collapse_or_expand PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, ! unsigned long, int)); PINETHRD_S *fetch_thread PROTO((MAILSTREAM *, unsigned long)); PINETHRD_S *fetch_head_thread PROTO((MAILSTREAM *)); int view_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int)); diff -rc pine4.61/pine/pine.hlp pine4.61.fancy/pine/pine.hlp *** pine4.61/pine/pine.hlp Thu Jul 15 10:37:22 2004 --- pine4.61.fancy/pine/pine.hlp Thu Aug 19 13:18:12 2004 *************** *** 3321,3326 **** --- 3321,3327 ----
  • OPTION: Signature-File
  • OPTION: SMTP-Server
  • OPTION: Sort-Key +
  • OPTION: Thread-Sort-Key
  • OPTION: Speller
  • OPTION: Ssh-Command
  • OPTION: Ssh-Open-Timeout *************** *** 4826,4831 **** --- 4827,4985 ---- <End of help on this topic> + ======= h_thread_index_sort_arrival ======= + + + SORT OPTION: Arrival + + +

    SORT OPTION: Arrival

    + + The Arrival sort option arranges threads according to the last + time that a message was added to it. In this order the last thread + contains the most recent message in the folder. + +

    + <End of help on this topic> + + + ======= h_thread_index_sort_date ======= + + + SORT OPTION: Date + + +

    SORT OPTION: Date

    + + The Date sort option in the THREAD INDEX screen is the same + as sorting by thread, the most likely thing is that you won't see Pine + sorting the folder, because it's already sorted. + +

    + On a folder like INBOX, sorting by "Date" should be almost + identical to sorting by "Arrival". + +

    + <End of help on this topic> + + + ======= h_thread_index_sort_subj ======= + + + SORT OPTION: Subject + + +

    SORT OPTION: Subject

    + + The Subject sort option has not been defined yet. + +

    + <End of help on this topic> + + + ======= h_thread_index_sort_ordsubj ======= + + + SORT OPTION: OrderedSubject + + +

    SORT OPTION: OrderedSubject

    + + The OrderedSubject sort option in the THREAD INDEX screen is + the same as sorting by Subject. + +

    + <End of help on this topic> + + + ======= h_thread_index_sort_thread ======= + + + SORT OPTION: Thread + + +

    SORT OPTION: Thread

    + + The Thread sort option in the THREAD INDEX screen sorts all + messages by the proposed algorithm by Crispin and Murchison. In this + method of sorting once threads have been isolated they are sorted by the + date of their parents, or if that is missing, the first message in that + thread. + +

    + <End of help on this topic> + + + ======= h_thread_index_sort_from ======= + + + SORT OPTION: From + + +

    SORT OPTION: From

    + + The From sort option has not been defined yet. + +

    + <End of help on this topic> + + + ======= h_thread_index_sort_size ======= + + + SORT OPTION: Size + + +

    SORT OPTION: Size

    + + The Size sort option has not been defined yet. + +

    + <End of help on this topic> + + + ======= h_thread_index_sort_score ======= + + + SORT OPTION: Score + + +

    SORT OPTION: Score

    + + The Score sort option has not been defined yet. + +

    + <End of help on this topic> + + + ======= h_thread_index_sort_to ======= + + + SORT OPTION: To + + +

    SORT OPTION: To

    + + The To sort option has not been defined yet. + +

    + <End of help on this topic> + + + ======= h_thread_index_sort_cc ======= + + + SORT OPTION: Cc + + +

    SORT OPTION: Cc

    + + The Cc sort option has not been defined yet. + +

    + <End of help on this topic> + + ======= h_index_cmd_whereis ======= *************** *** 16831,16836 **** --- 16985,16998 ----

    +

    SIZETHREAD
    +
    + This token represents the total size of the thread for a collapsed thread + or the size of the branch for an expanded thread. The field is omitted for + messages that are not top of threads nor branches and it defaults to + the SIZE token when your folders is not sorted by thread. +
    +
    SIZENARROW
    This token represents the total size, in bytes, of the message. *************** *** 19525,19530 **** --- 19687,19727 ---- <End of help on this topic> + ====== h_config_thread_sort_key ===== + + + OPTION: Thread-Sort-Key + + +

    OPTION: Thread-Sort-Key

    + + This option determines the order in which threads will be displayed. You + can choose from the following options. + +

    +

    + +

    Each type of sort may also be reversed. Normal default is by + "Thread". + +

    +

    + <End of help on this topic> + + ====== h_config_other_startup ===== *************** *** 25934,25939 **** --- 26131,26153 ---- <End of help on this topic> + ====== h_config_enhanced_thread ===== + + + FEATURE: enhanced-fancy-thread-support + + +

    FEATURE: enhanced-fancy-thread-support

    + + If this option is set certain commands in Pine will operate in loose + threads too. For example, the command ^D marks a thread deleted, but if + this feature is set, it will remove all threads that share the same missing + parent with this thread. + +

    + <End of help on this topic> + + ====== h_config_news_cross_deletes ===== diff -rc pine4.61/pine/strings.c pine4.61.fancy/pine/strings.c *** pine4.61/pine/strings.c Wed Jul 14 15:15:10 2004 --- pine4.61.fancy/pine/strings.c Thu Aug 19 13:18:13 2004 *************** *** 5935,5941 **** SortOrder def_sort; int def_sort_rev; ! if(decode_sort(p, &def_sort, &def_sort_rev) != -1){ action->sort_is_set = 1; action->sortorder = def_sort; action->revsort = (def_sort_rev ? 1 : 0); --- 5935,5941 ---- SortOrder def_sort; int def_sort_rev; ! if(decode_sort(p, &def_sort, &def_sort_rev, 0) != -1){ action->sort_is_set = 1; action->sortorder = def_sort; action->revsort = (def_sort_rev ? 1 : 0);