2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/alpine/arg.c
===================================================================
*** alpine-2.23.2.orig/alpine/arg.c
--- alpine-2.23.2/alpine/arg.c
*************** static char args_err_non_abs_pwdcertdir[
2017-04-12 17:37:46 +02:00
*** 68,73 ****
--- 68,74 ----
#endif /* SMIME inside PASSFILE */
#endif
static char args_err_missing_sort[] = N_("missing argument for option \"-sort\"");
+ static char args_err_missing_thread_sort[] = N_("missing argument for option \"-threadsort\"");
static char args_err_missing_flag_arg[] = N_("missing argument for flag \"%c\"");
static char args_err_missing_flag_num[] = N_("Non numeric argument for flag \"%c\"");
static char args_err_missing_debug_num[] = N_("Non numeric argument for \"%s\"");
2020-10-05 19:41:16 +02:00
*************** N_(" -k \t\tKeys - Force use of function
*** 116,121 ****
--- 117,123 ----
2017-04-12 17:37:46 +02:00
N_(" -z \t\tSuspend - allow use of ^Z suspension"),
N_(" -r \t\tRestricted - can only send mail to oneself"),
N_(" -sort <sort>\tSort - Specify sort order of folder:"),
+ N_(" -threadsort <sort>\tSort - Specify sort order of thread index screen:"),
N_("\t\t\tarrival, subject, threaded, orderedsubject, date,"),
N_("\t\t\tfrom, size, score, to, cc, /reverse"),
N_(" -i\t\tIndex - Go directly to index, bypassing main menu"),
2020-10-05 19:41:16 +02:00
*************** pine_args(struct pine *pine_state, int a
*** 217,222 ****
--- 219,225 ----
2017-04-12 17:37:46 +02:00
char *cmd_list = NULL;
char *debug_str = NULL;
char *sort = NULL;
+ char *threadsort = NULL;
char *pinerc_file = NULL;
char *lc = NULL;
2020-10-05 19:41:16 +02:00
XOAUTH2_INFO_S x;
*************** Loop: while(--ac > 0)
*** 440,445 ****
--- 443,459 ----
2017-04-12 17:37:46 +02:00
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;
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/alpine/confscroll.c
===================================================================
*** alpine-2.23.2.orig/alpine/confscroll.c
--- alpine-2.23.2/alpine/confscroll.c
*************** char *yesno_pretty_value(struct pine
*** 140,146 ****
2017-04-12 17:37:46 +02:00
char *radio_pretty_value(struct pine *, CONF_S *);
char *sigfile_pretty_value(struct pine *, CONF_S *);
char *color_pretty_value(struct pine *, CONF_S *);
! char *sort_pretty_value(struct pine *, CONF_S *);
int longest_feature_name(void);
COLOR_PAIR *sample_color(struct pine *, struct variable *);
COLOR_PAIR *sampleexc_color(struct pine *, struct variable *);
2020-10-05 19:41:16 +02:00
--- 140,146 ----
2017-04-12 17:37:46 +02:00
char *radio_pretty_value(struct pine *, CONF_S *);
char *sigfile_pretty_value(struct pine *, CONF_S *);
char *color_pretty_value(struct pine *, CONF_S *);
! char *sort_pretty_value(struct pine *, CONF_S *, int);
int longest_feature_name(void);
COLOR_PAIR *sample_color(struct pine *, struct variable *);
COLOR_PAIR *sampleexc_color(struct pine *, struct variable *);
2020-10-05 19:41:16 +02:00
*************** set_radio_pretty_vals(struct pine *ps, C
*** 288,294 ****
2017-04-12 17:37:46 +02:00
CONF_S *ctmp;
if(!(cl && *cl &&
! ((*cl)->var == &ps->vars[V_SORT_KEY] ||
standard_radio_var(ps, (*cl)->var) ||
(*cl)->var == startup_ptr)))
return;
2020-10-05 19:41:16 +02:00
--- 288,295 ----
2017-04-12 17:37:46 +02:00
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;
2020-10-05 19:41:16 +02:00
*************** radiobutton_tool(struct pine *ps, int cm
*** 2960,2966 ****
2017-04-12 17:37:46 +02:00
}
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;
}
2020-10-05 19:41:16 +02:00
--- 2961,2967 ----
2017-04-12 17:37:46 +02:00
}
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;
}
2020-10-05 19:41:16 +02:00
*************** radiobutton_tool(struct pine *ps, int cm
*** 2969,2974 ****
--- 2970,3006 ----
2017-04-12 17:37:46 +02:00
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.");
2020-10-05 19:41:16 +02:00
*************** pretty_value(struct pine *ps, CONF_S *cl
*** 3832,3838 ****
2017-04-12 17:37:46 +02:00
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])
2020-10-05 19:41:16 +02:00
--- 3864,3872 ----
2017-04-12 17:37:46 +02:00
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])
2020-10-05 19:41:16 +02:00
*************** color_pretty_value(struct pine *ps, CONF
*** 4363,4376 ****
2017-04-12 17:37:46 +02:00
char *
! sort_pretty_value(struct pine *ps, CONF_S *cl)
{
! return(generalized_sort_pretty_value(ps, cl, 1));
}
char *
! generalized_sort_pretty_value(struct pine *ps, CONF_S *cl, int default_ok)
{
char tmp[6*MAXPATH];
char *pvalnorm, *pvalexc, *pval;
2020-10-05 19:41:16 +02:00
--- 4397,4410 ----
2017-04-12 17:37:46 +02:00
char *
! sort_pretty_value(struct pine *ps, CONF_S *cl, int thread)
{
! return(generalized_sort_pretty_value(ps, cl, 1, thread));
}
char *
! generalized_sort_pretty_value(struct pine *ps, CONF_S *cl, int default_ok, int thread)
{
char tmp[6*MAXPATH];
char *pvalnorm, *pvalexc, *pval;
2020-10-05 19:41:16 +02:00
*************** generalized_sort_pretty_value(struct pin
*** 4420,4426 ****
2017-04-12 17:37:46 +02:00
}
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);
utf8_snprintf(tmp, sizeof(tmp), "(%c) %s%-*w%*s%s",
2020-10-05 19:41:16 +02:00
--- 4454,4460 ----
2017-04-12 17:37:46 +02:00
}
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);
utf8_snprintf(tmp, sizeof(tmp), "(%c) %s%-*w%*s%s",
2020-10-05 19:41:16 +02:00
*************** generalized_sort_pretty_value(struct pin
*** 4431,4439 ****
2017-04-12 17:37:46 +02:00
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);
utf8_snprintf(tmp, sizeof(tmp), "(%c) %s%-*w%*s%s",
2020-10-05 19:41:16 +02:00
--- 4465,4473 ----
2017-04-12 17:37:46 +02:00
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);
utf8_snprintf(tmp, sizeof(tmp), "(%c) %s%-*w%*s%s",
2020-10-05 19:41:16 +02:00
*************** generalized_sort_pretty_value(struct pin
*** 4451,4457 ****
2017-04-12 17:37:46 +02:00
}
else{
if(pvalexc){
! decode_sort(pvalexc, &exc_sort, &exc_sort_rev);
is_the_one = (exc_sort_rev == line_sort_rev &&
exc_sort == line_sort);
utf8_snprintf(tmp, sizeof(tmp), "( ) %s%-*w%*s%s",
2020-10-05 19:41:16 +02:00
--- 4485,4491 ----
2017-04-12 17:37:46 +02:00
}
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);
utf8_snprintf(tmp, sizeof(tmp), "( ) %s%-*w%*s%s",
2020-10-05 19:41:16 +02:00
*************** generalized_sort_pretty_value(struct pin
*** 4462,4468 ****
2017-04-12 17:37:46 +02:00
}
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);
2020-10-05 19:41:16 +02:00
--- 4496,4502 ----
2017-04-12 17:37:46 +02:00
}
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);
2020-10-05 19:41:16 +02:00
*************** fix_side_effects(struct pine *ps, struct
*** 5621,5629 ****
2017-04-12 17:37:46 +02:00
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]){
2020-10-05 19:41:16 +02:00
--- 5655,5669 ----
2017-04-12 17:37:46 +02:00
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]){
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/alpine/confscroll.h
===================================================================
*** alpine-2.23.2.orig/alpine/confscroll.h
--- alpine-2.23.2/alpine/confscroll.h
*************** int checkbox_tool(struct pine *, int, C
2017-04-12 17:37:46 +02:00
*** 97,103 ****
int radiobutton_tool(struct pine *, int, CONF_S **, unsigned);
int yesno_tool(struct pine *, int, CONF_S **, unsigned);
int text_toolit(struct pine *, int, CONF_S **, unsigned, int);
! char *generalized_sort_pretty_value(struct pine *, CONF_S *, int);
int exclude_config_var(struct pine *, struct variable *, int);
int config_exit_cmd(unsigned);
int simple_exit_cmd(unsigned);
--- 97,103 ----
int radiobutton_tool(struct pine *, int, CONF_S **, unsigned);
int yesno_tool(struct pine *, int, CONF_S **, unsigned);
int text_toolit(struct pine *, int, CONF_S **, unsigned, int);
! char *generalized_sort_pretty_value(struct pine *, CONF_S *, int, int);
int exclude_config_var(struct pine *, struct variable *, int);
int config_exit_cmd(unsigned);
int simple_exit_cmd(unsigned);
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/alpine/keymenu.c
===================================================================
*** alpine-2.23.2.orig/alpine/keymenu.c
--- alpine-2.23.2/alpine/keymenu.c
*************** struct key index_keys[] =
2020-09-08 22:48:40 +02:00
*** 679,688 ****
2017-04-12 17:37:46 +02:00
RCOMPOSE_MENU,
HOMEKEY_MENU,
ENDKEY_MENU,
! NULL_MENU,
/* TRANSLATORS: toggles a collapsed view or an expanded view
of a message thread on and off */
{"/",N_("Collapse/Expand"),{MC_COLLAPSE,1,{'/'}},KS_NONE},
{"@", N_("Quota"), {MC_QUOTA,1,{'@'}}, KS_NONE},
NULL_MENU};
INST_KEY_MENU(index_keymenu, index_keys);
2020-09-08 22:48:40 +02:00
--- 679,703 ----
2017-04-12 17:37:46 +02:00
RCOMPOSE_MENU,
HOMEKEY_MENU,
ENDKEY_MENU,
! {"K","Sort Thread",{MC_SORTHREAD,1,{'k'}},KS_NONE},
/* TRANSLATORS: toggles a collapsed view or an expanded view
of a message thread on and off */
{"/",N_("Collapse/Expand"),{MC_COLLAPSE,1,{'/'}},KS_NONE},
+ /* TRANSLATORS: Collapse all threads */
+ {"{",N_("Collapse All"),{MC_KOLAPSE,1,{'{'}},KS_NONE},
+ /* TRANSLATORS: Expand all threads */
+ {"}",N_("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},
+ {"^R","Remove Thr",{MC_DELTHREAD,1,{ctrl('r')}},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},
{"@", N_("Quota"), {MC_QUOTA,1,{'@'}}, KS_NONE},
NULL_MENU};
INST_KEY_MENU(index_keymenu, index_keys);
2020-10-05 19:41:16 +02:00
*************** struct key thread_keys[] =
2020-09-08 22:48:40 +02:00
*** 757,765 ****
2017-04-12 17:37:46 +02:00
RCOMPOSE_MENU,
HOMEKEY_MENU,
ENDKEY_MENU,
! NULL_MENU,
{"/",N_("Collapse/Expand"),{MC_COLLAPSE,1,{'/'}},KS_NONE},
{"@", N_("Quota"), {MC_QUOTA,1,{'@'}}, KS_NONE},
NULL_MENU};
INST_KEY_MENU(thread_keymenu, thread_keys);
2020-09-08 22:48:40 +02:00
--- 772,793 ----
2017-04-12 17:37:46 +02:00
RCOMPOSE_MENU,
HOMEKEY_MENU,
ENDKEY_MENU,
! {"]",N_("Open Thread"),{MC_OTHREAD,1,{']'}},KS_NONE},
{"/",N_("Collapse/Expand"),{MC_COLLAPSE,1,{'/'}},KS_NONE},
+ {")",N_("Next Thread"),{MC_NEXTHREAD,1,{')'}},KS_NONE},
+ {"(",N_("Prev Thread"),{MC_PRETHREAD,1,{'('}},KS_NONE},
+
+ HELP_MENU,
+ OTHER_MENU,
{"@", N_("Quota"), {MC_QUOTA,1,{'@'}}, KS_NONE},
+ NULL_MENU,
+ {"^R",N_("Remove Thread"),{MC_DELTHREAD,1,{ctrl('r')}},KS_NONE},
+ {"^U",N_("Undelete Thread"),{MC_UNDTHREAD,1,{ctrl('u')}},KS_NONE},
+ {"^T",N_("SelecT Thread"),{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);
2020-10-05 19:41:16 +02:00
*************** struct key view_keys[] =
2020-09-08 22:48:40 +02:00
*** 927,933 ****
2017-04-12 17:37:46 +02:00
NULL_MENU,
NULL_MENU,
NULL_MENU,
! NULL_MENU};
INST_KEY_MENU(view_keymenu, view_keys);
2020-09-08 22:48:40 +02:00
--- 955,974 ----
2017-04-12 17:37:46 +02:00
NULL_MENU,
NULL_MENU,
NULL_MENU,
! NULL_MENU,
!
! HELP_MENU,
! OTHER_MENU,
! NULL_MENU,
! NULL_MENU,
! NULL_MENU,
! NULL_MENU,
! NULL_MENU,
! {"(",N_("Prev Thread"),{MC_PRETHREAD,1,{'('}},KS_NONE},
! {")",N_("Next Thread"),{MC_NEXTHREAD,1,{')'}},KS_NONE},
! {"^R",N_("Remove Thread"),{MC_DELTHREAD,1,{ctrl('r')}},KS_NONE},
! {"^U",N_("Undelete Thread"),{MC_UNDTHREAD,1,{ctrl('u')}},KS_NONE},
! {"^T",N_("selecT Thread"),{MC_SELTHREAD,1,{ctrl('t')}},KS_NONE}};
INST_KEY_MENU(view_keymenu, view_keys);
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/alpine/keymenu.h
===================================================================
*** alpine-2.23.2.orig/alpine/keymenu.h
--- alpine-2.23.2/alpine/keymenu.h
*************** struct key_menu {
*** 217,225 ****
2017-04-12 17:37:46 +02:00
#define MC_ADDHEADER 804
2020-05-12 22:34:54 +02:00
#define MC_XOAUTH2 805
2020-09-08 22:48:40 +02:00
#define MC_EXTERNAL 806
2020-10-05 19:41:16 +02:00
! #define MC_XSADD 807
! #define MC_XSDELETE 808
! #define MC_XSHELP 809
2017-04-12 17:37:46 +02:00
2020-10-05 19:41:16 +02:00
/* Commands for S/MIME screens */
#define MC_TRUST 900
--- 217,238 ----
#define MC_ADDHEADER 804
#define MC_XOAUTH2 805
#define MC_EXTERNAL 806
! #define MC_DELTHREAD 807
! #define MC_UNDTHREAD 808
! #define MC_SELTHREAD 809
! #define MC_SSUTHREAD 810
! #define MC_DSUTHREAD 811
! #define MC_USUTHREAD 812
! #define MC_SORTHREAD 813
! #define MC_NEXTHREAD 814
! #define MC_KOLAPSE 815
! #define MC_EXPTHREAD 816
! #define MC_PRETHREAD 817
! #define MC_CTHREAD 818
! #define MC_OTHREAD 819
! #define MC_XSADD 820
! #define MC_XSDELETE 821
! #define MC_XSHELP 822
2017-04-12 17:37:46 +02:00
/* Commands for S/MIME screens */
2020-10-05 19:41:16 +02:00
#define MC_TRUST 900
Index: alpine-2.23.2/alpine/mailcmd.c
===================================================================
*** alpine-2.23.2.orig/alpine/mailcmd.c
--- alpine-2.23.2/alpine/mailcmd.c
*************** int select_by_thread(MAILSTREAM *, MSG
2020-05-12 22:34:54 +02:00
*** 114,120 ****
2017-04-12 17:37:46 +02:00
char *choose_a_rule(int);
int select_by_keyword(MAILSTREAM *, SEARCHSET **);
char *choose_a_keyword(void);
! int select_sort(struct pine *, int, SortOrder *, int *);
int print_index(struct pine *, MSGNO_S *, int);
/*
2020-05-12 22:34:54 +02:00
--- 114,120 ----
2017-04-12 17:37:46 +02:00
char *choose_a_rule(int);
int select_by_keyword(MAILSTREAM *, SEARCHSET **);
char *choose_a_keyword(void);
! int select_sort(struct pine *, int, SortOrder *, int *, int);
int print_index(struct pine *, MSGNO_S *, int);
/*
2020-10-05 19:41:16 +02:00
*************** get_out:
*** 1435,1441 ****
2017-04-12 17:37:46 +02:00
if(any_messages(msgmap, NULL, NULL)){
if(any_lflagged(msgmap, MN_SLCT) > 0L){
if(apply_command(state, stream, msgmap, 0,
! AC_NONE, question_line)){
if(F_ON(F_AUTO_UNSELECT, state)){
agg_select_all(stream, msgmap, NULL, 0);
unzoom_index(state, stream, msgmap);
2020-10-05 19:41:16 +02:00
--- 1435,1441 ----
2017-04-12 17:37:46 +02:00
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)){
if(F_ON(F_AUTO_UNSELECT, state)){
agg_select_all(stream, msgmap, NULL, 0);
unzoom_index(state, stream, msgmap);
2020-10-05 19:41:16 +02:00
*************** get_out:
*** 1453,1475 ****
2017-04-12 17:37:46 +02:00
/*-------- Sort command -------*/
case MC_SORT :
{
int were_threading = THREADING();
SortOrder sort = mn_get_sort(msgmap);
int rev = mn_get_revsort(msgmap);
dprint((1,"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);
if(ps_global && ps_global->ttyo){
blank_keymenu(ps_global->ttyo->screen_rows - 2, 0);
ps_global->mangled_footer = 1;
}
! sort_folder(stream, msgmap, sort, rev, SRT_VRB|SRT_MAN);
}
state->mangled_footer = 1;
2020-10-05 19:41:16 +02:00
--- 1453,1487 ----
2017-04-12 17:37:46 +02:00
/*-------- 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;
dprint((1,"MAIL_CMD: sort\n"));
! if(sort == SortThread)
! sort = ps_global->thread_cur_sort;
! 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 = SortThread;
+ }
+ else if(sort == SortThread) /* command = MC_SORT */
+ ps_global->thread_cur_sort = F_ON(F_THREAD_SORTS_BY_ARRIVAL, ps_global)
+ ? SortArrival : ps_global->thread_def_sort;
+
if(ps_global && ps_global->ttyo){
blank_keymenu(ps_global->ttyo->screen_rows - 2, 0);
ps_global->mangled_footer = 1;
}
! sort_folder(stream, msgmap, sort, rev, SRT_VRB|SRT_MAN, 1);
}
state->mangled_footer = 1;
2020-10-05 19:41:16 +02:00
*************** cmd_expunge(struct pine *state, MAILSTRE
*** 3314,3319 ****
--- 3326,3335 ----
2017-04-12 17:37:46 +02:00
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,
2020-10-05 19:41:16 +02:00
*************** cmd_expunge(struct pine *state, MAILSTRE
*** 3415,3420 ****
--- 3431,3439 ----
2017-04-12 17:37:46 +02:00
*/
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){
2020-10-05 19:41:16 +02:00
*************** select_by_current(struct pine *state, MS
*** 7324,7330 ****
2017-04-12 17:37:46 +02:00
* Maybe it makes sense to zoom after a select but not after a colon
* command even though they are very similar.
*/
! thread_command(state, state->mail_stream, msgmap, ':', -FOOTER_ROWS(state));
}
else{
if((all_selected =
2020-10-05 19:41:16 +02:00
--- 7343,7349 ----
2017-04-12 17:37:46 +02:00
* Maybe it makes sense to zoom after a select but not after a colon
* command even though they are very similar.
*/
! thread_command(state, state->mail_stream, msgmap, ':', -FOOTER_ROWS(state), 1);
}
else{
if((all_selected =
2020-10-05 19:41:16 +02:00
*************** select_by_current(struct pine *state, MS
*** 7380,7386 ****
2017-04-12 17:37:46 +02:00
----*/
int
apply_command(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap,
! UCS preloadkeystroke, int flags, int q_line)
{
int i = 8, /* number of static entries in sel_opts3 */
rv = 0,
2020-10-05 19:41:16 +02:00
--- 7399,7405 ----
2017-04-12 17:37:46 +02:00
----*/
int
apply_command(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap,
! UCS preloadkeystroke, int flags, int q_line, int display)
{
int i = 8, /* number of static entries in sel_opts3 */
rv = 0,
2020-10-05 19:41:16 +02:00
*************** apply_command(struct pine *state, MAILST
*** 7547,7555 ****
2017-04-12 17:37:46 +02:00
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;
2020-10-05 19:41:16 +02:00
--- 7566,7584 ----
2017-04-12 17:37:46 +02:00
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;
2020-10-05 19:41:16 +02:00
*************** Args: state -- pine state pointer
*** 9595,9604 ****
2017-04-12 17:37:46 +02:00
Returns 0 if it was cancelled, 1 otherwise.
----*/
int
! select_sort(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];
2020-10-05 19:41:16 +02:00
--- 9624,9633 ----
2017-04-12 17:37:46 +02:00
Returns 0 if it was cancelled, 1 otherwise.
----*/
int
! select_sort(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];
2020-10-05 19:41:16 +02:00
*************** select_sort(struct pine *state, int ql,
*** 9631,9647 ****
2017-04-12 17:37:46 +02:00
strncpy(prompt, _("Choose type of sort, or 'R' to reverse current sort : "),
sizeof(prompt));
! 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);
2020-05-12 22:34:54 +02:00
2017-04-12 17:37:46 +02:00
! if(mn_get_sort(state->msgmap) == state->sort_types[i])
! deefault = sorts[i].rval;
}
sorts[i].ch = 'r';
2020-10-05 19:41:16 +02:00
--- 9660,9685 ----
2017-04-12 17:37:46 +02:00
strncpy(prompt, _("Choose type of sort, or 'R' to reverse current sort : "),
sizeof(prompt));
! 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 || allowed_thread_key(state->sort_types[i])){
! 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);
! }
2020-05-12 22:34:54 +02:00
2017-04-12 17:37:46 +02:00
! 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';
2020-10-05 19:41:16 +02:00
*************** select_sort(struct pine *state, int ql,
*** 9665,9672 ****
2017-04-12 17:37:46 +02:00
state->mangled_body = 1; /* signal screen's changed */
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;
2020-10-05 19:41:16 +02:00
--- 9703,9719 ----
2017-04-12 17:37:46 +02:00
state->mangled_body = 1; /* signal screen's changed */
if(s == 'r')
*rev = !mn_get_revsort(state->msgmap);
! else{
! if(thread){
! for(i = 0; state->sort_types[i] != EndofList; i++){
! if(struncmp(sort_name(state->sort_types[i]),
! sorts[s].label, strlen(sorts[s].label)) == 0)
! break;
! }
! s = i;
! }
*sort = state->sort_types[s];
+ }
if(F_ON(F_SHOW_SORT, ps_global))
ps_global->mangled_header = 1;
2020-10-05 19:41:16 +02:00
*************** flag_submenu(mc)
*** 10050,10052 ****
--- 10097,10474 ----
2017-04-12 17:37:46 +02:00
}
#endif /* _WINDOWS */
+
+ 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, MCMD_NONE, cmd_delete_index);
+ count = count_thread(state, stream, msgmap, rawno);
+ q_status_message2(SM_ORDER, 0, 1, "%s message%s marked deleted",
+ int2string(count), plural(count));
+ }
+
+ 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(stream, rawno, 0);
+
+ 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);
2013-05-27 09:31:30 +02:00
+ }
+ }
2013-10-22 11:53:24 +02:00
+ else{
2017-04-12 17:37:46 +02:00
+ 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");
+ }
2013-05-27 09:31:30 +02:00
+ }
2017-04-12 17:37:46 +02:00
+ 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(stream, rawno, 0);
+
+ 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(stream, 0);
+ 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)));
+ }
+
+ 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);
+ }
+
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/alpine/mailcmd.h
===================================================================
*** alpine-2.23.2.orig/alpine/mailcmd.h
--- alpine-2.23.2/alpine/mailcmd.h
*************** char *broach_folder(int, int, int *,
2017-04-12 17:37:46 +02:00
*** 90,96 ****
int ask_mailbox_reopen(struct pine *, int *);
void visit_folder(struct pine *, char *, CONTEXT_S *, MAILSTREAM *, unsigned long);
int select_by_current(struct pine *, MSGNO_S *, CmdWhere);
! int apply_command(struct pine *, MAILSTREAM *, MSGNO_S *, UCS, int, int);
char **choose_list_of_keywords(void);
char *choose_a_charset(int);
char **choose_list_of_charsets(void);
--- 90,96 ----
int ask_mailbox_reopen(struct pine *, int *);
void visit_folder(struct pine *, char *, CONTEXT_S *, MAILSTREAM *, unsigned long);
int select_by_current(struct pine *, MSGNO_S *, CmdWhere);
! int apply_command(struct pine *, MAILSTREAM *, MSGNO_S *, UCS, int, int, int);
char **choose_list_of_keywords(void);
char *choose_a_charset(int);
char **choose_list_of_charsets(void);
2020-10-05 19:41:16 +02:00
*************** int any_selected_callback(int, long)
2017-04-12 17:37:46 +02:00
*** 108,113 ****
int flag_callback(int, long);
MPopup *flag_submenu(MESSAGECACHE *);
#endif
!
#endif /* PINE_MAILCMD_INCLUDED */
--- 108,122 ----
int flag_callback(int, long);
MPopup *flag_submenu(MESSAGECACHE *);
#endif
! void cmd_delete_thread(struct pine *, MAILSTREAM *, MSGNO_S *);
! void cmd_delete_this_thread(struct pine *, MAILSTREAM *, MSGNO_S *);
! void cmd_undelete_this_thread(struct pine *, MAILSTREAM *, MSGNO_S *);
! void cmd_undelete_thread(struct pine *, MAILSTREAM *, MSGNO_S *);
! void cmd_select_thread(struct pine *, MAILSTREAM *, MSGNO_S *);
! void kolapse_thread(struct pine *, MAILSTREAM *, MSGNO_S *, char, int);
! void collapse_thread(struct pine *, MAILSTREAM *, MSGNO_S *, int);
! void expand_thread(struct pine *, MAILSTREAM *, MSGNO_S *, int);
! int collapse_this_thread(struct pine *, MAILSTREAM *, MSGNO_S *, int, int);
! int expand_this_thread(struct pine *, MAILSTREAM *, MSGNO_S *, int, int);
#endif /* PINE_MAILCMD_INCLUDED */
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/alpine/mailindx.c
===================================================================
*** alpine-2.23.2.orig/alpine/mailindx.c
--- alpine-2.23.2/alpine/mailindx.c
*************** index_lister(struct pine *state, CONTEXT
2017-04-12 17:37:46 +02:00
*** 564,569 ****
--- 564,570 ----
/*---------- Scroll line up ----------*/
case MC_CHARUP :
+ previtem:
(void) process_cmd(state, stream, msgmap, MC_PREVITEM,
(style == MsgIndex
|| style == MultiMsgIndex
2020-10-05 19:41:16 +02:00
*************** index_lister(struct pine *state, CONTEXT
2017-04-12 17:37:46 +02:00
*** 581,586 ****
--- 582,588 ----
/*---------- Scroll line down ----------*/
case MC_CHARDOWN :
+ nextitem:
/*
* Special Page framing handling here. If we
* did something that should scroll-by-a-line, frame
2020-10-05 19:41:16 +02:00
*************** view_a_thread:
2017-04-12 17:37:46 +02:00
*** 798,803 ****
--- 800,806 ----
case MC_THRDINDX :
+ mc_thrdindx:
if(any_lflagged(msgmap, MN_SLCT)){
PINETHRD_S *thrd, *topthrd;
for(i = 1L; i > 0L && i <= mn_get_total(msgmap);){
2020-10-05 19:41:16 +02:00
*************** view_a_thread:
2017-04-12 17:37:46 +02:00
*** 863,869 ****
&& 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){
--- 866,872 ----
&& 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){
2020-10-05 19:41:16 +02:00
*************** view_a_thread:
2017-04-12 17:37:46 +02:00
*** 972,980 ****
case MC_COLLAPSE :
! thread_command(state, stream, msgmap, ch, -FOOTER_ROWS(state));
break;
case MC_DELETE :
case MC_UNDELETE :
case MC_REPLY :
--- 975,1079 ----
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 :
2020-10-05 19:41:16 +02:00
*************** view_a_thread:
2017-04-12 17:37:46 +02:00
*** 995,1007 ****
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,
--- 1094,1105 ----
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,
2020-10-05 19:41:16 +02:00
*************** top_ent_calc(MAILSTREAM *stream, MSGNO_S
2017-04-12 17:37:46 +02:00
*** 2692,2697 ****
--- 2790,2796 ----
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;
2020-10-05 19:41:16 +02:00
*************** top_ent_calc(MAILSTREAM *stream, MSGNO_S
2017-04-12 17:37:46 +02:00
*** 2760,2770 ****
/* 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;
}
--- 2859,2870 ----
/* 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;
}
2020-10-05 19:41:16 +02:00
*************** warn_other_cmds(void)
2017-04-12 17:37:46 +02:00
*** 2872,2878 ****
void
thread_command(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap,
! UCS preloadkeystroke, int q_line)
{
PINETHRD_S *thrd = NULL;
unsigned long rawno, save_branch;
--- 2972,2978 ----
void
thread_command(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap,
! UCS preloadkeystroke, int q_line, int display)
{
PINETHRD_S *thrd = NULL;
unsigned long rawno, save_branch;
2020-10-05 19:41:16 +02:00
*************** thread_command(struct pine *state, MAILS
2017-04-12 17:37:46 +02:00
*** 2921,2927 ****
cancel_busy_cue(0);
(void ) apply_command(state, stream, msgmap, preloadkeystroke, flags,
! q_line);
/* restore the original flags */
copy_lflags(stream, msgmap, MN_STMP, MN_SLCT);
--- 3021,3027 ----
cancel_busy_cue(0);
(void ) apply_command(state, stream, msgmap, preloadkeystroke, flags,
! q_line, display);
/* restore the original flags */
copy_lflags(stream, msgmap, MN_STMP, MN_SLCT);
2020-10-05 19:41:16 +02:00
*************** index_sort_callback(set, order)
2020-05-12 22:34:54 +02:00
*** 3438,3444 ****
2017-04-12 17:37:46 +02:00
if(set){
sort_folder(ps_global->mail_stream, ps_global->msgmap,
order & 0x000000ff,
! (order & 0x00000100) != 0, SRT_VRB);
mswin_beginupdate();
update_titlebar_message();
update_titlebar_status();
2020-05-12 22:34:54 +02:00
--- 3538,3544 ----
2017-04-12 17:37:46 +02:00
if(set){
sort_folder(ps_global->mail_stream, ps_global->msgmap,
order & 0x000000ff,
! (order & 0x00000100) != 0, SRT_VRB, 1);
mswin_beginupdate();
update_titlebar_message();
update_titlebar_status();
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/alpine/mailindx.h
===================================================================
*** alpine-2.23.2.orig/alpine/mailindx.h
--- alpine-2.23.2/alpine/mailindx.h
*************** int truncate_subj_and_from_strings(voi
2017-04-12 17:37:46 +02:00
*** 103,109 ****
void paint_index_hline(MAILSTREAM *, long, ICE_S *);
void setup_index_state(int);
void warn_other_cmds(void);
! void thread_command(struct pine *, MAILSTREAM *, MSGNO_S *, UCS, int);
COLOR_PAIR *apply_rev_color(COLOR_PAIR *, int);
#ifdef _WINDOWS
int index_sort_callback(int, long);
--- 103,109 ----
void paint_index_hline(MAILSTREAM *, long, ICE_S *);
void setup_index_state(int);
void warn_other_cmds(void);
! void thread_command(struct pine *, MAILSTREAM *, MSGNO_S *, UCS, int, int);
COLOR_PAIR *apply_rev_color(COLOR_PAIR *, int);
#ifdef _WINDOWS
int index_sort_callback(int, long);
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/alpine/mailview.c
===================================================================
*** alpine-2.23.2.orig/alpine/mailview.c
--- alpine-2.23.2/alpine/mailview.c
*************** scrolltool(SCROLL_S *sparms)
2020-09-08 22:48:40 +02:00
*** 3495,3500 ****
--- 3495,3546 ----
2017-04-12 17:37:46 +02:00
print_to_printer(sparms);
break;
+ case MC_NEXTHREAD:
+ case MC_PRETHREAD:
2013-05-27 09:31:30 +02:00
+ if (THREADING()){
2013-10-22 11:53:24 +02:00
+ if (any_messages(ps_global->msgmap, NULL,
2017-04-12 17:37:46 +02:00
+ "to move to other thread"))
+ move_thread(ps_global, ps_global->mail_stream, ps_global->msgmap,
+ cmd == MC_NEXTHREAD ? 1 : -1);
+ done = 1;
2013-05-27 09:31:30 +02:00
+ }
+ else
2017-04-12 17:37:46 +02:00
+ 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;
2013-05-27 09:31:30 +02:00
+ }
2017-04-12 17:37:46 +02:00
+ 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;
2013-05-27 09:31:30 +02:00
+ }
2017-04-12 17:37:46 +02:00
+ else
+ q_status_message(SM_ORDER, 0, 1,
+ "Command available in threaded mode only");
+ break;
/* ------- First handle on Line ------ */
case MC_GOTOBOL :
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/alpine/roleconf.c
===================================================================
*** alpine-2.23.2.orig/alpine/roleconf.c
--- alpine-2.23.2/alpine/roleconf.c
*************** role_config_edit_screen(struct pine *ps,
2017-04-12 17:37:46 +02:00
*** 4478,4488 ****
ctmp->tool = role_sort_tool;
ctmp->valoffset = rindent;
ctmp->flags |= CF_NOSELECT;
! ctmp->value = cpystr(set_choose); \
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;
--- 4478,4488 ----
ctmp->tool = role_sort_tool;
ctmp->valoffset = rindent;
ctmp->flags |= CF_NOSELECT;
! ctmp->value = cpystr(set_choose);
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;
2020-10-05 19:41:16 +02:00
*************** role_config_edit_screen(struct pine *ps,
2017-04-12 17:37:46 +02:00
*** 4492,4498 ****
ctmp->tool = role_sort_tool;
ctmp->valoffset = rindent;
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++){
--- 4492,4498 ----
ctmp->tool = role_sort_tool;
ctmp->valoffset = rindent;
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++){
2020-10-05 19:41:16 +02:00
*************** role_config_edit_screen(struct pine *ps,
2017-04-12 17:37:46 +02:00
*** 4504,4510 ****
ctmp->valoffset = rindent;
ctmp->varmem = i + (j * EndofList);
ctmp->value = generalized_sort_pretty_value(ps, ctmp,
! 0);
}
}
--- 4504,4510 ----
ctmp->valoffset = rindent;
ctmp->varmem = i + (j * EndofList);
ctmp->value = generalized_sort_pretty_value(ps, ctmp,
! 0, 0);
}
}
2020-10-05 19:41:16 +02:00
*************** role_config_edit_screen(struct pine *ps,
2017-04-12 17:37:46 +02:00
*** 5437,5443 ****
(*result)->patgrp->stat_boy = 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);
--- 5437,5443 ----
(*result)->patgrp->stat_boy = 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);
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/alpine/setup.c
===================================================================
*** alpine-2.23.2.orig/alpine/setup.c
--- alpine-2.23.2/alpine/setup.c
*************** option_screen(struct pine *ps, int edit_
2017-04-12 17:37:46 +02:00
*** 262,268 ****
ctmpa->flags |= CF_NOSELECT;
ctmpa->value = cpystr("--- ----------------------");
! decode_sort(pval, &def_sort, &def_sort_rev);
for(j = 0; j < 2; j++){
for(i = 0; ps->sort_types[i] != EndofList; i++){
--- 262,268 ----
ctmpa->flags |= CF_NOSELECT;
ctmpa->value = cpystr("--- ----------------------");
! decode_sort(pval, &def_sort, &def_sort_rev, 0);
for(j = 0; j < 2; j++){
for(i = 0; ps->sort_types[i] != EndofList; i++){
2020-10-05 19:41:16 +02:00
*************** option_screen(struct pine *ps, int edit_
2017-04-12 17:37:46 +02:00
*** 277,282 ****
--- 277,331 ----
}
}
}
+ else if(vtmp == &ps->vars[V_THREAD_SORT_KEY]){ /* radio case */
+ SortOrder thread_def_sort;
+ int thread_def_sort_rev, lv;
+
+ 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 (allowed_thread_key(ps->sort_types[i])){
+ 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;
2020-10-05 19:41:16 +02:00
*************** option_screen(struct pine *ps, int edit_
2020-09-08 22:48:40 +02:00
*** 469,474 ****
--- 518,532 ----
2017-04-12 17:37:46 +02:00
}
}
+ 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(ps_global->mail_stream, 0);
+ reset_sort_order(SRT_VRB);
+ }
+ }
+
treat_color_vars_as_text = 0;
free_saved_config(ps, &vsave, expose_hidden_config);
#ifdef _WINDOWS
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/pith/conf.c
===================================================================
*** alpine-2.23.2.orig/pith/conf.c
--- alpine-2.23.2/pith/conf.c
*************** CONF_TXT_T cf_text_fcc_name_rule[] = "De
2020-09-08 22:48:40 +02:00
*** 207,212 ****
--- 207,214 ----
2017-04-12 17:37:46 +02:00
CONF_TXT_T cf_text_sort_key[] = "Sets presentation order of messages in Index. Choices:\n# Subject, From, Arrival, Date, Size, To, Cc, OrderedSubj, Score, and Thread.\n# Order may be reversed by appending /Reverse. 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\".";
2020-10-05 19:41:16 +02:00
*************** static struct variable variables[] = {
*** 541,546 ****
--- 543,550 ----
2017-04-12 17:37:46 +02:00
NULL, cf_text_fcc_name_rule},
{"sort-key", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
NULL, cf_text_sort_key},
+ {"thread-sort-key", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
+ NULL, cf_text_thread_sort_key},
{"addrbook-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
"Address Book Sort Rule", cf_text_addrbook_sort_rule},
{"folder-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
2020-10-05 19:41:16 +02:00
*************** init_vars(struct pine *ps, void (*cmds_f
*** 1613,1619 ****
2017-04-12 17:37:46 +02:00
register struct variable *vars = ps->vars;
int obs_header_in_reply = 0, /* the obs_ variables are to */
obs_old_style_reply = 0, /* support backwards compatibility */
! obs_save_by_sender, i, def_sort_rev;
long rvl;
PINERC_S *fixedprc = NULL;
FeatureLevel obs_feature_level;
2020-10-05 19:41:16 +02:00
--- 1617,1623 ----
2017-04-12 17:37:46 +02:00
register struct variable *vars = ps->vars;
int obs_header_in_reply = 0, /* the obs_ variables are to */
obs_old_style_reply = 0, /* 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;
2020-10-05 19:41:16 +02:00
*************** init_vars(struct pine *ps, void (*cmds_f
*** 1641,1646 ****
--- 1645,1651 ----
2017-04-12 17:37:46 +02:00
GLO_FEATURE_LEVEL = cpystr("sappling");
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);
2020-10-05 19:41:16 +02:00
*************** init_vars(struct pine *ps, void (*cmds_f
*** 2594,2600 ****
2017-04-12 17:37:46 +02:00
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){
snprintf(tmp_20k_buf, SIZEOF_20KBUF, "Sort type \"%.200s\" is invalid", VAR_SORT_KEY);
init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
ps->def_sort = SortArrival;
2020-10-05 19:41:16 +02:00
--- 2599,2605 ----
2017-04-12 17:37:46 +02:00
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){
snprintf(tmp_20k_buf, SIZEOF_20KBUF, "Sort type \"%.200s\" is invalid", VAR_SORT_KEY);
init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
ps->def_sort = SortArrival;
2020-10-05 19:41:16 +02:00
*************** init_vars(struct pine *ps, void (*cmds_f
*** 2603,2608 ****
--- 2608,2624 ----
2017-04-12 17:37:46 +02:00
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++)
2020-10-05 19:41:16 +02:00
*************** feature_list(int index)
*** 3028,3033 ****
--- 3044,3051 ----
2017-04-12 17:37:46 +02:00
F_COLOR_LINE_IMPORTANT, h_config_color_thrd_import, PREF_INDX, 0},
{"thread-sorts-by-arrival", "Thread Sorts by Arrival",
F_THREAD_SORTS_BY_ARRIVAL, h_config_thread_sorts_by_arrival, PREF_INDX, 0},
+ {"enhanced-fancy-thread-support", "Enhanced Fancy Thread Support",
+ F_ENHANCED_THREAD, h_config_enhanced_thread, PREF_INDX, 0},
/* Viewer prefs */
{"enable-msg-view-addresses", "Enable Message View Address Links",
2020-10-05 19:41:16 +02:00
*************** config_help(int var, int feature)
*** 7792,7797 ****
--- 7810,7817 ----
2017-04-12 17:37:46 +02:00
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 :
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/pith/conf.h
===================================================================
*** alpine-2.23.2.orig/pith/conf.h
--- alpine-2.23.2/pith/conf.h
2017-04-12 17:37:46 +02:00
***************
2020-09-08 22:48:40 +02:00
*** 150,155 ****
--- 150,158 ----
2017-04-12 17:37:46 +02:00
#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
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/pith/conftype.h
===================================================================
*** alpine-2.23.2.orig/pith/conftype.h
--- alpine-2.23.2/pith/conftype.h
*************** typedef enum { V_PERSONAL_NAME = 0
2017-04-12 17:37:46 +02:00
*** 59,64 ****
--- 59,65 ----
, 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
2020-10-05 19:41:16 +02:00
*************** typedef enum {
*** 529,534 ****
--- 530,536 ----
2017-04-12 17:37:46 +02:00
F_QUELL_TIMEZONE,
F_QUELL_USERAGENT,
F_COLOR_LINE_IMPORTANT,
+ F_ENHANCED_THREAD,
F_SLASH_COLL_ENTIRE,
F_ENABLE_FULL_HDR_AND_TEXT,
F_QUELL_FULL_HDR_RESET,
2020-10-05 19:41:16 +02:00
*************** typedef struct smime_stuff {
*** 794,798 ****
--- 796,801 ----
2017-04-12 17:37:46 +02:00
2020-05-12 22:34:54 +02:00
/* exported prototypes */
2017-04-12 17:37:46 +02:00
+ #define DF_THREAD_SORT_KEY "thread"
#endif /* PITH_CONFTYPE_INCLUDED */
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/pith/flag.c
===================================================================
*** alpine-2.23.2.orig/pith/flag.c
--- alpine-2.23.2/pith/flag.c
*************** set_lflag(MAILSTREAM *stream, MSGNO_S *m
2017-04-12 17:37:46 +02:00
*** 594,607 ****
was_invisible = (pelt->hidden || pelt->colhid) ? 1 : 0;
if((chk_thrd_cnt = ((msgs->visible_threads >= 0L)
&& THRD_INDX_ENABLED() && (f & MN_HIDE) && (pelt->hidden != v))) != 0){
thrd = fetch_thread(stream, rawno);
if(thrd && thrd->top){
! if(thrd->top == thrd->rawno)
topthrd = thrd;
else
! topthrd = fetch_thread(stream, thrd->top);
}
if(topthrd){
--- 594,609 ----
was_invisible = (pelt->hidden || pelt->colhid) ? 1 : 0;
+ thrd = fetch_thread(stream, rawno);
+
if((chk_thrd_cnt = ((msgs->visible_threads >= 0L)
&& THRD_INDX_ENABLED() && (f & MN_HIDE) && (pelt->hidden != v))) != 0){
thrd = fetch_thread(stream, rawno);
if(thrd && thrd->top){
! if(top_thread(stream, thrd->top) == thrd->rawno)
topthrd = thrd;
else
! topthrd = fetch_thread(stream, top_thread(stream, thrd->top));
}
if(topthrd){
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/pith/indxtype.h
===================================================================
*** alpine-2.23.2.orig/pith/indxtype.h
--- alpine-2.23.2/pith/indxtype.h
*************** typedef enum {iNothing, iStatus, iFStatu
2017-04-12 17:37:46 +02:00
*** 78,84 ****
iKey, iKeyInit,
iPrefDate, iPrefTime, iPrefDateTime,
iCurPrefDate, iCurPrefTime, iCurPrefDateTime,
! iSize, iSizeComma, iSizeNarrow, iDescripSize,
iNewsAndTo, iToAndNews, iNewsAndRecips, iRecipsAndNews,
iFromTo, iFromToNotNews, iFrom, iTo, iSender, iCc, iNews, iRecips,
iCurNews, iArrow,
--- 78,84 ----
iKey, iKeyInit,
iPrefDate, iPrefTime, iPrefDateTime,
iCurPrefDate, iCurPrefTime, iCurPrefDateTime,
! iSize, iSizeComma, iSizeNarrow, iDescripSize, iSizeThread,
iNewsAndTo, iToAndNews, iNewsAndRecips, iRecipsAndNews,
iFromTo, iFromToNotNews, iFrom, iTo, iSender, iCc, iNews, iRecips,
iCurNews, iArrow,
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/pith/mailindx.c
===================================================================
*** alpine-2.23.2.orig/pith/mailindx.c
--- alpine-2.23.2/pith/mailindx.c
*************** init_index_format(char *format, INDEX_CO
2020-05-12 22:34:54 +02:00
*** 229,234 ****
--- 229,235 ----
2017-04-12 17:37:46 +02:00
case iSTime:
case iKSize:
case iSize:
+ case iSizeThread:
case iPrioAlpha:
(*answer)[column].req_width = 7;
break;
2020-10-05 19:41:16 +02:00
*************** static INDEX_PARSE_T itokens[] = {
2020-05-12 22:34:54 +02:00
*** 456,461 ****
--- 457,463 ----
2017-04-12 17:37:46 +02:00
{"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},
2020-10-05 19:41:16 +02:00
*************** static IndexColType fixed_ctypes[] = {
2020-05-12 22:34:54 +02:00
*** 954,960 ****
2017-04-12 17:37:46 +02:00
iSDateTimeS1, iSDateTimeS2, iSDateTimeS3, iSDateTimeS4,
iSDateTimeIso24, iSDateTimeIsoS24,
iSDateTimeS124, iSDateTimeS224, iSDateTimeS324, iSDateTimeS424,
! iSize, iSizeComma, iSizeNarrow, iKSize, iDescripSize,
iPrio, iPrioBang, iPrioAlpha, iInit,
iAtt, iTime24, iTime12, iTimezone, iMonAbb, iYear, iYear2Digit,
iDay2Digit, iMon2Digit, iDayOfWeekAbb, iScore, iMonLong, iDayOfWeek
2020-05-12 22:34:54 +02:00
--- 956,962 ----
2017-04-12 17:37:46 +02:00
iSDateTimeS1, iSDateTimeS2, iSDateTimeS3, iSDateTimeS4,
iSDateTimeIso24, iSDateTimeIsoS24,
iSDateTimeS124, iSDateTimeS224, iSDateTimeS324, iSDateTimeS424,
! iSize, iSizeComma, iSizeNarrow, iKSize, iDescripSize, iSizeThread,
iPrio, iPrioBang, iPrioAlpha, iInit,
iAtt, iTime24, iTime12, iTimezone, iMonAbb, iYear, iYear2Digit,
iDay2Digit, iMon2Digit, iDayOfWeekAbb, iScore, iMonLong, iDayOfWeek
2020-10-05 19:41:16 +02:00
*************** setup_index_header_widths(MAILSTREAM *st
2020-05-12 22:34:54 +02:00
*** 1147,1152 ****
--- 1149,1155 ----
2017-04-12 17:37:46 +02:00
case iTime12:
case iSize:
case iKSize:
+ case iSizeThread:
cdesc->actual_length = 7;
cdesc->adjustment = Right;
break;
2020-10-05 19:41:16 +02:00
*************** setup_index_header_widths(MAILSTREAM *st
2020-05-12 22:34:54 +02:00
*** 1241,1247 ****
2017-04-12 17:37:46 +02:00
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 */
2020-05-12 22:34:54 +02:00
--- 1244,1250 ----
2017-04-12 17:37:46 +02:00
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 */
2020-10-05 19:41:16 +02:00
*************** build_header_work(struct pine *state, MA
2020-05-12 22:34:54 +02:00
*** 1627,1636 ****
2017-04-12 17:37:46 +02:00
/* 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
2020-05-12 22:34:54 +02:00
--- 1630,1641 ----
2017-04-12 17:37:46 +02:00
/* find next thread which is visible */
do{
+ unsigned long branch;
if(mn_get_revsort(msgmap) && thrd->prevthd)
thrd = fetch_thread(stream, thrd->prevthd);
! /*branch = get_branch(stream,thrd)*/
! else if(!mn_get_revsort(msgmap) && thrd->branch)
! thrd = fetch_thread(stream, thrd->branch);
else
thrd = NULL;
} while(thrd
2020-10-05 19:41:16 +02:00
*************** format_index_index_line(INDEXDATA_S *ida
2020-05-12 22:34:54 +02:00
*** 2042,2054 ****
2017-04-12 17:37:46 +02:00
*/
ice = copy_ice(ice);
/* 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 */
for(cdesc = ps_global->index_disp_format; cdesc->ctype != iNothing; cdesc++)
2020-05-12 22:34:54 +02:00
--- 2047,2056 ----
2017-04-12 17:37:46 +02:00
*/
ice = copy_ice(ice);
+ thrd = fetch_thread(idata->stream, idata->rawno);
/* is this a collapsed thread index line? */
! if(!idata->bogus && THREADING())
! collapsed = thrd && thread_is_kolapsed(ps_global, idata->stream, ps_global->msgmap, idata->rawno);
/* calculate contents of the required fields */
for(cdesc = ps_global->index_disp_format; cdesc->ctype != iNothing; cdesc++)
2020-10-05 19:41:16 +02:00
*************** format_index_index_line(INDEXDATA_S *ida
2020-05-12 22:34:54 +02:00
*** 2550,2556 ****
--- 2552,2581 ----
2017-04-12 17:37:46 +02:00
break;
+ case iSizeThread:
+ if (!THREADING()){
+ goto getsize;
+ } else if (collapsed){
+ l = count_flags_in_thread(idata->stream, thrd, F_NONE);
+ snprintf(str, sizeof(str), "(%lu)", l);
+ }
+ else{
+ thrd = fetch_thread(idata->stream, idata->rawno);
+ if(!thrd)
+ snprintf(str, sizeof(str), "%s", "Error");
+ else{
+ long lengthb;
+ lengthb = get_length_branch(idata->stream, idata->rawno);
+ if (lengthb > 0L)
+ snprintf(str, sizeof(str), "(%lu)", lengthb);
+ else
+ snprintf(str,sizeof(str), "%s", " ");
+ }
+ }
+ break;
+
case iSize:
+ getsize:
/* 0 ... 9999 */
if((l = fetch_size(idata)) < 10*1000L)
snprintf(str, sizeof(str), "(%lu)", l);
2020-10-05 19:41:16 +02:00
*************** subj_str(INDEXDATA_S *idata, char *str,
2020-05-12 22:34:54 +02:00
*** 5582,5591 ****
2017-04-12 17:37:46 +02:00
if(pith_opt_condense_thread_cue)
width = (*pith_opt_condense_thread_cue)(thd, ice, &str, &strsize, width,
! thd && thd->next
! && get_lflag(idata->stream,
! NULL,idata->rawno,
! MN_COLL));
/*
* width is < available strsize and
2020-05-12 22:34:54 +02:00
--- 5607,5614 ----
2017-04-12 17:37:46 +02:00
if(pith_opt_condense_thread_cue)
width = (*pith_opt_condense_thread_cue)(thd, ice, &str, &strsize, width,
! this_thread_is_kolapsed(ps_global, idata->stream, ps_global->msgmap, idata->rawno) &&
! (count_thread(ps_global,idata->stream, ps_global->msgmap, idata->rawno) != 1));
/*
* width is < available strsize and
2020-10-05 19:41:16 +02:00
*************** from_str(IndexColType ctype, INDEXDATA_S
2020-09-08 22:48:40 +02:00
*** 6211,6221 ****
2017-04-12 17:37:46 +02:00
border = str + width;
if(pith_opt_condense_thread_cue)
width = (*pith_opt_condense_thread_cue)(thd, ice, &str, &strsize, width,
! thd && thd->next
! && get_lflag(idata->stream,
! NULL,idata->rawno,
! MN_COLL));
!
fptr = str;
if(thd)
2020-09-08 22:48:40 +02:00
--- 6234,6241 ----
2017-04-12 17:37:46 +02:00
border = str + width;
if(pith_opt_condense_thread_cue)
width = (*pith_opt_condense_thread_cue)(thd, ice, &str, &strsize, width,
! this_thread_is_kolapsed(ps_global, idata->stream, ps_global->msgmap, idata->rawno) &&
! (count_thread(ps_global,idata->stream, ps_global->msgmap, idata->rawno) != 1));
fptr = str;
if(thd)
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/pith/pattern.c
===================================================================
*** alpine-2.23.2.orig/pith/pattern.c
--- alpine-2.23.2/pith/pattern.c
*************** parse_action_slash(char *str, ACTION_S *
2017-04-12 17:37:46 +02:00
*** 1756,1762 ****
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);
--- 1756,1762 ----
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);
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/pith/pine.hlp
===================================================================
*** alpine-2.23.2.orig/pith/pine.hlp
--- alpine-2.23.2/pith/pine.hlp
*************** There are also additional details on
*** 4839,4844 ****
--- 4839,4845 ----
2017-04-12 17:37:46 +02:00
<li><a href="h_config_signature_file">OPTION: <!--#echo var="VAR_signature-file"--></a>
<li><a href="h_config_smtp_server">OPTION: <!--#echo var="VAR_smtp-server"--></a>
<li><a href="h_config_sort_key">OPTION: <!--#echo var="VAR_sort-key"--></a>
+ <li><a href="h_config_thread_sort_key">OPTION: <!--#echo var="VAR_thread-sort-key"--></a>
<li><a href="h_config_speller">OPTION: <!--#echo var="VAR_speller"--></a>
<li><a href="h_config_aspell_dictionary">OPTION: <!--#echo var="VAR_aspell-dictionary-list"--></a>
<li><a href="h_config_sshcmd">OPTION: <!--#echo var="VAR_ssh-command"--></a>
2020-10-05 19:41:16 +02:00
*************** the names of the carbon copy addresses o
*** 6780,6785 ****
--- 6781,6943 ----
2017-04-12 17:37:46 +02:00
<End of help on this topic>
</BODY>
</HTML>
+ ======= h_thread_index_sort_arrival =======
+ <HTML>
+ <HEAD>
+ <TITLE>SORT OPTION: Arrival</TITLE>
+ </HEAD>
+ <BODY>
+ <H1>SORT OPTION: Arrival</H1>
+
+ The <EM>Arrival</EM> 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.
+
+ <P>
+ <End of help on this topic>
+ </BODY>
+ </HTML>
+ ======= h_thread_index_sort_date =======
+ <HTML>
+ <HEAD>
+ <TITLE>SORT OPTION: Date</TITLE>
+ </HEAD>
+ <BODY>
+ <H1>SORT OPTION: Date</H1>
+
+ The <EM>Date</EM> sort option in the THREAD INDEX screen sorts
+ threads by the date in which messages were sent. The thread containing the
+ last message in this order is displayed last.
+ <P>
+ <End of help on this topic>
+ </BODY>
+ </HTML>
+ ======= h_thread_index_sort_subj =======
+ <HTML>
+ <HEAD>
+ <TITLE>SORT OPTION: Subject</TITLE>
+ </HEAD>
+ <BODY>
+ <H1>SORT OPTION: Subject</H1>
+
+ The <EM>Subject</EM> sort option has not been defined yet.
+
+ <P>
+ <End of help on this topic>
+ </BODY>
+ </HTML>
+ ======= h_thread_index_sort_ordsubj =======
+ <HTML>
+ <HEAD>
+ <TITLE>SORT OPTION: OrderedSubject</TITLE>
+ </HEAD>
+ <BODY>
+ <H1>SORT OPTION: OrderedSubject</H1>
+
+ The <EM>OrderedSubject</EM> sort option in the THREAD INDEX screen is
+ the same as sorting by <A HREF="h_thread_index_sort_subj">Subject</A>.
+
+ <P>
+ <End of help on this topic>
+ </BODY>
+ </HTML>
+ ======= h_thread_index_sort_thread =======
+ <HTML>
+ <HEAD>
+ <TITLE>SORT OPTION: Thread</TITLE>
+ </HEAD>
+ <BODY>
+ <H1>SORT OPTION: Thread</H1>
+
+ The <EM>Thread</EM> 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.
+
+ <P>
+ <End of help on this topic>
+ </BODY>
+ </HTML>
+ ======= h_thread_index_sort_from =======
+ <HTML>
+ <HEAD>
+ <TITLE>SORT OPTION: From</TITLE>
+ </HEAD>
+ <BODY>
+ <H1>SORT OPTION: From</H1>
+
+ The <EM>From</EM> sort option has not been defined yet.
+
+ <P>
+ <End of help on this topic>
+ </BODY>
+ </HTML>
+ ======= h_thread_index_sort_size =======
+ <HTML>
+ <HEAD>
+ <TITLE>SORT OPTION: Size</TITLE>
+ </HEAD>
+ <BODY>
+ <H1>SORT OPTION: Size</H1>
+
+ The <EM>Size</EM> sort option sorts threads by their size (the number
+ of messages in the thread). This could be used to find conversations
+ where no reply has been sent by any of the participants in the thread
+ (e.g. those whose length is equal to one). Longer threads appear
+ below shorter ones.
+
+ <P>
+ <End of help on this topic>
+ </BODY>
+ </HTML>
+ ======= h_thread_index_sort_score =======
+ <HTML>
+ <HEAD>
+ <TITLE>SORT OPTION: Score</TITLE>
+ </HEAD>
+ <BODY>
+ <H1>SORT OPTION: Score</H1>
+
+ The <EM>Score</EM> sort option means that threads are sorted according to
+ the maximum score of a message in that thread. A thread all of whose
+ messages contain a smaller score than a message in some other thread is
+ placed in an earlier place in the list of messages for that folder; that
+ is, threads with the highest scores appear at the bottom of the index
+ list.
+
+ <P>
+ <End of help on this topic>
+ </BODY>
+ </HTML>
+ ======= h_thread_index_sort_to =======
+ <HTML>
+ <HEAD>
+ <TITLE>SORT OPTION: To</TITLE>
+ </HEAD>
+ <BODY>
+ <H1>SORT OPTION: To</H1>
+
+ The <EM>To</EM> sort option has not been defined yet.
+
+ <P>
+ <End of help on this topic>
+ </BODY>
+ </HTML>
+ ======= h_thread_index_sort_cc =======
+ <HTML>
+ <HEAD>
+ <TITLE>SORT OPTION: Cc</TITLE>
+ </HEAD>
+ <BODY>
+ <H1>SORT OPTION: Cc</H1>
+
+ The <EM>Cc</EM> sort option has not been defined yet.
+
+ <P>
+ <End of help on this topic>
+ </BODY>
+ </HTML>
======= h_index_cmd_whereis =======
<HTML>
<HEAD>
2020-10-05 19:41:16 +02:00
*************** The progression of sizes used looks like
*** 20325,20330 ****
--- 20483,20496 ----
2017-04-12 17:37:46 +02:00
<P>
</DD>
+ <DT>SIZETHREAD</DT>
+ <DD>
+ 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.
+ </DD>
+
<DT>SIZENARROW</DT>
<DD>
This token represents the total size, in bytes, of the message.
2020-10-05 19:41:16 +02:00
*************** command, then it will not be re-sorted u
*** 23948,23953 ****
--- 24114,24158 ----
2017-04-12 17:37:46 +02:00
<End of help on this topic>
</BODY>
</HTML>
+ ====== h_config_thread_sort_key =====
+ <HTML>
+ <HEAD>
+ <TITLE>OPTION: <!--#echo var="VAR_thread-sort-key--></TITLE>
+ </HEAD>
+ <BODY>
+ <H1>OPTION: <!--#echo var="VAR_thread-sort-key--></TITLE></H1>
+
+ This option determines the order in which threads will be displayed. You
+ can choose from the options listed below. Each folder is sorted in one of
+ the sort orders displayed below first, then the thread containing the last
+ message of that sorted list is put at the end of the index. All messages
+ of that thread are "removed" from the sorted list and the
+ process is repeated with the remaining messages in that list.
+
+ <P>
+ <UL>
+ <LI> <A HREF="h_thread_index_sort_arrival">Arrival</A>
+ <LI> <A HREF="h_thread_index_sort_date">Date</A>
+ <!-- <LI> <A HREF="h_thread_index_sort_subj">Subject</A>
+ <LI> <A HREF="h_thread_index_sort_ordsubj">OrderedSubj</A>-->
+ <LI> <A HREF="h_thread_index_sort_thread">Thread</A>
+ <!-- <LI> <A HREF="h_thread_index_sort_from">From</A> -->
+ <LI> <A HREF="h_thread_index_sort_size">Size</A>
+ <LI> <A HREF="h_thread_index_sort_score">Score</A>
+ <!-- <LI> <A HREF="h_thread_index_sort_to">To</A>
+ <LI> <A HREF="h_thread_index_sort_cc">Cc</A>-->
+ </UL>
+
+ <P> Each type of sort may also be reversed. Normal default is by
+ "Thread".
+
+ <P>
+ <UL>
+ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
+ </UL><P>
+ <End of help on this topic>
+ </BODY>
+ </HTML>
====== h_config_other_startup =====
<HTML>
<HEAD>
2020-10-05 19:41:16 +02:00
*************** Reply Use, Forward Use, and Compose Use.
*** 32059,32064 ****
--- 32264,32286 ----
2017-04-12 17:37:46 +02:00
<End of help on this topic>
</BODY>
</HTML>
+ ====== h_config_enhanced_thread =====
+ <HTML>
+ <HEAD>
+ <TITLE>FEATURE: <!--#echo var="FEAT_enhanced-fancy-thread-support"--></TITLE>
+ </HEAD>
+ <BODY>
+ <H1>FEATURE: <!--#echo var="FEAT_enhanced-fancy-thread-support"--></H1>
+
+ If this option is set certain commands in Pine will operate in loose
+ threads too. For example, the command ^R marks a thread deleted, but if
+ this feature is set, it will remove all threads that share the same missing
+ parent with this thread.
+
+ <P>
+ <End of help on this topic>
+ </BODY>
+ </HTML>
====== h_config_news_cross_deletes =====
<HTML>
<HEAD>
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/pith/sort.c
===================================================================
*** alpine-2.23.2.orig/pith/sort.c
--- alpine-2.23.2/pith/sort.c
*************** Args: msgmap --
2017-04-12 17:37:46 +02:00
*** 91,97 ****
----*/
void
sort_folder(MAILSTREAM *stream, MSGNO_S *msgmap, SortOrder new_sort,
! int new_rev, unsigned int flags)
{
long raw_current, i, j;
unsigned long *sort = NULL;
--- 91,97 ----
----*/
void
sort_folder(MAILSTREAM *stream, MSGNO_S *msgmap, SortOrder new_sort,
! int new_rev, unsigned int flags, int first)
{
long raw_current, i, j;
unsigned long *sort = NULL;
2020-10-05 19:41:16 +02:00
*************** sort_folder(MAILSTREAM *stream, MSGNO_S
2017-04-12 17:37:46 +02:00
*** 101,106 ****
--- 101,115 ----
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, "Sorting by %s%s\n",
sort_name(new_sort), new_rev ? "/reverse" : ""));
2020-10-05 19:41:16 +02:00
*************** percent_sorted(void)
2017-04-12 17:37:46 +02:00
*** 530,549 ****
* argument also means arrival/reverse.
*/
int
! decode_sort(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);
}
--- 539,558 ----
* argument also means arrival/reverse.
*/
int
! decode_sort(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);
}
2020-10-05 19:41:16 +02:00
*************** decode_sort(char *sort_spec, SortOrder *
2017-04-12 17:37:46 +02:00
*** 572,578 ****
if(ps_global->sort_types[x] == EndofList)
return(-1);
! *def_sort = ps_global->sort_types[x];
*def_sort_rev = reverse;
return(0);
}
--- 581,587 ----
if(ps_global->sort_types[x] == EndofList)
return(-1);
! *def_sort = ps_global->sort_types[x];
*def_sort_rev = reverse;
return(0);
}
2020-10-05 19:41:16 +02:00
*************** reset_sort_order(unsigned int flags)
2017-04-12 17:37:46 +02:00
*** 689,695 ****
/* 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)){
--- 698,706 ----
/* 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)){
2020-10-05 19:41:16 +02:00
*************** reset_sort_order(unsigned int flags)
2017-04-12 17:37:46 +02:00
*** 702,710 ****
&& 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);
}
--- 713,727 ----
&& pat->action->sort_is_set){
the_sort_order = pat->action->sortorder;
sort_is_rev = pat->action->revsort;
+ sort_is_rev = the_sort_order == SortThread
+ ? (ps_global->thread_def_sort_rev + pat->action->revsort) % 2
+ : pat->action->revsort;
}
}
+ if(the_sort_order == SortThread && !(flags & SRT_MAN))
+ 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);
}
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/pith/sort.h
===================================================================
*** alpine-2.23.2.orig/pith/sort.h
--- alpine-2.23.2/pith/sort.h
2017-04-12 17:37:46 +02:00
***************
*** 23,29 ****
#define refresh_sort(S,M,F) sort_folder((S), (M), mn_get_sort(M), \
! mn_get_revsort(M), (F))
struct global_sort_data {
MSGNO_S *msgmap;
--- 23,29 ----
#define refresh_sort(S,M,F) sort_folder((S), (M), mn_get_sort(M), \
! mn_get_revsort(M), (F), 1)
struct global_sort_data {
MSGNO_S *msgmap;
2020-10-05 19:41:16 +02:00
*************** extern struct global_sort_data g_sort;
2017-04-12 17:37:46 +02:00
*** 42,49 ****
2020-05-12 22:34:54 +02:00
/* exported prototypes */
2017-04-12 17:37:46 +02:00
char *sort_name(SortOrder);
! void sort_folder(MAILSTREAM *, MSGNO_S *, SortOrder, int, unsigned);
! int decode_sort(char *, SortOrder *, int *);
void reset_sort_order(unsigned);
--- 42,49 ----
2020-05-12 22:34:54 +02:00
/* exported prototypes */
2017-04-12 17:37:46 +02:00
char *sort_name(SortOrder);
! void sort_folder(MAILSTREAM *, MSGNO_S *, SortOrder, int, unsigned, int);
! int decode_sort(char *, SortOrder *, int *, int);
void reset_sort_order(unsigned);
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/pith/state.c
===================================================================
*** alpine-2.23.2.orig/pith/state.c
--- alpine-2.23.2/pith/state.c
*************** new_pine_struct(void)
2020-05-12 22:34:54 +02:00
*** 75,80 ****
--- 75,81 ----
2017-04-12 17:37:46 +02:00
p = (struct pine *)fs_get(sizeof (struct pine));
memset((void *) p, 0, sizeof(struct pine));
+ p->thread_def_sort = SortDate;
p->def_sort = SortArrival;
p->sort_types[0] = SortSubject;
p->sort_types[1] = SortArrival;
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/pith/state.h
===================================================================
*** alpine-2.23.2.orig/pith/state.h
--- alpine-2.23.2/pith/state.h
*************** struct pine {
2020-09-08 22:48:40 +02:00
*** 148,153 ****
--- 148,155 ----
2017-04-12 17:37:46 +02:00
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 tcptimeout:1; /* a tcp timeout is in progress */
2020-10-05 19:41:16 +02:00
*************** struct pine {
2020-09-08 22:48:40 +02:00
*** 311,316 ****
--- 313,321 ----
2017-04-12 17:37:46 +02:00
EditWhich ew_for_srch_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;
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/pith/thread.c
===================================================================
*** alpine-2.23.2.orig/pith/thread.c
--- alpine-2.23.2/pith/thread.c
*************** static char rcsid[] = "$Id: thread.c 942
2017-04-12 17:37:46 +02:00
*** 30,41 ****
#include "../pith/mailcmd.h"
#include "../pith/ablookup.h"
/*
* Internal prototypes
*/
long *sort_thread_flatten(THREADNODE *, MAILSTREAM *, long *,
! char *, long, PINETHRD_S *, unsigned);
void make_thrdflags_consistent(MAILSTREAM *, MSGNO_S *, PINETHRD_S *, int);
THREADNODE *collapse_threadnode_tree(THREADNODE *);
THREADNODE *collapse_threadnode_tree_sorted(THREADNODE *);
--- 30,47 ----
#include "../pith/mailcmd.h"
#include "../pith/ablookup.h"
+ static int erase_thread_info = 1;
+
+ typedef struct sizethread_t {
+ int count;
+ long pos;
+ } SIZETHREAD_T;
/*
* Internal prototypes
*/
long *sort_thread_flatten(THREADNODE *, MAILSTREAM *, long *,
! char *, long, PINETHRD_S *, unsigned, int, long, long);
void make_thrdflags_consistent(MAILSTREAM *, MSGNO_S *, PINETHRD_S *, int);
THREADNODE *collapse_threadnode_tree(THREADNODE *);
THREADNODE *collapse_threadnode_tree_sorted(THREADNODE *);
2020-10-05 19:41:16 +02:00
*************** THREADNODE *sort_threads_and_collapse(
2017-04-12 17:37:46 +02:00
*** 43,48 ****
--- 49,55 ----
THREADNODE *insert_tree_in_place(THREADNODE *, THREADNODE *);
unsigned long branch_greatest_num(THREADNODE *, int);
long calculate_visible_threads(MAILSTREAM *);
+ int pine_compare_size_thread(const qsort_t *, const qsort_t *);
PINETHRD_S *
2020-10-05 19:41:16 +02:00
*************** void
2017-04-12 17:37:46 +02:00
*** 95,114 ****
set_flags_for_thread(MAILSTREAM *stream, MSGNO_S *msgmap, int f, PINETHRD_S *thrd, 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);
}
--- 102,123 ----
set_flags_for_thread(MAILSTREAM *stream, MSGNO_S *msgmap, int f, PINETHRD_S *thrd, 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);
}
2020-10-05 19:41:16 +02:00
*************** erase_threading_info(MAILSTREAM *stream,
2017-04-12 17:37:46 +02:00
*** 122,128 ****
MESSAGECACHE *mc;
PINELT_S *peltp;
! if(!(stream && stream->spare))
return;
ps_global->view_skipped_index = 0;
--- 131,137 ----
MESSAGECACHE *mc;
PINELT_S *peltp;
! if(!(stream && stream->spare) || !erase_thread_info)
return;
ps_global->view_skipped_index = 0;
2020-10-05 19:41:16 +02:00
*************** sort_thread_callback(MAILSTREAM *stream,
2017-04-12 17:37:46 +02:00
*** 155,161 ****
PINETHRD_S *thrd = NULL;
unsigned long msgno, rawno;
int un_view_thread = 0;
! long raw_current;
char *dup_chk = NULL;
--- 164,170 ----
PINETHRD_S *thrd = NULL;
unsigned long msgno, rawno;
int un_view_thread = 0;
! long raw_current, branch;
char *dup_chk = NULL;
2020-10-05 19:41:16 +02:00
*************** sort_thread_callback(MAILSTREAM *stream,
2017-04-12 17:37:46 +02:00
*** 168,177 ****
* way. If the dummy node is at the top-level, then its children are
* promoted to the top-level as separate threads.
*/
! if(F_ON(F_THREAD_SORTS_BY_ARRIVAL, ps_global))
! collapsed_tree = collapse_threadnode_tree_sorted(tree);
! else
! collapsed_tree = collapse_threadnode_tree(tree);
/* dup_chk is like sort with an origin of 1 */
dup_chk = (char *) fs_get((mn_get_nmsgs(g_sort.msgmap)+1) * sizeof(char));
--- 177,187 ----
* 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)
! : (F_ON(F_THREAD_SORTS_BY_ARRIVAL, ps_global)
! ? collapse_threadnode_tree_sorted(tree)
! : collapse_threadnode_tree(tree));
/* dup_chk is like sort with an origin of 1 */
dup_chk = (char *) fs_get((mn_get_nmsgs(g_sort.msgmap)+1) * sizeof(char));
2020-10-05 19:41:16 +02:00
*************** sort_thread_callback(MAILSTREAM *stream,
2017-04-12 17:37:46 +02:00
*** 182,188 ****
(void) sort_thread_flatten(collapsed_tree, stream,
&g_sort.msgmap->sort[1],
dup_chk, mn_get_nmsgs(g_sort.msgmap),
! NULL, THD_TOP);
/* reset the inverse array */
msgno_reset_isort(g_sort.msgmap);
--- 192,198 ----
(void) sort_thread_flatten(collapsed_tree, stream,
&g_sort.msgmap->sort[1],
dup_chk, mn_get_nmsgs(g_sort.msgmap),
! NULL, THD_TOP, 0, 1L, 0L);
/* reset the inverse array */
msgno_reset_isort(g_sort.msgmap);
2020-10-05 19:41:16 +02:00
*************** sort_thread_callback(MAILSTREAM *stream,
2017-04-12 17:37:46 +02:00
*** 340,351 ****
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;
--- 350,363 ----
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;
2020-10-05 19:41:16 +02:00
*************** sort_thread_callback(MAILSTREAM *stream,
2017-04-12 17:37:46 +02:00
*** 359,367 ****
MN_COLL));
}
! if(thrd->nextthd)
! thrd = fetch_thread(stream, thrd->nextthd);
! else
thrd = NULL;
}
}
--- 371,380 ----
MN_COLL));
}
! while (thrd && top_thread(stream, thrd->rawno) == top
! && thrd->nextthd)
! thrd = fetch_thread(stream, thrd->nextthd);
! if (!(thrd && thrd->nextthd))
thrd = NULL;
}
}
2020-10-05 19:41:16 +02:00
*************** make_thrdflags_consistent(MAILSTREAM *st
2017-04-12 17:37:46 +02:00
*** 412,418 ****
int a_parent_is_collapsed)
{
PINETHRD_S *nthrd, *bthrd;
! unsigned long msgno;
if(!thrd)
return;
--- 425,431 ----
int a_parent_is_collapsed)
{
PINETHRD_S *nthrd, *bthrd;
! unsigned long msgno, next, branch;
if(!thrd)
return;
2020-10-05 19:41:16 +02:00
*************** make_thrdflags_consistent(MAILSTREAM *st
2017-04-12 17:37:46 +02:00
*** 430,437 ****
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
--- 443,450 ----
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
2020-10-05 19:41:16 +02:00
*************** make_thrdflags_consistent(MAILSTREAM *st
2017-04-12 17:37:46 +02:00
*** 440,447 ****
MN_COLL));
}
! if(thrd->branch){
! bthrd = fetch_thread(stream, thrd->branch);
if(bthrd)
make_thrdflags_consistent(stream, msgmap, bthrd,
a_parent_is_collapsed);
--- 453,460 ----
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);
2020-10-05 19:41:16 +02:00
*************** calculate_visible_threads(MAILSTREAM *st
2017-04-12 17:37:46 +02:00
*** 488,496 ****
long *
sort_thread_flatten(THREADNODE *node, MAILSTREAM *stream,
long *entry, char *dup_chk, long maxno,
! PINETHRD_S *thrd, unsigned int flags)
{
! PINETHRD_S *newthrd = NULL;
if(node){
if(node->num > 0L && node->num <= maxno){ /* holes happen */
--- 501,510 ----
long *
sort_thread_flatten(THREADNODE *node, MAILSTREAM *stream,
long *entry, char *dup_chk, long maxno,
! PINETHRD_S *thrd, unsigned int flags,
! int adopted, long top, long threadno)
{
! PINETHRD_S *newthrd = NULL, *save_thread = NULL;
if(node){
if(node->num > 0L && node->num <= maxno){ /* holes happen */
2020-10-05 19:41:16 +02:00
*************** sort_thread_flatten(THREADNODE *node, MA
2017-04-12 17:37:46 +02:00
*** 498,503 ****
--- 512,520 ----
*entry = node->num;
dup_chk[node->num] = 1;
+ if(adopted == 2)
+ top = node->num;
+
/*
* Build a richer threading structure that will help us paint
* and operate on threads and subthreads.
2020-10-05 19:41:16 +02:00
*************** sort_thread_flatten(THREADNODE *node, MA
2017-04-12 17:37:46 +02:00
*** 506,525 ****
if(newthrd){
entry++;
if(node->next)
entry = sort_thread_flatten(node->next, stream,
entry, dup_chk, maxno,
! newthrd, THD_NEXT);
if(node->branch)
entry = sort_thread_flatten(node->branch, stream,
entry, dup_chk, maxno,
newthrd,
! (flags == THD_TOP) ? THD_TOP
! : THD_BRANCH);
}
}
}
}
return(entry);
--- 523,573 ----
if(newthrd){
entry++;
+ if(adopted == 2)
+ threadno = newthrd->thrdno;
+ if(adopted){
+ newthrd->toploose = top;
+ newthrd->thrdno = threadno;
+ }
+ adopted = adopted ? 1 : 0;
if(node->next)
entry = sort_thread_flatten(node->next, stream,
entry, dup_chk, maxno,
! newthrd, THD_NEXT, adopted, top, threadno);
if(node->branch)
entry = sort_thread_flatten(node->branch, stream,
entry, dup_chk, maxno,
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, dup_chk,
+ maxno, thrd, THD_TOP, adopted, top, threadno);
+ adopted = 0;
+ if(node->branch){
+ if(entry){
+ long *last_entry = entry;
+
+ do{
+ last_entry--;
+ save_thread = ((PINELT_S *)mail_elt(stream, *last_entry)->sparep)->pthrd;
+ } while (save_thread->parent != 0L);
+ entry = sort_thread_flatten(node->branch, stream, entry, dup_chk,
+ maxno, save_thread, (flags == THD_TOP ? THD_TOP : THD_BRANCH),
+ adopted, top, threadno);
+ }
+ else
+ entry = sort_thread_flatten(node->branch, stream, entry, dup_chk,
+ maxno, NULL, THD_TOP, adopted, top, threadno);
+ }
+ }
}
return(entry);
2020-10-05 19:41:16 +02:00
*************** msgno_thread_info(MAILSTREAM *stream, lo
2017-04-12 17:37:46 +02:00
*** 788,794 ****
*/
void
collapse_or_expand(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap,
! long unsigned int msgno)
{
int collapsed, adjust_current = 0;
PINETHRD_S *thrd = NULL, *nthrd;
--- 836,842 ----
*/
void
collapse_or_expand(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap,
! long unsigned int msgno, int display)
{
int collapsed, adjust_current = 0;
PINETHRD_S *thrd = NULL, *nthrd;
2020-10-05 19:41:16 +02:00
*************** collapse_or_expand(struct pine *state, M
2017-04-12 17:37:46 +02:00
*** 841,847 ****
if(!thrd)
return;
! collapsed = get_lflag(stream, NULL, thrd->rawno, MN_COLL) && thrd->next;
if(collapsed){
msgno = mn_raw2m(msgmap, thrd->rawno);
--- 889,895 ----
if(!thrd)
return;
! collapsed = this_thread_is_kolapsed(ps_global, stream, msgmap, thrd->rawno);
if(collapsed){
msgno = mn_raw2m(msgmap, thrd->rawno);
2020-10-05 19:41:16 +02:00
*************** collapse_or_expand(struct pine *state, M
2017-04-12 17:37:46 +02:00
*** 859,871 ****
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)) != NULL)
set_thread_subtree(stream, nthrd, msgmap, 1, MN_CHID);
clear_index_cache_ent(stream, msgno, 0);
}
}
! else
q_status_message(SM_ORDER, 0, 1,
_("No thread to collapse or expand on this line"));
--- 907,919 ----
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)) != NULL))
set_thread_subtree(stream, nthrd, msgmap, 1, MN_CHID);
clear_index_cache_ent(stream, msgno, 0);
}
}
! else if(display)
q_status_message(SM_ORDER, 0, 1,
_("No thread to collapse or expand on this line"));
2020-10-05 19:41:16 +02:00
*************** count_flags_in_thread(MAILSTREAM *stream
2017-04-12 17:37:46 +02:00
*** 952,969 ****
unsigned long 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);
}
--- 1000,1018 ----
unsigned long 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);
}
2020-10-05 19:41:16 +02:00
*************** int
2017-04-12 17:37:46 +02:00
*** 1051,1070 ****
mark_msgs_in_thread(MAILSTREAM *stream, PINETHRD_S *thrd, 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);
}
--- 1100,1120 ----
mark_msgs_in_thread(MAILSTREAM *stream, PINETHRD_S *thrd, 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);
}
2020-10-05 19:41:16 +02:00
*************** set_thread_lflags(MAILSTREAM *stream, PI
2017-04-12 17:37:46 +02:00
*** 1098,1104 ****
/* flags to set or clear */
/* set or clear? */
{
! unsigned long msgno;
PINETHRD_S *nthrd, *bthrd;
if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
--- 1148,1154 ----
/* flags to set or clear */
/* set or clear? */
{
! unsigned long msgno, next, branch;
PINETHRD_S *nthrd, *bthrd;
if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
2020-10-05 19:41:16 +02:00
*************** set_thread_lflags(MAILSTREAM *stream, PI
2017-04-12 17:37:46 +02:00
*** 1122,1135 ****
if(msgno > 0L && flags == MN_CHID2 && v == 1)
clear_index_cache_ent(stream, msgno, 0);
! 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);
}
--- 1172,1185 ----
if(msgno > 0L && flags == MN_CHID2 && v == 1)
clear_index_cache_ent(stream, msgno, 0);
! 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);
}
2020-10-05 19:41:16 +02:00
*************** to_us_symbol_for_thread(MAILSTREAM *stre
2017-04-12 17:37:46 +02:00
*** 1218,1236 ****
char to_us = ' ';
char branch_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(((consider_flagged && to_us != '*') || (!consider_flagged && to_us != '+'))
! && thrd->branch){
bthrd = fetch_thread(stream, thrd->branch);
if(bthrd)
branch_to_us = to_us_symbol_for_thread(stream, bthrd, consider_flagged);
--- 1268,1287 ----
char to_us = ' ';
char branch_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(((consider_flagged && to_us != '*') || (!consider_flagged && to_us != '+'))
! && (branch = get_branch(stream, thrd))){
bthrd = fetch_thread(stream, thrd->branch);
if(bthrd)
branch_to_us = to_us_symbol_for_thread(stream, bthrd, consider_flagged);
2020-10-05 19:41:16 +02:00
*************** to_us_symbol_for_thread(MAILSTREAM *stre
2017-04-12 17:37:46 +02:00
*** 1280,1286 ****
break;
}
! if(to_us != '+' && resent_to_us(&idata))
to_us = '+';
if(to_us == ' ' && F_ON(F_MARK_FOR_CC,ps_global))
--- 1331,1337 ----
break;
}
! if(to_us != '+' && !idata.bogus && resent_to_us(&idata))
to_us = '+';
if(to_us == ' ' && F_ON(F_MARK_FOR_CC,ps_global))
2020-10-05 19:41:16 +02:00
*************** set_thread_subtree(MAILSTREAM *stream, P
2017-04-12 17:37:46 +02:00
*** 1328,1334 ****
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);
--- 1379,1386 ----
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);
2020-10-05 19:41:16 +02:00
*************** view_thread(struct pine *state, MAILSTRE
2017-04-12 17:37:46 +02:00
*** 1368,1375 ****
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;
--- 1420,1427 ----
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;
2020-10-05 19:41:16 +02:00
*************** unview_thread(struct pine *state, MAILST
2017-04-12 17:37:46 +02:00
*** 1433,1439 ****
thrd = fetch_thread(stream, rawno);
if(thrd && thrd->top)
! topthrd = fetch_thread(stream, thrd->top);
if(!topthrd)
return 0;
--- 1485,1491 ----
thrd = fetch_thread(stream, rawno);
if(thrd && thrd->top)
! topthrd = fetch_thread(stream, top_thread(stream,thrd->top));
if(!topthrd)
return 0;
2020-10-05 19:41:16 +02:00
*************** void
2017-04-12 17:37:46 +02:00
*** 1539,1544 ****
--- 1591,1597 ----
set_search_bit_for_thread(MAILSTREAM *stream, PINETHRD_S *thrd, SEARCHSET **msgset)
{
PINETHRD_S *nthrd, *bthrd;
+ unsigned long next, branch;
if(!(stream && thrd))
return;
2020-10-05 19:41:16 +02:00
*************** set_search_bit_for_thread(MAILSTREAM *st
2017-04-12 17:37:46 +02:00
*** 1547,1561 ****
&& (!(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);
}
}
--- 1600,2221 ----
&& (!(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);
}
}
+
+ /*
+ * Make a copy of c-client's THREAD tree
+ */
+ THREADNODE *
+ copy_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);
+ }
+
+ long
+ top_thread(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(MAILSTREAM *stream, MSGNO_S *msgmap, long rawmsgno)
+ {
+ mn_set_cur(msgmap,mn_raw2m(msgmap, top_thread(stream, rawmsgno)));
+ }
+
+ long
+ top_this_thread(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(MAILSTREAM *stream, MSGNO_S *msgmap, long rawmsgno)
+ {
+ mn_set_cur(msgmap,mn_raw2m(msgmap, top_this_thread(stream, rawmsgno)));
+ }
+
+ int
+ thread_is_kolapsed(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(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);
2013-05-27 09:31:30 +02:00
+ else
2017-04-12 17:37:46 +02:00
+ collapsed = get_lflag(stream, NULL, rawno, MN_COLL);
+ }
+
+ return collapsed;
+ }
+
+ /*
+ * This function assumes that it is called at a top of a thread in its
+ * first call
+ */
+
+ int
+ count_this_thread(MAILSTREAM *stream, unsigned long rawno)
+ {
+ unsigned long top, orig_top, topnxt;
2013-05-27 09:31:30 +02:00
+ PINETHRD_S *thrd = NULL;
2017-04-12 17:37:46 +02:00
+ int count = 1;
+
2013-05-27 09:31:30 +02:00
+ if(!stream)
2017-04-12 17:37:46 +02:00
+ return 0;
+
+ if(rawno)
+ thrd = fetch_thread(stream, rawno);
+
2013-05-27 09:31:30 +02:00
+ if(!thrd)
2017-04-12 17:37:46 +02:00
+ 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(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap, long rawno)
+ {
+ unsigned long top, orig, orig_top;
2013-05-27 09:31:30 +02:00
+ PINETHRD_S *thrd = NULL;
2017-04-12 17:37:46 +02:00
+ int done = 0, count = 0;
+
2013-05-27 09:31:30 +02:00
+ if(!stream)
2017-04-12 17:37:46 +02:00
+ 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);
+
2013-05-27 09:31:30 +02:00
+ if(!thrd)
2017-04-12 17:37:46 +02:00
+ return 0;
+
+ while (!done){
+ count += count_this_thread(stream, top);
2013-05-27 09:31:30 +02:00
+ if (F_OFF(F_ENHANCED_THREAD, state)
+ || (move_next_this_thread(state, stream, msgmap, 0) <= 0)
2017-04-12 17:37:46 +02:00
+ || !(top = mn_m2raw(msgmap, mn_get_cur(msgmap)))
+ || (orig_top != top_thread(stream, top)))
+ done++;
2013-05-27 09:31:30 +02:00
+ }
2017-04-12 17:37:46 +02:00
+ mn_set_cur(msgmap,mn_raw2m(msgmap, orig));
+ return count;
+ }
2013-05-27 09:31:30 +02:00
+
2017-04-12 17:37:46 +02:00
+ unsigned long
+ get_branch(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(MAILSTREAM *stream, PINETHRD_S *thrd)
+ {
+ return thrd->next;
+ }
+
+ long
+ get_length_branch(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;
+ }
2013-05-27 09:31:30 +02:00
+ }
+ }
2017-04-12 17:37:46 +02:00
+
+ 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++;
2013-05-27 09:31:30 +02:00
+ }
2017-04-12 17:37:46 +02:00
+
+ 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--;
2013-10-22 11:53:24 +02:00
+ }
2017-04-12 17:37:46 +02:00
+ return branchp ? (count ? count : 1L) : 0L;
+ }
+
+ int pine_compare_size_thread(const qsort_t *a, const qsort_t *b)
+ {
+ SIZETHREAD_T *s = (SIZETHREAD_T *) a, *t = (SIZETHREAD_T *) b;
+
+ return s->count == t->count ? s->pos - t->pos : s->count - t->count;
+ }
+
+
+
+ void
+ find_msgmap(MAILSTREAM *stream, MSGNO_S *msgmap, int flags, SortOrder ordersort, unsigned is_rev)
+ {
+ long *old_arrival,*new_arrival;
+ long init_thread, end_thread, current;
+ long i, j, k;
+ long tmsg, ntmsg, nthreads;
+ SIZETHREAD_T *l;
+ PINETHRD_S *thrd;
+
+ erase_thread_info = 0;
+ current = mn_m2raw(msgmap, mn_get_cur(msgmap));
+
+ switch(ordersort){
+ case SortSize:
+ sort_folder(stream, msgmap, SortThread, 0, SRT_VRB, 0);
+ tmsg = mn_get_total(msgmap) + 1;
+
+ if(tmsg <= 1)
+ return;
+
+ for (i= 1L, k = 0L; i <= mn_get_total(msgmap); i += count_thread(ps_global, stream, msgmap, msgmap->sort[i]), k++);
+ l = (SIZETHREAD_T *) fs_get(k*sizeof(SIZETHREAD_T));
+ for (j = 0L, i=1L; j < k && i<= mn_get_total(msgmap); ){
+ l[j].count = count_thread(ps_global, stream, msgmap, msgmap->sort[i]);
+ l[j].pos = i;
+ i += l[j].count;
+ j++;
+ }
+ qsort((void *)l, (size_t) k, sizeof(SIZETHREAD_T), pine_compare_size_thread);
+ old_arrival = (long *) fs_get(tmsg * sizeof(long));
+ for(i = 1L, j = 0; j < k; j++){ /* copy thread of length .count */
+ int p;
+ for(p = 0; p < l[j].count; p++)
+ old_arrival[i++] = msgmap->sort[l[j].pos + p];
+ }
+ fs_give((void **)&l);
+ break;
+ default:
+ sort_folder(stream, msgmap, ordersort, 0, SRT_VRB, 0);
+ tmsg = mn_get_total(msgmap) + 1;
+
+ if (tmsg <= 1)
+ return;
+
+ old_arrival = (long *) fs_get(tmsg * sizeof(long));
+ for (i= 1L;(i <= mn_get_total(msgmap)) && (old_arrival[i] = msgmap->sort[i]); i++);
+ /* sort by thread */
+ sort_folder(stream, msgmap, SortThread, 0, SRT_VRB, 0);
+ break;
+
+ }
+
+ 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;
2013-05-27 09:31:30 +02:00
+ }
2017-04-12 17:37:46 +02:00
+
+ /* reconstruct the msgmap */
+
+ new_arrival = (long *) fs_get(tmsg * sizeof(long));
+ memset(new_arrival, 0, tmsg*sizeof(long));
+ i = mn_get_total(msgmap);
+ /* we copy from the bottom, the last one to be filled is new_arrival[1] */
+ while (new_arrival[1] == 0){
+ int done = 0;
+ long n;
+
+ init_thread = top_thread(stream, old_arrival[i]);
+ thrd = fetch_thread(stream, init_thread);
+ for (n = mn_get_total(msgmap); new_arrival[n] != 0 && !done; n--)
+ done = (new_arrival[n] == init_thread);
+ if (!done){
+ 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;
+ for(k = 1L; k <= j; k++)
+ new_arrival[tmsg - k] = msgmap->sort[end_thread - k];
+ tmsg -= j;
+ }
+ i--;
2013-05-27 09:31:30 +02:00
+ }
2017-04-12 17:37:46 +02:00
+ 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);
2013-05-27 09:31:30 +02:00
+ }
2017-04-12 17:37:46 +02:00
+ 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(stream, 0);
+ }
+
+ void
+ move_thread(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(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;
+ }
+ }
+ }
+
+ int
+ move_next_this_thread(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)
2013-05-27 09:31:30 +02:00
+ return -1;
2017-04-12 17:37:46 +02:00
+
2013-05-27 09:31:30 +02:00
+ top = top_thread(stream, rawno);
2017-04-12 17:37:46 +02:00
+
+ 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");
2013-05-27 09:31:30 +02:00
+ }
+ return rv;
2017-04-12 17:37:46 +02:00
+ }
+
+ int
+ move_next_thread(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(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;
+ }
+
+ /* add more keys to this list */
+ int
+ allowed_thread_key(SortOrder sort)
+ {
+ return sort == SortArrival || sort == SortDate
+ || sort == SortScore || sort == SortThread
+ || sort == SortSize;
+ }
+
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/pith/thread.h
===================================================================
*** alpine-2.23.2.orig/pith/thread.h
--- alpine-2.23.2/pith/thread.h
*************** typedef struct pine_thrd {
2017-04-12 17:37:46 +02:00
*** 38,43 ****
--- 38,44 ----
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;
2020-10-05 19:41:16 +02:00
*************** void erase_threading_info(MAILSTRE
2017-04-12 17:37:46 +02:00
*** 93,99 ****
void sort_thread_callback(MAILSTREAM *, THREADNODE *);
void collapse_threads(MAILSTREAM *, MSGNO_S *, PINETHRD_S *);
PINETHRD_S *msgno_thread_info(MAILSTREAM *, unsigned long, PINETHRD_S *, unsigned);
! void collapse_or_expand(struct pine *, MAILSTREAM *, MSGNO_S *, unsigned long);
void select_thread_stmp(struct pine *, MAILSTREAM *, MSGNO_S *);
unsigned long count_flags_in_thread(MAILSTREAM *, PINETHRD_S *, long);
unsigned long count_lflags_in_thread(MAILSTREAM *, PINETHRD_S *, MSGNO_S *, int);
--- 94,100 ----
void sort_thread_callback(MAILSTREAM *, THREADNODE *);
void collapse_threads(MAILSTREAM *, MSGNO_S *, PINETHRD_S *);
PINETHRD_S *msgno_thread_info(MAILSTREAM *, unsigned long, PINETHRD_S *, unsigned);
! void collapse_or_expand(struct pine *, MAILSTREAM *, MSGNO_S *, unsigned long, int);
void select_thread_stmp(struct pine *, MAILSTREAM *, MSGNO_S *);
unsigned long count_flags_in_thread(MAILSTREAM *, PINETHRD_S *, long);
unsigned long count_lflags_in_thread(MAILSTREAM *, PINETHRD_S *, MSGNO_S *, int);
2020-10-05 19:41:16 +02:00
*************** int view_thread(struct pine *, MAI
2017-04-12 17:37:46 +02:00
*** 107,112 ****
int unview_thread(struct pine *, MAILSTREAM *, MSGNO_S *);
PINETHRD_S *find_thread_by_number(MAILSTREAM *, MSGNO_S *, long, PINETHRD_S *);
void set_search_bit_for_thread(MAILSTREAM *, PINETHRD_S *, SEARCHSET **);
!
#endif /* PITH_THREAD_INCLUDED */
--- 108,131 ----
int unview_thread(struct pine *, MAILSTREAM *, MSGNO_S *);
PINETHRD_S *find_thread_by_number(MAILSTREAM *, MSGNO_S *, long, PINETHRD_S *);
void set_search_bit_for_thread(MAILSTREAM *, PINETHRD_S *, SEARCHSET **);
! void find_msgmap(MAILSTREAM *, MSGNO_S *, int, SortOrder, unsigned);
! void move_thread(struct pine *, MAILSTREAM *, MSGNO_S *, int);
! void relink_threads(MAILSTREAM *, MSGNO_S *, long *);
! long top_thread(MAILSTREAM *, long);
! long top_this_thread(MAILSTREAM *, long);
! long get_length_branch(MAILSTREAM *, long);
! unsigned long get_next(MAILSTREAM *,PINETHRD_S *);
! unsigned long get_branch(MAILSTREAM *,PINETHRD_S *);
! int count_thread(struct pine *, MAILSTREAM *, MSGNO_S *, long);
! int count_this_thread(MAILSTREAM *, unsigned long);
! int this_thread_is_kolapsed(struct pine *, MAILSTREAM *, MSGNO_S *, long);
! int thread_is_kolapsed(struct pine *, MAILSTREAM *, MSGNO_S *, long);
! int move_prev_thread(struct pine *, MAILSTREAM *, MSGNO_S *, int);
! int move_next_thread(struct pine *, MAILSTREAM *, MSGNO_S *, int);
! int move_next_this_thread(struct pine *, MAILSTREAM *, MSGNO_S *, int);
! void move_top_thread(MAILSTREAM *, MSGNO_S *, long);
! void move_top_this_thread(MAILSTREAM *, MSGNO_S *, long);
! THREADNODE *copy_tree(THREADNODE *);
! int allowed_thread_key(SortOrder sort);
#endif /* PITH_THREAD_INCLUDED */
2020-10-05 19:41:16 +02:00
Index: alpine-2.23.2/web/src/alpined.d/alpined.c
===================================================================
*** alpine-2.23.2.orig/web/src/alpined.d/alpined.c
--- alpine-2.23.2/web/src/alpined.d/alpined.c
*************** PEConfigCmd(ClientData clientData, Tcl_I
2017-04-12 17:37:46 +02:00
*** 2755,2761 ****
init_save_defaults();
break;
case V_SORT_KEY:
2020-09-08 22:48:40 +02:00
! decode_sort(wps_global->VAR_SORT_KEY, &wps_global->def_sort, &def_sort_rev);
2017-04-12 17:37:46 +02:00
break;
case V_VIEW_HDR_COLORS :
2020-09-08 22:48:40 +02:00
set_custom_spec_colors(wps_global);
2017-04-12 17:37:46 +02:00
--- 2755,2761 ----
init_save_defaults();
break;
case V_SORT_KEY:
2020-09-08 22:48:40 +02:00
! decode_sort(wps_global->VAR_SORT_KEY, &wps_global->def_sort, &def_sort_rev, 0);
2017-04-12 17:37:46 +02:00
break;
case V_VIEW_HDR_COLORS :
2020-09-08 22:48:40 +02:00
set_custom_spec_colors(wps_global);
2020-10-05 19:41:16 +02:00
*************** PEMailboxCmd(ClientData clientData, Tcl_
2017-04-12 17:37:46 +02:00
*** 6331,6337 ****
2020-09-08 22:48:40 +02:00
&& mn_get_revsort(sp_msgmap(wps_global->mail_stream)) == reversed))
sort_folder(wps_global->mail_stream, sp_msgmap(wps_global->mail_stream),
wps_global->sort_types[i],
2017-04-12 17:37:46 +02:00
! reversed, 0);
break;
}
--- 6331,6337 ----
2020-09-08 22:48:40 +02:00
&& mn_get_revsort(sp_msgmap(wps_global->mail_stream)) == reversed))
sort_folder(wps_global->mail_stream, sp_msgmap(wps_global->mail_stream),
wps_global->sort_types[i],
2017-04-12 17:37:46 +02:00
! reversed, 0, 1);
break;
}