summaryrefslogtreecommitdiff
path: root/alpine/listsel.c
diff options
context:
space:
mode:
authorEduardo Chappa <echappa@gmx.com>2013-02-03 00:59:38 -0700
committerEduardo Chappa <echappa@gmx.com>2013-02-03 00:59:38 -0700
commit094ca96844842928810f14844413109fc6cdd890 (patch)
treee60efbb980f38ba9308ccb4fb2b77b87bbc115f3 /alpine/listsel.c
downloadalpine-094ca96844842928810f14844413109fc6cdd890.tar.xz
Initial Alpine Version
Diffstat (limited to 'alpine/listsel.c')
-rw-r--r--alpine/listsel.c332
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);
+}