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 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 = 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 161repaint: 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 278done: 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 291