GIDForums  

Go Back   GIDForums > Computer Programming Forums > C++ Forum
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 31-Jan-2005, 00:13
kikazaru kikazaru is offline
New Member
 
Join Date: Jan 2005
Posts: 2
kikazaru is on a distinguished road

Getting arrow key's from a terminal immediately


I was wondering whether it's possible to read keys input to a terminal immediately without having to engage curses, in a PC linux g++ coding environment. OR, set up curses so that it still allows printf and cout to display lines on the terminal.

I want to write a simple shell with a command history that can be scrolled using the arrow keys, but since I have a lot of legacy code using cout and printf to show various messages I'd rather not use the curses library because it supresses these output channels.

I tried using getchar but that only returns when the user enters the whole line and I want to replace what the user input with the contents of the command history if they press an arrow key before they press return.

Any suggestions?
  #2  
Old 31-Jan-2005, 01:38
aaroncohn's Avatar
aaroncohn aaroncohn is offline
Regular Member
 
Join Date: Feb 2004
Location: Bay Area, CA.
Posts: 564
aaroncohn is a jewel in the roughaaroncohn is a jewel in the roughaaroncohn is a jewel in the rough
I believe you must use the function kbhit() for detecting arrow keys. It is located in the conio.h library.

CPP / C++ / C Code:
int kbhit(void);
kbhit returns 0 if no keypress is detected, and nonzero if a keypress is detected. kbhit() will not pause the program. Once you find out if a keypress is detected, you can get the user's input out of the keyboard buffer with getchar().

Bear in mind that conio.h is not a standard library and doesn't come with all compilers, however, Borland compilers usually do. I think MSVC 6.0 includes conio.h as well, but I am not certain.
__________________
-Aaron
  #3  
Old 31-Jan-2005, 08:30
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,791
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold
Quote:
Originally Posted by kikazaru
I was wondering whether it's possible to read keys input to a terminal immediately without having to engage curses, in a PC linux g++ coding environment.
Any suggestions?


You might check this out: http://www.gidforums.com/t-3386.html

Regards,

Dave
  #4  
Old 31-Jan-2005, 20:45
kikazaru kikazaru is offline
New Member
 
Join Date: Jan 2005
Posts: 2
kikazaru is on a distinguished road
Thanks for your suggestions Dave and Aaron.

Unfortunately, I don't have conio.h, and the linux_getch code you posted blocks waiting for input. I need to read a character without blocking so I can suspend the thread the input handler is running in unless there is some keyboard input.

I NEARLY managed to solve the problem! I've posted some code below that does non-blocking keyboard input and I tested for the key sequence substituted for the arrow keys, e.g., ^[[A as a string... probably not ideal but it seems to work.

HOWEVER, there is one problem remaining, in that when I print a char 0x0D to go back to the start of the line, and replace the current input line with some new text (which is supposed to be taken from the command history but for now is just "UP" or "DOWN") the output doesn't appear until the getchar command is executed, and actually happens AFTER the echo to the terminal of the key pressed by the user... this doesn't happen if I don't use "select" to wait until input exists in stdin because in that case getchar gets called before the user gets a chance to input another character and the display is updated properly first.

So the question now is: how can you flush the output buffer to the terminal immediately? cout.flush, fflush(stdout) etc. do not seem to have any effect!


--------- Code example... sorry, I couldn't see how to put it in a tidy sub-window

CPP / C++ / C Code:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>


using namespace std;

void get_command(char *command, int length);

int main() {
  char command[10];

  get_command(command, 10);
  
  cout << "The command input was: " << command << endl << endl;
  system("stty cooked");
  
  return 0;
}




void get_command(char* command, int max_length) {
  int i, j;
  int c;

  static bool input_initialized = false;
  static fd_set rfds;
  static struct timeval tv;
  unsigned long int skips = 0;
 
  if (!input_initialized) {
    /* put screen in raw data mode */
    system("stty   -icanon");
    input_initialized = true;
  }

  // Echo a prompt
  cout << "> ";
  cout.flush();
  // Read the input
  i = 0;
  c = 0;
  while (i < max_length-1 && c != '\n' ) {
    // Set up stdin buffer probe
    FD_ZERO(&rfds);
    FD_SET(0, &rfds);
    
    tv.tv_sec = 0;
    tv.tv_usec = 0;
    if (!select(1, &rfds, NULL, NULL, &tv)) {
      // No input available
      skips++;
    }
    else {
      // Input available immediately
      c = getchar();
      if (c != '\n' ) {
	command[i++] = c;
	// Test for arrow key codes
	if (i >= 3) {
	  if (command[i-3] == 27 && command[i-2] == '[' ) {
	    if (command[i-1] == 'A' ) {
	      // Up arrow
	      cout << (char) 13 << "  ";
	      for(j=0; j<i+1; j++)
		cout << " ";
	      cout << (char)13 << "> ";
	      strcpy(command, "UP" );
	      cout << command;
	      cout.flush();
	      i = strlen(command);
	    }
	    else if (command[i-1] == 'B' ) {
	      // Down arrow	  
	      printf("%c  ",(char) 13);
	      for(j=0; j<i+1; j++)
		printf(" ");
	      strcpy( command, "DOWN" );
	      printf("%c> %s", (char) 13, command);
	      i = strlen(command);
	    }
	  }
	}
      }
    }
  }
  command[i] = 0;
  if (c != '\n' )
    cout << endl;
  
  printf("Skips: %ld\n", skips);

  return;
}
Last edited by JdS : 01-Feb-2005 at 06:09. Reason: Please insert your example C/C++ codes between [c] and [/c] tags
 
 

Recent GIDBlogPython ebook by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Receive arrow key input tay C++ Forum 12 28-Aug-2008 18:54

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 06:57.


vBulletin, Copyright © 2000 - 2008, Jelsoft Enterprises Ltd.