Compare commits
5 commits
ae6130f095
...
78672521c4
Author | SHA1 | Date | |
---|---|---|---|
Christian Burger | 78672521c4 | ||
Christian Burger | a300dd492b | ||
Christian Burger | ed534363a2 | ||
Christian Burger | 3af1284cf8 | ||
Christian Burger | 746e458cd2 |
17
.vscode/c_cpp_properties.json
vendored
Normal file
17
.vscode/c_cpp_properties.json
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Linux",
|
||||||
|
"includePath": [
|
||||||
|
"${default}"
|
||||||
|
],
|
||||||
|
"defines": [],
|
||||||
|
"compilerPath": "/usr/bin/gcc",
|
||||||
|
"cStandard": "gnu17",
|
||||||
|
"cppStandard": "gnu++14",
|
||||||
|
"intelliSenseMode": "linux-gcc-x64",
|
||||||
|
"configurationProvider": "ms-vscode.cmake-tools"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
|
@ -55,5 +55,8 @@
|
||||||
"typeinfo": "cpp",
|
"typeinfo": "cpp",
|
||||||
"pointers": "cpp"
|
"pointers": "cpp"
|
||||||
},
|
},
|
||||||
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools"
|
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
|
||||||
|
"C_Cpp.default.includePath": [
|
||||||
|
"${workspaceFolder}/include"
|
||||||
|
]
|
||||||
}
|
}
|
5
App.cpp
5
App.cpp
|
@ -4,11 +4,12 @@
|
||||||
|
|
||||||
#include "App.hpp"
|
#include "App.hpp"
|
||||||
#include "Debug.hpp"
|
#include "Debug.hpp"
|
||||||
#include <NCursesPtyWindow/Window.hpp>
|
#include <NCursesPtyWindow/PtyWindow.hpp>
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <utmp.h>
|
#include <utmp.h>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
namespace krikkel::NCursesPtyWindow
|
namespace krikkel::NCursesPtyWindow
|
||||||
{
|
{
|
||||||
|
@ -21,7 +22,7 @@ namespace krikkel::NCursesPtyWindow
|
||||||
{
|
{
|
||||||
std::mutex writeMutex;
|
std::mutex writeMutex;
|
||||||
|
|
||||||
Window *ptyWindow = new Window(&writeMutex
|
PtyWindow *ptyWindow = new PtyWindow(&writeMutex
|
||||||
, Root_Window->lines()
|
, Root_Window->lines()
|
||||||
, Root_Window->cols()
|
, Root_Window->cols()
|
||||||
, 0
|
, 0
|
||||||
|
|
|
@ -13,7 +13,7 @@ set(CMAKE_CXX_STANDARD 17)
|
||||||
include(CTest)
|
include(CTest)
|
||||||
enable_testing()
|
enable_testing()
|
||||||
|
|
||||||
add_library(NCursesPtyWindow Window.cpp SingleUserInput.cpp Debug.cpp)
|
add_library(NCursesPtyWindow Window.cpp PtyWindow.cpp SingleUserInput.cpp Debug.cpp)
|
||||||
|
|
||||||
### path to own system includes
|
### path to own system includes
|
||||||
include_directories(SYSTEM "${CMAKE_SOURCE_DIR}/include")
|
include_directories(SYSTEM "${CMAKE_SOURCE_DIR}/include")
|
||||||
|
|
328
PtyWindow.cpp
Normal file
328
PtyWindow.cpp
Normal file
|
@ -0,0 +1,328 @@
|
||||||
|
/**
|
||||||
|
* @author Christian Burger (christian@krikkel.de)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <NCursesPtyWindow/PtyWindow.hpp>
|
||||||
|
#include "Debug.hpp"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <gsl/gsl>
|
||||||
|
#include <cctype>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
namespace krikkel::NCursesPtyWindow
|
||||||
|
{
|
||||||
|
using gsl::narrow;
|
||||||
|
using std::lock_guard;
|
||||||
|
|
||||||
|
PtyWindow::PtyWindow(std::mutex *writeToNCursesMutex, int lines, int columns, int y, int x)
|
||||||
|
: writeToNCursesMutex(writeToNCursesMutex), Window(lines, columns, y, x)
|
||||||
|
{
|
||||||
|
// to get the original terminal we need to shutdown ncurses for a moment
|
||||||
|
/// @todo maybe try `reset_prog_mode()` and `reset_shell_mode()` instead
|
||||||
|
::endwin();
|
||||||
|
tcgetattr(STDIN_FILENO, &terminalParameters);
|
||||||
|
::refresh();
|
||||||
|
|
||||||
|
winsize windowSize =
|
||||||
|
{
|
||||||
|
.ws_row = narrow<short unsigned int>(this->height())
|
||||||
|
, .ws_col = narrow<short unsigned int>(this->width())
|
||||||
|
};
|
||||||
|
openpty(&fdPtyHost, &fdPtyClient, NULL, &terminalParameters, &windowSize);
|
||||||
|
|
||||||
|
pseudoTerminal = vterm_new(windowSize.ws_row, windowSize.ws_col);
|
||||||
|
vterm_set_utf8(pseudoTerminal, true);
|
||||||
|
pseudoTerminalScreen = vterm_obtain_screen(pseudoTerminal);
|
||||||
|
vterm_screen_reset(pseudoTerminalScreen, true);
|
||||||
|
vterm_screen_set_callbacks(pseudoTerminalScreen, &screenCallbacks, this);
|
||||||
|
vterm_output_set_callback(pseudoTerminal, &staticHandlerOutput, this);
|
||||||
|
vterm_screen_enable_altscreen(pseudoTerminalScreen, true);
|
||||||
|
|
||||||
|
//raw(); //— cbreak might suffice
|
||||||
|
//noecho(); — already set
|
||||||
|
//nodelay(true); — @todo needs some reprogramming
|
||||||
|
keypad(true);
|
||||||
|
nonl();
|
||||||
|
|
||||||
|
/// @todo block all signals, this thread does not handle any
|
||||||
|
readPtyClientThread =
|
||||||
|
std::thread(&PtyWindow::readFromPtyClientThreadMethod, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
PtyWindow::~PtyWindow()
|
||||||
|
{
|
||||||
|
close(fdPtyHost);
|
||||||
|
close(fdPtyClient);
|
||||||
|
vterm_free(pseudoTerminal);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PtyWindow::getFdPtyClient() const
|
||||||
|
{
|
||||||
|
return fdPtyClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PtyWindow::writeToClient(const char *output, size_t length)
|
||||||
|
{
|
||||||
|
lock_guard writeLock(writeToPseudoTerminalMutex);
|
||||||
|
write(fdPtyHost, output, length);
|
||||||
|
__debug_log("written to PTY client: '" + __debug_make_bytes_printable(std::string(output, length)) + '\'');
|
||||||
|
}
|
||||||
|
|
||||||
|
void PtyWindow::writeUnicodeCharToClient(wint_t character)
|
||||||
|
{
|
||||||
|
vterm_keyboard_unichar(pseudoTerminal, character, VTERM_MOD_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PtyWindow::writeKeyToClient(VTermKey key)
|
||||||
|
{
|
||||||
|
__debug_log("writing key: " + std::to_string(key));
|
||||||
|
vterm_keyboard_key(pseudoTerminal, key, VTERM_MOD_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PtyWindow::readFromPtyClientThreadMethod()
|
||||||
|
{
|
||||||
|
/// @todo in theory, there is no need for a timeout or select …
|
||||||
|
/// file descriptor is blocking
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
readFromPtyClient();
|
||||||
|
struct timeval timeout = { .tv_sec = 0, .tv_usec = 200000 };
|
||||||
|
fd_set readFds;
|
||||||
|
|
||||||
|
FD_ZERO(&readFds);
|
||||||
|
FD_SET(fdPtyHost, &readFds);
|
||||||
|
if(select(fdPtyHost + 1, &readFds, NULL, NULL, &timeout) < 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PtyWindow::readFromPtyClient()
|
||||||
|
{
|
||||||
|
size_t bytesRead = read(fdPtyHost, ptyClientOutputBuffer, PTY_CLIENT_OUTPUT_BUFFER_SIZE);
|
||||||
|
if(bytesRead != -1 && bytesRead != 0)
|
||||||
|
{
|
||||||
|
lock_guard writeLock(writeToPseudoTerminalMutex);
|
||||||
|
vterm_input_write(pseudoTerminal, ptyClientOutputBuffer, bytesRead);
|
||||||
|
}
|
||||||
|
__debug_log("read from PTY client: '" + __debug_make_bytes_printable(std::string(ptyClientOutputBuffer, bytesRead)) + '\'');
|
||||||
|
}
|
||||||
|
|
||||||
|
VTermScreenCallbacks PtyWindow::screenCallbacks =
|
||||||
|
{
|
||||||
|
.damage = staticHandlerDamage,
|
||||||
|
.moverect = staticHandlerMoveRect,
|
||||||
|
.movecursor = staticHandlerMoveCursor,
|
||||||
|
.settermprop = staticHandlerSetTermProp,
|
||||||
|
.bell = staticHandlerBell,
|
||||||
|
.resize = staticHandlerResize,
|
||||||
|
.sb_pushline = staticHandlerPushLine,
|
||||||
|
.sb_popline = staticHandlerPopLine,
|
||||||
|
};
|
||||||
|
|
||||||
|
int PtyWindow::handlerDamage(VTermRect rect)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
refresh();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PtyWindow::handlerMoveRect(VTermRect dest, VTermRect src)
|
||||||
|
{
|
||||||
|
__debug_log("(unimplemented) move content in rectangle from ("
|
||||||
|
+ std::to_string(src.start_col) + ", "
|
||||||
|
+ std::to_string(src.start_row) + ", "
|
||||||
|
+ std::to_string(src.end_col) + ", "
|
||||||
|
+ std::to_string(src.end_row) + ") "
|
||||||
|
+ "size: " + std::to_string((src.start_col - src.end_col) * (src.start_row - src.end_row))
|
||||||
|
+ " to ("
|
||||||
|
+ std::to_string(dest.start_col) + ", "
|
||||||
|
+ std::to_string(dest.start_row) + ", "
|
||||||
|
+ std::to_string(dest.end_col) + ", "
|
||||||
|
+ std::to_string(dest.end_row) + ") "
|
||||||
|
+ "size: " + std::to_string((dest.start_col - dest.end_col) * (dest.start_row - dest.end_row)));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PtyWindow::handlerMoveCursor(VTermPos pos, VTermPos oldpos, int visible)
|
||||||
|
{
|
||||||
|
/// @todo maybe use `mvcur()` instead?
|
||||||
|
cursorX = pos.col;
|
||||||
|
cursorY = pos.row;
|
||||||
|
refresh();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PtyWindow::handlerSetTermProp(VTermProp prop, VTermValue *val)
|
||||||
|
{
|
||||||
|
/// @todo maybe use "vterm_get_prop_type() —> bool, number, string"?
|
||||||
|
__debug_stringify_switch_begin(handlerSetTermProp, prop, val);
|
||||||
|
__debug_stringify_switch_case(VTERM_PROP_CURSORVISIBLE);
|
||||||
|
__debug_stringify_switch_case(VTERM_PROP_CURSORBLINK);
|
||||||
|
__debug_stringify_switch_case(VTERM_PROP_ALTSCREEN);
|
||||||
|
__debug_stringify_switch_case(VTERM_PROP_REVERSE);
|
||||||
|
__debug_stringify_switch_case_end_bool(val->boolean);
|
||||||
|
__debug_stringify_switch_case(VTERM_PROP_TITLE);
|
||||||
|
__debug_stringify_switch_case(VTERM_PROP_ICONNAME);
|
||||||
|
__debug_stringify_switch_case_end_string(val->string);
|
||||||
|
__debug_stringify_switch_case(VTERM_PROP_CURSORSHAPE);
|
||||||
|
__debug_stringify_switch_case(VTERM_PROP_MOUSE);
|
||||||
|
__debug_stringify_switch_case_end_number(val->number);
|
||||||
|
__debug_stringify_switch_end(prop);
|
||||||
|
|
||||||
|
__debug_log(std::string("unimplemented handler called: ")
|
||||||
|
+ __debug_stringify_get_string(handlerSetTermProp)
|
||||||
|
);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PtyWindow::handlerBell()
|
||||||
|
{
|
||||||
|
beep();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PtyWindow::handlerResize(int rows, int cols)
|
||||||
|
{
|
||||||
|
__debug_log("unimplemented handler called");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PtyWindow::handlerPushLine(int cols, const VTermScreenCell *cells)
|
||||||
|
{
|
||||||
|
__debug_log("(unimplemented) push line with " + std::to_string(cols) + " columns");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PtyWindow::handlerPopLine(int cols, VTermScreenCell *cells)
|
||||||
|
{
|
||||||
|
__debug_log("unimplemented handler called");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
attr_t PtyWindow::extractAttributesFromVTermCell(VTermScreenCell vTermCell)
|
||||||
|
{
|
||||||
|
attr_t result = A_NORMAL;
|
||||||
|
//__debug_log("unimplemented method called");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
short PtyWindow::extractColorFromVTermCell(VTermScreenCell vTermCell)
|
||||||
|
{
|
||||||
|
//__debug_log("unimplemented method called");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PtyWindow::copyPtyCellToNCursesWindow(int x, int y)
|
||||||
|
{
|
||||||
|
VTermPos cellPosition = {y, x};
|
||||||
|
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;
|
||||||
|
|
||||||
|
{
|
||||||
|
lock_guard nCursesLock(*writeToNCursesMutex);
|
||||||
|
setcchar(&converted, &character, formatting, colorPair, NULL);
|
||||||
|
move(cellPosition.row, cellPosition.col);
|
||||||
|
chgat(1, formatting, colorPair, NULL);
|
||||||
|
add_wch(&converted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int PtyWindow::refresh()
|
||||||
|
{
|
||||||
|
lock_guard nCursesLock(*writeToNCursesMutex);
|
||||||
|
move(cursorY, cursorX);
|
||||||
|
return NCursesWindow::refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @todo potential racing condition where drawing into terminal while
|
||||||
|
/// resizing?
|
||||||
|
int PtyWindow::wresize(int rows, int cols)
|
||||||
|
{
|
||||||
|
lock_guard nCursesLock(*writeToNCursesMutex);
|
||||||
|
lock_guard writeLock(writeToPseudoTerminalMutex);
|
||||||
|
winsize windowSize =
|
||||||
|
{
|
||||||
|
.ws_row = narrow<unsigned short>(rows)
|
||||||
|
, .ws_col = narrow<unsigned short>(cols)
|
||||||
|
};
|
||||||
|
ioctl(fdPtyHost, TIOCSWINSZ, &windowSize);
|
||||||
|
vterm_set_size(pseudoTerminal, rows, cols);
|
||||||
|
|
||||||
|
return NCursesWindow::wresize(rows, cols);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PtyWindow::staticHandlerDamage(VTermRect rect, void *user)
|
||||||
|
{
|
||||||
|
PtyWindow *instance = static_cast<PtyWindow *>(user);
|
||||||
|
return instance->handlerDamage(rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PtyWindow::staticHandlerMoveRect(VTermRect dest, VTermRect src, void *user)
|
||||||
|
{
|
||||||
|
PtyWindow *instance = static_cast<PtyWindow *>(user);
|
||||||
|
return instance->handlerMoveRect(dest, src);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PtyWindow::staticHandlerMoveCursor(VTermPos pos, VTermPos oldpos, int visible, void *user)
|
||||||
|
{
|
||||||
|
PtyWindow *instance = static_cast<PtyWindow *>(user);
|
||||||
|
return instance->handlerMoveCursor(pos, oldpos, visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PtyWindow::staticHandlerSetTermProp(VTermProp prop, VTermValue *val, void *user)
|
||||||
|
{
|
||||||
|
PtyWindow *instance = static_cast<PtyWindow *>(user);
|
||||||
|
return instance->handlerSetTermProp(prop, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PtyWindow::staticHandlerBell(void *user)
|
||||||
|
{
|
||||||
|
PtyWindow *instance = static_cast<PtyWindow *>(user);
|
||||||
|
return instance->handlerBell();
|
||||||
|
}
|
||||||
|
|
||||||
|
int PtyWindow::staticHandlerResize(int rows, int cols, void *user)
|
||||||
|
{
|
||||||
|
PtyWindow *instance = static_cast<PtyWindow *>(user);
|
||||||
|
return instance->handlerResize(rows, cols);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PtyWindow::staticHandlerPushLine(int cols, const VTermScreenCell *cells, void *user)
|
||||||
|
{
|
||||||
|
PtyWindow *instance = static_cast<PtyWindow *>(user);
|
||||||
|
return instance->handlerPushLine(cols, cells);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PtyWindow::staticHandlerPopLine(int cols, VTermScreenCell *cells, void *user)
|
||||||
|
{
|
||||||
|
PtyWindow *instance = static_cast<PtyWindow *>(user);
|
||||||
|
return instance->handlerPopLine(cols, cells);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PtyWindow::staticHandlerOutput(const char *s, size_t len, void *user)
|
||||||
|
{
|
||||||
|
PtyWindow *instance = static_cast<PtyWindow *>(user);
|
||||||
|
__debug_log("output handler writing to client: '" + __debug_make_bytes_printable(std::string(s, len)) + "'");
|
||||||
|
instance->writeToClient(s, len);
|
||||||
|
}
|
||||||
|
}
|
327
Window.cpp
327
Window.cpp
|
@ -3,84 +3,31 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <NCursesPtyWindow/Window.hpp>
|
#include <NCursesPtyWindow/Window.hpp>
|
||||||
#include "Debug.hpp"
|
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/select.h>
|
|
||||||
#include <gsl/gsl>
|
|
||||||
#include <cctype>
|
|
||||||
#include <termios.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
namespace krikkel::NCursesPtyWindow
|
namespace krikkel::NCursesPtyWindow
|
||||||
{
|
{
|
||||||
using gsl::narrow;
|
Window::Window(int lines, int columns, int y, int x)
|
||||||
using std::lock_guard;
|
: NCursesWindow(lines, columns, y, x)
|
||||||
|
{}
|
||||||
|
|
||||||
Window::Window(std::mutex *writeToNCursesMutex, int lines, int columns, int y, int x)
|
int Window::addnwstr(const wchar_t *wstr, int n)
|
||||||
: writeToNCursesMutex(writeToNCursesMutex), NCursesWindow(lines, columns, y, x)
|
|
||||||
{
|
{
|
||||||
// to get the original terminal we need to shutdown ncurses for a moment
|
return ::waddnwstr(w, wstr, n);
|
||||||
/// @todo maybe try `reset_prog_mode()` and `reset_shell_mode()` instead
|
|
||||||
::endwin();
|
|
||||||
tcgetattr(STDIN_FILENO, &terminalParameters);
|
|
||||||
::refresh();
|
|
||||||
|
|
||||||
winsize windowSize =
|
|
||||||
{
|
|
||||||
.ws_row = narrow<short unsigned int>(this->height())
|
|
||||||
, .ws_col = narrow<short unsigned int>(this->width())
|
|
||||||
};
|
|
||||||
openpty(&fdPtyHost, &fdPtyClient, NULL, &terminalParameters, &windowSize);
|
|
||||||
|
|
||||||
pseudoTerminal = vterm_new(windowSize.ws_row, windowSize.ws_col);
|
|
||||||
vterm_set_utf8(pseudoTerminal, true);
|
|
||||||
pseudoTerminalScreen = vterm_obtain_screen(pseudoTerminal);
|
|
||||||
vterm_screen_reset(pseudoTerminalScreen, true);
|
|
||||||
vterm_screen_set_callbacks(pseudoTerminalScreen, &screenCallbacks, this);
|
|
||||||
vterm_output_set_callback(pseudoTerminal, &staticHandlerOutput, this);
|
|
||||||
vterm_screen_enable_altscreen(pseudoTerminalScreen, true);
|
|
||||||
|
|
||||||
//raw(); //— cbreak might suffice
|
|
||||||
//noecho(); — already set
|
|
||||||
//nodelay(true); — @todo needs some reprogramming
|
|
||||||
keypad(true);
|
|
||||||
nonl();
|
|
||||||
|
|
||||||
/// @todo block all signals, this thread does not handle any
|
|
||||||
readPtyClientThread =
|
|
||||||
std::thread(&Window::readFromPtyClientThreadMethod, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::~Window()
|
int Window::add_wch(const cchar_t *character)
|
||||||
{
|
{
|
||||||
close(fdPtyHost);
|
return ::wadd_wch(w, character);
|
||||||
close(fdPtyClient);
|
|
||||||
vterm_free(pseudoTerminal);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Window::getFdPtyClient() const
|
int Window::ins_wch(const cchar_t *character)
|
||||||
{
|
{
|
||||||
return fdPtyClient;
|
return ::wins_wch(w, character);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::writeToClient(const char *output, size_t length)
|
int Window::get_wch(wint_t *character)
|
||||||
{
|
{
|
||||||
lock_guard writeLock(writeToPseudoTerminalMutex);
|
return ::wget_wch(w, character);
|
||||||
write(fdPtyHost, output, length);
|
|
||||||
__debug_log("written to PTY client: '" + __debug_make_bytes_printable(std::string(output, length)) + '\'');
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::writeUnicodeCharToClient(wint_t character)
|
|
||||||
{
|
|
||||||
vterm_keyboard_unichar(pseudoTerminal, character, VTERM_MOD_NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::writeKeyToClient(VTermKey key)
|
|
||||||
{
|
|
||||||
__debug_log("writing key: " + std::to_string(key));
|
|
||||||
vterm_keyboard_key(pseudoTerminal, key, VTERM_MOD_NONE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SingleUserInput Window::readSingleUserInput()
|
SingleUserInput Window::readSingleUserInput()
|
||||||
|
@ -90,256 +37,4 @@ namespace krikkel::NCursesPtyWindow
|
||||||
return SingleUserInput(result, input);
|
return SingleUserInput(result, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::readFromPtyClientThreadMethod()
|
|
||||||
{
|
|
||||||
/// @todo in theory, there is no need for a timeout or select …
|
|
||||||
/// file descriptor is blocking
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
readFromPtyClient();
|
|
||||||
struct timeval timeout = { .tv_sec = 0, .tv_usec = 200000 };
|
|
||||||
fd_set readFds;
|
|
||||||
|
|
||||||
FD_ZERO(&readFds);
|
|
||||||
FD_SET(fdPtyHost, &readFds);
|
|
||||||
if(select(fdPtyHost + 1, &readFds, NULL, NULL, &timeout) < 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::readFromPtyClient()
|
|
||||||
{
|
|
||||||
size_t bytesRead = read(fdPtyHost, ptyClientOutputBuffer, PTY_CLIENT_OUTPUT_BUFFER_SIZE);
|
|
||||||
if(bytesRead != -1 && bytesRead != 0)
|
|
||||||
{
|
|
||||||
lock_guard writeLock(writeToPseudoTerminalMutex);
|
|
||||||
vterm_input_write(pseudoTerminal, ptyClientOutputBuffer, bytesRead);
|
|
||||||
}
|
|
||||||
__debug_log("read from PTY client: '" + __debug_make_bytes_printable(std::string(ptyClientOutputBuffer, bytesRead)) + '\'');
|
|
||||||
}
|
|
||||||
|
|
||||||
VTermScreenCallbacks Window::screenCallbacks =
|
|
||||||
{
|
|
||||||
.damage = staticHandlerDamage,
|
|
||||||
.moverect = staticHandlerMoveRect,
|
|
||||||
.movecursor = staticHandlerMoveCursor,
|
|
||||||
.settermprop = staticHandlerSetTermProp,
|
|
||||||
.bell = staticHandlerBell,
|
|
||||||
.resize = staticHandlerResize,
|
|
||||||
.sb_pushline = staticHandlerPushLine,
|
|
||||||
.sb_popline = staticHandlerPopLine,
|
|
||||||
};
|
|
||||||
|
|
||||||
int Window::handlerDamage(VTermRect rect)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
|
|
||||||
refresh();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Window::handlerMoveRect(VTermRect dest, VTermRect src)
|
|
||||||
{
|
|
||||||
__debug_log("(unimplemented) move content in rectangle from ("
|
|
||||||
+ std::to_string(src.start_col) + ", "
|
|
||||||
+ std::to_string(src.start_row) + ", "
|
|
||||||
+ std::to_string(src.end_col) + ", "
|
|
||||||
+ std::to_string(src.end_row) + ") "
|
|
||||||
+ "size: " + std::to_string((src.start_col - src.end_col) * (src.start_row - src.end_row))
|
|
||||||
+ " to ("
|
|
||||||
+ std::to_string(dest.start_col) + ", "
|
|
||||||
+ std::to_string(dest.start_row) + ", "
|
|
||||||
+ std::to_string(dest.end_col) + ", "
|
|
||||||
+ std::to_string(dest.end_row) + ") "
|
|
||||||
+ "size: " + std::to_string((dest.start_col - dest.end_col) * (dest.start_row - dest.end_row)));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Window::handlerMoveCursor(VTermPos pos, VTermPos oldpos, int visible)
|
|
||||||
{
|
|
||||||
/// @todo maybe use `mvcur()` instead?
|
|
||||||
cursorX = pos.col;
|
|
||||||
cursorY = pos.row;
|
|
||||||
refresh();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Window::handlerSetTermProp(VTermProp prop, VTermValue *val)
|
|
||||||
{
|
|
||||||
/// @todo maybe use "vterm_get_prop_type() —> bool, number, string"?
|
|
||||||
__debug_stringify_switch_begin(handlerSetTermProp, prop, val);
|
|
||||||
__debug_stringify_switch_case(VTERM_PROP_CURSORVISIBLE);
|
|
||||||
__debug_stringify_switch_case(VTERM_PROP_CURSORBLINK);
|
|
||||||
__debug_stringify_switch_case(VTERM_PROP_ALTSCREEN);
|
|
||||||
__debug_stringify_switch_case(VTERM_PROP_REVERSE);
|
|
||||||
__debug_stringify_switch_case_end_bool(val->boolean);
|
|
||||||
__debug_stringify_switch_case(VTERM_PROP_TITLE);
|
|
||||||
__debug_stringify_switch_case(VTERM_PROP_ICONNAME);
|
|
||||||
__debug_stringify_switch_case_end_string(val->string);
|
|
||||||
__debug_stringify_switch_case(VTERM_PROP_CURSORSHAPE);
|
|
||||||
__debug_stringify_switch_case(VTERM_PROP_MOUSE);
|
|
||||||
__debug_stringify_switch_case_end_number(val->number);
|
|
||||||
__debug_stringify_switch_end(prop);
|
|
||||||
|
|
||||||
__debug_log(std::string("unimplemented handler called: ")
|
|
||||||
+ __debug_stringify_get_string(handlerSetTermProp)
|
|
||||||
);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Window::handlerBell()
|
|
||||||
{
|
|
||||||
beep();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Window::handlerResize(int rows, int cols)
|
|
||||||
{
|
|
||||||
__debug_log("unimplemented handler called");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Window::handlerPushLine(int cols, const VTermScreenCell *cells)
|
|
||||||
{
|
|
||||||
__debug_log("(unimplemented) push line with " + std::to_string(cols) + " columns");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Window::handlerPopLine(int cols, VTermScreenCell *cells)
|
|
||||||
{
|
|
||||||
__debug_log("unimplemented handler called");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
attr_t Window::extractAttributesFromVTermCell(VTermScreenCell vTermCell)
|
|
||||||
{
|
|
||||||
attr_t result = A_NORMAL;
|
|
||||||
//__debug_log("unimplemented method called");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
short Window::extractColorFromVTermCell(VTermScreenCell vTermCell)
|
|
||||||
{
|
|
||||||
//__debug_log("unimplemented method called");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::copyPtyCellToNCursesWindow(int x, int y)
|
|
||||||
{
|
|
||||||
VTermPos cellPosition = {y, x};
|
|
||||||
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;
|
|
||||||
|
|
||||||
{
|
|
||||||
lock_guard nCursesLock(*writeToNCursesMutex);
|
|
||||||
setcchar(&converted, &character, formatting, colorPair, NULL);
|
|
||||||
move(cellPosition.row, cellPosition.col);
|
|
||||||
chgat(1, formatting, colorPair, NULL);
|
|
||||||
add_wch(&converted);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int Window::add_wch(const cchar_t *character)
|
|
||||||
{
|
|
||||||
return ::wadd_wch(w, character);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Window::get_wch(wint_t *character)
|
|
||||||
{
|
|
||||||
return ::wget_wch(w, character);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Window::refresh()
|
|
||||||
{
|
|
||||||
lock_guard nCursesLock(*writeToNCursesMutex);
|
|
||||||
move(cursorY, cursorX);
|
|
||||||
return NCursesWindow::refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @todo potential racing condition where drawing into terminal while
|
|
||||||
/// resizing?
|
|
||||||
int Window::wresize(int rows, int cols)
|
|
||||||
{
|
|
||||||
lock_guard nCursesLock(*writeToNCursesMutex);
|
|
||||||
lock_guard writeLock(writeToPseudoTerminalMutex);
|
|
||||||
winsize windowSize =
|
|
||||||
{
|
|
||||||
.ws_row = narrow<unsigned short>(rows)
|
|
||||||
, .ws_col = narrow<unsigned short>(cols)
|
|
||||||
};
|
|
||||||
ioctl(fdPtyHost, TIOCSWINSZ, &windowSize);
|
|
||||||
vterm_set_size(pseudoTerminal, rows, cols);
|
|
||||||
|
|
||||||
return NCursesWindow::wresize(rows, cols);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Window::staticHandlerDamage(VTermRect rect, void *user)
|
|
||||||
{
|
|
||||||
Window *instance = static_cast<Window *>(user);
|
|
||||||
return instance->handlerDamage(rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Window::staticHandlerMoveRect(VTermRect dest, VTermRect src, void *user)
|
|
||||||
{
|
|
||||||
Window *instance = static_cast<Window *>(user);
|
|
||||||
return instance->handlerMoveRect(dest, src);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Window::staticHandlerMoveCursor(VTermPos pos, VTermPos oldpos, int visible, void *user)
|
|
||||||
{
|
|
||||||
Window *instance = static_cast<Window *>(user);
|
|
||||||
return instance->handlerMoveCursor(pos, oldpos, visible);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Window::staticHandlerSetTermProp(VTermProp prop, VTermValue *val, void *user)
|
|
||||||
{
|
|
||||||
Window *instance = static_cast<Window *>(user);
|
|
||||||
return instance->handlerSetTermProp(prop, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Window::staticHandlerBell(void *user)
|
|
||||||
{
|
|
||||||
Window *instance = static_cast<Window *>(user);
|
|
||||||
return instance->handlerBell();
|
|
||||||
}
|
|
||||||
|
|
||||||
int Window::staticHandlerResize(int rows, int cols, void *user)
|
|
||||||
{
|
|
||||||
Window *instance = static_cast<Window *>(user);
|
|
||||||
return instance->handlerResize(rows, cols);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Window::staticHandlerPushLine(int cols, const VTermScreenCell *cells, void *user)
|
|
||||||
{
|
|
||||||
Window *instance = static_cast<Window *>(user);
|
|
||||||
return instance->handlerPushLine(cols, cells);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Window::staticHandlerPopLine(int cols, VTermScreenCell *cells, void *user)
|
|
||||||
{
|
|
||||||
Window *instance = static_cast<Window *>(user);
|
|
||||||
return instance->handlerPopLine(cols, cells);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::staticHandlerOutput(const char *s, size_t len, void *user)
|
|
||||||
{
|
|
||||||
Window *instance = static_cast<Window *>(user);
|
|
||||||
__debug_log("output handler writing to client: '" + __debug_make_bytes_printable(std::string(s, len)) + "'");
|
|
||||||
instance->writeToClient(s, len);
|
|
||||||
}
|
|
||||||
}
|
}
|
76
include/NCursesPtyWindow/PtyWindow.hpp
Normal file
76
include/NCursesPtyWindow/PtyWindow.hpp
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
/**
|
||||||
|
* @brief `ncurses` window displaying contents of a pseudo terminal
|
||||||
|
* @author Christian Burger (christian@krikkel.de)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __WINDOW_H__
|
||||||
|
#define __WINDOW_H__
|
||||||
|
|
||||||
|
#include "SingleUserInput.hpp"
|
||||||
|
#include "Window.hpp"
|
||||||
|
|
||||||
|
#include <cursesw.h>
|
||||||
|
#include <pty.h>
|
||||||
|
#include <vterm.h>
|
||||||
|
#include <string>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
namespace krikkel::NCursesPtyWindow
|
||||||
|
{
|
||||||
|
class PtyWindow : public Window
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PtyWindow(std::mutex *writeToNCursesMutex, int lines, int columns, int y, int x);
|
||||||
|
~PtyWindow();
|
||||||
|
|
||||||
|
int getFdPtyClient() const;
|
||||||
|
void writeToClient(const char * string, size_t length);
|
||||||
|
void writeUnicodeCharToClient(wint_t character);
|
||||||
|
void writeKeyToClient(VTermKey key);
|
||||||
|
|
||||||
|
int refresh() override;
|
||||||
|
int wresize(int rows, int cols);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int fdPtyHost, fdPtyClient;
|
||||||
|
struct termios terminalParameters;
|
||||||
|
VTerm *pseudoTerminal;
|
||||||
|
std::mutex writeToPseudoTerminalMutex;
|
||||||
|
std::mutex *writeToNCursesMutex;
|
||||||
|
VTermScreen *pseudoTerminalScreen;
|
||||||
|
static VTermScreenCallbacks screenCallbacks;
|
||||||
|
/// @todo one line is at most 4096 chars long
|
||||||
|
static const uint16_t PTY_CLIENT_OUTPUT_BUFFER_SIZE = 2 * 4096;
|
||||||
|
char ptyClientOutputBuffer[PTY_CLIENT_OUTPUT_BUFFER_SIZE];
|
||||||
|
uint16_t cursorX, cursorY;
|
||||||
|
|
||||||
|
std::thread readPtyClientThread;
|
||||||
|
void readFromPtyClientThreadMethod();
|
||||||
|
void readFromPtyClient();
|
||||||
|
|
||||||
|
int handlerDamage(VTermRect rect);
|
||||||
|
int handlerMoveRect(VTermRect dest, VTermRect src);
|
||||||
|
int handlerMoveCursor(VTermPos pos, VTermPos oldpos, int visible);
|
||||||
|
int handlerSetTermProp(VTermProp prop, VTermValue *val);
|
||||||
|
int handlerBell();
|
||||||
|
int handlerResize(int rows, int cols);
|
||||||
|
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);
|
||||||
|
static int staticHandlerMoveRect(VTermRect dest, VTermRect src, void *user);
|
||||||
|
static int staticHandlerMoveCursor(VTermPos pos, VTermPos oldpos, int visible, void *user);
|
||||||
|
static int staticHandlerSetTermProp(VTermProp prop, VTermValue *val, void *user);
|
||||||
|
static int staticHandlerBell(void *user);
|
||||||
|
static int staticHandlerResize(int rows, int cols, void *user);
|
||||||
|
static int staticHandlerPushLine(int cols, const VTermScreenCell *cells, void *user);
|
||||||
|
static int staticHandlerPopLine(int cols, VTermScreenCell *cells, void *user);
|
||||||
|
static void staticHandlerOutput(const char *s, size_t len, void *user);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif // __WINDOW_H__
|
|
@ -1,28 +1,35 @@
|
||||||
/**
|
/**
|
||||||
* @brief `ncurses` window displaying contents of a pseudo terminal
|
* @brief Providing wide character methods missing in NCursesWindow.
|
||||||
* @author Christian Burger (christian@krikkel.de)
|
* @author Christian Burger (christian@krikkel.de)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __WINDOW_H__
|
#ifndef A2C3FDB7_7A85_4527_BC85_366E14149EB8
|
||||||
#define __WINDOW_H__
|
#define A2C3FDB7_7A85_4527_BC85_366E14149EB8
|
||||||
|
|
||||||
#include "SingleUserInput.hpp"
|
#include "SingleUserInput.hpp"
|
||||||
|
|
||||||
#include <cursesw.h>
|
#include <ncursesw/cursesw.h>
|
||||||
#include <pty.h>
|
|
||||||
#include <vterm.h>
|
#ifdef addnwstr
|
||||||
#include <string>
|
inline int UNDEF(addnwstr)(const wchar_t *wstr, int n) { addnwstr(wstr, n); }
|
||||||
#include <thread>
|
#undef addnwstr
|
||||||
#include <mutex>
|
#define addnwstr UNDEF(addnwstr)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef add_wch
|
#ifdef add_wch
|
||||||
inline void UNDEF(add_wch)(const cchar_t *character) { add_wch(character); }
|
inline int UNDEF(add_wch)(const cchar_t *character) { add_wch(character); }
|
||||||
#undef add_wch
|
#undef add_wch
|
||||||
#define add_wch UNDEF(add_wch)
|
#define add_wch UNDEF(add_wch)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ins_wch
|
||||||
|
inline int UNDEF(ins_wch)(cchar_t *character) { ins_wch(character); }
|
||||||
|
#undef ins_wch
|
||||||
|
#define ins_wch UNDEF(ins_wch)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef get_wch
|
#ifdef get_wch
|
||||||
inline void UNDEF(get_wch)(wint_t *character) { get_wch(character); }
|
inline int UNDEF(get_wch)(wint_t *character) { get_wch(character); }
|
||||||
#undef get_wch
|
#undef get_wch
|
||||||
#define get_wch UNDEF(get_wch)
|
#define get_wch UNDEF(get_wch)
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,60 +39,14 @@ namespace krikkel::NCursesPtyWindow
|
||||||
class Window : public NCursesWindow
|
class Window : public NCursesWindow
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Window(std::mutex *writeToNCursesMutex, int lines, int columns, int y, int x);
|
Window(int lines, int columns, int y, int x);
|
||||||
~Window();
|
int addnwstr(const wchar_t *wstr, int n);
|
||||||
|
int add_wch(const cchar_t *character);
|
||||||
int getFdPtyClient() const;
|
int ins_wch(const cchar_t *character);
|
||||||
void writeToClient(const char * string, size_t length);
|
int get_wch(wint_t *character);
|
||||||
void writeUnicodeCharToClient(wint_t character);
|
|
||||||
void writeKeyToClient(VTermKey key);
|
|
||||||
|
|
||||||
SingleUserInput readSingleUserInput();
|
SingleUserInput readSingleUserInput();
|
||||||
|
|
||||||
int add_wch(const cchar_t *character);
|
|
||||||
int get_wch(wint_t *character);
|
|
||||||
int refresh() override;
|
|
||||||
int wresize(int rows, int cols);
|
|
||||||
|
|
||||||
private:
|
|
||||||
int fdPtyHost, fdPtyClient;
|
|
||||||
struct termios terminalParameters;
|
|
||||||
VTerm *pseudoTerminal;
|
|
||||||
std::mutex writeToPseudoTerminalMutex;
|
|
||||||
std::mutex *writeToNCursesMutex;
|
|
||||||
VTermScreen *pseudoTerminalScreen;
|
|
||||||
static VTermScreenCallbacks screenCallbacks;
|
|
||||||
/// @todo one line is at most 4096 chars long
|
|
||||||
static const uint16_t PTY_CLIENT_OUTPUT_BUFFER_SIZE = 2 * 4096;
|
|
||||||
char ptyClientOutputBuffer[PTY_CLIENT_OUTPUT_BUFFER_SIZE];
|
|
||||||
uint16_t cursorX, cursorY;
|
|
||||||
|
|
||||||
std::thread readPtyClientThread;
|
|
||||||
void readFromPtyClientThreadMethod();
|
|
||||||
void readFromPtyClient();
|
|
||||||
|
|
||||||
int handlerDamage(VTermRect rect);
|
|
||||||
int handlerMoveRect(VTermRect dest, VTermRect src);
|
|
||||||
int handlerMoveCursor(VTermPos pos, VTermPos oldpos, int visible);
|
|
||||||
int handlerSetTermProp(VTermProp prop, VTermValue *val);
|
|
||||||
int handlerBell();
|
|
||||||
int handlerResize(int rows, int cols);
|
|
||||||
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);
|
|
||||||
static int staticHandlerMoveRect(VTermRect dest, VTermRect src, void *user);
|
|
||||||
static int staticHandlerMoveCursor(VTermPos pos, VTermPos oldpos, int visible, void *user);
|
|
||||||
static int staticHandlerSetTermProp(VTermProp prop, VTermValue *val, void *user);
|
|
||||||
static int staticHandlerBell(void *user);
|
|
||||||
static int staticHandlerResize(int rows, int cols, void *user);
|
|
||||||
static int staticHandlerPushLine(int cols, const VTermScreenCell *cells, void *user);
|
|
||||||
static int staticHandlerPopLine(int cols, VTermScreenCell *cells, void *user);
|
|
||||||
static void staticHandlerOutput(const char *s, size_t len, void *user);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif // __WINDOW_H__
|
|
||||||
|
#endif /* A2C3FDB7_7A85_4527_BC85_366E14149EB8 */
|
||||||
|
|
Loading…
Reference in a new issue