/* * gconio.c v0.5 * * A replacement library for Borland C-specific conio.c functions for gcc * and MSVC. * * Implemented functions: clrscr, delay, delline, gotoxy, kader, * lijnh, lijnv, textbackground, textcolor, * getch, getche, setcursortype. * * Implemented MSVC-only functions: wherex, wherey. * * Added functions: get_screen_rows, get_screen_columns * * Warning: The Linux functions in this library rely on ANSI code sequences * _A_LOT_. Output might look weird on non-ANSI-compliant terminals. * * Warning: gotoxy() uses (0, 0) as topleft corner. This is different from * what MSVC users may be used to. * * An updated version of this file can be requested by sending email * to Wence Van der Meersch or * Filip Duyck . * * Copyright (C) 2002-2003 Wence Van der Meersch & Filip Duyck * * The MSVC versions of setcursortype, textcolor and textbackground were * kindly donated by Sebastien Boelpaep . * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * History: * * v0.5: - gconio.h should now be compatible with MSVC! * - Rewrote clrscr, lineh, linev functions to evade ANSI codes. * - Added wherex, wherey, setcursortype functions (MSVC only). * v0.2: - Added getch, getche, strlwr, strupr functions. * - Added aliases for stricmp, strnicmp. * v0.1: - First release. */ #include "gconio.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /**** GLOBAL VARIABLES *********************/ #ifdef __GNUC__ int __gconio_h_ansi_attr = 0; int __gconio_h_ansi_fg = 37; int __gconio_h_ansi_bg = 40; #endif #ifdef WIN32 enum COLORS { BLACK = 0, BLUE = FOREGROUND_BLUE, GREEN = FOREGROUND_GREEN, CYAN = FOREGROUND_GREEN | FOREGROUND_BLUE, RED = FOREGROUND_RED, MAGENTA = FOREGROUND_RED | FOREGROUND_BLUE, BROWN = FOREGROUND_RED | FOREGROUND_GREEN, LIGHTGRAY = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, DARKGRAY = FOREGROUND_INTENSITY, LIGHTBLUE = FOREGROUND_BLUE | FOREGROUND_INTENSITY, LIGHTGREEN = FOREGROUND_GREEN | FOREGROUND_INTENSITY, LIGHTCYAN = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY, LIGHTRED = FOREGROUND_RED | FOREGROUND_INTENSITY, LIGHTMAGENTA = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY, YELLOW = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY, WHITE = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY, }; enum CURSOR { NORMALCURSOR = 0, NOCURSOR = 100, SOLIDCURSOR = 20, }; WORD __gconio_h_ansi_fg = WHITE; WORD __gconio_h_ansi_bg = BLACK << 4; #endif /**** FUNCTIONS ****************************/ void delay (unsigned long milliseconds) { #ifdef __GNUC__ usleep (milliseconds * 1000); #endif #ifdef WIN32 unsigned long tstart, tnow; milliseconds *= CLK_TCK/1000; tstart = clock(); while ((tnow = clock() - tstart) < milliseconds) { } #endif } #ifdef __GNUC__ void flushall (void) { fflush(stdin); fflush(stdout); fflush(stderr); } #endif #ifdef __GNUC__ int getch (void) { int kbdinput; struct termios t_orig, t_new; // We need to change terminal settings so getchar() does't // require a CR at the end. Also disable local echo. tcgetattr(0, &t_orig); t_new = t_orig; t_new.c_lflag &= ~ICANON; t_new.c_lflag &= ~ECHO; t_new.c_lflag &= ~ISIG; t_new.c_cc[VMIN] = 1; t_new.c_cc[VTIME] = 0; tcsetattr(0, TCSANOW, &t_new); // Get actual input kbdinput = getchar(); // Reset terminal settings. tcsetattr(0, TCSANOW, &t_orig); return (kbdinput); } #endif #ifdef __GNUC__ int getche (void) { int kbdinput; kbdinput = getch(); putchar (kbdinput); return (kbdinput); } #endif #ifdef __GNUC__ char *strlwr (char *text) { char *origtext = text; while (*text != '\0') { if ((*text > 64) && (*text < 91)) *text += 32; text++; } return (origtext); } #endif #ifdef __GNUC__ char *strupr (char *text) { char *origtext = text; while (*text != '\0') { if ((*text > 96) && (*text < 123)) *text -= 32; text++; } return (origtext); } #endif #ifdef __GNUC__ int get_win_size (struct winsize *win) { int err = ioctl (1, TIOCGWINSZ, (char *) win); if (err != 0) err = ioctl (0, TIOCGWINSZ, (char *) win); return (err); } #endif int get_screen_columns (void) { #ifdef __GNUC__ #ifdef TIOCGWINSZ struct winsize win; /* In older versions of Solaris, ioctl will fail and set errno to EINVAL when using it in a telnet session. We are not going to support this, as these versions of Solaris (2.1 - 2.3) are barely used anymore, and telnet sessions should not be used. -FD */ if (!get_win_size (&win)) if (win.ws_col > 0) return win.ws_col; #endif if (getenv ("COLUMNS")) return ((unsigned int) atoi (getenv ("COLUMNS"))); return 80; /* return default */ #endif #ifdef WIN32 CONSOLE_SCREEN_BUFFER_INFO conScrBufInfo; if (GetConsoleScreenBufferInfo (GetStdHandle(STD_OUTPUT_HANDLE), &conScrBufInfo)) return ((unsigned int) conScrBufInfo.dwSize.X); else return (80); #endif } int get_screen_rows (void) { #ifdef __GNUC__ #ifdef TIOCGWINSZ struct winsize win; /* In older versions of Solaris, ioctl will fail and set errno to EINVAL when using it in a telnet session. We are not going to support this, as these versions of Solaris (2.1 - 2.3) are barely used anymore, and telnet sessions should not be used. -FD */ if (!get_win_size (&win)) if (win.ws_row > 0) return win.ws_row; #endif if (getenv ("LINES")) return ((unsigned int) atoi(getenv ("LINES"))); return 25; /* return default */ #endif #ifdef WIN32 CONSOLE_SCREEN_BUFFER_INFO conScrBufInfo; if (GetConsoleScreenBufferInfo (GetStdHandle(STD_OUTPUT_HANDLE), &conScrBufInfo)) return ((unsigned int) (conScrBufInfo.srWindow.Bottom - conScrBufInfo.srWindow.Top + 1)); else return (25); #endif } void clrscr (void) { int count; for (count = 0; count < get_screen_rows(); count++) { gotoxy (0, count); delline(); } gotoxy (0,0); } void delline () { #ifdef __GNUC__ printf ("\r\033[K\r"); #endif #ifdef WIN32 int xcount, ycur; ycur = wherey(); gotoxy (0, ycur); for (xcount = 0; xcount < get_screen_columns(); xcount++) putchar (' '); gotoxy (0, ycur); #endif } void gotoxy (int x, int y) { #ifdef __GNUC__ if ( (x <= get_screen_columns()) && (y <= get_screen_rows()) ) printf("\033[%d;%dH", y, x); #endif #ifdef WIN32 COORD cxy = { x, y }; CONSOLE_SCREEN_BUFFER_INFO conScrBufInfo; if (GetConsoleScreenBufferInfo (GetStdHandle(STD_OUTPUT_HANDLE), &conScrBufInfo)) cxy.Y = y + conScrBufInfo.srWindow.Top; SetConsoleCursorPosition (GetStdHandle(STD_OUTPUT_HANDLE), cxy); #endif } void linev (int x, int y, int length, int character) { int count; if ((y + length - 1) <= get_screen_rows()) { gotoxy (x,y); for (count = 0; count < length; count++) { gotoxy (x, y + count); putchar (character); } } } void lineh (int x, int y, int length, int character) { int count; if ((x + length - 1) <= get_screen_columns()) { gotoxy (x,y); for (count = 0; count < length; count++) putchar (character); } } void box (int x, int y, int length, int height, int type) { char charset[10]; if ( (x<0) || (y<0) || (length<0) || (height<0) || ((x+length)>get_screen_columns()) || ((y+height)>get_screen_rows())) return; else { switch (type) { #ifdef __GNUC__ case 1: sprintf (charset, "++++-|"); break; case 2: sprintf (charset, "++++=|"); break; default: sprintf (charset, "++++-|"); break; #endif #ifdef WIN32 case 1: sprintf (charset, "%c%c%c%c%c%c", 218, 192, 191, 217, 196, 179); break; case 2: sprintf (charset, "%c%c%c%c%c%c", 201, 200, 187, 188, 205, 186); break; default: sprintf (charset, "%c%c%c%c%c%c", 218, 192, 191, 217, '-', '|'); #endif } lineh (x, y, length, charset[4]); lineh (x, y + height - 1, length , charset[4]); linev (x, y, height, charset[5]); linev (x + length - 1, y, height, charset[5]); gotoxy (x, y); putchar (charset[0]); gotoxy (x, y + height - 1); putchar (charset[1]); gotoxy (x + length - 1, y); putchar (charset[2]); gotoxy (x + length - 1, y + height - 1); putchar (charset[3]); gotoxy(0, y + height + 2); } } void textcolor (int newcolor) { #ifdef __GNUC__ if (newcolor > 7) { __gconio_h_ansi_attr = 1; newcolor -= 8; } else { __gconio_h_ansi_attr = 0; } switch(newcolor) { case 0: __gconio_h_ansi_fg = 30; break; // black case 1: __gconio_h_ansi_fg = 34; break; // blue case 2: __gconio_h_ansi_fg = 32; break; // green case 3: __gconio_h_ansi_fg = 36; break; // cyan case 4: __gconio_h_ansi_fg = 31; break; // red case 5: __gconio_h_ansi_fg = 35; break; // magenta case 6: __gconio_h_ansi_fg = 33; break; // brown case 7: __gconio_h_ansi_fg = 37; break; // gray } printf ("\033[%d;%d;%dm", __gconio_h_ansi_attr, __gconio_h_ansi_fg, __gconio_h_ansi_bg); #endif #ifdef WIN32 __gconio_h_ansi_fg = newcolor; SetConsoleTextAttribute (GetStdHandle(STD_OUTPUT_HANDLE), (WORD) (__gconio_h_ansi_fg | __gconio_h_ansi_bg)); #endif } void textbackground (int newcolor) { #ifdef __GNUC__ switch(newcolor) { case 0: __gconio_h_ansi_bg = 40; break; case 1: __gconio_h_ansi_bg = 44; break; case 2: __gconio_h_ansi_bg = 42; break; case 3: __gconio_h_ansi_bg = 46; break; case 4: __gconio_h_ansi_bg = 41; break; case 5: __gconio_h_ansi_bg = 45; break; case 6: __gconio_h_ansi_bg = 43; break; case 7: __gconio_h_ansi_bg = 47; break; } printf ("\033[%d;%d;%dm", __gconio_h_ansi_attr, __gconio_h_ansi_fg, __gconio_h_ansi_bg); #endif #ifdef WIN32 __gconio_h_ansi_bg = newcolor << 4; SetConsoleTextAttribute (GetStdHandle(STD_OUTPUT_HANDLE), (WORD) (__gconio_h_ansi_fg | __gconio_h_ansi_bg)); #endif } #ifdef WIN32 int wherex (void) { CONSOLE_SCREEN_BUFFER_INFO conScrBufInfo; GetConsoleScreenBufferInfo (GetStdHandle(STD_OUTPUT_HANDLE), &conScrBufInfo); return conScrBufInfo.dwCursorPosition.X - conScrBufInfo.srWindow.Left; } #endif #ifdef WIN32 int wherey (void) { CONSOLE_SCREEN_BUFFER_INFO conScrBufInfo; GetConsoleScreenBufferInfo (GetStdHandle(STD_OUTPUT_HANDLE), &conScrBufInfo); return conScrBufInfo.dwCursorPosition.Y - conScrBufInfo.srWindow.Top; } #endif void setcursortype (int type) { #ifdef WIN32 CONSOLE_CURSOR_INFO conCursInfo = { type, (type != NOCURSOR) }; SetConsoleCursorInfo (GetStdHandle(STD_OUTPUT_HANDLE), &conCursInfo); #endif #ifdef __GNUC__ // not implemented #endif } #ifdef __cplusplus } #endif /* __cplusplus */