@@ -157,3 +157,87 @@ u32 ucs_recompose(u32 base, u32 mark)
157157
158158 return result ? result -> recomposed : 0 ;
159159}
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+ }
0 commit comments