1 #if !defined(lint) && !defined(DOS)
2 static char rcsid
[] = "$Id: listsel.c 918 2008-01-23 19:39:38Z hubert@u.washington.edu $";
4 /* ========================================================================
5 * Copyright 2013-2017 Eduardo Chappa
6 * Copyright 2006-2008 University of Washington
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * ========================================================================
21 #include "confscroll.h"
22 #include "../pith/state.h"
28 int select_from_list_tool(struct pine
*, int, CONF_S
**, unsigned);
29 int select_from_list_tool_allow_noselections(struct pine
*, int, CONF_S
**, unsigned);
33 * This is intended to be a generic tool to select strings from a list
36 * Args lsel -- the items as well as the answer are contained in this list
37 * flags -- There is some inconsistent flags usage. Notice that the
38 * flag SFL_ALLOW_LISTMODE is a flag passed in the flags
39 * argument whereas the flag SFL_NOSELECT is a per item
40 * (that is, per LIST_SEL_S) flag.
41 * title -- passed to conf_scroll_screen
42 * pdesc -- passed to conf_scroll_screen
43 * help -- passed to conf_scroll_screen
44 * helptitle -- passed to conf_scroll_screen
46 * You have screen width - 4 columns to work with. If you want to overflow to
47 * a second (or third or fourth) line for an item just send another item
48 * in the list but with the SFL_NOSELECT flag set. Only the selectable lines
49 * will be highlighted, which is kind of a crock, but it looked like a lot
50 * of work to fix that.
52 * Returns 0 on successful choice
56 select_from_list_screen(LIST_SEL_S
*lsel
, long unsigned int flags
, char *title
,
57 char *pdesc
, HelpType help
, char *htitle
,
58 LIST_SEL_S
*starting_val
)
60 CONF_S
*ctmp
= NULL
, *first_line
= NULL
;
66 ScreenMode listmode
= SingleMode
;
67 int (*tool
)(struct pine
*, int, CONF_S
**, unsigned);
72 /* find longest value's length */
73 for(lv
= 0, p
= lsel
; p
; p
= p
->next
){
74 if(!(p
->flags
& SFL_NOSELECT
)){
75 display
= p
->display_item
? p
->display_item
:
76 p
->item
? p
->item
: "";
77 if(lv
< (j
= utf8_width(display
)))
82 lv
= MIN(lv
, ps_global
->ttyo
->screen_cols
- 4);
84 tool
= (flags
& SFL_CTRLC
) ? select_from_list_tool_allow_noselections
85 : select_from_list_tool
;
88 * Convert the passed in list to conf_scroll lines.
91 if(flags
& SFL_ALLOW_LISTMODE
){
93 if(flags
& SFL_ONLY_LISTMODE
) {assert(flags
& SFL_STARTIN_LISTMODE
);}
95 for(p
= lsel
; p
; p
= p
->next
){
97 display
= p
->display_item
? p
->display_item
:
98 p
->item
? p
->item
: "";
100 if(!first_line
&& !(p
->flags
& SFL_NOSELECT
))
102 if(!first_line
&& !(p
->flags
& SFL_NOSELECT
))
103 if(!starting_val
|| (starting_val
== p
))
106 /* generous allocation */
107 l
= lv
+ 4 + strlen(display
);
108 ctmp
->value
= (char *) fs_get((l
+ 1) * sizeof(char));
109 utf8_snprintf(ctmp
->value
, l
+1, " %-*.*w", lv
, lv
, display
);
110 ctmp
->value
[l
] = '\0';
113 ctmp
->d
.l
.listmode
= &listmode
;
114 if(flags
& SFL_ONLY_LISTMODE
){
115 if(flags
& SFL_CTRLC
)
116 ctmp
->keymenu
= &sel_from_list_olm_ctrlc
;
118 ctmp
->keymenu
= &sel_from_list_olm
;
121 if(flags
& SFL_CTRLC
)
122 ctmp
->keymenu
= &sel_from_list_sm_ctrlc
;
124 ctmp
->keymenu
= &sel_from_list_sm
;
128 ctmp
->help_title
= htitle
;
130 ctmp
->flags
= CF_STARTITEM
|
131 ((p
->flags
& SFL_NOSELECT
) ? CF_NOSELECT
: 0);
136 assert(!(flags
& SFL_ONLY_LISTMODE
));
137 assert(!(flags
& SFL_STARTIN_LISTMODE
));
139 for(p
= lsel
; p
; p
= p
->next
){
141 display
= p
->display_item
? p
->display_item
:
142 p
->item
? p
->item
: "";
144 if(!first_line
&& !(p
->flags
& SFL_NOSELECT
))
145 if(!starting_val
|| (starting_val
== p
))
148 l
= lv
+ strlen(display
);
149 ctmp
->value
= (char *) fs_get((l
+ 1) * sizeof(char));
150 utf8_snprintf(ctmp
->value
, l
+1, "%-*.*w", lv
, lv
, display
);
151 ctmp
->value
[l
] = '\0';
154 ctmp
->d
.l
.listmode
= &listmode
;
155 if(flags
& SFL_CTRLC
)
156 ctmp
->keymenu
= &sel_from_list_ctrlc
;
158 ctmp
->keymenu
= &sel_from_list
;
161 ctmp
->help_title
= htitle
;
163 ctmp
->flags
= CF_STARTITEM
|
164 ((p
->flags
& SFL_NOSELECT
) ? CF_NOSELECT
: 0);
169 /* just convert to start in listmode after the fact, easier that way */
170 if(flags
& SFL_STARTIN_LISTMODE
){
173 for(ctmp
= first_line
; ctmp
; ctmp
= next_confline(ctmp
))
174 if(!(ctmp
->flags
& CF_NOSELECT
) && ctmp
->value
){
175 ctmp
->value
[0] = '[';
176 ctmp
->value
[1] = ctmp
->d
.l
.lsel
->selected
? 'X' : SPACE
;
177 ctmp
->value
[2] = ']';
178 if(flags
& SFL_ONLY_LISTMODE
){
179 if(flags
& SFL_CTRLC
)
180 ctmp
->keymenu
= &sel_from_list_olm_ctrlc
;
182 ctmp
->keymenu
= &sel_from_list_olm
;
185 if(flags
& SFL_CTRLC
)
186 ctmp
->keymenu
= &sel_from_list_lm_ctrlc
;
188 ctmp
->keymenu
= &sel_from_list_lm
;
193 memset(&screen
, 0, sizeof(screen
));
194 switch(conf_scroll_screen(ps_global
, &screen
, first_line
, title
, pdesc
, 0, NULL
)){
203 ps_global
->mangled_screen
= 1;
209 select_from_list_tool(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
216 if(*(*cl
)->d
.l
.listmode
== SingleMode
){
217 (*cl
)->d
.l
.lsel
->selected
= 1;
221 /* check if anything is selected */
222 /* go to first line */
223 for(ctmp
= *cl
; prev_confline(ctmp
); ctmp
= prev_confline(ctmp
))
226 for(; ctmp
; ctmp
= next_confline(ctmp
))
227 if(!(ctmp
->flags
& CF_NOSELECT
) && ctmp
->d
.l
.lsel
->selected
){
233 q_status_message(SM_ORDER
, 0, 3,
234 _("Nothing selected, use Exit to exit without a selection."));
241 if(*(*cl
)->d
.l
.listmode
== SingleMode
){
243 * UnHide the checkboxes
246 *(*cl
)->d
.l
.listmode
= ListMode
;
248 /* go to first line */
249 for(ctmp
= *cl
; prev_confline(ctmp
); ctmp
= prev_confline(ctmp
))
252 for(; ctmp
; ctmp
= next_confline(ctmp
))
253 if(!(ctmp
->flags
& CF_NOSELECT
) && ctmp
->value
){
254 ctmp
->value
[0] = '[';
255 ctmp
->value
[1] = ctmp
->d
.l
.lsel
->selected
? 'X' : SPACE
;
256 ctmp
->value
[2] = ']';
257 ctmp
->keymenu
= &sel_from_list_lm
;
262 * Hide the checkboxes
265 *(*cl
)->d
.l
.listmode
= SingleMode
;
267 /* go to first line */
268 for(ctmp
= *cl
; prev_confline(ctmp
); ctmp
= prev_confline(ctmp
))
271 for(; ctmp
; ctmp
= next_confline(ctmp
))
272 if(!(ctmp
->flags
& CF_NOSELECT
) && ctmp
->value
){
273 ctmp
->value
[0] = ctmp
->value
[1] = ctmp
->value
[2] = SPACE
;
274 ctmp
->keymenu
= &sel_from_list_sm
;
278 ps
->mangled_body
= ps
->mangled_footer
= 1;
282 if((*cl
)->value
[1] == 'X'){
283 (*cl
)->d
.l
.lsel
->selected
= 0;
284 (*cl
)->value
[1] = SPACE
;
287 (*cl
)->d
.l
.lsel
->selected
= 1;
288 (*cl
)->value
[1] = 'X';
291 ps
->mangled_body
= 1;
295 retval
= simple_exit_cmd(flags
);
304 ps
->mangled_body
= 1;
311 select_from_list_tool_allow_noselections(struct pine
*ps
, int cmd
, CONF_S
**cl
, unsigned int flags
)
318 if(*(*cl
)->d
.l
.listmode
== SingleMode
)
319 (*cl
)->d
.l
.lsel
->selected
= 1;
324 retval
= select_from_list_tool(ps
, cmd
, cl
, flags
);
329 ps
->mangled_body
= 1;