From 6bf4b90c90f15f4ab60833bddf5b5756d1a6b1f6 Mon Sep 17 00:00:00 2001 From: Elizabeth Alexander Hunt Date: Thu, 2 Jul 2026 11:55:17 -0700 Subject: Init --- Homework/cs3460/gameoflife/rlutil.h | 876 ++++++++++++++++++++++++++++++++++++ 1 file changed, 876 insertions(+) create mode 100644 Homework/cs3460/gameoflife/rlutil.h (limited to 'Homework/cs3460/gameoflife/rlutil.h') diff --git a/Homework/cs3460/gameoflife/rlutil.h b/Homework/cs3460/gameoflife/rlutil.h new file mode 100644 index 0000000..2343859 --- /dev/null +++ b/Homework/cs3460/gameoflife/rlutil.h @@ -0,0 +1,876 @@ +#pragma once +/** + * File: rlutil.h + * + * About: Description + * This file provides some useful utilities for console mode + * roguelike game development with C and C++. It is aimed to + * be cross-platform (at least Windows and Linux). + * + * About: Copyright + * (C) 2010 Tapio Vierros + * + * About: Licensing + * See + */ + +/// Define: RLUTIL_USE_ANSI +/// Define this to use ANSI escape sequences also on Windows +/// (defaults to using WinAPI instead). +#if 0 + #define RLUTIL_USE_ANSI +#endif + +/// Define: RLUTIL_STRING_T +/// Define/typedef this to your preference to override rlutil's string type. +/// +/// Defaults to std::string with C++ and char* with C. +#if 0 + #define RLUTIL_STRING_T char* +#endif + +#ifndef RLUTIL_INLINE + #ifdef _MSC_VER + #define RLUTIL_INLINE __inline + #else + #define RLUTIL_INLINE static __inline__ + #endif +#endif + +#ifdef __cplusplus + /// Common C++ headers + #include // for getch() + #include + #include +/// Namespace forward declarations +namespace rlutil +{ + RLUTIL_INLINE void locate(int x, int y); +} +#else + #include // for getch() / printf() + #include // for strlen() +RLUTIL_INLINE void locate(int x, + int y); // Forward declare for C to avoid warnings +#endif // __cplusplus + +#ifdef _WIN32 + #include // for WinAPI and Sleep() + #define _NO_OLDNAMES // for MinGW compatibility + #include // for getch() and kbhit() + #define getch _getch + #define kbhit _kbhit +#else + #include // for getkey() + #include // for kbhit() + #include // for kbhit() + #include // for getch() and kbhit() + #include // for getch(), kbhit() and (u)sleep() + +/// Function: getch +/// Get character without waiting for Return to be pressed. +/// Windows has this in conio.h +RLUTIL_INLINE int getch(void) +{ + // Here be magic. + struct termios oldt, newt; + int ch; + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO); + tcsetattr(STDIN_FILENO, TCSANOW, &newt); + ch = getchar(); + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + return ch; +} + +/// Function: kbhit +/// Determines if keyboard has been hit. +/// Windows has this in conio.h +RLUTIL_INLINE int kbhit(void) +{ + // Here be dragons. + static struct termios oldt, newt; + int cnt = 0; + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO); + newt.c_iflag = 0; // input mode + newt.c_oflag = 0; // output mode + newt.c_cc[VMIN] = 1; // minimum time to wait + newt.c_cc[VTIME] = 1; // minimum characters to wait for + tcsetattr(STDIN_FILENO, TCSANOW, &newt); + ioctl(0, FIONREAD, &cnt); // Read count + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 100; + select(STDIN_FILENO + 1, NULL, NULL, NULL, &tv); // A small time delay + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + return cnt; // Return number of characters +} +#endif // _WIN32 + +#ifndef gotoxy +/// Function: gotoxy +/// Same as . +RLUTIL_INLINE void gotoxy(int x, int y) +{ + #ifdef __cplusplus + rlutil:: + #endif + locate(x, y); +} +#endif // gotoxy + +#ifdef __cplusplus +/// Namespace: rlutil +/// In C++ all functions except , and are arranged +/// under namespace rlutil. That is because some platforms have them defined +/// outside of rlutil. +namespace rlutil +{ +#endif + + /** + * Defs: Internal typedefs and macros + * RLUTIL_STRING_T - String type depending on which one of C or C++ is used + * RLUTIL_PRINT(str) - Printing macro independent of C/C++ + */ + +#ifdef __cplusplus + #ifndef RLUTIL_STRING_T + typedef std::string RLUTIL_STRING_T; + #endif // RLUTIL_STRING_T + + #define RLUTIL_PRINT(st) \ + do \ + { \ + std::cout << st; \ + } while (false) +#else // __cplusplus + #ifndef RLUTIL_STRING_T +typedef const char* RLUTIL_STRING_T; + #endif // RLUTIL_STRING_T + + #define RLUTIL_PRINT(st) printf("%s", st) +#endif // __cplusplus + + /** + * Enums: Color codes + * + * BLACK - Black + * BLUE - Blue + * GREEN - Green + * CYAN - Cyan + * RED - Red + * MAGENTA - Magenta / purple + * BROWN - Brown / dark yellow + * GREY - Grey / dark white + * DARKGREY - Dark grey / light black + * LIGHTBLUE - Light blue + * LIGHTGREEN - Light green + * LIGHTCYAN - Light cyan + * LIGHTRED - Light red + * LIGHTMAGENTA - Light magenta / light purple + * YELLOW - Yellow (bright) + * WHITE - White (bright) + */ + enum + { + BLACK, + BLUE, + GREEN, + CYAN, + RED, + MAGENTA, + BROWN, + GREY, + DARKGREY, + LIGHTBLUE, + LIGHTGREEN, + LIGHTCYAN, + LIGHTRED, + LIGHTMAGENTA, + YELLOW, + WHITE + }; + + /** + * Consts: ANSI escape strings + * + * ANSI_CLS - Clears screen + * ANSI_CONSOLE_TITLE_PRE - Prefix for changing the window title, print the + * window title in between ANSI_CONSOLE_TITLE_POST - Suffix for changing the + * window title, print the window title in between ANSI_ATTRIBUTE_RESET - + * Resets all attributes ANSI_CURSOR_HIDE - Hides the cursor + * ANSI_CURSOR_SHOW - Shows the cursor + * ANSI_CURSOR_HOME - Moves the cursor home (0,0) + * ANSI_BLACK - Black + * ANSI_RED - Red + * ANSI_GREEN - Green + * ANSI_BROWN - Brown / dark yellow + * ANSI_BLUE - Blue + * ANSI_MAGENTA - Magenta / purple + * ANSI_CYAN - Cyan + * ANSI_GREY - Grey / dark white + * ANSI_DARKGREY - Dark grey / light black + * ANSI_LIGHTRED - Light red + * ANSI_LIGHTGREEN - Light green + * ANSI_YELLOW - Yellow (bright) + * ANSI_LIGHTBLUE - Light blue + * ANSI_LIGHTMAGENTA - Light magenta / light purple + * ANSI_LIGHTCYAN - Light cyan + * ANSI_WHITE - White (bright) + * ANSI_BACKGROUND_BLACK - Black background + * ANSI_BACKGROUND_RED - Red background + * ANSI_BACKGROUND_GREEN - Green background + * ANSI_BACKGROUND_YELLOW - Yellow background + * ANSI_BACKGROUND_BLUE - Blue background + * ANSI_BACKGROUND_MAGENTA - Magenta / purple background + * ANSI_BACKGROUND_CYAN - Cyan background + * ANSI_BACKGROUND_WHITE - White background + */ + const RLUTIL_STRING_T ANSI_CLS = "\033[2J\033[3J"; + const RLUTIL_STRING_T ANSI_CONSOLE_TITLE_PRE = "\033]0;"; + const RLUTIL_STRING_T ANSI_CONSOLE_TITLE_POST = "\007"; + const RLUTIL_STRING_T ANSI_ATTRIBUTE_RESET = "\033[0m"; + const RLUTIL_STRING_T ANSI_CURSOR_HIDE = "\033[?25l"; + const RLUTIL_STRING_T ANSI_CURSOR_SHOW = "\033[?25h"; + const RLUTIL_STRING_T ANSI_CURSOR_HOME = "\033[H"; + const RLUTIL_STRING_T ANSI_BLACK = "\033[22;30m"; + const RLUTIL_STRING_T ANSI_RED = "\033[22;31m"; + const RLUTIL_STRING_T ANSI_GREEN = "\033[22;32m"; + const RLUTIL_STRING_T ANSI_BROWN = "\033[22;33m"; + const RLUTIL_STRING_T ANSI_BLUE = "\033[22;34m"; + const RLUTIL_STRING_T ANSI_MAGENTA = "\033[22;35m"; + const RLUTIL_STRING_T ANSI_CYAN = "\033[22;36m"; + const RLUTIL_STRING_T ANSI_GREY = "\033[22;37m"; + const RLUTIL_STRING_T ANSI_DARKGREY = "\033[01;30m"; + const RLUTIL_STRING_T ANSI_LIGHTRED = "\033[01;31m"; + const RLUTIL_STRING_T ANSI_LIGHTGREEN = "\033[01;32m"; + const RLUTIL_STRING_T ANSI_YELLOW = "\033[01;33m"; + const RLUTIL_STRING_T ANSI_LIGHTBLUE = "\033[01;34m"; + const RLUTIL_STRING_T ANSI_LIGHTMAGENTA = "\033[01;35m"; + const RLUTIL_STRING_T ANSI_LIGHTCYAN = "\033[01;36m"; + const RLUTIL_STRING_T ANSI_WHITE = "\033[01;37m"; + const RLUTIL_STRING_T ANSI_BACKGROUND_BLACK = "\033[40m"; + const RLUTIL_STRING_T ANSI_BACKGROUND_RED = "\033[41m"; + const RLUTIL_STRING_T ANSI_BACKGROUND_GREEN = "\033[42m"; + const RLUTIL_STRING_T ANSI_BACKGROUND_YELLOW = "\033[43m"; + const RLUTIL_STRING_T ANSI_BACKGROUND_BLUE = "\033[44m"; + const RLUTIL_STRING_T ANSI_BACKGROUND_MAGENTA = "\033[45m"; + const RLUTIL_STRING_T ANSI_BACKGROUND_CYAN = "\033[46m"; + const RLUTIL_STRING_T ANSI_BACKGROUND_WHITE = "\033[47m"; + // Remaining colors not supported as background colors + + /** + * Enums: Key codes for keyhit() + * + * KEY_ESCAPE - Escape + * KEY_ENTER - Enter + * KEY_SPACE - Space + * KEY_INSERT - Insert + * KEY_HOME - Home + * KEY_END - End + * KEY_DELETE - Delete + * KEY_PGUP - PageUp + * KEY_PGDOWN - PageDown + * KEY_UP - Up arrow + * KEY_DOWN - Down arrow + * KEY_LEFT - Left arrow + * KEY_RIGHT - Right arrow + * KEY_F1 - F1 + * KEY_F2 - F2 + * KEY_F3 - F3 + * KEY_F4 - F4 + * KEY_F5 - F5 + * KEY_F6 - F6 + * KEY_F7 - F7 + * KEY_F8 - F8 + * KEY_F9 - F9 + * KEY_F10 - F10 + * KEY_F11 - F11 + * KEY_F12 - F12 + * KEY_NUMDEL - Numpad del + * KEY_NUMPAD0 - Numpad 0 + * KEY_NUMPAD1 - Numpad 1 + * KEY_NUMPAD2 - Numpad 2 + * KEY_NUMPAD3 - Numpad 3 + * KEY_NUMPAD4 - Numpad 4 + * KEY_NUMPAD5 - Numpad 5 + * KEY_NUMPAD6 - Numpad 6 + * KEY_NUMPAD7 - Numpad 7 + * KEY_NUMPAD8 - Numpad 8 + * KEY_NUMPAD9 - Numpad 9 + */ + enum + { + KEY_ESCAPE = 0, + KEY_ENTER = 1, + KEY_SPACE = 32, + + KEY_INSERT = 2, + KEY_HOME = 3, + KEY_PGUP = 4, + KEY_DELETE = 5, + KEY_END = 6, + KEY_PGDOWN = 7, +#ifndef _WIN32 + KEY_BACKSPACE = 127, +#else + KEY_BACKSPACE = 8, +#endif + + KEY_UP = 14, + KEY_DOWN = 15, + KEY_LEFT = 16, + KEY_RIGHT = 17, + + KEY_F1 = 18, + KEY_F2 = 19, + KEY_F3 = 20, + KEY_F4 = 21, + KEY_F5 = 22, + KEY_F6 = 23, + KEY_F7 = 24, + KEY_F8 = 25, + KEY_F9 = 26, + KEY_F10 = 27, + KEY_F11 = 28, + KEY_F12 = 29, + + KEY_NUMDEL = 30, + KEY_NUMPAD0 = 31, + KEY_NUMPAD1 = 127, + KEY_NUMPAD2 = 128, + KEY_NUMPAD3 = 129, + KEY_NUMPAD4 = 130, + KEY_NUMPAD5 = 131, + KEY_NUMPAD6 = 132, + KEY_NUMPAD7 = 133, + KEY_NUMPAD8 = 134, + KEY_NUMPAD9 = 135 + }; + + /// Function: getkey + /// Reads a key press (blocking) and returns a key code. + /// + /// See + /// + /// Note: + /// Only Arrows, Esc, Enter and Space are currently working properly. + RLUTIL_INLINE int getkey(void) + { +#ifndef _WIN32 + int cnt = kbhit(); // for ANSI escapes processing +#endif + int k = getch(); + switch (k) + { + case 0: + { + int kk; + switch (kk = getch()) + { + case 71: + return KEY_NUMPAD7; + case 72: + return KEY_NUMPAD8; + case 73: + return KEY_NUMPAD9; + case 75: + return KEY_NUMPAD4; + case 77: + return KEY_NUMPAD6; + case 79: + return KEY_NUMPAD1; + case 80: + return KEY_NUMPAD2; + case 81: + return KEY_NUMPAD3; + case 82: + return KEY_NUMPAD0; + case 83: + return KEY_NUMDEL; + default: + return kk - 59 + KEY_F1; // Function keys + } + } + case 224: + { + int kk; + switch (kk = getch()) + { + case 71: + return KEY_HOME; + case 72: + return KEY_UP; + case 73: + return KEY_PGUP; + case 75: + return KEY_LEFT; + case 77: + return KEY_RIGHT; + case 79: + return KEY_END; + case 80: + return KEY_DOWN; + case 81: + return KEY_PGDOWN; + case 82: + return KEY_INSERT; + case 83: + return KEY_DELETE; + default: + return kk - 123 + KEY_F1; // Function keys + } + } + case 13: + return KEY_ENTER; +#ifdef _WIN32 + case 27: + return KEY_ESCAPE; +#else // _WIN32 + case 155: // single-character CSI + case 27: + { + // Process ANSI escape sequences + if (cnt >= 3 && getch() == '[') + { + switch (k = getch()) + { + case 'A': + return KEY_UP; + case 'B': + return KEY_DOWN; + case 'C': + return KEY_RIGHT; + case 'D': + return KEY_LEFT; + } + } + else + return KEY_ESCAPE; + [[fallthrough]]; + } +#endif // _WIN32 + default: + return k; + } + } + + /// Function: nb_getch + /// Non-blocking getch(). Returns 0 if no key was pressed. + RLUTIL_INLINE int nb_getch(void) + { + if (kbhit()) + return getch(); + else + return 0; + } + + /// Function: getANSIColor + /// Return ANSI color escape sequence for specified number 0-15. + /// + /// See + RLUTIL_INLINE RLUTIL_STRING_T getANSIColor(const int c) + { + switch (c) + { + case BLACK: + return ANSI_BLACK; + case BLUE: + return ANSI_BLUE; // non-ANSI + case GREEN: + return ANSI_GREEN; + case CYAN: + return ANSI_CYAN; // non-ANSI + case RED: + return ANSI_RED; // non-ANSI + case MAGENTA: + return ANSI_MAGENTA; + case BROWN: + return ANSI_BROWN; + case GREY: + return ANSI_GREY; + case DARKGREY: + return ANSI_DARKGREY; + case LIGHTBLUE: + return ANSI_LIGHTBLUE; // non-ANSI + case LIGHTGREEN: + return ANSI_LIGHTGREEN; + case LIGHTCYAN: + return ANSI_LIGHTCYAN; // non-ANSI; + case LIGHTRED: + return ANSI_LIGHTRED; // non-ANSI; + case LIGHTMAGENTA: + return ANSI_LIGHTMAGENTA; + case YELLOW: + return ANSI_YELLOW; // non-ANSI + case WHITE: + return ANSI_WHITE; + default: + return ""; + } + } + + /// Function: getANSIBackgroundColor + /// Return ANSI background color escape sequence for specified number 0-15. + /// + /// See + RLUTIL_INLINE RLUTIL_STRING_T getANSIBackgroundColor(const int c) + { + switch (c) + { + case BLACK: + return ANSI_BACKGROUND_BLACK; + case BLUE: + return ANSI_BACKGROUND_BLUE; + case GREEN: + return ANSI_BACKGROUND_GREEN; + case CYAN: + return ANSI_BACKGROUND_CYAN; + case RED: + return ANSI_BACKGROUND_RED; + case MAGENTA: + return ANSI_BACKGROUND_MAGENTA; + case BROWN: + return ANSI_BACKGROUND_YELLOW; + case GREY: + return ANSI_BACKGROUND_WHITE; + default: + return ""; + } + } + + /// Function: setColor + /// Change color specified by number (Windows / QBasic colors). + /// Don't change the background color + /// + /// See + RLUTIL_INLINE void setColor(int c) + { +#if defined(_WIN32) && !defined(RLUTIL_USE_ANSI) + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_SCREEN_BUFFER_INFO csbi; + + GetConsoleScreenBufferInfo(hConsole, &csbi); + + SetConsoleTextAttribute( + hConsole, + (csbi.wAttributes & 0xFFF0) | + (WORD)c); // Foreground colors take up the least significant byte +#else + RLUTIL_PRINT(getANSIColor(c)); +#endif + } + + /// Function: setBackgroundColor + /// Change background color specified by number (Windows / QBasic colors). + /// Don't change the foreground color + /// + /// See + RLUTIL_INLINE void setBackgroundColor(int c) + { +#if defined(_WIN32) && !defined(RLUTIL_USE_ANSI) + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_SCREEN_BUFFER_INFO csbi; + + GetConsoleScreenBufferInfo(hConsole, &csbi); + + SetConsoleTextAttribute( + hConsole, (csbi.wAttributes & 0xFF0F) | + (((WORD)c) << 4)); // Background colors take up the + // second-least significant byte +#else + RLUTIL_PRINT(getANSIBackgroundColor(c)); +#endif + } + + /// Function: saveDefaultColor + /// Call once to preserve colors for use in resetColor() + /// on Windows without ANSI, no-op otherwise + /// + /// See + /// See + RLUTIL_INLINE int saveDefaultColor(void) + { +#if defined(_WIN32) && !defined(RLUTIL_USE_ANSI) + static char initialized = 0; // bool + static WORD attributes; + + if (!initialized) + { + CONSOLE_SCREEN_BUFFER_INFO csbi; + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); + attributes = csbi.wAttributes; + initialized = 1; + } + return (int)attributes; +#else + return -1; +#endif + } + + /// Function: resetColor + /// Reset color to default + /// Requires a call to saveDefaultColor() to set the defaults + /// + /// See + /// See + /// See + RLUTIL_INLINE void resetColor(void) + { +#if defined(_WIN32) && !defined(RLUTIL_USE_ANSI) + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), + (WORD)saveDefaultColor()); +#else + RLUTIL_PRINT(ANSI_ATTRIBUTE_RESET); +#endif + } + + /// Function: cls + /// Clears screen, resets all attributes and moves cursor home. + RLUTIL_INLINE void cls(void) + { +#if defined(_WIN32) && !defined(RLUTIL_USE_ANSI) + // Based on + // https://msdn.microsoft.com/en-us/library/windows/desktop/ms682022%28v=vs.85%29.aspx + const HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + const COORD coordScreen = { 0, 0 }; + DWORD cCharsWritten; + CONSOLE_SCREEN_BUFFER_INFO csbi; + + GetConsoleScreenBufferInfo(hConsole, &csbi); + const DWORD dwConSize = csbi.dwSize.X * csbi.dwSize.Y; + FillConsoleOutputCharacter(hConsole, (TCHAR)' ', dwConSize, coordScreen, + &cCharsWritten); + + GetConsoleScreenBufferInfo(hConsole, &csbi); + FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, + &cCharsWritten); + + SetConsoleCursorPosition(hConsole, coordScreen); +#else + RLUTIL_PRINT(ANSI_CLS); + RLUTIL_PRINT(ANSI_CURSOR_HOME); +#endif + } + + /// Function: locate + /// Sets the cursor position to 1-based x,y. + RLUTIL_INLINE void locate(int x, int y) + { +#if defined(_WIN32) && !defined(RLUTIL_USE_ANSI) + COORD coord; + // TODO: clamping/assert for x/y <= 0? + coord.X = (SHORT)(x - 1); + coord.Y = (SHORT)(y - 1); // Windows uses 0-based coordinates + SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord); +#else // _WIN32 || USE_ANSI + #ifdef __cplusplus + RLUTIL_PRINT("\033[" << y << ";" << x << "H"); + #else // __cplusplus + char buf[32]; + sprintf(buf, "\033[%d;%df", y, x); + RLUTIL_PRINT(buf); + #endif // __cplusplus +#endif // _WIN32 || USE_ANSI + } + +/// Function: setString +/// Prints the supplied string without advancing the cursor +#ifdef __cplusplus + RLUTIL_INLINE void setString(const RLUTIL_STRING_T& str_) + { + const char* const str = str_.data(); + std::size_t len = str_.size(); +#else // __cplusplus +RLUTIL_INLINE void setString(RLUTIL_STRING_T str) +{ + unsigned int len = strlen(str); +#endif // __cplusplus +#if defined(_WIN32) && !defined(RLUTIL_USE_ANSI) + HANDLE hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD numberOfCharsWritten; + CONSOLE_SCREEN_BUFFER_INFO csbi; + + GetConsoleScreenBufferInfo(hConsoleOutput, &csbi); + WriteConsoleOutputCharacter(hConsoleOutput, str, (DWORD)len, + csbi.dwCursorPosition, &numberOfCharsWritten); +#else // _WIN32 || USE_ANSI + RLUTIL_PRINT(str); + #ifdef __cplusplus + RLUTIL_PRINT("\033[" << len << 'D'); + #else // __cplusplus + char buf[3 + 20 + + 1]; // 20 = max length of 64-bit unsigned int when printed as dec + sprintf(buf, "\033[%uD", len); + RLUTIL_PRINT(buf); + #endif // __cplusplus +#endif // _WIN32 || USE_ANSI + } + + /// Function: setChar + /// Sets the character at the cursor without advancing the cursor + RLUTIL_INLINE void setChar(char ch) + { + const char buf[] = { ch, 0 }; + setString(buf); + } + + /// Function: setCursorVisibility + /// Shows/hides the cursor. + RLUTIL_INLINE void setCursorVisibility(char visible) + { +#if defined(_WIN32) && !defined(RLUTIL_USE_ANSI) + HANDLE hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_CURSOR_INFO structCursorInfo; + GetConsoleCursorInfo(hConsoleOutput, + &structCursorInfo); // Get current cursor size + structCursorInfo.bVisible = (visible ? TRUE : FALSE); + SetConsoleCursorInfo(hConsoleOutput, &structCursorInfo); +#else // _WIN32 || USE_ANSI + RLUTIL_PRINT((visible ? ANSI_CURSOR_SHOW : ANSI_CURSOR_HIDE)); +#endif // _WIN32 || USE_ANSI + } + + /// Function: hidecursor + /// Hides the cursor. + RLUTIL_INLINE void hidecursor(void) + { + setCursorVisibility(0); + } + + /// Function: showcursor + /// Shows the cursor. + RLUTIL_INLINE void showcursor(void) + { + setCursorVisibility(1); + } + + /// Function: msleep + /// Waits given number of milliseconds before continuing. + RLUTIL_INLINE void msleep(unsigned int ms) + { +#ifdef _WIN32 + Sleep(ms); +#else + // usleep argument must be under 1 000 000 + if (ms > 1000) + sleep(ms / 1000000); + usleep((ms % 1000000) * 1000); +#endif + } + + /// Function: trows + /// Get the number of rows in the terminal window or -1 on error. + RLUTIL_INLINE int trows(void) + { +#ifdef _WIN32 + CONSOLE_SCREEN_BUFFER_INFO csbi; + if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) + return -1; + else + return csbi.srWindow.Bottom - csbi.srWindow.Top + 1; // Window height + // return csbi.dwSize.Y; // Buffer height +#else + #ifdef TIOCGSIZE + struct ttysize ts; + ioctl(STDIN_FILENO, TIOCGSIZE, &ts); + return ts.ts_lines; + #elif defined(TIOCGWINSZ) + struct winsize ts; + ioctl(STDIN_FILENO, TIOCGWINSZ, &ts); + return ts.ws_row; + #else // TIOCGSIZE + return -1; + #endif // TIOCGSIZE +#endif // _WIN32 + } + + /// Function: tcols + /// Get the number of columns in the terminal window or -1 on error. + RLUTIL_INLINE int tcols(void) + { +#ifdef _WIN32 + CONSOLE_SCREEN_BUFFER_INFO csbi; + if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) + return -1; + else + return csbi.srWindow.Right - csbi.srWindow.Left + 1; // Window width + // return csbi.dwSize.X; // Buffer width +#else + #ifdef TIOCGSIZE + struct ttysize ts; + ioctl(STDIN_FILENO, TIOCGSIZE, &ts); + return ts.ts_cols; + #elif defined(TIOCGWINSZ) + struct winsize ts; + ioctl(STDIN_FILENO, TIOCGWINSZ, &ts); + return ts.ws_col; + #else // TIOCGSIZE + return -1; + #endif // TIOCGSIZE +#endif // _WIN32 + } + +/// Function: anykey +/// Waits until a key is pressed. +/// In C++, it either takes no arguments +/// or a template-type-argument-deduced +/// argument. +/// In C, it takes a const char* representing +/// the message to be displayed, or NULL +/// for no message. +#ifdef __cplusplus + RLUTIL_INLINE void anykey() + { + getch(); + } + + template + void anykey(const T& msg) + { + RLUTIL_PRINT(msg); +#else +RLUTIL_INLINE void anykey(RLUTIL_STRING_T msg) +{ + if (msg) + RLUTIL_PRINT(msg); +#endif // __cplusplus + getch(); + } + + RLUTIL_INLINE void setConsoleTitle(RLUTIL_STRING_T title) + { + const char* true_title = +#ifdef __cplusplus + title.c_str(); +#else // __cplusplus + title; +#endif // __cplusplus +#if defined(_WIN32) && !defined(RLUTIL_USE_ANSI) + SetConsoleTitleA(true_title); +#else + RLUTIL_PRINT(ANSI_CONSOLE_TITLE_PRE); + RLUTIL_PRINT(true_title); + RLUTIL_PRINT(ANSI_CONSOLE_TITLE_POST); +#endif // defined(_WIN32) && !defined(RLUTIL_USE_ANSI) + } + + // Classes are here at the end so that documentation is pretty. + +#ifdef __cplusplus + /// Class: CursorHider + /// RAII OOP wrapper for . + /// Hides the cursor and shows it again + /// when the object goes out of scope. + struct CursorHider + { + CursorHider() { hidecursor(); } + ~CursorHider() { showcursor(); } + }; + +} // namespace rlutil +#endif -- cgit v1.3