1218799Snwhitehorn/*-
2218799Snwhitehorn * Copyright (c) 2011 Nathan Whitehorn
3218799Snwhitehorn * All rights reserved.
4218799Snwhitehorn *
5218799Snwhitehorn * Redistribution and use in source and binary forms, with or without
6218799Snwhitehorn * modification, are permitted provided that the following conditions
7218799Snwhitehorn * are met:
8218799Snwhitehorn * 1. Redistributions of source code must retain the above copyright
9218799Snwhitehorn *    notice, this list of conditions and the following disclaimer.
10218799Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright
11218799Snwhitehorn *    notice, this list of conditions and the following disclaimer in the
12218799Snwhitehorn *    documentation and/or other materials provided with the distribution.
13218799Snwhitehorn *
14218799Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15218799Snwhitehorn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16218799Snwhitehorn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17218799Snwhitehorn * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18218799Snwhitehorn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19218799Snwhitehorn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20218799Snwhitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21218799Snwhitehorn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22218799Snwhitehorn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23218799Snwhitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24218799Snwhitehorn * SUCH DAMAGE.
25218799Snwhitehorn *
26218799Snwhitehorn * $FreeBSD$
27218799Snwhitehorn */
28218799Snwhitehorn
29218799Snwhitehorn#include <stdio.h>
30218799Snwhitehorn#include <unistd.h>
31218799Snwhitehorn#include <libutil.h>
32218799Snwhitehorn#include <dialog.h>
33218799Snwhitehorn#include <dlg_keys.h>
34218799Snwhitehorn
35218799Snwhitehorn#include "diskeditor.h"
36218799Snwhitehorn
37218799Snwhitehornstatic void
38218799Snwhitehornprint_partedit_item(WINDOW *partitions, struct partedit_item *items,
39218799Snwhitehorn    int item, int nscroll, int selected)
40218799Snwhitehorn{
41218799Snwhitehorn	chtype attr = A_NORMAL;
42218799Snwhitehorn	char sizetext[16];
43218799Snwhitehorn	int y = item - nscroll + 1;
44218799Snwhitehorn
45218799Snwhitehorn	wattrset(partitions, selected ? item_selected_attr : item_attr);
46218799Snwhitehorn	wmove(partitions, y, MARGIN + items[item].indentation*2);
47226212Snwhitehorn	dlg_print_text(partitions, items[item].name, 10, &attr);
48226212Snwhitehorn	wmove(partitions, y, 17);
49218799Snwhitehorn	wattrset(partitions, item_attr);
50218799Snwhitehorn
51218799Snwhitehorn	humanize_number(sizetext, 7, items[item].size, "B", HN_AUTOSCALE,
52218799Snwhitehorn	    HN_DECIMAL);
53218799Snwhitehorn	dlg_print_text(partitions, sizetext, 8, &attr);
54218799Snwhitehorn	wmove(partitions, y, 25);
55218799Snwhitehorn	dlg_print_text(partitions, items[item].type, 15, &attr);
56218799Snwhitehorn	wmove(partitions, y, 40);
57218799Snwhitehorn	if (items[item].mountpoint != NULL)
58218799Snwhitehorn		dlg_print_text(partitions, items[item].mountpoint, 8, &attr);
59218799Snwhitehorn}
60218799Snwhitehorn
61218799Snwhitehornint
62218799Snwhitehorndiskeditor_show(const char *title, const char *cprompt,
63218799Snwhitehorn    struct partedit_item *items, int nitems, int *selected, int *nscroll)
64218799Snwhitehorn{
65218799Snwhitehorn	WINDOW *dialog, *partitions;
66218799Snwhitehorn	char *prompt;
67218799Snwhitehorn	const char *buttons[] =
68225066Snwhitehorn	    { "Create", "Delete", "Modify", "Revert", "Auto", "Finish", NULL };
69225066Snwhitehorn	const char *help_text[] = {
70225066Snwhitehorn	    "Add a new partition", "Delete selected partition or partitions",
71225066Snwhitehorn	    "Change partition type or mountpoint",
72225066Snwhitehorn	    "Revert changes to disk setup", "Use guided partitioning tool",
73225066Snwhitehorn	    "Exit partitioner (will ask whether to save changes)", NULL };
74218799Snwhitehorn	int x, y;
75218799Snwhitehorn	int i;
76218799Snwhitehorn	int height, width, min_width;
77237428Seadler	int partlist_height, partlist_width;
78218799Snwhitehorn	int cur_scroll = 0;
79218799Snwhitehorn	int key, fkey;
80248239Snwhitehorn	int cur_button = 5, cur_part = 0;
81218799Snwhitehorn	int result = DLG_EXIT_UNKNOWN;
82218799Snwhitehorn
83218799Snwhitehorn	static DLG_KEYS_BINDING binding[] = {
84218799Snwhitehorn		ENTERKEY_BINDINGS,
85218799Snwhitehorn		DLG_KEYS_DATA( DLGK_ENTER,      ' ' ),
86218799Snwhitehorn		DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_DOWN ),
87218799Snwhitehorn		DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_UP ),
88218799Snwhitehorn		DLG_KEYS_DATA( DLGK_FIELD_NEXT, KEY_RIGHT ),
89218799Snwhitehorn		DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ),
90218799Snwhitehorn		DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ),
91218799Snwhitehorn		DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_LEFT ),
92218799Snwhitehorn
93218799Snwhitehorn		SCROLLKEY_BINDINGS,
94218799Snwhitehorn		END_KEYS_BINDING
95218799Snwhitehorn	};
96218799Snwhitehorn
97218799Snwhitehorn	/*
98218799Snwhitehorn	 * Set up editor window.
99218799Snwhitehorn	 */
100218799Snwhitehorn	prompt = dlg_strclone(cprompt);
101218799Snwhitehorn
102218799Snwhitehorn	min_width = 50;
103218799Snwhitehorn	height = width = 0;
104218799Snwhitehorn	partlist_height = 10;
105218799Snwhitehorn	dlg_tab_correct_str(prompt);
106218799Snwhitehorn	dlg_button_layout(buttons, &min_width);
107218799Snwhitehorn	dlg_auto_size(title, prompt, &height, &width, 2, min_width);
108218799Snwhitehorn	height += partlist_height;
109218799Snwhitehorn	partlist_width = width - 2*MARGIN;
110218799Snwhitehorn	dlg_print_size(height, width);
111218799Snwhitehorn	dlg_ctl_size(height, width);
112218799Snwhitehorn
113218799Snwhitehorn	x = dlg_box_x_ordinate(width);
114218799Snwhitehorn	y = dlg_box_y_ordinate(height);
115218799Snwhitehorn
116218799Snwhitehorn	dialog = dlg_new_window(height, width, y, x);
117218799Snwhitehorn	dlg_register_window(dialog, "diskeditorbox", binding);
118218799Snwhitehorn	dlg_register_buttons(dialog, "diskeditorbox", buttons);
119218799Snwhitehorn
120218799Snwhitehorn	dlg_draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
121218799Snwhitehorn	dlg_draw_bottom_box(dialog);
122218799Snwhitehorn	dlg_draw_title(dialog, title);
123218799Snwhitehorn	wattrset(dialog, dialog_attr);
124218799Snwhitehorn
125218799Snwhitehorn	/* Partition list sub-window */
126218799Snwhitehorn	partitions = dlg_sub_window(dialog, partlist_height, partlist_width,
127218799Snwhitehorn	    y + 3, x + 1);
128218799Snwhitehorn	dlg_register_window(partitions, "partlist", binding);
129218799Snwhitehorn	dlg_register_buttons(partitions, "partlist", buttons);
130218799Snwhitehorn	wattrset(partitions, menubox_attr);
131218799Snwhitehorn
132225066Snwhitehorn	dlg_item_help(help_text[cur_button]);
133218799Snwhitehorn	dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
134218799Snwhitehorn	    cur_button, FALSE, width);
135218799Snwhitehorn	dlg_print_autowrap(dialog, prompt, height, width);
136218799Snwhitehorn
137218799Snwhitehorn	if (selected != NULL)
138218799Snwhitehorn		cur_part = *selected;
139218799Snwhitehorn	if (nscroll != NULL)
140218799Snwhitehorn		cur_scroll = *nscroll;
141218799Snwhitehorn	if (cur_part - cur_scroll >= partlist_height - 2 ||
142218799Snwhitehorn	    cur_part - cur_scroll < 0)
143218799Snwhitehorn		cur_scroll = cur_part;
144218799Snwhitehorn
145218799Snwhitehornrepaint:
146218799Snwhitehorn	dlg_draw_box(dialog, 3, 1,  partlist_height, partlist_width,
147218799Snwhitehorn	    menubox_border_attr, menubox_attr);
148218799Snwhitehorn	for (i = cur_scroll; i < MIN(cur_scroll + partlist_height - 2, nitems);
149218799Snwhitehorn	    i++)
150218799Snwhitehorn		print_partedit_item(partitions, items, i, cur_scroll,
151218799Snwhitehorn		    i == cur_part);
152218799Snwhitehorn	if (nitems > partlist_height - 2)
153218799Snwhitehorn		dlg_draw_arrows(partitions, cur_scroll > 0,
154218799Snwhitehorn		    nitems > cur_scroll + partlist_height - 2,
155218799Snwhitehorn		    partlist_width - 5, 0, partlist_height - 1);
156218799Snwhitehorn	wrefresh(partitions);
157218799Snwhitehorn
158218799Snwhitehorn	while (result == DLG_EXIT_UNKNOWN) {
159218799Snwhitehorn		key = dlg_mouse_wgetch(dialog, &fkey);
160218799Snwhitehorn		if ((i = dlg_char_to_button(key, buttons)) >= 0) {
161218799Snwhitehorn			cur_button = i;
162225066Snwhitehorn			dlg_item_help(help_text[cur_button]);
163218799Snwhitehorn			dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
164218799Snwhitehorn			    cur_button, FALSE, width);
165218799Snwhitehorn			break;
166218799Snwhitehorn		}
167218799Snwhitehorn
168218799Snwhitehorn		if (!fkey)
169218799Snwhitehorn			continue;
170218799Snwhitehorn
171218799Snwhitehorn		switch (key) {
172218799Snwhitehorn		case DLGK_FIELD_NEXT:
173218799Snwhitehorn			cur_button = dlg_next_button(buttons, cur_button);
174218799Snwhitehorn			if (cur_button < 0)
175218799Snwhitehorn				cur_button = 0;
176225066Snwhitehorn			dlg_item_help(help_text[cur_button]);
177218799Snwhitehorn			dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
178218799Snwhitehorn			    cur_button, FALSE, width);
179218799Snwhitehorn			break;
180218799Snwhitehorn		case DLGK_FIELD_PREV:
181218799Snwhitehorn			cur_button = dlg_prev_button(buttons, cur_button);
182218799Snwhitehorn			if (cur_button < 0)
183218799Snwhitehorn				cur_button = 0;
184225066Snwhitehorn			dlg_item_help(help_text[cur_button]);
185218799Snwhitehorn			dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
186218799Snwhitehorn			    cur_button, FALSE, width);
187218799Snwhitehorn			break;
188218799Snwhitehorn		case DLGK_ITEM_NEXT:
189218799Snwhitehorn			if (cur_part == nitems - 1)
190218799Snwhitehorn				break; /* End of list */
191218799Snwhitehorn
192218799Snwhitehorn			/* Deselect old item */
193218799Snwhitehorn			print_partedit_item(partitions, items, cur_part,
194218799Snwhitehorn			    cur_scroll, 0);
195218799Snwhitehorn			/* Select new item */
196218799Snwhitehorn			cur_part++;
197218799Snwhitehorn			if (cur_part - cur_scroll >= partlist_height - 2) {
198218799Snwhitehorn				cur_scroll = cur_part;
199218799Snwhitehorn				goto repaint;
200218799Snwhitehorn			}
201218799Snwhitehorn			print_partedit_item(partitions, items, cur_part,
202218799Snwhitehorn			    cur_scroll, 1);
203218799Snwhitehorn			wrefresh(partitions);
204218799Snwhitehorn			break;
205218799Snwhitehorn		case DLGK_ITEM_PREV:
206218799Snwhitehorn			if (cur_part == 0)
207218799Snwhitehorn				break; /* Start of list */
208218799Snwhitehorn
209218799Snwhitehorn			/* Deselect old item */
210218799Snwhitehorn			print_partedit_item(partitions, items, cur_part,
211218799Snwhitehorn			    cur_scroll, 0);
212218799Snwhitehorn			/* Select new item */
213218799Snwhitehorn			cur_part--;
214218799Snwhitehorn			if (cur_part - cur_scroll < 0) {
215218799Snwhitehorn				cur_scroll = cur_part;
216218799Snwhitehorn				goto repaint;
217218799Snwhitehorn			}
218218799Snwhitehorn			print_partedit_item(partitions, items, cur_part,
219218799Snwhitehorn			    cur_scroll, 1);
220218799Snwhitehorn			wrefresh(partitions);
221218799Snwhitehorn			break;
222218799Snwhitehorn		case DLGK_PAGE_NEXT:
223218799Snwhitehorn			cur_scroll += (partlist_height - 2);
224218799Snwhitehorn			if (cur_scroll + partlist_height - 2 >= nitems)
225218799Snwhitehorn				cur_scroll = nitems - (partlist_height - 2);
226225066Snwhitehorn			if (cur_scroll < 0)
227225066Snwhitehorn				cur_scroll = 0;
228218799Snwhitehorn			if (cur_part < cur_scroll)
229218799Snwhitehorn				cur_part = cur_scroll;
230218799Snwhitehorn			goto repaint;
231218799Snwhitehorn		case DLGK_PAGE_PREV:
232218799Snwhitehorn			cur_scroll -= (partlist_height - 2);
233218799Snwhitehorn			if (cur_scroll < 0)
234218799Snwhitehorn				cur_scroll = 0;
235218799Snwhitehorn			if (cur_part >= cur_scroll + partlist_height - 2)
236218799Snwhitehorn				cur_part = cur_scroll;
237218799Snwhitehorn			goto repaint;
238218799Snwhitehorn		case DLGK_PAGE_FIRST:
239218799Snwhitehorn			cur_scroll = 0;
240218799Snwhitehorn			cur_part = cur_scroll;
241218799Snwhitehorn			goto repaint;
242218799Snwhitehorn		case DLGK_PAGE_LAST:
243218799Snwhitehorn			cur_scroll = nitems - (partlist_height - 2);
244225066Snwhitehorn			if (cur_scroll < 0)
245225066Snwhitehorn				cur_scroll = 0;
246218799Snwhitehorn			cur_part = cur_scroll;
247218799Snwhitehorn			goto repaint;
248218799Snwhitehorn		case DLGK_ENTER:
249218799Snwhitehorn			goto done;
250218799Snwhitehorn		default:
251218799Snwhitehorn			if (is_DLGK_MOUSE(key)) {
252218799Snwhitehorn				cur_button = key - M_EVENT;
253225066Snwhitehorn				dlg_item_help(help_text[cur_button]);
254218799Snwhitehorn				dlg_draw_buttons(dialog, height - 2*MARGIN, 0,
255218799Snwhitehorn				    buttons, cur_button, FALSE, width);
256218799Snwhitehorn				goto done;
257218799Snwhitehorn			}
258218799Snwhitehorn			break;
259218799Snwhitehorn		}
260218799Snwhitehorn	}
261218799Snwhitehorn
262218799Snwhitehorndone:
263218799Snwhitehorn	if (selected != NULL)
264218799Snwhitehorn		*selected = cur_part;
265218799Snwhitehorn	if (nscroll != NULL)
266218799Snwhitehorn		*nscroll = cur_scroll;
267218799Snwhitehorn
268218799Snwhitehorn	dlg_del_window(partitions);
269218799Snwhitehorn	dlg_del_window(dialog);
270218799Snwhitehorn	dlg_mouse_free_regions();
271218799Snwhitehorn
272218799Snwhitehorn	return (cur_button);
273218799Snwhitehorn}
274218799Snwhitehorn
275