A patch to XScreensaver to provide lock window theming.

Default theme is a metallic grey border with green on black body using
the Neuropol font. For further details on the patch and theming see the
following web page; http://www.swanson.ukfsn.org/xss/

Alan Swanson <swanson@ukfsn.org>

Version 1.1
o Update for XScreenSaver 4.22
o Optional login button implemented
o Fix backgrounds for label and date fields
o Use clipmask for status to prevent overwriting borders

Version 1.0
o Initial release against XScreenSaver 4.15

diff -urP xscreensaver-4.22/driver/lock.c xscreensaver-4.22-lock/driver/lock.c
--- xscreensaver-4.22/driver/lock.c	2005-06-04 20:50:10.000000000 +0100
+++ xscreensaver-4.22-lock/driver/lock.c	2005-06-27 18:56:15.000000000 +0100
@@ -25,6 +25,28 @@
 #include "xscreensaver.h"
 #include "resources.h"
 
+#include "theme.h"
+#include "theme_logo.xpm"
+#include "theme_frame_t.xpm"
+#include "theme_frame_b.xpm"
+#include "theme_frame_l.xpm"
+#include "theme_frame_r.xpm"
+#include "theme_frame_tl.xpm"
+#include "theme_frame_tr.xpm"
+#include "theme_frame_bl.xpm"
+#include "theme_frame_br.xpm"
+
+#ifndef THEME_FONT_LOGIN
+#define THEME_FONT_LOGIN THEME_FONT_LABEL
+#endif
+#ifndef THEME_FG_LOGIN
+#define THEME_FG_LOGIN THEME_FG_LABEL
+#endif
+#ifndef THEME_BG_LOGIN
+#define THEME_BG_LOGIN THEME_BG
+#endif
+
+
 #ifndef NO_LOCKING              /* (mostly) whole file */
 
 #ifdef HAVE_SYSLOG
@@ -79,7 +101,18 @@
 #undef MAX
 #define MAX(a,b) ((a)>(b)?(a):(b))
 
-enum passwd_state { pw_read, pw_ok, pw_null, pw_fail, pw_cancel, pw_time };
+#undef MAX3
+#define MAX3(a,b,c) MAX(a,MAX(b,c))
+
+enum passwd_state { pw_read, pw_check, pw_ok, pw_null, pw_fail, pw_cancel, pw_time };
+
+struct xpm_data {
+  Pixmap pixmap;
+  Dimension width;
+  Dimension height;
+  int npixels;
+  unsigned long *pixels;
+};
 
 struct passwd_dialog_data {
 
@@ -100,38 +133,38 @@
   Bool show_stars_p; /* "I regret that I have but one asterisk for my country."
                         -- Nathan Hale, 1776. */
 
-  char *heading_label;
-  char *body_label;
   char *user_label;
   char *passwd_label;
   char *date_label;
+  char *login_label;
   char *user_string;
   char *passwd_string;
-  char *login_label;
+  char *status_string;
 
-  XFontStruct *heading_font;
-  XFontStruct *body_font;
   XFontStruct *label_font;
   XFontStruct *passwd_font;
   XFontStruct *date_font;
-  XFontStruct *button_font;
+  XFontStruct *login_font;
+  XFontStruct *status_font;
 
   Pixel foreground;
   Pixel background;
+
+  Pixel label_foreground;
+  Pixel label_background;
   Pixel passwd_foreground;
   Pixel passwd_background;
+  Pixel date_foreground;
+  Pixel date_background;
   Pixel thermo_foreground;
   Pixel thermo_background;
-  Pixel shadow_top;
-  Pixel shadow_bottom;
-  Pixel button_foreground;
-  Pixel button_background;
+  Pixel login_foreground;
+  Pixel login_background;
+  Pixel denied_foreground;
 
-  Dimension logo_width;
-  Dimension logo_height;
   Dimension thermo_width;
   Dimension internal_border;
-  Dimension shadow_width;
+  Dimension internal_spacer;
 
   Dimension passwd_field_x, passwd_field_y;
   Dimension passwd_field_width, passwd_field_height;
@@ -142,9 +175,20 @@
   Dimension thermo_field_x, thermo_field_y;
   Dimension thermo_field_height;
 
-  Pixmap logo_pixmap;
-  int logo_npixels;
-  unsigned long *logo_pixels;
+  struct xpm_data logo;
+  struct xpm_data frame_t;
+  struct xpm_data frame_b;
+  struct xpm_data frame_l;
+  struct xpm_data frame_r;
+  struct xpm_data frame_tl;
+  struct xpm_data frame_tr;
+  struct xpm_data frame_bl;
+  struct xpm_data frame_br;
+
+  Dimension frame_max_t;
+  Dimension frame_max_b;
+  Dimension frame_max_l;
+  Dimension frame_max_r;
 
   Cursor passwd_cursor;
   Bool login_button_down_p;
@@ -196,10 +240,6 @@
 
   pw->show_stars_p = get_boolean_resource("passwd.asterisks", "Boolean");
   
-  pw->heading_label = get_string_resource ("passwd.heading.label",
-					   "Dialog.Label.Label");
-  pw->body_label = get_string_resource ("passwd.body.label",
-					"Dialog.Label.Label");
   pw->user_label = get_string_resource ("passwd.user.label",
 					"Dialog.Label.Label");
   pw->passwd_label = get_string_resource ("passwd.passwd.label",
@@ -207,64 +247,53 @@
   pw->login_label = get_string_resource ("passwd.login.label",
                                          "Dialog.Button.Label");
 
-  pw->date_label = get_string_resource ("dateFormat", "DateFormat");
-
-  if (!pw->heading_label)
-    pw->heading_label = strdup("ERROR: RESOURCES NOT INSTALLED CORRECTLY");
-  if (!pw->body_label)
-    pw->body_label = strdup("ERROR: RESOURCES NOT INSTALLED CORRECTLY");
   if (!pw->user_label) pw->user_label = strdup("ERROR");
   if (!pw->passwd_label) pw->passwd_label = strdup("ERROR");
-  if (!pw->date_label) pw->date_label = strdup("ERROR");
-  if (!pw->login_label) pw->login_label = strdup ("ERROR (LOGIN)") ;
-
-  /* Put the version number in the label. */
-  {
-    char *s = (char *) malloc (strlen(pw->heading_label) + 20);
-    sprintf(s, pw->heading_label, si->version);
-    free (pw->heading_label);
-    pw->heading_label = s;
-  }
+  if (!pw->login_label) pw->login_label = strdup ("ERROR") ;
 
   pw->user_string = strdup (p && p->pw_name ? p->pw_name : "???");
   pw->passwd_string = strdup("");
+  pw->date_label = strdup("%H:%M");
+
+  pw->label_font = XLoadQueryFont (si->dpy, THEME_FONT_LABEL);
+  if (!pw->label_font) {
+    f = get_string_resource("passwd.labelFont", "Dialog.Font");
+    pw->label_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
+    if (!pw->label_font) pw->label_font = XLoadQueryFont (si->dpy, "fixed");
+    if (f) free (f);
+  }
 
-  f = get_string_resource ("passwd.headingFont", "Dialog.Font");
-  pw->heading_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
-  if (!pw->heading_font) pw->heading_font = XLoadQueryFont (si->dpy, "fixed");
-  if (f) free (f);
-
-  f = get_string_resource ("passwd.buttonFont", "Dialog.Font");
-  pw->button_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
-  if (!pw->button_font) pw->button_font = XLoadQueryFont (si->dpy, "fixed");
-  if (f) free (f);
-
-  f = get_string_resource("passwd.bodyFont", "Dialog.Font");
-  pw->body_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
-  if (!pw->body_font) pw->body_font = XLoadQueryFont (si->dpy, "fixed");
-  if (f) free (f);
-
-  f = get_string_resource("passwd.labelFont", "Dialog.Font");
-  pw->label_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
-  if (!pw->label_font) pw->label_font = XLoadQueryFont (si->dpy, "fixed");
-  if (f) free (f);
-
-  f = get_string_resource("passwd.passwdFont", "Dialog.Font");
-  pw->passwd_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
-  if (!pw->passwd_font) pw->passwd_font = XLoadQueryFont (si->dpy, "fixed");
-  if (f) free (f);
-
-  f = get_string_resource("passwd.dateFont", "Dialog.Font");
-  pw->date_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
-  if (!pw->date_font) pw->date_font = XLoadQueryFont (si->dpy, "fixed");
-  if (f) free (f);
-
-  pw->foreground = get_pixel_resource ("passwd.foreground",
-				       "Dialog.Foreground",
-				       si->dpy, cmap);
-  pw->background = get_pixel_resource ("passwd.background",
-				       "Dialog.Background",
-				       si->dpy, cmap);
+  pw->passwd_font = XLoadQueryFont (si->dpy, THEME_FONT_PASSWD);
+  if (!pw->passwd_font) {
+    f = get_string_resource("passwd.passwdFont", "Dialog.Font");
+    pw->passwd_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
+    if (!pw->passwd_font) pw->passwd_font = XLoadQueryFont (si->dpy, "fixed");
+    if (f) free (f);
+  }
+
+  pw->login_font = XLoadQueryFont (si->dpy, THEME_FONT_LOGIN);
+  if (!pw->login_font) {
+    f = get_string_resource("passwd.loginFont", "Dialog.Font");
+    pw->login_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
+    if (!pw->login_font) pw->login_font = XLoadQueryFont (si->dpy, "fixed");
+    if (f) free (f);
+  }
+
+  pw->date_font = XLoadQueryFont (si->dpy, THEME_FONT_DATE);
+  if (!pw->date_font) {
+    f = get_string_resource("passwd.dateFont", "Dialog.Font");
+    pw->date_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
+    if (!pw->date_font) pw->date_font = XLoadQueryFont (si->dpy, "fixed");
+    if (f) free (f);
+  }
+
+  pw->status_font = XLoadQueryFont (si->dpy, THEME_FONT_STATUS);
+  if (!pw->status_font) {
+    pw->status_font = XLoadQueryFont (si->dpy, ("fixed"));
+  }
+
+  pw->foreground = parse_pixel_resource (THEME_FG, si->dpy, cmap);
+  pw->background = parse_pixel_resource (THEME_BG, si->dpy, cmap);
 
   if (pw->foreground == pw->background)
     {
@@ -273,47 +302,76 @@
       pw->background = WhitePixelOfScreen (screen);
     }
 
-  pw->passwd_foreground = get_pixel_resource ("passwd.text.foreground",
-					      "Dialog.Text.Foreground",
-					      si->dpy, cmap);
-  pw->passwd_background = get_pixel_resource ("passwd.text.background",
-					      "Dialog.Text.Background",
-					      si->dpy, cmap);
-  pw->button_foreground = get_pixel_resource ("splash.Button.foreground",
-                                              "Dialog.Button.Foreground",
-                                              si->dpy, cmap);
-  pw->button_background = get_pixel_resource ("splash.Button.background",
-                                              "Dialog.Button.Background",
-                                              si->dpy, cmap);
-  pw->thermo_foreground = get_pixel_resource ("passwd.thermometer.foreground",
-					      "Dialog.Thermometer.Foreground",
-					      si->dpy, cmap);
-  pw->thermo_background = get_pixel_resource ("passwd.thermometer.background",
-					      "Dialog.Thermometer.Background",
-					      si->dpy, cmap);
-  pw->shadow_top = get_pixel_resource ("passwd.topShadowColor",
-				       "Dialog.Foreground",
-				       si->dpy, cmap);
-  pw->shadow_bottom = get_pixel_resource ("passwd.bottomShadowColor",
-					  "Dialog.Background",
-					  si->dpy, cmap);
-
-  pw->logo_width = get_integer_resource ("passwd.logo.width",
-					 "Dialog.Logo.Width");
-  pw->logo_height = get_integer_resource ("passwd.logo.height",
-					  "Dialog.Logo.Height");
-  pw->thermo_width = get_integer_resource ("passwd.thermometer.width",
-					   "Dialog.Thermometer.Width");
-  pw->internal_border = get_integer_resource ("passwd.internalBorderWidth",
-					      "Dialog.InternalBorderWidth");
-  pw->shadow_width = get_integer_resource ("passwd.shadowThickness",
-					   "Dialog.ShadowThickness");
-
-  if (pw->logo_width == 0)  pw->logo_width = 150;
-  if (pw->logo_height == 0) pw->logo_height = 150;
-  if (pw->internal_border == 0) pw->internal_border = 15;
-  if (pw->shadow_width == 0) pw->shadow_width = 4;
-  if (pw->thermo_width == 0) pw->thermo_width = pw->shadow_width;
+  pw->label_foreground = parse_pixel_resource (THEME_FG_LABEL, si->dpy, cmap);
+  pw->label_background = parse_pixel_resource (THEME_BG_LABEL, si->dpy, cmap);
+
+  pw->passwd_foreground = parse_pixel_resource (THEME_FG_PASSWD, si->dpy, cmap);
+  pw->passwd_background = parse_pixel_resource (THEME_BG_PASSWD, si->dpy, cmap);
+
+  pw->date_foreground = parse_pixel_resource (THEME_FG_DATE, si->dpy, cmap);
+  pw->date_background = parse_pixel_resource (THEME_BG_DATE, si->dpy, cmap);
+
+  pw->login_foreground = parse_pixel_resource (THEME_FG_LOGIN, si->dpy, cmap);
+  pw->login_background = parse_pixel_resource (THEME_BG_LOGIN, si->dpy, cmap);
+
+  pw->thermo_foreground = parse_pixel_resource (THEME_FG_THERMO, si->dpy, cmap);
+  pw->thermo_background = parse_pixel_resource (THEME_BG_THERMO, si->dpy, cmap);
+
+  pw->denied_foreground = parse_pixel_resource (THEME_FG_DENIED, si->dpy, cmap);
+
+  pw->thermo_width = THEME_THERMO_WIDTH;
+  pw->internal_border = THEME_INTERNAL_BORDER;
+  pw->internal_spacer = THEME_INTERNAL_SPACER;
+
+  {
+    int w, h, tmp;
+
+    /* THEME HACK: A macro or array would tidy the following. */
+    if (sscanf(*theme_logo_xpm, "%d %d %d %d", &w, &h, &tmp, &tmp) == 4) {
+      pw->logo.width = (int) w;
+      pw->logo.height = (int) h;
+    }
+
+    if (sscanf(*theme_frame_t_xpm, "%d %d %d %d", &w, &h, &tmp, &tmp) == 4) {
+      pw->frame_t.width = (int) w;
+      pw->frame_t.height = (int) h;
+    }
+    if (sscanf(*theme_frame_b_xpm, "%d %d %d %d", &w, &h, &tmp, &tmp) == 4) {
+      pw->frame_b.width = (int) w;
+      pw->frame_b.height = (int) h;
+    }
+    if (sscanf(*theme_frame_l_xpm, "%d %d %d %d", &w, &h, &tmp, &tmp) == 4) {
+      pw->frame_l.width = (int) w;
+      pw->frame_l.height = (int) h;
+    }
+    if (sscanf(*theme_frame_r_xpm, "%d %d %d %d", &w, &h, &tmp, &tmp) == 4) {
+      pw->frame_r.width = (int) w;
+      pw->frame_r.height = (int) h;
+    }
+    if (sscanf(*theme_frame_tl_xpm, "%d %d %d %d", &w, &h, &tmp, &tmp) == 4) {
+      pw->frame_tl.width = (int) w;
+      pw->frame_tl.height = (int) h;
+    }
+    if (sscanf(*theme_frame_tr_xpm, "%d %d %d %d", &w, &h, &tmp, &tmp) == 4) {
+      pw->frame_tr.width = (int) w;
+      pw->frame_tr.height = (int) h;
+    }
+    if (sscanf(*theme_frame_bl_xpm, "%d %d %d %d", &w, &h, &tmp, &tmp) == 4) {
+      pw->frame_bl.width = (int) w;
+      pw->frame_bl.height = (int) h;
+    }
+    if (sscanf(*theme_frame_br_xpm, "%d %d %d %d", &w, &h, &tmp, &tmp) == 4) {
+      pw->frame_br.width = (int) w;
+      pw->frame_br.height = (int) h;
+    }
+
+    /* THEME HACK: As the pixmaps may not have same dimensions and are aligned
+       along outside edges find the maximums. */
+    pw->frame_max_t = MAX3(pw->frame_t.height, pw->frame_tl.height, pw->frame_tr.height);
+    pw->frame_max_b = MAX3(pw->frame_b.height, pw->frame_bl.height, pw->frame_br.height);
+    pw->frame_max_l = MAX3(pw->frame_l.width, pw->frame_tl.width, pw->frame_bl.width);
+    pw->frame_max_r = MAX3(pw->frame_r.width, pw->frame_tr.width, pw->frame_br.width);
+  }
 
   {
     int direction, ascent, descent;
@@ -322,24 +380,14 @@
     pw->width = 0;
     pw->height = 0;
 
-    /* Measure the heading_label. */
-    XTextExtents (pw->heading_font,
-		  pw->heading_label, strlen(pw->heading_label),
-		  &direction, &ascent, &descent, &overall);
-    if (overall.width > pw->width) pw->width = overall.width;
-    pw->height += ascent + descent;
-
-    /* Measure the body_label. */
-    XTextExtents (pw->body_font,
-		  pw->body_label, strlen(pw->body_label),
-		  &direction, &ascent, &descent, &overall);
-    if (overall.width > pw->width) pw->width = overall.width;
-    pw->height += ascent + descent;
-
-    {
-      Dimension w2 = 0, w3 = 0, button_w = 0;
-      Dimension h2 = 0, h3 = 0, button_h = 0;
-      const char *passwd_string = "MMMMMMMMMMMM";
+    {
+      Dimension w2 = 0, w3 = 0, w4 = 0;
+      Dimension h2 = 0, h3 = 0, h4 = 0;
+      /* THEME HACK: This used to be 12 M's to allow for result strings but on
+         fonts like Neuropol it is just too wide. Result strings now get
+         overwritten by theme so it doesn't matter. */
+      const char *passwd_string = "************";
+      const char *date_string = "88:88";
 
       /* Measure the user_label. */
       XTextExtents (pw->label_font,
@@ -359,8 +407,6 @@
       XTextExtents (pw->passwd_font,
 		    pw->user_string, strlen(pw->user_string),
 		    &direction, &ascent, &descent, &overall);
-      overall.width += (pw->shadow_width * 4);
-      ascent += (pw->shadow_width * 4);
       if (overall.width > w3)  w3 = overall.width;
       h3 += ascent + descent;
 
@@ -368,58 +414,68 @@
       XTextExtents (pw->passwd_font,
 		    passwd_string, strlen(passwd_string),
 		    &direction, &ascent, &descent, &overall);
-      overall.width += (pw->shadow_width * 4);
-      ascent += (pw->shadow_width * 4);
       if (overall.width > w3)  w3 = overall.width;
       h3 += ascent + descent;
 
-      w2 = w2 + w3 + (pw->shadow_width * 2);
-      h2 = MAX (h2, h3);
-
-      pw->login_button_width = 0;
-      pw->login_button_height = 0;
+      /* Measure the date_label. */
+      XTextExtents (pw->date_font,
+		    date_string, strlen(date_string),
+		    &direction, &ascent, &descent, &overall);
+      if (overall.width > w4)  w4 = overall.width;
+      h4 += ascent + descent;
 
+      /* Measure the login_label if enabled. */
       if (pw->login_button_p)
-        {
-          pw->login_button_enabled_p = True;
-
-          /* Measure the "New Login" button */
-          XTextExtents (pw->button_font, pw->login_label,
-                        strlen (pw->login_label),
-                        &direction, &ascent, &descent, &overall);
-          button_w = overall.width;
-          button_h = ascent + descent;
-
-          /* Add some horizontal padding inside the buttons. */
-          button_w += ascent;
-
-          button_w += ((ascent + descent) / 2) + (pw->shadow_width * 2);
-          button_h += ((ascent + descent) / 2) + (pw->shadow_width * 2);
-
-          pw->login_button_width = button_w;
-          pw->login_button_height = button_h;
-
-          w2 = MAX (w2, button_w);
-          h2 += button_h * 1.5;
-        }
+      {
+        XTextExtents (pw->login_font,
+		      pw->login_label, strlen(pw->login_label),
+		      &direction, &ascent, &descent, &overall);
+        w4 += overall.width + 4;
+        if (ascent + descent > h4) h4 = ascent + descent + 4;
+      }
 
-      if (w2 > pw->width)  pw->width  = w2;
-      pw->height += h2;
+      pw->width = MAX (w2 + w3, w4);
+      pw->height = MAX (h2, h3);
+      pw->height += h4;
     }
 
-    pw->width  += (pw->internal_border * 2);
-    pw->height += (pw->internal_border * 4);
+    if (pw->logo.height > pw->height)
+      pw->height = pw->logo.height;
 
-    pw->width += pw->thermo_width + (pw->shadow_width * 3);
+    pw->width += 2 * pw->internal_border + pw->logo.width +
+                 3 * pw->internal_spacer + pw->thermo_width;
+    pw->height+= 2 * pw->internal_border;
 
-    if (pw->logo_height > pw->height)
-      pw->height = pw->logo_height;
-    else if (pw->height > pw->logo_height)
-      pw->logo_height = pw->height;
 
-    pw->logo_width = pw->logo_height;
+    /* THEME HACK: By default, increase size so as to draw complete pixmaps.
+       Can only do for one (opposing) side - top and left. */
+#if defined THEME_TOP_CENTRED || defined THEME_TOP_FIT
+    if (pw->width % pw->frame_t.width)
+      pw->width += pw->frame_t.width - pw->width % pw->frame_t.width;
+#endif
+#if defined THEME_LEFT_CENTRED || defined THEME_LEFT_FIT
+    if (pw->height % pw->frame_l.height)
+      pw->height += pw->frame_l.height - pw->height % pw->frame_l.height;
+#endif
+#ifdef THEME_BOTTOM_FIT
+    if (pw->width % pw->frame_b.width)
+      pw->width += pw->frame_b.width - pw->width % pw->frame_b.width;
+#endif
+#ifdef THEME_RIGHT_FIT
+    if (pw->height % pw->frame_r.height)
+      pw->height += pw->frame_r.height - pw->height % pw->frame_r.height;
+#endif
+#ifdef THEME_BOTTOM_CENTRED
+    if (pw->width % pw->frame_b.width)
+      pw->width += pw->frame_b.width - pw->width % pw->frame_b.width;
+#endif
+#ifdef THEME_RIGHT_CENTRED
+    if (pw->height % pw->frame_r.height)
+      pw->height += pw->frame_r.height - pw->height % pw->frame_r.height;
+#endif
 
-    pw->width += pw->logo_width;
+    pw->width += pw->frame_max_l + pw->frame_max_r;
+    pw->height+= pw->frame_max_t + pw->frame_max_b;
   }
 
   attrmask |= CWOverrideRedirect; attrs.override_redirect = True;
@@ -483,13 +539,63 @@
 
   /* We use the default visual, not ssi->visual, so that the logo pixmap's
      visual matches that of the si->passwd_dialog window. */
-  pw->logo_pixmap = xscreensaver_logo (ssi->screen,
+  pw->logo.pixmap = xscreensaver_xpm (ssi->screen,
                                        /* ssi->current_visual, */
                                        DefaultVisualOfScreen(screen),
                                        si->passwd_dialog, cmap,
                                        pw->background, 
-                                       &pw->logo_pixels, &pw->logo_npixels,
-                                       0, True);
+                                       &pw->logo.pixels, &pw->logo.npixels,
+                                       0, theme_logo_xpm);
+
+  /* THEME HACK: A macro or array would tidy the following. */
+  pw->frame_t.pixmap = xscreensaver_xpm (ssi->screen,
+                                       DefaultVisualOfScreen(screen),
+                                       si->passwd_dialog, cmap,
+                                       pw->background, 
+                                       &pw->frame_t.pixels, &pw->frame_t.npixels,
+                                       0, theme_frame_t_xpm);
+  pw->frame_b.pixmap = xscreensaver_xpm (ssi->screen,
+                                       DefaultVisualOfScreen(screen),
+                                       si->passwd_dialog, cmap,
+                                       pw->background, 
+                                       &pw->frame_b.pixels, &pw->frame_b.npixels,
+                                       0, theme_frame_b_xpm);
+  pw->frame_l.pixmap = xscreensaver_xpm (ssi->screen,
+                                       DefaultVisualOfScreen(screen),
+                                       si->passwd_dialog, cmap,
+                                       pw->background, 
+                                       &pw->frame_l.pixels, &pw->frame_l.npixels,
+                                       0, theme_frame_l_xpm);
+  pw->frame_r.pixmap = xscreensaver_xpm (ssi->screen,
+                                       DefaultVisualOfScreen(screen),
+                                       si->passwd_dialog, cmap,
+                                       pw->background, 
+                                       &pw->frame_r.pixels, &pw->frame_r.npixels,
+                                       0, theme_frame_r_xpm);
+  pw->frame_tl.pixmap = xscreensaver_xpm (ssi->screen,
+                                       DefaultVisualOfScreen(screen),
+                                       si->passwd_dialog, cmap,
+                                       pw->background, 
+                                       &pw->frame_tl.pixels, &pw->frame_tl.npixels,
+                                       0, theme_frame_tl_xpm);
+  pw->frame_tr.pixmap = xscreensaver_xpm (ssi->screen,
+                                       DefaultVisualOfScreen(screen),
+                                       si->passwd_dialog, cmap,
+                                       pw->background, 
+                                       &pw->frame_tr.pixels, &pw->frame_tr.npixels,
+                                       0, theme_frame_tr_xpm);
+  pw->frame_bl.pixmap = xscreensaver_xpm (ssi->screen,
+                                       DefaultVisualOfScreen(screen),
+                                       si->passwd_dialog, cmap,
+                                       pw->background, 
+                                       &pw->frame_bl.pixels, &pw->frame_bl.npixels,
+                                       0, theme_frame_bl_xpm);
+  pw->frame_br.pixmap = xscreensaver_xpm (ssi->screen,
+                                       DefaultVisualOfScreen(screen),
+                                       si->passwd_dialog, cmap,
+                                       pw->background, 
+                                       &pw->frame_br.pixels, &pw->frame_br.npixels,
+                                       0, theme_frame_br_xpm);
 
   /* Before mapping the window, save the bits that are underneath the
      rectangle the window will occlude.  When we lower the window, we
@@ -533,6 +639,27 @@
   XSync (si->dpy, False);
 }
 
+static void
+xpm_passwd_window (saver_info *si, GC gc, Pixmap pixmap, int dx, int dy)
+{
+  passwd_dialog_data *pw = si->pw_data;
+
+  if (pixmap) {
+    Window root;
+    int x, y;
+    unsigned int w, h, bw, d;
+
+    XGetGeometry (si->dpy, pixmap, &root, &x, &y, &w, &h, &bw, &d);
+    XSetForeground (si->dpy, gc, pw->foreground);
+    XSetBackground (si->dpy, gc, pw->background);
+    if (d == 1)
+      XCopyPlane (si->dpy, pixmap, si->passwd_dialog, gc,
+                  0, 0, w, h, dx, dy, 1);
+    else
+      XCopyArea (si->dpy, pixmap, si->passwd_dialog, gc,
+                 0, 0, w, h, dx, dy);
+  }
+}
 
 static void
 draw_passwd_window (saver_info *si)
@@ -542,66 +669,45 @@
   GC gc1, gc2;
   int spacing, height;
   int x1, x2, x3, y1, y2;
-  int sw;
+  int i;
   int tb_height;
 
-  height = (pw->heading_font->ascent + pw->heading_font->descent +
-            pw->body_font->ascent + pw->body_font->descent +
-            (2 * MAX ((pw->label_font->ascent + pw->label_font->descent),
-                      (pw->passwd_font->ascent + pw->passwd_font->descent +
-                       (pw->shadow_width * 4)))) +
-            pw->date_font->ascent + pw->date_font->descent);
-
-  if (pw->login_button_p)
-    height += ((pw->button_font->ascent + pw->button_font->descent) * 2 +
-               2 * pw->shadow_width);
-
-  spacing = (((pw->height
-               - ((pw->login_button_p ? 4 : 2) * pw->shadow_width)
-               - pw->internal_border - height))
-             / 8);
-
+  height = 2 * MAX ((pw->label_font->ascent + pw->label_font->descent),
+		    (pw->passwd_font->ascent + pw->passwd_font->descent)) +
+           pw->date_font->ascent + pw->date_font->descent;
+  /* THEME HACK: The "spacing" is automatic padding to allow for logo size.
+     Frame->Border->Spacer->User->Spacer->Password->Spacer->Date->Border->Frame
+  */
+  spacing = ((pw->height - pw->frame_max_t - 2 * pw->internal_border -
+              pw->frame_max_b - height)) / 3;
   if (spacing < 0) spacing = 0;
 
   gcv.foreground = pw->foreground;
   gc1 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv);
   gc2 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv);
-  x1 = pw->logo_width + pw->thermo_width + (pw->shadow_width * 3);
-  x3 = pw->width - (pw->shadow_width * 2);
-  y1 = (pw->shadow_width * 2) + spacing + spacing;
-
-  /* top heading
-   */
-  XSetFont (si->dpy, gc1, pw->heading_font->fid);
-  sw = string_width (pw->heading_font, pw->heading_label);
-  x2 = (x1 + ((x3 - x1 - sw) / 2));
-  y1 += spacing + pw->heading_font->ascent + pw->heading_font->descent;
-  XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1,
-	       pw->heading_label, strlen(pw->heading_label));
-
-  /* text below top heading
-   */
-  XSetFont (si->dpy, gc1, pw->body_font->fid);
-  y1 += spacing + pw->body_font->ascent + pw->body_font->descent;
-  sw = string_width (pw->body_font, pw->body_label);
-  x2 = (x1 + ((x3 - x1 - sw) / 2));
-  XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1,
-	       pw->body_label, strlen(pw->body_label));
+  /* THEME HACK: Changed from original logo-thermometer-test order to
+     logo-text-thermometer. */
+  x1 = pw->frame_max_l + pw->internal_border + pw->logo.width + pw->internal_spacer;
+  y1 = pw->frame_max_t + pw->internal_border;
+  x3 = pw->width - pw->internal_spacer - pw->internal_border - pw->frame_max_r;
 
-
-  tb_height = (pw->passwd_font->ascent + pw->passwd_font->descent +
-	       (pw->shadow_width * 4));
+  tb_height = pw->passwd_font->ascent + pw->passwd_font->descent;
 
   /* the "User:" prompt
    */
-  y1 += spacing;
+  y1 += spacing + tb_height;
   y2 = y1;
-  XSetForeground (si->dpy, gc1, pw->foreground);
+  x2 = x1 + MAX(string_width (pw->label_font, pw->user_label),
+                string_width (pw->label_font, pw->passwd_label));
+
   XSetFont (si->dpy, gc1, pw->label_font->fid);
-  y1 += (spacing + tb_height);
-  x2 = (x1 + pw->internal_border +
-	MAX(string_width (pw->label_font, pw->user_label),
-	    string_width (pw->label_font, pw->passwd_label)));
+  XSetForeground (si->dpy, gc1, pw->label_background);
+  XFillRectangle (si->dpy, si->passwd_dialog, gc1,
+		  x2 - string_width (pw->label_font, pw->user_label),
+		  y1 - (pw->label_font->ascent + pw->label_font->descent),
+		  string_width (pw->label_font, pw->user_label),
+                  pw->label_font->ascent + pw->label_font->descent);
+  XSetForeground (si->dpy, gc1, pw->label_foreground);
   XDrawString (si->dpy, si->passwd_dialog, gc1,
 	       x2 - string_width (pw->label_font, pw->user_label),
 	       y1 - pw->passwd_font->descent,
@@ -609,7 +715,15 @@
 
   /* the "Password:" prompt
    */
-  y1 += (spacing + tb_height);
+  y1 += spacing + tb_height;
+  XSetForeground (si->dpy, gc1, pw->label_background);
+  XFillRectangle (si->dpy, si->passwd_dialog, gc1,
+		  x2 - string_width (pw->label_font, pw->passwd_label),
+		  y1 - (pw->label_font->ascent + pw->label_font->descent),
+		  string_width (pw->label_font, pw->passwd_label),
+                  pw->label_font->ascent + pw->label_font->descent);
+
+  XSetForeground (si->dpy, gc1, pw->label_foreground);
   XDrawString (si->dpy, si->passwd_dialog, gc1,
 	       x2 - string_width (pw->label_font, pw->passwd_label),
 	       y1 - pw->passwd_font->descent,
@@ -623,16 +737,13 @@
   y1 = y2;
   XSetForeground (si->dpy, gc1, pw->passwd_foreground);
   XSetFont (si->dpy, gc1, pw->passwd_font->fid);
-  y1 += (spacing + tb_height);
-  x2 += (pw->shadow_width * 4);
+  x2 += pw->internal_spacer;
 
   pw->passwd_field_width = x3 - x2 - pw->internal_border;
-  pw->passwd_field_height = (pw->passwd_font->ascent +
-			     pw->passwd_font->descent +
-			     pw->shadow_width);
+  pw->passwd_field_height = pw->passwd_font->ascent + pw->passwd_font->descent;
 
   XFillRectangle (si->dpy, si->passwd_dialog, gc2,
-		  x2 - pw->shadow_width,
+		  x2,
 		  y1 - (pw->passwd_font->ascent + pw->passwd_font->descent),
 		  pw->passwd_field_width, pw->passwd_field_height);
   XDrawString (si->dpy, si->passwd_dialog, gc1,
@@ -642,32 +753,24 @@
 
   /* the "password" text field
    */
-  y1 += (spacing + tb_height);
+  y1 += spacing + tb_height;
 
-  pw->passwd_field_x = x2 - pw->shadow_width;
-  pw->passwd_field_y = y1 - (pw->passwd_font->ascent +
-			     pw->passwd_font->descent);
+  pw->passwd_field_x = x2;
+  pw->passwd_field_y = y1 - pw->passwd_field_height;
 
-  /* The shadow around the text fields
+  /* The "New Login" button
    */
-  y1 = y2;
-  y1 += (spacing + (pw->shadow_width * 3));
-  x1 = x2 - (pw->shadow_width * 2);
-  x2 = pw->passwd_field_width + (pw->shadow_width * 2);
-  y2 = pw->passwd_field_height + (pw->shadow_width * 2);
-
-  draw_shaded_rectangle (si->dpy, si->passwd_dialog,
-			 x1, y1, x2, y2,
-			 pw->shadow_width,
-			 pw->shadow_bottom, pw->shadow_top);
-
-  y1 += (spacing + pw->passwd_font->ascent + pw->passwd_font->descent +
-	 (pw->shadow_width * 4));
-  draw_shaded_rectangle (si->dpy, si->passwd_dialog,
-			 x1, y1, x2, y2,
-			 pw->shadow_width,
-			 pw->shadow_bottom, pw->shadow_top);
+  if (pw->login_button_p)
+    {
+      pw->login_button_width = string_width(pw->login_font, pw->login_label) + 4;
+      pw->login_button_height = pw->login_font->ascent + pw->login_font->descent + 4;
 
+      pw->login_button_x = pw->width - pw->login_button_width -
+                           pw->internal_spacer - pw->thermo_width -
+                           pw->internal_border - pw->frame_max_r;
+      pw->login_button_y = pw->height - pw->internal_border -
+                           pw->frame_max_b - pw->login_button_height;
+    }
 
   /* The date, below the text fields
    */
@@ -679,122 +782,151 @@
     strftime (buf, sizeof(buf)-1, pw->date_label, tm);
 
     XSetFont (si->dpy, gc1, pw->date_font->fid);
-    y1 += pw->shadow_width;
-    y1 += (spacing + tb_height);
-    y1 += spacing/2;
-    sw = string_width (pw->date_font, buf);
-    x2 = x1 + x2 - sw;
-    XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1, buf, strlen(buf));
+    /* THEME HACK: Place date centred between logo and thermometer
+       (or login button if enabled). */
+    x1 += (pw->width - pw->frame_max_l - 2 * pw->internal_border -
+           pw->logo.width - pw->login_button_width - pw->thermo_width -
+           pw->frame_max_r) / 2 -
+          string_width(pw->date_font, buf) / 2;
+    y1 = pw->height - pw->internal_border - pw->frame_max_b;
+
+    XSetForeground (si->dpy, gc1, pw->date_background);
+    XFillRectangle (si->dpy, si->passwd_dialog, gc1,
+		    x1,
+		    y1 - (pw->date_font->ascent + pw->date_font->descent),
+		    string_width (pw->date_font, buf),
+                    pw->date_font->ascent + pw->date_font->descent);
+    XSetForeground (si->dpy, gc1, pw->date_foreground);
+    XDrawString (si->dpy, si->passwd_dialog, gc1,
+                 x1,
+                 y1  - pw->date_font->descent,
+                 buf, strlen(buf));
   }
 
-  /* The "New Login" button
-   */
-  if (pw->login_button_p)
-    {
-      XSetForeground (si->dpy, gc1, pw->button_foreground);
-      XSetForeground (si->dpy, gc2, pw->button_background);
-      XSetFont (si->dpy, gc1, pw->button_font->fid);
-
-      sw = string_width (pw->button_font, pw->login_label);
-
-      x2 = pw->width - pw->internal_border - (pw->shadow_width * 2);
-
-      /* right aligned button */
-      /* x1 = x2 - pw->login_button_width;  */
-
-      /* centered button */
-      x1 = (pw->logo_width + pw->thermo_width + (pw->shadow_width * 3) +
-            pw->internal_border);
-      x1 = x1 + (x2 - x1 - pw->login_button_width) / 2;
-
-      y1 = (pw->height - pw->internal_border - pw->login_button_height +
-            spacing);
-      y2 = (y1 +
-            ((pw->login_button_height -
-              (pw->button_font->ascent + pw->button_font->descent))
-             / 2) +
-            pw->button_font->ascent);
-
-      pw->login_button_x = x1;
-      pw->login_button_y = y1;
-    }
-
   /* The logo
    */
-  x1 = pw->shadow_width * 6;
-  y1 = pw->shadow_width * 6;
-  x2 = pw->logo_width - (pw->shadow_width * 12);
-  y2 = pw->logo_height - (pw->shadow_width * 12);
-
-  if (pw->logo_pixmap)
-    {
-      Window root;
-      int x, y;
-      unsigned int w, h, bw, d;
-      XGetGeometry (si->dpy, pw->logo_pixmap, &root, &x, &y, &w, &h, &bw, &d);
-      XSetForeground (si->dpy, gc1, pw->foreground);
-      XSetBackground (si->dpy, gc1, pw->background);
-      if (d == 1)
-        XCopyPlane (si->dpy, pw->logo_pixmap, si->passwd_dialog, gc1,
-                    0, 0, w, h,
-                    x1 + ((x2 - (int)w) / 2),
-                    y1 + ((y2 - (int)h) / 2),
-                    1);
-      else
-        XCopyArea (si->dpy, pw->logo_pixmap, si->passwd_dialog, gc1,
-                   0, 0, w, h,
-                   x1 + ((x2 - (int)w) / 2),
-                   y1 + ((y2 - (int)h) / 2));
-    }
+  x1 = pw->frame_max_l + pw->internal_border;
+  y1 = pw->frame_max_t + (pw->height - pw->frame_max_t - pw->frame_max_b) / 2 -
+       pw->logo.height / 2;
+  x2 = pw->logo.width;
+  y2 = pw->logo.height;
+
+  if (pw->logo.pixmap) {
+    xpm_passwd_window (si, gc1, pw->logo.pixmap,
+                       x1 + ((x2 - pw->logo.width) / 2),
+                       y1 + ((y2 - pw->logo.height) / 2));
+  }
 
-  /* The thermometer
+  /* The frame
    */
-  XSetForeground (si->dpy, gc1, pw->thermo_foreground);
-  XSetForeground (si->dpy, gc2, pw->thermo_background);
-
-  pw->thermo_field_x = pw->logo_width + pw->shadow_width;
-  pw->thermo_field_y = pw->shadow_width * 5;
-  pw->thermo_field_height = pw->height - (pw->shadow_width * 10);
-
-#if 0
-  /* Solid border inside the logo box. */
-  XSetForeground (si->dpy, gc1, pw->foreground);
-  XDrawRectangle (si->dpy, si->passwd_dialog, gc1, x1, y1, x2-1, y2-1);
+  /* THEME HACK: The side pixmaps are either drawn centred or repeated along
+     outside side of the frame. */
+  if (pw->frame_t.pixmap) {
+#ifdef THEME_TOP_CENTRED
+    xpm_passwd_window (si, gc1, pw->frame_t.pixmap,
+                       pw->frame_max_l +
+                       (pw->width - pw->frame_max_l - pw->frame_max_r) / 2 -
+                       pw->frame_t.width / 2,
+                       0);
+#else
+    for (i = pw->frame_max_l; i < (pw->width - pw->frame_max_r) ; i += pw->frame_t.width) {
+      xpm_passwd_window (si, gc1, pw->frame_t.pixmap, i, 0);
+    }
 #endif
+  }
+  if (pw->frame_b.pixmap) {
+#ifdef THEME_BOTTOM_CENTRED
+    xpm_passwd_window (si, gc1, pw->frame_b.pixmap,
+                       pw->frame_max_l +
+                       (pw->width - pw->frame_max_l - pw->frame_max_r) / 2 -
+                       pw->frame_b.width / 2,
+                       pw->height - pw->frame_b.height);
+#else
+    for (i = pw->frame_max_l; i < (pw->width - pw->frame_max_r) ; i += pw->frame_b.width) {
+      xpm_passwd_window (si, gc1, pw->frame_b.pixmap,
+                             i, pw->height - pw->frame_b.height);
+    }
+#endif
+  }
+  if (pw->frame_l.pixmap) {
+#ifdef THEME_LEFT_CENTRED
+    xpm_passwd_window (si, gc1, pw->frame_l.pixmap,
+                       0,
+                       pw->frame_max_t +
+                       (pw->height - pw->frame_max_t - pw->frame_max_b) / 2 -
+                       pw->frame_l.height / 2 );
+#else
+    for (i = pw->frame_max_t; i < (pw->height - pw->frame_max_b) ; i += pw->frame_l.height) {
+      xpm_passwd_window (si, gc1, pw->frame_l.pixmap, 0, i);
+    }
+#endif
+  }
+  if (pw->frame_r.pixmap) {
+#ifdef THEME_RIGHT_CENTRED
+    xpm_passwd_window (si, gc1, pw->frame_r.pixmap,
+                       pw->width - pw->frame_r.width,
+                       pw->frame_max_t +
+                       (pw->height - pw->frame_max_t - pw->frame_max_b) / 2 -
+                       pw->frame_r.height / 2 );
+#else
+    for (i = pw->frame_max_t; i < (pw->height - pw->frame_max_b) ; i += pw->frame_r.height) {
+      xpm_passwd_window (si, gc1, pw->frame_r.pixmap,
+                         pw->width - pw->frame_r.width, i);
+    }
+#endif
+  }
+  /* THEME HACK: Black out corners. If corner pixmap is smaller than side
+     pixmaps we need to clear side pixmap overwrite. Additionally if background
+     is not black, then undrawn parts would have that colour. */
+  XSetForeground (si->dpy, gc1, BlackPixelOfScreen (pw->prompt_screen->screen));
+  XFillRectangle (si->dpy, si->passwd_dialog, gc1,
+                  0, 0,
+                  pw->frame_max_l, pw->frame_max_t);
+  XFillRectangle (si->dpy, si->passwd_dialog, gc1,
+                  pw->width - pw->frame_max_r, 0,
+                  pw->frame_max_l, pw->frame_max_t);
+  XFillRectangle (si->dpy, si->passwd_dialog, gc1,
+                  0, pw->height - pw->frame_max_b,
+                  pw->frame_max_l, pw->frame_max_t);
+  XFillRectangle (si->dpy, si->passwd_dialog, gc1,
+                  pw->width - pw->frame_max_r, pw->height - pw->frame_max_b,
+                  pw->frame_max_l, pw->frame_max_t);
+  /* THEME HACK: The corner pixmaps are drawn to the inside corner of the
+     frame. */
+  if (pw->frame_tl.pixmap) {
+    xpm_passwd_window (si, gc1, pw->frame_tl.pixmap,
+                       pw->frame_max_l - pw->frame_tl.width,
+                       pw->frame_max_t - pw->frame_tl.height);
+  }
+  if (pw->frame_tr.pixmap) {
+    xpm_passwd_window (si, gc1, pw->frame_tr.pixmap,
+                       pw->width - pw->frame_max_l,
+                       pw->frame_max_t - pw->frame_tl.height);
+  }
+  if (pw->frame_bl.pixmap) {
+    xpm_passwd_window (si, gc1, pw->frame_bl.pixmap,
+                       pw->frame_max_l - pw->frame_bl.width,
+                       pw->height - pw->frame_max_b);
+  }
+  if (pw->frame_br.pixmap) {
+    xpm_passwd_window (si, gc1, pw->frame_br.pixmap,
+                       pw->width - pw->frame_max_r,
+                       pw->height - pw->frame_max_b);
+  }
 
-  /* The shadow around the logo
-   */
-  draw_shaded_rectangle (si->dpy, si->passwd_dialog,
-			 pw->shadow_width * 4,
-			 pw->shadow_width * 4,
-			 pw->logo_width - (pw->shadow_width * 8),
-			 pw->logo_height - (pw->shadow_width * 8),
-			 pw->shadow_width,
-			 pw->shadow_bottom, pw->shadow_top);
-
-  /* The shadow around the thermometer
+  /* the thermometer
    */
-  draw_shaded_rectangle (si->dpy, si->passwd_dialog,
-			 pw->logo_width,
-			 pw->shadow_width * 4,
-			 pw->thermo_width + (pw->shadow_width * 2),
-			 pw->height - (pw->shadow_width * 8),
-			 pw->shadow_width,
-			 pw->shadow_bottom, pw->shadow_top);
+  pw->thermo_field_x = pw->width - pw->thermo_width - pw->internal_border -
+                       pw->frame_max_r;
+  pw->thermo_field_y = pw->frame_max_t + pw->internal_border;
+  pw->thermo_field_height = pw->height - pw->frame_max_t - 2 * pw->internal_border -
+                            pw->frame_max_b;
 
-#if 1
   /* Solid border inside the thermometer. */
-  XSetForeground (si->dpy, gc1, pw->foreground);
+  XSetForeground (si->dpy, gc1, pw->thermo_background);
   XDrawRectangle (si->dpy, si->passwd_dialog, gc1, 
 		  pw->thermo_field_x, pw->thermo_field_y,
                   pw->thermo_width - 1, pw->thermo_field_height - 1);
-#endif
-
-  /* The shadow around the whole window
-   */
-  draw_shaded_rectangle (si->dpy, si->passwd_dialog,
-			 0, 0, pw->width, pw->height, pw->shadow_width,
-			 pw->shadow_top, pw->shadow_bottom);
 
   XFreeGC (si->dpy, gc1);
   XFreeGC (si->dpy, gc2);
@@ -839,7 +971,7 @@
   XSetClipRectangles (si->dpy, gc1, 0, 0, rects, 1, Unsorted);
 
   XDrawString (si->dpy, si->passwd_dialog, gc1,
-               rects[0].x + pw->shadow_width,
+               rects[0].x,
                rects[0].y + pw->passwd_font->ascent,
                pw->passwd_string, strlen(pw->passwd_string));
 
@@ -849,25 +981,24 @@
    */
   if (pw->i_beam != 0)
     {
-      x = (rects[0].x + pw->shadow_width +
-	   string_width (pw->passwd_font, pw->passwd_string));
-      y = rects[0].y + pw->shadow_width;
+      x = rects[0].x + string_width (pw->passwd_font, pw->passwd_string);
+      y = rects[0].y;
 
       if (x > rects[0].x + rects[0].width - 1)
         x = rects[0].x + rects[0].width - 1;
       XDrawLine (si->dpy, si->passwd_dialog, gc1, 
-		 x, y,
-                 x, y + pw->passwd_font->ascent + pw->passwd_font->descent-1);
+		 x, y, x, y + pw->passwd_field_height - 1);
     }
 
   pw->i_beam = (pw->i_beam + 1) % 4;
 
 
-  /* the thermometer
+  /* The thermometer
    */
   y = (pw->thermo_field_height - 2) * (1.0 - pw->ratio);
   if (y > 0)
     {
+      XSetForeground (si->dpy, gc2, pw->background);
       XFillRectangle (si->dpy, si->passwd_dialog, gc2,
 		      pw->thermo_field_x + 1,
 		      pw->thermo_field_y + 1,
@@ -885,41 +1016,81 @@
    */
   if (pw->login_button_p)
     {
-      int x2, y2, sw;
-      XSetFont (si->dpy, gc1, pw->button_font->fid);
       XSetForeground (si->dpy, gc1,
                       (pw->login_button_enabled_p
-                       ? pw->passwd_foreground
-                       : pw->shadow_bottom));
-      XSetForeground (si->dpy, gc2, pw->button_background);
+                       ? pw->login_background
+                       : pw->login_foreground));
 
-      XFillRectangle (si->dpy, si->passwd_dialog, gc2,
+      XDrawRectangle (si->dpy, si->passwd_dialog, gc1,
                       pw->login_button_x, pw->login_button_y,
-		      pw->login_button_width, pw->login_button_height);
+                      pw->login_button_width - 1, pw->login_button_height - 1);
+      XSetFont (si->dpy, gc1, pw->login_font->fid);
+      XDrawString (si->dpy, si->passwd_dialog, gc1,
+                   pw->login_button_x + 1,
+                   pw->login_button_y + pw->login_font->ascent + 2,
+                   pw->login_label, strlen(pw->login_label));
 
-      sw = string_width (pw->button_font, pw->login_label);
-      x2 = pw->login_button_x + ((pw->login_button_width - sw) / 2);
-      y2 = (pw->login_button_y +
-            ((pw->login_button_height -
-              (pw->button_font->ascent + pw->button_font->descent))
-             / 2) +
-            pw->button_font->ascent);
-
-      XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y2,
-	           pw->login_label, strlen(pw->login_label));
-
-      draw_shaded_rectangle (si->dpy, si->passwd_dialog,
-                             pw->login_button_x, pw->login_button_y, 
-                             pw->login_button_width, pw->login_button_height,
-                             pw->shadow_width,
-                             (pw->login_button_down_p
-                              ? pw->shadow_bottom
-                              : pw->shadow_top), 
-                             (pw->login_button_down_p
-                              ? pw->shadow_top
-                              : pw->shadow_bottom));
     }
 
+  /* the status mapping
+   */
+  /* THEME HACK: Text is cheaper than pixmaps even though they'd look
+     nicer being anti-aliased. */
+  if (pw->state) {
+    XSetForeground (si->dpy, gc1, pw->foreground);
+    switch (pw->state)
+      {
+        case pw_check:
+          pw->status_string = strdup("VERIFYING");
+          break;
+        case pw_ok:
+          pw->status_string = strdup("APPROVED");
+          break;
+        case pw_fail:
+          XSetForeground (si->dpy, gc1, pw->denied_foreground);
+          pw->status_string = strdup("DENIED");
+          break;
+        case pw_null:
+        case pw_cancel:
+          pw->status_string = strdup("CANCELLED");
+          break;
+        case pw_time:
+          pw->status_string = strdup("TIMED OUT");
+          break;
+        default:
+          break;
+      }
+    if (pw->status_string) {
+      XSetForeground (si->dpy, gc2, pw->background);
+      XSetFont (si->dpy, gc1, pw->status_font->fid);
+      XFillRectangle (si->dpy, si->passwd_dialog, gc2,
+  		      pw->frame_max_l + pw->internal_border,
+		      pw->frame_max_t + pw->internal_border,
+		      pw->width - pw->frame_max_l - 2 * pw->internal_border -
+                      pw->frame_max_r,
+		      pw->height - pw->frame_max_t - 2 * pw->internal_border -
+                      pw->frame_max_b);
+
+      /* THEME HACK: Clip status message to not overdraw frame. */
+      rects[0].x = pw->frame_max_l;
+      rects[0].y =  pw->frame_max_t;
+      rects[0].width = pw->width - pw->frame_max_l - pw->frame_max_r;
+      rects[0].height = pw->height - pw->frame_max_t - pw->frame_max_b;
+      XSetClipRectangles (si->dpy, gc1, 0, 0, rects, 1, Unsorted);
+
+      x = (pw->width - pw->frame_max_l - pw->frame_max_r) / 2 + pw->frame_max_l -
+          string_width (pw->status_font, pw->status_string) / 2;
+      y = (pw->height - pw->frame_max_t - pw->frame_max_b) / 2 + pw->frame_max_t +
+          (pw->status_font->ascent) / 2;
+      XDrawString (si->dpy, si->passwd_dialog, gc1,
+                      x, y,
+                      pw->status_string, strlen(pw->status_string));
+
+      XSetClipMask (si->dpy, gc1, None);
+      free (pw->status_string);
+    }
+  }
+
   XFreeGC (si->dpy, gc1);
   XFreeGC (si->dpy, gc2);
   XSync (si->dpy, False);
@@ -986,8 +1157,6 @@
       XFreeGC (si->dpy, gc);
     }
 
-  if (pw->heading_label) free (pw->heading_label);
-  if (pw->body_label)    free (pw->body_label);
   if (pw->user_label)    free (pw->user_label);
   if (pw->passwd_label)  free (pw->passwd_label);
   if (pw->date_label)    free (pw->date_label);
@@ -995,43 +1164,132 @@
   if (pw->user_string)   free (pw->user_string);
   if (pw->passwd_string) free (pw->passwd_string);
 
-  if (pw->heading_font) XFreeFont (si->dpy, pw->heading_font);
-  if (pw->body_font)    XFreeFont (si->dpy, pw->body_font);
   if (pw->label_font)   XFreeFont (si->dpy, pw->label_font);
   if (pw->passwd_font)  XFreeFont (si->dpy, pw->passwd_font);
   if (pw->date_font)    XFreeFont (si->dpy, pw->date_font);
-  if (pw->button_font)  XFreeFont (si->dpy, pw->button_font);
+  if (pw->login_font)   XFreeFont (si->dpy, pw->login_font);
+  if (pw->status_font)  XFreeFont (si->dpy, pw->status_font);
 
   if (pw->foreground != black && pw->foreground != white)
     XFreeColors (si->dpy, cmap, &pw->foreground, 1, 0L);
   if (pw->background != black && pw->background != white)
     XFreeColors (si->dpy, cmap, &pw->background, 1, 0L);
-  if (!(pw->button_foreground == black || pw->button_foreground == white))
-    XFreeColors (si->dpy, cmap, &pw->button_foreground, 1, 0L);
-  if (!(pw->button_background == black || pw->button_background == white))
-    XFreeColors (si->dpy, cmap, &pw->button_background, 1, 0L);
+
+  if (pw->label_foreground != black && pw->label_foreground != white)
+    XFreeColors (si->dpy, cmap, &pw->label_foreground, 1, 0L);
+  if (pw->label_background != black && pw->label_background != white)
+    XFreeColors (si->dpy, cmap, &pw->label_background, 1, 0L);
+
   if (pw->passwd_foreground != black && pw->passwd_foreground != white)
     XFreeColors (si->dpy, cmap, &pw->passwd_foreground, 1, 0L);
   if (pw->passwd_background != black && pw->passwd_background != white)
     XFreeColors (si->dpy, cmap, &pw->passwd_background, 1, 0L);
+
+  if (pw->date_foreground != black && pw->date_foreground != white)
+    XFreeColors (si->dpy, cmap, &pw->date_foreground, 1, 0L);
+  if (pw->date_background != black && pw->date_background != white)
+    XFreeColors (si->dpy, cmap, &pw->date_background, 1, 0L);
+
+  if (!(pw->login_foreground == black || pw->login_foreground == white))
+    XFreeColors (si->dpy, cmap, &pw->login_foreground, 1, 0L);
+  if (!(pw->login_background == black || pw->login_background == white))
+    XFreeColors (si->dpy, cmap, &pw->login_background, 1, 0L);
+
   if (pw->thermo_foreground != black && pw->thermo_foreground != white)
     XFreeColors (si->dpy, cmap, &pw->thermo_foreground, 1, 0L);
   if (pw->thermo_background != black && pw->thermo_background != white)
     XFreeColors (si->dpy, cmap, &pw->thermo_background, 1, 0L);
-  if (pw->shadow_top != black && pw->shadow_top != white)
-    XFreeColors (si->dpy, cmap, &pw->shadow_top, 1, 0L);
-  if (pw->shadow_bottom != black && pw->shadow_bottom != white)
-    XFreeColors (si->dpy, cmap, &pw->shadow_bottom, 1, 0L);
-
-  if (pw->logo_pixmap)
-    XFreePixmap (si->dpy, pw->logo_pixmap);
-  if (pw->logo_pixels)
-    {
-      if (pw->logo_npixels)
-        XFreeColors (si->dpy, cmap, pw->logo_pixels, pw->logo_npixels, 0L);
-      free (pw->logo_pixels);
-      pw->logo_pixels = 0;
-      pw->logo_npixels = 0;
+
+  /* THEME HACK: A macro or array would tidy the following. */
+  if (pw->logo.pixmap)
+    XFreePixmap (si->dpy, pw->logo.pixmap);
+  if (pw->logo.pixels)
+    {
+      if (pw->logo.npixels)
+        XFreeColors (si->dpy, cmap, pw->logo.pixels, pw->logo.npixels, 0L);
+      free (pw->logo.pixels);
+      pw->logo.pixels = 0;
+      pw->logo.npixels = 0;
+    }
+  if (pw->frame_t.pixmap)
+    XFreePixmap (si->dpy, pw->frame_t.pixmap);
+  if (pw->frame_t.pixels)
+    {
+      if (pw->frame_t.npixels)
+        XFreeColors (si->dpy, cmap, pw->frame_t.pixels, pw->frame_t.npixels, 0L);
+      free (pw->frame_t.pixels);
+      pw->frame_t.pixels = 0;
+      pw->frame_t.npixels = 0;
+    }
+  if (pw->frame_b.pixmap)
+    XFreePixmap (si->dpy, pw->frame_b.pixmap);
+  if (pw->frame_b.pixels)
+    {
+      if (pw->frame_b.npixels)
+        XFreeColors (si->dpy, cmap, pw->frame_b.pixels, pw->frame_b.npixels, 0L);
+      free (pw->frame_b.pixels);
+      pw->frame_b.pixels = 0;
+      pw->frame_b.npixels = 0;
+    }
+  if (pw->frame_l.pixmap)
+    XFreePixmap (si->dpy, pw->frame_l.pixmap);
+  if (pw->frame_l.pixels)
+    {
+      if (pw->frame_l.npixels)
+        XFreeColors (si->dpy, cmap, pw->frame_l.pixels, pw->frame_l.npixels, 0L);
+      free (pw->frame_l.pixels);
+      pw->frame_l.pixels = 0;
+      pw->frame_l.npixels = 0;
+    }
+  if (pw->frame_r.pixmap)
+    XFreePixmap (si->dpy, pw->frame_r.pixmap);
+  if (pw->frame_r.pixels)
+    {
+      if (pw->frame_r.npixels)
+        XFreeColors (si->dpy, cmap, pw->frame_r.pixels, pw->frame_r.npixels, 0L);
+      free (pw->frame_r.pixels);
+      pw->frame_r.pixels = 0;
+      pw->frame_r.npixels = 0;
+    }
+  if (pw->frame_tl.pixmap)
+    XFreePixmap (si->dpy, pw->frame_tl.pixmap);
+  if (pw->frame_tl.pixels)
+    {
+      if (pw->frame_tl.npixels)
+        XFreeColors (si->dpy, cmap, pw->frame_tl.pixels, pw->frame_tl.npixels, 0L);
+      free (pw->frame_tl.pixels);
+      pw->frame_tl.pixels = 0;
+      pw->frame_tl.npixels = 0;
+    }
+  if (pw->frame_tr.pixmap)
+    XFreePixmap (si->dpy, pw->frame_tr.pixmap);
+  if (pw->frame_tr.pixels)
+    {
+      if (pw->frame_tr.npixels)
+        XFreeColors (si->dpy, cmap, pw->frame_tr.pixels, pw->frame_tr.npixels, 0L);
+      free (pw->frame_tr.pixels);
+      pw->frame_tr.pixels = 0;
+      pw->frame_tr.npixels = 0;
+    }
+  if (pw->frame_bl.pixmap)
+    XFreePixmap (si->dpy, pw->frame_bl.pixmap);
+  if (pw->frame_bl.pixels)
+    {
+      if (pw->frame_bl.npixels)
+        XFreeColors (si->dpy, cmap, pw->frame_bl.pixels, pw->frame_bl.npixels, 0L);
+      free (pw->frame_bl.pixels);
+      pw->frame_bl.pixels = 0;
+      pw->frame_bl.npixels = 0;
+    }
+  if (pw->frame_br.pixmap)
+    XFreePixmap (si->dpy, pw->frame_br.pixmap);
+  if (pw->frame_br.pixels)
+    {
+      if (pw->frame_br.npixels)
+        XFreeColors (si->dpy, cmap, pw->frame_br.pixels, pw->frame_br.npixels, 0L);
+      free (pw->frame_br.pixels);
+      pw->frame_br.pixels = 0;
+      pw->frame_br.npixels = 0;
     }
 
   if (pw->save_under)
@@ -1413,6 +1671,7 @@
 	pw->state = pw_null;
       else
         {
+          pw->state = pw_check;
           update_passwd_window (si, "Checking...", pw->ratio);
           XSync (si->dpy, False);
           if (passwd_valid_p (typed_passwd, p->verbose_p))
@@ -1481,7 +1740,7 @@
 
   switch (si->pw_data->state)
     {
-    case pw_ok:   msg = 0; break;
+    case pw_ok:   msg = "Success!"; break;
     case pw_null: msg = ""; break;
     case pw_time: msg = "Timed out!"; break;
     default:      msg = (caps_p ? "CapsLock?" : "Sorry!"); break;
diff -urP xscreensaver-4.22/driver/theme.h xscreensaver-4.22-lock/driver/theme.h
--- xscreensaver-4.22/driver/theme.h	1970-01-01 01:00:00.000000000 +0100
+++ xscreensaver-4.22-lock/driver/theme.h	2005-06-27 16:45:05.000000000 +0100
@@ -0,0 +1,82 @@
+/* THE XSCREENSAVER LOCK WINDOW THEME HEADER */
+/* Alan Swanson <swanson@ukfsn.org>          */
+/* THEME - Neuropol Green On Black           */
+
+/* General foreground and background colours. */
+
+#define THEME_FG	"#3DC832"
+#define THEME_BG	"#000000"
+
+/* The username and password labels. */
+
+#define THEME_FONT_LABEL	"-*-neuropol-*-r-*-*-*-80-*-*-p-*-iso8859-1"
+#define THEME_FG_LABEL		"#267C1F"
+#define THEME_BG_LABEL		"#000000"
+
+/* The usernane and password field. */
+
+#define THEME_FONT_PASSWD	"-*-neuropol-*-r-*-*-*-120-*-*-p-*-iso8859-1"
+#define THEME_FG_PASSWD		"#3DC832"
+#define THEME_BG_PASSWD		"#000000"
+
+/* The date field. */
+
+#define THEME_FONT_DATE		"-*-neuropol-*-r-*-*-*-150-*-*-p-*-iso8859-1"
+#define THEME_FG_DATE		"#267C1F"
+#define THEME_BG_DATE		"#000000"
+
+/* The countdown thermometer. Note the background is the outline box, not
+   the background. */
+
+#define THEME_FG_THERMO	"#3DC832"
+#define THEME_BG_THERMO	"#267C1F"
+
+/* The width of the countdown thermometer. */
+
+#define THEME_THERMO_WIDTH      15
+
+/* The login button. The foreground is the active state and the background
+ *    is the inactive state. */
+
+#define THEME_FONT_LOGIN        "-*-neuropol-*-r-*-*-*-80-*-*-p-*-iso8859-1"
+#define THEME_FG_LOGIN          "#267C1F"
+#define THEME_BG_LOGIN          "#174A12"
+
+/* The status shown when the password is entered. Note unlike the pasword
+   maxmimum string length check, this font size is not taken into account
+   when defining window size. */
+
+#define THEME_FONT_STATUS       "-*-neuropol-*-r-*-*-*-200-*-*-p-*-iso8859-1"
+#define THEME_FG_DENIED		"#CB1B1B"
+
+/* Spacing between frame and outside edge of logo, test and thermometer.
+   Remember to take account of background colours in frames and that
+   pixmaps are aligned on outside edge.
+   
+   For example, if the corner pixmap is 15x15 with inner 3x3 of background
+   colour (allowing for corner effects) and the edge pixmaps are 12x20 and
+   20x12 then instead of a border of 15 select 12. */
+   
+#define THEME_INTERNAL_BORDER	15
+
+/* Spacing between logo to label, label to password and password to
+   thermometer. */
+   
+#define THEME_INTERNAL_SPACER	8
+
+/* Define these if the repeating pixmaps need to be drawn complete,
+   i.e. not cut-off on last image. Only define only one opposing side as
+   top and bottom widths and right and left heights will usually be same
+   size. */
+   
+#define THEME_TOP_FIT
+#define THEME_LEFT_FIT
+/* #define THEME_BOTTOM_FIT */
+/* #define THEME_RIGHT_FIT */
+
+/* Define these if the side pixmaps are to be centred once and not repeated. */
+
+/* #define THEME_TOP_CENTRED */
+/* #define THEME_BOTTOM_CENTRED */
+/* #define THEME_LEFT_CENTRED */
+/* #define THEME_RIGHT_CENTRED */
diff -urP xscreensaver-4.22/driver/theme_frame_b.xpm xscreensaver-4.22-lock/driver/theme_frame_b.xpm
--- xscreensaver-4.22/driver/theme_frame_b.xpm	1970-01-01 01:00:00.000000000 +0100
+++ xscreensaver-4.22-lock/driver/theme_frame_b.xpm	2005-06-27 16:42:20.000000000 +0100
@@ -0,0 +1,56 @@
+/* XPM */
+static const char * const theme_frame_b_xpm[] = {
+"20 10 43 1",
+" 	c #938787",
+".	c #968A8A",
+"+	c #988C8C",
+"@	c #9B8F90",
+"#	c #938082",
+"$	c #958284",
+"%	c #988587",
+"&	c #A19495",
+"*	c #928686",
+"=	c #948888",
+"-	c #8F8383",
+";	c #908485",
+">	c #776C6C",
+",	c #827072",
+"'	c #736869",
+")	c #756A6B",
+"!	c #786D6D",
+"~	c #7B7070",
+"{	c #796E6E",
+"]	c #807575",
+"^	c #887678",
+"/	c #817676",
+"(	c #827777",
+"_	c #847979",
+":	c #706465",
+"<	c #6E5D5F",
+"[	c #6F6364",
+"}	c #716566",
+"|	c #74696A",
+"1	c #6E6263",
+"2	c #7A6F6F",
+"3	c #7C7171",
+"4	c #7E7373",
+"5	c #7D7272",
+"6	c #5C5152",
+"7	c #5E5354",
+"8	c #574C4C",
+"9	c #615657",
+"0	c #5F5555",
+"a	c #433E3D",
+"b	c #403C3B",
+"c	c #3C3837",
+"d	c #463C3C",
+"   .++........++@+++",
+"###$%$%%%%%%%@%%+%&%",
+"*=*-*=***---$; $*#; ",
+">,>>>')>!~~~!!!{>!!~",
+"]]^/^(/_^^^]]]](](^(",
+":<[<[,<<'}}[|<[}[[1}",
+"!>2>|){>>>>,>{,|!>>>",
+">>{{334~4],53~3~,>,!",
+"66777676686679900666",
+"aaabbcbaaaabcbdbdaaa"};
diff -urP xscreensaver-4.22/driver/theme_frame_bl.xpm xscreensaver-4.22-lock/driver/theme_frame_bl.xpm
--- xscreensaver-4.22/driver/theme_frame_bl.xpm	1970-01-01 01:00:00.000000000 +0100
+++ xscreensaver-4.22-lock/driver/theme_frame_bl.xpm	2005-06-27 16:42:20.000000000 +0100
@@ -0,0 +1,67 @@
+/* XPM */
+static const char * const theme_frame_bl_xpm[] = {
+"13 13 51 1",
+" 	c #887678",
+".	c #847979",
+"+	c #8E7B7D",
+"@	c #7B7070",
+"#	c #786D6D",
+"$	c #776C6C",
+"%	c #6B6060",
+"&	c #564B4B",
+"*	c #000100",
+"=	c #827072",
+"-	c #7D7272",
+";	c #807575",
+">	c #756A6B",
+",	c #726768",
+"'	c #716566",
+")	c #6E5D5F",
+"!	c #675C5C",
+"~	c #514747",
+"{	c #796E6E",
+"]	c #736869",
+"^	c #706465",
+"/	c #4D4948",
+"(	c #837878",
+"_	c #594F4F",
+":	c #504C4A",
+"<	c #897E7E",
+"[	c #7E7373",
+"}	c #6D6162",
+"|	c #6F6364",
+"1	c #635859",
+"2	c #625758",
+"3	c #938082",
+"4	c #857A7A",
+"5	c #887C7D",
+"6	c #8A787A",
+"7	c #908485",
+"8	c #948888",
+"9	c #827777",
+"0	c #7A6F6F",
+"a	c #7C7171",
+"b	c #817676",
+"c	c #6E6263",
+"d	c #8D8181",
+"e	c #74696A",
+"f	c #5F5555",
+"g	c #615657",
+"h	c #5E5354",
+"i	c #5C5152",
+"j	c #454140",
+"k	c #433E3D",
+"l	c #463C3C",
+" .+ @##$%&***",
+"=-;#>,')!~***",
+"{===']'^!/***",
+"(.. =#@$%_:%<",
+"[==$^}|%12)[3",
+"45<;{$=',{678",
+"=-=@)^']'>@;=",
+" 9+(-0@@a=;(b",
+"#=a#)c)%)})}}",
+"dd3.a[={#0$##",
+"= .a,''ee>'e$",
+";6='!f2gh1ghi",
+"[#!~jkjjkllkk"};
diff -urP xscreensaver-4.22/driver/theme_frame_br.xpm xscreensaver-4.22-lock/driver/theme_frame_br.xpm
--- xscreensaver-4.22/driver/theme_frame_br.xpm	1970-01-01 01:00:00.000000000 +0100
+++ xscreensaver-4.22-lock/driver/theme_frame_br.xpm	2005-06-27 16:42:20.000000000 +0100
@@ -0,0 +1,78 @@
+/* XPM */
+static const char * const theme_frame_br_xpm[] = {
+"13 13 62 1",
+" 	c #000100",
+".	c #8D8181",
+"+	c #8E8282",
+"@	c #958284",
+"#	c #897E7E",
+"$	c #847979",
+"%	c #807575",
+"&	c #7E7373",
+"*	c #7B7070",
+"=	c #716566",
+"-	c #5B5151",
+";	c #675C5C",
+">	c #685D5D",
+",	c #6E5D5F",
+"'	c #625758",
+")	c #594F4F",
+"!	c #574C4C",
+"~	c #584E4E",
+"{	c #4A4544",
+"]	c #3C3837",
+"^	c #A19495",
+"/	c #9E9292",
+"(	c #9D9191",
+"_	c #948888",
+":	c #938082",
+"<	c #8B7F80",
+"[	c #5F5555",
+"}	c #928686",
+"|	c #988587",
+"1	c #8E7B7D",
+"2	c #7D7272",
+"3	c #756A6B",
+"4	c #736869",
+"5	c #74696A",
+"6	c #635859",
+"7	c #514747",
+"8	c #857A7A",
+"9	c #726768",
+"0	c #6E6263",
+"a	c #827777",
+"b	c #776C6C",
+"c	c #827072",
+"d	c #534849",
+"e	c #786D6D",
+"f	c #7A6F6F",
+"g	c #433E3D",
+"h	c #867B7B",
+"i	c #887C7D",
+"j	c #817676",
+"k	c #7C7171",
+"l	c #5C5152",
+"m	c #796E6E",
+"n	c #6B6060",
+"o	c #4E4A49",
+"p	c #5E5354",
+"q	c #615657",
+"r	c #4C4242",
+"s	c #484442",
+"t	c #474341",
+"u	c #4A4041",
+"v	c #454140",
+"w	c #403C3B",
+"   .+@#$%&*=-",
+"   ;>,')!~!{]",
+"   ^/(_@:<#*[",
+"}@|^@12345=67",
+":++||8*3=90'{",
+"|||}@:abc34>d",
+"bbeffb4,;,6-g",
+"h8$hii8%jak=l",
+"fbcc3bmem3cno",
+"=b53c3mecb=nd",
+"39999439=9=>o",
+"lpl[q6q[q[')r",
+"s{{tututtvtuw"};
diff -urP xscreensaver-4.22/driver/theme_frame_l.xpm xscreensaver-4.22-lock/driver/theme_frame_l.xpm
--- xscreensaver-4.22/driver/theme_frame_l.xpm	1970-01-01 01:00:00.000000000 +0100
+++ xscreensaver-4.22-lock/driver/theme_frame_l.xpm	2005-06-27 16:42:20.000000000 +0100
@@ -0,0 +1,76 @@
+/* XPM */
+static const char * const theme_frame_l_xpm[] = {
+"10 20 53 1",
+" 	c #7D7272",
+".	c #827072",
+"+	c #857A7A",
+"@	c #776C6C",
+"#	c #716566",
+"$	c #6E5D5F",
+"%	c #6F6364",
+"&	c #5F5555",
+"*	c #474341",
+"=	c #7B7070",
+"-	c #817676",
+";	c #74696A",
+">	c #675C5C",
+",	c #4F4445",
+"'	c #907E80",
+")	c #8E7B7D",
+"!	c #8D8181",
+"~	c #887C7D",
+"{	c #7A6F6F",
+"]	c #756A6B",
+"^	c #514747",
+"/	c #7E7373",
+"(	c #6B6060",
+"_	c #6E6263",
+":	c #837878",
+"<	c #8B7F80",
+"[	c #807575",
+"}	c #786D6D",
+"|	c #584E4E",
+"1	c #736869",
+"2	c #726768",
+"3	c #685D5D",
+"4	c #5C5152",
+"5	c #433E3D",
+"6	c #897E7E",
+"7	c #564B4B",
+"8	c #887678",
+"9	c #635859",
+"0	c #7F7474",
+"a	c #847979",
+"b	c #706465",
+"c	c #615657",
+"d	c #938082",
+"e	c #7C7171",
+"f	c #504C4A",
+"g	c #574C4C",
+"h	c #6D6162",
+"i	c #484442",
+"j	c #3C3837",
+"k	c #827777",
+"l	c #867B7B",
+"m	c #796E6E",
+"n	c #4D4948",
+" .+ @#$%&*",
+"=- .$.;%>,",
+"')!~{@]#>^",
+"/-.@#(%_&*",
+". .@$%((&*",
+":)<)[=}]_|",
+"12]#((3345",
+"6)6+=}@2(7",
+"-88..###9,",
+". 0@;#$(&*",
+"..a @;#bc,",
+"a6d+8/e}#f",
+"8+)[/./}bg",
+"=.e@$_%h&i",
+"h$#_>994gj",
+"!!dk ==@(7",
+"8~)8=@}@>^",
+"lll-/{=m_g",
+"8)d8=.@@(g",
+":k~-.;.](n"};
diff -urP xscreensaver-4.22/driver/theme_frame_r.xpm xscreensaver-4.22-lock/driver/theme_frame_r.xpm
--- xscreensaver-4.22/driver/theme_frame_r.xpm	1970-01-01 01:00:00.000000000 +0100
+++ xscreensaver-4.22-lock/driver/theme_frame_r.xpm	2005-06-27 16:42:20.000000000 +0100
@@ -0,0 +1,80 @@
+/* XPM */
+static const char * const theme_frame_r_xpm[] = {
+"10 20 57 1",
+" 	c #8E7B7D",
+".	c #867B7B",
+"+	c #907E80",
+"@	c #8A787A",
+"#	c #7A6F6F",
+"$	c #796E6E",
+"%	c #7C7171",
+"&	c #776C6C",
+"*	c #6B6060",
+"=	c #564B4B",
+"-	c #827072",
+";	c #7E7373",
+">	c #6F6364",
+",	c #716566",
+"'	c #615657",
+")	c #474341",
+"!	c #887C7D",
+"~	c #8D8181",
+"{	c #938082",
+"]	c #897E7E",
+"^	c #847979",
+"/	c #807575",
+"(	c #827777",
+"_	c #817676",
+":	c #74696A",
+"<	c #5F5555",
+"[	c #837878",
+"}	c #756A6B",
+"|	c #6E5D5F",
+"1	c #706465",
+"2	c #887678",
+"3	c #6E6263",
+"4	c #665A5B",
+"5	c #514747",
+"6	c #8F8383",
+"7	c #958284",
+"8	c #7B7070",
+"9	c #574C4C",
+"0	c #7D7272",
+"a	c #736869",
+"b	c #4D4948",
+"c	c #7F7474",
+"d	c #4F4445",
+"e	c #685D5D",
+"f	c #726768",
+"g	c #4E4A49",
+"h	c #8E8282",
+"i	c #594F4F",
+"j	c #675C5C",
+"k	c #5B5151",
+"l	c #433E3D",
+"m	c #504C4A",
+"n	c #635859",
+"o	c #786D6D",
+"p	c #4A4041",
+"q	c #5C5152",
+"r	c #6D6162",
+" .+@#$%&*=",
+"-$;->,,>')",
+"!~{]^/(_:<",
+"-[_$},|1<)",
+"/_2&-,:345",
+"{67!/88&*9",
+"0-(%}aa|4b",
+"c-(--3,3<d",
+"_(2$}&}aeb",
+";((%-,f3<d",
+"222;$:-a*g",
+"hh{._#-#>i",
+"}-#,|je|kl",
+"^@{.##&&*9",
+"2^^/#&&f*m",
+"----|1|>n)",
+":&o,3e*nkp",
+"  h._/c%fq",
+"o0-:**|ekl",
+"_/@--a-,r9"};
diff -urP xscreensaver-4.22/driver/theme_frame_t.xpm xscreensaver-4.22-lock/driver/theme_frame_t.xpm
--- xscreensaver-4.22/driver/theme_frame_t.xpm	1970-01-01 01:00:00.000000000 +0100
+++ xscreensaver-4.22-lock/driver/theme_frame_t.xpm	2005-06-27 16:42:20.000000000 +0100
@@ -0,0 +1,64 @@
+/* XPM */
+static const char * const theme_frame_t_xpm[] = {
+"20 10 51 1",
+" 	c #857A7A",
+".	c #837878",
+"+	c #897E7E",
+"@	c #8D8181",
+"#	c #8E8282",
+"$	c #958284",
+"%	c #938787",
+"&	c #968A8A",
+"*	c #988C8C",
+"=	c #A19495",
+"-	c #988587",
+";	c #9B8F90",
+">	c #998D8D",
+",	c #9D9191",
+"'	c #9E9292",
+")	c #887C7D",
+"!	c #8E7B7D",
+"~	c #8F8383",
+"{	c #907E80",
+"]	c #938082",
+"^	c #807575",
+"/	c #7D7272",
+"(	c #7B7070",
+"_	c #7A6F6F",
+":	c #827072",
+"<	c #74696A",
+"[	c #776C6C",
+"}	c #756A6B",
+"|	c #736869",
+"1	c #716566",
+"2	c #6F6364",
+"3	c #6E6263",
+"4	c #6B6060",
+"5	c #6E5D5F",
+"6	c #6D6162",
+"7	c #726768",
+"8	c #796E6E",
+"9	c #7F7474",
+"0	c #7E7373",
+"a	c #817676",
+"b	c #786D6D",
+"c	c #706465",
+"d	c #584E4E",
+"e	c #594F4F",
+"f	c #5B5151",
+"g	c #564B4B",
+"h	c #504C4A",
+"i	c #574C4C",
+"j	c #433E3D",
+"k	c #4A4041",
+"l	c #463C3C",
+" .  +@@#####$$%&&**&",
+"=====-;;;=;-;>--$---",
+"----;,----'>>;>,,>>;",
+". .)!!+#~~!!{@]@~]-~",
+"^^/(_::<[<[}<|112342",
+"55564435562157}|<<:[",
+"8((900^a90(_8::8b<1[",
+"<<}1<<<7<<<<<c7<[7:7",
+"defeeededgdehfdddhih",
+"jklllljljljlljjjjkjk"};
diff -urP xscreensaver-4.22/driver/theme_frame_tl.xpm xscreensaver-4.22-lock/driver/theme_frame_tl.xpm
--- xscreensaver-4.22/driver/theme_frame_tl.xpm	1970-01-01 01:00:00.000000000 +0100
+++ xscreensaver-4.22-lock/driver/theme_frame_tl.xpm	2005-06-27 16:42:20.000000000 +0100
@@ -0,0 +1,67 @@
+/* XPM */
+static const char * const theme_frame_tl_xpm[] = {
+"13 13 51 1",
+" 	c #958284",
+".	c #988587",
+"+	c #8E7B7D",
+"@	c #857A7A",
+"#	c #837878",
+"$	c #A59899",
+"%	c #AEA1A2",
+"&	c #A19495",
+"*	c #928686",
+"=	c #968A8A",
+"-	c #9B8F90",
+";	c #9E9292",
+">	c #827072",
+",	c #867B7B",
+"'	c #8A787A",
+")	c #897E7E",
+"!	c #847979",
+"~	c #8D8181",
+"{	c #887678",
+"]	c #807575",
+"^	c #817676",
+"/	c #827777",
+"(	c #74696A",
+"_	c #6D6162",
+":	c #685D5D",
+"<	c #6B6060",
+"[	c #6E5D5F",
+"}	c #7F7474",
+"|	c #7D7272",
+"1	c #7A6F6F",
+"2	c #776C6C",
+"3	c #796E6E",
+"4	c #786D6D",
+"5	c #7E7373",
+"6	c #7C7171",
+"7	c #726768",
+"8	c #635859",
+"9	c #675C5C",
+"0	c #615657",
+"a	c #5C5152",
+"b	c #574C4C",
+"c	c #564B4B",
+"d	c #887C7D",
+"e	c #7B7070",
+"f	c #504C4A",
+"g	c #4A4544",
+"h	c #463C3C",
+"i	c #454140",
+"j	c #756A6B",
+"k	c #000100",
+"l	c #716566",
+" .+@@###@###@",
+"$%%$$$$&&&&&&",
+"*=&-...;.....",
+">>++@,,',)@!@",
+"~~~+{{]]^///]",
+">>>(_:<[[[:[[",
+"}^#|12223>344",
+"'++@^>5647(22",
+"21>[<890abccc",
+"#'dd1e12_fghi",
+")+~@5>j4_ckkk",
+"#!{>>72l8gkkk",
+"^^!]4>j3lbkkk"};
diff -urP xscreensaver-4.22/driver/theme_frame_tr.xpm xscreensaver-4.22-lock/driver/theme_frame_tr.xpm
--- xscreensaver-4.22/driver/theme_frame_tr.xpm	1970-01-01 01:00:00.000000000 +0100
+++ xscreensaver-4.22-lock/driver/theme_frame_tr.xpm	2005-06-27 16:42:20.000000000 +0100
@@ -0,0 +1,72 @@
+/* XPM */
+static const char * const theme_frame_tr_xpm[] = {
+"13 13 56 1",
+" 	c #928686",
+".	c #958284",
+"+	c #908485",
+"@	c #8E8282",
+"#	c #8D8181",
+"$	c #8B7F80",
+"%	c #8E7B7D",
+"&	c #897E7E",
+"*	c #988587",
+"=	c #978B8B",
+"-	c #9B8F90",
+";	c #9D9191",
+">	c #968A8A",
+",	c #988C8C",
+"'	c #776C6C",
+")	c #827072",
+"!	c #7E7373",
+"~	c #7F7474",
+"{	c #817676",
+"]	c #887678",
+"^	c #7D7272",
+"/	c #706465",
+"(	c #574C4C",
+"_	c #716566",
+":	c #726768",
+"<	c #736869",
+"[	c #74696A",
+"}	c #685D5D",
+"|	c #534849",
+"1	c #756A6B",
+"2	c #4D4948",
+"3	c #6E5D5F",
+"4	c #6E6263",
+"5	c #6B6060",
+"6	c #5F5555",
+"7	c #474341",
+"8	c #7A6F6F",
+"9	c #7B7070",
+"0	c #796E6E",
+"a	c #635859",
+"b	c #625758",
+"c	c #3C3837",
+"d	c #564B4B",
+"e	c #675C5C",
+"f	c #615657",
+"g	c #403C3B",
+"h	c #000100",
+"i	c #433E3D",
+"j	c #6F6364",
+"k	c #887C7D",
+"l	c #857A7A",
+"m	c #827777",
+"n	c #786D6D",
+"o	c #5E5354",
+"p	c #837878",
+"q	c #514747",
+" .+ +@#$#$#%&",
+"*=*****-*;*-.",
+"=>,,=>*>*= #'",
+")!~!)){]{{^/(",
+"_)_::</<[_:}|",
+"):)'')1)_)[}2",
+"___3_443_3567",
+"89908^!~!9)5|",
+"ababa5_[<<:5|",
+"ccccdb5}eefdg",
+"hhhijk%k{lm'f",
+"hhh7}nn_/35o7",
+"hhh1{p{'n1_}q"};
diff -urP xscreensaver-4.22/driver/theme_logo.xpm xscreensaver-4.22-lock/driver/theme_logo.xpm
--- xscreensaver-4.22/driver/theme_logo.xpm	1970-01-01 01:00:00.000000000 +0100
+++ xscreensaver-4.22-lock/driver/theme_logo.xpm	2005-06-27 16:42:20.000000000 +0100
@@ -0,0 +1,187 @@
+/* XPM */
+static const char * const theme_logo_xpm[] = {
+"15 116 68 1",
+" 	c None",
+".	c #000200",
+"+	c #144C14",
+"@	c #227C19",
+"#	c #1E8421",
+"$	c #2A8220",
+"%	c #267F1D",
+"&	c #20641B",
+"*	c #040703",
+"=	c #3EC633",
+"-	c #36C92B",
+";	c #2B8B1F",
+">	c #12350D",
+",	c #3BB028",
+"'	c #194710",
+")	c #124313",
+"!	c #1A4F10",
+"~	c #30C834",
+"{	c #0B310F",
+"]	c #1B7A20",
+"^	c #000100",
+"/	c #165515",
+"(	c #27781F",
+"_	c #33A223",
+":	c #051C0A",
+"<	c #0C1F07",
+"[	c #2AA626",
+"}	c #3BC431",
+"|	c #3EBB28",
+"1	c #020501",
+"2	c #228724",
+"3	c #102C0A",
+"4	c #09280C",
+"5	c #000C05",
+"6	c #2EA02A",
+"7	c #289427",
+"8	c #091003",
+"9	c #38B930",
+"0	c #2E8E22",
+"a	c #051407",
+"b	c #2C941F",
+"c	c #185616",
+"d	c #37C02D",
+"e	c #153D0E",
+"f	c #070F02",
+"g	c #27801E",
+"h	c #279B25",
+"i	c #2F9721",
+"j	c #37B82F",
+"k	c #1B6018",
+"l	c #0A1A08",
+"m	c #10320A",
+"n	c #206B1A",
+"o	c #1F7218",
+"p	c #1D6918",
+"q	c #092E0C",
+"r	c #0D2306",
+"s	c #249124",
+"t	c #32AC2C",
+"u	c #35BF2C",
+"v	c #25771D",
+"w	c #0C380F",
+"x	c #215B14",
+"y	c #1A6716",
+"z	c #32B52B",
+"A	c #27881C",
+"B	c #08270A",
+"C	c #0C1602",
+"..+@######$%&*.",
+".$========-=-;.",
+">-=,''''')!,~-{",
+"]=-'.^^^^^^/==(",
+"_=~:^....^^<==[",
+"}==*^...^^^*=-|",
+"~=-^.....^.1=~=",
+"===......^.^==-",
+"-==1.....^.1==-",
+"==-^......^^===",
+"==-^.....^.1-=-",
+"-==^.....^^^===",
+"-=-^....^..^-=-",
+"===^.....^^*===",
+"-=-^......^^-=-",
+"===^.....^^*===",
+"-=-^.....^^^-=-",
+"===#######22===",
+"}===========-=}",
+"3'''''''''''))4",
+"^^^^^^^5^^^^^^.",
+"^^....6=7^^._=7",
+"......==~^^^-=-",
+".....^-==^..===",
+"....^^-=-^^^==-",
+"....^*===.^*=-=",
+"...^^^-=-^^.==-",
+"....^*===^1^=-=",
+";|2.^^-=-^.^==-",
+"=~=..*===^^*=-=",
+"=-=.^^-=-^^^==-",
+"==-.^*===^^^=-=",
+"===*^^-=~^^^===",
+",=-8^*===^^*=-9",
+"0=~4^^-=-^^a==b",
+"&==!^*===^^+=-c",
+"8|~9$$-=~$$9=d8",
+"^>|=~-===~-=de^",
+"^^8e)'''')'ef^.",
+"^^*^^^^^^^^^^^^",
+")e^*^^1^..^^4_g",
+"}-{^^^^^^^^.h=}",
+"=-i^^.^^^^.>~=j",
+"==={^.^..^.h=-k",
+"(~=i^.....{==|5",
+"l==~m....^i==&^",
+"^(=~i^...3-==8.",
+".l===m..^7=-n^.",
+".^(~=i^^3==98..",
+"..l==~{^i==o^^.",
+"^^^(=-74-==a^..",
+"...l===,=-(.^..",
+"..^^(-====l....",
+"....l====(^....",
+"..^^^(-==:.....",
+"n###2i=-|$$###p",
+"}===~==~-~====}",
+"3'')'')')'''''q",
+"3c3^^^^^^^^^<!r",
+"}=}^^*^.^^..d=9",
+"==~^^^^^..^^=--",
+"=-=^.^^^...^-==",
+"==-^......^^~=-",
+"=-=^......^*===",
+"==~^.....^^^-=-",
+"=-=.......^*===",
+"===......^^^-=-",
+"==-^.......*===",
+"-=~^......^^-=-",
+"===.......^*===",
+"==-^.....^^^-==",
+"9-=*......^8==9",
+"7=-r.....^^3-=s",
+"c==&.....^^$=='",
+"*t-=uuuu99d==t.",
+"^l7-=}}=--~=_l^",
+"^^^*885**88*^^.",
+"^*'@$$$22$$vw..",
+"^2=~~===~~==-k.",
+"e==9!'''''!9=}:",
+"g-=x^..^^^^c==y",
+"6==4^^^..^1r-=7",
+"9==5^....^^*-=z",
+"==-1^.....^*==d",
+"-==^....^^^^==~",
+"==-^....^^.^-==",
+"==~^....^^.^-=-",
+"===.......^*===",
+"-==1.....^^^-=-",
+"==-^......^*===",
+"|=~*.....^^*-=d",
+"t==a......^a==_",
+";=->.....^^{==$",
+"+-=v.....^^(=~)",
+"*9~=;####A;==,*",
+"*3|~-======-|4.",
+".^*>'''')')>8^.",
+"^^^^^^^^^^^.*B5",
+"^.^^..^.^.^.,=j",
+".^^....^^^.^=-=",
+".......^^.^^==-",
+"...........^=-=",
+"..........^^==-",
+"..........^*=-=",
+".........^^^==-",
+"...........*=-=",
+"..........^^==-",
+"..........^^=-=",
+".........^^^===",
+".........^^*=-d",
+"........^^^5==j",
+".........^^r=-0",
+"........^^*&=-&",
+"n########2$-=dC",
+"}========-=-9).",
+"3''''''''))e8.^"};
diff -urP xscreensaver-4.22/utils/logo.c xscreensaver-4.22-lock/utils/logo.c
--- xscreensaver-4.22/utils/logo.c	2003-07-23 03:25:00.000000000 +0100
+++ xscreensaver-4.22-lock/utils/logo.c	2005-06-27 16:47:31.000000000 +0100
@@ -27,6 +27,11 @@
    you didn't write; please don't alter its logo either.
  */
 
+/* THEME HACK: Reasonable enough, but the lock window is bloody ugly and
+   I cannot stand to look at it anymore. Replacing the lock window does not
+   prevent people knowing that it is xscreensaver running.
+ */
+
 #include "utils.h"
 #include "resources.h"
 #include "visual.h"
@@ -242,3 +247,50 @@
     }
   return p;
 }
+
+
+
+/* Returns a pixmap of the XPM data passed.
+ */
+Pixmap
+xscreensaver_xpm  (Screen *screen, Visual *visual,
+                   Drawable drawable, Colormap cmap,
+                   unsigned long background_color,
+                   unsigned long **pixels_ret, int *npixels_ret,
+                   Pixmap *mask_ret,
+                   const char * const *xpm_data)
+{
+  Display *dpy = DisplayOfScreen (screen);
+  int depth = visual_depth (screen, visual);
+  int iw, ih;
+  XImage *image;
+  Pixmap p = 0;
+  unsigned char *mask = 0;
+
+  image = parse_xpm_data (dpy, visual, cmap, depth, background_color,
+                          xpm_data,
+                          &iw, &ih, pixels_ret, npixels_ret,
+                          (mask_ret ? &mask : 0));
+
+  if (image)
+    {
+      XGCValues gcv;
+      GC gc;
+      p = XCreatePixmap (dpy, drawable, iw, ih, depth);
+      gc = XCreateGC (dpy, p, 0, &gcv);
+      XPutImage (dpy, p, gc, image, 0, 0, 0, 0, iw, ih);
+      free (image->data);
+      image->data = 0;
+      XDestroyImage (image);
+      XFreeGC (dpy, gc);
+
+      if (mask_ret && mask)
+        {
+          *mask_ret = (Pixmap)
+            XCreatePixmapFromBitmapData (dpy, drawable, (char *) mask,
+                                         iw, ih, 1L, 0L, 1);
+          free (mask);
+        }
+    }
+  return p;
+}
diff -urP xscreensaver-4.22/utils/resources.c xscreensaver-4.22-lock/utils/resources.c
--- xscreensaver-4.22/utils/resources.c	2003-07-23 03:25:00.000000000 +0100
+++ xscreensaver-4.22-lock/utils/resources.c	2005-06-27 16:47:31.000000000 +0100
@@ -129,6 +129,52 @@
   return 0.0;
 }
 
+unsigned int
+parse_pixel_resource (char *s, Display *dpy, Colormap cmap)
+{
+  XColor color;
+  char *s2;
+  Bool ok = True;
+  if (!s) goto DEFAULT;
+
+  for (s2 = s + strlen(s) - 1; s2 > s; s2--)
+    if (*s2 == ' ' || *s2 == '\t')
+      *s2 = 0;
+    else
+      break;
+
+  if (! XParseColor (dpy, cmap, s, &color))
+    {
+      fprintf (stderr, "%s: can't parse color %s", progname, s);
+      ok = False;
+      goto DEFAULT;
+    }
+  if (! XAllocColor (dpy, cmap, &color))
+    {
+      fprintf (stderr, "%s: couldn't allocate color %s", progname, s);
+      ok = False;
+      goto DEFAULT;
+    }
+  return color.pixel;
+ DEFAULT:
+  {
+    if (!ok)
+      fprintf (stderr, ": using black.\n");
+    color.flags = DoRed|DoGreen|DoBlue;
+    color.red = color.green = color.blue = 0;
+    if (XAllocColor (dpy, cmap, &color))
+      return color.pixel;
+    else
+      {
+        fprintf (stderr, "%s: couldn't allocate black either!\n", progname);
+        /* We can't use BlackPixel/WhitePixel here, because we don't know
+           what screen we're allocating on (only an issue when running inside
+           the xscreensaver daemon: for hacks, DefaultScreen is fine.)
+         */
+        return 0;
+      }
+  }
+}
 
 unsigned int
 get_pixel_resource (char *res_name, char *res_class,
diff -urP xscreensaver-4.22/utils/resources.h xscreensaver-4.22-lock/utils/resources.h
--- xscreensaver-4.22/utils/resources.h	2003-03-16 05:24:50.000000000 +0000
+++ xscreensaver-4.22-lock/utils/resources.h	2005-06-27 16:47:31.000000000 +0100
@@ -17,6 +17,7 @@
 extern Bool get_boolean_resource (char*,char*);
 extern int get_integer_resource (char*,char*);
 extern double get_float_resource (char*,char*);
+extern unsigned int parse_pixel_resource (char*,Display*,Colormap);
 extern unsigned int get_pixel_resource (char*,char*,Display*,Colormap);
 extern unsigned int get_minutes_resource (char*,char*);
 extern unsigned int get_seconds_resource (char*,char*);
@@ -29,5 +30,12 @@
                    unsigned long **pixels_ret, int *npixels_ret,
                    Pixmap *mask_ret,
                    Bool big_p);
+extern Pixmap
+xscreensaver_xpm  (Screen *screen, Visual *visual,
+                   Drawable drawable, Colormap cmap,
+                   unsigned long background_color,
+                   unsigned long **pixels_ret, int *npixels_ret,
+                   Pixmap *mask_ret,
+                   const char * const *xpm_data);
 
 #endif /* __XSCREENSAVER_RESOURCES_H__ */
