Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations bkrike on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Catch the up-arrow keypress

Status
Not open for further replies.

jstreich

Programmer
Apr 20, 2002
1,067
US
I'm looking for a way to catch when the user presses the up arrow. It can only use standard libraries and shouldn't use curses... I'm working on a shell, and the basic functionality is done, and I want to add the scroll feature bash has (that is go backward through the history (I already have a history for the bang-bang, and will be writting bang later).
 
wath is the OS of the server?

in most unix you have the getch() function, if not (as linux) you will need to write one.

Anyway, arrow keys are 2 byte keys, so if you press up arrow, actually you are pressing <esc> and A keys. So, a pseudo could by:

A=getch()
if A=27 (esc key)
{
B=getch();
if B=&quot;A&quot; <-- you pressed up key!!
{
code
}
}

Hope this helps.
 
It's HP-Unix, and it appears to be
<esc>+[+a
as it is echoed as ^[[A
I'm currently using getline to retrive the user imput. I'll try and play with it to see what I can do with it.
 
ok.. then 3 bytes:

A=getch()
if A=27 (esc key)
{
B=getch();
if B=&quot;[&quot;
{
C=getch();
if C=&quot;A&quot; <-- you pressed up key!!
{
code
}
}
}
 
Oh, getline still requires a \n char... hmmm.
will play with it, thanks for the advice.
 
It appears that I've got to write my own getline function... because I want to do stuff on:
up, down, and a string + \n...

I don't seem to have a gtch (not stanard) but I do have getchar... and it eating the escape chars.

 
> It appears that I've got to write my own getline function...

Before doing this, You should really look at using getch() it's in curses (or ncurses), it handles it all for you.

Here's a brief example that needs to be compiled with the curses or ncurses library:

Code:
#include <stdio.h>
#include <curses.h>

int main() {

  int c=0;
  char line[250]=&quot;&quot;;
  int j = 0;

  initscr();
  raw();
  noecho();

  keypad(stdscr,TRUE);
  cbreak();

  while (c != '\n') {
    c = getch();
    mvprintw(0,0,&quot;key value: %04d\n&quot;,c);

    switch(c) {
      case KEY_UP:   mvprintw(1,0,&quot;UP Arrow   &quot;);
                     break;
      case KEY_DOWN: mvprintw(1,0,&quot;Down Arrow &quot;);
                     break;
      case KEY_LEFT: mvprintw(1,0,&quot;Left Arrow &quot;);
                     break;
      case KEY_RIGHT:mvprintw(1,0,&quot;Right Arrow&quot;);
                     break;

      default: if (c <= 'z' && c >= ' ') {
                 line[j++] = c;
                 line[j] = '\0';
               }
    }
    refresh();
  }
  mvprintw(2,0,&quot;The string is: %s&quot;,line);
  refresh();
  endwin();
  return 0;
}
 
This is what I got from your code (copy-paste):
Code:
Undefined                       first referenced
 symbol                             in file
endwin                              /var/tmp//cc2w6L8T.o
wgetch                              /var/tmp//cc2w6L8T.o
cbreak                              /var/tmp//cc2w6L8T.o
stdscr                              /var/tmp//cc2w6L8T.o
initscr                             /var/tmp//cc2w6L8T.o
mvprintw                            /var/tmp//cc2w6L8T.o
refresh                             /var/tmp//cc2w6L8T.o
raw                                 /var/tmp//cc2w6L8T.o
noecho                              /var/tmp//cc2w6L8T.o
keypad                              /var/tmp//cc2w6L8T.o
ld: fatal: Symbol referencing errors. No output written to curses

I'm not admin on the machine, and I've tried curses earlier as well -- I think it's not set up right. I think I'm not going have the cool scroll feature... :( ... But, I am implementing the history to take an optional parameter (the number of the command, the last one being zero). I've always wanted to play with curses, but most of my stuff is simple commandline or all-out windowed gui.

When I have more time, I'll port it to linux (shouldn't be difficult, as linux is almost POSIX compliant) and then I'll pla with adding the curses on my own machine.
 
Ok, readch.c, tested on linux and hp-ux.
Code:
************* readch.c ***********
#include <stdio.h>
#include <termios.h>
//#include <term.h>
//#include <curses.h>
#include <unistd.h>
/*-------------------------------------------------------*/
static struct termios initial_settings, new_settings;
static int peek_character = -1;
/*-------------------------------------------------------*/
void init_keyboard()
{
  tcgetattr( 0, &initial_settings );
  new_settings = initial_settings;
  new_settings.c_lflag &= ~ICANON;
  new_settings.c_lflag &= ~ECHO;
  new_settings.c_lflag &= ~ISIG;
  new_settings.c_cc[VMIN] = 1;
  new_settings.c_cc[VTIME] = 0;
  tcsetattr( 0, TCSANOW, &new_settings );
}

void close_keyboard()
{
  tcsetattr( 0, TCSANOW, &initial_settings );
}

int kbhit()
{
  char ch;
  int nread;
 
  if( peek_character != -1 )
    return( 1 );
  new_settings.c_cc[VMIN] = 0;
  tcsetattr( 0, TCSANOW, &new_settings );
  nread = read( 0, &ch, 1 );  
  new_settings.c_cc[VMIN] = 1;  
  tcsetattr( 0, TCSANOW, &new_settings );
  if( nread == 1 ) {
    peek_character = ch;
    return( 1 );
  }
  return( 0 );
}

int readch()
{
  char ch;
  init_keyboard();
  if( peek_character != -1 ) {
    ch = peek_character;
    peek_character = -1;
    return( ch );
  }
  read( 0, &ch, 1 );
  close_keyboard();
  return( ch );
}

int main()
{
    char c,ext;
//	init_keyboard();

 	c=readch();  //       <---- getch()
	if(c!=27)	
		printf(&quot;Caracter: %c - ASCII: %d\n\n&quot;,c,c);
	else {
		ext=readch();
		printf(&quot;Caracteres: %d - %d\n\n&quot;,c,ext);
	}
	
// 	close_keyboard();
}
 
Chacalinc,
That doesn't seem to work. It does sucessfully block printing of the ^[[A char and catch the up arrow, but does something odd to all the other I/O. I saw this posted when I first searched before posting. It is the closest that I've gotten, and I tried to play arround with it a little... but alas, the termio flags (even with the man page) are little hard to keep straight.

I will get the rest of this thing working and if I have still have the time to play with it, I'll start putzing with the termio flags trying to get it behave the way I need.
 
*********************************************************************
try this:
Code:
#include <conio.h>
#define CTRL_Z 26
#define FRONT_ARROW 77
#define BACK_ARROW 75
#define DOWN_ARROW 80
#define UP_ARROW 72


void main()
{
    int ch;

    while(( ch = getch() ) != CTRL_Z ) // stops with CTRL-Z
    {
        switch(ch) {
        case FRONT_ARROW:
            cprintf(&quot;Front arrow.\r\n&quot;);
            break;
        case BACK_ARROW:
            cprintf(&quot;Back arrow.\r\n&quot;);
            break;
        case DOWN_ARROW:
            cprintf(&quot;Down arrow.\r\n&quot;);
            break;
        case UP_ARROW:
            cprintf(&quot;Up arrow.\r\n&quot;);
            break;
        }//etc
    }
}
 
No <conio.h> on the system, and I don't have the permission to add it. :(
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top