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