[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.
calculate-0.9.5
Charlie Brej 15 years ago
parent f6da5d5aeb
commit fc2d96de67

@ -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: */

@ -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 */

@ -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;

@ -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);

Loading…
Cancel
Save