#include "pch.hpp"								

#include "DirectX.hpp"
#include "DXRasterizer.hpp"
#include "Texture Manager.hpp"
#include "Font3D_DBCS_Storage.hpp"
#include "Font3D.hpp"
#include <mbstring.h>
#include <mbctype.h>
#include "Windows.hpp"

HFONT workFont = NULL;
HFONT oldFont=NULL;
HDC gdiDC = NULL;
bool g_GDIColorChange = false;

extern HGOSHEAP Heap_Font;
extern HGOSFONT3D FontHandle;
extern int FontX;
extern int FontY;
extern DWORD FontColor;
extern bool FontProportional;
extern DWORD FontWrapType;
extern float FontMinX;
extern float FontMinY;
extern float FontMaxX;
extern float FontMaxY;
extern bool FontDisableCodes;
extern bool FontWordWrap;
extern bool FontBold;
extern bool FontItalic;
extern bool FontInPointSize;
extern float FontSize;
extern char gDefaultGDIFont[];
extern bool OddSize;
extern int LargestHeight;
bool g_InTextDrawDBCS = false;
extern gos_DBCS * g_pDBCSList;
extern BYTE UppertoLowerTable[256];

extern HGOSHEAP DefaultHeap;
extern DWORD gLanguageDLL;
extern BYTE LeadByteTable[];
extern char gApplicationLocale[MAX_PATH];

void GDIGetChrSize( DWORD * w, DWORD * h, int index);
DWORD GDIGetNextWordLen( BYTE* pText, int * byteWidth, bool * foundReturn )	;
int GDIEmbedded( BYTE* pText, bool ignore = false );
void GDICreateFont( char * string = NULL );
void GDIDrawLine(BYTE *, gos_DBCS * );
DWORD GDIGetLineLength(BYTE * pText);
void GDIGetStringHeight(BYTE * pText, DWORD * width, DWORD *height);
void GDIGetStringLen (char * msg, DWORD * w, DWORD * h);
bool HasDBCS(char * str);

void TextDrawDBCS(  char *Message )
{
	// By the time we get here, we know the font, the font size, the justification, and whether the
	// font should be in "proportional mode"
	// Embedded commands, like /color, /italic, or /bold, however, still can exist. We have to look
	// for them before we print!
	//
	// Because we have to support embedded changes to the font, we can't simply use DrawText's
	// justification routines, which sucks ass. Oh well. C'est la guerre.

	//
	// Empty message?
	//
	if (!Message || *Message==0 )
		return;

	g_InTextDrawDBCS = true;
	g_GDIColorChange = false;

	//
	// here's where we iterate through the list of gos_DBCS's to see if this string was
	// rendered in the last frame
	//

	gos_DBCS * pTmp = g_pDBCSList;
	while (pTmp)
	{
		if (pTmp->m_FontX == FontX && pTmp->m_FontY == FontY &&
			pTmp->m_FontBold == FontBold &&
			(!pTmp->embeddedColorChange || pTmp->m_color == FontColor) &&
			pTmp->m_FontSize == FontSize)
		{
			if (_mbscmp((const unsigned char *) Message, (const unsigned char *) pTmp->m_msg) == 0)
			{
				if (!pTmp->embeddedColorChange && FontColor != pTmp->m_FontColor)
					pTmp->Color( FontColor);
				pTmp->Render();
				pTmp->Color( pTmp->m_FontColor);
				FontX = float2long(pTmp->m_doneFontX);
				FontY = float2long(pTmp->m_doneFontY);

				g_InTextDrawDBCS = false;
				return;
			}
		}
		pTmp = pTmp->m_pNext;
	}


	// We're creating a new instance of GDI text. We'll need to set a few things up.
	//
	// the region...
	int weWantFontX = FontX;
	int weWantFontY = FontY;

    // Get the HDC of the back buffer so we can do DrawText calc's to it
	gdiDC = DesktopDC;
	oldFont=0;
	
	DWORD calcWidth=0, calcHeight=0;
 	GDIGetStringLen(Message, &calcWidth, &calcHeight);

	switch(FontWrapType)
	{
	case 1:
		calcWidth = float2long(((FontMaxX - FontMinX)));
		break;
	case 2:
	case 3:
		calcWidth = float2long(((FontMaxX - FontMinX)))	;
	}

	GDICreateFont(Message);

	SelectObject(gdiDC, oldFont);

	pTmp = new (Heap_Font) gos_DBCS( Message, calcWidth, calcHeight, g_GDIColorChange );
	pTmp->m_FontSize = FontSize;
	pTmp->m_FontBold = FontBold;
	pTmp->m_FontColor = FontColor;
	pTmp->m_FontX = (float) FontX;
	pTmp->m_FontY = (float) FontY;
	pTmp->m_beginFontX = 0;
	pTmp->m_beginFontY = 0;

	if (pTmp->m_surf)
	{
		wGetDC( pTmp->m_surf->m_lpdds7,&gdiDC);

		oldFont=(HFONT)SelectObject(gdiDC, workFont);

		SetBkColor  (gdiDC, RGB(0,   0,   0  ));
		SetBkMode ( gdiDC, TRANSPARENT );

		if (g_GDIColorChange)
		{
			if (!(FontColor & 0xffffff))
				SetTextColor(gdiDC, RGB( 1,1,1 ) );
			else
				SetTextColor(gdiDC, RGB( (FontColor & 0xff0000)>>16 , (FontColor & 0xff00) >> 8, FontColor & 0xff) );
		}		
		else
		{
			SetTextColor(gdiDC, RGB(255,255,255));
		}

		GDIDrawLine((BYTE *)Message, pTmp);

		SelectObject(gdiDC, oldFont);

		wReleaseDC( pTmp->m_surf->m_lpdds7, gdiDC );

		pTmp->Update();

		if (weWantFontX < FontMinX)
		{
			FontX = float2long(FontMinX);
			weWantFontX = FontX;
		}

		pTmp->ShiftCoordinates((float) weWantFontX + pTmp->m_beginFontX,(float) weWantFontY + pTmp->m_beginFontY);
		pTmp->Render();
	}

	DeleteObject(workFont);
	workFont = NULL;

	FontX += pTmp->m_beginFontX;
	FontY += pTmp->m_beginFontY;
	pTmp->m_doneFontX = (float) FontX;
	pTmp->m_doneFontY = (float) FontY;

	g_InTextDrawDBCS = false;
	gdiDC = 0;
}


//
// Returns the pixel length of the next word
//
DWORD GDIGetNextWordLen( BYTE* pText, int * byteWidth, int * bytePositionChange, bool * foundReturn )
{
	DWORD Width,Height,Len = 0;
	DWORD aSpace;
	*foundReturn = false;
	*byteWidth = 0;
	*bytePositionChange = 0;
	GDIGetChrSize( &aSpace, &Height, ' ' );

	float FontSizeTmp = FontSize;
	bool OddSizeTmp = OddSize;
	FontInfo * FontHandleTmp = FontHandle;
	LargestHeight = 0;
	int add = 0;
	while( (add = GDIEmbedded( pText)) != 0 )
	{
		*bytePositionChange += add;
		pText+=add;
	}
	
	if (*pText == 0x0d  )
	{
		*byteWidth += 1;
		if (*(pText+1) == 0x0a)
		{
			*byteWidth += 1;
		}
		*foundReturn = true;
		return Len;
	}
	else
	if (*(pText) == 0x0a)
	{
		*byteWidth += 1;
		*foundReturn = true;
		return Len;
	}
	else
	while( *pText!=' ' || (*pText == 0x0d || *pText == 0x0a))
	{
		if (*pText == 0x0d || *pText == 0x0a)
		{
			FontHandle = FontHandleTmp;
			FontSize = FontSizeTmp;
			OddSize = OddSizeTmp;
			return Len;
		}
		if (*pText == 0)
		{
			*byteWidth = (*byteWidth) - 1;
			break;
		}
		if (*pText=='/' && GDIEmbedded(pText, true) != 0)
		{
			*byteWidth = (*byteWidth) - 1;
			break;
		}
		int character = *pText;
        int nChrBytes = 1;
		if (pText[1] && LeadByteTable[(unsigned char) *pText]) // jcem - check last-byte + '\0' char 
		{
			character = character << 8;
			character += *(pText+1);
            nChrBytes++;
		}
		GDIGetChrSize( &Width, &Height, character );
		*byteWidth = *byteWidth + 1 + (pText[1] && LeadByteTable[(unsigned char) *pText]); // jcem - check last-byte + '\0' char 
		pText = &pText[nChrBytes]; // _mbsinc() => jcem - check last-byte + '\0' char 
		if (Height > LargestHeight)
			LargestHeight = Height;
		Len+=Width;
	}
	if (*pText == ' ')
		Len += aSpace;
	*byteWidth += 1;
	*bytePositionChange = (*bytePositionChange);
	FontHandle = FontHandleTmp;
	FontSize = FontSizeTmp;
	OddSize = OddSizeTmp;
	return Len;
}

void GDIGetChrSize( DWORD * w, DWORD * h, int index)
{
	ABC abc;

	GetCharABCWidths(gdiDC, index, index, &abc);
	*w = abc.abcA + abc.abcB + abc.abcC;
	*h = (int) float2long(FontSize);
}

void GDIDrawLine(BYTE * text, gos_DBCS * dbcs)
{
	int pixelsUsed = 0;
	bool foundReturn = false;
	int byteslen = 0;
	int byteschange = 0 ;
	int pixelsAvail = float2long(FontMaxX - FontMinX);
	int pixelsWide = GDIGetNextWordLen(text, &byteslen, &byteschange, &foundReturn);
	DWORD pixelsOffsetFromTop = 0;
	DWORD width = 0;

	if (FontWrapType == 3)
	{
		GDIGetStringHeight(text,&width, &pixelsOffsetFromTop);
		pixelsOffsetFromTop /= 2;
	 	pixelsOffsetFromTop = float2long((((FontMaxY-FontMinY)/2)-((float)pixelsOffsetFromTop))-1);
	}


	if (FontY < FontMinY)
	{
		dbcs->m_beginFontY = float2long(FontMinY-FontY);
	}

	while (byteslen)
	{
		//if (FontWordWrap)
		int pixelsUsedInLine = 0;
		switch(FontWrapType)
		{
		case 0: // left
			if (FontWordWrap)
				FontX = float2long(FontMinX);
			break;
		case 1: // right
			pixelsUsedInLine = GDIGetLineLength(text+byteschange);
			FontX = float2long((FontMaxX-pixelsUsedInLine));
			break;
		case 2: // center
			pixelsUsedInLine = GDIGetLineLength(text+byteschange);
			FontX = (int) (FontMinX+(((FontMaxX-FontMinX)-pixelsUsedInLine)/2));
			break;
		case 3: // center h/v
			pixelsUsedInLine = GDIGetLineLength(text+byteschange);
			FontX = (int) (FontMinX+(((FontMaxX-FontMinX)-pixelsUsedInLine)/2));
			break;
		}

		if (!FontWordWrap)
		{
			// here's where to put nowrap code.
//
// Jim -2 make it line up with .d3f
//
//			RECT rc = {0,float2long(FontY-dbcs->m_FontY-2), Environment.screenWidth, float2long(FontMaxY-FontMinY)};
			RECT rc = {0,float2long(FontY-dbcs->m_FontY), Environment.screenWidth, float2long(FontMaxY-FontMinY)};
			switch(FontWrapType)
			{
			case 0:
//				FontX -= FontMinX;
				if (FontX < FontMinX)
					rc.left -= float2long(FontMinX - FontX);
				break;
			case 1:
				rc.left = dbcs->m_width - pixelsUsedInLine ;
				break;
			case 2:
				rc.left = dbcs->m_width/2 - pixelsUsedInLine/2 ;
				dbcs->m_beginFontX = 0;
				break;
			case 3:
				rc.left = dbcs->m_width/2 - pixelsUsedInLine/2;
				dbcs->m_beginFontX = 0;
				break;										 			
			}
			pixelsWide = GDIGetNextWordLen(text, &byteslen, &byteschange, &foundReturn);
			foundReturn = false;

			//if (FontX < FontMinX)
			//	rc.left -= float2long(FontMinX-FontX);

			//if (FontY < FontMinY)
			//	rc.top -= float2long(FontMinY-FontY);

			while (byteslen && !foundReturn)
			{
				DrawText( gdiDC, (char *) text+byteschange,  byteslen, &rc, DT_NOPREFIX );
				FontX += pixelsWide;
				rc.left += pixelsWide;
				pixelsUsed  += pixelsWide;
				text += byteschange+byteslen;
				pixelsWide = GDIGetNextWordLen(text, &byteslen, &byteschange, &foundReturn);
			}

			if (foundReturn)
			{
				FontX = 0;
				FontY += float2long(FontSize);
			}

			FontY += pixelsOffsetFromTop;
			dbcs->m_beginFontY += pixelsOffsetFromTop;
			return;
		}
		RECT rc;
		if (dbcs->m_FontY >= FontMinY)
		{
			rc.left	= float2long(FontX-FontMinX);
			rc.top = float2long(FontY-dbcs->m_FontY);
			rc.right = Environment.screenWidth;
			rc.bottom =	float2long(FontMaxY-FontMinY);
		}
		else
		{
			rc.left	= float2long(FontX-FontMinX);
			rc.top = float2long(FontY-FontMinY);
			rc.right = Environment.screenWidth;
			rc.bottom =	float2long(FontMaxY-FontMinY);
		}

		foundReturn = false;
		pixelsWide = GDIGetNextWordLen(text, &byteslen, &byteschange, &foundReturn);

		if (pixelsWide > pixelsAvail)
		{
			// do something
			DWORD w,h;
			do
			{
				int character = *text;
				if (text[1] && LeadByteTable[(unsigned char) *text]) // jcem - check last-byte + '\0' char 
				{
					character = character << 8;
					character += *(text+1);
				}
				GDIGetChrSize(&w,&h,character);

				if (w +FontX > FontMaxX)
				{
					break;
				}
				else
				{

					if (text[1] && LeadByteTable[(unsigned char) *text]) // jcem - check last-byte + '\0' char 
					{
						DrawText(gdiDC, (char *) text, 2, &rc, DT_NOPREFIX);
						text += 2;
					}
					else
					{
						DrawText(gdiDC, (char *) text, 1, &rc, DT_NOPREFIX);
						text += 1;
					}
					FontX += w;
					rc.left += w;
					pixelsUsed += w;
				}
			} while (1);
		}

		while (byteslen && (pixelsUsed + pixelsWide <= pixelsAvail) && !foundReturn)
		{
			DrawText( gdiDC, (char *) text+byteschange,  byteslen, &rc, DT_NOPREFIX );
			FontX += pixelsWide;
			rc.left += pixelsWide;
			pixelsUsed  += pixelsWide;
			text += byteschange+byteslen;
			pixelsWide = GDIGetNextWordLen(text, &byteslen, &byteschange, &foundReturn);
			if (pixelsWide == 0)
				text += byteschange;

		}

		if (pixelsUsed == 0 && pixelsWide > pixelsAvail)
		{
			pixelsUsed  += pixelsWide;
			text += byteschange+byteslen;
			pixelsWide = GDIGetNextWordLen(text, &byteslen, &byteschange, &foundReturn);
		}
		if (foundReturn)
			text++;
		if (pixelsUsed >= pixelsAvail && FontWordWrap)
			FontX = float2long(FontMinX);
		FontY += float2long(FontSize);
		pixelsUsed = 0;
	}
	FontY -= float2long(FontSize);

	FontY += pixelsOffsetFromTop;
	dbcs->m_beginFontY += pixelsOffsetFromTop;

}

//
// Am I sitting on a special code? If so, how many characters should I move ahead?
//
int GDIEmbedded( BYTE* pText, bool ignore )
{
	if( FontDisableCodes )
		return 0;

	if( *pText=='/' )
	{
		if( *(pText+1)=='/' )
			return 1;
		else
		if( 0==strnicmp( "color=", (char*)pText+1, 6 ) )
		{
			if (!ignore)
			{
				pText+=7;
				DWORD Color=0;
				for( int t0=0; t0<8; t0++ )
				{
					Color<<=4;
					DWORD Tchr=UppertoLowerTable[(*pText++)];
					if( Tchr>='0' && Tchr<='9' || Tchr>='a' && Tchr<='f' )
					{
						Tchr-='0';
						if( Tchr>9 )
							Tchr-=('a'-'9'-1);
						Color+=Tchr;
					}
					else
					{
#ifdef _DEBUG
						STOP(( "Bad color - /color=AARRGGBB in hex" ));
#endif
					}		
				}
				if (!(Color & 0xffffff))
				{
					Color = Color + 0x010101;
					SetTextColor(gdiDC, RGB( 1,1,1 ) );
				}
				else
					SetTextColor(gdiDC, RGB( (Color&0xff0000)>>16, (Color&0xff00)>>8, (Color&0xff)) );

				FontColor=Color;
			}
			g_GDIColorChange = true;
			return 15;
		}
		else
		if( 0==strnicmp( "bold=0", (char*)pText+1, 6 ) )
		{
			if (!ignore)
			{
				FontBold = 0;
				GDICreateFont();
			}
			return 7;
		}
		else
		if( 0==strnicmp( "bold=1", (char*)pText+1, 6 ) )
		{
			if (!ignore)
			{
				FontBold = 1;
				GDICreateFont();
			}
			return 7;
		}
		else
		if( 0==strnicmp( "proportional=1", (char*)pText+1, 14 ) )
		{
			if (!ignore)
			{
				FontProportional = 1;
			}
			return 15;
		}
		else
		if( 0==strnicmp( "proportional=0", (char*)pText+1, 14 ) )
		{
			if (!ignore)
			{
				FontProportional = 0;
			}
			return 15;
		}
		else
		if( 0==strnicmp( "italic=0", (char*)pText+1, 8 ) )
		{
			if (!ignore)
			{
				FontItalic = false;
				GDICreateFont();
			}
			return 9;
		}
		else
		if( 0==strnicmp( "italic=1", (char*)pText+1, 8 ) )
		{
			if (!ignore)
			{
				FontItalic = true;
				GDICreateFont();
			}
			return 9;
		}
	}
	return 0;
}

DWORD GDIGetLineLength(BYTE * pText)
{
	int pixelsUsed = 0;
	int byteslen = 0;
	int byteschange = 0 ;
	int pixelsAvail = (int) (FontMaxX - FontMinX);
	bool foundReturn =false;
	int pixelsWide = GDIGetNextWordLen(pText, &byteslen, &byteschange, &foundReturn);
	if (*pText == 0x0d ||*pText == 0x0a)
		return pixelsWide;
	
	while (byteslen && (!FontWordWrap || (FontWordWrap &&pixelsUsed + pixelsWide <= pixelsAvail)) && !foundReturn)
	{
		pixelsUsed  += pixelsWide;
		pText += byteschange+byteslen;
		pixelsWide = GDIGetNextWordLen(pText, &byteslen, &byteschange, &foundReturn);
	}

	if ((pixelsUsed == 0 && pixelsWide > pixelsAvail) || foundReturn)
	{
		pixelsUsed  += pixelsWide;
	}

	FontX = (int) FontMinX;

	return pixelsUsed;
}

void GDIGetStringHeight(BYTE * pText, DWORD * width, DWORD *height)
{
	int pixelsUsed = 0;
	int byteslen = 0;
	int byteschange = 0 ;
	bool foundReturn = false;

	int pixelsAvail = (int) (FontMaxX - FontMinX);
	float FontYPlaceholder = (float) FontY;
	int pixelsWide = GDIGetNextWordLen(pText, &byteslen, &byteschange, &foundReturn);
	int widest = 0;

	while (byteslen)
	{
		RECT rc = {0,(int) (FontYPlaceholder-FontMinY), Environment.screenWidth, Environment.screenHeight};
		if (pixelsWide > pixelsAvail)
		{
			DWORD  h,w;
			int character = 0;
			do
			{
				character = *pText;
				if (pText[1] && LeadByteTable[(unsigned char) *pText]) // jcem - check last-byte + '\0' char 
				{
					character = character << 8;
					character += *(pText+1);
				}
				GDIGetChrSize( &w, &h, character );

				if (pixelsUsed + w < pixelsAvail)
				{
					pixelsUsed += w;
					if (pText[1] && LeadByteTable[(unsigned char) *pText])
					{
						pText += 2;
						byteslen -= 2;
					}
					else
					{
						pText += 1;
						byteslen -= 1;
					}
				}
				else
				{
					break;
				}
			} while(byteslen);
		}

		while (byteslen && (!FontWordWrap || (FontWordWrap && (pixelsUsed + pixelsWide <= pixelsAvail))) && !foundReturn)
		{
			rc.left += pixelsWide;

			pixelsUsed  += pixelsWide;
			if (pixelsUsed > pixelsAvail)
				pixelsUsed = pixelsAvail;

			if (pixelsUsed > widest)
				widest = pixelsUsed;

			pText += byteschange+byteslen;
			pixelsWide = GDIGetNextWordLen(pText, &byteslen, &byteschange, &foundReturn);
		}

		pixelsUsed += pixelsWide;
		if (pixelsUsed > pixelsAvail)
			pixelsUsed = pixelsAvail;

		if (pixelsUsed > widest)
			widest = pixelsUsed;



		FontYPlaceholder += float2long(FontSize);
		pixelsUsed = 0;
		foundReturn = false;
	}
	//
	// Take the actual height and add 1 to account for scaling...
	//
//
//
//
//	*height = (DWORD) (FontYPlaceholder - FontY);
	*height = (DWORD) (FontYPlaceholder - FontY) + 1;
	*width = widest;
	return ;
}


void GDICreateFont( char * string )
{
	if( oldFont )
		SelectObject(gdiDC, oldFont);

	if (workFont)
		DeleteObject(workFont);
	//
	// Create a font of the proper size...
	//
    LOGFONT lf;
	memset(&lf, 0, sizeof(lf));
//
// Jim - I altered this line to make the fonts look normal again
//
	lf.lfHeight =  -float2long(FontSize * 2.0f /3.0f * (4.0f/3.0f));
//	lf.lfHeight =  float2long(FontSize);
	lf.lfWeight = FontBold ? FW_BOLD : FW_NORMAL;
	lf.lfItalic = FontItalic;
	lf.lfCharSet = DEFAULT_CHARSET;
	lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
	lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
	if (g_GDIColorChange)
		lf.lfQuality = 0;
	else
		lf.lfQuality = ANTIALIASED_QUALITY ;
	lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;

	if (!FontHandle || FontHandle->hFontTTF == 0)
	{
		// use default GDI font in this case
		strncpy(lf.lfFaceName, gDefaultGDIFont, strlen(gDefaultGDIFont)-4);
	}
	else
		strncpy(lf.lfFaceName, FontHandle->FontFile, strlen(FontHandle->FontFile)-4);

	if (string && HasDBCS(string))
	{
		if (strcmp(gApplicationLocale, "English") == 0 &&
			GetACP() == 932 )
		{
			// rely on the automatic font association
			strcpy(lf.lfFaceName, "");
		}
	}

	workFont = CreateFontIndirect(&lf);
	oldFont=(HFONT)SelectObject(gdiDC, workFont);
}

void GDIGetStringLen (char * msg, DWORD * w, DWORD * h)
{

	HDC aDC = gdiDC;
	bool tmpFontBold = FontBold;
	bool tmpFontItalic = FontItalic;
	DWORD tmpFontColor = FontColor;
	float tmpFontSize = FontSize;
	HFONT aFont = workFont;
	HFONT tFont = oldFont;
	gdiDC = DesktopDC;
	oldFont = 0;
	workFont = 0;
	GDICreateFont(msg);
	GDIGetStringHeight((BYTE*)msg, w, h);
	SelectObject(gdiDC, oldFont);
	gdiDC = aDC;
	DeleteObject(workFont);
	workFont = aFont;
	oldFont = tFont;

	FontBold = tmpFontBold;
	FontItalic = tmpFontItalic;
	FontColor = tmpFontColor;
	FontSize = tmpFontSize;
	return;
}

bool HasDBCS(char * str)
{
	unsigned char * itr = (unsigned char *) str;
	if (!itr)
		return false;
	while (*itr)
	{
		if (itr[1] && LeadByteTable[*itr]) // jcem - check last-byte + '\0' char 
			return true;
		itr++;
	}
	return false;
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//	All of the routines with MW4HUD as the prefix and for the hud in MechWarrior4 only
//			if they are used by anything else the results are unexpected.
//			Andrew Farrier (afarrier)
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void MW4HUD_GDICreateFont( char * string ,int size);
gos_DBCS *MW4HUD_TextDrawDBCS(  char *Message,int size,bool dorender );
extern DWORD gDisableText;

gos_DBCS *MW4HUD_gos_TextStringLength (DWORD* w,DWORD* h,char *Message,int size)
{
	gos_DBCS *toret;
	toret = MW4HUD_TextDrawDBCS (Message,size,false);
	if (toret)
	{
		if (w)
			*w = toret->m_width;
		if (h)
			*h = toret->m_height;
	}
	return toret;
}

void MW4HUD_GDIGetStringLen (char * msg, DWORD * w, DWORD * h,int size)
{

	HDC aDC = gdiDC;
	bool tmpFontBold = FontBold;
	bool tmpFontItalic = FontItalic;
	DWORD tmpFontColor = FontColor;
	float tmpFontSize = FontSize;
	HFONT aFont = workFont;
	HFONT tFont = oldFont;
	gdiDC = DesktopDC;
	oldFont = 0;
	workFont = 0;
	MW4HUD_GDICreateFont(msg,size);
	GDIGetStringHeight((BYTE*)msg, w, h);
	SelectObject(gdiDC, oldFont);
	gdiDC = aDC;
	DeleteObject(workFont);
	workFont = aFont;
	oldFont = tFont;

	FontBold = tmpFontBold;
	FontItalic = tmpFontItalic;
	FontColor = tmpFontColor;
	FontSize = tmpFontSize;
	return;
}

gos_DBCS *MW4HUD_TextDrawDBCS(  char *Message,int size,bool dorender )
{
	// Because we have to support embedded changes to the font, we can't simply use DrawText's
	// justification routines, which sucks ass. Oh well. C'est la guerre.

	//
	// Empty message?
	//
	if (!Message || *Message==0 )
		return NULL;
//
//
//
	#ifdef LAB_ONLY
	if( gDisableText )
		return NULL;
	#endif

    bool bAutoChangeSize;
    if (size <= -1000) { // jcem
        size += 1000;
        bAutoChangeSize = false; 
    } else {
        bAutoChangeSize = true;
    }

	g_InTextDrawDBCS = true;
	g_GDIColorChange = false;

	//
	// here's where we iterate through the list of gos_DBCS's to see if this string was
	// rendered in the last frame
	//

	gos_DBCS * pTmp = g_pDBCSList;
	while (pTmp)
	{
//		if (pTmp->m_FontX == FontX && pTmp->m_FontY == FontY &&
		if (pTmp->m_FontBold == FontBold &&
			(!pTmp->embeddedColorChange || pTmp->m_color == FontColor) &&
			pTmp->m_FontSize == size)
		{
			if (_mbscmp((const unsigned char *) Message, (const unsigned char *) pTmp->m_msg) == 0)
			{
				if (!pTmp->embeddedColorChange && FontColor != pTmp->m_FontColor)
					pTmp->Color( FontColor);
				float dx,dy;
				float TOffset=gos_GetMachineInformation(gos_Info_TextureOffset) ? 0.0f : 0.5f;
//				float tx,ty;
//				tx = pTmp->m_LastFontX;
//				ty = pTmp->m_LastFontY;
				dx = (FontX) - pTmp->m_FontX + TOffset;
				dy = (FontY) - pTmp->m_FontY + TOffset - pTmp->m_surf->m_offsety;
//				dx = (FontX+pTmp->m_beginFontX) - pTmp->m_LastFontShiftX;
//				dy = (FontY+pTmp->m_beginFontY) - pTmp->m_LastFontShiftY;

				pTmp->ShiftCoordinates((float) dx,(float) dy);
//				pTmp->m_LastFontShiftX = tx - dx;
//				pTmp->m_LastFontShiftY = ty - dy;
				pTmp->m_FontX = (float) FontX;
				pTmp->m_FontY = (float) FontY;
				if (dorender)
					pTmp->Render();
				pTmp->Color( pTmp->m_FontColor);
				FontX = float2long(pTmp->m_doneFontX);
				FontY = float2long(pTmp->m_doneFontY);

				g_InTextDrawDBCS = false;
				return pTmp;
			}
		}
		pTmp = pTmp->m_pNext;
	}


	// We're creating a new instance of GDI text. We'll need to set a few things up.
	//
	// the region...
	int weWantFontX = FontX;
	int weWantFontY = FontY;

    // Get the HDC of the back buffer so we can do DrawText calc's to it
	gdiDC = DesktopDC;
	oldFont=0;
	
	float oldsize = FontSize;
    if (bAutoChangeSize)
	FontSize = size * -1.333f;				// to correct for funky math

	DWORD calcWidth=0, calcHeight=0;
 	MW4HUD_GDIGetStringLen(Message, &calcWidth, &calcHeight,size);

	switch(FontWrapType)
	{
	case 1:
		calcWidth = float2long(((FontMaxX - FontMinX)));
		break;
	case 2:
	case 3:
		calcWidth = float2long(((FontMaxX - FontMinX)))	;
	}

	MW4HUD_GDICreateFont(Message,size);

	SelectObject(gdiDC, oldFont);

	pTmp = new (Heap_Font) gos_DBCS( Message, calcWidth, calcHeight, g_GDIColorChange );
	pTmp->m_FontSize = (float) size;
	pTmp->m_FontBold = FontBold;
	pTmp->m_FontColor = FontColor;
	pTmp->m_FontX = (float) FontX;
	pTmp->m_FontY = (float) FontY;
	pTmp->m_beginFontX = 0;
	pTmp->m_beginFontY = 0;

	if (pTmp->m_surf)
	{
		wGetDC( pTmp->m_surf->m_lpdds7,&gdiDC);

		oldFont=(HFONT)SelectObject(gdiDC, workFont);

		SetBkColor  (gdiDC, RGB(0,   0,   0  ));
		SetBkMode ( gdiDC, TRANSPARENT );

		if (g_GDIColorChange)
		{
			if (!(FontColor & 0xffffff))
				SetTextColor(gdiDC, RGB( 1,1,1 ) );
			else
				SetTextColor(gdiDC, RGB( (FontColor & 0xff0000)>>16 , (FontColor & 0xff00) >> 8, FontColor & 0xff) );
		}		
		else
		{
			SetTextColor(gdiDC, RGB(255,255,255));
		}

		GDIDrawLine((BYTE *)Message, pTmp);

		SelectObject(gdiDC, oldFont);

		wReleaseDC( pTmp->m_surf->m_lpdds7, gdiDC );

		pTmp->Update();

		if (weWantFontX < FontMinX)
		{
			FontX = float2long(FontMinX);
			weWantFontX = FontX;
		}


		pTmp->ShiftCoordinates((float) weWantFontX + pTmp->m_beginFontX,(float) weWantFontY + pTmp->m_beginFontY);
		if (dorender)
			pTmp->Render();
	}
	else
	{
		DeleteObject(workFont);
		workFont = NULL;
		delete pTmp;
		FontSize = oldsize;
		return NULL;
	}

	DeleteObject(workFont);
	workFont = NULL;

	FontX += pTmp->m_beginFontX;
	FontY += pTmp->m_beginFontY;
	pTmp->m_doneFontX = (float) FontX;
	pTmp->m_doneFontY = (float) FontY;

	g_InTextDrawDBCS = false;
	gdiDC = 0;
	FontSize = oldsize;
	return pTmp;
}


void MW4HUD_GDICreateFont( char * string,int size )
{
	if( oldFont )
		SelectObject(gdiDC, oldFont);

	if (workFont)
		DeleteObject(workFont);
	//
	// Create a font of the proper size...
	//
    LOGFONT lf;
	memset(&lf, 0, sizeof(lf));
//
// Jim - I altered this line to make the fonts look normal again
//
//	lf.lfHeight =  -float2long(FontSize * 2.0f /3.0f * (4.0f/3.0f));
	lf.lfHeight =  size;
	lf.lfWeight = FW_NORMAL;
//	lf.lfWeight = FontBold ? FW_BOLD : FW_NORMAL;
	lf.lfItalic = FontItalic;
	lf.lfCharSet = DEFAULT_CHARSET;
	lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
	lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
//	if (g_GDIColorChange)
//		lf.lfQuality = 0;
//	else
	lf.lfQuality = ANTIALIASED_QUALITY ;
	lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;

	if (!FontHandle || FontHandle->hFontTTF == 0)
	{
		// use default GDI font in this case
		strncpy(lf.lfFaceName, gDefaultGDIFont, strlen(gDefaultGDIFont)-4);
	}
	else
		strncpy(lf.lfFaceName, FontHandle->FontFile, strlen(FontHandle->FontFile)-4);

	if (string && HasDBCS(string))
	{
		if (strcmp(gApplicationLocale, "English") == 0 &&
			GetACP() == 932 )
		{
			// rely on the automatic font association
			strcpy(lf.lfFaceName, "");
		}
	}

	workFont = CreateFontIndirect(&lf);
	oldFont=(HFONT)SelectObject(gdiDC, workFont);
}


