2 * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
19 FILE_LICENCE ( GPL2_OR_LATER
);
23 #include <gpxe/keys.h>
24 #include <gpxe/editstring.h>
32 static void insert_delete ( struct edit_string
*string
, size_t delete_len
,
33 const char *insert_text
)
34 __attribute__ (( nonnull (1) ));
35 static void insert_character ( struct edit_string
*string
,
36 unsigned int character
) __nonnull
;
37 static void delete_character ( struct edit_string
*string
) __nonnull
;
38 static void backspace ( struct edit_string
*string
) __nonnull
;
39 static void kill_eol ( struct edit_string
*string
) __nonnull
;
42 * Insert and/or delete text within an editable string
44 * @v string Editable string
45 * @v delete_len Length of text to delete from current cursor position
46 * @v insert_text Text to insert at current cursor position, or NULL
48 static void insert_delete ( struct edit_string
*string
, size_t delete_len
,
49 const char *insert_text
) {
50 size_t old_len
, max_delete_len
, insert_len
, max_insert_len
, new_len
;
52 /* Calculate lengths */
53 old_len
= strlen ( string
->buf
);
54 assert ( string
->cursor
<= old_len
);
55 max_delete_len
= ( old_len
- string
->cursor
);
56 if ( delete_len
> max_delete_len
)
57 delete_len
= max_delete_len
;
58 insert_len
= ( insert_text
? strlen ( insert_text
) : 0 );
59 max_insert_len
= ( ( string
->len
- 1 ) - ( old_len
- delete_len
) );
60 if ( insert_len
> max_insert_len
)
61 insert_len
= max_insert_len
;
62 new_len
= ( old_len
- delete_len
+ insert_len
);
64 /* Fill in edit history */
65 string
->mod_start
= string
->cursor
;
66 string
->mod_end
= ( ( new_len
> old_len
) ? new_len
: old_len
);
68 /* Move data following the cursor */
69 memmove ( ( string
->buf
+ string
->cursor
+ insert_len
),
70 ( string
->buf
+ string
->cursor
+ delete_len
),
71 ( max_delete_len
+ 1 - delete_len
) );
73 /* Copy inserted text to cursor position */
74 memcpy ( ( string
->buf
+ string
->cursor
), insert_text
, insert_len
);
75 string
->cursor
+= insert_len
;
79 * Insert character at current cursor position
81 * @v string Editable string
82 * @v character Character to insert
84 static void insert_character ( struct edit_string
*string
,
85 unsigned int character
) {
86 char insert_text
[2] = { character
, '\0' };
87 insert_delete ( string
, 0, insert_text
);
91 * Delete character at current cursor position
93 * @v string Editable string
95 static void delete_character ( struct edit_string
*string
) {
96 insert_delete ( string
, 1, NULL
);
100 * Delete character to left of current cursor position
102 * @v string Editable string
104 static void backspace ( struct edit_string
*string
) {
105 if ( string
->cursor
> 0 ) {
107 delete_character ( string
);
112 * Delete to end of line
114 * @v string Editable string
116 static void kill_eol ( struct edit_string
*string
) {
117 insert_delete ( string
, ~( ( size_t ) 0 ), NULL
);
121 * Edit editable string
123 * @v string Editable string
124 * @v key Key pressed by user
125 * @ret key Key returned to application, or zero
127 * Handles keypresses and updates the content of the editable string.
128 * Basic line editing facilities (delete/insert/cursor) are supported.
129 * If edit_string() understands and uses the keypress it will return
130 * zero, otherwise it will return the original key.
132 * This function does not update the display in any way.
134 * The string's edit history will be updated to allow the caller to
135 * efficiently bring the display into sync with the string content.
137 int edit_string ( struct edit_string
*string
, int key
) {
139 size_t len
= strlen ( string
->buf
);
141 /* Prepare edit history */
142 string
->last_cursor
= string
->cursor
;
143 string
->mod_start
= string
->cursor
;
144 string
->mod_end
= string
->cursor
;
147 if ( ( key
>= 0x20 ) && ( key
<= 0x7e ) ) {
148 /* Printable character; insert at current position */
149 insert_character ( string
, key
);
150 } else switch ( key
) {
153 backspace ( string
);
157 /* Delete character */
158 delete_character ( string
);
161 /* Delete to end of line */
172 string
->cursor
= len
;
177 if ( string
->cursor
> 0 )
183 if ( string
->cursor
< len
)