mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-21 08:29:41 +00:00
terminal: don't overwrite last column until eol
Introduce a new _overflowed state variable to indicate whether the horizontal boundary was reached already and to omit subsequent character output. This state is necessary to maintain a valid cursor position at all times. The _overflowed attribute is reset once the cursor is moved into a valid position again. To harmonise the bounds checking for _cursor_pos modifications, the `constrain()` method was added. Fixes genodelabs/genode#4093 Also fixes a bug in `vpa()` and `vpb()` which moved the cursor horizontally instead of vertically.
This commit is contained in:
committed by
Norman Feske
parent
9cb8c37e3a
commit
1c49da8ce4
@ -94,6 +94,8 @@ class Char_cell_array_character_screen : public Terminal::Character_screen
|
|||||||
|
|
||||||
bool _wrap = false;
|
bool _wrap = false;
|
||||||
|
|
||||||
|
bool _overflowed = false;
|
||||||
|
|
||||||
enum { DEFAULT_COLOR_INDEX_BG = 0, DEFAULT_COLOR_INDEX = 7, DEFAULT_TAB_SIZE = 8 };
|
enum { DEFAULT_COLOR_INDEX_BG = 0, DEFAULT_COLOR_INDEX = 7, DEFAULT_TAB_SIZE = 8 };
|
||||||
|
|
||||||
struct Cursor_guard
|
struct Cursor_guard
|
||||||
@ -117,7 +119,13 @@ class Char_cell_array_character_screen : public Terminal::Character_screen
|
|||||||
|
|
||||||
/* if cursor position changed, move cursor */
|
/* if cursor position changed, move cursor */
|
||||||
Terminal::Position &new_cursor_pos = cs._cursor_pos;
|
Terminal::Position &new_cursor_pos = cs._cursor_pos;
|
||||||
|
Terminal::Boundary const &boundary = cs._boundary;
|
||||||
if (old_cursor_pos != new_cursor_pos) {
|
if (old_cursor_pos != new_cursor_pos) {
|
||||||
|
cs._overflowed = (new_cursor_pos.x >= boundary.width);
|
||||||
|
|
||||||
|
/* make sure cursor pos is within range */
|
||||||
|
new_cursor_pos.constrain(boundary);
|
||||||
|
|
||||||
cs._char_cell_array.cursor(old_cursor_pos, false, true);
|
cs._char_cell_array.cursor(old_cursor_pos, false, true);
|
||||||
cs._char_cell_array.cursor(
|
cs._char_cell_array.cursor(
|
||||||
new_cursor_pos, cs._cursor_visibility != CURSOR_INVISIBLE, true);
|
new_cursor_pos, cs._cursor_visibility != CURSOR_INVISIBLE, true);
|
||||||
@ -179,8 +187,9 @@ class Char_cell_array_character_screen : public Terminal::Character_screen
|
|||||||
|
|
||||||
void cursor_pos(Terminal::Position pos)
|
void cursor_pos(Terminal::Position pos)
|
||||||
{
|
{
|
||||||
_cursor_pos.x = Genode::min(_boundary.width - 1, pos.x);
|
Cursor_guard guard(*this);
|
||||||
_cursor_pos.y = Genode::min(_boundary.height - 1, pos.y);
|
|
||||||
|
_cursor_pos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void output(Terminal::Character c) override
|
void output(Terminal::Character c) override
|
||||||
@ -219,7 +228,7 @@ class Char_cell_array_character_screen : public Terminal::Character_screen
|
|||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (c.value > 0x1f) {
|
if (c.value > 0x1f && !_overflowed) {
|
||||||
Cursor_guard guard(*this);
|
Cursor_guard guard(*this);
|
||||||
_char_cell_array.set_cell(_cursor_pos.x, _cursor_pos.y,
|
_char_cell_array.set_cell(_cursor_pos.x, _cursor_pos.y,
|
||||||
Char_cell(c, Font_face::REGULAR,
|
Char_cell(c, Font_face::REGULAR,
|
||||||
@ -229,19 +238,17 @@ class Char_cell_array_character_screen : public Terminal::Character_screen
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_cursor_pos.x >= _boundary.width) {
|
if (_wrap && _overflowed) {
|
||||||
if (_wrap) {
|
|
||||||
_new_line();
|
_new_line();
|
||||||
} else {
|
|
||||||
_cursor_pos.x = _boundary.width-1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cha(int pn) override
|
void cha(int pn) override
|
||||||
{
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
Cursor_guard guard(*this);
|
Cursor_guard guard(*this);
|
||||||
_cursor_pos.x = Genode::max(pn - 1, _boundary.width);
|
_cursor_pos.x = pn - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void civis() override
|
void civis() override
|
||||||
@ -280,7 +287,6 @@ class Char_cell_array_character_screen : public Terminal::Character_screen
|
|||||||
Cursor_guard guard(*this);
|
Cursor_guard guard(*this);
|
||||||
|
|
||||||
_cursor_pos.x -= dx;
|
_cursor_pos.x -= dx;
|
||||||
_cursor_pos.x = Genode::max(0, _cursor_pos.x);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cud(int dy) override
|
void cud(int dy) override
|
||||||
@ -288,7 +294,6 @@ class Char_cell_array_character_screen : public Terminal::Character_screen
|
|||||||
Cursor_guard guard(*this);
|
Cursor_guard guard(*this);
|
||||||
|
|
||||||
_cursor_pos.y += dy;
|
_cursor_pos.y += dy;
|
||||||
_cursor_pos.y = Genode::min(_boundary.height - 1, _cursor_pos.y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cuf(int dx) override
|
void cuf(int dx) override
|
||||||
@ -296,7 +301,6 @@ class Char_cell_array_character_screen : public Terminal::Character_screen
|
|||||||
Cursor_guard guard(*this);
|
Cursor_guard guard(*this);
|
||||||
|
|
||||||
_cursor_pos.x += dx;
|
_cursor_pos.x += dx;
|
||||||
_cursor_pos.x = Genode::min(_boundary.width - 1, _cursor_pos.x);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cup(int y, int x) override
|
void cup(int y, int x) override
|
||||||
@ -307,10 +311,6 @@ class Char_cell_array_character_screen : public Terminal::Character_screen
|
|||||||
x--;
|
x--;
|
||||||
y--;
|
y--;
|
||||||
|
|
||||||
using namespace Genode;
|
|
||||||
x = max(0, min(x, _boundary.width - 1));
|
|
||||||
y = max(0, min(y, _boundary.height - 1));
|
|
||||||
|
|
||||||
_cursor_pos = Terminal::Position(x, y);
|
_cursor_pos = Terminal::Position(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,7 +319,6 @@ class Char_cell_array_character_screen : public Terminal::Character_screen
|
|||||||
Cursor_guard guard(*this);
|
Cursor_guard guard(*this);
|
||||||
|
|
||||||
_cursor_pos.y -= dy;
|
_cursor_pos.y -= dy;
|
||||||
_cursor_pos.y = Genode::max(0, _cursor_pos.y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void da(int) override { _missing(__func__); }
|
void da(int) override { _missing(__func__); }
|
||||||
@ -429,7 +428,8 @@ class Char_cell_array_character_screen : public Terminal::Character_screen
|
|||||||
|
|
||||||
void ich(int pn) override
|
void ich(int pn) override
|
||||||
{
|
{
|
||||||
pn = Genode::min(_boundary.width - _cursor_pos.x, pn);
|
using namespace Genode;
|
||||||
|
pn = max(0, min(_boundary.width - _cursor_pos.x, pn));
|
||||||
|
|
||||||
for (int x = _boundary.width-1; _cursor_pos.x+pn < x; --x) {
|
for (int x = _boundary.width-1; _cursor_pos.x+pn < x; --x) {
|
||||||
_char_cell_array.set_cell(x, _cursor_pos.y,
|
_char_cell_array.set_cell(x, _cursor_pos.y,
|
||||||
@ -565,13 +565,13 @@ class Char_cell_array_character_screen : public Terminal::Character_screen
|
|||||||
void vpa(int pn) override
|
void vpa(int pn) override
|
||||||
{
|
{
|
||||||
Cursor_guard guard(*this);
|
Cursor_guard guard(*this);
|
||||||
_cursor_pos.x = pn;
|
_cursor_pos.y = pn - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vpb(int pn) override
|
void vpb(int pn) override
|
||||||
{
|
{
|
||||||
Cursor_guard guard(*this);
|
Cursor_guard guard(*this);
|
||||||
_cursor_pos.x = Genode::min(0, _cursor_pos.x - pn);
|
_cursor_pos.y -= pn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void decsc() override
|
void decsc() override
|
||||||
|
@ -102,6 +102,16 @@ struct Terminal::Position
|
|||||||
&& y >= 0 && y < boundary.height;
|
&& y >= 0 && y < boundary.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make sure that position lies within specified boundaries
|
||||||
|
*/
|
||||||
|
void constrain(Boundary const &boundary)
|
||||||
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
x = max(0, min(boundary.width - 1, x));
|
||||||
|
y = max(0, min(boundary.height - 1, y));
|
||||||
|
}
|
||||||
|
|
||||||
void print(Genode::Output &out) const {
|
void print(Genode::Output &out) const {
|
||||||
Genode::print(out, y, ",", x); }
|
Genode::print(out, y, ",", x); }
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user