Home | History | Annotate | Download | only in hci
      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