SCRNIO.C - Version 1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>

/* Anywhere the WIN32 define is tested, indicates an area that
** provides portability between 16-bit DOS and Win32 consoles.
**
** Since this is the screen IO module, and ANSI C does not support
** Color, non-buffered input, this module calls mostly non-ANSI, Intel-specific
** functions.
*/
#include "myio.h"

#ifdef WIN32
static HANDLE hStdOut;
static COORD Coord;
static DWORD Written;
static CONSOLE_CURSOR_INFO CursorInfo;
static WORD ScreenBuffer[80*25];
/* Init - Initializes console data for a Win32 program (removed for DOS) */
void Init(void)
{
	if( !hStdOut )
	{
		if( (hStdOut=GetStdHandle(STD_OUTPUT_HANDLE)) ==  INVALID_HANDLE_VALUE)
		{
			perror( "Error initializing console");
			exit(1);
		}
		GetConsoleCursorInfo( hStdOut, &CursorInfo ); 
	}
}
#endif

/* CPrintChar - Prints character 'Char', in color 'Color' */
void CPrintChar( int Char, int Color )
{
#ifdef WIN32
	if( !hStdOut) 
		Init();
	if( Char=='\b' )
	{
		if( Coord.X--==0 ) /* Move Cursor */
		{
			Coord.X=79;
			if( Coord.Y--==0 )
				Coord.Y=0;
		}
		SetConsoleCursorPosition( hStdOut, Coord );
		return;
	}
	CursorOn();
	WriteConsoleOutputAttribute( hStdOut, (CONST WORD*)&Color, 1, Coord, &Written );
	WriteConsoleOutputCharacter( hStdOut, (char*)&Char,  1, Coord, &Written );
	if( Coord.X++==79 ) /* Move Cursor */
	{
		Coord.X=0;
		if( Coord.Y++==25 )
			Coord.Y=0;
	}
	SetConsoleCursorPosition( hStdOut, Coord );
#else
	union REGS Regin;
	Regin.h.al=(unsigned char )Char;
	if( Regin.h.al >= ' ' ) /* Don't print TAB or ENTER (or anything <' ') */
	{                       /* in color, it displays odd characters        */
		Regin.h.ah=9; /* 9 = Print Character and Attribute */
		Regin.h.bh=0;
		Regin.h.bl=(unsigned char)Color;
		Regin.x.cx=1;
		int86( 0x10, &Regin, &Regin );
	}
	Regin.h.ah=0x0e; /* E = Print character (w/o Color), and move cursor */
	int86( 0x10, &Regin, &Regin );
#endif
}

/* CPrintStr - Prints string 'Str', in color 'Color' */
void CPrintStr( char *Str, int Color )
{
	while( *Str )
		CPrintChar( *Str++, Color );
}

/* Locate - Moves cursor to screen coordinate Row, Col */
void Locate( int Row, int Col )
{
#ifdef WIN32
	Coord.X=(SHORT)Col;
	Coord.Y=(SHORT)Row;
	if( !hStdOut) 
		Init();
	SetConsoleCursorPosition( hStdOut, Coord );
#else
	union REGS Regin;
	Regin.h.ah=2; /* 2 = Set Cursor location */
	Regin.h.bh=0;
	Regin.h.dh=(unsigned char) Row;
	Regin.h.dl=(unsigned char) Col;
	int86( 0x10, &Regin, &Regin );
#endif
}

/* GetLocation - Gets current cursor location, and stores it to Row and Col */
void GetLocation( int *Row, int *Col )
{
#ifdef WIN32
	*Row = Coord.Y;
	*Col = Coord.X;
#else
	union REGS Regin;
	Regin.h.ah=3; /* 3 = Get Cursor location */
	Regin.h.bh=0;
	int86( 0x10, &Regin, &Regin );
	*Row = (int)Regin.h.dh;
	*Col = (int)Regin.h.dl;
#endif
}

/* Cls - Clears the screen to the specified 'Color' value */
void Cls( int Color )
{
#ifdef WIN32
	int i;
	short Clr=(short)Color;
	Init();
	Locate(0,0);
	for( i=0; i<80*25; i++ )
		ScreenBuffer[i]=Clr;
	WriteConsoleOutputAttribute( hStdOut, ScreenBuffer, 80*25, Coord, &Written );
	memset( ScreenBuffer, ' ', 80*25);
	WriteConsoleOutputCharacter( hStdOut, (char*)ScreenBuffer,  80*25, Coord, &Written );
#else
	union REGS Regin;
	Regin.h.ah=6;  /* 6 = Scroll window up (clear window) */
	Regin.h.al=0;
	Regin.h.bh=(unsigned char) Color;
	Regin.x.cx=0; /* ch,cl = row, column of upper-left corner */
	Regin.x.dx=0x184F; /* dh,dl = row,column of lower-right corner */
	int86( 0x10, &Regin, &Regin );
	Locate(0,0);
#endif
}

/* ClearRect - Clears out a rectangular region, with a specific color.*/
/* Row, Col - Determine upper left corner of rectangle on screen      */
/* Height, Width - Determine size of rectangle                        */
void ClearRect( int Row, int Col, int Height, int Width, int Color )
{
#ifdef WIN32
	COORD Tmp;
	int i;
	Tmp.X=(SHORT)Col;
	//Row++;
	Height=Height+1;
	Width=Width+1;
	while( Height-- )
	{
		Tmp.Y = (SHORT) (Row+Height);
		for( i=0; i <Width; i++ )
			ScreenBuffer[i]=(short)Color;
		WriteConsoleOutputAttribute( hStdOut, ScreenBuffer, Width, Tmp, &Written );
		memset( ScreenBuffer, ' ', Width );
		WriteConsoleOutputCharacter( hStdOut, (char*)ScreenBuffer,  Width, Tmp, &Written );
	}
#else
	union REGS Regin;
	Regin.h.ah=6;
	Regin.h.al=0;
	Regin.h.bl=0;
	Regin.h.bh=(unsigned char)Color;
	Regin.h.ch=Row;
	Regin.h.cl=Col;
	Regin.h.dh=Row+Height;
	Regin.h.dl=Col+Width;
	int86( 0x10, &Regin, &Regin );
#endif
}

/* Trim - Removes trailing whitespace from 'Str' */
void Trim( char *Str )
{
	char *End;
	for( End=Str+strlen(Str)-1; End >= Str && *End<=' '; End--)
		*End = '\0';
}

/* GetKey - Inputs keys, including function keys.  Returns their value */
/*  Note: For normal keys, the value is their ASCII code.  For special */
/* Keys like F1, Home, etc, the return value is their scan code (see   */
/* .h file)                                                            */
int GetKey( void )
{
	int i;
	if( (i=getch())==0  || (i==0xE0) )
		i=getch()*0x100; /* For 'special' keys. */
	return(i);
}

/* GetStr - Inputs a string, with field-like editing ability        */
/*  Dest - Where to store result                                    */
/*  Len - Maximum length to input                                   */
/*  EColor - Edit Color.  Editing takes place in this color         */
/*  RColor - String is re-drawn in this color when edits are done   */
/*  Options - one or more of the following:                         */
/*         GS_INIT = Blank out string before editing                */
/*         GS_UPPR = Users text is converted to uppercase           */
/*  Note: This function will not wipe out previous data for Dest,   */
/*         unlike gets() does.                                      */
int GetStr(char *Dest, int Len, int EColor, int RColor, int Options)
{
	int CurPos, Row, Col, Ch;
	if( Options & GS_INIT )	/* Option Setting: Initial Dest to blank string */
		*Dest='\0';
	GetLocation( &Row, &Col ); /* Save starting screen location, needed later*/
	Dest[Len]='\0'; /* Make sure Dest isn't already to long */
	CurPos=strlen( Dest ); /*Make initial starting position the end of the str */
	while( strlen( Dest ) < (unsigned int) Len ) /* Pad right with spaces to Len */
		strcat( Dest, " ");
	CPrintStr( Dest, EColor );
	Locate( Row, Col+CurPos );
	while( (Ch=GetKey())!=ENTER && !IsGetStrExitKey(Ch) )
	{
		if( Ch==BACKSPACE )
		{
			if( CurPos )
			{
				CPrintStr( "\b \b", EColor );
				Dest[--CurPos]=' ';
			}
			continue;
		}
		if( CurPos == Len || IsFuncKey( Ch ) ) /* Ignore Function keys */
			continue;
		if( Options & GS_UPPR ) /* Upper-case only option on? */
			Ch=toupper(Ch);
		CPrintChar( Ch, EColor ); /* Store and Print character */
		Dest[CurPos++]=(char)Ch;
	}
	Locate( Row, Col );
	CPrintStr( Dest, RColor );
	Trim( Dest );	/* Remove those right-side spaces */
	return( Ch ); /* Return character used to terminate input */
}

/* At - Displays string 'Str' in color 'Color, at location Row, Col */
void At( int Row, int Col, char *Str , int Color )
{
	Locate(Row,Col);
	CPrintStr( Str, Color );
}

/* HideCursor - Hides cursor from screen */
void HideCursor()
{
#ifdef WIN32
	CONSOLE_CURSOR_INFO Tmp=CursorInfo;
	if( !hStdOut )
		Init();
	Tmp.bVisible=FALSE;
	SetConsoleCursorInfo( hStdOut, &Tmp );
#else
	Locate(100,0);
#endif
}

/* CursorHidden() - returns true if cursor is invisible, false if not */
int CursorHidden()
{
#ifdef WIN32
	CONSOLE_CURSOR_INFO Tmp;
	GetConsoleCursorInfo( hStdOut, &Tmp); 
	return( !Tmp.bVisible );
#else
	int X, Y;
	GetLocation( &Y, &X );
	return( Y==100 );
#endif
}

#ifdef WIN32
/* CursorOn - Turns the cursor on.  Automatically called by output routines*/
void CursorOn(void)
{
	if( !hStdOut )
		Init();
	SetConsoleCursorInfo( hStdOut, &CursorInfo );
}
#endif