Commit fe26933c authored by Nicolas Pitre's avatar Nicolas Pitre Committed by Greg Kroah-Hartman
Browse files

vt: add ucs_get_fallback()



This is the code querying the newly introduced tables.

Signed-off-by: default avatarNicolas Pitre <npitre@baylibre.com>
Link: https://lore.kernel.org/r/20250507141535.40655-7-nico@fluxnic.net


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent de45d93f
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -36,7 +36,8 @@ $(obj)/defkeymap.c: $(obj)/%.c: $(src)/%.map

endif

$(obj)/ucs.o: $(src)/ucs.c $(obj)/ucs_width_table.h $(obj)/ucs_recompose_table.h
$(obj)/ucs.o:	$(src)/ucs.c $(obj)/ucs_width_table.h \
		$(obj)/ucs_recompose_table.h $(obj)/ucs_fallback_table.h

# You may uncomment one of those to have the UCS tables be regenerated
# during the build process. By default the _shipped versions are used.
+84 −0
Original line number Diff line number Diff line
@@ -157,3 +157,87 @@ u32 ucs_recompose(u32 base, u32 mark)

	return result ? result->recomposed : 0;
}

/*
 * The fallback table structures implement a 2-level lookup.
 */

struct ucs_page_desc {
	u8 page;	/* Page index (high byte of code points) */
	u8 count;	/* Number of entries in this page */
	u16 start;	/* Start index in entries array */
};

struct ucs_page_entry {
	u8 offset;	/* Offset within page (0-255) */
	u8 fallback;	/* Fallback character or range start marker */
};

#include "ucs_fallback_table.h"

static int ucs_page_desc_cmp(const void *key, const void *element)
{
	u8 page = *(u8 *)key;
	const struct ucs_page_desc *entry = element;

	if (page < entry->page)
		return -1;
	if (page > entry->page)
		return 1;
	return 0;
}

static int ucs_page_entry_cmp(const void *key, const void *element)
{
	u8 offset = *(u8 *)key;
	const struct ucs_page_entry *entry = element;

	if (offset < entry->offset)
		return -1;
	if (entry->fallback == UCS_PAGE_ENTRY_RANGE_MARKER) {
		if (offset > entry[1].offset)
			return 1;
	} else {
		if (offset > entry->offset)
			return 1;
	}
	return 0;
}

/**
 * ucs_get_fallback() - Get a substitution for the provided Unicode character
 * @base: Base Unicode code point (UCS-4)
 *
 * Get a simpler fallback character for the provided Unicode character.
 * This is used for terminal display when corresponding glyph is unavailable.
 * The substitution may not be as good as the actual glyph for the original
 * character but still way more helpful than a squared question mark.
 *
 * Return: Fallback Unicode code point, or 0 if none is available
 */
u32 ucs_get_fallback(u32 cp)
{
	const struct ucs_page_desc *page;
	const struct ucs_page_entry *entry;
	u8 page_idx = cp >> 8, offset = cp;

	if (!UCS_IS_BMP(cp))
		return 0;

	page = __inline_bsearch(&page_idx, ucs_fallback_pages,
				ARRAY_SIZE(ucs_fallback_pages),
				sizeof(*ucs_fallback_pages),
				ucs_page_desc_cmp);
	if (!page)
		return 0;

	entry = __inline_bsearch(&offset, ucs_fallback_entries + page->start,
				 page->count, sizeof(*ucs_fallback_entries),
				 ucs_page_entry_cmp);
	if (!entry)
		return 0;

	if (entry->fallback == UCS_PAGE_ENTRY_RANGE_MARKER)
		entry++;
	return entry->fallback;
}
+6 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ void console_map_init(void);
bool ucs_is_double_width(uint32_t cp);
bool ucs_is_zero_width(uint32_t cp);
u32 ucs_recompose(u32 base, u32 mark);
u32 ucs_get_fallback(u32 cp);
#else
static inline u16 inverse_translate(const struct vc_data *conp, u16 glyph,
		bool use_unicode)
@@ -75,6 +76,11 @@ static inline u32 ucs_recompose(u32 base, u32 mark)
{
	return 0;
}

static inline u32 ucs_get_fallback(u32 cp)
{
	return 0;
}
#endif /* CONFIG_CONSOLE_TRANSLATIONS */

#endif /* __LINUX_CONSOLEMAP_H__ */