From d3b82dcac0cbd6bb46c3236d1183f84b76b44748 Mon Sep 17 00:00:00 2001
From: Brody Kenrick 
Date: Thu, 5 Dec 2013 15:56:50 +1100
Subject: Fix for bad boost libraries
Get this error because of a search for a non-existent library on linux64
-----------
[ 69%] Built target tests-cgal
Scanning dependencies of target cgalcachetest
[ 70%] Building CXX object
CMakeFiles/cgalcachetest.dir/cgalcachetest.cc.o
make[2]: *** No rule to make target `/usr/lib/libboost_thread.so',
needed by `cgalcachetest'.  Stop.
make[1]: *** [CMakeFiles/cgalcachetest.dir/all] Error 2
make: *** [all] Error 2
[2]+  Done                    gedit openscad.pro  (wd:
~/git/openscad_unicode)
----------
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 0477a45..4cc86f5 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -377,11 +377,45 @@ if("${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}" VERSION_LESS 3.6)
 endif()
 inclusion(CGAL_DIR CGAL_INCLUDE_DIRS)
 
+#Get rid of bad libraries suggested for BOOST dependencies (they don't exist on some machines and cause build failures).
+#/usr/lib/libboost_thread.so;/usr/lib/libboost_system.so;
+string(FIND "${CGAL_3RD_PARTY_LIBRARIES}" "/usr/lib/libboost_system.so" FIND_POSITION  )
+if(NOT "-1" STREQUAL ${FIND_POSITION} )
+if(NOT EXISTS "/usr/lib/libboost_system.so")
+  MESSAGE( WARNING "CGAL_3RD_PARTY_LIBRARIES:Found erroneous /usr/lib/libboost_system.so -- stripping" )
+  string(REPLACE "/usr/lib/libboost_system.so" "" CGAL_3RD_PARTY_LIBRARIES ${CGAL_3RD_PARTY_LIBRARIES})
+endif()
+endif() 
+string(FIND "${CGAL_3RD_PARTY_LIBRARIES}" "/usr/lib/libboost_thread.so" FIND_POSITION  )
+if(NOT "-1" STREQUAL ${FIND_POSITION} )
+if(NOT EXISTS "/usr/lib/libboost_thread.so")
+  MESSAGE( WARNING "CGAL_3RD_PARTY_LIBRARIES:Found erroneous /usr/lib/libboost_thread.so -- stripping" )
+  string(REPLACE "/usr/lib/libboost_thread.so" "" CGAL_3RD_PARTY_LIBRARIES ${CGAL_3RD_PARTY_LIBRARIES})
+endif()
+endif() 
 if(${CMAKE_CXX_COMPILER} MATCHES ".*clang.*" AND NOT ${CGAL_CXX_FLAGS_INIT} STREQUAL "" )
 	string(REPLACE "-frounding-math" "" CGAL_CXX_FLAGS_INIT ${CGAL_CXX_FLAGS_INIT})
 	string(REPLACE "--param=ssp-buffer-size=4" "" CGAL_CXX_FLAGS_INIT ${CGAL_CXX_FLAGS_INIT})
 endif()
 
+if (NOT $ENV{OPENSCAD_LIBRARIES} STREQUAL "")
+  # Force pkg-config to look _only_ in the local library folder
+  # in case OPENSCAD_LIBRARIES is set.
+  set(ENV{PKG_CONFIG_PATH} "$ENV{OPENSCAD_LIBRARIES}/lib/pkgconfig")
+  set(ENV{PKG_CONFIG_LIBDIR} "$ENV{OPENSCAD_LIBRARIES}/lib/pkgconfig")
+endif()
+
+# Find libraries (system installed or dependency built) using pkg-config
+find_package(PkgConfig REQUIRED)
+
+#GLib-2
+pkg_search_module(GLIB2 REQUIRED glib-2.0>=2.2.0)
+#Can't use the CXXFlags directly as they are ;-separated
+string(REPLACE ";" " " GLIB2_CFLAGS "${GLIB2_CFLAGS}")
+message(STATUS "glib-2.0 found: ${GLIB2_VERSION}")
+
+add_definitions(${GLIB2_CFLAGS})
+
 # Imagemagick
 
 if (SKIP_IMAGEMAGICK)
-- 
cgit v0.10.1
From 0717c67c9fa894ecb08dc5de281753a00922d1ee Mon Sep 17 00:00:00 2001
From: Brody Kenrick 
Date: Thu, 5 Dec 2013 17:56:54 +1100
Subject: Unicode support for strings
Add suport for using unicode strings in .scad files. Support iterating
across them/accessing them via [] and searching.
--------
Add GLIB (to build for test and normal build -- both with installed and
built locally development files).
Add support for unicode chars to length and search builtin functions and
[] for strings.
Added unicode testing functions.
Ad GLIB to library info page.
diff --git a/.gitignore b/.gitignore
index 50dace1..59bac49 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
 /*.scad
 *.dmg
+*~
 *.tar*
 Makefile
 objects
diff --git a/README.md b/README.md
index 27f12ce..1e97e0f 100644
--- a/README.md
+++ b/README.md
@@ -93,6 +93,7 @@ Follow the instructions for the platform you're compiling on below.
 * [OpenCSG (1.3.2)](http://www.opencsg.org/)
 * [GLEW (1.5.4 ->)](http://glew.sourceforge.net/)
 * [Eigen (3.0 - 3.2)](http://eigen.tuxfamily.org/)
+* [glib2 (2.2.0)](https://developer.gnome.org/glib/)
 * [GCC C++ Compiler (4.2 ->)](http://gcc.gnu.org/)
 * [Bison (2.4)](http://www.gnu.org/software/bison/)
 * [Flex (2.5.35)](http://flex.sourceforge.net/)
diff --git a/common.pri b/common.pri
index 7153ded..696c8b1 100644
--- a/common.pri
+++ b/common.pri
@@ -11,3 +11,4 @@ include(opencsg.pri)
 include(glew.pri)
 include(eigen.pri)
 include(boost.pri)
+include(glib-2.0.pri)
\ No newline at end of file
diff --git a/glib-2.0.pri b/glib-2.0.pri
new file mode 100644
index 0000000..0fbc4e2
--- /dev/null
+++ b/glib-2.0.pri
@@ -0,0 +1,38 @@
+# Detect glib-2.0, then use this priority list to determine
+# which library to use:
+#
+# Priority
+# 1. GLIB2_INCLUDEPATH / GLIB2_LIBPATH (qmake parameter, not checked it given on commandline)
+# 2. OPENSCAD_LIBRARIES (environment variable)
+# 3. system's standard include paths from pkg-config
+
+glib-2.0 {
+
+# read environment variables
+OPENSCAD_LIBRARIES_DIR = $$(OPENSCAD_LIBRARIES)
+GLIB2_DIR = $$(GLIB2DIR)
+
+!isEmpty(OPENSCAD_LIBRARIES_DIR) {
+  isEmpty(GLIB2_INCLUDEPATH) {
+    GLIB2_INCLUDEPATH_1 = $$OPENSCAD_LIBRARIES_DIR/include/glib-2.0
+    GLIB2_INCLUDEPATH_2 = $$OPENSCAD_LIBRARIES_DIR/lib/glib-2.0/include
+    GLIB2_LIBPATH = $$OPENSCAD_LIBRARIES_DIR/lib
+  }
+}
+
+isEmpty(GLIB2_INCLUDEPATH) {
+  GLIB2_CFLAGS = $$system("pkg-config --cflags glib-2.0")
+} else {
+  GLIB2_CFLAGS = -I$$GLIB2_INCLUDEPATH_1
+  GLIB2_CFLAGS += -I$$GLIB2_INCLUDEPATH_2
+}
+
+isEmpty(GLIB2_LIBPATH) {
+  GLIB2_LIBS = $$system("pkg-config --libs glib-2.0")
+} else {
+  GLIB2_LIBS = -L$$GLIB2_LIBPATH -lglib-2.0
+}
+
+QMAKE_CXXFLAGS += $$GLIB2_CFLAGS
+LIBS += $$GLIB2_LIBS
+}
diff --git a/openscad.pro b/openscad.pro
index b38419e..ec5af20 100644
--- a/openscad.pro
+++ b/openscad.pro
@@ -8,7 +8,7 @@
 #   OPENCSGDIR
 #   OPENSCAD_LIBRARIES
 #
-# Please see the 'Buildling' sections of the OpenSCAD user manual 
+# Please see the 'Building' sections of the OpenSCAD user manual 
 # for updated tips & workarounds.
 #
 # http://en.wikibooks.org/wiki/OpenSCAD_User_Manual
@@ -156,6 +156,7 @@ CONFIG += cgal
 CONFIG += opencsg
 CONFIG += boost
 CONFIG += eigen
+CONFIG += glib-2.0
 
 #Uncomment the following line to enable QCodeEdit
 #CONFIG += qcodeedit
diff --git a/scripts/check-dependencies.sh b/scripts/check-dependencies.sh
index b63c677..e587198 100755
--- a/scripts/check-dependencies.sh
+++ b/scripts/check-dependencies.sh
@@ -66,6 +66,21 @@ cgal_sysver()
   cgal_sysver_result=`grep "define  *CGAL_VERSION  *[0-9.]*" $cgalpath | awk '{print $3}'`
 }
 
+glib2_sysver()
+{
+  #Get architecture triplet - e.g. x86_64-linux-gnu
+  glib2archtriplet=`gcc -dumpmachine 2>/dev/null`
+  if [ -z "$VAR" ]; then
+    glib2archtriplet=`dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null`
+  fi
+  glib2path=$1/lib/$glib2archtriplet/glib-2.0/include/glibconfig.h
+  if [ ! -e $glib2path ]; then return; fi
+  glib2major=`grep "define  *GLIB_MAJOR_VERSION  *[0-9.]*" $glib2path | awk '{print $3}'`
+  glib2minor=`grep "define  *GLIB_MINOR_VERSION  *[0-9.]*" $glib2path | awk '{print $3}'`
+  glib2micro=`grep "define  *GLIB_MICRO_VERSION  *[0-9.]*" $glib2path | awk '{print $3}'`
+  glib2_sysver_result="${glib2major}.${glib2minor}.${glib2micro}"
+}
+
 boost_sysver()
 {
   boostpath=$1/include/boost/version.hpp
@@ -530,7 +545,7 @@ checkargs()
 
 main()
 {
-  deps="qt4 cgal gmp mpfr boost opencsg glew eigen gcc bison flex make"
+  deps="qt4 cgal gmp mpfr boost opencsg glew eigen glib2 gcc bison flex make"
   #deps="$deps curl git" # not technically necessary for build
   #deps="$deps python cmake imagemagick" # only needed for tests
   #deps="cgal"
diff --git a/scripts/uni-build-dependencies.sh b/scripts/uni-build-dependencies.sh
index e652c47..8d912c3 100755
--- a/scripts/uni-build-dependencies.sh
+++ b/scripts/uni-build-dependencies.sh
@@ -603,5 +603,6 @@ build_boost 1.53.0
 build_cgal 4.0.2
 build_glew 1.9.0
 build_opencsg 1.3.2
+build_glib2 2.38.2
 
 echo "OpenSCAD dependencies built and installed to " $BASEDIR
diff --git a/scripts/uni-get-dependencies.sh b/scripts/uni-get-dependencies.sh
index a0306ef..d2408c0 100755
--- a/scripts/uni-get-dependencies.sh
+++ b/scripts/uni-get-dependencies.sh
@@ -8,7 +8,7 @@ get_fedora_deps()
 {
  sudo yum install qt-devel bison flex eigen3-devel python-paramiko \
   boost-devel mpfr-devel gmp-devel glew-devel CGAL-devel gcc gcc-c++ pkgconfig \
-  opencsg-devel git libXmu-devel curl imagemagick ImageMagick make \
+  opencsg-devel git libXmu-devel curl imagemagick ImageMagick glib2-devel make \
   xorg-x11-server-Xvfb
 }
 
@@ -21,7 +21,7 @@ get_altlinux_deps()
 {
  for i in boost-devel boost-filesystem-devel gcc4.5 gcc4.5-c++ boost-program_options-devel \
   boost-thread-devel boost-system-devel boost-regex-devel eigen3 libmpfr libgmp libgmp_cxx-devel qt4-devel libcgal-devel git-core \
-  libglew-devel flex bison curl imagemagick; do sudo apt-get install $i; done
+  libglew-devel flex bison curl imagemagick glib2-devel; do sudo apt-get install $i; done
 }
 
 get_freebsd_deps()
@@ -29,20 +29,21 @@ get_freebsd_deps()
  pkg_add -r bison boost-libs cmake git bash eigen3 flex gmake gmp mpfr \
   xorg libGLU libXmu libXi xorg-vfbserver glew \
   qt4-corelib qt4-gui qt4-moc qt4-opengl qt4-qmake qt4-rcc qt4-uic \
-  opencsg cgal curl imagemagick
+  opencsg cgal curl imagemagick glib2-devel
 }
 
 get_netbsd_deps()
 {
  sudo pkgin install bison boost cmake git bash eigen flex gmake gmp mpfr \
   qt4 glew cgal opencsg modular-xorg python27 py27-paramiko curl \
-  imagemagick ImageMagick
+  imagemagick ImageMagick glib2-devel
 }
 
 get_opensuse_deps()
 {
  sudo zypper install libeigen3-devel mpfr-devel gmp-devel boost-devel \
-  libqt4-devel glew-devel cmake git bison flex cgal-devel opencsg-devel curl
+  libqt4-devel glew-devel cmake git bison flex cgal-devel opencsg-devel curl \
+  glib2-devel
 }
 
 get_mageia_deps()
@@ -50,7 +51,7 @@ get_mageia_deps()
  sudo urpmi ctags
  sudo urpmi task-c-devel task-c++-devel libqt4-devel libgmp-devel \
   libmpfr-devel libboost-devel eigen3-devel libglew-devel bison flex \
-  cmake imagemagick python curl git x11-server-xvfb
+  cmake imagemagick glib2-devel python curl git x11-server-xvfb
 }
 
 get_debian_deps()
@@ -59,7 +60,7 @@ get_debian_deps()
   libxmu-dev cmake bison flex git-core libboost-all-dev \
   libXi-dev libmpfr-dev libboost-dev libglew-dev \
   libeigen3-dev libcgal-dev libopencsg-dev libgmp3-dev libgmp-dev \
-  python-paramiko curl imagemagick; do
+  python-paramiko curl imagemagick libglib2.0-dev; do
    sudo apt-get -y install $pkg;
  done
 }
diff --git a/src/AboutDialog.html b/src/AboutDialog.html
index 99e7c3b..65a54d7 100644
--- a/src/AboutDialog.html
+++ b/src/AboutDialog.html
@@ -64,6 +64,7 @@ Please visit this link for a copy of the license: C++, GCC, clang
 python
 Nullsoft installer
+GLib
 
 
 
diff --git a/src/PlatformUtils.cc b/src/PlatformUtils.cc
index b02b822..8b39f6d 100644
--- a/src/PlatformUtils.cc
+++ b/src/PlatformUtils.cc
@@ -1,6 +1,8 @@
 #include "PlatformUtils.h"
 #include "boosty.h"
 
+#include 
+
 bool PlatformUtils::createLibraryPath()
 {
 	std::string path = PlatformUtils::libraryPath();
@@ -114,6 +116,7 @@ std::string PlatformUtils::info()
 	  << "\nOpenCSG version: " << OPENCSG_VERSION_STRING
 	  << "\nQt version: " << qtVersion
 	  << "\nMingW build: " << mingwstatus
+	  << "\nGLib version: "       << GLIB_MAJOR_VERSION << "." << GLIB_MINOR_VERSION << "." << GLIB_MICRO_VERSION
 	  << "\nOPENSCADPATH: " << getenv("OPENSCADPATH") << "\n"
 	;
 	return s.str();
diff --git a/src/func.cc b/src/func.cc
index 865a2b4..4587f72 100644
--- a/src/func.cc
+++ b/src/func.cc
@@ -45,6 +45,8 @@
 
 #include 
 #include 
+/*Unicode support for string lengths and array accesses*/
+#include 
 
 #ifdef __WIN32__
 #include 
@@ -306,7 +308,11 @@ Value builtin_length(const Context *, const EvalContext *evalctx)
 {
 	if (evalctx->numArgs() == 1) {
 		if (evalctx->getArgValue(0).type() == Value::VECTOR) return Value(int(evalctx->getArgValue(0).toVector().size()));
-		if (evalctx->getArgValue(0).type() == Value::STRING) return Value(int(evalctx->getArgValue(0).toString().size()));
+		if (evalctx->getArgValue(0).type() == Value::STRING) {
+			//Unicode glyph count for the length -- rather than the string (num. of bytes) length.
+			std::string text = evalctx->getArgValue(0).toString();
+			return Value(int( g_utf8_strlen( text.c_str(), text.size() ) ));
+		}
 	}
 	return Value();
 }
@@ -380,10 +386,17 @@ Value builtin_lookup(const Context *, const EvalContext *evalctx)
   num_returns_per_match : int;
   index_col_num : int;
 
+ The search string and searched strings can be unicode strings.
  Examples:
   Index values return as list:
     search("a","abcdabcd");
-        - returns [0,4]
+        - returns [0]
+    search("Π","Π");  //A unicode string
+        - returns [0]
+    search("π‘aΠ","aπ‘Ππ‘aπ‘Ππ‘a",0);
+        - returns [[1,3,5,7],[0,4,8],[2,6]]
+    search("a","abcdabcd",0); //Search up to all matches
+        - returns [[0,4]]
     search("a","abcdabcd",1);
         - returns [0]
     search("e","abcdabcd",1);
@@ -433,16 +446,25 @@ Value builtin_search(const Context *, const EvalContext *evalctx)
 		}
 	} else if (findThis.type() == Value::STRING) {
 		unsigned int searchTableSize;
-		if (searchTable.type() == Value::STRING) searchTableSize = searchTable.toString().size();
-		else searchTableSize = searchTable.toVector().size();
-		for (size_t i = 0; i < findThis.toString().size(); i++) {
+		//Unicode glyph count for the length
+		unsigned int findThisSize =  g_utf8_strlen( findThis.toString().c_str(), findThis.toString().size() );
+		if (searchTable.type() == Value::STRING) {
+			searchTableSize = g_utf8_strlen( searchTable.toString().c_str(), searchTable.toString().size() );
+		} else {
+		    searchTableSize = searchTable.toVector().size();
+		}
+		for (size_t i = 0; i < findThisSize; i++) {
 		  unsigned int matchCount = 0;
 			Value::VectorType resultvec;
 		  for (size_t j = 0; j < searchTableSize; j++) {
-		    if ((searchTable.type() == Value::VECTOR && 
-						 findThis.toString()[i] == searchTable.toVector()[j].toVector()[index_col_num].toString()[0]) ||
-						(searchTable.type() == Value::STRING && 
-						 findThis.toString()[i] == searchTable.toString()[j])) {
+		    gchar* ptr_ft = g_utf8_offset_to_pointer(findThis.toString().c_str(), i);
+		    gchar* ptr_st = NULL;
+		    if(searchTable.type() == Value::VECTOR) {
+		        ptr_st = g_utf8_offset_to_pointer(searchTable.toVector()[j].toVector()[index_col_num].toString().c_str(), 0);
+		    } else if(searchTable.type() == Value::STRING){
+		    	ptr_st = g_utf8_offset_to_pointer(searchTable.toString().c_str(), j);
+		    }
+		    if( (ptr_ft) && (ptr_st) && (g_utf8_get_char(ptr_ft) == g_utf8_get_char(ptr_st)) ) {
 		      Value resultValue((double(j)));
 		      matchCount++;
 		      if (num_returns_per_match == 1) {
@@ -454,7 +476,14 @@ Value builtin_search(const Context *, const EvalContext *evalctx)
 		      if (num_returns_per_match > 1 && matchCount >= num_returns_per_match) break;
 		    }
 		  }
-		  if (matchCount == 0) PRINTB("  WARNING: search term not found: \"%s\"", findThis.toString()[i]);
+		  if (matchCount == 0) {
+			  gchar* ptr_ft = g_utf8_offset_to_pointer(findThis.toString().c_str(), i);
+			  gchar utf8_of_cp[6] = ""; //A buffer for a single unicode character to be copied into
+			  if(ptr_ft) {
+			      g_utf8_strncpy( utf8_of_cp, ptr_ft, 1 );
+		      }
+			  PRINTB("  WARNING: search term not found: \"%s\"", utf8_of_cp );
+		  }
 		  if (num_returns_per_match == 0 || num_returns_per_match > 1) {
 				returnvec.push_back(Value(resultvec));
 			}
diff --git a/src/value.cc b/src/value.cc
index 5afb650..c8a88c6 100644
--- a/src/value.cc
+++ b/src/value.cc
@@ -36,6 +36,8 @@
 #include 
 #include "boost-utils.h"
 #include "boosty.h"
+/*Unicode support for string lengths and array accesses*/
+#include 
 
 std::ostream &operator<<(std::ostream &stream, const Filename &filename)
 {
@@ -579,14 +581,28 @@ Value Value::operator-() const
   }
 */
 
+/*
+ * bracket operation [] detecting multi-byte unicode.
+ * If the string is multi-byte unicode then the index will offset to the character (2 or 4 byte) and not to the byte.
+ * A 'normal' string with byte chars are a subset of unicode and still work.
+ */
 class bracket_visitor : public boost::static_visitor
 {
 public:
   Value operator()(const std::string &str, const double &idx) const {
     int i = int(idx);
     Value v;
+    //Check that the index is positive and less than the size in bytes
     if ((i >= 0) && (i < (int)str.size())) {
-      v = Value(str[int(idx)]);
+	  //Ensure character (not byte) index is inside the character/glyph array
+	  if( (unsigned) i < g_utf8_strlen( str.c_str(), str.size() ) )	{
+		  gchar utf8_of_cp[6] = ""; //A buffer for a single unicode character to be copied into
+		  gchar* ptr = g_utf8_offset_to_pointer(str.c_str(), i);
+		  if(ptr) {
+		    g_utf8_strncpy(utf8_of_cp, ptr, 1);
+		  }
+		  v = std::string(utf8_of_cp);
+	  }
       //      std::cout << "bracket_visitor: " <<  v << "\n";
     }
     return v;
diff --git a/testdata/scad/misc/search-tests-unicode.scad b/testdata/scad/misc/search-tests-unicode.scad
new file mode 100644
index 0000000..d863eff
--- /dev/null
+++ b/testdata/scad/misc/search-tests-unicode.scad
@@ -0,0 +1,116 @@
+//Test search with unicode strings
+
+//Helper function that pretty prints our search test
+//Expected result is checked against execution of a search() invocation and OK/FAIL is indicated
+module test_search_and_echo( exp_res, search_to_find, search_to_search, search_up_to_num_matches = undef)
+{
+   if(undef != search_up_to_num_matches)
+   {
+      assign( test_res = search(search_to_find, search_to_search, search_up_to_num_matches) )
+      echo(str("Expect ", exp_res, " for search(", search_to_find, ", ", search_to_search, ", ", search_up_to_num_matches, ")=", test_res, ". ", (exp_res == test_res)?"OK":"FAIL"  ));
+   }
+   else
+   {
+      assign( test_res = search(search_to_find, search_to_search) )
+      echo(str("Expect ", exp_res, " for search(", search_to_find, ", ", search_to_search, ")=", test_res, ". ", (exp_res == test_res)?"OK":"FAIL"  ));
+   }
+}
+
+
+//"Normal" text for comparison
+echo ("----- Lookup of 1 byte into 1 byte");
+//Hits - up_to_count 1
+test_search_and_echo( [0],   "a","aaaa" );
+test_search_and_echo( [0],   "a","aaaa",1 );
+test_search_and_echo( [0,0], "aa","aaaa" );
+test_search_and_echo( [0,0], "aa","aaaa",1 );
+
+
+//Hits - up to count 1+ (incl 0 == all)
+test_search_and_echo( [[0,1,2,3]] , 	"a","aaaa",0 );
+test_search_and_echo( [[0,1]], 			"a","aaaa",2 );
+test_search_and_echo( [[0,1,2]], 		"a","aaaa",3 );
+test_search_and_echo( [[0,1,2,3]] , 	"a","aaaa",4 );
+test_search_and_echo( [[0,1,2,3],[0,1,2,3]] , "aa","aaaa",0 );
+//Misses
+test_search_and_echo( [],		"b","aaaa" );
+test_search_and_echo( [],		"b","aaaa",1 );
+test_search_and_echo( [[]],		"b","aaaa",0 );
+test_search_and_echo( [[]],		"b","aaaa",2 );
+
+test_search_and_echo( [],			"bb","aaaa" );
+test_search_and_echo( [],			"bb","aaaa",1 );
+test_search_and_echo( [[],[]],		"bb","aaaa",0 );
+test_search_and_echo( [[],[]],		"bb","aaaa",2 );
+//Miss - empties
+test_search_and_echo( [], "","aaaa" );
+test_search_and_echo( [], "","" );
+test_search_and_echo( [], "a","" );
+
+
+//Unicode tests
+echo ("----- Lookup of multi-byte into 1 byte");
+test_search_and_echo( [],		"Π","aaaa" );
+test_search_and_echo( [],		"π‘","aaaa" );
+test_search_and_echo( [[]],		"Π","aaaa",0 );
+test_search_and_echo( [[]],		"π‘","aaaa",0 );
+
+test_search_and_echo( [],		"ΠΠ","aaaa" );
+test_search_and_echo( [],		"π‘π‘","aaaa" );
+test_search_and_echo( [[],[]],		"ΠΠ","aaaa",0 );
+test_search_and_echo( [[],[]],		"π‘π‘","aaaa",0 );
+
+echo ("----- Lookup of 1-byte into multi-byte");
+test_search_and_echo( [] , "a","ΠΠΠΠ" );
+test_search_and_echo( [] , "a","π‘π‘π‘π‘" );
+test_search_and_echo( [] , "a","ΠΠΠΠ",1 );
+
+test_search_and_echo( [[]] , "a","π‘π‘π‘π‘",0 );
+test_search_and_echo( [[]] , "a","π‘π‘π‘π‘",2 );
+
+echo ("----- Lookup of 1-byte into mixed multi-byte");
+test_search_and_echo( [0], "a","aΠaΠaΠaΠa" );
+test_search_and_echo( [0], "a","aπ‘aπ‘aπ‘aπ‘a" );
+test_search_and_echo( [0], "a","aπ‘Ππ‘aπ‘Ππ‘a" );
+
+test_search_and_echo( [[0,2,4,6,8]], "a","aΠaΠaΠaΠa",0 );
+test_search_and_echo( [[0,2,4,6,8]], "a","aπ‘aπ‘aπ‘aπ‘a", 0 );
+test_search_and_echo( [[0,4,8]]    , "a","aπ‘Ππ‘aπ‘Ππ‘a", 0 );
+
+echo ("----- Lookup of 2-byte into 2-byte");
+test_search_and_echo( [0]       , "Π","ΠΠΠΠ" );
+test_search_and_echo( [[0,1,2,3]] , "Π","ΠΠΠΠ",0 );
+
+echo ("----- Lookup of 2-byte into 4-byte");
+test_search_and_echo( [] , "Π","π‘π‘π‘π‘" );
+
+echo ("----- Lookup of 4-byte into 4-byte");
+test_search_and_echo( [0] , 		  "π‘","π‘π‘π‘π‘" );
+test_search_and_echo( [[0,1,2,3]], "π‘","π‘π‘π‘π‘",0 );
+
+echo ("----- Lookup of 4-byte into 2-byte");
+test_search_and_echo( [] , "π‘","ΠΠΠΠ" );
+
+echo ("----- Lookup of 2-byte into mixed multi-byte");
+test_search_and_echo( [1] , 	"Π","aΠaΠaΠaΠa",1 );
+test_search_and_echo( [] , 	"Π","aπ‘aπ‘aπ‘aπ‘a", 1 );
+test_search_and_echo( [2] , 	"Π","aπ‘Ππ‘aπ‘Ππ‘a", 1 );
+
+test_search_and_echo( [[1,3,5,7]] , 	"Π","aΠaΠaΠaΠa",0 );
+test_search_and_echo( [[]] , 				"Π","aπ‘aπ‘aπ‘aπ‘a", 0 );
+test_search_and_echo( [[2,6]] , 			"Π","aπ‘Ππ‘aπ‘Ππ‘a", 0 );
+
+echo ("----- Lookup of 4-byte into mixed multi-byte");
+test_search_and_echo( [] , 			"π‘","aΠaΠaΠaΠa",1 );
+test_search_and_echo( [1] , "π‘","aπ‘aπ‘aπ‘aπ‘a", 1 );
+
+test_search_and_echo( [[]] , 			"π‘","aΠaΠaΠaΠa",0 );
+test_search_and_echo( [[1,3,5,7]] , "π‘","aπ‘aπ‘aπ‘aπ‘a", 0 );
+test_search_and_echo( [[1,3,5,7]] , "π‘","aπ‘Ππ‘aπ‘Ππ‘a", 0 );
+
+echo ("----- Lookup of mixed multi-byte into mixed multi-byte");
+test_search_and_echo( [[0,2,4,6,8],[1,3,5,7],[]], "aΠπ‘","aΠaΠaΠaΠa",0 );
+test_search_and_echo( [[0,2,4,6,8],[],[1,3,5,7]], "aΠπ‘","aπ‘aπ‘aπ‘aπ‘a", 0 );
+test_search_and_echo( [[0,4,8],[2,6],[1,3,5,7]]    , "aΠπ‘","aπ‘Ππ‘aπ‘Ππ‘a", 0 );
+test_search_and_echo( [[1,3,5,7],[0,4,8],[2,6]]    , "π‘aΠ","aπ‘Ππ‘aπ‘Ππ‘a", 0 );
+
diff --git a/testdata/scad/misc/string-unicode.scad b/testdata/scad/misc/string-unicode.scad
new file mode 100644
index 0000000..d8e3e5c
--- /dev/null
+++ b/testdata/scad/misc/string-unicode.scad
@@ -0,0 +1,36 @@
+//Test how well arrays of unicode string are accessed.
+
+texts_array = [
+"DEADBEEF",
+"ΠΠ΅Π½ΠΈΠ²ΡΠΉ ΡΡΠΆΠΈΠΉ ΠΊΠΎΡ",
+"ΩΨ³ΩΩ Ψ§ΩΨ²ΩΨ¬Ψ¨ΩΩ Ψ§ΩΩΨ·",
+"ζΆζ°ηε§θ²",
+"Àâü ΓΓΓ Γ",
+"πππππ
πππππππππππ",
+"β β β β β 
β β β β β β β β β β ",
+"π‘π±ππ",
+];
+
+text_2bytes = "ΠΠ΅Π½ΠΈΠ²ΡΠΉ ΡΡΠΆΠΈΠΉ ΠΊΠΎΡ";
+text_4bytes = "π‘π±ππ";
+
+
+//Test all the normal accesses
+for (text_array_idx = [0:(len(texts_array)-1)])
+{
+	echo( "[", text_array_idx, "] = ", texts_array[text_array_idx], " of len=", len(texts_array[text_array_idx]), ":"  );
+    for (text_idx = [0:(len(texts_array[text_array_idx])-1)])
+    {
+	    echo( "    [", text_idx, ,"]=", texts_array[text_array_idx][text_idx]  );
+    }
+}
+
+//Test one past the last element of (x-byte unicode). This will be one past the length but inside the char length of the string
+echo( "Past end of unicode only 2-byte ", text_2bytes[len(text_2bytes)]  );
+echo( "Past end of unicode only 4-byte ", text_4bytes[len(text_4bytes)]  );
+
+//Test past the last element of (x-byte unicode). Outside both lengths.
+echo( "Past end of both 2-byte ", text_2bytes[ len(text_2bytes) * 2 ]   );
+echo( "Past end of both 4-byte ", text_4bytes[ len(text_4bytes) * 4 ]   );
+
+
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 4cc86f5..fd5097a 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -587,8 +587,8 @@ set(OFFSCREEN_SOURCES
   ../src/OpenCSGRenderer.cc)
 
 add_library(tests-core STATIC ${CORE_SOURCES})
-target_link_libraries(tests-core ${OPENGL_LIBRARIES})
-set(TESTS-CORE-LIBRARIES ${OPENGL_LIBRARIES} ${Boost_LIBRARIES})
+target_link_libraries(tests-core ${OPENGL_LIBRARIES} ${GLIB2_LIBRARIES} )
+set(TESTS-CORE-LIBRARIES ${OPENGL_LIBRARIES} ${GLIB2_LIBRARIES} ${Boost_LIBRARIES} )
 
 add_library(tests-common STATIC ${COMMON_SOURCES})
 target_link_libraries(tests-common tests-core)
@@ -808,8 +808,10 @@ list(APPEND ECHO_FILES ${FUNCTION_FILES}
             ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/dim-all.scad
             ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/string-test.scad
             ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/string-indexing.scad
+            ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/string-unicode.scad
             ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/vector-values.scad
             ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/search-tests.scad
+            ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/search-tests-unicode.scad
             ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/recursion-tests.scad
             ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/value-reassignment-tests.scad
             ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/value-reassignment-tests2.scad
diff --git a/tests/regression/echotest/search-tests-unicode-expected.echo b/tests/regression/echotest/search-tests-unicode-expected.echo
new file mode 100644
index 0000000..801bc8c
--- /dev/null
+++ b/tests/regression/echotest/search-tests-unicode-expected.echo
@@ -0,0 +1,109 @@
+ECHO: "----- Lookup of 1 byte into 1 byte"
+ECHO: "Expect [0] for search(a, aaaa)=[0]. OK"
+ECHO: "Expect [0] for search(a, aaaa, 1)=[0]. OK"
+ECHO: "Expect [0, 0] for search(aa, aaaa)=[0, 0]. OK"
+ECHO: "Expect [0, 0] for search(aa, aaaa, 1)=[0, 0]. OK"
+ECHO: "Expect [[0, 1, 2, 3]] for search(a, aaaa, 0)=[[0, 1, 2, 3]]. OK"
+ECHO: "Expect [[0, 1]] for search(a, aaaa, 2)=[[0, 1]]. OK"
+ECHO: "Expect [[0, 1, 2]] for search(a, aaaa, 3)=[[0, 1, 2]]. OK"
+ECHO: "Expect [[0, 1, 2, 3]] for search(a, aaaa, 4)=[[0, 1, 2, 3]]. OK"
+ECHO: "Expect [[0, 1, 2, 3], [0, 1, 2, 3]] for search(aa, aaaa, 0)=[[0, 1, 2, 3], [0, 1, 2, 3]]. OK"
+  WARNING: search term not found: "b"
+ECHO: "Expect [] for search(b, aaaa)=[]. OK"
+  WARNING: search term not found: "b"
+ECHO: "Expect [] for search(b, aaaa, 1)=[]. OK"
+  WARNING: search term not found: "b"
+ECHO: "Expect [[]] for search(b, aaaa, 0)=[[]]. OK"
+  WARNING: search term not found: "b"
+ECHO: "Expect [[]] for search(b, aaaa, 2)=[[]]. OK"
+  WARNING: search term not found: "b"
+  WARNING: search term not found: "b"
+ECHO: "Expect [] for search(bb, aaaa)=[]. OK"
+  WARNING: search term not found: "b"
+  WARNING: search term not found: "b"
+ECHO: "Expect [] for search(bb, aaaa, 1)=[]. OK"
+  WARNING: search term not found: "b"
+  WARNING: search term not found: "b"
+ECHO: "Expect [[], []] for search(bb, aaaa, 0)=[[], []]. OK"
+  WARNING: search term not found: "b"
+  WARNING: search term not found: "b"
+ECHO: "Expect [[], []] for search(bb, aaaa, 2)=[[], []]. OK"
+ECHO: "Expect [] for search(, aaaa)=[]. OK"
+ECHO: "Expect [] for search(, )=[]. OK"
+  WARNING: search term not found: "a"
+ECHO: "Expect [] for search(a, )=[]. OK"
+ECHO: "----- Lookup of multi-byte into 1 byte"
+  WARNING: search term not found: "Π"
+ECHO: "Expect [] for search(Π, aaaa)=[]. OK"
+  WARNING: search term not found: "π‘"
+ECHO: "Expect [] for search(π‘, aaaa)=[]. OK"
+  WARNING: search term not found: "Π"
+ECHO: "Expect [[]] for search(Π, aaaa, 0)=[[]]. OK"
+  WARNING: search term not found: "π‘"
+ECHO: "Expect [[]] for search(π‘, aaaa, 0)=[[]]. OK"
+  WARNING: search term not found: "Π"
+  WARNING: search term not found: "Π"
+ECHO: "Expect [] for search(ΠΠ, aaaa)=[]. OK"
+  WARNING: search term not found: "π‘"
+  WARNING: search term not found: "π‘"
+ECHO: "Expect [] for search(π‘π‘, aaaa)=[]. OK"
+  WARNING: search term not found: "Π"
+  WARNING: search term not found: "Π"
+ECHO: "Expect [[], []] for search(ΠΠ, aaaa, 0)=[[], []]. OK"
+  WARNING: search term not found: "π‘"
+  WARNING: search term not found: "π‘"
+ECHO: "Expect [[], []] for search(π‘π‘, aaaa, 0)=[[], []]. OK"
+ECHO: "----- Lookup of 1-byte into multi-byte"
+  WARNING: search term not found: "a"
+ECHO: "Expect [] for search(a, ΠΠΠΠ)=[]. OK"
+  WARNING: search term not found: "a"
+ECHO: "Expect [] for search(a, π‘π‘π‘π‘)=[]. OK"
+  WARNING: search term not found: "a"
+ECHO: "Expect [] for search(a, ΠΠΠΠ, 1)=[]. OK"
+  WARNING: search term not found: "a"
+ECHO: "Expect [[]] for search(a, π‘π‘π‘π‘, 0)=[[]]. OK"
+  WARNING: search term not found: "a"
+ECHO: "Expect [[]] for search(a, π‘π‘π‘π‘, 2)=[[]]. OK"
+ECHO: "----- Lookup of 1-byte into mixed multi-byte"
+ECHO: "Expect [0] for search(a, aΠaΠaΠaΠa)=[0]. OK"
+ECHO: "Expect [0] for search(a, aπ‘aπ‘aπ‘aπ‘a)=[0]. OK"
+ECHO: "Expect [0] for search(a, aπ‘Ππ‘aπ‘Ππ‘a)=[0]. OK"
+ECHO: "Expect [[0, 2, 4, 6, 8]] for search(a, aΠaΠaΠaΠa, 0)=[[0, 2, 4, 6, 8]]. OK"
+ECHO: "Expect [[0, 2, 4, 6, 8]] for search(a, aπ‘aπ‘aπ‘aπ‘a, 0)=[[0, 2, 4, 6, 8]]. OK"
+ECHO: "Expect [[0, 4, 8]] for search(a, aπ‘Ππ‘aπ‘Ππ‘a, 0)=[[0, 4, 8]]. OK"
+ECHO: "----- Lookup of 2-byte into 2-byte"
+ECHO: "Expect [0] for search(Π, ΠΠΠΠ)=[0]. OK"
+ECHO: "Expect [[0, 1, 2, 3]] for search(Π, ΠΠΠΠ, 0)=[[0, 1, 2, 3]]. OK"
+ECHO: "----- Lookup of 2-byte into 4-byte"
+  WARNING: search term not found: "Π"
+ECHO: "Expect [] for search(Π, π‘π‘π‘π‘)=[]. OK"
+ECHO: "----- Lookup of 4-byte into 4-byte"
+ECHO: "Expect [0] for search(π‘, π‘π‘π‘π‘)=[0]. OK"
+ECHO: "Expect [[0, 1, 2, 3]] for search(π‘, π‘π‘π‘π‘, 0)=[[0, 1, 2, 3]]. OK"
+ECHO: "----- Lookup of 4-byte into 2-byte"
+  WARNING: search term not found: "π‘"
+ECHO: "Expect [] for search(π‘, ΠΠΠΠ)=[]. OK"
+ECHO: "----- Lookup of 2-byte into mixed multi-byte"
+ECHO: "Expect [1] for search(Π, aΠaΠaΠaΠa, 1)=[1]. OK"
+  WARNING: search term not found: "Π"
+ECHO: "Expect [] for search(Π, aπ‘aπ‘aπ‘aπ‘a, 1)=[]. OK"
+ECHO: "Expect [2] for search(Π, aπ‘Ππ‘aπ‘Ππ‘a, 1)=[2]. OK"
+ECHO: "Expect [[1, 3, 5, 7]] for search(Π, aΠaΠaΠaΠa, 0)=[[1, 3, 5, 7]]. OK"
+  WARNING: search term not found: "Π"
+ECHO: "Expect [[]] for search(Π, aπ‘aπ‘aπ‘aπ‘a, 0)=[[]]. OK"
+ECHO: "Expect [[2, 6]] for search(Π, aπ‘Ππ‘aπ‘Ππ‘a, 0)=[[2, 6]]. OK"
+ECHO: "----- Lookup of 4-byte into mixed multi-byte"
+  WARNING: search term not found: "π‘"
+ECHO: "Expect [] for search(π‘, aΠaΠaΠaΠa, 1)=[]. OK"
+ECHO: "Expect [1] for search(π‘, aπ‘aπ‘aπ‘aπ‘a, 1)=[1]. OK"
+  WARNING: search term not found: "π‘"
+ECHO: "Expect [[]] for search(π‘, aΠaΠaΠaΠa, 0)=[[]]. OK"
+ECHO: "Expect [[1, 3, 5, 7]] for search(π‘, aπ‘aπ‘aπ‘aπ‘a, 0)=[[1, 3, 5, 7]]. OK"
+ECHO: "Expect [[1, 3, 5, 7]] for search(π‘, aπ‘Ππ‘aπ‘Ππ‘a, 0)=[[1, 3, 5, 7]]. OK"
+ECHO: "----- Lookup of mixed multi-byte into mixed multi-byte"
+  WARNING: search term not found: "π‘"
+ECHO: "Expect [[0, 2, 4, 6, 8], [1, 3, 5, 7], []] for search(aΠπ‘, aΠaΠaΠaΠa, 0)=[[0, 2, 4, 6, 8], [1, 3, 5, 7], []]. OK"
+  WARNING: search term not found: "Π"
+ECHO: "Expect [[0, 2, 4, 6, 8], [], [1, 3, 5, 7]] for search(aΠπ‘, aπ‘aπ‘aπ‘aπ‘a, 0)=[[0, 2, 4, 6, 8], [], [1, 3, 5, 7]]. OK"
+ECHO: "Expect [[0, 4, 8], [2, 6], [1, 3, 5, 7]] for search(aΠπ‘, aπ‘Ππ‘aπ‘Ππ‘a, 0)=[[0, 4, 8], [2, 6], [1, 3, 5, 7]]. OK"
+ECHO: "Expect [[1, 3, 5, 7], [0, 4, 8], [2, 6]] for search(π‘aΠ, aπ‘Ππ‘aπ‘Ππ‘a, 0)=[[1, 3, 5, 7], [0, 4, 8], [2, 6]]. OK"
diff --git a/tests/regression/echotest/string-unicode-expected.echo b/tests/regression/echotest/string-unicode-expected.echo
new file mode 100644
index 0000000..b4b848f
--- /dev/null
+++ b/tests/regression/echotest/string-unicode-expected.echo
@@ -0,0 +1,104 @@
+ECHO: "[", 0, "] = ", "DEADBEEF", " of len=", 8, ":"
+ECHO: "    [", 0, "]=", "D"
+ECHO: "    [", 1, "]=", "E"
+ECHO: "    [", 2, "]=", "A"
+ECHO: "    [", 3, "]=", "D"
+ECHO: "    [", 4, "]=", "B"
+ECHO: "    [", 5, "]=", "E"
+ECHO: "    [", 6, "]=", "E"
+ECHO: "    [", 7, "]=", "F"
+ECHO: "[", 1, "] = ", "ΠΠ΅Π½ΠΈΠ²ΡΠΉ ΡΡΠΆΠΈΠΉ ΠΊΠΎΡ", " of len=", 17, ":"
+ECHO: "    [", 0, "]=", "Π"
+ECHO: "    [", 1, "]=", "Π΅"
+ECHO: "    [", 2, "]=", "Π½"
+ECHO: "    [", 3, "]=", "ΠΈ"
+ECHO: "    [", 4, "]=", "Π²"
+ECHO: "    [", 5, "]=", "Ρ"
+ECHO: "    [", 6, "]=", "ΠΉ"
+ECHO: "    [", 7, "]=", " "
+ECHO: "    [", 8, "]=", "Ρ"
+ECHO: "    [", 9, "]=", "Ρ"
+ECHO: "    [", 10, "]=", "ΠΆ"
+ECHO: "    [", 11, "]=", "ΠΈ"
+ECHO: "    [", 12, "]=", "ΠΉ"
+ECHO: "    [", 13, "]=", " "
+ECHO: "    [", 14, "]=", "ΠΊ"
+ECHO: "    [", 15, "]=", "ΠΎ"
+ECHO: "    [", 16, "]=", "Ρ"
+ECHO: "[", 2, "] = ", "ΩΨ³ΩΩ Ψ§ΩΨ²ΩΨ¬Ψ¨ΩΩ Ψ§ΩΩΨ·", " of len=", 18, ":"
+ECHO: "    [", 0, "]=", "Ω"
+ECHO: "    [", 1, "]=", "Ψ³"
+ECHO: "    [", 2, "]=", "Ω"
+ECHO: "    [", 3, "]=", "Ω"
+ECHO: "    [", 4, "]=", " "
+ECHO: "    [", 5, "]=", "Ψ§"
+ECHO: "    [", 6, "]=", "Ω"
+ECHO: "    [", 7, "]=", "Ψ²"
+ECHO: "    [", 8, "]=", "Ω"
+ECHO: "    [", 9, "]=", "Ψ¬"
+ECHO: "    [", 10, "]=", "Ψ¨"
+ECHO: "    [", 11, "]=", "Ω"
+ECHO: "    [", 12, "]=", "Ω"
+ECHO: "    [", 13, "]=", " "
+ECHO: "    [", 14, "]=", "Ψ§"
+ECHO: "    [", 15, "]=", "Ω"
+ECHO: "    [", 16, "]=", "Ω"
+ECHO: "    [", 17, "]=", "Ψ·"
+ECHO: "[", 3, "] = ", "ζΆζ°ηε§θ²", " of len=", 5, ":"
+ECHO: "    [", 0, "]=", "ζΆ"
+ECHO: "    [", 1, "]=", "ζ°"
+ECHO: "    [", 2, "]=", "η"
+ECHO: "    [", 3, "]=", "ε§"
+ECHO: "    [", 4, "]=", "θ²"
+ECHO: "[", 4, "] = ", "Àâü ΓΓΓ Γ", " of len=", 9, ":"
+ECHO: "    [", 0, "]=", "Γ€"
+ECHO: "    [", 1, "]=", "ΓΆ"
+ECHO: "    [", 2, "]=", "ΓΌ"
+ECHO: "    [", 3, "]=", " "
+ECHO: "    [", 4, "]=", "Γ"
+ECHO: "    [", 5, "]=", "Γ"
+ECHO: "    [", 6, "]=", "Γ"
+ECHO: "    [", 7, "]=", " "
+ECHO: "    [", 8, "]=", "Γ"
+ECHO: "[", 5, "] = ", "πππππ
πππππππππππ", " of len=", 16, ":"
+ECHO: "    [", 0, "]=", "π"
+ECHO: "    [", 1, "]=", "π"
+ECHO: "    [", 2, "]=", "π"
+ECHO: "    [", 3, "]=", "π"
+ECHO: "    [", 4, "]=", "π
"
+ECHO: "    [", 5, "]=", "π"
+ECHO: "    [", 6, "]=", "π"
+ECHO: "    [", 7, "]=", "π"
+ECHO: "    [", 8, "]=", "π"
+ECHO: "    [", 9, "]=", "π"
+ECHO: "    [", 10, "]=", "π"
+ECHO: "    [", 11, "]=", "π"
+ECHO: "    [", 12, "]=", "π"
+ECHO: "    [", 13, "]=", "π"
+ECHO: "    [", 14, "]=", "π"
+ECHO: "    [", 15, "]=", "π"
+ECHO: "[", 6, "] = ", "β β β β β 
β β β β β β β β β β ", " of len=", 15, ":"
+ECHO: "    [", 0, "]=", "β "
+ECHO: "    [", 1, "]=", "β "
+ECHO: "    [", 2, "]=", "β "
+ECHO: "    [", 3, "]=", "β "
+ECHO: "    [", 4, "]=", "β 
"
+ECHO: "    [", 5, "]=", "β "
+ECHO: "    [", 6, "]=", "β "
+ECHO: "    [", 7, "]=", "β "
+ECHO: "    [", 8, "]=", "β "
+ECHO: "    [", 9, "]=", "β "
+ECHO: "    [", 10, "]=", "β "
+ECHO: "    [", 11, "]=", "β "
+ECHO: "    [", 12, "]=", "β "
+ECHO: "    [", 13, "]=", "β "
+ECHO: "    [", 14, "]=", "β "
+ECHO: "[", 7, "] = ", "π‘π±ππ", " of len=", 4, ":"
+ECHO: "    [", 0, "]=", "π‘"
+ECHO: "    [", 1, "]=", "π±"
+ECHO: "    [", 2, "]=", "π"
+ECHO: "    [", 3, "]=", "π"
+ECHO: "Past end of unicode only 2-byte ", undef
+ECHO: "Past end of unicode only 4-byte ", undef
+ECHO: "Past end of both 2-byte ", undef
+ECHO: "Past end of both 4-byte ", undef
-- 
cgit v0.10.1
From ac7b37a3d67662b99adb2648945f7c972624344c Mon Sep 17 00:00:00 2001
From: Brody Kenrick 
Date: Fri, 6 Dec 2013 09:56:22 +1100
Subject: Update comments/messages for CGAL source of bad boost libraries
Add comments and change to a status instead of a warning (as we recover
nicely and it is a known issue in CGAL @
https://bugs.launchpad.net/ubuntu/+source/cgal/+bug/1242111)
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index fd5097a..65eefcd 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -376,23 +376,24 @@ if("${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}" VERSION_LESS 3.6)
   message(FATAL_ERROR "CGAL >= 3.6 required")
 endif()
 inclusion(CGAL_DIR CGAL_INCLUDE_DIRS)
-
-#Get rid of bad libraries suggested for BOOST dependencies (they don't exist on some machines and cause build failures).
-#/usr/lib/libboost_thread.so;/usr/lib/libboost_system.so;
+#Remove bad BOOST libraries from CGAL 3rd party dependencies when they don't exist (such as on 64-bit Ubuntu 13.10).
+#Libs of concern are /usr/lib/libboost_thread.so;/usr/lib/libboost_system.so;
+#Confirmed bug in CGAL @ https://bugs.launchpad.net/ubuntu/+source/cgal/+bug/1242111
 string(FIND "${CGAL_3RD_PARTY_LIBRARIES}" "/usr/lib/libboost_system.so" FIND_POSITION  )
 if(NOT "-1" STREQUAL ${FIND_POSITION} )
-if(NOT EXISTS "/usr/lib/libboost_system.so")
-  MESSAGE( WARNING "CGAL_3RD_PARTY_LIBRARIES:Found erroneous /usr/lib/libboost_system.so -- stripping" )
-  string(REPLACE "/usr/lib/libboost_system.so" "" CGAL_3RD_PARTY_LIBRARIES ${CGAL_3RD_PARTY_LIBRARIES})
-endif()
+  if(NOT EXISTS "/usr/lib/libboost_system.so")
+    MESSAGE( STATUS "CGAL_3RD_PARTY_LIBRARIES:Removing non-existent /usr/lib/libboost_system.so" )
+    string(REPLACE "/usr/lib/libboost_system.so" "" CGAL_3RD_PARTY_LIBRARIES ${CGAL_3RD_PARTY_LIBRARIES})
+  endif()
 endif() 
 string(FIND "${CGAL_3RD_PARTY_LIBRARIES}" "/usr/lib/libboost_thread.so" FIND_POSITION  )
 if(NOT "-1" STREQUAL ${FIND_POSITION} )
-if(NOT EXISTS "/usr/lib/libboost_thread.so")
-  MESSAGE( WARNING "CGAL_3RD_PARTY_LIBRARIES:Found erroneous /usr/lib/libboost_thread.so -- stripping" )
-  string(REPLACE "/usr/lib/libboost_thread.so" "" CGAL_3RD_PARTY_LIBRARIES ${CGAL_3RD_PARTY_LIBRARIES})
-endif()
+  if(NOT EXISTS "/usr/lib/libboost_thread.so")
+    MESSAGE( STATUS "CGAL_3RD_PARTY_LIBRARIES:Removing non-existent /usr/lib/libboost_thread.so" )
+    string(REPLACE "/usr/lib/libboost_thread.so" "" CGAL_3RD_PARTY_LIBRARIES ${CGAL_3RD_PARTY_LIBRARIES})
+  endif()
 endif() 
+
 if(${CMAKE_CXX_COMPILER} MATCHES ".*clang.*" AND NOT ${CGAL_CXX_FLAGS_INIT} STREQUAL "" )
 	string(REPLACE "-frounding-math" "" CGAL_CXX_FLAGS_INIT ${CGAL_CXX_FLAGS_INIT})
 	string(REPLACE "--param=ssp-buffer-size=4" "" CGAL_CXX_FLAGS_INIT ${CGAL_CXX_FLAGS_INIT})
-- 
cgit v0.10.1
From a0d8cbe692a5a474a7bc284cded4a01894b25c2a Mon Sep 17 00:00:00 2001
From: Brody Kenrick 
Date: Fri, 6 Dec 2013 17:46:52 +1100
Subject: Add in missed glib build dependencies for OS X and unix
diff --git a/scripts/macosx-build-dependencies.sh b/scripts/macosx-build-dependencies.sh
index 19c9709..81985bc 100755
--- a/scripts/macosx-build-dependencies.sh
+++ b/scripts/macosx-build-dependencies.sh
@@ -282,6 +282,30 @@ build_glew()
   make GLEW_DEST=$DEPLOYDIR CC=$CC CFLAGS.EXTRA="-no-cpp-precomp -dynamic -fno-common -mmacosx-version-min=$MAC_OSX_VERSION_MIN $GLEW_EXTRA_FLAGS -arch x86_64" LDFLAGS.EXTRA="-mmacosx-version-min=$MAC_OSX_VERSION_MIN $GLEW_EXTRA_FLAGS -arch x86_64" STRIP= install
 }
 
+build_glib2()
+{
+  version="$1"
+  maj_min_version="${version%.*}" #Drop micro
+
+  if [ -e $DEPLOYDIR/lib/glib-2.0 ]; then
+    echo "glib2 already installed. not building"
+    return
+  fi
+
+   echo "Building glib2 $version..."
+  cd "$BASEDIR"/src
+  rm -rf "glib-$version"
+  if [ ! -f "glib-$version.tar.xz" ]; then
+    curl --insecure -LO "http://ftp.gnome.org/pub/gnome/sources/glib/$maj_min_version/glib-$version.tar.xz"
+  fi
+  tar xJf "glib-$version.tar.xz"
+  cd "glib-$version"
+
+  ./configure --prefix="$DEPLOYDIR"
+  make -j$NUMCPU
+  make install
+}
+
 build_opencsg()
 {
   version=$1
@@ -446,6 +470,7 @@ build_boost 1.54.0
 # NB! For CGAL, also update the actual download URL in the function
 build_cgal 4.3
 build_glew 1.10.0
+build_glib2 2.38.1
 build_opencsg 1.3.2
 if $OPTION_DEPLOY; then
 #  build_sparkle andymatuschak 0ed83cf9f2eeb425d4fdd141c01a29d843970c20
diff --git a/scripts/uni-build-dependencies.sh b/scripts/uni-build-dependencies.sh
index 8d912c3..ba328b7 100755
--- a/scripts/uni-build-dependencies.sh
+++ b/scripts/uni-build-dependencies.sh
@@ -409,6 +409,31 @@ build_glew()
   GLEW_DEST=$DEPLOYDIR $MAKER install
 }
 
+build_glib2()
+{
+  version="$1"
+  maj_min_version="${version%.*}" #Drop micro
+
+  if [ -e $DEPLOYDIR/lib/glib-2.0 ]; then
+echo "glib2 already installed. not building"
+    return
+fi
+
+echo "Building glib2 $version..."
+  cd "$BASEDIR"/src
+  rm -rf "glib-$version"
+  if [ ! -f "glib-$version.tar.xz" ]; then
+curl --insecure -LO "http://ftp.gnome.org/pub/gnome/sources/glib/$maj_min_version/glib-$version.tar.xz"
+  fi
+tar xJf "glib-$version.tar.xz"
+  cd "glib-$version"
+
+  ./configure --prefix="$DEPLOYDIR"
+  make -j$NUMCPU
+  make install
+   
+}
+
 build_opencsg()
 {
   if [ -e $DEPLOYDIR/lib/libopencsg.so ]; then
-- 
cgit v0.10.1
From d7d5bea7363703c76b9787598304bfc838e893ee Mon Sep 17 00:00:00 2001
From: Brody Kenrick 
Date: Fri, 6 Dec 2013 18:33:42 +1100
Subject: Add specific tests for unicode len()
diff --git a/testdata/scad/misc/string-unicode.scad b/testdata/scad/misc/string-unicode.scad
index d8e3e5c..1386d63 100644
--- a/testdata/scad/misc/string-unicode.scad
+++ b/testdata/scad/misc/string-unicode.scad
@@ -1,3 +1,12 @@
+//Test length reporting
+text_1bytes_len = "1234";
+text_2bytes_len = "ΠΠΠΠ";
+text_4bytes_len = "π‘π±ππ";
+
+echo( "text_1bytes_len = ", text_1bytes_len, " len = ", len(text_1bytes_len)  );
+echo( "text_2bytes_len = ", text_2bytes_len, " len = ", len(text_2bytes_len)  );
+echo( "text_4bytes_len = ", text_4bytes_len, " len = ", len(text_4bytes_len)  );
+
 //Test how well arrays of unicode string are accessed.
 
 texts_array = [
@@ -33,4 +42,3 @@ echo( "Past end of unicode only 4-byte ", text_4bytes[len(text_4bytes)]  );
 echo( "Past end of both 2-byte ", text_2bytes[ len(text_2bytes) * 2 ]   );
 echo( "Past end of both 4-byte ", text_4bytes[ len(text_4bytes) * 4 ]   );
 
-
diff --git a/tests/regression/echotest/string-unicode-expected.echo b/tests/regression/echotest/string-unicode-expected.echo
index b4b848f..a1cd3be 100644
--- a/tests/regression/echotest/string-unicode-expected.echo
+++ b/tests/regression/echotest/string-unicode-expected.echo
@@ -1,3 +1,6 @@
+ECHO: "text_1bytes_len = ", "1234", " len = ", 4
+ECHO: "text_2bytes_len = ", "ΠΠΠΠ", " len = ", 4
+ECHO: "text_4bytes_len = ", "π‘π±ππ", " len = ", 4
 ECHO: "[", 0, "] = ", "DEADBEEF", " of len=", 8, ":"
 ECHO: "    [", 0, "]=", "D"
 ECHO: "    [", 1, "]=", "E"
-- 
cgit v0.10.1
From 7075d8d9c4dde62798022bdfe02c5d57e997ba43 Mon Sep 17 00:00:00 2001
From: Brody Kenrick 
Date: Thu, 5 Dec 2013 15:56:50 +1100
Subject: Fix for bad boost libraries
Get this error because of a search for a non-existent library on linux64
-----------
[ 69%] Built target tests-cgal
Scanning dependencies of target cgalcachetest
[ 70%] Building CXX object
CMakeFiles/cgalcachetest.dir/cgalcachetest.cc.o
make[2]: *** No rule to make target `/usr/lib/libboost_thread.so',
needed by `cgalcachetest'.  Stop.
make[1]: *** [CMakeFiles/cgalcachetest.dir/all] Error 2
make: *** [all] Error 2
[2]+  Done                    gedit openscad.pro  (wd:
~/git/openscad_unicode)
----------
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index f92eddf..d7ad18a 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -384,11 +384,45 @@ if("${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}" VERSION_LESS 3.6)
 endif()
 inclusion(CGAL_DIR CGAL_INCLUDE_DIRS)
 
+#Get rid of bad libraries suggested for BOOST dependencies (they don't exist on some machines and cause build failures).
+#/usr/lib/libboost_thread.so;/usr/lib/libboost_system.so;
+string(FIND "${CGAL_3RD_PARTY_LIBRARIES}" "/usr/lib/libboost_system.so" FIND_POSITION  )
+if(NOT "-1" STREQUAL ${FIND_POSITION} )
+if(NOT EXISTS "/usr/lib/libboost_system.so")
+  MESSAGE( WARNING "CGAL_3RD_PARTY_LIBRARIES:Found erroneous /usr/lib/libboost_system.so -- stripping" )
+  string(REPLACE "/usr/lib/libboost_system.so" "" CGAL_3RD_PARTY_LIBRARIES ${CGAL_3RD_PARTY_LIBRARIES})
+endif()
+endif() 
+string(FIND "${CGAL_3RD_PARTY_LIBRARIES}" "/usr/lib/libboost_thread.so" FIND_POSITION  )
+if(NOT "-1" STREQUAL ${FIND_POSITION} )
+if(NOT EXISTS "/usr/lib/libboost_thread.so")
+  MESSAGE( WARNING "CGAL_3RD_PARTY_LIBRARIES:Found erroneous /usr/lib/libboost_thread.so -- stripping" )
+  string(REPLACE "/usr/lib/libboost_thread.so" "" CGAL_3RD_PARTY_LIBRARIES ${CGAL_3RD_PARTY_LIBRARIES})
+endif()
+endif() 
 if(${CMAKE_CXX_COMPILER} MATCHES ".*clang.*" AND NOT ${CGAL_CXX_FLAGS_INIT} STREQUAL "" )
 	string(REPLACE "-frounding-math" "" CGAL_CXX_FLAGS_INIT ${CGAL_CXX_FLAGS_INIT})
 	string(REPLACE "--param=ssp-buffer-size=4" "" CGAL_CXX_FLAGS_INIT ${CGAL_CXX_FLAGS_INIT})
 endif()
 
+if (NOT $ENV{OPENSCAD_LIBRARIES} STREQUAL "")
+  # Force pkg-config to look _only_ in the local library folder
+  # in case OPENSCAD_LIBRARIES is set.
+  set(ENV{PKG_CONFIG_PATH} "$ENV{OPENSCAD_LIBRARIES}/lib/pkgconfig")
+  set(ENV{PKG_CONFIG_LIBDIR} "$ENV{OPENSCAD_LIBRARIES}/lib/pkgconfig")
+endif()
+
+# Find libraries (system installed or dependency built) using pkg-config
+find_package(PkgConfig REQUIRED)
+
+#GLib-2
+pkg_search_module(GLIB2 REQUIRED glib-2.0>=2.2.0)
+#Can't use the CXXFlags directly as they are ;-separated
+string(REPLACE ";" " " GLIB2_CFLAGS "${GLIB2_CFLAGS}")
+message(STATUS "glib-2.0 found: ${GLIB2_VERSION}")
+
+add_definitions(${GLIB2_CFLAGS})
+
 # Imagemagick
 
 if (SKIP_IMAGEMAGICK)
-- 
cgit v0.10.1
From 3abf64249fd667f0b7f558ecfbbf35cfe9916a5d Mon Sep 17 00:00:00 2001
From: Brody Kenrick 
Date: Thu, 5 Dec 2013 17:56:54 +1100
Subject: Unicode support for strings
Add suport for using unicode strings in .scad files. Support iterating
across them/accessing them via [] and searching.
--------
Add GLIB (to build for test and normal build -- both with installed and
built locally development files).
Add support for unicode chars to length and search builtin functions and
[] for strings.
Added unicode testing functions.
Ad GLIB to library info page.
diff --git a/.gitignore b/.gitignore
index 50dace1..59bac49 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
 /*.scad
 *.dmg
+*~
 *.tar*
 Makefile
 objects
diff --git a/README.md b/README.md
index 27f12ce..1e97e0f 100644
--- a/README.md
+++ b/README.md
@@ -93,6 +93,7 @@ Follow the instructions for the platform you're compiling on below.
 * [OpenCSG (1.3.2)](http://www.opencsg.org/)
 * [GLEW (1.5.4 ->)](http://glew.sourceforge.net/)
 * [Eigen (3.0 - 3.2)](http://eigen.tuxfamily.org/)
+* [glib2 (2.2.0)](https://developer.gnome.org/glib/)
 * [GCC C++ Compiler (4.2 ->)](http://gcc.gnu.org/)
 * [Bison (2.4)](http://www.gnu.org/software/bison/)
 * [Flex (2.5.35)](http://flex.sourceforge.net/)
diff --git a/common.pri b/common.pri
index 7153ded..696c8b1 100644
--- a/common.pri
+++ b/common.pri
@@ -11,3 +11,4 @@ include(opencsg.pri)
 include(glew.pri)
 include(eigen.pri)
 include(boost.pri)
+include(glib-2.0.pri)
\ No newline at end of file
diff --git a/glib-2.0.pri b/glib-2.0.pri
new file mode 100644
index 0000000..0fbc4e2
--- /dev/null
+++ b/glib-2.0.pri
@@ -0,0 +1,38 @@
+# Detect glib-2.0, then use this priority list to determine
+# which library to use:
+#
+# Priority
+# 1. GLIB2_INCLUDEPATH / GLIB2_LIBPATH (qmake parameter, not checked it given on commandline)
+# 2. OPENSCAD_LIBRARIES (environment variable)
+# 3. system's standard include paths from pkg-config
+
+glib-2.0 {
+
+# read environment variables
+OPENSCAD_LIBRARIES_DIR = $$(OPENSCAD_LIBRARIES)
+GLIB2_DIR = $$(GLIB2DIR)
+
+!isEmpty(OPENSCAD_LIBRARIES_DIR) {
+  isEmpty(GLIB2_INCLUDEPATH) {
+    GLIB2_INCLUDEPATH_1 = $$OPENSCAD_LIBRARIES_DIR/include/glib-2.0
+    GLIB2_INCLUDEPATH_2 = $$OPENSCAD_LIBRARIES_DIR/lib/glib-2.0/include
+    GLIB2_LIBPATH = $$OPENSCAD_LIBRARIES_DIR/lib
+  }
+}
+
+isEmpty(GLIB2_INCLUDEPATH) {
+  GLIB2_CFLAGS = $$system("pkg-config --cflags glib-2.0")
+} else {
+  GLIB2_CFLAGS = -I$$GLIB2_INCLUDEPATH_1
+  GLIB2_CFLAGS += -I$$GLIB2_INCLUDEPATH_2
+}
+
+isEmpty(GLIB2_LIBPATH) {
+  GLIB2_LIBS = $$system("pkg-config --libs glib-2.0")
+} else {
+  GLIB2_LIBS = -L$$GLIB2_LIBPATH -lglib-2.0
+}
+
+QMAKE_CXXFLAGS += $$GLIB2_CFLAGS
+LIBS += $$GLIB2_LIBS
+}
diff --git a/openscad.pro b/openscad.pro
index b38419e..ec5af20 100644
--- a/openscad.pro
+++ b/openscad.pro
@@ -8,7 +8,7 @@
 #   OPENCSGDIR
 #   OPENSCAD_LIBRARIES
 #
-# Please see the 'Buildling' sections of the OpenSCAD user manual 
+# Please see the 'Building' sections of the OpenSCAD user manual 
 # for updated tips & workarounds.
 #
 # http://en.wikibooks.org/wiki/OpenSCAD_User_Manual
@@ -156,6 +156,7 @@ CONFIG += cgal
 CONFIG += opencsg
 CONFIG += boost
 CONFIG += eigen
+CONFIG += glib-2.0
 
 #Uncomment the following line to enable QCodeEdit
 #CONFIG += qcodeedit
diff --git a/scripts/check-dependencies.sh b/scripts/check-dependencies.sh
index b63c677..e587198 100755
--- a/scripts/check-dependencies.sh
+++ b/scripts/check-dependencies.sh
@@ -66,6 +66,21 @@ cgal_sysver()
   cgal_sysver_result=`grep "define  *CGAL_VERSION  *[0-9.]*" $cgalpath | awk '{print $3}'`
 }
 
+glib2_sysver()
+{
+  #Get architecture triplet - e.g. x86_64-linux-gnu
+  glib2archtriplet=`gcc -dumpmachine 2>/dev/null`
+  if [ -z "$VAR" ]; then
+    glib2archtriplet=`dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null`
+  fi
+  glib2path=$1/lib/$glib2archtriplet/glib-2.0/include/glibconfig.h
+  if [ ! -e $glib2path ]; then return; fi
+  glib2major=`grep "define  *GLIB_MAJOR_VERSION  *[0-9.]*" $glib2path | awk '{print $3}'`
+  glib2minor=`grep "define  *GLIB_MINOR_VERSION  *[0-9.]*" $glib2path | awk '{print $3}'`
+  glib2micro=`grep "define  *GLIB_MICRO_VERSION  *[0-9.]*" $glib2path | awk '{print $3}'`
+  glib2_sysver_result="${glib2major}.${glib2minor}.${glib2micro}"
+}
+
 boost_sysver()
 {
   boostpath=$1/include/boost/version.hpp
@@ -530,7 +545,7 @@ checkargs()
 
 main()
 {
-  deps="qt4 cgal gmp mpfr boost opencsg glew eigen gcc bison flex make"
+  deps="qt4 cgal gmp mpfr boost opencsg glew eigen glib2 gcc bison flex make"
   #deps="$deps curl git" # not technically necessary for build
   #deps="$deps python cmake imagemagick" # only needed for tests
   #deps="cgal"
diff --git a/scripts/uni-build-dependencies.sh b/scripts/uni-build-dependencies.sh
index e652c47..8d912c3 100755
--- a/scripts/uni-build-dependencies.sh
+++ b/scripts/uni-build-dependencies.sh
@@ -603,5 +603,6 @@ build_boost 1.53.0
 build_cgal 4.0.2
 build_glew 1.9.0
 build_opencsg 1.3.2
+build_glib2 2.38.2
 
 echo "OpenSCAD dependencies built and installed to " $BASEDIR
diff --git a/scripts/uni-get-dependencies.sh b/scripts/uni-get-dependencies.sh
index a0306ef..d2408c0 100755
--- a/scripts/uni-get-dependencies.sh
+++ b/scripts/uni-get-dependencies.sh
@@ -8,7 +8,7 @@ get_fedora_deps()
 {
  sudo yum install qt-devel bison flex eigen3-devel python-paramiko \
   boost-devel mpfr-devel gmp-devel glew-devel CGAL-devel gcc gcc-c++ pkgconfig \
-  opencsg-devel git libXmu-devel curl imagemagick ImageMagick make \
+  opencsg-devel git libXmu-devel curl imagemagick ImageMagick glib2-devel make \
   xorg-x11-server-Xvfb
 }
 
@@ -21,7 +21,7 @@ get_altlinux_deps()
 {
  for i in boost-devel boost-filesystem-devel gcc4.5 gcc4.5-c++ boost-program_options-devel \
   boost-thread-devel boost-system-devel boost-regex-devel eigen3 libmpfr libgmp libgmp_cxx-devel qt4-devel libcgal-devel git-core \
-  libglew-devel flex bison curl imagemagick; do sudo apt-get install $i; done
+  libglew-devel flex bison curl imagemagick glib2-devel; do sudo apt-get install $i; done
 }
 
 get_freebsd_deps()
@@ -29,20 +29,21 @@ get_freebsd_deps()
  pkg_add -r bison boost-libs cmake git bash eigen3 flex gmake gmp mpfr \
   xorg libGLU libXmu libXi xorg-vfbserver glew \
   qt4-corelib qt4-gui qt4-moc qt4-opengl qt4-qmake qt4-rcc qt4-uic \
-  opencsg cgal curl imagemagick
+  opencsg cgal curl imagemagick glib2-devel
 }
 
 get_netbsd_deps()
 {
  sudo pkgin install bison boost cmake git bash eigen flex gmake gmp mpfr \
   qt4 glew cgal opencsg modular-xorg python27 py27-paramiko curl \
-  imagemagick ImageMagick
+  imagemagick ImageMagick glib2-devel
 }
 
 get_opensuse_deps()
 {
  sudo zypper install libeigen3-devel mpfr-devel gmp-devel boost-devel \
-  libqt4-devel glew-devel cmake git bison flex cgal-devel opencsg-devel curl
+  libqt4-devel glew-devel cmake git bison flex cgal-devel opencsg-devel curl \
+  glib2-devel
 }
 
 get_mageia_deps()
@@ -50,7 +51,7 @@ get_mageia_deps()
  sudo urpmi ctags
  sudo urpmi task-c-devel task-c++-devel libqt4-devel libgmp-devel \
   libmpfr-devel libboost-devel eigen3-devel libglew-devel bison flex \
-  cmake imagemagick python curl git x11-server-xvfb
+  cmake imagemagick glib2-devel python curl git x11-server-xvfb
 }
 
 get_debian_deps()
@@ -59,7 +60,7 @@ get_debian_deps()
   libxmu-dev cmake bison flex git-core libboost-all-dev \
   libXi-dev libmpfr-dev libboost-dev libglew-dev \
   libeigen3-dev libcgal-dev libopencsg-dev libgmp3-dev libgmp-dev \
-  python-paramiko curl imagemagick; do
+  python-paramiko curl imagemagick libglib2.0-dev; do
    sudo apt-get -y install $pkg;
  done
 }
diff --git a/src/AboutDialog.html b/src/AboutDialog.html
index 99e7c3b..65a54d7 100644
--- a/src/AboutDialog.html
+++ b/src/AboutDialog.html
@@ -64,6 +64,7 @@ Please visit this link for a copy of the license: C++, GCC, clang
 python
 Nullsoft installer
+GLib
 
 
 
diff --git a/src/PlatformUtils.cc b/src/PlatformUtils.cc
index b02b822..8b39f6d 100644
--- a/src/PlatformUtils.cc
+++ b/src/PlatformUtils.cc
@@ -1,6 +1,8 @@
 #include "PlatformUtils.h"
 #include "boosty.h"
 
+#include 
+
 bool PlatformUtils::createLibraryPath()
 {
 	std::string path = PlatformUtils::libraryPath();
@@ -114,6 +116,7 @@ std::string PlatformUtils::info()
 	  << "\nOpenCSG version: " << OPENCSG_VERSION_STRING
 	  << "\nQt version: " << qtVersion
 	  << "\nMingW build: " << mingwstatus
+	  << "\nGLib version: "       << GLIB_MAJOR_VERSION << "." << GLIB_MINOR_VERSION << "." << GLIB_MICRO_VERSION
 	  << "\nOPENSCADPATH: " << getenv("OPENSCADPATH") << "\n"
 	;
 	return s.str();
diff --git a/src/func.cc b/src/func.cc
index 865a2b4..4587f72 100644
--- a/src/func.cc
+++ b/src/func.cc
@@ -45,6 +45,8 @@
 
 #include 
 #include 
+/*Unicode support for string lengths and array accesses*/
+#include 
 
 #ifdef __WIN32__
 #include 
@@ -306,7 +308,11 @@ Value builtin_length(const Context *, const EvalContext *evalctx)
 {
 	if (evalctx->numArgs() == 1) {
 		if (evalctx->getArgValue(0).type() == Value::VECTOR) return Value(int(evalctx->getArgValue(0).toVector().size()));
-		if (evalctx->getArgValue(0).type() == Value::STRING) return Value(int(evalctx->getArgValue(0).toString().size()));
+		if (evalctx->getArgValue(0).type() == Value::STRING) {
+			//Unicode glyph count for the length -- rather than the string (num. of bytes) length.
+			std::string text = evalctx->getArgValue(0).toString();
+			return Value(int( g_utf8_strlen( text.c_str(), text.size() ) ));
+		}
 	}
 	return Value();
 }
@@ -380,10 +386,17 @@ Value builtin_lookup(const Context *, const EvalContext *evalctx)
   num_returns_per_match : int;
   index_col_num : int;
 
+ The search string and searched strings can be unicode strings.
  Examples:
   Index values return as list:
     search("a","abcdabcd");
-        - returns [0,4]
+        - returns [0]
+    search("Π","Π");  //A unicode string
+        - returns [0]
+    search("π‘aΠ","aπ‘Ππ‘aπ‘Ππ‘a",0);
+        - returns [[1,3,5,7],[0,4,8],[2,6]]
+    search("a","abcdabcd",0); //Search up to all matches
+        - returns [[0,4]]
     search("a","abcdabcd",1);
         - returns [0]
     search("e","abcdabcd",1);
@@ -433,16 +446,25 @@ Value builtin_search(const Context *, const EvalContext *evalctx)
 		}
 	} else if (findThis.type() == Value::STRING) {
 		unsigned int searchTableSize;
-		if (searchTable.type() == Value::STRING) searchTableSize = searchTable.toString().size();
-		else searchTableSize = searchTable.toVector().size();
-		for (size_t i = 0; i < findThis.toString().size(); i++) {
+		//Unicode glyph count for the length
+		unsigned int findThisSize =  g_utf8_strlen( findThis.toString().c_str(), findThis.toString().size() );
+		if (searchTable.type() == Value::STRING) {
+			searchTableSize = g_utf8_strlen( searchTable.toString().c_str(), searchTable.toString().size() );
+		} else {
+		    searchTableSize = searchTable.toVector().size();
+		}
+		for (size_t i = 0; i < findThisSize; i++) {
 		  unsigned int matchCount = 0;
 			Value::VectorType resultvec;
 		  for (size_t j = 0; j < searchTableSize; j++) {
-		    if ((searchTable.type() == Value::VECTOR && 
-						 findThis.toString()[i] == searchTable.toVector()[j].toVector()[index_col_num].toString()[0]) ||
-						(searchTable.type() == Value::STRING && 
-						 findThis.toString()[i] == searchTable.toString()[j])) {
+		    gchar* ptr_ft = g_utf8_offset_to_pointer(findThis.toString().c_str(), i);
+		    gchar* ptr_st = NULL;
+		    if(searchTable.type() == Value::VECTOR) {
+		        ptr_st = g_utf8_offset_to_pointer(searchTable.toVector()[j].toVector()[index_col_num].toString().c_str(), 0);
+		    } else if(searchTable.type() == Value::STRING){
+		    	ptr_st = g_utf8_offset_to_pointer(searchTable.toString().c_str(), j);
+		    }
+		    if( (ptr_ft) && (ptr_st) && (g_utf8_get_char(ptr_ft) == g_utf8_get_char(ptr_st)) ) {
 		      Value resultValue((double(j)));
 		      matchCount++;
 		      if (num_returns_per_match == 1) {
@@ -454,7 +476,14 @@ Value builtin_search(const Context *, const EvalContext *evalctx)
 		      if (num_returns_per_match > 1 && matchCount >= num_returns_per_match) break;
 		    }
 		  }
-		  if (matchCount == 0) PRINTB("  WARNING: search term not found: \"%s\"", findThis.toString()[i]);
+		  if (matchCount == 0) {
+			  gchar* ptr_ft = g_utf8_offset_to_pointer(findThis.toString().c_str(), i);
+			  gchar utf8_of_cp[6] = ""; //A buffer for a single unicode character to be copied into
+			  if(ptr_ft) {
+			      g_utf8_strncpy( utf8_of_cp, ptr_ft, 1 );
+		      }
+			  PRINTB("  WARNING: search term not found: \"%s\"", utf8_of_cp );
+		  }
 		  if (num_returns_per_match == 0 || num_returns_per_match > 1) {
 				returnvec.push_back(Value(resultvec));
 			}
diff --git a/src/value.cc b/src/value.cc
index 5afb650..c8a88c6 100644
--- a/src/value.cc
+++ b/src/value.cc
@@ -36,6 +36,8 @@
 #include 
 #include "boost-utils.h"
 #include "boosty.h"
+/*Unicode support for string lengths and array accesses*/
+#include 
 
 std::ostream &operator<<(std::ostream &stream, const Filename &filename)
 {
@@ -579,14 +581,28 @@ Value Value::operator-() const
   }
 */
 
+/*
+ * bracket operation [] detecting multi-byte unicode.
+ * If the string is multi-byte unicode then the index will offset to the character (2 or 4 byte) and not to the byte.
+ * A 'normal' string with byte chars are a subset of unicode and still work.
+ */
 class bracket_visitor : public boost::static_visitor
 {
 public:
   Value operator()(const std::string &str, const double &idx) const {
     int i = int(idx);
     Value v;
+    //Check that the index is positive and less than the size in bytes
     if ((i >= 0) && (i < (int)str.size())) {
-      v = Value(str[int(idx)]);
+	  //Ensure character (not byte) index is inside the character/glyph array
+	  if( (unsigned) i < g_utf8_strlen( str.c_str(), str.size() ) )	{
+		  gchar utf8_of_cp[6] = ""; //A buffer for a single unicode character to be copied into
+		  gchar* ptr = g_utf8_offset_to_pointer(str.c_str(), i);
+		  if(ptr) {
+		    g_utf8_strncpy(utf8_of_cp, ptr, 1);
+		  }
+		  v = std::string(utf8_of_cp);
+	  }
       //      std::cout << "bracket_visitor: " <<  v << "\n";
     }
     return v;
diff --git a/testdata/scad/misc/search-tests-unicode.scad b/testdata/scad/misc/search-tests-unicode.scad
new file mode 100644
index 0000000..d863eff
--- /dev/null
+++ b/testdata/scad/misc/search-tests-unicode.scad
@@ -0,0 +1,116 @@
+//Test search with unicode strings
+
+//Helper function that pretty prints our search test
+//Expected result is checked against execution of a search() invocation and OK/FAIL is indicated
+module test_search_and_echo( exp_res, search_to_find, search_to_search, search_up_to_num_matches = undef)
+{
+   if(undef != search_up_to_num_matches)
+   {
+      assign( test_res = search(search_to_find, search_to_search, search_up_to_num_matches) )
+      echo(str("Expect ", exp_res, " for search(", search_to_find, ", ", search_to_search, ", ", search_up_to_num_matches, ")=", test_res, ". ", (exp_res == test_res)?"OK":"FAIL"  ));
+   }
+   else
+   {
+      assign( test_res = search(search_to_find, search_to_search) )
+      echo(str("Expect ", exp_res, " for search(", search_to_find, ", ", search_to_search, ")=", test_res, ". ", (exp_res == test_res)?"OK":"FAIL"  ));
+   }
+}
+
+
+//"Normal" text for comparison
+echo ("----- Lookup of 1 byte into 1 byte");
+//Hits - up_to_count 1
+test_search_and_echo( [0],   "a","aaaa" );
+test_search_and_echo( [0],   "a","aaaa",1 );
+test_search_and_echo( [0,0], "aa","aaaa" );
+test_search_and_echo( [0,0], "aa","aaaa",1 );
+
+
+//Hits - up to count 1+ (incl 0 == all)
+test_search_and_echo( [[0,1,2,3]] , 	"a","aaaa",0 );
+test_search_and_echo( [[0,1]], 			"a","aaaa",2 );
+test_search_and_echo( [[0,1,2]], 		"a","aaaa",3 );
+test_search_and_echo( [[0,1,2,3]] , 	"a","aaaa",4 );
+test_search_and_echo( [[0,1,2,3],[0,1,2,3]] , "aa","aaaa",0 );
+//Misses
+test_search_and_echo( [],		"b","aaaa" );
+test_search_and_echo( [],		"b","aaaa",1 );
+test_search_and_echo( [[]],		"b","aaaa",0 );
+test_search_and_echo( [[]],		"b","aaaa",2 );
+
+test_search_and_echo( [],			"bb","aaaa" );
+test_search_and_echo( [],			"bb","aaaa",1 );
+test_search_and_echo( [[],[]],		"bb","aaaa",0 );
+test_search_and_echo( [[],[]],		"bb","aaaa",2 );
+//Miss - empties
+test_search_and_echo( [], "","aaaa" );
+test_search_and_echo( [], "","" );
+test_search_and_echo( [], "a","" );
+
+
+//Unicode tests
+echo ("----- Lookup of multi-byte into 1 byte");
+test_search_and_echo( [],		"Π","aaaa" );
+test_search_and_echo( [],		"π‘","aaaa" );
+test_search_and_echo( [[]],		"Π","aaaa",0 );
+test_search_and_echo( [[]],		"π‘","aaaa",0 );
+
+test_search_and_echo( [],		"ΠΠ","aaaa" );
+test_search_and_echo( [],		"π‘π‘","aaaa" );
+test_search_and_echo( [[],[]],		"ΠΠ","aaaa",0 );
+test_search_and_echo( [[],[]],		"π‘π‘","aaaa",0 );
+
+echo ("----- Lookup of 1-byte into multi-byte");
+test_search_and_echo( [] , "a","ΠΠΠΠ" );
+test_search_and_echo( [] , "a","π‘π‘π‘π‘" );
+test_search_and_echo( [] , "a","ΠΠΠΠ",1 );
+
+test_search_and_echo( [[]] , "a","π‘π‘π‘π‘",0 );
+test_search_and_echo( [[]] , "a","π‘π‘π‘π‘",2 );
+
+echo ("----- Lookup of 1-byte into mixed multi-byte");
+test_search_and_echo( [0], "a","aΠaΠaΠaΠa" );
+test_search_and_echo( [0], "a","aπ‘aπ‘aπ‘aπ‘a" );
+test_search_and_echo( [0], "a","aπ‘Ππ‘aπ‘Ππ‘a" );
+
+test_search_and_echo( [[0,2,4,6,8]], "a","aΠaΠaΠaΠa",0 );
+test_search_and_echo( [[0,2,4,6,8]], "a","aπ‘aπ‘aπ‘aπ‘a", 0 );
+test_search_and_echo( [[0,4,8]]    , "a","aπ‘Ππ‘aπ‘Ππ‘a", 0 );
+
+echo ("----- Lookup of 2-byte into 2-byte");
+test_search_and_echo( [0]       , "Π","ΠΠΠΠ" );
+test_search_and_echo( [[0,1,2,3]] , "Π","ΠΠΠΠ",0 );
+
+echo ("----- Lookup of 2-byte into 4-byte");
+test_search_and_echo( [] , "Π","π‘π‘π‘π‘" );
+
+echo ("----- Lookup of 4-byte into 4-byte");
+test_search_and_echo( [0] , 		  "π‘","π‘π‘π‘π‘" );
+test_search_and_echo( [[0,1,2,3]], "π‘","π‘π‘π‘π‘",0 );
+
+echo ("----- Lookup of 4-byte into 2-byte");
+test_search_and_echo( [] , "π‘","ΠΠΠΠ" );
+
+echo ("----- Lookup of 2-byte into mixed multi-byte");
+test_search_and_echo( [1] , 	"Π","aΠaΠaΠaΠa",1 );
+test_search_and_echo( [] , 	"Π","aπ‘aπ‘aπ‘aπ‘a", 1 );
+test_search_and_echo( [2] , 	"Π","aπ‘Ππ‘aπ‘Ππ‘a", 1 );
+
+test_search_and_echo( [[1,3,5,7]] , 	"Π","aΠaΠaΠaΠa",0 );
+test_search_and_echo( [[]] , 				"Π","aπ‘aπ‘aπ‘aπ‘a", 0 );
+test_search_and_echo( [[2,6]] , 			"Π","aπ‘Ππ‘aπ‘Ππ‘a", 0 );
+
+echo ("----- Lookup of 4-byte into mixed multi-byte");
+test_search_and_echo( [] , 			"π‘","aΠaΠaΠaΠa",1 );
+test_search_and_echo( [1] , "π‘","aπ‘aπ‘aπ‘aπ‘a", 1 );
+
+test_search_and_echo( [[]] , 			"π‘","aΠaΠaΠaΠa",0 );
+test_search_and_echo( [[1,3,5,7]] , "π‘","aπ‘aπ‘aπ‘aπ‘a", 0 );
+test_search_and_echo( [[1,3,5,7]] , "π‘","aπ‘Ππ‘aπ‘Ππ‘a", 0 );
+
+echo ("----- Lookup of mixed multi-byte into mixed multi-byte");
+test_search_and_echo( [[0,2,4,6,8],[1,3,5,7],[]], "aΠπ‘","aΠaΠaΠaΠa",0 );
+test_search_and_echo( [[0,2,4,6,8],[],[1,3,5,7]], "aΠπ‘","aπ‘aπ‘aπ‘aπ‘a", 0 );
+test_search_and_echo( [[0,4,8],[2,6],[1,3,5,7]]    , "aΠπ‘","aπ‘Ππ‘aπ‘Ππ‘a", 0 );
+test_search_and_echo( [[1,3,5,7],[0,4,8],[2,6]]    , "π‘aΠ","aπ‘Ππ‘aπ‘Ππ‘a", 0 );
+
diff --git a/testdata/scad/misc/string-unicode.scad b/testdata/scad/misc/string-unicode.scad
new file mode 100644
index 0000000..d8e3e5c
--- /dev/null
+++ b/testdata/scad/misc/string-unicode.scad
@@ -0,0 +1,36 @@
+//Test how well arrays of unicode string are accessed.
+
+texts_array = [
+"DEADBEEF",
+"ΠΠ΅Π½ΠΈΠ²ΡΠΉ ΡΡΠΆΠΈΠΉ ΠΊΠΎΡ",
+"ΩΨ³ΩΩ Ψ§ΩΨ²ΩΨ¬Ψ¨ΩΩ Ψ§ΩΩΨ·",
+"ζΆζ°ηε§θ²",
+"Àâü ΓΓΓ Γ",
+"πππππ
πππππππππππ",
+"β β β β β 
β β β β β β β β β β ",
+"π‘π±ππ",
+];
+
+text_2bytes = "ΠΠ΅Π½ΠΈΠ²ΡΠΉ ΡΡΠΆΠΈΠΉ ΠΊΠΎΡ";
+text_4bytes = "π‘π±ππ";
+
+
+//Test all the normal accesses
+for (text_array_idx = [0:(len(texts_array)-1)])
+{
+	echo( "[", text_array_idx, "] = ", texts_array[text_array_idx], " of len=", len(texts_array[text_array_idx]), ":"  );
+    for (text_idx = [0:(len(texts_array[text_array_idx])-1)])
+    {
+	    echo( "    [", text_idx, ,"]=", texts_array[text_array_idx][text_idx]  );
+    }
+}
+
+//Test one past the last element of (x-byte unicode). This will be one past the length but inside the char length of the string
+echo( "Past end of unicode only 2-byte ", text_2bytes[len(text_2bytes)]  );
+echo( "Past end of unicode only 4-byte ", text_4bytes[len(text_4bytes)]  );
+
+//Test past the last element of (x-byte unicode). Outside both lengths.
+echo( "Past end of both 2-byte ", text_2bytes[ len(text_2bytes) * 2 ]   );
+echo( "Past end of both 4-byte ", text_4bytes[ len(text_4bytes) * 4 ]   );
+
+
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index d7ad18a..3c19b77 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -594,8 +594,8 @@ set(OFFSCREEN_SOURCES
   ../src/OpenCSGRenderer.cc)
 
 add_library(tests-core STATIC ${CORE_SOURCES})
-target_link_libraries(tests-core ${OPENGL_LIBRARIES})
-set(TESTS-CORE-LIBRARIES ${OPENGL_LIBRARIES} ${Boost_LIBRARIES})
+target_link_libraries(tests-core ${OPENGL_LIBRARIES} ${GLIB2_LIBRARIES} )
+set(TESTS-CORE-LIBRARIES ${OPENGL_LIBRARIES} ${GLIB2_LIBRARIES} ${Boost_LIBRARIES} )
 
 add_library(tests-common STATIC ${COMMON_SOURCES})
 target_link_libraries(tests-common tests-core)
@@ -815,8 +815,10 @@ list(APPEND ECHO_FILES ${FUNCTION_FILES}
             ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/dim-all.scad
             ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/string-test.scad
             ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/string-indexing.scad
+            ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/string-unicode.scad
             ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/vector-values.scad
             ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/search-tests.scad
+            ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/search-tests-unicode.scad
             ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/recursion-tests.scad
             ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/value-reassignment-tests.scad
             ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/value-reassignment-tests2.scad
diff --git a/tests/regression/echotest/search-tests-unicode-expected.echo b/tests/regression/echotest/search-tests-unicode-expected.echo
new file mode 100644
index 0000000..801bc8c
--- /dev/null
+++ b/tests/regression/echotest/search-tests-unicode-expected.echo
@@ -0,0 +1,109 @@
+ECHO: "----- Lookup of 1 byte into 1 byte"
+ECHO: "Expect [0] for search(a, aaaa)=[0]. OK"
+ECHO: "Expect [0] for search(a, aaaa, 1)=[0]. OK"
+ECHO: "Expect [0, 0] for search(aa, aaaa)=[0, 0]. OK"
+ECHO: "Expect [0, 0] for search(aa, aaaa, 1)=[0, 0]. OK"
+ECHO: "Expect [[0, 1, 2, 3]] for search(a, aaaa, 0)=[[0, 1, 2, 3]]. OK"
+ECHO: "Expect [[0, 1]] for search(a, aaaa, 2)=[[0, 1]]. OK"
+ECHO: "Expect [[0, 1, 2]] for search(a, aaaa, 3)=[[0, 1, 2]]. OK"
+ECHO: "Expect [[0, 1, 2, 3]] for search(a, aaaa, 4)=[[0, 1, 2, 3]]. OK"
+ECHO: "Expect [[0, 1, 2, 3], [0, 1, 2, 3]] for search(aa, aaaa, 0)=[[0, 1, 2, 3], [0, 1, 2, 3]]. OK"
+  WARNING: search term not found: "b"
+ECHO: "Expect [] for search(b, aaaa)=[]. OK"
+  WARNING: search term not found: "b"
+ECHO: "Expect [] for search(b, aaaa, 1)=[]. OK"
+  WARNING: search term not found: "b"
+ECHO: "Expect [[]] for search(b, aaaa, 0)=[[]]. OK"
+  WARNING: search term not found: "b"
+ECHO: "Expect [[]] for search(b, aaaa, 2)=[[]]. OK"
+  WARNING: search term not found: "b"
+  WARNING: search term not found: "b"
+ECHO: "Expect [] for search(bb, aaaa)=[]. OK"
+  WARNING: search term not found: "b"
+  WARNING: search term not found: "b"
+ECHO: "Expect [] for search(bb, aaaa, 1)=[]. OK"
+  WARNING: search term not found: "b"
+  WARNING: search term not found: "b"
+ECHO: "Expect [[], []] for search(bb, aaaa, 0)=[[], []]. OK"
+  WARNING: search term not found: "b"
+  WARNING: search term not found: "b"
+ECHO: "Expect [[], []] for search(bb, aaaa, 2)=[[], []]. OK"
+ECHO: "Expect [] for search(, aaaa)=[]. OK"
+ECHO: "Expect [] for search(, )=[]. OK"
+  WARNING: search term not found: "a"
+ECHO: "Expect [] for search(a, )=[]. OK"
+ECHO: "----- Lookup of multi-byte into 1 byte"
+  WARNING: search term not found: "Π"
+ECHO: "Expect [] for search(Π, aaaa)=[]. OK"
+  WARNING: search term not found: "π‘"
+ECHO: "Expect [] for search(π‘, aaaa)=[]. OK"
+  WARNING: search term not found: "Π"
+ECHO: "Expect [[]] for search(Π, aaaa, 0)=[[]]. OK"
+  WARNING: search term not found: "π‘"
+ECHO: "Expect [[]] for search(π‘, aaaa, 0)=[[]]. OK"
+  WARNING: search term not found: "Π"
+  WARNING: search term not found: "Π"
+ECHO: "Expect [] for search(ΠΠ, aaaa)=[]. OK"
+  WARNING: search term not found: "π‘"
+  WARNING: search term not found: "π‘"
+ECHO: "Expect [] for search(π‘π‘, aaaa)=[]. OK"
+  WARNING: search term not found: "Π"
+  WARNING: search term not found: "Π"
+ECHO: "Expect [[], []] for search(ΠΠ, aaaa, 0)=[[], []]. OK"
+  WARNING: search term not found: "π‘"
+  WARNING: search term not found: "π‘"
+ECHO: "Expect [[], []] for search(π‘π‘, aaaa, 0)=[[], []]. OK"
+ECHO: "----- Lookup of 1-byte into multi-byte"
+  WARNING: search term not found: "a"
+ECHO: "Expect [] for search(a, ΠΠΠΠ)=[]. OK"
+  WARNING: search term not found: "a"
+ECHO: "Expect [] for search(a, π‘π‘π‘π‘)=[]. OK"
+  WARNING: search term not found: "a"
+ECHO: "Expect [] for search(a, ΠΠΠΠ, 1)=[]. OK"
+  WARNING: search term not found: "a"
+ECHO: "Expect [[]] for search(a, π‘π‘π‘π‘, 0)=[[]]. OK"
+  WARNING: search term not found: "a"
+ECHO: "Expect [[]] for search(a, π‘π‘π‘π‘, 2)=[[]]. OK"
+ECHO: "----- Lookup of 1-byte into mixed multi-byte"
+ECHO: "Expect [0] for search(a, aΠaΠaΠaΠa)=[0]. OK"
+ECHO: "Expect [0] for search(a, aπ‘aπ‘aπ‘aπ‘a)=[0]. OK"
+ECHO: "Expect [0] for search(a, aπ‘Ππ‘aπ‘Ππ‘a)=[0]. OK"
+ECHO: "Expect [[0, 2, 4, 6, 8]] for search(a, aΠaΠaΠaΠa, 0)=[[0, 2, 4, 6, 8]]. OK"
+ECHO: "Expect [[0, 2, 4, 6, 8]] for search(a, aπ‘aπ‘aπ‘aπ‘a, 0)=[[0, 2, 4, 6, 8]]. OK"
+ECHO: "Expect [[0, 4, 8]] for search(a, aπ‘Ππ‘aπ‘Ππ‘a, 0)=[[0, 4, 8]]. OK"
+ECHO: "----- Lookup of 2-byte into 2-byte"
+ECHO: "Expect [0] for search(Π, ΠΠΠΠ)=[0]. OK"
+ECHO: "Expect [[0, 1, 2, 3]] for search(Π, ΠΠΠΠ, 0)=[[0, 1, 2, 3]]. OK"
+ECHO: "----- Lookup of 2-byte into 4-byte"
+  WARNING: search term not found: "Π"
+ECHO: "Expect [] for search(Π, π‘π‘π‘π‘)=[]. OK"
+ECHO: "----- Lookup of 4-byte into 4-byte"
+ECHO: "Expect [0] for search(π‘, π‘π‘π‘π‘)=[0]. OK"
+ECHO: "Expect [[0, 1, 2, 3]] for search(π‘, π‘π‘π‘π‘, 0)=[[0, 1, 2, 3]]. OK"
+ECHO: "----- Lookup of 4-byte into 2-byte"
+  WARNING: search term not found: "π‘"
+ECHO: "Expect [] for search(π‘, ΠΠΠΠ)=[]. OK"
+ECHO: "----- Lookup of 2-byte into mixed multi-byte"
+ECHO: "Expect [1] for search(Π, aΠaΠaΠaΠa, 1)=[1]. OK"
+  WARNING: search term not found: "Π"
+ECHO: "Expect [] for search(Π, aπ‘aπ‘aπ‘aπ‘a, 1)=[]. OK"
+ECHO: "Expect [2] for search(Π, aπ‘Ππ‘aπ‘Ππ‘a, 1)=[2]. OK"
+ECHO: "Expect [[1, 3, 5, 7]] for search(Π, aΠaΠaΠaΠa, 0)=[[1, 3, 5, 7]]. OK"
+  WARNING: search term not found: "Π"
+ECHO: "Expect [[]] for search(Π, aπ‘aπ‘aπ‘aπ‘a, 0)=[[]]. OK"
+ECHO: "Expect [[2, 6]] for search(Π, aπ‘Ππ‘aπ‘Ππ‘a, 0)=[[2, 6]]. OK"
+ECHO: "----- Lookup of 4-byte into mixed multi-byte"
+  WARNING: search term not found: "π‘"
+ECHO: "Expect [] for search(π‘, aΠaΠaΠaΠa, 1)=[]. OK"
+ECHO: "Expect [1] for search(π‘, aπ‘aπ‘aπ‘aπ‘a, 1)=[1]. OK"
+  WARNING: search term not found: "π‘"
+ECHO: "Expect [[]] for search(π‘, aΠaΠaΠaΠa, 0)=[[]]. OK"
+ECHO: "Expect [[1, 3, 5, 7]] for search(π‘, aπ‘aπ‘aπ‘aπ‘a, 0)=[[1, 3, 5, 7]]. OK"
+ECHO: "Expect [[1, 3, 5, 7]] for search(π‘, aπ‘Ππ‘aπ‘Ππ‘a, 0)=[[1, 3, 5, 7]]. OK"
+ECHO: "----- Lookup of mixed multi-byte into mixed multi-byte"
+  WARNING: search term not found: "π‘"
+ECHO: "Expect [[0, 2, 4, 6, 8], [1, 3, 5, 7], []] for search(aΠπ‘, aΠaΠaΠaΠa, 0)=[[0, 2, 4, 6, 8], [1, 3, 5, 7], []]. OK"
+  WARNING: search term not found: "Π"
+ECHO: "Expect [[0, 2, 4, 6, 8], [], [1, 3, 5, 7]] for search(aΠπ‘, aπ‘aπ‘aπ‘aπ‘a, 0)=[[0, 2, 4, 6, 8], [], [1, 3, 5, 7]]. OK"
+ECHO: "Expect [[0, 4, 8], [2, 6], [1, 3, 5, 7]] for search(aΠπ‘, aπ‘Ππ‘aπ‘Ππ‘a, 0)=[[0, 4, 8], [2, 6], [1, 3, 5, 7]]. OK"
+ECHO: "Expect [[1, 3, 5, 7], [0, 4, 8], [2, 6]] for search(π‘aΠ, aπ‘Ππ‘aπ‘Ππ‘a, 0)=[[1, 3, 5, 7], [0, 4, 8], [2, 6]]. OK"
diff --git a/tests/regression/echotest/string-unicode-expected.echo b/tests/regression/echotest/string-unicode-expected.echo
new file mode 100644
index 0000000..b4b848f
--- /dev/null
+++ b/tests/regression/echotest/string-unicode-expected.echo
@@ -0,0 +1,104 @@
+ECHO: "[", 0, "] = ", "DEADBEEF", " of len=", 8, ":"
+ECHO: "    [", 0, "]=", "D"
+ECHO: "    [", 1, "]=", "E"
+ECHO: "    [", 2, "]=", "A"
+ECHO: "    [", 3, "]=", "D"
+ECHO: "    [", 4, "]=", "B"
+ECHO: "    [", 5, "]=", "E"
+ECHO: "    [", 6, "]=", "E"
+ECHO: "    [", 7, "]=", "F"
+ECHO: "[", 1, "] = ", "ΠΠ΅Π½ΠΈΠ²ΡΠΉ ΡΡΠΆΠΈΠΉ ΠΊΠΎΡ", " of len=", 17, ":"
+ECHO: "    [", 0, "]=", "Π"
+ECHO: "    [", 1, "]=", "Π΅"
+ECHO: "    [", 2, "]=", "Π½"
+ECHO: "    [", 3, "]=", "ΠΈ"
+ECHO: "    [", 4, "]=", "Π²"
+ECHO: "    [", 5, "]=", "Ρ"
+ECHO: "    [", 6, "]=", "ΠΉ"
+ECHO: "    [", 7, "]=", " "
+ECHO: "    [", 8, "]=", "Ρ"
+ECHO: "    [", 9, "]=", "Ρ"
+ECHO: "    [", 10, "]=", "ΠΆ"
+ECHO: "    [", 11, "]=", "ΠΈ"
+ECHO: "    [", 12, "]=", "ΠΉ"
+ECHO: "    [", 13, "]=", " "
+ECHO: "    [", 14, "]=", "ΠΊ"
+ECHO: "    [", 15, "]=", "ΠΎ"
+ECHO: "    [", 16, "]=", "Ρ"
+ECHO: "[", 2, "] = ", "ΩΨ³ΩΩ Ψ§ΩΨ²ΩΨ¬Ψ¨ΩΩ Ψ§ΩΩΨ·", " of len=", 18, ":"
+ECHO: "    [", 0, "]=", "Ω"
+ECHO: "    [", 1, "]=", "Ψ³"
+ECHO: "    [", 2, "]=", "Ω"
+ECHO: "    [", 3, "]=", "Ω"
+ECHO: "    [", 4, "]=", " "
+ECHO: "    [", 5, "]=", "Ψ§"
+ECHO: "    [", 6, "]=", "Ω"
+ECHO: "    [", 7, "]=", "Ψ²"
+ECHO: "    [", 8, "]=", "Ω"
+ECHO: "    [", 9, "]=", "Ψ¬"
+ECHO: "    [", 10, "]=", "Ψ¨"
+ECHO: "    [", 11, "]=", "Ω"
+ECHO: "    [", 12, "]=", "Ω"
+ECHO: "    [", 13, "]=", " "
+ECHO: "    [", 14, "]=", "Ψ§"
+ECHO: "    [", 15, "]=", "Ω"
+ECHO: "    [", 16, "]=", "Ω"
+ECHO: "    [", 17, "]=", "Ψ·"
+ECHO: "[", 3, "] = ", "ζΆζ°ηε§θ²", " of len=", 5, ":"
+ECHO: "    [", 0, "]=", "ζΆ"
+ECHO: "    [", 1, "]=", "ζ°"
+ECHO: "    [", 2, "]=", "η"
+ECHO: "    [", 3, "]=", "ε§"
+ECHO: "    [", 4, "]=", "θ²"
+ECHO: "[", 4, "] = ", "Àâü ΓΓΓ Γ", " of len=", 9, ":"
+ECHO: "    [", 0, "]=", "Γ€"
+ECHO: "    [", 1, "]=", "ΓΆ"
+ECHO: "    [", 2, "]=", "ΓΌ"
+ECHO: "    [", 3, "]=", " "
+ECHO: "    [", 4, "]=", "Γ"
+ECHO: "    [", 5, "]=", "Γ"
+ECHO: "    [", 6, "]=", "Γ"
+ECHO: "    [", 7, "]=", " "
+ECHO: "    [", 8, "]=", "Γ"
+ECHO: "[", 5, "] = ", "πππππ
πππππππππππ", " of len=", 16, ":"
+ECHO: "    [", 0, "]=", "π"
+ECHO: "    [", 1, "]=", "π"
+ECHO: "    [", 2, "]=", "π"
+ECHO: "    [", 3, "]=", "π"
+ECHO: "    [", 4, "]=", "π
"
+ECHO: "    [", 5, "]=", "π"
+ECHO: "    [", 6, "]=", "π"
+ECHO: "    [", 7, "]=", "π"
+ECHO: "    [", 8, "]=", "π"
+ECHO: "    [", 9, "]=", "π"
+ECHO: "    [", 10, "]=", "π"
+ECHO: "    [", 11, "]=", "π"
+ECHO: "    [", 12, "]=", "π"
+ECHO: "    [", 13, "]=", "π"
+ECHO: "    [", 14, "]=", "π"
+ECHO: "    [", 15, "]=", "π"
+ECHO: "[", 6, "] = ", "β β β β β 
β β β β β β β β β β ", " of len=", 15, ":"
+ECHO: "    [", 0, "]=", "β "
+ECHO: "    [", 1, "]=", "β "
+ECHO: "    [", 2, "]=", "β "
+ECHO: "    [", 3, "]=", "β "
+ECHO: "    [", 4, "]=", "β 
"
+ECHO: "    [", 5, "]=", "β "
+ECHO: "    [", 6, "]=", "β "
+ECHO: "    [", 7, "]=", "β "
+ECHO: "    [", 8, "]=", "β "
+ECHO: "    [", 9, "]=", "β "
+ECHO: "    [", 10, "]=", "β "
+ECHO: "    [", 11, "]=", "β "
+ECHO: "    [", 12, "]=", "β "
+ECHO: "    [", 13, "]=", "β "
+ECHO: "    [", 14, "]=", "β "
+ECHO: "[", 7, "] = ", "π‘π±ππ", " of len=", 4, ":"
+ECHO: "    [", 0, "]=", "π‘"
+ECHO: "    [", 1, "]=", "π±"
+ECHO: "    [", 2, "]=", "π"
+ECHO: "    [", 3, "]=", "π"
+ECHO: "Past end of unicode only 2-byte ", undef
+ECHO: "Past end of unicode only 4-byte ", undef
+ECHO: "Past end of both 2-byte ", undef
+ECHO: "Past end of both 4-byte ", undef
-- 
cgit v0.10.1
From c0849eb1d3c98db505eec0396c56276a9a35120f Mon Sep 17 00:00:00 2001
From: Brody Kenrick 
Date: Fri, 6 Dec 2013 09:56:22 +1100
Subject: Update comments/messages for CGAL source of bad boost libraries
Add comments and change to a status instead of a warning (as we recover
nicely and it is a known issue in CGAL @
https://bugs.launchpad.net/ubuntu/+source/cgal/+bug/1242111)
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 3c19b77..2533103 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -383,23 +383,24 @@ if("${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}" VERSION_LESS 3.6)
   message(FATAL_ERROR "CGAL >= 3.6 required")
 endif()
 inclusion(CGAL_DIR CGAL_INCLUDE_DIRS)
-
-#Get rid of bad libraries suggested for BOOST dependencies (they don't exist on some machines and cause build failures).
-#/usr/lib/libboost_thread.so;/usr/lib/libboost_system.so;
+#Remove bad BOOST libraries from CGAL 3rd party dependencies when they don't exist (such as on 64-bit Ubuntu 13.10).
+#Libs of concern are /usr/lib/libboost_thread.so;/usr/lib/libboost_system.so;
+#Confirmed bug in CGAL @ https://bugs.launchpad.net/ubuntu/+source/cgal/+bug/1242111
 string(FIND "${CGAL_3RD_PARTY_LIBRARIES}" "/usr/lib/libboost_system.so" FIND_POSITION  )
 if(NOT "-1" STREQUAL ${FIND_POSITION} )
-if(NOT EXISTS "/usr/lib/libboost_system.so")
-  MESSAGE( WARNING "CGAL_3RD_PARTY_LIBRARIES:Found erroneous /usr/lib/libboost_system.so -- stripping" )
-  string(REPLACE "/usr/lib/libboost_system.so" "" CGAL_3RD_PARTY_LIBRARIES ${CGAL_3RD_PARTY_LIBRARIES})
-endif()
+  if(NOT EXISTS "/usr/lib/libboost_system.so")
+    MESSAGE( STATUS "CGAL_3RD_PARTY_LIBRARIES:Removing non-existent /usr/lib/libboost_system.so" )
+    string(REPLACE "/usr/lib/libboost_system.so" "" CGAL_3RD_PARTY_LIBRARIES ${CGAL_3RD_PARTY_LIBRARIES})
+  endif()
 endif() 
 string(FIND "${CGAL_3RD_PARTY_LIBRARIES}" "/usr/lib/libboost_thread.so" FIND_POSITION  )
 if(NOT "-1" STREQUAL ${FIND_POSITION} )
-if(NOT EXISTS "/usr/lib/libboost_thread.so")
-  MESSAGE( WARNING "CGAL_3RD_PARTY_LIBRARIES:Found erroneous /usr/lib/libboost_thread.so -- stripping" )
-  string(REPLACE "/usr/lib/libboost_thread.so" "" CGAL_3RD_PARTY_LIBRARIES ${CGAL_3RD_PARTY_LIBRARIES})
-endif()
+  if(NOT EXISTS "/usr/lib/libboost_thread.so")
+    MESSAGE( STATUS "CGAL_3RD_PARTY_LIBRARIES:Removing non-existent /usr/lib/libboost_thread.so" )
+    string(REPLACE "/usr/lib/libboost_thread.so" "" CGAL_3RD_PARTY_LIBRARIES ${CGAL_3RD_PARTY_LIBRARIES})
+  endif()
 endif() 
+
 if(${CMAKE_CXX_COMPILER} MATCHES ".*clang.*" AND NOT ${CGAL_CXX_FLAGS_INIT} STREQUAL "" )
 	string(REPLACE "-frounding-math" "" CGAL_CXX_FLAGS_INIT ${CGAL_CXX_FLAGS_INIT})
 	string(REPLACE "--param=ssp-buffer-size=4" "" CGAL_CXX_FLAGS_INIT ${CGAL_CXX_FLAGS_INIT})
-- 
cgit v0.10.1
From d2575016b989b9cee5b44c29f10a76d84a7bf182 Mon Sep 17 00:00:00 2001
From: Brody Kenrick 
Date: Fri, 6 Dec 2013 17:46:52 +1100
Subject: Add in missed glib build dependencies for OS X and unix
diff --git a/scripts/macosx-build-dependencies.sh b/scripts/macosx-build-dependencies.sh
index d4ca1f7..5e26fee 100755
--- a/scripts/macosx-build-dependencies.sh
+++ b/scripts/macosx-build-dependencies.sh
@@ -285,6 +285,30 @@ build_glew()
   make GLEW_DEST=$DEPLOYDIR CC=$CC CFLAGS.EXTRA="-no-cpp-precomp -dynamic -fno-common -mmacosx-version-min=$MAC_OSX_VERSION_MIN $GLEW_EXTRA_FLAGS -arch x86_64" LDFLAGS.EXTRA="-mmacosx-version-min=$MAC_OSX_VERSION_MIN $GLEW_EXTRA_FLAGS -arch x86_64" STRIP= install
 }
 
+build_glib2()
+{
+  version="$1"
+  maj_min_version="${version%.*}" #Drop micro
+
+  if [ -e $DEPLOYDIR/lib/glib-2.0 ]; then
+    echo "glib2 already installed. not building"
+    return
+  fi
+
+   echo "Building glib2 $version..."
+  cd "$BASEDIR"/src
+  rm -rf "glib-$version"
+  if [ ! -f "glib-$version.tar.xz" ]; then
+    curl --insecure -LO "http://ftp.gnome.org/pub/gnome/sources/glib/$maj_min_version/glib-$version.tar.xz"
+  fi
+  tar xJf "glib-$version.tar.xz"
+  cd "glib-$version"
+
+  ./configure --prefix="$DEPLOYDIR"
+  make -j$NUMCPU
+  make install
+}
+
 build_opencsg()
 {
   version=$1
@@ -449,6 +473,7 @@ build_boost 1.54.0
 # NB! For CGAL, also update the actual download URL in the function
 build_cgal 4.3
 build_glew 1.10.0
+build_glib2 2.38.1
 build_opencsg 1.3.2
 if $OPTION_DEPLOY; then
 #  build_sparkle andymatuschak 0ed83cf9f2eeb425d4fdd141c01a29d843970c20
diff --git a/scripts/uni-build-dependencies.sh b/scripts/uni-build-dependencies.sh
index 8d912c3..ba328b7 100755
--- a/scripts/uni-build-dependencies.sh
+++ b/scripts/uni-build-dependencies.sh
@@ -409,6 +409,31 @@ build_glew()
   GLEW_DEST=$DEPLOYDIR $MAKER install
 }
 
+build_glib2()
+{
+  version="$1"
+  maj_min_version="${version%.*}" #Drop micro
+
+  if [ -e $DEPLOYDIR/lib/glib-2.0 ]; then
+echo "glib2 already installed. not building"
+    return
+fi
+
+echo "Building glib2 $version..."
+  cd "$BASEDIR"/src
+  rm -rf "glib-$version"
+  if [ ! -f "glib-$version.tar.xz" ]; then
+curl --insecure -LO "http://ftp.gnome.org/pub/gnome/sources/glib/$maj_min_version/glib-$version.tar.xz"
+  fi
+tar xJf "glib-$version.tar.xz"
+  cd "glib-$version"
+
+  ./configure --prefix="$DEPLOYDIR"
+  make -j$NUMCPU
+  make install
+   
+}
+
 build_opencsg()
 {
   if [ -e $DEPLOYDIR/lib/libopencsg.so ]; then
-- 
cgit v0.10.1
From d46ce3fb8150fe01c0c07fac11ea2e9a8ed97038 Mon Sep 17 00:00:00 2001
From: Brody Kenrick 
Date: Fri, 6 Dec 2013 18:33:42 +1100
Subject: Add specific tests for unicode len()
diff --git a/testdata/scad/misc/string-unicode.scad b/testdata/scad/misc/string-unicode.scad
index d8e3e5c..1386d63 100644
--- a/testdata/scad/misc/string-unicode.scad
+++ b/testdata/scad/misc/string-unicode.scad
@@ -1,3 +1,12 @@
+//Test length reporting
+text_1bytes_len = "1234";
+text_2bytes_len = "ΠΠΠΠ";
+text_4bytes_len = "π‘π±ππ";
+
+echo( "text_1bytes_len = ", text_1bytes_len, " len = ", len(text_1bytes_len)  );
+echo( "text_2bytes_len = ", text_2bytes_len, " len = ", len(text_2bytes_len)  );
+echo( "text_4bytes_len = ", text_4bytes_len, " len = ", len(text_4bytes_len)  );
+
 //Test how well arrays of unicode string are accessed.
 
 texts_array = [
@@ -33,4 +42,3 @@ echo( "Past end of unicode only 4-byte ", text_4bytes[len(text_4bytes)]  );
 echo( "Past end of both 2-byte ", text_2bytes[ len(text_2bytes) * 2 ]   );
 echo( "Past end of both 4-byte ", text_4bytes[ len(text_4bytes) * 4 ]   );
 
-
diff --git a/tests/regression/echotest/string-unicode-expected.echo b/tests/regression/echotest/string-unicode-expected.echo
index b4b848f..a1cd3be 100644
--- a/tests/regression/echotest/string-unicode-expected.echo
+++ b/tests/regression/echotest/string-unicode-expected.echo
@@ -1,3 +1,6 @@
+ECHO: "text_1bytes_len = ", "1234", " len = ", 4
+ECHO: "text_2bytes_len = ", "ΠΠΠΠ", " len = ", 4
+ECHO: "text_4bytes_len = ", "π‘π±ππ", " len = ", 4
 ECHO: "[", 0, "] = ", "DEADBEEF", " of len=", 8, ":"
 ECHO: "    [", 0, "]=", "D"
 ECHO: "    [", 1, "]=", "E"
-- 
cgit v0.10.1
From 7cb3ea77ff090e136eb4a9536a394b3766908d17 Mon Sep 17 00:00:00 2001
From: Marius Kintel 
Date: Tue, 10 Dec 2013 23:08:04 -0500
Subject: Build glib2 and gettext on Mac, Find macro for glib2
diff --git a/scripts/macosx-build-dependencies.sh b/scripts/macosx-build-dependencies.sh
index 5e26fee..b61c656 100755
--- a/scripts/macosx-build-dependencies.sh
+++ b/scripts/macosx-build-dependencies.sh
@@ -285,27 +285,40 @@ build_glew()
   make GLEW_DEST=$DEPLOYDIR CC=$CC CFLAGS.EXTRA="-no-cpp-precomp -dynamic -fno-common -mmacosx-version-min=$MAC_OSX_VERSION_MIN $GLEW_EXTRA_FLAGS -arch x86_64" LDFLAGS.EXTRA="-mmacosx-version-min=$MAC_OSX_VERSION_MIN $GLEW_EXTRA_FLAGS -arch x86_64" STRIP= install
 }
 
-build_glib2()
+build_gettext()
 {
-  version="$1"
-  maj_min_version="${version%.*}" #Drop micro
+  version=$1
+  echo "Building gettext $version..."
 
-  if [ -e $DEPLOYDIR/lib/glib-2.0 ]; then
-    echo "glib2 already installed. not building"
-    return
+  cd "$BASEDIR"/src
+  rm -rf "gettext-$version"
+  if [ ! -f "glib-$version.tar.xz" ]; then
+    curl --insecure -LO "http://ftpmirror.gnu.org/gettext/gettext-$version.tar.gz"
   fi
+  tar xzf "gettext-$version.tar.gz"
+  cd "gettext-$version"
+
+  ./configure --prefix="$DEPLOYDIR"
+  make -j4
+  make install
+}
+
+build_glib2()
+{
+  version=$1
+  echo "Building glib2 $version..."
 
-   echo "Building glib2 $version..."
   cd "$BASEDIR"/src
   rm -rf "glib-$version"
+  maj_min_version="${version%.*}" #Drop micro
   if [ ! -f "glib-$version.tar.xz" ]; then
     curl --insecure -LO "http://ftp.gnome.org/pub/gnome/sources/glib/$maj_min_version/glib-$version.tar.xz"
   fi
   tar xJf "glib-$version.tar.xz"
   cd "glib-$version"
 
-  ./configure --prefix="$DEPLOYDIR"
-  make -j$NUMCPU
+  ./configure --disable-gtk-doc --disable-man --prefix="$DEPLOYDIR" CFLAGS="-I$DEPLOYDIR/include" LDFLAGS="-L$DEPLOYDIR/lib"
+  make -j4
   make install
 }
 
@@ -473,7 +486,8 @@ build_boost 1.54.0
 # NB! For CGAL, also update the actual download URL in the function
 build_cgal 4.3
 build_glew 1.10.0
-build_glib2 2.38.1
+build_gettext 0.18.3.1
+build_glib2 2.38.2
 build_opencsg 1.3.2
 if $OPTION_DEPLOY; then
 #  build_sparkle andymatuschak 0ed83cf9f2eeb425d4fdd141c01a29d843970c20
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 2533103..e590070 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -366,10 +366,10 @@ if (NOT $ENV{CGALDIR} STREQUAL "")
 elseif (NOT $ENV{OPENSCAD_LIBRARIES} STREQUAL "")
   if (EXISTS "$ENV{OPENSCAD_LIBRARIES}/lib/CGAL")
     set(CGAL_DIR "$ENV{OPENSCAD_LIBRARIES}/lib/CGAL")
-    set(CMAKE_MODULE_PATH "${CGAL_DIR}")
+    set(CMAKE_MODULE_PATH "${CGAL_DIR}" ${CMAKE_MODULE_PATH})
   elseif (EXISTS "$ENV{OPENSCAD_LIBRARIES}/include/CGAL")
     set(CGAL_DIR "$ENV{OPENSCAD_LIBRARIES}")
-    set(CMAKE_MODULE_PATH "${CGAL_DIR}")
+    set(CMAKE_MODULE_PATH "${CGAL_DIR}" ${CMAKE_MODULE_PATH})
   endif()
 endif()
 message(STATUS "CGAL_DIR: " ${CGAL_DIR})
@@ -413,16 +413,9 @@ if (NOT $ENV{OPENSCAD_LIBRARIES} STREQUAL "")
   set(ENV{PKG_CONFIG_LIBDIR} "$ENV{OPENSCAD_LIBRARIES}/lib/pkgconfig")
 endif()
 
-# Find libraries (system installed or dependency built) using pkg-config
-find_package(PkgConfig REQUIRED)
-
-#GLib-2
-pkg_search_module(GLIB2 REQUIRED glib-2.0>=2.2.0)
-#Can't use the CXXFlags directly as they are ;-separated
-string(REPLACE ";" " " GLIB2_CFLAGS "${GLIB2_CFLAGS}")
-message(STATUS "glib-2.0 found: ${GLIB2_VERSION}")
-
-add_definitions(${GLIB2_CFLAGS})
+find_package(GLIB2 2.2.0 REQUIRED)
+add_definitions(${GLIB2_DEFINITIONS})
+inclusion(GLIB2_DIR GLIB2_INCLUDE_DIRS)
 
 # Imagemagick
 
@@ -595,7 +588,7 @@ set(OFFSCREEN_SOURCES
   ../src/OpenCSGRenderer.cc)
 
 add_library(tests-core STATIC ${CORE_SOURCES})
-target_link_libraries(tests-core ${OPENGL_LIBRARIES} ${GLIB2_LIBRARIES} )
+target_link_libraries(tests-core)
 set(TESTS-CORE-LIBRARIES ${OPENGL_LIBRARIES} ${GLIB2_LIBRARIES} ${Boost_LIBRARIES} )
 
 add_library(tests-common STATIC ${COMMON_SOURCES})
@@ -616,7 +609,7 @@ set(TESTS-NOCGAL-LIBRARIES ${TESTS-CORE-LIBRARIES})
 # modulecachetest
 #
 add_executable(modulecachetest modulecachetest.cc)
-target_link_libraries(modulecachetest tests-nocgal ${TESTS-NOCGAL-LIBRARIES} ${Boost_LIBRARIES})
+target_link_libraries(modulecachetest tests-nocgal ${TESTS-NOCGAL-LIBRARIES})
 
 #
 # csgtexttest
@@ -636,7 +629,7 @@ target_link_libraries(cgalcachetest tests-cgal ${TESTS-CGAL-LIBRARIES} ${GLEW_LI
 #
 add_executable(openscad_nogui ../src/openscad.cc)
 set_target_properties(openscad_nogui PROPERTIES COMPILE_FLAGS "-fno-strict-aliasing -DEIGEN_DONT_ALIGN -DENABLE_CGAL -DENABLE_OPENCSG ${CGAL_CXX_FLAGS_INIT}")
-target_link_libraries(openscad_nogui tests-offscreen tests-cgal tests-nocgal ${TESTS-CORE-LIBRARIES} ${TESTS-CGAL-LIBRARIES} ${GLEW_LIBRARY} ${Boost_LIBRARIES} ${OPENCSG_LIBRARY} ${COCOA_LIBRARY} )
+target_link_libraries(openscad_nogui tests-offscreen tests-cgal tests-nocgal ${TESTS-CORE-LIBRARIES} ${TESTS-CGAL-LIBRARIES} ${GLEW_LIBRARY} ${OPENCSG_LIBRARY} ${COCOA_LIBRARY} )
 
 #
 # GUI binary tests
diff --git a/tests/FindGLIB2.cmake b/tests/FindGLIB2.cmake
new file mode 100644
index 0000000..b27b9a9
--- /dev/null
+++ b/tests/FindGLIB2.cmake
@@ -0,0 +1,27 @@
+find_package(PkgConfig REQUIRED)
+
+pkg_search_module(GLIB2 REQUIRED glib-2.0)
+#message("GLIB2_LIBRARIES ${GLIB2_LIBRARIES}")
+#message("GLIB2_LIBRARY_DIRS ${GLIB2_LIBRARY_DIRS}")
+#message("GLIB2_LDFLAGS ${GLIB2_LDFLAGS}")
+#message("GLIB2_LDFLAGS_OTHER ${GLIB2_LDFLAGS_OTHER}")
+message("GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS}")
+#message("GLIB2_CFLAGS ${GLIB2_CFLAGS}")
+#message("GLIB2_CFLAGS_OTHER ${GLIB2_CFLAGS_OTHER}")
+#message("GLIB2_LIBDIR ${GLIB2_LIBDIR}")
+
+set(GLIB2_DEFINITIONS ${GLIB2_CFLAGS_OTHER})
+#message("GLIB2_DEFINITIONS ${GLIB2_DEFINITIONS}")
+
+set(GLIB2_LIBRARY_NAMES ${GLIB2_LIBRARIES})
+set(GLIB2_LIBRARIES "")
+foreach(GLIB2_LIB ${GLIB2_LIBRARY_NAMES})
+#  message("lib: ${GLIB2_LIB}")
+  set(TMP TMP-NOTFOUND)
+  find_library(TMP NAMES ${GLIB2_LIB}
+               PATHS ${GLIB2_LIBRARY_DIRS}
+               NO_DEFAULT_PATH)
+#  message("TMP: ${TMP}")
+  list(APPEND GLIB2_LIBRARIES "${TMP}")
+endforeach()
+message("GLIB2_LIBRARIES: ${GLIB2_LIBRARIES}")
-- 
cgit v0.10.1
From 745664f1266b3a46898c671ba17db21df19adebf Mon Sep 17 00:00:00 2001
From: Brody Kenrick 
Date: Wed, 11 Dec 2013 17:06:27 +1100
Subject: Ctests build for Glib2 - Add GLIB2_LIBDIR to find_library paths
diff --git a/tests/FindGLIB2.cmake b/tests/FindGLIB2.cmake
index b27b9a9..9164c39 100644
--- a/tests/FindGLIB2.cmake
+++ b/tests/FindGLIB2.cmake
@@ -2,13 +2,13 @@ find_package(PkgConfig REQUIRED)
 
 pkg_search_module(GLIB2 REQUIRED glib-2.0)
 #message("GLIB2_LIBRARIES ${GLIB2_LIBRARIES}")
-#message("GLIB2_LIBRARY_DIRS ${GLIB2_LIBRARY_DIRS}")
+message("GLIB2_LIBRARY_DIRS ${GLIB2_LIBRARY_DIRS}")
 #message("GLIB2_LDFLAGS ${GLIB2_LDFLAGS}")
 #message("GLIB2_LDFLAGS_OTHER ${GLIB2_LDFLAGS_OTHER}")
 message("GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS}")
 #message("GLIB2_CFLAGS ${GLIB2_CFLAGS}")
 #message("GLIB2_CFLAGS_OTHER ${GLIB2_CFLAGS_OTHER}")
-#message("GLIB2_LIBDIR ${GLIB2_LIBDIR}")
+message("GLIB2_LIBDIR ${GLIB2_LIBDIR}")
 
 set(GLIB2_DEFINITIONS ${GLIB2_CFLAGS_OTHER})
 #message("GLIB2_DEFINITIONS ${GLIB2_DEFINITIONS}")
@@ -20,6 +20,7 @@ foreach(GLIB2_LIB ${GLIB2_LIBRARY_NAMES})
   set(TMP TMP-NOTFOUND)
   find_library(TMP NAMES ${GLIB2_LIB}
                PATHS ${GLIB2_LIBRARY_DIRS}
+               PATHS ${GLIB2_LIBDIR}
                NO_DEFAULT_PATH)
 #  message("TMP: ${TMP}")
   list(APPEND GLIB2_LIBRARIES "${TMP}")
-- 
cgit v0.10.1
From 225afc966be6a99453b2ff2f77c621b7db01b12e Mon Sep 17 00:00:00 2001
From: Brody Kenrick 
Date: Wed, 11 Dec 2013 17:53:43 +1100
Subject: Add gettext lib for linux also
diff --git a/scripts/uni-build-dependencies.sh b/scripts/uni-build-dependencies.sh
index ba328b7..5b9e129 100755
--- a/scripts/uni-build-dependencies.sh
+++ b/scripts/uni-build-dependencies.sh
@@ -409,6 +409,24 @@ build_glew()
   GLEW_DEST=$DEPLOYDIR $MAKER install
 }
 
+build_gettext()
+{
+  version=$1
+  echo "Building gettext $version..."
+
+  cd "$BASEDIR"/src
+  rm -rf "gettext-$version"
+  if [ ! -f "glib-$version.tar.xz" ]; then
+    curl --insecure -LO "http://ftpmirror.gnu.org/gettext/gettext-$version.tar.gz"
+  fi
+  tar xzf "gettext-$version.tar.gz"
+  cd "gettext-$version"
+
+  ./configure --prefix="$DEPLOYDIR"
+  make -j4
+  make install
+}
+
 build_glib2()
 {
   version="$1"
@@ -428,10 +446,9 @@ curl --insecure -LO "http://ftp.gnome.org/pub/gnome/sources/glib/$maj_min_versio
 tar xJf "glib-$version.tar.xz"
   cd "glib-$version"
 
-  ./configure --prefix="$DEPLOYDIR"
+  ./configure --disable-gtk-doc --disable-man --prefix="$DEPLOYDIR" CFLAGS="-I$DEPLOYDIR/include" LDFLAGS="-L$DEPLOYDIR/lib"
   make -j$NUMCPU
   make install
-   
 }
 
 build_opencsg()
@@ -628,6 +645,7 @@ build_boost 1.53.0
 build_cgal 4.0.2
 build_glew 1.9.0
 build_opencsg 1.3.2
+build_gettext 0.18.3.1
 build_glib2 2.38.2
 
 echo "OpenSCAD dependencies built and installed to " $BASEDIR
-- 
cgit v0.10.1
From 4552d2d26352330ea0786dc65bc8f49328f90e02 Mon Sep 17 00:00:00 2001
From: Brody Kenrick 
Date: Wed, 11 Dec 2013 17:59:38 +1100
Subject: Add back in GL and GLIB2 links for tests-core
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index e590070..519f1e1 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -588,7 +588,7 @@ set(OFFSCREEN_SOURCES
   ../src/OpenCSGRenderer.cc)
 
 add_library(tests-core STATIC ${CORE_SOURCES})
-target_link_libraries(tests-core)
+target_link_libraries(tests-core ${OPENGL_LIBRARIES} ${GLIB2_LIBRARIES} )
 set(TESTS-CORE-LIBRARIES ${OPENGL_LIBRARIES} ${GLIB2_LIBRARIES} ${Boost_LIBRARIES} )
 
 add_library(tests-common STATIC ${COMMON_SOURCES})
-- 
cgit v0.10.1