// #include #ifdef _WIN32 #include #include #else #include #include #include #include #endif // Special key codes (unified across platforms) #define KEY_ARROW_UP 1001 #define KEY_ARROW_DOWN 1002 #define KEY_ARROW_RIGHT 1003 #define KEY_ARROW_LEFT 1004 int terminkey(); void echooff(); void echoon(); int termwidth(); #ifdef _WIN32 int terminkey() { if (_kbhit()) { int ch = _getch(); // Handle Windows arrow keys if (ch == 224) { int next = _getch(); switch (next) { case 72: return KEY_ARROW_UP; case 80: return KEY_ARROW_DOWN; case 75: return KEY_ARROW_LEFT; case 77: return KEY_ARROW_RIGHT; default: return next; } } return ch; } return -1; } void echooff() { HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); DWORD mode = 0; GetConsoleMode(hStdin, &mode); SetConsoleMode(hStdin, mode & ~ENABLE_ECHO_INPUT); } void echoon() { HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); DWORD mode = 0; GetConsoleMode(hStdin, &mode); SetConsoleMode(hStdin, mode | ENABLE_ECHO_INPUT); } int termwidth() { HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO csbi; if (GetConsoleScreenBufferInfo(hStdout, &csbi)) { return csbi.srWindow.Right - csbi.srWindow.Left + 1; } return -1; } #else int terminkey() { struct termios oldt, newt; int ch; int oldf; // Save existing terminal settings tcgetattr(STDIN_FILENO, &oldt); newt = oldt; // Disable buffering and echoing newt.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &newt); // Set STDIN to non-blocking oldf = fcntl(STDIN_FILENO, F_GETFL, 0); fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); ch = getchar(); // Handle Unix arrow keys (ESC [ A/B/C/D) if (ch == 27) { int next1 = getchar(); if (next1 == '[') { int next2 = getchar(); switch (next2) { case 'A': ch = KEY_ARROW_UP; break; case 'B': ch = KEY_ARROW_DOWN; break; case 'C': ch = KEY_ARROW_RIGHT; break; case 'D': ch = KEY_ARROW_LEFT; break; } } } // Restore terminal settings tcsetattr(STDIN_FILENO, TCSANOW, &oldt); fcntl(STDIN_FILENO, F_SETFL, oldf); return ch; } void echooff() { struct termios tty; tcgetattr(STDIN_FILENO, &tty); tty.c_lflag &= ~ECHO; tcsetattr(STDIN_FILENO, TCSANOW, &tty); } void echoon() { struct termios tty; tcgetattr(STDIN_FILENO, &tty); tty.c_lflag |= ECHO; tcsetattr(STDIN_FILENO, TCSANOW, &tty); } int termwidth() { struct winsize w; if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0) { return w.ws_col; } return -1; } #endif