Index: trunk/src/core/ascii_printer.cc
===================================================================
--- trunk/src/core/ascii_printer.cc	(revision 512)
+++ trunk/src/core/ascii_printer.cc	(revision 514)
@@ -15,10 +15,10 @@
 }
 
-void ascii_printer::print( const string_view& text, const position& p, uint32 color )
+void ascii_printer::print( const string_view& text, const position& p, term_color color )
 {
 	position coord( p );
 	for ( char c : text )
 	{
-		m_terminal->print( coord, color, c );
+		m_terminal->print( coord, color, term_color(), c );
 		++coord.x;
 		if ( coord.x >= m_terminal->get_size().x ) break;
@@ -26,27 +26,27 @@
 }
 
-void nv::ascii_printer::frame( const nv::rectangle& area, const nv::string_view& border_chars, uint32 color )
+void nv::ascii_printer::frame( const nv::rectangle& area, const nv::string_view& border_chars, term_color color )
 {
 	if ( border_chars.length() < 8 )
 	{
-		m_terminal->clear( area );
+		m_terminal->clear( area, color, term_color() );
 		return;
 	}
-	m_terminal->clear( area.shrinked( 1 ) );
+	m_terminal->clear( area.shrinked( 1 ), color, term_color() );
 	for ( int x = 0; x < area.get_width(); ++x )
 	{
-		m_terminal->print( position( area.ul.x + x, area.ul.y ), color, border_chars[0] );
-		m_terminal->print( position( area.ul.x + x, area.lr.y ), color, border_chars[1] );
+		m_terminal->print( position( area.ul.x + x, area.ul.y ), color, term_color(), border_chars[0] );
+		m_terminal->print( position( area.ul.x + x, area.lr.y ), color, term_color(), border_chars[1] );
 	}
 
 	for ( int y = 0; y < area.get_height(); ++y )
 	{
-		m_terminal->print( position( area.ul.x, area.ul.y + y ), color, border_chars[2] );
-		m_terminal->print( position( area.lr.x, area.ul.y + y ), color, border_chars[3] );
+		m_terminal->print( position( area.ul.x, area.ul.y + y ), color, term_color(), border_chars[2] );
+		m_terminal->print( position( area.lr.x, area.ul.y + y ), color, term_color(), border_chars[3] );
 	}
 
-	m_terminal->print( area.ul, color, border_chars[4] );
-	m_terminal->print( area.ur(), color, border_chars[5] );
-	m_terminal->print( area.ll(), color, border_chars[6] );
-	m_terminal->print( area.lr, color, border_chars[7] );
+	m_terminal->print( area.ul, color,   term_color(), border_chars[4] );
+	m_terminal->print( area.ur(), color, term_color(), border_chars[5] );
+	m_terminal->print( area.ll(), color, term_color(), border_chars[6] );
+	m_terminal->print( area.lr, color,   term_color(), border_chars[7] );
 }
Index: trunk/src/core/term_color.cc
===================================================================
--- trunk/src/core/term_color.cc	(revision 514)
+++ trunk/src/core/term_color.cc	(revision 514)
@@ -0,0 +1,30 @@
+// Copyright (C) 2016-2016 ChaosForge Ltd
+// http://chaosforge.org/
+//
+// This file is part of Nova libraries. 
+// For conditions of distribution and use, see copying.txt file in root folder.
+
+#include "nv/core/term_color.hh"
+
+using namespace nv;
+
+term_color term_color::s_default_colors[17] = {
+	term_color( term_color::BLACK,        u8vec3(   0,   0,   0 ) ),
+	term_color( term_color::BLUE,         u8vec3(   0,   0, 160 ) ),
+	term_color( term_color::GREEN,        u8vec3(   0, 160,   0 ) ),
+	term_color( term_color::CYAN,         u8vec3(   0, 160, 160 ) ),
+	term_color( term_color::RED,          u8vec3( 160,   0,   0 ) ),
+	term_color( term_color::MAGENTA,      u8vec3( 160,   0, 160 ) ),
+	term_color( term_color::BROWN,        u8vec3( 160, 160,   0 ) ),
+	term_color( term_color::LIGHTGRAY,    u8vec3( 216, 216, 216 ) ),
+	term_color( term_color::DARKGRAY,     u8vec3( 127, 127, 127 ) ),
+	term_color( term_color::LIGHTBLUE,    u8vec3(   0,   0, 255 ) ),
+	term_color( term_color::LIGHTGREEN,   u8vec3(   0, 255,   0 ) ),
+	term_color( term_color::LIGHTCYAN,    u8vec3(   0, 255, 255 ) ),
+	term_color( term_color::LIGHTRED,     u8vec3( 255,   0,   0 ) ),
+	term_color( term_color::LIGHTMAGENTA, u8vec3( 255,   0, 255 ) ),
+	term_color( term_color::YELLOW,       u8vec3( 255, 255,   0 ) ),
+	term_color( term_color::WHITE,        u8vec3( 255, 255, 255 ) ),
+	term_color( term_color::BLACK,        u8vec4( 0,   0,   0,  0 ) ),
+};
+
Index: trunk/src/curses/curses_terminal.cc
===================================================================
--- trunk/src/curses/curses_terminal.cc	(revision 512)
+++ trunk/src/curses/curses_terminal.cc	(revision 514)
@@ -28,12 +28,6 @@
 	PDC_save_key_modifiers( true );
 
-	init_pair( 1, 0, 0 );
-	init_pair( 2, 1, 0 );
-	init_pair( 3, 2, 0 );
-	init_pair( 4, 3, 0 );
-	init_pair( 5, 4, 0 );
-	init_pair( 6, 5, 0 );
-	init_pair( 7, 6, 0 );
-	init_pair( 8, 7, 0 );
+	for ( short i = 0; i < 64; ++i )
+		init_pair( i+1, i % 8, i / 8 );
 
 	clear();
@@ -53,22 +47,23 @@
 }
 
-void curses_terminal::print( position p, uint32 color, char ch )
+void curses_terminal::print( position p, term_color fgcolor, term_color bgcolor, char ch )
 {
+	uint32 fcolor = fgcolor.get_color();
+	uint32 bcolor = ( bgcolor.get_color() % 8 ) * 8;
 	m_update_needed = true;
-	if ( color > 7 )
-	{
-		attrset(((static_cast<uint32>(color-7) << 24)  & 0xff000000ul ) | 0x00800000ul);
-	}
-	else
-	{
-		attrset((static_cast<uint32>(color+1) << 24)  & 0xff000000ul);
-	}
+	chtype attr = static_cast<chtype>( ( fcolor > 7 ? fcolor - 7 + bcolor : fcolor + bcolor + 1 ) << 24 );
+	if ( fcolor > 7 ) attr = attr | 0x00800000ul;
+	attrset(attr);
 	mvaddch( p.y-1, p.x-1, chtype(ch) );
 	::move( m_cursor.y-1, m_cursor.x-1 );
 }
 
-void curses_terminal::clear( rectangle r )
+void curses_terminal::clear( rectangle r, term_color fgcolor, term_color bgcolor )
 {
-	attrset( 0x00000000ul | 0x00800000ul );
+	uint32 fcolor = fgcolor.get_color();
+	uint32 bcolor = ( bgcolor.get_color() % 8 ) * 8;
+	chtype attr = static_cast<chtype>( ( fcolor > 7 ? fcolor - 7 + bcolor : fcolor + bcolor + 1 ) << 24 );
+	if ( fcolor > 7 ) attr = attr | 0x00800000ul;
+	attrset( attr );
 	for ( int x = r.ul.x-1; x <= r.lr.x-1; ++x )
 		for ( int y = r.ul.y-1; y <= r.lr.y-1; ++y )
Index: trunk/src/gfx/gfx_terminal.cc
===================================================================
--- trunk/src/gfx/gfx_terminal.cc	(revision 514)
+++ trunk/src/gfx/gfx_terminal.cc	(revision 514)
@@ -0,0 +1,200 @@
+// Copyright (C) 2016-2016 ChaosForge Ltd
+// http://chaosforge.org/
+//
+// This file is part of Nova libraries. 
+// For conditions of distribution and use, see copying.txt file in root folder.
+
+#include "nv/gfx/gfx_terminal.hh"
+
+#include "nv/core/logging.hh"
+
+using namespace nv;
+
+static const char *nv_gfx_terminal_vs = R"(
+#version 330
+in vec2 nv_position;
+in vec2 nv_texcoord;
+out vec2 v_texcoord;
+void main(void)
+{
+	gl_Position = vec4(nv_position, 0.0, 1.0);
+	v_texcoord  = nv_texcoord;
+};
+)";
+static const char *nv_gfx_terminal_fs = R"(
+#version 330
+in  vec2 v_texcoord;
+out vec4 o_frag_color;
+
+uniform vec2 term_size;
+uniform vec2 dev_size;
+//uniform vec2 gylph_size;
+uniform sampler2D nv_t_diffuse;
+
+struct term_data
+{
+	uint fg;
+	uint bg;
+	uint gylph;
+	uint pad;
+};
+
+layout(std140) uniform terminal_block
+{
+	term_data term[80*50];
+};
+
+void main(void)
+{
+	vec2 coord   = v_texcoord * term_size;
+	ivec2 icoord = ivec2( coord );
+	vec2 tc      = coord - vec2( icoord );
+	tc.y = 1.0f - tc.y;
+
+	coord.y = term_size.y - coord.y;
+	
+	int index = int( coord.x ) + int( term_size.x ) * int( coord.y );
+	uint fg   = term[ index ].fg;
+	int gylph = int( term[ index ].gylph );
+	ivec2 gxy = ivec2( gylph % 16, gylph / 16 );
+	vec2 gpos = vec2( ( float(gxy.x) + tc.x ) / 16.0f, ( float(gxy.y) + tc.y ) / 16.0f );
+	vec4 tt   = texture( nv_t_diffuse, gpos );
+
+
+    vec4 color = vec4(
+        float( ( fg & uint(0x00FF0000) ) >> 16 ) / 255.0f,
+        float( ( fg & uint(0x0000FF00) ) >> 8 ) / 255.0f,
+        float(   fg & uint(0x000000FF) ) / 255.0f,
+        1.0 //fg & uint(0xFF000000)
+	);
+	o_frag_color = vec4( color.xyz * tt.xyz + vec3( 0.0, 0.2, 0.0 ) * ( 1.0 - tt.xyz ), 1.0 * tt.x );
+//	o_frag_color = vec4( fg, 0.0, 0.0, 1.0) ;
+}
+)";
+
+struct gfx_terminal_uniform_block
+{
+	uint32 fgcolor = 0;
+	uint32 bgcolor = 0;
+	uint32 gylph   = 0;
+	uint32 pad;
+
+	void set( term_color fg, term_color bg, char ch )
+	{
+		fgcolor = fg.get_argb32();
+		bgcolor = bg.get_argb32();
+		gylph   = uint32( ch );
+		NV_LOG_INFO( uint32( 
+			( fgcolor & uint32( 0x00FF0000 ) ) >> 16 ), "-", uint32( ( fgcolor & uint32( 0x0000FF00 ) ) >> 8 ),"-" , uint32( fgcolor & uint32( 0x000000FF ) ) );
+	}
+};
+
+struct nv::gfx_terminal_data
+{
+	gfx_terminal_uniform_block* data;
+	dimension                   size;
+	buffer                      buffer;
+
+	gfx_terminal_data( dimension dim )
+	{
+		size = dim;
+		data = new gfx_terminal_uniform_block[dim.x * dim.y];
+	}
+
+	gfx_terminal_uniform_block& operator[]( position p )
+	{
+		int index = size.x * p.y + p.x;
+		return data[index];
+	}
+
+	~gfx_terminal_data()
+	{
+		delete[] data;
+	}
+};
+
+gfx_terminal::gfx_terminal( context* ctx, texture t, dimension tsize, dimension psize )
+	: terminal( tsize ), m_context( ctx )
+{
+	m_data = new gfx_terminal_data( tsize );
+	
+	struct qvtx
+	{
+		vec2 position;
+		vec2 texcoord;
+	};
+
+	qvtx quad[] = {
+		qvtx{ vec2( -1.0f,-1.0f ), vec2( 0.0f, 0.0f ) },
+		qvtx{ vec2( 1.0f,-1.0f ),  vec2( 1.0f, 0.0f ) },
+		qvtx{ vec2( 1.0f,1.0f ),   vec2( 1.0f, 1.0f ) },
+		qvtx{ vec2( 1.0f,1.0f ),   vec2( 1.0f, 1.0f ) },
+		qvtx{ vec2( -1.0f,1.0f ),  vec2( 0.0f, 1.0f ) },
+		qvtx{ vec2( -1.0f,-1.0f ), vec2( 0.0f, 0.0f ) },
+	};
+	m_dc.va       = m_context->create_vertex_array( quad, 6, nv::STATIC_DRAW );
+	m_dc.va_count = 6;
+	m_dc.image    = t;
+
+	m_dc.p = m_context->create_program( nv_gfx_terminal_vs, nv_gfx_terminal_fs );
+
+	m_data->buffer = m_context->create_buffer( nv::UNIFORM_BUFFER, nv::DYNAMIC_DRAW, tsize.x * tsize.y * sizeof( gfx_terminal_uniform_block ), m_data->data );
+	m_context->bind( m_data->buffer, 7 );
+	m_context->get_device()->set_opt_uniform( m_dc.p, "term_size", vec2( tsize ) );
+//	m_context->get_device()->set_opt_uniform( m_dc.p, "dev_size", vec2( psize ) );
+	m_context->get_device()->set_opt_uniform( m_dc.p, "gylph_size", vec2( 8,8 ) );
+	m_context->get_device()->set_opt_uniform( m_dc.p, "nv_t_diffuse", int( nv::TEX_DIFFUSE ) );
+	m_context->get_device()->bind_block( m_dc.p, "terminal_block", 7 );
+	m_update_needed = false;
+}
+
+void gfx_terminal::update()
+{
+	m_context->bind( m_data->buffer, 7 );
+	m_context->update( m_data->buffer, m_data->data, 0, m_data->size.x * m_data->size.y * sizeof( gfx_terminal_uniform_block ) );
+	m_update_needed = false;
+}
+
+void gfx_terminal::print( position p, term_color fgcolor, term_color bgcolor, char ch )
+{
+	m_update_needed = true;
+	( *m_data )[position( p.x - 1, p.y - 1)].set( fgcolor, bgcolor, ch );
+}
+
+void gfx_terminal::clear( rectangle r, term_color fgcolor, term_color bgcolor )
+{
+	m_update_needed = true;
+	for ( int x = r.ul.x - 1; x <= r.lr.x - 1; ++x )
+		for ( int y = r.ul.y - 1; y <= r.lr.y - 1; ++y )
+			(*m_data)[ position( x, y ) ].set( fgcolor, bgcolor, ' ' );
+}
+
+void gfx_terminal::clear()
+{
+	m_update_needed = true;
+	for ( int i = 0; i < m_data->size.x * m_data->size.y; ++i )
+		m_data->data[i].set( term_color::LIGHTGRAY, term_color::TRANSPARENT, ' ' );
+}
+
+bool gfx_terminal::poll( io_event & kevent )
+{
+	return false;
+}
+
+void gfx_terminal::set_cursor( position p )
+{
+}
+
+void gfx_terminal::show_cursor()
+{
+}
+
+void gfx_terminal::hide_cursor()
+{
+}
+
+gfx_terminal::~gfx_terminal()
+{
+	delete m_data;
+}
+
Index: trunk/src/gui/gui_ascii_renderer.cc
===================================================================
--- trunk/src/gui/gui_ascii_renderer.cc	(revision 512)
+++ trunk/src/gui/gui_ascii_renderer.cc	(revision 514)
@@ -15,10 +15,10 @@
 struct ascii_render_data : public render_data
 {
-	ascii_render_data() {}
-	bool   clear;
-	bool   border;
-	char   border_chars[8];
-	uint32 border_color;
-	uint32 text_color;
+	bool       clear;
+	bool       border;
+	char       border_chars[8];
+	ivec2      padding;
+	term_color border_color;
+	term_color text_color;
 };
 
@@ -38,5 +38,4 @@
 		er->border     = false;
 		er->clear      = false;
-		er->text_color = 0;
 		e->m_render_data = er;
 	}
@@ -57,6 +56,10 @@
 		
 		m_style.get( e, "ascii_color", selector, color );
-		er->text_color = uint32( color );
+		er->text_color = term_color::color( color );
 		er->border     = false;
+		vec4 padding;
+		m_style.get( e, "ascii_padding", selector, padding );
+		er->padding    = ivec2( int( padding.x ), int( padding.y ) );
+
 		if ( m_style.get( e, "ascii_border", selector, path ) )
 		{
@@ -65,5 +68,5 @@
 			int border_color = 0;
 			if ( m_style.get( e, "ascii_border_color", selector, border_color ) )
-				er->border_color = uint32( border_color );
+				er->border_color = term_color::color( border_color );
 			for ( uint32 i = 0; i < 8 && i < path.length(); i++ )
 				er->border_chars[i] = path[i];
@@ -76,31 +79,31 @@
 	ascii_render_data* er = static_cast< ascii_render_data* >( e->m_render_data );
 	rectangle abs = e->m_absolute;
-	if ( er->clear ) m_terminal->clear( abs );
+	if ( er->clear ) m_terminal->clear( abs, term_color::LIGHTGRAY, term_color() );
 	if ( er->border )
 	{
 		for ( int x = 0; x < abs.get_width(); ++x )
 		{
-			m_terminal->print( position( abs.ul.x + x, abs.ul.y ), er->border_color, er->border_chars[0] );
-			m_terminal->print( position( abs.ul.x + x, abs.lr.y ), er->border_color, er->border_chars[1] );
+			m_terminal->print( position( abs.ul.x + x, abs.ul.y ), er->border_color, term_color(), er->border_chars[0] );
+			m_terminal->print( position( abs.ul.x + x, abs.lr.y ), er->border_color, term_color(), er->border_chars[1] );
 		}
 
 		for ( int y = 0; y < abs.get_height(); ++y )
 		{
-			m_terminal->print( position( abs.ul.x, abs.ul.y + y ), er->border_color, er->border_chars[2] );
-			m_terminal->print( position( abs.lr.x, abs.ul.y + y ), er->border_color, er->border_chars[3] );
+			m_terminal->print( position( abs.ul.x, abs.ul.y + y ), er->border_color, term_color(), er->border_chars[2] );
+			m_terminal->print( position( abs.lr.x, abs.ul.y + y ), er->border_color, term_color(), er->border_chars[3] );
 		}
 
-		m_terminal->print( abs.ul,   er->border_color, er->border_chars[4] );
-		m_terminal->print( abs.ur(), er->border_color, er->border_chars[5] );
-		m_terminal->print( abs.ll(), er->border_color, er->border_chars[6] );
-		m_terminal->print( abs.lr,   er->border_color, er->border_chars[7] );
+		m_terminal->print( abs.ul,   er->border_color, term_color(), er->border_chars[4] );
+		m_terminal->print( abs.ur(), er->border_color, term_color(), er->border_chars[5] );
+		m_terminal->print( abs.ll(), er->border_color, term_color(), er->border_chars[6] );
+		m_terminal->print( abs.lr,   er->border_color, term_color(), er->border_chars[7] );
 		m_terminal->update();
 	}
 	if ( !e->m_text.empty() )
 	{
-		position p = abs.ul;
+		position p = abs.ul + er->padding;
 		for ( char c : e->m_text )
 		{
-			m_terminal->print( p, er->text_color, c );
+			m_terminal->print( p, er->text_color, term_color(), c );
 			++p.x;
 		}
