Elimination of unnecessary terminal flushes

This commit is contained in:
Markus Gans 2020-11-04 16:19:02 +01:00
parent 63672a28d5
commit 1d3522f35b
20 changed files with 170 additions and 114 deletions

View File

@ -1,3 +1,6 @@
2020-11-04 Markus Gans <guru.mail@muenster.de>
* Elimination of unnecessary terminal flushes
2020-11-03 Markus Gans <guru.mail@muenster.de> 2020-11-03 Markus Gans <guru.mail@muenster.de>
* Use FIONREAD to get the number of characters available * Use FIONREAD to get the number of characters available
for reading on stdin for reading on stdin

View File

@ -521,6 +521,9 @@ void MouseDraw::drawCanvas()
} }
printarea->has_changes = true; printarea->has_changes = true;
if ( updateTerminal() )
flush();
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------

View File

@ -73,6 +73,7 @@ FMouseControl* FApplication::mouse {nullptr}; // mouse control
int FApplication::loop_level {0}; // event loop level int FApplication::loop_level {0}; // event loop level
int FApplication::quit_code {EXIT_SUCCESS}; int FApplication::quit_code {EXIT_SUCCESS};
bool FApplication::quit_now {false}; bool FApplication::quit_now {false};
bool FApplication::pending_updates {false};
uInt64 FApplication::next_event_wait {5000}; // 5 ms (200 Hz) uInt64 FApplication::next_event_wait {5000}; // 5 ms (200 Hz)
struct timeval FApplication::time_last_event {}; struct timeval FApplication::time_last_event {};
@ -845,7 +846,6 @@ void FApplication::queuingKeyboardInput() const
findKeyboardWidget(); findKeyboardWidget();
keyboard->escapeKeyHandling(); // special case: Esc key keyboard->escapeKeyHandling(); // special case: Esc key
keyboard->clearKeyBufferOnTimeout(); keyboard->clearKeyBufferOnTimeout();
std::fflush(stdout);
if ( isKeyPressed() ) if ( isKeyPressed() )
keyboard->fetchKeyCode(); keyboard->fetchKeyCode();
@ -1234,11 +1234,18 @@ void FApplication::sendWheelEvent ( const FMouseData& md
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline void FApplication::flushTerminal() inline void FApplication::flushTerminal()
{ {
if ( flush_count == 0 || flush_count % 4 != 0 ) if ( ! pending_updates )
return; return;
if ( flush_count < 4 )
{
flush_count++;
return;
}
flush(); flush();
flush_count = 0; flush_count = 0;
pending_updates = false;
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -1321,9 +1328,11 @@ bool FApplication::processNextEvent()
processMouseEvent(); processMouseEvent();
processResizeEvent(); processResizeEvent();
processCloseWidget(); processCloseWidget();
processTerminalUpdate(); // after terminal changes
if ( processTerminalUpdate() ) // after terminal changes
pending_updates = true;
flushTerminal(); flushTerminal();
flush_count++;
processLogger(); processLogger();
} }

View File

@ -270,7 +270,9 @@ void FDialog::setPos (const FPoint& pos, bool)
restoreOverlaidWindows(); restoreOverlaidWindows();
FWindow::adjustSize(); FWindow::adjustSize();
setCursorToFocusWidget(); setCursorToFocusWidget();
updateTerminal();
if ( updateTerminal() )
flush();
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------

View File

@ -467,15 +467,13 @@ FKey FKeyboard::UTF8decode (const char utf8[]) const
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline ssize_t FKeyboard::readKey() inline ssize_t FKeyboard::readKey()
{ {
setNonBlockingInput();
int len{0}; int len{0};
if ( ioctl(FTermios::getStdIn(), FIONREAD, &len) >= 0 && len > int(FIFO_BUF_SIZE) ) if ( ioctl(FTermios::getStdIn(), FIONREAD, &len) < 0 || len == 0 )
len = int(FIFO_BUF_SIZE); return 0;
else
len = 1;
const ssize_t bytes = read(FTermios::getStdIn(), &read_character, std::size_t(len)); setNonBlockingInput();
const ssize_t bytes = read(FTermios::getStdIn(), &read_character, 1);
unsetNonBlockingInput(); unsetNonBlockingInput();
return bytes; return bytes;
} }
@ -492,7 +490,7 @@ void FKeyboard::parseKeyBuffer()
if ( bytesread + fifo_offset <= int(FIFO_BUF_SIZE) ) if ( bytesread + fifo_offset <= int(FIFO_BUF_SIZE) )
{ {
fifo_buf[fifo_offset] = char(read_character); fifo_buf[fifo_offset] = read_character;
fifo_offset++; fifo_offset++;
fifo_in_use = true; fifo_in_use = true;
} }
@ -527,8 +525,6 @@ void FKeyboard::parseKeyBuffer()
if ( fkey_queue.size() >= MAX_QUEUE_SIZE ) if ( fkey_queue.size() >= MAX_QUEUE_SIZE )
break; break;
} }
read_character = 0;
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------

View File

@ -357,7 +357,9 @@ void FLineEdit::onKeyPress (FKeyEvent* ev)
&& key != fc::Fkey_enter ) && key != fc::Fkey_enter )
{ {
drawInputField(); drawInputField();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
} }
} }
@ -397,7 +399,9 @@ void FLineEdit::onMouseDown (FMouseEvent* ev)
adjustTextOffset(); adjustTextOffset();
drawInputField(); drawInputField();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
} }
} }
@ -431,7 +435,9 @@ void FLineEdit::onMouseMove (FMouseEvent* ev)
adjustTextOffset(); adjustTextOffset();
drawInputField(); drawInputField();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
} }
// auto-scrolling when dragging mouse outside the widget // auto-scrolling when dragging mouse outside the widget
@ -534,7 +540,9 @@ void FLineEdit::onTimer (FTimerEvent*)
adjustTextOffset(); adjustTextOffset();
drawInputField(); drawInputField();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------

View File

@ -352,7 +352,8 @@ void FListBox::onMouseDown (FMouseEvent* ev)
if ( yoffset_before != yoffset ) if ( yoffset_before != yoffset )
vbar->drawBar(); vbar->drawBar();
processTerminalUpdate(); if ( processTerminalUpdate() )
flush();
} }
} }
@ -425,7 +426,7 @@ void FListBox::onMouseMove (FMouseEvent* ev)
if ( yoffset_before != yoffset ) if ( yoffset_before != yoffset )
vbar->drawBar(); vbar->drawBar();
processTerminalUpdate(); if ( processTerminalUpdate() )
flush(); flush();
} }
@ -503,7 +504,8 @@ void FListBox::onTimer (FTimerEvent*)
if ( yoffset_before != yoffset ) if ( yoffset_before != yoffset )
vbar->drawBar(); vbar->drawBar();
processTerminalUpdate(); if ( processTerminalUpdate() )
flush();
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -545,7 +547,8 @@ void FListBox::onWheel (FWheelEvent* ev)
if ( yoffset_before != yoffset ) if ( yoffset_before != yoffset )
vbar->drawBar(); vbar->drawBar();
processTerminalUpdate(); if ( processTerminalUpdate() )
flush();
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -1079,7 +1082,8 @@ inline void FListBox::updateDrawing (bool draw_vbar, bool draw_hbar)
if ( draw_hbar ) if ( draw_hbar )
hbar->drawBar(); hbar->drawBar();
processTerminalUpdate(); if ( processTerminalUpdate() )
flush();
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -1799,7 +1803,8 @@ void FListBox::cb_vbarChange (const FWidget*)
if ( yoffset_before != yoffset ) if ( yoffset_before != yoffset )
vbar->drawBar(); vbar->drawBar();
processTerminalUpdate(); if ( processTerminalUpdate() )
flush();
} }
} }
@ -1867,7 +1872,8 @@ void FListBox::cb_hbarChange (const FWidget*)
if ( xoffset_before != xoffset ) if ( xoffset_before != xoffset )
hbar->drawBar(); hbar->drawBar();
processTerminalUpdate(); if ( processTerminalUpdate() )
flush();
} }
} }

View File

@ -1116,7 +1116,8 @@ void FListView::onMouseDown (FMouseEvent* ev)
if ( first_line_position_before != first_visible_line.getPosition() ) if ( first_line_position_before != first_visible_line.getPosition() )
vbar->drawBar(); vbar->drawBar();
processTerminalUpdate(); if ( processTerminalUpdate() )
flush();
} }
} }
} }
@ -1220,7 +1221,7 @@ void FListView::onMouseMove (FMouseEvent* ev)
if ( first_line_position_before != first_visible_line.getPosition() ) if ( first_line_position_before != first_visible_line.getPosition() )
vbar->drawBar(); vbar->drawBar();
processTerminalUpdate(); if ( processTerminalUpdate() )
flush(); flush();
} }
@ -1307,7 +1308,8 @@ void FListView::onTimer (FTimerEvent*)
if ( first_line_position_before != first_visible_line.getPosition() ) if ( first_line_position_before != first_visible_line.getPosition() )
vbar->drawBar(); vbar->drawBar();
processTerminalUpdate(); if ( processTerminalUpdate() )
flush();
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -1345,7 +1347,8 @@ void FListView::onWheel (FWheelEvent* ev)
if ( first_line_position_before != first_visible_line.getPosition() ) if ( first_line_position_before != first_visible_line.getPosition() )
vbar->drawBar(); vbar->drawBar();
processTerminalUpdate(); if ( processTerminalUpdate() )
flush();
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -2149,7 +2152,8 @@ void FListView::updateDrawing (bool draw_vbar, bool draw_hbar)
if ( draw_hbar ) if ( draw_hbar )
hbar->drawBar(); hbar->drawBar();
processTerminalUpdate(); if ( processTerminalUpdate() )
flush();
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -2868,7 +2872,8 @@ void FListView::cb_vbarChange (const FWidget*)
if ( first_line_position_before != first_visible_line.getPosition() ) if ( first_line_position_before != first_visible_line.getPosition() )
vbar->drawBar(); vbar->drawBar();
processTerminalUpdate(); if ( processTerminalUpdate() )
flush();
} }
} }
@ -2933,7 +2938,8 @@ void FListView::cb_hbarChange (const FWidget*)
if ( xoffset_before != xoffset ) if ( xoffset_before != xoffset )
hbar->drawBar(); hbar->drawBar();
processTerminalUpdate(); if ( processTerminalUpdate() )
flush();
} }
} }

View File

@ -311,7 +311,8 @@ void FMenu::onMouseMove (FMouseEvent* ev)
else if ( ms.hide_sub_menu ) else if ( ms.hide_sub_menu )
{ {
closeOpenedSubMenu(); closeOpenedSubMenu();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush(); flush();
} }
} }

View File

@ -223,8 +223,10 @@ void FMenuBar::onAccel (FAccelEvent* ev)
getStatusBar()->drawMessage(); getStatusBar()->drawMessage();
redraw(); redraw();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush(); flush();
ev->accept(); ev->accept();
} }
@ -920,7 +922,8 @@ void FMenuBar::mouseMoveOverList (const FMouseEvent&& ev)
if ( focus_changed ) if ( focus_changed )
{ {
redraw(); redraw();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush(); flush();
} }
} }

View File

@ -428,8 +428,9 @@ void FMenuItem::onAccel (FAccelEvent* ev)
mbar->drop_down = false; mbar->drop_down = false;
} }
processTerminalUpdate(); if ( processTerminalUpdate() )
flush(); flush();
ev->accept(); ev->accept();
} }

View File

@ -144,6 +144,7 @@ void FProgressbar::draw()
if ( getFlags().shadow ) if ( getFlags().shadow )
drawShadow(this); drawShadow(this);
if ( processTerminalUpdate() )
flush(); flush();
} }

View File

@ -352,7 +352,10 @@ void FScrollbar::onMouseMove (FMouseEvent* ev)
{ {
setValue(new_val); setValue(new_val);
drawBar(); drawBar();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
processScroll(); processScroll();
} }
} }
@ -757,7 +760,10 @@ void FScrollbar::jumpToClickPos (int x, int y)
{ {
setValue(new_val); setValue(new_val);
drawBar(); drawBar();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
scroll_type = FScrollbar::scrollJump; scroll_type = FScrollbar::scrollJump;
processScroll(); processScroll();
} }

View File

@ -411,7 +411,9 @@ void FScrollView::scrollTo (int x, int y)
viewport->has_changes = true; viewport->has_changes = true;
copy2area(); copy2area();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------

View File

@ -184,7 +184,9 @@ void FTextView::scrollTo (int x, int y)
} }
drawText(); drawText();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush();
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -475,7 +477,8 @@ void FTextView::onWheel (FWheelEvent* ev)
if ( isShown() ) if ( isShown() )
drawText(); drawText();
processTerminalUpdate(); if ( processTerminalUpdate() )
flush();
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------

View File

@ -62,7 +62,7 @@ uInt FVTerm::clr_bol_length{};
uInt FVTerm::clr_eol_length{}; uInt FVTerm::clr_eol_length{};
uInt FVTerm::cursor_address_length{}; uInt FVTerm::cursor_address_length{};
struct timeval FVTerm::last_term_size_check{}; struct timeval FVTerm::last_term_size_check{};
std::queue<int>* FVTerm::output_buffer{nullptr}; std::vector<int>* FVTerm::output_buffer{nullptr};
FPoint* FVTerm::term_pos{nullptr}; FPoint* FVTerm::term_pos{nullptr};
const FVTerm* FVTerm::init_object{nullptr}; const FVTerm* FVTerm::init_object{nullptr};
FSystem* FVTerm::fsystem{nullptr}; FSystem* FVTerm::fsystem{nullptr};
@ -266,7 +266,7 @@ void FVTerm::putVTerm() const
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FVTerm::updateTerminal() const bool FVTerm::updateTerminal() const
{ {
// Updates pending changes to the terminal // Updates pending changes to the terminal
@ -275,7 +275,7 @@ void FVTerm::updateTerminal() const
if ( no_terminal_updates || FApplication::isQuit() if ( no_terminal_updates || FApplication::isQuit()
|| ! (hasPendingUpdates(vterm) && draw_completed) ) || ! (hasPendingUpdates(vterm) && draw_completed) )
{ {
return; return false;
} }
std::size_t changedlines = 0; std::size_t changedlines = 0;
@ -287,12 +287,12 @@ void FVTerm::updateTerminal() const
changedlines++; changedlines++;
if ( changedlines % check_interval == 0 if ( changedlines % check_interval == 0
&& (keyboard->hasUnprocessedInput() || keyboard->isKeyPressed(0)) && (keyboard->hasUnprocessedInput() || keyboard->isKeyPressed(0) )
&& skipped_terminal_update <= max_skip ) && skipped_terminal_update <= max_skip )
{ {
// Skipping terminal updates if there is unprocessed inputs // Skipping terminal updates if there is unprocessed inputs
skipped_terminal_update++; skipped_terminal_update++;
return; return false;
} }
} }
@ -301,6 +301,7 @@ void FVTerm::updateTerminal() const
// sets the new input cursor position // sets the new input cursor position
updateTerminalCursor(); updateTerminalCursor();
return changedlines > 0;
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -613,20 +614,18 @@ void FVTerm::flush()
{ {
// Flush the output buffer // Flush the output buffer
if ( ! output_buffer ) if ( ! output_buffer || output_buffer->empty() )
return; return;
while ( ! output_buffer->empty() )
{
static const FTerm::defaultPutChar& FTermPutchar = FTerm::putchar(); static const FTerm::defaultPutChar& FTermPutchar = FTerm::putchar();
if ( FTermPutchar ) if ( ! FTermPutchar )
{ return;
FTermPutchar (output_buffer->front());
output_buffer->pop();
}
}
for (auto&& ch : *output_buffer)
FTermPutchar(ch);
output_buffer->clear();
std::fflush(stdout); std::fflush(stdout);
} }
@ -1263,26 +1262,26 @@ void FVTerm::clearArea (FTermArea* area, int fillchar) const
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FVTerm::processTerminalUpdate() const bool FVTerm::processTerminalUpdate() const
{ {
const auto& data = FTerm::getFTermData(); const auto& data = FTerm::getFTermData();
// Checks if the resizing of the terminal is not finished // Checks if the resizing of the terminal is not finished
if ( data && data->hasTermResized() ) if ( data && data->hasTermResized() )
return; return false;
// Monitor whether the terminal size has changed // Monitor whether the terminal size has changed
if ( isTermSizeChanged() ) if ( isTermSizeChanged() )
{ {
raise (SIGWINCH); // Send SIGWINCH raise (SIGWINCH); // Send SIGWINCH
return; return false;
} }
// Update data on VTerm // Update data on VTerm
updateVTerm(); updateVTerm();
// Update the visible terminal // Update the visible terminal
updateTerminal(); return updateTerminal();
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -1845,7 +1844,7 @@ void FVTerm::init()
{ {
fterm = new FTerm(); fterm = new FTerm();
term_pos = new FPoint(-1, -1); term_pos = new FPoint(-1, -1);
output_buffer = new std::queue<int>; output_buffer = new std::vector<int>;
} }
catch (const std::bad_alloc&) catch (const std::bad_alloc&)
{ {
@ -1857,6 +1856,9 @@ void FVTerm::init()
// The final setting is made later in FTerm::init_locale(). // The final setting is made later in FTerm::init_locale().
std::setlocale (LC_ALL, ""); std::setlocale (LC_ALL, "");
// Reserve memory on the terminal output buffer
output_buffer->reserve(TERMINAL_OUTPUT_BUFFER_SIZE + 256);
// term_attribute stores the current state of the terminal // term_attribute stores the current state of the terminal
term_attribute.ch = '\0'; term_attribute.ch = '\0';
term_attribute.fg_color = fc::Default; term_attribute.fg_color = fc::Default;
@ -3072,23 +3074,17 @@ inline void FVTerm::characterFilter (FChar& next_char)
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline void FVTerm::appendOutputBuffer (const std::string& s) inline void FVTerm::appendOutputBuffer (const std::string& str)
{ {
const auto& c_string = s.c_str(); for (auto&& ch : str)
FTermcap::paddingPrint (c_string, 1, appendOutputBuffer); FVTerm::appendOutputBuffer(int(ch));
}
//----------------------------------------------------------------------
inline void FVTerm::appendOutputBuffer (const char s[])
{
FTermcap::paddingPrint (s, 1, appendOutputBuffer);
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
int FVTerm::appendOutputBuffer (int ch) int FVTerm::appendOutputBuffer (int ch)
{ {
// append method for unicode character // append method for unicode character
output_buffer->push(ch); output_buffer->push_back(ch);
if ( output_buffer->size() >= TERMINAL_OUTPUT_BUFFER_SIZE ) if ( output_buffer->size() >= TERMINAL_OUTPUT_BUFFER_SIZE )
flush(); flush();

View File

@ -981,8 +981,10 @@ void FWidget::show()
if ( show_root_widget && show_root_widget == this ) if ( show_root_widget && show_root_widget == this )
{ {
finishDrawing(); finishDrawing();
processTerminalUpdate();
if ( processTerminalUpdate() )
flush(); flush();
show_root_widget = nullptr; show_root_widget = nullptr;
} }

View File

@ -243,10 +243,10 @@ class FApplication : public FWidget
int flush_count{0}; int flush_count{0};
static uInt64 next_event_wait; static uInt64 next_event_wait;
static timeval time_last_event; static timeval time_last_event;
static int loop_level;
static int quit_code; static int quit_code;
static bool quit_now; static bool quit_now;
static int loop_level; static bool pending_updates;
static bool process_timer_event;
static FMouseControl* mouse; static FMouseControl* mouse;
static FKeyboard* keyboard; static FKeyboard* keyboard;
static FWidget* keyboard_widget; static FWidget* keyboard_widget;

View File

@ -197,7 +197,7 @@ class FKeyboard final
std::queue<FKey> fkey_queue{}; std::queue<FKey> fkey_queue{};
FKey fkey{0}; FKey fkey{0};
FKey key{0}; FKey key{0};
uChar read_character{}; char read_character{};
char fifo_buf[FIFO_BUF_SIZE]{'\0'}; char fifo_buf[FIFO_BUF_SIZE]{'\0'};
int fifo_offset{0}; int fifo_offset{0};
int stdin_status_flags{0}; int stdin_status_flags{0};

View File

@ -50,7 +50,6 @@
#include <sys/time.h> // need for timeval (cygwin) #include <sys/time.h> // need for timeval (cygwin)
#include <queue>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -255,7 +254,7 @@ class FVTerm
void createVTerm (const FSize&); void createVTerm (const FSize&);
void resizeVTerm (const FSize&) const; void resizeVTerm (const FSize&) const;
void putVTerm() const; void putVTerm() const;
void updateTerminal() const; bool updateTerminal() const;
virtual void addPreprocessingHandler ( const FVTerm* virtual void addPreprocessingHandler ( const FVTerm*
, const FPreprocessingFunction& ); , const FPreprocessingFunction& );
virtual void delPreprocessingHandler (const FVTerm*); virtual void delPreprocessingHandler (const FVTerm*);
@ -318,7 +317,7 @@ class FVTerm
void scrollAreaForward (FTermArea*) const; void scrollAreaForward (FTermArea*) const;
void scrollAreaReverse (FTermArea*) const; void scrollAreaReverse (FTermArea*) const;
void clearArea (FTermArea*, int = ' ') const; void clearArea (FTermArea*, int = ' ') const;
void processTerminalUpdate() const; bool processTerminalUpdate() const;
static void startDrawing(); static void startDrawing();
static void finishDrawing(); static void finishDrawing();
virtual void initTerminal(); virtual void initTerminal();
@ -420,7 +419,8 @@ class FVTerm
void appendLowerRight (FChar&) const; void appendLowerRight (FChar&) const;
static void characterFilter (FChar&); static void characterFilter (FChar&);
static void appendOutputBuffer (const std::string&); static void appendOutputBuffer (const std::string&);
static void appendOutputBuffer (const char[]); template <std::size_t N>
static void appendOutputBuffer (const char (&)[N]);
static int appendOutputBuffer (int); static int appendOutputBuffer (int);
// Data members // Data members
@ -433,7 +433,7 @@ class FVTerm
static FTermArea* vterm; // virtual terminal static FTermArea* vterm; // virtual terminal
static FTermArea* vdesktop; // virtual desktop static FTermArea* vdesktop; // virtual desktop
static FTermArea* active_area; // active area static FTermArea* active_area; // active area
static std::queue<int>* output_buffer; static std::vector<int>* output_buffer;
static FChar term_attribute; static FChar term_attribute;
static FChar next_attribute; static FChar next_attribute;
static FChar s_ch; // shadow character static FChar s_ch; // shadow character
@ -988,6 +988,14 @@ inline bool FVTerm::isCursorHideable() const
inline void FVTerm::hideVTermCursor() const inline void FVTerm::hideVTermCursor() const
{ vterm->input_cursor_visible = false; } { vterm->input_cursor_visible = false; }
//----------------------------------------------------------------------
template <std::size_t N>
inline void FVTerm::appendOutputBuffer (const char (&str)[N])
{
for (auto&& ch : str)
FVTerm::appendOutputBuffer(int(ch));
}
} // namespace finalcut } // namespace finalcut
#endif // FVTERM_H #endif // FVTERM_H