/* CONLIB.C - Console library functions from Borland-C for WIN32. */

#include <windows.h>
#include <stdio.h>
#include "vt.h"

static HANDLE hStdout ;
static HANDLE hStdin ;
static CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo ;
static CHAR_INFO ScreenTemp[50*80] ;
static COORD ZeroCoord = { 0,0 } ;
static WORD DefAttr ;
static struct vt_info v = { 0 } ;

int
ConsoleInit(
    void
){
/*
 * this routine is called once during initialization to set up the console
 * library environment.  it makes sure the screen is an 80x25 window.
 */
    DWORD   dwMode ;

    hStdin = GetStdHandle(STD_INPUT_HANDLE) ;
    hStdout = GetStdHandle(STD_OUTPUT_HANDLE) ;
    if (hStdin == INVALID_HANDLE_VALUE || 
        hStdout == INVALID_HANDLE_VALUE) 
        return(0) ;
 
    if (! GetConsoleScreenBufferInfo(hStdout,&ScreenBufferInfo))  {
        return(0) ;
    }
    //
    // turn off line wrap
    //
    GetConsoleMode(hStdout,&dwMode) ;
    dwMode &= ~(ENABLE_WRAP_AT_EOL_OUTPUT) ;
    SetConsoleMode(hStdout,dwMode) ;
    DefAttr = ScreenBufferInfo.wAttributes ;   // set default attributes
}

void
gotoxy(
    int x,
    int y
){
    COORD   CursorPos ;

    CursorPos.X = x-1 ;
    CursorPos.Y = y-1 ;
    SetConsoleCursorPosition(hStdout,CursorPos) ;
}

void
clreol(
    void
){
    DWORD   NumWritten ;

    GetConsoleScreenBufferInfo(hStdout,&ScreenBufferInfo) ;
    FillConsoleOutputAttribute(hStdout,
        FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE,
        ScreenBufferInfo.dwSize.X-ScreenBufferInfo.dwCursorPosition.X+1,
        ScreenBufferInfo.dwCursorPosition,&NumWritten) ;
    FillConsoleOutputCharacter(hStdout,(TCHAR)' ',
        ScreenBufferInfo.dwSize.X-ScreenBufferInfo.dwCursorPosition.X+1,
        ScreenBufferInfo.dwCursorPosition,&NumWritten) ;
}

void
clrbol(
    void
){
    DWORD   NumWritten ;
    COORD   BegLine ;

    GetConsoleScreenBufferInfo(hStdout,&ScreenBufferInfo) ;
    BegLine.X = 0 ;
    BegLine.Y = ScreenBufferInfo.dwCursorPosition.Y ;
    FillConsoleOutputAttribute(hStdout,FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE,
        ScreenBufferInfo.dwCursorPosition.X+1,
        BegLine,&NumWritten) ;
    FillConsoleOutputCharacter(hStdout,(TCHAR)' ',
        ScreenBufferInfo.dwCursorPosition.X+1,
        BegLine,&NumWritten) ;
}

int
gettext(
    int Left,
    int Top,
    int Right,
    int Bottom,
    void *Result
){
    SMALL_RECT  Rect ;
    COORD   DestCoord ;
    int     Len ;
    int     i ;
    PCHAR_INFO p ;
    unsigned short *r = Result ;

    Rect.Left = Left-1 ;
    Rect.Top = Top-1 ;
    Rect.Right = Right-1 ;
    Rect.Bottom = Bottom-1 ;
    DestCoord.X = Right-Left+1 ;
    DestCoord.Y = Bottom-Top+1 ;
    if (!ReadConsoleOutput(hStdout,ScreenTemp,DestCoord,ZeroCoord,&Rect))  {
        return(0) ;
    }
    Len = DestCoord.X*DestCoord.Y ;
    for (i=0,p=ScreenTemp ; i<Len ; i++,p++)  {
        *r++ = p->Char.AsciiChar|(p->Attributes<<8) ;
    }
}

int
puttext(
    int Left,
    int Top,
    int Right,
    int Bottom,
    void *Source
){
    SMALL_RECT  Rect ;
    COORD   DestCoord ;
    int     Len ;
    int     i ;
    PCHAR_INFO p ;
    char    *s = Source ;

    Rect.Left = Left-1 ;
    Rect.Top = Top-1 ;
    Rect.Right = Right-1 ;
    Rect.Bottom = Bottom-1 ;
    DestCoord.X = Right-Left+1 ;
    DestCoord.Y = Bottom-Top+1 ;
    Len = DestCoord.X*DestCoord.Y ;
    for (i=0,p=ScreenTemp ; i<Len ; i++,p++)  {
        p->Char.AsciiChar = *s++ ;
        p->Attributes = *s++ ;
    }
    if (!ReadConsoleOutput(hStdout,ScreenTemp,DestCoord,ZeroCoord,&Rect))  {
        return(0) ;
    }
}

void
textattr(
    int NewAttr
){
    SetConsoleTextAttribute(hStdout,(WORD)NewAttr) ;
}

void
normvideo(
    void
){
    textattr(DefAttr) ;
}

int
wherex(
    void
){
    GetConsoleScreenBufferInfo(hStdout,&ScreenBufferInfo) ;
    return(ScreenBufferInfo.dwCursorPosition.X+1) ;
}

int
wherey(
    void
){
    GetConsoleScreenBufferInfo(hStdout,&ScreenBufferInfo) ;
    return(ScreenBufferInfo.dwCursorPosition.Y+1) ;
}

int
scroll_up(
    int Left,
    int Top,
    int Right,
    int Bottom,
    int Count
){
    COORD   NewOrigin ;
    SMALL_RECT  ScrollRect ;
    SMALL_RECT  ClipRect ;
    CHAR_INFO   Fill ;

    ClipRect.Left = Left-1 ;
    ClipRect.Top = Top-1 ; ;
    ClipRect.Right = Right-1 ;
    ClipRect.Bottom = Bottom-1 ;
    ScrollRect = ClipRect ;
    Fill.Char.AsciiChar = ' ' ;
    Fill.Attributes = DefAttr ;
    NewOrigin.Y = ClipRect.Top-Count ;
    NewOrigin.X = 0 ;
    if (!ScrollConsoleScreenBuffer(
        hStdout,&ScrollRect,&ScrollRect,NewOrigin,&Fill))  {
        return(0) ;
    }
    return(1) ;
}

int
scroll_down(
    int Left,
    int Top,
    int Right,
    int Bottom,
    int Count
){
    COORD   NewOrigin ;
    SMALL_RECT  ScrollRect ;
    SMALL_RECT  ClipRect ;
    CHAR_INFO   Fill ;

    ClipRect.Left = Left-1 ;
    ClipRect.Top = Top-1 ; ;
    ClipRect.Right = Right-1 ;
    ClipRect.Bottom = Bottom-1 ;
    ScrollRect = ClipRect ;
    Fill.Char.AsciiChar = ' ' ;
    Fill.Attributes = DefAttr ;
    NewOrigin.Y = ClipRect.Top+Count ;
    NewOrigin.X = 0 ;
    if (!ScrollConsoleScreenBuffer(
        hStdout,&ScrollRect,&ScrollRect,NewOrigin,&Fill))  {
        return(0) ;
    }
    return(1) ;
}

int
getch(
    void
){
    DWORD   Len ;
    INPUT_RECORD InRec ;

    for (;;)  {
        ReadConsoleInput(hStdin,&InRec,1,&Len) ;
        if (Len == 1)  {
            if (InRec.EventType == KEY_EVENT &&
                InRec.Event.KeyEvent.bKeyDown)  {
                if ((InRec.Event.KeyEvent.uChar.AsciiChar&0xff) != 0)  {
                    return(InRec.Event.KeyEvent.uChar.AsciiChar&0xff) ;
                }
                else  {
                    return(InRec.Event.KeyEvent.wVirtualScanCode<<8) ;
                }
            }
        }
        else  {     /* must be an error */
            return(0) ;
        }
    }
}

int
kbhit(
    void
){
    DWORD   Len ;
    INPUT_RECORD InRec ;

    for (;;)  {
        PeekConsoleInput(hStdin,&InRec,1,&Len) ;
        if (Len == 1)  {
            if (InRec.EventType == KEY_EVENT &&
                InRec.Event.KeyEvent.bKeyDown)  {
                return(TRUE) ;
            }
            ReadConsoleInput(hStdin,&InRec,1,&Len) ;
        }
        else  {
            return(0) ;
        }
    }
}

int
kbready(
    int MilliSeconds
){
// wait for indicated mS, or until an event (of any kind) is ready on stdin.
    WaitForSingleObject(hStdin,MilliSeconds) ;
    return(kbhit()) ;
}

int
tfprintf(
    void    *fp,
    char    *fmt,
    ...
){
    char    Buf[1024] ;

    if (fp == stdout)  {
        vsprintf(Buf,fmt,(char *)&((&fmt)[1])) ;
        vtdecode(&v,Buf,0) ;
    }
    else  {
        vfprintf((FILE *)fp,fmt,(char *)&((&fmt)[1])) ;
    }
    return(1) ;
}

int
my_printf(
    const char *fmt,
    ...
){
    char    Buf[1024] ;

    vsprintf(Buf,fmt,(char *)&((&fmt)[1])) ;
    vtdecode(&v,Buf,0) ;
    return(1) ;
}

void
beep(
    void
){
#if defined(__BORLANDC__)
    sound(1000) ;
    delay(200) ;
    nosound() ;
#endif
#if defined(_CONSOLE)
    Beep(1000,200) ;
#endif
}
