mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-21 10:01:57 +00:00
Refactor terminal for intrinsic Unicode support
Refactor the graphical terminal server to internally represent characters as 16-bit codepoints and handle the duplex terminal stream as UTF-8. - Make the Codepoint class printable to the Output interface - Decode data received at the Terminal session from UTF-8 to a 16-bit character - Pass 16-bit characters through terminal decoder and char-cell arrays - Send Unicode through terminal session in a burst of UTF-8 bytes Fix #3148
This commit is contained in:
parent
0c24e1efdc
commit
22327b43ae
@ -1,9 +1,9 @@
|
||||
create_boot_directory
|
||||
|
||||
import_from_depot genodelabs/src/[base_src] \
|
||||
genodelabs/pkg/[drivers_interactive_pkg] \
|
||||
genodelabs/pkg/terminal \
|
||||
genodelabs/src/init
|
||||
import_from_depot [depot_user]/src/[base_src] \
|
||||
[depot_user]/pkg/[drivers_interactive_pkg] \
|
||||
[depot_user]/pkg/terminal \
|
||||
[depot_user]/src/init
|
||||
|
||||
install_config {
|
||||
<config>
|
||||
|
@ -1,12 +1,12 @@
|
||||
create_boot_directory
|
||||
|
||||
import_from_depot genodelabs/src/[base_src] \
|
||||
genodelabs/pkg/[drivers_interactive_pkg] \
|
||||
genodelabs/pkg/terminal \
|
||||
genodelabs/src/nitpicker \
|
||||
genodelabs/src/nit_fb \
|
||||
genodelabs/src/demo \
|
||||
genodelabs/src/init
|
||||
import_from_depot [depot_user]/src/[base_src] \
|
||||
[depot_user]/pkg/[drivers_interactive_pkg] \
|
||||
[depot_user]/pkg/terminal \
|
||||
[depot_user]/src/nitpicker \
|
||||
[depot_user]/src/nit_fb \
|
||||
[depot_user]/src/demo \
|
||||
[depot_user]/src/init
|
||||
|
||||
install_config {
|
||||
<config>
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2011-2019 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -254,29 +254,6 @@ void Terminal::Main::_handle_input()
|
||||
|
||||
event.handle_press([&] (Input::Keycode, Codepoint codepoint) {
|
||||
|
||||
struct Utf8 { char b0, b1, b2, b3, b4; };
|
||||
|
||||
auto utf8_from_codepoint = [] (unsigned c) {
|
||||
|
||||
/* extract 'n' bits 'at' bit position of value 'c' */
|
||||
auto bits = [c] (unsigned at, unsigned n) {
|
||||
return (c >> at) & ((1 << n) - 1); };
|
||||
|
||||
return (c < 2<<7) ? Utf8 { char(bits( 0, 7)), 0, 0, 0, 0 }
|
||||
: (c < 2<<11) ? Utf8 { char(bits( 6, 5) | 0xc0),
|
||||
char(bits( 0, 6) | 0x80), 0, 0, 0 }
|
||||
: (c < 2<<16) ? Utf8 { char(bits(12, 4) | 0xe0),
|
||||
char(bits( 6, 6) | 0x80),
|
||||
char(bits( 0, 6) | 0x80), 0, 0 }
|
||||
: (c < 2<<21) ? Utf8 { char(bits(18, 3) | 0xf0),
|
||||
char(bits(12, 6) | 0x80),
|
||||
char(bits( 6, 6) | 0x80),
|
||||
char(bits( 0, 6) | 0x80), 0 }
|
||||
: Utf8 { };
|
||||
};
|
||||
|
||||
Utf8 const sequence = utf8_from_codepoint(codepoint.value);
|
||||
|
||||
/* function-key unicodes */
|
||||
enum {
|
||||
CODEPOINT_UP = 0xf700, CODEPOINT_DOWN = 0xf701,
|
||||
@ -321,7 +298,7 @@ void Terminal::Main::_handle_input()
|
||||
if (special_sequence)
|
||||
_read_buffer.add(special_sequence);
|
||||
else
|
||||
_read_buffer.add(&sequence.b0);
|
||||
_read_buffer.add(codepoint);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018 Genode Labs GmbH
|
||||
* Copyright (C) 2018-2019 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -105,7 +105,8 @@ class Terminal::Session_component : public Rpc_object<Session, Session_component
|
||||
unsigned i = 0;
|
||||
for (Utf8_ptr utf8(src); utf8.complete() && i < max; ) {
|
||||
|
||||
_character_consumer.consume_character(utf8.codepoint().value);
|
||||
_character_consumer.consume_character(
|
||||
Terminal::Character(utf8.codepoint()));
|
||||
|
||||
i += utf8.length();
|
||||
if (i >= max)
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2018 Genode Labs GmbH
|
||||
* Copyright (C) 2011-2019 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -198,14 +198,8 @@ class Terminal::Text_screen_surface
|
||||
for (unsigned column = 0; column < _cell_array.num_cols(); column++) {
|
||||
|
||||
Char_cell cell = _cell_array.get_cell(column, line);
|
||||
unsigned char ascii = cell.ascii;
|
||||
|
||||
if (ascii == 0)
|
||||
ascii = ' ';
|
||||
|
||||
Text_painter::Codepoint const c { ascii };
|
||||
|
||||
_font.apply_glyph(c, [&] (Glyph_painter::Glyph const &glyph) {
|
||||
_font.apply_glyph(cell.codepoint(), [&] (Glyph_painter::Glyph const &glyph) {
|
||||
|
||||
Color_palette::Highlighted const highlighted { cell.highlight() };
|
||||
Color_palette::Inverse const inverse { cell.inverse() };
|
||||
@ -274,7 +268,7 @@ class Terminal::Text_screen_surface
|
||||
void apply_character(Character c)
|
||||
{
|
||||
/* submit character to sequence decoder */
|
||||
_decoder.insert(c.c);
|
||||
_decoder.insert(c);
|
||||
}
|
||||
|
||||
void import(Snapshot const &snapshot)
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018 Genode Labs GmbH
|
||||
* Copyright (C) 2018-2019 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
|
@ -47,9 +47,9 @@ static void convert_char_array_to_window(Cell_array<Char_cell> *cell_array,
|
||||
for (unsigned column = 0; column < cell_array->num_cols(); column++) {
|
||||
|
||||
Char_cell cell = cell_array->get_cell(column, line);
|
||||
unsigned char ascii = cell.ascii;
|
||||
unsigned char ascii = cell.codepoint().value;
|
||||
|
||||
if (ascii == 0) {
|
||||
if (ascii == 0 || ascii & 0x80) {
|
||||
window.print_char(' ', false, false);
|
||||
continue;
|
||||
}
|
||||
@ -301,10 +301,12 @@ class Terminal::Session_component : public Genode::Rpc_object<Session, Session_c
|
||||
{
|
||||
unsigned char *src = _io_buffer.local_addr<unsigned char>();
|
||||
|
||||
Terminal::Character character;
|
||||
for (unsigned i = 0; i < num_bytes; i++) {
|
||||
|
||||
/* submit character to sequence decoder */
|
||||
_decoder.insert(src[i]);
|
||||
character.value = src[i];
|
||||
_decoder.insert(character);
|
||||
}
|
||||
|
||||
return num_bytes;
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2013-2019 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -20,8 +20,9 @@
|
||||
|
||||
struct Char_cell
|
||||
{
|
||||
Genode::uint16_t value { ' ' };
|
||||
|
||||
unsigned char attr;
|
||||
unsigned char ascii;
|
||||
unsigned char color;
|
||||
|
||||
enum { ATTR_COLIDX_MASK = 0x07U,
|
||||
@ -31,14 +32,14 @@ struct Char_cell
|
||||
|
||||
enum { COLOR_MASK = 0x3f }; /* 111111 */
|
||||
|
||||
Char_cell() : attr(0), ascii(0), color(0) { }
|
||||
Char_cell() : attr(0), color(0) { }
|
||||
|
||||
Char_cell(unsigned char c, Font_face f,
|
||||
Char_cell(Terminal::Character c, Font_face f,
|
||||
int colidx, bool inv, bool highlight)
|
||||
:
|
||||
value(c.value),
|
||||
attr(f.attr_bits() | (inv ? ATTR_INVERSE : 0)
|
||||
| (highlight ? ATTR_HIGHLIGHT : 0)),
|
||||
ascii(c),
|
||||
color(colidx & COLOR_MASK)
|
||||
{ }
|
||||
|
||||
@ -56,6 +57,9 @@ struct Char_cell
|
||||
void clear_cursor() { attr &= ~ATTR_CURSOR; }
|
||||
|
||||
bool has_cursor() const { return attr & ATTR_CURSOR; }
|
||||
|
||||
Terminal::Codepoint codepoint() const {
|
||||
return Terminal::Codepoint { value }; }
|
||||
};
|
||||
|
||||
|
||||
@ -184,7 +188,7 @@ class Char_cell_array_character_screen : public Terminal::Character_screen
|
||||
if (_irm == INSERT)
|
||||
_missing("insert mode");
|
||||
|
||||
switch (c.ascii()) {
|
||||
switch (c.value) {
|
||||
|
||||
case '\n': /* 10 */
|
||||
_new_line();
|
||||
@ -215,10 +219,10 @@ class Char_cell_array_character_screen : public Terminal::Character_screen
|
||||
}
|
||||
|
||||
default:
|
||||
if (c.ascii() > 0x1f) {
|
||||
if (c.value > 0x1f) {
|
||||
Cursor_guard guard(*this);
|
||||
_char_cell_array.set_cell(_cursor_pos.x, _cursor_pos.y,
|
||||
Char_cell(c.ascii(), Font_face::REGULAR,
|
||||
Char_cell(c, Font_face::REGULAR,
|
||||
_color_index, _inverse, _highlight));
|
||||
_cursor_pos.x++;
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2011-2019 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
|
@ -1,11 +1,12 @@
|
||||
/*
|
||||
* \brief Escape-sequence decoder
|
||||
* \author Norman Feske
|
||||
* \author Emery Hemingway
|
||||
* \date 2011-06-06
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2011-2019 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -452,8 +453,10 @@ class Terminal::Decoder
|
||||
|
||||
Decoder(Character_screen &screen) : _screen(screen) { }
|
||||
|
||||
void insert(unsigned char c)
|
||||
void insert(Character character)
|
||||
{
|
||||
auto const c = character.value;
|
||||
|
||||
switch (_state) {
|
||||
|
||||
case STATE_IDLE:
|
||||
@ -467,7 +470,7 @@ class Terminal::Decoder
|
||||
/* handle special characters */
|
||||
|
||||
/* handle normal characters */
|
||||
_screen.output(c);
|
||||
_screen.output(character);
|
||||
|
||||
break;
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2011-2019 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -15,6 +15,7 @@
|
||||
#define _TERMINAL__READ_BUFFER_H_
|
||||
|
||||
#include <os/ring_buffer.h>
|
||||
#include <util/utf8.h>
|
||||
#include <base/signal.h>
|
||||
|
||||
|
||||
@ -50,6 +51,19 @@ class Terminal::Read_buffer : public Genode::Ring_buffer<unsigned char, READ_BUF
|
||||
Genode::Signal_transmitter(_sigh_cap).submit();
|
||||
}
|
||||
|
||||
void add(Codepoint code)
|
||||
{
|
||||
/* send Unicode in a burst of UTF-8 */
|
||||
Genode::String<5> utf8(code);
|
||||
char const *str = utf8.string();
|
||||
|
||||
while (*str)
|
||||
Genode::Ring_buffer<unsigned char, READ_BUFFER_SIZE>::add(*str++);
|
||||
|
||||
if (_sigh_cap.valid())
|
||||
Genode::Signal_transmitter(_sigh_cap).submit();
|
||||
}
|
||||
|
||||
void add(char const *str)
|
||||
{
|
||||
while (*str)
|
||||
|
@ -15,10 +15,11 @@
|
||||
#define _TERMINAL__TYPES_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/utf8.h>
|
||||
#include <util/interface.h>
|
||||
|
||||
namespace Terminal {
|
||||
|
||||
using Genode::Codepoint;
|
||||
struct Character;
|
||||
struct Boundary;
|
||||
struct Offset;
|
||||
@ -34,14 +35,13 @@ namespace Terminal {
|
||||
*/
|
||||
struct Terminal::Character
|
||||
{
|
||||
unsigned char c;
|
||||
Genode::uint16_t value;
|
||||
|
||||
Character() : c(0) { }
|
||||
Character(unsigned char c) : c(c) { }
|
||||
Character() : value(0) { }
|
||||
Character(Codepoint cp)
|
||||
: value(cp.value < 1<<16 ? cp.value : 0) { }
|
||||
|
||||
bool valid() const { return c != 0; }
|
||||
|
||||
unsigned char ascii() const { return c; }
|
||||
bool valid() const { return value != 0; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018 Genode Labs GmbH
|
||||
* Copyright (C) 2018-2019 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -14,6 +14,7 @@
|
||||
#ifndef _INCLUDE__OS__UTIL__UTF8_H_
|
||||
#define _INCLUDE__OS__UTIL__UTF8_H_
|
||||
|
||||
#include <base/output.h>
|
||||
#include <base/stdint.h>
|
||||
|
||||
namespace Genode {
|
||||
@ -29,6 +30,32 @@ struct Genode::Codepoint
|
||||
uint32_t value;
|
||||
|
||||
bool valid() const { return value != INVALID; }
|
||||
|
||||
void print(Output &output) const
|
||||
{
|
||||
/* extract 'n' bits 'at' bit position of value */
|
||||
auto bits = [&] (unsigned at, unsigned n) {
|
||||
return (char)((value >> at) & ((1 << n) - 1)); };
|
||||
|
||||
if (value < 1<<7) {
|
||||
output.out_char(bits( 0, 7));
|
||||
} else
|
||||
if (value < 1<<11) {
|
||||
output.out_char(bits( 6, 5) | 0xc0);
|
||||
output.out_char(bits( 0, 6) | 0x80);
|
||||
} else
|
||||
if (value < 1<<16) {
|
||||
output.out_char(bits(12, 4) | 0xe0);
|
||||
output.out_char(bits( 6, 6) | 0x80);
|
||||
output.out_char(bits( 0, 6) | 0x80);
|
||||
} else
|
||||
if (value < 0x11<<16) {
|
||||
output.out_char(bits(18, 3) | 0xf0);
|
||||
output.out_char(bits(12, 6) | 0x80);
|
||||
output.out_char(bits( 6, 6) | 0x80);
|
||||
output.out_char(bits( 0, 6) | 0x80);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user