summaryrefslogtreecommitdiff
path: root/Homework/cs3460/gameoflife/rlutil.h
diff options
context:
space:
mode:
authorElizabeth Alexander Hunt <me@liz.coffee>2026-07-02 11:55:17 -0700
committerElizabeth Alexander Hunt <me@liz.coffee>2026-07-02 11:55:17 -0700
commit6bf4b90c90f15f4ab60833bddf5b5756d1a6b1f6 (patch)
treeed97e39ec77c5231ffd2c394493e68d00ddac5a4 /Homework/cs3460/gameoflife/rlutil.h
downloadmisc-undergrad-6bf4b90c90f15f4ab60833bddf5b5756d1a6b1f6.tar.gz
misc-undergrad-6bf4b90c90f15f4ab60833bddf5b5756d1a6b1f6.zip
Diffstat (limited to 'Homework/cs3460/gameoflife/rlutil.h')
-rw-r--r--Homework/cs3460/gameoflife/rlutil.h876
1 files changed, 876 insertions, 0 deletions
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 <License>
+ */
+
+/// 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 <cstdio> // for getch()
+ #include <iostream>
+ #include <string>
+/// Namespace forward declarations
+namespace rlutil
+{
+ RLUTIL_INLINE void locate(int x, int y);
+}
+#else
+ #include <stdio.h> // for getch() / printf()
+ #include <string.h> // for strlen()
+RLUTIL_INLINE void locate(int x,
+ int y); // Forward declare for C to avoid warnings
+#endif // __cplusplus
+
+#ifdef _WIN32
+ #include <windows.h> // for WinAPI and Sleep()
+ #define _NO_OLDNAMES // for MinGW compatibility
+ #include <conio.h> // for getch() and kbhit()
+ #define getch _getch
+ #define kbhit _kbhit
+#else
+ #include <sys/ioctl.h> // for getkey()
+ #include <sys/time.h> // for kbhit()
+ #include <sys/types.h> // for kbhit()
+ #include <termios.h> // for getch() and kbhit()
+ #include <unistd.h> // 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.locate>.
+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 <getch>, <kbhit> and <gotoxy> 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 <Key codes for keyhit()>
+ ///
+ /// 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 <Color Codes>
+ 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 <Color Codes>
+ 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 <Color Codes>
+ 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 <Color Codes>
+ 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 <Color Codes>
+ /// See <resetColor>
+ 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 <Color Codes>
+ /// See <setColor>
+ /// See <saveDefaultColor>
+ 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 <class T>
+ 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 <rlutil.hidecursor>.
+ /// Hides the cursor and shows it again
+ /// when the object goes out of scope.
+ struct CursorHider
+ {
+ CursorHider() { hidecursor(); }
+ ~CursorHider() { showcursor(); }
+ };
+
+} // namespace rlutil
+#endif