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