1use alloc::string::String;
4
5#[derive(Debug, Clone, Default)]
6pub struct TextBox {
7 pub text: String,
8 pub cursor_pos: usize, pub multiline: bool, }
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum KeyOutcome {
15 Ignored,
17 CursorMoved,
19 TextChanged,
21}
22
23impl TextBox {
24 pub fn new() -> Self {
25 Self {
26 text: String::new(),
27 cursor_pos: 0,
28 multiline: false,
29 }
30 }
31
32 pub fn with_text(text: &str) -> Self {
33 let text_str = String::from(text);
34 let len = text_str.chars().count();
35 Self {
36 text: text_str,
37 cursor_pos: len,
38 multiline: false,
39 }
40 }
41
42 pub fn with_text_multiline(text: &str) -> Self {
44 let mut tb = Self::with_text(text);
45 tb.multiline = true;
46 tb
47 }
48
49 pub fn set_text(&mut self, text: &str) {
50 self.text = String::from(text);
51 self.cursor_pos = self.text.chars().count();
52 }
53
54 pub fn get_text_with_cursor(&self, show_cursor: bool) -> String {
56 if !show_cursor {
57 return self.text.clone();
58 }
59 let mut s = String::new();
60 for (i, c) in self.text.chars().enumerate() {
61 if i == self.cursor_pos {
62 s.push('|');
63 }
64 s.push(c);
65 }
66 if self.cursor_pos >= self.text.chars().count() {
67 s.push('|');
68 }
69 s
70 }
71
72 pub fn handle_key(&mut self, keycode: u8, ascii: Option<char>) -> bool {
77 self.handle_key_outcome(keycode, ascii) != KeyOutcome::Ignored
78 }
79
80 pub fn handle_key_outcome(&mut self, keycode: u8, ascii: Option<char>) -> KeyOutcome {
91 let chars_count = self.text.chars().count();
92 if self.cursor_pos > chars_count {
93 self.cursor_pos = chars_count;
94 }
95
96 match keycode {
97 0x0E => {
98 if self.cursor_pos > 0 && !self.text.is_empty() {
100 let mut new_text = String::new();
101 for (i, c) in self.text.chars().enumerate() {
102 if i != self.cursor_pos - 1 {
103 new_text.push(c);
104 }
105 }
106 self.text = new_text;
107 self.cursor_pos -= 1;
108 return KeyOutcome::TextChanged;
109 }
110 }
111 0x4B => {
112 if self.cursor_pos > 0 {
114 self.cursor_pos -= 1;
115 return KeyOutcome::CursorMoved;
116 }
117 }
118 0x4D => {
119 if self.cursor_pos < chars_count {
121 self.cursor_pos += 1;
122 return KeyOutcome::CursorMoved;
123 }
124 }
125 0x48 => {
126 let chars: alloc::vec::Vec<char> = self.text.chars().collect();
128 let mut line_ranges = alloc::vec::Vec::new();
129 let mut start = 0;
130 for (idx, &c) in chars.iter().enumerate() {
131 if c == '\n' {
132 line_ranges.push((start, idx));
133 start = idx + 1;
134 }
135 }
136 line_ranges.push((start, chars.len()));
137
138 let mut current_line_idx = 0;
139 for (idx, &(start, end)) in line_ranges.iter().enumerate() {
140 if self.cursor_pos >= start && self.cursor_pos <= end {
141 current_line_idx = idx;
142 break;
143 }
144 }
145
146 if current_line_idx > 0 {
147 let current_col = self.cursor_pos - line_ranges[current_line_idx].0;
148 let target_line_idx = current_line_idx - 1;
149 let (t_start, t_end) = line_ranges[target_line_idx];
150 let t_len = t_end - t_start;
151 self.cursor_pos = t_start + current_col.min(t_len);
152 return KeyOutcome::CursorMoved;
153 }
154 }
155 0x50 => {
156 let chars: alloc::vec::Vec<char> = self.text.chars().collect();
158 let mut line_ranges = alloc::vec::Vec::new();
159 let mut start = 0;
160 for (idx, &c) in chars.iter().enumerate() {
161 if c == '\n' {
162 line_ranges.push((start, idx));
163 start = idx + 1;
164 }
165 }
166 line_ranges.push((start, chars.len()));
167
168 let mut current_line_idx = 0;
169 for (idx, &(start, end)) in line_ranges.iter().enumerate() {
170 if self.cursor_pos >= start && self.cursor_pos <= end {
171 current_line_idx = idx;
172 break;
173 }
174 }
175
176 if current_line_idx < line_ranges.len() - 1 {
177 let current_col = self.cursor_pos - line_ranges[current_line_idx].0;
178 let target_line_idx = current_line_idx + 1;
179 let (t_start, t_end) = line_ranges[target_line_idx];
180 let t_len = t_end - t_start;
181 self.cursor_pos = t_start + current_col.min(t_len);
182 return KeyOutcome::CursorMoved;
183 }
184 }
185 0x53 => {
186 if self.cursor_pos < chars_count {
188 let mut new_text = String::new();
189 for (i, c) in self.text.chars().enumerate() {
190 if i != self.cursor_pos {
191 new_text.push(c);
192 }
193 }
194 self.text = new_text;
195 return KeyOutcome::TextChanged;
196 }
197 }
198 0x47 => {
199 let chars: alloc::vec::Vec<char> = self.text.chars().collect();
201 let mut start = self.cursor_pos;
202 while start > 0 && chars[start - 1] != '\n' {
203 start -= 1;
204 }
205 if start != self.cursor_pos {
206 self.cursor_pos = start;
207 return KeyOutcome::CursorMoved;
208 }
209 }
210 0x4F => {
211 let chars: alloc::vec::Vec<char> = self.text.chars().collect();
213 let mut end = self.cursor_pos;
214 while end < chars.len() && chars[end] != '\n' {
215 end += 1;
216 }
217 if end != self.cursor_pos {
218 self.cursor_pos = end;
219 return KeyOutcome::CursorMoved;
220 }
221 }
222 0x49 => {
223 if self.cursor_pos != 0 {
225 self.cursor_pos = 0;
226 return KeyOutcome::CursorMoved;
227 }
228 }
229 0x51 => {
230 if self.cursor_pos != chars_count {
232 self.cursor_pos = chars_count;
233 return KeyOutcome::CursorMoved;
234 }
235 }
236 crate::kernel::keyboard::KC_KILL_LINE => {
237 let chars: alloc::vec::Vec<char> = self.text.chars().collect();
239 let mut end = self.cursor_pos;
240 while end < chars.len() && chars[end] != '\n' {
241 end += 1;
242 }
243 if end > self.cursor_pos {
244 let mut new_text = String::new();
245 for (i, c) in chars.iter().enumerate() {
246 if i < self.cursor_pos || i >= end {
247 new_text.push(*c);
248 }
249 }
250 self.text = new_text;
251 return KeyOutcome::TextChanged;
252 }
253 }
254 0x0F if self.multiline => {
255 let chars: alloc::vec::Vec<char> = self.text.chars().collect();
258 let mut col = 0usize;
259 let mut i = self.cursor_pos;
260 while i > 0 && chars[i - 1] != '\n' {
261 i -= 1;
262 col += 1;
263 }
264 let spaces = 4 - (col % 4);
265 let mut new_text = String::new();
266 for (idx, ch) in chars.iter().enumerate() {
267 if idx == self.cursor_pos {
268 for _ in 0..spaces {
269 new_text.push(' ');
270 }
271 }
272 new_text.push(*ch);
273 }
274 if self.cursor_pos >= chars.len() {
275 for _ in 0..spaces {
276 new_text.push(' ');
277 }
278 }
279 self.text = new_text;
280 self.cursor_pos += spaces;
281 return KeyOutcome::TextChanged;
282 }
283 _ => {
284 if let Some(c) = ascii {
285 if c == '\r' || c == '\n' {
286 let mut new_text = String::new();
287 let mut inserted = false;
288 for (i, ch) in self.text.chars().enumerate() {
289 if i == self.cursor_pos {
290 new_text.push('\n');
291 inserted = true;
292 }
293 new_text.push(ch);
294 }
295 if !inserted {
296 new_text.push('\n');
297 }
298 self.text = new_text;
299 self.cursor_pos += 1;
300 return KeyOutcome::TextChanged;
301 } else {
302 let mut new_text = String::new();
303 let mut inserted = false;
304 for (i, ch) in self.text.chars().enumerate() {
305 if i == self.cursor_pos {
306 new_text.push(c);
307 inserted = true;
308 }
309 new_text.push(ch);
310 }
311 if !inserted {
312 new_text.push(c);
313 }
314 self.text = new_text;
315 self.cursor_pos += 1;
316 return KeyOutcome::TextChanged;
317 }
318 }
319 }
320 }
321 KeyOutcome::Ignored
322 }
323}