/** 
 * --	terminal driver fo djgpp
 *
 *  Copyright (C) Tektronix, Inc. 1998 - 2001. All rights reserved.
 *
 *  @see     GNU LGPL
 *  @author  Tektronix CTE             @(#) %derived_by: guidod %
 *  @version %version: 5.5 %
 *    (%date_modified: Mon Mar 12 10:32:53 2001 %) 
 *
 *  @description
 *                      Terminal driver for DOS and OS/2 with DJGPP,
 *			there is almost nothing to do.
 *
 * Adapted from term-emx.c by Antonio Costa (acc@asterix.inescn.pt)
 * Works in 25 and 50 lines text modes (at least).
 */
/*@{*/
#if defined(__version_control__) && defined(__GNUC__)
static char* id __attribute__((unused)) = 
"@(#) $Id: %full_filespec: term-dj.c~5.5:csrc:bln_12xx!5 % $";
#endif

#define _P4_SOURCE 1

#include <pfe/incl-sub.h>
#include <pfe/term-sub.h>

#include <pc.h>
#include <ctype.h>

char *
term_dj_rawkey_string [P4_NUM_KEYS] =	/* what function keys send */
{
    "\377;", "\377<", "\377=", "\377>", "\377?",
    "\377@", "\377A", "\377B", "\377C", "\377D",
    "\377K", "\377M", "\377H", "\377P",
    "\377G", "\377O", "\377Q", "\377I",
    NULL,	   "\377S", NULL,    "\377R",
    NULL,    NULL,    NULL,    NULL,    /*"\r"*/
};
static int c_interrupt_key (char ch)		{ return 0; }
static void c_interactive_terminal (void)	{}
static void c_system_terminal (void)		{}
static void c_query_winsize (void)		{}
static int
c_prepare_terminal (void)
{
    setbuf (stdout, NULL);
    PFE.cols = ScreenCols ();
    PFE.rows = ScreenRows ();
    return 1;
}
static void
c_cleanup_terminal (void)
{
    return; /* nothing to do here */
}
static int
c_keypressed (void)
{
    return kbhit ();
}

#undef getkey

static int nextkey = 0;

static int newgetkey (void)
{
    int key;
    
    if (nextkey)
    {
        key = nextkey;
        nextkey = 0;
        return key;
    }
    key = getkey ();
    if (key > 255)
    {
        nextkey = key & 255;
        return 255;
    }
    return key;
}

#define BLINK        0x0080
#define INTENSITY    0x0008
#define BW_NORMAL    0x0007
#define BW_UNDERLINE 0x0004
static int attribs = BW_NORMAL;

#if 1
static void
c_putc (char c)
{
    int row, col;
    
    if (attribs == BW_NORMAL || iscntrl(c))
    {
        putchar (c);
        return;
    }
    ScreenGetCursor (&row, &col);
    ScreenPutChar (c, attribs, col, row);
    ScreenSetCursor (row, col + 1);
}
static void
c_puts (const char *s)
{ 
    int i;
    
    if (attribs == BW_NORMAL)
    {
        fputs (s, stdout);
        return;
    }
    for (i = 0; s[i]; i++)
        c_putc(s[i]);
}
#else
static void c_putc (char c)		{ putchar (c); }
static void c_puts (const char *s)	{ fputs (s, stdout); }
#endif

static void c_gotoxy (int x, int y)	{ ScreenSetCursor (y, x); }
static void c_wherexy (int *x, int *y)	{ ScreenGetCursor (y, x); }
static void _addxy (int x, int y)
{
    int col, row;
    
    ScreenGetCursor (&row, &col);
    ScreenSetCursor (row + y, col + x);
}
static void _clrscr (void)	{ ScreenClear (); ScreenSetCursor (0, 0); }
static void _home (void)	{ ScreenSetCursor (0, 0); }
static void _clreol (void)
{
    int i, col;
    
    ScreenGetCursor (&i, &col);
    for (i = col; i < PFE.cols; i++)
        putchar (' ');
}
static void _clrdown (void)
{
    int i, row, col;
    
    ScreenGetCursor (&row, &col);
    clreol ();
    for (i = row + 1; i < PFE.rows; i++)
    {
        gotoxy (0, i);
        clreol ();
    }
    gotoxy (col, row);
}
static int c_tput (int attr)
{
    switch (attr)
    {
     case P4_TERM_GOLEFT:	_addxy (-1,  0); break;
     case P4_TERM_GORIGHT:	_addxy ( 1,  0); break;
     case P4_TERM_GOUP:		_addxy ( 0, -1); break;
     case P4_TERM_GODOWN:	_addxy ( 0,  1); break;
         
     case P4_TERM_CLRSCR:	_clrscr (); break;
     case P4_TERM_HOME:		_home (); break;
     case P4_TERM_CLREOL:	_clreol (); break;
     case P4_TERM_CLRDOWN:	_clrdown (); break;

     case P4_TERM_BELL:		putchar ('\a'); break;
         
     case P4_TERM_NORMAL:	attribs = BW_NORMAL; break;
     case P4_TERM_BOLD_ON:	attribs |= INTENSITY; break;
     case P4_TERM_BOLD_OFF:	attribs &= ~INTENSITY; break;
     case P4_TERM_BRIGHT:	standout_on (); break;
     case P4_TERM_REVERSE:	attribs = ((attribs & 0x0007) << 4) |
					    (attribs & 0x0088); break;
     case P4_TERM_BLINKING:	attribs |= BLINK; break;
     case P4_TERM_UNDERLINE_ON:	attribs = (attribs&0x00F8) | BW_UNDERLINE; 
         break;
     case P4_TERM_UNDERLINE_OFF: attribs = BW_NORMAL; break;
     default: break;
    }
}

#ifdef __GNUC__
#define INTO(x) .x =
#else
#define INTO(x)
#endif

p4_term_struct p4_term_ios =
{
    "term-dj",
    0, term_dj_rawkey_string,
    INTO(init) 		c_prepare_terminal, 
    INTO(fini) 		c_cleanup_terminal,
    INTO(tput)		c_tput,

    INTO(tty_interrupt_key) c_interrupt_key,
    INTO(interactive_terminal) c_interactive_terminal,
    INTO(system_terminal)   c_system_termainl,
    INTO(query_winsize)     c_query_winsize,
    
    INTO(c_keypressed)	c_keypressed,
    INTO(c_getkey)	c_getkey,
    INTO(c_putc_noflush)  c_putc_noflush,
    INTO(c_put_flush)	c_put_flush,
    INTO(c_putc)		c_putc,
    INTO(c_puts)		c_puts,
    INTO(c_gotoxy)	c_gotoxy,
    INTO(c_wherexy)	c_wherexy
};
/*@}*/