diff -rbBu gtk+-1.2.8-orig/gtk/gtkcombo.c gtk+-1.2.8/gtk/gtkcombo.c
--- gtk+-1.2.8-orig/gtk/gtkcombo.c	Sun Feb 13 01:01:01 2000
+++ gtk+-1.2.8/gtk/gtkcombo.c	Wed Nov 15 19:16:12 2000
@@ -41,6 +41,13 @@
 #include "gtkcombo.h"
 #include "gtkframe.h"
 
+enum {
+  FINAL_SELECT_SIGNAL,
+  LAST_SIGNAL
+};
+
+static gint gtkcombo_signals[LAST_SIGNAL] = { 0 };
+
 const gchar *gtk_combo_string_key = "gtk-combo-string-value";
 
 #define COMBO_LIST_MAX_HEIGHT	(400)
@@ -104,6 +111,13 @@
   oclass = (GtkObjectClass *) klass;
   widget_class = (GtkWidgetClass *) klass;
 
+  gtkcombo_signals[FINAL_SELECT_SIGNAL] = gtk_signal_new("final-select",
+							 GTK_RUN_FIRST,
+							 oclass->type,
+							 GTK_SIGNAL_OFFSET(GtkComboClass, final_select),
+							 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
+  gtk_object_class_add_signals(oclass, gtkcombo_signals, LAST_SIGNAL);
+
   oclass->destroy = gtk_combo_destroy;
   
   widget_class->size_allocate = gtk_combo_size_allocate;
@@ -555,6 +569,13 @@
 			    NULL, NULL, GDK_CURRENT_TIME);
 	  return FALSE;
 	}
+      else
+      {
+	/* Was a final release */
+	gtk_signal_emit(GTK_OBJECT(combo), 
+			gtkcombo_signals[FINAL_SELECT_SIGNAL]);
+
+      }
     }
   else
     {
@@ -565,6 +586,8 @@
 	  gtk_grab_remove (combo->popwin);
 	  gdk_pointer_ungrab (event->button.time);
 	}
+
+      gtk_signal_emit(combo, gtkcombo_signals[FINAL_SELECT_SIGNAL]);
     }
   
   gtk_widget_hide (combo->popwin);
diff -rbBu gtk+-1.2.8-orig/gtk/gtkcombo.h gtk+-1.2.8/gtk/gtkcombo.h
--- gtk+-1.2.8-orig/gtk/gtkcombo.h	Sun Feb 13 00:59:43 2000
+++ gtk+-1.2.8/gtk/gtkcombo.h	Wed Nov 15 10:32:45 2000
@@ -65,6 +65,8 @@
 
 struct _GtkComboClass {
 	GtkHBoxClass parent_class;
+
+        void (*final_select)(GtkCombo *combo, GtkWidget *selected, gpointer user_data);
 };
 
 guint      gtk_combo_get_type              (void);
diff -rbBu gtk+-1.2.8-orig/gtk/gtkfilesel.c gtk+-1.2.8/gtk/gtkfilesel.c
--- gtk+-1.2.8-orig/gtk/gtkfilesel.c	Wed Oct 18 15:05:25 2000
+++ gtk+-1.2.8/gtk/gtkfilesel.c	Thu Nov 30 16:15:43 2000
@@ -37,6 +37,7 @@
 #include "fnmatch.h"
 
 #include "gdk/gdkkeysyms.h"
+#include "gdk/gdk.h"
 #include "gtkbutton.h"
 #include "gtkentry.h"
 #include "gtkfilesel.h"
@@ -55,6 +56,7 @@
 #include "gtkclist.h"
 #include "gtkdialog.h"
 #include "gtkintl.h"
+#include "gtkcombo.h"
 
 #define DIR_LIST_WIDTH   180
 #define DIR_LIST_HEIGHT  180
@@ -298,6 +300,9 @@
 static gint gtk_file_selection_key_press     (GtkWidget             *widget,
 					      GdkEventKey           *event,
 					      gpointer               user_data);
+static gint gtk_file_selection_file_list_key_press (GtkWidget             *widget,
+						    GdkEventKey           *event,
+						    gpointer               user_data);
 
 static void gtk_file_selection_file_button (GtkWidget *widget,
 					    gint row, 
@@ -311,6 +316,10 @@
 					   GdkEventButton *bevent,
 					   gpointer data);
 
+static void gtk_file_selection_show_file(GtkFileSelection *fs, gchar *name);
+static gint gtk_file_selection_find_nearest_file(GtkFileSelection *fs, 
+						 gchar *name);
+
 static void gtk_file_selection_populate      (GtkFileSelection      *fs,
 					      gchar                 *rel_path,
 					      gint                   try_complete);
@@ -322,7 +331,17 @@
 static void gtk_file_selection_create_dir (GtkWidget *widget, gpointer data);
 static void gtk_file_selection_delete_file (GtkWidget *widget, gpointer data);
 static void gtk_file_selection_rename_file (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_home (GtkWidget *widget, gpointer data);
+
+static void gtk_file_selection_save_history(GtkFileSelection *filesel);
+static void gtk_file_selection_load_history(GtkFileSelection *filesel);
 
+void gtk_file_selection_filter(GtkWidget *widget, gpointer data);
+static gint gtk_file_selection_filter_key_press (GtkWidget   *widget,
+						 GdkEventKey *event,
+						 gpointer     user_data);
+static void gtk_file_selection_filter_combo_select(GtkWidget *widget,
+						   gpointer   user_data);
 
 
 static GtkWindowClass *parent_class = NULL;
@@ -368,6 +387,32 @@
 }
 
 static void
+gtk_file_selection_file_chosen( GtkWidget *widget, gpointer data) {
+  GtkFileSelection *filesel = GTK_FILE_SELECTION(widget);
+  gchar *filename = gtk_file_selection_get_filename(filesel);
+  GList *elem = NULL;
+
+  gtk_file_selection_load_history(filesel);
+
+  if ((elem = g_list_find_custom(filesel->last_selected_files, 
+				 filename, strcmp)) != NULL) {
+    filesel->last_selected_files = g_list_remove_link(filesel->last_selected_files, elem);
+    g_free(elem->data);
+    g_list_free(elem);
+  }
+
+  filesel->last_selected_files = g_list_prepend(filesel->last_selected_files, g_strdup(filename));
+  if (g_list_length(filesel->last_selected_files) >
+      GTK_FILE_SELECTION_VISUAL_HISTORY_LENGTH) {
+    GList *last = g_list_last(filesel->last_selected_files);
+    filesel->last_selected_files = g_list_remove_link(filesel->last_selected_files, last);
+    g_free(last->data);
+    g_list_free(last);
+  }
+  gtk_file_selection_save_history(filesel);
+}
+
+static void
 gtk_file_selection_init (GtkFileSelection *filesel)
 {
   GtkWidget *entry_vbox;
@@ -376,6 +421,8 @@
   GtkWidget *confirm_area;
   GtkWidget *pulldown_hbox;
   GtkWidget *scrolled_win;
+  GtkWidget *filter_area;
+  GList     *filter_list;
 
   char *dir_title [2];
   char *file_title [2];
@@ -441,6 +488,8 @@
   gtk_signal_connect (GTK_OBJECT (filesel->file_list), "select_row",
 		      (GtkSignalFunc) gtk_file_selection_file_button, 
 		      (gpointer) filesel);
+  gtk_signal_connect (GTK_OBJECT (filesel->file_list), "key_press_event",
+		      (GtkSignalFunc) gtk_file_selection_file_list_key_press, filesel);
   gtk_clist_column_titles_passive (GTK_CLIST (filesel->file_list));
 
   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
@@ -458,11 +507,47 @@
 		      FALSE, FALSE, 0);
   gtk_widget_show (filesel->action_area);
   
+  /* The filter/confirm area */
+  filter_area = gtk_hbox_new(FALSE, 0);
+  gtk_box_pack_end (GTK_BOX (filesel->main_vbox), filter_area, FALSE, FALSE, 0);
+  gtk_widget_show(filter_area);
+
+  label = gtk_label_new(_("Show: "));
+  gtk_box_pack_start(GTK_BOX(filter_area), label, FALSE, FALSE, 0);
+  gtk_widget_show(label);
+
+  filesel->filter_combo = gtk_combo_new();
+  gtk_box_pack_start(GTK_BOX(filter_area), filesel->filter_combo, FALSE, FALSE, 0);
+  gtk_combo_disable_activate(GTK_COMBO(filesel->filter_combo));
+  gtk_widget_show(filesel->filter_combo);
+
+  gtk_signal_connect (GTK_OBJECT (GTK_COMBO(filesel->filter_combo)->entry),
+		      "key_press_event",
+		      (GtkSignalFunc) gtk_file_selection_filter_key_press,
+		      filesel);
+  gtk_signal_connect (GTK_OBJECT (GTK_COMBO(filesel->filter_combo)->entry), 
+		      "activate",
+		      (GtkSignalFunc) gtk_file_selection_filter,
+		      filesel);
+  g_print("Filesel is %p\n", filesel);
+  gtk_signal_connect (GTK_OBJECT (filesel->filter_combo), 
+		      "final-select",
+		      (GtkSignalFunc) gtk_file_selection_filter_combo_select,
+		      filesel);
+
+  filter_list = g_list_append(NULL, _("All files"));
+  filter_list = g_list_append(filter_list, _("JPG files"));
+  gtk_object_set_data(GTK_OBJECT(filesel->filter_combo), "labels", filter_list);
+
+  filter_list = g_list_append(NULL, "*");
+  filter_list = g_list_append(filter_list, "*.[jJ][pP][eE]?[gG]");
+  gtk_object_set_data(GTK_OBJECT(filesel->filter_combo), "regexps", filter_list);
+
   /*  The OK/Cancel button area */
   confirm_area = gtk_hbutton_box_new ();
   gtk_button_box_set_layout(GTK_BUTTON_BOX(confirm_area), GTK_BUTTONBOX_END);
   gtk_button_box_set_spacing(GTK_BUTTON_BOX(confirm_area), 5);
-  gtk_box_pack_end (GTK_BOX (filesel->main_vbox), confirm_area, FALSE, FALSE, 0);
+  gtk_box_pack_end (GTK_BOX (filter_area), confirm_area, FALSE, FALSE, 0);
   gtk_widget_show (confirm_area);
 
   /*  The OK button  */
@@ -488,7 +573,10 @@
   gtk_box_pack_start (GTK_BOX (entry_vbox), label, FALSE, FALSE, 0);
   gtk_widget_show (label);
 
-  filesel->selection_entry = gtk_entry_new ();
+  filesel->selection_combo = gtk_combo_new();
+  gtk_combo_disable_activate(GTK_COMBO(filesel->selection_combo));
+
+  filesel->selection_entry = GTK_COMBO(filesel->selection_combo)->entry;
   gtk_signal_connect (GTK_OBJECT (filesel->selection_entry), "key_press_event",
 		      (GtkSignalFunc) gtk_file_selection_key_press, filesel);
   gtk_signal_connect_object (GTK_OBJECT (filesel->selection_entry), "focus_in_event",
@@ -497,8 +585,11 @@
   gtk_signal_connect_object (GTK_OBJECT (filesel->selection_entry), "activate",
                              (GtkSignalFunc) gtk_button_clicked,
                              GTK_OBJECT (filesel->ok_button));
-  gtk_box_pack_start (GTK_BOX (entry_vbox), filesel->selection_entry, TRUE, TRUE, 0);
-  gtk_widget_show (filesel->selection_entry);
+  gtk_signal_connect_object (GTK_OBJECT (filesel->ok_button), "clicked",
+			     (GtkSignalFunc) gtk_file_selection_file_chosen,
+			     GTK_OBJECT(filesel));
+  gtk_box_pack_start (GTK_BOX (entry_vbox), filesel->selection_combo, TRUE, TRUE, 0);
+  gtk_widget_show (filesel->selection_combo);
 
   if (!cmpl_state_okay (filesel->cmpl_state))
     {
@@ -567,6 +658,17 @@
       gtk_widget_show (filesel->fileop_ren_file);
     }
 
+  if (!filesel->fileop_home)
+    {
+      filesel->fileop_home = gtk_button_new_with_label (_("Home"));
+      gtk_signal_connect (GTK_OBJECT (filesel->fileop_home), "clicked",
+			  (GtkSignalFunc) gtk_file_selection_home, 
+			  (gpointer) filesel);
+      gtk_box_pack_start (GTK_BOX (filesel->button_area), 
+			  filesel->fileop_home, TRUE, TRUE, 0);
+      gtk_widget_show (filesel->fileop_home);
+    }
+
   gtk_widget_queue_resize(GTK_WIDGET(filesel));
 }
 
@@ -576,6 +678,11 @@
   g_return_if_fail (filesel != NULL);
   g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
     
+  if (filesel->fileop_home)
+    {
+      gtk_widget_destroy (filesel->fileop_home);
+      filesel->fileop_home = NULL;
+    }
   if (filesel->fileop_ren_file) 
     {
       gtk_widget_destroy (filesel->fileop_ren_file);
@@ -700,6 +807,199 @@
     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
 }
 
+static void
+unmake_directories(gchar *dirname, gchar *until) {
+  if (strcmp(dirname, until) && strcmp(dirname, "/")) {
+    if (!rmdir(dirname)) {
+      dirname = g_dirname(dirname);
+      unmake_directories(dirname, until);
+      g_free(dirname);
+    }
+  }
+}
+
+static gchar *
+make_directories(gchar *filename) {
+  struct stat dummy;
+
+  if ((stat(filename, &dummy) == -1) && 
+      errno == ENOENT) {
+    gchar *dirname = g_dirname(filename);
+    gchar *created = make_directories(dirname);
+    if (created) {
+      int retval = mkdir(filename, 0700);
+      if (retval == -1) {
+	g_warning("Unable to create history directory %s: %s\n",
+		  filename, strerror(errno));
+	unmake_directories(dirname, created);
+	created = NULL;
+      }
+    }
+    g_free(dirname);
+    return created;
+  } else {
+    return filename;
+  }
+}
+
+void
+gtk_file_selection_set_history_filename(GtkFileSelection *filesel,
+					const gchar *filename)
+{
+  g_assert(filesel != NULL);
+
+  if (filename == NULL) {
+    filename = "file_dialog_history";
+  }
+  
+  if (*filename == '/')
+    filesel->file_history_filename = strdup(filename);
+  else {
+    gchar *full_filename;
+    char *home_dir = getenv("HOME");
+    gchar *dirname;
+    if (home_dir == NULL) {
+      g_warning("Couldn't find home directory!");
+      home_dir = "/tmp";
+    }
+    if (!strcmp(home_dir, "/") && getpid() != 0) {
+      home_dir = "/tmp";
+    }
+    full_filename = g_strdup_printf("%s/.gtk/%s/%s",
+				    home_dir, g_get_prgname(), filename);
+
+    dirname = g_dirname(full_filename);
+    if (make_directories(dirname) == NULL) {
+      filesel->file_history_filename = (gchar *)-1;
+    } else {
+      filesel->file_history_filename = full_filename;
+    }
+    g_free(dirname);
+  }    
+}
+
+gchar *
+gtk_file_selection_get_history_filename(GtkFileSelection *filesel)
+{
+  return filesel->file_history_filename;
+}
+
+static void
+gtk_file_selection_load_history(GtkFileSelection *filesel) {
+  FILE *history_file;
+  GList *elem = NULL;
+  GString *history_entry;
+  struct stat statbuf;
+
+  if (filesel->file_history_filename == NULL)
+    gtk_file_selection_set_history_filename(filesel, NULL);
+  if (filesel->file_history_filename == (gchar *)-1)
+    return;
+
+  if (filesel->last_history_file_save != 0 &&
+      (stat(filesel->file_history_filename, &statbuf) != -1) &&
+      (statbuf.st_mtime <= filesel->last_history_file_save))
+    return;
+
+  history_file = fopen(filesel->file_history_filename, "r");
+  if (history_file == NULL) {
+    /* Not a fail -- file might not have been written yet */
+    if (errno == ENOENT) return;
+    g_warning("Couldn't open file dialog persistence file %s: %s\n", 
+	      filesel->file_history_filename, strerror(errno));
+    return;
+  }
+  history_entry = g_string_new("");
+  while (!feof(history_file)) {
+    char buf[80];
+    int len = 0;
+    buf[0] = '\0';
+    do {
+      if (feof(history_file)) {
+	break;
+      }
+      if (fgets(buf, 80, history_file) == EOF) {
+	g_warning("Couldn't read file dialog persistence file %s: %s\n", 
+		  filesel->file_history_filename, strerror(errno));
+	g_string_free(history_entry, TRUE);
+	/* Failed reading, but we might as well use what we got */
+	filesel->last_selected_files = g_list_reverse(elem);
+	goto FAIL;
+      }
+      len += strlen(buf);
+      history_entry = g_string_append(history_entry, buf);
+    } while (!strchr(buf, '\n'));
+    if (len > 0) {
+      /* Chop! */
+      history_entry = g_string_truncate(history_entry, len-1);
+      elem = g_list_prepend(elem, strdup(history_entry->str));
+      g_string_truncate(history_entry, 0);
+    }
+  }
+  if (fstat(fileno(history_file), &statbuf) != -1) 
+    filesel->last_history_file_save = statbuf.st_mtime;
+
+  g_string_free(history_entry, TRUE);
+  filesel->last_selected_files = g_list_reverse(elem);
+  if (fclose(history_file)) {
+    g_warning("Failed closing file dialog persistence file %s: %s\n", 
+	      filesel->file_history_filename, strerror(errno));
+    goto FAIL;
+  }
+  return;
+
+ FAIL:
+  g_free(filesel->file_history_filename);
+  filesel->file_history_filename = (gchar *)-1;
+  return;
+}
+
+static void
+gtk_file_selection_save_history(GtkFileSelection *filesel) {
+  FILE *history_file;
+  GList *file_list;
+  struct stat statbuf;
+
+  if (filesel->file_history_filename == NULL)
+    gtk_file_selection_set_history_filename(filesel, NULL);
+  if (filesel->file_history_filename == (gchar *)-1)
+    return;
+  
+  history_file = fopen(filesel->file_history_filename, "w");
+  if (history_file == NULL) {
+    g_warning("Couldn't write file dialog persistence file %s: %s\n", 
+	      filesel->file_history_filename, strerror(errno));
+    goto FAIL;
+  }
+  file_list = filesel->last_selected_files;
+  while (file_list != NULL) {
+    if (fprintf(history_file, file_list->data) == 0) {
+      g_warning("Failed writing file dialog persistence file %s: %s\n", 
+		filesel->file_history_filename, strerror(errno));
+      goto FAIL;
+    }
+    if (fprintf(history_file, "\n") == 0) {
+      g_warning("Failed writing file dialog persistence file %s: %s\n", 
+		filesel->file_history_filename, strerror(errno));
+      goto FAIL;
+    }
+    file_list = g_list_next(file_list);
+  }
+  if (fstat(fileno(history_file), &statbuf) != -1) 
+    filesel->last_history_file_save = statbuf.st_mtime;
+  if (fclose(history_file)) {
+    g_warning("Failed closing file dialog persistence file %s: %s\n", 
+	      filesel->file_history_filename, strerror(errno));
+    goto FAIL;
+  }
+
+  return;
+ FAIL:
+  g_free(filesel->file_history_filename);
+  filesel->file_history_filename = (gchar *)-1;
+  return;
+}
+
 /* Begin file operations callbacks */
 
 static void
@@ -890,8 +1190,13 @@
     }
   g_free (full_path);
   
+  full_path = strdup(fs->fileop_file);
+
   gtk_widget_destroy (fs->fileop_dialog);
   gtk_file_selection_populate (fs, "", FALSE);
+
+  gtk_file_selection_show_file(fs, full_path);
+  g_free(full_path);
 }
 
 static void
@@ -994,11 +1299,14 @@
 			 g_strerror(errno), NULL);
       gtk_file_selection_fileop_error (fs, buf);
     }
-  g_free (new_filename);
-  g_free (old_filename);
   
   gtk_widget_destroy (fs->fileop_dialog);
   gtk_file_selection_populate (fs, "", FALSE);
+
+  gtk_file_selection_show_file(fs, old_filename);
+
+  g_free (new_filename);
+  g_free (old_filename);
 }
   
 static void
@@ -1082,20 +1390,43 @@
 }
 
 
+static void
+gtk_file_selection_home (GtkWidget *widget, gpointer data)
+{
+  GtkFileSelection *fs = data;
+  char *home_dir = getenv("HOME");
+
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  if (home_dir == NULL) {
+    /* Pop up error dialog */
+    gtk_file_selection_fileop_error (fs, "No home directory found.");
+    return;
+  }
+
+  home_dir = g_strconcat(home_dir, "/", NULL);
+
+  gtk_file_selection_populate (fs, home_dir, FALSE);
+
+  g_free(home_dir); /* Does gtk_file_selection_populate keep it? */
+}
+
 static gint
 gtk_file_selection_key_press (GtkWidget   *widget,
 			      GdkEventKey *event,
 			      gpointer     user_data)
 {
   GtkFileSelection *fs;
-  char *text;
 
   g_return_val_if_fail (widget != NULL, FALSE);
   g_return_val_if_fail (event != NULL, FALSE);
 
+  fs = GTK_FILE_SELECTION (user_data);
+
   if (event->keyval == GDK_Tab)
     {
-      fs = GTK_FILE_SELECTION (user_data);
+      char *text;
       text = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
 
       text = g_strdup (text);
@@ -1108,10 +1439,133 @@
 
       return TRUE;
     }
+  if (event->keyval == GDK_Escape) {
+    GtkWidget *cancel;
+
+    cancel = fs->cancel_button;
+    gtk_signal_emit_by_name(GTK_OBJECT(cancel), "clicked");
+    return TRUE;
+  }
 
   return FALSE;
 }
 
+static gint
+gtk_file_selection_file_list_key_press (GtkWidget   *widget,
+				       GdkEventKey *event,
+				       gpointer     user_data)
+{
+  GtkFileSelection *fs;
+  gchar *keyname;
+
+  g_return_val_if_fail (widget != NULL, FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
+
+  fs = GTK_FILE_SELECTION (user_data);
+
+  keyname = gdk_keyval_name(event->keyval);
+
+  g_print("Got char %s\n", keyname);
+  if (keyname != NULL && strlen(keyname) == 1) {
+    gtk_file_selection_show_file(fs, keyname);
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+void
+gtk_file_selection_append_filter(GtkFileSelection *filesel,
+				 const gchar      *label,
+				 const gchar      *regexp) {
+  GtkObject *combo = GTK_OBJECT(filesel->filter_combo);
+  GList *labels, *regexps;
+
+  labels = (GList *)gtk_object_get_data(combo, "labels");
+  regexps = (GList *)gtk_object_get_data(combo, "regexps");
+  
+  gtk_object_set_data(combo, "labels", g_list_append(labels, label));
+  gtk_object_set_data(combo, "regexps", g_list_append(regexps, regexp));
+}
+
+void
+gtk_file_selection_set_filter          (GtkFileSelection *filesel,
+					GList            *labels,
+					GList            *regexps) {
+  GtkObject *combo = GTK_OBJECT(filesel->filter_combo);
+
+  gtk_object_set_data(GTK_OBJECT(filesel->filter_combo), "labels", labels);
+  gtk_object_set_data(GTK_OBJECT(filesel->filter_combo), "regexps", regexps);
+}
+
+
+void
+gtk_file_selection_filter(GtkWidget *widget, gpointer data) {
+  GtkFileSelection *fs = GTK_FILE_SELECTION(data);
+  gchar *regexp, *entry;
+  GList *labels, *regexps;
+
+  g_assert(fs != NULL);
+  g_assert(GTK_IS_FILE_SELECTION (fs));
+  g_assert(fs->filter_combo != NULL);
+
+  g_print("Doing filter\n");
+
+  labels = (GList *)gtk_object_get_data(GTK_OBJECT(fs->filter_combo),
+					"labels");
+  regexps = (GList *)gtk_object_get_data(GTK_OBJECT(fs->filter_combo),
+					 "regexps");
+
+  g_print("Found lists\n");
+
+  regexp = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(fs->filter_combo)->entry));
+
+  g_print("Regexp was %s\n", regexp);
+
+  /* Find the label */
+  for (;labels != NULL;
+       labels = g_list_next(labels), regexps = g_list_next(regexps)) {
+    if (strcasecmp((char *)labels->data, regexp) == 0) {
+      regexp = (char *)regexps->data;
+    }
+  }
+
+  g_print("Regexp is %s\n", regexp);
+
+  entry = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
+
+  gtk_file_selection_populate(fs, regexp, TRUE);
+
+  gtk_entry_set_text(GTK_ENTRY(fs->selection_entry), entry);
+}
+
+static void
+gtk_file_selection_filter_combo_select(GtkWidget *widget,
+				       gpointer   user_data) {
+  g_print("Doing filter combo select: %p, %p\n", widget, user_data);
+
+  gtk_file_selection_filter(widget, user_data);
+}
+
+static gint
+gtk_file_selection_filter_key_press (GtkWidget   *widget,
+				     GdkEventKey *event,
+				     gpointer     user_data)
+{
+  g_return_val_if_fail (widget != NULL, FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
+
+  g_print("Doing filter key press\n");
+
+  if (event->keyval == GDK_Tab)
+  {
+    g_print("Tab pressed\n");
+    gtk_file_selection_filter(widget, user_data);
+    return TRUE;
+  }
+
+  return FALSE;
+}
 
 static void
 gtk_file_selection_history_callback (GtkWidget *widget, gpointer data)
@@ -1248,7 +1702,7 @@
       else
 	gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
 
-      g_free (filename);
+      g_free(filename);
     }
 }
 
@@ -1281,16 +1735,49 @@
 	    break;
 	  
 	  default:
+	    /*
 	    gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
+	    */
 	    break;
 	  }
       else
+	gtk_file_selection_populate (fs, filename, FALSE);
+	/*
 	gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
+	*/
 
       g_free (filename);
     }
 }
 
+static gint
+gtk_file_selection_find_nearest_file(GtkFileSelection *fs, gchar *name) {
+  GList *rows = GTK_CLIST(fs->file_list)->row_list;
+  int i = 0;
+  
+  name = g_basename(name);
+
+  for (; rows != NULL; rows = g_list_next(rows)) {
+    GtkCListRow *row = GTK_CLIST_ROW(rows);
+
+    if (strcmp(name, row->cell->u.text) <= 0)
+      return i;
+    i++;
+  }
+
+  return -1;
+}
+
+static void
+gtk_file_selection_show_file(GtkFileSelection *fs, gchar *name) {
+  int row = gtk_file_selection_find_nearest_file(fs, name);
+
+  if (row != -1) {
+    gtk_clist_moveto(GTK_CLIST(fs->file_list),
+		     row, 0, .5, 0.0);
+  }
+}
+
 static void
 gtk_file_selection_populate (GtkFileSelection *fs,
 			     gchar            *rel_path,
@@ -1431,8 +1918,35 @@
     }
   else
     {
+      if (fs->selection_entry) {
+	gchar * basename;
+	basename = g_basename(gtk_entry_get_text(GTK_ENTRY(fs->selection_entry)));
+	if (basename == NULL) {
+	  g_warning("NULL basename");
+	} else if (basename != gtk_entry_get_text(GTK_ENTRY(fs->selection_entry))) {
+	  basename = strdup(basename);
+	  gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), basename);
+	  g_free(basename);
+	}
+	gtk_combo_set_popdown_strings(GTK_COMBO(fs->filter_combo),
+				      (GList *)gtk_object_get_data(GTK_OBJECT(fs->filter_combo), "labels"));
+
+	if (!fs->last_selected_files) {
+	  gtk_file_selection_load_history(fs);
+	}
+
+	if (fs->last_selected_files) {
+	  gtk_file_selection_show_file(fs,fs->last_selected_files->data);
+
+	  gtk_combo_set_popdown_strings(GTK_COMBO(fs->selection_combo),
+					fs->last_selected_files);
+	}
+      }
+     
+      /*
       if (fs->selection_entry)
 	gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), "");
+      */
     }
 
   if (!did_recurse)
diff -rbBu gtk+-1.2.8-orig/gtk/gtkfilesel.h gtk+-1.2.8/gtk/gtkfilesel.h
--- gtk+-1.2.8-orig/gtk/gtkfilesel.h	Wed Oct 18 15:05:25 2000
+++ gtk+-1.2.8/gtk/gtkfilesel.h	Tue Nov 14 18:14:21 2000
@@ -42,9 +42,9 @@
 #define GTK_FILE_SELECTION_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_SELECTION, GtkFileSelectionClass))
 #define GTK_IS_FILE_SELECTION(obj)         (GTK_CHECK_TYPE ((obj), GTK_TYPE_FILE_SELECTION))
 #define GTK_IS_FILE_SELECTION_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_SELECTION))
+#define GTK_FILE_SELECTION_VISUAL_HISTORY_LENGTH 5
 
-
-typedef struct _GtkFileSelection       GtkFileSelection;
+  typedef struct _GtkFileSelection       GtkFileSelection;
 typedef struct _GtkFileSelectionClass  GtkFileSelectionClass;
 
 struct _GtkFileSelection
@@ -74,6 +74,13 @@
   GtkWidget *button_area;
   GtkWidget *action_area;
   
+  GtkWidget *fileop_home;
+
+  GtkWidget *selection_combo;
+  GList     *last_selected_files;
+  gchar     *file_history_filename;
+  time_t     last_history_file_save;
+  GtkWidget *filter_combo;
 };
 
 struct _GtkFileSelectionClass
@@ -91,8 +98,15 @@
 						   const gchar	    *pattern);
 void       gtk_file_selection_show_fileop_buttons (GtkFileSelection *filesel);
 void       gtk_file_selection_hide_fileop_buttons (GtkFileSelection *filesel);
-
-
+void       gtk_file_selection_set_history_filename(GtkFileSelection *filesel,
+						   const gchar      *filename);
+gchar     *gtk_file_selection_get_history_filename(GtkFileSelection *filesel);
+void       gtk_file_selection_append_filter       (GtkFileSelection *filesel,
+						   const gchar      *label,
+						   const gchar      *regexp);
+void       gtk_file_selection_set_filter          (GtkFileSelection *filesel,
+						   GList            *labels,
+						   GList            *regexps);
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

