Rev 46 | Blame | Compare with Previous | Last modification | View Log | RSS feed
/************************************************************************** Copyright (C) 1995 Embedded Solutions* All rights reserved** file: src\vduW32.c** purpose: This module contains all the VDU interface routines** This instance of this file implements the functions* in a Win32 platform.** A small number of routines are provided. These can be emulated* on other machines to provide similar functions** A number of general purpose I/O routines are also provided** functions* init_screen - Initialize the screen* cur - Position the cursor on the screen* clearscreen - Clears the vdu screen* beep - Generate a bell character* flush_out - Flush terminal output* getinp - Get one character of input* getnum - Get a number from the operator* getstring - Get and edit a string* getsex - Get a sex type from the operator* getclass - Get a class descriptor* getcountry - Get a country descriptor* getfnc - Get menu selector* getyes - Prompt for YES / NO* to_upper - Convert character to upper case* to_lower - Convert character to lower case* sleep - Wait a bit* printf - Text display routines* putchar - Text display routines* console_clreol - Clear to end of the line* console_prompt - Display a hightlighted prompt** programmer: David Purdie** revision date by reason* 00.0 17/09/2002 DDP Created***************************************************************************/#include <stdio.h>#include <ctype.h>#include <windows.h>#include <wincon.h>#include "consts.h"#include "structs.h"#include "proto.h"/* variables used by the routines */int n_lines; /* Number of lines on the screen */int n_cols;int rubout = '\010'; /* users rubout character */char escape = '\033'; /* Escape character */int abort_flag = FALSE; /* Abort character detected */int fnc_opr; /* Function key pushed */char *force_cmds = NULL; /* Initial commnads */HANDLE h_console; /* Output handle *//*** Prototypes*/int get_kb_character( void );/*----------------------------------------------------------------------------** FUNCTION : set_commands**** DESCRIPTION :****** INPUTS : cptr - Address of commands to execute**** RETURNS : Nothing**** PRECONDITION :**** EXCEPTIONS :**** WARNING :**** SEE ALSO :----------------------------------------------------------------------------*/void set_commands ( char * cptr ){force_cmds = cptr;}/*========================================================================** Initialize the screen** Purpose:* This function is called to Initialize the screen** Parameters:* None** Returns:* Nothing**========================================================================*/void init_screen( void ){/*** Save a handle to the console*/h_console = GetStdHandle(STD_OUTPUT_HANDLE);/*** Operate within a virtual console area of 24 * 80** Ignore the real console area*/n_lines = 24; /* Fix number of lines for export */n_cols = 80; /* Number of cols */}/*========================================================================** Restore screen to normal** Purpose:* This function is called to Restore screen to normal** Parameters:* None** Returns:* Nothing**========================================================================*/void fix_screen( void ) /* Restore screen to normal */{flush_out();}/*========================================================================** Position the cursor on the screen** Purpose:* This function is called to Position the cursor on the screen** Parameters:* x col number* y line number** Returns:* Nothing**========================================================================*/void cur( int x, int y ){COORD cursor;cursor.Y = y;cursor.X = x;SetConsoleCursorPosition ( h_console, cursor );}/*========================================================================** Position the cursor on the screen** Purpose:* This function is called to save the current cursor location* A single level save - for debug** Parameters:* None** Returns:* Nothing**========================================================================*/int save_x,save_y;void save_cur(void){CONSOLE_SCREEN_BUFFER_INFO console_info;/*** Determine the screen size and the current location of the** cursor within the screen*/GetConsoleScreenBufferInfo( h_console, &console_info );save_x = console_info.dwCursorPosition.X;save_y = console_info.dwCursorPosition.Y;}void restore_cur(void){cur( save_x, save_y);}/*========================================================================** Clears the vdu screen** Purpose:* This function is called to Clears the vdu screen* From the Microsoft Web Site** Parameters:* None** Returns:* Nothing**========================================================================*/void clearscreen( void ){COORD coordScreen = { 0, 0 }; /* home for the cursor */DWORD cCharsWritten;CONSOLE_SCREEN_BUFFER_INFO csbi;DWORD dwConSize;/*** Get the number of character cells in the current buffer.*/if( !GetConsoleScreenBufferInfo( h_console, &csbi ))return;dwConSize = csbi.dwSize.X * csbi.dwSize.Y;/*** Fill the entire screen with blanks.*/if( !FillConsoleOutputCharacter( h_console, (TCHAR) ' ',dwConSize, coordScreen, &cCharsWritten ))return;/*** Get the current text attribute.*/if( !GetConsoleScreenBufferInfo( h_console, &csbi ))return;/*** Set the buffer's attributes accordingly.*/if( !FillConsoleOutputAttribute( h_console, csbi.wAttributes,dwConSize, coordScreen, &cCharsWritten ))return;/*** Put the cursor at its home coordinates.*/SetConsoleCursorPosition( h_console, coordScreen );}/*========================================================================** Generate a bell character** Purpose:* This function is called to Generate a bell character** Parameters:* None** Returns:* Nothing**========================================================================*/void beep( void ){putchar( '\007' );}/*========================================================================** Flush terminal output** Purpose:* This function is called to Flush terminal output** Parameters:* None** Returns:* Nothing**========================================================================*/void flush_out( void ){}/*========================================================================** Get one character of input** Purpose:* This function is called to Get one character of input** Parameters:* None** Returns:* Ascii code or internal control code which will be greater than* a byte**========================================================================*/int getinp( void ){/** General input routine* Will intercept function keys and set flags*/int c;if ( force_cmds && *force_cmds ){c = *force_cmds++;}else{c = get_kb_character();}if( c & 0xff ){c = c & 0xff;if( c == '\r' )c = '\n';if( c == ABORT_CHAR || c == ABORT_CHAR_1 ){abort_flag = TRUE;c = ABORT_CHAR;}return ( c ); /* Input is ascii char */}c >>= 8; /* Upper byte */if( c >= 59 && c <= 68 ){fnc_opr = FNC1 + c - 59;return ( 0 );}switch ( c ){case 71: return ( HOME_KEY );case 72: return ( UPARROW );case 75: return ( LEFTARROW );case 77: return ( RIGHTARROW );case 80: return ( DOWNARROW );case 73: return ( PAGE_UP );case 81: return ( PAGE_DOWN );case 79: return ( END_KEY );case 82: return ( INSERT_KEY );case 83: return ( DELETE_KEY );case 15: return ( BACKTAB );}return ( 0 );}/*========================================================================** Get a number from the operator** Purpose:* This function is called to get a number from the operator** This routine will accept numeric data entry from the operator* the routine will limit the operator input to a limited number* of characters. This allowes fixed format input** Parameters:* max_len Max field width allowed* final_buf pointer to the final resting place of the number** Returns:* This routine will return an indication of operator input* 0 - No valid entry* 1 - data entered and transfered to number.**========================================================================*/bool getnum( int max_len, int *final_buf ){char n_buf[30]; /* Convert number here */n_buf[0] = '\0';if ( *final_buf )sprintf( n_buf, "%*.*d", max_len,max_len, *final_buf );if( getstring( max_len, n_buf, Digit ) ){sscanf( n_buf, "%d", final_buf );return ( TRUE );}elsereturn ( FALSE );}/*========================================================================** Get and edit a string** Purpose:* This function is called to Get and edit a string** Parameters:* len Max length of the string* str Address of the string* limit Types of chars allowed** Returns:* Length of the input string**========================================================================*/int getstring( int len, char *str, enum class_enum limit ){char buf[100]; /* Internal edit buffer */int i; /* Current index into buf */int ii; /* Number of characters in buf */int j; /* Loooopy variable */int ch; /* Current input character */( void ) memset( buf, 0, 100 ); /* Init the buffer */( void ) strcpy( buf, str ); /* Copy in the original string */ii = i = strlen( str ); /* i is at the end of the string */printf( "%s", buf ); /* Display the current string *//** This routine assumes that the cursor is at the end of* the string as it is displayed on the screen*/while( !abort_flag ){ch = getinp(); /* Get the next character */if( ch == '\n' || ch == '\t' || fnc_opr || abort_flag )/* RETURN */break; /* Finish the edit */else if( ch == rubout && i ) /* Users rubout character */{i--;putchar( '\010' );for( j = i; j <= ii; j++ )buf[j] = buf[j + 1];printf( "%s ", &buf[i] ); /* Print remainder of the buffer */ii--; /* One less in the buffer */for( j = i; j <= ii; j++ )putchar( '\010' );}else if( ch == DELETE_KEY && i != ii ) /* Delete char under cursor */{for( j = i; j <= ii; j++ )buf[j] = buf[j + 1];printf( "%s ", &buf[i] );ii--;for( j = i; j <= ii; j++ )putchar( '\010' );}else if( ( ch == '\010' || ch == LEFTARROW ) && i ) /* Back-space */{i--;putchar( '\010' );}else if( ch == RIGHTARROW && i < ii ) /* forward */putchar( buf[i++] );else if( ( ii < len ) && ( ( ( limit == Alphanum || limit == AlphnumUpper) && isprint( ch ) ) || ( ( limit == Digit ) && isascii( ch ) && isdigit( ch ) ) || ( ( limit == Alpha ) && isalpha( ch ) ) ) ) /* Insert the char */{if ( limit == AlphnumUpper )ch = toupper(ch);for( j = ii + 1; j > i; j-- )buf[j] = buf[j - 1];buf[i] = ch;ii++;printf( "%s", &buf[i++] ); /* Print remainder of the buffer */for( j = i; j < ii; j++ )putchar( '\010' );}else{beep();}}/** Edit complete - transfer the data to the user*/printf( "%s", &buf[i] ); /* Cursor to end of the buffer */if( !abort_flag )strcpy( str, buf ); /* Copy buffer to the user */elseii = 0;return ( ii ); /* Return length of input */}/*========================================================================** Get a sex type from the operator** Purpose:* This function is called to Get a sex type from the operator** Parameters:* None** Returns:* A sex type* The unknown sex type is used to signal no change in state**========================================================================*/sex_type getsex( void ){sex_type curr = unknown; /* current sex type in display */char c;while( ( c = getinp() ) != ABORT_CHAR ){if( c == '\n' || c == '\t' ){return ( curr );}if( c == 'M' || c == 'm'){printf( "Male \010\010\010\010\010\010" );curr = male;}else if( c == 'F' || c == 'f' ){printf( "Female\010\010\010\010\010\010" );curr = female;}else{beep();}}return ( unknown );}/*========================================================================** Get a class descriptor** Purpose:* This function is called to Get a class descriptor** Parameters:* None** Returns:* An integer which is the index into the config.team_class array**========================================================================*/int getclass( void ){char cc[3]; /* Input character */int i, j; /* One those loopy things */cc[0] = '\0';while( ( j = getstring( 2, cc, AlphnumUpper ) ) != 0 ){/*** Is this a valid class*/if ( (i = lookup_class(cc, NULL)) > 0 )return (i);/*** Invalid** Rubout and try again*/beep();for( i = 0; i < j; i++ )putchar( '\010' );}return ( 0 );}/*========================================================================** Get a country descriptor** Purpose:* This function is called to Get a country descriptor** Parameters:* None** Returns:* An integer which is the index into the config.country_name array.**========================================================================*/int getcountry( void ){char cc[5]; /* Input character */int i, j, k; /* One those loopy things */cc[0] = '\0';while( ( j = getstring( 4, cc, Alphanum ) ) != 0 ){/** Attempt to locate the entered country in the list of defined countries*/for( i = 0; i < MAX_COUNTRY; i++ ){for( k = 0; k <= j; k++ ){if( cc[k] == '\000' )return ( ++i ); /* Found it */if( toupper( cc[k] ) !=toupper( config.country_name[i].abr[k] ) )break;}}beep();for( i = 0; i < j; i++ )putchar( '\010' );}return ( 0 );}/*========================================================================** Get menu selector** Purpose:* This function is called to Get menu selector** This function will accept characters until one in* "list" is encountered. This is returned to the user* RETURN is valid if the first character of the list is not a "*"* it will return the first charcater of the list;* ABORT will return a zero** Parameters:* List A string of valid responses** Returns:* Selected character**========================================================================*/char getfnc( char *list ){char *copylist;char c;char result = 0;copylist = ( *list == '*' ) ? list + 1 : list;while( ( c = getinp() ) != ABORT_CHAR ){c = toupper( c ); /* Get a character */if( strchr( copylist, c ) ){result = c;break;}if( c == '\n' && *list != '*' ){result = *list;break;}beep();}/*** Display the option selected** Not ready for this yet. Looks a bit ugle in a few places*//* if ( result )** putchar(result);*/return ( result );}/*========================================================================** Prompt for YES / NO** Purpose:* This function is called to Prompt for YES / NO** Parameters:* prompt Prompt to display to the user** Returns:* TRUE for Yes, FALSE for No**========================================================================*/bool getyes( char *prompt ){char c;printf( "%s ? ", prompt );c = getfnc( "*YN" );putchar( '\n' );return ( c == 'Y' );}/*========================================================================** Convert character to upper case** Purpose:* This function is called to convert character to upper case** Parameters:* ch Character to convert** Returns:* Converted character**========================================================================*/char to_upper( char ch ){if( islower( ch ) )return ( ch + 'A' - 'a' );return ( ch );}/*========================================================================** Convert character to lower case** Purpose:* This function is called to convert character to lower case** Parameters:* ch Character to convert** Returns:* Converted character**========================================================================*/char to_lower( char ch ){if( isupper( ch ) )return ( ch + 'a' - 'A' );return ( ch );}/*========================================================================** Wait a bit** Purpose:* This function is called to idle and to nothing for a while** Parameters:* t Time to wait** Returns:* Nothing**========================================================================*/void sleep( int t ){Sleep ( t * 1000 );}/*========================================================================** Clear to the end of the current display line** Purpose:* Clears to the end of the line** Parameters:* None** Returns:* Nothing**========================================================================*/void console_clreol( void ){CONSOLE_SCREEN_BUFFER_INFO console_info;DWORD rlen;int ii;int top;/*** Determine the screen size and the current location of the** cursor within the screen*/GetConsoleScreenBufferInfo( h_console, &console_info );/*** Clear all of it*/top = console_info.dwSize.X - console_info.dwCursorPosition.X;for ( ii = 0; ii < top ; ii++ ){WriteConsole( h_console, " ", 1, &rlen, NULL );}cur ( console_info.dwCursorPosition.X, console_info.dwCursorPosition.Y );}/*========================================================================** printf - Text display routines* putchar - Text display routines*** Purpose:* Intercept standard output calls and direct output to the* console.** Parameters: As per standard function definitions* None** Returns:* As per standard function definitions**========================================================================*/int putchar(int cc){printf( "%c", cc );return 1;}// void gross_error_message(void)// {// LPVOID lpMsgBuf;//// FormatMessage(// FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,// NULL,// GetLastError(),// MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language// (LPTSTR) &lpMsgBuf,// 0,// NULL// );//// // Display the string.// MessageBox( NULL, lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION );//// // Free the buffer.// LocalFree( lpMsgBuf );// }int printf( const char *format, ... ){va_list ap;char pp[200];int len;BOOL result;HANDLE h_console;DWORD llen;DWORD rlen;va_start( ap, format );len = vsprintf( pp, format, ap );va_end( ap );llen = len;h_console = GetStdHandle(STD_OUTPUT_HANDLE);result = WriteConsole( h_console, pp, llen, &rlen, NULL );return ( len );}/*========================================================================** Display a prompt character in a highlight** Purpose:* USed to highlight menu entries** Parameters:* None** Returns:* Nothing**========================================================================*/void console_prompt( char prompt ){SetConsoleTextAttribute( h_console, FOREGROUND_GREEN );putchar( prompt );SetConsoleTextAttribute( h_console, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE );}/*------------------------------------------------------------------------------Name: get_kb_characterDescription: Extract a keyboard character - including cursor and functionkeys.Parameters: NoneGlobal Refs:Returns: a 16 bit value that encodes ascii character and scan codeSide-effects:------------------------------------------------------------------------------*/int get_kb_character( void ){HANDLE hConsoleInput;INPUT_RECORD Buffer;DWORD NumberOfEventsRead;hConsoleInput = GetStdHandle(STD_INPUT_HANDLE);/*** Process console events until we get a suitable keystroke event*/FlushFileBuffers( h_console );for (;;){if (ReadConsoleInput( hConsoleInput, &Buffer, 1, &NumberOfEventsRead )){/*** Only want keyboard depression - ignore other events*/if (Buffer.EventType == KEY_EVENT && Buffer.Event.KeyEvent.bKeyDown){/*** Ignore several scan codes** CNTRL, ALT, SHIFT, CAPLOCK*/if (Buffer.Event.KeyEvent.wVirtualScanCode == 0x38 ||Buffer.Event.KeyEvent.wVirtualScanCode == 0x1D ||Buffer.Event.KeyEvent.wVirtualScanCode == 0x2A ||Buffer.Event.KeyEvent.wVirtualScanCode == 0x3A){continue;}return ( (int) (Buffer.Event.KeyEvent.uChar.AsciiChar + (Buffer.Event.KeyEvent.wVirtualScanCode << 8)));}}}}/********************************* EOF ***********************************/