--- /tmp/interface.c	2006-08-31 09:49:57.000000000 +0200
+++ gpe-package-0.3/interface.c	2006-08-31 09:50:20.855780000 +0200
@@ -27,6 +27,10 @@
 #include <locale.h>
 #include <libintl.h>
 
+#ifdef ENABLE_PCRE
+#include <pcre.h>
+#endif
+
 #define _(x) gettext(x)
 #define N_(_x) (_x)
 
@@ -55,11 +59,8 @@
 #define MI_PACKAGES_APPLY   7
 #define MI_FILTER_INST		8
 #define MI_FILTER_NOTINST	9
-#define MI_PACKAGES_INFO    10
-
-#define TREE_SHOW_ALL		0x00
-#define TREE_SHOW_INST		0x01
-#define TREE_SHOW_NOTINST	0x02
+#define MI_FILTER_SEARCH	10
+#define MI_PACKAGES_INFO    11
 
 #define HELPMESSAGE "GPE-Package\nVersion " VERSION \
 		"\nGPE frontend for ipkg\n\nflorian@handhelds.org"
@@ -79,7 +80,6 @@
 
 static description_t *pkg_info = NULL;
 static int pkg_count = 0;
-static int tree_filter = TREE_SHOW_ALL;
 
 int sock;
 static pkcommand_t running_command = CMD_NONE;
@@ -91,10 +91,12 @@
 static GtkWidget *notebook;
 static GtkWidget *txLog;
 static GtkWidget *treeview;
+static GtkTreeModel *filter;
+static gchar *filter_term = NULL;
 static GtkTreeStore *store = NULL;
 static GtkToolItem *bApply;
 static GtkWidget *miUpdate, *miSysUpgrade, *miSelectLocal, *miApply;
-static GtkWidget *miFilterInst, *miFilterNotInst;
+static GtkWidget *miFilterInst, *miFilterNotInst, *miFilterSearch;
 static GtkWidget *sbar;
 GtkWidget *fMain;
 static GtkWidget *dlgAction = NULL;
@@ -102,10 +104,17 @@
 static GtkTextBuffer *infobuffer = NULL;
 static GtkWidget *mMain;
 
+#ifdef ENABLE_PCRE
+static gboolean is_regexp;
+#endif
 
 /* some forwards */
 gboolean get_pending_messages ();
 void on_tree_filter_changed(GtkCheckMenuItem *menuitem, gpointer user_data);
+void on_tree_filter_search_changed (GtkCheckMenuItem *menuitem, gpointer user_data);
+gboolean filter_visible_func (GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data);
+void set_filter_term (const gchar *text, gboolean regexp);
+void search_entry_activated (GtkEntry *entry, gpointer user_data);
 void create_fMain (void);
 void on_select_local(GtkButton *button, gpointer user_data);
 void on_packages_update_clicked(GtkButton *button, gpointer user_data);
@@ -125,8 +134,10 @@
   { N_("/Packages/Show Insta_lled"), "", on_tree_filter_changed, MI_FILTER_INST , "<CheckItem>"},
   { N_("/Packages/Show _Not Installed"), "", on_tree_filter_changed, MI_FILTER_NOTINST, "<CheckItem>"},
   { N_("/_Packages/s2"), NULL , NULL,    0, "<Separator>"},
-  { N_("/Packages/Show _Info"), "<Control> I", on_package_info_clicked, MI_PACKAGES_INFO , "<Item>"},
+  { N_("/Packages/_Search"), "<Control> I", on_tree_filter_search_changed, MI_FILTER_SEARCH , "<CheckItem>"},
   { N_("/_Packages/s3"), NULL , NULL,    0, "<Separator>"},
+  { N_("/Packages/Show _Info"), "<Control> I", on_package_info_clicked, MI_PACKAGES_INFO , "<Item>"},
+  { N_("/_Packages/s4"), NULL , NULL,    0, "<Separator>"},
   { N_("/Packages/_Update lists"), "<Control> U", on_packages_update_clicked, MI_PACKAGES_UPDATE , "<Item>"},
   { N_("/Packages/Upgrade _System"), "", on_system_update_clicked, MI_PACKAGES_UPGRADE, "<Item>"},
   { N_("/_Packages/s3"), NULL , NULL,    0, "<Separator>"},
@@ -215,10 +226,10 @@
 GtkWidget *
 progress_dialog (gchar * text, GdkPixbuf * pixbuf)
 {
-GtkWidget *window;
-GtkWidget *label;
-GtkWidget *image;
-GtkWidget *hbox;
+	GtkWidget *window;
+	GtkWidget *label;
+	GtkWidget *image;
+	GtkWidget *hbox;
 	
 	window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 	hbox = gtk_hbox_new (FALSE, 0);
@@ -227,6 +238,7 @@
 
 	gtk_window_set_type_hint (GTK_WINDOW (window),
 				  GDK_WINDOW_TYPE_HINT_DIALOG);
+	gtk_window_set_title (GTK_WINDOW (window), _("Working"));
 
 	gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
 
@@ -381,9 +393,9 @@
 
 void update_tree(void)
 {
-guint id;
-int i;
-GtkTreeIter iter;
+	guint id;
+	int i;
+	GtkTreeIter iter;
 
 	id = gtk_statusbar_get_context_id(GTK_STATUSBAR(sbar),"upd");
 	gtk_statusbar_push(GTK_STATUSBAR(sbar),
@@ -392,10 +404,6 @@
 	gtk_tree_store_clear(GTK_TREE_STORE(store));
 	
 	for (i=0; i<pkg_count; i++) {
-		if (((tree_filter & TREE_SHOW_INST) && (pkg_info[i].status == SS_INSTALLED))
-			|| ((tree_filter & TREE_SHOW_NOTINST) && (pkg_info[i].status != SS_INSTALLED)))		
-			continue;
-		
 		gtk_tree_store_append (store, &iter, NULL);
 	
 		gtk_tree_store_set (store, &iter,
@@ -412,14 +420,137 @@
 
 void on_tree_filter_changed(GtkCheckMenuItem *menuitem, gpointer user_data)
 {
-	tree_filter =
-		!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(miFilterInst)) *
-		TREE_SHOW_INST +
-		!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(miFilterNotInst)) *
-		TREE_SHOW_NOTINST;
-	update_tree();
+	if (filter)
+		gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filter));
 }
 
+gboolean filter_visible_func (GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
+{
+	gboolean installed;
+	gboolean not_installed;
+	GValue value_installed = { 0, };
+	GValue value_name = { 0, };
+	const gchar *pkgname;
+
+	installed = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(miFilterInst));
+	not_installed = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(miFilterNotInst));
+        
+	gtk_tree_model_get_value (model, iter, COL_INSTALLED, &value_installed);
+        
+	if (g_value_get_boolean (&value_installed)) {
+		/* Package is installed */
+		if (!installed)
+			return FALSE;
+		} else {
+		/* Package is not installed */
+		if (!not_installed)
+			return FALSE;
+	}
+
+	if (!filter_term)
+		return TRUE;
+
+	gtk_tree_model_get_value (model, iter, COL_NAME, &value_name);
+
+	pkgname = g_value_get_string (&value_name);
+
+#ifdef ENABLE_PCRE
+	pcre *re;
+	gint ret;
+	const gchar *error;
+	gint error_offset;
+
+	if (is_regexp) {
+		re = pcre_compile (filter_term, 0, &error, &error_offset, NULL);
+
+		if (re) {
+			ret = pcre_exec (re, NULL, pkgname, strlen (pkgname), 0, 0, NULL, 0); 
+
+			g_free (re);
+
+			if (ret >= 0) {
+				return TRUE;
+			}
+		}
+
+		return FALSE;
+	}
+#endif
+
+	if (strstr (pkgname, filter_term))
+		return TRUE;
+
+	return FALSE;
+}
+
+void set_filter_term (const gchar *text, gboolean regexp)
+{
+	if (filter_term) {
+		g_free (filter_term);
+	}
+	
+	filter_term = g_strdup (text);
+
+#ifdef ENABLE_PCRE
+	is_regexp = regexp;
+#endif
+
+	gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filter));
+}
+
+void search_entry_activated (GtkEntry *entry, gpointer user_data)
+{
+	GtkDialog *dialog = user_data;
+
+	gtk_dialog_response (dialog, GTK_RESPONSE_ACCEPT);
+}
+
+void on_tree_filter_search_changed (GtkCheckMenuItem *menuitem, gpointer user_data)
+{
+	GtkWidget *dialog;
+	GtkWidget *entry;
+	const gchar *text;
+#ifdef ENABLE_PCRE
+	GtkWidget *checkbutton;
+#endif
+
+	if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (miFilterSearch))) {
+		dialog = gtk_dialog_new_with_buttons (_("Search term:"),
+			GTK_WINDOW (fMain),
+			GTK_DIALOG_DESTROY_WITH_PARENT,
+		        GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+			GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+			NULL);
+		entry = gtk_entry_new ();
+		g_signal_connect (G_OBJECT (entry), "activate", G_CALLBACK (search_entry_activated), dialog);
+		gtk_widget_show (entry);
+		gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), entry);
+#ifdef ENABLE_PCRE
+		checkbutton = gtk_check_button_new_with_label (_("Regular expression"));
+		gtk_widget_show (checkbutton);
+		gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), checkbutton);
+#endif
+		if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
+			text = gtk_entry_get_text (GTK_ENTRY (entry));
+			if (strlen (text)) {
+#ifdef ENABLE_PCRE			
+				set_filter_term (text, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbutton)));
+#else
+				set_filter_term (text, FALSE);
+#endif
+			} else {
+				gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (miFilterSearch), FALSE);
+			}
+		} else {
+			gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (miFilterSearch), FALSE);
+                }
+		gtk_widget_destroy (dialog);
+	} else {
+		set_filter_term (NULL, FALSE);
+	}
+		
+        
+}
 
 void on_about_clicked (GtkWidget * w)
 {
@@ -740,9 +871,9 @@
 
 void on_package_info_clicked(GtkButton *button, gpointer user_data)
 {
-GtkTreeIter iter;
-GtkTreeSelection *sel;
-char *name = NULL;
+	GtkTreeIter iter;
+	GtkTreeSelection *sel;
+	char *name = NULL;
 	
 	sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
 	
@@ -848,7 +979,7 @@
 	selection = gtk_tree_view_get_selection (treeview);
 	if (gtk_tree_selection_get_selected (selection, NULL, &iter) == FALSE) 
 		return FALSE;
-	gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, COL_VERSION, &version, -1);
+	gtk_tree_model_get (GTK_TREE_MODEL (filter), &iter, COL_VERSION, &version, -1);
 	gtk_statusbar_push(GTK_STATUSBAR(sbar),0,version);
 
 	return TRUE;
@@ -882,6 +1013,8 @@
 		MI_FILTER_INST);
 	miFilterNotInst = gtk_item_factory_get_item_by_action(itemfactory,
 		MI_FILTER_NOTINST);
+	miFilterSearch = gtk_item_factory_get_item_by_action(itemfactory,
+		MI_FILTER_SEARCH);
 	
 	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(miFilterInst),TRUE); 
 	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(miFilterNotInst),TRUE); 
@@ -984,7 +1117,9 @@
 	gtk_box_pack_start(GTK_BOX(vbox), cur, TRUE, TRUE, 0);	
 
 	/* packages tree */
-	treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
+	filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
+	gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter), filter_visible_func, NULL, NULL);
+	treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (filter));
 	gtk_tree_view_set_reorderable(GTK_TREE_VIEW(treeview),FALSE);
 	gtk_tree_view_set_rules_hint (GTK_TREE_VIEW(treeview),TRUE);
 	gtk_container_add(GTK_CONTAINER(cur),treeview);