summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Herlant <aerostitch@users.noreply.github.com>2019-09-22 09:56:36 -0700
committerGitHub <noreply@github.com>2019-09-22 09:56:36 -0700
commit8fc531c7e50963f96bc919ea8a16eebe1d65978c (patch)
treeabf7439049ea0f77dcebf672cf82a61ef7277bac
parent4c23749db062885437976893cf7034654c889e6d (diff)
parentbb680f70f18f1200bdc25b45031e26ac07c71979 (diff)
downloadnavit-aerostitch/wiki_migration.tar.gz
Merge branch 'trunk' into aerostitch/wiki_migrationaerostitch/wiki_migration
-rw-r--r--navit/android.c44
-rw-r--r--navit/android/src/org/navitproject/navit/NavitGraphics.java5
-rw-r--r--navit/attr.c39
-rw-r--r--navit/attr.h2
-rw-r--r--navit/bookmarks.c25
-rw-r--r--navit/coord.c103
-rw-r--r--navit/coord.h21
-rw-r--r--navit/gui/internal/gui_internal.c7
-rw-r--r--navit/gui/internal/gui_internal_command.c171
-rw-r--r--navit/util.c123
-rw-r--r--navit/util.h17
11 files changed, 344 insertions, 213 deletions
diff --git a/navit/android.c b/navit/android.c
index dc506ffb0..4c6d1ff1e 100644
--- a/navit/android.c
+++ b/navit/android.c
@@ -11,6 +11,7 @@
#include "callback.h"
#include "country.h"
#include "projection.h"
+#include "coord.h"
#include "map.h"
#include "mapset.h"
#include "navit_nls.h"
@@ -141,7 +142,7 @@ JNIEXPORT void JNICALL Java_org_navitproject_navit_NavitGraphics_KeypressCallbac
const char *s;
dbg(lvl_debug,"enter %p %p",(struct callback *)id,str);
s=(*env)->GetStringUTFChars(env, str, NULL);
- dbg(lvl_debug,"key=%d",s);
+ dbg(lvl_debug,"key=%s",s);
if (id)
callback_call_1((struct callback *)id,s);
(*env)->ReleaseStringUTFChars(env, str, s);
@@ -190,8 +191,6 @@ JNIEXPORT void JNICALL Java_org_navitproject_navit_NavitTraff_onFeedReceived(JNI
(*env)->ReleaseStringUTFChars(env, feed, s);
}
-
-
// type: 0=town, 1=street, 2=House#
void android_return_search_result(struct jni_object *jni_o, int type, struct pcoord *location, const char *address) {
struct coord_geo geo_location;
@@ -329,16 +328,17 @@ JNIEXPORT jint JNICALL Java_org_navitproject_navit_NavitGraphics_CallbackMessage
transform_reverse(transform, &p, &c);
-
pc.x = c.x;
pc.y = c.y;
pc.pro = transform_get_projection(transform);
- dbg(lvl_debug,"22x=%d",pc.x);
- dbg(lvl_debug,"22y=%d",pc.y);
+ char coord_str[32];
+ pcoord_format_short(&pc, coord_str, sizeof(coord_str), " ");
+
+ dbg(lvl_debug,"Setting destination to %s",coord_str);
// start navigation asynchronous
- navit_set_destination(attr.u.navit, &pc, parse_str, 1);
+ navit_set_destination(attr.u.navit, &pc, coord_str, 1);
}
break;
case 3: {
@@ -388,6 +388,36 @@ JNIEXPORT jint JNICALL Java_org_navitproject_navit_NavitGraphics_CallbackMessage
return ret;
}
+JNIEXPORT jstring JNICALL Java_org_navitproject_navit_NavitGraphics_getCoordForPoint( JNIEnv* env, jobject thiz,
+ jint id, int x, int y) {
+
+ jstring return_string = NULL;
+
+ struct attr attr;
+ config_get_attr(config_get(), attr_navit, &attr, NULL);
+
+ struct transformation *transform=navit_get_trans(attr.u.navit);
+ struct point p;
+ struct coord c;
+ struct pcoord pc;
+
+ p.x = x;
+ p.y = y;
+
+ transform_reverse(transform, &p, &c);
+
+ pc.x = c.x;
+ pc.y = c.y;
+ pc.pro = transform_get_projection(transform);
+
+ char coord_str[32];
+ pcoord_format_short(&pc, coord_str, sizeof(coord_str), " ");
+
+ dbg(lvl_debug,"Display point x=%d y=%d is \"%s\"",x,y,coord_str);
+ return_string = (*env)->NewStringUTF(env,coord_str);
+ return return_string;
+}
+
JNIEXPORT jstring JNICALL Java_org_navitproject_navit_NavitGraphics_GetDefaultCountry( JNIEnv* env, jobject thiz,
int channel, jobject str) {
struct attr search_attr, country_name, country_iso2, *country_attr;
diff --git a/navit/android/src/org/navitproject/navit/NavitGraphics.java b/navit/android/src/org/navitproject/navit/NavitGraphics.java
index 4e7929f88..22b9e8ca3 100644
--- a/navit/android/src/org/navitproject/navit/NavitGraphics.java
+++ b/navit/android/src/org/navitproject/navit/NavitGraphics.java
@@ -201,7 +201,8 @@ public class NavitGraphics {
protected void onCreateContextMenu(ContextMenu menu) {
super.onCreateContextMenu(menu);
- menu.setHeaderTitle(activity.getTstring(R.string.position_popup_title) + "..");
+ String clickCoord = getCoordForPoint(0, (int)mPressedPosition.x, (int)mPressedPosition.y);
+ menu.setHeaderTitle(activity.getTstring(R.string.position_popup_title) + " " + clickCoord);
menu.add(1, 1, NONE, activity.getTstring(R.string.position_popup_drive_here))
.setOnMenuItemClickListener(this);
menu.add(1, 2, NONE, activity.getTstring(R.string.cancel)).setOnMenuItemClickListener(this);
@@ -733,6 +734,8 @@ public class NavitGraphics {
public native void MotionCallback(int id, int x, int y);
+ private native String getCoordForPoint(int id, int x, int y);
+
public native String GetDefaultCountry(int id, String s);
public static native String[][] GetAllCountries();
diff --git a/navit/attr.c b/navit/attr.c
index 78e2a683c..58cfe621d 100644
--- a/navit/attr.c
+++ b/navit/attr.c
@@ -927,17 +927,19 @@ attr_list_dup(struct attr **attrs) {
* parsed value including the terminating NULL character. The minimum safe size is
* `strlen(line) - strlen(name) - *pos` (assuming zero for NULL pointers).
*
- * @param line The line to parse
- * @param name The name of the attribute to retrieve; if NULL,
- * @param pos Offset pointer, see description
- * @param val_ret Points to a buffer which will receive the value as text
- * @param name_ret Points to a buffer which will receive the name of the attribute parsed, can be NULL
+ * @param[in] line The line to parse, must be non-NULL and pointing to a NUL terminated string
+ * @param[in] name The name of the attribute to retrieve; can be NULL (see description)
+ * @param[in,out] pos As input, if pointer is non-NULL, this argument contains the character index inside @p line from which to start the search (see description)
+ * @param[out] val_ret Points to a buffer which will receive the value as text
+ * @param[out] name_ret Points to a buffer which will receive the actual name of the attribute found in the line, if NULL this argument won't be used. Note that the buffer provided here should be long enough to contain the attribute name + a terminating NUL character
*
* @return true if successful, false in case of failure
*/
-int attr_from_line(char *line, char *name, int *pos, char *val_ret, char *name_ret) {
- int len=0,quoted;
- char *p,*e,*n;
+int attr_from_line(const char *line, const char *name, int *pos, char *val_ret, char *name_ret) {
+ int len=0,quoted,escaped;
+ const char *p;
+ char *e;
+ const char *n;
dbg(lvl_debug,"get_tag %s from %s", name, line);
if (name)
@@ -958,15 +960,23 @@ int attr_from_line(char *line, char *name, int *pos, char *val_ret, char *name_r
return 0;
p=e+1;
quoted=0;
+ escaped=0;
while (*p) {
if (*p == ' ' && !quoted)
break;
if (*p == '"')
quoted=1-quoted;
+ if (*p == '\\') { /* Next character is escaped */
+ escaped++;
+ if (*(p+1)) /* Make sure the string is not terminating just after this escape character */
+ p++; /* if the string continues, skip the next character, whatever is is (space, double-quote or backslash) */
+ else
+ dbg(lvl_warning, "Trailing backslash in input string \"%s\"", line);
+ }
p++;
}
- if (name == NULL || (e-n == len && !strncmp(n, name, len))) {
- if (name_ret) {
+ if (name == NULL || (e-n == len && strncmp(n, name, len)==0)) { /* We matched the searched attribute name */
+ if (name_ret) { /* If instructed to, store the actual name into the string pointed by name_ret */
len=e-n;
strncpy(name_ret, n, len);
name_ret[len]='\0';
@@ -977,8 +987,13 @@ int attr_from_line(char *line, char *name, int *pos, char *val_ret, char *name_r
e++;
len-=2;
}
- strncpy(val_ret, e, len);
- val_ret[len]='\0';
+ /* Note: in the strncpy* calls below, we give a max size_t argument exactly matching the string lengh we want to copy within the source string e, so no terminating NUL char will be appended */
+ if (escaped)
+ strncpy_unescape(val_ret, e, len-escaped); /* Unescape if necessary */
+ else
+ strncpy(val_ret, e, len);
+ /* Because no NUL terminating char was copied over, we manually append it here to terminate the C-string properly, just after the copied string */
+ val_ret[len-escaped]='\0';
if (pos)
*pos=p-line;
return 1;
diff --git a/navit/attr.h b/navit/attr.h
index a9e4d9467..ab4283394 100644
--- a/navit/attr.h
+++ b/navit/attr.h
@@ -243,7 +243,7 @@ struct attr *attr_dup(struct attr *attr);
void attr_list_free(struct attr **attrs);
struct attr **attr_list_dup(struct attr **attrs);
struct attr **attr_list_append(struct attr **attrs, struct attr *attr);
-int attr_from_line(char *line, char *name, int *pos, char *val_ret, char *name_ret);
+int attr_from_line(const char *line, const char *name, int *pos, char *val_ret, char *name_ret);
int attr_types_contains(enum attr_type *types, enum attr_type type);
int attr_types_contains_default(enum attr_type *types, enum attr_type type, int deflt);
int attr_rel2real(int attrval, int whole, int treat_neg_as_rel);
diff --git a/navit/bookmarks.c b/navit/bookmarks.c
index 5df36b7a3..f32b6d89c 100644
--- a/navit/bookmarks.c
+++ b/navit/bookmarks.c
@@ -711,22 +711,32 @@ static GList* find_destination_in_list(struct former_destination* dest_to_remove
}
-
-static void write_former_destinations(GList* former_destinations, char *former_destination_file, enum projection proj) {
+/**
+ * @brief Write all former destinations into a text file
+ *
+ * @param[in] former_destinations A GList of struct coord data elements containing the list of former destinations
+ * @param[in] former_destination_file The name of the output text file
+ * @param proj The projection used to represent coordinates in former_destinations' list elements
+ */
+static void write_former_destinations(const GList* former_destinations, const char *former_destination_file,
+ enum projection proj) {
FILE *f;
- GList* currdest = NULL;
+ const GList* currdest = NULL;
GList* c_list = NULL;
struct coord *c;
struct former_destination *dest;
const char* prostr = projection_to_name(proj);
+ if (prostr == NULL)
+ prostr = ""; /* Protect from NULL pointer dereference below */
+
f=fopen(former_destination_file, "w");
if (f) {
for(currdest = former_destinations; currdest; currdest = g_list_next(currdest)) {
dest = currdest->data;
+ fprintf(f,"type=%s", item_to_name(dest->type));
if (dest->description)
- fprintf(f,"type=%s label=\"%s\"\n", item_to_name(dest->type), dest->description);
- else
- fprintf(f,"type=%s\n", item_to_name(dest->type));
+ fprintf(f," label=\"%s\"", str_escape(escape_mode_quote, dest->description));
+ fputc('\n', f);
c_list = dest->c;
do {
c = (struct coord *)c_list->data;
@@ -742,8 +752,9 @@ static void write_former_destinations(GList* former_destinations, char *former_d
dbg(lvl_error, "Error updating destinations file %s: %s", former_destination_file, strerror(errno));
}
}
+
/**
- * Append recent destination(s) item to the former destionations map.
+ * @brief Append recent destination(s) item to the former destionations map.
* @param former_destination_map
* @param former_destination_file
* @param c coordinates of item point(s). Can be set to NULL when navigation is stopped to remove type_former_itinerary and
diff --git a/navit/coord.c b/navit/coord.c
index bb16978c8..3cfa33eff 100644
--- a/navit/coord.c
+++ b/navit/coord.c
@@ -293,23 +293,26 @@ void coord_print(enum projection pro, struct coord *c, FILE *out) {
* @brief Converts a lat/lon into a text formatted text string.
* @param lat The latitude (if lat is 360 or greater, the latitude will be omitted)
* @param lng The longitude (if lng is 360 or greater, the longitude will be omitted)
- * @param fmt The format to use.
- * @li DEGREES_DECIMAL=>Degrees with decimal places, i.e. 20.5000°N 110.5000°E
- * @li DEGREES_MINUTES=>Degrees and minutes, i.e. 20°30.00'N 110°30.00'E
- * @li DEGREES_MINUTES_SECONDS=>Degrees, minutes and seconds, i.e. 20°30'30.00"N 110°30'30"E
- *
- *
- * @param buffer A buffer large enough to hold the output + a terminating NULL (up to 31 bytes)
+ * @param fmt The format to use:
+ * @li DEGREES_DECIMAL=>Degrees with decimal places, i.e. 20.500000°N 110.500000°E (max: 26 bytes)
+ * @li DEGREES_MINUTES=>Degrees and minutes, i.e. 20°30.0000' N 110°30.0000' E (max: 30 bytes)
+ * @li DEGREES_MINUTES_SECONDS=>Degrees, minutes and seconds, i.e. 20°30'30.00" N 110°30'30.00" E (max: 32 bytes)
+ * @li DEGREES_MINUTES_SECONDS_BRIEF=>Degrees, minutes and seconds but with the shortest possible string, i.e. 20°30'30"N 110°30'30"E (max 24 bytes)
+ * @param[out] buffer A buffer large enough to hold the output (bearing in mind '°' uses 2 bytes in UTF-8).
+ * Maximum size depends on the format, see values above, and add an extra character for the terminating NUL character
* @param size The size of the buffer
+ * @param[in] sep The separator to use (if needed) between latitude and longitude (if NULL we will use a space)
*
*/
-void coord_format(float lat,float lng, enum coord_format fmt, char * buffer, int size) {
+void coord_format_with_sep(float lat,float lng, enum coord_format fmt, char *buffer, int size, const char *sep) {
char lat_c='N';
char lng_c='E';
float lat_deg,lat_min,lat_sec;
float lng_deg,lng_min,lng_sec;
int size_used=0;
+ if (sep == NULL)
+ sep = " ";
if (lng < 0) {
lng=-lng;
@@ -331,7 +334,7 @@ void coord_format(float lat,float lng, enum coord_format fmt, char * buffer, int
if (lat<360)
size_used+=g_snprintf(buffer+size_used,size-size_used,"%02.6f°%c",lat,lat_c);
if ((lat<360)&&(lng<360))
- size_used+=g_snprintf(buffer+size_used,size-size_used," ");
+ size_used+=g_snprintf(buffer+size_used,size-size_used,"%s",sep);
if (lng<360)
size_used+=g_snprintf(buffer+size_used,size-size_used,"%03.7f°%c",lng,lng_c);
break;
@@ -339,7 +342,7 @@ void coord_format(float lat,float lng, enum coord_format fmt, char * buffer, int
if (lat<360)
size_used+=g_snprintf(buffer+size_used,size-size_used,"%02.0f°%07.4f' %c",floor(lat_deg),lat_min,lat_c);
if ((lat<360)&&(lng<360))
- size_used+=g_snprintf(buffer+size_used,size-size_used," ");
+ size_used+=g_snprintf(buffer+size_used,size-size_used,"%s",sep);
if (lng<360)
size_used+=g_snprintf(buffer+size_used,size-size_used,"%03.0f°%07.4f' %c",floor(lng_deg),lng_min,lng_c);
break;
@@ -348,22 +351,97 @@ void coord_format(float lat,float lng, enum coord_format fmt, char * buffer, int
size_used+=g_snprintf(buffer+size_used,size-size_used,"%02.0f°%02.0f'%05.2f\" %c",floor(lat_deg),floor(lat_min),
lat_sec,lat_c);
if ((lat<360)&&(lng<360))
- size_used+=g_snprintf(buffer+size_used,size-size_used," ");
+ size_used+=g_snprintf(buffer+size_used,size-size_used,"%s",sep);
if (lng<360)
size_used+=g_snprintf(buffer+size_used,size-size_used,"%03.0f°%02.0f'%05.2f\" %c",floor(lng_deg),floor(lng_min),
lng_sec,lng_c);
break;
+ case DEGREES_MINUTES_SECONDS_BRIEF:
+ if (lat<360)
+ size_used+=g_snprintf(buffer+size_used,size-size_used,"%.0f°%.0f'%.0f\"%c",floor(lat_deg),floor(lat_min),
+ round(lat_sec),lat_c);
+ if ((lat<360)&&(lng<360))
+ size_used+=g_snprintf(buffer+size_used,size-size_used,"%s",sep);
+ if (lng<360)
+ size_used+=g_snprintf(buffer+size_used,size-size_used,"%.0f°%.0f'%.0f\"%c",floor(lng_deg),floor(lng_min),
+ round(lng_sec),lng_c);
+ break;
+ }
+}
+/**
+ * @brief Converts a lat/lon into a text formatted text string.
+ * @param lat The latitude (if lat is 360 or greater, the latitude will be omitted)
+ * @param lng The longitude (if lng is 360 or greater, the longitude will be omitted)
+ * @param fmt The format to use.
+ * @li DEGREES_DECIMAL=>Degrees with decimal places, i.e. 20.500000°N 110.500000°E
+ * @li DEGREES_MINUTES=>Degrees and minutes, i.e. 20°30.0000' N 110°30.0000' E
+ * @li DEGREES_MINUTES_SECONDS=>Degrees, minutes and seconds, i.e. 20°30'30.00" N 110°30'30.00" E
+ * @li DEGREES_MINUTES_SECONDS_BRIEF=>Degrees, minutes and seconds but with the shortest possible string, i.e. 20°30'30"N 110°30'30"E
+ * @param[out] buffer A buffer large enough to hold the output + a terminating NUL character (up to 31 bytes)
+ * @param size The size of the buffer
+ *
+ */
+inline void coord_format(float lat,float lng, enum coord_format fmt, char *buffer, int size) {
+ coord_format_with_sep(lat, lng, fmt, buffer, size, NULL);
+}
- }
+/**
+ * @brief Converts a WGS84 coordinate pair to its string representation.
+ *
+ * This function takes a coordinate pair with latitude and longitude in degrees and converts them to a
+ * string of the form {@code 45°28'0"N 9°11'26"E}.
+ *
+ * @param gc A WGS84 coordinate pair
+ * @param[out] buffer A buffer large enough to hold the output + a terminating NUL character (up to 31 bytes)
+ * @param size The size of the buffer
+ * @param[in] sep The separator to use (if needed) between latitude and longitude (if NULL we will use a space)
+ */
+inline void coord_geo_format_short(const struct coord_geo *gc, char *buffer, int size, char *sep) {
+ dbg_assert(gc != NULL);
+ coord_format_with_sep(gc->lat, gc->lng, DEGREES_MINUTES_SECONDS_BRIEF, buffer, size, sep);
+}
+/**
+ * @brief Converts an integer mercator coordinate pair to its string representation.
+ *
+ * This function takes a coordinate pair, transforms it to WGS84 and converts it to a string of the form
+ * {@code 45°28'0"N 9°11'26"E}.
+ *
+ * @param pc Coordinates as integer mercator
+ * @param[out] buffer A buffer large enough to hold the output + a terminating NUL character (up to 31 bytes)
+ * @param size The size of the buffer
+ * @param[in] sep The separator to use (if needed) between latitude and longitude (if NULL we will use a space)
+ */
+inline void pcoord_format_short(const struct pcoord *pc, char *buffer, int size, char *sep) {
+ dbg_assert(pc != NULL);
+ struct coord_geo g;
+ struct coord c;
+ c.x=pc->x;
+ c.y=pc->y;
+ transform_to_geo(pc->pro, &c, &g);
+ coord_format_with_sep(g.lat, g.lng, DEGREES_MINUTES_SECONDS_BRIEF, buffer, size, sep);
}
+/**
+ * @brief Generate a hash from a struct coord pointed by key
+ *
+ * @param[in] key A pointer to the struct coord to hash
+ * @return The resulting hash
+ */
unsigned int coord_hash(const void *key) {
const struct coord *c=key;
return c->x^c->y;
}
+/**
+ * @brief Test if two struct coord structures are equal
+ *
+ * @param[in] a A pointer to the first struct coord
+ * @param[in] b A pointer to the second struct coord
+ *
+ * @return TRUE if a and b are equal, FALSE otherwise
+ */
int coord_equal(const void *a, const void *b) {
const struct coord *c_a=a;
const struct coord *c_b=b;
@@ -371,4 +449,5 @@ int coord_equal(const void *a, const void *b) {
return TRUE;
return FALSE;
}
+
/** @} */
diff --git a/navit/coord.h b/navit/coord.h
index 8387462a2..753da5e8c 100644
--- a/navit/coord.h
+++ b/navit/coord.h
@@ -65,7 +65,7 @@ struct coord_rect {
/**
* On platforms where we are trying to avoid floats, sometimes we can't.
* It is better on these platforms to use single precision floating points
- * over double percision ones since performance is much better.
+ * over double precision ones since performance is much better.
*/
typedef float navit_float;
#define navit_sin(x) sinf(x)
@@ -114,20 +114,25 @@ enum coord_format
{
/**
* Degrees with decimal places.
- * Ie 20.5000 N 110.5000 E
+ * ie 20.500000°N 110.500000°E
*/
DEGREES_DECIMAL,
/**
* Degrees and minutes.
- * ie 20 30.00 N 110 30.00 E
+ * ie 20°30.0000' N 110°30.0000' E
*/
DEGREES_MINUTES,
/**
* Degrees, minutes and seconds.
- * ie 20 30 30.00 N 110 30 30 E
+ * ie 20°30'30.00" N 110°30'30.00" E
*/
- DEGREES_MINUTES_SECONDS
+ DEGREES_MINUTES_SECONDS,
+ /**
+ * Degrees, minutes and seconds, brief
+ * ie 20°30'30"N 110°30'30"E
+ */
+ DEGREES_MINUTES_SECONDS_BRIEF
};
enum projection;
@@ -145,7 +150,11 @@ void coord_rect_destroy(struct coord_rect *r);
int coord_rect_overlap(struct coord_rect *r1, struct coord_rect *r2);
int coord_rect_contains(struct coord_rect *r, struct coord *c);
void coord_rect_extend(struct coord_rect *r, struct coord *c);
-void coord_format(float lat,float lng, enum coord_format, char * buffer, int size);
+void coord_format_with_sep(float lat,float lng, enum coord_format fmt, char *buffer, int size, const char *sep);
+void coord_format(float lat,float lng, enum coord_format fmt, char *buffer, int size);
+void coord_geo_format_short(const struct coord_geo *gc, char *buffer, int size, char *sep);
+void pcoord_format_short(const struct pcoord *pc, char *buffer, int size, char *sep);
+char *coordinates_geo(const struct coord_geo *gc, char sep);
/* prototypes */
enum coord_format;
diff --git a/navit/gui/internal/gui_internal.c b/navit/gui/internal/gui_internal.c
index 726a03d17..23dae0808 100644
--- a/navit/gui/internal/gui_internal.c
+++ b/navit/gui/internal/gui_internal.c
@@ -1044,7 +1044,6 @@ void gui_internal_cmd_position_do(struct gui_priv *this, struct pcoord *pc_in, s
struct coord_geo g;
struct pcoord pc;
struct coord c;
- char *coord;
if (pc_in) {
pc=*pc_in;
@@ -1067,9 +1066,9 @@ void gui_internal_cmd_position_do(struct gui_priv *this, struct pcoord *pc_in, s
wb=gui_internal_menu(this, name);
w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
gui_internal_widget_append(wb, w);
- coord=gui_internal_coordinates(&pc, ' ');
- gui_internal_widget_append(w, gui_internal_label_new(this, coord));
- g_free(coord);
+ char coord_str[32];
+ pcoord_format_short(&pc, coord_str, sizeof(coord_str), " ");
+ gui_internal_widget_append(w, gui_internal_label_new(this, coord_str));
wtable = gui_internal_widget_table_new(this,gravity_left_top | flags_fill | flags_expand |orientation_vertical,1);
gui_internal_widget_append(w,wtable);
diff --git a/navit/gui/internal/gui_internal_command.c b/navit/gui/internal/gui_internal_command.c
index 3148e83e5..910e2e8cf 100644
--- a/navit/gui/internal/gui_internal_command.c
+++ b/navit/gui/internal/gui_internal_command.c
@@ -41,161 +41,6 @@
#include <arpa/inet.h>
#endif
-/**
- * @brief Converts a WGS84 coordinate pair to its string representation.
- *
- * This function takes a coordinate pair with latitude and longitude in degrees and converts them to a
- * string of the form {@code 45°28'0" N 9°11'26" E}.
- *
- * @param gc A WGS84 coordinate pair
- * @param sep The separator character to insert between latitude and longitude
- *
- * @return The coordinates as a formatted string
- */
-static char *coordinates_geo(const struct coord_geo *gc, char sep) {
- char latc='N',lngc='E';
- int lat_deg,lat_min,lat_sec;
- int lng_deg,lng_min,lng_sec;
- struct coord_geo g=*gc;
-
- if (g.lat < 0) {
- g.lat=-g.lat;
- latc='S';
- }
- if (g.lng < 0) {
- g.lng=-g.lng;
- lngc='W';
- }
- lat_sec=fmod(g.lat*3600+0.5,60);
- lat_min=fmod(g.lat*60-lat_sec/60.0+0.5,60);
- lat_deg=g.lat-lat_min/60.0-lat_sec/3600.0+0.5;
- lng_sec=fmod(g.lng*3600+0.5,60);
- lng_min=fmod(g.lng*60-lng_sec/60.0+0.5,60);
- lng_deg=g.lng-lng_min/60.0-lng_sec/3600.0+0.5;;
-
- return g_strdup_printf("%d°%d'%d\" %c%c%d°%d'%d\" %c",lat_deg,lat_min,lat_sec,latc,sep,lng_deg,lng_min,lng_sec,lngc);
-}
-
-/**
- * @brief Converts a coordinate pair to its WGS84 string representation.
- *
- * This function takes a coordinate pair, transforms it to WGS84 and converts it to a string of the form
- * {@code 45°28'0" N 9°11'26" E}.
- *
- * @param gc A coordinate pair
- * @param sep The separator character to insert between latitude and longitude
- *
- * @return The coordinates as a formatted string
- */
-char *gui_internal_coordinates(struct pcoord *pc, char sep) {
- struct coord_geo g;
- struct coord c;
- c.x=pc->x;
- c.y=pc->y;
- transform_to_geo(pc->pro, &c, &g);
- return coordinates_geo(&g, sep);
-
-}
-
-enum escape_mode {
- escape_mode_none=0,
- escape_mode_string=1, /*!< Surround string by double quotes */
- escape_mode_quote=2, /*!< Escape double quotes and backslashes */
- escape_mode_html_amp=4, /*!< Use HTML-style escape sequences for ampersands */
- escape_mode_html_quote=8, /*!< Use HTML-style escape sequences for double quotes */
- escape_mode_html_apos=16, /*!< Use HTML-style escape sequences for single quotes (apostrophes) */
- escape_mode_html_lt=16, /*!< Use HTML-style escape sequences for lower than sign ('<') */
- escape_mode_html_gt=16, /*!< Use HTML-style escape sequences for greater than sign ('>') */
- escape_mode_html=escape_mode_html_amp|escape_mode_html_quote|escape_mode_html_apos|escape_mode_html_lt|escape_mode_html_gt, /*!< Use all known HTML-style escape sequences */
-};
-
-/**
- * @brief Escape special characters from a string
- *
- * @param mode The escape mode that needs to be enabled (see enum escape_mode)
- * @param in The string to escape
- *
- * @return The escaped string
- *
- * @note In html escape mode (escape_mode_html), we will only process HTML escape sequence, and string quoting, but we won't escape backslashes or double quotes
- * @warning The returned string has been allocated and g_free() must thus be called on this string
- */
-static char *gui_internal_escape(enum escape_mode mode, const char *in) {
- int len=mode & escape_mode_string ? 2:0; /* Add 2 characters to the length of the buffer if quoting is enabled */
- char *dst,*out;
- const char *src=in;
- static const char *quot="&quot;";
- static const char *apos="&apos;";
- static const char *amp="&amp;";
- static const char *lt="&lt;";
- static const char *gt="&gt;";
-
- dbg(lvl_debug, "Entering %s with string=\"%s\", escape mode %d", __func__, in, mode);
- while (*src) {
- if ((*src == '"' || *src == '\\') && (mode & (escape_mode_string | escape_mode_quote)))
- len++;
- if (*src == '"' && mode == escape_mode_html_quote)
- len+=strlen(quot);
- else if (*src == '\'' && mode == escape_mode_html_apos)
- len+=strlen(apos);
- else if (*src == '&' && mode == escape_mode_html_amp)
- len+=strlen(amp);
- else if (*src == '<' && mode == escape_mode_html_lt)
- len+=strlen(lt);
- else if (*src == '>' && mode == escape_mode_html_gt)
- len+=strlen(gt);
- else
- len++;
- src++;
- }
- src=in;
- out=dst=g_malloc(len+1); /* +1 character for NUL termination */
-
- /* In string quoting mode (escape_mode_string), prepend the whole string with a double quote */
- if (mode & escape_mode_string)
- *dst++='"';
-
- while (*src) {
- if (mode & escape_mode_html) { /* In html escape mode, only process HTML escape sequence, not backslashes or quotes */
- if (*src == '"' && (mode & escape_mode_html_quote)) {
- strcpy(dst,quot);
- src++;
- dst+=strlen(quot);
- } else if (*src == '\'' && (mode & escape_mode_html_apos)) {
- strcpy(dst,apos);
- src++;
- dst+=strlen(apos);
- } else if (*src == '&' && (mode & escape_mode_html_amp)) {
- strcpy(dst,amp);
- src++;
- dst+=strlen(amp);
- } else if (*src == '<' && (mode & escape_mode_html_lt)) {
- strcpy(dst,lt);
- src++;
- dst+=strlen(lt);
- } else if (*src == '>' && (mode & escape_mode_html_gt)) {
- strcpy(dst,gt);
- src++;
- dst+=strlen(gt);
- } else
- *dst++=*src++;
- } else {
- if ((*src == '"' || *src == '\\') && (mode & (escape_mode_string | escape_mode_quote))) {
- *dst++='\\';
- }
- *dst++=*src++;
- }
- }
-
- /* In string quoting mode (escape_mode_string), append a double quote to the whole string */
- if (mode & escape_mode_string)
- *dst++='"';
-
- *dst++='\0';
- dbg(lvl_debug, "Exitting %s with string=\"%s\"", __func__, out);
- return out;
-}
-
static void gui_internal_cmd_escape(struct gui_priv *this, char *function, struct attr **in, struct attr ***out,
int *valid) {
struct attr escaped;
@@ -209,7 +54,7 @@ static void gui_internal_cmd_escape(struct gui_priv *this, char *function, struc
}
if (ATTR_IS_STRING(in[0]->type)) {
escaped.type=in[0]->type;
- escaped.u.str=gui_internal_escape(escape_mode_string,in[0]->u.str);
+ escaped.u.str=str_escape(escape_mode_string,in[0]->u.str);
} else if (ATTR_IS_INT(in[0]->type)) {
escaped.type=attr_type_string_begin;
escaped.u.str=g_strdup_printf("%ld",in[0]->u.num);
@@ -1103,11 +948,11 @@ void gui_internal_cmd2_quit(struct gui_priv *this, char *function, struct attr *
static char *gui_internal_append_attr(char *str, enum escape_mode mode, char *pre, struct attr *attr, char *post) {
char *astr=NULL;
if (ATTR_IS_STRING(attr->type))
- astr=gui_internal_escape(mode, attr->u.str);
+ astr=str_escape(mode, attr->u.str);
else if (ATTR_IS_COORD_GEO(attr->type)) {
- char *str2=coordinates_geo(attr->u.coord_geo, '\n');
- astr=gui_internal_escape(mode, str2);
- g_free(str2);
+ char coord_str[32];
+ coord_geo_format_short(attr->u.coord_geo, coord_str, sizeof(coord_str), "\n");
+ astr=str_escape(mode, coord_str);
} else if (ATTR_IS_INT(attr->type))
astr=g_strdup_printf("%ld",attr->u.num);
else
@@ -1174,7 +1019,7 @@ static void gui_internal_onclick(struct attr ***in, char **onclick, char *set) {
if (!strcmp(format,"se")) {
replacement=gui_internal_append_attr(NULL, escape_mode_string, "", *i++, "");
if (is_arg) {
- char *arg=gui_internal_escape(escape_mode_string, replacement);
+ char *arg=str_escape(escape_mode_string, replacement);
args=g_strconcat_printf(args, "%s%s", args ? "," : "", arg);
g_free(replacement);
g_free(arg);
@@ -1199,7 +1044,7 @@ static void gui_internal_onclick(struct attr ***in, char **onclick, char *set) {
if (str && strlen(str)) {
char *old=*onclick;
if (set) {
- char *setstr=gui_internal_escape(escape_mode_string,str);
+ char *setstr=str_escape(escape_mode_string,str);
char *argssep="";
if (args && strlen(args))
argssep=",";
@@ -1251,7 +1096,7 @@ static void gui_internal_cmd_img(struct gui_priv * this, char *function, struct
gui_internal_onclick(&in,&onclick,"set");
gui_internal_onclick(&in,&onclick,NULL);
if (strlen(onclick)) {
- char *tmp=gui_internal_escape(escape_mode_html_apos, onclick);
+ char *tmp=str_escape(escape_mode_html_apos, onclick);
str=g_strconcat_printf(str," onclick='%s'",tmp);
g_free(tmp);
}
diff --git a/navit/util.c b/navit/util.c
index 944dc2a21..cf4412938 100644
--- a/navit/util.c
+++ b/navit/util.c
@@ -114,6 +114,129 @@ static void strtrim(char *s) {
}
/**
+ * @brief Escape special characters from a string
+ *
+ * @param mode The escape mode that needs to be enabled (see enum escape_mode)
+ * @param in The string to escape
+ *
+ * @return The escaped string
+ *
+ * @note In html escape mode (escape_mode_html), we will only process HTML escape sequence, and string quoting, but we won't escape backslashes or double quotes
+ * @warning The returned string has been allocated and g_free() must thus be called on this string
+ */
+char *str_escape(enum escape_mode mode, const char *in) {
+ int len=mode & escape_mode_string ? 2:0; /* Add 2 characters to the length of the buffer if quoting is enabled */
+ char *dst,*out;
+ const char *src=in;
+ static const char *quot="&quot;";
+ static const char *apos="&apos;";
+ static const char *amp="&amp;";
+ static const char *lt="&lt;";
+ static const char *gt="&gt;";
+
+ dbg(lvl_debug, "Will escape string=\"%s\", escape mode %d", in, mode);
+ while (*src) {
+ if ((*src == '"' || *src == '\\') && (mode & (escape_mode_string | escape_mode_quote)))
+ len++;
+ if (*src == '"' && mode == escape_mode_html_quote)
+ len+=strlen(quot);
+ else if (*src == '\'' && mode == escape_mode_html_apos)
+ len+=strlen(apos);
+ else if (*src == '&' && mode == escape_mode_html_amp)
+ len+=strlen(amp);
+ else if (*src == '<' && mode == escape_mode_html_lt)
+ len+=strlen(lt);
+ else if (*src == '>' && mode == escape_mode_html_gt)
+ len+=strlen(gt);
+ else
+ len++;
+ src++;
+ }
+ src=in;
+ out=dst=g_malloc(len+1); /* +1 character for NUL termination */
+
+ /* In string quoting mode (escape_mode_string), prepend the whole string with a double quote */
+ if (mode & escape_mode_string)
+ *dst++='"';
+
+ while (*src) {
+ if (mode & escape_mode_html) { /* In html escape mode, only process HTML escape sequence, not backslashes or quotes */
+ if (*src == '"' && (mode & escape_mode_html_quote)) {
+ strcpy(dst,quot);
+ src++;
+ dst+=strlen(quot);
+ } else if (*src == '\'' && (mode & escape_mode_html_apos)) {
+ strcpy(dst,apos);
+ src++;
+ dst+=strlen(apos);
+ } else if (*src == '&' && (mode & escape_mode_html_amp)) {
+ strcpy(dst,amp);
+ src++;
+ dst+=strlen(amp);
+ } else if (*src == '<' && (mode & escape_mode_html_lt)) {
+ strcpy(dst,lt);
+ src++;
+ dst+=strlen(lt);
+ } else if (*src == '>' && (mode & escape_mode_html_gt)) {
+ strcpy(dst,gt);
+ src++;
+ dst+=strlen(gt);
+ } else
+ *dst++=*src++;
+ } else {
+ if ((*src == '"' || *src == '\\') && (mode & (escape_mode_string | escape_mode_quote))) {
+ *dst++='\\';
+ }
+ *dst++=*src++;
+ }
+ }
+
+ /* In string quoting mode (escape_mode_string), append a double quote to the whole string */
+ if (mode & escape_mode_string)
+ *dst++='"';
+
+ *dst++='\0';
+ dbg(lvl_debug, "Result of escaped string=\"%s\"", out);
+ return out;
+}
+
+/**
+ * @brief Copy a string from @p src to @p dest, unescaping characters
+ *
+ * @note Escaped characters are "\\\\" (double backslash) resulting in '\\' (single backslash)
+ * and "\\\"" (backslash followed by double quote), resulting in '"' (double quote)
+ * but we will escape any other character, for example "\\ " will result in ' ' (space)
+ * This is the reverse of function str_escape, except that we assume (and only support) unescaping mode escape_mode_quote here
+ *
+ * @param[out] dest The location where to store the unescaped string
+ * @param[in] src The source string to copy (and to unescape)
+ * @param n The maximum amount of bytes copied into dest. Warning: If there is no null byte among the n bytes written to dest, the string placed in dest will not be null-terminated.
+ *
+ * @return A pointer to the destination string @p dest
+ */
+char *strncpy_unescape(char *dest, const char *src, size_t n) {
+ char *dest_ptr; /* A pointer to the currently parsed character inside string dest */
+
+ for (dest_ptr=dest; (dest_ptr-dest) < n && (*src != '\0'); src++, dest_ptr++) {
+ if (*src == '\\') {
+ src++;
+ }
+ *dest_ptr = *src;
+ if (*dest_ptr == '\0') {
+ /* This is only possible if we just parsed an escaped sequence '\\' followed by a NUL termination, which is not really sane, but we will silently accept this case */
+ return dest;
+ }
+ }
+ if ((dest_ptr-dest) < n)
+ *dest_ptr='\0'; /* Add a trailing '\0' if any room is remaining */
+ else {
+ // strncpy_unescape will return a non NUL-terminated string. Trouble ahead if this is not handled properly
+ }
+
+ return dest;
+}
+
+/**
* @brief Parser states for `parse_for_systematic_comparison()`.
*/
enum parse_state {
diff --git a/navit/util.h b/navit/util.h
index 685adc080..6da7808b4 100644
--- a/navit/util.h
+++ b/navit/util.h
@@ -26,10 +26,27 @@
#define MAX_MISMATCH 100
+/**
+ * @brief Escape modes for function str_escape()
+ */
+enum escape_mode {
+ escape_mode_none=0,
+ escape_mode_string=1, /*!< Surround string by double quotes */
+ escape_mode_quote=2, /*!< Escape double quotes and backslashes */
+ escape_mode_html_amp=4, /*!< Use HTML-style escape sequences for ampersands */
+ escape_mode_html_quote=8, /*!< Use HTML-style escape sequences for double quotes */
+ escape_mode_html_apos=16, /*!< Use HTML-style escape sequences for single quotes (apostrophes) */
+ escape_mode_html_lt=32, /*!< Use HTML-style escape sequences for lower than sign ('<') */
+ escape_mode_html_gt=64, /*!< Use HTML-style escape sequences for greater than sign ('>') */
+ escape_mode_html=escape_mode_html_amp|escape_mode_html_quote|escape_mode_html_apos|escape_mode_html_lt|escape_mode_html_gt, /*!< Use all known HTML-style escape sequences */
+};
+
void strtoupper(char *dest, const char *src);
void strtolower(char *dest, const char *src);
unsigned int uint_sqrt(unsigned int n);
int navit_utf8_strcasecmp(const char *s1, const char *s2);
+char *str_escape(enum escape_mode mode, const char *in);
+char *strncpy_unescape(char *dest, const char *src, size_t n);
int compare_name_systematic(const char *s1, const char *s2);
GList * g_hash_to_list(GHashTable *h);
GList * g_hash_to_list_keys(GHashTable *h);