src/plugins/splash/Makefile
            src/plugins/splash/spinfinity/Makefile
            src/plugins/splash/fade-in/Makefile
+           src/plugins/splash/text/Makefile
            src/plugins/splash/pulser/Makefile
            src/plugins/splash/details/Makefile
            src/plugins/controls/Makefile
 
 inst ${LIBDIR}/plymouth/text.so $INITRDDIR
 inst ${LIBDIR}/plymouth/details.so $INITRDDIR
 inst ${PLYMOUTH_LOGO_FILE} $INITRDDIR
+inst /etc/system-release $INITRDDIR
 mkdir -p ${INITRDDIR}${DATADIR}/plymouth
 
 PLUGIN_NAME=$(plymouth-set-default-plugin)
 
 lib_LTLIBRARIES = libplybootsplash.la
 
 libplybootsplashdir = $(includedir)/plymouth-1/plybootsplash
-libplybootsplash_HEADERS = ply-entry.h ply-progress-bar.h ply-text-pulser.h ply-throbber.h ply-window.h ply-label.h ply-boot-splash-plugin.h ply-label-plugin.h
+libplybootsplash_HEADERS = ply-entry.h ply-progress-bar.h ply-text-progress-bar.h ply-text-pulser.h ply-throbber.h ply-window.h ply-label.h ply-boot-splash-plugin.h ply-label-plugin.h
 
 libplybootsplash_la_CFLAGS = $(PLYMOUTH_CFLAGS)                               \
                              -DPLYMOUTH_BACKGROUND_COLOR=$(background_color)   \
                    ply-label.c                                              \
                    ply-progress-bar.c                                       \
                    ply-throbber.c                                           \
+                   ply-text-progress-bar.c                                  \
                    ply-text-pulser.c                                        \
                    ply-window.c
 
 
--- /dev/null
+/* ply-text-progress-bar.c -  simple text based progress bar
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by: Adam Jackson <ajax@redhat.com>
+ *             Bill Nottingham <notting@redhat.com>
+ *             Ray Strode <rstrode@redhat.com>
+ */
+#include "config.h"
+
+#include <assert.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <math.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <values.h>
+#include <unistd.h>
+#include <wchar.h>
+
+#include "ply-text-progress-bar.h"
+#include "ply-event-loop.h"
+#include "ply-array.h"
+#include "ply-logger.h"
+#include "ply-utils.h"
+#include "ply-window.h"
+
+#include <linux/kd.h>
+
+#ifndef FRAMES_PER_SECOND
+#define FRAMES_PER_SECOND 5
+#endif
+
+#define NUMBER_OF_INDICATOR_COLUMNS 6
+
+#define OS_STRING " "
+char *os_string = OS_STRING;
+
+struct _ply_text_progress_bar
+{
+  ply_event_loop_t *loop;
+
+  ply_window_t            *window;
+
+  int column, row;
+  int number_of_rows;
+  int number_of_columns;
+  int spinner_position;
+  double start_time, now;
+};
+
+ply_text_progress_bar_t *
+ply_text_progress_bar_new (void)
+{
+  ply_text_progress_bar_t *progress_bar;
+
+  progress_bar = calloc (1, sizeof (ply_text_progress_bar_t));
+
+  progress_bar->row = 0;
+  progress_bar->column = 0;
+  progress_bar->spinner_position = 0;
+  progress_bar->number_of_columns = 0;
+  progress_bar->number_of_rows = 0;
+
+  return progress_bar;
+}
+
+void
+ply_text_progress_bar_free (ply_text_progress_bar_t *progress_bar)
+{
+  if (progress_bar == NULL)
+    return;
+
+  free (progress_bar);
+}
+
+static void
+get_os_string (void)
+{
+   int fd;
+   char *buf, *pos, *pos2;
+   struct stat sbuf;
+   
+   fd = open("/etc/system-release", O_RDONLY);
+   if (fd == -1) return;
+   if (fstat(fd, &sbuf) == -1) return;
+   buf = calloc(sbuf.st_size + 1, sizeof(char));
+   read(fd, buf, sbuf.st_size);
+   close(fd);
+   
+   pos = strstr(buf, " release ");
+   if (!pos) goto out;
+   pos2 = strstr(pos, " (");
+   if (!pos2) goto out;
+   *pos = '\0';
+   pos+= 9;
+   *pos2 = '\0';
+   asprintf(&os_string," %s %s", buf, pos);
+out:
+   free(buf);
+}
+
+/* Hi Will! */
+static double
+woodsify(double time, double estimate)
+{
+    return 1.0 - pow(2.0, -pow(time, 1.45) / estimate);
+}
+
+#define STARTUP_TIME 20.0
+
+static void
+animate_at_time (ply_text_progress_bar_t *progress_bar,
+                 double             time)
+{
+    int i, width = progress_bar->number_of_columns - 2 - strlen(os_string);
+    double brown_fraction, blue_fraction, white_fraction;
+
+    ply_window_set_mode (progress_bar->window, PLY_WINDOW_MODE_TEXT);
+    ply_window_set_text_cursor_position(progress_bar->window,
+                                       progress_bar->column,
+                                       progress_bar->row);
+
+    brown_fraction = woodsify(time, STARTUP_TIME);
+    blue_fraction  = woodsify(time, STARTUP_TIME / brown_fraction);
+    white_fraction = woodsify(time, STARTUP_TIME / blue_fraction);
+
+    for (i = 0; i < width; i += 1) {
+       double f = (double)i / (double)width;
+       if (f < white_fraction)
+           ply_window_set_background_color (progress_bar->window,
+                                            PLY_WINDOW_COLOR_WHITE);
+       else if (f < blue_fraction)
+           ply_window_set_background_color (progress_bar->window,
+                                            PLY_WINDOW_COLOR_BLUE);
+       else if (f < brown_fraction)
+           ply_window_set_background_color (progress_bar->window,
+                                            PLY_WINDOW_COLOR_BROWN);
+       else break;
+
+       write (STDOUT_FILENO, " ", strlen (" "));
+    }
+
+    ply_window_set_background_color (progress_bar->window, PLY_WINDOW_COLOR_BLACK);
+
+    if (brown_fraction > 0.5) {
+       if (white_fraction > 0.875)
+           ply_window_set_foreground_color (progress_bar->window,
+                                            PLY_WINDOW_COLOR_WHITE);
+       else if (blue_fraction > 0.66)
+           ply_window_set_foreground_color (progress_bar->window,
+                                            PLY_WINDOW_COLOR_BLUE);
+       else
+           ply_window_set_foreground_color (progress_bar->window,
+                                            PLY_WINDOW_COLOR_BROWN);
+
+       ply_window_set_text_cursor_position(progress_bar->window,
+                                           progress_bar->column + width,
+                                           progress_bar->row);
+
+
+       write (STDOUT_FILENO, os_string, strlen(os_string));
+       
+       ply_window_set_foreground_color (progress_bar->window,
+                                        PLY_WINDOW_COLOR_DEFAULT);
+    }
+}
+
+static void
+on_timeout (ply_text_progress_bar_t *progress_bar)
+{
+  double sleep_time;
+  progress_bar->now = ply_get_timestamp ();
+
+#ifdef REAL_TIME_ANIMATION
+  animate_at_time (progress_bar,
+                   progress_bar->now - progress_bar->start_time);
+#else
+  static double time = 0.0;
+  time += 1.0 / FRAMES_PER_SECOND;
+  animate_at_time (progress_bar, time);
+#endif
+
+  sleep_time = 1.0 / FRAMES_PER_SECOND;
+  sleep_time = MAX (sleep_time - (ply_get_timestamp () - progress_bar->now),
+                    0.005);
+
+  ply_event_loop_watch_for_timeout (progress_bar->loop,
+                                    sleep_time,
+                                    (ply_event_loop_timeout_handler_t)
+                                    on_timeout, progress_bar);
+}
+
+bool
+ply_text_progress_bar_start (ply_text_progress_bar_t  *progress_bar,
+                       ply_event_loop_t   *loop,
+                       ply_window_t       *window)
+{
+  assert (progress_bar != NULL);
+  assert (progress_bar->loop == NULL);
+
+  progress_bar->loop = loop;
+  progress_bar->window = window;
+
+  progress_bar->number_of_rows = ply_window_get_number_of_text_rows(window);
+  progress_bar->row = progress_bar->number_of_rows - 1;
+  progress_bar->number_of_columns = ply_window_get_number_of_text_columns(window);
+  progress_bar->column = 2;
+
+  progress_bar->start_time = ply_get_timestamp ();
+  
+  get_os_string ();
+
+  ply_event_loop_watch_for_timeout (progress_bar->loop,
+                                    1.0 / FRAMES_PER_SECOND,
+                                    (ply_event_loop_timeout_handler_t)
+                                    on_timeout, progress_bar);
+
+  return true;
+}
+
+void
+ply_text_progress_bar_stop (ply_text_progress_bar_t *progress_bar)
+{
+  progress_bar->window = NULL;
+
+  if (progress_bar->loop != NULL)
+    {
+      ply_event_loop_stop_watching_for_timeout (progress_bar->loop,
+                                                (ply_event_loop_timeout_handler_t)
+                                                on_timeout, progress_bar);
+      progress_bar->loop = NULL;
+    }
+}
+
+int
+ply_text_progress_bar_get_number_of_columns (ply_text_progress_bar_t *progress_bar)
+{
+  return progress_bar->number_of_columns;
+}
+
+int
+ply_text_progress_bar_get_number_of_rows (ply_text_progress_bar_t *progress_bar)
+{
+  return progress_bar->number_of_rows;
+}
+
+/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
 
--- /dev/null
+/* ply-text-progress-bar.h - simple text based pulsing animation
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by: Adam Jackson <ajax@redhat.com>
+ *             Bill Nottingham <notting@redhat.com>
+ *             Ray Strode <rstrode@redhat.com>
+ */
+#ifndef PLY_TEXT_PROGRESS_BAR_H
+#define PLY_TEXT_PROGRESS_BAR_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include "ply-event-loop.h"
+#include "ply-window.h"
+
+typedef struct _ply_text_progress_bar ply_text_progress_bar_t;
+
+#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
+ply_text_progress_bar_t *ply_text_progress_bar_new (void);
+void ply_text_progress_bar_free (ply_text_progress_bar_t *progress_bar);
+
+bool ply_text_progress_bar_load (ply_text_progress_bar_t *progress_bar);
+bool ply_text_progress_bar_start (ply_text_progress_bar_t  *progress_bar,
+                            ply_event_loop_t   *loop,
+                            ply_window_t       *window);
+void ply_text_progress_bar_stop (ply_text_progress_bar_t *progress_bar);
+
+int ply_text_progress_bar_get_number_of_rows (ply_text_progress_bar_t *progress_bar);
+int ply_text_progress_bar_get_number_of_columns (ply_text_progress_bar_t *progress_bar);
+#endif
+
+#endif /* PLY_TEXT_PULSER_H */
+/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
 
-SUBDIRS = spinfinity fade-in pulser details
+SUBDIRS = spinfinity fade-in text pulser details
 MAINTAINERCLEANFILES = Makefile.in
 
 if ADD_DEFAULT_PLUGIN_LINK
 
--- /dev/null
+INCLUDES = -I$(top_srcdir)                                                    \
+           -I$(srcdir)/../../../libply                                        \
+           -I$(srcdir)/../../../libplybootsplash                              \
+           -I$(srcdir)/../../..                                               \
+           -I$(srcdir)/../..                                                  \
+           -I$(srcdir)/..                                                     \
+           -I$(srcdir)
+
+plugindir = $(libdir)/plymouth
+plugin_LTLIBRARIES = text.la
+
+text_la_CFLAGS = $(PLYMOUTH_CFLAGS)                                           \
+                 -DPLYMOUTH_BACKGROUND_COLOR=$(background_color)              \
+                 -DPLYMOUTH_BACKGROUND_END_COLOR=$(background_end_color)      \
+                 -DPLYMOUTH_BACKGROUND_START_COLOR=$(background_start_color)
+
+text_la_LDFLAGS = -module -avoid-version -export-dynamic
+text_la_LIBADD = $(PLYMOUTH_LIBS)                                            \
+                 ../../../libply/libply.la                                   \
+                 ../../../libplybootsplash/libplybootsplash.la
+text_la_SOURCES = $(srcdir)/plugin.c
+
+MAINTAINERCLEANFILES = Makefile.in
 
--- /dev/null
+/* text.c - boot splash plugin
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by: Adam Jackson <ajax@redhat.com>
+ *             Ray Strode <rstrode@redhat.com>
+ */
+#include "config.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <math.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <termios.h>
+#include <unistd.h>
+#include <values.h>
+#include <wchar.h>
+
+#include "ply-trigger.h"
+#include "ply-boot-splash-plugin.h"
+#include "ply-buffer.h"
+#include "ply-event-loop.h"
+#include "ply-list.h"
+#include "ply-logger.h"
+#include "ply-frame-buffer.h"
+#include "ply-image.h"
+#include "ply-text-progress-bar.h"
+#include "ply-utils.h"
+#include "ply-window.h"
+
+#include <linux/kd.h>
+
+#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;
+};
+void hide_splash_screen (ply_boot_splash_plugin_t *plugin,
+                         ply_event_loop_t         *loop);
+
+ply_boot_splash_plugin_t *
+create_plugin (void)
+{
+  ply_boot_splash_plugin_t *plugin;
+
+  ply_trace ("creating plugin");
+
+  plugin = calloc (1, sizeof (ply_boot_splash_plugin_t));
+  plugin->progress_bar = ply_text_progress_bar_new ();
+
+  return plugin;
+}
+
+static void
+detach_from_event_loop (ply_boot_splash_plugin_t *plugin)
+{
+  plugin->loop = NULL;
+
+  ply_trace ("detaching from event loop");
+}
+
+void
+destroy_plugin (ply_boot_splash_plugin_t *plugin)
+{
+  ply_trace ("destroying plugin");
+
+  if (plugin == NULL)
+    return;
+
+  /* It doesn't ever make sense to keep this plugin on screen
+   * after exit
+   */
+  hide_splash_screen (plugin, plugin->loop);
+
+  ply_text_progress_bar_free (plugin->progress_bar);
+
+  free (plugin);
+}
+
+static void
+start_animation (ply_boot_splash_plugin_t *plugin)
+{
+
+  int window_width, window_height;
+  int width, height;
+  assert (plugin != NULL);
+  assert (plugin->loop != NULL);
+
+  ply_window_set_color_hex_value (plugin->window,
+                                  PLY_WINDOW_COLOR_BLACK,
+                                  0x000000);
+  ply_window_set_color_hex_value (plugin->window,
+                                  PLY_WINDOW_COLOR_WHITE,
+                                  0xffffff);
+  ply_window_set_color_hex_value (plugin->window,
+                                  PLY_WINDOW_COLOR_BLUE,
+                                  0x0073B3);
+  ply_window_set_color_hex_value (plugin->window,
+                                  PLY_WINDOW_COLOR_BROWN,
+                                  0x00457E);
+#if 0
+  ply_window_set_color_hex_value (plugin->window,
+                                  PLY_WINDOW_COLOR_BLUE,
+                                  PLYMOUTH_BACKGROUND_START_COLOR);
+  ply_window_set_color_hex_value (plugin->window,
+                                  PLY_WINDOW_COLOR_GREEN,
+                                  PLYMOUTH_BACKGROUND_COLOR);
+#endif
+
+  ply_window_set_background_color (plugin->window, PLY_WINDOW_COLOR_BLACK);
+  ply_window_clear_screen (plugin->window);
+  ply_window_hide_text_cursor (plugin->window);
+
+  ply_text_progress_bar_start (plugin->progress_bar,
+                         plugin->loop,
+                         plugin->window);
+}
+
+static void
+stop_animation (ply_boot_splash_plugin_t *plugin)
+{
+  assert (plugin != NULL);
+  assert (plugin->loop != NULL);
+
+  ply_text_progress_bar_stop (plugin->progress_bar);
+}
+
+void
+on_keyboard_input (ply_boot_splash_plugin_t *plugin,
+                   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
+on_draw (ply_boot_splash_plugin_t *plugin,
+         int                       x,
+         int                       y,
+         int                       width,
+         int                       height)
+{
+  ply_window_set_background_color (plugin->window, PLY_WINDOW_COLOR_BLUE);
+  ply_window_clear_screen (plugin->window);
+}
+
+void
+on_erase (ply_boot_splash_plugin_t *plugin,
+          int                       x,
+          int                       y,
+          int                       width,
+          int                       height)
+{
+  ply_window_set_background_color (plugin->window, PLY_WINDOW_COLOR_BLUE);
+  ply_window_clear_screen (plugin->window);
+}
+
+void
+add_window (ply_boot_splash_plugin_t *plugin,
+            ply_window_t             *window)
+{
+  plugin->window = window;
+}
+
+void
+remove_window (ply_boot_splash_plugin_t *plugin,
+               ply_window_t             *window)
+{
+  plugin->window = NULL;
+}
+
+bool
+show_splash_screen (ply_boot_splash_plugin_t *plugin,
+                    ply_event_loop_t         *loop,
+                    ply_buffer_t             *boot_buffer)
+{
+  assert (plugin != NULL);
+
+  ply_window_set_keyboard_input_handler (plugin->window,
+                                         (ply_window_keyboard_input_handler_t)
+                                         on_keyboard_input, plugin);
+  ply_window_set_backspace_handler (plugin->window,
+                                    (ply_window_backspace_handler_t)
+                                    on_backspace, plugin);
+  ply_window_set_enter_handler (plugin->window,
+                                (ply_window_enter_handler_t)
+                                on_enter, plugin);
+  ply_window_set_draw_handler (plugin->window,
+                               (ply_window_draw_handler_t)
+                                on_draw, plugin);
+  ply_window_set_erase_handler (plugin->window,
+                                (ply_window_erase_handler_t)
+                                on_erase, plugin);
+
+  plugin->loop = loop;
+  ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t)
+                                 detach_from_event_loop,
+                                 plugin);
+
+  start_animation (plugin);
+
+  return true;
+}
+
+void
+update_status (ply_boot_splash_plugin_t *plugin,
+               const char               *status)
+{
+  assert (plugin != NULL);
+
+  ply_trace ("status update");
+}
+
+void
+hide_splash_screen (ply_boot_splash_plugin_t *plugin,
+                    ply_event_loop_t         *loop)
+{
+  assert (plugin != NULL);
+
+  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);
+
+      ply_event_loop_stop_watching_for_exit (plugin->loop,
+                                             (ply_event_loop_exit_handler_t)
+                                             detach_from_event_loop,
+                                             plugin);
+      detach_from_event_loop (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_set_draw_handler (plugin->window, NULL, NULL);
+      ply_window_set_erase_handler (plugin->window, NULL, NULL);
+
+      ply_window_set_background_color (plugin->window, PLY_WINDOW_COLOR_DEFAULT);
+      ply_window_clear_screen (plugin->window);
+      ply_window_show_text_cursor (plugin->window);
+      ply_window_reset_colors (plugin->window);
+    }
+}
+
+void
+ask_for_password (ply_boot_splash_plugin_t *plugin,
+                  const char               *prompt,
+                  ply_trigger_t            *answer)
+{
+  int window_width, window_height;
+
+  plugin->pending_password_answer = answer;
+
+  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 != NULL)
+    {
+      ply_window_set_text_cursor_position (plugin->window,
+                                           window_width / 2 - strlen (prompt) / 2,
+                                           window_height / 2 - 1);
+      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;
+}
+
+ply_boot_splash_plugin_interface_t *
+ply_boot_splash_plugin_get_interface (void)
+{
+  static ply_boot_splash_plugin_interface_t plugin_interface =
+    {
+      .create_plugin = create_plugin,
+      .destroy_plugin = destroy_plugin,
+      .add_window = add_window,
+      .remove_window = remove_window,
+      .show_splash_screen = show_splash_screen,
+      .update_status = update_status,
+      .hide_splash_screen = hide_splash_screen,
+      .ask_for_password = ask_for_password,
+    };
+
+  return &plugin_interface;
+}
+
+/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */