1 /* 2 * Copyright (C) 2006 Michael Brown <mbrown (at) fensystems.co.uk>. 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 <stdio.h> 22 #include <string.h> 23 #include <stdlib.h> 24 #include <console.h> 25 #include <gpxe/keys.h> 26 #include <gpxe/editstring.h> 27 #include <readline/readline.h> 28 29 /** @file 30 * 31 * Minimal readline 32 * 33 */ 34 35 #define READLINE_MAX 256 36 37 static void sync_console ( struct edit_string *string ) __nonnull; 38 39 /** 40 * Synchronise console with edited string 41 * 42 * @v string Editable string 43 */ 44 static void sync_console ( struct edit_string *string ) { 45 unsigned int mod_start = string->mod_start; 46 unsigned int mod_end = string->mod_end; 47 unsigned int cursor = string->last_cursor; 48 size_t len = strlen ( string->buf ); 49 50 /* Expand region back to old cursor position if applicable */ 51 if ( mod_start > string->last_cursor ) 52 mod_start = string->last_cursor; 53 54 /* Expand region forward to new cursor position if applicable */ 55 if ( mod_end < string->cursor ) 56 mod_end = string->cursor; 57 58 /* Backspace to start of region */ 59 while ( cursor > mod_start ) { 60 putchar ( '\b' ); 61 cursor--; 62 } 63 64 /* Print modified region */ 65 while ( cursor < mod_end ) { 66 putchar ( ( cursor >= len ) ? ' ' : string->buf[cursor] ); 67 cursor++; 68 } 69 70 /* Backspace to new cursor position */ 71 while ( cursor > string->cursor ) { 72 putchar ( '\b' ); 73 cursor--; 74 } 75 } 76 77 /** 78 * Read line from console 79 * 80 * @v prompt Prompt string 81 * @ret line Line read from console (excluding terminating newline) 82 * 83 * The returned line is allocated with malloc(); the caller must 84 * eventually call free() to release the storage. 85 */ 86 char * readline ( const char *prompt ) { 87 char buf[READLINE_MAX]; 88 struct edit_string string; 89 int key; 90 char *line; 91 92 if ( prompt ) 93 printf ( "%s", prompt ); 94 95 memset ( &string, 0, sizeof ( string ) ); 96 string.buf = buf; 97 string.len = sizeof ( buf ); 98 buf[0] = '\0'; 99 100 while ( 1 ) { 101 key = edit_string ( &string, getkey() ); 102 sync_console ( &string ); 103 switch ( key ) { 104 case CR: 105 case LF: 106 putchar ( '\n' ); 107 line = strdup ( buf ); 108 if ( ! line ) 109 printf ( "Out of memory\n" ); 110 return line; 111 case CTRL_C: 112 putchar ( '\n' ); 113 return NULL; 114 default: 115 /* Do nothing */ 116 break; 117 } 118 } 119 } 120