summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlains <lains@caramail.com>2019-03-05 16:26:59 +0100
committerjkoan <jkoan@users.noreply.github.com>2019-03-05 16:26:59 +0100
commitcc781eec9b8825d1ffbbb4798e2b86ac2d08be62 (patch)
tree2a15abeec06946b26b6fc768211e420bdae307df
parent5352c402c7aeef45206d99577217f20a283fb8b1 (diff)
downloadnavit-cc781eec9b8825d1ffbbb4798e2b86ac2d08be62.tar.gz
Refactor:GUI/GTK:Adding pointer and label when displaying POI on map (#729)
* Moving get_search_results_map from internal gui to generic navit functions * Moving square_shape_str() and populate_search_results_map() in generic files (not making them gui_internal-specific) * Adding GList cleanup after adding search results to a map, setting result names properly in GTK POI * Using common navit_populate_search_results_map() in internal GUI (factorizing code) * Adding doxygen comments * Reverting added empty lines * Applying expected style (indentation) * Adding dedicated code to free payload for GList (instead of using unavailable g_list_free_full()) * Avoiding for loop initial declarations * Remove obsolete FIXME comment * Minor tweaking doxygen comments and variables * Removing highlighted points on result map when starting routing
-rw-r--r--navit/coord.h12
-rw-r--r--navit/gui/gtk/destination.c50
-rw-r--r--navit/gui/gtk/gui_gtk_poi.c71
-rw-r--r--navit/gui/gtk/gui_gtk_window.c1
-rw-r--r--navit/gui/internal/gui_internal.c200
-rw-r--r--navit/navit.c132
-rw-r--r--navit/navit.h2
-rw-r--r--navit/util.c64
-rw-r--r--navit/util.h3
9 files changed, 336 insertions, 199 deletions
diff --git a/navit/coord.h b/navit/coord.h
index cff549e95..8387462a2 100644
--- a/navit/coord.h
+++ b/navit/coord.h
@@ -36,6 +36,18 @@ struct coord {
int y; /*!< Y-Value */
};
+/**
+ * @brief An integer mercator coordinate packed with a text label
+ *
+ * This structure holds information about an item (coordinates & label) on a map. This can be
+ * used in a list as group of points to display as search results on a map.
+ * It is used to structure input data for function navit_populate_search_results_map()
+ */
+struct lcoord {
+ struct coord c; /*!< The coordinates for this item */
+ char *label; /*!< A label to associate to this item */
+};
+
/*! A integer mercator coordinate carrying its projection */
struct pcoord {
enum projection pro;
diff --git a/navit/gui/gtk/destination.c b/navit/gui/gtk/destination.c
index 5f52e042b..6a0fbb5b7 100644
--- a/navit/gui/gtk/destination.c
+++ b/navit/gui/gtk/destination.c
@@ -50,22 +50,6 @@ static struct search_param {
GtkTreeModel *liststore2;
} search_param;
-static void button_map(GtkWidget *widget, struct search_param *search) {
- GtkTreePath *path;
- GtkTreeViewColumn *focus_column;
- struct pcoord *c=NULL;
- GtkTreeIter iter;
-
- gtk_tree_view_get_cursor(GTK_TREE_VIEW(search->treeview), &path, &focus_column);
- if(!path)
- return;
- if(!gtk_tree_model_get_iter(search->liststore2, &iter, path))
- return;
- gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), &iter, COL_COUNT, &c, -1);
- if (c) {
- navit_set_center(search->nav, c, 1);
- }
-}
static char *description(struct search_param *search, GtkTreeIter *iter) {
char *desc,*car,*postal,*town,*street;
@@ -89,6 +73,39 @@ static char *description(struct search_param *search, GtkTreeIter *iter) {
return desc;
}
+static void button_map(GtkWidget *widget, struct search_param *search) {
+ GtkTreePath *path;
+ GtkTreeViewColumn *focus_column;
+ struct pcoord *point=NULL; /* A pointer on the geographical position of the selected map point */
+ GtkTreeIter iter;
+ char *label;
+ GList* p;
+
+ gtk_tree_view_get_cursor(GTK_TREE_VIEW(search->treeview), &path, &focus_column);
+ if(!path)
+ return;
+ if(!gtk_tree_model_get_iter(search->liststore2, &iter, path))
+ return;
+ gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), &iter, COL_COUNT, &point, -1);
+ if (point) {
+ GList* list = NULL;
+ struct lcoord *result = g_new0(struct lcoord, 1);
+ result->c.x=point->x;
+ result->c.y=point->y;
+ result->label=description(search, &iter); /* Allocated here, freed by invoking g_free() below when parsing the GList */
+ list = g_list_prepend(list, result);
+ navit_populate_search_results_map(search->nav, list, NULL);
+ /* Parse the GList starting at list and free all payloads before freeing the list itself */
+ for(p=list; p; p=g_list_next(p)) {
+ if (((struct lcoord *)(p->data))->label)
+ g_free(((struct lcoord *)(p->data))->label);
+ }
+ g_list_free(list);
+
+ navit_set_center(search->nav, point, 1);
+ }
+}
+
static void button_destination(GtkWidget *widget, struct search_param *search) {
struct pcoord *c=NULL;
GtkTreeIter iter;
@@ -99,6 +116,7 @@ static void button_destination(GtkWidget *widget, struct search_param *search) {
gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), &iter, COL_COUNT, &c, -1);
if (c) {
desc=description(search, &iter);
+ navit_populate_search_results_map(search->nav, NULL, NULL); /* Remove any highlighted point on the map */
navit_set_destination(search->nav, c, desc, 1);
g_free(desc);
}
diff --git a/navit/gui/gtk/gui_gtk_poi.c b/navit/gui/gtk/gui_gtk_poi.c
index 503bc321f..265f1f28e 100644
--- a/navit/gui/gtk/gui_gtk_poi.c
+++ b/navit/gui/gtk/gui_gtk_poi.c
@@ -37,6 +37,9 @@
#include "navigation.h" /* for FEET_PER_METER and other conversion factors. */
+/**
+ * @brief Context passed around POI search function
+ */
static struct gtk_poi_search {
GtkWidget *entry_distance;
GtkWidget *label_distance;
@@ -51,6 +54,12 @@ static struct gtk_poi_search {
struct navit *nav;
} gtk_poi_search;
+/**
+ * @brief Get a pixbuf representing an icon for the catalog
+ *
+ * @param name The name of the icon to use (eg: "pharmacy.png"
+ * @return A pixbuf containing this icon of NULL if the icon could not be loaded
+ */
static GdkPixbuf *geticon(const char *name) {
GdkPixbuf *icon=NULL;
GError *error=NULL;
@@ -217,7 +226,14 @@ static void treeview_poi_reload(GtkWidget *widget, struct gtk_poi_search *search
gtk_tree_view_set_model(GTK_TREE_VIEW (search->treeview_poi), model_poi(search));
}
-/** Set the selected POI as destination. */
+/**
+ * @brief Callback invoked when 'Destination' is clicked in a POI contextual window
+ *
+ * Set the selected POI as destination
+ *
+ * @param widget The widget that has been clicked
+ * @param search A pointer to private data containing the POI search context
+ */
static void button_destination_clicked(GtkWidget *widget, struct gtk_poi_search *search) {
GtkTreePath *path;
GtkTreeViewColumn *focus_column;
@@ -241,6 +257,7 @@ static void button_destination_clicked(GtkWidget *widget, struct gtk_poi_search
gtk_tree_model_get(GTK_TREE_MODEL(search->store_poi_sorted), &iter, 3, &lat, -1);
gtk_tree_model_get(GTK_TREE_MODEL(search->store_poi_sorted), &iter, 4, &lon, -1);
sprintf(buffer, _("POI %s. %s"), category, label);
+ navit_populate_search_results_map(search->nav, NULL, NULL); /* Remove any highlighted point on the map */
struct pcoord dest;
dest.x=lat;
@@ -250,28 +267,58 @@ static void button_destination_clicked(GtkWidget *widget, struct gtk_poi_search
dbg(lvl_debug,_("Set destination to %ld, %ld "),lat,lon);
}
-/* Show the POI's position in the map. */
+/**
+ * @brief Callback invoked when 'Map' is clicked in a POI contextual window
+ *
+ * Show the POI's position in the map
+ *
+ * @param widget The widget that has been clicked
+ * @param search A pointer to private data containing the POI search context
+ */
static void button_map_clicked(GtkWidget *widget, struct gtk_poi_search *search) {
GtkTreePath *path;
GtkTreeViewColumn *focus_column;
GtkTreeIter iter;
long int lat,lon;
+ char *label;
+ GList* p;
gtk_tree_view_get_cursor(GTK_TREE_VIEW(search->treeview_poi), &path, &focus_column);
if(!path) return;
if(!gtk_tree_model_get_iter(GTK_TREE_MODEL(search->store_poi_sorted), &iter, path)) return;
+ gtk_tree_model_get(GTK_TREE_MODEL(search->store_poi_sorted), &iter, 2, &label, -1);
gtk_tree_model_get(GTK_TREE_MODEL(search->store_poi_sorted), &iter, 3, &lat, -1);
gtk_tree_model_get(GTK_TREE_MODEL(search->store_poi_sorted), &iter, 4, &lon, -1);
- struct pcoord dest;
- dest.x=lat;
- dest.y=lon;
- dest.pro=1;
- navit_set_center(search->nav, &dest,1);
+ struct pcoord point; /* The geographical position of the selected POI point */
+ point.x=lat;
+ point.y=lon;
+ point.pro=1;
+ GList* list = NULL;
+ struct lcoord *result = g_new0(struct lcoord, 1);
+ result->c.x=lat;
+ result->c.y=lon;
+ result->label=g_strdup(label);
+ list = g_list_prepend(list, result);
+ navit_populate_search_results_map(search->nav, list, NULL);
+ /* Parse the GList starting at list and free all payloads before freeing the list itself */
+ for(p=list; p; p=g_list_next(p)) {
+ if (((struct lcoord *)(p->data))->label)
+ g_free(((struct lcoord *)(p->data))->label);
+ }
+ g_list_free(list);
+ navit_set_center(search->nav, &point,1);
dbg(lvl_debug,_("Set map to %ld, %ld "),lat,lon);
}
-/** Set POI as the first "visit before". */
+/**
+ * @brief Callback invoked when 'Visit before' is clicked in a POI contextual window
+ *
+ * Set POI as a waypoint to visit before an existing destination
+ *
+ * @param widget The widget that has been clicked
+ * @param search A pointer to private data containing the POI search context
+ */
static void button_visit_clicked(GtkWidget *widget, struct gtk_poi_search *search) {
GtkTreePath *path;
GtkTreeViewColumn *focus_column;
@@ -284,6 +331,7 @@ static void button_visit_clicked(GtkWidget *widget, struct gtk_poi_search *searc
gtk_tree_model_get(GTK_TREE_MODEL(search->store_poi_sorted), &iter, 3, &lat, -1);
gtk_tree_model_get(GTK_TREE_MODEL(search->store_poi_sorted), &iter, 4, &lon, -1);
dbg(lvl_debug,_("Set next visit to %ld, %ld "),lat,lon);
+ navit_populate_search_results_map(search->nav, NULL, NULL); /* Remove any highlighted point on the map */
struct pcoord dest;
dest.x=lat;
@@ -292,7 +340,11 @@ static void button_visit_clicked(GtkWidget *widget, struct gtk_poi_search *searc
popup_set_visitbefore(search->nav,&dest,0);
}
-/** Create UI and connect objects to functions. */
+/**
+ * @brief Create the POI search UI window and connect objects to functions
+ *
+ * @param nav The navit instance
+ */
void gtk_gui_poi(struct navit *nav) {
GtkWidget *window2,*vbox, *keyboard, *table;
GtkWidget *label_category, *label_poi;
@@ -302,6 +354,7 @@ void gtk_gui_poi(struct navit *nav) {
struct gtk_poi_search *search=&gtk_poi_search;
search->nav=nav;
+ navit_populate_search_results_map(search->nav, NULL, NULL); /* Remove any highlighted point on the map */
window2 = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window2),_("POI search"));
gtk_window_set_wmclass (GTK_WINDOW (window2), "navit", "Navit");
diff --git a/navit/gui/gtk/gui_gtk_window.c b/navit/gui/gtk/gui_gtk_window.c
index 782add46f..1e57004d0 100644
--- a/navit/gui/gtk/gui_gtk_window.c
+++ b/navit/gui/gtk/gui_gtk_window.c
@@ -323,6 +323,7 @@ static void gui_gtk_action_activate(GtkAction *action, struct action_cb_data *da
if(data->attr.type == attr_destination) {
char * label;
g_object_get(G_OBJECT(action), "label", &label,NULL);
+ navit_populate_search_results_map(data->gui->nav, NULL, NULL); /* Remove any highlighted point on the map */
navit_set_destination(data->gui->nav, data->attr.u.pcoord, label, 1);
g_free(label);
}
diff --git a/navit/gui/internal/gui_internal.c b/navit/gui/internal/gui_internal.c
index afae9a9f1..726a03d17 100644
--- a/navit/gui/internal/gui_internal.c
+++ b/navit/gui/internal/gui_internal.c
@@ -895,125 +895,6 @@ static void gui_internal_cmd_view_in_browser(struct gui_priv *this, struct widge
}
/**
- * @brief Get the search result map (and create it if it does not exist)
- *
- * @param this The GUI context
- *
- * @return A pointer to the map named "search_results" or NULL if there wasa failure
- */
-static struct map *get_search_results_map(struct gui_priv *this) {
-
- struct mapset *ms;
- struct map *map;
-
- ms=navit_get_mapset(this->nav);
-
- if(!ms)
- return NULL;
-
- map=mapset_get_map_by_name(ms, "search_results");
- if(!map) {
- struct attr *attrs[10], attrmap;
- enum attr_type types[]= {attr_position_longitude,attr_position_latitude,attr_label,attr_none};
- int i;
-
- attrs[0]=g_new0(struct attr,1);
- attrs[0]->type=attr_type;
- attrs[0]->u.str="csv";
-
- attrs[1]=g_new0(struct attr,1);
- attrs[1]->type=attr_name;
- attrs[1]->u.str="search_results";
-
- attrs[2]=g_new0(struct attr,1);
- attrs[2]->type=attr_charset;
- attrs[2]->u.str="utf-8";
-
- attrs[3]=g_new0(struct attr,1);
- attrs[3]->type=attr_item_type;
- attrs[3]->u.num=type_found_item;
-
- attrs[4]=g_new0(struct attr,1);
- attrs[4]->type=attr_attr_types;
- attrs[4]->u.attr_types=types;
- attrs[5]=NULL;
-
- attrmap.type=attr_map;
- map=attrmap.u.map=map_new(NULL,attrs);
- if(map)
- mapset_add_attr(ms,&attrmap);
-
- for(i=0; attrs[i]; i++)
- g_free(attrs[i]);
- }
- return map;
-}
-
-/**
- * @brief Optimizes the format of a string, adding carriage returns so that when displayed, the result text zone is roughly as wide as high
- *
- * @param[in,out] s The string to proces (will be modified by this function, but length will be unchanged)
- */
-static void square_shape_str(char *s) {
- char *c;
- char *last_break;
- unsigned int max_cols = 0;
- unsigned int cur_cols = 0;
- unsigned int max_rows = 0;
- unsigned int surface;
- unsigned int target_cols;
-
- if (!s)
- return;
- for (c=s; *c!='\0'; c++) {
- if (*c==' ') {
- if (max_cols < cur_cols)
- max_cols = cur_cols;
- cur_cols = 0;
- max_rows++;
- } else
- cur_cols++;
- }
- if (max_cols < cur_cols)
- max_cols = cur_cols;
- if (cur_cols) /* If last line does not end with CR, add it to line numbers anyway */
- max_rows++;
- /* Give twice more room for rows (hence the factor 2 below)
- * This will render as a rectangular shape, taking more horizontal space than vertical */
- surface = max_rows * 2 * max_cols;
- target_cols = uint_sqrt(surface);
-
- if (target_cols < max_cols)
- target_cols = max_cols;
-
- target_cols = target_cols + target_cols/10; /* Allow 10% extra on columns */
- dbg(lvl_debug, "square_shape_str(): analyzing input text=\"%s\". max_rows=%u, max_cols=%u, surface=%u, target_cols=%u",
- s, max_rows, max_cols, max_rows * 2 * max_cols, target_cols);
-
- cur_cols = 0;
- last_break = NULL;
- for (c=s; *c!='\0'; c++) {
- if (*c==' ') {
- if (cur_cols>=target_cols) { /* This line is too long, break at the previous non alnum character */
- if (last_break) {
- *last_break =
- '\n'; /* Replace the previous non alnum character with a line break, this creates a new line and prevents the previous line from being too long */
- cur_cols = c-last_break;
- }
- }
- last_break = c; /* Record this position as a candidate to insert a line break */
- }
- cur_cols++;
- }
- if (cur_cols>=target_cols && last_break) {
- *last_break =
- '\n'; /* Replace the previous non alnum character with a line break, this creates a new line and prevents the previous line from being too long */
- }
-
- dbg(lvl_debug, "square_shape_str(): output text=\"%s\"", s);
-}
-
-/**
* @brief Create a map rect highlighting one of multiple points provided in argument @data and displayed using
* the style type_found_item (name for each point will also be displayed aside)
*
@@ -1024,28 +905,10 @@ static void square_shape_str(char *s) {
*/
static void gui_internal_prepare_search_results_map(struct gui_priv *this, struct widget *table, struct coord_rect *r) {
struct widget *w;
- struct map *map;
- struct map_rect *mr;
- struct item *item;
- GList *l;
+ GList *l; /* Cursor in the list of widgets */
+ GList* list = NULL; /* List we will create to store the points to add to the result map */
struct attr a;
- int count;
- char *name_label;
-
- map = get_search_results_map(this);
- if(!map)
- return;
-
-
- mr = map_rect_new(map, NULL);
-
- if(!mr)
- return;
-
- /* Clean the map */
- while((item = map_rect_get_item(mr))!=NULL) {
- item_type_set(item,type_none);
- }
+ GList* p;
this->results_map_population=0;
@@ -1053,43 +916,33 @@ static void gui_internal_prepare_search_results_map(struct gui_priv *this, struc
for(w=table; w && w->type!=widget_table; w=w->parent);
if(!w) {
- map_rect_destroy(mr);
dbg(lvl_warning,"Can't find the results table - only map clean up is done.");
- return;
- }
-
- /* Populate the map with search results*/
- for(l=w->children, count=0; l; l=g_list_next(l)) {
- struct widget *wr=l->data;
- if(wr->type==widget_table_row) {
- struct widget *wi=wr->children->data;
- struct item* it;
- if(wi->name==NULL)
- continue;
- dbg(lvl_info,"%s",wi->name);
- it=map_rect_create_item(mr,type_found_item);
- if(it) {
- struct coord c;
- struct attr a;
- c.x=wi->c.x;
- c.y=wi->c.y;
- item_coord_set(it, &c, 1, change_mode_modify);
- a.type=attr_label;
- name_label = g_strdup(wi->name);
- square_shape_str(name_label);
- a.u.str=name_label;
- item_attr_set(it, &a, change_mode_modify);
- if (r) {
- if(!count++)
- r->lu=r->rl=c;
- else
- coord_rect_extend(r,&c);
- }
+ } else {
+ /* Create a GList containing all search results */
+ for(l=w->children; l; l=g_list_next(l)) {
+ struct widget *wr=l->data;
+ if(wr->type==widget_table_row) {
+ struct widget *wi=wr->children->data;
+ if(wi->name==NULL)
+ continue;
+ struct lcoord *result = g_new0(struct lcoord, 1);
+ result->c.x=wi->c.x;
+ result->c.y=wi->c.y;
+ result->label=g_strdup(wi->name);
+ list = g_list_prepend(list, result);
}
}
}
- map_rect_destroy(mr);
- if(!count)
+ this->results_map_population=navit_populate_search_results_map(this->nav, list, r);
+ /* Parse the GList starting at list and free all payloads before freeing the list itself */
+ if (list) {
+ for(p=list; p; p=g_list_next(p)) {
+ if (((struct lcoord *)(p->data))->label)
+ g_free(((struct lcoord *)(p->data))->label);
+ }
+ }
+ g_list_free(list);
+ if(!this->results_map_population)
return;
a.type=attr_orientation;
a.u.num=0;
@@ -1098,7 +951,6 @@ static void gui_internal_prepare_search_results_map(struct gui_priv *this, struc
navit_zoom_to_rect(this->nav,r);
gui_internal_prune_menu(this, NULL);
}
- this->results_map_population=count;
}
/**
diff --git a/navit/navit.c b/navit/navit.c
index 90935786d..1d1b8e664 100644
--- a/navit/navit.c
+++ b/navit/navit.c
@@ -213,6 +213,13 @@ void navit_add_mapset(struct navit *this_, struct mapset *ms) {
this_->mapsets = g_list_append(this_->mapsets, ms);
}
+/**
+ * @brief Get the current mapset
+ *
+ * @param this_ The navit instance
+ *
+ * @return A pointer to the current mapset
+ */
struct mapset *
navit_get_mapset(struct navit *this_) {
if(this_->mapsets) {
@@ -223,6 +230,131 @@ navit_get_mapset(struct navit *this_) {
return NULL;
}
+/**
+ * @brief Get the search result map (and create it if it does not exist)
+ *
+ * @param this_ The navit instance
+ *
+ * @return A pointer to the map named "search_results" or NULL if there wasa failure
+ */
+struct map *navit_get_search_results_map(struct navit *this_) {
+
+ struct mapset *ms;
+ struct map *map;
+
+ ms=navit_get_mapset(this_);
+
+ if(!ms)
+ return NULL;
+
+ map=mapset_get_map_by_name(ms, "search_results");
+ if(!map) {
+ struct attr *attrs[10], attrmap;
+ enum attr_type types[]= {attr_position_longitude,attr_position_latitude,attr_label,attr_none};
+ int i;
+
+ attrs[0]=g_new0(struct attr,1);
+ attrs[0]->type=attr_type;
+ attrs[0]->u.str="csv";
+
+ attrs[1]=g_new0(struct attr,1);
+ attrs[1]->type=attr_name;
+ attrs[1]->u.str="search_results";
+
+ attrs[2]=g_new0(struct attr,1);
+ attrs[2]->type=attr_charset;
+ attrs[2]->u.str="utf-8";
+
+ attrs[3]=g_new0(struct attr,1);
+ attrs[3]->type=attr_item_type;
+ attrs[3]->u.num=type_found_item;
+
+ attrs[4]=g_new0(struct attr,1);
+ attrs[4]->type=attr_attr_types;
+ attrs[4]->u.attr_types=types;
+ attrs[5]=NULL;
+
+ attrmap.type=attr_map;
+ map=attrmap.u.map=map_new(NULL,attrs);
+ if(map)
+ mapset_add_attr(ms,&attrmap);
+
+ for(i=0; attrs[i]; i++)
+ g_free(attrs[i]);
+ }
+ return map;
+}
+
+/**
+ * @brief Populate a map containing one or more search result points
+ *
+ * These search results will be displayed as an overlay on the top of the geographic map.
+ *
+ * @warning Each call to this function will replace currently displayed results, it will not add to them
+ *
+ * @param this_ The navit instance
+ * @param search_results A GList storing {@code struct lcoord} elements to display on the result map
+ * If this argument in NULL, all existing results will be removed from the map
+ * @param[in,out] coord_rect An optional rectangular zone that will be extended to contain all result points
+ * or NULL if no zone needs to be computed
+ * @return The number of results actually added to the map
+ */
+int navit_populate_search_results_map(struct navit *this_, GList *search_results, struct coord_rect *r) {
+ struct map *map;
+ struct map_rect *mr;
+ struct item *item;
+ GList *curr_result = search_results;
+ int count;
+ char *name_label;
+
+ map = navit_get_search_results_map(this_);
+ if(!map)
+ return 0;
+
+ mr = map_rect_new(map, NULL);
+
+ if(!mr)
+ return 0;
+
+ /* Clean the map */
+ while((item = map_rect_get_item(mr))!=NULL) {
+ item_type_set(item,type_none);
+ }
+
+ if(!search_results) {
+ map_rect_destroy(mr);
+ dbg(lvl_warning,"NULL result table - only map clean up is done.");
+ return 0;
+ }
+
+ /* Populate the map with search results*/
+ for(curr_result = search_results, count=0; curr_result; curr_result=g_list_next(curr_result)) {
+ struct lcoord *point = curr_result->data;
+ struct item* it;
+ if(point->label==NULL)
+ continue;
+ dbg(lvl_info,"%s",point->label);
+ it=map_rect_create_item(mr,type_found_item);
+ if(it) {
+ struct attr a;
+ item_coord_set(it, &(point->c), 1, change_mode_modify);
+ a.type=attr_label;
+ name_label = g_strdup(point->label);
+ square_shape_str(name_label);
+ a.u.str=name_label;
+ item_attr_set(it, &a, change_mode_modify);
+ if (r) {
+ if(!count++)
+ r->lu=r->rl=point->c;
+ else
+ coord_rect_extend(r,&(point->c));
+ }
+ }
+ }
+ map_rect_destroy(mr);
+ return count;
+}
+
struct tracking *
navit_get_tracking(struct navit *this_) {
return this_->tracking;
diff --git a/navit/navit.h b/navit/navit.h
index 7125c1878..f543a7baf 100644
--- a/navit/navit.h
+++ b/navit/navit.h
@@ -54,6 +54,8 @@ struct command_table;
struct item;
void navit_add_mapset(struct navit *this_, struct mapset *ms);
struct mapset *navit_get_mapset(struct navit *this_);
+struct map *navit_get_search_results_map(struct navit *this_);
+int navit_populate_search_results_map(struct navit *navit, GList *search_results, struct coord_rect *r);
struct tracking *navit_get_tracking(struct navit *this_);
char *navit_get_user_data_directory(int create);
void navit_draw_async(struct navit *this_, int async);
diff --git a/navit/util.c b/navit/util.c
index 9398e316c..944dc2a21 100644
--- a/navit/util.c
+++ b/navit/util.c
@@ -529,6 +529,70 @@ char * newSysString(const char *toconvert) {
#endif
#endif
+/**
+ * @brief Optimizes the format of a string, adding carriage returns so that when displayed, the result text zone is roughly as wide as high
+ *
+ * @param[in,out] s The string to proces (will be modified by this function, but length will be unchanged)
+ */
+void square_shape_str(char *s) {
+ char *c;
+ char *last_break;
+ unsigned int max_cols = 0;
+ unsigned int cur_cols = 0;
+ unsigned int max_rows = 0;
+ unsigned int surface;
+ unsigned int target_cols;
+
+ if (!s)
+ return;
+ for (c=s; *c!='\0'; c++) {
+ if (*c==' ') {
+ if (max_cols < cur_cols)
+ max_cols = cur_cols;
+ cur_cols = 0;
+ max_rows++;
+ } else
+ cur_cols++;
+ }
+ if (max_cols < cur_cols)
+ max_cols = cur_cols;
+ if (cur_cols) /* If last line does not end with CR, add it to line numbers anyway */
+ max_rows++;
+ /* Give twice more room for rows (hence the factor 2 below)
+ * This will render as a rectangular shape, taking more horizontal space than vertical */
+ surface = max_rows * 2 * max_cols;
+ target_cols = uint_sqrt(surface);
+
+ if (target_cols < max_cols)
+ target_cols = max_cols;
+
+ target_cols = target_cols + target_cols/10; /* Allow 10% extra on columns */
+ dbg(lvl_debug, "square_shape_str(): analyzing input text=\"%s\". max_rows=%u, max_cols=%u, surface=%u, target_cols=%u",
+ s, max_rows, max_cols, max_rows * 2 * max_cols, target_cols);
+
+ cur_cols = 0;
+ last_break = NULL;
+ for (c=s; *c!='\0'; c++) {
+ if (*c==' ') {
+ if (cur_cols>=target_cols) { /* This line is too long, break at the previous non alnum character */
+ if (last_break) {
+ *last_break =
+ '\n'; /* Replace the previous non alnum character with a line break, this creates a new line and prevents the previous line from being too long */
+ cur_cols = c-last_break;
+ }
+ }
+ last_break = c; /* Record this position as a candidate to insert a line break */
+ }
+ cur_cols++;
+ }
+ if (cur_cols>=target_cols && last_break) {
+ *last_break =
+ '\n'; /* Replace the previous non alnum character with a line break, this creates a new line and prevents the previous line from being too long */
+ }
+
+ dbg(lvl_debug, "square_shape_str(): output text=\"%s\"", s);
+}
+
#if defined(_MSC_VER) || (!defined(HAVE_GETTIMEOFDAY) && defined(HAVE_API_WIN32_BASE))
/**
* Impements a simple incomplete version of gettimeofday. Only usefull for messuring
diff --git a/navit/util.h b/navit/util.h
index 131173ff6..685adc080 100644
--- a/navit/util.h
+++ b/navit/util.h
@@ -41,6 +41,9 @@ wchar_t* newSysString(const char *toconvert);
char * newSysString(const char *toconvert);
#endif
#endif
+
+void square_shape_str(char *s);
+
unsigned int iso8601_to_secs(char *iso8601);
time_t mkgmtime(struct tm * pt);
time_t iso8601_to_time(char * iso8601);