diskeditor.c revision 237253
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: head/usr.sbin/bsdinstall/partedit/diskeditor.c 237253 2012-06-19 06:09:47Z eadler $ 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 37static void 38print_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 61int 62diskeditor_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 = 0, 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 145repaint: 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 262done: 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 275