]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/bsdinstall/partedit/diskeditor.c
MFC r326276:
[FreeBSD/FreeBSD.git] / usr.sbin / bsdinstall / partedit / diskeditor.c
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
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
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