diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 00000000..5b6cdaad
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,51 @@
+name: CI
+
+on: [push, pull_request]
+
+jobs:
+  ubuntu2004:
+    name: "Ubuntu 20.04"
+    runs-on: ubuntu-20.04
+    if: "!contains(github.event.head_commit.message, '[skip ci]')"
+    steps:
+    - uses: actions/checkout@v2
+    - name: dependencies
+      run: |
+        sudo apt-get install g++ libz-dev libboost-dev libwxgtk3.0-gtk3-dev swig libxy-dev liblua5.3-dev lua5.3
+        curl -LsS -o tests/catch.hpp https://github.com/philsquared/Catch/releases/download/v1.10.0/catch.hpp
+    - name: build
+      run: |
+        g++ --version
+        autoreconf -i
+        ./configure LUA=/usr/bin/lua5.3 LUA_INCLUDE=-I/usr/include/lua5.3 LUA_LIB=-llua5.3
+        make -j2
+        sudo make install
+    - name: test
+      run: |
+        make -j2 check
+        export LD_LIBRARY_PATH=/usr/local/lib
+        cfityk --version
+
+  clang39:
+    name: "Ubuntu 18.04, Clang 3.9"
+    runs-on: ubuntu-18.04
+    if: "!contains(github.event.head_commit.message, '[skip ci]')"
+    env:
+      CC: clang-3.9
+      CXX: clang++-3.9
+    steps:
+    - uses: actions/checkout@v2
+    - name: dependencies
+      run: |
+        sudo apt-get install clang-3.9 cmake libz-dev libxy-dev libboost-dev liblua5.2-dev lua5.2
+    - name: build
+      run: |
+        $CXX --version
+        cmake --version
+        cmake . -DDOWNLOAD_XYLIB=OFF -DDOWNLOAD_LUA=OFF -DDOWNLOAD_ZLIB=OFF
+        make VERBOSE=1
+        sudo make install
+    - name: test
+      run: |
+        export LD_LIBRARY_PATH=/usr/local/lib
+        cfityk --version
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 3153ff82..00000000
--- a/.travis.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-language: cpp
-compiler:
-  - gcc
-# - clang
-before_install:
-  - curl http://download.opensuse.org/repositories/home:/wojdyr/xUbuntu_12.04/Release.key | sudo apt-key add -
-  - echo 'deb http://download.opensuse.org/repositories/home:/wojdyr/xUbuntu_12.04/ /' | sudo tee -a /etc/apt/sources.list.d/obs.list
-  - sudo add-apt-repository ppa:teward/swig3.0 -y
-  - sudo apt-get update -qq
-  - sudo apt-get install -y libboost-dev liblua5.1-0-dev lua5.1
-  - sudo apt-get install -y --force-yes swig3.0
-  - sudo apt-get install -y --force-yes libxy-dev wxgtk-for-fityk-devel
-before_script:
-  -  curl -o tests/catch.hpp https://raw.githubusercontent.com/philsquared/Catch/master/single_include/catch.hpp
-  - autoreconf -i
-script: ./configure LUA=/usr/bin/lua5.1 LUA_INCLUDE=-I/usr/include/lua5.1 LUA_LIB=-llua5.1 SWIG=swig3.0 && make -j2 check
-
-branches:
-  only:
-    - master
-
-notifications:
-  email:
-    - wojdyr@gmail.com
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1c5a1728..62f99156 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,10 +1,18 @@
-# Use autotools-based build system instead if you can.
-# For now CMake limited to building libfityk and cfityk.
-# But it can automatically download and build Lua, xylib and zlib!
+# CMake build is limited to building libfityk, cfityk and Python module.
+# It is used only for building with fityk in Visual Studio, for example
+# on AppVeyor: https://ci.appveyor.com/project/wojdyr/fityk
+# All offical releases are prepared with autotools instead.
+
+# This build script cannot build GUI, has fewer options than the configure
+# script, but it can automatically download and build Lua, xylib and zlib!
 # You still need to have Boost libraries (headers only).
-# If they can't be found automatically, use -D BOOST_ROOT=C:\Path\to\boost
+# You may need to point to them with -D BOOST_ROOT=C:\Path\to\boost
+# If you downloaded the source from git you also need SWIG.
+# On Windows it can be installed with "cinst swig".
+# When using Microsoft Visual C++ Compiler for Python 2.7 add cmake option
+# -D CMAKE_BUILD_TYPE=Release (I haven't investigated why it was needed).
 
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.12)
 project(fityk C CXX)
 
 option(DOWNLOAD_LUA "Fetch Lua from its website" ON)
@@ -29,10 +37,6 @@ endif()
 
 include(ExternalProject)
 
-if (POLICY CMP0042)
-  cmake_policy(SET CMP0042 OLD)
-endif()
-
 if (MSVC)
   # C4244: '=' : conversion from 'double' to 'float', possible loss of data
   add_definitions( /wd4244 )
@@ -99,7 +103,6 @@ endif()
 include_directories(${LUA_INCLUDE_DIR})
 
 find_package(SWIG REQUIRED)
-#include(${SWIG_USE_FILE})
 
 if (BUILD_SHARED_LIBS)
   set(LIB_PREFIX ${CMAKE_SHARED_LIBRARY_PREFIX})
@@ -115,8 +118,8 @@ endif()
 
 if (DOWNLOAD_ZLIB)
   ExternalProject_Add(zlib
-    URL "http://zlib.net/zlib-1.2.8.tar.gz"
-    URL_MD5 44d667c142d7cda120332623eab69f40
+    URL "http://zlib.net/zlib-1.2.12.tar.gz"
+    URL_HASH SHA256=91844808532e5ce316b3c010929493c0244f3d37593afd6de04f71821d5136d9
     DOWNLOAD_DIR ${thirdparty_dir}
     SOURCE_DIR ${thirdparty_dir}/zlib
     BINARY_DIR ${CMAKE_BINARY_DIR}/zlib
@@ -157,7 +160,8 @@ if (DOWNLOAD_XYLIB)
   set(XY_LIBRARY "${THIRDPARTY_INSTALL}/lib/${LIB_PREFIX}xy${LIB_SUFFIX}")
   set(XY_INCLUDE_DIR "${THIRDPARTY_INSTALL}/include")
 else()
-  set(XY_LIBRARY xy)
+  find_path(XY_INCLUDE_DIR xylib/xylib.h HINTS ${CMAKE_INSTALL_PREFIX}/include)
+  find_library(XY_LIBRARY NAMES xy HINTS ${LIB_INSTALL_DIR})
 endif()
 include_directories("${XY_INCLUDE_DIR}")
 
@@ -197,7 +201,7 @@ fityk/data.cpp       fityk/lexer.cpp      fityk/runner.cpp     fityk/vm.cpp
 fityk/eparser.cpp    fityk/LMfit.cpp      fityk/settings.cpp   fityk/voigt.cpp
 fityk/f_fcjasym.cpp  fityk/logic.cpp      fityk/tplate.cpp
 fityk/fit.cpp        fityk/luabridge.cpp  fityk/transform.cpp
-fityk/cmpfit/mpfit.c
+fityk/cmpfit/mpfit.c fityk/root/background.cpp
 ${lua_runtime} ${lua_cxx})
 
 if (DOWNLOAD_XYLIB)
@@ -217,13 +221,27 @@ set_target_properties(fityk PROPERTIES SOVERSION 4 VERSION 4.0.0)
 add_executable(cfityk cli/gnuplot.cpp cli/main.cpp)
 target_link_libraries(cfityk fityk)
 
-#add_definitions(-DVERSION="1.3.0")
+#add_definitions(-DVERSION="1.3.1")
 set_target_properties (fityk cfityk PROPERTIES
-                       COMPILE_DEFINITIONS VERSION="1.3.0")
+                       COMPILE_DEFINITIONS VERSION="1.3.1")
 
 
-#swig_add_module(fityk python fityk/swig/fityk.i fityk/ui_api.h)
-#swig_link_libraries(fityk fityk ${PYTHON_LIBRARIES})
+if(MSVC90) # compiling with VS2008? It's most likely for Python 2.7.
+  set(Python_ADDITIONAL_VERSIONS 2.7)
+endif()
+find_package(PythonLibs)
+if (PYTHONLIBS_FOUND)
+  message(STATUS "Building extension for Python ${PYTHONLIBS_VERSION_STRING}")
+  include_directories(${PYTHON_INCLUDE_DIRS})
+  include(${SWIG_USE_FILE})
+  set_property(SOURCE fityk/swig/fityk.i PROPERTY SWIG_MODULE_NAME fityk)
+  swig_add_module(fityk python fityk/swig/fityk.i fityk/ui_api.h)
+  swig_link_libraries(fityk fityk ${PYTHON_LIBRARIES})
+  string(REGEX REPLACE "\\.[0-9]+$" ""
+         py_dir python${PYTHONLIBS_VERSION_STRING})
+  install(TARGETS ${SWIG_MODULE_fityk_REAL_NAME} DESTINATION ${py_dir})
+  install(FILES ${CMAKE_BINARY_DIR}/fityk.py DESTINATION ${py_dir})
+endif()
 
 
 install(TARGETS cfityk DESTINATION bin)
@@ -231,13 +249,15 @@ install(TARGETS fityk ${BUILT_LUA}
         RUNTIME DESTINATION bin
         ARCHIVE DESTINATION "${LIB_INSTALL_DIR}"
         LIBRARY DESTINATION "${LIB_INSTALL_DIR}")
+install(FILES fityk/fityk.h fityk/ui_api.h DESTINATION include/fityk)
 
 
 enable_testing()
 if (NOT EXISTS "${CMAKE_SOURCE_DIR}/tests/catch.hpp")
   message(STATUS "Downloading catch.hpp...")
+# the latest version of Catch 1.x does not compile with VS 2008
   file(DOWNLOAD
-       https://raw.githubusercontent.com/philsquared/Catch/master/single_include/catch.hpp
+       https://github.com/philsquared/Catch/releases/download/v1.9.5/catch.hpp
        "${CMAKE_SOURCE_DIR}/tests/catch.hpp" SHOW_PROGRESS
        STATUS download_status)
   list(GET download_status 0 status_code)
@@ -251,3 +271,14 @@ foreach(t gradient guess psvoigt num lua)
   target_link_libraries(test_${t} fityk catch)
   add_test(NAME ${t} COMMAND $<TARGET_FILE:test_${t}>)
 endforeach()
+
+# make sure that API examples can be compiled
+add_executable(hello_cc samples/hello.cc)
+target_link_libraries(hello_cc fityk)
+add_test(NAME "helloC++" COMMAND $<TARGET_FILE:hello_cc>)
+add_executable(hello_c samples/hello.c)
+if(UNIX)
+  find_library(MATH_LIBRARY m)
+endif()
+target_link_libraries(hello_c fityk ${MATH_LIBRARY})
+add_test(NAME "helloC" COMMAND $<TARGET_FILE:hello_c>)
diff --git a/Makefile.am b/Makefile.am
index 2cf1c924..106c0df2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -19,11 +19,13 @@ icon32dir = $(datadir)/icons/hicolor/32x32/apps
 iconscdir = $(datadir)/icons/hicolor/scalable/apps
 desktopdir = $(datadir)/applications
 mimepkgdir = $(datadir)/mime/packages
+appdatadir = $(datadir)/appdata
 
 dist_icon32_DATA = fityk.png
 dist_iconsc_DATA = fityk.svg
 dist_desktop_DATA = fityk.desktop
 dist_mimepkg_DATA = fityk.xml
+dist_appdata_DATA = fityk.appdata.xml
 
 # ---  cli/ ---
 cli_cfityk_SOURCES = cli/gnuplot.cpp cli/main.cpp cli/gnuplot.h
@@ -96,7 +98,13 @@ check-python:
 	PYTHONPATH=fityk/swig/.libs:$(srcdir)/fityk/swig/ \
 	   python -m unittest discover -s $(srcdir)/tests/
 
-check-scripts: check-cfityk check-python
+check-help:
+	echo '$$ fityk -h'   > $(srcdir)/doc/help-message.txt
+	wxgui/fityk -h 2>&1 | sed s/lt-fi/fi/ >> $(srcdir)/doc/help-message.txt
+	echo -e '\n$$ cfityk -h' >> $(srcdir)/doc/help-message.txt
+	cli/cfityk -h       >> $(srcdir)/doc/help-message.txt
+
+check-scripts: check-cfityk check-python check-help
 
 # --- doc/ ---
 
diff --git a/README.md b/README.md
index 0e15d4bb..1d8c1fd0 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@ Code:         https://github.com/wojdyr/fityk
 Manual:       http://fityk.readthedocs.org/en/latest/  
 Discussions:  http://groups.google.com/group/fityk-users/  
 Building from Source: Read the INSTALL file
-[![Build Status](https://travis-ci.org/wojdyr/fityk.svg?branch=master)](https://travis-ci.org/wojdyr/fityk)
-[![MSVC Build Status](https://ci.appveyor.com/api/projects/status/q2vmyiya4vril835?svg=true)](https://ci.appveyor.com/project/wojdyr/fityk)  
+[![GitHub CI](https://github.com/wojdyr/fityk/workflows/CI/badge.svg)](https://github.com/wojdyr/fityk/actions)
+[![AppVeyor CI](https://ci.appveyor.com/api/projects/status/q2vmyiya4vril835?svg=true)](https://ci.appveyor.com/project/wojdyr/fityk)  
 Citing in academic papers: [J. Appl. Cryst. 43, 1126 (2010)](http://dx.doi.org/10.1107/S0021889810030499) ([reprint](http://wojdyr.github.io/fityk-JAC-10-reprint.pdf))  
 Contact: wojdyr@gmail.com  
diff --git a/cli/gnuplot.cpp b/cli/gnuplot.cpp
index 75df46d2..fe5eb9da 100644
--- a/cli/gnuplot.cpp
+++ b/cli/gnuplot.cpp
@@ -61,7 +61,7 @@ void GnuPlot::fork_and_make_pipe()
         if (fd[0] > 2)
             close(fd[0]);
         //putenv("PAGER=");
-        execlp(GNUPLOT_PATH, GNUPLOT_PATH, /*"-",*/ NULL);
+        execlp(GNUPLOT_PATH, GNUPLOT_PATH, /*"-",*/ (char*) NULL);
         // if we are here, sth went wrong
         fprintf(stderr, "** Calling `" GNUPLOT_PATH
                         "' failed. Plotting disabled. **\n");
diff --git a/cli/main.cpp b/cli/main.cpp
index 5f565a95..b007cbbc 100644
--- a/cli/main.cpp
+++ b/cli/main.cpp
@@ -239,23 +239,12 @@ void main_loop()
 
 #endif //HAVE_LIBREADLINE
 
-
-
-void interrupt_handler (int /*signum*/)
-{
-    fityk::user_interrupt = 1;  // set flag to stop computations
-}
-
 } // anonymous namespace
 
 
-int main (int argc, char **argv)
+int main(int argc, char **argv)
 {
-#ifndef _WIN32
-    // setting Ctrl-C handler
-    if (signal (SIGINT, interrupt_handler) == SIG_IGN)
-        signal (SIGINT, SIG_IGN);
-#endif //_WIN32
+    interrupt_computations_on_sigint();
 
     // process command-line arguments
     bool exec_init_file = true;
@@ -336,10 +325,10 @@ int main (int argc, char **argv)
         if (!quit)
             main_loop();
     }
-    catch(ExitRequestedException) {
+    catch(const ExitRequestedException&) {
         fprintf(stderr, "\nbye...\n");
     }
-    catch (runtime_error const& e) {
+    catch (const runtime_error& e) {
         fprintf(stderr, "Error: %s\n", e.what());
         return 1;
     }
diff --git a/configure.ac b/configure.ac
index 219783b3..7bb0673e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -31,11 +31,6 @@ AC_ARG_ENABLE(nlopt, AS_HELP_STRING([--enable-nlopt],
 AC_ARG_WITH(readline, AS_HELP_STRING([--without-readline],
                        [do not use the GNU readline library for cfityk]))
 
-AC_ARG_WITH(options, AS_HELP_STRING([--with-options=OPTIONS],
-                       [options appended to CC, CXX and LD (e.g. -isysroot)]),
-            [UNIV_OPTION=$withval])
-
-
 AM_OPTIONS_WXCONFIG
 
 
@@ -110,8 +105,10 @@ AC_COMPILE_IFELSE(
   ])],
   [], [AC_MSG_ERROR([xylib >= 1.0 is not installed])])
 
-AS_IF([test x"$LUA52_FROM_SOURCE" != xyes], [
-    AX_PROG_LUA(5.1, 5.4)
+AS_IF([test x"$LUA52_FROM_SOURCE" = xyes], [
+    LUA_INCLUDE='-I$(top_srcdir)/fityk/lua52/src'
+  ], [
+    AX_PROG_LUA(5.1, 5.5)
     AX_LUA_HEADERS
     AX_LUA_LIBS
 ])
diff --git a/debian/changelog b/debian/changelog
index 6b86fadd..103ae274 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,12 @@
+fityk (1.3.1+git20220502.1.f0f19ea-1) UNRELEASED; urgency=low
+
+  * New upstream snapshot.
+  * Drop patch permit-gtk3.patch, present upstream.
+  * Drop patch float-approx.patch, present upstream.
+  * Drop patch update-sphinx.patch, present upstream.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Tue, 07 Jun 2022 18:29:59 -0000
+
 fityk (1.3.1-7) unstable; urgency=medium
 
   * Force compilation with c++-14 for compatibility with GCC-11
diff --git a/debian/patches/float-approx.patch b/debian/patches/float-approx.patch
deleted file mode 100644
index 3cfa7da0..00000000
--- a/debian/patches/float-approx.patch
+++ /dev/null
@@ -1,23 +0,0 @@
-From 9684b96e336ae7c926d70dbccf03f1618eee7433 Mon Sep 17 00:00:00 2001
-From: Marcin Wojdyr <wojdyr@gmail.com>
-Date: Mon, 25 Sep 2017 20:51:12 +0100
-Subject: [PATCH] blind fix for test failure
-
-https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=876776
----
- tests/psvoigt.cpp | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/tests/psvoigt.cpp b/tests/psvoigt.cpp
-index 0e676d6a..32cb1cdb 100644
---- a/tests/psvoigt.cpp
-+++ b/tests/psvoigt.cpp
-@@ -47,7 +47,7 @@ TEST_CASE("pseudo-voigt", "") {
-             double H = fik->calculate_expr("%pv.Height");
-             REQUIRE(H == height);
-             double ib = fik->calculate_expr("%pv.IB");
--            REQUIRE(ib == area/height);
-+            REQUIRE(ib == Approx(area/height));
-         }
-         const fityk::Func *f = fik->get_function("pv");
-         double at_ctr = f->value_at(center);
diff --git a/debian/patches/permit-gtk3.patch b/debian/patches/permit-gtk3.patch
deleted file mode 100644
index b7df05f2..00000000
--- a/debian/patches/permit-gtk3.patch
+++ /dev/null
@@ -1,20 +0,0 @@
-Description: Enable GTK3 to be used in building fityk
- Use of GTK3 is currently disabled in the upstream code but the GTK2 version
- of wx is going away soon, so it's time to enable the GTK3 build to see how
- it goes.
-Author: Stuart Prescott <stuart@debian.org>
-Bug: https://bugs.debian.org/933450
---- a/wxgui/app.cpp
-+++ b/wxgui/app.cpp
-@@ -8,11 +8,6 @@
- #include <wx/filesys.h>
- #include <wx/tooltip.h>
- 
--#ifdef __WXGTK3__
--#error "Not everything is working with wxGTK3. Use default wxGTK instead, " \
--       "based on GTK+2. If you want to test it, just remove this #error."
--#endif
--
- #include <stdio.h>
- #include <stdlib.h>
- #include <vector>
diff --git a/debian/patches/series b/debian/patches/series
index d1e64b2a..e69de29b 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,3 +0,0 @@
-permit-gtk3.patch
-float-approx.patch
-update-sphinx.patch
diff --git a/debian/patches/update-sphinx.patch b/debian/patches/update-sphinx.patch
deleted file mode 100644
index 21ad68cb..00000000
--- a/debian/patches/update-sphinx.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-From ab4c3d63f9db6e93b8cb7521c5619737a86c3405 Mon Sep 17 00:00:00 2001
-From: Marcin Wojdyr <wojdyr@gmail.com>
-Date: Sat, 16 Jan 2021 19:44:06 +0100
-Subject: [PATCH] update sphinx
-
-the warning in sphinx 3.0.3 was:
-RemovedInSphinx40Warning: app.add_lexer() API changed;
-Please give lexer class instead instance
----
- doc/conf.py      | 2 +-
- doc/fityk_ext.py | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/doc/conf.py b/doc/conf.py
-index 3198a0a8..af917f9f 100644
---- a/doc/conf.py
-+++ b/doc/conf.py
-@@ -1,6 +1,6 @@
- # -*- coding: utf-8 -*-
- 
--needs_sphinx = '1.5'
-+needs_sphinx = '3.0'
- 
- import sys, os
- sys.path.append(os.path.abspath('.'))
-diff --git a/doc/fityk_ext.py b/doc/fityk_ext.py
-index 3da2b262..208af0fe 100644
---- a/doc/fityk_ext.py
-+++ b/doc/fityk_ext.py
-@@ -47,7 +47,7 @@ def role_ftype(name, rawtext, text, lineno, inliner, options={}, content=[]):
-     return [node], []
- 
- def setup(app):
--    app.add_lexer('fityk', FitykLexer());
-+    app.add_lexer('fityk', FitykLexer);
-     app.connect('doctree-read', doctree_read)
-     app.add_role('ftype', role_ftype)
- 
--- 
-2.30.2
-
diff --git a/doc/Makefile b/doc/Makefile
index a92407ed..2b085a2a 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -3,7 +3,7 @@
 
 SPHINX = sphinx-build -a -d ./doctrees/
 
-html: *.rst fitheme/* fitheme/static/* conf.py
+html: *.rst fitheme/* fitheme/static/* conf.py help-message.txt
 	$(SPHINX) -b html . html
 	rm -f html/objects.inv html/.buildinfo
 
@@ -20,6 +20,6 @@ website:
 	BUILD_WEBSITE=1 $(SPHINX) -b html -Awebsite=1 . web
 	cp screenshots/fityk-1.0.1-osx-so.png web/_images/
 	rm -f web/objects.inv web/.buildinfo
-	sed -i 's/&mdash; Fityk ..... manual//' web/index.html web/screens.html
+	sed -i 's/&#8212; Fityk ..... manual//' web/index.html web/screens.html
 
 .PHONY: pdf website
diff --git a/doc/conf.py b/doc/conf.py
index 0e582a4d..8f1847d7 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 
-needs_sphinx = '1.5'
+needs_sphinx = '3.0'
 
 import sys, os
 sys.path.append(os.path.abspath('.'))
@@ -11,7 +11,7 @@ exclude_patterns = ['html', 'latex']
 if not os.getenv('BUILD_WEBSITE'):
     exclude_patterns += ['index.rst', 'screens.rst']
 
-if os.getenv('READTHEDOCS'):
+if os.getenv('READTHEDOCS') and 'epub' not in sys.argv:
     # RTD works better with index.html
     html_additional_pages = { 'index': '_build/html/fityk-manual.html' }
 
@@ -39,15 +39,12 @@ html_theme_options = {
     'website': 'http://fityk.nieto.pl/',
     'wiki': 'https://github.com/wojdyr/fityk/wiki',
 }
-if os.getenv('BUILD_WEBSITE'):
-    html_theme_options['analytics_id'] = 'UA-20519098-2'
 html_sidebars = { 'index': [], 'screens': [], '**': ['side.html'] }
 html_title = 'Fityk %s manual' % version
 html_short_title = 'Manual'
 html_favicon = 'fityk.ico'
 html_static_path = ['fityk-logo.png', 'img/mouse16.png']
 html_last_updated_fmt = '%Y-%m-%d'
-html_use_smartypants = True
 html_use_modindex = False
 html_use_index = False
 #html_add_permalinks = False
@@ -114,10 +111,10 @@ latex_keep_old_macro_names = False
 # determine vertical alignment of the math PNGs
 imgmath_use_preview = True
 
-dl_dir = 'http://fityk.nieto.pl/subscribers/'
+dl_dir = 'https://github.com/wojdyr/fityk/releases/download/v%s/' % version
 dl_prefix = 'fityk-%s' % version
 extlinks = {
     'wiki': ('https://github.com/wojdyr/fityk/wiki/%s', ''),
-    'subscribers_download': (dl_dir + dl_prefix + '%s', dl_prefix),
+    'github_download': (dl_dir + dl_prefix + '%s', dl_prefix),
     }
 
diff --git a/doc/data.rst b/doc/data.rst
index feb064eb..35ebd947 100644
--- a/doc/data.rst
+++ b/doc/data.rst
@@ -29,7 +29,7 @@ where
 - *dataslot* should be replaced with ``@0``, unless many datasets
   are to be used simultaneously (for details see: :ref:`multidata`),
 
-- *xcol*, *ycol*, *scol* (supported only in text file) are columns
+- *xcol*, *ycol*, *scol* (supported only in text and CSV files) are columns
   corresponding to x, y and std. dev. of y.
   Column 0 means index of the point: 0 for the first point,
   1 for the second, etc.
@@ -47,19 +47,24 @@ If the filename contains blank characters, a semicolon or comma, it
 should be put inside single quotation marks (together with colon-separated
 indices, if any).
 
-Multiple y columns and/or blocks can be specified, see the examples below::
+A few examples should clarify it::
 
     @0 < foo.vms
-    @0 < foo.fii text first_line_header
-    @0 < foo.dat:1:4:: # x,y - 1st and 4th columns
-    @0 < foo.dat:1:3,4:: # load two dataset (with y in columns 3,4)
-    @0 < foo.dat:1:3..5:: # load three dataset (with y in columns 3,4,5)
-    @0 < foo.dat:1:4..6,2:: # load four dataset (y: 4,5,6,2)
-    @0 < foo.dat:1:2..:: # load 2nd and all the next columns as y
-    @0 < foo.dat:1:2:3: # read std. dev. of y from 3rd column
-    @0 < foo.dat:0:1:: # x - 0,1,2,..., y - first column
-    @0 < 'foo.dat:0:1::' # the same
-    @0 < foo.raw::::0,1 # load two first blocks of data (as one dataset)
+    @0 < 'foo.vms'  # filename can be quoted
+    @0 < foo.fii text first_line_header  # with filetype options
+    @0 < foo.csv:1:4::  # x,y - 1st and 4th columns
+    @0 < foo.csv:1:2:3:  # read std. dev. of y from 3rd column
+    @0 < foo.csv:0:1::  # x - index (0,1,2,...), y - first column
+    @0 < foo.raw::::0,1  # load two first blocks of data (as one dataset)
+
+You may also specify multiple *y* columns.
+It will load each *x*/*y* pair as a separate dataset.
+In this case you need to use ``@+ < ...`` (``@+`` denotes new dataslot)::
+
+    @+ < foo.csv:1:3,4:: # load two dataset (with y in columns 3,4)
+    @+ < foo.csv:1:3..5:: # load three dataset (with y in columns 3,4,5)
+    @+ < foo.csv:1:4..6,2:: # load four dataset (y: 4,5,6,2)
+    @+ < foo.csv:1:2..:: # load 2nd and all the next columns as y
 
 Information about loaded data can be obtained with::
 
@@ -72,9 +77,15 @@ text
     ASCII text, multicolumn numeric data.
     The details are given in the next section.
 
+csv
+    CSV or TSV file. Similar to text but supports quoted (``"``) values
+    and uses different heuristic to interpret ambiguous cases.
+
 dbws
-    format used by DBWS (program for Rietveld analysis)
-    and DMPLOT.
+    format used by DBWS (program for Rietveld analysis) and DMPLOT.
+
+canberra_cnf
+    Canberra CNF format
 
 cpi
     Sietronics Sieray CPI format
@@ -106,6 +117,7 @@ spe
 pdcif
     CIF for powder diffraction
 
+And a few others.
 The full list is available at: http://xylib.sourceforge.net/.
 
 Reading Text Files
@@ -625,11 +637,24 @@ and functions:
     Calculates Shirley background
     (useful in X-ray photoelectron spectroscopy).
 
+``snip_bg(@n, window_width, direction, filter_order, estimate_compton)``
+    Calculates the spectrum background applying a Sensitive Nonlinear Iterative Peak clipping algorithm (SNIP) (useful in gamma-ray spectroscopy).
+    This SNIP algorithm is taken from the `TSpectrum <https://root.cern.ch/doc/v608/classTSpectrum.html>`_ class of `ROOT <http://root.cern.ch>`_.
+    It requires the parameters:
+    1. ``window_width``: maximal width of clipping window;
+    2. ``direction``:  direction of change of clipping window, if it is a positive number the window will be increasing;
+    3. ``filter_order``:  order of clipping filter, possible values are 2, 4, 6 or 8;
+    4. ``estimate_compton``:  if a positive number the algorithm will try to estimate the Compton edge.
+    Active points are modified according to the SNIP algorithm.
+    Inactive points are left as they are, assuming that they are already considered background.
+    Subtracting the calculated background from the initial spectrum gives zero in all inactive points.
+
 Examples::
 
   @+ = @0 # duplicate the dataset
   @+ = @0 and @1 # create a new dataset from @0 and @1
   @0 = @0 - shirley_bg(@0) # remove Shirley background 
+  @0 = @0 - snip_bg(@0, 30, 1, 2, 0) # remove gamma background 
   @0 = @0 - @1 # subtract @1 from @0
   @0 = @0 - 0.28*@1 # subtract scaled dataset @1 from @0
 
diff --git a/doc/fitheme/layout.html b/doc/fitheme/layout.html
index 3cb2adf5..4cd77ac7 100644
--- a/doc/fitheme/layout.html
+++ b/doc/fitheme/layout.html
@@ -26,21 +26,4 @@
           rel="nofollow">{{ 'Edit on GitHub' }}</a>
     {%- endif %}
   </div>
-  {%- if theme_analytics_id %}
-    <script type="text/javascript">
-
-      var _gaq = _gaq || [];
-      _gaq.push(['_setAccount', '{{ theme_analytics_id }}']);
-      _gaq.push(['_setDomainName', 'none']);
-      _gaq.push(['_setAllowLinker', true]);
-      _gaq.push(['_trackPageview']);
-
-      (function() {
-        var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
-        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
-        var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
-      })();
-
-    </script>
-  {%- endif %}
 {%- endblock %}
diff --git a/doc/fitheme/theme.conf b/doc/fitheme/theme.conf
index b529b265..e21abb62 100644
--- a/doc/fitheme/theme.conf
+++ b/doc/fitheme/theme.conf
@@ -4,7 +4,6 @@ stylesheet = fitheme.css
 
 [options]
 github_blob =
-analytics_id =
 logo =
 website =
 wiki =
diff --git a/doc/fityk_ext.py b/doc/fityk_ext.py
index 3da2b262..208af0fe 100644
--- a/doc/fityk_ext.py
+++ b/doc/fityk_ext.py
@@ -47,7 +47,7 @@ def role_ftype(name, rawtext, text, lineno, inliner, options={}, content=[]):
     return [node], []
 
 def setup(app):
-    app.add_lexer('fityk', FitykLexer());
+    app.add_lexer('fityk', FitykLexer);
     app.connect('doctree-read', doctree_read)
     app.add_role('ftype', role_ftype)
 
diff --git a/doc/getstarted.rst b/doc/getstarted.rst
index 4be35080..b3efdb8d 100644
--- a/doc/getstarted.rst
+++ b/doc/getstarted.rst
@@ -14,14 +14,13 @@ That's how the :abbr:`GUI (Graphical User Interface)` looks like:
    :scale: 50
 
 The **main plot** can display data points, model that is to be fitted to the
-data and individual functions in the model. Use can configure what is displayed
+data and individual functions in the model. You can configure what is displayed
 and how (through :menuselection:`GUI --> Configure` or context menu).
 
 The **helper plot** shows how well the model fits the data.
 You may have one, two or no helper plots (:menuselection:`GUI --> Show`).
 By default, the plot shows the difference between the data and the model.
-It can also show weighted or cumulative difference,
-and a couple of other things.
+It can also show weighted or cumulative difference, and a couple of other things.
 
 The helper plot is also handy for zooming -- with left and middle
 mouse buttons. Selecting a horizontal span with the left button
@@ -47,7 +46,7 @@ buttons:
   i.e. for selecting regions of interest,
 
 * |mode-bg-icon| *baseline mode* -- manual baseline subtraction
-  (in may never need it),
+  (you may never need it),
 
 * |mode-add-icon| *add-peak mode* -- for placing peaks and other functions.
 
@@ -67,7 +66,7 @@ buttons:
    :alt: Add-Peak Mode
    :class: icon
 
-The status bar shows a hint what the mouse does in the current mode.
+The status bar shows a hint of what the mouse does in the current mode.
 
 Finally, the **input field** and the **output window** provide alternative,
 console-like way of interacting with the program.
@@ -85,7 +84,7 @@ Minimal Example
 Let us analyze a diffraction pattern of NaCl. Our goal is to determine
 the position of the center of the highest peak. It is needed for
 calculating the pressure under which the sample was measured, but this
-later detail in the processing is irrelevent for the time being.
+later detail in the processing is irrelevant for the time being.
 
 The data file used in this example is distributed with the program and
 can be found in the :file:`samples` directory.
@@ -141,14 +140,14 @@ and press |add-peak-icon|.
 
 Automatic peak detection works in this case, but if it wouldn't, you may
 set the initial peak position, height and width manually.
-Either with mouse in the *add-peak mode*, or with a command.
+Either with the mouse in the *add-peak mode*, or with a command.
 
 .. admonition:: CLI
 
    F += Gaussian(~60000, ~24.6, ~0.2)
 
-Parameters of an existing function can be changed in the sideber,
-or by dragging that little square handle attached to each function
+Parameters of an existing function can be changed in the sidebar,
+or by dragging that little circle handle attached to each function
 (you should see a handle at the top of your Gaussian).
 
 If the peaks/functions are not named explicitely (like in this example),
@@ -222,7 +221,7 @@ fitting, or writing results to a file.
 
 A sequence of commands written down in a file makes a script (macro),
 which can automate common tasks. Complex tasks may need to be programmed
-in a general-purpose language. That is why Fityk has embedded Lua interpreter
+in a general-purpose language. That is why Fityk has an embedded Lua interpreter
 (Lua is a lightweight programming language).
 It is also possible to use Fityk library from a program in Python, C, C++,
 Java, Ruby or Perl, and possibly from other languages supported by SWIG.
@@ -249,8 +248,8 @@ or a backslash can be used to continue a command in the next line::
   ... 'this'
   this
 
-If the user works simultaneously with multiple datasets, she can refer to
-a dataset using its number: the first dataset is ``@0``, the second -- ``@1``,
+If you want to work with multiple datasets simultaneously, you can refer to
+a dataset through its number: the first dataset is ``@0``, the second -- ``@1``,
 etc::
 
   =-> fit # perform fitting of the default dataset (the first one)
diff --git a/doc/help-message.txt b/doc/help-message.txt
new file mode 100644
index 00000000..c7fd7199
--- /dev/null
+++ b/doc/help-message.txt
@@ -0,0 +1,18 @@
+$ fityk -h
+Usage: fityk [-h] [-V] [--full-version] [-c <str>] [-g <str>] [-I] [-r] [script or data file...]
+  -h, --help        	show this help message
+  -V, --version     	output version information and exit
+  --full-version    	print version with additional info and exit
+  -c, --cmd=<str>   	script passed in as string
+  -g, --config=<str>	choose GUI configuration
+  -I, --no-init     	don't process $HOME/.fityk/init file
+  -r, --reorder     	reorder data (50.xy before 100.xy)
+
+$ cfityk -h
+Usage: cfityk [-h] [-V] [-c <str>] [script or data file...]
+  -h, --help            show this help message
+  -V, --version         output version information and exit
+  -c, --cmd=<str>       script passed in as string
+  -I, --no-init         don't process $HOME/.fityk/init file
+  -n, --no-plot         disable plotting (gnuplot)
+  -q, --quit            don't enter interactive shell
diff --git a/doc/index.rst b/doc/index.rst
index e64b2889..5d37aee3 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -39,7 +39,7 @@ and nonlinear **curve fitting**.
 
 Primarily used
 
-* by scientists (150+ citations_ per year)
+* by scientists_
   who analyse data from powder diffraction, chromatography,
   photoluminescence and photoelectron spectroscopy,
   infrared and Raman spectroscopy, and other experimental techniques,
@@ -49,9 +49,9 @@ Primarily used
 * to fit peaks -- bell-shaped functions (Gaussian, Lorentzian, Voigt,
   Pearson VII, bifurcated Gaussian, EMG, Doniach-Sunjic, etc.),
 
-but the program is suitable for fitting any curve to 2D (*x*,\ *y*) data.
+but it is suitable for fitting any curve to 2D (*x*,\ *y*) data.
 
-.. _citations: https://scholar.google.com/citations?view_op=view_citation&hl=en&citation_for_view=aCtDUBMAAAAJ:u5HHmVD_uO8C
+.. _scientists: https://scholar.google.com/scholar?cites=1686729773533771289
 
 .. _contents:
 
@@ -90,59 +90,28 @@ Features
 Download
 ========
 
-In an attempt to make this software self-sustaining and actively
-developed in the future,
-`new binaries </subscribers>`_ are available to subscribers only:
+|ico-win| MS Windows: :github_download:`-setup.exe`
 
-|ico-win| MS Windows: :subscribers_download:`-setup.exe`  $
+|ico-osx| Mac OS X (10.6 or later): :github_download:`-osx.zip`
 
-|ico-osx| Mac OS X (10.6 or later): :subscribers_download:`-osx.zip`  $
-
-|ico-tux| Linux: binary `RPM and deb packages </subscribers>`_
+|ico-tux| Linux: binary
+`RPM and deb packages <https://software.opensuse.org/download?project=home:wojdyr&package=fityk>`_
+(`files <https://download.opensuse.org/repositories/home://wojdyr/>`_)
 :smallfont:`for about 10 distros (incl. Ubuntu, Fedora, Suse), 32- and 64-bit.`
 
-.. raw:: html
-
-   <div class="subscr">
-
-Subscribers have access to all versions of the program and to e-mail support.
-The program can be installed on many computers and can be also used
-after the end of subscription.
-
-* `1 month subscription <https://sites.fastspring.com/nieto/instant/fityk-1M>`_: $115 (≈ €90)
-
-* `1 year subscription <https://sites.fastspring.com/nieto/instant/fityk-1Y>`_: $199 (≈ €150)
-
-* `2 years subscription <https://sites.fastspring.com/nieto/instant/fityk-2Y>`_: $299 (≈ €225)
-
-.. raw:: html
-
-   <div class="smallfont">
-
-Fityk is usually bought by companies and institutions.
-If you're a home user or a student in an institution that won't buy software
-for you - email wojdyr@gmail.com for info about discount.
-
-.. raw:: html
-
-    </div>
-    </div>
-
-
-Versions 0.9.8 and older are free:
-for `Windows <https://github.com/wojdyr/fityk/downloads>`_
-and Linux (Ubuntu PPA_ and RPMs from OBS_).
-
 Source code: `GitHub <https://github.com/wojdyr/fityk>`_
 (`releases <https://github.com/wojdyr/fityk/releases>`_)
 
+Installers for ver. 1.0+ used to be available to paid subscribers only.
+This made `version 0.9.8 <https://github.com/wojdyr/fityk/downloads>`_
+more popular than more recent releases.
+To change this situation the latest binaries are no longer
+`paywalled </subscribers>`_.
+The author is grateful to all people who supported Fityk with subscriptions.
+
 Version 1.3.1 was released on 2016-12-19
 (`changelog <https://github.com/wojdyr/fityk/raw/master/NEWS>`_).
-New version `notifications <http://fityk-announce.nieto.pl/>`_
-are delivered via email and feeds.
 
-.. _OBS: http://download.opensuse.org/repositories/home://wojdyr/
-.. _PPA: https://launchpad.net/~wojdyr/+archive/fityk
 .. |ico-win| image:: img/ico-win.png
 .. |ico-tux| image:: img/ico-tux.png
 .. |ico-osx| image:: img/ico-osx.png
@@ -196,14 +165,6 @@ or, if it already is in the list, in assigning higher priority to it.
        $("#features").show('slow');
        event.preventDefault();
      });
-
-  $('#download a[href*="/subscribers/"]').click(function(event){
-    event.preventDefault();
-    var reply = prompt("Your password, please.", "")
-    if (reply != null)
-      location.href = $(this).attr("href") + "?u=" + reply;
-  });
-
    });
    //--> </script>
 
diff --git a/doc/model.rst b/doc/model.rst
index 077ed772..c72a9250 100644
--- a/doc/model.rst
+++ b/doc/model.rst
@@ -519,7 +519,7 @@ UDFs can be defined in a few ways:
 - as a sum of already defined functions
   (see the ``GLSum`` example below),
 
-- as a splitted (bifurcated) function:
+- as a split (bifurcated) function:
   ``x <`` *expression* ``?`` *Function1(...)* ``:`` *Function2(...)*
   (see the ``SplitL`` example below).
 
diff --git a/doc/ref.rst b/doc/ref.rst
index d7e751c4..08a5450f 100644
--- a/doc/ref.rst
+++ b/doc/ref.rst
@@ -330,26 +330,9 @@ option, if given, and processes command line arguments:
 .. highlight:: none
 
 There are also other parameters to the CLI and GUI versions of the program.
-Option "-h" ("/h" on MS Windows) gives the full listing::
-
-    wojdyr@ubu:~/fityk/src$ ./fityk -h
-    Usage: fityk \[-h] \[-V] \[-c <str>] \[-I] \[-r] \[script or data file...]
-    -h, --help            show this help message
-    -V, --version         output version information and exit
-    -c, --cmd=<str>       script passed in as string
-    -g, --config=<str>    choose GUI configuration
-    -I, --no-init         don't process $HOME/.fityk/init file
-    -r, --reorder         reorder data (50.xy before 100.xy)
-
-
-    wojdyr@ubu:~/foo$ cfityk -h
-    Usage: cfityk \[-h] \[-V] \[-c <str>] \[script or data file...]
-    -h, --help            show this help message
-    -V, --version         output version information and exit
-    -c, --cmd=<str>       script passed in as string
-    -I, --no-init         don't process $HOME/.fityk/init file
-    -n, --no-plot         disable plotting (gnuplot)
-    -q, --quit            don't enter interactive shell
+Option "-h" ("/h" on MS Windows) gives the full listing:
+
+.. literalinclude:: help-message.txt
 
 The example of non-interactive using CLI version on Linux::
 
diff --git a/doc/script.rst b/doc/script.rst
index d39683ad..253cd4ad 100644
--- a/doc/script.rst
+++ b/doc/script.rst
@@ -1,3 +1,4 @@
+.. _scripts:
 
 Scripts
 #######
@@ -5,12 +6,16 @@ Scripts
 Working with Scripts
 ====================
 
-Scripts can be executed using the command::
+Fityk can run two kinds of scripts:
 
-    exec filename
+- Fityk scripts composed of the commands described in previous sections,
+- and Lua scripts (extension ``.lua``), in the Lua language.
 
-The file can be either a fityk script (usually with extension ``fit``),
-or a Lua script (extension ``lua``).
+Scripts are executed using the `exec` command::
+
+    exec file1.fit
+    exec file2.lua
+    exec file3.fit.gz  # read script compressed with gzip
 
 .. note::
 
@@ -18,11 +23,7 @@ or a Lua script (extension ``lua``).
     It can also save all commands executed (directly or via GUI) in the session
     to a script (``info history > file.fit``).
 
-Since a Fityk script with all the data inside can be a large file,
-the files may be stored compressed and it is possible to directly read
-gzip-compressed fityk script (``.fit.gz``).
-
-Embedded Lua interpreter can execute any program in Lua 5.1.
+Embedded Lua interpreter can execute any program in Lua 5.2.
 One-liners can be run with command ``lua``::
 
     =-> lua print(_VERSION)
@@ -47,25 +48,29 @@ as Lua expressions, but this time the resulting string is executed
 as a fityk command::
 
     =-> = string.format("fit @%d", math.random(0,5))
-    fit 17
+    fit @4
     =-> exec= string.format("fit @%d", math.random(0,5))
     # fitting random dataset (useless example)
 
-The Lua interpreter in Fityk has defined global object ``F`` which
-enables interaction with the program::
+The embedded Lua interpreter interacts with the rest of the program
+through the global object ``F``::
 
     =-> = F:get_info("version")
     Fityk 1.2.1
 
-Now the first example that can be useful. For each dataset write output
-of the ``info peaks`` command to a file named after the data file,
-with appended ".out"::
+All methods of ``F`` are documented in the section :ref:`api`.
 
-    =-> @*: lua F:execute("info peaks >'%s.out'" % F:get_info("filename"))
+A few more examples.
 
-This and other methods of ``F`` are documented in the next section.
+Let's say that we work with a number of datasets, and for each of them
+we want to save output of the ``info peaks`` command to a file
+named *original-data-filename*\ .out. This can be done in one line::
 
-Here is an example of Lua-Fityk interactions:
+    =-> @*: lua F:execute("info peaks >'%s.out'" % F:get_info("filename"))
+
+Now a more complex script that would need to be put into a file
+(with extension ``.lua``) and run with ``exec``.
+:
 
 .. code-block:: lua
 
@@ -98,15 +103,24 @@ stopped, unless you catch the error:
         print("Error: " .. err)
     end
 
-The Lua interpreter was added in ver. 1.0.3. If you have any questions
-about it, feel free to ask.
-
-Older, but still supported way to automate Fityk is to prepare
-a stand-alone program that writes a valid fityk script to the standard output.
-To run such program and execute the output use command::
-
-    exec ! program [args...]
-
+The Lua interpreter was added in ver. 1.0.3. If you need help with writing
+Lua scripts - feel free to ask. Usage scenarios give us a better idea
+what functions should be available from the Lua interface.
+
+Fityk also has a simple mechanism to interact with external programs.
+It is useful mostly on Unix systems.  ``!`` runs a program,
+``exec!`` runs a program, reads its standard output and executes it
+as a Fityk script.
+Here is an example of using Unix utilties ``echo``, ``ls`` and ``head``
+to load the newest CIF file from the current directory::
+
+    =-> ! pwd
+    /home/wojdyr/fityk/data
+    =-> ! ls -t *.cif | head -1
+    lab6_3-2610-q.cif
+    =-> exec! echo "@+ < $(ls -t *.cif | head -1)"
+    > @+ < lab6_3-2610-q.cif
+    2300 points. No explicit std. dev. Set as sqrt(y)
 
 Fityk DSL
 =========
@@ -136,7 +150,7 @@ is equivalent to::
    =-> use @4
    =-> guess Voigt
 
-(except that the letter sets permenently default dataset to ``@4``.
+(except that the latter sets permenently default dataset to ``@4``.
 
 ``@*`` stands for all datasets, from ``@0`` to the last one.
 
@@ -333,6 +347,8 @@ and pseudo-parameters (%f.Area).
    NonblankString: (AllChars - (WhiteSpace | ";" | "#" ))*
    RestOfLine: AllChars*
 
+.. _api:
+
 Fityk library API
 =================
 
@@ -427,6 +443,20 @@ Data
     ``format``, ``options``. The meaning of these parameters is the same
     as described in :ref:`dataload`.
 
+    For example, due to limitations of the Fityk DSL a file with
+    the ``'`` character in the path must be loaded through Lua::
+
+        lua F:load([[Kat's file.dat]])
+
+    LoadSpec is used to specify also format of the file, columns, etc::
+
+        spec = fityk.LoadSpec('my.csv')
+        spec.x_col = 1
+        spec.y_col = 3
+        spec.format = 'csv'
+        spec.options = 'decimal_comma'
+        F:load(spec)
+
 .. method:: Fityk.load_data(d, xx, yy, sigmas [, title])
 
     Load data to @*d* slot. *xx* and *yy* must be numeric arrays
diff --git a/fityk.appdata.xml b/fityk.appdata.xml
new file mode 100644
index 00000000..eff154d3
--- /dev/null
+++ b/fityk.appdata.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<component type="desktop-application">
+	<id>pl.nieto.fityk</id>
+	<metadata_license>CC0-1.0</metadata_license>
+	<project_license>GPL-2.0-or-later</project_license>
+	<name>Fityk</name>
+	<summary>Non-linear curve fitting and data analysis</summary>
+
+	<description>
+		<p>Fityk [fi:tik] is a program for data processing and nonlinear curve fitting.</p>
+		<p>Primarily used:</p>
+		<ul>
+			<li>by scientists who analyse data from powder diffraction, chromatography, photoluminescence and photoelectron spectroscopy, infrared and Raman spectroscopy, and other experimental techniques,</li>
+			<li>to fit peaks – bell-shaped functions (Gaussian, Lorentzian, Voigt, Pearson VII, bifurcated Gaussian, EMG, Doniach-Sunjic, etc.),</li>
+		</ul>
+		<p>but it is suitable for fitting any curve to 2D (x,y) data.</p>
+	</description>
+
+	<categories>
+		<category>Science</category>
+		<category>DataVisualization</category>
+		<category>NumericalAnalysis</category>
+	</categories>
+
+	<launchable type="desktop-id">fityk.desktop</launchable>
+
+	<screenshots>
+		<screenshot type="default">
+			<caption>Main window with three plots</caption>
+			<image>https://alexpl.fedorapeople.org/AppData/fityk/screens/Screen00.png</image>
+		</screenshot>
+		<screenshot>
+			<caption>Automatic peak detection and fitting</caption>
+			<image>https://alexpl.fedorapeople.org/AppData/fityk/screens/Screen01.png</image>
+		</screenshot>
+		<screenshot>
+			<caption>Configuring the main plot</caption>
+			<image>https://alexpl.fedorapeople.org/AppData/fityk/screens/Screen02.png</image>
+		</screenshot>
+		<screenshot>
+			<caption>Spacing out stacked data sets</caption>
+			<image>https://alexpl.fedorapeople.org/AppData/fityk/screens/Screen03.png</image>
+		</screenshot>
+		<screenshot>
+			<caption>Subtracting the baseline of a curve</caption>
+			<image>https://alexpl.fedorapeople.org/AppData/fityk/screens/Screen04.png</image>
+		</screenshot>
+		<screenshot>
+			<caption>Plot and data preview when opening files</caption>
+			<image>https://alexpl.fedorapeople.org/AppData/fityk/screens/Screen05.png</image>
+		</screenshot>
+		<screenshot>
+			<caption>Fitting functions can be edited and custom ones added</caption>
+			<image>https://alexpl.fedorapeople.org/AppData/fityk/screens/Screen06.png</image>
+		</screenshot>
+	</screenshots>
+
+	<url type="homepage">http://fityk.nieto.pl/</url>
+
+	<provides>
+		<binary>fityk</binary>
+	</provides>
+
+</component>
diff --git a/fityk/CMPfit.h b/fityk/CMPfit.h
index e5686573..1fc0307b 100644
--- a/fityk/CMPfit.h
+++ b/fityk/CMPfit.h
@@ -16,7 +16,7 @@ namespace fityk {
 class MPfit : public Fit
 {
 public:
-    MPfit(Full* F, const char* name) : Fit(F, name) {}
+    MPfit(Full* F, const char* fname) : Fit(F, fname) {}
     virtual double run_method(std::vector<realt>* best_a);
 
     // implementation (must be public to be called inside callback function)
diff --git a/fityk/GAfit.cpp b/fityk/GAfit.cpp
index 3060cf83..a607037f 100644
--- a/fityk/GAfit.cpp
+++ b/fityk/GAfit.cpp
@@ -19,8 +19,8 @@ using namespace std;
 
 namespace fityk {
 
-GAfit::GAfit(Full* F, const char* name)
-   : Fit(F, name),
+GAfit::GAfit(Full* F, const char* fname)
+   : Fit(F, fname),
      popsize (100), elitism(0),
      mutation_type('u'), p_mutation(0.1), mutate_all_genes(false),
      mutation_strength(0.1), crossover_type('u'), p_crossover(0.3),
@@ -205,7 +205,7 @@ void GAfit::arithmetic_crossover1 (vector<Individual>::iterator c1,
     realt a = rand_0_1();
     for (int j = 0; j < na_; ++j) {
         c1->g[j] = a * c1->g[j] + (1 - a) * c2->g[j];
-        c2->g[j] = (1 - a) * c1->g[j] + a * c2->g[j]; ;
+        c2->g[j] = (1 - a) * c1->g[j] + a * c2->g[j];
     }
 }
 
@@ -215,7 +215,7 @@ void GAfit::arithmetic_crossover2 (vector<Individual>::iterator c1,
     for (int j = 0; j < na_; ++j) {
         realt a = rand_0_1();
         c1->g[j] = a * c1->g[j] + (1 - a) * c2->g[j];
-        c2->g[j] = (1 - a) * c1->g[j] + a * c2->g[j]; ;
+        c2->g[j] = (1 - a) * c1->g[j] + a * c2->g[j];
     }
 }
 
diff --git a/fityk/LMfit.h b/fityk/LMfit.h
index f62c8567..484dcc79 100644
--- a/fityk/LMfit.h
+++ b/fityk/LMfit.h
@@ -15,7 +15,7 @@ namespace fityk {
 class LMfit : public Fit
 {
 public:
-    LMfit(Full* F, const char* name) : Fit(F, name) {}
+    LMfit(Full* F, const char* fname) : Fit(F, fname) {}
     virtual double run_method(std::vector<realt>* best_a);
 
     // the same methods that were used for all methods up to ver. 1.2.1
diff --git a/fityk/Makefile.am b/fityk/Makefile.am
index 331ffefb..b9ba04bf 100644
--- a/fityk/Makefile.am
+++ b/fityk/Makefile.am
@@ -13,6 +13,7 @@ libfityk_la_SOURCES = logic.cpp view.cpp lexer.cpp eparser.cpp cparser.cpp \
 		 runner.cpp info.cpp common.cpp data.cpp var.cpp mgr.cpp \
 		 tplate.cpp func.cpp udf.cpp bfunc.cpp f_fcjasym.cpp ast.cpp \
 		 vm.cpp transform.cpp settings.cpp ui.cpp ui_api.cpp \
+		 root/background.cpp \
 		 luabridge.cpp GAfit.cpp LMfit.cpp guess.cpp NMfit.cpp \
 		 model.cpp fit.cpp voigt.cpp numfuncs.cpp fityk.cpp \
 		 \
@@ -20,6 +21,7 @@ libfityk_la_SOURCES = logic.cpp view.cpp lexer.cpp eparser.cpp cparser.cpp \
 		 runner.h info.h common.h data.h var.h mgr.h \
 		 tplate.h func.h udf.h bfunc.h f_fcjasym.h ast.h \
 		 vm.h transform.h settings.h ui.h luabridge.h \
+		 root/background.hpp \
 		 GAfit.h LMfit.h guess.h NMfit.h \
 		 model.h fit.h voigt.h numfuncs.h \
 		 swig/fityk_lua.cpp swig/luarun.h \
@@ -98,6 +100,9 @@ $(srcdir)/swig/Fityk.pm: $(srcdir)/swig/fityk_perl.cpp
 $(srcdir)/swig/fityk_ruby.cpp: swig/fityk.i fityk.h
 	$(SWIG) -c++ -ruby -I$(srcdir) -o $@ $<
 
+$(srcdir)/swig/fityk_csharp.cpp: swig/fityk.i fityk.h
+	$(SWIG) -c++ -csharp -I$(srcdir) -o $@ -namespace Fityk -outfile $(srcdir)/swig/Fityk.cs $<
+
 $(srcdir)/swig/java/fityk_java.cpp: swig/fityk.i fityk.h
 	mkdir -p $(srcdir)/swig/java
 	$(SWIG) -c++ -java -I$(srcdir) -o $@ -package fityk -outdir $(srcdir)/swig/java $<
@@ -110,6 +115,10 @@ ruby: swig/fityk_ruby.o
 	mkdir -p swig/ruby
 	$(CXX) -shared $(CXXFLAGS) $(LDFLAGS) $< -L./.libs -lfityk -o swig/ruby/fityk.so
 
+csharp: swig/fityk_csharp.o
+	mkdir -p swig/csharp
+	$(CXX) -shared $(CXXFLAGS) $(LDFLAGS) $< -L./.libs -lfityk -o swig/csharp/Fityk.so
+
 java: swig/java/fityk_java.o
 	$(CXX) -shared $(CXXFLAGS) $(LDFLAGS) $< -L./.libs -lfityk -o swig/java/libfitykJ.so
 
@@ -122,6 +131,9 @@ swig/fityk_ruby.o: swig/fityk_ruby.cpp
 	    -I`ruby -e "require 'rbconfig'; puts Config::CONFIG['archdir']"` \
 	    $(CXXFLAGS) -fPIC -o $@ -c $<
 
+swig/fityk_csharp.o: swig/fityk_csharp.cpp
+	$(CXX) $(CPPFLAGS) -I$(srcdir) $(CXXFLAGS) -fPIC -o $@ -c $<
+
 swig/java/fityk_java.o: swig/java/fityk_java.cpp
 	mkdir -p swig/java
 	$(CXX) $(CPPFLAGS) -I$(srcdir) \
diff --git a/fityk/NLfit.cpp b/fityk/NLfit.cpp
index 344adf6e..59a41298 100644
--- a/fityk/NLfit.cpp
+++ b/fityk/NLfit.cpp
@@ -13,8 +13,8 @@ using namespace std;
 
 namespace fityk {
 
-NLfit::NLfit(Full* F, const char* name, nlopt_algorithm algorithm)
-    : Fit(F, name), algorithm_(algorithm), opt_(NULL)
+NLfit::NLfit(Full* F, const char* fname, nlopt_algorithm algorithm)
+    : Fit(F, fname), algorithm_(algorithm), opt_(NULL)
 {
 }
 
diff --git a/fityk/NMfit.h b/fityk/NMfit.h
index 8fb2200f..08b013d7 100644
--- a/fityk/NMfit.h
+++ b/fityk/NMfit.h
@@ -26,7 +26,7 @@ struct Vertex
 class NMfit : public Fit
 {
 public:
-    NMfit(Full* F, const char* name) : Fit(F, name) {}
+    NMfit(Full* F, const char* fname) : Fit(F, fname) {}
     virtual double run_method(std::vector<realt>* best_a);
 private:
     std::vector<Vertex> vertices;
diff --git a/fityk/bfunc.cpp b/fityk/bfunc.cpp
index a5b07ead..f28c0e4d 100644
--- a/fityk/bfunc.cpp
+++ b/fityk/bfunc.cpp
@@ -464,7 +464,7 @@ void FuncVoigt::more_precomputations()
 }
 
 CALCULATE_VALUE_BEGIN(FuncVoigt)
-    // humdev/humlik routines require with y (a3 here) parameter >0.
+    // humdev/humlik routines require the y (a3 here) parameter >0.
     float k;
     realt xa1a2 = (x - av_[1]) / av_[2];
     k = humlik(xa1a2, fabs(av_[3]));
@@ -557,13 +557,13 @@ const vector<string>& FuncVoigt::get_other_prop_names() const
     return p;
 }
 
-bool FuncVoigt::get_other_prop(string const& name, realt* a) const
+bool FuncVoigt::get_other_prop(string const& pname, realt* a) const
 {
-    if (name == "GaussianFWHM") {
+    if (pname == "GaussianFWHM") {
         realt sigma = fabs(av_[2]) / M_SQRT2;
         *a = 2 * sigma * sqrt(2 * M_LN2);
         return true;
-    } else if (name == "LorentzianFWHM") {
+    } else if (pname == "LorentzianFWHM") {
         realt gamma = fabs(av_[2]) * av_[3];
         *a = 2 * gamma;
         return true;
@@ -585,15 +585,15 @@ void FuncVoigtA::more_precomputations()
 }
 
 CALCULATE_VALUE_BEGIN(FuncVoigtA)
-    // humdev/humlik routines require with y (a3 here) parameter >0.
+    // humdev/humlik routines require the y (a3 here) parameter >0.
     float k;
     realt xa1a2 = (x - av_[1]) / av_[2];
     k = humlik(xa1a2, fabs(av_[3]));
 CALCULATE_VALUE_END(av_[0] / (sqrt(M_PI) * av_[2]) * k)
 
 CALCULATE_DERIV_BEGIN(FuncVoigtA)
-    // humdev/humlik routines require with y (a3 here) parameter >0.
-    // here fabs(av_[3]) is used, and dy_dv[3] is negated if av_[3]<0.
+    // humdev/humlik routines require the y (a3 here) parameter >0.
+    // Here fabs(av_[3]) is used, and dy_dv[3] is negated if av_[3]<0.
     float k;
     realt xa1a2 = (x-av_[1]) / av_[2];
     realt f = av_[0] / (sqrt(M_PI) * av_[2]);
diff --git a/fityk/bfunc.h b/fityk/bfunc.h
index da247446..884fe83d 100644
--- a/fityk/bfunc.h
+++ b/fityk/bfunc.h
@@ -14,10 +14,10 @@ private:\
     DISALLOW_COPY_AND_ASSIGN(Func##NAME); \
 public:\
     Func##NAME (const Settings* settings, \
-                const std::string &name, \
+                const std::string &fname, \
                 Tplate::Ptr tp, \
                 std::vector<std::string> const &vars) \
-        : PARENT(settings, name, tp, vars) {} \
+        : PARENT(settings, fname, tp, vars) {} \
     void calculate_value_in_range(std::vector<realt> const &xx, \
                                   std::vector<realt> &yy, \
                                   int first, int last) const;\
@@ -150,7 +150,7 @@ class FuncVoigt : public Function
     bool get_fwhm(realt* a) const;
     bool get_area(realt* a) const;
     const std::vector<std::string>& get_other_prop_names() const;
-    bool get_other_prop(std::string const& name, realt* a) const;
+    bool get_other_prop(std::string const& pname, realt* a) const;
 };
 
 class FuncVoigtA : public Function
@@ -205,10 +205,10 @@ public:
     virtual std::string get_param(int n) const;
 protected:
     VarArgFunction(const Settings* settings,
-                   const std::string &name,
+                   const std::string &fname,
                    Tplate::Ptr tp,
                    const std::vector<std::string> &vars)
-        : Function(settings, name, tp, vars) {}
+        : Function(settings, fname, tp, vars) {}
     virtual void init() { center_idx_ = -1; }
 };
 
diff --git a/fityk/cmpfit/README b/fityk/cmpfit/README
index e62ab9f6..29a9cef4 100644
--- a/fityk/cmpfit/README
+++ b/fityk/cmpfit/README
@@ -1,4 +1,3 @@
-(this directory contains modified copy of cmpfit-1.2, see mpfit.patch)
 
 MPFIT: A MINPACK-1 Least Squares Fitting Library in C
 
@@ -10,7 +9,7 @@ Tranlation to C Language by S. Moshier (moshier.net)
 Enhancements, documentation and packaging by C. Markwardt
   (comparable to IDL fitting routine MPFIT
    see http://cow.physics.wisc.edu/~craigm/idl/idl.html)
-  Copyright (C) 2003, 2004, 2006, 2007, 2009, 2010 Craig B. Markwardt
+  Copyright (C) 2003, 2004, 2006, 2007, 2009, 2010, 2013 Craig B. Markwardt
 
 
 SUMMARY of CHANGES
@@ -22,8 +21,10 @@ SUMMARY of CHANGES
  04 Oct 2010 -             - add static declarations, remove some compiler warnings
                              (reported by Lars Kr. Lundin)
  13 Nov 2010 - version 1.2 - additional documentation, cleanup of mpfit.h
+ 23 Apr 2013 - version 1.3 - add MP_NO_ITER; bug fix mpside=2 when debugging
+                             (thanks to M. Wojdyr)
 
-$Id: README.html,v 1.3 2010/11/13 08:17:15 craigm Exp $
+$Id: README,v 1.18 2016/06/02 19:14:16 craigm Exp $
 
 INTRODUCTION
 
@@ -444,12 +445,12 @@ turn is defined as a pointer to the following structure:
     double epsfcn;  /* Finite derivative step size               Default: MP_MACHEP0 */
     double stepfactor; /* Initial step bound                     Default: 100.0 */
     double covtol;  /* Range tolerance for covariance calculation Default: 1e-14 */
-    int maxiter;    /* Maximum number of iterations.  If maxiter == 0,
+    int maxiter;    /* Maximum number of iterations.  If maxiter == MP_NO_ITER,
                        then basic error checking is done, and parameter
                        errors/covariances are estimated based on input
                        parameter values, but no fitting iterations are done. 
-  		       Default: 200
-  		    */
+                       Default: 200
+		  */
     int maxfev;     /* Maximum number of function evaluations, or 0 for no limit
   		       Default: 0 (no limit) */
     int nprint;     /* Default: 1 */
diff --git a/fityk/cmpfit/mpfit.c b/fityk/cmpfit/mpfit.c
index 99c29c83..1ab9abb8 100644
--- a/fityk/cmpfit/mpfit.c
+++ b/fityk/cmpfit/mpfit.c
@@ -13,7 +13,7 @@
  */
 
 /* Main mpfit library routines (double precision) 
-   $Id: mpfit.c,v 1.23 2013/04/23 04:24:16 craigm Exp $
+   $Id: mpfit.c,v 1.24 2013/04/23 18:37:38 craigm Exp $
  */
 
 #include <stdio.h>
@@ -332,7 +332,7 @@ int mpfit(mp_func funct, int m, int npar,
     conf.maxfev = config->maxfev;
   }
 
-  info = 0;
+  info = MP_ERR_INPUT; /* = 0 */
   iflag = 0;
   nfree = 0;
   npegged = 0;
diff --git a/fityk/cmpfit/mpfit.h b/fityk/cmpfit/mpfit.h
index d17fcb8d..47469c82 100644
--- a/fityk/cmpfit/mpfit.h
+++ b/fityk/cmpfit/mpfit.h
@@ -13,7 +13,7 @@
 
 /* Header file defining constants, data structures and functions of
    mpfit library 
-   $Id: mpfit.h,v 1.15 2013/04/09 17:55:32 craigm Exp $
+   $Id: mpfit.h,v 1.16 2016/06/02 19:14:16 craigm Exp $
 */
 
 #ifndef MPFIT_H
@@ -25,7 +25,7 @@ extern "C" {
 #endif
 
 /* MPFIT version string */
-#define MPFIT_VERSION "1.2"
+#define MPFIT_VERSION "1.3"
 
 /* Definition of a parameter constraint structure */
 struct mp_par_struct {
diff --git a/fityk/cmpfit/mpfit.patch b/fityk/cmpfit/mpfit.patch
deleted file mode 100644
index 838b6153..00000000
--- a/fityk/cmpfit/mpfit.patch
+++ /dev/null
@@ -1,23 +0,0 @@
---- mpfit.c.orig	2012-10-01 00:30:51.533258108 +0100
-+++ mpfit.c	2012-10-01 01:46:42.106809470 +0100
-@@ -322,7 +322,7 @@
-     if (config->stepfactor > 0) conf.stepfactor = config->stepfactor;
-     if (config->nprint >= 0) conf.nprint = config->nprint;
-     if (config->epsfcn > 0) conf.epsfcn = config->epsfcn;
--    if (config->maxiter > 0) conf.maxiter = config->maxiter;
-+    if (config->maxiter >= 0) conf.maxiter = config->maxiter;
-     if (config->douserscale != 0) conf.douserscale = config->douserscale;
-     if (config->covtol > 0) conf.covtol = config->covtol;
-     if (config->nofinitecheck > 0) conf.nofinitecheck = config->nofinitecheck;
-@@ -624,7 +624,10 @@
-    */
-   if (gnorm <= conf.gtol) info = MP_OK_DIR;
-   if (info != 0) goto L300;
--  if (conf.maxiter == 0) goto L300;
-+  if (conf.maxiter == 0) {
-+    info = MP_MAXITER;
-+    goto L300;
-+  }
- 
-   /*
-    *	 rescale if necessary.
diff --git a/fityk/cparser.cpp b/fityk/cparser.cpp
index 9fb87a5c..8d1116c2 100644
--- a/fityk/cparser.cpp
+++ b/fityk/cparser.cpp
@@ -127,8 +127,7 @@ Token Parser::read_expr(Lexer& lex, ExpressionParser::ParseMode mode)
     t.type = kTokenExpr;
     t.str = lex.pchar();
     ep_.clear_vm();
-    assert(!st_.datasets.empty());
-    int ds = st_.datasets[0];
+    int ds = st_.datasets.empty() ? 0 : st_.datasets[0];
     ep_.parse_expr(lex, ds, NULL, NULL, mode);
     t.length = lex.pchar() - t.str;
     t.value.d = 0.;
@@ -138,7 +137,7 @@ Token Parser::read_expr(Lexer& lex, ExpressionParser::ParseMode mode)
 Token Parser::read_and_calc_expr(Lexer& lex)
 {
     Token t = read_expr(lex);
-    int ds = st_.datasets[0];
+    int ds = st_.datasets.empty() ? 0 : st_.datasets[0];
     const vector<Point>& points = F_->dk.data(ds)->points();
     t.value.d = ep_.calculate(0, points);
     return t;
diff --git a/fityk/eparser.cpp b/fityk/eparser.cpp
index b21a7db2..99d9786e 100644
--- a/fityk/eparser.cpp
+++ b/fityk/eparser.cpp
@@ -79,6 +79,7 @@ const char* function_name(int op)
         case OP_DT_SUM_SAME_X: return "sum_same_x";
         case OP_DT_AVG_SAME_X: return "avg_same_x";
         case OP_DT_SHIRLEY_BG: return "shirley_bg";
+        case OP_DT_SNIP_BG: return "snip_bg";
         // 2-args functions
         case OP_MOD: return "mod";
         case OP_MIN2: return "min2";
@@ -138,6 +139,8 @@ int get_function_narg(int op)
         case OP_RANDNORM:
         case OP_RANDU:
             return 2;
+        case OP_DT_SNIP_BG:
+            return 5;
         // Fityk functions
         case OP_FUNC:
         case OP_SUM_F:
@@ -819,6 +822,8 @@ void ExpressionParser::parse_expr(Lexer& lex, int default_ds,
                         put_function(OP_DT_AVG_SAME_X);
                     else if (mode == kDatasetTrMode && word == "shirley_bg")
                         put_function(OP_DT_SHIRLEY_BG);
+                    else if (mode == kDatasetTrMode && word == "snip_bg")
+                        put_function(OP_DT_SNIP_BG);
 
                     else
                         lex.throw_syntax_error("unknown function: " + word);
diff --git a/fityk/fit.cpp b/fityk/fit.cpp
index 120494a4..3d203582 100644
--- a/fityk/fit.cpp
+++ b/fityk/fit.cpp
@@ -556,27 +556,27 @@ const char* FitManager::method_list[][3] =
 };
 
 
-FitManager::FitManager(Full *F_)
-    : ParameterHistoryMgr(F_), dirty_error_cache_(true)
+FitManager::FitManager(Full *F)
+    : ParameterHistoryMgr(F), dirty_error_cache_(true)
 
 {
     // these methods correspond to method_list[]
-    methods_.push_back(new LMfit(F_, next_method()));
-    methods_.push_back(new MPfit(F_, next_method()));
+    methods_.push_back(new LMfit(F, next_method()));
+    methods_.push_back(new MPfit(F, next_method()));
 #if HAVE_LIBNLOPT
-    methods_.push_back(new NLfit(F_, next_method(), NLOPT_LN_NELDERMEAD));
-    methods_.push_back(new NLfit(F_, next_method(), NLOPT_LD_LBFGS));
-    methods_.push_back(new NLfit(F_, next_method(), NLOPT_LD_VAR2));
-    methods_.push_back(new NLfit(F_, next_method(), NLOPT_LN_PRAXIS));
-    methods_.push_back(new NLfit(F_, next_method(), NLOPT_LN_BOBYQA));
-    methods_.push_back(new NLfit(F_, next_method(), NLOPT_LN_SBPLX));
-    //methods_.push_back(new NLfit(F_, next_method(), NLOPT_LD_MMA));
-    //methods_.push_back(new NLfit(F_, next_method(), NLOPT_LD_SLSQP));
-    //methods_.push_back(new NLfit(F_, next_method(), NLOPT_LN_COBYLA));
-    //methods_.push_back(new NLfit(F_, next_method(), NLOPT_GN_CRS2_LM));
+    methods_.push_back(new NLfit(F, next_method(), NLOPT_LN_NELDERMEAD));
+    methods_.push_back(new NLfit(F, next_method(), NLOPT_LD_LBFGS));
+    methods_.push_back(new NLfit(F, next_method(), NLOPT_LD_VAR2));
+    methods_.push_back(new NLfit(F, next_method(), NLOPT_LN_PRAXIS));
+    methods_.push_back(new NLfit(F, next_method(), NLOPT_LN_BOBYQA));
+    methods_.push_back(new NLfit(F, next_method(), NLOPT_LN_SBPLX));
+    //methods_.push_back(new NLfit(F, next_method(), NLOPT_LD_MMA));
+    //methods_.push_back(new NLfit(F, next_method(), NLOPT_LD_SLSQP));
+    //methods_.push_back(new NLfit(F, next_method(), NLOPT_LN_COBYLA));
+    //methods_.push_back(new NLfit(F, next_method(), NLOPT_GN_CRS2_LM));
 #endif
-    methods_.push_back(new NMfit(F_, next_method()));
-    methods_.push_back(new GAfit(F_, next_method()));
+    methods_.push_back(new NMfit(F, next_method()));
+    methods_.push_back(new GAfit(F, next_method()));
 }
 
 
diff --git a/fityk/fityk.cpp b/fityk/fityk.cpp
index 2a898307..7b28768f 100644
--- a/fityk/fityk.cpp
+++ b/fityk/fityk.cpp
@@ -220,7 +220,7 @@ vector<Func*> Fityk::get_components(int dataset, char fz)  throw(ExecuteError)
     return ret;
 }
 
-realt Fityk::get_model_value(realt x, int dataset)  throw(ExecuteError)
+realt Fityk::get_model_value(realt x, int dataset) const  throw(ExecuteError)
 {
     try {
         return priv_->dk.get_model(hd(priv_, dataset))->value(x);
@@ -241,7 +241,7 @@ vector<realt> Fityk::get_model_vector(vector<realt> const& x, int dataset)
     return yy;
 }
 
-const Var* Fityk::get_variable(string const& name)  throw(ExecuteError)
+const Var* Fityk::get_variable(string const& name) const  throw(ExecuteError)
 {
     try {
         string vname;
@@ -259,7 +259,7 @@ const Var* Fityk::get_variable(string const& name)  throw(ExecuteError)
         return priv_->mgr.find_variable(vname);
     }
     CATCH_EXECUTE_ERROR
-    return NULL; // avoid compiler warning
+    return NULL;
 }
 
 double Fityk::get_view_boundary(char side)
@@ -474,15 +474,15 @@ void fityk_delete(Fityk *f)
     delete f;
 }
 
-bool fityk_execute(Fityk *f, const char* command)
+int fityk_execute(Fityk *f, const char* command)
 {
     try {
         f->execute(command);
     }
-    catch(ExitRequestedException) {
-        return false;
+    catch(const ExitRequestedException&) {
+        return 0;
     }
-    return true;
+    return 1;
 }
 
 void fityk_load_data(Fityk *f, int dataset,
@@ -528,6 +528,16 @@ int fityk_get_parameter_count(const Fityk* f)
     return f->get_parameter_count();
 }
 
+const Var* fityk_get_variable(const Fityk* f, const char* name)
+{
+    return f->get_variable(name);
+}
+
+const Func* fityk_get_function(const Fityk* f, const char* name)
+{
+    return f->get_function(name);
+}
+
 const Point* fityk_get_data_point(Fityk *f, int dataset, int index)
 {
     const vector<Point>& data = f->get_data(dataset);
@@ -553,4 +563,19 @@ realt* fityk_get_covariance_matrix(Fityk *f, int dataset)
     return f->get_covariance_matrix_as_array(dataset);
 }
 
+realt fityk_var_value(const Var *var)
+{
+    return var->value();
+}
+
+const char* fityk_var_name(const Func *func, const char *param)
+{
+    return func->var_name(param).c_str();
+}
+
+realt fityk_value_at(const Func *func, realt x)
+{
+    return func->value_at(x);
+}
+
 } // extern "C"
diff --git a/fityk/fityk.h b/fityk/fityk.h
index 6cfa95dc..deb7d5a6 100644
--- a/fityk/fityk.h
+++ b/fityk/fityk.h
@@ -43,12 +43,14 @@ namespace fityk {
 
 // C++ exception specifications are used by SWIG bindings.
 // They are deprecated (in this form) in C++-11.
-#ifdef _MSC_VER
+#if defined(_MSC_VER)
 #pragma warning( disable : 4290 ) // C++ exception specification ignored...
-#endif
-#ifdef __clang__
+#elif defined(__clang__)
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated"
+#elif defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated"
 #endif
 
 /// Public C++ API of libfityk: class Fityk and helpers.
@@ -286,7 +288,7 @@ public:
     std::vector<Var*> all_variables() const;
 
     /// returns variable $name
-    const Var* get_variable(std::string const& name)  throw(ExecuteError);
+    const Var* get_variable(std::string const& name) const throw(ExecuteError);
 
     /// returns all %functions
     std::vector<Func*> all_functions() const;
@@ -299,7 +301,7 @@ public:
                                                          throw(ExecuteError);
 
     /// returns the value of the model for a given dataset at x
-    realt get_model_value(realt x, int dataset=DEFAULT_DATASET)
+    realt get_model_value(realt x, int dataset=DEFAULT_DATASET) const
                                                          throw(ExecuteError);
 
     /// multiple point version of the get_model_value()
@@ -345,7 +347,7 @@ public:
 private:
     Full *priv_;
     bool throws_;
-    std::string last_error_;
+    mutable std::string last_error_;
     FitykInternalData *p_; // members hidden for the sake of API stability
     // disallow copy and assign
     Fityk(const Fityk&);
@@ -354,25 +356,31 @@ private:
 
 } // namespace fityk
 
-#ifdef __clang__
+#if defined(__clang__)
 #pragma clang diagnostic pop
+#elif defined(__GNUC__)
+#pragma GCC diagnostic pop
 #endif
 
 #else /* !__cplusplus */
 /* C API.
  * Functions below correspond to member functions of class Fityk.
  * To check for errors use fityk_last_error().
- * bool and Point here should be ABI-compatible with C++ bool and fityk::Point.
+ * Point here should be ABI-compatible with C++ bool and fityk::Point.
  */
 
-#define bool _Bool
-
 typedef struct Fityk_ Fityk;
+typedef struct Func_ Func;
+typedef struct Var_ Var;
 
 typedef struct
 {
     realt x, y, sigma;
-    bool is_active;
+#if __STDC_VERSION__-0 >= 199901L
+    _Bool is_active;
+#else
+    unsigned char is_active; // best guess
+#endif
 } Point;
 
 #endif /* __cplusplus */
@@ -382,12 +390,14 @@ typedef struct
 extern "C" {
 using fityk::Point;
 using fityk::Fityk;
+using fityk::Func;
+using fityk::Var;
 #endif
 
 FITYK_API Fityk* fityk_create();
 FITYK_API void fityk_delete(Fityk *f);
-/* returns false on ExitRequestedException */
-FITYK_API bool fityk_execute(Fityk *f, const char* command);
+/* returns 0 on ExitRequestedException */
+FITYK_API int fityk_execute(Fityk *f, const char* command);
 FITYK_API void fityk_load_data(Fityk *f, int dataset,
                                double *x, double *y, double *sigma, int num,
                                const char* title);
@@ -399,6 +409,8 @@ FITYK_API char* fityk_get_info(Fityk *f, const char *s, int dataset);
 FITYK_API realt fityk_calculate_expr(Fityk *f, const char* s, int dataset);
 FITYK_API int fityk_get_dataset_count(const Fityk *f);
 FITYK_API int fityk_get_parameter_count(const Fityk* f);
+FITYK_API const Var* fityk_get_variable(const Fityk* f, const char* name);
+FITYK_API const Func* fityk_get_function(const Fityk* f, const char* name);
 /* get data point, returns NULL if index is out of range */
 FITYK_API const Point* fityk_get_data_point(Fityk *f, int dataset, int index);
 FITYK_API realt fityk_get_model_value(Fityk *f, realt x, int dataset);
@@ -410,6 +422,10 @@ FITYK_API int fityk_get_dof(Fityk *f, int dataset);
 /* length of the array is parameter_count^2                        */
 FITYK_API realt* fityk_get_covariance_matrix(Fityk *f, int dataset);
 
+FITYK_API realt fityk_var_value(const Var *var);
+FITYK_API const char* fityk_var_name(const Func *func, const char *param);
+FITYK_API realt fityk_value_at(const Func *func, realt x);
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
diff --git a/fityk/func.h b/fityk/func.h
index 4fb894e9..8cbf5f9b 100644
--- a/fityk/func.h
+++ b/fityk/func.h
@@ -82,9 +82,12 @@ public:
     int get_param_nr(const std::string& param) const;
 // C++ exception specifications are used by SWIG bindings.
 // They are deprecated (in this form) in C++-11.
-#ifdef __clang__
+#if defined(__clang__)
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated"
+#elif defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated"
 #endif
     virtual realt get_param_value(const std::string& param) const
                             throw(ExecuteError); // exc. spec. is used by SWIG
@@ -103,15 +106,18 @@ public:
     virtual const std::string& var_name(const std::string& param) const
                         throw(ExecuteError) // exc. spec. is used by SWIG
                         { return used_vars_.get_name(get_param_nr(param)); }
-#ifdef __clang__
+#if defined(__clang__)
 #pragma clang diagnostic pop
+#elif defined(__GNUC__)
+#pragma GCC diagnostic pop
 #endif
 
     virtual realt value_at(realt x) const { return calculate_value(x); }
     int max_param_pos() const;
 
     realt calculate_value_and_deriv(realt x, std::vector<realt> &dy_da) const {
-        bufx_[0] = x, bufy_[0] = 0.;
+        bufx_[0] = x;
+        bufy_[0] = 0.;
         calculate_value_deriv_in_range(bufx_, bufy_, dy_da, false, 0, 1);
         return bufy_[0];
     }
diff --git a/fityk/info.cpp b/fityk/info.cpp
index 80d3a724..863f177a 100644
--- a/fityk/info.cpp
+++ b/fityk/info.cpp
@@ -226,7 +226,7 @@ string info_func_props(const Full* F, const string& name)
         s += "\n" + f->get_param(i) + " = " + get_variable_info(F, v);
     }
     realt a;
-    const vector<string>& fargs = f->tp()->fargs;;
+    const vector<string>& fargs = f->tp()->fargs;
     if (f->get_center(&a) && !contains_element(fargs, string("center")))
         s += "\nCenter: " + S(a);
     if (f->get_height(&a) && !contains_element(fargs, string("height")))
diff --git a/fityk/luabridge.cpp b/fityk/luabridge.cpp
index d9112553..745ec9c6 100644
--- a/fityk/luabridge.cpp
+++ b/fityk/luabridge.cpp
@@ -80,8 +80,8 @@ LuaBridge::LuaBridge(Full *F)
 
     // make vectors also iterators over elements
     const char* vectors[] = { "FuncVector", "VarVector", "PointVector",
-                              "RealVector" };
-    for (int i = 0; i < 4; ++i) {
+                              "RealVector", "IntVector" };
+    for (int i = 0; i < 5; ++i) {
         SWIG_Lua_get_class_metatable(L_, vectors[i]);
         SWIG_Lua_add_function(L_, "__call", lua_vector_iterator);
         lua_pop(L_, 1);
diff --git a/fityk/root/background.cpp b/fityk/root/background.cpp
index c39459f2..2f898243 100644
--- a/fityk/root/background.cpp
+++ b/fityk/root/background.cpp
@@ -15,6 +15,7 @@
 #include <cmath>
 #include <vector>
 
+#include "fityk.h"  // for ExecuteError
 #include "background.hpp"
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -441,30 +442,33 @@
 /// }
 /// ~~~
 
-std::vector<double> background::background(std::vector<double> spectrum,
-                                           int numberIterations,
-                                           int direction,
-                                           int filterOrder,
-                                           bool smoothing,
-                                           int smoothWindow,
-                                           bool compton)
+std::vector<double> ROOT::background(const std::vector<double>& spectrum,
+                                     int numberIterations,
+                                     int direction,
+                                     int filterOrder,
+                                     bool smoothing,
+                                     int smoothWindow,
+                                     bool compton)
 {
     int i, j, w, bw, b1, b2, priz;
     double a, b, c, d, e, yb1, yb2, ai, av, men, b4, c4, d4, e4, b6, c6, d6, e6, f6, g6, b8, c8, d8, e8, f8, g8, h8, i8;
 
-    const unsigned int ssize = spectrum.size();
+    const int ssize = (int) spectrum.size();
 
     if (ssize <= 0)
-        throw "Wrong Parameters";
+        throw fityk::ExecuteError("Wrong vector size");
 
     if (numberIterations < 1)
-        throw "Width of Clipping Window Must Be Positive";
+        throw fityk::ExecuteError("Width of Clipping Window Must Be Positive");
 
     if (ssize < 2 * numberIterations + 1)
-        throw "Too Large Clipping Window";
+        throw fityk::ExecuteError("Too Large Clipping Window");
+
+    if (filterOrder != kBackOrder2 && filterOrder != kBackOrder4 && filterOrder != kBackOrder6 && filterOrder != kBackOrder8)
+        throw fityk::ExecuteError("Incorrect order of clipping filter, possible values are: 2, 4, 6 or 8");
 
     if (smoothing == true && smoothWindow != kBackSmoothing3 && smoothWindow != kBackSmoothing5 && smoothWindow != kBackSmoothing7 && smoothWindow != kBackSmoothing9 && smoothWindow != kBackSmoothing11 && smoothWindow != kBackSmoothing13 && smoothWindow != kBackSmoothing15)
-        throw "Incorrect width of smoothing window";
+        throw fityk::ExecuteError("Incorrect width of smoothing window");
 
    std::vector<double> working_space(2 * ssize);
 
@@ -1025,7 +1029,7 @@ std::vector<double> background::background(std::vector<double> spectrum,
                   b = b4;
                if (b < a)
                   av = b;
-               working_space[j]=av;
+               working_space[j] = av;
             }
          }
          for (j = i; j < ssize - i; j++)
@@ -1094,7 +1098,5 @@ std::vector<double> background::background(std::vector<double> spectrum,
       }
    }
 
-    working_space.resize(ssize);
-
-    return working_space;
+    return std::vector<double>(working_space.begin() + ssize, working_space.end());
 }
diff --git a/fityk/root/background.hpp b/fityk/root/background.hpp
index efe016b8..03ccd69e 100644
--- a/fityk/root/background.hpp
+++ b/fityk/root/background.hpp
@@ -15,25 +15,27 @@
 #ifndef __BACKGROUND_HPP__
 #define __BACKGROUND_HPP__
 
-namespace background {
+#include <vector>
+
+namespace ROOT {
 
     enum {
-        kBackIncreasingWindow =0,
-        kBackDecreasingWindow =1,
-        kBackOrder2 =2,
-        kBackOrder4 =4,
-        kBackOrder6 =6,
-        kBackOrder8 =8,
-        kBackSmoothing3 =3,
-        kBackSmoothing5 =5,
-        kBackSmoothing7 =7,
-        kBackSmoothing9 =9,
-        kBackSmoothing11 =11,
-        kBackSmoothing13 =13,
-        kBackSmoothing15 =15
-   };
-
-    std::vector<double> background(std::vector<double> spectrum,
+        kBackIncreasingWindow = 1,
+        kBackDecreasingWindow = -1,
+        kBackOrder2 = 2,
+        kBackOrder4 = 4,
+        kBackOrder6 = 6,
+        kBackOrder8 = 8,
+        kBackSmoothing3 = 3,
+        kBackSmoothing5 = 5,
+        kBackSmoothing7 = 7,
+        kBackSmoothing9 = 9,
+        kBackSmoothing11 = 11,
+        kBackSmoothing13 = 13,
+        kBackSmoothing15 = 15
+    };
+
+    std::vector<double> background(const std::vector<double>& spectrum,
                                    int numberIterations,
                                    int direction,
                                    int filterOrder,
diff --git a/fityk/swig/fityk.i b/fityk/swig/fityk.i
index 00a36b86..487f8a25 100644
--- a/fityk/swig/fityk.i
+++ b/fityk/swig/fityk.i
@@ -14,6 +14,9 @@
 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
 #pragma clang diagnostic ignored "-Wconditional-uninitialized"
 #endif
+#ifdef __GNUC__
+#pragma GCC diagnostic ignored "-Wshadow"
+#endif
 %}
 
 #if defined(SWIGPERL)
@@ -51,6 +54,7 @@ namespace std {
      */
     //%template(RealVector) vector<realt>;
     %template(RealVector) vector<double>;
+    %template(IntVector) vector<int>;
     %template(VarVector) vector<fityk::Var*>;
     %template(FuncVector) vector<fityk::Func*>;
 }
@@ -159,10 +163,6 @@ namespace std {
             SWIG_exception(SWIG_TypeError,"Expected function.");
     }
 
-    /* we had problem with user_interrupt, see
-       https://github.com/swig/swig/issues/629 */
-    %apply int { std::sig_atomic_t };
-
     #define FITYK_API // empirical workaround that makes SWIG 2.0.8 work
     %{
     using fityk::Fityk; // empirical workaround that makes SWIG 2.0.8 work
diff --git a/fityk/transform.cpp b/fityk/transform.cpp
index 0e675713..6b950180 100644
--- a/fityk/transform.cpp
+++ b/fityk/transform.cpp
@@ -6,6 +6,8 @@
 #include "transform.h"
 #include "logic.h"
 #include "data.h"
+#include "root/background.hpp"
+#include <stdio.h>
 
 using namespace std;
 
@@ -95,6 +97,53 @@ void shirley_bg(vector<Point> &pp)
         pp[i].y = B[i];
 }
 
+// Calculates the SNIP background iteratively in the
+// given slice of the vector of points.
+// The active points are modified in-place, inactive
+// points are left as they are, assuming that they
+// are already considered background.
+vector<Point>::iterator snip_bg_slice(vector<Point>::iterator begin,
+                                      vector<Point>::iterator end,
+                                      int window_width,
+                                      int direction,
+                                      int filter_order,
+                                      bool smoothing,
+                                      bool smooth_window,
+                                      bool estimate_compton)
+{
+    // Determine the first active slice of the data points.
+    while (begin != end && !begin->is_active)
+        ++begin;
+    if (begin == end)
+        return end;
+    for (vector<Point>::iterator it = begin + 1; it != end; ++it)
+        if (!it->is_active) {
+            end = it;
+            break;
+        }
+    if (end <= begin)  // just in case
+        return end;
+
+    vector<double> bg_input(end - begin);
+    for (vector<Point>::iterator it = begin; it != end; it++)
+        bg_input[it - begin] = it->y;
+
+    vector<double> bg_output = ROOT::background(bg_input,
+                                                window_width,
+                                                direction,
+                                                filter_order,
+                                                smoothing,
+                                                smooth_window,
+                                                estimate_compton);
+
+    if (bg_output.size() == bg_input.size()) {
+        for (vector<Point>::iterator it = begin; it != end; it++)
+            it->y = bg_output[it - begin];
+    }
+
+    return end;
+}
+
 } // anonymous namespace
 
 namespace fityk {
@@ -202,6 +251,33 @@ void run_data_transform(const DataKeeper& dk, const VMData& vm, Data* data_out)
                 shirley_bg(stackPtr->points);
                 break;
 
+            case OP_DT_SNIP_BG: {
+                stackPtr -= 4;
+
+                if ((stackPtr)->is_num)
+                    throw ExecuteError(op2str(*i) + " is defined only for @n");
+                int window_width = (stackPtr+1)->num;
+                int direction = (stackPtr+2)->num >= 0
+                                ? ROOT::kBackIncreasingWindow
+                                : ROOT::kBackDecreasingWindow;
+                int filter_order = (stackPtr+3)->num;
+                bool smoothing = false;
+                int smooth_window = ROOT::kBackSmoothing3;
+                bool estimate_compton = (stackPtr+4)->num > 0 ? true : false;
+
+                vector<Point>::iterator start = stackPtr->points.begin();
+                while (start != stackPtr->points.end())
+                    start = snip_bg_slice(start,
+                                          stackPtr->points.end(),
+                                          window_width,
+                                          direction,
+                                          filter_order,
+                                          smoothing,
+                                          smooth_window,
+                                          estimate_compton);
+                break;
+            }
+
             case OP_AND:
                 // do nothing
                 break;
diff --git a/fityk/udf.cpp b/fityk/udf.cpp
index 834a4992..f1f7cad2 100644
--- a/fityk/udf.cpp
+++ b/fityk/udf.cpp
@@ -41,10 +41,10 @@ Function* init_component(const string& func_name, const Tplate::Component& c,
 
 
 CompoundFunction::CompoundFunction(const Settings* settings,
-                                   const string &name,
+                                   const string &fname,
                                    const Tplate::Ptr tp,
                                    const vector<string> &vars)
-    : Function(settings, name, tp, vars)
+    : Function(settings, fname, tp, vars)
 {
 }
 
@@ -201,10 +201,10 @@ bool CompoundFunction::get_nonzero_range(double level,
 ///////////////////////////////////////////////////////////////////////
 
 CustomFunction::CustomFunction(const Settings* settings,
-                               const string &name,
+                               const string &fname,
                                const Tplate::Ptr tp,
                                const vector<string> &vars)
-    : Function(settings, name, tp, vars),
+    : Function(settings, fname, tp, vars),
       // don't use nv() here, it's not set until init()
       derivatives_(vars.size()+1),
       value_offset_(0)
@@ -295,10 +295,10 @@ string CustomFunction::get_current_formula(const string& x,
 ///////////////////////////////////////////////////////////////////////
 
 SplitFunction::SplitFunction(const Settings* settings,
-                             const string &name,
+                             const string &fname,
                              const Tplate::Ptr tp,
                              const vector<string> &vars)
-    : Function(settings, name, tp, vars), left_(NULL), right_(NULL)
+    : Function(settings, fname, tp, vars), left_(NULL), right_(NULL)
 {
 }
 
diff --git a/fityk/ui.cpp b/fityk/ui.cpp
index c37b613b..77026fb4 100644
--- a/fityk/ui.cpp
+++ b/fityk/ui.cpp
@@ -253,7 +253,7 @@ private:
 
 void UserInterface::exec_fityk_script(const string& filename)
 {
-    user_interrupt = false;
+    user_interrupt = 0;
 
     boost::scoped_ptr<FileOpener> opener;
     if (endswith(filename, ".gz"))
diff --git a/fityk/ui.h b/fityk/ui.h
index abb18960..4b764dad 100644
--- a/fityk/ui.h
+++ b/fityk/ui.h
@@ -4,6 +4,7 @@
 #ifndef FITYK_UI_H_
 #define FITYK_UI_H_
 
+#include <csignal> // sig_atomic_t
 #include "common.h"
 #include "ui_api.h"
 
@@ -91,5 +92,7 @@ private:
     DISALLOW_COPY_AND_ASSIGN(UserInterface);
 };
 
+extern volatile std::sig_atomic_t user_interrupt;
+
 } // namespace fityk
 #endif
diff --git a/fityk/ui_api.cpp b/fityk/ui_api.cpp
index 6d0f7e44..69cdc43c 100644
--- a/fityk/ui_api.cpp
+++ b/fityk/ui_api.cpp
@@ -8,6 +8,7 @@
 #include <ctype.h> // for isspace
 #include "cparser.h"
 #include "mgr.h"
+#include "ui.h"
 #include "logic.h"
 #include "func.h"
 
@@ -53,6 +54,26 @@ const char* startup_commands_filename() { return "init"; }
 
 volatile std::sig_atomic_t user_interrupt = 0;
 
+void interrupt_computations()
+{
+    user_interrupt = 1;
+}
+
+static
+void interrupt_handler(int /*signum*/)
+{
+    interrupt_computations();
+}
+
+void interrupt_computations_on_sigint()
+{
+#ifndef _WIN32
+    // setting Ctrl-C handler
+    if (signal (SIGINT, interrupt_handler) == SIG_IGN)
+        signal (SIGINT, SIG_IGN);
+#endif //_WIN32
+}
+
 static
 void simple_show_message(UiApi::Style style, const string& s)
 {
diff --git a/fityk/ui_api.h b/fityk/ui_api.h
index 9c749ea8..77f1a708 100644
--- a/fityk/ui_api.h
+++ b/fityk/ui_api.h
@@ -4,7 +4,6 @@
 #ifndef FITYK_UI_API_H_
 #define FITYK_UI_API_H_
 
-#include <csignal> // sig_atomic_t
 #include <string>
 #include <vector>
 #include "fityk.h" // FITYK_API
@@ -92,8 +91,9 @@ complete_fityk_line(Fityk *F, const char* line_buffer, int start, int end,
 
 FITYK_API const char* startup_commands_filename(); // "init"
 FITYK_API const char* config_dirname(); // ".fityk"
-/// flag that is set to interrupt fitting (it is checked after each iteration)
-extern volatile FITYK_API std::sig_atomic_t user_interrupt;
+/// stops fitting after the current iteration
+FITYK_API void interrupt_computations();
+FITYK_API void interrupt_computations_on_sigint();
 
 } // namespace fityk
 #endif // FITYK_UI_API_H_
diff --git a/fityk/var.cpp b/fityk/var.cpp
index 1acb6168..5c9ae339 100644
--- a/fityk/var.cpp
+++ b/fityk/var.cpp
@@ -97,14 +97,14 @@ void Variable::set_var_idx(vector<Variable*> const& variables)
 
 string Variable::get_formula(vector<realt> const &parameters) const
 {
-    assert(gpos_ >= -1);
+    if (gpos_ >= 0)
+        return "~" + eS(parameters[gpos_]) + domain.str();
+    assert(gpos_ == -1);
     vector<string> vn;
     v_foreach (string, i, used_vars_.names())
         vn.push_back("$" + *i);
-    const char* num_format = "%.12g";
-    OpTreeFormat fmt = { num_format, &vn };
-    return gpos_ == -1 ? get_op_trees().back()->str(fmt)
-                    : "~" + eS(parameters[gpos_]);
+    OpTreeFormat fmt = { "%.12g", &vn };
+    return get_op_trees().back()->str(fmt);
 }
 
 void Variable::recalculate(vector<Variable*> const &variables,
diff --git a/fityk/view.h b/fityk/view.h
index 73296002..26459211 100644
--- a/fityk/view.h
+++ b/fityk/view.h
@@ -46,6 +46,8 @@ public:
     void change_view(const RealRange& hor_r, const RealRange& ver_r,
                      const std::vector<int>& datasets);
     void set_log_scale(bool log_x, bool log_y) { log_x_=log_x; log_y_=log_y; }
+    bool get_log_scale_x() const { return log_x_; }
+    bool get_log_scale_y() const { return log_y_; }
     double y0_factor() const { return y0_factor_; }
     void set_y0_factor(double f) { y0_factor_ = f; }
 private:
diff --git a/fityk/vm.cpp b/fityk/vm.cpp
index a89beb3e..a6e467da 100644
--- a/fityk/vm.cpp
+++ b/fityk/vm.cpp
@@ -109,7 +109,7 @@ string op2str(int op)
         OP_(FUNC) OP_(SUM_F) OP_(SUM_Z)
         OP_(NUMAREA) OP_(FINDX) OP_(FIND_EXTR)
         OP_(TILDE)
-        OP_(DATASET) OP_(DT_SUM_SAME_X) OP_(DT_AVG_SAME_X) OP_(DT_SHIRLEY_BG)
+        OP_(DATASET) OP_(DT_SUM_SAME_X) OP_(DT_AVG_SAME_X) OP_(DT_SHIRLEY_BG) OP_(DT_SNIP_BG)
         OP_(OPEN_ROUND)  OP_(OPEN_SQUARE)
     }
     return S(op); // unreachable (if all OPs are listed above)
@@ -633,6 +633,11 @@ void run_func_op(const vector<realt>& numbers, vector<int>::const_iterator &i,
 
         case OP_TILDE:
             // used for default values in Runner::make_func_from_template()
+            // compare with ModelManager::eval_tilde()
+            assert(*(i+1) == OP_NUMBER);
+            STACK_OFFSET_CHANGE(+1);
+            *stackPtr = numbers[*(i+2)];
+            i += (*(i+3) == OP_TILDE ? 3 : 6);
             break;
 
         default:
diff --git a/fityk/vm.h b/fityk/vm.h
index 0aa3437c..7532b011 100644
--- a/fityk/vm.h
+++ b/fityk/vm.h
@@ -101,6 +101,7 @@ enum Op
     OP_DT_SUM_SAME_X,
     OP_DT_AVG_SAME_X,
     OP_DT_SHIRLEY_BG,
+    OP_DT_SNIP_BG,
 
     // these two are not VM operators, but are handy to have here,
     // they and are used in implementation of shunting yard algorithm
diff --git a/fityk/voigt.cpp b/fityk/voigt.cpp
index 5381a63d..07a8c340 100644
--- a/fityk/voigt.cpp
+++ b/fityk/voigt.cpp
@@ -1,6 +1,6 @@
 
 // fastest_humlik.for and humdev.for - from Bob Wells Voigt Function Page
-// http://www.atm.ox.ac.uk/user/wells/voigt.html
+// http://web.archive.org/web/20100503005358/http://www.atm.ox.ac.uk/user/wells/voigt.html
 // Translated to C++ with f2c program and modified by M.W.
 // It can be slower than original, I haven't compared the speed.
 
@@ -10,7 +10,6 @@
 
 ///     Calculates the Faddeeva function
 ///     and partial derivatives of the Voigt function for y>=0
-///     (from http://www.atm.ox.ac.uk/user/wells/voigt.html)
 /// arguments:
 ///  x, y - Faddeeva/Voigt function arguments
 ///  k - voigt              -- output
@@ -28,7 +27,7 @@ void humdev(const float x, const float y,
                                 2.2795071f,      3.020637f,        3.8897249f };
 
     static const float rrtpi = 0.56418958f; // 1/SQRT(pi)
-    static const double drtpi = 0.5641895835477563f; // 1/SQRT(pi)
+    static const double drtpi = 0.5641895835477563; // 1/SQRT(pi)
 
     static float a0, b1, c0, c2, d0, d1, d2, e0, e2, e4, f1, f3, f5,
                  g0, g2, g4, g6, h0, h2, h4, h6, p0, p2, p4, p6, p8,
@@ -43,7 +42,9 @@ void humdev(const float x, const float y,
 
     if (y != old_y) {
         old_y = y;
-        rgb = true, rgc = true, rgd = true;
+        rgb = true;
+        rgc = true;
+        rgd = true;
         yq = y * y;
         xlima = 146.7f - y;
         xlimb = 24.f - y;
@@ -234,7 +235,6 @@ void humdev(const float x, const float y,
 
 
 ///   Calculates the Faddeeva function with relative error less than 10^(-4).
-///     (from http://www.atm.ox.ac.uk/user/wells/voigt.html)
 /// arguments:
 ///  x, y - Faddeeva/Voigt function arguments
 /// return value -- voigt
@@ -261,14 +261,16 @@ float humlik(const float x, const float y)
         old_y = y;
         yq = y * y;
         yrrtpi = y * rrtpi;
-        rg1 = true, rg2 = true, rg3 = true;
-        if (y < 70.55) {
+        rg1 = true;
+        rg2 = true;
+        rg3 = true;
+        if (y < 70.55f) {
             xlim0 = sqrt(y * (40.f - y * 3.6f) + 15100.f);
-            xlim1 = (y >= 8.425 ?  0.f : sqrt(164.f - y * (y * 1.8f + 4.3f)));
+            xlim1 = (y >= 8.425f ?  0.f : sqrt(164.f - y * (y * 1.8f + 4.3f)));
             xlim2 = 6.8f - y;
             xlim3 = y * 2.4f;
             xlim4 = y * 18.1f + 1.65f;
-            if (y <= 1e-6)
+            if (y <= 1e-6f)
                 xlim2 = xlim1 = xlim0;
         }
     }
@@ -276,7 +278,7 @@ float humlik(const float x, const float y)
     float abx = fabs(x);
     float xq = abx * abx;
 
-    if (abx >= xlim0 || y >= 70.55)         // Region 0 algorithm
+    if (abx >= xlim0 || y >= 70.55f)         // Region 0 algorithm
         return yrrtpi / (xq + yq);
 
     else if (abx >= xlim1) {            //  Humlicek W4 Region 1
diff --git a/fityk/voigt.h b/fityk/voigt.h
index 511122d5..647a97d8 100644
--- a/fityk/voigt.h
+++ b/fityk/voigt.h
@@ -1,7 +1,8 @@
 
 ///     calculates the Faddeeva function
 ///     and partial derivatives of the Voigt function for y>=0
-///     (from http://www.atm.ox.ac.uk/user/wells/voigt.html)
+///     Based on (now only in Wayback Machine):
+///     http://web.archive.org/web/20100503005358/http://www.atm.ox.ac.uk/user/wells/voigt.html
 void humdev(const float x, const float y,
             float &k, float &l, float &dkdx, float &dkdy);
         // arguments:
@@ -13,7 +14,6 @@ void humdev(const float x, const float y,
 
 
 ///     calculates the Faddeeva function with relative error less than 10^(-4).
-///     (from http://www.atm.ox.ac.uk/user/wells/voigt.html)
 float humlik(const float x, const float y);
         // arguments:
         //  x, y - Faddeeva/Voigt function arguments
diff --git a/m4/ax_lib_readline.m4 b/m4/ax_lib_readline.m4
index 056f25c2..0d0822bc 100644
--- a/m4/ax_lib_readline.m4
+++ b/m4/ax_lib_readline.m4
@@ -1,5 +1,5 @@
 # ===========================================================================
-#      http://www.gnu.org/software/autoconf-archive/ax_lib_readline.html
+#     https://www.gnu.org/software/autoconf-archive/ax_lib_readline.html
 # ===========================================================================
 #
 # SYNOPSIS
@@ -58,7 +58,7 @@
 #   and this notice are preserved. This file is offered as-is, without any
 #   warranty.
 
-#serial 6
+#serial 8
 
 AU_ALIAS([VL_LIB_READLINE], [AX_LIB_READLINE])
 AC_DEFUN([AX_LIB_READLINE], [
@@ -73,7 +73,7 @@ AC_DEFUN([AX_LIB_READLINE], [
           TRY_LIB="-l$readline_lib -l$termcap_lib"
         fi
         LIBS="$ORIG_LIBS $TRY_LIB"
-        AC_TRY_LINK_FUNC(readline, ax_cv_lib_readline="$TRY_LIB")
+        AC_LINK_IFELSE([AC_LANG_CALL([], [readline])], [ax_cv_lib_readline="$TRY_LIB"])
         if test -n "$ax_cv_lib_readline"; then
           break
         fi
@@ -96,7 +96,7 @@ AC_DEFUN([AX_LIB_READLINE], [
     AC_CACHE_CHECK([whether readline supports history],
                    ax_cv_lib_readline_history, [
       ax_cv_lib_readline_history="no"
-      AC_TRY_LINK_FUNC(add_history, ax_cv_lib_readline_history="yes")
+      AC_LINK_IFELSE([AC_LANG_CALL([], [add_history])], [ax_cv_lib_readline_history="yes"])
     ])
     if test "$ax_cv_lib_readline_history" = "yes"; then
       AC_DEFINE(HAVE_READLINE_HISTORY, 1,
diff --git a/m4/ax_lua.m4 b/m4/ax_lua.m4
index 9feb3522..59201671 100644
--- a/m4/ax_lua.m4
+++ b/m4/ax_lua.m4
@@ -1,5 +1,5 @@
 # ===========================================================================
-#          http://www.gnu.org/software/autoconf-archive/ax_lua.html
+#          https://www.gnu.org/software/autoconf-archive/ax_lua.html
 # ===========================================================================
 #
 # SYNOPSIS
@@ -166,7 +166,7 @@
 #   Public License for more details.
 #
 #   You should have received a copy of the GNU General Public License along
-#   with this program. If not, see <http://www.gnu.org/licenses/>.
+#   with this program. If not, see <https://www.gnu.org/licenses/>.
 #
 #   As a special exception, the respective Autoconf Macro's copyright owner
 #   gives unlimited permission to copy, distribute and modify the configure
@@ -181,7 +181,7 @@
 #   modified version of the Autoconf Macro, you may extend this special
 #   exception to the GPL to apply to your modified version as well.
 
-#serial 39
+#serial 40
 
 dnl =========================================================================
 dnl AX_PROG_LUA([MINIMUM-VERSION], [TOO-BIG-VERSION],
diff --git a/m4/ax_pkg_swig.m4 b/m4/ax_pkg_swig.m4
index 73fbffef..49717385 100644
--- a/m4/ax_pkg_swig.m4
+++ b/m4/ax_pkg_swig.m4
@@ -1,5 +1,5 @@
 # ===========================================================================
-#        http://www.gnu.org/software/autoconf-archive/ax_pkg_swig.html
+#       https://www.gnu.org/software/autoconf-archive/ax_pkg_swig.html
 # ===========================================================================
 #
 # SYNOPSIS
@@ -36,6 +36,7 @@
 #   Copyright (c) 2008 Rafael Laboissiere <rafael@laboissiere.net>
 #   Copyright (c) 2008 Andrew Collier
 #   Copyright (c) 2011 Murray Cumming <murrayc@openismus.com>
+#   Copyright (c) 2021 Vincent Danjean <Vincent.Danjean@ens-lyon.org>
 #
 #   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
@@ -48,7 +49,7 @@
 #   Public License for more details.
 #
 #   You should have received a copy of the GNU General Public License along
-#   with this program. If not, see <http://www.gnu.org/licenses/>.
+#   with this program. If not, see <https://www.gnu.org/licenses/>.
 #
 #   As a special exception, the respective Autoconf Macro's copyright owner
 #   gives unlimited permission to copy, distribute and modify the configure
@@ -63,14 +64,16 @@
 #   modified version of the Autoconf Macro, you may extend this special
 #   exception to the GPL to apply to your modified version as well.
 
-#serial 12
+#serial 14
 
 AC_DEFUN([AX_PKG_SWIG],[
         # Find path to the "swig" executable.
         AC_PATH_PROGS([SWIG],[swig swig3.0 swig2.0])
         if test -z "$SWIG" ; then
                 m4_ifval([$3],[$3],[:])
-        elif test -n "$1" ; then
+        elif test -z "$1" ; then
+                m4_ifval([$2],[$2],[:])
+	else
                 AC_MSG_CHECKING([SWIG version])
                 [swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`]
                 AC_MSG_RESULT([$swig_version])
@@ -81,12 +84,12 @@ AC_DEFUN([AX_PKG_SWIG],[
                         if test -z "$required_major" ; then
                                 [required_major=0]
                         fi
-                        [required=`echo $required | sed 's/[0-9]*[^0-9]//'`]
+                        [required=`echo $required. | sed 's/[0-9]*[^0-9]//'`]
                         [required_minor=`echo $required | sed 's/[^0-9].*//'`]
                         if test -z "$required_minor" ; then
                                 [required_minor=0]
                         fi
-                        [required=`echo $required | sed 's/[0-9]*[^0-9]//'`]
+                        [required=`echo $required. | sed 's/[0-9]*[^0-9]//'`]
                         [required_patch=`echo $required | sed 's/[^0-9].*//'`]
                         if test -z "$required_patch" ; then
                                 [required_patch=0]
diff --git a/m4/ax_python_devel.m4 b/m4/ax_python_devel.m4
index f18ed8a0..c79f042c 100644
--- a/m4/ax_python_devel.m4
+++ b/m4/ax_python_devel.m4
@@ -1,5 +1,5 @@
 # ===========================================================================
-#      http://www.gnu.org/software/autoconf-archive/ax_python_devel.html
+#     https://www.gnu.org/software/autoconf-archive/ax_python_devel.html
 # ===========================================================================
 #
 # SYNOPSIS
@@ -52,7 +52,7 @@
 #   Public License for more details.
 #
 #   You should have received a copy of the GNU General Public License along
-#   with this program. If not, see <http://www.gnu.org/licenses/>.
+#   with this program. If not, see <https://www.gnu.org/licenses/>.
 #
 #   As a special exception, the respective Autoconf Macro's copyright owner
 #   gives unlimited permission to copy, distribute and modify the configure
@@ -67,7 +67,7 @@
 #   modified version of the Autoconf Macro, you may extend this special
 #   exception to the GPL to apply to your modified version as well.
 
-#serial 18
+#serial 25
 
 AU_ALIAS([AC_PYTHON_DEVEL], [AX_PYTHON_DEVEL])
 AC_DEFUN([AX_PYTHON_DEVEL],[
@@ -112,15 +112,39 @@ to something else than an empty string.
 	fi
 
 	#
-	# if the macro parameter ``version'' is set, honour it
+	# If the macro parameter ``version'' is set, honour it.
+	# A Python shim class, VPy, is used to implement correct version comparisons via
+	# string expressions, since e.g. a naive textual ">= 2.7.3" won't work for
+	# Python 2.7.10 (the ".1" being evaluated as less than ".3").
 	#
 	if test -n "$1"; then
 		AC_MSG_CHECKING([for a version of Python $1])
-		ac_supports_python_ver=`$PYTHON -c "import sys; \
-			ver = sys.version.split ()[[0]]; \
+                cat << EOF > ax_python_devel_vpy.py
+class VPy:
+    def vtup(self, s):
+        return tuple(map(int, s.strip().replace("rc", ".").split(".")))
+    def __init__(self):
+        import sys
+        self.vpy = tuple(sys.version_info)
+    def __eq__(self, s):
+        return self.vpy == self.vtup(s)
+    def __ne__(self, s):
+        return self.vpy != self.vtup(s)
+    def __lt__(self, s):
+        return self.vpy < self.vtup(s)
+    def __gt__(self, s):
+        return self.vpy > self.vtup(s)
+    def __le__(self, s):
+        return self.vpy <= self.vtup(s)
+    def __ge__(self, s):
+        return self.vpy >= self.vtup(s)
+EOF
+		ac_supports_python_ver=`$PYTHON -c "import ax_python_devel_vpy; \
+                        ver = ax_python_devel_vpy.VPy(); \
 			print (ver $1)"`
+                rm -rf ax_python_devel_vpy*.py* __pycache__/ax_python_devel_vpy*.py*
 		if test "$ac_supports_python_ver" = "True"; then
-		   AC_MSG_RESULT([yes])
+			AC_MSG_RESULT([yes])
 		else
 			AC_MSG_RESULT([no])
 			AC_MSG_ERROR([this package requires Python $1.
@@ -135,16 +159,25 @@ variable to configure. See ``configure --help'' for reference.
 	#
 	# Check if you have distutils, else fail
 	#
-	AC_MSG_CHECKING([for the distutils Python package])
-	ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`
-	if test -z "$ac_distutils_result"; then
+	AC_MSG_CHECKING([for the sysconfig Python package])
+	ac_sysconfig_result=`$PYTHON -c "import sysconfig" 2>&1`
+	if test $? -eq 0; then
 		AC_MSG_RESULT([yes])
+		IMPORT_SYSCONFIG="import sysconfig"
 	else
 		AC_MSG_RESULT([no])
-		AC_MSG_ERROR([cannot import Python module "distutils".
+
+		AC_MSG_CHECKING([for the distutils Python package])
+		ac_sysconfig_result=`$PYTHON -c "from distutils import sysconfig" 2>&1`
+		if test $? -eq 0; then
+			AC_MSG_RESULT([yes])
+			IMPORT_SYSCONFIG="from distutils import sysconfig"
+		else
+			AC_MSG_ERROR([cannot import Python module "distutils".
 Please check your Python installation. The error was:
-$ac_distutils_result])
-		PYTHON_VERSION=""
+$ac_sysconfig_result])
+			PYTHON_VERSION=""
+		fi
 	fi
 
 	#
@@ -152,10 +185,19 @@ $ac_distutils_result])
 	#
 	AC_MSG_CHECKING([for Python include path])
 	if test -z "$PYTHON_CPPFLAGS"; then
-		python_path=`$PYTHON -c "import distutils.sysconfig; \
-			print (distutils.sysconfig.get_python_inc ());"`
-		plat_python_path=`$PYTHON -c "import distutils.sysconfig; \
-			print (distutils.sysconfig.get_python_inc (plat_specific=1));"`
+		if test "$IMPORT_SYSCONFIG" = "import sysconfig"; then
+			# sysconfig module has different functions
+			python_path=`$PYTHON -c "$IMPORT_SYSCONFIG; \
+				print (sysconfig.get_path ('include'));"`
+			plat_python_path=`$PYTHON -c "$IMPORT_SYSCONFIG; \
+				print (sysconfig.get_path ('platinclude'));"`
+		else
+			# old distutils way
+			python_path=`$PYTHON -c "$IMPORT_SYSCONFIG; \
+				print (sysconfig.get_python_inc ());"`
+			plat_python_path=`$PYTHON -c "$IMPORT_SYSCONFIG; \
+				print (sysconfig.get_python_inc (plat_specific=1));"`
+		fi
 		if test -n "${python_path}"; then
 			if test "${plat_python_path}" != "${python_path}"; then
 				python_path="-I$python_path -I$plat_python_path"
@@ -179,7 +221,7 @@ $ac_distutils_result])
 
 # join all versioning strings, on some systems
 # major/minor numbers could be in different list elements
-from distutils.sysconfig import *
+from sysconfig import *
 e = get_config_var('VERSION')
 if e is not None:
 	print(e)
@@ -202,8 +244,8 @@ EOD`
 		ac_python_libdir=`cat<<EOD | $PYTHON -
 
 # There should be only one
-import distutils.sysconfig
-e = distutils.sysconfig.get_config_var('LIBDIR')
+$IMPORT_SYSCONFIG
+e = sysconfig.get_config_var('LIBDIR')
 if e is not None:
 	print (e)
 EOD`
@@ -211,8 +253,8 @@ EOD`
 		# Now, for the library:
 		ac_python_library=`cat<<EOD | $PYTHON -
 
-import distutils.sysconfig
-c = distutils.sysconfig.get_config_vars()
+$IMPORT_SYSCONFIG
+c = sysconfig.get_config_vars()
 if 'LDVERSION' in c:
 	print ('python'+c[['LDVERSION']])
 else:
@@ -231,7 +273,7 @@ EOD`
 		else
 			# old way: use libpython from python_configdir
 			ac_python_libdir=`$PYTHON -c \
-			  "from distutils.sysconfig import get_python_lib as f; \
+			  "from sysconfig import get_python_lib as f; \
 			  import os; \
 			  print (os.path.join(f(plat_specific=1, standard_lib=1), 'config'));"`
 			PYTHON_LIBS="-L$ac_python_libdir -lpython$ac_python_version"
@@ -252,35 +294,58 @@ EOD`
 	#
 	AC_MSG_CHECKING([for Python site-packages path])
 	if test -z "$PYTHON_SITE_PKG"; then
-		PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \
-			print (distutils.sysconfig.get_python_lib(0,0));"`
+		if test "$IMPORT_SYSCONFIG" = "import sysconfig"; then
+			PYTHON_SITE_PKG=`$PYTHON -c "$IMPORT_SYSCONFIG; \
+				print (sysconfig.get_path('purelib'));"`
+		else
+			# distutils.sysconfig way
+			PYTHON_SITE_PKG=`$PYTHON -c "$IMPORT_SYSCONFIG; \
+				print (sysconfig.get_python_lib(0,0));"`
+		fi
 	fi
 	AC_MSG_RESULT([$PYTHON_SITE_PKG])
 	AC_SUBST([PYTHON_SITE_PKG])
 
+	#
+	# Check for platform-specific site packages
+	#
+	AC_MSG_CHECKING([for Python platform specific site-packages path])
+	if test -z "$PYTHON_SITE_PKG"; then
+		if test "$IMPORT_SYSCONFIG" = "import sysconfig"; then
+			PYTHON_PLATFORM_SITE_PKG=`$PYTHON -c "$IMPORT_SYSCONFIG; \
+				print (sysconfig.get_path('platlib'));"`
+		else
+			# distutils.sysconfig way
+			PYTHON_PLATFORM_SITE_PKG=`$PYTHON -c "$IMPORT_SYSCONFIG; \
+				print (sysconfig.get_python_lib(1,0));"`
+		fi
+	fi
+	AC_MSG_RESULT([$PYTHON_PLATFORM_SITE_PKG])
+	AC_SUBST([PYTHON_PLATFORM_SITE_PKG])
+
 	#
 	# libraries which must be linked in when embedding
 	#
 	AC_MSG_CHECKING(python extra libraries)
-	if test -z "$PYTHON_EXTRA_LDFLAGS"; then
-	   PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import distutils.sysconfig; \
-                conf = distutils.sysconfig.get_config_var; \
+	if test -z "$PYTHON_EXTRA_LIBS"; then
+	   PYTHON_EXTRA_LIBS=`$PYTHON -c "$IMPORT_SYSCONFIG; \
+                conf = sysconfig.get_config_var; \
                 print (conf('LIBS') + ' ' + conf('SYSLIBS'))"`
 	fi
-	AC_MSG_RESULT([$PYTHON_EXTRA_LDFLAGS])
-	AC_SUBST(PYTHON_EXTRA_LDFLAGS)
+	AC_MSG_RESULT([$PYTHON_EXTRA_LIBS])
+	AC_SUBST(PYTHON_EXTRA_LIBS)
 
 	#
 	# linking flags needed when embedding
 	#
 	AC_MSG_CHECKING(python extra linking flags)
-	if test -z "$PYTHON_EXTRA_LIBS"; then
-		PYTHON_EXTRA_LIBS=`$PYTHON -c "import distutils.sysconfig; \
-			conf = distutils.sysconfig.get_config_var; \
+	if test -z "$PYTHON_EXTRA_LDFLAGS"; then
+		PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "$IMPORT_SYSCONFIG; \
+			conf = sysconfig.get_config_var; \
 			print (conf('LINKFORSHARED'))"`
 	fi
-	AC_MSG_RESULT([$PYTHON_EXTRA_LIBS])
-	AC_SUBST(PYTHON_EXTRA_LIBS)
+	AC_MSG_RESULT([$PYTHON_EXTRA_LDFLAGS])
+	AC_SUBST(PYTHON_EXTRA_LDFLAGS)
 
 	#
 	# final check to see if everything compiles alright
diff --git a/m4/wxwin.m4 b/m4/wxwin.m4
index f8e5b704..ec0ab09b 100644
--- a/m4/wxwin.m4
+++ b/m4/wxwin.m4
@@ -64,7 +64,7 @@ dnl If you want to support standard --enable-debug/unicode/shared options, you
 dnl may do the following:
 dnl
 dnl     ...
-dnl     AC_CANONICAL_SYSTEM
+dnl     AC_CANONICAL_TARGET
 dnl
 dnl     # define configure options
 dnl     WX_CONFIG_OPTIONS
@@ -142,7 +142,8 @@ AC_DEFUN([_WX_PRIVATE_CHECK_VERSION],
 
 dnl ---------------------------------------------------------------------------
 dnl WX_CONFIG_CHECK(VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND
-dnl                  [, WX-LIBS [, ADDITIONAL-WX-CONFIG-FLAGS]]]])
+dnl                  [, WX-LIBS [, ADDITIONAL-WX-CONFIG-FLAGS
+dnl                  [, WX-OPTIONAL-LIBS]]]]])
 dnl
 dnl Test for wxWidgets, and define WX_C*FLAGS, WX_LIBS and WX_LIBS_STATIC
 dnl (the latter is for static linking against wxWidgets). Set WX_CONFIG_NAME
@@ -159,6 +160,10 @@ dnl Optional ADDITIONAL-WX-CONFIG-FLAGS argument is appended to wx-config
 dnl invocation command in present. It can be used to fine-tune lookup of
 dnl best wxWidgets build available.
 dnl
+dnl Optional WX-OPTIONAL-LIBS argument contains comma- or space-separated list
+dnl of wxWidgets libraries to link against if they are available.
+dnl WX-OPTIONAL-LIBS is supported on version 2.9.0 and later.
+dnl
 dnl Example use:
 dnl   WX_CONFIG_CHECK([2.6.0], [wxWin=1], [wxWin=0], [html,core,net]
 dnl                    [--unicode --debug])
@@ -210,8 +215,8 @@ AC_DEFUN([WX_CONFIG_CHECK],
       AC_MSG_CHECKING([for wxWidgets version >= $min_wx_version ($5)])
     fi
 
-    dnl don't add the libraries ($4) to this variable as this would result in
-    dnl an error when it's used with --version below
+    dnl don't add the libraries (4th argument) to this variable as this would
+    dnl result in an error when it's used with --version below
     WX_CONFIG_WITH_ARGS="$WX_CONFIG_PATH $wx_config_args $5"
 
     WX_VERSION=`$WX_CONFIG_WITH_ARGS --version 2>/dev/null`
@@ -235,14 +240,20 @@ AC_DEFUN([WX_CONFIG_CHECK],
 
     if test -n "$wx_ver_ok"; then
       AC_MSG_RESULT(yes (version $WX_VERSION))
-      WX_LIBS=`$WX_CONFIG_WITH_ARGS --libs $4`
+
+      wx_optional_libs=""
+      _WX_PRIVATE_CHECK_VERSION(2,9,0)
+      if test -n "$wx_ver_ok" -a -n "$6"; then
+        wx_optional_libs="--optional-libs $6"
+      fi
+      WX_LIBS=`$WX_CONFIG_WITH_ARGS --libs $4 $wx_optional_libs`
 
       dnl is this even still appropriate?  --static is a real option now
       dnl and WX_CONFIG_WITH_ARGS is likely to contain it if that is
       dnl what the user actually wants, making this redundant at best.
       dnl For now keep it in case anyone actually used it in the past.
       AC_MSG_CHECKING([for wxWidgets static library])
-      WX_LIBS_STATIC=`$WX_CONFIG_WITH_ARGS --static --libs $4 2>/dev/null`
+      WX_LIBS_STATIC=`$WX_CONFIG_WITH_ARGS --static --libs $4 $wx_optional_libs 2>/dev/null`
       if test "x$WX_LIBS_STATIC" = "x"; then
         AC_MSG_RESULT(no)
       else
@@ -505,7 +516,7 @@ dnl $5 = additional action to do in case option is given with "yes" value
 dnl ---------------------------------------------------------------------------
 AC_DEFUN([WX_ARG_ENABLE_YESNOAUTO],
          [AC_ARG_ENABLE($1,
-            AC_HELP_STRING([--enable-$1], [$3 (default is $4)]),
+            AS_HELP_STRING([--enable-$1],[$3 (default is $4)]),
             [], [enableval="$4"])
 
             dnl Show a message to the user about this option
@@ -519,7 +530,7 @@ AC_DEFUN([WX_ARG_ENABLE_YESNOAUTO],
                 $2=0
             elif test "$enableval" = "auto" ; then
                 AC_MSG_RESULT([will be automatically detected])
-                $2="auto"
+                $2=""
             else
                 AC_MSG_ERROR([
     Unrecognized option value (allowed values: yes, no, auto)
@@ -529,7 +540,7 @@ AC_DEFUN([WX_ARG_ENABLE_YESNOAUTO],
 
 AC_DEFUN([WX_ARG_WITH_YESNOAUTO],
          [AC_ARG_WITH($1,
-            AC_HELP_STRING([--with-$1], [$3 (default is $4)]),
+            AS_HELP_STRING([--with-$1],[$3 (default is $4)]),
             [], [withval="$4"])
 
             dnl Show a message to the user about this option
@@ -545,7 +556,7 @@ AC_DEFUN([WX_ARG_WITH_YESNOAUTO],
                 $2=0
             elif test "$withval" = "auto" ; then
                 AC_MSG_RESULT([will be automatically detected])
-                $2="auto"
+                $2=""
             else
                 AC_MSG_ERROR([
     Unrecognized option value (allowed values: yes, auto)
@@ -589,25 +600,24 @@ AC_DEFUN([WX_STANDARD_OPTIONS],
         ifelse(index([$1], [toolkit]), [-1],,
                [
                 AC_ARG_WITH([toolkit],
-                            AC_HELP_STRING([--with-toolkit],
-                                           [Build against a specific wxWidgets toolkit (default is auto)]),
+                            AS_HELP_STRING([--with-toolkit],[Build against a specific wxWidgets toolkit (default is auto)]),
                             [], [withval="auto"])
 
                 dnl Show a message to the user about this option
                 AC_MSG_CHECKING([for the --with-toolkit option])
                 if test "$withval" = "auto" ; then
                     AC_MSG_RESULT([will be automatically detected])
-                    TOOLKIT="auto"
+                    TOOLKIT=""
                 else
                     TOOLKIT="$withval"
 
                     dnl PORT must be one of the allowed values
-                    if test "$TOOLKIT" != "gtk1" -a "$TOOLKIT" != "gtk2" -a \
+                    if test "$TOOLKIT" != "gtk1" -a "$TOOLKIT" != "gtk2" -a "$TOOLKIT" != "gtk3" -a \
                             "$TOOLKIT" != "msw" -a "$TOOLKIT" != "motif" -a \
                             "$TOOLKIT" != "osx_carbon" -a "$TOOLKIT" != "osx_cocoa" -a \
-                            "$TOOLKIT" != "dfb" -a "$TOOLKIT" != "x11"; then
+                            "$TOOLKIT" != "dfb" -a "$TOOLKIT" != "x11" -a "$TOOLKIT" != "base"; then
                         AC_MSG_ERROR([
-    Unrecognized option value (allowed values: auto, gtk1, gtk2, msw, motif, osx_carbon, osx_cocoa, dfb, x11)
+    Unrecognized option value (allowed values: auto, gtk1, gtk2, gtk3, msw, motif, osx_carbon, osx_cocoa, dfb, x11, base)
                         ])
                     fi
 
@@ -663,15 +673,14 @@ AC_DEFUN([WX_STANDARD_OPTIONS],
         ifelse(index([$1], [wxversion]), [-1],,
                [
                 AC_ARG_WITH([wxversion],
-                            AC_HELP_STRING([--with-wxversion],
-                                           [Build against a specific version of wxWidgets (default is auto)]),
+                            AS_HELP_STRING([--with-wxversion],[Build against a specific version of wxWidgets (default is auto)]),
                             [], [withval="auto"])
 
                 dnl Show a message to the user about this option
                 AC_MSG_CHECKING([for the --with-wxversion option])
                 if test "$withval" = "auto" ; then
                     AC_MSG_RESULT([will be automatically detected])
-                    WX_RELEASE="auto"
+                    WX_RELEASE=""
                 else
 
                     wx_requested_major_version=`echo $withval | \
@@ -706,7 +715,7 @@ dnl ---------------------------------------------------------------------------
 dnl WX_CONVERT_STANDARD_OPTIONS_TO_WXCONFIG_FLAGS
 dnl
 dnl Sets the WXCONFIG_FLAGS string using the SHARED,DEBUG,UNICODE variable values
-dnl which are different from "auto".
+dnl which were specified.
 dnl Thus this macro needs to be called only once all options have been set.
 dnl ---------------------------------------------------------------------------
 AC_DEFUN([WX_CONVERT_STANDARD_OPTIONS_TO_WXCONFIG_FLAGS],
@@ -730,11 +739,11 @@ AC_DEFUN([WX_CONVERT_STANDARD_OPTIONS_TO_WXCONFIG_FLAGS],
             WXCONFIG_FLAGS="$WXCONFIG_FLAGS""--unicode=no "
         fi
 
-        if test "$TOOLKIT" != "auto" ; then
+        if test -n "$TOOLKIT" ; then
             WXCONFIG_FLAGS="$WXCONFIG_FLAGS""--toolkit=$TOOLKIT "
         fi
 
-        if test "$WX_RELEASE" != "auto" ; then
+        if test -n "$WX_RELEASE" ; then
             WXCONFIG_FLAGS="$WXCONFIG_FLAGS""--version=$WX_RELEASE "
         fi
 
@@ -748,16 +757,16 @@ AC_DEFUN([WX_CONVERT_STANDARD_OPTIONS_TO_WXCONFIG_FLAGS],
 
 
 dnl ---------------------------------------------------------------------------
-dnl _WX_SELECTEDCONFIG_CHECKFOR([RESULTVAR], [STRING], [MSG]
-dnl                             [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
+dnl _WX_SELECTEDCONFIG_CHECKFOR([RESULTVAR], [STRING], [MSG])
 dnl
-dnl Outputs the given MSG. Then searches the given STRING in the wxWidgets
-dnl additional CPP flags and put the result of the search in WX_$RESULTVAR
-dnl also adding the "yes" or "no" message result to MSG.
+dnl Sets WX_$RESULTVAR to the value of $RESULTVAR if it's defined. Otherwise,
+dnl auto-detect the value by checking for the presence of STRING in
+dnl $WX_SELECTEDCONFIG (which is supposed to be set by caller) and set
+dnl WX_$RESULTVAR to either 0 or 1, also outputting "yes" or "no" after MSG.
 dnl ---------------------------------------------------------------------------
 AC_DEFUN([_WX_SELECTEDCONFIG_CHECKFOR],
         [
-        if test "$$1" = "auto" ; then
+        if test -z "$$1" ; then
 
             dnl The user does not have particular preferences for this option;
             dnl so we will detect the wxWidgets relative build setting and use it
@@ -772,11 +781,9 @@ AC_DEFUN([_WX_SELECTEDCONFIG_CHECKFOR],
             if test "$WX_$1" != "0"; then
                 WX_$1=1
                 AC_MSG_RESULT([yes])
-                ifelse([$4], , :, [$4])
             else
                 WX_$1=0
                 AC_MSG_RESULT([no])
-                ifelse([$5], , :, [$5])
             fi
         else
 
@@ -823,19 +830,16 @@ AC_DEFUN([WX_DETECT_STANDARD_OPTION_VALUES],
             echo "[[dbg]] WX_SELECTEDCONFIG: $WX_SELECTEDCONFIG"
         fi
 
-
         dnl we could test directly for WX_SHARED with a line like:
         dnl    _WX_SELECTEDCONFIG_CHECKFOR([SHARED], [shared],
         dnl                                [if wxWidgets was built in SHARED mode])
         dnl but wx-config --selected-config DOES NOT outputs the 'shared'
         dnl word when wx was built in shared mode; it rather outputs the
         dnl 'static' word when built in static mode.
-        if test $WX_SHARED = "1"; then
+        if test "$WX_SHARED" = "1"; then
             STATIC=0
-        elif test $WX_SHARED = "0"; then
+        elif test "$WX_SHARED" = "0"; then
             STATIC=1
-        elif test $WX_SHARED = "auto"; then
-            STATIC="auto"
         fi
 
         dnl Now set the WX_UNICODE, WX_DEBUG, WX_STATIC variables
@@ -858,7 +862,7 @@ AC_DEFUN([WX_DETECT_STANDARD_OPTION_VALUES],
         AC_SUBST(WX_SHARED)
 
         dnl detect the WX_PORT to use
-        if test "$TOOLKIT" = "auto" ; then
+        if test -z "$TOOLKIT" ; then
 
             dnl The user does not have particular preferences for this option;
             dnl so we will detect the wxWidgets relative build setting and use it
@@ -866,22 +870,26 @@ AC_DEFUN([WX_DETECT_STANDARD_OPTION_VALUES],
 
             WX_GTKPORT1=$(expr "$WX_SELECTEDCONFIG" : ".*gtk1.*")
             WX_GTKPORT2=$(expr "$WX_SELECTEDCONFIG" : ".*gtk2.*")
+            WX_GTKPORT3=$(expr "$WX_SELECTEDCONFIG" : ".*gtk3.*")
             WX_MSWPORT=$(expr "$WX_SELECTEDCONFIG" : ".*msw.*")
             WX_MOTIFPORT=$(expr "$WX_SELECTEDCONFIG" : ".*motif.*")
             WX_OSXCOCOAPORT=$(expr "$WX_SELECTEDCONFIG" : ".*osx_cocoa.*")
             WX_OSXCARBONPORT=$(expr "$WX_SELECTEDCONFIG" : ".*osx_carbon.*")
             WX_X11PORT=$(expr "$WX_SELECTEDCONFIG" : ".*x11.*")
             WX_DFBPORT=$(expr "$WX_SELECTEDCONFIG" : ".*dfb.*")
+            WX_BASEPORT=$(expr "$WX_SELECTEDCONFIG" : ".*base.*")
 
             WX_PORT="unknown"
             if test "$WX_GTKPORT1" != "0"; then WX_PORT="gtk1"; fi
             if test "$WX_GTKPORT2" != "0"; then WX_PORT="gtk2"; fi
+            if test "$WX_GTKPORT3" != "0"; then WX_PORT="gtk3"; fi
             if test "$WX_MSWPORT" != "0"; then WX_PORT="msw"; fi
             if test "$WX_MOTIFPORT" != "0"; then WX_PORT="motif"; fi
             if test "$WX_OSXCOCOAPORT" != "0"; then WX_PORT="osx_cocoa"; fi
             if test "$WX_OSXCARBONPORT" != "0"; then WX_PORT="osx_carbon"; fi
             if test "$WX_X11PORT" != "0"; then WX_PORT="x11"; fi
             if test "$WX_DFBPORT" != "0"; then WX_PORT="dfb"; fi
+            if test "$WX_BASEPORT" != "0"; then WX_PORT="base"; fi
 
             dnl NOTE: backward-compatible check for wx2.8; in wx2.9 the mac
             dnl       ports are called 'osx_cocoa' and 'osx_carbon' (see above)
@@ -899,14 +907,8 @@ AC_DEFUN([WX_DETECT_STANDARD_OPTION_VALUES],
 
             AC_MSG_RESULT([$WX_PORT])
         else
-
             dnl Use the setting given by the user
-            if test -z "$TOOLKIT" ; then
-                WX_PORT=$TOOLKIT
-            else
-                dnl try with PORT
-                WX_PORT=$PORT
-            fi
+            WX_PORT=$TOOLKIT
         fi
 
         AC_SUBST(WX_PORT)
@@ -937,35 +939,29 @@ AC_DEFUN([WX_DETECT_STANDARD_OPTION_VALUES],
                          ])
         fi
 
-        dnl now we can finally update the DEBUG,UNICODE,SHARED options
-        dnl to their final values if they were set to 'auto'
-        if test "$DEBUG" = "auto"; then
-            DEBUG=$WX_DEBUG
-        fi
-        if test "$UNICODE" = "auto"; then
+        dnl now we can finally update the options to their final values if they
+        dnl were not already set
+        if test -z "$UNICODE" ; then
             UNICODE=$WX_UNICODE
         fi
-        if test "$SHARED" = "auto"; then
+        if test -z "$SHARED" ; then
             SHARED=$WX_SHARED
         fi
-        if test "$TOOLKIT" = "auto"; then
+        if test -z "$TOOLKIT" ; then
             TOOLKIT=$WX_PORT
         fi
 
-        dnl in case the user needs a BUILD=debug/release var...
-        if test "$DEBUG" = "1"; then
-            BUILD="debug"
-        elif test "$DEBUG" = "0" -o "$DEBUG" = ""; then
-            BUILD="release"
-        fi
-
-        dnl respect the DEBUG variable adding the optimize/debug flags
+        dnl respect the DEBUG variable adding the optimize/debug flags and also
+        dnl define a BUILD variable in case the user wants to use it
+        dnl
         dnl NOTE: the CXXFLAGS are merged together with the CPPFLAGS so we
         dnl       don't need to set them, too
         if test "$DEBUG" = "1"; then
+            BUILD="debug"
             CXXFLAGS="$CXXFLAGS -g -O0"
             CFLAGS="$CFLAGS -g -O0"
-        else
+        elif test "$DEBUG" = "0"; then
+            BUILD="release"
             CXXFLAGS="$CXXFLAGS -O2"
             CFLAGS="$CFLAGS -O2"
         fi
diff --git a/release.sh b/release.sh
index 4bb72a75..97c85b1b 100755
--- a/release.sh
+++ b/release.sh
@@ -43,6 +43,8 @@ elif [ $1 -eq 0 ]; then
  echo now the version in this script is: $version
  echo configure.ac:
  grep AC_INIT configure.ac
+ echo CMakeLists.txt:
+ grep 'VERSION=' CMakeLists.txt
  echo doc/conf.py:
  grep 'version =' doc/conf.py
  echo doc/index.rst:
diff --git a/samples/cfityk.py b/samples/cfityk.py
index 2342ea0a..b13f9286 100755
--- a/samples/cfityk.py
+++ b/samples/cfityk.py
@@ -10,11 +10,11 @@ try:
 except ImportError:
     readline = None
 import atexit
-import signal
 from optparse import OptionParser
 import subprocess
 import bisect
 import functools
+from math import isnan
 
 import fityk
 
@@ -23,14 +23,6 @@ _PROMPT2 = "... "
 
 _gnuplot = None
 
-# Python 3.2 has math.isfinite()
-def finite(x):
-    return x == x
-
-def interrupt_handler(signum, frame):
-    sys.stderr.write("\n(^C interrupts long calculations, use ^D to exit)\n")
-    fityk.cvar.user_interrupt = True
-
 def read_line():
     try:
         line = raw_input(_PROMPT)
@@ -80,7 +72,7 @@ def main():
                 pass
             atexit.register(readline.write_history_file, histfile)
 
-    signal.signal(signal.SIGINT, interrupt_handler)
+    fityk.interrupt_computations_on_sigint()
 
     parser = OptionParser("Usage: %prog [-h] [-V] [-c <str>]"
                           " [script or data file...]")
@@ -126,7 +118,7 @@ def main():
             while True:
                 line = read_line()
                 ui.exec_and_log(line)
-            print("")
+                print("")
     except fityk.ExitRequestedException:
         sys.stderr.write("\nbye...\n")
 
@@ -166,7 +158,7 @@ def plot_in_gnuplot(f, mode):
     # data
     if has_points:
         for p in points[begin:end]:
-            if p.is_active and finite(p.x) and finite(p.y):
+            if p.is_active and not isnan(p.x) and not isnan(p.y):
                 _gnuplot.stdin.write("%f  %f\n" % (p.x, p.y))
     else:
         _gnuplot.stdin.write("0.0  0.0\n")
@@ -175,9 +167,9 @@ def plot_in_gnuplot(f, mode):
     # model
     if has_points:
         for p in points[begin:end]:
-            if p.is_active and finite(p.x):
+            if p.is_active and not isnan(p.x):
                 y = f.get_model_value(p.x, dm_number)
-                if finite(y):
+                if not isnan(y):
                     _gnuplot.stdin.write("%f  %f\n" % (p.x, y))
     else:
         _gnuplot.stdin.write("0.0  0.0\n")
diff --git a/samples/hello.c b/samples/hello.c
index 004a442d..63ba04cc 100644
--- a/samples/hello.c
+++ b/samples/hello.c
@@ -13,6 +13,7 @@ int main()
     double x[500], y[500], sigma[500];
     const double mu = 12.345;
     double d;
+    const Func* gauss;
 
     Fityk *f = fityk_create();
 
@@ -34,6 +35,8 @@ int main()
     fityk_execute(f, "fit");
     d = fityk_calculate_expr(f, "%gauss.Center", 0);
     printf("peak center: %g\n", d);
+    gauss = fityk_get_function(f, "gauss");
+    printf("value at x=12: %g\n", fityk_value_at(gauss, 12));
     fityk_delete(f);
     return 0;
 }
diff --git a/samples/hello.cc b/samples/hello.cc
index 436c4868..1fe897d1 100644
--- a/samples/hello.cc
+++ b/samples/hello.cc
@@ -22,6 +22,7 @@ int main()
     f->execute("guess %gauss = Gaussian");
     f->execute("fit");
     cout << "peak center: " << f->calculate_expr("%gauss.Center") << endl;
+    cout << "value at x=12: " << f->get_function("gauss")->value_at(12) << endl;
     delete f;
     return 0;
 }
diff --git a/tests/gradient.cpp b/tests/gradient.cpp
index 84e28e85..e06a0be9 100644
--- a/tests/gradient.cpp
+++ b/tests/gradient.cpp
@@ -27,7 +27,7 @@ static double boxbetts_f(const double *a, double *grad)
     for (int x = 1; x <= 10; ++x) {
         double e0 = exp(-0.1*x*a[0]);
         double e1 = exp(-0.1*x*a[1]);
-        double e2 = exp(-0.1*x) - exp(-x);
+        double e2 = exp(-0.1*x) - exp(-1.0*x);
         double g = e0 - e1 - e2 * a[2];
         f += g*g;
         if (grad) {
diff --git a/tests/psvoigt.cpp b/tests/psvoigt.cpp
index 0e676d6a..32cb1cdb 100644
--- a/tests/psvoigt.cpp
+++ b/tests/psvoigt.cpp
@@ -47,7 +47,7 @@ TEST_CASE("pseudo-voigt", "") {
             double H = fik->calculate_expr("%pv.Height");
             REQUIRE(H == height);
             double ib = fik->calculate_expr("%pv.IB");
-            REQUIRE(ib == area/height);
+            REQUIRE(ib == Approx(area/height));
         }
         const fityk::Func *f = fik->get_function("pv");
         double at_ctr = f->value_at(center);
diff --git a/tests/test_syntax.fit b/tests/test_syntax.fit
index a5b8c22d..b67e8412 100644
--- a/tests/test_syntax.fit
+++ b/tests/test_syntax.fit
@@ -68,6 +68,7 @@ guess %lo = SplitGaussian [38:]
 sleep 0.3
 guess %lo = LorentzianA [38:44]
 %pe = Pearson7(height=~1901, center=~75.313, hwhm=~1/2, shape=2.4)
+%g2S = GaussianA(height=~300, center=75, area=~11174, hwhm=~6.3[0:10])
 F += %pe
 %ble = copy(%pe)
 dele %pe
diff --git a/wxgui/Makefile.am b/wxgui/Makefile.am
index d10d7789..ad6dab23 100644
--- a/wxgui/Makefile.am
+++ b/wxgui/Makefile.am
@@ -105,6 +105,7 @@ img/zoom_prev.xpm \
 img/zoom_right.xpm \
 img/zoom_up.xpm \
 img/zoom_vert.xpm \
+img/log_y_toggle.xpm \
 img/zshift.xpm \
 \
 img/eq_fwhm.h \
diff --git a/wxgui/about.cpp b/wxgui/about.cpp
index 62557a03..3a5ccc62 100644
--- a/wxgui/about.cpp
+++ b/wxgui/about.cpp
@@ -7,10 +7,14 @@
 #include <wx/hyperlink.h>
 
 #include "cmn.h" // pchar2wx, s2wx, GET_BMP
-#include "fityk/common.h" // VERSION
+#include "fityk/common.h" // VERSION, HAVE_LIBNLOPT
 #include "fityk/info.h" // embedded_lua_version()
 #include "img/fityk96.h"
 
+#if HAVE_LIBNLOPT
+# include <nlopt.h>  // nlopt_version()
+#endif
+
 AboutDlg::AboutDlg(wxWindow* parent)
     : wxDialog(parent, -1, wxT("About Fityk"), wxDefaultPosition,
                wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
@@ -50,15 +54,20 @@ AboutDlg::AboutDlg(wxWindow* parent)
     txt->SetBackgroundColour(bg_col);
     txt->SetDefaultStyle(wxTextAttr(wxNullColour, bg_col, *wxITALIC_FONT));
     txt->AppendText(wxT("powered by: ") wxVERSION_STRING);
-    txt->AppendText(wxString::Format(wxT(", Boost %d.%d.%d"),
+    txt->AppendText(wxString::Format(", Boost %d.%d.%d",
                                      BOOST_VERSION / 100000,
                                      BOOST_VERSION / 100 % 1000,
                                      BOOST_VERSION % 100));
     txt->AppendText(wxString(", ") + fityk::embedded_lua_version());
-    txt->AppendText(wxT(" and xylib ") + pchar2wx(xylib_get_version())
-                    + wxT("\n"));
+#if HAVE_LIBNLOPT
+    int nl_ver[3];
+    nlopt_version(nl_ver, nl_ver+1, nl_ver+2);
+    txt->AppendText(wxString::Format(", NLopt %d.%d.%d",
+                                     nl_ver[0], nl_ver[1], nl_ver[2]));
+#endif
+    txt->AppendText(" and xylib " + pchar2wx(xylib_get_version()) + "\n");
     txt->SetDefaultStyle(wxTextAttr(wxNullColour, bg_col, *wxNORMAL_FONT));
-    txt->AppendText(wxT("\nCopyright 2001 - 2016 Marcin Wojdyr\n\n"));
+    txt->AppendText(wxT("\nCopyright 2001 - 2022 Marcin Wojdyr\n\n"));
     txt->SetDefaultStyle(wxTextAttr(wxNullColour, bg_col, *wxSMALL_FONT));
     txt->AppendText(
    wxT("This program is free software; you can redistribute it and/or modify ")
diff --git a/wxgui/aplot.cpp b/wxgui/aplot.cpp
index 3feeecff..bcea4db2 100644
--- a/wxgui/aplot.cpp
+++ b/wxgui/aplot.cpp
@@ -392,7 +392,6 @@ void AuxPlot::OnLeftUp (wxMouseEvent &event)
     if (GetCapture() == this)
         ReleaseMouse();
     connect_esc_to_cancel(false);
-    downX = INT_MIN;
     SetCursor(wxCURSOR_CROSS);
     overlay.switch_mode(Overlay::kVLine);
     if (abs(event.GetX() - downX) >= 5) {
@@ -403,6 +402,7 @@ void AuxPlot::OnLeftUp (wxMouseEvent &event)
         overlay.draw_overlay();
         frame->plot_pane()->draw_vertical_lines(event.GetX(), -1, this);
     }
+    downX = INT_MIN;
 }
 
 //popup-menu
@@ -574,8 +574,8 @@ AuxPlotConfDlg::AuxPlotConfDlg(AuxPlot* ap)
     zoom_sizer->AddSpacer(10);
     zoom_sizer->Add(new wxStaticText(this, -1, wxT("y zoom")),
                     0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
-    zoom_sc_ = new SpinCtrl(this, -1, iround(ap_->y_zoom_ * 100),
-                            0, 999999, 70);
+    zoom_sc_ = make_wxspinctrl(this, -1, iround(ap_->y_zoom_ * 100),
+                               0, 999999, 70);
     zoom_sc_->Enable(!ap_->auto_zoom_y_);
     zoom_sizer->Add(zoom_sc_, 0, wxALL, 5);
     zoom_sizer->Add(new wxStaticText(this, -1, wxT("%")),
diff --git a/wxgui/app.cpp b/wxgui/app.cpp
index f55dbeee..f3af43cc 100644
--- a/wxgui/app.cpp
+++ b/wxgui/app.cpp
@@ -8,11 +8,6 @@
 #include <wx/filesys.h>
 #include <wx/tooltip.h>
 
-#ifdef __WXGTK3__
-#error "Not everything is working with wxGTK3. Use default wxGTK instead, " \
-       "based on GTK+2. If you want to test it, just remove this #error."
-#endif
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <vector>
@@ -39,6 +34,13 @@ using namespace std;
 using fityk::UserInterface;
 using fityk::range_vector;
 
+#ifdef HELP_DIR
+// We don't pass HELP_DIR directly to wxString as a workaround for a problem
+// with Conda builds. wxString uses the system wchar_t by default
+// and Conda overlooks wide strings when replacing prefixes.
+static const char* kHelpDir = HELP_DIR;
+#endif
+
 IMPLEMENT_APP(FApp)
 
 
@@ -155,7 +157,7 @@ UserInterface::Status gui_exec_command(const string& s)
     try {
         r = ftk->ui()->execute_line(s);
     }
-    catch(fityk::ExitRequestedException) {
+    catch(const fityk::ExitRequestedException&) {
         frame->Close(true);
         return UserInterface::kStatusOk;
     }
@@ -164,12 +166,6 @@ UserInterface::Status gui_exec_command(const string& s)
 }
 //-------------------------------------------------------------------------
 
-static
-void interrupt_handler (int /*signum*/)
-{
-    fityk::user_interrupt = 1;  // set flag to stop computations
-}
-
 static
 void write_white_config(wxConfigBase *w)
 {
@@ -203,21 +199,16 @@ FApp::FApp()
 
 bool FApp::OnInit(void)
 {
-#ifndef _WIN32
-    // setting Ctrl-C handler
-    if (signal (SIGINT, interrupt_handler) == SIG_IGN)
-        signal (SIGINT, SIG_IGN);
-#endif //_WIN32
-
-    SetAppName(wxT("fityk"));
+    fityk::interrupt_computations_on_sigint();
+    SetAppName("fityk");
 
     // if options can be parsed
     wxCmdLineParser cmdLineParser(cmdLineDesc, argc, argv);
     if (cmdLineParser.Parse(false) != 0) {
         cmdLineParser.Usage();
         return false; //false = exit the application
-    } else if (cmdLineParser.Found(wxT("V"))) {
-        wxMessageOutput::Get()->Printf(wxT("fityk version %s\n"), wxT(VERSION));
+    } else if (cmdLineParser.Found("V")) {
+        wxMessageOutput::Get()->Printf("fityk version %s\n", VERSION);
         return false; //false = exit the application
     } else if (cmdLineParser.Found("full-version")) {
         wxMessageOutput::Get()->Printf("fityk version %s\n%s\n%s\n", VERSION,
@@ -259,7 +250,7 @@ bool FApp::OnInit(void)
     wxConfig::Set(config);
 
     // directory for configs
-    config_dir = fityk_dir + wxFILE_SEP_PATH + wxT("configs") + wxFILE_SEP_PATH;
+    config_dir = fityk_dir + wxFILE_SEP_PATH + "configs" + wxFILE_SEP_PATH;
     if (!wxDirExists(config_dir)) {
         wxMkdir(config_dir);
         // create white-background config
@@ -271,20 +262,20 @@ bool FApp::OnInit(void)
     // moving configs from ver. <= 0.9.7 to the current locations
     wxString old_config = get_conf_file("config");
     if (wxFileExists(old_config))
-        wxRenameFile(old_config, config_dir + wxT("default"), false);
+        wxRenameFile(old_config, config_dir + "default", false);
     wxString old_alt_config = get_conf_file("alt-config");
     if (wxFileExists(old_alt_config))
-        wxRenameFile(old_alt_config, config_dir + wxT("alt-config"), false);
+        wxRenameFile(old_alt_config, config_dir + "alt-config", false);
 
     EditTransDlg::read_transforms(false);
 
     // Create the main frame window
-    frame = new FFrame(NULL, -1, wxT("fityk"), wxDEFAULT_FRAME_STYLE);
+    frame = new FFrame(NULL, -1, "fityk", wxDEFAULT_FRAME_STYLE);
 
-    wxString ini_conf = wxT("default");
+    wxString ini_conf = "default";
     // if the -g option was given, it replaces default config
-    cmdLineParser.Found(wxT("g"), &ini_conf);
-    wxConfigBase *cf = new wxFileConfig(wxT(""), wxT(""), config_dir+ini_conf);
+    cmdLineParser.Found("g", &ini_conf);
+    wxConfigBase *cf = new wxFileConfig("", "", config_dir+ini_conf);
     frame->read_all_settings(cf);
 
     frame->Show(true);
@@ -299,7 +290,7 @@ bool FApp::OnInit(void)
 
     SetTopWindow(frame);
 
-    if (!cmdLineParser.Found(wxT("I"))) {
+    if (!cmdLineParser.Found("I")) {
         // run initial commands
         wxString startup_file =
                     get_conf_file(fityk::startup_commands_filename());
@@ -311,7 +302,7 @@ bool FApp::OnInit(void)
     try {
         process_argv(cmdLineParser);
     }
-    catch(fityk::ExitRequestedException) {
+    catch(const fityk::ExitRequestedException&) {
         return false;
     }
 
@@ -323,7 +314,7 @@ bool FApp::OnInit(void)
 int FApp::OnExit()
 {
     delete ftk;
-    wxConfig::Get()->Write(wxT("/FitykVersion"), pchar2wx(VERSION));
+    wxConfig::Get()->Write("/FitykVersion", pchar2wx(VERSION));
     delete wxConfig::Set((wxConfig *) NULL);
     return 0;
 }
@@ -372,13 +363,13 @@ int find_common_prefix_length(vector<string> const& p)
 void FApp::process_argv(wxCmdLineParser &cmdLineParser)
 {
     wxString cmd;
-    if (cmdLineParser.Found(wxT("c"), &cmd))
+    if (cmdLineParser.Found("c", &cmd))
         ftk->ui()->exec_and_log(wx2s(cmd));
     //the rest of parameters/arguments are scripts and/or data files
     vector<string> p;
     for (unsigned int i = 0; i < cmdLineParser.GetParamCount(); i++)
         p.push_back(wx2s(cmdLineParser.GetParam(i)));
-    if (cmdLineParser.Found(wxT("r")) && p.size() > 1) { // reorder
+    if (cmdLineParser.Found("r") && p.size() > 1) { // reorder
         sort(p.begin(), p.end(), less_filename(find_common_prefix_length(p)));
     }
     for (vector<string>::const_iterator i = p.begin(); i != p.end(); ++i) {
@@ -413,42 +404,42 @@ void FApp::process_argv(wxCmdLineParser &cmdLineParser)
 //   {exedir}/../../doc/ and {exedir}/../../../doc/ - for uninstalled program
 wxString get_help_url(const wxString& name)
 {
-    wxString dir = wxFILE_SEP_PATH + wxString(wxT("html"));
+    wxString dir = wxFILE_SEP_PATH + wxString("html");
     wxPathList paths;
     // installed path
 #if defined(__WXMAC__) || defined(__WXMSW__)
     paths.Add(wxStandardPaths::Get().GetResourcesDir() + dir);
 #endif
 #ifdef HELP_DIR
-    paths.Add(wxT(HELP_DIR) + dir);
+    paths.Add(kHelpDir + dir);
 #endif
     // uninstalled paths, relative to executable
-    wxString up = wxFILE_SEP_PATH + wxString(wxT(".."));
+    wxString up = wxFILE_SEP_PATH + wxString("..");
     paths.Add(wxPathOnly(wxGetApp().argv[0]) + up + up
-              + wxFILE_SEP_PATH + wxT("doc") + dir);
+              + wxFILE_SEP_PATH + "doc" + dir);
     paths.Add(wxPathOnly(wxGetApp().argv[0]) + up + up + up
-              + wxFILE_SEP_PATH + wxT("doc") + dir);
+              + wxFILE_SEP_PATH + "doc" + dir);
 
     wxString path = paths.FindAbsoluteValidPath(name);
     if (!path.IsEmpty())
         return wxFileSystem::FileNameToURL(path);
     else
-        return wxT("http://fityk.nieto.pl/") + name;
+        return "http://fityk.nieto.pl/" + name;
 }
 
 wxString get_sample_path(const wxString& name)
 {
-    wxString dir = wxFILE_SEP_PATH + wxString(wxT("samples"));
+    wxString dir = wxFILE_SEP_PATH + wxString("samples");
     wxPathList paths;
     // installed path
 #if defined(__WXMAC__) || defined(__WXMSW__)
     paths.Add(wxStandardPaths::Get().GetResourcesDir() + dir);
 #endif
 #ifdef HELP_DIR
-    paths.Add(wxT(HELP_DIR) + dir);
+    paths.Add(kHelpDir + dir);
 #endif
     // uninstalled paths, relative to executable
-    wxString up = wxFILE_SEP_PATH + wxString(wxT(".."));
+    wxString up = wxFILE_SEP_PATH + wxString("..");
     paths.Add(wxPathOnly(wxGetApp().argv[0]) + up + up + dir);
     paths.Add(wxPathOnly(wxGetApp().argv[0]) + up + up + up + dir);
     wxFileName path(paths.FindAbsoluteValidPath(name));
diff --git a/wxgui/cmn.cpp b/wxgui/cmn.cpp
index 67214016..1954ccd1 100644
--- a/wxgui/cmn.cpp
+++ b/wxgui/cmn.cpp
@@ -113,18 +113,18 @@ ProportionalSplitter::ProportionalSplitter(wxWindow* parent, wxWindowID id,
     SetMinimumPaneSize(20);
     ResetSash();
     Connect(GetId(), wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED,
-                (wxObjectEventFunction) &ProportionalSplitter::OnSashChanged);
+            wxSplitterEventHandler(ProportionalSplitter::OnSashChanged));
     Connect(GetId(), wxEVT_SIZE,
-                     (wxObjectEventFunction) &ProportionalSplitter::OnReSize);
+            wxSizeEventHandler(ProportionalSplitter::OnReSize));
     //hack to set sizes on first paint event
     Connect(GetId(), wxEVT_PAINT,
-                      (wxObjectEventFunction) &ProportionalSplitter::OnPaint);
+            wxPaintEventHandler(ProportionalSplitter::OnPaint));
 }
 
 bool ProportionalSplitter::SplitHorizProp(wxWindow* win1, wxWindow* win2,
                                           float proportion)
 {
-    if (proportion >= 0. && proportion <= 1.)
+    if (proportion >= 0.f && proportion <= 1.f)
         m_proportion = proportion;
     int height = GetClientSize().GetHeight();
     int h = iround(height * m_proportion);
@@ -137,7 +137,7 @@ bool ProportionalSplitter::SplitHorizProp(wxWindow* win1, wxWindow* win2,
 bool ProportionalSplitter::SplitVertProp(wxWindow* win1, wxWindow* win2,
                                          float proportion)
 {
-    if (proportion >= 0. && proportion <= 1.)
+    if (proportion >= 0.f && proportion <= 1.f)
         m_proportion = proportion;
     int width = GetClientSize().GetWidth();
     int w = iround(width * m_proportion);
@@ -185,7 +185,7 @@ void ProportionalSplitter::OnSashChanged(wxSplitterEvent &event)
     const wxSize& s = GetSize();
     int t = GetSplitMode() == wxSPLIT_HORIZONTAL ? s.GetHeight() : s.GetWidth();
     float prop = float(event.GetSashPosition()) / t;
-    if (prop > 0. && prop < 1.)
+    if (prop > 0.f && prop < 1.f)
         m_proportion = prop;
     event.Skip();
 }
diff --git a/wxgui/cmn.h b/wxgui/cmn.h
index fea482fb..22ffddb3 100644
--- a/wxgui/cmn.h
+++ b/wxgui/cmn.h
@@ -113,7 +113,7 @@ public:
                          wxWindowID id=-1,
                          float proportion=0.66, // 0. - 1.
                          const wxSize& size = wxDefaultSize,
-                         long style=wxSP_NOBORDER|wxSP_3DSASH);
+                         long style=wxSP_3DSASH|wxSP_LIVE_UPDATE);
     bool SplitHorizProp(wxWindow* win1, wxWindow* win2, float proportion=-1);
     bool SplitVertProp(wxWindow* win1, wxWindow* win2, float proportion=-1);
     float GetProportion() const { return m_proportion; }
@@ -131,16 +131,16 @@ private:
     void OnPaint(wxPaintEvent &event);
 };
 
-class SpinCtrl: public wxSpinCtrl
+inline wxSpinCtrl* make_wxspinctrl(wxWindow* parent, wxWindowID id, int val,
+                                   int min, int max, int width=50)
 {
-public:
-    SpinCtrl(wxWindow* parent, wxWindowID id, int val,
-             int min, int max, int width=50)
-        : wxSpinCtrl (parent, id, wxString::Format(wxT("%i"), val),
-                      wxDefaultPosition, wxSize(width, -1),
-                      wxSP_ARROW_KEYS, min, max, val)
-    {}
-};
+#ifdef __WXGTK3__
+    width = std::max(width, 50) + 30;
+#endif
+    return new wxSpinCtrl (parent, id, wxString::Format(wxT("%i"), val),
+                           wxDefaultPosition, wxSize(width, -1),
+                           wxSP_ARROW_KEYS, min, max, val);
+}
 
 /// wxTextCtrl which sends wxEVT_COMMAND_TEXT_ENTER when loses the focus
 class KFTextCtrl : public wxTextCtrl
diff --git a/wxgui/dataedit.cpp b/wxgui/dataedit.cpp
index ef499fde..10f075b4 100644
--- a/wxgui/dataedit.cpp
+++ b/wxgui/dataedit.cpp
@@ -260,7 +260,7 @@ void EditTransDlg::init()
     bb_sizer->Add(todefault_btn, wxSizerFlags().Border());
     bb_sizer->AddStretchSpacer();
     bb_sizer->Add(new wxButton(this, wxID_CLOSE, wxT("&Close")),
-                  wxSizerFlags().Border().Right());
+                  wxSizerFlags().Border());
     top_sizer->Add(bb_sizer, wxSizerFlags().Expand());
     SetSizerAndFit(top_sizer);
     SetEscapeId(wxID_CLOSE);
diff --git a/wxgui/defmgr.cpp b/wxgui/defmgr.cpp
index f991867d..6c681280 100644
--- a/wxgui/defmgr.cpp
+++ b/wxgui/defmgr.cpp
@@ -256,7 +256,9 @@ vector<string> DefinitionMgrDlg::get_commands()
 void DefinitionMgrDlg::OnAddButton(wxCommandEvent &)
 {
     Tplate tp;
+    tp.traits = 0;
     tp.create = NULL;
+    tp.docs_fragment = NULL;
     modified_.push_back(tp);
     lb->Append(wxT("-"));
     lb->SetSelection(lb->GetCount() - 1);
diff --git a/wxgui/dload.cpp b/wxgui/dload.cpp
index c9e8b4d4..e9e0c40a 100644
--- a/wxgui/dload.cpp
+++ b/wxgui/dload.cpp
@@ -107,15 +107,11 @@ void DLoadDlg::exec_command(bool replace)
     wxArrayString paths;
     browser_->filectrl->GetPaths(paths);
     string trailer;
-    string lua_trailer;
     string fmt = browser_->get_filetype();
-    if (fmt != "" || browser_->comma_cb->GetValue()) {
-        trailer = " " + (fmt == "" ? "_" : fmt);
-        lua_trailer = ", '" + fmt + "'";
-        if (browser_->comma_cb->GetValue()) {
+    if (!fmt.empty() || browser_->comma_cb->GetValue()) {
+        trailer = " " + (fmt.empty() ? "_" : fmt);
+        if (browser_->comma_cb->GetValue())
             trailer += " decimal_comma";
-            lua_trailer += ", 'decimal_comma'";
-        }
     }
     for (size_t i = 0; i < paths.GetCount(); ++i) {
         string cmd;
@@ -123,9 +119,10 @@ void DLoadDlg::exec_command(bool replace)
             cmd = "@" + (replace ? S(data_idx_) : S("+")) +
                    " < '" + wx2s(paths[i]) + cols + "'" + trailer;
         else // very special case
-            cmd = "lua F:load(" + S(replace ? data_idx_ : -1) +
-                   ", [[" + wx2s(paths[i]) + "]], " + S(b) + ", " +
-                   S(x) + ", " + S(y) + ", " + S(sig) + lua_trailer + ")";
+            cmd = "lua " +
+                  make_lua_load((replace ? data_idx_ : -1), paths[i], b,
+                                x, y, (has_s ? sig : fityk::LoadSpec::NN),
+                                fmt, browser_->comma_cb->GetValue());
         exec(with_options + cmd);
         wxString title = browser_->title_tc->GetValue().Trim();
         if (!title.empty() && title != browser_->auto_title_) {
@@ -136,3 +133,22 @@ void DLoadDlg::exec_command(bool replace)
     }
 }
 
+std::string make_lua_load(int data_idx, const wxString& path, int b,
+                          int x, int y, int sig,
+                          const std::string& fmt, bool comma) {
+    std::string cmd = "_spec=fityk.LoadSpec([[" + wx2s(path) + "]]); ";
+    if (b != 0)
+        cmd += "_spec.blocks=fityk.IntVector(1," + S(b) + "); ";
+    if (x != fityk::LoadSpec::NN)
+        cmd += "_spec.x_col=" + S(x) + "; ";
+    if (y != fityk::LoadSpec::NN)
+        cmd += "_spec.y_col=" + S(y) + "; ";
+    if (sig != fityk::LoadSpec::NN)
+        cmd += "_spec.sig_col=" + S(sig) + "; ";
+    if (!fmt.empty())
+        cmd += "_spec.format='" + fmt + "'; ";
+    if (comma)
+        cmd += "_spec.options='decimal_comma'; ";
+    cmd += "F:load(_spec, " + S(data_idx) + ")";
+    return cmd;
+}
diff --git a/wxgui/dload.h b/wxgui/dload.h
index 55fa5f97..7d810bda 100644
--- a/wxgui/dload.h
+++ b/wxgui/dload.h
@@ -7,6 +7,10 @@
 namespace fityk { class Data; }
 class XyFileBrowser;
 
+std::string make_lua_load(int data_idx, const wxString& path, int b,
+                          int x, int y, int sig,
+                          const std::string& fmt, bool comma);
+
 class DLoadDlg : public wxDialog
 {
 public:
diff --git a/wxgui/fitinfo.cpp b/wxgui/fitinfo.cpp
index ab2c3c9e..65409a42 100644
--- a/wxgui/fitinfo.cpp
+++ b/wxgui/fitinfo.cpp
@@ -9,7 +9,7 @@
 
 #include "fitinfo.h"
 #include "frame.h" //frame
-#include "cmn.h" //ProportionalSplitter
+#include "cmn.h" // make_wxspinctrl, ProportionalSplitter
 #include "fityk/logic.h"
 #include "fityk/fit.h"
 #include "fityk/data.h"
@@ -24,7 +24,7 @@ NumericFormatPanel::NumericFormatPanel(wxWindow* parent)
     wxSizer *sizer = new wxBoxSizer(wxHORIZONTAL);
     sizer->Add(new wxStaticText(this, -1, wxT("precision:")),
                wxSizerFlags().Center());
-    prec_sc = new SpinCtrl(this, -1, 6, 0, 30);
+    prec_sc = make_wxspinctrl(this, -1, 6, 0, 30);
     sizer->Add(prec_sc, wxSizerFlags().Center());
     wxArrayString fmt_choices;
     fmt_choices.Add(wxT("g"));
@@ -115,7 +115,7 @@ bool FitInfoDlg::Initialize()
                    wxSizerFlags().Border());
     btn_sizer->AddStretchSpacer();
     btn_sizer->Add(new wxButton(this, wxID_CLOSE),
-                   wxSizerFlags().Right().Border());
+                   wxSizerFlags().Border());
     top_sizer->Add(btn_sizer, wxSizerFlags().Expand());
     SetSizerAndFit(top_sizer);
     SetSize(wxSize(640, 440));
diff --git a/wxgui/fitinfo.h b/wxgui/fitinfo.h
index d93328e8..40a0b949 100644
--- a/wxgui/fitinfo.h
+++ b/wxgui/fitinfo.h
@@ -8,8 +8,8 @@
 #include <string>
 #include <wx/config.h>
 
-#include "cmn.h" //SpinCtrl
 #include "fityk/common.h" //realt
+class wxSpinCtrl;
 
 /// Control for changing numeric precision and format.
 /// Sends wxEVT_COMMAND_CHOICE_SELECTED when the precision changes.
diff --git a/wxgui/fitrun.cpp b/wxgui/fitrun.cpp
index 879e8161..6bb4cbd7 100644
--- a/wxgui/fitrun.cpp
+++ b/wxgui/fitrun.cpp
@@ -63,14 +63,14 @@ FitRunDlg::FitRunDlg(wxWindow* parent, wxWindowID id)
     wxFlexGridSizer *max_sizer = new wxFlexGridSizer(2, 3, 0, 0);
     max_sizer->Add(new wxStaticText(this, -1, wxT("max. iterations")),
                    0, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5);
-    maxiter_sc = new SpinCtrl(this, -1, 0, 0, 999999, 70);
+    maxiter_sc = make_wxspinctrl(this, -1, 0, 0, 999999, 70);
     max_sizer->Add(maxiter_sc, 0, wxALL, 5);
     nomaxiter_st = new wxStaticText(this, -1, wxT("(unlimited)"));
     max_sizer->Add(nomaxiter_st, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5);
     max_sizer->Add(new wxStaticText(this, -1, wxT("max. WSSR evaluations")),
                    0, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5);
     int default_max_eval = ftk->get_settings()->max_wssr_evaluations;
-    maxeval_sc = new SpinCtrl(this, -1, default_max_eval, 0, 999999, 70);
+    maxeval_sc = make_wxspinctrl(this, -1, default_max_eval, 0, 999999, 70);
     max_sizer->Add(maxeval_sc, 0, wxALL, 5);
     nomaxeval_st = new wxStaticText(this, -1, wxT("(unlimited)"));
     max_sizer->Add(nomaxeval_st, 0, wxALIGN_CENTER_VERTICAL, 0);
diff --git a/wxgui/fitrun.h b/wxgui/fitrun.h
index edce8b36..79197cf8 100644
--- a/wxgui/fitrun.h
+++ b/wxgui/fitrun.h
@@ -7,8 +7,6 @@
 #include <vector>
 #include <wx/spinctrl.h>
 
-#include "cmn.h"
-
 class FitRunDlg : public wxDialog
 {
 public:
@@ -18,7 +16,7 @@ private:
     wxRadioBox* data_rb;
     wxChoice* method_c;
     wxCheckBox *separately_cb, *autoplot_cb;
-    SpinCtrl *maxiter_sc, *maxeval_sc;
+    wxSpinCtrl *maxiter_sc, *maxeval_sc;
     wxStaticText *nomaxeval_st, *nomaxiter_st;
 
     void OnSpinEvent(wxSpinEvent &) { update_unlimited(); }
diff --git a/wxgui/frame.cpp b/wxgui/frame.cpp
index 6a5091e2..d1861998 100644
--- a/wxgui/frame.cpp
+++ b/wxgui/frame.cpp
@@ -17,6 +17,7 @@
 #include <wx/stdpaths.h>
 #include <wx/clipbrd.h>
 #include <wx/filepicker.h>
+#include <wx/filename.h>
 
 #include <algorithm>
 #include <string.h>
@@ -83,6 +84,7 @@
 #include "img/zoom_right.xpm"
 #include "img/zoom_up.xpm"
 #include "img/zoom_vert.xpm"
+#include "img/log_y_toggle.xpm"
 
 #include "img/book16.h"
 #include "img/editor16.h"
@@ -129,8 +131,8 @@ static const wxString website_url(
         wxT("http://fityk.nieto.pl/"));
 static const wxString wiki_url(
         wxT("https://github.com/wojdyr/fityk/wiki"));
-static const wxString feedback_url(
-        wxT("http://fityk.nieto.pl/feedback/") + pchar2wx(VERSION));
+static const wxString issues_url(
+        wxT("http://github.com/wojdyr/fityk/issues"));
 
 enum {
     // menu
@@ -138,7 +140,7 @@ enum {
     ID_H_WEBSITE               ,
     ID_H_WIKI                  ,
     ID_H_DISCUSSIONS           ,
-    ID_H_FEEDBACK              ,
+    ID_H_ISSUES                ,
     ID_H_EXAMPLE1              ,
     ID_H_EXAMPLE2              ,
     ID_H_EXAMPLE3              ,
@@ -254,6 +256,7 @@ enum {
     ID_T_RUN                  ,
     ID_T_UNDO                 ,
     ID_T_AUTO                 ,
+    ID_T_LOGY                 ,
     //ID_T_BAR                  ,
     ID_T_CHOICE
 };
@@ -381,7 +384,7 @@ BEGIN_EVENT_TABLE(FFrame, wxFrame)
     EVT_MENU (ID_H_WEBSITE,     FFrame::OnOnline)
     EVT_MENU (ID_H_WIKI,        FFrame::OnOnline)
     EVT_MENU (ID_H_DISCUSSIONS, FFrame::OnOnline)
-    EVT_MENU (ID_H_FEEDBACK,    FFrame::OnOnline)
+    EVT_MENU (ID_H_ISSUES,      FFrame::OnOnline)
     EVT_MENU_RANGE (ID_H_EXAMPLE1, ID_H_EXAMPLE4, FFrame::OnExample)
     EVT_MENU (wxID_ABOUT,       FFrame::OnAbout)
     EVT_MENU (wxID_EXIT,        FFrame::OnQuit)
@@ -407,8 +410,10 @@ FFrame::FFrame(wxWindow *parent, const wxWindowID id, const wxString& title,
 
     //sizer, splitters, etc.
     wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
-    v_splitter_ = new ProportionalSplitter(this);
-    main_pane_ = new ProportionalSplitter(v_splitter_);
+    v_splitter_ = new ProportionalSplitter(this, -1, 0.66, wxDefaultSize,
+                                           wxSP_3DSASH);
+    main_pane_ = new ProportionalSplitter(v_splitter_, -1, 0.66, wxDefaultSize,
+                                          wxSP_3DSASH);
     plot_pane_ = new PlotPane(main_pane_);
     text_pane_ = new TextPane(main_pane_);
     main_pane_->SplitHorizProp(plot_pane_, text_pane_);
@@ -805,10 +810,8 @@ void FFrame::set_menubar()
               wiki_url);
     append_mi(help_menu, ID_H_DISCUSSIONS, GET_BMP(web16),
               wxT("&Visit Discussions"), discussions_url);
-    /*
-    append_mi(help_menu, ID_H_FEEDBACK, GET_BMP(web16),
-              wxT("&Anonymous Feedback"), feedback_url);
-    */
+    append_mi(help_menu, ID_H_ISSUES, GET_BMP(web16),
+              wxT("&Visit Issues"), issues_url);
     wxMenu* help_menu_examples = new wxMenu;
     help_menu_examples->Append(ID_H_EXAMPLE1, wxT("&Single Peak"),
                                wxT("nacl01.fit"));
@@ -907,8 +910,8 @@ void FFrame::OnOnline(wxCommandEvent& event)
         url = &wiki_url;
     else if (event.GetId() == ID_H_DISCUSSIONS)
         url = &discussions_url;
-    else //if (event.GetId() == ID_H_FEEDBACK)
-        url = &feedback_url;
+    else //if (event.GetId() == ID_H_ISSUES)
+        url = &issues_url;
     bool r = wxLaunchDefaultBrowser(*url);
     if (!r)
         wxMessageBox(wxT("Can not open URL in browser,")
@@ -965,17 +968,18 @@ void FFrame::OnDataQLoad (wxCommandEvent&)
         return;
 
     string cmd;
-    string options;
+    std::string tail;
     wxWindow *extra = fdlg.GetExtraControl();
+    bool decimal_comma = false;
     if (extra != NULL) {
         Extra2CheckBoxes *extracb = wxDynamicCast(extra,Extra2CheckBoxes);
         string selected = extracb->is_checked1() ? "sqrt" : "one";
         if (ftk->get_settings()->default_sigma != selected)
             cmd = "with default_sigma=" + selected + " ";
 
-        bool decimal_comma = extracb->is_checked2();
+        decimal_comma = extracb->is_checked2();
         if (decimal_comma)
-            options += "decimal_comma";
+            tail = "_ decimal_comma";
         wxConfig::Get()->Write("decimalComma", decimal_comma);
     }
 
@@ -1032,14 +1036,13 @@ void FFrame::OnDataQLoad (wxCommandEvent&)
                 cmd += "lua ";
             }
         if (has_single_quote) { // very special case
-            cmd += "F:load(-1, [[" + wx2s(paths[i]) + "]], 0, 1, 2, 0, '', '"
-                + options + "')";
+            int NN = fityk::LoadSpec::NN;
+            cmd += make_lua_load(-1, paths[i], 0, NN, NN, NN,
+                                 "", decimal_comma);
         } else {
-            cmd += "@+ <'" + wx2s(paths[i]) + "'";
-            if (!options.empty())
-               cmd += " _ " + options;
+            cmd += "@+ <'" + wx2s(paths[i]) + "' " + tail;
         }
-        recent_data_->add(paths[i], options.empty() ? "" : "_ "+options);
+        recent_data_->add(paths[i], tail);
     }
 
     exec(cmd);
@@ -1476,15 +1479,26 @@ void FFrame::show_editor(const wxString& path, const wxString& content)
     dlg->Show(true);
 }
 
+static void split_path(const wxString& path, wxString* dir, wxString* name) {
+    if (path.empty())
+        return;
+    wxFileName fn(path);
+    *dir = fn.GetPath(); // GetPath() returns only directory not path
+    *name = fn.GetFullName(); // "fullname" is basename w/ extension
+}
+
 void FFrame::OnSessionLoad(wxCommandEvent&)
 {
+    wxString dir = script_dir_;
+    wxString file;
+    split_path(last_session_path_, &dir, &file);
     wxFileDialog fdlg(this, "Run script (after resetting session)",
-                      script_dir_, "", fityk_lua_wildcards,
+                      dir, file, fityk_lua_wildcards,
                       wxFD_OPEN | wxFD_FILE_MUST_EXIST);
     if (fdlg.ShowModal() == wxID_OK) {
         get_main_plot()->bgm()->clear_background();
-        exec("reset; exec '" + wx2s(fdlg.GetPath()) + "'");
-        //last_include_path_ = wx2s(fdlg.GetPath());
+        last_session_path_ = fdlg.GetPath();
+        exec("reset; exec '" + wx2s(last_session_path_) + "'");
         //GetMenuBar()->Enable(ID_SESSION_RECENT, true);
     }
     script_dir_ = fdlg.GetDirectory();
@@ -1492,14 +1506,17 @@ void FFrame::OnSessionLoad(wxCommandEvent&)
 
 void FFrame::OnSessionSave(wxCommandEvent&)
 {
-    wxFileDialog fdlg(this, wxT("Save everything as a script"),
-                      export_dir_, wxT(""),
-                      wxT("fityk file (*.fit)|*.fit;*.FIT"),
+    wxString dir = script_dir_;
+    wxString file;
+    split_path(last_session_path_, &dir, &file);
+    wxFileDialog fdlg(this, "Save everything as a script",
+                      dir, file, "fityk file (*.fit)|*.fit;*.FIT",
                       wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
     if (fdlg.ShowModal() == wxID_OK) {
-        exec("info state > '" + wx2s(fdlg.GetPath()) + "'");
+        last_session_path_ = fdlg.GetPath();
+        exec("info state > '" + wx2s(last_session_path_) + "'");
     }
-    export_dir_ = fdlg.GetDirectory();
+    script_dir_ = fdlg.GetDirectory();
 }
 
 void FFrame::OnSettings (wxCommandEvent&)
@@ -1736,17 +1753,17 @@ void FFrame::OnConfigureDirectories(wxCommandEvent&)
     wxDirPickerCtrl *dp = new wxDirPickerCtrl(&dlg, -1, data_dir_,
                 wxDirSelectorPromptStr, wxDefaultPosition, wxDefaultSize,
                 wxDIRP_USE_TEXTCTRL);
-    gsizer->Add(dp, wxSizerFlags().Center().Expand());
+    gsizer->Add(dp, wxSizerFlags().Expand());
     gsizer->Add(new wxStaticText(&dlg, -1, "Script Directory"), sf);
     wxDirPickerCtrl *sp = new wxDirPickerCtrl(&dlg, -1, script_dir_,
                 wxDirSelectorPromptStr, wxDefaultPosition, wxDefaultSize,
                 wxDIRP_USE_TEXTCTRL);
-    gsizer->Add(sp, wxSizerFlags().Center().Expand());
+    gsizer->Add(sp, wxSizerFlags().Expand());
     gsizer->Add(new wxStaticText(&dlg, -1, "Export Directory"), sf);
     wxDirPickerCtrl *ep = new wxDirPickerCtrl(&dlg, -1, export_dir_,
                 wxDirSelectorPromptStr, wxDefaultPosition, wxDefaultSize,
                 wxDIRP_USE_TEXTCTRL);
-    gsizer->Add(ep, wxSizerFlags().Center().Expand());
+    gsizer->Add(ep, wxSizerFlags().Expand());
     top_sizer->Add(gsizer, wxSizerFlags().Border().Expand());
 
     wxBoxSizer *button_sizer = new wxBoxSizer(wxHORIZONTAL);
@@ -2002,11 +2019,11 @@ public:
         c.Border(wxBOTTOM);
 #endif
         sizer->Add(new wxStaticText(this, -1, "width:"), c);
-        w_spin = new SpinCtrl(this, -1, size.x, 0, 9999, 70);
+        w_spin = make_wxspinctrl(this, -1, size.x, 0, 9999, 70);
         sizer->Add(w_spin, c);
         sizer->AddSpacer(10);
         sizer->Add(new wxStaticText(this, -1, "height:"), c);
-        h_spin = new SpinCtrl(this, -1, size.y, 0, 9999, 70);
+        h_spin = make_wxspinctrl(this, -1, size.y, 0, 9999, 70);
         sizer->Add(h_spin, c);
         sizer->AddSpacer(10);
         aux_cb = new wxCheckBox(this, -1, "with auxiliary plots");
@@ -2276,6 +2293,7 @@ BEGIN_EVENT_TABLE (FToolBar, wxToolBar)
     //EVT_TOOL (ID_T_BAR, FToolBar::OnSwitchSideBar)
     EVT_CHOICE (ID_T_CHOICE, FToolBar::OnPeakChoice)
     EVT_TOOL_ENTER (-1, FToolBar::OnToolEnter)
+    EVT_TOOL (ID_T_LOGY, FToolBar::OnLogYToggle)
 END_EVENT_TABLE()
 
 FToolBar::FToolBar (wxFrame *parent, wxWindowID id)
@@ -2327,6 +2345,10 @@ FToolBar::FToolBar (wxFrame *parent, wxWindowID id)
             wxITEM_NORMAL, wxT("Previous view"),
             wxT("Go to the previous view"));
     AddSeparator();
+    AddTool(ID_T_LOGY, wxT("Log y"), wxBitmap(log_y_toggle_xpm), wxNullBitmap,
+            wxITEM_NORMAL, wxT("Toggle y log"),
+            wxT("Toggle y scale between logarithmic and linear"));
+    AddSeparator();
     //file
     AddTool(ID_SESSION_INCLUDE, wxT("Execute"),
             wxBitmap(run_script_xpm), wxNullBitmap, wxITEM_NORMAL,
@@ -2449,6 +2471,18 @@ void FToolBar::OnToolEnter(wxCommandEvent& event)
     }
 }
 
+void FToolBar::OnLogYToggle(wxCommandEvent&)
+{
+    const bool log_x = frame->get_main_plot()->get_x_scale().logarithm;
+    const bool log_y = frame->get_main_plot()->get_y_scale().logarithm;
+
+    frame->get_main_plot()->get_x_scale().logarithm = log_x;
+    frame->get_main_plot()->get_y_scale().logarithm = !log_y;
+    ftk->view.set_log_scale(log_x, !log_y);
+
+    frame->plot_pane()->refresh_plots(false, kMainPlot);
+}
+
 void FToolBar::on_addpeak_hover()
 {
     string info;
diff --git a/wxgui/frame.h b/wxgui/frame.h
index 8f494c20..8f2a573c 100644
--- a/wxgui/frame.h
+++ b/wxgui/frame.h
@@ -36,6 +36,7 @@ public:
     void OnSwitchSideBar (wxCommandEvent& event);
     void OnClickTool (wxCommandEvent& event);
     void OnToolEnter(wxCommandEvent& event);
+    void OnLogYToggle (wxCommandEvent& event);
 
 private:
     wxChoice *peak_choice;
@@ -226,6 +227,7 @@ private:
     RecentFiles *recent_scripts_, *recent_data_;
     wxMenu *data_ft_menu_, *func_type_menu_;
     wxString script_dir_, data_dir_, export_dir_;
+    wxString last_session_path_;
     bool antialias_;
 
     void place_plot_and_io_windows(wxWindow *parent);
diff --git a/wxgui/gradient.cpp b/wxgui/gradient.cpp
index 6c1301e5..21747e80 100644
--- a/wxgui/gradient.cpp
+++ b/wxgui/gradient.cpp
@@ -6,7 +6,7 @@
 #include <wx/spinctrl.h>
 
 #include "gradient.h"
-#include "cmn.h" //SpinCtrl, change_color_dlg, add_apply_close_buttons
+#include "cmn.h" // change_color_dlg, add_apply_close_buttons
 #include "fityk/common.h" //iround()
 
 using namespace std;
@@ -28,7 +28,7 @@ public:
         wxSize size = GetClientSize();
         wxPen pen;
         for (int i = 0; i < size.GetWidth(); ++i) {
-            float d = i / (size.GetWidth() - 1.0);
+            double d = i / (size.GetWidth() - 1.0);
             pen.SetColour(gradient_dlg_->get_value(d));
             dc.SetPen(pen);
             dc.DrawLine(i, 0, i, size.GetHeight());
@@ -108,10 +108,10 @@ static wxColour hsv2wxColour(unsigned char h, unsigned char s, unsigned char v)
     if (s == 0)
         return wxColour(v, v, v);
 
-    float hx = h / 42.501;      // 0 <= hx <= 5.
+    double hx = h / 42.501;      // 0 <= hx <= 5.
     int i = (int) floor(hx);
-    float f = hx - i;
-    float sx = s / 255.;
+    double f = hx - i;
+    double sx = s / 255.;
     unsigned char p = iround(v * (1 - sx));
     unsigned char q = iround(v * (1 - sx * f));
     unsigned char t = iround(v * (1 - sx * (1 - f)));
@@ -134,7 +134,7 @@ static wxColour hsv2wxColour(unsigned char h, unsigned char s, unsigned char v)
 }
 
 
-wxColour GradientDlg::get_value(float x)
+wxColour GradientDlg::get_value(double x)
 {
     wxColour c;
     if (x < 0)
diff --git a/wxgui/gradient.h b/wxgui/gradient.h
index 455f53cf..0324fdc3 100644
--- a/wxgui/gradient.h
+++ b/wxgui/gradient.h
@@ -15,7 +15,7 @@ public:
                 const wxColour& first_col, const wxColour& last_col);
     void OnColor(wxColourPickerEvent&) { display_->Refresh(); }
     void OnRadioChanged(wxCommandEvent &) { display_->Refresh(); }
-    wxColour get_value(float x);
+    wxColour get_value(double x);
 private:
     wxRadioButton *rb1_, *rb2_, *rb3_, *rb4_;
     wxColourPickerCtrl *from_cp_, *to_cp_;
diff --git a/wxgui/history.cpp b/wxgui/history.cpp
index 4e202f6f..18cf13a8 100644
--- a/wxgui/history.cpp
+++ b/wxgui/history.cpp
@@ -57,8 +57,8 @@ SumHistoryDlg::SumHistoryDlg (wxWindow* parent, wxWindowID id)
     buttons_sizer->Add (new wxStaticText(this, -1, wxT("View parameters:")),
                         0, wxALL|wxALIGN_CENTER, 5);
     for (int i = 0; i < 4; i++)
-        buttons_sizer->Add (new SpinCtrl(this, ID_SHIST_V + i, view[i],
-                                         0, view_max, 40),
+        buttons_sizer->Add(make_wxspinctrl(this, ID_SHIST_V + i, view[i],
+                                           0, view_max, 40),
                             0, wxALL, 5);
     buttons_sizer->Add (10, 10, 1);
     buttons_sizer->Add (new wxButton (this, wxID_CLOSE, wxT("&Close")),
diff --git a/wxgui/img/log_y_toggle.xpm b/wxgui/img/log_y_toggle.xpm
new file mode 100644
index 00000000..d0381487
--- /dev/null
+++ b/wxgui/img/log_y_toggle.xpm
@@ -0,0 +1,49 @@
+/* XPM */
+static const char * log_y_toggle_xpm[] = {
+"24 24 22 1",
+" 	c None",
+".	c #000000",
+"+	c #221E11",
+"@	c #0B0B06",
+"#	c #363220",
+"$	c #EAE8E3",
+"%	c #2B2719",
+"&	c #EED680",
+"*	c #302C19",
+"=	c #3D351F",
+"-	c #2F2C19",
+";	c #937025",
+">	c #D29815",
+",	c #322F1E",
+"'	c #916F25",
+")	c #C58F13",
+"!	c #A97C1A",
+"~	c #A37819",
+"{	c #353120",
+"]	c #B68411",
+"^	c #231F13",
+"/	c #826321",
+"......            ......",
+".                 .     ",
+".                 .     ",
+".                 ......",
+".                 .     ",
+"......            .     ",
+".                 ......",
+".                 .     ",
+".                 .     ",
+".                 .     ",
+".        +@  @+   .     ",
+"......  #$.  .$#  .     ",
+".      %$&.  .&$% .     ",
+".     *$&&.==.&&$*......",
+".    *$&&&&&&&&&&$*     ",
+".    -;>>>>>>>>>>;-     ",
+".     ,'>)!~~!)>',.     ",
+"...... {'].^^.]'{ .     ",
+".       ,/.  ./,  .     ",
+".        *.  .*   .     ",
+".                 .     ",
+".                 .     ",
+".                 .     ",
+"......            ......"};
diff --git a/wxgui/inputline.cpp b/wxgui/inputline.cpp
index 1f74ff66..3063b5f5 100644
--- a/wxgui/inputline.cpp
+++ b/wxgui/inputline.cpp
@@ -32,30 +32,34 @@ InputLine::InputLine(wxWindow *parent, wxWindowID id,
     : wxPanel(parent, id), m_hpos(0), m_observer(observer),
       hist_file(hist_file_)
 {
+    wxBoxSizer *sizer = new wxBoxSizer(wxHORIZONTAL);
     m_text = new wxTextCtrl(this, wxID_ANY, wxT(""),
                        wxDefaultPosition, wxDefaultSize,
                        wxWANTS_CHARS|wxTE_PROCESS_ENTER /*|wxTE_PROCESS_TAB*/);
+    sizer->Add(m_text, 1, wxEXPAND);
+    // wxGTK3 has [+][-] instead of the up/down spin buttons.
+    // Better to not have it at all.
+#ifndef __WXGTK3__
     m_button = new wxSpinButton(this, wxID_ANY,
                                 wxDefaultPosition, wxDefaultSize,
-                                wxSP_VERTICAL|wxSP_ARROW_KEYS|wxNO_BORDER),
+                                wxSP_VERTICAL|wxSP_ARROW_KEYS|wxNO_BORDER);
     m_button->SetRange(0, 0);
     m_button->SetValue(0);
-    wxBoxSizer *sizer = new wxBoxSizer(wxHORIZONTAL);
-    sizer->Add(m_text, 1, wxEXPAND);
     sizer->Add(m_button, 0, wxEXPAND);
-    SetSizer(sizer);
-    SetMinSize(wxSize(-1, m_text->GetBestSize().y));
 #if !wxCHECK_VERSION(2, 9, 0)
 # define wxEVT_SPIN wxEVT_SCROLL_THUMBTRACK
 #endif
     m_button->Connect(wxEVT_SPIN, wxSpinEventHandler(InputLine::OnSpinButton),
                       NULL, this);
-    m_text->Connect(wxEVT_KEY_DOWN,
-                    wxKeyEventHandler(InputLine::OnKeyDownAtText),
-                    NULL, this);
     m_button->Connect(wxEVT_KEY_DOWN,
                       wxKeyEventHandler(InputLine::OnKeyDownAtSpinButton),
                       NULL, this);
+#endif // not __WXGTK3__
+    m_text->Connect(wxEVT_KEY_DOWN,
+                    wxKeyEventHandler(InputLine::OnKeyDownAtText),
+                    NULL, this);
+    SetSizer(sizer);
+    SetMinSize(wxSize(-1, m_text->GetBestSize().y));
     // read history
     if (!hist_file.IsEmpty()) {
         FFile f(hist_file, "r");
@@ -110,7 +114,9 @@ void InputLine::HistoryMove(int n, bool relative)
 
     m_hpos = new_pos;
     m_text->SetValue(m_history[new_pos]);
+#ifndef __WXGTK3__
     m_button->SetValue(m_history.GetCount() - 1 - new_pos);
+#endif // not __WXGTK3__
     m_text->SetFocus();
     m_text->SetInsertionPointEnd();
 }
@@ -135,8 +141,10 @@ void InputLine::GoToHistoryEnd()
     if (m_history.GetCount() > hist_size + hist_chunk)
         m_history.RemoveAt(0, m_history.GetCount() - hist_size);
     m_hpos = m_history.GetCount() - 1;
+#ifndef __WXGTK3__
     m_button->SetRange(0, m_hpos);
     m_button->SetValue(0);
+#endif // not __WXGTK3__
 }
 
 void InputLine::OnKeyDownAtText (wxKeyEvent& event)
diff --git a/wxgui/inputline.h b/wxgui/inputline.h
index dc47816c..cd256252 100644
--- a/wxgui/inputline.h
+++ b/wxgui/inputline.h
@@ -27,7 +27,9 @@ public:
     void SetValue(const wxString& value) { m_text->SetValue(value); }
 protected:
     wxTextCtrl *m_text;
+#ifndef __WXGTK3__
     wxSpinButton *m_button;
+#endif
     wxArrayString m_history;
     int m_hpos; // current item in m_history
     InputLineObserver* m_observer;
diff --git a/wxgui/listptxt.cpp b/wxgui/listptxt.cpp
index 639f3eb4..fd5ed6d8 100644
--- a/wxgui/listptxt.cpp
+++ b/wxgui/listptxt.cpp
@@ -6,8 +6,8 @@
 #include <wx/imaglist.h>
 
 #include "listptxt.h"
-#include "cmn.h" //SpinCtrl, ProportionalSplitter
-#include "sidebar.h" //SideBar::delete_selected_items()
+#include "cmn.h" // ProportionalSplitter
+#include "sidebar.h" // SideBar::delete_selected_items()
 #include "frame.h" // frame->focus_input() and used in update_data_list()
 #include "mplot.h" // used in update_data_list()
 #include "fityk/common.h" // s2wx
diff --git a/wxgui/modelinfo.cpp b/wxgui/modelinfo.cpp
index 73f53ecf..928a08d2 100644
--- a/wxgui/modelinfo.cpp
+++ b/wxgui/modelinfo.cpp
@@ -67,7 +67,7 @@ bool ModelInfoDlg::Initialize()
     btn_sizer->Add(new wxButton(this, wxID_SAVE),
                    wxSizerFlags().Border());
     btn_sizer->Add(new wxButton(this, wxID_CLOSE),
-                   wxSizerFlags().Right().Border());
+                   wxSizerFlags().Border());
     top_sizer->Add(btn_sizer, wxSizerFlags().Expand());
     SetSizerAndFit(top_sizer);
     SetSize(wxSize(640, 440));
diff --git a/wxgui/mplot.cpp b/wxgui/mplot.cpp
index ab0d953a..218e3f69 100644
--- a/wxgui/mplot.cpp
+++ b/wxgui/mplot.cpp
@@ -1368,7 +1368,7 @@ void MainPlot::OnButtonUp (wxMouseEvent &event)
                   + frame->get_guess_string(frame->get_peak_type())
                   + " [" + eS(min(x1,x2)) + " : " + eS(max(x1,x2)) + "]");
     } else {
-        ;// nothing - action done in OnButtonDown()
+        // nothing - action done in OnButtonDown()
     }
 }
 
@@ -1520,14 +1520,14 @@ MainPlotConfDlg::MainPlotConfDlg(MainPlot* mp)
 
     gsizer->Add(new wxStaticText(this, -1, wxT("colors for datasets")), cr);
     wxBoxSizer *data_col_sizer = new wxBoxSizer(wxHORIZONTAL);
-    data_colors_sc_ = new SpinCtrl(this, -1, mp_->data_colors_.size(),
-                                   2, MainPlot::kMaxDataColors, /*width=*/60);
+    data_colors_sc_ = make_wxspinctrl(this, -1, mp_->data_colors_.size(),
+                                      2, MainPlot::kMaxDataColors, /*width*/60);
     data_col_sizer->Add(data_colors_sc_, cl);
     data_color_combo_ = new MultiColorCombo(this, &mp_->get_bg_color(),
                                             mp_->data_colors_);
     data_color_combo_->SetSelection(0);
     data_col_sizer->Add(data_color_combo_, cl);
-    gsizer->Add(data_col_sizer, cr);
+    gsizer->Add(data_col_sizer, cl);
 
     gsizer->Add(new wxStaticText(this, -1, wxT("inactive data")), cr);
     inactive_cp_ = new wxColourPickerCtrl(this, -1, mp_->inactiveDataCol);
@@ -1540,7 +1540,7 @@ MainPlotConfDlg::MainPlotConfDlg(MainPlot* mp)
     model_cp_ = new wxColourPickerCtrl(this, -1, mp_->modelCol);
     model_sizer->Add(model_cp_, cl.Border(wxRIGHT));
     model_sizer->Add(new wxStaticText(this, -1, wxT("width:")), cl);
-    model_width_sc_ = new SpinCtrl(this, -1, mp_->model_line_width_, 1, 5);
+    model_width_sc_ = make_wxspinctrl(this, -1, mp_->model_line_width_, 1, 5);
     model_sizer->Add(model_width_sc_, cl);
     gsizer->Add(model_sizer, cl);
 
@@ -1550,18 +1550,39 @@ MainPlotConfDlg::MainPlotConfDlg(MainPlot* mp)
     func_cp_ = new wxColourPickerCtrl(this, -1, mp_->peakCol[0]);
     gsizer->Add(func_cp_, cl);
 
+    gsizer->Add(new wxStaticText(this, -1, wxT("axes and tics")), cr);
+    wxBoxSizer *tics_sizer = new wxBoxSizer(wxHORIZONTAL);
+    axis_cp_ = new wxColourPickerCtrl(this, -1, mp_->xAxisCol);
+    tics_fp_ = new wxFontPickerCtrl(this, -1, mp_->ticsFont);
+    tics_sizer->Add(axis_cp_, cl);
+    tics_sizer->Add(tics_fp_, cl);
+    gsizer->Add(tics_sizer, cl);
+
+
+    desc_cb_ = new wxCheckBox(this, -1, wxT("plot description"));
+    desc_cb_->SetValue(mp_->desc_visible_);
+    gsizer->Add(desc_cb_, cr);
+
+    wxArrayString desc_choices;
+    desc_choices.Add("title");
+    desc_choices.Add("filename");
+    desc_choices.Add("fit");
+    desc_choices.Add("filename,fit");
+    desc_combo_ = new wxComboBox(this, -1, s2wx(mp_->desc_format_),
+                                 wxDefaultPosition, wxDefaultSize,
+                                 desc_choices);
+    desc_combo_->SetToolTip("Description (in the right top corner)\n"
+                            "is an output of the info command.\n"
+                            "You can give any info arguments here.");
+    gsizer->Add(desc_combo_, cl);
+
+    gsizer->AddSpacer(10);
+    gsizer->AddSpacer(10);
     labels_cb_ = new wxCheckBox(this, -1, wxT("function labels"));
     labels_cb_->SetValue(mp_->plabels_visible_);
-    gsizer->Add(labels_cb_, cr);
     label_fp_ = new wxFontPickerCtrl(this, -1, mp_->plabelFont);
-    gsizer->Add(label_fp_, cl);
-
-    gsizer->Add(new wxStaticText(this, -1, wxEmptyString), cr);
     vertical_labels_cb_ = new wxCheckBox(this, -1, wxT("vertical"));
     vertical_labels_cb_->SetValue(mp_->vertical_plabels_);
-    gsizer->Add(vertical_labels_cb_, cl);
-
-    gsizer->Add(new wxStaticText(this, -1, wxEmptyString), cr);
     wxArrayString label_choices;
     label_choices.Add(wxT("<area>"));
     label_choices.Add(wxT("<height>"));
@@ -1582,32 +1603,14 @@ MainPlotConfDlg::MainPlotConfDlg(MainPlot* mp)
                              wxT("<ib>     integral breadth (area/FWHM)\n")
                              wxT("<name>   function's name\n")
                              wxT("<br>     line break\n"));
-    gsizer->Add(label_combo_, cl);
-
-    desc_cb_ = new wxCheckBox(this, -1, wxT("plot description"));
-    desc_cb_->SetValue(mp_->desc_visible_);
-    gsizer->Add(desc_cb_, cr);
 
-    wxArrayString desc_choices;
-    desc_choices.Add("title");
-    desc_choices.Add("filename");
-    desc_choices.Add("fit");
-    desc_choices.Add("filename,fit");
-    desc_combo_ = new wxComboBox(this, -1, s2wx(mp_->desc_format_),
-                                 wxDefaultPosition, wxDefaultSize,
-                                 desc_choices);
-    desc_combo_->SetToolTip("Description (in the right top corner)\n"
-                            "is an output of the info command.\n"
-                            "You can give any info arguments here.");
-    gsizer->Add(desc_combo_, cl);
-
-    gsizer->Add(new wxStaticText(this, -1, wxT("axis & tics color")), cr);
-    axis_cp_ = new wxColourPickerCtrl(this, -1, mp_->xAxisCol);
-    gsizer->Add(axis_cp_, cl);
-
-    gsizer->Add(new wxStaticText(this, -1, wxT("tic label font")), cr);
-    tics_fp_ = new wxFontPickerCtrl(this, -1, mp_->ticsFont);
-    gsizer->Add(tics_fp_, cl);
+    gsizer->Add(labels_cb_, cr);
+    gsizer->Add(label_combo_, cl);
+    gsizer->AddSpacer(0);
+    wxBoxSizer* flabels_sizer = new wxBoxSizer(wxHORIZONTAL);
+    flabels_sizer->Add(label_fp_, cl);
+    flabels_sizer->Add(vertical_labels_cb_, cl);
+    gsizer->Add(flabels_sizer, cl);
 
     hor_sizer->Add(gsizer, wxSizerFlags().Border());
 
@@ -1629,19 +1632,13 @@ MainPlotConfDlg::MainPlotConfDlg(MainPlot* mp)
     wxBoxSizer *xmt_sizer = new wxBoxSizer(wxHORIZONTAL);
     xmt_sizer->Add(new wxStaticText(this, -1, wxT("max. number of tics")),
                   0, wxALL|wxALIGN_CENTRE_VERTICAL, 5);
-    x_max_tics_sc_ = new wxSpinCtrl(this, -1, wxT("7"),
-                                    wxDefaultPosition, wxSize(50, -1),
-                                    wxSP_ARROW_KEYS, 1, 30, 7);
-    x_max_tics_sc_->SetValue(mp_->x_max_tics);
+    x_max_tics_sc_ = make_wxspinctrl(this, -1, mp_->x_max_tics, 1, 30);
     xmt_sizer->Add(x_max_tics_sc_, 0, wxALL, 5);
     xsizer_t->Add(xmt_sizer);
     wxBoxSizer *xts_sizer = new wxBoxSizer(wxHORIZONTAL);
     xts_sizer->Add(new wxStaticText(this, -1, wxT("length of tics")),
                   0, wxALL|wxALIGN_CENTRE_VERTICAL, 5);
-    x_tic_size_sc_ = new wxSpinCtrl(this, -1, wxT("4"),
-                                    wxDefaultPosition, wxSize(50, -1),
-                                    wxSP_ARROW_KEYS, -10, 20, 4);
-    x_tic_size_sc_->SetValue(mp_->x_tic_size);
+    x_tic_size_sc_ = make_wxspinctrl(this, -1, mp_->x_tic_size, -10, 20);
     xts_sizer->Add(x_tic_size_sc_, 0, wxALL, 5);
     xsizer_t->Add(xts_sizer);
     xsizer->Add(xsizer_t, 0, wxLEFT, 15);
@@ -1671,19 +1668,13 @@ MainPlotConfDlg::MainPlotConfDlg(MainPlot* mp)
     wxBoxSizer *ymt_sizer = new wxBoxSizer(wxHORIZONTAL);
     ymt_sizer->Add(new wxStaticText(this, -1, wxT("max. number of tics")),
                   0, wxALL|wxALIGN_CENTRE_VERTICAL, 5);
-    y_max_tics_sc_ = new wxSpinCtrl(this, -1, wxT("7"),
-                                    wxDefaultPosition, wxSize(50, -1),
-                                    wxSP_ARROW_KEYS, 1, 30, 7);
-    y_max_tics_sc_->SetValue(mp_->y_max_tics);
+    y_max_tics_sc_ = make_wxspinctrl(this, -1, mp_->y_max_tics, 1, 30);
     ymt_sizer->Add(y_max_tics_sc_, 0, wxALL, 5);
     ysizer_t->Add(ymt_sizer);
     wxBoxSizer *yts_sizer = new wxBoxSizer(wxHORIZONTAL);
     yts_sizer->Add(new wxStaticText(this, -1, wxT("length of tics")),
                   0, wxALL|wxALIGN_CENTRE_VERTICAL, 5);
-    y_tic_size_sc_ = new wxSpinCtrl(this, -1, wxT("4"),
-                                     wxDefaultPosition, wxSize(50, -1),
-                                     wxSP_ARROW_KEYS, 1, 20, 4);
-    y_tic_size_sc_->SetValue(mp_->y_tic_size);
+    y_tic_size_sc_ = make_wxspinctrl(this, -1, mp_->y_tic_size, -10, 20);
     yts_sizer->Add(y_tic_size_sc_, 0, wxALL, 5);
     ysizer_t->Add(yts_sizer);
     ysizer->Add(ysizer_t, 0, wxLEFT, 15);
diff --git a/wxgui/parpan.cpp b/wxgui/parpan.cpp
index 6586f3ef..1145f2c4 100644
--- a/wxgui/parpan.cpp
+++ b/wxgui/parpan.cpp
@@ -338,9 +338,9 @@ void ParameterPanel::append_row()
                                  .Border(wxLEFT, 2)
 #endif
                                    );
-    grid_sizer_->Add(data.text, wxSizerFlags().Expand().Center()
+    grid_sizer_->Add(data.text, wxSizerFlags().Expand()
                                          .Border(wxLEFT|wxTOP|wxBOTTOM, 2));
-    grid_sizer_->Add(data.rsizer, wxSizerFlags().Expand().Center());
+    grid_sizer_->Add(data.rsizer, wxSizerFlags().Expand());
 
     data.label2->Show(false);
 
@@ -409,13 +409,13 @@ int ParameterPanel::find_in_rows(wxObject* w)
     for (int n = 0; n != get_count(); ++n)
         if (w == rows_[n].text || w == rows_[n].lock || w == rows_[n].arm)
             return n;
-    assert(0);
-    return 0;
+    return -1;
 }
 
 void ParameterPanel::OnLockButton(wxCommandEvent& event)
 {
     int n = find_in_rows(event.GetEventObject());
+    if (n == -1) return;
     int old_state = rows_[n].lock->state();
     if (old_state != 2) {
         rows_[n].lock->set_state(old_state == 0 ? 1 : 0);
@@ -429,6 +429,7 @@ void ParameterPanel::OnLockButton(wxCommandEvent& event)
 void ParameterPanel::OnTextEnter(wxCommandEvent &event)
 {
     int n = find_in_rows(event.GetEventObject());
+    if (n == -1) return;
     wxTextCtrl *tc = rows_[n].text;
     if (tc->GetValue() == double2wxstr(values_[n]))
         return;
@@ -451,6 +452,7 @@ void ParameterPanel::OnMouseWheel(wxMouseEvent &event)
     if (event.AltDown())
         change /= 20;
     int n = find_in_rows(event.GetEventObject());
+    if (n == -1) return;
     double new_value = values_[n] + fabs(values_[n]) * change;
     set_value(n, new_value);
     observer_->on_parameter_changed(n);
diff --git a/wxgui/plot.h b/wxgui/plot.h
index 74e20079..815ce249 100644
--- a/wxgui/plot.h
+++ b/wxgui/plot.h
@@ -139,8 +139,8 @@ public:
     void set_font(wxDC &dc, wxFont const& font);
     void set_scale(int pixel_width, int pixel_height);
     int get_special_point_at_pointer(wxMouseEvent& event);
-    Scale const& get_x_scale() const { return xs; }
-    Scale const& get_y_scale() const { return ys; }
+    Scale & get_x_scale() { return xs; }
+    Scale & get_y_scale() { return ys; }
     virtual void save_settings(wxConfigBase *cf) const;
     virtual void read_settings(wxConfigBase *cf);
     void set_magnification(int m) { pen_width = m > 0 ? m : 1; }
diff --git a/wxgui/plotpane.cpp b/wxgui/plotpane.cpp
index 6265bb51..424b2f7f 100644
--- a/wxgui/plotpane.cpp
+++ b/wxgui/plotpane.cpp
@@ -33,10 +33,11 @@ void ZoomHistory::set_pos(size_t p)
 }
 
 PlotPane::PlotPane(wxWindow *parent, wxWindowID id)
-    : ProportionalSplitter(parent, id)
+    : ProportionalSplitter(parent, id, 0.66, wxDefaultSize, wxSP_3DSASH)
 {
     plot_ = new MainPlot(this);
-    aux_split_ = new ProportionalSplitter(this, -1, 0.5);
+    aux_split_ = new ProportionalSplitter(this, -1, 0.5, wxDefaultSize,
+                                          wxSP_3DSASH);
     SplitHorizProp(plot_, aux_split_);
 
     aux_plot_[0] = new AuxPlot(aux_split_, plot_, wxT("0"));
diff --git a/wxgui/powdifpat.cpp b/wxgui/powdifpat.cpp
index 92a0e41e..b29f9dbb 100644
--- a/wxgui/powdifpat.cpp
+++ b/wxgui/powdifpat.cpp
@@ -189,7 +189,7 @@ PowderBook::PowderBook(wxWindow* parent, wxWindowID id)
                                                c.Blue(), c.Alpha()));
 
     Connect(GetId(), wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGED,
-            (wxObjectEventFunction) &PowderBook::OnPageChanged);
+            wxBookCtrlEventHandler(PowderBook::OnPageChanged));
 }
 
 static
@@ -284,7 +284,7 @@ wxPanel* PowderBook::PrepareIntroPanel()
     range_sizer->Add(range_to, wxSizerFlags().Center().Border());
     intro_sizer->Add(range_sizer);
     Connect(file_picker->GetId(), wxEVT_COMMAND_FILEPICKER_CHANGED,
-            (wxObjectEventFunction) &PowderBook::OnFilePicked);
+            wxFileDirPickerEventHandler(PowderBook::OnFilePicked));
 #endif
 
     wxStaticBoxSizer *legend_box = new wxStaticBoxSizer(wxHORIZONTAL,
@@ -461,7 +461,7 @@ void PlotWithLines::draw(wxDC &dc, bool)
     dc.SetPen(peak_pen);
     const vector<PlanesWithSameD>& bp = phase_panel_->get_crystal().bp;
     int selected = phase_panel_->get_selected_hkl();
-    double max_intensity = get_max_intensity(bp);;
+    double max_intensity = get_max_intensity(bp);
     double h_mult = 0;
     if (max_intensity > 0)
         h_mult = powder_book_->y_max / max_intensity;
@@ -596,41 +596,41 @@ PhasePanel::PhasePanel(wxNotebook *parent, PowderBook *powder_book_)
     SetSizerAndFit(vsizer);
 
     Connect(sg_btn->GetId(), wxEVT_COMMAND_BUTTON_CLICKED,
-            (wxObjectEventFunction) &PhasePanel::OnSpaceGroupButton);
+            wxCommandEventHandler(PhasePanel::OnSpaceGroupButton));
     Connect(save_btn->GetId(), wxEVT_COMMAND_BUTTON_CLICKED,
-            (wxObjectEventFunction) &PhasePanel::OnAddToQLButton);
+            wxCommandEventHandler(PhasePanel::OnAddToQLButton));
     Connect(s_clear_btn->GetId(), wxEVT_COMMAND_BUTTON_CLICKED,
-            (wxObjectEventFunction) &PhasePanel::OnClearButton);
+            wxCommandEventHandler(PhasePanel::OnClearButton));
     Connect(name_tc->GetId(), wxEVT_COMMAND_TEXT_UPDATED,
-            (wxObjectEventFunction) &PhasePanel::OnNameChanged);
+            wxCommandEventHandler(PhasePanel::OnNameChanged));
     Connect(sg_tc->GetId(), wxEVT_COMMAND_TEXT_ENTER,
-            (wxObjectEventFunction) &PhasePanel::OnSpaceGroupChanged);
+            wxCommandEventHandler(PhasePanel::OnSpaceGroupChanged));
     Connect(sg_tc->GetId(), wxEVT_COMMAND_TEXT_UPDATED,
-            (wxObjectEventFunction) &PhasePanel::OnSpaceGroupChanging);
+            wxCommandEventHandler(PhasePanel::OnSpaceGroupChanging));
 
     const LockableRealCtrl* param_controls[] =
             { par_a, par_b, par_c, par_alpha, par_beta, par_gamma };
     for (int i = 0; i != sizeof(param_controls) / sizeof(par_a); ++i) {
         wxWindowID id = param_controls[i]->get_text_ctrl()->GetId();
         Connect(id, wxEVT_COMMAND_TEXT_UPDATED,
-                (wxObjectEventFunction) &PhasePanel::OnParameterChanging);
+                wxCommandEventHandler(PhasePanel::OnParameterChanging));
         Connect(id, wxEVT_COMMAND_TEXT_ENTER,
-                (wxObjectEventFunction) &PhasePanel::OnParameterChanged);
+                wxCommandEventHandler(PhasePanel::OnParameterChanged));
     }
 
     Connect(hkl_list->GetId(), wxEVT_COMMAND_CHECKLISTBOX_TOGGLED,
-            (wxObjectEventFunction) &PhasePanel::OnLineToggled);
+            wxCommandEventHandler(PhasePanel::OnLineToggled));
     Connect(hkl_list->GetId(), wxEVT_COMMAND_LISTBOX_SELECTED,
-            (wxObjectEventFunction) &PhasePanel::OnLineSelected);
+            wxCommandEventHandler(PhasePanel::OnLineSelected));
 
     atoms_tc->Connect(wxEVT_SET_FOCUS,
-                      (wxObjectEventFunction) &PhasePanel::OnAtomsFocus,
+                      wxFocusEventHandler(PhasePanel::OnAtomsFocus),
                       NULL, this);
     atoms_tc->Connect(wxEVT_KILL_FOCUS,
-                      (wxObjectEventFunction) &PhasePanel::OnAtomsUnfocus,
+                      wxFocusEventHandler(PhasePanel::OnAtomsUnfocus),
                       NULL, this);
     atoms_tc->Connect(wxEVT_COMMAND_TEXT_UPDATED,
-                      (wxObjectEventFunction) &PhasePanel::OnAtomsChanged,
+                      wxCommandEventHandler(PhasePanel::OnAtomsChanged),
                       NULL, this);
 }
 
@@ -1801,7 +1801,7 @@ void PowderBook::OnQuickListImport(wxCommandEvent&)
                     + wxT("' already exists.\nOverwrite?"),
                     wxT("Overwrite?"), wxYES_NO|wxICON_QUESTION);
             if (answer != wxYES)
-                continue;;
+                continue;
         }
         if (ext == wxT("cif") || ext == wxT("CIF")) {
             wxMessageBox(wxT("Support for CIF files is not ready yet."),
diff --git a/wxgui/print.cpp b/wxgui/print.cpp
index 58ba84c3..925f6921 100644
--- a/wxgui/print.cpp
+++ b/wxgui/print.cpp
@@ -45,24 +45,24 @@ PageSetupDialog::PageSetupDialog(wxWindow *parent, PrintManager *print_mgr)
     wxBoxSizer *m1sizer = new wxBoxSizer(wxHORIZONTAL);
     m1sizer->Add(new wxStaticText(this, -1, "Top"),
                  0, wxALIGN_CENTER_VERTICAL);
-    top_margin_sc = new SpinCtrl(this, -1, 0, -100, 500);
+    top_margin_sc = make_wxspinctrl(this, -1, 0, -100, 500);
     m1sizer->Add(top_margin_sc, 0, wxALL, 5);
     hsizer->Add(m1sizer, 0, wxALIGN_CENTER|wxRIGHT, 15);
     wxBoxSizer *m2sizer = new wxBoxSizer(wxHORIZONTAL);
     m2sizer->Add(new wxStaticText(this, -1, "Left"),
                  0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5);
-    left_margin_sc = new SpinCtrl(this, -1, 0, -100, 500);
+    left_margin_sc = make_wxspinctrl(this, -1, 0, -100, 500);
     m2sizer->Add(left_margin_sc, 0, wxLEFT, 5);
     m2sizer->AddStretchSpacer();
     m2sizer->Add(new wxStaticText(this, -1, "Right"),
-                 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT);
-    right_margin_sc = new SpinCtrl(this, -1, 0, -100, 500);
-    m2sizer->Add(right_margin_sc, 0, wxLEFT|wxRIGHT|wxALIGN_RIGHT, 5);
+                 0, wxALIGN_CENTER_VERTICAL);
+    right_margin_sc = make_wxspinctrl(this, -1, 0, -100, 500);
+    m2sizer->Add(right_margin_sc, 0, wxLEFT|wxRIGHT, 5);
     hsizer->Add(m2sizer, 0, wxEXPAND);
     wxBoxSizer *m3sizer = new wxBoxSizer(wxHORIZONTAL);
     m3sizer->Add(new wxStaticText(this, -1, "Bottom"),
                  0, wxALIGN_CENTER_VERTICAL);
-    bottom_margin_sc = new SpinCtrl(this, -1, 0, -100, 500);
+    bottom_margin_sc = make_wxspinctrl(this, -1, 0, -100, 500);
     m3sizer->Add(bottom_margin_sc, 0, wxALL, 5);
     hsizer->Add(m3sizer, 0, wxALIGN_CENTER|wxRIGHT, 30);
     top_sizer->Add(hsizer, 0, wxALL|wxEXPAND, 5);
diff --git a/wxgui/print.h b/wxgui/print.h
index e1be7f1d..a872c8e5 100644
--- a/wxgui/print.h
+++ b/wxgui/print.h
@@ -8,7 +8,7 @@
 #include <wx/print.h>
 
 class PlotPane;
-class SpinCtrl;
+class wxSpinCtrl;
 
 // it can be confusing how the code is split into classes here,
 // but let's leave it as it is
@@ -39,8 +39,8 @@ private:
     PrintManager *pm;
     wxRadioBox *orientation_rb, *colors_rb;
     wxCheckBox *plot_aux_cb[2], *plot_borders_cb;
-    SpinCtrl *left_margin_sc, *right_margin_sc,
-             *top_margin_sc, *bottom_margin_sc;
+    wxSpinCtrl *left_margin_sc, *right_margin_sc,
+               *top_margin_sc, *bottom_margin_sc;
     DECLARE_EVENT_TABLE()
 };
 
diff --git a/wxgui/setdlg.cpp b/wxgui/setdlg.cpp
index 6fac967b..407ad70d 100644
--- a/wxgui/setdlg.cpp
+++ b/wxgui/setdlg.cpp
@@ -99,12 +99,12 @@ wxChoice *addEnumSetting(wxWindow *parent, const wxString& label,
     return ctrl;
 }
 
-SpinCtrl* addSpinCtrl(wxWindow *parent, const wxString& label,
-                      int value, int min_v, int max_v, wxSizer *sizer,
-                      int indentation=0)
+wxSpinCtrl* addSpinCtrl(wxWindow *parent, const wxString& label,
+                        int value, int min_v, int max_v, wxSizer *sizer,
+                        int indentation=0)
 {
     wxStaticText *st = new wxStaticText(parent, -1, label);
-    SpinCtrl *spin = new SpinCtrl(parent, -1, value, min_v, max_v, 70);
+    wxSpinCtrl *spin = make_wxspinctrl(parent, -1, value, min_v, max_v, 70);
     wxBoxSizer *box = new wxBoxSizer(wxHORIZONTAL);
     if (indentation)
         box->AddSpacer(indentation);
diff --git a/wxgui/sgchooser.cpp b/wxgui/sgchooser.cpp
index 462544c4..241076b1 100644
--- a/wxgui/sgchooser.cpp
+++ b/wxgui/sgchooser.cpp
@@ -74,14 +74,14 @@ SpaceGroupChooser::SpaceGroupChooser(wxWindow* parent,
 
     for (size_t i = 0; i < sizeof(centering_cb)/sizeof(centering_cb[0]); ++i)
         Connect(centering_cb[i]->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED,
-                (wxObjectEventFunction) &SpaceGroupChooser::OnCheckBox);
+                wxCommandEventHandler(SpaceGroupChooser::OnCheckBox));
 
     Connect(system_c->GetId(), wxEVT_COMMAND_CHOICE_SELECTED,
-            (wxObjectEventFunction) &SpaceGroupChooser::OnSystemChoice);
+            wxCommandEventHandler(SpaceGroupChooser::OnSystemChoice));
     //Connect(list->GetId(), wxEVT_COMMAND_LIST_ITEM_FOCUSED,
-    //        (wxObjectEventFunction) &SpaceGroupChooser::OnListItemFocused);
+    //        wxCommandEventHandler(SpaceGroupChooser::OnListItemFocused));
     Connect(list->GetId(), wxEVT_COMMAND_LIST_ITEM_ACTIVATED,
-            (wxObjectEventFunction) &SpaceGroupChooser::OnListItemActivated);
+            wxCommandEventHandler(SpaceGroupChooser::OnListItemActivated));
 }
 
 void SpaceGroupChooser::OnListItemActivated(wxCommandEvent&)
diff --git a/wxgui/sidebar.cpp b/wxgui/sidebar.cpp
index 28ebe79c..1e0efdca 100644
--- a/wxgui/sidebar.cpp
+++ b/wxgui/sidebar.cpp
@@ -12,7 +12,7 @@
 #include "parpan.h"
 #include "listptxt.h"
 #include "gradient.h"
-#include "cmn.h" //SpinCtrl, ProportionalSplitter, change_color_dlg, ...
+#include "cmn.h" // ProportionalSplitter, change_color_dlg, ...
 #include "frame.h" //frame
 #include "plotpane.h"
 #include "mplot.h"
@@ -177,7 +177,7 @@ SideBar::SideBar(wxWindow *parent, wxWindowID id)
     data_spin_sizer->Add(new wxStaticBitmap(data_page, -1,
                                             wxBitmap(dpsize_xpm)),
                          0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5);
-    dpsize_sc = new SpinCtrl(data_page, ID_DP_PSIZE, 1, 1, 9, 40);
+    dpsize_sc = make_wxspinctrl(data_page, ID_DP_PSIZE, 1, 1, 9, 40);
     dpsize_sc->SetToolTip(wxT("data point size"));
     data_spin_sizer->Add(dpsize_sc, 0);
     // line between points
@@ -193,7 +193,7 @@ SideBar::SideBar(wxWindow *parent, wxWindowID id)
     data_spin_sizer->Add(new wxStaticBitmap(data_page, -1,
                                             wxBitmap(shiftup_xpm)),
                          0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5);
-    shiftup_sc = new SpinCtrl(data_page, ID_DP_SHIFTUP, 0, 0, 80, 50);
+    shiftup_sc = make_wxspinctrl(data_page, ID_DP_SHIFTUP, 0, 0, 80, 50);
     shiftup_sc->SetToolTip(wxT("shift up (in % of plot height)"));
     data_spin_sizer->Add(shiftup_sc, 0);
     data_sizer->Add(data_spin_sizer, 0, wxEXPAND);
@@ -895,8 +895,8 @@ void SideBar::update_var_inf()
     if (n < 0)
         return;
     const Variable* var = ftk->mgr.get_variable(n);
-    string t = "$"+var->name + " = " + var->get_formula(ftk->mgr.parameters());
-    t += "\n" + var->domain.str();
+    string t = "$" + var->name + " = ";
+    t += var->get_formula(ftk->mgr.parameters());
     inf->AppendText(s2wx(t));
     vector<string> in = ftk->mgr.get_variable_references(var->name);
     if (!in.empty())
diff --git a/wxgui/statbar.cpp b/wxgui/statbar.cpp
index a3613e63..4170bfd1 100644
--- a/wxgui/statbar.cpp
+++ b/wxgui/statbar.cpp
@@ -28,7 +28,8 @@ FStatusBar::FStatusBar(wxWindow *parent)
         : wxPanel(parent, -1), extra_parser(NULL), last_x(0), last_y(0)
 {
     wxBoxSizer *sizer = new wxBoxSizer(wxHORIZONTAL);
-    split = new wxSplitterWindow(this, -1, wxDefaultPosition, wxDefaultSize, 0);
+    split = new wxSplitterWindow(this, -1, wxDefaultPosition, wxDefaultSize,
+                                 wxSP_LIVE_UPDATE|wxSP_THIN_SASH);
     wxPanel *panel_text = new wxPanel(split, -1);
     wxPanel *panel_coords = new wxPanel(split, -1);
     text = new wxStaticText(panel_text, -1, wxT(""));
@@ -58,7 +59,7 @@ FStatusBar::FStatusBar(wxWindow *parent)
         (this, -1, GET_BMP(sbprefs));
 #endif
     prefbtn->SetToolTip(wxT("configure status bar"));
-    sizer->Add(prefbtn, wxSizerFlags().Expand().Centre());
+    sizer->Add(prefbtn, wxSizerFlags().Expand());
 
     // wxALIGN_RIGHT flag for wxStaticText doesn't work on wxGTK 2.9
     // (wx bug #10716), so we must align the text in a different way
@@ -78,11 +79,11 @@ FStatusBar::FStatusBar(wxWindow *parent)
     mousebmp = new wxStaticBitmap(this, -1, GET_BMP(mouse16));
     wxBoxSizer *lmouse_sizer = new wxBoxSizer(wxHORIZONTAL);
     lmouse_sizer->AddStretchSpacer();
-    lmouse_sizer->Add(lmouse_hint, wxSizerFlags().Right());
+    lmouse_sizer->Add(lmouse_hint);
     lmouse_sizer->SetMinSize(rmouse_hint->GetClientSize());
     wxBoxSizer *hint_sizer = new wxBoxSizer(wxVERTICAL);
     wxBoxSizer *vhint_sizer = new wxBoxSizer(wxHORIZONTAL);
-    vhint_sizer->Add(lmouse_sizer, wxSizerFlags(1).Expand().FixedMinSize());
+    vhint_sizer->Add(lmouse_sizer, wxSizerFlags(1).Centre().FixedMinSize());
     vhint_sizer->Add(mousebmp, wxSizerFlags().Centre().Border(wxRIGHT, 3));
     vhint_sizer->Add(rmouse_hint, wxSizerFlags().Centre().FixedMinSize());
     hint_sizer->Add(new wxStaticLine(this), wxSizerFlags().Expand());
@@ -92,12 +93,12 @@ FStatusBar::FStatusBar(wxWindow *parent)
     sizer->AddSpacer(16);
     SetSizer(sizer);
     Connect(prefbtn->GetId(), wxEVT_COMMAND_BUTTON_CLICKED,
-            (wxObjectEventFunction) &FStatusBar::OnPrefButton);
+            wxCommandEventHandler(FStatusBar::OnPrefButton));
     mousebmp->Connect(wxEVT_LEFT_DOWN,
-                      (wxObjectEventFunction) &FStatusBar::OnMouseBmpClicked,
+                      wxMouseEventHandler(FStatusBar::OnMouseBmpClicked),
                       NULL, this);
     mousebmp->Connect(wxEVT_RIGHT_DOWN,
-                      (wxObjectEventFunction) &FStatusBar::OnMouseBmpClicked,
+                      wxMouseEventHandler(FStatusBar::OnMouseBmpClicked),
                       NULL, this);
 }
 
@@ -245,7 +246,7 @@ ConfStatBarDlg::ConfStatBarDlg(wxWindow* parent, wxWindowID id, FStatusBar* sb_)
     gsizer->Add(new wxStaticText(this, -1, wxT("formula")),
                 wxSizerFlags().Align(wxALIGN_CENTRE_VERTICAL|wxALIGN_RIGHT));
     extra_tc = new wxTextCtrl(this, -1, sb->extra_value);
-    gsizer->Add(extra_tc, wxSizerFlags().Expand().Center());
+    gsizer->Add(extra_tc, wxSizerFlags().Expand());
     okbmp = new wxStaticBitmap(this, -1, GET_BMP(ok24));
     gsizer->Add(okbmp, wxSizerFlags().Center()
 #if wxCHECK_VERSION(2, 8, 8)
@@ -255,7 +256,7 @@ ConfStatBarDlg::ConfStatBarDlg(wxWindow* parent, wxWindowID id, FStatusBar* sb_)
 
     gsizer->Add(new wxStaticText(this, -1,wxT("precision")),
                 wxSizerFlags().Align(wxALIGN_CENTRE_VERTICAL|wxALIGN_RIGHT));
-    e_prec_sc = new SpinCtrl(this, -1, sb->e_prec, 0, 9, 40);
+    e_prec_sc = make_wxspinctrl(this, -1, sb->e_prec, 0, 9);
     gsizer->Add(e_prec_sc, wxSizerFlags().Align(wxALIGN_CENTRE_VERTICAL));
 
     f_sizer->Add(gsizer, wxSizerFlags(1).Expand().Border());
@@ -272,13 +273,13 @@ ConfStatBarDlg::ConfStatBarDlg(wxWindow* parent, wxWindowID id, FStatusBar* sb_)
     //okbmp->Show(!sb->extra_value.empty());
 
     Connect(show_btn_cb->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED,
-            (wxObjectEventFunction) &ConfStatBarDlg::OnShowBtnCheckbox);
+            wxCommandEventHandler(ConfStatBarDlg::OnShowBtnCheckbox));
     Connect(show_hints_cb->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED,
-            (wxObjectEventFunction) &ConfStatBarDlg::OnShowHintsCheckbox);
+            wxCommandEventHandler(ConfStatBarDlg::OnShowHintsCheckbox));
     Connect(extra_tc->GetId(), wxEVT_COMMAND_TEXT_UPDATED,
-            (wxObjectEventFunction) &ConfStatBarDlg::OnExtraValueChange);
+            wxCommandEventHandler(ConfStatBarDlg::OnExtraValueChange));
     Connect(e_prec_sc->GetId(), wxEVT_COMMAND_SPINCTRL_UPDATED,
-            (wxObjectEventFunction) &ConfStatBarDlg::OnPrecisionSpin);
+            wxCommandEventHandler(ConfStatBarDlg::OnPrecisionSpin));
 }
 
 void ConfStatBarDlg::OnShowBtnCheckbox(wxCommandEvent& event)
diff --git a/wxgui/statbar.h b/wxgui/statbar.h
index b75c45d6..758fea0e 100644
--- a/wxgui/statbar.h
+++ b/wxgui/statbar.h
@@ -8,7 +8,7 @@
 #include <string>
 #include <wx/config.h>
 
-#include "cmn.h" //SpinCtrl
+#include "cmn.h" // PlotTypeEnum
 #include "fityk/eparser.h" // ExpressionParser
 
 // used by MainPlot to set hints on FStatusBar
diff --git a/wxgui/textpane.cpp b/wxgui/textpane.cpp
index 3129f91a..6ba6dce1 100644
--- a/wxgui/textpane.cpp
+++ b/wxgui/textpane.cpp
@@ -300,19 +300,19 @@ OutputWinConfDlg::OutputWinConfDlg(wxWindow* parent, wxWindowID id,
     SetEscapeId(wxID_CLOSE);
 
     Connect(system_font_cb->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED,
-            (wxObjectEventFunction) &OutputWinConfDlg::OnSystemFontCheckbox);
+            wxCommandEventHandler(OutputWinConfDlg::OnSystemFontCheckbox));
     Connect(font_picker_->GetId(), wxEVT_COMMAND_FONTPICKER_CHANGED,
-            (wxObjectEventFunction) &OutputWinConfDlg::OnFontChange);
+            wxFontPickerEventHandler(OutputWinConfDlg::OnFontChange));
     Connect(cp_bg_->GetId(), wxEVT_COMMAND_COLOURPICKER_CHANGED,
-            (wxObjectEventFunction) &OutputWinConfDlg::OnColor);
+            wxColourPickerEventHandler(OutputWinConfDlg::OnColor));
     Connect(cp_input_->GetId(), wxEVT_COMMAND_COLOURPICKER_CHANGED,
-            (wxObjectEventFunction) &OutputWinConfDlg::OnColor);
+            wxColourPickerEventHandler(OutputWinConfDlg::OnColor));
     Connect(cp_output_->GetId(), wxEVT_COMMAND_COLOURPICKER_CHANGED,
-            (wxObjectEventFunction) &OutputWinConfDlg::OnColor);
+            wxColourPickerEventHandler(OutputWinConfDlg::OnColor));
     Connect(cp_quote_->GetId(), wxEVT_COMMAND_COLOURPICKER_CHANGED,
-            (wxObjectEventFunction) &OutputWinConfDlg::OnColor);
+            wxColourPickerEventHandler(OutputWinConfDlg::OnColor));
     Connect(cp_warning_->GetId(), wxEVT_COMMAND_COLOURPICKER_CHANGED,
-            (wxObjectEventFunction) &OutputWinConfDlg::OnColor);
+            wxColourPickerEventHandler(OutputWinConfDlg::OnColor));
 }
 
 void OutputWinConfDlg::OnSystemFontCheckbox(wxCommandEvent& event)
diff --git a/wxgui/uplot.cpp b/wxgui/uplot.cpp
index cc125168..75de5edc 100644
--- a/wxgui/uplot.cpp
+++ b/wxgui/uplot.cpp
@@ -119,8 +119,7 @@ void BufferedPanel::set_bg_color(wxColour const& c)
 PlotWithTics::PlotWithTics(wxWindow* parent)
     : BufferedPanel(parent)
 {
-    Connect(GetId(), wxEVT_PAINT,
-                  (wxObjectEventFunction) &PlotWithTics::OnPaint);
+    Connect(GetId(), wxEVT_PAINT, wxPaintEventHandler(PlotWithTics::OnPaint));
 }
 
 void PlotWithTics::draw_tics(wxDC &dc, double x_min, double x_max,
diff --git a/wxgui/xybrowser.cpp b/wxgui/xybrowser.cpp
index f95c49a7..a9e92381 100644
--- a/wxgui/xybrowser.cpp
+++ b/wxgui/xybrowser.cpp
@@ -33,16 +33,16 @@ inline std::string S(int n) { return format1<int, 16>("%d", n); }
 inline std::string S(double d) { return format1<double, 16>("%g", d); }
 
 // copied from cmn.h
-class SpinCtrl: public wxSpinCtrl
+inline wxSpinCtrl* make_wxspinctrl(wxWindow* parent, wxWindowID id, int val,
+                                   int min, int max, int width=50)
 {
-public:
-    SpinCtrl(wxWindow* parent, wxWindowID id, int val,
-             int min, int max, int width=50)
-        : wxSpinCtrl (parent, id, wxString::Format(wxT("%i"), val),
-                      wxDefaultPosition, wxSize(width, -1),
-                      wxSP_ARROW_KEYS, min, max, val)
-    {}
-};
+#ifdef __WXGTK3__
+    width += 30;
+#endif
+    return new wxSpinCtrl (parent, id, wxString::Format(wxT("%i"), val),
+                           wxDefaultPosition, wxSize(width, -1),
+                           wxSP_ARROW_KEYS, min, max, val);
+}
 
 #endif // XYCONVERT
 
@@ -95,7 +95,7 @@ void PreviewPlot::load_dataset(string const& filename,
 
 XyFileBrowser::XyFileBrowser(wxWindow* parent)
     : wxSplitterWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
-                       wxSP_NOBORDER),
+                       wxSP_LIVE_UPDATE),
       auto_plot_cb(NULL)
 {
     // +----------------------------+
@@ -110,7 +110,7 @@ XyFileBrowser::XyFileBrowser(wxWindow* parent)
     wxBoxSizer *left_sizer = new wxBoxSizer(wxVERTICAL);
     wxSplitterWindow *right_splitter = new wxSplitterWindow(this, -1,
                                              wxDefaultPosition, wxDefaultSize,
-                                             wxSP_NOBORDER);
+                                             wxSP_LIVE_UPDATE);
     right_splitter->SetSashGravity(0.5);
     right_splitter->SetMinimumPaneSize(20);
     wxPanel *rupper_panel = new wxPanel(right_splitter, -1);
@@ -130,12 +130,14 @@ XyFileBrowser::XyFileBrowser(wxWindow* parent)
     wxBoxSizer *block_sizer = new wxBoxSizer(wxHORIZONTAL);
     block_sizer->Add(new wxStaticText(left_panel, -1, "file format:"),
                      wxSizerFlags().Border(wxLEFT|wxRIGHT).Center());
-    format_ch = new wxChoice(left_panel, -1, wxDefaultPosition, wxSize(140,-1));
+    format_ch = new wxChoice(left_panel, -1);
     format_ch->Append(wxString("<automatic>"));
     const xylibFormat *format;
     for (int i = 0; (format = xylib_get_format(i)) != NULL; ++i)
         format_ch->Append(format->desc);
     format_ch->SetSelection(0);
+    if (format_ch->GetBestSize().GetWidth() < 140)
+        format_ch->SetMinSize(wxSize(140, -1));
     block_sizer->Add(format_ch, wxSizerFlags(0).Border(wxRIGHT));
     block_sizer->Add(new wxStaticText(left_panel, -1, "block:"),
                      wxSizerFlags().Border(wxLEFT|wxRIGHT).Center());
@@ -153,11 +155,11 @@ XyFileBrowser::XyFileBrowser(wxWindow* parent)
                     columns_panel, wxT("Select columns (0 for point index):"));
     h2a_sizer->Add (new wxStaticText (columns_panel, -1, wxT("x")),
                     0, wxALL|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
-    x_column = new SpinCtrl(columns_panel, wxID_ANY, 1, 0, 999, 50);
+    x_column = make_wxspinctrl(columns_panel, wxID_ANY, 1, 0, 999, 50);
     h2a_sizer->Add (x_column, 0, wxALL|wxALIGN_LEFT, 5);
     h2a_sizer->Add (new wxStaticText (columns_panel, -1, wxT("y")),
                     0, wxALL|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
-    y_column = new SpinCtrl(columns_panel, wxID_ANY, 2, 0, 999, 50);
+    y_column = make_wxspinctrl(columns_panel, wxID_ANY, 2, 0, 999, 50);
     h2a_sizer->Add (y_column, 0, wxALL|wxALIGN_LEFT, 5);
 #ifdef XYCONVERT
     std_dev_b = new wxCheckBox(columns_panel, -1, wxT("\u03C3"));
@@ -166,7 +168,7 @@ XyFileBrowser::XyFileBrowser(wxWindow* parent)
 #endif
     std_dev_b->SetValue(false);
     h2a_sizer->Add(std_dev_b, 0, wxALL|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL,5);
-    s_column = new SpinCtrl(columns_panel, wxID_ANY, 3, 1, 999, 50);
+    s_column = make_wxspinctrl(columns_panel, wxID_ANY, 3, 1, 999, 50);
     h2a_sizer->Add(s_column, 0, wxALL|wxALIGN_LEFT, 5);
 #ifndef XYCONVERT
     h2a_sizer->Add(new wxStaticText(columns_panel, wxID_ANY, "or"),