/* TN5250 - An implementation of the 5250 telnet protocol.
 * Copyright (C) 1997 Michael Madore
 * 
 * This file is part of TN5250.
 *
 * TN5250 is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1, or (at your option)
 * any later version.
 * 
 * TN5250 is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this software; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307 USA
 * 
 */
#define _TN5250_TERMINAL_PRIVATE_DEFINED
#include "tn5250-private.h"

#if USE_SLANG

/* Mapping of 5250 colors to curses colors */
#define A_5250_WHITE    0x100
#define A_5250_RED      0x200
#define A_5250_TURQ     0x300
#define A_5250_YELLOW   0x400
#define A_5250_PINK     0x500
#define A_5250_BLUE     0x600
#define A_5250_BLACK	0x700
#define A_5250_GREEN    0x800

#define A_COLOR_MASK	0xf00

#define A_REVERSE	0x1000
#define A_UNDERLINE	0x2000
#define A_BLINK		0x4000
#define A_VERTICAL	0x8000

static int attribute_map[] =
{A_5250_GREEN,
 A_5250_GREEN | A_REVERSE,
 A_5250_WHITE,
 A_5250_WHITE | A_REVERSE,
 A_5250_GREEN | A_UNDERLINE,
 A_5250_GREEN | A_UNDERLINE | A_REVERSE,
 A_5250_WHITE | A_UNDERLINE,
 0x00,
 A_5250_RED,
 A_5250_RED | A_REVERSE,
 A_5250_RED | A_BLINK,
 A_5250_RED | A_BLINK | A_REVERSE,
 A_5250_RED | A_UNDERLINE,
 A_5250_RED | A_UNDERLINE | A_REVERSE,
 A_5250_RED | A_UNDERLINE | A_BLINK,
 0x00,
 A_5250_TURQ | A_VERTICAL,
 A_5250_TURQ | A_VERTICAL | A_REVERSE,
 A_5250_YELLOW | A_VERTICAL,
 A_5250_YELLOW | A_VERTICAL | A_REVERSE,
 A_5250_TURQ | A_UNDERLINE | A_VERTICAL,
 A_5250_TURQ | A_UNDERLINE | A_REVERSE | A_VERTICAL,
 A_5250_YELLOW | A_UNDERLINE | A_VERTICAL,
 0x00,
 A_5250_PINK,
 A_5250_PINK | A_REVERSE,
 A_5250_BLUE,
 A_5250_BLUE | A_REVERSE,
 A_5250_PINK | A_UNDERLINE,
 A_5250_PINK | A_UNDERLINE | A_REVERSE,
 A_5250_BLUE | A_UNDERLINE,
 0x00};

static void slang_terminal_init(Tn5250Terminal * This);
static void slang_terminal_term(Tn5250Terminal * This);
static void slang_terminal_destroy(Tn5250Terminal /*@only@*/ * This);
static int slang_terminal_width(Tn5250Terminal * This);
static int slang_terminal_height(Tn5250Terminal * This);
static int slang_terminal_flags(Tn5250Terminal * This);
static void slang_terminal_update(Tn5250Terminal * This,
				   Tn5250Display * display);
static void slang_terminal_update_indicators(Tn5250Terminal * This,
					      Tn5250Display *display);
static int slang_terminal_waitevent(Tn5250Terminal * This);
static int slang_terminal_getkey(Tn5250Terminal * This);
static void slang_terminal_beep(Tn5250Terminal * This);
static int slang_terminal_enhanced (Tn5250Terminal * This);
static int slang_terminal_get_esc_key(Tn5250Terminal * This, int is_esc);
static void slang_terminal_set_attrs (Tn5250Terminal * This, int attrs);

struct _Tn5250TerminalPrivate {
   int quit_flag;
   int last_width, last_height;
   int attrs;
};

/****f* lib5250/tn5250_slang_terminal_new
 * NAME
 *    tn5250_slang_terminal_new
 * SYNOPSIS
 *    ret = tn5250_slang_terminal_new ();
 * INPUTS
 *    None
 * DESCRIPTION
 *    Create a new curses terminal object.
 *****/
Tn5250Terminal *tn5250_slang_terminal_new()
{
   Tn5250Terminal *r = tn5250_new(Tn5250Terminal, 1);
   if (r == NULL)
      return NULL;

   r->data = tn5250_new(struct _Tn5250TerminalPrivate, 1);
   if (r->data == NULL) {
      free(r);
      return NULL;
   }

   r->data->quit_flag = 0;
   r->data->last_width = 0;
   r->data->last_height = 0;
   r->data->attrs = 0;

   r->conn_fd = -1;
   r->init = slang_terminal_init;
   r->term = slang_terminal_term;
   r->destroy = slang_terminal_destroy;
   r->width = slang_terminal_width;
   r->height = slang_terminal_height;
   r->flags = slang_terminal_flags;
   r->update = slang_terminal_update;
   r->update_indicators = slang_terminal_update_indicators;
   r->waitevent = slang_terminal_waitevent;
   r->getkey = slang_terminal_getkey;
   r->putkey = NULL;
   r->beep = slang_terminal_beep;
   r->flags = slang_terminal_enhanced;
   return r;
}

/****i* lib5250/slang_terminal_init
 * NAME
 *    slang_terminal_init
 * SYNOPSIS
 *    slang_terminal_init (This);
 * INPUTS
 *    Tn5250Terminal *     This       - 
 * DESCRIPTION
 *    DOCUMENT ME!!!
 *****/
static void slang_terminal_init(Tn5250Terminal * This)
{
   SLtt_get_terminfo ();
   if (-1 == SLkp_init ()) {
      SLang_doerror ("SLkp_init failed.");
      exit (255);
   }
   if (-1 == SLang_init_tty (K_CTRL('Q'), 1, 0)) {
      SLang_doerror ("SLang_init_tty failed.");
      exit (255);
   }
   SLang_set_abort_signal (NULL);
   if (-1 == SLsmg_init_smg ()) {
      SLang_doerror ("SLsmg_init_smg failed.");
      exit (255);
   }

   SLtt_set_color_fgbg (1, SLSMG_COLOR_BRIGHT_WHITE, SLSMG_COLOR_BLACK);
   SLtt_set_color_fgbg (2, SLSMG_COLOR_RED, SLSMG_COLOR_BLACK);
   SLtt_set_color_fgbg (3, SLSMG_COLOR_BLUE, SLSMG_COLOR_BLACK);
   SLtt_set_color_fgbg (4, SLSMG_COLOR_BRIGHT_BROWN, SLSMG_COLOR_BLACK);
   SLtt_set_color_fgbg (5, SLSMG_COLOR_BRIGHT_MAGENTA, SLSMG_COLOR_BLACK);
   SLtt_set_color_fgbg (6, SLSMG_COLOR_BRIGHT_BLUE, SLSMG_COLOR_BLACK);
   SLtt_set_color_fgbg (7, SLSMG_COLOR_BLACK, SLSMG_COLOR_BLACK);
   SLtt_set_color_fgbg (8, SLSMG_COLOR_GREEN, SLSMG_COLOR_BLACK);

   SLsmg_cls ();
   SLsmg_refresh ();
   This->data->quit_flag = 0;
}

/****i* lib5250/slang_terminal_term
 * NAME
 *    slang_terminal_term
 * SYNOPSIS
 *    slang_terminal_term (This);
 * INPUTS
 *    Tn5250Terminal *     This       - 
 * DESCRIPTION
 *    DOCUMENT ME!!!
 *****/
static void slang_terminal_term(Tn5250Terminal * This)
{
   SLsmg_reset_smg ();
   SLang_reset_tty ();
}

/****i* lib5250/slang_terminal_destroy
 * NAME
 *    slang_terminal_destroy
 * SYNOPSIS
 *    slang_terminal_destroy (This);
 * INPUTS
 *    Tn5250Terminal *     This       - 
 * DESCRIPTION
 *    DOCUMENT ME!!!
 *****/
static void slang_terminal_destroy(Tn5250Terminal * This)
{
   if (This->data != NULL)
      free(This->data);
   free(This);
}

/****i* lib5250/slang_terminal_width
 * NAME
 *    slang_terminal_width
 * SYNOPSIS
 *    ret = slang_terminal_width (This);
 * INPUTS
 *    Tn5250Terminal  *    This       - 
 * DESCRIPTION
 *    DOCUMENT ME!!!
 *****/
static int slang_terminal_width(Tn5250Terminal /*@unused@*/ * This)
{
   SLtt_get_screen_size();
   return SLtt_Screen_Cols;
}

/****i* lib5250/slang_terminal_height
 * NAME
 *    slang_terminal_height
 * SYNOPSIS
 *    ret = slang_terminal_height (This);
 * INPUTS
 *    Tn5250Terminal  *    This       - 
 * DESCRIPTION
 *    DOCUMENT ME!!!
 *****/
static int slang_terminal_height(Tn5250Terminal /*@unused@*/ * This)
{
   SLtt_get_screen_size();
   return SLtt_Screen_Rows;
}

/****i* lib5250/slang_terminal_flags
 * NAME
 *    slang_terminal_flags
 * SYNOPSIS
 *    ret = slang_terminal_flags (This);
 * INPUTS
 *    Tn5250Terminal  *    This       - 
 * DESCRIPTION
 *    DOCUMENT ME!!!
 *****/
static int slang_terminal_flags(Tn5250Terminal /*@unused@*/ * This)
{
   int f = 0;
   if (SLtt_Use_Ansi_Colors)
      f |= TN5250_TERMINAL_HAS_COLOR;
   return f;
}

/****i* lib5250/slang_terminal_update
 * NAME
 *    slang_terminal_update
 * SYNOPSIS
 *    slang_terminal_update (This, display);
 * INPUTS
 *    Tn5250Terminal *     This       - 
 *    Tn5250Display *      display    - 
 * DESCRIPTION
 *    DOCUMENT ME!!!
 *****/
static void slang_terminal_update(Tn5250Terminal * This, Tn5250Display * display)
{
   int my, mx;
   int y, x;
   int curs_attr, temp_attr;
   unsigned char a = 0x20, c;

   if (This->data->last_width != tn5250_display_width(display)
       || This->data->last_height != tn5250_display_height(display)) {
      SLsmg_cls ();
      This->data->last_width = tn5250_display_width(display);
      This->data->last_height = tn5250_display_height(display);
      slang_terminal_update_indicators(This, display);
   }
   SLsmg_normal_video ();
   my = SLtt_Screen_Rows - 1;
   mx = SLtt_Screen_Cols - 1;
   for (y = 0; y < tn5250_display_height(display); y++) {
      if (y > my)
	 break;

      SLsmg_gotorc (y, 0);
      for (x = 0; x < tn5250_display_width(display); x++) {
	 c = tn5250_display_char_at(display, y, x);
	 if ((c & 0xe0) == 0x20) {	/* ATTRIBUTE */
	    a = (c & 0xff);
	    temp_attr = This->data->attrs;
	    slang_terminal_set_attrs (This, attribute_map[0]);
	    SLsmg_write_char (' ');
	    slang_terminal_set_attrs (This, temp_attr);
	 } else {		/* DATA */
	    curs_attr = attribute_map[a - 0x20];
	    if (curs_attr == 0x00) {	/* NONDISPLAY */
	       temp_attr = This->data->attrs;
	       slang_terminal_set_attrs (This, attribute_map[0]);
	       SLsmg_write_char (' ');
	       slang_terminal_set_attrs (This, temp_attr);
	    } else {
	       c = tn5250_char_map_to_local (tn5250_display_char_map (display), c);
	       if ((c < 0x20 && c > 0x00) || c >= 0x7f) { /* UNPRINTABLE */
		  c = ' ';
		  curs_attr ^= A_REVERSE;
	       }
	       if ((curs_attr & A_VERTICAL) != 0) {
		  curs_attr |= A_UNDERLINE;
		  curs_attr &= ~A_VERTICAL;
	       }
	       /* This is a kludge since vga hardware doesn't support under-
	        * lining characters.  It's pretty ugly. */
	       if ((curs_attr & A_UNDERLINE) != 0) {
		  curs_attr &= ~A_UNDERLINE;
		  if (c == ' ')
		     c = '_';
	       }
	       slang_terminal_set_attrs (This, curs_attr);
	       SLsmg_write_char (c);
	    }
	 }			/* if ((c & 0xe0) ... */
      }				/* for (int x ... */
   }				/* for (int y ... */

   SLsmg_gotorc (tn5250_display_cursor_y(display), tn5250_display_cursor_x(display));
   SLsmg_refresh();
}

/****i* lib5250/slang_terminal_update_indicators
 * NAME
 *    slang_terminal_update_indicators
 * SYNOPSIS
 *    slang_terminal_update_indicators (This, display);
 * INPUTS
 *    Tn5250Terminal *     This       - 
 *    Tn5250Display *      display    - 
 * DESCRIPTION
 *    DOCUMENT ME!!!
 *****/
static void slang_terminal_update_indicators(Tn5250Terminal * This, Tn5250Display * display)
{
   int inds = tn5250_display_indicators(display);
   char ind_buf[80];

   memset(ind_buf, ' ', sizeof(ind_buf));
   memcpy(ind_buf, "5250", 4);
   if ((inds & TN5250_DISPLAY_IND_MESSAGE_WAITING) != 0) {
      memcpy(ind_buf + 23, "MW", 2);
   }
   if ((inds & TN5250_DISPLAY_IND_INHIBIT) != 0) {
      memcpy(ind_buf + 9, "X II", 4);
   } else if ((inds & TN5250_DISPLAY_IND_X_CLOCK) != 0) {
      memcpy(ind_buf + 9, "X CLOCK", 7);
   } else if ((inds & TN5250_DISPLAY_IND_X_SYSTEM) != 0) {
      memcpy(ind_buf + 9, "X SYSTEM", 8);
   }
   if ((inds & TN5250_DISPLAY_IND_INSERT) != 0) {
      memcpy(ind_buf + 30, "IM", 2);
   }
   if ((inds & TN5250_DISPLAY_IND_MACRO) != 0) {
      memcpy(ind_buf + 54, tn5250_macro_printstate (display), 11);
   }
   SLsmg_normal_video ();
   SLsmg_gotorc (tn5250_display_height (display), 0);
   SLsmg_write_nchars (ind_buf, 80);
   SLsmg_gotorc (tn5250_display_cursor_y(display), tn5250_display_cursor_x(display));
   SLsmg_refresh();
}

/****i* lib5250/slang_terminal_waitevent
 * NAME
 *    slang_terminal_waitevent
 * SYNOPSIS
 *    ret = slang_terminal_waitevent (This);
 * INPUTS
 *    Tn5250Terminal *     This       - 
 * DESCRIPTION
 *    DOCUMENT ME!!!
 *****/
static int slang_terminal_waitevent(Tn5250Terminal * This)
{
#if !defined(WIN32) && !defined(WINE)
   fd_set fdr;
   int result = 0;
   int sm;

   if (SLang_Error == USER_BREAK)
      This->data->quit_flag = 1;
   if (This->data->quit_flag)
      return TN5250_TERMINAL_EVENT_QUIT;

   FD_ZERO(&fdr);
   FD_SET(0, &fdr);
   sm = 1;
   if (This->conn_fd >= 0) {
      FD_SET(This->conn_fd, &fdr);
      sm = This->conn_fd + 1;
   }

   select(sm, &fdr, NULL, NULL, NULL);

   if (FD_ISSET(0, &fdr))
      result |= TN5250_TERMINAL_EVENT_KEY;

   if (This->conn_fd >= 0 && FD_ISSET(This->conn_fd, &fdr))
      result |= TN5250_TERMINAL_EVENT_DATA;

   return result;
#else
   /* XXX: WIN32/WINE - need to do this using WaitForMultipleObjects */
#endif
}

/****i* lib5250/slang_terminal_getkey
 * NAME
 *    slang_terminal_getkey
 * SYNOPSIS
 *    ret = slang_terminal_getkey (This);
 * INPUTS
 *    Tn5250Terminal *     This       - 
 * DESCRIPTION
 *    DOCUMENT ME!!!
 *****/
static int slang_terminal_getkey(Tn5250Terminal * This)
{
   unsigned int key;

   if (!SLang_input_pending (0))
      return -1;

   key = SLkp_getkey ();
   while (1) {
      switch (key) {
      case 0x0d:
      case 0x0a:
	 return K_ENTER;

      case 0x1b:
	 if ((key = slang_terminal_get_esc_key(This, 1)) != SL_KEY_ERR)
	    return key;
	 break;

      case K_CTRL('A'):
	 return K_ATTENTION;
      case K_CTRL('B'):
	 return K_ROLLDN;
      case K_CTRL('C'):
	 return K_SYSREQ;
      case K_CTRL('D'):
	 return K_ROLLUP;
      case K_CTRL('E'):
	 return K_ERASE;
      case K_CTRL('F'):
	 return K_ROLLUP;
      case K_CTRL('K'):
	 return K_FIELDEXIT;
      case K_CTRL('L'):
	 return K_REFRESH;
      case K_CTRL('O'):
	 return K_HOME;
      case K_CTRL('P'):
	 return K_PRINT;
      case K_CTRL('R'):
	 return K_RESET;	/* Error Reset */
      case K_CTRL('S'):
	 return K_MEMO;
      case K_CTRL('T'):
	 return K_TESTREQ;
      case K_CTRL('U'):
	 return K_ROLLDN;
      case K_CTRL('W'):
	 return K_EXEC;
      case K_CTRL('X'):
	 return K_FIELDEXIT;

      case K_CTRL('Q'):
	 This->data->quit_flag = 1;
	 return -1;

      case K_CTRL('G'):	/* C-g <function-key-shortcut> */
	 if ((key = slang_terminal_get_esc_key(This, 0)) != SL_KEY_ERR)
	    return key;
	 break;

      case SL_KEY_ERR:
	 if (SLang_Error == USER_BREAK)
	    This->data->quit_flag = 1;
	 return -1;

      case SL_KEY_DELETE:
	 return K_DELETE;

      case SL_KEY_F(1):
	 return K_F1;
      case SL_KEY_F(2):
	 return K_F2;
      case SL_KEY_F(3):
	 return K_F3;
      case SL_KEY_F(4):
	 return K_F4;
      case SL_KEY_F(5):
	 return K_F5;
      case SL_KEY_F(6):
	 return K_F6;
      case SL_KEY_F(7):
	 return K_F7;
      case SL_KEY_F(8):
	 return K_F8;
      case SL_KEY_F(9):
	 return K_F9;
      case SL_KEY_F(10):
	 return K_F10;
      case SL_KEY_F(11):
	 return K_F11;
      case SL_KEY_F(12):
	 return K_F12;
      case SL_KEY_F(13):
	 return K_F13;
      case SL_KEY_F(14):
	 return K_F14;
      case SL_KEY_F(15):
	 return K_F15;
      case SL_KEY_F(16):
	 return K_F16;
      case SL_KEY_F(17):
	 return K_F17;
      case SL_KEY_F(18):
	 return K_F18;
      case SL_KEY_F(19):
	 return K_F19;
      case SL_KEY_F(20):
	 return K_F20;
      case SL_KEY_F(21):
	 return K_F21;
      case SL_KEY_F(22):
	 return K_F22;
      case SL_KEY_F(23):
	 return K_F23;
      case SL_KEY_F(24):
	 return K_F24;
      case SL_KEY_BACKSPACE:
	 return K_BACKSPACE;
      case SL_KEY_IC:
	 return K_INSERT;

      case SL_KEY_HOME:
      case SL_KEY_A1:
	 return K_HOME;

      case SL_KEY_PPAGE:
      case SL_KEY_A3:
	 return K_ROLLDN;

      case SL_KEY_END:
      case SL_KEY_C1:
	 return K_END;

      case SL_KEY_NPAGE:
      case SL_KEY_C3:
	 return K_ROLLUP;

      case SL_KEY_ENTER:
	 return K_FIELDEXIT;

      case SL_KEY_UP:
	 return K_UP;

      case SL_KEY_DOWN:
	 return K_DOWN;

      case SL_KEY_LEFT:
	 return K_LEFT;

      case SL_KEY_RIGHT:
	 return K_RIGHT;

      default:
	 return key;
      }
   }
}

/****i* lib5250/slang_terminal_beep
 * NAME
 *    slang_terminal_beep
 * SYNOPSIS
 *    slang_terminal_beep (This);
 * INPUTS
 *    Tn5250Terminal *     This       - 
 * DESCRIPTION
 *    DOCUMENT ME!!!
 *****/
static void slang_terminal_beep (Tn5250Terminal * This)
{
   SLtt_beep ();
}


/***** lib5250/slang_terminal_enhanced
 * NAME
 *    slang_terminal_enhanced
 * SYNOPSIS
 *    ret = slang_terminal_enhanced (This);
 * INPUTS
 *    Tn5250Terminal  *    This       - 
 * DESCRIPTION
 *    Return 1 if we support the enhanced 5250 protocol, 0 otherwise.
 *****/
static int
slang_terminal_enhanced (Tn5250Terminal * This)
{
  return (0);
}


/****i* lib5250/slang_terminal_get_esc_key
 * NAME
 *    slang_terminal_get_esc_key
 * SYNOPSIS
 *    ret = slang_terminal_get_esc_key (This, is_esc);
 * INPUTS
 *    Tn5250Terminal *     This       - 
 *    int                  is_esc     - 
 * DESCRIPTION
 *    If a vt100 escape key sequence was introduced (using either
 *    <Esc> or <Ctrl+g>), handle the next key in the sequence.
 *****/
static int slang_terminal_get_esc_key(Tn5250Terminal * This, int is_esc)
{
   int y, x, key, display_key;

   y = SLsmg_get_row ();
   x = SLsmg_get_column ();
   SLsmg_normal_video ();
   SLsmg_gotorc (This->data->last_height, 60);
   if (is_esc)
      SLsmg_write_string ("Esc ");
   else
      SLsmg_write_string ("C-g ");
   SLsmg_gotorc (y, x);
   SLsmg_refresh();

#if !defined(WIN32) && !defined(WINE)
   {
      fd_set fdr;
      FD_ZERO(&fdr);
      FD_SET(0, &fdr);
      select(1, &fdr, NULL, NULL, NULL);
   }
#else
   /* XXX: What do we need that for? */
#endif
   key = SLkp_getkey ();

   if (isalpha(key))
      key = toupper(key);

   display_key = key;
   switch (key) {

      /* Function keys */
   case '1':
      key = K_F1;
      break;
   case '2':
      key = K_F2;
      break;
   case '3':
      key = K_F3;
      break;
   case '4':
      key = K_F4;
      break;
   case '5':
      key = K_F5;
      break;
   case '6':
      key = K_F6;
      break;
   case '7':
      key = K_F7;
      break;
   case '8':
      key = K_F8;
      break;
   case '9':
      key = K_F9;
      break;
   case '0':
      key = K_F10;
      break;
   case '-':
      key = K_F11;
      break;
   case '=':
      key = K_F12;
      break;
   case '!':
      key = K_F13;
      break;
   case '@':
      key = K_F14;
      break;
   case '#':
      key = K_F15;
      break;
   case '$':
      key = K_F16;
      break;
   case '%':
      key = K_F17;
      break;
   case '^':
      key = K_F18;
      break;
   case '&':
      key = K_F19;
      break;
   case '*':
      key = K_F20;
      break;
   case '(':
      key = K_F21;
      break;
   case ')':
      key = K_F22;
      break;
   case '_':
      key = K_F23;
      break;
   case '+':
      key = K_F24;
      break;

      /* AS/400 strangeness */
   case 'A':
      key = K_ATTENTION;
      break;
   case 'C':
      key = K_CLEAR;
      break;
   case 'D':
      key = K_DUPLICATE;
      break;
   case 'H':
      key = K_HELP;
      break;
   case 'I':
      key = K_INSERT;
      break;
   case 'L':
      key = K_REFRESH;
      break;
   case 'M':
      key = K_FIELDMINUS;
      break;
   case 'P':
      key = K_PRINT;
      break;
   case 'R':
      key = K_RESET;
      break;
   case 'S':
      key = K_SYSREQ;
      break;
   case 'T':
      key = K_TOGGLE;
      break;
   case 'X':
      key = K_FIELDEXIT;
      break;

   case 127:
      key = K_INSERT;
      break;			/* ESC DEL */
   case SL_KEY_DELETE:
      key = K_INSERT;
      break;			/* ESC DEL, also */
   case K_CTRL('J'):
      key = K_NEWLINE;
      break;

   case 'Q':
      This->data->quit_flag = 1;
      key = SL_KEY_ERR;
      break;

   default:
      SLtt_beep();
      key = SL_KEY_ERR;
      break;
   }

   SLsmg_gotorc (This->data->last_height, 64);
   if (key == SL_KEY_ERR)
      SLsmg_write_string ("???");
   else
      SLsmg_write_char (display_key);
   SLsmg_gotorc (y, x);
   SLsmg_refresh ();
   return key;
}

/****i* lib5250/slang_terminal_set_attrs
 * NAME
 *    slang_terminal_set_attrs
 * SYNOPSIS
 *    slang_terminal_set_attrs (This, attrs);
 * INPUTS
 *    Tn5250Terminal *     This       - 
 *    int                  attrs      - 
 * DESCRIPTION
 *    DOCUMENT ME!!!
 *****/
static void slang_terminal_set_attrs (Tn5250Terminal * This, int attrs)
{
   if (attrs == This->data->attrs)
      return;
   SLsmg_normal_video ();
   SLsmg_set_color ((attrs & A_COLOR_MASK) >> 8);
   if ((attrs & A_REVERSE) != 0)
      SLsmg_reverse_video ();
   /* FIXME: Handle A_BLINK */
   This->data->attrs = attrs;
}

#else /* USE_SLANG */

/* When compiled with -Wall -pedantic: ANSI C forbids empty source file. */
struct NoSlang {
   long dummy;
};

#endif /* USE_SLANG */

/* vi:set cindent sts=3 sw=3: */


syntax highlighted by Code2HTML, v. 0.9.1