fixes #1
* 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:
parent
28643632ce
commit
c0a3ca7822
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,11 @@ namespace krikkel::NCursesPty
|
||||||
{
|
{
|
||||||
class NCursesPtyApp : public NCursesApplication
|
class NCursesPtyApp : public NCursesApplication
|
||||||
{
|
{
|
||||||
int run() override;
|
public:
|
||||||
|
NCursesPtyApp();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int run() override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue