@@ -157,3 +157,87 @@ u32 ucs_recompose(u32 base, u32 mark)
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
+ }
0 commit comments