1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2011 Nathan Whitehorn
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD$
29 */
30
31 #include <stdio.h>
32 #include <unistd.h>
33 #include <libutil.h>
34 #include <dialog.h>
35 #include <dlg_keys.h>
36
37 #include "diskeditor.h"
38
39 static void
print_partedit_item(WINDOW * partitions,struct partedit_item * items,int item,int nscroll,int selected)40 print_partedit_item(WINDOW *partitions, struct partedit_item *items,
41 int item, int nscroll, int selected)
42 {
43 chtype attr = A_NORMAL;
44 char sizetext[16];
45 int y = item - nscroll + 1;
46
47 wattrset(partitions, selected ? item_selected_attr : item_attr);
48 wmove(partitions, y, MARGIN + items[item].indentation*2);
49 dlg_print_text(partitions, items[item].name, 10, &attr);
50 wmove(partitions, y, 17);
51 wattrset(partitions, item_attr);
52
53 humanize_number(sizetext, 7, items[item].size, "B", HN_AUTOSCALE,
54 HN_DECIMAL);
55 dlg_print_text(partitions, sizetext, 8, &attr);
56 wmove(partitions, y, 25);
57 dlg_print_text(partitions, items[item].type, 15, &attr);
58 wmove(partitions, y, 40);
59 if (items[item].mountpoint != NULL)
60 dlg_print_text(partitions, items[item].mountpoint, 8, &attr);
61 }
62
63 int
diskeditor_show(const char * title,const char * cprompt,struct partedit_item * items,int nitems,int * selected,int * nscroll)64 diskeditor_show(const char *title, const char *cprompt,
65 struct partedit_item *items, int nitems, int *selected, int *nscroll)
66 {
67 WINDOW *dialog, *partitions;
68 char *prompt;
69 const char *buttons[] =
70 { "Create", "Delete", "Modify", "Revert", "Auto", "Finish", NULL };
71 const char *help_text[] = {
72 "Add a new partition", "Delete selected partition or partitions",
73 "Change partition type or mountpoint",
74 "Revert changes to disk setup", "Use guided partitioning tool",
75 "Exit partitioner (will ask whether to save changes)", NULL };
76 int x, y;
77 int i;
78 int height, width, min_width;
79 int partlist_height, partlist_width;
80 int cur_scroll = 0;
81 int key, fkey;
82 int cur_button = 5, cur_part = 0;
83 int result = DLG_EXIT_UNKNOWN;
84
85 static DLG_KEYS_BINDING binding[] = {
86 ENTERKEY_BINDINGS,
87 DLG_KEYS_DATA( DLGK_ENTER, ' ' ),
88 DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_DOWN ),
89 DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_UP ),
90 DLG_KEYS_DATA( DLGK_FIELD_NEXT, KEY_RIGHT ),
91 DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ),
92 DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ),
93 DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_LEFT ),
94
95 SCROLLKEY_BINDINGS,
96 END_KEYS_BINDING
97 };
98
99 static DLG_KEYS_BINDING binding2[] = {
100 INPUTSTR_BINDINGS,
101 ENTERKEY_BINDINGS,
102 DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ),
103 DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ),
104 DLG_KEYS_DATA( DLGK_ITEM_NEXT, CHR_NEXT ),
105 DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_DOWN ),
106 DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_NEXT ),
107 DLG_KEYS_DATA( DLGK_ITEM_PREV, CHR_PREVIOUS ),
108 DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_PREVIOUS ),
109 DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_UP ),
110 DLG_KEYS_DATA( DLGK_PAGE_NEXT, KEY_NPAGE ),
111 DLG_KEYS_DATA( DLGK_PAGE_PREV, KEY_PPAGE ),
112 END_KEYS_BINDING
113 };
114
115 /*
116 * Set up editor window.
117 */
118 prompt = dlg_strclone(cprompt);
119
120 min_width = 50;
121 height = width = 0;
122 partlist_height = 10;
123 dlg_tab_correct_str(prompt);
124 dlg_button_layout(buttons, &min_width);
125 dlg_auto_size(title, prompt, &height, &width, 2, min_width);
126 height += partlist_height;
127 partlist_width = width - 2*MARGIN;
128 dlg_print_size(height, width);
129 dlg_ctl_size(height, width);
130
131 x = dlg_box_x_ordinate(width);
132 y = dlg_box_y_ordinate(height);
133
134 dialog = dlg_new_window(height, width, y, x);
135 dlg_register_window(dialog, "diskeditorbox", binding);
136 dlg_register_buttons(dialog, "diskeditorbox", buttons);
137
138 dlg_draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
139 dlg_draw_bottom_box(dialog);
140 dlg_draw_title(dialog, title);
141 wattrset(dialog, dialog_attr);
142
143 /* Partition list sub-window */
144 partitions = dlg_sub_window(dialog, partlist_height, partlist_width,
145 y + 3, x + 1);
146 dlg_register_window(partitions, "partlist", binding2);
147 dlg_register_buttons(partitions, "partlist", buttons);
148 wattrset(partitions, menubox_attr);
149
150 dlg_item_help(help_text[cur_button]);
151 dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
152 cur_button, FALSE, width);
153 dlg_print_autowrap(dialog, prompt, height, width);
154
155 if (selected != NULL)
156 cur_part = *selected;
157 if (nscroll != NULL)
158 cur_scroll = *nscroll;
159 if (cur_part - cur_scroll >= partlist_height - 2 ||
160 cur_part - cur_scroll < 0)
161 cur_scroll = cur_part;
162
163 repaint:
164 dlg_draw_box(dialog, 3, 1, partlist_height, partlist_width,
165 menubox_border_attr, menubox_attr);
166 for (i = cur_scroll; i < MIN(cur_scroll + partlist_height - 2, nitems);
167 i++)
168 print_partedit_item(partitions, items, i, cur_scroll,
169 i == cur_part);
170 if (nitems > partlist_height - 2)
171 dlg_draw_arrows(partitions, cur_scroll > 0,
172 nitems > cur_scroll + partlist_height - 2,
173 partlist_width - 5, 0, partlist_height - 1);
174 wrefresh(partitions);
175
176 while (result == DLG_EXIT_UNKNOWN) {
177 key = dlg_mouse_wgetch(dialog, &fkey);
178 if ((i = dlg_char_to_button(key, buttons)) >= 0) {
179 cur_button = i;
180 dlg_item_help(help_text[cur_button]);
181 dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
182 cur_button, FALSE, width);
183 break;
184 }
185
186 if (!fkey)
187 continue;
188
189 switch (key) {
190 case DLGK_FIELD_NEXT:
191 cur_button = dlg_next_button(buttons, cur_button);
192 if (cur_button < 0)
193 cur_button = 0;
194 dlg_item_help(help_text[cur_button]);
195 dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
196 cur_button, FALSE, width);
197 break;
198 case DLGK_FIELD_PREV:
199 cur_button = dlg_prev_button(buttons, cur_button);
200 if (cur_button < 0)
201 cur_button = 0;
202 dlg_item_help(help_text[cur_button]);
203 dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
204 cur_button, FALSE, width);
205 break;
206 case DLGK_ITEM_NEXT:
207 if (cur_part == nitems - 1)
208 break; /* End of list */
209
210 /* Deselect old item */
211 print_partedit_item(partitions, items, cur_part,
212 cur_scroll, 0);
213 /* Select new item */
214 cur_part++;
215 if (cur_part - cur_scroll >= partlist_height - 2) {
216 cur_scroll = cur_part;
217 goto repaint;
218 }
219 print_partedit_item(partitions, items, cur_part,
220 cur_scroll, 1);
221 wrefresh(partitions);
222 break;
223 case DLGK_ITEM_PREV:
224 if (cur_part == 0)
225 break; /* Start of list */
226
227 /* Deselect old item */
228 print_partedit_item(partitions, items, cur_part,
229 cur_scroll, 0);
230 /* Select new item */
231 cur_part--;
232 if (cur_part - cur_scroll < 0) {
233 cur_scroll = cur_part;
234 goto repaint;
235 }
236 print_partedit_item(partitions, items, cur_part,
237 cur_scroll, 1);
238 wrefresh(partitions);
239 break;
240 case DLGK_PAGE_NEXT:
241 cur_scroll += (partlist_height - 2);
242 if (cur_scroll + partlist_height - 2 >= nitems)
243 cur_scroll = nitems - (partlist_height - 2);
244 if (cur_scroll < 0)
245 cur_scroll = 0;
246 if (cur_part < cur_scroll)
247 cur_part = cur_scroll;
248 goto repaint;
249 case DLGK_PAGE_PREV:
250 cur_scroll -= (partlist_height - 2);
251 if (cur_scroll < 0)
252 cur_scroll = 0;
253 if (cur_part >= cur_scroll + partlist_height - 2)
254 cur_part = cur_scroll;
255 goto repaint;
256 case DLGK_PAGE_FIRST:
257 cur_scroll = 0;
258 cur_part = cur_scroll;
259 goto repaint;
260 case DLGK_PAGE_LAST:
261 cur_scroll = nitems - (partlist_height - 2);
262 if (cur_scroll < 0)
263 cur_scroll = 0;
264 cur_part = cur_scroll;
265 goto repaint;
266 case DLGK_ENTER:
267 goto done;
268 default:
269 if (is_DLGK_MOUSE(key)) {
270 cur_button = key - M_EVENT;
271 dlg_item_help(help_text[cur_button]);
272 dlg_draw_buttons(dialog, height - 2*MARGIN, 0,
273 buttons, cur_button, FALSE, width);
274 goto done;
275 }
276 break;
277 }
278 }
279
280 done:
281 if (selected != NULL)
282 *selected = cur_part;
283 if (nscroll != NULL)
284 *nscroll = cur_scroll;
285
286 dlg_del_window(partitions);
287 dlg_del_window(dialog);
288 dlg_mouse_free_regions();
289
290 return (cur_button);
291 }
292
293