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.
21 #include <gpxe/keys.h>
22 #include <gpxe/editstring.h>
30 static void insert_delete ( struct edit_string
*string
, size_t delete_len
,
31 const char *insert_text
)
32 __attribute__ (( nonnull (1) ));
33 static void insert_character ( struct edit_string
*string
,
34 unsigned int character
) __nonnull
;
35 static void delete_character ( struct edit_string
*string
) __nonnull
;
36 static void backspace ( struct edit_string
*string
) __nonnull
;
37 static void kill_eol ( struct edit_string
*string
) __nonnull
;
40 * Insert and/or delete text within an editable string
42 * @v string Editable string
43 * @v delete_len Length of text to delete from current cursor position
44 * @v insert_text Text to insert at current cursor position, or NULL
46 static void insert_delete ( struct edit_string
*string
, size_t delete_len
,
47 const char *insert_text
) {
48 size_t old_len
, max_delete_len
, insert_len
, max_insert_len
, new_len
;
50 /* Calculate lengths */
51 old_len
= strlen ( string
->buf
);
52 assert ( string
->cursor
<= old_len
);
53 max_delete_len
= ( old_len
- string
->cursor
);
54 if ( delete_len
> max_delete_len
)
55 delete_len
= max_delete_len
;
56 insert_len
= ( insert_text
? strlen ( insert_text
) : 0 );
57 max_insert_len
= ( ( string
->len
- 1 ) - ( old_len
- delete_len
) );
58 if ( insert_len
> max_insert_len
)
59 insert_len
= max_insert_len
;
60 new_len
= ( old_len
- delete_len
+ insert_len
);
62 /* Fill in edit history */
63 string
->mod_start
= string
->cursor
;
64 string
->mod_end
= ( ( new_len
> old_len
) ? new_len
: old_len
);
66 /* Move data following the cursor */
67 memmove ( ( string
->buf
+ string
->cursor
+ insert_len
),
68 ( string
->buf
+ string
->cursor
+ delete_len
),
69 ( max_delete_len
+ 1 - delete_len
) );
71 /* Copy inserted text to cursor position */
72 memcpy ( ( string
->buf
+ string
->cursor
), insert_text
, insert_len
);
73 string
->cursor
+= insert_len
;
77 * Insert character at current cursor position
79 * @v string Editable string
80 * @v character Character to insert
82 static void insert_character ( struct edit_string
*string
,
83 unsigned int character
) {
84 char insert_text
[2] = { character
, '\0' };
85 insert_delete ( string
, 0, insert_text
);
89 * Delete character at current cursor position
91 * @v string Editable string
93 static void delete_character ( struct edit_string
*string
) {
94 insert_delete ( string
, 1, NULL
);
98 * Delete character to left of current cursor position
100 * @v string Editable string
102 static void backspace ( struct edit_string
*string
) {
103 if ( string
->cursor
> 0 ) {
105 delete_character ( string
);
110 * Delete to end of line
112 * @v string Editable string
114 static void kill_eol ( struct edit_string
*string
) {
115 insert_delete ( string
, ~( ( size_t ) 0 ), NULL
);
119 * Edit editable string
121 * @v string Editable string
122 * @v key Key pressed by user
123 * @ret key Key returned to application, or zero
125 * Handles keypresses and updates the content of the editable string.
126 * Basic line editing facilities (delete/insert/cursor) are supported.
127 * If edit_string() understands and uses the keypress it will return
128 * zero, otherwise it will return the original key.
130 * This function does not update the display in any way.
132 * The string's edit history will be updated to allow the caller to
133 * efficiently bring the display into sync with the string content.
135 int edit_string ( struct edit_string
*string
, int key
) {
137 size_t len
= strlen ( string
->buf
);
139 /* Prepare edit history */
140 string
->last_cursor
= string
->cursor
;
141 string
->mod_start
= string
->cursor
;
142 string
->mod_end
= string
->cursor
;
145 if ( ( key
>= 0x20 ) && ( key
<= 0x7e ) ) {
146 /* Printable character; insert at current position */
147 insert_character ( string
, key
);
148 } else switch ( key
) {
151 backspace ( string
);
155 /* Delete character */
156 delete_character ( string
);
159 /* Delete to end of line */
170 string
->cursor
= len
;
175 if ( string
->cursor
> 0 )
181 if ( string
->cursor
< len
)