[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: C/C++ programming on Linux/Unix




Hi Vlady and all the others

 I wrote few years ago such thing as part of a library.
the code is attached.

Replys are welcomed, the source is GPL I'll write help
if needed.
Try it and use it.
Maybe we should write a HOWTO for translating code from
MS / Borland to Linux with a set of functions.

Erez

BTW: no flames for using the list for the answer
     As I think the subject might be of interes for
     some other readers.

On Sun, 7 Dec 1997 rutman@handlin.pet.ac.il wrote:

> Hi.
> I have a big question.How can I get the functions like getch() and
> getche() for Linux/Unix C programs ,or possibly to develop them by
> any language (may be Assembler)?
> Has anybody have an answer or solution?
> 
> Mail me:
> rutman@handlin.pet.ac.il 
> 				Vlady
> 

/* ____________________________________________________________________________
 *
 * $Header: /home/erez/cvs-main/tlib/ukbhit.h,v 1.2 1994/08/04 13:31:37 erez Exp $
 * ukbhit.h
 * Unix kbhit emulation functions interface. This file gives the prototype
 * of a set of functions that emulate the operation of the DOS kbhit, getch
 * and getche functions.
 * The library works and tested on SunOs4.1.3 and Solaris2.3
 *
 * Written by Erez Strauss. 1994.
 *
 * $Log: ukbhit.h,v $
 * Revision 1.2  1994/08/04  13:31:37  erez
 * (1)(N) The non user function are static, (2)(N) There are new user
 * functions kbhit_on, kbhit_off.
 *
 * Revision 1.1.1.1  1994/07/06  15:44:51  erez
 * Library.
 *
 * ____________________________________________________________________________
 */

# ifndef __UKBHIT_H__
# define __UKBHIT_H__

# if defined ( __GNUC__ ) && ! defined ( NO_IDENT )
# ident "@(#)$Id: ukbhit.h,v 1.2 1994/08/04 13:31:37 erez Exp $"
# else /* __GNUC__ */
static const char _ukbhit_h_id[] = "@(#)$Id: ukbhit.h,v 1.2 1994/08/04 13:31:37 erez Exp $";
# endif /* __GNUC__ */

/* User usable Functions */
extern void kbhit_on (void);
extern void kbhit_off (void);
extern int  kbhit (void);
extern void kbwait (void); 
extern char getch (void); 
extern char getche (void); 

# endif /* __UKBHIT_H__ */

/* End of file: ukbhit.h ___________________________________________________ */

/* ____________________________________________________________________________
 *
 * $Header: /home/erez/cvs-main/tlib/ukbhit.c,v 1.4 1994/12/28 12:27:05 erez Exp $
 * Unix emulation of the PC non waiting input/output.
 *
 * Written by Erez Strauss. 1994.
 *
 * $Log: ukbhit.c,v $
 * Revision 1.4  1994/12/28  12:27:05  erez
 * (1)(N) UKBHIT_TYPE, compile time flag choose which system call to use
 *  the select or the poll.
 *
 * Revision 1.3  1994/08/04  13:30:47  erez
 * (1)(N) The non user function are static, (2)(N) There are new user
 * functions kbhit_on, kbhit_off. (3)(BGFX) the kbhit_end was calling the
 * termio set function with null argument in cat the end was called before.
 *
 * Revision 1.2  1994/07/31  08:09:13  erez
 * (1)(U) The conditions of the Identification was updated.
 *
 * Revision 1.1.1.1  1994/07/06  15:44:51  erez
 * Library.
 *
 * ____________________________________________________________________________
 */

# if ! defined ( NO_IDENT )
#   if defined ( __GNUC__ )
#     ident "@(#)$Id: ukbhit.c,v 1.4 1994/12/28 12:27:05 erez Exp $"
#   else /* __GNUC__ */
      static const char file_id[] = "@(#)$Id: ukbhit.c,v 1.4 1994/12/28 12:27:05 erez Exp $";
#   endif/* __GNUC__ */
# endif /* NO_IDENT */

# include <stdio.h>
# include <stdlib.h>
# include <memory.h>
# include <unistd.h>
# include <signal.h>
# include <sys/termios.h>
# include <sys/types.h>
# include <sys/time.h>

# define UKBHIT_SELECT 1
# define UKBHIT_POLL   2

# include "ukbhit.h"

# ifndef UKBHIT_TYPE
#  define UKBHIT_TYPE   UKBHIT_SELECT
# endif /* UKBHIT_TYPE */

# if ( UKBHIT_TYPE == UKBHIT_POLL )
# include <poll.h>
# endif /* UKBHIT_TYPE */

static void   kbhit_init (void);
static void   kbhit_end (void);

/*
 * The ukbhit library will provide the following user accessable functions:
 *  kbhit_on
 *  kbhit_off
 *  kbwait
 *  kbhit
 *  getch
 *  getche
 * The other functions in this file are static and will be used only localy.
 */

/* first - code that doesn't depend on the select / poll */

void
kbhit_on (void)
    {
    kbhit_init ();
    }

void
kbhit_off (void)
    {
    kbhit_end ();
    }

char
getch (void)
    {
    char ch = 0;

    kbwait ();
    read (0, &ch, 1);
    return ch;
    }

char
getche ()
    {
    char ch = getch ();

    fwrite (&ch, 1, 1, stdout);
    fflush (stdout);
    return ch;
    }

/* poll code */
# if ( UKBHIT_TYPE == UKBHIT_POLL )

int
kbhit (void)                    /* with poll - just check input */
    {
    int            i = 0;
    struct pollfd  ifd;

    ifd.fd = 0;
    ifd.events = POLLIN;
    ifd.revents = 0;

    kbhit_init ();
    if (poll (&ifd, 1, 0) && (ifd.revents & POLLIN))
        {
        i = 1;
        }
    return i;
    }

void
kbwait (void)                   /* with poll - just check input */
    {
    struct pollfd  ifd;

    ifd.fd = 0;
    ifd.events = POLLIN;
    ifd.revents = 0;

    fflush (stdout);
    kbhit_init ();
    poll (&ifd, 1, -1);        /* Wait without timeout */
    }

# elif ( UKBHIT_TYPE == UKBHIT_SELECT ) /* UKBHIT_TYPE */

int
kbhit (void)             /* with select - just check input */
    {
    int     i = 0;
    fd_set  fds;
    struct timeval tv;

    tv.tv_sec = 0;
    tv.tv_usec = 0;

    FD_ZERO (&fds);
    FD_SET (0, &fds);

    kbhit_init ();
    if (select (1, &fds, 0, 0, &tv))
        {
        i = 1;
        }
    return i;
    }

void
kbwait (void)            /* with select */
    {
    fd_set  fds;

    FD_ZERO (&fds);
    FD_SET (0, &fds);
    fflush (stdout);
    kbhit_init ();
    select (1, &fds, 0, 0, 0);
    }

# else

# error  ***** Error What about UKBHIT_TYPE, (UKBHIT_SELECT / UKBHIT_POLL)

# endif /* UKBHIT_TYPE */


static struct termios*	trm_init_mode = 0;
static struct termios*	trm_direct_mode = 0;

# ifdef UKBHIT_DEBUG

static void termios_dump (struct termios* p, FILE* fp); 

static void
termios_dump (struct termios* p, FILE* fp)
    {
    fprintf (fp,
             "p: 0x%lX\n"
             "c_iflag:\t0x%08lX\n"
             "c_oflag:\t0x%08lX\n"
             "c_cflag:\t0x%08lX\n"
             "c_lflag:\t0x%08lX\n"
             "c_cc[0]:\t0x%02lX\n",
             (long)p,
             (long)p->c_iflag,
             (long)p->c_oflag,
             (long)p->c_cflag,
             (long)p->c_lflag,
             (long)p->c_cc[0]);
    }

# endif /* UKBHIT_DEBUG */

static void
kbhit_init (void)
    {
    int		status;
    static int  set_at_exit = 0;
  
    if (!trm_init_mode || !trm_direct_mode)
        {
        if (!trm_init_mode)
            {
            trm_init_mode = (struct termios*)malloc (sizeof (struct termios));
            }
        if (!trm_direct_mode)
            {
            trm_direct_mode = (struct termios*)malloc (sizeof (struct termios));
            }
        if (!trm_init_mode || !trm_direct_mode)
            {
            fprintf (stderr, "kbhit_init: can't malloc !\n");
            exit (1);
            }
        status = tcgetattr (0, trm_init_mode);
      
        *trm_direct_mode = *trm_init_mode;
      
        /* change trm_direct_mode */
      
        trm_direct_mode->c_iflag &= ~BRKINT ;
        trm_direct_mode->c_oflag |= 0;
        trm_direct_mode->c_cflag |= 0;
        trm_direct_mode->c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK
                                      | ECHONL | ECHOCTL);
        /* trm_direct_mode->c_line  |= 0; */
        trm_direct_mode->c_cc[0] |= 0;
        trm_direct_mode->c_cc[VMIN] = 0;
        trm_direct_mode->c_cc[VTIME] = 0;
      
        status = tcsetattr (0, TCSANOW, trm_direct_mode);

        /* set atexit() function so at the end of the program the
         * mode will return to normal.
         */

# if defined ( __GNUC__ ) && !defined ( __svr4__ )
        /* SunOS 4.1.3 doesn't have the atexit() function. */
#  define atexit(FNC)     on_exit((FNC),0)
# endif/* __GNUC__ */

        if (!set_at_exit)
            {
            set_at_exit = 1;
            atexit (kbhit_end);
            }
        }
    }

static void
kbhit_end (void)
    {
    /*
     * We set the attributes without cleaning the input buffer.
     */
    if (trm_init_mode)
        {
        tcsetattr (0, TCSANOW, trm_init_mode);
        }
    if (trm_direct_mode)
        {
        free (trm_direct_mode);
        trm_direct_mode = 0;
        }
    if (trm_init_mode)
        {
        free (trm_init_mode);
        trm_init_mode = 0;
        }
    }

# ifdef STAND_ALONE

int
main (int argc, char** argv)
    {
    int   i = 0;
    char  buff[32];
  
    while (!kbhit ())     /* busy wait */
        {
        if (!(i++ % 1000))
            printf (".\n");
        }
    kbhit_off ();
    fprintf (stderr, "\nEnter a string: ");
    scanf ("%[^\n]", buff);
    fprintf (stderr, "the buff: '%s'\n", buff);

    return 0;
    }

# endif /* STAND_ALONE */

/* End of file: ukbhit.c ___________________________________________________ */