4

I gone through the Documentation of NCURSES. I am not getting that if I use getch without initscr then why this program is not working. Is there any other approach to get arrow keys input without clearing screen (that initscr do).

#include <ncurses.h>
#include <unistd.h>
int main()
{
    int ch;
    //initscr();
    //raw();
    //keypad(stdscr, TRUE);
    //noecho();

    while(1)
    {
        ch = getch();
        switch(ch)
        {
            case KEY_UP: 
                printw("\nUp Arrow");
                break;
            case KEY_DOWN: 
                printw("\nDown Arrow");
                break;
            case KEY_LEFT: 
                printw("\nLeft Arrow");
                break;
            case KEY_RIGHT: 
                printw("\nRight Arrow");
                break;
        }

        if(ch == KEY_UP)
            break;
    }
    //endwin();
}
piyush-balwani
  • 524
  • 3
  • 15

3 Answers3

2

getch is the same as wgetch(stdscr). It assumes that the screen has been initialized. ncurses (any curses implementation) has to do a couple of things to make wgetch usable:

  • read the terminal description
  • initialize the terminal I/O modes
  • allocate a screen to draw on.

The last is because wgetch does a wrefresh on the window for which it was called, before doing a read.

You could use newterm with filter to avoid clearing the screen, and doing line-oriented input. The filter program in ncurses-examples demonstrates how to do this.

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
  • with use of filter and newterm, it is working, but not showing any printw statements. It shows ^[[A for 'up arrow key' instead of printw("\nUp Arrow"); statement output. – piyush-balwani Aug 11 '15 at 17:07
  • You have to call `keypad(stdscr,TRUE);` to fix that. Also, using `filter`, it only displays on the current line -- and a `printw` containing a newline will clear the (one-line) window. – Thomas Dickey Aug 11 '15 at 20:47
2

Alternatively you may use change the terminal attribute through tcsetattr in termios. If you cycle between the canonical mode (requires new line for the process to begin) and non-canonocal mode (Keypress is more than enough).

The following program works as follows - THe process waits for user input. If up arrow key is pressed, it prints 'Arrow key pressed' and exits. If something else is pressed, it waits for the user to press Enter and then prints the user inpu. Exits after the inut is printed.

#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
  struct termios oldt, newt;
  char ch, command[20];
  int oldf;

  tcgetattr(STDIN_FILENO, &oldt);
  newt = oldt;
  newt.c_lflag &= ~(ICANON | ECHO);
  tcsetattr(STDIN_FILENO, TCSANOW, &newt);
  oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
  fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);

  while(1)
  {
    ch = getchar();
    if (ch == '\033')
    { printf("Arrow key\n"); ch=-1; break;}
    else if(ch == -1) // by default the function returns -1, as it is non blocking
    {
      continue;
    }
    else
    {
      break;
    }

  }
  tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
  fcntl(STDIN_FILENO, F_SETFL, oldf);
  if(ch != EOF)
  {
    ungetc(ch,stdin);ith
    putchar(ch);
    scanf("%s",command);
    printf("\n%s\n",command);

    return 1;
  }

  return 0;
}
Amrith Krishna
  • 2,768
  • 3
  • 31
  • 65
  • My answer is relevant to ". Is there any other approach to get arrow keys input without clearing screen (that initscr do)." and not to the question title – Amrith Krishna Aug 12 '15 at 16:12
  • I provided an alternative solution to your question. I am still not sure this is the answer you really wanted. – Amrith Krishna Aug 17 '15 at 03:28
0

I have a solution without ncurses

You can use simple-getch like this:

t_key keys[] = {
  {"[A", K_UP},
  {"[B", K_DOWN},
  {"[D", K_LEFT},
  {"[C", K_RIGHT},
  {NULL, K_UNK},
};

int key;

ch_init();
while ((key = ch_get(keys)) != K_BACK)
  {
    printf("%d\n", key);
  }
ch_end();

keys array is a list of escape sequences which will be used, (when you type an arrow key in a terminal, it will write an escape key followed by multiples characters to define the key.)

This sequences may/will change between terminals, you should use termcap to properly set this sequences.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Arnaud Aliès
  • 1,079
  • 13
  • 26