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