From: Charlie Brej Date: Wed, 15 Jul 2009 10:30:19 +0000 (+0100) Subject: [utils] Add utf-8 support functions to determine character and string length X-Git-Tag: 0.7.0~157 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fc2d96de67e986e538b02f574ae6981964a038c7;p=thirdparty%2Fplymouth.git [utils] Add utf-8 support functions to determine character and string length These are used to feed the keyboard input a single character at a time, to determine the number of bullets in the password dialogue and process backspaes. --- diff --git a/src/libply/ply-utils.c b/src/libply/ply-utils.c index 25f9e064..3db71634 100644 --- a/src/libply/ply-utils.c +++ b/src/libply/ply-utils.c @@ -891,4 +891,45 @@ ply_detach_daemon (ply_daemon_handle_t *handle, return true; } + +/* UTF-8 encoding +00000000-01111111 00-7F US-ASCII (single byte) +10000000-10111111 80-BF Second, third, or fourth byte of a multi-byte sequence +11000000-11011111 C0-DF Start of 2-byte sequence +11100000-11101111 E0-EF Start of 3-byte sequence +11110000-11110100 F0-F4 Start of 4-byte sequence +*/ + +int +ply_utf8_character_get_size (char *string, + size_t n) +{ + int length; + if (n < 1) return -1; + if (string[0] == 0x00) length = 0; + else if ((string[0] & 0x80) == 0x00) length = 1; + else if ((string[0] & 0xE0) == 0xC0) length = 2; + else if ((string[0] & 0xF0) == 0xE0) length = 3; + else if ((string[0] & 0xF8) == 0xF0) length = 4; + else return -2; + if (length > n) return -1; + return length; +} + +int +ply_utf8_string_get_length (char *string, + size_t n) +{ + size_t count = 0; + while (true) + { + int charlen = ply_utf8_character_get_size(string, n); + if (charlen <= 0) break; + string += charlen; + n -= charlen; + count++; + } + return count; +} + /* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ diff --git a/src/libply/ply-utils.h b/src/libply/ply-utils.h index 53280688..e0d6e856 100644 --- a/src/libply/ply-utils.h +++ b/src/libply/ply-utils.h @@ -38,6 +38,8 @@ #define CLAMP(a,b,c) (MIN (MAX ((a), (b)), (c))) #endif +#define PLY_UTF8_CHARACTER_SIZE_MAX 4 + typedef intptr_t ply_module_handle_t; typedef void (* ply_module_function_t) (void); @@ -97,6 +99,11 @@ ply_daemon_handle_t *ply_create_daemon (void); bool ply_detach_daemon (ply_daemon_handle_t *handle, int exit_code); +int ply_utf8_character_get_size (char *string, + size_t n); +int ply_utf8_string_get_length (char *string, + size_t n); + #endif #endif /* PLY_UTILS_H */ diff --git a/src/libplybootsplash/ply-window.c b/src/libplybootsplash/ply-window.c index 8a126815..9fca3eb9 100644 --- a/src/libplybootsplash/ply-window.c +++ b/src/libplybootsplash/ply-window.c @@ -236,10 +236,14 @@ process_backspace (ply_window_t *window) bytes = ply_buffer_get_bytes (window->line_buffer); size = ply_buffer_get_size (window->line_buffer); - bytes_to_remove = MIN(size, MB_CUR_MAX); - while ((previous_character_size = mbrlen (bytes + size - bytes_to_remove, bytes_to_remove, NULL)) < bytes_to_remove && - previous_character_size > 0) - bytes_to_remove -= previous_character_size; + bytes_to_remove = MIN(size, PLY_UTF8_CHARACTER_SIZE_MAX); + while ((previous_character_size = ply_utf8_character_get_size (bytes + size - bytes_to_remove, bytes_to_remove)) < bytes_to_remove) + { + if (previous_character_size > 0) + bytes_to_remove -= previous_character_size; + else + bytes_to_remove--; + } if (bytes_to_remove <= size) { @@ -379,7 +383,7 @@ check_buffer_for_key_events (ply_window_t *window) ssize_t character_size; char *keyboard_input; - character_size = (ssize_t) mbrlen (bytes + i, size - i, NULL); + character_size = (ssize_t) ply_utf8_character_get_size (bytes + i, size - i); if (character_size < 0) break; diff --git a/src/main.c b/src/main.c index ee3ffd6e..a6295bf6 100644 --- a/src/main.c +++ b/src/main.c @@ -774,7 +774,8 @@ update_display (state_t *state) ply_entry_trigger_t* entry_trigger = ply_list_node_get_data (node); if (entry_trigger->type == PLY_ENTRY_TRIGGER_TYPE_PASSWORD) { - int bullets = mbstowcs (NULL, ply_buffer_get_bytes (state->entry_buffer), 0); + int bullets = ply_utf8_string_get_length (ply_buffer_get_bytes (state->entry_buffer), + ply_buffer_get_size (state->entry_buffer)); bullets = MAX(0, bullets); ply_boot_splash_display_password (state->boot_splash, entry_trigger->prompt, @@ -874,10 +875,14 @@ on_backspace (state_t *state) bytes = ply_buffer_get_bytes (state->entry_buffer); size = ply_buffer_get_size (state->entry_buffer); - bytes_to_remove = MIN(size, MB_CUR_MAX); - while ((previous_character_size = mbrlen (&bytes[size - bytes_to_remove], bytes_to_remove, NULL)) < bytes_to_remove && - previous_character_size > 0) - bytes_to_remove -= previous_character_size; + bytes_to_remove = MIN(size, PLY_UTF8_CHARACTER_SIZE_MAX); + while ((previous_character_size = ply_utf8_character_get_size (bytes + size - bytes_to_remove, bytes_to_remove)) < bytes_to_remove) + { + if (previous_character_size > 0) + bytes_to_remove -= previous_character_size; + else + bytes_to_remove--; + } ply_buffer_remove_bytes_at_end (state->entry_buffer, bytes_to_remove); update_display (state);