#include "Script.hpp"
//==========================================================================//
// File:	 Font.cpp														//
// Project:  GameOS					                                        //
// Contents: Font-drawing routines											//
//--------------------------------------------------------------------------//
// Date      Who    Modification                                            //
// 11/15/97  JTR    Created													//
//																			//
//--------------------------------------------------------------------------//
// Copyright (C) 2000, Microsoft, Inc.										//
// All Rights reserved worldwide                                            //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL              //
//==========================================================================//

int  g_scriptLineColor;

extern POSITION g_textXY;
extern CUBE g_textMargins;
extern HGOSSURFACE g_textDstSurf;
extern gosEnum_TextWrap g_textWrapMode;
extern HGOSFONT g_textFont;
void gosScript_CreateFont(HGOSFONT * font, const char * path, DWORD width, DWORD height, bool proportional)
{
	gosASSERT(path != NULL);
	gosASSERT(width > 0 && height > 0);
	*font = NULL;
	*font = (HGOSFONT) new Font( path, width, height, proportional);
	gosASSERT(font != NULL);
}

void gosScript_TextSelectFont(HGOSFONT font)
{
	gosASSERT(IsValidSurface(font));
	g_textFont = font;
}

void
	gosScript_TextSetLocation(DWORD x, DWORD y)
{
	gosASSERT(x >= 0 && y >= 0);
	g_textXY.x = x;
	g_textXY.y = y;
}

void
	gosScript_TextSetSurface(HGOSSURFACE surf)
{
	gosASSERT(IsValidSurface(surf));
	g_textDstSurf = surf;
	g_textMargins.p2.x = surf->m_nativeFormat.m_width;
	g_textMargins.p1.x = 0;
	g_textMargins.p1.y = 0;
	g_textMargins.p2.y = surf->m_nativeFormat.m_height;
}

void gosScript_TextGetSurfaceAndLocation(HGOSSURFACE* surf, DWORD* x, DWORD* y)
{
	if (surf)
		*surf = g_textDstSurf;
	if (x)
		*x = g_textXY.x;
	if (y)
		*y = g_textXY.y;
}

void gosScript_TextOut(const char * text, ...)
{
	gosASSERT(IsValidSurface(g_textFont));
	if (!text) return;
	static char buffer_sprintf[8192];
	if (text[0] == 0) return;
    vsprintf( buffer_sprintf, text, (char*)(&text+1) );
	if (g_textWrapMode == GOSWRAP_WORD || g_textWrapMode == GOSWRAP_WORDSCROLL)
		g_textFont->TextOutByWord(buffer_sprintf);
	else
		g_textFont->TextOut(buffer_sprintf);

}

void gosScript_TextOutN(DWORD count, const char * text, ...)
{
	gosASSERT(IsValidSurface(g_textFont));
	if (!text) return;
	static char buffer_sprintf[8192];
	if (text[0] == 0) return;
    vsprintf( buffer_sprintf, text, (char*)(&text+1) );
	g_textFont->TextOut(count, buffer_sprintf);
}

void gosScript_DestroyFont(HGOSFONT* font)
{
	gosASSERT(IsValidSurface(*font));
	delete *font;
	*font = NULL;
}

void 
	gosScript_FontSetBackgroundColor(HGOSFONT font, DWORD color)
{
	gosASSERT(IsValidSurface(font));
	HGOSFONT f = font;
	f->m_backgroundColorSet = TRUE;
	f->m_backgroundColor = color;
}

void 
	gosScript_FontSetForegroundColor(HGOSFONT font, DWORD color)
{
	gosASSERT(IsValidSurface(font));
	HGOSFONT f = font;
	f->m_foregroundColorSet = TRUE;
	f->m_foregroundColor = color;
}


void 
	gosScript_TextSetMargins(CUBE * borders)
{
	gosASSERT(borders != NULL);
	memcpy(&g_textMargins, borders, sizeof(CUBE));
}

void 
	gosScript_TextSetWrapMode(gosEnum_TextWrap wrap)
{
	g_textWrapMode = wrap;
}

DWORD
	gosScript_FontGetWidth(HGOSFONT font)
{
	gosASSERT(IsValidSurface(font));
	return font->m_pointSizeX;
}

DWORD
	gosScript_FontGetHeight(HGOSFONT font)
{
	gosASSERT(IsValidSurface(font));
	return font->m_pointSizeY;
}




Font::Font(const char * path, DWORD width, DWORD height, bool proportional) :
Surface(path,1)
{
	gosASSERT(path != NULL);
	gosASSERT(width > 0 && height > 0);
	m_pointSizeX = width;
	m_pointSizeY = height;
	m_foregroundColorSet = FALSE;
	m_backgroundColorSet = FALSE;
	m_isProportional = proportional;
	if (m_isProportional)
		DetermineSpacings();

}

Font::~Font()
{
	// deconstruction happens in surface.cpp
}

void Font::DetermineSpacings()
{
	memset(m_characterWidth,0,96);
	DWORD backgr = GetPixel(1,1);// space is totally clear!
	for(int j=0; j < 3; j++)
	{
		for(int i=0; i < 32; i++)
		{
			// scan the cell for right-most lit pixel and add one
			for(int x=m_pointSizeX-1; x >= 0 ; x--)
			{
				for( int y=0; y < m_pointSizeY; y++)
				{
					if (GetPixel(i*m_pointSizeX + x, j*m_pointSizeY+y) != backgr)
					{
						m_characterWidth[j*32+i] = (char)(x+2);
						break;
					}
				}
				if (m_characterWidth[j*32+i]) 
					break;
			}
			if (!m_characterWidth[j*32+i]) 
				m_characterWidth[j*32+i] = (char)m_pointSizeX;
		}
	}
	m_characterWidth[0] = (char)(m_pointSizeX/2);
}

void
	Font::TextOut(const char * str)
{
	DWORD row, column;
	gosASSERT(IsValidSurface(g_textDstSurf));
	for(unsigned int k = 0; k < strlen(str); k++)
	{
		// if carriage return, do it.
		if (str[k] == '\n')
		{
			g_textXY.y += m_pointSizeY;
			g_textXY.x = g_textMargins.p1.x;
			continue;
		}

		// process tabs
		if (str[k] == '\t')
		{
			int tab_to_use = g_textXY.x / (m_pointSizeX*4);
			g_textXY.x = (tab_to_use+1)*(4*m_pointSizeX);

		}

		char c = (char)(str[k]-32);

		// if it's not a valid char, go to next one
		if (!(c >= 0 && c < 96))
			continue;

		row = c / 32;
		column = c % 32;

		CUBE 
			src = 
		{
			column*m_pointSizeX,
			row*m_pointSizeY,
			0,
			column*m_pointSizeX + (m_isProportional ? m_characterWidth[c] : m_pointSizeX), 
			row*m_pointSizeY + m_pointSizeY,
			0
		};
		switch(g_textWrapMode)
		{
			case GOSWRAP_NONE:
			{
				if (g_textXY.x + (m_isProportional ? m_characterWidth[c] : m_pointSizeX) > g_textMargins.p2.x)
				{
					c = 127;
					break;
				}
				if (g_textXY.x < g_textMargins.p1.x)
				{
					c = 127;
					break;
				}
				if (g_textXY.y + m_pointSizeY > g_textMargins.p2.y)
				{
					c = 127;
					break;
				}
				if (g_textXY.y < g_textMargins.p1.y)
				{
					c = 127;
					break;
				}
			}
			break;
			case GOSWRAP_CHAR:
			case GOSWRAP_WORD:
			{
				if (g_textXY.x + (m_isProportional ? m_characterWidth[c] : m_pointSizeX) > g_textMargins.p2.x)
				{
					g_textXY.y += m_pointSizeY;
					g_textXY.x = g_textMargins.p1.x;
				}
				if (g_textXY.x <  g_textMargins.p1.x)
				{
					g_textXY.x = g_textMargins.p1.x;
				}
				if (g_textXY.y + m_pointSizeY > g_textMargins.p2.y+1)
				{
					g_textXY.y = g_textMargins.p1.y;
				}
				if (g_textXY.y <  g_textMargins.p1.y)
				{
					g_textXY.y = g_textMargins.p1.y;
				}
			}
			break;
			case GOSWRAP_CHARSCROLL:
			{
				if (g_textXY.x + m_pointSizeX > g_textMargins.p2.x)
				{
					g_textXY.y += m_pointSizeY;
					g_textXY.x = g_textMargins.p1.x;
				}
				if (g_textXY.x < g_textMargins.p1.x)
				{
					g_textXY.x = g_textMargins.p1.x;
				}
				if (g_textXY.y + m_pointSizeY > g_textMargins.p2.y)
				{
					// scroll it!
					for(signed long i = g_textMargins.p1.y+m_pointSizeY; i < g_textMargins.p2.y; i++)
					{
						memcpy
						(
							((char *)g_textDstSurf->m_nativeFormat.m_lpRawData)+((i-m_pointSizeY)*g_textDstSurf->m_nativeFormat.m_pitch),
							((char *)g_textDstSurf->m_nativeFormat.m_lpRawData)+(i*g_textDstSurf->m_nativeFormat.m_pitch),
							g_textDstSurf->m_nativeFormat.m_pitch
						);
					}
					for(i = g_textXY.y - (m_isProportional ? m_characterWidth[c] : m_pointSizeX); i < g_textMargins.p2.y; i++)
					{
						memset
						(
							((char *)g_textDstSurf->m_nativeFormat.m_lpRawData)+(i*g_textDstSurf->m_nativeFormat.m_pitch),
							0x00,
							g_textDstSurf->m_nativeFormat.m_pitch
						);
					}
					g_textXY.y -= m_pointSizeY;
				}
				if (g_textXY.y < g_textMargins.p1.y)
				{
					g_textXY.y = g_textMargins.p1.y;
				}
			}
			break;
			case GOSWRAP_WORDSCROLL:
			{
				if (g_textXY.x + (m_isProportional ? m_characterWidth[c] : m_pointSizeX) > g_textMargins.p2.x)
				{
					g_textXY.y += m_pointSizeY;
					g_textXY.x = g_textMargins.p1.x;
				}
				if (g_textXY.x < g_textMargins.p1.x)
				{
					g_textXY.x = g_textMargins.p1.x;
				}
				if (g_textXY.y + m_pointSizeY > g_textMargins.p2.y)
				{
					g_textXY.y = g_textMargins.p1.y;
				}
				if (g_textXY.y < g_textMargins.p1.y)
				{
					g_textXY.y = g_textMargins.p1.y;
				}
			}
			break;
		}
		if (c >= 0 && c < 96)
		{
			if (c != 0)
				TextBlit(&src,g_textXY.x, g_textXY.y, g_textDstSurf);
		  	if (m_isProportional)
				g_textXY.x += m_characterWidth[c];
			else
				g_textXY.x += m_pointSizeX;
		}
	}
}

void
	Font::TextOut(DWORD count, const char * str)
{
	gosASSERT(IsValidSurface(g_textDstSurf));
	DWORD row, column;
	for(unsigned int k = 0; k < strlen(str) && k < count; k++)
	{
		char c = (char)(str[k]-32);

		row = c / 32;
		column = c % 32;

		CUBE 
			src = 
		{
			column*m_pointSizeX,
			row*m_pointSizeY,
			0,
			column*m_pointSizeX + (m_isProportional ? m_characterWidth[c] : m_pointSizeX), 
			row*m_pointSizeY + m_pointSizeY,
			0
		};

		switch(g_textWrapMode)
		{
			case GOSWRAP_NONE:
			{
				if (g_textXY.x + (m_isProportional ? m_characterWidth[c] : m_pointSizeX) > g_textMargins.p2.x)
				{
					c = 127;
					break;
				}
				if (g_textXY.x < g_textMargins.p1.x)
				{
					c = 127;
					break;
				}
				if (g_textXY.y + m_pointSizeY > g_textMargins.p2.y)
				{
					c = 127;
					break;
				}
				if (g_textXY.y < g_textMargins.p1.y)
				{
					c = 127;
					break;
				}
			}
			break;
			case GOSWRAP_CHAR:
			{
				if (g_textXY.x + (m_isProportional ? m_characterWidth[c] : m_pointSizeX) > g_textMargins.p2.x)
				{
					g_textXY.y += m_pointSizeY;
					g_textXY.x = g_textMargins.p1.x;
				}
				if (g_textXY.x < g_textMargins.p1.x)
				{
					g_textXY.x = g_textMargins.p1.x;
				}
				if (g_textXY.y + m_pointSizeY > g_textMargins.p2.y)
				{
					g_textXY.y = g_textMargins.p1.y;
				}
				if (g_textXY.y < g_textMargins.p1.y)
				{
					g_textXY.y = g_textMargins.p1.y;
				}
			}
			break;

			case GOSWRAP_WORD:
			{
				if (g_textXY.x + (m_isProportional ? m_characterWidth[c] : m_pointSizeX) > g_textMargins.p2.x)
				{
					g_textXY.y += m_pointSizeY;
					g_textXY.x = g_textMargins.p1.x;
				}
				if (g_textXY.x < g_textMargins.p1.x)
				{
					g_textXY.x = g_textMargins.p1.x;
				}
				if (g_textXY.y + m_pointSizeY > g_textMargins.p2.y)
				{
					g_textXY.y = g_textMargins.p1.y;
				}
				if (g_textXY.y < g_textMargins.p1.y)
				{
					g_textXY.y = g_textMargins.p1.y;
				}
			}
			break;
			case GOSWRAP_CHARSCROLL:
			{
				if (g_textXY.x + (m_isProportional ? m_characterWidth[c] : m_pointSizeX) > g_textMargins.p2.x)
				{
					g_textXY.y += m_pointSizeY;
					g_textXY.x = g_textMargins.p1.x;
				}
				if (g_textXY.x < g_textMargins.p1.x)
				{
					g_textXY.x = g_textMargins.p1.x;
				}
				if (g_textXY.y + m_pointSizeY > g_textMargins.p2.y)
				{
					// scroll it!
					for(signed long i = g_textMargins.p1.y+m_pointSizeY; i < g_textMargins.p2.y; i++)
					{
						memcpy
						(
							((char *)g_textDstSurf->m_nativeFormat.m_lpRawData)+((i-m_pointSizeY)*g_textDstSurf->m_nativeFormat.m_pitch),
							((char *)g_textDstSurf->m_nativeFormat.m_lpRawData)+(i*g_textDstSurf->m_nativeFormat.m_pitch),
							g_textDstSurf->m_nativeFormat.m_pitch
						);
					}
					for(i = g_textXY.y - m_pointSizeY; i < g_textMargins.p2.y; i++)
					{
						memset
						(
							((char *)g_textDstSurf->m_nativeFormat.m_lpRawData)+(i*g_textDstSurf->m_nativeFormat.m_pitch),
							0x00,
							g_textDstSurf->m_nativeFormat.m_pitch
						);
					}
					g_textXY.y -= m_pointSizeY;
				}
				if (g_textXY.y < g_textMargins.p1.y)
				{
					g_textXY.y = g_textMargins.p1.y;
				}
			}
			break;
			case GOSWRAP_WORDSCROLL:
			{
				if (g_textXY.x + (m_isProportional ? m_characterWidth[c] : m_pointSizeX) > g_textMargins.p2.x)
				{
					g_textXY.y += m_pointSizeY;
					g_textXY.x = g_textMargins.p1.x;
				}
				if (g_textXY.x < g_textMargins.p1.x)
				{
					g_textXY.x = g_textMargins.p1.x;
				}
				if (g_textXY.y + m_pointSizeY > g_textMargins.p2.y)
				{
					g_textXY.y = g_textMargins.p1.y;
				}
				if (g_textXY.y < g_textMargins.p1.y)
				{
					g_textXY.y = g_textMargins.p1.y;
				}
			}
			break;
		}
		if (c >= 0 && c < 96)
		{
			TextBlit(&src,g_textXY.x, g_textXY.y, g_textDstSurf);
		  	if (m_isProportional)
				g_textXY.x += m_characterWidth[c];
			else
				g_textXY.x += m_pointSizeX;
		}
		else
		if (str[k] == '\n')
		{
			g_textXY.y += m_pointSizeY;
			g_textXY.x = g_textMargins.p1.x;
		}
	}
}


///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
// The new textblit routine (hey, it's lots better than before)
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
void
	Font::TextBlit(CUBE * rect_in, int x, int y, HGOSSURFACE dst)
{
	gosASSERT(IsValidSurface(dst));
	CUBE
		rect;
	if (rect_in == NULL)
	{									   
		rect.p1.y = 0;
		rect.p1.x = 0;
		rect.p2.y = m_nativeFormat.m_height-1;
		rect.p2.x = m_nativeFormat.m_width-1;

	}
	else
	{
		memcpy(&rect,rect_in,sizeof(CUBE));
	}


	if (rect.p2.x + x < 0)
		return;
	
	if (x >= (signed) dst->m_nativeFormat.m_width-1 && m_nativeFormat.m_width-1 + x> dst->m_nativeFormat.m_width-1)
		return;
	
	if (rect.p2.y +y  < 0)
		return;

	if (y >= (signed) dst->m_nativeFormat.m_height-1 && m_nativeFormat.m_height-1 + y> dst->m_nativeFormat.m_height-1)
		return;
	
	if (x < 0)
	{
		if (x + (rect.p2.x-rect.p1.x) > 0)
		{
			rect.p1.x -= x;
			x = 0;
			if (rect.p2.x < rect.p1.x) 
				return;
		}
		else
		{
			return;
		}
	}

	if (x == 0 && y == 0)
	{
		if (rect.p1.x < 0)
		{
			x -= rect.p1.x;
			rect.p1.x = 0 ;
		}
		if (rect.p2.x > m_nativeFormat.m_width-1)//
		{
			rect.p2.x = m_nativeFormat.m_width-1;//
		}
		if (rect.p2.x <= rect.p1.x) 
			return;
	  
		if (rect.p2.x-rect.p1.x > dst->m_nativeFormat.m_width) //
		{
			rect.p2.x = dst->m_nativeFormat.m_width-1;	 //
		}

		if (rect.p2.y-rect.p1.y > dst->m_nativeFormat.m_height)	 //
		{
			rect.p2.y = dst->m_nativeFormat.m_height-1;	//
		}

		if (rect.p1.y < 0)
		{
			y -= rect.p1.y;
			rect.p1.y = 0 ;
		}
		if (rect.p2.y <= rect.p1.y) 
			return;
	}
	else
	{
		if (x + (rect.p2.x - rect.p1.x)-1 > dst->m_nativeFormat.m_width-1)
		{
			rect.p2.x -= (x + m_nativeFormat.m_width-1 -  (dst->m_nativeFormat.m_width-1));
			if (rect.p2.x <= rect.p1.x) 
				return;
		}
		if (y < 0 && y + m_nativeFormat.m_height-1 >= 0)
		{
			rect.p1.y -= y;
			y = 0;
			if (rect.p2.y <= rect.p1.y) 
				return;
		}

// removed -1 from dwheight
		if (y < dst->m_nativeFormat.m_height && (y + (rect.p2.y-rect.p1.y)) > dst->m_nativeFormat.m_height)
		{
			rect.p2.y -= (y + (rect.p2.y-rect.p1.y) -  (dst->m_nativeFormat.m_height));
			if (rect.p2.y <= rect.p1.y) 
				return;
		}
	}

	unsigned char * lpSrcData = (unsigned char *) m_nativeFormat.m_lpRawData;
	unsigned char * lpDstData = (unsigned char *) dst->m_nativeFormat.m_lpDynData;

	DWORD srcBytesPerPixel = 4;
	DWORD dstBytesPerPixel = 4;

	lpDstData += (y * dst->m_nativeFormat.m_pitch) + (x * dstBytesPerPixel);
	lpSrcData += (rect.p1.y * m_nativeFormat.m_pitch) + ( rect.p1.x  * srcBytesPerPixel);

	if (m_chromaKey == TRUE)
	{
		if (m_foregroundColorSet)
		{
			for( int i = 0; i < rect.p2.y - rect.p1.y; i++)
			{
				for( int j = 0; j < rect.p2.x - rect.p1.x; j ++ )
				{
					if (*lpSrcData != 0)
					{
						for( unsigned long k = 0; k < dstBytesPerPixel; k++) lpDstData[k] = ((unsigned char *)(&m_foregroundColor))[k];
					}
					// increment the pointers by the pixel size (in bytes, obviously)
					lpSrcData += srcBytesPerPixel;
					lpDstData += dstBytesPerPixel;
				}		
				//
				// we CAN'T count on the lPitch being equal to width * bytesperpixel
				//
				lpSrcData += m_nativeFormat.m_pitch - ((rect.p2.x - rect.p1.x) * srcBytesPerPixel);
				lpDstData += dst->m_nativeFormat.m_pitch - ((rect.p2.x - rect.p1.x) * dstBytesPerPixel);
			}
		}
		else
		{
			for( int i = 0; i < rect.p2.y - rect.p1.y; i++)
			{
				for( int j = 0; j < rect.p2.x - rect.p1.x; j ++ )
				{
					if (*lpSrcData != 0)
					{
						for( unsigned long k = 0; k < dstBytesPerPixel; k++) lpDstData[k] = lpSrcData[k];
					}
						// increment the pointers by the pixel size (in bytes, obviously)
					lpSrcData += srcBytesPerPixel;
					lpDstData += dstBytesPerPixel;
				}
				//
				// we CAN'T count on the lPitch being equal to width * bytesperpixel
				//
				lpSrcData += m_nativeFormat.m_pitch - ((rect.p2.x - rect.p1.x) * srcBytesPerPixel);
				lpDstData += dst->m_nativeFormat.m_pitch - ((rect.p2.x - rect.p1.x) * dstBytesPerPixel);
			}
		}
	}
	else
	{
		if (m_foregroundColorSet)
		{
			if (m_backgroundColorSet)
			{
				for( int i = 0; i < rect.p2.y - rect.p1.y; i++)
				{
					for( int j = 0; j < rect.p2.x - rect.p1.x; j ++ )
					{
						if (*lpSrcData == 0)
						{
							for( unsigned long k = 0; k < dstBytesPerPixel; k++)
								lpDstData[k] = (BYTE)(&m_backgroundColor)[k];
						}
						else
						{
							for( unsigned long k = 0; k < dstBytesPerPixel; k++)
								lpDstData[k] = (BYTE)(&m_foregroundColor)[k];
						}
	
						// increment the pointers by the pixel size (in bytes, obviously)
						lpSrcData += srcBytesPerPixel;
						lpDstData += dstBytesPerPixel;
					}
					//
					// we CAN'T count on the lPitch being equal to width * bytesperpixel
					//
					lpSrcData += m_nativeFormat.m_pitch - ((rect.p2.x - rect.p1.x) * srcBytesPerPixel);
					lpDstData += dst->m_nativeFormat.m_pitch - ((rect.p2.x - rect.p1.x) * dstBytesPerPixel);
				}		
			}
			else
			{
				for( int i = 0; i < rect.p2.y - rect.p1.y; i++)
				{
					for( int j = 0; j < rect.p2.x - rect.p1.x; j ++ )
					{
						if (*lpSrcData == 0)
						{
							for( unsigned long k = 0; k < dstBytesPerPixel; k++)
								lpDstData[k] = lpSrcData[k];
						}
						else
						{
							for( unsigned long k = 0; k < dstBytesPerPixel; k++)
								lpDstData[k] = (BYTE)((&m_foregroundColor)[k]);
						}

						// increment the pointers by the pixel size (in bytes, obviously)
						lpSrcData += srcBytesPerPixel;
						lpDstData += dstBytesPerPixel;
					}
					//
					// we CAN'T count on the lPitch being equal to width * bytesperpixel
					//		
					lpSrcData += m_nativeFormat.m_pitch - ((rect.p2.x - rect.p1.x) * srcBytesPerPixel);
					lpDstData += dst->m_nativeFormat.m_pitch - ((rect.p2.x - rect.p1.x) * dstBytesPerPixel);
				}
			}
		}
		else
		{
			if (m_backgroundColorSet)
			{
				for( int i = 0; i < rect.p2.y - rect.p1.y; i++)
				{
					for( int j = 0; j < rect.p2.x - rect.p1.x; j ++ )
					{
						if (*lpSrcData == 0)
						{
							for( unsigned long k = 0; k < dstBytesPerPixel; k++)
								lpDstData[k] = (BYTE)((&m_backgroundColor)[k]);
						}
						else
						{
							for( unsigned long k = 0; k < dstBytesPerPixel; k++)
								lpDstData[k] = lpSrcData[k];
						}
					
						// increment the pointers by the pixel size (in bytes, obviously)
						lpSrcData += srcBytesPerPixel;
						lpDstData += dstBytesPerPixel;
					}
					//
					// we CAN'T count on the lPitch being equal to width * bytesperpixel
					//
					lpSrcData += m_nativeFormat.m_pitch - ((rect.p2.x - rect.p1.x) * srcBytesPerPixel);
					lpDstData += dst->m_nativeFormat.m_pitch - ((rect.p2.x - rect.p1.x) * dstBytesPerPixel);
				}
			}		
			else
			{
				for( int i = 0; i < rect.p2.y - rect.p1.y; i++)
				{
					for( signed long j = 0; j < rect.p2.x - rect.p1.x; j ++ )
					{
						for( unsigned long k = 0; k < dstBytesPerPixel; k++) 
							lpDstData[k] = lpSrcData[k];
					
						// increment the pointers by the pixel size (in bytes, obviously)
						lpSrcData += srcBytesPerPixel;
						lpDstData += dstBytesPerPixel;
					}
					//
					// we CAN'T count on the lPitch being equal to width * bytesperpixel
					//
					lpSrcData += m_nativeFormat.m_pitch - ((rect.p2.x - rect.p1.x) * srcBytesPerPixel);
					lpDstData += dst->m_nativeFormat.m_pitch - ((rect.p2.x - rect.p1.x) * dstBytesPerPixel);
				}
			}		
		}
	}
}

DWORD Font::GetStringPixelWidth(const char * string)
{
	if (string == NULL) 
		return 0;

	if (m_isProportional)
	{
		DWORD len = 0;
		for( unsigned long i=0; i < strlen(string); i++)
		{
			if (string[i] >= 32 && string[i] < 128)
				len += m_characterWidth[string[i]-32];
		}
		return len;
	}
	else
	{
		return strlen(string) * m_pointSizeX;
	}
}


void Font::TextOutByWord(const char * str)
{
	gosASSERT(IsValidSurface(g_textDstSurf));
	const char * word_start = str;
	const char * word_end = str;

	while (*word_start != NULL)
	{
		while(*word_end >= 32 && *word_end < 128 && *word_end != ' ' && *word_end != '\0')
		{
			word_end++;
		}
		if (*word_end != '\0') word_end++;
		static char g_TextOutByWordBuffer[128];
		memcpy( g_TextOutByWordBuffer,word_start,word_end - word_start);
		 g_TextOutByWordBuffer[word_end - word_start] = 0;
		
		if (GetStringPixelWidth( g_TextOutByWordBuffer) + g_textXY.x > (unsigned)g_textMargins.p2.x)
		{
			g_textXY.y += m_pointSizeY;
			g_textXY.x = g_textMargins.p1.x;
		}
		
		TextOut( g_TextOutByWordBuffer);

		word_start = word_end;
	}
}

