           Borland Conio Functions For Other PC C Compilers


Borland's range of C compilers include various useful, but non-
standard functions which find their way into numerous source code 
listings and C libraries. The functions below should compile with any 
PC C compiler, and enable you to make use of C libraries which require 
these functions and also use source listings which make use of them.

There is no guarrantee that the functionality of these functions is 
identical to the Borland equivalents, these functions are intended to 
behave as closely as possible to the originals without being a rip-off 
of Borland's copyrighted source code.



/*
    Reproduce Borland's window() conio functionality
    for other PC C compilers

    This doesn't provide all the conio functions, just
    the common ones such as window(), clrscr(), cprintf(),
    textcolor(), textattr(), textbackground(), gotoxy(),
    wherex(), wherey(), clreol(), gettextinfo(), lowvideo(),
    hivideo(), normvideo()

*/

#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <stdarg.h>

struct text_info
{
    unsigned char winleft;
    unsigned char wintop;
    unsigned char winright;
    unsigned char winbottom;
    unsigned char attribute;
    unsigned char normattr;
    unsigned char currmode;
    unsigned char screenheight;
    unsigned char screenwidth;
    unsigned char curx;
    unsigned char cury;
};


enum COLORS
{
    BLACK,          /* dark colors */
    BLUE,
    GREEN,
    CYAN,
    RED,
    MAGENTA,
    BROWN,
    LIGHTGRAY,
    DARKGRAY,       /* light colors */
    LIGHTBLUE,
    LIGHTGREEN,
    LIGHTCYAN,
    LIGHTRED,
    LIGHTMAGENTA,
    YELLOW,
    WHITE
};

#define BLINK    128

static struct text_info _text_info;


void cprintf(char *, ...);
void normvideo(void);
static void _win_ok(void);
static void _win_up(void);

static void _at(int row, int col)
{
    /* Position text cursor on current screen */

    union REGS regs;

    regs.h.bh = 0;
    regs.h.dh = row;
    regs.h.dl = col;
    regs.h.ah = 2;
    int86(0x10,&regs,&regs);
}

void gotoxy(int col, int row)
{
    /* Position text cursor in window */

    row = row % (_text_info.winbottom - _text_info.wintop + 2);

    if (row == 0)
        row = 1;

    col = col % (_text_info.winright - _text_info.winleft + 2);

    if (col == 0)
        col = 1;

    _text_info.curx = col;
    _text_info.cury = row;
}

int wherex()
{
    /* Return text cursor x coord in window */

    return _text_info.curx;
}

int wherey()
{
    /* Return text cursor y coord in window */

    return _text_info.cury;
}

void gettextinfo(struct text_info *ti)
{
    ti->winleft = _text_info.winleft;
    ti->wintop = _text_info.wintop;
    ti->winright = _text_info.winright;
    ti->winbottom = _text_info.winbottom;
    ti->attribute = _text_info.attribute;
    ti->normattr = _text_info.normattr;
    ti->currmode = _text_info.currmode;
    ti->screenheight = _text_info.screenheight;
    ti->screenwidth = _text_info.screenwidth;
    ti->curx = _text_info.curx;
    ti->cury = _text_info.cury;
}


void window(int left, int top, int right, int bottom)
{
    static int first = 1;

    if (first)
    {
        normvideo();
        first = 0;
    }
    _text_info.winleft = left;
    _text_info.wintop = top;
    _text_info.winright = right;
    _text_info.winbottom = bottom;
    _text_info.curx = 1;
    _text_info.cury = 1;
}

void clreol()
{
    /* Clear to end of current line */
    union REGS regs;

    regs.h.bh = (unsigned char)0;
    regs.h.bl = _text_info.attribute;
    regs.x.cx = _text_info.winright - _text_info.winleft - _text_info.curx;
    regs.h.ah = (unsigned char)0x09;
    regs.h.al = 32;
    int86(0x10, &regs, &regs);
}

void textattr(int newattr)
{
    _text_info.attribute = newattr;
}

void textbackground(int newcolor)
{
    /*
        Set background to 0
    */
    _text_info.attribute &= 207;

    /*
        Set background bit pair
    */
    _text_info.attribute |= (newcolor << 4);
}

void textcolor(int newcolor)
{
    _text_info.attribute &= 48;

    /*
        Set forgeround bits pair
    */
    _text_info.attribute |= newcolor;
}

void lowvideo(void)
{
    _text_info.attribute &= 191;
}

void hivideo(void)
{
    _text_info.attribute |= 64;
}

void normvideo(void)
{
    _text_info.attribute = 7;
}

void clrscr(void)
{
    /*
        Clear window, setting attributes
    */
    union REGS regs;

    regs.h.al = 60;
    regs.h.cl = _text_info.winleft - 1;
    regs.h.ch = _text_info.wintop - 1;
    regs.h.dl = _text_info.winright - 1;
    regs.h.dh = _text_info.winbottom - 1;
    regs.h.bh = _text_info.attribute;
    regs.h.ah = 6;
    int86(0x10,&regs,&regs);

    _text_info.curx = 1;
    _text_info.cury = 1;
}

void cprintf(char *format, ...)
{
    /*
        print text to window
        A maximum 8k of output can be coped with by this function
    */

    va_list arg_ptr;
    static char output[8192];
    union REGS regs;
    int n;

    va_start(arg_ptr, format);
    vsprintf(output, format, arg_ptr);

    _win_ok();

    _at(_text_info.wintop + _text_info.cury - 2,_text_info.winleft + 
_text_info.curx - 2); 
    n = 0;

    while (output[n])
    {
        if (output[n] == '\r')
        {
            _text_info.curx = 1;
        }
        else
        if (output[n] == '\n')
        {
            _text_info.cury++;
            _win_ok();
        }
        else
        if (output[n] > 31)
        {
            regs.h.bh = (unsigned char)0;
            regs.h.bl = _text_info.attribute;
            regs.x.cx = 0x01;
            regs.h.ah = (unsigned char)0x09;
            regs.h.al = (unsigned char)output[n];
            int86(0x10, &regs, &regs);

            _text_info.curx++;

            _win_ok();
        }
        n++;
        _at(_text_info.wintop + _text_info.cury - 2,_text_info.winleft 
+ _text_info.curx - 2); 
    }
}

static void _win_ok()
{
    if (_text_info.winleft + _text_info.curx > _text_info.winright)
    {
        _text_info.curx = 1;
        _text_info.cury++;
    }

    if (_text_info.wintop + _text_info.cury - 1 > _text_info.winbottom)
    {
        _text_info.cury--;
        _win_up();
    }
}

static void _win_up()
{
    /* Scroll a text window */
    union REGS regs;

    regs.h.al = 1;
    regs.h.cl = _text_info.winleft - 1;
    regs.h.ch = _text_info.wintop - 1;
    regs.h.dl = _text_info.winright - 1;
    regs.h.dh = _text_info.winbottom - 1;
    regs.h.bh = _text_info.attribute;
    regs.h.ah = 6;
    int86(0x10,&regs,&regs);
}


