Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

vt: add ucs_get_fallback()

This is the code querying the newly introduced tables.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Link: https://lore.kernel.org/r/20250507141535.40655-7-nico@fluxnic.net
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Nicolas Pitre and committed by
Greg Kroah-Hartman
fe26933c de45d93f

+92 -1
+2 -1
drivers/tty/vt/Makefile
··· 36 36 37 37 endif 38 38 39 - $(obj)/ucs.o: $(src)/ucs.c $(obj)/ucs_width_table.h $(obj)/ucs_recompose_table.h 39 + $(obj)/ucs.o: $(src)/ucs.c $(obj)/ucs_width_table.h \ 40 + $(obj)/ucs_recompose_table.h $(obj)/ucs_fallback_table.h 40 41 41 42 # You may uncomment one of those to have the UCS tables be regenerated 42 43 # during the build process. By default the _shipped versions are used.
+84
drivers/tty/vt/ucs.c
··· 157 157 158 158 return result ? result->recomposed : 0; 159 159 } 160 + 161 + /* 162 + * The fallback table structures implement a 2-level lookup. 163 + */ 164 + 165 + struct ucs_page_desc { 166 + u8 page; /* Page index (high byte of code points) */ 167 + u8 count; /* Number of entries in this page */ 168 + u16 start; /* Start index in entries array */ 169 + }; 170 + 171 + struct ucs_page_entry { 172 + u8 offset; /* Offset within page (0-255) */ 173 + u8 fallback; /* Fallback character or range start marker */ 174 + }; 175 + 176 + #include "ucs_fallback_table.h" 177 + 178 + static int ucs_page_desc_cmp(const void *key, const void *element) 179 + { 180 + u8 page = *(u8 *)key; 181 + const struct ucs_page_desc *entry = element; 182 + 183 + if (page < entry->page) 184 + return -1; 185 + if (page > entry->page) 186 + return 1; 187 + return 0; 188 + } 189 + 190 + static int ucs_page_entry_cmp(const void *key, const void *element) 191 + { 192 + u8 offset = *(u8 *)key; 193 + const struct ucs_page_entry *entry = element; 194 + 195 + if (offset < entry->offset) 196 + return -1; 197 + if (entry->fallback == UCS_PAGE_ENTRY_RANGE_MARKER) { 198 + if (offset > entry[1].offset) 199 + return 1; 200 + } else { 201 + if (offset > entry->offset) 202 + return 1; 203 + } 204 + return 0; 205 + } 206 + 207 + /** 208 + * ucs_get_fallback() - Get a substitution for the provided Unicode character 209 + * @base: Base Unicode code point (UCS-4) 210 + * 211 + * Get a simpler fallback character for the provided Unicode character. 212 + * This is used for terminal display when corresponding glyph is unavailable. 213 + * The substitution may not be as good as the actual glyph for the original 214 + * character but still way more helpful than a squared question mark. 215 + * 216 + * Return: Fallback Unicode code point, or 0 if none is available 217 + */ 218 + u32 ucs_get_fallback(u32 cp) 219 + { 220 + const struct ucs_page_desc *page; 221 + const struct ucs_page_entry *entry; 222 + u8 page_idx = cp >> 8, offset = cp; 223 + 224 + if (!UCS_IS_BMP(cp)) 225 + return 0; 226 + 227 + page = __inline_bsearch(&page_idx, ucs_fallback_pages, 228 + ARRAY_SIZE(ucs_fallback_pages), 229 + sizeof(*ucs_fallback_pages), 230 + ucs_page_desc_cmp); 231 + if (!page) 232 + return 0; 233 + 234 + entry = __inline_bsearch(&offset, ucs_fallback_entries + page->start, 235 + page->count, sizeof(*ucs_fallback_entries), 236 + ucs_page_entry_cmp); 237 + if (!entry) 238 + return 0; 239 + 240 + if (entry->fallback == UCS_PAGE_ENTRY_RANGE_MARKER) 241 + entry++; 242 + return entry->fallback; 243 + }
+6
include/linux/consolemap.h
··· 31 31 bool ucs_is_double_width(uint32_t cp); 32 32 bool ucs_is_zero_width(uint32_t cp); 33 33 u32 ucs_recompose(u32 base, u32 mark); 34 + u32 ucs_get_fallback(u32 cp); 34 35 #else 35 36 static inline u16 inverse_translate(const struct vc_data *conp, u16 glyph, 36 37 bool use_unicode) ··· 73 72 } 74 73 75 74 static inline u32 ucs_recompose(u32 base, u32 mark) 75 + { 76 + return 0; 77 + } 78 + 79 + static inline u32 ucs_get_fallback(u32 cp) 76 80 { 77 81 return 0; 78 82 }