* 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
This commit is contained in:
Christian Burger 2022-04-05 10:23:50 +02:00
parent 28643632ce
commit c0a3ca7822
4 changed files with 85 additions and 40 deletions

View file

@ -8,9 +8,15 @@
#include <unistd.h> #include <unistd.h>
#include <utmp.h> #include <utmp.h>
#include <cstdlib>
namespace krikkel::NCursesPty namespace krikkel::NCursesPty
{ {
NCursesPtyApp::NCursesPtyApp() : NCursesApplication(false)
{
}
int NCursesPtyApp::run() int NCursesPtyApp::run()
{ {
NCursesPtyWindow *ptyWindow = new NCursesPtyWindow( NCursesPtyWindow *ptyWindow = new NCursesPtyWindow(
@ -21,18 +27,25 @@ namespace krikkel::NCursesPty
if(fork() == 0) if(fork() == 0)
{ {
/// @todo close(ptyWindow->getFdPtyHost()); ??? const char *shellPath = getenv("SHELL");
if(!shellPath)
shellPath = "/bin/bash";
login_tty(ptyWindow->getFdPtyClient()); login_tty(ptyWindow->getFdPtyClient());
const int sizeArg = 2; const int sizeArg = 2;
const char *arg[sizeArg] = {"/bin/bash", NULL}; const char *arg[sizeArg] = {shellPath, NULL};
fprintf(stderr, "<CTRL>+C exits shell.\n\n");
execv("/bin/bash", const_cast<char * const *>(arg)); execv(shellPath, const_cast<char * const *>(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; int input;
while((input = ptyWindow->getch()) != 27) while(true)
{ {
__debug_log("input: " + std::to_string(input)); input = ptyWindow->getch();
ptyWindow->writeToClient((unsigned char) input); ptyWindow->writeToClient((unsigned char) input);
} }

View file

@ -12,6 +12,10 @@ namespace krikkel::NCursesPty
{ {
class NCursesPtyApp : public NCursesApplication class NCursesPtyApp : public NCursesApplication
{ {
public:
NCursesPtyApp();
private:
int run() override; int run() override;
}; };
} }

View file

@ -60,7 +60,6 @@ namespace krikkel::NCursesPty
/// @todo maybe implement a function with a string buffer /// @todo maybe implement a function with a string buffer
void NCursesPtyWindow::writeToClient(char character) void NCursesPtyWindow::writeToClient(char character)
{ {
//__debug_log(std::string("written '") + character + "' to client");
write(fdPtyHost, &character, sizeof(character)); write(fdPtyHost, &character, sizeof(character));
} }
@ -86,45 +85,27 @@ namespace krikkel::NCursesPty
size_t bytesRead = read(fdPtyHost, clientOutputBuffer, CLIENT_OUTPUT_BUFFER_SIZE); size_t bytesRead = read(fdPtyHost, clientOutputBuffer, CLIENT_OUTPUT_BUFFER_SIZE);
if(bytesRead) if(bytesRead)
vterm_input_write(pseudoTerminal, clientOutputBuffer, 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 = VTermScreenCallbacks NCursesPtyWindow::screenCallbacks =
{ {
.damage = staticHandlerDamage, .damage = staticHandlerDamage,
/* .moverect = staticHandlerMoveRect, .moverect = staticHandlerMoveRect,
.movecursor = staticHandlerMoveCursor, .movecursor = staticHandlerMoveCursor,
.settermprop = staticHandlerSetTermProp, .settermprop = staticHandlerSetTermProp,
.bell = staticHandlerBell, .bell = staticHandlerBell,
.resize = staticHandlerResize, .resize = staticHandlerResize,
.sb_pushline = staticHandlerPushLine, .sb_pushline = staticHandlerPushLine,
.sb_popline = staticHandlerPopLine,*/ .sb_popline = staticHandlerPopLine,
}; };
int NCursesPtyWindow::handlerDamage(VTermRect rect) 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 x = rect.start_col; x < rect.end_col; ++x)
for(int y = rect.start_row; y < rect.end_row; ++y) for(int y = rect.start_row; y < rect.end_row; ++y)
copyPtyCellToNCursesWindow(x, y); copyPtyCellToNCursesWindow(x, y);
move(cursorY, cursorX); refresh();
return 0; return 0;
} }
@ -148,11 +129,9 @@ namespace krikkel::NCursesPty
int NCursesPtyWindow::handlerMoveCursor(VTermPos pos, VTermPos oldpos, int visible) int NCursesPtyWindow::handlerMoveCursor(VTermPos pos, VTermPos oldpos, int visible)
{ {
__debug_log("cursor moved to (" cursorX = pos.col;
+ std::to_string(pos.col) + ", " cursorY = pos.row;
+ std::to_string(pos.row) + ") " refresh();
+ "visible: " + (visible ? "true" : "false"));
move(pos.row, pos.col);
return 0; return 0;
} }
@ -222,15 +201,52 @@ namespace krikkel::NCursesPty
return 0; 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) void NCursesPtyWindow::copyPtyCellToNCursesWindow(int x, int y)
{ {
VTermPos cellPosition = {y, x}; VTermPos cellPosition = {y, x};
VTermScreenCell cell; VTermScreenCell vTermCell;
vterm_screen_get_cell(pseudoTerminalScreen, cellPosition, &cell); cchar_t converted;
move(y, x); attr_t formatting;
addch(cell.chars[0] ? cell.chars[0] : ' ' ); short colorPair;
/// @todo boy, is this expensive … wchar_t character;
refresh();
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) int NCursesPtyWindow::staticHandlerDamage(VTermRect rect, void *user)

View file

@ -9,6 +9,12 @@
#include <string> #include <string>
#include <thread> #include <thread>
#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 namespace krikkel::NCursesPty
{ {
class NCursesPtyWindow : public NCursesWindow class NCursesPtyWindow : public NCursesWindow
@ -20,6 +26,9 @@ namespace krikkel::NCursesPty
int getFdPtyClient() const; int getFdPtyClient() const;
void writeToClient(char character); void writeToClient(char character);
int add_wch(cchar_t *character);
int refresh() override;
private: private:
int fdPtyHost, fdPtyClient; int fdPtyHost, fdPtyClient;
struct termios terminalParameters; struct termios terminalParameters;
@ -29,6 +38,7 @@ namespace krikkel::NCursesPty
/// @todo one line is at most 4096 chars long /// @todo one line is at most 4096 chars long
static const u_int CLIENT_OUTPUT_BUFFER_SIZE = 512; static const u_int CLIENT_OUTPUT_BUFFER_SIZE = 512;
char clientOutputBuffer[CLIENT_OUTPUT_BUFFER_SIZE]; char clientOutputBuffer[CLIENT_OUTPUT_BUFFER_SIZE];
uint16_t cursorX, cursorY;
std::thread readPtyClientThread; std::thread readPtyClientThread;
void readFromPtyClientThreadMethod(); void readFromPtyClientThreadMethod();
@ -43,6 +53,8 @@ namespace krikkel::NCursesPty
int handlerPushLine(int cols, const VTermScreenCell *cells); int handlerPushLine(int cols, const VTermScreenCell *cells);
int handlerPopLine(int cols, VTermScreenCell *cells); int handlerPopLine(int cols, VTermScreenCell *cells);
attr_t extractAttributesFromVTermCell(VTermScreenCell cell);
short extractColorFromVTermCell(VTermScreenCell cell);
void copyPtyCellToNCursesWindow(int x, int y); void copyPtyCellToNCursesWindow(int x, int y);
static int staticHandlerDamage(VTermRect rect, void *user); static int staticHandlerDamage(VTermRect rect, void *user);