Index: navit/gui/internal/gui_internal.c
===================================================================
--- navit/gui/internal/gui_internal.c	(revision 4499)
+++ navit/gui/internal/gui_internal.c	(working copy)
@@ -2245,15 +2245,69 @@
 		type_none}},
 };
 
-union poi_param {
-	guint i;
-	struct {
+
+/*
+ *  Get a utf-8 string, return the same prepared for case insensetive search. Result shoud be g_free()d after use.
+ */
+
+static char *
+removecase(char *s) 
+{
+	char *r;
+	r=g_utf8_casefold(s,-1);
+	return r;
+}
+
+struct poi_param {
 		unsigned char sel, selnb, pagenb, dist;
-	} p;
+		char *filterstr; /* Filter string, casefold()ed and divided into substrings at the spaces, which are replaced by ASCII 0*/
+		GList *filter; /* list of pointers to individual substrings of filterstr */
 };
 
+
+/**
+ * @brief Free poi_param structure.
+ *
+ * @param p reference to the object to be freed.
+ */
+static void
+gui_internal_poi_param_free(void *p) 
+{
+	if(((struct poi_param *)p)->filterstr)
+	   g_free(((struct poi_param *)p)->filterstr);
+	if(((struct poi_param *)p)->filter)
+	   g_list_free(((struct poi_param *)p)->filter);
+	g_free(p);
+};
+
+/**
+ * @brief Clone poi_param structure.
+ *
+ * @param p reference to the object to be cloned.
+ * @return  Cloned object reference.
+ */
+static struct poi_param *
+gui_internal_poi_param_clone(struct poi_param *p) 
+{
+	struct poi_param *r=g_new(struct poi_param,1);
+	GList *l=p->filter;
+	memcpy(r,p,sizeof(struct poi_param));
+	r->filter=NULL;
+	r->filterstr=NULL;
+	if(p->filterstr)
+		r->filterstr=g_strdup(p->filterstr);
+	while(l) {
+		r->filter=g_list_append(r->filter, r->filterstr + ((char*)(l->data) - p->filterstr) );
+		l=g_list_next(l);
+	}
+	return r;
+};
+
+
 static void gui_internal_cmd_pois(struct gui_priv *this, struct widget *wm, void *data);
+static void gui_internal_cmd_pois_filter(struct gui_priv *this, struct widget *wm, void *data);
 
+
 static struct widget *
 gui_internal_cmd_pois_selector(struct gui_priv *this, struct pcoord *c, int pagenb)
 {
@@ -2269,17 +2323,27 @@
 	nrows=nitems/wl->cols + (nitems%wl->cols>0);
 	wl->h=this->icon_l*nrows;
 	for (i = 0 ; i < nitems ; i++) {
-		union poi_param p;
-		p.p.sel = 1;
-		p.p.selnb = i;
-		p.p.pagenb = pagenb;
-		p.p.dist = 0;
+		struct poi_param *p=g_new(struct poi_param,1);
+		p->sel = 1;
+		p->selnb = i;
+		p->pagenb = pagenb;
+		p->dist = 0;
+		p->filter=NULL;
+		p->filterstr=NULL;
 		gui_internal_widget_append(wl, wb=gui_internal_button_new_with_callback(this, NULL,
 			image_new_s(this, selectors[i].icon), gravity_left_center|orientation_vertical,
-			gui_internal_cmd_pois, GUINT_TO_POINTER(p.i)));
+			gui_internal_cmd_pois, p));
 		wb->c=*c;
+		wb->data_free=gui_internal_poi_param_free;
 		wb->bt=10;
 	}
+
+	gui_internal_widget_append(wl, wb=gui_internal_button_new_with_callback(this, NULL,
+			image_new_s(this, "gui_about"), gravity_left_center|orientation_vertical,
+			gui_internal_cmd_pois_filter, NULL));
+	wb->c=*c;
+	wb->bt=10;
+	
 	gui_internal_widget_pack(this,wl);
 	return wl;
 }
@@ -2334,21 +2398,49 @@
 }
 
 static int
-gui_internal_cmd_pois_item_selected(struct selector *sel, enum item_type type)
+gui_internal_cmd_pois_item_selected(struct poi_param *param, struct item *item)
 {
 	enum item_type *types;
-	if (type >= type_line)
+	struct selector *sel = param->sel? &selectors[param->selnb]: NULL;
+	enum item_type type=item->type;
+	struct attr attr;
+	int match=0;
+	if (type >= type_line && param->filter==NULL)
 		return 0;
-	if (! sel || !sel->types)
-		return 1;
-	types=sel->types;
-	while (*types != type_none) {
-		if (type >= types[0] && type <= types[1]) {
-			return 1;
+	if (! sel || !sel->types) {
+		match=1;
+	} else {
+		types=sel->types;
+		while (*types != type_none) {
+			if (item->type >= types[0] && item->type <= types[1]) {
+				return 1;
+			}
+			types+=2;
 		}
-		types+=2;
 	}
-	return 0;
+	if (param->filter) {
+		char *long_name, *s;
+		GList *f;
+		
+		if (item_attr_get(item, attr_label, &attr)) 
+			s=g_strdup_printf("%s %s", item_to_name(item->type), attr.u.str);
+		else
+			s=g_strdup(item_to_name(item->type));
+		long_name=removecase(s);
+		g_free(s);
+                item_attr_rewind(item);
+                
+		for(s=long_name,f=param->filter;f && s;f=g_list_next(f)) {
+			s=strstr(s,f->data);
+			if(!s) 
+				break;
+			s=g_utf8_strchr(s,-1,' ');
+		}
+		if(f)
+			match=0;
+		g_free(long_name);
+	}
+	return match;
 }
 
 struct item_data {
@@ -2372,13 +2464,100 @@
 	w->data=wm->data;
 	w->c=wm->c;
 	w->w=wm->w;
+	wm->data_free=NULL;
 	gui_internal_back(this, NULL, NULL);
-	gui_internal_cmd_pois(this, w, NULL);
+	gui_internal_cmd_pois(this, w, w->data);
 	free(w);
 }
 
+/**
+ * @brief apply POIs text filter.
+ *
+ * @param this The graphics context.
+ * @param wm called widget.
+ * @param data event data (pointer to editor widget containg filter text).
+ */
+static void
+gui_internal_cmd_pois_filter_do(struct gui_priv *this, struct widget *wm, void *data) 
+{
+	struct widget *w=data;
+	struct poi_param *param;
+	char *s1, *s2;
+	
+	if(!w->text)
+		return;
+	
+	if(w->data) {
+		param=gui_internal_poi_param_clone(w->data);
+		param->pagenb=0;
+	} else {
+		param=g_new0(struct poi_param,1);
+	}
+	param->filterstr=removecase(w->text);
+	s1=param->filterstr;
+	do {
+		s2=g_utf8_strchr(s1,-1,' ');
+		if(s2)
+			*s2++=0;
+		param->filter=g_list_append(param->filter,s1);
+		if(s2) {
+			while(*s2==' ')
+				s2++;
+		}
+		s1=s2;
+	} while(s2 && *s2);
 
+	gui_internal_cmd_pois(this,w,param);
+	gui_internal_poi_param_free(param);
+}
+
+
+/**
+ * @brief POIs filter dialog.
+ *
+ * @param this The graphics context.
+ * @param wm called widget.
+ * @param data event data.
+ */
 static void
+gui_internal_cmd_pois_filter(struct gui_priv *this, struct widget *wm, void *data) 
+{
+	struct widget *wb, *w, *wr, *wk, *we, *wc;
+	int keyboard_mode=2;
+	wb=gui_internal_menu(this,"Filter");
+	w=gui_internal_box_new(this, gravity_center|orientation_vertical|flags_expand|flags_fill);
+	gui_internal_widget_append(wb, w);
+	wr=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
+        gui_internal_widget_append(w, wr);
+        we=gui_internal_box_new(this, gravity_left_center|orientation_horizontal|flags_fill);
+        gui_internal_widget_append(wr, we);
+
+	gui_internal_widget_append(we, wk=gui_internal_label_new(this, NULL));
+	wk->state |= STATE_EDIT|STATE_EDITABLE;
+	wk->background=this->background;
+	wk->flags |= flags_expand|flags_fill;
+	wk->name=g_strdup("POIsFilter");
+	wk->c=wm->c;
+	gui_internal_widget_append(we, wb=gui_internal_image_new(this, image_new_xs(this, "gui_active")));
+	
+	wb->state |= STATE_SENSITIVE;
+	wb->func = gui_internal_cmd_pois_filter_do;
+	wb->data=wk;
+	if (this->keyboard)
+		gui_internal_widget_append(w, gui_internal_keyboard(this,keyboard_mode));
+	gui_internal_menu_render(this);
+
+
+}
+
+/**
+ * @brief Do POI search specified by poi_param and display POIs found
+ *
+ * @param this The graphics context.
+ * @param wm called widget.
+ * @param data event data, reference to poi_param or NULL.
+ */
+static void
 gui_internal_cmd_pois(struct gui_priv *this, struct widget *wm, void *data)
 {
 	struct map_selection *sel,*selm;
@@ -2389,25 +2568,43 @@
 	struct item *item;
 	struct widget *wi,*w,*w2,*wb, *wtable, *row;
 	enum projection pro=wm->c.pro;
-	union poi_param param = {.i = GPOINTER_TO_UINT(wm->data)};
-	int idist,dist=10000*(param.p.dist+1);
-	struct selector *isel = param.p.sel? &selectors[param.p.selnb]: NULL;
-	int pagenb = param.p.pagenb;
-	int prevdist=param.p.dist*10000;
+	struct poi_param *param;
+	int param_free=0;
+	int idist,dist;
+	struct selector *isel;
+	int pagenb;
+	int prevdist;
 	const int pagesize = 50; // Starting value and increment of count of items to be extracted
-	int maxitem = pagesize*(pagenb+1), it = 0, i;
-	struct item_data *items= g_new0( struct item_data, maxitem);
+	int maxitem, it = 0, i;
+	struct item_data *items;
 	struct fibheap* fh = fh_makekeyheap();
 	int cnt = 0;
 	struct table_data *td;
 	int width=wm->w;
-	dbg(2, "Params: sel = %i, selnb = %i, pagenb = %i, dist = %i\n",
-		param.p.sel, param.p.selnb, param.p.pagenb, param.p.dist);
+	
+	
+	if(data) {
+	  param = data;
+	} else {
+	  param = g_new0(struct poi_param,1);
+	  param_free=1;
+	}
+	
+	dist=10000*(param->dist+1);
+	isel = param->sel? &selectors[param->selnb]: NULL;
+	pagenb = param->pagenb;
+	prevdist=param->dist*10000;
+	maxitem = pagesize*(pagenb+1);
+	items= g_new0( struct item_data, maxitem);
+	
+	
+	dbg(0, "Params: sel = %i, selnb = %i, pagenb = %i, dist = %i, filterstr = %s\n",
+		param->sel, param->selnb, param->pagenb, param->dist, param->filterstr);
 
 	wb=gui_internal_menu(this, isel ? isel->name : _("POIs"));
 	w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
 	gui_internal_widget_append(wb, w);
-	if (!isel)
+	if (!isel && !param->filter)
 		gui_internal_widget_append(w, gui_internal_cmd_pois_selector(this,&wm->c,pagenb));
 	w2=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
 	gui_internal_widget_append(w, w2);
@@ -2422,7 +2619,7 @@
 		dbg(2,"mr=%p\n", mr);
 		if (mr) {
 			while ((item=map_rect_get_item(mr))) {
-				if (gui_internal_cmd_pois_item_selected(isel, item->type) &&
+				if (gui_internal_cmd_pois_item_selected(param, item) &&
 				    item_coord_get_pro(item, &c, 1, pro) &&
 				    coord_rect_contains(&sel->u.c_rect, &c)  &&
 				    (idist=transform_distance(pro, &center, &c)) < dist) {
@@ -2504,18 +2701,21 @@
 	// Add an entry for more POI
 	struct widget *wl,*wt;
 	char buffer[32];
+	struct poi_param *paramnew;
+	paramnew=gui_internal_poi_param_clone(param);
 	wl=gui_internal_box_new(this, gravity_left_center|orientation_horizontal|flags_fill);
 	if (it == maxitem) {
-		param.p.pagenb++;
-		snprintf(buffer, sizeof(buffer), "Get more (up to %d items)...", (param.p.pagenb+1)*pagesize);
+		paramnew->pagenb++;
+		snprintf(buffer, sizeof(buffer), "Get more (up to %d items)...", (paramnew->pagenb+1)*pagesize);
 	} else {
-		param.p.dist++;
-		snprintf(buffer, sizeof(buffer), "Set search distance to %i km", 10*(param.p.dist+1));
+		paramnew->dist++;
+		snprintf(buffer, sizeof(buffer), "Set search distance to %i km", 10*(paramnew->dist+1));
 	}
 	wt=gui_internal_label_new(this, buffer);
 	gui_internal_widget_append(wl, wt);
 	wl->func=gui_internal_cmd_pois_more;
-	wl->data=GUINT_TO_POINTER(param.i);
+	wl->data=paramnew;
+	wl->data_free=gui_internal_poi_param_free;
 	wl->state |= STATE_SENSITIVE;
 	wl->c = wm->c;
 	row = gui_internal_widget_table_row_new(this,
@@ -2537,7 +2737,8 @@
 		}
 	}
 	gui_internal_menu_render(this);
-
+        if(param_free)
+        	g_free(param);
 }
 #endif /* _MSC_VER */
 

