int label_x;
int field_x;
+ int scroll_y;
+ WINDOW *pad;
struct nc_widgetset *widgetset;
struct {
struct nc_widget_label *device_l;
return boot_editor;
}
+static void pad_refresh(struct boot_editor *boot_editor)
+{
+ int y, x, rows, cols;
+
+ getmaxyx(boot_editor->scr.sub_ncw, rows, cols);
+ getbegyx(boot_editor->scr.sub_ncw, y, x);
+
+ prefresh(boot_editor->pad, boot_editor->scroll_y, 0,
+ y, x, rows, cols);
+}
+
static struct boot_editor *boot_editor_from_arg(void *arg)
{
struct boot_editor *boot_editor = arg;
widgetset_post(boot_editor->widgetset);
nc_scr_frame_draw(scr);
- redrawwin(boot_editor->scr.main_ncw);
- wrefresh(boot_editor->scr.main_ncw);
-
+ pad_refresh(boot_editor);
return 0;
}
handled = widgetset_process_key(boot_editor->widgetset, key);
if (handled) {
- wrefresh(boot_editor->scr.main_ncw);
+ pad_refresh(boot_editor);
return;
}
{
struct boot_editor *boot_editor = boot_editor_from_arg(arg);
boot_editor->scr.sig = pb_removed_sig;
+ if (boot_editor->pad)
+ delwin(boot_editor->pad);
return 0;
}
return max(widget_height(label_w), widget_height(field_w));
}
+static int pad_height(int blockdevs_height)
+{
+ return 10 + blockdevs_height;
+}
+
static void boot_editor_layout_widgets(struct boot_editor *boot_editor)
{
struct nc_widget *wf, *wl;
y++;
widget_move(widget_button_base(boot_editor->widgets.ok_b), y, 9);
widget_move(widget_button_base(boot_editor->widgets.cancel_b), y, 19);
+
+ pad_refresh(boot_editor);
+}
+
+static void boot_editor_widget_focus(struct nc_widget *widget, void *arg)
+{
+ struct boot_editor *boot_editor = arg;
+ int w_y, s_max;
+
+ w_y = widget_y(widget) + widget_focus_y(widget);
+ s_max = getmaxy(boot_editor->scr.sub_ncw) - 1;
+
+ if (w_y < boot_editor->scroll_y)
+ boot_editor->scroll_y = w_y;
+
+ else if (w_y + boot_editor->scroll_y + 1 > s_max)
+ boot_editor->scroll_y = 1 + w_y - s_max;
+
+ else
+ return;
+
+ pad_refresh(boot_editor);
}
static void boot_editor_device_select_change(void *arg, int idx)
* resolved. In this case, we want the manual device pre-selected.
* However, we only do this if the widget hasn't been manually
* changed. */
- selected = boot_editor->item && !boot_editor->selected_device;
+ selected = !boot_editor->selected_device;
widget_select_add_option(boot_editor->widgets.device_f,
-1, "Specify paths/URLs manually", selected);
}
+static bool path_on_device(struct blockdev_info *bd_info,
+ const char *path)
+{
+ int len;
+
+ if (!bd_info->mountpoint)
+ return false;
+
+ len = strlen(bd_info->mountpoint);
+ if (strncmp(bd_info->mountpoint, path, len))
+ return false;
+
+ /* if the mountpoint doesn't have a trailing slash, ensure that
+ * the path starts with one (so we don't match a "/mnt/sda1/foo" path
+ * on a "/mnt/sda" mountpoint) */
+ return bd_info->mountpoint[len-1] == '/' || path[len] == '/';
+}
+
+
+static void boot_editor_find_device(struct boot_editor *boot_editor,
+ struct pb_boot_data *bd, const struct system_info *sysinfo,
+ char **image, char **initrd, char **dtb)
+{
+ struct blockdev_info *bd_info, *tmp;
+ unsigned int i, len;
+
+ if (!sysinfo || !sysinfo->n_blockdevs)
+ return;
+
+ /* find the device for our boot image, by finding the longest
+ * matching blockdev's mountpoint */
+ for (len = 0, i = 0, bd_info = NULL; i < sysinfo->n_blockdevs; i++) {
+ tmp = sysinfo->blockdevs[i];
+ if (!path_on_device(tmp, bd->image))
+ continue;
+ if (strlen(tmp->mountpoint) <= len)
+ continue;
+ bd_info = tmp;
+ len = strlen(tmp->mountpoint);
+ }
+
+ if (!bd_info)
+ return;
+
+ /* ensure that other paths are on this device */
+ if (bd->initrd && !path_on_device(bd_info, bd->initrd))
+ return;
+
+ if (bd->dtb && !path_on_device(bd_info, bd->dtb))
+ return;
+
+ /* ok, we match; preselect the device option, and remove the common
+ * prefix */
+ boot_editor->selected_device = bd_info->name;
+ *image += len;
+
+ if (*initrd)
+ *initrd += len;
+ if (*dtb)
+ *dtb += len;
+}
+
struct boot_editor *boot_editor_init(struct cui *cui,
struct pmenu_item *item,
const struct system_info *sysinfo,
initrd = bd->initrd;
dtb = bd->dtb;
args = bd->args;
+ boot_editor_find_device(boot_editor, bd, sysinfo,
+ &image, &initrd, &dtb);
} else {
image = initrd = dtb = args = "";
}
field_size = COLS - 1 - boot_editor->field_x;
+ boot_editor->pad = newpad(pad_height(sysinfo->n_blockdevs), COLS);
+
boot_editor->widgetset = set = widgetset_create(boot_editor,
boot_editor->scr.main_ncw,
- boot_editor->scr.sub_ncw);
+ boot_editor->pad);
+
+ widgetset_set_widget_focus(boot_editor->widgetset,
+ boot_editor_widget_focus, boot_editor);
boot_editor->widgets.device_l = widget_new_label(set, 0, 0, "device:");
boot_editor->widgets.device_f = widget_new_select(set, 0, 0,