2004-01-20 21:32:43 +03:00
/*
* Guillaume Cottenceau ( gc @ mandrakesoft . com )
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* public license .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*
*/
/*
* Each different frontend must implement all functions defined in frontend . h
*/
# include <stdlib.h>
# include <unistd.h>
# include <string.h>
# include <stdio.h>
# include <stdarg.h>
# include <fcntl.h>
# include <sys/ioctl.h>
# include <termios.h>
# include "frontend.h"
void init_frontend ( char * welcome_msg )
{
printf ( welcome_msg ) ;
}
void finish_frontend ( void )
{
}
static void get_any_response ( void )
{
unsigned char t ;
printf ( " \n \t (press <enter> to proceed) " ) ;
fflush ( stdout ) ;
read ( 0 , & t , 1 ) ;
fcntl ( 0 , F_SETFL , O_NONBLOCK ) ;
while ( read ( 0 , & t , 1 ) > 0 ) ;
fcntl ( 0 , F_SETFL , 0 ) ;
}
2018-05-09 15:21:26 +03:00
2004-01-20 21:32:43 +03:00
static int get_int_response ( void )
{
char s [ 50 ] ;
int j = 0 , i = 0 ; /* (0) tied to Cancel */
fflush ( stdout ) ;
read ( 0 , & ( s [ i + + ] ) , 1 ) ;
fcntl ( 0 , F_SETFL , O_NONBLOCK ) ;
do {
int v = s [ i - 1 ] ;
if ( v > = ' 0 ' & & v < = ' 9 ' )
j = j * 10 + ( v - ' 0 ' ) ;
} while ( read ( 0 , & ( s [ i + + ] ) , 1 ) > 0 & & i < sizeof ( s ) ) ;
fcntl ( 0 , F_SETFL , 0 ) ;
return j ;
}
static char * get_string_response ( char * initial_string )
{
/* I won't use a scanf/%s since I also want the null string to be accepted -- also, I want the initial_string */
char s [ 500 ] ;
int i = 0 ;
char buf [ 10 ] ;
int b_index = 0 ;
char b ;
struct termios t ;
memset ( s , ' \0 ' , sizeof ( s ) ) ;
if ( initial_string ) {
printf ( initial_string ) ;
strcpy ( s , initial_string ) ;
i = strlen ( s ) ;
}
2018-05-09 15:21:26 +03:00
2004-01-20 21:32:43 +03:00
/* from ncurses/tinfo/lib_raw.c:(cbreak) */
tcgetattr ( 0 , & t ) ;
t . c_lflag & = ~ ICANON ;
t . c_lflag | = ISIG ;
t . c_lflag & = ~ ECHO ;
t . c_iflag & = ~ ICRNL ;
t . c_cc [ VMIN ] = 1 ;
t . c_cc [ VTIME ] = 0 ;
tcsetattr ( 0 , TCSADRAIN , & t ) ;
fflush ( stdout ) ;
fcntl ( 0 , F_SETFL , O_NONBLOCK ) ;
while ( 1 ) {
if ( read ( 0 , & b , 1 ) > 0 ) {
if ( b_index = = 1 ) {
if ( b = = 91 ) {
buf [ b_index ] = b ;
b_index + + ;
continue ;
}
else
b_index = 0 ;
}
if ( b_index = = 2 ) {
if ( b = = 67 ) {
if ( s [ i ] ! = ' \0 ' ) {
printf ( " \033 [C " ) ;
i + + ;
}
}
if ( b = = 68 ) {
if ( i > 0 ) {
printf ( " \033 [D " ) ;
i - - ;
}
}
b_index = 0 ;
continue ;
}
2018-05-09 15:21:26 +03:00
2004-01-20 21:32:43 +03:00
if ( b = = 13 )
break ;
if ( b = = 127 ) {
if ( i > 0 ) {
printf ( " \033 [D " ) ;
printf ( " " ) ;
printf ( " \033 [D " ) ;
if ( s [ i ] = = ' \0 ' )
s [ i - 1 ] = ' \0 ' ;
else
s [ i - 1 ] = ' ' ;
i - - ;
}
} else if ( b = = 27 ) {
buf [ b_index ] = b ;
b_index + + ;
} else {
printf ( " %c " , b ) ;
s [ i ] = b ;
i + + ;
}
}
}
t . c_lflag | = ICANON ;
t . c_lflag | = ECHO ;
2018-05-09 15:21:26 +03:00
t . c_iflag | = ICRNL ;
2004-01-20 21:32:43 +03:00
tcsetattr ( 0 , TCSADRAIN , & t ) ;
fcntl ( 0 , F_SETFL , 0 ) ;
printf ( " \n " ) ;
return strdup ( s ) ;
}
static void blocking_msg ( char * type , char * fmt , va_list ap )
{
printf ( type ) ;
vprintf ( fmt , ap ) ;
get_any_response ( ) ;
}
void verror_message ( char * msg , va_list ap )
{
blocking_msg ( " > Error! " , msg , ap ) ;
}
void vinfo_message ( char * msg , va_list ap )
{
blocking_msg ( " > Notice: " , msg , ap ) ;
}
void vwait_message ( char * msg , va_list ap )
{
printf ( " Please wait: " ) ;
vprintf ( msg , ap ) ;
fflush ( stdout ) ;
}
void remove_wait_message ( void )
{
printf ( " \n " ) ;
}
static int size_progress ;
static int actually_drawn ;
# define PROGRESS_SIZE 45
void init_progression ( char * msg , int size )
{
int i ;
size_progress = size ;
printf ( " %s " , msg ) ;
if ( size ) {
actually_drawn = 0 ;
for ( i = 0 ; i < PROGRESS_SIZE ; i + + )
printf ( " . " ) ;
printf ( " ] \033 [G%s [ " , msg ) ; /* only works on ANSI-compatibles */
fflush ( stdout ) ;
} else
printf ( " \n " ) ;
}
void update_progression ( int current_size )
{
if ( size_progress ) {
if ( current_size > size_progress )
current_size = size_progress ;
while ( ( int ) ( ( current_size * PROGRESS_SIZE ) / size_progress ) > actually_drawn ) {
printf ( " * " ) ;
actually_drawn + + ;
}
} else
printf ( " \033 [GStatus: [%8d] bytes loaded... " , current_size ) ;
2018-05-09 15:21:26 +03:00
2004-01-20 21:32:43 +03:00
fflush ( stdout ) ;
}
void end_progression ( void )
{
if ( size_progress ) {
update_progression ( size_progress ) ;
printf ( " ] \n " ) ;
} else
printf ( " done. \n " ) ;
}
enum return_type ask_from_list_comments ( char * msg , char * * elems , char * * elems_comments , char * * choice )
{
int justify_number = 1 ;
void print_choice_number ( int i ) {
char tmp [ 500 ] ;
snprintf ( tmp , sizeof ( tmp ) , " [%%%dd] " , justify_number ) ;
printf ( tmp , i ) ;
}
char * * sav_elems = elems ;
int i = 1 ;
int j = 0 ;
while ( elems & & * elems ) {
elems + + ;
i + + ;
}
if ( i > = 10 )
justify_number = 2 ;
elems = sav_elems ;
i = 1 ;
printf ( " > %s \n " , msg ) ;
print_choice_number ( 0 ) ;
printf ( " Cancel " ) ;
while ( elems & & * elems ) {
if ( elems_comments & & * elems_comments ) {
printf ( " \n " ) ;
print_choice_number ( i ) ;
printf ( " %s (%s) " , * elems , * elems_comments ) ;
j = 0 ;
} else {
if ( j = = 0 )
printf ( " \n " ) ;
print_choice_number ( i ) ;
printf ( " %-14s " , * elems ) ;
j + + ;
}
if ( j = = 4 )
j = 0 ;
2018-05-09 15:21:26 +03:00
2004-01-20 21:32:43 +03:00
if ( elems_comments )
elems_comments + + ;
i + + ;
elems + + ;
}
2018-05-09 15:21:26 +03:00
printf ( " \n ? " ) ;
2004-01-20 21:32:43 +03:00
j = get_int_response ( ) ;
if ( j = = 0 )
return RETURN_BACK ;
if ( j > = 1 & & j < = i ) {
* choice = strdup ( sav_elems [ j - 1 ] ) ;
return RETURN_OK ;
}
return RETURN_ERROR ;
}
enum return_type ask_from_list ( char * msg , char * * elems , char * * choice )
{
return ask_from_list_comments ( msg , elems , NULL , choice ) ;
}
enum return_type ask_yes_no ( char * msg )
{
int j ;
printf ( " > %s \n [0] Yes [1] No [2] Back \n ? " , msg ) ;
j = get_int_response ( ) ;
if ( j = = 0 )
return RETURN_OK ;
else if ( j = = 2 )
return RETURN_BACK ;
else return RETURN_ERROR ;
}
enum return_type ask_from_entries ( char * msg , char * * questions , char * * * answers , int entry_size , void ( * callback_func ) ( char * * strings ) )
{
int j , i = 0 ;
char * * already_answers = NULL ;
printf ( " > %s \n " , msg ) ;
while ( questions & & * questions ) {
printf ( " (%c) %s \n " , i + ' a ' , * questions ) ;
i + + ;
questions + + ;
}
if ( * answers = = NULL )
* answers = ( char * * ) malloc ( sizeof ( char * ) * i ) ;
else
already_answers = * answers ;
while ( 1 ) {
int r ;
for ( j = 0 ; j < i ; j + + ) {
printf ( " (%c) ? " , j + ' a ' ) ;
if ( already_answers & & * already_answers ) {
( * answers ) [ j ] = get_string_response ( * already_answers ) ;
already_answers + + ;
} else
( * answers ) [ j ] = get_string_response ( NULL ) ;
}
printf ( " [0] Cancel [1] Accept [2] Re-enter answers \n ? " ) ;
r = get_int_response ( ) ;
if ( r = = 0 )
return RETURN_BACK ;
if ( r = = 1 )
return RETURN_OK ;
}
}