mirror of
https://github.com/torvalds/linux.git
synced 2026-05-26 08:02:27 +02:00
vt: move unicode processing to a separate file
This will make it easier to maintain. Also make it depend on CONFIG_CONSOLE_TRANSLATIONS. Signed-off-by: Nicolas Pitre <npitre@baylibre.com> Reviewed-by: Jiri Slaby <jirislaby@kernel.org> Link: https://lore.kernel.org/r/20250417184849.475581-3-nico@fluxnic.net Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
d066989a3d
commit
07bc3f442f
|
|
@ -7,7 +7,8 @@ FONTMAPFILE = cp437.uni
|
|||
obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o \
|
||||
selection.o keyboard.o \
|
||||
vt.o defkeymap.o
|
||||
obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o
|
||||
obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o \
|
||||
ucs.o
|
||||
|
||||
# Files generated that shall be removed upon make clean
|
||||
clean-files := consolemap_deftbl.c defkeymap.c
|
||||
|
|
|
|||
57
drivers/tty/vt/ucs.c
Normal file
57
drivers/tty/vt/ucs.c
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* ucs.c - Universal Character Set processing
|
||||
*/
|
||||
|
||||
#include <linux/array_size.h>
|
||||
#include <linux/bsearch.h>
|
||||
#include <linux/consolemap.h>
|
||||
#include <linux/minmax.h>
|
||||
|
||||
/* ucs_is_double_width() is based on the wcwidth() implementation by
|
||||
* Markus Kuhn -- 2007-05-26 (Unicode 5.0)
|
||||
* Latest version: https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
|
||||
*/
|
||||
|
||||
struct ucs_interval {
|
||||
u32 first;
|
||||
u32 last;
|
||||
};
|
||||
|
||||
static const struct ucs_interval ucs_double_width_ranges[] = {
|
||||
{ 0x1100, 0x115F }, { 0x2329, 0x232A }, { 0x2E80, 0x303E },
|
||||
{ 0x3040, 0xA4CF }, { 0xAC00, 0xD7A3 }, { 0xF900, 0xFAFF },
|
||||
{ 0xFE10, 0xFE19 }, { 0xFE30, 0xFE6F }, { 0xFF00, 0xFF60 },
|
||||
{ 0xFFE0, 0xFFE6 }, { 0x20000, 0x2FFFD }, { 0x30000, 0x3FFFD }
|
||||
};
|
||||
|
||||
static int interval_cmp(const void *key, const void *element)
|
||||
{
|
||||
u32 cp = *(u32 *)key;
|
||||
const struct ucs_interval *entry = element;
|
||||
|
||||
if (cp < entry->first)
|
||||
return -1;
|
||||
if (cp > entry->last)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ucs_is_double_width() - Determine if a Unicode code point is double-width.
|
||||
* @cp: Unicode code point (UCS-4)
|
||||
*
|
||||
* Return: true if the character is double-width, false otherwise
|
||||
*/
|
||||
bool ucs_is_double_width(u32 cp)
|
||||
{
|
||||
size_t size = ARRAY_SIZE(ucs_double_width_ranges);
|
||||
|
||||
if (!in_range(cp, ucs_double_width_ranges[0].first,
|
||||
ucs_double_width_ranges[size - 1].last))
|
||||
return false;
|
||||
|
||||
return __inline_bsearch(&cp, ucs_double_width_ranges, size,
|
||||
sizeof(*ucs_double_width_ranges),
|
||||
interval_cmp) != NULL;
|
||||
}
|
||||
|
|
@ -104,7 +104,6 @@
|
|||
#include <linux/uaccess.h>
|
||||
#include <linux/kdb.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/bsearch.h>
|
||||
#include <linux/gcd.h>
|
||||
|
||||
#define MAX_NR_CON_DRIVER 16
|
||||
|
|
@ -2712,43 +2711,6 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, u8 c)
|
|||
}
|
||||
}
|
||||
|
||||
/* is_double_width() is based on the wcwidth() implementation by
|
||||
* Markus Kuhn -- 2007-05-26 (Unicode 5.0)
|
||||
* Latest version: https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
|
||||
*/
|
||||
struct interval {
|
||||
uint32_t first;
|
||||
uint32_t last;
|
||||
};
|
||||
|
||||
static int ucs_cmp(const void *key, const void *elt)
|
||||
{
|
||||
uint32_t ucs = *(uint32_t *)key;
|
||||
struct interval e = *(struct interval *) elt;
|
||||
|
||||
if (ucs > e.last)
|
||||
return 1;
|
||||
else if (ucs < e.first)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_double_width(uint32_t ucs)
|
||||
{
|
||||
static const struct interval double_width[] = {
|
||||
{ 0x1100, 0x115F }, { 0x2329, 0x232A }, { 0x2E80, 0x303E },
|
||||
{ 0x3040, 0xA4CF }, { 0xAC00, 0xD7A3 }, { 0xF900, 0xFAFF },
|
||||
{ 0xFE10, 0xFE19 }, { 0xFE30, 0xFE6F }, { 0xFF00, 0xFF60 },
|
||||
{ 0xFFE0, 0xFFE6 }, { 0x20000, 0x2FFFD }, { 0x30000, 0x3FFFD }
|
||||
};
|
||||
if (ucs < double_width[0].first ||
|
||||
ucs > double_width[ARRAY_SIZE(double_width) - 1].last)
|
||||
return 0;
|
||||
|
||||
return bsearch(&ucs, double_width, ARRAY_SIZE(double_width),
|
||||
sizeof(struct interval), ucs_cmp) != NULL;
|
||||
}
|
||||
|
||||
struct vc_draw_region {
|
||||
unsigned long from, to;
|
||||
int x;
|
||||
|
|
@ -2953,7 +2915,7 @@ static int vc_con_write_normal(struct vc_data *vc, int tc, int c,
|
|||
bool inverse = false;
|
||||
|
||||
if (vc->vc_utf && !vc->vc_disp_ctrl) {
|
||||
if (is_double_width(c))
|
||||
if (ucs_is_double_width(c))
|
||||
width = 2;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ int conv_uni_to_pc(struct vc_data *conp, long ucs);
|
|||
u32 conv_8bit_to_uni(unsigned char c);
|
||||
int conv_uni_to_8bit(u32 uni);
|
||||
void console_map_init(void);
|
||||
bool ucs_is_double_width(uint32_t cp);
|
||||
#else
|
||||
static inline u16 inverse_translate(const struct vc_data *conp, u16 glyph,
|
||||
bool use_unicode)
|
||||
|
|
@ -57,6 +58,11 @@ static inline int conv_uni_to_8bit(u32 uni)
|
|||
}
|
||||
|
||||
static inline void console_map_init(void) { }
|
||||
|
||||
static inline bool ucs_is_double_width(uint32_t cp)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif /* CONFIG_CONSOLE_TRANSLATIONS */
|
||||
|
||||
#endif /* __LINUX_CONSOLEMAP_H__ */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user