Thread: Detecting esc... or any other key (kbhit()) alternative.

  1. #1
    Registered User Staz's Avatar
    Join Date
    Aug 2002
    Posts
    8

    Detecting esc... or any other key (kbhit()) alternative.

    I am writing an application in Linux to display certin text and hex images on a large LCD screen and everything seems to be working fine except: I wrote a "commander" to issue instructions, I have it set on a loop to refresh the display data and if want to stop it (break) to issue a new command then I have to use ctrl+c which exits the entire application. I would like to beable just to hit esc or any other key so I just break the loop and not the whole application. I found a function which works under Windows (kbhit()) but is included in the conio.h header so it doesn't work under Linux...

    if (kbhit()) break; is what I wold use under Windows, is there an ANSI-C or C++ alternative that would work under Linux?

    Thanks
    Last edited by Staz; 11-03-2002 at 06:46 AM.

  2. #2
    still a n00b Jaguar's Avatar
    Join Date
    Jun 2002
    Posts
    187
    Try curses.h on linux with -lcurses option while compiling with gcc or g++. Or if you still want to use conio.h, links...

    -------------
    Jaguar

  3. #3
    Registered User Fredd's Avatar
    Join Date
    Oct 2002
    Posts
    69
    Try curses.h on linux
    there is no kbhit function in (n)curses but there is a getch() function if that is what you are looking for.
    otherwise you could try this :

    Code:
    int kbhit(void)
    {
      int cnt = 0;
      int error;
      static struct termios Otty, Ntty;
    
    
      tcgetattr( 0, &Otty);
      Ntty = Otty;
    
      Ntty.c_iflag          = 0;       /* input mode                */
      Ntty.c_oflag          = 0;       /* output mode               */
      Ntty.c_lflag         &= ~ICANON; /* raw mode */
      Ntty.c_cc[VMIN]       = CMIN;    /* minimum time to wait      */
      Ntty.c_cc[VTIME]      = CTIME;   /* minimum characters to wait for */
    
      if (0 == (error = tcsetattr(0, TCSANOW, &Ntty))) {
        error += ioctl(0, FIONREAD, &cnt);
        error += tcsetattr(0, TCSANOW, &Otty);
      }
    
      return ( error == 0 ? cnt : -1 );
    }
    worked for me.
    "Writing software is more fun than working."

    got slack?
    http://www.slackware.com/

  4. #4
    Registered User
    Join Date
    Nov 2007
    Posts
    1
    what kind of include files do you need for this function?
    i managed to figure out termios.h, unistd.h, stdlib.h but i still get undeclared errors for CMIN, CTIME, and FIONREAD

  5. #5
    Registered User
    Join Date
    Nov 2006
    Posts
    519
    you can use this kbhit-replacement. No need to link curses if you use it. it works fine for me:

    Code:
    // kbhit.h
    
    #ifdef _WIN32
    #else
    
    #ifndef KBHIT_H_
    #define KBHIT_H_
    
    
    // non-blocking keyboard i/o for linux
    // on win32 use kbhit() and read()
    
    
    /* ***************************************************************************
     *
     *          Copyright 1992-2005 by Pete Wilson All Rights Reserved
     *           50 Staples Street : Lowell Massachusetts 01851 : USA
     *        http://www.pwilson.net/   pete at pwilson dot net   +1 978-454-4547
     *
     * This item is free software: you can redistribute it and/or modify it as 
     * long as you preserve this copyright notice. Pete Wilson prepared this item 
     * hoping it might be useful, but it has NO WARRANTY WHATEVER, not even any 
     * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
     *
     *************************************************************************** */
    
    /* ***************************************************************************
     *
     *                          KBHIT.C
     *
     * Based on the work of W. Richard Stevens in "Advanced Programming in
     *   the Unix Environment," Addison-Wesley; and of Floyd Davidson. 
     *
     * Contains these functions:
     *
     *  To set the TTY mode:
     *     tty_set_raw() Unix setup to read a character at a time.
     *     tty_set_cooked() Unix setup to reverse tty_set_raw()
     *
     *  To read keyboard input:
     *     kb_getc()      keyboard get character, NON-BLOCKING. If a char
     *                      has been typed, return it. Else return 0.
     *     kb_getc_w()    kb get char with wait: BLOCKING. Wait for a char
     *                      to be typed and return it.
     *
     *  How to use:
     *     tty_set_raw()  set the TTY mode to read one char at a time.
     *     kb_getc()      read chars one by one.
     *     tty_set_cooked() VERY IMPORTANT: restore cooked mode when done.
     *
     * Revision History:
     *
     *     DATE                  DESCRIPTION
     * -----------    --------------------------------------------
     * 12-jan-2002     new
     * 20-aug-2002     cleanup
     * 24-nov-2003     Fixed kb_getc() so that it really is non blocking(JH)
     * 10-sep-2006     Let kb_getc() work right under certain Unix/Linux flavors
     *
     *************************************************************************** */
    
    #ifdef __cplusplus
      extern "C" {
    #endif
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <termios.h>
    #include <unistd.h>
    #include <errno.h>
    
    #ifndef STDIN_FILENO
      #define STDIN_FILENO 0
    #endif
    
    extern int errno;                 
    
    
    
    /* ***************************************************************************
     *
     * set_tty_raw(), put the user's TTY in one-character-at-a-time mode.
     * returns 0 on success, -1 on failure.
     *
     *************************************************************************** */
    int
    set_tty_raw(void);
    
    /* ***************************************************************************
     *
     * set_tty_cbreak(), put the user's TTY in cbreak mode.
     * returns 0 on success, -1 on failure.
     *
     *************************************************************************** */
    int 
    set_tty_cbreak();
    
    /* ***************************************************************************
     *
     * set_tty_cooked(), restore normal TTY mode. Very important to call
     *   the function before exiting else the TTY won't be too usable.
     * returns 0 on success, -1 on failure.
     *
     *************************************************************************** */
    int
    set_tty_cooked();
    
    /* ***************************************************************************
     *
     * kb_getc(), if there's a typed character waiting to be read,
     *   return it; else return 0.
     * 10-sep-2006: kb_getc() fails (it hangs on the read() and never returns
     * until a char is typed) under some Unix/Linux versions: ubuntu, suse, and
     * maybe others. To make it work, please uncomment two source lines below.
     *
     *************************************************************************** */
    unsigned char
    kb_getc(void);
    
    /* ***************************************************************************
     *
     * kb_getc_w(), wait for a character to be typed and return it.
     *
     *************************************************************************** */
    unsigned char
    kb_getc_w(void);
    
    
    #define TEST
    #ifdef TEST
    
    void echo(unsigned char ch);
    
    //static enum 
    //{ 
    //  CH_ONLY, CH_HEX 
    //} how_echo = CH_ONLY;
    
    
    
    void
    echo(unsigned char ch);
    
    #endif /* test */
    
    
    #ifdef __cplusplus
    }
    #endif
    
    
      
    
    #endif /*KBHIT_H_*/
    
    #endif // _WIN32


    Code:
    // .cpp
    
    #ifdef _WIN32
    #else
    
    
    #include "kbhit.h"
    
    static struct termios termattr, save_termattr;
    static int ttysavefd = -1;
    static enum 
    { 
      RESET, RAW, CBREAK 
    } ttystate = RESET;
    
    /* ***************************************************************************
     *
     * set_tty_raw(), put the user's TTY in one-character-at-a-time mode.
     * returns 0 on success, -1 on failure.
     *
     *************************************************************************** */
    int
    set_tty_raw(void) 
    {
      int i;
    
      i = tcgetattr (STDIN_FILENO, &termattr);
      if (i < 0) 
      {
        printf("tcgetattr() returned &#37;d for fildes=%d\n",i,STDIN_FILENO); 
        perror ("");
        return -1;
      }
      save_termattr = termattr;
    
      termattr.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
      termattr.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
      termattr.c_cflag &= ~(CSIZE | PARENB);
      termattr.c_cflag |= CS8;
      termattr.c_oflag &= ~(OPOST);
       
      termattr.c_cc[VMIN] = 1;  /* or 0 for some Unices;  see note 1 */
      termattr.c_cc[VTIME] = 0;
    
      i = tcsetattr (STDIN_FILENO, TCSANOW, &termattr);
      if (i < 0) 
      {
        printf("tcsetattr() returned %d for fildes=%d\n",i,STDIN_FILENO); 
        perror("");
        return -1;
      }
       
      ttystate = RAW;
      ttysavefd = STDIN_FILENO;
    
      return 0;
    }
    
    /* ***************************************************************************
     *
     * set_tty_cbreak(), put the user's TTY in cbreak mode.
     * returns 0 on success, -1 on failure.
     *
     *************************************************************************** */
    int 
    set_tty_cbreak() 
    {
      int i;
    
      i = tcgetattr (STDIN_FILENO, &termattr);
      if (i < 0) 
      {
        printf("tcgetattr() returned %d for fildes=%d\n",i,STDIN_FILENO); 
        perror ("");
        return -1;
      }
    
      save_termattr = termattr;
    
      termattr.c_lflag &= ~(ECHO | ICANON);
      termattr.c_cc[VMIN] = 1;
      termattr.c_cc[VTIME] = 0;
          
      i = tcsetattr (STDIN_FILENO, TCSANOW, &termattr);
      if (i < 0) 
      {
        printf("tcsetattr() returned %d for fildes=%d\n",i,STDIN_FILENO); 
        perror ("");
        return -1;
      }
      ttystate = CBREAK;
      ttysavefd = STDIN_FILENO;
    
      return 0;
    }
    
    /* ***************************************************************************
     *
     * set_tty_cooked(), restore normal TTY mode. Very important to call
     *   the function before exiting else the TTY won't be too usable.
     * returns 0 on success, -1 on failure.
     *
     *************************************************************************** */
    int
    set_tty_cooked() 
    {
      int i;
      if (ttystate != CBREAK && ttystate != RAW) 
      {
        return 0;
      }
      i = tcsetattr (STDIN_FILENO, TCSAFLUSH, &save_termattr);
      if (i < 0) 
      {
        return -1;
      }
      ttystate = RESET;
      return 0;
    }
    
    /* ***************************************************************************
     *
     * kb_getc(), if there's a typed character waiting to be read,
     *   return it; else return 0.
     * 10-sep-2006: kb_getc() fails (it hangs on the read() and never returns
     * until a char is typed) under some Unix/Linux versions: ubuntu, suse, and
     * maybe others. To make it work, please uncomment two source lines below.
     *
     *************************************************************************** */
    unsigned char
    kb_getc(void) 
    {
      int i;
      unsigned char ch;
      ssize_t size;
    	termattr.c_cc[VMIN] = 0; /* uncomment if needed */
      i = tcsetattr (STDIN_FILENO, TCSANOW, &termattr);
      size = read (STDIN_FILENO, &ch, 1);
      termattr.c_cc[VMIN] = 1; /* uncomment if needed */
      i = tcsetattr (STDIN_FILENO, TCSANOW, &termattr);
      if (size == 0)
      {
        return 0;
      }
      else
      {
        return ch;
      }
    }
    
    /* ***************************************************************************
     *
     * kb_getc_w(), wait for a character to be typed and return it.
     *
     *************************************************************************** */
    unsigned char
    kb_getc_w(void) 
    {
      unsigned char ch;
      size_t size;
    
      while (1)
      {
    
        usleep(20000);        /* 1/50th second: thanks, Floyd! */
    
        size = read (STDIN_FILENO, &ch, 1);
        if (size > 0)
        {
          break;
        }
      }
      return ch;
    }
    
    
    #endif // _WIN32

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    FIVE AND A HALF YEAR BUMP - nice shooting tex!.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 16
    Last Post: 11-23-2007, 01:48 PM
  2. Virtual keys
    By Arkanos in forum Windows Programming
    Replies: 4
    Last Post: 12-12-2005, 10:00 AM
  3. Directional Keys - Useing in Console
    By RoD in forum C++ Programming
    Replies: 38
    Last Post: 10-06-2002, 04:42 PM
  4. FAQ: Directional Keys - Useing in Console
    By RoD in forum FAQ Board
    Replies: 38
    Last Post: 10-06-2002, 04:42 PM