1 // SPDX-License-Identifier: GPL-2.0+
3 * Implementation of a menu in a scene
5 * Copyright 2023 Google LLC
9 #define LOG_CATEGORY LOGC_EXPO
14 #include <video_console.h>
15 #include "scene_internal.h"
17 int scene_textline(struct scene *scn, const char *name, uint id, uint max_chars,
18 struct scene_obj_textline **tlinep)
20 struct scene_obj_textline *tline;
24 if (max_chars >= EXPO_MAX_CHARS)
25 return log_msg_ret("chr", -E2BIG);
27 ret = scene_obj_add(scn, name, id, SCENEOBJT_TEXTLINE,
28 sizeof(struct scene_obj_textline),
29 (struct scene_obj **)&tline);
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);
37 tline->pos = max_chars;
38 tline->max_chars = max_chars;
46 void scene_textline_calc_bbox(struct scene_obj_textline *tline,
47 struct vidconsole_bbox *bbox,
48 struct vidconsole_bbox *edit_bbox)
50 const struct expo_theme *theme = &tline->obj.scene->expo->theme;
53 scene_bbox_union(tline->obj.scene, tline->label_id, 0, bbox);
54 scene_bbox_union(tline->obj.scene, tline->edit_id, 0, bbox);
56 edit_bbox->valid = false;
57 scene_bbox_union(tline->obj.scene, tline->edit_id, theme->menu_inset,
61 int scene_textline_calc_dims(struct scene_obj_textline *tline)
63 struct scene *scn = tline->obj.scene;
64 struct vidconsole_bbox bbox;
65 struct scene_obj_txt *txt;
68 txt = scene_obj_find(scn, tline->edit_id, SCENEOBJT_NONE);
70 return log_msg_ret("dim", -ENOENT);
72 ret = vidconsole_nominal(scn->expo->cons, txt->font_name,
73 txt->font_size, tline->max_chars, &bbox);
75 return log_msg_ret("nom", ret);
78 tline->obj.dim.w = bbox.x1 - bbox.x0;
79 tline->obj.dim.h = bbox.y1 - bbox.y0;
81 scene_obj_set_size(scn, tline->edit_id, tline->obj.dim.w,
88 int scene_textline_arrange(struct scene *scn, struct scene_obj_textline *tline)
90 const bool open = tline->obj.flags & SCENEOF_OPEN;
97 if (tline->label_id) {
98 ret = scene_obj_set_pos(scn, tline->label_id, tline->obj.dim.x,
101 return log_msg_ret("tit", ret);
103 ret = scene_obj_set_pos(scn, tline->edit_id,
104 tline->obj.dim.x + 200, y);
106 return log_msg_ret("tit", ret);
108 ret = scene_obj_get_hw(scn, tline->label_id, NULL);
110 return log_msg_ret("hei", ret);
115 point = scn->highlight_id == tline->obj.id;
117 scene_obj_flag_clrset(scn, tline->edit_id, SCENEOF_POINT,
118 point ? SCENEOF_POINT : 0);
123 int scene_textline_send_key(struct scene *scn, struct scene_obj_textline *tline,
124 int key, struct expo_action *event)
126 const bool open = tline->obj.flags & SCENEOF_OPEN;
128 log_debug("key=%d\n", key);
132 event->type = EXPOACT_CLOSE;
133 event->select.id = tline->obj.id;
135 /* Copy the backup text from the scene buffer */
136 memcpy(abuf_data(&tline->buf), abuf_data(&scn->buf),
137 abuf_size(&scn->buf));
139 event->type = EXPOACT_QUIT;
140 log_debug("menu quit\n");
146 event->type = EXPOACT_CLOSE;
147 event->select.id = tline->obj.id;
151 struct udevice *cons = scn->expo->cons;
154 ret = vidconsole_entry_restore(cons, &scn->entry_save);
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);
160 return log_msg_ret("sav", ret);
168 int scene_textline_render_deps(struct scene *scn,
169 struct scene_obj_textline *tline)
171 const bool open = tline->obj.flags & SCENEOF_OPEN;
172 struct udevice *cons = scn->expo->cons;
173 struct scene_obj_txt *txt;
176 scene_render_deps(scn, tline->label_id);
177 scene_render_deps(scn, tline->edit_id);
179 /* show the vidconsole cursor if open */
181 /* get the position within the field */
182 txt = scene_obj_find(scn, tline->edit_id, SCENEOBJT_NONE);
184 return log_msg_ret("cur", -ENOENT);
186 if (txt->font_name || txt->font_size) {
187 ret = vidconsole_select_font(cons,
191 ret = vidconsole_select_font(cons, NULL, 0);
194 ret = vidconsole_entry_restore(cons, &scn->entry_save);
196 return log_msg_ret("sav", ret);
198 vidconsole_set_cursor_visible(cons, true, txt->obj.dim.x,
199 txt->obj.dim.y, scn->cls.num);
205 int scene_textline_open(struct scene *scn, struct scene_obj_textline *tline)
207 struct udevice *cons = scn->expo->cons;
208 struct scene_obj_txt *txt;
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));
215 /* get the position of the editable */
216 txt = scene_obj_find(scn, tline->edit_id, SCENEOBJT_NONE);
218 return log_msg_ret("cur", -ENOENT);
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);
226 return log_msg_ret("sav", ret);