Merge with modular_map
authormartin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220>
Wed, 4 Jul 2007 22:44:46 +0000 (22:44 +0000)
committermartin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220>
Wed, 4 Jul 2007 22:44:46 +0000 (22:44 +0000)
git-svn-id: https://navit.svn.sourceforge.net/svnroot/navit/trunk/navit@255 ffa7fe5e-494d-0410-b361-a75ebd5db220

128 files changed:
Makefile.am
Makefile.inc [new file with mode: 0644]
configure.in
src/Makefile.am
src/action.h [deleted file]
src/attr.c [new file with mode: 0644]
src/attr.h [new file with mode: 0644]
src/attr_def.h [new file with mode: 0644]
src/callback.c [new file with mode: 0644]
src/callback.h [new file with mode: 0644]
src/color.h [new file with mode: 0644]
src/command.c [deleted file]
src/command.h [deleted file]
src/compass.c
src/coord.c
src/coord.h
src/country.c
src/country.h
src/cursor.c
src/cursor.h
src/data.h
src/data/Makefile.am [new file with mode: 0644]
src/data/garmin_img/Makefile.am [new file with mode: 0644]
src/data/garmin_img/garmin_img.c [new file with mode: 0644]
src/data/mg/Makefile.am [new file with mode: 0644]
src/data/mg/block.c [new file with mode: 0644]
src/data/mg/map.c [new file with mode: 0644]
src/data/mg/mg.h [new file with mode: 0644]
src/data/mg/poly.c [new file with mode: 0644]
src/data/mg/street.c [new file with mode: 0644]
src/data/mg/town.c [new file with mode: 0644]
src/data/mg/tree.c [new file with mode: 0644]
src/data/textfile/Makefile.am [new file with mode: 0644]
src/data/textfile/textfile.c [new file with mode: 0644]
src/data/textfile/textfile.h [new file with mode: 0644]
src/data_window.c
src/debug.c
src/debug.h
src/destination.h
src/display.h [deleted file]
src/fib-1.1/fib.c
src/file.c
src/file.h
src/graphics.c
src/graphics.h
src/graphics/Makefile.am
src/graphics/gtk_drawing_area/Makefile.am
src/graphics/gtk_drawing_area/graphics_gtk_drawing_area.c
src/graphics/null/Makefile.am [new file with mode: 0644]
src/graphics/null/graphics_null.c [new file with mode: 0644]
src/graphics/opengl/Makefile.am [new file with mode: 0644]
src/graphics/opengl/graphics_opengl.c [new file with mode: 0644]
src/gui.c [new file with mode: 0644]
src/gui.h [new file with mode: 0644]
src/gui/Makefile.am
src/gui/gtk/Makefile.am
src/gui/gtk/destination.c [new file with mode: 0644]
src/gui/gtk/gtkeyboard.c [deleted file]
src/gui/gtk/gtkeyboard.h [deleted file]
src/gui/gtk/gui_gtk.h
src/gui/gtk/gui_gtk_action.c
src/gui/gtk/gui_gtk_menu.c [deleted file]
src/gui/gtk/gui_gtk_statusbar.c
src/gui/gtk/gui_gtk_toolbar.c [deleted file]
src/gui/gtk/gui_gtk_window.c
src/gui/sdl/Makefile.am [new file with mode: 0644]
src/gui/sdl/gui_sdl.h [new file with mode: 0644]
src/gui/sdl/gui_sdl_window.cpp [new file with mode: 0644]
src/gui/sdl/sdl_events.cpp [new file with mode: 0644]
src/gui/sdl/sdl_events.h [new file with mode: 0644]
src/item.c [new file with mode: 0644]
src/item.h [new file with mode: 0644]
src/item_def.h [new file with mode: 0644]
src/layer.h [new file with mode: 0644]
src/layout.c [new file with mode: 0644]
src/layout.h [new file with mode: 0644]
src/main.c
src/map.c [new file with mode: 0644]
src/map.h
src/mapset.c [new file with mode: 0644]
src/mapset.h [new file with mode: 0644]
src/maptype.c [new file with mode: 0644]
src/maptype.h [new file with mode: 0644]
src/menu.c
src/menu.h
src/navigation.c
src/navigation.h
src/navit.c [new file with mode: 0644]
src/navit.h [new file with mode: 0644]
src/navit.xml [new file with mode: 0644]
src/phrase.c
src/plugin.c
src/plugin.h
src/plugin_def.h [new file with mode: 0644]
src/popup.c
src/popup.h
src/profile.c
src/profile.h
src/projection.h [new file with mode: 0644]
src/python.c [new file with mode: 0644]
src/python.h [new file with mode: 0644]
src/route.c
src/route.h
src/script/get_map
src/search.c
src/search.h
src/statusbar.h
src/street.c
src/street_name.c
src/track.c
src/track.h
src/transform.c
src/transform.h
src/tree.h [deleted file]
src/util.c
src/vehicle.c
src/vehicle.h
src/xmlconfig.c [new file with mode: 0644]
src/xmlconfig.h [new file with mode: 0644]
src/xpm/Makefile.am [new file with mode: 0644]
src/xpm/camping.xpm [new file with mode: 0644]
src/xpm/car_dealer.xpm [new file with mode: 0644]
src/xpm/fuel.xpm [new file with mode: 0644]
src/xpm/hospital.xpm [new file with mode: 0644]
src/xpm/hotel.xpm [new file with mode: 0644]
src/xpm/parking.xpm [new file with mode: 0644]
src/xpm/restaurant.xpm [new file with mode: 0644]
src/xpm/unknown.xpm [new file with mode: 0644]

index 1bfdcf4..43860cd 100644 (file)
@@ -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 (file)
index 0000000..a5102f1
--- /dev/null
@@ -0,0 +1,2 @@
+plugindir=$(pkglibdir)/plugins
+xpmdir=$(pkglibdir)/xpm
index 090145b..abd30fe 100644 (file)
@@ -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
 ])
index fb2fad6..f198c09 100644 (file)
@@ -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 (file)
index ed64fd5..0000000
+++ /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 (file)
index 0000000..0c6d58a
--- /dev/null
@@ -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 (file)
index 0000000..83a12f5
--- /dev/null
@@ -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 (file)
index 0000000..1a2d472
--- /dev/null
@@ -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 (file)
index 0000000..9a4cad9
--- /dev/null
@@ -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 (file)
index 0000000..6719faa
--- /dev/null
@@ -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 (file)
index 0000000..9fdfd3b
--- /dev/null
@@ -0,0 +1,3 @@
+struct color {
+       int r,g,b;
+};
diff --git a/src/command.c b/src/command.c
deleted file mode 100644 (file)
index ba46316..0000000
+++ /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 (file)
index 5082fa0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-void command_goto(struct container *co, const char *arg);
index 4daa430..dff312e 100644 (file)
@@ -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
index 7ccc8e2..6f22a8d 100644 (file)
@@ -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;
+}
+
 /** @} */
index 550c032..13491d2 100644 (file)
@@ -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
index 4f3a5d0..9d49ef5 100644 (file)
@@ -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);
 }
index 616a6c2..83be5b9 100644 (file)
@@ -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);
index d126f68..933a834 100644 (file)
@@ -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;
+}
+
+
index eeb6306..df15168 100644 (file)
@@ -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);
index 61a9e00..e2af6f9 100644 (file)
@@ -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 (file)
index 0000000..35a1135
--- /dev/null
@@ -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 (file)
index 0000000..7fb8432
--- /dev/null
@@ -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 (file)
index 0000000..86b03ca
--- /dev/null
@@ -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 (file)
index 0000000..65f0157
--- /dev/null
@@ -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 (file)
index 0000000..93c2fb1
--- /dev/null
@@ -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 (file)
index 0000000..20feb8f
--- /dev/null
@@ -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 (file)
index 0000000..696fd55
--- /dev/null
@@ -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 (file)
index 0000000..b19aeed
--- /dev/null
@@ -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 (file)
index 0000000..550e500
--- /dev/null
@@ -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 (file)
index 0000000..838bc2c
--- /dev/null
@@ -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 (file)
index 0000000..aedce72
--- /dev/null
@@ -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 (file)
index 0000000..9285072
--- /dev/null
@@ -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 (file)
index 0000000..e5c3497
--- /dev/null
@@ -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 (file)
index 0000000..980c95d
--- /dev/null
@@ -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;
+};
+
index 1eff89d..9988948 100644 (file)
@@ -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
 }
index 5fbe603..62a9335 100644 (file)
@@ -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);
+       }
 }
index fb9abbc..69ced33 100644 (file)
@@ -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, ...);
index 68530f8..263cc92 100644 (file)
@@ -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 (file)
index 952381f..0000000
+++ /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);
index ace5d12..276b6bd 100644 (file)
@@ -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);
index b097261..e0ca0c2 100644 (file)
@@ -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)
 {
index f020ee4..615e22b 100644 (file)
@@ -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 */
index ad430c6..b922299 100644 (file)
 #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);
 }
index a73f1e1..f514565 100644 (file)
-
+#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
index b5787ee..87d68de 100644 (file)
@@ -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
index 376b888..5b8b944 100644 (file)
@@ -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
index a1d18c3..5fe34d4 100644 (file)
@@ -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 (file)
index 0000000..8b22bdb
--- /dev/null
@@ -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 (file)
index 0000000..2d8bb30
--- /dev/null
@@ -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 (file)
index 0000000..99023e3
--- /dev/null
@@ -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 (file)
index 0000000..81c8cd4
--- /dev/null
@@ -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 (file)
index 0000000..f47856e
--- /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 (file)
index 0000000..1131690
--- /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 */
index 126d10a..e0e3a22 100644 (file)
@@ -1 +1,8 @@
-SUBDIRS=gtk
+SUBDIRS=
+if GUI_GTK
+  SUBDIRS += gtk
+endif
+if GUI_SDL
+  SUBDIRS += sdl
+endif
+
index d5ffe2f..9b8d907 100644 (file)
@@ -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 (file)
index 0000000..5ef6e7f
--- /dev/null
@@ -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 (file)
index 58f929b..0000000
+++ /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 (file)
index fef9fa7..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-int init_keyboard_stuff(char *input);
-GtkWidget *build_keyboard(GtkWidget * input, char *filename);
-gint track_focus(gpointer data);
index 6c7792f..1b968ef 100644 (file)
@@ -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);
 
index b8386cb..d1867be 100644 (file)
 #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 (file)
index 6f6b22b..0000000
+++ /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;
-}
index 1095029..b31b8dd 100644 (file)
@@ -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 (file)
index ec27b74..0000000
+++ /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;
-}
index f080bbd..663cbcc 100644 (file)
 #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 (file)
index 0000000..d8be2a3
--- /dev/null
@@ -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 (file)
index 0000000..1519084
--- /dev/null
@@ -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 (file)
index 0000000..818e517
--- /dev/null
@@ -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 (file)
index 0000000..0d83acf
--- /dev/null
@@ -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 (file)
index 0000000..1f475f0
--- /dev/null
@@ -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 (file)
index 0000000..4db0be7
--- /dev/null
@@ -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 (file)
index 0000000..00a8b3a
--- /dev/null
@@ -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 (file)
index 0000000..755497d
--- /dev/null
@@ -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 (file)
index 0000000..3415cf9
--- /dev/null
@@ -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 (file)
index 0000000..0ca3359
--- /dev/null
@@ -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 (file)
index 0000000..ed96838
--- /dev/null
@@ -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);
index d68d311..db91ef8 100644 (file)
@@ -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 (file)
index 0000000..b5f991e
--- /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);
+}
index 2ffa914..7f33057 100644 (file)
--- a/src/map.h
+++ b/src/map.h
-/*
- * 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 (file)
index 0000000..17fbecf
--- /dev/null
@@ -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 (file)
index 0000000..6998486
--- /dev/null
@@ -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 (file)
index 0000000..8103961
--- /dev/null
@@ -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 (file)
index 0000000..1a41da5
--- /dev/null
@@ -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);
index 5430b00..d774575 100644 (file)
@@ -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);
 }
index 51b2472..8f40fbc 100644 (file)
@@ -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);
index c6a7e3e..20125be 100644 (file)
-#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);
+}
index c8c1c39..aa80e6c 100644 (file)
@@ -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 (file)
index 0000000..04b22eb
--- /dev/null
@@ -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 (file)
index 0000000..234391b
--- /dev/null
@@ -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 (file)
index 0000000..2339d15
--- /dev/null
@@ -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>
+-->
index 761de5a..b3fef2a 100644 (file)
@@ -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
 
 }
index e7edfe4..65db797 100644 (file)
-#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;
 }
index 84e0845..d6e7c17 100644 (file)
@@ -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 (file)
index 0000000..4108a78
--- /dev/null
@@ -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)) 
index bf6fea0..4d1c812 100644 (file)
@@ -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);
 }
-
-
index 989d515..13be980 100644 (file)
@@ -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);
index b941747..c8ea537 100644 (file)
@@ -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);
 }
index 5028035..0a548d6 100644 (file)
@@ -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 (file)
index 0000000..9d73f1b
--- /dev/null
@@ -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 (file)
index 0000000..4b85beb
--- /dev/null
@@ -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 (file)
index 0000000..9829b13
--- /dev/null
@@ -0,0 +1,2 @@
+void python_init(void);
+
index 8907a54..aa239e7 100644 (file)
 #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
index 33fcdb5..6cceae8 100644 (file)
@@ -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);
index 20de37d..7c8ef97 100755 (executable)
@@ -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 &
index 0d2f17b..8cb2a8d 100644 (file)
 #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_);
 }
index 88f3882..0a09494 100644 (file)
@@ -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
index 1b9092c..1411ef7 100644 (file)
@@ -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 */
index 8633224..1880e12 100644 (file)
@@ -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);
+}
+
index cecc62a..1e8da63 100644 (file)
@@ -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);
index 2f86165..295e2ab 100644 (file)
@@ -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"
 #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;
 }
index 2b435e0..90073a5 100644 (file)
@@ -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);
index 859e0e5..abf9c35 100644 (file)
@@ -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
 */
 
 
-
index f2099d2..6c9059e 100644 (file)
@@ -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 (file)
index 58ff044..0000000
+++ /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);
index 7f77ca2..44643d4 100644 (file)
@@ -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;
+}
index 747ffff..c81f4d4 100644 (file)
@@ -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);
 }
index aa028c4..46cf430 100644 (file)
@@ -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 (file)
index 0000000..dadbb4d
--- /dev/null
@@ -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 (file)
index 0000000..036eab5
--- /dev/null
@@ -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 (file)
index 0000000..786803d
--- /dev/null
@@ -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 (file)
index 0000000..86ff7d4
--- /dev/null
@@ -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 (file)
index 0000000..892f10b
--- /dev/null
@@ -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 (file)
index 0000000..7b9f5f8
--- /dev/null
@@ -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 (file)
index 0000000..44ac274
--- /dev/null
@@ -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 (file)
index 0000000..c371b95
--- /dev/null
@@ -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 (file)
index 0000000..505ac68
--- /dev/null
@@ -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 (file)
index 0000000..730fcc9
--- /dev/null
@@ -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 (file)
index 0000000..8f6835f
--- /dev/null
@@ -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 */
+"             ",
+" ........... ",
+" ...     ... ",
+" .. ..... .. ",
+" ........ .. ",
+" ........ .. ",
+" ......  ... ",
+" ..... ..... ",
+" ..... ..... ",
+" ........... ",
+" ..... ..... ",
+" ........... ",
+" ........... ",
+"             "
+};