]> git.ipfire.org Git - thirdparty/plymouth.git/commitdiff
[utils] Add utf-8 support functions to determine character and string length
authorCharlie Brej <cbrej@cs.man.ac.uk>
Wed, 15 Jul 2009 10:30:19 +0000 (11:30 +0100)
committerCharlie Brej <cbrej@cs.man.ac.uk>
Wed, 15 Jul 2009 10:30:19 +0000 (11:30 +0100)
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.

src/libply/ply-utils.c
src/libply/ply-utils.h
src/libplybootsplash/ply-window.c
src/main.c

index 25f9e064b15874f428c2c4306f25dd3fec45f884..3db716349c38551fec3afee672c3cbc64ab278da 100644 (file)
@@ -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: */
index 53280688bb52b2057a63f46e975303e5bae506a9..e0d6e8567228b5c425fd2fa709bd754306affc91 100644 (file)
@@ -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 */
index 8a1268150488e31df046f89a770887723687d746..9fca3eb98e59a6eb182040ab0e268d52a01c2f5a 100644 (file)
@@ -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;
index ee3ffd6e521b4af895ac7cda577880d54f1bc9c1..a6295bf61da9576fd02ef68a246f734b28af1ff7 100644 (file)
@@ -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);