|
|
1.1 ! root 1: /* ! 2: * Copyright (C) 2006 Michael Brown <[email protected]>. ! 3: * ! 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. ! 8: * ! 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. ! 13: * ! 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. ! 17: */ ! 18: ! 19: FILE_LICENCE ( GPL2_OR_LATER ); ! 20: ! 21: #include <assert.h> ! 22: #include <string.h> ! 23: #include <ipxe/keys.h> ! 24: #include <ipxe/editstring.h> ! 25: ! 26: /** @file ! 27: * ! 28: * Editable strings ! 29: * ! 30: */ ! 31: ! 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; ! 40: ! 41: /** ! 42: * Insert and/or delete text within an editable string ! 43: * ! 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 ! 47: */ ! 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; ! 51: ! 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 ); ! 63: ! 64: /* Fill in edit history */ ! 65: string->mod_start = string->cursor; ! 66: string->mod_end = ( ( new_len > old_len ) ? new_len : old_len ); ! 67: ! 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 ) ); ! 72: ! 73: /* Copy inserted text to cursor position */ ! 74: memcpy ( ( string->buf + string->cursor ), insert_text, insert_len ); ! 75: string->cursor += insert_len; ! 76: } ! 77: ! 78: /** ! 79: * Insert character at current cursor position ! 80: * ! 81: * @v string Editable string ! 82: * @v character Character to insert ! 83: */ ! 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 ); ! 88: } ! 89: ! 90: /** ! 91: * Delete character at current cursor position ! 92: * ! 93: * @v string Editable string ! 94: */ ! 95: static void delete_character ( struct edit_string *string ) { ! 96: insert_delete ( string, 1, NULL ); ! 97: } ! 98: ! 99: /** ! 100: * Delete character to left of current cursor position ! 101: * ! 102: * @v string Editable string ! 103: */ ! 104: static void backspace ( struct edit_string *string ) { ! 105: if ( string->cursor > 0 ) { ! 106: string->cursor--; ! 107: delete_character ( string ); ! 108: } ! 109: } ! 110: ! 111: /** ! 112: * Delete to end of line ! 113: * ! 114: * @v string Editable string ! 115: */ ! 116: static void kill_eol ( struct edit_string *string ) { ! 117: insert_delete ( string, ~( ( size_t ) 0 ), NULL ); ! 118: } ! 119: ! 120: /** ! 121: * Replace editable string ! 122: * ! 123: * @v string Editable string ! 124: * @v replacement Replacement string ! 125: */ ! 126: void replace_string ( struct edit_string *string, const char *replacement ) { ! 127: string->cursor = 0; ! 128: insert_delete ( string, ~( ( size_t ) 0 ), replacement ); ! 129: } ! 130: ! 131: /** ! 132: * Edit editable string ! 133: * ! 134: * @v string Editable string ! 135: * @v key Key pressed by user ! 136: * @ret key Key returned to application, or zero ! 137: * ! 138: * Handles keypresses and updates the content of the editable string. ! 139: * Basic line editing facilities (delete/insert/cursor) are supported. ! 140: * If edit_string() understands and uses the keypress it will return ! 141: * zero, otherwise it will return the original key. ! 142: * ! 143: * This function does not update the display in any way. ! 144: * ! 145: * The string's edit history will be updated to allow the caller to ! 146: * efficiently bring the display into sync with the string content. ! 147: */ ! 148: int edit_string ( struct edit_string *string, int key ) { ! 149: int retval = 0; ! 150: size_t len = strlen ( string->buf ); ! 151: ! 152: /* Prepare edit history */ ! 153: string->last_cursor = string->cursor; ! 154: string->mod_start = string->cursor; ! 155: string->mod_end = string->cursor; ! 156: ! 157: /* Interpret key */ ! 158: if ( ( key >= 0x20 ) && ( key <= 0x7e ) ) { ! 159: /* Printable character; insert at current position */ ! 160: insert_character ( string, key ); ! 161: } else switch ( key ) { ! 162: case KEY_BACKSPACE: ! 163: /* Backspace */ ! 164: backspace ( string ); ! 165: break; ! 166: case KEY_DC: ! 167: case CTRL_D: ! 168: /* Delete character */ ! 169: delete_character ( string ); ! 170: break; ! 171: case CTRL_K: ! 172: /* Delete to end of line */ ! 173: kill_eol ( string ); ! 174: break; ! 175: case KEY_HOME: ! 176: case CTRL_A: ! 177: /* Start of line */ ! 178: string->cursor = 0; ! 179: break; ! 180: case KEY_END: ! 181: case CTRL_E: ! 182: /* End of line */ ! 183: string->cursor = len; ! 184: break; ! 185: case KEY_LEFT: ! 186: case CTRL_B: ! 187: /* Cursor left */ ! 188: if ( string->cursor > 0 ) ! 189: string->cursor--; ! 190: break; ! 191: case KEY_RIGHT: ! 192: case CTRL_F: ! 193: /* Cursor right */ ! 194: if ( string->cursor < len ) ! 195: string->cursor++; ! 196: break; ! 197: default: ! 198: retval = key; ! 199: break; ! 200: } ! 201: ! 202: return retval; ! 203: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.