aboutsummaryrefslogtreecommitdiff
path: root/bsdinstall/partedit/diskeditor.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsdinstall/partedit/diskeditor.c')
-rw-r--r--bsdinstall/partedit/diskeditor.c292
1 files changed, 292 insertions, 0 deletions
diff --git a/bsdinstall/partedit/diskeditor.c b/bsdinstall/partedit/diskeditor.c
new file mode 100644
index 000000000000..1679def32a19
--- /dev/null
+++ b/bsdinstall/partedit/diskeditor.c
@@ -0,0 +1,292 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2011 Nathan Whitehorn
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <libutil.h>
+#include <dialog.h>
+#include <dlg_keys.h>
+
+#include "diskeditor.h"
+
+static void
+print_partedit_item(WINDOW *partitions, struct partedit_item *items,
+ int item, int nscroll, int selected)
+{
+ chtype attr = A_NORMAL;
+ char sizetext[16];
+ int y = item - nscroll + 1;
+
+ wattrset(partitions, selected ? item_selected_attr : item_attr);
+ wmove(partitions, y, MARGIN + items[item].indentation*2);
+ dlg_print_text(partitions, items[item].name, 10, &attr);
+ wmove(partitions, y, 17);
+ wattrset(partitions, item_attr);
+
+ humanize_number(sizetext, 7, items[item].size, "B", HN_AUTOSCALE,
+ HN_DECIMAL);
+ dlg_print_text(partitions, sizetext, 8, &attr);
+ wmove(partitions, y, 25);
+ dlg_print_text(partitions, items[item].type, 15, &attr);
+ wmove(partitions, y, 40);
+ if (items[item].mountpoint != NULL)
+ dlg_print_text(partitions, items[item].mountpoint, 8, &attr);
+}
+
+int
+diskeditor_show(const char *title, const char *cprompt,
+ struct partedit_item *items, int nitems, int *selected, int *nscroll)
+{
+ WINDOW *dialog, *partitions;
+ char *prompt;
+ const char *buttons[] =
+ { "Create", "Delete", "Modify", "Revert", "Auto", "Finish", NULL };
+ const char *help_text[] = {
+ "Add a new partition", "Delete selected partition or partitions",
+ "Change partition type or mountpoint",
+ "Revert changes to disk setup", "Use guided partitioning tool",
+ "Exit partitioner (will ask whether to save changes)", NULL };
+ int x, y;
+ int i;
+ int height, width, min_width;
+ int partlist_height, partlist_width;
+ int cur_scroll = 0;
+ int key, fkey;
+ int cur_button = 5, cur_part = 0;
+ int result = DLG_EXIT_UNKNOWN;
+
+ static DLG_KEYS_BINDING binding[] = {
+ ENTERKEY_BINDINGS,
+ DLG_KEYS_DATA( DLGK_ENTER, ' ' ),
+ DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_DOWN ),
+ DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_UP ),
+ DLG_KEYS_DATA( DLGK_FIELD_NEXT, KEY_RIGHT ),
+ DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ),
+ DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ),
+ DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_LEFT ),
+
+ SCROLLKEY_BINDINGS,
+ END_KEYS_BINDING
+ };
+
+ static DLG_KEYS_BINDING binding2[] = {
+ INPUTSTR_BINDINGS,
+ ENTERKEY_BINDINGS,
+ DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ),
+ DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ),
+ DLG_KEYS_DATA( DLGK_ITEM_NEXT, CHR_NEXT ),
+ DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_DOWN ),
+ DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_NEXT ),
+ DLG_KEYS_DATA( DLGK_ITEM_PREV, CHR_PREVIOUS ),
+ DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_PREVIOUS ),
+ DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_UP ),
+ DLG_KEYS_DATA( DLGK_PAGE_NEXT, KEY_NPAGE ),
+ DLG_KEYS_DATA( DLGK_PAGE_PREV, KEY_PPAGE ),
+ END_KEYS_BINDING
+ };
+
+ /*
+ * Set up editor window.
+ */
+ prompt = dlg_strclone(cprompt);
+
+ min_width = 50;
+ height = width = 0;
+ partlist_height = 10;
+ dlg_tab_correct_str(prompt);
+ dlg_button_layout(buttons, &min_width);
+ dlg_auto_size(title, prompt, &height, &width, 2, min_width);
+ height += partlist_height;
+ partlist_width = width - 2*MARGIN;
+ dlg_print_size(height, width);
+ dlg_ctl_size(height, width);
+
+ x = dlg_box_x_ordinate(width);
+ y = dlg_box_y_ordinate(height);
+
+ dialog = dlg_new_window(height, width, y, x);
+ dlg_register_window(dialog, "diskeditorbox", binding);
+ dlg_register_buttons(dialog, "diskeditorbox", buttons);
+
+ dlg_draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
+ dlg_draw_bottom_box(dialog);
+ dlg_draw_title(dialog, title);
+ wattrset(dialog, dialog_attr);
+
+ /* Partition list sub-window */
+ partitions = dlg_sub_window(dialog, partlist_height, partlist_width,
+ y + 3, x + 1);
+ dlg_register_window(partitions, "partlist", binding2);
+ dlg_register_buttons(partitions, "partlist", buttons);
+ wattrset(partitions, menubox_attr);
+
+ dlg_item_help(help_text[cur_button]);
+ dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
+ cur_button, FALSE, width);
+ dlg_print_autowrap(dialog, prompt, height, width);
+
+ if (selected != NULL)
+ cur_part = *selected;
+ if (nscroll != NULL)
+ cur_scroll = *nscroll;
+ if (cur_part - cur_scroll >= partlist_height - 2 ||
+ cur_part - cur_scroll < 0)
+ cur_scroll = cur_part;
+
+repaint:
+ dlg_draw_box(dialog, 3, 1, partlist_height, partlist_width,
+ menubox_border_attr, menubox_attr);
+ for (i = cur_scroll; i < MIN(cur_scroll + partlist_height - 2, nitems);
+ i++)
+ print_partedit_item(partitions, items, i, cur_scroll,
+ i == cur_part);
+ if (nitems > partlist_height - 2)
+ dlg_draw_arrows(partitions, cur_scroll > 0,
+ nitems > cur_scroll + partlist_height - 2,
+ partlist_width - 5, 0, partlist_height - 1);
+ wrefresh(partitions);
+
+ while (result == DLG_EXIT_UNKNOWN) {
+ key = dlg_mouse_wgetch(dialog, &fkey);
+ if ((i = dlg_char_to_button(key, buttons)) >= 0) {
+ cur_button = i;
+ dlg_item_help(help_text[cur_button]);
+ dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
+ cur_button, FALSE, width);
+ break;
+ }
+
+ if (!fkey)
+ continue;
+
+ switch (key) {
+ case DLGK_FIELD_NEXT:
+ cur_button = dlg_next_button(buttons, cur_button);
+ if (cur_button < 0)
+ cur_button = 0;
+ dlg_item_help(help_text[cur_button]);
+ dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
+ cur_button, FALSE, width);
+ break;
+ case DLGK_FIELD_PREV:
+ cur_button = dlg_prev_button(buttons, cur_button);
+ if (cur_button < 0)
+ cur_button = 0;
+ dlg_item_help(help_text[cur_button]);
+ dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
+ cur_button, FALSE, width);
+ break;
+ case DLGK_ITEM_NEXT:
+ if (cur_part == nitems - 1)
+ break; /* End of list */
+
+ /* Deselect old item */
+ print_partedit_item(partitions, items, cur_part,
+ cur_scroll, 0);
+ /* Select new item */
+ cur_part++;
+ if (cur_part - cur_scroll >= partlist_height - 2) {
+ cur_scroll = cur_part;
+ goto repaint;
+ }
+ print_partedit_item(partitions, items, cur_part,
+ cur_scroll, 1);
+ wrefresh(partitions);
+ break;
+ case DLGK_ITEM_PREV:
+ if (cur_part == 0)
+ break; /* Start of list */
+
+ /* Deselect old item */
+ print_partedit_item(partitions, items, cur_part,
+ cur_scroll, 0);
+ /* Select new item */
+ cur_part--;
+ if (cur_part - cur_scroll < 0) {
+ cur_scroll = cur_part;
+ goto repaint;
+ }
+ print_partedit_item(partitions, items, cur_part,
+ cur_scroll, 1);
+ wrefresh(partitions);
+ break;
+ case DLGK_PAGE_NEXT:
+ cur_scroll += (partlist_height - 2);
+ if (cur_scroll + partlist_height - 2 >= nitems)
+ cur_scroll = nitems - (partlist_height - 2);
+ if (cur_scroll < 0)
+ cur_scroll = 0;
+ if (cur_part < cur_scroll)
+ cur_part = cur_scroll;
+ goto repaint;
+ case DLGK_PAGE_PREV:
+ cur_scroll -= (partlist_height - 2);
+ if (cur_scroll < 0)
+ cur_scroll = 0;
+ if (cur_part >= cur_scroll + partlist_height - 2)
+ cur_part = cur_scroll;
+ goto repaint;
+ case DLGK_PAGE_FIRST:
+ cur_scroll = 0;
+ cur_part = cur_scroll;
+ goto repaint;
+ case DLGK_PAGE_LAST:
+ cur_scroll = nitems - (partlist_height - 2);
+ if (cur_scroll < 0)
+ cur_scroll = 0;
+ cur_part = cur_scroll;
+ goto repaint;
+ case DLGK_ENTER:
+ goto done;
+ default:
+ if (is_DLGK_MOUSE(key)) {
+ cur_button = key - M_EVENT;
+ dlg_item_help(help_text[cur_button]);
+ dlg_draw_buttons(dialog, height - 2*MARGIN, 0,
+ buttons, cur_button, FALSE, width);
+ goto done;
+ }
+ break;
+ }
+ }
+
+done:
+ if (selected != NULL)
+ *selected = cur_part;
+ if (nscroll != NULL)
+ *nscroll = cur_scroll;
+
+ dlg_del_window(partitions);
+ dlg_del_window(dialog);
+ dlg_mouse_free_regions();
+
+ return (cur_button);
+}
+