readline.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00019 FILE_LICENCE ( GPL2_OR_LATER );
00020 
00021 #include <stdio.h>
00022 #include <string.h>
00023 #include <stdlib.h>
00024 #include <console.h>
00025 #include <gpxe/keys.h>
00026 #include <gpxe/editstring.h>
00027 #include <readline/readline.h>
00028 
00029 /** @file
00030  *
00031  * Minimal readline
00032  *
00033  */
00034 
00035 #define READLINE_MAX 256
00036 
00037 static void sync_console ( struct edit_string *string ) __nonnull;
00038 
00039 /**
00040  * Synchronise console with edited string
00041  *
00042  * @v string            Editable string
00043  */
00044 static void sync_console ( struct edit_string *string ) {
00045         unsigned int mod_start = string->mod_start;
00046         unsigned int mod_end = string->mod_end;
00047         unsigned int cursor = string->last_cursor;
00048         size_t len = strlen ( string->buf );
00049 
00050         /* Expand region back to old cursor position if applicable */
00051         if ( mod_start > string->last_cursor )
00052                 mod_start = string->last_cursor;
00053 
00054         /* Expand region forward to new cursor position if applicable */
00055         if ( mod_end < string->cursor )
00056                 mod_end = string->cursor;
00057 
00058         /* Backspace to start of region */
00059         while ( cursor > mod_start ) {
00060                 putchar ( '\b' );
00061                 cursor--;
00062         }
00063 
00064         /* Print modified region */
00065         while ( cursor < mod_end ) {
00066                 putchar ( ( cursor >= len ) ? ' ' : string->buf[cursor] );
00067                 cursor++;
00068         }
00069 
00070         /* Backspace to new cursor position */
00071         while ( cursor > string->cursor ) {
00072                 putchar ( '\b' );
00073                 cursor--;
00074         }
00075 }
00076 
00077 /**
00078  * Read line from console
00079  *
00080  * @v prompt            Prompt string
00081  * @ret line            Line read from console (excluding terminating newline)
00082  *
00083  * The returned line is allocated with malloc(); the caller must
00084  * eventually call free() to release the storage.
00085  */
00086 char * readline ( const char *prompt ) {
00087         char buf[READLINE_MAX];
00088         struct edit_string string;
00089         int key;
00090         char *line;
00091 
00092         if ( prompt )
00093                 printf ( "%s", prompt );
00094 
00095         memset ( &string, 0, sizeof ( string ) );
00096         string.buf = buf;
00097         string.len = sizeof ( buf );
00098         buf[0] = '\0';
00099 
00100         while ( 1 ) {
00101                 key = edit_string ( &string, getkey() );
00102                 sync_console ( &string );
00103                 switch ( key ) {
00104                 case CR:
00105                 case LF:
00106                         putchar ( '\n' );
00107                         line = strdup ( buf );
00108                         if ( ! line )
00109                                 printf ( "Out of memory\n" );
00110                         return line;
00111                 case CTRL_C:
00112                         putchar ( '\n' );
00113                         return NULL;
00114                 default:
00115                         /* Do nothing */
00116                         break;
00117                 }
00118         }
00119 }

Generated on Tue Apr 6 20:01:06 2010 for gPXE by  doxygen 1.5.7.1