/************************************************************************* * 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 #include #include #include #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 ); } else return ( 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 */ else ii = 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_character Description: Extract a keyboard character - including cursor and function keys. Parameters: None Global Refs: Returns: a 16 bit value that encodes ascii character and scan code Side-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 ***********************************/