Merge from default flibqtfrontend
authorunc0rr
Fri, 04 Jan 2013 21:44:40 +0400
branchflibqtfrontend
changeset 8363 0b4ac686fc44
parent 8306 50fe80adbfcb (current diff)
parent 8362 89a6b7cc6f95 (diff)
Merge from default
CMakeLists.txt
QTfrontend/CMakeLists.txt
QTfrontend/game.cpp
QTfrontend/game.h
QTfrontend/hwconsts.cpp.in
QTfrontend/hwconsts.h
QTfrontend/hwform.cpp
QTfrontend/main.cpp
QTfrontend/net/hwmap.cpp
QTfrontend/net/recorder.cpp
QTfrontend/net/tcpBase.cpp
QTfrontend/net/tcpBase.h
QTfrontend/team.cpp
QTfrontend/team.h
QTfrontend/ui/page/pageeditteam.cpp
QTfrontend/ui/page/pagemain.cpp
QTfrontend/ui/page/pagenettype.cpp
QTfrontend/ui/page/pagenettype.h
hedgewars/ArgParsers.inc
hedgewars/hwengine.pas
misc/physfs/CMakeLists.txt
project_files/hedgewars.pro
--- a/.hgignore	Tue Dec 18 20:48:37 2012 +0400
+++ b/.hgignore	Fri Jan 04 21:44:40 2013 +0400
@@ -56,4 +56,5 @@
 glob:hedgewars-build-desktop-Qt_4_7_4_for_Desktop_-_MinGW_4_4__Qt_SDK__Release
 glob:*.depends
 glob:tools/build_windows_koda.bat
+glob:share/hedgewars/Data/misc/hwengine.desktop
 
--- a/CMakeLists.txt	Tue Dec 18 20:48:37 2012 +0400
+++ b/CMakeLists.txt	Fri Jan 04 21:44:40 2013 +0400
@@ -22,9 +22,12 @@
 option(BUILD_ENGINE_LIBRARY "Enable hwengine library [default: off]" OFF)
 option(ANDROID "Enable Android build [default: off]" OFF)
 option(NOAUTOUPDATE "Disable OS X Sparkle update checking" OFF)
-option(CROSSAPPLE "Enable OSX when not on OSX [default: off]" OFF)
 option(MINIMAL_FLAGS "Respect system flags as much as possible [default: off]" OFF)
-
+set(FPFLAGS "" CACHE STRING "Additional Freepascal flags")
+set(GHFLAGS "" CACHE STRING "Additional Haskell flags")
+if(UNIX AND NOT APPLE)
+    set(DATA_INSTALL_DIR "share/hedgewars" CACHE STRING "Resource folder path")
+endif()
 
 #detect Mercurial revision (if present)
 if(NOT NOREVISION)
@@ -65,18 +68,31 @@
 set(HEDGEWARS_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
 
 
-#bundle .app setup
-if(APPLE OR CROSSAPPLE)
-    #paths for creating the bundle
-    set(bundle_name Hedgewars.app)
-    set(frameworks_dir ${bundle_name}/Contents/Frameworks/)
-    set(CMAKE_INSTALL_PREFIX ${bundle_name}/Contents/MacOS/)
-    set(DATA_INSTALL_DIR "../Resources/")
-    set(target_dir ".")
+set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
+set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
+
+if(UNIX AND NOT APPLE)
+    set(target_binary_install_dir "bin")
+    set(target_library_install_dir "lib")
+    set(SHAREPATH "${DATA_INSTALL_DIR}/")
 else()
-    set(target_dir "bin")
+    set(target_binary_install_dir "./")
+
+    if(APPLE)
+        set(CMAKE_INSTALL_PREFIX "Hedgewars.app/Contents/MacOS/")
+        set(SHAREPATH "../Resources/")
+        set(target_library_install_dir "../Frameworks/")
+    else()
+        if(WIN32)
+            set(target_library_install_dir "./")
+            set(SHAREPATH "./")
+            set(CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/misc/winutils/")
+            link_directories("${EXECUTABLE_OUTPUT_PATH}" "${CMAKE_SOURCE_DIR}/misc/winutils/bin")
+        endif(WIN32)
+    endif()
 endif()
 
+
 if(APPLE)
     set(CMAKE_FIND_FRAMEWORK "FIRST")
 
@@ -114,8 +130,8 @@
         find_package(SDL_mixer REQUIRED)
         set(DYLIB_SMPEG "-dylib_file @loader_path/Frameworks/smpeg.framework/Versions/A/smpeg:${SDLMIXER_LIBRARY}/Versions/A/Frameworks/smpeg.framework/Versions/A/smpeg")
         set(DYLIB_MIKMOD "-dylib_file @loader_path/Frameworks/mikmod.framework/Versions/A/mikmod:${SDLMIXER_LIBRARY}/Versions/A/Frameworks/mikmod.framework/Versions/A/mikmod")
-        set(pascal_flags "-k${DYLIB_SMPEG}" "-k${DYLIB_MIKMOD}" ${pascal_flags})
-        set(CMAKE_C_FLAGS "${DYLIB_SMPEG}" "${DYLIB_MIKMOD}" ${CMAKE_C_FLAGS})
+        set(CMAKE_C_FLAGS "${DYLIB_SMPEG} ${DYLIB_MIKMOD}")
+        list(APPEND pascal_flags "-k${DYLIB_SMPEG}" "-k${DYLIB_MIKMOD}")
     endif()
 
     #CMAKE_OSX_ARCHITECTURES and CMAKE_OSX_SYSROOT need to be set for universal binary and correct linking
@@ -145,9 +161,9 @@
     endif()
 
     #add user framework directory, other paths can be passed via FPFLAGS
-    set(pascal_flags "-Ff~/Library/Frameworks" ${pascal_flags})
+    list(APPEND pascal_flags "-Ff~/Library/Frameworks")
     #set deployment target
-    set(pascal_flags "-k-macosx_version_min" "-k${minimum_macosx_version}" "-XR${CMAKE_OSX_SYSROOT}" ${pascal_flags})
+    list(APPEND pascal_flags "-k-macosx_version_min" "-k${minimum_macosx_version}" "-XR${CMAKE_OSX_SYSROOT}")
 
     #silly libav that always brings in VideoDecoderAcceleration, avaible only from 10.6.3
     if(NOT NOVIDEOREC AND ${minimum_macosx_version} VERSION_LESS "10.6")
@@ -168,10 +184,10 @@
 endif (CMAKE_BUILD_TYPE)
 
 #set default flags values for all projects (unless MINIMAL_FLAGS is true)
-if(NOT MINIMAL_FLAGS)
-    set(CMAKE_C_FLAGS "-pipe")
-    set(CMAKE_C_FLAGS_RELEASE "-w -Os -fomit-frame-pointer")
-    set(CMAKE_C_FLAGS_DEBUG "-Wall -O0 -g -DDEBUG")
+if(NOT ${MINIMAL_FLAGS})
+    set(CMAKE_C_FLAGS "-pipe ${CMAKE_C_FLAGS}")
+    set(CMAKE_C_FLAGS_RELEASE "-w -Os -fomit-frame-pointer ${CMAKE_C_FLAGS_RELEASE}")
+    set(CMAKE_C_FLAGS_DEBUG "-Wall -O0 -g -DDEBUG ${CMAKE_C_FLAGS_DEBUG}")
     set(CMAKE_CXX_FLAGS ${CMAKE_C_FLAGS})
     set(CMAKE_CXX_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE})
     set(CMAKE_CXX_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG})
@@ -194,7 +210,7 @@
     endif()
 endif()
 
-set(pascal_flags ${fpflags_parsed}              # user flags
+list(APPEND pascal_flags ${fpflags_parsed}              # user flags
                  "-vm4079,4080,4081"            # fpc output format
                  "-B"                           # compile all units
                  "-FE${PROJECT_BINARY_DIR}/bin" # fpc output directory
@@ -202,36 +218,21 @@
                  "-Cs2000000"                   # stack size
                  "-vewnq"                       # fpc output verbosity
                  "-dDEBUGFILE"                  # macro for engine output
-                 ${pascal_flags}                # adding to list
                  )
-set(haskell_flags "-O2" ${ghflags_parsed} ${haskell_flags})
+list(APPEND haskell_flags "-O2" ${ghflags_parsed})
 
 #get BUILD_TYPE and enable/disable optimisation
 message(STATUS "Using ${CMAKE_BUILD_TYPE} configuration")
 if(CMAKE_BUILD_TYPE MATCHES "DEBUG")
-    set(pascal_flags "-O-" "-g" "-gl" "-gv" ${pascal_flags})
-    set(haskell_flags "-Wall" "-debug" "-dcore-lint" "-fno-warn-unused-do-bind" ${haskell_flags})
+    list(APPEND pascal_flags "-O-" "-g" "-gl" "-gv")
+    list(APPEND haskell_flags "-Wall" "-debug" "-dcore-lint" "-fno-warn-unused-do-bind")
 else()
 #    set(pascal_flags "-O3" "-OpPENTIUM4" "-CfSSE3" "-Xs" "-Si" ${pascal_flags})
-    set(pascal_flags "-Os" "-Xs" "-Si" ${pascal_flags})
-    set(haskell_flags "-w" "-fno-warn-unused-do-bind" ${haskell_flags})
+    list(APPEND pascal_flags "-Os" "-Xs" "-Si")
+    list(APPEND haskell_flags "-w" "-fno-warn-unused-do-bind")
 endif()
 
 
-#finish setting paths
-if(DEFINED DATA_INSTALL_DIR)
-    set(SHAREPATH ${DATA_INSTALL_DIR}/hedgewars/)
-else()
-    set(SHAREPATH share/hedgewars/)
-endif()
-set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
-set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
-if(WIN32)
-    set(CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/misc/winutils/")
-    link_directories("${EXECUTABLE_OUTPUT_PATH}" "${CMAKE_SOURCE_DIR}/misc/winutils/bin")
-endif(WIN32)
-
-
 #server discovery
 if(NOT NOSERVER)
     if(GHC)
@@ -262,14 +263,14 @@
     message(STATUS "LUA will be provided by the bundled sources")
     add_subdirectory(misc/liblua)
     #linking with liblua.a requires system readline
-    set(pascal_flags "-k${EXECUTABLE_OUTPUT_PATH}/lib${LUA_LIBRARY}.a" "-k-lreadline" ${pascal_flags})
+    list(APPEND pascal_flags "-k${EXECUTABLE_OUTPUT_PATH}/lib${LUA_LIBRARY}.a" "-k-lreadline")
 endif()
 
 
 #physfs library (static on unix, dll on win32)
 add_subdirectory(misc/physfs)
 if(NOT WIN32)
-    set(pascal_flags "-k${LIBRARY_OUTPUT_PATH}/libphysfs.a" ${pascal_flags})
+    list(APPEND pascal_flags "-k${LIBRARY_OUTPUT_PATH}/libphysfs.a")
 endif()
 
 
@@ -310,6 +311,7 @@
     set(CPACK_NSIS_URL_INFO_ABOUT "http://www.hedgewars.org/")
     set(CPACK_NSIS_CONTACT "unC0Rr@gmail.com")
     set(CPACK_NSIS_MODIFY_PATH OFF)
+    set(CPACK_NSIS_EXECUTABLES_DIRECTORY "${target_binary_install_dir}")
     set(CPACK_GENERATOR "ZIP;NSIS")
     set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "hedgewars")
 else(WIN32 AND NOT UNIX)
--- a/QTfrontend/CMakeLists.txt	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/CMakeLists.txt	Fri Jan 04 21:44:40 2013 +0400
@@ -11,9 +11,7 @@
 set(QT_USE_QTMAIN TRUE)
 
 find_package(Qt4 REQUIRED)
-if (NOT CROSSAPPLE)
-    include(${QT_USE_FILE})
-endif()
+include(${QT_USE_FILE})
 
 find_package(SDL REQUIRED)       #video in SDLInteraction
 find_package(SDL_mixer REQUIRED) #audio in SDLInteraction
@@ -44,24 +42,20 @@
     include_directories("/usr/local/include")
 endif(UNIX)
 
-
-if(WIN32 AND NOT UNIX)
-    set(HEDGEWARS_BINDIR ".")
-    set(HEDGEWARS_DATADIR "../share/")
-    add_definitions(-DUSE_XFIRE)
+#directory for resources, relative to bindir (on linux an absolute path is always used)
+string(SUBSTRING "${SHAREPATH}" 0 1 sharepath_start)
+if(APPLE OR WIN32 OR ${sharepath_start} MATCHES "/")
+    set(HEDGEWARS_DATADIR ${SHAREPATH})
 else()
-    set(HEDGEWARS_BINDIR ${CMAKE_INSTALL_PREFIX})
-    if(DEFINED DATA_INSTALL_DIR)
-        set(HEDGEWARS_DATADIR ${DATA_INSTALL_DIR})
-    else()
-        set(HEDGEWARS_DATADIR ${CMAKE_INSTALL_PREFIX}/share/)
-    endif()
-    #only the cocoa version of qt supports building 64 bit apps
-    if(APPLE AND (CMAKE_OSX_ARCHITECTURES MATCHES "x86_64*") AND (NOT QT_MAC_USE_COCOA))
-        message(FATAL_ERROR "Building the 64 bit version of Hedgewars *requires* the Cocoa variant of QT on Mac OS X")
-    endif()
+    set(HEDGEWARS_DATADIR ${CMAKE_INSTALL_PREFIX}/${SHAREPATH})
 endif()
 
+#only the cocoa version of qt supports building 64 bit apps
+if(APPLE AND (CMAKE_OSX_ARCHITECTURES MATCHES "x86_64*") AND (NOT QT_MAC_USE_COCOA))
+    message(FATAL_ERROR "Building the 64 bit version of Hedgewars *requires* the Cocoa variant of QT on Mac OS X")
+endif()
+#endif()
+
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/hwconsts.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/hwconsts.cpp)
 
 file(GLOB NetCpp net/*.cpp)
@@ -69,7 +63,7 @@
 file(GLOB_RECURSE UIcpp ui/*.cpp)
 file(GLOB UtilCpp util/*.cpp)
 
-set(hwfr_src
+list(APPEND hwfr_src
     ${ModelCpp}
     ${NetCpp}
     ${UIcpp}
@@ -90,7 +84,7 @@
 
 #xfire integration
 if(WIN32)
-    set(hwfr_src ${hwfr_src} xfire.cpp ../misc/xfire/xfiregameclient.cpp)
+    list(APPEND hwfr_src xfire.cpp ../misc/xfire/xfiregameclient.cpp)
 endif(WIN32)
 
 if(MINGW)
@@ -99,9 +93,9 @@
                        COMMAND windres -I ${CMAKE_CURRENT_SOURCE_DIR}
                                -i ${CMAKE_CURRENT_SOURCE_DIR}/hedgewars.rc
                                -o ${CMAKE_CURRENT_BINARY_DIR}/hedgewars_rc.o)
-    set(hwfr_src ${hwfr_src} ${CMAKE_CURRENT_BINARY_DIR}/hedgewars_rc.o)
+    list(APPEND hwfr_src ${CMAKE_CURRENT_BINARY_DIR}/hedgewars_rc.o)
 else(MINGW)
-    set(hwfr_src ${hwfr_src} hedgewars.rc)
+    list(APPEND hwfr_src hedgewars.rc)
 endif(MINGW)
 
 file(GLOB ModelHdr model/*.h)
@@ -138,15 +132,21 @@
 
 set(hwfr_rez hedgewars.qrc)
 
+if(${BUILD_ENGINE_LIBRARY})
+    add_definitions(-DHWLIBRARY=1)
+    set(hwlibname "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_SHARED_LIBRARY_PREFIX}hwengine${CMAKE_SHARED_LIBRARY_SUFFIX}")
+    list(APPEND HW_LINK_LIBS ${hwlibname})
+endif()
+
 qt4_add_resources(hwfr_rez_src ${hwfr_rez})
 
 qt4_wrap_cpp(hwfr_moc_srcs ${hwfr_moc_hdrs})
 
 
-if(APPLE OR CROSSAPPLE)
+if(APPLE)
     find_library(iokit_framework NAMES IOKit)
-    set(HW_LINK_LIBS ${iokit_framework} ${HW_LINK_LIBS})
-    set(hwfr_src ${hwfr_src} CocoaInitializer.mm
+    list(APPEND HW_LINK_LIBS ${iokit_framework})
+    list(APPEND hwfr_src CocoaInitializer.mm
                              InstallController.cpp
                              M3Panel.mm
                              M3InstallController.m
@@ -156,18 +156,12 @@
         find_package(Sparkle)
         if(SPARKLE_FOUND)
             add_definitions(-DSPARKLE_ENABLED)
-            set(hwfr_src ${hwfr_src} AutoUpdater.cpp SparkleAutoUpdater.mm)
-            set(HW_LINK_LIBS ${SPARKLE_LIBRARY} ${HW_LINK_LIBS})
+            list(APPEND hwfr_src AutoUpdater.cpp SparkleAutoUpdater.mm)
+            list(APPEND HW_LINK_LIBS ${SPARKLE_LIBRARY})
         endif()
     endif()
 endif()
 
-if(BUILD_ENGINE_LIBRARY)
-    add_definitions(-DHWLIBRARY)
-    set(HW_LINK_LIBS hwengine ${HW_LINK_LIBS})
-    link_directories(${EXECUTABLE_OUTPUT_PATH})
-endif()
-
 #when debugging, always prompt a console to see fronted messages
 #TODO: check it doesn't interfere on UNIX
 if(CMAKE_BUILD_TYPE MATCHES "RELEASE")
@@ -181,8 +175,11 @@
     ${hwfr_rez_src}
     )
 
+if((UNIX AND NOT APPLE) AND ${BUILD_ENGINE_LIBRARY})
+    set_target_properties(hedgewars PROPERTIES LINK_FLAGS "-Wl,-rpath,${CMAKE_INSTALL_PREFIX}/${target_library_install_dir}")
+endif()
 
-set(HW_LINK_LIBS
+list(APPEND HW_LINK_LIBS
     frontlib
     physfs
     ${QT_LIBRARIES}
@@ -190,16 +187,14 @@
     ${SDLMIXER_LIBRARY}
     ${SDLNET_LIBRARY}
     ${FFMPEG_LIBRARIES}
-    ${HW_LINK_LIBS}
     )
 
 if(WIN32 AND NOT UNIX)
     if(NOT SDL_LIBRARY)
-        set(HW_LINK_LIBS ${HW_LINK_LIBS} SDL)
+        list(APPEND HW_LINK_LIBS SDL)
     endif()
 
-    set(HW_LINK_LIBS
-        ${HW_LINK_LIBS}
+    list(APPEND HW_LINK_LIBS
         ole32
         oleaut32
         winspool
@@ -207,11 +202,8 @@
         )
 endif()
 
-
-if (NOT CROSSAPPLE)
-    target_link_libraries(hedgewars ${HW_LINK_LIBS})
-endif()
+target_link_libraries(hedgewars ${HW_LINK_LIBS})
 
 
-install(PROGRAMS "${EXECUTABLE_OUTPUT_PATH}/hedgewars${CMAKE_EXECUTABLE_SUFFIX}" DESTINATION ${target_dir})
+install(PROGRAMS "${EXECUTABLE_OUTPUT_PATH}/hedgewars${CMAKE_EXECUTABLE_SUFFIX}" DESTINATION ${target_binary_install_dir})
 
--- a/QTfrontend/binds.cpp	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/binds.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -20,17 +20,15 @@
 
 const BindAction cbinds[BINDS_NUMBER] =
 {
-    {"+up",       "up",         QT_TRANSLATE_NOOP("binds", "up"),              QT_TRANSLATE_NOOP("binds (categories)", "Basic controls"), QT_TRANSLATE_NOOP("binds (descriptions)", "Move your hogs and aim:")},
+    {"+up",       "up",         QT_TRANSLATE_NOOP("binds", "up"),              QT_TRANSLATE_NOOP("binds (categories)", "Movement"), QT_TRANSLATE_NOOP("binds (descriptions)", "Hedgehog movement")},
     {"+left",     "left",       QT_TRANSLATE_NOOP("binds", "left"),            NULL, NULL},
     {"+right",    "right",      QT_TRANSLATE_NOOP("binds", "right"),           NULL, NULL},
     {"+down",     "down",       QT_TRANSLATE_NOOP("binds", "down"),            NULL, NULL},
     {"+precise",  "left_shift", QT_TRANSLATE_NOOP("binds", "precise aim"),     NULL, NULL},
     {"ljump",     "return",     QT_TRANSLATE_NOOP("binds", "long jump"),       NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Traverse gaps and obstacles by jumping:")},
     {"hjump",     "backspace",  QT_TRANSLATE_NOOP("binds", "high jump"),       NULL, NULL},
-    {"+attack",   "space",      QT_TRANSLATE_NOOP("binds", "attack"),          NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Fire your selected weapon or trigger an utility item:")},
-    {"put",       "mousel",     QT_TRANSLATE_NOOP("binds", "put"),             NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Pick a weapon or a target location under the cursor:")},
     {"switch",    "tab",        QT_TRANSLATE_NOOP("binds", "switch"),          NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Switch your currently active hog (if possible):")},
-    {"ammomenu",  "mouser",     QT_TRANSLATE_NOOP("binds", "ammo menu"),       QT_TRANSLATE_NOOP("binds (categories)", "Weapon controls"), QT_TRANSLATE_NOOP("binds (descriptions)", "Pick a weapon or utility item:")},
+    {"ammomenu",  "mouser",     QT_TRANSLATE_NOOP("binds", "ammo menu"),       QT_TRANSLATE_NOOP("binds (categories)", "Weapons"), QT_TRANSLATE_NOOP("binds (descriptions)", "Pick a weapon or utility item:")},
     {"slot 1",    "f1",         QT_TRANSLATE_NOOP("binds", "slot 1"),          NULL, NULL},
     {"slot 2",    "f2",         QT_TRANSLATE_NOOP("binds", "slot 2"),          NULL, NULL},
     {"slot 3",    "f3",         QT_TRANSLATE_NOOP("binds", "slot 3"),          NULL, NULL},
@@ -46,7 +44,9 @@
     {"timer 3",   "3",          QT_TRANSLATE_NOOP("binds", "timer 3 sec"),     NULL, NULL},
     {"timer 4",   "4",          QT_TRANSLATE_NOOP("binds", "timer 4 sec"),     NULL, NULL},
     {"timer 5",   "5",          QT_TRANSLATE_NOOP("binds", "timer 5 sec"),     NULL, NULL},
-    {"findhh",    "h",          QT_TRANSLATE_NOOP("binds", "find hedgehog"),   QT_TRANSLATE_NOOP("binds (categories)", "Camera and cursor controls"), QT_TRANSLATE_NOOP("binds (descriptions)", "Move the camera to the active hog:")},
+    {"+attack",   "space",      QT_TRANSLATE_NOOP("binds", "attack"),          NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Fire your selected weapon or trigger an utility item:")},
+    {"put",       "mousel",     QT_TRANSLATE_NOOP("binds", "put"),             NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Pick a weapon or a target location under the cursor:")},
+    {"findhh",    "h",          QT_TRANSLATE_NOOP("binds", "find hedgehog"),   QT_TRANSLATE_NOOP("binds (categories)", "Camera"), QT_TRANSLATE_NOOP("binds (descriptions)", "Move the camera to the active hog:")},
     {"+cur_u",    "[8]",        QT_TRANSLATE_NOOP("binds", "up"),              NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Move the cursor or camera without using the mouse:")},
     {"+cur_l",    "[4]",        QT_TRANSLATE_NOOP("binds", "left"),            NULL, NULL},
     {"+cur_r",    "[6]",        QT_TRANSLATE_NOOP("binds", "right"),           NULL, NULL},
@@ -55,7 +55,7 @@
     {"zoomin",    "wheelup",    QT_TRANSLATE_NOOP("binds", "zoom in"),         NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Modify the camera's zoom level:")},
     {"zoomout",   "wheeldown",  QT_TRANSLATE_NOOP("binds", "zoom out"),        NULL, NULL},
     {"zoomreset", "mousem",     QT_TRANSLATE_NOOP("binds", "reset zoom"),      NULL, NULL},
-    {"chat",      "t",          QT_TRANSLATE_NOOP("binds", "chat"),            QT_TRANSLATE_NOOP("binds (categories)", "Other"), QT_TRANSLATE_NOOP("binds (descriptions)", "Talk to your team or all participants:")},
+    {"chat",      "t",          QT_TRANSLATE_NOOP("binds", "chat"),            QT_TRANSLATE_NOOP("binds (categories)", "Miscellaneous"), QT_TRANSLATE_NOOP("binds (descriptions)", "Talk to your team or all participants:")},
     {"history",   "`",          QT_TRANSLATE_NOOP("binds", "chat history"),    NULL, NULL},
     {"pause",     "p",          QT_TRANSLATE_NOOP("binds", "pause"),           NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Pause, continue or leave your game:")},
     {"quit",      "escape",     QT_TRANSLATE_NOOP("binds", "quit"),            NULL, NULL},
@@ -65,7 +65,7 @@
     {"mute",      "8",          QT_TRANSLATE_NOOP("binds", "mute audio"),      NULL, NULL},
     {"fullscr",   "f12",        QT_TRANSLATE_NOOP("binds", "change mode"),     NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Toggle fullscreen mode:")},
     {"capture",   "c",          QT_TRANSLATE_NOOP("binds", "capture"),         NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Take a screenshot:")},
-    {"rotmask",   "delete",     QT_TRANSLATE_NOOP("binds", "hedgehogs\ninfo"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Toggle labels above hedgehogs:")},
+    {"rotmask",   "delete",     QT_TRANSLATE_NOOP("binds", "hedgehog info"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Toggle labels above hedgehogs:")},
 #ifdef VIDEOREC
     {"record",    "r",          QT_TRANSLATE_NOOP("binds", "record"),          NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Record video:")}
 #endif
--- a/QTfrontend/game.cpp	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/game.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -22,13 +22,17 @@
 #include <QColor>
 #include <QStringListModel>
 #include <QTextStream>
+#include <utility>
 
+#include "hwform.h"
+#include "ui/page/pageoptions.h"
 #include "game.h"
 #include "hwconsts.h"
 #include "gameuiconfig.h"
 #include "gamecfgwidget.h"
 #include "teamselect.h"
 #include "proto.h"
+#include "binds.h"
 #include "campaign.h"
 #include "ThemeModel.h"
 #include "frontlibpoller.h"
@@ -55,6 +59,18 @@
         flib_gameconn_destroy(m_conn);
 }
 
+void HWGame::addKeyBindings(QByteArray * buf)
+{
+    for(int i = 0; i < BINDS_NUMBER; i++)
+    {
+        QString value = config->value(QString("Binds/%1").arg(cbinds[i].action), cbinds[i].strbind).toString();
+        if (value.isEmpty() || value == "default") continue;
+        
+        QString bind = QString("edbind " + value + " " + cbinds[i].action);
+        HWProto::addStringToBuffer(*buf, bind);
+    }
+}
+
 void HWGame::commonConfig()
 {
     QByteArray buf;
@@ -72,6 +88,8 @@
     }
     HWProto::addStringToBuffer(buf, gt);
 
+    addKeyBindings(&buf);
+
     buf += gamecfg->getFullConfig();
 
     if (m_pTeamSelWidget)
@@ -84,10 +102,11 @@
             HWProto::addStringToBuffer(buf, QString("eammreinf %1").arg(ammostr.mid(3 * cAmmoNumber, cAmmoNumber)));
             if(gamecfg->schemeData(15).toBool() || !gamecfg->schemeData(21).toBool()) HWProto::addStringToBuffer(buf, QString("eammstore"));
 //            HWProto::addStringListToBuffer(buf,
-//                                           team.teamGameConfig(gamecfg->getInitHealth()));
-            ;
+//                                           team.teamGameConfig(gamecfg->getInitHealth(), config));
+           ;
         }
     }
+
     //RawSendIPC(buf);
 }
 
@@ -103,7 +122,9 @@
     HWProto::addStringToBuffer(traincfg, "eseed " + QUuid::createUuid().toString());
     HWProto::addStringToBuffer(traincfg, "escript " + training);
 
-   //RawSendIPC(traincfg);
+    addKeyBindings(&traincfg);
+
+    //RawSendIPC(traincfg);
 }
 
 void HWGame::SendCampaignConfig()
@@ -114,7 +135,9 @@
 
     HWProto::addStringToBuffer(campaigncfg, "escript " + campaignScript);
 
-   // RawSendIPC(campaigncfg);
+    addKeyBindings(&campaigncfg);
+
+    //RawSendIPC(campaigncfg);
 }
 
 void HWGame::SendNetConfig()
@@ -217,6 +240,16 @@
                 writeCampaignVar(msg.right(msg.size() - 3));
             break;
         }
+        case 'W':
+        {
+            // fetch new window resolution via IPC and save it in the settings
+            int size = msg.size();
+            QString newResolution = QString().append(msg.mid(2)).left(size - 4);
+            QStringList wh = newResolution.split('x');
+            config->Form->ui.pageOptions->windowWidthEdit->setText(wh[0]);
+            config->Form->ui.pageOptions->windowHeightEdit->setText(wh[1]);
+            break;
+        }
         default:
         {
             if (gameType == gtNet && !netSuspend)
@@ -256,24 +289,48 @@
 QStringList HWGame::getArguments()
 {
     QStringList arguments;
-    QRect resolution = config->vid_Resolution();
-    arguments << cfgdir->absolutePath();
-    arguments << QString::number(resolution.width());
-    arguments << QString::number(resolution.height());
-    arguments << QString::number(config->bitDepth()); // bpp
+    std::pair<QRect, QRect> resolutions = config->vid_ResolutionPair();
+    QString nick = config->netNick().toUtf8().toBase64();
+
+    arguments << "--internal"; //Must be passed as first argument
+    arguments << "--port";
     arguments << QString::number(flib_gameconn_getport(m_conn));
-    arguments << (config->vid_Fullscreen() ? "1" : "0");
-    arguments << (config->isSoundEnabled() ? "1" : "0");
-    arguments << (config->isMusicEnabled() ? "1" : "0");
-    arguments << QString::number(config->volume()); // sound volume
-    arguments << QString::number(config->timerInterval());
+    arguments << "--prefix";
     arguments << datadir->absolutePath();
-    arguments << (config->isShowFPSEnabled() ? "1" : "0");
-    arguments << (config->isAltDamageEnabled() ? "1" : "0");
-    arguments << config->netNick().toUtf8().toBase64();
+    arguments << "--user-prefix";
+    arguments << cfgdir->absolutePath();
+    arguments << "--locale";
+    arguments << tr("en.txt");
+    arguments << "--frame-interval";
+    arguments << QString::number(config->timerInterval());
+    arguments << "--volume";
+    arguments << QString::number(config->volume());
+    arguments << "--fullscreen-width";
+    arguments << QString::number(resolutions.first.width());
+    arguments << "--fullscreen-height";
+    arguments << QString::number(resolutions.first.height());
+    arguments << "--width";
+    arguments << QString::number(resolutions.second.width());
+    arguments << "--height";
+    arguments << QString::number(resolutions.second.height());
+    arguments << "--raw-quality";
     arguments << QString::number(config->translateQuality());
+    arguments << "--stereo";
     arguments << QString::number(config->stereoMode());
-    arguments << tr("en.txt");
+    if (config->vid_Fullscreen())
+        arguments << "--fullscreen";
+    if (config->isShowFPSEnabled())
+        arguments << "--showfps";
+    if (config->isAltDamageEnabled())
+        arguments << "--altdmg";
+    if (!config->isSoundEnabled())
+        arguments << "--nosound";
+    if (!config->isMusicEnabled())
+        arguments << "--nomusic";
+    if (!nick.isEmpty()) {
+        arguments << "--nick";
+        arguments << nick;
+    }
 
     return arguments;
 }
--- a/QTfrontend/game.h	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/game.h	Fri Jan 04 21:44:40 2013 +0400
@@ -107,6 +107,7 @@
         flib_gameconn * m_conn;
         FrontLibPoller * m_poller;
 
+        void addKeyBindings(QByteArray * buf);
         void commonConfig();
         void SendConfig();
         void SendNetConfig();
--- a/QTfrontend/gameuiconfig.cpp	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/gameuiconfig.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -24,6 +24,7 @@
 #include <QStandardItemModel>
 #include <QNetworkProxy>
 #include <QNetworkProxyFactory>
+#include <utility>
 
 #include "gameuiconfig.h"
 #include "hwform.h"
@@ -34,6 +35,7 @@
 #include "fpsedit.h"
 #include "HWApplication.h"
 #include "DataManager.h"
+#include "SDL.h"
 
 
 const QNetworkProxy::ProxyType proxyTypesMap[] = {
@@ -52,6 +54,13 @@
 
     connect(Form->ui.pageOptions->CBFrontendMusic, SIGNAL(toggled(bool)), Form, SLOT(Music(bool)));
 
+    for(int i = 0; i < BINDS_NUMBER; i++)
+    {
+        m_binds.append(BindAction());
+        m_binds[i].action = cbinds[i].action;
+        m_binds[i].strbind = cbinds[i].strbind;
+    }
+
     //Form->resize(value("frontend/width", 640).toUInt(), value("frontend/height", 450).toUInt());
     resizeToConfigValues();
 
@@ -65,7 +74,7 @@
 {
     Form->ui.pageOptions->WeaponTooltip->setChecked(value("misc/weaponTooltips", true).toBool());
 
-    int t = Form->ui.pageOptions->CBResolution->findText(value("video/resolution").toString());
+    int t = Form->ui.pageOptions->CBResolution->findText(value("video/fullscreenResolution").toString());
     if (t < 0)
     {
         if (Form->ui.pageOptions->CBResolution->count() > 1)
@@ -74,6 +83,20 @@
             Form->ui.pageOptions->CBResolution->setCurrentIndex(0);
     }
     else Form->ui.pageOptions->CBResolution->setCurrentIndex(t);
+    
+    // Default the windowed resolution to 5/6 of the screen size
+    int screenWidth = SDL_GetVideoInfo()->current_w * 5 / 6;
+    int screenHeight = SDL_GetVideoInfo()->current_h * 5 / 6;
+    QString widthStr; widthStr.setNum(screenWidth);
+    QString heightStr; heightStr.setNum(screenHeight);
+    QString wWidth = value("video/windowedWidth", widthStr).toString();
+    QString wHeight = value("video/windowedHeight", heightStr).toString();
+    // If left blank reset the resolution to the default
+    wWidth = (wWidth == "" ? widthStr : wWidth);
+    wHeight = (wHeight == "" ? heightStr : wHeight);
+    Form->ui.pageOptions->windowWidthEdit->setText(wWidth);
+    Form->ui.pageOptions->windowHeightEdit->setText(wHeight);
+    
     Form->ui.pageOptions->CBResolution->setCurrentIndex((t < 0) ? 1 : t);
     Form->ui.pageOptions->CBFullscreen->setChecked(value("video/fullscreen", false).toBool());
     bool ffscr=value("frontend/fullscreen", false).toBool();
@@ -130,15 +153,20 @@
     Form->ui.pageOptions->leProxyLogin->setText(value("proxy/login", "").toString());
     Form->ui.pageOptions->leProxyPassword->setText(value("proxy/password", "").toString());
 
-    depth = HWApplication::desktop()->depth();
-    if (depth < 16) depth = 16;
-    else if (depth > 16) depth = 32;
-
     { // load colors
         QStandardItemModel * model = DataManager::instance().colorsModel();
         for(int i = model->rowCount() - 1; i >= 0; --i)
             model->item(i)->setData(QColor(value(QString("colors/color%1").arg(i), model->item(i)->data().value<QColor>()).value<QColor>()));
     }
+
+    { // load binds
+        QStandardItemModel * binds = DataManager::instance().bindsModel();
+        for(int i = 0; i < BINDS_NUMBER; i++)
+        {
+            m_binds[i].strbind = value(QString("Binds/%1").arg(m_binds[i].action), cbinds[i].strbind).toString();
+            if (m_binds[i].strbind.isEmpty() || m_binds[i].strbind == "default") m_binds[i].strbind = cbinds[i].strbind;
+        }
+    }
 }
 
 void GameUIConfig::reloadVideosValues(void)
@@ -203,7 +231,9 @@
 
 void GameUIConfig::SaveOptions()
 {
-    setValue("video/resolution", Form->ui.pageOptions->CBResolution->currentText());
+    setValue("video/fullscreenResolution", Form->ui.pageOptions->CBResolution->currentText());
+    setValue("video/windowedWidth", Form->ui.pageOptions->windowWidthEdit->text());
+    setValue("video/windowedHeight", Form->ui.pageOptions->windowHeightEdit->text());
     setValue("video/fullscreen", vid_Fullscreen());
 
     setValue("video/quality", Form->ui.pageOptions->SLQuality->value());
@@ -323,16 +353,28 @@
     return Form->ui.pageOptions->CBLanguage->itemData(Form->ui.pageOptions->CBLanguage->currentIndex()).toString();
 }
 
-QRect GameUIConfig::vid_Resolution()
-{
-    QRect result(0, 0, 640, 480);
+std::pair<QRect, QRect> GameUIConfig::vid_ResolutionPair() {
+    // returns a pair of both the fullscreen and the windowed resolution
+    QRect full(0, 0, 640, 480);
+    QRect windowed(0, 0, 640, 480);
     QStringList wh = Form->ui.pageOptions->CBResolution->currentText().split('x');
     if (wh.size() == 2)
     {
-        result.setWidth(wh[0].toInt());
-        result.setHeight(wh[1].toInt());
+        full.setWidth(wh[0].toInt());
+        full.setHeight(wh[1].toInt());
     }
-    return result;
+    windowed.setWidth(Form->ui.pageOptions->windowWidthEdit->text().toInt());
+    windowed.setHeight(Form->ui.pageOptions->windowHeightEdit->text().toInt());
+    return std::make_pair(full, windowed);
+}
+
+QRect GameUIConfig::vid_Resolution()
+{
+    std::pair<QRect, QRect> result = vid_ResolutionPair();
+    if(Form->ui.pageOptions->CBFullscreen->isChecked())
+        return result.first;
+    else 
+        return result.second;
 }
 
 bool GameUIConfig::vid_Fullscreen()
@@ -449,11 +491,6 @@
     return 35 - Form->ui.pageOptions->fpsedit->value();
 }
 
-quint8 GameUIConfig::bitDepth()
-{
-    return depth;
-}
-
 QString GameUIConfig::netNick()
 {
     return Form->ui.pageOptions->editNetNick->text();
@@ -590,3 +627,16 @@
 {
     return Form->ui.pageOptions->checkRecordAudio->isChecked();
 }
+
+// Gets a bind for a bindID
+QString GameUIConfig::bind(int bindID)
+{
+    return m_binds[bindID].strbind;
+}
+
+// Sets a bind for a bindID and saves it
+void GameUIConfig::setBind(int bindID, QString & strbind)
+{
+    m_binds[bindID].strbind = strbind;
+    setValue(QString("Binds/%1").arg(m_binds[bindID].action), strbind);
+}
--- a/QTfrontend/gameuiconfig.h	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/gameuiconfig.h	Fri Jan 04 21:44:40 2013 +0400
@@ -23,6 +23,9 @@
 #include <QStringList>
 #include <QRect>
 #include <QEvent>
+#include <QList>
+#include <utility>
+#include "binds.h"
 
 class HWForm;
 class QSettings;
@@ -36,6 +39,7 @@
         GameUIConfig(HWForm * FormWidgets, const QString & fileName);
         QStringList GetTeamsList();
         QRect vid_Resolution();
+        std::pair<QRect, QRect> vid_ResolutionPair();
         bool vid_Fullscreen();
         quint32 translateQuality();
         bool isSoundEnabled();
@@ -48,7 +52,6 @@
         bool appendDateTimeToRecordName();
         quint8 volume();
         quint8 timerInterval();
-        quint8 bitDepth();
         QString netNick();
         QByteArray netPasswordHash();
         int netPasswordLength();
@@ -65,6 +68,8 @@
         void resizeToConfigValues();
         quint32 stereoMode() const;
         void setValue(const QString & key, const QVariant & value);
+        QString bind(int bindID);
+        void setBind(int bindID, QString & strbind);
 
         QString AVFormat();
         QString videoCodec();
@@ -92,8 +97,8 @@
     private:
         bool netPasswordIsValid();
         bool eventFilter(QObject *object, QEvent *event);
-        quint8 depth;
-	QString temphash;
+	    QString temphash;
+        QList<BindAction> m_binds;
 };
 
 #endif
--- a/QTfrontend/hedgewars.qrc	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/hedgewars.qrc	Fri Jan 04 21:44:40 2013 +0400
@@ -44,6 +44,7 @@
         <file>res/HedgewarsTitle.png</file>
         <file>res/LocalPlay.png</file>
         <file>res/NetworkPlay.png</file>
+        <file>res/NetworkPlayDisabled.png</file>
         <file>res/Settings.png</file>
         <file>res/dropdown.png</file>
         <file>res/new.png</file>
@@ -145,6 +146,8 @@
         <file>res/chat/serveradmin_gray.png</file>
         <file>res/chat/lamp_off.png</file>
         <file>res/chat/ingame.png</file>
-	<file>res/html/about.html</file>
+        <file>res/splash.png</file>
+        <file>res/html/about.html</file>
+        <file>res/xml/tips.xml</file>
     </qresource>
 </RCC>
--- a/QTfrontend/hwconsts.cpp.in	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/hwconsts.cpp.in	Fri Jan 04 21:44:40 2013 +0400
@@ -23,10 +23,9 @@
 
 QString * cProtoVer = new QString("${HEDGEWARS_PROTO_VER}");
 QString * cDataDir = new QString("${HEDGEWARS_DATADIR}");
-QString * cConfigDir = new QString("");
 QString * cVersionString = new QString("${HEDGEWARS_VERSION}");
 
-QDir * bindir = new QDir("${HEDGEWARS_BINDIR}");
+QDir * bindir = new QDir();
 QDir * cfgdir = new QDir();
 QDir * datadir = new QDir();
 
--- a/QTfrontend/hwconsts.h	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/hwconsts.h	Fri Jan 04 21:44:40 2013 +0400
@@ -26,7 +26,6 @@
 extern QString * cProtoVer;
 extern QString * cVersionString;
 extern QString * cDataDir;
-extern QString * cConfigDir;
 
 extern QDir * bindir;
 extern QDir * cfgdir;
--- a/QTfrontend/hwform.cpp	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/hwform.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -39,6 +39,8 @@
 #include <QSignalMapper>
 #include <QShortcut>
 #include <QDesktopServices>
+#include <QDesktopWidget>
+#include <QApplication>
 #include <QInputDialog>
 #include <QPropertyAnimation>
 #include <QSettings>
@@ -73,7 +75,6 @@
 #include "pagefeedback.h"
 #include "pagenetserver.h"
 #include "pagedrawmap.h"
-#include "pagenettype.h"
 #include "pagegamestats.h"
 #include "pageplayrecord.h"
 #include "pagedata.h"
@@ -98,6 +99,18 @@
 #include "DataManager.h"
 #include "AutoUpdater.h"
 
+#ifdef Q_WS_WIN
+#define WINVER 0x0500
+#include <windows.h>
+#else
+#include <unistd.h>
+#include <sys/types.h>
+#endif
+
+#ifdef Q_WS_MAC
+#include <sys/sysctl.h>
+#endif
+
 #ifdef __APPLE__
 #include "M3Panel.h"
 #ifdef SPARKLE_ENABLED
@@ -144,9 +157,9 @@
     ui.pageRoomsList->setSettings(config);
     ui.pageNetGame->chatWidget->setSettings(config);
     ui.pageRoomsList->chatWidget->setSettings(config);
+    ui.pageOptions->setConfig(config);
 #ifdef VIDEOREC
     ui.pageVideos->init(config);
-    ui.pageOptions->setConfig(config);
 #endif
 
 #ifdef __APPLE__
@@ -205,9 +218,6 @@
     connect(ui.pageMain->BtnFeedback, SIGNAL(clicked()), pageSwitchMapper, SLOT(map()));
     pageSwitchMapper->setMapping(ui.pageMain->BtnFeedback, ID_PAGE_FEEDBACK);
 
-    connect(ui.pageMain->BtnNet, SIGNAL(clicked()), pageSwitchMapper, SLOT(map()));
-    pageSwitchMapper->setMapping(ui.pageMain->BtnNet, ID_PAGE_NETTYPE);
-
     connect(ui.pageMain->BtnInfo, SIGNAL(clicked()), pageSwitchMapper, SLOT(map()));
     pageSwitchMapper->setMapping(ui.pageMain->BtnInfo, ID_PAGE_INFO);
 
@@ -306,8 +316,8 @@
     //    this, SLOT(GoBack())); // executed third
 
 
-    connect(ui.pageNetType->BtnLAN, SIGNAL(clicked()), this, SLOT(GoToNet()));
-    connect(ui.pageNetType->BtnOfficialServer, SIGNAL(clicked()), this, SLOT(NetConnectOfficialServer()));
+    connect(ui.pageMain->BtnNetLocal, SIGNAL(clicked()), this, SLOT(GoToNet()));
+    connect(ui.pageMain->BtnNetOfficial, SIGNAL(clicked()), this, SLOT(NetConnectOfficialServer()));
 
     connect(ui.pageConnecting, SIGNAL(cancelConnection()), this, SLOT(GoBack()));
 
@@ -545,74 +555,49 @@
     GoToPage(ID_PAGE_VIDEOS);
 }
 
+//TODO: maybe find a better place for this?
+QString HWForm::stringifyPageId(quint32 id)
+{
+    QString pageName;
+    switch (id)
+    {
+      case ID_PAGE_SETUP_TEAM :   pageName = "PAGE_SETUP_TEAM"; break;
+      case ID_PAGE_SETUP :        pageName = "PAGE_SETUP"; break;
+      case ID_PAGE_MULTIPLAYER :  pageName = "PAGE_MULTIPLAYER"; break;
+      case ID_PAGE_DEMOS :        pageName = "PAGE_DEMOS"; break;
+      case ID_PAGE_NET :          pageName = "PAGE_NET"; break;
+      case ID_PAGE_NETGAME :      pageName = "PAGE_NETGAME"; break;
+      case ID_PAGE_INFO :         pageName = "PAGE_INFO"; break;
+      case ID_PAGE_MAIN :         pageName = "PAGE_MAIN"; break;
+      case ID_PAGE_GAMESTATS :    pageName = "PAGE_GAMESTATS"; break;
+      case ID_PAGE_SINGLEPLAYER : pageName = "PAGE_SINGLEPLAYER"; break;
+      case ID_PAGE_TRAINING :     pageName = "PAGE_TRAINING"; break;
+      case ID_PAGE_SELECTWEAPON : pageName = "PAGE_SELECTWEAPON"; break;
+      case ID_PAGE_NETSERVER :    pageName = "PAGE_NETSERVER"; break;
+      case ID_PAGE_INGAME :       pageName = "PAGE_INGAME"; break;
+      case ID_PAGE_ROOMSLIST :    pageName = "PAGE_ROOMSLIST"; break;
+      case ID_PAGE_CONNECTING :   pageName = "PAGE_CONNECTING"; break;
+      case ID_PAGE_SCHEME :       pageName = "PAGE_SCHEME"; break;
+      case ID_PAGE_ADMIN :        pageName = "PAGE_ADMIN"; break;
+      case ID_PAGE_CAMPAIGN :     pageName = "PAGE_CAMPAIGN"; break;
+      case ID_PAGE_DRAWMAP :      pageName = "PAGE_DRAWMAP"; break;
+      case ID_PAGE_DATADOWNLOAD : pageName = "PAGE_DATADOWNLOAD"; break;
+      case ID_PAGE_FEEDBACK :     pageName = "PAGE_FEEDBACK"; break;
+      case ID_PAGE_VIDEOS :       pageName = "PAGE_VIDEOS"; break;
+      case MAX_PAGE :             pageName = "MAX_PAGE"; break;
+      default :                   pageName = "UNKNOWN_PAGE"; break;
+    }
+    return pageName;
+}
+
 void HWForm::OnPageShown(quint8 id, quint8 lastid)
 {
 #ifdef USE_XFIRE
     updateXfire();
 #endif
     
-    QString openPrefix = "Debug:   (PAGE_OPENED: ";
-    QString openSuffix = ")";
-    QString closePrefix = "Debug:   (PAGE_LEFT: ";
-    QString closeSuffix = ")";
-    
-    switch (lastid) { //Print the id of the page we're leaving      
-      case ID_PAGE_SETUP_TEAM :	qDebug("%sPAGE_SETUP_TEAM%s", qPrintable(closePrefix), qPrintable(closeSuffix)); 	break;      
-      case ID_PAGE_SETUP :		qDebug("%sPAGE_SETUP%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
-      case ID_PAGE_MULTIPLAYER :	qDebug("%sPAGE_MULTIPLAYER%s", qPrintable(closePrefix), qPrintable(closeSuffix));	break;      
-      case ID_PAGE_DEMOS :		qDebug("%sPAGE_DEMOS%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
-      case ID_PAGE_NET :		qDebug("%sPAGE_NET%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
-      case ID_PAGE_NETGAME :		qDebug("%sPAGE_NETGAME%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
-      case ID_PAGE_INFO :		qDebug("%sPAGE_INFO%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
-      case ID_PAGE_MAIN :		qDebug("%sPAGE_MAIN%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
-      case ID_PAGE_GAMESTATS :		qDebug("%sPAGE_GAMESTATS%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
-      case ID_PAGE_SINGLEPLAYER :	qDebug("%sPAGE_SINGLEPLAYER%s", qPrintable(closePrefix), qPrintable(closeSuffix));	break;      
-      case ID_PAGE_TRAINING :		qDebug("%sPAGE_TRAINING%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
-      case ID_PAGE_SELECTWEAPON :	qDebug("%sPAGE_SELECTWEAPON%s", qPrintable(closePrefix), qPrintable(closeSuffix));	break;      
-      case ID_PAGE_NETSERVER :		qDebug("%sPAGE_NETSERVER%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
-      case ID_PAGE_INGAME :		qDebug("%sPAGE_INGAME%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
-      case ID_PAGE_ROOMSLIST :		qDebug("%sPAGE_ROOMSLIST%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
-      case ID_PAGE_CONNECTING :	qDebug("%sPAGE_CONNECTING%s", qPrintable(closePrefix), qPrintable(closeSuffix));	break;      
-      case ID_PAGE_SCHEME :		qDebug("%sPAGE_SCHEME%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
-      case ID_PAGE_ADMIN :		qDebug("%sPAGE_ADMIN%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
-      case ID_PAGE_NETTYPE :		qDebug("%sPAGE_NETTYPE%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
-      case ID_PAGE_CAMPAIGN :		qDebug("%sPAGE_CAMPAIGN%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
-      case ID_PAGE_DRAWMAP :		qDebug("%sPAGE_DRAWMAP%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
-      case ID_PAGE_DATADOWNLOAD :	qDebug("%sPAGE_DATADOWNLOAD%s", qPrintable(closePrefix), qPrintable(closeSuffix));	break;      
-      case ID_PAGE_FEEDBACK :		qDebug("%sPAGE_FEEDBACK%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;      
-      case ID_PAGE_VIDEOS :		qDebug("%sPAGE_VIDEOS%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;
-      case MAX_PAGE :			qDebug("%sMAX_PAGE%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break; 
-      default :			qDebug("%sUNKNOWN PAGE%s", qPrintable(closePrefix), qPrintable(closeSuffix));		break;
-    } //end switch(lastid)
-    switch (id) { //Print the id of the opened page
-      case ID_PAGE_SETUP_TEAM :	qDebug("%sPAGE_SETUP_TEAM%s", qPrintable(openPrefix), qPrintable(openSuffix)); 		break;      
-      case ID_PAGE_SETUP :		qDebug("%sPAGE_SETUP%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
-      case ID_PAGE_MULTIPLAYER :	qDebug("%sPAGE_MULTIPLAYER%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
-      case ID_PAGE_DEMOS :		qDebug("%sPAGE_DEMOS%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
-      case ID_PAGE_NET :		qDebug("%sPAGE_NET%s", qPrintable(openPrefix), qPrintable(openSuffix));			break;      
-      case ID_PAGE_NETGAME :		qDebug("%sPAGE_NETGAME%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
-      case ID_PAGE_INFO :		qDebug("%sPAGE_INFO%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
-      case ID_PAGE_MAIN :		qDebug("%sPAGE_MAIN%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
-      case ID_PAGE_GAMESTATS :		qDebug("%sPAGE_GAMESTATS%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
-      case ID_PAGE_SINGLEPLAYER :	qDebug("%sPAGE_SINGLEPLAYER%s", qPrintable(openPrefix), qPrintable(openSuffix));	break;      
-      case ID_PAGE_TRAINING :		qDebug("%sPAGE_TRAINING%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
-      case ID_PAGE_SELECTWEAPON :	qDebug("%sPAGE_SELECTWEAPON%s", qPrintable(openPrefix), qPrintable(openSuffix));	break;      
-      case ID_PAGE_NETSERVER :		qDebug("%sPAGE_NETSERVER%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
-      case ID_PAGE_INGAME :		qDebug("%sPAGE_INGAME%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
-      case ID_PAGE_ROOMSLIST :		qDebug("%sPAGE_ROOMSLIST%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
-      case ID_PAGE_CONNECTING :	qDebug("%sPAGE_CONNECTING%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
-      case ID_PAGE_SCHEME :		qDebug("%sPAGE_SCHEME%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
-      case ID_PAGE_ADMIN :		qDebug("%sPAGE_ADMIN%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
-      case ID_PAGE_NETTYPE :		qDebug("%sPAGE_NETTYPE%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
-      case ID_PAGE_CAMPAIGN :		qDebug("%sPAGE_CAMPAIGN%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
-      case ID_PAGE_DRAWMAP :		qDebug("%sPAGE_DRAWMAP%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
-      case ID_PAGE_DATADOWNLOAD :	qDebug("%sPAGE_DATADOWNLOAD%s", qPrintable(openPrefix), qPrintable(openSuffix));	break;      
-      case ID_PAGE_FEEDBACK :		qDebug("%sPAGE_FEEDBACK%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;      
-      case ID_PAGE_VIDEOS :		qDebug("%sPAGE_VIDEOS%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;
-      case MAX_PAGE :			qDebug("%sMAX_PAGE%s", qPrintable(openPrefix), qPrintable(openSuffix));			break; 
-      default :			qDebug("%sUNKNOWN PAGE%s", qPrintable(openPrefix), qPrintable(openSuffix));		break;
-    } //end switch(id)
-    
+    qDebug("Leaving %s, entering %s", qPrintable(stringifyPageId(lastid)), qPrintable(stringifyPageId(id)));
+
     if (id == ID_PAGE_DATADOWNLOAD)
     {
         ui.pageDataDownload->fetchList();
@@ -969,18 +954,8 @@
 
 void HWForm::DeleteTeam(const QString & teamName)
 {
-    QMessageBox reallyDeleteMsg(this);
-    reallyDeleteMsg.setIcon(QMessageBox::Question);
-    reallyDeleteMsg.setWindowTitle(QMessageBox::tr("Teams - Are you sure?"));
-    reallyDeleteMsg.setText(QMessageBox::tr("Do you really want to delete the team '%1'?").arg(teamName));
-    reallyDeleteMsg.setWindowModality(Qt::WindowModal);
-    reallyDeleteMsg.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
-
-    if (reallyDeleteMsg.exec() == QMessageBox::Ok)
-    {
-        ui.pageEditTeam->deleteTeam(teamName);
-        UpdateTeamsLists();
-    }
+    ui.pageEditTeam->deleteTeam(teamName);
+    UpdateTeamsLists();
 }
 
 void HWForm::DeleteScheme()
@@ -1510,7 +1485,6 @@
         }
         else {
             while (ui.Pages->currentIndex() != ID_PAGE_NET
-                && ui.Pages->currentIndex() != ID_PAGE_NETTYPE
                 && ui.Pages->currentIndex() != ID_PAGE_MAIN) 
             {
                 GoBack();
@@ -1527,7 +1501,6 @@
     }
 
     while (ui.Pages->currentIndex() != ID_PAGE_NET
-        && ui.Pages->currentIndex() != ID_PAGE_NETTYPE
         && ui.Pages->currentIndex() != ID_PAGE_MAIN)
     {
         GoBack();
@@ -1881,16 +1854,21 @@
 // used for --set-everything [screen width] [screen height] [color dept] [volume] [enable music] [enable sounds] [language file] [full screen] [show FPS] [alternate damage] [timer value] [reduced quality]
 QString HWForm::getDemoArguments()
 {
+
+    QString prefix = datadir->absolutePath();
+    QString userPrefix = cfgdir->absolutePath();
 #ifdef Q_WS_WIN
-    QString userdir = cfgdir->absolutePath().replace("/","\\");
-#else
-    QString userdir = cfgdir->absolutePath();
+    prefix = prefix.replace("/","\\");
+    userPrefix = userPrefix.replace("/","\\");
 #endif
 
-    QRect resolution = config->vid_Resolution();
-    return QString("--user-dir " + userdir
-                   + " --width " + QString::number(resolution.width())
-                   + " --height " + QString::number(resolution.height())
+    std::pair<QRect, QRect> resolutions = config->vid_ResolutionPair();
+    return QString("--prefix " + prefix
+                   + " --user-prefix " + userPrefix
+                   + " --fullscreen-width " + QString::number(resolutions.first.width())
+                   + " --fullscreen-height " + QString::number(resolutions.first.height())
+                   + " --width " + QString::number(resolutions.second.width())
+                   + " --height " + QString::number(resolutions.second.height())
                    + " --volume " + QString::number(config->volume())
                    + (config->isMusicEnabled() ? "" : " --nomusic")
                    + (config->isSoundEnabled() ? "" : " --nosound")
@@ -1914,8 +1892,8 @@
     registry_hkcr.setValue("Hedgewars.Save/Default", tr("Hedgewars Save File", "File Types"));
     registry_hkcr.setValue("Hedgewars.Demo/DefaultIcon/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwdfile.ico\",0");
     registry_hkcr.setValue("Hedgewars.Save/DefaultIcon/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwsfile.ico\",0");
-    registry_hkcr.setValue("Hedgewars.Demo/Shell/Open/Command/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwengine.exe\" \"" + datadir->absolutePath().replace("/", "\\") + "\" \"%1\" "+arguments);
-    registry_hkcr.setValue("Hedgewars.Save/Shell/Open/Command/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwengine.exe\" \"" + datadir->absolutePath().replace("/", "\\") + "\" \"%1\" "+arguments);
+    registry_hkcr.setValue("Hedgewars.Demo/Shell/Open/Command/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwengine.exe\" \"%1\" "+arguments);
+    registry_hkcr.setValue("Hedgewars.Save/Shell/Open/Command/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwengine.exe\" \"%1\" "+arguments);
 #elif defined __APPLE__
     // only useful when other apps have taken precedence over our file extensions and you want to reset it
     system("defaults write com.apple.LaunchServices LSHandlers -array-add '<dict><key>LSHandlerContentTag</key><string>hwd</string><key>LSHandlerContentTagClass</key><string>public.filename-extension</string><key>LSHandlerRoleAll</key><string>org.hedgewars.desktop</string></dict>'");
@@ -1981,28 +1959,41 @@
 
 void HWForm::SendFeedback()
 {
-    //Create Xml representation of google code issue first
-    if (!CreateIssueXml())
+    // Get form data
+    
+    QString summary = ui.pageFeedback->summary->text();
+    QString description = ui.pageFeedback->description->toPlainText();
+    QString email = ui.pageFeedback->email->text();
+    QString captchaCode = ui.pageFeedback->captcha_code->text();
+    QString captchaID = QString::number(ui.pageFeedback->captchaID);
+    QString version = "HedgewarsFoundation-Hedgewars-" + (cVersionString?(*cVersionString):QString(""));
+
+    if (summary.isEmpty() || description.isEmpty())
     {
-        ShowErrorMessage(QMessageBox::tr("Please fill out all fields"));
+        ShowErrorMessage(QMessageBox::tr("Please fill out all fields. Email is optional."));
         return;
     }
 
-    //Submit issue to PHP script
-    QString source = "HedgewarsFoundation-Hedgewars-";
-    source += (cVersionString?(*cVersionString):QString(""));
-    QString captchaCode = ui.pageFeedback->captcha_code->text();
-    QString captchaID = QString::number(ui.pageFeedback->captchaID);
+    // Submit issue to PHP script
     
     QByteArray body;
     body.append("captcha=");
     body.append(captchaID);
     body.append("&code=");
     body.append(captchaCode);
-    body.append("&source=");
-    body.append(source);
-    body.append("&issue=");
-    body.append(QUrl::toPercentEncoding(issueXml));
+    body.append("&version=");
+    body.append(QUrl::toPercentEncoding(version));
+    body.append("&title=");
+    body.append(QUrl::toPercentEncoding(summary));
+    body.append("&body=");
+    body.append(QUrl::toPercentEncoding(description));
+    body.append("&email=");
+    body.append(QUrl::toPercentEncoding(email));
+    if (ui.pageFeedback->CheckSendSpecs->isChecked())
+    {
+        body.append("&specs=");
+        body.append(QUrl::toPercentEncoding(ui.pageFeedback->specs));
+    }
     
     nam = new QNetworkAccessManager(this);
     connect(nam, SIGNAL(finished(QNetworkReply*)),
@@ -2014,40 +2005,6 @@
     nam->post(header, body);
 }
 
-bool HWForm::CreateIssueXml()
-{
-    QString summary = ui.pageFeedback->summary->text();
-    QString description = ui.pageFeedback->description->toPlainText();
-    QString email = ui.pageFeedback->email->text();
-
-    //Check if all necessary information is entered
-    if (summary.isEmpty() || description.isEmpty())
-        return false;
-
-    issueXml =
-        "<?xml version='1.0' encoding='UTF-8'?>"
-        "<entry xmlns='http://www.w3.org/2005/Atom' xmlns:issues='http://code.google.com/p/hedgewars/issues/list'>"
-        "<title>";
-    issueXml.append(summary);
-    issueXml.append("</title><content type='html'>");
-    issueXml.append(description);
-    issueXml.append("</content><author><name>feedback.hedgewars</name></author>");
-
-    if (!email.isEmpty())
-    {
-        issueXml.append("<issues:owner><issues:username>");
-        issueXml.append(email);
-        issueXml.append("</issues:username></issues:owner>");
-        issueXml.append("<issues:cc><issues:username>");
-        issueXml.append(email);
-        issueXml.append("</issues:username></issues:cc>");
-    }
-
-    issueXml.append("</entry>");
-
-    return true;
-}
-
 void HWForm::finishedSlot(QNetworkReply* reply)
 {
     if (reply && reply->error() == QNetworkReply::NoError)
@@ -2055,13 +2012,13 @@
             QMessageBox infoMsg(this);
             infoMsg.setIcon(QMessageBox::Information);
             infoMsg.setWindowTitle(QMessageBox::tr("Hedgewars - Success"));
-            infoMsg.setText(QMessageBox::tr("Successfully posted the issue on hedgewars.googlecode.com"));
+            infoMsg.setText(reply->readAll());
             infoMsg.setWindowModality(Qt::WindowModal);
             infoMsg.exec();
 
             ui.pageFeedback->summary->clear();
+            ui.pageFeedback->email->clear();
             ui.pageFeedback->description->clear();
-            ui.pageFeedback->EmbedSystemInfo();
             ui.pageFeedback->LoadCaptchaImage();
             
             return;
--- a/QTfrontend/hwform.h	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/hwform.h	Fri Jan 04 21:44:40 2013 +0400
@@ -128,9 +128,7 @@
         void InitCampaignPage();
         //Starts the transmission process for the feedback
         void SendFeedback();
-        //Make a xml representation of the issue to be created
-        bool CreateIssueXml();
-        //Called after posting a new issue
+        //Called after submitting new feedback
         void finishedSlot(QNetworkReply* reply);
 
         void NetGameChangeStatus(bool isMaster);
@@ -150,6 +148,7 @@
         void closeEvent(QCloseEvent *event);
         void CustomizePalettes();
         void resizeEvent(QResizeEvent * event);
+        QString stringifyPageId(quint32 id);
         //void keyReleaseEvent(QKeyEvent *event);
 
         enum PageIDs
@@ -172,7 +171,6 @@
             ID_PAGE_CONNECTING     ,
             ID_PAGE_SCHEME         ,
             ID_PAGE_ADMIN          ,
-            ID_PAGE_NETTYPE        ,
             ID_PAGE_CAMPAIGN       ,
             ID_PAGE_DRAWMAP        ,
             ID_PAGE_DATADOWNLOAD   ,
@@ -193,7 +191,6 @@
         QSignalMapper * pageSwitchMapper;
         QByteArray m_lastDemo;
         QNetworkAccessManager * nam;
-        QString issueXml;
 
         QPropertyAnimation *animationNewSlide;
         QPropertyAnimation *animationOldSlide;
--- a/QTfrontend/main.cpp	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/main.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -27,6 +27,8 @@
 #include <QSettings>
 #include <QStringListModel>
 #include <QDate>
+#include <QDesktopWidget>
+#include <QLabel>
 
 #include "hwform.h"
 #include "hwconsts.h"
@@ -39,9 +41,11 @@
 
 #ifdef _WIN32
 #include <Shlobj.h>
+#elif defined __APPLE__
+#include "CocoaInitializer.h"
 #endif
-#ifdef __APPLE__
-#include "CocoaInitializer.h"
+#ifndef _WIN32
+#include <signal.h>
 #endif
 
 
@@ -87,6 +91,12 @@
     else
         season = SEASON_NONE;
 }
+#ifndef _WIN32
+void terminateFrontend(int signal)
+{
+    QCoreApplication::exit(0);
+}
+#endif
 
 bool checkForDir(const QString & dir)
 {
@@ -136,8 +146,25 @@
     atexit(releaseCocoaPool);
 #endif
 
+#ifndef _WIN32
+    signal(SIGINT, &terminateFrontend);
+#endif
+
     HWApplication app(argc, argv);
 
+    QLabel *splash = NULL;
+#if defined Q_WS_WIN
+    QPixmap pixmap(":res/splash.png");
+    splash = new QLabel(0, Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint);
+    splash->setAttribute(Qt::WA_TranslucentBackground);
+    const QRect deskSize = QApplication::desktop()->screenGeometry(-1);
+    QPoint splashCenter = QPoint( (deskSize.width() - pixmap.width())/2,
+                                  (deskSize.height() - pixmap.height())/2 );
+    splash->move(splashCenter);
+    splash->setPixmap(pixmap);
+    splash->show();
+#endif
+
     FileEngineHandler engine(argv[0]);
 
     flib_init();
@@ -179,9 +206,14 @@
     if(parsedArgs.contains("config-dir"))
     {
         QFileInfo f(parsedArgs["config-dir"]);
-        *cConfigDir = f.absoluteFilePath();
+        cfgdir->setPath(f.absoluteFilePath());
         custom_config = true;
     }
+    else
+    {
+        cfgdir->setPath(QDir::homePath());
+        custom_config = false;
+    }
 
     app.setStyle(new QPlastiqueStyle());
 
@@ -193,14 +225,9 @@
 
     qRegisterMetaType<HWTeam>("HWTeam");
 
-    bindir->cd("bin"); // workaround over NSIS installer
+    bindir->cd(QCoreApplication::applicationDirPath());
 
-    if(cConfigDir->length() == 0)
-        cfgdir->setPath(cfgdir->homePath());
-    else
-        cfgdir->setPath(*cConfigDir);
-
-    if(cConfigDir->length() == 0)
+    if(custom_config == false)
     {
 #ifdef __APPLE__
         checkForDir(cfgdir->absolutePath() + "/Library/Application Support/Hedgewars");
@@ -241,14 +268,14 @@
 
     datadir->cd(bindir->absolutePath());
     datadir->cd(*cDataDir);
-    if(!datadir->cd("hedgewars/Data"))
+    if(!datadir->cd("Data"))
     {
         QMessageBox missingMsg(QApplication::activeWindow());
         missingMsg.setIcon(QMessageBox::Critical);
         missingMsg.setWindowTitle(QMessageBox::tr("Main - Error"));
         missingMsg.setText(QMessageBox::tr("Failed to open data directory:\n%1\n\n"
                                            "Please check your installation!").
-                                            arg(datadir->absolutePath()+"/hedgewars/Data"));
+                                            arg(datadir->absolutePath()+"/Data"));
         missingMsg.setWindowModality(Qt::WindowModal);
         missingMsg.exec();
         return 1;
@@ -307,6 +334,7 @@
             break;
         default :
             fname = "qt.css";
+            break;
     }
 
     // load external stylesheet if there is any
@@ -321,6 +349,10 @@
 
     app.form = new HWForm(NULL, style);
     app.form->show();
+
+    if(splash)
+        splash->close();
+
     int r = app.exec();
 
     flib_quit();
--- a/QTfrontend/net/hwmap.cpp	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/net/hwmap.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -79,9 +79,12 @@
     int ipc_port = flib_mapconn_getport(m_conn);
 
     QStringList arguments;
-    arguments << cfgdir->absolutePath();
+    arguments << "--internal";
+    arguments << "--port";
     arguments << QString("%1").arg(ipc_port);
-    arguments << "landpreview";
+    arguments << "--user-prefix";
+    arguments << cfgdir->absolutePath();
+    arguments << "--landpreview";
     return arguments;
 }
 
--- a/QTfrontend/net/recorder.cpp	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/net/recorder.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -104,25 +104,40 @@
 {
     QStringList arguments;
     QRect resolution = config->rec_Resolution();
-    arguments << cfgdir->absolutePath();
-    arguments << QString::number(resolution.width());
-    arguments << QString::number(resolution.height());
-    arguments << "32"; // bpp
+    QString nick = config->netNick().toUtf8().toBase64();
+
+    arguments << "--internal";
+    arguments << "--port";
     //arguments << QString("%1").arg(ipc_port);
-    arguments << "0"; // fullscreen
-    arguments << "0"; // sound
-    arguments << "0"; // music
-    arguments << "0"; // sound volume
+    arguments << "--prefix";
+    arguments << datadir->absolutePath();
+    arguments << "--user-prefix";
+    arguments << cfgdir->absolutePath();
+    arguments << "--locale";
+    arguments << HWGame::tr("en.txt");
+    arguments << "--frame-interval";
     arguments << QString::number(config->timerInterval());
-    arguments << datadir->absolutePath();
-    arguments << "0"; // fps
-    arguments << (config->isAltDamageEnabled() ? "1" : "0");
-    arguments << config->netNick().toUtf8().toBase64();
+    arguments << "--width";
+    arguments << QString::number(resolution.width());
+    arguments << "--height";
+    arguments << QString::number(resolution.height());
+    arguments << "--nosound";
+    arguments << "--raw-quality";
     arguments << QString::number(config->translateQuality());
+    arguments << "--stereo";
     arguments << QString::number(config->stereoMode());
-    arguments << HWGame::tr("en.txt");
-    arguments << QString::number(config->rec_Framerate()); // framerate numerator
-    arguments << "1";  // framerate denominator
+    arguments << "--nomusic";
+    arguments << "--volume";
+    arguments << "0";
+    if (config->isAltDamageEnabled())
+        arguments << "--altdmg";
+    if (!nick.isEmpty()) {
+        arguments << "--nick";
+        arguments << nick;
+    }
+    arguments << "--recorder";
+    arguments << QString::number(config->rec_Framerate()); //cVideoFramerateNum
+    arguments << "1"; //cVideoFramerateDen
     arguments << prefix;
     arguments << config->AVFormat();
     arguments << config->videoCodec();
--- a/QTfrontend/net/tcpBase.cpp	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/net/tcpBase.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -29,31 +29,39 @@
 
 #ifdef HWLIBRARY
 extern "C" void Game(char**arguments);
+extern "C" void GenLandPreview(int port);
 
-//NOTE: most likely subclassing QThread is wrong
-class EngineThread : public QThread
+
+EngineInstance::EngineInstance(QObject *parent)
+    : QObject(parent)
 {
-protected:
-    void run();
-};
+    port = 0;
+}
 
-void EngineThread::run()
+EngineInstance::~EngineInstance()
+{
+}
+
+void EngineInstance::start()
 {
-    char *args[12];
-    args[0] = "1";      //cShowFPS
-    args[1] = "65000";  //ipcPort
-    args[2] = "1024";   //cScreenWidth
-    args[3] = "768";    //cScreenHeight
-    args[4] = "0";      //cReducedQuality
-    args[5] = "en.txt"; //cLocaleFName
-    args[6] = "koda";   //UserNick
-    args[7] = "1";      //SetSound
-    args[8] = "1";      //SetMusic
-    args[9] = "0";      //cAltDamage
-    args[10]= "../Resources/hedgewars/Data";   //cPathPrefix
-    args[11]= NULL;     //recordFileName
+#if 0
+    char *args[11];
+    args[0] = "65000";  //ipcPort
+    args[1] = "1024";   //cScreenWidth
+    args[2] = "768";    //cScreenHeight
+    args[3] = "0";      //cReducedQuality
+    args[4] = "en.txt"; //cLocaleFName
+    args[5] = "koda";   //UserNick
+    args[6] = "1";      //SetSound
+    args[7] = "1";      //SetMusic
+    args[8] = "0";      //cAltDamage
+    args[9]= datadir->absolutePath().toAscii().data(); //cPathPrefix
+    args[10]= NULL;     //recordFileName
     Game(args);
+#endif
+    GenLandPreview(port);
 }
+
 #endif
 
 QList<TCPBase*> srvsList;
@@ -76,8 +84,17 @@
     onEngineStart();
 
 #ifdef HWLIBRARY
-    EngineThread engineThread;// = new EngineThread(this);
-    engineThread.start();
+    QThread *thread = new QThread;
+    EngineInstance *instance = new EngineInstance;
+    instance->port = IPCServer->serverPort();
+
+    instance->moveToThread(thread);
+
+    connect(thread, SIGNAL(started()), instance, SLOT(start(void)));
+    connect(instance, SIGNAL(finished()), thread, SLOT(quit()));
+    connect(instance, SIGNAL(finished()), instance, SLOT(deleteLater()));
+    connect(instance, SIGNAL(finished()), thread, SLOT(deleteLater()));
+    thread->start();
 #else
     QProcess * process;
 
--- a/QTfrontend/net/tcpBase.h	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/net/tcpBase.h	Fri Jan 04 21:44:40 2013 +0400
@@ -54,4 +54,21 @@
         void iStart();
 };
 
+#ifdef HWLIBRARY
+class EngineInstance : public QObject
+{
+    Q_OBJECT
+public:
+    EngineInstance(QObject *parent = 0);
+    ~EngineInstance();
+
+    int port;
+public slots:
+    void start(void);
+signals:
+    void finished(void);
+private:
+};
+#endif
+
 #endif // _TCPBASE_INCLUDED
Binary file QTfrontend/res/NetworkPlayDisabled.png has changed
--- a/QTfrontend/res/css/christmas.css	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/res/css/christmas.css	Fri Jan 04 21:44:40 2013 +0400
@@ -21,7 +21,7 @@
 background-image: url(":/res/BackgroundChristmas.png");
 background-position: bottom center;
 background-repeat: repeat-x;
-background-color: #141250;
+background-color: #0c0f28;
 }
 
 * {
--- a/QTfrontend/res/css/qt.css	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/res/css/qt.css	Fri Jan 04 21:44:40 2013 +0400
@@ -105,7 +105,6 @@
 outline: none;
 }
 
-
 QHeaderView {
 border-radius: 0;
 border-width: 0;
Binary file QTfrontend/res/splash.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/res/xml/tips.xml	Fri Jan 04 21:44:40 2013 +0400
@@ -0,0 +1,61 @@
+# This is not xml actually, but it looks and behaves like it.
+# Including an xml library would need too much resources.
+# Tips between the platform specific tags are shown only on those platforms.
+# Do not escape characters or use the CDATA tag.
+<tips>
+    <tip>Simply pick the same color as a friend to play together as a team. Each of you will still control his or her own hedgehogs but they'll win or lose together.</tip>
+    <tip>Some weapons might do only low damage but they can be a lot more devastating in the right situation. Try to use the Desert Eagle to knock multiple hedgehogs into the water.</tip>
+    <tip>If you're unsure what to do and don't want to waste ammo, skip one round. But don't let too much time pass as there will be Sudden Death!</tip>
+    <tip>Want to save ropes? Release the rope in mid air and then shoot again. As long as you don't touch the ground you'll reuse your rope without wasting ammo!</tip>
+    <tip>If you'd like to keep others from using your preferred nickname on the official server, register an account at http://www.hedgewars.org/.</tip>
+    <tip>You're bored of default gameplay? Try one of the missions - they'll offer different gameplay depending on the one you picked.</tip>
+    <tip>By default the game will always record the last game played as a demo. Select 'Local Game' and pick the 'Demos' button on the lower right corner to play or manage them.</tip>
+    <tip>Hedgewars is Open Source and Freeware we create in our spare time. If you've got problems, ask on our forums but please don't expect 24/7 support!</tip>
+    <tip>Hedgewars is Open Source and Freeware we create in our spare time. If you like it, help us with a small donation or contribute your own work!</tip>
+    <tip>Hedgewars is Open Source and Freeware we create in our spare time. Share it with your family and friends as you like!</tip>
+    <tip>Hedgewars is Open Source and Freeware we create in our spare time. If someone sold you the game, you should try get a refund!</tip>
+    <tip>From time to time there will be official tournaments. Upcoming events will be announced at http://www.hedgewars.org/ some days in advance.</tip>
+    <tip>Hedgewars is available in many languages. If the translation in your language seems to be missing or outdated, feel free to contact us!</tip>
+    <tip>Hedgewars can be run on lots of different operating systems including Microsoft Windows, Mac OS X and Linux.</tip>
+    <tip>Always remember you're able to set up your own games in local and network/online play. You're not restricted to the 'Simple Game' option.</tip>
+    <tip>Connect one or more gamepads before starting the game to be able to assign their controls to your teams.</tip>
+    <tip>Create an account on <a href="http://www.hedgewars.org/">http://www.hedgewars.org/</a> to keep others from using your most favourite nickname while playing on the official server.</tip>
+    <tip>While playing you should give yourself a short break at least once an hour.</tip>
+    <tip>If your graphics card isn't able to provide hardware accelerated OpenGL, try to enable the low quality mode to improve performance.</tip>
+    <tip>If your graphics card isn't able to provide hardware accelerated OpenGL, try to update the associated drivers.</tip>
+    <tip>We're open to suggestions and constructive feedback. If you don't like something or got a great idea, let us know!</tip>
+    <tip>Especially while playing online be polite and always remember there might be some minors playing with or against you as well!</tip>
+    <tip>Special game modes such as 'Vampirism' or 'Karma' allow you to develop completely new tactics. Try them in a custom game!</tip>
+    <tip>The Windows version of Hedgewars supports Xfire. Make sure to add Hedgewars to its game list so your friends can see you playing.</tip>
+    <tip>You should never install Hedgewars on computers you don't own (school, university, work, etc.). Please ask the responsible person instead!</tip>
+    <tip>Hedgewars can be perfect for short games during breaks. Just ensure you don't add too many hedgehogs or use an huge map. Reducing time and health might help as well.</tip>
+    <tip>No hedgehogs were harmed in making this game.</tip>
+    <tip>There are three different jumps available. Tap [high jump] twice to do a very high/backwards jump.</tip>
+    <tip>Afraid of falling off a cliff? Hold down [precise] to turn [left] or [right] without actually moving.</tip>
+    <tip>Some weapons require special strategies or just lots of training, so don't give up on a particular tool if you miss an enemy once.</tip>
+    <tip>Most weapons won't work once they touch the water. The Homing Bee as well as the Cake are exceptions to this.</tip>
+    <tip>The Old Limbuger only causes a small explosion. However the wind affected smelly cloud can poison lots of hogs at once.</tip>
+    <tip>The Piano Strike is the most damaging air strike. You'll lose the hedgehog performing it, so there's a huge downside as well.</tip>
+    <tip>The Homing Bee can be tricky to use. Its turn radius depends on its velocity, so try to not use full power.</tip>
+    <tip>Sticky Mines are a perfect tool to create small chain reactions knocking enemy hedgehogs into dire situations ... or water.</tip>
+    <tip>The Hammer is most effective when used on bridges or girders. Hit hogs will just break through the ground.</tip>
+    <tip>If you're stuck behind an enemy hedgehog, use the Hammer to free yourself without getting damaged by an explosion.</tip>
+    <tip>The Cake's maximum walking distance depends on the ground it has to pass. Use [attack] to detonate it early.</tip>
+    <tip>The Flame Thrower is a weapon but it can be used for tunnel digging as well.</tip>
+    <tip>Use the Molotov or Flame Thrower to temporary keep hedgehogs from passing terrain such as tunnels or platforms.</tip>
+    <tip>Want to know who's behind the game? Click on the Hedgewars logo in the main menu to see the credits.</tip>
+    <tip>Like Hedgewars? Become a fan on <a href="http://www.facebook.com/Hedgewars">Facebook</a> or follow us on <a href="http://twitter.com/hedgewars">Twitter</a></tip>
+    <tip>Feel free to draw your own graves, hats, flags or even maps and themes! But note that you'll have to share them somewhere to use them online.</tip>
+    <tip>Keep your video card drivers up to date to avoid issues playing the game.</tip>
+    <tip>You're able to associate Hedgewars related files (savegames and demo recordings) with the game to launch them right from your favorite file or internet browser.</tip>
+    <windows-only>
+        <tip>You can find your Hedgewars configuration files under "My Documents\Hedgewars". Create backups or take the files with you, but don't edit them by hand.</tip>
+    </windows-only>
+    <mac-only>
+        <tip>You can find your Hedgewars configuration files under "Library/Application Support/Hedgewars" in your home directory. Create backups or take the files with you, but don't edit them by hand.</tip>
+    </mac-only>
+    <linux-only>
+        <tip>lintip</tip>
+        <tip>You can find your Hedgewars configuration files under ".hedgewars" in your home directory. Create backups or take the files with you, but don't edit them by hand.</tip>
+    </linux-only>
+</tips>
--- a/QTfrontend/ui/mouseoverfilter.cpp	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/ui/mouseoverfilter.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -39,7 +39,7 @@
         QComboBox * droplist = dynamic_cast<QComboBox*>(dist);
         QSlider * slider = dynamic_cast<QSlider*>(dist);
         QTabWidget * tab = dynamic_cast<QTabWidget*>(dist);
-        if (HWForm::config->isFrontendSoundEnabled() && (button || textfield || checkbox || droplist || slider || tab))
+        if (button || textfield || checkbox || droplist || slider || tab)
         {
             SDLInteraction::instance().playSoundFile("/Sounds/steps.ogg");
         }
--- a/QTfrontend/ui/page/pageeditteam.cpp	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/ui/page/pageeditteam.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -30,6 +30,7 @@
 #include <QDebug>
 #include "SquareLabel.h"
 #include "HWApplication.h"
+#include "keybinder.h"
 
 #include "DataManager.h"
 #include "HatModel.h"
@@ -39,16 +40,16 @@
 QLayout * PageEditTeam::bodyLayoutDefinition()
 {
     QGridLayout * pageLayout = new QGridLayout();
-    QTabWidget * tbw = new QTabWidget();
+    tbw = new QTabWidget();
     QWidget * page1 = new QWidget(this);
-    QWidget * page2 = new QWidget(this);
+    binder = new KeyBinder(this, tr("Select an action to choose a custom key bind for this team"), tr("Use my default"), tr("Reset all binds"));
+    connect(binder, SIGNAL(resetAllBinds()), this, SLOT(resetAllBinds()));
     tbw->addTab(page1, tr("General"));
-    tbw->addTab(page2, tr("Advanced"));
+    tbw->addTab(binder, tr("Custom Controls"));
     pageLayout->addWidget(tbw, 0, 0, 1, 3);
 
     QHBoxLayout * page1Layout = new QHBoxLayout(page1);
     page1Layout->setAlignment(Qt::AlignTop);
-    QGridLayout * page2Layout = new QGridLayout(page2);
 
 // ====== Page 1 ======
     QVBoxLayout * vbox1 = new QVBoxLayout();
@@ -157,52 +158,6 @@
     vbox1->addStretch();
     vbox2->addStretch();
 
-// ====== Page 2 ======
-    GBoxBinds = new QGroupBox(this);
-    GBoxBinds->setTitle(QGroupBox::tr("Key binds"));
-    QGridLayout * GBBLayout = new QGridLayout(GBoxBinds);
-    BindsBox = new QToolBox(GBoxBinds);
-    BindsBox->setLineWidth(0);
-    GBBLayout->addWidget(BindsBox);
-    page2Layout->addWidget(GBoxBinds, 0, 0);
-
-    quint16 i = 0;
-    quint16 num = 0;
-    QWidget * curW = NULL;
-    QGridLayout * pagelayout = NULL;
-    QLabel* l = NULL;
-    while (i < BINDS_NUMBER)
-    {
-        if(cbinds[i].category != NULL)
-        {
-            if(curW != NULL)
-            {
-                l = new QLabel(curW);
-                l->setText("");
-                pagelayout->addWidget(l, num++, 0, 1, 2);
-            }
-            curW = new QWidget(this);
-            BindsBox->addItem(curW, HWApplication::translate("binds (categories)", cbinds[i].category));
-            pagelayout = new QGridLayout(curW);
-            num = 0;
-        }
-        if(cbinds[i].description != NULL)
-        {
-            l = new QLabel(curW);
-            l->setText((num > 0 ? QString("\n") : QString("")) + HWApplication::translate("binds (descriptions)", cbinds[i].description));
-            pagelayout->addWidget(l, num++, 0, 1, 2);
-        }
-
-        l = new QLabel(curW);
-        l->setText(HWApplication::translate("binds", cbinds[i].name));
-        l->setAlignment(Qt::AlignRight);
-        pagelayout->addWidget(l, num, 0);
-
-        CBBind[i] = new QComboBox(curW);
-        CBBind[i]->setModel(DataManager::instance().bindsModel());
-        pagelayout->addWidget(CBBind[i++], num++, 1);
-    }
-
     return pageLayout;
 }
 
@@ -407,6 +362,9 @@
 
 void PageEditTeam::loadTeam(const HWTeam & team)
 {
+    tbw->setCurrentIndex(0);
+    binder->resetInterface();
+    
     TeamNameEdit->setText(team.name());
     CBTeamLvl->setCurrentIndex(team.difficulty());
 
@@ -430,10 +388,12 @@
     QStandardItemModel * binds = DataManager::instance().bindsModel();
     for(int i = 0; i < BINDS_NUMBER; i++)
     {
+        if (team.keyBind(i).isEmpty()) continue;
+        
         QModelIndexList mdl = binds->match(binds->index(0, 0), Qt::UserRole + 1, team.keyBind(i), 1, Qt::MatchExactly);
 
         if(mdl.size() == 1)
-            CBBind[i]->setCurrentIndex(mdl[0].row());
+            binder->setBindIndex(i, mdl[0].row());
         else
             qDebug() << "Binds: cannot find" << team.keyBind(i);
     }
@@ -463,7 +423,7 @@
     QStandardItemModel * binds = DataManager::instance().bindsModel();
     for(int i = 0; i < BINDS_NUMBER; i++)
     {
-        team.bindKey(i, binds->index(CBBind[i]->currentIndex(), 0).data(Qt::UserRole + 1).toString());
+        team.bindKey(i, binds->index(binder->bindIndex(i), 0).data(Qt::UserRole + 1).toString());
     }
 
     return team;
@@ -473,3 +433,10 @@
 {
     data().saveToFile();
 }
+
+// When the "Use default for all binds" is pressed...
+void PageEditTeam::resetAllBinds()
+{
+    for (int i = 0; i < BINDS_NUMBER; i++)
+        binder->setBindIndex(i, 0);
+}
--- a/QTfrontend/ui/page/pageeditteam.h	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/ui/page/pageeditteam.h	Fri Jan 04 21:44:40 2013 +0400
@@ -28,6 +28,7 @@
 #include "team.h"
 
 class SquareLabel;
+class KeyBinder;
 
 class PageEditTeam : public AbstractPage
 {
@@ -44,6 +45,7 @@
         void CBFort_activated(const QString & gravename);
 
     private:
+        QTabWidget * tbw;
         QSignalMapper* signalMapper1;
         QSignalMapper* signalMapper2;
         QGroupBox *GBoxHedgehogs;
@@ -60,9 +62,9 @@
         QLineEdit * TeamNameEdit;
         QLineEdit * HHNameEdit[HEDGEHOGS_PER_TEAM];
         QComboBox * HHHats[HEDGEHOGS_PER_TEAM];
-        QComboBox * CBBind[BINDS_NUMBER];
         HWTeam data();
         QString m_playerHash;
+        KeyBinder * binder;
 
         QLayout * bodyLayoutDefinition();
         QLayout * footerLayoutDefinition();
@@ -85,6 +87,7 @@
         void testSound();
 
         void fixHHname(int idx);
+        void resetAllBinds();
 };
 
 #endif
--- a/QTfrontend/ui/page/pagefeedback.cpp	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/ui/page/pagefeedback.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -29,6 +29,7 @@
 #include <QNetworkReply>
 #include <QProcess>
 #include <QMessageBox>
+#include <QCheckBox>
 
 #include <string>
 
@@ -54,7 +55,9 @@
     QVBoxLayout * pageLayout = new QVBoxLayout();
     QHBoxLayout * summaryLayout = new QHBoxLayout();
     QHBoxLayout * emailLayout = new QHBoxLayout();
+    QHBoxLayout * descriptionLayout = new QHBoxLayout();
     QHBoxLayout * combinedTopLayout = new QHBoxLayout();
+    QHBoxLayout * systemLayout = new QHBoxLayout();
 
     info = new QLabel();
     info->setText(
@@ -62,55 +65,161 @@
         "a { color: #fc0; }"
         "b { color: #0df; }"
         "</style>"
-        "<div align=\"center\"><h1>Please give us a feedback!</h1>"
-        "<h3>We are always happy about suggestions, ideas or bug reports.<h3>"
-        "<h4>The feedback will be posted as a new issue on our Google Code page.<br />"
-        "<b>Don't forget to mention your email or you won't be able to receive updates on this topic!</b><br /></h4>"
-        //"<h4>Your email is optional, but if given, you will be notified of responses.<h4>"
+        "<div align=\"center\"><h1>Please give us feedback!</h1>"
+        "<h3>We are always happy about suggestions, ideas, or bug reports.<h3>"
+        "<h4>Your email address is optional, but we may want to contact you.<h4>"
         "</div>"
     );
     pageLayout->addWidget(info);
 
-    label_summary = new QLabel();
-    label_summary->setText(QLabel::tr("Summary"));
-    summaryLayout->addWidget(label_summary);
-    summary = new QLineEdit();
-    summaryLayout->addWidget(summary);
-    combinedTopLayout->addLayout(summaryLayout);
+    QVBoxLayout * summaryEmailLayout = new QVBoxLayout();
+
+    const int labelWidth = 90;
 
     label_email = new QLabel();
     label_email->setText(QLabel::tr("Your Email"));
+    label_email->setFixedWidth(labelWidth);
     emailLayout->addWidget(label_email);
     email = new QLineEdit();
     emailLayout->addWidget(email);
+    summaryEmailLayout->addLayout(emailLayout);
     
-    //  Email -- although implemented -- doesn't seem to work as intended.
-    //  It's sent in the XML as a <issues:cc> , the <entry>, but it doesn't seem
-    //  to actually do anything. If you figure out how to fix that, uncomment these lines
-    //  and the line above in the 'info' QLabel to re-enable this feature.
-    //  UPDATE: I found out that CC only works if that email is a member of the
-    //  Google Code project. So this feature is pretty much useless atm.
-    /*
-    combinedTopLayout->addLayout(emailLayout);
-    combinedTopLayout->insertSpacing(1, 50);
-    */
+    label_summary = new QLabel();
+    label_summary->setText(QLabel::tr("Summary"));
+    label_summary->setFixedWidth(labelWidth);
+    summaryLayout->addWidget(label_summary);
+    summary = new QLineEdit();
+    summaryLayout->addWidget(summary);
+    summaryEmailLayout->addLayout(summaryLayout);
+    
+    combinedTopLayout->addLayout(summaryEmailLayout);
+
+
+    CheckSendSpecs = new QCheckBox();
+    CheckSendSpecs->setText(QLabel::tr("Send system information"));
+    CheckSendSpecs->setChecked(true);
+    systemLayout->addWidget(CheckSendSpecs);
+    BtnViewInfo = addButton("View", systemLayout, 1, false);
+    BtnViewInfo->setFixedSize(60, 30);
+    connect(BtnViewInfo, SIGNAL(clicked()), this, SLOT(ShowSpecs()));
+    combinedTopLayout->addLayout(systemLayout);
+
+    combinedTopLayout->setStretch(0, 1);
+    combinedTopLayout->insertSpacing(1, 20);
 
     pageLayout->addLayout(combinedTopLayout);
 
     label_description = new QLabel();
     label_description->setText(QLabel::tr("Description"));
-    pageLayout->addWidget(label_description, 0, Qt::AlignHCenter);
+    label_description->setFixedWidth(labelWidth);
+    descriptionLayout->addWidget(label_description, 0, Qt::AlignTop);
     description = new QTextBrowser();
-
-    EmbedSystemInfo();
-    
     description->setReadOnly(false);
-    pageLayout->addWidget(description);
+    descriptionLayout->addWidget(description);
+    pageLayout->addLayout(descriptionLayout);
 
     return pageLayout;
 }
 
-void PageFeedback::EmbedSystemInfo()
+QNetworkAccessManager * PageFeedback::GetNetManager()
+{
+    if (netManager) return netManager;
+    netManager = new QNetworkAccessManager(this);
+    connect(netManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(NetReply(QNetworkReply*)));
+    return netManager;
+}
+
+void PageFeedback::LoadCaptchaImage()
+{
+        QNetworkAccessManager *netManager = GetNetManager();
+        QUrl captchaURL("http://hedgewars.org/feedback/?gencaptcha");
+        QNetworkRequest req(captchaURL);
+        genCaptchaRequest = netManager->get(req);
+}
+
+void PageFeedback::NetReply(QNetworkReply *reply)
+{
+    if (reply == genCaptchaRequest)
+    {
+        if (reply->error() != QNetworkReply::NoError)
+        {
+            qDebug() << "Error generating captcha image: " << reply->errorString();
+            ShowErrorMessage(QMessageBox::tr("Failed to generate captcha"));
+            return;
+        }
+
+        bool okay;
+        QByteArray body = reply->readAll();
+        captchaID = QString(body).toInt(&okay);
+
+        if (!okay)
+        {
+            qDebug() << "Failed to get captcha ID: " << body;
+            ShowErrorMessage(QMessageBox::tr("Failed to generate captcha"));
+            return;
+        }
+
+        QString url = "http://hedgewars.org/feedback/?captcha&id=";
+        url += QString::number(captchaID);
+        
+        QNetworkAccessManager *netManager = GetNetManager();
+        QUrl captchaURL(url);
+        QNetworkRequest req(captchaURL);
+        captchaImageRequest = netManager->get(req);
+    }
+    else if (reply == captchaImageRequest)
+    {
+        if (reply->error() != QNetworkReply::NoError)
+        {
+            qDebug() << "Error loading captcha image: " << reply->errorString();
+            ShowErrorMessage(QMessageBox::tr("Failed to download captcha"));
+            return;
+        }
+
+        QByteArray imageData = reply->readAll();
+        QPixmap pixmap;
+        pixmap.loadFromData(imageData);
+        label_captcha->setPixmap(pixmap);
+        captcha_code->setText("");
+    }
+}
+
+QLayout * PageFeedback::footerLayoutDefinition()
+{
+    QHBoxLayout * bottomLayout = new QHBoxLayout();
+    QHBoxLayout * captchaLayout = new QHBoxLayout();
+    QVBoxLayout * captchaInputLayout = new QVBoxLayout();
+
+    label_captcha = new QLabel();
+    label_captcha->setStyleSheet("border: 3px solid #ffcc00; border-radius: 4px");
+    label_captcha->setText("<div style='width: 200px; height: 100px;'>loading<br>captcha</div>");
+    captchaLayout->addWidget(label_captcha);
+
+    label_captcha_input = new QLabel();
+    label_captcha_input->setText(QLabel::tr("Type the security code:"));
+    captchaInputLayout->addWidget(label_captcha_input);
+    captchaInputLayout->setAlignment(label_captcha, Qt::AlignBottom);
+    captcha_code = new QLineEdit();
+    captcha_code->setFixedSize(165, 30);
+    captchaInputLayout->addWidget(captcha_code);
+    captchaInputLayout->setAlignment(captcha_code, Qt::AlignTop);
+    captchaLayout->addLayout(captchaInputLayout);
+    captchaLayout->setAlignment(captchaInputLayout, Qt::AlignLeft);
+
+    captchaLayout->insertSpacing(-1, 40);
+    bottomLayout->addLayout(captchaLayout);
+    
+    //TODO: create logo for send button
+    BtnSend = addButton("Send Feedback", bottomLayout, 0, false);
+    BtnSend->setFixedSize(120, 40);
+
+    bottomLayout->setStretchFactor(captchaLayout, 0);
+    bottomLayout->setStretchFactor(BtnSend, 1);
+
+    return bottomLayout;
+}
+
+void PageFeedback::GenerateSpecs()
 {
     // Gather some information about the system and embed it into the report
     QDesktopWidget* screen = QApplication::desktop();
@@ -243,11 +352,8 @@
     else if(sizeof(void*) == 8)
         compiler_bits += "x86_64\n";
 
-    // add everything to the field of text
-    description->setText(
-        "\n\n\n\n\n"
-        "System information:\n"
-        + qt_version
+    // concat system info
+    specs = qt_version
         + os_version
         + total_ram
         + screen_size
@@ -256,106 +362,7 @@
         + number_of_cores
         + compiler_version
         + compiler_bits
-        + kernel_line
-    );
-}
-
-QNetworkAccessManager * PageFeedback::GetNetManager()
-{
-    if (netManager) return netManager;
-    netManager = new QNetworkAccessManager(this);
-    connect(netManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(NetReply(QNetworkReply*)));
-    return netManager;
-}
-
-void PageFeedback::LoadCaptchaImage()
-{
-        QNetworkAccessManager *netManager = GetNetManager();
-        QUrl captchaURL("http://hedgewars.org/feedback/?gencaptcha");
-        QNetworkRequest req(captchaURL);
-        genCaptchaRequest = netManager->get(req);
-}
-
-void PageFeedback::NetReply(QNetworkReply *reply)
-{
-    if (reply == genCaptchaRequest)
-    {
-        if (reply->error() != QNetworkReply::NoError)
-        {
-            qDebug() << "Error generating captcha image: " << reply->errorString();
-            ShowErrorMessage(QMessageBox::tr("Failed to generate captcha"));
-            return;
-        }
-
-        bool okay;
-        QByteArray body = reply->readAll();
-        captchaID = QString(body).toInt(&okay);
-
-        if (!okay)
-        {
-            qDebug() << "Failed to get captcha ID: " << body;
-            ShowErrorMessage(QMessageBox::tr("Failed to generate captcha"));
-            return;
-        }
-
-        QString url = "http://hedgewars.org/feedback/?captcha&id=";
-        url += QString::number(captchaID);
-        
-        QNetworkAccessManager *netManager = GetNetManager();
-        QUrl captchaURL(url);
-        QNetworkRequest req(captchaURL);
-        captchaImageRequest = netManager->get(req);
-    }
-    else if (reply == captchaImageRequest)
-    {
-        if (reply->error() != QNetworkReply::NoError)
-        {
-            qDebug() << "Error loading captcha image: " << reply->errorString();
-            ShowErrorMessage(QMessageBox::tr("Failed to download captcha"));
-            return;
-        }
-
-        QByteArray imageData = reply->readAll();
-        QPixmap pixmap;
-        pixmap.loadFromData(imageData);
-        label_captcha->setPixmap(pixmap);
-        captcha_code->setText("");
-    }
-}
-
-QLayout * PageFeedback::footerLayoutDefinition()
-{
-    QHBoxLayout * bottomLayout = new QHBoxLayout();
-    QHBoxLayout * captchaLayout = new QHBoxLayout();
-    QVBoxLayout * captchaInputLayout = new QVBoxLayout();
-
-    label_captcha = new QLabel();
-    label_captcha->setStyleSheet("border: 3px solid #ffcc00; border-radius: 4px");
-    label_captcha->setText("<div style='width: 200px; height: 100px;'>loading<br>captcha</div>");
-    captchaLayout->addWidget(label_captcha);
-
-    label_captcha_input = new QLabel();
-    label_captcha_input->setText(QLabel::tr("Type the security code:"));
-    captchaInputLayout->addWidget(label_captcha_input);
-    captchaInputLayout->setAlignment(label_captcha, Qt::AlignBottom);
-    captcha_code = new QLineEdit();
-    captcha_code->setFixedSize(165, 30);
-    captchaInputLayout->addWidget(captcha_code);
-    captchaInputLayout->setAlignment(captcha_code, Qt::AlignTop);
-    captchaLayout->addLayout(captchaInputLayout);
-    captchaLayout->setAlignment(captchaInputLayout, Qt::AlignLeft);
-
-    captchaLayout->insertSpacing(-1, 40);
-    bottomLayout->addLayout(captchaLayout);
-    
-    //TODO: create logo for send button
-    BtnSend = addButton("Send Feedback", bottomLayout, 0, false);
-    BtnSend->setFixedSize(120, 40);
-
-    bottomLayout->setStretchFactor(captchaLayout, 0);
-    bottomLayout->setStretchFactor(BtnSend, 1);
-
-    return bottomLayout;
+        + kernel_line;
 }
 
 void PageFeedback::connectSignals()
@@ -373,8 +380,21 @@
     msgMsg.exec();
 }
 
+void PageFeedback::ShowSpecs()
+{
+    QMessageBox msgMsg(this);
+    msgMsg.setIcon(QMessageBox::Information);
+    msgMsg.setWindowTitle(QMessageBox::tr("System Information Preview"));
+    msgMsg.setText(specs);
+    msgMsg.setTextFormat(Qt::PlainText);
+    msgMsg.setWindowModality(Qt::WindowModal);
+    msgMsg.setStyleSheet("background: #0A0533;");
+    msgMsg.exec();
+}
+
 PageFeedback::PageFeedback(QWidget* parent) : AbstractPage(parent)
 {
     initPage();
     netManager = NULL;
+    GenerateSpecs();
 }
--- a/QTfrontend/ui/page/pagefeedback.h	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/ui/page/pagefeedback.h	Fri Jan 04 21:44:40 2013 +0400
@@ -34,6 +34,8 @@
         void LoadCaptchaImage();
 
         QPushButton * BtnSend;
+        QPushButton * BtnViewInfo;
+        QCheckBox * CheckSendSpecs;
         QLineEdit * summary;
         QTextBrowser * description;
         QLabel * info;
@@ -45,12 +47,15 @@
         QLineEdit * captcha_code;
         QLineEdit * email;
         int captchaID;
+        QString specs;
         
     private slots:
     
         virtual void NetReply(QNetworkReply*);
+        virtual void ShowSpecs();
 
     private:
+        void GenerateSpecs();
         QLayout * bodyLayoutDefinition();
         QLayout * footerLayoutDefinition();
         QNetworkAccessManager * GetNetManager();
--- a/QTfrontend/ui/page/pagemain.cpp	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/ui/page/pagemain.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -21,6 +21,7 @@
 #include <QPushButton>
 #include <QLabel>
 #include <QTime>
+#include <QTextStream>
 
 #include "pagemain.h"
 #include "hwconsts.h"
@@ -46,10 +47,35 @@
     BtnSinglePlayer->setWhatsThis(tr("Play a game on a single computer"));
     pageLayout->setAlignment(BtnSinglePlayer, Qt::AlignHCenter);
 
+    //BtnNet = addButton(":/res/NetworkPlay.png", (QBoxLayout*)netLayout, 1, true);
     BtnNet = addButton(":/res/NetworkPlay.png", pageLayout, 2, 2, 1, 2, true);
     BtnNet->setToolTip(tr("Network Game"));
     BtnNet->setWhatsThis(tr("Play a game across a network"));
     pageLayout->setAlignment(BtnNet, Qt::AlignHCenter);
+    connect(BtnNet, SIGNAL(clicked()), this, SLOT(toggleNetworkChoice()));
+    
+    originalNetworkIcon = BtnNet->icon();
+    disabledNetworkIcon = QIcon(":/res/NetworkPlayDisabled.png");
+
+    //QWidget *netLayoutWidget = new QWidget();
+    QVBoxLayout *netLayout = new QVBoxLayout(BtnNet);
+    //pageLayout->addWidget(netLayoutWidget, 2, 2, 1, 2);
+    //netLayoutWidget->setStyleSheet("background: green;");
+    //netLayoutWidget->setFixedSize(314, 260);
+    netLayout->setSpacing(20);
+    netLayout->setAlignment(Qt::AlignHCenter);
+
+    BtnNetLocal = addButton("Play local network game", (QBoxLayout*)netLayout, 0, false);
+    BtnNetLocal->setToolTip(tr("Play a local network game"));
+    BtnNetLocal->setWhatsThis(tr("Play a game across a local area network"));
+    BtnNetLocal->setFixedSize(BtnNet->width() - 50, 60);
+    BtnNetLocal->setVisible(false);
+
+    BtnNetOfficial = addButton("Play official network game", (QBoxLayout*)netLayout, 0, false);
+    BtnNetOfficial->setToolTip(tr("Play a network game"));
+    BtnNetOfficial->setWhatsThis(tr("Play a game on an official server"));
+    BtnNetOfficial->setFixedSize(BtnNet->width() - 50, 60);
+    BtnNetOfficial->setVisible(false);
 
     // button order matters for overlapping (what's on top and what isn't)
     BtnInfo = addButton(":/res/HedgewarsTitle.png", pageLayout, 0, 0, 1, 4, true);
@@ -124,63 +150,49 @@
 
 QString PageMain::randomTip() const
 {
+#ifdef _WIN32
+    int platform = 1;
+#elif defined __APPLE__
+    int platform = 2;
+#else
+    int platform = 3;
+#endif
     QStringList Tips;
-    Tips << tr("Simply pick the same color as a friend to play together as a team. Each of you will still control his or her own hedgehogs but they'll win or lose together.", "Tips");
-    Tips << tr("Some weapons might do only low damage but they can be a lot more devastating in the right situation. Try to use the Desert Eagle to knock multiple hedgehogs into the water.", "Tips");
-    Tips << tr("If you're unsure what to do and don't want to waste ammo, skip one round. But don't let too much time pass as there will be Sudden Death!", "Tips");
-    Tips << tr("Want to save ropes? Release the rope in mid air and then shoot again. As long as you don't touch the ground you'll reuse your rope without wasting ammo!", "Tips");
-    Tips << tr("If you'd like to keep others from using your preferred nickname on the official server, register an account at http://www.hedgewars.org/.", "Tips");
-    Tips << tr("You're bored of default gameplay? Try one of the missions - they'll offer different gameplay depending on the one you picked.", "Tips");
-    Tips << tr("By default the game will always record the last game played as a demo. Select 'Local Game' and pick the 'Demos' button on the lower right corner to play or manage them.", "Tips");
-    Tips << tr("Hedgewars is Open Source and Freeware we create in our spare time. If you've got problems, ask on our forums but please don't expect 24/7 support!", "Tips");
-    Tips << tr("Hedgewars is Open Source and Freeware we create in our spare time. If you like it, help us with a small donation or contribute your own work!", "Tips");
-    Tips << tr("Hedgewars is Open Source and Freeware we create in our spare time. Share it with your family and friends as you like!", "Tips");
-    Tips << tr("Hedgewars is Open Source and Freeware we create in our spare time. If someone sold you the game, you should try get a refund!", "Tips");
-    Tips << tr("From time to time there will be official tournaments. Upcoming events will be announced at http://www.hedgewars.org/ some days in advance.", "Tips");
-    Tips << tr("Hedgewars is available in many languages. If the translation in your language seems to be missing or outdated, feel free to contact us!", "Tips");
-    Tips << tr("Hedgewars can be run on lots of different operating systems including Microsoft Windows, Mac OS X and Linux.", "Tips");
-    Tips << tr("Always remember you're able to set up your own games in local and network/online play. You're not restricted to the 'Simple Game' option.", "Tips");
-    Tips << tr("Connect one or more gamepads before starting the game to be able to assign their controls to your teams.", "Tips");
-    Tips << tr("Create an account on %1 to keep others from using your most favourite nickname while playing on the official server.", "Tips").arg("<a href=\"http://www.hedgewars.org/\">http://www.hedgewars.org/</a>");
-    Tips << tr("While playing you should give yourself a short break at least once an hour.", "Tips");
-    Tips << tr("If your graphics card isn't able to provide hardware accelerated OpenGL, try to enable the low quality mode to improve performance.", "Tips");
-    Tips << tr("If your graphics card isn't able to provide hardware accelerated OpenGL, try to update the associated drivers.", "Tips");
-    Tips << tr("We're open to suggestions and constructive feedback. If you don't like something or got a great idea, let us know!", "Tips");
-    Tips << tr("Especially while playing online be polite and always remember there might be some minors playing with or against you as well!", "Tips");
-    Tips << tr("Special game modes such as 'Vampirism' or 'Karma' allow you to develop completely new tactics. Try them in a custom game!", "Tips");
-    Tips << tr("The Windows version of Hedgewars supports Xfire. Make sure to add Hedgewars to its game list so your friends can see you playing.", "Tips");
-    Tips << tr("You should never install Hedgewars on computers you don't own (school, university, work, etc.). Please ask the responsible person instead!", "Tips");
-    Tips << tr("Hedgewars can be perfect for short games during breaks. Just ensure you don't add too many hedgehogs or use an huge map. Reducing time and health might help as well.", "Tips");
-    Tips << tr("No hedgehogs were harmed in making this game.", "Tips");
-    Tips << tr("There are three different jumps available. Tap [high jump] twice to do a very high/backwards jump.", "Tips");
-    Tips << tr("Afraid of falling off a cliff? Hold down [precise] to turn [left] or [right] without actually moving.", "Tips");
-    Tips << tr("Some weapons require special strategies or just lots of training, so don't give up on a particular tool if you miss an enemy once.", "Tips");
-    Tips << tr("Most weapons won't work once they touch the water. The Homing Bee as well as the Cake are exceptions to this.", "Tips");
-    Tips << tr("The Old Limbuger only causes a small explosion. However the wind affected smelly cloud can poison lots of hogs at once.", "Tips");
-    Tips << tr("The Piano Strike is the most damaging air strike. You'll lose the hedgehog performing it, so there's a huge downside as well.", "Tips");
-    Tips << tr("The Homing Bee can be tricky to use. Its turn radius depends on its velocity, so try to not use full power.", "Tips");
-    Tips << tr("Sticky Mines are a perfect tool to create small chain reactions knocking enemy hedgehogs into dire situations ... or water.", "Tips");
-    Tips << tr("The Hammer is most effective when used on bridges or girders. Hit hogs will just break through the ground.", "Tips");
-    Tips << tr("If you're stuck behind an enemy hedgehog, use the Hammer to free yourself without getting damaged by an explosion.", "Tips");
-    Tips << tr("The Cake's maximum walking distance depends on the ground it has to pass. Use [attack] to detonate it early.", "Tips");
-    Tips << tr("The Flame Thrower is a weapon but it can be used for tunnel digging as well.", "Tips");
-    Tips << tr("Use the Molotov or Flame Thrower to temporary keep hedgehogs from passing terrain such as tunnels or platforms.", "Tips");
-    Tips << tr("Want to know who's behind the game? Click on the Hedgewars logo in the main menu to see the credits.", "Tips");
-    Tips << tr("Like Hedgewars? Become a fan on %1 or follow us on %2!", "Tips").arg("<a href=\"http://www.facebook.com/Hedgewars\">Facebook</a>").arg("<a href=\"http://twitter.com/hedgewars\">Twitter</a>");
-    Tips << tr("Feel free to draw your own graves, hats, flags or even maps and themes! But note that you'll have to share them somewhere to use them online.", "Tips");
-    Tips << tr("Really want to wear a specific hat? Donate to us and receive an exclusive hat of your choice!", "Tips");
+    QFile file(":/res/xml/tips.xml");
+    file.open(QIODevice::ReadOnly);
+    QTextStream in(&file);
+    QString line = in.readLine();
+    int tip_platform = 0;
+    while (!line.isNull()) {
+        if(line.contains("<windows-only>", Qt::CaseSensitive))
+            tip_platform = 1;
+        if(line.contains("<mac-only>", Qt::CaseSensitive))
+            tip_platform = 2;
+        if(line.contains("<linux-only>", Qt::CaseSensitive))
+            tip_platform = 3;
+        if(line.contains("</windows-only>", Qt::CaseSensitive) || 
+                line.contains("</mac-only>", Qt::CaseSensitive) || 
+                line.contains("</linux-only>", Qt::CaseSensitive)) {
+            tip_platform = 0;
+        }
+        QStringList split_string = line.split(QRegExp("</?tip>"));
+        if((tip_platform == platform || tip_platform == 0) && split_string.size() != 1)
+            Tips << tr(split_string[1].toLatin1().data(), "Tips");
+        line = in.readLine();
+    }
     // The following tip will require links to app store entries first.
     //Tips << tr("Want to play Hedgewars any time? Grab the Mobile version for %1 and %2.", "Tips").arg("").arg("");
     // the ios version is located here: http://itunes.apple.com/us/app/hedgewars/id391234866
-    Tips << tr("Keep your video card drivers up to date to avoid issues playing the game.", "Tips");
-    Tips << tr("You're able to associate Hedgewars related files (savegames and demo recordings) with the game to launch them right from your favorite file or internet browser.", "Tips");
-#ifdef _WIN32
-    Tips << tr("You can find your Hedgewars configuration files under \"My Documents\\Hedgewars\". Create backups or take the files with you, but don't edit them by hand.", "Tips");
-#elif defined __APPLE__
-    Tips << tr("You can find your Hedgewars configuration files under \"Library/Application Support/Hedgewars\" in your home directory. Create backups or take the files with you, but don't edit them by hand.", "Tips");
-#else
-    Tips << tr("You can find your Hedgewars configuration files under \".hedgewars\" in your home directory. Create backups or take the files with you, but don't edit them by hand.", "Tips");
-#endif
 
+    file.close();
     return Tips[QTime(0, 0, 0).secsTo(QTime::currentTime()) % Tips.length()];
 }
+
+void PageMain::toggleNetworkChoice()
+{
+    bool visible = BtnNetLocal->isVisible();
+    BtnNetLocal->setVisible(!visible);
+    BtnNetOfficial->setVisible(!visible);
+    if (visible)    BtnNet->setIcon(originalNetworkIcon);
+    else            BtnNet->setIcon(disabledNetworkIcon);
+}
--- a/QTfrontend/ui/page/pagemain.h	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/ui/page/pagemain.h	Fri Jan 04 21:44:40 2013 +0400
@@ -21,15 +21,19 @@
 
 #include "AbstractPage.h"
 
+class QIcon;
+
 class PageMain : public AbstractPage
 {
-        Q_OBJECT
+    Q_OBJECT
 
     public:
         PageMain(QWidget * parent = 0);
 
         QPushButton * BtnSinglePlayer;
         QPushButton * BtnNet;
+        QPushButton * BtnNetLocal;
+        QPushButton * BtnNetOfficial;
         QPushButton * BtnSetup;
         QPushButton * BtnFeedback;
         QPushButton * BtnInfo;
@@ -41,8 +45,12 @@
         QLayout * bodyLayoutDefinition();
         QLayout * footerLayoutDefinition();
         void connectSignals();
+        QIcon originalNetworkIcon, disabledNetworkIcon;
 
         QString randomTip() const;
+
+    private slots:
+        void toggleNetworkChoice();
 };
 
 #endif
--- a/QTfrontend/ui/page/pagenettype.cpp	Tue Dec 18 20:48:37 2012 +0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
- *
- * 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; version 2 of the License
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <QGridLayout>
-#include <QPushButton>
-
-#include "pagenettype.h"
-
-
-QLayout * PageNetType::bodyLayoutDefinition()
-{
-    QGridLayout * pageLayout = new QGridLayout();
-    pageLayout->setRowStretch(0, 10);
-    pageLayout->setRowStretch(3, 10);
-
-    pageLayout->setColumnStretch(1, 10);
-    pageLayout->setColumnStretch(2, 20);
-    pageLayout->setColumnStretch(3, 10);
-
-    BtnLAN = addButton(tr("LAN game"), pageLayout, 1, 2);
-    BtnLAN->setWhatsThis(tr("Join or host your own game server in a Local Area Network."));
-    BtnOfficialServer = addButton(tr("Official server"), pageLayout, 2, 2);
-    BtnOfficialServer->setWhatsThis(tr("Join hundreds of players online!"));
-
-    // hack: temporary deactivated - requires server modifications that aren't backward compatible (yet)
-    //BtnOfficialServer->setEnabled(false);
-
-    return pageLayout;
-}
-
-PageNetType::PageNetType(QWidget* parent) : AbstractPage(parent)
-{
-    initPage();
-}
--- a/QTfrontend/ui/page/pagenettype.h	Tue Dec 18 20:48:37 2012 +0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
- *
- * 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; version 2 of the License
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef PAGE_NETTYPE_H
-#define PAGE_NETTYPE_H
-
-#include "AbstractPage.h"
-
-class PageNetType : public AbstractPage
-{
-        Q_OBJECT
-
-    public:
-        PageNetType(QWidget* parent = 0);
-
-        QPushButton * BtnLAN;
-        QPushButton * BtnOfficialServer;
-
-    protected:
-        QLayout * bodyLayoutDefinition();
-};
-
-#endif
--- a/QTfrontend/ui/page/pageoptions.cpp	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/ui/page/pageoptions.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -23,14 +23,17 @@
 #include <QComboBox>
 #include <QCheckBox>
 #include <QLabel>
+#include <QTableWidget>
 #include <QLineEdit>
 #include <QSpinBox>
 #include <QTextBrowser>
-#include <QTableWidget>
+#include <QScrollArea>
+#include <QHeaderView>
 #include <QSlider>
 #include <QSignalMapper>
 #include <QColorDialog>
 #include <QStandardItemModel>
+#include <QDebug>
 
 #include "pageoptions.h"
 #include "gameuiconfig.h"
@@ -40,6 +43,8 @@
 #include "DataManager.h"
 #include "LibavInteraction.h"
 #include "AutoUpdater.h"
+#include "HWApplication.h"
+#include "keybinder.h"
 
 #ifdef __APPLE__
 #ifdef SPARKLE_ENABLED
@@ -56,9 +61,15 @@
     pageLayout->addWidget(tabs);
     QWidget * page1 = new QWidget(this);
     QWidget * page2 = new QWidget(this);
+    binder = new KeyBinder(this, tr("Select an action to change what key controls it"), tr("Reset to default"), tr("Reset all binds"));
+    connect(binder, SIGNAL(bindUpdate(int)), this, SLOT(bindUpdated(int)));
+    connect(binder, SIGNAL(resetAllBinds()), this, SLOT(resetAllBinds()));
     tabs->addTab(page1, tr("General"));
+    binderTab = tabs->addTab(binder, tr("Controls"));
     tabs->addTab(page2, tr("Advanced"));
 
+    connect(tabs, SIGNAL(currentChanged(int)), this, SLOT(tabIndexChanged(int)));
+
 #ifdef VIDEOREC
     QWidget * page3 = new QWidget(this);
     tabs->addTab(page3, tr("Video Recording"));
@@ -260,7 +271,9 @@
 
             QVBoxLayout * GBAlayout = new QVBoxLayout(AGGroupBox);
             QGridLayout * GBAfrontendlayout = new QGridLayout(0);
-            QHBoxLayout * GBAreslayout = new QHBoxLayout(0);
+            QGridLayout * GBAreslayout = new QGridLayout(0);
+            QHBoxLayout * GBAfslayout = new QHBoxLayout(0);
+            QVBoxLayout * GBArescolumn = new QVBoxLayout(0);
             QHBoxLayout * GBAstereolayout = new QHBoxLayout(0);
             QHBoxLayout * GBAqualayout = new QHBoxLayout(0);
 
@@ -293,18 +306,43 @@
             hr->setFixedHeight(10);
             GBAlayout->addWidget(hr);
 
-            QLabel * resolution = new QLabel(AGGroupBox);
-            resolution->setText(QLabel::tr("Resolution"));
-            GBAreslayout->addWidget(resolution);
-
+            CBFullscreen = new QCheckBox(AGGroupBox);
+            GBAreslayout->addWidget(CBFullscreen, 0, 0);
+            CBFullscreen->setText(QLabel::tr("Fullscreen"));
+                        
             CBResolution = new QComboBox(AGGroupBox);
-            GBAreslayout->addWidget(CBResolution);
+            GBArescolumn->addWidget(CBResolution);
+            
+            QLabel * fullscreenResolution = new QLabel(AGGroupBox);
+            fullscreenResolution->setText(QLabel::tr("Fullscreen Resolution"));
+            GBAreslayout->addWidget(fullscreenResolution,1, 0);
+            
+            QLabel * windowedResolution = new QLabel(AGGroupBox);
+            windowedResolution->setText(QLabel::tr("Windowed Resolution"));
+            GBAreslayout->addWidget(windowedResolution, 2, 0);
+            
+            // decorational X
+            QLabel *winLabelX = new QLabel(AGGroupBox);
+            winLabelX->setText("X");
+            
+            windowWidthEdit = new QLineEdit(AGGroupBox);
+            windowWidthEdit->setValidator(new QIntValidator(this));
+            windowHeightEdit = new QLineEdit(AGGroupBox);
+            windowHeightEdit->setValidator(new QIntValidator(this));
+            
+            GBAfslayout->addWidget(windowWidthEdit);
+            GBAfslayout->addWidget(winLabelX);
+            GBAfslayout->addWidget(windowHeightEdit);
+            
+            GBAfslayout->setAlignment(windowHeightEdit, Qt::AlignRight);
+            GBAfslayout->setAlignment(windowWidthEdit, Qt::AlignRight);
+            GBAfslayout->setAlignment(winLabelX, Qt::AlignRight);
+            GBArescolumn->addLayout(GBAfslayout);
+            GBAreslayout->addLayout(GBArescolumn, 1, 1, 2, 1);
+            GBAreslayout->setAlignment(GBArescolumn, Qt::AlignRight);
+            
             GBAlayout->addLayout(GBAreslayout);
-
-            CBFullscreen = new QCheckBox(AGGroupBox);
-            CBFullscreen->setText(QCheckBox::tr("Fullscreen"));
-            GBAreslayout->addWidget(CBFullscreen);
-
+            
             QLabel * quality = new QLabel(AGGroupBox);
             quality->setText(QLabel::tr("Quality"));
             quality->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
@@ -330,15 +368,14 @@
             CBStereoMode->addItem(QComboBox::tr("Blue/Red"));
             CBStereoMode->addItem(QComboBox::tr("Red/Green"));
             CBStereoMode->addItem(QComboBox::tr("Green/Red"));
-            CBStereoMode->addItem(QComboBox::tr("Side-by-side"));
-            CBStereoMode->addItem(QComboBox::tr("Top-Bottom"));
-            CBStereoMode->addItem(QComboBox::tr("Wiggle"));
             CBStereoMode->addItem(QComboBox::tr("Red/Cyan grayscale"));
             CBStereoMode->addItem(QComboBox::tr("Cyan/Red grayscale"));
             CBStereoMode->addItem(QComboBox::tr("Red/Blue grayscale"));
             CBStereoMode->addItem(QComboBox::tr("Blue/Red grayscale"));
             CBStereoMode->addItem(QComboBox::tr("Red/Green grayscale"));
             CBStereoMode->addItem(QComboBox::tr("Green/Red grayscale"));
+            CBStereoMode->addItem(QComboBox::tr("Side-by-side"));
+            CBStereoMode->addItem(QComboBox::tr("Top-Bottom"));
 
             GBAstereolayout->addWidget(CBStereoMode);
             GBAlayout->addLayout(GBAstereolayout);
@@ -627,7 +664,7 @@
     previousQuality = this->SLQuality->value();
     previousResolutionIndex = this->CBResolution->currentIndex();
     previousFullscreenValue = this->CBFullscreen->isChecked();
-
+    // mutually exclude window and fullscreen resolution
     return pageLayout;
 }
 
@@ -661,19 +698,17 @@
 void PageOptions::forceFullscreen(int index)
 {
     bool forced = (index == 7 || index == 8 || index == 9);
-
+    
     if (index != 0)
     {
         this->SLQuality->setValue(this->SLQuality->maximum());
         this->SLQuality->setEnabled(false);
-        this->CBFullscreen->setEnabled(!forced);
         this->CBFullscreen->setChecked(forced ? true : previousFullscreenValue);
         this->CBResolution->setCurrentIndex(forced ? 0 : previousResolutionIndex);
     }
     else
     {
         this->SLQuality->setEnabled(true);
-        this->CBFullscreen->setEnabled(true);
         this->SLQuality->setValue(previousQuality);
         this->CBFullscreen->setChecked(previousFullscreenValue);
         this->CBResolution->setCurrentIndex(previousResolutionIndex);
@@ -693,6 +728,7 @@
 {
     Q_UNUSED(state);
 
+    
     int index = this->CBStereoMode->currentIndex();
     if (index != 7 && index != 8 && index != 9)
         previousFullscreenValue = this->CBFullscreen->isChecked();
@@ -914,3 +950,57 @@
 
     return true;
 }
+
+// When the current tab is switched
+void PageOptions::tabIndexChanged(int index)
+{
+    if (index == binderTab) // Switched to bind tab
+    {
+        binder->resetInterface();
+
+        if (!config) return;
+
+        QStandardItemModel * binds = DataManager::instance().bindsModel();
+        for(int i = 0; i < BINDS_NUMBER; i++)
+        {
+            QString value = config->bind(i);
+            QModelIndexList mdl = binds->match(binds->index(0, 0), Qt::UserRole + 1, value, 1, Qt::MatchExactly);
+            if(mdl.size() == 1) binder->setBindIndex(i, mdl[0].row());
+        }
+    }
+
+    currentTab = index;
+}
+
+// When a key bind combobox is changed
+void PageOptions::bindUpdated(int bindID)
+{
+    int bindIndex = binder->bindIndex(bindID);
+    
+    if (bindIndex == 0) bindIndex = resetBindToDefault(bindID);
+
+    // Save bind
+    QStandardItemModel * binds = DataManager::instance().bindsModel();
+    QString strbind = binds->index(binder->bindIndex(bindID), 0).data(Qt::UserRole + 1).toString();
+    config->setBind(bindID, strbind);
+}
+
+// Changes a key bind (bindID) to its default value. This updates the bind's combo-box in the UI.
+// Returns: The bind model index of the default.
+int PageOptions::resetBindToDefault(int bindID)
+{
+    QStandardItemModel * binds = DataManager::instance().bindsModel();
+    QModelIndexList mdl = binds->match(binds->index(0, 0), Qt::UserRole + 1, cbinds[bindID].strbind, 1, Qt::MatchExactly);
+    if(mdl.size() == 1) binder->setBindIndex(bindID, mdl[0].row());
+    return mdl[0].row();
+}
+
+// Called when "reset all binds" button is pressed
+void PageOptions::resetAllBinds()
+{
+    for (int i = 0; i < BINDS_NUMBER; i++)
+    {
+        resetBindToDefault(i);
+        bindUpdated(i);
+    }
+}
--- a/QTfrontend/ui/page/pageoptions.h	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/ui/page/pageoptions.h	Fri Jan 04 21:44:40 2013 +0400
@@ -25,6 +25,7 @@
 class FPSEdit;
 class IconedGroupBox;
 class QSignalMapper;
+class KeyBinder;
 
 class PageOptions : public AbstractPage
 {
@@ -57,6 +58,8 @@
         QComboBox *CBTeamName;
         IconedGroupBox *AGGroupBox;
         QComboBox *CBResolution;
+        QLineEdit *windowWidthEdit;
+        QLineEdit *windowHeightEdit;
         QComboBox *CBStereoMode;
         QCheckBox *CBFrontendSound;
         QCheckBox *CBFrontendMusic;
@@ -118,6 +121,7 @@
         QLayout * bodyLayoutDefinition();
         QLayout * footerLayoutDefinition();
         void connectSignals();
+        int resetBindToDefault(int bindID);
 
         bool previousFullscreenValue;
         int previousResolutionIndex;
@@ -134,6 +138,9 @@
         QPushButton *btnDefaults;
         QPushButton *btnUpdateNow;
         GameUIConfig * config;
+        KeyBinder * binder;
+        int currentTab;
+        int binderTab;
 
     private slots:
         void forceFullscreen(int index);
@@ -151,6 +158,9 @@
         void changeUseGameRes(int state);
         void changeRecordAudio(int state);
         void checkForUpdates();
+        void tabIndexChanged(int);
+        void bindUpdated(int bindID);
+        void resetAllBinds();
 
     public slots:
         void setDefaultOptions();
--- a/QTfrontend/ui/page/pagevideos.cpp	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/ui/page/pagevideos.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -177,8 +177,9 @@
                                            Qt::LinksAccessibleByMouse |
                                            Qt::LinksAccessibleByKeyboard);
         labelDesc->setTextFormat(Qt::RichText);
+        labelDesc->setWordWrap(true);
         labelDesc->setOpenExternalLinks(true);
-        labelDesc->setMinimumSize(ThumbnailSize);
+        //labelDesc->setMinimumSize(ThumbnailSize);
         //pTopDescLayout->addWidget(labelDesc, 1);
 
         // buttons: play and delete
@@ -195,12 +196,10 @@
         btnToYouTube->setWhatsThis(QPushButton::tr("Upload this video to your Youtube account"));
         pBottomDescLayout->addWidget(btnToYouTube);
 
-        pDescLayout->addStretch(1);
         pDescLayout->addWidget(labelThumbnail, 0);
+        pDescLayout->addWidget(labelDesc, 0);
+        pDescLayout->addLayout(pBottomDescLayout, 0);
         pDescLayout->addStretch(1);
-        pDescLayout->addWidget(labelDesc, 0);
-        pDescLayout->addStretch(1);
-        pDescLayout->addLayout(pBottomDescLayout, 0);
 
         pPageLayout->addWidget(pDescGroup, 0, 0);
     }
@@ -509,8 +508,8 @@
     else
     {
         QString path = item->path();
-        desc += tr("Date: ") + QFileInfo(path).created().toString(Qt::DefaultLocaleLongDate) + '\n';
-        desc += tr("Size: ") + FileSizeStr(path) + '\n';
+        desc += tr("Date: %1\n").arg(QFileInfo(path).created().toString(Qt::DefaultLocaleLongDate));
+        desc += tr("Size: %1\n").arg(FileSizeStr(path));
         if (item->desc.isEmpty())
         {
             // Extract description from file;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/keybinder.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -0,0 +1,301 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * 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; version 2 of the License
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "keybinder.h"
+#include "HWApplication.h"
+#include "DataManager.h"
+#include <QHBoxLayout>
+#include <QScrollArea>
+#include <QTableWidget>
+#include <QTableWidgetItem>
+#include <QStandardItemModel>
+#include <QAbstractItemModel>
+#include <QListWidget>
+#include <QListWidgetItem>
+#include <QPushButton>
+#include <QHeaderView>
+#include <QComboBox>
+#include <QLabel>
+#include <QFrame>
+#include <QDebug>
+
+KeyBinder::KeyBinder(QWidget * parent, const QString & helpText, const QString & defaultText, const QString & resetButtonText) : QWidget(parent)
+{
+    this->defaultText = defaultText;
+    enableSignal = false;
+    
+    // Two-column tab layout
+    QHBoxLayout * pageKeysLayout = new QHBoxLayout(this);
+    pageKeysLayout->setSpacing(0);
+    pageKeysLayout->setContentsMargins(0, 0, 0, 0);
+    
+    // Table for category list
+    QVBoxLayout * catListContainer = new QVBoxLayout();
+    catListContainer->setContentsMargins(10, 10, 10, 10);
+    catList = new QListWidget();
+    catList->setFixedWidth(180);
+    catList->setStyleSheet("QListWidget::item { font-size: 14px; } QListWidget:hover { border-color: #F6CB1C; } QListWidget::item:selected { background: #150A61; color: yellow; }");
+    catList->setFocusPolicy(Qt::NoFocus);
+    connect(catList, SIGNAL(currentRowChanged(int)), this, SLOT(changeBindingsPage(int)));
+    catListContainer->addWidget(catList);
+    pageKeysLayout->addLayout(catListContainer);
+
+    // Reset all binds button
+    if (!resetButtonText.isEmpty())
+    {
+        QPushButton * btnResetAll = new QPushButton(resetButtonText);
+        catListContainer->addWidget(btnResetAll);
+        btnResetAll->setFixedHeight(40);
+        catListContainer->setStretch(1, 0);
+        catListContainer->setSpacing(10);
+        connect(btnResetAll, SIGNAL(clicked()), this, SIGNAL(resetAllBinds()));
+    }
+
+    // Container for pages of key bindings
+    QWidget * bindingsPagesContainer = new QWidget();
+    QVBoxLayout * rightLayout = new QVBoxLayout(bindingsPagesContainer);
+
+    // Scroll area for key bindings
+    QScrollArea * scrollArea = new QScrollArea();
+    scrollArea->setContentsMargins(0, 0, 0, 0);
+    scrollArea->setWidget(bindingsPagesContainer);
+    scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+    scrollArea->setWidgetResizable(true);
+    scrollArea->setFrameShape(QFrame::NoFrame);
+    scrollArea->setStyleSheet("background: #130F2A;");
+
+    // Add key binding pages to bindings tab
+    pageKeysLayout->addWidget(scrollArea);
+    pageKeysLayout->setStretch(1, 1);
+
+    // Custom help text
+    QLabel * helpLabel = new QLabel();
+    helpLabel->setText(helpText);
+    helpLabel->setStyleSheet("color: #130F2A; background: #F6CB1C; border: solid 4px #F6CB1C; border-radius: 10px; padding: auto 20px;");
+    helpLabel->setFixedHeight(24);
+    rightLayout->addWidget(helpLabel, 0, Qt::AlignCenter);
+
+    // Category list and bind table row heights
+    const int rowHeight = 20;
+    QSize catSize, headerSize;
+    catSize.setHeight(36);
+    headerSize.setHeight(24);
+
+    // Category list header
+    QListWidgetItem * catListHeader = new QListWidgetItem(tr("Category"));
+    catListHeader->setSizeHint(headerSize);
+    catListHeader->setFlags(Qt::NoItemFlags);
+    catListHeader->setForeground(QBrush(QColor("#130F2A")));
+    catListHeader->setBackground(QBrush(QColor("#F6CB1C")));
+    catListHeader->setTextAlignment(Qt::AlignCenter);
+    catList->addItem(catListHeader);
+
+    // Populate
+    bindingsPages = new QHBoxLayout();
+    bindingsPages->setContentsMargins(0, 0, 0, 0);
+    rightLayout->addLayout(bindingsPages);
+    QWidget * curPage = NULL;
+    QVBoxLayout * curLayout = NULL;
+    QTableWidget * curTable = NULL;
+    bool bFirstPage = true;
+    selectedBindTable = NULL;
+    bindComboBoxCellMappings = new QHash<QObject *, QTableWidgetItem *>();
+    bindCellComboBoxMappings = new QHash<QTableWidgetItem *, QComboBox *>();
+    for (int i = 0; i < BINDS_NUMBER; i++)
+    {
+        if (cbinds[i].category != NULL)
+        {
+            // Add stretch at end of previous layout
+            if (curLayout != NULL) curLayout->insertStretch(-1, 1);
+            
+            // Category list item
+            QListWidgetItem * catItem = new QListWidgetItem(HWApplication::translate("binds (categories)", cbinds[i].category));
+            catItem->setSizeHint(catSize);
+            catList->addItem(catItem);
+            
+            // Create new page
+            curPage = new QWidget();
+            curLayout = new QVBoxLayout(curPage);
+            curLayout->setSpacing(2);
+            bindingsPages->addWidget(curPage);
+            if (!bFirstPage) curPage->setVisible(false);
+        }
+
+        // Description
+        if (cbinds[i].description != NULL)
+        {
+            QLabel * desc = new QLabel(HWApplication::translate("binds (descriptions)", cbinds[i].description));
+            curLayout->addWidget(desc, 0);
+            QFrame * divider = new QFrame();
+            divider->setFrameShape(QFrame::HLine);
+            divider->setFrameShadow(QFrame::Plain);
+            curLayout->addWidget(divider, 0);
+        }
+
+        // New table
+        if (cbinds[i].category != NULL || cbinds[i].description != NULL)
+        {
+            curTable = new QTableWidget(0, 2);
+            curTable->verticalHeader()->setVisible(false);
+            curTable->horizontalHeader()->setVisible(false);
+            curTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
+            curTable->verticalHeader()->setDefaultSectionSize(rowHeight);
+            curTable->setShowGrid(false);
+            curTable->setStyleSheet("QTableWidget { border: none; } ");
+            curTable->setSelectionBehavior(QAbstractItemView::SelectRows);
+            curTable->setSelectionMode(QAbstractItemView::SingleSelection);
+            curTable->setFocusPolicy(Qt::NoFocus);
+            connect(curTable, SIGNAL(itemSelectionChanged()), this, SLOT(bindSelectionChanged()));
+            connect(curTable, SIGNAL(itemClicked(QTableWidgetItem *)), this, SLOT(bindCellClicked(QTableWidgetItem *)));
+            curLayout->addWidget(curTable, 0);
+        }
+
+        // Hidden combo box
+        QComboBox * comboBox = CBBind[i] = new QComboBox(curTable);
+        comboBox->setModel((QAbstractItemModel*)DataManager::instance().bindsModel());
+        comboBox->setVisible(false);
+        comboBox->setFixedWidth(200);
+        
+        // Table row
+        int row = curTable->rowCount();
+        QTableWidgetItem * nameCell = new QTableWidgetItem(HWApplication::translate("binds", cbinds[i].name));
+        nameCell->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
+        curTable->insertRow(row);
+        curTable->setItem(row, 0, nameCell);
+        QTableWidgetItem * bindCell = new QTableWidgetItem(comboBox->currentText());
+        bindCell->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
+        curTable->setItem(row, 1, bindCell);
+        curTable->resizeColumnsToContents();
+        curTable->setFixedHeight(curTable->verticalHeader()->length() + 10);
+
+        // Updates the text in the table cell
+        connect(comboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(bindChanged(const QString &)));
+
+        // Map combo box and that row's cells to each other
+        bindComboBoxCellMappings->insert(comboBox, bindCell);
+        bindCellComboBoxMappings->insert(nameCell, comboBox);
+        bindCellComboBoxMappings->insert(bindCell, comboBox);
+    }
+
+    // Add stretch at end of last layout
+    if (curLayout != NULL) curLayout->insertStretch(-1, 1);
+
+    // Go to first page
+    catList->setCurrentItem(catList->item(1));
+
+    enableSignal = true;
+}
+
+KeyBinder::~KeyBinder()
+{
+    delete bindComboBoxCellMappings;
+    delete bindCellComboBoxMappings;
+}
+
+// Switches between different pages of key binds
+void KeyBinder::changeBindingsPage(int page)
+{
+    page--; // Disregard first item (the list header)
+    int pages = bindingsPages->count();
+    for (int i = 0; i < pages; i++)
+        bindingsPages->itemAt(i)->widget()->setVisible(false);
+    bindingsPages->itemAt(page)->widget()->setVisible(true);
+}
+
+// When a key bind combobox value is changed, updates the table cell text
+void KeyBinder::bindChanged(const QString & text)
+{
+    bindComboBoxCellMappings->value(sender())->setText(text);
+
+    if (enableSignal)
+    {
+        for (int i = 0; i < BINDS_NUMBER; i++)
+        {
+            if (CBBind[i] == sender())
+            {
+                emit bindUpdate(i);
+                break;
+            }
+        }
+    }
+}
+
+// When a row in a key bind table is clicked, this shows the popup
+void KeyBinder::bindCellClicked(QTableWidgetItem * item)
+{
+    QComboBox * box = bindCellComboBoxMappings->value(item);
+    QTableWidget * table = item->tableWidget();
+    QFrame * frame = box->findChild<QFrame*>();
+    
+    box->showPopup();
+    frame->move(
+        frame->x() + table->horizontalHeader()->sectionSize(0),
+        frame->y() + (table->verticalHeader()->defaultSectionSize() * item->row())
+    );
+}
+
+// When a new row in a bind table is *selected*, this clears selection in any other table
+void KeyBinder::bindSelectionChanged()
+{
+    QTableWidget * theSender = (QTableWidget*)sender();
+    if (theSender != selectedBindTable)
+    {
+        if (selectedBindTable != NULL)
+            selectedBindTable->clearSelection();
+        selectedBindTable = theSender;
+    }
+}
+
+// Set a combobox's index
+void KeyBinder::setBindIndex(int keyIndex, int bindIndex)
+{
+    enableSignal = false;
+    CBBind[keyIndex]->setCurrentIndex(bindIndex);
+    enableSignal = true;
+}
+
+// Return a combobox's selected index
+int KeyBinder::bindIndex(int keyIndex)
+{
+    return CBBind[keyIndex]->currentIndex();
+}
+
+// Clears selection and goes to first category
+void KeyBinder::resetInterface()
+{
+    enableSignal = false;
+    
+    catList->setCurrentItem(catList->item(1));
+    changeBindingsPage(1);
+    if (selectedBindTable != NULL)
+    {
+        selectedBindTable->clearSelection();
+        selectedBindTable = NULL;
+    }
+    
+    // Default bind text
+    DataManager::instance().bindsModel()->item(0)->setData(defaultText, Qt::DisplayRole);
+    for (int i = 0; i < BINDS_NUMBER; i++)
+    {
+        CBBind[i]->setModel(DataManager::instance().bindsModel());
+        CBBind[i]->setCurrentIndex(0);
+        bindComboBoxCellMappings->value(CBBind[i])->setText(defaultText);
+    }
+
+    enableSignal = true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/keybinder.h	Fri Jan 04 21:44:40 2013 +0400
@@ -0,0 +1,68 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * 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; version 2 of the License
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef _KEY_BINDER_H
+#define _KEY_BINDER_H
+
+#include <QWidget>
+#include <QHash>
+
+#include "binds.h"
+
+class QListWidget;
+class QTableWidgetItem;
+class QTableWidget;
+class QBoxLayout;
+class QComboBox;
+
+// USAGE NOTE: Every time the widget comes into view, you must call resetInterface()
+
+class KeyBinder : public QWidget
+{
+    Q_OBJECT
+
+    public:
+        KeyBinder(QWidget * parent = NULL, const QString & helpText = QString(), const QString & defaultText = QString(), const QString & resetButtonText = QString());
+        ~KeyBinder();
+
+        void setBindIndex(int keyIndex, int bindIndex);
+        int bindIndex(int keyIndex);
+        void resetInterface();
+
+    private:
+        QHash<QObject *, QTableWidgetItem *> * bindComboBoxCellMappings;
+        QHash<QTableWidgetItem *, QComboBox *> * bindCellComboBoxMappings;
+        QTableWidget * selectedBindTable;
+        QListWidget * catList;
+        QBoxLayout *bindingsPages;
+        QComboBox * CBBind[BINDS_NUMBER];
+        QString defaultText;
+        bool enableSignal;
+
+    signals:
+        void bindUpdate(int bindID);
+        void resetAllBinds();
+
+    private slots:
+        void changeBindingsPage(int page);
+        void bindChanged(const QString &);
+        void bindCellClicked(QTableWidgetItem * item);
+        void bindSelectionChanged();
+};
+
+#endif // _KEY_BINDER_H
--- a/QTfrontend/ui/widget/qpushbuttonwithsound.cpp	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/ui/widget/qpushbuttonwithsound.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -33,7 +33,7 @@
 
 void QPushButtonWithSound::buttonClicked()
 {
-    if ( !isSoundEnabled || !HWForm::config->isFrontendSoundEnabled())
+    if ( !isSoundEnabled )
         return;
 
     if (this->isEnabled())
--- a/QTfrontend/ui_hwform.cpp	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/ui_hwform.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -30,7 +30,6 @@
 #include "pagefeedback.h"
 #include "pageingame.h"
 #include "pagescheme.h"
-#include "pagenettype.h"
 #include "pageroomslist.h"
 #include "pageinfo.h"
 #include "pagenetgame.h"
@@ -132,9 +131,6 @@
     pageAdmin = new PageAdmin();
     Pages->addWidget(pageAdmin);
 
-    pageNetType = new PageNetType();
-    Pages->addWidget(pageNetType);
-
     pageCampaign = new PageCampaign();
     Pages->addWidget(pageCampaign);
 
--- a/QTfrontend/ui_hwform.h	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/ui_hwform.h	Fri Jan 04 21:44:40 2013 +0400
@@ -41,7 +41,6 @@
 class PageConnecting;
 class PageScheme;
 class PageAdmin;
-class PageNetType;
 class PageDrawMap;
 class PageVideos;
 class QStackedLayout;
@@ -76,7 +75,6 @@
         PageConnecting *pageConnecting;
         PageScheme *pageScheme;
         PageAdmin *pageAdmin;
-        PageNetType *pageNetType;
         PageCampaign *pageCampaign;
         PageDrawMap *pageDrawMap;
         PageVideos *pageVideos;
--- a/QTfrontend/util/DataManager.cpp	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/util/DataManager.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -135,6 +135,11 @@
     {
         m_bindsModel = new QStandardItemModel();
 
+        QStandardItem * firstItem = new QStandardItem();
+        firstItem->setData(tr("Use Default"), Qt::DisplayRole);
+        firstItem->setData("default", Qt::UserRole + 1);
+        m_bindsModel->appendRow(firstItem);
+
         for(int j = 0; sdlkeys[j][1][0] != '\0'; j++)
         {
             QStandardItem * item = new QStandardItem();
--- a/QTfrontend/util/LibavInteraction.cpp	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/util/LibavInteraction.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -302,7 +302,7 @@
         else
             continue;
         AVCodec* pDecoder = avcodec_find_decoder(pCodec->codec_id);
-        desc += pDecoder? pDecoder->name : "unknown";
+        desc += pDecoder? pDecoder->name : tr("unknown");
         desc += "\n";
     }
     AVDictionaryEntry* pComment = av_dict_get(pContext->metadata, "comment", NULL, 0);
--- a/QTfrontend/util/SDLInteraction.cpp	Tue Dec 18 20:48:37 2012 +0400
+++ b/QTfrontend/util/SDLInteraction.cpp	Fri Jan 04 21:44:40 2013 +0400
@@ -25,6 +25,8 @@
 #include "SDL_mixer.h"
 
 #include "HWApplication.h"
+#include "hwform.h" /* you know, we could just put a config singleton lookup function in gameuiconfig or something... */
+#include "gameuiconfig.h"
 
 #include "SDLInteraction.h"
 
@@ -186,14 +188,16 @@
         return;
 
     SDL_Init(SDL_INIT_AUDIO);
-    Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024);
-    m_audioInitialized = true;
+    if(!Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024)) /* should we keep trying, or just turn off permanently? */
+        m_audioInitialized = true;
 }
 
 
 void SDLInteraction::playSoundFile(const QString & soundFile)
 {
+    if (!HWForm::config || !HWForm::config->isFrontendSoundEnabled()) return;
     SDLAudioInit();
+    if (!m_audioInitialized) return;
     if (!m_soundMap->contains(soundFile))
         m_soundMap->insert(soundFile, Mix_LoadWAV_RW(PHYSFSRWOPS_openRead(soundFile.toLocal8Bit().constData()), 1));
 
@@ -232,6 +236,7 @@
         return;
 
     SDLAudioInit();
+    if (!m_audioInitialized) return;
 
     if (m_music == NULL)
         m_music = Mix_LoadMUS_RW(PHYSFSRWOPS_openRead(m_musicTrack.toLocal8Bit().constData()));
--- a/bin/CMakeLists.txt	Tue Dec 18 20:48:37 2012 +0400
+++ b/bin/CMakeLists.txt	Fri Jan 04 21:44:40 2013 +0400
@@ -5,5 +5,5 @@
 	install(FILES
 		${DLLs}
 		${ICOs}
-		DESTINATION bin)
+		DESTINATION ${target_library_install_dir})
 endif(WIN32 AND NOT UNIX)
--- a/cmake_modules/FindSDL_Extras.cmake	Tue Dec 18 20:48:37 2012 +0400
+++ b/cmake_modules/FindSDL_Extras.cmake	Fri Jan 04 21:44:40 2013 +0400
@@ -13,7 +13,7 @@
 
     if(sdlmixer_version GREATER "10209")
         message(STATUS "Mix_Init() is present")
-        set(pascal_flags "-dSDL_MIXER_NEWER" ${pascal_flags})
+        list(APPEND pascal_flags "-dSDL_MIXER_NEWER")
     endif()
 endif()
 
@@ -30,7 +30,7 @@
 
     if(sdlimage_version GREATER "010207")
         message(STATUS "IMG_Init() is present")
-        set(pascal_flags "-dSDL_IMAGE_NEWER" ${pascal_flags})
+        list(APPEND pascal_flags "-dSDL_IMAGE_NEWER")
     endif()
 endif()
 
--- a/gameServer/CMakeLists.txt	Tue Dec 18 20:48:37 2012 +0400
+++ b/gameServer/CMakeLists.txt	Fri Jan 04 21:44:40 2013 +0400
@@ -42,4 +42,4 @@
 
 add_custom_target(hedgewars-server ALL DEPENDS "${EXECUTABLE_OUTPUT_PATH}/hedgewars-server${CMAKE_EXECUTABLE_SUFFIX}")
 
-install(PROGRAMS "${EXECUTABLE_OUTPUT_PATH}/hedgewars-server${CMAKE_EXECUTABLE_SUFFIX}" DESTINATION ${target_dir})
+install(PROGRAMS "${EXECUTABLE_OUTPUT_PATH}/hedgewars-server${CMAKE_EXECUTABLE_SUFFIX}" DESTINATION ${target_binary_install_dir})
--- a/hedgewars/ArgParsers.inc	Tue Dec 18 20:48:37 2012 +0400
+++ b/hedgewars/ArgParsers.inc	Fri Jan 04 21:44:40 2013 +0400
@@ -16,74 +16,40 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  *)
 
-
-procedure internalStartGameWithParameters();
-var tmp: LongInt;
+procedure GciEasterEgg;
 begin
-    UserPathPrefix:= ParamStr(1);
-    cScreenWidth:= StrToInt(ParamStr(2));
-    cScreenHeight:= StrToInt(ParamStr(3));
-    cBits:= StrToInt(ParamStr(4));
-    ipcPort:= StrToInt(ParamStr(5));
-    cFullScreen:= ParamStr(6) = '1';
-    SetSound(ParamStr(7) = '1');
-    SetMusic(ParamStr(8) = '1');
-    SetVolume(StrToInt(ParamStr(9)));
-    cTimerInterval:= StrToInt(ParamStr(10));
-    PathPrefix:= ParamStr(11);
-    cShowFPS:= ParamStr(12) = '1';
-    cAltDamage:= ParamStr(13) = '1';
-    UserNick:= DecodeBase64(ParamStr(14));
-    cReducedQuality:= StrToInt(ParamStr(15));
-    tmp:= StrToInt(ParamStr(16));
-    GrayScale:= false;
-{$IFDEF USE_S3D_RENDERING}
-    if (tmp > 9) and (tmp < 16) then
-        begin
-        // set the gray anaglyph rendering
-        GrayScale:= true;
-        cStereoMode:= TStereoMode(max(0, min(ord(high(TStereoMode)), tmp-9)))
-        end
-    else if tmp <= 9 then
-        // set the fullcolor anaglyph
-        cStereoMode:= TStereoMode(max(0, min(ord(high(TStereoMode)), tmp)))
-    else
-        // any other mode
-        cStereoMode:= TStereoMode(max(0, min(ord(high(TStereoMode)), tmp-6)));
-{$ELSE}
-	cStereoMode:= smNone;
-{$ENDIF}
-    cLocaleFName:= ParamStr(17);
+    WriteLn(stdout, '                                                                ');
+    WriteLn(stdout, '      /\\\\\\\\\\\\        /\\\\\\\\\  /\\\\\\\\\\\             ');
+    WriteLn(stdout, '     /\\\//////////      /\\\////////  \/////\\\///             ');
+    WriteLn(stdout, '     /\\\               /\\\/               \/\\\               ');
+    WriteLn(stdout, '     \/\\\    /\\\\\\\  /\\\                 \/\\\              ');
+    WriteLn(stdout, '      \/\\\   \/////\\\ \/\\\                 \/\\\             ');
+    WriteLn(stdout, '       \/\\\       \/\\\ \//\\\                \/\\\            ');
+    WriteLn(stdout, '        \/\\\       \/\\\  \///\\\              \/\\\           ');
+    WriteLn(stdout, '         \/\\\\\\\\\\\\\/     \////\\\\\\\\\  /\\\\\\\\\\\      ');
+    WriteLn(stdout, '          \/////////////          \/////////  \///////////      ');
+    WriteLn(stdout, '                                                                ');
+    WriteLn(stdout, ' Command Line Parser Implementation by a Google Code-In Student ');
+    WriteLn(stdout, '             ASCII Art easter egg idea by @sheepluva            ');
+    WriteLn(stdout, '                                                                ');
 end;
 
-{$IFDEF USE_VIDEO_RECORDING}
-procedure internalStartVideoRecordingWithParameters();
-begin
-    internalStartGameWithParameters();
-    GameType:= gmtRecord;
-    cVideoFramerateNum:= StrToInt(ParamStr(18));
-    cVideoFramerateDen:= StrToInt(ParamStr(19));
-    RecPrefix:= ParamStr(20);
-    cAVFormat:= ParamStr(21);
-    cVideoCodec:= ParamStr(22);
-    cVideoQuality:= StrToInt(ParamStr(23));
-    cAudioCodec:= ParamStr(24);
-end;
-{$ENDIF}
-
 procedure DisplayUsage;
 begin
-    WriteLn(stdout, 'Usage:');
-    WriteLn(stdout, '');
-    WriteLn(stdout, '  hwengine <path to global data folder> <path to replay file> [options]');
+    WriteLn(stdout, 'Usage: hwengine <path to replay file> [options]');
     WriteLn(stdout, '');
-    WriteLn(stdout, 'where [options] are any of the following:');
-    WriteLn(stdout, ' --user-dir [path to user data folder]');
+    WriteLn(stdout, 'where [options] can be any of the following:');
+    WriteLn(stdout, ' --prefix [path to folder]');
+    WriteLn(stdout, ' --user-prefix [path to folder]');
     WriteLn(stdout, ' --locale [name of language file]');
-    WriteLn(stdout, ' --width [screen width in pixels]');
-    WriteLn(stdout, ' --height [screen height in pixels]');
+    WriteLn(stdout, ' --nick [string]');
+    WriteLn(stdout, ' --fullscreen-width [fullscreen width in pixels]');
+    WriteLn(stdout, ' --fullscreen-height [fullscreen height in pixels]');
+    WriteLn(stdout, ' --width [window width in pixels]');
+    WriteLn(stdout, ' --height [window height in pixels]');
     WriteLn(stdout, ' --volume [sound level]');
     WriteLn(stdout, ' --frame-interval [milliseconds]');
+    Writeln(stdout, ' --stereo [value]');
     WriteLn(stdout, ' --raw-quality [flags]');
     WriteLn(stdout, ' --low-quality');
     WriteLn(stdout, ' --nomusic');
@@ -96,12 +62,85 @@
     WriteLn(stdout, '');
     WriteLn(stdout, 'For more detailed help and examples go to:');
     WriteLn(stdout, 'http://code.google.com/p/hedgewars/wiki/CommandLineOptions');
+    GameType:= gmtSyntax;
+end;
+
+procedure setDepth(var paramIndex: LongInt);
+begin
+    WriteLn(stdout, 'WARNING: --depth is a deprecated command, which could be removed in a future version!');
+    WriteLn(stdout, '         This option no longer does anything, please consider removing it');
+    WriteLn(stdout, '');
+   inc(ParamIndex);
+end;
+
+procedure statsOnlyGame;
+begin
+    cOnlyStats:= true;
+    cReducedQuality:= $FFFFFFFF xor rqLowRes;
+    SetSound(false);
+    SetMusic(false);
+    SetVolume(0);
+end;
+
+procedure setIpcPort(port: LongInt; var wrongParameter:Boolean);
+begin
+    if isInternal then
+        ipcPort := port
+    else
+        begin
+        WriteLn(stderr, 'ERROR: use of --port is not allowed');
+        wrongParameter := true;
+        end
+end;
+
+function parseNick(nick: String): String;
+begin
+    if isInternal then
+        parseNick:= DecodeBase64(nick)
+    else
+        parseNick:= nick;
+end;
+
+procedure setStereoMode(tmp: LongInt);
+begin
+    GrayScale:= false;
+{$IFDEF USE_S3D_RENDERING}
+    if (tmp > 6) and (tmp < 13) then
+        begin
+        // set the gray anaglyph rendering
+        GrayScale:= true;
+        cStereoMode:= TStereoMode(max(0, min(ord(high(TStereoMode)), tmp-6)))
+        end
+    else if tmp <= 6 then
+        // set the fullcolor anaglyph
+        cStereoMode:= TStereoMode(max(0, min(ord(high(TStereoMode)), tmp)))
+    else
+        // any other mode
+        cStereoMode:= TStereoMode(max(0, min(ord(high(TStereoMode)), tmp-6)));
+{$ELSE}
+    cStereoMode:= smNone;
+{$ENDIF}
+end;
+
+procedure startVideoRecording(var paramIndex: LongInt);
+begin
+{$IFDEF USE_VIDEO_RECORDING}
+    GameType:= gmtRecord;
+    inc(paramIndex);
+    cVideoFramerateNum:= StrToInt(ParamStr(paramIndex)); inc(paramIndex);
+    cVideoFramerateDen:= StrToInt(ParamStr(paramIndex)); inc(paramIndex);
+    RecPrefix:= ParamStr(paramIndex);                    inc(paramIndex);
+    cAVFormat:= ParamStr(paramIndex);                    inc(paramIndex);
+    cVideoCodec:= ParamStr(paramIndex);                  inc(paramIndex);
+    cVideoQuality:= StrToInt(ParamStr(paramIndex));      inc(paramIndex);
+    cAudioCodec:= ParamStr(paramIndex);                  inc(paramIndex);
+{$ENDIF}
 end;
 
 function getLongIntParameter(str:String; var paramIndex:LongInt; var wrongParameter:Boolean): LongInt;
 var tmpInt, c: LongInt;
 begin
-    paramIndex:= paramIndex + 1;
+    inc(paramIndex);
     val(str, tmpInt, c);
     wrongParameter:= c <> 0;
     if wrongParameter then
@@ -111,7 +150,7 @@
 
 function getStringParameter(str:String; var paramIndex:LongInt; var wrongParameter:Boolean): String;
 begin
-    paramIndex:= paramIndex + 1;
+    inc(paramIndex);
     wrongParameter:= (str='') or (Copy(str,1,2) = '--');
     if wrongParameter then
          WriteLn(stderr, 'ERROR: '+ParamStr(paramIndex-1)+' expects a string, you passed "'+str+'"');
@@ -122,16 +161,18 @@
 procedure parseClassicParameter(cmdArray: Array of String; size:LongInt; var paramIndex:LongInt); Forward;
 
 function parseParameter(cmd:String; arg:String; var paramIndex:LongInt): Boolean;
-const videoArray: Array [1..3] of String = ('--width','--height','--depth');
-const audioArray: Array [1..3] of String = ('--volume','--nomusic','--nosound');
-const otherArray: Array [1..3] of String = ('--locale','--fullscreen','--showfps');
-const mediaArray: Array [1..8] of String = ('--width','--height','--depth','--volume','--nomusic','--nosound','--locale','--fullscreen');
-const allArray: Array [1..12] of String = ('--width','--height','--depth','--volume','--nomusic','--nosound','--locale','--fullscreen','--showfps','--altdmg','--time','--lowquality');
-const reallyAll: array[0..21] of shortstring = (
-                '--user-dir', '--locale', '--width', '--height', '--frame-interval', '--volume','--nomusic', '--nosound',
-                '--fullscreen', '--showfps', '--altdmg', '--low-quality', '--raw-quality',
+const videoArray: Array [1..5] of String = ('--fullscreen-width','--fullscreen-height', '--width', '--height', '--depth');
+      audioArray: Array [1..3] of String = ('--volume','--nomusic','--nosound');
+      otherArray: Array [1..3] of String = ('--locale','--fullscreen','--showfps');
+      mediaArray: Array [1..10] of String = ('--fullscreen-width', '--fullscreen-height', '--width', '--height', '--depth', '--volume','--nomusic','--nosound','--locale','--fullscreen');
+      allArray: Array [1..14] of String = ('--fullscreen-width','--fullscreen-height', '--width', '--height', '--depth','--volume','--nomusic','--nosound','--locale','--fullscreen','--showfps','--altdmg','--frame-interval','--low-quality');
+      reallyAll: array[0..30] of shortstring = (
+                '--prefix', '--user-prefix', '--locale', '--fullscreen-width', '--fullscreen-height', '--width', 
+                '--height', '--frame-interval', '--volume','--nomusic', '--nosound',
+                '--fullscreen', '--showfps', '--altdmg', '--low-quality', '--raw-quality', '--stereo', '--nick', 
   {deprecated}  '--depth', '--set-video', '--set-audio', '--set-other', '--set-multimedia', '--set-everything',
-                '--stats-only', '--gci', '--help');
+  {internal}    '--internal', '--port', '--recorder', '--landpreview',
+  {misc}        '--stats-only', '--gci', '--help');
 var cmdIndex: byte;
 begin
     parseParameter:= false;
@@ -142,96 +183,157 @@
 
     while (cmdIndex <= High(reallyAll)) and (cmd <> reallyAll[cmdIndex]) do inc(cmdIndex);
     case cmdIndex of
-        {--user-dir}        0 : UserPathPrefix := getStringParameter (arg, paramIndex, parseParameter);
-        {--locale}          1 : cLocaleFName   := getStringParameter (arg, paramIndex, parseParameter);
-        {--width}           2 : cScreenWidth   := getLongIntParameter(arg, paramIndex, parseParameter);
-        {--height}          3 : cScreenHeight  := getLongIntParameter(arg, paramIndex, parseParameter);
-        {--frame-interval}  4 : cTimerInterval := getLongIntParameter(arg, paramIndex, parseParameter);
-        {--volume}          5 : SetVolume       ( getLongIntParameter(arg, paramIndex, parseParameter) );
-        {--nomusic}         6 : SetMusic        ( false );
-        {--nosound}         7 : SetSound        ( false );
-        {--fullscreen}      8 : cFullScreen    := true;
-        {--showfps}         9 : cShowFPS       := true;
-        {--altdmg}         10 : cAltDamage     := true;
-        {--low-quality}    11 : cReducedQuality:= $FFFFFFFF xor rqLowRes;
-        {--raw-quality}    12 : cReducedQuality:= getLongIntParameter(arg, paramIndex, parseParameter);
+        {--prefix}               0 : PathPrefix        := getStringParameter (arg, paramIndex, parseParameter);
+        {--user-prefix}          1 : UserPathPrefix    := getStringParameter (arg, paramIndex, parseParameter);
+        {--locale}               2 : cLocaleFName      := getStringParameter (arg, paramIndex, parseParameter);
+        {--fullscreen-width}     3 : cFullscreenWidth  := getLongIntParameter(arg, paramIndex, parseParameter);
+        {--fullscreen-height}    4 : cFullscreenHeight := getLongIntParameter(arg, paramIndex, parseParameter);
+        {--width}       5 : cWindowedWidth    := getLongIntParameter(arg, paramIndex, parseParameter);
+        {--height}      6 : cWindowedHeight   := getLongIntParameter(arg, paramIndex, parseParameter);
+        {--frame-interval}       7 : cTimerInterval    := getLongIntParameter(arg, paramIndex, parseParameter);
+        {--volume}               8 : SetVolume          ( getLongIntParameter(arg, paramIndex, parseParameter) );
+        {--nomusic}              9 : SetMusic           ( false );
+        {--nosound}             10 : SetSound           ( false );
+        {--fullscreen}          11 : cFullScreen       := true;
+        {--showfps}             12 : cShowFPS          := true;
+        {--altdmg}              13 : cAltDamage        := true;
+        {--low-quality}         14 : cReducedQuality   := $FFFFFFFF xor rqLowRes;
+        {--raw-quality}         15 : cReducedQuality   := getLongIntParameter(arg, paramIndex, parseParameter);
+        {--stereo}              16 : setStereoMode      ( getLongIntParameter(arg, paramIndex, parseParameter) );
+        {--nick}                17 : UserNick          := parseNick( getStringParameter(arg, paramIndex, parseParameter) );
         {deprecated options}
-        {--depth}          13 : cBits          := getLongIntParameter(arg, paramIndex, parseParameter);
-        {--set-video}      14 : parseClassicParameter(videoArray,3,paramIndex);
-        {--set-audio}      15 : parseClassicParameter(audioArray,3,paramIndex);
-        {--set-other}      16 : parseClassicParameter(otherArray,3,paramIndex);
-        {--set-multimedia} 17 : parseClassicParameter(mediaArray,8,paramIndex);
-        {--set-everything} 18 : parseClassicParameter(allArray,12,paramIndex);
+        {--depth}               18 : setDepth(paramIndex);
+        {--set-video}           19 : parseClassicParameter(videoArray,5,paramIndex);
+        {--set-audio}           20 : parseClassicParameter(audioArray,3,paramIndex);
+        {--set-other}           21 : parseClassicParameter(otherArray,3,paramIndex);
+        {--set-multimedia}      22 : parseClassicParameter(mediaArray,10,paramIndex);
+        {--set-everything}      23 : parseClassicParameter(allArray,14,paramIndex);
+        {"internal" options}
+        {--internal}            24 : {note it, but do nothing};
+        {--port}                25 : setIpcPort( getLongIntParameter(arg, paramIndex, parseParameter), parseParameter );
+        {--recorder}            26 : startVideoRecording(paramIndex);
+        {--landpreview}         27 : GameType := gmtLandPreview;
         {anything else}
-        {--stats-only}     19 : begin
-                                cOnlyStats:= true;
-                                cReducedQuality:= $FFFFFFFF xor rqLowRes;
-                                SetSound(false);
-                                end;
-        {--gci}            20 : begin            //     We had to make up all this saved space some how...     \\
-                                WriteLn(stdout, '                                                                ');
-                                WriteLn(stdout, '      /\\\\\\\\\\\\        /\\\\\\\\\  /\\\\\\\\\\\             ');
-                                WriteLn(stdout, '     /\\\//////////      /\\\////////  \/////\\\///             ');
-                                WriteLn(stdout, '     /\\\               /\\\/               \/\\\               ');
-                                WriteLn(stdout, '     \/\\\    /\\\\\\\  /\\\                 \/\\\              ');
-                                WriteLn(stdout, '      \/\\\   \/////\\\ \/\\\                 \/\\\             ');
-                                WriteLn(stdout, '       \/\\\       \/\\\ \//\\\                \/\\\            ');
-                                WriteLn(stdout, '        \/\\\       \/\\\  \///\\\              \/\\\           ');
-                                WriteLn(stdout, '         \/\\\\\\\\\\\\\/     \////\\\\\\\\\  /\\\\\\\\\\\      ');
-                                WriteLn(stdout, '          \/////////////          \/////////  \///////////      ');
-                                WriteLn(stdout, '                                                                ');
-                                WriteLn(stdout, ' Command Line Parser Implementation by a Google Code-In Student ');
-                                WriteLn(stdout, '             ASCII Art easter egg idea by @sheepluva            ');
-                                WriteLn(stdout, '                                                                ');
-                                end;
-        {--help}           21 : begin
-                                DisplayUsage();
-                                GameType:= gmtSyntax;
-                                end;
+        {--stats-only}          28 : statsOnlyGame();
+        {--gci}                 29 : GciEasterEgg();
+        {--help}                30 : DisplayUsage();
     else
         begin
-        WriteLn(stderr, 'ERROR: '+cmd+' is not a valid argument');
-        parseParameter:= true;
-        end
+        //Asusme the first "non parameter" is the replay file, anything else is invalid
+        if (recordFileName = '') and (Copy(cmd,1,2) <> '--') then
+            recordFileName := cmd
+        else
+            begin
+            WriteLn(stderr, '"'+cmd+'" is not a valid option');
+            parseParameter:= true;
+            end;
+        end;
     end;
 end;
 
 procedure parseClassicParameter(cmdArray: Array of String; size:LongInt; var paramIndex:LongInt);
 var index, tmpInt: LongInt;
-    isBool: Boolean;
+    isBool, isValid: Boolean;
+    cmd, arg, newSyntax: String;
 begin
+    WriteLn(stdout, 'WARNING: you are using a deprecated command, which could be removed in a future version!');
+    WriteLn(stdout, '         Consider updating to the latest syntax, which is much more flexible!');
+    WriteLn(stdout, '         Run `hwegine --help` to learn it!');
+    WriteLn(stdout, '');
+
     index:= 0;
     tmpInt:= 1;
     while (index < size) do
         begin
-        paramIndex:= paramIndex+1;
+        inc(paramIndex);
+        cmd:= cmdArray[index];
+        arg:= ParamStr(paramIndex);
+        isValid:= (cmd<>'--depth');
+
         // check if the parameter is a boolean one
-        isBool:= (cmdArray[index] = '--nomusic')
-            or (cmdArray[index] = '--nosound')
-            or (cmdArray[index] = '--fullscreen')
-            or (cmdArray[index] = '--showfps')
-            or (cmdArray[index] = '--altdmg')
-            or (cmdArray[index] = '--low-quality');
-        if (not isBool) or ((ParamStr(paramIndex)='1') and (cmdArray[index]<>'--nomusic') and (cmdArray[index]<>'--nosound')) then
-            parseParameter(cmdArray[index], ParamStr(paramIndex), tmpInt);
-        index:= index+1;
+        isBool:= (cmd = '--nomusic') or (cmd = '--nosound') or (cmd = '--fullscreen') or (cmd = '--showfps') or (cmd = '--altdmg');
+        if isBool and (arg='0') then
+            isValid:= false;
+        if (cmd='--nomusic') or (cmd='--nosound') then
+            isValid:= not isValid;
+
+        if isValid then
+            begin
+            parseParameter(cmd, arg, tmpInt);
+            newSyntax := newSyntax + cmd + ' ';
+            if not isBool then
+                newSyntax := newSyntax + arg + ' ';
+            end;
+        inc(index);
         end;
+    
+    WriteLn(stdout, 'Attempted to automatically convert to the new syntax:');
+    WriteLn(stdout, newSyntax);
+    WriteLn(stdout, '');
 end;
 
-procedure playReplayFileWithParameters(paramIndex: LongInt);
-var tmpInt: LongInt;
+procedure parseCommandLine{$IFDEF HWLIBRARY}(argc: LongInt; argv: PPChar){$ENDIF};
+var paramIndex: LongInt;
+    paramTotal: LongInt;
     wrongParameter: boolean;
 begin
+    paramIndex:= 1;
+    paramTotal:={$IFDEF HWLIBRARY}argc{$ELSE}ParamCount{$ENDIF};
     wrongParameter:= false;
-    while (paramIndex <= ParamCount) do
+    while (paramIndex <= paramTotal) do
         begin
-        if parseParameter( ParamStr(paramIndex), ParamStr(paramIndex+1), paramIndex) then
-            wrongParameter:= true;
-        paramIndex:= paramIndex+1;
+        {$IFDEF HWLIBRARY}
+        wrongParameter:= parseParameter( argv[paramIndex], argv[paramIndex+1], paramIndex);
+        {$ELSE}
+        wrongParameter:= parseParameter( ParamStr(paramIndex), ParamStr(paramIndex+1), paramIndex);
+        {$ENDIF}
+        inc(paramIndex);
         end;
     if wrongParameter = true then
+        GameType:= gmtSyntax;
+end;
+
+{$IFNDEF HWLIBRARY}
+procedure GetParams;
+//var tmpInt: LongInt;
+begin
+    (*
+    tmpInt:=0;
+    while (tmpInt <= ParamCount) do
         begin
+        WriteLn(stdout, inttostr(tmpInt) + ': ' + ParamStr(tmpInt));
+        inc(tmpInt);
+        end;
+    *)
+
+    isInternal:= (ParamStr(1) = '--internal');
+
+    UserPathPrefix := '.';
+    PathPrefix     := cDefaultPathPrefix;
+    recordFileName := '';
+    parseCommandLine();
+
+    if (isInternal) and (ParamCount<=1) then
+        begin
+        WriteLn(stderr, '--internal should not be manually used');
+        GameType := gmtSyntax;
+        end;
+
+    if (not isInternal) and (recordFileName = '') then
+        begin
+        WriteLn(stderr, 'You must specify a replay file');
+        GameType := gmtSyntax;
+        end
+    else if (recordFileName <> '') then
+        WriteLn(stdout, 'Attempting to play demo file "' + recordFilename + '"');
+
+    if (GameType = gmtSyntax) then
         WriteLn(stderr, 'Please use --help to see possible arguments and their usage');
-        GameType:= gmtSyntax;
-        end
+
+    (*
+    WriteLn(stdout,'PathPrefix:     ' + PathPrefix);
+    WriteLn(stdout,'UserPathPrefix: ' + UserPathPrefix);
+    *)
 end;
+{$ENDIF}
+
--- a/hedgewars/CMakeLists.txt	Tue Dec 18 20:48:37 2012 +0400
+++ b/hedgewars/CMakeLists.txt	Fri Jan 04 21:44:40 2013 +0400
@@ -9,8 +9,13 @@
 configure_file(${hedgewars_SOURCE_DIR}/hedgewars/config.inc.in ${CMAKE_CURRENT_BINARY_DIR}/config.inc)
 
 #SOURCE AND PROGRAMS SECTION
-set(hwengine_project ${hedgewars_SOURCE_DIR}/hedgewars/hwengine.pas)
-set(engine_output_name "hwengine")
+if(${BUILD_ENGINE_LIBRARY})
+    set(engine_output_name "${CMAKE_SHARED_LIBRARY_PREFIX}hwengine${CMAKE_SHARED_LIBRARY_SUFFIX}")
+    set(hwengine_project ${hedgewars_SOURCE_DIR}/hedgewars/hwLibrary.pas)
+else()
+    set(engine_output_name "hwengine${CMAKE_EXECUTABLE_SUFFIX}")
+    set(hwengine_project ${hedgewars_SOURCE_DIR}/hedgewars/hwengine.pas)
+endif()
 
 if (APPLE)
     set(required_fpc_version 2.6)
@@ -85,25 +90,23 @@
     ${CMAKE_CURRENT_BINARY_DIR}/config.inc
     )
 
-if(BUILD_ENGINE_LIBRARY)
-    message(STATUS "Engine will be built as library (experimental)")
-    set(hwengine_project ${hedgewars_SOURCE_DIR}/hedgewars/hwLibrary.pas)
-    set(pascal_flags "-dHWLIBRARY" ${pascal_flags})
+if(${BUILD_ENGINE_LIBRARY})
+    message(WARNING "Engine will be built as library (experimental)")
+    list(APPEND pascal_flags "-dHWLIBRARY")
 
     # create position independent code, only required for x68_64 builds, similar to -fPIC
     if(CMAKE_SIZEOF_VOID_P MATCHES "8")
-        set(pascal_flags "-Cg" ${pascal_flags})
+        list(APPEND pascal_flags "-Cg")
     endif(CMAKE_SIZEOF_VOID_P MATCHES "8")
 
     # due to compiler/linker issues on Max OS X 10.6 -k-no_order_inits is needed to avoid linking fail
-    if(APPLE AND current_macosx_version GREATER "10.5")
-        set(pascal_flags "-k-no_order_inits" ${pascal_flags})
+    if(APPLE AND current_macosx_version VERSION_GREATER "10.5")
+        list(APPEND pascal_flags "-k-no_order_inits")
     endif()
-
-    if(APPLE)
-        set(engine_output_name "libhwengine.dylib")
-    endif (APPLE)
-endif(BUILD_ENGINE_LIBRARY)
+    set(destination_dir ${target_library_install_dir})
+else(${BUILD_ENGINE_LIBRARY})
+    set(destination_dir ${target_binary_install_dir})
+endif(${BUILD_ENGINE_LIBRARY})
 
 
 # Check Freepascal version
@@ -125,32 +128,32 @@
     endif()
 
     #on OSX we need to provide the SDL_main() function when building as executable
-    if(NOT BUILD_ENGINE_LIBRARY)
+    if(NOT ${BUILD_ENGINE_LIBRARY})
         #let's look for the installed sdlmain file; if it is not found, let's build our own
         find_package(SDL REQUIRED)
         #remove the ";-framework Cocoa" from the SDL_LIBRARY variable
-        string(REGEX REPLACE "(.*);-.*" "\\1" sdl_dir "${SDL_LIBRARY}")
+        string(REGEX REPLACE "(.*);-.*" "\\1" sdl_library_only "${SDL_LIBRARY}")
         #find libsdmain.a
-        find_file(SDLMAIN_LIB libSDLMain.a PATHS ${sdl_dir}/Resources/)
+        find_file(SDLMAIN_LIB libSDLMain.a PATHS ${sdl_library_only}/Resources/)
 
         if(SDLMAIN_LIB MATCHES "SDLMAIN_LIB-NOTFOUND")
             include_directories(${SDL_INCLUDE_DIR})
             add_library (SDLmain STATIC SDLMain.m)
             #add a dependency to the hwengine target
-            set(engine_sources ${engine_sources} SDLmain)
+            list(APPEND engine_sources SDLmain)
             set(SDLMAIN_LIB "${LIBRARY_OUTPUT_PATH}/libSDLmain.a")
         endif()
 
-        set(pascal_flags "-k${SDLMAIN_LIB}" ${pascal_flags})
+        list(APPEND pascal_flags "-k${SDLMAIN_LIB}")
     endif()
 endif(APPLE)
 
 if(NOT NOPNG)
     find_package(PNG)
     if(${PNG_FOUND})
-        set(pascal_flags "-dPNG_SCREENSHOTS" ${pascal_flags})
+        list(APPEND pascal_flags "-dPNG_SCREENSHOTS")
         if(APPLE)  # fpc png unit doesn't pull the library (see bug 21833)
-            set(pascal_flags "-k${PNG_LIBRARY}" ${pascal_flags})
+            list(APPEND pascal_flags "-k${PNG_LIBRARY}")
         endif()
     else()
         message(WARNING "Screenshots will be in BMP format because libpng was not found")
@@ -182,15 +185,15 @@
 
         #TODO: convert avwrapper to .pas unit so we can skip this step
         include_directories(${FFMPEG_INCLUDE_DIR})
-        set(pascal_flags "-dUSE_VIDEO_RECORDING" ${pascal_flags})
+        list(APPEND pascal_flags "-dUSE_VIDEO_RECORDING")
         IF (WIN32)
             # there are some problems with linking our avwrapper as static lib, so link it as shared
             add_library(avwrapper SHARED avwrapper.c)
             target_link_libraries(avwrapper ${FFMPEG_LIBRARIES})
-            install(PROGRAMS "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_SHARED_LIBRARY_PREFIX}avwrapper${CMAKE_SHARED_LIBRARY_SUFFIX}" DESTINATION ${target_dir})
+            install(PROGRAMS "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_SHARED_LIBRARY_PREFIX}avwrapper${CMAKE_SHARED_LIBRARY_SUFFIX}" DESTINATION ${target_library_install_dir})
         ELSE()
             add_library(avwrapper STATIC avwrapper.c)
-            set(pascal_flags "-k${FFMPEG_LIBAVCODEC}" "-k${FFMPEG_LIBAVFORMAT}" "-k${FFMPEG_LIBAVUTIL}" ${pascal_flags})
+            list(APPEND pascal_flags "-k${FFMPEG_LIBAVCODEC}" "-k${FFMPEG_LIBAVFORMAT}" "-k${FFMPEG_LIBAVUTIL}")
         ENDIF()
     else()
         message(WARNING "Could NOT find FFMPEG/LibAV, video recording will be disabled")
@@ -204,16 +207,16 @@
 
 if(NOT APPLE)
     #here is the command for standard executables or for shared library
-    add_custom_command(OUTPUT "${EXECUTABLE_OUTPUT_PATH}/${engine_output_name}${CMAKE_EXECUTABLE_SUFFIX}"
+    add_custom_command(OUTPUT "${EXECUTABLE_OUTPUT_PATH}/${engine_output_name}"
         COMMAND "${FPC_EXECUTABLE}"
-        ARGS ${fpc_flags}
+        ARGS ${fpc_flags} -o${engine_output_name}
         MAIN_DEPENDENCY ${hwengine_project}
         DEPENDS ${engine_sources}
         )
 else()
     #these are the dependencies for building a universal binary on Mac OS X
     foreach (build_arch ${powerpc_build} ${i386_build} ${x86_64_build})
-        set(lipo_args_list "${EXECUTABLE_OUTPUT_PATH}/hwengine.${build_arch}" ${lipo_args_list})
+        list(APPEND lipo_args_list "${EXECUTABLE_OUTPUT_PATH}/hwengine.${build_arch}")
         add_custom_command(OUTPUT "${EXECUTABLE_OUTPUT_PATH}/hwengine.${build_arch}"
             COMMAND "${FPC_EXECUTABLE}"
             ARGS ${fpc_flags} -ohwengine.${build_arch} -P${build_arch}
@@ -221,6 +224,11 @@
             DEPENDS ${engine_sources}
             )
         add_custom_target(hwengine.${build_arch} ALL DEPENDS "${EXECUTABLE_OUTPUT_PATH}/hwengine.${build_arch}")
+        add_custom_command(TARGET hwengine.${build_arch} POST_BUILD
+            COMMAND "install_name_tool"
+            ARGS -id @executable_path/../Frameworks/${engine_output_name}
+                ${EXECUTABLE_OUTPUT_PATH}/hwengine.${build_arch}
+            )
     endforeach()
 
     add_custom_command(OUTPUT "${EXECUTABLE_OUTPUT_PATH}/${engine_output_name}"
@@ -231,7 +239,7 @@
 endif()
 
 
-add_custom_target(${engine_output_name} ALL DEPENDS "${EXECUTABLE_OUTPUT_PATH}/${engine_output_name}${CMAKE_EXECUTABLE_SUFFIX}")
+add_custom_target(${engine_output_name} ALL DEPENDS "${EXECUTABLE_OUTPUT_PATH}/${engine_output_name}")
 
 #when system Lua is not found we need to compile it before engine
 if(NOT LUA_FOUND)
@@ -252,4 +260,4 @@
     add_dependencies(${engine_output_name} ENGINECLEAN)
 endif()
 
-install(PROGRAMS "${EXECUTABLE_OUTPUT_PATH}/${engine_output_name}${CMAKE_EXECUTABLE_SUFFIX}" DESTINATION ${target_dir})
+install(PROGRAMS "${EXECUTABLE_OUTPUT_PATH}/${engine_output_name}" DESTINATION ${destination_dir})
--- a/hedgewars/config.inc.in	Tue Dec 18 20:48:37 2012 +0400
+++ b/hedgewars/config.inc.in	Fri Jan 04 21:44:40 2013 +0400
@@ -24,3 +24,4 @@
 const cNetProtoVersion = ${HEDGEWARS_PROTO_VER};
       cVersionString = '${HEDGEWARS_VERSION}';
       cLuaLibrary = '${LUA_LIBRARY}';
+      cDefaultPathPrefix = '${CMAKE_INSTALL_PREFIX}/${SHAREPATH}/Data';
--- a/hedgewars/hwengine.pas	Tue Dec 18 20:48:37 2012 +0400
+++ b/hedgewars/hwengine.pas	Fri Jan 04 21:44:40 2013 +0400
@@ -38,12 +38,13 @@
      {$IFDEF ANDROID}, GLUnit{$ENDIF}
      ;
 
+var isInternal: Boolean;
 
 {$IFDEF HWLIBRARY}
 procedure preInitEverything();
 procedure initEverything(complete:boolean);
 procedure freeEverything(complete:boolean);
-procedure Game(gameArgs: PPChar); cdecl; export;
+procedure Game(argc: LongInt; argv: PPChar); cdecl; export;
 procedure GenLandPreview(port: Longint); cdecl; export;
 
 implementation
@@ -53,6 +54,8 @@
 procedure freeEverything(complete:boolean); forward;
 {$ENDIF}
 
+{$INCLUDE "ArgParsers.inc"}
+
 ///////////////////////////////////////////////////////////////////////////////
 function DoTimer(Lag: LongInt): boolean;
 var s: shortstring;
@@ -261,18 +264,24 @@
             end; //end case event.type_ of
         end; //end while SDL_PollEvent(@event) <> 0 do
 
+        if (CursorMovementX <> 0) or (CursorMovementY <> 0) then
+            handlePositionUpdate(CursorMovementX * cameraKeyboardSpeed, CursorMovementY * cameraKeyboardSpeed);
+
         if (cScreenResizeDelay <> 0) and (cScreenResizeDelay < RealTicks) and
            ((cNewScreenWidth <> cScreenWidth) or (cNewScreenHeight <> cScreenHeight)) then
         begin
             cScreenResizeDelay:= 0;
-            cScreenWidth:= cNewScreenWidth;
-            cScreenHeight:= cNewScreenHeight;
+            cWindowedWidth:= cNewScreenWidth;
+            cWindowedHeight:= cNewScreenHeight;
+            cScreenWidth:= cWindowedWidth;
+            cScreenHeight:= cWindowedHeight;
 
             ParseCommand('fullscr '+intToStr(LongInt(cFullScreen)), true);
             WriteLnToConsole('window resize: ' + IntToStr(cScreenWidth) + ' x ' + IntToStr(cScreenHeight));
             ScriptOnScreenResize();
             InitCameraBorders();
             InitTouchInterface();
+            SendIPC('W' + IntToStr(cScreenWidth) + 'x' + IntToStr(cScreenHeight));
         end;
 
         CurrTime:= SDL_GetTicks();
@@ -320,29 +329,16 @@
 {$ENDIF}
 
 ///////////////////////////////////////////////////////////////////////////////
-procedure Game{$IFDEF HWLIBRARY}(gameArgs: PPChar); cdecl; export{$ENDIF};
+procedure Game{$IFDEF HWLIBRARY}(argc: LongInt; argv: PPChar); cdecl; export{$ENDIF};
 var p: TPathType;
     s: shortstring;
     i: LongInt;
 begin
 {$IFDEF HWLIBRARY}
     preInitEverything();
-    cShowFPS:= {$IFDEF DEBUGFILE}true{$ELSE}false{$ENDIF};
-    ipcPort:= StrToInt(gameArgs[0]);
-    cScreenWidth:= StrToInt(gameArgs[1]);
-    cScreenHeight:= StrToInt(gameArgs[2]);
-    cReducedQuality:= StrToInt(gameArgs[3]);
-    cLocaleFName:= gameArgs[4];
-    UserNick:= gameArgs[5];
-    SetSound(gameArgs[6] = '1');
-    SetMusic(gameArgs[7] = '1');
-    cAltDamage:= gameArgs[8] = '1';
-    PathPrefix:= gameArgs[9];
-    UserPathPrefix:= '../Documents';
-    recordFileName:= gameArgs[10];
+    parseCommandLine(argc, argv);
 {$ENDIF}
     initEverything(true);
-
     WriteLnToConsole('Hedgewars ' + cVersionString + ' engine (network protocol: ' + inttostr(cNetProtoVersion) + ')');
     AddFileLog('Prefix: "' + PathPrefix +'"');
     AddFileLog('UserPrefix: "' + UserPathPrefix +'"');
@@ -544,68 +540,6 @@
 {$IFNDEF HWLIBRARY}
 
 ///////////////////////////////////////////////////////////////////////////////
-{$INCLUDE "ArgParsers.inc"}
-
-procedure GetParams;
-var startIndex,tmpInt: LongInt;
-    debug: string;
-begin
-    (*
-    tmpInt:=0;
-    while (tmpInt <= ParamCount) do
-        begin
-        WriteLn(stdout,inttostr(tmpInt) + ': ' + ParamStr(tmpInt));
-        inc(tmpInt);
-        end;
-    *)
-
-    if (ParamCount = 3) and (ParamStr(3) = 'landpreview') then
-    begin
-        PathPrefix := ParamStr(1);
-        ipcPort    := StrToInt(ParamStr(2));
-        GameType   := gmtLandPreview;
-        exit;
-    end;
-
-    //TODO: prepend something so that we can use a cDefaultParamNum of parameters
-    if ParamCount = cDefaultParamNum then
-    begin
-        internalStartGameWithParameters();
-        exit;
-    end
-{$IFDEF USE_VIDEO_RECORDING}
-    else if ParamCount = cVideorecParamNum then
-    begin
-        internalStartVideoRecordingWithParameters();
-        exit;
-    end
-{$ENDIF};
-
-    if (ParamCount < 2) then
-        begin
-        DisplayUsage();
-        GameType:= gmtSyntax;
-        end
-    else
-        begin
-        if (ParamCount >= 2) then
-            begin
-            UserPathPrefix := '.';
-            PathPrefix     := ParamStr(1);
-            recordFileName := ParamStr(2);
-            startIndex     := 3;
-            end;
-
-        playReplayFileWithParameters(startIndex);
-        end;
-    (*
-    WriteLn(stdout,recordFilename);
-    WriteLn(stdout,PathPrefix);
-    WriteLn(stdout,UserPathPrefix);
-    *)
-end;
-
-///////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////// m a i n ///////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 begin
@@ -614,9 +548,8 @@
 
     if GameType = gmtLandPreview then
         GenLandPreview()
-    else if GameType = gmtSyntax then
-        //Exit cleanly
-    else Game();
+    else if GameType <> gmtSyntax then
+        Game();
 
     // return 1 when engine is not called correctly
     halt(LongInt(GameType = gmtSyntax));
--- a/hedgewars/uConsts.pas	Tue Dec 18 20:48:37 2012 +0400
+++ b/hedgewars/uConsts.pas	Fri Jan 04 21:44:40 2013 +0400
@@ -27,8 +27,6 @@
 
 const
     sfMax = 1000;
-    cDefaultParamNum = 17;
-    cVideorecParamNum = cDefaultParamNum + 7;
 
     // message constants
     errmsgCreateSurface   = 'Error creating SDL surface';
@@ -45,6 +43,9 @@
     msgFailedSize        = 'failed due to size';
     msgGettingConfig     = 'Getting game config...';
 
+    // camera movement multipliers
+    cameraKeyboardSpeed : ShortInt = 10;
+
     // color constants
     cWhiteColorChannels : TSDL_Color = (r:$FF; g:$FF; b:$FF; unused:$FF);
     cNearBlackColorChannels : TSDL_Color = (r:$00; g:$00; b:$10; unused:$FF);
--- a/hedgewars/uCursor.pas	Tue Dec 18 20:48:37 2012 +0400
+++ b/hedgewars/uCursor.pas	Fri Jan 04 21:44:40 2013 +0400
@@ -5,6 +5,7 @@
 procedure init;
 procedure resetPosition;
 procedure updatePosition;
+procedure handlePositionUpdate(x, y: LongInt);
 
 implementation
 
@@ -24,15 +25,20 @@
 var x, y: LongInt;
 begin
     SDL_GetMouseState(@x, @y);
-
+    
     if(x <> cScreenWidth div 2) or (y <> cScreenHeight div 2) then
-        begin
-        CursorPoint.X:= CursorPoint.X + x - cScreenWidth div 2;
-        CursorPoint.Y:= CursorPoint.Y - y + cScreenHeight div 2;
+    begin
+        handlePositionUpdate(x - cScreenWidth div 2, y - cScreenHeight div 2);
 
         if cHasFocus then
             SDL_WarpMouse(cScreenWidth div 2, cScreenHeight div 2);
-        end
+    end
+end;
+
+procedure handlePositionUpdate(x, y: LongInt);
+begin
+    CursorPoint.X:= CursorPoint.X + x;
+    CursorPoint.Y:= CursorPoint.Y - y;
 end;
 
 end.
--- a/hedgewars/uGears.pas	Tue Dec 18 20:48:37 2012 +0400
+++ b/hedgewars/uGears.pas	Fri Jan 04 21:44:40 2013 +0400
@@ -78,6 +78,7 @@
     stSpawn, stNTurn);
     upd: Longword;
     snowLeft,snowRight: LongInt;
+    NewTurnTick: LongWord;
     //SDMusic: shortstring;
 
 // For better maintainability the step handlers of gears are stored in
@@ -189,6 +190,16 @@
     i, AliveCount: LongInt;
     s: shortstring;
 begin
+ScriptCall('onGameTick');
+if GameTicks mod 20 = 0 then ScriptCall('onGameTick20');
+if GameTicks = NewTurnTick then
+    begin
+    ScriptCall('onNewTurn');
+{$IFDEF SDL13}
+    uTouch.NewTurnBeginning();
+{$ENDIF}
+    end;
+
 PrvInactive:= AllInactive;
 AllInactive:= true;
 
@@ -383,7 +394,8 @@
                 SwitchHedgehog;
 
                 AfterSwitchHedgehog;
-                bBetweenTurns:= false
+                bBetweenTurns:= false;
+                NewTurnTick:= GameTicks + 1
                 end;
             step:= Low(step)
             end;
@@ -470,8 +482,6 @@
         inc(hiTicks) // we do not recieve a message for this
     end;
 AddRandomness(CheckSum);
-ScriptCall('onGameTick');
-if GameTicks mod 20 = 0 then ScriptCall('onGameTick20');
 
 inc(GameTicks)
 end;
@@ -1396,6 +1406,7 @@
     upd:= 0;
 
     //SDMusic:= 'hell.ogg';
+    NewTurnTick:= $FFFFFFFF;
 end;
 
 procedure freeModule;
--- a/hedgewars/uInputHandler.pas	Tue Dec 18 20:48:37 2012 +0400
+++ b/hedgewars/uInputHandler.pas	Fri Jan 04 21:44:40 2013 +0400
@@ -39,6 +39,7 @@
 
 procedure SetBinds(var binds: TBinds);
 procedure SetDefaultBinds;
+procedure chDefaultBind(var id: shortstring);
 
 procedure ControllerInit;
 procedure ControllerAxisEvent(joy, axis: Byte; value: Integer);
@@ -70,6 +71,7 @@
     //ControllerBalls: array[0..5] of array[0..19] of array[0..1] of Integer;
     ControllerHats: array[0..5] of array[0..19] of Byte;
     ControllerButtons: array[0..5] of array[0..19] of Byte;
+    usingDBinds: boolean;
 
 function  KeyNameToCode(name: shortstring): LongInt; inline;
 begin
@@ -329,9 +331,9 @@
     binds:= binds; // avoid hint
     CurrentBinds:= DefaultBinds;
 {$ELSE}
-for t:= 0 to cKbdMaxIndex do
-    if (CurrentBinds[t] <> binds[t]) and tkbd[t] then
-        ProcessKey(t, False);
+    for t:= 0 to cKbdMaxIndex do
+        if (CurrentBinds[t] <> binds[t]) and tkbd[t] then
+            ProcessKey(t, False);
 
     CurrentBinds:= binds;
 {$ENDIF}
@@ -450,8 +452,45 @@
     ProcessKey(k +  ControllerNumAxes[joy]*2 + ControllerNumHats[joy]*4 + button, pressed);
 end;
 
+// Bind that isn't a team bind, but overrides defaultbinds.
+// When first called, DefaultBinds is cleared, because we assume we are getting a full list of dbinds.
+procedure chDefaultBind(var id: shortstring);
+var KeyName, Modifier, tmp: shortstring;
+    b: LongInt;
+begin
+KeyName:= '';
+Modifier:= '';
+
+if (not usingDBinds) then
+    begin
+    usingDBinds:= true;
+    FillByte(DefaultBinds, SizeOf(DefaultBinds), 0);
+    end;
+
+if (Pos('mod:', id) <> 0) then
+    begin
+    tmp:= '';
+    SplitBySpace(id, tmp);
+    Modifier:= id;
+    id:= tmp;
+    end;
+
+SplitBySpace(id, KeyName);
+if KeyName[1]='"' then
+    Delete(KeyName, 1, 1);
+if KeyName[byte(KeyName[0])]='"' then
+    Delete(KeyName, byte(KeyName[0]), 1);
+b:= KeyNameToCode(id, Modifier);
+if b = 0 then
+    OutError(errmsgUnknownVariable + ' "' + id + '"', false)
+else
+    DefaultBinds[b]:= KeyName;
+end;
+
 procedure initModule;
 begin
+    usingDBinds:= false;
+    RegisterVariable('dbind', @chDefaultBind, true );
 end;
 
 procedure freeModule;
--- a/hedgewars/uPhysFSLayer.pas	Tue Dec 18 20:48:37 2012 +0400
+++ b/hedgewars/uPhysFSLayer.pas	Fri Jan 04 21:44:40 2013 +0400
@@ -40,7 +40,7 @@
 procedure physfsReaderSetBuffer(buf: pointer); cdecl; external PhysfsLibName;
 
 implementation
-uses uUtils, uVariables;
+uses uUtils, uVariables, sysutils;
 
 function PHYSFS_init(argv0: PChar) : LongInt; cdecl; external PhysfsLibName;
 function PHYSFS_deinit() : LongInt; cdecl; external PhysfsLibName;
@@ -135,8 +135,16 @@
 
 procedure initModule;
 var i: LongInt;
+    cPhysfsId: shortstring;
 begin
-    i:= PHYSFS_init(Str2PChar(ParamStr(0)));
+{$IFDEF HWLIBRARY}
+    //TODO: http://icculus.org/pipermail/physfs/2011-August/001006.html
+    cPhysfsId:= GetCurrentDir() + {$IFDEF DARWIN}'/Hedgewars.app/Contents/MacOS/' + {$ENDIF} ' hedgewars';
+{$ELSE}
+    cPhysfsId:= ParamStr(0);
+{$ENDIF}
+
+    i:= PHYSFS_init(Str2PChar(cPhysfsId));
     AddFileLog('[PhysFS] init: ' + inttostr(i));
 
     i:= PHYSFS_mount(Str2PChar(PathPrefix), nil, true);
--- a/hedgewars/uStore.pas	Tue Dec 18 20:48:37 2012 +0400
+++ b/hedgewars/uStore.pas	Fri Jan 04 21:44:40 2013 +0400
@@ -547,7 +547,7 @@
         DeleteFramebuffer(defaultFrame, depthv, texv);
 {$ENDIF}
 {$IFDEF USE_S3D_RENDERING}
-    if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) or (cStereoMode = smAFR) then
+    if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) then
         begin
         DeleteFramebuffer(framel, depthl, texl);
         DeleteFramebuffer(framer, depthr, texr);
@@ -813,7 +813,7 @@
 {$ENDIF}
 
 {$IFDEF USE_S3D_RENDERING}
-    if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) or (cStereoMode = smAFR) then
+    if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) then
     begin
         // prepare left and right frame buffers and associated textures
         if glLoadExtension('GL_EXT_framebuffer_object') then
@@ -1142,6 +1142,17 @@
     if Length(s) = 0 then
          cFullScreen:= (not cFullScreen)
     else cFullScreen:= s = '1';
+    
+    if cFullScreen then
+        begin
+        cScreenWidth:= cFullscreenWidth;
+        cScreenHeight:= cFullscreenHeight;
+        end
+    else
+        begin
+        cScreenWidth:= cWindowedWidth;
+        cScreenHeight:= cWindowedHeight;
+        end;
 
     AddFileLog('Preparing to change video parameters...');
 {$IFDEF SDL13}
@@ -1219,22 +1230,25 @@
 
     if SDLwindow = nil then
         if cFullScreen then
-            SDLwindow:= SDL_CreateWindow('Hedgewars', x, y, cOrigScreenWidth, cOrigScreenHeight, flags or SDL_WINDOW_FULLSCREEN)
+            SDLwindow:= SDL_CreateWindow('Hedgewars', x, y, cScreenWidth, cScreenHeight, flags or SDL_WINDOW_FULLSCREEN)
         else
+            begin
             SDLwindow:= SDL_CreateWindow('Hedgewars', x, y, cScreenWidth, cScreenHeight, flags);
+            end;
     SDLTry(SDLwindow <> nil, true);
 {$ELSE}
     flags:= SDL_OPENGL or SDL_RESIZABLE;
     if cFullScreen then
+        begin
         flags:= flags or SDL_FULLSCREEN;
-
+        end;
     if not cOnlyStats then
         begin
     {$IFDEF WIN32}
         s:= SDL_getenv('SDL_VIDEO_CENTERED');
         SDL_putenv('SDL_VIDEO_CENTERED=1');
     {$ENDIF}
-        SDLPrimSurface:= SDL_SetVideoMode(cScreenWidth, cScreenHeight, cBits, flags);
+        SDLPrimSurface:= SDL_SetVideoMode(cScreenWidth, cScreenHeight, 0, flags);
         SDLTry(SDLPrimSurface <> nil, true);
     {$IFDEF WIN32}SDL_putenv(str2pchar('SDL_VIDEO_CENTERED=' + s));{$ENDIF}
         end;
--- a/hedgewars/uTeams.pas	Tue Dec 18 20:48:37 2012 +0400
+++ b/hedgewars/uTeams.pas	Fri Jan 04 21:44:40 2013 +0400
@@ -321,16 +321,11 @@
         end;
     ReadyTimeLeft:= 0
     end;
-
-{$IFDEF SDL13}
-uTouch.NewTurnBeginning();
-{$ENDIF}
-ScriptCall('onNewTurn');
 end;
 
 function AddTeam(TeamColor: Longword): PTeam;
 var team: PTeam;
-    c: LongInt;
+    c, t: LongInt;
 begin
 TryDo(TeamsCount < cMaxTeams, 'Too many teams', true);
 New(team);
@@ -343,6 +338,9 @@
 TeamsArray[TeamsCount]:= team;
 inc(TeamsCount);
 
+for t:= 0 to cKbdMaxIndex do
+    team^.Binds[t]:= '';
+
 c:= Pred(ClansCount);
 while (c >= 0) and (ClansArray[c]^.Color <> TeamColor) do dec(c);
 if c < 0 then
--- a/hedgewars/uTypes.pas	Tue Dec 18 20:48:37 2012 +0400
+++ b/hedgewars/uTypes.pas	Fri Jan 04 21:44:40 2013 +0400
@@ -169,7 +169,7 @@
     TWave = (waveRollup, waveSad, waveWave, waveHurrah, waveLemonade, waveShrug, waveJuggle);
 
     TRenderMode = (rmDefault, rmLeftEye, rmRightEye);
-    TStereoMode = (smNone, smRedCyan, smCyanRed, smRedBlue, smBlueRed, smRedGreen, smGreenRed, smHorizontal, smVertical, smAFR);
+    TStereoMode = (smNone, smRedCyan, smCyanRed, smRedBlue, smBlueRed, smRedGreen, smGreenRed, smHorizontal, smVertical);
 
     THHFont = record
             Handle: PTTF_Font;
--- a/hedgewars/uVariables.pas	Tue Dec 18 20:48:37 2012 +0400
+++ b/hedgewars/uVariables.pas	Fri Jan 04 21:44:40 2013 +0400
@@ -27,14 +27,15 @@
 /////// init flags ///////
     cMinScreenWidth    : LongInt;
     cMinScreenHeight   : LongInt;
+    cFullscreenWidth   : LongInt;
+    cFullscreenHeight  : LongInt;
+    cWindowedWidth     : LongInt;
+    cWindowedHeight    : LongInt;
     cScreenWidth       : LongInt;
     cScreenHeight      : LongInt;
-    cOrigScreenWidth   : LongInt;
-    cOrigScreenHeight  : LongInt;
     cNewScreenWidth    : LongInt;
     cNewScreenHeight   : LongInt;
     cScreenResizeDelay : LongWord;
-    cBits              : LongInt;
     ipcPort            : Word;
     cFullScreen        : boolean;
     cLocaleFName       : shortstring;
@@ -2325,9 +2326,13 @@
 begin
     // initialisation flags - they are going to be overwritten by program args
 
-    cScreenWidth    := 1024;
-    cScreenHeight   := 768;
-    cBits           := 32;
+    cFullscreenWidth  := 0;
+    cFullscreenHeight := 0;
+    cWindowedWidth    := 1024;
+    cWindowedHeight   := 768;
+    cScreenWidth      := cWindowedWidth;
+    cScreenHeight     := cWindowedHeight;
+
     cShowFPS        := false;
     cAltDamage      := true;
     cTimerInterval  := 8;
@@ -2508,15 +2513,20 @@
     vobSDVelocity:= 15;
     vobSDFallSpeed:= 250;
 
-    cMinScreenWidth:= min(cScreenWidth, 640);
-    cMinScreenHeight:= min(cScreenHeight, 480);
-    cOrigScreenWidth:= cScreenWidth;
-    cOrigScreenHeight:= cScreenHeight;
+    cMinScreenWidth  := min(cScreenWidth, 640);
+    cMinScreenHeight := min(cScreenHeight, 480);
 
     cNewScreenWidth    := cScreenWidth;
     cNewScreenHeight   := cScreenHeight;
     cScreenResizeDelay := 0;
 
+    // make sure fullscreen resolution is always initialised somehow
+    if cFullscreenWidth = 0 then
+        cFullscreenWidth:= min(cWindowedWidth, 640);
+    if cFullscreenHeight = 0 then
+        cFullscreenHeight:= min(cWindowedHeight, 480);
+
+
     LuaGoals:= '';
     cMapName:= '';
 
--- a/hedgewars/uWorld.pas	Tue Dec 18 20:48:37 2012 +0400
+++ b/hedgewars/uWorld.pas	Fri Jan 04 21:44:40 2013 +0400
@@ -987,15 +987,6 @@
         DrawWorldStereo(Lag, rmDefault)
         end
 {$IFDEF USE_S3D_RENDERING}
-    else if (cStereoMode = smAFR) then
-        begin
-        AFRToggle:= not AFRToggle;
-        glClear(GL_COLOR_BUFFER_BIT);
-        if AFRToggle then
-            DrawWorldStereo(Lag, rmLeftEye)
-        else
-            DrawWorldStereo(Lag, rmRightEye)
-        end
     else if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) then
         begin
         // create left fb
--- a/misc/liblua/CMakeLists.txt	Tue Dec 18 20:48:37 2012 +0400
+++ b/misc/liblua/CMakeLists.txt	Fri Jan 04 21:44:40 2013 +0400
@@ -9,7 +9,7 @@
     set(LUA_LIBRARY lua.dll)
 
     set_target_properties(lua PROPERTIES PREFIX "")
-    install(TARGETS lua RUNTIME DESTINATION ${target_dir})
+    install(TARGETS lua RUNTIME DESTINATION ${target_library_install_dir})
 else(WIN32)
     add_definitions(-DLUA_USE_LINUX)
     add_library(lua STATIC ${lua_src})
--- a/misc/physfs/CMakeLists.txt	Tue Dec 18 20:48:37 2012 +0400
+++ b/misc/physfs/CMakeLists.txt	Fri Jan 04 21:44:40 2013 +0400
@@ -3,64 +3,65 @@
 #
 # Please see the file LICENSE.txt in the source's root directory.
 
-#lines overridden by Hedgewars configuration
-#CMAKE_MINIMUM_REQUIRED(VERSION 2.4)
-#PROJECT(PhysicsFS)
-SET(PHYSFS_VERSION 2.1.0)
+## lines starting with '##' are lines overridden/modified/added by Hedgewars configuration
+##CMAKE_MINIMUM_REQUIRED(VERSION 2.4)
+##PROJECT(PhysicsFS)
+set(PHYSFS_VERSION 2.1.0)
 
 # Increment this if/when we break backwards compatibility.
-SET(PHYSFS_SOVERSION 1)
+set(PHYSFS_SOVERSION 1)
 
 # I hate that they define "WIN32" ... we're about to move to Win64...I hope!
-IF(WIN32 AND NOT WINDOWS)
-    SET(WINDOWS TRUE)
-ENDIF(WIN32 AND NOT WINDOWS)
-
+if(WIN32 AND NOT WINDOWS)
+    set(WINDOWS TRUE)
+endif(WIN32 AND NOT WINDOWS)
 
 # Bleh, let's do it for "APPLE" too.
-IF(APPLE AND NOT MACOSX)
-    SET(MACOSX TRUE)
-ENDIF(APPLE AND NOT MACOSX)
+if(APPLE AND NOT MACOSX)
+    set(MACOSX TRUE)
+endif(APPLE AND NOT MACOSX)
 
 # For now, Haiku and BeOS are the same, as far as the build system cares.
-IF(HAIKU AND NOT BEOS)
-    SET(BEOS TRUE)
-ENDIF(HAIKU AND NOT BEOS)
+if(HAIKU AND NOT BEOS)
+    set(BEOS TRUE)
+endif(HAIKU AND NOT BEOS)
 
-IF(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
-    SET(SOLARIS TRUE)
-ENDIF(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
+if(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
+    set(SOLARIS TRUE)
+endif(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
 
-INCLUDE(CheckIncludeFile)
-INCLUDE(CheckLibraryExists)
-INCLUDE(CheckCSourceCompiles)
+include(CheckIncludeFile)
+include(CheckLibraryExists)
+include(CheckCSourceCompiles)
 
+## SDL is needed by extra
 find_package(SDL REQUIRED)
-include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
-include_directories(${SDL_INCLUDE_DIR}) #hw
-include_directories(${LUA_INCLUDE_DIR}) #hw
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src) ##
+include_directories(${SDL_INCLUDE_DIR}) ##
+include_directories(${LUA_INCLUDE_DIR}) ##
 
-IF(MACOSX)
+if(MACOSX)
     # Fallback to older OS X on PowerPC to support wider range of systems...
-    IF(CMAKE_OSX_ARCHITECTURES MATCHES ppc)
-        ADD_DEFINITIONS(-DMAC_OS_X_VERSION_MIN_REQUIRED=1020)
-        SET(OTHER_LDFLAGS ${OTHER_LDFLAGS} " -mmacosx-version-min=10.2")
-    ENDIF(CMAKE_OSX_ARCHITECTURES MATCHES ppc)
+    if(CMAKE_OSX_ARCHITECTURES MATCHES ppc)
+        add_definitions(-DMAC_OS_X_VERSION_MIN_REQUIRED=1020)
+        set(OTHER_LDFLAGS ${OTHER_LDFLAGS} " -mmacosx-version-min=10.2")
+    endif(CMAKE_OSX_ARCHITECTURES MATCHES ppc)
 
     # Need these everywhere...
-    ADD_DEFINITIONS(-fno-common)
-    SET(OTHER_LDFLAGS ${OTHER_LDFLAGS} "-framework IOKit")
-ENDIF(MACOSX)
+    add_definitions(-fno-common)
+    find_library(iokit_framework NAMES IOKit)
+    list(APPEND OTHER_LDFLAGS ${iokit_framework})
+endif(MACOSX)
 
 # Add some gcc-specific command lines.
-IF(CMAKE_COMPILER_IS_GNUCC)
+if(CMAKE_COMPILER_IS_GNUCC)
     # Always build with debug symbols...you can strip it later.
-    ADD_DEFINITIONS(-g -pipe -Werror -fsigned-char)
+    add_definitions(-g -pipe -Werror -fsigned-char)
 
     # Stupid BeOS generates warnings in the system headers.
-    IF(NOT BEOS)
-        ADD_DEFINITIONS(-Wall)
-    ENDIF(NOT BEOS)
+    if(NOT BEOS)
+        add_definitions(-Wall)
+    endif(NOT BEOS)
 
     CHECK_C_SOURCE_COMPILES("
         #if ((defined(__GNUC__)) && (__GNUC__ >= 4))
@@ -70,31 +71,31 @@
         #endif
     " PHYSFS_IS_GCC4)
 
-    IF(PHYSFS_IS_GCC4)
+    if(PHYSFS_IS_GCC4)
         # Not supported on several operating systems at this time.
-        IF(NOT SOLARIS AND NOT WINDOWS)
-            ADD_DEFINITIONS(-fvisibility=hidden)
-        ENDIF(NOT SOLARIS AND NOT WINDOWS)
-    ENDIF(PHYSFS_IS_GCC4)
+        if(NOT SOLARIS AND NOT WINDOWS)
+            add_definitions(-fvisibility=hidden)
+        endif(NOT SOLARIS AND NOT WINDOWS)
+    endif(PHYSFS_IS_GCC4)
 
     # Don't use -rpath.
-    SET(CMAKE_SKIP_RPATH ON CACHE BOOL "Skip RPATH" FORCE)
-ENDIF(CMAKE_COMPILER_IS_GNUCC)
+    set(CMAKE_SKIP_RPATH ON CACHE BOOL "Skip RPATH" FORCE)
+endif(CMAKE_COMPILER_IS_GNUCC)
 
-IF(CMAKE_C_COMPILER_ID STREQUAL "SunPro")
-    ADD_DEFINITIONS(-erroff=E_EMPTY_TRANSLATION_UNIT)
-    ADD_DEFINITIONS(-xldscope=hidden)
-ENDIF(CMAKE_C_COMPILER_ID STREQUAL "SunPro")
+if(CMAKE_C_COMPILER_ID STREQUAL "SunPro")
+    add_definitions(-erroff=E_EMPTY_TRANSLATION_UNIT)
+    add_definitions(-xldscope=hidden)
+endif(CMAKE_C_COMPILER_ID STREQUAL "SunPro")
 
-IF(MSVC)
+if(MSVC)
     # VS.NET 8.0 got really really anal about strcpy, etc, which even if we
     #  cleaned up our code, zlib, etc still use...so disable the warning.
-    ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS=1)
-ENDIF(MSVC)
+    add_definitions(-D_CRT_SECURE_NO_WARNINGS=1)
+endif(MSVC)
+
 
 # Basic chunks of source code ...
-
-SET(LZMA_SRCS
+set(LZMA_SRCS
     src/lzma/C/7zCrc.c
     src/lzma/C/Archive/7z/7zBuffer.c
     src/lzma/C/Archive/7z/7zDecode.c
@@ -108,20 +109,29 @@
     src/lzma/C/Compress/Lzma/LzmaDecode.c
 )
 
-IF(BEOS)
+if(BEOS)
     # We add this explicitly, since we don't want CMake to think this
     #  is a C++ project unless we're on BeOS.
-    SET(PHYSFS_BEOS_SRCS src/platform_beos.cpp)
-    FIND_LIBRARY(BE_LIBRARY be)
-    FIND_LIBRARY(ROOT_LIBRARY root)
-    SET(OPTIONAL_LIBRARY_LIBS ${OPTIONAL_LIBRARY_LIBS} ${BE_LIBRARY} ${ROOT_LIBRARY})
-ENDIF(BEOS)
+    set(PHYSFS_BEOS_SRCS src/platform_beos.cpp)
+    find_library(BE_LIBRARY be)
+    find_library(ROOT_LIBRARY root)
+    set(optionAL_LIBRARY_LIBS ${optionAL_LIBRARY_LIBS} ${BE_LIBRARY} ${ROOT_LIBRARY})
+endif(BEOS)
+
+## extra functions needed by Hedgewars
+## TODO: maybe it's better to have them in a separate library?
+set(PHYSFS_HEDGE_SRCS
+    extras/physfsrwops.c
+    extras/physfslualoader.c
+    extras/hwpacksmounter.c
+    extras/physfsfgets.c
+)
 
 # Almost everything is "compiled" here, but things that don't apply to the
 #  build are #ifdef'd out. This is to make it easy to embed PhysicsFS into
 #  another project or bring up a new build system: just compile all the source
 #  code and #define the things you want.
-SET(PHYSFS_SRCS
+set(PHYSFS_SRCS
     src/physfs.c
     src/physfs_byteorder.c
     src/physfs_unicode.c
@@ -139,34 +149,30 @@
     src/archiver_wad.c
     src/archiver_zip.c
     src/archiver_iso9660.c
-    #custom files from Hedgewars
-    extras/physfsrwops.c
-    extras/physfslualoader.c
-    extras/hwpacksmounter.c
-    extras/physfsfgets.c
     ${PHYSFS_BEOS_SRCS}
+    ${PHYSFS_HEDGE_SRCS} ##
 )
 
 
 # platform layers ...
 
-IF(UNIX)
-    IF(BEOS)
-        SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
-        SET(PHYSFS_HAVE_THREAD_SUPPORT TRUE)
-        SET(HAVE_PTHREAD_H TRUE)
-    ELSE(BEOS)
+if(UNIX)
+    if(BEOS)
+        set(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
+        set(PHYSFS_HAVE_THREAD_SUPPORT TRUE)
+        set(HAVE_PTHREAD_H TRUE)
+    else(BEOS)
         CHECK_INCLUDE_FILE(sys/ucred.h HAVE_UCRED_H)
-        IF(HAVE_UCRED_H)
-            ADD_DEFINITIONS(-DPHYSFS_HAVE_SYS_UCRED_H=1)
-            SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
-        ENDIF(HAVE_UCRED_H)
+        if(HAVE_UCRED_H)
+            add_definitions(-DPHYSFS_HAVE_SYS_UCRED_H=1)
+            set(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
+        endif(HAVE_UCRED_H)
 
         CHECK_INCLUDE_FILE(mntent.h HAVE_MNTENT_H)
-        IF(HAVE_MNTENT_H)
-            ADD_DEFINITIONS(-DPHYSFS_HAVE_MNTENT_H=1)
-            SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
-        ENDIF(HAVE_MNTENT_H)
+        if(HAVE_MNTENT_H)
+            add_definitions(-DPHYSFS_HAVE_MNTENT_H=1)
+            set(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
+        endif(HAVE_MNTENT_H)
 
         # !!! FIXME: Solaris fails this, because mnttab.h implicitly
         # !!! FIXME:  depends on other system headers.  :(
@@ -177,387 +183,134 @@
             int main(int argc, char **argv) { return 0; }
         " HAVE_SYS_MNTTAB_H)
 
-        IF(HAVE_SYS_MNTTAB_H)
-            ADD_DEFINITIONS(-DPHYSFS_HAVE_SYS_MNTTAB_H=1)
-            SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
-        ENDIF(HAVE_SYS_MNTTAB_H)
+        if(HAVE_SYS_MNTTAB_H)
+            add_definitions(-DPHYSFS_HAVE_SYS_MNTTAB_H=1)
+            set(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
+        endif(HAVE_SYS_MNTTAB_H)
 
         CHECK_INCLUDE_FILE(pthread.h HAVE_PTHREAD_H)
-        IF(HAVE_PTHREAD_H)
-            SET(PHYSFS_HAVE_THREAD_SUPPORT TRUE)
-        ENDIF(HAVE_PTHREAD_H)
-    ENDIF(BEOS)
-ENDIF(UNIX)
+        if(HAVE_PTHREAD_H)
+            set(PHYSFS_HAVE_THREAD_SUPPORT TRUE)
+        endif(HAVE_PTHREAD_H)
+    endif(BEOS)
+endif(UNIX)
 
-IF(WINDOWS)
-    SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
-    SET(PHYSFS_HAVE_THREAD_SUPPORT TRUE)
-ENDIF(WINDOWS)
+if(WINDOWS)
+    set(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
+    set(PHYSFS_HAVE_THREAD_SUPPORT TRUE)
+endif(WINDOWS)
 
-IF(NOT PHYSFS_HAVE_CDROM_SUPPORT)
-    ADD_DEFINITIONS(-DPHYSFS_NO_CDROM_SUPPORT=1)
-    MESSAGE(WARNING " ***")
-    MESSAGE(WARNING " *** There is no CD-ROM support in this build!")
-    MESSAGE(WARNING " *** PhysicsFS will just pretend there are no discs.")
-    MESSAGE(WARNING " *** This may be fine, depending on how PhysicsFS is used,")
-    MESSAGE(WARNING " ***   but is this what you REALLY wanted?")
-    MESSAGE(WARNING " *** (Maybe fix CMakeLists.txt, or write a platform driver?)")
-    MESSAGE(WARNING " ***")
-ENDIF(NOT PHYSFS_HAVE_CDROM_SUPPORT)
+if(NOT PHYSFS_HAVE_CDROM_SUPPORT)
+    add_definitions(-DPHYSFS_NO_CDROM_SUPPORT=1)
+    message(WARNING " ***")
+    message(WARNING " *** There is no CD-ROM support in this build!")
+    message(WARNING " *** PhysicsFS will just pretend there are no discs.")
+    message(WARNING " *** This may be fine, depending on how PhysicsFS is used,")
+    message(WARNING " ***   but is this what you REALLY wanted?")
+    message(WARNING " *** (Maybe fix CMakeLists.txt, or write a platform driver?)")
+    message(WARNING " ***")
+endif(NOT PHYSFS_HAVE_CDROM_SUPPORT)
 
-IF(PHYSFS_HAVE_THREAD_SUPPORT)
-    ADD_DEFINITIONS(-D_REENTRANT -D_THREAD_SAFE)
-ELSE(PHYSFS_HAVE_THREAD_SUPPORT)
-    ADD_DEFINITIONS(-DPHYSFS_NO_THREAD_SUPPORT=1)
-    MESSAGE(WARNING " ***")
-    MESSAGE(WARNING " *** There is no thread support in this build!")
-    MESSAGE(WARNING " *** PhysicsFS will NOT be reentrant!")
-    MESSAGE(WARNING " *** This may be fine, depending on how PhysicsFS is used,")
-    MESSAGE(WARNING " ***   but is this what you REALLY wanted?")
-    MESSAGE(WARNING " *** (Maybe fix CMakeLists.txt, or write a platform driver?)")
-    MESSAGE(WARNING " ***")
-ENDIF(PHYSFS_HAVE_THREAD_SUPPORT)
+if(PHYSFS_HAVE_THREAD_SUPPORT)
+    add_definitions(-D_REENTRANT -D_THREAD_SAFE)
+else(PHYSFS_HAVE_THREAD_SUPPORT)
+    add_definitions(-DPHYSFS_NO_THREAD_SUPPORT=1)
+    message(WARNING " ***")
+    message(WARNING " *** There is no thread support in this build!")
+    message(WARNING " *** PhysicsFS will NOT be reentrant!")
+    message(WARNING " *** This may be fine, depending on how PhysicsFS is used,")
+    message(WARNING " ***   but is this what you REALLY wanted?")
+    message(WARNING " *** (Maybe fix CMakeLists.txt, or write a platform driver?)")
+    message(WARNING " ***")
+endif(PHYSFS_HAVE_THREAD_SUPPORT)
 
 
 # Archivers ...
 
-OPTION(PHYSFS_ARCHIVE_ZIP "Enable ZIP support" TRUE)
-IF(PHYSFS_ARCHIVE_ZIP)
-    ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_ZIP=1)
-ENDIF(PHYSFS_ARCHIVE_ZIP)
+option(PHYSFS_ARCHIVE_ZIP "Enable ZIP support" TRUE)
+if(PHYSFS_ARCHIVE_ZIP)
+    add_definitions(-DPHYSFS_SUPPORTS_ZIP=1)
+    set(PHYSFS_FEATURES "ZIP")
+endif(PHYSFS_ARCHIVE_ZIP)
 
-OPTION(PHYSFS_ARCHIVE_7Z "Enable 7zip support" FALSE)
-IF(PHYSFS_ARCHIVE_7Z)
-    ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_7Z=1)
-    # !!! FIXME: rename to 7z.c?
-    SET(PHYSFS_SRCS ${PHYSFS_SRCS} ${LZMA_SRCS})
-ENDIF(PHYSFS_ARCHIVE_7Z)
-
-OPTION(PHYSFS_ARCHIVE_GRP "Enable Build Engine GRP support" TRUE)
-IF(PHYSFS_ARCHIVE_GRP)
-    ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_GRP=1)
-ENDIF(PHYSFS_ARCHIVE_GRP)
+option(PHYSFS_ARCHIVE_7Z "Enable 7zip support" FALSE)
+if(PHYSFS_ARCHIVE_7Z)
+    add_definitions(-DPHYSFS_SUPPORTS_7Z=1)
+    list(APPEND PHYSFS_SRCS ${LZMA_SRCS})
+    set(PHYSFS_FEATURES "${PHYSFS_FEATURES} 7zip")
+endif(PHYSFS_ARCHIVE_7Z)
 
-OPTION(PHYSFS_ARCHIVE_WAD "Enable Doom WAD support" TRUE)
-IF(PHYSFS_ARCHIVE_WAD)
-    ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_WAD=1)
-ENDIF(PHYSFS_ARCHIVE_WAD)
+option(PHYSFS_ARCHIVE_GRP "Enable Build Engine GRP support" TRUE)
+if(PHYSFS_ARCHIVE_GRP)
+    add_definitions(-DPHYSFS_SUPPORTS_GRP=1)
+    set(PHYSFS_FEATURES "${PHYSFS_FEATURES} GRP")
+endif(PHYSFS_ARCHIVE_GRP)
 
-OPTION(PHYSFS_ARCHIVE_HOG "Enable Descent I/II HOG support" TRUE)
-IF(PHYSFS_ARCHIVE_HOG)
-    ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_HOG=1)
-ENDIF(PHYSFS_ARCHIVE_HOG)
+option(PHYSFS_ARCHIVE_WAD "Enable Doom WAD support" TRUE)
+if(PHYSFS_ARCHIVE_WAD)
+    add_definitions(-DPHYSFS_SUPPORTS_WAD=1)
+    set(PHYSFS_FEATURES "${PHYSFS_FEATURES} WAD")
+endif(PHYSFS_ARCHIVE_WAD)
 
-OPTION(PHYSFS_ARCHIVE_MVL "Enable Descent I/II MVL support" TRUE)
-IF(PHYSFS_ARCHIVE_MVL)
-    ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_MVL=1)
-ENDIF(PHYSFS_ARCHIVE_MVL)
+option(PHYSFS_ARCHIVE_HOG "Enable Descent I/II HOG support" TRUE)
+if(PHYSFS_ARCHIVE_HOG)
+    add_definitions(-DPHYSFS_SUPPORTS_HOG=1)
+    set(PHYSFS_FEATURES "${PHYSFS_FEATURES} HOG")
+endif(PHYSFS_ARCHIVE_HOG)
 
-OPTION(PHYSFS_ARCHIVE_QPAK "Enable Quake I/II QPAK support" TRUE)
-IF(PHYSFS_ARCHIVE_QPAK)
-    ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_QPAK=1)
-ENDIF(PHYSFS_ARCHIVE_QPAK)
+option(PHYSFS_ARCHIVE_MVL "Enable Descent I/II MVL support" TRUE)
+if(PHYSFS_ARCHIVE_MVL)
+    add_definitions(-DPHYSFS_SUPPORTS_MVL=1)
+    set(PHYSFS_FEATURES "${PHYSFS_FEATURES} MVL")
+endif(PHYSFS_ARCHIVE_MVL)
 
-OPTION(PHYSFS_ARCHIVE_ISO9660 "Enable ISO9660 support" TRUE)
-IF(PHYSFS_ARCHIVE_ISO9660)
-    ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_ISO9660=1)
-ENDIF(PHYSFS_ARCHIVE_ISO9660)
+option(PHYSFS_ARCHIVE_QPAK "Enable Quake I/II QPAK support" TRUE)
+if(PHYSFS_ARCHIVE_QPAK)
+    add_definitions(-DPHYSFS_SUPPORTS_QPAK=1)
+    set(PHYSFS_FEATURES "${PHYSFS_FEATURES} QPAK")
+endif(PHYSFS_ARCHIVE_QPAK)
 
-#as needed by Hedgewars configuration
-IF(WINDOWS)
-    OPTION(PHYSFS_BUILD_STATIC "Build static library" FALSE)
-    OPTION(PHYSFS_BUILD_SHARED "Build shared library" TRUE)
-    SET(OTHER_LDFLAGS ${OTHER_LDFLAGS} ${SDL_LIBRARY})
-ELSE(WINDOWS)
-    OPTION(PHYSFS_BUILD_STATIC "Build static library" TRUE)
-    OPTION(PHYSFS_BUILD_SHARED "Build shared library" FALSE)
-ENDIF(WINDOWS)
+option(PHYSFS_ARCHIVE_ISO9660 "Enable ISO9660 support" TRUE)
+if(PHYSFS_ARCHIVE_ISO9660)
+    add_definitions(-DPHYSFS_SUPPORTS_ISO9660=1)
+    set(PHYSFS_FEATURES "${PHYSFS_FEATURES} CD-ROM")
+endif(PHYSFS_ARCHIVE_ISO9660)
 
-IF(PHYSFS_BUILD_STATIC)
-    ADD_LIBRARY(physfs STATIC ${PHYSFS_SRCS})
-    SET_TARGET_PROPERTIES(physfs PROPERTIES OUTPUT_NAME "physfs")
-    SET(PHYSFS_LIB_TARGET physfs)
-    SET(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";physfs")
-ENDIF(PHYSFS_BUILD_STATIC)
+##as needed by Hedgewars configuration
+if(WINDOWS)
+    option(PHYSFS_BUILD_STATIC "Build static library" FALSE)
+    option(PHYSFS_BUILD_SHARED "Build shared library" TRUE)
+    list(APPEND OTHER_LDFLAGS ${SDL_LIBRARY})
+else(WINDOWS)
+    option(PHYSFS_BUILD_STATIC "Build static library" TRUE)
+    option(PHYSFS_BUILD_SHARED "Build shared library" FALSE)
+endif(WINDOWS)
 
-IF(PHYSFS_BUILD_SHARED)
-    ADD_LIBRARY(physfs SHARED ${PHYSFS_SRCS})
-    SET_TARGET_PROPERTIES(physfs PROPERTIES VERSION ${PHYSFS_VERSION})
-    SET_TARGET_PROPERTIES(physfs PROPERTIES SOVERSION ${PHYSFS_SOVERSION})
-    TARGET_LINK_LIBRARIES(physfs ${OPTIONAL_LIBRARY_LIBS} ${OTHER_LDFLAGS})
-    SET(PHYSFS_LIB_TARGET physfs)
-    SET(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";physfs")
-    INSTALL(TARGETS ${PHYSFS_INSTALL_TARGETS}
-            RUNTIME DESTINATION ${LIBRARY_OUTPUT_PATH})
-ENDIF(PHYSFS_BUILD_SHARED)
+if(PHYSFS_BUILD_STATIC)
+    add_library(physfs STATIC ${PHYSFS_SRCS})
+    set_target_properties(physfs PROPERTIES OUTPUT_NAME "physfs")
+endif(PHYSFS_BUILD_STATIC)
 
-IF(NOT PHYSFS_BUILD_SHARED AND NOT PHYSFS_BUILD_STATIC)
-    MESSAGE(FATAL "Both shared and static libraries are disabled!")
-ENDIF(NOT PHYSFS_BUILD_SHARED AND NOT PHYSFS_BUILD_STATIC)
+if(PHYSFS_BUILD_SHARED)
+    add_library(physfs SHARED ${PHYSFS_SRCS})
+    set_target_properties(physfs PROPERTIES VERSION ${PHYSFS_VERSION})
+    set_target_properties(physfs PROPERTIES SOVERSION ${PHYSFS_SOVERSION})
+    target_link_libraries(physfs ${optionAL_LIBRARY_LIBS} ${OTHER_LDFLAGS})
+    install(TARGETS physfs RUNTIME DESTINATION ${target_library_install_dir}) ##
+endif(PHYSFS_BUILD_SHARED)
+
+if(NOT PHYSFS_BUILD_SHARED AND NOT PHYSFS_BUILD_STATIC)
+    message(FATAL "Both shared and static libraries are disabled!")
+endif(NOT PHYSFS_BUILD_SHARED AND NOT PHYSFS_BUILD_STATIC)
 
 # CMake FAQ says I need this...
-IF(PHYSFS_BUILD_SHARED AND PHYSFS_BUILD_STATIC)
-    SET_TARGET_PROPERTIES(physfs PROPERTIES CLEAN_DIRECT_OUTPUT 1)
-ENDIF(PHYSFS_BUILD_SHARED AND PHYSFS_BUILD_STATIC)
-
-OPTION(PHYSFS_BUILD_TEST "Build stdio test program." FALSE)
-MARK_AS_ADVANCED(PHYSFS_BUILD_TEST)
-IF(PHYSFS_BUILD_TEST)
-    FIND_PATH(READLINE_H readline/readline.h)
-    FIND_PATH(HISTORY_H readline/history.h)
-    IF(READLINE_H AND HISTORY_H)
-        FIND_LIBRARY(CURSES_LIBRARY NAMES curses ncurses)
-        SET(CMAKE_REQUIRED_LIBRARIES ${CURSES_LIBRARY})
-        FIND_LIBRARY(READLINE_LIBRARY readline)
-        IF(READLINE_LIBRARY)
-            SET(HAVE_SYSTEM_READLINE TRUE)
-            SET(TEST_PHYSFS_LIBS ${TEST_PHYSFS_LIBS} ${READLINE_LIBRARY} ${CURSES_LIBRARY})
-            INCLUDE_DIRECTORIES(${READLINE_H} ${HISTORY_H})
-            ADD_DEFINITIONS(-DPHYSFS_HAVE_READLINE=1)
-        ENDIF(READLINE_LIBRARY)
-    ENDIF(READLINE_H AND HISTORY_H)
-    ADD_EXECUTABLE(test_physfs test/test_physfs.c)
-    TARGET_LINK_LIBRARIES(test_physfs ${PHYSFS_LIB_TARGET} ${TEST_PHYSFS_LIBS} ${OTHER_LDFLAGS})
-    SET(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";test_physfs")
-ENDIF(PHYSFS_BUILD_TEST)
+if(PHYSFS_BUILD_SHARED AND PHYSFS_BUILD_STATIC)
+    set_target_properties(physfs PROPERTIES CLEAN_DIRECT_OUTPUT 1)
+endif(PHYSFS_BUILD_SHARED AND PHYSFS_BUILD_STATIC)
 
 
-# Scripting language bindings...
-
-#CMake's SWIG support is basically useless.
-#FIND_PACKAGE(SWIG)
-
-OPTION(PHYSFS_BUILD_SWIG "Build ${_LANG} bindings." FALSE)
-MARK_AS_ADVANCED(PHYSFS_BUILD_SWIG)
-
-FIND_PROGRAM(SWIG swig DOC "Path to swig command line app: http://swig.org/")
-IF(NOT SWIG)
-    MESSAGE(STATUS "SWIG not found. You won't be able to build scripting language bindings.")
-ELSE(NOT SWIG)
-    MARK_AS_ADVANCED(SWIG)
-    IF(DEFINED CMAKE_BUILD_TYPE)
-        IF((NOT CMAKE_BUILD_TYPE STREQUAL "") AND (NOT CMAKE_BUILD_TYPE STREQUAL "Debug"))
-            IF(CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
-                SET(SWIG_OPT_CFLAGS "-small")
-            ELSE(CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
-                SET(SWIG_OPT_CFLAGS "-O")
-            ENDIF(CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
-        ENDIF((NOT CMAKE_BUILD_TYPE STREQUAL "") AND (NOT CMAKE_BUILD_TYPE STREQUAL "Debug"))
-    ENDIF(DEFINED CMAKE_BUILD_TYPE)
-
-    SET(SWIG_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/physfs-swig-bindings")
-
-    MACRO(CONFIGURE_SWIG_BINDING _LANG _INSTALLPATH _EXTRAOUTPUTS _EXTRACFLAGS _EXTRALDFLAGS)
-        STRING(TOUPPER "${_LANG}" _UPPERLANG)
-        STRING(TOLOWER "${_LANG}" _LOWERLANG)
-        SET(_TARGET "physfs-${_LOWERLANG}")
-        SET(_TARGETDIR "${SWIG_OUTPUT_DIR}/${_LOWERLANG}")
-
-        IF(NOT EXISTS "${_TARGETDIR}")
-            FILE(MAKE_DIRECTORY "${_TARGETDIR}")
-        ENDIF(NOT EXISTS "${_TARGETDIR}")
-
-        IF(PHYSFS_BUILD_${_UPPERLANG})
-            ADD_CUSTOM_COMMAND(
-                OUTPUT "${_TARGETDIR}/${_TARGET}.c" ${_EXTRAOUTPUTS}
-                MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/extras/physfs-swig.i"
-                COMMAND "${SWIG}"
-                ARGS ${SWIG_OPT_CFLAGS} -${_LOWERLANG} -outdir "${_TARGETDIR}" -o "${_TARGETDIR}/${_TARGET}.c" "${CMAKE_CURRENT_SOURCE_DIR}/extras/physfs-swig.i"
-                COMMENT "Generating ${_LANG} bindings..."
-            )
-
-            ADD_LIBRARY(${_TARGET} SHARED "${_TARGETDIR}/${_TARGET}.c")
-            TARGET_LINK_LIBRARIES(${_TARGET} ${PHYSFS_LIB_TARGET})
-            SET_TARGET_PROPERTIES(${_TARGET} PROPERTIES
-                COMPILE_FLAGS "${_EXTRACFLAGS}"
-                LINK_FLAGS "${_EXTRALDFLAGS}"
-                LIBRARY_OUTPUT_NAME "physfs"
-                LIBRARY_OUTPUT_DIRECTORY "${_TARGETDIR}"
-                CLEAN_DIRECT_OUTPUT 1
-            )
-            INSTALL(TARGETS ${_TARGET} LIBRARY DESTINATION "${_INSTALLPATH}")
-            MESSAGE(STATUS "${_LANG} bindings configured!")
-        ELSE(PHYSFS_BUILD_${_UPPERLANG})
-            MESSAGE(STATUS "Couldn't figure out ${_LANG} configuration. Skipping ${_LANG} bindings.")
-        ENDIF(PHYSFS_BUILD_${_UPPERLANG})
-    ENDMACRO(CONFIGURE_SWIG_BINDING)
-
-    MACRO(ADD_SCRIPT_BINDING_OPTION _VAR _LANG _DEFVAL)
-        SET(BUILDSWIGVAL ${_DEFVAL})
-        IF(NOT PHYSFS_BUILD_SWIG)
-            SET(BUILDSWIGVAL FALSE)
-        ENDIF(NOT PHYSFS_BUILD_SWIG)
-        OPTION(${_VAR} "Build ${_LANG} bindings." ${BUILDSWIGVAL})
-        MARK_AS_ADVANCED(${_VAR})
-    ENDMACRO(ADD_SCRIPT_BINDING_OPTION)
-
-    ADD_SCRIPT_BINDING_OPTION(PHYSFS_BUILD_PERL "Perl" TRUE)
-    ADD_SCRIPT_BINDING_OPTION(PHYSFS_BUILD_RUBY "Ruby" TRUE)
-ENDIF(NOT SWIG)
-
-IF(PHYSFS_BUILD_PERL)
-    MESSAGE(STATUS "Configuring Perl bindings...")
-    FIND_PROGRAM(PERL perl DOC "Path to perl command line app: http://perl.org/")
-    IF(NOT PERL)
-        MESSAGE(STATUS "Perl not found. You won't be able to build perl bindings.")
-        SET(PHYSFS_BUILD_PERL FALSE)
-    ENDIF(NOT PERL)
-    MARK_AS_ADVANCED(PERL)
-
-    MACRO(GET_PERL_CONFIG _KEY _VALUE)
-        IF(PHYSFS_BUILD_PERL)
-            MESSAGE(STATUS "Figuring out perl config value '${_KEY}' ...")
-            EXECUTE_PROCESS(
-                COMMAND ${PERL} -w -e "use Config; print \$Config{${_KEY}};"
-                RESULT_VARIABLE GET_PERL_CONFIG_RC
-                OUTPUT_VARIABLE ${_VALUE}
-            )
-            IF(NOT GET_PERL_CONFIG_RC EQUAL 0)
-                MESSAGE(STATUS "Perl executable ('${PERL}') reported failure: ${GET_PERL_CONFIG_RC}")
-                SET(PHYSFS_BUILD_PERL FALSE)
-            ENDIF(NOT GET_PERL_CONFIG_RC EQUAL 0)
-            IF(NOT ${_VALUE})
-                MESSAGE(STATUS "Perl executable ('${PERL}') didn't have a value for '${_KEY}'")
-                SET(PHYSFS_BUILD_PERL FALSE)
-            ENDIF(NOT ${_VALUE})
-
-            IF(PHYSFS_BUILD_PERL)
-                MESSAGE(STATUS "Perl says: '${${_VALUE}}'.")
-            ENDIF(PHYSFS_BUILD_PERL)
-        ENDIF(PHYSFS_BUILD_PERL)
-    ENDMACRO(GET_PERL_CONFIG)
-
-    # !!! FIXME: installsitearch might be the wrong location.
-    GET_PERL_CONFIG("archlibexp" PERL_INCLUDE_PATH)
-    GET_PERL_CONFIG("ccflags" PERL_CCFLAGS)
-    GET_PERL_CONFIG("ldflags" PERL_LDFLAGS)
-    GET_PERL_CONFIG("installsitearch" PERL_INSTALL_PATH)
+## removed install, language bindings and test program
+## simplified configuration output
 
-    # !!! FIXME: this test for Mac OS X is wrong.
-    IF(MACOSX)
-        GET_PERL_CONFIG("libperl" PERL_LIBPERL)
-        SET(TMPLIBPERL "${PERL_LIBPERL}")
-        STRING(REGEX REPLACE "^lib" "" TMPLIBPERL "${TMPLIBPERL}")
-        STRING(REGEX REPLACE "\\.so$" "" TMPLIBPERL "${TMPLIBPERL}")
-        STRING(REGEX REPLACE "\\.dylib$" "" TMPLIBPERL "${TMPLIBPERL}")
-        STRING(REGEX REPLACE "\\.dll$" "" TMPLIBPERL "${TMPLIBPERL}")
-        IF(NOT "${TMPLIBPERL}" STREQUAL "${PERL_LIBPERL}")
-            MESSAGE(STATUS "Stripped '${PERL_LIBPERL}' down to '${TMPLIBPERL}'.")
-            SET(PERL_LIBPERL "${TMPLIBPERL}")
-        ENDIF(NOT "${TMPLIBPERL}" STREQUAL "${PERL_LIBPERL}")
-        SET(PERL_LIBPERL "-l${PERL_LIBPERL}")
-    ENDIF(MACOSX)
-
-    CONFIGURE_SWIG_BINDING(Perl "${PERL_INSTALL_PATH}" "${SWIG_OUTPUT_DIR}/perl/physfs.pm" "\"-I${PERL_INCLUDE_PATH}/CORE\" ${PERL_CCFLAGS} -w" "\"-L${PERL_INCLUDE_PATH}/CORE\" ${PERL_LIBPERL} ${PERL_LDFLAGS}")
-    INSTALL(FILES "${SWIG_OUTPUT_DIR}/perl/physfs.pm" DESTINATION "${PERL_INSTALL_PATH}")
-    INSTALL(
-        FILES test/test_physfs.pl
-        DESTINATION bin
-        PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
-                    GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
-    )
-ENDIF(PHYSFS_BUILD_PERL)
-
-# !!! FIXME: lots of cut-and-paste from perl bindings.
-IF(PHYSFS_BUILD_RUBY)
-    MESSAGE(STATUS "Configuring Ruby bindings...")
-    FIND_PROGRAM(RUBY ruby DOC "Path to ruby command line app: http://ruby-lang.org/")
-    IF(NOT RUBY)
-        MESSAGE(STATUS "Ruby not found. You won't be able to build ruby bindings.")
-        SET(PHYSFS_BUILD_RUBY FALSE)
-    ENDIF(NOT RUBY)
-    MARK_AS_ADVANCED(RUBY)
-
-    MACRO(GET_RUBY_CONFIG _KEY _VALUE)
-        IF(PHYSFS_BUILD_RUBY)
-            MESSAGE(STATUS "Figuring out ruby config value '${_KEY}' ...")
-            EXECUTE_PROCESS(
-                COMMAND ${RUBY} -e "require 'rbconfig'; puts RbConfig::CONFIG['${_KEY}'];"
-                RESULT_VARIABLE GET_RUBY_CONFIG_RC
-                OUTPUT_VARIABLE ${_VALUE}
-                OUTPUT_STRIP_TRAILING_WHITESPACE
-            )
-            IF(NOT GET_RUBY_CONFIG_RC EQUAL 0)
-                MESSAGE(STATUS "Ruby executable ('${RUBY}') reported failure: ${GET_RUBY_CONFIG_RC}")
-                SET(PHYSFS_BUILD_RUBY FALSE)
-            ENDIF(NOT GET_RUBY_CONFIG_RC EQUAL 0)
-            IF(NOT ${_VALUE})
-                MESSAGE(STATUS "Ruby executable ('${RUBY}') didn't have a value for '${_KEY}'")
-                SET(PHYSFS_BUILD_RUBY FALSE)
-            ENDIF(NOT ${_VALUE})
-
-            IF(PHYSFS_BUILD_RUBY)
-                MESSAGE(STATUS "Ruby says: '${${_VALUE}}'.")
-            ENDIF(PHYSFS_BUILD_RUBY)
-        ENDIF(PHYSFS_BUILD_RUBY)
-    ENDMACRO(GET_RUBY_CONFIG)
+message(STATUS "PhysicsFS will build with ${PHYSFS_FEATURES} support")
 
-    GET_RUBY_CONFIG("archdir" RUBY_INCLUDE_PATH)
-    GET_RUBY_CONFIG("CFLAGS" RUBY_CCFLAGS)
-    GET_RUBY_CONFIG("LDFLAGS" RUBY_LDFLAGS)
-    GET_RUBY_CONFIG("sitearchdir" RUBY_INSTALL_PATH)
-    GET_RUBY_CONFIG("LIBRUBYARG_SHARED" RUBY_LIBRUBY)
-    GET_RUBY_CONFIG("libdir" RUBY_LIBDIR)
-
-    CONFIGURE_SWIG_BINDING(Ruby "${RUBY_INSTALL_PATH}" "" "\"-I${RUBY_INCLUDE_PATH}\" ${RUBY_CCFLAGS} -w" "\"-L${RUBY_LIBDIR}\" ${RUBY_LIBRUBY} ${RUBY_LDFLAGS}")
-    SET_TARGET_PROPERTIES(physfs-ruby PROPERTIES PREFIX "")
-    INSTALL(
-        FILES test/test_physfs.rb
-        DESTINATION bin
-        PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
-                    GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
-    )
-ENDIF(PHYSFS_BUILD_RUBY)
-
-
-#INSTALL(TARGETS ${PHYSFS_INSTALL_TARGETS}
-#        RUNTIME DESTINATION bin
-#        LIBRARY DESTINATION lib${LIB_SUFFIX}
-#        ARCHIVE DESTINATION lib${LIB_SUFFIX})
-#INSTALL(FILES src/physfs.h DESTINATION include)
-
-IF(UNIX)
-    SET(PHYSFS_TARBALL "${CMAKE_CURRENT_SOURCE_DIR}/../physfs-${PHYSFS_VERSION}.tar.gz")
-    ADD_CUSTOM_TARGET(
-        dist
-        hg archive -t tgz "${PHYSFS_TARBALL}"
-        WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
-        COMMENT "Building source tarball '${PHYSFS_TARBALL}'..."
-    )
-#    ADD_CUSTOM_TARGET(
-#        uninstall
-#        "${CMAKE_CURRENT_SOURCE_DIR}/extras/uninstall.sh"
-#        WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
-#        COMMENT "Uninstall the project..."
-#    )
-ENDIF(UNIX)
-
-MACRO(MESSAGE_BOOL_OPTION _NAME _VALUE)
-    IF(${_VALUE})
-        MESSAGE(STATUS "  ${_NAME}: enabled")
-    ELSE(${_VALUE})
-        MESSAGE(STATUS "  ${_NAME}: disabled")
-    ENDIF(${_VALUE})
-ENDMACRO(MESSAGE_BOOL_OPTION)
-
-MESSAGE(STATUS "PhysicsFS will build with the following options:")
-MESSAGE_BOOL_OPTION("ZIP support" PHYSFS_ARCHIVE_ZIP)
-MESSAGE_BOOL_OPTION("7zip support" PHYSFS_ARCHIVE_7Z)
-MESSAGE_BOOL_OPTION("GRP support" PHYSFS_ARCHIVE_GRP)
-MESSAGE_BOOL_OPTION("WAD support" PHYSFS_ARCHIVE_WAD)
-MESSAGE_BOOL_OPTION("HOG support" PHYSFS_ARCHIVE_HOG)
-MESSAGE_BOOL_OPTION("MVL support" PHYSFS_ARCHIVE_MVL)
-MESSAGE_BOOL_OPTION("QPAK support" PHYSFS_ARCHIVE_QPAK)
-MESSAGE_BOOL_OPTION("CD-ROM drive support" PHYSFS_HAVE_CDROM_SUPPORT)
-MESSAGE_BOOL_OPTION("Thread safety" PHYSFS_HAVE_THREAD_SUPPORT)
-MESSAGE_BOOL_OPTION("Build static library" PHYSFS_BUILD_STATIC)
-MESSAGE_BOOL_OPTION("Build shared library" PHYSFS_BUILD_SHARED)
-MESSAGE_BOOL_OPTION("Build Perl bindings" PHYSFS_BUILD_PERL)
-MESSAGE_BOOL_OPTION("Build Ruby bindings" PHYSFS_BUILD_RUBY)
-MESSAGE_BOOL_OPTION("Build stdio test program" PHYSFS_BUILD_TEST)
-IF(PHYSFS_BUILD_TEST)
-    MESSAGE_BOOL_OPTION("  Use readline in test program" HAVE_SYSTEM_READLINE)
-ENDIF(PHYSFS_BUILD_TEST)
-
-# end of CMakeLists.txt ...
-
Binary file misc/winutils/Hedgewars.lnk has changed
--- a/project_files/hedgewars.pro	Tue Dec 18 20:48:37 2012 +0400
+++ b/project_files/hedgewars.pro	Fri Jan 04 21:44:40 2013 +0400
@@ -27,7 +27,6 @@
     ../QTfrontend/ui/page/pagetraining.h \
     ../QTfrontend/ui/page/pageselectweapon.h \
     ../QTfrontend/ui/page/pagesingleplayer.h \
-    ../QTfrontend/ui/page/pagenettype.h \
     ../QTfrontend/ui/page/pageingame.h \
     ../QTfrontend/ui/page/pageadmin.h \
     ../QTfrontend/ui/page/pagescheme.h \
@@ -110,7 +109,8 @@
     ../QTfrontend/util/LibavInteraction.h \
     ../QTfrontend/util/FileEngine.h \
     ../QTfrontend/util/frontlibpoller.h \
-    ../QTfrontend/ui/dialog/bandialog.h
+    ../QTfrontend/ui/dialog/bandialog.h \
+    ../QTfrontend/ui/widget/keybinder.h
 
 
 SOURCES += ../QTfrontend/model/ammoSchemeModel.cpp \
@@ -123,7 +123,6 @@
     ../QTfrontend/ui/page/pageroomslist.cpp \
     ../QTfrontend/ui/page/pagemultiplayer.cpp \
     ../QTfrontend/ui/page/pagegamestats.cpp \
-    ../QTfrontend/ui/page/pagenettype.cpp \
     ../QTfrontend/ui/page/pageeditteam.cpp \
     ../QTfrontend/ui/page/pagenetgame.cpp \
     ../QTfrontend/ui/page/pagedata.cpp \
@@ -203,7 +202,8 @@
     ../QTfrontend/util/LibavInteraction.cpp \
     ../QTfrontend/util/FileEngine.cpp \
     ../QTfrontend/util/frontlibpoller.cpp \
-    ../QTfrontend/ui/dialog/bandialog.cpp
+    ../QTfrontend/ui/dialog/bandialog.cpp \
+    ../QTfrontend/ui/widget/keybinder.cpp
 
 
 TRANSLATIONS += ../share/hedgewars/Data/Locale/hedgewars_ar.ts \
--- a/share/CMakeLists.txt	Tue Dec 18 20:48:37 2012 +0400
+++ b/share/CMakeLists.txt	Fri Jan 04 21:44:40 2013 +0400
@@ -1,6 +1,6 @@
 add_subdirectory(hedgewars)
 
-if(APPLE OR CROSSAPPLE)
+if(APPLE)
     #needed for CFBundleVersion and CFBundleShortVersionString
         #should reuse the variables set in main CMakeLists.txt
     if(HGCOMMAND AND (EXISTS ${CMAKE_SOURCE_DIR}/.hg))
@@ -29,4 +29,4 @@
             DESTINATION ../Resources/)
     install(PROGRAMS "${hedgewars_SOURCE_DIR}/share/dsa_pub.pem"
             DESTINATION ../Resources/)
-endif(APPLE OR CROSSAPPLE)
+endif(APPLE)
--- a/share/hedgewars/Data/Maps/Basketball/map.lua	Tue Dec 18 20:48:37 2012 +0400
+++ b/share/hedgewars/Data/Maps/Basketball/map.lua	Fri Jan 04 21:44:40 2013 +0400
@@ -1,6 +1,6 @@
 -- Hedgewars - Basketball for 2+ Players
 
-loadfile(GetDataPath() .. "Scripts/Locale.lua")()
+HedgewarsScriptLoad("Scripts/Locale.lua")()
 
 local score = {[0] = 0, [1] = 0, [2] = 0, [3] = 0, [4] = 0, [5] = 0}
 
--- a/share/hedgewars/Data/Maps/CTF_Blizzard/map.lua	Tue Dec 18 20:48:37 2012 +0400
+++ b/share/hedgewars/Data/Maps/CTF_Blizzard/map.lua	Fri Jan 04 21:44:40 2013 +0400
@@ -91,7 +91,7 @@
 -- add support for more players
 -- re-enable sudden death, but set water rise to 0
 
-loadfile(GetDataPath() .. "Scripts/Locale.lua")()
+HedgewarsScriptLoad("Scripts/Locale.lua")()
 
 ---------------------------------------------------------------
 ----------lots of bad variables and things
--- a/share/hedgewars/Data/Maps/Control/map.lua	Tue Dec 18 20:48:37 2012 +0400
+++ b/share/hedgewars/Data/Maps/Control/map.lua	Fri Jan 04 21:44:40 2013 +0400
@@ -49,7 +49,7 @@
 --script begins
 -----------------
 
-loadfile(GetDataPath() .. "Scripts/Locale.lua")()
+HedgewarsScriptLoad("Scripts/Locale.lua")()
 
 ---------------------------------------------------------------
 ----------lots of bad variables and things
--- a/share/hedgewars/Data/Maps/Knockball/map.lua	Tue Dec 18 20:48:37 2012 +0400
+++ b/share/hedgewars/Data/Maps/Knockball/map.lua	Fri Jan 04 21:44:40 2013 +0400
@@ -1,6 +1,6 @@
 -- Hedgewars - Knockball for 2+ Players
 
-loadfile(GetDataPath() .. "Scripts/Locale.lua")()
+HedgewarsScriptLoad("Scripts/Locale.lua")()
 
 local score = {[0] = 0, [1] = 0, [2] = 0, [3] = 0, [4] = 0, [5] = 0}
 
Binary file share/hedgewars/Data/Maps/ShoppaKing/map.png has changed
Binary file share/hedgewars/Data/Maps/ShoppaKing/map.xcf has changed
--- a/share/hedgewars/Data/Maps/TrophyRace/map.lua	Tue Dec 18 20:48:37 2012 +0400
+++ b/share/hedgewars/Data/Maps/TrophyRace/map.lua	Fri Jan 04 21:44:40 2013 +0400
@@ -1,6 +1,6 @@
 -- Hedgewars - Roperace for 2+ Players
 
-loadfile(GetDataPath() .. "Scripts/Locale.lua")()
+HedgewarsScriptLoad("Scripts/Locale.lua")()
 
 -- store number of hedgehogs
 local numhhs = 0
Binary file share/hedgewars/Data/Maps/TrophyRace/map.png has changed
--- a/share/hedgewars/Data/Scripts/Locale.lua	Tue Dec 18 20:48:37 2012 +0400
+++ b/share/hedgewars/Data/Scripts/Locale.lua	Fri Jan 04 21:44:40 2013 +0400
@@ -1,11 +1,11 @@
 -- Library for localizing strings in lua scripts
 
-local lang = loadfile(GetUserDataPath() .. "Locale/" .. tostring(L) .. ".lua")
+local lang = HedgewarsScriptLoad("Locale/" .. tostring(L) .. ".lua")
 
 if lang ~= nil then
     lang()
 else
-    lang = loadfile(GetDataPath() .. "Locale/" .. tostring(L) .. ".lua")
+    lang = HedgewarsScriptLoad("Locale/" .. tostring(L) .. ".lua")
     if lang ~= nil then
         lang()
     end
--- a/share/hedgewars/Data/misc/CMakeLists.txt	Tue Dec 18 20:48:37 2012 +0400
+++ b/share/hedgewars/Data/misc/CMakeLists.txt	Fri Jan 04 21:44:40 2013 +0400
@@ -1,14 +1,9 @@
-if(DEFINED DATA_INSTALL_DIR)
-    set(HEDGEWARS_DATADIR ${DATA_INSTALL_DIR}
-)
-else()
-    set(HEDGEWARS_DATADIR ${CMAKE_INSTALL_PREFIX}/share/)
-endif()  
 
 if(UNIX AND NOT APPLE)
-configure_file(hwengine.desktop.in hwengine.desktop)
+    configure_file(hwengine.desktop.in hwengine.desktop)
+
+    file(GLOB miscfiles *.xml *.desktop)
+
+    install(FILES ${miscfiles} DESTINATION ${SHAREPATH}/Data/misc)
 endif()
 
-file(GLOB miscfiles *.xml *.desktop)
-
-install(FILES ${miscfiles} DESTINATION ${SHAREPATH}Data/misc)
--- a/share/hedgewars/Data/misc/hwengine.desktop.in	Tue Dec 18 20:48:37 2012 +0400
+++ b/share/hedgewars/Data/misc/hwengine.desktop.in	Fri Jan 04 21:44:40 2013 +0400
@@ -17,7 +17,7 @@
 GenericName[sv]=Hedgewarsmotorn, för att öppna demo- och sparfiler
 GenericName[da]=Kæmpende Pindsvin
 Icon=hedgewars.png
-Exec=${CMAKE_INSTALL_PREFIX}/bin/hwengine ${HEDGEWARS_DATADIR}/hedgewars/Data %f
+Exec=${CMAKE_INSTALL_PREFIX}/${target_binary_install_dir}/hwengine %f
 Path=/tmp
 Terminal=false
 StartupNotify=false
--- a/tools/CMakeLists.txt	Tue Dec 18 20:48:37 2012 +0400
+++ b/tools/CMakeLists.txt	Fri Jan 04 21:44:40 2013 +0400
@@ -29,13 +29,20 @@
     string(REGEX REPLACE "(.*)/include.*" "\\1" qt_base_dir "${QT_INCLUDE_DIR}")
 
     #remove the ";-framework Cocoa" from the SDL_LIBRARY variable
-    string(REGEX REPLACE "(.*);-.*" "\\1" sdl_dir "${SDL_LIBRARY}")
+    string(REGEX REPLACE "(.*);-.*" "\\1" sdl_library_only "${SDL_LIBRARY}")
 
     if(NOT NOPNG)
         #get the neme of the library (harmelss if it is static)
         string(REGEX REPLACE ".*/(.*)$" "\\1" PNG_LIBNAME "${PNG_LIBRARY}")
     endif()
 
+    set(frameworks_dir ${CMAKE_INSTALL_PREFIX}/${target_library_install_dir})
+    if(${BUILD_ENGINE_LIBRARY})
+        set(engine_full_path "${frameworks_dir}/${CMAKE_SHARED_LIBRARY_PREFIX}hwengine${CMAKE_SHARED_LIBRARY_SUFFIX}")
+    else()
+        set(engine_full_path "${CMAKE_INSTALL_PREFIX}/hwengine${CMAKE_EXECUTABLE_SUFFIX}")
+    endif()
+
     #this tool is present in qt 4.5 but only if you compile from sources
     #from qt 4.6 is present also in the binary version
     find_program(macdeployqt_executable NAMES macdeployqt macdeployqt-mac PATHS ${qt_base_dir}/bin)
--- a/tools/CreateMacBundle.cmake.in	Tue Dec 18 20:48:37 2012 +0400
+++ b/tools/CreateMacBundle.cmake.in	Fri Jan 04 21:44:40 2013 +0400
@@ -1,34 +1,34 @@
 message(STATUS "Performing standalone bundle creation...")
 
-execute_process(COMMAND ls ${frameworks_dir} RESULT_VARIABLE doBundle OUTPUT_QUIET ERROR_QUIET)
+execute_process(COMMAND stat ${frameworks_dir} RESULT_VARIABLE doBundle OUTPUT_QUIET ERROR_QUIET)
 execute_process(COMMAND mkdir -p ${frameworks_dir})
 # macdeployqt will convert safely any absolute path library for 'hedgewars'
-execute_process(COMMAND ${macdeployqt_executable} ${CMAKE_BINARY_DIR}/${bundle_name} OUTPUT_QUIET ERROR_QUIET)
+execute_process(COMMAND ${macdeployqt_executable} ${CMAKE_BINARY_DIR}/Hedgewars.app OUTPUT_QUIET ERROR_QUIET)
 
 if(NOT ${NOVIDEOREC})
     # but macdeployqt will not work for 'hwengine'; luckily the dylibs were already updated before
-    execute_process(COMMAND install_name_tool -change ${FFMPEG_LIBAVCODEC} @executable_path/../Frameworks/libavcodec.dylib ${CMAKE_BINARY_DIR}/${bundle_name}/Contents/MacOS/hwengine)
-    execute_process(COMMAND install_name_tool -change ${FFMPEG_LIBAVFORMAT} @executable_path/../Frameworks/libavformat.dylib ${CMAKE_BINARY_DIR}/${bundle_name}/Contents/MacOS/hwengine)
-    execute_process(COMMAND install_name_tool -change ${FFMPEG_LIBAVUTIL} @executable_path/../Frameworks/libavutil.dylib ${CMAKE_BINARY_DIR}/${bundle_name}/Contents/MacOS/hwengine)
+    execute_process(COMMAND install_name_tool -change ${FFMPEG_LIBAVCODEC} @executable_path/../Frameworks/libavcodec.dylib ${engine_full_path})
+    execute_process(COMMAND install_name_tool -change ${FFMPEG_LIBAVFORMAT} @executable_path/../Frameworks/libavformat.dylib ${engine_full_path})
+    execute_process(COMMAND install_name_tool -change ${FFMPEG_LIBAVUTIL} @executable_path/../Frameworks/libavutil.dylib ${engine_full_path})
 endif()
 
 if(NOT ${NOPNG})
     #same here, for libpng and hwengine, let's assume the version pulled by macdeployqt is the same
     #(yes libpng is pulled by macdeployqt even when NOVIDEOREC is active)
-    execute_process(COMMAND install_name_tool -change ${PNG_LIBRARY} @executable_path/../Frameworks/${PNG_LIBNAME} ${CMAKE_BINARY_DIR}/${bundle_name}/Contents/MacOS/hwengine)
+    execute_process(COMMAND install_name_tool -change ${PNG_LIBRARY} @executable_path/../Frameworks/${PNG_LIBNAME} ${engine_full_path})
 endif()
 
 if(doBundle EQUAL 1)
-    execute_process(COMMAND cp -pPR ${sdl_dir}          ${CMAKE_BINARY_DIR}/${frameworks_dir}/SDL.framework)
-    execute_process(COMMAND cp -pPR ${SDLIMAGE_LIBRARY} ${CMAKE_BINARY_DIR}/${frameworks_dir}/SDL_image.framework)
-    execute_process(COMMAND cp -pPR ${SDLNET_LIBRARY}   ${CMAKE_BINARY_DIR}/${frameworks_dir}/SDL_net.framework)
-    execute_process(COMMAND cp -pPR ${SDLTTF_LIBRARY}   ${CMAKE_BINARY_DIR}/${frameworks_dir}/SDL_ttf.framework)
-    execute_process(COMMAND cp -pPR ${SDLMIXER_LIBRARY} ${CMAKE_BINARY_DIR}/${frameworks_dir}/SDL_mixer.framework)
-    execute_process(COMMAND cp -pPR ${OGG_LIBRARY}      ${CMAKE_BINARY_DIR}/${frameworks_dir}/Ogg.framework)
-    execute_process(COMMAND cp -pPR ${VORBIS_LIBRARY}   ${CMAKE_BINARY_DIR}/${frameworks_dir}/Vorbis.framework)
+    execute_process(COMMAND cp -pPR ${sdl_library_only} ${frameworks_dir}/SDL.framework)
+    execute_process(COMMAND cp -pPR ${SDLIMAGE_LIBRARY} ${frameworks_dir}/SDL_image.framework)
+    execute_process(COMMAND cp -pPR ${SDLNET_LIBRARY}   ${frameworks_dir}/SDL_net.framework)
+    execute_process(COMMAND cp -pPR ${SDLTTF_LIBRARY}   ${frameworks_dir}/SDL_ttf.framework)
+    execute_process(COMMAND cp -pPR ${SDLMIXER_LIBRARY} ${frameworks_dir}/SDL_mixer.framework)
+    execute_process(COMMAND cp -pPR ${OGG_LIBRARY}      ${frameworks_dir}/Ogg.framework)
+    execute_process(COMMAND cp -pPR ${VORBIS_LIBRARY}   ${frameworks_dir}/Vorbis.framework)
 
     if(${SPARKLE_FOUND})
-        execute_process(COMMAND cp -pPR ${SPARKLE_LIBRARY} ${CMAKE_BINARY_DIR}/${frameworks_dir}/Sparkle.framework)
+        execute_process(COMMAND cp -pPR ${SPARKLE_LIBRARY} ${frameworks_dir}/Sparkle.framework)
     endif()
     message(STATUS "Bundle frameworks added")
 else()