Mario, tuyndie, oink and ingraham:
Thank you all VERY much for the time you have all taken to give me some direction on this. I’ve tried the Mario, tuyndie, and ingraham approaches without success. The source code follows in case anyone wants to compile it and run it to see what I’m seeing. It appears that ECHO never turns off and neither does line buffering.
When I use read(fileno(stdin), charbuff, 1); after calling Mario’s raw(fileno(stdin)) function the program never even displays the starting banner until after the Enter key is hit which is pretty much the opposite of what I would expect to happen so I commented it out for now.
At any rate I’m sure it’s probably something simple I’m doing wrong (or MORE than one simple thing) due to my lack of experience with C++ and/or Neutrino and I would appreciate any direction anyone can offer. Regarding sticking with ASM, I wish I could because C++ makes me feel like an amateur despite 20 years of software engineering experience but trying to call Operating System functions and a bunch of libraries of C/C++ functions from ASM is probably at least as challenging as learning the C++ language itself so I’m determined to persevere despite the challenges and a critical looming deadline on my current project…
Oink, you’re apparently a very prolific coder! I’m going to dive into the POSIX link and the source code you sent me and give it a try as well but it’s a rather intimidating and massive chunk of code so I’ve saved it for last…
Warmest Regards,
Kevin Jackson
The source code follows…
#include
#include
#include <termios.h> //~~~~ Required by termios structure, tcgetattr and tcsetattr
#include <fcntl.h> //~~~~ Required by open() and close()
using namespace std;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
struct termios termios_Backup; //~~~~ termios_Backup is used to restore things to their original state upon program termination.
static int raw( int ); //~~~~ Function prototype
char get_one_char(); //~~~~ Function prototype
int buffered_input( int ); //~~~~ Function prototype
int unbuffered_input( int ); //~~~~ Function prototype
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int main(int argc, char *argv[])
{
cout << “\n";
cout << “Test of single keystroke retrieval.\n”;
cout << "\n\n”;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cout << " STDIN_FILENO is: " << STDIN_FILENO << "\n"; //~~~ Making sure I understand what STDIN_FILENO is.
cout << "fileno(stdin) is: " << fileno(stdin) << "\n\n"; //~~~ Making sure I understand what fileno() does.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~ Test OpenQNX QNX Master Mario’s raw() function ~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
raw(fileno(stdin)); // Execute Mario's raw() function
cout << "\n";
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
char charbuff[2]={ 0, 0 }; //~~~~ A little char array to hold the results of a one byte read()
char keycode = '?'; //~~~~ Set char variable to '?' to see if fgetchar() function returns anything else...
/*
read(fileno(stdin), charbuff, 1);
cout << "read(fileno(stdin),1) results: " << charbuff[0] << “\n”;
*/
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cout << "hit a single character key to test fgetchar() after raw()...\n";
keycode = fgetchar();
cout << "fgetchar() AFTER buffered_input function results: " << keycode << "\n\n";
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
keycode = '?'; //~~~~ Set char variable to '?' to see if cin.get function returns anything else...
cout << "hit a single character key to test cin.get() after raw()...\n";
cin.get(keycode);
cout << "cin.get() AFTER buffered_input function results: " << keycode << "\n\n";
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~ Test OpenQNX ingraham’s get_one_char() function ~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
keycode = '?'; //~~~~ Set char variable to '?' to see if get_one_char() returns anything else...
cout << "hit a single character key to test get_one_char()...\n";
// sleep( 2 ); //~~~~ Wait a few seconds after prompt so user has time to hit a key…
keycode = get_one_char(); // Execute ingraham's get_one_char() function
cout << "get_one_char() results: " << keycode << "\n\n";
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~ Test OpenQNX tuyndie’s buffered_input() function ~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
buffered_input( STDIN_FILENO ); // Execute tuyndie's buffered_input() function
keycode = '?'; //~~~~ Set char variable to '?' to see if fgetchar() function returns anything else...
cout << "hit a single character key to test fgetchar() after buffered_input()...\n";
keycode = fgetchar();
cout << "fgetchar() AFTER buffered_input function results: " << keycode << "\n\n";
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
keycode = '?'; //~~~~ Set char variable to '?' to see if cin.get function returns anything else...
cout << "hit a single character key to test cin.get() after buffered_input()...\n";
cin.get(keycode);
cout << "cin.get() AFTER buffered_input function results: " << keycode << "\n\n";
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~ Test OpenQNX tuyndie’s unbuffered_input() function ~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
unbuffered_input( STDIN_FILENO ); // Execute tuyndie's unbuffered_input() function
keycode = '?'; //~~~~ Set char variable to '?' to see if fgetchar() function returns anything else...
cout << "hit a single character key to test fgetchar() after unbuffered_input()...\n";
keycode = fgetchar();
cout << "fgetchar() AFTER unbuffered_input function results: " << keycode << "\n\n";
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
keycode = '?'; //~~~~ Set char variable to '?' to see if cin.get function returns anything else...
cout << "hit a single character key to test cin.get() after unbuffered_input()...\n";
cin.get(keycode);
cout << "cin.get() AFTER unbuffered_input function results: " << keycode << "\n\n";
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~ Restore termios to original state and exit.~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int tcsetattr_return = tcsetattr( fileno(stdin), TCSADRAIN, &termios_Backup ); //~~~~ Restore original state of termios
if (tcsetattr_return)
cout << "Error on tcsetattr (termios restore): " << tcsetattr_return << "\n";
else
cout << "tcsetattr (termios restore) successful: " << tcsetattr_return << "\n";
cout << "\n*** End of Get_A_Keystroke test ***\n";
return EXIT_SUCCESS;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~ Mario’s raw() function ~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static int raw( int fd )
{
struct termios termios_New;
int tcgetattr_return = tcgetattr( fd, &termios_Backup );
if (tcgetattr_return)
{
cout << "Error on tcgetattr: " << tcgetattr_return << "\n";
return tcgetattr_return;
}
else
cout << "tcgetattr successful: " << tcgetattr_return << "\n";
termios_New = termios_Backup; //~~~~ Copy structure that was filled by tcgetattr
termios_New.c_lflag &= ~( ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL ); //~~~~ Clear bits
int tcsetattr_return = tcsetattr( fd, TCSADRAIN, &termios_New );
if (tcsetattr_return)
{
cout << "Error on tcsetattr: " << tcsetattr_return << "\n";
return tcsetattr_return;
}
else
{
cout << "tcsetattr successful: " << tcsetattr_return << "\n";
return tcsetattr_return;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~ ingraham’s variation on Mario’s code: replacement for getchar() that returns as soon as a key is pressed. ~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
char get_one_char()
{
struct termios termios_Temp;
char ch=0;
if ( tcgetattr ( STDIN_FILENO, &termios_Temp ) )
{
return(0);
}
termios_Temp.c_cc[VMIN] = 1;
termios_Temp.c_cc[VTIME] = 0;
termios_Temp.c_lflag &= ~( ICANON | ECHO | ECHOE | ECHOK | ECHONL );
termios_Temp.c_oflag &= ~OPOST;
tcsetattr ( STDIN_FILENO, TCSADRAIN, &termios_Temp );
tcflush ( STDIN_FILENO, TCIFLUSH );
ch = getchar();
termios_Temp.c_lflag |= ( ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL );
termios_Temp.c_oflag |= OPOST;
tcsetattr ( STDIN_FILENO, TCSADRAIN, &termios_Temp );
return ch;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~ tuyndie’s buffered_input() function. ~~~~
// Set terminal to standard buffered input.
// Input Keys are displayed on screen and terminal waits for ENTER key.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int buffered_input( int fd)
{
struct termios termios_Temp;
if( tcgetattr( fd, &termios_Temp ) != 0)
{
// printf("ERROR: Unable to get terminal settings (%s)\n", strerror(errno));
cout << "ERROR: Unable to get terminal settings\n";
return( -1 );
}
termios_Temp.c_cc[VMIN] = 1;
termios_Temp.c_cc[VTIME] = 0;
termios_Temp.c_lflag |= ICANON;
termios_Temp.c_lflag |= ECHO;
return( tcsetattr( fd, TCSADRAIN, &termios_Temp ) );
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~ tuyndie’s unbuffered_input() function. ~~~~
// Set terminal to unbuffered input.
// Input Keys are not shown and immediately returned to kernel without ENTER key.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int unbuffered_input( int fd )
{
struct termios termios_Temp;
if( tcgetattr( fd, &termios_Temp ) != 0 )
{
// printf("ERROR: Unable to get terminal settings (%s)\n", strerror(errno));
cout << "ERROR: Unable to get terminal settings\n";
return( -1 );
}
termios_Temp.c_cc[VMIN] = 1;
termios_Temp.c_cc[VTIME] = 0;
termios_Temp.c_lflag &= ~ICANON;
termios_Temp.c_lflag &= ~ECHO;
return( tcsetattr( fd, TCSADRAIN, &termios_Temp ) );
}