Index: filter.c
===================================================================
--- filter.c	(revision 23fddadbb7a375688e9be9627f1f5ca39aaa54d0)
+++ filter.c	(revision 3cc4bfc144304de096deb510403db0c38a62af68)
@@ -164,4 +164,9 @@
 }
 
+SV *owl_filter_to_sv(const owl_filter *f)
+{
+  return owl_new_sv(owl_filter_get_name(f));
+}
+
 void owl_filter_set_fgcolor(owl_filter *f, int color)
 {
Index: fmtext.c
===================================================================
--- fmtext.c	(revision 6c171f190998142df485a1f93b4ef7bad5a8ea57)
+++ fmtext.c	(revision 1ee5c79201bda5ae7debf1c06a41c4813cebb496)
@@ -686,5 +686,6 @@
           /* set it as the current color */
           curcolor=owl_util_string_to_color(buff);
-          if (curcolor==-1) curcolor=OWL_COLOR_DEFAULT;
+          if (curcolor == OWL_COLOR_INVALID)
+	      curcolor = OWL_COLOR_DEFAULT;
           owl_free(buff);
           txtptr=tmpptr+1;
Index: owl.h
===================================================================
--- owl.h	(revision 6fc40a789c812bcdaacbe64f88178bb1409d1071)
+++ owl.h	(revision 6fc40a789c812bcdaacbe64f88178bb1409d1071)
@@ -44,4 +44,6 @@
 #else
 typedef void SV;
+typedef void AV;
+typedef void HV;
 #endif
 
Index: perl/lib/BarnOwl/Complete/Client.pm
===================================================================
--- perl/lib/BarnOwl/Complete/Client.pm	(revision a3a9eb73bf0972305a6b4df90ea6e4d482d6b4e0)
+++ perl/lib/BarnOwl/Complete/Client.pm	(revision 02a72bfacefe24e332415bea7225142b5d609763)
@@ -24,7 +24,10 @@
     commands    => undef,
     command     => \&complete_command,
+    errors      => undef,
     filters     => undef,
     filter      => \&complete_filter_name,
     license     => undef,
+    keymaps     => undef,
+    keymap      => \&complete_keymap,
     quickstart  => undef,
     startup     => undef,
@@ -45,4 +48,5 @@
 sub complete_variable    { return @{BarnOwl::all_variables()}; }
 sub complete_style       { return @{BarnOwl::all_styles()}; }
+sub complete_keymap      { return @{BarnOwl::all_keymaps()}; }
 
 sub complete_help {
Index: perlconfig.c
===================================================================
--- perlconfig.c	(revision ffc4df61a846d99a75783f7d348fb98dd19910aa)
+++ perlconfig.c	(revision ffc4df61a846d99a75783f7d348fb98dd19910aa)
@@ -33,4 +33,42 @@
     owl_free(escape);
   }
+  return ret;
+}
+
+AV *owl_new_av(const owl_list *l, SV *(*to_sv)(const void *))
+{
+  AV *ret;
+  int i;
+  void *element;
+
+  ret = newAV();
+
+  for (i = 0; i < owl_list_get_size(l); i++) {
+    element = owl_list_get_element(l, i);
+    av_push(ret, to_sv(element));
+  }
+
+  return ret;
+}
+
+HV *owl_new_hv(const owl_dict *d, SV *(*to_sv)(const void *))
+{
+  HV *ret;
+  owl_list l;
+  const char *key;
+  void *element;
+  int i;
+
+  ret = newHV();
+
+  /* TODO: add an iterator-like interface to owl_dict */
+  owl_dict_get_keys(d, &l);
+  for (i = 0; i < owl_list_get_size(&l); i++) {
+    key = owl_list_get_element(&l, i);
+    element = owl_dict_find_element(d, key);
+    (void)hv_store(ret, key, strlen(key), to_sv(element), 0);
+  }
+  owl_list_free_all(&l, owl_free);
+
   return ret;
 }
Index: perlglue.xs
===================================================================
--- perlglue.xs	(revision ffc4df61a846d99a75783f7d348fb98dd19910aa)
+++ perlglue.xs	(revision ffc4df61a846d99a75783f7d348fb98dd19910aa)
@@ -326,17 +326,9 @@
 all_filters()
 	PREINIT:
-		AV *filters;
 		const owl_list *fl;
-		const owl_filter *f;
-		int i;
 	CODE:
 	{
 		fl = owl_global_get_filterlist(&g);
-		filters = newAV();
-		for(i=0;i<owl_list_get_size(fl);i++) {
-			f = owl_list_get_element(fl, i);
-			av_push(filters, owl_new_sv(owl_filter_get_name(f)));
-		}
-		RETVAL = filters;
+		RETVAL = owl_new_av(fl, (SV*(*)(const void*))owl_filter_to_sv);
 		sv_2mortal((SV*)RETVAL);
 	}
@@ -347,18 +339,10 @@
 all_styles()
 	PREINIT:
-		AV *styles;
 		owl_list l;
-		const char *name;
-		int i;
 	CODE:
 	{
 		owl_list_create(&l);
 		owl_global_get_style_names(&g, &l);
-		styles = newAV();
-		for(i=0;i<owl_list_get_size(&l);i++) {
-			name = owl_list_get_element(&l, i);
-			av_push(styles, owl_new_sv(name));
-		}
-		RETVAL = styles;
+		RETVAL = owl_new_av(&l, (SV*(*)(const void*))owl_new_sv);
 		sv_2mortal((SV*)RETVAL);
 	}
@@ -372,18 +356,29 @@
 all_variables()
 	PREINIT:
-		AV *vars;
 		owl_list l;
-		const char *name;
-		int i;
 	CODE:
 	{
 		owl_list_create(&l);
 		owl_dict_get_keys(owl_global_get_vardict(&g), &l);
-		vars = newAV();
-		for(i=0;i<owl_list_get_size(&l);i++) {
-			name = owl_list_get_element(&l, i);
-			av_push(vars, owl_new_sv(name));
-		}
-		RETVAL = vars;
+		RETVAL = owl_new_av(&l, (SV*(*)(const void*))owl_new_sv);
+		sv_2mortal((SV*)RETVAL);
+	}
+	OUTPUT:
+		RETVAL
+	CLEANUP:
+		owl_list_free_all(&l, owl_free);
+
+
+AV*
+all_keymaps()
+	PREINIT:
+		owl_list l;
+		const owl_keyhandler *kh;
+	CODE:
+	{
+		owl_list_create(&l);
+		kh = owl_global_get_keyhandler(&g);
+		owl_keyhandler_get_keymap_names(kh, &l);
+		RETVAL = owl_new_av(&l, (SV*(*)(const void*))owl_new_sv);
 		sv_2mortal((SV*)RETVAL);
 	}
Index: scripts/locker-build
===================================================================
--- scripts/locker-build	(revision db98968bc3b30ba528ad63029aaba1addb187104)
+++ scripts/locker-build	(revision 2b6622a602f1f8b0922ad96976b2abc20232db9c)
@@ -80,9 +80,12 @@
     echo "Building BarnOwl version $VERS"
 
+    opt_rpath="-Wl,-R"
+    [ $(uname) = "SunOS" ] && opt_rpath="-R"
+
     BARNOWL="/afs/sipb.mit.edu/project/barnowl/arch/$ATHENA_SYS"
     export PKG_CONFIG_PATH="$BARNOWL/lib/pkgconfig"
 
     CFLAGS="-I$BARNOWL/include" \
-        LDFLAGS="-L$BARNOWL/lib -Wl,-R$BARNOWL/lib" \
+        LDFLAGS="-L$BARNOWL/lib $opt_rpath$BARNOWL/lib" \
         ./configure --exec-prefix="/mit/barnowl/arch/$ATHENA_SYS" \
         --prefix="/mit/barnowl/builds/barnowl-$VERS" --mandir=/mit/barnowl/man \
Index: util.c
===================================================================
--- util.c	(revision 0697f097cd4d945d2e96f60d1690da9c5f4d9dc4)
+++ util.c	(revision 1b9d3cc988eca748bb848a9e8e8c38c6b4022dfd)
@@ -407,4 +407,20 @@
 }
 
+/* These are in order of their value in owl.h */
+static const struct {
+  int number;
+  const char *name;
+} color_map[] = {
+  {OWL_COLOR_INVALID, "invalid"},
+  {OWL_COLOR_DEFAULT, "default"},
+  {OWL_COLOR_BLACK, "black"},
+  {OWL_COLOR_RED, "red"},
+  {OWL_COLOR_GREEN, "green"},
+  {OWL_COLOR_YELLOW,"yellow"},
+  {OWL_COLOR_BLUE, "blue"},
+  {OWL_COLOR_MAGENTA, "magenta"},
+  {OWL_COLOR_CYAN, "cyan"},
+  {OWL_COLOR_WHITE, "white"},
+};
 
 /* Return the owl color associated with the named color.  Return -1
@@ -413,26 +429,13 @@
 int owl_util_string_to_color(const char *color)
 {
-  int c;
-  if (!strcasecmp(color, "black")) {
-    return(OWL_COLOR_BLACK);
-  } else if (!strcasecmp(color, "red")) {
-    return(OWL_COLOR_RED);
-  } else if (!strcasecmp(color, "green")) {
-    return(OWL_COLOR_GREEN);
-  } else if (!strcasecmp(color, "yellow")) {
-    return(OWL_COLOR_YELLOW);
-  } else if (!strcasecmp(color, "blue")) {
-    return(OWL_COLOR_BLUE);
-  } else if (!strcasecmp(color, "magenta")) {
-    return(OWL_COLOR_MAGENTA);
-  } else if (!strcasecmp(color, "cyan")) {
-    return(OWL_COLOR_CYAN);
-  } else if (!strcasecmp(color, "white")) {
-    return(OWL_COLOR_WHITE);
-  } else if (!strcasecmp(color, "default")) {
-    return(OWL_COLOR_DEFAULT);
-  }
-  c = atoi(color);
-  if (c >= -1 && c < COLORS) {
+  int c, i;
+  char *p;
+
+  for (i = 0; i < (sizeof(color_map)/sizeof(color_map[0])); i++)
+    if (strcasecmp(color, color_map[i].name) == 0)
+      return color_map[i].number;
+
+  c = strtol(color, &p, 10);
+  if (p != color && c >= -1 && c < COLORS) {
     return(c);
   }
@@ -443,13 +446,6 @@
 const char *owl_util_color_to_string(int color)
 {
-  if (color==OWL_COLOR_BLACK)   return("black");
-  if (color==OWL_COLOR_RED)     return("red");
-  if (color==OWL_COLOR_GREEN)   return("green");
-  if (color==OWL_COLOR_YELLOW)  return("yellow");
-  if (color==OWL_COLOR_BLUE)    return("blue");
-  if (color==OWL_COLOR_MAGENTA) return("magenta");
-  if (color==OWL_COLOR_CYAN)    return("cyan");
-  if (color==OWL_COLOR_WHITE)   return("white");
-  if (color==OWL_COLOR_DEFAULT) return("default");
+  if (color >= OWL_COLOR_INVALID && color <= OWL_COLOR_WHITE)
+    return color_map[color - OWL_COLOR_INVALID].name;
   return("Unknown color");
 }
