Merge pull request #80 from gansm/master

merge
This commit is contained in:
Markus Gans 2020-11-14 22:58:38 +01:00 committed by GitHub
commit c52b22b4a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 4021 additions and 4068 deletions

View File

@ -1,5 +1,11 @@
2019-11-14 Markus Gans <guru.mail@muenster.de>
* Version 0.7.1
* Bugfix: The cursor position was not changed anymore
if there was no change to the content
* Forcing a direct update for faster terminal output
2019-11-07 Markus Gans <guru.mail@muenster.de>
* Version 0.7.0
* Version 0.7.0
2020-11-04 Markus Gans <guru.mail@muenster.de>
* Elimination of unnecessary terminal flushes

View File

@ -2,7 +2,7 @@
# Library for creating terminal applications with text-based widgets
The FINAL CUT is a C++ class library and widget toolkit with full [mouse](doc/mouse-control.md#title-bar-actions-on-mouse-clicks) support for creating a [text-based user interface](https://en.wikipedia.org/wiki/Text-based_user_interface). The library supports the programmer to develop an application for the text console. It allows the simultaneous handling of multiple text windows on the screen.
FINAL CUT is a C++ class library and widget toolkit with full [mouse](doc/mouse-control.md#title-bar-actions-on-mouse-clicks) support for creating a [text-based user interface](https://en.wikipedia.org/wiki/Text-based_user_interface). The library supports the programmer to develop an application for the text console. It allows the simultaneous handling of multiple text windows on the screen.
The structure of the Qt framework was originally the inspiration for the C++ class design of FINAL CUT. It provides common controls like dialog boxes, push buttons, check boxes, radio buttons, input lines, list boxes, status bars and so on.

View File

@ -4,7 +4,7 @@
# Process this file with autoconf to produce a configure script.
AC_INIT([finalcut], [0.7.0])
AC_INIT([finalcut], [0.7.1])
AC_CONFIG_HEADER([config.h])
AX_PREFIX_CONFIG_H([src/include/final/fconfig.h], [F])
AC_CONFIG_SRCDIR([src/fobject.cpp])
@ -64,7 +64,7 @@ LT_OUTPUT
### This defines the version number of the installed .so files
### Update this value for every release! (A:B:C will map to foo.so.(A-C).C.B)
### using libtool's versioning system.
AC_SUBST(SO_VERSION, ["7:0:7"])
AC_SUBST(SO_VERSION, ["7:1:7"])
AC_SUBST([LIBTOOL_DEPS])

6
debian/changelog vendored
View File

@ -1,3 +1,9 @@
finalcut (0.7.1) unstable; urgency=low
* Release (version 0.7.1)
-- Markus Gans <guru.mail@muenster.de> Sat, 14 Nov 2020 20:07:39 +0100
finalcut (0.7.0) unstable; urgency=low
* Release (version 0.7.0)

View File

@ -1 +1 @@
libfinal 0 libfinal0 (>= 0.7.0)
libfinal 0 libfinal0 (>= 0.7.1)

7578
debian/libfinal0.symbols vendored

File diff suppressed because it is too large Load Diff

View File

@ -225,7 +225,7 @@ void RotoZoomer::onShow (finalcut::FShowEvent*)
for (path = 1; path < loops; path++)
{
redraw();
processTerminalUpdate();
forceTerminalUpdate();
}
end = system_clock::now();
@ -244,6 +244,7 @@ void RotoZoomer::onTimer (finalcut::FTimerEvent*)
path++;
redraw();
forceTerminalUpdate();
}
//----------------------------------------------------------------------

View File

@ -1,3 +1,7 @@
-------------------------------------------------------------------
Sat Nov 14 20:13:57 UTC 2020 - Markus Gans <guru.mail@muenster.de>
- Release (version 0.7.1)
-------------------------------------------------------------------
Sat Nov 07 11:24:39 UTC 2020 - Markus Gans <guru.mail@muenster.de>
- Release (version 0.7.0)

View File

@ -1,6 +1,6 @@
sonar.projectKey=gansm_finalcut
sonar.projectName=finalcut
sonar.projectVersion=0.7.0
sonar.projectVersion=0.7.1
sonar.projectDescription=A text-based widget toolkit
#----------------------------------------------------------------------

View File

@ -3,7 +3,7 @@
#-----------------------------------------------------------------------------
# This is where make install will install the library
VERSION = "0.7.0"
VERSION = "0.7.1"
MAJOR := $(shell echo ${VERSION} | cut -d. -f1)
LIBDIR = /usr/local/lib
INCLUDEDIR1 = include/final

View File

@ -3,7 +3,7 @@
#-----------------------------------------------------------------------------
# This is where make install will install the library
VERSION = "0.7.0"
VERSION = "0.7.1"
MAJOR := $(shell echo ${VERSION} | cut -d. -f1)
LIBDIR = /usr/local/lib
INCLUDEDIR1 = include/final

View File

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

View File

@ -352,8 +352,7 @@ void FListBox::onMouseDown (FMouseEvent* ev)
if ( yoffset_before != yoffset )
vbar->drawBar();
if ( processTerminalUpdate() )
flush();
forceTerminalUpdate();
}
}
@ -426,8 +425,7 @@ void FListBox::onMouseMove (FMouseEvent* ev)
if ( yoffset_before != yoffset )
vbar->drawBar();
if ( processTerminalUpdate() )
flush();
forceTerminalUpdate();
}
// Auto-scrolling when dragging mouse outside the widget
@ -504,8 +502,7 @@ void FListBox::onTimer (FTimerEvent*)
if ( yoffset_before != yoffset )
vbar->drawBar();
if ( processTerminalUpdate() )
flush();
forceTerminalUpdate();
}
//----------------------------------------------------------------------
@ -547,8 +544,7 @@ void FListBox::onWheel (FWheelEvent* ev)
if ( yoffset_before != yoffset )
vbar->drawBar();
if ( processTerminalUpdate() )
flush();
forceTerminalUpdate();
}
//----------------------------------------------------------------------
@ -1082,8 +1078,7 @@ inline void FListBox::updateDrawing (bool draw_vbar, bool draw_hbar)
if ( draw_hbar )
hbar->drawBar();
if ( processTerminalUpdate() )
flush();
forceTerminalUpdate();
}
//----------------------------------------------------------------------
@ -1803,8 +1798,7 @@ void FListBox::cb_vbarChange (const FWidget*)
if ( yoffset_before != yoffset )
vbar->drawBar();
if ( processTerminalUpdate() )
flush();
forceTerminalUpdate();
}
}
@ -1872,8 +1866,7 @@ void FListBox::cb_hbarChange (const FWidget*)
if ( xoffset_before != xoffset )
hbar->drawBar();
if ( processTerminalUpdate() )
flush();
forceTerminalUpdate();
}
}

View File

@ -1116,8 +1116,7 @@ void FListView::onMouseDown (FMouseEvent* ev)
if ( first_line_position_before != first_visible_line.getPosition() )
vbar->drawBar();
if ( processTerminalUpdate() )
flush();
forceTerminalUpdate();
}
}
}
@ -1221,8 +1220,7 @@ void FListView::onMouseMove (FMouseEvent* ev)
if ( first_line_position_before != first_visible_line.getPosition() )
vbar->drawBar();
if ( processTerminalUpdate() )
flush();
forceTerminalUpdate();
}
// auto-scrolling when dragging mouse outside the widget
@ -1308,8 +1306,7 @@ void FListView::onTimer (FTimerEvent*)
if ( first_line_position_before != first_visible_line.getPosition() )
vbar->drawBar();
if ( processTerminalUpdate() )
flush();
forceTerminalUpdate();
}
//----------------------------------------------------------------------
@ -1347,8 +1344,7 @@ void FListView::onWheel (FWheelEvent* ev)
if ( first_line_position_before != first_visible_line.getPosition() )
vbar->drawBar();
if ( processTerminalUpdate() )
flush();
forceTerminalUpdate();
}
//----------------------------------------------------------------------
@ -2152,8 +2148,7 @@ void FListView::updateDrawing (bool draw_vbar, bool draw_hbar)
if ( draw_hbar )
hbar->drawBar();
if ( processTerminalUpdate() )
flush();
forceTerminalUpdate();
}
//----------------------------------------------------------------------
@ -2872,8 +2867,7 @@ void FListView::cb_vbarChange (const FWidget*)
if ( first_line_position_before != first_visible_line.getPosition() )
vbar->drawBar();
if ( processTerminalUpdate() )
flush();
forceTerminalUpdate();
}
}
@ -2938,8 +2932,7 @@ void FListView::cb_hbarChange (const FWidget*)
if ( xoffset_before != xoffset )
hbar->drawBar();
if ( processTerminalUpdate() )
flush();
forceTerminalUpdate();
}
}

View File

@ -311,9 +311,7 @@ void FMenu::onMouseMove (FMouseEvent* ev)
else if ( ms.hide_sub_menu )
{
closeOpenedSubMenu();
if ( processTerminalUpdate() )
flush();
forceTerminalUpdate();
}
}
@ -1060,6 +1058,7 @@ bool FMenu::selectNextItem()
getStatusBar()->drawMessage();
redraw();
forceTerminalUpdate();
break;
}
@ -1108,6 +1107,7 @@ bool FMenu::selectPrevItem()
getStatusBar()->drawMessage();
redraw();
forceTerminalUpdate();
break;
}
}

View File

@ -223,10 +223,7 @@ void FMenuBar::onAccel (FAccelEvent* ev)
getStatusBar()->drawMessage();
redraw();
if ( processTerminalUpdate() )
flush();
forceTerminalUpdate();
ev->accept();
}
@ -339,6 +336,7 @@ bool FMenuBar::selectNextItem()
redraw();
setTerminalUpdates (FVTerm::start_terminal_updates);
forceTerminalUpdate();
break;
}
@ -403,6 +401,7 @@ bool FMenuBar::selectPrevItem()
setSelectedItem(prev);
redraw();
setTerminalUpdates (FVTerm::start_terminal_updates);
forceTerminalUpdate();
break;
}
}
@ -922,9 +921,7 @@ void FMenuBar::mouseMoveOverList (const FMouseEvent&& ev)
if ( focus_changed )
{
redraw();
if ( processTerminalUpdate() )
flush();
forceTerminalUpdate();
}
}

View File

@ -417,7 +417,6 @@ void FMenuItem::onAccel (FAccelEvent* ev)
mbar->redraw();
mbar->drop_down = true;
}
else
{
@ -428,9 +427,7 @@ void FMenuItem::onAccel (FAccelEvent* ev)
mbar->drop_down = false;
}
if ( processTerminalUpdate() )
flush();
forceTerminalUpdate();
ev->accept();
}

View File

@ -557,7 +557,7 @@ const char* FOptiAttr::changeAttribute (FChar& term, FChar& next)
// Simulate invisible characters
if ( ! F_enter_secure_mode.cap && next.attr.bit.invisible )
next.encoded_char = ' ';
next.encoded_char[0] = ' ';
// Look for no changes
if ( ! (switchOn() || switchOff() || hasColorChanged(term, next)) )

View File

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

View File

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

View File

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

View File

@ -342,12 +342,6 @@ const FString& FString::operator () () const
// public methods of FString
//----------------------------------------------------------------------
std::size_t FString::getUTF8length() const
{
return length;
}
//----------------------------------------------------------------------
FString FString::clear()
{

View File

@ -158,11 +158,11 @@ const wchar_t ambiguous_width_list[] =
0x25d0, 0x25d1, 0x25d8, 0x25d9, 0x25e2, 0x25e3, 0x25e4, 0x25e5,
0x25ef, 0x2605, 0x2606, 0x2609, 0x260e, 0x260f, 0x2614, 0x2615,
0x261c, 0x261e, 0x2640, 0x2642, 0x2660, 0x2661, 0x2663, 0x2664,
0x2665, 0x2667, 0x2668, 0x2669, 0x266a, 0x266c, 0x266d, 0x266f,
0x273d, 0x2776, 0x2777, 0x2778, 0x2779, 0x277a, 0x277b, 0x277c,
0x277d, 0x277e, 0x277f, 0xfe00, 0xfe01, 0xfe02, 0xfe03, 0xfe04,
0xfe05, 0xfe07, 0xfe09, 0xfe0a, 0xfe0b, 0xfe0c, 0xfe0d, 0xfe0e,
0xfe0f, 0xfffd
0x2665, 0x2666, 0x2667, 0x2668, 0x2669, 0x266a, 0x266c, 0x266d,
0x266f, 0x273d, 0x2776, 0x2777, 0x2778, 0x2779, 0x277a, 0x277b,
0x277c, 0x277d, 0x277e, 0x277f, 0xfe00, 0xfe01, 0xfe02, 0xfe03,
0xfe04, 0xfe05, 0xfe07, 0xfe09, 0xfe0a, 0xfe0b, 0xfe0c, 0xfe0d,
0xfe0e, 0xfe0f, 0xfffd
#if !defined(__CYGWIN__)
, 0xe0100, 0xe0101, 0xe0102, 0xe0103, 0xe0104, 0xe0105, 0xe0106,
0xe0107, 0xe0108, 0xe0109, 0xe010a, 0xe01ef
@ -507,11 +507,11 @@ std::size_t getColumnWidth (const wchar_t wchar)
//----------------------------------------------------------------------
std::size_t getColumnWidth (FChar& term_char)
{
const std::size_t char_width = getColumnWidth(term_char.ch);
const std::size_t char_width = getColumnWidth(term_char.ch[0]);
if ( char_width == 2 && FTerm::getEncoding() != fc::UTF8 )
{
term_char.ch = '.';
term_char.ch[0] = '.';
term_char.attr.bit.char_width = 1;
}
else
@ -526,7 +526,7 @@ std::size_t getColumnWidth (const FTermBuffer& tb)
return std::accumulate ( std::next(tb.begin())
, tb.end()
, tb.front().attr.bit.char_width
, [] (std::size_t s, FChar c)
, [] (std::size_t s, const FChar& c)
{
return std::move(s) + c.attr.bit.char_width;
}

View File

@ -52,7 +52,7 @@ FString FTermBuffer::toString() const
, std::back_inserter(wide_string)
, [] (const FChar& fchar)
{
return fchar.ch;
return fchar.ch[0];
}
);
return wide_string;
@ -68,11 +68,11 @@ int FTermBuffer::write (const FString& string)
{
FChar nc; // next character
nc = FVTerm::getAttribute();
nc.ch = c;
nc.ch[0] = c;
nc.attr.byte[2] = 0;
nc.attr.byte[3] = 0;
getColumnWidth(nc); // add column width
nc.attr.bit.no_changes = false;
nc.attr.bit.printed = false;
data.push_back(nc);
data.push_back(std::move(nc));
}
return len;
@ -82,7 +82,7 @@ int FTermBuffer::write (const FString& string)
int FTermBuffer::write (wchar_t ch)
{
FChar nc = FVTerm::getAttribute(); // next character
nc.ch = ch;
nc.ch[0] = ch;
getColumnWidth(nc); // add column width
nc.attr.bit.no_changes = false;
nc.attr.bit.printed = false;

View File

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

View File

@ -54,6 +54,7 @@ namespace finalcut
bool FVTerm::draw_completed{false};
bool FVTerm::no_terminal_updates{false};
bool FVTerm::cursor_hideable{false};
bool FVTerm::force_terminal_update{false};
int FVTerm::skipped_terminal_update{0};
uInt64 FVTerm::term_size_check_timeout{500000}; // 500 ms
uInt FVTerm::erase_char_length{};
@ -286,9 +287,10 @@ bool FVTerm::updateTerminal() const
if ( updateTerminalLine(y) )
changedlines++;
if ( changedlines % check_interval == 0
if ( ! force_terminal_update
&& changedlines % check_interval == 0
&& (keyboard->hasUnprocessedInput() || keyboard->isKeyPressed(0) )
&& skipped_terminal_update <= max_skip )
&& skipped_terminal_update < max_skip )
{
// Skipping terminal updates if there is unprocessed inputs
skipped_terminal_update++;
@ -300,8 +302,8 @@ bool FVTerm::updateTerminal() const
vterm->has_changes = false;
// sets the new input cursor position
updateTerminalCursor();
return changedlines > 0;
bool cursor_update = updateTerminalCursor();
return cursor_update || changedlines > 0;
}
//----------------------------------------------------------------------
@ -340,49 +342,45 @@ void FVTerm::delPreprocessingHandler (const FVTerm* instance)
}
//----------------------------------------------------------------------
int FVTerm::print (const FString& s)
int FVTerm::print (const FString& string)
{
if ( s.isNull() )
if ( string.isNull() )
return -1;
auto area = getPrintArea();
if ( ! area )
return -1;
return print (area, s);
FTermBuffer term_buffer{};
term_buffer.write(string);
return print (term_buffer);
}
//----------------------------------------------------------------------
int FVTerm::print (FTermArea* area, const FString& s)
int FVTerm::print (FTermArea* area, const FString& string)
{
if ( s.isNull() || ! area )
if ( ! area || string.isNull() )
return -1;
std::vector<FChar> term_string{};
term_string.reserve(s.getLength());
const wchar_t* p = s.wc_str();
FTermBuffer term_buffer{};
term_buffer.write(string);
return print (area, term_buffer);
}
if ( p )
{
while ( *p )
{
FChar nc{}; // next character
nc.ch = *p;
nc.fg_color = next_attribute.fg_color;
nc.bg_color = next_attribute.bg_color;
nc.attr.byte[0] = next_attribute.attr.byte[0];
nc.attr.byte[1] = next_attribute.attr.byte[1];
nc.attr.byte[2] = 0;
nc.attr.byte[3] = 0;
term_string.push_back(std::move(nc));
p++;
} // end of while
//----------------------------------------------------------------------
int FVTerm::print (const std::vector<FChar>& term_string)
{
if ( term_string.empty() )
return -1;
return print (area, term_string);
}
FTermBuffer term_buffer{term_string.begin(), term_string.end()};
return print (term_buffer);
}
return 0;
//----------------------------------------------------------------------
int FVTerm::print (FTermArea* area, const std::vector<FChar>& term_string)
{
if ( ! area || term_string.empty() )
return -1;
FTermBuffer term_buffer{term_string.begin(), term_string.end()};
return print (area, term_buffer);
}
//----------------------------------------------------------------------
@ -401,42 +399,18 @@ int FVTerm::print (const FTermBuffer& term_buffer)
//----------------------------------------------------------------------
int FVTerm::print (FTermArea* area, const FTermBuffer& term_buffer)
{
const auto& term_string = term_buffer.getBuffer();
return print (area, term_string);
}
//----------------------------------------------------------------------
int FVTerm::print (const std::vector<FChar>& term_string)
{
if ( term_string.empty() )
return 0;
auto area = getPrintArea();
if ( ! area )
return -1;
return print (area, term_string);
}
//----------------------------------------------------------------------
int FVTerm::print (FTermArea* area, const std::vector<FChar>& term_string)
{
int len{0};
const auto tabstop = uInt(FTerm::getTabstop());
if ( ! area )
if ( ! area || term_buffer.isEmpty() )
return -1;
if ( term_string.empty() )
return 0;
for (auto&& fchar : term_string)
for (auto&& fchar : term_buffer)
{
bool printable_character{false};
switch ( fchar.ch )
switch ( fchar.ch[0] )
{
case '\n':
area->cursor_y++;
@ -478,30 +452,25 @@ int FVTerm::print (FTermArea* area, const std::vector<FChar>& term_string)
//----------------------------------------------------------------------
int FVTerm::print (wchar_t c)
{
auto area = getPrintArea();
if ( ! area )
return -1;
return print (area, c);
FChar nc{}; // next character
nc = FVTerm::getAttribute();
nc.ch[0] = c;
nc.attr.byte[2] = 0;
nc.attr.byte[3] = 0;
return print (nc);
}
//----------------------------------------------------------------------
int FVTerm::print (FTermArea* area, wchar_t c)
{
FChar nc{}; // next character
if ( ! area )
return -1;
nc.ch = wchar_t(c);
nc.fg_color = next_attribute.fg_color;
nc.bg_color = next_attribute.bg_color;
nc.attr.byte[0] = next_attribute.attr.byte[0];
nc.attr.byte[1] = next_attribute.attr.byte[1];
FChar nc{}; // next character
nc = FVTerm::getAttribute();
nc.ch[0] = c;
nc.attr.byte[2] = 0;
nc.attr.byte[3] = 0;
return print (area, nc);
}
@ -531,7 +500,10 @@ int FVTerm::print (FTermArea* area, FChar& term_char)
const int ax = area->cursor_x - 1;
const int ay = area->cursor_y - 1;
const std::size_t char_width = getColumnWidth(term_char); // add column width
std::size_t char_width = term_char.attr.bit.char_width;
if ( char_width == 0 )
char_width = getColumnWidth(term_char); // add column width
if ( char_width == 0 && ! term_char.attr.bit.fullwidth_padding )
return 0;
@ -1134,7 +1106,7 @@ void FVTerm::scrollAreaForward (FTermArea* area) const
auto bottom_right = std::size_t((y_max * total_width) - area->right_shadow - 1);
const auto& lc = area->data[bottom_right]; // last character
std::memcpy (&nc, &lc, sizeof(nc));
nc.ch = ' ';
nc.ch[0] = ' ';
auto& dc = area->data[y_max * total_width]; // destination character
std::fill_n (&dc, area->width, nc);
area->changes[y_max].xmin = 0;
@ -1186,7 +1158,7 @@ void FVTerm::scrollAreaReverse (FTermArea* area) const
FChar nc{}; // next character
const auto& lc = area->data[total_width]; // last character
std::memcpy (&nc, &lc, sizeof(nc));
nc.ch = ' ';
nc.ch[0] = ' ';
auto& dc = area->data[0]; // destination character
std::fill_n (&dc, area->width, nc);
area->changes[0].xmin = 0;
@ -1217,7 +1189,7 @@ void FVTerm::clearArea (FTermArea* area, int fillchar) const
// Current attributes with a space character
std::memcpy (&nc, &next_attribute, sizeof(nc));
nc.ch = fillchar;
nc.ch[0] = fillchar;
if ( ! (area && area->data) )
{
@ -1261,6 +1233,15 @@ void FVTerm::clearArea (FTermArea* area, int fillchar) const
area->has_changes = true;
}
//----------------------------------------------------------------------
void FVTerm::forceTerminalUpdate() const
{
force_terminal_update = true;
processTerminalUpdate();
flush();
force_terminal_update = false;
}
//----------------------------------------------------------------------
bool FVTerm::processTerminalUpdate() const
{
@ -1278,7 +1259,8 @@ bool FVTerm::processTerminalUpdate() const
}
// Update data on VTerm
updateVTerm();
if ( force_terminal_update || skipped_terminal_update == 0 )
updateVTerm();
// Update the visible terminal
return updateTerminal();
@ -1324,7 +1306,7 @@ inline void FVTerm::resetTextAreaToDefault ( const FTermArea* area
FChar default_char;
FLineChanges unchanged;
default_char.ch = ' ';
default_char.ch[0] = ' ';
default_char.fg_color = fc::Default;
default_char.bg_color = fc::Default;
default_char.attr.byte[0] = 0;
@ -1459,13 +1441,13 @@ inline void FVTerm::updateOverlappedColor ( const FChar& area_char
nc.attr.bit.reverse = false;
nc.attr.bit.standout = false;
if ( nc.ch == fc::LowerHalfBlock
|| nc.ch == fc::UpperHalfBlock
|| nc.ch == fc::LeftHalfBlock
|| nc.ch == fc::RightHalfBlock
|| nc.ch == fc::MediumShade
|| nc.ch == fc::FullBlock )
nc.ch = ' ';
if ( nc.ch[0] == fc::LowerHalfBlock
|| nc.ch[0] == fc::UpperHalfBlock
|| nc.ch[0] == fc::LeftHalfBlock
|| nc.ch[0] == fc::RightHalfBlock
|| nc.ch[0] == fc::MediumShade
|| nc.ch[0] == fc::FullBlock )
nc.ch[0] = ' ';
nc.attr.bit.no_changes = bool(vterm_char.attr.bit.printed && vterm_char == nc);
std::memcpy (&vterm_char, &nc, sizeof(vterm_char));
@ -1494,13 +1476,13 @@ inline void FVTerm::updateShadedCharacter ( const FChar& area_char
cover_char.attr.bit.reverse = false;
cover_char.attr.bit.standout = false;
if ( cover_char.ch == fc::LowerHalfBlock
|| cover_char.ch == fc::UpperHalfBlock
|| cover_char.ch == fc::LeftHalfBlock
|| cover_char.ch == fc::RightHalfBlock
|| cover_char.ch == fc::MediumShade
|| cover_char.ch == fc::FullBlock )
cover_char.ch = ' ';
if ( cover_char.ch[0] == fc::LowerHalfBlock
|| cover_char.ch[0] == fc::UpperHalfBlock
|| cover_char.ch[0] == fc::LeftHalfBlock
|| cover_char.ch[0] == fc::RightHalfBlock
|| cover_char.ch[0] == fc::MediumShade
|| cover_char.ch[0] == fc::FullBlock )
cover_char.ch[0] = ' ';
cover_char.attr.bit.no_changes = \
bool(vterm_char.attr.bit.printed && vterm_char == cover_char);
@ -1733,13 +1715,13 @@ FChar FVTerm::generateCharacter (const FPoint& pos)
s_ch.attr.bit.reverse = false;
s_ch.attr.bit.standout = false;
if ( s_ch.ch == fc::LowerHalfBlock
|| s_ch.ch == fc::UpperHalfBlock
|| s_ch.ch == fc::LeftHalfBlock
|| s_ch.ch == fc::RightHalfBlock
|| s_ch.ch == fc::MediumShade
|| s_ch.ch == fc::FullBlock )
s_ch.ch = ' ';
if ( s_ch.ch[0] == fc::LowerHalfBlock
|| s_ch.ch[0] == fc::UpperHalfBlock
|| s_ch.ch[0] == fc::LeftHalfBlock
|| s_ch.ch[0] == fc::RightHalfBlock
|| s_ch.ch[0] == fc::MediumShade
|| s_ch.ch[0] == fc::FullBlock )
s_ch.ch[0] = ' ';
sc = &s_ch;
}
@ -1860,7 +1842,7 @@ void FVTerm::init()
output_buffer->reserve(TERMINAL_OUTPUT_BUFFER_SIZE + 256);
// term_attribute stores the current state of the terminal
term_attribute.ch = '\0';
term_attribute.ch = { L'\0' };
term_attribute.fg_color = fc::Default;
term_attribute.bg_color = fc::Default;
term_attribute.attr.byte[0] = 0;
@ -1967,13 +1949,13 @@ void FVTerm::putAreaCharacter ( const FPoint& pos, const FTermArea* area
ch.attr.bit.reverse = false;
ch.attr.bit.standout = false;
if ( ch.ch == fc::LowerHalfBlock
|| ch.ch == fc::UpperHalfBlock
|| ch.ch == fc::LeftHalfBlock
|| ch.ch == fc::RightHalfBlock
|| ch.ch == fc::MediumShade
|| ch.ch == fc::FullBlock )
ch.ch = ' ';
if ( ch.ch[0] == fc::LowerHalfBlock
|| ch.ch[0] == fc::UpperHalfBlock
|| ch.ch[0] == fc::LeftHalfBlock
|| ch.ch[0] == fc::RightHalfBlock
|| ch.ch[0] == fc::MediumShade
|| ch.ch[0] == fc::FullBlock )
ch.ch[0] = ' ';
std::memcpy (&vterm_char, &ch, sizeof(vterm_char));
}
@ -2084,7 +2066,7 @@ bool FVTerm::clearFullArea (const FTermArea* area, FChar& nc) const
return false;
// Try to clear the terminal rapidly with a control sequence
if ( clearTerm (nc.ch) )
if ( clearTerm (nc.ch[0]) )
{
nc.attr.bit.printed = true;
std::fill_n (vterm->data, area_size, nc);
@ -2138,7 +2120,7 @@ bool FVTerm::canClearToEOL (uInt xmin, uInt y)
const auto& ce = TCAP(fc::t_clr_eol);
const auto& min_char = vt->data[y * uInt(vt->width) + xmin];
if ( ce && min_char.ch == ' ' )
if ( ce && min_char.ch[0] == ' ' )
{
uInt beginning_whitespace = 1;
const bool normal = FTerm::isNormal(min_char);
@ -2173,7 +2155,7 @@ bool FVTerm::canClearLeadingWS (uInt& xmin, uInt y)
const auto& cb = TCAP(fc::t_clr_bol);
const auto& first_char = vt->data[y * uInt(vt->width)];
if ( cb && first_char.ch == ' ' )
if ( cb && first_char.ch[0] == ' ' )
{
uInt leading_whitespace = 1;
const bool normal = FTerm::isNormal(first_char);
@ -2211,7 +2193,7 @@ bool FVTerm::canClearTrailingWS (uInt& xmax, uInt y)
const auto& ce = TCAP(fc::t_clr_eol);
const auto& last_char = vt->data[(y + 1) * uInt(vt->width) - 1];
if ( ce && last_char.ch == ' ' )
if ( ce && last_char.ch[0] == ' ' )
{
uInt trailing_whitespace = 1;
const bool normal = FTerm::isNormal(last_char);
@ -2245,18 +2227,18 @@ bool FVTerm::skipUnchangedCharacters (uInt& x, uInt xmax, uInt y) const
// Skip characters without changes if it is faster than redrawing
auto& vt = vterm;
auto print_char = &vt->data[y * uInt(vt->width) + x];
print_char->attr.bit.printed = true;
auto& print_char = vt->data[y * uInt(vt->width) + x];
print_char.attr.bit.printed = true;
if ( print_char->attr.bit.no_changes )
if ( print_char.attr.bit.no_changes )
{
uInt count{1};
for (uInt i = x + 1; i <= xmax; i++)
{
auto ch = &vt->data[y * uInt(vt->width) + i];
const auto& ch = vt->data[y * uInt(vt->width) + i];
if ( ch->attr.bit.no_changes )
if ( ch.attr.bit.no_changes )
count++;
else
break;
@ -2291,7 +2273,7 @@ void FVTerm::printRange ( uInt xmin, uInt xmax, uInt y
continue;
// Erase character
if ( ec && print_char.ch == ' ' )
if ( ec && print_char.ch[0] == ' ' )
{
exit_state erase_state = \
eraseCharacters(x, xmax, y, draw_trailing_ws);
@ -2320,13 +2302,15 @@ inline void FVTerm::replaceNonPrintableFullwidth ( uInt x
if ( x == 0 && isFullWidthPaddingChar(print_char) )
{
print_char.ch = fc::SingleLeftAngleQuotationMark; //
print_char.ch[0] = fc::SingleLeftAngleQuotationMark; //
print_char.ch[1] = L'\0';
print_char.attr.bit.fullwidth_padding = false;
}
else if ( x == uInt(vterm->width - 1)
&& isFullWidthChar(print_char) )
{
print_char.ch = fc::SingleRightAngleQuotationMark; //
print_char.ch[0] = fc::SingleRightAngleQuotationMark; //
print_char.ch[1] = L'\0';
print_char.attr.bit.char_width = 1;
}
}
@ -2500,7 +2484,7 @@ FVTerm::exit_state FVTerm::eraseCharacters ( uInt& x, uInt xmax, uInt y
const auto& ec = TCAP(fc::t_erase_chars);
auto& print_char = vt->data[y * uInt(vt->width) + x];
if ( ! ec || print_char.ch != ' ' )
if ( ! ec || print_char.ch[0] != ' ' )
return not_used;
uInt whitespace{1};
@ -2590,12 +2574,12 @@ FVTerm::exit_state FVTerm::repeatCharacter (uInt& x, uInt xmax, uInt y) const
const uInt start_pos = x;
if ( repetitions > repeat_char_length
&& print_char.ch < 128 )
&& print_char.ch[0] < 128 )
{
newFontChanges (print_char);
charsetChanges (print_char);
appendAttributes (print_char);
appendOutputBuffer (FTermcap::encodeParameter(rp, print_char.ch, repetitions, 0, 0, 0, 0, 0, 0, 0));
appendOutputBuffer (FTermcap::encodeParameter(rp, print_char.ch[0], repetitions, 0, 0, 0, 0, 0, 0, 0));
term_pos->x_ref() += int(repetitions);
x = x + repetitions - 1;
}
@ -2739,13 +2723,14 @@ void FVTerm::printPaddingCharacter (FTermArea* area, const FChar& term_char)
if ( FTerm::getEncoding() == fc::UTF8 )
{
pc.ch = 0;
pc.ch = { L'\0' };
pc.attr.bit.fullwidth_padding = true;
pc.attr.bit.char_width = 0;
}
else
{
pc.ch = '.';
pc.ch[0] = L'.';
pc.ch[1] = L'\0';
pc.attr.bit.char_width = 1;
}
@ -2917,20 +2902,20 @@ inline void FVTerm::newFontChanges (FChar& next_char)
if ( ! FTerm::isNewFont() )
return;
if ( next_char.ch == fc::LowerHalfBlock )
if ( next_char.ch[0] == fc::LowerHalfBlock )
{
next_char.ch = fc::UpperHalfBlock;
next_char.ch[0] = fc::UpperHalfBlock;
next_char.attr.bit.reverse = true;
}
else if ( isReverseNewFontchar(next_char.ch) )
else if ( isReverseNewFontchar(next_char.ch[0]) )
next_char.attr.bit.reverse = true; // Show in reverse video
}
//----------------------------------------------------------------------
inline void FVTerm::charsetChanges (FChar& next_char)
{
const wchar_t& ch = next_char.ch;
next_char.encoded_char = ch;
const wchar_t& ch = next_char.ch[0];
next_char.encoded_char[0] = ch;
if ( FTerm::getEncoding() == fc::UTF8 )
return;
@ -2942,11 +2927,11 @@ inline void FVTerm::charsetChanges (FChar& next_char)
if ( ch_enc == 0 )
{
next_char.encoded_char = wchar_t(FTerm::charEncode(ch, fc::ASCII));
next_char.encoded_char[0] = wchar_t(FTerm::charEncode(ch, fc::ASCII));
return;
}
next_char.encoded_char = ch_enc;
next_char.encoded_char[0] = ch_enc;
if ( FTerm::getEncoding() == fc::VT100 )
next_char.attr.bit.alt_charset = true;
@ -2960,10 +2945,10 @@ inline void FVTerm::charsetChanges (FChar& next_char)
if ( FTerm::isXTerminal() && ch_enc < 0x20 ) // Character 0x00..0x1f
{
if ( FTerm::hasUTF8() )
next_char.encoded_char = int(FTerm::charEncode(ch, fc::ASCII));
next_char.encoded_char[0] = int(FTerm::charEncode(ch, fc::ASCII));
else
{
next_char.encoded_char += 0x5f;
next_char.encoded_char[0] += 0x5f;
next_char.attr.bit.alt_charset = true;
}
}
@ -2992,14 +2977,14 @@ inline void FVTerm::appendChar (FChar& next_char) const
charsetChanges (next_char);
appendAttributes (next_char);
characterFilter (next_char);
appendOutputBuffer (next_char.encoded_char);
appendOutputBuffer (next_char.encoded_char[0]);
}
//----------------------------------------------------------------------
inline void FVTerm::appendAttributes (FChar& next_attr) const
{
// generate attribute string for the next character
const auto attr_str = FTerm::changeAttribute (term_attribute, next_attr);
const auto& attr_str = FTerm::changeAttribute (term_attribute, next_attr);
if ( attr_str )
appendOutputBuffer (attr_str);
@ -3069,8 +3054,8 @@ inline void FVTerm::characterFilter (FChar& next_char)
{
charSubstitution& sub_map = fterm->getCharSubstitutionMap();
if ( sub_map.find(next_char.encoded_char) != sub_map.end() )
next_char.encoded_char = sub_map[next_char.encoded_char];
if ( sub_map.find(next_char.encoded_char[0]) != sub_map.end() )
next_char.encoded_char[0] = sub_map[next_char.encoded_char[0]];
}
//----------------------------------------------------------------------

View File

@ -981,10 +981,7 @@ void FWidget::show()
if ( show_root_widget && show_root_widget == this )
{
finishDrawing();
if ( processTerminalUpdate() )
flush();
forceTerminalUpdate();
show_root_widget = nullptr;
}
@ -1978,7 +1975,7 @@ void FWidget::drawWindows() const
{
// redraw windows
FChar default_char{};
default_char.ch = ' ';
default_char.ch[0] = ' ';
default_char.fg_color = fc::Black;
default_char.bg_color = fc::Black;
default_char.attr.byte[0] = 0;

View File

@ -183,7 +183,7 @@
/* Define to the full name and version of this package. */
#ifndef F_PACKAGE_STRING
#define F_PACKAGE_STRING "finalcut 0.7.0"
#define F_PACKAGE_STRING "finalcut 0.7.1"
#endif
/* Define to the one symbol short name of this package. */
@ -198,7 +198,7 @@
/* Define to the version of this package. */
#ifndef F_PACKAGE_VERSION
#define F_PACKAGE_VERSION "0.7.0"
#define F_PACKAGE_VERSION "0.7.1"
#endif
/* Define to 1 if you have the ANSI C header files. */
@ -230,7 +230,7 @@
/* Version number of package */
#ifndef F_VERSION
#define F_VERSION "0.7.0"
#define F_VERSION "0.7.1"
#endif
/* Define to 1 if on MINIX. */

View File

@ -171,7 +171,6 @@ class FString
// Methods
std::size_t getLength() const;
std::size_t getUTF8length() const;
std::size_t capacity() const;
iterator begin();

View File

@ -31,6 +31,9 @@
#include <sys/types.h>
#include <cstddef>
#include <cstring>
#include <array>
#include <functional>
#include <limits>
#include <unordered_map>
@ -150,13 +153,17 @@ union attribute
uInt8 byte[4];
};
static constexpr uInt UNICODE_MAX = 5;
typedef std::array<wchar_t, UNICODE_MAX> FUnicode;
typedef struct
{
wchar_t ch; // Character code
wchar_t encoded_char; // Encoded output character
FColor fg_color; // Foreground color
FColor bg_color; // Background color
attribute attr; // Attributes
FUnicode ch; // Character code
FUnicode encoded_char; // Encoded output character
FColor fg_color; // Foreground color
FColor bg_color; // Background color
attribute attr; // Attributes
} FChar;
@ -189,9 +196,9 @@ FKeyName;
// FChar operator functions
//----------------------------------------------------------------------
constexpr bool operator == (const FChar& lhs, const FChar& rhs)
inline bool operator == (const FChar& lhs, const FChar& rhs)
{
return lhs.ch == rhs.ch
return operator == (lhs.ch, rhs.ch)
&& lhs.fg_color == rhs.fg_color
&& lhs.bg_color == rhs.bg_color
&& lhs.attr.byte[0] == rhs.attr.byte[0]
@ -201,7 +208,7 @@ constexpr bool operator == (const FChar& lhs, const FChar& rhs)
}
//----------------------------------------------------------------------
constexpr bool operator != (const FChar& lhs, const FChar& rhs)
inline bool operator != (const FChar& lhs, const FChar& rhs)
{
return ! ( lhs == rhs );
}

View File

@ -262,10 +262,10 @@ class FVTerm
int printf (const FString&, Args&&...);
int print (const FString&);
int print (FTermArea*, const FString&);
int print (const FTermBuffer&);
int print (FTermArea*, const FTermBuffer&);
int print (const std::vector<FChar>&);
int print (FTermArea*, const std::vector<FChar>&);
int print (const FTermBuffer&);
int print (FTermArea*, const FTermBuffer&);
int print (wchar_t);
int print (FTermArea*, wchar_t);
int print (FChar&);
@ -317,6 +317,7 @@ class FVTerm
void scrollAreaForward (FTermArea*) const;
void scrollAreaReverse (FTermArea*) const;
void clearArea (FTermArea*, int = ' ') const;
void forceTerminalUpdate() const;
bool processTerminalUpdate() const;
static void startDrawing();
static void finishDrawing();
@ -340,7 +341,7 @@ class FVTerm
// Constants
// Buffer size for character output on the terminal
static constexpr uInt TERMINAL_OUTPUT_BUFFER_SIZE = 131072;
static constexpr int max_skip = 20;
static constexpr int max_skip = 2;
// Methods
void resetTextAreaToDefault ( const FTermArea*
@ -441,8 +442,9 @@ class FVTerm
static timeval last_term_size_check;
static bool draw_completed;
static bool no_terminal_updates;
static uInt64 term_size_check_timeout;
static bool force_terminal_update;
static int skipped_terminal_update;
static uInt64 term_size_check_timeout;
static uInt erase_char_length;
static uInt repeat_char_length;
static uInt clr_bol_length;

View File

@ -107,12 +107,6 @@
#include "final/ftypes.h"
#include "final/fvterm.h"
// Old callback macros (deprecated)
#define F_FUNCTION_CALLBACK(h) (h), this, nullptr
#define F_FUNCTION_CALLBACK_DATA(h) (h), this
#define F_METHOD_CALLBACK(i,h) (i), (h), this, nullptr
#define F_METHOD_CALLBACK_DATA(i,h) (i), (h), this
namespace finalcut
{

View File

@ -1085,7 +1085,7 @@ void FOptiAttrTest::vt100Test()
CPPUNIT_ASSERT_CSTRING ( oa.changeAttribute(from, to)
, CSI "0m\017$<2>" );
CPPUNIT_ASSERT ( from == to );
CPPUNIT_ASSERT ( to.encoded_char == ' ' );
CPPUNIT_ASSERT ( to.encoded_char[0] == ' ' );
CPPUNIT_ASSERT ( oa.changeAttribute(from, to) == 0 );
// Invisible off (with default colors)
@ -2028,7 +2028,7 @@ void FOptiAttrTest::rxvtTest()
CPPUNIT_ASSERT_CSTRING ( oa.changeAttribute(from, to)
, CSI "0m\017" );
CPPUNIT_ASSERT ( from == to );
CPPUNIT_ASSERT ( to.encoded_char == ' ' );
CPPUNIT_ASSERT ( to.encoded_char[0] == ' ' );
CPPUNIT_ASSERT ( oa.changeAttribute(from, to) == 0 );
// Invisible off (with default colors)
@ -2498,7 +2498,7 @@ void FOptiAttrTest::linuxTest()
CPPUNIT_ASSERT_CSTRING ( oa.changeAttribute(from, to)
, CSI "0m\017" );
CPPUNIT_ASSERT ( from == to );
CPPUNIT_ASSERT ( to.encoded_char == ' ' );
CPPUNIT_ASSERT ( to.encoded_char[0] == ' ' );
CPPUNIT_ASSERT ( oa.changeAttribute(from, to) == 0 );
// Invisible off (with default colors)
@ -2979,7 +2979,7 @@ void FOptiAttrTest::puttyTest()
CPPUNIT_ASSERT_CSTRING ( oa.changeAttribute(from, to)
, CSI "0m\017" );
CPPUNIT_ASSERT ( from == to );
CPPUNIT_ASSERT ( to.encoded_char == ' ' );
CPPUNIT_ASSERT ( to.encoded_char[0] == ' ' );
CPPUNIT_ASSERT ( oa.changeAttribute(from, to) == 0 );
// Invisible off (with default colors)
@ -3450,7 +3450,7 @@ void FOptiAttrTest::teratermTest()
CPPUNIT_ASSERT_CSTRING ( oa.changeAttribute(from, to)
, CSI "0m\017$<2>" );
CPPUNIT_ASSERT ( from == to );
CPPUNIT_ASSERT ( to.encoded_char == ' ' );
CPPUNIT_ASSERT ( to.encoded_char[0] == ' ' );
CPPUNIT_ASSERT ( oa.changeAttribute(from, to) == 0 );
// Invisible off (with default colors)
@ -3905,7 +3905,7 @@ void FOptiAttrTest::ibmColorTest()
CPPUNIT_ASSERT ( from != to );
CPPUNIT_ASSERT_CSTRING ( oa.changeAttribute(from, to), "" );
CPPUNIT_ASSERT ( from == to );
CPPUNIT_ASSERT ( to.encoded_char == ' ' );
CPPUNIT_ASSERT ( to.encoded_char[0] == ' ' );
CPPUNIT_ASSERT ( oa.changeAttribute(from, to) == 0 );
// Invisible off (with default colors)

View File

@ -162,7 +162,6 @@ void FStringTest::noArgumentTest()
CPPUNIT_ASSERT ( empty.isEmpty() );
CPPUNIT_ASSERT ( empty.getLength() == 0 );
CPPUNIT_ASSERT ( empty.capacity() == 0 );
CPPUNIT_ASSERT ( empty.getUTF8length() == 0 );
CPPUNIT_ASSERT ( empty.wc_str() == nullptr );
CPPUNIT_ASSERT ( empty.c_str() == nullptr );
CPPUNIT_ASSERT_EQUAL ( empty.toString(), std::string() );
@ -657,7 +656,6 @@ void FStringTest::equalTest()
constexpr char cstr[] = "abc";
CPPUNIT_ASSERT ( str == cstr );
CPPUNIT_ASSERT ( str.getLength() == 3 );
CPPUNIT_ASSERT ( str.getUTF8length() == 3 );
CPPUNIT_ASSERT ( str.capacity() == 18 );
CPPUNIT_ASSERT ( strncmp(cstr, str.c_str(), 3) == 0 );
@ -706,8 +704,6 @@ void FStringTest::notEqualTest()
CPPUNIT_ASSERT ( strlen(s1.c_str()) == 3 );
CPPUNIT_ASSERT ( s2.getLength() == 3 );
CPPUNIT_ASSERT ( strlen(s2.c_str()) == 6 );
CPPUNIT_ASSERT ( s1.getUTF8length() == 3 );
CPPUNIT_ASSERT ( s2.getUTF8length() == 3 );
CPPUNIT_ASSERT ( s1.capacity() == 18 );
CPPUNIT_ASSERT ( s2.capacity() == 18 );
CPPUNIT_ASSERT ( strncmp(cstr, s1.c_str(), 3) != 0 );