From d21b0be246bf3bbf569e6e239f56abb529c7154e Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 26 Jun 2018 23:56:41 -0400 Subject: vt: introduce unicode mode for /dev/vcs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the core vt code knows how to preserve unicode values for each displayed character, it is then possible to let user space access it via /dev/vcs*. Unicode characters are presented as 32 bit values in native endianity via the /dev/vcsu* devices, mimicking the simple /dev/vcs* devices. Unicode with attributes (similarly to /dev/vcsa*) is not supported at the moment. Data is available only as long as the console is in UTF-8 mode. ENODATA is returned otherwise. This was tested with the latest development version (to become version 5.7) of BRLTTY. Amongst other things, this allows ⠋⠕⠗ ⠞⠓⠊⠎ ⠃⠗⠁⠊⠇⠇⠑⠀⠞⠑⠭⠞⠀to appear directly on braille displays regardless of the console font being used. Signed-off-by: Nicolas Pitre Tested-by: Dave Mielke Acked-by: Adam Borowski Signed-off-by: Greg Kroah-Hartman --- include/linux/selection.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include/linux/selection.h') diff --git a/include/linux/selection.h b/include/linux/selection.h index 5b278ce99d8d..2b34df9f1e26 100644 --- a/include/linux/selection.h +++ b/include/linux/selection.h @@ -42,4 +42,9 @@ extern u16 vcs_scr_readw(struct vc_data *vc, const u16 *org); extern void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org); extern void vcs_scr_updated(struct vc_data *vc); +extern int vc_uniscr_check(struct vc_data *vc); +extern void vc_uniscr_copy_line(struct vc_data *vc, void *dest, + unsigned int row, unsigned int col, + unsigned int nr); + #endif -- cgit v1.2.3 From 708d0bff9121506db08adb73845a3c70312fadf3 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 26 Jun 2018 23:56:42 -0400 Subject: vt: unicode fallback for scrollback There is currently no provision for scrollback content in the core code, leaving that to backend video drivers where this can be highly optimized. There is currently no common method for those drivers to tell the core what part of the scrollback is actually displayed and what size the scrollback buffer is either. Because of that, the unicode screen buffer has no provision for any scrollback. At least we can provide backtranslated glyph values when the scrollback is active which should be plenty good enough for now. Signed-off-by: Nicolas Pitre Tested-by: Dave Mielke Acked-by: Adam Borowski Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vc_screen.c | 3 ++- drivers/tty/vt/vt.c | 31 +++++++++++++++++++++++++++++-- include/linux/selection.h | 2 +- 3 files changed, 32 insertions(+), 4 deletions(-) (limited to 'include/linux/selection.h') diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c index 9c44252e52a3..2384ea85ffaf 100644 --- a/drivers/tty/vt/vc_screen.c +++ b/drivers/tty/vt/vc_screen.c @@ -311,7 +311,8 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) do { if (nr > this_round/4) nr = this_round/4; - vc_uniscr_copy_line(vc, con_buf0, row, col, nr); + vc_uniscr_copy_line(vc, con_buf0, viewed, + row, col, nr); con_buf0 += nr * 4; this_round -= nr * 4; row++; diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 062ce6be7957..2d14bb195d98 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -533,13 +533,40 @@ int vc_uniscr_check(struct vc_data *vc) * This must be preceded by a successful call to vc_uniscr_check() once * the console lock has been taken. */ -void vc_uniscr_copy_line(struct vc_data *vc, void *dest, +void vc_uniscr_copy_line(struct vc_data *vc, void *dest, int viewed, unsigned int row, unsigned int col, unsigned int nr) { struct uni_screen *uniscr = get_vc_uniscr(vc); + int offset = row * vc->vc_size_row + col * 2; + unsigned long pos; BUG_ON(!uniscr); - memcpy(dest, &uniscr->lines[row][col], nr * sizeof(char32_t)); + + pos = (unsigned long)screenpos(vc, offset, viewed); + if (pos >= vc->vc_origin && pos < vc->vc_scr_end) { + /* + * Desired position falls in the main screen buffer. + * However the actual row/col might be different if + * scrollback is active. + */ + row = (pos - vc->vc_origin) / vc->vc_size_row; + col = ((pos - vc->vc_origin) % vc->vc_size_row) / 2; + memcpy(dest, &uniscr->lines[row][col], nr * sizeof(char32_t)); + } else { + /* + * Scrollback is active. For now let's simply backtranslate + * the screen glyphs until the unicode screen buffer does + * synchronize with console display drivers for a scrollback + * buffer of its own. + */ + u16 *p = (u16 *)pos; + int mask = vc->vc_hi_font_mask | 0xff; + char32_t *uni_buf = dest; + while (nr--) { + u16 glyph = scr_readw(p++) & mask; + *uni_buf++ = inverse_translate(vc, glyph, true); + } + } } diff --git a/include/linux/selection.h b/include/linux/selection.h index 2b34df9f1e26..067d2e99c79f 100644 --- a/include/linux/selection.h +++ b/include/linux/selection.h @@ -43,7 +43,7 @@ extern void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org); extern void vcs_scr_updated(struct vc_data *vc); extern int vc_uniscr_check(struct vc_data *vc); -extern void vc_uniscr_copy_line(struct vc_data *vc, void *dest, +extern void vc_uniscr_copy_line(struct vc_data *vc, void *dest, int viewed, unsigned int row, unsigned int col, unsigned int nr); -- cgit v1.2.3 From 9bfdc2611d417be453c3deb7a7ef2ffc718febfa Mon Sep 17 00:00:00 2001 From: Adam Borowski Date: Wed, 18 Jul 2018 04:10:44 +0200 Subject: vt: selection: take screen contents from uniscr if available This preserves whatever was written even if we can't currently display the given glyph. Mouse paste won't corrupt any character of wcwidth() == 1 anymore. Note that for now uniscr doesn't get allocated until something reads /dev/vcsuN for that console, making this code dormant for most users. Signed-off-by: Adam Borowski Acked-by: Nicolas Pitre Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/selection.c | 11 +++++++---- drivers/tty/vt/vt.c | 10 ++++++++++ include/linux/selection.h | 1 + 3 files changed, 18 insertions(+), 4 deletions(-) (limited to 'include/linux/selection.h') diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index 69ca337d3220..07496c711d7d 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -57,11 +57,13 @@ static inline void highlight_pointer(const int where) complement_pos(sel_cons, where); } -static u16 +static u32 sel_pos(int n) { + if (use_unicode) + return screen_glyph_unicode(sel_cons, n / 2); return inverse_translate(sel_cons, screen_glyph(sel_cons, n), - use_unicode); + 0); } /** @@ -90,7 +92,8 @@ static u32 inwordLut[]={ 0x07FFFFFE, /* lowercase */ }; -static inline int inword(const u16 c) { +static inline int inword(const u32 c) +{ return c > 0x7f || (( inwordLut[c>>5] >> (c & 0x1F) ) & 1); } @@ -167,7 +170,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t struct tiocl_selection v; char *bp, *obp; int i, ps, pe, multiplier; - u16 c; + u32 c; int mode; poke_blanked_console(); diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 846dfedb657d..7adcb6dcc50c 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -4543,6 +4543,16 @@ u16 screen_glyph(struct vc_data *vc, int offset) } EXPORT_SYMBOL_GPL(screen_glyph); +u32 screen_glyph_unicode(struct vc_data *vc, int n) +{ + struct uni_screen *uniscr = get_vc_uniscr(vc); + + if (uniscr) + return uniscr->lines[n / vc->vc_cols][n % vc->vc_cols]; + return inverse_translate(vc, screen_glyph(vc, n * 2), 1); +} +EXPORT_SYMBOL_GPL(screen_glyph_unicode); + /* used by vcs - note the word offset */ unsigned short *screen_pos(struct vc_data *vc, int w_offset, int viewed) { diff --git a/include/linux/selection.h b/include/linux/selection.h index 067d2e99c79f..a8f5b97b216f 100644 --- a/include/linux/selection.h +++ b/include/linux/selection.h @@ -32,6 +32,7 @@ extern unsigned char default_blu[]; extern unsigned short *screen_pos(struct vc_data *vc, int w_offset, int viewed); extern u16 screen_glyph(struct vc_data *vc, int offset); +extern u32 screen_glyph_unicode(struct vc_data *vc, int offset); extern void complement_pos(struct vc_data *vc, int offset); extern void invert_screen(struct vc_data *vc, int offset, int count, int shift); -- cgit v1.2.3