diff options
author | martin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220> | 2007-07-04 22:44:46 +0000 |
---|---|---|
committer | martin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220> | 2007-07-04 22:44:46 +0000 |
commit | c7efe5c02b4d6ac162f348e48a57451596fa5e32 (patch) | |
tree | c0b1ca6d58a3f8668d070ab65a967c34c2e7b6ef | |
parent | c5a5ad0f86737b3d34dcd4345f048961eb6bc6d0 (diff) | |
download | navit-svn-c7efe5c02b4d6ac162f348e48a57451596fa5e32.tar.gz |
Merge with modular_map
git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit@255 ffa7fe5e-494d-0410-b361-a75ebd5db220
128 files changed, 15739 insertions, 6672 deletions
diff --git a/Makefile.am b/Makefile.am index 1bfdcf48..43860cda 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1 +1,5 @@ SUBDIRS=src +pkglibplugdir=${pkglibdir}/plugins +pkglib_DATA = README +EXTRA_DIST = README + diff --git a/Makefile.inc b/Makefile.inc new file mode 100644 index 00000000..a5102f1f --- /dev/null +++ b/Makefile.inc @@ -0,0 +1,2 @@ +plugindir=$(pkglibdir)/plugins +xpmdir=$(pkglibdir)/xpm diff --git a/configure.in b/configure.in index 090145bc..abd30fef 100644 --- a/configure.in +++ b/configure.in @@ -7,27 +7,164 @@ AC_PROG_CC if eval "test x$GCC = xyes"; then CFLAGS="$CFLAGS -Wall -Wcast-align -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wpointer-arith -Wreturn-type -D_GNU_SOURCE" fi +AC_PROG_CXX +if eval "test x$G++ = xyes"; then + CFLAGS="$CFLAGS -Wall -Wcast-align -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wpointer-arith -Wreturn-type -D_GNU_SOURCE" +fi + # CFLAGS="$CFLAGS -DG_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGDK_PIXBUF_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED" -pkg_modules="glib-2.0 gtk+-2.0 ORBit-2.0 freetype2" -PKG_CHECK_MODULES(PACKAGE, [$pkg_modules]) -AC_SUBST(PACKAGE_CFLAGS) -AC_SUBST(PACKAGE_LIBS) -AC_CHECK_HEADER(libspeechd.h, AC_DEFINE([HAVE_LIBSPEECHD],[],Define to 1 if you have the <libspeechd.h> header file.) LIBS="$LIBS -lspeechd", AC_MSG_WARN([*** no libspeechd.h -- Speech output disabled])) -AC_CHECK_HEADER(gps.h, AC_DEFINE([HAVE_LIBGPS],[],Define to 1 if you have the <gps.h> header file.) LIBS="$LIBS -lgps", AC_MSG_WARN([*** no gps.h -- gpsd support disabled])) +AC_DISABLE_STATIC +AC_PROG_LIBTOOL + +AC_ARG_ENABLE(avoid-unaligned, +[ --enable-avoid-unaligned avoid unaligned accesses], +AVOID_UNALIGNED=$enableval, AVOID_UNALIGNED=no) +test x"${AVOID_UNALIGNED}" = xyes && AC_DEFINE(AVOID_UNALIGNED,[],Define to avoid unaligned access) + +AC_ARG_ENABLE(avoid-float, +[ --enable-avoid-float avoid floating point calculations], +AVOID_FLOAT=$enableval, AVOID_FLOAT=no) +test x"${AVOID_FLOAT}" = xyes && AC_DEFINE(AVOID_FLOAT,[],Define to avoid floating point) + +AC_ARG_ENABLE(libgps, +[ --disable-libgps don't use libgps], +USE_LIBGPS=$enableval, USE_LIBGPS=yes) + +PKG_CHECK_MODULES(NAVIT, [glib-2.0]) +AC_SUBST(NAVIT_CFLAGS) +AC_SUBST(NAVIT_LIBS) + +PKG_CHECK_MODULES(GTK2, [gtk+-2.0], [gtk2_pkgconfig=yes], [gtk2_pkgconfig=no]) +if test "x$gtk2_pkgconfig" = "xyes"; then + AC_DEFINE(HAVE_GTK2, 1, [Define to 1 if you have imlib2]) +fi +AC_SUBST(GTK2_CFLAGS) +AC_SUBST(GTK2_LIBS) + +PKG_CHECK_MODULES(FREETYPE2, [freetype2], [freetype2_pkgconfig=yes], [freetype2_pkgconfig=no]) +if test "x$freetype2_pkgconfig" = "xyes"; then + AC_DEFINE(HAVE_FREETYPE2, 1, [Define to 1 if you have imlib2]) +fi +AC_SUBST(FREETYPE2_CFLAGS) +AC_SUBST(FREETYPE2_LIBS) + +PKG_CHECK_MODULES(IMLIB2, [imlib2], [imlib2_pkgconfig=yes], [imlib2_pkgconfig=no]) +if test "x$imlib2_pkgconfig" = "xyes"; then + AC_DEFINE(HAVE_IMLIB2, 1, [Define to 1 if you have imlib2]) +fi +AC_SUBST(IMLIB2_CFLAGS) +AC_SUBST(IMLIB2_LIBS) + +AC_CHECK_HEADER(libspeechd.h, AC_DEFINE([HAVE_LIBSPEECHD],[],Define to 1 if you have the <libspeechd.h> header file.) SPEECHD_LIBS="-lspeechd", AC_MSG_WARN([*** no libspeechd.h -- Speech output disabled])) +AC_SUBST(SPEECHD_CFLAGS) +AC_SUBST(SPEECHD_LIBS) + +AC_CHECK_HEADER( + SDL/SDL.h, + AC_DEFINE( + [HAVE_LIBSDL], + [], + Define to 1 if you have the <SDL/SDL.h> header file. + ) + SDL_LIBS="-lSDL" + sdl=yes, + AC_MSG_WARN([*** no SDL/SDL.h -- SDL support disabled]) +) +AC_SUBST(SDL_CFLAGS) +AC_SUBST(SDL_LIBS) + +AC_PREPROC_IFELSE( + CEGUI/CEGUI.h, + AC_DEFINE( + [HAVE_CEGUI], + [], + Define to 1 if you have the <CEGUI/CEGUI.h> header file. + ) + CEGUI_LIBS="-lCEGUIBase -lCEGUIOpenGLRenderer" + CEGUI_CFLAGS="-I /usr/local/include/CEGUI -I /usr/include/CEGUI" + cegui=yes, + AC_MSG_WARN([*** no CEGUI/CEGUI.h -- SDL support disabled]) + exit 1 +) +AC_SUBST(CEGUI_CFLAGS) +AC_SUBST(CEGUI_LIBS) + +AC_CHECK_HEADER( + GL/gl.h, + AC_DEFINE( + [HAVE_OPENGL], + [], + Define to 1 if you have the <GL/gl.h> header file. + ) + OPENGL_LIBS="-lGL -lGLU -lGLC" + opengl=yes, + AC_MSG_WARN([*** no GL/gl.h -- opengl and SDL support disabled]) +) +AC_SUBST(OPENGL_CFLAGS) +AC_SUBST(OPENGL_LIBS) +AM_CONDITIONAL(GUI_SDL, [test "x$sdl" = "xyes" -a "x$cegui" = "xyes" -a "x$opengl" = "xyes" ]) +AM_CONDITIONAL(GUI_GTK, [test "x$gtk2_pkgconfig" = "xyes"]) +AM_CONDITIONAL(GRAPHICS_OPENGL, [test "x$opengl" = "xyes"]) +AM_CONDITIONAL(GRAPHICS_GTK_DRAWING_AREA, [test "x$sdl" = "xyes"]) + +if test x"${USE_LIBGPS}" = xyes +then + AC_CHECK_HEADER(gps.h, AC_DEFINE([HAVE_LIBGPS],[],Define to 1 if you have the <gps.h> header file.) LIBS="$LIBS -lgps", AC_MSG_WARN([*** no gps.h -- gpsd support disabled])) +fi + +PYTHON_LIB="" +PYTHON_INC="" +if test "$cross_compiling" = no; then + AC_PATH_PROG(_PATH_PYTHON,[python]) + dnl Libraries and flags for embedded Python. + dnl FIXME: I wish there was a less icky way to get this. + if test x"$_PATH_PYTHON" != x ; then + AC_MSG_CHECKING(for Python linkage) + py_prefix=`$_PATH_PYTHON -c 'import sys; print sys.prefix'` + py_ver=`$_PATH_PYTHON -c 'import sys; print sys.version[[:3]]'` + py_libdir="${py_prefix}/lib/python${py_ver}" + PYTHON_INC="-I${py_prefix}/include/python${py_ver}" + if test -f $py_libdir/config/Makefile ; then + py_libs=`grep '^LIBS=' $py_libdir/config/Makefile | sed -e 's/^.*=//'` + py_libc=`grep '^LIBC=' $py_libdir/config/Makefile | sed -e 's/^.*=//'` + py_libm=`grep '^LIBM=' $py_libdir/config/Makefile | sed -e 's/^.*=//'` + py_liblocalmod=`grep '^LOCALMODLIBS=' $py_libdir/config/Makefile | sed -e 's/^.*=//'` + py_libbasemod=`grep '^BASEMODLIBS=' $py_libdir/config/Makefile | sed -e 's/^.*=//'` + PYTHON_LIB="-L$py_libdir/config $py_libs $py_libc $py_libm -lpython$py_ver $py_liblocalmod $py_libbasemod" + PYTHON_LIB=`echo $PYTHON_LIB | sed -e 's/[ \\t]*/ /g'` + CFLAGS="$CFLAGS $PYTHON_INC" + LIBS="$LIBS $PYTHON_LIB" + AC_MSG_RESULT($py_libdir) + else + AC_MSG_WARN([$py_libdir/config/Makefile missing, support for python disabled]) + fi + fi +else + AC_MSG_WARN([*** cross compiling, support for python disabled]) +fi +AC_SUBST(PYTHON_LIB) +AC_SUBST(PYTHON_INC) AC_CONFIG_SUBDIRS(src/fib-1.0) +LIBS="$LIBS -rdynamic" + AC_OUTPUT([ Makefile src/Makefile +src/data/Makefile +src/data/mg/Makefile +src/data/textfile/Makefile +src/data/garmin_img/Makefile src/gui/Makefile src/gui/gtk/Makefile +src/gui/sdl/Makefile src/graphics/Makefile src/graphics/gtk_drawing_area/Makefile -src/plugins/Makefile -src/plugins/poi_geodownload/Makefile -src/plugins/poi_geodownload/libmdb/Makefile +src/graphics/opengl/Makefile +src/graphics/null/Makefile +src/xpm/Makefile ]) diff --git a/src/Makefile.am b/src/Makefile.am index fb2fad6b..f198c092 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,24 +1,27 @@ -SUBDIRS=fib-1.0 gui graphics +SUBDIRS=fib-1.0 data gui graphics xpm fib-1.0 fib-1.0/Makefile.in: fib-1.0/Makefile.am cd fib-1.0 ./configure -AM_CPPFLAGS = @PACKAGE_CFLAGS@ -LDFLAGS = -Wl,--export-dynamic +AM_CPPFLAGS = @NAVIT_CFLAGS@ @SPEECHD_CFLAGS@ @GTK2_CFLAGS@ -DMODULE=\"navit\" bin_PROGRAMS = navit -navit_SOURCES = block.c command.c compass.c coord.c country.c cursor.c data_window.c debug.c destination.c \ - display.c file.c graphics.c log.c main.c map-common.c map-skelimpl.c map-skels.c map-srv.c \ - map-stubs.c map_data.c menu.c navigation.c osd.c param.c phrase.c plugin.c poly.c popup.c \ - profile.c route.c search.c speech.c street.c street_name.c town.c transform.c tree.c track.c \ - util.c vehicle.c block.h command.h compass.h config.h container.h coord.h country.h \ - cursor.h data.h data_window.h data_window_int.h debug.h destination.h display.h draw_info.h \ - file.h graphics.h gtkext.h log.h main.h map-share.h map.h map_data.h menu.h navigation.h \ - osd.h param.h phrase.h plugin.h point.h poly.h popup.h route.h search.h speech.h statusbar.h \ - street.h street_data.h street_name.h toolbar.h town.h transform.h tree.h track.h util.h vehicle.h - -navit_LDADD = @PACKAGE_LIBS@ gui/gtk/gtk.o graphics/gtk_drawing_area/gtk_drawing_area.o -Lfib-1.0 -lfib +#pkglib_DATA = navit.xml +#EXTRA_DIST = navit.xml + +navit_SOURCES = attr.c callback.c compass.c coord.c country.c cursor.c data_window.c debug.c \ + file.c graphics.c gui.c item.c layout.c log.c main.c map.c \ + mapset.c maptype.c menu.c navit.c navigation.c param.c phrase.c plugin.c popup.c \ + profile.c python.c route.c search.c speech.c transform.c track.c \ + util.c vehicle.c xmlconfig.c attr.h attr_def.h callback.h color.h compass.h coord.h country.h \ + cursor.h data.h data_window.h data_window_int.h debug.h destination.h draw_info.h \ + file.h graphics.h gtkext.h gui.h item.h item_def.h log.h layout.h main.h map-share.h map.h\ + map_data.h mapset.h maptype.h menu.h navigation.h navit.h \ + param.h phrase.h plugin.h point.h plugin_def.h projection.h popup.h route.h search.h speech.h statusbar.h \ + toolbar.h transform.h track.h util.h vehicle.h xmlconfig.h + +navit_LDADD = @NAVIT_LIBS@ @SPEECHD_LIBS@ @GTK2_LIBS@ -Lfib-1.0 -lfib diff --git a/src/action.h b/src/action.h deleted file mode 100644 index ed64fd56..00000000 --- a/src/action.h +++ /dev/null @@ -1,3 +0,0 @@ -struct action { - struct action_gui *gui; -}; diff --git a/src/attr.c b/src/attr.c new file mode 100644 index 00000000..0c6d58ae --- /dev/null +++ b/src/attr.c @@ -0,0 +1,40 @@ +#include <string.h> +#include "attr.h" + +struct attr_name { + enum attr_type attr; + char *name; +}; + + +static struct attr_name attr_names[]={ +#define ATTR2(x,y) ATTR(x) +#define ATTR(x) { attr_##x, #x }, +#include "attr_def.h" +#undef ATTR2 +#undef ATTR +}; + +enum attr_type +attr_from_name(char *name) +{ + int i; + + for (i=0 ; i < sizeof(attr_names)/sizeof(struct attr_name) ; i++) { + if (! strcmp(attr_names[i].name, name)) + return attr_names[i].attr; + } + return attr_none; +} + +char * +attr_to_name(enum attr_type attr) +{ + int i; + + for (i=0 ; i < sizeof(attr_names)/sizeof(struct attr_name) ; i++) { + if (attr_names[i].attr == attr) + return attr_names[i].name; + } + return NULL; +} diff --git a/src/attr.h b/src/attr.h new file mode 100644 index 00000000..83a12f5b --- /dev/null +++ b/src/attr.h @@ -0,0 +1,24 @@ +#ifndef ATTR_H +#define ATTR_H + +enum attr_type { +#define ATTR2(x,y) attr_##x=y, +#define ATTR(x) attr_##x, +#include "attr_def.h" +#undef ATTR2 +#undef ATTR +}; + +struct attr { + enum attr_type type; + union { + char *str; + int num; + struct item *item; + } u; +}; + +enum attr_type attr_from_name(char *name); +char * attr_to_name(enum attr_type attr); + +#endif diff --git a/src/attr_def.h b/src/attr_def.h new file mode 100644 index 00000000..1a2d472c --- /dev/null +++ b/src/attr_def.h @@ -0,0 +1,37 @@ +/* common */ +ATTR2(none,0x00000000) +ATTR(any) +ATTR2(type_item_begin,0x00010000) +ATTR(town_streets_item) +ATTR(street_name_item) +ATTR(street_name_numbers_item) +ATTR(street_item) +ATTR(street_number_item) +ATTR2(type_item_end,0x0001ffff) +ATTR2(type_int_begin,0x00020000) +ATTR(id) +ATTR(limit) +ATTR2(type_int_end,0x0002ffff) +ATTR2(type_string_begin,0x00030000) +ATTR(label) +ATTR(country_all) +ATTR(country_iso3) +ATTR(country_iso2) +ATTR(country_car) +ATTR(country_name) +ATTR(town_name) +ATTR(town_postal) +ATTR(district_name) +ATTR(street_name) +ATTR(street_name_systematic) +ATTR(street_number) +ATTR(debug) +ATTR(address) +ATTR(phone) +ATTR(entry_fee) +ATTR(open_hours) +/* poi */ +ATTR(icon) +ATTR(info_html) +ATTR(price_html) +ATTR2(type_string_end,0x0003ffff) diff --git a/src/callback.c b/src/callback.c new file mode 100644 index 00000000..9a4cad92 --- /dev/null +++ b/src/callback.c @@ -0,0 +1,112 @@ +#include <glib.h> +#include "callback.h" + +struct callback { + void (*func)(); + int pcount; + void *p[0]; + +}; + +struct callback_list { + GList *list; +}; + +struct callback_list * +callback_list_new(void) +{ + struct callback_list *ret=g_new0(struct callback_list, 1); + + return ret; +} + +struct callback * +callback_list_add_new(struct callback_list *l, void (*func)(), int pcount, void **p) +{ + struct callback *ret; + int i; + + ret=g_malloc0(sizeof(struct callback)+pcount*sizeof(void *)); + ret->func=func; + ret->pcount=pcount; + for (i = 0 ; i < pcount ; i++) { + ret->p[i]=p[i]; + } + l->list=g_list_prepend(l->list, ret); + return ret; +} + +void +callback_list_remove_destroy(struct callback_list *l, struct callback *cb) +{ + l->list=g_list_remove(l->list, cb); + g_free(cb); +} + + +void +callback_list_call(struct callback_list *l, int pcount, void **p) +{ + void *pf[8]; + struct callback *cb; + GList *cbi; + int i; + + cbi=l->list; + while (cbi) { + cb=cbi->data; + if (cb->pcount + pcount <= 8) { + for (i = 0 ; i < cb->pcount ; i++) + pf[i]=cb->p[i]; + for (i = 0 ; i < pcount ; i++) + pf[i+cb->pcount]=p[i]; + switch (cb->pcount+pcount) { + case 8: + cb->func(p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7]); + break; + case 7: + cb->func(p[0],p[1],p[2],p[3],p[4],p[5],p[6]); + break; + case 6: + cb->func(p[0],p[1],p[2],p[3],p[4],p[5]); + break; + case 5: + cb->func(p[0],p[1],p[2],p[3],p[4]); + break; + case 4: + cb->func(p[0],p[1],p[2],p[3]); + break; + case 3: + cb->func(p[0],p[1],p[2]); + break; + case 2: + cb->func(p[0],p[1]); + break; + case 1: + cb->func(p[0]); + break; + case 0: + cb->func(); + break; + } + } else { + g_warning("too many parameters for callback\n"); + } + cbi=g_list_next(cbi); + } + +} + + +void +callback_list_destroy(struct callback_list *l) +{ + GList *cbi; + cbi=l->list; + while (cbi) { + g_free(cbi->data); + cbi=g_list_next(cbi); + } + g_list_free(l->list); + g_free(l); +} diff --git a/src/callback.h b/src/callback.h new file mode 100644 index 00000000..6719faaf --- /dev/null +++ b/src/callback.h @@ -0,0 +1,15 @@ +#ifdef __cplusplus +extern "C" { +#endif +/* prototypes */ +struct callback; +struct callback_list; +struct callback_list *callback_list_new(void); +struct callback *callback_list_add_new(struct callback_list *l, void (*func)(void), int pcount, void **p); +void callback_list_remove_destroy(struct callback_list *l, struct callback *cb); +void callback_list_call(struct callback_list *l, int pcount, void **p); +void callback_list_destroy(struct callback_list *l); +/* end of prototypes */ +#ifdef __cplusplus +} +#endif diff --git a/src/color.h b/src/color.h new file mode 100644 index 00000000..9fdfd3b7 --- /dev/null +++ b/src/color.h @@ -0,0 +1,3 @@ +struct color { + int r,g,b; +}; diff --git a/src/command.c b/src/command.c deleted file mode 100644 index ba463168..00000000 --- a/src/command.c +++ /dev/null @@ -1,147 +0,0 @@ -#include <stdio.h> -#include <string.h> -#include "coord.h" -#include "town.h" -#include "street.h" -#include "command.h" - -/* Phonetisch - "KLEIN " -> CL - (x)(x)->x - EI:AY - E:- - F:V - G:C - H:- - I:Y - J:Y - K:C - T:D - W:V -*/ - -struct tree_hdr { - unsigned int addr; - unsigned int size; - unsigned int low; -}; - -struct tree_leaf { - unsigned int low; - unsigned int data; - unsigned char text[0]; -}; - -#if 0 -static int -compare(char *s1, char *s2) -{ - char s1_exp, s2_exp; - for (;;) { - s1_exp=*s1++; - s2_exp=*s2++; - if (! s1_exp && ! s2_exp) - return 0; - if (s1_exp == 'A' && *s1 == 'E') { s1_exp='Ä'; s1++; } - if (s1_exp == 'O' && *s1 == 'E') { s1_exp='Ö'; s1++; } - if (s1_exp == 'U' && *s1 == 'E') { s1_exp='Ü'; s1++; } - if (s2_exp == 'A' && *s2 == 'E') { s2_exp='Ä'; s2++; } - if (s2_exp == 'O' && *s2 == 'E') { s2_exp='Ö'; s2++; } - if (s2_exp == 'U' && *s2 == 'E') { s2_exp='Ü'; s2++; } - if (s1_exp != s2_exp) - return s1_exp-s2_exp; - } -#if 0 - for (;;) { - while (*s1 && *s1 == *s2) { - s1++; - s2++; - } - if (! *s1 && ! *s2) - return 0; - if (! *s1) - return -1; - if (! *s2) - return 1; - if (*s1 < *s2 && *s2 < 0x80) - return -1; - if (*s1 > *s2 && *s1 < 0x80) - return 1; - s1_exp=*s1; - s2_exp=*s2; - if (s1_exp >= 0x80) - s1_exp=' '; - if (s2_exp >= 0x80) - s2_exp=' '; -#if 0 - if (*s1 == (unsigned char)'Ä') s1_exp='A'; - if (*s1 == (unsigned char)'Ö') s1_exp='O'; - if (*s1 == (unsigned char)'Ü') s1_exp='U'; - if (*s1 == (unsigned char)'ä') s1_exp='a'; - if (*s1 == (unsigned char)'ö') s1_exp='o'; - if (*s1 == (unsigned char)'ü') s1_exp='u'; - if (*s1 == (unsigned char)'ß') s1_exp='s'; - if (*s2 == (unsigned char)'Ä') s2_exp='A'; - if (*s2 == (unsigned char)'Ö') s2_exp='O'; - if (*s2 == (unsigned char)'Ü') s2_exp='U'; - if (*s2 == (unsigned char)'ä') s2_exp='a'; - if (*s2 == (unsigned char)'ö') s2_exp='o'; - if (*s2 == (unsigned char)'ü') s2_exp='u'; - if (*s2 == (unsigned char)'ß') s2_exp='s'; -#endif - if (s1_exp < s2_exp) - return -1; - if (s1_exp > s2_exp) - return 1; - printf("Problem %c vs %c\n", *s1, *s2); - exit(1); - } -#endif -} -#endif - -void -command_goto(struct container *co, const char *arg) -{ -#if 0 - struct container *co=map->container; - struct town_list *list,*curr,*best=NULL; - int order=256; - int argc=0; - unsigned long x,y,scale; - char args[strlen(arg)+1]; - char *argv[strlen(arg)+1]; - char *tok; - - - strcpy(args, arg); - tok=strtok(args, " "); - while (tok) { - argv[argc++]=tok; - tok=strtok(NULL," "); - } - - list=NULL; - town_search_by_name(&list, co->map_data, argv[0], 0, 10000); - town_get_by_index(co->map_data, 0x311d54cb); - curr=list; - while (curr) { - if (curr->town->order < order) { - order=curr->town->order; - best=curr; - } - curr=curr->next; - } - if (best) { - printf("'%s' '%s' '%s' '%s'\n", best->town->name, best->town->district, best->town->postal_code1, best->town->postal_code2); -#if 0 - street_search_by_name(class->map_data, best->town->country, best->town->street_assoc, 0, argv[1]); -#endif - map_get_view(map, &x, &y, &scale); - x=best->town->c->x; - y=best->town->c->y; - map_set_view(map, x, y, scale); - } - town_list_free(list); -#endif -} diff --git a/src/command.h b/src/command.h deleted file mode 100644 index 5082fa04..00000000 --- a/src/command.h +++ /dev/null @@ -1 +0,0 @@ -void command_goto(struct container *co, const char *arg); diff --git a/src/compass.c b/src/compass.c index 4daa430f..dff312ec 100644 --- a/src/compass.c +++ b/src/compass.c @@ -7,10 +7,10 @@ #include "transform.h" #include "route.h" #include "vehicle.h" -#include "container.h" -#include "compass.h" +#include "navit.h" #include "compass.h" +#if 0 struct compass { struct graphics *gr; struct graphics_gc *bg; @@ -83,6 +83,7 @@ compass_draw(struct compass *comp, struct container *co) handle(comp->gr,comp->white, &p, 20,0); else handle(comp->gr, comp->white, &p, 20, -*vehicle_dir); +#if 0 /* FIXME */ dest=route_get_destination(co->route); if (dest) { pos=vehicle_pos_get(co->vehicle); @@ -107,6 +108,7 @@ compass_draw(struct compass *comp, struct container *co) comp->gr->draw_text(comp->gr, comp->green, NULL, comp->font, buffer, &p, 0x10000, 0); } +#endif comp->gr->draw_mode(comp->gr, draw_mode_end); } @@ -131,3 +133,4 @@ compass_new(struct container *co) compass_draw(this, co); return this; } +#endif diff --git a/src/coord.c b/src/coord.c index 7ccc8e2e..6f22a8d8 100644 --- a/src/coord.c +++ b/src/coord.c @@ -1,4 +1,12 @@ +#include <glib.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include "debug.h" #include "coord.h" +#include "transform.h" +#include "projection.h" /** * @defgroup coord Coordinate handling functions * @{ @@ -19,4 +27,172 @@ coord_get(unsigned char **p) return ret; } +struct coord * +coord_new(int x, int y) +{ + struct coord *c=g_new(struct coord, 1); + + c->x=x; + c->y=y; + + return c; +} + +void +coord_destroy(struct coord *c) +{ + g_free(c); +} + +struct coord_rect * +coord_rect_new(struct coord *lu, struct coord *rl) +{ + struct coord_rect *r=g_new(struct coord_rect, 1); + + g_assert(lu->x <= rl->x); + g_assert(lu->y >= rl->y); + + r->lu=*lu; + r->rl=*rl; + + return r; + +} + +void +coord_rect_destroy(struct coord_rect *r) +{ + g_free(r); +} + +int +coord_rect_overlap(struct coord_rect *r1, struct coord_rect *r2) +{ + g_assert(r1->lu.x <= r1->rl.x); + g_assert(r1->lu.y >= r1->rl.y); + g_assert(r2->lu.x <= r2->rl.x); + g_assert(r2->lu.y >= r2->rl.y); + if (r1->lu.x > r2->rl.x) + return 0; + if (r1->rl.x < r2->lu.x) + return 0; + if (r1->lu.y < r2->rl.y) + return 0; + if (r1->rl.y > r2->lu.y) + return 0; + return 1; +} + +int +coord_rect_contains(struct coord_rect *r, struct coord *c) +{ + g_assert(r->lu.x <= r->rl.x); + g_assert(r->lu.y >= r->rl.y); + if (c->x < r->lu.x) + return 0; + if (c->x > r->rl.x) + return 0; + if (c->y < r->rl.y) + return 0; + if (c->y > r->lu.y) + return 0; + return 1; +} + +void +coord_rect_extend(struct coord_rect *r, struct coord *c) +{ + if (c->x < r->lu.x) + r->lu.x=c->x; + if (c->x > r->rl.x) + r->rl.x=c->x; + if (c->y < r->rl.y) + r->rl.y=c->y; + if (c->y > r->lu.y) + r->lu.y=c->y; +} + + /* [Proj:][Ã]DMM.ss[S][S]... N/S [D][D]DMM.ss[S][S]... E/W */ + /* [Proj:][-][D]D.d[d]... [-][D][D]D.d[d]... */ + /* [Proj:][-]0xX [-]0xX */ + +int +coord_parse(const char *c_str, enum projection pro, struct coord *c_ret) +{ + int debug=0; + char *proj=NULL,*s,*co; + const char *str=c_str; + int args,ret; + struct coord_geo g; + struct coord c; + enum projection str_pro=projection_none; + + dbg(1,"enter('%s',%d,%p)\n", c_str, pro, c_ret); + s=index(str,' '); + co=index(str,':'); + if (co && co < s) { + proj=malloc(co-str+1); + strncpy(proj, str, co-str); + proj[co-str]='\0'; + dbg(1,"projection=%s\n", proj); + str=co+1; + s=index(str,' '); + } + while (*s == ' ') { + s++; + } + if (!strncmp(str, "0x", 2) || !strncmp(str,"-0x", 3)) { + args=sscanf(str, "%i %i%n",&c.x, &c.y, &ret); + if (args < 2) + return 0; + dbg(1,"str='%s' x=0x%x y=0x%x c=%d\n", str, c.x, c.y, ret); + dbg(1,"rest='%s'\n", str+ret); + + if (str_pro == projection_none) + str_pro=projection_mg; + if (str_pro == projection_mg) { + *c_ret=c; + } else { + printf("help\n"); + } + } else if (*s == 'N' || *s == 'n' || *s == 'S' || *s == 's') { + dbg(1,"str='%s'\n", str); + double lng, lat; + char ns, ew; + args=sscanf(str, "%lf %c %lf %c%n", &lat, &ns, &lng, &ew, &ret); + if (args < 4) + return 0; + if (str_pro == projection_none) { + g.lat=floor(lat/100); + lat-=g.lat*100; + g.lat+=lat/60; + g.lng=floor(lng/100); + lng-=g.lng*100; + g.lng+=lng/60; + transform_from_geo(pro, &g, c_ret); + } + if (debug) { + printf("str='%s' x=%f ns=%c y=%f ew=%c c=%d\n", str, lng, ns, lat, ew, ret); + printf("rest='%s'\n", str+ret); + } + } else { + double lng, lat; + args=sscanf(str, "%lf %lf%n", &lng, &lat, &ret); + if (args < 2) + return 0; + printf("str='%s' x=%f y=%f c=%d\n", str, lng, lat, ret); + printf("rest='%s'\n", str+ret); + } + if (debug) + printf("rest='%s'\n", str+ret); + ret+=str-c_str; + if (debug) { + printf("args=%d\n", args); + printf("ret=%d delta=%d ret_str='%s'\n", ret, str-c_str, c_str+ret); + } + if (proj) + free(proj); + return ret; +} + /** @} */ diff --git a/src/coord.h b/src/coord.h index 550c0322..13491d22 100644 --- a/src/coord.h +++ b/src/coord.h @@ -1,12 +1,15 @@ #ifndef COORD_H #define COORD_H -#include "types.h" - /*! A integer mercator coordinate */ struct coord { - s32 x; /*!< X-Value */ - s32 y; /*!< Y-Value */ + int x; /*!< X-Value */ + int y; /*!< Y-Value */ +}; + +struct coord_rect { + struct coord lu; + struct coord rl; }; //! A double mercator coordinate @@ -21,6 +24,17 @@ struct coord_geo { double lat; /*!< Latitude */ }; +enum projection; + struct coord * coord_get(unsigned char **p); +struct coord * coord_new(int x, int y); +void coord_destroy(struct coord *c); +int coord_parse(const char *c_str, enum projection pro, struct coord *c_ret); +struct coord_rect * coord_rect_new(struct coord *lu, struct coord *rl); +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); + #endif diff --git a/src/country.c b/src/country.c index 4f3a5d00..9d49ef59 100644 --- a/src/country.c +++ b/src/country.c @@ -1,10 +1,32 @@ #include <string.h> #include <stdio.h> #include <glib.h> +#include "debug.h" +#include "attr.h" +#include "item.h" #include "country.h" +#include "search.h" + +struct country { + int id; + char *car; + char *iso2; + char *iso3; + char *name; +}; struct country country[]= { + { 1 ,"CZ", "CZ", "CZE", "Tschechische Republik"}, + { 2 ,"SK", "SK", "SVK", "Slowakei"}, + { 7 ,"RSM", "SM", "SMR", "San Marino"}, + {11 ,"EST", "EE", "EST", "Estland"}, + {12 ,"GE", "GE", "GEO", "Georgien"}, + {13 ,"LV", "LV", "LVA", "Lettland"}, + {14 ,"LT", "LT", "LTU", "Litauen"}, + {15 ,"MD", "MD", "MDA", "Moldawien"}, {16 ,"RUS", "RU", "RUS", "Rußland"}, + {17 ,"UA", "UA", "UKR", "Ukraine"}, + {18 ,"BY", "BY", "BLR", "Weißrussland"}, {20 ,"ET", "EG", "EGY", "Ägypten"}, {30 ,"GR", "GR", "GRC", "Griechenland"}, {31 ,"NL", "NL", "NLD", "Niederlande"}, @@ -18,77 +40,163 @@ struct country country[]= { {43 ,"A", "AT", "AUT", "Österreich"}, {44 ,"GB", "GB", "GBR", "Grossbritannien"}, {45 ,"DK", "DK", "DNK", "Dänemark"}, + {46 ,"S", "SE", "SWE", "Schweden"}, {47 ,"N", "NO", "NOR", "Norwegen"}, + {48 ,"PL", "PL", "POL", "Polen"}, {49 ,"D", "DE", "DEU", "Deutschland"}, + {50 ,"GBZ", "GI", "GIB", "Gibraltar"}, {51 ,"P", "PT", "PRT", "Portugal"}, {52 ,"L", "LU", "LUX", "Luxemburg"}, + {53 ,"IRL", "IE", "IRL", "Irland"}, + {54 ,"IS", "IS", "ISL", "Island"}, + {55 ,"AL", "AL", "ALB", "Albanien"}, + {56 ,"M", "MT", "MLT", "Malta"}, + {57 ,"CY", "CY", "CYP", "Zypern"}, + {58 ,"FIN", "FI", "FIN", "Finnland"}, + {59 ,"BG", "BG", "BGR", "Bulgarien"}, + {61 ,"RL", "LB", "LBN", "Libanon"}, + {62 ,"AND", "AD", "AND", "Andorra"}, + {63 ,"SYR", "SY", "SYR", "Syrien"}, + {66 ,"KSA", "SA", "SAU", "Saudi-Arabien"}, {71 ,"LAR", "LY", "LYB", "Libyen"}, + {72 ,"IL", "IL", "ISR", "Israel"}, + {73 ,"AUT", "PS", "PSE", "Palästinensische Autonomiegebiete"}, + {75 ,"FL", "LI", "LIE", "Liechtenstein"}, {76 ,"MA", "MA", "MAR", "Marokko"}, + {77 ,"DZ", "DZ", "DZA", "Algerien"}, {78 ,"TN", "TN", "TUN", "Tunesien"}, + {81 ,"SRB", "RS", "SRB", "Serbien"}, + {83 ,"HKJ", "JO", "JOR", "Jordanien"}, + {85 ,"NDH", "HR", "HRV", "Kroatien"}, + {86 ,"SLO", "SI", "SVN", "Slowenien"}, + {87 ,"BIH", "BA", "BIH", "Bosnien und Herzegowina"}, + {89 ,"MK", "MK", "MKD", "Mazedonien"}, + {90 ,"TR", "TR", "TUR", "Türkei"}, + {93 ,"MC", "MC", "MCO", "Monaco"}, + {94 ,"AZ", "AZ", "AZE", "Aserbaidschan"}, + {95 ,"ARM", "AM", "ARM", "Armenien"}, + {98 ,"FO", "FO", "FRO", "Färöer"}, + {99 ,"WSA", "EH", "ESH", "Westsahara"}, + {336 ,NULL, "SJ", "SJM", "Svalbard und Jan Mayen"}, }; -struct country * -country_get_by_id(int id) -{ - int i; - for (i=0 ; i < sizeof(country)/sizeof(struct country); i++) { - if (id == country[i].id) { - return &country[i]; - } - } - return NULL; -} -static int -compare(const char *name1, const char *name2, int len, int partial) -{ - if (partial) - return strncasecmp(name1, name2, len); - else - return strcasecmp(name1, name2); -} +struct country_search { + struct attr search; + int len; + int partial; + struct item item; + int count; + struct country *country; + enum attr_type attr_next; +}; static int -search(int offset, const char *name, int partial, int (*func)(struct country *cou, void *data), void *data) +country_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr) { - char *col; - int i,ret,len=strlen(name); - int debug=0; - - for (i=0 ; i < sizeof(country)/sizeof(struct country); i++) { - col=G_STRUCT_MEMBER(char *,country+i,offset); - if (debug) - printf("comparing '%s'\n", col); - if (!compare(col, name, len, partial)) { - ret=(*func)(&country[i], data); - if (ret) - return 1; - } - col+=sizeof(struct country); - } - return 0; + struct country_search *this=priv_data; + struct country *country=this->country; + + attr->type=attr_type; + switch (attr_type) { + case attr_any: + while (this->attr_next != attr_none) { + if (country_attr_get(this, this->attr_next, attr)) + return 1; + } + return 0; + case attr_label: + attr->u.str=country->name; + this->attr_next=attr_id; + return 1; + case attr_id: + attr->u.num=country->id; + this->attr_next=country->car ? attr_country_car : attr_country_iso2; + return 1; + case attr_country_car: + attr->u.str=country->car; + this->attr_next=attr_country_iso2; + return attr->u.str ? 1 : 0; + case attr_country_iso2: + attr->u.str=country->iso2; + this->attr_next=attr_country_iso3; + return 1; + case attr_country_iso3: + attr->u.str=country->iso3; + this->attr_next=attr_country_name; + return 1; + case attr_country_name: + attr->u.str=country->name; + this->attr_next=attr_none; + return 1; + default: + return 0; + } } -int -country_search_by_name(const char *name, int partial, int (*func)(struct country *cou, void *data), void *data) + + +struct item_methods country_meth = { + NULL, /* coord_rewind */ + NULL, /* coord_get */ + NULL, /* attr_rewind */ + country_attr_get, /* attr_get */ +}; + +struct country_search * +country_search_new(struct attr *search, int partial) { - return search(G_STRUCT_OFFSET(struct country, name), name, partial, func, data); + struct country_search *ret=g_new(struct country_search, 1); + ret->search=*search; + ret->len=strlen(search->u.str); + ret->partial=partial; + ret->count=0; + + ret->item.type=type_country_label; + ret->item.id_hi=0; + ret->item.map=NULL; + ret->item.meth=&country_meth; + ret->item.priv_data=ret; + + return ret; } -int -country_search_by_car(const char *name, int partial, int (*func)(struct country *cou, void *data), void *data) +static int +match(struct country_search *this, enum attr_type type, const char *name) { - return search(G_STRUCT_OFFSET(struct country, car), name, partial, func, data); + int ret; + if (!name) + return 0; + if (this->search.type != type && this->search.type != attr_country_all) + return 0; + if (this->partial) + ret=(strncasecmp(this->search.u.str, name, this->len) == 0); + else + ret=(strcasecmp(this->search.u.str, name) == 0); + return ret; + } -int -country_search_by_iso2(const char *name, int partial, int (*func)(struct country *cou, void *data), void *data) + +struct item * +country_search_get_item(struct country_search *this) { - return search(G_STRUCT_OFFSET(struct country, iso2), name, partial, func, data); + for (;;) { + if (this->count >= sizeof(country)/sizeof(struct country)) + return NULL; + this->country=&country[this->count++]; + if (match(this, attr_country_iso3, this->country->iso3) || + match(this, attr_country_iso2, this->country->iso2) || + match(this, attr_country_car, this->country->car) || + match(this, attr_country_name, this->country->name)) { + this->item.id_lo=this->country->id; + return &this->item; + } + } } -int -country_search_by_iso3(const char *name, int partial, int (*func)(struct country *cou, void *data), void *data) +void +country_search_destroy(struct country_search *this) { - return search(G_STRUCT_OFFSET(struct country, iso3), name, partial, func, data); + g_free(this); } diff --git a/src/country.h b/src/country.h index 616a6c26..83be5b95 100644 --- a/src/country.h +++ b/src/country.h @@ -1,12 +1,7 @@ -struct country { - int id; - char *car; - char *iso2; - char *iso3; - char *name; -}; -struct country * country_get_by_id(int id); -int country_search_by_name(const char *name, int partial, int (*func)(struct country *cou, void *data), void *data); -int country_search_by_car(const char *name, int partial, int (*func)(struct country *cou, void *data), void *data); -int country_search_by_iso2(const char *name, int partial, int (*func)(struct country *cou, void *data), void *data); -int country_search_by_iso3(const char *name, int partial, int (*func)(struct country *cou, void *data), void *data); +/* prototypes */ +struct attr; +struct country_search; +struct item; +struct country_search *country_search_new(struct attr *search, int partial); +struct item *country_search_get_item(struct country_search *this); +void country_search_destroy(struct country_search *this); diff --git a/src/cursor.c b/src/cursor.c index d126f684..933a8347 100644 --- a/src/cursor.c +++ b/src/cursor.c @@ -8,59 +8,87 @@ #include <glib.h> #include "coord.h" #include "transform.h" +#include "projection.h" +#include "point.h" #include "graphics.h" #include "statusbar.h" #include "menu.h" #include "vehicle.h" -#include "container.h" +#include "navit.h" +#include "color.h" #include "cursor.h" #include "compass.h" -#include "track.h" +/* #include "track.h" */ +struct callback { + void (*func)(struct cursor *, void *data); + void *data; +}; -#include "route.h" struct cursor { - struct container *co; + struct graphics *gra; struct graphics_gc *cursor_gc; + struct transformation *trans; struct point cursor_pnt; + struct callback offscreen_callback; + struct callback update_callback; + struct vehicle *v; + int dir; + struct coord pos; + void *vehicle_callback; }; struct coord * cursor_pos_get(struct cursor *this) { - return vehicle_pos_get(this->co->vehicle); + return &this->pos; +#if 0 + return vehicle_pos_get(this->v); +#endif +} + + +struct coord * +cursor_pos_set(struct cursor *this, struct coord *pos) +{ + this->pos=*pos; +#if 0 + return vehicle_pos_get(this->v); +#endif } + static void -cursor_draw(struct cursor *this, struct point *pnt, double *speed, double *dir) +cursor_draw(struct cursor *this, struct point *pnt, int dir, int draw_dir) { int x=this->cursor_pnt.x; int y=this->cursor_pnt.y; int r=12,lw=2; double dx,dy; double fac1,fac2; - int dir_i=*dir-this->co->trans->angle; struct point cpnt[3]; - struct graphics *gra=this->co->gra; + struct graphics *gra=this->gra; if (pnt && x == pnt->x && y == pnt->y) return; + if (!graphics_ready(gra)) + return; cpnt[0]=this->cursor_pnt; cpnt[0].x-=r+lw; cpnt[0].y-=r+lw; - gra->draw_restore(gra, &cpnt[0], (r+lw)*2, (r+lw)*2); + graphics_draw_restore(gra, &cpnt[0], (r+lw)*2, (r+lw)*2); if (pnt) { - gra->draw_mode(gra, draw_mode_cursor); + graphics_draw_mode(gra, draw_mode_cursor); this->cursor_pnt=*pnt; x=pnt->x; y=pnt->y; cpnt[0].x=x; cpnt[0].y=y; - gra->draw_circle(gra, this->cursor_gc, &cpnt[0], r*2); - if (*speed > 2.5) { - dx=sin(M_PI*dir_i/180); - dy=-cos(M_PI*dir_i/180); + graphics_draw_circle(gra, this->cursor_gc, &cpnt[0], r*2); + if (draw_dir) { + dx=sin(M_PI*dir/180.0); + dy=-cos(M_PI*dir/180.0); fac1=0.7*r; fac2=0.4*r; @@ -70,15 +98,16 @@ cursor_draw(struct cursor *this, struct point *pnt, double *speed, double *dir) cpnt[1].y=y+dy*r; cpnt[2].x=x-dx*fac1-dy*fac2; cpnt[2].y=y-dy*fac1+dx*fac2; - gra->draw_lines(gra, this->cursor_gc, cpnt, 3); + graphics_draw_lines(gra, this->cursor_gc, cpnt, 3); } else { cpnt[1]=cpnt[0]; - gra->draw_lines(gra, this->cursor_gc, cpnt, 2); + graphics_draw_lines(gra, this->cursor_gc, cpnt, 2); } - gra->draw_mode(gra, draw_mode_end); + graphics_draw_mode(gra, draw_mode_end); } } +#if 0 static void cursor_map_reposition_screen(struct cursor *this, struct coord *c, double *dir, int x_new, int y_new) { @@ -153,47 +182,74 @@ cursor_map_reposition_boundary(struct cursor *this, struct coord *c, double *dir return 0; } +#endif + +int +cursor_get_dir(struct cursor *this) +{ + return this->dir; +} + static void -cursor_update(struct vehicle *v, void *t) +cursor_update(struct vehicle *v, void *data) { - struct cursor *this=t; + struct cursor *this=data; struct point pnt; struct coord *pos; double *dir; + double *speed; + enum projection pro; + int border=10; if (v) { pos=vehicle_pos_get(v); dir=vehicle_dir_get(v); - track_update(this->co->track, pos, (int)(*dir)); - if (this->co->flags->orient_north) - dir=0; - route_set_position(this->co->route, cursor_pos_get(this->co->cursor)); - if (!transform(this->co->trans, pos, &pnt)) { - cursor_map_reposition(this, pos, dir); - transform(this->co->trans, pos, &pnt); + speed=vehicle_speed_get(v); + pro=vehicle_projection(v); + this->dir=*dir; + this->pos=*pos; + if (this->update_callback.func) + (*this->update_callback.func)(this, this->update_callback.data); + if (!transform(this->trans, pro, &this->pos, &pnt) || !transform_within_border(this->trans, &pnt, border)) { + if (this->offscreen_callback.func) + (*this->offscreen_callback.func)(this, this->offscreen_callback.data); + transform(this->trans, pro, &this->pos, &pnt); } - if (pnt.x < 0 || pnt.y < 0 || pnt.x >= this->co->trans->width || pnt.y >= this->co->trans->height || this->co->flags->fixedpos_mode) { - cursor_map_reposition(this, pos, dir); - transform(this->co->trans, pos, &pnt); - } - if (cursor_map_reposition_boundary(this, pos, dir, &pnt)) - transform(this->co->trans, pos, &pnt); - cursor_draw(this, &pnt, vehicle_speed_get(v), vehicle_dir_get(v)); + cursor_draw(this, &pnt, *dir-transform_get_angle(this->trans, 0), *speed > 2.5); } +#if 0 compass_draw(this->co->compass, this->co); - osd_draw(this->co->osd, this->co); +#endif } -extern void *vehicle; - struct cursor * -cursor_new(struct container *co, struct vehicle *v) +cursor_new(struct graphics *gra, struct vehicle *v, struct color *c, struct transformation *t) { + printf("cursor_new v=%p\n", v); struct cursor *this=g_new(struct cursor,1); - this->co=co; - this->cursor_gc=co->gra->gc_new(co->gra); - co->gra->gc_set_foreground(this->cursor_gc, 0x0000, 0x0000, 0xffff); - co->gra->gc_set_linewidth(this->cursor_gc, 2); - vehicle_callback_register(v, cursor_update, this); + this->gra=gra; + this->trans=t; + this->cursor_gc=graphics_gc_new(gra); + this->v=v; + graphics_gc_set_foreground(this->cursor_gc, c); + graphics_gc_set_linewidth(this->cursor_gc, 2); + this->vehicle_callback=vehicle_callback_register(v, cursor_update, this); return this; } + +void +cursor_register_offscreen_callback(struct cursor *this, void (*func)(struct cursor *cursor, void *data), void *data) +{ + this->offscreen_callback.func=func; + this->offscreen_callback.data=data; +} + + +void +cursor_register_update_callback(struct cursor *this, void (*func)(struct cursor *cursor, void *data), void *data) +{ + this->update_callback.func=func; + this->update_callback.data=data; +} + + diff --git a/src/cursor.h b/src/cursor.h index eeb63069..df15168a 100644 --- a/src/cursor.h +++ b/src/cursor.h @@ -1,6 +1,13 @@ +/* prototypes */ +struct color; +struct coord; struct cursor; -struct container; +struct graphics; +struct transformation; struct vehicle; - -struct coord * cursor_pos_get(struct cursor *this); -struct cursor *cursor_new(struct container *co, struct vehicle *v); +struct coord *cursor_pos_get(struct cursor *this); +struct coord *cursor_pos_set(struct cursor *this, struct coord *pos); +int cursor_get_dir(struct cursor *this); +struct cursor *cursor_new(struct graphics *gra, struct vehicle *v, struct color *c, struct transformation *t); +void cursor_register_offscreen_callback(struct cursor *this, void (*func)(struct cursor *cursor, void *data), void *data); +void cursor_register_update_callback(struct cursor *this, void (*func)(struct cursor *cursor, void *data), void *data); @@ -1,33 +1,50 @@ -#include "types.h" - -static inline u8 +static inline unsigned char get_u8(unsigned char **p) { return *((*p)++); } -static inline u16 +static inline unsigned short get_u16(unsigned char **p) { - u16 ret; - ret=*((u16 *)*p); - *p+=sizeof(u16); + unsigned short ret; + ret=*((unsigned short *)*p); + *p+=sizeof(unsigned short); return ret; } -static inline u32 +static inline unsigned short +get_u16_unal(unsigned char **p) { + unsigned short ret; + ret=*(*p)++; + ret|=(*(*p)++) << 8; + return ret; +} + + +static inline unsigned int get_u24(unsigned char **p) { - u32 ret; + unsigned long ret; ret=get_u16(p); ret|=*((*p)++) << 16; return ret; } -static inline u32 +static inline unsigned int get_u32(unsigned char **p) { - u32 ret; - ret=*((u32 *)*p); - *p+=sizeof(u32); + unsigned long ret; + ret=*((unsigned int *)*p); + *p+=sizeof(unsigned int); + return ret; +} + +static inline unsigned int +get_u32_unal(unsigned char **p) { + unsigned long ret; + ret=*(*p)++; + ret|=(*(*p)++) << 8; + ret|=(*(*p)++) << 16; + ret|=(*(*p)++) << 24; return ret; } @@ -38,5 +55,7 @@ get_string(unsigned char **p) while (**p) (*p)++; (*p)++; return ret; -} +} + +#define L(x) ({ unsigned char *t=(unsigned char *)&(x); t[0] | (t[1] << 8) | (t[2] << 16) | (t[3] << 24); }) diff --git a/src/data/Makefile.am b/src/data/Makefile.am new file mode 100644 index 00000000..35a11357 --- /dev/null +++ b/src/data/Makefile.am @@ -0,0 +1 @@ +SUBDIRS=mg textfile garmin_img diff --git a/src/data/garmin_img/Makefile.am b/src/data/garmin_img/Makefile.am new file mode 100644 index 00000000..7fb84323 --- /dev/null +++ b/src/data/garmin_img/Makefile.am @@ -0,0 +1,4 @@ +include $(top_srcdir)/Makefile.inc +AM_CPPFLAGS = @NAVIT_CFLAGS@ -I../.. +plugin_LTLIBRARIES = libdata_garmin_img.la +libdata_garmin_img_la_SOURCES = garmin_img.c diff --git a/src/data/garmin_img/garmin_img.c b/src/data/garmin_img/garmin_img.c new file mode 100644 index 00000000..86b03ca1 --- /dev/null +++ b/src/data/garmin_img/garmin_img.c @@ -0,0 +1,1486 @@ +#include <glib.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <math.h> +#include "plugin.h" +#include "data.h" +#include "map.h" +#include "maptype.h" +#include "item.h" +#include "attr.h" +#include "coord.h" +#include "transform.h" +#include "projection.h" +#include <stdio.h> +#include "attr.h" +#include "coord.h" + +struct file { + FILE *f; + int offset; +}; + + +int shift=5; +int subdiv_next=0x10; + + +static void * +file_read(struct file *f, int offset, int size) +{ + void *ptr; + int ret; + + ptr=calloc(size, 1); + if (! ptr) + return ptr; + fseek(f->f, f->offset+offset, SEEK_SET); + ret=fread(ptr, size, 1, f->f); + if (ret != 1) { + printf("fread %d vs %d offset %d+%d(0x%x)\n", ret, size, f->offset, offset,offset); + g_assert(1==0); + } + return ptr; +} + +static void +file_free(void *ptr) +{ + free(ptr); +} + +struct offset_len { + int offset; + int length; +} __attribute ((packed)); + +static void +dump_offset_len(struct offset_len *off_len) +{ + printf("offset: 0x%x(%d) length 0x%x(%d)\n", off_len->offset, off_len->offset, off_len->length, off_len->length); +} + +struct timestamp { + short creation_year; + char creation_month; + char creation_day; + char creation_hour; + char creation_minute; + char creation_second; +} __attribute__((packed)); + +struct img_header { + char xor; + char zero1[9]; + char update_month; + char update_year; + char zero2[3]; + char checksum[1]; + char signature[7]; + char unknown1[1]; + char unknown2[2]; + char unknown3[2]; + char unknown4[2]; + char unknown5[2]; + char zero3[25]; + struct timestamp ts; + char unknown6; + char map_file_identifier[7]; + char unknown12; + char map_description1[20]; + short unknown13; + short unknown14; + char e1; + char e2; + char other[413]; + char zero4[512]; + char unknown7; + char unknown8[11]; + int file_offset; + char unknown9; + char unknown10[15]; + char unknown11[480]; +} __attribute__((packed)); + +static void +dump_ts(struct timestamp *ts) +{ + printf("%d-%02d-%02d %02d:%02d:%02d\n", ts->creation_year, ts->creation_month, ts->creation_day, ts->creation_hour, ts->creation_minute, ts->creation_second); +} + +#if 0 +static void +dump_img(struct img_header *img_hdr) +{ + printf("signature: '%s'\n", img_hdr->signature); + printf("creation: "); + dump_ts(&img_hdr->ts); + printf("map_file_identifier: '%s'\n", img_hdr->map_file_identifier); + printf("file_offset: 0x%x\n", img_hdr->file_offset); + printf("e1: 0x%x(%d)\n", img_hdr->e1, img_hdr->e1); + printf("e2: 0x%x(%d)\n", img_hdr->e2, img_hdr->e2); + printf("offset 0x%x\n", (int) &img_hdr->e1 - (int) img_hdr); + printf("size %d\n", sizeof(*img_hdr)); +} +#endif + +struct fat_block { + char flag; + char filename[8]; + char type[3]; + int size; + char zero1; + char part; + char zero[14]; + unsigned short blocks[240]; +} __attribute__((packed)); + +#if 0 +static void +dump_fat_block(struct fat_block *fat_blk) +{ + int i=0; + char name[9]; + char type[4]; + printf("flag: 0x%x(%d)\n", fat_blk->flag, fat_blk->flag); + strcpy(name, fat_blk->filename); + name[8]='\0'; + strcpy(type, fat_blk->type); + type[3]='\0'; + printf("name: '%s.%s'\n", name, type); + printf("size: 0x%x(%d)\n", fat_blk->size, fat_blk->size); + printf("part: 0x%x(%d)\n", fat_blk->part, fat_blk->part); + printf("blocks: "); + while (i < 240) { + printf("0x%x(%d) ",fat_blk->blocks[i], fat_blk->blocks[i]); + if (fat_blk->blocks[i] == 0xffff) + break; + i++; + } + printf("size: %d\n", sizeof(*fat_blk)); + +} +#endif + +struct file_header { + short header_len; + char type[10]; + char unknown1; + char unknown2; + struct timestamp ts; +} __attribute__((packed)); + +static void +dump_file(struct file_header *fil_hdr) +{ + printf("header_len: %d\n", fil_hdr->header_len); + printf("type: '%s'\n", fil_hdr->type); + printf("unknown1: 0x%x(%d)\n", fil_hdr->unknown1, fil_hdr->unknown1); + printf("unknown2: 0x%x(%d)\n", fil_hdr->unknown2, fil_hdr->unknown2); + printf("creation: "); + dump_ts(&fil_hdr->ts); + printf("size %d\n", sizeof(*fil_hdr)); +} + +struct region_header { + struct file_header fil_hdr; + struct offset_len offset_len; +} __attribute__((packed)); + +#if 0 +static void +dump_region(struct region_header *rgn_hdr) +{ + dump_offset_len(&rgn_hdr->offset_len); +} +#endif + +struct map_priv { + int id; + char *filename; +}; + +struct map_rect_priv { + struct coord_rect r; + int limit; + + struct file tre; + struct tree_header *tre_hdr; + struct file rgn; + struct region_header *rgn_hdr; + struct file lbl; + struct label_header *lbl_hdr; + char *label; + + int subdiv_level_count; + int subdiv_pos; + char *subdiv; + + int rgn_offset; + int rgn_end; + struct rgn_point *pnt; + struct rgn_poly *ply; + unsigned char *ply_data; + int ply_bitpos; + int ply_bitcount; + int ply_lngbits; + int ply_latbits; + int ply_lng; + int ply_lat; + int ply_lnglimit; + int ply_latlimit; + int ply_lngsign; + int ply_latsign; + struct offset_len rgn_items[4]; + int rgn_type; + + int count; + + FILE *f; + long pos; + char line[256]; + int attr_pos; + enum attr_type attr_last; + char attrs[256]; + char attr[256]; + double lat,lng; + char lat_c,lng_c; + int eoc; + struct map_priv *m; + struct item item; +}; + +static int map_id; + +static int +contains_coord(char *line) +{ + return g_ascii_isdigit(line[0]); +} + +static int debug=1; + +static int +get_tag(char *line, char *name, int *pos, char *ret) +{ + int len,quoted; + char *p,*e,*n; + + if (debug) + printf("get_tag %s from %s\n", name, line); + if (! name) + return 0; + len=strlen(name); + if (pos) + p=line+*pos; + else + p=line; + for(;;) { + while (*p == ' ') { + p++; + } + if (! *p) + return 0; + n=p; + e=index(p,'='); + if (! e) + return 0; + p=e+1; + quoted=0; + while (*p) { + if (*p == ' ' && !quoted) + break; + if (*p == '"') + quoted=1-quoted; + p++; + } + if (e-n == len && !strncmp(n, name, len)) { + e++; + len=p-e; + if (e[0] == '"') { + e++; + len-=2; + } + strncpy(ret, e, len); + ret[len]='\0'; + if (pos) + *pos=p-line; + return 1; + } + } + return 0; +} + +static void +get_line(struct map_rect_priv *mr) +{ + mr->pos=ftell(mr->f); + fgets(mr->line, 256, mr->f); +} + +static void +map_destroy_garmin_img(struct map_priv *m) +{ + if (debug) + printf("map_destroy_garmin_img\n"); + g_free(m); +} + +static char * +map_charset_garmin_img(struct map_priv *m) +{ + return "iso8859-1"; +} + +static enum projection +map_projection_garmin_img(struct map_priv *m) +{ + return projection_garmin; +} + +struct label_data_offset { + struct offset_len offset_len; + char multiplier; + char data; +} __attribute ((packed)); + +#if 0 +static void +dump_label_data_offset(struct label_data_offset *lbl_dat) +{ + dump_offset_len(&lbl_dat->offset_len); + printf("multiplier 0x%x(%d)\n", lbl_dat->multiplier, lbl_dat->multiplier); + printf("data 0x%x(%d)\n", lbl_dat->data, lbl_dat->data); +} +#endif + +struct label_data { + struct offset_len offset_len; + short size; + int zero; +} __attribute ((packed)); + +static void +dump_label_data(struct label_data *lbl_dat) +{ + dump_offset_len(&lbl_dat->offset_len); + printf("size 0x%x(%d)\n", lbl_dat->size, lbl_dat->size); +} + +struct tree_header { + struct file_header fil_hdr; + char boundary[12]; + struct offset_len level; + struct offset_len subdivision; + struct label_data copyright; + struct offset_len tre7; + short unknown1; + char zero1; + struct label_data polyline; + struct label_data polygon; + struct label_data point; + int mapid; +}; + +static void +dump_tree_header(struct tree_header *tre_hdr) +{ + printf("tree_header:\n"); + dump_file(&tre_hdr->fil_hdr); + printf("level: "); dump_offset_len(&tre_hdr->level); + printf("subdivision: "); dump_offset_len(&tre_hdr->subdivision); + printf("copyright: "); dump_label_data(&tre_hdr->copyright); + printf("polyline: "); dump_label_data(&tre_hdr->polyline); + printf("polygon: "); dump_label_data(&tre_hdr->polygon); + printf("point: "); dump_label_data(&tre_hdr->point); + printf("len: 0x%x(%d)\n", sizeof(*tre_hdr), sizeof(*tre_hdr)); +} + +struct label_header { + struct file_header fil_hdr; + struct label_data_offset label; + struct label_data country; + struct label_data region; + struct label_data city; + struct label_data poi_index; + struct label_data_offset poi_properties; + short zero1; + char zero2; + struct label_data poi_types; + struct label_data zip; + struct label_data hway; + struct label_data exit; + struct label_data hway_data; + int unknown1; + short unknown2; + struct offset_len sort_descriptor; + struct label_data lbl13; + struct label_data lbl14; +} __attribute((packed)); + +#if 0 +static void +dump_label(struct label_header *lbl_hdr) +{ + dump_file(&lbl_hdr->fil_hdr); + printf("label:\n"); + dump_label_data_offset(&lbl_hdr->label); + printf("country:\n"); + dump_label_data(&lbl_hdr->country); + printf("region:\n"); + dump_label_data(&lbl_hdr->region); + printf("city:\n"); + dump_label_data(&lbl_hdr->city); + printf("poi_index:\n"); + dump_label_data(&lbl_hdr->poi_index); + printf("poi_properties:\n"); + dump_label_data_offset(&lbl_hdr->poi_properties); + printf("poi_types:\n"); + dump_label_data(&lbl_hdr->poi_types); + printf("zip:\n"); + dump_label_data(&lbl_hdr->zip); + printf("hway:\n"); + dump_label_data(&lbl_hdr->hway); + printf("exit:\n"); + dump_label_data(&lbl_hdr->exit); + printf("hway_data:\n"); + dump_label_data(&lbl_hdr->hway_data); + printf("lbl13:\n"); + dump_label_data(&lbl_hdr->lbl13); + printf("lbl14:\n"); + dump_label_data(&lbl_hdr->lbl14); + printf("len: 0x%x(%d)\n", sizeof(*lbl_hdr), sizeof(*lbl_hdr)); +} +#endif + +struct triple { + unsigned char data[3]; +} __attribute((packed)); + +static unsigned int +triple_u(struct triple *t) +{ + return t->data[0] | (t->data[1] << 8) | (t->data[2] << 16); +} + +static int +triple(struct triple *t) +{ + int ret=t->data[0] | (t->data[1] << 8) | (t->data[2] << 16); + if (ret > 1<<23) + ret=ret-(1<<24); + return ret; +} + +static void +dump_triple_u(struct triple *t) +{ + int val=triple_u(t); + printf("0x%x(%d)\n", val, val); +} + +struct tcoord { + struct triple lng,lat; +} __attribute((packed)); + +static void +dump_tcoord(struct tcoord *t) +{ + printf ("0x%x(%d),0x%x(%d)\n", triple_u(&t->lng), triple_u(&t->lng), triple_u(&t->lat), triple_u(&t->lat)); +} + +struct level { + unsigned char zoom; + unsigned char bits_per_coord; + unsigned short subdivisions; +} __attribute((packed)); + +static void +dump_level(struct level *lvl) +{ + printf("level:\n"); + printf("\tzoom 0x%x(%d)\n", lvl->zoom, lvl->zoom); + printf("\tbits_per_coord 0x%x(%d)\n", lvl->bits_per_coord, lvl->bits_per_coord); + printf("\tsubdivisions 0x%x(%d)\n", lvl->subdivisions, lvl->subdivisions); +} + +struct subdivision { + struct triple rgn_offset; + unsigned char types; + struct tcoord center; + unsigned short width; + unsigned short height; + unsigned short next; +} __attribute((packed)); + +static void +dump_subdivision(struct subdivision *sub) +{ + printf("subdivision:\n"); + printf("\trgn_offset: "); dump_triple_u(&sub->rgn_offset); + printf("\ttypes: 0x%x(%d)\n", sub->types, sub->types); + printf("\tcenter: "); dump_tcoord(&sub->center); + printf("\tsize: 0x%x(%d)x0x%x(%d) %s\n",sub->width & 0x7fff, sub->width & 0x7fff, sub->height, sub->height, sub->width & 0x8000 ? "Terminating" : ""); + printf("\tnext: 0x%x(%d)\n",sub->next, sub->next); + + printf("\tlen: 0x%x(%d)\n", sizeof(*sub), sizeof(*sub)); +} + +struct rgn_point { + unsigned char info; + struct triple lbl_offset; + short lng_delta; + short lat_delta; + unsigned char subtype; +} __attribute((packed)); + +static void +dump_point(struct rgn_point *pnt) +{ + printf("point:\n"); + printf("\tinfo 0x%x(%d)\n", pnt->info, pnt->info); + printf("\tlbl_offset 0x%x(%d)\n", triple_u(&pnt->lbl_offset), triple_u(&pnt->lbl_offset)); + printf("\tlng_delta 0x%x(%d)\n", pnt->lng_delta, pnt->lng_delta); + printf("\tlat_delta 0x%x(%d)\n", pnt->lat_delta, pnt->lat_delta); + printf("\tsubtype 0x%x(%d)\n", pnt->subtype, pnt->subtype); + printf("\tlen: 0x%x(%d)\n", sizeof(*pnt), sizeof(*pnt)); +} + +struct rgn_poly { + unsigned char info; + struct triple lbl_offset; + short lng_delta; + short lat_delta; + union { + struct { + unsigned char bitstream_len; + unsigned char bitstream_info; + } __attribute((packed)) p1; + struct { + unsigned short bitstream_len; + unsigned char bitstream_info; + } __attribute((packed)) p2; + } __attribute((packed)) u; +} __attribute((packed)); + +static void +dump_poly(struct rgn_poly *ply) +{ + printf("poly:\n"); + printf("\tinfo 0x%x(%d)\n", ply->info, ply->info); + printf("\tlbl_offset 0x%x(%d)\n", triple_u(&ply->lbl_offset), triple_u(&ply->lbl_offset)); + printf("\tlng_delta 0x%x(%d)\n", ply->lng_delta, ply->lng_delta); + printf("\tlat_delta 0x%x(%d)\n", ply->lat_delta, ply->lat_delta); + if (ply->info & 0x80) { + printf("\tbitstream_len 0x%x(%d)\n", ply->u.p2.bitstream_len, ply->u.p2.bitstream_len); + printf("\tbitstream_info 0x%x(%d)\n", ply->u.p2.bitstream_info, ply->u.p2.bitstream_info); + } else { + printf("\tbitstream_len 0x%x(%d)\n", ply->u.p1.bitstream_len, ply->u.p1.bitstream_len); + printf("\tbitstream_info 0x%x(%d)\n", ply->u.p1.bitstream_info, ply->u.p1.bitstream_info); + } + printf("\tlen: 0x%x(%d)\n", sizeof(*ply), sizeof(*ply)); +} + +static void +dump_hex(void *ptr, int len) +{ + unsigned char *c=ptr; + while (len--) { + printf("%02x ", *c++); + } + printf("\n"); +} + +static void +dump_hex_r(void *ptr, int len, int rec) +{ + unsigned char *c=ptr; + int l=rec; + while (len--) { + printf("%02x ", *c++); + if (! --l) { + printf("\n"); + l=rec; + } + } + printf("\n"); +} + +#if 0 +static void +dump_label_offset(struct map_rect_priv *mr, int offset) +{ + void *p; + p=file_read(&mr->lbl, mr->lbl_hdr->label.offset_len.offset+offset, 128); + printf("%s\n", (char *)p); +} +#endif + + +#if 0 +static void +dump_region_item(struct subdivision *sub, struct file *rgn, struct map_rect_priv *mr) +{ + int offset,item_offset,i,j; + unsigned short count=0; + unsigned short *offsets[4]; + unsigned short *file_offsets; + struct rgn_point *pnt; + + offset=triple_u(&sub->rgn_offset)+mr->rgn_hdr->offset_len.offset; + file_offsets=file_read(rgn, offset, 90*sizeof(unsigned short)); + printf("0x%x ", offset); dump_hex(file_offsets, 90); + for (i=0 ; i < 4 ; i++) { + printf("i=%d\n", i); + if (sub->types & (0x10 << i)) { + if (count) { + offsets[i]=&file_offsets[count-1]; + } else + offsets[i]=&count; + count++; + } else + offsets[i]=NULL; + + } + count--; + count*=2; + for (i=0 ; i < 4 ; i++) { + printf("i=%d\n", i); + if (offsets[i]) { + printf("offset[%d]=0x%x(%d)\n", i, *offsets[i], *offsets[i]); + switch (i) { + case 0: + printf("point\n"); + break; + case 1: + printf("indexed point\n"); + break; + case 2: + printf("polyline\n"); + break; + case 3: + printf("polygon\n"); + break; + } + item_offset=offset+*offsets[i]; + switch (i) { + case 0: + case 1: + for (j = 0 ; j < 10 ; j++) { + struct coord_geo g; + char buffer[1024]; + double conv=180.0/(1UL<<23); + pnt=file_read(rgn, item_offset, sizeof(*pnt)*20); + // printf("0x%x ", item_offset); dump_hex(pnt, 32); + dump_point(pnt); + g.lng=(triple(&sub->center.lng)+(pnt->lng_delta << shift))*conv; + g.lat=(triple(&sub->center.lat)+(pnt->lat_delta << shift))*conv; + printf("%f %f\n", g.lng, g.lat); + transform_geo_text(&g, buffer); + printf("%s\n", buffer); + dump_label_offset(mr, triple_u(&pnt->lbl_offset)); + if (pnt->info & 0x80) + item_offset+=sizeof(*pnt); + else + item_offset+=sizeof(*pnt)-1; + } + } + } else { + printf("offset[%d] doesn't exist\n", i); + } + } + file_free(file_offsets); +} + +#endif + +static void +dump_levels(struct map_rect_priv *mr) +{ + int i,offset; + struct level *lvl; + + offset=mr->tre_hdr->level.offset; + for (i = 0 ; i < mr->tre_hdr->level.length/sizeof(*lvl) ; i++) { + lvl=file_read(&mr->tre, offset, sizeof(*lvl)); + dump_level(lvl); + offset+=sizeof(*lvl); + } +} + +#if 0 +static void +dump_tree(struct file *f, struct file *rgn, struct map_rect_priv *mr) +{ + struct tree_header *tre_hdr; + struct subdivision *sub; + int i,offset; + + tre_hdr=file_read(f, 0, sizeof(*tre_hdr)); + dump_tree_header(tre_hdr); + offset=tre_hdr->subdivision.offset; + sub=file_read(f, offset, sizeof(*sub)); + dump_subdivision(sub); + offset+=sizeof(*sub); + for (i = 1 ; i < tre_hdr->subdivision.length/sizeof(*sub) ; i++) { + printf("i=%d\n", i); + sub=file_read(f, offset, sizeof(*sub)); + dump_subdivision(sub); + dump_region_item(sub, rgn, mr); + if (sub->width & 0x8000) + break; + offset+=sizeof(*sub); + } + file_free(tre_hdr); +} +#endif + +#if 0 +static void +dump_labels(struct file *f) +{ + struct label_header *lbl_hdr; + + lbl_hdr=file_read(f, 0, sizeof(*lbl_hdr)); + printf("**labels**\n"); + dump_label(lbl_hdr); + file_free(lbl_hdr); +#if 0 + labels=alloca(lbl_hdr.label_length); + file_read(f, lbl_hdr.label_offset, labels, lbl_hdr.label_length); + l=labels; + while (l < labels+lbl_hdr.label_length) { + printf("'%s'(%d)\n", l, strlen(l)); + l+=strlen(l)+1; + } +#endif + +} +#endif + +static void +garmin_img_coord_rewind(void *priv_data) +{ +} + +static void +parse_line(struct map_rect_priv *mr) +{ + int pos=0; + sscanf(mr->line,"%lf %c %lf %c %n",&mr->lat,&mr->lat_c,&mr->lng,&mr->lng_c,&pos); + if (pos < strlen(mr->line)) { + strcpy(mr->attrs, mr->line+pos); + } +} + +static int +get_bits(struct map_rect_priv *mr, int bits) +{ + unsigned long ret; + ret=L(*((unsigned long *)(mr->ply_data+mr->ply_bitpos/8))); + ret >>= (mr->ply_bitpos & 7); + ret &= (1 << bits)-1; + mr->ply_bitpos+=bits; + return ret; +} + +static int +garmin_img_coord_get(void *priv_data, struct coord *c, int count) +{ + struct map_rect_priv *mr=priv_data; + struct subdivision *sub=(struct subdivision *)(mr->subdiv+mr->subdiv_pos); + int ret=0; + int debug=0; + if (debug) + printf("garmin_img_coord_get %d\n",count); + if (debug) + dump_subdivision(sub); + while (count--) { + if (mr->rgn_type < 2) { + c->x=triple(&sub->center.lng)+(mr->pnt->lng_delta << shift); + c->y=triple(&sub->center.lat)+(mr->pnt->lat_delta << shift); + } else { + if (! mr->ply_bitpos) { + if (mr->ply->info & 0x80) { + mr->ply_bitcount=mr->ply->u.p2.bitstream_len*8; + mr->ply_lngbits=mr->ply->u.p2.bitstream_info & 0xf; + mr->ply_latbits=mr->ply->u.p2.bitstream_info >> 4; + } else { + mr->ply_bitcount=mr->ply->u.p1.bitstream_len*8; + mr->ply_lngbits=mr->ply->u.p1.bitstream_info & 0xf; + mr->ply_latbits=mr->ply->u.p1.bitstream_info >> 4; + } + if (mr->ply_lngbits <= 9) + mr->ply_lngbits+=2; + if (mr->ply_latbits <= 9) + mr->ply_latbits+=2; + if (! get_bits(mr,1)) { + mr->ply_lngbits+=1; + mr->ply_lngsign=0; + } else + if (get_bits(mr, 1)) + mr->ply_lngsign=-1; + else + mr->ply_lngsign=1; + if (! get_bits(mr,1)) { + mr->ply_latbits+=1; + mr->ply_latsign=0; + } else + if (get_bits(mr, 1)) + mr->ply_latsign=-1; + else + mr->ply_latsign=1; + mr->ply_lnglimit=1 << (mr->ply_lngbits-1); + mr->ply_latlimit=1 << (mr->ply_latbits-1); + mr->ply_lng=mr->ply->lng_delta; + mr->ply_lat=mr->ply->lat_delta; + if (debug) + printf("lngbits %d latbits %d bitcount %d\n", mr->ply_lngbits, mr->ply_latbits, mr->ply_bitcount); + c->x=0; + c->y=0; + } else { + if (mr->ply_bitpos + mr->ply_lngbits + mr->ply_latbits > mr->ply_bitcount) { + if (debug) + printf("out of bits %d + %d + %d >= %d\n", mr->ply_bitpos, mr->ply_lngbits, mr->ply_latbits, mr->ply_bitcount); + return ret; + } + c->x=0; + c->y=0; + int x,y; + for (;;) { + x=get_bits(mr,mr->ply_lngbits); + if (debug) + printf("x %d ", x); + if (mr->ply_lngsign || x != mr->ply_lnglimit) + break; + c->x += x-1; + } + if (mr->ply_lngsign) { + c->x=x*mr->ply_lngsign; + } else { + if (x >= mr->ply_lnglimit) + c->x = x - (mr->ply_lnglimit << 1) - c->x; + else + c->x +=x; + } + for (;;) { + y=get_bits(mr,mr->ply_latbits); + if (debug) + printf("y %d ", y); + if (mr->ply_latsign || y != mr->ply_latlimit) + break; + c->y += y-1; + } + if (mr->ply_latsign) { + c->y=y*mr->ply_latsign; + } else { + if (y >= mr->ply_latlimit) + c->y = y - (mr->ply_latlimit << 1) - c->y; + else + c->y +=y; + } + mr->ply_lng += c->x; + mr->ply_lat += c->y; + } + if (debug) + printf(": x %d y %d\n", c->x, c->y); + + c->x=triple(&sub->center.lng)+(mr->ply_lng << shift); + c->y=triple(&sub->center.lat)+(mr->ply_lat << shift); + } +#if 0 + c->x-=0x6f160; + c->y-=0x181f59; + c->x+=0x168ca1; + c->y+=0x68d815; +#endif + c++; + ret++; + if (mr->rgn_type < 2) + return ret; + } + return ret; +} + +static char * +get_label_offset(struct map_rect_priv *mr, int offset) +{ + g_assert(offset < mr->lbl_hdr->label.offset_len.length); + return file_read(&mr->lbl, mr->lbl_hdr->label.offset_len.offset+offset, 128); +} + +static void +garmin_img_attr_rewind(void *priv_data) +{ +} + +static int +garmin_img_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr) +{ + struct map_rect_priv *mr=priv_data; + int debug=0; + + if (debug) + printf("garmin_img_attr_get\n"); + if (attr_type == attr_label) { + if (debug) + printf("garmin_img_attr_get label\n"); + attr->type=attr_type; + if (mr->rgn_type < 2) { + if (mr->label) + file_free(mr->label); + mr->label=get_label_offset(mr, triple_u(&mr->pnt->lbl_offset) & 0x3fffff); + attr->u.str=mr->label; + } else { + attr->u.str=""; + } + return 1; + } + return 0; +} + +static struct item_methods methods_garmin_img = { + garmin_img_coord_rewind, + garmin_img_coord_get, + garmin_img_attr_rewind, + garmin_img_attr_get, +}; + +static int rgn_next_type(struct map_rect_priv *mr) +{ + while (mr->rgn_type < 3) { + mr->rgn_type++; + if (mr->rgn_items[mr->rgn_type].offset && mr->rgn_items[mr->rgn_type].length != 0) { + mr->rgn_offset=mr->rgn_items[mr->rgn_type].offset; + mr->rgn_end=mr->rgn_offset+mr->rgn_items[mr->rgn_type].length; + return 0; + } + } + return 1; +} + +static int +sub_next(struct map_rect_priv *mr, int next) +{ + int i,offset,first=-1,last=-1,count=-1; + int end; + unsigned short *offsets; + int debug=0; + + if (mr->subdiv_level_count <= 0) + return 1; + if (debug) + printf("%d left\n", mr->subdiv_level_count); + mr->subdiv_level_count--; + +#if 0 + if (next && mr->subdiv[mr->subdiv_current].width & 0x8000) + return 1; +#endif + if (debug) + dump_hex_r(mr->subdiv+mr->subdiv_pos, 64, 14); + mr->subdiv_pos+=next; + if (debug) + printf("subdiv_pos 0x%x\n", mr->subdiv_pos); + if (mr->subdiv_pos > mr->tre_hdr->subdivision.length) + return 1; + struct subdivision *sub=(struct subdivision *)(mr->subdiv+mr->subdiv_pos); + offset=triple_u(&sub->rgn_offset)+mr->rgn_hdr->offset_len.offset; + if (debug) { + printf("offset=0x%x\n", offset); + dump_subdivision(sub); + } + offsets=file_read(&mr->rgn, offset, 3*sizeof(unsigned short)); + + if (! next) + next=subdiv_next; + if (mr->subdiv_pos+next < mr->tre_hdr->subdivision.length) + end=triple_u(&((struct subdivision *)(mr->subdiv+mr->subdiv_pos+next))->rgn_offset)+mr->rgn_hdr->offset_len.offset; + else + end=mr->rgn_hdr->offset_len.offset+mr->rgn_hdr->offset_len.length; + if (debug) { + dump_subdivision(sub); + dump_hex(offsets, 6); + } + for (i=0 ; i < 4 ; i++) { + if (debug) + printf("i=%d ", i); + if (sub->types & (0x10 << i)) { + if (debug) + printf("+ "); + if (first == -1) { + first=i; + mr->rgn_items[i].offset=offset; + if (debug) + printf("\n"); + } else { + mr->rgn_items[i].offset=offset+offsets[count]; + if (debug) + printf("0x%x\n", offsets[count]); + mr->rgn_items[last].length=mr->rgn_items[i].offset-mr->rgn_items[last].offset; + } + last=i; + count++; + } else { + if (debug) + printf("-\n"); + mr->rgn_items[i].offset=0; + mr->rgn_items[i].length=0; + } + + } + if (first != -1) { + mr->rgn_items[first].offset+=count*2; + mr->rgn_items[first].length-=count*2; + mr->rgn_items[last].length=end-mr->rgn_items[last].offset; + } + if (debug) { + for (i=0 ; i < 4 ; i++) { + printf("%d 0x%x 0x%x\n", i, mr->rgn_items[i].offset, mr->rgn_items[i].length); + } + } + mr->rgn_type=-1; + rgn_next_type(mr); + if (debug) + printf("*** offset 0x%x\n", mr->rgn_offset); + file_free(offsets); + return 0; +} + +int item_count; + +static struct map_rect_priv * +map_rect_new_garmin_img(struct map_priv *map, struct coord_rect *r, struct layer *layers, int limit) +{ + struct map_rect_priv *mr; + struct img_header img; + + if (debug) + printf("map_rect_new_garmin_img\n"); + mr=g_new0(struct map_rect_priv, 1); + mr->m=map; + if (r) + mr->r=*r; + mr->limit=limit; + mr->item.id_hi=0; + mr->item.id_lo=0; + mr->item.meth=&methods_garmin_img; + mr->item.priv_data=mr; + mr->f=fopen(map->filename, "r"); + + fread(&img, sizeof(img), 1, mr->f); +#if 0 + dump_img(&img); + for (i = 0 ; i < (img.file_offset-sizeof(img))/sizeof(fat_blk) ; i++) { + fread(&fat_blk, sizeof(fat_blk), 1, mr->f); + if (!fat_blk.flag) + break; + dump_fat_block(&fat_blk); + } +#endif + mr->rgn.offset=0xa*2048; + mr->rgn.f=mr->f; + mr->rgn_hdr=file_read(&mr->rgn, 0, sizeof(*mr->rgn_hdr)); + + mr->tre.offset=0x62b*2048; + mr->tre.f=mr->f; + mr->tre_hdr=file_read(&mr->tre, 0, sizeof(*mr->tre_hdr)); + + mr->lbl.offset=0x64a*2048; + mr->lbl.f=mr->f; + mr->lbl_hdr=file_read(&mr->lbl, 0, sizeof(*mr->lbl_hdr)); + + mr->subdiv=file_read(&mr->tre, mr->tre_hdr->subdivision.offset, mr->tre_hdr->subdivision.length); +#if 0 + dump_hex_r(mr->subdiv, mr->tre_hdr->subdivision.length, 16); +#endif + dump_tree_header(mr->tre_hdr); + + dump_levels(mr); + + + printf("limit=%d\n", limit); + if (limit < 3) { + mr->subdiv_pos=0; + mr->subdiv_level_count=1; + shift=11; + } else if (limit < 6) { + mr->subdiv_pos=1*sizeof(struct subdivision); + mr->subdiv_level_count=5; + shift=9; + } else if (limit < 8) { + mr->subdiv_pos=6*sizeof(struct subdivision); + mr->subdiv_level_count=9; + shift=7; + } else if (limit < 10) { + mr->subdiv_pos=15*sizeof(struct subdivision); + mr->subdiv_level_count=143; + shift=5; + } else { + mr->subdiv_pos=158*sizeof(struct subdivision); + mr->subdiv_level_count=4190; + shift=2; + subdiv_next=14; + } + +#if 0 + mr->rgn_offset=triple_u(&mr->subdiv[mr->subdiv_current].rgn_offset)+mr->rgn_hdr->offset_len.offset+4; + mr->rgn_type=1; + mr->rgn_end=mr->rgn_offset+20*8; +#endif + mr->count=0; + item_count=0; + +#if 0 + printf("*** offset 0x%x\n", 0x656c-mr->rgn.offset); + printf("*** offset 0x%x\n", mr->rgn_offset); +#endif +#if 1 + sub_next(mr, 0); +#endif +#if 0 + { + struct rgn_point *pnt; + int i; + int offset=0x65cc; + for (i = 0 ; i < 26 ; i++) { + pnt=file_read(&mr->rgn, 0x656c+8*i-mr->rgn.offset, sizeof(*pnt)); + // dump_hex(pnt, sizeof(*pnt)); + dump_point(pnt); + dump_label_offset(mr, triple_u(&pnt->lbl_offset)); + } + } + exit(0); +#endif +#if 0 + dump_tree(&mr->tre,&mr->rgn,mr); +#endif + +#if 0 + f.offset=0x64a*2048; + f.f=mr->f; + dump_labels(&f); +#endif +#if 0 + fseek(mr->f, img.file_offset, SEEK_SET); + fread(&fil, sizeof(fil), 1, mr->f); + dump_file(&fil); + fread(&rgn, sizeof(rgn), 1, mr->f); + dump_region(&rgn); + fseek(mr->f, rgn.data_length, SEEK_CUR); + fread(&fil, sizeof(fil), 1, mr->f); + dump_file(&fil); +#endif + return mr; +} + + +static void +map_rect_destroy_garmin_img(struct map_rect_priv *mr) +{ + fclose(mr->f); + g_free(mr); +} + + +static struct item * +map_rect_get_item_garmin_img(struct map_rect_priv *mr) +{ + char *p,type[256]; + int ptype; + int debug=0; + + item_count++; + + if (debug) + printf("map_rect_get_item_garmin_img\n"); + for (;;) { + if (mr->rgn_offset < mr->rgn_end) { + if (debug) + printf("data available\n"); + if (mr->rgn_type >= 2) { + int len; + if (debug) + printf("polyline %d\n", mr->count); + if (mr->ply) + file_free(mr->ply); + mr->ply=file_read(&mr->rgn, mr->rgn_offset, sizeof(*mr->ply)*3); + if(triple_u(&mr->ply->lbl_offset) >= mr->lbl_hdr->label.offset_len.length) { + printf("item_count %d\n", item_count); + dump_poly(mr->ply); + dump_hex(mr->ply, 32); + printf("%d vs %d\n", triple_u(&mr->ply->lbl_offset), mr->lbl_hdr->label.offset_len.length); + } + g_assert(triple_u(&mr->ply->lbl_offset) < mr->lbl_hdr->label.offset_len.length); + if (debug) { + dump_hex(mr->ply, 16); + dump_poly(mr->ply); + } + if (mr->ply_data) + file_free(mr->ply_data); + mr->rgn_offset+=10; + if (mr->ply->info & 0x80) { + mr->rgn_offset++; + len=mr->ply->u.p2.bitstream_len; + } else + len=mr->ply->u.p1.bitstream_len; + + mr->ply_data=file_read(&mr->rgn, mr->rgn_offset, len); + mr->rgn_offset += len; + mr->ply_bitpos=0; + // dump_hex(mr->ply_data, 32); + if (mr->rgn_type == 3) { + switch(mr->ply->info & 0x7f) { + case 0x1: /* large urban area (>200k) */ + mr->item.type=type_town_poly; + break; + case 0xd: /* reservation */ + mr->item.type=type_park_poly; + break; + case 0xe: /* airport runway */ + mr->item.type=type_airport_poly; + break; + case 0x14: /* national park */ + mr->item.type=type_park_poly; + break; + case 0x32: /* sea */ + case 0x3d: /* large lake (77-250km2) */ + case 0x4c: /* intermittend water */ + mr->item.type=type_water_poly; + break; + case 0x4b: /* background */ + continue; + default: + printf("unknown polygon: 0x%x\n", mr->ply->info); + mr->item.type=type_street_3_city; + } + } else { + switch(mr->ply->info & 0x3f) { + case 0x1: /* major highway */ + mr->item.type=type_highway_land; + break; + case 0x2: /* principal highway */ + mr->item.type=type_street_3_land; + break; + case 0x6: /* residental street */ + mr->item.type=type_street_2_land; + break; + case 0x16: /* walkway/trail */ + mr->item.type=type_street_1_land; + break; + case 0x1e: /* international boundary */ + mr->item.type=type_border_country; + break; + case 0x20: /* minor land contour 1/10 */ + mr->item.type=type_height_line_1; + break; + case 0x21: /* major land contour 1/2 */ + mr->item.type=type_height_line_2; + break; + default: + printf("unknown polyline: 0x%x\n", mr->ply->info); + mr->item.type=type_street_3_city; + } + } + return &mr->item; + } + if (mr->pnt) + file_free(mr->pnt); + mr->pnt=file_read(&mr->rgn, mr->rgn_offset, sizeof(*mr->pnt)); + mr->item.type=type_none; + int subtype=mr->pnt->subtype; + if (mr->pnt->lbl_offset.data[2] & 0x80) + mr->rgn_offset+=9; + else { + mr->rgn_offset+=8; + subtype=0; + } + switch(mr->pnt->info) { + case 0x3: /* large city 2-5M */ + mr->item.type=type_town_label_2e6; + break; + case 0xa: /* small city/town 10-20k */ + mr->item.type=type_town_label_1e4; + break; + case 0xd: /* settlement 1-2K */ + mr->item.type=type_town_label_1e3; + break; + case 0x11: /* settlement less 100 */ + mr->item.type=type_town_label_5e1; + break; + case 0x1c: + switch(subtype) { + case 0x01: + mr->item.type=type_poi_wreck; + break; + } + break; + case 0x20: + mr->item.type=type_highway_exit; + break; + case 0x25: + mr->item.type=type_poi_toll_booth; + break; + case 0x2b: + switch(subtype) { + case 0x01: + mr->item.type=type_poi_hotel; + break; + case 0x03: + mr->item.type=type_poi_camp_rv; + break; + } + break; + case 0x2c: + switch(subtype) { + case 0x00: + mr->item.type=type_poi_attraction; + break; + case 0x02: + mr->item.type=type_poi_museum_history; + break; + } + break; + case 0x2e: + mr->item.type=type_poi_shopping; + break; + case 0x2f: + switch(subtype) { + case 0x01: + mr->item.type=type_poi_fuel; + break; + case 0x07: + mr->item.type=type_poi_car_dealer_parts; + break; + case 0x0b: + mr->item.type=type_poi_car_parking; + break; + case 0x15: + mr->item.type=type_poi_public_utilities; + break; + } + break; + case 0x30: + switch(subtype) { + case 0x02: + mr->item.type=type_poi_hospital; + break; + } + break; + case 0x43: + mr->item.type=type_poi_marina; + break; + case 0x46: + mr->item.type=type_poi_bar; + break; + case 0x48: + mr->item.type=type_poi_camping; + break; + case 0x49: + mr->item.type=type_poi_park; + break; + case 0x4a: + mr->item.type=type_poi_picnic; + break; + case 0x59: /* airport */ + mr->item.type=type_poi_airport; + break; + case 0x64: + switch(subtype) { + case 0x1: + mr->item.type=type_poi_bridge; + break; + case 0x2: + mr->item.type=type_poi_building; + break; + case 0x15: + mr->item.type=type_town_ghost; + break; + } + break; + case 0x65: + switch(subtype) { + case 0x0: + mr->item.type=type_poi_water_feature; + break; + case 0xc: + mr->item.type=type_poi_island; + break; + case 0xd: + mr->item.type=type_poi_lake; + break; + } + break; + case 0x66: + switch(subtype) { + case 0x0: + mr->item.type=type_poi_land_feature; + break; + case 0x6: + mr->item.type=type_poi_cape; + break; + case 0x14: + mr->item.type=type_poi_rock; + break; + } + break; + } + if (mr->item.type == type_none) { + printf("unknown point: 0x%x 0x%x\n", mr->pnt->info, mr->pnt->subtype); + dump_point(mr->pnt); + printf("label: %s\n", get_label_offset(mr, triple_u(&mr->pnt->lbl_offset) & 0x3fffff)); + mr->item.type=type_town_label; + } + return &mr->item; + } + if (debug) + printf("out of data for type\n"); + if (rgn_next_type(mr)) { + if (debug) + printf("out of data for region\n"); + if (sub_next(mr, subdiv_next)) { + if (debug) + printf("out of data for subdivision\n"); + return NULL; + } + } + } +} + +static struct item * +map_rect_get_item_byid_garmin_img(struct map_rect_priv *mr, int id_hi, int id_lo) +{ + fseek(mr->f, id_lo, SEEK_SET); + get_line(mr); + mr->item.id_hi=id_hi; + return map_rect_get_item_garmin_img(mr); +} + +static struct map_methods map_methods_garmin_img = { + map_destroy_garmin_img, + map_charset_garmin_img, + map_projection_garmin_img, + map_rect_new_garmin_img, + map_rect_destroy_garmin_img, + map_rect_get_item_garmin_img, + map_rect_get_item_byid_garmin_img, +}; + +static struct map_priv * +map_new_garmin_img(struct map_methods *meth, char *filename) +{ + struct map_priv *m; + *meth=map_methods_garmin_img; + m=g_new(struct map_priv, 1); + m->id=++map_id; + m->filename=g_strdup(filename); + return m; +} + +void +plugin_init(void) +{ + plugin_register_map_type("garmin_img", map_new_garmin_img); +} + diff --git a/src/data/mg/Makefile.am b/src/data/mg/Makefile.am new file mode 100644 index 00000000..65f0157e --- /dev/null +++ b/src/data/mg/Makefile.am @@ -0,0 +1,4 @@ +include $(top_srcdir)/Makefile.inc +AM_CPPFLAGS = @NAVIT_CFLAGS@ -I../.. -DMODULE=\"data_mg\" +plugin_LTLIBRARIES = libdata_mg.la +libdata_mg_la_SOURCES = map.c block.c town.c tree.c poly.c street.c mg.h diff --git a/src/data/mg/block.c b/src/data/mg/block.c new file mode 100644 index 00000000..93c2fb11 --- /dev/null +++ b/src/data/mg/block.c @@ -0,0 +1,261 @@ +#include <stdio.h> +#include <string.h> +#include "debug.h" +#include "mg.h" + + +int block_lin_count,block_idx_count,block_active_count,block_mem,block_active_mem; + +struct block_index_item { + unsigned long blocknum; + unsigned long blocks; +}; + +struct block_index { + unsigned long blocks; + unsigned long size; + unsigned long next; + struct block_index_item list[0]; +}; + +static struct block * +block_get(unsigned char **p) +{ + struct block *ret=(struct block *)(*p); + *p += sizeof(*ret); + return ret; +} + + +static struct block * +block_get_byid(struct file *file, int id, unsigned char **p_ret) +{ + struct block_index *blk_idx; + int blk_num,max; + + + blk_idx=(struct block_index *)(file->begin+0x1000); + max=(blk_idx->size-sizeof(struct block_index))/sizeof(struct block_index_item); + block_mem+=24; + while (id >= max) { + blk_idx=(struct block_index *)(file->begin+blk_idx->next*512); + id-=max; + } + blk_num=blk_idx->list[id].blocknum; + + *p_ret=file->begin+blk_num*512; + return block_get(p_ret); +} + +int +block_get_byindex(struct file *file, int idx, struct block_priv *blk) +{ + dbg(1,"idx=%d\n", idx); + blk->b=block_get_byid(file, idx, &blk->p); + blk->block_start=(unsigned char *)(blk->b); + blk->p_start=blk->p; + blk->end=blk->block_start+blk->b->size; + + return 1; +} + +static void +block_setup_tags(struct map_rect_priv *mr) +{ + int len; + unsigned char *p,*t; + char *str; + + mr->b.binarytree=0; + + p=mr->file->begin+0x0c; + while (*p) { + str=get_string(&p); + len=get_u32_unal(&p); + t=p; + /* printf("String '%s' len %d\n", str, len); */ + if (! strcmp(str,"FirstBatBlock")) { + /* printf("%ld\n", get_u32_unal(&t)); */ + } else if (! strcmp(str,"MaxBlockSize")) { + /* printf("%ld\n", get_u32_unal(&t)); */ + } else if (! strcmp(str,"FREE_BLOCK_LIST")) { + /* printf("%ld\n", get_u32_unal(&t)); */ + } else if (! strcmp(str,"TotalRect")) { + mr->b.b_rect.lu.x=get_u32_unal(&t); + mr->b.b_rect.lu.y=get_u32_unal(&t); + mr->b.b_rect.rl.x=get_u32_unal(&t); + mr->b.b_rect.rl.y=get_u32_unal(&t); + /* printf("0x%x,0x%x-0x%x,0x%x\n", mr->b.b_rect.lu.x, mr->b.b_rect.lu.y, mr->b.b_rect.rl.x, mr->b.b_rect.rl.y); */ + } else if (! strcmp(str,"Version")) { + /* printf("0x%lx\n", get_u32_unal(&t)); */ + } else if (! strcmp(str,"Categories")) { + /* printf("0x%x\n", get_u16(&t)); */ + } else if (! strcmp(str,"binaryTree")) { + mr->b.binarytree=get_u32_unal(&t); + /* printf("%d\n", mr->b.binarytree); */ + } else if (! strcmp(str,"CategorySets")) { + /* printf("0x%x\n", get_u16(&t)); */ + } else if (! strcmp(str,"Kommentar")) { + /* printf("%s\n", get_string(&t)); */ + } + p+=len; + } +} + +#if 0 +static void +block_rect_print(struct coord_rect *r) +{ + printf ("0x%x,0x%x-0x%x,0x%x (0x%x,0x%x)", r->lu.x, r->lu.y, r->rl.x, r->rl.y, r->lu.x/2+r->rl.x/2,r->lu.y/2+r->rl.y/2); +} +#endif + +static void +block_rect_same(struct coord_rect *r1, struct coord_rect *r2) +{ + g_assert(r1->lu.x==r2->lu.x); + g_assert(r1->lu.y==r2->lu.y); + g_assert(r1->rl.x==r2->rl.x); + g_assert(r1->rl.y==r2->rl.y); +} + +int +block_init(struct map_rect_priv *mr) +{ + mr->b.block_num=-1; + mr->b.bt.b=NULL; + mr->b.bt.next=0; + block_setup_tags(mr); + if (mr->b.binarytree) { + mr->b.bt.next=mr->b.binarytree; + mr->b.bt.p=NULL; + mr->b.bt.block_count=0; + } + if (mr->cur_sel && !coord_rect_overlap(&mr->cur_sel->rect, &mr->b.b_rect)) + return 0; + return block_next(mr); +} + + +int +block_next_lin(struct map_rect_priv *mr) +{ + for (;;) { + block_lin_count++; + block_mem+=sizeof(struct block *); + mr->b.block_num++; + if (! mr->b.block_num) + mr->b.p=mr->file->begin+0x2000; + else + mr->b.p=mr->b.block_start+mr->b.b->blocks*512; + if (mr->b.p >= mr->file->end) + return 0; + mr->b.block_start=mr->b.p; + mr->b.b=block_get(&mr->b.p); + mr->b.p_start=mr->b.p; + mr->b.end=mr->b.block_start+mr->b.b->size; + if (mr->b.b->count == -1) + return 0; + if (!mr->cur_sel || coord_rect_overlap(&mr->cur_sel->rect, &mr->b.b->r)) { + block_active_count++; + block_active_mem+=mr->b.b->blocks*512-sizeof(struct block *); + return 1; + } + } +} + +int +block_next(struct map_rect_priv *mr) +{ + int blk_num,coord,r_h,r_w; + struct block_bt_priv *bt=&mr->b.bt; + + if (!mr->b.binarytree || ! mr->cur_sel) + return block_next_lin(mr); + for (;;) { + if (! bt->p) { + dbg(1,"block 0x%x\n", bt->next); + if (bt->next == -1) + return 0; + bt->b=block_get_byid(mr->file, bt->next, &bt->p); + bt->end=(unsigned char *)mr->b.bt.b+mr->b.bt.b->size; + bt->next=bt->b->next; + bt->order=0; + dbg(1,"size 0x%x next 0x%x\n", bt->b->size, bt->b->next); + if (! mr->b.bt.block_count) { +#if 0 + if (debug) { + printf("idx rect "); + block_rect_print(&mr->b.bt.b->r); + } +#endif + bt->r=bt->b->r; + bt->r_curr=bt->r; + coord=get_u32(&mr->b.bt.p); + } else { + bt->p=(unsigned char *)bt->b+0xc; + } + bt->block_count++; + } + while (mr->b.bt.p < mr->b.bt.end) { + block_idx_count++; + blk_num=get_u32(&mr->b.bt.p); + coord=get_u32(&mr->b.bt.p); + block_mem+=8; + dbg(1,"%p vs %p coord 0x%x ", mr->b.bt.end, mr->b.bt.p, coord); + dbg(1,"block 0x%x", blk_num); + + r_w=bt->r_curr.rl.x-bt->r_curr.lu.x; + r_h=bt->r_curr.lu.y-bt->r_curr.rl.y; +#if 0 + if (debug) { + printf(" rect1 "); + block_rect_print(&bt->r_curr); + printf(" %dx%d", r_w, r_h); + } +#endif + mr->b.b=NULL; + if (blk_num != -1) { + block_mem+=8; + if (coord_rect_overlap(&mr->cur_sel->rect, &bt->r_curr)) { + mr->b.b=block_get_byid(mr->file, blk_num, &mr->b.p); + mr->b.block_num=blk_num; + g_assert(mr->b.b != NULL); + mr->b.block_start=(unsigned char *)(mr->b.b); + mr->b.p_start=mr->b.p; + mr->b.end=mr->b.block_start+mr->b.b->size; + block_rect_same(&mr->b.b->r, &bt->r_curr); + } + } + if (coord != -1) { + bt->stack[bt->stackp]=bt->r_curr; + if (r_w > r_h) { + bt->r_curr.rl.x=coord; + bt->stack[bt->stackp].lu.x=coord+1; + } else { + bt->r_curr.lu.y=coord; + bt->stack[bt->stackp].rl.y=coord+1; + } + bt->stackp++; + g_assert(bt->stackp < BT_STACK_SIZE); + } else { + if (bt->stackp) { + bt->stackp--; + bt->r_curr=bt->stack[bt->stackp]; + } else { + bt->r_curr=bt->r; + bt->order++; + if (bt->order > 100) + return 0; + } + } + if (mr->b.b) { + block_active_count++; + block_active_mem+=mr->b.b->blocks*512; + return 1; + } + } + bt->p=NULL; + } + return 0; +} diff --git a/src/data/mg/map.c b/src/data/mg/map.c new file mode 100644 index 00000000..20feb8f1 --- /dev/null +++ b/src/data/mg/map.c @@ -0,0 +1,296 @@ +#include <stdio.h> +#include <string.h> +#include "debug.h" +#include "plugin.h" +#include "maptype.h" +#include "projection.h" +#include "mg.h" + + +struct map_priv * map_new_mg(struct map_methods *meth, char *dirname, char **charset, enum projection *pro); + +static int map_id; + +static char *file[]={ + [file_border_ply]="border.ply", + [file_bridge_ply]="bridge.ply", + [file_build_ply]="build.ply", + [file_golf_ply]="golf.ply", + [file_height_ply]="height.ply", + [file_natpark_ply]="natpark.ply", + [file_nature_ply]="nature.ply", + [file_other_ply]="other.ply", + [file_rail_ply]="rail.ply", + [file_sea_ply]="sea.ply", + [file_street_bti]="street.bti", + [file_street_str]="street.str", + [file_strname_stn]="strname.stn", + [file_town_twn]="town.twn", + [file_tunnel_ply]="tunnel.ply", + [file_water_ply]="water.ply", + [file_woodland_ply]="woodland.ply", +}; + + +static int +file_next(struct map_rect_priv *mr) +{ + int debug=0; + enum layer_type layer; + + for (;;) { + mr->current_file++; + if (mr->current_file >= file_end) + return 0; + mr->file=mr->m->file[mr->current_file]; + if (! mr->file) + continue; + switch (mr->current_file) { + case file_strname_stn: + continue; + case file_town_twn: + layer=layer_town; + break; + case file_street_str: + layer=layer_street; + break; + default: + layer=layer_poly; + } + if (mr->cur_sel && !mr->cur_sel->order[layer]) + continue; + if (debug) + printf("current file: '%s'\n", file[mr->current_file]); + mr->cur_sel=mr->xsel; + if (block_init(mr)) + return 1; + } +} + +static void +map_destroy_mg(struct map_priv *m) +{ + int i; + + printf("mg_map_destroy\n"); + for (i = 0 ; i < file_end ; i++) { + if (m->file[i]) + file_destroy(m->file[i]); + } +} + +extern int block_lin_count,block_idx_count,block_active_count,block_mem,block_active_mem; + +static struct map_rect_priv * +map_rect_new_mg(struct map_priv *map, struct map_selection *sel) +{ + struct map_rect_priv *mr; + int i; + + block_lin_count=0; + block_idx_count=0; + block_active_count=0; + block_mem=0; + block_active_mem=0; + mr=g_new0(struct map_rect_priv, 1); + mr->m=map; + mr->xsel=sel; + mr->current_file=-1; + if (sel && sel->next) + for (i=0 ; i < file_end ; i++) + mr->block_hash[i]=g_hash_table_new(g_int_hash,g_int_equal); + + file_next(mr); + return mr; +} + + +static struct item * +map_rect_get_item_mg(struct map_rect_priv *mr) +{ + for (;;) { + switch (mr->current_file) { + case file_town_twn: + if (town_get(mr, &mr->town, &mr->item)) + return &mr->item; + break; + case file_border_ply: + /* case file_bridge_ply: */ + case file_build_ply: + case file_golf_ply: + /* case file_height_ply: */ + case file_natpark_ply: + case file_nature_ply: + case file_other_ply: + case file_rail_ply: + case file_sea_ply: + /* case file_tunnel_ply: */ + case file_water_ply: + case file_woodland_ply: + if (poly_get(mr, &mr->poly, &mr->item)) + return &mr->item; + break; + case file_street_str: + if (street_get(mr, &mr->street, &mr->item)) + return &mr->item; + break; + case file_end: + return NULL; + default: + break; + } + if (block_next(mr)) + continue; + if (mr->cur_sel->next) { + mr->cur_sel=mr->cur_sel->next; + if (block_init(mr)) + continue; + } + if (file_next(mr)) + continue; + dbg(1,"lin_count %d idx_count %d active_count %d %d kB (%d kB)\n", block_lin_count, block_idx_count, block_active_count, (block_mem+block_active_mem)/1024, block_active_mem/1024); + return NULL; + } +} + +static struct item * +map_rect_get_item_byid_mg(struct map_rect_priv *mr, int id_hi, int id_lo) +{ + mr->current_file = id_hi >> 16; + switch (mr->current_file) { + case file_town_twn: + if (town_get_byid(mr, &mr->town, id_hi, id_lo, &mr->item)) + return &mr->item; + break; + case file_street_str: + if (street_get_byid(mr, &mr->street, id_hi, id_lo, &mr->item)) + return &mr->item; + break; + default: + if (poly_get_byid(mr, &mr->poly, id_hi, id_lo, &mr->item)) + return &mr->item; + break; + } + return NULL; +} + + +static void +map_rect_destroy_mg(struct map_rect_priv *mr) +{ + int i; + for (i=0 ; i < file_end ; i++) + if (mr->block_hash[i]) + g_hash_table_destroy(mr->block_hash[i]); + g_free(mr); +} + +static struct map_search_priv * +map_search_new_mg(struct map_priv *map, struct item *item, struct attr *search, int partial) +{ + struct map_rect_priv *mr=g_new0(struct map_rect_priv, 1); + dbg(1,"id_lo=0x%x\n", item->id_lo); + dbg(1,"search=%s\n", search->u.str); + mr->m=map; + mr->search_type=search->type; + switch (search->type) { + case attr_town_name: + if (item->type != type_country_label) + return NULL; + tree_search_init(map->dirname, "town.b2", &mr->ts, 0x1000); + break; + case attr_street_name: + if (item->type != type_town_streets) + return NULL; + dbg(1,"street_assoc=0x%x\n", item->id_lo); + tree_search_init(map->dirname, "strname.b1", &mr->ts, 0); + break; + default: + dbg(0,"unknown search\n"); + g_free(mr); + return NULL; + } + mr->search_item=*item; + mr->search_country=item->id_lo; + mr->search_str=search->u.str; + mr->search_partial=partial; + mr->current_file=file_town_twn-1; + file_next(mr); + return (struct map_search_priv *)mr; +} + +static void +map_search_destroy_mg(struct map_search_priv *ms) +{ + struct map_rect_priv *mr=(struct map_rect_priv *)ms; + + if (! mr) + return; + tree_search_free(&mr->ts); + g_free(mr); +} + +static struct item * +map_search_get_item_mg(struct map_search_priv *ms) +{ + struct map_rect_priv *mr=(struct map_rect_priv *)ms; + + if (! mr) + return NULL; + switch (mr->search_type) { + case attr_town_name: + return town_search_get_item(mr); + case attr_street_name: + return street_search_get_item(mr); + default: + return NULL; + } +} + +static struct map_methods map_methods_mg = { + map_destroy_mg, + map_rect_new_mg, + map_rect_destroy_mg, + map_rect_get_item_mg, + map_rect_get_item_byid_mg, + map_search_new_mg, + map_search_destroy_mg, + map_search_get_item_mg, +}; + +struct map_priv * +map_new_mg(struct map_methods *meth, char *dirname, char **charset, enum projection *pro) +{ + struct map_priv *m; + int i,maybe_missing,len=strlen(dirname); + char filename[len+16]; + + *meth=map_methods_mg; + *charset="iso8859-1"; + *pro=projection_mg; + + m=g_new(struct map_priv, 1); + m->id=++map_id; + m->dirname=g_strdup(dirname); + strcpy(filename, dirname); + filename[len]='/'; + for (i = 0 ; i < file_end ; i++) { + if (file[i]) { + strcpy(filename+len+1, file[i]); + m->file[i]=file_create_caseinsensitive(filename); + if (! m->file[i]) { + maybe_missing=(i == file_border_ply || i == file_height_ply || i == file_sea_ply); + if (! maybe_missing) + g_warning("Failed to load %s", filename); + } + } + } + + return m; +} + +void +plugin_init(void) +{ + plugin_register_map_type("mg", map_new_mg); +} diff --git a/src/data/mg/mg.h b/src/data/mg/mg.h new file mode 100644 index 00000000..696fd55c --- /dev/null +++ b/src/data/mg/mg.h @@ -0,0 +1,286 @@ +#include <glib.h> +#include "attr.h" +#include "coord.h" +#include "data.h" +#include "item.h" +#include "map.h" +#include "file.h" + +struct block_data { + struct file *file; +}; + +struct block { + int blocks; + int size; + int next; + struct coord_rect r; + int count; +}; + +struct item_priv { + int cidx; + int aidx; + unsigned char *cstart,*cp,*cend; + unsigned char *astart,*ap,*aend; + enum attr_type attr_last; + enum attr_type attr_next; + struct item item; +}; + +struct town_priv { + unsigned int id; /*!< Identifier */ + struct coord c; /*!< Coordinates */ + char *name; /*!< Name */ + char *district; /*!< District */ + char *postal_code1; /*!< Postal code */ + unsigned char order; /*!< Order (Importance) */ + unsigned char type; /*!< Type */ + unsigned short country; /*!< Country */ + unsigned int unknown2; /*!< Unknown */ + unsigned char size; /*!< Size of town */ + unsigned int street_assoc; /*!< Association to streets */ + unsigned char unknown3; /*!< Unknown */ + char *postal_code2; /*!< 2nd postal code */ + unsigned int unknown4; /*!< Unknown */ + + int cidx; + int aidx; + enum attr_type attr_next; + char debug[256]; + struct item town_attr_item; +}; + +struct poly_priv { + int poly_num; + unsigned char *poly_next; + int subpoly_num; + int subpoly_num_all; + unsigned char *subpoly_next; + unsigned char *subpoly_start; + unsigned char *p; + struct coord c[2]; + char *name; + unsigned char order; + unsigned char type; + unsigned int polys; + unsigned int *count; + unsigned int count_sum; + + int aidx; + enum attr_type attr_next; +}; + +struct street_header { + unsigned char order; + int count; +} __attribute__((packed)); + +struct street_type { + unsigned char order; + unsigned short country; +} __attribute__((packed)); + +struct street_header_type { + struct street_header *header; + int type_count; + struct street_type *type; +}; + +struct street_str { + int segid; + unsigned char limit; /* 0x03,0x30=One Way,0x33=No Passing */ + unsigned char unknown2; + unsigned char unknown3; + unsigned char type; + unsigned int nameid; +}; + +struct street_name_segment { + int segid; + int country; +}; + +struct street_name { + int len; + int country; + int townassoc; + char *name1; + char *name2; + int segment_count; + struct street_name_segment *segments; + int aux_len; + unsigned char *aux_data; + int tmp_len; + unsigned char *tmp_data; +}; + +struct street_name_numbers { + int len; + int tag; + int dist; + int country; + struct coord *c; + int first; + int last; + int segment_count; + struct street_name_segment *segments; + int aux_len; + unsigned char *aux_data; + int tmp_len; + unsigned char *tmp_data; +}; + +struct street_name_number { + int len; + int tag; + struct coord *c; + int first; + int last; + struct street_name_segment *segment; +}; + + + +struct street_priv { + struct file *name_file; + struct street_header *header; + int type_count; + struct street_type *type; + struct street_str *str; + struct street_str *str_start; + unsigned char *coord_begin; + unsigned char *p; + unsigned char *p_rewind; + unsigned char *end; + unsigned char *next; + int status; + int status_rewind; + struct coord *ref; + int bytes; + struct street_name name; + enum attr_type attr_next; + char debug[256]; +}; + +enum file_index { + file_border_ply=0, + file_bridge_ply, + file_build_ply, + file_golf_ply, + file_height_ply, + file_natpark_ply, + file_nature_ply, + file_other_ply, + file_rail_ply, + file_sea_ply, + file_street_bti, + file_street_str, + file_strname_stn, + file_town_twn, + file_tunnel_ply, + file_water_ply, + file_woodland_ply, + file_end +}; + +struct map_priv { + int id; + struct file *file[file_end]; + char *dirname; +}; + +#define BT_STACK_SIZE 32 + +struct block_bt_priv { + struct block *b; + struct coord_rect r, r_curr; + int next; + int block_count; + struct coord_rect stack[BT_STACK_SIZE]; + int stackp; + int order; + unsigned char *p; + unsigned char *end; +}; + +struct block_priv { + int block_num; + struct coord_rect b_rect; + unsigned char *block_start; + struct block *b; + unsigned char *p; + unsigned char *end; + unsigned char *p_start; + int binarytree; + struct block_bt_priv bt; +}; + +struct block_offset { + unsigned short offset; + unsigned short block; +}; + + +struct tree_search_node { + struct tree_hdr *hdr; + unsigned char *p; + unsigned char *last; + unsigned char *end; + int low; + int high; + int last_low; + int last_high; + }; + +struct tree_search { + struct file *f; + int last_node; + int curr_node; + struct tree_search_node nodes[5]; +}; + + +struct map_rect_priv { + struct map_selection *xsel; + struct map_selection *cur_sel; + + struct map_priv *m; + enum file_index current_file; + struct file *file; + struct block_priv b; + struct item item; + struct town_priv town; + struct poly_priv poly; + struct street_priv street; + struct tree_search ts; + int search_country; + struct item search_item; + char *search_str; + int search_partial; + int search_linear; + unsigned char *search_p; + int search_blk_count; + enum attr_type search_type; + struct block_offset *search_blk_off; + int search_block; + GHashTable *block_hash[file_end]; + struct item_priv item3; +}; + +int block_init(struct map_rect_priv *mr); +int block_next(struct map_rect_priv *mr); +int block_get_byindex(struct file *file, int idx, struct block_priv *blk); + +int tree_search_hv(char *dirname, char *filename, unsigned int search1, unsigned int search2, int *result); +int town_get(struct map_rect_priv *mr, struct town_priv *poly, struct item *item); +int town_get_byid(struct map_rect_priv *mr, struct town_priv *twn, int id_hi, int id_lo, struct item *item); +struct item * town_search_get_item(struct map_rect_priv *mr); +int poly_get(struct map_rect_priv *mr, struct poly_priv *poly, struct item *item); +int poly_get_byid(struct map_rect_priv *mr, struct poly_priv *poly, int id_hi, int id_lo, struct item *item); +int street_get(struct map_rect_priv *mr, struct street_priv *street, struct item *item); +int street_get_byid(struct map_rect_priv *mr, struct street_priv *street, int id_hi, int id_lo, struct item *item); +void tree_search_init(char *dirname, char *filename, struct tree_search *ts, int offset); +void tree_search_free(struct tree_search *ts); +int tree_search_next(struct tree_search *ts, unsigned char **p, int dir); +int tree_search_next_lin(struct tree_search *ts, unsigned char **p); diff --git a/src/data/mg/poly.c b/src/data/mg/poly.c new file mode 100644 index 00000000..b19aeed5 --- /dev/null +++ b/src/data/mg/poly.c @@ -0,0 +1,196 @@ +#include "debug.h" +#include "mg.h" + +static void +poly_coord_rewind(void *priv_data) +{ + struct poly_priv *poly=priv_data; + + poly->p=poly->subpoly_start; + +} + +static int +poly_coord_get(void *priv_data, struct coord *c, int count) +{ + struct poly_priv *poly=priv_data; + int ret=0; + + while (count--) { + if (poly->p >= poly->subpoly_next) + break; + c->x=get_u32_unal(&poly->p); + c->y=get_u32_unal(&poly->p); + c++; + ret++; + } + return ret; +} + +static void +poly_attr_rewind(void *priv_data) +{ + struct poly_priv *poly=priv_data; + + poly->aidx=0; +} + +static int +poly_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr) +{ + struct poly_priv *poly=priv_data; + + attr->type=attr_type; + switch (attr_type) { + case attr_any: + while (poly->attr_next != attr_none) { + if (poly_attr_get(poly, poly->attr_next, attr)) + return 1; + } + return 0; + case attr_label: + attr->u.str=poly->name; + poly->attr_next=attr_none; + if (attr->u.str[0]) + return 1; + return 0; + default: + return 0; + } + return 1; +} + +static struct item_methods poly_meth = { + poly_coord_rewind, + poly_coord_get, + poly_attr_rewind, + poly_attr_get, +}; + +static void +poly_get_data(struct poly_priv *poly, unsigned char **p) +{ + poly->c[0].x=get_u32_unal(p); + poly->c[0].y=get_u32_unal(p); + poly->c[1].x=get_u32_unal(p); + poly->c[1].y=get_u32_unal(p); + *p+=sizeof(struct coord); + poly->name=(char *)(*p); + while (**p) { + (*p)++; + } + (*p)++; + poly->order=*(*p)++; + poly->type=*(*p)++; + poly->polys=get_u32_unal(p); + poly->count=(unsigned int *)(*p); (*p)+=poly->polys*sizeof(unsigned int); + poly->count_sum=get_u32_unal(p); +} + +int +poly_get(struct map_rect_priv *mr, struct poly_priv *poly, struct item *item) +{ + struct coord_rect r; + + for (;;) { + if (mr->b.p >= mr->b.end) + return 0; + if (mr->b.p == mr->b.p_start) { + poly->poly_num=0; + poly->subpoly_num=0; + poly->subpoly_num_all=0; + poly->poly_next=mr->b.p; + item->meth=&poly_meth; + } + if (poly->poly_num >= mr->b.b->count) + return 0; + if (!poly->subpoly_num) { + mr->b.p=poly->poly_next; + item->id_lo=mr->b.p-mr->file->begin; + poly_get_data(poly, &mr->b.p); + poly->poly_next=mr->b.p+poly->count_sum*sizeof(struct coord); + poly->poly_num++; + r.lu=poly->c[0]; + r.rl=poly->c[1]; + if (mr->cur_sel && (poly->order > mr->cur_sel->order[layer_poly]*3 || !coord_rect_overlap(&mr->cur_sel->rect, &r))) { + poly->subpoly_num_all+=poly->polys; + mr->b.p=poly->poly_next; + continue; + } + switch(poly->type) { + case 0x13: + item->type=type_wood; + break; + case 0x14: + item->type=type_town_poly; + break; + case 0x15: + item->type=type_cemetery_poly; + break; + case 0x1e: + item->type=type_industry_poly; + break; + case 0x24: + item->type=type_parking_lot_poly; + break; + case 0x28: + item->type=type_airport_poly; + break; + case 0x2d: + item->type=type_hospital_poly; + break; + case 0x32: + item->type=type_park_poly; + break; + case 0x34: + item->type=type_sport_poly; + break; + case 0x3c: + item->type=type_water_poly; + break; + case 0xbc: + item->type=type_water_line; + break; + case 0xc6: + item->type=type_border_country; + break; + case 0xc7: + item->type=type_border_state; + break; + case 0xd0: + item->type=type_rail; + break; + default: + dbg(0,"Unknown poly type 0x%x '%s' 0x%x,0x%x\n", poly->type,poly->name,r.lu.x,r.lu.y); + item->type=type_street_unkn; + } + } else + mr->b.p=poly->subpoly_next; + dbg(1,"%d %d %s\n", poly->subpoly_num_all, mr->b.block_num, poly->name); + item->id_lo=poly->subpoly_num_all | (mr->b.block_num << 16); + item->id_hi=(mr->current_file << 16); + dbg(1,"0x%x 0x%x\n", item->id_lo, item->id_hi); + poly->subpoly_next=mr->b.p+L(poly->count[poly->subpoly_num])*sizeof(struct coord); + poly->subpoly_num++; + poly->subpoly_num_all++; + if (poly->subpoly_num >= poly->polys) + poly->subpoly_num=0; + poly->subpoly_start=poly->p=mr->b.p; + item->priv_data=poly; + poly->attr_next=attr_label; + return 1; + } +} + +int +poly_get_byid(struct map_rect_priv *mr, struct poly_priv *poly, int id_hi, int id_lo, struct item *item) +{ + int count=id_lo & 0xffff; + int ret=0; + block_get_byindex(mr->m->file[mr->current_file], id_lo >> 16, &mr->b); + while (count-- >= 0) { + ret=poly_get(mr, poly, item); + } + return ret; +} + diff --git a/src/data/mg/street.c b/src/data/mg/street.c new file mode 100644 index 00000000..550e5006 --- /dev/null +++ b/src/data/mg/street.c @@ -0,0 +1,702 @@ +#include <stdio.h> +#include "debug.h" +#include "mg.h" + +int coord_debug; + +static void +street_name_get(struct street_name *name, unsigned char **p) +{ + unsigned char *start=*p; + name->len=get_u16_unal(p); + name->country=get_u16_unal(p); + name->townassoc=get_u32_unal(p); + name->name1=get_string(p); + name->name2=get_string(p); + name->segment_count=get_u32_unal(p); + name->segments=(struct street_name_segment *)(*p); + (*p)+=(sizeof (struct street_name_segment))*name->segment_count; + name->aux_len=name->len-(*p-start); + name->aux_data=*p; + name->tmp_len=name->aux_len; + name->tmp_data=name->aux_data; + *p=start+name->len; +} + +static void +street_name_numbers_get(struct street_name_numbers *name_numbers, unsigned char **p) +{ + unsigned char *start=*p; + name_numbers->len=get_u16(p); + name_numbers->tag=get_u8(p); + name_numbers->dist=get_u32(p); + name_numbers->country=get_u32(p); + name_numbers->c=coord_get(p); + name_numbers->first=get_u24(p); + name_numbers->last=get_u24(p); + name_numbers->segment_count=get_u32(p); + name_numbers->segments=(struct street_name_segment *)(*p); + (*p)+=sizeof(struct street_name_segment)*name_numbers->segment_count; + name_numbers->aux_len=name_numbers->len-(*p-start); + name_numbers->aux_data=*p; + name_numbers->tmp_len=name_numbers->aux_len; + name_numbers->tmp_data=name_numbers->aux_data; + *p=start+name_numbers->len; +} + +static void +street_name_number_get(struct street_name_number *name_number, unsigned char **p) +{ + unsigned char *start=*p; + name_number->len=get_u16(p); + name_number->tag=get_u8(p); + name_number->c=coord_get(p); + name_number->first=get_u24(p); + name_number->last=get_u24(p); + name_number->segment=(struct street_name_segment *)p; + *p=start+name_number->len; +} + +static void +street_name_get_by_id(struct street_name *name, struct file *file, unsigned long id) +{ + unsigned char *p; + if (id) { + p=file->begin+id+0x2000; + street_name_get(name, &p); + } +} + +static int street_get_bytes(struct coord_rect *r) +{ + int bytes,dx,dy; + bytes=2; + dx=r->rl.x-r->lu.x; + dy=r->lu.y-r->rl.y; + g_assert(dx > 0); + g_assert(dy > 0); + if (dx > 32767 || dy > 32767) + bytes=3; + if (dx > 8388608 || dy > 8388608) + bytes=4; + + return bytes; +} + +static int street_get_coord(unsigned char **pos, int bytes, struct coord *ref, struct coord *f) +{ + unsigned char *p; + int x,y,flags=0; + + p=*pos; + x=*p++; + x|=(*p++) << 8; + if (bytes == 2) { + if ( x > 0x7fff) { + x=0x10000-x; + flags=1; + } + } + else if (bytes == 3) { + x|=(*p++) << 16; + if ( x > 0x7fffff) { + x=0x1000000-x; + flags=1; + } + } else { + x|=(*p++) << 16; + x|=(*p++) << 24; + if (x < 0) { + x=-x; + flags=1; + } + } + y=*p++; + y|=(*p++) << 8; + if (bytes == 3) { + y|=(*p++) << 16; + } else if (bytes == 4) { + y|=(*p++) << 16; + y|=(*p++) << 24; + } + if (f) { + f->x=ref[0].x+x; + f->y=ref[1].y+y; + } + dbg(1,"0x%x,0x%x + 0x%x,0x%x = 0x%x,0x%x\n", x, y, ref[0].x, ref[1].y, f->x, f->y); + *pos=p; + return flags; +} + +static void +street_coord_get_begin(unsigned char **p) +{ + struct street_str *str; + + str=(struct street_str *)(*p); + while (L(str->segid)) { + str++; + } + (*p)=(unsigned char *)str; + (*p)+=4; +} + + +static void +street_coord_rewind(void *priv_data) +{ + /* struct street_priv *street=priv_data; */ + +} + +static int +street_coord_get_helper(struct street_priv *street, struct coord *c) +{ + unsigned char *n; + if (street->p+street->bytes*2 >= street->end) + return 0; + if (street->status >= 4) + return 0; + n=street->p; + if (street_get_coord(&street->p, street->bytes, street->ref, c)) { + if (street->status) + street->next=n; + street->status+=2; + if (street->status == 5) + return 0; + } + return 1; +} + +static int +street_coord_get(void *priv_data, struct coord *c, int count) +{ + struct street_priv *street=priv_data; + int ret=0,i,scount; + + if (! street->p && count) { + street->p=street->coord_begin; + scount=street->str-street->str_start; + for (i = 0 ; i < scount ; i++) { + street->status=L(street->str[i+1].segid) >= 0 ? 0:1; + while (street_coord_get_helper(street, c)); + street->p=street->next; + } + street->status_rewind=street->status=L(street->str[1].segid) >= 0 ? 0:1; + } + while (count > 0) { + if (street_coord_get_helper(street, c)) { + c++; + ret++; + count--; + } else + return ret; + } + return ret; +} + +static void +street_attr_rewind(void *priv_data) +{ + /* struct street_priv *street=priv_data; */ + +} + +static int +street_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr) +{ + struct street_priv *street=priv_data; + int nameid; + + dbg(1,"segid 0x%x\n", street->str->segid); + attr->type=attr_type; + switch (attr_type) { + case attr_any: + while (street->attr_next != attr_none) { + if (street_attr_get(street, street->attr_next, attr)) + return 1; + } + return 0; + case attr_label: + nameid=L(street->str->nameid); + if (! nameid) + return 0; + if (! street->name.len) + street_name_get_by_id(&street->name,street->name_file,nameid); + street->attr_next=attr_street_name; + attr->u.str=street->name.name2; + if (attr->u.str && attr->u.str[0]) + return 1; + attr->u.str=street->name.name1; + if (attr->u.str && attr->u.str[0]) + return 1; + return 0; + case attr_street_name: + nameid=L(street->str->nameid); + if (! nameid) + return 0; + if (! street->name.len) + street_name_get_by_id(&street->name,street->name_file,nameid); + attr->u.str=street->name.name2; + street->attr_next=attr_street_name_systematic; + return ((attr->u.str && attr->u.str[0]) ? 1:0); + case attr_street_name_systematic: + nameid=L(street->str->nameid); + if (! nameid) + return 0; + if (! street->name.len) + street_name_get_by_id(&street->name,street->name_file,nameid); + attr->u.str=street->name.name1; + street->attr_next=attr_limit; + return ((attr->u.str && attr->u.str[0]) ? 1:0); + case attr_limit: + if (street->str->type & 0x40) { + attr->u.num=(street->str->limit & 0x30) ? 2:0; + attr->u.num|=(street->str->limit & 0x03) ? 1:0; + } else { + attr->u.num=(street->str->limit & 0x30) ? 1:0; + attr->u.num|=(street->str->limit & 0x03) ? 2:0; + } + street->attr_next=attr_debug; + return 1; + case attr_debug: + street->attr_next=attr_none; + { + struct street_str *str=street->str; + sprintf(street->debug,"order:0x%x\nsegid:0x%x\nlimit:0x%x\nunknown2:0x%x\nunknown3:0x%x\ntype:0x%x\nnameid:0x%x\ntownassoc:0x%x",street->header->order,str->segid,str->limit,str->unknown2,str->unknown3,str->type,str->nameid, street->name.len ? street->name.townassoc : 0); + attr->u.str=street->debug; + } + return 1; + default: + return 0; + } + return 1; +} + +static struct item_methods street_meth = { + street_coord_rewind, + street_coord_get, + street_attr_rewind, + street_attr_get, +}; + +static void +street_get_data(struct street_priv *street, unsigned char **p) +{ + street->header=(struct street_header *)(*p); + (*p)+=sizeof(struct street_header); + street->type_count=street->header->count; + street->type=(struct street_type *)(*p); + (*p)+=street->type_count*sizeof(struct street_type); +} + + + /*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 */ +static unsigned char limit[]={0,0,1,1,1,2,2,4,6,6,12,13,14,20,20,20,20,20,20}; + +int +street_get(struct map_rect_priv *mr, struct street_priv *street, struct item *item) +{ + if (mr->b.p == mr->b.p_start) { + street_get_data(street, &mr->b.p); + street->name_file=mr->m->file[file_strname_stn]; + if (mr->cur_sel && street->header->order > limit[mr->cur_sel->order[layer_street]]) + return 0; + street->end=mr->b.end; + street->ref=&mr->b.b->r.lu; + street->bytes=street_get_bytes(&mr->b.b->r); + street->str_start=street->str=(struct street_str *)mr->b.p; + street->coord_begin=mr->b.p; + street_coord_get_begin(&street->coord_begin); + street->p=street->coord_begin; + street->type--; + item->meth=&street_meth; + item->priv_data=street; + } else { + street->str++; + street->p=street->next; + } + if (! L(street->str->segid)) + return 0; + if (L(street->str->segid) < 0) + street->type++; +#if 0 + g_assert(street->p != NULL); +#endif + street->next=NULL; + street->status_rewind=street->status=L(street->str[1].segid) >= 0 ? 0:1; +#if 0 + if (street->type->country != 0x31) { + printf("country=0x%x\n", street->type->country); + } +#endif + item->id_hi=street->type->country | (mr->current_file << 16); + item->id_lo=L(street->str->segid) > 0 ? L(street->str->segid) : -L(street->str->segid); + switch(street->str->type & 0x1f) { + case 0xf: /* very small street */ + if (street->str->limit == 0x33) + item->type=type_street_nopass; + else + item->type=type_street_0; + break; + case 0xd: + item->type=type_ferry; + break; + case 0xc: /* small street */ + item->type=type_street_1_city; + break; + case 0xb: + item->type=type_street_2_city; + break; + case 0xa: + if ((street->str->limit == 0x03 || street->str->limit == 0x30) && street->header->order < 4) + item->type=type_street_4_city; + else + item->type=type_street_3_city; + break; + case 0x9: + if (street->header->order < 5) + item->type=type_street_4_city; + else if (street->header->order < 7) + item->type=type_street_2_city; + else + item->type=type_street_1_city; + break; + case 0x8: + item->type=type_street_2_land; + break; + case 0x7: + if ((street->str->limit == 0x03 || street->str->limit == 0x30) && street->header->order < 4) + item->type=type_street_4_city; + else + item->type=type_street_3_land; + break; + case 0x6: + item->type=type_ramp; + break; + case 0x5: + item->type=type_street_4_land; + break; + case 0x4: + item->type=type_street_4_land; + break; + case 0x3: + item->type=type_street_n_lanes; + break; + case 0x2: + item->type=type_highway_city; + break; + case 0x1: + item->type=type_highway_land; + break; + default: + item->type=type_street_unkn; + dbg(0,"unknown type 0x%x\n",street->str->type); + } +#if 0 + coord_debug=(street->str->unknown2 != 0x40 || street->str->unknown3 != 0x40); + if (coord_debug) { + item->type=type_street_unkn; + printf("%d %02x %02x %02x %02x\n", street->str->segid, street->str->type, street->str->limit, street->str->unknown2, street->str->unknown3); + } +#endif + street->p_rewind=street->p; + street->name.len=0; + street->attr_next=attr_label; + return 1; +} + +int +street_get_byid(struct map_rect_priv *mr, struct street_priv *street, int id_hi, int id_lo, struct item *item) +{ + int country=id_hi & 0xffff; + int res; + dbg(1,"enter(%p,%p,0x%x,0x%x,%p)\n", mr, street, id_hi, id_lo, item); + if (! country) + return 0; + tree_search_hv(mr->m->dirname, "street", (id_lo >> 8) | (country << 24), id_lo & 0xff, &res); + dbg(1,"res=0x%x (blk=0x%x)\n", res, res >> 12); + block_get_byindex(mr->m->file[mr->current_file], res >> 12, &mr->b); + street_get_data(street, &mr->b.p); + street->name_file=mr->m->file[file_strname_stn]; + street->end=mr->b.end; + street->ref=&mr->b.b->r.lu; + street->bytes=street_get_bytes(&mr->b.b->r); + street->str_start=street->str=(struct street_str *)mr->b.p; + street->coord_begin=mr->b.p; + street_coord_get_begin(&street->coord_begin); + street->p=street->coord_begin; + street->type--; + item->meth=&street_meth; + item->priv_data=street; + street->str+=(res & 0xfff)-1; + dbg(1,"segid 0x%x\n", street->str[1].segid); + return street_get(mr, street, item); +#if 0 + mr->b.p=mr->b.block_start+(res & 0xffff); + return town_get(mr, twn, item); +#endif + + return 0; +} + + +struct street_name_index { + int block; + unsigned short country; + long town_assoc; + char name[0]; +} __attribute__((packed)); + + +static int +street_search_compare_do(struct map_rect_priv *mr, int country, int town_assoc, char *name) +{ + int d; + + dbg(1,"enter"); + dbg(1,"country 0x%x town_assoc 0x%x name '%s'\n", country, town_assoc, name); + d=(mr->search_item.id_hi & 0xffff)-country; + dbg(1,"country %d\n", d); + if (!d) { + d=mr->search_item.id_lo-town_assoc; + dbg(1,"assoc %d 0x%x-0x%x\n",d, mr->search_item.id_lo, town_assoc); + if (! d) { + if (mr->search_partial) + d=strncasecmp(mr->search_str, name, strlen(mr->search_str)); + else + d=strcasecmp(mr->search_str, name); + dbg(1,"string %d\n", d); + } + } + dbg(1,"d=%d\n", d); + return d; +} + +static int +street_search_compare(unsigned char **p, struct map_rect_priv *mr) +{ + struct street_name_index *i; + + dbg(1,"enter\n"); + i=(struct street_name_index *)(*p); + *p+=sizeof(*i)+strlen(i->name)+1; + mr->search_block=i->block; + + dbg(1,"block 0x%x\n", i->block); + + return street_search_compare_do(mr, i->country, i->town_assoc, i->name); +} + +static void +street_name_numbers_coord_rewind(void *priv_data) +{ + /* struct street_priv *street=priv_data; */ + +} + +static void +street_name_numbers_attr_rewind(void *priv_data) +{ + /* struct street_priv *street=priv_data; */ + +} + +static int +street_name_numbers_coord_get(void *priv_data, struct coord *c, int count) +{ + return 0; +} + +static int +street_name_numbers_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr) +{ + struct map_rect_priv *mr=priv_data; + struct item *item; + + attr->type=attr_type; + switch (attr_type) { + default: + dbg(0,"unknown item\n"); + return 0; + } +} + + + + + +static struct item_methods street_name_numbers_meth = { + street_name_numbers_coord_rewind, + street_name_numbers_coord_get, + street_name_numbers_attr_rewind, + street_name_numbers_attr_get, +}; + + +static void +street_name_coord_rewind(void *priv_data) +{ + /* struct street_priv *street=priv_data; */ + +} + +static void +street_name_attr_rewind(void *priv_data) +{ + /* struct street_priv *street=priv_data; */ + +} + +static int +street_name_coord_get(void *priv_data, struct coord *c, int count) +{ + struct map_rect_priv *mr=priv_data; + struct street_name_numbers snns; + unsigned char *p=mr->street.name.aux_data; + + dbg(0,"aux_data=%p\n", p); + if (count) { + street_name_numbers_get(&snns, &p); + *c=*(snns.c); + return 1; + } + + return 0; +} + +static int +street_name_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr) +{ + struct map_rect_priv *mr=priv_data; + struct item *item; + + attr->type=attr_type; + switch (attr_type) { + case attr_street_name: + attr->u.str=mr->street.name.name2; + return ((attr->u.str && attr->u.str[0]) ? 1:0); + case attr_street_name_systematic: + attr->u.str=mr->street.name.name1; + return ((attr->u.str && attr->u.str[0]) ? 1:0); + case attr_street_name_numbers_item: + item=&mr->item3.item; + attr->u.item=item; + item->type=type_street_name_numbers; + item->id_hi=0; + item->id_lo=1; + item->meth=&street_name_numbers_meth; + item->map=NULL; + item->priv_data=mr; + { + int i; + struct street_name_numbers nns; + unsigned char *p=mr->street.name.aux_data; + unsigned char *end=p+mr->street.name.aux_len; + printf("len=0x%x\n", mr->street.name.aux_len); + for (i = 0 ; i < mr->street.name.aux_len ; i++) { + printf("%02x ",mr->street.name.aux_data[i]); + } + printf("\n"); + { + while (p < end) { + unsigned char *pn,*pn_end;; + struct street_name_number nn; + street_name_numbers_get(&nns, &p); + printf("name_numbers:\n"); + printf(" len 0x%x\n", nns.len); + printf(" tag 0x%x\n", nns.tag); + printf(" dist 0x%x\n", nns.dist); + printf(" country 0x%x\n", nns.country); + printf(" coord 0x%x,0x%x\n", nns.c->x, nns.c->y); + printf(" first %d\n", nns.first); + printf(" last %d\n", nns.last); + printf(" segment count 0x%x\n", nns.segment_count); + printf(" aux_len 0x%x\n", nns.aux_len); + pn=nns.aux_data; + pn_end=nns.aux_data+nns.aux_len; + while (pn < pn_end) { + printf(" number:\n"); + street_name_number_get(&nn, &pn); + printf(" len 0x%x\n", nn.len); + printf(" tag 0x%x\n", nn.tag); + printf(" coord 0x%x,0x%x\n", nn.c->x, nn.c->y); + printf(" first %d\n", nn.first); + printf(" last %d\n", nn.last); + } + } + } + } + return 1; + default: + dbg(0,"unknown item\n"); + return 0; + } +} + + + + + +static struct item_methods street_name_meth = { + street_name_coord_rewind, + street_name_coord_get, + street_name_attr_rewind, + street_name_attr_get, +}; + + +struct item * +street_search_get_item(struct map_rect_priv *mr) +{ + int dir=1,leaf; + unsigned char *last; + + dbg(1,"enter\n"); + if (! mr->search_blk_count) { + dbg(1,"partial 0x%x '%s' ***\n", mr->town.street_assoc, mr->search_str); + if (mr->search_linear) + return NULL; + dbg(1,"tree_search_next\n"); + mr->search_block=-1; + while ((leaf=tree_search_next(&mr->ts, &mr->search_p, dir)) != -1) { + dir=street_search_compare(&mr->search_p, mr); + } + if (mr->search_block == -1) + return NULL; + dbg(1,"mr->search_block=0x%x\n", mr->search_block); + mr->search_blk_count=1; + block_get_byindex(mr->m->file[file_strname_stn], mr->search_block, &mr->b); + mr->b.p=mr->b.block_start+12; + } + dbg(1,"name id 0x%x\n", mr->b.p-mr->m->file[file_strname_stn]->begin); + if (! mr->search_blk_count) + return NULL; + if (mr->b.p >= mr->b.end) { + if (!block_next_lin(mr)) + return NULL; + mr->b.p=mr->b.block_start+12; + } + while (mr->b.p < mr->b.end) { + last=mr->b.p; + street_name_get(&mr->street.name, &mr->b.p); + dir=street_search_compare_do(mr, mr->street.name.country, mr->street.name.townassoc, mr->street.name.name2); + dbg(1,"country 0x%x assoc 0x%x name1 '%s' name2 '%s' dir=%d\n", mr->street.name.country, mr->street.name.townassoc, mr->street.name.name1, mr->street.name.name2, dir); + if (dir < 0) { + mr->search_blk_count=0; + return NULL; + } + if (!dir) { + dbg(0,"result country 0x%x assoc 0x%x name1 '%s' name2 '%s' dir=%d aux_data=%p len=0x%x\n", mr->street.name.country, mr->street.name.townassoc, mr->street.name.name1, mr->street.name.name2, dir, mr->street.name.aux_data, mr->street.name.aux_len); + mr->item.type = type_street_name; + mr->item.id_hi=mr->street.name.country | (mr->current_file << 16) | 0x10000000; + mr->item.id_lo=last-mr->m->file[mr->current_file]->begin; + mr->item.meth=&street_name_meth; + mr->item.map=NULL; + mr->item.priv_data=mr; + return &mr->item; + } + } + return NULL; +} + diff --git a/src/data/mg/town.c b/src/data/mg/town.c new file mode 100644 index 00000000..838bc2cc --- /dev/null +++ b/src/data/mg/town.c @@ -0,0 +1,261 @@ +#include <stdio.h> +#include <string.h> +#include "debug.h" +#include "mg.h" + + + +static void +town_coord_rewind(void *priv_data) +{ + struct town_priv *twn=priv_data; + + twn->cidx=0; +} + +static int +town_coord_get(void *priv_data, struct coord *c, int count) +{ + struct town_priv *twn=priv_data; + + if (twn->cidx || count <= 0) + return 0; + twn->cidx=1; + *c=twn->c; + return 1; +} + +static void +town_attr_rewind(void *priv_data) +{ + struct town_priv *twn=priv_data; + + twn->aidx=0; + twn->attr_next=attr_label; +} + +static int +town_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr) +{ + struct town_priv *twn=priv_data; + + attr->type=attr_type; + switch (attr_type) { + case attr_any: + while (twn->attr_next != attr_none) { + if (town_attr_get(twn, twn->attr_next, attr)) + return 1; + } + return 0; + case attr_label: + attr->u.str=twn->district; + twn->attr_next=attr_town_name; + if (attr->u.str[0]) + return 1; + attr->u.str=twn->name; + return ((attr->u.str && attr->u.str[0]) ? 1:0); + case attr_town_name: + attr->u.str=twn->name; + twn->attr_next=attr_town_postal; + return ((attr->u.str && attr->u.str[0]) ? 1:0); + case attr_town_postal: + attr->u.str=twn->postal_code1; + twn->attr_next=attr_district_name; + return ((attr->u.str && attr->u.str[0]) ? 1:0); + case attr_district_name: + attr->u.str=twn->district; + twn->attr_next=attr_debug; + return ((attr->u.str && attr->u.str[0]) ? 1:0); + case attr_town_streets_item: + twn->town_attr_item.type=type_town_streets; + twn->town_attr_item.id_hi=twn->country | (file_town_twn << 16) | 0x10000000; + twn->town_attr_item.id_lo=twn->street_assoc; + attr->u.item=&twn->town_attr_item; + twn->attr_next=attr_debug; + return 1; + case attr_debug: + sprintf(twn->debug, "order %d\nsize %d\nstreet_assoc 0x%x", twn->order, twn->size, twn->street_assoc); + attr->u.str=twn->debug; + twn->attr_next=attr_none; + return 1; + default: + g_assert(1==0); + return 0; + } + return 1; +} + +static struct item_methods town_meth = { + town_coord_rewind, + town_coord_get, + town_attr_rewind, + town_attr_get, +}; + +static void +town_get_data(struct town_priv *twn, unsigned char **p) +{ + twn->id=get_u32_unal(p); + twn->c.x=get_u32_unal(p); + twn->c.y=get_u32_unal(p); + twn->name=get_string(p); + twn->district=get_string(p); + twn->postal_code1=get_string(p); + twn->order=get_u8(p); /* 1-15 (19) */ + twn->country=get_u16(p); + twn->type=get_u8(p); + twn->unknown2=get_u32_unal(p); + twn->size=get_u8(p); + twn->street_assoc=get_u32_unal(p); + twn->unknown3=get_u8(p); + twn->postal_code2=get_string(p); + twn->unknown4=get_u32_unal(p); +#if 0 + printf("%s\t%s\t%s\t%d\t%d\t%d\n",twn->name,twn->district,twn->postal_code1,twn->order, twn->country, twn->type); +#endif +} + /*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 */ +static unsigned char limit[]={0,1,2,2,4,6,8,10,11,13,14,14,14,20,20,20,20,20,20}; + +static enum item_type town_item[]={type_town_label_5e1, type_town_label_1e2, type_town_label_2e2, type_town_label_5e2, type_town_label_1e3, type_town_label_1e3, type_town_label_2e3, type_town_label_5e3, type_town_label_1e4, type_town_label_2e4, type_town_label_5e4, type_town_label_1e5, type_town_label_1e5, type_town_label_2e5, type_town_label_5e5, type_town_label_1e6, type_town_label_2e6}; +static enum item_type district_item[]={type_district_label_5e1, type_district_label_1e2, type_district_label_2e2, type_district_label_5e2, type_district_label_1e3, type_district_label_1e3, type_district_label_2e3, type_district_label_5e3, type_district_label_1e4, type_district_label_2e4, type_district_label_5e4, type_district_label_1e5, type_district_label_1e5, type_district_label_2e5, type_district_label_5e5, type_district_label_1e6, type_district_label_2e6}; +int +town_get(struct map_rect_priv *mr, struct town_priv *twn, struct item *item) +{ + int size; + for (;;) { + if (mr->b.p >= mr->b.end) + return 0; + town_get_data(twn, &mr->b.p); + twn->cidx=0; + twn->aidx=0; + twn->attr_next=attr_label; + if (! mr->cur_sel || (twn->order <= limit[mr->cur_sel->order[layer_town]] && coord_rect_contains(&mr->cur_sel->rect,&twn->c))) { + switch(twn->type) { + case 1: + size=twn->size; + if (size >= sizeof(town_item)/sizeof(enum item_type)) + size=sizeof(town_item)/sizeof(enum item_type)-1; + item->type=town_item[size]; + break; + case 3: + size=twn->size; + if (size == 6 && twn->order < 14) + size++; + if (size == 5 && twn->order < 14) + size+=2; + if (size >= sizeof(district_item)/sizeof(enum item_type)) + size=sizeof(district_item)/sizeof(enum item_type)-1; + item->type=district_item[size]; + break; + case 4: + item->type=type_port_label; + break; + case 9: + item->type=type_highway_exit_label; + break; + default: + printf("unknown town type 0x%x '%s' '%s' 0x%x,0x%x\n", twn->type, twn->name, twn->district, twn->c.x, twn->c.y); + item->type=type_town_label; + } + item->id_hi=twn->country | (mr->current_file << 16); + item->id_lo=twn->id; + item->priv_data=twn; + item->meth=&town_meth; + return 1; + } + } +} + +int +town_get_byid(struct map_rect_priv *mr, struct town_priv *twn, int id_hi, int id_lo, struct item *item) +{ + int country=id_hi & 0xffff; + int res; + if (!tree_search_hv(mr->m->dirname, "town", (id_lo >> 8) | (country << 24), id_lo & 0xff, &res)) + return 0; + block_get_byindex(mr->m->file[mr->current_file], res >> 16, &mr->b); + mr->b.p=mr->b.block_start+(res & 0xffff); + return town_get(mr, twn, item); +} + +static int +town_search_compare(unsigned char **p, struct map_rect_priv *mr) +{ + int country, d; + char *name; + + country=get_u16(p); + dbg(1,"country 0x%x ", country); + name=get_string(p); + dbg(1,"name '%s' ",name); + mr->search_blk_count=get_u32(p); + mr->search_blk_off=(struct block_offset *)(*p); + dbg(1,"len %d ", mr->search_blk_count); + (*p)+=mr->search_blk_count*4; + d=mr->search_country-country; + if (!d) { + if (mr->search_partial) + d=strncasecmp(mr->search_str, name, strlen(mr->search_str)); + else + d=strcasecmp(mr->search_str, name); + } + dbg(1,"%d \n",d); + return d; + +} + + + +struct item * +town_search_get_item(struct map_rect_priv *mr) +{ + int dir=1,leaf; + + if (! mr->search_blk_count) { + if (mr->search_partial) { + dbg(1,"partial 0x%x '%s' ***\n", mr->search_country, mr->search_str); + if (! mr->search_linear) { + while ((leaf=tree_search_next(&mr->ts, &mr->search_p, dir)) != -1) { + dir=town_search_compare(&mr->search_p, mr); + if (! dir && leaf) { + mr->search_linear=1; + mr->search_p=NULL; + break; + } + } + if (! mr->search_linear) + return NULL; + } + if (! tree_search_next_lin(&mr->ts, &mr->search_p)) + return NULL; + if (town_search_compare(&mr->search_p, mr)) + return NULL; + dbg(1,"found %d blocks\n",mr->search_blk_count); + } else { + #if 0 + dbg(1,"full 0x%x '%s' ***\n", country, search); + while (tree_search_next(&ts, &p, dir) != -1) { + ps=p; + printf("0x%x ",p-ts.f->begin); + dir=show_town2(&p, country, search, 0); + if (! dir) { + printf("*** found full: "); + show_town2(&ps, country, search, 0); + break; + } + } + #endif + return NULL; + } + } + if (! mr->search_blk_count) + return NULL; + dbg(1,"block 0x%x offset 0x%x\n", mr->search_blk_off->block, mr->search_blk_off->offset); + block_get_byindex(mr->m->file[mr->current_file], mr->search_blk_off->block, &mr->b); + mr->b.p=mr->b.block_start+mr->search_blk_off->offset; + town_get(mr, &mr->town, &mr->item); + mr->search_blk_off++; + mr->search_blk_count--; + return &mr->item; +} diff --git a/src/data/mg/tree.c b/src/data/mg/tree.c new file mode 100644 index 00000000..aedce721 --- /dev/null +++ b/src/data/mg/tree.c @@ -0,0 +1,232 @@ +#include <stdio.h> +#include "debug.h" +#include "mg.h" + +struct tree_hdr { + unsigned int addr; + unsigned int size; + unsigned int low; +}; + +struct tree_hdr_h { + unsigned int addr; + unsigned int size; +}; + +struct tree_leaf_h { + unsigned int lower; + unsigned int higher; + unsigned int match; + unsigned int value; +}; + + +struct tree_hdr_v { + unsigned int count; + unsigned int next; + unsigned int unknown; +}; + +struct tree_leaf_v { + unsigned char key; + int value; +} __attribute__((packed)); + +static int +tree_search_h(struct file *file, unsigned int search) +{ + unsigned char *p=file->begin,*end; + int last,i=0,value,lower; + struct tree_hdr_h *thdr; + struct tree_leaf_h *tleaf; + + dbg(1,"enter\n"); + while (i++ < 1000) { + thdr=(struct tree_hdr_h *)p; + p+=sizeof(*thdr); + end=p+thdr->size; + dbg(1,"@0x%x\n", p-file->begin); + last=0; + while (p < end) { + tleaf=(struct tree_leaf_h *)p; + p+=sizeof(*tleaf); + dbg(1,"low:0x%x high:0x%x match:0x%x val:0x%x search:0x%x\n", tleaf->lower, tleaf->higher, tleaf->match, tleaf->value, search); + value=tleaf->value; + if (value == search) + return tleaf->match; + if (value > search) { + dbg(1,"lower\n"); + lower=tleaf->lower; + if (lower) + last=lower; + break; + } + last=tleaf->higher; + } + if (! last || last == -1) + return 0; + p=file->begin+last; + } + return 0; +} + +static int +tree_search_v(struct file *file, int offset, int search) +{ + unsigned char *p=file->begin+offset; + int i=0,count,next; + struct tree_hdr_v *thdr; + struct tree_leaf_v *tleaf; + while (i++ < 1000) { + thdr=(struct tree_hdr_v *)p; + p+=sizeof(*thdr); + count=L(thdr->count); + dbg(1,"offset=0x%x count=0x%x\n", p-file->begin, count); + while (count--) { + tleaf=(struct tree_leaf_v *)p; + p+=sizeof(*tleaf); + dbg(1,"0x%x 0x%x\n", tleaf->key, search); + if (tleaf->key == search) + return L(tleaf->value); + } + next=L(thdr->next); + if (! next) + break; + p=file->begin+next; + } + return 0; +} + +int +tree_search_hv(char *dirname, char *filename, unsigned int search_h, unsigned int search_v, int *result) +{ + struct file *f_idx_h, *f_idx_v; + char buffer[4096]; + int h,v; + + dbg(1,"enter(%s, %s, 0x%x, 0x%x, %p)\n",dirname, filename, search_h, search_v, result); + sprintf(buffer, "%s/%s.h1", dirname, filename); + f_idx_h=file_create_caseinsensitive(buffer); + sprintf(buffer, "%s/%s.v1", dirname, filename); + f_idx_v=file_create_caseinsensitive(buffer); + dbg(1,"%p %p\n", f_idx_h, f_idx_v); + if ((h=tree_search_h(f_idx_h, search_h))) { + dbg(1,"h=0x%x\n", h); + if ((v=tree_search_v(f_idx_v, h, search_v))) { + dbg(1,"v=0x%x\n", v); + *result=v; + file_destroy(f_idx_v); + file_destroy(f_idx_h); + dbg(1,"return 1\n"); + return 1; + } + } + file_destroy(f_idx_v); + file_destroy(f_idx_h); + dbg(1,"return 0\n"); + return 0; +} + +static struct tree_search_node * +tree_search_enter(struct tree_search *ts, int offset) +{ + struct tree_search_node *tsn=&ts->nodes[++ts->curr_node]; + unsigned char *p; + p=ts->f->begin+offset; + tsn->hdr=(struct tree_hdr *)p; + tsn->p=p+sizeof(struct tree_hdr); + tsn->last=tsn->p; + tsn->end=p+tsn->hdr->size; + tsn->low=tsn->hdr->low; + tsn->high=tsn->hdr->low; + dbg(1,"pos 0x%x addr 0x%x size 0x%x low 0x%x end 0x%x\n", p-ts->f->begin, tsn->hdr->addr, tsn->hdr->size, tsn->hdr->low, tsn->end-ts->f->begin); + return tsn; +} + +int tree_search_next(struct tree_search *ts, unsigned char **p, int dir) +{ + struct tree_search_node *tsn=&ts->nodes[ts->curr_node]; + + if (! *p) + *p=tsn->p; + dbg(1,"next *p=%p dir=%d\n", *p, dir); + dbg(1,"low1=0x%x high1=0x%x\n", tsn->low, tsn->high); + if (dir <= 0) { + dbg(1,"down 0x%x\n", tsn->low); + if (tsn->low != 0xffffffff) { + tsn=tree_search_enter(ts, tsn->low); + *p=tsn->p; + tsn->high=get_u32(p); + ts->last_node=ts->curr_node; + dbg(1,"saving last2 %d 0x%x\n", ts->curr_node, tsn->last-ts->f->begin); + dbg(1,"high2=0x%x\n", tsn->high); + return 0; + } + return -1; + } + tsn->low=tsn->high; + tsn->last=*p; + tsn->high=get_u32(p); + dbg(1,"saving last3 %d %p\n", ts->curr_node, tsn->last); + if (*p < tsn->end) + return (tsn->low == 0xffffffff ? 1 : 0); + dbg(1,"end reached\n"); + if (tsn->low != 0xffffffff) { + dbg(1,"low 0x%x\n", tsn->low); + tsn=tree_search_enter(ts, tsn->low); + *p=tsn->p; + tsn->high=get_u32(p); + ts->last_node=ts->curr_node; + dbg(1,"saving last4 %d 0x%x\n", ts->curr_node, tsn->last-ts->f->begin); + dbg(1,"high4=0x%x\n", tsn->high); + return 0; + } + return -1; +} + +int tree_search_next_lin(struct tree_search *ts, unsigned char **p) +{ + struct tree_search_node *tsn=&ts->nodes[ts->curr_node]; + int high; + + dbg(1,"pos=%d 0x%x\n", ts->curr_node, *p-ts->f->begin); + if (*p) + ts->nodes[ts->last_node].last=*p; + *p=tsn->last; + for (;;) { + high=get_u32(p); + if (*p < tsn->end) { + ts->last_node=ts->curr_node; + while (high != 0xffffffff) { + tsn=tree_search_enter(ts, high); + dbg(1,"reload %d\n",ts->curr_node); + high=tsn->low; + } + return 1; + } + dbg(1,"eon %d 0x%x 0x%x\n", ts->curr_node, *p-ts->f->begin, tsn->end-ts->f->begin); + if (! ts->curr_node) + break; + ts->curr_node--; + tsn=&ts->nodes[ts->curr_node]; + *p=tsn->last; + } + + return 0; +} + +void +tree_search_init(char *dirname, char *filename, struct tree_search *ts, int offset) +{ + char buffer[4096]; + sprintf(buffer, "%s/%s", dirname, filename); + ts->f=file_create_caseinsensitive(buffer); + ts->curr_node=-1; + tree_search_enter(ts, offset); +} + +void +tree_search_free(struct tree_search *ts) +{ + file_destroy(ts->f); +} diff --git a/src/data/textfile/Makefile.am b/src/data/textfile/Makefile.am new file mode 100644 index 00000000..92850723 --- /dev/null +++ b/src/data/textfile/Makefile.am @@ -0,0 +1,4 @@ +include $(top_srcdir)/Makefile.inc +AM_CPPFLAGS = @NAVIT_CFLAGS@ -I../.. +plugin_LTLIBRARIES = libdata_textfile.la +libdata_textfile_la_SOURCES = textfile.c textfile.h diff --git a/src/data/textfile/textfile.c b/src/data/textfile/textfile.c new file mode 100644 index 00000000..e5c3497a --- /dev/null +++ b/src/data/textfile/textfile.c @@ -0,0 +1,355 @@ +#include <glib.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <math.h> +#include "plugin.h" +#include "map.h" +#include "maptype.h" +#include "item.h" +#include "attr.h" +#include "coord.h" +#include "transform.h" +#include "projection.h" + +#include "textfile.h" + +static int map_id; + +static int +contains_coord(char *line) +{ + return g_ascii_isdigit(line[0]); +} + +static int debug=0; + +static int +get_tag(char *line, char *name, int *pos, char *ret, char *name_ret) +{ + int len=0,quoted; + char *p,*e,*n; + + if (debug) + printf("get_tag %s from %s\n", name, line); + if (name) + len=strlen(name); + if (pos) + p=line+*pos; + else + p=line; + for(;;) { + while (*p == ' ') { + p++; + } + if (! *p) + return 0; + n=p; + e=index(p,'='); + if (! e) + return 0; + p=e+1; + quoted=0; + while (*p) { + if (*p == ' ' && !quoted) + break; + if (*p == '"') + quoted=1-quoted; + p++; + } + if (name == NULL || (e-n == len && !strncmp(n, name, len))) { + if (name_ret) { + len=e-n; + strncpy(name_ret, n, len); + name_ret[len]='\0'; + } + e++; + len=p-e; + if (e[0] == '"') { + e++; + len-=2; + } + strncpy(ret, e, len); + ret[len]='\0'; + if (pos) + *pos=p-line; + return 1; + } + } + return 0; +} + +static void +get_line(struct map_rect_priv *mr) +{ + if(mr->f) { + mr->pos=ftell(mr->f); + fgets(mr->line, SIZE, mr->f); + if (strlen(mr->line) >= SIZE-1) + printf("line too long\n"); + } +} + +static void +map_destroy_textfile(struct map_priv *m) +{ + if (debug) + printf("map_destroy_textfile\n"); + g_free(m); +} + +static void +textfile_coord_rewind(void *priv_data) +{ +} + +static void +parse_line(struct map_rect_priv *mr) +{ + int pos=0; + sscanf(mr->line,"%lf %c %lf %c %n",&mr->lat,&mr->lat_c,&mr->lng,&mr->lng_c,&pos); + if (pos < strlen(mr->line)) { + strcpy(mr->attrs, mr->line+pos); + } +} + +static int +textfile_coord_get(void *priv_data, struct coord *c, int count) +{ + double lat,lng; + struct coord_geo cg; + struct map_rect_priv *mr=priv_data; + int ret=0; + if (debug) + printf("textfile_coord_get %d\n",count); + while (count--) { + if (contains_coord(mr->line) && mr->f && !feof(mr->f) && (!mr->item.id_hi || !mr->eoc)) { + parse_line(mr); + lat=mr->lat; + lng=mr->lng; + cg.lat=floor(lat/100); + lat-=cg.lat*100; + cg.lat+=lat/60; + + cg.lng=floor(lng/100); + lng-=cg.lng*100; + cg.lng+=lng/60; + + transform_from_geo(projection_mg, &cg, c); + c++; + ret++; + get_line(mr); + if (mr->item.id_hi) + mr->eoc=1; + } else { + break; + } + } + return ret; +} + +static void +textfile_attr_rewind(void *priv_data) +{ +} + +static void +textfile_encode_attr(char *attr_val, enum attr_type attr_type, struct attr *attr) +{ + if (attr_type >= attr_type_int_begin && attr_type <= attr_type_int_end) + attr->u.num=atoi(attr_val); + else + attr->u.str=attr_val; +} + +static int +textfile_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr) +{ + struct map_rect_priv *mr=priv_data; + char *str=NULL; + if (debug) + printf("textfile_attr_get mr=%p attrs='%s' ", mr, mr->attrs); + if (attr_type != mr->attr_last) { + if (debug) + printf("reset attr_pos\n"); + mr->attr_pos=0; + mr->attr_last=attr_type; + } + if (attr_type == attr_any) { + if (debug) + printf("attr_any"); + if (get_tag(mr->attrs,NULL,&mr->attr_pos,mr->attr, mr->attr_name)) { + attr_type=attr_from_name(mr->attr_name); + if (debug) + printf("found attr '%s' 0x%x\n", mr->attr_name, attr_type); + attr->type=attr_type; + textfile_encode_attr(mr->attr, attr_type, attr); + return 1; + } + } else { + str=attr_to_name(attr_type); + if (debug) + printf("attr='%s' ",str); + if (get_tag(mr->attrs,str,&mr->attr_pos,mr->attr, NULL)) { + textfile_encode_attr(mr->attr, attr_type, attr); + if (debug) + printf("found\n"); + return 1; + } + } + if (debug) + printf("not found\n"); + return 0; +} + +static struct item_methods methods_textfile = { + textfile_coord_rewind, + textfile_coord_get, + textfile_attr_rewind, + textfile_attr_get, +}; + +static struct map_rect_priv * +map_rect_new_textfile(struct map_priv *map, struct map_selection *sel) +{ + struct map_rect_priv *mr; + + if (debug) + printf("map_rect_new_textfile\n"); + mr=g_new0(struct map_rect_priv, 1); + mr->m=map; + mr->sel=sel; + mr->item.id_hi=0; + mr->item.id_lo=0; + mr->item.meth=&methods_textfile; + mr->item.priv_data=mr; + mr->f=fopen(map->filename, "r"); + if(!mr->f) { + printf("map_rect_new_textfile unable to open textfile %s\n",map->filename); + } + get_line(mr); + return mr; +} + + +static void +map_rect_destroy_textfile(struct map_rect_priv *mr) +{ + if (mr->f) { + fclose(mr->f); + } + g_free(mr); +} + +static struct item * +map_rect_get_item_textfile(struct map_rect_priv *mr) +{ + char *p,type[SIZE]; + if (debug) + printf("map_rect_get_item_textfile id_hi=%d line=%s", mr->item.id_hi, mr->line); + if (!mr->f) { + return NULL; + } + for(;;) { + if (feof(mr->f)) { + if (debug) + printf("map_rect_get_item_textfile: eof\n"); + if (mr->item.id_hi) { + return NULL; + } + mr->item.id_hi++; + fseek(mr->f, 0, SEEK_SET); + get_line(mr); + } + if (mr->item.id_hi) { + if (!contains_coord(mr->line)) { + get_line(mr); + continue; + } + if ((p=index(mr->line,'\n'))) + *p='\0'; + if (debug) + printf("map_rect_get_item_textfile: point found\n"); + mr->attrs[0]='\0'; + parse_line(mr); + mr->eoc=0; + mr->item.id_lo=mr->pos; + } else { + if (contains_coord(mr->line)) { + get_line(mr); + continue; + } + if ((p=index(mr->line,'\n'))) + *p='\0'; + if (debug) + printf("map_rect_get_item_textfile: line found\n"); + if (! mr->line[0]) { + get_line(mr); + continue; + } + mr->item.id_lo=mr->pos; + strcpy(mr->attrs, mr->line); + get_line(mr); + if (debug) + printf("mr=%p attrs=%s\n", mr, mr->attrs); + } + if (debug) + printf("get_attrs %s\n", mr->attrs); + if (get_tag(mr->attrs,"type",NULL,type,NULL)) { + if (debug) + printf("type='%s'\n", type); + mr->item.type=item_from_name(type); + if (mr->item.type == type_none) + printf("Warning: type '%s' unknown\n", type); + } else { + get_line(mr); + continue; + } + mr->attr_last=attr_none; + if (debug) + printf("return attr='%s'\n", mr->attrs); + return &mr->item; + } +} + +static struct item * +map_rect_get_item_byid_textfile(struct map_rect_priv *mr, int id_hi, int id_lo) +{ + fseek(mr->f, id_lo, SEEK_SET); + get_line(mr); + mr->item.id_hi=id_hi; + return map_rect_get_item_textfile(mr); +} + +static struct map_methods map_methods_textfile = { + map_destroy_textfile, + map_rect_new_textfile, + map_rect_destroy_textfile, + map_rect_get_item_textfile, + map_rect_get_item_byid_textfile, +}; + +static struct map_priv * +map_new_textfile(struct map_methods *meth, char *filename, char **charset, enum projection *pro) +{ + struct map_priv *m; + if (debug) + printf("map_new_textfile %s\n",filename); + *meth=map_methods_textfile; + *charset="iso8859-1"; + *pro=projection_mg; + + m=g_new(struct map_priv, 1); + m->id=++map_id; + m->filename=g_strdup(filename); + return m; +} + +void +plugin_init(void) +{ + if (debug) + printf("textfile: plugin_init\n"); + plugin_register_map_type("textfile", map_new_textfile); +} + diff --git a/src/data/textfile/textfile.h b/src/data/textfile/textfile.h new file mode 100644 index 00000000..980c95d6 --- /dev/null +++ b/src/data/textfile/textfile.h @@ -0,0 +1,28 @@ +#include <stdio.h> +#include "attr.h" +#include "coord.h" +struct map_priv { + int id; + char *filename; +}; + +#define SIZE 512 + +struct map_rect_priv { + struct map_selection *sel; + + FILE *f; + long pos; + char line[SIZE]; + int attr_pos; + enum attr_type attr_last; + char attrs[SIZE]; + char attr[SIZE]; + char attr_name[SIZE]; + double lat,lng; + char lat_c,lng_c; + int eoc; + struct map_priv *m; + struct item item; +}; + diff --git a/src/data_window.c b/src/data_window.c index 1eff89dc..99889488 100644 --- a/src/data_window.c +++ b/src/data_window.c @@ -1,5 +1,6 @@ #include <malloc.h> #include <stdio.h> +#include <string.h> #include <gtk/gtk.h> #include "param.h" #include "data_window.h" @@ -36,7 +37,6 @@ data_window_begin(struct data_window *win) } } -#if 0 static void click_column(GtkCList *clist, int column) { @@ -52,19 +52,30 @@ click_column(GtkCList *clist, int column) gtk_clist_sort(clist); } + GValue value; static void -select_row(GtkCList *clist, int row, int column, GdkEventButton *event, struct data_window *win) +select_row(GtkTreeView *tree, GtkTreePath *path, GtkTreeViewColumn *column, struct data_window *win) { int i; if (win->callback) { + printf("callback\n"); + char *cols[20]; - for (i=0;i<20;i++) { - gtk_clist_get_text(clist, row, i, &cols[i]); + GtkTreeIter iter; + GtkTreeModel *model; + + model=gtk_tree_view_get_model(tree); + gtk_tree_model_get_iter(model, &iter, path); + + for (i=0;i<gtk_tree_model_get_n_columns(model);i++) { + gtk_tree_model_get_value(model, &iter, i, &value); + cols[i]=g_strdup_value_contents(&value)+1; + cols[i][strlen(cols[i])-1]='\0'; + g_value_unset(&value); } win->callback(win, cols); } } -#endif void data_window_add(struct data_window *win, struct param_list *param, int count) @@ -87,6 +98,10 @@ data_window_add(struct data_window *win, struct param_list *param, int count) gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (win->treeview),-1,param[i].name, cell,"text",i, NULL); } +#if 0 + g_signal_connect(G_OBJECT(win->treeview), "click-column", G_CALLBACK(click_column), NULL); +#endif + g_signal_connect(G_OBJECT(win->treeview), "row-activated", G_CALLBACK(select_row), win); } /* find data storage and create a new one if none is there */ @@ -106,19 +121,9 @@ data_window_add(struct data_window *win, struct param_list *param, int count) gtk_list_store_set(liststore,&iter,i,utf8,-1); } -#if 0 - g_signal_connect(G_OBJECT(win->clist), "click-column", G_CALLBACK(click_column), NULL); - g_signal_connect(G_OBJECT(win->clist), "select-row", G_CALLBACK(select_row), win); -#endif } void data_window_end(struct data_window *win) { -#if 0 - if (win && win->treeview) { - gtk_clist_thaw(GTK_CLIST(win->clist)); - gtk_clist_columns_autosize (GTK_CLIST(win->clist)); - } -#endif } diff --git a/src/debug.c b/src/debug.c index 5fbe6035..62a93350 100644 --- a/src/debug.c +++ b/src/debug.c @@ -1,11 +1,16 @@ #include <signal.h> +#include <stdarg.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <time.h> +#include <glib.h> #include "file.h" #include "debug.h" +int debug_level=0; +static GHashTable *debug_hash; static void sigsegv(int sig) { @@ -26,5 +31,52 @@ static void sigsegv(int sig) void debug_init(void) { +#if 0 signal(SIGSEGV, sigsegv); +#endif + debug_hash=g_hash_table_new(g_str_hash, g_str_equal); +} + + +static void +debug_update_level(gpointer key, gpointer value, gpointer user_data) +{ + if (debug_level < (int) value) + debug_level=(int) value; +} + +void +debug_level_set(char *name, int level) +{ + debug_level=0; + g_hash_table_insert(debug_hash, name, (gpointer) level); + g_hash_table_foreach(debug_hash, debug_update_level, NULL); + debug_level_get(name); +} + +int +debug_level_get(const char *name) +{ + return (int)(g_hash_table_lookup(debug_hash, name)); +} + +void +debug_print(int level, const char *module, const char *function, const char *fmt, ...) +{ + va_list ap; + int module_len=strlen(module); + int function_len=strlen(function); + char buffer[module_len+function_len+3]; + + strcpy(buffer, module); + buffer[module_len]=':'; + strcpy(buffer+module_len+1, function); + + if (debug_level_get(module) >= level || debug_level_get(buffer) >= level) { + strcpy(buffer+module_len+function_len+1, ":"); + printf("%s",buffer); + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + } } diff --git a/src/debug.h b/src/debug.h index fb9abbc9..69ced33a 100644 --- a/src/debug.h +++ b/src/debug.h @@ -1 +1,8 @@ +int debug_level; +#define dbg(level,fmt...) if (debug_level >= level) debug_print(level,MODULE,__PRETTY_FUNCTION__,fmt) + +/* prototypes */ void debug_init(void); +void debug_level_set(char *name, int level); +int debug_level_get(const char *name); +void debug_print(int level, const char *module, const char *function, const char *fmt, ...); diff --git a/src/destination.h b/src/destination.h index 68530f8f..263cc920 100644 --- a/src/destination.h +++ b/src/destination.h @@ -1,11 +1,4 @@ -enum destination_type { - destination_type_town=4, - destination_type_poly=6, - destination_type_street=8, - destination_type_house=12, - destination_type_map_point=16, - destination_type_bookmark=128, -}; - -int destination_address(struct container *co); -int destination_set(struct container *co, enum destination_type type, char *text, struct coord *c); +/* prototypes */ +struct navit; +int destination_address(struct navit *nav); +/* end of prototypes */ diff --git a/src/display.h b/src/display.h deleted file mode 100644 index 952381f2..00000000 --- a/src/display.h +++ /dev/null @@ -1,24 +0,0 @@ -#include "point.h" - -struct popup_item; -struct graphics; -struct graphics_gc; -struct graphics_font; - -struct display_list { - struct display_list *next; - void *data; - int type; - int attr; - char *label; - int count; - void (*info)(struct display_list *list, struct popup_item **popup); - struct point p[0]; -}; -void *display_add(struct display_list **head, int type, int attr, char *label, int count, struct point *p, void (*info)(struct display_list *list, struct popup_item **popup), void *data, int data_size); - -void display_free(struct display_list **list, int count); - -void display_draw(struct display_list *list, struct graphics *gr, struct graphics_gc *gc_fill, struct graphics_gc *gc_line); -void display_find(struct point *pnt, struct display_list **in, int in_count, int maxdist, struct display_list **out, int out_count); -void display_labels(struct display_list *list, struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg, struct graphics_font *font); diff --git a/src/fib-1.1/fib.c b/src/fib-1.1/fib.c index ace5d129..276b6bd3 100644 --- a/src/fib-1.1/fib.c +++ b/src/fib-1.1/fib.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: fib.c,v 1.1 2005-12-02 10:41:56 martin-s Exp $ + * $Id: fib.c,v 1.2 2007-07-04 22:44:39 martin-s Exp $ * */ @@ -261,6 +261,8 @@ fh_replacekey(struct fibheap *h, struct fibheap_el *x, int key) return ret; } +#include <stdio.h> + void * fh_replacekeydata(struct fibheap *h, struct fibheap_el *x, int key, void *data) { @@ -277,6 +279,7 @@ fh_replacekeydata(struct fibheap *h, struct fibheap_el *x, int key, void *data) * requires O(lgn) time. */ if ((r = fh_comparedata(h, key, data, x)) > 0) { + printf("fh_comparedata r=%d key=%d data=%p\n", r, key, data); /* XXX - bad code! */ abort(); fh_deleteel(h, x); @@ -5,6 +5,7 @@ #include <sys/mman.h> #include <dirent.h> #include <stdio.h> +#include <wordexp.h> #include <glib.h> #include "file.h" @@ -41,6 +42,15 @@ file_create(char *name) return file; } +int +file_exists(char *name) +{ + struct stat buf; + if (! stat(name, &buf)) + return 1; + return 0; +} + void file_remap_readonly(struct file *f) { @@ -152,6 +162,38 @@ file_destroy(struct file *f) g_free(f); } +struct file_wordexp { + wordexp_t we; +}; + +struct file_wordexp * +file_wordexp_new(char *pattern) +{ + struct file_wordexp *ret=g_new(struct file_wordexp, 1); + wordexp(pattern, &ret->we, 0); + return ret; +} + +int +file_wordexp_get_count(struct file_wordexp *wexp) +{ + return wexp->we.we_wordc; +} + +char ** +file_wordexp_get_array(struct file_wordexp *wexp) +{ + return wexp->we.we_wordv; +} + +void +file_wordexp_destroy(struct file_wordexp *wexp) +{ + wordfree(&wexp->we); + g_free(wexp); +} + + int file_get_param(struct file *file, struct param_list *param, int count) { @@ -10,14 +10,24 @@ struct file { struct file *next; }; +/* prototypes */ +struct file; +struct file_wordexp; +struct param_list; struct file *file_create(char *name); -void file_remap_readonly(struct file *file); +int file_exists(char *name); +void file_remap_readonly(struct file *f); void file_remap_readonly_all(void); -void file_unmap(struct file *file); +void file_unmap(struct file *f); void file_unmap_all(void); -struct file *file_create_caseinsensitive(char *name); -int file_get_param(struct file *file, struct param_list *param, int count); -void file_destroy(struct file *f); void *file_opendir(char *dir); char *file_readdir(void *hnd); void file_closedir(void *hnd); +struct file *file_create_caseinsensitive(char *name); +void file_destroy(struct file *f); +struct file_wordexp *file_wordexp_new(char *pattern); +int file_wordexp_get_count(struct file_wordexp *wexp); +char **file_wordexp_get_array(struct file_wordexp *wexp); +void file_wordexp_destroy(struct file_wordexp *wexp); +int file_get_param(struct file *file, struct param_list *param, int count); +/* end of prototypes */ diff --git a/src/graphics.c b/src/graphics.c index ad430c66..b9222990 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -1,416 +1,694 @@ #include <glib.h> +#include <stdio.h> +#include <math.h> +#include "debug.h" #include "string.h" #include "draw_info.h" #include "graphics.h" -#include "map_data.h" +#include "map.h" #include "coord.h" -#include "param.h" /* FIXME */ -#include "block.h" /* FIXME */ -#include "poly.h" -#include "town.h" -#include "street.h" #include "transform.h" -#include "container.h" +#include "projection.h" +#include "point.h" #include "plugin.h" -#include "display.h" -#include "data_window.h" #include "profile.h" +#include "mapset.h" +#include "route.h" -#define GC_BACKGROUND 0 -#define GC_WOOD 1 -#define GC_TOWN_FILL 2 -#define GC_TOWN_LINE 3 -#define GC_WATER_FILL 4 -#define GC_WATER_LINE 5 -#define GC_RAIL 6 -#define GC_TEXT_FG 7 -#define GC_TEXT_BG 8 -#define GC_BLACK 9 -#define GC_STREET_SMALL 10 -#define GC_STREET_SMALL_B 11 -#define GC_PARK 12 -#define GC_BUILDING 13 -#define GC_BUILDING_2 14 -#define GC_STREET_MID 15 -#define GC_STREET_MID_B 16 -#define GC_STREET_BIG 17 -#define GC_STREET_BIG_B 18 -#define GC_STREET_BIG2 19 -#define GC_STREET_BIG2_B 20 -#define GC_STREET_BIG2_L 21 -#define GC_STREET_NO_PASS 22 -#define GC_STREET_ROUTE 23 -#define GC_LAST 24 - - -int color[][3]={ - {0xffff, 0xefef, 0xb7b7}, - {0x8e8e, 0xc7c7, 0x8d8d}, - {0xffff, 0xc8c8, 0x9595}, - {0xebeb, 0xb4b4, 0x8181}, - {0x8282, 0xc8c8, 0xeaea}, - {0x5050, 0x9696, 0xb8b8}, - {0x8080, 0x8080, 0x8080}, - {0x0, 0x0, 0x0}, - {0xffff, 0xffff, 0xffff}, - {0x0, 0x0, 0x0}, - {0xffff, 0xffff, 0xffff}, - {0xe0e0, 0xe0e0, 0xe0e0}, - {0x7c7c, 0xc3c3, 0x3434}, - {0xe6e6, 0xe6e6, 0xe6e6}, - {0xffff, 0x6666, 0x6666}, - {0xffff, 0xffff, 0x0a0a}, - {0xe0e0, 0xe0e0, 0xe0e0}, - {0xffff, 0x0000, 0x0000}, - {0x0000, 0x0000, 0x0000}, - {0xffff, 0xffff, 0x0a0a}, - {0xffff, 0x0000, 0x0000}, - {0xffff, 0x0000, 0x0000}, - {0xe0e0, 0xe0e0, 0xffff}, - {0x0000, 0x0000, 0xa0a0}, +#include "layout.h" + +struct graphics +{ + struct graphics_priv *priv; + struct graphics_methods meth; + struct graphics_font *font[16]; + struct graphics_gc *gc[3]; + int ready; +}; + +struct displaylist { + GHashTable *dl; }; +struct graphics * +graphics_new(const char *type) +{ + struct graphics *this_; + struct graphics_priv * (*new)(struct graphics_methods *meth); + + new=plugin_get_graphics_type(type); + if (! new) + return NULL; + this_=g_new0(struct graphics, 1); + this_->priv=(*new)(&this_->meth); + return this_; +} + void -container_init_gra(struct container *co) +graphics_init(struct graphics *this_) { - struct graphics *gra=co->gra; - int i; + this_->gc[0]=graphics_gc_new(this_); + graphics_gc_set_background(this_->gc[0], &(struct color) { 0xffff, 0xefef, 0xb7b7 }); + graphics_gc_set_foreground(this_->gc[0], &(struct color) { 0xffff, 0xefef, 0xb7b7 }); + this_->gc[1]=graphics_gc_new(this_); + graphics_gc_set_background(this_->gc[1], &(struct color) { 0x0000, 0x0000, 0x0000 }); + graphics_gc_set_foreground(this_->gc[1], &(struct color) { 0xffff, 0xffff, 0xffff }); + this_->gc[2]=graphics_gc_new(this_); + graphics_gc_set_background(this_->gc[2], &(struct color) { 0xffff, 0xffff, 0xffff }); + graphics_gc_set_foreground(this_->gc[2], &(struct color) { 0xffff, 0xffff, 0xffff }); + this_->meth.background_gc(this_->priv, this_->gc[0]->priv); +} - gra->font=g_new0(struct graphics_font *,3); - gra->font[0]=gra->font_new(gra,140); - gra->font[1]=gra->font_new(gra,200); - gra->font[2]=gra->font_new(gra,300); - gra->gc=g_new0(struct graphics_gc *, GC_LAST); - for (i = 0 ; i < GC_LAST ; i++) { - gra->gc[i]=gra->gc_new(gra); - gra->gc_set_background(gra->gc[i], color[0][0], color[0][1], color[0][2]); - gra->gc_set_foreground(gra->gc[i], color[i][0], color[i][1], color[i][2]); - } - gra->gc_set_background(gra->gc[GC_TEXT_BG], color[7][0], color[7][1], color[7][2]); +void * +graphics_get_data(struct graphics *this_, char *type) +{ + return (this_->meth.get_data(this_->priv, type)); } void -graphics_get_view(struct container *co, long *x, long *y, unsigned long *scale) +graphics_register_resize_callback(struct graphics *this_, void (*callback)(void *data, int w, int h), void *data) { - struct transformation *t=co->trans; - if (x) *x=t->center.x; - if (y) *y=t->center.y; - if (scale) *scale=t->scale; + this_->meth.register_resize_callback(this_->priv, callback, data); } void -graphics_set_view(struct container *co, long *x, long *y, unsigned long *scale) +graphics_register_button_callback(struct graphics *this_, void (*callback)(void *data, int pressed, int button, struct point *p), void *data) { - struct transformation *t=co->trans; - if (x) t->center.x=*x; - if (y) t->center.y=*y; - if (scale) t->scale=*scale; - graphics_redraw(co); + this_->meth.register_button_callback(this_->priv, callback, data); } -static void -graphics_draw(struct map_data *mdata, int file, struct container *co, int display, int limit, int limit2, - void(*func)(struct block_info *, unsigned char *, unsigned char *, void *)) +void +graphics_register_motion_callback(struct graphics *this_, void (*callback)(void *data, struct point *p), void *data) +{ + this_->meth.register_motion_callback(this_->priv, callback, data); +} + +struct graphics_font * +graphics_font_new(struct graphics *gra, int size) +{ + struct graphics_font *this_; + + this_=g_new0(struct graphics_font,1); + this_->priv=gra->meth.font_new(gra->priv, &this_->meth, size); + return this_; +} + +struct graphics_gc * +graphics_gc_new(struct graphics *gra) +{ + struct graphics_gc *this_; + + this_=g_new0(struct graphics_gc,1); + this_->priv=gra->meth.gc_new(gra->priv, &this_->meth); + return this_; +} + +void +graphics_gc_set_foreground(struct graphics_gc *gc, struct color *c) +{ + gc->meth.gc_set_foreground(gc->priv, c); +} + +void +graphics_gc_set_background(struct graphics_gc *gc, struct color *c) +{ + gc->meth.gc_set_background(gc->priv, c); +} + +void +graphics_gc_set_linewidth(struct graphics_gc *gc, int width) +{ + gc->meth.gc_set_linewidth(gc->priv, width); +} + +struct graphics_image * +graphics_image_new(struct graphics *gra, char *path) +{ + struct graphics_image *this_; + + this_=g_new0(struct graphics_image,1); + this_->priv=gra->meth.image_new(gra->priv, &this_->meth, path, &this_->width, &this_->height); + return this_; +} + +void +graphics_draw_restore(struct graphics *this_, struct point *p, int w, int h) +{ + this_->meth.draw_restore(this_->priv, p, w, h); +} + +void +graphics_draw_mode(struct graphics *this_, enum draw_mode_num mode) +{ + this_->meth.draw_mode(this_->priv, mode); +} + +void +graphics_draw_lines(struct graphics *this_, struct graphics_gc *gc, struct point *p, int count) { - struct draw_info info; - info.co=co; - info.display=display; - info.limit=limit; - map_data_foreach(mdata, file, co->trans, limit2, func, &info); + this_->meth.draw_lines(this_->priv, gc->priv, p, count); } void -graphics_redraw(struct container *co) +graphics_draw_circle(struct graphics *this_, struct graphics_gc *gc, struct point *p, int r) { - int scale=transform_get_scale(co->trans); - int i,slimit=255,tlimit=255,plimit=255; - int bw[4],w[4],t[4]; - struct display_list **disp=co->disp; - struct graphics *gra=co->gra; + this_->meth.draw_circle(this_->priv, gc->priv, p, r); +} + + +#include "attr.h" +#include "popup.h" +#include <stdio.h> #if 0 - printf("scale=%d center=0x%lx,0x%lx mercator scale=%f\n", scale, co->trans->center.x, co->trans->center.y, transform_scale(co->trans->center.y)); +static void +popup_view_html(struct popup_item *item, char *file) +{ + char command[1024]; + sprintf(command,"firefox %s", file); + system(command); +} + +static void +graphics_popup(struct display_list *list, struct popup_item **popup) +{ + struct item *item; + struct attr attr; + struct map_rect *mr; + struct coord c; + struct popup_item *curr_item,*last=NULL; + item=list->data; + mr=map_rect_new(item->map, NULL, NULL, 0); + printf("id hi=0x%x lo=0x%x\n", item->id_hi, item->id_lo); + item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo); + if (item) { + if (item_attr_get(item, attr_name, &attr)) { + curr_item=popup_item_new_text(popup,attr.u.str,1); + if (item_attr_get(item, attr_info_html, &attr)) { + popup_item_new_func(&last,"HTML Info",1, popup_view_html, g_strdup(attr.u.str)); + } + if (item_attr_get(item, attr_price_html, &attr)) { + popup_item_new_func(&last,"HTML Preis",2, popup_view_html, g_strdup(attr.u.str)); + } + curr_item->submenu=last; + } + } + map_rect_destroy(mr); +} #endif - - display_free(co->disp, display_end); - transform_setup_source_rect(co->trans); +struct displayitem { + struct item item; + char *label; + int displayed; + int count; + struct point pnt[0]; +}; - gra->draw_mode(gra, draw_mode_begin); - for (i = 0 ; i < data_window_type_end; i++) { - data_window_begin(co->data_window[i]); +static int +xdisplay_free_list(gpointer key, gpointer value, gpointer user_data) +{ + GList *h, *l; + h=value; + l=h; + while (l) { +#if 1 + struct displayitem *di=l->data; + if (! di->displayed && di->item.type < type_line) + dbg(0,"warning: item '%s' not displayed\n", item_to_name(di->item.type)); +#endif + g_free(l->data); + l=g_list_next(l); } - gra->gc_set_linewidth(gra->gc[GC_RAIL], 3); - - bw[0]=0; - bw[1]=0; - bw[2]=0; - bw[3]=0; - w[0]=1; - w[1]=1; - w[2]=1; - w[3]=1; - t[0]=0xf; - t[1]=0xf; - t[2]=0xf; - t[3]=0xf; - if (scale < 2) { - tlimit=0xff; - slimit=0xff; - bw[0]=17; - w[0]=15; - bw[1]=19; - w[1]=17; - bw[2]=19; - w[2]=17; - bw[3]=21; - w[3]=17; - } else if (scale < 4) { - tlimit=0xff; - slimit=0xff; - bw[0]=11; - w[0]=9; - bw[1]=13; - w[1]=11; - bw[2]=13; - w[2]=11; - bw[3]=15; - w[3]=11; - } else if (scale < 8) { - tlimit=0xff; - slimit=0xff; - bw[0]=5; - w[0]=3; - bw[1]=11; - w[1]=9; - bw[2]=11; - w[2]=9; - bw[3]=13; - w[3]=9; - t[0]=0xa; - t[1]=0xf; - } else if (scale < 16) { - tlimit=0xff; - slimit=0xff; - bw[1]=9; - w[1]=7; - bw[2]=9; - w[2]=7; - bw[3]=11; - w[3]=7; - t[0]=0x9; - t[1]=0xe; - } else if (scale < 32) { - tlimit=0xff; - slimit=0xff; - bw[1]=5; - w[1]=3; - bw[2]=5; - w[2]=3; - bw[3]=5; - w[3]=3; - t[0]=0x8; - t[1]=0xb; - } else if (scale < 64) { - tlimit=0xf; - slimit=0x6; - bw[1]=5; - w[1]=3; - bw[2]=5; - w[2]=3; - bw[3]=5; - w[3]=3; - t[0]=0x8; - t[1]=0xa; - } else if (scale < 128) { - tlimit=0xc; - slimit=0x6; - plimit=0x1e; - w[1]=3; - w[2]=3; - bw[3]=5; - w[3]=3; - t[0]=0x7; - t[1]=0xa; - } else if (scale < 256) { - tlimit=0xb; - slimit=0x5; - plimit=0x1a; - w[2]=3; - bw[3]=5; - w[3]=3; - t[0]=0x7; - t[1]=0x8; - } else if (scale < 512) { - tlimit=0x9; - slimit=0x5; - plimit=0x14; - w[1]=0; - w[2]=1; - bw[3]=3; - w[3]=1; - t[0]=0x4; - t[1]=0x7; - } else if (scale < 1024) { - tlimit=0x8; - slimit=0x4; - slimit=0x4; - plimit=0x11; - w[1]=0; - w[2]=1; - bw[3]=3; - w[3]=1; - t[0]=0x3; - t[1]=0x5; - } else if (scale < 2048) { - tlimit=0x5; - slimit=0x3; - plimit=0x10; - bw[3]=3; - w[3]=1; - t[0]=0x2; - t[1]=0x4; - } else if (scale < 4096) { - bw[3]=3; - w[3]=1; - tlimit=0x4; - slimit=0x2; - plimit=0xf; - t[0]=0x2; - t[1]=0x3; - } else if (scale < 8192) { - bw[3]=3; - w[3]=1; - tlimit=0x3; - slimit=0x2; - plimit=0xf; - t[0]=0x1; - t[1]=0x2; - } else { - bw[3]=3; - w[3]=1; - tlimit=0x2; - slimit=0x2; - plimit=0xf; - t[0]=0x1; - t[1]=0x4; + g_list_free(h); + return TRUE; +} + +static void +xdisplay_free(GHashTable *display_list) +{ + g_hash_table_foreach_remove(display_list, xdisplay_free_list, NULL); +} + +void +display_add(struct displaylist *displaylist, struct item *item, int count, struct point *pnt, char *label) +{ + struct displayitem *di; + int len; + GList *l; + char *p; + + len=sizeof(*di)+count*sizeof(*pnt); + if (label) + len+=strlen(label)+1; + + p=g_malloc(len); + + di=(struct displayitem *)p; + di->displayed=0; + p+=sizeof(*di)+count*sizeof(*pnt); + di->item=*item; + if (label) { + di->label=p; + strcpy(di->label, label); + } else + di->label=NULL; + di->count=count; + memcpy(di->pnt, pnt, count*sizeof(*pnt)); + + l=g_hash_table_lookup(displaylist->dl, GINT_TO_POINTER(item->type)); + l=g_list_prepend(l, di); + g_hash_table_insert(displaylist->dl, GINT_TO_POINTER(item->type), l); +} + + +static void +label_line(struct graphics *gra, struct graphics_gc *fg, struct graphics_gc *bg, struct graphics_font *font, struct point *p, int count, char *label) +{ + int i,x,y,tl; + double dx,dy,l; + struct point p_t; + + tl=strlen(label)*400; + for (i = 0 ; i < count-1 ; i++) { + dx=p[i+1].x-p[i].x; + dx*=100; + dy=p[i+1].y-p[i].y; + dy*=100; + l=(int)sqrt((float)(dx*dx+dy*dy)); + if (l > tl) { + x=p[i].x; + y=p[i].y; + if (dx < 0) { + dx=-dx; + dy=-dy; + x=p[i+1].x; + y=p[i+1].y; + } + x+=(l-tl)*dx/l/200; + y+=(l-tl)*dy/l/200; + x-=dy*45/l/10; + y+=dx*45/l/10; + p_t.x=x; + p_t.y=y; + #if 0 + printf("display_text: '%s', %d, %d, %d, %d %d\n", label, x, y, dx*0x10000/l, dy*0x10000/l, l); + #endif + gra->meth.draw_text(gra->priv, fg->priv, bg->priv, font->priv, label, &p_t, dx*0x10000/l, dy*0x10000/l); + } } - gra->gc_set_linewidth(gra->gc[GC_STREET_SMALL], w[0]); - gra->gc_set_linewidth(gra->gc[GC_STREET_NO_PASS], w[0]); - gra->gc_set_linewidth(gra->gc[GC_STREET_SMALL_B], bw[0]); - gra->gc_set_linewidth(gra->gc[GC_STREET_MID], w[1]); - gra->gc_set_linewidth(gra->gc[GC_STREET_MID_B], bw[1]); - gra->gc_set_linewidth(gra->gc[GC_STREET_BIG], w[2]); - gra->gc_set_linewidth(gra->gc[GC_STREET_BIG_B], bw[2]); - gra->gc_set_linewidth(gra->gc[GC_STREET_BIG2], w[3]); - gra->gc_set_linewidth(gra->gc[GC_STREET_BIG2_B], bw[3]); - gra->gc_set_linewidth(gra->gc[GC_STREET_ROUTE], w[3]+7+w[3]/2); - -#ifdef DEBUG - profile_timer(NULL); -#endif - graphics_draw(co->map_data, file_border_ply, co, display_rail, plimit, 48, poly_draw_block); - graphics_draw(co->map_data, file_woodland_ply, co, display_wood, plimit, 48, poly_draw_block); - graphics_draw(co->map_data, file_other_ply, co, display_other, plimit, 48, poly_draw_block); - graphics_draw(co->map_data, file_town_twn, co, display_town, tlimit, 48, town_draw_block); - graphics_draw(co->map_data, file_water_ply, co, display_water, plimit, 48, poly_draw_block); - graphics_draw(co->map_data, file_sea_ply, co, display_sea, plimit, 48, poly_draw_block); - /* todo height, tunnel, bridge, street_bti ??? */ -#if 0 - graphics_draw(co->map_data, file_height_ply, co, display_other1, plimit, 48, poly_draw_block); -#endif - if (scale < 256) { - graphics_draw(co->map_data, file_rail_ply, co, display_rail, plimit, 48, poly_draw_block); +} + + +static void +xdisplay_draw_elements(struct graphics *gra, GHashTable *display_list, struct itemtype *itm) +{ + struct element *e; + GList *l,*ls,*es,*types; + enum item_type type; + struct graphics_gc *gc; + struct graphics_image *img; + struct point p; + + es=itm->elements; + while (es) { + e=es->data; + types=itm->type; + while (types) { + type=GPOINTER_TO_INT(types->data); + ls=g_hash_table_lookup(display_list, GINT_TO_POINTER(type)); + l=ls; + gc=NULL; + img=NULL; + while (l) { + struct displayitem *di; + di=l->data; + di->displayed=1; + if (! gc) { + gc=graphics_gc_new(gra); + gc->meth.gc_set_foreground(gc->priv, &e->color); + } + switch (e->type) { + case element_polygon: + gra->meth.draw_polygon(gra->priv, gc->priv, di->pnt, di->count); + break; + case element_polyline: + if (e->u.polyline.width > 1) + gc->meth.gc_set_linewidth(gc->priv, e->u.polyline.width); + gra->meth.draw_lines(gra->priv, gc->priv, di->pnt, di->count); + break; + case element_circle: + if (e->u.circle.width > 1) + gc->meth.gc_set_linewidth(gc->priv, e->u.polyline.width); + gra->meth.draw_circle(gra->priv, gc->priv, &di->pnt[0], e->u.circle.radius); + p.x=di->pnt[0].x+3; + p.y=di->pnt[0].y+10; + if (! gra->font[e->label_size]) + gra->font[e->label_size]=graphics_font_new(gra, e->label_size*20); + gra->meth.draw_text(gra->priv, gra->gc[2]->priv, gra->gc[1]->priv, gra->font[e->label_size]->priv, di->label, &p, 0x10000, 0); + break; + case element_label: + if (di->label) { + if (! gra->font[e->label_size]) + gra->font[e->label_size]=graphics_font_new(gra, e->label_size*20); + label_line(gra, gra->gc[2], gra->gc[1], gra->font[e->label_size], di->pnt, di->count, di->label); + } + break; + case element_icon: + if (!img) { + img=graphics_image_new(gra, e->u.icon.src); + if (! img) + g_warning("failed to load icon '%s'\n", e->u.icon.src); + } + p.x=di->pnt[0].x - img->width/2; + p.y=di->pnt[0].y - img->height/2; + gra->meth.draw_image(gra->priv, gra->gc[0]->priv, &p, img->priv); + break; + case element_image: + printf("image: '%s'\n", di->label); + gra->meth.draw_image_warp(gra->priv, gra->gc[0]->priv, di->pnt, di->count, di->label); + break; + default: + printf("Unhandled element type %d\n", e->type); + + } + l=g_list_next(l); + } + types=g_list_next(types); + } + es=g_list_next(es); + } +} + +static void +xdisplay_draw_layer(GHashTable *display_list, struct graphics *gra, struct layer *lay, int order) +{ + GList *itms; + struct itemtype *itm; + + itms=lay->itemtypes; + while (itms) { + itm=itms->data; + if (order >= itm->zoom_min && order <= itm->zoom_max) + xdisplay_draw_elements(gra, display_list, itm); + itms=g_list_next(itms); } -#ifdef DEBUG - profile_timer("map_draw"); -#endif - plugin_call_draw(co); -#ifdef DEBUG - profile_timer("plugin"); -#endif +} -#if 0 - draw_poly(map, &co->d_tunnel_ply, "Tunnel", 0, 11, plimit); -#endif - graphics_draw(co->map_data, file_street_str, co, display_street, slimit, 7, street_draw_block); - - display_draw(disp[display_sea], gra, gra->gc[GC_WATER_FILL], NULL); - display_draw(disp[display_wood], gra, gra->gc[GC_WOOD], NULL); - display_draw(disp[display_other], gra, gra->gc[GC_TOWN_FILL], gra->gc[GC_TOWN_LINE]); - display_draw(disp[display_other1], gra, gra->gc[GC_BUILDING], NULL); - display_draw(disp[display_other2], gra, gra->gc[GC_BUILDING_2], NULL); - display_draw(disp[display_other3], gra, gra->gc[GC_PARK], NULL); - display_draw(disp[display_water], gra, gra->gc[GC_WATER_FILL], gra->gc[GC_WATER_LINE]); - display_draw(disp[display_rail], gra, gra->gc[GC_RAIL], NULL); - street_route_draw(co); - display_draw(disp[display_street_route], gra, gra->gc[GC_STREET_ROUTE], NULL); - if (bw[0]) { - display_draw(disp[display_street_no_pass], gra, gra->gc[GC_STREET_SMALL_B], NULL); - display_draw(disp[display_street], gra, gra->gc[GC_STREET_SMALL_B], NULL); +static void +xdisplay_draw_layout(GHashTable *display_list, struct graphics *gra, struct layout *l, int order) +{ + GList *lays; + struct layer *lay; + + lays=l->layers; + while (lays) { + lay=lays->data; + xdisplay_draw_layer(display_list, gra, lay, order); + lays=g_list_next(lays); } - if (bw[1]) - display_draw(disp[display_street1], gra, gra->gc[GC_STREET_MID_B], NULL); - if (bw[2]) - display_draw(disp[display_street2], gra, gra->gc[GC_STREET_BIG_B], NULL); - if (bw[3]) - display_draw(disp[display_street3], gra, gra->gc[GC_STREET_BIG2_B], NULL); - if (w[0]) { - display_draw(disp[display_street_no_pass], gra, gra->gc[GC_STREET_NO_PASS], NULL); - display_draw(disp[display_street], gra, gra->gc[GC_STREET_SMALL], NULL); +} + +static void +xdisplay_draw(GHashTable *display_list, struct graphics *gra, GList *layouts, int order) +{ + struct layout *l; + + while (layouts) { + l=layouts->data; + xdisplay_draw_layout(display_list, gra, l, order); + return; + layouts=g_list_next(layouts); } - if (w[1]) - display_draw(disp[display_street1], gra, gra->gc[GC_STREET_MID], gra->gc[GC_BLACK]); - display_draw(disp[display_street2], gra, gra->gc[GC_STREET_BIG], gra->gc[GC_BLACK]); - display_draw(disp[display_street3], gra, gra->gc[GC_STREET_BIG2], gra->gc[GC_BLACK]); - if (w[3] > 1) - display_draw(disp[display_street3], gra, gra->gc[GC_STREET_BIG2_L], NULL); +} - display_draw(disp[display_poi], gra, gra->gc[GC_BLACK], NULL); +extern void *route_selection; +static void +do_draw(struct displaylist *displaylist, struct transformation *t, GList *mapsets, int order, struct route *route) +{ + struct map_selection sel; + struct map_rect *mr; + struct item *item; + struct mapset *ms; + struct map *m; + enum projection pro; + struct mapset_handle *h; + struct coord c; + int conv,count,max=16384; + struct point pnt[max]; + struct attr attr; + struct coord_rect r; -#ifdef DEBUG - profile_timer("display_draw"); -#endif - if (scale < 2) { - display_labels(disp[display_street], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[1]); - display_labels(disp[display_street1], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[1]); + sel.next=NULL; + sel.order[layer_town]=1*order; + sel.order[layer_street]=order; + sel.order[layer_poly]=1*order; + ms=mapsets->data; + h=mapset_open(ms); + while ((m=mapset_next(h, 1))) { + pro=map_projection(m); + conv=map_requires_conversion(m); + transform_rect(t, pro, &sel.rect); + if (route_selection) + mr=map_rect_new(m, route_selection); + else + mr=map_rect_new(m, &sel); + while ((item=map_rect_get_item(mr))) { + if (item->type < type_line) { + item_coord_get(item, &c, 1); + if (!transform(t, pro, &c, &pnt[0])) + continue; + count=1; + } else { + count=0; + while (count < max) { + if (!item_coord_get(item, &c, 1)) + break; + if (! count) { + r.lu=c; + r.rl=c; + } else + coord_rect_extend(&r, &c); + transform(t, pro, &c, &pnt[count]); + if (! count || pnt[count].x != pnt[count-1].x || pnt[count].y != pnt[count-1].y) + count++; + + } + g_assert(count < max); + if (!transform_contains(t, pro, &r)) + continue; + if (route && route_contains(route, item)) { + struct item ritem; + ritem=*item; + ritem.type=type_street_route; + display_add(displaylist, &ritem, count, pnt, NULL); + } + } + if (!item_attr_get(item, attr_label, &attr)) + attr.u.str=NULL; + if (conv && attr.u.str && attr.u.str[0]) { + char *str=map_convert_string(m, attr.u.str); + display_add(displaylist, item, count, pnt, str); + map_convert_free(str); + } else + display_add(displaylist, item, count, pnt, attr.u.str); + } + map_rect_destroy(mr); } - else { - display_labels(disp[display_street], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[0]); - display_labels(disp[display_street1], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[0]); + mapset_close(h); +} + +int +graphics_ready(struct graphics *this_) +{ + return this_->ready; +} + +void +graphics_displaylist_draw(struct graphics *gra, struct displaylist *displaylist, struct transformation *trans, GList *layouts, struct route *route) +{ + int order=transform_get_order(trans); + gra->meth.draw_mode(gra->priv, draw_mode_begin); + if (route) + route_draw(route, trans, displaylist); + xdisplay_draw(displaylist->dl, gra, layouts, order); +} + + +void +graphics_draw(struct graphics *gra, struct displaylist *displaylist, GList *mapsets, struct transformation *trans, GList *layouts, struct route *route) +{ + int order=transform_get_order(trans); + + dbg(1,"enter"); + +#if 0 + printf("scale=%d center=0x%x,0x%x mercator scale=%f\n", scale, co->trans->center.x, co->trans->center.y, transform_scale(co->trans->center.y)); +#endif + + xdisplay_free(displaylist->dl); + dbg(0,"order=%d\n", order); + + +#if 0 + for (i = 0 ; i < data_window_type_end; i++) { + data_window_begin(co->data_window[i]); } - display_labels(disp[display_street2], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[0]); - display_labels(disp[display_street3], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[0]); - - for (i = display_town+t[1] ; i < display_town+0x10 ; i++) - display_labels(disp[i], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[0]); - for (i = display_town+t[0] ; i < display_town+t[1] ; i++) - display_labels(disp[i], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[1]); - for (i = display_town ; i < display_town+t[0] ; i++) - display_labels(disp[i], gra, gra->gc[GC_TEXT_FG], gra->gc[GC_TEXT_BG], gra->font[2]); - - for (i = display_town ; i < display_town+0x10 ; i++) - display_draw(disp[i], gra, gra->gc[GC_BLACK], NULL); - display_draw(disp[display_bti], gra, gra->gc[GC_BLACK], NULL); -#ifdef DEBUG - profile_timer("labels"); #endif - gra->draw_mode(gra, draw_mode_end); + profile(0,NULL); + do_draw(displaylist, trans, mapsets, order, route); + profile(1,"do_draw"); + graphics_displaylist_draw(gra, displaylist, trans, layouts, route); + profile(1,"xdisplay_draw"); + profile(0,"end"); + + gra->meth.draw_mode(gra->priv, draw_mode_end); +#if 0 for (i = 0 ; i < data_window_type_end; i++) { data_window_end(co->data_window[i]); } -#if 0 - map_scrollbars_update(map); #endif + gra->ready=1; +} + + +struct displaylist_handle { + GList *hl_head,*hl,*l; +}; + + +struct displaylist_handle * +graphics_displaylist_open(struct displaylist *displaylist) +{ + struct displaylist_handle *ret; + + ret=g_new0(struct displaylist_handle, 1); + ret->hl_head=ret->hl=g_hash_to_list(displaylist->dl); + + return ret; +} + +struct displayitem * +graphics_displaylist_next(struct displaylist_handle *dlh) +{ + struct displayitem *ret; + if (! dlh->l) { + if (!dlh->hl) + return NULL; + dlh->l=dlh->hl->data; + dlh->hl=g_list_next(dlh->hl); + } + ret=dlh->l->data; + dlh->l=g_list_next(dlh->l); + return ret; } void -graphics_resize(struct container *co, int w, int h) +graphics_displaylist_close(struct displaylist_handle *dlh) +{ + g_list_free(dlh->hl_head); + g_free(dlh); +} + +struct displaylist * +graphics_displaylist_new(void) +{ + struct displaylist *ret=g_new(struct displaylist, 1); + + ret->dl=g_hash_table_new(NULL,NULL); + + return ret; +} + +struct item * +graphics_displayitem_get_item(struct displayitem *di) { - co->trans->width=w; - co->trans->height=h; - graphics_redraw(co); + return &di->item; +} + +char * +graphics_displayitem_get_label(struct displayitem *di) +{ + return di->label; +} + +static int +within_dist_point(struct point *p0, struct point *p1, int dist) +{ + if (p0->x == 32767 || p0->y == 32767 || p1->x == 32767 || p1->y == 32767) + return 0; + if (p0->x == -32768 || p0->y == -32768 || p1->x == -32768 || p1->y == -32768) + return 0; + if ((p0->x-p1->x)*(p0->x-p1->x) + (p0->y-p1->y)*(p0->y-p1->y) <= dist*dist) { + return 1; + } + return 0; +} + +static int +within_dist_line(struct point *p, struct point *line_p0, struct point *line_p1, int dist) +{ + int vx,vy,wx,wy; + int c1,c2; + struct point line_p; + + vx=line_p1->x-line_p0->x; + vy=line_p1->y-line_p0->y; + wx=p->x-line_p0->x; + wy=p->y-line_p0->y; + + c1=vx*wx+vy*wy; + if ( c1 <= 0 ) + return within_dist_point(p, line_p0, dist); + c2=vx*vx+vy*vy; + if ( c2 <= c1 ) + return within_dist_point(p, line_p1, dist); + + line_p.x=line_p0->x+vx*c1/c2; + line_p.y=line_p0->y+vy*c1/c2; + return within_dist_point(p, &line_p, dist); +} + +static int +within_dist_polyline(struct point *p, struct point *line_pnt, int count, int dist, int close) +{ + int i; + for (i = 0 ; i < count-1 ; i++) { + if (within_dist_line(p,line_pnt+i,line_pnt+i+1,dist)) { + return 1; + } + } + if (close) + return (within_dist_line(p,line_pnt,line_pnt+count-1,dist)); + return 0; +} + +static int +within_dist_polygon(struct point *p, struct point *poly_pnt, int count, int dist) +{ + int i, j, c = 0; + for (i = 0, j = count-1; i < count; j = i++) { + if ((((poly_pnt[i].y <= p->y) && ( p->y < poly_pnt[j].y )) || + ((poly_pnt[j].y <= p->y) && ( p->y < poly_pnt[i].y))) && + (p->x < (poly_pnt[j].x - poly_pnt[i].x) * (p->y - poly_pnt[i].y) / (poly_pnt[j].y - poly_pnt[i].y) + poly_pnt[i].x)) + c = !c; + } + if (! c) + return within_dist_polyline(p, poly_pnt, count, dist, 1); + return c; +} + +int +graphics_displayitem_within_dist(struct displayitem *di, struct point *p, int dist) +{ + if (di->item.type < type_line) { + return within_dist_point(p, &di->pnt[0], dist); + } + if (di->item.type < type_area) { + return within_dist_polyline(p, di->pnt, di->count, dist, 0); + } + return within_dist_polygon(p, di->pnt, di->count, dist); } diff --git a/src/graphics.h b/src/graphics.h index a73f1e1e..f5145658 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -1,50 +1,125 @@ - +#ifdef __cplusplus +extern "C" { +#endif struct point; struct container; +struct color; +struct graphics; struct graphics_gc; struct graphics_font; -struct graphics_image_gra; +struct graphics_image; +struct transformation; +struct display_list; -struct graphics_image { - struct graphics_image *next; - struct graphics *gr; - char *name; - int height; - int width; - struct graphics_image_gra *gra; +enum draw_mode_num { + draw_mode_begin, draw_mode_end, draw_mode_cursor }; -void container_init_gra(struct container *co); +struct graphics_priv; +struct graphics_font_priv; +struct graphics_image_priv; +struct graphics_gc_priv; +struct graphics_font_methods; +struct graphics_gc_methods; +struct graphics_image_methods; -void graphics_get_view(struct container *co, long *x, long *y, unsigned long *scale); -void graphics_set_view(struct container *co, long *x, long *y, unsigned long *scale); -void graphics_resize(struct container *co, int w, int h); -void graphics_redraw(struct container *co); +struct graphics_methods { + void (*graphics_destroy)(struct graphics_priv *gr); + void (*draw_mode)(struct graphics_priv *gr, enum draw_mode_num mode); + void (*draw_lines)(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count); + void (*draw_polygon)(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count); + void (*draw_rectangle)(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int w, int h); + void (*draw_circle)(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int r); + void (*draw_text)(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg, struct graphics_font_priv *font, char *text, struct point *p, int dx, int dy); + void (*draw_image)(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, struct graphics_image_priv *img); + void (*draw_image_warp)(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, int count, char *data); + void (*draw_restore)(struct graphics_priv *gr, struct point *p, int w, int h); + struct graphics_font_priv *(*font_new)(struct graphics_priv *gr, struct graphics_font_methods *meth, int size); + struct graphics_gc_priv *(*gc_new)(struct graphics_priv *gr, struct graphics_gc_methods *meth); + void (*background_gc)(struct graphics_priv *gr, struct graphics_gc_priv *gc); + struct graphics_priv *(*overlay_new)(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h); + struct graphics_image_priv *(*image_new)(struct graphics_priv *gr, struct graphics_image_methods *meth, char *path, int *w, int *h); + void *(*get_data)(struct graphics_priv *gr, char *type); + void (*register_resize_callback)(struct graphics_priv *gr, void (*callback)(void *data, int w, int h), void *data); + void (*register_button_callback)(struct graphics_priv *gr, void (*callback)(void *data, int pressed, int button, struct point *p), void *data); + void (*register_motion_callback)(struct graphics_priv *gr, void (*callback)(void *data, struct point *p), void *data); +}; -enum draw_mode_num { - draw_mode_begin, draw_mode_end, draw_mode_cursor + +struct graphics_font_methods { + void (*font_destroy)(struct graphics_font_priv *font); }; -struct graphics -{ - struct graphics_gra *gra; - struct graphics_font **font; - struct graphics_gc **gc; - - void (*draw_mode)(struct graphics *gr, enum draw_mode_num mode); - void (*draw_lines)(struct graphics *gr, struct graphics_gc *gc, struct point *p, int count); - void (*draw_polygon)(struct graphics *gr, struct graphics_gc *gc, struct point *p, int count); - void (*draw_rectangle)(struct graphics *gr, struct graphics_gc *gc, struct point *p, int w, int h); - void (*draw_circle)(struct graphics *gr, struct graphics_gc *gc, struct point *p, int r); - void (*draw_text)(struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg, struct graphics_font *font, char *text, struct point *p, int dx, int dy); - void (*draw_image)(struct graphics *gr, struct graphics_gc *fg, struct point *p, struct graphics_image *img); - void (*draw_restore)(struct graphics *gr, struct point *p, int w, int h); - - struct graphics_font *(*font_new)(struct graphics *gr, int size); - struct graphics_gc *(*gc_new)(struct graphics *gr); - void (*gc_set_linewidth)(struct graphics_gc *gc, int width); - void (*gc_set_foreground)(struct graphics_gc *gc, int r, int g, int b); - void (*gc_set_background)(struct graphics_gc *gc, int r, int g, int b); - struct graphics_image *(*image_new)(struct graphics *gr, char *path); - struct graphics *(*overlay_new)(struct graphics *gr, struct point *p, int w, int h); +struct graphics_font { + struct graphics_font_priv *priv; + struct graphics_font_methods meth; }; + +struct graphics_gc_methods { + void (*gc_destroy)(struct graphics_gc_priv *gc); + void (*gc_set_linewidth)(struct graphics_gc_priv *gc, int width); + void (*gc_set_dashes)(struct graphics_gc_priv *gc, unsigned char dash_list[], int n); + void (*gc_set_foreground)(struct graphics_gc_priv *gc, struct color *c); + void (*gc_set_background)(struct graphics_gc_priv *gc, struct color *c); +}; + +struct graphics_gc { + struct graphics_gc_priv *priv; + struct graphics_gc_methods meth; +}; + +struct graphics_image_methods { + void (*image_destroy)(struct graphics_image_priv *img); +}; + +struct graphics_image { + struct graphics_image_priv *priv; + struct graphics_image_methods meth; + int width; + int height; +}; + +/* prototypes */ +enum draw_mode_num; +struct color; +struct displayitem; +struct displaylist; +struct displaylist_handle; +struct graphics; +struct graphics_font; +struct graphics_gc; +struct graphics_image; +struct item; +struct point; +struct route; +struct transformation; +struct graphics *graphics_new(const char *type); +void graphics_init(struct graphics *this_); +void *graphics_get_data(struct graphics *this_, char *type); +void graphics_register_resize_callback(struct graphics *this_, void (*callback)(void *data, int w, int h), void *data); +void graphics_register_button_callback(struct graphics *this_, void (*callback)(void *data, int pressed, int button, struct point *p), void *data); +void graphics_register_motion_callback(struct graphics *this_, void (*callback)(void *data, struct point *p), void *data); +struct graphics_font *graphics_font_new(struct graphics *gra, int size); +struct graphics_gc *graphics_gc_new(struct graphics *gra); +void graphics_gc_set_foreground(struct graphics_gc *gc, struct color *c); +void graphics_gc_set_background(struct graphics_gc *gc, struct color *c); +void graphics_gc_set_linewidth(struct graphics_gc *gc, int width); +struct graphics_image *graphics_image_new(struct graphics *gra, char *path); +void graphics_draw_restore(struct graphics *this_, struct point *p, int w, int h); +void graphics_draw_mode(struct graphics *this_, enum draw_mode_num mode); +void graphics_draw_lines(struct graphics *this_, struct graphics_gc *gc, struct point *p, int count); +void graphics_draw_circle(struct graphics *this_, struct graphics_gc *gc, struct point *p, int r); +void display_add(struct displaylist *displaylist, struct item *item, int count, struct point *pnt, char *label); +int graphics_ready(struct graphics *this_); +void graphics_draw(struct graphics *gra, struct displaylist *displaylist, GList *mapsets, struct transformation *trans, GList *layouts, struct route *route); +struct displaylist_handle *graphics_displaylist_open(struct displaylist *displaylist); +struct displayitem *graphics_displaylist_next(struct displaylist_handle *dlh); +void graphics_displaylist_close(struct displaylist_handle *dlh); +struct displaylist *graphics_displaylist_new(void); +struct item *graphics_displayitem_get_item(struct displayitem *di); +char *graphics_displayitem_get_label(struct displayitem *di); +int graphics_displayitem_within_dist(struct displayitem *di, struct point *p, int dist); +/* end of prototypes */ +#ifdef __cplusplus +} +#endif diff --git a/src/graphics/Makefile.am b/src/graphics/Makefile.am index b5787ee6..87d68de8 100644 --- a/src/graphics/Makefile.am +++ b/src/graphics/Makefile.am @@ -1 +1,7 @@ -SUBDIRS=gtk_drawing_area +SUBDIRS=null +if GRAPHICS_GTK_DRAWING_AREA + SUBDIRS+=gtk_drawing_area +endif +if GRAPHICS_OPENGL + SUBDIRS+=opengl +endif diff --git a/src/graphics/gtk_drawing_area/Makefile.am b/src/graphics/gtk_drawing_area/Makefile.am index 376b8884..5b8b9448 100644 --- a/src/graphics/gtk_drawing_area/Makefile.am +++ b/src/graphics/gtk_drawing_area/Makefile.am @@ -1,11 +1,4 @@ -AUTOMAKE_OPTIONS = no-exeext -AM_CPPFLAGS = @PACKAGE_CFLAGS@ -I../.. - -objdir=$(prefix) -obj_PROGRAMS=gtk_drawing_area.o -INSTALL_PROGRAM=/bin/true - -gtk_drawing_area_o_SOURCES=graphics_gtk_drawing_area.c - -gtk_drawing_area.o: $(gtk_drawing_area_o_OBJECTS) - ld -r -o gtk_drawing_area.o $(gtk_drawing_area_o_OBJECTS) +include $(top_srcdir)/Makefile.inc +AM_CPPFLAGS = @GTK2_CFLAGS@ -I../.. +plugin_LTLIBRARIES = libgraphics_gtk_drawing_area.la +libgraphics_gtk_drawing_area_la_SOURCES = graphics_gtk_drawing_area.c diff --git a/src/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c b/src/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c index a1d18c31..5fe34d4e 100644 --- a/src/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c +++ b/src/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c @@ -1,16 +1,18 @@ #define GDK_ENABLE_BROKEN +#include "config.h" #include <gtk/gtk.h> #include <ft2build.h> #include FT_FREETYPE_H +#ifdef HAVE_IMLIB2 +#include <Imlib2.h> +#endif +#include <gdk/gdkx.h> #include "point.h" -#include "coord.h" -#include "transform.h" #include "graphics.h" -#include "statusbar.h" -#include "popup.h" -#include "container.h" +#include "color.h" +#include "plugin.h" -struct graphics_gra { +struct graphics_priv { GdkEventButton button_event; int button_timeout; GtkWidget *widget; @@ -23,27 +25,40 @@ struct graphics_gra { int height; int library_init; int visible; - struct graphics_gra *parent; - struct graphics_gra *overlays; - struct graphics_gra *next; + struct graphics_priv *parent; + struct graphics_priv *overlays; + struct graphics_priv *next; + struct graphics_gc_priv *background_gc; enum draw_mode_num mode; + void (*resize_callback)(void *data, int w, int h); + void *resize_callback_data; + void (*motion_callback)(void *data, struct point *p); + void *motion_callback_data; + void (*button_callback)(void *data, int press, int button, struct point *p); + void *button_callback_data; }; -struct graphics_font { +struct graphics_font_priv { FT_Face face; }; -struct graphics_gc { +struct graphics_gc_priv { GdkGC *gc; - struct graphics_gra *gra; + struct graphics_priv *gr; }; -struct graphics_image_gra { +struct graphics_image_priv { GdkPixbuf *pixbuf; + int w; + int h; }; +static void +graphics_destroy(struct graphics_priv *gr) +{ +} -char *fontlist[]={ +static char *fontlist[]={ "/usr/X11R6/lib/X11/fonts/msttcorefonts/arial.ttf", "/usr/X11R6/lib/X11/fonts/truetype/arial.ttf", "/usr/share/fonts/truetype/msttcorefonts/arial.ttf", @@ -52,20 +67,43 @@ char *fontlist[]={ NULL, }; +#if 0 +static char *fontlist_bd[]={ + "/usr/X11R6/lib/X11/fonts/msttcorefonts/arialbd.ttf", + "/usr/X11R6/lib/X11/fonts/truetype/arialbd.ttf", + "/usr/share/fonts/truetype/msttcorefonts/arialbd.ttf", + "/usr/share/fonts/ttf/arialbd.ttf", + "/usr/share/fonts/corefonts/arialbd.ttf", + NULL, +}; +#endif + + + +static void font_destroy(struct graphics_font_priv *font) +{ + g_free(font); + /* TODO: free font->face */ +} -struct graphics * graphics_gtk_drawing_area_new(struct container *co, GtkWidget **widget); +static struct graphics_font_methods font_methods = { + font_destroy +}; -static struct graphics_font *font_new(struct graphics *gr, int size) +static struct graphics_font_priv *font_new(struct graphics_priv *gr, struct graphics_font_methods *meth, int size) { char **filename=fontlist; - struct graphics_font *font=g_new(struct graphics_font, 1); - if (!gr->gra->library_init) { - FT_Init_FreeType( &gr->gra->library ); - gr->gra->library_init=1; + struct graphics_font_priv *font=g_new(struct graphics_font_priv, 1); + + *meth=font_methods; + + if (!gr->library_init) { + FT_Init_FreeType( &gr->library ); + gr->library_init=1; } while (*filename) { - if (!FT_New_Face( gr->gra->library, *filename, 0, &font->face )) + if (!FT_New_Face( gr->library, *filename, 0, &font->face )) break; filename++; } @@ -79,98 +117,121 @@ static struct graphics_font *font_new(struct graphics *gr, int size) return font; } -static struct graphics_gc *gc_new(struct graphics *gr) +static void +gc_destroy(struct graphics_gc_priv *gc) { - struct graphics_gc *gc=g_new(struct graphics_gc, 1); - - gc->gc=gdk_gc_new(gr->gra->widget->window); - gc->gra=gr->gra; - return gc; + g_object_unref(gc->gc); + g_free(gc); } static void -gc_set_linewidth(struct graphics_gc *gc, int w) +gc_set_linewidth(struct graphics_gc_priv *gc, int w) { gdk_gc_set_line_attributes(gc->gc, w, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND); } static void -gc_set_color(struct graphics_gc *gc, int r, int g, int b, int fg) -{ - GdkColor c; - c.pixel=0; - c.red=r; - c.green=g; - c.blue=b; - gdk_colormap_alloc_color(gc->gra->colormap, &c, FALSE, TRUE); +gc_set_dashes(struct graphics_gc_priv *gc, unsigned char *dash_list, int n) +{ + gdk_gc_set_dashes(gc->gc, 0, (gint8 *)dash_list, n); + gdk_gc_set_line_attributes(gc->gc, 1, GDK_LINE_ON_OFF_DASH, GDK_CAP_ROUND, GDK_JOIN_ROUND); +} + +static void +gc_set_color(struct graphics_gc_priv *gc, struct color *c, int fg) +{ + GdkColor gdkc; + gdkc.pixel=0; + gdkc.red=c->r; + gdkc.green=c->g; + gdkc.blue=c->b; + gdk_colormap_alloc_color(gc->gr->colormap, &gdkc, FALSE, TRUE); if (fg) - gdk_gc_set_foreground(gc->gc, &c); + gdk_gc_set_foreground(gc->gc, &gdkc); else - gdk_gc_set_background(gc->gc, &c); + gdk_gc_set_background(gc->gc, &gdkc); } static void -gc_set_foreground(struct graphics_gc *gc, int r, int g, int b) +gc_set_foreground(struct graphics_gc_priv *gc, struct color *c) { - gc_set_color(gc, r, g, b, 1); + gc_set_color(gc, c, 1); } static void -gc_set_background(struct graphics_gc *gc, int r, int g, int b) +gc_set_background(struct graphics_gc_priv *gc, struct color *c) { - gc_set_color(gc, r, g, b, 0); + gc_set_color(gc, c, 0); } -static struct graphics_image * -image_new(struct graphics *gr, char *name) +static struct graphics_gc_methods gc_methods = { + gc_destroy, + gc_set_linewidth, + gc_set_dashes, + gc_set_foreground, + gc_set_background +}; + +static struct graphics_gc_priv *gc_new(struct graphics_priv *gr, struct graphics_gc_methods *meth) +{ + struct graphics_gc_priv *gc=g_new(struct graphics_gc_priv, 1); + + *meth=gc_methods; + gc->gc=gdk_gc_new(gr->widget->window); + gc->gr=gr; + return gc; +} + + +static struct graphics_image_priv * +image_new(struct graphics_priv *gr, struct graphics_image_methods *meth, char *name, int *w, int *h) { GdkPixbuf *pixbuf; - struct graphics_image *ret; + struct graphics_image_priv *ret; pixbuf=gdk_pixbuf_new_from_file(name, NULL); if (! pixbuf) return NULL; - ret=g_new0(struct graphics_image, 1); - ret->gr=gr; - ret->name=strdup(name); - ret->gra=g_new0(struct graphics_image_gra, 1); - ret->gra->pixbuf=pixbuf; - ret->width=gdk_pixbuf_get_width(ret->gra->pixbuf); - ret->height=gdk_pixbuf_get_height(ret->gra->pixbuf); + ret=g_new0(struct graphics_image_priv, 1); + ret->pixbuf=pixbuf; + ret->w=gdk_pixbuf_get_width(pixbuf); + ret->h=gdk_pixbuf_get_height(pixbuf); + *w=ret->w; + *h=ret->h; return ret; } static void -draw_lines(struct graphics *gr, struct graphics_gc *gc, struct point *p, int count) +draw_lines(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count) { - if (gr->gra->mode == draw_mode_begin || gr->gra->mode == draw_mode_end) - gdk_draw_lines(gr->gra->drawable, gc->gc, (GdkPoint *)p, count); - if (gr->gra->mode == draw_mode_end || gr->gra->mode == draw_mode_cursor) - gdk_draw_lines(gr->gra->widget->window, gc->gc, (GdkPoint *)p, count); + if (gr->mode == draw_mode_begin || gr->mode == draw_mode_end) + gdk_draw_lines(gr->drawable, gc->gc, (GdkPoint *)p, count); + if (gr->mode == draw_mode_end || gr->mode == draw_mode_cursor) + gdk_draw_lines(gr->widget->window, gc->gc, (GdkPoint *)p, count); } static void -draw_polygon(struct graphics *gr, struct graphics_gc *gc, struct point *p, int count) +draw_polygon(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count) { - if (gr->gra->mode == draw_mode_begin || gr->gra->mode == draw_mode_end) - gdk_draw_polygon(gr->gra->drawable, gc->gc, TRUE, (GdkPoint *)p, count); - if (gr->gra->mode == draw_mode_end || gr->gra->mode == draw_mode_cursor) - gdk_draw_polygon(gr->gra->widget->window, gc->gc, TRUE, (GdkPoint *)p, count); + if (gr->mode == draw_mode_begin || gr->mode == draw_mode_end) + gdk_draw_polygon(gr->drawable, gc->gc, TRUE, (GdkPoint *)p, count); + if (gr->mode == draw_mode_end || gr->mode == draw_mode_cursor) + gdk_draw_polygon(gr->widget->window, gc->gc, TRUE, (GdkPoint *)p, count); } static void -draw_rectangle(struct graphics *gr, struct graphics_gc *gc, struct point *p, int w, int h) +draw_rectangle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int w, int h) { - gdk_draw_rectangle(gr->gra->drawable, gc->gc, TRUE, p->x, p->y, w, h); + gdk_draw_rectangle(gr->drawable, gc->gc, TRUE, p->x, p->y, w, h); } static void -draw_circle(struct graphics *gr, struct graphics_gc *gc, struct point *p, int r) +draw_circle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int r) { - if (gr->gra->mode == draw_mode_begin || gr->gra->mode == draw_mode_end) - gdk_draw_arc(gr->gra->drawable, gc->gc, FALSE, p->x-r/2, p->y-r/2, r, r, 0, 64*360); - if (gr->gra->mode == draw_mode_end || gr->gra->mode == draw_mode_cursor) - gdk_draw_arc(gr->gra->widget->window, gc->gc, FALSE, p->x-r/2, p->y-r/2, r, r, 0, 64*360); + if (gr->mode == draw_mode_begin || gr->mode == draw_mode_end) + gdk_draw_arc(gr->drawable, gc->gc, FALSE, p->x-r/2, p->y-r/2, r, r, 0, 64*360); + if (gr->mode == draw_mode_end || gr->mode == draw_mode_cursor) + gdk_draw_arc(gr->widget->window, gc->gc, FALSE, p->x-r/2, p->y-r/2, r, r, 0, 64*360); } @@ -234,7 +295,7 @@ display_text_render_shadow(struct text_glyph *g) } static struct text_render * -display_text_render(char *text, struct graphics_font *font, int dx, int dy, int x, int y) +display_text_render(char *text, struct graphics_font_priv *font, int dx, int dy, int x, int y) { FT_GlyphSlot slot = font->face->glyph; // a small shortcut FT_Matrix matrix; @@ -294,7 +355,7 @@ display_text_render(char *text, struct graphics_font *font, int dx, int dy, int } static void -display_text_draw(struct text_render *text, struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg) +display_text_draw(struct text_render *text, struct graphics_priv *gr, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg) { int i; struct text_glyph *g, **gp; @@ -305,7 +366,7 @@ display_text_draw(struct text_render *text, struct graphics *gr, struct graphics { g=*gp++; if (g->shadow && bg) - gdk_draw_image(gr->gra->drawable, bg->gc, g->shadow, 0, 0, g->x-1, g->y-1, g->w+2, g->h+2); + gdk_draw_image(gr->drawable, bg->gc, g->shadow, 0, 0, g->x-1, g->y-1, g->w+2, g->h+2); } gp=text->glyph; i=text->glyph_count; @@ -313,7 +374,7 @@ display_text_draw(struct text_render *text, struct graphics *gr, struct graphics { g=*gp++; if (g->w && g->h) - gdk_draw_gray_image(gr->gra->drawable, fg->gc, g->x, g->y, g->w, g->h, GDK_RGB_DITHER_NONE, g->pixmap, g->w); + gdk_draw_gray_image(gr->drawable, fg->gc, g->x, g->y, g->w, g->h, GDK_RGB_DITHER_NONE, g->pixmap, g->w); } } @@ -335,7 +396,7 @@ display_text_free(struct text_render *text) } static void -draw_text(struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg, struct graphics_font *font, char *text, struct point *p, int dx, int dy) +draw_text(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg, struct graphics_font_priv *font, char *text, struct point *p, int dx, int dy) { struct text_render *t; @@ -356,16 +417,38 @@ draw_text(struct graphics *gr, struct graphics_gc *fg, struct graphics_gc *bg, s } static void -draw_image(struct graphics *gr, struct graphics_gc *fg, struct point *p, struct graphics_image *img) +draw_image(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, struct graphics_image_priv *img) { - printf("draw_image1 \n"); - gdk_draw_pixbuf(gr->gra->drawable, fg->gc, img->gra->pixbuf, 0, 0, p->x, p->y, - img->width, img->height, GDK_RGB_DITHER_NONE, 0, 0); - printf("draw_image1 end\n"); + gdk_draw_pixbuf(gr->drawable, fg->gc, img->pixbuf, 0, 0, p->x, p->y, + img->w, img->h, GDK_RGB_DITHER_NONE, 0, 0); } +#ifdef HAVE_IMLIB2 static void -overlay_draw(struct graphics_gra *parent, struct graphics_gra *overlay, int window) +draw_image_warp(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, int count, char *data) +{ + void *image; + int w,h; + printf("draw_image_warp data=%s\n", data); + image = imlib_load_image(data); + imlib_context_set_display(gdk_x11_drawable_get_xdisplay(gr->widget->window)); + imlib_context_set_colormap(gdk_x11_colormap_get_xcolormap(gtk_widget_get_colormap(gr->widget))); + imlib_context_set_visual(gdk_x11_visual_get_xvisual(gtk_widget_get_visual(gr->widget))); + imlib_context_set_drawable(gdk_x11_drawable_get_xid(gr->drawable)); + imlib_context_set_image(image); + w = imlib_image_get_width(); + h = imlib_image_get_height(); + if (count == 3) { + imlib_render_image_on_drawable_skewed(0, 0, w, h, p[0].x, p[0].y, p[1].x-p[0].x, p[1].y-p[0].y, p[2].x-p[0].x, p[2].y-p[0].y); + } + if (count == 2) { + imlib_render_image_on_drawable_skewed(0, 0, w, h, p[0].x, p[0].y, p[1].x-p[0].x, 0, 0, p[1].y-p[0].y); + } +} +#endif + +static void +overlay_draw(struct graphics_priv *parent, struct graphics_priv *overlay, int window) { GdkPixbuf *pixbuf,*pixbuf2; GtkWidget *widget=parent->widget; @@ -413,44 +496,48 @@ overlay_draw(struct graphics_gra *parent, struct graphics_gra *overlay, int wind } static void -draw_restore(struct graphics *gr, struct point *p, int w, int h) +draw_restore(struct graphics_priv *gr, struct point *p, int w, int h) { - struct graphics_gra *gra=gr->gra; - GtkWidget *widget=gra->widget; + GtkWidget *widget=gr->widget; gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], - gra->drawable, + gr->drawable, p->x, p->y, p->x, p->y, w, h); } static void -draw_mode(struct graphics *gr, enum draw_mode_num mode) +background_gc(struct graphics_priv *gr, struct graphics_gc_priv *gc) { - struct graphics_gra *gra=gr->gra; - struct graphics_gra *overlay; - GtkWidget *widget=gra->widget; + gr->background_gc=gc; +} + +static void +draw_mode(struct graphics_priv *gr, enum draw_mode_num mode) +{ + struct graphics_priv *overlay; + GtkWidget *widget=gr->widget; if (mode == draw_mode_begin) { - if (! gra->parent) - gdk_draw_rectangle(gr->gra->drawable, gr->gc[0]->gc, TRUE, 0, 0, gr->gra->width, gr->gra->height); + if (! gr->parent && gr->background_gc) + gdk_draw_rectangle(gr->drawable, gr->background_gc->gc, TRUE, 0, 0, gr->width, gr->height); } - if (mode == draw_mode_end && gr->gra->mode == draw_mode_begin) { - if (gra->parent) { - overlay_draw(gra->parent, gra, 1); + if (mode == draw_mode_end && gr->mode == draw_mode_begin) { + if (gr->parent) { + overlay_draw(gr->parent, gr, 1); } else { - overlay=gra->overlays; + overlay=gr->overlays; while (overlay) { - overlay_draw(gra, overlay, 0); + overlay_draw(gr, overlay, 0); overlay=overlay->next; } gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], - gra->drawable, - 0, 0, 0, 0, gra->width, gra->height); + gr->drawable, + 0, 0, 0, 0, gr->width, gr->height); } } - gr->gra->mode=mode; + gr->mode=mode; } /* Events */ @@ -458,9 +545,7 @@ draw_mode(struct graphics *gr, enum draw_mode_num mode) static gint configure(GtkWidget * widget, GdkEventConfigure * event, gpointer user_data) { - struct container *co=user_data; - struct graphics_gra *gra=co->gra->gra; - + struct graphics_priv *gra=user_data; if (! gra->visible) return TRUE; if (gra->drawable != NULL) { @@ -469,31 +554,32 @@ configure(GtkWidget * widget, GdkEventConfigure * event, gpointer user_data) gra->width=widget->allocation.width; gra->height=widget->allocation.height; gra->drawable = gdk_pixmap_new(widget->window, gra->width, gra->height, -1); - graphics_resize(co, gra->width, gra->height); + if (gra->resize_callback) + (*gra->resize_callback)(gra->resize_callback_data, gra->width, gra->height); return TRUE; } static gint expose(GtkWidget * widget, GdkEventExpose * event, gpointer user_data) { - struct container *co=user_data; - struct graphics *gr=co->gra; + struct graphics_priv *gra=user_data; - gr->gra->visible=1; - if (! gr->gra->drawable) + gra->visible=1; + if (! gra->drawable) configure(widget, NULL, user_data); gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], - gr->gra->drawable, event->area.x, event->area.y, + gra->drawable, event->area.x, event->area.y, event->area.x, event->area.y, event->area.width, event->area.height); - return FALSE; } +#if 0 static gint button_timeout(gpointer user_data) { +#if 0 struct container *co=user_data; int x=co->gra->gra->button_event.x; int y=co->gra->gra->button_event.y; @@ -503,130 +589,186 @@ button_timeout(gpointer user_data) popup(co, x, y, button); return FALSE; +#endif } +#endif static gint button_press(GtkWidget * widget, GdkEventButton * event, gpointer user_data) { - struct container *co=user_data; - int x=event->x; - int y=event->y; - int button=event->button; - int border=16; - long map_x,map_y,x_new,y_new; - unsigned long scale; - - if (button == 3) - popup(co, x, y, button); - if (button == 1) { - graphics_get_view(co, &map_x, &map_y, &scale); - if (x < border) { - x_new=map_x-co->trans->width*scale/32; - graphics_set_view(co, &x_new, NULL, NULL); - } else if (x >= co->trans->width-border) { - x_new=map_x+co->trans->width*scale/32; - graphics_set_view(co, &x_new, NULL, NULL); - } else if (y < border) { - y_new=map_y+co->trans->height*scale/32; - graphics_set_view(co, NULL, &y_new, NULL); - } else if (y >= co->trans->height-border) { - y_new=map_y-co->trans->height*scale/32; - graphics_set_view(co, NULL, &y_new, NULL); - } else { - co->gra->gra->button_event=*event; - co->gra->gra->button_timeout=g_timeout_add(500, button_timeout, co); - } - } + struct graphics_priv *this=user_data; + struct point p; + + p.x=event->x; + p.y=event->y; + if (this->button_callback) + (*this->button_callback)(this->button_callback_data, 1, event->button, &p); return FALSE; } static gint button_release(GtkWidget * widget, GdkEventButton * event, gpointer user_data) { - struct container *co=user_data; - if (co->gra->gra->button_timeout) - g_source_remove(co->gra->gra->button_timeout); + struct graphics_priv *this=user_data; + struct point p; + + p.x=event->x; + p.y=event->y; + if (this->button_callback) + (*this->button_callback)(this->button_callback_data, 0, event->button, &p); + return FALSE; +} + +static gint +scroll(GtkWidget * widget, GdkEventScroll * event, gpointer user_data) +{ + struct graphics_priv *this=user_data; + struct point p; + int button; + + p.x=event->x; + p.y=event->y; + if (this->button_callback) { + switch (event->direction) { + case GDK_SCROLL_UP: + button=4; + break; + case GDK_SCROLL_DOWN: + button=5; + break; + default: + button=-1; + break; + } + if (button != -1) { + (*this->button_callback)(this->button_callback_data, 1, button, &p); + (*this->button_callback)(this->button_callback_data, 0, button, &p); + } + } return FALSE; } static gint motion_notify(GtkWidget * widget, GdkEventMotion * event, gpointer user_data) { - struct container *co=user_data; + struct graphics_priv *this=user_data; struct point p; - if (co->statusbar && co->statusbar->statusbar_mouse_update) { - p.x=event->x; - p.y=event->y; - co->statusbar->statusbar_mouse_update(co->statusbar, co->trans, &p); - } + p.x=event->x; + p.y=event->y; + if (this->motion_callback) + (*this->motion_callback)(this->motion_callback_data, &p); return FALSE; } -static struct graphics *graphics_new(void); +static struct graphics_priv *graphics_gtk_drawing_area_new_helper(struct graphics_methods *meth); -static struct graphics * -overlay_new(struct graphics *gr, struct point *p, int w, int h) +static struct graphics_priv * +overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h) { - struct graphics *this=graphics_new(); - this->gra->drawable=gdk_pixmap_new(gr->gra->widget->window, w, h, -1); - this->gra->colormap=gr->gra->colormap; - this->gra->widget=gr->gra->widget; - this->gra->p=*p; - this->gra->width=w; - this->gra->height=h; - this->gra->parent=gr->gra; - this->gra->background=gdk_pixmap_new(gr->gra->widget->window, w, h, -1); - this->gra->next=gr->gra->overlays; - gr->gra->overlays=this->gra; + struct graphics_priv *this=graphics_gtk_drawing_area_new_helper(meth); + this->drawable=gdk_pixmap_new(gr->widget->window, w, h, -1); + this->colormap=gr->colormap; + this->widget=gr->widget; + this->p=*p; + this->width=w; + this->height=h; + this->parent=gr; + this->background=gdk_pixmap_new(gr->widget->window, w, h, -1); + this->next=gr->overlays; + gr->overlays=this; return this; } +static void * +get_data(struct graphics_priv *this, char *type) +{ + if (strcmp(type,"gtk_widget")) + return NULL; + return this->widget; +} +static void +register_resize_callback(struct graphics_priv *this, void (*callback)(void *data, int w, int h), void *data) +{ + this->resize_callback=callback; + this->resize_callback_data=data; +} -static struct graphics * -graphics_new(void) +static void +register_motion_callback(struct graphics_priv *this, void (*callback)(void *data, struct point *p), void *data) { - struct graphics *this=g_new0(struct graphics,1); - this->draw_mode=draw_mode; - this->draw_lines=draw_lines; - this->draw_polygon=draw_polygon; - this->draw_rectangle=draw_rectangle; - this->draw_circle=draw_circle; - this->draw_text=draw_text; - this->draw_image=draw_image; - this->draw_restore=draw_restore; - this->gc_new=gc_new; - this->gc_set_linewidth=gc_set_linewidth; - this->gc_set_foreground=gc_set_foreground; - this->gc_set_background=gc_set_background; - this->font_new=font_new; - this->image_new=image_new; - this->overlay_new=overlay_new; - this->gra=g_new0(struct graphics_gra, 1); + this->motion_callback=callback; + this->motion_callback_data=data; +} + +static void +register_button_callback(struct graphics_priv *this, void (*callback)(void *data, int press, int button, struct point *p), void *data) +{ + this->button_callback=callback; + this->button_callback_data=data; +} + +static struct graphics_methods graphics_methods = { + graphics_destroy, + draw_mode, + draw_lines, + draw_polygon, + draw_rectangle, + draw_circle, + draw_text, + draw_image, +#ifdef HAVE_IMLIB2 + draw_image_warp, +#else + NULL, +#endif + draw_restore, + font_new, + gc_new, + background_gc, + overlay_new, + image_new, + get_data, + register_resize_callback, + register_button_callback, + register_motion_callback, +}; + +static struct graphics_priv * +graphics_gtk_drawing_area_new_helper(struct graphics_methods *meth) +{ + struct graphics_priv *this=g_new0(struct graphics_priv,1); + *meth=graphics_methods; return this; } -struct graphics * -graphics_gtk_drawing_area_new(struct container *co, GtkWidget **widget) +static struct graphics_priv * +graphics_gtk_drawing_area_new(struct graphics_methods *meth) { GtkWidget *draw; draw=gtk_drawing_area_new(); - struct graphics *this=graphics_new(); - this->gra->widget=draw; - this->gra->colormap=gdk_colormap_new(gdk_visual_get_system(),FALSE); - gtk_widget_set_events(draw, GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_POINTER_MOTION_MASK); - g_signal_connect(G_OBJECT(draw), "expose_event", G_CALLBACK(expose), co); - g_signal_connect(G_OBJECT(draw), "configure_event", G_CALLBACK(configure), co); + struct graphics_priv *this=graphics_gtk_drawing_area_new_helper(meth); + this->widget=draw; + + this->colormap=gdk_colormap_new(gdk_visual_get_system(),FALSE); + gtk_widget_set_events(draw, GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_POINTER_MOTION_MASK|GDK_KEY_PRESS_MASK); + g_signal_connect(G_OBJECT(draw), "expose_event", G_CALLBACK(expose), this); + g_signal_connect(G_OBJECT(draw), "configure_event", G_CALLBACK(configure), this); #if 0 g_signal_connect(G_OBJECT(draw), "realize_event", G_CALLBACK(realize), co); #endif - g_signal_connect(G_OBJECT(draw), "button_press_event", G_CALLBACK(button_press), co); - g_signal_connect(G_OBJECT(draw), "button_release_event", G_CALLBACK(button_release), co); - g_signal_connect(G_OBJECT(draw), "motion_notify_event", G_CALLBACK(motion_notify), co); - *widget=draw; + g_signal_connect(G_OBJECT(draw), "button_press_event", G_CALLBACK(button_press), this); + g_signal_connect(G_OBJECT(draw), "button_release_event", G_CALLBACK(button_release), this); + g_signal_connect(G_OBJECT(draw), "scroll_event", G_CALLBACK(scroll), this); + g_signal_connect(G_OBJECT(draw), "motion_notify_event", G_CALLBACK(motion_notify), this); return this; } +void +plugin_init(void) +{ + plugin_register_graphics_type("gtk_drawing_area", graphics_gtk_drawing_area_new); +} diff --git a/src/graphics/null/Makefile.am b/src/graphics/null/Makefile.am new file mode 100644 index 00000000..8b22bdbc --- /dev/null +++ b/src/graphics/null/Makefile.am @@ -0,0 +1,4 @@ +include $(top_srcdir)/Makefile.inc +AM_CPPFLAGS = @NAVIT_CFLAGS@ -I../.. +plugin_LTLIBRARIES = libgraphics_null.la +libgraphics_null_la_SOURCES = graphics_null.c diff --git a/src/graphics/null/graphics_null.c b/src/graphics/null/graphics_null.c new file mode 100644 index 00000000..2d8bb308 --- /dev/null +++ b/src/graphics/null/graphics_null.c @@ -0,0 +1,217 @@ +#include <glib.h> +#include "point.h" +#include "graphics.h" +#include "color.h" +#include "plugin.h" + +static int dummy; +static struct graphics_priv { + int dummy; +} graphics_priv; + +static struct graphics_font_priv { + int dummy; +} graphics_font_priv; + +static struct graphics_gc_priv { + int dummy; +} graphics_gc_priv; + +static struct graphics_image_priv { + int dummy; +} graphics_image_priv; + +static void +graphics_destroy(struct graphics_priv *gr) +{ +} + +static void font_destroy(struct graphics_font_priv *font) +{ + +} + +static struct graphics_font_methods font_methods = { + font_destroy +}; + +static struct graphics_font_priv *font_new(struct graphics_priv *gr, struct graphics_font_methods *meth, int size) +{ + *meth=font_methods; + return &graphics_font_priv; +} + +static void +gc_destroy(struct graphics_gc_priv *gc) +{ +} + +static void +gc_set_linewidth(struct graphics_gc_priv *gc, int w) +{ +} + +static void +gc_set_dashes(struct graphics_gc_priv *gc, unsigned char *dash_list, int n) +{ +} + +static void +gc_set_color(struct graphics_gc_priv *gc, struct color *c, int fg) +{ +} + +static void +gc_set_foreground(struct graphics_gc_priv *gc, struct color *c) +{ +} + +static void +gc_set_background(struct graphics_gc_priv *gc, struct color *c) +{ +} + +static struct graphics_gc_methods gc_methods = { + gc_destroy, + gc_set_linewidth, + gc_set_dashes, + gc_set_foreground, + gc_set_background +}; + +static struct graphics_gc_priv *gc_new(struct graphics_priv *gr, struct graphics_gc_methods *meth) +{ + *meth=gc_methods; + return &graphics_gc_priv; +} + + +static struct graphics_image_priv * +image_new(struct graphics_priv *gr, struct graphics_image_methods *meth, char *name, int *w, int *h) +{ + return &graphics_image_priv; +} + +static void +draw_lines(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count) +{ +} + +static void +draw_polygon(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count) +{ +} + +static void +draw_rectangle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int w, int h) +{ +} + +static void +draw_circle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int r) +{ +} + + +static void +draw_text(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg, struct graphics_font_priv *font, char *text, struct point *p, int dx, int dy) +{ +} + +static void +draw_image(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, struct graphics_image_priv *img) +{ +} + +static void +draw_image_warp(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, int count, char *data) +{ +} + +static void +overlay_draw(struct graphics_priv *parent, struct graphics_priv *overlay, int window) +{ +} + +static void +draw_restore(struct graphics_priv *gr, struct point *p, int w, int h) +{ +} + +static void +background_gc(struct graphics_priv *gr, struct graphics_gc_priv *gc) +{ +} + +static void +draw_mode(struct graphics_priv *gr, enum draw_mode_num mode) +{ +} + +static struct graphics_priv * overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h); + +static void * +get_data(struct graphics_priv *this, char *type) +{ + return &dummy; +} + + + +static void +register_resize_callback(struct graphics_priv *this, void (*callback)(void *data, int w, int h), void *data) +{ +} + +static void +register_motion_callback(struct graphics_priv *this, void (*callback)(void *data, struct point *p), void *data) +{ +} + +static void +register_button_callback(struct graphics_priv *this, void (*callback)(void *data, int press, int button, struct point *p), void *data) +{ +} + +static struct graphics_methods graphics_methods = { + graphics_destroy, + draw_mode, + draw_lines, + draw_polygon, + draw_rectangle, + draw_circle, + draw_text, + draw_image, + draw_image_warp, + draw_restore, + font_new, + gc_new, + background_gc, + overlay_new, + image_new, + get_data, + register_resize_callback, + register_button_callback, + register_motion_callback, +}; + +static struct graphics_priv * +overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h) +{ + *meth=graphics_methods; + return &graphics_priv; +} + + +static struct graphics_priv * +graphics_null_new(struct graphics_methods *meth) +{ + *meth=graphics_methods; + return &graphics_priv; +} + +void +plugin_init(void) +{ + plugin_register_graphics_type("null", graphics_null_new); +} diff --git a/src/graphics/opengl/Makefile.am b/src/graphics/opengl/Makefile.am new file mode 100644 index 00000000..99023e34 --- /dev/null +++ b/src/graphics/opengl/Makefile.am @@ -0,0 +1,4 @@ +include $(top_srcdir)/Makefile.inc +AM_CPPFLAGS = @NAVIT_CFLAGS@ @OPENGL_CFLAGS@ -I../.. +plugin_LTLIBRARIES = libgraphics_opengl.la +libgraphics_opengl_la_SOURCES = graphics_opengl.c diff --git a/src/graphics/opengl/graphics_opengl.c b/src/graphics/opengl/graphics_opengl.c new file mode 100644 index 00000000..81c8cd4d --- /dev/null +++ b/src/graphics/opengl/graphics_opengl.c @@ -0,0 +1,927 @@ +#include <math.h> +#include <glib.h> +#include "config.h" +#if 0 +#include <ft2build.h> +#include FT_FREETYPE_H +#endif +#include <GL/glc.h> +#include "point.h" +#include "graphics.h" +#include "color.h" +#include "plugin.h" + +struct graphics_priv { +#if 0 + GdkEventButton button_event; +#endif + int button_timeout; +#if 0 + GtkWidget *widget; + GdkDrawable *drawable; + GdkDrawable *background; + GdkColormap *colormap; + FT_Library library; +#endif + struct point p; + int width; + int height; + int library_init; + int visible; + struct graphics_priv *parent; + struct graphics_priv *overlays; + struct graphics_priv *next; + struct graphics_gc_priv *background_gc; + enum draw_mode_num mode; + void (*resize_callback)(void *data, int w, int h); + void *resize_callback_data; + void (*motion_callback)(void *data, struct point *p); + void *motion_callback_data; + void (*button_callback)(void *data, int press, int button, struct point *p); + void *button_callback_data; + GLuint DLid; +}; + +struct graphics_font_priv { +#if 0 + FT_Face face; +#endif +}; + +struct graphics_gc_priv { + struct graphics_priv *gr; + float fr,fg,fb,fa; + float br,bg,bb,ba; + int linewidth; +}; + +struct graphics_image_priv { +#if 0 + GdkPixbuf *pixbuf; +#endif + int w; + int h; +}; + +static void +graphics_destroy(struct graphics_priv *gr) +{ +} + +static char *fontlist[]={ + "/usr/X11R6/lib/X11/fonts/msttcorefonts/arial.ttf", + "/usr/X11R6/lib/X11/fonts/truetype/arial.ttf", + "/usr/share/fonts/truetype/msttcorefonts/arial.ttf", + "/usr/share/fonts/ttf/arial.ttf", + "/usr/share/fonts/corefonts/arial.ttf", + NULL, +}; + +#if 0 +static char *fontlist_bd[]={ + "/usr/X11R6/lib/X11/fonts/msttcorefonts/arialbd.ttf", + "/usr/X11R6/lib/X11/fonts/truetype/arialbd.ttf", + "/usr/share/fonts/truetype/msttcorefonts/arialbd.ttf", + "/usr/share/fonts/ttf/arialbd.ttf", + "/usr/share/fonts/corefonts/arialbd.ttf", + NULL, +}; +#endif + + + +static void font_destroy(struct graphics_font_priv *font) +{ + g_free(font); + /* TODO: free font->face */ +} + +static struct graphics_font_methods font_methods = { + font_destroy +}; + +static struct graphics_font_priv *font_new(struct graphics_priv *gr, struct graphics_font_methods *meth, int size) +{ +#if 0 + char **filename=fontlist; + struct graphics_font_priv *font=g_new(struct graphics_font_priv, 1); + + *meth=font_methods; + + if (!gr->library_init) { + FT_Init_FreeType( &gr->library ); + gr->library_init=1; + } + + while (*filename) { + if (!FT_New_Face( gr->library, *filename, 0, &font->face )) + break; + filename++; + } + if (! *filename) { + g_warning("Failed to load font, no labelling"); + g_free(font); + return NULL; + } + FT_Set_Char_Size(font->face, 0, size, 300, 300); + FT_Select_Charmap(font->face, FT_ENCODING_UNICODE); + return font; +#endif + return NULL; +} + +static void +gc_destroy(struct graphics_gc_priv *gc) +{ + g_free(gc); +} + +static void +gc_set_linewidth(struct graphics_gc_priv *gc, int w) +{ + gc->linewidth=w; +} + +static void +gc_set_dashes(struct graphics_gc_priv *gc, unsigned char *dash_list, int n) +{ +#if 0 + gdk_gc_set_dashes(gc->gc, 0, (gint8 *)dash_list, n); + gdk_gc_set_line_attributes(gc->gc, 1, GDK_LINE_ON_OFF_DASH, GDK_CAP_ROUND, GDK_JOIN_ROUND); +#endif +} + +static void +gc_set_foreground(struct graphics_gc_priv *gc, struct color *c) +{ + gc->fr=c->r/65535.0; + gc->fg=c->g/65535.0; + gc->fb=c->b/65535.0; + gc->fa=0; +} + +static void +gc_set_background(struct graphics_gc_priv *gc, struct color *c) +{ + gc->br=c->r/65535.0; + gc->bg=c->g/65535.0; + gc->bb=c->b/65535.0; + gc->ba=0; +} + +static struct graphics_gc_methods gc_methods = { + gc_destroy, + gc_set_linewidth, + gc_set_dashes, + gc_set_foreground, + gc_set_background +}; + +static struct graphics_gc_priv *gc_new(struct graphics_priv *gr, struct graphics_gc_methods *meth) +{ + struct graphics_gc_priv *gc=g_new(struct graphics_gc_priv, 1); + + *meth=gc_methods; + gc->gr=gr; + gc->linewidth=1; + return gc; +} + + +static struct graphics_image_priv * +image_new(struct graphics_priv *gr, struct graphics_image_methods *meth, char *name, int *w, int *h) +{ +#if 0 + GdkPixbuf *pixbuf; + struct graphics_image_priv *ret; + + pixbuf=gdk_pixbuf_new_from_file(name, NULL); + if (! pixbuf) + return NULL; + ret=g_new0(struct graphics_image_priv, 1); + ret->pixbuf=pixbuf; + ret->w=gdk_pixbuf_get_width(pixbuf); + ret->h=gdk_pixbuf_get_height(pixbuf); + *w=ret->w; + *h=ret->h; + return ret; +#endif + return NULL; +} + +static void +draw_lines(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count) +{ + // printf("draw_lines\n"); +// glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT); + int i; +/* + if (gr->mode == draw_mode_begin || gr->mode == draw_mode_end) + gdk_draw_lines(gr->drawable, gc->gc, (GdkPoint *)p, count); + if (gr->mode == draw_mode_end || gr->mode == draw_mode_cursor) + gdk_draw_lines(gr->widget->window, gc->gc, (GdkPoint *)p, count); +*/ + /* + if(gr->mode == draw_mode_begin){ + printf("B"); + } else if (gr->mode == draw_mode_end){ + printf("E"); + } else { + printf("x"); + } +*/ + + for (i = 0 ; i < count-1 ; i++) { + +// glEnable( GL_POLYGON_SMOOTH ); +// glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); +// glEnable( GL_BLEND ); + + float dx=p[i+1].x-p[i].x; + float dy=p[i+1].y-p[i].y; + + float cx=(p[i+1].x+p[i].x)/2; + float cy=(p[i+1].y+p[i].y)/2; +// printf("(%lx,%lx) -> (%lx,%lx) : (%lx,%lx)\n",p[i].x,p[i].y,p[i+1].x,p[i+1].y,dx,dy); + + int w=round(sqrt(pow((dx),2)+pow((dy),2))); + + float angle=atan (dy/dx) * 180 / M_PI; + + glPushMatrix(); + glTranslatef(cx,cy,1); + // glColor4f( 0,0,0,1); + // glRasterPos2f( 1,1 ); + glRotatef(angle,0.0,0.0,1.0); + + glColor4f( gc->fr, gc->fg, gc->fb, gc->fa); + + int linewidth=gc->linewidth; + + glBegin( GL_POLYGON ); + glVertex2f( -w/2,-linewidth/2 ); + glVertex2f( -w/2-4,0 ); + glVertex2f( -w/2,+linewidth/2 ); + glVertex2f( +w/2,+linewidth/2 ); + glVertex2f( +w/2+4,0 ); + glVertex2f( +w/2,-linewidth/2 ); + glVertex2f( -w/2,+linewidth/2 ); + glEnd(); + + + // FIXME Roads label can maybe be drawn here, avoid the display_label loop, when playing with Z axis position. + /* + if(attr==1){ + glcRenderStyle(GLC_TEXTURE); + glColor3f(0., 0., 0.); + glScalef(12, 12, 0.); + glcRenderString(">>"); + } else if(attr==-1){ + glcRenderStyle(GLC_TEXTURE); + glColor3f(0., 0., 0.); + glScalef(12, 12, 0.); + glcRenderString("<<"); + } + + */ + glPopMatrix(); + } +// glDisable( GL_BLEND ); +// glDisable( GL_POLYGON_SMOOTH ); + +/* + if(label){ + if((strlen(label)*6)<w){ + SDL_print(label,cx, cy,-angle); + } + } +*/ + +} + +static void +draw_polygon(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count) +{ +#if 0 + if (gr->mode == draw_mode_begin || gr->mode == draw_mode_end) + gdk_draw_polygon(gr->drawable, gc->gc, TRUE, (GdkPoint *)p, count); + if (gr->mode == draw_mode_end || gr->mode == draw_mode_cursor) + gdk_draw_polygon(gr->widget->window, gc->gc, TRUE, (GdkPoint *)p, count); +#endif + int i; + glColor4f( gc->fr, gc->fg, gc->fb, gc->fa); + glBegin( GL_POLYGON ); + for (i = 0 ; i < count ; i++) { + glVertex2i(p[i].x, p[i].y); + } + glVertex2i(p[0].x, p[0].y); + glEnd(); + +} + +static void +draw_rectangle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int w, int h) +{ +#if 0 + gdk_draw_rectangle(gr->drawable, gc->gc, TRUE, p->x, p->y, w, h); +#endif +} + +static void +draw_circle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int r) +{ +#if 0 + if (gr->mode == draw_mode_begin || gr->mode == draw_mode_end) + gdk_draw_arc(gr->drawable, gc->gc, FALSE, p->x-r/2, p->y-r/2, r, r, 0, 64*360); + if (gr->mode == draw_mode_end || gr->mode == draw_mode_cursor) + gdk_draw_arc(gr->widget->window, gc->gc, FALSE, p->x-r/2, p->y-r/2, r, r, 0, 64*360); +#endif +} + + +#if 0 +struct text_glyph { + int x,y,w,h; + GdkImage *shadow; + unsigned char pixmap[0]; +}; + +struct text_render { + int x1,y1; + int x2,y2; + int x3,y3; + int x4,y4; + int glyph_count; + struct text_glyph *glyph[0]; +}; + +static GdkImage * +display_text_render_shadow(struct text_glyph *g) +{ + int mask0, mask1, mask2, x, y, w=g->w, h=g->h; + int str=(g->w+9)/8; + unsigned char *shadow; + unsigned char *p, *pm=g->pixmap; + GdkImage *ret; + + shadow=malloc(str*(g->h+2)); /* do not use g_malloc() here */ + memset(shadow, 0, str*(g->h+2)); + for (y = 0 ; y < h ; y++) { + p=shadow+str*y; + mask0=0x4000; + mask1=0xe000; + mask2=0x4000; + for (x = 0 ; x < w ; x++) { + if (pm[x+y*w]) { + p[0]|=(mask0 >> 8); + if (mask0 & 0xff) + p[1]|=mask0; + + p[str]|=(mask1 >> 8); + if (mask1 & 0xff) + p[str+1]|=mask1; + p[str*2]|=(mask2 >> 8); + if (mask2 & 0xff) + p[str*2+1]|=mask2; + } + mask0 >>= 1; + mask1 >>= 1; + mask2 >>= 1; + if (!((mask0 >> 8) | (mask1 >> 8) | (mask2 >> 8))) { + mask0<<=8; + mask1<<=8; + mask2<<=8; + p++; + } + } + } + ret=gdk_image_new_bitmap(gdk_visual_get_system(), shadow, g->w+2, g->h+2); + return ret; +} + +static struct text_render * +display_text_render(char *text, struct graphics_font_priv *font, int dx, int dy, int x, int y) +{ + + FT_GlyphSlot slot = font->face->glyph; // a small shortcut + FT_Matrix matrix; + FT_Vector pen; + FT_UInt glyph_index; + int n,len; + struct text_render *ret; + struct text_glyph *curr; + wchar_t wtext[1024]; + + len=mbstowcs(wtext, text, 1024); + ret=g_malloc(sizeof(*ret)+len*sizeof(struct text_glyph *)); + ret->glyph_count=len; + + matrix.xx = dx; + matrix.xy = dy; + matrix.yx = -dy; + matrix.yy = dx; + + pen.x = 0 * 64; + pen.y = 0 * 64; + x <<= 6; + y <<= 6; + FT_Set_Transform( font->face, &matrix, &pen ); + + + + for ( n = 0; n < len; n++ ) + { + + glyph_index = FT_Get_Char_Index(font->face, wtext[n]); + FT_Load_Glyph(font->face, glyph_index, FT_LOAD_DEFAULT ); + FT_Render_Glyph(font->face->glyph, ft_render_mode_normal ); + + curr=g_malloc(sizeof(*curr)+slot->bitmap.rows*slot->bitmap.pitch); + ret->glyph[n]=curr; + + curr->x=(x>>6)+slot->bitmap_left; + curr->y=(y>>6)-slot->bitmap_top; + curr->w=slot->bitmap.width; + curr->h=slot->bitmap.rows; + if (slot->bitmap.width && slot->bitmap.rows) { + memcpy(curr->pixmap, slot->bitmap.buffer, slot->bitmap.rows*slot->bitmap.pitch); + curr->shadow=display_text_render_shadow(curr); + } + else + curr->shadow=NULL; +#if 0 + printf("height=%d\n", slot->metrics.height); + printf("height2=%d\n", face->height); + printf("bbox %d %d %d %d\n", face->bbox.xMin, face->bbox.yMin, face->bbox.xMax, face->bbox.yMax); +#endif + x += slot->advance.x; + y -= slot->advance.y; + } + return ret; +} + +static void +display_text_draw(struct text_render *text, struct graphics_priv *gr, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg) +{ +#if 0 + int i; + struct text_glyph *g, **gp; + + gp=text->glyph; + i=text->glyph_count; + while (i-- > 0) + { + g=*gp++; + if (g->shadow && bg) + gdk_draw_image(gr->drawable, bg->gc, g->shadow, 0, 0, g->x-1, g->y-1, g->w+2, g->h+2); + } + gp=text->glyph; + i=text->glyph_count; + while (i-- > 0) + { + g=*gp++; + if (g->w && g->h) + gdk_draw_gray_image(gr->drawable, fg->gc, g->x, g->y, g->w, g->h, GDK_RGB_DITHER_NONE, g->pixmap, g->w); + } +#endif +} + +static void +display_text_free(struct text_render *text) +{ + int i; + struct text_glyph **gp; + + gp=text->glyph; + i=text->glyph_count; + while (i-- > 0) { + if ((*gp)->shadow) { + g_object_unref((*gp)->shadow); + } + g_free(*gp++); + } + g_free(text); +} + +#endif + +void SDL_print(char * label,int x, int y, int angle){ + glPushMatrix(); +// glLoadIdentity(); + glcRenderStyle(GLC_TRIANGLE); + glColor3f(0., 0., 0.); + glTranslatef(x, y, -10); + glRotatef(180,1,0,0); + glRotatef(angle,0,0,1); + glScalef(14, 14, 0.); + glcRenderString(label); + glPopMatrix(); + +// glFlush(); + +} + +static void +draw_text(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg, struct graphics_font_priv *font, char *text, struct point *p, int dx, int dy) +{ + printf("******************************************* %s\n",text); + SDL_print(text,p->x,p->y,0); + +#if 0 + struct text_render *t; + + if (! font) + return; + if (bg) { + gdk_gc_set_function(fg->gc, GDK_AND_INVERT); + gdk_gc_set_function(bg->gc, GDK_OR); + } + + t=display_text_render(text, font, dx, dy, p->x, p->y); + display_text_draw(t, gr, fg, bg); + display_text_free(t); + if (bg) { + gdk_gc_set_function(fg->gc, GDK_COPY); + gdk_gc_set_function(bg->gc, GDK_COPY); + } +#endif +} + +static void +draw_image(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, struct graphics_image_priv *img) +{ +#if 0 + gdk_draw_pixbuf(gr->drawable, fg->gc, img->pixbuf, 0, 0, p->x, p->y, + img->w, img->h, GDK_RGB_DITHER_NONE, 0, 0); +#endif +} + +#ifdef HAVE_IMLIB2 +static void +draw_image_warp(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, int count, char *data) +{ +#if 0 + void *image; + int w,h; + printf("draw_image_warp data=%s\n", data); + image = imlib_load_image(data); + imlib_context_set_display(gdk_x11_drawable_get_xdisplay(gr->widget->window)); + imlib_context_set_colormap(gdk_x11_colormap_get_xcolormap(gtk_widget_get_colormap(gr->widget))); + imlib_context_set_visual(gdk_x11_visual_get_xvisual(gtk_widget_get_visual(gr->widget))); + imlib_context_set_drawable(gdk_x11_drawable_get_xid(gr->drawable)); + imlib_context_set_image(image); + w = imlib_image_get_width(); + h = imlib_image_get_height(); + if (count == 3) { + imlib_render_image_on_drawable_skewed(0, 0, w, h, p[0].x, p[0].y, p[1].x-p[0].x, p[1].y-p[0].y, p[2].x-p[0].x, p[2].y-p[0].y); + } + if (count == 2) { + imlib_render_image_on_drawable_skewed(0, 0, w, h, p[0].x, p[0].y, p[1].x-p[0].x, 0, 0, p[1].y-p[0].y); + } +#endif +} +#endif + +static void +overlay_draw(struct graphics_priv *parent, struct graphics_priv *overlay, int window) +{ +#if 0 + GdkPixbuf *pixbuf,*pixbuf2; + GtkWidget *widget=parent->widget; + guchar *pixels1, *pixels2, *p1, *p2; + int x,y; + int rowstride1,rowstride2; + int n_channels1,n_channels2; + + if (! parent->drawable) + return; + + pixbuf=gdk_pixbuf_get_from_drawable(NULL, overlay->drawable, NULL, 0, 0, 0, 0, overlay->width, overlay->height); + pixbuf2=gdk_pixbuf_new(gdk_pixbuf_get_colorspace(pixbuf), TRUE, gdk_pixbuf_get_bits_per_sample(pixbuf), + gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf)); + + rowstride1 = gdk_pixbuf_get_rowstride (pixbuf); + rowstride2 = gdk_pixbuf_get_rowstride (pixbuf2); + pixels1=gdk_pixbuf_get_pixels (pixbuf); + pixels2=gdk_pixbuf_get_pixels (pixbuf2); + n_channels1 = gdk_pixbuf_get_n_channels (pixbuf); + n_channels2 = gdk_pixbuf_get_n_channels (pixbuf2); + for (y = 0 ; y < overlay->height ; y++) { + for (x = 0 ; x < overlay->width ; x++) { + p1 = pixels1 + y * rowstride1 + x * n_channels1; + p2 = pixels2 + y * rowstride2 + x * n_channels2; + p2[0]=p1[0]; + p2[1]=p1[1]; + p2[2]=p1[2]; + p2[3]=127; + } + } + if (window) + gdk_draw_pixmap(parent->drawable, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], overlay->background, 0, 0, overlay->p.x, overlay->p.y, overlay->width, overlay->height); + else + gdk_draw_pixmap(overlay->background, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], parent->drawable, overlay->p.x, overlay->p.y, 0, 0, overlay->width, overlay->height); + gdk_draw_pixbuf(parent->drawable, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], pixbuf2, 0, 0, overlay->p.x, overlay->p.y, overlay->width, overlay->height, GDK_RGB_DITHER_NONE, 0, 0); + if (window) + gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], parent->drawable, overlay->p.x, overlay->p.y, overlay->p.x, overlay->p.y, overlay->width, overlay->height); +#if 0 + gdk_draw_pixmap(gr->gra->drawable, + gr->gra->widget->style->fg_gc[GTK_WIDGET_STATE(gr->gra->widget)], + img->gra->drawable, + 0, 0, p->x, p->y, img->gra->width, img->gra->height); +#endif +#endif +} + +static void +draw_restore(struct graphics_priv *gr, struct point *p, int w, int h) +{ +#if 0 + GtkWidget *widget=gr->widget; + gdk_draw_pixmap(widget->window, + widget->style->fg_gc[GTK_WIDGET_STATE(widget)], + gr->drawable, + p->x, p->y, p->x, p->y, w, h); +#endif + +} + +static void +background_gc(struct graphics_priv *gr, struct graphics_gc_priv *gc) +{ + gr->background_gc=gc; +} + +static void +draw_mode(struct graphics_priv *gr, enum draw_mode_num mode) +{ +#if 0 + if (mode == draw_mode_begin) + glNewList(gr->DLid,GL_COMPILE); + if (mode == draw_mode_end) + glEndList(); +#endif + +#if 0 + struct graphics_priv *overlay; + GtkWidget *widget=gr->widget; + + if (mode == draw_mode_begin) { + if (! gr->parent && gr->background_gc) + gdk_draw_rectangle(gr->drawable, gr->background_gc->gc, TRUE, 0, 0, gr->width, gr->height); + } + if (mode == draw_mode_end && gr->mode == draw_mode_begin) { + if (gr->parent) { + overlay_draw(gr->parent, gr, 1); + } else { + overlay=gr->overlays; + while (overlay) { + overlay_draw(gr, overlay, 0); + overlay=overlay->next; + } + gdk_draw_pixmap(widget->window, + widget->style->fg_gc[GTK_WIDGET_STATE(widget)], + gr->drawable, + 0, 0, 0, 0, gr->width, gr->height); + } + } + gr->mode=mode; +#endif +} + +#if 0 +/* Events */ + +static gint +configure(GtkWidget * widget, GdkEventConfigure * event, gpointer user_data) +{ + struct graphics_priv *gra=user_data; + if (! gra->visible) + return TRUE; + if (gra->drawable != NULL) { + gdk_pixmap_unref(gra->drawable); + } + gra->width=widget->allocation.width; + gra->height=widget->allocation.height; + gra->drawable = gdk_pixmap_new(widget->window, gra->width, gra->height, -1); + if (gra->resize_callback) + (*gra->resize_callback)(gra->resize_callback_data, gra->width, gra->height); + return TRUE; +} + +static gint +expose(GtkWidget * widget, GdkEventExpose * event, gpointer user_data) +{ + struct graphics_priv *gra=user_data; + + gra->visible=1; + if (! gra->drawable) + configure(widget, NULL, user_data); + gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], + gra->drawable, event->area.x, event->area.y, + event->area.x, event->area.y, + event->area.width, event->area.height); + + return FALSE; +} + +#if 0 +static gint +button_timeout(gpointer user_data) +{ +#if 0 + struct container *co=user_data; + int x=co->gra->gra->button_event.x; + int y=co->gra->gra->button_event.y; + int button=co->gra->gra->button_event.button; + + co->gra->gra->button_timeout=0; + popup(co, x, y, button); + + return FALSE; +#endif +} +#endif + +static gint +button_press(GtkWidget * widget, GdkEventButton * event, gpointer user_data) +{ + struct graphics_priv *this=user_data; + struct point p; + + p.x=event->x; + p.y=event->y; + if (this->button_callback) + (*this->button_callback)(this->button_callback_data, 1, event->button, &p); + return FALSE; +} + +static gint +button_release(GtkWidget * widget, GdkEventButton * event, gpointer user_data) +{ + struct graphics_priv *this=user_data; + struct point p; + + p.x=event->x; + p.y=event->y; + if (this->button_callback) + (*this->button_callback)(this->button_callback_data, 0, event->button, &p); + return FALSE; +} + +static gint +scroll(GtkWidget * widget, GdkEventScroll * event, gpointer user_data) +{ + struct graphics_priv *this=user_data; + struct point p; + int button; + + p.x=event->x; + p.y=event->y; + if (this->button_callback) { + switch (event->direction) { + case GDK_SCROLL_UP: + button=4; + break; + case GDK_SCROLL_DOWN: + button=5; + break; + default: + button=-1; + break; + } + if (button != -1) { + (*this->button_callback)(this->button_callback_data, 1, button, &p); + (*this->button_callback)(this->button_callback_data, 0, button, &p); + } + } + return FALSE; +} + +static gint +motion_notify(GtkWidget * widget, GdkEventMotion * event, gpointer user_data) +{ + struct graphics_priv *this=user_data; + struct point p; + + p.x=event->x; + p.y=event->y; + if (this->motion_callback) + (*this->motion_callback)(this->motion_callback_data, &p); + return FALSE; +} + +#endif + + +static struct graphics_priv * +overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h) +{ +#if 0 + struct graphics_priv *this=graphics_gtk_drawing_area_new_helper(meth); + this->drawable=gdk_pixmap_new(gr->widget->window, w, h, -1); + this->colormap=gr->colormap; + this->widget=gr->widget; + this->p=*p; + this->width=w; + this->height=h; + this->parent=gr; + this->background=gdk_pixmap_new(gr->widget->window, w, h, -1); + this->next=gr->overlays; + gr->overlays=this; + return this; +#endif + return NULL; +} + +static void * +get_data(struct graphics_priv *this, char *type) +{ + if (strcmp(type,"opengl_displaylist")) + return NULL; + return &this->DLid; +} + +static void +register_resize_callback(struct graphics_priv *this, void (*callback)(void *data, int w, int h), void *data) +{ + this->resize_callback=callback; + this->resize_callback_data=data; +} + +static void +register_motion_callback(struct graphics_priv *this, void (*callback)(void *data, struct point *p), void *data) +{ + this->motion_callback=callback; + this->motion_callback_data=data; +} + +static void +register_button_callback(struct graphics_priv *this, void (*callback)(void *data, int press, int button, struct point *p), void *data) +{ + this->button_callback=callback; + this->button_callback_data=data; +} + +static struct graphics_methods graphics_methods = { + graphics_destroy, + draw_mode, + draw_lines, + draw_polygon, + draw_rectangle, + draw_circle, + draw_text, + draw_image, +#ifdef HAVE_IMLIB2 + draw_image_warp, +#else + NULL, +#endif + draw_restore, + font_new, + gc_new, + background_gc, + overlay_new, + image_new, + get_data, + register_resize_callback, + register_button_callback, + register_motion_callback, +}; + +static struct graphics_priv * +graphics_opengl_new(struct graphics_methods *meth) +{ + struct graphics_priv *this=g_new0(struct graphics_priv,1); + *meth=graphics_methods; + +// GtkWidget *draw; + +// draw=gtk_drawnig_area_new(); + + printf("Creating the DL from driver\n"); + this->DLid = glGenLists(1); + + +/* + this->widget=draw; + + this->colormap=gdk_colormap_new(gdk_visual_get_system(),FALSE); + gtk_widget_set_events(draw, GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_POINTER_MOTION_MASK|GDK_KEY_PRESS_MASK); + g_signal_connect(G_OBJECT(draw), "expose_event", G_CALLBACK(expose), this); + g_signal_connect(G_OBJECT(draw), "configure_event", G_CALLBACK(configure), this); +#if 0 + g_signal_connect(G_OBJECT(draw), "realize_event", G_CALLBACK(realize), co); +#endif + g_signal_connect(G_OBJECT(draw), "button_press_event", G_CALLBACK(button_press), this); + g_signal_connect(G_OBJECT(draw), "button_release_event", G_CALLBACK(button_release), this); + g_signal_connect(G_OBJECT(draw), "scroll_event", G_CALLBACK(scroll), this); + g_signal_connect(G_OBJECT(draw), "motion_notify_event", G_CALLBACK(motion_notify), this); + */ + return this; +} + +void +plugin_init(void) +{ + plugin_register_graphics_type("opengl", graphics_opengl_new); +} diff --git a/src/gui.c b/src/gui.c new file mode 100644 index 00000000..f47856ee --- /dev/null +++ b/src/gui.c @@ -0,0 +1,106 @@ +#include <glib.h> +#include "gui.h" +#include "statusbar.h" +#include "menu.h" +#include "plugin.h" + +struct gui * +gui_new(struct navit *nav, const char *type, int w, int h) +{ + struct gui *this_; + struct gui_priv *(*guitype_new)(struct navit *nav, struct gui_methods *meth, int w, int h); + + guitype_new=plugin_get_gui_type(type); + if (! guitype_new) + return NULL; + + this_=g_new0(struct gui, 1); + this_->priv=guitype_new(nav, &this_->meth, w, h); + return this_; +} + +struct statusbar * +gui_statusbar_new(struct gui *gui) +{ + struct statusbar *this_; + if (! gui->meth.statusbar_new) + return NULL; + this_=g_new0(struct statusbar, 1); + this_->priv=gui->meth.statusbar_new(gui->priv, &this_->meth); + if (! this_->priv) { + g_free(this_); + return NULL; + } + return this_; +} + +struct menu * +gui_menubar_new(struct gui *gui) +{ + struct menu *this_; + if (! gui->meth.menubar_new) + return NULL; + this_=g_new0(struct menu, 1); + this_->priv=gui->meth.menubar_new(gui->priv, &this_->meth); + if (! this_->priv) { + g_free(this_); + return NULL; + } + return this_; +} + + +struct menu * +gui_toolbar_new(struct gui *gui) +{ + struct menu *this_; + if (! gui->meth.toolbar_new) + return NULL; + this_=g_new0(struct menu, 1); + this_->priv=gui->meth.toolbar_new(gui->priv, &this_->meth); + if (! this_->priv) { + g_free(this_); + return NULL; + } + return this_; +} + +struct menu * +gui_popup_new(struct gui *gui) +{ + struct menu *this_; + if (! gui->meth.popup_new) + return NULL; + this_=g_new0(struct menu, 1); + this_->priv=gui->meth.popup_new(gui->priv, &this_->meth); + if (! this_->priv) { + g_free(this_); + return NULL; + } + return this_; +} + +int +gui_set_graphics(struct gui *this_, struct graphics *gra) +{ + if (! this_->meth.set_graphics) + return 1; + return this_->meth.set_graphics(this_->priv, gra); +} + +int +gui_has_main_loop(struct gui *this_) +{ + if (! this_->meth.run_main_loop) + return 0; + return 1; +} + +int +gui_run_main_loop(struct gui *this_) +{ + if (! gui_has_main_loop(this_)) + return 1; + return this_->meth.run_main_loop(this_->priv); +} + diff --git a/src/gui.h b/src/gui.h new file mode 100644 index 00000000..11316908 --- /dev/null +++ b/src/gui.h @@ -0,0 +1,36 @@ +struct navit; +struct gui_priv; +struct menu_methods; +struct statusbar_methods; +struct graphics; + +struct gui_methods { + struct menu_priv *(*menubar_new)(struct gui_priv *priv, struct menu_methods *meth); + struct menu_priv *(*toolbar_new)(struct gui_priv *priv, struct menu_methods *meth); + struct statusbar_priv *(*statusbar_new)(struct gui_priv *priv, struct statusbar_methods *meth); + struct menu_priv *(*popup_new)(struct gui_priv *priv, struct menu_methods *meth); + int (*set_graphics)(struct gui_priv *priv, struct graphics *gra); + int (*run_main_loop)(struct gui_priv *priv); +}; + + +struct gui { + struct gui_methods meth; + struct gui_priv *priv; +}; + +/* prototypes */ +struct graphics; +struct gui; +struct menu; +struct navit; +struct statusbar; +struct gui *gui_new(struct navit *nav, const char *type, int w, int h); +struct statusbar *gui_statusbar_new(struct gui *gui); +struct menu *gui_menubar_new(struct gui *gui); +struct menu *gui_toolbar_new(struct gui *gui); +struct menu *gui_popup_new(struct gui *gui); +int gui_set_graphics(struct gui *this_, struct graphics *gra); +int gui_has_main_loop(struct gui *this_); +int gui_run_main_loop(struct gui *this_); +/* end of prototypes */ diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index 126d10a6..e0e3a225 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -1 +1,8 @@ -SUBDIRS=gtk +SUBDIRS= +if GUI_GTK + SUBDIRS += gtk +endif +if GUI_SDL + SUBDIRS += sdl +endif + diff --git a/src/gui/gtk/Makefile.am b/src/gui/gtk/Makefile.am index d5ffe2f7..9b8d907f 100644 --- a/src/gui/gtk/Makefile.am +++ b/src/gui/gtk/Makefile.am @@ -1,11 +1,4 @@ -AUTOMAKE_OPTIONS = no-exeext -AM_CPPFLAGS = @PACKAGE_CFLAGS@ -I../.. - -objdir=$(prefix) -obj_PROGRAMS=gtk.o -INSTALL_PROGRAM=/bin/true - -gtk_o_SOURCES=gtkeyboard.c gui_gtk_statusbar.c gui_gtk_action.c gui_gtk_window.c - -gtk.o: $(gtk_o_OBJECTS) - ld -r -o gtk.o $(gtk_o_OBJECTS) +include $(top_srcdir)/Makefile.inc +AM_CPPFLAGS = @NAVIT_CFLAGS@ @GTK2_CFLAGS@ -I../.. -DMODULE=\"gui_gtk\" +plugin_LTLIBRARIES = libgui_gtk.la +libgui_gtk_la_SOURCES = destination.c gui_gtk_statusbar.c gui_gtk_action.c gui_gtk_window.c gui_gtk.h diff --git a/src/gui/gtk/destination.c b/src/gui/gtk/destination.c new file mode 100644 index 00000000..5ef6e7f5 --- /dev/null +++ b/src/gui/gtk/destination.c @@ -0,0 +1,369 @@ +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <gtk/gtk.h> +#include "debug.h" +#include "destination.h" +#include "navit.h" +#include "attr.h" +#include "coord.h" +#include "item.h" +#include "search.h" + +#define COL_COUNT 8 + +static struct search_param { + struct navit *nav; + struct mapset *ms; + struct search_list *sl; + struct attr attr; + GtkWidget *entry_country, *entry_postal, *entry_city, *entry_district; + GtkWidget *entry_street, *entry_number; + GtkWidget *listbox; + GtkWidget *treeview; + GtkListStore *liststore; + GtkTreeModel *liststore2; +} search_param; + +static void button_map(GtkWidget *widget, struct search_param *search) +{ + struct coord *c=NULL; + GtkTreeIter iter; + gtk_tree_model_get_iter_first (GTK_TREE_MODEL (search->liststore2), &iter); + gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), &iter, COL_COUNT, &c, -1); + if (c) + navit_set_center(search->nav, c); +} + +static void button_destination(GtkWidget *widget, struct search_param *search) +{ + struct coord *c=NULL; + GtkTreeIter iter; + char *desc,*car,*postal,*town,*street; + gtk_tree_model_get_iter_first (GTK_TREE_MODEL (search->liststore2), &iter); + gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), &iter, COL_COUNT, &c, -1); + if (c) { + gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), &iter, 0, &car, -1); + gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), &iter, 1, &postal, -1); + gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), &iter, 2, &town, -1); + gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), &iter, 4, &street, -1); + if (search->attr.type == attr_town_name) + desc=g_strdup_printf("%s-%s %s", car, postal, town); + else + desc=g_strdup_printf("%s-%s %s, %s", car, postal, town, street); + navit_set_destination(search->nav, c, desc); + g_free(desc); + } +} + + +char **columns_text[] = { + (char *[]){"Car","Iso2","Iso3","Country",NULL}, + (char *[]){"Car","Postal","Town","District",NULL}, + (char *[]){"Car","Postal","Town","District","Street",NULL}, + (char *[]){"Car","Postal","Town","District","Street","Number",NULL}, +}; + +static void set_columns(struct search_param *param, int mode) +{ + GList *columns_list,*columns; + char **column_text=columns_text[mode]; + int i=0; + + columns_list=gtk_tree_view_get_columns(GTK_TREE_VIEW(param->treeview)); + columns=columns_list; + while (columns) { + gtk_tree_view_remove_column(GTK_TREE_VIEW(param->treeview), columns->data); + columns=g_list_next(columns); + } + g_list_free(columns_list); + while (*column_text) { + printf("column_text=%p\n", column_text); + printf("*column_text=%s\n", *column_text); + GtkCellRenderer *cell=gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (param->treeview),-1, *column_text, cell, "text", i, NULL); + i++; + column_text++; + } + +} + +static void changed(GtkWidget *widget, struct search_param *search) +{ + struct search_list_result *res; + GtkTreeIter iter; + + search->attr.u.str=(char *)gtk_entry_get_text(GTK_ENTRY(widget)); + printf("changed %s\n", search->attr.u.str); + if (widget == search->entry_country) { + dbg(0,"country\n"); + search->attr.type=attr_country_all; + set_columns(search, 0); + } + if (widget == search->entry_city) { + dbg(0,"town\n"); + search->attr.type=attr_town_name; + if (strlen(search->attr.u.str) < 2) + return; + set_columns(search, 1); + } + if (widget == search->entry_street) { + dbg(0,"street\n"); + search->attr.type=attr_street_name; + set_columns(search, 2); + } + + + search_list_search(search->sl, &search->attr, 1); + gtk_list_store_clear(search->liststore); + while((res=search_list_get_result(search->sl))) { + gtk_list_store_append(search->liststore,&iter); + gtk_list_store_set(search->liststore,&iter,COL_COUNT,res->c,-1); + if (widget == search->entry_country) { + if (res->country) { + gtk_list_store_set(search->liststore,&iter,0,res->country->car,-1); + gtk_list_store_set(search->liststore,&iter,1,res->country->iso3,-1); + gtk_list_store_set(search->liststore,&iter,2,res->country->iso2,-1); + gtk_list_store_set(search->liststore,&iter,3,res->country->name,-1); + } + } else { + if (res->country) + gtk_list_store_set(search->liststore,&iter,0,res->country->car,-1); + else + gtk_list_store_set(search->liststore,&iter,0,"",-1); + if (res->town) { + gtk_list_store_set(search->liststore,&iter,1,res->town->postal,-1); + gtk_list_store_set(search->liststore,&iter,2,res->town->name,-1); + gtk_list_store_set(search->liststore,&iter,3,"",-1); + } else { + gtk_list_store_set(search->liststore,&iter,1,"",-1); + gtk_list_store_set(search->liststore,&iter,2,"",-1); + gtk_list_store_set(search->liststore,&iter,3,"",-1); + } + if (res->street) + gtk_list_store_set(search->liststore,&iter,4,res->street->name,-1); + else + gtk_list_store_set(search->liststore,&iter,4,"",-1); + + } + } +} + +/* borrowed from gpe-login */ + + +#define MAX_ARGS 8 + +static void +parse_xkbd_args (const char *cmd, char **argv) +{ + const char *p = cmd; + char buf[strlen (cmd) + 1], *bufp = buf; + int nargs = 0; + int escape = 0, squote = 0, dquote = 0; + + while (*p) + { + if (escape) + { + *bufp++ = *p; + escape = 0; + } + else + { + switch (*p) + { + case '\\': + escape = 1; + break; + case '"': + if (squote) + *bufp++ = *p; + else + dquote = !dquote; + break; + case '\'': + if (dquote) + *bufp++ = *p; + else + squote = !squote; + break; + case ' ': + if (!squote && !dquote) + { + *bufp = 0; + if (nargs < MAX_ARGS) + argv[nargs++] = strdup (buf); + bufp = buf; + break; + } + default: + *bufp++ = *p; + break; + } + } + p++; + } + + if (bufp != buf) + { + *bufp = 0; + if (nargs < MAX_ARGS) + argv[nargs++] = strdup (buf); + } + argv[nargs] = NULL; +} + +int kbd_pid; + +static int +spawn_xkbd (char *xkbd_path, char *xkbd_str) +{ + char *xkbd_args[MAX_ARGS + 1]; + int fd[2]; + char buf[256]; + char c; + int a = 0; + size_t n; + + pipe (fd); + kbd_pid = fork (); + if (kbd_pid == 0) + { + close (fd[0]); + if (dup2 (fd[1], 1) < 0) + perror ("dup2"); + close (fd[1]); + if (fcntl (1, F_SETFD, 0)) + perror ("fcntl"); + xkbd_args[0] = (char *)xkbd_path; + xkbd_args[1] = "-xid"; + if (xkbd_str) + parse_xkbd_args (xkbd_str, xkbd_args + 2); + else + xkbd_args[2] = NULL; + execvp (xkbd_path, xkbd_args); + perror (xkbd_path); + _exit (1); + } + close (fd[1]); + do { + n = read (fd[0], &c, 1); + if (n) + { + buf[a++] = c; + } + } while (n && (c != 10) && (a < (sizeof (buf) - 1))); + + if (a) + { + buf[a] = 0; + return atoi (buf); + } + return 0; +} + +int destination_address(struct navit *nav) +{ + + GtkWidget *window2, *keyboard, *vbox, *table; + GtkWidget *label_country; + GtkWidget *label_postal, *label_city, *label_district; + GtkWidget *label_street, *label_number; + GtkWidget *hseparator1,*hseparator2; + GtkWidget *button1,*button2; + int i; + struct search_param *search=&search_param; + + + search->nav=nav; + search->ms=navit_get_mapset(nav); + search->sl=search_list_new(search->ms); + + window2 = gtk_window_new(GTK_WINDOW_TOPLEVEL); + vbox = gtk_vbox_new(FALSE, 0); + table = gtk_table_new(3, 8, FALSE); + + search->entry_country = gtk_entry_new(); + label_country = gtk_label_new("Land"); + search->entry_postal = gtk_entry_new(); + label_postal = gtk_label_new("PLZ"); + search->entry_city = gtk_entry_new(); + label_city = gtk_label_new("Ort"); + search->entry_district = gtk_entry_new(); + label_district = gtk_label_new("Ortsteil/Gemeinde"); + hseparator1 = gtk_vseparator_new(); + search->entry_street = gtk_entry_new(); + label_street = gtk_label_new("Strasse"); + search->entry_number = gtk_entry_new(); + label_number = gtk_label_new("Nummer"); + search->treeview=gtk_tree_view_new(); + search->listbox = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (search->listbox), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + + gtk_tree_view_set_model (GTK_TREE_VIEW (search->treeview), NULL); + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(search->listbox),search->treeview); + { + GType types[COL_COUNT+1]; + for(i=0;i<COL_COUNT;i++) + types[i]=G_TYPE_STRING; + types[i]=G_TYPE_POINTER; + search->liststore=gtk_list_store_newv(COL_COUNT+1,types); + search->liststore2=gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(search->liststore)); + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (search->liststore2), 0, GTK_SORT_ASCENDING); + gtk_tree_view_set_model (GTK_TREE_VIEW (search->treeview), GTK_TREE_MODEL(search->liststore2)); + } + + + + + hseparator2 = gtk_vseparator_new(); + button1 = gtk_button_new_with_label("Karte"); + button2 = gtk_button_new_with_label("Ziel"); + + gtk_table_attach(GTK_TABLE(table), label_country, 0, 1, 0, 1, 0, GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), label_postal, 1, 2, 0, 1, 0, GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), label_city, 2, 3, 0, 1, 0, GTK_FILL, 0, 0); + + gtk_table_attach(GTK_TABLE(table), search->entry_country, 0, 1, 1, 2, 0, GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), search->entry_postal, 1, 2, 1, 2, 0, GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), search->entry_city, 2, 3, 1, 2, 0, GTK_FILL, 0, 0); + + gtk_table_attach(GTK_TABLE(table), label_district, 0, 1, 2, 3, 0, GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), label_street, 1, 2, 2, 3, 0, GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), label_number, 2, 3, 2, 3, 0, GTK_FILL, 0, 0); + + gtk_table_attach(GTK_TABLE(table), search->entry_district, 0, 1, 3, 4, 0, GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), search->entry_street, 1, 2, 3, 4, 0, GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), search->entry_number, 2, 3, 3, 4, 0, GTK_FILL, 0, 0); + + gtk_table_attach(GTK_TABLE(table), search->listbox, 0, 3, 4, 5, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0); + + gtk_table_attach(GTK_TABLE(table), button1, 0, 1, 5, 6, GTK_FILL, GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(table), button2, 2, 3, 5, 6, GTK_FILL, GTK_FILL, 0, 0); + + g_signal_connect(G_OBJECT(search->entry_country), "changed", G_CALLBACK(changed), search); + g_signal_connect(G_OBJECT(search->entry_postal), "changed", G_CALLBACK(changed), search); + g_signal_connect(G_OBJECT(search->entry_city), "changed", G_CALLBACK(changed), search); + g_signal_connect(G_OBJECT(search->entry_district), "changed", G_CALLBACK(changed), search); + g_signal_connect(G_OBJECT(search->entry_street), "changed", G_CALLBACK(changed), search); + g_signal_connect(G_OBJECT(search->entry_number), "changed", G_CALLBACK(changed), search); + g_signal_connect(G_OBJECT(button1), "clicked", G_CALLBACK(button_map), search); + g_signal_connect(G_OBJECT(button2), "clicked", G_CALLBACK(button_destination), search); + + gtk_widget_grab_focus(search->entry_city); + + gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0); + keyboard=gtk_socket_new(); + gtk_box_pack_end(GTK_BOX(vbox), keyboard, FALSE, FALSE, 0); + gtk_container_add(GTK_CONTAINER(window2), vbox); +#if 0 + g_signal_connect(G_OBJECT(listbox), "select-row", G_CALLBACK(select_row), NULL); +#endif + gtk_widget_show_all(window2); + gtk_socket_steal(GTK_SOCKET(keyboard), spawn_xkbd("xkbd","-geometry 200x100")); + + return 0; +} diff --git a/src/gui/gtk/gtkeyboard.c b/src/gui/gtk/gtkeyboard.c deleted file mode 100644 index 58f929b8..00000000 --- a/src/gui/gtk/gtkeyboard.c +++ /dev/null @@ -1,2350 +0,0 @@ -/* app.c - * For use with GTKeyboard - * written by David Allen, s2mdalle@titan.vcu.edu - * http://opop.nols.com/ - * - * #define DEBUGGING at compile time for interesting info most people don't - * want to see. - */ -/* GTKeyboard - A Graphical Keyboard For X - * Copyright (C) 1999, 2000 David Allen - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <glib.h> -#include <gtk/gtk.h> -#include <gdk/gdk.h> -#include <gdk/gdkx.h> -#include <signal.h> -#include <dirent.h> -#include <sys/stat.h> -#include <unistd.h> -#include <ctype.h> -#include <assert.h> -#include <time.h> -#include <sys/time.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/Xatom.h> -#include <X11/Xos.h> -#include <X11/extensions/shape.h> -#include <X11/Xmu/WinUtil.h> -#include <X11/cursorfont.h> -#include <X11/keysym.h> -#include <stdarg.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <sys/types.h> - -/* The regular non-fun glib calls for distro copies of gtkeyboard. */ -# define g_new0_(t,c) g_new0(t,c) -# define g_free_(mem) g_free(mem) -# define g_new_(t,c) g_new(t,c) -# define g_strdup_(x) g_strdup(x) -# define g_malloc_(x) g_malloc(x) -# define MEM(x) ; /* Don't do anything */ - - -/* modmap.h - * Written by David Allen <s2mdalle@titan.vcu.edu> - * - * Released under the terms of the GNU General Public License - */ - - - - -#define slot_number_to_mask(x) (1<<x) - -typedef struct { - KeyCode codes[4]; -} ModmapRow; - -typedef struct { - int max_keypermod; /* Alias for the entry in XModifierMap */ - ModmapRow modifiers[8]; /* Exactly 8 entries */ -} ModmapTable; - -static int file_exists(const char *filename); -static void send_redirect_a_keysym(KeySym input); -static unsigned long find_modifier_mask(KeyCode code); -static ModmapTable *ModmapTable_new(void); -static void ModmapTable_destroy(ModmapTable * table); -static int ModmapTable_insert(ModmapTable * table, KeyCode code, int slot); -static int mask_name_to_slot_number(char *maskname); -GtkWidget *build_keyboard(GtkWidget * input, char *filename); - - -/* templates.h - * - * Written by David Allen <s2mdalle@titan.vcu.edu> - * http://opop.nols.com/ - * Released under the terms of the GNU General Public License - */ - -#define MAXIMUM_ROWS 6 - -/* Abstract data types */ - -typedef struct { - KeySym lower_case; /* What happens when pressed by itself */ - KeySym upper_case; /* What happens when pressed with Shift/CL */ - KeySym alt_gr; /* Alt GR+ button -- mostly unused */ - KeyCode code; - char *aux_string; /* Cheating string holder for things that aren't - * right with XKeysymToString() -- most notably - * the F keys and the keypad keys - * This should NEVER be used in conjunction - * with foreign windows - only text insertion in - * our editing buffer - */ -} KEY; - -typedef struct { - char *tab; - char *backspace; - char *caps_lock; - char *space; - char *alt; - char *alt_gr; - char *control; - char *shift; -} KeyboardTranslation; - -typedef struct { - int row_values[MAXIMUM_ROWS]; - int keycount; - KeySym *syms; - KeyCode *codes; - KeyboardTranslation *trans; - char *name; - ModmapTable *modmap; -} KEYBOARD; - -/* Macros */ -#define NO_KEYBOARD ((KEYBOARD *)NULL) -#define NO_KEY ((KEY *)NULL) - -/* Function prototypes */ -static KEY *gtkeyboard_key_copy(KEY * key); -static KEY *gtkeyboard_keyboard_get_key(KEYBOARD * keyb, int row, int keyno); -static KEYBOARD *gtkeyboard_destroy_keyboard(KEYBOARD * input); -static KEYBOARD *read_keyboard_template(char *filename); -static KEY *gtkeyboard_destroy_key(KEY * input); -static KEY *gtkeyboard_new_key(const KeySym lower, - const KeySym upper, - const KeySym altgr, const char *alt); -gint track_focus(gpointer data); - - - -/* rc_file.h - A simple configuration file reader/writer header file - * by Patrick Gallot <patrick.gallot@cimlinc.com> - * - * This file is part of GTKeyboard and as such is licensed under the terms - * of the GNU General Public License. - */ - - -/* Different types that resource file varaibles can have */ -#define RC_NONE 0x0000 -#define RC_STR 0x0002 /* String */ -#define RC_PARSE_FUNC 0x0006 /* This one means that an external - * parsing function should be used - * and the resource file code - * shouldn't bother with the values - */ -typedef struct config_var { - /* These go together to specify a line in a file that could say something - * like "set foo_variable 10" or "foobar = 20" or even - * "toolbar menubar off" - */ - - gchar *Prefix; /* This could be something like "set" or "toolbar" */ - gchar *Name; /* Element name */ - gint Type; /* Type of the value */ - gpointer Val; /* Pointer to the value to store */ - /* Function pointer for custom handling -- it should have parameters - * of the "prefix" token, (usually "set"), the variable name, the - * varaible value, and the pointer we were supposed to store it in. - * The pointer is usually going to be the same as Val above - */ - int (*func) (char *prefix, char *varname, char *val, gpointer ptr); -} RCVARS; - -static int read_ConfigFile(char *filename, RCVARS * vars, int complain); - -#define CONDFREE(x) if(x){ g_free_(x); x = NULL; } - -#define FLUSH_EVERYTHING fflush(Q); fflush(stdout);\ - fflush(stderr); - -/* Toggling Defines */ -#define ON 1 -#define OFF 0 -/* Whatever the status is, FLIP IT */ -#define ISOFF(x) ( x==OFF ) - -/* In case we ever achieve portability to winblows, we can change this - * to a backslash. :) - */ -#define _DIR "/" - -#define FLUSH fflush(Q) -#define NONE NULL - -#define LEFT_MOUSE_BUTTON 1 -#define RIGHT_MOUSE_BUTTON 3 -#define MIDDLE_MOUSE_BUTTON 2 - -#define Q stderr -#define ABOUT_INFO "about.data" -#define RC_FILENAME ".gtkeyboardrc" -#define PROVIDED_RCFILE "example_configurations/defaults.gtkeyboard" -#define APPNAME "GTKeyboard" -#define CR "\n" - - - -/* adt.h - * For GTKeyboard - * written by David Allen s2mdalle@titan.vcu.edu - * http://opop.nols.com/ - * - * This file is released under the terms of the GNU General Public License. - * Please see COPYING for more details. - */ - - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> -#include <glib.h> -#include <gtk/gtk.h> -#include <errno.h> -#include <signal.h> -#include <ctype.h> -#include <assert.h> -#include <time.h> -#include <sys/time.h> - -/* Maximum number of custom colors. 10 is a good number, above that is - * really not needed per se. - */ -#define MAX_CUSTOM_COLORS 10 - -/**************************************************************************/ - -/* ADTs */ -/* Program configuration settings */ -typedef struct { - /* Changed to bits in 0.97.3 to save a little space. */ - /* Different program options - initialized in app.c changed in - * file_manip.c and messed with elsewhere. - * - * See app.c and the initialization code for comments on what they - * all mean. - */ - int REDIRECT_POLICY_IMPLICIT; - int STATUS_LOGGING; - int CAPS_LOCK; - int IGNORE_LAYOUT_FILE; - /* int ASK_REMAP_ON_EXIT; -- Deprecated for now... */ - int SHIFT; - int ALT_GR; - int NUMLOCK; - int VERBOSE; - int ALT; - int CONTROL; - int USE_KEYBOARD; - - - char *home; /* Home dir of user running the app. */ - char *tempslot; - char *extrafiles; /* Extra files, docs, default rcfile, lic. */ - char *redirect_window_name; /* Window name of redirection location. */ - char *keyboard_file; - char *cache_file; - Window redirect_window; /* Xlib window structure for redirection. */ - Window other; /* Temporary window structure for Xlib */ - - KEYBOARD *keyboard; - KEYBOARD *old_keyboard; - - /* These memory areas won't be used unless PROD isn't defined. - * When PROD isn't defined, we're not debugging, and they essentially - * keep track of the number of memory calls that I make. See also - * mem_header.h for a full definition of how they're used. - */ -#if defined(GTKEYBOARD_MEMORY_DEBUGGING) || defined(DEBUGGING) - long MEM; /* Number of bytes allocated */ - int gnew; /* Number of gnew() calls (alloc) */ - int gnew0; /* Number of gnew0() calls (alloc) */ - int gmalloc; /* Number of g_malloc() calls (alloc) */ - int gstrdup; /* Number of g_strdup() calls (alloc) */ - int gfree; /* Number of g_free() calls (free) */ -#endif -} GTKeyboardOptions; - -typedef struct { - GtkWidget *keyboard; - gint show_keyboard; -} GTKeyboardKeyboardElements; - -typedef struct { - int keyboard; -} GTKeyboardElements; - -/****************************************************************************/ - -typedef struct { - Window xwindow; /* So we can play with xlib. (our window) */ - GtkWidget *KEYBOARD; /* Container containing all keyb elements */ - - - GTKeyboardKeyboardElements keyboard_elements; - - /* If a field has a comment of "Cleaned" next to it, then it is - * either deallocated or destroyed in - * callbacks.c:gtkeyboard_mem_cleanup() via macro calls. - */ - char *custom_colors[MAX_CUSTOM_COLORS]; /* Cleaned */ - gchar *fontname; /* Cleaned */ - gchar *kfontname; /* Cleaned */ - gchar *colorname; /* Cleaned */ - gdouble saved_colors[4]; - - GtkShadowType SHADOW_TYPE; - GtkPositionType PULLOFFS_SIDE; - - GtkUIManager *uimanager; - GtkWidget *popup_menu; /* Cleaned */ - GdkCursor *cursor; - GtkStyle *style; - - /* Style referring to the main output text area */ - GtkStyle *textstyle; /* Cleaned */ - - /* The default GTK style */ - GtkStyle *deflt; /* Cleaned */ - - GdkFont *font; /* Cleaned */ - - /* The keyboard widget's style */ - GtkStyle *kstyle; /* Cleaned */ - - /* Keyboard font */ - GdkFont *kfont; /* Cleaned */ - - GtkTooltips *tooltips; -} GTKeyboardGUI; - -/**************************************************************************/ - -typedef struct { - int width; - int height; - int x; - int y; -} window_dimensions; - - -/* file_manip.h - * - * For use with GTKeyboard - * written by David Allen s2mdalle@titan.vcu.edu - * This file is released under the terms of the GNU General Public License - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <gtk/gtk.h> - - -#define MAX_LINE_LENGTH 128 -#define TOKEN_SIZE 50 -#define DEFAULT_RCFILE "# Default .gtkeyboardrc file written by GTKeyboard\nkeyboard main_keyboard on\nkeyboard number_pad on\nkeyboard cursor_keys on\nkeyboard f_keys on\n\nset handlebars off\n\nset word_wrap off\nset info_popups on\nset bump_amount 15\nhide buttonbar\nset random_strlen 10\nset eyecandy off\nset redirect_policy implicit\n" - - - - -#define STAT_AND_RETURN_IF_BAD(fname, someint, statstruct) \ - if(!fname)return(0);\ - someint = stat(fname, &statstruct);\ - if(someint<0) return(0); - -/* List of strings - GTKeyboard is really looking for these when it - * reads the rcfiles. These are the options it recognizes. To the user, - * they aren't case sensitive, but here, they must ALL be specified in all caps - */ -#define OPT_KEYBOARD_FILE "KEYBOARD_FILE" - - -/* Prototypes - creeping evil */ -static void parse_user_resource_file(char *filename); -static void FILE_readline(FILE * fp, char *buffer, const int maxlen); -static int setup_default_rcfile(char *file); - -/* EOF */ - -static const char *active_window_name = "CurrentWindow"; - -static Window root; -static XEvent xev; - -/* fake_timestamp is static in irxevent.c */ -static Window find_window(Window top, char *name); -static void gtkeyboard_XEvent_common_setup(XKeyEvent * xev); - -/* Various keyboards are included only for app.c and build_keyboard.c - * in master.h - */ - -/* Just make them all different - gets passed to build_an_entire_keyboard */ -/* Not used yet.. */ - -/* Local defines for what keys appear as */ - -/* - * Check the notes at the bottom of the page for an ASCII drawing of how the - * keyboard should look - * - * Each button is defined as a character string of two characters. The first - * is what you get when SHIFT || CAPS_LOCK > 0 and the second is the normal - * key function. This function loops through grabbing two characters at a - * time and then calling makekeybutton to set things up and map the - * callback to the key and so on. - * - * SPECIAL CASES WITHIN stuff[]: (Yes it's braindamaged) - * LL is the left cursor key - * RR is the right cursor key - * || is caps lock key - * \\ (or escaped, it's \\\\) is SHIFT key - * CC is control - * AA is alt - * -*/ - -/* PROTOTYPES - Most functions in build_keyboard.c are static and don't need - * prototypes here. - */ -int init_keyboard_stuff(char *input); -static void keysym_callback(GtkWidget * emitter, gpointer data); -static void capslock_toggle(GtkWidget * w, gpointer data); -static void alt_toggle(GtkWidget * w, gpointer data); -static void alt_gr_toggle(GtkWidget * w, gpointer data); -static void control_toggle(GtkWidget * w, gpointer data); -static void shift_on(GtkWidget * w, gpointer data); - -typedef struct { - GtkStyle *style; - int mask; -} GTKeyboardStyle; - -typedef struct { - GtkWidget *dialog; - GdkColor *color; -} color_info; - -typedef struct { - long code; - char *name; -} binding; - - -/* Main program options - do not declare as static - all global */ -static GTKeyboardOptions options; -static GTKeyboardGUI GUI; -static GTKeyboardElements ELEMENTS; - - -#define NO_HANDLER 666 - -/* Static function prototypes */ -static void setup_default_opts(void); -static void setup_default_opts_other(void); - -#define INSTALL_DOC_DIR "/usr/local/share/gtkeyboard" - -int init_keyboard_stuff(char *input) -{ - char *filename; - char *homeptr; - - /* This sets the values in the structure GUI to default values. - * I'll add things for changing the default in that function later. - */ - setup_default_opts(); /* Handles the stuff in options */ - setup_default_opts_other(); - - /* Allocate the necessary memory to copy location of support files - * into */ - options.extrafiles = g_new0_(char, (strlen(INSTALL_DOC_DIR) + 3)); - sprintf(options.extrafiles, "%s%s", INSTALL_DOC_DIR, _DIR); - - options.keyboard = NO_KEYBOARD; - options.old_keyboard = NO_KEYBOARD; - - /* End if */ - homeptr = getenv("HOME"); - - if (homeptr) { - options.home = g_strdup_(getenv("HOME")); - } /* End if */ - else - options.home = NULL; - - filename = - g_new0_(char, strlen(options.home) + 5 + strlen(RC_FILENAME)); - sprintf(filename, "%s%s%s", (options.home ? options.home : "/tmp"), - _DIR, RC_FILENAME); - - /* This parses ALL user preferences from ~/.gtkeyboardrc into various - * structures - the important parts of this are in rc_file.h and - * file_manip.c - */ - - parse_user_resource_file(filename); - - CONDFREE(filename); - - return (1); -} /* End init_keyboard_stuff */ - -/* This gets called once at setup to initialize all the GUI but - * non-keyboard related opts - * Shouldn't return anything or allocate any memory, it just sets - * things to "reasonable" defaults. - */ -static void setup_default_opts_other(void) -{ - /* Here's where you get to set all of the defaults for GUI structure - * members. - */ - GUI.SHADOW_TYPE = GTK_SHADOW_ETCHED_OUT; - GUI.PULLOFFS_SIDE = GTK_POS_LEFT; - GUI.cursor = (GdkCursor *) NULL; - GUI.fontname = (gchar *) NULL; - GUI.kfontname = (gchar *) NULL; - GUI.colorname = (gchar *) NULL; - GUI.textstyle = (GtkStyle *) NULL; - GUI.style = (GtkStyle *) NULL; - GUI.font = (GdkFont *) NULL; - GUI.kfont = (GdkFont *) NULL; - GUI.deflt = (GtkStyle *) NULL; - GUI.xwindow = (Window) NULL; - GUI.popup_menu = (GtkWidget *) NULL; - GUI.uimanager = (GtkUIManager *) NULL; - - GUI.keyboard_elements.show_keyboard = ON; - - GUI.keyboard_elements.keyboard = (GtkWidget *) NULL; - - return; -} /* End setup_default_opts_other */ - -/* This gets called once at startup, sets all the initial values for - * options.whatever stuff - */ -static void setup_default_opts(void) -{ - /* All screen ELEMENTS on by default */ - - ELEMENTS.keyboard = 1; - - /* Set up some default values for program parameters - * Can be changed by parse_rcfile later. Hopefully these are reasonable. - */ - options.other = (Window) NULL; - options.redirect_window = (Window) NULL; - options.home = (char *) NULL; - options.redirect_window_name = (char *) NULL; - options.tempslot = (char *) NULL; - options.keyboard_file = (char *) NULL; - - - /* options.ASK_REMAP_ON_EXIT = OFF; *//* Currently deprecated */ - options.STATUS_LOGGING = OFF; /* Save the status window */ - options.CAPS_LOCK = OFF; /* Caps lock starts at OFF */ - options.SHIFT = OFF; /* Shift starts at OFF */ - options.ALT_GR = OFF; /* Alt-GR key status */ - options.CONTROL = OFF; /* Control button at OFF */ - options.NUMLOCK = OFF; /* Numlock starts at OFF */ - options.ALT = OFF; /* Alt key starts at OFF */ - options.VERBOSE = OFF; /* Spew messages */ - options.REDIRECT_POLICY_IMPLICIT = ON; /* Default to implicit redir */ - options.IGNORE_LAYOUT_FILE = OFF; /* Dont ignore layout file */ - -} /* End setup_default_opts */ - - - -#define BUILD_KEYBOARD_C - -static char *string_special_cases(KeySym input); - -static void rotate_keyboard_definitions(KEYBOARD * new_keyboard) -{ - if (!new_keyboard) { - fprintf(stderr, - "rotate_keyboard_definitions Error: Bad keyboard.\n"); - fflush(stderr); - return; - } - - /* End if */ - /* If there is an old definition laying around, destroy it to free - * up the memory. - */ - if (options.old_keyboard) { - options.old_keyboard = - gtkeyboard_destroy_keyboard(options.old_keyboard); -#ifdef REMAPPING_DEBUGGING - fprintf(Q, "Rotated old keyboard out..."); - fflush(Q); -#endif /* REMAPPING_DEBUGGING */ - } - - /* End if */ - /* Copy the current keyboard definition to the 'old' keyboard */ - options.old_keyboard = options.keyboard; - - /* Make the argument to this function the 'current' keyboard */ - options.keyboard = new_keyboard; - -#ifdef REMAPPING_DEBUGGING - fprintf(Q, "Old keyboard is now %s, Current keyboard is now %s\n", - (options.old_keyboard ? "valid" : "dead"), - (options.keyboard ? "valid" : "dead")); - fflush(Q); -#endif /* REMAPPING_DEBUGGING */ - - return; -} /* End rotate_keyboard_definitions() */ - -/* This destroys the key attached as object data to a lot of the buttons - * when they get destroyed - */ -static void destroy_key_widget_data(GtkObject *object, gpointer data) -{ - KEY *key = (KEY *) data; - - if (!key) { - fprintf(stderr, - "GTKeyboard error (destroy_key_widget_data) "); - fprintf(stderr, "data == NULL!\n"); - fflush(stderr); - return; - } - /* End if */ - key = gtkeyboard_destroy_key(key); -} /* End destroy_key_widget_data() */ - -/* Call this for every widget that has a KEY structure as its object data - * this makes sure that when the widget is destroyed, destroy_key_widget_data - * gets called on the object data - */ -static void connect_destroy_signal(GtkWidget * widget, gpointer data) -{ -#if 0 - g_signal_connect_data(G_OBJECT(widget), - "destroy", - G_CALLBACK(destroy_key_widget_data), - (GtkCallbackMarshal) - gtk_signal_default_marshaller, data, - (GtkDestroyNotify) destroy_key_widget_data, - FALSE, TRUE); -#endif - g_signal_connect(G_OBJECT(widget), - "destroy", - G_CALLBACK(destroy_key_widget_data), - data); -} /* End connect_destroy_signal() */ - -static gint triple_callback(GtkWidget * emitter, GdkEvent * event, - gpointer data) -{ - KEY *k = (KEY *) data; - KEY *key = NO_KEY; - - if (!k) { - fprintf(stderr, - "GTKeyboard internal error: %s: NULL \"KEY\" arg.\n", - "(triple_callback)"); - fflush(stderr); - return TRUE; - } - /* End if */ - if (event->type == GDK_BUTTON_PRESS) { - key = gtkeyboard_key_copy(k); - - if (event->button.button == LEFT_MOUSE_BUTTON) { - /* Regular keypress, deal with it as normal */ - keysym_callback((GtkWidget *) NULL, - (gpointer) key); - key = gtkeyboard_destroy_key(key); - return TRUE; - } /* End if */ - else if (event->button.button == MIDDLE_MOUSE_BUTTON) { - KeySym lower, upper; - - /* Always generate the "Alt-GR" keysym */ - if (!key->alt_gr || key->alt_gr == NoSymbol) { - key->alt_gr = key->lower_case; - } /* End if */ - key->lower_case = key->upper_case = key->alt_gr; - - /* Not sure whether this is upper case or lower case. Try to - * find out by seeing if what XConvertCase returns is the same - * or different. - */ - XConvertCase(key->alt_gr, &lower, &upper); - - /* If upper is the same as alt_gr, then we need shift to be - * on. Otherwise leave it however it is - */ - if (key->alt_gr == upper) - options.SHIFT = ON; - - keysym_callback((GtkWidget *) NULL, - (gpointer) key); - /* Free the memory */ - key = gtkeyboard_destroy_key(key); - return TRUE; - } /* End else if */ - else if (event->button.button == RIGHT_MOUSE_BUTTON) { - /* Always generate the "uppercase" Keysym */ - key->lower_case = key->alt_gr = key->upper_case; - - options.SHIFT = ON; - - keysym_callback((GtkWidget *) NULL, - (gpointer) key); - key = gtkeyboard_destroy_key(key); - return TRUE; - } /* End if */ - else { - key = gtkeyboard_destroy_key(key); - return FALSE; - } /* End else */ - } - - /* End if */ - /* Tell calling code that we have not handled this event; pass it on. */ - return FALSE; -} /* End triple_callback() */ - -static void keysym_callback(GtkWidget * emitter, gpointer data) -{ - KEY *key = (KEY *) data; - KeySym sym; - char *keyname = (char *) NULL; - char *altkeyname = (char *) NULL; - KeySym lower = (KeySym) NULL, upper = (KeySym) NULL; - -#ifdef PARANOID_DEBUGGING - fprintf(Q, "keysym_callback(): Got (%s, %s, %s).\n", - XKeysymToString(key->lower_case), - XKeysymToString(key->upper_case), - XKeysymToString(key->alt_gr)); - fflush(Q); -#endif /* PARANOID_DEBUGGING */ - - /* Determine which of the syms in the KEY * structure to use. */ - keyname = XKeysymToString(key->lower_case); - altkeyname = XKeysymToString(key->alt_gr); - - if (options.ALT_GR) { - sym = key->alt_gr; - /* We have only three symbols, and we have to generate - * the fourth one for cyrillic letters. - */ - if (strstr(altkeyname, "Cyrillic_")) { - XConvertCase(sym, &lower, &upper); - - if (options.SHIFT || options.CAPS_LOCK) { - sym = upper; - } /* End if */ - } /* End if */ - } /* End if */ - else if (strstr(keyname, "KP")) { - if (options.NUMLOCK) - sym = key->upper_case; - else - sym = key->lower_case; - } /* End else if */ - else if (options.SHIFT) - sym = key->upper_case; - else if (options.CAPS_LOCK) { - if (isalpha((char) key->upper_case)) - sym = key->upper_case; - else - sym = key->lower_case; - } /* End else if */ - else - sym = key->lower_case; - - if (options.redirect_window_name) { - send_redirect_a_keysym(sym); - - } - /* End if */ - return; -} /* End keysym_callback() */ - -static int isspecial(KeySym input) -{ - char *ptr = XKeysymToString(input); - - if (input == NoSymbol || !ptr) - return (1); - if (strstr(ptr, "_L") || strstr(ptr, "_R")) - return (1); - if (strstr(ptr, "ontrol") || strstr(ptr, "Alt")) - return (1); - if (strstr(ptr, "ode")) - return (1); - if (strstr(ptr, "Tab") || strstr(ptr, "Lock") - || strstr(ptr, "pace")) - return (1); - - return (0); -} /* End isspecial */ - -GtkWidget *build_keyboard(GtkWidget * input, char *filename) -{ - /* NEW BUILD_KEYBOARD() */ - GtkWidget *mainbox = gtk_vbox_new(FALSE, 0); - GtkWidget *hbox = (GtkWidget *) NULL; - GtkWidget *button = (GtkWidget *) NULL; - char *name = (char *) NULL; - char *altname = (char *) NULL; - GtkWidget *align = (GtkWidget *) NULL; - char label[512]; - char tooltip_label[1024]; - char *errbuf = NULL; - char *utf8, *ptr; - int rowno; - int index; - char letter = '\0'; - char cyrletter = '\0'; - KEY *key; - KeySym s; - KeySym altlower, altupper; - - /* Create the current keyboard in a new place. -- This takes care of - * destroying our old ones for us. - */ - rotate_keyboard_definitions(read_keyboard_template(filename)); - - if (!options.keyboard) { - fprintf(stderr, "Couldn't read keyboard: Bummer.\n"); - fflush(stderr); - - errbuf = g_new0(char, strlen(filename) + 100); - sprintf(errbuf, - "Couldn't create keyboard from file:\n%s!\nCheck the file format!", - filename); - - button = gtk_button_new_with_label(errbuf); - - CONDFREE(errbuf); - - return (button); - } /* End if */ - else if (options.keyboard->keycount <= 0) { - errbuf = g_new0(char, strlen(filename) + 100); - sprintf(errbuf, - "Couldn't create keyboard from file:\n%s!\nCheck the file format!", - filename); - - button = gtk_button_new_with_label(errbuf); - CONDFREE(errbuf); - return (button); - } - /* End else if */ - for (rowno = 0; rowno < MAXIMUM_ROWS; rowno++) { - hbox = gtk_hbox_new(FALSE, 0); - align = gtk_alignment_new(0.5, 0.5, 0, 0); - - for (index = 0; - index < options.keyboard->row_values[rowno]; - index++) { - key = - gtkeyboard_keyboard_get_key(options.keyboard, - rowno, index); - - letter = (int) key->upper_case; - name = XKeysymToString(key->upper_case); - altname = XKeysymToString(key->alt_gr); - - if (key->upper_case == XK_Mode_switch || - key->lower_case == XK_Mode_switch) { - sprintf(label, " Alt Gr"); - } /* End if */ - else if (strstr(altname, "Cyrillic_")) { - /* We have only lower case letter, let us - * ask X to convert it to upper case. - */ - XConvertCase(key->alt_gr, &altlower, - &altupper); - - /* FIXME: Yes, this is totally wrong method to get - * the cyrillic letter. It just happen to to - * yield the right letter in koi8-r encoding. - */ - cyrletter = (char) altupper; - if (!isalpha(letter)) { - sprintf(label, " %c \n %c %c", - (char) key->upper_case, - (char) key->lower_case, - cyrletter); - } /* End if */ - else { - sprintf(label, " %c \n %c", - (char) key->upper_case, - cyrletter); - } /* End else */ - } /* End else if */ - else if ((isalnum(letter) || ispunct(letter)) - && (letter > 0)) { - if (!isalpha(letter)) - sprintf(label, " %c \n %c", - (char) key->upper_case, - (char) key->lower_case); - else - sprintf(label, " %c \n", - (char) key->upper_case); - } /* End if */ - else if (letter != 0) { - if (!iscntrl(letter) - && !isspecial(key->upper_case) - && letter != ' ') - sprintf(label, " %c \n %c", - (char) key->upper_case, - (char) key->lower_case); - else { - ptr = - string_special_cases(key-> - lower_case); - strncpy(label, ptr, 512); - g_free_(ptr); - } /* End else */ - } /* End else if */ - else { - ptr = - string_special_cases(key->lower_case); - strncpy(label, ptr, 512); - g_free_(ptr); - } /* End else */ - - s = key->lower_case; - -#if 0 - utf8 = - g_locale_to_utf8(label, -1, NULL, NULL, NULL); -#else - utf8=g_convert(label,-1,"utf-8","iso8859-1",NULL,NULL,NULL); -#endif - /* Make the correct key, and attach the correct signal - * function to it. Toggle/normal button/function - */ - if (s == XK_Caps_Lock || s == XK_Control_L || - s == XK_Control_R || s == XK_Alt_L || - s == XK_Alt_R || s == XK_Mode_switch) - button = - gtk_toggle_button_new_with_label(utf8); - else - button = gtk_button_new_with_label(utf8); - - g_free(utf8); - GTK_WIDGET_UNSET_FLAGS(button, GTK_CAN_FOCUS); - if (key->code != 0) - sprintf(tooltip_label, - "KeyCode %d:\n%s\n%s\n%s", - key->code, - XKeysymToString(key->lower_case), - XKeysymToString(key->upper_case), - XKeysymToString(key->alt_gr)); - else - sprintf(tooltip_label, - "KeyCode unknown:\n%s\n%s\n%s", - XKeysymToString(key->lower_case), - XKeysymToString(key->upper_case), - XKeysymToString(key->alt_gr)); - - switch (key->lower_case) { - case XK_Caps_Lock: - g_signal_connect(G_OBJECT(button), - "clicked", - G_CALLBACK(capslock_toggle), - input); - /* Key unused in signalling */ - key = gtkeyboard_destroy_key(key); - break; - case XK_Alt_L: - case XK_Alt_R: - g_signal_connect(G_OBJECT(button), - "clicked", - G_CALLBACK(alt_toggle), NULL); - /* Key unused in signalling */ - key = gtkeyboard_destroy_key(key); - break; - case XK_Control_L: - case XK_Control_R: - g_signal_connect(G_OBJECT(button), - "clicked", - G_CALLBACK(control_toggle), NULL); - /* Key unused in signalling */ - key = gtkeyboard_destroy_key(key); - break; - case XK_Shift_L: - case XK_Shift_R: - g_signal_connect(G_OBJECT(button), - "clicked", - G_CALLBACK(shift_on), NULL); - /* Key unused in signalling */ - key = gtkeyboard_destroy_key(key); - break; - case XK_Mode_switch: - g_signal_connect(G_OBJECT(button), - "clicked", - G_CALLBACK(alt_gr_toggle), NULL); - /* Key unused in signalling */ - key = gtkeyboard_destroy_key(key); - break; - default: - g_signal_connect(G_OBJECT(button), - "button_press_event", - G_CALLBACK(triple_callback), key); - connect_destroy_signal(button, key); - break; - } /* End switch */ - - gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, - FALSE, 0); - } /* End for */ - - gtk_container_add(GTK_CONTAINER(align), hbox); - gtk_box_pack_start(GTK_BOX(mainbox), align, FALSE, FALSE, - 0); - } /* End for */ - - if (filename) { - if (options.keyboard_file) { - /* We just built a complete keyboard with this file, so save its - * name for future use. - */ - /* This weird indirect freeing and copying of the string is - * due to the fact that the filename argument to this function - * may in fact be options.keyboard_file itself, so in that - * case it wouldn't be that bright to try to free it and - * copy something that's pointing to the same location. So - * instead we copy it to an intermediate spot, free the - * original, and copy the new value back. - * - * When the value actually is options.keyboard_file, we do a - * bit of redundant work, but oh well. - */ - char *tptr; - tptr = g_strdup_(filename); - g_free_(options.keyboard_file); - options.keyboard_file = g_strdup_(tptr); - g_free_(tptr); -#if 0 - fprintf(Q, - "options.keyboard_file set to be \"%s\"\n", - options.keyboard_file); - fflush(Q); -#endif - } /* End if */ - else { - /* No need to free it - just copy */ - options.keyboard_file = g_strdup_(filename); - fprintf(Q, - "options.keyboard_file set to be \"%s\"\n", - options.keyboard_file); - fflush(Q); - } /* End else */ - } - - /* End if */ - /* gtk_widget_show_all(mainbox); */ - return (mainbox); -} /* End build_keyboard() */ - -static char *string_special_cases(KeySym input) -{ - char label[1024]; - int len, x; - char *ptr; - - if (input == XK_space) { - sprintf(label, - " \n"); - } /* End if */ - else { - /* Space out the output a bit depending on string target - * length so the buttons will look right. - */ - ptr = XKeysymToString(input); - if (strlen(ptr) > 4) - sprintf(label, " %s \n", ptr); - else - sprintf(label, " %s \n", ptr); - } /* End else */ - - len = strlen(label); - - /* Special cases */ - if (strstr(label, "Control") || strstr(label, "control")) { - strcpy(label, " Ctrl "); - } /* End if */ - else if (input == XK_Mode_switch) - strcpy(label, " Alt Gr"); - else { - /* Remove the sillyness from XK_ names from the string. */ - for (x = 0; x < len; x++) { - /* Make everything uppercase */ - label[x] = toupper(label[x]); - - /* Get rid of the _R or _L that may be there. */ - if (label[x] == '_' && - (label[x + 1] == 'R' || label[x + 1] == 'L')) { - label[x] = '\0'; - } /* End if */ - } /* End for */ - } /* End else */ - - ptr = g_strdup_(label); - - return (ptr); -} /* End string_special_cases() */ - - -#define MODE_WRITE - -/* Do not allow both MODE_WRITE and MODE_APPEND to be defined. If both are - * defined, default to MODE_WRITE. The End Of Earth As We Know It (TM) occurs - * (or maybe just a compile error) MODE_WRITE is spiffier. - */ -#ifdef MODE_APPEND -# ifdef MODE_WRITE -# undef MODE_APPEND -# endif /* MODE_WRITE */ -#endif /* MODE_APPEND */ - -#ifndef __USE_GNU -# define __USE_GNU -#endif /* __USE_GNU */ - - -static void alt_gr_toggle(GtkWidget * w, gpointer data) -{ - if (ISOFF(options.ALT_GR)) { - options.ALT_GR = ON; - } /* End if */ - else { - options.ALT_GR = OFF; - } /* End else */ -} /* End alt_gr_toggle */ - -static void control_toggle(GtkWidget * w, gpointer data) -{ - if (ISOFF(options.CONTROL)) { - options.CONTROL = ON; - } /* End if */ - else { - options.CONTROL = OFF; - } /* End else */ -} /* End control_toggle */ - -static void alt_toggle(GtkWidget * w, gpointer data) -{ - if (ISOFF(options.ALT)) { - options.ALT = ON; - } /* End if */ - else { - options.ALT = OFF; - } /* End else */ -} /* End alt_toggle */ - -static void capslock_toggle(GtkWidget * w, gpointer data) -{ - if (options.redirect_window_name) - send_redirect_a_keysym(XK_Caps_Lock); - - /* Whatever it currently is, swtich it */ - if (ISOFF(options.CAPS_LOCK)) { - options.CAPS_LOCK = ON; - } /* End if */ - else { - options.CAPS_LOCK = OFF; - } /* End else */ -} /* End capslock_toggle */ - -static void shift_on(GtkWidget * w, gpointer data) -{ - /* Turn shift on */ - options.SHIFT = ON; - -} /* End shift_on */ - -/* This parses the user resource file via read_ConfigFile. This function - * doesn't actually do much other than define all of the structures for - * parsing in one place and actually doing the function calls. This is - * where you need to tweak command options. - */ -static void parse_user_resource_file(char *filename) -{ - RCVARS rc_parse_values[] = { - {"set", OPT_KEYBOARD_FILE, RC_STR, &options.keyboard_file, - NULL}, - {NULL, NULL, RC_NONE, NULL, NULL} - }; /* End rc_parse_values */ - - if (!file_exists(filename)) { - fprintf(stderr, - "Your resource file doesn't seem to exist.\n"); - fprintf(stderr, "I'll create one for you at \"%s\"\n", - filename); - fflush(stderr); - setup_default_rcfile(filename); - } - /* End if */ - read_ConfigFile(filename, rc_parse_values, 1); -} /* End parse_user_resource_file() */ - -/* Read one line from the specified file pointer and return it as - * as a pointer to char and so on. - */ -static void FILE_readline(FILE * fp, char *buffer, const int maxlen) -{ - int index = 0; - int x; - char tmp; - - do { - x = fread(&tmp, sizeof(char), 1, fp); - if ((x == 0) || (tmp == '\n')) - buffer[index] = '\0'; /* Terminate the string with a NULL */ - else - buffer[index++] = tmp; /* Add the character */ - if (!(index < maxlen)) { - fprintf(Q, - "Error on FILE_readline: index >= maxlen\n"); - fflush(Q); - return; - } /* End if */ - } while ((x != 0) && (tmp != '\n')); - return; -} /* End FILE_readline */ - -/* Copies a default rcfile from somewhere to the input filename */ -static int setup_default_rcfile(char *file) -{ - FILE *fp; - FILE *dflt; - char buffer[1024]; - char buffer2[1024]; - - if ((fp = fopen(file, "w")) == NULL) { - fprintf(Q, "Couldn't open %s for writing - cannot create ", - file); - fprintf(Q, "default .gtkeyboardrc!\n"); - fflush(Q); - return (0); - } /* End if */ - else { - /* Try to open the distribution-provided rcfile first */ - sprintf(buffer, "%s/%s", options.extrafiles, - PROVIDED_RCFILE); - - if ((dflt = fopen(buffer, "r")) == NULL) { - /* Ok, fine, so we can't open the default one we provided - * with the distribution. We'll just give the user a really - * short and crappy one. - */ - fprintf(Q, "Couldn't open %s: %s.\n", buffer, - g_strerror(errno)); - fprintf(Q, - "Fine then! We'll try something else...\n"); - fflush(Q); - - fprintf(fp, "%s", DEFAULT_RCFILE); - fclose(fp); - fprintf(Q, - "Success writing default .gtkeyboardrc\n"); - fprintf(Q, - "You can edit it to make changes later by editing "); - fprintf(Q, "%s\n", file); - fflush(Q); - return (1); - } /* End if */ - else { - while (!feof(dflt)) { - FILE_readline(dflt, buffer2, 1024); - /* Add a newline because FILE_readline kills them off */ - fprintf(fp, "%s\n", buffer2); - } /* End while */ - - fflush(fp); - fclose(dflt); - fclose(fp); - - fprintf(Q, - "Successfully wrote .gtkeyboardrc from "); - fprintf(Q, - "default. (%s: Distribution provided)\n", - PROVIDED_RCFILE); - } /* End else */ - } /* End else */ - FLUSH_EVERYTHING; - return (1); -} /* End setup_default_rcfile */ - -static int file_exists(const char *filename) -{ - struct stat file_info; - int x; - - STAT_AND_RETURN_IF_BAD(filename, x, file_info); - - return (1); -} /* End file_exists */ - -/* seems that xfree86 computes the timestamps for events like this - * strange but it relies on the *1000-32bit-wrap-around - * if anybody knows exactly how to do it, please contact me - * returns: a timestamp for the - * constructed event - */ -static Time fake_timestamp(void) -{ - int tint; - struct timeval tv; - struct timezone tz; /* is not used since ages */ - gettimeofday(&tv, &tz); - tint = (int) tv.tv_sec * 1000; - tint = tint / 1000 * 1000; - tint = tint + tv.tv_usec / 1000; - return ((Time) tint); -} /* End fake_timestamp() */ - -/* in: id of the root window name of the target window - * returns: id of the target window - * called by: main - */ -static Window find_window(Window top, char *name) -{ - char *wname, *iname; - XClassHint xch; - Window *children, foo; - int revert_to_return; - unsigned int nc; - - if (!strcmp(active_window_name, name)) { - XGetInputFocus(GDK_DISPLAY(), &foo, &revert_to_return); - return (foo); - } - - /* End if */ - /* First the base case */ - if (XFetchName(GDK_DISPLAY(), top, &wname)) { - if (!strncmp(wname, name, strlen(name))) { - XFree(wname); - return (top); /* found it! */ - } - /* End if */ - XFree(wname); - } - /* End if */ - if (XGetIconName(GDK_DISPLAY(), top, &iname)) { - if (!strncmp(iname, name, strlen(name))) { - XFree(iname); - return (top); /* found it! */ - } /* End if */ - XFree(iname); - } - /* End if */ - if (XGetClassHint(GDK_DISPLAY(), top, &xch)) { - if (!strcmp(xch.res_class, name)) { - XFree(xch.res_name); - XFree(xch.res_class); - return (top); /* found it! */ - } /* End if */ - XFree(xch.res_name); - XFree(xch.res_class); - } - /* End if */ - if (!XQueryTree(GDK_DISPLAY(), top, &foo, &foo, &children, &nc) || - children == NULL) - return (0); /* no more windows here */ - - /* check all the sub windows */ - for (; nc > 0; nc--) { - top = find_window(children[nc - 1], name); - if (top) - break; /* we found it somewhere */ - } /* End for */ - - /* Free that mem! Yeehaw!!! */ - if (children) - XFree(children); - - return (top); -} /* End find_window() */ - -/* This just assigns a bunch of things to certain elements of the pointer - * that are shared no matter what type of signal GTKeyboard is sending. - * Prevents code duplication in ugly places - */ -static void gtkeyboard_XEvent_common_setup(XKeyEvent * xev) -{ - xev->type = KeyPress; - xev->display = GDK_DISPLAY(); - xev->root = root; - xev->subwindow = None; - xev->time = fake_timestamp(); - xev->same_screen = True; - xev->state = 0; - xev->x = xev->y = xev->x_root = xev->y_root = 1; -} /* End gtkeyboard_XEvent_common_setup */ - -static int assign_keycode_from_keysym(KeySym foo, XKeyEvent * xev) -{ - unsigned long mask = 0; - char *keyname = (char *) NULL; - - keyname = XKeysymToString(foo); - xev->keycode = XKeysymToKeycode(GDK_DISPLAY(), foo); - - /* Check and assign masks. */ - if (options.SHIFT) { /* Need ShiftMask? */ - mask = find_modifier_mask(XKeysymToKeycode(GDK_DISPLAY(), - XK_Shift_L)); - if (!mask) { - /* WTF? Shift_L isn't mapped? OK, try Shift_R */ - mask = - find_modifier_mask(XKeysymToKeycode - (GDK_DISPLAY(), - XK_Shift_R)); - } - /* End if */ - fprintf(Q, "Shift mask: 0x%lx normal mask 0x%lx\n", mask, - (unsigned long) ShiftMask); - - /* Even if mask is actually 0 because we couldn't find the shift - * key mapped, this just won't do anything at all. - * find_modifier_mask issued a warning about not finding it, too - */ - xev->state |= mask; - options.SHIFT = 0; - } - /* End if */ - if (options.CAPS_LOCK) { /* Need LockMask? */ - mask = find_modifier_mask(XKeysymToKeycode(GDK_DISPLAY(), - XK_Caps_Lock)); - fprintf(Q, "Capslock mask: 0x%lx normal mask 0x%lx\n", - mask, (unsigned long) LockMask); - xev->state |= mask; /* Normally LockMask */ - } - /* End if */ - if (options.CONTROL) { /* Need ControlMask? */ - mask = find_modifier_mask(XKeysymToKeycode(GDK_DISPLAY(), - XK_Control_L)); - if (!mask) { - mask = - find_modifier_mask(XKeysymToKeycode - (GDK_DISPLAY(), - XK_Control_R)); - } - /* End if */ - fprintf(Q, "Control mask: 0x%lx normal mask 0x%lx\n", - mask, (unsigned long) ControlMask); - xev->state |= mask; - } - /* End if */ - if (options.ALT) { /* Need Mod1Mask? */ - mask = find_modifier_mask(XKeysymToKeycode(GDK_DISPLAY(), - XK_Alt_L)); - if (!mask) { - mask = - find_modifier_mask(XKeysymToKeycode - (GDK_DISPLAY(), XK_Alt_R)); - } - /* End if */ - fprintf(Q, "Alt mask: 0x%lx normal mask 0x%lx\n", - mask, (unsigned long) Mod1Mask); - xev->state |= mask; - } - /* End if */ - if (options.NUMLOCK) { - mask = find_modifier_mask(XKeysymToKeycode(GDK_DISPLAY(), - XK_Num_Lock)); - fprintf(Q, "Numlock: Mask 0x%lx\n", mask); - xev->state |= mask; - } - /* End if */ - if (options.ALT_GR) { - mask = find_modifier_mask(XKeysymToKeycode(GDK_DISPLAY(), - XK_Mode_switch)); - fprintf(Q, "Alt_GR: Mask 0x%lx\n", mask); - xev->state |= mask; - } - /* End if */ - if (strstr(keyname, "Cyrillic_")) { /* Cyrillic? */ - mask = find_modifier_mask(XKeysymToKeycode(GDK_DISPLAY(), - XK_ISO_Group_Shift)); - /* FIXME: How do we get this mask and what does it mean? - * Seems to be XKB_Group. Default 0x2000 - */ - - xev->state |= mask; - } - - - /* End if */ - /* xev->state = xev->state | ButtonMotionMask; */ -#if 0 - fprintf(Q, "Final mask on event: %ld 0x%lx\n", - (unsigned long) xev->state, (unsigned long) xev->state); -#endif - - if (xev->keycode != 0) - return 1; - - else - return 0; -} /* End assign_keycode_from_keysym() */ - -static void keysym_sendkey(KeySym somesym, Window w) -{ - gtkeyboard_XEvent_common_setup((XKeyEvent *) & xev); - - /* assign_keycode_from_keysym() will also add in the needed - * masks. WARNING: This may change options.SHIFT and other - * bitflags in options according to whether or not they should - * change. - */ - if (!assign_keycode_from_keysym(somesym, (XKeyEvent *) & xev)) { - return; - } - /* End if */ - xev.xkey.window = w; - - /* This may produce a BadWindow error with Xlib. Bummer. - * This happens most commonly when the window that was selected to - * redirect to doesn't exist on screen anymore. - */ - gdk_error_trap_push(); /* Catch errors, hopefully */ - - XSendEvent(GDK_DISPLAY(), w, True, KeyPressMask, &xev); - - XSync(GDK_DISPLAY(), False); - - xev.type = KeyRelease; /* Start the next Event */ - /* usleep(50000); */ -#if 0 - XFlush(GDK_DISPLAY()); -#endif - xev.xkey.time = fake_timestamp(); - XSendEvent(GDK_DISPLAY(), w, True, KeyReleaseMask, &xev); - XSync(GDK_DISPLAY(), False); - -#if 0 - gdk_flush(); -#endif - - if (gdk_error_trap_pop()) { - } - /* End if */ - return; -} /* End keysym_sendkey() */ - -/* Insert KeyCode code into slot slot in the table structure. - * Returns != 0 on success, 0 on failure. Failure means that - * the table is full, or that the code you're trying to insert is 0 - */ -static int ModmapTable_insert(ModmapTable * table, KeyCode code, int slot) -{ - int x = 0; - - if ((code == (KeyCode) 0) || (slot < 0) || (slot > 8)) - /* This operation makes no sense. Return failure. */ - return 0; - - for (x = 0; x < table->max_keypermod; x++) { - /* Insert in the first available open slot - * but not in taken slots. That would be a bad idea to - * silently overwrite some of the caller's data. :) - */ - if (table->modifiers[slot].codes[x] == 0) { - table->modifiers[slot].codes[x] = code; - return 1; - } /* End if */ - } /* End for */ - - /* Fail - can't find empty slot */ - return (0); -} /* End ModmapTable_insert() */ - -static ModmapTable *ModmapTable_new(void) -{ - XModifierKeymap *map = XGetModifierMapping(GDK_DISPLAY()); - ModmapTable *table; - int mkpm = map->max_keypermod; - int x = 0; - int y = 0; - - XFreeModifiermap(map); - table = g_new0_(ModmapTable, 1); - table->max_keypermod = mkpm; - - for (x = 0; x < 8; x++) { - for (y = 0; y < 4; y++) { - table->modifiers[x].codes[y] = (KeyCode) 0; - } /* End for */ - } /* End for */ - - return table; -} /* End ModmapTable_new() */ - -static void ModmapTable_destroy(ModmapTable * table) -{ - g_free_(table); -} /* End ModmapTable_destroy() */ - -/* Translates a string mask name into a slot number for access to numerous - * modmap data structures. - */ -static int mask_name_to_slot_number(char *maskname) -{ - char *masks[] = { "ShiftMask", "LockMask", - "ControlMask", "Mod1Mask", - "Mod2Mask", "Mod3Mask", - "Mod4Mask", "Mod5Mask" - }; - int maskcount = 8; - int y = 0; - - for (y = 0; y < maskcount; y++) { - if (g_ascii_strcasecmp(maskname, masks[y]) == 0) - return y; - } /* End for */ - - return (-1); -} /* End mask_name_to_slot_number() */ - -static unsigned long find_modifier_mask(KeyCode code) -{ - XModifierKeymap *map = XGetModifierMapping(GDK_DISPLAY()); - int x = 0, y = 0; - KeyCode c = (KeyCode) NULL; - unsigned long mask = 0; - - if (code == (KeyCode) 0) { - XFreeModifiermap(map); - fprintf(Q, - "Error finding modifier mask for 0 keycode: Have you\n"); - fprintf(Q, - "actually remapped your keyboard to this layout?\n"); - return 0; - } - /* End if */ - for (x = 0; x < 8; x++) { - for (y = 0; y < map->max_keypermod; y++) { - c = map->modifiermap[x * map->max_keypermod + y]; - if (c == code) { - XFreeModifiermap(map); - mask = slot_number_to_mask(x); - fprintf(Q, - "Found modifier %d in slot (%d,%d) mask %ld 0x%lx\n", - code, x, y, mask, mask); - return mask; - } /* End if */ - } /* End for */ - } /* End for */ - - XFreeModifiermap(map); - - /* Return nothing. This is bad, but better than doing the wrong thing. */ - fprintf(Q, - "***** WARNING: find_modifier_mask failed to locate code %d\n", - code); - fflush(Q); - return 0; -} /* End find_modifier_mask() */ - - -/* Makes a NULL-terminated string that gets passed as input nothing but - * upper case characters. - * - * THIS FUNCTION MODIFIES ITS ARGUMENT - */ -static void str_toupper(char *string) -{ - int x = 0; - - while (string[x]) { /* Stop on NULL */ - string[x] = toupper(string[x]); - x++; - } /* End while */ -} /* End str_toupper() */ - -/* Passed - the filename, the set of variables to look for, (see the header - * file for the definition of that structure) and an integer - if it's 0, - * then "syntax error" messages won't be printed. Otherwise, we'll complain. - */ -static int read_ConfigFile(char *filename, RCVARS * vars, int complain) -{ - gint n = 0; - gpointer N; - FILE *rcFile; - GHashTable *H; - gchar Line[BUFSIZ], varPrefix[BUFSIZ], varName[BUFSIZ], - varVal[BUFSIZ]; - - /* if the RC file doesn't exist, don't bother doing anything else */ - if ((rcFile = fopen(filename, "r")) == NULL) { - if (complain) { - fprintf(Q, "Couldn't open %s for reading: %s\n", - filename, g_strerror(errno)); - fflush(Q); - } /* End if */ - return 1; - } - - /* End if */ - /* Create a hash table of all the variable names and their arrayindex+1 */ - H = g_hash_table_new(g_str_hash, g_str_equal); - - n = 0; - /* Hash in all of the variable names. Later when we read them in, - * we'll hash in what we read to compare it against what was in the - * table passed to us. - */ - while (vars[n].Type != RC_NONE) { - g_hash_table_insert(H, vars[n].Name, - GINT_TO_POINTER(n + 1)); - n++; - } /* End while */ - - /* read each line of the RC file */ - while (fgets(Line, BUFSIZ, rcFile) != NULL) { - /* Strip leading and trailing whitespace from the string */ - strcpy(Line, g_strstrip(Line)); - - /* Skip comments and lines too short to have useful information - * in them. This will include "blank" lines that got g_strstrip'd - * down to 0 or 1 bytes - */ - if ((strlen(Line) < 2) || Line[0] == '#') - continue; - - /* Initialize values so in case of error they will be NULL, not - * the value of the last parse. - */ - varPrefix[0] = varName[0] = varVal[0] = '\0'; - - /* grab each variable and its value (maybe). - * If prefix is specified, it tries to read the - * given prefix. - */ - if (strstr(Line, "=")) - sscanf(Line, " %s = %s\n", varName, varVal); - else - sscanf(Line, " %s %s %s\n", varPrefix, varName, - varVal); - - /* Sometimes prefix *could* be null, but if name or value is - * null, there's really nothing we can do with that string. - */ - if (!varName[0] && !varVal[0]) { - if (complain) { - fprintf(stderr, - "Error parsing line \"%s\": ", - Line); - fprintf(stderr, - "I have no idea what that line means.\n"); - fflush(stderr); - } - /* End if */ - continue; - } - - /* End if */ - /* We want the rc file to be case insensitive, but we're looking for - * all upper-case varaible names, so convert the string to all - * upper-case so it will hash in correctly. - */ - str_toupper(varName); - - /* use the hash table to find the correct array entry */ - if ((N = g_hash_table_lookup(H, varName)) == NULL) { - continue; /* but skip to the next line if can't find it. */ - } - /* End if */ - n = GPOINTER_TO_INT(N) - 1; /* convert back into an array index */ - - /* We can't necessarily match the read prefix to the requested - * prefix since the prefixes may be different and may require - * processing through the function pointer associated with the - * record - */ - - /* - * Did we see a prefix when we didn't want one? - */ - if (!vars[n].Prefix && varPrefix[0]) { - fprintf(stderr, - "Error: Bad syntax. I wasn't expecting to see "); - fprintf(stderr, "a variable prefix on \"%s\".\n", - (varName ? varName : Line)); - fprintf(stderr, "Ignoring line \"%s\"\n", Line); - fflush(stderr); - continue; - } - - /* End if */ - /* Are we supposed to run this one through a function? */ - if (vars[n].Type == RC_PARSE_FUNC) { - /* Use the outside function specified in the structure - * to parse these line elements since their grammar is - * somewhat weird - */ - if (!vars[n]. - func(varPrefix, varName, varVal, - vars[n].Val)) { - fprintf(stderr, - "There was an error parsing \"%s\"\n", - Line); - fflush(stderr); - } - /* End if */ - continue; /* Done with this line */ - } - - /* End if */ - /* We're not supposed to run this through a function -- - * based on the variable's type, set the C variable to its saved - * value - */ - switch (vars[n].Type) { - case (RC_STR): - { - char *tok; - - /* varVal is not trustworthy, find the string - * within the quotes and use that instead. - */ - if (strstr(Line, "\"")) { - tok = strtok(Line, "\""); - if (!tok) { - /* This really shouldn't happen */ - if (complain) { - fprintf(stderr, - "Parse error within \"%s\"\n", - Line); - fflush(stderr); - } /* End if */ - break; - } /* End if */ - tok = strtok(NULL, "\""); - } /* End if */ - else - tok = &varVal[0]; - - /* free the current contents of the variable */ - if (*(gchar **) (vars[n].Val)) - g_free_(*(gchar **) vars[n].Val); - - /* set the variable to its new value. */ - if (tok) { - *(gchar **) (vars[n].Val) = - g_strdup_(tok); - } /* End if */ - else - *(gchar **) (vars[n].Val) = - (char *) NULL; - break; - } /* End block */ - } /* End switch */ - } /* End while */ - - /* clean up and exit */ - g_hash_table_destroy(H); - fclose(rcFile); - return 0; -} /* End read_ConfigFile() */ - -static KEY *gtkeyboard_key_copy(KEY * key) -{ - KEY *newkey; - - if (!key) - return (NO_KEY); - - newkey = gtkeyboard_new_key(key->lower_case, - key->upper_case, - key->alt_gr, key->aux_string); - newkey->code = key->code; - return (newkey); -} /* End gtkeyboard_key_copy() */ - -/* Returns the "keyno"th key in row "row" of keyb - * This is allocated memory which must be g_free()'d later. - * This will ALWAYS return allocated memory - it just might always be - * filled with NoSymbol - */ -static KEY *gtkeyboard_keyboard_get_key(KEYBOARD * keyb, int row, - int keyno) -{ - KEY *foobar; - int index; - int x, findex = 0; - - foobar = gtkeyboard_new_key(NoSymbol, NoSymbol, NoSymbol, NULL); - - if (row > MAXIMUM_ROWS) { - fprintf(stderr, - "gtkeyboard_keyboard_get_key: Row out of range.\n"); - fflush(stderr); - return (foobar); - } - /* End if */ - if (!keyb) { - fprintf(stderr, - "gtkeyboard_keyboard_get_key: Null keyb.\n"); - fflush(stderr); - return (foobar); - } - /* End if */ - x = findex = 0; - - while (x < row) { - /* Add up the number of keys on all lines preceeding the one we're - * looking for - */ - findex += keyb->row_values[x]; - x++; - } /* End while */ - - index = (findex * 3) + (keyno * 3); - - if (index > ((keyb->keycount * 3) - 3)) { - fprintf(stderr, "gtkeyboard_keyboard_get_key(): "); - fprintf(stderr, - "Illegal index %d of a total keycount of %d (%d).\n", - index, keyb->keycount, ((keyb->keycount * 3) - 3)); - fflush(stderr); - return (foobar); - } - - /* End if */ - /* Three consecutive KeySyms */ - foobar->lower_case = keyb->syms[index]; - foobar->upper_case = keyb->syms[(index + 1)]; - foobar->alt_gr = keyb->syms[(index + 2)]; - foobar->aux_string = (char *) NULL; /* No auxilliary */ - - if (keyb->codes) - foobar->code = keyb->codes[(findex + keyno)]; - else - foobar->code = 0; - - return (foobar); -} /* End gtkeyboard_keyboard_get_key() */ - -static KEY *gtkeyboard_new_key(const KeySym lower, const KeySym upper, - const KeySym altgr, const char *alt) -{ - KEY *somekey = g_new0_(KEY, 1); - somekey->lower_case = lower; - somekey->upper_case = upper; - somekey->alt_gr = altgr; - somekey->code = 0; - if (alt) { - somekey->aux_string = g_strdup_(alt); - } /* End if */ - else - somekey->aux_string = NULL; - - return (somekey); -} /* End gtkeyboard_new_key() */ - -static KEY *gtkeyboard_destroy_key(KEY * input) -{ - if (!input) { - fprintf(Q, - "Error: gtkeyboard_destroy_key: NULL argument.\n"); - fflush(Q); - return (NO_KEY); - } - /* End if */ - if (input->aux_string) { - g_free_(input->aux_string); - input->aux_string = (char *) NULL; - } - /* End if */ - g_free_(input); - input = NO_KEY; /* Null pointer so it won't be reused */ - - return (NO_KEY); -} /* End gtkeyboard_destroy_key() */ - -static KEYBOARD *gtkeyboard_destroy_keyboard(KEYBOARD * input) -{ - if (!input) { - fprintf(stderr, - "gtkeyboard_destroy_keyboard: Cannot destroy NULL ptr.\n"); - fflush(stderr); - return (NO_KEYBOARD); - } - /* End if */ - if (input->syms) { - g_free_(input->syms); - input->syms = NULL; - } - /* End if */ - if (input->name) { - g_free_(input->name); - input->name = NULL; - } - /* End if */ - if (input->codes) { - g_free_(input->codes); - input->codes = NULL; - } - /* End if */ - if (input->modmap) { - ModmapTable_destroy(input->modmap); - input->modmap = (ModmapTable *) NULL; - } - /* End if */ - if (input->trans) { - CONDFREE(input->trans->space); - CONDFREE(input->trans->tab); - CONDFREE(input->trans->alt_gr); - CONDFREE(input->trans->alt); - CONDFREE(input->trans->control); - CONDFREE(input->trans->shift); - CONDFREE(input->trans->backspace); - - /* Free the parent pointer */ - CONDFREE(input->trans); - } - /* End if */ - g_free_(input); - input = NO_KEYBOARD; - - return (NO_KEYBOARD); -} /* End gtkeyboard_destroy_keyboard() */ - -static int get_valid_line(FILE * fp, char *mem, const int maxlen) -{ - mem[0] = '\0'; - - while (!feof(fp) && mem[0] == '\0') { - FILE_readline(fp, mem, maxlen); - - if (mem[0] != '\0') { - strcpy(mem, g_strstrip(mem)); - - if ((mem[0] && mem[0] == '#') - || (mem[0] && mem[0] == '!')) - mem[0] = '\0'; - } /* End if */ - } /* End while */ - - if (mem[0] == '\0') - return (0); - - else - return (1); -} /* End get_valid_line() */ - -/* Parses the contents of a keyboard description file and returns - * a corresponding KEYBOARD structure. - */ -static KEYBOARD *read_keyboard_template(char *filename) -{ - KEYBOARD *keyb = NO_KEYBOARD; - FILE *fp; - register int x = 0, y = 0; - int line_size = 1024; - int index = 0; - char linedata[line_size]; - char **tokens; - char **tofree; - char *ptr; - - if (!filename || !file_exists(filename)) { - fprintf(stderr, "Error loading keyboard file \"%s\": ", - (filename ? filename : "NULL")); - fprintf(stderr, "File doesn't exist."); - fflush(stderr); - return (NO_KEYBOARD); - } - /* End if */ - fp = fopen(filename, "r"); - - if (!fp) { - return (NO_KEYBOARD); - } - /* End if */ - linedata[0] = '\0'; - - if (!get_valid_line(fp, linedata, line_size)) { - fclose(fp); - return (NO_KEYBOARD); - } - /* End if */ - keyb = g_new0_(KEYBOARD, 1); - keyb->modmap = ModmapTable_new(); - - tofree = g_strsplit(linedata, " ", -1); - tokens = tofree; - - keyb->keycount = 0; - keyb->trans = g_new_(KeyboardTranslation, 1); - - /* Initialize it's various elements */ - keyb->trans->shift = keyb->trans->backspace = keyb->trans->space = - keyb->trans->caps_lock = keyb->trans->control = - keyb->trans->tab = keyb->trans->alt = keyb->trans->alt_gr = - (char *) NULL; - - for (x = 0; x < MAXIMUM_ROWS; x++) { - if (*tokens) - ptr = *tokens++; - else - ptr = NULL; - - if (ptr) - keyb->row_values[x] = atoi(ptr); - else { - *tokens = NULL; - keyb->row_values[x] = 0; - } /* End else */ - - keyb->keycount += keyb->row_values[x]; - } /* End for */ - - g_strfreev(tofree); - tofree = tokens = NULL; - ptr = NULL; - - /* We now know how many keys we have to allocate, how many lines to read, - * and all that good stuff. - * - * Each key must have 3 syms, (lower case, upper case, and Alt Gr) - * So allocate 3*keyb->keycount items, and read keyb->keycount lines. - */ - keyb->syms = g_new0_(KeySym, (3 * keyb->keycount)); - keyb->codes = g_new0_(KeyCode, keyb->keycount); - keyb->name = g_strdup_(filename); /* Save the name of the keyboard */ - - for (x = 0; x < keyb->keycount; x++) { - keyb->codes[x] = 0; /* Initialize that keycode since we're already - * paying the price of the loop and it needs - * to be done. - */ - - if (!get_valid_line(fp, linedata, line_size)) { - fprintf(stderr, - "Error reading file %s: Bad line %d.\n", - filename, (x + 1)); - fflush(stderr); - fflush(stderr); - keyb = gtkeyboard_destroy_keyboard(keyb); - fclose(fp); - return (NO_KEYBOARD); - } - /* End if */ - tokens = tofree = g_strsplit(linedata, " ", -1); - - for (y = 0; y < 3; y++) { - if (*tokens) - ptr = *tokens++; - else - ptr = NULL; - - index = (x * 3) + y; - - if (ptr) { - /* Translate a string into a KeySym */ - keyb->syms[index] = XStringToKeysym(ptr); - - /* Error check that KeySym */ - if (!keyb->syms[index] - || keyb->syms[index] == NoSymbol) { - keyb->syms[index] = NoSymbol; - keyb = - gtkeyboard_destroy_keyboard - (keyb); - return (NO_KEYBOARD); - } /* End if */ - } /* End if */ - else { - /* This kinda sucks */ - keyb->syms[index] = NoSymbol; - } /* End else */ - } /* End for */ - - if (ptr) { - ptr = *tokens++; - } - - /* End if */ - /* Grab the KeyCode if it's there */ - keyb->codes[x] = atoi(ptr ? ptr : "0"); - - if (ptr) { - ptr = *tokens++; - } - /* End if */ - if (ptr && strcmp(ptr, "") != 0) { -#if 0 - fprintf(Q, "Reading proposed mask \"%s\"\n", ptr); - fflush(Q); -#endif - - if (!ModmapTable_insert - (keyb->modmap, keyb->codes[x], - mask_name_to_slot_number(ptr))) { - fprintf(Q, - "*** Warning: Failed to insert %d into %d\n", - keyb->codes[x], - mask_name_to_slot_number(ptr)); - } - /* End if */ -#if 0 - fprintf(Q, "Inserted code %d in slot %d\n", - keyb->codes[x], - mask_name_to_slot_number(ptr)); - fflush(Q); -#endif - } - /* End if */ - g_strfreev(tofree); - } /* End for */ - - fclose(fp); - - return (keyb); -} /* End read_keyboard_template() */ - -static void send_redirect_a_keysym(KeySym input) -{ - Window window; - int revert_to; - - if (!options.other || options.other == (Window) NULL) { - /* SEND_TO_BOTH_WINDOWS was probably set and there wasn't - * a redirect window to send to. Let's save the time involved - * with doing all this string crap and just jump out here. - */ - return; - } - /* End if */ - if (options.other) { - /* send to window user picked */ - keysym_sendkey(input, options.other); - } /* End if */ - else { - /* default to just send the event to whatever window has the input - * focus - */ - XGetInputFocus(GDK_DISPLAY(), &window, &revert_to); - keysym_sendkey(input, window); - } /* End else */ -} /* End send_redirect_a_keysym() */ - -gint track_focus(gpointer data) -{ - Window winFocus; - Window wfcopy; - int revert_to_return; - char *winName; - - - /* find out which window currently has focus */ - XGetInputFocus(GDK_DISPLAY(), &winFocus, &revert_to_return); - wfcopy = winFocus; - - /* Return if the window is the same or if it's the program - * window or if we can't redirect to that window. - * - * If there was a previous window that was any good, stick to - * that one. - */ - if (winFocus == options.redirect_window || - winFocus == GUI.xwindow || - winFocus == None || winFocus == PointerRoot) { - return TRUE; - } - - - - /* End if */ - /* At this point, we know the window is "good" and that we want - * it's name. We're going to use it as the redirect from now on. - */ - /* set up error trapping, in case we get a BadWindow error */ - gdk_error_trap_push(); - - /* this could generate the error */ - XFetchName(GDK_DISPLAY(), winFocus, &winName); - if (!winName) - winName = "Unknown"; - - gdk_flush(); - - if (gdk_error_trap_pop()) { - /* Oops...error. Probably BadWindow */ - CONDFREE(options.redirect_window_name); - - options.redirect_window = None; /* reset focus window */ - options.other = None; - - printf - ("There was an error finding a valid redirect window.\n"); - return TRUE; /* better luck next time */ - } - - /* End if */ - /* since we made it this far, update the window_name */ - if (winName) { - CONDFREE(options.redirect_window_name); - - /* Grab the window definition */ - options.redirect_window = wfcopy; - options.other = wfcopy; - - options.redirect_window_name = g_strdup_(winName); - } /* End if */ - return TRUE; -} /* End track_focus */ diff --git a/src/gui/gtk/gtkeyboard.h b/src/gui/gtk/gtkeyboard.h deleted file mode 100644 index fef9fa7a..00000000 --- a/src/gui/gtk/gtkeyboard.h +++ /dev/null @@ -1,3 +0,0 @@ -int init_keyboard_stuff(char *input); -GtkWidget *build_keyboard(GtkWidget * input, char *filename); -gint track_focus(gpointer data); diff --git a/src/gui/gtk/gui_gtk.h b/src/gui/gtk/gui_gtk.h index 6c7792f1..1b968ef5 100644 --- a/src/gui/gtk/gui_gtk.h +++ b/src/gui/gtk/gui_gtk.h @@ -1,5 +1,22 @@ +struct statusbar_methods; +struct menu_methods; +struct navit; -struct statusbar *gui_gtk_statusbar_new(GtkWidget **widget); -void gui_gtk_actions_new(struct container *co, GtkWidget **vbox); -struct container * gui_gtk_window(int x, int y, int scale); +struct gui_priv { + struct navit *nav; + GtkWidget *win; + GtkWidget *vbox; + GtkWidget *menubar; + GtkActionGroup *base_group; + GtkActionGroup *debug_group; + GtkActionGroup *dyn_group; + GtkUIManager *menu_manager; + void *statusbar; + int dyn_counter; +}; + +struct menu_priv *gui_gtk_menubar_new(struct gui_priv *gui, struct menu_methods *meth); +struct menu_priv *gui_gtk_toolbar_new(struct gui_priv *gui, struct menu_methods *meth); +struct statusbar_priv *gui_gtk_statusbar_new(struct gui_priv *gui, struct statusbar_methods *meth); +struct menu_priv *gui_gtk_popup_new(struct gui_priv *gui, struct menu_methods *meth); diff --git a/src/gui/gtk/gui_gtk_action.c b/src/gui/gtk/gui_gtk_action.c index b8386cbb..d1867be8 100644 --- a/src/gui/gtk/gui_gtk_action.c +++ b/src/gui/gtk/gui_gtk_action.c @@ -1,69 +1,101 @@ #include <string.h> #include <gtk/gtk.h> +#include "navit.h" #include "graphics.h" #include "gui_gtk.h" -#include "container.h" #include "menu.h" -#include "data_window.h" #include "coord.h" -#include "destination.h" -struct action_gui { - struct container *co; +struct menu_priv { + char *path; + GtkAction *action; + struct gui_priv *gui; + enum menu_type type; + void (*callback)(struct menu *menu, void *data1, void *data2); + struct menu *callback_menu; + void *callback_data1; + void *callback_data2; + struct menu_priv *child; + struct menu_priv *sibling; + gulong handler_id; + guint merge_id; }; -#include "action.h" - - /* Create callbacks that implement our Actions */ static void -zoom_in_action(GtkWidget *w, struct action *ac) +zoom_in_action(GtkWidget *w, struct navit *nav, void *dummy) { - unsigned long scale; - graphics_get_view(ac->gui->co, NULL, NULL, &scale); - scale/=2; - if (scale < 1) - scale=1; - graphics_set_view(ac->gui->co, NULL, NULL, &scale); + navit_zoom_in(nav, 2); } static void -zoom_out_action(GtkWidget *w, struct action *ac) +zoom_out_action(GtkWidget *w, struct navit *nav, void *dummy) { - unsigned long scale; - graphics_get_view(ac->gui->co, NULL, NULL, &scale); - scale*=2; - graphics_set_view(ac->gui->co, NULL, NULL, &scale); + navit_zoom_out(nav, 2); } static void -refresh_action(GtkWidget *w, struct action *ac) +refresh_action(GtkWidget *w, struct navit *nav, void *dummy) { - menu_route_update(ac->gui->co); + navit_draw(nav); } static void -cursor_action(GtkWidget *w, struct action *ac) +cursor_action(GtkWidget *w, struct navit *nav, void *dummy) { + navit_toggle_cursor(nav); +#if 0 ac->gui->co->flags->track=gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w)); +#endif } static void -orient_north_action(GtkWidget *w, struct action *ac) +orient_north_action(GtkWidget *w, struct navit *nav, void *dummy) { +#if 0 ac->gui->co->flags->orient_north=gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w)); +#endif } +#include <stdlib.h> +#include "point.h" +#include "transform.h" + static void -destination_action(GtkWidget *w, struct action *ac) +info_action(GtkWidget *w, struct navit *nav, void *dummy) { - destination_address(ac->gui->co); + char buffer[512]; + int mw,mh; + struct coord lt, rb; + struct point p; + struct transformation *t; + + t=navit_get_trans(nav); + transform_get_size(t, &mw, &mh); + p.x=0; + p.y=0; + transform_reverse(t, &p, <); + p.x=mw; + p.y=mh; + transform_reverse(t, &p, &rb); + + sprintf(buffer,"./info.sh %d,%d 0x%x,0x%x 0x%x,0x%x", mw, mh, lt.x, lt.y, rb.x, rb.y); + system(buffer); + +} + + + +static void +destination_action(GtkWidget *w, struct navit *nav, void *dummy) +{ + destination_address(nav); } static void -quit_action (GtkWidget *w, struct action *ac) +quit_action (GtkWidget *w, struct navit *nav, void *dummy) { gtk_main_quit(); } @@ -71,36 +103,46 @@ quit_action (GtkWidget *w, struct action *ac) static void visible_blocks_action(GtkWidget *w, struct container *co) { +#if 0 co->data_window[data_window_type_block]=data_window("Visible Blocks",co->win,NULL); graphics_redraw(co); +#endif } static void visible_towns_action(GtkWidget *w, struct container *co) { +#if 0 co->data_window[data_window_type_town]=data_window("Visible Towns",co->win,NULL); graphics_redraw(co); +#endif } static void visible_polys_action(GtkWidget *w, struct container *co) { +#if 0 co->data_window[data_window_type_street]=data_window("Visible Polys",co->win,NULL); graphics_redraw(co); +#endif } static void visible_streets_action(GtkWidget *w, struct container *co) { +#if 0 co->data_window[data_window_type_street]=data_window("Visible Streets",co->win,NULL); graphics_redraw(co); +#endif } static void visible_points_action(GtkWidget *w, struct container *co) { +#if 0 co->data_window[data_window_type_point]=data_window("Visible Points",co->win,NULL); graphics_redraw(co); +#endif } @@ -108,10 +150,14 @@ static GtkActionEntry entries[] = { { "DisplayMenuAction", NULL, "Display" }, { "RouteMenuAction", NULL, "Route" }, + { "Map", NULL, "Map" }, + { "LayoutMenuAction", NULL, "Layout" }, { "ZoomOutAction", GTK_STOCK_ZOOM_OUT, "ZoomOut", NULL, NULL, G_CALLBACK(zoom_out_action) }, { "ZoomInAction", GTK_STOCK_ZOOM_IN, "ZoomIn", NULL, NULL, G_CALLBACK(zoom_in_action) }, { "RefreshAction", GTK_STOCK_REFRESH, "Refresh", NULL, NULL, G_CALLBACK(refresh_action) }, + { "InfoAction", GTK_STOCK_INFO, "Info", NULL, NULL, G_CALLBACK(info_action) }, { "DestinationAction", "flag_icon", "Destination", NULL, NULL, G_CALLBACK(destination_action) }, + { "Test", NULL, "Test", NULL, NULL, G_CALLBACK(destination_action) }, { "QuitAction", GTK_STOCK_QUIT, "_Quit", "<control>Q",NULL, G_CALLBACK (quit_action) } }; @@ -232,6 +278,7 @@ static struct { {"flag_icon", flag_xpm } }; + static gint n_stock_icons = G_N_ELEMENTS (stock_icons); @@ -259,17 +306,11 @@ register_my_stock_icons (void) g_object_unref(icon_factory); } -static void -action_add_widget (GtkUIManager *ui, GtkWidget *widget, GtkContainer *container) -{ - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - gtk_widget_show (widget); -} static char layout[] = "<ui>\ - <menubar>\ - <menu name=\"DisplayMenu\" action=\"DisplayMenuAction\">\ + <menubar name=\"MenuBar\">\ + <menu name=\"Display\" action=\"DisplayMenuAction\">\ <menuitem name=\"Zoom in\" action=\"ZoomInAction\" />\ <menuitem name=\"Zoom out\" action=\"ZoomOutAction\" />\ <menuitem name=\"Cursor\" action=\"CursorAction\"/>\ @@ -277,7 +318,7 @@ static char layout[] = <menuitem name=\"Quit\" action=\"QuitAction\" />\ <placeholder name=\"RouteMenuAdditions\" />\ </menu>\ - <menu name=\"DataMenu\" action=\"DataMenuAction\">\ + <menu name=\"Data\" action=\"DataMenuAction\">\ <menuitem name=\"Visible Blocks\" action=\"VisibleBlocksAction\" />\ <menuitem name=\"Visible Towns\" action=\"VisibleTownsAction\" />\ <menuitem name=\"Visible Polys\" action=\"VisiblePolysAction\" />\ @@ -285,13 +326,13 @@ static char layout[] = <menuitem name=\"Visible Points\" action=\"VisiblePointsAction\" />\ <placeholder name=\"DataMenuAdditions\" />\ </menu>\ - <menu name=\"RouteMenu\" action=\"RouteMenuAction\">\ + <menu name=\"Route\" action=\"RouteMenuAction\">\ <menuitem name=\"Refresh\" action=\"RefreshAction\" />\ <menuitem name=\"Destination\" action=\"DestinationAction\" />\ <placeholder name=\"RouteMenuAdditions\" />\ </menu>\ </menubar>\ - <toolbar action=\"BaseToolbar\" action=\"BaseToolbarAction\">\ + <toolbar name=\"ToolBar\" action=\"BaseToolbar\" action=\"BaseToolbarAction\">\ <placeholder name=\"ToolItems\">\ <separator/>\ <toolitem name=\"Zoom in\" action=\"ZoomInAction\"/>\ @@ -300,46 +341,170 @@ static char layout[] = <toolitem name=\"Cursor\" action=\"CursorAction\"/>\ <toolitem name=\"Orientation\" action=\"OrientationAction\"/>\ <toolitem name=\"Destination\" action=\"DestinationAction\"/>\ + <toolitem name=\"Info\" action=\"InfoAction\"/>\ <toolitem name=\"Quit\" action=\"QuitAction\"/>\ <separator/>\ </placeholder>\ </toolbar>\ + <popup name=\"PopUp\">\ + </popup>\ </ui>"; - + + +static void +activate(void *dummy, struct menu_priv *menu) +{ + if (menu->callback) + (*menu->callback)(menu->callback_menu, menu->callback_data1, menu->callback_data2); +} + +static struct menu_methods menu_methods; -void -gui_gtk_actions_new(struct container *co, GtkWidget **vbox) +static struct menu_priv * +add_menu(struct menu_priv *menu, struct menu_methods *meth, char *name, enum menu_type type, void (*callback)(struct menu *data_menu, void *data1, void *data2), struct menu *data_menu, void *data1, void *data2) { - GtkActionGroup *base_group,*debug_group; - GtkUIManager *menu_manager; - GError *error; + struct menu_priv *ret; + char *dynname; + + ret=g_new0(struct menu_priv, 1); + *meth=menu_methods; + if (! strcmp(menu->path, "/ui/MenuBar") && !strcmp(name,"Route")) { + dynname=g_strdup("Route"); + } else { + dynname=g_strdup_printf("%d", menu->gui->dyn_counter++); + if (type == menu_type_toggle) + ret->action=GTK_ACTION(gtk_toggle_action_new(dynname, name, NULL, NULL)); + else + ret->action=gtk_action_new(dynname, name, NULL, NULL); + if (callback) + ret->handler_id=g_signal_connect(ret->action, "activate", G_CALLBACK(activate), ret); + gtk_action_group_add_action(menu->gui->dyn_group, ret->action); + ret->merge_id=gtk_ui_manager_new_merge_id(menu->gui->menu_manager); + gtk_ui_manager_add_ui( menu->gui->menu_manager, ret->merge_id, menu->path, dynname, dynname, type == menu_type_submenu ? GTK_UI_MANAGER_MENU : GTK_UI_MANAGER_MENUITEM, FALSE); + } + ret->gui=menu->gui; + ret->path=g_strdup_printf("%s/%s", menu->path, dynname); + ret->type=type; + ret->callback=callback; + ret->callback_menu=data_menu; + ret->callback_data1=data1; + ret->callback_data2=data2; + ret->sibling=menu->child; + menu->child=ret; + g_free(dynname); + return ret; + +} - struct action *this=g_new0(struct action, 1); +static void +remove_menu(struct menu_priv *item, int recursive) +{ - this->gui=g_new0(struct action_gui, 1); - this->gui->co=co; + if (recursive) { + struct menu_priv *next,*child=item->child; + while (child) { + next=child->sibling; + remove_menu(child, recursive); + child=next; + } + } + if (item->action) { + gtk_ui_manager_remove_ui(item->gui->menu_manager, item->merge_id); + gtk_action_group_remove_action(item->gui->dyn_group, item->action); +#if 0 + if (item->callback) + g_signal_handler_disconnect(item->action, item->handler_id); +#endif + g_object_unref(item->action); + } + g_free(item->path); + g_free(item); +} - register_my_stock_icons(); +static void +set_toggle(struct menu_priv *menu, int active) +{ + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(menu->action), active); +} - base_group = gtk_action_group_new ("BaseActions"); - debug_group = gtk_action_group_new ("DebugActions"); - menu_manager = gtk_ui_manager_new (); +static int +get_toggle(struct menu_priv *menu) +{ + return gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(menu->action)); +} - gtk_action_group_add_actions (base_group, entries, n_entries, this); - gtk_action_group_add_toggle_actions (base_group, toggleentries, n_toggleentries, this); - gtk_ui_manager_insert_action_group (menu_manager, base_group, 0); +static struct menu_methods menu_methods = { + add_menu, + set_toggle, + get_toggle, +}; - gtk_action_group_add_actions (debug_group, debug_entries, n_debug_entries, co); - gtk_ui_manager_insert_action_group (menu_manager, debug_group, 0); - error = NULL; - gtk_ui_manager_add_ui_from_string (menu_manager, layout, strlen(layout), &error); +static void +popup_deactivate(GtkWidget *widget, struct menu_priv *menu) +{ + g_signal_handler_disconnect(widget, menu->handler_id); + remove_menu(menu, 1); +} - if (error) { - g_message ("building menus failed: %s", error->message); - g_error_free (error); +static struct menu_priv * +gui_gtk_ui_new (struct gui_priv *this, struct menu_methods *meth, char *path, int popup, GtkWidget **widget_ret) +{ + struct menu_priv *ret; + GError *error; + GtkWidget *widget; + + *meth=menu_methods; + ret=g_new0(struct menu_priv, 1); + ret->path=g_strdup(path); + ret->gui=this; + if (! this->menu_manager) { + this->base_group = gtk_action_group_new ("BaseActions"); + this->debug_group = gtk_action_group_new ("DebugActions"); + this->dyn_group = gtk_action_group_new ("DynamicActions"); + register_my_stock_icons(); + this->menu_manager = gtk_ui_manager_new (); + gtk_action_group_add_actions (this->base_group, entries, n_entries, this->nav); + gtk_action_group_add_toggle_actions (this->base_group, toggleentries, n_toggleentries, this->nav); + gtk_ui_manager_insert_action_group (this->menu_manager, this->base_group, 0); + gtk_action_group_add_actions (this->debug_group, debug_entries, n_debug_entries, this->nav); + gtk_ui_manager_insert_action_group (this->menu_manager, this->debug_group, 0); + gtk_ui_manager_add_ui_from_string (this->menu_manager, layout, strlen(layout), &error); + gtk_ui_manager_insert_action_group (this->menu_manager, this->dyn_group, 0); + error=NULL; + if (error) { + g_message ("building menus failed: %s", error->message); + g_error_free (error); + } + } + widget=gtk_ui_manager_get_widget(this->menu_manager, path); + GTK_WIDGET_UNSET_FLAGS (widget, GTK_CAN_FOCUS); + if (widget_ret) + *widget_ret=widget; + if (! popup) { + gtk_box_pack_start (GTK_BOX(this->vbox), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + } else { + gtk_menu_popup(GTK_MENU(widget), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time ()); + ret->handler_id=g_signal_connect(widget, "deactivate", G_CALLBACK(popup_deactivate), ret); } + return ret; +} + +struct menu_priv * +gui_gtk_toolbar_new(struct gui_priv *this, struct menu_methods *meth) +{ + return gui_gtk_ui_new(this, meth, "/ui/ToolBar", 0, NULL); +} - g_signal_connect ( menu_manager, "add_widget", G_CALLBACK (action_add_widget), *vbox); +struct menu_priv * +gui_gtk_menubar_new(struct gui_priv *this, struct menu_methods *meth) +{ + return gui_gtk_ui_new(this, meth, "/ui/MenuBar", 0, &this->menubar); } +struct menu_priv * +gui_gtk_popup_new(struct gui_priv *this, struct menu_methods *meth) +{ + return gui_gtk_ui_new(this, meth, "/ui/PopUp", 1, NULL); +} diff --git a/src/gui/gtk/gui_gtk_menu.c b/src/gui/gtk/gui_gtk_menu.c deleted file mode 100644 index 6f6b22b2..00000000 --- a/src/gui/gtk/gui_gtk_menu.c +++ /dev/null @@ -1,364 +0,0 @@ -#define GTK_ENABLE_BROKEN -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <math.h> -#include <time.h> -#include <gtk/gtk.h> -#include "coord.h" -#include "graphics.h" -#include "data_window.h" -#include "route.h" -#include "cursor.h" -#include "command.h" -#include "transform.h" -#include "block.h" -#include "street.h" -#include "statusbar.h" -#include "destination.h" -#include "main.h" -#include "container.h" -#include "gui_gtk.h" - -struct menu_gui { - struct container *co; -}; - -#include "menu.h" - -extern struct coord current_pos; - -extern struct data_window *navigation_window; - -struct destination { - struct container *co; - char *text; - struct coord pos; -}; - -static void -menu_window_clone(struct container *co) -{ -#if 0 - void window(int x, int y, int scale); - window(co->trans->center.x, co->trans->center.y, co->trans->scale); -#endif -} - -static gboolean -menu_window_command_key_press(GtkWidget *widget, GdkEventKey *event, - GtkWidget *win) -{ - GtkWidget *text; - const char *t; - struct container *co; - - if (! strcmp(event->string,"\r")) { - text=g_object_get_data(G_OBJECT(win), "Input"); - co=g_object_get_data(G_OBJECT(win), "Container"); - t=gtk_entry_get_text(GTK_ENTRY(text)); - if (!strncmp(t,"goto ",5)) { - command_goto(co, t+5); - } - } - return TRUE; -} - - -static void -menu_window_command(struct container *co) -{ - GtkWidget *win,*entry,*text,*box; - win=gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_default_size(GTK_WINDOW(win), 320, 200); - gtk_window_set_title(GTK_WINDOW(win), "Command"); - entry=gtk_entry_new(); - text=gtk_text_new(NULL, NULL); - box=gtk_vbox_new(FALSE, 0); - gtk_box_pack_start(GTK_BOX(box), entry, 1, 1, 0); - gtk_box_pack_start(GTK_BOX(box), text, 1, 1, 0); - gtk_container_add(GTK_CONTAINER(win), box); - g_object_set_data(G_OBJECT(win), "Container", co); - g_object_set_data(G_OBJECT(win), "Input", entry); - g_object_set_data(G_OBJECT(win), "Output", text); - g_signal_connect(G_OBJECT(win), "key-press-event", G_CALLBACK(menu_window_command_key_press), win); - gtk_widget_show_all(win); -} - -static void -menu_window_visible_blocks(struct container *co) -{ - co->data_window[data_window_type_block]=data_window("Visible Blocks",co->win,NULL); - graphics_redraw(co); -} - -static void -menu_window_visible_towns(struct container *co) -{ - co->data_window[data_window_type_town]=data_window("Visible Towns",co->win,NULL); - graphics_redraw(co); -} - -static void -menu_window_visible_polys(struct container *co) -{ - co->data_window[data_window_type_street]=data_window("Visible Polys",co->win,NULL); - graphics_redraw(co); -} - -static void -menu_window_visible_streets(struct container *co) -{ - co->data_window[data_window_type_street]=data_window("Visible Streets",co->win,NULL); - graphics_redraw(co); -} - -static void -menu_window_visible_points(struct container *co) -{ - co->data_window[data_window_type_point]=data_window("Visible Points",co->win,NULL); - graphics_redraw(co); -} - -static void -menu_map_compare(struct container *co) -{ - char cmd[256]; - int x_min, x_max, y_min, y_max; - - x_min=co->trans->center.x-co->trans->scale/16*co->trans->width*4/10; - x_max=co->trans->center.x+co->trans->scale/16*co->trans->width*4/10; - y_min=co->trans->center.y-co->trans->scale/16*co->trans->height*4/10; - y_max=co->trans->center.y+co->trans->scale/16*co->trans->height*4/10; - sprintf(cmd, "./get_map %d %d %d %d %d %d ; xv map.xpm &", co->trans->width, co->trans->height, x_min, y_max, x_max, y_min); - system(cmd); -} - -static void -menu_map_distances(struct container *co) -{ - route_display_points(co->route, co); -} - -static void -menu_destination_selected(GtkMenuItem *item, struct destination *dest) -{ - struct container *co =dest->co; - - destination_set(co, destination_type_bookmark, dest->text, &dest->pos); -} - -static void -menu_item(struct menu *me, GtkWidget *menu, char *name, void (*func)(struct container *co)) -{ - GtkWidget *item; - item=gtk_menu_item_new_with_label(name); - gtk_menu_shell_append (GTK_MENU_SHELL(menu), item); - g_signal_connect_swapped(G_OBJECT(item), "activate", - G_CALLBACK(func), me); -} - -static int -menu_clock_update(void *data) -{ - char buffer[16]; - time_t now=time(NULL); - GtkWidget *widget=GTK_WIDGET(data); - struct tm *now_tm=localtime(&now); - - sprintf(buffer,"%02d:%02d", now_tm->tm_hour, now_tm->tm_min); - gtk_label_set_text(GTK_LABEL(widget), buffer); - g_timeout_add((60-now_tm->tm_sec)*1000,menu_clock_update,widget); - return FALSE; -} - -struct menu * -gui_gtk_menu_new(struct container *co, GtkWidget **widget) -{ - struct menu *this=g_new0(struct menu, 1); - - this->gui=g_new0(struct menu_gui,1); - this->gui->co=co; - - - GtkWidget *menu,*item,*menu2,*item2,*menu3,*clock; - - menu=gtk_menu_bar_new(); - item=gtk_menu_item_new_with_label("Goto"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - { - menu2=gtk_menu_new(); - } - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu2); - - item=gtk_menu_item_new_with_label("Window"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - { - menu2=gtk_menu_new(); - - item2=gtk_menu_item_new_with_label("Clone"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - g_signal_connect_swapped(G_OBJECT(item2), "activate", - G_CALLBACK (menu_window_clone), this); - - item2=gtk_menu_item_new_with_label("Command"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - g_signal_connect_swapped(G_OBJECT(item2), "activate", - G_CALLBACK (menu_window_command), this); - - item2=gtk_menu_item_new_with_label("Visible Blocks"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - g_signal_connect_swapped(G_OBJECT(item2), "activate", - G_CALLBACK (menu_window_visible_blocks), co); - - item2=gtk_menu_item_new_with_label("Visible Towns"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - g_signal_connect_swapped(G_OBJECT(item2), "activate", - G_CALLBACK (menu_window_visible_towns), co); - - item2=gtk_menu_item_new_with_label("Visible Polys"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - g_signal_connect_swapped(G_OBJECT(item2), "activate", - G_CALLBACK (menu_window_visible_polys), co); - - - item2=gtk_menu_item_new_with_label("Visible Streets"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - g_signal_connect_swapped(G_OBJECT(item2), "activate", - G_CALLBACK (menu_window_visible_streets), co); - - menu_item(this, menu2, "Visible Points", menu_window_visible_points); - - item2=gtk_menu_item_new_with_label("Exit"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - g_signal_connect_swapped(G_OBJECT(item2), "activate", - G_CALLBACK (exit), this); - } - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu2); - - item=gtk_menu_item_new_with_label("Map"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - { - menu2=gtk_menu_new(); - - item2=gtk_menu_item_new_with_label("Compare"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - g_signal_connect_swapped(G_OBJECT(item2), "activate", - G_CALLBACK (menu_map_compare), this); - - item2=gtk_menu_item_new_with_label("Distances"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - g_signal_connect_swapped(G_OBJECT(item2), "activate", - G_CALLBACK (menu_map_distances), this); - } - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu2); - - item=gtk_menu_item_new_with_label("Route"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - { - menu2=gtk_menu_new(); - - item2=gtk_menu_item_new_with_label("Start"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - g_signal_connect_swapped(G_OBJECT(item2), "activate", - G_CALLBACK (route_start), co); - - item2=gtk_menu_item_new_with_label("Trace"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - g_signal_connect_swapped(G_OBJECT(item2), "activate", - G_CALLBACK (route_trace), co); - - item2=gtk_menu_item_new_with_label("Update"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - g_signal_connect_swapped(G_OBJECT(item2), "activate", - G_CALLBACK (menu_route_update), this); - } - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu2); - - item=gtk_menu_item_new_with_label("Destinations"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - menu2=gtk_menu_new(); - - item2=gtk_menu_item_new_with_label("Last Destinations"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - menu3=gtk_menu_new(); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item2), menu3); - - item2=gtk_menu_item_new_with_label("Address"); - gtk_menu_shell_append (GTK_MENU_SHELL(menu2), item2); - - { - FILE *file; - char buffer[8192]; - double lat,lng,lat_deg,lng_deg; - char lat_c,lng_c; - struct destination *dest; - int pos,len; - char *utf8,*text,*tok,*label; - GList *list; - - file=fopen("locations.txt","r"); - while (file && fgets(buffer,8192,file)) { - dest=g_new0(struct destination,1); - dest->co=co; - len=strlen(buffer)-1; - while (len >= 0 && buffer[len] == '\n') { - buffer[len]='\0'; - } - sscanf(buffer,"%lf %c %lf %c %n",&lat, &lat_c, &lng, &lng_c, &pos); - - lat_deg=floor(lat/100); - lat-=lat_deg*100; - lat_deg+=lat/60; - - lng_deg=floor(lng/100); - lng-=lng_deg*100; - lng_deg+=lng/60; - - transform_mercator(&lng_deg, &lat_deg, &dest->pos); - - text=buffer+pos; - dest->text=strdup(text); - item2=NULL; - menu3=menu2; - while ((tok=strtok(text,"/"))) { - list=NULL; - if (item2) { - menu3=gtk_menu_new(); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item2), menu3); - } - list=gtk_container_get_children(GTK_CONTAINER(menu3)); - while (list) { - item2=GTK_WIDGET(list->data); - label=g_strdup(gtk_label_get_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(item2))))); - if (!strcmp(label, tok)) { - menu3=gtk_menu_item_get_submenu(GTK_MENU_ITEM(item2)); - break; - } - list=list->next; - } - item2=NULL; - if (! list) { - utf8=g_locale_to_utf8(tok,-1,NULL,NULL,NULL); - item2=gtk_menu_item_new_with_label(utf8); - gtk_menu_shell_append (GTK_MENU_SHELL(menu3), item2); - g_free(utf8); - } - text=NULL; - } - g_signal_connect(G_OBJECT(item2), "activate", - G_CALLBACK (menu_destination_selected), dest); - } - } - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu2); - - item=gtk_menu_item_new(); - clock=gtk_label_new(NULL); - gtk_menu_item_set_right_justified(GTK_MENU_ITEM(item),TRUE); - gtk_container_add(GTK_CONTAINER(item), clock); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - menu_clock_update(clock); - - *widget=menu; - return this; -} diff --git a/src/gui/gtk/gui_gtk_statusbar.c b/src/gui/gtk/gui_gtk_statusbar.c index 10950298..b31b8dd3 100644 --- a/src/gui/gtk/gui_gtk_statusbar.c +++ b/src/gui/gtk/gui_gtk_statusbar.c @@ -10,7 +10,8 @@ #include "statusbar.h" -struct statusbar_gui { +struct statusbar_priv { + struct gui_priv *gui; GtkWidget *hbox; char mouse_text[128]; GtkWidget *mouse; @@ -22,15 +23,15 @@ struct statusbar_gui { static void -statusbar_destroy(struct statusbar *this) +statusbar_destroy(struct statusbar_priv *this) { - g_free(this->gui); g_free(this); } static void -statusbar_mouse_update(struct statusbar *this, struct transformation *tr, struct point *p) +statusbar_mouse_update(struct statusbar_priv *this, struct transformation *tr, struct point *p) { +#if 0 struct coord c; struct coord_geo g; char buffer[128]; @@ -38,12 +39,13 @@ statusbar_mouse_update(struct statusbar *this, struct transformation *tr, struct transform_reverse(tr, p, &c); transform_lng_lat(&c, &g); transform_geo_text(&g, buffer); - sprintf(this->gui->mouse_text,"M: %s", buffer); - gtk_label_set_text(GTK_LABEL(this->gui->mouse), this->gui->mouse_text); + sprintf(this->mouse_text,"M: %s", buffer); + gtk_label_set_text(GTK_LABEL(this->mouse), this->mouse_text); +#endif } static void -statusbar_gps_update(struct statusbar *this, int sats, int qual, double lng, double lat, double height, double direction, double speed) +statusbar_gps_update(struct statusbar_priv *this, int sats, int qual, double lng, double lat, double height, double direction, double speed) { char lat_c='N'; char lng_c='E'; @@ -62,54 +64,66 @@ statusbar_gps_update(struct statusbar *this, int sats, int qual, double lng, dou } dir_idx=(direction+22.5)/45; dir=dirs[dir_idx]; - sprintf(this->gui->gps_text,"GPS %2d/%1d %02.0f%07.4f%c %03.0f%07.4f%c %4.0fm %3.0f°%-2s %3.0fkm/h", sats, qual, floor(lat), fmod(lat*60,60), lat_c, floor(lng), fmod(lng*60,60), lng_c, height, direction, dir, speed); - utf8=g_locale_to_utf8(this->gui->gps_text,-1,NULL,NULL,NULL); - gtk_label_set_text(GTK_LABEL(this->gui->gps), utf8); + sprintf(this->gps_text,"GPS %2d/%1d %02.0f%07.4f%c %03.0f%07.4f%c %4.0fm %3.0f°%-2s %3.0fkm/h", sats, qual, floor(lat), fmod(lat*60,60), lat_c, floor(lng), fmod(lng*60,60), lng_c, height, direction, dir, speed); + utf8=g_locale_to_utf8(this->gps_text,-1,NULL,NULL,NULL); + gtk_label_set_text(GTK_LABEL(this->gps), utf8); g_free(utf8); } static void -statusbar_route_update(struct statusbar *this, struct route *route) +statusbar_route_update(struct statusbar_priv *this, struct route *route) { +#if 0 /* FIXME */ struct tm *eta_tm; double route_len; eta_tm=route_get_eta(route); route_len=route_get_len(route); - sprintf(this->gui->route_text,"Route %4.0fkm %02d:%02d ETA",route_len/1000, eta_tm->tm_hour, eta_tm->tm_min); - gtk_label_set_text(GTK_LABEL(this->gui->route), this->gui->route_text); + sprintf(this->route_text,"Route %4.0fkm %02d:%02d ETA",route_len/1000, eta_tm->tm_hour, eta_tm->tm_min); + gtk_label_set_text(GTK_LABEL(this->route), this->route_text); +#endif } -struct statusbar * -gui_gtk_statusbar_new(GtkWidget **widget) +static struct statusbar_methods methods = { + statusbar_destroy, + statusbar_mouse_update, + statusbar_route_update, + statusbar_gps_update, +}; + +struct statusbar_priv * +gui_gtk_statusbar_new(struct gui_priv *gui, struct statusbar_methods *meth) { - struct statusbar *this=g_new0(struct statusbar, 1); + struct statusbar_priv *this=g_new0(struct statusbar_priv, 1); char *utf8; - this->gui=g_new0(struct statusbar_gui,1); - this->statusbar_destroy=statusbar_destroy; - this->statusbar_mouse_update=statusbar_mouse_update; - this->statusbar_route_update=statusbar_route_update; - this->statusbar_gps_update=statusbar_gps_update; + this->gui=gui; + *meth=methods; - this->gui->hbox=gtk_hbox_new(FALSE, 1); - this->gui->mouse=gtk_label_new("M: 0000.0000N 00000.0000E"); - gtk_label_set_justify(GTK_LABEL(this->gui->mouse), GTK_JUSTIFY_LEFT); + this->hbox=gtk_hbox_new(FALSE, 1); + this->mouse=gtk_label_new("M: 0000.0000N 00000.0000E"); + gtk_label_set_justify(GTK_LABEL(this->mouse), GTK_JUSTIFY_LEFT); utf8=g_locale_to_utf8("GPS 00/0 0000.0000N 00000.0000E 0000m 000°NO 000km/h",-1,NULL,NULL,NULL); - this->gui->gps=gtk_label_new(utf8); + this->gps=gtk_label_new(utf8); g_free(utf8); - gtk_label_set_justify(GTK_LABEL(this->gui->gps), GTK_JUSTIFY_LEFT); - this->gui->route=gtk_label_new("Route 0000km 0+00:00 ETA"); - gtk_label_set_justify(GTK_LABEL(this->gui->route), GTK_JUSTIFY_LEFT); - gtk_box_pack_start(GTK_BOX(this->gui->hbox), this->gui->mouse, FALSE, FALSE, 2); - gtk_box_pack_start(GTK_BOX(this->gui->hbox), gtk_vseparator_new(), TRUE, TRUE, 2); - gtk_box_pack_start(GTK_BOX(this->gui->hbox), this->gui->gps, TRUE, TRUE, 2); - gtk_box_pack_start(GTK_BOX(this->gui->hbox), gtk_vseparator_new(), TRUE, TRUE, 2); - gtk_box_pack_start(GTK_BOX(this->gui->hbox), this->gui->route, TRUE, TRUE, 2); + gtk_label_set_justify(GTK_LABEL(this->gps), GTK_JUSTIFY_LEFT); + this->route=gtk_label_new("Route 0000km 0+00:00 ETA"); + gtk_label_set_justify(GTK_LABEL(this->route), GTK_JUSTIFY_LEFT); + gtk_box_pack_start(GTK_BOX(this->hbox), this->mouse, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(this->hbox), gtk_vseparator_new(), TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(this->hbox), this->gps, TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(this->hbox), gtk_vseparator_new(), TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(this->hbox), this->route, TRUE, TRUE, 2); + GTK_WIDGET_UNSET_FLAGS (this->hbox, GTK_CAN_FOCUS); + + gtk_box_pack_end(GTK_BOX(gui->vbox), this->hbox, FALSE, FALSE, 0); + gtk_widget_show_all(this->hbox); +#if 0 *widget=this->gui->hbox; +#endif return this; } diff --git a/src/gui/gtk/gui_gtk_toolbar.c b/src/gui/gtk/gui_gtk_toolbar.c deleted file mode 100644 index ec27b746..00000000 --- a/src/gui/gtk/gui_gtk_toolbar.c +++ /dev/null @@ -1,340 +0,0 @@ -#include <gtk/gtk.h> -#include "graphics.h" -#include "gui_gtk.h" -#include "menu.h" -#include "coord.h" -#include "destination.h" -#include "container.h" - -struct toolbar_gui { - struct container *co; -}; - -#include "toolbar.h" - -static void -zoom_in(GtkWidget *w, struct toolbar *tb) -{ - unsigned long scale; - graphics_get_view(tb->gui->co, NULL, NULL, &scale); - scale/=2; - if (scale < 1) - scale=1; - graphics_set_view(tb->gui->co, NULL, NULL, &scale); -} - -static void -zoom_out(GtkWidget *w, struct toolbar *tb) -{ - unsigned long scale; - graphics_get_view(tb->gui->co, NULL, NULL, &scale); - scale*=2; - graphics_set_view(tb->gui->co, NULL, NULL, &scale); -} - -static void -refresh_route(GtkWidget *w, struct toolbar *tb) -{ - menu_route_update(tb->gui->co); -} - -static void -track(GtkWidget *w, struct toolbar *tb) -{ - if (tb->gui->co->flags->track) { - tb->gui->co->flags->track=0; - gtk_widget_set_state(w, GTK_STATE_ACTIVE); - } else { - tb->gui->co->flags->track=1; - gtk_widget_set_state(w, GTK_STATE_ACTIVE); - } -} - -static void -orient_north(GtkWidget *w, struct toolbar *tb) -{ - if (tb->gui->co->flags->orient_north) { - tb->gui->co->flags->orient_north=0; - gtk_widget_set_state(w, GTK_STATE_ACTIVE); - } else { - tb->gui->co->flags->orient_north=1; - gtk_widget_set_state(w, GTK_STATE_ACTIVE); - } -} - -static void -destination(GtkWidget *w, struct toolbar *tb) -{ - destination_address(tb->gui->co); -} - - -/* XPM */ -/* Drawn by Mark Donohoe for the K Desktop Environment */ -/* See http://www.kde.org */ -static char*viewmag_plus_xpm[]={ -"22 22 5 1", -"# c #000000", -"c c #a0a0a4", -"a c #dcdcdc", -"b c #ffffff", -". c None", -"......................", -"......................", -"......................", -"......................", -"......................", -".......####...........", -"......#abba#..........", -".....#abcbba#.........", -".....#bcbbbb#.........", -".....#bbbbbb#.........", -".....#abbbba#.........", -"......#abba##.........", -".......#######........", -"............###.......", -".....#.......###......", -".....#........###.....", -"...#####.......##.....", -".....#................", -".....#................", -"......................", -"......................", -"......................"}; - - -/* XPM */ -/* Drawn by Mark Donohoe for the K Desktop Environment */ -/* See http://www.kde.org */ -static char*viewmag_minus_xpm[]={ -"22 22 5 1", -"# c #000000", -"c c #a0a0a4", -"a c #dcdcdc", -"b c #ffffff", -". c None", -"......................", -"......................", -"......................", -"......................", -"......................", -".......####...........", -"......#abba#..........", -".....#abcbba#.........", -".....#bcbbbb#.........", -".....#bbbbbb#.........", -".....#abbbba#.........", -"......#abba##.........", -".......#######........", -"............###.......", -".............###......", -"..............###.....", -"...#####.......##.....", -"......................", -"......................", -"......................", -"......................", -"......................"}; - - -/* XPM */ -/* Drawn by Mark Donohoe for the K Desktop Environment */ -/* See http://www.kde.org */ -static char*reload_xpm[]={ -"22 22 3 1", -"# c #808080", -"a c #000000", -". c None", -"......................", -"......................", -"......................", -"......................", -"........##aaa#........", -".......#aaaaaaa.......", -"......#aa#....#a......", -"......aa#.............", -".....aaa.......a......", -"...aaaaaaa....aaa.....", -"....aaaaa....aaaaa....", -".....aaa....aaaaaaa...", -"......a.......aaa.....", -".............#aa......", -"......a#....#aa#......", -".......aaaaaaa#.......", -"........#aaa##........", -"......................", -"......................", -"......................", -"......................", -"......................"}; - - -/* XPM */ -static char * cursor_xpm[] = { -"22 22 2 1", -" c None", -". c #0000FF", -" ", -" ", -" ", -" .. ", -" .. .. ", -" .. .. ", -" . . ", -" . . ", -" . ... . ", -" . ... . . ", -" . ... . . ", -" . .. . . ", -" . . . ", -" . . . ", -" . . . ", -" . . . ", -" .. .. ", -" .. .. ", -" .. ", -" ", -" ", -" "}; - - -/* XPM */ -static char * north_xpm[] = { -"22 22 2 1", -" c None", -". c #000000", -" ", -" ", -" . ", -" ... ", -" . . . ", -" . . . ", -" . ", -" .... . .... ", -" .... . .... ", -" .... . .. ", -" .. .. .. ", -" .. .. .. ", -" .. .. .. ", -" .. .. .. ", -" .. . .... ", -" .... . .... ", -" .... . .... ", -" . ", -" . ", -" . ", -" ", -" "}; - - -/* XPM */ -static char * flag_xpm[] = { -"22 22 2 1", -" c None", -"+ c #000000", -"+++++++ ", -"+ +++++++++ ", -"+ +++ +++++++++ ", -"+ +++ +++ +++ ", -"++++ +++ +++ ", -"++++ +++ +++ ", -"++++ +++ +++ + ", -"+ ++++++ +++ + ", -"+ +++ ++++++ + ", -"+ +++ +++ +++ ", -"++++ +++ +++ ", -"++++ +++ +++ ", -"++++++++++ +++ + ", -"+ +++++++++ + ", -"+ ++++++ ", -"+ ", -"+ ", -"+ ", -"+ ", -"+ ", -"+ ", -"+ "}; - -static GtkWidget * -xpm_to_widget(GtkWidget *draw, gchar **xpm_data) -{ - /* GtkWidget is the storage type for widgets */ - GtkWidget *imagewid; - GdkPixmap *pixmap; - GdkBitmap *mask; - GtkStyle *style; - - style = gtk_widget_get_style(draw); - - /* In order for this to not create a warning, window has to be a - * gtk_realize_widget (realized) widget - */ - pixmap = gdk_pixmap_create_from_xpm_d(draw->window, &mask, - &style->bg[GTK_STATE_NORMAL], - (gchar **)xpm_data ); - - /* a pixmap widget to contain the pixmap */ - imagewid = gtk_image_new_from_pixmap(pixmap, mask); - gtk_widget_show(imagewid); - - return(imagewid); -} - -int tst_stat=1; - -static void -toolbar_button(GtkWidget *window, GtkWidget *toolbar, char **icon_data, char *text, void (*func)(GtkWidget *w, struct toolbar *tb), void *data) -{ - GtkWidget *icon; - GtkToolItem *toolitem; - - icon=xpm_to_widget(window, icon_data); - toolitem=gtk_tool_button_new(icon,text); - gtk_toolbar_insert(GTK_TOOLBAR(toolbar),toolitem,-1); - g_signal_connect(G_OBJECT(toolitem), "clicked", G_CALLBACK(func), data); -} - -static void -toolbar_button_toggle(GtkWidget *window, GtkWidget *toolbar, char **icon_data, char *text, void (*func)(GtkWidget *w, struct toolbar *tb), void *data, int *flag) -{ - GtkWidget *icon; - GtkToolItem *toggleitem; - - icon=xpm_to_widget(window, icon_data); - toggleitem=gtk_toggle_tool_button_new(); - gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(toggleitem),icon); - gtk_tool_button_set_label(GTK_TOOL_BUTTON(toggleitem),text); - gtk_toolbar_insert(GTK_TOOLBAR(toolbar),toggleitem,-1); - if(*flag) - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(toggleitem),TRUE); - - g_signal_connect(G_OBJECT(toggleitem), "clicked", G_CALLBACK(func), data); -} - - -struct toolbar * -gui_gtk_toolbar_new(struct container *co, GtkWidget **widget) -{ - GtkWidget *toolbar,*window; - struct toolbar *this=g_new0(struct toolbar, 1); - - this->gui=g_new0(struct toolbar_gui, 1); - this->gui->co=co; - - toolbar=gtk_toolbar_new(); - window=(GtkWidget *)(co->win); - - co->flags->track=1; - co->flags->orient_north=1; - - toolbar_button(window, toolbar, viewmag_plus_xpm, "Zoom In", zoom_in, this); - toolbar_button(window, toolbar, viewmag_minus_xpm, "Zoom Out", zoom_out, this); - toolbar_button(window, toolbar, reload_xpm, "Refresh Route", refresh_route, this); - toolbar_button_toggle(window, toolbar, cursor_xpm, "Cursor on/off", track, this, &co->flags->track); - toolbar_button_toggle(window, toolbar, north_xpm, "Orientate North on/off", orient_north, this, &co->flags->orient_north); - toolbar_button(window, toolbar, flag_xpm, "Destination", destination, this); - - *widget=toolbar; - - return this; -} diff --git a/src/gui/gtk/gui_gtk_window.c b/src/gui/gtk/gui_gtk_window.c index f080bbda..663cbcca 100644 --- a/src/gui/gtk/gui_gtk_window.c +++ b/src/gui/gtk/gui_gtk_window.c @@ -1,68 +1,119 @@ #include <stdio.h> +#include <gdk/gdkkeysyms.h> +#if !defined(GDK_Book) || !defined(GDK_Calendar) +#include <X11/XF86keysym.h> +#endif #include <gtk/gtk.h> +#include "navit.h" +#include "debug.h" +#include "gui.h" #include "coord.h" -#include "transform.h" -#include "container.h" +#include "point.h" +#include "plugin.h" +#include "graphics.h" #include "gui_gtk.h" +#ifndef GDK_Book +#define GDK_Book XF86XK_Book +#endif -extern void container_init_gra(struct container *co); +#ifndef GDK_Calendar +#define GDK_Calendar XF86XK_Calendar +#endif -static struct container * -container_new(GtkWidget **widget) +static gboolean +keypress(GtkWidget *widget, GdkEventKey *event, struct gui_priv *this) { - struct container *co=g_new0(struct container, 1); - extern struct map_data *map_data_default; - struct transformation *t=g_new0(struct transformation, 1); - struct map_flags *flags=g_new0(struct map_flags, 1); - struct graphics *gra; + int w,h; + struct point p; + if (event->type != GDK_KEY_PRESS) + return FALSE; + dbg(1,"keypress 0x%x\n", event->keyval); + transform_get_size(navit_get_trans(this->nav), &w, &h); + switch (event->keyval) { + case GDK_KP_Enter: + gtk_menu_shell_select_first(this->menubar, TRUE); + break; + case GDK_Up: + p.x=w/2; + p.y=0; + navit_set_center_screen(this->nav, &p); + break; + case GDK_Down: + p.x=w/2; + p.y=h; + navit_set_center_screen(this->nav, &p); + break; + case GDK_Left: + p.x=0; + p.y=h/2; + navit_set_center_screen(this->nav, &p); + break; + case GDK_Right: + p.x=w; + p.y=h/2; + navit_set_center_screen(this->nav, &p); + break; + case GDK_Book: + navit_zoom_in(this->nav, 2); + break; + case GDK_Calendar: + navit_zoom_out(this->nav, 2); + break; + default: + return FALSE; + } + return TRUE; +} - co->map_data=map_data_default; -#if 1 - extern struct graphics *graphics_gtk_drawing_area_new(struct container *co, GtkWidget **widget); - gra=graphics_gtk_drawing_area_new(co, widget); -#else - extern struct graphics *graphics_gtk_gl_area_new(struct container *co, GtkWidget **widget); - gra=graphics_gtk_gl_area_new(co, widget); -#endif - co->gra=gra; - co->trans=t; - co->flags=flags; +static int +gui_gtk_set_graphics(struct gui_priv *this, struct graphics *gra) +{ + GtkWidget *graphics; - return co; + graphics=graphics_get_data(gra, "gtk_widget"); + if (! graphics) + return 1; + GTK_WIDGET_SET_FLAGS (graphics, GTK_CAN_FOCUS); + gtk_widget_set_sensitive(graphics, TRUE); + g_signal_connect(G_OBJECT(graphics), "key-press-event", G_CALLBACK(keypress), this); + gtk_box_pack_end(GTK_BOX(this->vbox), graphics, TRUE, TRUE, 0); + gtk_widget_show_all(graphics); + gtk_widget_grab_focus(graphics); + + return 0; } -struct container * -gui_gtk_window(int x, int y, int scale) +struct gui_methods gui_gtk_methods = { + gui_gtk_menubar_new, + gui_gtk_toolbar_new, + gui_gtk_statusbar_new, + gui_gtk_popup_new, + gui_gtk_set_graphics, +}; + +static struct gui_priv * +gui_gtk_new(struct navit *nav, struct gui_methods *meth, int w, int h) { - GtkWidget *window,*map_widget; - GtkWidget *vbox; - GtkWidget *statusbar; - struct container *co; + struct gui_priv *this; + + *meth=gui_gtk_methods; - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_default_size(GTK_WINDOW(window), 792, 547); - gtk_window_set_title(GTK_WINDOW(window), "Map"); - gtk_widget_realize(window); - vbox = gtk_vbox_new(FALSE, 0); - co=container_new(&map_widget); - - transform_setup(co->trans, x, y, scale, 0); + this=g_new0(struct gui_priv, 1); + this->nav=nav; + this->win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + this->vbox = gtk_vbox_new(FALSE, 0); + gtk_window_set_default_size(GTK_WINDOW(this->win), w, h); + gtk_window_set_title(GTK_WINDOW(this->win), "Navit"); + gtk_widget_realize(this->win); + gtk_container_add(GTK_CONTAINER(this->win), this->vbox); + gtk_widget_show_all(this->win); - co->win=(struct window *) window; - co->statusbar=gui_gtk_statusbar_new(&statusbar); - gui_gtk_actions_new(co,&vbox); - -/* - gtk_box_pack_start(GTK_BOX(vbox), menu, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0); -*/ - gtk_box_pack_end(GTK_BOX(vbox), statusbar, FALSE, FALSE, 0); - gtk_box_pack_end(GTK_BOX(vbox), map_widget, TRUE, TRUE, 0); - gtk_container_add(GTK_CONTAINER(window), vbox); - - gtk_widget_show_all(window); - container_init_gra(co); - return co; + return this; } +void +plugin_init(void) +{ + plugin_register_gui_type("gtk", gui_gtk_new); +} diff --git a/src/gui/sdl/Makefile.am b/src/gui/sdl/Makefile.am new file mode 100644 index 00000000..d8be2a30 --- /dev/null +++ b/src/gui/sdl/Makefile.am @@ -0,0 +1,5 @@ +include $(top_srcdir)/Makefile.inc +AM_CPPFLAGS = @NAVIT_CFLAGS@ @CEGUI_CFLAGS@ -I../.. +plugin_LTLIBRARIES = libgui_sdl.la +libgui_sdl_la_SOURCES = gui_sdl_window.cpp sdl_events.cpp +libgui_sdl_la_LIBADD = @SDL_LIBS@ @CEGUI_LIBS@ @OPENGL_LIBS@ diff --git a/src/gui/sdl/gui_sdl.h b/src/gui/sdl/gui_sdl.h new file mode 100644 index 00000000..1519084c --- /dev/null +++ b/src/gui/sdl/gui_sdl.h @@ -0,0 +1,23 @@ +#include "SDL/SDL.h" + +#define XRES 800 +#define YRES 600 + + +struct statusbar_methods; +struct menu_methods; +struct navit; + +struct gui_priv { +/* + GtkWidget *win; + GtkWidget *vbox; + GtkActionGroup *base_group; + GtkActionGroup *debug_group; + GtkActionGroup *dyn_group; + GtkUIManager *menu_manager; + void *statusbar;*/ + struct navit *nav; + int dyn_counter; +}; + diff --git a/src/gui/sdl/gui_sdl_window.cpp b/src/gui/sdl/gui_sdl_window.cpp new file mode 100644 index 00000000..818e517e --- /dev/null +++ b/src/gui/sdl/gui_sdl_window.cpp @@ -0,0 +1,684 @@ +#include "glib.h" +#include <stdio.h> +// #include <gtk/gtk.h> + +// FIXME temporary fix for enum +#include "projection.h" + + +#include "navit.h" +#include "profile.h" +#include "transform.h" +#include "gui.h" +#include "coord.h" +#include "plugin.h" +#include "graphics.h" +#include "gui_sdl.h" + +#include "navigation.h" + +#include "CEGUI.h" + + +// This is for 3d fonts +#include "GL/glc.h" + + +#include "sdl_events.h" + +#define VM_2D 0 +#define VM_3D 1 + +bool VIEW_MODE=VM_3D; + +GLdouble eyeX=400; +GLdouble eyeY=900; +GLdouble eyeZ=-800; +GLdouble centerX=400; +GLdouble centerY=300; +GLdouble centerZ=0; +GLdouble upX=0; +GLdouble upY=-1; +GLdouble upZ=0; + +#include <CEGUI/RendererModules/OpenGLGUIRenderer/openglrenderer.h> +#include "CEGUIDefaultResourceProvider.h" +CEGUI::OpenGLRenderer* renderer; + +#undef profile +#define profile(x,y) + +CEGUI::Window* myRoot; + +#define MODULE "gui_sdl" +GLuint * DLid; + +struct navit *sdl_gui_navit; + +static int +gui_sdl_set_graphics(struct gui_priv *this_, struct graphics *gra) +{ + printf("setting up the graphics\n"); + + DLid=(GLuint *)graphics_get_data(gra, "opengl_displaylist"); + if (!DLid) + return 1; + return 0; +} + + +void drawCursor() { + printf("Pushing a cursor from GUI\n"); + int x=400; + int y=400; + float cursor_size=15.0f; + glColor4f(0.0f,0.0f,1.0f,0.75f); + glEnable(GL_BLEND); + glBegin(GL_TRIANGLES); + glVertex3f( x, y-cursor_size, 0.0f); + glVertex3f(x-cursor_size,y+cursor_size, 0.0f); + glVertex3f( x+cursor_size,y+cursor_size, 0.0f); + glEnd(); + glDisable(GL_BLEND); + + } + + +static void +sdl_update_roadbook(struct navigation *nav, void *data) +{ + using namespace CEGUI; + extern Window* myRoot; + + if(! WindowManager::getSingleton().getWindow("OSD/RoadbookButton")->isVisible()){ + WindowManager::getSingleton().getWindow("OSD/RoadbookButton")->show(); + } + + MultiColumnList* mcl = static_cast<MultiColumnList*>(myRoot->getChild("Navit/RoadBook")->getChild("Roadbook")); + mcl->resetList(); + + + struct navigation_list *list; + char *str; + + list=navigation_list_new(nav); + while ((str=navigation_list_get(list, navigation_mode_short))) { + +// printf("SDL : %s\n", str); + + + mcl->addRow(); + /* + char from [256]; + char to [256]; + + sprintf(from,"%s %s",param[0].value,param[1].value); + ListboxTextItem* itemListbox = new ListboxTextItem(from); + sprintf(to,"%s %s",param[2].value,param[3].value); + + itemListbox = new ListboxTextItem(to); + itemListbox->setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush"); + mcl->setItem(itemListbox, 1, mcl->getRowCount()-1); + + itemListbox = new ListboxTextItem(param[9].value); + itemListbox->setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush"); + mcl->setItem(itemListbox, 2, mcl->getRowCount()-1); + + itemListbox = new ListboxTextItem(param[11].value); + itemListbox->setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush"); + mcl->setItem(itemListbox, 3, mcl->getRowCount()-1); + + itemListbox = new ListboxTextItem(param[10].value); + itemListbox->setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush"); + mcl->setItem(itemListbox, 4, mcl->getRowCount()-1); + + */ + ListboxTextItem* itemListbox = new ListboxTextItem(str); + itemListbox->setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush"); + mcl->setItem(itemListbox, 0, mcl->getRowCount()-1); + + } + navigation_list_destroy(list); +} + +static int gui_run_main_loop(struct gui_priv *this_) +{ + printf("Entering main loop\n"); + + bool must_quit = false; + + // get "run-time" in seconds + double last_time_pulse = static_cast<double>(SDL_GetTicks()); + + int frames=0; + char fps [12]; + + struct transformation *t; + + + t=navit_get_trans(this_->nav); + transform_set_size(t, 800, 600); + navit_draw(this_->nav); +/* + glNewList(DLid,GL_COMPILE); + int x=400; + int y=400; + float cursor_size=15.0f; + glColor4f(1.0f,0.0f,0.0f,0.75f); + glEnable(GL_BLEND); + glBegin(GL_TRIANGLES); + glVertex3f( x, y-cursor_size, 0.0f); + glVertex3f(x-cursor_size,y+cursor_size, 0.0f); + glVertex3f( x+cursor_size,y+cursor_size, 0.0f); + glEnd(); + glDisable(GL_BLEND); + glEndList(); +*/ + GLuint cursorDL; + cursorDL=glGenLists(1); + glNewList(cursorDL,GL_COMPILE); + drawCursor(); + glEndList(); + + bool enable_timer=0; + + struct navigation *navig; + navig=navit_get_navigation(sdl_gui_navit); + if(navig){ + printf("navig valid, registering callback\n"); + navigation_register_callback(navig, navigation_mode_long, sdl_update_roadbook, sdl_gui_navit); + } else { + printf("navig unvalid\n"); + } + + + while (!must_quit) + { + if(enable_timer) + profile(0,NULL); + glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + if(VIEW_MODE==VM_3D){ + gluLookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ); + } + +/* + // FIXME This is to draw a ground. This is ugly and need to be fixed. Without it, we see the color of sky under the roads. + glColor4f(0.0f,0.7f,0.35f,1.0f); + glBegin(GL_POLYGON); + glVertex3f( -800,-600*3, 0.0f); + glVertex3f( -800,600*2, 0.0f); + glVertex3f( 1600,600*2, 0.0f); + glVertex3f( 1600,-600*3, 0.0f); + glEnd(); +*/ + + if(enable_timer) + profile(0,"graphics_redraw"); + g_main_context_iteration (NULL, FALSE); +// profile_timer("main context"); + + // graphics_get_data(this_->gra,DLid); + +#if 0 + glCallList(*DLid); +#endif + navit_draw_displaylist(sdl_gui_navit); + + // glCallList(cursorDL); + inject_input(must_quit); + if(enable_timer) + profile(0,"inputs"); + + // Render the cursor. + int x=400; + int y=480; + float cursor_size=15.0f; + glColor4f(0.0f,1.0f,0.0f,0.75f); + glEnable(GL_BLEND); + glBegin(GL_TRIANGLES); + glVertex3f( x, y-cursor_size, 0.0f); + glVertex3f(x-cursor_size,y+cursor_size, 0.0f); + glVertex3f( x+cursor_size,y+cursor_size, 0.0f); + glEnd(); + glDisable(GL_BLEND); + if(enable_timer) + profile(0,"cursor"); + + frames++; + if(SDL_GetTicks()-last_time_pulse>1000){ + sprintf(fps,"%i",frames); // /(SDL_GetTicks()/1000)); + frames=0; + last_time_pulse = SDL_GetTicks(); + } + + myRoot->getChild("OSD/SpeedoMeter")->setText(fps); + + /* + glcRenderStyle(GLC_TEXTURE); + glColor3f(1, 0, 0); + glRotatef(180,1,0,0); + glScalef(64, 64, 0); + glcRenderString(fps); + */ + + if(enable_timer) + profile(0,"fps"); + + CEGUI::System::getSingleton().renderGUI(); + if(enable_timer) + profile(0,"GUI"); + + SDL_GL_SwapBuffers(); + } + + +} + + +static struct menu_priv * +gui_sdl_toolbar_new(struct gui_priv *this_, struct menu_methods *meth) +{ + return NULL; //gui_gtk_ui_new(this_, meth, "/ui/ToolBar", nav, 0); +} + +static struct statusbar_priv * +gui_sdl_statusbar_new(struct gui_priv *gui, struct statusbar_methods *meth) +{ + return NULL; //gui_gtk_ui_new(this_, meth, "/ui/ToolBar", nav, 0); +} + +static struct menu_priv * +gui_sdl_menubar_new(struct gui_priv *this_, struct menu_methods *meth) +{ + return NULL; //gui_gtk_ui_new(this_, meth, "/ui/MenuBar", nav, 0); +} + +static struct menu_priv * +gui_sdl_popup_new(struct gui_priv *this_, struct menu_methods *meth) +{ + return NULL; //gui_gtk_ui_new(this_, meth, "/ui/PopUp", nav, 1); +} + +struct gui_methods gui_sdl_methods = { + gui_sdl_menubar_new, + gui_sdl_toolbar_new, + gui_sdl_statusbar_new, + gui_sdl_popup_new, + gui_sdl_set_graphics, + gui_run_main_loop, +}; + + +int init_GL() { + + printf("init_GL()\n"); +// glClearColor(1.0,0.9,0.7,0); + + // Blue sky + glClearColor(0.3,0.7,1.0,0); + + if(VIEW_MODE==VM_2D){ + printf("Switching to 2D view\n"); +// myRoot->getChild("OSD/ViewMode")->setText("2D"); + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + + glOrtho( 0, XRES, YRES, 0, -1, 1 ); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + } else { + printf("Switching to 3D view\n"); +// myRoot->getChild("OSD/ViewMode")->setText("3D"); + + // Dimensions de la fenetre de rendu + glViewport(0, 0, XRES, YRES); + // Initialisation de la matrice de projection + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(45, 1.0, 0.1, 2800.0); + // Rendu avec lissage de Gouraud +// glShadeModel(GL_SMOOTH); + // glEnable(GL_DEPTH_TEST); + + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +// gluLookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ); + + } + + //Display list code + // GLuint glGenLists(GLsizei numberOfIDsRequired); + // linesDL = glGenLists(1); + + if( glGetError() != GL_NO_ERROR ) { + return 0; + } + return 1; +} + +bool ToggleView(const CEGUI::EventArgs& event) +{ + VIEW_MODE=!VIEW_MODE; + + if(VIEW_MODE==VM_2D){ + myRoot->getChild("OSD/ViewMode")->setText("2D"); + } else { + myRoot->getChild("OSD/ViewMode")->setText("3D"); + } + init_GL(); +} + +bool MoveCamera(const CEGUI::EventArgs& event){ + + CEGUI::Scrollbar * sb = static_cast<const CEGUI::Scrollbar *>(myRoot->getChild("OSD/Scrollbar1")); +// printf("moving : %f\n",sb->getScrollPosition()); + eyeZ=-sb->getScrollPosition(); + if (eyeZ>-100){ + eyeZ=-100; + } +} + +bool ShowKeyboard(const CEGUI::EventArgs& event){ + myRoot->getChild("Navit/Keyboard")->getChild("Navit/Keyboard/Input")->setText(""); + myRoot->getChild("Navit/Keyboard")->show(); +} + +void Add_KeyBoard_key(char * key,int x,int y,int w){ + + using namespace CEGUI; + char button_name [5]; + sprintf(button_name,"%s",key); + FrameWindow* wnd = (FrameWindow*)WindowManager::getSingleton().createWindow("TaharezLook/Button", button_name); + myRoot->getChild("Navit/Keyboard")->addChildWindow(wnd); + wnd->setPosition(UVector2(cegui_absdim(x), cegui_absdim( y))); + wnd->setSize(UVector2(cegui_absdim(w), cegui_absdim( 40))); + wnd->setText(key); + wnd->subscribeEvent(PushButton::EventClicked, Event::Subscriber(Handle_Virtual_Key_Down)); + +} + + +void BuildKeyboard(){ + int w=55; + int offset_x=10; + int count_x=0; + + int y=25; + Add_KeyBoard_key("A",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("Z",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("E",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("R",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("T",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("Y",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("U",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("I",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("O",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("P",offset_x+(count_x++)*w,y,w); + count_x++; + Add_KeyBoard_key("7",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("8",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("9",offset_x+(count_x++)*w,y,w); + + y=70; + count_x=0; + Add_KeyBoard_key("Q",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("S",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("D",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("F",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("G",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("H",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("J",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("K",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("L",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("M",offset_x+(count_x++)*w,y,w); + count_x++; + Add_KeyBoard_key("4",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("5",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("6",offset_x+(count_x++)*w,y,w); + + y=115; + count_x=0; + + Add_KeyBoard_key("W",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("X",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("C",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("V",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("B",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("N",offset_x+(count_x++)*w,y,w); + + Add_KeyBoard_key(" ",offset_x+(count_x++)*w,y,w*2); + count_x++; + + Add_KeyBoard_key("BACK",offset_x+(count_x++)*w,y,w*2); + count_x+=2; + + Add_KeyBoard_key("1",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("2",offset_x+(count_x++)*w,y,w); + Add_KeyBoard_key("3",offset_x+(count_x++)*w,y,w); + + y=160; + count_x=11; + Add_KeyBoard_key("0",offset_x+(count_x++)*w,y,w); + + Add_KeyBoard_key("OK",offset_x+(count_x++)*w,y,w*2); + + +} + +static void init_sdlgui(void) +{ + SDL_Surface * screen; +// atexit (SDL_Quit); + SDL_Init (SDL_INIT_VIDEO); + int videoFlags; + const SDL_VideoInfo *videoInfo; + videoInfo = SDL_GetVideoInfo( ); + + if ( !videoInfo ) + { + fprintf( stderr, "Video query failed: %s\n", + SDL_GetError( ) ); + } + + /* the flags to pass to SDL_SetVideoMode */ + videoFlags = SDL_OPENGL; /* Enable OpenGL in SDL */ + videoFlags |= SDL_GL_DOUBLEBUFFER; /* Enable double buffering */ + videoFlags |= SDL_HWPALETTE; /* Store the palette in hardware */ + videoFlags |= SDL_RESIZABLE; /* Enable window resizing */ + + /* This checks to see if surfaces can be stored in memory */ + if ( videoInfo->hw_available ) + videoFlags |= SDL_HWSURFACE; + else + videoFlags |= SDL_SWSURFACE; + + /* This checks if hardware blits can be done */ + if ( videoInfo->blit_hw ) + videoFlags |= SDL_HWACCEL; + + /* Sets up OpenGL double buffering */ + SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); + + SDL_WM_SetCaption("NavIt - The OpenSource vector based navigation engine", NULL); + + /* get a SDL surface */ + screen = SDL_SetVideoMode( XRES, YRES, 32, + videoFlags ); + + if (screen == NULL) { + fprintf (stderr, "Can't set SDL: %s\n", SDL_GetError ()); + exit (1); + } + + SDL_ShowCursor (SDL_ENABLE); + SDL_EnableUNICODE (1); + SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); + + init_GL(); + +// sdl_audio_init(); + + try + { + renderer = new CEGUI::OpenGLRenderer(0,XRES,YRES); + new CEGUI::System(renderer); + + using namespace CEGUI; + + SDL_ShowCursor(SDL_ENABLE); + SDL_EnableUNICODE(1); + SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); + + CEGUI::DefaultResourceProvider* rp = static_cast<CEGUI::DefaultResourceProvider*> + (CEGUI::System::getSingleton().getResourceProvider()); + + rp->setResourceGroupDirectory("schemes", "../datafiles/schemes/"); + rp->setResourceGroupDirectory("imagesets", "../datafiles/imagesets/"); + rp->setResourceGroupDirectory("fonts", "../datafiles/fonts/"); + rp->setResourceGroupDirectory("layouts", "../datafiles/layouts/"); + rp->setResourceGroupDirectory("looknfeels", "../datafiles/looknfeel/"); + rp->setResourceGroupDirectory("lua_scripts", "../datafiles/lua_scripts/"); + + + CEGUI::Imageset::setDefaultResourceGroup("imagesets"); + CEGUI::Font::setDefaultResourceGroup("fonts"); + CEGUI::Scheme::setDefaultResourceGroup("schemes"); + CEGUI::WidgetLookManager::setDefaultResourceGroup("looknfeels"); + CEGUI::WindowManager::setDefaultResourceGroup("layouts"); + CEGUI::ScriptModule::setDefaultResourceGroup("lua_scripts"); + + CEGUI::SchemeManager::getSingleton().loadScheme("TaharezLook.scheme"); + + CEGUI::FontManager::getSingleton().createFont("DejaVuSans-10.font"); + CEGUI::FontManager::getSingleton().createFont("DejaVuSans-14.font"); + + CEGUI::System::getSingleton().setDefaultFont("DejaVuSans-10"); + + CEGUI::WindowManager& wmgr = CEGUI::WindowManager::getSingleton(); + + myRoot = CEGUI::WindowManager::getSingleton().loadWindowLayout("navit.layout"); + + CEGUI::System::getSingleton().setGUISheet(myRoot); + + + myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/CountryEditbox")->subscribeEvent(Window::EventKeyUp, Event::Subscriber(DestinationEntryChange)); + myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/CountryEditbox")->subscribeEvent(Window::EventMouseButtonDown, Event::Subscriber(handleMouseEnters)); + myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/TownEditbox")->subscribeEvent(Window::EventKeyUp, Event::Subscriber(DestinationEntryChange)); + myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/TownEditbox")->subscribeEvent(Window::EventMouseButtonDown, Event::Subscriber(handleMouseEnters)); + myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/StreetEditbox")->subscribeEvent(Window::EventKeyUp, Event::Subscriber(DestinationEntryChange)); + myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/StreetEditbox")->subscribeEvent(Window::EventMouseButtonDown, Event::Subscriber(handleMouseEnters)); + + myRoot->getChild("OSD/DestinationButton")->subscribeEvent(PushButton::EventClicked, Event::Subscriber(DialogWindowSwitch)); + + myRoot->getChild("OSD/RoadbookButton")->subscribeEvent(PushButton::EventClicked, Event::Subscriber(RoadBookSwitch)); + myRoot->getChild("Navit/RoadBook")->getChild("OSD/RoadbookButton2")->subscribeEvent(PushButton::EventClicked, Event::Subscriber(RoadBookSwitch)); + myRoot->getChild("OSD/ZoomIn")->subscribeEvent(PushButton::EventClicked, Event::Subscriber(ZoomIn)); + myRoot->getChild("OSD/ZoomOut")->subscribeEvent(PushButton::EventClicked, Event::Subscriber(ZoomOut)); + myRoot->getChild("OSD/Quit")->subscribeEvent(PushButton::EventClicked, Event::Subscriber(ButtonQuit)); + myRoot->getChild("OSD/ViewMode")->subscribeEvent(PushButton::EventClicked, Event::Subscriber(ToggleView)); + + myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/GO")->subscribeEvent(PushButton::EventClicked, Event::Subscriber(ButtonGo)); + myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/KB")->subscribeEvent(PushButton::EventClicked, Event::Subscriber(ShowKeyboard)); + + myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/Listbox")->subscribeEvent(MultiColumnList::EventSelectionChanged, Event::Subscriber(ItemSelect)); + + myRoot->getChild("OSD/Scrollbar1")->subscribeEvent(Scrollbar::EventScrollPositionChanged, Event::Subscriber(MoveCamera)); + + + MultiColumnList* mcl = static_cast<MultiColumnList*>(WindowManager::getSingleton().getWindow("DestinationWindow/Listbox")); + + mcl->setSelectionMode(MultiColumnList::RowSingle) ; + mcl->addColumn("Value", 0, cegui_absdim(200.0)); + mcl->addColumn("ID", 1, cegui_absdim(70.0)); + mcl->addColumn("Assoc", 2, cegui_absdim(70.0)); + mcl->addColumn("x", 3, cegui_absdim(70.0)); + mcl->addColumn("y", 4, cegui_absdim(70.0)); + + MultiColumnList* mcl2 = static_cast<MultiColumnList*>(WindowManager::getSingleton().getWindow("Roadbook")); + + mcl2->setSelectionMode(MultiColumnList::RowSingle) ; + mcl2->addColumn("From", 0, cegui_absdim(200.0)); + mcl2->addColumn("To", 1, cegui_absdim(200.0)); + mcl2->addColumn("Dist", 2, cegui_absdim(80.0)); + mcl2->addColumn("ETA", 3, cegui_absdim(80.0)); + mcl2->addColumn("Instruction",4, cegui_absdim(300.0)); + + BuildKeyboard(); + + } + catch (CEGUI::Exception& e) + { + fprintf(stderr,"CEGUI Exception occured: \n%s\n", e.getMessage().c_str()); + printf("quiting...\n"); + exit(1); + } + + char * fontname="/usr/share/fonts/corefonts/verdana.ttf"; + +// printf("Gui initialized. Building fonts\n"); + + + int ctx = 0; + int font = 0; + ctx = glcGenContext(); + glcContext(ctx); + font = glcNewFontFromFamily(glcGenFontID(), "Arial"); + glcFont(font); +// glcFontFace(font, "Italic"); + +// printf("Fonts built. Ready to rock!\n"); + + +} + +static struct gui_priv * +gui_sdl_new(struct navit *nav, struct gui_methods *meth, int w, int h) +{ + printf("Begin SDL init\n"); + struct gui_priv *this_; + sdl_gui_navit=nav; + + if(sdl_gui_navit){ + printf("*** VALID navit instance in gui\n"); + } else { + printf("*** Invalid navit instance in gui\n"); + } + if(nav){ + printf("*** VALID source navit instance in gui\n"); + } else { + printf("*** Invalid source navit instance in gui\n"); + } + + *meth=gui_sdl_methods; + + this_=g_new0(struct gui_priv, 1); + init_sdlgui(); + printf("End SDL init\n"); + + /* + this_->win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + this_->vbox = gtk_vbox_new(FALSE, 0); + gtk_window_set_default_size(GTK_WINDOW(this_->win), w, h); + gtk_window_set_title(GTK_WINDOW(this_->win), "Navit"); + gtk_widget_realize(this_->win); + gtk_container_add(GTK_CONTAINER(this_->win), this_->vbox); + gtk_widget_show_all(this_->win); + */ + this_->nav=nav; + + + return this_; +} + +void +plugin_init(void) +{ + printf("registering sdl plugin\n"); + plugin_register_gui_type("sdl", gui_sdl_new); +} diff --git a/src/gui/sdl/sdl_events.cpp b/src/gui/sdl/sdl_events.cpp new file mode 100644 index 00000000..0d83acff --- /dev/null +++ b/src/gui/sdl/sdl_events.cpp @@ -0,0 +1,771 @@ +#include "CEGUI.h" +#include "sdl_events.h" + +#include <CEGUI/RendererModules/OpenGLGUIRenderer/openglrenderer.h> + +// FIXME temporary fix for enum +#include "projection.h" +#include "navit.h" + +#include "../../coord.h" + +// Theses are needed for searches +#include "../../attr.h" +#include "../../item.h" +#include "../../search.h" + +struct sdl_destination{ + int country; + int town; + int town_street_assoc; + int current_search; +} SDL_dest; + + +static struct search_param { + struct navit *nav; + struct mapset *ms; + struct search_list *sl; + struct attr attr; +} search_param; + +// extern "C" struct navit *global_navit; + +void route_to(int x,int y){ + struct coord pos; + pos.x=x; + pos.y=y; + using namespace CEGUI; + extern struct navit *sdl_gui_navit; + + WindowManager::getSingleton().getWindow("DestinationWindow")->hide(); + WindowManager::getSingleton().getWindow("Navit/Routing/Tips")->show(); + WindowManager::getSingleton().getWindow("Navit/ProgressWindow")->show(); +// route_set_destination(co->route, &pos); + // I could have been using search->nav instead of sdl_gui_navit. is it better this way? + + navit_set_destination(sdl_gui_navit, &pos, "FIXME"); + WindowManager::getSingleton().getWindow("Navit/ProgressWindow")->hide(); + WindowManager::getSingleton().getWindow("OSD/RoadbookButton")->show(); + WindowManager::getSingleton().getWindow("OSD/ETA")->show(); + +} + + +bool handleItemSelect(int r) +{ + using namespace CEGUI; + extern CEGUI::Window* myRoot; + + MultiColumnList* mcl = static_cast<MultiColumnList*>(WindowManager::getSingleton().getWindow("DestinationWindow/Listbox")); + + ListboxItem * item = mcl->getItemAtGridReference(MCLGridRef(r,0)); + ListboxItem * itemid = mcl->getItemAtGridReference(MCLGridRef(r,1)); + ListboxItem * item_assoc = mcl->getItemAtGridReference(MCLGridRef(r,2)); + + + Window* country_edit = static_cast<Window*>(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/CountryEditbox")); + Window* twn_edit = static_cast<Window*>(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/TownEditbox")); + Window* street_edit = static_cast<Window*>(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/StreetEditbox")); + + if(SDL_dest.current_search==SRCH_COUNTRY){ + country_edit->setText(item->getText()); + // Need to record the country here + twn_edit->activate(); + SDL_dest.current_search=SRCH_TOWN; + myRoot->getChild("Navit/Keyboard")->getChild("Navit/Keyboard/Input")->setText(""); + + } else if(SDL_dest.current_search==SRCH_TOWN){ + twn_edit->setText(item->getText()); +// SDL_dest.town_street_assoc=atoi(item_assoc->getText().c_str()); +// SDL_dest.town=atoi(itemid->getText().c_str()); +// printf(" town %s , id=%lx, assoc=%li\n",item->getText().c_str(),SDL_dest.town_street_assoc,SDL_dest.town_street_assoc); + + + ListboxItem * itemx = mcl->getItemAtGridReference(MCLGridRef(r,3)); + ListboxItem * itemy = mcl->getItemAtGridReference(MCLGridRef(r,4)); + + Window* Dest_x = static_cast<Window*>(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/Dest_x")); + Dest_x->setText(itemx->getText().c_str()); + + Window* Dest_y = static_cast<Window*>(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/Dest_y")); + Dest_y->setText(itemy->getText().c_str()); + + mcl->resetList(); + + SDL_dest.current_search=SRCH_STREET; + street_edit->activate(); + myRoot->getChild("Navit/Keyboard")->getChild("Navit/Keyboard/Input")->setText(""); + + } else if(SDL_dest.current_search==SRCH_STREET){ + street_edit->setText(item->getText()); + + myRoot->getChild("Navit/Keyboard")->hide(); + + ListboxItem * itemx = mcl->getItemAtGridReference(MCLGridRef(r,3)); + ListboxItem * itemy = mcl->getItemAtGridReference(MCLGridRef(r,4)); + + Window* Dest_x = static_cast<Window*>(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/Dest_x")); + Dest_x->setText(itemx->getText().c_str()); + + Window* Dest_y = static_cast<Window*>(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/Dest_y")); + Dest_y->setText(itemy->getText().c_str()); + + mcl->resetList(); + + SDL_dest.current_search=SRCH_STREET; + + myRoot->getChild("Navit/Keyboard")->getChild("Navit/Keyboard/Input")->setText(""); + + + /* + ListboxItem * itemid = mcl->getItemAtGridReference(MCLGridRef(r,1)); + int segment_id=atoi(itemid->getText().c_str()); + printf("street seg id : %li\n",segment_id); + + extern struct container *co; + struct block_info res_blk_inf; + struct street_str *res_str; + street_get_by_id(co->map_data, 33, segment_id,&res_blk_inf,&res_str ); + + struct street_coord * streetcoord; + streetcoord=street_coord_get(&res_blk_inf,res_str); + + printf("Street coordinates : %i,%i\n",streetcoord->c->x,streetcoord->c->y); + + char xbuff [256]; + sprintf(xbuff,"%li",streetcoord->c->x); + char ybuff [256]; + sprintf(ybuff,"%li",streetcoord->c->y); + + Window* Dest_x = static_cast<Window*>(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/Dest_x")); + Dest_x->setText(xbuff); + + Window* Dest_y = static_cast<Window*>(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/Dest_y")); + Dest_y->setText(ybuff); + + struct street_name name; +// printf("street_name_get_by_id returns : %i\n",street_name_get_by_id(&name, res_blk_inf.mdata, res_str->nameid)); + street_name_get_by_id(&name, res_blk_inf.mdata, res_str->nameid); +// printf("name1:%s / name2%s\n",name.name1,name.name2); + + struct street_name_number_info num; + struct street_name_info inf; + + SDL_dest.current_search=SRCH_NUMBER; + mcl->resetList(); + + while (street_name_get_info(&inf, &name)) { + while(street_name_get_number_info(&num,&inf)){ +// printf(" House Number : %i -> %i\n",num.first,num.last); + for(int i=num.first;i<=num.last;i+=2){ + add_number_to_list(i,num.c->x,num.c->y); + } + } + } + */ +// route_to(streetcoord->c->x,streetcoord->c->y); + } else if (SDL_dest.current_search==SRCH_NUMBER){ + + struct coord pos; + ListboxItem * itemx = mcl->getItemAtGridReference(MCLGridRef(r,3)); + ListboxItem * itemy = mcl->getItemAtGridReference(MCLGridRef(r,4)); + + pos.x=atoi(itemx->getText().c_str()); + pos.y=atoi(itemy->getText().c_str()); + + route_to(pos.x,pos.y); + } + + return true; +} + + + +bool ItemSelect(const CEGUI::EventArgs& event) +{ + using namespace CEGUI; + + MultiColumnList* mcl = static_cast<MultiColumnList*>(WindowManager::getSingleton().getWindow("DestinationWindow/Listbox")); + ListboxItem * item = mcl->getFirstSelectedItem(); + handleItemSelect(mcl->getItemRowIndex(item)); +} + +bool handleMouseEnters(const CEGUI::EventArgs& event) +{ + // FIXME this whole function could maybe be removed + const CEGUI::WindowEventArgs& we = static_cast<const CEGUI::WindowEventArgs&>(event); + + // FIXME theses variables should be shared + extern CEGUI::OpenGLRenderer* renderer; + extern CEGUI::Window* myRoot; + + using namespace CEGUI; + myRoot->getChild("Navit/Keyboard")->getChild("Navit/Keyboard/Input")->setText(""); + MultiColumnList* mcl = static_cast<MultiColumnList*>(WindowManager::getSingleton().getWindow("DestinationWindow/Listbox")); + + String senderID = we.window->getName(); + + if (senderID == "DestinationWindow/CountryEditbox"){ + // First, clean off the Street and Town Editbox + extern Window* myRoot; + Window* town_edit = static_cast<Window*>(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/TownEditbox")); + town_edit->setText(""); + Window* street_edit = static_cast<Window*>(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/StreetEditbox")); + street_edit->setText(""); + SDL_dest.current_search=SRCH_COUNTRY; + + } else if (senderID == "DestinationWindow/TownEditbox"){ + // First, clean off the Street Editbox + extern Window* myRoot; + Window* street_edit = static_cast<Window*>(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/StreetEditbox")); + street_edit->setText(""); + SDL_dest.current_search=SRCH_TOWN; + + } else if (senderID == "DestinationWindow/StreetEditbox"){ + // First, make sure the user selected an entry in the town choice. If he hadn't, select the first for him. + if(SDL_dest.current_search==SRCH_TOWN){ + if (mcl->getRowCount()>0) + { + handleItemSelect(0); + } + } + SDL_dest.current_search=SRCH_STREET; + + } +} + + +void handle_destination_change(){ + printf("Called handle_destination_change\n"); + + using namespace CEGUI; + extern CEGUI::Window* myRoot; + + struct search_param *search=&search_param; + struct search_list_result *res; + + MultiColumnList* mcl = static_cast<MultiColumnList*>(WindowManager::getSingleton().getWindow("DestinationWindow/Listbox")); + + + if (SDL_dest.current_search==SRCH_COUNTRY) + { + printf("Starting a country search\n"); + Editbox* country_edit = static_cast<Editbox*>(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/CountryEditbox")); + String content=country_edit->getText(); + + mcl->resetList(); + + search->attr.type=attr_country_all; + + // FIXME the following codeblock could be shared between country, town and street search + search->attr.u.str=(char *)content.c_str(); + + search_list_search(search->sl, &search->attr, 1); + while((res=search_list_get_result(search->sl))) { + ListboxTextItem* itemListbox = new ListboxTextItem(res->country->name); + itemListbox->setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush"); + + mcl->addRow(itemListbox,0); + } + + } else if (SDL_dest.current_search==SRCH_TOWN) + { + + Editbox* town_edit = static_cast<Editbox*>(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/TownEditbox")); + String content=town_edit->getText(); + + + mcl->resetList(); + + if(strlen(content.c_str())<4){ + + } else { + printf("town searching for %s\n",content.c_str()); + search->attr.type=attr_town_name; + search->attr.u.str=(char *)content.c_str(); + + search_list_search(search->sl, &search->attr, 1); + while((res=search_list_get_result(search->sl))) { + ListboxTextItem* itemListbox = new ListboxTextItem(res->town->name); + itemListbox->setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush"); + + mcl->addRow(itemListbox,0); + + char x [256]; + sprintf(x,"%li",res->c->x); + ListboxTextItem* xitem = new ListboxTextItem(x); + + char y [256]; + sprintf(y,"%li",res->c->y); + + ListboxTextItem* yitem = new ListboxTextItem(y); +// item->setSelectionBrushImage(&ImagesetManager::getSingleton().getImageset("TaharezLook")->getImage("MultiListSelectionBrush")); + + try + { + mcl->setItem(xitem, 3, mcl->getRowCount()-1); + mcl->setItem(yitem, 4, mcl->getRowCount()-1); + } + // something went wrong, so cleanup the ListboxTextItem. + catch (InvalidRequestException) + { +// delete item; + } + + } + + } + + + } else if (SDL_dest.current_search==SRCH_STREET) + { + Editbox* street_edit = static_cast<Editbox*>(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/StreetEditbox")); + + String content=street_edit->getText(); + if(strlen(content.c_str())<1){ + + } else { + printf("street searching for %s\n",content.c_str()); + search->attr.type=attr_street_name; + search->attr.u.str=(char *)content.c_str(); + + mcl->resetList(); + + search_list_search(search->sl, &search->attr, 1); + while((res=search_list_get_result(search->sl))) { + ListboxTextItem* itemListbox = new ListboxTextItem(res->street->name); + itemListbox->setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush"); + + mcl->addRow(itemListbox,0); + + char x [256]; + sprintf(x,"%li",res->c->x); + ListboxTextItem* xitem = new ListboxTextItem(x); + + char y [256]; + sprintf(y,"%li",res->c->y); + + ListboxTextItem* yitem = new ListboxTextItem(y); +// item->setSelectionBrushImage(&ImagesetManager::getSingleton().getImageset("TaharezLook")->getImage("MultiListSelectionBrush")); + + try + { + mcl->setItem(xitem, 3, mcl->getRowCount()-1); + mcl->setItem(yitem, 4, mcl->getRowCount()-1); + } + // something went wrong, so cleanup the ListboxTextItem. + catch (InvalidRequestException) + { +// delete item; + } + + + } + +// street_name_search(search->map_data, 33, SDL_dest.town_street_assoc, content.c_str(), 1, destination_street_add, search); + } + } + +} + + +bool DestinationEntryChange(const CEGUI::EventArgs& event) +{ + handleMouseEnters(event); + handle_destination_change(); + + return true; +} + +bool DialogWindowSwitch(const CEGUI::EventArgs& event) +{ + using namespace CEGUI; + + extern CEGUI::Window* myRoot; + + const CEGUI::WindowEventArgs& we = static_cast<const CEGUI::WindowEventArgs&>(event); + if(we.window->getParent()->getChild("DestinationWindow")->isVisible()){ + we.window->getParent()->getChild("DestinationWindow")->hide(); + } else { + Window* town_edit = static_cast<Window*>(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/TownEditbox")); + town_edit->setText(""); + Window* street_edit = static_cast<Window*>(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/StreetEditbox")); + street_edit->setText(""); + town_edit->activate(); + SDL_dest.current_search=SRCH_COUNTRY; + MultiColumnList* mcl = static_cast<MultiColumnList*>(WindowManager::getSingleton().getWindow("DestinationWindow/Listbox")); + mcl->resetList(); + we.window->getParent()->getChild("DestinationWindow")->show(); + } + + extern struct navit *sdl_gui_navit; + + if(sdl_gui_navit){ + } else { + printf("*** Invalid navit instance in sdl_events\n"); + } + struct search_param *search=&search_param; + + printf("search->nav=sdl_gui_navit;\n"); + search->nav=sdl_gui_navit; + printf("search->ms=navit_get_mapset(sdl_gui_navit);\n"); + search->ms=navit_get_mapset(sdl_gui_navit); + printf("search->sl=search_list_new(search->ms);\n"); + search->sl=search_list_new(search->ms); + + return true; +} + +bool RoadBookSwitch(const CEGUI::EventArgs& event) +{ + using namespace CEGUI; + extern CEGUI::Window* myRoot; + +// const CEGUI::WindowEventArgs& we = static_cast<const CEGUI::WindowEventArgs&>(event); + if(myRoot->getChild("Navit/RoadBook")->isVisible()){ + myRoot->getChild("Navit/RoadBook")->hide(); + WindowManager::getSingleton().getWindow("OSD/RoadbookButton")->show(); + } else { + myRoot->getChild("Navit/RoadBook")->show(); + WindowManager::getSingleton().getWindow("OSD/RoadbookButton")->hide(); + } + return true; +} + +bool ButtonGo(const CEGUI::EventArgs& event) +{ + using namespace CEGUI; + extern CEGUI::Window* myRoot; + + MultiColumnList* mcl = static_cast<MultiColumnList*>(WindowManager::getSingleton().getWindow("DestinationWindow/Listbox")); + // First, make sure the user selected an entry in the town choice. If he hadn't, select the first for him. + if(SDL_dest.current_search==SRCH_TOWN){ + if (mcl->getRowCount()>0) + { + handleItemSelect(0); + } + } + + + Window* Dest_x = static_cast<Window*>(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/Dest_x")); + Window* Dest_y = static_cast<Window*>(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/Dest_y")); + + extern struct navit *sdl_gui_navit; + route_to(atoi(Dest_x->getText().c_str()),atoi(Dest_y->getText().c_str())); + + return true; +} + + +bool ZoomIn(const CEGUI::EventArgs& event) +{ + extern struct navit *sdl_gui_navit; + navit_zoom_in(sdl_gui_navit, 2); + /* + extern struct container *co; + struct transformation *t=co->trans; + if(t->scale>1){ + t->scale/=2; + } + */ + +} + +bool ZoomOut(const CEGUI::EventArgs& event) +{ + extern struct navit *sdl_gui_navit; + navit_zoom_out(sdl_gui_navit, 2); + /* + extern struct container *co; + struct transformation *t=co->trans; + t->scale*=2; + */ +} + +bool ButtonQuit(const CEGUI::EventArgs& event) +{ + exit(0); +} + +bool Handle_Virtual_Key_Down(const CEGUI::EventArgs& event){ + + using namespace CEGUI; + + extern CEGUI::Window* myRoot; + + const CEGUI::WindowEventArgs& we = static_cast<const CEGUI::WindowEventArgs&>(event); + String senderID = we.window->getName(); + + Window* editbox = myRoot->getChild("Navit/Keyboard")->getChild("Navit/Keyboard/Input"); + String content=editbox->getText(); + + + if(senderID=="OK"){ + printf("Validating : %s\n",content.c_str()); + myRoot->getChild("Navit/Keyboard")->hide(); + return 0; + } else if(senderID=="BACK"){ + content=content.substr(0, content.length()-1); + editbox->setText(content); + } else { + content+=senderID; + editbox->setText(content); + } + + Window* country_edit = static_cast<Window*>(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/CountryEditbox")); + Window* town_edit = static_cast<Window*>(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/TownEditbox")); + Window* street_edit = static_cast<Window*>(myRoot->getChild("DestinationWindow")->getChild("DestinationWindow/StreetEditbox")); + + switch (SDL_dest.current_search) { + case SRCH_COUNTRY: + country_edit->setText(content); + break; + case SRCH_TOWN : + town_edit->setText(content); + break; + case SRCH_STREET : + street_edit->setText(content); + break; + } + handle_destination_change(); +} + + + +// Nothing really interesting below. + +void handle_mouse_down(Uint8 button) +{ + switch ( button ) + { + // handle real mouse buttons + case SDL_BUTTON_LEFT: + CEGUI::System::getSingleton().injectMouseButtonDown(CEGUI::LeftButton); + break; + case SDL_BUTTON_MIDDLE: + CEGUI::System::getSingleton().injectMouseButtonDown(CEGUI::MiddleButton); + break; + case SDL_BUTTON_RIGHT: + CEGUI::System::getSingleton().injectMouseButtonDown(CEGUI::RightButton); + break; + + // handle the mouse wheel + case SDL_BUTTON_WHEELDOWN: + CEGUI::System::getSingleton().injectMouseWheelChange( -1 ); + break; + case SDL_BUTTON_WHEELUP: + CEGUI::System::getSingleton().injectMouseWheelChange( +1 ); + break; + } +} + + +void handle_mouse_up(Uint8 button) +{ + switch ( button ) + { + case SDL_BUTTON_LEFT: + CEGUI::System::getSingleton().injectMouseButtonUp(CEGUI::LeftButton); + break; + case SDL_BUTTON_MIDDLE: + CEGUI::System::getSingleton().injectMouseButtonUp(CEGUI::MiddleButton); + break; + case SDL_BUTTON_RIGHT: + CEGUI::System::getSingleton().injectMouseButtonUp(CEGUI::RightButton); + break; + } +} + +void inject_time_pulse(double& last_time_pulse) +{ + // get current "run-time" in seconds + double t = 0.001*SDL_GetTicks(); + + // inject the time that passed since the last call + CEGUI::System::getSingleton().injectTimePulse( float(t-last_time_pulse) ); + + // store the new time as the last time + last_time_pulse = t; +} + + CEGUI::uint SDLKeyToCEGUIKey(SDLKey key) + { + using namespace CEGUI; + switch (key) + { + case SDLK_BACKSPACE: return Key::Backspace; + case SDLK_TAB: return Key::Tab; + case SDLK_RETURN: return Key::Return; + case SDLK_PAUSE: return Key::Pause; + case SDLK_ESCAPE: return Key::Escape; + case SDLK_SPACE: return Key::Space; + case SDLK_COMMA: return Key::Comma; + case SDLK_MINUS: return Key::Minus; + case SDLK_PERIOD: return Key::Period; + case SDLK_SLASH: return Key::Slash; + case SDLK_0: return Key::Zero; + case SDLK_1: return Key::One; + case SDLK_2: return Key::Two; + case SDLK_3: return Key::Three; + case SDLK_4: return Key::Four; + case SDLK_5: return Key::Five; + case SDLK_6: return Key::Six; + case SDLK_7: return Key::Seven; + case SDLK_8: return Key::Eight; + case SDLK_9: return Key::Nine; + case SDLK_COLON: return Key::Colon; + case SDLK_SEMICOLON: return Key::Semicolon; + case SDLK_EQUALS: return Key::Equals; + case SDLK_LEFTBRACKET: return Key::LeftBracket; + case SDLK_BACKSLASH: return Key::Backslash; + case SDLK_RIGHTBRACKET: return Key::RightBracket; + case SDLK_a: return Key::A; + case SDLK_b: return Key::B; + case SDLK_c: return Key::C; + case SDLK_d: return Key::D; + case SDLK_e: return Key::E; + case SDLK_f: return Key::F; + case SDLK_g: return Key::G; + case SDLK_h: return Key::H; + case SDLK_i: return Key::I; + case SDLK_j: return Key::J; + case SDLK_k: return Key::K; + case SDLK_l: return Key::L; + case SDLK_m: return Key::M; + case SDLK_n: return Key::N; + case SDLK_o: return Key::O; + case SDLK_p: return Key::P; + case SDLK_q: return Key::Q; + case SDLK_r: return Key::R; + case SDLK_s: return Key::S; + case SDLK_t: return Key::T; + case SDLK_u: return Key::U; + case SDLK_v: return Key::V; + case SDLK_w: return Key::W; + case SDLK_x: return Key::X; + case SDLK_y: return Key::Y; + case SDLK_z: return Key::Z; + case SDLK_DELETE: return Key::Delete; + case SDLK_KP0: return Key::Numpad0; + case SDLK_KP1: return Key::Numpad1; + case SDLK_KP2: return Key::Numpad2; + case SDLK_KP3: return Key::Numpad3; + case SDLK_KP4: return Key::Numpad4; + case SDLK_KP5: return Key::Numpad5; + case SDLK_KP6: return Key::Numpad6; + case SDLK_KP7: return Key::Numpad7; + case SDLK_KP8: return Key::Numpad8; + case SDLK_KP9: return Key::Numpad9; + case SDLK_KP_PERIOD: return Key::Decimal; + case SDLK_KP_DIVIDE: return Key::Divide; + case SDLK_KP_MULTIPLY: return Key::Multiply; + case SDLK_KP_MINUS: return Key::Subtract; + case SDLK_KP_PLUS: return Key::Add; + case SDLK_KP_ENTER: return Key::NumpadEnter; + case SDLK_KP_EQUALS: return Key::NumpadEquals; + case SDLK_UP: return Key::ArrowUp; + case SDLK_DOWN: return Key::ArrowDown; + case SDLK_RIGHT: return Key::ArrowRight; + case SDLK_LEFT: return Key::ArrowLeft; + case SDLK_INSERT: return Key::Insert; + case SDLK_HOME: return Key::Home; + case SDLK_END: return Key::End; + case SDLK_PAGEUP: return Key::PageUp; + case SDLK_PAGEDOWN: return Key::PageDown; + case SDLK_F1: return Key::F1; + case SDLK_F2: return Key::F2; + case SDLK_F3: return Key::F3; + case SDLK_F4: return Key::F4; + case SDLK_F5: return Key::F5; + case SDLK_F6: return Key::F6; + case SDLK_F7: return Key::F7; + case SDLK_F8: return Key::F8; + case SDLK_F9: return Key::F9; + case SDLK_F10: return Key::F10; + case SDLK_F11: return Key::F11; + case SDLK_F12: return Key::F12; + case SDLK_F13: return Key::F13; + case SDLK_F14: return Key::F14; + case SDLK_F15: return Key::F15; + case SDLK_NUMLOCK: return Key::NumLock; + case SDLK_SCROLLOCK: return Key::ScrollLock; + case SDLK_RSHIFT: return Key::RightShift; + case SDLK_LSHIFT: return Key::LeftShift; + case SDLK_RCTRL: return Key::RightControl; + case SDLK_LCTRL: return Key::LeftControl; + case SDLK_RALT: return Key::RightAlt; + case SDLK_LALT: return Key::LeftAlt; + case SDLK_LSUPER: return Key::LeftWindows; + case SDLK_RSUPER: return Key::RightWindows; + case SDLK_SYSREQ: return Key::SysRq; + case SDLK_MENU: return Key::AppMenu; + case SDLK_POWER: return Key::Power; + default: return 0; + } + return 0; + } + + +void inject_input(bool& must_quit) +{ + SDL_Event e; + + // go through all available events + while (SDL_PollEvent(&e)) + { + // we use a switch to determine the event type + switch (e.type) + { + // mouse motion handler + case SDL_MOUSEMOTION: + // we inject the mouse position directly. + CEGUI::System::getSingleton().injectMousePosition( + static_cast<float>(e.motion.x), + static_cast<float>(e.motion.y) + ); + break; + + // mouse down handler + case SDL_MOUSEBUTTONDOWN: + // let a special function handle the mouse button down event + handle_mouse_down(e.button.button); + break; + + // mouse up handler + case SDL_MOUSEBUTTONUP: + // let a special function handle the mouse button up event + handle_mouse_up(e.button.button); + break; + + + // key down + case SDL_KEYDOWN: + // to tell CEGUI that a key was pressed, we inject the scancode, translated from SDL + CEGUI::System::getSingleton().injectKeyDown(SDLKeyToCEGUIKey(e.key.keysym.sym)); + + // as for the character it's a litte more complicated. we'll use for translated unicode value. + // this is described in more detail below. + if ((e.key.keysym.unicode & 0xFF80) == 0) + { + CEGUI::System::getSingleton().injectChar(e.key.keysym.unicode & 0x7F); + } + break; + + // key up + case SDL_KEYUP: + // like before we inject the scancode translated from SDL. + CEGUI::System::getSingleton().injectKeyUp(SDLKeyToCEGUIKey(e.key.keysym.sym)); + break; + + + // WM quit event occured + case SDL_QUIT: + must_quit = true; + break; + + } + + } + +} diff --git a/src/gui/sdl/sdl_events.h b/src/gui/sdl/sdl_events.h new file mode 100644 index 00000000..1f475f08 --- /dev/null +++ b/src/gui/sdl/sdl_events.h @@ -0,0 +1,32 @@ +#include "SDL/SDL.h" +#include "CEGUI.h" + + + +#define SRCH_COUNTRY 1 +#define SRCH_TOWN 2 +#define SRCH_STREET 3 +#define SRCH_NUMBER 4 + +bool handleItemSelect(int r); +bool ItemSelect(const CEGUI::EventArgs& event); +bool handleMouseEnters(const CEGUI::EventArgs& event); +void handle_destination_change(); + +bool DestinationEntryChange(const CEGUI::EventArgs& event); +bool DialogWindowSwitch(const CEGUI::EventArgs& event); +bool RoadBookSwitch(const CEGUI::EventArgs& event); +bool ButtonGo(const CEGUI::EventArgs& event); +bool ZoomIn(const CEGUI::EventArgs& event); +bool ZoomOut(const CEGUI::EventArgs& event); +bool ButtonQuit(const CEGUI::EventArgs& event); + +void inject_time_pulse(double& last_time_pulse); + +bool Handle_Virtual_Key_Down(const CEGUI::EventArgs& event); + +CEGUI::uint SDLKeyToCEGUIKey(SDLKey key); + +void inject_input(bool& must_quit); + + diff --git a/src/item.c b/src/item.c new file mode 100644 index 00000000..4db0be71 --- /dev/null +++ b/src/item.c @@ -0,0 +1,132 @@ +#include <string.h> +#include <glib.h> +#include "attr.h" +#include "coord.h" +#include "item.h" + +struct item_name { + enum item_type item; + char *name; +}; + + +struct item_name item_names[]={ +#define ITEM2(x,y) ITEM(y) +#define ITEM(x) { type_##x, #x }, +#include "item_def.h" +#undef ITEM2 +#undef ITEM +}; + +void +item_coord_rewind(struct item *it) +{ + it->meth->item_coord_rewind(it->priv_data); +} + +int +item_coord_get(struct item *it, struct coord *c, int count) +{ + return it->meth->item_coord_get(it->priv_data, c, count); +} + +void +item_attr_rewind(struct item *it) +{ + it->meth->item_attr_rewind(it->priv_data); +} +int +item_attr_get(struct item *it, enum attr_type attr_type, struct attr *attr) +{ + return it->meth->item_attr_get(it->priv_data, attr_type, attr); +} + +struct item * item_new(char *type, int zoom) +{ + struct item * it; + + it = g_new0(struct item, 1); + + /* FIXME evaluate arguments */ + + return it; +} + +enum item_type +item_from_name(char *name) +{ + int i; + + for (i=0 ; i < sizeof(item_names)/sizeof(struct item_name) ; i++) { + if (! strcmp(item_names[i].name, name)) + return item_names[i].item; + } + return type_none; +} + +char * +item_to_name(enum item_type item) +{ + int i; + + for (i=0 ; i < sizeof(item_names)/sizeof(struct item_name) ; i++) { + if (item_names[i].item == item) + return item_names[i].name; + } + return NULL; +} + +struct item_hash { + GHashTable *h; +}; + +static guint +item_hash_hash(gconstpointer key) +{ + const struct item *itm=key; + gconstpointer hashkey=(gconstpointer)(itm->id_hi^itm->id_lo^((int) itm->map)); + return g_direct_hash(hashkey); +} + +static gboolean +item_hash_equal(gconstpointer a, gconstpointer b) +{ + const struct item *itm_a=a; + const struct item *itm_b=b; + if (item_is_equal(*itm_a, *itm_b)) + return TRUE; + return FALSE; +} + + + +struct item_hash * +item_hash_new(void) +{ + struct item_hash *ret=g_new(struct item_hash, 1); + + ret->h=g_hash_table_new_full(item_hash_hash, item_hash_equal, g_free, NULL); + return ret; +} + +void +item_hash_insert(struct item_hash *h, struct item *item, void *val) +{ + struct item *hitem=g_new(struct item, 1); + *hitem=*item; + g_hash_table_insert(h->h, hitem, val); +} + +void * +item_hash_lookup(struct item_hash *h, struct item *item) +{ + return g_hash_table_lookup(h->h, item); +} + + +void +item_hash_destroy(struct item_hash *h) +{ + g_hash_table_destroy(h->h); + g_free(h); +} diff --git a/src/item.h b/src/item.h new file mode 100644 index 00000000..00a8b3a1 --- /dev/null +++ b/src/item.h @@ -0,0 +1,50 @@ +#include "attr.h" + + +enum item_type { +#define ITEM2(x,y) type_##y=x, +#define ITEM(x) type_##x, +#include "item_def.h" +#undef ITEM2 +#undef ITEM +}; + +#define item_is_equal_id(a,b) ((a).id_hi == (b).id_hi && (a).id_lo == (b).id_lo) +#define item_is_equal(a,b) (item_is_equal_id(a,b) && (a).map == (b).map) + +struct coord; + +struct item_methods { + void (*item_coord_rewind)(void *priv_data); + int (*item_coord_get)(void *priv_data, struct coord *c, int count); + void (*item_attr_rewind)(void *priv_data); + int (*item_attr_get)(void *priv_data, enum attr_type attr_type, struct attr *attr); +}; + +struct item { + enum item_type type; + int id_hi; + int id_lo; + struct map *map; + struct item_methods *meth; + void *priv_data; +}; + +/* prototypes */ +enum attr_type; +enum item_type; +struct attr; +struct coord; +struct item; +struct item_hash; +void item_coord_rewind(struct item *it); +int item_coord_get(struct item *it, struct coord *c, int count); +void item_attr_rewind(struct item *it); +int item_attr_get(struct item *it, enum attr_type attr_type, struct attr *attr); +struct item *item_new(char *type, int zoom); +enum item_type item_from_name(char *name); +char *item_to_name(enum item_type item); +struct item_hash *item_hash_new(void); +void item_hash_insert(struct item_hash *h, struct item *item, void *val); +void *item_hash_lookup(struct item_hash *h, struct item *item); +void item_hash_destroy(struct item_hash *h); diff --git a/src/item_def.h b/src/item_def.h new file mode 100644 index 00000000..755497d2 --- /dev/null +++ b/src/item_def.h @@ -0,0 +1,131 @@ +ITEM2(0x00000000,none) +ITEM2(0x00000001,point_unspecified) +ITEM(town_streets) +ITEM(street_name) +ITEM(street_name_numbers) +ITEM(street_number) +/* Point */ +ITEM2(0x00010000,town_label) +ITEM2(0x00010001,town_label_0e0) +ITEM2(0x00010002,town_label_1e0) +ITEM2(0x00010003,town_label_2e0) +ITEM2(0x00010004,town_label_5e0) +ITEM2(0x00010005,town_label_1e1) +ITEM2(0x00010006,town_label_2e1) +ITEM2(0x00010007,town_label_5e1) +ITEM2(0x00010008,town_label_1e2) +ITEM2(0x00010009,town_label_2e2) +ITEM2(0x0001000a,town_label_5e2) +ITEM2(0x0001000b,town_label_1e3) +ITEM2(0x0001000c,town_label_2e3) +ITEM2(0x0001000d,town_label_5e3) +ITEM2(0x0001000e,town_label_1e4) +ITEM2(0x0001000f,town_label_2e4) +ITEM2(0x00010010,town_label_5e4) +ITEM2(0x00010011,town_label_1e5) +ITEM2(0x00010012,town_label_2e5) +ITEM2(0x00010013,town_label_5e5) +ITEM2(0x00010014,town_label_1e6) +ITEM2(0x00010015,town_label_2e6) +ITEM2(0x00010016,town_label_5e6) +ITEM2(0x00010017,town_label_1e7) +ITEM2(0x00010100,district_label) +ITEM2(0x00010101,district_label_0e0) +ITEM2(0x00010102,district_label_1e0) +ITEM2(0x00010103,district_label_2e0) +ITEM2(0x00010104,district_label_5e0) +ITEM2(0x00010105,district_label_1e1) +ITEM2(0x00010106,district_label_2e1) +ITEM2(0x00010107,district_label_5e1) +ITEM2(0x00010108,district_label_1e2) +ITEM2(0x00010109,district_label_2e2) +ITEM2(0x0001010a,district_label_5e2) +ITEM2(0x0001010b,district_label_1e3) +ITEM2(0x0001010c,district_label_2e3) +ITEM2(0x0001010d,district_label_5e3) +ITEM2(0x0001010e,district_label_1e4) +ITEM2(0x0001010f,district_label_2e4) +ITEM2(0x00010110,district_label_5e4) +ITEM2(0x00010111,district_label_1e5) +ITEM2(0x00010112,district_label_2e5) +ITEM2(0x00010113,district_label_5e5) +ITEM2(0x00010114,district_label_1e6) +ITEM2(0x00010115,district_label_2e6) +ITEM2(0x00010116,district_label_5e6) +ITEM2(0x00010117,district_label_1e7) +ITEM(country_label) +ITEM(town_ghost) +ITEM(highway_exit_label) +ITEM(port_label) +ITEM(label_unkn) +ITEM(highway_exit) +ITEM(poi_lake) +ITEM(poi_island) +ITEM(poi) +ITEM(waypoint) +ITEM(poi_land_feature) +ITEM(poi_cape) +ITEM(poi_rock) +ITEM(poi_airport) +ITEM(poi_toll_booth) +ITEM(poi_fuel) +ITEM(poi_hotel) +ITEM(poi_camp_rv) +ITEM(poi_marina) +ITEM(poi_attraction) +ITEM(poi_museum_history) +ITEM(poi_shopping) +ITEM(poi_car_dealer_parts) +ITEM(poi_car_parking) +ITEM(poi_wreck) +ITEM(poi_building) +ITEM(poi_bridge) +ITEM(poi_park) +ITEM(poi_water_feature) +ITEM(poi_bar) +ITEM(poi_picnic) +ITEM(poi_hospital) +ITEM(poi_camping) +ITEM(poi_public_utilities) +ITEM2(0x80000000,line) +ITEM2(0x80000001,line_unspecified) +/* Line */ +ITEM(border_country) +ITEM(border_state) +ITEM(rail) +ITEM(water_line) +ITEM(street_nopass) +ITEM(street_0) +ITEM(street_1_city) +ITEM(street_2_city) +ITEM(street_3_city) +ITEM(street_4_city) +ITEM(highway_city) +ITEM(street_1_land) +ITEM(street_2_land) +ITEM(street_3_land) +ITEM(street_4_land) +ITEM(street_n_lanes) +ITEM(highway_land) +ITEM(ramp) +ITEM(ferry) +ITEM(roadbook) +ITEM(street_unkn) +ITEM(street_route) +ITEM(height_line_1) +ITEM(height_line_2) +/* Area */ +ITEM2(0xc0000000,area) +ITEM2(0xc0000001,area_unspecified) +ITEM(wood) +ITEM(water_poly) +ITEM(town_poly) +ITEM(cemetery_poly) +ITEM(parking_lot_poly) +ITEM(industry_poly) +ITEM(airport_poly) +ITEM(hospital_poly) +ITEM(park_poly) +ITEM(sport_poly) +ITEM(image) +ITEM(image_path) diff --git a/src/layer.h b/src/layer.h new file mode 100644 index 00000000..3415cf94 --- /dev/null +++ b/src/layer.h @@ -0,0 +1,6 @@ +enum layer_type { + layer_town=0, + layer_street, + layer_poly, + layer_end, +}; diff --git a/src/layout.c b/src/layout.c new file mode 100644 index 00000000..0ca33599 --- /dev/null +++ b/src/layout.c @@ -0,0 +1,131 @@ +#include <glib.h> +#include <string.h> +#include "layout.h" + +struct layout * layout_new(const char *name) +{ + struct layout *l; + + l = g_new0(struct layout, 1); + l->name = g_strdup(name); + return l; +} + + +struct layer * layer_new(const char *name, int details) +{ + struct layer *l; + + l = g_new0(struct layer, 1); + l->name = g_strdup(name); + l->details = details; + return l; +} + +void layout_add_layer(struct layout *layout, struct layer *layer) +{ + layout->layers = g_list_append(layout->layers, layer); +} + +struct itemtype * itemtype_new(int zoom_min, int zoom_max) +{ + struct itemtype *itm; + + itm = g_new0(struct itemtype, 1); + itm->zoom_min=zoom_min; + itm->zoom_max=zoom_max; + return itm; +} + +void itemtype_add_type(struct itemtype *this, enum item_type type) +{ + this->type = g_list_append(this->type, GINT_TO_POINTER(type)); +} + + +void layer_add_itemtype(struct layer *layer, struct itemtype * itemtype) +{ + layer->itemtypes = g_list_append(layer->itemtypes, itemtype); + +} + +void itemtype_add_element(struct itemtype *itemtype, struct element *element) +{ + itemtype->elements = g_list_append(itemtype->elements, element); +} + +struct element * +polygon_new(struct color *color) +{ + struct element *e; + e = g_new0(struct element, 1); + e->type=element_polygon; + e->color=*color; + + return e; +} + +struct element * +polyline_new(struct color *color, int width) +{ + struct element *e; + + e = g_new0(struct element, 1); + e->type=element_polyline; + e->color=*color; + e->u.polyline.width=width; + + return e; +} + +struct element * +circle_new(struct color *color, int radius, int width, int label_size) +{ + struct element *e; + + e = g_new0(struct element, 1); + e->type=element_circle; + e->color=*color; + e->label_size=label_size; + e->u.circle.width=width; + e->u.circle.radius=radius; + + return e; +} + +struct element * +label_new(int label_size) +{ + struct element *e; + + e = g_new0(struct element, 1); + e->type=element_label; + e->label_size=label_size; + + return e; +} + +struct element * +icon_new(const char *src) +{ + struct element *e; + + e = g_malloc0(sizeof(*e)+strlen(src)+1); + e->type=element_icon; + e->u.icon.src=(char *)(e+1); + strcpy(e->u.icon.src,src); + + return e; +} + +struct element * +image_new(void) +{ + struct element *e; + + e = g_malloc0(sizeof(*e)); + e->type=element_image; + + return e; +} + diff --git a/src/layout.h b/src/layout.h new file mode 100644 index 00000000..ed96838e --- /dev/null +++ b/src/layout.h @@ -0,0 +1,59 @@ +#include "item.h" +#include "color.h" + +struct element_line; +struct element_text; + +struct element { + enum { element_point, element_polyline, element_polygon, element_circle, element_label, element_icon, element_image } type; + struct color color; + int label_size; + union { + struct element_point { + } point; + struct element_polyline { + int width; + } polyline; + struct element_polygon { + } polygon; + struct element_circle { + int width; + int radius; + } circle; + struct element_icon { + char *src; + } icon; + } u; +}; + + +struct itemtype { + int zoom_min, zoom_max; + GList *type; + GList *elements; +}; + +struct layer { char *name; int details; GList *itemtypes; }; + +struct layout { char *name; GList *layers; }; + +/* prototypes */ +enum item_type; +struct color; +struct element; +struct itemtype; +struct layer; +struct layout; +struct layout *layout_new(const char *name); +struct layer *layer_new(const char *name, int details); +void layout_add_layer(struct layout *layout, struct layer *layer); +struct itemtype *itemtype_new(int zoom_min, int zoom_max); +void itemtype_add_type(struct itemtype *this, enum item_type type); +void layer_add_itemtype(struct layer *layer, struct itemtype *itemtype); +void itemtype_add_element(struct itemtype *itemtype, struct element *element); +struct element *polygon_new(struct color *color); +struct element *polyline_new(struct color *color, int width); +struct element *circle_new(struct color *color, int radius, int width, int label_size); +struct element *label_new(int label_size); +struct element *icon_new(const char *src); +struct element *image_new(void); @@ -1,46 +1,59 @@ #include <locale.h> -#include <stdio.h> #include <stdlib.h> #include <glib.h> +#include <sys/types.h> +#include <sys/wait.h> #include <gtk/gtk.h> -#include "coord.h" -#include "vehicle.h" -#include "cursor.h" -#include "speech.h" -#include "route.h" -#include "map.h" -#include "map_data.h" -#if 0 -#include "map-share.h" +#include "file.h" +#include "debug.h" +#include "navit.h" +#include "gui.h" +#ifdef HAVE_PYTHON +#include "python.h" #endif -#include "transform.h" -#include "popup.h" #include "plugin.h" -#include "compass.h" -#include "track.h" -#include "container.h" -#include "debug.h" +#include "xmlconfig.h" -#include "osd.h" +struct map_data *map_data_default; -void *speech_handle; +static void sigchld(int sig) +{ + int status; + while (waitpid(-1, &status, WNOHANG) > 0); +} -struct container *co; -struct map_data *map_data_default; +static gchar *get_home_directory(void) +{ + static gchar *homedir = NULL; -struct container *gui_gtk_window(int x, int y, int scale); + if (homedir) return homedir; + homedir = getenv("HOME"); + if (!homedir) + { + struct passwd *p; + +// p = getpwuid(getuid()); +// if (p) homedir = p->pw_dir; + } + if (!homedir) + { + g_warning("Could not find home directory. Using current directory as home directory."); + homedir = "."; + } + return homedir; +} -extern void test(struct map_data *mdat); int main(int argc, char **argv) { + GError *error = NULL; + char *config_file = NULL; #if 0 - CORBA_Environment ev; - CORBA_ORB orb; - Map map_client = CORBA_OBJECT_NIL; + GMainLoop *loop; #endif - char *gps; + + signal(SIGCHLD, sigchld); setenv("LC_NUMERIC","C",1); setlocale(LC_ALL,""); @@ -51,58 +64,38 @@ int main(int argc, char **argv) gtk_init(&argc, &argv); gdk_rgb_init(); -// i18n basic support - - bindtextdomain( "navit", "./locale" ); - textdomain( "navit" ); - - map_data_default=load_maps(NULL); - plugin_load(); - co=gui_gtk_window(1300000,7000000,8192); - - co->route=route_new(); - route_mapdata_set(co->route, co->map_data); - gps=getenv("GPSDATA"); - if (gps) { - co->vehicle=vehicle_new(gps); - if (co->vehicle) { - co->cursor=cursor_new(co,co->vehicle); +#ifdef HAVE_PYTHON + python_init(); +#endif + if (argc > 1) + config_file=argv[1]; + else { + config_file=g_strjoin(NULL,get_home_directory(), "/.navit/navit.xml" , NULL); + if (!file_exists(config_file)) { + if (file_exists("navit.xml.local")) + config_file="navit.xml.local"; + else + config_file="navit.xml"; } - } else { - g_warning(gettext("Environment-Variable GPSDATA not set - No gps tracking. Set it to file:filename or gpsd://host[:port]")); } - co->speech=speech_new(); - if (! co->speech) - g_warning(gettext("Can't connect to speechd, no speech output available")); - speech_handle=co->speech; - if (co->vehicle) - co->compass=compass_new(co); - if (co->vehicle) - co->osd=osd_new(co); - if (co->vehicle) - co->track=track_new(co->map_data); - - -#if 0 - CORBA_exception_init(&ev); - orb = CORBA_ORB_init(&argc, argv, "orbit-local-orb", &ev); - g_assert(ev._major == CORBA_NO_EXCEPTION); - - map_srv_start_poa(orb, &ev); - g_assert(ev._major == CORBA_NO_EXCEPTION); - map_client = map_srv_start_object(&ev, map); - retval = CORBA_ORB_object_to_string(orb, map_client, &ev); - g_assert(ev._major == CORBA_NO_EXCEPTION); - ior=fopen("map.ior","w"); - if (ior) { - fprintf(ior, "%s\n", retval); - fclose(ior); + if (!config_load(config_file, &error)) { + g_error("Error parsing '%s': %s\n", config_file, error->message); + } else { + printf("Using '%s'\n", config_file); } - CORBA_free(retval); + if (main_loop_gui) { + gui_run_main_loop(main_loop_gui); + } else { +#if 1 + gtk_main(); +#else + loop = g_main_loop_new (NULL, TRUE); + if (g_main_loop_is_running (loop)) + { + g_main_loop_run (loop); + } #endif + } - gtk_main(); return 0; } - - diff --git a/src/map.c b/src/map.c new file mode 100644 index 00000000..b5f991e3 --- /dev/null +++ b/src/map.c @@ -0,0 +1,197 @@ +#include <glib.h> +#include <string.h> +#include "debug.h" +#include "coord.h" +#include "map.h" +#include "maptype.h" +#include "transform.h" +#include "projection.h" +#include "item.h" +#include "plugin.h" +#include "country.h" + +struct map { + struct map_methods meth; + struct map_priv *priv; + char *filename; + char *type; + char *charset; + int active; + enum projection projection; +}; + +struct map_rect { + struct map *m; + struct map_rect_priv *priv; +}; + +struct map * +map_new(const char *type, const char *filename) +{ + struct map *m; + struct map_priv *(*maptype_new)(struct map_methods *meth, const char *name, char **charset, enum projection *pro); + + maptype_new=plugin_get_map_type(type); + if (! maptype_new) + return NULL; + + m=g_new0(struct map, 1); + m->active=1; + m->filename=g_strdup(filename); + m->type=g_strdup(type); + m->priv=maptype_new(&m->meth, filename, &m->charset, &m->projection); + return m; +} + +char * +map_get_filename(struct map *this) +{ + return this->filename; +} + +char * +map_get_type(struct map *this) +{ + return this->type; +} + +int +map_get_active(struct map *this) +{ + return this->active; +} + +void +map_set_active(struct map *this, int active) +{ + this->active=active; +} + +int +map_requires_conversion(struct map *this) +{ + return (this->charset != NULL); +} + +char * +map_convert_string(struct map *this, char *str) +{ + return g_convert(str, -1,"utf-8",this->charset,NULL,NULL,NULL); +} + +void +map_convert_free(char *str) +{ + g_free(str); +} + +enum projection +map_projection(struct map *this) +{ + return this->projection; +} + +void +map_destroy(struct map *m) +{ + m->meth.map_destroy(m->priv); + g_free(m); +} + +struct map_rect * +map_rect_new(struct map *m, struct map_selection *sel) +{ + struct map_rect *mr; + +#if 0 + printf("map_rect_new 0x%x,0x%x-0x%x,0x%x\n", r->lu.x, r->lu.y, r->rl.x, r->rl.y); +#endif + mr=g_new0(struct map_rect, 1); + mr->m=m; + mr->priv=m->meth.map_rect_new(m->priv, sel); + + return mr; +} + +struct item * +map_rect_get_item(struct map_rect *mr) +{ + struct item *ret; + g_assert(mr != NULL); + g_assert(mr->m != NULL); + g_assert(mr->m->meth.map_rect_get_item != NULL); + ret=mr->m->meth.map_rect_get_item(mr->priv); + if (ret) + ret->map=mr->m; + return ret; +} + +struct item * +map_rect_get_item_byid(struct map_rect *mr, int id_hi, int id_lo) +{ + struct item *ret=NULL; + g_assert(mr != NULL); + g_assert(mr->m != NULL); + if (mr->m->meth.map_rect_get_item_byid) + ret=mr->m->meth.map_rect_get_item_byid(mr->priv, id_hi, id_lo); + if (ret) + ret->map=mr->m; + return ret; +} + +void +map_rect_destroy(struct map_rect *mr) +{ + mr->m->meth.map_rect_destroy(mr->priv); + g_free(mr); +} + +struct map_search { + struct map *m; + struct attr search_attr; + void *priv; +}; + +struct map_search * +map_search_new(struct map *m, struct item *item, struct attr *search_attr, int partial) +{ + struct map_search *this; + dbg(1,"enter(%p,%p,%p,%d)\n", m, item, search_attr, partial); + dbg(1,"0x%x 0x%x 0x%x\n", attr_country_all, search_attr->type, attr_country_name); + this=g_new0(struct map_search,1); + this->m=m; + this->search_attr=*search_attr; + if (search_attr->type >= attr_country_all && search_attr->type <= attr_country_name) + this->priv=country_search_new(&this->search_attr, partial); + else + this->priv=m->meth.map_search_new(m->priv, item, search_attr, partial); + + return this; +} + +struct item * +map_search_get_item(struct map_search *this) +{ + struct item *ret; + + if (! this) + return NULL; + if (this->search_attr.type >= attr_country_all && this->search_attr.type <= attr_country_name) + return country_search_get_item(this->priv); + ret=this->m->meth.map_search_get_item(this->priv); + if (ret) + ret->map=this->m; + return ret; +} + +void +map_search_destroy(struct map_search *this) +{ + if (! this) + return; + if (this->search_attr.type >= attr_country_all && this->search_attr.type <= attr_country_name) + country_search_destroy(this->priv); + else + this->m->meth.map_search_destroy(this->priv); + g_free(this); +} @@ -1,341 +1,44 @@ -/* - * This file was generated by orbit-idl-2 - DO NOT EDIT! - */ - -#ifndef map_H -#define map_H 1 -#include <glib.h> -#define ORBIT_IDL_SERIAL 20 -#include <orbit/orbit-types.h> - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -/** typedefs **/ -#if !defined(_PointObj_defined) -#define _PointObj_defined 1 - typedef struct PointObj_type PointObj; - struct PointObj_type - { - CORBA_float lng; - CORBA_float lat; - CORBA_float height; - }; - -#if !defined(TC_IMPL_TC_PointObj_0) -#define TC_IMPL_TC_PointObj_0 'm' -#define TC_IMPL_TC_PointObj_1 'a' -#define TC_IMPL_TC_PointObj_2 'p' -#ifdef ORBIT_IDL_C_IMODULE_map - static -#else - extern -#endif - const struct CORBA_TypeCode_struct TC_PointObj_struct; -#define TC_PointObj ((CORBA_TypeCode)&TC_PointObj_struct) -#endif -#define PointObj__alloc() ((PointObj *)ORBit_small_alloc (TC_PointObj)) -#define PointObj__freekids(m,d) ORBit_small_freekids (TC_PointObj,(m),(d)) -#endif -#if !defined(ORBIT_DECL_CORBA_sequence_PointObj) -#define ORBIT_DECL_CORBA_sequence_PointObj 1 -#define ORBIT_IMPL_CORBA_sequence_PointObj_0 'm' -#define ORBIT_IMPL_CORBA_sequence_PointObj_1 'a' -#define ORBIT_IMPL_CORBA_sequence_PointObj_2 'p' -#if !defined(_CORBA_sequence_PointObj_defined) -#define _CORBA_sequence_PointObj_defined 1 - typedef struct - { - CORBA_unsigned_long _maximum, - _length; - PointObj *_buffer; - CORBA_boolean _release; - } CORBA_sequence_PointObj; -#endif -#if !defined(TC_IMPL_TC_CORBA_sequence_PointObj_0) -#define TC_IMPL_TC_CORBA_sequence_PointObj_0 'm' -#define TC_IMPL_TC_CORBA_sequence_PointObj_1 'a' -#define TC_IMPL_TC_CORBA_sequence_PointObj_2 'p' -#ifdef ORBIT_IDL_C_IMODULE_map - static -#else - extern -#endif - const struct CORBA_TypeCode_struct TC_CORBA_sequence_PointObj_struct; -#define TC_CORBA_sequence_PointObj ((CORBA_TypeCode)&TC_CORBA_sequence_PointObj_struct) -#endif -#define CORBA_sequence_PointObj__alloc() ((CORBA_sequence_PointObj *)ORBit_small_alloc (TC_CORBA_sequence_PointObj)) -#define CORBA_sequence_PointObj__freekids(m,d) ORBit_small_freekids (TC_CORBA_sequence_PointObj,(m),(d)) -#define CORBA_sequence_PointObj_allocbuf(l) ((PointObj*)ORBit_small_allocbuf (TC_CORBA_sequence_PointObj, (l))) -#define CORBA_sequence_PointObj_allocbuf(l) ((PointObj*)ORBit_small_allocbuf (TC_CORBA_sequence_PointObj, (l))) -#endif -#if !defined(_PointObjSequence_defined) -#define _PointObjSequence_defined 1 - typedef CORBA_sequence_PointObj PointObjSequence; -#define PointObjSequence_marshal(x,y,z) CORBA_sequence_PointObj_marshal((x),(y),(z)) -#define PointObjSequence_demarshal(x,y,z,i) CORBA_sequence_PointObj_demarshal((x),(y),(z),(i)) -#if !defined(TC_IMPL_TC_PointObjSequence_0) -#define TC_IMPL_TC_PointObjSequence_0 'm' -#define TC_IMPL_TC_PointObjSequence_1 'a' -#define TC_IMPL_TC_PointObjSequence_2 'p' -#ifdef ORBIT_IDL_C_IMODULE_map - static -#else - extern -#endif - const struct CORBA_TypeCode_struct TC_PointObjSequence_struct; -#define TC_PointObjSequence ((CORBA_TypeCode)&TC_PointObjSequence_struct) -#endif -#define PointObjSequence__alloc() ((PointObjSequence *)ORBit_small_alloc (TC_CORBA_sequence_PointObj)) -#define PointObjSequence__freekids(m,d) ORBit_small_freekids (TC_CORBA_sequence_PointObj,(m),(d)) -#define PointObjSequence_allocbuf(l) ((PointObj*)ORBit_small_allocbuf (TC_CORBA_sequence_PointObj, (l))) -#endif -#if !defined(ORBIT_DECL_Mappel) && !defined(_Mappel_defined) -#define ORBIT_DECL_Mappel 1 -#define _Mappel_defined 1 -#define Mappel__freekids CORBA_Object__freekids - typedef CORBA_Object Mappel; - extern CORBA_unsigned_long Mappel__classid; -#if !defined(TC_IMPL_TC_Mappel_0) -#define TC_IMPL_TC_Mappel_0 'm' -#define TC_IMPL_TC_Mappel_1 'a' -#define TC_IMPL_TC_Mappel_2 'p' -#ifdef ORBIT_IDL_C_IMODULE_map - static -#else - extern -#endif - const struct CORBA_TypeCode_struct TC_Mappel_struct; -#define TC_Mappel ((CORBA_TypeCode)&TC_Mappel_struct) -#endif -#endif -#if !defined(ORBIT_DECL_Map) && !defined(_Map_defined) -#define ORBIT_DECL_Map 1 -#define _Map_defined 1 -#define Map__freekids CORBA_Object__freekids - typedef CORBA_Object Map; - extern CORBA_unsigned_long Map__classid; -#if !defined(TC_IMPL_TC_Map_0) -#define TC_IMPL_TC_Map_0 'm' -#define TC_IMPL_TC_Map_1 'a' -#define TC_IMPL_TC_Map_2 'p' -#ifdef ORBIT_IDL_C_IMODULE_map - static -#else - extern -#endif - const struct CORBA_TypeCode_struct TC_Map_struct; -#define TC_Map ((CORBA_TypeCode)&TC_Map_struct) -#endif -#endif - -/** POA structures **/ -#ifndef _defined_POA_Mappel -#define _defined_POA_Mappel 1 - typedef struct - { - void *_private; - void (*Test) (PortableServer_Servant _servant, CORBA_Environment * ev); - } POA_Mappel__epv; - typedef struct - { - PortableServer_ServantBase__epv *_base_epv; - POA_Mappel__epv *Mappel_epv; - } POA_Mappel__vepv; - typedef struct - { - void *_private; - POA_Mappel__vepv *vepv; - } POA_Mappel; - extern void POA_Mappel__init(PortableServer_Servant servant, - CORBA_Environment * ev); - extern void POA_Mappel__fini(PortableServer_Servant servant, - CORBA_Environment * ev); -#endif /* _defined_POA_Mappel */ -#ifndef _defined_POA_Map -#define _defined_POA_Map 1 - typedef struct - { - void *_private; - Map(*mapString) (PortableServer_Servant _servant, - const CORBA_char * astring, CORBA_double * anum, - CORBA_Environment * ev); - void (*doNothing) (PortableServer_Servant _servant, - CORBA_Environment * ev); - void (*doOneWay) (PortableServer_Servant _servant, - const CORBA_char * ignore, CORBA_Environment * ev); - void (*PlaceFlag) (PortableServer_Servant _servant, - CORBA_Environment * ev); - PointObj(*PointFromCoord) (PortableServer_Servant _servant, - const CORBA_char * coord, - CORBA_Environment * ev); - void (*View) (PortableServer_Servant _servant, const PointObj * where, - CORBA_Environment * ev); - void (*ViewAll) (PortableServer_Servant _servant, - const PointObjSequence * where, - CORBA_Environment * ev); - void (*Route) (PortableServer_Servant _servant, const PointObj * src, - const PointObj * dst, CORBA_Environment * ev); - Mappel(*Get) (PortableServer_Servant _servant, CORBA_Environment * ev); - } POA_Map__epv; - typedef struct - { - PortableServer_ServantBase__epv *_base_epv; - POA_Map__epv *Map_epv; - } POA_Map__vepv; - typedef struct - { - void *_private; - POA_Map__vepv *vepv; - } POA_Map; - extern void POA_Map__init(PortableServer_Servant servant, - CORBA_Environment * ev); - extern void POA_Map__fini(PortableServer_Servant servant, - CORBA_Environment * ev); -#endif /* _defined_POA_Map */ - -/** skel prototypes **/ - void _ORBIT_skel_small_Mappel_Test(POA_Mappel * _ORBIT_servant, - gpointer _ORBIT_retval, - gpointer * _ORBIT_args, - CORBA_Context ctx, - CORBA_Environment * ev, - void (*_impl_Test) - (PortableServer_Servant _servant, - CORBA_Environment * ev)); - void _ORBIT_skel_small_Map_mapString(POA_Map * _ORBIT_servant, - gpointer _ORBIT_retval, - gpointer * _ORBIT_args, - CORBA_Context ctx, - CORBA_Environment * ev, - Map(*_impl_mapString) - (PortableServer_Servant _servant, - const CORBA_char * astring, - CORBA_double * anum, - CORBA_Environment * ev)); - void _ORBIT_skel_small_Map_doNothing(POA_Map * _ORBIT_servant, - gpointer _ORBIT_retval, - gpointer * _ORBIT_args, - CORBA_Context ctx, - CORBA_Environment * ev, - void (*_impl_doNothing) - (PortableServer_Servant _servant, - CORBA_Environment * ev)); - void _ORBIT_skel_small_Map_doOneWay(POA_Map * _ORBIT_servant, - gpointer _ORBIT_retval, - gpointer * _ORBIT_args, - CORBA_Context ctx, - CORBA_Environment * ev, - void (*_impl_doOneWay) - (PortableServer_Servant _servant, - const CORBA_char * ignore, - CORBA_Environment * ev)); - void _ORBIT_skel_small_Map_PlaceFlag(POA_Map * _ORBIT_servant, - gpointer _ORBIT_retval, - gpointer * _ORBIT_args, - CORBA_Context ctx, - CORBA_Environment * ev, - void (*_impl_PlaceFlag) - (PortableServer_Servant _servant, - CORBA_Environment * ev)); - void _ORBIT_skel_small_Map_PointFromCoord(POA_Map * _ORBIT_servant, - gpointer _ORBIT_retval, - gpointer * _ORBIT_args, - CORBA_Context ctx, - CORBA_Environment * ev, - PointObj(*_impl_PointFromCoord) - (PortableServer_Servant _servant, - const CORBA_char * coord, - CORBA_Environment * ev)); - void _ORBIT_skel_small_Map_View(POA_Map * _ORBIT_servant, - gpointer _ORBIT_retval, - gpointer * _ORBIT_args, CORBA_Context ctx, - CORBA_Environment * ev, - void (*_impl_View) (PortableServer_Servant - _servant, - const PointObj * where, - CORBA_Environment * - ev)); - void _ORBIT_skel_small_Map_ViewAll(POA_Map * _ORBIT_servant, - gpointer _ORBIT_retval, - gpointer * _ORBIT_args, - CORBA_Context ctx, - CORBA_Environment * ev, - void (*_impl_ViewAll) - (PortableServer_Servant _servant, - const PointObjSequence * where, - CORBA_Environment * ev)); - void _ORBIT_skel_small_Map_Route(POA_Map * _ORBIT_servant, - gpointer _ORBIT_retval, - gpointer * _ORBIT_args, CORBA_Context ctx, - CORBA_Environment * ev, - void (*_impl_Route) - (PortableServer_Servant _servant, - const PointObj * src, - const PointObj * dst, - CORBA_Environment * ev)); - void _ORBIT_skel_small_Map_Get(POA_Map * _ORBIT_servant, - gpointer _ORBIT_retval, - gpointer * _ORBIT_args, CORBA_Context ctx, - CORBA_Environment * ev, - Mappel(*_impl_Get) (PortableServer_Servant - _servant, - CORBA_Environment * - ev)); - -/** stub prototypes **/ - void Mappel_Test(Mappel _obj, CORBA_Environment * ev); - Map Map_mapString(Map _obj, const CORBA_char * astring, - CORBA_double * anum, CORBA_Environment * ev); - void Map_doNothing(Map _obj, CORBA_Environment * ev); - void Map_doOneWay(Map _obj, const CORBA_char * ignore, - CORBA_Environment * ev); - void Map_PlaceFlag(Map _obj, CORBA_Environment * ev); - PointObj Map_PointFromCoord(Map _obj, const CORBA_char * coord, - CORBA_Environment * ev); - void Map_View(Map _obj, const PointObj * where, CORBA_Environment * ev); - void Map_ViewAll(Map _obj, const PointObjSequence * where, - CORBA_Environment * ev); - void Map_Route(Map _obj, const PointObj * src, const PointObj * dst, - CORBA_Environment * ev); - Mappel Map_Get(Map _obj, CORBA_Environment * ev); -#include <orbit/orb-core/orbit-interface.h> - -#ifdef ORBIT_IDL_C_IMODULE_map - static -#else - extern -#endif - ORBit_IInterface Mappel__iinterface; -#define Mappel_IMETHODS_LEN 1 -#ifdef ORBIT_IDL_C_IMODULE_map - static -#else - extern -#endif - ORBit_IMethod Mappel__imethods[Mappel_IMETHODS_LEN]; -#ifdef ORBIT_IDL_C_IMODULE_map - static -#else - extern -#endif - ORBit_IInterface Map__iinterface; -#define Map_IMETHODS_LEN 9 -#ifdef ORBIT_IDL_C_IMODULE_map - static -#else - extern -#endif - ORBit_IMethod Map__imethods[Map_IMETHODS_LEN]; -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#ifndef EXCLUDE_ORBIT_H -#include <orbit/orbit.h> - -#endif /* EXCLUDE_ORBIT_H */ -#endif -#undef ORBIT_IDL_SERIAL +struct map_priv; +struct attr; +#include "coord.h" +#include "layer.h" + +struct map_selection { + struct map_selection *next; + struct coord_rect rect; + int order[layer_end]; +}; + +struct map_methods { + void (*map_destroy)(struct map_priv *priv); + struct map_rect_priv * (*map_rect_new)(struct map_priv *map, struct map_selection *sel); + void (*map_rect_destroy)(struct map_rect_priv *mr); + struct item * (*map_rect_get_item)(struct map_rect_priv *mr); + struct item * (*map_rect_get_item_byid)(struct map_rect_priv *mr, int id_hi, int id_lo); + struct map_search_priv *(*map_search_new)(struct map_priv *map, struct item *item, struct attr *search, int partial); + void (*map_search_destroy)(struct map_search_priv *ms); + struct item * (*map_search_get_item)(struct map_search_priv *ms); +}; + +/* prototypes */ +enum projection; +struct attr; +struct item; +struct map; +struct map_rect; +struct map_search; +struct map_selection; +struct map *map_new(const char *type, const char *filename); +char *map_get_filename(struct map *this); +char *map_get_type(struct map *this); +int map_get_active(struct map *this); +void map_set_active(struct map *this, int active); +enum projection map_projection(struct map *this); +void map_destroy(struct map *m); +struct map_rect *map_rect_new(struct map *m, struct map_selection *sel); +struct item *map_rect_get_item(struct map_rect *mr); +struct item *map_rect_get_item_byid(struct map_rect *mr, int id_hi, int id_lo); +void map_rect_destroy(struct map_rect *mr); +struct map_search *map_search_new(struct map *m, struct item *item, struct attr *search_attr, int partial); +struct item *map_search_get_item(struct map_search *this); +void map_search_destroy(struct map_search *this); diff --git a/src/mapset.c b/src/mapset.c new file mode 100644 index 00000000..17fbecf3 --- /dev/null +++ b/src/mapset.c @@ -0,0 +1,116 @@ +#include <glib.h> +#include <glib/gprintf.h> +#include "debug.h" +#include "attr.h" +#include "mapset.h" +#include "map.h" + +struct mapset { + GList *maps; +}; + +struct mapset *mapset_new(void) +{ + struct mapset *ms; + + ms=g_new0(struct mapset, 1); + + return ms; +} + +void mapset_add(struct mapset *ms, struct map *m) +{ + ms->maps=g_list_append(ms->maps, m); +} + +#if 0 +static void mapset_maps_free(struct mapset *ms) +{ + /* todo */ +} +#endif + +void mapset_destroy(struct mapset *ms) +{ + g_free(ms); +} + +struct mapset_handle { + GList *l; +}; + +struct mapset_handle * +mapset_open(struct mapset *ms) +{ + struct mapset_handle *ret; + + ret=g_new(struct mapset_handle, 1); + ret->l=ms->maps; + + return ret; +} + +struct map * mapset_next(struct mapset_handle *msh, int active) +{ + struct map *ret; + + for (;;) { + if (!msh->l) + return NULL; + ret=msh->l->data; + msh->l=g_list_next(msh->l); + if (!active || map_get_active(ret)) + return ret; + } +} + +void +mapset_close(struct mapset_handle *msh) +{ + g_free(msh); +} + +struct mapset_search { + GList *map; + struct map_search *ms; + struct item *item; + struct attr *search_attr; + int partial; +}; + +struct mapset_search * +mapset_search_new(struct mapset *ms, struct item *item, struct attr *search_attr, int partial) +{ + struct mapset_search *this; + dbg(1,"enter(%p,%p,%p,%d)\n", ms, item, search_attr, partial); + this=g_new0(struct mapset_search,1); + this->map=ms->maps; + this->item=item; + this->search_attr=search_attr; + this->partial=partial; + this->ms=map_search_new(this->map->data, item, search_attr, partial); + return this; +} + +struct item * +mapset_search_get_item(struct mapset_search *this) +{ + struct item *ret; + while (!(ret=map_search_get_item(this->ms))) { + if (this->search_attr->type >= attr_country_all && this->search_attr->type <= attr_country_name) + break; + this->map=g_list_next(this->map); + if (! this->map) + break; + map_search_destroy(this->ms); + this->ms=map_search_new(this->map->data, this->item, this->search_attr, this->partial); + } + return ret; +} + +void +mapset_search_destroy(struct mapset_search *this) +{ + map_search_destroy(this->ms); + g_free(this); +} diff --git a/src/mapset.h b/src/mapset.h new file mode 100644 index 00000000..6998486d --- /dev/null +++ b/src/mapset.h @@ -0,0 +1,16 @@ +/* prototypes */ +struct attr; +struct item; +struct map; +struct mapset; +struct mapset_handle; +struct mapset_search; +struct mapset *mapset_new(void); +void mapset_add(struct mapset *ms, struct map *m); +void mapset_destroy(struct mapset *ms); +struct mapset_handle *mapset_open(struct mapset *ms); +struct map *mapset_next(struct mapset_handle *msh, int active); +void mapset_close(struct mapset_handle *msh); +struct mapset_search *mapset_search_new(struct mapset *ms, struct item *item, struct attr *search_attr, int partial); +struct item *mapset_search_get_item(struct mapset_search *this); +void mapset_search_destroy(struct mapset_search *this); diff --git a/src/maptype.c b/src/maptype.c new file mode 100644 index 00000000..81039613 --- /dev/null +++ b/src/maptype.c @@ -0,0 +1,29 @@ +#include <glib.h> +#include "map.h" +#include "maptype.h" + +static struct maptype *maptype_root; + +void +maptype_register(char *name, struct map_priv *(*map_new)(struct map_methods *meth, char *data, char **charset, enum projection *pro)) +{ + struct maptype *mt; + mt=g_new(struct maptype, 1); + mt->name=g_strdup(name); + mt->map_new=map_new; + mt->next=maptype_root; + maptype_root=mt; +} + +struct maptype * +maptype_get(const char *name) +{ + struct maptype *mt=maptype_root; + + while (mt) { + if (!g_ascii_strcasecmp(mt->name, name)) + return mt; + mt=mt->next; + } + return NULL; +} diff --git a/src/maptype.h b/src/maptype.h new file mode 100644 index 00000000..1a41da53 --- /dev/null +++ b/src/maptype.h @@ -0,0 +1,15 @@ +struct map_methods; + +struct maptype { + char *name; + struct map_priv *(*map_new)(struct map_methods *meth, char *data); + struct maptype *next; +}; + +/* prototypes */ +enum projection; +struct map_methods; +struct map_priv; +struct maptype; +void maptype_register(char *name, struct map_priv *(*map_new)(struct map_methods *meth, char *data, char **charset, enum projection *pro)); +struct maptype *maptype_get(const char *name); @@ -1,36 +1,52 @@ -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <math.h> -#include <time.h> -#include "coord.h" -#include "data_window.h" -#include "route.h" -#include "cursor.h" +#include <glib.h> #include "menu.h" -#include "command.h" -#include "transform.h" -#include "street.h" -#include "statusbar.h" -#include "destination.h" -#include "main.h" -#include "container.h" -#include "graphics.h" void menu_route_do_update(struct container *co) { +#if 0 if (co->cursor) { +#if 0 /* FIXME */ route_set_position(co->route, cursor_pos_get(co->cursor)); +#endif graphics_redraw(co); if (co->statusbar && co->statusbar->statusbar_route_update) co->statusbar->statusbar_route_update(co->statusbar, co->route); } +#endif } void menu_route_update(struct container *co) { +#if 0 menu_route_do_update(co); graphics_redraw(co); +#endif +} + +struct menu * +menu_add(struct menu *menu, char *name, enum menu_type type, void (*callback)(struct menu *menu, void *data1, void *data2), void *data1, void *data2) +{ + struct menu *this; + this=g_new0(struct menu, 1); + this->priv=(*menu->meth.add)(menu->priv, &this->meth, name, type, callback, this, data1, data2); + if (! this->priv) { + g_free(this); + return NULL; + } + + return this; +} + +void +menu_set_toggle(struct menu *menu, int active) +{ + (*menu->meth.set_toggle)(menu->priv, active); +} + +int +menu_get_toggle(struct menu *menu) +{ + return (*menu->meth.get_toggle)(menu->priv); } @@ -1,8 +1,27 @@ +enum menu_type { + menu_type_submenu, + menu_type_menu, + menu_type_toggle, +}; + +struct menu; + +struct menu_methods { + struct menu_priv *(*add)(struct menu_priv *menu, struct menu_methods *meth, char *name, enum menu_type type, void (*callback)(struct menu *data_menu, void *data1, void *data2), struct menu *data_menu, void *data1, void *data2); + void (*set_toggle)(struct menu_priv *menu, int active); + int (*get_toggle)(struct menu_priv *menu); +}; + struct menu { - struct menu_gui *gui; + struct menu_priv *priv; + struct menu_methods meth; }; +/* prototypes */ struct container; - +struct menu; void menu_route_do_update(struct container *co); void menu_route_update(struct container *co); +struct menu *menu_add(struct menu *menu, char *name, enum menu_type type, void (*callback)(struct menu *menu, void *data1, void *data2), void *data1, void *data2); +void menu_set_toggle(struct menu *menu, int active); +int menu_get_toggle(struct menu *menu); diff --git a/src/navigation.c b/src/navigation.c index c6a7e3e0..20125be6 100644 --- a/src/navigation.c +++ b/src/navigation.c @@ -1,341 +1,359 @@ -#include <math.h> -#include <string.h> -#include <stdlib.h> #include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <glib.h> +#include "debug.h" +#include "navigation.h" #include "coord.h" -#include "graphics.h" -#include "param.h" -#include "block.h" +#include "item.h" #include "route.h" -#include "street.h" -#include "street_name.h" -#include "speech.h" -#include "navigation.h" -#include "data_window.h" -#include "osd.h" +#include "transform.h" +#include "mapset.h" +#include "map.h" +#include "navit.h" +#include "callback.h" -struct data_window *navigation_window; +struct navigation { + struct mapset *ms; + struct navigation_itm *first; + struct navigation_itm *last; + struct navigation_command *cmd_first; + struct navigation_command *cmd_last; + struct callback_list *callback_speech; + struct callback_list *callback; +}; -struct navigation_item { - char name1[128]; - char name2[128]; - int length; - int time; - int crossings_start; - int crossings_end; +struct navigation_command { + struct navigation_itm *itm; + struct navigation_command *next; + int delta; +}; + +struct navigation_list { + struct navigation *nav; + struct navigation_command *cmd; + struct navigation_itm *itm; + char *str; +}; + +struct street_data { + struct item item; + int count; + int limit; + struct coord c[0]; +}; + + +struct navigation * +navigation_new(struct mapset *ms) +{ + struct navigation *ret=g_new(struct navigation, 1); + ret->ms=ms; + ret->callback=callback_list_new(); + ret->callback_speech=callback_list_new(); + + return ret; +} + +struct navigation_itm { + char *name1; + char *name2; + struct coord start; + struct item item; int angle_start; int angle_end; - int points; - struct coord start; - struct coord end; + int time; + int length; + int dest_time; + int dest_length; + struct navigation_itm *next; + struct navigation_itm *prev; }; +/* 0=N,90=E */ static int -road_angle(struct coord *c, int dir) +road_angle(struct coord *c1, struct coord *c2, int dir) { - double angle; - int dx=c[1].x-c[0].x; - int dy=c[1].y-c[0].y; - angle=atan2(dx,dy); - angle*=180/M_PI; - if (dir == -1) - angle=angle-180; - if (angle < 0) - angle+=360; - return angle; + int ret=transform_get_angle_delta(c1, c2, dir); + dbg(1, "road_angle(0x%x,0x%x - 0x%x,0x%x)=%d\n", c1->x, c1->y, c2->x, c2->y, ret); + return ret; } -static void -expand_str(char *str) +static struct navigation_itm * +navigation_itm_new(struct navigation *this_, struct item *item, struct coord *start) { - int len=strlen(str); - if (len > 4 && !strcmp(str+len-4,"str.")) - strcpy(str+len-4,"strasse"); - if (len > 4 && !strcmp(str+len-4,"Str.")) - strcpy(str+len-4,"Strasse"); + struct navigation_itm *ret=g_new0(struct navigation_itm, 1); + int l,i=0,a1,a2,dir=0; + struct map_rect *mr; + struct attr attr; + struct coord c[5]; + + if (item) { + mr=map_rect_new(item->map, NULL); + item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo); + if (item_attr_get(item, attr_street_name, &attr)) + ret->name1=g_strdup(attr.u.str); + if (item_attr_get(item, attr_street_name_systematic, &attr)) + ret->name2=g_strdup(attr.u.str); + ret->item=*item; + l=-1; + while (item_coord_get(item, &c[i], 1)) { + dbg(1, "coord %d 0x%x 0x%x\n", i, c[i].x ,c[i].y); + l=i; + if (i < 4) + i++; + else { + c[2]=c[3]; + c[3]=c[4]; + } + } + dbg(1,"count=%d\n", l); + if (l == 4) + l=3; + if (start->x != c[0].x || start->y != c[0].y) + dir=-1; + a1=road_angle(&c[0], &c[1], dir); + a2=road_angle(&c[l-1], &c[l], dir); + if (dir >= 0) { + ret->angle_start=a1; + ret->angle_end=a2; + } else { + ret->angle_start=a2; + ret->angle_end=a1; + } + dbg(1,"i=%d a1 %d a2 %d '%s' '%s'\n", i, a1, a2, ret->name1, ret->name2); + map_rect_destroy(mr); + } + if (start) + ret->start=*start; + if (! this_->first) + this_->first=ret; + if (this_->last) { + this_->last->next=ret; + ret->prev=this_->last; + } + this_->last=ret; + return ret; } static void -navigation_goto(struct data_window *navigation_window, char **cols) +calculate_dest_distance(struct navigation *this_) { - extern struct container *co; - long x,y; - - printf("goto %s\n",cols[8]); - sscanf(cols[8],"%lx,%lx",&x,&y); - graphics_set_view(co, &x, &y, NULL); + int len=0, time=0; + struct navigation_itm *itm=this_->last; + while (itm) { + len+=itm->length; + time+=itm->time; + itm->dest_length=len; + itm->dest_time=time; + itm=itm->prev; + } + printf("len %d time %d\n", len, time); } static int -is_same_street(struct navigation_item *old, struct navigation_item *new) +is_same_street2(struct navigation_itm *old, struct navigation_itm *new) { - if (strlen(old->name2) && !strcmp(old->name2, new->name2)) { - strcpy(old->name1, new->name1); + if (old->name1 && new->name1 && !strcmp(old->name1, new->name1)) { + dbg(1,"is_same_street: '%s' '%s' vs '%s' '%s' yes (1.)\n", old->name2, new->name2, old->name1, new->name1); return 1; } - if (strlen(old->name1) && !strcmp(old->name1, new->name1)) { - strcpy(old->name2, new->name2); + if (old->name2 && new->name2 && !strcmp(old->name2, new->name2)) { + dbg(1,"is_same_street: '%s' '%s' vs '%s' '%s' yes (2.)\n", old->name2, new->name2, old->name1, new->name1); return 1; } + dbg(1,"is_same_street: '%s' '%s' vs '%s' '%s' no\n", old->name2, new->name2, old->name1, new->name1); return 0; } static int -maneuver_required(struct navigation_item *old, struct navigation_item *new, int *delta) +maneuver_required2(struct navigation_itm *old, struct navigation_itm *new, int *delta) { - if (is_same_street(old, new)) + dbg(1,"enter %p %p %p\n",old, new, delta); + if (new->item.type == type_ramp && old && (old->item.type == type_highway_land || old->item.type == type_highway_city)) { + dbg(1, "maneuver_required: new is ramp from highway: yes\n"); + return 1; + } + if (is_same_street2(old, new)) { + dbg(1, "maneuver_required: is_same_street: no\n"); return 0; - if (old->crossings_end == 2) + } +#if 0 + if (old->crossings_end == 2) { + dbg(1, "maneuver_required: only 2 connections: no\n"); return 0; + } +#endif *delta=new->angle_start-old->angle_end; if (*delta < -180) *delta+=360; if (*delta > 180) *delta-=360; - if (*delta < 20 && *delta >-20) + if (*delta < 20 && *delta >-20) { + dbg(1, "maneuver_required: delta(%d) < 20: no\n", *delta); return 0; + } + dbg(1, "maneuver_required: delta=%d: yes\n", *delta); return 1; } -int flag,old_level; -extern void *speech_handle; +static struct navigation_command * +command_new(struct navigation *this_, struct navigation_itm *itm, int delta) +{ + struct navigation_command *ret=g_new0(struct navigation_command, 1); + ret->delta=delta; + ret->itm=itm; + if (this_->cmd_last) + this_->cmd_last->next=ret; + this_->cmd_last=ret; + if (!this_->cmd_first) + this_->cmd_first=ret; + return ret; +} static void -get_distance(char *dst, int dist) +make_maneuvers(struct navigation *this_) { - if (dist < 100) { - dist=(dist+5)/10; - dist*=10; - sprintf(dst,gettext("%d meter"), dist); - return; - } - if (dist < 250) { - dist=(dist+13)/25; - dist*=25; - sprintf(dst,gettext("%d meter"), dist); - return; - } - if (dist < 500) { - dist=(dist+25)/50; - dist*=50; - sprintf(dst,gettext("%d meter"), dist); - return; - } - if (dist < 1000) { - dist=(dist+50)/100; - dist*=100; - sprintf(dst,gettext("%d meter"), dist); - return; + struct navigation_itm *itm, *last=NULL, *last_itm=NULL; + itm=this_->first; + int delta; + this_->cmd_last=NULL; + this_->cmd_first=NULL; + while (itm) { + if (last) { + if (maneuver_required2(last_itm, itm, &delta)) { + command_new(this_, itm, delta); + } + } else + last=itm; + last_itm=itm; + itm=itm->next; } - if (dist < 5000) { - dist=(dist+50)/100; - if (dist % 10) - sprintf(dst,gettext("%d,%d kilometer"), dist/10,dist%10); - else - sprintf(dst,gettext("%d kilometer"), dist/10); - return; +} + +static char * +show_maneuver(struct navigation_itm *itm, struct navigation_command *cmd, int mode) +{ + char *dir="rechts",*strength=""; + int distance=itm->dest_length-cmd->itm->dest_length; + int delta=cmd->delta; + if (delta < 0) { + dir="links"; + delta=-delta; } - if (dist < 100000) { - dist=(dist+500)/1000; - sprintf(dst,gettext("%d kilometer"), dist); - return; + if (delta < 45) { + strength="leicht "; + } else if (delta < 105) { + strength=""; + } else if (delta < 165) { + strength="scharf "; + } else { + dbg(0,"delta=%d\n", delta); + strength="unbekannt "; } - dist=(dist+5000)/10000; - dist*=10; - sprintf(dst,gettext("%d kilometer"), dist); + if (cmd->itm->next) + return g_strdup_printf("In %d m %s%s abbiegen", distance, strength, dir); + else + return g_strdup_printf("In %d m haben Sie ihr Ziel erreicht", distance); } -static void -make_maneuver(struct navigation_item *old, struct navigation_item *new) +struct navigation_list * +navigation_list_new(struct navigation *this_) { - - int delta,navmode=1,add_dir,level; - struct param_list param_list[20]; - - char roadname[256]; + struct navigation_list *ret=g_new0(struct navigation_list, 1); + ret->nav=this_; + ret->cmd=this_->cmd_first; + ret->itm=this_->first; + return ret; +} - char angle_old[30],angle_new[30],angle_delta[30],cross_roads[30],position[30],distance[30]; - char command[256],*p,*dir,*strength; - char dist[256]; +char * +navigation_list_get(struct navigation_list *this_, enum navigation_mode mode) +{ + if (!this_->cmd) + return NULL; + g_free(this_->str); + this_->str=show_maneuver(this_->itm, this_->cmd, mode); + this_->itm=this_->cmd->itm; + this_->cmd=this_->cmd->next; - param_list[0].name="Name1 Old"; - param_list[0].value=old->name1; - param_list[1].name="Name2 Old"; - param_list[1].value=old->name2; - param_list[2].name="Name1 New"; - param_list[2].value=new->name1; - param_list[3].name="Name2 New"; - param_list[3].value=new->name2; - param_list[4].name="Angle\nOld"; - param_list[5].name="Angle\nNew"; - param_list[6].name="Delta"; - param_list[7].name="X-\nRoads"; - param_list[8].name="Position"; - param_list[9].name="Dist"; - param_list[10].name="Command"; - if (old->points) { - if (!maneuver_required(old, new, &delta)) { - old->length+=new->length; - old->time+=new->time; - old->crossings_end=new->crossings_end; - old->angle_end=new->angle_end; - old->points+=new->points; - } else { - sprintf(angle_old,"%d", old->angle_end); - param_list[4].value=angle_old; - sprintf(angle_new,"%d", new->angle_start); - param_list[5].value=angle_new; - sprintf(angle_delta,"%d", delta); - param_list[6].value=angle_delta; - sprintf(cross_roads,"%d", old->crossings_end); - param_list[7].value=cross_roads; - sprintf(position,"0x%lx,0x%lx", new->start.x, new->start.y); - param_list[8].value=position; - sprintf(distance,"%d", old->length); - param_list[9].value=distance; - add_dir=1; - dir=gettext("rechts"); - if (delta < 0) { - dir=gettext("links"); - delta=-delta; - } - if (delta < 45) { - strength=gettext("leicht "); - } else if (delta < 105) { - strength=""; - } else if (delta < 165) { - strength=gettext("scharf "); - } else { -#ifdef DEBUG - printf("delta=%d\n", delta); -#endif - strength=gettext("unbekannt "); - } - level=0; - if (navmode) { - if (old->length < 20) { - level=1; - sprintf(command,gettext("Jetzt ")); - } else if (old->length <= 200) { - level=2; - get_distance(dist, old->length); - sprintf(command,gettext("In %sn "), dist); - } else if (old->length <= 500) { - level=3; - sprintf(command,gettext("In Kürze ")); - } else { - level=4; - get_distance(dist, old->length); - sprintf(command,gettext("Dem Strassenverlauf %s folgen"), dist); - add_dir=0; - } - } else { - sprintf(command,gettext("Dem Strassenverlauf %d Meter folgen, dann "), old->length); - add_dir=1; - } - if (add_dir) { -/* p=command+strlen(command); - strcpy(p,strength); - p+=strlen(p); - strcpy(p,dir); - p+=strlen(p); - strcpy(p,gettext(" abbiegen"));*/ - sprintf(command,gettext(" %s %s abbiegen"),strength,dir); - p=command+strlen(command); - } - param_list[10].value=command; - if (flag) { - sprintf(roadname,"%s %s",old->name1,old->name2); - osd_set_next_command(command,roadname); - if (level != old_level) { - printf("command='%s'\n", command); - if (speech_handle) - speech_say(speech_handle, command); - old_level=level; - } - flag=0; - } - data_window_add(navigation_window, param_list, 11); - *old=*new; - } - } else { - *old=*new; - } + return this_->str; } + void -navigation_path_description(void *route) +navigation_list_destroy(struct navigation_list *this_) { - int id; - struct route_path_segment *curr=route_path_get_all(route); - struct block_info blk_inf; - struct street_str *str; - struct street_name name; - struct street_coord *coord; - struct map_data *mdata=route_mapdata_get(route); - struct coord *start,*end,*tmp; - int angle_start, angle_end, angle_tmp; - struct route_crossings *crossings_start,*crossings_end; - struct navigation_item item_curr,item_last; + g_free(this_->str); + g_free(this_); +} - memset(&item_last,0,sizeof(item_last)); +void +navigation_update(struct navigation *this_, struct route *route) +{ + struct route_path_handle *rph; + struct route_path_segment *s; + struct navigation_itm *itm; + struct route_info *pos,*dst; + struct street_data *sd; + int len,end_flag=0; + void *p; - if (!navigation_window) - navigation_window=data_window("Navigation",NULL,navigation_goto); - data_window_begin(navigation_window); - flag=1; - while (curr) { - str=NULL; - id=curr->segid; - if (id) { - if (id < 0) - id=-id; - street_get_by_id(mdata, curr->country, id, &blk_inf, &str); - coord=street_coord_get(&blk_inf, str); - start=coord->c; - end=coord->c+coord->count-1; - angle_start=road_angle(coord->c, curr->dir); - if (coord->count > 2) - angle_end=road_angle(coord->c+coord->count-2,curr->dir); - else - angle_end=angle_start; - if (curr->dir < 0) { - tmp=start; - angle_tmp=angle_start; - start=end; - angle_start=angle_end; - end=tmp; - angle_end=angle_tmp; - } - crossings_start=route_crossings_get(route, start); - crossings_end=route_crossings_get(route, end); - if (str && str->nameid) { - street_name_get_by_id(&name, blk_inf.mdata, str->nameid); - strcpy(item_curr.name1,name.name1); - strcpy(item_curr.name2,name.name2); - expand_str(item_curr.name1); - expand_str(item_curr.name2); - } else { - item_curr.name1[0]='\0'; - item_curr.name2[0]='\0'; - } - item_curr.length=curr->length; - item_curr.time=curr->time; - item_curr.crossings_start=crossings_start->count; - item_curr.crossings_end=crossings_end->count; - item_curr.angle_start=angle_start; - item_curr.angle_end=angle_end; - item_curr.points=coord->count; - item_curr.start=*start; - item_curr.end=*end; - make_maneuver(&item_last,&item_curr); - free(coord); - free(crossings_start); - free(crossings_end); - } - curr=curr->next; + + pos=route_get_pos(route); + dst=route_get_dst(route); + if (! pos || ! dst) + return; + this_->first=this_->last=NULL; + len=route_info_length(pos, dst, 0); + if (len == -1) { + len=route_info_length(pos, NULL, 0); + end_flag=1; + } + sd=route_info_street(pos); + itm=navigation_itm_new(this_, &sd->item, route_info_point(pos, -1)); + itm->length=len; + itm->time=route_time(&sd->item, len); + rph=route_path_open(route); + while((s=route_path_get_segment(rph))) { + itm=navigation_itm_new(this_, route_path_segment_get_item(s),route_path_segment_get_start(s)); + itm->time=route_path_segment_get_time(s); + itm->length=route_path_segment_get_length(s); } - data_window_end(navigation_window); + if (end_flag) { + len=route_info_length(NULL, dst, 0); + printf("end %d\n", len); + sd=route_info_street(dst); + itm=navigation_itm_new(this_, &sd->item, route_info_point(pos, 2)); + itm->length=len; + itm->time=route_time(&sd->item, len); + } + itm=navigation_itm_new(this_, NULL, NULL); + route_path_close(rph); + calculate_dest_distance(this_); + make_maneuvers(this_); + p=this_; + callback_list_call(this_->callback, 1, &p); +} + +void +navigation_destroy(struct navigation *this_) +{ + callback_list_destroy(this_->callback); + callback_list_destroy(this_->callback_speech); + g_free(this_); } +struct callback * +navigation_register_callback(struct navigation *this_, enum navigation_mode mode, void (*func)(struct navigation *nav, void *data), void *data) +{ + return callback_list_add_new(this_->callback, func, 1, &data); +} + +void +navigation_unregister_callback(struct navigation *this_, struct callback *cb) +{ + callback_list_remove_destroy(this_->callback, cb); +} diff --git a/src/navigation.h b/src/navigation.h index c8c1c399..aa80e6c1 100644 --- a/src/navigation.h +++ b/src/navigation.h @@ -1,2 +1,28 @@ -void navigation_path_description(void *route); +#ifdef __cplusplus +extern "C" { +#endif +enum navigation_mode { + navigation_mode_long, + navigation_mode_short, + navigation_mode_speech, +}; +/* prototypes */ +enum navigation_mode; +struct callback; +struct mapset; +struct navigation; +struct navigation_list; +struct route; +struct navigation *navigation_new(struct mapset *ms); +struct navigation_list *navigation_list_new(struct navigation *this_); +char *navigation_list_get(struct navigation_list *this_, enum navigation_mode mode); +void navigation_list_destroy(struct navigation_list *this_); +void navigation_update(struct navigation *this_, struct route *route); +void navigation_destroy(struct navigation *this_); +struct callback *navigation_register_callback(struct navigation *this_, enum navigation_mode mode, void (*func)(struct navigation *nav, void *data), void *data); +void navigation_unregister_callback(struct navigation *this_, struct callback *cb); +/* end of prototypes */ +#ifdef __cplusplus +} +#endif diff --git a/src/navit.c b/src/navit.c new file mode 100644 index 00000000..04b22eb3 --- /dev/null +++ b/src/navit.c @@ -0,0 +1,465 @@ +#include <stdio.h> +#include <fcntl.h> +#include <glib.h> +#include "debug.h" +#include "navit.h" +#include "gui.h" +#include "map.h" +#include "mapset.h" +#include "coord.h" +#include "point.h" +#include "transform.h" +#include "projection.h" +#include "menu.h" +#include "graphics.h" +#include "cursor.h" +#include "popup.h" +#include "route.h" +#include "navigation.h" +#include "track.h" + +struct navit { + GList *mapsets; + GList *layouts; + struct gui *gui; + struct layout *layout_current; + struct graphics *gra; + struct action *action; + struct transformation *trans; + struct compass *compass; + struct map_data *map_data; + struct menu *menu; + struct menu *toolbar; + struct statusbar *statusbar; + struct menu *menubar; + struct route *route; + struct navigation *navigation; + struct cursor *cursor; + struct speech *speech; + struct vehicle *vehicle; + struct track *track; + struct map_flags *flags; + int ready; + struct window *win; + struct displaylist *displaylist; + int cursor_flag; + int update; + int follow; + int update_curr; + int follow_curr; +}; + +struct gui * +main_loop_gui; + + +void +navit_add_mapset(struct navit *this_, struct mapset *ms) +{ + this_->mapsets = g_list_append(this_->mapsets, ms); +} + +struct mapset * +navit_get_mapset(struct navit *this_) +{ + return this_->mapsets->data; +} + +void +navit_add_layout(struct navit *this_, struct layout *lay) +{ + this_->layouts = g_list_append(this_->layouts, lay); +} + +void +navit_draw(struct navit *this_) +{ + transform_setup_source_rect(this_->trans); + graphics_draw(this_->gra, this_->displaylist, this_->mapsets, this_->trans, this_->layouts, this_->route); + this_->ready=1; +} + +void +navit_draw_displaylist(struct navit *this_) +{ + if (this_->ready) { + graphics_displaylist_draw(this_->gra, this_->displaylist, this_->trans, this_->layouts, this_->route); + } +} + +static void +navit_resize(void *data, int w, int h) +{ + struct navit *this_=data; + transform_set_size(this_->trans, w, h); + navit_draw(this_); +} + +static void +navit_button(void *data, int pressed, int button, struct point *p) +{ + struct navit *this_=data; + if (pressed && button == 1) { + int border=16; + if (! transform_within_border(this_->trans, p, border)) { + navit_set_center_screen(this_, p); + } else + popup(this_, button, p); + } + if (pressed && button == 2) + navit_set_center_screen(this_, p); + if (pressed && button == 3) + popup(this_, button, p); + if (pressed && button == 4) + navit_zoom_in(this_, 2); + if (pressed && button == 5) + navit_zoom_out(this_, 2); +} + +void +navit_zoom_in(struct navit *this_, int factor) +{ + long scale=transform_get_scale(this_->trans)/factor; + if (scale < 1) + scale=1; + transform_set_scale(this_->trans, scale); + navit_draw(this_); +} + +void +navit_zoom_out(struct navit *this_, int factor) +{ + long scale=transform_get_scale(this_->trans)*factor; + transform_set_scale(this_->trans,scale); + navit_draw(this_); +} + +struct navit * +navit_new(const char *ui, const char *graphics, struct coord *center, enum projection pro, int zoom) +{ + struct navit *this_=g_new0(struct navit, 1); + + this_->cursor_flag=1; + this_->trans=transform_new(); + transform_set_projection(this_->trans, pro); + + transform_setup(this_->trans, center, zoom, 0); + /* this_->flags=g_new0(struct map_flags, 1); */ + this_->displaylist=graphics_displaylist_new(); + this_->gui=gui_new(this_, ui, 792, 547); + if (! this_->gui) { + g_warning("failed to create gui '%s'", ui); + navit_destroy(this_); + return NULL; + } + if (gui_has_main_loop(this_->gui)) { + if (! main_loop_gui) { + main_loop_gui=this_->gui; + } else { + g_warning("gui with main loop already active, ignoring this instance"); + navit_destroy(this_); + return NULL; + } + } + this_->menubar=gui_menubar_new(this_->gui); + this_->toolbar=gui_toolbar_new(this_->gui); + this_->statusbar=gui_statusbar_new(this_->gui); + this_->gra=graphics_new(graphics); + if (! this_->gra) { + g_warning("failed to create graphics '%s'", graphics); + navit_destroy(this_); + return NULL; + } + graphics_register_resize_callback(this_->gra, navit_resize, this_); + graphics_register_button_callback(this_->gra, navit_button, this_); + if (gui_set_graphics(this_->gui, this_->gra)) { + g_warning("failed to connect graphics '%s' to gui '%s'\n", graphics, ui); + navit_destroy(this_); + return NULL; + } + graphics_init(this_->gra); + return this_; +} + +static void +navit_map_toggle(struct menu *menu, void *this__p, void *map_p) +{ + if ((menu_get_toggle(menu) != 0) != (map_get_active(map_p) != 0)) { + map_set_active(map_p, (menu_get_toggle(menu) != 0)); + navit_draw(this__p); + } +} + +static void +navit_projection_set(struct menu *menu, void *this__p, void *pro_p) +{ + struct navit *this_=this__p; + enum projection pro=(enum projection) pro_p; + struct coord_geo g; + struct coord *c; + + c=transform_center(this_->trans); + transform_to_geo(transform_get_projection(this_->trans), c, &g); + transform_set_projection(this_->trans, pro); + transform_from_geo(pro, &g, c); + navit_draw(this_); +} + +static void +navit_set_destination_menu(struct menu *menu, void *this__p, void *c_p) +{ + struct navit *this_=this__p; + struct coord *c=c_p; + if (this_->route) { + route_set_destination(this_->route, c); + navit_draw(this_); + } + +} + +void +navit_set_destination(struct navit *this_, struct coord *c, char *description) +{ + int fd; + char *buffer; + buffer=g_strdup_printf("0x%x 0x%x %s\n", c->x, c->y, description); + fd=open("destination.txt", O_RDWR|O_CREAT|O_APPEND, 0644); + if (fd != -1) + write(fd, buffer, strlen(buffer)); + close(fd); + g_free(buffer); + if (this_->route) { + route_set_destination(this_->route, c); + navit_draw(this_); + } +} + +struct navit *global_navit; + +static void +navit_show_roadbook(struct navigation *nav, void *data) +{ + struct navigation_list *list; + char *str; + + list=navigation_list_new(nav); + while ((str=navigation_list_get(list, navigation_mode_long))) { + printf("%s\n", str); + } + navigation_list_destroy(list); +} + +void +navit_init(struct navit *this_) +{ + struct menu *mapmen,*men,*men2; + struct map *map; + struct mapset_handle *handle; + struct mapset *ms=this_->mapsets->data; + + if (this_->menubar) { + mapmen=menu_add(this_->menubar, "Map", menu_type_submenu, NULL, NULL, NULL); + // menu_add(map, "Test", menu_type_menu, NULL, NULL); + men=menu_add(mapmen, "Layout", menu_type_submenu, NULL, NULL, NULL); + menu_add(men, "Test", menu_type_menu, NULL, NULL, NULL); + men=menu_add(mapmen, "Projection", menu_type_submenu, NULL, NULL, NULL); + menu_add(men, "M&G", menu_type_menu, navit_projection_set, this_, (void *)projection_mg); + menu_add(men, "Garmin", menu_type_menu, navit_projection_set, this_, (void *)projection_garmin); + handle=mapset_open(ms); + while ((map=mapset_next(handle,0))) { + char *s=g_strdup_printf("%s:%s", map_get_type(map), map_get_filename(map)); + men2=menu_add(mapmen, s, menu_type_toggle, navit_map_toggle, this_, map); + menu_set_toggle(men2, map_get_active(map)); + g_free(s); + } + mapset_close(handle); + } + { + struct mapset *ms=this_->mapsets->data; + struct coord c; + int pos,flag=0; + FILE *f; + + char buffer[2048]; + this_->route=route_new(ms); + this_->navigation=navigation_new(ms); + dbg(0,"navigation_register_callback(%p, ... %p)\n", this_->navigation, this_); + navigation_register_callback(this_->navigation, navigation_mode_long, navit_show_roadbook, this_); +#if 1 + this_->track=track_new(ms); +#endif + men=NULL; + if (this_->menubar) { + men=menu_add(this_->menubar, "Route", menu_type_submenu, NULL, NULL, NULL); + men=menu_add(men, "Former Destinations", menu_type_submenu, NULL, NULL, NULL); + } + f=fopen("destination.txt", "r"); + if (f) { + while (! feof(f) && fgets(buffer, 2048, f)) { + if ((pos=coord_parse(buffer, projection_mg, &c))) { + if (buffer[pos] && buffer[pos] != '\n' ) { + struct coord *cn=g_new(struct coord, 1); + *cn=c; + buffer[strlen(buffer)-1]='\0'; + if (men) + menu_add(men, buffer+pos+1, menu_type_menu, navit_set_destination_menu, this_, cn); + } + flag=1; + } + } + fclose(f); + if (flag) + route_set_destination(this_->route, &c); + } + } + global_navit=this_; +} + +void +navit_set_center(struct navit *this_, struct coord *center) +{ + struct coord *c=transform_center(this_->trans); + *c=*center; + if (this_->ready) + navit_draw(this_); +} + +static void +navit_set_center_cursor(struct navit *this_, struct coord *cursor, int dir, int xpercent, int ypercent) +{ + struct coord *c=transform_center(this_->trans); + int width, height; + struct point p; + struct coord cnew; + + transform_get_size(this_->trans, &width, &height); + *c=*cursor; + transform_set_angle(this_->trans, dir); + p.x=(100-xpercent)*width/100; + p.y=(100-ypercent)*height/100; + transform_reverse(this_->trans, &p, &cnew); + *c=cnew; + if (this_->ready) + navit_draw(this_); + +} + + +void +navit_set_center_screen(struct navit *this_, struct point *p) +{ + struct coord c; + transform_reverse(this_->trans, p, &c); + navit_set_center(this_, &c); +} + +void +navit_toggle_cursor(struct navit *this_) +{ + this_->cursor_flag=1-this_->cursor_flag; +} + +static void +navit_cursor_offscreen(struct cursor *cursor, void *this__p) +{ + struct navit *this_=this__p; + + if (this_->cursor_flag) + navit_set_center(this_, cursor_pos_get(cursor)); +} + +static void +navit_cursor_update(struct cursor *cursor, void *this__p) +{ + struct navit *this_=this__p; + struct coord *cursor_c=cursor_pos_get(cursor); + int dir=cursor_get_dir(cursor); + + if (this_->track) { + struct coord c=*cursor_c; + if (track_update(this_->track, &c, dir)) { + cursor_c=&c; + cursor_pos_set(cursor, cursor_c); + if (this_->route && this_->update_curr == 1) + route_set_position_from_track(this_->route, this_->track); + } + } else { + if (this_->route && this_->update_curr == 1) + route_set_position(this_->route, cursor_c); + } + if (this_->route && this_->update_curr == 1) + navigation_update(this_->navigation, this_->route); + if (this_->cursor_flag) { + if (this_->follow_curr == 1) + navit_set_center_cursor(this_, cursor_c, dir, 50, 80); + } + if (this_->follow_curr > 1) + this_->follow_curr--; + else + this_->follow_curr=this_->follow; + if (this_->update_curr > 1) + this_->update_curr--; + else + this_->update_curr=this_->update; +} + +void +navit_set_position(struct navit *this_, struct coord *c) +{ + if (this_->route) { + route_set_position(this_->route, c); + if (this_->navigation) { + navigation_update(this_->navigation, this_->route); + } + } + navit_draw(this_); +} + +void +navit_vehicle_add(struct navit *this_, struct vehicle *v, struct color *c, int update, int follow) +{ + this_->vehicle=v; + this_->update_curr=this_->update=update; + this_->follow_curr=this_->follow=follow; + this_->cursor=cursor_new(this_->gra, v, c, this_->trans); + cursor_register_offscreen_callback(this_->cursor, navit_cursor_offscreen, this_); + cursor_register_update_callback(this_->cursor, navit_cursor_update, this_); +} + + +struct gui * +navit_get_gui(struct navit *this_) +{ + return this_->gui; +} + +struct transformation * +navit_get_trans(struct navit *this_) +{ + return this_->trans; +} + +struct route * +navit_get_route(struct navit *this_) +{ + return this_->route; +} + +struct navigation * +navit_get_navigation(struct navit *this_) +{ + return this_->navigation; +} + +struct displaylist * +navit_get_displaylist(struct navit *this_) +{ + return this_->displaylist; +} + +void +navit_destroy(struct navit *this_) +{ + g_free(this_); +} + diff --git a/src/navit.h b/src/navit.h new file mode 100644 index 00000000..234391b1 --- /dev/null +++ b/src/navit.h @@ -0,0 +1,43 @@ +#ifdef __cplusplus +extern "C" { +#endif +extern struct gui *main_loop_gui; +/* prototypes */ +enum projection; +struct color; +struct coord; +struct displaylist; +struct gui; +struct layout; +struct mapset; +struct navigation; +struct navit; +struct point; +struct route; +struct transformation; +struct vehicle; +void navit_add_mapset(struct navit *this_, struct mapset *ms); +struct mapset *navit_get_mapset(struct navit *this_); +void navit_add_layout(struct navit *this_, struct layout *lay); +void navit_draw(struct navit *this_); +void navit_draw_displaylist(struct navit *this_); +void navit_zoom_in(struct navit *this_, int factor); +void navit_zoom_out(struct navit *this_, int factor); +struct navit *navit_new(const char *ui, const char *graphics, struct coord *center, enum projection pro, int zoom); +void navit_set_destination(struct navit *this_, struct coord *c, char *description); +void navit_init(struct navit *this_); +void navit_set_center(struct navit *this_, struct coord *center); +void navit_set_center_screen(struct navit *this_, struct point *p); +void navit_toggle_cursor(struct navit *this_); +void navit_set_position(struct navit *this_, struct coord *c); +void navit_vehicle_add(struct navit *this_, struct vehicle *v, struct color *c, int update, int follow); +struct gui *navit_get_gui(struct navit *this_); +struct transformation *navit_get_trans(struct navit *this_); +struct route *navit_get_route(struct navit *this_); +struct navigation *navit_get_navigation(struct navit *this_); +struct displaylist *navit_get_displaylist(struct navit *this_); +void navit_destroy(struct navit *this_); +/* end of prototypes */ +#ifdef __cplusplus +} +#endif diff --git a/src/navit.xml b/src/navit.xml new file mode 100644 index 00000000..2339d15f --- /dev/null +++ b/src/navit.xml @@ -0,0 +1,477 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE navit SYSTEM "navit.dtd"> +<plugins> + <plugin path="*/*/.libs/lib*.so" /> + <plugin path="graphics/null/.libs/libgraphics_null.so" active="no" /> +</plugins> +<navit gui="gtk" graphics="gtk_drawing_area" center="5031.51 N 735.83 E" zoom="8192" > + <vehicle name="Meins" enabled="no" source="gpsd://192.168.1.14" color="#0000ff"/> + <vehicle name="Deins" enabled="no" source="gpsd://somehost" color="#0000aa"/> + <mapset> + <map type="mg" enabled="yes" data="/opt/reiseplaner/travel/DE.map" /> + <map type="mg" enabled="yes" data="/opt/reiseplaner/travel/DE.map/smp2.smp" /> + <map type="mg" enabled="yes" data="/opt/reiseplaner/travel/DE.map/smp3.smp" /> + <map type="mg" enabled="yes" data="/opt/reiseplaner/travel/DE.map/smp4.smp" /> + </mapset> + <layout name="Tag"> + <layer name="sea" details="0"> + <item type="wood" zoom="0-"> + <polygon color="#8ec78d" /> + </item> + <item type="town_poly" zoom="0-"> + <polygon color="#ffc895" /> + <polyline color="#ebb481" /> + </item> + <item type="water_poly" zoom="0-"> + <polygon color="#82c8ea" /> + <polyline color="#5096b8" /> + </item> + <item type="park_poly" zoom="0-"> + <polygon color="#7cc334" /> + </item> + <item type="airport_poly" zoom="0-"> + <polygon color="#a0a0a0" /> + </item> + <item type="sport_poly" zoom="0-"> + <polygon color="#4af04f" /> + </item> + <item type="industry_poly" zoom="0-"> + <polygon color="#e6e6e6" /> + </item> + <item type="water_line" zoom="0-"> + <polyline color="#5096b8" width="1" /> + </item> + <item type="rail" zoom="6-"> + <polyline color="#808080" width="3" /> + </item> + <item type="ferry" zoom="5-"> + <polyline color="#000000" width="1" /> + </item> + <item type="border_country" zoom="0-"> + <polyline color="#b8434e" width="1" /> + </item> + <item type="border_state" zoom="0-"> + <polyline color="#808080" width="1" /> + </item> + <item type="height_line_1" zoom="0-"> + <polyline color="#000000" width="1" /> + </item> + <item type="height_line_2" zoom="0-"> + <polyline color="#000000" width="2" /> + </item> + <item type="street_route" zoom="2"> + <polyline color="#0000a0" width="4" /> + </item> + <item type="street_route" zoom="3-5"> + <polyline color="#0000a0" width="8" /> + </item> + <item type="street_route" zoom="6"> + <polyline color="#0000a0" width="10" /> + </item> + <item type="street_route" zoom="7-8"> + <polyline color="#0000a0" width="16" /> + </item> + <item type="street_route" zoom="9-10"> + <polyline color="#0000a0" width="20" /> + </item> + <item type="street_route" zoom="11"> + <polyline color="#0000a0" width="28" /> + </item> + <item type="street_route" zoom="12"> + <polyline color="#0000a0" width="32" /> + </item> + <item type="street_route" zoom="13"> + <polyline color="#0000a0" width="52" /> + </item> + <item type="street_route" zoom="14"> + <polyline color="#0000a0" width="64" /> + </item> + <item type="street_route" zoom="15"> + <polyline color="#0000a0" width="68" /> + </item> + <item type="street_route" zoom="16"> + <polyline color="#0000a0" width="132" /> + </item> + <item type="street_route" zoom="17"> + <polyline color="#0000a0" width="268" /> + </item> + <item type="street_route" zoom="18"> + <polyline color="#0000a0" width="530" /> + </item> + <item type="street_nopass" zoom="10-"> + <polyline color="#000000" width="1" /> + </item> + <item type="street_0,street_1_city,street_1_land" zoom="10"> + <polyline color="#d2d2d2" width="4" /> + <polyline color="#ffffff" width="2" /> + </item> + <item type="street_0,street_1_city,street_1_land" zoom="11"> + <polyline color="#d2d2d2" width="6" /> + <polyline color="#ffffff" width="4" /> + </item> + <item type="street_0,street_1_city,street_1_land" zoom="12"> + <polyline color="#d2d2d2" width="10" /> + <polyline color="#ffffff" width="8" /> + </item> + <item type="street_0,street_1_city,street_1_land" zoom="13"> + <polyline color="#d2d2d2" width="12" /> + <polyline color="#ffffff" width="9" /> + </item> + <item type="street_0,street_1_city,street_1_land" zoom="14"> + <polyline color="#d2d2d2" width="15" /> + <polyline color="#ffffff" width="13" /> + </item> + <item type="street_0,street_1_city,street_1_land" zoom="15"> + <polyline color="#d2d2d2" width="17" /> + <polyline color="#ffffff" width="14" /> + </item> + <item type="street_0,street_1_city,street_1_land" zoom="16"> + <polyline color="#d2d2d2" width="33" /> + <polyline color="#ffffff" width="26" /> + </item> + <item type="street_0,street_1_city,street_1_land" zoom="17"> + <polyline color="#d2d2d2" width="69" /> + <polyline color="#ffffff" width="61" /> + </item> + <item type="street_0,street_1_city,street_1_land" zoom="18"> + <polyline color="#d2d2d2" width="132" /> + <polyline color="#ffffff" width="126" /> + </item> + <item type="street_2_city,street_2_land" zoom="7-8"> + <polyline color="#c0c0c0" width="2" /> + </item> + <item type="street_2_city,street_2_land" zoom="9"> + <polyline color="#c0c0c0" width="4" /> + <polyline color="#ffff00" width="2" /> + </item> + <item type="street_2_city,street_2_land" zoom="10"> + <polyline color="#c0c0c0" width="6" /> + <polyline color="#ffff00" width="4" /> + </item> + <item type="street_2_city,street_2_land" zoom="11"> + <polyline color="#c0c0c0" width="8" /> + <polyline color="#ffff00" width="6" /> + </item> + <item type="street_2_city,street_2_land" zoom="12"> + <polyline color="#c0c0c0" width="12" /> + <polyline color="#ffff00" width="9" /> + </item> + <item type="street_2_city,street_2_land" zoom="13"> + <polyline color="#c0c0c0" width="15" /> + <polyline color="#ffff00" width="11" /> + </item> + <item type="street_2_city,street_2_land" zoom="14"> + <polyline color="#c0c0c0" width="18" /> + <polyline color="#ffff00" width="14" /> + </item> + <item type="street_2_city,street_2_land" zoom="15"> + <polyline color="#c0c0c0" width="21" /> + <polyline color="#ffff00" width="17" /> + </item> + <item type="street_2_city,street_2_land" zoom="16"> + <polyline color="#c0c0c0" width="35" /> + <polyline color="#ffff00" width="30" /> + </item> + <item type="street_2_city,street_2_land" zoom="17"> + <polyline color="#c0c0c0" width="73" /> + <polyline color="#ffff00" width="67" /> + </item> + <item type="street_2_city,street_2_land" zoom="18"> + <polyline color="#c0c0c0" width="144" /> + <polyline color="#ffff00" width="138" /> + </item> + <item type="street_3_city,street_3_land,ramp" zoom="7-8"> + <polyline color="#a0a0a0" width="3" /> + <polyline color="#ffff00" width="1" /> + </item> + <item type="street_3_city,street_3_land,ramp" zoom="9"> + <polyline color="#a0a0a0" width="5" /> + <polyline color="#ffff00" width="3" /> + </item> + <item type="street_3_city,street_3_land,ramp" zoom="10"> + <polyline color="#a0a0a0" width="8" /> + <polyline color="#ffff00" width="6" /> + </item> + <item type="street_3_city,street_3_land,ramp" zoom="11"> + <polyline color="#a0a0a0" width="9" /> + <polyline color="#ffff00" width="7" /> + </item> + <item type="street_3_city,street_3_land,ramp" zoom="12"> + <polyline color="#a0a0a0" width="13" /> + <polyline color="#ffff00" width="9" /> + </item> + <item type="street_3_city,street_3_land,ramp" zoom="13"> + <polyline color="#a0a0a0" width="18" /> + <polyline color="#ffff00" width="14" /> + </item> + <item type="street_3_city,street_3_land,ramp" zoom="14"> + <polyline color="#a0a0a0" width="21" /> + <polyline color="#ffff00" width="17" /> + </item> + <item type="street_3_city,street_3_land,ramp" zoom="15"> + <polyline color="#a0a0a0" width="25" /> + <polyline color="#ffff00" width="21" /> + </item> + <item type="street_3_city,street_3_land,ramp" zoom="16"> + <polyline color="#a0a0a0" width="40" /> + <polyline color="#ffff00" width="34" /> + </item> + <item type="street_3_city,street_3_land,ramp" zoom="17"> + <polyline color="#a0a0a0" width="79" /> + <polyline color="#ffff00" width="73" /> + </item> + <item type="street_3_city,street_3_land,ramp" zoom="18"> + <polyline color="#a0a0a0" width="156" /> + <polyline color="#ffff00" width="150" /> + </item> + <item type="street_4_city,street_4_land,street_n_lanes" zoom="2-6"> + <polyline color="#404040" width="1" /> + </item> + <item type="street_4_city,street_4_land,street_n_lanes" zoom="7-8"> + <polyline color="#404040" width="3" /> + <polyline color="#ff0000" width="1" /> + </item> + <item type="street_4_city,street_4_land,street_n_lanes" zoom="9"> + <polyline color="#000000" width="5" /> + <polyline color="#ff0000" width="3" /> + </item> + <item type="street_4_city,street_4_land,street_n_lanes" zoom="10"> + <polyline color="#000000" width="6" /> + <polyline color="#ff0000" width="4" /> + </item> + <item type="street_4_city,street_4_land,street_n_lanes" zoom="11"> + <polyline color="#000000" width="9" /> + <polyline color="#ff0000" width="7" /> + </item> + <item type="street_4_city,street_4_land,street_n_lanes" zoom="12"> + <polyline color="#000000" width="13" /> + <polyline color="#ff0000" width="9" /> + </item> + <item type="street_4_city,street_4_land,street_n_lanes" zoom="13"> + <polyline color="#000000" width="18" /> + <polyline color="#ff0000" width="14" /> + </item> + <item type="street_4_city,street_4_land,street_n_lanes" zoom="14"> + <polyline color="#000000" width="21" /> + <polyline color="#ff0000" width="17" /> + </item> + <item type="street_4_city,street_4_land,street_n_lanes" zoom="15"> + <polyline color="#000000" width="24" /> + <polyline color="#ff0000" width="20" /> + </item> + <item type="street_4_city,street_4_land,street_n_lanes" zoom="16"> + <polyline color="#000000" width="39" /> + <polyline color="#ff0000" width="33" /> + </item> + <item type="street_4_city,street_4_land,street_n_lanes" zoom="17"> + <polyline color="#000000" width="78" /> + <polyline color="#ff0000" width="72" /> + </item> + <item type="street_4_city,street_4_land,street_n_lanes" zoom="18"> + <polyline color="#000000" width="156" /> + <polyline color="#ff0000" width="150" /> + </item> + <item type="highway_city,highway_land" zoom="2"> + <polyline color="#ff0000" width="1" /> + </item> + <item type="highway_city,highway_land" zoom="3-5"> + <polyline color="#ff0000" width="3" /> + <polyline color="#ffff00" width="1" /> + </item> + <item type="highway_city,highway_land" zoom="6"> + <polyline color="#ff0000" width="4" /> + <polyline color="#ffff00" width="2" /> + </item> + <item type="highway_city,highway_land" zoom="7-8"> + <polyline color="#ff0000" width="7" /> + <polyline color="#ffff00" width="5" /> + <polyline color="#ff0000" width="1" /> + </item> + <item type="highway_city,highway_land" zoom="9-10"> + <polyline color="#ff0000" width="9" /> + <polyline color="#ffff00" width="5" /> + <polyline color="#ff0000" width="1" /> + </item> + <item type="highway_city,highway_land" zoom="11"> + <polyline color="#ff0000" width="13" /> + <polyline color="#ffff00" width="9" /> + <polyline color="#ff0000" width="1" /> + </item> + <item type="highway_city,highway_land" zoom="12"> + <polyline color="#ff0000" width="15" /> + <polyline color="#ffff00" width="10" /> + <polyline color="#ff0000" width="1" /> + </item> + <item type="highway_city,highway_land" zoom="13"> + <polyline color="#ff0000" width="25" /> + <polyline color="#ffff00" width="17" /> + <polyline color="#ff0000" width="1" /> + </item> + <item type="highway_city,highway_land" zoom="14"> + <polyline color="#ff0000" width="31" /> + <polyline color="#ffff00" width="24" /> + <polyline color="#ff0000" width="1" /> + </item> + <item type="highway_city,highway_land" zoom="15"> + <polyline color="#ff0000" width="33" /> + <polyline color="#ffff00" width="27" /> + <polyline color="#ff0000" width="1" /> + </item> + <item type="highway_city,highway_land" zoom="16"> + <polyline color="#ff0000" width="65" /> + <polyline color="#ffff00" width="59" /> + <polyline color="#ff0000" width="1" /> + </item> + <item type="highway_city,highway_land" zoom="17"> + <polyline color="#ff0000" width="133" /> + <polyline color="#ffff00" width="127" /> + <polyline color="#ff0000" width="1" /> + </item> + <item type="highway_city,highway_land" zoom="18"> + <polyline color="#ff0000" width="264" /> + <polyline color="#ffff00" width="258" /> + <polyline color="#ff0000" width="1" /> + </item> + <item type="street_unkn" zoom="0-"> + <polyline color="#8080ff" width="3" /> + </item> + <item type="highway_exit_label" zoom="10-"> + <circle color="#000000" radius="3" label_size="7" /> + </item> + <item type="district_label_1e3,district_label_2e3" zoom="10-11"> + <circle color="#000000" radius="3" label_size="7" /> + </item> + <item type="district_label_5e3" zoom="10-"> + <circle color="#000000" radius="3" label_size="10" /> + </item> + <item type="town_label_5e1" zoom="10-"> + <circle color="#000000" radius="3" label_size="10" /> + </item> + <item type="town_label_1e3" zoom="10-"> + <circle color="#000000" radius="3" label_size="10" /> + </item> + <item type="town_label_5e3" zoom="6-7"> + <circle color="#000000" radius="3" label_size="7" /> + </item> + <item type="town_label_5e3" zoom="8-10"> + <circle color="#000000" radius="3" label_size="10" /> + </item> + <item type="town_label_5e3" zoom="11"> + <circle color="#000000" radius="3" label_size="15" /> + </item> + <item type="town_label_1e4" zoom="5-6"> + <circle color="#000000" radius="5" label_size="7" /> + </item> + <item type="town_label_1e4" zoom="7-10"> + <circle color="#000000" radius="5" label_size="10" /> + </item> + <item type="town_label_1e4" zoom="11"> + <circle color="#000000" radius="5" label_size="15" /> + </item> + <item type="town_label,town_label_0e0,town_label_1e0,town_label_2e0,town_label_5e0,town_label_1e1,town_label_2e1,town_label_5e1,town_label_1e2,town_label_2e2,town_label_5e2,town_label_1e3,town_label_2e3,town_label_5e3,town_label_1e4,town_label_2e4,town_label_5e4,town_label_1e5,town_label_2e5,town_label_5e5,town_label_1e6,town_label_2e6,town_label_5e6,town_label_1e7,district_label,district_label_0e0,district_label_1e0,district_label_2e0,district_label_5e0,district_label_1e1,district_label_2e1,district_label_5e1,district_label_1e2,district_label_2e2,district_label_5e2,district_label_1e3,district_label_2e3,district_label_5e3,district_label_1e4,district_label_2e4,district_label_5e4,district_label_1e5,district_label_2e5,district_label_5e5,district_label_1e6,district_label_2e6,district_label_5e6,district_label_1e7" zoom="2-"> + <circle color="#000000" radius="3" label_size="15" /> + </item> + <item type="town_label_1e5,town_label_2e5" zoom="2-"> + <circle color="#000000" radius="3" label_size="10" /> + </item> + <item type="town_label_1e5,town_label_5e5,town_label_1e6,town_label_2e6,town_label_5e6,town_label_1e7" zoom="0-"> + <circle color="#000000" radius="3" label_size="10" /> + </item> + <item type="poi_airport" zoom="0-"> + <icon src="airport.xpm" /> + </item> + <item type="town_ghost" zoom="0-"> + <icon src="ghost_town.xpm" /> + </item> + <item type="poi_hotel" zoom="0-"> + <icon src="hotel.xpm" /> + </item> + <item type="poi_car_parking" zoom="0-"> + <icon src="parking.xpm" /> + </item> + <item type="poi_car_dealer_parts" zoom="0-"> + <icon src="car_dealer.xpm" /> + </item> + <item type="poi_fuel" zoom="0-"> + <icon src="fuel.xpm" /> + </item> + <item type="poi_shopping" zoom="0-"> + <icon src="shopping.xpm" /> + </item> + <item type="poi_attraction" zoom="0-"> + <icon src="attraction.xpm" /> + </item> + <item type="poi_bar" zoom="0-"> + <icon src="bar.xpm" /> + </item> + <item type="poi_bridge" zoom="0-"> + <icon src="bridge.xpm" /> + </item> + <item type="highway_exit" zoom="0-"> + <icon src="exit.xpm" /> + </item> + <item type="poi_camp_rv" zoom="0-"> + <icon src="camping.xpm" /> + </item> + <item type="poi_museum_history" zoom="0-"> + <icon src="museum.xpm" /> + </item> + <item type="poi_hospital" zoom="0-"> + <icon src="hospital.xpm" /> + </item> + </layer> + <!-- + <layer name="sea" details="0"> + <item type="sea" zoom="0-"> + <polygon color="#82c8ea" /> + </item> + </layer> + <layer name="wood" details="0"> + <item type="wood" zoom="0-"> + <polygon color="#8ec78d" /> + </item> + </layer> + <layer name="highway" details="0"> + <item type="highway" zoom="0-"> + <line color="#ff0000" width="3" /> + <line color="#ffff0a" width="1" /> + </item> + <item type="highway" zoom="2-5"> + <line color="#ff0000" width="5" /> + <line color="#ffff0a" width="3" /> + <text color="#000000" font="arial" size="12"> + </item> + </layer> + <layer name="label" details="0"> + <item type="town0" zoom="3-"> + <circle radius="3" /> + <text color="#000000" font="arial" size="12"> + </item> + </layer> + <layer name="poi" details="0"> + <item type="mcdonalds" zoom="3-"> + <icon src="mcdonalds.xpm" /> + </item> + </layer> + <layer name="wood" details="0"> + <item type="wood" zoom="1-"> + <polygon color="#8ec78d" /> + <polyline color="#8ec78d" /> + </item> + </layer> + --> + </layout> + <layout name="Nacht"> + </layout> + </navit> + <!-- + <navit gui="sdl" graphics="gtk_drawing_area" center="5031.51 N 305.83 E" zoom="8192" > + <vehicle name="Meins" source="gpsd://localhost" color="#0000ff"/> + <vehicle name="Deins" source="gpsd://somehost" color="#0000aa"/> + <mapset> + <map type="mg" enabled="yes" data="/nobackup/reiseplaner/DIRMAP_MAP/DIE.map" /> + <map type="mg" enabled="yes" data="/nobackup/reiseplaner/DIRMAP_MAP/DIE.map/smp3.smp" /> + <map type="mg" enabled="yes" data="/nobackup/reiseplaner/DIRMAP_MAP/DIE.map/smp4.smp" /> + </mapset> + </navit> +--> diff --git a/src/phrase.c b/src/phrase.c index 761de5a1..b3fef2a8 100644 --- a/src/phrase.c +++ b/src/phrase.c @@ -1,4 +1,5 @@ #include <time.h> +#include <glib.h> #include "coord.h" #include "route.h" #include "speech.h" @@ -15,12 +16,16 @@ phrase_route_calc(void *speech) void phrase_route_calculated(void *speech, void *route) { +#if 0 struct tm *eta; +#endif if (! speech) return; +#if 0 /* FIXME */ eta=route_get_eta(route); speech_sayf(speech,"Die Route wurde berechnet, geschätzte Ankunftszeit %d Uhr %d Entfernung %4.0f Kilometer", eta->tm_hour,eta->tm_min,route_get_len(route)/1000); +#endif } diff --git a/src/plugin.c b/src/plugin.c index e7edfe40..65db7973 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -1,21 +1,197 @@ -#include <stdio.h> -#include <dlfcn.h> +#include <glib.h> +#include <gmodule.h> #include "plugin.h" +#include "file.h" #define PLUGIN_C #include "plugin.h" -void -plugin_load(void) -{ - char *plugin="plugins/poi_geodownload/plugin_poi_geodownload.so"; - void *h=dlopen(plugin,RTLD_LAZY); +struct plugin { + int active; + int lazy; + char *name; + GModule *mod; void (*init)(void); +}; + +struct plugins { + GHashTable *hash; + GList *list; +}; + +struct plugin * +plugin_new(char *plugin) +{ + struct plugin *ret; + if (! g_module_supported()) { + return NULL; + } + ret=g_new0(struct plugin, 1); + ret->name=g_strdup(plugin); + return ret; + +} + +int +plugin_load(struct plugin *pl) +{ + gpointer init; + + GModule *mod; - if (! h) { - /* printf("can't load '%s', Error '%s'\n", plugin, dlerror()); */ + if (pl->mod) { + g_warning("can't load '%s', already loaded\n", pl->name); + return 0; + } + mod=g_module_open(pl->name, pl->lazy ? G_MODULE_BIND_LAZY : 0); + if (! mod) { + g_warning("can't load '%s', Error '%s'\n", pl->name, g_module_error()); + return 0; + } + if (!g_module_symbol(mod, "plugin_init", &init)) { + g_warning("can't load '%s', plugin_init not found\n", pl->name); + g_module_close(mod); + return 0; } else { - init=dlsym(h,"plugin_init"); - if (init) - (*init)(); + pl->mod=mod; + pl->init=init; + } + return 1; +} + +char * +plugin_get_name(struct plugin *pl) +{ + return pl->name; +} + +int +plugin_get_active(struct plugin *pl) +{ + return pl->active; +} + +void +plugin_set_active(struct plugin *pl, int active) +{ + pl->active=active; +} + +void +plugin_set_lazy(struct plugin *pl, int lazy) +{ + pl->lazy=lazy; +} + +void +plugin_call_init(struct plugin *pl) +{ + pl->init(); +} + +void +plugin_unload(struct plugin *pl) +{ + g_module_close(pl->mod); + pl->mod=NULL; +} + +void +plugin_destroy(struct plugin *pl) +{ + g_free(pl); +} + +struct plugins * +plugins_new(void) +{ + struct plugins *ret=g_new0(struct plugins, 1); + ret->hash=g_hash_table_new(g_str_hash, g_str_equal); + return ret; +} + +void +plugins_add_path(struct plugins *pls, char *path, int active, int lazy) +{ + struct file_wordexp *we; + int i, count; + char **array; + char *name; + struct plugin *pl; + + we=file_wordexp_new(path); + count=file_wordexp_get_count(we); + array=file_wordexp_get_array(we); + for (i = 0 ; i < count ; i++) { + name=array[i]; + if (! (pl=g_hash_table_lookup(pls->hash, name))) { + pl=plugin_new(name); + if (! pl) { + g_warning("failed to create plugin '%s'\n", name); + continue; + } + g_hash_table_insert(pls->hash, plugin_get_name(pl), pl); + pls->list=g_list_append(pls->list, pl); + } else { + pls->list=g_list_remove(pls->list, pl); + pls->list=g_list_append(pls->list, pl); + } + plugin_set_active(pl, active); + plugin_set_lazy(pl, lazy); + } + file_wordexp_destroy(we); +} + +void +plugins_init(struct plugins *pls) +{ + struct plugin *pl; + GList *l; + + l=pls->list; + while (l) { + pl=l->data; + if (plugin_get_active(pl)) + if (!plugin_load(pl)) + plugin_set_active(pl, 0); + l=g_list_next(l); + } + l=pls->list; + while (l) { + pl=l->data; + if (plugin_get_active(pl)) + plugin_call_init(pl); + l=g_list_next(l); + } +} + +void +plugins_destroy(struct plugins *pls) +{ + GList *l; + struct plugin *pl; + + l=pls->list; + while (l) { + pl=l->data; + plugin_unload(pl); + plugin_destroy(pl); + } + g_list_free(pls->list); + g_hash_table_destroy(pls->hash); + g_free(pls); +} + +void * +plugin_get_type(enum plugin_type type, const char *name) +{ + GList *l; + struct name_val *nv; + l=plugin_types[type]; + while (l) { + nv=l->data; + if (!g_ascii_strcasecmp(nv->name, name)) + return nv->val; + l=g_list_next(l); } + return NULL; } diff --git a/src/plugin.h b/src/plugin.h index 84e0845d..d6e7c17d 100644 --- a/src/plugin.h +++ b/src/plugin.h @@ -1,5 +1,18 @@ -void plugin_load(void); -int plugin_init(void); +#ifndef PLUGIN_C + +#ifdef __cplusplus +extern "C" { +#endif + +struct plugin; + +enum plugin_type { + plugin_type_map, + plugin_type_gui, + plugin_type_graphics, + plugin_type_last, +}; +#endif struct container; struct popup; @@ -7,6 +20,7 @@ struct popup_item; #undef PLUGIN_FUNC1 #undef PLUGIN_FUNC3 #undef PLUGIN_FUNC4 +#undef PLUGIN_TYPE #define PLUGIN_PROTO(name,args...) void name(args) #ifdef PLUGIN_C @@ -38,6 +52,32 @@ PLUGIN_PROTO((*plugin_##name##_func),t1 p1,t2 p2,t3 p3,t4 p4); \ void plugin_call_##name(t1 p1,t2 p2, t3 p3, t4 p4) PLUGIN_CALL(name,p1,p2,p3,p4) \ PLUGIN_REGISTER(name,t1 p1,t2 p2,t3 p3,t4 p4) +struct name_val { + char *name; + void *val; +}; + +GList *plugin_types[plugin_type_last]; + +#define PLUGIN_TYPE(type,newargs) \ +struct type##_priv; \ +struct type##_methods; \ +void \ +plugin_register_##type##_type(const char *name, struct type##_priv *(*new_) newargs) \ +{ \ + struct name_val *nv; \ + nv=g_new(struct name_val, 1); \ + nv->name=g_strdup(name); \ + nv->val=new_; \ + plugin_types[plugin_type_##type]=g_list_append(plugin_types[plugin_type_##type], nv); \ +} \ + \ +void * \ +plugin_get_##type##_type(const char *name) \ +{ \ + return plugin_get_type(plugin_type_##type, name); \ +} + #else #define PLUGIN_FUNC1(name,t1,p1) \ void plugin_register_##name(void(*func)(t1 p1)); \ @@ -50,7 +90,35 @@ void plugin_call_##name(t1 p1,t2 p2,t3 p3); #define PLUGIN_FUNC4(name,t1,p1,t2,p2,t3,p3,t4,p4) \ void plugin_register_##name(void(*func)(t1 p1,t2 p2,t3 p3,t4 p4)); \ void plugin_call_##name(t1 p1,t2 p2,t3 p3,t4 p4); + +#define PLUGIN_TYPE(type,newargs) \ +struct type##_priv; \ +struct type##_methods; \ +void plugin_register_##type##_type(const char *name, struct type##_priv *(*new_) newargs); \ +void *plugin_get_##type##_type(const char *name); + #endif -PLUGIN_FUNC1(draw, struct container *, co) -PLUGIN_FUNC3(popup, struct container *, map, struct popup *, p, struct popup_item **, list) +#include "plugin_def.h" + +void plugin_init(void); +/* prototypes */ +struct plugin *plugin_new(char *plugin); +int plugin_load(struct plugin *pl); +char *plugin_get_name(struct plugin *pl); +int plugin_get_active(struct plugin *pl); +void plugin_set_active(struct plugin *pl, int active); +void plugin_set_lazy(struct plugin *pl, int lazy); +void plugin_call_init(struct plugin *pl); +void plugin_unload(struct plugin *pl); +void plugin_destroy(struct plugin *pl); +struct plugins *plugins_new(void); +void plugins_add_path(struct plugins *pls, char *path, int active, int lazy); +void plugins_init(struct plugins *pls); +void plugins_destroy(struct plugins *pls); +void *plugin_get_type(enum plugin_type type, const char *name); +/* end of prototypes */ + +#ifdef __cplusplus +} +#endif diff --git a/src/plugin_def.h b/src/plugin_def.h new file mode 100644 index 00000000..4108a782 --- /dev/null +++ b/src/plugin_def.h @@ -0,0 +1,7 @@ +enum projection; +PLUGIN_FUNC1(draw, struct container *, co) +PLUGIN_FUNC3(popup, struct container *, map, struct popup *, p, struct popup_item **, list) +PLUGIN_TYPE(map, (struct map_methods *meth, char *data, char **charset, enum projection *pro)) +struct navit; +PLUGIN_TYPE(gui, (struct navit *nav, struct gui_methods *meth, int w, int h)) +PLUGIN_TYPE(graphics, (struct graphics_methods *meth)) diff --git a/src/popup.c b/src/popup.c index bf6fea08..4d1c812b 100644 --- a/src/popup.c +++ b/src/popup.c @@ -1,87 +1,28 @@ -#include <string.h> +#include <stdarg.h> #include <stdio.h> -#include <assert.h> -#include <gtk/gtk.h> -#include "coord.h" -#include "file.h" -#include "map_data.h" -#include "block.h" -#include "display.h" -#include "town.h" -#include "street.h" -#include "poly.h" -#include "log.h" +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <glib.h> #include "popup.h" -#include "plugin.h" -#include "vehicle.h" -#include "route.h" -#include "cursor.h" -#include "statusbar.h" -#include "container.h" +#include "debug.h" +#include "navit.h" +#include "coord.h" +#include "gui.h" +#include "menu.h" +#include "point.h" +#include "transform.h" +#include "projection.h" +#include "map.h" #include "graphics.h" +#include "item.h" +#include "route.h" -static void -popup_item_destroy_text(struct popup_item *item) -{ - g_free(item->text); - g_free(item); -} - -struct popup_item * -popup_item_new_text(struct popup_item **last, char *text, int priority) -{ - struct popup_item *curr; - curr=g_new0(struct popup_item,1); - curr->text=g_strdup(text); - curr->priority=priority; - curr->destroy=popup_item_destroy_text; - if (last) { - curr->next=*last; - *last=curr; - } - return curr; -} - -static struct popup_item * -popup_item_new_func(struct popup_item **last, char *text, int priority, void (*func)(struct popup_item *, void *), void *param) -{ - struct popup_item *curr=popup_item_new_text(last, text, priority); - curr->func=func; - curr->param=param; - return curr; -} - -static struct popup_item * -param_to_menu_new(char *name,struct param_list *plist, int c, int iso) -{ - struct popup_item *last, *curr, *ret; - int i; - - ret=popup_item_new_text(NULL,name,1); - last=NULL; - for (i = 0 ; i < c ; i++) { - char *name_buffer = g_strjoin(":",plist[i].name, plist[i].value,NULL); - char *text = name_buffer; - - if (iso) { - text=g_convert(name_buffer,-1,"utf-8","iso8859-1",NULL,NULL,NULL); - if (! text) { - printf("problem converting '%s'\n", name_buffer); - } - } - curr=popup_item_new_text(&last,text,i); - if (iso) - g_free(text); - g_free(name_buffer); - - } - ret->submenu=last; - return ret; -} - +#if 0 static void popup_set_no_passing(struct popup_item *item, void *param) { +#if 0 struct display_list *l=param; struct segment *seg=(struct segment *)(l->data); struct street_str *str=(struct street_str *)(seg->data[0]); @@ -93,32 +34,36 @@ popup_set_no_passing(struct popup_item *item, void *param) sprintf(log,"Attributes Street 0x%x updated: limit=0x%x(0x%x)", segid, 0x33, str->limit); str->limit=0x33; log_write(log, seg->blk_inf.file, str, sizeof(*str)); +#endif } +#endif + static void -popup_set_destination(struct popup_item *item, void *param) +popup_set_destination(struct menu *menu, void *data1, void *data2) { - struct popup_item *ref=param; - struct popup *popup=ref->param; - struct container *co=popup->co; - printf("Destination %s\n", ref->text); - route_set_position(co->route, cursor_pos_get(co->cursor)); - route_set_destination(co->route, &popup->c); - graphics_redraw(popup->co); - if (co->statusbar && co->statusbar->statusbar_route_update) - co->statusbar->statusbar_route_update(co->statusbar, co->route); + struct navit *nav=data1; + struct coord *c=data2; + struct route *route; + struct coord_geo g; + char buffer[1024]; + char buffer_geo[1024]; + transform_to_geo(transform_get_projection(navit_get_trans(nav)), c, &g); + transform_geo_text(&g, buffer_geo); + sprintf(buffer,"Map Point %s", buffer_geo); + navit_set_destination(nav, c, buffer); } + extern void *vehicle; static void -popup_set_position(struct popup_item *item, void *param) +popup_set_position(struct menu *menu, void *data1, void *data2) { - struct popup_item *ref=param; - struct popup *popup=ref->param; - printf("Position %s\n", ref->text); - g_assert(popup->co->vehicle != NULL); - vehicle_set_position(popup->co->vehicle, &popup->c); + struct navit *nav=data1; + struct coord *c=data2; + dbg(0,"%p %p\n", nav, c); + navit_set_position(nav, c); } #if 0 @@ -138,170 +83,139 @@ popup_break_crossing(struct display_list *l) } #endif -static void -popup_call_func(GtkObject *obj, void *parm) + +#define popup_printf(menu, type, fmt...) popup_printf_cb(menu, type, NULL, NULL, NULL, fmt) + +static void * +popup_printf_cb(void *menu, enum menu_type type, void (*callback)(struct menu *menu, void *data1, void *data2), void *data1, void *data2, const char *fmt, ...) { - struct popup_item *curr=parm; - curr->func(curr, curr->param); + gchar *str; + va_list ap; + void *ret; + + va_start(ap, fmt); + str=g_strdup_vprintf(fmt, ap); + dbg(0,"%s\n", str); + ret=menu_add(menu, str, type, callback, data1, data2); + va_end(ap); + g_free(str); + return ret; } -static GtkWidget * -popup_menu(struct popup_item *list) +static void +popup_show_attr_val(void *menu, struct attr *attr) { - int min_prio,curr_prio; - struct popup_item *curr; - GtkWidget *item,*menu,*submenu; + char *attr_name=attr_to_name(attr->type); - curr_prio=0; - menu=gtk_menu_new(); - do { - min_prio=INT_MAX; - curr=list; - while (curr) { - if (curr->priority == curr_prio) { - item=gtk_menu_item_new_with_label(curr->text); - gtk_menu_append(GTK_MENU(menu), item); - if (curr->submenu) { - submenu=popup_menu(curr->submenu); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu); - } else if (curr->func) { - g_signal_connect(G_OBJECT(item), "activate", - G_CALLBACK (popup_call_func), curr); - } - } - if (curr->priority > curr_prio && curr->priority < min_prio) - min_prio=curr->priority; - curr=curr->next; - } - curr_prio=min_prio; - } while (min_prio != INT_MAX); - return menu; + if (attr->type == attr_limit) + popup_printf(menu, menu_type_menu, "%s: %d", attr_name, attr->u.num); + else + popup_printf(menu, menu_type_menu, "%s: %s", attr_name, attr->u.str); } +#if 0 static void -popup_display_list_default(struct display_list *d, struct popup_item **popup_list) +popup_show_attr(void *menu, struct item *item, enum attr_type attr_type) { - struct segment *seg; - char *desc,*text,*item_text; - struct popup_item *curr_item,*submenu; - struct param_list plist[100]; - - desc=NULL; - if (d->type == 0) desc="Polygon"; - if (d->type == 1) desc="Polyline"; - if (d->type == 2) desc="Street"; - if (d->type == 3) desc="Label"; - if (d->type == 4) desc="Point"; - seg=(struct segment *)(d->data); - if (seg) { - if (d->label && strlen(d->label)) - item_text=g_strjoin(" ",desc,d->label,NULL); - else - item_text=g_strdup(desc); - text=g_convert(item_text,-1,"utf-8","iso8859-1",NULL,NULL,NULL); - curr_item=popup_item_new_text(popup_list,text,1); - g_free(text); - g_free(item_text); - - curr_item->submenu=param_to_menu_new("File", plist, file_get_param(seg->blk_inf.file, plist, 100), 1); - submenu=curr_item->submenu; - submenu->next=param_to_menu_new("Block", plist, block_get_param(&seg->blk_inf, plist, 100), 1); - submenu=submenu->next; - - if (d->type == 0 || d->type == 1) { - submenu->next=param_to_menu_new(desc, plist, poly_get_param(seg, plist, 100), 1); - } - if (d->type == 2) { - submenu->next=param_to_menu_new(desc, plist, street_get_param(seg, plist, 100, 1), 1); - popup_item_new_func(&submenu->next,"Set no passing", 1000, popup_set_no_passing, d); - } - if (d->type == 3) { - submenu->next=param_to_menu_new(desc, plist, town_get_param(seg, plist, 100), 1); - } - if (d->type == 4) { - submenu->next=param_to_menu_new(desc, plist, street_bti_get_param(seg, plist, 100), 1); - } - } + struct attr attr; + memset(&attr, 0, sizeof(attr)); + attr.type=attr_type; + if (item_attr_get(item, attr_type, &attr)) + popup_show_attr_val(menu, &attr); } +#endif static void -popup_display_list(struct container *co, struct popup *popup, struct popup_item **popup_list) +popup_show_attrs(void *menu, struct item *item) { - GtkWidget *menu, *item; - struct display_list *list[100],**p=list; - - menu=gtk_menu_new(); - item=gtk_menu_item_new_with_label("Selection"); - gtk_menu_append (GTK_MENU(menu), item); - display_find(&popup->pnt, co->disp, display_end, 3, list, 100); - while (*p) { - if (! (*p)->info) - popup_display_list_default(*p, popup_list); +#if 0 + popup_show_attr(menu, item, attr_debug); + popup_show_attr(menu, item, attr_address); + popup_show_attr(menu, item, attr_phone); + popup_show_attr(menu, item, attr_phone); + popup_show_attr(menu, item, attr_entry_fee); + popup_show_attr(menu, item, attr_open_hours); +#else + struct attr attr; + for (;;) { + memset(&attr, 0, sizeof(attr)); + if (item_attr_get(item, attr_any, &attr)) + popup_show_attr_val(menu, &attr); else - (*(*p)->info)(*p, popup_list); - p++; - } + break; + } + +#endif } static void -popup_destroy_items(struct popup_item *item) +popup_show_item(void *popup, struct displayitem *di) { - struct popup_item *next; - while (item) { - if (item->active && item->func) - item->func(item, item->param); - if (item->submenu) - popup_destroy_items(item->submenu); - next=item->next; - assert(item->destroy != NULL); - item->destroy(item); - item=next; + struct map_rect *mr; + void *menu, *menu_map, *menu_item; + char *label; + struct item *item; + + label=graphics_displayitem_get_label(di); + item=graphics_displayitem_get_item(di); + + if (label) + menu=popup_printf(popup, menu_type_submenu, "%s '%s'", item_to_name(item->type), label); + else + menu=popup_printf(popup, menu_type_submenu, "%s", item_to_name(item->type)); + menu_item=popup_printf(menu, menu_type_submenu, "Item"); + popup_printf(menu_item, menu_type_menu, "type: 0x%x", item->type); + popup_printf(menu_item, menu_type_menu, "id: 0x%x 0x%x", item->id_hi, item->id_lo); + if (item->map) { + mr=map_rect_new(item->map,NULL); + item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo); + dbg(1,"item=%p\n", item); + if (item) { + popup_show_attrs(menu_item, item); + } + map_rect_destroy(mr); + menu_map=popup_printf(menu, menu_type_submenu, "Map"); + } else { + popup_printf(menu, menu_type_menu, "(No map)"); } } static void -popup_destroy(GtkObject *obj, void *parm) +popup_display(struct navit *nav, void *popup, struct point *p) { - struct popup *popup=parm; - - popup_destroy_items(popup->items); - g_free(popup); + struct displaylist_handle *dlh; + struct displaylist *display; + struct displayitem *di; + + display=navit_get_displaylist(nav); + dlh=graphics_displaylist_open(display); + while ((di=graphics_displaylist_next(dlh))) { + if (graphics_displayitem_within_dist(di, p, 5)) { + popup_show_item(popup, di); + } + } + graphics_displaylist_close(dlh); } +struct coord c; + void -popup(struct container *co, int x, int y, int button) +popup(struct navit *nav, int button, struct point *p) { - GtkWidget *menu; - struct popup *popup=g_new(struct popup,1); - struct popup_item *list=NULL; - struct popup_item *descr; + void *popup,*men; + char buffer[1024]; struct coord_geo g; - char buffer[256]; - - popup->co=co; - popup->pnt.x=x; - popup->pnt.y=y; - transform_reverse(co->trans, &popup->pnt, &popup->c); - popup_display_list(co, popup, &list); - plugin_call_popup(co, popup, &list); - transform_lng_lat(&popup->c, &g); - strcpy(buffer,"Map Point "); - transform_geo_text(&g, buffer+strlen(buffer)); - sprintf(buffer+strlen(buffer), " (0x%lx,0x%lx)", popup->c.x, popup->c.y); - descr=popup_item_new_text(&list,buffer, 0); - descr->param=popup; - - popup_item_new_func(&list,"Set as Position", 1000, popup_set_position, descr); - popup_item_new_func(&list,"Set as Destination", 1001, popup_set_destination, descr); - - popup->items=list; - menu=popup_menu(list); - gtk_widget_show_all(menu); - popup->gui_data=menu; - - gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, button, gtk_get_current_event_time()); - g_signal_connect(G_OBJECT(menu), "selection-done", G_CALLBACK (popup_destroy), popup); + popup=gui_popup_new(navit_get_gui(nav)); + transform_reverse(navit_get_trans(nav), p, &c); + men=popup_printf(popup, menu_type_submenu, "Point 0x%x 0x%x", c.x, c.y); + popup_printf(men, menu_type_menu, "Screen %d %d", p->x, p->y); + transform_to_geo(transform_get_projection(navit_get_trans(nav)), &c, &g); + transform_geo_text(&g, buffer); + popup_printf(men, menu_type_menu, "%s", buffer); + popup_printf(men, menu_type_menu, "%f %f", g.lat, g.lng); + dbg(0,"%p %p\n", nav, &c); + popup_printf_cb(men, menu_type_menu, popup_set_position, nav, &c, "Set as position"); + popup_printf_cb(men, menu_type_menu, popup_set_destination, nav, &c, "Set as destination"); + popup_display(nav, popup, p); } - - diff --git a/src/popup.h b/src/popup.h index 989d5155..13be9802 100644 --- a/src/popup.h +++ b/src/popup.h @@ -1,22 +1,3 @@ -void popup(struct container *co, int x, int y, int button); -struct popup_item *popup_item_new_text(struct popup_item **last, char *text, int priority); - -struct popup { - struct container *co; - struct point pnt; - struct coord c; - void *gui_data; - struct popup_item *items; - struct popup_item *active; -}; - -struct popup_item { - char *text; - int priority; - void (*func)(struct popup_item *, void *); - void *param; - struct popup_item *submenu; - struct popup_item *next; - void (*destroy)(struct popup_item *); - int active; -}; +struct navit; +struct point; +void popup(struct navit *nav, int button, struct point *p); diff --git a/src/profile.c b/src/profile.c index b9417470..c8ea5371 100644 --- a/src/profile.c +++ b/src/profile.c @@ -1,25 +1,39 @@ +#include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <sys/time.h> #include "profile.h" void -profile_timer(char *where) +profile_timer(int level, const char *module, const char *function, const char *fmt, ...) { - static struct timeval last; + va_list ap; + static struct timeval last[3]; struct timeval curr; int msec,usec; - if (where) { + if (level < 0) + level=0; + if (level > 2) + level=2; + if (fmt) { gettimeofday(&curr, NULL); - msec=(curr.tv_usec-last.tv_usec)/1000+ - (curr.tv_sec-last.tv_sec)*1000; - if (msec >= 100) { - printf("%s:%d msec\n", where, msec); - } else { - usec=(curr.tv_usec-last.tv_usec)+(curr.tv_sec-last.tv_sec)*1000*1000; - printf("%s:%d usec\n", where, usec); + msec=(curr.tv_usec-last[level].tv_usec)/1000+ + (curr.tv_sec-last[level].tv_sec)*1000; + printf("%s:%s ", module, function); + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + if (msec >= 100) + printf(" %d msec\n", msec); + else { + usec=(curr.tv_usec-last[level].tv_usec)+(curr.tv_sec-last[level].tv_sec)*1000*1000; + printf(" %d.%d msec\n", usec/1000, usec%1000); } + gettimeofday(&last[level], NULL); + } else { + gettimeofday(&curr, NULL); + for (level = 0 ; level < 3 ; level++) + last[level]=curr; } - gettimeofday(&last, NULL); } diff --git a/src/profile.h b/src/profile.h index 50280354..0a548d6b 100644 --- a/src/profile.h +++ b/src/profile.h @@ -1 +1,8 @@ -void profile_timer(char *where); +#ifdef __cplusplus +extern "C" { +#endif +#define profile(level,fmt...) profile_timer(level,MODULE,__PRETTY_FUNCTION__,fmt) +void profile_timer(int level, const char *module, const char *function, const char *fmt, ...); +#ifdef __cplusplus +} +#endif diff --git a/src/projection.h b/src/projection.h new file mode 100644 index 00000000..9d73f1b0 --- /dev/null +++ b/src/projection.h @@ -0,0 +1,3 @@ +enum projection { + projection_none, projection_mg, projection_garmin +}; diff --git a/src/python.c b/src/python.c new file mode 100644 index 00000000..4b85bebb --- /dev/null +++ b/src/python.c @@ -0,0 +1,281 @@ +#include "config.h" +#ifdef HAVE_PYTHON +#include <Python.h> +#include <fcntl.h> +#include "coord.h" +#include "map.h" +#include "mapset.h" + +#if defined(MS_WINDOWS) || defined(__CYGWIN__) +#define Obj_HEAD PyObject_HEAD_INIT(NULL); +#else +#define Obj_HEAD PyObject_HEAD_INIT(&PyType_Type) +#endif + +/* *** coord *** */ + +typedef struct { + PyObject_HEAD + struct coord *c; +} coordObject; + +static void coord_destroy_py(coordObject *self); + +PyTypeObject coord_Type = { + Obj_HEAD + .tp_name="coord", + .tp_basicsize=sizeof(coordObject), + .tp_dealloc=(destructor)coord_destroy_py, +}; + + +/* *** map *** */ + +typedef struct { + PyObject_HEAD + struct map *m; +} mapObject; + +static void map_destroy_py(mapObject *self); +static PyObject *map_getattr_py(PyObject *self, char *name); + +PyTypeObject map_Type = { + Obj_HEAD + .tp_name="map", + .tp_basicsize=sizeof(mapObject), + .tp_dealloc=(destructor)map_destroy_py, + .tp_getattr=map_getattr_py, +}; + +/* *** IMPLEMENTATIONS *** */ + +/* *** coord *** */ + +static PyObject * +coord_new_py(PyObject *self, PyObject *args) +{ + coordObject *ret; + int x,y; + if (!PyArg_ParseTuple(args, "ii:navit.coord",&x,&y)) + return NULL; + ret=PyObject_NEW(coordObject, &coord_Type); + ret->c=coord_new(x,y); + return (PyObject *)ret; +} + +static void +coord_destroy_py(coordObject *self) +{ + coord_destroy(self->c); +} + +/* *** coord_rect *** */ + +typedef struct { + PyObject_HEAD + struct coord_rect *r; +} coord_rectObject; + + +static void coord_rect_destroy_py(coord_rectObject *self); + +PyTypeObject coord_rect_Type = { +#if defined(MS_WINDOWS) || defined(__CYGWIN__) + PyObject_HEAD_INIT(NULL); +#else + PyObject_HEAD_INIT(&PyType_Type) +#endif + .tp_name="coord_rect", + .tp_basicsize=sizeof(coord_rectObject), + .tp_dealloc=(destructor)coord_rect_destroy_py, +}; + +static PyObject * +coord_rect_new_py(PyObject *self, PyObject *args) +{ + coord_rectObject *ret; + coordObject *lu,*rd; + if (!PyArg_ParseTuple(args, "O!O!:navit.coord_rect_rect",&coord_Type,&lu,&coord_Type,&rd)) + return NULL; + ret=PyObject_NEW(coord_rectObject, &coord_rect_Type); + ret->r=coord_rect_new(lu->c,rd->c); + return (PyObject *)ret; +} + +static void +coord_rect_destroy_py(coord_rectObject *self) +{ + coord_rect_destroy(self->r); +} + +/* *** map_rect *** */ + +typedef struct { + PyObject_HEAD + struct map_rect *mr; +} map_rectObject; + + +static void map_rect_destroy_py(map_rectObject *self); + +PyTypeObject map_rect_Type = { +#if defined(MS_WINDOWS) || defined(__CYGWIN__) + PyObject_HEAD_INIT(NULL); +#else + PyObject_HEAD_INIT(&PyType_Type) +#endif + .tp_name="map_rect", + .tp_basicsize=sizeof(map_rectObject), + .tp_dealloc=(destructor)map_rect_destroy_py, +}; + +static PyObject * +map_rect_new_py(mapObject *self, PyObject *args) +{ + map_rectObject *ret; + coord_rectObject *r; + if (!PyArg_ParseTuple(args, "O!:navit.map_rect_rect",&coord_rect_Type,&r)) + return NULL; + ret=PyObject_NEW(map_rectObject, &map_rect_Type); + ret->mr=map_rect_new(self->m, r->r, NULL, 0); + return (PyObject *)ret; +} + +static void +map_rect_destroy_py(map_rectObject *self) +{ + map_rect_destroy(self->mr); +} + + +/* *** map *** */ + + + +static PyMethodDef map_methods[] = { + {"map_rect_new", (PyCFunction) map_rect_new_py, METH_VARARGS }, + {NULL, NULL }, +}; + +static PyObject * +map_getattr_py(PyObject *self, char *name) +{ + return Py_FindMethod(map_methods, self, name); +} + + +static PyObject * +map_new_py(PyObject *self, PyObject *args) +{ + mapObject *ret; + char *type, *filename; + + if (!PyArg_ParseTuple(args, "ss:navit.map", &type, &filename)) + return NULL; + ret=PyObject_NEW(mapObject, &map_Type); + ret->m=map_new(type,filename); + return (PyObject *)ret; +} + +static void +map_destroy_py(mapObject *self) +{ + map_destroy(self->m); +} + +/* *** mapset *** */ + + +typedef struct { + PyObject_HEAD + struct mapset *ms; +} mapsetObject; + + +static void mapset_destroy_py(mapsetObject *self); +static PyObject *mapset_getattr_py(PyObject *self, char *name); + +PyTypeObject mapset_Type = { +#if defined(MS_WINDOWS) || defined(__CYGWIN__) + PyObject_HEAD_INIT(NULL); +#else + PyObject_HEAD_INIT(&PyType_Type) +#endif + .tp_name="mapset", + .tp_basicsize=sizeof(mapsetObject), + .tp_dealloc=(destructor)mapset_destroy_py, + .tp_getattr=mapset_getattr_py, +}; + +static PyObject * +mapset_add_py(mapsetObject *self, PyObject *args) +{ + mapObject *map; + if (!PyArg_ParseTuple(args, "O:navit.mapset", &map)) + return NULL; + Py_INCREF(map); + mapset_add(self->ms, map->m); + return Py_BuildValue(""); +} + +static PyMethodDef mapset_methods[] = { + {"add", (PyCFunction) mapset_add_py, METH_VARARGS }, + {NULL, NULL }, +}; + +static PyObject * +mapset_getattr_py(PyObject *self, char *name) +{ + return Py_FindMethod(mapset_methods, self, name); +} + +static PyObject * +mapset_new_py(PyObject *self, PyObject *args) +{ + mapsetObject *ret; + if (!PyArg_ParseTuple(args, ":navit.mapset")) + return NULL; + ret=PyObject_NEW(mapsetObject, &mapset_Type); + ret->ms=mapset_new(); + return (PyObject *)ret; +} + +static void +mapset_destroy_py(mapsetObject *self) +{ + mapset_destroy(self->ms); +} + + + +static PyMethodDef navitMethods[]={ + {"coord", coord_new_py, METH_VARARGS, "Create a new coordinate point."}, + {"coord_rect", coord_rect_new_py, METH_VARARGS, "Create a new coordinate rectangle."}, + {"map", map_new_py, METH_VARARGS, "Create a new map."}, + {"mapset", mapset_new_py, METH_VARARGS, "Create a new mapset."}, + {NULL, NULL, 0, NULL} +}; + + +void python_init(void) +{ + int fd,size; + char buffer[65536]; + + return; + + Py_Initialize(); + Py_InitModule("navit", navitMethods); + fd=open("startup.py",O_RDONLY); + if (fd >= 0) { + size=read(fd, buffer, 65535); + if (size > 0) { + buffer[size]='\0'; + PyRun_SimpleString(buffer); + } + } + + Py_Finalize(); + exit(0); +} +#endif diff --git a/src/python.h b/src/python.h new file mode 100644 index 00000000..9829b130 --- /dev/null +++ b/src/python.h @@ -0,0 +1,2 @@ +void python_init(void); + diff --git a/src/route.c b/src/route.c index 8907a54b..aa239e75 100644 --- a/src/route.c +++ b/src/route.c @@ -1,286 +1,326 @@ #include <stdio.h> #include <string.h> +#if 0 #include <math.h> #include <assert.h> #include <unistd.h> #include <sys/time.h> +#endif #include <glib.h> +#include "config.h" +#include "debug.h" +#include "profile.h" #include "coord.h" -#include "param.h" -#include "map_data.h" -#include "block.h" -#include "street.h" -#include "street_data.h" -#include "display.h" -#include "transform.h" +#include "map.h" +#include "mapset.h" +#include "item.h" #include "route.h" -#include "phrase.h" -#include "navigation.h" +#include "track.h" +#include "graphics.h" +#include "transform.h" #include "fib-1.0/fib.h" -#include "time.h" -#include "container.h" - -/* Node1: 4 */ -/* Node2: 4 */ -/* Segid: 4 */ -/* len: 4 */ -/* type: 1 */ -/* limit/order: 1 */ -/* 18 Bytes */ -extern void *speech_handle; -static int speed_list[16]={120,120,80,110,90,80,60,90,80,70,60,50,30,10,0,60}; +static int speed_list[]={ + 10, /* street_0 */ + 10, /* street_1_city */ + 30, /* street_2_city */ + 40, /* street_3_city */ + 50, /* street_4_city */ + 80, /* highway_city */ + 60, /* street_1_land */ + 65, /* street_2_land */ + 70, /* street_3_land */ + 80, /* street_4_land */ + 120, /* street_n_lanes */ + 120, /* highway_land */ + 40, /* ramp */ + 30, /* ferry */ +}; int debug_route=0; -#define GC_TEXT_FG 7 -#define GC_TEXT_BG 8 -#define GC_BLACK 9 -#define GC_RED 21 - -int hx=0x1416bc; /* 447C9E dx=3E18, dxmg=5E09*/ -int hy=0x5f224c; /* 5282B5 dy=5E07, dymg=8F1C*/ -int segid_h=0x20461961; - -int hkx=0x1474c5; /* 44BAB6 */ -int hky=0x5fb168; /* 52E0BC */ - -int lx=0x141ac3; -int ly=0x5f2d7a; - -int trace; -/* 0x141b53, 0x5f2065 */ - -struct coord3d { - struct coord xy; - int h; -}; - -struct route_point { - struct route_point *next; - struct route_point *hash_next; - struct route_segment *start; - struct route_segment *end; - struct route_segment *seg; -#if 0 - int conn; - int id; -#endif +struct route_graph_point { + struct route_graph_point *next; + struct route_graph_point *hash_next; + struct route_graph_segment *start; + struct route_graph_segment *end; + struct route_graph_segment *seg; struct fibheap_el *el; int value; - struct coord3d c; + struct coord c; }; -struct route_segment { - struct route_segment *next; - struct route_segment *start_next; - struct route_segment *end_next; - struct route_point *start; - struct route_point *end; - struct street_str *str; - struct street_type *strt; +struct route_graph_segment { + struct route_graph_segment *next; + struct route_graph_segment *start_next; + struct route_graph_segment *end_next; + struct route_graph_point *start; + struct route_graph_point *end; + struct item item; int limit; int len; - int offset; }; -struct street_info { - struct street_header *hdr; - struct street_type *strt; - struct street_str *str; - unsigned char *p; - int bytes; - int include; +struct route_path_segment { + struct item item; + int time; + int length; + struct coord c[2]; + struct route_path_segment *next; +}; + + +struct street_data { + struct item item; + int count; + int limit; + struct coord c[0]; }; struct route_info { - int mode; - struct coord3d seg1,seg2,line1,line2,pos,click; - int seg1_len,seg2_len; - int offset; + struct coord c; + struct coord lp; + int pos; + int dist; - struct block_info blk_inf; - struct street_info str_inf; + int dir; + + struct street_data *street; }; -struct route { - struct map_data *map_data; - double route_time_val; - double route_len_val; +struct route_path { struct route_path_segment *path; struct route_path_segment *path_last; + struct item_hash *path_hash; +}; + + +struct route { + int version; + struct mapset *ms; struct route_info *pos; struct route_info *dst; - struct route_segment *route_segments; - struct route_point *route_points; - struct block_list *blk_lst; + + struct route_graph *graph; + struct route_path *path2; + +}; + +struct route_graph { + struct route_graph_point *route_points; + struct route_graph_segment *route_segments; #define HASH_SIZE 8192 - struct route_point *hash[HASH_SIZE]; + struct route_graph_point *hash[HASH_SIZE]; }; +static struct route_info * route_find_nearest_street(struct mapset *ms, struct coord *c); +static struct route_graph_point *route_graph_get_point(struct route_graph *this, struct coord *c); +static void route_graph_update(struct route *this); +static struct route_path *route_path_new(struct route_graph *this, struct route_info *pos, struct route_info *dst); +static void route_process_street_graph(struct route_graph *this, struct item *item); +static void route_graph_destroy(struct route_graph *this); +static void route_path_update(struct route *this); + + +static void +route_path_destroy(struct route_path *this) +{ + struct route_path_segment *c,*n; + if (! this) + return; + if (this->path_hash) { + item_hash_destroy(this->path_hash); + this->path_hash=NULL; + } + c=this->path; + while (c) { + n=c->next; + g_free(c); + c=n; + } + g_free(this); +} + struct route * -route_new(void) +route_new(struct mapset *ms) { struct route *this=g_new0(struct route, 1); + this->ms=ms; return this; } -static void -route_path_free(struct route *this) +struct mapset * +route_get_mapset(struct route *this) { - struct route_path_segment *curr, *next; - curr=this->path; + return this->ms; +} - while (curr) { - next=curr->next; - g_free(curr); - curr=next; - } - this->path=NULL; - this->path_last=NULL; +struct route_info * +route_get_pos(struct route *this) +{ + return this->pos; } -void -route_mapdata_set(struct route *this, struct map_data *mdata) +struct route_info * +route_get_dst(struct route *this) { - this->map_data=mdata; + return this->dst; } -struct map_data * -route_mapdata_get(struct route *this) +int +route_contains(struct route *this, struct item *item) { - return this->map_data; + if (! this->path2 || !item_hash_lookup(this->path2->path_hash, item)) + return 0; + return 1; } static void -route_add_path_segment(struct route *this, int country, s32 segid, int offset, struct coord *start, struct coord *end, int dir, int len, int time) +route_path_update(struct route *this) { - struct route_path_segment *segment=g_new0(struct route_path_segment,1); - - segment->next=NULL; - segment->country=country; - segment->segid=segid; - segment->offset=offset; - segment->dir=dir; - segment->length=len; - segment->time=time; - if (start) - segment->c[0]=*start; - if (end) - segment->c[1]=*end; - if (!this->path) - this->path=segment; - if (this->path_last) - this->path_last->next=segment; - this->path_last=segment; + route_path_destroy(this->path2); + if (! this->graph || !(this->path2=route_path_new(this->graph, this->pos, this->dst))) { + profile(0,NULL); + route_graph_update(this); + this->path2=route_path_new(this->graph, this->pos, this->dst); + profile(1,"route_path_new"); + profile(0,"end"); + } } void route_set_position(struct route *this, struct coord *pos) { - struct route_info *rt; - - route_path_free(this); - rt=route_find_nearest_street(this->map_data, pos); - route_find_point_on_street(rt); if (this->pos) - g_free(this->pos); - this->pos=rt; - if (this->dst) { - route_find(this, this->pos, this->dst); - } -} - -struct route_path_segment * -route_path_get_all(struct route *this) -{ - return this->path; + route_info_free(this->pos); + this->pos=route_find_nearest_street(this->ms, pos); + dbg(0,"this->pos=%p\n", this->pos); + if (! this->pos) + return; + if (this->dst) + route_path_update(this); } -struct route_path_segment * -route_path_get(struct route *this, s32 segid) +void +route_set_position_from_track(struct route *this, struct track *track) { - struct route_path_segment *curr=this->path; - - while (curr) { - if (curr->segid == segid) - return curr; - curr=curr->next; - } - return NULL; + struct coord *c; + struct route_info *ret; + c=track_get_pos(track); + ret=g_new0(struct route_info, 1); + if (this->pos) + route_info_free(this->pos); + ret->c=*c; + ret->lp=*c; + ret->pos=track_get_segment_pos(track); + ret->dist=0; + ret->dir=0; + ret->street=street_data_dup(track_get_street_data(track)); + this->pos=ret; + if (this->dst) + route_path_update(this); } -void -route_set_destination(struct route *this, struct coord *dest) -{ - struct route_info *rt; +struct map_selection *route_selection; - rt=route_find_nearest_street(this->map_data, dest); - route_find_point_on_street(rt); - if (this->dst) - g_free(this->dst); - this->dst=rt; - route_do_start(this, this->pos, this->dst); +struct map_selection * +route_rect(int order, struct coord *c1, struct coord *c2, int rel, int abs) +{ + int dx,dy,sx=1,sy=1,d,m; + struct map_selection *sel=g_new(struct map_selection, 1); + sel->order[layer_town]=0; + sel->order[layer_poly]=0; + sel->order[layer_street]=order; + dbg(1,"%p %p\n", c1, c2); + dx=c1->x-c2->x; + dy=c1->y-c2->y; + if (dx < 0) { + sx=-1; + sel->rect.lu.x=c1->x; + sel->rect.rl.x=c2->x; + } else { + sel->rect.lu.x=c2->x; + sel->rect.rl.x=c1->x; + } + if (dy < 0) { + sy=-1; + sel->rect.lu.y=c2->y; + sel->rect.rl.y=c1->y; + } else { + sel->rect.lu.y=c1->y; + sel->rect.rl.y=c2->y; + } + if (dx*sx > dy*sy) + d=dx*sx; + else + d=dy*sy; + m=d*rel/100+abs; + sel->rect.lu.x-=m; + sel->rect.rl.x+=m; + sel->rect.lu.y+=m; + sel->rect.rl.y-=m; + sel->next=NULL; + return sel; } -struct coord * -route_get_destination(struct route *this) +static struct map_selection * +route_calc_selection(struct coord *c1, struct coord *c2) { - if (! this->dst) - return NULL; - return &this->dst->click.xy; + struct map_selection *ret,*sel; + sel=route_rect(4, c1, c2, 25, 0); + ret=sel; + sel->next=route_rect(8, c1, c1, 0, 40000); + sel=sel->next; + sel->next=route_rect(18, c1, c1, 0, 10000); + sel=sel->next; + sel->next=route_rect(8, c2, c2, 0, 40000); + sel=sel->next; + sel->next=route_rect(18, c2, c2, 0, 10000); + /* route_selection=ret; */ + return ret; } static void -route_street_foreach(struct block_info *blk_inf, unsigned char *p, unsigned char *end, void *data, - void(*func)(struct block_info *, struct street_info *, unsigned char **, unsigned char *, void *)) +route_free_selection(struct map_selection *sel) { - struct street_info str_inf; - struct street_str *str,*str_tmp; - - if (blk_inf->block_number == 0x10c6) { - printf("route_street_foreach p=%p\n", p); + struct map_selection *next; + while (sel) { + next=sel->next; + g_free(sel); + sel=next; } - str_inf.hdr=(struct street_header *)p; - p+=sizeof(struct street_header); - assert(str_inf.hdr->count == blk_inf->block->count); +} - str_inf.bytes=street_get_bytes(blk_inf->block); - - str_inf.strt=(struct street_type *)p; - p+=blk_inf->block->count*sizeof(struct street_type); - str=(struct street_str *)p; - str_tmp=str; - while (str_tmp->segid) - str_tmp++; - p=(unsigned char *)str_tmp; - p+=4; - - while (str->segid) { - str_inf.include=(str[1].segid > 0); - str_inf.str=str; - str_inf.p=p; - func(blk_inf, &str_inf, &p, end-4, data); - if (!str_inf.include) - str_inf.strt++; - str++; - } +void +route_set_destination(struct route *this, struct coord *dst) +{ + profile(0,NULL); + if (this->dst) + route_info_free(this->dst); + this->dst=route_find_nearest_street(this->ms, dst); + if (! this->dst || ! this->pos) + return; + profile(1,"find_nearest_street"); + + route_graph_destroy(this->graph); + this->graph=NULL; + route_path_update(this); + profile(0,"end"); } - -static struct route_point * -route_get_point(struct route *this, struct coord3d *c) +static struct route_graph_point * +route_graph_get_point(struct route_graph *this, struct coord *c) { - struct route_point *p=this->route_points; - int hashval=(c->xy.x + c->xy.y + c->h) & (HASH_SIZE-1); + struct route_graph_point *p=this->route_points; + int hashval=(c->x + c->y) & (HASH_SIZE-1); p=this->hash[hashval]; while (p) { - if (p->c.xy.x == c->xy.x && p->c.xy.y == c->xy.y && p->c.h == c->h) + if (p->c.x == c->x && p->c.y == c->y) return p; p=p->hash_next; } @@ -288,29 +328,21 @@ route_get_point(struct route *this, struct coord3d *c) } -static struct route_point * -route_point_add(struct route *this, struct coord3d *f, int conn) +static struct route_graph_point * +route_graph_add_point(struct route_graph *this, struct coord *f) { int hashval; - struct route_point *p; + struct route_graph_point *p; - p=route_get_point(this,f); - if (p) { -#if 0 - p->conn+=conn; -#endif - } else { - hashval=(f->xy.x + f->xy.y + f->h) & (HASH_SIZE-1); + p=route_graph_get_point(this,f); + if (!p) { + hashval=(f->x + f->y) & (HASH_SIZE-1); if (debug_route) - printf("p (0x%lx,0x%lx,0x%x)\n", f->xy.x, f->xy.y, f->h); - p=g_new(struct route_point,1); + printf("p (0x%x,0x%x)\n", f->x, f->y); + p=g_new(struct route_graph_point,1); p->hash_next=this->hash[hashval]; this->hash[hashval]=p; p->next=this->route_points; -#if 0 - p->conn=conn; - p->id=++id; -#endif p->el=NULL; p->start=NULL; p->end=NULL; @@ -322,10 +354,11 @@ route_point_add(struct route *this, struct coord3d *f, int conn) return p; } + static void -route_points_free(struct route *this) +route_graph_free_points(struct route_graph *this) { - struct route_point *curr,*next; + struct route_graph_point *curr,*next; curr=this->route_points; while (curr) { next=curr->next; @@ -337,32 +370,113 @@ route_points_free(struct route *this) } static void -route_segment_add(struct route *this, struct route_point *start, struct route_point *end, int len, struct street_str *str, struct street_type *strt, int offset, int limit) +route_graph_add_segment(struct route_graph *this, struct route_graph_point *start, struct route_graph_point *end, int len, struct item *item, int limit) { - struct route_segment *s; - s=g_new0(struct route_segment,1); + struct route_graph_segment *s; + s=g_new0(struct route_graph_segment,1); s->start=start; s->start_next=start->start; start->start=s; s->end=end; s->end_next=end->end; end->end=s; + g_assert(len >= 0); s->len=len; - s->str=str; - s->strt=strt; - s->offset=offset; + s->item=*item; s->limit=limit; s->next=this->route_segments; this->route_segments=s; if (debug_route) - printf("l (0x%lx,0x%lx,0x%x)-(0x%lx,0x%lx,0x%x)\n", start->c.xy.x, start->c.xy.y, start->c.h, end->c.xy.x, end->c.xy.y, end->c.h); + printf("l (0x%x,0x%x)-(0x%x,0x%x)\n", start->c.x, start->c.y, end->c.x, end->c.y); } static void -route_segments_free(struct route *this) +route_path_add_item(struct route_path *this, struct item *itm, struct coord *start, struct coord *end, int len, int time) +{ + struct route_path_segment *segment=g_new0(struct route_path_segment,1); + item_hash_insert(this->path_hash, itm, (void *)1); + segment->item=*itm; + segment->next=NULL; + segment->length=len; + segment->time=time; + if (start) + segment->c[0]=*start; + if (end) + segment->c[1]=*end; + if (!this->path) + this->path=segment; + if (this->path_last) + this->path_last->next=segment; + this->path_last=segment; +} + + +struct route_path_handle { + struct route_path_segment *s; +}; + +struct route_path_handle * +route_path_open(struct route *this) +{ + struct route_path_handle *ret=g_new(struct route_path_handle, 1); + + ret->s=this->path2->path; + return ret; +} + +struct route_path_segment * +route_path_get_segment(struct route_path_handle *h) +{ + struct route_path_segment *ret=h->s; + + if (ret) + h->s=ret->next; + + return ret; +} + +struct coord * +route_path_segment_get_start(struct route_path_segment *s) +{ + return &s->c[0]; +} + +struct coord * +route_path_segment_get_end(struct route_path_segment *s) +{ + return &s->c[1]; +} + +struct item * +route_path_segment_get_item(struct route_path_segment *s) +{ + return &s->item; +} + +int +route_path_segment_get_length(struct route_path_segment *s) +{ + return s->length; +} + +int +route_path_segment_get_time(struct route_path_segment *s) +{ + return s->time; +} + +void +route_path_close(struct route_path_handle *h) +{ + g_free(h); +} + + +static void +route_graph_free_segments(struct route_graph *this) { - struct route_segment *curr,*next; + struct route_graph_segment *curr,*next; curr=this->route_segments; while (curr) { next=curr->next; @@ -372,165 +486,156 @@ route_segments_free(struct route *this) this->route_segments=NULL; } -void -route_display_points(struct route *this, struct container *co) +static void +route_graph_destroy(struct route_graph *this) { -#if 0 - GtkMap *map=co->map; - struct route_point *p=this->route_points; - int r=5; - struct point pnt; - char text[256]; - - while (p) { - if (transform(co->trans, &p->c.xy, &pnt)) { - gdk_draw_arc(GTK_WIDGET(map)->window, map->gc[GC_BLACK], FALSE, pnt.x-r/2, pnt.y-r/2, r, r, 0, 64*360); - if (p->value != -1) { - sprintf(text,"%d", p->value); -#if 0 - display_text(GTK_WIDGET(map)->window, map->gc[GC_TEXT_FG], map->gc[GC_TEXT_BG], map->face[0], text, pnt.x+6, pnt.y+4, 0x10000, 0); -#endif - } - } - p=p->next; + if (this) { + route_graph_free_points(this); + route_graph_free_segments(this); + g_free(this); } -#endif } -static int -route_time(int type, int len) +int +route_time(struct item *item, int len) { - // The following is a quick hack to handle - // properly tolled road, at least in France. - extern struct container *co; - if((type==0x21)||(type==0x61)){ - if(co->flags->tollfree){ - // We don't allow tolled roads. We return the highest possible value. - return len*36; - } else { - type=1; - } - } - if(speed_list[type & 0x3f]<1 || speed_list[type & 0x3f]>150){ - // The road here hasn't its speed correctly set up. - // I think it's best to assign it a high cost for the moment. - printf("Road type %x (%i) is unknown (speed %i, key %i), assigning high cost\n",type,type,speed_list[type & 0x3f],(type & 0x3f)); + int idx=(item->type-type_street_0); + if (idx >= sizeof(speed_list)/sizeof(int) || idx < 0) { + dbg(0,"street idx(%d) out of range [0,%d[", sizeof(speed_list)/sizeof(int)); return len*36; } - return len*36/speed_list[type & 0x3f]; + return len*36/speed_list[idx]; } -static int -route_value(int type, int len) -{ - return route_time(type, len); -} static int -route_get_height(s32 segid, struct coord *c) +route_value(struct item *item, int len) { - if (c->x == 0x141b53 && c->y == 0x5f2065 && (segid == 0x4fad2fa || segid == 0x4fad155)) - return 1; - if (c->x == 0x1477a7 && c->y == 0x5fac38 && (segid == 0x32adac2 || segid == 0x40725c6)) - return 1; - if (c->x == 0x147a4c && c->y == 0x5fb194 && (segid == 0x32adb17 || segid == 0x32adb16)) - return 1; - return 0; + int ret; + if (len < 0) { + printf("len=%d\n", len); + } + g_assert(len >= 0); + ret=route_time(item, len); + dbg(1, "route_value(0x%x, %d)=%d\n", item->type, len, ret); + return ret; } static void -route_process_street_graph(struct block_info *blk_inf, struct street_info *str_inf, unsigned char **p, unsigned char *end, void *data) +route_process_street_graph(struct route_graph *this, struct item *item) { - struct route *this=data; - int limit,flags=0; +#ifdef AVOID_FLOAT + int len=0; +#else double len=0; - struct coord3d f,o,l; - struct route_point *s_pnt,*e_pnt; - - street_get_coord(p, str_inf->bytes, blk_inf->block->c, &f.xy); - f.h=route_get_height(str_inf->str->segid, &f.xy); - s_pnt=route_point_add(this,&f, 1); - - l=f; - o=f; - while (*p < end) { - flags=street_get_coord(p, str_inf->bytes, blk_inf->block->c, &f.xy); - if (flags && !str_inf->include) - break; - len+=transform_distance(&l.xy, &o.xy); - l=o; - o=f; - if (flags) - break; +#endif + struct route_graph_point *s_pnt,*e_pnt; + struct coord c,l; + struct attr attr; + + + if (item_coord_get(item, &l, 1)) { + s_pnt=route_graph_add_point(this,&l); + while (item_coord_get(item, &c, 1)) { + len+=transform_distance(&l, &c); + l=c; + } + e_pnt=route_graph_add_point(this,&l); + g_assert(len >= 0); + if (item_attr_get(item, attr_limit, &attr)) + route_graph_add_segment(this, s_pnt, e_pnt, len, item, attr.u.num); + else + route_graph_add_segment(this, s_pnt, e_pnt, len, item, 0); } - len+=transform_distance(&l.xy, &o.xy); - o.h=route_get_height(str_inf->str->segid, &o.xy); - e_pnt=route_point_add(this,&o, 1); - - limit=str_inf->str->limit; - if (str_inf->str->limit == 0x30 && (str_inf->str->type & 0x40)) - limit=0x03; - if (str_inf->str->limit == 0x03 && (str_inf->str->type & 0x40)) - limit=0x30; - - if (str_inf->str->limit != 0x33) - route_segment_add(this, s_pnt, e_pnt, len, str_inf->str, str_inf->strt, 0, limit); - debug_route=0; - *p-=2*str_inf->bytes; } static int compare(void *v1, void *v2) { - struct route_point *p1=v1; - struct route_point *p2=v2; + struct route_graph_point *p1=v1; + struct route_graph_point *p2=v2; +#if 0 + if (debug_route) + printf("compare %d (%p) vs %d (%p)\n", p1->value,p1,p2->value,p2); +#endif return p1->value-p2->value; } +int +route_info_length(struct route_info *pos, struct route_info *dst, int dir) +{ + struct route_info_handle *h; + struct coord *c,*l; + int ret=0; + + h=route_info_open(pos, dst, dir); + if (! h) + return -1; + l=route_info_get(h); + while ((c=route_info_get(h))) { + ret+=transform_distance(c, l); + l=c; + } + return ret; +} + static void -route_flood(struct route *this, struct route_info *rt_end) +route_graph_flood(struct route_graph *this, struct route_info *dst) { - struct route_point *end; - struct route_point *p_min; - struct route_segment *s; + struct route_graph_point *p_min,*end=NULL; + struct route_graph_segment *s; int min,new,old,val; struct fibheap *heap; - - heap = fh_makeheap(); + struct street_data *sd=dst->street; + heap = fh_makeheap(); fh_setcmp(heap, compare); - end=route_get_point(this, &rt_end->pos); - assert(end != 0); - end->value=0; - end->el=fh_insert(heap, end); + if (! (sd->limit & 2)) { + end=route_graph_get_point(this, &sd->c[0]); + g_assert(end != 0); + end->value=route_value(&sd->item, route_value(&sd->item, route_info_length(NULL, dst, -1))); + end->el=fh_insert(heap, end); + } + + if (! (sd->limit & 1)) { + end=route_graph_get_point(this, &sd->c[sd->count-1]); + g_assert(end != 0); + end->value=route_value(&sd->item, route_value(&sd->item, route_info_length(NULL, dst, 1))); + end->el=fh_insert(heap, end); + } + + dbg(1,"0x%x,0x%x\n", end->c.x, end->c.y); for (;;) { p_min=fh_extractmin(heap); if (! p_min) break; min=p_min->value; if (debug_route) - printf("min=%d, 0x%lx, 0x%lx\n", min, p_min->c.xy.x, p_min->c.xy.y); + printf("extract p=%p free el=%p min=%d, 0x%x, 0x%x\n", p_min, p_min->el, min, p_min->c.x, p_min->c.y); + p_min->el=NULL; s=p_min->start; while (s) { - val=route_value(s->str->type, s->len); + val=route_value(&s->item, s->len); #if 0 val+=val*2*street_route_contained(s->str->segid); #endif new=min+val; if (debug_route) - printf("begin %d (0x%lx,0x%lx) ",new,s->end->c.xy.x, s->end->c.xy.y); - if (new < s->end->value && !(s->limit & 0x30)) { + printf("begin %d len %d vs %d (0x%x,0x%x)\n",new,val,s->end->value, s->end->c.x, s->end->c.y); + if (new < s->end->value && !(s->limit & 1)) { s->end->value=new; s->end->seg=s; if (! s->end->el) { if (debug_route) - printf("insert"); + printf("insert_end p=%p el=%p val=%d ", s->end, s->end->el, s->end->value); s->end->el=fh_insert(heap, s->end); + if (debug_route) + printf("el new=%p\n", s->end->el); } else { if (debug_route) - printf("replace"); + printf("replace_end p=%p el=%p val=%d\n", s->end, s->end->el, s->end->value); fh_replacedata(heap, s->end->el, s->end); } } @@ -540,21 +645,24 @@ route_flood(struct route *this, struct route_info *rt_end) } s=p_min->end; while (s) { - new=min+route_value(s->str->type, s->len); + val=route_value(&s->item, s->len); + new=min+val; if (debug_route) - printf("end %d vs %d (0x%lx,0x%lx) ",new,s->start->value,s->start->c.xy.x, s->start->c.xy.y); - if (new < s->start->value && !(s->limit & 0x03)) { + printf("end %d len %d vs %d (0x%x,0x%x)\n",new,val,s->start->value,s->start->c.x, s->start->c.y); + if (new < s->start->value && !(s->limit & 2)) { old=s->start->value; s->start->value=new; s->start->seg=s; if (! s->start->el) { if (debug_route) - printf("insert"); + printf("insert_start p=%p el=%p val=%d ", s->start, s->start->el, s->start->value); s->start->el=fh_insert(heap, s->start); + if (debug_route) + printf("el new=%p\n", s->start->el); } else { if (debug_route) - printf("replace"); + printf("replace_start p=%p el=%p val=%d\n", s->start, s->start->el, s->start->value); fh_replacedata(heap, s->start->el, s->start); } } @@ -563,495 +671,478 @@ route_flood(struct route *this, struct route_info *rt_end) s=s->end_next; } } + fh_deleteheap(heap); } -int -route_find(struct route *this, struct route_info *rt_start, struct route_info *rt_end) +static struct route_path * +route_path_new(struct route_graph *this, struct route_info *pos, struct route_info *dst) { - struct route_point *start,*start1,*start2; - struct route_segment *s=NULL; - double len=0,slen; - int ret,hr,min,time=0,seg_time,dir,type; + struct route_graph_point *start1=NULL,*start2=NULL,*start; + struct route_graph_segment *s=NULL; + int len=0,segs=0; + int ilen,hr,min,sec,time=0,seg_time,seg_len; unsigned int val1=0xffffffff,val2=0xffffffff; - - start1=route_get_point(this, &rt_start->seg1); - start2=route_get_point(this, &rt_start->seg2); - assert(start1 != 0); - assert(start2 != 0); - if (start1->value != -1) - val1=start1->value+route_value(rt_start->str_inf.str->type, rt_start->seg1_len); - if (start2->value != -1) - val2=start2->value+route_value(rt_start->str_inf.str->type, rt_start->seg2_len); - - route_add_path_segment(this, 0, 0, 0, &rt_start->click.xy, &rt_start->pos.xy, 1, 0, 0); - type=rt_start->str_inf.str->type; - if (val1 < val2) { - ret=1; - start=start1; - slen=transform_distance(&rt_start->pos.xy, &rt_start->line1.xy); - route_add_path_segment(this, 0, 0, 0, &rt_start->pos.xy, &rt_start->line1.xy, 1, slen, route_time(type, slen)); - route_add_path_segment(this, rt_start->str_inf.strt->country, rt_start->str_inf.str->segid, rt_start->offset, NULL, NULL, -1, rt_start->seg1_len, route_time(type, rt_start->seg1_len)); + struct street_data *sd=pos->street; + struct route_path *ret; + + if (! (sd->limit & 1)) { + start1=route_graph_get_point(this, &sd->c[0]); + if (! start1) + return NULL; + val1=start1->value+route_value(&sd->item, route_info_length(pos, NULL, -1)); + dbg(0,"start1: %d(route)+%d=%d\n", start1->value, val1-start1->value, val1); } - else { - ret=2; - start=start2; - slen=transform_distance(&rt_start->pos.xy, &rt_start->line2.xy); - route_add_path_segment(this, 0, 0, 0, &rt_start->pos.xy, &rt_start->line2.xy, 1, slen, route_time(type, slen)); - route_add_path_segment(this, rt_start->str_inf.strt->country, rt_start->str_inf.str->segid, -rt_start->offset, NULL, NULL, 1, rt_start->seg2_len, route_time(type, rt_start->seg2_len)); + if (! (sd->limit & 2)) { + start2=route_graph_get_point(this, &sd->c[sd->count-1]); + if (! start2) + return NULL; + val2=start2->value+route_value(&sd->item, route_info_length(pos, NULL, 1)); + dbg(0,"start2: %d(route)+%d=%d\n", start2->value, val2-start2->value, val2); } - - while (start->value) { - s=start->seg; - if (! s) { - printf("No Route found\n"); - break; + if (start1 && (val1 < val2)) { + start=start1; + pos->dir=-1; + } else { + if (start2) { + start=start2; + pos->dir=1; + } else { + printf("no route found, pos blocked\n"); + return NULL; } + } + ret=g_new0(struct route_path, 1); + ret->path_hash=item_hash_new(); + dbg(0,"dir=%d\n", pos->dir); + while ((s=start->seg)) { + segs++; +#if 0 + printf("start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y); +#endif + seg_len=s->len; + seg_time=route_time(&s->item, seg_len); + len+=seg_len; + time+=seg_time; if (s->start == start) { + route_path_add_item(ret, &s->item, &s->start->c, &s->end->c, seg_len, seg_time); start=s->end; - dir=1; - } - else { + } else { + route_path_add_item(ret, &s->item, &s->end->c, &s->start->c, seg_len, seg_time); start=s->start; - dir=-1; } - len+=s->len; - seg_time=route_time(s->str->type, s->len); - time+=seg_time; - route_add_path_segment(this, s->strt->country, s->str->segid, s->offset, NULL, NULL, dir, s->len, seg_time); } - if (s) { - if (s->start->c.xy.x == rt_end->seg1.xy.x && s->start->c.xy.y == rt_end->seg1.xy.y) - route_add_path_segment(this, 0, 0, 0, &rt_end->pos.xy, &rt_end->line1.xy, -1, 0, 0); - else - route_add_path_segment(this, 0, 0, 0, &rt_end->pos.xy, &rt_end->line2.xy, -1, 0, 0); - route_add_path_segment(this, 0, 0, 0, &rt_end->click.xy, &rt_end->pos.xy, -1, 0, 0); -#if 0 - printf("len %5.3f\n", len/1000); -#endif - this->route_time_val=time/10; - time/=10; - this->route_len_val=len; - min=time/60; - time-=min*60; - hr=min/60; - min-=hr*60; -#if 0 - printf("time %02d:%02d:%02d\n", hr, min, time); -#endif -#if 1 - navigation_path_description(this); -#endif + sd=dst->street; + dbg(0,"start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y); + dbg(0,"dst sd->limit=%d sd->c[0]=0x%x,0x%x sd->c[sd->count-1]=0x%x,0x%x\n", sd->limit, sd->c[0].x,sd->c[0].y, sd->c[sd->count-1].x, sd->c[sd->count-1].y); + if (start->c.x == sd->c[0].x && start->c.y == sd->c[0].y) + dst->dir=-1; + else if (start->c.x == sd->c[sd->count-1].x && start->c.y == sd->c[sd->count-1].y) + dst->dir=1; + else { + printf("no route found\n"); + route_path_destroy(ret); + return NULL; } + ilen=route_info_length(pos, NULL, 0); + time+=route_time(&pos->street->item, ilen); + len+=ilen; + + ilen=route_info_length(NULL, dst, 0); + time+=route_time(&dst->street->item, ilen); + len+=ilen; + + dbg(0, "%d segments\n", segs); + dbg(0, "len %5.3f\n", len/1000.0); + time/=10; + sec=time; + min=time/60; + time-=min*60; + hr=min/60; + min-=hr*60; + dbg(0, "time %02d:%02d:%02d (%d sec)\n", hr, min, time, sec); + dbg(0, "speed %f km/h\n", len/sec*3.6); return ret; } -struct block_list { - struct block_info blk_inf; - unsigned char *p; - unsigned char *end; - struct block_list *next; -}; - -static void -route_process_street_block_graph(struct block_info *blk_inf, unsigned char *p, unsigned char *end, void *data) +static struct route_graph * +route_graph_build(struct mapset *ms, struct coord *c1, struct coord *c2) { - struct route *this=data; - struct block_list *blk_lst=this->blk_lst; - - while (blk_lst) { - if (blk_lst->blk_inf.block_number == blk_inf->block_number && blk_lst->blk_inf.file == blk_inf->file) - return; - blk_lst=blk_lst->next; - } - blk_lst=g_new(struct block_list,1); - blk_lst->blk_inf=*blk_inf; - blk_lst->p=p; - blk_lst->end=end; - blk_lst->next=this->blk_lst; - this->blk_lst=blk_lst; -#if 0 - route_street_foreach(blk_inf, p, end, data, route_process_street_graph); -#endif -} + struct route_graph *ret=g_new0(struct route_graph, 1); + struct map_selection *sel; + struct mapset_handle *h; + struct map_rect *mr; + struct map *m; + struct item *item; + struct coord e; + + sel=route_calc_selection(c1, c2); + h=mapset_open(ms); + while ((m=mapset_next(h,1))) { + mr=map_rect_new(m, sel); + while ((item=map_rect_get_item(mr))) { + if (item->type >= type_street_0 && item->type <= type_ferry) { + route_process_street_graph(ret, item); + } else + while (item_coord_get(item, &e, 1)); + } + map_rect_destroy(mr); + } + mapset_close(h); + route_free_selection(sel); -static void -route_blocklist_free(struct route *this) -{ - struct block_list *curr,*next; - curr=this->blk_lst; - while (curr) { - next=curr->next; - g_free(curr); - curr=next; - } + return ret; } static void -route_build_graph(struct route *this, struct map_data *mdata, struct coord *c, int coord_count) +route_graph_update(struct route *this) { - struct coord rect[2]; - struct transformation t; - - int i,j,max_dist,max_coord_dist; - int ranges[7]={0,1024000,512000,256000,128000,64000,32000}; - this->blk_lst=NULL; - struct block_list *blk_lst_curr; - - rect[0]=c[0]; - rect[1]=c[0]; - for (i = 1 ; i < coord_count ; i++) { - if (c[i].x < rect[0].x) - rect[0].x=c[i].x; - if (c[i].x > rect[1].x) - rect[1].x=c[i].x; - if (c[i].y > rect[0].y) - rect[0].y=c[i].y; - if (c[i].y < rect[1].y) - rect[1].y=c[i].y; - } - max_coord_dist=rect[1].x-rect[0].x; - if (max_coord_dist < rect[0].y-rect[1].y) - max_coord_dist=rect[0].y-rect[1].y; - max_coord_dist+=10000+max_coord_dist/2; - - printf("Collecting Blocks\n"); - for (i = 0 ; i < coord_count ; i++) { - for (j = 0 ; j < 7 ; j++) { - printf("range %d,%d\n", i, j); - max_dist=ranges[j]; - if (max_dist == 0 || max_dist > max_coord_dist) - max_dist=max_coord_dist; - - transform_setup_source_rect_limit(&t,&c[i],max_dist); - - map_data_foreach(mdata, file_street_str, &t, j+1, route_process_street_block_graph, this); - } - } - blk_lst_curr=this->blk_lst; - i=0; - while (blk_lst_curr) { - i++; - blk_lst_curr=blk_lst_curr->next; - } - printf("Block Count %d\n", i); - blk_lst_curr=this->blk_lst; - - j=0; - while (blk_lst_curr) { - j++; - printf("%d/%d\n", j, i); - route_street_foreach(&blk_lst_curr->blk_inf, blk_lst_curr->p, blk_lst_curr->end, this, route_process_street_graph); - blk_lst_curr=blk_lst_curr->next; - } + route_graph_destroy(this->graph); + profile(1,"graph_free"); + this->graph=route_graph_build(this->ms, &this->pos->c, &this->dst->c); + profile(1,"route_graph_build"); + route_graph_flood(this->graph, this->dst); + profile(1,"route_graph_flood"); + this->version++; } -static void -route_process_street3(struct block_info *blk_inf, struct street_info *str_inf, unsigned char **p, unsigned char *end, void *data) +struct street_data * +street_get_data (struct item *item) { - int flags=0; - int i,ldist; - struct coord3d first,f,o,l; - struct coord3d cret; - int match=0; - double len=0,len_p=0; - struct route_info *rt_inf=(struct route_info *)data; - - street_get_coord(p, str_inf->bytes, blk_inf->block->c, &f.xy); - f.h=route_get_height(str_inf->str->segid, &f.xy); - - l=f; - o=f; - first=f; - i=0; - - while (*p < end) { - flags=street_get_coord(p, str_inf->bytes, blk_inf->block->c, &f.xy); - f.h=route_get_height(str_inf->str->segid, &f.xy); - if (flags && !str_inf->include) - break; - - if (i++) { - ldist=transform_distance_line_sq(&l.xy, &o.xy, &rt_inf->click.xy, &cret.xy); - if (ldist < rt_inf->dist) { - rt_inf->dist=ldist; - rt_inf->seg1=first; - rt_inf->line1=l; - rt_inf->pos=cret; - rt_inf->blk_inf=*blk_inf; - rt_inf->str_inf=*str_inf; - rt_inf->line2=o; - rt_inf->offset=i-1; - len_p=len; - match=1; - } - if (rt_inf->mode == 1) - len+=transform_distance(&l.xy, &o.xy); - } - l=o; - o=f; - if (flags) + struct coord c[1000]; + int count=0; + struct street_data *ret; + struct attr attr; + + while (count < 1000) { + if (!item_coord_get(item, &c[count], 1)) break; - } - ldist=transform_distance_line_sq(&l.xy, &o.xy, &rt_inf->click.xy, &cret.xy); - if (ldist < rt_inf->dist) { - rt_inf->dist=ldist; - rt_inf->seg1=first; - rt_inf->line1=l; - rt_inf->pos=cret; - rt_inf->blk_inf=*blk_inf; - rt_inf->str_inf=*str_inf; - rt_inf->line2=o; - rt_inf->offset=i; - len_p=len; - match=1; + count++; } - if (match) { - rt_inf->seg2=o; - if (rt_inf->mode == 1) { - len+=transform_distance(&l.xy, &o.xy); - len_p+=transform_distance(&rt_inf->pos.xy, &rt_inf->line1.xy); - rt_inf->seg1_len=len_p; - rt_inf->seg2_len=len-len_p; - } - } - *p-=2*str_inf->bytes; -} + g_assert(count < 1000); + ret=g_malloc(sizeof(struct street_data)+count*sizeof(struct coord)); + ret->item=*item; + ret->count=count; + if (item_attr_get(item, attr_limit, &attr)) + ret->limit=attr.u.num; + else + ret->limit=0; + memcpy(ret->c, c, count*sizeof(struct coord)); + return ret; + +} -static void -route_process_street_block(struct block_info *blk_inf, unsigned char *p, unsigned char *end, void *data) +struct street_data * +street_data_dup(struct street_data *orig) { - route_street_foreach(blk_inf, p, end, data, route_process_street3); -} + struct street_data *ret; + int size=sizeof(struct street_data)+orig->count*sizeof(struct coord); + + ret=g_malloc(size); + memcpy(ret, orig, size); -struct street_str * -route_info_get_street(struct route_info *rt) -{ - return rt->str_inf.str; + return ret; } -struct block_info * -route_info_get_block(struct route_info *rt) +void +street_data_free(struct street_data *sd) { - return &rt->blk_inf; + g_free(sd); } -struct route_info * -route_find_nearest_street(struct map_data *mdata, struct coord *c) +static struct route_info * +route_find_nearest_street(struct mapset *ms, struct coord *c) { - struct route_info *ret=g_new0(struct route_info,1); - struct transformation t; + struct route_info *ret=NULL; int max_dist=1000; - - transform_setup_source_rect_limit(&t,c,max_dist); + struct map_selection *sel=route_rect(18, c, c, 0, max_dist); + int dist,pos; + struct mapset_handle *h; + struct map *m; + struct map_rect *mr; + struct item *item; + struct coord lp, sc[1000]; + struct street_data *sd; + + h=mapset_open(ms); + while ((m=mapset_next(h,1))) { + mr=map_rect_new(m, sel); + while ((item=map_rect_get_item(mr))) { + if (item->type >= type_street_0 && item->type <= type_ferry) { + sd=street_get_data(item); + dist=transform_distance_polyline_sq(sd->c, sd->count, c, &lp, &pos); + if (!ret || dist < ret->dist) { + if (ret) { + street_data_free(ret->street); + g_free(ret); + } + ret=g_new(struct route_info, 1); + ret->c=*c; + ret->lp=lp; + ret->pos=pos; + ret->dist=dist; + ret->dir=0; + ret->street=sd; + dbg(1,"dist=%d id 0x%x 0x%x pos=%d\n", dist, item->id_hi, item->id_lo, pos); + } else + street_data_free(sd); + } else + while (item_coord_get(item, &sc[0], 1)); + } + map_rect_destroy(mr); + } + mapset_close(h); - ret->click.xy=*c; - ret->dist=INT_MAX; - ret->mode=0; - - map_data_foreach(mdata, file_street_str, &t, 48, route_process_street_block, ret); - return ret; } void -route_find_point_on_street(struct route_info *rt_inf) +route_info_free(struct route_info *inf) { - unsigned char *p,*end; - - rt_inf->dist=INT_MAX; - rt_inf->mode=1; - - p=rt_inf->str_inf.p; - end=(unsigned char *)rt_inf->blk_inf.block; - end+=rt_inf->blk_inf.block->size; - - route_process_street3(&rt_inf->blk_inf, &rt_inf->str_inf, &p, end, rt_inf); + if (inf->street) + street_data_free(inf->street); + g_free(inf); } -struct route_info *start,*end; -int count; +#include "point.h" +#include "projection.h" -void -route_click(struct route *this, struct container *co, int x, int y) +struct street_data * +route_info_street(struct route_info *rinf) { -#if 0 - GtkMap *map=co->map; - struct point pnt; - GdkBitmap *flag_mask; - GdkPixmap *flag; - struct coord c; - struct route_info *rt_inf; - GdkGC *gc; - - - pnt.x=x; - pnt.y=y; - transform_reverse(co->trans, &pnt, &c); - transform(co->trans, &c, &pnt); - rt_inf=route_find_nearest_street(co->map_data, &c); - + return rinf->street; +} - route_find_point_on_street(rt_inf); +struct coord * +route_info_point(struct route_info *rinf, int point) +{ + struct street_data *sd=rinf->street; + int dir; + + switch(point) { + case -1: + case 2: + dir=point == 2 ? rinf->dir : -rinf->dir; + if (dir > 0) + return &sd->c[sd->count-1]; + else + return &sd->c[0]; + case 0: + return &rinf->c; + case 1: + return &rinf->lp; + } + return NULL; - flag=gdk_pixmap_create_from_xpm_d(GTK_WIDGET(map)->window, &flag_mask, NULL, flag_xpm); - gc=gdk_gc_new(map->DrawingBuffer); +} - gdk_gc_set_clip_origin(gc,pnt.x, pnt.y-15); - gdk_gc_set_clip_mask(gc,flag_mask); - gdk_draw_pixmap(GTK_WIDGET(map)->window, - gc, - flag, - 0, 0, pnt.x, pnt.y-15, 16, 16); - printf("Segment ID 0x%lx\n", rt_inf->str_inf.str->segid); -#if 0 - printf("Segment Begin 0x%lx, 0x%lx, 0x%x\n", route_info.seg1.xy.x, route_info.seg1.xy.y, route_info.seg1.h); - printf("Segment End 0x%lx, 0x%lx, 0x%x\n", route_info.seg2.xy.x, route_info.seg2.xy.y, route_info.seg2.h); -#endif +struct route_info_handle { + struct route_info *start; + struct route_info *curr; + struct route_info *end; + struct coord *last; + int count; + int iter; + int pos; + int endpos; + int dir; +}; -#if 0 - transform(map, &route_info.seg1.xy, &pnt); gdk_draw_arc(GTK_WIDGET(map)->window, map->gc[GC_BLACK], TRUE, pnt.x-r/2, pnt.y-r/2, r, r, 0, 64*360); - transform(map, &route_info.line1.xy, &pnt); gdk_draw_arc(GTK_WIDGET(map)->window, map->gc[GC_BLACK], TRUE, pnt.x-r/2, pnt.y-r/2, r, r, 0, 64*360); - transform(map, &route_info.seg2.xy, &pnt); gdk_draw_arc(GTK_WIDGET(map)->window, map->gc[GC_BLACK], TRUE, pnt.x-r/2, pnt.y-r/2, r, r, 0, 64*360); - transform(map, &route_info.line2.xy, &pnt); gdk_draw_arc(GTK_WIDGET(map)->window, map->gc[GC_BLACK], TRUE, pnt.x-r/2, pnt.y-r/2, r, r, 0, 64*360); - transform(map, &route_info.pos.xy, &pnt); gdk_draw_arc(GTK_WIDGET(map)->window, map->gc[GC_BLACK], TRUE, pnt.x-r/2, pnt.y-r/2, r, r, 0, 64*360); -#endif - printf("offset=%d\n", rt_inf->offset); - printf("seg1_len=%d\n", rt_inf->seg1_len); - printf("seg2_len=%d\n", rt_inf->seg2_len); - - if (trace) { - start=rt_inf; - count=0; - route_path_free(this); - route_find(this, start, end); - map_redraw(map); - } else { - if (! count) { - start=rt_inf; - count=1; +struct route_info_handle * +route_info_open(struct route_info *start, struct route_info *end, int dir) +{ + struct route_info_handle *ret=g_new0(struct route_info_handle, 1); + + struct route_info *curr; + dbg(1,"enter\n"); + ret->start=start; + ret->end=end; + if (start) + curr=start; + else + curr=end; + ret->endpos=-2; + if (start && end) { + if (start->street->item.map != end->street->item.map || start->street->item.id_hi != end->street->item.id_hi || start->street->item.id_lo != end->street->item.id_lo) { + dbg(1,"return NULL\n"); + return NULL; + } + printf("trivial start=%d end=%d start dir %d end dir %d\n", start->pos, end->pos, start->dir, end->dir); + if (start->pos == end->pos) { + printf("fixme\n"); + start->dir=0; + end->dir=0; + } + if (start->pos > end->pos) { + printf("fixme\n"); + start->dir=-1; + end->dir=1; } - else { - end=rt_inf; - count=0; + if (start->pos < end->pos) { + printf("fixme\n"); + start->dir=1; + end->dir=-1; } + printf("trivial now start=%d end=%d start dir %d end dir %d\n", start->pos, end->pos, start->dir, end->dir); + ret->endpos=end->pos; } -#endif -} -void -route_start(struct route *this, struct container *co) -{ - route_do_start(this, end, start); -} - -void -route_trace(struct container *co) -{ - trace=1-trace; + if (!dir) + dir=curr->dir; + ret->dir=dir; + ret->curr=curr; + ret->pos=curr->pos; + if (dir > 0) { + ret->pos++; + ret->endpos++; + } + dbg(1,"return %p\n",ret); + return ret; } -static void -route_data_free(void *t) +struct coord * +route_info_get(struct route_info_handle *h) { - route_blocklist_free(t); - route_path_free(t); - route_points_free(t); - route_segments_free(t); + struct coord *new; + for (;;) { + new=NULL; + dbg(1,"iter=%d\n", h->iter); + switch(h->iter) { + case 0: + if (h->start) { + new=&h->start->c; + h->iter++; + break; + } else { + h->iter=2; + continue; + } + case 1: + new=&h->start->lp; + h->iter++; + break; + case 2: + dbg(1,"h->pos=%d\n", h->pos); + if (h->dir && h->pos >= 0 && h->pos < h->curr->street->count && (h->end == NULL || h->endpos!=h->pos)) { + new=&h->curr->street->c[h->pos]; + h->pos+=h->dir; + } else { + h->iter++; + continue; + } + break; + case 3: + if (h->end) { + new=&h->end->lp; + h->iter++; + break; + } + break; + case 4: + new=&h->end->c; + h->iter++; + break; + + } + if (new) { + dbg(1,"new=%p (0x%x,0x%x) last=%p\n", new, new->x, new->y, h->last); + if (h->last && new->x == h->last->x && new->y == h->last->y) + continue; + h->last=new; + return new; + } + return NULL; + } } void -route_do_start(struct route *this, struct route_info *rt_start, struct route_info *rt_end) +route_info_close(struct route_info_handle *h) { - int res; - struct route_point *seg1,*seg2,*pos; - struct coord c[2]; - struct timeval tv[4]; - - phrase_route_calc(speech_handle); - route_data_free(this); - gettimeofday(&tv[0], NULL); - c[0]=rt_start->pos.xy; - c[1]=rt_end->pos.xy; - route_build_graph(this,this->map_data,c,2); - gettimeofday(&tv[1], NULL); - seg1=route_point_add(this, &rt_end->seg1, 1); - pos=route_point_add(this, &rt_end->pos, 2); - seg2=route_point_add(this ,&rt_end->seg2, 1); - route_segment_add(this, seg1, pos, rt_end->seg1_len, rt_end->str_inf.str, rt_end->str_inf.strt, rt_end->offset, 0); - route_segment_add(this, seg2, pos, rt_end->seg2_len, rt_end->str_inf.str, rt_end->str_inf.strt, -rt_end->offset, 0); - - printf("flood\n"); - route_flood(this, rt_end); - gettimeofday(&tv[2], NULL); - printf("find\n"); - res=route_find(this, rt_start, rt_end); - printf("ok\n"); - gettimeofday(&tv[3], NULL); - - printf("graph time %ld\n", (tv[1].tv_sec-tv[0].tv_sec)*1000+(tv[1].tv_usec-tv[0].tv_usec)/1000); - printf("flood time %ld\n", (tv[2].tv_sec-tv[1].tv_sec)*1000+(tv[2].tv_usec-tv[1].tv_usec)/1000); - printf("find time %ld\n", (tv[3].tv_sec-tv[2].tv_sec)*1000+(tv[3].tv_usec-tv[2].tv_usec)/1000); - phrase_route_calculated(speech_handle, this); - + g_free(h); } -int -route_destroy(void *t) -{ - struct route *this=t; - - route_data_free(t); - if (this->pos) - g_free(this->pos); - if (this->dst) - g_free(this->dst); - g_free(this); - return 0; -} -struct tm * -route_get_eta(struct route *this) +static int +route_draw_route_info(struct route_info *pos, struct route_info *dst, struct transformation *t, struct displaylist *dsp) { - time_t eta; - - eta=time(NULL)+this->route_time_val; - - return localtime(&eta); + struct route_info_handle *h; + struct coord *c; + struct coord_rect r; + struct item item; + struct point pnt[100]; + int count=0; + + item.id_lo=0; + item.id_hi=0; + item.map=NULL; + item.type=type_street_route; + + dbg(1, "enter\n"); + h=route_info_open(pos, dst, 0); + dbg(1,"h=%p\n", h); + if (! h) { + dbg(1, "return 0\n"); + return 0; + } + if (pos) + dbg(1, "pos=%p pos->dir=%d pos->pos=%d\n", pos, pos->dir, pos->pos); + c=route_info_get(h); + r.lu=*c; + r.rl=*c; + while (c && count < 100) { + dbg(1,"c=%p (0x%x,0x%x)\n", c, c->x, c->y); + transform(t, projection_mg, c, &pnt[count++]); + coord_rect_extend(&r, c); + c=route_info_get(h); + + } + if (count && transform_contains(t, projection_mg, &r)) + display_add(dsp, &item, count, pnt, "Route"); + route_info_close(h); + dbg(1, "return 1\n"); + return 1; } -double -route_get_len(struct route *this) +void +route_draw(struct route *this, struct transformation *t, struct displaylist *dsp) { - return this->route_len_val; + dbg(1,"enter\n"); + if (! this->pos || ! this->dst) + return; + if (! route_draw_route_info(this->pos, this->dst, t, dsp)) { + route_draw_route_info(this->pos, NULL, t, dsp); + route_draw_route_info(NULL, this->dst, t, dsp); + } + dbg(1,"exit\n"); } +#if 0 struct route_crossings * route_crossings_get(struct route *this, struct coord *c) { - struct coord3d c3; - struct route_point *pnt; - struct route_segment *seg; - int crossings=0; - struct route_crossings *ret; - - c3.xy=*c; - c3.h=0; - pnt=route_get_point(this, &c3); - seg=pnt->start; - while (seg) { - crossings++; - seg=seg->start_next; - } - seg=pnt->end; - while (seg) { - crossings++; - seg=seg->end_next; - } - ret=g_malloc(sizeof(struct route_crossings)+crossings*sizeof(struct route_crossing)); - ret->count=crossings; - return ret; + struct route_point *pnt; + struct route_segment *seg; + int crossings=0; + struct route_crossings *ret; + + pnt=route_graph_get_point(this, c); + seg=pnt->start; + while (seg) { + printf("start: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo); + crossings++; + seg=seg->start_next; + } + seg=pnt->end; + while (seg) { + printf("end: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo); + crossings++; + seg=seg->end_next; + } + ret=g_malloc(sizeof(struct route_crossings)+crossings*sizeof(struct route_crossing)); + ret->count=crossings; + return ret; } +#endif diff --git a/src/route.h b/src/route.h index 33fcdb58..6cceae8e 100644 --- a/src/route.h +++ b/src/route.h @@ -1,18 +1,5 @@ -#include "types.h" - -struct route_path_segment { - struct route_path_segment *next; - int country; - s32 segid; - int offset; - int dir; - int time; - int length; - struct coord c[2]; -}; - struct route_crossing { - s32 segid; + long segid; int dir; }; @@ -21,31 +8,46 @@ struct route_crossings { struct route_crossing crossing[0]; }; +/* prototypes */ +struct coord; +struct displaylist; +struct item; +struct map_selection; +struct mapset; struct route; -struct map_data; -struct container; struct route_info; - -struct route *route_new(void); -int route_destroy(void *t); -void route_mapdata_set(struct route *this, struct map_data *mdata); -struct map_data* route_mapdata_get(struct route *this); -void route_display_points(struct route *this, struct container *co); -void route_click(struct route *this, struct container *co, int x, int y); -void route_start(struct route *this, struct container *co); +struct route_info_handle; +struct route_path_handle; +struct route_path_segment; +struct street_data; +struct track; +struct transformation; +struct route *route_new(struct mapset *ms); +struct mapset *route_get_mapset(struct route *this); +struct route_info *route_get_pos(struct route *this); +struct route_info *route_get_dst(struct route *this); +int route_contains(struct route *this, struct item *item); void route_set_position(struct route *this, struct coord *pos); +void route_set_position_from_track(struct route *this, struct track *track); +struct map_selection *route_rect(int order, struct coord *c1, struct coord *c2, int rel, int abs); void route_set_destination(struct route *this, struct coord *dst); -struct coord *route_get_destination(struct route *this); -struct route_path_segment *route_path_get(struct route *, s32 segid); -struct route_path_segment *route_path_get_all(struct route *this); -void route_trace(struct container *co); -struct street_str *route_info_get_street(struct route_info *rt); -struct block_info *route_info_get_block(struct route_info *rt); -struct route_info *route_find_nearest_street(struct map_data *mdata, struct coord *c); -void route_find_point_on_street(struct route_info *rt_inf); -void route_do_start(struct route *this, struct route_info *rt_start, struct route_info *rt_end); -int route_find(struct route *this, struct route_info *rt_start, struct route_info *rt_end); -struct tm *route_get_eta(struct route *this); -double route_get_len(struct route *this); -struct route_crossings *route_crossings_get(struct route *this, struct coord *c); - +struct route_path_handle *route_path_open(struct route *this); +struct route_path_segment *route_path_get_segment(struct route_path_handle *h); +struct coord *route_path_segment_get_start(struct route_path_segment *s); +struct coord *route_path_segment_get_end(struct route_path_segment *s); +struct item *route_path_segment_get_item(struct route_path_segment *s); +int route_path_segment_get_length(struct route_path_segment *s); +int route_path_segment_get_time(struct route_path_segment *s); +void route_path_close(struct route_path_handle *h); +int route_time(struct item *item, int len); +int route_info_length(struct route_info *pos, struct route_info *dst, int dir); +struct street_data *street_get_data(struct item *item); +struct street_data *street_data_dup(struct street_data *orig); +void street_data_free(struct street_data *sd); +void route_info_free(struct route_info *inf); +struct street_data *route_info_street(struct route_info *rinf); +struct coord *route_info_point(struct route_info *rinf, int point); +struct route_info_handle *route_info_open(struct route_info *start, struct route_info *end, int dir); +struct coord *route_info_get(struct route_info_handle *h); +void route_info_close(struct route_info_handle *h); +void route_draw(struct route *this, struct transformation *t, struct displaylist *dsp); diff --git a/src/script/get_map b/src/script/get_map index 20de37d3..7c8ef970 100755 --- a/src/script/get_map +++ b/src/script/get_map @@ -2,4 +2,4 @@ echo "/* XPM */" >map.xpm req="<MapRequest reqVer='100' format='jpeg' visibleRoutes='111111111' colorDepth='4'><Rect l='0' t='0' r='$1' b='$2'></Rect><Rect l='$3' t='$4' r='$5' b='$6'></Rect></MapRequest>" perl -e 'print (pack("a20",length($ARGV[0]))) ; print $ARGV[0]' "$req" | netcat localhost 10371 | dd bs=20 skip=1 2>/dev/null | tail +2 >>map.xpm - +xv map.xpm & diff --git a/src/search.c b/src/search.c index 0d2f17be..8cb2a8d5 100644 --- a/src/search.c +++ b/src/search.c @@ -1,442 +1,300 @@ #include <glib.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include "search.h" +#include "debug.h" +#include "mapset.h" +#include "attr.h" #include "coord.h" -#include "country.h" -#include "town.h" -#include "street.h" -#include "street_name.h" - +#include "item.h" +#include "search.h" -struct search { - struct map_data *map_data; - char *country; - GHashTable *country_hash; - char *postal; - char *town; - GHashTable *town_hash; - char *district; - GHashTable *district_hash; - char *street; - GHashTable *street_hash; - char *number; - int number_low, number_high; - int (*func)(struct search_destination *dest, void *user_data); - void *user_data; +struct search_list_level { + struct mapset *ms; + struct item *parent; + struct attr attr; + int partial; + struct mapset_search *search; + GHashTable *hash; + GList *list,*curr,*last; + int complete; + }; -struct dest_town { - int country; - int assoc; - char *name; - char postal_code[16]; - struct town town; +struct search_list { + struct mapset *ms; + int level; + struct search_list_level levels[4]; + struct search_list_result result; }; -static GHashTable * -search_country_new(void) -{ - return g_hash_table_new_full(NULL, NULL, NULL, g_free); -} - -static int -search_country_add(struct country *cou, void *data) -{ - struct search *search=data; - struct country *cou2; - - void *first; - first=g_hash_table_lookup(search->country_hash, (void *)(cou->id)); - if (! first) { - cou2=g_new(struct country, 1); - *cou2=*cou; - g_hash_table_insert(search->country_hash, (void *)(cou->id), cou2); - } - return 0; -} - -static void -search_country_show(gpointer key, gpointer value, gpointer user_data) -{ - struct country *cou=value; - struct search *search=(struct search *)user_data; - struct search_destination dest; - - memset(&dest, 0, sizeof(dest)); - dest.country=cou; - dest.country_name=cou->name; - dest.country_car=cou->car; - dest.country_iso2=cou->iso2; - dest.country_iso3=cou->iso3; - (*search->func)(&dest, search->user_data); -} - static guint -search_town_hash(gconstpointer key) +search_item_hash_hash(gconstpointer key) { - const struct dest_town *hash=key; - gconstpointer hashkey=(gconstpointer)(hash->country^hash->assoc); - return g_direct_hash(hashkey); + const struct item *itm=key; + gconstpointer hashkey=(gconstpointer)(itm->id_hi^itm->id_lo); + return g_direct_hash(hashkey); } static gboolean -search_town_equal(gconstpointer a, gconstpointer b) +search_item_hash_equal(gconstpointer a, gconstpointer b) { - const struct dest_town *t_a=a; - const struct dest_town *t_b=b; - if (t_a->assoc == t_b->assoc && t_a->country == t_b->country) { - if (t_a->name && t_b->name && strcmp(t_a->name, t_b->name)) - return FALSE; + const struct item *itm_a=a; + const struct item *itm_b=b; + if (item_is_equal_id(*itm_a, *itm_b)) return TRUE; - } return FALSE; } - -static GHashTable * -search_town_new(void) +struct search_list * +search_list_new(struct mapset *ms) { - return g_hash_table_new_full(search_town_hash, search_town_equal, NULL, g_free); -} + struct search_list *ret; + ret=g_new0(struct search_list, 1); + ret->ms=ms; + + return ret; +} -static int -search_town_add(struct town *town, void *data) +static void search_list_search_free(struct search_list *sl, int level); +void +search_list_search(struct search_list *this_, struct attr *search_attr, int partial) { - struct search *search=data; - struct dest_town *first; - - struct dest_town cmp; - char *zip1, *zip2; - - if (town->id == 0x1d546b7e) { - printf("found\n"); + int level=-1; + struct search_list_level *le; + switch(search_attr->type) { + case attr_country_all: + level=0; + break; + case attr_town_name: + level=1; + break; + case attr_street_name: + level=2; + break; + default: + break; } - cmp.country=town->country; - cmp.assoc=town->street_assoc; - cmp.name=town->name; - first=g_hash_table_lookup(search->town_hash, &cmp); - if (! first) { - first=g_new(struct dest_town, 1); - first->country=cmp.country; - first->assoc=cmp.assoc; - strcpy(first->postal_code, town->postal_code2); - first->name=town->name; - first->town=*town; - g_hash_table_insert(search->town_hash, first, first); - } else { - zip1=town->postal_code2; - zip2=first->postal_code; - while (*zip1 && *zip2) { - if (*zip1 != *zip2) { - while (*zip2) { - *zip2++='.'; - } - break; - } - zip1++; - zip2++; + dbg(0,"level=%d\n", level); + if (level != -1) { + this_->level=level; + le=&this_->levels[level]; + le->attr=*search_attr; + le->attr.u.str=g_strdup(search_attr->u.str); + search_list_search_free(this_, level); + le->partial=partial; + if (level > 0) { + le=&this_->levels[level-1]; + le->curr=le->list; } + dbg(1,"le=%p partial=%d\n", le, partial); } - cmp.name=NULL; - cmp.assoc=town->id; - first=g_hash_table_lookup(search->district_hash, &cmp); - if (! first) { - first=g_new(struct dest_town, 1); - first->country=cmp.country; - first->assoc=cmp.assoc; - first->name=NULL; - first->town=*town; - g_hash_table_insert(search->district_hash, first, first); - } - return 0; } -static void -search_town_search(gpointer key, gpointer value, gpointer user_data) +static struct search_list_country * +search_list_country_new(struct item *item) { - struct country *cou=value; - struct search *search=user_data; - - town_search_by_name(search->map_data, cou->id, search->town, 1, search_town_add, search); + struct search_list_country *ret=g_new0(struct search_list_country, 1); + struct attr attr; + + ret->item=*item; + if (item_attr_get(item, attr_country_car, &attr)) + ret->car=g_strdup(attr.u.str); + if (item_attr_get(item, attr_country_iso2, &attr)) + ret->iso2=g_strdup(attr.u.str); + if (item_attr_get(item, attr_country_iso3, &attr)) + ret->iso3=g_strdup(attr.u.str); + if (item_attr_get(item, attr_country_name, &attr)) + ret->name=g_strdup(attr.u.str); + return ret; } static void -search_town_set(const struct dest_town *town, struct search_destination *dest, int full) +search_list_country_destroy(struct search_list_country *this_) { - char country[32]; - struct country *cou; - if ((cou=country_get_by_id(town->country))) { - dest->country=cou; - dest->country_name=cou->name; - dest->country_car=cou->car; - dest->country_iso2=cou->iso2; - dest->country_iso3=cou->iso3; - } else { - sprintf(country,"(%d)", town->country); - dest->country=NULL; - dest->country_car=country; - } - if (full) { - dest->town_postal=(char *)(town->town.postal_code2); - dest->town_name=g_convert(town->town.name,-1,"utf-8","iso8859-1",NULL,NULL,NULL); - if (town->town.district[0]) - dest->district=g_convert(town->town.district,-1,"utf-8","iso8859-1",NULL,NULL,NULL); - else - dest->district=NULL; - } else { - dest->town_postal=(char *)(town->postal_code); - dest->town_name=g_convert(town->name,-1,"utf-8","iso8859-1",NULL,NULL,NULL); - } + g_free(this_->car); + g_free(this_->iso2); + g_free(this_->iso3); + g_free(this_->name); + g_free(this_); } - -static void -search_town_show(gpointer key, gpointer value, gpointer user_data) +static struct search_list_town * +search_list_town_new(struct item *item) { - struct dest_town *town=value; - struct search *search=user_data; - struct search_destination dest; - - memset(&dest, 0, sizeof(dest)); - dest.town=&town->town; - dest.street_name=NULL; - dest.c=town->town.c; - search_town_set(town, &dest, 0); + struct search_list_town *ret=g_new0(struct search_list_town, 1); + struct attr attr; + struct coord c; - (*search->func)(&dest, search->user_data); -} - - -static GHashTable * -search_street_new(void) -{ - return g_hash_table_new_full(NULL, NULL, NULL, g_free); + ret->itemt=*item; + if (item_attr_get(item, attr_town_streets_item, &attr)) { + dbg(1,"town_assoc 0x%x 0x%x\n", attr.u.item->id_hi, attr.u.item->id_lo); + ret->item=*attr.u.item; + } + else + ret->item=*item; + if (item_attr_get(item, attr_town_name, &attr)) + ret->name=map_convert_string(item->map,attr.u.str); + if (item_attr_get(item, attr_town_postal, &attr)) + ret->postal=map_convert_string(item->map,attr.u.str); + if (item_coord_get(item, &c, 1)) { + ret->c=g_new(struct coord, 1); + *(ret->c)=c; + } + return ret; } - -static int -search_street_add(struct street_name *name, void *data) +static void +search_list_town_destroy(struct search_list_town *this_) { - struct search *search=data; - struct street_name *name2; - - name2=g_new(struct street_name, 1); - *name2=*name; - g_hash_table_insert(search->street_hash, name2, name2); - return 0; + map_convert_free(this_->name); + map_convert_free(this_->postal); + g_free(this_); } -static int -number_partial(int search, int ref, int ext) +static struct search_list_street * +search_list_street_new(struct item *item) { - int max=1; - - printf("number_partial(%d,%d,%d)", search, ref, ext); - if (ref >= 10) - max=10; - if (ref >= 100) - max=100; - if (ref >= 1000) - max=1000; - while (search < max) { - search*=10; - search+=ext; + struct search_list_street *ret=g_new0(struct search_list_street, 1); + struct attr attr; + struct coord c; + + ret->item=*item; + if (item_attr_get(item, attr_street_name, &attr)) + ret->name=map_convert_string(item->map, attr.u.str); + if (item_coord_get(item, &c, 1)) { + ret->c=g_new(struct coord, 1); + *(ret->c)=c; } - printf("max=%d result=%d\n", max, search); - return search; + return ret; } -static int -check_number(int low, int high, int s_low, int s_high) +static void +search_list_street_destroy(struct search_list_street *this_) { - int debug=0; - - if (debug) - printf("check_number(%d,%d,%d,%d)\n", low, high, s_low, s_high); - if (low <= s_high && high >= s_low) - return 1; - if (s_low == s_high) { - if (low <= number_partial(s_high, high, 9) && high >= number_partial(s_low, low, 0)) - return 1; - } - if (debug) - printf("return 0\n"); - return 0; + map_convert_free(this_->name); + g_free(this_); } + static void -search_street_show_common(gpointer key, gpointer value, gpointer user_data, int number) +search_list_result_destroy(int level, void *p) { - struct street_name *name=value; - struct search *search=user_data; - char *utf8; - struct dest_town cmp; - struct dest_town *town; - char buffer[32]; - struct street_name_info info; - struct street_name_number_info num_info; - struct search_destination dest; - int debug=0; - - memset(&dest, 0, sizeof(dest)); - name->tmp_len=name->aux_len; - name->tmp_data=name->aux_data; - while (street_name_get_info(&info, name)) { - cmp.country=info.country; - cmp.assoc=info.dist; - cmp.name=NULL; - town=g_hash_table_lookup(search->district_hash, &cmp); - if (debug) - printf("town=%p\n", town); - if (town) { - search_town_set(town, &dest, 1); - utf8=g_convert(name->name2,-1,"utf-8","iso8859-1",NULL,NULL,NULL); - dest.street_name=utf8; - if (number) { - info.tmp_len=info.aux_len; - info.tmp_data=info.aux_data; - while (street_name_get_number_info(&num_info, &info)) { - dest.town=&town->town; - dest.street=name; - dest.c=num_info.c; - if (check_number(num_info.first, num_info.last, search->number_low, search->number_high)) { - if (num_info.first == num_info.last) - sprintf(buffer,"%d",num_info.first); - else - sprintf(buffer,"%d-%d",num_info.first,num_info.last); - dest.street_number=buffer; - (*search->func)(&dest, search->user_data); - } - } - } else { - dest.town=&town->town; - dest.street=name; - dest.c=info.c; - (*search->func)(&dest, search->user_data); - } - g_free(utf8); - } else { - printf("Town for '%s' not found\n", name->name2); - } + switch (level) { + case 0: + search_list_country_destroy(p); + break; + case 1: + search_list_town_destroy(p); + break; + case 2: + search_list_street_destroy(p); + break; } } static void -search_street_show(gpointer key, gpointer value, gpointer user_data) +search_list_search_free(struct search_list *sl, int level) { - search_street_show_common(key, value, user_data, 0); -} + struct search_list_level *le=&sl->levels[level]; + GList *next,*curr; + if (le->search) { + mapset_search_destroy(le->search); + le->search=NULL; + } + if (le->search) { + g_hash_table_destroy(le->hash); + } + curr=le->list; + while (curr) { + search_list_result_destroy(level, curr->data); + next=g_list_next(curr); + curr=next; + } + g_list_free(le->list); + le->list=NULL; + le->curr=NULL; + le->last=NULL; + le->complete=0; -static void -search_street_show_number(gpointer key, gpointer value, gpointer user_data) -{ - search_street_show_common(key, value, user_data, 1); } -static void -search_street_search(gpointer key, gpointer value, gpointer user_data) +static int +search_add_result(struct search_list_level *le, void *p) { - const struct dest_town *town=value; - struct search *search=user_data; - street_name_search(search->map_data, town->country, town->assoc, search->street, 1, search_street_add, search); + if (! g_hash_table_lookup(le->hash, p)) { + g_hash_table_insert(le->hash, p, (void *)1); + le->list=g_list_append(le->list, p); + return 1; + } + return 0; } - - -void search_update(struct search *search, enum search_param what, char *val) +struct search_list_result * +search_list_get_result(struct search_list *this_) { - char *dash; - - if (what == search_country) { - if (search->country_hash) g_hash_table_destroy(search->country_hash); - search->country_hash=NULL; - } - if (what == search_country || what == search_town) { - if (search->town_hash) g_hash_table_destroy(search->town_hash); - if (search->district_hash) g_hash_table_destroy(search->district_hash); - search->town_hash=NULL; - search->district_hash=NULL; - } - - if (what == search_country || what == search_town || what == search_street) { - if (search->street_hash) g_hash_table_destroy(search->street_hash); - search->street_hash=NULL; - } - - if (what == search_country) { - g_free(search->country); - search->country=g_strdup(val); - if (val) { - search->country_hash=search_country_new(); - country_search_by_name(val, 1, search_country_add, search); - country_search_by_car(val, 1, search_country_add, search); - country_search_by_iso2(val, 1, search_country_add, search); - country_search_by_iso3(val, 1, search_country_add, search); - g_hash_table_foreach(search->country_hash, search_country_show, search); - } - } - if (what == search_town) { - g_free(search->town); - search->town=g_strdup(val); - if (val) { - search->town_hash=search_town_new(); - search->district_hash=search_town_new(); - g_hash_table_foreach(search->country_hash, search_town_search, search); - g_hash_table_foreach(search->town_hash, search_town_show, search); - } - } - if (what == search_street) { - g_free(search->street); - search->street=g_strdup(val); - if (val) { - search->street_hash=search_street_new(); - g_hash_table_foreach(search->town_hash, search_street_search, search); - g_hash_table_foreach(search->street_hash, search_street_show, search); - } - } - if (what == search_number) { - g_free(search->number); - search->number=g_strdup(val); - if (val) { - char buffer[strlen(val)+1]; - strcpy(buffer, val); - dash=index(buffer,'-'); - if (dash) { - *dash++=0; - search->number_low=atoi(buffer); - if (strlen(val)) - search->number_high=atoi(dash); - else - search->number_high=10000; - } else { - if (!strlen(val)) { - search->number_low=0; - search->number_high=10000; - } else { - search->number_low=atoi(val); - search->number_high=atoi(val); - } + struct search_list_level *le,*leu; + struct item *item; + int level=this_->level; + + dbg(1,"enter\n"); + le=&this_->levels[level]; + dbg(1,"le=%p\n", le); + while(! le->complete) { + dbg(1,"le->search=%p\n", le->search); + if (! le->search) { + dbg(1,"partial=%d\n", le->partial); + if (! level) + le->parent=NULL; + else { + leu=&this_->levels[level-1]; + le->parent=leu->curr->data; + leu->last=leu->curr; + leu->curr=g_list_next(leu->curr); } - g_hash_table_foreach(search->street_hash, search_street_show_number, search); + le->search=mapset_search_new(this_->ms, le->parent, &le->attr, le->partial); + le->hash=g_hash_table_new_full(search_item_hash_hash, search_item_hash_equal, g_free, NULL); } + dbg(1,"le->search=%p\n", le->search); + item=mapset_search_get_item(le->search); + dbg(1,"item=%p\n", item); + if (item) { + void *p=NULL; + this_->result.country=NULL; + this_->result.town=NULL; + this_->result.street=NULL; + this_->result.c=NULL; + switch (level) { + case 0: + p=search_list_country_new(item); + this_->result.country=p; + break; + case 1: + p=search_list_town_new(item); + this_->result.country=this_->levels[0].last->data; + this_->result.town=p; + this_->result.c=this_->result.town->c; + break; + case 2: + p=search_list_street_new(item); + this_->result.country=this_->levels[0].last->data; + this_->result.town=this_->levels[1].last->data; + this_->result.street=p; + this_->result.c=this_->result.street->c; + break; + } + if (p) { + if (search_add_result(le, p)) + return &this_->result; + else + search_list_result_destroy(level, p); + } + } else + le->complete=1; } + return NULL; } -struct search * -search_new(struct map_data *mdat, char *country, char *postal, char *town, char *district, char *street, char *number, int (*func)(struct search_destination *dest, void *user_data), void *user_data) +void +search_list_destroy(struct search_list *this_) { - struct search *this=g_new0(struct search,1); - this->map_data=mdat; - this->country=g_strdup(country); - this->postal=g_strdup(postal); - this->town=g_strdup(town); - this->district=g_strdup(district); - this->street=g_strdup(street); - this->number=g_strdup(number); - this->func=func; - this->user_data=user_data; - return this; + g_free(this_); } diff --git a/src/search.h b/src/search.h index 88f38826..0a09494e 100644 --- a/src/search.h +++ b/src/search.h @@ -1,30 +1,45 @@ -enum search_param { - search_country, - search_postal, - search_town, - search_district, - search_street, - search_number +#ifdef __cplusplus +extern "C" { +#endif +struct search_list_country { + struct item item; + char *car; + char *iso2; + char *iso3; + char *name; }; -struct search_destination { - char *country_name; - char *country_car; - char *country_iso2; - char *country_iso3; - char *town_postal; - char *town_name; - char *district; - char *street_name; - char *street_number; - struct country *country; - struct town *town; - struct street_name *street; +struct search_list_town { + struct item item; + struct item itemt; struct coord *c; + char *postal; + char *name; }; -struct search; -struct map_data; +struct search_list_street { + struct item item; + struct coord *c; + char *name; +}; + +struct search_list_result { + struct coord *c; + struct search_list_country *country; + struct search_list_town *town; + struct search_list_street *street; +}; -void search_update(struct search *search, enum search_param what, char *val); -struct search *search_new(struct map_data *mdat, char *country, char *postal, char *town, char *district, char *street, char *number, int (*func)(struct search_destination *dest, void *user_data), void *user_data); +/* prototypes */ +struct attr; +struct mapset; +struct search_list; +struct search_list_result; +struct search_list *search_list_new(struct mapset *ms); +void search_list_search(struct search_list *this_, struct attr *search_attr, int partial); +struct search_list_result *search_list_get_result(struct search_list *this_); +void search_list_destroy(struct search_list *this_); +/* end of prototypes */ +#ifdef __cplusplus +} +#endif diff --git a/src/statusbar.h b/src/statusbar.h index 1b9092c9..1411ef76 100644 --- a/src/statusbar.h +++ b/src/statusbar.h @@ -1,10 +1,18 @@ struct route; -struct statusbar_gui; +struct statusbar_priv; +struct point; +struct transformation; + +struct statusbar_methods { + void (*statusbar_destroy)(struct statusbar_priv *this); + void (*statusbar_mouse_update)(struct statusbar_priv *this, struct transformation *tr, struct point *p); + void (*statusbar_route_update)(struct statusbar_priv *this, struct route *route); + void (*statusbar_gps_update)(struct statusbar_priv *this, int sats, int qual, double lng, double lat, double height, double direction, double speed); +}; struct statusbar { - void (*statusbar_destroy)(struct statusbar *this); - void (*statusbar_mouse_update)(struct statusbar *this, struct transformation *tr, struct point *p); - void (*statusbar_route_update)(struct statusbar *this, struct route *route); - void (*statusbar_gps_update)(struct statusbar *this, int sats, int qual, double lng, double lat, double height, double direction, double speed); - struct statusbar_gui *gui; + struct statusbar_methods meth; + struct statusbar_priv *priv; }; + +/* prototypes */ diff --git a/src/street.c b/src/street.c index 8633224a..1880e12c 100644 --- a/src/street.c +++ b/src/street.c @@ -568,3 +568,49 @@ street_bti_get_param(struct segment *seg, struct param_list *param, int count) return i-count; } + +struct street_data * +street_get_data (struct item *item) +{ + struct coord c[1000]; + int count=0; + struct street_data *ret; + struct attr attr; + + while (count < 1000) { + if (!item_coord_get(item, &c[count], 1)) + break; + count++; + } + g_assert(count < 1000); + ret=g_malloc(sizeof(struct street_data)+count*sizeof(struct coord)); + ret->item=*item; + ret->count=count; + if (item_attr_get(item, attr_limit, &attr)) + ret->limit=attr.u.num; + else + ret->limit=0; + memcpy(ret->c, c, count*sizeof(struct coord)); + + return ret; + +} + +struct street_data * +street_data_dup(struct street_data *orig) +{ + struct street_data *ret; + int size=sizeof(struct street_data)+orig->count*sizeof(struct coord); + + ret=g_malloc(size); + memcpy(ret, orig, size); + + return ret; +} + +void +street_data_free(struct street_data *sd) +{ + g_free(sd); +} + diff --git a/src/street_name.c b/src/street_name.c index cecc62a6..1e8da63a 100644 --- a/src/street_name.c +++ b/src/street_name.c @@ -54,7 +54,7 @@ struct street_search_priv { static int street_name_compare(struct street_name_index *i1, struct street_name_index *i2, int partial) { - unsigned char c1_u,c2_u; + char c1_u,c2_u; int ret=0; int debug=0; @@ -122,7 +122,7 @@ street_name_tree_process(int version, int leaf, unsigned char **s2, struct map_d blk_off=(struct block_offset *)(*s2); if (debug) - printf("0x%x\n", get_u32(s2)); + printf("0x%lx\n", get_u32(s2)); else get_u32(s2); struct street_name_index *i1=priv_data->search; @@ -132,7 +132,7 @@ street_name_tree_process(int version, int leaf, unsigned char **s2, struct map_d printf("Country %d %d\n",i1->country, i2->country); printf("Town_Assoc 0x%lx 0x%lx\n",i1->town_assoc, i2->town_assoc); printf("Name '%s' '%s'\n",i1->name, i2->name); - printf("Leaf Data 0x%x 0x%x %ld\n", blk_off->offset, blk_off->block, sizeof(*blk_off)); + printf("Leaf Data 0x%x 0x%x %d\n", blk_off->offset, blk_off->block, sizeof(*blk_off)); } *s2+=sizeof(*i2)+strlen(i2->name)+1; ret=street_name_compare(i1, i2, priv_data->partial); diff --git a/src/track.c b/src/track.c index 2f861650..295e2ab1 100644 --- a/src/track.c +++ b/src/track.c @@ -1,3 +1,14 @@ +#include <glib.h> +#include "track.h" +#include "debug.h" +#include "transform.h" +#include "coord.h" +#include "item.h" +#include "route.h" +#include "map.h" +#include "mapset.h" + +#if 0 #include <stdio.h> #include <glib.h> #include "coord.h" @@ -6,89 +17,116 @@ #include "profile.h" #include "track.h" +#endif + +struct street_data { + struct item item; + int count; + int limit; + struct coord c[0]; +}; + + struct track_line { + struct street_data *street; +#if 0 long segid; int linenum; struct coord c[2]; struct coord lpnt; int value; - int angle; int dir; +#endif struct track_line *next; + int angle[0]; }; + struct track { - struct map_data *ma; + struct mapset *ms; +#if 0 struct transformation t; +#endif struct coord last_updated; struct track_line *lines; +#if 0 struct track_line **last_ptr; +#endif + struct track_line *curr_line; + int pos; struct coord curr[2]; struct coord last_in; struct coord last_out; }; -int angle_factor=5; + +int angle_factor=10; int connected_pref=-10; int nostop_pref=10; -struct track_line **last; +struct coord * +track_get_pos(struct track *tr) +{ + return &tr->last_out; +} -static void -tst_callback(struct street_str *str, void *handle, void *data) +int +track_get_segment_pos(struct track *tr) { - struct coord c[2]; - int visible=0,count=0; - struct track *tr=data; - struct track_line *lines; - int debug_segid=0; - int debug=0; + return tr->pos; +} - /* printf("tst_callback id=0x%x ",str->segid < 0 ? -str->segid : str->segid); */ - if (street_coord_handle_get(handle, &c[0], 1)) { - if (str->segid == debug_segid) - printf("0x%lx,0x%lx ", c->x, c->y); - c[1]=c[0]; - while (street_coord_handle_get(handle, &c[0], 1)) { - if (is_line_visible(&tr->t, c)) { - visible=1; - } - c[1]=c[0]; - count++; - if (str->segid == debug_segid) - printf("0x%lx,0x%lx ", c->x, c->y); - } - } - if (visible) { - lines=g_new(struct track_line, count); - street_coord_handle_rewind(handle); - street_coord_handle_get(handle, &c[0], 1); - count=0; - while (street_coord_handle_get(handle, &c[1], 1)) { - *(tr->last_ptr)=lines; - tr->last_ptr=&lines->next; - lines->segid=str->segid; - lines->linenum=count; - lines->c[0]=c[0]; - lines->c[1]=c[1]; - lines->angle=transform_get_angle(c,0); - lines->next=NULL; - lines++; - count++; - c[0]=c[1]; - } - if (debug) - printf("%d lines\n", count); - } - /* printf("\n"); */ +struct street_data * +track_get_street_data(struct track *tr) +{ + return tr->curr_line->street; +} + +static void +track_get_angles(struct track_line *tl) +{ + int i; + struct street_data *sd=tl->street; + for (i = 0 ; i < sd->count-1 ; i++) + tl->angle[i]=transform_get_angle_delta(&sd->c[i], &sd->c[i+1], 0); } static void -track_doupdate_lines(struct track *tr, struct coord *c) +track_doupdate_lines(struct track *tr, struct coord *cc) { + int max_dist=1000; + struct map_selection *sel=route_rect(18, cc, cc, 0, max_dist); + struct mapset_handle *h; + struct map *m; + struct map_rect *mr; + struct item *item; + struct street_data *street; + struct track_line *tl; + struct coord c; + + dbg(0,"enter\n"); + h=mapset_open(tr->ms); + while ((m=mapset_next(h,1))) { + mr=map_rect_new(m, sel); + while ((item=map_rect_get_item(mr))) { + if (item->type >= type_street_0 && item->type <= type_ferry) { + street=street_get_data(item); + tl=g_malloc(sizeof(struct track_line)+(street->count-1)*sizeof(int)); + tl->street=street; + track_get_angles(tl); + tl->next=tr->lines; + tr->lines=tl; + } else + while (item_coord_get(item, &c, 1)); + } + map_rect_destroy(mr); + } + mapset_close(h); + dbg(0, "exit\n"); +#if 0 struct transformation t; @@ -100,20 +138,20 @@ track_doupdate_lines(struct track *tr, struct coord *c) profile_timer(NULL); street_get_block(tr->ma,&t,tst_callback,tr); profile_timer("end"); +#endif } + static void track_free_lines(struct track *tr) { struct track_line *tl=tr->lines,*next; -#ifdef DEBUG - printf("track_free_lines(tr=%p)\n", tr); -#endif + dbg(0,"enter(tr=%p)\n", tr); + while (tl) { next=tl->next; - if (! tl->linenum) { - g_free(tl); - } + street_data_free(tl->street); + g_free(tl); tl=next; } tr->lines=NULL; @@ -156,71 +194,77 @@ track_is_connected(struct coord *c1, struct coord *c2) return 0; } -void +int track_update(struct track *tr, struct coord *c, int angle) { - struct track_line *t,*tm; + struct track_line *t; + int i,value,min=0; + struct coord lpnt; +#if 0 int min,dist; int debug=0; +#endif + dbg(1,"enter(%p,%p,%d)\n", tr, c, angle); + dbg(1,"c=0x%x,0x%x\n", c->x, c->y); if (c->x == tr->last_in.x && c->y == tr->last_in.y) { *c=tr->last_out; - return; + return 0; } - if (transform_distance_sq(&tr->last_updated, c) > 250000 || !tr->lines) { - printf("update\n"); + tr->last_in=*c; + if (!tr->lines || transform_distance_sq(&tr->last_updated, c) > 250000) { + dbg(1, "update\n"); track_free_lines(tr); track_doupdate_lines(tr, c); tr->last_updated=*c; + dbg(1,"update end\n"); } - profile_timer(NULL); t=tr->lines; - g_assert(t != NULL); - - if (debug) printf("0x%lx,0x%lx (%d deg)\n", c->x, c->y, angle); + if (! t) + return 0; + tr->curr_line=NULL; while (t) { - if (debug) printf("0x%lx 0x%lx,0x%lx - 0x%lx,0x%lx (%d deg) ", -t->segid, t->c[0].x, t->c[0].y, t->c[1].x, t->c[1].y, t->angle); - t->value=transform_distance_line_sq(&t->c[0], &t->c[1], c, &t->lpnt); - if (t->value < INT_MAX/2) - t->value += track_angle_delta(angle, t->angle, 0)*angle_factor; - if (track_is_connected(tr->curr, t->c)) - t->value += connected_pref; - if (t->lpnt.x == tr->last_out.x && t->lpnt.y == tr->last_out.y) - t->value += nostop_pref; - if (debug) printf(" %d\n", t->value); - t=t->next; - } - t=tr->lines; - tm=t; - min=t->value; - while (t) { - if (t->value < min) { - min=t->value; - tm=t; + struct street_data *sd=t->street; + for (i = 0; i < sd->count-1 ; i++) { + value=transform_distance_line_sq(&sd->c[i], &sd->c[i+1], c, &lpnt); + if (value < INT_MAX/2) + value += track_angle_delta(angle, t->angle[i], 0)*angle_factor; + if (track_is_connected(tr->curr, &sd->c[i])) + value += connected_pref; + if (lpnt.x == tr->last_out.x && lpnt.y == tr->last_out.y) + value += nostop_pref; + if (! tr->curr_line || value < min) { + tr->curr_line=t; + tr->pos=i; + tr->curr[0]=sd->c[i]; + tr->curr[1]=sd->c[i+1]; + dbg(1,"lpnt.x=0x%x,lpnt.y=0x%x %d+%d+%d+%d=%d\n", lpnt.x, lpnt.y, + transform_distance_line_sq(&sd->c[i], &sd->c[i+1], c, &lpnt), + track_angle_delta(angle, t->angle[i], 0)*angle_factor, + track_is_connected(tr->curr, &sd->c[i]) ? connected_pref : 0, + lpnt.x == tr->last_out.x && lpnt.y == tr->last_out.y ? nostop_pref : 0, + value + ); + tr->last_out=lpnt; + min=value; + } } t=t->next; } - dist=transform_distance_sq(&tm->lpnt, c); - if (debug) printf("dist=%d id=0x%lx\n", dist, tm->segid); - *c=tm->lpnt; - tr->curr[0]=tm->c[0]; - tr->curr[1]=tm->c[1]; - tr->last_out=tm->lpnt; - - // printf("pos 0x%lx,0x%lx value %d dist %d angle %d vs %d (%d)\n", c->x, c->y, tm->value, dist, angle, tm->angle, track_angle_delta(angle, tm->angle, 0)); - g_assert(dist < 10000); -#if 0 - profile_timer("track_update end"); -#endif - + dbg(0,"tr->curr_line=%p\n", tr->curr_line); + if (!tr->curr_line) + return 0; + dbg(0,"found 0x%x,0x%x\n", tr->last_out.x, tr->last_out.y); + *c=tr->last_out; + return 1; } struct track * -track_new(struct map_data *ma) +track_new(struct mapset *ms) { struct track *this=g_new0(struct track, 1); - this->ma=ma; + this->ms=ms; return this; } diff --git a/src/track.h b/src/track.h index 2b435e0f..90073a5c 100644 --- a/src/track.h +++ b/src/track.h @@ -1,5 +1,11 @@ +/* prototypes */ +struct coord; +struct mapset; +struct street_data; struct track; - -void track_update(struct track *tr, struct coord *c, int angle); -struct track * track_new(struct map_data *ma); +struct coord *track_get_pos(struct track *tr); +int track_get_segment_pos(struct track *tr); +struct street_data *track_get_street_data(struct track *tr); +int track_update(struct track *tr, struct coord *c, int angle); +struct track *track_new(struct mapset *ms); void track_destroy(struct track *tr); diff --git a/src/transform.c b/src/transform.c index 859e0e5a..abf9c35f 100644 --- a/src/transform.c +++ b/src/transform.c @@ -3,18 +3,93 @@ #include <math.h> #include <limits.h> #include <glib.h> +#include "config.h" #include "coord.h" +#include "debug.h" #include "transform.h" +#include "projection.h" +#include "point.h" + +struct transformation { + int width; /* Height of destination rectangle */ + int height; /* Width of destination rectangle */ + long scale; /* Scale factor */ + int angle; /* Rotation angle */ + double cos_val,sin_val; /* cos and sin of rotation angle */ + enum projection pro; + struct coord_rect r; /* Source rectangle */ + struct coord center; /* Center of source rectangle */ +}; + +struct transformation * +transform_new(void) +{ + struct transformation *this_; + + this_=g_new0(struct transformation, 1); + + return this_; +} + +void +transform_to_geo(enum projection pro, struct coord *c, struct coord_geo *g) +{ + double f; + + switch (pro) { + case projection_mg: + g->lng=c->x/6371000.0/M_PI*180; + g->lat=atan(exp(c->y/6371000.0))/M_PI*360-90; + break; + case projection_garmin: + f=360.0/(1<<24); + g->lng=c->x*f; + g->lat=c->y*f; + break; + default: + break; + } +} + +void +transform_from_geo(enum projection pro, struct coord_geo *g, struct coord *c) +{ + double f; + + switch (pro) { + case projection_mg: + c->x=g->lng*6371000.0*M_PI/180; + c->y=log(tan(M_PI_4+g->lat*M_PI/360))*6371000.0; + break; + case projection_garmin: + f=360.0/(1<<24); + c->x=g->lng/f; + c->y=g->lat/f; + break; + default: + break; + } +} int -transform(struct transformation *t, struct coord *c, struct point *p) +transform(struct transformation *t, enum projection pro, struct coord *c, struct point *p) { + struct coord c1; +#ifdef AVOID_FLOAT + int xc,yc; +#else double xc,yc; - int ret=0; +#endif + int ret; + if (pro != t->pro) { + struct coord_geo g; + transform_to_geo(pro, c, &g); + transform_from_geo(t->pro, &g, &c1); + c=&c1; + } xc=c->x; yc=c->y; - if (xc >= t->rect[0].x && xc <= t->rect[1].x && yc >= t->rect[1].y && yc <= t->rect[0].y) - ret=1; + ret=coord_rect_contains(&t->r, c); xc-=t->center.x; yc-=t->center.y; yc=-yc; @@ -25,8 +100,13 @@ transform(struct transformation *t, struct coord *c, struct point *p) xc=xcn; yc=ycn; } +#ifdef AVOID_FLOAT xc=xc*16.0/(double)(t->scale); yc=yc*16.0/(double)(t->scale); +#else + xc=xc*16/t->scale; + yc=yc*16/t->scale; +#endif #if 0 { double zc=yc; @@ -77,6 +157,17 @@ transform_reverse(struct transformation *t, struct point *p, struct coord *c) c->y=t->center.y+yc; } +enum projection +transform_get_projection(struct transformation *this_) +{ + return this_->pro; +} + +void +transform_set_projection(struct transformation *this_, enum projection pro) +{ + this_->pro=pro; +} static int min4(int v1,int v2, int v3, int v4) @@ -105,6 +196,45 @@ max4(int v1,int v2, int v3, int v4) } void +transform_rect(struct transformation *this_, enum projection pro, struct coord_rect *r) +{ + struct coord_geo g; + if (0 && this_->pro == pro) { + *r=this_->r; + } else { + transform_to_geo(this_->pro, &this_->r.lu, &g); + transform_from_geo(pro, &g, &r->lu); + dbg(1,"%f,%f", g.lat, g.lng); + transform_to_geo(this_->pro, &this_->r.rl, &g); + dbg(1,": - %f,%f\n", g.lat, g.lng); + transform_from_geo(pro, &g, &r->rl); + } + dbg(1,"transform rect for %d is %d,%d - %d,%d\n", pro, r->lu.x, r->lu.y, r->rl.x, r->rl.y); +} + +struct coord * +transform_center(struct transformation *this_) +{ + return &this_->center; +} + +int +transform_contains(struct transformation *this_, enum projection pro, struct coord_rect *r) +{ + struct coord_geo g; + struct coord_rect r1; + if (this_->pro != pro) { + transform_to_geo(pro, &r->lu, &g); + transform_from_geo(this_->pro, &g, &r1.lu); + transform_to_geo(pro, &r->rl, &g); + transform_from_geo(this_->pro, &g, &r1.rl); + r=&r1; + } + return coord_rect_overlap(&this_->r, r); + +} + +void transform_set_angle(struct transformation *t,int angle) { t->angle=angle; @@ -112,11 +242,30 @@ transform_set_angle(struct transformation *t,int angle) t->sin_val=sin(M_PI*t->angle/180); } +int +transform_get_angle(struct transformation *this_,int angle) +{ + return this_->angle; +} + +void +transform_set_size(struct transformation *t, int width, int height) +{ + t->width=width; + t->height=height; +} + +void +transform_get_size(struct transformation *t, int *width, int *height) +{ + *width=t->width; + *height=t->height; +} + void -transform_setup(struct transformation *t, int x, int y, int scale, int angle) +transform_setup(struct transformation *t, struct coord *c, int scale, int angle) { - t->center.x=x; - t->center.y=y; + t->center=*c; t->scale=scale; transform_set_angle(t, angle); } @@ -127,10 +276,10 @@ transform_setup_source_rect_limit(struct transformation *t, struct coord *center t->center=*center; t->scale=1; t->angle=0; - t->rect[0].x=center->x-limit; - t->rect[1].x=center->x+limit; - t->rect[1].y=center->y-limit; - t->rect[0].y=center->y+limit; + t->r.lu.x=center->x-limit; + t->r.rl.x=center->x+limit; + t->r.rl.y=center->y-limit; + t->r.lu.y=center->y+limit; } void @@ -151,28 +300,41 @@ transform_setup_source_rect(struct transformation *t) for (i = 0 ; i < 4 ; i++) { transform_reverse(t, &screen_pnt[i], &screen[i]); } - t->rect[0].x=min4(screen[0].x,screen[1].x,screen[2].x,screen[3].x); - t->rect[1].x=max4(screen[0].x,screen[1].x,screen[2].x,screen[3].x); - t->rect[1].y=min4(screen[0].y,screen[1].y,screen[2].y,screen[3].y); - t->rect[0].y=max4(screen[0].y,screen[1].y,screen[2].y,screen[3].y); + t->r.lu.x=min4(screen[0].x,screen[1].x,screen[2].x,screen[3].x); + t->r.rl.x=max4(screen[0].x,screen[1].x,screen[2].x,screen[3].x); + t->r.rl.y=min4(screen[0].y,screen[1].y,screen[2].y,screen[3].y); + t->r.lu.y=max4(screen[0].y,screen[1].y,screen[2].y,screen[3].y); } -int +long transform_get_scale(struct transformation *t) { - return t->scale/16; + return t->scale; } void -transform_lng_lat(struct coord *c, struct coord_geo *g) +transform_set_scale(struct transformation *t, long scale) { - g->lng=c->x/6371000.0/M_PI*180; - g->lat=atan(exp(c->y/6371000.0))/M_PI*360-90; -#if 0 - printf("y=%d vs %f\n", c->y, log(tan(M_PI_4+*lat*M_PI/360))*6371020.0); -#endif + t->scale=scale; } + +int +transform_get_order(struct transformation *t) +{ + int scale=t->scale; + int order=0; + while (scale > 1) { + order++; + scale>>=1; + } + order=18-order; + if (order < 0) + order=0; + return order; +} + + void transform_geo_text(struct coord_geo *g, char *buffer) { @@ -194,13 +356,6 @@ transform_geo_text(struct coord_geo *g, char *buffer) } -void -transform_mercator(double *lng, double *lat, struct coord *c) -{ - c->x=*lng*6371000.0*M_PI/180; - c->y=log(tan(M_PI_4+*lat*M_PI/360))*6371000.0; -} - double transform_scale(int y) { @@ -208,17 +363,52 @@ transform_scale(int y) struct coord_geo g; c.x=0; c.y=y; - transform_lng_lat(&c, &g); + transform_to_geo(projection_mg, &c, &g); return 1/cos(g.lat/180*M_PI); } +#ifdef AVOID_FLOAT +static int +tab_sqrt[]={14142,13379,12806,12364,12018,11741,11517,11333,11180,11051,10943,10850,10770,10701,10640,10587,10540,10499,10462,10429,10400,10373,10349,10327,10307,10289,10273,10257,10243,10231,10219,10208}; +#endif + double transform_distance(struct coord *c1, struct coord *c2) { +#ifndef AVOID_FLOAT double dx,dy,scale=transform_scale((c1->y+c2->y)/2); dx=c1->x-c2->x; dy=c1->y-c2->y; return sqrt(dx*dx+dy*dy)/scale; +#else + int dx,dy,f,scale=15539; + dx=c1->x-c2->x; + dy=c1->y-c2->y; + if (dx < 0) + dx=-dx; + if (dy < 0) + dy=-dy; + while (dx > 20000 || dy > 20000) { + dx/=10; + dy/=10; + scale/=10; + } + if (! dy) + return dx*10000/scale; + if (! dx) + return dy*10000/scale; + if (dx > dy) { + f=dx*8/dy-8; + if (f >= 32) + return dx*10000/scale; + return dx*tab_sqrt[f]/scale; + } else { + f=dy*8/dx-8; + if (f >= 32) + return dy*10000/scale; + return dy*tab_sqrt[f]/scale; + } +#endif } int @@ -269,6 +459,29 @@ transform_distance_line_sq(struct coord *l0, struct coord *l1, struct coord *ref return transform_distance_sq(&l, ref); } +int +transform_distance_polyline_sq(struct coord *c, int count, struct coord *ref, struct coord *lpnt, int *pos) +{ + int i,dist,distn; + struct coord lp; + if (count < 2) + return 0; + if (pos) + *pos=0; + dist=transform_distance_line_sq(&c[0], &c[1], ref, lpnt); + for (i=2 ; i < count ; i++) { + distn=transform_distance_line_sq(&c[i-1], &c[i], ref, &lp); + if (distn < dist) { + dist=distn; + if (lpnt) + *lpnt=lp; + if (pos) + *pos=i-1; + } + } + return dist; +} + void transform_print_deg(double deg) @@ -279,19 +492,19 @@ transform_print_deg(double deg) int is_visible(struct transformation *t, struct coord *c) { - struct coord *r=t->rect; + struct coord_rect *r=&t->r; assert(c[0].x <= c[1].x); assert(c[0].y >= c[1].y); - assert(r[0].x <= r[1].x); - assert(r[0].y >= r[1].y); - if (c[0].x > r[1].x) + assert(r->lu.x <= r->rl.x); + assert(r->lu.y >= r->rl.y); + if (c[0].x > r->rl.x) return 0; - if (c[1].x < r[0].x) + if (c[1].x < r->lu.x) return 0; - if (c[0].y < r[1].y) + if (c[0].y < r->rl.y) return 0; - if (c[1].y > r[0].y) + if (c[1].y > r->lu.y) return 0; return 1; } @@ -299,17 +512,17 @@ is_visible(struct transformation *t, struct coord *c) int is_line_visible(struct transformation *t, struct coord *c) { - struct coord *r=t->rect; + struct coord_rect *r=&t->r; - assert(r[0].x <= r[1].x); - assert(r[0].y >= r[1].y); - if (MIN(c[0].x,c[1].x) > r[1].x) + assert(r->lu.x <= r->rl.x); + assert(r->lu.y >= r->rl.y); + if (MIN(c[0].x,c[1].x) > r->rl.x) return 0; - if (MAX(c[0].x,c[1].x) < r[0].x) + if (MAX(c[0].x,c[1].x) < r->lu.x) return 0; - if (MAX(c[0].y,c[1].y) < r[1].y) + if (MAX(c[0].y,c[1].y) < r->rl.y) return 0; - if (MIN(c[0].y,c[1].y) > r[0].y) + if (MIN(c[0].y,c[1].y) > r->lu.y) return 0; return 1; } @@ -317,17 +530,17 @@ is_line_visible(struct transformation *t, struct coord *c) int is_point_visible(struct transformation *t, struct coord *c) { - struct coord *r=t->rect; + struct coord_rect *r=&t->r; - assert(r[0].x <= r[1].x); - assert(r[0].y >= r[1].y); - if (c->x > r[1].x) + assert(r->lu.x <= r->rl.x); + assert(r->lu.y >= r->rl.y); + if (c->x > r->rl.x) return 0; - if (c->x < r[0].x) + if (c->x < r->lu.x) return 0; - if (c->y < r[1].y) + if (c->y < r->rl.y) return 0; - if (c->y > r[0].y) + if (c->y > r->lu.y) return 0; return 1; } @@ -346,25 +559,72 @@ is_too_small(struct transformation *t, struct coord *c, int limit) return 0; } +#ifdef AVOID_FLOAT +static int tab_atan[]={0,262,524,787,1051,1317,1584,1853,2126,2401,2679,2962,3249,3541,3839,4142,4452,4770,5095,5430,5774,6128,6494,6873,7265,7673,8098,8541,9004,9490,10000,10538}; -void transform_limit_extend(struct coord *rect, struct coord *c) +static int +atan2_int_lookup(int val) { - if (c->x < rect[0].x) rect[0].x=c->x; - if (c->x > rect[1].x) rect[1].x=c->x; - if (c->y < rect[1].y) rect[1].y=c->y; - if (c->y > rect[0].y) rect[0].y=c->y; + int len=sizeof(tab_atan)/sizeof(int); + int i=len/2; + int p=i-1; + for (;;) { + i>>=1; + if (val < tab_atan[p]) + p-=i; + else + if (val < tab_atan[p+1]) + return p+(p>>1); + else + p+=i; + } } - +static int +atan2_int(int dx, int dy) +{ + int f,mul=1,add=0,ret; + if (! dx) { + return dy < 0 ? 180 : 0; + } + if (! dy) { + return dx < 0 ? -90 : 90; + } + if (dx < 0) { + dx=-dx; + mul=-1; + } + if (dy < 0) { + dy=-dy; + add=180*mul; + mul*=-1; + } + while (dx > 20000 || dy > 20000) { + dx/=10; + dy/=10; + } + if (dx > dy) { + ret=90-atan2_int_lookup(dy*10000/dx); + } else { + ret=atan2_int_lookup(dx*10000/dy); + } + return ret*mul+add; +} +#endif int -transform_get_angle(struct coord *c, int dir) +transform_get_angle_delta(struct coord *c1, struct coord *c2, int dir) { + int dx=c2->x-c1->x; + int dy=c2->y-c1->y; +#ifndef AVOID_FLOAT double angle; - int dx=c[1].x-c[0].x; - int dy=c[1].y-c[0].y; angle=atan2(dx,dy); angle*=180/M_PI; +#else + int angle; + angle=atan2_int(dx,dy); +#endif if (dir == -1) angle=angle-180; if (angle < 0) @@ -372,6 +632,14 @@ transform_get_angle(struct coord *c, int dir) return angle; } +int +transform_within_border(struct transformation *this_, struct point *p, int border) +{ + if (p->x < border || p->x > this_->width-border || p->y < border || p->y > this_->height-border) + return 0; + return 1; +} + /* Note: there are many mathematically equivalent ways to express these formulas. As usual, not all of them are computationally equivalent. @@ -412,4 +680,3 @@ e = the first eccentricity of the ellipsoid */ - diff --git a/src/transform.h b/src/transform.h index f2099d25..6c9059e1 100644 --- a/src/transform.h +++ b/src/transform.h @@ -1,39 +1,47 @@ -#ifndef TRANSFORM_H -#define TRANSFORM_H - -#include "point.h" - -struct transformation { - int width; /* Height of destination rectangle */ - int height; /* Width of destination rectangle */ - long scale; /* Scale factor */ - int angle; /* Rotation angle */ - double cos_val,sin_val; /* cos and sin of rotation angle */ - struct coord rect[2]; /* Source rectangle */ - struct coord center; /* Center of source rectangle */ -}; - -int transform(struct transformation *t, struct coord *c, struct point *p); -int is_visible(struct transformation *t, struct coord *c); -int is_line_visible(struct transformation *t, struct coord *c); -int is_too_small(struct transformation *t, struct coord *c, int limit); -void transform_lng_lat(struct coord *c, struct coord_geo *g); +#ifdef __cplusplus +extern "C" { +#endif +/* prototypes */ +enum projection; +struct coord; +struct coord_geo; +struct coord_rect; +struct point; +struct transformation; +struct transformation *transform_new(void); +void transform_to_geo(enum projection pro, struct coord *c, struct coord_geo *g); +void transform_from_geo(enum projection pro, struct coord_geo *g, struct coord *c); +int transform(struct transformation *t, enum projection pro, struct coord *c, struct point *p); void transform_reverse(struct transformation *t, struct point *p, struct coord *c); -void transform_print_deg(double deg); +enum projection transform_get_projection(struct transformation *this_); +void transform_set_projection(struct transformation *this_, enum projection pro); +void transform_rect(struct transformation *this_, enum projection pro, struct coord_rect *r); +struct coord *transform_center(struct transformation *this_); +int transform_contains(struct transformation *this_, enum projection pro, struct coord_rect *r); +void transform_set_angle(struct transformation *t, int angle); +int transform_get_angle(struct transformation *this_, int angle); +void transform_set_size(struct transformation *t, int width, int height); +void transform_get_size(struct transformation *t, int *width, int *height); +void transform_setup(struct transformation *t, struct coord *c, int scale, int angle); +void transform_setup_source_rect_limit(struct transformation *t, struct coord *center, int limit); +void transform_setup_source_rect(struct transformation *t); +long transform_get_scale(struct transformation *t); +void transform_set_scale(struct transformation *t, long scale); +int transform_get_order(struct transformation *t); +void transform_geo_text(struct coord_geo *g, char *buffer); double transform_scale(int y); double transform_distance(struct coord *c1, struct coord *c2); int transform_distance_sq(struct coord *c1, struct coord *c2); int transform_distance_line_sq(struct coord *l0, struct coord *l1, struct coord *ref, struct coord *lpnt); - -void transform_mercator(double *lng, double *lat, struct coord *c); +int transform_distance_polyline_sq(struct coord *c, int count, struct coord *ref, struct coord *lpnt, int *pos); +void transform_print_deg(double deg); +int is_visible(struct transformation *t, struct coord *c); +int is_line_visible(struct transformation *t, struct coord *c); int is_point_visible(struct transformation *t, struct coord *c); -int transform_get_scale(struct transformation *t); -void transform_setup_source_rect(struct transformation *t); -void transform_set_angle(struct transformation *t,int angle); -void transform_setup(struct transformation *t, int x, int y, int scale, int angle); -void transform_setup_source_rect_limit(struct transformation *t, struct coord *center, int limit); -void transform_geo_text(struct coord_geo *g, char *buffer); -void transform_limit_extend(struct coord *rect, struct coord *c); -int transform_get_angle(struct coord *c, int dir); - +int is_too_small(struct transformation *t, struct coord *c, int limit); +int transform_get_angle_delta(struct coord *c1, struct coord *c2, int dir); +int transform_within_border(struct transformation *this_, struct point *p, int border); +/* end of prototypes */ +#ifdef __cplusplus +} #endif diff --git a/src/tree.h b/src/tree.h deleted file mode 100644 index 58ff0448..00000000 --- a/src/tree.h +++ /dev/null @@ -1,13 +0,0 @@ -struct block_offset { - unsigned short offset; - unsigned short block; -}; - - -int tree_compare_string(unsigned char *s1, unsigned char **s2); -int tree_compare_string_partial(unsigned char *s1, unsigned char **s2); -#if 0 -int tree_search(struct file *file, unsigned char *search, int (*tree_func)(int, unsigned char *, unsigned char **, struct map_data *, void *), struct map_data *mdat, void *data2); -#endif -int tree_search_map(struct map_data *mdat, int map, char *ext, int (*tree_func)(int, int, unsigned char **, struct map_data *, void *), void *data); -int tree_search_hv_map(struct map_data *mdat, int map, unsigned int search1, unsigned int search2, int *result, struct map_data **mdat_result); @@ -1,3 +1,4 @@ +#include <glib.h> #include <ctype.h> #include "util.h" @@ -17,3 +18,19 @@ strtolower(char *dest, const char *src) *dest='\0'; } + +static void +hash_callback(gpointer key, gpointer value, gpointer user_data) +{ + GList **l=user_data; + *l=g_list_prepend(*l, value); +} + +GList * +g_hash_to_list(GHashTable *h) +{ + GList *ret=NULL; + g_hash_table_foreach(h, hash_callback, &ret); + + return ret; +} diff --git a/src/vehicle.c b/src/vehicle.c index 747ffffa..c81f4d43 100644 --- a/src/vehicle.c +++ b/src/vehicle.c @@ -2,19 +2,28 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <termios.h> #include <unistd.h> #include <fcntl.h> #include <math.h> +#include <sys/stat.h> #include <glib.h> #ifdef HAVE_LIBGPS #include <gps.h> #endif +#include "debug.h" #include "coord.h" #include "transform.h" +#include "projection.h" #include "statusbar.h" #include "vehicle.h" -/* #define INTERPOLATION_TIME 50 */ +int vfd; + +static void disable_watch(struct vehicle *this); +static void enable_watch(struct vehicle *this); + + /* #define INTERPOLATION_TIME 50 */ struct callback { void (*func)(struct vehicle *, void *data); @@ -22,11 +31,15 @@ struct callback { }; struct vehicle { + char *url; GIOChannel *iochan; + guint watch; + int is_file; + int is_pipe; int timer_count; int qual; int sats; - double lat,lng; + struct coord_geo geo; double height; double dir,speed; double time; @@ -35,9 +48,14 @@ struct vehicle { struct coord_d delta; double speed_last; + int fd; + FILE *file; #ifdef HAVE_LIBGPS struct gps_data_t *gps; #endif +#define BUFFER_SIZE 256 + char buffer[BUFFER_SIZE]; + int buffer_pos; GList *callbacks; }; @@ -55,13 +73,19 @@ vehicle_timer(gpointer t) this->current_pos.x=this->curr.x; this->current_pos.y=this->curr.y; if (this->callback_func) - (*this->callback_func)(this->callback_data); + (*this->callback_func)(this, this->callback_data); } /* } */ return TRUE; } #endif +enum projection +vehicle_projection(struct vehicle *this) +{ + return projection_mg; +} + static void vehicle_call_callbacks(struct vehicle *this) { @@ -91,12 +115,6 @@ vehicle_dir_get(struct vehicle *this) return &this->dir; } -double * -vehicle_height_get(struct vehicle *this) -{ - return &this->height; -} - void vehicle_set_position(struct vehicle *this, struct coord *pos) { @@ -108,16 +126,57 @@ vehicle_set_position(struct vehicle *this, struct coord *pos) vehicle_call_callbacks(this); } +static int +enable_watch_timer(gpointer t) +{ + struct vehicle *this=t; + enable_watch(this); + + return FALSE; +} + static void vehicle_parse_gps(struct vehicle *this, char *buffer) { char *p,*item[16]; double lat,lng,scale,speed; - int i,debug=0; + int i,bcsum; + int len=strlen(buffer); + unsigned char csum=0; - if (debug) { - printf("GPS %s\n", buffer); + dbg(1, "buffer='%s' ", buffer); + write(vfd, buffer, len); + write(vfd, "\n", 1); + for (;;) { + if (len < 4) { + dbg(0, "too short\n"); + return; + } + if (buffer[len-1] == '\r' || buffer[len-1] == '\n') + buffer[--len]='\0'; + else + break; + } + if (buffer[0] != '$') { + dbg(0, "no leading $\n"); + return; } + if (buffer[len-3] != '*') { + dbg(0, "no *XX\n"); + return; + } + for (i = 1 ; i < len-3 ; i++) { + csum ^= (unsigned char)(buffer[i]); + } + if (!sscanf(buffer+len-2, "%x", &bcsum)) { + dbg(0, "no checksum\n"); + return; + } + if (bcsum != csum) { + dbg(0, "wrong checksum\n"); + return; + } + if (!strncmp(buffer,"$GPGGA",6)) { /* $GPGGA,184424.505,4924.2811,N,01107.8846,E,1,05,2.5,408.6,M,,,,0000*0C UTC of Fix,Latitude,N/S,Longitude,E/W,Quality,Satelites,HDOP,Altitude,"M" @@ -133,25 +192,29 @@ vehicle_parse_gps(struct vehicle *this, char *buffer) } sscanf(item[2],"%lf",&lat); - this->lat=floor(lat/100); - lat-=this->lat*100; - this->lat+=lat/60; + this->geo.lat=floor(lat/100); + lat-=this->geo.lat*100; + this->geo.lat+=lat/60; sscanf(item[4],"%lf",&lng); - this->lng=floor(lng/100); - lng-=this->lng*100; - this->lng+=lng/60; + this->geo.lng=floor(lng/100); + lng-=this->geo.lng*100; + this->geo.lng+=lng/60; sscanf(item[6],"%d",&this->qual); sscanf(item[7],"%d",&this->sats); sscanf(item[9],"%lf",&this->height); - transform_mercator(&this->lng, &this->lat, &this->current_pos); + transform_from_geo(projection_mg, &this->geo, &this->current_pos); this->curr.x=this->current_pos.x; this->curr.y=this->current_pos.y; this->timer_count=0; vehicle_call_callbacks(this); + if (this->is_file) { + disable_watch(this); + g_timeout_add(1000, enable_watch_timer, this); + } } if (!strncmp(buffer,"$GPVTG",6)) { /* $GPVTG,143.58,T,,M,0.26,N,0.5,K*6A @@ -178,44 +241,40 @@ vehicle_parse_gps(struct vehicle *this, char *buffer) #endif this->speed_last=this->speed; } -} - -static gboolean -vehicle_track(GIOChannel *iochan, GIOCondition condition, gpointer t) -{ - struct vehicle *this=t; - GError *error=NULL; - char buffer[4096]; - char *str,*tok; - gsize size; - - if (condition == G_IO_IN) { -#ifdef HAVE_LIBGPS - if (this->gps) { - vehicle_last=this; - gps_poll(this->gps); - } else { -#else - { -#endif - g_io_channel_read_chars(iochan, buffer, 4096, &size, &error); - buffer[size]='\0'; - str=buffer; - while ((tok=strtok(str, "\n"))) { - str=NULL; - vehicle_parse_gps(this, tok); - } + if (!strncmp(buffer,"$GPRMC",6)) { + /* $GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A */ + /* Time,Active/Void,lat,N/S,long,W/E,speed in knots,track angle,date,magnetic variation */ + i=0; + p=buffer; + while (i < 16) { + item[i++]=p; + while (*p && *p != ',') + p++; + if (! *p) break; + *p++='\0'; } - - return TRUE; - } - return FALSE; + sscanf(item[8],"%lf",&this->dir); + sscanf(item[7],"%lf",&this->speed); + this->speed *= 1.852; + scale=transform_scale(this->current_pos.y); + speed=this->speed+(this->speed-this->speed_last)/2; +#ifdef INTERPOLATION_TIME + this->delta.x=sin(M_PI*this->dir/180)*speed*scale/3600*INTERPOLATION_TIME; + this->delta.y=cos(M_PI*this->dir/180)*speed*scale/3600*INTERPOLATION_TIME; +#endif + this->speed_last=this->speed; + } } #ifdef HAVE_LIBGPS static void vehicle_gps_callback(struct gps_data_t *data, char *buf, size_t len, int level) { + // If data->fix.speed is NAN, then the drawing gets jumpy. + if(isnan(data->fix.speed)){ + return 0; + } + struct vehicle *this=vehicle_last; double scale,speed; #if INTERPOLATION_TIME @@ -243,9 +302,9 @@ vehicle_gps_callback(struct gps_data_t *data, char *buf, size_t len, int level) data->set &= ~TRACK_SET; } if (data->set & LATLON_SET) { - this->lat=data->fix.latitude; - this->lng=data->fix.longitude; - transform_mercator(&this->lng, &this->lat, &this->current_pos); + this->geo.lat=data->fix.latitude; + this->geo.lng=data->fix.longitude; + transform_from_geo(projection_mg, &this->geo, &this->current_pos); this->curr.x=this->current_pos.x; this->curr.y=this->current_pos.y; this->timer_count=0; @@ -267,53 +326,166 @@ vehicle_gps_callback(struct gps_data_t *data, char *buf, size_t len, int level) } #endif -struct vehicle * -vehicle_new(const char *url) + +static void +vehicle_close(struct vehicle *this) { - struct vehicle *this; GError *error=NULL; - int fd=-1; - char *url_,*colon; + + + g_io_channel_shutdown(this->iochan,0,&error); #ifdef HAVE_LIBGPS - struct gps_data_t *gps=NULL; + if (this->gps) + gps_close(this->gps); #endif + if (this->file) + pclose(this->file); + if (this->fd != -1) + close(this->fd); +} - if (! strncmp(url,"file:",5)) { - fd=open(url+5,O_RDONLY|O_NDELAY); +static int +vehicle_open(struct vehicle *this) +{ + struct termios tio; + struct stat st; + int fd; + +#ifdef HAVE_LIBGPS + struct gps_data_t *gps=NULL; + char *url_,*colon; +#endif + if (! strncmp(this->url,"file:",5)) { + fd=open(this->url+5,O_RDONLY|O_NDELAY); if (fd < 0) { - g_warning("Failed to open %s", url); + g_warning("Failed to open %s", this->url); + return 0; } - } else if (! strncmp(url,"gpsd://",7)) { + stat(this->url+5, &st); + if (S_ISREG (st.st_mode)) { + this->is_file=1; + } else { + tcgetattr(fd, &tio); + cfmakeraw(&tio); + cfsetispeed(&tio, B4800); + cfsetospeed(&tio, B4800); + tio.c_cc[VMIN]=16; + tio.c_cc[VTIME]=1; + tcsetattr(fd, TCSANOW, &tio); + } + this->fd=fd; + } else if (! strncmp(this->url,"pipe:",5)) { + this->file=popen(this->url+5, "r"); + this->is_pipe=1; + if (! this->file) { + g_warning("Failed to open %s", this->url); + return 0; + } + fd=fileno(this->file); + } else if (! strncmp(this->url,"gpsd://",7)) { #ifdef HAVE_LIBGPS - url_=g_strdup(url); + url_=g_strdup(this->url); colon=index(url_+7,':'); if (colon) { *colon=0; gps=gps_open(url_+7,colon+1); } else - gps=gps_open(url+7,NULL); + gps=gps_open(this->url+7,NULL); g_free(url_); if (! gps) { - g_warning("Failed to connect to %s", url); - } else { - gps_query(gps, "w+x\n"); - gps_set_raw_hook(gps, vehicle_gps_callback); - fd=gps->gps_fd; + g_warning("Failed to connect to %s", this->url); + return 0; } + gps_query(gps, "w+x\n"); + gps_set_raw_hook(gps, vehicle_gps_callback); + fd=gps->gps_fd; + this->gps=gps; #else g_warning("No support for gpsd compiled in\n"); + return 0; #endif } - this=g_new0(struct vehicle,1); + this->iochan=g_io_channel_unix_new(fd); + enable_watch(this); + return 1; +} + + +static gboolean +vehicle_track(GIOChannel *iochan, GIOCondition condition, gpointer t) +{ + struct vehicle *this=t; + GError *error=NULL; + char *str,*tok; + gsize size; + + dbg(1,"enter condition=%d\n", condition); + if (condition == G_IO_IN) { #ifdef HAVE_LIBGPS - if(gps) - this->gps=gps; + if (this->gps) { + vehicle_last=this; + gps_poll(this->gps); + } else { +#else + { #endif - if(fd !=-1) { - this->iochan=g_io_channel_unix_new(fd); - g_io_channel_set_encoding(this->iochan, NULL, &error); - g_io_add_watch(this->iochan, G_IO_IN|G_IO_ERR|G_IO_HUP, vehicle_track, this); + size=read(g_io_channel_unix_get_fd(iochan), this->buffer+this->buffer_pos, BUFFER_SIZE-this->buffer_pos-1); + if (size <= 0) { + vehicle_close(this); + vehicle_open(this); + return TRUE; + } + this->buffer_pos+=size; + this->buffer[this->buffer_pos]='\0'; + dbg(1,"size=%d pos=%d buffer='%s'\n", size, this->buffer_pos, this->buffer); + str=this->buffer; + while ((tok=index(str, '\n'))) { + *tok++='\0'; + dbg(1,"line='%s'\n", str); + vehicle_parse_gps(this, str); + str=tok; + } + if (str != this->buffer) { + size=this->buffer+this->buffer_pos-str; + memmove(this->buffer, str, size+1); + this->buffer_pos=size; + dbg(1,"now pos=%d buffer='%s'\n", this->buffer_pos, this->buffer); + } else if (this->buffer_pos == BUFFER_SIZE-1) { + dbg(0,"overflow\n"); + this->buffer_pos=0; + } + + } + + return TRUE; + } + return FALSE; +} + +static void +enable_watch(struct vehicle *this) +{ + this->watch=g_io_add_watch(this->iochan, G_IO_IN|G_IO_ERR|G_IO_HUP, vehicle_track, this); +} + +static void +disable_watch(struct vehicle *this) +{ + g_source_remove(this->watch); +} + +struct vehicle * +vehicle_new(const char *url) +{ + struct vehicle *this; + this=g_new0(struct vehicle,1); + this->url=g_strdup(url); + this->fd=-1; + + if (! vfd) { + vfd=open("vlog.txt", O_RDWR|O_APPEND|O_CREAT, 0644); } + vehicle_open(this); this->current_pos.x=0x130000; this->current_pos.y=0x600000; this->curr.x=this->current_pos.x; @@ -321,7 +493,7 @@ vehicle_new(const char *url) this->delta.x=0; this->delta.y=0; #if INTERPOLATION_TIME - g_timeout_add(INTERPOLATION_TIME, vehicle_timer, this); + g_timeout_add(INTERPOLATION_TIME, vehicle_timer, this); #endif return this; @@ -344,23 +516,11 @@ vehicle_callback_unregister(struct vehicle *this, void *handle) g_list_remove(this->callbacks, handle); } + void vehicle_destroy(struct vehicle *this) { - GError *error=NULL; - GList *item=g_list_first(this->callbacks),*next; - - - g_io_channel_shutdown(this->iochan,0,&error); -#ifdef HAVE_LIBGPS - if (this->gps) - gps_close(this->gps); -#endif - while (item) { - next=g_list_next(item); - vehicle_callback_unregister(this, item->data); - item=next; - } - g_list_free(this->callbacks); + vehicle_close(this); + g_free(this->url); g_free(this); } diff --git a/src/vehicle.h b/src/vehicle.h index aa028c49..46cf4304 100644 --- a/src/vehicle.h +++ b/src/vehicle.h @@ -1,11 +1,12 @@ +/* prototypes */ +struct coord; struct vehicle; - -struct coord *vehicle_pos_get(struct vehicle *); -double *vehicle_dir_get(struct vehicle *); -double *vehicle_speed_get(struct vehicle *); -double *vehicle_height_get(struct vehicle *this); -void * vehicle_callback_register(struct vehicle *this, void (*func)(struct vehicle *, void *data), void *data); -void vehicle_callback_unregister(struct vehicle *this, void *handle); -void vehicle_set_position(struct vehicle *, struct coord *); +enum projection vehicle_projection(struct vehicle *this); +struct coord *vehicle_pos_get(struct vehicle *this); +double *vehicle_speed_get(struct vehicle *this); +double *vehicle_dir_get(struct vehicle *this); +void vehicle_set_position(struct vehicle *this, struct coord *pos); struct vehicle *vehicle_new(const char *url); -void vehicle_destroy(struct vehicle *); +void *vehicle_callback_register(struct vehicle *this, void (*func)(struct vehicle *, void *data), void *data); +void vehicle_callback_unregister(struct vehicle *this, void *handle); +void vehicle_destroy(struct vehicle *this); diff --git a/src/xmlconfig.c b/src/xmlconfig.c new file mode 100644 index 00000000..dadbb4d0 --- /dev/null +++ b/src/xmlconfig.c @@ -0,0 +1,534 @@ +#include <glib.h> +#include <glib/gprintf.h> +#include <string.h> +#include "xmlconfig.h" +#include "navit.h" +#include "vehicle.h" +#include "mapset.h" +#include "map.h" +#include "layout.h" +#include "projection.h" +#include "coord.h" +#include "plugin.h" + + +struct xmlstate { + const gchar **attribute_names; + const gchar **attribute_values; + struct xmlstate *parent; + void *element_object; + const gchar *element; + GError **error; + struct element_func *func; +} *xmlstate_root; + + +static const char * find_attribute(struct xmlstate *state, const char *attribute, int required) +{ + const gchar **attribute_name=state->attribute_names; + const gchar **attribute_value=state->attribute_values; + while(*attribute_name) { + if(! g_ascii_strcasecmp(attribute,*attribute_name)) + return *attribute_value; + attribute_name++; + attribute_value++; + } + if (required) + g_set_error(state->error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT, "element '%s' is missing attribute '%s'", state->element, attribute); + return NULL; +} + +static int +find_color(struct xmlstate *state, int required, struct color *color) +{ + const char *value; + int r,g,b; + + value=find_attribute(state, "color", required); + if (! value) + return 0; + + sscanf(value,"#%02x%02x%02x", &r, &g, &b); + color->r = (r << 8) | r; + color->g = (g << 8) | g; + color->b = (b << 8) | b; + return 1; +} + +static int +find_zoom(struct xmlstate *state, int required, int *min, int *max) +{ + const char *value, *pos; + int ret; + + *min=0; + *max=18; + value=find_attribute(state, "zoom", required); + if (! value) + return 0; + pos=index(value, '-'); + if (! pos) { + ret=sscanf(value,"%d",min); + *max=*min; + } else if (pos == value) + ret=sscanf(value,"-%d",max); + else + ret=sscanf(value,"%d-%d", min, max); + return ret; +} + +static int +find_boolean(struct xmlstate *state, const char *attribute, int deflt, int required) +{ + const char *value; + + value=find_attribute(state, attribute, required); + if (! value) + return deflt; + if (g_ascii_strcasecmp(value,"no") && g_ascii_strcasecmp(value,"0") && g_ascii_strcasecmp(value,"false")) + return 1; + return 0; +} + +static int +convert_number(const char *val) +{ + return g_ascii_strtoull(val,NULL,0); +} + +static int +xmlconfig_plugins(struct xmlstate *state) +{ + state->element_object = plugins_new(); + if (! state->element_object) + return 0; + return 1; +} + +static int +xmlconfig_plugin(struct xmlstate *state) +{ + const char *path; + int active,lazy; + + state->element_object=state->parent->element_object; + path=find_attribute(state, "path", 1); + if (! path) + return 0; + active=find_boolean(state, "active", 1, 0); + lazy=find_boolean(state, "lazy", 1, 0); + plugins_add_path(state->parent->element_object, path, active, lazy); + return 1; +} + +static int +xmlconfig_navit(struct xmlstate *state) +{ + const char *value,*gui,*graphics; + int zoom=0; + struct coord c; + enum projection pro=projection_mg; + + value=find_attribute(state, "zoom", 0); + if (value) + zoom=convert_number(value); + if (! zoom) + zoom=256; + value=find_attribute(state, "center", 0); + if (! value || ! coord_parse(value, pro, &c)) { + c.x=1300000; + c.y=7000000; + } + gui=find_attribute(state, "gui", 0); + if (! gui) + gui="gtk"; + graphics=find_attribute(state, "graphics", 0); + if (! graphics) + graphics="gtk_drawing_area"; + state->element_object = navit_new(gui, graphics, &c, pro, zoom); + if (! state->element_object) + return 0; + return 1; +} + +static int +xmlconfig_vehicle(struct xmlstate *state) +{ + const char *s=find_attribute(state, "source", 1); + const char *value; + struct color color; + int update=1, follow=0; + + if (! s) + return 0; + if (! find_color(state, 1, &color)) + return 0; + state->element_object = vehicle_new(s); + if (! state->element_object) + return 0; + if ((value=find_attribute(state, "update", 0))) + update=convert_number(value); + if ((value=find_attribute(state, "follow", 0))) + follow=convert_number(value); + + navit_vehicle_add(state->parent->element_object, state->element_object, &color, update, follow); + return 1; +} + +static int +xmlconfig_mapset(struct xmlstate *state) +{ + state->element_object = mapset_new(); + if (! state->element_object) + return 0; + navit_add_mapset(state->parent->element_object, state->element_object); + + return 1; +} + +static int +xmlconfig_map(struct xmlstate *state) +{ + const char *type=find_attribute(state, "type", 1); + const char *data=find_attribute(state, "data", 1); + if (! type || ! data) + return 0; + state->element_object = map_new(type, data); + if (! state->element_object) + return 0; + if (!find_boolean(state, "active", 1, 0)) + map_set_active(state->element_object, 0); + mapset_add(state->parent->element_object, state->element_object); + + return 1; +} + +static int +xmlconfig_layout(struct xmlstate *state) +{ + const char *name=find_attribute(state, "name", 1); + + if (! name) + return 0; + state->element_object = layout_new(name); + if (! state->element_object) + return 0; + navit_add_layout(state->parent->element_object, state->element_object); + return 1; +} + +static int +xmlconfig_layer(struct xmlstate *state) +{ + const char *name=find_attribute(state, "name", 1); + if (! name) + return 0; + state->element_object = layer_new(name, convert_number(find_attribute(state, "details", 0))); + if (! state->element_object) + return 0; + layout_add_layer(state->parent->element_object, state->element_object); + return 1; +} + +static int +xmlconfig_item(struct xmlstate *state) +{ + const char *type=find_attribute(state, "type", 1); + int min, max; + enum item_type itype; + char *saveptr, *tok, *type_str, *str; + + if (! type) + return 0; + if (! find_zoom(state, 1, &min, &max)) + return 0; + state->element_object=itemtype_new(min, max); + if (! state->element_object) + return 0; + type_str=g_strdup(type); + str=type_str; + layer_add_itemtype(state->parent->element_object, state->element_object); + while ((tok=strtok_r(str, ",", &saveptr))) { + itype=item_from_name(tok); + itemtype_add_type(state->element_object, itype); + str=NULL; + } + g_free(type_str); + + return 1; +} + +static int +xmlconfig_polygon(struct xmlstate *state) +{ + struct color color; + + if (! find_color(state, 1, &color)) + return 0; + state->element_object=polygon_new(&color); + if (! state->element_object) + return 0; + itemtype_add_element(state->parent->element_object, state->element_object); + + return 1; +} + +static int +xmlconfig_polyline(struct xmlstate *state) +{ + struct color color; + const char *width; + int w=0; + + if (! find_color(state, 1, &color)) + return 0; + width=find_attribute(state, "width", 0); + if (width) + w=convert_number(width); + state->element_object=polyline_new(&color, w); + if (! state->element_object) + return 0; + itemtype_add_element(state->parent->element_object, state->element_object); + + return 1; +} + +static int +xmlconfig_circle(struct xmlstate *state) +{ + struct color color; + const char *width, *radius, *label_size; + int w=0,r=0,ls=0; + + if (! find_color(state, 1, &color)) + return 0; + width=find_attribute(state, "width", 0); + if (width) + w=convert_number(width); + radius=find_attribute(state, "radius", 0); + if (radius) + r=convert_number(radius); + label_size=find_attribute(state, "label_size", 0); + if (label_size) + ls=convert_number(label_size); + state->element_object=circle_new(&color, r, w, ls); + if (! state->element_object) + return 0; + itemtype_add_element(state->parent->element_object, state->element_object); + + return 1; +} + +static int +xmlconfig_label(struct xmlstate *state) +{ + const char *label_size; + int ls=0; + + label_size=find_attribute(state, "label_size", 0); + if (label_size) + ls=convert_number(label_size); + state->element_object=label_new(ls); + if (! state->element_object) + return 0; + itemtype_add_element(state->parent->element_object, state->element_object); + + return 1; +} + +static int +xmlconfig_icon(struct xmlstate *state) +{ + const char *src=find_attribute(state, "src", 1); + + if (! src) + return 0; + state->element_object=icon_new(src); + if (! state->element_object) + return 0; + itemtype_add_element(state->parent->element_object, state->element_object); + + return 1; +} + +static int +xmlconfig_image(struct xmlstate *state) +{ + state->element_object=image_new(); + if (! state->element_object) + return 0; + itemtype_add_element(state->parent->element_object, state->element_object); + + return 1; +} + +struct element_func { + char *name; + char *parent; + int (*func)(struct xmlstate *state); +} elements[] = { + { "plugins", NULL, xmlconfig_plugins}, + { "plugin", "plugins", xmlconfig_plugin}, + { "navit", NULL, xmlconfig_navit}, + { "vehicle", "navit", xmlconfig_vehicle}, + { "mapset", "navit", xmlconfig_mapset}, + { "map", "mapset", xmlconfig_map}, + { "layout", "navit", xmlconfig_layout}, + { "layer", "layout", xmlconfig_layer}, + { "item", "layer", xmlconfig_item}, + { "polygon", "item", xmlconfig_polygon}, + { "polyline", "item", xmlconfig_polyline}, + { "circle", "item", xmlconfig_circle}, + { "label", "item", xmlconfig_label}, + { "icon", "item", xmlconfig_icon}, + { "image", "item", xmlconfig_image}, + {}, +}; + +static void +start_element (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error) +{ + struct xmlstate *new=NULL, **parent = user_data; + struct element_func *e=elements,*func=NULL; + const char *parent_name=NULL; + while (e->name) { + if (!g_ascii_strcasecmp(element_name, e->name)) { + func=e; + } + e++; + } + if (! func) { + g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT, + "Unknown element '%s'", element_name); + return; + } + if (*parent) + parent_name=(*parent)->element; + if ((parent_name && func->parent && g_ascii_strcasecmp(parent_name, func->parent)) || + (!parent_name && func->parent) || (parent_name && !func->parent)) { + g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT, + "Element '%s' within unexpected context '%s'. Expected '%s'", + element_name, parent_name, func->parent); + return; + } + + new=g_new(struct xmlstate, 1); + new->attribute_names=attribute_names; + new->attribute_values=attribute_values; + new->parent=*parent; + new->element_object=NULL; + new->element=element_name; + new->error=error; + new->func=func; + *parent=new; + if (!find_boolean(new, "enabled", 1, 0)) + return; + if (new->parent && !new->parent->element_object) + return; + if (!func->func(new)) { + return; + } + return; +#if 0 + struct elem_data *data = user_data; + void *elem=NULL; + void *parent_object; + char *parent_token; + parent_object=data->elem_stack ? data->elem_stack->data : NULL; + parent_token=data->token_stack ? data->token_stack->data : NULL; + + /* g_printf("start_element: %s AN: %s AV: %s\n",element_name,*attribute_names,*attribute_values); */ + + + printf("Unknown element '%s'\n", element_name); +#if 0 + data->elem_stack = g_list_prepend(data->elem_stack, elem); + data->token_stack = g_list_prepend(data->token_stack, (gpointer)element_name); +#endif +#endif +} + + +/* Called for close tags </foo> */ +static void +end_element (GMarkupParseContext *context, + const gchar *element_name, + gpointer user_data, + GError **error) +{ + struct xmlstate *curr, **state = user_data; + + curr=*state; + if(!g_ascii_strcasecmp("plugins", element_name) && curr->element_object) + plugins_init(curr->element_object); + if(!g_ascii_strcasecmp("navit", element_name) && curr->element_object) + navit_init(curr->element_object); + *state=curr->parent; + g_free(curr); +} + + +/* Called for character data */ +/* text is not nul-terminated */ +static void +text (GMarkupParseContext *context, + const gchar *text, + gsize text_len, + gpointer user_data, + GError **error) +{ + struct xmlstate **state = user_data; + + (void) state; +} + + + +static const GMarkupParser parser = { + start_element, + end_element, + text, + NULL, + NULL +}; + + +gboolean config_load(char *filename, GError **error) +{ + GMarkupParseContext *context; + char *contents; + gsize len; + gboolean result; + gint line; + gint chr; + gchar *message; + + struct xmlstate *curr=NULL; + + context = g_markup_parse_context_new (&parser, 0, &curr, NULL); + + if (!g_file_get_contents (filename, &contents, &len, error)) + return FALSE; + + result = g_markup_parse_context_parse (context, contents, len, error); + if (result && curr) { + g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_PARSE, "element '%s' not closed", curr->element); + result=FALSE; + } + if (!result && error && *error) { + g_markup_parse_context_get_position(context, &line, &chr); + message=g_strdup_printf("%s at line %d, char %d\n", (*error)->message, line, chr); + g_free((*error)->message); + (*error)->message=message; + } + g_markup_parse_context_free (context); + g_free (contents); + + return result; +} + diff --git a/src/xmlconfig.h b/src/xmlconfig.h new file mode 100644 index 00000000..036eab52 --- /dev/null +++ b/src/xmlconfig.h @@ -0,0 +1,3 @@ + +struct container; +gboolean config_load(char *filename,GError **error); diff --git a/src/xpm/Makefile.am b/src/xpm/Makefile.am new file mode 100644 index 00000000..786803d2 --- /dev/null +++ b/src/xpm/Makefile.am @@ -0,0 +1,3 @@ +include $(top_srcdir)/Makefile.inc +xpm_DATA = *.xpm +EXTRA_DIST = *.xpm diff --git a/src/xpm/camping.xpm b/src/xpm/camping.xpm new file mode 100644 index 00000000..86ff7d46 --- /dev/null +++ b/src/xpm/camping.xpm @@ -0,0 +1,24 @@ +/* XPM */ +static char *camping[]={ +"16 16 5 1", +". c None", +"b c #000000", +"a c #0000ff", +"c c #c6c6c6", +"# c #ffffff", +".##############.", +"#aaaaaaaaaaaaaa#", +"#aaaaaaaaaaaaaa#", +"#aa####bb####aa#", +"#aa###cbbc###aa#", +"#aa###b##b###aa#", +"#aa##cb##bc##aa#", +"#aa##bc##cb##aa#", +"#aa#cb#bb#bc#aa#", +"#aa#bccbbccb#aa#", +"#aacb#bbbb#bcaa#", +"#aabbbbbbbbbbaa#", +"#aa##########aa#", +"#aaaaaaaaaaaaaa#", +"#aaaaaaaaaaaaaa#", +".##############."}; diff --git a/src/xpm/car_dealer.xpm b/src/xpm/car_dealer.xpm new file mode 100644 index 00000000..892f10b2 --- /dev/null +++ b/src/xpm/car_dealer.xpm @@ -0,0 +1,26 @@ +/* XPM */ +static char *car_dealer[]={ +"16 16 7 1", +". c None", +"c c #000000", +"a c #0000ff", +"b c #7f7f7f", +"d c #bfbfbf", +"e c #f6f6fa", +"# c #ffffff", +".##############.", +"#aaaaaaaaaaaaaa#", +"#a############a#", +"#a####bccb####a#", +"#a##dccccccd##a#", +"#a#####cc#####a#", +"#a##dccccccd##a#", +"#a####bccbe###a#", +"#a#####cc#####a#", +"#a####dccd####a#", +"#a####dccd####a#", +"#a####bccb####a#", +"#a####bccb####a#", +"#a############a#", +"#aaaaaaaaaaaaaa#", +".##############."}; diff --git a/src/xpm/fuel.xpm b/src/xpm/fuel.xpm new file mode 100644 index 00000000..7b9f5f84 --- /dev/null +++ b/src/xpm/fuel.xpm @@ -0,0 +1,26 @@ +/* XPM */ +static char *fuel[]={ +"16 16 7 1", +". c None", +"d c #000000", +"a c #0000ff", +"c c #7f7f7f", +"e c #d1d2d3", +"b c #fefefe", +"# c #ffffff", +".##############.", +"#aaaaaaaaaaaaaa#", +"#aaaaaaaaaaaaaa#", +"#aabbbbbbbbbbaa#", +"#aabbbcdddcbbaa#", +"#aabbed#bbdbbaa#", +"#aabbed#bbdbbaa#", +"#aabbccddddbbaa#", +"#aabbccddddbbaa#", +"#aabeecddddbbaa#", +"#aabcecddddbbaa#", +"#aabccedddcbbaa#", +"#aabbbbbbbbbbaa#", +"#aaaaaaaaaaaaaa#", +"#aaaaaaaaaaaaaa#", +".##############."}; diff --git a/src/xpm/hospital.xpm b/src/xpm/hospital.xpm new file mode 100644 index 00000000..44ac2740 --- /dev/null +++ b/src/xpm/hospital.xpm @@ -0,0 +1,24 @@ +/* XPM */ +static char *hospital[]={ +"16 16 5 1", +". c None", +"a c #0000ff", +"c c #e32b2b", +"b c #fdfefe", +"# c #ffffff", +".##############.", +"#aaaaaaaaaaaaaa#", +"#aaaaaaaaaaaaaa#", +"#aabbbb###bbbaa#", +"#aabbb#cc#bbbaa#", +"#aabbb#cc##bbaa#", +"#aa####cc####aa#", +"#aa#cccccccc#aa#", +"#aa#cccccccc#aa#", +"#aa####cc####aa#", +"#aabbb#cc#bbbaa#", +"#aabbb#cc#bbbaa#", +"#aabbb###bbbbaa#", +"#aaaaaaaaaaaaaa#", +"#aaaaaaaaaaaaaa#", +".##############."}; diff --git a/src/xpm/hotel.xpm b/src/xpm/hotel.xpm new file mode 100644 index 00000000..c371b95a --- /dev/null +++ b/src/xpm/hotel.xpm @@ -0,0 +1,26 @@ +/* XPM */ +static char *hotel[]={ +"16 16 7 1", +". c None", +"b c #000000", +"a c #0000ff", +"d c #555566", +"c c #727283", +"e c #ededef", +"# c #ffffff", +".##############.", +"#aaaaaaaaaaaaaa#", +"#aaaaaaaaaaaaaa#", +"#aa##########aa#", +"#aa#b########aa#", +"#aa#bc#######aa#", +"#aa#bdc####b#aa#", +"#aa#bcdccccb#aa#", +"#aa#bbbbbbbb#aa#", +"#aa#b######b#aa#", +"#aa#e########aa#", +"#aa##########aa#", +"#aa##########aa#", +"#aaaaaaaaaaaaaa#", +"#aaaaaaaaaaaaaa#", +".##############."}; diff --git a/src/xpm/parking.xpm b/src/xpm/parking.xpm new file mode 100644 index 00000000..505ac681 --- /dev/null +++ b/src/xpm/parking.xpm @@ -0,0 +1,24 @@ +/* XPM */ +static char *parking[]={ +"16 16 5 1", +". c None", +"a c #0000ff", +"b c #8080ff", +"c c #f6f6fa", +"# c #ffffff", +".##############.", +"#aaaaaaaaaaaaaa#", +"#aaa######baaaa#", +"#aaa##cccc#baaa#", +"#aaa##aaaab#baa#", +"#aaa##aaaab#baa#", +"#aaa##aaaab#baa#", +"#aaa######cbaaa#", +"#aaa##cc##baaaa#", +"#aaa##aaaaaaaaa#", +"#aaa##aaaaaaaaa#", +"#aaa##aaaaaaaaa#", +"#aaa##aaaaaaaaa#", +"#aaa##aaaaaaaaa#", +"#aaaaaaaaaaaaaa#", +".##############."}; diff --git a/src/xpm/restaurant.xpm b/src/xpm/restaurant.xpm new file mode 100644 index 00000000..730fcc94 --- /dev/null +++ b/src/xpm/restaurant.xpm @@ -0,0 +1,73 @@ +/* XPM */ +static char *tst[]={ +"16 16 54 1", +". c None", +"o c #000000", +"a c #0000ff", +"v c #161717", +"X c #181919", +"V c #191a1a", +"S c #1a1b1b", +"M c #1b1c1c", +"T c #1c1d1d", +"F c #1e1f1f", +"Q c #1f2020", +"L c #212222", +"y c #292a2a", +"G c #2b2c2c", +"Z c #3f3f3f", +"g c #3f4040", +"z c #4d4e4e", +"D c #4e4f4f", +"s c #505050", +"n c #606161", +"A c #6b6c6c", +"E c #6d6d6d", +"r c #6f6f6f", +"t c #6f7070", +"l c #737373", +"w c #7b7b7b", +"h c #7e7e7e", +"P c #7f7f7f", +"W c #818181", +"B c #858686", +"k c #888888", +"K c #8f9090", +"H c #909090", +"q c #919292", +"Y c #929393", +"J c #9a9b9b", +"f c #9c9c9c", +"u c #a8a8a8", +"N c #b1b2b2", +"m c #bfbfbf", +"p c #dedede", +"i c #e8e8e8", +"I c #f3f3f3", +"x c #f8f8f8", +"O c #f9f9f9", +"C c #fafafa", +"U c #fcfcfc", +"e c #fcfcfe", +"c c #fcfdfe", +"b c #fcfdff", +"R c #fdfdfd", +"d c #fdfdff", +"j c #fefefe", +"# c #ffffff", +".##############.", +"#aaaaaaaaaaaaaa#", +"#a#bcddddde#d#a#", +"#a#fghi##jklm#a#", +"#a#nooop#qrst#a#", +"#a#uoovwxyzAB#a#", +"#a#CDovEmFGHj#a#", +"#a##IJKLMNO###a#", +"#a####PQFPR###a#", +"#a##jPSmmTPU##a#", +"#a#RPVP##PMPC#a#", +"#a#WXY####uVP#a#", +"#a#oPj#####Po#a#", +"#a############a#", +"#PZmaaaaaaaaaaa#", +".##############."}; diff --git a/src/xpm/unknown.xpm b/src/xpm/unknown.xpm new file mode 100644 index 00000000..8f6835f2 --- /dev/null +++ b/src/xpm/unknown.xpm @@ -0,0 +1,24 @@ +/* XPM */ +static char *noname[] = { +/* width height ncolors chars_per_pixel */ +"13 14 3 1", +/* colors */ +" c yellow", +". c blue", +"X c None", +/* pixels */ +" ", +" ........... ", +" ... ... ", +" .. ..... .. ", +" ........ .. ", +" ........ .. ", +" ...... ... ", +" ..... ..... ", +" ..... ..... ", +" ........... ", +" ..... ..... ", +" ........... ", +" ........... ", +" " +}; |