summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormartin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220>2007-07-04 22:44:46 +0000
committermartin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220>2007-07-04 22:44:46 +0000
commitc7efe5c02b4d6ac162f348e48a57451596fa5e32 (patch)
treec0b1ca6d58a3f8668d070ab65a967c34c2e7b6ef
parentc5a5ad0f86737b3d34dcd4345f048961eb6bc6d0 (diff)
downloadnavit-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
-rw-r--r--Makefile.am4
-rw-r--r--Makefile.inc2
-rw-r--r--configure.in155
-rw-r--r--src/Makefile.am31
-rw-r--r--src/action.h3
-rw-r--r--src/attr.c40
-rw-r--r--src/attr.h24
-rw-r--r--src/attr_def.h37
-rw-r--r--src/callback.c112
-rw-r--r--src/callback.h15
-rw-r--r--src/color.h3
-rw-r--r--src/command.c147
-rw-r--r--src/command.h1
-rw-r--r--src/compass.c7
-rw-r--r--src/coord.c176
-rw-r--r--src/coord.h22
-rw-r--r--src/country.c204
-rw-r--r--src/country.h19
-rw-r--r--src/cursor.c140
-rw-r--r--src/cursor.h15
-rw-r--r--src/data.h47
-rw-r--r--src/data/Makefile.am1
-rw-r--r--src/data/garmin_img/Makefile.am4
-rw-r--r--src/data/garmin_img/garmin_img.c1486
-rw-r--r--src/data/mg/Makefile.am4
-rw-r--r--src/data/mg/block.c261
-rw-r--r--src/data/mg/map.c296
-rw-r--r--src/data/mg/mg.h286
-rw-r--r--src/data/mg/poly.c196
-rw-r--r--src/data/mg/street.c702
-rw-r--r--src/data/mg/town.c261
-rw-r--r--src/data/mg/tree.c232
-rw-r--r--src/data/textfile/Makefile.am4
-rw-r--r--src/data/textfile/textfile.c355
-rw-r--r--src/data/textfile/textfile.h28
-rw-r--r--src/data_window.c35
-rw-r--r--src/debug.c52
-rw-r--r--src/debug.h7
-rw-r--r--src/destination.h15
-rw-r--r--src/display.h24
-rw-r--r--src/fib-1.1/fib.c5
-rw-r--r--src/file.c42
-rw-r--r--src/file.h20
-rw-r--r--src/graphics.c996
-rw-r--r--src/graphics.h151
-rw-r--r--src/graphics/Makefile.am8
-rw-r--r--src/graphics/gtk_drawing_area/Makefile.am15
-rw-r--r--src/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c524
-rw-r--r--src/graphics/null/Makefile.am4
-rw-r--r--src/graphics/null/graphics_null.c217
-rw-r--r--src/graphics/opengl/Makefile.am4
-rw-r--r--src/graphics/opengl/graphics_opengl.c927
-rw-r--r--src/gui.c106
-rw-r--r--src/gui.h36
-rw-r--r--src/gui/Makefile.am9
-rw-r--r--src/gui/gtk/Makefile.am15
-rw-r--r--src/gui/gtk/destination.c369
-rw-r--r--src/gui/gtk/gtkeyboard.c2350
-rw-r--r--src/gui/gtk/gtkeyboard.h3
-rw-r--r--src/gui/gtk/gui_gtk.h23
-rw-r--r--src/gui/gtk/gui_gtk_action.c289
-rw-r--r--src/gui/gtk/gui_gtk_menu.c364
-rw-r--r--src/gui/gtk/gui_gtk_statusbar.c80
-rw-r--r--src/gui/gtk/gui_gtk_toolbar.c340
-rw-r--r--src/gui/gtk/gui_gtk_window.c153
-rw-r--r--src/gui/sdl/Makefile.am5
-rw-r--r--src/gui/sdl/gui_sdl.h23
-rw-r--r--src/gui/sdl/gui_sdl_window.cpp684
-rw-r--r--src/gui/sdl/sdl_events.cpp771
-rw-r--r--src/gui/sdl/sdl_events.h32
-rw-r--r--src/item.c132
-rw-r--r--src/item.h50
-rw-r--r--src/item_def.h131
-rw-r--r--src/layer.h6
-rw-r--r--src/layout.c131
-rw-r--r--src/layout.h59
-rw-r--r--src/main.c141
-rw-r--r--src/map.c197
-rw-r--r--src/map.h385
-rw-r--r--src/mapset.c116
-rw-r--r--src/mapset.h16
-rw-r--r--src/maptype.c29
-rw-r--r--src/maptype.h15
-rw-r--r--src/menu.c50
-rw-r--r--src/menu.h23
-rw-r--r--src/navigation.c574
-rw-r--r--src/navigation.h28
-rw-r--r--src/navit.c465
-rw-r--r--src/navit.h43
-rw-r--r--src/navit.xml477
-rw-r--r--src/phrase.c5
-rw-r--r--src/plugin.c200
-rw-r--r--src/plugin.h76
-rw-r--r--src/plugin_def.h7
-rw-r--r--src/popup.c374
-rw-r--r--src/popup.h25
-rw-r--r--src/profile.c36
-rw-r--r--src/profile.h9
-rw-r--r--src/projection.h3
-rw-r--r--src/python.c281
-rw-r--r--src/python.h2
-rw-r--r--src/route.c1589
-rw-r--r--src/route.h78
-rwxr-xr-xsrc/script/get_map2
-rw-r--r--src/search.c606
-rw-r--r--src/search.h63
-rw-r--r--src/statusbar.h20
-rw-r--r--src/street.c46
-rw-r--r--src/street_name.c6
-rw-r--r--src/track.c240
-rw-r--r--src/track.h12
-rw-r--r--src/transform.c391
-rw-r--r--src/transform.h72
-rw-r--r--src/tree.h13
-rw-r--r--src/util.c17
-rw-r--r--src/vehicle.c346
-rw-r--r--src/vehicle.h19
-rw-r--r--src/xmlconfig.c534
-rw-r--r--src/xmlconfig.h3
-rw-r--r--src/xpm/Makefile.am3
-rw-r--r--src/xpm/camping.xpm24
-rw-r--r--src/xpm/car_dealer.xpm26
-rw-r--r--src/xpm/fuel.xpm26
-rw-r--r--src/xpm/hospital.xpm24
-rw-r--r--src/xpm/hotel.xpm26
-rw-r--r--src/xpm/parking.xpm24
-rw-r--r--src/xpm/restaurant.xpm73
-rw-r--r--src/xpm/unknown.xpm24
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);
diff --git a/src/data.h b/src/data.h
index 61a9e007..e2af6f96 100644
--- a/src/data.h
+++ b/src/data.h
@@ -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);
diff --git a/src/file.c b/src/file.c
index b097261a..e0ca0c21 100644
--- a/src/file.c
+++ b/src/file.c
@@ -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)
{
diff --git a/src/file.h b/src/file.h
index f020ee47..615e22b7 100644
--- a/src/file.h
+++ b/src/file.h
@@ -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, &lt);
+ 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);
diff --git a/src/main.c b/src/main.c
index d68d3119..db91ef88 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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);
+}
diff --git a/src/map.h b/src/map.h
index 2ffa914b..7f330576 100644
--- a/src/map.h
+++ b/src/map.h
@@ -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);
diff --git a/src/menu.c b/src/menu.c
index 5430b007..d7745751 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -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);
}
diff --git a/src/menu.h b/src/menu.h
index 51b24729..8f40fbc4 100644
--- a/src/menu.h
+++ b/src/menu.h
@@ -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);
diff --git a/src/util.c b/src/util.c
index 7f77ca28..44643d4f 100644
--- a/src/util.c
+++ b/src/util.c
@@ -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 */
+" ",
+" ........... ",
+" ... ... ",
+" .. ..... .. ",
+" ........ .. ",
+" ........ .. ",
+" ...... ... ",
+" ..... ..... ",
+" ..... ..... ",
+" ........... ",
+" ..... ..... ",
+" ........... ",
+" ........... ",
+" "
+};