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