handler, failed_handler, user_data);
 }
 
+void
+ply_boot_client_ask_daemon_question     (ply_boot_client_t                    *client,
+                                         const char                            *prompt,
+                                         ply_boot_client_answer_handler_t       handler,
+                                         ply_boot_client_response_handler_t     failed_handler,
+                                         void                                  *user_data)
+{
+  assert (client != NULL);
+
+  ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_QUESTION,
+                                 prompt, (ply_boot_client_response_handler_t)
+                                 handler, failed_handler, user_data);
+}
+
+void
+ply_boot_client_ask_daemon_to_watch_for_keystroke (ply_boot_client_t           *client,
+                                         const char                            *keys,
+                                         ply_boot_client_answer_handler_t       handler,
+                                         ply_boot_client_response_handler_t     failed_handler,
+                                         void                                  *user_data)
+{
+  assert (client != NULL);
+
+  ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_KEYSTROKE,
+                                 keys, (ply_boot_client_response_handler_t)
+                                 handler, failed_handler, user_data);
+}
+
+void
+ply_boot_client_ask_daemon_to_ignore_keystroke (ply_boot_client_t                  *client,
+                                         const char                                *keys,
+                                         ply_boot_client_answer_handler_t           handler,
+                                         ply_boot_client_response_handler_t         failed_handler,
+                                         void                                      *user_data)
+{
+  assert (client != NULL);
+
+  ply_boot_client_queue_request (client, PLY_BOOT_PROTOCOL_REQUEST_TYPE_KEYSTROKE_REMOVE,
+                                 keys, (ply_boot_client_response_handler_t)
+                                 handler, failed_handler, user_data);
+}
+
 void
 ply_boot_client_tell_daemon_to_show_splash (ply_boot_client_t                  *client,
                                             ply_boot_client_response_handler_t  handler,
 
                                                  ply_boot_client_response_handler_t  failed_handler,
                                                  void                               *user_data);
 void ply_boot_client_ask_daemon_for_password (ply_boot_client_t                  *client,
-                                              const char *prompt,
+                                              const char                         *prompt,
                                               ply_boot_client_answer_handler_t    handler,
                                               ply_boot_client_response_handler_t  failed_handler,
                                               void                               *user_data);
-
 void ply_boot_client_ask_daemon_for_cached_passwords (ply_boot_client_t                  *client,
                                                       ply_boot_client_multiple_answers_handler_t    handler,
                                                       ply_boot_client_response_handler_t  failed_handler,
                                                       void                               *user_data);
+void ply_boot_client_ask_daemon_question     (ply_boot_client_t                    *client,
+                                              const char                           *prompt,
+                                              ply_boot_client_answer_handler_t      handler,
+                                              ply_boot_client_response_handler_t    failed_handler,
+                                              void                                 *user_data);
+void ply_boot_client_ask_daemon_to_watch_for_keystroke (ply_boot_client_t          *client,
+                                         const char                                *keys,
+                                         ply_boot_client_answer_handler_t           handler,
+                                         ply_boot_client_response_handler_t         failed_handler,
+                                         void                                      *user_data);
+void ply_boot_client_ask_daemon_to_ignore_keystroke (ply_boot_client_t             *client,
+                                         const char                                *keys,
+                                         ply_boot_client_answer_handler_t           handler,
+                                         ply_boot_client_response_handler_t         failed_handler,
+                                         void                                      *user_data);
 void ply_boot_client_tell_daemon_system_is_initialized (ply_boot_client_t                  *client,
                                                         ply_boot_client_response_handler_t  handler,
                                                         ply_boot_client_response_handler_t  failed_handler,
 
   char    *command;
   char    *prompt;
   int      number_of_tries_left;
-} answer_state_t;
+} password_answer_state_t;
+
+typedef struct
+{
+  state_t *state;
+  char    *command;
+  char    *prompt;
+} question_answer_state_t;
+
+typedef struct
+{
+  state_t *state;
+  char    *command;
+  char    *keys;
+} key_answer_state_t;
 
 static char **
 split_string (const char *command,
 }
 
 static bool
-answer_via_command (answer_state_t *answer_state,
+answer_via_command (char           *command,
                     const char     *answer,
                     int            *exit_status)
 {
   if (pid == 0)
     {
       char **args;
-      args = split_string (answer_state->command, ' ');
+      args = split_string (command, ' ');
       if (answer != NULL)
         {
           close (command_input_sender_fd);
 }
 
 static void
-on_answer_failure (answer_state_t *answer_state)
+on_password_answer_failure (password_answer_state_t *answer_state, ply_boot_client_t *client)
 {
   ply_event_loop_exit (answer_state->state->loop, 1);
 }
 
 static void
-on_answer (answer_state_t   *answer_state,
-           const char       *answer)
+on_password_answer (password_answer_state_t   *answer_state,
+                    const char                *answer)
 {
   int exit_status;
 
       bool command_started = false;
 
       exit_status = 127;
-      command_started = answer_via_command (answer_state, answer,
+      command_started = answer_via_command (answer_state->command, answer,
                                             &exit_status);
 
       if (command_started && (!WIFEXITED (exit_status) ||
               ply_boot_client_ask_daemon_for_password (answer_state->state->client,
                                                        answer_state->prompt,
                                                        (ply_boot_client_answer_handler_t)
-                                                       on_answer,
+                                                       on_password_answer,
                                                        (ply_boot_client_response_handler_t)
-                                                       on_answer_failure, answer_state);
+                                                       on_password_answer_failure, answer_state);
               return;
             }
         }
 }
 
 static void
-on_multiple_answers (answer_state_t     *answer_state,
-                     const char * const *answers)
+on_question_answer (question_answer_state_t   *answer_state,
+                   const char                 *answer,
+                   ply_boot_client_t          *client)
+{
+  if (answer_state->command != NULL)
+    {
+      answer_via_command (answer_state->command, answer, NULL);
+    }
+  else
+    {
+      if (answer)
+        write (STDOUT_FILENO, answer, strlen (answer));
+    }
+
+  if (answer)
+    ply_event_loop_exit (answer_state->state->loop, 0);
+  ply_event_loop_exit (answer_state->state->loop, 1);
+}
+
+static void
+on_key_answer (key_answer_state_t   *answer_state,
+           const char       *answer,
+           ply_boot_client_t *client)
+{
+  if (answer_state->command != NULL)
+    {
+      answer_via_command (answer_state->command, answer, NULL);
+    }
+  else
+    {
+      if (answer)
+        write (STDOUT_FILENO, answer, strlen (answer));
+    }
+
+  if (answer) ply_event_loop_exit (answer_state->state->loop, 0);
+  ply_event_loop_exit (answer_state->state->loop, 1);
+}
+
+static void
+on_multiple_answers (password_answer_state_t     *answer_state,
+                     const char * const          *answers)
 {
   bool need_to_ask_user;
   int i;
       {
         bool command_started;
         exit_status = 127;
-        command_started = answer_via_command (answer_state, answers[i],
+        command_started = answer_via_command (answer_state->command, answers[i],
                                               &exit_status);
         if (command_started && WIFEXITED (exit_status) &&
             WEXITSTATUS (exit_status) == 0)
       ply_boot_client_ask_daemon_for_password (answer_state->state->client,
                                                answer_state->prompt,
                                                (ply_boot_client_answer_handler_t)
-                                               on_answer,
+                                               on_password_answer,
                                                (ply_boot_client_response_handler_t)
-                                               on_answer_failure, answer_state);
+                                               on_password_answer_failure, answer_state);
       return;
     }
 
   char *prompt;
   char *program;
   int number_of_tries;
-  answer_state_t *answer_state;
+  password_answer_state_t *password_answer_state;
 
   prompt = NULL;
   program = NULL;
   if (number_of_tries <= 0)
     number_of_tries = 3;
 
-  answer_state = calloc (1, sizeof (answer_state_t));
-  answer_state->state = state;
-  answer_state->command = program;
-  answer_state->prompt = prompt;
-  answer_state->number_of_tries_left = number_of_tries;
+  password_answer_state = calloc (1, sizeof (password_answer_state_t));
+  password_answer_state->state = state;
+  password_answer_state->command = program;
+  password_answer_state->prompt = prompt;
+  password_answer_state->number_of_tries_left = number_of_tries;
 
-  if (answer_state->command != NULL)
+  if (password_answer_state->command != NULL)
     {
       ply_boot_client_ask_daemon_for_cached_passwords (state->client,
                                                        (ply_boot_client_multiple_answers_handler_t)
                                                        on_multiple_answers,
                                                        (ply_boot_client_response_handler_t)
-                                                       on_answer_failure, answer_state);
-
+                                                       on_password_answer_failure, password_answer_state);
     }
   else
     {
       ply_boot_client_ask_daemon_for_password (state->client,
-                                               answer_state->prompt,
+                                               password_answer_state->prompt,
                                                (ply_boot_client_answer_handler_t)
-                                               on_answer,
+                                               on_password_answer,
                                                (ply_boot_client_response_handler_t)
-                                               on_answer_failure, answer_state);
+                                               on_password_answer_failure, password_answer_state);
     }
 }
 
+static void
+on_question_request (state_t    *state,
+                     const char *command)
+{
+  char *prompt;
+  char *program;
+  int number_of_tries;
+  question_answer_state_t *question_answer_state;
+
+  prompt = NULL;
+  program = NULL;
+  number_of_tries = 0;
+  ply_command_parser_get_command_options (state->command_parser,
+                                          command,
+                                          "command", &program,
+                                          "prompt", &prompt,
+                                          NULL);
+
+  question_answer_state = calloc (1, sizeof (question_answer_state_t));
+  question_answer_state->state = state;
+  question_answer_state->command = program;
+  question_answer_state->prompt = prompt;
+
+  ply_boot_client_ask_daemon_question (state->client,
+                                       question_answer_state->prompt,
+                                       (ply_boot_client_answer_handler_t)
+                                       on_question_answer,
+                                       (ply_boot_client_response_handler_t)
+                                       on_failure, question_answer_state);
+}
+
+static void
+on_keystroke_request (state_t    *state,
+                     const char *command)
+{
+  char *keys;
+  char *program;
+  bool remove;
+
+  keys = NULL;
+  program = NULL;
+  remove = false;
+  
+  ply_command_parser_get_command_options (state->command_parser,
+                                          command,
+                                          "command", &program,
+                                          "keys", &keys,
+                                          NULL);
+  key_answer_state_t *key_answer_state;
+  key_answer_state = calloc (1, sizeof (key_answer_state_t));
+  key_answer_state->state = state;
+  key_answer_state->keys = keys;
+  key_answer_state->command = program;
+  ply_boot_client_ask_daemon_to_watch_for_keystroke (state->client,
+                                       keys,
+                                       (ply_boot_client_answer_handler_t)
+                                       on_key_answer,
+                                       (ply_boot_client_response_handler_t)
+                                       on_failure, key_answer_state);
+}
+
 static void
 on_report_error_request (state_t    *state,
                          const char *command)
 {
   state_t state = { 0 };
   bool should_help, should_quit, should_ping, should_sysinit, should_ask_for_password, should_show_splash, should_hide_splash, should_wait, should_be_verbose, report_error;
-  char *status, *chroot_dir;
+  char *status, *chroot_dir, *ignore_keystroke;
   int exit_code;
 
   exit_code = 0;
                                   "show-splash", "Show splash screen", PLY_COMMAND_OPTION_TYPE_FLAG,
                                   "hide-splash", "Hide splash screen", PLY_COMMAND_OPTION_TYPE_FLAG,
                                   "ask-for-password", "Ask user for password", PLY_COMMAND_OPTION_TYPE_FLAG,
+                                  "ignore-keystroke", "Remove sensitivity to a keystroke", PLY_COMMAND_OPTION_TYPE_STRING,
                                   "update", "Tell boot daemon an update about boot progress", PLY_COMMAND_OPTION_TYPE_STRING,
                                   "details", "Tell boot daemon there were errors during boot", PLY_COMMAND_OPTION_TYPE_FLAG,
                                   "wait", "Wait for boot daemon to quit", PLY_COMMAND_OPTION_TYPE_FLAG,
                                   PLY_COMMAND_OPTION_TYPE_INTEGER,
                                   NULL);
 
+  ply_command_parser_add_command (state.command_parser,
+                                  "ask-question", "Ask user a question",
+                                  (ply_command_handler_t)
+                                  on_question_request, &state,
+                                  "command", "Command to send the answer to via standard input",
+                                  PLY_COMMAND_OPTION_TYPE_STRING,
+                                  "prompt", "Message to display when asking the question",
+                                  PLY_COMMAND_OPTION_TYPE_STRING,
+                                  NULL);
+
+
+  ply_command_parser_add_command (state.command_parser,
+                                  "watch-keystroke", "Become sensitive to a keystroke",
+                                  (ply_command_handler_t)
+                                  on_keystroke_request, &state,
+                                  "command", "Command to send keystroke to via standard input",
+                                  PLY_COMMAND_OPTION_TYPE_STRING,
+                                  "keys", "Keys to become sensitive to",
+                                  PLY_COMMAND_OPTION_TYPE_STRING,
+                                  NULL);
+
   ply_command_parser_add_command (state.command_parser,
                                   "report-error", "Tell boot daemon there were errors during boot",
                                   (ply_command_handler_t)
                                   "show-splash", &should_show_splash,
                                   "hide-splash", &should_hide_splash,
                                   "ask-for-password", &should_ask_for_password,
+                                  "ignore-keystroke", &ignore_keystroke,
                                   "update", &status,
                                   "wait", &should_wait,
                                   "details", &report_error,
                                    on_failure, &state);
   else if (should_ask_for_password)
     {
-      answer_state_t answer_state = { 0 };
+      password_answer_state_t answer_state = { 0 };
 
       answer_state.state = &state;
       answer_state.number_of_tries_left = 1;
       ply_boot_client_ask_daemon_for_password (state.client,
                                                NULL,
                                                (ply_boot_client_answer_handler_t)
-                                                on_answer,
+                                               on_password_answer,
                                                (ply_boot_client_response_handler_t)
-                                               on_answer_failure, &answer_state);
+                                               on_password_answer_failure, &answer_state);
+    }
+  else if (ignore_keystroke)
+    {
+      ply_boot_client_ask_daemon_to_ignore_keystroke (state.client,
+                                           ignore_keystroke,
+                                           (ply_boot_client_answer_handler_t)
+                                           on_success,
+                                           (ply_boot_client_response_handler_t)
+                                           on_failure, &state);
     }
   else if (should_sysinit)
     ply_boot_client_tell_daemon_system_is_initialized (state.client,
 
 
 typedef struct _ply_boot_splash_plugin ply_boot_splash_plugin_t;
 
-typedef void (* ply_boot_splash_password_answer_handler_t) (void *answer_data, const char *password);
-
 typedef struct
 {
   ply_boot_splash_plugin_t * (* create_plugin) (void);
   void (* on_root_mounted) (ply_boot_splash_plugin_t *plugin);
   void (* hide_splash_screen) (ply_boot_splash_plugin_t *plugin,
                                ply_event_loop_t         *loop);
-
-  void (* ask_for_password) (ply_boot_splash_plugin_t *plugin,
+  void (* display_normal) (ply_boot_splash_plugin_t *plugin);
+  void (* display_password) (ply_boot_splash_plugin_t *plugin,
+                             const char               *prompt,
+                             int                       bullets);
+  void (* display_question) (ply_boot_splash_plugin_t *plugin,
                              const char               *prompt,
-                             ply_trigger_t            *answer);
+                             const char               *entry_text);
   void (* become_idle) (ply_boot_splash_plugin_t       *plugin,
                         ply_trigger_t                  *idle_trigger);
 } ply_boot_splash_plugin_interface_t;
 
 #include "ply-entry.h"
 #include "ply-event-loop.h"
 #include "ply-array.h"
+#include "ply-label.h"
 #include "ply-logger.h"
 #include "ply-frame-buffer.h"
 #include "ply-image.h"
   ply_frame_buffer_area_t  area;
   ply_image_t             *text_field_image;
   ply_image_t             *bullet_image;
+  ply_label_t             *label;
 
+  char* text;
   int number_of_bullets;
   int max_number_of_visible_bullets;
 
   uint32_t is_hidden : 1;
+  uint32_t is_password : 1;
 };
 
 ply_entry_t *
   asprintf (&image_path, "%s/bullet.png", image_dir);
   entry->bullet_image = ply_image_new (image_path);
   free (image_path);
+  entry->label = ply_label_new ();
 
+  entry->number_of_bullets = 0;
+  entry->text = strdup("");
+  
   entry->is_hidden = true;
+  entry->is_password = true;
 
   return entry;
 }
     return;
   ply_image_free (entry->text_field_image);
   ply_image_free (entry->bullet_image);
+  ply_label_free (entry->label);
+
   free (entry);
 }
 
   ply_frame_buffer_fill_with_argb32_data (entry->frame_buffer,
                                           &entry->area, 0, 0,
                                           text_field_data);
-
-  bullet_data = ply_image_get_data (entry->bullet_image);
-  bullet_area.width = ply_image_get_width (entry->bullet_image);
-  bullet_area.height = ply_image_get_height (entry->bullet_image);
-
-  if (entry->number_of_bullets < entry->max_number_of_visible_bullets)
-    number_of_visible_bullets = entry->number_of_bullets;
+  
+  if (entry->is_password)
+    {
+      bullet_data = ply_image_get_data (entry->bullet_image);
+      bullet_area.width = ply_image_get_width (entry->bullet_image);
+      bullet_area.height = ply_image_get_height (entry->bullet_image);
+
+      if (entry->number_of_bullets < entry->max_number_of_visible_bullets)
+        number_of_visible_bullets = entry->number_of_bullets;
+      else
+        {
+          number_of_visible_bullets = entry->max_number_of_visible_bullets;
+
+          /* We've got more bullets than we can show in the available space, so
+           * draw a little half bullet to indicate some bullets are offscreen
+           */
+          bullet_area.x = entry->area.x;
+          bullet_area.y = entry->area.y + entry->area.height / 2.0 - bullet_area.height / 2.0;
+
+          ply_frame_buffer_fill_with_argb32_data (entry->frame_buffer,
+                                                  &bullet_area, bullet_area.width / 2.0, 0,
+                                                  bullet_data);
+        }
+
+      for (i = 0; i < number_of_visible_bullets; i++)
+        {
+          bullet_area.x = entry->area.x + i * bullet_area.width + bullet_area.width / 2.0;
+          bullet_area.y = entry->area.y + entry->area.height / 2.0 - bullet_area.height / 2.0;
+
+          ply_frame_buffer_fill_with_argb32_data (entry->frame_buffer,
+                                                  &bullet_area, 0, 0,
+                                                  bullet_data);
+        }
+    }
   else
     {
-      number_of_visible_bullets = entry->max_number_of_visible_bullets;
-
-      /* We've got more bullets than we can show in the available space, so
-       * draw a little half bullet to indicate some bullets are offscreen
-       */
-      bullet_area.x = entry->area.x;
-      bullet_area.y = entry->area.y + entry->area.height / 2.0 - bullet_area.height / 2.0;
-
-      ply_frame_buffer_fill_with_argb32_data (entry->frame_buffer,
-                                              &bullet_area, bullet_area.width / 2.0, 0,
-                                              bullet_data);
+      ply_label_set_text (entry->label, entry->text);
+      ply_label_show (entry->label, entry->window, entry->area.x, entry->area.y);
+      
     }
+  ply_frame_buffer_unpause_updates (entry->frame_buffer);
+}
 
-  for (i = 0; i < number_of_visible_bullets; i++)
+void
+ply_entry_set_bullet_count (ply_entry_t *entry, int count)
+{
+  count = MAX(0, count);
+  if (!entry->is_password || entry->number_of_bullets != count)
     {
-      bullet_area.x = entry->area.x + i * bullet_area.width + bullet_area.width / 2.0;
-      bullet_area.y = entry->area.y + entry->area.height / 2.0 - bullet_area.height / 2.0;
-
-      ply_frame_buffer_fill_with_argb32_data (entry->frame_buffer,
-                                              &bullet_area, 0, 0,
-                                              bullet_data);
+      entry->is_password = true;
+      entry->number_of_bullets = count;
+      ply_entry_draw (entry);
     }
-  ply_frame_buffer_unpause_updates (entry->frame_buffer);
+}
+
+int
+ply_entry_get_bullet_count (ply_entry_t *entry)
+{
+  return entry->number_of_bullets;
 }
 
 void
 ply_entry_add_bullet (ply_entry_t *entry)
 {
-  entry->number_of_bullets++;
-  ply_entry_draw (entry);
+  ply_entry_set_bullet_count (entry, ply_entry_get_bullet_count (entry)+1);
 }
 
 void
 ply_entry_remove_bullet (ply_entry_t *entry)
 {
-  entry->number_of_bullets--;
-  ply_entry_draw (entry);
+  ply_entry_set_bullet_count (entry, ply_entry_get_bullet_count (entry)-1);
 }
 
 void
 ply_entry_remove_all_bullets (ply_entry_t *entry)
 {
-  entry->number_of_bullets = 0;
-  ply_entry_draw (entry);
+  ply_entry_set_bullet_count (entry, 0);
+}
+
+void
+ply_entry_set_text (ply_entry_t *entry, const char* text)
+{
+  if (entry->is_password || strcmp(entry->text, text) != 0)
+    {
+      entry->is_password = false;
+      free(entry->text);
+      entry->text = strdup(text);
+      ply_entry_draw (entry);
+    }
 }
 
 void
 
 long ply_entry_get_width (ply_entry_t *entry);
 long ply_entry_get_height (ply_entry_t *entry);
 
+void ply_entry_set_bullet_count (ply_entry_t *entry, int count);
+int ply_entry_get_bullet_count (ply_entry_t *entry);
 void ply_entry_add_bullet (ply_entry_t *entry);
 void ply_entry_remove_bullet (ply_entry_t *entry);
 void ply_entry_remove_all_bullets (ply_entry_t *entry);
+void ply_entry_set_text (ply_entry_t *entry, const char* text);
+
 #endif
 
 #endif /* PLY_ENTRY_H */
 
 #include "ply-buffer.h"
 #include "ply-event-loop.h"
 #include "ply-frame-buffer.h"
+#include "ply-list.h"
 #include "ply-logger.h"
 #include "ply-utils.h"
 
 #define TEXT_PALETTE_SIZE 48
 #endif
 
+typedef void (* ply_window_handler_t) (void *);
+
+typedef struct
+{
+  ply_window_handler_t *function;
+  void *user_data;
+} ply_window_closure_t;
+
 struct _ply_window
 {
   ply_event_loop_t *loop;
   uint32_t supports_text_color : 1;
   uint32_t is_open : 1;
 
-  ply_window_keyboard_input_handler_t keyboard_input_handler;
-  void *keyboard_input_handler_user_data;
-
-  ply_window_backspace_handler_t backspace_handler;
-  void *backspace_handler_user_data;
-
-  ply_window_escape_handler_t escape_handler;
-  void *escape_handler_user_data;
-
-  ply_window_enter_handler_t enter_handler;
-  void *enter_handler_user_data;
+  ply_list_t *keyboard_input_handler_list;
+  ply_list_t *backspace_handler_list;
+  ply_list_t *escape_handler_list;
+  ply_list_t *enter_handler_list;
 
   ply_window_draw_handler_t draw_handler;
   void *draw_handler_user_data;
   window->keyboard_input_buffer = ply_buffer_new ();
   window->line_buffer = ply_buffer_new ();
   window->frame_buffer = ply_frame_buffer_new (NULL);
+  window->keyboard_input_handler_list = ply_list_new();
+  window->backspace_handler_list = ply_list_new();
+  window->escape_handler_list = ply_list_new();
+  window->enter_handler_list = ply_list_new();
+  
   window->loop = NULL;
   if (tty_name != NULL)
     {
   ssize_t previous_character_size;
   const char *bytes;
   size_t size;
+  ply_list_node_t *node;
 
   bytes = ply_buffer_get_bytes (window->line_buffer);
   size = ply_buffer_get_size (window->line_buffer);
 
-  bytes_to_remove = MB_CUR_MAX;
+  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;
   if (bytes_to_remove <= size)
     {
       ply_buffer_remove_bytes_at_end (window->line_buffer, bytes_to_remove);
+    }
 
-      if (window->backspace_handler != NULL)
-        window->backspace_handler (window->backspace_handler_user_data);
+  for (node = ply_list_get_first_node(window->backspace_handler_list);
+       node; node = ply_list_get_next_node(window->backspace_handler_list, node))
+    {
+      ply_window_closure_t *closure = ply_list_node_get_data (node);
+      ply_window_backspace_handler_t backspace_handler = 
+                            (ply_window_backspace_handler_t) closure->function;
+      backspace_handler (closure->user_data);
     }
 }
 
                         size_t        character_size)
 {
   wchar_t key;
+  ply_list_node_t *node;
 
-  if (mbrtowc (&key, keyboard_input, 1, NULL) > 0)
+  if ((ssize_t) mbrtowc (&key, keyboard_input, character_size, NULL) > 0)
     {
       switch (key)
         {
 
           case KEY_ESCAPE:
             ply_trace ("escape key!");
-            if (window->escape_handler != NULL)
-              window->escape_handler (window->escape_handler_user_data);
+            for (node = ply_list_get_first_node(window->escape_handler_list);
+                 node; node = ply_list_get_next_node(window->escape_handler_list, node))
+              {
+                ply_window_closure_t *closure = ply_list_node_get_data (node);
+                ply_window_escape_handler_t escape_handler = (ply_window_escape_handler_t) closure->function;
+                escape_handler (closure->user_data);
+              }
+            
             ply_trace ("end escape key handler");
           return;
 
           case KEY_RETURN:
             ply_trace ("return key!");
 
-            if (window->enter_handler != NULL)
-              window->enter_handler (window->enter_handler_user_data,
-                                     ply_buffer_get_bytes (window->line_buffer));
-
+            for (node = ply_list_get_first_node(window->enter_handler_list);
+                 node; node = ply_list_get_next_node(window->enter_handler_list, node))
+              {
+                ply_window_closure_t *closure = ply_list_node_get_data (node);
+                ply_window_enter_handler_t enter_handler = (ply_window_enter_handler_t)  closure->function;
+                enter_handler (closure->user_data, ply_buffer_get_bytes (window->line_buffer));
+              }
             ply_buffer_clear (window->line_buffer);
           return;
 
           break;
         }
     }
-
-  if (window->keyboard_input_handler != NULL)
-    window->keyboard_input_handler (window->keyboard_input_handler_user_data,
-                                    keyboard_input, character_size);
+  for (node = ply_list_get_first_node(window->keyboard_input_handler_list);
+       node; node = ply_list_get_next_node(window->keyboard_input_handler_list, node))
+    {
+      ply_window_closure_t *closure = ply_list_node_get_data (node);
+      ply_window_keyboard_input_handler_t keyboard_input_handler =
+                        (ply_window_keyboard_input_handler_t) closure->function;
+      
+      keyboard_input_handler (closure->user_data,
+                              keyboard_input, character_size);
+    }
 }
 
 static void
                                      int           row)
 {
   char *sequence;
-
+  column = MAX(column, 0);
+  row = MAX(row, 0);
   sequence = NULL;
   asprintf (&sequence, MOVE_CURSOR_SEQUENCE, row, column);
   write (window->tty_fd, sequence, strlen (sequence));
   free (window);
 }
 
+static ply_window_closure_t *
+ply_window_closure_new(void* function, void* user_data)
+{
+  ply_window_closure_t *closure = calloc (1, sizeof (ply_window_closure_t));
+  closure->function = function;
+  closure->user_data = user_data;
+  return closure;
+}
+
+
+static void
+ply_window_closure_free(ply_window_closure_t* closure)
+{
+  free(closure);
+}
+
 void
-ply_window_set_keyboard_input_handler (ply_window_t *window,
+ply_window_add_keyboard_input_handler (ply_window_t *window,
                                        ply_window_keyboard_input_handler_t input_handler,
                                        void       *user_data)
 {
   assert (window != NULL);
+  ply_window_closure_t *closure = ply_window_closure_new(input_handler, user_data);
+  ply_list_append_data (window->keyboard_input_handler_list, closure);
+}
 
-  window->keyboard_input_handler = input_handler;
-  window->keyboard_input_handler_user_data = user_data;
+
+void
+ply_window_remove_keyboard_input_handler (ply_window_t *window,
+                                       ply_window_keyboard_input_handler_t input_handler)
+{
+  ply_list_node_t *node;
+  assert (window != NULL);
+  for (node = ply_list_get_first_node(window->keyboard_input_handler_list);
+       node; node = ply_list_get_next_node(window->keyboard_input_handler_list, node))
+    {
+      ply_window_closure_t *closure = ply_list_node_get_data (node);
+      if ((ply_window_keyboard_input_handler_t) closure->function == input_handler)
+        {
+          ply_window_closure_free(closure);
+          ply_list_remove_node (window->keyboard_input_handler_list, node);
+          return;
+        }
+    }
 }
 
 void
-ply_window_set_backspace_handler (ply_window_t *window,
+ply_window_add_backspace_handler (ply_window_t *window,
                                   ply_window_backspace_handler_t backspace_handler,
                                   void         *user_data)
 {
   assert (window != NULL);
+  ply_window_closure_t *closure = ply_window_closure_new(backspace_handler, user_data);
+  ply_list_append_data (window->backspace_handler_list, closure);
+}
+
 
-  window->backspace_handler = backspace_handler;
-  window->backspace_handler_user_data = user_data;
+void
+ply_window_remove_backspace_handler (ply_window_t *window,
+                                  ply_window_backspace_handler_t backspace_handler)
+{
+  ply_list_node_t *node;
+  assert (window != NULL);
+  for (node = ply_list_get_first_node(window->backspace_handler_list);
+       node; node = ply_list_get_next_node(window->backspace_handler_list, node))
+    {
+      ply_window_closure_t *closure = ply_list_node_get_data (node);
+      if ((ply_window_backspace_handler_t) closure->function == backspace_handler)
+        {
+          ply_window_closure_free(closure);
+          ply_list_remove_node (window->backspace_handler_list, node);
+          return;
+        }
+    }
 }
 
 void
-ply_window_set_escape_handler (ply_window_t *window,
+ply_window_add_escape_handler (ply_window_t *window,
                                ply_window_escape_handler_t escape_handler,
                                void       *user_data)
 {
   assert (window != NULL);
+  ply_window_closure_t *closure = ply_window_closure_new(escape_handler, user_data);
+  ply_list_append_data (window->escape_handler_list, closure);
+}
+
 
-  window->escape_handler = escape_handler;
-  window->escape_handler_user_data = user_data;
+void
+ply_window_remove_escape_handler (ply_window_t *window,
+                               ply_window_escape_handler_t escape_handler)
+{
+  assert (window != NULL);
+  ply_list_node_t *node;
+  assert (window != NULL);
+  for (node = ply_list_get_first_node(window->escape_handler_list);
+       node; node = ply_list_get_next_node(window->escape_handler_list, node))
+    {
+      ply_window_closure_t *closure = ply_list_node_get_data (node);
+      if ((ply_window_escape_handler_t) closure->function == escape_handler)
+        {
+          ply_window_closure_free(closure);
+          ply_list_remove_node (window->escape_handler_list, node);
+          return;
+        }
+    }
 }
 
 void
-ply_window_set_enter_handler (ply_window_t *window,
+ply_window_add_enter_handler (ply_window_t *window,
                               ply_window_enter_handler_t enter_handler,
                               void         *user_data)
 {
   assert (window != NULL);
+  ply_window_closure_t *closure = ply_window_closure_new(enter_handler, user_data);
+  ply_list_append_data (window->enter_handler_list, closure);
+}
 
-  window->enter_handler = enter_handler;
-  window->enter_handler_user_data = user_data;
+
+void
+ply_window_remove_enter_handler (ply_window_t *window,
+                              ply_window_enter_handler_t enter_handler)
+{
+  assert (window != NULL);
+  ply_list_node_t *node;
+  assert (window != NULL);
+  for (node = ply_list_get_first_node(window->enter_handler_list);
+       node; node = ply_list_get_next_node(window->enter_handler_list, node))
+    {
+      ply_window_closure_t *closure = ply_list_node_get_data (node);
+      if ((ply_window_enter_handler_t) closure->function == enter_handler)
+        {
+          ply_window_closure_free(closure);
+          ply_list_remove_node (window->enter_handler_list, node);
+          return;
+        }
+    }
 }
 
 void
 
   window = ply_window_new (tty_name);
   ply_window_attach_to_event_loop (window, loop);
-  ply_window_set_keyboard_input_handler (window,
+  ply_window_add_keyboard_input_handler (window,
                                          (ply_window_keyboard_input_handler_t)
                                          on_keypress, window);
 
 
                                                       size_t      character_size);
 
 typedef void (* ply_window_backspace_handler_t) (void *user_data);
-
 typedef void (* ply_window_escape_handler_t) (void *user_data);
 typedef void (* ply_window_enter_handler_t) (void *user_data,
                                              const char *line);
 ply_window_t *ply_window_new (const char *name);
 void ply_window_free (ply_window_t *window);
 
-void ply_window_set_keyboard_input_handler (ply_window_t *window,
-                                            ply_window_keyboard_input_handler_t input_handler,
-                                            void         *user_data);
-void ply_window_set_backspace_handler (ply_window_t *window,
-                                       ply_window_backspace_handler_t backspace_handler,
-                                       void         *user_data);
-void ply_window_set_escape_handler (ply_window_t *window,
-                                    ply_window_escape_handler_t escape_handler,
-                                    void         *user_data);
-void ply_window_set_enter_handler (ply_window_t *window,
-                                   ply_window_enter_handler_t enter_handler,
-                                   void         *user_data);
-void ply_window_set_draw_handler (ply_window_t *window,
-                                  ply_window_draw_handler_t draw_handler,
-                                  void         *user_data);
-void ply_window_set_erase_handler (ply_window_t *window,
-                                   ply_window_erase_handler_t erase_handler,
-                                   void         *user_data);
+void ply_window_add_keyboard_input_handler (ply_window_t                        *window,
+                                            ply_window_keyboard_input_handler_t  input_handler,
+                                            void                                *user_data);
+void ply_window_remove_keyboard_input_handler (ply_window_t                        *window,
+                                               ply_window_keyboard_input_handler_t  input_handler);
+void ply_window_add_backspace_handler (ply_window_t                   *window,
+                                       ply_window_backspace_handler_t  backspace_handler,
+                                       void                           *user_data);
+void ply_window_remove_backspace_handler (ply_window_t                   *window,
+                                          ply_window_backspace_handler_t  backspace_handler);
+void ply_window_add_escape_handler (ply_window_t                *window,
+                                    ply_window_escape_handler_t  escape_handler,
+                                    void                        *user_data);
+void ply_window_remove_escape_handler (ply_window_t                *window,
+                                       ply_window_escape_handler_t  escape_handler);
+void ply_window_add_enter_handler (ply_window_t               *window,
+                                   ply_window_enter_handler_t  enter_handler,
+                                   void                       *user_data);
+void ply_window_remove_enter_handler (ply_window_t               *window,
+                                      ply_window_enter_handler_t  enter_handler);
+void ply_window_add_draw_handler (ply_window_t              *window,
+                                  ply_window_draw_handler_t  draw_handler,
+                                  void                      *user_data);
+void ply_window_remove_draw_handler (ply_window_t              *window,
+                                     ply_window_draw_handler_t  draw_handler);
+void ply_window_add_erase_handler (ply_window_t               *window,
+                                   ply_window_erase_handler_t  erase_handler,
+                                   void                       *user_data);
+void ply_window_remove_erase_handler (ply_window_t               *window,
+                                      ply_window_erase_handler_t erase_handler);
 
 bool ply_window_open (ply_window_t *window);
 bool ply_window_is_open (ply_window_t *window);
                                      uint32_t            hex_value);
 void ply_window_reset_colors (ply_window_t *window);
 
+void ply_window_set_draw_handler (ply_window_t                *window,
+                                  ply_window_draw_handler_t    draw_handler,
+                                  void                        *user_data);
+void ply_window_set_erase_handler (ply_window_t               *window,
+                                   ply_window_erase_handler_t  erase_handler,
+                                   void                       *user_data);
 void ply_window_attach_to_event_loop (ply_window_t     *window,
                                       ply_event_loop_t *loop);
 ply_frame_buffer_t *ply_window_get_frame_buffer (ply_window_t *window);
 
 #include <sysexits.h>
 #include <sys/ioctl.h>
 #include <unistd.h>
+#include <wchar.h>
 
 #include <linux/kd.h>
 
 #define PLY_MAX_COMMAND_LINE_SIZE 512
 #endif
 
+typedef struct 
+{
+  const char    *keys;
+  ply_trigger_t *trigger;
+} ply_keystroke_watch_t;
+
+typedef struct 
+{
+  enum {PLY_ENTRY_TRIGGER_TYPE_PASSWORD,
+        PLY_ENTRY_TRIGGER_TYPE_QUESTION}
+        type;
+  const char    *prompt;
+  ply_trigger_t *trigger;
+} ply_entry_trigger_t;
+
 typedef struct
 {
   ply_event_loop_t *loop;
   ply_terminal_session_t *session;
   ply_buffer_t *boot_buffer;
   ply_progress_t *progress;
+  ply_list_t *keystroke_triggers;
+  ply_list_t *entry_triggers;
+  ply_buffer_t *entry_buffer;
   long ptmx;
 
   char kernel_command_line[PLY_MAX_COMMAND_LINE_SIZE];
 static bool attach_to_running_session (state_t *state);
 static void on_escape_pressed (state_t *state);
 static void dump_details_and_quit_splash (state_t *state);
+static void update_display (state_t *state);
 
 static void
 on_session_output (state_t    *state,
                      const char   *prompt,
                      ply_trigger_t *answer)
 {
-  if (state->boot_splash == NULL)
+  ply_entry_trigger_t *entry_trigger =
+                                  calloc (1, sizeof (ply_entry_trigger_t));
+  entry_trigger->type = PLY_ENTRY_TRIGGER_TYPE_PASSWORD;
+  entry_trigger->prompt = prompt;
+  entry_trigger->trigger = answer;
+  ply_list_append_data (state->entry_triggers, entry_trigger);
+  update_display (state);
+}
+
+static void
+on_ask_question (state_t      *state,
+                 const char   *prompt,
+                 ply_trigger_t *answer)
+{
+  ply_entry_trigger_t *entry_trigger =
+                                  calloc (1, sizeof (ply_entry_trigger_t));
+  entry_trigger->type = PLY_ENTRY_TRIGGER_TYPE_QUESTION;
+  entry_trigger->prompt = prompt;
+  entry_trigger->trigger = answer;
+  ply_list_append_data (state->entry_triggers, entry_trigger);
+  update_display (state);
+}
+
+static void
+on_watch_for_keystroke (state_t      *state,
+                     const char    *keys,
+                     ply_trigger_t *trigger)
+{
+  ply_keystroke_watch_t *keystroke_trigger =
+                                  calloc (1, sizeof (ply_keystroke_watch_t));
+  keystroke_trigger->keys = keys;
+  keystroke_trigger->trigger = trigger;
+  ply_list_append_data (state->keystroke_triggers, keystroke_trigger);
+}
+
+
+static void
+on_ignore_keystroke (state_t      *state,
+                     const char    *keys)
+{
+  ply_list_node_t *node;
+  
+  for (node = ply_list_get_first_node (state->keystroke_triggers); node;
+                    node = ply_list_get_next_node (state->keystroke_triggers, node))
     {
-      show_detailed_splash (state);
-      if (state->boot_splash == NULL)
-        ply_trigger_pull (answer, "");
-      return;
+      ply_keystroke_watch_t* keystroke_trigger = ply_list_node_get_data (node);
+      if ((!keystroke_trigger->keys && !keys) ||
+          (keystroke_trigger->keys && keys && strcmp(keystroke_trigger->keys, keys)==0))
+        {
+          ply_trigger_pull (keystroke_trigger->trigger, NULL);
+          ply_list_remove_node (state->keystroke_triggers, node);
+          return;
+        }
     }
-
-  ply_boot_splash_ask_for_password (state->boot_splash,
-                                    prompt, answer);
 }
 
+
 static void
 on_newroot (state_t    *state,
              const char *root_dir)
 
   server = ply_boot_server_new ((ply_boot_server_update_handler_t) on_update,
                                 (ply_boot_server_ask_for_password_handler_t) on_ask_for_password,
+                                (ply_boot_server_ask_question_handler_t) on_ask_question,
+                                (ply_boot_server_watch_for_keystroke_handler_t) on_watch_for_keystroke,
+                                (ply_boot_server_ignore_keystroke_handler_t) on_ignore_keystroke,
                                 (ply_boot_server_show_splash_handler_t) on_show_splash,
                                 (ply_boot_server_hide_splash_handler_t) on_hide_splash,
                                 (ply_boot_server_newroot_handler_t) on_newroot,
   return server;
 }
 
+
+static void
+update_display (state_t *state)
+{
+  if (!state->boot_splash) return;
+  
+  ply_list_node_t *node;
+  node = ply_list_get_first_node (state->entry_triggers);
+  if (node)
+    {
+      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);
+          bullets = MAX(0, bullets);
+          ply_boot_splash_display_password (state->boot_splash, 
+                                            entry_trigger->prompt,
+                                            bullets);
+        }
+      else if (entry_trigger->type == PLY_ENTRY_TRIGGER_TYPE_QUESTION)
+        {
+          ply_boot_splash_display_question (state->boot_splash,
+                                            entry_trigger->prompt,
+                                            ply_buffer_get_bytes (state->entry_buffer));
+        }
+      else {
+          ply_trace("unkown entry type");
+        }
+    }
+  else
+    {
+      ply_boot_splash_display_normal (state->boot_splash);
+    }
+
+}
+
 static void
 on_escape_pressed (state_t *state)
 {
       show_default_splash (state);
       state->showing_details = false;
     }
+  update_display (state);
 }
 
+static void
+on_keyboard_input (state_t                  *state,
+                   const char               *keyboard_input,
+                   size_t                    character_size)
+{
+  ply_list_node_t *node;
+  node = ply_list_get_first_node (state->entry_triggers);
+  if (node)
+    {
+      ply_buffer_append_bytes (state->entry_buffer, keyboard_input, character_size);
+      update_display (state);
+    }
+  else
+    {
+      for (node = ply_list_get_first_node (state->keystroke_triggers); node;
+                        node = ply_list_get_next_node (state->keystroke_triggers, node))
+        {
+          ply_keystroke_watch_t* keystroke_trigger = ply_list_node_get_data (node);
+          if (!keystroke_trigger->keys || strstr(keystroke_trigger->keys, keyboard_input))  /* assume strstr works on utf8 arrays */
+            {
+              ply_trigger_pull (keystroke_trigger->trigger, keyboard_input);
+              ply_list_remove_node (state->keystroke_triggers, node);
+              free(keystroke_trigger);
+              return;
+            }
+        }
+      return;
+    }
+}
+void
+on_backspace (state_t                  *state)
+{
+  ssize_t bytes_to_remove;
+  ssize_t previous_character_size;
+  const char *bytes;
+  size_t size;
+  ply_list_node_t *node = ply_list_get_first_node (state->entry_triggers);
+  if (!node) return;
+
+  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;
+
+  ply_buffer_remove_bytes_at_end (state->entry_buffer, bytes_to_remove);
+  update_display (state);
+}
+
+void
+on_enter (state_t                  *state,
+          const char               *line)
+{
+  ply_list_node_t *node;
+  node = ply_list_get_first_node (state->entry_triggers);
+  if (node)
+    {
+      ply_entry_trigger_t* entry_trigger = ply_list_node_get_data (node);
+      const char* reply_text = ply_buffer_get_bytes (state->entry_buffer);
+      ply_trigger_pull (entry_trigger->trigger, reply_text);
+      ply_buffer_clear (state->entry_buffer);
+      ply_list_remove_node (state->entry_triggers, node);
+      free(entry_trigger);
+      update_display (state);
+    }
+}
+
+
 static ply_window_t *
 create_window (state_t    *state,
                const char *tty_name)
         {
           ply_trace ("adding window to boot splash");
           ply_boot_splash_add_window (splash, window);
-          ply_trace ("listening for escape key");
-          ply_window_set_escape_handler (window, (ply_window_escape_handler_t)
-                                         on_escape_pressed, state);
         }
       node = next_node;
     }
 
   ply_trace ("adding windows to boot splash");
   add_windows_to_boot_splash (state, splash);
-
   ply_trace ("showing plugin");
   if (!ply_boot_splash_show (splash))
     {
       return NULL;
     }
 
+  update_display (state);
   return splash;
 }
 
 initialize_environment (state_t *state)
 {
   ply_trace ("initializing minimal work environment");
+  ply_list_node_t *node;
 
   if (!get_kernel_command_line (state))
     return false;
   check_logging (state);
 
   state->windows = ply_list_new ();
+  state->keystroke_triggers = ply_list_new ();
+  state->entry_triggers = ply_list_new ();
+  state->entry_buffer = ply_buffer_new();
   check_for_consoles (state);
 
   if (state->console != NULL)
     redirect_standard_io_to_device (state->console);
   else
     redirect_standard_io_to_device ("tty1");
-
+  
+  
+  for (node = ply_list_get_first_node (state->windows); node;
+                    node = ply_list_get_next_node (state->windows, node))
+    {
+      ply_window_t *window = ply_list_node_get_data (node);
+      
+      ply_trace ("listening for escape key");
+      ply_window_add_escape_handler (window, (ply_window_escape_handler_t)
+                                     on_escape_pressed, state);
+      ply_trace ("listening for keystrokes");
+      ply_window_add_keyboard_input_handler (window,
+           (ply_window_keyboard_input_handler_t) on_keyboard_input, state);
+      ply_trace ("listening for backspace");
+      ply_window_add_backspace_handler (window,
+           (ply_window_backspace_handler_t) on_backspace, state);
+      ply_trace ("listening for enter");
+      ply_window_add_enter_handler (window,
+           (ply_window_enter_handler_t) on_enter, state);
+    }
+  
+  
   ply_trace ("initialized minimal work environment");
   return true;
 }
 
 
 #include <linux/kd.h>
 
-void ask_for_password (ply_boot_splash_plugin_t *plugin,
-                       const char               *prompt,
-                       ply_trigger_t            *answer);
+#define CLEAR_LINE_SEQUENCE "\033[2K\r"
+
+typedef enum {
+   PLY_BOOT_SPLASH_DISPLAY_NORMAL,
+   PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY,
+   PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY
+} ply_boot_splash_display_type_t;
+
+
 typedef void (* ply_boot_splash_plugin_window_handler_t) (ply_window_t *window, ply_boot_splash_plugin_t *, void *user_data, void *other_user_data);
 
 ply_boot_splash_plugin_interface_t *ply_boot_splash_plugin_get_interface (void);
 struct _ply_boot_splash_plugin
 {
   ply_event_loop_t *loop;
-
-  ply_trigger_t *pending_password_answer;
   ply_list_t *windows;
+  ply_boot_splash_display_type_t state;
 
-  uint32_t keyboard_input_is_hidden : 1;
 };
 
 ply_boot_splash_plugin_t *
 
   plugin = calloc (1, sizeof (ply_boot_splash_plugin_t));
   plugin->windows = ply_list_new ();
-
+  plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL;
   return plugin;
 }
 
   ply_trace ("detaching from event loop");
 }
 
-
-static void
-write_text_on_window (ply_window_t             *window,
-                      ply_boot_splash_plugin_t *plugin,
-                      const char               *text,
-                      void                     *user_data);
 static void
 for_each_window (ply_boot_splash_plugin_t *plugin,
                  ply_boot_splash_plugin_window_handler_t handler,
   write (fd, text, size);
 }
 
+static void
+clear_line_on_window (ply_window_t             *window,
+                      ply_boot_splash_plugin_t *plugin,
+                      void                     *user_data,
+                      void                     *more_user_data)
+{
+  ply_window_clear_text_line (window);
+}
+
 void
 on_keyboard_input (ply_boot_splash_plugin_t *plugin,
                    const char               *keyboard_input,
                    size_t                    character_size)
 {
-  if (plugin->keyboard_input_is_hidden)
-      for_each_window (plugin,
-                       (ply_boot_splash_plugin_window_handler_t)
-                       write_text_on_window, (void *) "*",
-                       (void *) strlen ("*"));
-  else
-      for_each_window (plugin,
-                       (ply_boot_splash_plugin_window_handler_t)
-                       write_text_on_window, (void *) keyboard_input,
-                       (void *) character_size);
 }
 
 void
 on_backspace (ply_boot_splash_plugin_t *plugin)
 {
-  for_each_window (plugin,
-                   (ply_boot_splash_plugin_window_handler_t)
-                   ply_window_clear_text_character, NULL, NULL);
 }
 
 void
 on_enter (ply_boot_splash_plugin_t *plugin,
           const char               *line)
 {
-  if (plugin->pending_password_answer != NULL)
-    {
-      ply_trigger_pull (plugin->pending_password_answer, line);
-      plugin->keyboard_input_is_hidden = false;
-      plugin->pending_password_answer = NULL;
-
-      for_each_window (plugin,
-                       (ply_boot_splash_plugin_window_handler_t)
-                       ply_window_clear_text_line, NULL, NULL);
-    }
 }
 
 void
 initialize_window (ply_window_t             *window,
                    ply_boot_splash_plugin_t *plugin)
 {
-  ply_boot_splash_plugin_interface_t *interface;
-
   ply_window_set_mode (window, PLY_WINDOW_MODE_TEXT);
 
-  ply_window_set_keyboard_input_handler (window,
+  ply_window_add_keyboard_input_handler (window,
                                          (ply_window_keyboard_input_handler_t)
                                          on_keyboard_input, plugin);
-  ply_window_set_backspace_handler (window,
+  ply_window_add_backspace_handler (window,
                                     (ply_window_backspace_handler_t)
                                     on_backspace, plugin);
-  ply_window_set_enter_handler (window,
+  ply_window_add_enter_handler (window,
                                 (ply_window_enter_handler_t)
                                 on_enter, plugin);
-
-  interface = ply_boot_splash_plugin_get_interface ();
-
-  interface->ask_for_password = ask_for_password;
 }
 
 static void
 uninitialize_window (ply_window_t             *window,
                      ply_boot_splash_plugin_t *plugin)
 {
-  ply_window_set_keyboard_input_handler (window, NULL, NULL);
-  ply_window_set_backspace_handler (window, NULL, NULL);
-  ply_window_set_enter_handler (window, NULL, NULL);
+  ply_window_remove_keyboard_input_handler (window, (ply_window_keyboard_input_handler_t) on_keyboard_input);
+  ply_window_remove_backspace_handler (window, (ply_window_backspace_handler_t) on_backspace);
+  ply_window_remove_enter_handler (window, (ply_window_enter_handler_t) on_enter);
 }
 
 bool
                    (ply_boot_splash_plugin_window_handler_t)
                    uninitialize_window, NULL, NULL);
 
-  if (plugin->pending_password_answer != NULL)
-    {
-      ply_trigger_pull (plugin->pending_password_answer, "");
-      plugin->pending_password_answer = NULL;
-      plugin->keyboard_input_is_hidden = false;
-    }
-
   ply_event_loop_stop_watching_for_exit (plugin->loop,
                                          (ply_event_loop_exit_handler_t)
                                          detach_from_event_loop,
   detach_from_event_loop (plugin);
 }
 
-static void
-ask_for_password_on_window (ply_window_t             *window,
-                            ply_boot_splash_plugin_t *plugin,
-                            const char               *prompt)
+void display_normal (ply_boot_splash_plugin_t *plugin)
 {
-  int fd;
-
-  ply_window_set_mode (window, PLY_WINDOW_MODE_TEXT);
+  if (plugin->state != PLY_BOOT_SPLASH_DISPLAY_NORMAL)
+    {
+      for_each_window (plugin,
+                 (ply_boot_splash_plugin_window_handler_t)
+                 write_text_on_window, 
+                 (void *) "\r\n", (void *) strlen ("\r\n"));
+    }
+  plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL;
+}
 
-  fd = ply_window_get_tty_fd (window);
 
-  if (prompt != NULL)
+void
+display_password (ply_boot_splash_plugin_t *plugin,
+                  const char               *prompt,
+                  int                       bullets)
+{
+  int i;
+  if (plugin->state != PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY)
+    {
+      for_each_window (plugin,
+                 (ply_boot_splash_plugin_window_handler_t)
+                 write_text_on_window,
+                 (void *) "\r\n", (void *) strlen ("\r\n"));
+    }
+  else
     {
-      write (fd, "\r\n", strlen ("\r\n"));
-      write (fd, prompt, strlen (prompt));
+      for_each_window (plugin,
+                 (ply_boot_splash_plugin_window_handler_t)
+                 write_text_on_window,
+                 (void *) CLEAR_LINE_SEQUENCE,
+                 (void *) strlen (CLEAR_LINE_SEQUENCE));
     }
+  plugin->state = PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY;
+  
+  if (prompt)
+      for_each_window (plugin,
+                 (ply_boot_splash_plugin_window_handler_t)
+                 write_text_on_window, 
+                 (void *) prompt,
+                 (void *) strlen (prompt));
+  else
+      for_each_window (plugin,
+                 (ply_boot_splash_plugin_window_handler_t)
+                 write_text_on_window, 
+                 (void *) "Password",
+                 (void *) strlen ("Password"));
 
-  write (fd, "\r\nPassword: ", strlen ("\r\nPassword: "));
-  plugin->keyboard_input_is_hidden = true;
+  for_each_window (plugin,
+             (ply_boot_splash_plugin_window_handler_t)
+             write_text_on_window, 
+             (void *) ":",
+             (void *) strlen (":"));
+  for (i=0; i<bullets; i++)
+      for_each_window (plugin,
+             (ply_boot_splash_plugin_window_handler_t)
+             write_text_on_window, 
+             (void *) "*",
+             (void *) strlen ("*"));
 }
 
 void
-ask_for_password (ply_boot_splash_plugin_t *plugin,
+display_question (ply_boot_splash_plugin_t *plugin,
                   const char               *prompt,
-                  ply_trigger_t            *answer)
+                  const char               *entry_text)
 {
-  plugin->pending_password_answer = answer;
-
+  if (plugin->state != PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY)
+    {
+      for_each_window (plugin,
+                 (ply_boot_splash_plugin_window_handler_t)
+                 write_text_on_window,
+                 (void *) "\r\n", (void *) strlen ("\r\n"));
+    }
+  else
+    {
+      for_each_window (plugin,
+                 (ply_boot_splash_plugin_window_handler_t)
+                 write_text_on_window,
+                 (void *) CLEAR_LINE_SEQUENCE,
+                 (void *) strlen (CLEAR_LINE_SEQUENCE));
+    }
+  plugin->state = PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY;
+  if (prompt)
+    for_each_window (plugin,
+               (ply_boot_splash_plugin_window_handler_t)
+               write_text_on_window, 
+               (void *) prompt,
+               (void *) strlen (prompt));
   for_each_window (plugin,
-                   (ply_boot_splash_plugin_window_handler_t)
-                   ask_for_password_on_window, (void *) prompt, NULL);
+             (ply_boot_splash_plugin_window_handler_t)
+             write_text_on_window, 
+             (void *) ":",
+             (void *) strlen (":"));
+  for_each_window (plugin,
+             (ply_boot_splash_plugin_window_handler_t)
+             write_text_on_window, 
+             (void *) entry_text,
+             (void *) strlen (entry_text));
 }
 
 ply_boot_splash_plugin_interface_t *
       .update_status = update_status,
       .on_boot_output = on_boot_output,
       .hide_splash_screen = hide_splash_screen,
+      .display_normal = display_normal,
+      .display_password = display_password,
+      .display_question = display_question,      
     };
 
   return &plugin_interface;
 
 #define FRAMES_PER_SECOND 30
 #endif
 
+typedef enum {
+   PLY_BOOT_SPLASH_DISPLAY_NORMAL,
+   PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY,
+   PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY
+} ply_boot_splash_display_type_t;
+
 typedef struct
 {
   int x; 
   ply_window_t *window;
 
   ply_entry_t *entry;
-
-  ply_trigger_t *pending_password_answer;
+  ply_boot_splash_display_type_t state;
 
   double start_time;
   double now;
   plugin->star_image = ply_image_new (PLYMOUTH_IMAGE_DIR "fade-in/star.png");
   plugin->lock_image = ply_image_new (PLYMOUTH_IMAGE_DIR "fade-in/lock.png");
   plugin->entry = ply_entry_new (PLYMOUTH_IMAGE_DIR "fade-in");
+  plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL;
   plugin->stars = ply_list_new ();
 
   return plugin;
   ply_frame_buffer_unpause_updates (plugin->frame_buffer);
 }
 
-static void draw_password_entry (ply_boot_splash_plugin_t *plugin);
 static void
 on_timeout (ply_boot_splash_plugin_t *plugin)
 {
                    const char               *keyboard_input,
                    size_t                    character_size)
 {
-  if (plugin->pending_password_answer == NULL)
-    return;
-
-  ply_entry_add_bullet (plugin->entry);
 }
 
 void
 on_backspace (ply_boot_splash_plugin_t *plugin)
 {
-  ply_entry_remove_bullet (plugin->entry);
 }
 
 void
 on_enter (ply_boot_splash_plugin_t *plugin,
           const char               *text)
 {
-
-  if (plugin->pending_password_answer == NULL)
-    return;
-
-  ply_trigger_pull (plugin->pending_password_answer, text);
-  plugin->pending_password_answer = NULL;
-
-  ply_entry_hide (plugin->entry);
-  start_animation (plugin);
 }
 
 void
 
   draw_background (plugin, &area);
 
-  if (plugin->pending_password_answer != NULL)
-    ply_entry_draw (plugin->entry);
-  else
+  if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL)
     animate_at_time (plugin, plugin->now);
+  else
+    ply_entry_draw (plugin->entry);
 }
 
 void
   assert (plugin != NULL);
   assert (plugin->logo_image != NULL);
 
-  ply_window_set_keyboard_input_handler (plugin->window,
+  ply_window_add_keyboard_input_handler (plugin->window,
                                          (ply_window_keyboard_input_handler_t)
                                          on_keyboard_input, plugin);
-  ply_window_set_backspace_handler (plugin->window,
+  ply_window_add_backspace_handler (plugin->window,
                                     (ply_window_backspace_handler_t)
                                     on_backspace, plugin);
-  ply_window_set_enter_handler (plugin->window,
+  ply_window_add_enter_handler (plugin->window,
                                 (ply_window_enter_handler_t)
                                 on_enter, plugin);
 
 {
   assert (plugin != NULL);
 
-  if (plugin->pending_password_answer != NULL)
-    {
-      ply_trigger_pull (plugin->pending_password_answer, "");
-      plugin->pending_password_answer = NULL;
-    }
-
-  ply_window_set_keyboard_input_handler (plugin->window, NULL, NULL);
-  ply_window_set_backspace_handler (plugin->window, NULL, NULL);
-  ply_window_set_enter_handler (plugin->window, NULL, NULL);
+  ply_window_remove_keyboard_input_handler (plugin->window, (ply_window_keyboard_input_handler_t) on_keyboard_input);
+  ply_window_remove_backspace_handler (plugin->window, (ply_window_backspace_handler_t) on_backspace);
+  ply_window_remove_enter_handler (plugin->window, (ply_window_enter_handler_t) on_enter);
+  ply_window_set_draw_handler (plugin->window, NULL, NULL);
+  ply_window_set_erase_handler (plugin->window, NULL, NULL);
 
   if (plugin->loop != NULL)
     {
   x = area.width / 2.0 - (lock_width + entry_width) / 2.0 + lock_width;
   y = area.height / 2.0 - entry_height / 2.0;
 
-  draw_background (plugin, NULL);
-
   ply_entry_show (plugin->entry, plugin->loop, plugin->window, x, y);
 }
 
+void display_normal (ply_boot_splash_plugin_t *plugin)
+{
+  if (plugin->state ==  PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY ||
+      plugin->state ==  PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY)
+    {
+      plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL;
+      ply_entry_hide (plugin->entry);
+      start_animation(plugin);
+    }
+}
+
+void
+display_password (ply_boot_splash_plugin_t *plugin,
+                  const char               *prompt,
+                  int                       bullets)
+{
+  if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL)
+    {
+      stop_animation (plugin);
+    }
+  plugin->state = PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY;
+  show_password_entry (plugin);
+  ply_entry_set_bullet_count (plugin->entry, bullets);
+}
+
 void
-ask_for_password (ply_boot_splash_plugin_t *plugin,
+display_question (ply_boot_splash_plugin_t *plugin,
                   const char               *prompt,
-                  ply_trigger_t            *answer)
+                  const char               *entry_text)
 {
-  plugin->pending_password_answer = answer;
+  if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL)
+    {
+      stop_animation (plugin);
+      show_password_entry (plugin);
+    }
 
-  stop_animation (plugin);
+  plugin->state = PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY;
   show_password_entry (plugin);
+  ply_entry_set_text (plugin->entry, entry_text);
 }
 
 ply_boot_splash_plugin_interface_t *
       .show_splash_screen = show_splash_screen,
       .update_status = update_status,
       .hide_splash_screen = hide_splash_screen,
-      .ask_for_password = ask_for_password,
+      .display_normal = display_normal,
+      .display_password = display_password,
+      .display_question = display_question,
     };
 
   return &plugin_interface;
 
 {
   ply_event_loop_t *loop;
 
-  ply_trigger_t *pending_password_answer;
   ply_window_t *window;
 
   ply_text_pulser_t *pulser;
                    const char               *keyboard_input,
                    size_t                    character_size)
 {
-  if (plugin->keyboard_input_is_hidden)
-    write (STDOUT_FILENO, "•", strlen ("•"));
-  else
-    write (STDOUT_FILENO, keyboard_input, character_size);
 }
 
 void
 on_backspace (ply_boot_splash_plugin_t *plugin)
 {
-  write (STDOUT_FILENO, BACKSPACE, strlen (BACKSPACE));
 }
 
 void
 on_enter (ply_boot_splash_plugin_t *plugin,
           const char               *line)
 {
-  if (plugin->pending_password_answer != NULL)
-    {
-      ply_trigger_pull (plugin->pending_password_answer, line);
-      plugin->keyboard_input_is_hidden = false;
-      plugin->pending_password_answer = NULL;
-
-      start_animation (plugin);
-    }
 }
 
 void
 
   ply_show_new_kernel_messages (false);
 
-  ply_window_set_keyboard_input_handler (plugin->window,
+  ply_window_add_keyboard_input_handler (plugin->window,
                                          (ply_window_keyboard_input_handler_t)
                                          on_keyboard_input, plugin);
-  ply_window_set_backspace_handler (plugin->window,
+  ply_window_add_backspace_handler (plugin->window,
                                     (ply_window_backspace_handler_t)
                                     on_backspace, plugin);
-  ply_window_set_enter_handler (plugin->window,
+  ply_window_add_enter_handler (plugin->window,
                                 (ply_window_enter_handler_t)
                                 on_enter, plugin);
   ply_window_set_draw_handler (plugin->window,
 
   ply_trace ("hiding splash screen");
 
-  if (plugin->pending_password_answer != NULL)
-    {
-      ply_trigger_pull (plugin->pending_password_answer, "");
-      plugin->pending_password_answer = NULL;
-    }
-
   if (plugin->loop != NULL)
     {
       stop_animation (plugin);
 
   if (plugin->window != NULL)
     {
-      ply_window_set_keyboard_input_handler (plugin->window, NULL, NULL);
-      ply_window_set_backspace_handler (plugin->window, NULL, NULL);
-      ply_window_set_enter_handler (plugin->window, NULL, NULL);
+      ply_window_remove_keyboard_input_handler (plugin->window, (ply_window_keyboard_input_handler_t) on_keyboard_input);
+      ply_window_remove_backspace_handler (plugin->window, (ply_window_backspace_handler_t) on_backspace);
+      ply_window_remove_enter_handler (plugin->window, (ply_window_enter_handler_t) on_enter);
       ply_window_set_draw_handler (plugin->window, NULL, NULL);
       ply_window_set_erase_handler (plugin->window, NULL, NULL);
 
   ply_show_new_kernel_messages (true);
 }
 
+void display_normal (ply_boot_splash_plugin_t *plugin)
+{
+  start_animation(plugin);
+}
+
 void
-ask_for_password (ply_boot_splash_plugin_t *plugin,
+display_password (ply_boot_splash_plugin_t *plugin,
                   const char               *prompt,
-                  ply_trigger_t            *answer)
+                  int                       bullets)
 {
-  int window_width, window_height;
-
-  plugin->pending_password_answer = answer;
+      int window_width, window_height;
+      int i;
+      stop_animation (plugin);
+      ply_window_set_background_color (plugin->window, PLY_WINDOW_COLOR_DEFAULT);
+      ply_window_clear_screen (plugin->window);
 
-  stop_animation (plugin);
-  ply_window_set_background_color (plugin->window, PLY_WINDOW_COLOR_DEFAULT);
-  ply_window_clear_screen (plugin->window);
+      window_width = ply_window_get_number_of_text_columns (plugin->window);
+      window_height = ply_window_get_number_of_text_rows (plugin->window);
+      
+      if (!prompt)
+        prompt = "Password";
+      
+      ply_window_set_text_cursor_position (plugin->window, 0, window_height / 2);
+      
+      for (i=0; i < window_width; i++)
+        {
+          write (STDOUT_FILENO, " ", strlen (" "));
+        }
+      ply_window_set_text_cursor_position (plugin->window,
+                                           window_width / 2 - (strlen (prompt)),
+                                           window_height / 2);
+      write (STDOUT_FILENO, prompt, strlen (prompt));
+      write (STDOUT_FILENO, ":", strlen (":"));
+      
+      for (i=0; i < bullets; i++)
+        {
+          write (STDOUT_FILENO, "•", strlen ("•"));
+        }
+      ply_window_show_text_cursor (plugin->window);
+}
 
-  window_width = ply_window_get_number_of_text_columns (plugin->window);
-  window_height = ply_window_get_number_of_text_rows (plugin->window);
+void
+display_question (ply_boot_splash_plugin_t *plugin,
+                  const char               *prompt,
+                  const char               *entry_text)
+{
+      int window_width, window_height;
+      int i;
+      stop_animation (plugin);
+      ply_window_set_background_color (plugin->window, PLY_WINDOW_COLOR_DEFAULT);
+      ply_window_clear_screen (plugin->window);
 
-  if (prompt != NULL)
-    {
+      window_width = ply_window_get_number_of_text_columns (plugin->window);
+      window_height = ply_window_get_number_of_text_rows (plugin->window);
+      
+      if (!prompt)
+        prompt = "";
+      
       ply_window_set_text_cursor_position (plugin->window,
-                                           window_width / 2 - strlen (prompt) / 2,
-                                           window_height / 2 - 1);
+                                           0, window_height / 2);
+      
+      for (i=0; i < window_width; i++)
+        {
+          write (STDOUT_FILENO, " ", strlen (" "));
+        }
+      ply_window_set_text_cursor_position (plugin->window,
+                                           window_width / 2 - (strlen (prompt)),
+                                           window_height / 2);
       write (STDOUT_FILENO, prompt, strlen (prompt));
-    }
-  ply_window_set_text_cursor_position (plugin->window,
-                                       window_width / 2 - strlen ("Password:        "),
-                                       window_height / 2);
-  write (STDOUT_FILENO, "Password: ", strlen ("Password: "));
-  ply_window_show_text_cursor (plugin->window);
-  plugin->keyboard_input_is_hidden = true;
+      write (STDOUT_FILENO, ":", strlen (":"));
+      
+      write (STDOUT_FILENO, entry_text, strlen (entry_text));
+      ply_window_show_text_cursor (plugin->window);
 }
 
+
 ply_boot_splash_plugin_interface_t *
 ply_boot_splash_plugin_get_interface (void)
 {
       .show_splash_screen = show_splash_screen,
       .update_status = update_status,
       .hide_splash_screen = hide_splash_screen,
-      .ask_for_password = ask_for_password,
+      .display_normal = display_normal,
+      .display_password = display_password,
+      .display_question = display_question,      
     };
 
   return &plugin_interface;
 
 #define SHOW_PROGRESS_BAR
 /*#define SHOW_LOGO_HALO */
 
+typedef enum {
+  PLY_BOOT_SPLASH_DISPLAY_NORMAL,
+  PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY,
+  PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY
+} ply_boot_splash_display_type_t;
 
 typedef enum
 {
 
   ply_entry_t *entry;
   ply_label_t *label;
+  ply_boot_splash_display_type_t state;
 
-  ply_trigger_t *pending_password_answer;
   ply_trigger_t *idle_trigger;
 
   ply_list_t *sprites;
 #endif
   plugin->entry = ply_entry_new (PLYMOUTH_IMAGE_DIR "solar");
   plugin->label = ply_label_new ();
+  plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL;
   plugin->sprites = ply_list_new();
   plugin->progress = 0;
   plugin->progress_target = -1;
   int stretched_width = ply_image_get_width (scaled_image);
   int stretched_height = ply_image_get_height (scaled_image);
   int orig_width = ply_image_get_width (orig_image);
-  int orig_height = ply_image_get_height (orig_image);
   uint32_t * scaled_image_data = ply_image_get_data (scaled_image);
   uint32_t * orig_image_data = ply_image_get_data (orig_image);
   
   
   if (satellite->type == SATELLITE_TYPE_PLANET)
     {
-      int x, y, z;
+      int x, y;
 
       uint32_t *image_data = ply_image_get_data (satellite->image);
       uint32_t *cresent_data = ply_image_get_data (satellite->image_altered);
   
   if (satellite->type == SATELLITE_TYPE_COMET)
     {
-      int x, y, z;
+      int x, y;
 
       uint32_t *image_data = ply_image_get_data (satellite->image);
       uint32_t *comet_data = ply_image_get_data (satellite->image_altered);
 
 
   int b;
-  static int start=1;
-
   for (b=0; b<FLARE_COUNT; b++)
     {
       int flare_line;
 animate_attime (ply_boot_splash_plugin_t *plugin, double time)
 {
   ply_list_node_t *node;
-  long width, height;
-
+  
   ply_window_set_mode (plugin->window, PLY_WINDOW_MODE_GRAPHICS);
 
   if (plugin->progress_target>=0)
           sprite->z != sprite->oldz ||
           sprite->refresh_me)
         {
-          ply_frame_buffer_area_t sprite_area;
           sprite->refresh_me=0;
 
           int width = ply_image_get_width (sprite->image);
 stop_animation (ply_boot_splash_plugin_t *plugin,
                 ply_trigger_t            *trigger)
 {
-  int i;
   ply_list_node_t *node;
 
   assert (plugin != NULL);
                    const char               *keyboard_input,
                    size_t                    character_size)
 {
-  if (plugin->pending_password_answer == NULL)
-    return;
-
-  ply_entry_add_bullet (plugin->entry);
 }
 
 void
 on_backspace (ply_boot_splash_plugin_t *plugin)
 {
-  ply_entry_remove_bullet (plugin->entry);
 }
 
 void
 on_enter (ply_boot_splash_plugin_t *plugin,
           const char               *text)
 {
-  if (plugin->pending_password_answer == NULL)
-    return;
-
-  ply_trigger_pull (plugin->pending_password_answer, text);
-  plugin->pending_password_answer = NULL;
-
-  ply_entry_hide (plugin->entry);
-  ply_entry_remove_all_bullets (plugin->entry);
-  start_animation (plugin);
 }
 
 
   else 
       ply_frame_buffer_pause_updates (plugin->frame_buffer);
 
-  if (plugin->pending_password_answer != NULL)
+  if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY || 
+      plugin->state == PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY  )
     {
       draw_background (plugin, &clip_area);
       ply_entry_draw (plugin->entry);
   assert (plugin != NULL);
   assert (plugin->logo_image != NULL);
 
-  ply_window_set_keyboard_input_handler (plugin->window,
+  ply_window_add_keyboard_input_handler (plugin->window,
                                          (ply_window_keyboard_input_handler_t)
                                          on_keyboard_input, plugin);
-  ply_window_set_backspace_handler (plugin->window,
+  ply_window_add_backspace_handler (plugin->window,
                                     (ply_window_backspace_handler_t)
                                     on_backspace, plugin);
-  ply_window_set_enter_handler (plugin->window,
+  ply_window_add_enter_handler (plugin->window,
                                 (ply_window_enter_handler_t)
                                 on_enter, plugin);
 
 {
   assert (plugin != NULL);
 
-  if (plugin->pending_password_answer != NULL)
-    {
-      ply_trigger_pull (plugin->pending_password_answer, "");
-      plugin->pending_password_answer = NULL;
-    }
-
-  ply_window_set_keyboard_input_handler (plugin->window, NULL, NULL);
-  ply_window_set_backspace_handler (plugin->window, NULL, NULL);
-  ply_window_set_enter_handler (plugin->window, NULL, NULL);
+  ply_window_remove_keyboard_input_handler (plugin->window, (ply_window_keyboard_input_handler_t) on_keyboard_input);
+  ply_window_remove_backspace_handler (plugin->window, (ply_window_backspace_handler_t) on_backspace);
+  ply_window_remove_enter_handler (plugin->window, (ply_window_enter_handler_t) on_enter);
   ply_window_set_draw_handler (plugin->window, NULL, NULL);
   ply_window_set_erase_handler (plugin->window, NULL, NULL);
 
 
   assert (plugin != NULL);
 
-  draw_background (plugin, NULL);
-
-  ply_frame_buffer_get_size (plugin->frame_buffer, &area);
-  plugin->box_area.width = ply_image_get_width (plugin->box_image);
-  plugin->box_area.height = ply_image_get_height (plugin->box_image);
-  plugin->box_area.x = area.width / 2.0 - plugin->box_area.width / 2.0;
-  plugin->box_area.y = area.height / 2.0 - plugin->box_area.height / 2.0;
+  if (ply_entry_is_hidden (plugin->entry))
+    {
+      draw_background (plugin, NULL);
 
-  plugin->lock_area.width = ply_image_get_width (plugin->lock_image);
-  plugin->lock_area.height = ply_image_get_height (plugin->lock_image);
+      ply_frame_buffer_get_size (plugin->frame_buffer, &area);
+      plugin->box_area.width = ply_image_get_width (plugin->box_image);
+      plugin->box_area.height = ply_image_get_height (plugin->box_image);
+      plugin->box_area.x = area.width / 2.0 - plugin->box_area.width / 2.0;
+      plugin->box_area.y = area.height / 2.0 - plugin->box_area.height / 2.0;
 
-  entry_width = ply_entry_get_width (plugin->entry);
-  entry_height = ply_entry_get_height (plugin->entry);
+      plugin->lock_area.width = ply_image_get_width (plugin->lock_image);
+      plugin->lock_area.height = ply_image_get_height (plugin->lock_image);
 
-  x = area.width / 2.0 - (plugin->lock_area.width + entry_width) / 2.0 + plugin->lock_area.width;
-  y = area.height / 2.0 - entry_height / 2.0;
+      entry_width = ply_entry_get_width (plugin->entry);
+      entry_height = ply_entry_get_height (plugin->entry);
 
-  plugin->lock_area.x = area.width / 2.0 - (plugin->lock_area.width + entry_width) / 2.0;
-  plugin->lock_area.y = area.height / 2.0 - plugin->lock_area.height / 2.0;
+      x = area.width / 2.0 - (plugin->lock_area.width + entry_width) / 2.0 + plugin->lock_area.width;
+      y = area.height / 2.0 - entry_height / 2.0;
 
-  box_data = ply_image_get_data (plugin->box_image);
-  ply_frame_buffer_fill_with_argb32_data (plugin->frame_buffer,
-                                          &plugin->box_area, 0, 0,
-                                          box_data);
+      plugin->lock_area.x = area.width / 2.0 - (plugin->lock_area.width + entry_width) / 2.0;
+      plugin->lock_area.y = area.height / 2.0 - plugin->lock_area.height / 2.0;
 
-  ply_entry_show (plugin->entry, plugin->loop, plugin->window, x, y);
+      box_data = ply_image_get_data (plugin->box_image);
+      ply_frame_buffer_fill_with_argb32_data (plugin->frame_buffer,
+                                              &plugin->box_area, 0, 0,
+                                              box_data);
 
-  lock_data = ply_image_get_data (plugin->lock_image);
-  ply_frame_buffer_fill_with_argb32_data (plugin->frame_buffer,
-                                          &plugin->lock_area, 0, 0,
-                                          lock_data);
+      ply_entry_show (plugin->entry, plugin->loop, plugin->window, x, y);
 
+      lock_data = ply_image_get_data (plugin->lock_image);
+      ply_frame_buffer_fill_with_argb32_data (plugin->frame_buffer,
+                                              &plugin->lock_area, 0, 0,
+                                              lock_data);
+    }
+  else
+    {
+      ply_entry_draw (plugin->entry);
+    }
   if (prompt != NULL)
     {
       int label_width, label_height;
       label_height = ply_label_get_height (plugin->label);
 
       x = plugin->box_area.x + plugin->lock_area.width / 2;
-      y = plugin->box_area.y + plugin->box_area.height + label_height;
+      y = plugin->box_area.y + plugin->box_area.height;
 
       ply_label_show (plugin->label, plugin->window, x, y);
     }
 }
 
 void
-ask_for_password (ply_boot_splash_plugin_t *plugin,
-                  const char               *prompt,
-                  ply_trigger_t             *answer)
+on_root_mounted (ply_boot_splash_plugin_t *plugin)
 {
-  plugin->pending_password_answer = answer;
+  plugin->root_is_mounted = true;
+}
 
-  if (ply_entry_is_hidden (plugin->entry))
-    {
-      stop_animation (plugin, NULL);
-      show_password_prompt (plugin, prompt);
-    }
-  else
+void
+become_idle (ply_boot_splash_plugin_t *plugin,
+             ply_trigger_t            *idle_trigger)
+{
+  stop_animation (plugin, idle_trigger);
+}
+
+void display_normal (ply_boot_splash_plugin_t *plugin)
+{
+  if (plugin->state != PLY_BOOT_SPLASH_DISPLAY_NORMAL)
     {
-      ply_entry_draw (plugin->entry);
-      ply_label_draw (plugin->label);
+      plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL;
+      ply_entry_hide (plugin->entry);
+      start_animation(plugin);
     }
 }
 
 void
-on_root_mounted (ply_boot_splash_plugin_t *plugin)
+display_password (ply_boot_splash_plugin_t *plugin,
+                  const char               *prompt,
+                  int                       bullets)
 {
-  plugin->root_is_mounted = true;
+  if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL)
+    {
+      stop_animation (plugin, NULL);
+    }
+  plugin->state = PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY;
+  show_password_prompt (plugin, prompt);
+  ply_entry_set_bullet_count (plugin->entry, bullets);
 }
 
 void
-become_idle (ply_boot_splash_plugin_t *plugin,
-             ply_trigger_t            *idle_trigger)
+display_question (ply_boot_splash_plugin_t *plugin,
+                  const char               *prompt,
+                  const char               *entry_text)
 {
-  stop_animation (plugin, idle_trigger);
+  if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL)
+    {
+      stop_animation (plugin, NULL);
+    }
+
+  plugin->state = PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY;
+  show_password_prompt (plugin, prompt);
+  ply_entry_set_text (plugin->entry, entry_text);
 }
 
 ply_boot_splash_plugin_interface_t *
       .update_status = update_status,
       .on_boot_progress = on_boot_progress,
       .hide_splash_screen = hide_splash_screen,
-      .ask_for_password = ask_for_password,
       .on_root_mounted = on_root_mounted,
-      .become_idle = become_idle
+      .become_idle = become_idle,
+      .display_normal = display_normal,
+      .display_password = display_password,
+      .display_question = display_question,      
     };
 
   return &plugin_interface;
 
 #define BAR_HEIGHT 16
 #endif
 
+typedef enum {
+   PLY_BOOT_SPLASH_DISPLAY_NORMAL,
+   PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY,
+   PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY
+} ply_boot_splash_display_type_t;
+
 struct _ply_boot_splash_plugin
 {
   ply_event_loop_t *loop;
   ply_throbber_t *throbber;
   ply_label_t *label;
   ply_progress_bar_t *progress_bar;
+  ply_boot_splash_display_type_t state;
 
-  ply_trigger_t *pending_password_answer;
   ply_trigger_t *idle_trigger;
 
   uint32_t root_is_mounted : 1;
 stop_animation (ply_boot_splash_plugin_t *plugin,
                 ply_trigger_t            *trigger)
 {
-  int i;
-
   assert (plugin != NULL);
   assert (plugin->loop != NULL);
 
                    const char               *keyboard_input,
                    size_t                    character_size)
 {
-  if (plugin->pending_password_answer == NULL)
-    return;
-
-  ply_entry_add_bullet (plugin->entry);
 }
 
 void
 on_enter (ply_boot_splash_plugin_t *plugin,
           const char               *text)
 {
-  if (plugin->pending_password_answer == NULL)
-    return;
-
-  ply_trigger_pull (plugin->pending_password_answer, text);
-  plugin->pending_password_answer = NULL;
-
-  ply_entry_hide (plugin->entry);
-  ply_entry_remove_all_bullets (plugin->entry);
-  start_animation (plugin);
 }
 
 void
   ply_frame_buffer_pause_updates (plugin->frame_buffer);
   draw_background (plugin, &area);
 
-  if (plugin->pending_password_answer != NULL)
+  if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY || 
+      plugin->state == PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY  )
     {
       ply_entry_draw (plugin->entry);
       ply_label_draw (plugin->label);
   assert (plugin != NULL);
   assert (plugin->logo_image != NULL);
 
-  ply_window_set_keyboard_input_handler (plugin->window,
+  ply_window_add_keyboard_input_handler (plugin->window,
                                          (ply_window_keyboard_input_handler_t)
                                          on_keyboard_input, plugin);
-  ply_window_set_backspace_handler (plugin->window,
+  ply_window_add_backspace_handler (plugin->window,
                                     (ply_window_backspace_handler_t)
                                     on_backspace, plugin);
-  ply_window_set_enter_handler (plugin->window,
+  ply_window_add_enter_handler (plugin->window,
                                 (ply_window_enter_handler_t)
                                 on_enter, plugin);
 
 {
   assert (plugin != NULL);
 
-  if (plugin->pending_password_answer != NULL)
-    {
-      ply_trigger_pull (plugin->pending_password_answer, "");
-      plugin->pending_password_answer = NULL;
-    }
 
-  ply_window_set_keyboard_input_handler (plugin->window, NULL, NULL);
-  ply_window_set_backspace_handler (plugin->window, NULL, NULL);
-  ply_window_set_enter_handler (plugin->window, NULL, NULL);
+  ply_window_remove_keyboard_input_handler (plugin->window, (ply_window_keyboard_input_handler_t) on_keyboard_input);
+  ply_window_remove_backspace_handler (plugin->window, (ply_window_backspace_handler_t) on_backspace);
+  ply_window_remove_enter_handler (plugin->window, (ply_window_enter_handler_t) on_enter);
   ply_window_set_draw_handler (plugin->window, NULL, NULL);
   ply_window_set_erase_handler (plugin->window, NULL, NULL);
 
 
   assert (plugin != NULL);
 
-  draw_background (plugin, NULL);
-
-  ply_frame_buffer_get_size (plugin->frame_buffer, &area);
-  plugin->box_area.width = ply_image_get_width (plugin->box_image);
-  plugin->box_area.height = ply_image_get_height (plugin->box_image);
-  plugin->box_area.x = area.width / 2.0 - plugin->box_area.width / 2.0;
-  plugin->box_area.y = area.height / 2.0 - plugin->box_area.height / 2.0;
+  if (ply_entry_is_hidden (plugin->entry))
+    {
+      draw_background (plugin, NULL);
 
-  plugin->lock_area.width = ply_image_get_width (plugin->lock_image);
-  plugin->lock_area.height = ply_image_get_height (plugin->lock_image);
+      ply_frame_buffer_get_size (plugin->frame_buffer, &area);
+      plugin->box_area.width = ply_image_get_width (plugin->box_image);
+      plugin->box_area.height = ply_image_get_height (plugin->box_image);
+      plugin->box_area.x = area.width / 2.0 - plugin->box_area.width / 2.0;
+      plugin->box_area.y = area.height / 2.0 - plugin->box_area.height / 2.0;
 
-  entry_width = ply_entry_get_width (plugin->entry);
-  entry_height = ply_entry_get_height (plugin->entry);
+      plugin->lock_area.width = ply_image_get_width (plugin->lock_image);
+      plugin->lock_area.height = ply_image_get_height (plugin->lock_image);
 
-  x = area.width / 2.0 - (plugin->lock_area.width + entry_width) / 2.0 + plugin->lock_area.width;
-  y = area.height / 2.0 - entry_height / 2.0;
+      entry_width = ply_entry_get_width (plugin->entry);
+      entry_height = ply_entry_get_height (plugin->entry);
 
-  plugin->lock_area.x = area.width / 2.0 - (plugin->lock_area.width + entry_width) / 2.0;
-  plugin->lock_area.y = area.height / 2.0 - plugin->lock_area.height / 2.0;
+      x = area.width / 2.0 - (plugin->lock_area.width + entry_width) / 2.0 + plugin->lock_area.width;
+      y = area.height / 2.0 - entry_height / 2.0;
 
-  box_data = ply_image_get_data (plugin->box_image);
-  ply_frame_buffer_fill_with_argb32_data (plugin->frame_buffer,
-                                          &plugin->box_area, 0, 0,
-                                          box_data);
+      plugin->lock_area.x = area.width / 2.0 - (plugin->lock_area.width + entry_width) / 2.0;
+      plugin->lock_area.y = area.height / 2.0 - plugin->lock_area.height / 2.0;
 
-  ply_entry_show (plugin->entry, plugin->loop, plugin->window, x, y);
+      box_data = ply_image_get_data (plugin->box_image);
+      ply_frame_buffer_fill_with_argb32_data (plugin->frame_buffer,
+                                              &plugin->box_area, 0, 0,
+                                              box_data);
 
-  lock_data = ply_image_get_data (plugin->lock_image);
-  ply_frame_buffer_fill_with_argb32_data (plugin->frame_buffer,
-                                          &plugin->lock_area, 0, 0,
-                                          lock_data);
+      ply_entry_show (plugin->entry, plugin->loop, plugin->window, x, y);
 
+      lock_data = ply_image_get_data (plugin->lock_image);
+      ply_frame_buffer_fill_with_argb32_data (plugin->frame_buffer,
+                                              &plugin->lock_area, 0, 0,
+                                              lock_data);
+    }
+  else
+    {
+      ply_entry_draw (plugin->entry);
+    }
   if (prompt != NULL)
     {
       int label_width, label_height;
       label_height = ply_label_get_height (plugin->label);
 
       x = plugin->box_area.x + plugin->lock_area.width / 2;
-      y = plugin->box_area.y + plugin->box_area.height + label_height;
+      y = plugin->box_area.y + plugin->box_area.height;
 
       ply_label_show (plugin->label, plugin->window, x, y);
     }
 }
 
 void
-ask_for_password (ply_boot_splash_plugin_t *plugin,
-                  const char               *prompt,
-                  ply_trigger_t            *answer)
+on_root_mounted (ply_boot_splash_plugin_t *plugin)
 {
-  plugin->pending_password_answer = answer;
+  plugin->root_is_mounted = true;
+}
 
-  if (ply_entry_is_hidden (plugin->entry))
-    {
-      stop_animation (plugin, NULL);
-      show_password_prompt (plugin, prompt);
-    }
-  else
+void
+become_idle (ply_boot_splash_plugin_t *plugin,
+             ply_trigger_t            *idle_trigger)
+{
+  stop_animation (plugin, idle_trigger);
+}
+
+void display_normal (ply_boot_splash_plugin_t *plugin)
+{
+  if (plugin->state != PLY_BOOT_SPLASH_DISPLAY_NORMAL)
     {
-      ply_entry_draw (plugin->entry);
-      ply_label_draw (plugin->label);
+      plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL;
+      ply_entry_hide (plugin->entry);
+      start_animation(plugin);
     }
 }
 
 void
-on_root_mounted (ply_boot_splash_plugin_t *plugin)
+display_password (ply_boot_splash_plugin_t *plugin,
+                  const char               *prompt,
+                  int                       bullets)
 {
-  plugin->root_is_mounted = true;
+  if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL)
+    {
+      stop_animation (plugin, NULL);
+    }
+  plugin->state = PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY;
+  show_password_prompt (plugin, prompt);
+  ply_entry_set_bullet_count (plugin->entry, bullets);
 }
 
 void
-become_idle (ply_boot_splash_plugin_t *plugin,
-             ply_trigger_t            *idle_trigger)
+display_question (ply_boot_splash_plugin_t *plugin,
+                  const char               *prompt,
+                  const char               *entry_text)
 {
-  stop_animation (plugin, idle_trigger);
+  if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL)
+    {
+      stop_animation (plugin, NULL);
+    }
+
+  plugin->state = PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY;
+  show_password_prompt (plugin, prompt);
+  ply_entry_set_text (plugin->entry, entry_text);
 }
 
 ply_boot_splash_plugin_interface_t *
       .update_status = update_status,
       .on_boot_progress = on_boot_progress,
       .hide_splash_screen = hide_splash_screen,
-      .ask_for_password = ask_for_password,
       .on_root_mounted = on_root_mounted,
       .become_idle = become_idle,
+      .display_normal = display_normal,
+      .display_password = display_password,
+      .display_question = display_question,      
     };
 
   return &plugin_interface;
 
 #define CLEAR_LINE_SEQUENCE "\033[2K\r\n"
 #define BACKSPACE "\b\033[0K"
 
+
 struct _ply_boot_splash_plugin
 {
   ply_event_loop_t *loop;
 
-  ply_trigger_t *pending_password_answer;
   ply_window_t *window;
 
   ply_text_progress_bar_t *progress_bar;
 
-  uint32_t keyboard_input_is_hidden : 1;
   uint32_t is_animating : 1;
 };
 void hide_splash_screen (ply_boot_splash_plugin_t *plugin,
 start_animation (ply_boot_splash_plugin_t *plugin)
 {
 
-  int window_width, window_height;
-  int width, height;
   assert (plugin != NULL);
   assert (plugin->loop != NULL);
 
                    const char               *keyboard_input,
                    size_t                    character_size)
 {
-  if (plugin->keyboard_input_is_hidden)
-    write (STDOUT_FILENO, "•", strlen ("•"));
-  else
-    write (STDOUT_FILENO, keyboard_input, character_size);
 }
 
 void
 on_backspace (ply_boot_splash_plugin_t *plugin)
 {
-  write (STDOUT_FILENO, BACKSPACE, strlen (BACKSPACE));
 }
 
 void
 on_enter (ply_boot_splash_plugin_t *plugin,
           const char               *line)
 {
-  if (plugin->pending_password_answer != NULL)
-    {
-      ply_trigger_pull (plugin->pending_password_answer, line);
-      plugin->keyboard_input_is_hidden = false;
-      plugin->pending_password_answer = NULL;
-
-      start_animation (plugin);
-    }
 }
 
 void
 {
   assert (plugin != NULL);
 
-  ply_window_set_keyboard_input_handler (plugin->window,
+  ply_window_add_keyboard_input_handler (plugin->window,
                                          (ply_window_keyboard_input_handler_t)
                                          on_keyboard_input, plugin);
-  ply_window_set_backspace_handler (plugin->window,
+  ply_window_add_backspace_handler (plugin->window,
                                     (ply_window_backspace_handler_t)
                                     on_backspace, plugin);
-  ply_window_set_enter_handler (plugin->window,
+  ply_window_add_enter_handler (plugin->window,
                                 (ply_window_enter_handler_t)
                                 on_enter, plugin);
   ply_window_set_draw_handler (plugin->window,
 
   ply_trace ("hiding splash screen");
 
-  if (plugin->pending_password_answer != NULL)
-    {
-      ply_trigger_pull (plugin->pending_password_answer, "");
-      plugin->pending_password_answer = NULL;
-    }
-
   if (plugin->loop != NULL)
     {
       stop_animation (plugin);
 
   if (plugin->window != NULL)
     {
-      ply_window_set_keyboard_input_handler (plugin->window, NULL, NULL);
-      ply_window_set_backspace_handler (plugin->window, NULL, NULL);
-      ply_window_set_enter_handler (plugin->window, NULL, NULL);
+      ply_window_remove_keyboard_input_handler (plugin->window, (ply_window_keyboard_input_handler_t) on_keyboard_input);
+      ply_window_remove_backspace_handler (plugin->window, (ply_window_backspace_handler_t) on_backspace);
+      ply_window_remove_enter_handler (plugin->window, (ply_window_enter_handler_t) on_enter);
       ply_window_set_draw_handler (plugin->window, NULL, NULL);
       ply_window_set_erase_handler (plugin->window, NULL, NULL);
 
   ply_show_new_kernel_messages (true);
 }
 
+void display_normal (ply_boot_splash_plugin_t *plugin)
+{
+  start_animation(plugin);
+}
+
 void
-ask_for_password (ply_boot_splash_plugin_t *plugin,
+display_password (ply_boot_splash_plugin_t *plugin,
                   const char               *prompt,
-                  ply_trigger_t            *answer)
+                  int                       bullets)
 {
-  int window_width, window_height;
-
-  plugin->pending_password_answer = answer;
+      int window_width, window_height;
+      int i;
+      stop_animation (plugin);
+      ply_window_set_background_color (plugin->window, PLY_WINDOW_COLOR_DEFAULT);
+      ply_window_clear_screen (plugin->window);
 
-  stop_animation (plugin);
-  ply_window_set_background_color (plugin->window, PLY_WINDOW_COLOR_DEFAULT);
-  ply_window_clear_screen (plugin->window);
+      window_width = ply_window_get_number_of_text_columns (plugin->window);
+      window_height = ply_window_get_number_of_text_rows (plugin->window);
+      
+      if (!prompt)
+        prompt = "Password";
+      
+      ply_window_set_text_cursor_position (plugin->window, 0, window_height / 2);
+      
+      for (i=0; i < window_width; i++)
+        {
+          write (STDOUT_FILENO, " ", strlen (" "));
+        }
+      ply_window_set_text_cursor_position (plugin->window,
+                                        window_width / 2 - (strlen (prompt)),
+                                        window_height / 2);
+      write (STDOUT_FILENO, prompt, strlen (prompt));
+      write (STDOUT_FILENO, ":", strlen (":"));
+      
+      for (i=0; i < bullets; i++)
+        {
+          write (STDOUT_FILENO, "*", strlen ("*"));
+        }
+      ply_window_show_text_cursor (plugin->window);
+}
 
-  window_width = ply_window_get_number_of_text_columns (plugin->window);
-  window_height = ply_window_get_number_of_text_rows (plugin->window);
+void
+display_question (ply_boot_splash_plugin_t *plugin,
+                  const char               *prompt,
+                  const char               *entry_text)
+{
+      int window_width, window_height;
+      int i;
+      stop_animation (plugin);
+      ply_window_set_background_color (plugin->window, PLY_WINDOW_COLOR_DEFAULT);
+      ply_window_clear_screen (plugin->window);
 
-  if (prompt != NULL)
-    {
+      window_width = ply_window_get_number_of_text_columns (plugin->window);
+      window_height = ply_window_get_number_of_text_rows (plugin->window);
+      
+      if (!prompt)
+        prompt = "";
+      
+      ply_window_set_text_cursor_position (plugin->window,
+                                        0, window_height / 2);
+      
+      for (i=0; i < window_width; i++)
+        {
+          write (STDOUT_FILENO, " ", strlen (" "));
+        }
       ply_window_set_text_cursor_position (plugin->window,
-                                           window_width / 2 - strlen (prompt) / 2,
-                                           window_height / 2 - 1);
+                                        window_width / 2 - (strlen (prompt)),
+                                        window_height / 2);
       write (STDOUT_FILENO, prompt, strlen (prompt));
-    }
-  ply_window_set_text_cursor_position (plugin->window,
-                                       window_width / 2 - strlen ("Password:        "),
-                                       window_height / 2);
-  write (STDOUT_FILENO, "Password: ", strlen ("Password: "));
-  ply_window_show_text_cursor (plugin->window);
-  plugin->keyboard_input_is_hidden = true;
+      write (STDOUT_FILENO, ":", strlen (":"));
+      
+      write (STDOUT_FILENO, entry_text, strlen (entry_text));
+      ply_window_show_text_cursor (plugin->window);
 }
 
+
 ply_boot_splash_plugin_interface_t *
 ply_boot_splash_plugin_get_interface (void)
 {
       .update_status = update_status,
       .on_boot_progress = on_boot_progress,
       .hide_splash_screen = hide_splash_screen,
-      .ask_for_password = ask_for_password,
+      .display_normal = display_normal,
+      .display_password = display_password,
+      .display_question = display_question,      
     };
 
   return &plugin_interface;
 
 #define PLY_BOOT_PROTOCOL_REQUEST_TYPE_QUIT "Q"
 #define PLY_BOOT_PROTOCOL_REQUEST_TYPE_PASSWORD "*"
 #define PLY_BOOT_PROTOCOL_REQUEST_TYPE_CACHED_PASSWORD "c"
+#define PLY_BOOT_PROTOCOL_REQUEST_TYPE_QUESTION "W"
+#define PLY_BOOT_PROTOCOL_REQUEST_TYPE_KEYSTROKE "K"
+#define PLY_BOOT_PROTOCOL_REQUEST_TYPE_KEYSTROKE_REMOVE "L"
 #define PLY_BOOT_PROTOCOL_REQUEST_TYPE_SHOW_SPLASH "$"
 #define PLY_BOOT_PROTOCOL_REQUEST_TYPE_HIDE_SPLASH "H"
 #define PLY_BOOT_PROTOCOL_REQUEST_TYPE_NEWROOT "R"
 
   ply_boot_server_show_splash_handler_t show_splash_handler;
   ply_boot_server_hide_splash_handler_t hide_splash_handler;
   ply_boot_server_ask_for_password_handler_t ask_for_password_handler;
+  ply_boot_server_ask_question_handler_t ask_question_handler;
+  ply_boot_server_watch_for_keystroke_handler_t watch_for_keystroke_handler;
+  ply_boot_server_ignore_keystroke_handler_t ignore_keystroke_handler;
   ply_boot_server_quit_handler_t quit_handler;
   void *user_data;
 
 ply_boot_server_t *
 ply_boot_server_new (ply_boot_server_update_handler_t  update_handler,
                      ply_boot_server_ask_for_password_handler_t ask_for_password_handler,
+                     ply_boot_server_ask_question_handler_t ask_question_handler,
+                     ply_boot_server_watch_for_keystroke_handler_t watch_for_keystroke_handler,
+                     ply_boot_server_ignore_keystroke_handler_t ignore_keystroke_handler,
                      ply_boot_server_show_splash_handler_t show_splash_handler,
                      ply_boot_server_hide_splash_handler_t hide_splash_handler,
                      ply_boot_server_newroot_handler_t newroot_handler,
   server->is_listening = false;
   server->update_handler = update_handler;
   server->ask_for_password_handler = ask_for_password_handler;
+  server->ask_question_handler = ask_question_handler;
+  server->watch_for_keystroke_handler = watch_for_keystroke_handler;
+  server->ignore_keystroke_handler = ignore_keystroke_handler;
   server->newroot_handler = newroot_handler;
   server->error_handler = error_handler;
   server->system_initialized_handler = initialized_handler;
   ply_list_node_t *node;
   if (server == NULL)
     return;
-  while (node = ply_list_get_first_node(server->connections))
+  while ((node = ply_list_get_first_node(server->connections)))
     {
       ply_boot_connection_t *connection = ply_list_node_get_data (node);
       ply_boot_connection_on_hangup (connection);
   return uid == 0;
 }
 
+
 static void
-ply_boot_connection_on_password_answer (ply_boot_connection_t *connection,
-                                        const char            *password)
+ply_boot_connection_send_answer (ply_boot_connection_t *connection,
+                                 const char            *answer)
 {
-
   uint8_t size;
 
   /* splash plugin isn't able to ask for password,
    * punt to client
    */
-  if (password == NULL)
+  if (answer == NULL)
     {
       if (!ply_write (connection->fd,
                       PLY_BOOT_PROTOCOL_RESPONSE_TYPE_NO_ANSWER,
     {
       /* FIXME: support up to 4 billion
       */
-      if (strlen (password) > 255)
-          ply_error ("password to long to fit in buffer");
+      if (strlen (answer) > 255)
+          ply_error ("answer to long to fit in buffer");
 
-      size = (uint8_t) strlen (password);
+      size = (uint8_t) strlen (answer);
 
       if (!ply_write (connection->fd,
                       PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ANSWER,
           !ply_write (connection->fd,
                       &size, sizeof (uint8_t)) ||
           !ply_write (connection->fd,
-                      password, size))
+                      answer, size))
           ply_error ("could not write bytes: %m");
 
-      ply_list_append_data (connection->server->cached_passwords,
-                            strdup (password));
     }
 
 }
 
+static void
+ply_boot_connection_on_password_answer (ply_boot_connection_t *connection,
+                                        const char            *password)
+{
+  ply_boot_connection_send_answer (connection, password);
+  if (password != NULL)
+    ply_list_append_data (connection->server->cached_passwords,
+                          strdup (password));
+
+}
+
+
+static void
+ply_boot_connection_on_question_answer (ply_boot_connection_t *connection,
+                                        const char             *answer)
+{
+  ply_boot_connection_send_answer (connection, answer);
+}
+
+static void
+ply_boot_connection_on_keystroke_answer (ply_boot_connection_t *connection,
+                                        const char            *key)
+{
+  ply_boot_connection_send_answer (connection, key);
+}
+
 static void
 ply_boot_connection_on_request (ply_boot_connection_t *connection)
 {
       free(command);
       return;
     }
+  else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_QUESTION) == 0)
+    {
+      ply_trigger_t *answer;
+
+      answer = ply_trigger_new (NULL);
+      ply_trigger_add_handler (answer,
+                               (ply_trigger_handler_t)
+                               ply_boot_connection_on_question_answer,
+                               connection);
+
+      if (server->ask_question_handler != NULL)
+        server->ask_question_handler (server->user_data,
+                                          argument,
+                                          answer,
+                                          server);
+      /* will reply later
+       */
+      free(command);
+      return;
+    }
+  else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_KEYSTROKE) == 0)
+    {
+      ply_trigger_t *answer;
+
+      answer = ply_trigger_new (NULL);
+      ply_trigger_add_handler (answer,
+                               (ply_trigger_handler_t)
+                               ply_boot_connection_on_keystroke_answer,
+                               connection);
+
+      if (server->watch_for_keystroke_handler != NULL)
+        server->watch_for_keystroke_handler (server->user_data,
+                                          argument,
+                                          answer,
+                                          server);
+      /* will reply later
+       */
+      free(command);
+      return;
+    }
+  else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_KEYSTROKE_REMOVE) == 0)
+    {
+      if (server->ignore_keystroke_handler != NULL)
+        server->ignore_keystroke_handler (server->user_data,
+                                          argument,
+                                          server);
+    }
   else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_NEWROOT) == 0)
     {
       if (server->newroot_handler != NULL)
   return strdup ("password");
 }
 
+static void
+on_ask_question (ply_event_loop_t *loop)
+{
+  printf ("got question request\n");
+  return;
+}
+
+static void
+on_watch_for_keystroke (ply_event_loop_t *loop)
+{
+  printf ("got keystroke request\n");
+
+  return;
+}
+
+
+static void
+on_ignore_keystroke (ply_event_loop_t *loop)
+{
+  printf ("got keystroke ignore request\n");
+
+  return;
+}
+
 int
 main (int    argc,
       char **argv)
 
   server = ply_boot_server_new ((ply_boot_server_update_handler_t) on_update,
                                 (ply_boot_server_ask_for_password_handler_t) on_ask_for_password,
+                                (ply_boot_server_ask_question_handler_t) on_ask_question,
+                                (ply_boot_server_watch_for_keystroke_handler_t) on_watch_for_keystroke,
+                                (ply_boot_server_ignore_keystroke_handler_t) on_ignore_keystroke,
                                 (ply_boot_server_show_splash_handler_t) on_show_splash,
                                 (ply_boot_server_hide_splash_handler_t) on_hide_splash,
                                 (ply_boot_server_newroot_handler_t) on_newroot,
 
                                                              const char        *prompt,
                                                              ply_trigger_t     *answer,
                                                              ply_boot_server_t *server);
+typedef void (* ply_boot_server_question_answer_handler_t) (void              *answer_data,
+                                                            const char         *answer,
+                                                            ply_boot_server_t  *server);
+typedef void (* ply_boot_server_ask_question_handler_t)      (void              *user_data,
+                                                              const char        *prompt,
+                                                              ply_trigger_t     *answer,
+                                                              ply_boot_server_t *server);
+typedef void (* ply_boot_server_watch_for_keystroke_handler_t) (void             *user_data,
+                                                             const char        *keys,
+                                                             ply_trigger_t     *answer,
+                                                             ply_boot_server_t *server);
+
+typedef void (* ply_boot_server_ignore_keystroke_handler_t) (void             *user_data,
+                                                             const char        *keys,
+                                                             ply_boot_server_t *server);
 
 typedef void (* ply_boot_server_system_initialized_handler_t) (void              *user_data,
                                                         ply_boot_server_t *server);
 #ifndef PLY_HIDE_FUNCTION_DECLARATIONS
 ply_boot_server_t *ply_boot_server_new (ply_boot_server_update_handler_t update_handler,
                                         ply_boot_server_ask_for_password_handler_t ask_for_password_handler,
+                                        ply_boot_server_ask_question_handler_t ask_question_handler,
+                                        ply_boot_server_watch_for_keystroke_handler_t watch_for_keystroke_handler,
+                                        ply_boot_server_ignore_keystroke_handler_t ignore_keystroke_handler,
                                         ply_boot_server_show_splash_handler_t show_splash_handler,
                                         ply_boot_server_hide_splash_handler_t hide_splash_handler,
                                         ply_boot_server_newroot_handler_t newroot_handler,
 
     splash->plugin_interface->on_root_mounted (splash->plugin);
 }
 
-static void
-on_password_answered (ply_boot_splash_t *splash)
-{
-  if (splash->progress)
-    ply_progress_unpause (splash->progress);
-}
-
-void
-ply_boot_splash_ask_for_password (ply_boot_splash_t *splash,
-                                  const char        *prompt,
-                                  ply_trigger_t     *trigger)
-{
-
-  assert (splash != NULL);
-  assert (splash->plugin_interface != NULL);
-  assert (splash->plugin != NULL);
-  assert (splash->is_shown);
-
-  if (splash->plugin_interface->ask_for_password == NULL)
-    {
-      ply_trigger_pull (trigger, NULL);
-      return;
-    }
-
-  if (splash->progress)
-    ply_progress_pause (splash->progress);
-  
-  ply_trigger_add_handler (trigger,
-                           (ply_trigger_handler_t)
-                           on_password_answered, splash);
-
-  splash->plugin_interface->ask_for_password (splash->plugin,
-                                              prompt,
-                                              trigger);
-}
-
 static void
 ply_boot_splash_detach_from_event_loop (ply_boot_splash_t *splash)
 {
     }
 }
 
+void ply_boot_splash_display_normal  (ply_boot_splash_t              *splash)
+{
+  assert (splash != NULL);
+  assert (splash->plugin_interface != NULL);
+  assert (splash->plugin != NULL);
+  if (splash->plugin_interface->display_normal != NULL)
+      splash->plugin_interface->display_normal (splash->plugin);
+}
+void ply_boot_splash_display_password (ply_boot_splash_t             *splash,
+                                       const char                    *prompt,
+                                       int                            bullets)
+{
+  assert (splash != NULL);
+  assert (splash->plugin_interface != NULL);
+  assert (splash->plugin != NULL);
+  if (splash->plugin_interface->display_password != NULL)
+      splash->plugin_interface->display_password (splash->plugin, prompt, bullets);
+}
+void ply_boot_splash_display_question (ply_boot_splash_t             *splash,
+                                       const char                    *prompt,
+                                       const char                    *entry_text)
+{
+  assert (splash != NULL);
+  assert (splash->plugin_interface != NULL);
+  assert (splash->plugin != NULL);
+  if (splash->plugin_interface->display_question != NULL)
+      splash->plugin_interface->display_question (splash->plugin, prompt, entry_text);
+}
+
+
+
 void
 ply_boot_splash_attach_to_event_loop (ply_boot_splash_t *splash,
                                       ply_event_loop_t  *loop)
     }
 
   ply_window_attach_to_event_loop (state.window, state.loop);
-  ply_window_set_escape_handler (state.window,
+  ply_window_add_escape_handler (state.window,
                                  (ply_window_escape_handler_t) on_quit, &state);
 
   state.buffer = ply_buffer_new ();
 
                                     const char        *output,
                                     size_t             size);
 void ply_boot_splash_root_mounted (ply_boot_splash_t *splash);
-
-void ply_boot_splash_ask_for_password (ply_boot_splash_t *splash,
-                                       const char        *prompt,
-                                       ply_trigger_t     *answer);
 void ply_boot_splash_hide (ply_boot_splash_t *splash);
+void ply_boot_splash_display_normal  (ply_boot_splash_t              *splash);
+void ply_boot_splash_display_password (ply_boot_splash_t             *splash,
+                                       const char                    *prompt,
+                                       int                            bullets);
+void ply_boot_splash_display_question (ply_boot_splash_t             *splash,
+                                       const char                    *prompt,
+                                       const char                    *entry_text);
 void ply_boot_splash_attach_to_event_loop (ply_boot_splash_t *splash,
                                            ply_event_loop_t  *loop);
 void ply_boot_splash_attach_progress (ply_boot_splash_t *splash,