/*----------------------------------------------------------------
 *  tty.c - tty specific functions
 *
 *  Directory:
 *    TT_addch (ch)             - add a character on screen
 *    TT_getch ()               - read keyboard
 *    TT_initscr ()             - initialize TTY
 *    TT_endwin ()              - restore TTY
 *    TT_echo ()                - switch echo on
 *    TT_noecho ()              - switch echo off
 *    TT_raw ()                 - set raw mode
 *    TT_noraw ()               - set cooked mode
 *
 *  Author: Frank Meyer
 *  (c) Copyright 1992 textware GmbH Koeln
 *--------------------------------------------------------------*/

#include <ecurses.h>
#include "private.h"
#include <sys/termio.h>

extern unsigned char key_table[MAX_KEYS][MAX_KEY_SEQ_LEN];

extern char * keyname_table[];

static struct termio oldmode;         /* initial terminal mode */
static struct termio newmode;         /* current terminal mode */

/*----------------------------------------------------------------
 *    TT_addch (ch)             - add a character on screen
 *--------------------------------------------------------------*/

int
TT_addch (ch)
int ch;
{
  static int  last_chset_no = -1;           /* last charset     */
  int         chset_no;                     /* current charset  */
  int         char_to_send;                 /* char to send     */
  int         attrs;

  attrs = ch & A_ATTRIBUTES;                /* get attributes   */

  ch &= A_CHARTEXT;                         /* get character    */

  if (attrs)
  {
    (*attrset_func) (attrs);                /* set attributes   */
  }

  (*move_func) ();

  chset_no     = map_table[ch].chset_no;
  char_to_send = map_table[ch].ch_out;

  if (last_chset_no != chset_no)            /* charset changed? */
  {                                         /* yes, send new    */
    last_chset_no = chset_no;               /* charset sequence */
    fputs (charset[chset_no], stdout);
  }
  putc (char_to_send, stdout);              /* send character   */

  if (ch == '\n')
  {
    if (stdscr->cury < LINES)
    {
      stdscr->cury++;
    }
    stdscr->curx = 0;
  }
  else
  {
      stdscr->curx++;
  }
  return (OK);
} /* TT_addch (ch) */


/*----------------------------------------------------------------
 *    TT_getch ()               - read keyboard
 *--------------------------------------------------------------*/

int
TT_getch ()
{
  int ch;                           /* character to be read     */
  int len = 0;                      /* length of input sequence */
  int scan = 0;                     /* scancode                 */
  unsigned char buf[MAX_KEY_SEQ_LEN]; /* input buffer           */

  (*move_func) ();

  fflush (stdout);                  /* 1st flush output stream  */

  ch = getchar ();                  /* read one character       */

  if (key_table[ch][0] == ch && key_table[ch][1] == '\0')
  {                                 /* simple character, return */
    return (ch);                    /* it                       */
  }

  buf[len++] = ch;                  /* no simple character,     */
  buf[len] = '\0';                  /* store it in input buffer */

  while (scan < MAX_KEYS)           /* search input sequence    */
  {                                 /* in key table             */
    if (! strncmp (buf, key_table[scan], len))
    {                               /* found ?                  */
      if (key_table[scan][len] == '\0') /* yes, but more chars? */
      {                             /* no, we are ready         */
        return (scan);              /* return scan code         */
      }
      else                          /* there must be more ..    */
      {
        ch = getchar ();            /* read next character      */
        buf[len++] = ch;            /* and store it in buf      */
        buf[len] = '\0';
      }
    }
    else                            /* key_table doesn't        */
    {                               /* match, try next scan     */
      scan++;                       /* code                     */
    }
  }

  return (KEY_ERR);                 /* unknown key !            */
} /* TT_getch () */


/*----------------------------------------------------------------
 *    TT_initscr ()             - initialize TTY
 *--------------------------------------------------------------*/

TT_initscr ()
{
  (void) ioctl (0, TCGETA, &oldmode);
  (void) ioctl (0, TCGETA, &newmode);

  newmode.c_iflag        |= ICRNL;   /* map CR into NL          */
  newmode.c_iflag        &= ~INLCR;  /* don't map NL into CR    */
  newmode.c_lflag        &= ~ICANON; /* no canonical input      */
  newmode.c_oflag        &= ~TAB3;   /* switch off TAB conv     */
  newmode.c_cc[VMIN]     = 1;        /* read only one character */
  newmode.c_cc[VTIME]    = 0;        /* block input             */

  return (ioctl (0, TCSETAW, &newmode));
} /* TT_initscr () */


/*----------------------------------------------------------------
 *    TT_endwin ()              - restore TTY
 *--------------------------------------------------------------*/

int
TT_endwin ()
{
    (void) ioctl (0, TCSETAW, &oldmode); /* return to init mode */
    return (OK);
} /* TT_endwin () */


/*----------------------------------------------------------------
 *    TT_echo ()                - switch echo on
 *--------------------------------------------------------------*/

int
TT_echo ()
{
  newmode.c_lflag |= ECHO;                  /* echo on         */
  return (ioctl (0, TCSETAW, &newmode));    /* set new mode    */
} /* TT_echo () */


/*----------------------------------------------------------------
 *    TT_noecho ()              - switch echo off
 *--------------------------------------------------------------*/

int
TT_noecho ()
{
  newmode.c_lflag &= ~ECHO;                 /* echo off        */
  return (ioctl (0, TCSETAW, &newmode));    /* set new mode    */
} /* TT_noecho () */


/*----------------------------------------------------------------
 *    TT_raw ()             - set raw mode
 *--------------------------------------------------------------*/

int
TT_raw ()
{
  newmode.c_cc[VINTR] = '\377';     /* disable VINTR VQUIT      */
  newmode.c_cc[VQUIT] = '\377';     /* but don't touch VSWTCH   */
  return (ioctl (0, TCSETAW, &newmode));
} /* TT_raw () */


/*----------------------------------------------------------------
 *    TT_noraw ()               - set cooked mode
 *--------------------------------------------------------------*/

int
TT_noraw ()
{
  newmode.c_cc[VINTR] = oldmode.c_cc[VINTR];
/* enable VINTR VQUIT   */
  newmode.c_cc[VQUIT] = oldmode.c_cc[VQUIT];
/* don't touch VSWTCH   */
  return (ioctl (0, TCSETAW, &newmode));
} /* TT_noraw () */

/* end of tty.c */
