Index: /trunk/nv/core/allocator.hh
===================================================================
--- /trunk/nv/core/allocator.hh	(revision 357)
+++ /trunk/nv/core/allocator.hh	(revision 357)
@@ -0,0 +1,61 @@
+// Copyright (C) 2015 ChaosForge Ltd
+// http://chaosforge.org/
+//
+// This file is part of NV Libraries.
+// For conditions of distribution and use, see copyright notice in nv.hh
+
+/**
+* @file allocator.hh
+* @author Kornel Kisielewicz
+* @brief allocator type
+*
+* Allocator concept based on:
+*
+* http://bitsquid.blogspot.com/2010/09/custom-memory-allocation-in-c.html
+* http://www.gamedev.net/page/resources/_/technical/general-programming/c-custom-memory-allocation-r3010
+*/
+
+#ifndef NV_CORE_ALLOCATOR_HH
+#define NV_CORE_ALLOCATOR_HH
+
+#include <nv/core/common.hh>
+#include <nv/core/type_traits.hh>
+
+namespace nv
+{
+
+	class allocator
+	{
+	public:
+		virtual void* allocate( size_t size, size_t alignment ) = 0;
+		virtual void deallocate( void *p ) = 0;
+		virtual void* reallocate( void* p, size_t new_size ) = 0;
+		virtual size_t allocated_size( void *p ) = 0;
+
+		virtual size_t get_allocated_count() = 0;
+		virtual size_t get_allocated_size() = 0;
+		virtual size_t get_max_allocated_count() = 0;
+		virtual size_t get_max_allocated_size() = 0;
+
+		template < class T, typename... Args > 
+		T *create( Args&&... args ) 
+		{
+			return new ( allocate( sizeof( T ), alignof( T ) ) ) T( std::forward<Args>( args )... );
+		}
+
+		template <class T> 
+		void destroy( T *p )
+		{
+			if ( p )
+			{
+				p->~T();
+				deallocate( p );
+			}
+		}
+	};
+
+
+
+}
+
+#endif // NV_CORE_ALLOCATOR_HH
Index: /trunk/nv/core/common.hh
===================================================================
--- /trunk/nv/core/common.hh	(revision 356)
+++ /trunk/nv/core/common.hh	(revision 357)
@@ -101,6 +101,6 @@
 #endif
 
-#if NV_COMPILER == NV_MSVC && NV_COMP_VER < 1600
-#error "MSVC 2012+ required!"
+#if NV_COMPILER == NV_MSVC && NV_COMP_VER < 1700
+#error "MSVC 2013+ required!"
 #endif
 
@@ -112,4 +112,8 @@
 #error "clang 3.2+ required!"
 #endif
+
+// Feature incoming - remove and find when constexpr compiler is used
+#define NV_CONSTEXPR 
+#define NV_CONSTEXPR_CONST const
 
 #if NV_COMPILER == NV_MSVC 
@@ -196,5 +200,5 @@
 	{
 	protected:
-		noncopyable() = default;
+		NV_CONSTEXPR noncopyable() = default;
 		~noncopyable() = default;
 		noncopyable( const noncopyable& ) = delete;
Index: /trunk/nv/core/io_event.hh
===================================================================
--- /trunk/nv/core/io_event.hh	(revision 356)
+++ /trunk/nv/core/io_event.hh	(revision 357)
@@ -62,4 +62,7 @@
 		/// True if pressed
 		bool pressed;
+
+		/// native scan code
+		int native;
 	};
 
Index: /trunk/nv/core/string_ref.hh
===================================================================
--- /trunk/nv/core/string_ref.hh	(revision 357)
+++ /trunk/nv/core/string_ref.hh	(revision 357)
@@ -0,0 +1,293 @@
+// Copyright (C) 2015 ChaosForge Ltd
+// This file is part of NV Libraries.
+// For conditions of distribution and use, see copyright notice in nv.hh
+// 
+// String reference implementation based of string_ref proposal and boost::string_ref
+//
+// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html
+// http://www.boost.org/doc/libs/1_58_0/libs/utility/doc/html/string_ref.html
+
+
+#ifndef NV_CORE_STRING_REF_HH
+#define NV_CORE_STRING_REF_HH
+
+#include <nv/core/common.hh>
+#include <nv/core/exception.hh>
+#include <nv/core/string.hh>
+
+namespace nv
+{
+
+	template<typename T, typename TRAITS = std::char_traits<T> > class basic_string_ref;
+
+	typedef basic_string_ref<char, std::char_traits<char> > string_ref;
+
+	template<typename T, typename TRAITS>
+	class basic_string_ref
+	{
+	public:
+		typedef T              value_type;
+		typedef const T*       pointer;
+		typedef const T&       reference;
+		typedef const T&       const_reference;
+		typedef pointer        const_iterator; 
+		typedef const_iterator iterator;
+		typedef std::size_t    size_type;
+		typedef std::ptrdiff_t difference_type;
+
+		typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+		typedef const_reverse_iterator                reverse_iterator;
+		
+		static NV_CONSTEXPR_CONST size_type npos = size_type( -1 );
+
+		NV_CONSTEXPR basic_string_ref() : m_data( nullptr ), m_length( 0 ) {}
+		NV_CONSTEXPR basic_string_ref( const basic_string_ref &rhs ) : m_data( rhs.m_data ), m_length( rhs.m_length ) {}
+
+		template< typename ALLOCATOR >
+		basic_string_ref( const std::basic_string<T, TRAITS, ALLOCATOR>& str )
+			: m_data( str.data() ), m_length( str.length() ) {}
+
+		NV_CONSTEXPR basic_string_ref( const T* str, size_type len )
+			: m_data( str ), m_length( len ) {}
+
+		// Literal constructors
+		template< size_t N, typename std::enable_if<std::is_same<T, char>::value>::type* = nullptr >
+		basic_string_ref( T( &s )[N] ) : m_data( s ), m_length( N - 1 ) {}
+		template< size_t N, typename std::enable_if<std::is_same<T, char>::value>::type* = nullptr >
+		basic_string_ref( const T( &s )[N] ) : m_data( s ), m_length( N - 1 ) {}
+
+		// Non-literal constructors
+		template< typename U, typename std::enable_if<std::is_same<U,const char*>::value>::type* = nullptr >
+		basic_string_ref( U str )
+			: m_data( str ), m_length( TRAITS::length( str ) )
+		{
+			static_assert( std::is_same<T, U>::value  );
+		}
+
+		basic_string_ref& operator=( const basic_string_ref &rhs )
+		{
+			m_data = rhs.m_data;
+			m_length = rhs.m_length;
+			return *this;
+		}
+
+		// conversion to std::string
+		template<typename ALLOCATOR>
+		explicit operator std::basic_string<T, TRAITS, ALLOCATOR>() const
+		{
+			return std::basic_string<T, TRAITS, ALLOCATOR>( m_data, m_length );
+		}
+		std::basic_string<T, TRAITS> to_string() const
+		{
+			return std::basic_string<T, TRAITS>( m_data, m_length );
+		}
+
+		// iterators
+		NV_CONSTEXPR const_iterator   begin() const { return m_data; }
+		NV_CONSTEXPR const_iterator  cbegin() const { return m_data; }
+		NV_CONSTEXPR const_iterator     end() const { return m_data + m_length; }
+		NV_CONSTEXPR const_iterator    cend() const { return m_data + m_length; }
+		const_reverse_iterator  rbegin() const { return const_reverse_iterator( end() ); }
+		const_reverse_iterator crbegin() const { return const_reverse_iterator( end() ); }
+		const_reverse_iterator    rend() const { return const_reverse_iterator( begin() ); }
+		const_reverse_iterator   crend() const { return const_reverse_iterator( begin() ); }
+
+		NV_CONSTEXPR size_type size()     const { return m_length; }
+		NV_CONSTEXPR size_type length()   const { return m_length; }
+		NV_CONSTEXPR size_type max_size() const { return m_length; }
+		NV_CONSTEXPR bool empty()         const { return m_length == 0; }
+
+		// access
+		NV_CONSTEXPR const T& operator[]( size_type i ) const { return m_data[i]; }
+		const T& at( size_t i ) const
+		{
+		//	if ( i >= m_data ) NV_THROW( std::out_of_range( "string_ref::at" ) );
+			return m_data[i];
+		}
+
+		NV_CONSTEXPR const T& front() const { return m_data[ 0 ]; }
+		NV_CONSTEXPR const T& back()  const { return m_data[ m_length - 1 ]; }
+		NV_CONSTEXPR const T* data()  const { return m_data; }
+
+		// modifiers
+		void clear()
+		{
+			m_length = 0;
+			m_data   = nullptr;
+		}
+		void remove_prefix( size_type n )
+		{
+			if ( n > m_length )	n = m_length;
+			m_data   += n;
+			m_length -= n;
+		}
+		void remove_suffix( size_type n )
+		{
+			if ( n > m_length ) n = m_length;
+			m_length -= n;
+		}
+
+		// string operations
+		basic_string_ref substr( size_type p, size_type n = npos ) const
+		{
+			if ( p > size() ) return basic_string_ref(); // NV_THROW( std::out_of_range( "substr" ) );
+			if ( n == p || p + n > size() ) n = size() - p;
+			return basic_string_ref( data() + p, n );
+		}
+		int compare( basic_string_ref rhs ) const
+		{
+			int cmp = TRAITS::compare( m_data, rhs.m_data, ( std::min )( m_length, rhs.m_length ) );
+			return cmp != 0 ? cmp : ( m_length == rhs.m_length ? 0 : m_length < rhs.m_length ? -1 : 1 );
+		}
+		bool starts_with( T c ) const { return !empty() && TRAITS::eq( c, front() ); }
+		bool starts_with( basic_string_ref s ) const
+		{
+			return m_length >= s.m_length && TRAITS::compare( m_data, s.m_data, s.m_length ) == 0;
+		}
+		bool ends_with( T c ) const { return !empty() && TRAITS::eq( c, back() ); }
+		bool ends_with( basic_string_ref s ) const
+		{
+			return m_length >= s.m_length && TRAITS::compare( m_data + m_length - s.m_length, s.m_data, s.m_length ) == 0;
+		}
+		size_type find( basic_string_ref s ) const
+		{
+			const_iterator it = std::search( this->cbegin(), this->cend(), s.cbegin(), s.cend(), TRAITS::eq );
+			return it == this->cend() ? npos : std::distance( this->cbegin(), it );
+		}
+		size_type find( T c ) const
+		{
+			const_iterator it = std::find_if( this->cbegin(), this->cend(), [=] ( T val ) { return TRAITS::eq( val, c ); } );
+			return it == this->cend() ? npos : std::distance( this->cbegin(), it );
+		}
+		size_type rfind( basic_string_ref s ) const
+		{
+			const_reverse_iterator it = std::search( this->crbegin(), this->crend(), s.crbegin(), s.crend(), TRAITS::eq );
+			return it == this->crend() ? npos : m_length - 1 - std::distance( this->crbegin(), it );
+		}
+		size_type rfind( T c ) const
+		{
+			const_reverse_iterator it = std::find_if( this->crbegin(), this->crend(), [=] ( T val ) { return TRAITS::eq( val, c ); } );
+			return it == this->crend() ? npos : m_length - 1 - std::distance( this->crbegin(), it );
+		}
+		size_type find_first_of( T c ) const { return find( c ); }
+		size_type find_first_of( basic_string_ref s ) const
+		{ 
+			const_iterator it = std::find_first_of( this->cbegin(), this->cend(), s.cbegin(), s.cend(), TRAITS::eq );
+			return it == this->cend() ? npos : std::distance( this->cbegin(), it );
+		}
+		size_type find_last_of( T c )  const { return rfind( c ); }
+		size_type find_last_of( basic_string_ref s ) const
+		{
+			const_reverse_iterator it = std::find_first_of( this->crbegin(), this->crend(), s.cbegin(), s.cend(), TRAITS::eq );
+			return it == this->crend() ? npos : m_length - 1 - std::distance( this->crbegin(), it );
+		}
+		size_type find_first_not_of( basic_string_ref s ) const
+		{
+			for ( const_iterator it = this->cbegin(); it != this->cend(); ++it )
+				if ( 0 == TRAITS::find( s.m_data, s.m_length, *first ) )
+					return std::distance( this->cbegin(), it );
+			return npos;
+		}
+		size_type find_first_not_of( T c ) const
+		{
+			for ( const_iterator it = this->cbegin(); it != this->cend(); ++it )
+				if ( !TRAITS::eq( c, *it ) )
+					return std::distance( this->cbegin(), it );
+			return npos;
+		}
+		size_type find_last_not_of( basic_string_ref s ) const
+		{
+			for ( const_reverse_iterator it = this->crbegin(); it != this->crend(); ++it )
+				if ( 0 == TRAITS::find( s.m_data, s.m_length, *it ) )
+					return m_length - 1 - std::distance( this->crbegin(), it );;
+			return npos;
+		}
+		size_type find_last_not_of( T c ) const
+		{
+			for ( const_reverse_iterator it = this->crbegin(); it != this->crend(); ++it )
+				if ( !TRAITS::eq( c, *it ) )
+					return m_length - 1 - std::distance( this->crbegin(), it );
+			return npos;
+		}
+
+	private:
+		pointer   m_data;
+		size_type m_length;
+	};
+
+#define NV_STRING_REF_CAST_OPERATORS( OPERATOR )\
+template < typename T, typename TRAITS, typename ALLOCATOR >\
+inline bool operator OPERATOR ( basic_string_ref< T, TRAITS > lhs, const std::basic_string< T, TRAITS, ALLOCATOR >& rhs )\
+{\
+	return lhs OPERATOR basic_string_ref< T, TRAITS >( rhs );\
+}\
+template < typename T, typename TRAITS, typename ALLOCATOR >\
+inline bool operator OPERATOR ( const std::basic_string< T, TRAITS, ALLOCATOR >& lhs, basic_string_ref< T, TRAITS > rhs )\
+{\
+	return basic_string_ref< T, TRAITS >( lhs ) OPERATOR rhs;\
+}\
+template < typename T, typename TRAITS >\
+inline bool operator OPERATOR ( basic_string_ref<T, TRAITS> lhs, const T* rhs )\
+{\
+	return lhs OPERATOR basic_string_ref< T, TRAITS >( rhs );\
+}\
+template < typename T, typename TRAITS >\
+inline bool operator OPERATOR ( const T* lhs, basic_string_ref< T, TRAITS > rhs )\
+{\
+	return basic_string_ref< T, TRAITS >( lhs ) OPERATOR rhs;\
+}\
+
+	// Base operators
+	template < typename T, typename TRAITS >
+	inline bool operator==( basic_string_ref< T, TRAITS > lhs, basic_string_ref< T, TRAITS > rhs )
+	{
+		return lhs.size() != rhs.size() ? false : ( lhs.compare( rhs ) == 0 );
+	}
+	template < typename T, typename TRAITS >
+	inline bool operator!=( basic_string_ref< T, TRAITS > lhs, basic_string_ref< T, TRAITS > rhs )
+	{
+		return lhs.size() != rhs.size() ? true : ( lhs.compare( rhs ) != 0 );
+	}
+	template < typename T, typename TRAITS >
+	inline bool operator<( basic_string_ref< T, TRAITS > lhs, basic_string_ref< T, TRAITS > rhs )
+	{
+		return lhs.compare( rhs ) < 0;
+	}
+	template < typename T, typename TRAITS >
+	inline bool operator>( basic_string_ref< T, TRAITS > lhs, basic_string_ref< T, TRAITS > rhs )
+	{
+		return lhs.compare( rhs ) > 0;
+	}
+	template < typename T, typename TRAITS >
+	inline bool operator<=( basic_string_ref< T, TRAITS > lhs, basic_string_ref< T, TRAITS > rhs )
+	{
+		return lhs.compare( rhs ) <= 0;
+	}
+	template < typename T, typename TRAITS >
+	inline bool operator>=( basic_string_ref< T, TRAITS > lhs, basic_string_ref< T, TRAITS > rhs )
+	{
+		return lhs.compare( rhs ) >= 0;
+	}
+
+NV_STRING_REF_CAST_OPERATORS( == )
+NV_STRING_REF_CAST_OPERATORS( != )
+NV_STRING_REF_CAST_OPERATORS( < )
+NV_STRING_REF_CAST_OPERATORS( > )
+NV_STRING_REF_CAST_OPERATORS( <= )
+NV_STRING_REF_CAST_OPERATORS( >= )
+
+	template < class T, class TRAITS >
+	inline std::basic_ostream<T, TRAITS>& operator<<( std::basic_ostream<T, TRAITS>& os, const basic_string_ref<T, TRAITS>& str )
+	{
+		if ( os.good() )
+		{
+			os.write( str.data(), str.size() );
+		}
+		return os;
+	}
+
+#undef NV_STRING_REF_CAST_OPERATORS
+
+}
+
+#endif // NV_CORE_STRING_REF_HH
Index: /trunk/src/sdl/sdl_input.cc
===================================================================
--- /trunk/src/sdl/sdl_input.cc	(revision 356)
+++ /trunk/src/sdl/sdl_input.cc	(revision 357)
@@ -98,4 +98,6 @@
 	default : break;
 	}
+
+	kevent.key.native = ke.keysym.scancode;
 
 	// If key was understood by nv, then it's valid, otherwise ignored
