/*
** Copyright (C) 2000 Erik de Castro Lopo <erikd@zip.com.au>
**  
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
** 
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
** 
** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

/* =========================================================================
** This program actually provides the functionality which was advertised for
** listing 13.6 of the book "SAMs Teach Yourself C for Linux Programming in
** 21 days", by Erik de Castro Lopo, Brad Jones and Peter Aitken.
**
** Compile this code using :
**
**     gcc -Wall list1306_readline.c -lreadline -o list1306_readline
**
** On some systems it might be necessary to also link in the termcap
** library as follows:
**
**     gcc -Wall list1306_readline.c -lreadline -ltermcap -o list1306_readline
**
** If neither of these two compile commands works, you may be missing the
** readline library or the header files for that library from your 
** installation.
** 
** More information about the problem in the original code will appear on the
** web page at http://www.zip.com.au/~erikd/BOOK/faq.html as soon as its
** ready.
**
** Dec 21 2000 : Version  1.0 <erikd@zip.com.au>
** Dec 21 2000 : Version  1.1 <erikd@zip.com.au>
**                   Added atexit (), and restore_terminal ().
*/

#include   <stdio.h>
#include   <stdlib.h>
#include   <unistd.h>
#include   <termios.h>
#include   <readline/readline.h>

#define    TERM_SILENCE_ON     1
#define    TERM_SILENCE_OFF    0

#define    TERM_STDIN          0

void silence_terminal (int on) ;
void restore_terminal (void) ;

int main (void)
{   int    age ;
    char   *name, *line ;
    
    /* During the running of this program we are fiddling with the terminal
    ** settings. If the program terminates before restoring the settings the
    ** settings will be permanent.
    ** To avoid this we register the restore_terminal function with atexit.
    ** The functions registered in this way are called when the program
    ** exits.
    */
    atexit (restore_terminal) ;
    
    line = readline ("Enter your age : ") ;
    sscanf (line, "%d", &age) ;

    /* While we're processing data (simulated by sleep (5) below) we want 
    ** to prevent the user from typing characters at the terminal.
    */
    silence_terminal (TERM_SILENCE_ON) ;
    
    printf ("Doing some processing here.\n") ;
    sleep (5) ; 

    /* We're now ready to resume dealing with the user, so turn the
    ** terminal back on.
    */    
    silence_terminal (TERM_SILENCE_OFF) ;
    name = readline ("Enter your name : ") ;

    /* Display the data. */
    printf("\nYour age is %d.\n", age);
    printf("Your name is %s.\n", name);

    return 0 ;
} /* main */

/* The atexit () function requires a parameter-less function so we
** create one here which simply calls silence_terminal ().
*/
void restore_terminal (void)
{    silence_terminal (TERM_SILENCE_OFF) ;
} /* restore_terminal */

void silence_terminal (int on)
{   /* On first entry to this function we want to store the current 
    ** terminal settings so they can be restored later. We do that
    ** by storing them in static structure. We also store a modified 
    ** copy to use as the special terminal settings for a silent
    ** terminal.
    ** The terminal settings are stored in a termios structure 
    ** defined in <termios.h>. They are declared static so they will
    ** keep their information across function calls.
    */
    static struct termios original ;
    static struct termios no_echo ;
    static int    initialized = 0 ;


    if (! initialized)
    {   tcgetattr (TERM_STDIN, &original) ;
        /* Also get a another ... */
        tcgetattr (TERM_STDIN, &no_echo) ;
        /* ... and modify it, turing of terminal charcter echoing. */
        no_echo.c_lflag &= (~ECHO) ;
        initialized = 1 ;
        } ;

    if (on)
    {   /* Turn off terminal character echoing. */
        tcsetattr (TERM_STDIN, TCSANOW, &no_echo) ;
        }
    else
    {   /* Restore original settings. */
        tcsetattr (TERM_STDIN, TCSANOW, &original) ;
        /* Flush the input buffer. */
        tcflush (TERM_STDIN, TCIFLUSH) ;
        } ;

    return ;
} /* silence_terminal */


