]> Git Repo - u-boot.git/blob - boot/scene_textline.c
6ea072a1c2688bb62a3d4664fd11ad8b9c8df347
[u-boot.git] / boot / scene_textline.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Implementation of a menu in a scene
4  *
5  * Copyright 2023 Google LLC
6  * Written by Simon Glass <[email protected]>
7  */
8
9 #define LOG_CATEGORY    LOGC_EXPO
10
11 #include <common.h>
12 #include <expo.h>
13 #include <menu.h>
14 #include <video_console.h>
15 #include "scene_internal.h"
16
17 int scene_textline(struct scene *scn, const char *name, uint id, uint max_chars,
18                    struct scene_obj_textline **tlinep)
19 {
20         struct scene_obj_textline *tline;
21         char *buf;
22         int ret;
23
24         if (max_chars >= EXPO_MAX_CHARS)
25                 return log_msg_ret("chr", -E2BIG);
26
27         ret = scene_obj_add(scn, name, id, SCENEOBJT_TEXTLINE,
28                             sizeof(struct scene_obj_textline),
29                             (struct scene_obj **)&tline);
30         if (ret < 0)
31                 return log_msg_ret("obj", -ENOMEM);
32         abuf_init(&tline->buf);
33         if (!abuf_realloc(&tline->buf, max_chars + 1))
34                 return log_msg_ret("buf", -ENOMEM);
35         buf = abuf_data(&tline->buf);
36         *buf = '\0';
37         tline->pos = max_chars;
38         tline->max_chars = max_chars;
39
40         if (tlinep)
41                 *tlinep = tline;
42
43         return tline->obj.id;
44 }
45
46 void scene_textline_calc_bbox(struct scene_obj_textline *tline,
47                               struct vidconsole_bbox *bbox,
48                               struct vidconsole_bbox *edit_bbox)
49 {
50         const struct expo_theme *theme = &tline->obj.scene->expo->theme;
51
52         bbox->valid = false;
53         scene_bbox_union(tline->obj.scene, tline->label_id, 0, bbox);
54         scene_bbox_union(tline->obj.scene, tline->edit_id, 0, bbox);
55
56         edit_bbox->valid = false;
57         scene_bbox_union(tline->obj.scene, tline->edit_id, theme->menu_inset,
58                          edit_bbox);
59 }
60
61 int scene_textline_calc_dims(struct scene_obj_textline *tline)
62 {
63         struct scene *scn = tline->obj.scene;
64         struct vidconsole_bbox bbox;
65         struct scene_obj_txt *txt;
66         int ret;
67
68         txt = scene_obj_find(scn, tline->edit_id, SCENEOBJT_NONE);
69         if (!txt)
70                 return log_msg_ret("dim", -ENOENT);
71
72         ret = vidconsole_nominal(scn->expo->cons, txt->font_name,
73                                  txt->font_size, tline->max_chars, &bbox);
74         if (ret)
75                 return log_msg_ret("nom", ret);
76
77         if (bbox.valid) {
78                 tline->obj.dim.w = bbox.x1 - bbox.x0;
79                 tline->obj.dim.h = bbox.y1 - bbox.y0;
80
81                 scene_obj_set_size(scn, tline->edit_id, tline->obj.dim.w,
82                                    tline->obj.dim.h);
83         }
84
85         return 0;
86 }
87
88 int scene_textline_arrange(struct scene *scn, struct scene_obj_textline *tline)
89 {
90         const bool open = tline->obj.flags & SCENEOF_OPEN;
91         bool point;
92         int x, y;
93         int ret;
94
95         x = tline->obj.dim.x;
96         y = tline->obj.dim.y;
97         if (tline->label_id) {
98                 ret = scene_obj_set_pos(scn, tline->label_id, tline->obj.dim.x,
99                                         y);
100                 if (ret < 0)
101                         return log_msg_ret("tit", ret);
102
103                 ret = scene_obj_set_pos(scn, tline->edit_id,
104                                         tline->obj.dim.x + 200, y);
105                 if (ret < 0)
106                         return log_msg_ret("tit", ret);
107
108                 ret = scene_obj_get_hw(scn, tline->label_id, NULL);
109                 if (ret < 0)
110                         return log_msg_ret("hei", ret);
111
112                 y += ret * 2;
113         }
114
115         point = scn->highlight_id == tline->obj.id;
116         point &= !open;
117         scene_obj_flag_clrset(scn, tline->edit_id, SCENEOF_POINT,
118                               point ? SCENEOF_POINT : 0);
119
120         return 0;
121 }
122
123 int scene_textline_send_key(struct scene *scn, struct scene_obj_textline *tline,
124                             int key, struct expo_action *event)
125 {
126         const bool open = tline->obj.flags & SCENEOF_OPEN;
127
128         log_debug("key=%d\n", key);
129         switch (key) {
130         case BKEY_QUIT:
131                 if (open) {
132                         event->type = EXPOACT_CLOSE;
133                         event->select.id = tline->obj.id;
134
135                         /* Copy the backup text from the scene buffer */
136                         memcpy(abuf_data(&tline->buf), abuf_data(&scn->buf),
137                                abuf_size(&scn->buf));
138                 } else {
139                         event->type = EXPOACT_QUIT;
140                         log_debug("menu quit\n");
141                 }
142                 break;
143         case BKEY_SELECT:
144                 if (!open)
145                         break;
146                 event->type = EXPOACT_CLOSE;
147                 event->select.id = tline->obj.id;
148                 key = '\n';
149                 fallthrough;
150         default: {
151                 struct udevice *cons = scn->expo->cons;
152                 int ret;
153
154                 ret = vidconsole_entry_restore(cons, &scn->entry_save);
155                 if (ret)
156                         return log_msg_ret("sav", ret);
157                 ret = cread_line_process_ch(&scn->cls, key);
158                 ret = vidconsole_entry_save(cons, &scn->entry_save);
159                 if (ret)
160                         return log_msg_ret("sav", ret);
161                 break;
162         }
163         }
164
165         return 0;
166 }
167
168 int scene_textline_render_deps(struct scene *scn,
169                                struct scene_obj_textline *tline)
170 {
171         const bool open = tline->obj.flags & SCENEOF_OPEN;
172         struct udevice *cons = scn->expo->cons;
173         struct scene_obj_txt *txt;
174         int ret;
175
176         scene_render_deps(scn, tline->label_id);
177         scene_render_deps(scn, tline->edit_id);
178
179         /* show the vidconsole cursor if open */
180         if (open) {
181                 /* get the position within the field */
182                 txt = scene_obj_find(scn, tline->edit_id, SCENEOBJT_NONE);
183                 if (!txt)
184                         return log_msg_ret("cur", -ENOENT);
185
186                 if (txt->font_name || txt->font_size) {
187                         ret = vidconsole_select_font(cons,
188                                                      txt->font_name,
189                                                      txt->font_size);
190                 } else {
191                         ret = vidconsole_select_font(cons, NULL, 0);
192                 }
193
194                 ret = vidconsole_entry_restore(cons, &scn->entry_save);
195                 if (ret)
196                         return log_msg_ret("sav", ret);
197
198                 vidconsole_set_cursor_visible(cons, true, txt->obj.dim.x,
199                                               txt->obj.dim.y, scn->cls.num);
200         }
201
202         return 0;
203 }
204
205 int scene_textline_open(struct scene *scn, struct scene_obj_textline *tline)
206 {
207         struct udevice *cons = scn->expo->cons;
208         struct scene_obj_txt *txt;
209         int ret;
210
211         /* Copy the text into the scene buffer in case the edit is cancelled */
212         memcpy(abuf_data(&scn->buf), abuf_data(&tline->buf),
213                abuf_size(&scn->buf));
214
215         /* get the position of the editable */
216         txt = scene_obj_find(scn, tline->edit_id, SCENEOBJT_NONE);
217         if (!txt)
218                 return log_msg_ret("cur", -ENOENT);
219
220         vidconsole_set_cursor_pos(cons, txt->obj.dim.x, txt->obj.dim.y);
221         vidconsole_entry_start(cons);
222         cli_cread_init(&scn->cls, abuf_data(&tline->buf), tline->max_chars);
223         scn->cls.insert = true;
224         ret = vidconsole_entry_save(cons, &scn->entry_save);
225         if (ret)
226                 return log_msg_ret("sav", ret);
227
228         return 0;
229 }
This page took 0.027543 seconds and 2 git commands to generate.