[jstest-gtk] 01/06: New upstream version 0.1.1~git20160825

Stephen Kitt skitt at moszumanska.debian.org
Mon Dec 12 22:11:21 UTC 2016


This is an automated email from the git hooks/post-receive script.

skitt pushed a commit to branch master
in repository jstest-gtk.

commit 3a1752ee57c3c3e6e3b9e39bd954b059825b5699
Author: Stephen Kitt <steve at sk2.org>
Date:   Mon Dec 12 22:35:02 2016 +0100

    New upstream version 0.1.1~git20160825
---
 CMakeLists.txt                      |  74 ++++
 README => README.md                 |  57 +--
 SConstruct                          |  39 --
 TODO                                |  20 +-
 data/PS3.png                        | Bin 0 -> 5285 bytes
 external/binreloc-2.0/binreloc.c    | 766 ++++++++++++++++++++++++++++++++++++
 external/binreloc-2.0/binreloc.h    |  80 ++++
 src/axis_widget.cpp                 |  84 ++--
 src/axis_widget.hpp                 |   4 +-
 src/button_widget.cpp               |  46 +--
 src/button_widget.hpp               |   4 +-
 src/calibrate_maximum_dialog.cpp    |  88 ++---
 src/calibrate_maximum_dialog.hpp    |   4 +-
 src/evdev_helper.cpp                | 192 ++++-----
 src/evdev_helper.hpp                |   2 +-
 src/joystick.cpp                    | 522 ++++++++++--------------
 src/joystick.hpp                    |   8 +-
 src/joystick_calibration_widget.cpp | 131 +++---
 src/joystick_calibration_widget.hpp |   6 +-
 src/joystick_configuration.cpp      |  36 --
 src/joystick_configuration.hpp      |  48 ---
 src/joystick_description.hpp        |   6 +-
 src/joystick_list_widget.cpp        |  70 ++--
 src/joystick_list_widget.hpp        |   4 +-
 src/joystick_map_widget.cpp         |  38 +-
 src/joystick_map_widget.hpp         |   4 +-
 src/joystick_test_widget.cpp        | 326 +++++++--------
 src/joystick_test_widget.hpp        |  22 +-
 src/jscfg.cpp                       |  41 --
 src/main.cpp                        | 234 +++++------
 src/main.hpp                        |  10 +-
 src/remap_widget.cpp                |  73 ++--
 src/remap_widget.hpp                |  14 +-
 src/rudder_widget.cpp               |  58 +--
 src/rudder_widget.hpp               |   4 +-
 src/throttle_widget.cpp             |  46 +--
 src/throttle_widget.hpp             |   4 +-
 src/xml_parser.cpp                  | 178 ---------
 src/xml_parser.hpp                  | 141 -------
 src/xml_reader.cpp                  | 137 -------
 src/xml_reader.hpp                  |  50 ---
 src/xml_writer.cpp                  |  88 -----
 src/xml_writer.hpp                  |  48 ---
 43 files changed, 1896 insertions(+), 1911 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..2fefa54
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,74 @@
+# jstest-gtk - A graphical joystick tester
+# Copyright (C) 2015 Ingo Ruhnke <grumbel at gmx.de>
+#
+# 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 3 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 General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+cmake_minimum_required(VERSION 2.8)
+project(jstest-gtk)
+
+option(WARNINGS "Switch on extra warnings" OFF)
+option(WERROR "Turn warnings into errors" OFF)
+
+if(WARNINGS)
+  set(WARNINGS_CXX_FLAGS ${WARNINGS_CXX_FLAGS}
+    -Wall -Wextra
+    -pedantic -Wno-c++0x-compat -Wnon-virtual-dtor
+    -Wcast-qual -Winit-self -Wno-unused-parameter
+    # -Wconversion -Wshadow -Weffc++
+    )
+endif()
+
+if(WERROR)
+  set(WARNINGS_CXX_FLAGS ${WARNINGS_CXX_FLAGS}
+    -Werror)
+endif()
+
+include(CheckCXXCompilerFlag)
+CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
+CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
+
+if(COMPILER_SUPPORTS_CXX11)
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+elseif(COMPILER_SUPPORTS_CXX0X)
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
+endif()
+
+find_package(PkgConfig REQUIRED)
+pkg_search_module(GTKMM REQUIRED gtkmm-2.4)
+pkg_search_module(SIGCPP REQUIRED sigc++-2.0)
+pkg_search_module(X11 REQUIRED x11)
+
+add_library(binreloc STATIC ${CMAKE_CURRENT_SOURCE_DIR}/external/binreloc-2.0/binreloc.c)
+set_property(TARGET binreloc PROPERTY COMPILE_DEFINITIONS ENABLE_BINRELOC)
+
+file(GLOB JSTEST_GTK_SOURCES src/*.cpp)
+
+add_executable(jstest-gtk ${JSTEST_GTK_SOURCES})
+include_directories(
+  ${CMAKE_CURRENT_SOURCE_DIR}/external/binreloc-2.0/
+  ${GTKMM_INCLUDE_DIRS}
+  ${SIGCPP_INCLUDE_DIRS}
+  ${X11_INCLUDE_DIRS})
+set_property(TARGET jstest-gtk PROPERTY COMPILE_OPTIONS
+  ${GTKMM_CFLAGS_OTHER}
+  ${SIGCPP_CFLAGS_OTHER}
+  ${X11_CFLAGS_OTHER}
+  ${WARNINGS_CXX_FLAGS})
+target_link_libraries(jstest-gtk
+  binreloc
+  ${GTKMM_LIBRARIES}
+  ${SIGCPP_LIBRARIES}
+  ${X11_LIBRARIES})
+
+# EOF #
diff --git a/README b/README.md
similarity index 70%
rename from README
rename to README.md
index 72ab2d6..153a5c8 100644
--- a/README
+++ b/README.md
@@ -1,5 +1,7 @@
-[[ jstest-gtk ]]
-================
+[![Build Status](https://travis-ci.org/Grumbel/jstest-gtk.svg?branch=master)](https://travis-ci.org/Grumbel/jstest-gtk)
+
+jstest-gtk
+==========
 
 jstest-gtk is a simple joystick tester based on Gtk+. It provides you
 with a list of attached joysticks, a way to display which buttons and
@@ -10,37 +12,39 @@ You can find the latest version at:
 
  * http://github.com/Grumbel/jstest-gtk/tree/master
 
-Questions, comments and bug reporst can be given to:
+Questions, comments and bug reports can be given to:
 
  * Ingo Ruhnke <grumbel at gmx.de>
 
 
-[[ Compiling ]]
-===============
+Compiling
+---------
 
 Make sure you have the following pieces of software installed (they
 are part of most distributions):
 
- * scons
+ * cmake
  * sigc++
  * gtkmm
- * exapt
 
 You can compile it by typing:
 
- $ scons
+    $ mkdir build
+    $ cd build
+    $ cmake ..
+    $ make
 
 
-[[ Usage ]]
-===========
+Usage
+-----
 
 Once compiled you can start jstest-gtk with:
 
- $ ./jstest-gtk
+    $ ./jstest-gtk
 
 or if you know the device you want to test with:
 
- $ ./jstest-gtk /dev/input/js0
+    $ ./jstest-gtk /dev/input/js0
 
 The main window will provide you with a list of currently available
 joysticks. When you double click a joystick it will display the Test
@@ -60,8 +64,8 @@ give it a far bigger deadzone then needed, thus reducing your ability
 for fine movements.
 
 
-[[ SDL Notes ]]
-===============
+SDL Notes
+---------
 
 Depending on what version and what compilation flags where used, your
 version of SDL might not use the joystick interface at all, but
@@ -72,8 +76,8 @@ the joystick interface, not evdev.
 To work around that you have to set an environment variable that
 forces SDL to use the joystick device:
 
- $ SDL_JOYSTICK_DEVICE="/dev/input/js0"
- $ export SDL_JOYSTICK_DEVICE
+    $ SDL_JOYSTICK_DEVICE="/dev/input/js0"
+    $ export SDL_JOYSTICK_DEVICE
 
 When you need two or more joysticks this will not work and you might
 need to recompile SDL and disable the evdev support.
@@ -82,16 +86,13 @@ More info can be found at:
 
  * ftp://ptah.lnf.kth.se/pub/misc/sdl-env-vars
 
-SDL_LINUX_JOYSTICK
-	Special joystick configuration string for linux. The format is
-	"name numaxes numhats numballs"
-	where name is the name string of the joystick (possibly in single
-	quotes), and the rest are the number of axes, hats and balls
-	respectively.
-
-SDL_JOYSTICK_DEVICE
-	Joystick device to use in the linux joystick driver, in addition
-	to the usual: /dev/js*, /dev/input/event*, /dev/input/js*
-
+`SDL_LINUX_JOYSTICK`:
+  Special joystick configuration string for linux. The format is
+  `name numaxes numhats numballs`
+  where name is the name string of the joystick (possibly in single
+  quotes), and the rest are the number of axes, hats and balls
+  respectively.
 
-# EOF #
+`SDL_JOYSTICK_DEVICE`:
+  Joystick device to use in the linux joystick driver, in addition to
+  the usual: `/dev/js*`, `/dev/input/event*`, `/dev/input/js*`
diff --git a/SConstruct b/SConstruct
deleted file mode 100644
index 2ed5c66..0000000
--- a/SConstruct
+++ /dev/null
@@ -1,39 +0,0 @@
-##  -*- python -*-
-##  jstest-gtk - A graphical joystick tester
-##  Copyright (C) 2009 Ingo Ruhnke <grumbel at gmx.de>
-##
-##  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 3 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 General Public License
-##  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-env = Environment(CXXFLAGS=["-g", "-Wall", "-Werror"])
-env.ParseConfig('pkg-config --cflags --libs gtkmm-2.4 sigc++-2.0 expat x11')
-env.Program('jstest-gtk', [
-    'src/axis_widget.cpp',
-    'src/button_widget.cpp',
-    'src/throttle_widget.cpp',
-    'src/rudder_widget.cpp',
-    'src/xml_writer.cpp',
-    'src/xml_reader.cpp',
-    'src/xml_parser.cpp',
-    'src/joystick_list_widget.cpp',
-    'src/joystick_test_widget.cpp',
-    'src/joystick_calibration_widget.cpp',
-    'src/joystick_map_widget.cpp',
-    'src/joystick.cpp',
-    'src/calibrate_maximum_dialog.cpp',
-    'src/remap_widget.cpp',
-    'src/evdev_helper.cpp',
-    'src/main.cpp'
-    ])
-    
-# EOF #
diff --git a/TODO b/TODO
index 43a7f2d..a960d07 100644
--- a/TODO
+++ b/TODO
@@ -5,7 +5,7 @@ Pre Release Testing:
 
 VERSION="0.1.0"
 TAG="v${VERSION}"
-git tag -s  "${TAG}" -m "jstest-gtk ${TAG}" 
+git tag -s  "${TAG}" -m "jstest-gtk ${TAG}"
 git archive --format=tar --prefix="jstest-gtk-${VERSION}/" ${TAG} | bzip2 -c > /tmp/jstest-gtk-${VERSION}.tar.bz2
 git push --tags
 

@@ -13,6 +13,18 @@ git push --tags
 [[ TODO ]]
 ==========
 
+* add ability to plot axis values into a dynamic 2d graph (good for seeing steps/noise)
+
+* use libudev for automatic detection of newly plugged in joysticks
+  (would allow getting the correct evdev and doing proper reset of
+  joystick calibration values without replug)
+
+* axis mapping seems to behave broken
+
+* grey out Properties when no joystick is present in the list
+
+* Refresh doesn't work (can't find images)
+
 * display "No joystick found" when no joystick is available
 
 * [  Save Profile         ]
@@ -98,7 +110,7 @@ git push --tags
 * jscal:
 
 # Remove any calibration and report raw USB data
-jsscal -s 6,0,0,0,0,0,0,0,0,0,0,0,0 /dev/input/js0 
+jsscal -s 6,0,0,0,0,0,0,0,0,0,0,0,0 /dev/input/js0
 
 jscal -s
 6, // number of axes
@@ -148,14 +160,14 @@ Apply coef:
 ===========
 
   if (value > corr->coef[0])
-    { 
+    {
       if (value < corr->coef[1])
         {
           value = 0;
         }
       else
         {
-          value = (corr->coef[3] * (value - corr->coef[1])) / 16384; 
+          value = (corr->coef[3] * (value - corr->coef[1])) / 16384;
         }
     }
   else
diff --git a/data/PS3.png b/data/PS3.png
new file mode 100644
index 0000000..d6a1bd5
Binary files /dev/null and b/data/PS3.png differ
diff --git a/external/binreloc-2.0/binreloc.c b/external/binreloc-2.0/binreloc.c
new file mode 100644
index 0000000..c6dc0ae
--- /dev/null
+++ b/external/binreloc-2.0/binreloc.c
@@ -0,0 +1,766 @@
+/*
+ * BinReloc - a library for creating relocatable executables
+ * Written by: Hongli Lai <h.lai at chello.nl>
+ * http://autopackage.org/
+ *
+ * This source code is public domain. You can relicense this code
+ * under whatever license you want.
+ *
+ * See http://autopackage.org/docs/binreloc/ for
+ * more information and how to use this.
+ */
+
+#ifndef __BINRELOC_C__
+#define __BINRELOC_C__
+
+#ifdef ENABLE_BINRELOC
+	#include <sys/types.h>
+	#include <sys/stat.h>
+	#include <unistd.h>
+#endif /* ENABLE_BINRELOC */
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include "binreloc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+
+/** @internal
+ * Find the canonical filename of the executable. Returns the filename
+ * (which must be freed) or NULL on error. If the parameter 'error' is
+ * not NULL, the error code will be stored there, if an error occured.
+ */
+static char *
+_br_find_exe (BrInitError *error)
+{
+#ifndef ENABLE_BINRELOC
+	if (error)
+		*error = BR_INIT_ERROR_DISABLED;
+	return NULL;
+#else
+	char *path, *path2, *line, *result;
+	size_t buf_size;
+	ssize_t size;
+	struct stat stat_buf;
+	FILE *f;
+
+	/* Read from /proc/self/exe (symlink) */
+	if (sizeof (path) > SSIZE_MAX)
+		buf_size = SSIZE_MAX - 1;
+	else
+		buf_size = PATH_MAX - 1;
+	path = (char *) malloc (buf_size);
+	if (path == NULL) {
+		/* Cannot allocate memory. */
+		if (error)
+			*error = BR_INIT_ERROR_NOMEM;
+		return NULL;
+	}
+	path2 = (char *) malloc (buf_size);
+	if (path2 == NULL) {
+		/* Cannot allocate memory. */
+		if (error)
+			*error = BR_INIT_ERROR_NOMEM;
+		free (path);
+		return NULL;
+	}
+
+	strncpy (path2, "/proc/self/exe", buf_size - 1);
+
+	while (1) {
+		int i;
+
+		size = readlink (path2, path, buf_size - 1);
+		if (size == -1) {
+			/* Error. */
+			free (path2);
+			break;
+		}
+
+		/* readlink() success. */
+		path[size] = '\0';
+
+		/* Check whether the symlink's target is also a symlink.
+		 * We want to get the final target. */
+		i = stat (path, &stat_buf);
+		if (i == -1) {
+			/* Error. */
+			free (path2);
+			break;
+		}
+
+		/* stat() success. */
+		if (!S_ISLNK (stat_buf.st_mode)) {
+			/* path is not a symlink. Done. */
+			free (path2);
+			return path;
+		}
+
+		/* path is a symlink. Continue loop and resolve this. */
+		strncpy (path, path2, buf_size - 1);
+	}
+
+
+	/* readlink() or stat() failed; this can happen when the program is
+	 * running in Valgrind 2.2. Read from /proc/self/maps as fallback. */
+
+	buf_size = PATH_MAX + 128;
+	line = (char *) realloc (path, buf_size);
+	if (line == NULL) {
+		/* Cannot allocate memory. */
+		free (path);
+		if (error)
+			*error = BR_INIT_ERROR_NOMEM;
+		return NULL;
+	}
+
+	f = fopen ("/proc/self/maps", "r");
+	if (f == NULL) {
+		free (line);
+		if (error)
+			*error = BR_INIT_ERROR_OPEN_MAPS;
+		return NULL;
+	}
+
+	/* The first entry should be the executable name. */
+	result = fgets (line, (int) buf_size, f);
+	if (result == NULL) {
+		fclose (f);
+		free (line);
+		if (error)
+			*error = BR_INIT_ERROR_READ_MAPS;
+		return NULL;
+	}
+
+	/* Get rid of newline character. */
+	buf_size = strlen (line);
+	if (buf_size <= 0) {
+		/* Huh? An empty string? */
+		fclose (f);
+		free (line);
+		if (error)
+			*error = BR_INIT_ERROR_INVALID_MAPS;
+		return NULL;
+	}
+	if (line[buf_size - 1] == 10)
+		line[buf_size - 1] = 0;
+
+	/* Extract the filename; it is always an absolute path. */
+	path = strchr (line, '/');
+
+	/* Sanity check. */
+	if (strstr (line, " r-xp ") == NULL || path == NULL) {
+		fclose (f);
+		free (line);
+		if (error)
+			*error = BR_INIT_ERROR_INVALID_MAPS;
+		return NULL;
+	}
+
+	path = strdup (path);
+	free (line);
+	fclose (f);
+	return path;
+#endif /* ENABLE_BINRELOC */
+}
+
+
+/** @internal
+ * Find the canonical filename of the executable which owns symbol.
+ * Returns a filename which must be freed, or NULL on error.
+ */
+static char *
+_br_find_exe_for_symbol (const void *symbol, BrInitError *error)
+{
+#ifndef ENABLE_BINRELOC
+	if (error)
+		*error = BR_INIT_ERROR_DISABLED;
+	return (char *) NULL;
+#else
+	#define SIZE PATH_MAX + 100
+	FILE *f;
+	size_t address_string_len;
+	char *address_string, line[SIZE], *found;
+
+	if (symbol == NULL)
+		return (char *) NULL;
+
+	f = fopen ("/proc/self/maps", "r");
+	if (f == NULL)
+		return (char *) NULL;
+
+	address_string_len = 4;
+	address_string = (char *) malloc (address_string_len);
+	found = (char *) NULL;
+
+	while (!feof (f)) {
+		char *start_addr, *end_addr, *end_addr_end, *file;
+		void *start_addr_p, *end_addr_p;
+		size_t len;
+
+		if (fgets (line, SIZE, f) == NULL)
+			break;
+
+		/* Sanity check. */
+		if (strstr (line, " r-xp ") == NULL || strchr (line, '/') == NULL)
+			continue;
+
+		/* Parse line. */
+		start_addr = line;
+		end_addr = strchr (line, '-');
+		file = strchr (line, '/');
+
+		/* More sanity check. */
+		if (!(file > end_addr && end_addr != NULL && end_addr[0] == '-'))
+			continue;
+
+		end_addr[0] = '\0';
+		end_addr++;
+		end_addr_end = strchr (end_addr, ' ');
+		if (end_addr_end == NULL)
+			continue;
+
+		end_addr_end[0] = '\0';
+		len = strlen (file);
+		if (len == 0)
+			continue;
+		if (file[len - 1] == '\n')
+			file[len - 1] = '\0';
+
+		/* Get rid of "(deleted)" from the filename. */
+		len = strlen (file);
+		if (len > 10 && strcmp (file + len - 10, " (deleted)") == 0)
+			file[len - 10] = '\0';
+
+		/* I don't know whether this can happen but better safe than sorry. */
+		len = strlen (start_addr);
+		if (len != strlen (end_addr))
+			continue;
+
+
+		/* Transform the addresses into a string in the form of 0xdeadbeef,
+		 * then transform that into a pointer. */
+		if (address_string_len < len + 3) {
+			address_string_len = len + 3;
+			address_string = (char *) realloc (address_string, address_string_len);
+		}
+
+		memcpy (address_string, "0x", 2);
+		memcpy (address_string + 2, start_addr, len);
+		address_string[2 + len] = '\0';
+		sscanf (address_string, "%p", &start_addr_p);
+
+		memcpy (address_string, "0x", 2);
+		memcpy (address_string + 2, end_addr, len);
+		address_string[2 + len] = '\0';
+		sscanf (address_string, "%p", &end_addr_p);
+
+
+		if (symbol >= start_addr_p && symbol < end_addr_p) {
+			found = file;
+			break;
+		}
+	}
+
+	free (address_string);
+	fclose (f);
+
+	if (found == NULL)
+		return (char *) NULL;
+	else
+		return strdup (found);
+#endif /* ENABLE_BINRELOC */
+}
+
+
+#ifndef BINRELOC_RUNNING_DOXYGEN
+	#undef NULL
+	#define NULL ((void *) 0) /* typecasted as char* for C++ type safeness */
+#endif
+
+static char *exe = (char *) NULL;
+
+
+/** Initialize the BinReloc library (for applications).
+ *
+ * This function must be called before using any other BinReloc functions.
+ * It attempts to locate the application's canonical filename.
+ *
+ * @note If you want to use BinReloc for a library, then you should call
+ *       br_init_lib() instead.
+ *
+ * @param error  If BinReloc failed to initialize, then the error code will
+ *               be stored in this variable. Set to NULL if you want to
+ *               ignore this. See #BrInitError for a list of error codes.
+ *
+ * @returns 1 on success, 0 if BinReloc failed to initialize.
+ */
+int
+br_init (BrInitError *error)
+{
+	exe = _br_find_exe (error);
+	return exe != NULL;
+}
+
+
+/** Initialize the BinReloc library (for libraries).
+ *
+ * This function must be called before using any other BinReloc functions.
+ * It attempts to locate the calling library's canonical filename.
+ *
+ * @note The BinReloc source code MUST be included in your library, or this
+ *       function won't work correctly.
+ *
+ * @param error  If BinReloc failed to initialize, then the error code will
+ *               be stored in this variable. Set to NULL if you want to
+ *               ignore this. See #BrInitError for a list of error codes.
+ *
+ * @returns 1 on success, 0 if a filename cannot be found.
+ */
+int
+br_init_lib (BrInitError *error)
+{
+	exe = _br_find_exe_for_symbol ((const void *) "", error);
+	return exe != NULL;
+}
+
+
+/** Find the canonical filename of the current application.
+ *
+ * @param default_exe  A default filename which will be used as fallback.
+ * @returns A string containing the application's canonical filename,
+ *          which must be freed when no longer necessary. If BinReloc is
+ *          not initialized, or if br_init() failed, then a copy of
+ *          default_exe will be returned. If default_exe is NULL, then
+ *          NULL will be returned.
+ */
+char *
+br_find_exe (const char *default_exe)
+{
+	if (exe == (char *) NULL) {
+		/* BinReloc is not initialized. */
+		if (default_exe != (const char *) NULL)
+			return strdup (default_exe);
+		else
+			return (char *) NULL;
+	}
+	return strdup (exe);
+}
+
+
+/** Locate the directory in which the current application is installed.
+ *
+ * The prefix is generated by the following pseudo-code evaluation:
+ * \code
+ * dirname(exename)
+ * \endcode
+ *
+ * @param default_dir  A default directory which will used as fallback.
+ * @return A string containing the directory, which must be freed when no
+ *         longer necessary. If BinReloc is not initialized, or if the
+ *         initialization function failed, then a copy of default_dir
+ *         will be returned. If default_dir is NULL, then NULL will be
+ *         returned.
+ */
+char *
+br_find_exe_dir (const char *default_dir)
+{
+	if (exe == NULL) {
+		/* BinReloc not initialized. */
+		if (default_dir != NULL)
+			return strdup (default_dir);
+		else
+			return NULL;
+	}
+
+	return br_dirname (exe);
+}
+
+
+/** Locate the prefix in which the current application is installed.
+ *
+ * The prefix is generated by the following pseudo-code evaluation:
+ * \code
+ * dirname(dirname(exename))
+ * \endcode
+ *
+ * @param default_prefix  A default prefix which will used as fallback.
+ * @return A string containing the prefix, which must be freed when no
+ *         longer necessary. If BinReloc is not initialized, or if
+ *         the initialization function failed, then a copy of default_prefix
+ *         will be returned. If default_prefix is NULL, then NULL will be returned.
+ */
+char *
+br_find_prefix (const char *default_prefix)
+{
+	char *dir1, *dir2;
+
+	if (exe == (char *) NULL) {
+		/* BinReloc not initialized. */
+		if (default_prefix != (const char *) NULL)
+			return strdup (default_prefix);
+		else
+			return (char *) NULL;
+	}
+
+	dir1 = br_dirname (exe);
+	dir2 = br_dirname (dir1);
+	free (dir1);
+	return dir2;
+}
+
+
+/** Locate the application's binary folder.
+ *
+ * The path is generated by the following pseudo-code evaluation:
+ * \code
+ * prefix + "/bin"
+ * \endcode
+ *
+ * @param default_bin_dir  A default path which will used as fallback.
+ * @return A string containing the bin folder's path, which must be freed when
+ *         no longer necessary. If BinReloc is not initialized, or if
+ *         the initialization function failed, then a copy of default_bin_dir will
+ *         be returned. If default_bin_dir is NULL, then NULL will be returned.
+ */
+char *
+br_find_bin_dir (const char *default_bin_dir)
+{
+	char *prefix, *dir;
+
+	prefix = br_find_prefix ((const char *) NULL);
+	if (prefix == (char *) NULL) {
+		/* BinReloc not initialized. */
+		if (default_bin_dir != (const char *) NULL)
+			return strdup (default_bin_dir);
+		else
+			return (char *) NULL;
+	}
+
+	dir = br_build_path (prefix, "bin");
+	free (prefix);
+	return dir;
+}
+
+
+/** Locate the application's superuser binary folder.
+ *
+ * The path is generated by the following pseudo-code evaluation:
+ * \code
+ * prefix + "/sbin"
+ * \endcode
+ *
+ * @param default_sbin_dir  A default path which will used as fallback.
+ * @return A string containing the sbin folder's path, which must be freed when
+ *         no longer necessary. If BinReloc is not initialized, or if the
+ *         initialization function failed, then a copy of default_sbin_dir will
+ *         be returned. If default_bin_dir is NULL, then NULL will be returned.
+ */
+char *
+br_find_sbin_dir (const char *default_sbin_dir)
+{
+	char *prefix, *dir;
+
+	prefix = br_find_prefix ((const char *) NULL);
+	if (prefix == (char *) NULL) {
+		/* BinReloc not initialized. */
+		if (default_sbin_dir != (const char *) NULL)
+			return strdup (default_sbin_dir);
+		else
+			return (char *) NULL;
+	}
+
+	dir = br_build_path (prefix, "sbin");
+	free (prefix);
+	return dir;
+}
+
+
+/** Locate the application's data folder.
+ *
+ * The path is generated by the following pseudo-code evaluation:
+ * \code
+ * prefix + "/share"
+ * \endcode
+ *
+ * @param default_data_dir  A default path which will used as fallback.
+ * @return A string containing the data folder's path, which must be freed when
+ *         no longer necessary. If BinReloc is not initialized, or if the
+ *         initialization function failed, then a copy of default_data_dir
+ *         will be returned. If default_data_dir is NULL, then NULL will be
+ *         returned.
+ */
+char *
+br_find_data_dir (const char *default_data_dir)
+{
+	char *prefix, *dir;
+
+	prefix = br_find_prefix ((const char *) NULL);
+	if (prefix == (char *) NULL) {
+		/* BinReloc not initialized. */
+		if (default_data_dir != (const char *) NULL)
+			return strdup (default_data_dir);
+		else
+			return (char *) NULL;
+	}
+
+	dir = br_build_path (prefix, "share");
+	free (prefix);
+	return dir;
+}
+
+
+/** Locate the application's localization folder.
+ *
+ * The path is generated by the following pseudo-code evaluation:
+ * \code
+ * prefix + "/share/locale"
+ * \endcode
+ *
+ * @param default_locale_dir  A default path which will used as fallback.
+ * @return A string containing the localization folder's path, which must be freed when
+ *         no longer necessary. If BinReloc is not initialized, or if the
+ *         initialization function failed, then a copy of default_locale_dir will be returned.
+ *         If default_locale_dir is NULL, then NULL will be returned.
+ */
+char *
+br_find_locale_dir (const char *default_locale_dir)
+{
+	char *data_dir, *dir;
+
+	data_dir = br_find_data_dir ((const char *) NULL);
+	if (data_dir == (char *) NULL) {
+		/* BinReloc not initialized. */
+		if (default_locale_dir != (const char *) NULL)
+			return strdup (default_locale_dir);
+		else
+			return (char *) NULL;
+	}
+
+	dir = br_build_path (data_dir, "locale");
+	free (data_dir);
+	return dir;
+}
+
+
+/** Locate the application's library folder.
+ *
+ * The path is generated by the following pseudo-code evaluation:
+ * \code
+ * prefix + "/lib"
+ * \endcode
+ *
+ * @param default_lib_dir  A default path which will used as fallback.
+ * @return A string containing the library folder's path, which must be freed when
+ *         no longer necessary. If BinReloc is not initialized, or if the initialization
+ *         function failed, then a copy of default_lib_dir will be returned.
+ *         If default_lib_dir is NULL, then NULL will be returned.
+ */
+char *
+br_find_lib_dir (const char *default_lib_dir)
+{
+	char *prefix, *dir;
+
+	prefix = br_find_prefix ((const char *) NULL);
+	if (prefix == (char *) NULL) {
+		/* BinReloc not initialized. */
+		if (default_lib_dir != (const char *) NULL)
+			return strdup (default_lib_dir);
+		else
+			return (char *) NULL;
+	}
+
+	dir = br_build_path (prefix, "lib");
+	free (prefix);
+	return dir;
+}
+
+
+/** Locate the application's libexec folder.
+ *
+ * The path is generated by the following pseudo-code evaluation:
+ * \code
+ * prefix + "/libexec"
+ * \endcode
+ *
+ * @param default_libexec_dir  A default path which will used as fallback.
+ * @return A string containing the libexec folder's path, which must be freed when
+ *         no longer necessary. If BinReloc is not initialized, or if the initialization
+ *         function failed, then a copy of default_libexec_dir will be returned.
+ *         If default_libexec_dir is NULL, then NULL will be returned.
+ */
+char *
+br_find_libexec_dir (const char *default_libexec_dir)
+{
+	char *prefix, *dir;
+
+	prefix = br_find_prefix ((const char *) NULL);
+	if (prefix == (char *) NULL) {
+		/* BinReloc not initialized. */
+		if (default_libexec_dir != (const char *) NULL)
+			return strdup (default_libexec_dir);
+		else
+			return (char *) NULL;
+	}
+
+	dir = br_build_path (prefix, "libexec");
+	free (prefix);
+	return dir;
+}
+
+
+/** Locate the application's configuration files folder.
+ *
+ * The path is generated by the following pseudo-code evaluation:
+ * \code
+ * prefix + "/etc"
+ * \endcode
+ *
+ * @param default_etc_dir  A default path which will used as fallback.
+ * @return A string containing the etc folder's path, which must be freed when
+ *         no longer necessary. If BinReloc is not initialized, or if the initialization
+ *         function failed, then a copy of default_etc_dir will be returned.
+ *         If default_etc_dir is NULL, then NULL will be returned.
+ */
+char *
+br_find_etc_dir (const char *default_etc_dir)
+{
+	char *prefix, *dir;
+
+	prefix = br_find_prefix ((const char *) NULL);
+	if (prefix == (char *) NULL) {
+		/* BinReloc not initialized. */
+		if (default_etc_dir != (const char *) NULL)
+			return strdup (default_etc_dir);
+		else
+			return (char *) NULL;
+	}
+
+	dir = br_build_path (prefix, "etc");
+	free (prefix);
+	return dir;
+}
+
+
+/***********************
+ * Utility functions
+ ***********************/
+
+/** Concatenate str1 and str2 to a newly allocated string.
+ *
+ * @param str1 A string.
+ * @param str2 Another string.
+ * @returns A newly-allocated string. This string should be freed when no longer needed.
+ */
+char *
+br_strcat (const char *str1, const char *str2)
+{
+	char *result;
+	size_t len1, len2;
+
+	if (str1 == NULL)
+		str1 = "";
+	if (str2 == NULL)
+		str2 = "";
+
+	len1 = strlen (str1);
+	len2 = strlen (str2);
+
+	result = (char *) malloc (len1 + len2 + 1);
+	memcpy (result, str1, len1);
+	memcpy (result + len1, str2, len2);
+	result[len1 + len2] = '\0';
+
+	return result;
+}
+
+
+char *
+br_build_path (const char *dir, const char *file)
+{
+	char *dir2, *result;
+	size_t len;
+	int must_free = 0;
+
+	len = strlen (dir);
+	if (len > 0 && dir[len - 1] != '/') {
+		dir2 = br_strcat (dir, "/");
+		must_free = 1;
+	} else
+		dir2 = (char *) dir;
+
+	result = br_strcat (dir2, file);
+	if (must_free)
+		free (dir2);
+	return result;
+}
+
+
+/* Emulates glibc's strndup() */
+static char *
+br_strndup (const char *str, size_t size)
+{
+	char *result = (char *) NULL;
+	size_t len;
+
+	if (str == (const char *) NULL)
+		return (char *) NULL;
+
+	len = strlen (str);
+	if (len == 0)
+		return strdup ("");
+	if (size > len)
+		size = len;
+
+	result = (char *) malloc (len + 1);
+	memcpy (result, str, size);
+	result[size] = '\0';
+	return result;
+}
+
+
+/** Extracts the directory component of a path.
+ *
+ * Similar to g_dirname() or the dirname commandline application.
+ *
+ * Example:
+ * \code
+ * br_dirname ("/usr/local/foobar");  --> Returns: "/usr/local"
+ * \endcode
+ *
+ * @param path  A path.
+ * @returns     A directory name. This string should be freed when no longer needed.
+ */
+char *
+br_dirname (const char *path)
+{
+	char *end, *result;
+
+	if (path == (const char *) NULL)
+		return (char *) NULL;
+
+	end = strrchr (path, '/');
+	if (end == (const char *) NULL)
+		return strdup (".");
+
+	while (end > path && *end == '/')
+		end--;
+	result = br_strndup (path, end - path + 1);
+	if (result[0] == 0) {
+		free (result);
+		return strdup ("/");
+	} else
+		return result;
+}
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __BINRELOC_C__ */
diff --git a/external/binreloc-2.0/binreloc.h b/external/binreloc-2.0/binreloc.h
new file mode 100644
index 0000000..c833378
--- /dev/null
+++ b/external/binreloc-2.0/binreloc.h
@@ -0,0 +1,80 @@
+/*
+ * BinReloc - a library for creating relocatable executables
+ * Written by: Hongli Lai <h.lai at chello.nl>
+ * http://autopackage.org/
+ *
+ * This source code is public domain. You can relicense this code
+ * under whatever license you want.
+ *
+ * See http://autopackage.org/docs/binreloc/ for
+ * more information and how to use this.
+ */
+
+#ifndef __BINRELOC_H__
+#define __BINRELOC_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/** These error codes can be returned by br_init(), br_init_lib(), gbr_init() or gbr_init_lib(). */
+typedef enum {
+	/** Cannot allocate memory. */
+	BR_INIT_ERROR_NOMEM,
+	/** Unable to open /proc/self/maps; see errno for details. */
+	BR_INIT_ERROR_OPEN_MAPS,
+	/** Unable to read from /proc/self/maps; see errno for details. */
+	BR_INIT_ERROR_READ_MAPS,
+	/** The file format of /proc/self/maps is invalid; kernel bug? */
+	BR_INIT_ERROR_INVALID_MAPS,
+	/** BinReloc is disabled (the ENABLE_BINRELOC macro is not defined). */
+	BR_INIT_ERROR_DISABLED
+} BrInitError;
+
+
+#ifndef BINRELOC_RUNNING_DOXYGEN
+/* Mangle symbol names to avoid symbol collisions with other ELF objects. */
+	#define br_init             gJdn38894613193140_br_init
+	#define br_init_lib         gJdn38894613193140_br_init_lib
+	#define br_find_exe         gJdn38894613193140_br_find_exe
+	#define br_find_exe_dir     gJdn38894613193140_br_find_exe_dir
+	#define br_find_prefix      gJdn38894613193140_br_find_prefix
+	#define br_find_bin_dir     gJdn38894613193140_br_find_bin_dir
+	#define br_find_sbin_dir    gJdn38894613193140_br_find_sbin_dir
+	#define br_find_data_dir    gJdn38894613193140_br_find_data_dir
+	#define br_find_locale_dir  gJdn38894613193140_br_find_locale_dir
+	#define br_find_lib_dir     gJdn38894613193140_br_find_lib_dir
+	#define br_find_libexec_dir gJdn38894613193140_br_find_libexec_dir
+	#define br_find_etc_dir     gJdn38894613193140_br_find_etc_dir
+	#define br_strcat           gJdn38894613193140_br_strcat
+	#define br_build_path       gJdn38894613193140_br_build_path
+	#define br_dirname          gJdn38894613193140_br_dirname
+
+
+#endif
+int   br_init             (BrInitError *error);
+int   br_init_lib         (BrInitError *error);
+
+char *br_find_exe         (const char *default_exe);
+char *br_find_exe_dir     (const char *default_dir);
+char *br_find_prefix      (const char *default_prefix);
+char *br_find_bin_dir     (const char *default_bin_dir);
+char *br_find_sbin_dir    (const char *default_sbin_dir);
+char *br_find_data_dir    (const char *default_data_dir);
+char *br_find_locale_dir  (const char *default_locale_dir);
+char *br_find_lib_dir     (const char *default_lib_dir);
+char *br_find_libexec_dir (const char *default_libexec_dir);
+char *br_find_etc_dir     (const char *default_etc_dir);
+
+/* Utility functions */
+char *br_strcat  (const char *str1, const char *str2);
+char *br_build_path (const char *dir, const char *file);
+char *br_dirname (const char *path);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __BINRELOC_H__ */
diff --git a/src/axis_widget.cpp b/src/axis_widget.cpp
index 584f0db..2c9f1d1 100644
--- a/src/axis_widget.cpp
+++ b/src/axis_widget.cpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -34,54 +34,54 @@ AxisWidget::on_my_expose_event(GdkEventExpose* event)
 {
   Glib::RefPtr<Gdk::Window> window = drawingarea.get_window();
   if(window)
+  {
+    Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
+    if (0)
     {
-      Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
-      if (0)
-        {
-          cr->rectangle(event->area.x, event->area.y,
-                        event->area.width, event->area.height);
-          cr->clip();
-        }
+      cr->rectangle(event->area.x, event->area.y,
+                    event->area.width, event->area.height);
+      cr->clip();
+    }
 
-      int w  = drawingarea.get_allocation().get_width()  - 10;
-      int h  = drawingarea.get_allocation().get_height() - 10;
-      int px = w/2 + (w/2  * x);
-      int py = h/2 + (h/2 * y);
+    int w  = drawingarea.get_allocation().get_width()  - 10;
+    int h  = drawingarea.get_allocation().get_height() - 10;
+    int px = w/2 + (w/2  * x);
+    int py = h/2 + (h/2 * y);
 
-      cr->translate(5, 5);
+    cr->translate(5, 5);
 
-      // Outer Rectangle
-      cr->set_source_rgb(0.0, 0.0, 0.0);
-      cr->set_line_width(1.0);
-      cr->rectangle(0, 0, w, h);
-      cr->stroke();
+    // Outer Rectangle
+    cr->set_source_rgb(0.0, 0.0, 0.0);
+    cr->set_line_width(1.0);
+    cr->rectangle(0, 0, w, h);
+    cr->stroke();
 
-      // BG Circle
-      cr->arc(w/2, h/2, w/2, 0.0, 2.0 * M_PI);
-      cr->set_source_rgba(0.0, 0.0, 0.0, 0.1);
-      cr->fill();
+    // BG Circle
+    cr->arc(w/2, h/2, w/2, 0.0, 2.0 * M_PI);
+    cr->set_source_rgba(0.0, 0.0, 0.0, 0.1);
+    cr->fill();
 
-      // Cross
-      cr->set_line_width(0.5);
-      cr->set_source_rgba(0.0, 0.0, 0.0, 0.5);
-      cr->move_to(w/2, 0);
-      cr->line_to(w/2, h);
+    // Cross
+    cr->set_line_width(0.5);
+    cr->set_source_rgba(0.0, 0.0, 0.0, 0.5);
+    cr->move_to(w/2, 0);
+    cr->line_to(w/2, h);
 
-      cr->set_source_rgba(0.0, 0.0, 0.0, 0.5);
-      cr->move_to(0, h/2);
-      cr->line_to(w, h/2);
-      cr->stroke();
+    cr->set_source_rgba(0.0, 0.0, 0.0, 0.5);
+    cr->move_to(0, h/2);
+    cr->line_to(w, h/2);
+    cr->stroke();
+
+    // Cursor
+    cr->set_source_rgb(0.0, 0.0, 0.0);
+    cr->set_line_width(2.0);
+    cr->move_to(px, py-5);
+    cr->line_to(px, py+5);
+    cr->move_to(px-5, py);
+    cr->line_to(px+5, py);
+    cr->stroke();
+  }
 
-      // Cursor
-      cr->set_source_rgb(0.0, 0.0, 0.0);
-      cr->set_line_width(2.0);
-      cr->move_to(px, py-5);          
-      cr->line_to(px, py+5);
-      cr->move_to(px-5, py);          
-      cr->line_to(px+5, py);
-      cr->stroke();
-    }
-  
   return true;
 }
 
diff --git a/src/axis_widget.hpp b/src/axis_widget.hpp
index cd4f9a0..83b541a 100644
--- a/src/axis_widget.hpp
+++ b/src/axis_widget.hpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
diff --git a/src/button_widget.cpp b/src/button_widget.cpp
index e5879b8..d566e4d 100644
--- a/src/button_widget.cpp
+++ b/src/button_widget.cpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -30,32 +30,32 @@ ButtonWidget::on_expose_event(GdkEventExpose* event)
   Gtk::DrawingArea::on_expose_event(event);
   Glib::RefPtr<Gdk::Window> window = get_window();
   if(window)
-    {
-      Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
+  {
+    Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
+
+    int w  = get_allocation().get_width()  - 10;
+    int h  = get_allocation().get_height() - 10;
 
-      int w  = get_allocation().get_width()  - 10;
-      int h  = get_allocation().get_height() - 10;
+    cr->set_source_rgb(0.0, 0.0, 0.0);
+    cr->set_line_width(1.0);
+    cr->translate(5, 5);
+    cr->rectangle(0, 0, w, h);
 
-      cr->set_source_rgb(0.0, 0.0, 0.0);
-      cr->set_line_width(1.0);
-      cr->translate(5, 5);
-      cr->rectangle(0, 0, w, h);
-      
-      if (down)
-        cr->fill_preserve();
+    if (down)
+      cr->fill_preserve();
 
-      cr->stroke();
+    cr->stroke();
 
-      if (down)
-        cr->set_source_rgb(1.0, 1.0, 1.0);
+    if (down)
+      cr->set_source_rgb(1.0, 1.0, 1.0);
 
-      // FIXME: There are better ways to center text
-      if (name.size() == 2)
-        cr->move_to(w/2-6, h/2+3);
-      else
-        cr->move_to(w/2-4, h/2+3);
-      cr->show_text(name);
-    }
+    // FIXME: There are better ways to center text
+    if (name.size() == 2)
+      cr->move_to(w/2-6, h/2+3);
+    else
+      cr->move_to(w/2-4, h/2+3);
+    cr->show_text(name);
+  }
 
   return true;
 }
diff --git a/src/button_widget.hpp b/src/button_widget.hpp
index ca904e1..30c86be 100644
--- a/src/button_widget.hpp
+++ b/src/button_widget.hpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
diff --git a/src/calibrate_maximum_dialog.cpp b/src/calibrate_maximum_dialog.cpp
index dcdc88e..65fc4a2 100644
--- a/src/calibrate_maximum_dialog.cpp
+++ b/src/calibrate_maximum_dialog.cpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -44,51 +44,51 @@ CalibrateMaximumDialog::CalibrateMaximumDialog(Joystick& joystick_)
   is_init_axis_state.resize(joystick.get_axis_count(), false);
   min_axis_state.resize(joystick.get_axis_count());
   max_axis_state.resize(joystick.get_axis_count());
- 
+
   for(int i = 0; i < joystick.get_axis_count(); ++i)
-    {
-      min_axis_state[i] = joystick.get_axis_state(i);
-      max_axis_state[i] = joystick.get_axis_state(i);
-    }
+  {
+    min_axis_state[i] = joystick.get_axis_state(i);
+    max_axis_state[i] = joystick.get_axis_state(i);
+  }
 }
 
 void
 CalibrateMaximumDialog::on_response(int v)
 {
   if (v == 0)
-    {
-      // Calculate CalibrationData
-      std::vector<Joystick::CalibrationData> data;
+  {
+    // Calculate CalibrationData
+    std::vector<Joystick::CalibrationData> data;
 
-      for(int i = 0; i < joystick.get_axis_count(); ++i)
-        {
-          Joystick::CalibrationData axis;
-          axis.calibrate  = true;
-          axis.invert     = false;
-          axis.center_min = axis.center_max = joystick.get_axis_state(i);
-          axis.range_min  = min_axis_state[i];
-          axis.range_max  = max_axis_state[i];
+    for(int i = 0; i < joystick.get_axis_count(); ++i)
+    {
+      Joystick::CalibrationData axis;
+      axis.calibrate  = true;
+      axis.invert     = false;
+      axis.center_min = axis.center_max = joystick.get_axis_state(i);
+      axis.range_min  = min_axis_state[i];
+      axis.range_max  = max_axis_state[i];
 
-          // When the center is the same as the outer edge of an axis,
-          // we assume its a throttle control or analog button and
-          // calculate the center on our own
-          if (axis.center_min == axis.range_min ||
-              axis.center_max == axis.range_max)
-            {
-              axis.center_min = axis.center_max = (axis.range_min + axis.range_max)/2;
-            }
-          
-          data.push_back(axis);
-        }
-      
-      joystick.set_calibration(data);
+      // When the center is the same as the outer edge of an axis,
+      // we assume its a throttle control or analog button and
+      // calculate the center on our own
+      if (axis.center_min == axis.range_min ||
+          axis.center_max == axis.range_max)
+      {
+        axis.center_min = axis.center_max = (axis.range_min + axis.range_max)/2;
+      }
 
-      hide();
+      data.push_back(axis);
     }
+
+    joystick.set_calibration(data);
+
+    hide();
+  }
   else
-    {
-      joystick.set_calibration(orig_data);
-    }
+  {
+    joystick.set_calibration(orig_data);
+  }
 }
 
 void
@@ -96,16 +96,16 @@ CalibrateMaximumDialog::on_axis_move(int id, int value)
 {
   // std::cout << "AxisMove: " << id << " " << value << std::endl;
   if (!is_init_axis_state[id])
-    {
-      min_axis_state[id] = value;
-      max_axis_state[id] = value;
-      is_init_axis_state[id] = true;
-    }
+  {
+    min_axis_state[id] = value;
+    max_axis_state[id] = value;
+    is_init_axis_state[id] = true;
+  }
   else
-    {
-      min_axis_state[id] = std::min(value, min_axis_state[id]);
-      max_axis_state[id] = std::max(value, max_axis_state[id]);
-    }
+  {
+    min_axis_state[id] = std::min(value, min_axis_state[id]);
+    max_axis_state[id] = std::max(value, max_axis_state[id]);
+  }
 }
 

 /* EOF */
diff --git a/src/calibrate_maximum_dialog.hpp b/src/calibrate_maximum_dialog.hpp
index d353cb0..c7cb7ee 100644
--- a/src/calibrate_maximum_dialog.hpp
+++ b/src/calibrate_maximum_dialog.hpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
diff --git a/src/evdev_helper.cpp b/src/evdev_helper.cpp
index f209c51..ae76a60 100644
--- a/src/evdev_helper.cpp
+++ b/src/evdev_helper.cpp
@@ -1,4 +1,4 @@
-/* 
+/*
 **  Xbox360 USB Gamepad Userspace Driver
 **  Copyright (C) 2008 Ingo Ruhnke <grumbel at gmx.de>
 **
@@ -37,53 +37,53 @@ protected:
     : name(name)
   {
   }
-  
-  void add(Enum i, const std::string& name) 
+
+  void add(Enum i, const std::string& name)
   {
     enum2string[i] = name;
     string2enum[name] = i;
   }
 
 public:
-  Enum operator[](const std::string& str) const 
+  Enum operator[](const std::string& str) const
   {
     typename std::map<std::string, Enum>::const_iterator i = string2enum.find(str);
     if (i == string2enum.end())
+    {
+      std::istringstream in(str);
+      Enum tmp;
+      in >> tmp;
+      if (in.fail())
       {
-        std::istringstream in(str);
-        Enum tmp;
-        in >> tmp;
-        if (in.fail())
-          {
-            std::ostringstream out;
-            out << "Couldn't convert '" << str << "' to enum " << name << std::endl;
-            throw std::runtime_error(out.str());
-          }
-        else
-          {
-            return tmp;
-          }
+        std::ostringstream out;
+        out << "Couldn't convert '" << str << "' to enum " << name << std::endl;
+        throw std::runtime_error(out.str());
       }
-    else
+      else
       {
-        return i->second;
+        return tmp;
       }
+    }
+    else
+    {
+      return i->second;
+    }
   }
 
   std::string operator[](Enum v) const {
     typename std::map<Enum, std::string>::const_iterator i = enum2string.find(v);
     if (i == enum2string.end())
-      {
-        // If we can't convert symbolic, just convert the integer to a
-        // string
-        std::ostringstream out;
-        out << v;
-        return out.str();
-      }
+    {
+      // If we can't convert symbolic, just convert the integer to a
+      // string
+      std::ostringstream out;
+      out << v;
+      return out.str();
+    }
     else
-      {
-        return i->second;
-      }
+    {
+      return i->second;
+    }
   }
 };
 
@@ -91,7 +91,7 @@ public:
 class EvDevRelEnum : public EnumBox<int>
 {
 public:
-  EvDevRelEnum() 
+  EvDevRelEnum()
     : EnumBox<int>("EV_REL")
   {
     // File.new("/usr/include/linux/input.h")
@@ -113,7 +113,7 @@ public:
 class EvDevAbsEnum : public EnumBox<int>
 {
 public:
-  EvDevAbsEnum() 
+  EvDevAbsEnum()
     : EnumBox<int>("EV_ABS")
   {
     // File.new("/usr/include/linux/input.h")
@@ -151,7 +151,7 @@ public:
 class EvDevBtnEnum : public EnumBox<int>
 {
 public:
-  EvDevBtnEnum() 
+  EvDevBtnEnum()
     : EnumBox<int>("EV_KEY")
   {
     // File.new("/usr/include/linux/input.h")
@@ -600,20 +600,20 @@ public:
   // Map KeySym to kernel keycode
   std::map<KeySym, int> mapping;
 
-  Keysym2Keycode() 
+  Keysym2Keycode()
   {
     //std::cout << "Initing Keysym2Keycode" << std::endl;
 
     Display* dpy = XOpenDisplay(NULL);
     if (!dpy)
-      {
-        throw std::runtime_error("Keysym2Keycode: Couldn't open X11 display");
-      }
+    {
+      throw std::runtime_error("Keysym2Keycode: Couldn't open X11 display");
+    }
     else
-      {
-        process_keymap(dpy);
-        XCloseDisplay(dpy);
-      }
+    {
+      process_keymap(dpy);
+      XCloseDisplay(dpy);
+    }
   }
 
   void process_keymap(Display* dpy)
@@ -628,17 +628,17 @@ public:
                                          &keysyms_per_keycode);
 
     for(int i = 0; i < num_keycodes; ++i)
+    {
+      if (keymap[i*keysyms_per_keycode] != NoSymbol)
       {
-        if (keymap[i*keysyms_per_keycode] != NoSymbol)
-          {
-            KeySym keysym = keymap[i*keysyms_per_keycode];
-            // FIXME: Duplicate entries confuse the conversion
-            // std::map<KeySym, int>::iterator it = mapping.find(keysym);
-            // if (it != mapping.end())
-            //   std::cout << "Duplicate keycode: " << i << std::endl;
-            mapping[keysym] = i;
-          }
+        KeySym keysym = keymap[i*keysyms_per_keycode];
+        // FIXME: Duplicate entries confuse the conversion
+        // std::map<KeySym, int>::iterator it = mapping.find(keysym);
+        // if (it != mapping.end())
+        //   std::cout << "Duplicate keycode: " << i << std::endl;
+        mapping[keysym] = i;
       }
+    }
 
     XFree(keymap);
   }
@@ -651,71 +651,71 @@ int xkeysym2keycode(const std::string& name)
   KeySym keysym = XStringToKeysym(name.substr(3).c_str());
 
   if (keysym == NoSymbol)
-    {
-      throw std::runtime_error("xkeysym2keycode: Couldn't convert name '" + name + "' to xkeysym");
-    }
+  {
+    throw std::runtime_error("xkeysym2keycode: Couldn't convert name '" + name + "' to xkeysym");
+  }
 
   std::map<KeySym, int>::iterator i = sym2code.mapping.find(keysym);
   if (i == sym2code.mapping.end())
-    {
-      throw std::runtime_error("xkeysym2keycode: Couldn't convert xkeysym '" + name + "' to evdev keycode");
-    }
+  {
+    throw std::runtime_error("xkeysym2keycode: Couldn't convert xkeysym '" + name + "' to evdev keycode");
+  }
   else
-    {
-      if (0)
-        std::cout << name << " -> " << keysym << " -> " << XKeysymToString(keysym) 
-                  << " -> " << btn2str(i->second) << "(" << i->second << ")" << std::endl;
-      return i->second;
-    }
+  {
+    if (0)
+      std::cout << name << " -> " << keysym << " -> " << XKeysymToString(keysym)
+                << " -> " << btn2str(i->second) << "(" << i->second << ")" << std::endl;
+    return i->second;
+  }
 }
 

 bool str2event(const std::string& name, int& type, int& code)
 {
   if (name == "void" || name == "none")
-    {
-      type = -1;
-      code = -1;
-      return true;
-    }
+  {
+    type = -1;
+    code = -1;
+    return true;
+  }
   else if (name.compare(0, 3, "REL") == 0)
-    {
-      type = EV_REL;
-      code = evdev_rel_names[name];
-      return true;
-    }
+  {
+    type = EV_REL;
+    code = evdev_rel_names[name];
+    return true;
+  }
   else if (name.compare(0, 3, "ABS") == 0)
-    {
-      type = EV_ABS;
-      code = evdev_abs_names[name];
-      return true;
-    }
+  {
+    type = EV_ABS;
+    code = evdev_abs_names[name];
+    return true;
+  }
   else if (name.compare(0, 2, "XK") == 0)
-    {
-      type = EV_KEY;
-      code = xkeysym2keycode(name);
-      return true;      
-    }
+  {
+    type = EV_KEY;
+    code = xkeysym2keycode(name);
+    return true;
+  }
   else if (name.compare(0, 2, "JS") == 0)
-    {
-      int int_value = 0;
-      std::istringstream(name.substr(3)) >> int_value;
+  {
+    int int_value = 0;
+    std::istringstream(name.substr(3)) >> int_value;
 
-      type = EV_KEY;
-      code = BTN_JOYSTICK + int_value;
+    type = EV_KEY;
+    code = BTN_JOYSTICK + int_value;
 
-      return true;
-    }
+    return true;
+  }
   else if (name.compare(0, 3, "KEY") == 0 ||
            name.compare(0, 3, "BTN") == 0)
-    {
-      type = EV_KEY;
-      code = evdev_btn_names[name];
-      return true;
-    }
+  {
+    type = EV_KEY;
+    code = evdev_btn_names[name];
+    return true;
+  }
   else
-    {
-      return false;
-    }
+  {
+    return false;
+  }
 }
 
 std::string btn2str(int i)
diff --git a/src/evdev_helper.hpp b/src/evdev_helper.hpp
index 630d2e2..8aa33e4 100644
--- a/src/evdev_helper.hpp
+++ b/src/evdev_helper.hpp
@@ -1,4 +1,4 @@
-/* 
+/*
 **  Xbox360 USB Gamepad Userspace Driver
 **  Copyright (C) 2008 Ingo Ruhnke <grumbel at gmx.de>
 **
diff --git a/src/joystick.cpp b/src/joystick.cpp
index cefdff6..a09beaf 100644
--- a/src/joystick.cpp
+++ b/src/joystick.cpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -35,52 +35,50 @@
 #include <glibmm/convert.h>
 
 #include "evdev_helper.hpp"
-#include "xml_writer.hpp"
-#include "xml_reader.hpp"
 #include "joystick.hpp"
 

 Joystick::Joystick(const std::string& filename_)
   : filename(filename_)
 {
   if ((fd = open(filename.c_str(), O_RDONLY)) < 0)
+  {
+    std::ostringstream str;
+    str << filename << ": " << strerror(errno);
+    throw std::runtime_error(str.str());
+  }
+  else
+  {
+    // ok
+    uint8_t num_axis   = 0;
+    uint8_t num_button = 0;
+    ioctl(fd, JSIOCGAXES,    &num_axis);
+    ioctl(fd, JSIOCGBUTTONS, &num_button);
+    axis_count   = num_axis;
+    button_count = num_button;
+
+    // Get Name
+    char name_c_str[1024];
+    if (ioctl(fd, JSIOCGNAME(sizeof(name_c_str)), name_c_str) < 0)
     {
       std::ostringstream str;
       str << filename << ": " << strerror(errno);
       throw std::runtime_error(str.str());
     }
-  else
+    else
     {
-      // ok
-      uint8_t num_axis   = 0;
-      uint8_t num_button = 0;
-      ioctl(fd, JSIOCGAXES,    &num_axis);
-      ioctl(fd, JSIOCGBUTTONS, &num_button);
-      axis_count   = num_axis;
-      button_count = num_button;
-
-      // Get Name 
-      char name_c_str[1024];
-      if (ioctl(fd, JSIOCGNAME(sizeof(name_c_str)), name_c_str) < 0)
-        {
-          std::ostringstream str;
-          str << filename << ": " << strerror(errno);
-          throw std::runtime_error(str.str());          
-        }
-      else
-        {
-          orig_name = name_c_str;
-          try {
-            name = Glib::convert_with_fallback(name_c_str, "UTF-8", "ISO-8859-1");
-          } catch(Glib::ConvertError& err) {
-            std::cout << err.what() << std::endl;
-          }
-        }
-
-      axis_state.resize(axis_count);
+      orig_name = name_c_str;
+      try {
+        name = Glib::convert_with_fallback(name_c_str, "UTF-8", "ISO-8859-1");
+      } catch(Glib::ConvertError& err) {
+        std::cout << err.what() << std::endl;
+      }
     }
 
+    axis_state.resize(axis_count);
+  }
+
   orig_calibration_data = get_calibration();
-  
+
   connection = Glib::signal_io().connect(sigc::mem_fun(this, &Joystick::on_in), fd, Glib::IO_IN);
 }
 
@@ -105,29 +103,29 @@ Joystick::update()
   ssize_t len = read(fd, &event, sizeof(event));
 
   if (len < 0)
-    {
-      std::ostringstream str;
-      str << filename << ": " << strerror(errno);
-      throw std::runtime_error(str.str());
-    }
+  {
+    std::ostringstream str;
+    str << filename << ": " << strerror(errno);
+    throw std::runtime_error(str.str());
+  }
   else if (len == sizeof(event))
-    { // ok
-      if (event.type & JS_EVENT_AXIS)
-        {
-          //std::cout << "Axis: " << (int)event.number << " -> " << (int)event.value << std::endl;
-          axis_state[event.number] = event.value;
-          axis_move(event.number, event.value);
-        }
-      else if (event.type & JS_EVENT_BUTTON)
-        {
-          //std::cout << "Button: " << (int)event.number << " -> " << (int)event.value << std::endl;
-          button_move(event.number, event.value);
-        }
+  { // ok
+    if (event.type & JS_EVENT_AXIS)
+    {
+      //std::cout << "Axis: " << (int)event.number << " -> " << (int)event.value << std::endl;
+      axis_state[event.number] = event.value;
+      axis_move(event.number, event.value);
     }
-  else
+    else if (event.type & JS_EVENT_BUTTON)
     {
-      throw std::runtime_error("Joystick::update(): unknown read error");
+      //std::cout << "Button: " << (int)event.number << " -> " << (int)event.value << std::endl;
+      button_move(event.number, event.value);
     }
+  }
+  else
+  {
+    throw std::runtime_error("Joystick::update(): unknown read error");
+  }
 }
 

 std::vector<JoystickDescription>
@@ -136,23 +134,23 @@ Joystick::get_joysticks()
   std::vector<JoystickDescription> joysticks;
 
   for(int i = 0; i < 32; ++i)
+  {
+    try
     {
-      try 
-        {
-          std::ostringstream str;
-          str << "/dev/input/js" << i;
-          Joystick joystick(str.str());
-
-          joysticks.push_back(JoystickDescription(joystick.get_filename(),
-                                                  joystick.get_name(),                                                  
-                                                  joystick.get_axis_count(),
-                                                  joystick.get_button_count()));
-        }
-      catch(std::exception& err)
-        {
-          // ok
-        }
+      std::ostringstream str;
+      str << "/dev/input/js" << i;
+      Joystick joystick(str.str());
+
+      joysticks.push_back(JoystickDescription(joystick.get_filename(),
+                                              joystick.get_name(),
+                                              joystick.get_axis_count(),
+                                              joystick.get_button_count()));
     }
+    catch(std::exception& err)
+    {
+      // ok
+    }
+  }
 
   return joysticks;
 }
@@ -164,33 +162,33 @@ Joystick::CalibrationData corr2cal(const struct js_corr& corr_)
   Joystick::CalibrationData data;
 
   if (corr.type)
-    {
-      data.calibrate = true;
-      data.invert    = (corr.coef[2] < 0 && corr.coef[3] < 0);
-      data.center_min = corr.coef[0];
-      data.center_max = corr.coef[1];
-
-      if (data.invert)
-        {
-          corr.coef[2] = -corr.coef[2];
-          corr.coef[3] = -corr.coef[3];
-        }
+  {
+    data.calibrate = true;
+    data.invert    = (corr.coef[2] < 0 && corr.coef[3] < 0);
+    data.center_min = corr.coef[0];
+    data.center_max = corr.coef[1];
 
-      // Need to use double and rint(), since calculation doesn't end
-      // up on clean integer positions (i.e. 0.9999 can happen)
-      data.range_min = rint(data.center_min - ((32767.0 * 16384) / corr.coef[2]));
-      data.range_max = rint((32767.0 * 16384) / corr.coef[3] + data.center_max);
-    }
-  else
+    if (data.invert)
     {
-      data.calibrate  = false;
-      data.invert     = false;
-      data.center_min = 0;
-      data.center_max = 0;
-      data.range_min  = 0;
-      data.range_max  = 0;
+      corr.coef[2] = -corr.coef[2];
+      corr.coef[3] = -corr.coef[3];
     }
 
+    // Need to use double and rint(), since calculation doesn't end
+    // up on clean integer positions (i.e. 0.9999 can happen)
+    data.range_min = rint(data.center_min - ((32767.0 * 16384) / corr.coef[2]));
+    data.range_max = rint((32767.0 * 16384) / corr.coef[3] + data.center_max);
+  }
+  else
+  {
+    data.calibrate  = false;
+    data.invert     = false;
+    data.center_min = 0;
+    data.center_max = 0;
+    data.range_min  = 0;
+    data.range_max  = 0;
+  }
+
   return data;
 }
 
@@ -200,17 +198,17 @@ Joystick::get_calibration()
   std::vector<struct js_corr> corr(get_axis_count());
 
   if (ioctl(fd, JSIOCGCORR, &*corr.begin()) < 0)
-    {
-      std::ostringstream str;
-      str << filename << ": " << strerror(errno);
-      throw std::runtime_error(str.str());
-    }
+  {
+    std::ostringstream str;
+    str << filename << ": " << strerror(errno);
+    throw std::runtime_error(str.str());
+  }
   else
-    {
-      std::vector<CalibrationData> data;
-      std::transform(corr.begin(), corr.end(), std::back_inserter(data), corr2cal);
-      return data;
-    }
+  {
+    std::vector<CalibrationData> data;
+    std::transform(corr.begin(), corr.end(), std::back_inserter(data), corr2cal);
+    return data;
+  }
 }
 
 struct js_corr cal2corr(const Joystick::CalibrationData& data)
@@ -220,27 +218,27 @@ struct js_corr cal2corr(const Joystick::CalibrationData& data)
   if (data.calibrate &&
       (data.center_min - data.range_min)  != 0 &&
       (data.range_max  - data.center_max) != 0)
-    {
-      corr.type = 1;
-      corr.prec = 0;
-      corr.coef[0] = data.center_min;
-      corr.coef[1] = data.center_max;
+  {
+    corr.type = 1;
+    corr.prec = 0;
+    corr.coef[0] = data.center_min;
+    corr.coef[1] = data.center_max;
 
-      corr.coef[2] = (32767 * 16384) / (data.center_min - data.range_min);
-      corr.coef[3] = (32767 * 16384) / (data.range_max  - data.center_max);
+    corr.coef[2] = (32767 * 16384) / (data.center_min - data.range_min);
+    corr.coef[3] = (32767 * 16384) / (data.range_max  - data.center_max);
 
-      if (data.invert)
-        {
-          corr.coef[2] = -corr.coef[2];
-          corr.coef[3] = -corr.coef[3];
-        }
-    }
-  else
+    if (data.invert)
     {
-      corr.type = 0;
-      corr.prec = 0;
-      memset(corr.coef, 0, sizeof(corr.coef));
+      corr.coef[2] = -corr.coef[2];
+      corr.coef[3] = -corr.coef[3];
     }
+  }
+  else
+  {
+    corr.type = 0;
+    corr.prec = 0;
+    memset(corr.coef, 0, sizeof(corr.coef));
+  }
 
   return corr;
 }
@@ -250,34 +248,34 @@ Joystick::set_calibration(const std::vector<CalibrationData>& data)
 {
   std::vector<struct js_corr> corr;
 
- std::transform(data.begin(), data.end(), std::back_inserter(corr), cal2corr);
+  std::transform(data.begin(), data.end(), std::back_inserter(corr), cal2corr);
 
   if (ioctl(fd, JSIOCSCORR, &*corr.begin()) < 0)
-    {
-      std::ostringstream str;
-      str << filename << ": " << strerror(errno);
-      throw std::runtime_error(str.str());
-    }
+  {
+    std::ostringstream str;
+    str << filename << ": " << strerror(errno);
+    throw std::runtime_error(str.str());
+  }
 }
 
 void
 Joystick::clear_calibration()
 {
   std::vector<CalibrationData> data;
-  
+
   for(int i = 0; i < get_axis_count(); ++i)
-    {
-      CalibrationData cal;
-
-      cal.calibrate  = false;
-      cal.invert     = false;
-      cal.center_min = 0;
-      cal.center_max = 0;
-      cal.range_min  = 0;
-      cal.range_max  = 0;
-     
-      data.push_back(cal);
-    }
+  {
+    CalibrationData cal;
+
+    cal.calibrate  = false;
+    cal.invert     = false;
+    cal.center_min = 0;
+    cal.center_max = 0;
+    cal.range_min  = 0;
+    cal.range_max  = 0;
+
+    data.push_back(cal);
+  }
 
   set_calibration(data);
 }
@@ -293,17 +291,17 @@ Joystick::get_button_mapping()
 {
   uint16_t btnmap[KEY_MAX - BTN_MISC + 1];
   if (ioctl(fd, JSIOCGBTNMAP, btnmap) < 0)
-    {
-      std::ostringstream str;
-      str << filename << ": " << strerror(errno);
-      throw std::runtime_error(str.str());
-    }
+  {
+    std::ostringstream str;
+    str << filename << ": " << strerror(errno);
+    throw std::runtime_error(str.str());
+  }
   else
-    {
-      std::vector<int> mapping;
-      std::copy(btnmap, btnmap + button_count, std::back_inserter(mapping));
-      return mapping;
-    }
+  {
+    std::vector<int> mapping;
+    std::copy(btnmap, btnmap + button_count, std::back_inserter(mapping));
+    return mapping;
+  }
 }
 
 std::vector<int>
@@ -311,17 +309,17 @@ Joystick::get_axis_mapping()
 {
   uint8_t axismap[ABS_MAX + 1];
   if (ioctl(fd, JSIOCGAXMAP, axismap) < 0)
-    {
-      std::ostringstream str;
-      str << filename << ": " << strerror(errno);
-      throw std::runtime_error(str.str());
-    }
+  {
+    std::ostringstream str;
+    str << filename << ": " << strerror(errno);
+    throw std::runtime_error(str.str());
+  }
   else
-    {
-      std::vector<int> mapping;
-      std::copy(axismap, axismap + axis_count, std::back_inserter(mapping));
-      return mapping;
-    }
+  {
+    std::vector<int> mapping;
+    std::copy(axismap, axismap + axis_count, std::back_inserter(mapping));
+    return mapping;
+  }
 }
 
 void
@@ -335,16 +333,16 @@ Joystick::set_button_mapping(const std::vector<int>& mapping)
 
   if (0)
     for(int i = 0; i < button_count; ++i)
-      {
-        std::cout << i << " -> " << btnmap[i] << std::endl;
-      }
-
-  if (ioctl(fd, JSIOCSBTNMAP, btnmap) < 0)
     {
-      std::ostringstream str;
-      str << filename << ": " << strerror(errno);
-      throw std::runtime_error(str.str());
+      std::cout << i << " -> " << btnmap[i] << std::endl;
     }
+
+  if (ioctl(fd, JSIOCSBTNMAP, btnmap) < 0)
+  {
+    std::ostringstream str;
+    str << filename << ": " << strerror(errno);
+    throw std::runtime_error(str.str());
+  }
 }
 
 int
@@ -364,13 +362,13 @@ Joystick::set_axis_mapping(const std::vector<int>& mapping)
   uint8_t axismap[ABS_MAX + 1];
 
   std::copy(mapping.begin(), mapping.end(), axismap);
-  
+
   if (ioctl(fd, JSIOCSAXMAP, axismap) < 0)
-    {
-      std::ostringstream str;
-      str << filename << ": " << strerror(errno);
-      throw std::runtime_error(str.str());
-    }
+  {
+    std::ostringstream str;
+    str << filename << ": " << strerror(errno);
+    throw std::runtime_error(str.str());
+  }
 }
 
 void
@@ -378,128 +376,18 @@ Joystick::correct_calibration(const std::vector<int>& mapping_old, const std::ve
 {
   int axes[ABS_MAX + 1]; // axes[name] -> old_idx
   for(std::vector<int>::const_iterator i = mapping_old.begin(); i != mapping_old.end(); ++i)
-    {
-      axes[*i] = i - mapping_old.begin();
-    }
+  {
+    axes[*i] = i - mapping_old.begin();
+  }
 
   std::vector<CalibrationData> callib_old = get_calibration();
   std::vector<CalibrationData> callib_new;
   for(std::vector<int>::const_iterator i = mapping_new.begin(); i != mapping_new.end(); ++i)
-    {
-      callib_new.push_back(callib_old[axes[*i]]);
-    }
-  
-  set_calibration(callib_new);
-}
-
-void
-Joystick::write(XMLWriter& out)
-{
-  out.start_section("joystick");
-  out.write("name",   name);
-  out.write("device", filename);
-  
-  { // write CalibrationData
-    std::vector<CalibrationData> data = get_calibration();
-
-    out.start_section("calibration");
-    for(std::vector<CalibrationData>::iterator i = data.begin(); i != data.end(); ++i)
-      {
-        out.start_section("axis");
-        //out.write("id",         i - data.begin());
-        out.write("calibrate",  i->calibrate);
-        out.write("center-min", i->center_min);
-        out.write("center-max", i->center_max);
-        out.write("range-min",  i->range_min);
-        out.write("range-max",  i->range_max);
-        out.write("invert",     i->invert);
-        out.end_section("axis");
-      }
-    out.end_section("calibration");
-  }
-
   {
-    std::vector<int> mapping = get_axis_mapping();
-    out.start_section("axis-map");
-    for(std::vector<int>::iterator i = mapping.begin(); i != mapping.end(); ++i)
-      {
-        out.write("axis", abs2str(*i));
-      }
-    out.end_section("axis-map");
+    callib_new.push_back(callib_old[axes[*i]]);
   }
 
-  {
-    std::vector<int> mapping = get_button_mapping();
-    out.start_section("button-map");
-    for(std::vector<int>::iterator i = mapping.begin(); i != mapping.end(); ++i)
-      {
-        out.write("button", btn2str(*i));
-      }   
-    out.end_section("button-map");
-  }
-
-  out.end_section("joystick");
-}
-
-void
-Joystick::load(const XMLReader& root_reader)
-{
-  std::string cfg_name;
-  if (root_reader.read("name", cfg_name) && name == cfg_name)
-    {
-      // Read calibration data
-      if (XMLReader reader = root_reader.get_section("calibration"))
-        {
-          std::vector<CalibrationData> calibration_data;
-          const std::vector<XMLReader>& sections = reader.get_sections();
-          for(std::vector<XMLReader>::const_iterator i = sections.begin(); i != sections.end(); ++i)
-            {
-              CalibrationData data;
-
-              //i->read("axis", );
-              //i->read("precision", );
-              i->read("invert",     data.invert);
-              i->read("center-min", data.center_min);
-              i->read("center-max", data.center_max);
-              i->read("range-min",  data.range_min);
-              i->read("range-max",  data.range_max);
-
-              calibration_data.push_back(data);
-            }
-
-          set_calibration(calibration_data);
-        }
-
-      { // Read axis mapping
-        const std::vector<std::string>& cfg_axis_map = root_reader.get_string_list("axis-map");
-        std::vector<int> mapping;
-        
-        for(std::vector<std::string>::const_iterator i = cfg_axis_map.begin(); i != cfg_axis_map.end(); ++i)
-          {
-            int type = 0;
-            int code = 0;
-            str2event(*i, type, code);
-            mapping.push_back(code);
-          }
-
-        set_axis_mapping(mapping);
-      }
-
-      { // Read button mapping
-        const std::vector<std::string>& cfg_button_map = root_reader.get_string_list("button-map");
-        std::vector<int> mapping;
-        
-        for(std::vector<std::string>::const_iterator i = cfg_button_map.begin(); i != cfg_button_map.end(); ++i)
-          {
-            int type = 0;
-            int code = 0;
-            str2event(*i, type, code);
-            mapping.push_back(code);
-          }
-
-        set_button_mapping(mapping);
-      }
-    }
+  set_calibration(callib_new);
 }
 
 std::string
@@ -507,55 +395,55 @@ Joystick::get_evdev() const
 {
   // See /usr/share/doc/linux-doc-2.6.28/devices.txt.gz
   for(int i = 0; i < 32; ++i)
+  {
+    std::ostringstream out;
+    out << "/dev/input/event" << i;
+
+    int evdev_fd;
+    if ((evdev_fd = open(out.str().c_str(), O_RDONLY)) < 0)
     {
-      std::ostringstream out;
-      out << "/dev/input/event" << i;
-      
-      int evdev_fd;
-      if ((evdev_fd = open(out.str().c_str(), O_RDONLY)) < 0)
-        {
-          // ignore
-        }
+      // ignore
+    }
+    else
+    {
+      char evdev_name[256];
+      if (ioctl(evdev_fd, EVIOCGNAME(sizeof(evdev_name)), evdev_name) < 0)
+      {
+        std::cout << out.str() << ": " << strerror(errno) << std::endl;
+      }
       else
+      {
+        if (orig_name == evdev_name)
         {
-          char evdev_name[256];
-          if (ioctl(evdev_fd, EVIOCGNAME(sizeof(evdev_name)), evdev_name) < 0)
-            {
-              std::cout << out.str() << ": " << strerror(errno) << std::endl;
-            }
-          else
-            {
-              if (orig_name == evdev_name)
-                {
-                  // Found a device that matches, so return it
-                  close(evdev_fd);
-                  return out.str();
-                }
-            }
-
+          // Found a device that matches, so return it
           close(evdev_fd);
+          return out.str();
         }
+      }
+
+      close(evdev_fd);
     }
+  }
 
   throw std::runtime_error("couldn't find evdev for " + filename);
 }
 

 #ifdef __TEST__
 
-// g++ -D__TEST__ joystick.cpp evdev_helper.cpp xml_writer.cpp xml_reader.cpp -o joystick-test `pkg-config --cflags --libs gtkmm-2.4 sigc++-2.0`  
+// g++ -D__TEST__ joystick.cpp evdev_helper.cpp xml_writer.cpp xml_reader.cpp -o joystick-test `pkg-config --cflags --libs gtkmm-2.4 sigc++-2.0`
 
 int main(int argc, char** argv)
 {
   for(int i = 1; i < argc; ++i)
-    {
-      Joystick joystick(argv[i]);
+  {
+    Joystick joystick(argv[i]);
 
-      std::cout << "Filename: '" << joystick.get_filename() << "'\n";
-      std::cout << "Name:     '" << joystick.get_name() << "'\n";
-      std::cout << "Axis:     " << joystick.get_axis_count() << "\n";
-      std::cout << "Button:   " << joystick.get_button_count() << "\n";
-      std::cout << "Evdev:    '" << joystick.get_evdev() << "'\n";
-    }
+    std::cout << "Filename: '" << joystick.get_filename() << "'\n";
+    std::cout << "Name:     '" << joystick.get_name() << "'\n";
+    std::cout << "Axis:     " << joystick.get_axis_count() << "\n";
+    std::cout << "Button:   " << joystick.get_button_count() << "\n";
+    std::cout << "Evdev:    '" << joystick.get_evdev() << "'\n";
+  }
   return 0;
 }
 #endif
diff --git a/src/joystick.hpp b/src/joystick.hpp
index 8afb1cc..0aa9b61 100644
--- a/src/joystick.hpp
+++ b/src/joystick.hpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -89,10 +89,10 @@ public:
 
   void set_button_mapping(const std::vector<int>& mapping);
   void set_axis_mapping(const std::vector<int>& mapping);
-  
+
   /** Corrects calibration data after remaping axes */
   void correct_calibration(const std::vector<int>& mapping_old, const std::vector<int>& mapping_new);
-  
+
   void write(XMLWriter& out);
   void load(const XMLReader& reader);
 
diff --git a/src/joystick_calibration_widget.cpp b/src/joystick_calibration_widget.cpp
index 12ae5b9..ddc1631 100644
--- a/src/joystick_calibration_widget.cpp
+++ b/src/joystick_calibration_widget.cpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -49,7 +49,7 @@ JoystickCalibrationWidget::JoystickCalibrationWidget(Joystick& joystick)
   get_vbox()->pack_start(label, Gtk::PACK_SHRINK);
 
   calibration_button.signal_clicked().connect(sigc::mem_fun(this, &JoystickCalibrationWidget::on_calibrate));
-  
+
   buttonbox.set_border_width(5);
   buttonbox.add(calibration_button);
   get_vbox()->pack_start(buttonbox, Gtk::PACK_SHRINK);
@@ -58,57 +58,60 @@ JoystickCalibrationWidget::JoystickCalibrationWidget(Joystick& joystick)
 
   axis_table.attach(*Gtk::manage(new Gtk::Label("CenterMin")), 1, 2, 0, 1);
   axis_table.attach(*Gtk::manage(new Gtk::Label("CenterMax")), 2, 3, 0, 1);
-  
+
   axis_table.attach(*Gtk::manage(new Gtk::Label("RangeMin")), 3, 4, 0, 1);
   axis_table.attach(*Gtk::manage(new Gtk::Label("RangeMax")), 4, 5, 0, 1);
 
   axis_table.attach(*Gtk::manage(new Gtk::Label("Invert")), 5, 6, 0, 1);
-  
+
   axis_table.set_col_spacing(2, 8);
   for(int i = 0; i < joystick.get_axis_count(); ++i)
-    {
-      CalibrationData data;
-      
-      Gtk::SpinButton&  center_min = *Gtk::manage(new Gtk::SpinButton(*Gtk::manage(data.center_min = new Gtk::Adjustment(0, -32768, 32767))));
-      Gtk::SpinButton&  center_max = *Gtk::manage(new Gtk::SpinButton(*Gtk::manage(data.center_max = new Gtk::Adjustment(0, -32768, 32767))));
-      Gtk::SpinButton&  range_min  = *Gtk::manage(new Gtk::SpinButton(*Gtk::manage(data.range_min  = new Gtk::Adjustment(0, -32768, 32767))));
-      Gtk::SpinButton&  range_max  = *Gtk::manage(new Gtk::SpinButton(*Gtk::manage(data.range_max  = new Gtk::Adjustment(0, -32768, 32767))));
-      Gtk::CheckButton& invert     = *(data.invert = Gtk::manage(new Gtk::CheckButton()));
+  {
+    CalibrationData data;
+
+    Gtk::SpinButton&  center_min = *Gtk::manage(new Gtk::SpinButton(*Gtk::manage(data.center_min = new Gtk::Adjustment(0, -32768, 32767))));
+    Gtk::SpinButton&  center_max = *Gtk::manage(new Gtk::SpinButton(*Gtk::manage(data.center_max = new Gtk::Adjustment(0, -32768, 32767))));
+    Gtk::SpinButton&  range_min  = *Gtk::manage(new Gtk::SpinButton(*Gtk::manage(data.range_min  = new Gtk::Adjustment(0, -32768, 32767))));
+    Gtk::SpinButton&  range_max  = *Gtk::manage(new Gtk::SpinButton(*Gtk::manage(data.range_max  = new Gtk::Adjustment(0, -32768, 32767))));
+    Gtk::CheckButton& invert     = *(data.invert = Gtk::manage(new Gtk::CheckButton()));
 
-      center_min.signal_value_changed().connect(sigc::mem_fun(this, &JoystickCalibrationWidget::on_apply));
-      center_max.signal_value_changed().connect(sigc::mem_fun(this, &JoystickCalibrationWidget::on_apply));
-      range_min.signal_value_changed().connect(sigc::mem_fun(this, &JoystickCalibrationWidget::on_apply));
-      range_max.signal_value_changed().connect(sigc::mem_fun(this, &JoystickCalibrationWidget::on_apply));
-      invert.signal_clicked().connect(sigc::mem_fun(this, &JoystickCalibrationWidget::on_apply));
+    center_min.signal_value_changed().connect(sigc::mem_fun(this, &JoystickCalibrationWidget::on_apply));
+    center_max.signal_value_changed().connect(sigc::mem_fun(this, &JoystickCalibrationWidget::on_apply));
+    range_min.signal_value_changed().connect(sigc::mem_fun(this, &JoystickCalibrationWidget::on_apply));
+    range_max.signal_value_changed().connect(sigc::mem_fun(this, &JoystickCalibrationWidget::on_apply));
+    invert.signal_clicked().connect(sigc::mem_fun(this, &JoystickCalibrationWidget::on_apply));
 
-      center_min.set_tooltip_text("The minimal value of the dead zone");
-      center_max.set_tooltip_text("The maximum value of the dead zone");
-      range_min.set_tooltip_text("The minimal position reachable");
-      range_max.set_tooltip_text("The maximum position reachable");
+    center_min.set_tooltip_text("The minimal value of the dead zone");
+    center_max.set_tooltip_text("The maximum value of the dead zone");
+    range_min.set_tooltip_text("The minimal position reachable");
+    range_max.set_tooltip_text("The maximum position reachable");
 
-      calibration_data.push_back(data);
+    calibration_data.push_back(data);
 
-      std::ostringstream str;
-      str << i;
-      axis_table.attach(*Gtk::manage(new Gtk::Label(str.str())), 0, 1, i+1, i+2);
+    std::ostringstream str;
+    str << i;
+    axis_table.attach(*Gtk::manage(new Gtk::Label(str.str())), 0, 1, i+1, i+2);
 
-      axis_table.attach(center_min, 1, 2, i+1, i+2);
-      axis_table.attach(center_max, 2, 3, i+1, i+2);
+    axis_table.attach(center_min, 1, 2, i+1, i+2);
+    axis_table.attach(center_max, 2, 3, i+1, i+2);
 
-      axis_table.attach(range_min, 3, 4, i+1, i+2);
-      axis_table.attach(range_max, 4, 5, i+1, i+2);
+    axis_table.attach(range_min, 3, 4, i+1, i+2);
+    axis_table.attach(range_max, 4, 5, i+1, i+2);
 
-      axis_table.attach(invert, 5, 6, i+1, i+2, Gtk::SHRINK, Gtk::SHRINK);
-    }
+    axis_table.attach(invert, 5, 6, i+1, i+2, Gtk::SHRINK, Gtk::SHRINK);
+  }
 
   add_button(Gtk::Stock::REVERT_TO_SAVED,  2);
   add_button("Raw Events", 1);
   add_button(Gtk::Stock::CLOSE, 0);
-  
-  axis_frame.add(axis_table);
+
+  scroll.add(axis_table);
+  scroll.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
+  scroll.set_size_request(-1, 300);
+  axis_frame.add(scroll);
 
   get_vbox()->pack_start(axis_frame, Gtk::PACK_EXPAND_WIDGET);
-  
+
   signal_response().connect(sigc::mem_fun(this, &JoystickCalibrationWidget::on_response));
 
   update_with(joystick.get_calibration());
@@ -117,7 +120,7 @@ JoystickCalibrationWidget::JoystickCalibrationWidget(Joystick& joystick)
 void
 JoystickCalibrationWidget::on_clear()
 {
-  joystick.clear_calibration();  
+  joystick.clear_calibration();
   update_with(joystick.get_calibration());
 }
 
@@ -125,31 +128,31 @@ void
 JoystickCalibrationWidget::update_with(const std::vector<Joystick::CalibrationData>& data)
 {
   assert(data.size() == calibration_data.size());
-  
+
   for(int i = 0; i < (int)data.size(); ++i)
-    {
-      calibration_data[i].invert->set_active(data[i].invert);
-      calibration_data[i].center_min->set_value(data[i].center_min);
-      calibration_data[i].center_max->set_value(data[i].center_max);
-      calibration_data[i].range_min->set_value(data[i].range_min);
-      calibration_data[i].range_max->set_value(data[i].range_max);
-    }
+  {
+    calibration_data[i].invert->set_active(data[i].invert);
+    calibration_data[i].center_min->set_value(data[i].center_min);
+    calibration_data[i].center_max->set_value(data[i].center_max);
+    calibration_data[i].range_min->set_value(data[i].range_min);
+    calibration_data[i].range_max->set_value(data[i].range_max);
+  }
 }
 
 void
 JoystickCalibrationWidget::on_apply()
 {
   std::vector<Joystick::CalibrationData> data(calibration_data.size());
-  
+
   for(int i = 0; i < (int)data.size(); ++i)
-    {
-      data[i].calibrate  = true;
-      data[i].invert     = calibration_data[i].invert->get_active();
-      data[i].center_min = calibration_data[i].center_min->get_value();
-      data[i].center_max = calibration_data[i].center_max->get_value();
-      data[i].range_min  = calibration_data[i].range_min->get_value();
-      data[i].range_max  = calibration_data[i].range_max->get_value();
-    }
+  {
+    data[i].calibrate  = true;
+    data[i].invert     = calibration_data[i].invert->get_active();
+    data[i].center_min = calibration_data[i].center_min->get_value();
+    data[i].center_max = calibration_data[i].center_max->get_value();
+    data[i].range_min  = calibration_data[i].range_min->get_value();
+    data[i].range_max  = calibration_data[i].range_max->get_value();
+  }
 
   joystick.set_calibration(data);
 }
@@ -160,25 +163,25 @@ JoystickCalibrationWidget::on_calibrate()
   CalibrateMaximumDialog dialog(joystick);
   dialog.show_all();
   dialog.run();
-  update_with(joystick.get_calibration()); 
+  update_with(joystick.get_calibration());
 }
 
 void
 JoystickCalibrationWidget::on_response(int i)
 {
   if (i == 0)
-    {
-      hide();
-    }
+  {
+    hide();
+  }
   else if (i == 1)
-    {
-      on_clear();
-    }
+  {
+    on_clear();
+  }
   else if (i == 2)
-    {
-      joystick.reset_calibration();
-      update_with(joystick.get_calibration());      
-    }
+  {
+    joystick.reset_calibration();
+    update_with(joystick.get_calibration());
+  }
 }
 

 /* EOF */
diff --git a/src/joystick_calibration_widget.hpp b/src/joystick_calibration_widget.hpp
index d52ef7c..6a3fc4b 100644
--- a/src/joystick_calibration_widget.hpp
+++ b/src/joystick_calibration_widget.hpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -24,6 +24,7 @@
 #include <gtkmm/label.h>
 #include <gtkmm/table.h>
 #include <gtkmm/dialog.h>
+#include <gtkmm/scrolledwindow.h>
 
 #include "joystick.hpp"
 

@@ -37,6 +38,7 @@ private:
   Gtk::Table  axis_table;
   Gtk::HButtonBox buttonbox;
   Gtk::Button calibration_button;
+  Gtk::ScrolledWindow scroll;
 
   struct CalibrationData {
     Gtk::CheckButton* invert;
diff --git a/src/joystick_configuration.cpp b/src/joystick_configuration.cpp
deleted file mode 100644
index 76fdf1a..0000000
--- a/src/joystick_configuration.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-**  jstest-gtk - A graphical joystick tester
-**  Copyright (C) 2009 Ingo Ruhnke <grumbel at gmx.de>
-**
-**  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 3 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 General Public License
-**  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <vector>
-#include <iostream>
-#include <algorithm>
-#include <fstream>
-#include <iterator>
-#include <expat.h>
-
-#include "joystick_configuration.hpp"
-

-JoystickConfiguration::JoystickConfiguration(const std::string& filename)
-{
-}
-
-JoystickConfiguration::~JoystickConfiguration()
-{
-}
-

-/* EOF */
diff --git a/src/joystick_configuration.hpp b/src/joystick_configuration.hpp
deleted file mode 100644
index 3868984..0000000
--- a/src/joystick_configuration.hpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-**  jstest-gtk - A graphical joystick tester
-**  Copyright (C) 2009 Ingo Ruhnke <grumbel at gmx.de>
-**
-**  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 3 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 General Public License
-**  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef HEADER_JSTEST_GTK_JOYSTICK_CONFIGURATION_HPP
-#define HEADER_JSTEST_GTK_JOYSTICK_CONFIGURATION_HPP
-
-#include <string>
-

-class JoystickConfiguration
-{
-private:
-
-public:
-  JoystickConfiguration(const std::string& filename);
-  ~JoystickConfiguration();
-
-  void on_start_element(const char* el, const char** attr);
-  void on_end_element(const char* el);
-  void on_character_data(const char* s, int len);
-  
-private:
-  static void start_element(void* userdata, const char* el, const char** attr);
-  static void end_element(void* userdata, const char* el);
-  static void character_data(void* userdata, const char* s, int len);
-
-private:
-  JoystickConfiguration(const JoystickConfiguration&);
-  JoystickConfiguration& operator=(const JoystickConfiguration&);
-};
-

-#endif
-
-/* EOF */
diff --git a/src/joystick_description.hpp b/src/joystick_description.hpp
index 87cbc02..b99b4d3 100644
--- a/src/joystick_description.hpp
+++ b/src/joystick_description.hpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -34,7 +34,7 @@ public:
                       const std::string& name_,
                       int axis_count_,
                       int button_count_)
-    : filename(filename_), 
+    : filename(filename_),
       name(name_),
       axis_count(axis_count_),
       button_count(button_count_)
diff --git a/src/joystick_list_widget.cpp b/src/joystick_list_widget.cpp
index e369226..5b8f467 100644
--- a/src/joystick_list_widget.cpp
+++ b/src/joystick_list_widget.cpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -72,8 +72,6 @@ JoystickListWidget::JoystickListWidget()
   add_button(Gtk::Stock::PROPERTIES, 1);
   add_button(Gtk::Stock::CLOSE, 0);
 
-  signal_response().connect(sigc::mem_fun(this, &JoystickListWidget::on_response));
-
   // Set model
   device_list = Gtk::ListStore::create(DeviceListColumns::instance());
   treeview.set_model(device_list);
@@ -91,26 +89,26 @@ JoystickListWidget::on_row_activated(const Gtk::TreeModel::Path& path, Gtk::Tree
 {
   Gtk::TreeModel::iterator it = treeview.get_model()->get_iter(path);
   if (it)
-    {
-      Main::current()->show_device_property_dialog((*it)[DeviceListColumns::instance().path]);
-    }
+  {
+    Main::current()->show_device_property_dialog((*it)[DeviceListColumns::instance().path]);
+  }
 }
 
 void
 JoystickListWidget::on_response(int v)
 {
   if (v == 0)
-    {
-      hide();
-    }
+  {
+    hide();
+  }
   else if (v == 1)
-    {
-      on_properties();
-    }
+  {
+    on_properties();
+  }
   else if (v == 2)
-    {
-      on_refresh();
-    }
+  {
+    on_refresh();
+  }
 }
 
 void
@@ -121,18 +119,28 @@ JoystickListWidget::on_refresh()
   device_list->clear();
 
   for(std::vector<JoystickDescription>::const_iterator i = joysticks.begin(); i != joysticks.end(); ++i)
-    {
-      Gtk::ListStore::iterator it = device_list->append();
-      (*it)[DeviceListColumns::instance().icon] = Gdk::Pixbuf::create_from_file("data/generic.png");
-      (*it)[DeviceListColumns::instance().path] = i->filename;
-
-      std::ostringstream out;
-      out << i->name << "\n"
-          << "Device: " << i->filename << "\n"
-          << "Axes: " << i->axis_count << "\n"
-          << "Buttons: " << i->button_count;
-      (*it)[DeviceListColumns::instance().name] = out.str();
-    }
+  {
+    Gtk::ListStore::iterator it = device_list->append();
+
+	const Glib::ustring& name = i->name;
+	Glib::ustring icon_filename;
+	//Playstation icon for ps3 controller
+	if(name == "Sony PLAYSTATION(R)3 Controller") icon_filename = "PS3.png";
+	//Xbox icon for xbox controller
+	else if(name.find("X-Box") != Glib::ustring::npos) icon_filename = "xbox360_small.png";
+	//General icon for the rest
+	else icon_filename = "generic.png";
+
+	(*it)[DeviceListColumns::instance().icon] = Gdk::Pixbuf::create_from_file(Main::current()->get_data_directory() + icon_filename);
+    (*it)[DeviceListColumns::instance().path] = i->filename;
+
+    std::ostringstream out;
+	out << name << "\n"
+        << "Device: " << i->filename << "\n"
+        << "Axes: " << i->axis_count << "\n"
+        << "Buttons: " << i->button_count;
+    (*it)[DeviceListColumns::instance().name] = out.str();
+  }
 
   if (!joysticks.empty())
     treeview.get_selection()->select(device_list->children().begin());
@@ -143,9 +151,9 @@ JoystickListWidget::on_properties()
 {
   Gtk::TreeModel::iterator it = treeview.get_selection()->get_selected();
   if (it)
-    {
-      Main::current()->show_device_property_dialog((*it)[DeviceListColumns::instance().path]);
-    }
+  {
+    Main::current()->show_device_property_dialog((*it)[DeviceListColumns::instance().path]);
+  }
 }
 

 /* EOF */
diff --git a/src/joystick_list_widget.hpp b/src/joystick_list_widget.hpp
index 08acfcd..94902c1 100644
--- a/src/joystick_list_widget.hpp
+++ b/src/joystick_list_widget.hpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
diff --git a/src/joystick_map_widget.cpp b/src/joystick_map_widget.cpp
index 07a8812..c045291 100644
--- a/src/joystick_map_widget.cpp
+++ b/src/joystick_map_widget.cpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -45,19 +45,19 @@ JoystickMapWidget::JoystickMapWidget(Joystick& joystick)
 
   const std::vector<int>& button_mapping = joystick.get_button_mapping();
   for(std::vector<int>::const_iterator i = button_mapping.begin(); i != button_mapping.end(); ++i)
-    {
-      std::ostringstream s;
-      s << (i - button_mapping.begin()) << ": " << btn2str(*i);
-      button_map.add_entry(*i, s.str());
-    }
+  {
+    std::ostringstream s;
+    s << (i - button_mapping.begin()) << ": " << btn2str(*i);
+    button_map.add_entry(*i, s.str());
+  }
 
   const std::vector<int>& axis_mapping = joystick.get_axis_mapping();
   for(std::vector<int>::const_iterator i = axis_mapping.begin(); i != axis_mapping.end(); ++i)
-    {
-      std::ostringstream s;
-      s << (i - axis_mapping.begin()) << ": " << abs2str(*i);
-      axis_map.add_entry(*i, s.str());
-    }
+  {
+    std::ostringstream s;
+    s << (i - axis_mapping.begin()) << ": " << abs2str(*i);
+    axis_map.add_entry(*i, s.str());
+  }
 
   signal_response().connect(sigc::mem_fun(this, &JoystickMapWidget::on_response));
 }
@@ -66,14 +66,14 @@ void
 JoystickMapWidget::on_response(int v)
 {
   if (v == 0)
-    {
-      hide();
-    }
+  {
+    hide();
+  }
   else if (v == 1)
-    {
-      button_map.on_clear();
-      axis_map.on_clear();
-    }
+  {
+    button_map.on_clear();
+    axis_map.on_clear();
+  }
 }
 

 /* EOF */
diff --git a/src/joystick_map_widget.hpp b/src/joystick_map_widget.hpp
index 6d5cb37..8a56931 100644
--- a/src/joystick_map_widget.hpp
+++ b/src/joystick_map_widget.hpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
diff --git a/src/joystick_test_widget.cpp b/src/joystick_test_widget.cpp
index 72bb082..85b9cbd 100644
--- a/src/joystick_test_widget.cpp
+++ b/src/joystick_test_widget.cpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -23,24 +23,21 @@
 #include <gtkmm/dialog.h>
 #include <gtkmm/image.h>
 
-#include "xml_writer.hpp"
 #include "main.hpp"
 #include "joystick.hpp"
 #include "button_widget.hpp"
 #include "joystick_map_widget.hpp"
 #include "joystick_calibration_widget.hpp"
 #include "joystick_test_widget.hpp"
-

-JoystickTestWidget::JoystickTestWidget(Joystick& joystick_)
+
+JoystickTestWidget::JoystickTestWidget(Joystick& joystick_, bool simple_ui)
   : Gtk::Dialog(joystick_.get_name()),
     joystick(joystick_),
-    label("<b>" + joystick.get_name() + "</b>\nDevice: " + joystick.get_filename() , 
+    m_simple_ui(simple_ui),
+    label("<b>" + joystick.get_name() + "</b>\nDevice: " + joystick.get_filename() ,
           Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER),
-    profile_save_button(Gtk::Stock::SAVE_AS),
-    profile_delete_button(Gtk::Stock::DELETE),
     axis_frame("Axes"),
     button_frame("Buttons"),
-    button_table((joystick.get_button_count()-1) / 8 + 1, std::min(joystick.get_button_count(), 8)),
     mapping_button("Mapping"),
     calibration_button("Calibration"),
     buttonbox(Gtk::BUTTONBOX_SPREAD),
@@ -55,15 +52,6 @@ JoystickTestWidget::JoystickTestWidget(Joystick& joystick_)
   label.set_use_markup(true);
   label.set_selectable();
 
-  profile_delete_button.set_tooltip_text("Delete the current profile");
-  profile_save_button.set_tooltip_text("Save the current configuration into a profile");
-
-  profile_hbox.pack_start(profile_delete_button, Gtk::PACK_SHRINK);
-  profile_hbox.pack_start(profile_save_button, Gtk::PACK_SHRINK);
-  profile_hbox.add(profile_entry);
-  profile_delete_button.signal_clicked().connect(sigc::mem_fun(this, &JoystickTestWidget::on_delete_profile));
-  profile_save_button.signal_clicked().connect(sigc::mem_fun(this, &JoystickTestWidget::on_save_profile));
-
   axis_frame.set_border_width(5);
   axis_table.set_border_width(5);
   axis_table.set_spacings(5);
@@ -72,51 +60,38 @@ JoystickTestWidget::JoystickTestWidget(Joystick& joystick_)
   button_table.set_spacings(8);
   buttonbox.set_border_width(5);
 
-  // Use two columns for large number of axes
-  if (joystick.get_axis_count() > 15)
-    axis_table.resize((joystick.get_axis_count()+1)/2, 4);
-  else
-    axis_table.resize(joystick.get_axis_count(), 2);
-      
   for(int i = 0; i < joystick.get_axis_count(); ++i)
-    {
-      std::ostringstream str;
-      str << "Axis " << i << ": ";
-      Gtk::Label& label = *Gtk::manage(new Gtk::Label(str.str()));
-
-      Gtk::ProgressBar& progressbar = *Gtk::manage(new Gtk::ProgressBar());
-      progressbar.set_fraction(0.5);
-
-      if (i >= (int)axis_table.property_n_rows())
-        {
-          axis_table.attach(label, 2, 3, 
-                            i - axis_table.property_n_rows(), i+1 - axis_table.property_n_rows(),     
-                            Gtk::SHRINK, Gtk::FILL);
-          axis_table.attach(progressbar, 3, 4,
-                            i - axis_table.property_n_rows(), i+1 - axis_table.property_n_rows(), 
-                            Gtk::FILL|Gtk::EXPAND, Gtk::EXPAND);
-        }
-      else
-        {
-          axis_table.attach(label, 0, 1, i, i+1, Gtk::SHRINK, Gtk::FILL);
-          axis_table.attach(progressbar, 1, 2, i, i+1, Gtk::FILL|Gtk::EXPAND, Gtk::EXPAND);
-        }
-
-      axes.push_back(&progressbar);
-    }
+  {
+    std::ostringstream str;
+    str << "Axis " << i << ": ";
+    Gtk::Label& label = *Gtk::manage(new Gtk::Label(str.str()));
+
+    Gtk::ProgressBar& progressbar = *Gtk::manage(new Gtk::ProgressBar());
+    progressbar.set_fraction(0.5);
+
+    //Each column must have at most 10 axes
+
+    int x = (i/10)*2;
+    int y = i%10;
+
+    axis_table.attach(label, x, x+1, y, y+1, Gtk::SHRINK, Gtk::FILL);
+    axis_table.attach(progressbar, x+1, x+2, y, y+1, Gtk::FILL|Gtk::EXPAND, Gtk::EXPAND);
+
+    axes.push_back(&progressbar);
+  }
 
   for(int i = 0; i < joystick.get_button_count(); ++i)
-    {
-      int x = i % 8;
-      int y = i / 8;
-
-      std::ostringstream str;
-      str << i;
-      ButtonWidget& button = *Gtk::manage(new ButtonWidget(32, 32, str.str()));
-      button_table.attach(button, x, x+1, y, y+1, Gtk::EXPAND, Gtk::EXPAND);
-      buttons.push_back(&button);
-    }
-  
+  {
+    int x = i / 10;
+    int y = i % 10;
+
+    std::ostringstream str;
+    str << i;
+    ButtonWidget& button = *Gtk::manage(new ButtonWidget(32, 32, str.str()));
+    button_table.attach(button, x, x+1, y, y+1, Gtk::EXPAND, Gtk::EXPAND);
+    buttons.push_back(&button);
+  }
+
   alignment.set_padding(8, 8, 8, 8);
   alignment.add(label);
   get_vbox()->pack_start(alignment, Gtk::PACK_SHRINK);
@@ -124,12 +99,12 @@ JoystickTestWidget::JoystickTestWidget(Joystick& joystick_)
   buttonbox.add(mapping_button);
   buttonbox.add(calibration_button);
 
-  get_vbox()->pack_start(profile_hbox, Gtk::PACK_SHRINK);
-
-  get_vbox()->pack_start(axis_frame,   Gtk::PACK_EXPAND_WIDGET);
-  get_vbox()->pack_start(button_frame, Gtk::PACK_EXPAND_WIDGET);
+  test_hbox.pack_start(axis_frame,   Gtk::PACK_EXPAND_WIDGET);
+  test_hbox.pack_start(button_frame, Gtk::PACK_EXPAND_WIDGET);
+  get_vbox()->pack_start(test_hbox, Gtk::PACK_SHRINK);
   get_vbox()->pack_start(buttonbox, Gtk::PACK_SHRINK);
 
+
   stick_hbox.set_border_width(5);
 
   axis_callbacks.clear();
@@ -138,99 +113,108 @@ JoystickTestWidget::JoystickTestWidget(Joystick& joystick_)
   for(int i = 0; i < (int)joystick.get_axis_count(); ++i)
     axis_callbacks.push_back(sigc::signal<void, double>());
 
-  if (joystick.get_axis_count() == 2) // Simple stick
-    {
-      stick_hbox.pack_start(stick1_widget, Gtk::PACK_EXPAND_PADDING);
-      axis_callbacks[0].connect(sigc::mem_fun(stick1_widget, &AxisWidget::set_x_axis));
-      axis_callbacks[1].connect(sigc::mem_fun(stick1_widget, &AxisWidget::set_y_axis));
-    }
-  else if (joystick.get_axis_count() == 6) // Flightstick
-    {
-      Gtk::Table& table = *Gtk::manage(new Gtk::Table(2, 2));
-      
-      table.attach(stick1_widget, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
-      table.attach(rudder_widget,   0, 1, 1, 2, Gtk::SHRINK, Gtk::SHRINK);
-      table.attach(throttle_widget, 1, 2, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
-
-      stick_hbox.pack_start(table, Gtk::PACK_EXPAND_PADDING);
-      stick_hbox.pack_start(stick3_widget, Gtk::PACK_EXPAND_PADDING);
-
-      axis_callbacks[0].connect(sigc::mem_fun(stick1_widget, &AxisWidget::set_x_axis));
-      axis_callbacks[1].connect(sigc::mem_fun(stick1_widget, &AxisWidget::set_y_axis));
-      axis_callbacks[2].connect(sigc::mem_fun(rudder_widget, &RudderWidget::set_pos));
-      axis_callbacks[3].connect(sigc::mem_fun(throttle_widget, &ThrottleWidget::set_pos));
-      axis_callbacks[4].connect(sigc::mem_fun(stick3_widget, &AxisWidget::set_x_axis));
-      axis_callbacks[5].connect(sigc::mem_fun(stick3_widget, &AxisWidget::set_y_axis));
-    }
-  else if (joystick.get_axis_count() == 6) // Dual Analog Gamepad
-    {
-      // FIXME: never reached as this is the same as Flightstick, no
-      // way to tell them apart from simple axis count
-      stick_hbox.pack_start(stick1_widget, Gtk::PACK_EXPAND_PADDING);
-      stick_hbox.pack_start(stick2_widget, Gtk::PACK_EXPAND_PADDING);
-      stick_hbox.pack_start(stick3_widget, Gtk::PACK_EXPAND_PADDING);
-
-      axis_callbacks[0].connect(sigc::mem_fun(stick1_widget, &AxisWidget::set_x_axis));
-      axis_callbacks[1].connect(sigc::mem_fun(stick1_widget, &AxisWidget::set_y_axis));
-      axis_callbacks[2].connect(sigc::mem_fun(stick2_widget, &AxisWidget::set_x_axis));
-      axis_callbacks[3].connect(sigc::mem_fun(stick2_widget, &AxisWidget::set_y_axis));
-      axis_callbacks[4].connect(sigc::mem_fun(stick3_widget, &AxisWidget::set_x_axis));
-      axis_callbacks[5].connect(sigc::mem_fun(stick3_widget, &AxisWidget::set_y_axis));
-    }
-  else if (joystick.get_axis_count() == 8) // Dual Analog Gamepad + Analog Trigger
-    {
-      stick_hbox.pack_start(stick1_widget, Gtk::PACK_EXPAND_PADDING);
-      stick_hbox.pack_start(stick2_widget, Gtk::PACK_EXPAND_PADDING);
-      stick_hbox.pack_start(stick3_widget, Gtk::PACK_EXPAND_PADDING);
-      stick_hbox.pack_start(left_trigger_widget, Gtk::PACK_EXPAND_PADDING);
-      stick_hbox.pack_start(right_trigger_widget, Gtk::PACK_EXPAND_PADDING);
-
-      axis_callbacks[0].connect(sigc::mem_fun(stick1_widget, &AxisWidget::set_x_axis));
-      axis_callbacks[1].connect(sigc::mem_fun(stick1_widget, &AxisWidget::set_y_axis));
-      axis_callbacks[2].connect(sigc::mem_fun(stick2_widget, &AxisWidget::set_x_axis));
-      axis_callbacks[3].connect(sigc::mem_fun(stick2_widget, &AxisWidget::set_y_axis));
-      axis_callbacks[6].connect(sigc::mem_fun(stick3_widget, &AxisWidget::set_x_axis));
-      axis_callbacks[7].connect(sigc::mem_fun(stick3_widget, &AxisWidget::set_y_axis));
-      axis_callbacks[4].connect(sigc::mem_fun(left_trigger_widget, &ThrottleWidget::set_pos));
-      axis_callbacks[5].connect(sigc::mem_fun(right_trigger_widget, &ThrottleWidget::set_pos));
-    }
-  else if (joystick.get_axis_count() == 7) // Dual Analog Gamepad DragonRise Inc. Generic USB Joystick
-    {
-      stick_hbox.pack_start(stick1_widget, Gtk::PACK_EXPAND_PADDING);
-      stick_hbox.pack_start(stick2_widget, Gtk::PACK_EXPAND_PADDING);
-      stick_hbox.pack_start(stick3_widget, Gtk::PACK_EXPAND_PADDING);
-
-      axis_callbacks[0].connect(sigc::mem_fun(stick1_widget, &AxisWidget::set_x_axis));
-      axis_callbacks[1].connect(sigc::mem_fun(stick1_widget, &AxisWidget::set_y_axis));
-      axis_callbacks[3].connect(sigc::mem_fun(stick2_widget, &AxisWidget::set_x_axis));
-      axis_callbacks[4].connect(sigc::mem_fun(stick2_widget, &AxisWidget::set_y_axis));
-      axis_callbacks[5].connect(sigc::mem_fun(stick3_widget, &AxisWidget::set_x_axis));
-      axis_callbacks[6].connect(sigc::mem_fun(stick3_widget, &AxisWidget::set_y_axis));
-    }
-  else if (joystick.get_axis_count() == 28) // Playstation 3 Controller
-    {
-      stick_hbox.pack_start(stick1_widget, Gtk::PACK_EXPAND_PADDING);
-      stick_hbox.pack_start(stick2_widget, Gtk::PACK_EXPAND_PADDING);
-      // Not using stick3 for now, as the dpad is 4 axis on the PS3, not 2 (one for each direction)
-      //stick_hbox.pack_start(stick3_widget, Gtk::PACK_EXPAND_PADDING);
-      stick_hbox.pack_start(left_trigger_widget, Gtk::PACK_EXPAND_PADDING);
-      stick_hbox.pack_start(right_trigger_widget, Gtk::PACK_EXPAND_PADDING);
-
-      axis_callbacks[0].connect(sigc::mem_fun(stick1_widget, &AxisWidget::set_x_axis));
-      axis_callbacks[1].connect(sigc::mem_fun(stick1_widget, &AxisWidget::set_y_axis));
-      axis_callbacks[2].connect(sigc::mem_fun(stick2_widget, &AxisWidget::set_x_axis));
-      axis_callbacks[3].connect(sigc::mem_fun(stick2_widget, &AxisWidget::set_y_axis));
-      //axis_callbacks[6].connect(sigc::mem_fun(stick3_widget, &AxisWidget::set_x_axis));
-      //axis_callbacks[7].connect(sigc::mem_fun(stick3_widget, &AxisWidget::set_y_axis));
-      axis_callbacks[12].connect(sigc::mem_fun(left_trigger_widget, &ThrottleWidget::set_pos));
-      axis_callbacks[13].connect(sigc::mem_fun(right_trigger_widget, &ThrottleWidget::set_pos));
-    }
-  else
-    {
-      std::cout << "Warning: unknown joystick, not displaying graphical representation." << std::endl;
-    }
+  switch(joystick.get_axis_count())
+  {
+  case 2: // Simple stick
+    stick_hbox.pack_start(stick1_widget, Gtk::PACK_EXPAND_PADDING);
+    axis_callbacks[0].connect(sigc::mem_fun(stick1_widget, &AxisWidget::set_x_axis));
+    axis_callbacks[1].connect(sigc::mem_fun(stick1_widget, &AxisWidget::set_y_axis));
+    break;
+
+  case 6: // Flightstick
+  {
+    Gtk::Table& table = *Gtk::manage(new Gtk::Table(2, 2));
+
+    table.attach(stick1_widget, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
+    table.attach(rudder_widget,   0, 1, 1, 2, Gtk::SHRINK, Gtk::SHRINK);
+    table.attach(throttle_widget, 1, 2, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
+
+    stick_hbox.pack_start(table, Gtk::PACK_EXPAND_PADDING);
+    stick_hbox.pack_start(stick3_widget, Gtk::PACK_EXPAND_PADDING);
+
+    axis_callbacks[0].connect(sigc::mem_fun(stick1_widget, &AxisWidget::set_x_axis));
+    axis_callbacks[1].connect(sigc::mem_fun(stick1_widget, &AxisWidget::set_y_axis));
+    axis_callbacks[2].connect(sigc::mem_fun(rudder_widget, &RudderWidget::set_pos));
+    axis_callbacks[3].connect(sigc::mem_fun(throttle_widget, &ThrottleWidget::set_pos));
+    axis_callbacks[4].connect(sigc::mem_fun(stick3_widget, &AxisWidget::set_x_axis));
+    axis_callbacks[5].connect(sigc::mem_fun(stick3_widget, &AxisWidget::set_y_axis));
+    break;
+  }
+    /*
+   // Dual Analog Gamepad
+
+    // FIXME: never reached as this is the same as Flightstick, no
+    // way to tell them apart from simple axis count
+    stick_hbox.pack_start(stick1_widget, Gtk::PACK_EXPAND_PADDING);
+    stick_hbox.pack_start(stick2_widget, Gtk::PACK_EXPAND_PADDING);
+    stick_hbox.pack_start(stick3_widget, Gtk::PACK_EXPAND_PADDING);
+
+    axis_callbacks[0].connect(sigc::mem_fun(stick1_widget, &AxisWidget::set_x_axis));
+    axis_callbacks[1].connect(sigc::mem_fun(stick1_widget, &AxisWidget::set_y_axis));
+    axis_callbacks[2].connect(sigc::mem_fun(stick2_widget, &AxisWidget::set_x_axis));
+    axis_callbacks[3].connect(sigc::mem_fun(stick2_widget, &AxisWidget::set_y_axis));
+    axis_callbacks[4].connect(sigc::mem_fun(stick3_widget, &AxisWidget::set_x_axis));
+    axis_callbacks[5].connect(sigc::mem_fun(stick3_widget, &AxisWidget::set_y_axis));
+    */
+
+  case 8: // Dual Analog Gamepad + Analog Trigger
+    stick_hbox.pack_start(stick1_widget, Gtk::PACK_EXPAND_PADDING);
+    stick_hbox.pack_start(stick2_widget, Gtk::PACK_EXPAND_PADDING);
+    stick_hbox.pack_start(stick3_widget, Gtk::PACK_EXPAND_PADDING);
+    stick_hbox.pack_start(left_trigger_widget, Gtk::PACK_EXPAND_PADDING);
+    stick_hbox.pack_start(right_trigger_widget, Gtk::PACK_EXPAND_PADDING);
+
+    axis_callbacks[0].connect(sigc::mem_fun(stick1_widget, &AxisWidget::set_x_axis));
+    axis_callbacks[1].connect(sigc::mem_fun(stick1_widget, &AxisWidget::set_y_axis));
+    axis_callbacks[2].connect(sigc::mem_fun(stick2_widget, &AxisWidget::set_x_axis));
+    axis_callbacks[3].connect(sigc::mem_fun(stick2_widget, &AxisWidget::set_y_axis));
+    axis_callbacks[6].connect(sigc::mem_fun(stick3_widget, &AxisWidget::set_x_axis));
+    axis_callbacks[7].connect(sigc::mem_fun(stick3_widget, &AxisWidget::set_y_axis));
+    axis_callbacks[4].connect(sigc::mem_fun(left_trigger_widget, &ThrottleWidget::set_pos));
+    axis_callbacks[5].connect(sigc::mem_fun(right_trigger_widget, &ThrottleWidget::set_pos));
+    break;
+
+
+  case 7: // Dual Analog Gamepad DragonRise Inc. Generic USB Joystick
+    stick_hbox.pack_start(stick1_widget, Gtk::PACK_EXPAND_PADDING);
+    stick_hbox.pack_start(stick2_widget, Gtk::PACK_EXPAND_PADDING);
+    stick_hbox.pack_start(stick3_widget, Gtk::PACK_EXPAND_PADDING);
+
+    axis_callbacks[0].connect(sigc::mem_fun(stick1_widget, &AxisWidget::set_x_axis));
+    axis_callbacks[1].connect(sigc::mem_fun(stick1_widget, &AxisWidget::set_y_axis));
+    axis_callbacks[3].connect(sigc::mem_fun(stick2_widget, &AxisWidget::set_x_axis));
+    axis_callbacks[4].connect(sigc::mem_fun(stick2_widget, &AxisWidget::set_y_axis));
+    axis_callbacks[5].connect(sigc::mem_fun(stick3_widget, &AxisWidget::set_x_axis));
+    axis_callbacks[6].connect(sigc::mem_fun(stick3_widget, &AxisWidget::set_y_axis));
+    break;
+
+  case 27: // Playstation 3 Controller
+    stick_hbox.pack_start(stick1_widget, Gtk::PACK_EXPAND_PADDING);
+    stick_hbox.pack_start(stick2_widget, Gtk::PACK_EXPAND_PADDING);
+    // Not using stick3 for now, as the dpad is 4 axis on the PS3, not 2 (one for each direction)
+    //stick_hbox.pack_start(stick3_widget, Gtk::PACK_EXPAND_PADDING);
+    stick_hbox.pack_start(left_trigger_widget, Gtk::PACK_EXPAND_PADDING);
+    stick_hbox.pack_start(right_trigger_widget, Gtk::PACK_EXPAND_PADDING);
+
+    axis_callbacks[0].connect(sigc::mem_fun(stick1_widget, &AxisWidget::set_x_axis));
+    axis_callbacks[1].connect(sigc::mem_fun(stick1_widget, &AxisWidget::set_y_axis));
+    axis_callbacks[2].connect(sigc::mem_fun(stick2_widget, &AxisWidget::set_x_axis));
+    axis_callbacks[3].connect(sigc::mem_fun(stick2_widget, &AxisWidget::set_y_axis));
+    //axis_callbacks[6].connect(sigc::mem_fun(stick3_widget, &AxisWidget::set_x_axis));
+    //axis_callbacks[7].connect(sigc::mem_fun(stick3_widget, &AxisWidget::set_y_axis));
+    axis_callbacks[12].connect(sigc::mem_fun(left_trigger_widget, &ThrottleWidget::set_pos));
+    axis_callbacks[13].connect(sigc::mem_fun(right_trigger_widget, &ThrottleWidget::set_pos));
+    break;
+
+  default:
+    std::cout << "Warning: unknown joystick, not displaying graphical representation." << std::endl;
+  }
+
+  if (!m_simple_ui)
+  {
+    axis_vbox.pack_start(stick_hbox, Gtk::PACK_SHRINK);
+  }
 
-  axis_vbox.pack_start(stick_hbox, Gtk::PACK_SHRINK);
   axis_vbox.add(axis_table);
   axis_frame.add(axis_vbox);
 
@@ -285,34 +269,4 @@ JoystickTestWidget::on_response(int v)
   hide();
 }
 
-void
-JoystickTestWidget::on_save_profile()
-{
-  on_save_profile_as("Hello World");
-}
-
-void
-JoystickTestWidget::on_save_profile_as(const std::string& name)
-{
-  std::ostringstream profile_name; 
-  profile_name << "Profile " <<  profile_entry.get_model()->children().size();
-  profile_entry.append_text(profile_name.str());
-  profile_entry.set_active_text(profile_name.str());
-
-  std::ostringstream filename;
-  filename << Main::current()->get_cfg_directory() << "/" << "profile"
-           << profile_entry.get_model()->children().size() << ".xml";
-  XMLWriter out(filename.str());
-  out.start_section("joysticks");
-  joystick.write(out);
-  out.end_section("joysticks");
-}
-
-void
-JoystickTestWidget::on_delete_profile()
-{
-  // FIXME: Bad idea, could lead to deletion of the wrong entry when text is the same
-  profile_entry.remove_text(profile_entry.get_active_text());
-}
-

 /* EOF */
diff --git a/src/joystick_test_widget.hpp b/src/joystick_test_widget.hpp
index 41d4e34..cb26245 100644
--- a/src/joystick_test_widget.hpp
+++ b/src/joystick_test_widget.hpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -43,25 +43,23 @@ class JoystickTestWidget : public Gtk::Dialog
 {
 private:
   Joystick& joystick;
+  bool m_simple_ui;
+
   Gtk::Alignment alignment;
   Gtk::Label label;
 
-  Gtk::HBox  profile_hbox;
-  Gtk::ToolButton profile_save_button;
-  Gtk::ToolButton profile_delete_button;
-  Gtk::ComboBoxText profile_entry;
-
   Gtk::Frame axis_frame;
   Gtk::VBox  axis_vbox;
   Gtk::Frame button_frame;
   Gtk::Table axis_table;
   Gtk::Table button_table;
+  Gtk::HBox  test_hbox;
   Gtk::HBox  stick_hbox;
 
   Gtk::Button mapping_button;
   Gtk::Button calibration_button;
   Gtk::HButtonBox buttonbox;
-  
+
   AxisWidget stick1_widget;
   AxisWidget stick2_widget;
   AxisWidget stick3_widget;
@@ -71,7 +69,7 @@ private:
 
   ThrottleWidget left_trigger_widget;
   ThrottleWidget right_trigger_widget;
-  
+
   std::vector<Gtk::ProgressBar*> axes;
   std::vector<ButtonWidget*>     buttons;
 
@@ -81,7 +79,7 @@ private:
   std::vector<sigc::signal<void, double> > axis_callbacks;
 
 public:
-  JoystickTestWidget(Joystick& joystick);
+  JoystickTestWidget(Joystick& joystick, bool simple_ui);
 
   void axis_move(int number, int value);
   void button_move(int number, bool value);
@@ -90,10 +88,6 @@ public:
   void on_mapping();
   void on_response(int v);
 
-  void on_save_profile();
-  void on_save_profile_as(const std::string& name);
-  void on_delete_profile();
-
 private:
   JoystickTestWidget(const JoystickTestWidget&);
   JoystickTestWidget& operator=(const JoystickTestWidget&);
diff --git a/src/jscfg.cpp b/src/jscfg.cpp
deleted file mode 100644
index 33d323e..0000000
--- a/src/jscfg.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-**  jstest-gtk - A graphical joystick tester
-**  Copyright (C) 2009 Ingo Ruhnke <grumbel at gmx.de>
-**
-**  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 3 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 General Public License
-**  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <iostream>
-#include "jscfg.hpp"
-

-void print_help()
-{
-  std::cout << "Usage: jscfg [OPTIONS] JOYSTICKDEVICE\n"
-            << "\n" 
-            << "  --help, -h                 Display this help\n"
-            << "  --btnmap, -b B1,B2,...     Display this help\n"
-            << "  --axismap, -a A1,A2,...    Display this help\n"
-}
-

-int main(int argc, char** argv)
-{
-  for(int i = 1; i < argc; ++i)
-    {
-      
-    }
-  
-  return 0;
-}
-

-/* EOF */
diff --git a/src/main.cpp b/src/main.cpp
index a74cd13..d8023f4 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -24,18 +24,21 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#include "binreloc.h"
+
 #include "joystick_test_widget.hpp"
 #include "joystick_list_widget.hpp"
 #include "joystick_map_widget.hpp"
 #include "joystick_calibration_widget.hpp"
 #include "joystick.hpp"
 #include "main.hpp"
-#include "xml_writer.hpp"
 
 Main* Main::current_ = 0;
 

-Main::Main()
-  : list_dialog(0)
+Main::Main(const std::string& datadir_)
+  : datadir(datadir_),
+    m_simple_ui(false),
+    list_dialog(0)
 {
   current_ = this;
 }
@@ -48,21 +51,23 @@ void
 Main::show_device_list_dialog()
 {
   if (list_dialog)
-    {
-      list_dialog->show();
-    }
+  {
+    list_dialog->show();
+  }
   else
-    {
-      list_dialog = new JoystickListWidget();
-      list_dialog->show_all();
-    }
+  {
+    list_dialog = new JoystickListWidget();
+    dialogs.push_back(list_dialog);
+    list_dialog->signal_hide().connect(sigc::bind(sigc::mem_fun(this, &Main::on_dialog_hide), list_dialog));
+    list_dialog->show_all();
+  }
 }
 
 void
 Main::show_device_property_dialog(const std::string& filename)
 {
   Joystick* joystick = new Joystick(filename);
-  JoystickTestWidget* dialog = new JoystickTestWidget(*joystick);
+  JoystickTestWidget* dialog = new JoystickTestWidget(*joystick, m_simple_ui);
   dialog->signal_hide().connect(sigc::bind(sigc::mem_fun(this, &Main::on_dialog_hide), dialog));
   dialog->show_all();
   joysticks.push_back(joystick);
@@ -94,9 +99,9 @@ Main::on_dialog_hide(Gtk::Dialog* dialog)
   delete dialog;
 
   if (dialogs.empty())
-    {
-      Gtk::Main::quit();
-    }
+  {
+    Gtk::Main::quit();
+  }
 }
 
 int
@@ -104,123 +109,120 @@ Main::main(int argc, char** argv)
 {
   typedef std::vector<std::string> DeviceFiles;
   DeviceFiles device_files;
-  std::string config_save_file;
 
   for(int i = 1; i < argc; ++i)
+  {
+    if (strcmp("--help", argv[i]) == 0 ||
+        strcmp("-h", argv[i]) == 0)
+    {
+      std::cout << "Usage: " << argv[0] << " [OPTIONS]... [DEVICE]...\n"
+                << "A graphical joystick tester.\n"
+                << "\n"
+                << "Options:\n"
+                << "  -h, --help      Display this help and exit\n"
+                << "  -v, --version   Display version information and exit\n"
+                << "  --simple        Hide graphical representation of axis\n"
+                << "\n"
+                << "Report bugs to Ingo Ruhnke <grumbel at gmx.de>.\n";
+      return 0;
+    }
+    else if (strcmp("--version", argv[i]) == 0 ||
+             strcmp("-v", argv[i]) == 0)
+    {
+      std::cout << "jstest-gtk 0.1.0" << std::endl;
+      return 0;
+    }
+    else if (strcmp("--simple", argv[i]) == 0)
+    {
+      m_simple_ui = true;
+    }
+    else if (argv[i][0] == '-')
+    {
+      std::cout << "Error: " << argv[0] << ": unrecognized option '" << argv[i] << "'" << std::endl;
+      return EXIT_FAILURE;
+    }
+    else
     {
-      if (strcmp("--help", argv[i]) == 0 ||
-          strcmp("-h", argv[i]) == 0)
-        {
-          std::cout << "Usage: " << argv[0] << " [OPTIONS]... [DEVICE]...\n"
-                    << "A graphical joystick tester.\n"
-                    << "\n"
-                    << "Options:\n"
-                    << "  -h, --help      Display this help and exit\n"
-                    << "  -v, --version   Display version information and exit\n"
-                    << "  -l, --load CFG  Load load configuration from file and apply them\n"
-                    << "  -s, --save CFG  Save current device configuration to file CFG\n"
-                    << "\n"
-                    << "Report bugs to Ingo Ruhnke <grumbel at gmx.de>.\n";
-          return 0;
-        }
-      else if (strcmp("--load", argv[i]) == 0 ||
-               strcmp("-l", argv[i]) == 0)
-        {
-          ++i;
-          if (i < argc)
-            {
-              std::cout << "Configuration file load is not yet implemented" << std::endl;
-              return 0;
-            }
-          else
-            {
-              std::cout << "Error: " << argv[i-1] << " expected an argument" << std::endl;
-              exit(EXIT_FAILURE);
-            }         
-        }
-      else if (strcmp("--save", argv[i]) == 0 ||
-               strcmp("-s", argv[i]) == 0)
-        {
-          ++i;
-          if (i < argc)
-            {
-              config_save_file = argv[i];
-            }
-          else
-            {
-              std::cout << "Error: " << argv[i-1] << " expected an argument" << std::endl;
-              exit(EXIT_FAILURE);
-            }
-        }
-      else if (strcmp("--version", argv[i]) == 0 ||
-               strcmp("-v", argv[i]) == 0)
-        {
-          std::cout << "jstest-gtk 0.1.0" << std::endl;
-          return 0;
-        }
-      else if (argv[i][0] == '-')
-        {
-          std::cout << "Error: " << argv[0] << ": unrecognized option '" << argv[i] << "'" << std::endl;
-          return EXIT_FAILURE;
-        }
-      else
-        {
-          device_files.push_back(argv[i]);
-        }
+      device_files.push_back(argv[i]);
     }
+  }
 
-  if (!config_save_file.empty())
+  try
+  {
+    Glib::set_application_name("Joystick Test");
+    Glib::set_prgname("jstest-gtk");
+    cfg_directory = Glib::build_filename(Glib::get_user_config_dir(), Glib::get_prgname());
+    if (access(cfg_directory.c_str(), R_OK | W_OK) != 0 &&
+        mkdir(cfg_directory.c_str(), 0770) != 0)
     {
-      XMLWriter out(config_save_file);
-      out.start_section("joysticks");
-      for(DeviceFiles::iterator i = device_files.begin(); i != device_files.end(); ++i)
-        {
-          Joystick joystick(*i);
-          joystick.write(out);
-        }
-      out.end_section("joysticks");
+      throw std::runtime_error(cfg_directory + ": " + strerror(errno));
     }
-  else
+    Gtk::Main kit(&argc, &argv);
+
+    if (device_files.empty())
+    {
+      show_device_list_dialog();
+    }
+    else
     {
-      Glib::set_application_name("Joystick Test");
-      Glib::set_prgname("jstest-gtk");
-      cfg_directory = Glib::build_filename(Glib::get_user_config_dir(), Glib::get_prgname());
-      if (access(cfg_directory.c_str(), R_OK | W_OK) != 0 &&
-          mkdir(cfg_directory.c_str(), 0770) != 0)
-        {
-          throw std::runtime_error(cfg_directory + ": " + strerror(errno));
-        }
-      Gtk::Main kit(&argc, &argv);
-
-      if (device_files.empty())
-        {
-          show_device_list_dialog();
-        }
-      else
-        {
-          for(DeviceFiles::iterator i = device_files.begin(); i != device_files.end(); ++i)
-            {
-              show_device_property_dialog(*i);
-            }
-        }
-      Gtk::Main::run();
+      for(DeviceFiles::iterator i = device_files.begin(); i != device_files.end(); ++i)
+      {
+        show_device_property_dialog(*i);
+      }
     }
+    Gtk::Main::run();
+  }
+  catch(std::exception& err)
+  {
+    std::cout << "Error: " << err.what() << std::endl;
+    return EXIT_FAILURE;
+  }
+  catch(Glib::Exception& err)
+  {
+    std::cout << "Error: " << err.what() << std::endl;
+    return EXIT_FAILURE;
+  }
 
   return 0;
 }
 

-int main(int argc, char** argv)
+std::string find_datadir()
 {
-  try 
+  BrInitError error;
+  if (!br_init(&error))
+  {
+    std::ostringstream out;
+    out << "Error: Couldn't init binreloc: " << error;
+    throw std::runtime_error(out.str());
+  }
+  else
+  {
+    char* c_prefix = br_find_exe_dir(NULL);
+    if (!c_prefix)
     {
-      Main app;
-      return app.main(argc, argv);
-    } 
-  catch(std::exception& err) 
+      throw std::runtime_error("Error: Couldn't find prefix");
+    }
+    else
     {
-      std::cout << "Error: " << err.what() << std::endl;
-      return EXIT_FAILURE;
+      std::string prefix = c_prefix;
+      free(c_prefix);
+      return prefix + "/data/";
     }
+  }
+}
+

+int main(int argc, char** argv)
+{
+  try
+  {
+    Main app(find_datadir());
+    return app.main(argc, argv);
+  }
+  catch(std::exception& err)
+  {
+    std::cout << "Error: " << err.what() << std::endl;
+    return EXIT_FAILURE;
+  }
 }
 

 /* EOF */
diff --git a/src/main.hpp b/src/main.hpp
index d14d37e..e075182 100644
--- a/src/main.hpp
+++ b/src/main.hpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -33,6 +33,9 @@ public:
   static Main* current() { return current_; }
 
 private:
+  std::string datadir;
+  bool m_simple_ui;
+
   JoystickListWidget* list_dialog;
 
   std::vector<Joystick*>    joysticks;
@@ -43,7 +46,7 @@ private:
   void on_dialog_hide(Gtk::Dialog* dialog);
 
 public:
-  Main();
+  Main(const std::string& datadir);
   ~Main();
 
   void show_device_list_dialog();
@@ -54,6 +57,7 @@ public:
   int main(int argc, char** argv);
 
   std::string get_cfg_directory() const { return cfg_directory; }
+  std::string get_data_directory() const { return datadir; }
 };
 

 #endif
diff --git a/src/remap_widget.cpp b/src/remap_widget.cpp
index 72509e2..b96b189 100644
--- a/src/remap_widget.cpp
+++ b/src/remap_widget.cpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -61,10 +61,13 @@ RemapWidget::RemapWidget(Joystick& joystick_, Mode mode_)
   set_border_width(5);
   treeview.set_border_width(5);
 
-  pack_start(treeview,  Gtk::PACK_EXPAND_WIDGET);
-  
+  scroll.add(treeview);
+  scroll.set_size_request(-1, 300);
+  scroll.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
+  pack_start(scroll,  Gtk::PACK_EXPAND_WIDGET);
+
   treeview.set_reorderable();
-  
+
   map_list->signal_row_inserted().connect(sigc::mem_fun(this, &RemapWidget::on_my_row_inserted));
   map_list->signal_row_deleted().connect(sigc::mem_fun(this, &RemapWidget::on_my_row_deleted));
   map_list->signal_rows_reordered().connect(sigc::mem_fun(this, &RemapWidget::on_my_rows_reordered));
@@ -95,12 +98,12 @@ RemapWidget::on_clear()
   // Convert the ListStore into a vector
   std::vector<RemapEntry> rows;
   for(Gtk::TreeIter i = map_list->children().begin(); i != map_list->children().end(); ++i)
-    {
-      RemapEntry entry;
-      entry.id   = (*i)[RemapWidgetColumns::instance().id];
-      entry.name = (*i)[RemapWidgetColumns::instance().name];
-      rows.push_back(entry);
-    }
+  {
+    RemapEntry entry;
+    entry.id   = (*i)[RemapWidgetColumns::instance().id];
+    entry.name = (*i)[RemapWidgetColumns::instance().name];
+    rows.push_back(entry);
+  }
 
   // Sort the vector
   std::sort(rows.begin(), rows.end());
@@ -108,9 +111,9 @@ RemapWidget::on_clear()
   // Renter the vector into the liststore
   map_list->clear();
   for(std::vector<RemapEntry>::iterator i = rows.begin(); i != rows.end(); ++i)
-    {
-      add_entry(i->id, i->name);                
-    }
+  {
+    add_entry(i->id, i->name);
+  }
 
   on_apply();
 }
@@ -121,27 +124,27 @@ RemapWidget::on_apply()
   std::vector<int> mapping;
   std::vector<int> mapping_old;
   for(Gtk::TreeIter i = map_list->children().begin(); i != map_list->children().end(); ++i)
-    {
-      mapping.push_back((*i)[RemapWidgetColumns::instance().id]);
-    }
+  {
+    mapping.push_back((*i)[RemapWidgetColumns::instance().id]);
+  }
 
   if (mode == REMAP_AXIS)
-    {
-      mapping_old = joystick.get_axis_mapping();
-      joystick.set_axis_mapping(mapping);
-      joystick.correct_calibration(mapping_old, mapping);
-    }
+  {
+    mapping_old = joystick.get_axis_mapping();
+    joystick.set_axis_mapping(mapping);
+    joystick.correct_calibration(mapping_old, mapping);
+  }
   else if (mode == REMAP_BUTTON)
-    {
-      joystick.set_button_mapping(mapping);
-    }
+  {
+    joystick.set_button_mapping(mapping);
+  }
 }
 
 void
 RemapWidget::on_my_rows_reordered(const Gtk::TreeModel::Path& path, const Gtk::TreeModel::iterator& iter, int* new_order)
 {
   // std::cout << "on_my_rows_reordered" << std::endl;
-}                         
+}
 
 void
 RemapWidget::on_my_row_inserted(const Gtk::TreeModel::Path& path, const Gtk::TreeModel::iterator& iter)
@@ -153,21 +156,21 @@ void
 RemapWidget::on_my_row_deleted(const Gtk::TreeModel::Path& path)
 {
   // std::cout << "on_my_rows_deleted" << std::endl;
-  
+
   if (mode == REMAP_AXIS)
+  {
+    if (joystick.get_axis_count() == (int)map_list->children().size())
     {
-      if (joystick.get_axis_count() == (int)map_list->children().size())
-        {
-          on_apply();
-        }
+      on_apply();
     }
+  }
   else if (mode == REMAP_BUTTON)
+  {
+    if (joystick.get_button_count() == (int)map_list->children().size())
     {
-      if (joystick.get_button_count() == (int)map_list->children().size())
-        {
-          on_apply();
-        }
+      on_apply();
     }
+  }
 }
 

 /* EOF */
diff --git a/src/remap_widget.hpp b/src/remap_widget.hpp
index 0521ee2..85063c8 100644
--- a/src/remap_widget.hpp
+++ b/src/remap_widget.hpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -20,11 +20,10 @@
 #define HEADER_JSTEST_GTK_REMAP_WIDGET_HPP
 
 #include <gtkmm/box.h>
-#include <gtkmm/button.h>
-#include <gtkmm/buttonbox.h>
 #include <gtkmm/liststore.h>
 #include <gtkmm/treeview.h>
 #include <gtkmm/treemodel.h>
+#include <gtkmm/scrolledwindow.h>
 
 class Joystick;
 

@@ -39,6 +38,7 @@ private:
 
   Gtk::TreeView treeview;
   Glib::RefPtr<Gtk::ListStore> map_list;
+  Gtk::ScrolledWindow scroll;
 
 public:
   RemapWidget(Joystick& joystick_, Mode mode);
@@ -46,10 +46,10 @@ public:
   void add_entry(int id, const std::string& str);
   void on_clear();
   void on_apply();
-  void on_my_row_inserted(const Gtk::TreeModel::Path& path, const Gtk::TreeModel::iterator& iter); 
-  void on_my_row_deleted(const Gtk::TreeModel::Path& path); 
+  void on_my_row_inserted(const Gtk::TreeModel::Path& path, const Gtk::TreeModel::iterator& iter);
+  void on_my_row_deleted(const Gtk::TreeModel::Path& path);
   void on_my_rows_reordered(const Gtk::TreeModel::Path& path, const Gtk::TreeModel::iterator& iter, int* new_order);
-                         
+
 private:
   RemapWidget(const RemapWidget&);
   RemapWidget& operator=(const RemapWidget&);
diff --git a/src/rudder_widget.cpp b/src/rudder_widget.cpp
index 34b2d4b..6589f25 100644
--- a/src/rudder_widget.cpp
+++ b/src/rudder_widget.cpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -29,40 +29,40 @@ RudderWidget::on_expose_event(GdkEventExpose* event)
 {
   double p = (pos + 1.0)/2.0;
   if (0)
-    {
-      get_window()->draw_rectangle(get_style()->get_fg_gc(get_state()),
-                                   true,
-                                   (get_allocation().get_width() * p) - 4, 0,
-                                   9, get_allocation().get_height()-1);
-    }
+  {
+    get_window()->draw_rectangle(get_style()->get_fg_gc(get_state()),
+                                 true,
+                                 (get_allocation().get_width() * p) - 4, 0,
+                                 9, get_allocation().get_height()-1);
+  }
 
   Glib::RefPtr<Gdk::Window> window = get_window();
   if(window)
-    {
-      Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
-      
-      int w  = get_allocation().get_width()-10;
-      int h  = get_allocation().get_height()-10;
+  {
+    Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
+
+    int w  = get_allocation().get_width()-10;
+    int h  = get_allocation().get_height()-10;
 
-      cr->translate(5, 5);
+    cr->translate(5, 5);
 
-      // Outer Rectangle
-      cr->set_source_rgb(0.0, 0.0, 0.0);
-      cr->set_line_width(1.0);
-      cr->rectangle(0, 0, w, h);
-      cr->stroke();
+    // Outer Rectangle
+    cr->set_source_rgb(0.0, 0.0, 0.0);
+    cr->set_line_width(1.0);
+    cr->rectangle(0, 0, w, h);
+    cr->stroke();
 
-      cr->set_source_rgba(0.0, 0.0, 0.0, 0.5);
-      cr->move_to(w/2, 0);
-      cr->line_to(w/2, h);
-      cr->stroke();
+    cr->set_source_rgba(0.0, 0.0, 0.0, 0.5);
+    cr->move_to(w/2, 0);
+    cr->line_to(w/2, h);
+    cr->stroke();
 
-      cr->set_line_width(2.0);
-      cr->set_source_rgb(0.0, 0.0, 0.0);
-      cr->move_to(w * p, 0);
-      cr->line_to(w * p, h);
-      cr->stroke();
-    }
+    cr->set_line_width(2.0);
+    cr->set_source_rgb(0.0, 0.0, 0.0);
+    cr->move_to(w * p, 0);
+    cr->line_to(w * p, h);
+    cr->stroke();
+  }
 
   return true;
 }
diff --git a/src/rudder_widget.hpp b/src/rudder_widget.hpp
index 11788ed..b2da3d8 100644
--- a/src/rudder_widget.hpp
+++ b/src/rudder_widget.hpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
diff --git a/src/throttle_widget.cpp b/src/throttle_widget.cpp
index b5f5687..0b53c96 100644
--- a/src/throttle_widget.cpp
+++ b/src/throttle_widget.cpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -33,34 +33,34 @@ ThrottleWidget::on_expose_event(GdkEventExpose* event)
   double p = 1.0 - (pos + 1.0) / 2.0;
 
   if (0)
-    {
-      int h = (get_allocation().get_height() * p);
-      get_window()->draw_rectangle(get_style()->get_fg_gc(get_state()),
-                                   true,
-                                   0, get_allocation().get_height() - h,
-                                   get_allocation().get_width(), h);
-    }
+  {
+    int h = (get_allocation().get_height() * p);
+    get_window()->draw_rectangle(get_style()->get_fg_gc(get_state()),
+                                 true,
+                                 0, get_allocation().get_height() - h,
+                                 get_allocation().get_width(), h);
+  }
 
   Glib::RefPtr<Gdk::Window> window = get_window();
   if(window)
-    {
-      Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
+  {
+    Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
 
-      int w  = get_allocation().get_width()-10;
-      int h  = get_allocation().get_height()-10;
+    int w  = get_allocation().get_width()-10;
+    int h  = get_allocation().get_height()-10;
 
-      cr->translate(5, 5);
+    cr->translate(5, 5);
 
-      // Outer Rectangle
-      cr->set_source_rgb(0.0, 0.0, 0.0);
-      cr->set_line_width(1.0);
-      cr->rectangle(0, 0, w, h);
-      cr->stroke();
+    // Outer Rectangle
+    cr->set_source_rgb(0.0, 0.0, 0.0);
+    cr->set_line_width(1.0);
+    cr->rectangle(0, 0, w, h);
+    cr->stroke();
 
-      int dh = h*p;
-      cr->rectangle(0, h - dh, w, dh);
-      cr->fill();
-    }
+    int dh = h*p;
+    cr->rectangle(0, h - dh, w, dh);
+    cr->fill();
+  }
 
   return true;
 }
diff --git a/src/throttle_widget.hpp b/src/throttle_widget.hpp
index af7e6b8..a90043e 100644
--- a/src/throttle_widget.hpp
+++ b/src/throttle_widget.hpp
@@ -6,12 +6,12 @@
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 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 General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
diff --git a/src/xml_parser.cpp b/src/xml_parser.cpp
deleted file mode 100644
index d3ff468..0000000
--- a/src/xml_parser.cpp
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
-**  jstest-gtk - A graphical joystick tester
-**  Copyright (C) 2009 Ingo Ruhnke <grumbel at gmx.de>
-**
-**  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 3 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 General Public License
-**  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <stdexcept>
-#include <iostream>
-#include <fstream>
-#include <sstream>
-#include <expat.h>
-
-#include "xml_parser.hpp"
-

-// static C functions that map back to the C++ member functions
-void
-XMLParser::start_element(void* userdata, const char* el, const char** attr)
-{
-  static_cast<XMLParser*>(userdata)->on_start_element(el, attr);
-}
-
-void
-XMLParser::end_element(void* userdata, const char* el)
-{
-  static_cast<XMLParser*>(userdata)->on_end_element(el);
-}
-
-void
-XMLParser::character_data(void* userdata, const char* s, int len)
-{
-  static_cast<XMLParser*>(userdata)->on_character_data(s, len);
-}
-

-std::auto_ptr<XMLNode>
-XMLParser::parse(const std::string& filename)
-{
-  XMLParser tree(filename);
-  return tree.get_root();
-}
-

-XMLParser::XMLParser(const std::string& filename_)
-  : filename(filename_),
-    parser(0)
-{
-  std::vector<char> data;
-  { // Read the file into the vector data
-    std::ifstream in(filename.c_str(), std::ios::binary);
-    if (!in)
-      {
-        throw std::runtime_error("couldn't open: " + filename);
-      }
-    else
-      {
-        in.seekg (0, std::ios::end);
-        data.resize(in.tellg());
-        in.seekg (0, std::ios::beg);
-        in.read(&*data.begin(), data.size());
-      }
-  }
-
-  parser = XML_ParserCreate(NULL);
-  XML_SetUserData(parser, this);
-  XML_SetElementHandler(parser, &start_element, &end_element);
-  XML_SetCharacterDataHandler(parser, &character_data);
-
-  if (XML_Parse(parser, &*data.begin(), data.size(), 0) == XML_STATUS_ERROR)
-    {
-      std::ostringstream out;
-      out << filename << ":" << XML_GetCurrentLineNumber(parser)
-          << ": parse error: " << XML_ErrorString(XML_GetErrorCode(parser));
-
-      throw std::runtime_error(out.str());
-    }
-}
-
-XMLParser::~XMLParser()
-{
-  XML_ParserFree(parser);
-}
-
-void
-XMLParser::on_start_element(const char* name, const char** attr)
-{
-  if (*attr)
-    raise_error("attribute not allowed");
-
-  // spaces are ignored, everything else is an error
-  for(int i = 0; i < (int)cdata.size(); ++i)
-    if (!isspace(cdata[i]))
-      raise_error("unexpected character data");
-  cdata.clear();
-
-  if (!node.empty())
-    {
-      XMLListNode* new_node = new XMLListNode(node);
-      if (!root_node.get())
-        {
-          root_node.reset(new_node);
-        }
-      else
-        {
-          node_stack.back()->children.push_back(new_node);
-        }
-      node_stack.push_back(new_node);
-    }
-
-  node = name;
-}
-
-void
-XMLParser::on_end_element(const char* el)
-{
-  if (!node.empty() && !cdata.empty())
-    {
-      node_stack.back()->children.push_back(new XMLDataNode(node, cdata));
-      node.clear();
-      cdata.clear();
-    }
-  else
-    {
-      // spaces are ignored, everything else is an error
-      for(int i = 0; i < (int)cdata.size(); ++i)
-        if (!isspace(cdata[i]))
-          raise_error("unexpected character data");
-
-      node_stack.pop_back();
-      node.clear();
-      cdata.clear();      
-    }
-}
-
-void
-XMLParser::on_character_data(const char* s, int len)
-{
-  cdata += std::string(s, len);
-}
-
-void
-XMLParser::raise_error(const std::string& str)
-{
-  std::ostringstream out;
-  out << filename << ":" << XML_GetCurrentLineNumber(parser) << ": " << str;
-  throw std::runtime_error(out.str());
-}
-

-#ifdef __TEST__
-int main(int argc, char** argv)
-{
-  try 
-    {
-      for(int i = 1; i < argc; ++i)
-        {
-          std::auto_ptr<XMLNode> root = XMLParser::parse(argv[i]);
-          root->print(std::cout);
-        }
-    } 
-  catch(std::exception& err) 
-    {
-      std::cout << "Error: " << err.what() << std::endl;
-    }
-
-  return 0;
-}
-#endif
-

-/* EOF */
diff --git a/src/xml_parser.hpp b/src/xml_parser.hpp
deleted file mode 100644
index 650e5da..0000000
--- a/src/xml_parser.hpp
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
-**  jstest-gtk - A graphical joystick tester
-**  Copyright (C) 2009 Ingo Ruhnke <grumbel at gmx.de>
-**
-**  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 3 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 General Public License
-**  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef HEADER_JSTREE_GTK_XML_TREE_HPP
-#define HEADER_JSTREE_GTK_XML_TREE_HPP
-
-#include <vector>
-#include <memory>
-#include <iostream>
-
-#include <expat.h>
-
-/*
- * The code below does not produce a full DOM, but a drastically
- * simplified one, namely nodes can either contain text or they can
- * contain child nodes, but not both. Nodes are also not allowed to
- * have attributes.
- */
-

-class XMLNode
-{
-public:
-  XMLNode() {}
-  virtual ~XMLNode() {}
-
-  virtual std::string get_name() const =0;
-
-  virtual void print(std::ostream& out, int depth = 0) =0;
-};
-

-class XMLListNode : public XMLNode
-{
-public:
-  std::string name;
-  std::vector<XMLNode*> children;
-
-  XMLListNode(const std::string& name_)
-    : name(name_)
-  {
-  }
-
-  ~XMLListNode()
-  {
-    for(std::vector<XMLNode*>::iterator i = children.begin(); i != children.end(); ++i)
-      {
-        delete *i;
-      }
-  }
-
-  std::string get_name() const { return name; }
-
-  void print(std::ostream& out, int depth = 0)
-  {
-    std::cout << std::string(2*depth, ' ') << "<" << name << ">" << std::endl;
-    for(std::vector<XMLNode*>::iterator i = children.begin(); i != children.end(); ++i)
-      {
-        (*i)->print(out, depth + 1);
-      }
-    std::cout << std::string(2*depth, ' ') << "</" << name << ">" << std::endl;
-  }
-
-private:
-  XMLListNode(const XMLListNode&);
-  XMLListNode& operator=(const XMLListNode&);
-};
-

-class XMLDataNode : public XMLNode
-{
-public:
-  std::string name;
-  std::string data;
-
-  XMLDataNode(const std::string& name_, const std::string& data_)
-    : name(name_),
-      data(data_)
-  {}
-
-  std::string get_name() const { return name; }
-
-  void print(std::ostream& out, int depth = 0)
-  {
-    out << std::string(2*depth, ' ') << "<" << name << ">" << data << "</" << name << ">" << std::endl;
-  }
-
-private:
-  XMLDataNode(const XMLDataNode&);
-  XMLDataNode& operator=(const XMLDataNode&);
-};
-

-class XMLParser
-{
-public:
-  static std::auto_ptr<XMLNode> parse(const std::string& filename);
-
-private:
-  std::string filename;
-  XML_Parser parser;
-
-  std::auto_ptr<XMLNode> root_node;
-  std::vector<XMLListNode*> node_stack;
-
-  std::string node;
-  std::string cdata;
-
-  XMLParser(const std::string& filename);
-  ~XMLParser();
-
-  std::auto_ptr<XMLNode> get_root() { return root_node; }
-
-  void on_start_element(const char* el, const char** attr);
-  void on_end_element(const char* el);
-  void on_character_data(const char* s, int len);
-  void raise_error(const std::string& str);
-
-private:
-  static void start_element(void* userdata, const char* el, const char** attr);
-  static void end_element(void* userdata, const char* el);
-  static void character_data(void* userdata, const char* s, int len);
-
-  XMLParser(const XMLParser&);
-  XMLParser& operator=(const XMLParser&);
-};
-

-#endif
-
-/* EOF */
diff --git a/src/xml_reader.cpp b/src/xml_reader.cpp
deleted file mode 100644
index 54874c1..0000000
--- a/src/xml_reader.cpp
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
-**  jstest-gtk - A graphical joystick tester
-**  Copyright (C) 2009 Ingo Ruhnke <grumbel at gmx.de>
-**
-**  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 3 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 General Public License
-**  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "xml_parser.hpp"
-#include "xml_reader.hpp"
-

-XMLReader::XMLReader(XMLListNode* root_)
-  : root(root_)
-{
-}
-
-std::string
-XMLReader::get_name() const 
-{ 
-  return root->get_name(); 
-}
-
-XMLNode*
-XMLReader::get_node(const std::string& name) const
-{
-  if (root)
-    {
-      for(std::vector<XMLNode*>::const_iterator i = root->children.begin(); i != root->children.end(); ++i)
-        {
-          if ((*i)->get_name() == name)
-            return *i;
-        }
-    }
-  
-  return 0;
-}
-
-XMLReader
-XMLReader::get_section(const std::string& name) const
-{
-  return XMLReader(dynamic_cast<XMLListNode*>(get_node(name)));
-}
-
-std::vector<XMLReader>
-XMLReader::get_sections() const
-{
-  std::vector<XMLReader> lst;
-  if (root)
-    {
-      for(std::vector<XMLNode*>::const_iterator i = root->children.begin(); i != root->children.end(); ++i)
-        {
-          lst.push_back(XMLReader(dynamic_cast<XMLListNode*>(*i)));
-        }
-    }
-  return lst;
-}
-
-std::vector<std::string>
-XMLReader::get_string_list(const std::string& name) const
-{
-  std::vector<std::string> lst;
-
-  XMLListNode* node = dynamic_cast<XMLListNode*>(get_node(name));
-  if (node)
-    {
-      for(std::vector<XMLNode*>::iterator i = node->children.begin(); i != node->children.end(); ++i)
-        {
-          if (XMLDataNode* data = dynamic_cast<XMLDataNode*>(*i))
-            {
-              lst.push_back(data->data);
-            }
-        }
- 
-      return lst;
-    }
-  else
-    {
-      return lst;
-    }
-}
-
-bool
-XMLReader::read(const std::string& name, bool& value) const
-{
-  XMLDataNode* node = dynamic_cast<XMLDataNode*>(get_node(name));
-  if (node)
-    {
-      value = (node->data != "0");
-      return true;
-    }
-  else
-    {
-      return false;
-    }
-}
-
-bool
-XMLReader::read(const std::string& name, int& value) const
-{
-  XMLDataNode* node = dynamic_cast<XMLDataNode*>(get_node(name));
-  if (node)
-    {
-      value = atoi(node->data.c_str());
-      return true;
-    }
-  else
-    {
-      return false;
-    }
-}
-
-bool
-XMLReader::read(const std::string& name, std::string& value) const
-{
-  XMLDataNode* node = dynamic_cast<XMLDataNode*>(get_node(name));
-  if (node)
-    {
-      value = node->data;
-      return true;
-    }
-  else
-    {
-      return false;
-    }
-}
-

-/* EOF */
diff --git a/src/xml_reader.hpp b/src/xml_reader.hpp
deleted file mode 100644
index 2ff2c9e..0000000
--- a/src/xml_reader.hpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
-**  jstest-gtk - A graphical joystick tester
-**  Copyright (C) 2009 Ingo Ruhnke <grumbel at gmx.de>
-**
-**  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 3 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 General Public License
-**  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef HEADER_JSTEST_GTK_XML_READER_HPP
-#define HEADER_JSTEST_GTK_XML_READER_HPP
-
-#include <string>
-
-class XMLListNode;
-class XMLNode;
-

-class XMLReader
-{
-private:
-  XMLListNode* root;
-  
-public:
-  XMLReader(XMLListNode* node);
-
-  operator bool() const { return root; }
-
-  std::string get_name() const;
-  XMLNode*  get_node(const std::string& name) const;
-  XMLReader get_section(const std::string& name) const;
-  std::vector<XMLReader> get_sections() const;
-  std::vector<std::string> get_string_list(const std::string& name) const;
-
-  bool read(const std::string& name, bool& value) const;
-  bool read(const std::string& name, int& value) const;
-  bool read(const std::string& name, std::string& value) const;
-};
-

-#endif
-
-/* EOF */
diff --git a/src/xml_writer.cpp b/src/xml_writer.cpp
deleted file mode 100644
index 3e6db94..0000000
--- a/src/xml_writer.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
-**  jstest-gtk - A graphical joystick tester
-**  Copyright (C) 2009 Ingo Ruhnke <grumbel at gmx.de>
-**
-**  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 3 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 General Public License
-**  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <stdexcept>
-
-#include "xml_writer.hpp"
-

-XMLWriter::XMLWriter(const std::string& filename)
-  : out(new std::ofstream(filename.c_str())),
-    depth(0)
-{
-  if (!*out)
-    {
-      throw std::runtime_error("couldn't open " + filename);
-    }
-  else
-    {
-      (*out) << "<?xml version=\"1.0\"?>" << std::endl;
-    }
-}
-
-void
-XMLWriter::indent()
-{
-  for(int i = 0; i < depth; ++i)
-    *out << "  ";
-}
-
-void
-XMLWriter::start_section(const std::string& name)
-{
-  indent();
-  (*out.get()) << "<" << name << ">" << std::endl;
-  depth += 1;
-}
-
-void
-XMLWriter::end_section(const std::string& name)
-{
-  depth -= 1;
-  indent();
-  *out << "</" << name << ">" << std::endl;
-}
-
-void
-XMLWriter::write(const std::string& name, const std::string& value)
-{
-  indent();
-  // FIXME: Implement magic to convert things to UTF-8
-  *out << "<" << name << ">";
-  *out << value;
-  *out << "</" << name << ">" << std::endl;
-}
-
-void
-XMLWriter::write(const std::string& name, int value)
-{
-  indent();
-  *out << "<" << name << ">";
-  *out << value;
-  *out << "</" << name << ">" << std::endl;
-}
-
-void
-XMLWriter::write(const std::string& name, bool value)
-{
-  indent();
-  *out << "<" << name << ">";
-  *out << value;
-  *out << "</" << name << ">" << std::endl; 
-}
-

-/* EOF */
diff --git a/src/xml_writer.hpp b/src/xml_writer.hpp
deleted file mode 100644
index 204375e..0000000
--- a/src/xml_writer.hpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-**  jstest-gtk - A graphical joystick tester
-**  Copyright (C) 2009 Ingo Ruhnke <grumbel at gmx.de>
-**
-**  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 3 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 General Public License
-**  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef HEADER_JSTEST_GTK_XML_WRITER_HPP
-#define HEADER_JSTEST_GTK_XML_WRITER_HPP
-
-#include <memory>
-#include <fstream>
-

-class XMLWriter
-{
-private:
-  std::auto_ptr<std::ofstream> out;
-  int depth;
-  
-public:
-  XMLWriter(const std::string& filename);
-
-  void indent();
-  void start_section(const std::string& name);
-  void end_section(const std::string& name);
-  void write(const std::string& name, const std::string& value);
-  void write(const std::string& name, int value);
-  void write(const std::string& name, bool value);
-
-private:
-  XMLWriter(const XMLWriter&);
-  XMLWriter& operator=(const XMLWriter&);
-};
-
-#endif
-

-/* EOF */

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/jstest-gtk.git



More information about the Pkg-games-commits mailing list