]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - usr.sbin/bsdinstall/partedit/diskeditor.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.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         /*
98          * Set up editor window.
99          */
100         prompt = dlg_strclone(cprompt);
101
102         min_width = 50;
103         height = width = 0;
104         partlist_height = 10;
105         dlg_tab_correct_str(prompt);
106         dlg_button_layout(buttons, &min_width);
107         dlg_auto_size(title, prompt, &height, &width, 2, min_width);
108         height += partlist_height;
109         partlist_width = width - 2*MARGIN;
110         dlg_print_size(height, width);
111         dlg_ctl_size(height, width);
112
113         x = dlg_box_x_ordinate(width);
114         y = dlg_box_y_ordinate(height);
115
116         dialog = dlg_new_window(height, width, y, x);
117         dlg_register_window(dialog, "diskeditorbox", binding);
118         dlg_register_buttons(dialog, "diskeditorbox", buttons);
119
120         dlg_draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
121         dlg_draw_bottom_box(dialog);
122         dlg_draw_title(dialog, title);
123         wattrset(dialog, dialog_attr);
124
125         /* Partition list sub-window */
126         partitions = dlg_sub_window(dialog, partlist_height, partlist_width,
127             y + 3, x + 1);
128         dlg_register_window(partitions, "partlist", binding);
129         dlg_register_buttons(partitions, "partlist", buttons);
130         wattrset(partitions, menubox_attr);
131
132         dlg_item_help(help_text[cur_button]);
133         dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
134             cur_button, FALSE, width);
135         dlg_print_autowrap(dialog, prompt, height, width);
136
137         if (selected != NULL)
138                 cur_part = *selected;
139         if (nscroll != NULL)
140                 cur_scroll = *nscroll;
141         if (cur_part - cur_scroll >= partlist_height - 2 ||
142             cur_part - cur_scroll < 0)
143                 cur_scroll = cur_part;
144
145 repaint:
146         dlg_draw_box(dialog, 3, 1,  partlist_height, partlist_width,
147             menubox_border_attr, menubox_attr);
148         for (i = cur_scroll; i < MIN(cur_scroll + partlist_height - 2, nitems);
149             i++)
150                 print_partedit_item(partitions, items, i, cur_scroll,
151                     i == cur_part);
152         if (nitems > partlist_height - 2)
153                 dlg_draw_arrows(partitions, cur_scroll > 0,
154                     nitems > cur_scroll + partlist_height - 2,
155                     partlist_width - 5, 0, partlist_height - 1);
156         wrefresh(partitions);
157
158         while (result == DLG_EXIT_UNKNOWN) {
159                 key = dlg_mouse_wgetch(dialog, &fkey);
160                 if ((i = dlg_char_to_button(key, buttons)) >= 0) {
161                         cur_button = i;
162                         dlg_item_help(help_text[cur_button]);
163                         dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
164                             cur_button, FALSE, width);
165                         break;
166                 }
167
168                 if (!fkey)
169                         continue;
170
171                 switch (key) {
172                 case DLGK_FIELD_NEXT:
173                         cur_button = dlg_next_button(buttons, cur_button);
174                         if (cur_button < 0)
175                                 cur_button = 0;
176                         dlg_item_help(help_text[cur_button]);
177                         dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
178                             cur_button, FALSE, width);
179                         break;
180                 case DLGK_FIELD_PREV:
181                         cur_button = dlg_prev_button(buttons, cur_button);
182                         if (cur_button < 0)
183                                 cur_button = 0;
184                         dlg_item_help(help_text[cur_button]);
185                         dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
186                             cur_button, FALSE, width);
187                         break;
188                 case DLGK_ITEM_NEXT:
189                         if (cur_part == nitems - 1)
190                                 break; /* End of list */
191
192                         /* Deselect old item */
193                         print_partedit_item(partitions, items, cur_part,
194                             cur_scroll, 0);
195                         /* Select new item */
196                         cur_part++;
197                         if (cur_part - cur_scroll >= partlist_height - 2) {
198                                 cur_scroll = cur_part;
199                                 goto repaint;
200                         }
201                         print_partedit_item(partitions, items, cur_part,
202                             cur_scroll, 1);
203                         wrefresh(partitions);
204                         break;
205                 case DLGK_ITEM_PREV:
206                         if (cur_part == 0)
207                                 break; /* Start of list */
208
209                         /* Deselect old item */
210                         print_partedit_item(partitions, items, cur_part,
211                             cur_scroll, 0);
212                         /* Select new item */
213                         cur_part--;
214                         if (cur_part - cur_scroll < 0) {
215                                 cur_scroll = cur_part;
216                                 goto repaint;
217                         }
218                         print_partedit_item(partitions, items, cur_part,
219                             cur_scroll, 1);
220                         wrefresh(partitions);
221                         break;
222                 case DLGK_PAGE_NEXT:
223                         cur_scroll += (partlist_height - 2);
224                         if (cur_scroll + partlist_height - 2 >= nitems)
225                                 cur_scroll = nitems - (partlist_height - 2);
226                         if (cur_scroll < 0)
227                                 cur_scroll = 0;
228                         if (cur_part < cur_scroll)
229                                 cur_part = cur_scroll;
230                         goto repaint;
231                 case DLGK_PAGE_PREV:
232                         cur_scroll -= (partlist_height - 2);
233                         if (cur_scroll < 0)
234                                 cur_scroll = 0;
235                         if (cur_part >= cur_scroll + partlist_height - 2)
236                                 cur_part = cur_scroll;
237                         goto repaint;
238                 case DLGK_PAGE_FIRST:
239                         cur_scroll = 0;
240                         cur_part = cur_scroll;
241                         goto repaint;
242                 case DLGK_PAGE_LAST:
243                         cur_scroll = nitems - (partlist_height - 2);
244                         if (cur_scroll < 0)
245                                 cur_scroll = 0;
246                         cur_part = cur_scroll;
247                         goto repaint;
248                 case DLGK_ENTER:
249                         goto done;
250                 default:
251                         if (is_DLGK_MOUSE(key)) {
252                                 cur_button = key - M_EVENT;
253                                 dlg_item_help(help_text[cur_button]);
254                                 dlg_draw_buttons(dialog, height - 2*MARGIN, 0,
255                                     buttons, cur_button, FALSE, width);
256                                 goto done;
257                         }
258                         break;
259                 }
260         }
261
262 done:
263         if (selected != NULL)
264                 *selected = cur_part;
265         if (nscroll != NULL)
266                 *nscroll = cur_scroll;
267
268         dlg_del_window(partitions);
269         dlg_del_window(dialog);
270         dlg_mouse_free_regions();
271
272         return (cur_button);
273 }
274