Optimized input cursor positioning for terminals without hidden cursor

This commit is contained in:
Markus Gans 2016-11-12 22:59:48 +01:00
parent 125c4b961b
commit 04a483526f
11 changed files with 141 additions and 107 deletions

View File

@ -1,5 +1,11 @@
2016-11-12 Markus Gans <guru.mail@muenster.de>
* Better support for Linux terminals with 8 colors
* Optimized input cursor positioning for terminals without hidden cursor
* Switch locale name from "en_US" to "C"
* Fix FString toLong()
2016-11-06 Markus Gans <guru.mail@muenster.de>
* The use of xterm default colors now is configurable
* The adjustment of xterm default colors now is configurable
2016-11-05 Markus Gans <guru.mail@muenster.de>
* Determine xterm maximum number of colors via OSC 4

View File

@ -79,6 +79,7 @@ void FButton::setHotkeyForegroundColor (short color)
button_hotkey_fg = color;
}
//----------------------------------------------------------------------
void FButton::setFocusForegroundColor (short color)
{
// valid colors -1..254

View File

@ -592,6 +592,7 @@ void FMenu::onMouseMove (FMouseEvent* ev)
{
// Unselect selected item without mouse focus
(*iter)->unsetSelected();
(*iter)->unsetFocus();
if ( getSelectedItem() == *iter )
setSelectedItem(0);
@ -1055,12 +1056,12 @@ bool FMenu::selectNextItem()
unselectItem();
next->setSelected();
setSelectedItem(next);
redraw();
next->setFocus();
if ( getStatusBar() )
getStatusBar()->drawMessage();
redraw();
updateTerminal();
flush_out();
break;

View File

@ -256,47 +256,30 @@ void FMenuBar::onMouseUp (FMouseEvent* ev)
x1 = (*iter)->getX();
x2 = (*iter)->getX() + (*iter)->getWidth();
if ( mouse_y == 1 )
if ( mouse_y == 1 && (*iter)->isEnabled() && (*iter)->isSelected() )
{
if ( (*iter)->isEnabled() && (*iter)->isSelected() )
if ( mouse_x >= x1 && mouse_x < x2 )
{
if ( mouse_x >= x1 && mouse_x < x2 )
// Mouse pointer over item
if ( (*iter)->hasMenu() )
{
// Mouse pointer over item
if ( (*iter)->hasMenu() )
FMenu* menu = (*iter)->getMenu();
if ( ! menu->hasSelectedItem() )
{
FMenu* menu = (*iter)->getMenu();
FMenuItem* first_item;
menu->selectFirstItem();
first_item = menu->getSelectedItem();
if ( ! menu->hasSelectedItem() )
{
FMenuItem* first_item;
menu->selectFirstItem();
first_item = menu->getSelectedItem();
if ( first_item )
first_item->setFocus();
if ( first_item )
first_item->setFocus();
if ( getStatusBar() )
getStatusBar()->drawMessage();
menu->redraw();
if ( getStatusBar() )
getStatusBar()->drawMessage();
redraw();
drop_down = true;
}
}
else
{
(*iter)->unsetSelected();
if ( getSelectedItem() == *iter )
{
setSelectedItem(0);
leaveMenuBar();
drop_down = false;
(*iter)->processClicked();
return;
}
redraw();
menu->redraw();
drop_down = true;
}
}
else
@ -304,11 +287,24 @@ void FMenuBar::onMouseUp (FMouseEvent* ev)
(*iter)->unsetSelected();
if ( getSelectedItem() == *iter )
{
setSelectedItem(0);
redraw();
leaveMenuBar();
drop_down = false;
(*iter)->processClicked();
return;
}
}
}
else
{
(*iter)->unsetSelected();
if ( getSelectedItem() == *iter )
setSelectedItem(0);
redraw();
}
}
++iter;

View File

@ -271,6 +271,7 @@ void FMenuItem::setSelected()
void FMenuItem::unsetSelected()
{
selected = false;
unsetCursorPos();
processDeactivate();
}

View File

@ -690,7 +690,7 @@ long FString::toLong() const
p++;
}
while ( std::isdigit(*p) )
while ( std::iswdigit(*p) )
{
register uChar d = uChar((*p) - L'0');
@ -704,7 +704,7 @@ long FString::toLong() const
p++;
}
if ( ! std::isdigit(*p) )
if ( *p != L'\0' && ! std::iswdigit(*p) )
throw std::invalid_argument ("no valid number");
return num;
@ -736,7 +736,7 @@ uLong FString::toULong() const
p++;
}
while ( std::isdigit(*p) )
while ( std::iswdigit(*p) )
{
register uChar d = uChar((*p) - L'0');
@ -750,7 +750,7 @@ uLong FString::toULong() const
p++;
}
if ( ! std::isdigit(*p) )
if ( *p != L'\0' && ! std::iswdigit(*p) )
throw std::invalid_argument ("no valid number");
return num;

View File

@ -27,6 +27,7 @@ int FTerm::stdin_status_flags;
uInt FTerm::baudrate;
bool FTerm::resize_term;
bool FTerm::mouse_support;
bool FTerm::terminal_detection;
bool FTerm::raw_mode;
bool FTerm::input_data_pending;
bool FTerm::non_blocking_stdin;
@ -2265,7 +2266,6 @@ char* FTerm::parseSecDA (char*& current_termtype)
{
terminal_id_version = -1;
}
switch ( terminal_id_type )
{
case 0: // DEC VT100
@ -2520,7 +2520,8 @@ void FTerm::init_termcaps()
FTermcap::eat_nl_glitch = true;
// maximum number of colors on screen
FTermcap::max_color = tgetnum(const_cast<char*>("Co"));
FTermcap::max_color = std::max( FTermcap::max_color
, tgetnum(const_cast<char*>("Co")) );
if ( FTermcap::max_color < 0 )
FTermcap::max_color = 1;
@ -2577,10 +2578,21 @@ void FTerm::init_termcaps()
// set ansi foreground and background color
if ( linux_terminal || cygwin_terminal )
{
tcap[fc::t_set_a_foreground].string = \
const_cast<char*>(CSI "3%p1%{8}%m%d%?%p1%{7}%>%t;1%e;21%;m");
tcap[fc::t_set_a_background].string = \
const_cast<char*>(CSI "4%p1%{8}%m%d%?%p1%{7}%>%t;5%e;25%;m");
if ( FTermcap::max_color > 8 )
{
tcap[fc::t_set_a_foreground].string = \
const_cast<char*>(CSI "3%p1%{8}%m%d%?%p1%{7}%>%t;1%e;21%;m");
tcap[fc::t_set_a_background].string = \
const_cast<char*>(CSI "4%p1%{8}%m%d%?%p1%{7}%>%t;5%e;25%;m");
}
else
{
tcap[fc::t_set_a_foreground].string = \
const_cast<char*>(CSI "3%p1%dm");
tcap[fc::t_set_a_background].string = \
const_cast<char*>(CSI "4%p1%dm");
}
tcap[fc::t_orig_pair].string = \
const_cast<char*>(CSI "39;49;25m");
}
@ -2946,6 +2958,7 @@ void FTerm::init()
VGAFont = \
ascii_console = \
mouse_support = \
force_vt100 = \
tera_terminal = \
kterm_terminal = \
@ -2960,7 +2973,8 @@ void FTerm::init()
xterm_default_colors = false;
// Preset to true
cursor_optimisation = true;
cursor_optimisation = \
terminal_detection = true;
// assertion: programm start in cooked mode
raw_mode = \
@ -3015,33 +3029,61 @@ void FTerm::init()
else
linux_terminal = false;
// start terminal detection...
setRawMode();
// Identify the terminal via the answerback-message
new_termtype = parseAnswerbackMsg (new_termtype);
// Identify the terminal via the secondary device attributes (SEC_DA)
new_termtype = parseSecDA (new_termtype);
if ( ! color256 && getXTermColorName(0) != "" )
// terminal detection
if ( terminal_detection )
{
if ( getXTermColorName(256) != "" )
{
new_termtype = const_cast<char*>("xterm-256color");
}
else if ( FTermcap::max_color < 88 && getXTermColorName(87) != "" )
{
new_termtype = const_cast<char*>("xterm-88color");
}
else if ( FTermcap::max_color < 16 && getXTermColorName(15) != "" )
{
new_termtype = const_cast<char*>("xterm-16color");
}
}
setRawMode();
unsetRawMode();
// ...end of terminal detection
// Identify the terminal via the answerback-message
new_termtype = parseAnswerbackMsg (new_termtype);
// Identify the terminal via the secondary device attributes (SEC_DA)
new_termtype = parseSecDA (new_termtype);
// Determine xterm maximum number of colors via OSC 4
if ( ! color256 && ! tera_terminal && getXTermColorName(0) != "" )
{
if ( getXTermColorName(256) != "" )
{
new_termtype = const_cast<char*>("xterm-256color");
}
else if ( getXTermColorName(87) != "" )
{
new_termtype = const_cast<char*>("xterm-88color");
}
else if ( getXTermColorName(15) != "" )
{
new_termtype = const_cast<char*>("xterm-16color");
}
}
if ( cygwin_terminal
|| putty_terminal
|| tera_terminal
|| rxvt_terminal )
{
FTermcap::max_color = 16;
}
if ( linux_terminal && openConsole() == 0 )
{
if ( isConsole() )
{
if ( setBlinkAsIntensity(true) == 0 )
FTermcap::max_color = 16;
else
FTermcap::max_color = 8;
}
closeConsole();
setConsoleCursor(fc::underscore_cursor, true);
}
if ( linux_terminal && getFramebuffer_bpp() >= 4 )
FTermcap::max_color = 16;
unsetRawMode();
}
// stop non-blocking stdin
unsetNonBlockingInput();
@ -3083,11 +3125,7 @@ void FTerm::init()
// TeraTerm can not show UTF-8 character
if ( tera_terminal && ! std::strcmp(nl_langinfo(CODESET), "UTF-8") )
locale_name = std::setlocale (LC_ALL, "en_US");
// if locale C => switch from 7bit ascii -> latin1
if ( isatty(stdout_no) && ! std::strcmp(nl_langinfo(CODESET), "ANSI_X3.4-1968") )
locale_name = std::setlocale (LC_ALL, "en_US");
locale_name = std::setlocale (LC_ALL, "C");
// try to found a meaningful content for locale_name
if ( locale_name )
@ -3164,29 +3202,6 @@ void FTerm::init()
unsetNonBlockingInput();
}
if ( (FTermcap::max_color == 8)
&& ( linux_terminal
|| cygwin_terminal
|| putty_terminal
|| tera_terminal
|| rxvt_terminal) )
{
FTermcap::max_color = 16;
}
if ( linux_terminal && openConsole() == 0 )
{
if ( isConsole() )
if ( setBlinkAsIntensity(true) != 0 )
FTermcap::max_color = 8;
closeConsole();
setConsoleCursor(fc::underscore_cursor, true);
}
if ( linux_terminal && getFramebuffer_bpp() >= 4 )
FTermcap::max_color = 16;
if ( kde_konsole )
setKDECursor(fc::UnderlineCursor);

View File

@ -205,7 +205,7 @@ class FTerm
// function pointer -> static function
static int (*Fputchar)(int);
static void putstringf (const char*, ...)
#if defined(__clang__)
__attribute__((__format__ (__printf__, 1, 2)))
@ -313,6 +313,7 @@ class FTerm
static FTermcap::tcap_map* tcap;
static bool mouse_support;
static bool terminal_detection;
static bool raw_mode;
static bool input_data_pending;
static bool non_blocking_stdin;

View File

@ -22,6 +22,8 @@ FWidget::widgetList* FWidget::dialog_list = 0;
FWidget::widgetList* FWidget::always_on_top_list = 0;
FWidget::widgetList* FWidget::close_widget = 0;
FWidget::widget_colors FWidget::wc;
bool FWidget::hideable;
//----------------------------------------------------------------------
// class FWidget
@ -40,7 +42,7 @@ FWidget::FWidget (FWidget* parent)
, shown(false)
, focus(false)
, focusable(true)
, visible_cursor(false)
, visible_cursor(true)
, widget_cursor_position(-1,-1)
, size_hints()
, double_flatline_mask()
@ -72,6 +74,7 @@ FWidget::FWidget (FWidget* parent)
}
else
{
visible_cursor = ! hideable;
offset = parent->client_offset;
double_flatline_mask.top.resize (uLong(getWidth()), false);
double_flatline_mask.right.resize (uLong(getHeight()), false);
@ -2124,6 +2127,15 @@ void FWidget::init()
always_on_top_list = new widgetList();
close_widget = new widgetList();
char* cursor_off_str = disableCursor();
if ( cursor_off_str && std::strlen(cursor_off_str ) > 0 )
hideable = true;
else
hideable = false;
visible_cursor = ! hideable;
// determine width and height of the terminal
detectTermSize();
wsize.setRect(1, 1, getColumnNumber(), getLineNumber());

View File

@ -514,6 +514,7 @@ class FWidget : public FVTerm
static FMenuBar* menubar;
static FWidget* show_root_widget;
static FWidget* redraw_root_widget;
static bool hideable;
// Friend class
friend class FToggleButton;
@ -683,7 +684,7 @@ inline bool FWidget::setDisable()
//----------------------------------------------------------------------
inline bool FWidget::setVisibleCursor (bool on)
{ return visible_cursor = (on) ? true : false; }
{ return visible_cursor = (on) ? true : ((hideable) ? false : true); }
//----------------------------------------------------------------------
inline bool FWidget::setVisibleCursor()
@ -776,7 +777,7 @@ inline bool FWidget::setCursorPos (const FPoint& pos)
//----------------------------------------------------------------------
inline void FWidget::unsetCursorPos()
{ widget_cursor_position.setPoint(-1,-1); }
{ setCursorPos(-1,-1); }
//----------------------------------------------------------------------
inline void FWidget::setPrintPos (const FPoint& pos)

View File

@ -19,7 +19,7 @@ int main (int, char**)
if ( isatty(1) && ! std::strcmp(nl_langinfo(CODESET), "ANSI_X3.4-1968") )
{
// locale C -> switch from 7bit ascii -> latin1
std::setlocale(LC_ALL, "en_US");
std::setlocale(LC_ALL, "C");
}
printf (" Codeset: %s\n", nl_langinfo(CODESET));