diff options
author | Eduardo Chappa <echappa@gmx.com> | 2013-02-03 00:59:38 -0700 |
---|---|---|
committer | Eduardo Chappa <echappa@gmx.com> | 2013-02-03 00:59:38 -0700 |
commit | 094ca96844842928810f14844413109fc6cdd890 (patch) | |
tree | e60efbb980f38ba9308ccb4fb2b77b87bbc115f3 /alpine/listsel.c | |
download | alpine-094ca96844842928810f14844413109fc6cdd890.tar.xz |
Initial Alpine Version
Diffstat (limited to 'alpine/listsel.c')
-rw-r--r-- | alpine/listsel.c | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/alpine/listsel.c b/alpine/listsel.c new file mode 100644 index 00000000..cb9e8812 --- /dev/null +++ b/alpine/listsel.c @@ -0,0 +1,332 @@ +#if !defined(lint) && !defined(DOS) +static char rcsid[] = "$Id: listsel.c 918 2008-01-23 19:39:38Z hubert@u.washington.edu $"; +#endif +/* ======================================================================== + * Copyright 2006-2008 University of Washington + * Copyright 2013 Eduardo Chappa + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * ======================================================================== + */ + + +#include "headers.h" +#include "listsel.h" +#include "status.h" +#include "confscroll.h" +#include "../pith/state.h" + + +/* + * Internal prototypes + */ +int select_from_list_tool(struct pine *, int, CONF_S **, unsigned); +int select_from_list_tool_allow_noselections(struct pine *, int, CONF_S **, unsigned); + + +/* + * This is intended to be a generic tool to select strings from a list + * of strings. + * + * Args lsel -- the items as well as the answer are contained in this list + * flags -- There is some inconsistent flags usage. Notice that the + * flag SFL_ALLOW_LISTMODE is a flag passed in the flags + * argument whereas the flag SFL_NOSELECT is a per item + * (that is, per LIST_SEL_S) flag. + * title -- passed to conf_scroll_screen + * pdesc -- passed to conf_scroll_screen + * help -- passed to conf_scroll_screen + * helptitle -- passed to conf_scroll_screen + * + * You have screen width - 4 columns to work with. If you want to overflow to + * a second (or third or fourth) line for an item just send another item + * in the list but with the SFL_NOSELECT flag set. Only the selectable lines + * will be highlighted, which is kind of a crock, but it looked like a lot + * of work to fix that. + * + * Returns 0 on successful choice + * -1 if cancelled + */ +int +select_from_list_screen(LIST_SEL_S *lsel, long unsigned int flags, char *title, + char *pdesc, HelpType help, char *htitle, + LIST_SEL_S *starting_val) +{ + CONF_S *ctmp = NULL, *first_line = NULL; + OPT_SCREEN_S screen; + int j, lv, ret = -1; + LIST_SEL_S *p; + char *display; + size_t l; + ScreenMode listmode = SingleMode; + int (*tool)(struct pine *, int, CONF_S **, unsigned); + + if(!lsel) + return(ret); + + /* find longest value's length */ + for(lv = 0, p = lsel; p; p = p->next){ + if(!(p->flags & SFL_NOSELECT)){ + display = p->display_item ? p->display_item : + p->item ? p->item : ""; + if(lv < (j = utf8_width(display))) + lv = j; + } + } + + lv = MIN(lv, ps_global->ttyo->screen_cols - 4); + + tool = (flags & SFL_CTRLC) ? select_from_list_tool_allow_noselections + : select_from_list_tool; + + /* + * Convert the passed in list to conf_scroll lines. + */ + + if(flags & SFL_ALLOW_LISTMODE){ + + if(flags & SFL_ONLY_LISTMODE) {assert(flags & SFL_STARTIN_LISTMODE);} + + for(p = lsel; p; p = p->next){ + + display = p->display_item ? p->display_item : + p->item ? p->item : ""; + new_confline(&ctmp); + if(!first_line && !(p->flags & SFL_NOSELECT)) + first_line = ctmp; + if(!first_line && !(p->flags & SFL_NOSELECT)) + if(!starting_val || (starting_val == p)) + first_line = ctmp; + + /* generous allocation */ + l = lv + 4 + strlen(display); + ctmp->value = (char *) fs_get((l + 1) * sizeof(char)); + utf8_snprintf(ctmp->value, l+1, " %-*.*w", lv, lv, display); + ctmp->value[l] = '\0'; + + ctmp->d.l.lsel = p; + ctmp->d.l.listmode = &listmode; + if(flags & SFL_ONLY_LISTMODE){ + if(flags & SFL_CTRLC) + ctmp->keymenu = &sel_from_list_olm_ctrlc; + else + ctmp->keymenu = &sel_from_list_olm; + } + else{ + if(flags & SFL_CTRLC) + ctmp->keymenu = &sel_from_list_sm_ctrlc; + else + ctmp->keymenu = &sel_from_list_sm; + } + + ctmp->help = help; + ctmp->help_title = htitle; + ctmp->tool = tool; + ctmp->flags = CF_STARTITEM | + ((p->flags & SFL_NOSELECT) ? CF_NOSELECT : 0); + } + } + else{ + + assert(!(flags & SFL_ONLY_LISTMODE)); + assert(!(flags & SFL_STARTIN_LISTMODE)); + + for(p = lsel; p; p = p->next){ + + display = p->display_item ? p->display_item : + p->item ? p->item : ""; + new_confline(&ctmp); + if(!first_line && !(p->flags & SFL_NOSELECT)) + if(!starting_val || (starting_val == p)) + first_line = ctmp; + + l = lv + strlen(display); + ctmp->value = (char *) fs_get((l + 1) * sizeof(char)); + utf8_snprintf(ctmp->value, l+1, "%-*.*w", lv, lv, display); + ctmp->value[l] = '\0'; + + ctmp->d.l.lsel = p; + ctmp->d.l.listmode = &listmode; + if(flags & SFL_CTRLC) + ctmp->keymenu = &sel_from_list_ctrlc; + else + ctmp->keymenu = &sel_from_list; + + ctmp->help = help; + ctmp->help_title = htitle; + ctmp->tool = tool; + ctmp->flags = CF_STARTITEM | + ((p->flags & SFL_NOSELECT) ? CF_NOSELECT : 0); + ctmp->valoffset = 4; + } + } + + /* just convert to start in listmode after the fact, easier that way */ + if(flags & SFL_STARTIN_LISTMODE){ + listmode = ListMode; + + for(ctmp = first_line; ctmp; ctmp = next_confline(ctmp)) + if(!(ctmp->flags & CF_NOSELECT) && ctmp->value){ + ctmp->value[0] = '['; + ctmp->value[1] = ctmp->d.l.lsel->selected ? 'X' : SPACE; + ctmp->value[2] = ']'; + if(flags & SFL_ONLY_LISTMODE){ + if(flags & SFL_CTRLC) + ctmp->keymenu = &sel_from_list_olm_ctrlc; + else + ctmp->keymenu = &sel_from_list_olm; + } + else{ + if(flags & SFL_CTRLC) + ctmp->keymenu = &sel_from_list_lm_ctrlc; + else + ctmp->keymenu = &sel_from_list_lm; + } + } + } + + memset(&screen, 0, sizeof(screen)); + switch(conf_scroll_screen(ps_global, &screen, first_line, title, pdesc, 0)){ + case 1: + ret = 0; + break; + + default: + break; + } + + ps_global->mangled_screen = 1; + return(ret); +} + + +int +select_from_list_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) +{ + CONF_S *ctmp; + int retval = 0; + + switch(cmd){ + case MC_SELECT : + if(*(*cl)->d.l.listmode == SingleMode){ + (*cl)->d.l.lsel->selected = 1; + retval = 3; + } + else{ + /* check if anything is selected */ + /* go to first line */ + for(ctmp = *cl; prev_confline(ctmp); ctmp = prev_confline(ctmp)) + ; + + for(; ctmp; ctmp = next_confline(ctmp)) + if(!(ctmp->flags & CF_NOSELECT) && ctmp->d.l.lsel->selected){ + retval = 3; + break; + } + + if(retval == 0){ + q_status_message(SM_ORDER, 0, 3, + _("Nothing selected, use Exit to exit without a selection.")); + } + } + + break; + + case MC_LISTMODE : + if(*(*cl)->d.l.listmode == SingleMode){ + /* + * UnHide the checkboxes + */ + + *(*cl)->d.l.listmode = ListMode; + + /* go to first line */ + for(ctmp = *cl; prev_confline(ctmp); ctmp = prev_confline(ctmp)) + ; + + for(; ctmp; ctmp = next_confline(ctmp)) + if(!(ctmp->flags & CF_NOSELECT) && ctmp->value){ + ctmp->value[0] = '['; + ctmp->value[1] = ctmp->d.l.lsel->selected ? 'X' : SPACE; + ctmp->value[2] = ']'; + ctmp->keymenu = &sel_from_list_lm; + } + } + else{ + /* + * Hide the checkboxes + */ + + *(*cl)->d.l.listmode = SingleMode; + + /* go to first line */ + for(ctmp = *cl; prev_confline(ctmp); ctmp = prev_confline(ctmp)) + ; + + for(; ctmp; ctmp = next_confline(ctmp)) + if(!(ctmp->flags & CF_NOSELECT) && ctmp->value){ + ctmp->value[0] = ctmp->value[1] = ctmp->value[2] = SPACE; + ctmp->keymenu = &sel_from_list_sm; + } + } + + ps->mangled_body = ps->mangled_footer = 1; + break; + + case MC_TOGGLE : + if((*cl)->value[1] == 'X'){ + (*cl)->d.l.lsel->selected = 0; + (*cl)->value[1] = SPACE; + } + else{ + (*cl)->d.l.lsel->selected = 1; + (*cl)->value[1] = 'X'; + } + + ps->mangled_body = 1; + break; + + case MC_EXIT : + retval = simple_exit_cmd(flags); + break; + + default: + retval = -1; + break; + } + + if(retval > 0) + ps->mangled_body = 1; + + return(retval); +} + + +int +select_from_list_tool_allow_noselections(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags) +{ + int retval = 0; + + switch(cmd){ + case MC_SELECT : + retval = 3; + if(*(*cl)->d.l.listmode == SingleMode) + (*cl)->d.l.lsel->selected = 1; + + break; + + default: + retval = select_from_list_tool(ps, cmd, cl, flags); + break; + } + + if(retval > 0) + ps->mangled_body = 1; + + return(retval); +} |