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 <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);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,11 @@ namespace krikkel::NCursesPty
|
|||
{
|
||||
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
|
||||
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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue