02187e0adac685208083a48ba3b5a6f531611788
[petitboot] / ui / ncurses / nc-boot-editor.c
1 /*
2  *  Copyright (C) 2009 Sony Computer Entertainment Inc.
3  *  Copyright 2009 Sony Corp.
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; version 2 of the License.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #include "config.h"
20
21 #define _GNU_SOURCE
22
23 #include <assert.h>
24 #include <string.h>
25
26 #include "log/log.h"
27 #include "talloc/talloc.h"
28 #include "nc-boot-editor.h"
29 #include "nc-widgets.h"
30
31 struct boot_editor {
32         struct nc_scr           scr;
33         struct cui              *cui;
34         void                    *data;
35         struct pmenu_item       *item;
36         void                    (*on_exit)(struct cui *cui,
37                                         struct pmenu_item *item,
38                                         struct pb_boot_data *bd);
39
40         struct nc_widgetset     *widgetset;
41         struct {
42                 struct nc_widget_label          *image_l;
43                 struct nc_widget_textbox        *image_f;
44                 struct nc_widget_label          *initrd_l;
45                 struct nc_widget_textbox        *initrd_f;
46                 struct nc_widget_label          *dtb_l;
47                 struct nc_widget_textbox        *dtb_f;
48                 struct nc_widget_label          *args_l;
49                 struct nc_widget_textbox        *args_f;
50                 struct nc_widget_button         *ok_b;
51                 struct nc_widget_button         *cancel_b;
52         } widgets;
53 };
54
55 static struct boot_editor *boot_editor_from_scr(struct nc_scr *scr)
56 {
57         struct boot_editor *boot_editor;
58
59         assert(scr->sig == pb_boot_editor_sig);
60         boot_editor = (struct boot_editor *)
61                 ((char *)scr - (size_t)&((struct boot_editor *)0)->scr);
62         assert(boot_editor->scr.sig == pb_boot_editor_sig);
63         return boot_editor;
64 }
65
66 static struct boot_editor *boot_editor_from_arg(void *arg)
67 {
68         struct boot_editor *boot_editor = arg;
69
70         assert(boot_editor->scr.sig == pb_boot_editor_sig);
71         return boot_editor;
72 }
73
74 static int boot_editor_post(struct nc_scr *scr)
75 {
76         struct boot_editor *boot_editor = boot_editor_from_scr(scr);
77
78         widgetset_post(boot_editor->widgetset);
79         nc_scr_frame_draw(scr);
80         redrawwin(boot_editor->scr.main_ncw);
81         wrefresh(boot_editor->scr.main_ncw);
82
83         return 0;
84 }
85
86 static int boot_editor_unpost(struct nc_scr *scr)
87 {
88         widgetset_unpost(boot_editor_from_scr(scr)->widgetset);
89         return 0;
90 }
91
92 struct nc_scr *boot_editor_scr(struct boot_editor *boot_editor)
93 {
94         return &boot_editor->scr;
95 }
96
97 static void boot_editor_resize(struct nc_scr *scr)
98 {
99         /* FIXME: forms can't be resized, need to recreate here */
100         boot_editor_unpost(scr);
101         boot_editor_post(scr);
102 }
103
104 static struct pb_boot_data *boot_editor_prepare_data(
105                 struct boot_editor *boot_editor)
106 {
107         struct pb_boot_data *bd;
108         char *s;
109
110         bd = talloc(boot_editor, struct pb_boot_data);
111
112         if (!bd)
113                 return NULL;
114
115         s = widget_textbox_get_value(boot_editor->widgets.image_f);
116         bd->image = *s ? talloc_strdup(bd, s) : NULL;
117
118         s = widget_textbox_get_value(boot_editor->widgets.initrd_f);
119         bd->initrd = *s ? talloc_strdup(bd, s) : NULL;
120
121         s = widget_textbox_get_value(boot_editor->widgets.dtb_f);
122         bd->dtb = *s ? talloc_strdup(bd, s) : NULL;
123
124         s = widget_textbox_get_value(boot_editor->widgets.args_f);
125         bd->args = *s ? talloc_strdup(bd, s) : NULL;
126
127         return bd;
128 }
129
130 /**
131  * boot_editor_process_key - Process a user keystroke.
132  *
133  * Called from the cui via the scr:process_key method.
134  */
135
136 static void boot_editor_process_key(struct nc_scr *scr, int key)
137 {
138         struct boot_editor *boot_editor = boot_editor_from_scr(scr);
139         bool handled;
140
141         handled = widgetset_process_key(boot_editor->widgetset, key);
142         if (handled) {
143                 wrefresh(boot_editor->scr.main_ncw);
144                 return;
145         }
146
147         switch (key) {
148         case 'x':
149         case 27: /* ESC */
150                 boot_editor->on_exit(boot_editor->cui, NULL, NULL);
151                 nc_flush_keys();
152         }
153 }
154
155 /**
156  * boot_editor_destructor - The talloc destructor for a boot_editor.
157  */
158
159 static int boot_editor_destructor(void *arg)
160 {
161         struct boot_editor *boot_editor = boot_editor_from_arg(arg);
162         boot_editor->scr.sig = pb_removed_sig;
163         return 0;
164 }
165
166 static void ok_click(void *arg)
167 {
168         struct boot_editor *boot_editor = arg;
169         struct pb_boot_data *bd;
170
171         bd = boot_editor_prepare_data(boot_editor);
172         boot_editor->on_exit(boot_editor->cui, boot_editor->item, bd);
173 }
174
175 static void cancel_click(void *arg)
176 {
177         struct boot_editor *boot_editor = arg;
178         boot_editor->on_exit(boot_editor->cui, NULL, NULL);
179 }
180
181 struct boot_editor *boot_editor_init(struct cui *cui,
182                 struct pmenu_item *item,
183                 const struct system_info *sysinfo,
184                 void (*on_exit)(struct cui *cui,
185                                 struct pmenu_item *item,
186                                 struct pb_boot_data *bd))
187 {
188         int y, field_size, label_x = 1, field_x = 9;
189         char *image, *initrd, *dtb, *args;
190         struct boot_editor *boot_editor;
191         struct nc_widgetset *set;
192
193         (void)sysinfo;
194
195         boot_editor = talloc_zero(cui, struct boot_editor);
196
197         if (!boot_editor)
198                 return NULL;
199
200         talloc_set_destructor(boot_editor, boot_editor_destructor);
201         boot_editor->cui = cui;
202         boot_editor->item = item;
203         boot_editor->on_exit = on_exit;
204
205         nc_scr_init(&boot_editor->scr, pb_boot_editor_sig, 0,
206                         cui, boot_editor_process_key,
207                 boot_editor_post, boot_editor_unpost, boot_editor_resize);
208
209         boot_editor->scr.frame.ltitle = talloc_strdup(boot_editor,
210                         "Petitboot Option Editor");
211         boot_editor->scr.frame.rtitle = NULL;
212         boot_editor->scr.frame.help = talloc_strdup(boot_editor,
213                         "Enter=accept");
214
215         if (item) {
216                 struct pb_boot_data *bd = cod_from_item(item)->bd;
217                 image = bd->image;
218                 initrd = bd->initrd;
219                 dtb = bd->dtb;
220                 args = bd->args;
221         } else {
222                 image = initrd = dtb = args = "";
223         }
224
225         y = 0;
226         field_size = COLS - 1 - field_x;
227
228         boot_editor->widgetset = set = widgetset_create(boot_editor,
229                         boot_editor->scr.main_ncw,
230                         boot_editor->scr.sub_ncw);
231
232         boot_editor->widgets.image_l = widget_new_label(set, y,
233                                         label_x, "image:");
234         boot_editor->widgets.image_f = widget_new_textbox(set, y,
235                                         field_x, field_size, image);
236
237         y++;
238         boot_editor->widgets.initrd_l = widget_new_label(set, y,
239                                         label_x, "initrd:");
240         boot_editor->widgets.initrd_f = widget_new_textbox(set, y,
241                                         field_x, field_size, initrd);
242
243         y++;
244         boot_editor->widgets.dtb_l = widget_new_label(set, y,
245                                         label_x, "dtb:");
246         boot_editor->widgets.dtb_f = widget_new_textbox(set, y,
247                                         field_x, field_size, dtb);
248
249         y++;
250         boot_editor->widgets.args_l = widget_new_label(set, y,
251                                         label_x, "args:");
252         boot_editor->widgets.args_f = widget_new_textbox(set, y,
253                                         field_x, field_size, args);
254
255         y++;
256         y++;
257         boot_editor->widgets.ok_b = widget_new_button(set, y,
258                                         9, 6, "OK", ok_click, boot_editor);
259         boot_editor->widgets.cancel_b = widget_new_button(set, y,
260                                         19, 6, "Cancel", cancel_click,
261                                         boot_editor);
262
263         return boot_editor;
264 }