@@ -60,6 +60,24 @@
62#include <HsFFI.h>
62#include <HsFFI.h>
66+// The maximum size for a custom character width table is the total
67+// number of possible characters as dictated by the compiler.
68+#define MAX_CUSTOM_TABLE_SIZE (HS_CHAR_MAX + 1)
70+// The pointer to the start of the custom character width table, if any.
71+// If this is NULL, the built-in tree search logic is used.
72+static uint8_t* custom_table = NULL;
74+// The size of the custom table. This should only be set if custom_table
75+// is not NULL. Its value should be the size of the custom_table array.
76+static uint32_t custom_table_size = 0;
78+// A flag indicating whether the custom table is ready for use. This
79+// should only be set once the table has been allocated and initialized.
80+static uint8_t custom_table_ready = 0;
64struct interval {
82struct interval {
65 int first;
83 int first;
@@ -119,7 +137,7 @@ static int vty_bisearch(HsChar ucs, const struct interval *table, int max) {
119 * in ISO 10646.
137 * in ISO 10646.
122−HsInt vty_mk_wcwidth(HsChar ucs)
140+HsInt builtin_wcwidth(HsChar ucs)
124 /* sorted list of non-overlapping intervals of non-spacing characters */
142 /* sorted list of non-overlapping intervals of non-spacing characters */
125 /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
143 /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
@@ -202,3 +220,99 @@ HsInt vty_mk_wcwidth(HsChar ucs)
202 (ucs >= 0x20000 && ucs <= 0x2fffd) ||
220 (ucs >= 0x20000 && ucs <= 0x2fffd) ||
203 (ucs >= 0x30000 && ucs <= 0x3fffd)));
221 (ucs >= 0x30000 && ucs <= 0x3fffd)));
224+// Return the width, in terminal cells, of the specified character.
226+// If the global custom width table is present, that table will be
227+// consulted for the character's width. If the character is not in
228+// the table, zero will be returned. If the custom width table is not
229+// present, the built-in width table will be used.
230+HsInt vty_mk_wcwidth(HsChar ch)
232+ if (custom_table != NULL) {
233+ if (ch >= 0 && ch < custom_table_size) {
234+ return custom_table[ch];
239+ return builtin_wcwidth(ch);
243+// Initialize a custom character width table.
245+// This allocates a new character width table of the specified size
246+// (in characters). If a custom table has already been allocated, this
247+// returns 1. Otherwise it allocates a new table, initializes all of its
248+// entries to zero, and returns zero.
250+// Note that this does *not* mark the table as ready for use. Until the
251+// table is marked ready, it will not be used by vty_mk_wcwidth. To mark
252+// the table as ready, call vty_activate_custom_table() after the table
253+// has been set up with calls to vty_set_custom_table_range.
254+int vty_init_custom_table(int size)
256+ if (custom_table == NULL) {
257+ if (size > 0 && size <= MAX_CUSTOM_TABLE_SIZE) {
258+ custom_table_ready = 0;
259+ custom_table = malloc(size);
260+ bzero(custom_table, size);
261+ custom_table_size = size;
271+// Set the specified character range in the custom width table to the
274+// This function sets 'width' as the character width for all entries
275+// in the custom character table starting at the 'start' entry and
276+// including all entries up to and including 'start + size - 1'.
278+// If this succeeds, it returns zero. If it fails, it returns 1. It
279+// fails if the table is not allocated, marked as ready (i.e. it is in
280+// use and has already been populated), or if the start or size values
281+// are not in bounds for the table.
282+int vty_set_custom_table_range(uint32_t start, uint32_t size, uint8_t width)
284+ if (custom_table == NULL) {
286+ } else if ((start + size - 1) >= custom_table_size) {
288+ } else if (custom_table_ready) {
291+ memset(custom_table + start, (uint8_t) width, size);
296+// Mark the allocated custom character width table as ready for use.
298+// After this call, further calls to vty_set_custom_table_range will
301+// This function returns 0 if it succeeds. If it fails, it returns 1.
302+// It fails if the custom table is already ready or if it has not been
304+int vty_activate_custom_table()
306+ if (custom_table_ready || (custom_table == NULL)) {
309+ custom_table_ready = 1;
314+// Returns whether a custom character width table has been marked ready.
315+int vty_custom_table_ready()
317+ return ((custom_table != NULL) && custom_table_ready);