* 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
Gentoo
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 <utmp.h>
#include <cstdlib>
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<char * const *>(arg));
const char *arg[sizeArg] = {shellPath, NULL};
fprintf(stderr, "<CTRL>+C exits shell.\n\n");
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;
while((input = ptyWindow->getch()) != 27)
while(true)
{
__debug_log("input: " + std::to_string(input));
input = ptyWindow->getch();
ptyWindow->writeToClient((unsigned char) input);
}

View File

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

View File

@ -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)

View File

@ -9,6 +9,12 @@
#include <string>
#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
{
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);