From c0a3ca7822f74672e52b255a5a912038ba191ef8 Mon Sep 17 00:00:00 2001 From: Christian Burger Date: Tue, 5 Apr 2022 10:23:50 +0200 Subject: [PATCH] fixes #1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * demo app: using `SHELL` environment var or `/bin/bash` as default * removed some debug messages * enabled all vterm screen handlers; if not implemented there is a debug message * fixed and improved cursor position — was sometimes off; e. g. if pressing backspace * stubs for some functions required for implementing #3 --- NCursesPtyApp.cpp | 25 ++++++++++---- NCursesPtyApp.hpp | 6 +++- NCursesPtyWindow.cpp | 82 ++++++++++++++++++++++++++------------------ NCursesPtyWindow.hpp | 12 +++++++ 4 files changed, 85 insertions(+), 40 deletions(-) diff --git a/NCursesPtyApp.cpp b/NCursesPtyApp.cpp index dad7a74..e481e53 100644 --- a/NCursesPtyApp.cpp +++ b/NCursesPtyApp.cpp @@ -8,9 +8,15 @@ #include #include +#include namespace krikkel::NCursesPty { + NCursesPtyApp::NCursesPtyApp() : NCursesApplication(false) + { + + } + int NCursesPtyApp::run() { NCursesPtyWindow *ptyWindow = new NCursesPtyWindow( @@ -21,18 +27,25 @@ namespace krikkel::NCursesPty if(fork() == 0) { - /// @todo close(ptyWindow->getFdPtyHost()); ??? + const char *shellPath = getenv("SHELL"); + if(!shellPath) + shellPath = "/bin/bash"; + login_tty(ptyWindow->getFdPtyClient()); const int sizeArg = 2; - const char *arg[sizeArg] = {"/bin/bash", NULL}; - - execv("/bin/bash", const_cast(arg)); + const char *arg[sizeArg] = {shellPath, NULL}; + fprintf(stderr, "+C exits shell.\n\n"); + execv(shellPath, const_cast(arg)); + fprintf(stderr, "Well, well, well … could not start a shell. We " + "tried `%s`. Maybe set `SHELL` environment variable" + " to a working value?", shellPath); + exit(1); } int input; - while((input = ptyWindow->getch()) != 27) + while(true) { - __debug_log("input: " + std::to_string(input)); + input = ptyWindow->getch(); ptyWindow->writeToClient((unsigned char) input); } diff --git a/NCursesPtyApp.hpp b/NCursesPtyApp.hpp index 968b556..4f166ea 100644 --- a/NCursesPtyApp.hpp +++ b/NCursesPtyApp.hpp @@ -12,7 +12,11 @@ namespace krikkel::NCursesPty { class NCursesPtyApp : public NCursesApplication { - int run() override; + public: + NCursesPtyApp(); + + private: + int run() override; }; } diff --git a/NCursesPtyWindow.cpp b/NCursesPtyWindow.cpp index c994463..4236baa 100644 --- a/NCursesPtyWindow.cpp +++ b/NCursesPtyWindow.cpp @@ -60,7 +60,6 @@ namespace krikkel::NCursesPty /// @todo maybe implement a function with a string buffer void NCursesPtyWindow::writeToClient(char character) { - //__debug_log(std::string("written '") + character + "' to client"); write(fdPtyHost, &character, sizeof(character)); } @@ -86,45 +85,27 @@ namespace krikkel::NCursesPty size_t bytesRead = read(fdPtyHost, clientOutputBuffer, CLIENT_OUTPUT_BUFFER_SIZE); if(bytesRead) vterm_input_write(pseudoTerminal, clientOutputBuffer, bytesRead); - __debug_log("read " + std::to_string(bytesRead) + " bytes from PTY client"); - /*string readable; - for(char character : clientOutputBuffer) - if(std::isprint((unsigned char) character)) - readable += character; - else - readable += "\\" + std::to_string((int) character) + "/"; - __debug_log("read: '" + readable + "'");*/ } VTermScreenCallbacks NCursesPtyWindow::screenCallbacks = { .damage = staticHandlerDamage, -/* .moverect = staticHandlerMoveRect, + .moverect = staticHandlerMoveRect, .movecursor = staticHandlerMoveCursor, .settermprop = staticHandlerSetTermProp, .bell = staticHandlerBell, .resize = staticHandlerResize, .sb_pushline = staticHandlerPushLine, - .sb_popline = staticHandlerPopLine,*/ + .sb_popline = staticHandlerPopLine, }; int NCursesPtyWindow::handlerDamage(VTermRect rect) { - __debug_log("damage to rectangle (" - + std::to_string(rect.start_col) + ", " - + std::to_string(rect.start_row) + ", " - + std::to_string(rect.end_col) + ", " - + std::to_string(rect.end_row) + ") " - + "size: " + std::to_string((rect.start_col - rect.end_col) * (rect.start_row - rect.end_row)) ); - - int cursorX, cursorY; - getyx(cursorY, cursorX); - for(int x = rect.start_col; x < rect.end_col; ++x) for(int y = rect.start_row; y < rect.end_row; ++y) copyPtyCellToNCursesWindow(x, y); - move(cursorY, cursorX); + refresh(); return 0; } @@ -148,11 +129,9 @@ namespace krikkel::NCursesPty int NCursesPtyWindow::handlerMoveCursor(VTermPos pos, VTermPos oldpos, int visible) { - __debug_log("cursor moved to (" - + std::to_string(pos.col) + ", " - + std::to_string(pos.row) + ") " - + "visible: " + (visible ? "true" : "false")); - move(pos.row, pos.col); + cursorX = pos.col; + cursorY = pos.row; + refresh(); return 0; } @@ -222,15 +201,52 @@ namespace krikkel::NCursesPty return 0; } + attr_t NCursesPtyWindow::extractAttributesFromVTermCell(VTermScreenCell vTermCell) + { + attr_t result = A_NORMAL; + __debug_log("unimplemented method called"); + return result; + } + + short NCursesPtyWindow::extractColorFromVTermCell(VTermScreenCell vTermCell) + { + __debug_log("unimplemented method called"); + return 0; + } + void NCursesPtyWindow::copyPtyCellToNCursesWindow(int x, int y) { VTermPos cellPosition = {y, x}; - VTermScreenCell cell; - vterm_screen_get_cell(pseudoTerminalScreen, cellPosition, &cell); - move(y, x); - addch(cell.chars[0] ? cell.chars[0] : ' ' ); - /// @todo boy, is this expensive … - refresh(); + VTermScreenCell vTermCell; + cchar_t converted; + attr_t formatting; + short colorPair; + wchar_t character; + + vterm_screen_get_cell(pseudoTerminalScreen, cellPosition, &vTermCell); + formatting = extractAttributesFromVTermCell(vTermCell); + colorPair = extractColorFromVTermCell(vTermCell); + + if(vTermCell.chars[0] == 0) + character = ' '; + else + character = *vTermCell.chars; + + setcchar(&converted, &character, formatting, colorPair, NULL); + move(cellPosition.row, cellPosition.col); + chgat(1, formatting, colorPair, NULL); + add_wch(&converted); + } + + int NCursesPtyWindow::add_wch(cchar_t *character) + { + return ::wadd_wch(w, character); + } + + int NCursesPtyWindow::refresh() + { + move(cursorY, cursorX); + return NCursesWindow::refresh(); } int NCursesPtyWindow::staticHandlerDamage(VTermRect rect, void *user) diff --git a/NCursesPtyWindow.hpp b/NCursesPtyWindow.hpp index 592b154..fed6db8 100644 --- a/NCursesPtyWindow.hpp +++ b/NCursesPtyWindow.hpp @@ -9,6 +9,12 @@ #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 + namespace krikkel::NCursesPty { class NCursesPtyWindow : public NCursesWindow @@ -20,6 +26,9 @@ namespace krikkel::NCursesPty int getFdPtyClient() const; void writeToClient(char character); + int add_wch(cchar_t *character); + int refresh() override; + private: int fdPtyHost, fdPtyClient; struct termios terminalParameters; @@ -29,6 +38,7 @@ namespace krikkel::NCursesPty /// @todo one line is at most 4096 chars long static const u_int CLIENT_OUTPUT_BUFFER_SIZE = 512; char clientOutputBuffer[CLIENT_OUTPUT_BUFFER_SIZE]; + uint16_t cursorX, cursorY; std::thread readPtyClientThread; void readFromPtyClientThreadMethod(); @@ -43,6 +53,8 @@ namespace krikkel::NCursesPty 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);