So -
CMake has a testing framework called CTest that can generate html reports
and it's easy to integrate a new test on it. I created this in cmake *only*
because it was what I had used before, tried to learn the docs for qmake +
tests and it was a bit frustrating / hard to do.


what this does right now:
1 - compiles subsurface in small libraries
( core, ui, profile )
2 - compiles tests that are linked to those libraries
3 - run tests by running 'make test'

make test will run
a few tests are failing, even using IS_FP_SAME, and the plan is to increase
the amount
of code tested to 100% over time ( we can also include the gcov tool to get
the percent of code that is tested. )

Tomaz
From e3bda68cc0e928bca0f26c99ea2943b21bc9bb5e Mon Sep 17 00:00:00 2001
From: Tomaz Canabrava <tomaz.canabr...@intel.com>
Date: Mon, 14 Apr 2014 13:38:21 -0300
Subject: [PATCH 11/11] Rework double-comparisson to use IS_FP_SAME macro.

Signed-off-by: Tomaz Canabrava <tomaz.canabr...@intel.com>
---
 tests/testunitconversions.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/tests/testunitconversions.cpp b/tests/testunitconversions.cpp
index 907b0fc..34bf503 100644
--- a/tests/testunitconversions.cpp
+++ b/tests/testunitconversions.cpp
@@ -12,11 +12,11 @@ void TestUnitConversions::initTestCase()
 
 void TestUnitConversions::testUnitConversions()
 {
-	QCOMPARE(grams_to_lbs(1000), 2.20459);
+	QCOMPARE(IS_FP_SAME(grams_to_lbs(1000), 2.20459), true);
 	QCOMPARE(lbs_to_grams(1), 454);
-	QCOMPARE(ml_to_cuft(1000), 0.0353147);
-	QCOMPARE(cuft_to_l(1), 28.3168);
-	QCOMPARE(mm_to_feet(1000), 3.28084);
+	QCOMPARE(IS_FP_SAME(ml_to_cuft(1000), 0.0353147), true);
+	QCOMPARE(IS_FP_SAME(cuft_to_l(1), 28.3168), true);
+	QCOMPARE(IS_FP_SAME(mm_to_feet(1000), 3.28084), true);
 	QCOMPARE(feet_to_mm(1), (long unsigned int) 305);
 }
 
-- 
1.9.2

From 097b5e3ca88d9c9dcf3ea2ff667cff717789356d Mon Sep 17 00:00:00 2001
From: Tomaz Canabrava <tomaz.canabr...@intel.com>
Date: Mon, 14 Apr 2014 13:28:09 -0300
Subject: [PATCH 10/11] Implement the first testcase

This is the very first testcase for subsurface, it tests some of the
unit conversions. The idea is to get 100% of the code coverage, I'll
be working on the bugfixes and adding a testcase for them when fixed.

To test the testcase:
1 - create a out of source build dir, let's say 'build-tests'
2 - run CMake on it ( cmake .. )
3 - compile the code by runnign 'make
4 - run the tests by issuin 'make test'
(optional 5) - if your test fail for some reason, run with ctest -V
to see things more verbosically.

Signed-off-by: Tomaz Canabrava <tomaz.canabr...@intel.com>
---
 CMakeLists.txt                    | 10 ++++++++++
 tests/subsurfaceloadfiletests.cpp | 39 +++++++++++++++++++++++++++++++++++++++
 tests/subsurfaceloadfiletests.h   | 14 ++++++++++++++
 tests/testunitconversions.cpp     | 23 +++++++++++++++++++++++
 tests/testunitconversions.h       | 10 ++++++++++
 5 files changed, 96 insertions(+)
 create mode 100644 tests/subsurfaceloadfiletests.cpp
 create mode 100644 tests/subsurfaceloadfiletests.h
 create mode 100644 tests/testunitconversions.cpp
 create mode 100644 tests/testunitconversions.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index fe9ec1a..b110090 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -110,3 +110,13 @@ target_link_libraries( subsurface
 ADD_DEPENDENCIES(subsurface_profile subsurface_generated_ui)
 ADD_DEPENDENCIES(subsurface_interface subsurface_generated_ui)
 ADD_DEPENDENCIES(subsurface_generated_ui version)
+
+ENABLE_TESTING()
+
+ADD_EXECUTABLE( SubsurfaceLoadFileTest tests/subsurfaceloadfiletests.cpp )
+TARGET_LINK_LIBRARIES( SubsurfaceLoadFileTest ${QT_LIBRARIES})
+ADD_TEST( NAME SubsurfaceLoadFileTest COMMAND SubsurfaceLoadFileTest -v2)
+
+ADD_EXECUTABLE( TestUnitConversion tests/testunitconversions.cpp )
+TARGET_LINK_LIBRARIES( TestUnitConversion ${QT_LIBRARIES})
+ADD_TEST( NAME TestUnitConversion COMMAND TestUnitConversion -v2)
\ No newline at end of file
diff --git a/tests/subsurfaceloadfiletests.cpp b/tests/subsurfaceloadfiletests.cpp
new file mode 100644
index 0000000..f1b615d
--- /dev/null
+++ b/tests/subsurfaceloadfiletests.cpp
@@ -0,0 +1,39 @@
+#include "subsurfaceloadfiletests.h"
+#include <QtTest>
+
+void SubsurfaceLoadFileTests::cleanupTestCase()
+{
+
+}
+
+void SubsurfaceLoadFileTests::initTestCase()
+{
+
+}
+
+void SubsurfaceLoadFileTests::loadMultipleFiles()
+{
+
+}
+
+void SubsurfaceLoadFileTests::loadMultipleFilesImportMultipleFiles()
+{
+
+}
+
+void SubsurfaceLoadFileTests::loadSingleFile()
+{
+
+}
+
+void SubsurfaceLoadFileTests::loadSingleFileImportMultipleFiles()
+{
+
+}
+
+void SubsurfaceLoadFileTests::loadSingleFileImportSingleFile()
+{
+
+}
+
+QTEST_MAIN(SubsurfaceLoadFileTests)
\ No newline at end of file
diff --git a/tests/subsurfaceloadfiletests.h b/tests/subsurfaceloadfiletests.h
new file mode 100644
index 0000000..5a37a3f
--- /dev/null
+++ b/tests/subsurfaceloadfiletests.h
@@ -0,0 +1,14 @@
+#include <QtTest>
+
+class SubsurfaceLoadFileTests: public QObject
+{
+	Q_OBJECT
+private slots:
+	void initTestCase();
+	void loadSingleFile();
+	void loadMultipleFiles();
+	void loadSingleFileImportSingleFile();
+	void loadSingleFileImportMultipleFiles();
+	void loadMultipleFilesImportMultipleFiles();
+	void cleanupTestCase();
+};
\ No newline at end of file
diff --git a/tests/testunitconversions.cpp b/tests/testunitconversions.cpp
new file mode 100644
index 0000000..907b0fc
--- /dev/null
+++ b/tests/testunitconversions.cpp
@@ -0,0 +1,23 @@
+#include "testunitconversions.h"
+#include "dive.h"
+
+void TestUnitConversions::cleanupTestCase()
+{
+
+}
+
+void TestUnitConversions::initTestCase()
+{
+}
+
+void TestUnitConversions::testUnitConversions()
+{
+	QCOMPARE(grams_to_lbs(1000), 2.20459);
+	QCOMPARE(lbs_to_grams(1), 454);
+	QCOMPARE(ml_to_cuft(1000), 0.0353147);
+	QCOMPARE(cuft_to_l(1), 28.3168);
+	QCOMPARE(mm_to_feet(1000), 3.28084);
+	QCOMPARE(feet_to_mm(1), (long unsigned int) 305);
+}
+
+QTEST_MAIN(TestUnitConversions)
diff --git a/tests/testunitconversions.h b/tests/testunitconversions.h
new file mode 100644
index 0000000..a0aca99
--- /dev/null
+++ b/tests/testunitconversions.h
@@ -0,0 +1,10 @@
+#include <QtTest>
+
+class TestUnitConversions: public QObject
+{
+	Q_OBJECT
+private slots:
+	void initTestCase();
+	void testUnitConversions();
+	void cleanupTestCase();
+};
\ No newline at end of file
-- 
1.9.2

From 5ada0985ba7e9af6e010a80f0f8048ccbc6d14f1 Mon Sep 17 00:00:00 2001
From: Tomaz Canabrava <tomaz.canabr...@intel.com>
Date: Fri, 11 Apr 2014 16:20:26 -0300
Subject: [PATCH 09/11] Better Library Handling by pkg-config macro.

each library found by pkg config macro now needs 1 less
line of code. can be just a bit for now but if we increase
the number of used libraries, this will make the make
cleaner.

Signed-off-by: Tomaz Canabrava <tomaz.canabr...@intel.com>
---
 CMakeLists.txt | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index cbdb84b..fe9ec1a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,6 +18,7 @@ MACRO(pkg_config_library LIBNAME pcfile)
 	include_directories(${${LIBNAME}_INCLUDE_DIRS})
 	link_directories(${${LIBNAME}_LIBRARY_DIRS})
 	add_definitions(${${LIBNAME}_CFLAGS_OTHER})
+	set(SUBSURFACE_LINK_LIBRARIES ${SUBSURFACE_LINK_LIBRARIES} ${${LIBNAME}_LIBRARIES})
 ENDMACRO()
 
 pkg_config_library(LIBXML libxml-2.0)
@@ -101,10 +102,7 @@ target_link_libraries( subsurface
   subsurface_corelib
   ${QT_LIBRARIES}
   ${MARBLE_LIBRARIES}
-  ${LIBSQLITE3_LIBRARIES}
-  ${LIBXML_LIBRARIES}
-  ${LIBGIT2_LIBRARIES}
-  ${LIBXSLT_LIBRARIES}
+  ${SUBSURFACE_LINK_LIBRARIES}
   -ldivecomputer
   -lzip
 )
-- 
1.9.2

From 6d8693e4fdd42cf2478bb4b0936755058e8bd802 Mon Sep 17 00:00:00 2001
From: Tomaz Canabrava <tomaz.canabr...@intel.com>
Date: Thu, 10 Apr 2014 16:41:04 -0300
Subject: [PATCH 08/11] Updated gitignore in regard of out of source builds.

Signed-off-by: Tomaz Canabrava <tomaz.canabr...@intel.com>
---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index 6dc0218..1f5d76d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,3 +29,4 @@ Makefile
 subsurface.pro.user*
 Subsurface.app
 .DS_Store
+build*/*
-- 
1.9.2

From b9e3f8ce74cd0ba9f17cd24c40a7e4896eba426f Mon Sep 17 00:00:00 2001
From: Tomaz Canabrava <tomaz.canabr...@intel.com>
Date: Thu, 10 Apr 2014 16:37:21 -0300
Subject: [PATCH 07/11] More cleanup.

Signed-off-by: Tomaz Canabrava <tomaz.canabr...@intel.com>
---
 CMakeLists.txt | 23 +++++++++--------------
 1 file changed, 9 insertions(+), 14 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 958f9a2..cbdb84b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -31,7 +31,6 @@ STRING(COMPARE EQUAL "${${PROJECT_NAME}_SOURCE_DIR}" "${PARENTDIR}" insourcesubd
 IF(NOT (insource OR insourcedir))
 	add_custom_target(link_marble_data ALL COMMAND rm -f marbledata && ln -s ${${PROJECT_NAME}_SOURCE_DIR}/marbledata ${${PROJECT_NAME}_BINARY_DIR}/marbledata)
 ENDIF()
-#xslt
 
 #configure Qt version.
 IF(${SUBSURFACE_QT_VERSION} MATCHES "4")
@@ -40,7 +39,6 @@ IF(${SUBSURFACE_QT_VERSION} MATCHES "4")
 	SET(QT_USE_QTSVG TRUE)
 	SET(QT_USE_QTTEST TRUE)
 	SET(QT_USE_QTWEBKIT TRUE)
-	SET(QT_USE_QTXMLPATTERNS TRUE)
 	FIND_PACKAGE(Qt4 REQUIRED)
 	INCLUDE(${QT_USE_FILE})
 	ADD_DEFINITIONS(${QT_DEFINITIONS})
@@ -77,6 +75,10 @@ LIST(REMOVE_ITEM SUBSURFACE_CORE_LIB_SRCS
 FILE(GLOB SUBSURFACE_PROFILE_LIB_SRCS qt-ui/profile/*.cpp)
 FILE(GLOB SUBSURFACE_UI qt-ui/*.ui)
 FILE(GLOB SUBSURFACE_INTERFACE qt-ui/*.cpp)
+FILE(GLOB SUBSURFACE_APP *.cpp )
+IF(NOT (CMAKE_SYSTEM_NAME MATCHES Android))
+	LIST(REMOVE_ITEM SUBSURFACE_APP ${CMAKE_CURRENT_SOURCE_DIR}/android.cpp)
+ENDIF()
 
 # to be replaced by QT_WRAP_UI on CMake 3.
 IF(${SUBSURFACE_QT_VERSION} MATCHES "4")
@@ -90,14 +92,7 @@ ADD_LIBRARY(subsurface_corelib STATIC ${SUBSURFACE_CORE_LIB_SRCS} )
 ADD_LIBRARY(subsurface_profile STATIC ${SUBSURFACE_PROFILE_LIB_SRCS})
 ADD_LIBRARY(subsurface_generated_ui STATIC ${SUBSURFACE_UI_HDRS})
 ADD_LIBRARY(subsurface_interface STATIC ${SUBSURFACE_INTERFACE})
-ADD_EXECUTABLE(subsurface
-  main.cpp
-  gettextfromc.cpp
-  main.cpp
-  qt-gui.cpp
-  qthelper.cpp
-  ${SUBSURFACE_QRC_HRDS}
-)
+ADD_EXECUTABLE(subsurface ${SUBSURFACE_APP} ${SUBSURFACE_QRC_HRDS} )
 
 target_link_libraries( subsurface
   subsurface_generated_ui
@@ -106,10 +101,10 @@ target_link_libraries( subsurface
   subsurface_corelib
   ${QT_LIBRARIES}
   ${MARBLE_LIBRARIES}
-  -lsqlite3
-  -lxml2
-  -lgit2
-  -lxslt
+  ${LIBSQLITE3_LIBRARIES}
+  ${LIBXML_LIBRARIES}
+  ${LIBGIT2_LIBRARIES}
+  ${LIBXSLT_LIBRARIES}
   -ldivecomputer
   -lzip
 )
-- 
1.9.2

From 387fa4870d0705a8e60a80d770a52efe5a2615f6 Mon Sep 17 00:00:00 2001
From: Tomaz Canabrava <tomaz.canabr...@intel.com>
Date: Thu, 10 Apr 2014 16:18:26 -0300
Subject: [PATCH 06/11] Massive code cleanup on the CMake file.

Just a code cleanup.

Signed-off-by: Tomaz Canabrava <tomaz.canabr...@intel.com>
---
 CMakeLists.txt | 39 ++++++++++++---------------------------
 1 file changed, 12 insertions(+), 27 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index c9331b1..958f9a2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,36 +5,25 @@ cmake_minimum_required(VERSION 2.8)
 SET(SUBSURFACE_QT_VERSION "4")
 SET(CMAKE_AUTOMOC ON)
 SET(CMAKE_AUTOUIC ON)
+
 if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUXX)
   SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_GNU_SOURCE")
 endif()
 
-INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
-INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR})
-INCLUDE_DIRECTORIES( ${CMAKE_BINARY_DIR} )
-INCLUDE_DIRECTORIES(.)
-INCLUDE_DIRECTORIES(qt-ui)
-INCLUDE_DIRECTORIES(qt-ui/profile)
-
+INCLUDE_DIRECTORIES( . ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_BINARY_DIR} qt-ui qt-ui/profile)
 FIND_PACKAGE(PkgConfig)
 
-#libxml
-pkg_check_modules(LIBXML libxml-2.0)
-include_directories(${LIBXML_INCLUDE_DIRS})
-link_directories(${LIBXML_LIBRARY_DIRS})
-add_definitions(${LIBXML_CFLAGS_OTHER})
-
-#sqlite
-pkg_check_modules(LIBSQLITE3 sqlite3)
-include_directories(${LIBSQLITE3_INCLUDE_DIRS})
-link_directories(${LIBSQLITE3_LIBRARY_DIRS})
-add_definitions(${LIBSQLITE3_CFLAGS_OTHER})
+MACRO(pkg_config_library LIBNAME pcfile)
+	pkg_check_modules(${LIBNAME} ${pcfile})
+	include_directories(${${LIBNAME}_INCLUDE_DIRS})
+	link_directories(${${LIBNAME}_LIBRARY_DIRS})
+	add_definitions(${${LIBNAME}_CFLAGS_OTHER})
+ENDMACRO()
 
-#libgit
-pkg_check_modules(LIBGIT2 libgit2)
-include_directories(${LIBGIT2_INCLUDE_DIRS})
-link_directories(${LIBGIT2_LIBRARY_DIRS})
-add_definitions(${LIBGIT2_CFLAGS_OTHER})
+pkg_config_library(LIBXML libxml-2.0)
+pkg_config_library(LIBSQLITE3 sqlite3)
+pkg_config_library(LIBGIT2 libgit2)
+pkg_config_library(LIBXSLT libxslt)
 
 STRING(COMPARE EQUAL "${${PROJECT_NAME}_SOURCE_DIR}" "${${PROJECT_NAME}_BINARY_DIR}" insource)
 GET_FILENAME_COMPONENT(PARENTDIR ${${PROJECT_NAME}_SOURCE_DIR} PATH)
@@ -43,10 +32,6 @@ IF(NOT (insource OR insourcedir))
 	add_custom_target(link_marble_data ALL COMMAND rm -f marbledata && ln -s ${${PROJECT_NAME}_SOURCE_DIR}/marbledata ${${PROJECT_NAME}_BINARY_DIR}/marbledata)
 ENDIF()
 #xslt
-pkg_check_modules(LIBXSLT libxslt)
-include_directories(${LIBXSLT_INCLUDE_DIRS})
-link_directories(${LIBXSLT_LIBRARY_DIRS})
-add_definitions(${LIBXSLT_CFLAGS_OTHER})
 
 #configure Qt version.
 IF(${SUBSURFACE_QT_VERSION} MATCHES "4")
-- 
1.9.2

From ecabec8f805e69889c0728dd9ff01ba6e6757bf6 Mon Sep 17 00:00:00 2001
From: Tomaz Canabrava <tomaz.canabr...@intel.com>
Date: Thu, 10 Apr 2014 16:06:24 -0300
Subject: [PATCH 05/11] Link to marbledata, small fixes on the CMakeLists

This patch makes a link to the current build directory to
marbledata, this way we can run out of sources builds.

Signed-off-by: Tomaz Canabrava <tomaz.canabr...@intel.com>
---
 CMakeLists.txt | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 37b79e7..c9331b1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -19,7 +19,6 @@ INCLUDE_DIRECTORIES(qt-ui/profile)
 FIND_PACKAGE(PkgConfig)
 
 #libxml
-
 pkg_check_modules(LIBXML libxml-2.0)
 include_directories(${LIBXML_INCLUDE_DIRS})
 link_directories(${LIBXML_LIBRARY_DIRS})
@@ -37,6 +36,12 @@ include_directories(${LIBGIT2_INCLUDE_DIRS})
 link_directories(${LIBGIT2_LIBRARY_DIRS})
 add_definitions(${LIBGIT2_CFLAGS_OTHER})
 
+STRING(COMPARE EQUAL "${${PROJECT_NAME}_SOURCE_DIR}" "${${PROJECT_NAME}_BINARY_DIR}" insource)
+GET_FILENAME_COMPONENT(PARENTDIR ${${PROJECT_NAME}_SOURCE_DIR} PATH)
+STRING(COMPARE EQUAL "${${PROJECT_NAME}_SOURCE_DIR}" "${PARENTDIR}" insourcesubdir)
+IF(NOT (insource OR insourcedir))
+	add_custom_target(link_marble_data ALL COMMAND rm -f marbledata && ln -s ${${PROJECT_NAME}_SOURCE_DIR}/marbledata ${${PROJECT_NAME}_BINARY_DIR}/marbledata)
+ENDIF()
 #xslt
 pkg_check_modules(LIBXSLT libxslt)
 include_directories(${LIBXSLT_INCLUDE_DIRS})
@@ -71,7 +76,7 @@ FILE(WRITE ${CMAKE_BINARY_DIR}/version.cmake "EXECUTE_PROCESS(
  )
  CONFIGURE_FILE(\${SRC} \${DST} @ONLY)
 ")
-ADD_CUSTOM_TARGET(version
+ADD_CUSTOM_TARGET(version ALL COMMAND
     ${CMAKE_COMMAND} -D SRC=${CMAKE_BINARY_DIR}/version.h.in
                      -D DST=${CMAKE_BINARY_DIR}/ssrf-version.h
                      -P ${CMAKE_BINARY_DIR}/version.cmake
@@ -100,8 +105,8 @@ ADD_LIBRARY(subsurface_corelib STATIC ${SUBSURFACE_CORE_LIB_SRCS} )
 ADD_LIBRARY(subsurface_profile STATIC ${SUBSURFACE_PROFILE_LIB_SRCS})
 ADD_LIBRARY(subsurface_generated_ui STATIC ${SUBSURFACE_UI_HDRS})
 ADD_LIBRARY(subsurface_interface STATIC ${SUBSURFACE_INTERFACE})
-ADD_EXECUTABLE(subsurface 
-  main.cpp 
+ADD_EXECUTABLE(subsurface
+  main.cpp
   gettextfromc.cpp
   main.cpp
   qt-gui.cpp
@@ -109,11 +114,11 @@ ADD_EXECUTABLE(subsurface
   ${SUBSURFACE_QRC_HRDS}
 )
 
-target_link_libraries( subsurface 
+target_link_libraries( subsurface
   subsurface_generated_ui
   subsurface_interface
-  subsurface_profile 
-  subsurface_corelib 
+  subsurface_profile
+  subsurface_corelib
   ${QT_LIBRARIES}
   ${MARBLE_LIBRARIES}
   -lsqlite3
@@ -126,4 +131,4 @@ target_link_libraries( subsurface
 
 ADD_DEPENDENCIES(subsurface_profile subsurface_generated_ui)
 ADD_DEPENDENCIES(subsurface_interface subsurface_generated_ui)
-ADD_DEPENDENCIES(subsurface_corelib version)
+ADD_DEPENDENCIES(subsurface_generated_ui version)
-- 
1.9.2

From c3527d5ff87547860d0976982ad9718797b595d2 Mon Sep 17 00:00:00 2001
From: Tomaz Canabrava <tomaz.canabr...@intel.com>
Date: Thu, 10 Apr 2014 14:19:36 -0300
Subject: [PATCH 04/11] Compiled Executable on CMake

This patch makes the build with subsurface works on Linux
untested ( and probably will ever be untested ) on other platforms.
The reason for a CMake based build file is just to run
Unit tests, shouldn't be used for production.

Signed-off-by: Tomaz Canabrava <tomaz.canabr...@intel.com>
---
 CMakeLists.txt | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 80 insertions(+), 13 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3ff5722..37b79e7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,50 +1,67 @@
 project(Subsurface)
 cmake_minimum_required(VERSION 2.8)
 
+#options
 SET(SUBSURFACE_QT_VERSION "4")
-
-
+SET(CMAKE_AUTOMOC ON)
+SET(CMAKE_AUTOUIC ON)
 if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUXX)
   SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_GNU_SOURCE")
 endif()
 
 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
 INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR})
+INCLUDE_DIRECTORIES( ${CMAKE_BINARY_DIR} )
+INCLUDE_DIRECTORIES(.)
+INCLUDE_DIRECTORIES(qt-ui)
+INCLUDE_DIRECTORIES(qt-ui/profile)
 
 FIND_PACKAGE(PkgConfig)
+
 #libxml
+
 pkg_check_modules(LIBXML libxml-2.0)
 include_directories(${LIBXML_INCLUDE_DIRS})
 link_directories(${LIBXML_LIBRARY_DIRS})
 add_definitions(${LIBXML_CFLAGS_OTHER})
 
+#sqlite
+pkg_check_modules(LIBSQLITE3 sqlite3)
+include_directories(${LIBSQLITE3_INCLUDE_DIRS})
+link_directories(${LIBSQLITE3_LIBRARY_DIRS})
+add_definitions(${LIBSQLITE3_CFLAGS_OTHER})
+
+#libgit
+pkg_check_modules(LIBGIT2 libgit2)
+include_directories(${LIBGIT2_INCLUDE_DIRS})
+link_directories(${LIBGIT2_LIBRARY_DIRS})
+add_definitions(${LIBGIT2_CFLAGS_OTHER})
+
+#xslt
+pkg_check_modules(LIBXSLT libxslt)
+include_directories(${LIBXSLT_INCLUDE_DIRS})
+link_directories(${LIBXSLT_LIBRARY_DIRS})
+add_definitions(${LIBXSLT_CFLAGS_OTHER})
+
 #configure Qt version.
 IF(${SUBSURFACE_QT_VERSION} MATCHES "4")
-
 	SET(QT_USE_QTNETWORK TRUE)
 	SET(QT_USE_QTXML TRUE)
 	SET(QT_USE_QTSVG TRUE)
 	SET(QT_USE_QTTEST TRUE)
 	SET(QT_USE_QTWEBKIT TRUE)
 	SET(QT_USE_QTXMLPATTERNS TRUE)
-
 	FIND_PACKAGE(Qt4 REQUIRED)
 	INCLUDE(${QT_USE_FILE})
 	ADD_DEFINITIONS(${QT_DEFINITIONS})
+	FIND_PACKAGE(Marble REQUIRED)
+	INCLUDE_DIRECTORIES(${MARBLE_INCLUDE_DIR})
 ELSEIF(${SUBSURFACE_QT_VERSION} MATCHES "5")
+	ADD_DEFINITIONS(-DNO_MARBLE)
 ELSE()
 	message( FATAL_ERROR "Qt version should be 4 or 5" )
 ENDIF()
 
-SET(CMAKE_AUTOMOC ON)
-FILE(GLOB SUBSURFACE_CORE_LIB_SRCS *.c)
-LIST(REMOVE_ITEM SUBSURFACE_CORE_LIB_SRCS
-	${CMAKE_CURRENT_SOURCE_DIR}/windows.c
-	${CMAKE_CURRENT_SOURCE_DIR}/macos.c
-)
-
-ADD_LIBRARY(subsurface_corelib STATIC ${SUBSURFACE_CORE_LIB_SRCS} )
-
 # Generate the ssrf-config.h every 'make'
 FILE(WRITE ${CMAKE_BINARY_DIR}/version.h.in "\#define VERSION_STRING \"4.1.\"@VERSION@\n")
 FILE(WRITE ${CMAKE_BINARY_DIR}/version.cmake "EXECUTE_PROCESS(
@@ -59,4 +76,54 @@ ADD_CUSTOM_TARGET(version
                      -D DST=${CMAKE_BINARY_DIR}/ssrf-version.h
                      -P ${CMAKE_BINARY_DIR}/version.cmake
 )
+
+# compile the core library, in C.
+FILE(GLOB SUBSURFACE_CORE_LIB_SRCS *.c)
+LIST(REMOVE_ITEM SUBSURFACE_CORE_LIB_SRCS
+	${CMAKE_CURRENT_SOURCE_DIR}/windows.c
+	${CMAKE_CURRENT_SOURCE_DIR}/macos.c
+)
+
+FILE(GLOB SUBSURFACE_PROFILE_LIB_SRCS qt-ui/profile/*.cpp)
+FILE(GLOB SUBSURFACE_UI qt-ui/*.ui)
+FILE(GLOB SUBSURFACE_INTERFACE qt-ui/*.cpp)
+
+# to be replaced by QT_WRAP_UI on CMake 3.
+IF(${SUBSURFACE_QT_VERSION} MATCHES "4")
+    QT4_WRAP_UI( SUBSURFACE_UI_HDRS ${SUBSURFACE_UI} )
+    QT4_ADD_RESOURCES( SUBSURFACE_QRC_HRDS subsurface.qrc )
+ELSEIF(${SUBSURFACE_QT_VERSION} MATCHES "5")
+    QT5_WRAP_UI( SUBSURFACE_UI_HDRS ${SUBSURFACE_UI} )
+ENDIF()
+
+ADD_LIBRARY(subsurface_corelib STATIC ${SUBSURFACE_CORE_LIB_SRCS} )
+ADD_LIBRARY(subsurface_profile STATIC ${SUBSURFACE_PROFILE_LIB_SRCS})
+ADD_LIBRARY(subsurface_generated_ui STATIC ${SUBSURFACE_UI_HDRS})
+ADD_LIBRARY(subsurface_interface STATIC ${SUBSURFACE_INTERFACE})
+ADD_EXECUTABLE(subsurface 
+  main.cpp 
+  gettextfromc.cpp
+  main.cpp
+  qt-gui.cpp
+  qthelper.cpp
+  ${SUBSURFACE_QRC_HRDS}
+)
+
+target_link_libraries( subsurface 
+  subsurface_generated_ui
+  subsurface_interface
+  subsurface_profile 
+  subsurface_corelib 
+  ${QT_LIBRARIES}
+  ${MARBLE_LIBRARIES}
+  -lsqlite3
+  -lxml2
+  -lgit2
+  -lxslt
+  -ldivecomputer
+  -lzip
+)
+
+ADD_DEPENDENCIES(subsurface_profile subsurface_generated_ui)
+ADD_DEPENDENCIES(subsurface_interface subsurface_generated_ui)
 ADD_DEPENDENCIES(subsurface_corelib version)
-- 
1.9.2

From d2001e19517ea0e1cfeaa161d631ff0353945d0d Mon Sep 17 00:00:00 2001
From: Tomaz Canabrava <tomaz.canabr...@intel.com>
Date: Thu, 10 Apr 2014 11:08:06 -0300
Subject: [PATCH 03/11] Made the core lib compile in C11 mode.

C11 means a better interoperability with C++, and since the UI
is now made with C++ I think we should try to set our compilers
to use it.

Signed-off-by: Tomaz Canabrava <tomaz.canabr...@intel.com>
---
 CMakeLists.txt | 5 +++++
 device.c       | 4 ++++
 dive.c         | 4 ++++
 parse-xml.c    | 6 +++++-
 profile.c      | 4 ++++
 5 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index de90309..3ff5722 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,6 +3,11 @@ cmake_minimum_required(VERSION 2.8)
 
 SET(SUBSURFACE_QT_VERSION "4")
 
+
+if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUXX)
+  SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_GNU_SOURCE")
+endif()
+
 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
 INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR})
 
diff --git a/device.c b/device.c
index c952c84..df885c6 100644
--- a/device.c
+++ b/device.c
@@ -2,6 +2,10 @@
 #include "dive.h"
 #include "device.h"
 
+#ifndef typeof
+#define typeof __typeof__
+#endif
+
 /*
  * Good fake dive profiles are hard.
  *
diff --git a/dive.c b/dive.c
index 9a83603..c863f79 100644
--- a/dive.c
+++ b/dive.c
@@ -7,6 +7,10 @@
 #include "dive.h"
 #include "planner.h"
 
+#ifndef typeof
+#define typeof __typeof__
+#endif
+
 struct tag_entry *g_tag_list = NULL;
 
 static const char *default_tags[] = {
diff --git a/parse-xml.c b/parse-xml.c
index 483187a..ef35f32 100644
--- a/parse-xml.c
+++ b/parse-xml.c
@@ -5,13 +5,17 @@
 #include <errno.h>
 #include <unistd.h>
 #include <assert.h>
+#ifndef __USE_XOPEN
 #define __USE_XOPEN
+#endif
 #include <time.h>
 #include <libxml/parser.h>
 #include <libxml/parserInternals.h>
 #include <libxml/tree.h>
 #include <libxslt/transform.h>
-
+#ifndef typeof
+#define typeof __typeof__
+#endif
 #include "gettext.h"
 
 #include "dive.h"
diff --git a/profile.c b/profile.c
index 5db3c3d..93a1df5 100644
--- a/profile.c
+++ b/profile.c
@@ -15,6 +15,10 @@
 #include "libdivecomputer/version.h"
 #include "membuffer.h"
 
+#ifndef typeof
+#define typeof __typeof__
+#endif
+
 int selected_dive = -1; /* careful: 0 is a valid value */
 unsigned int dc_number = 0;
 
-- 
1.9.2

From a88cc28bded9abae1a8cc50a98ea81de55c8f8aa Mon Sep 17 00:00:00 2001
From: Tomaz Canabrava <tomaz.canabr...@intel.com>
Date: Tue, 8 Apr 2014 18:26:32 -0300
Subject: [PATCH 02/11] First stub of a CMakeLists.txt make generator.

I *know* that dirk didn't want this but to create unit tests
the cmake is much better to use than the qmake tool, so
you can just forget that this file exists and let me happy
hacking around it.

Currently it does not compile anything, because I didn't
put all the library rules yet, only the Qt4 and the libxml2.

But it already creates the version file. <3

Signed-off-by: Tomaz Canabrava <tomaz.canabr...@intel.com>
---
 CMakeLists.txt | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)
 create mode 100644 CMakeLists.txt

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..de90309
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,57 @@
+project(Subsurface)
+cmake_minimum_required(VERSION 2.8)
+
+SET(SUBSURFACE_QT_VERSION "4")
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR})
+
+FIND_PACKAGE(PkgConfig)
+#libxml
+pkg_check_modules(LIBXML libxml-2.0)
+include_directories(${LIBXML_INCLUDE_DIRS})
+link_directories(${LIBXML_LIBRARY_DIRS})
+add_definitions(${LIBXML_CFLAGS_OTHER})
+
+#configure Qt version.
+IF(${SUBSURFACE_QT_VERSION} MATCHES "4")
+
+	SET(QT_USE_QTNETWORK TRUE)
+	SET(QT_USE_QTXML TRUE)
+	SET(QT_USE_QTSVG TRUE)
+	SET(QT_USE_QTTEST TRUE)
+	SET(QT_USE_QTWEBKIT TRUE)
+	SET(QT_USE_QTXMLPATTERNS TRUE)
+
+	FIND_PACKAGE(Qt4 REQUIRED)
+	INCLUDE(${QT_USE_FILE})
+	ADD_DEFINITIONS(${QT_DEFINITIONS})
+ELSEIF(${SUBSURFACE_QT_VERSION} MATCHES "5")
+ELSE()
+	message( FATAL_ERROR "Qt version should be 4 or 5" )
+ENDIF()
+
+SET(CMAKE_AUTOMOC ON)
+FILE(GLOB SUBSURFACE_CORE_LIB_SRCS *.c)
+LIST(REMOVE_ITEM SUBSURFACE_CORE_LIB_SRCS
+	${CMAKE_CURRENT_SOURCE_DIR}/windows.c
+	${CMAKE_CURRENT_SOURCE_DIR}/macos.c
+)
+
+ADD_LIBRARY(subsurface_corelib STATIC ${SUBSURFACE_CORE_LIB_SRCS} )
+
+# Generate the ssrf-config.h every 'make'
+FILE(WRITE ${CMAKE_BINARY_DIR}/version.h.in "\#define VERSION_STRING \"4.1.\"@VERSION@\n")
+FILE(WRITE ${CMAKE_BINARY_DIR}/version.cmake "EXECUTE_PROCESS(
+	COMMAND date +\"%s\"
+	OUTPUT_VARIABLE VERSION
+	OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ CONFIGURE_FILE(\${SRC} \${DST} @ONLY)
+")
+ADD_CUSTOM_TARGET(version
+    ${CMAKE_COMMAND} -D SRC=${CMAKE_BINARY_DIR}/version.h.in
+                     -D DST=${CMAKE_BINARY_DIR}/ssrf-version.h
+                     -P ${CMAKE_BINARY_DIR}/version.cmake
+)
+ADD_DEPENDENCIES(subsurface_corelib version)
-- 
1.9.2

From fc8f7ecc2e986686d1b208e4561b505471966ba7 Mon Sep 17 00:00:00 2001
From: Tomaz Canabrava <tomaz.canabr...@intel.com>
Date: Tue, 8 Apr 2014 18:26:03 -0300
Subject: [PATCH 01/11] Removed cochram.c file that was unused.

The cochram.c file was unused, so I removed it.

Signed-off-by: Tomaz Canabrava <tomaz.canabr...@intel.com>
---
 cochran.c | 283 --------------------------------------------------------------
 1 file changed, 283 deletions(-)
 delete mode 100644 cochran.c

diff --git a/cochran.c b/cochran.c
deleted file mode 100644
index 018ca67..0000000
--- a/cochran.c
+++ /dev/null
@@ -1,283 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include "dive.h"
-#include "file.h"
-
-#define DON
-
-/*
- * The Cochran file format is designed to be annoying to read. It's roughly:
- *
- * 0x00000: room for 65534 4-byte words, giving the starting offsets
- *   of the dives themselves.
- *
- * 0x3fff8: the size of the file + 1
- * 0x3ffff: 0 (high 32 bits of filesize? Bogus: the offsets into the file
- *   are 32-bit, so it can't be a large file anyway)
- *
- * 0x40000: "block 0": the decoding block. The first byte is some random
- *   value (0x46 in the files I have access to), the next 200+ bytes or so
- *   are the "scrambling array" that needs to be added into the file
- *   contents to make sense of them.
- *
- * The descrambling array seems to be of some random size which is likely
- * determinable from the array somehow, the two test files I have it as
- * 230 bytes and 234 bytes respectively.
- */
-static unsigned int partial_decode(unsigned int start, unsigned int end,
-				   const unsigned char *decode, unsigned offset, unsigned mod,
-				   const unsigned char *buf, unsigned int size, unsigned char *dst)
-{
-	unsigned i, sum = 0;
-
-	for (i = start; i < end; i++) {
-		unsigned char d = decode[offset++];
-		if (i >= size)
-			break;
-		if (offset == mod)
-			offset = 0;
-		d += buf[i];
-		if (dst)
-			dst[i] = d;
-		sum += d;
-	}
-	return sum;
-}
-
-/*
- * The decode buffer size can be figured out by simply trying our the
- * decode: we expect that the scrambled contents are largely random, and
- * thus tend to have half the bits set. Summing over the bytes is going
- * to give an average of 0x80 per byte.
- *
- * The decoded array is mostly full of zeroes, so the sum is lower.
- *
- * Works for me.
- */
-static int figure_out_modulus(const unsigned char *decode, const unsigned char *dive, unsigned int size)
-{
-	int mod, best = -1;
-	unsigned int min = ~0u;
-
-	if (size < 0x1000)
-		return best;
-
-	for (mod = 50; mod < 300; mod++) {
-		unsigned int sum;
-
-		sum = partial_decode(0, 0x0fff, decode, 1, mod, dive, size, NULL);
-		if (sum < min) {
-			min = sum;
-			best = mod;
-		}
-	}
-	return best;
-}
-
-#define hexchar(n) ("0123456789abcdef"[(n) & 15])
-
-static int show_line(unsigned offset, const unsigned char *data, unsigned size, int show_empty)
-{
-	unsigned char bits;
-	int i, off;
-	char buffer[120];
-
-	if (size > 16)
-		size = 16;
-
-	bits = 0;
-	memset(buffer, ' ', sizeof(buffer));
-	off = sprintf(buffer, "%06x ", offset);
-	for (i = 0; i < size; i++) {
-		char *hex = buffer + off + 3 * i;
-		char *asc = buffer + off + 50 + i;
-		unsigned char byte = data[i];
-
-		hex[0] = hexchar(byte >> 4);
-		hex[1] = hexchar(byte);
-		bits |= byte;
-		if (byte < 32 || byte > 126)
-			byte = '.';
-		asc[0] = byte;
-		asc[1] = 0;
-	}
-
-	if (bits) {
-		puts(buffer);
-		return 1;
-	}
-	if (show_empty)
-		puts("...");
-	return 0;
-}
-
-static void cochran_debug_write(const char *filename, const unsigned char *data, unsigned size)
-{
-	int i, show = 1;
-
-	for (i = 0; i < size; i += 16)
-		show = show_line(i, data + i, size - i, show);
-}
-
-static void parse_cochran_header(const char *filename,
-				 const unsigned char *decode, unsigned mod,
-				 const unsigned char *in, unsigned size)
-{
-	char *buf = malloc(size);
-
-	/* Do the "null decode" using a one-byte decode array of '\0' */
-	partial_decode(0, 0x0b14, "", 0, 1, in, size, buf);
-
-	/*
-	 * The header scrambling is different form the dive
-	 * scrambling. Oh yay!
-	 */
-	partial_decode(0x010e, 0x0b14, decode, 0, mod, in, size, buf);
-	partial_decode(0x0b14, 0x1b14, decode, 0, mod, in, size, buf);
-	partial_decode(0x1b14, 0x2b14, decode, 0, mod, in, size, buf);
-	partial_decode(0x2b14, 0x3b14, decode, 0, mod, in, size, buf);
-	partial_decode(0x3b14, 0x5414, decode, 0, mod, in, size, buf);
-	partial_decode(0x5414, size, decode, 0, mod, in, size, buf);
-
-	printf("\n%s, header\n\n", filename);
-	cochran_debug_write(filename, buf, size);
-
-	free(buf);
-}
-
-/*
- * Cochran export files show that depths seem to be in
- * quarter feet (rounded up to tenths).
- *
- * Temperature seems to be exported in Fahrenheit.
- *
- * Cylinder pressure seems to be in multiples of 4 psi.
- *
- * The data seems to be some byte-stream where the pattern
- * appears to be that the two high bits indicate type of
- * data.
- *
- * For '00', the low six bits seem to be positive
- * values with a distribution towards zero, probably depth
- * deltas. '0 0' exists, but is very rare ("surface"?). 63
- * exists, but is rare.
- *
- * For '01', the low six bits seem to be a signed binary value,
- * with the most common being 0, and 1 and -1 (63) being the
- * next most common values.
- *
- * NOTE! Don's CAN data is different. It shows the reverse pattern
- * for 00 and 01 above: 00 looks like signed data, with 01 looking
- * like unsigned data.
- *
- * For '10', there seems to be another positive value distribution,
- * but unlike '00' the value 0 is common, and I see examples of 63
- * too ("overflow"?) and a spike at '7'.
- *
- * Again, Don's data is different.
- *
- * The values for '11' seem to be some exception case. Possibly
- * overflow handling, possibly warning events. It doesn't have
- * any clear distribution: values 0, 1, 16, 33, 35, 48, 51, 55
- * and 63 are common.
- *
- * For David and Don's data, '01' is the most common, with '00'
- * and '10' not uncommon. '11' is two orders of magnitude less
- * common.
- *
- * For Alex, '00' is the most common, with 01 about a third as
- * common, and 02 a third of that. 11 is least common.
- *
- * There clearly are variations in the format here. And Alex has
- * a different data offset than Don/David too (see the #ifdef DON).
- * Christ. Maybe I've misread the patterns entirely.
- */
-static void cochran_profile_write(const unsigned char *buf, int size)
-{
-	int i;
-
-	for (i = 0; i < size; i++) {
-		unsigned char c = buf[i];
-		printf("%d %d\n",
-		       c >> 6, c & 0x3f);
-	}
-}
-
-static void parse_cochran_dive(const char *filename, int dive,
-			       const unsigned char *decode, unsigned mod,
-			       const unsigned char *in, unsigned size)
-{
-	char *buf = malloc(size);
-#ifdef DON
-	unsigned int offset = 0x4a14;
-#else
-	unsigned int offset = 0x4b14;
-#endif
-
-	/*
-	 * The scrambling has odd boundaries. I think the boundaries
-	 * match some data structure size, but I don't know. They were
-	 * discovered the same way we dynamically discover the decode
-	 * size: automatically looking for least random output.
-	 *
-	 * The boundaries are also this confused "off-by-one" thing,
-	 * the same way the file size is off by one. It's as if the
-	 * cochran software forgot to write one byte at the beginning.
-	 */
-	partial_decode(0, 0x0fff, decode, 1, mod, in, size, buf);
-	partial_decode(0x0fff, 0x1fff, decode, 0, mod, in, size, buf);
-	partial_decode(0x1fff, 0x2fff, decode, 0, mod, in, size, buf);
-	partial_decode(0x2fff, 0x48ff, decode, 0, mod, in, size, buf);
-
-	/*
-	 * This is not all the descrambling you need - the above are just
-	 * what appears to be the fixed-size blocks. The rest is also
-	 * scrambled, but there seems to be size differences in the data,
-	 * so this just descrambles part of it:
-	 */
-	partial_decode(0x48ff, offset, decode, 0, mod, in, size, buf);
-	partial_decode(offset, size, decode, 0, mod, in, size, buf);
-
-	printf("\n%s, dive %d\n\n", filename, dive);
-	cochran_debug_write(filename, buf, size);
-	cochran_profile_write(buf + offset, size - offset);
-
-	free(buf);
-}
-
-int try_to_open_cochran(const char *filename, struct memblock *mem, GError **error)
-{
-	unsigned int i;
-	unsigned int mod;
-	unsigned int *offsets, dive1, dive2;
-	unsigned char *decode = mem->buffer + 0x40001;
-
-	if (mem->size < 0x40000)
-		return 0;
-	offsets = mem->buffer;
-	dive1 = offsets[0];
-	dive2 = offsets[1];
-	if (dive1 < 0x40000 || dive2 < dive1 || dive2 > mem->size)
-		return 0;
-
-	mod = figure_out_modulus(decode, mem->buffer + dive1, dive2 - dive1);
-
-	parse_cochran_header(filename, decode, mod, mem->buffer + 0x40000, dive1 - 0x40000);
-
-	for (i = 0; i < 65534; i++) {
-		dive1 = offsets[i];
-		dive2 = offsets[i + 1];
-		if (dive2 < dive1)
-			break;
-		if (dive2 > mem->size)
-			break;
-		parse_cochran_dive(filename, i + 1, decode, mod, mem->buffer + dive1, dive2 - dive1);
-	}
-
-	exit(0);
-}
-- 
1.9.2

_______________________________________________
subsurface mailing list
subsurface@hohndel.org
http://lists.hohndel.org/cgi-bin/mailman/listinfo/subsurface

Reply via email to