/** * @brief `ncurses` window displaying contents of a pseudo terminal * @author Christian Burger (christian@krikkel.de) */ #include "SingleUserInput.hpp" #include #include #include #include #include #include #ifdef add_wch inline void UNDEF(add_wch)(const cchar_t *character) { add_wch(character); } #undef add_wch #define add_wch UNDEF(add_wch) #endif #ifdef get_wch inline void UNDEF(get_wch)(wint_t *character) { get_wch(character); } #undef get_wch #define get_wch UNDEF(get_wch) #endif namespace krikkel::NCursesPtyWindow { class Window : public NCursesWindow { public: Window(int lines, int columns, int y, int x); ~Window(); int getFdPtyClient() const; void writeToClient(const char * string, size_t length); void writeUnicodeCharToClient(wint_t character); void writeKeyToClient(VTermKey key); SingleUserInput readSingleUserInput(); int add_wch(const cchar_t *character); int get_wch(wint_t *character); int refresh() override; int wresize(int rows, int cols); private: int fdPtyHost, fdPtyClient; struct termios terminalParameters; VTerm *pseudoTerminal; std::mutex writeToPseudoTerminalMutex; VTermScreen *pseudoTerminalScreen; static VTermScreenCallbacks screenCallbacks; /// @todo one line is at most 4096 chars long static const uint16_t PTY_CLIENT_OUTPUT_BUFFER_SIZE = 2 * 4096; char ptyClientOutputBuffer[PTY_CLIENT_OUTPUT_BUFFER_SIZE]; uint16_t cursorX, cursorY; std::thread readPtyClientThread; void readFromPtyClientThreadMethod(); void readFromPtyClient(); int handlerDamage(VTermRect rect); int handlerMoveRect(VTermRect dest, VTermRect src); int handlerMoveCursor(VTermPos pos, VTermPos oldpos, int visible); int handlerSetTermProp(VTermProp prop, VTermValue *val); int handlerBell(); int handlerResize(int rows, int cols); int handlerPushLine(int cols, const VTermScreenCell *cells); int handlerPopLine(int cols, VTermScreenCell *cells); attr_t extractAttributesFromVTermCell(VTermScreenCell cell); short extractColorFromVTermCell(VTermScreenCell cell); void copyPtyCellToNCursesWindow(int x, int y); static int staticHandlerDamage(VTermRect rect, void *user); static int staticHandlerMoveRect(VTermRect dest, VTermRect src, void *user); static int staticHandlerMoveCursor(VTermPos pos, VTermPos oldpos, int visible, void *user); static int staticHandlerSetTermProp(VTermProp prop, VTermValue *val, void *user); static int staticHandlerBell(void *user); static int staticHandlerResize(int rows, int cols, void *user); static int staticHandlerPushLine(int cols, const VTermScreenCell *cells, void *user); static int staticHandlerPopLine(int cols, VTermScreenCell *cells, void *user); static void staticHandlerOutput(const char *s, size_t len, void *user); }; }