terminal fixes

- handle line wraps in 'ech()'
- take (1,1) origin into account in 'hpa()' and 'vpa()'
- unify handling of SGR escape sequences of different lengths
- accept the '[?2004h' and '[?2004l' escape sequences (used by midnight commander)

Fixes #2671
This commit is contained in:
Christian Prochaska 2018-02-06 18:08:32 +01:00 committed by Norman Feske
parent fefeb29d5f
commit 12c8e51071
2 changed files with 98 additions and 67 deletions

View File

@ -276,12 +276,31 @@ class Char_cell_array_character_screen : public Terminal::Character_screen
void ech(int v)
{
Cursor_guard guard(*this);
/* clear number of characters */
for (int i = 0; i < v; i++, _cursor_pos.x++)
_char_cell_array.set_cell(_cursor_pos.x, _cursor_pos.y,
int x = _cursor_pos.x;
int y = _cursor_pos.y;
while (v-- > 0) {
_char_cell_array.set_cell(x, y,
Char_cell(' ', Font_face::REGULAR,
_color_index, _inverse, _highlight));
if (x == (_boundary.width - 1)) {
/* end of line reached */
if (y < (_boundary.height - 1)) {
/* continue at beginning of next line */
x = 0;
y++;
} else {
/* end of screen reached */
return;
}
} else {
x++;
}
}
}
void ed()
@ -311,8 +330,11 @@ class Char_cell_array_character_screen : public Terminal::Character_screen
{
Cursor_guard guard(*this);
_cursor_pos.x = x;
_cursor_pos.x = Genode::min(_boundary.width - 1, _cursor_pos.x);
/* top-left cursor position is reported as (1, 1) */
x--;
using namespace Genode;
_cursor_pos.x = max(0, min(x, _boundary.width - 1));
}
void hts() { Genode::warning(__func__, " not implemented"); }
@ -348,7 +370,6 @@ class Char_cell_array_character_screen : public Terminal::Character_screen
void setab(int value)
{
//_inverse = (value != 0);
_color_index &= ~0x38; /* clear 111000 */
_color_index |= (((value == 9) ? DEFAULT_COLOR_INDEX_BG : value) << 3);
}
@ -361,12 +382,22 @@ class Char_cell_array_character_screen : public Terminal::Character_screen
void sgr(int value)
{
_highlight = (value & 0x1) != 0;
_inverse = (value & 0x2) != 0;
/* sgr 0 is the command to reset all attributes, including color */
if (value == 0)
switch (value) {
case 0:
/* sgr 0 is the command to reset all attributes, including color */
_highlight = false;
_inverse = false;
_color_index = DEFAULT_COLOR_INDEX | (DEFAULT_COLOR_INDEX_BG << 3);
break;
case 1:
_highlight = true;
break;
case 7:
_inverse = true;
break;
default:
break;
}
}
void sgr0()
@ -387,8 +418,11 @@ class Char_cell_array_character_screen : public Terminal::Character_screen
{
Cursor_guard guard(*this);
_cursor_pos.y = y;
_cursor_pos.y = Genode::min(_boundary.height - 1, _cursor_pos.y);
/* top-left cursor position is reported as (1, 1) */
y--;
using namespace Genode;
_cursor_pos.y = max(0, min(y, _boundary.height - 1));
}
};

View File

@ -175,6 +175,22 @@ class Terminal::Decoder
_number = 0;
}
bool _sgr(int const p)
{
if (p < 30)
return (_screen.sgr(p), true);
/* p starting with digit '3' -> set foreground color */
if (starts_with_digit(3, p))
return (_screen.setaf(remove_first_digit(p)), true);
/* p starting with digit '4' -> set background color */
if (starts_with_digit(4, p))
return (_screen.setab(remove_first_digit(p)), true);
return false;
}
/**
* Try to handle single-element escape sequence
*
@ -244,18 +260,7 @@ class Terminal::Decoder
char const command = _escape_stack[2].value;
switch (command) {
case 'm':
if (p1 < 30)
return (_screen.sgr(p1), true);
/* p1 starting with digit '3' -> set foreground color */
if (starts_with_digit(3, p1))
return (_screen.setaf(remove_first_digit(p1)), true);
/* p1 starting with digit '4' -> set background color */
if (starts_with_digit(4, p1))
return (_screen.setab(remove_first_digit(p1)), true);
case 'm': return _sgr(p1);
case 'D': return (_screen.cub(p1), true);
case 'd': return (_screen.vpa(p1), true);
case 'g': return (p1 == 3) && (_screen.tbc(), true);
@ -292,12 +297,22 @@ class Terminal::Decoder
switch (command) {
case 'l':
if (p1 == 7) return (_screen.rmam(), true);
if (p1 == 25) return (_screen.civis(), true);
if (p1 == 7) return (_screen.rmam(), true);
if (p1 == 25) return (_screen.civis(), true);
if (p1 == 2004) {
/* disable bracketed paste */
Genode::warning("Sequence '[?2004l' is not implemented");
return true;
}
return false;
case 'h':
if (p1 == 7) return (_screen.smam(), true);
if (p1 == 25) return (_screen.cnorm(), true);
if (p1 == 7) return (_screen.smam(), true);
if (p1 == 25) return (_screen.cnorm(), true);
if (p1 == 2004) {
/* enable bracketed paste */
Genode::warning("Sequence '[?2004h' is not implemented");
return true;
}
return false;
case 'c':
if (p1 == 0) return true; /* appended to cnorm */
@ -328,39 +343,17 @@ class Terminal::Decoder
switch (command) {
case 'r': return (_screen.csr(p[0], p[1]), true);
case 'H': return (_screen.cup(p[0], p[1]), true);
case 'm': {
bool result = false;
case 'm':
for (int i = 0; i < 2; i++) {
for (int i = 0; i < 2; i++)
if (!_sgr(p[i]))
Genode::warning("Number ", p[i],
" in sequence '[",
p[0], ";",
p[1], "m' is not implemented");
if (p[i] == 0) {
/* turn off all attributes */
_screen.sgr0();
result = true;
return true;
} else if (p[i] == 1) {
/*
* attribute
* 1 bold (turn into highlight)
*/
_screen.sgr(p[i]);
result = true;
} else if ((p[i] >= 30) && (p[i] <= 37)) {
/*
* color
* 30...37 text colors
* 40...47 background colors
*/
_screen.setaf(p[i] - 30);
return true;
} else if ((p[i] == 39) && (p[!i] == 49))
return (_screen.op(), true);
}
return result;
}
case 'R': return (_screen.u6(p[0], p[1]), true);
default: return false;
}
@ -381,20 +374,24 @@ class Terminal::Decoder
|| (_escape_stack[5].type != Escape_stack::Entry::NUMBER))
return false;
int const p1 = _escape_stack[1].value;
int const p2 = _escape_stack[2].value;
int const p3 = _escape_stack[3].value;
int const p[3] = { _escape_stack[1].value,
_escape_stack[3].value,
_escape_stack[5].value };
int const command = _escape_stack[6].value;
switch (command) {
case 'm':
/*
* Currently returning true w/o actually handling the
* sequence
*/
Genode::warning("Sequence '[", p1, ";", p2, ";", p3, "m' is not implemented");
for (int i = 0; i < 3; i++)
if (!_sgr(p[i]))
Genode::warning("Number ", p[i],
" in sequence '[",
p[0], ";",
p[1], ";",
p[2], "m' is not implemented");
return true;
default: return false;
}