view GUIFont.cpp @ 812:9d2b911ef526

Fixed some odm terrain collision glitches.
author Nomad
date Tue, 26 Mar 2013 06:34:44 +0200
parents c0bfb386b15f
children 502b8b2e36b4
line wrap: on
line source

#include <string>
#include <assert.h>

#include "LOD.h"
#include "GUIFont.h"
#include "GUIWindow.h"
#include "Render.h"

#include "mm7_data.h"


extern LODFile_IconsBitmaps *pIcons_LOD;


struct GUIFont *pAutonoteFont;
struct GUIFont *pSpellFont;
struct GUIFont *pFontArrus;
struct GUIFont *pFontLucida;
struct GUIFont *pBook2Font;
struct GUIFont *pBookFont;
struct GUIFont *pFontCreate;
struct GUIFont *pFontCChar;
struct GUIFont *pFontComic;
struct GUIFont *pFontSmallnum;

char temp_string[2048];

char pTmpBuf3[10000];

//----- (0044C448) --------------------------------------------------------
GUIFont *LoadFont(const char *pFontFile, const char *pFontPalette, ...)
{
	
	int pallete_index; // eax@3
	GUIFont *pFont;
	unsigned int palletes_count =0;
	va_list palettes_ptr;

	pFont = (GUIFont *)pIcons_LOD->LoadRaw(pFontFile, 0);
	va_start(palettes_ptr, pFontFile);

	while  (NULL!=(pFontPalette=va_arg(palettes_ptr, const char *)))
		{
		pallete_index =pIcons_LOD->LoadTexture(pFontPalette, TEXTURE_16BIT_PALETTE);
		if (pallete_index == -1)
			{
			wsprintfA(pTmpBuf, "Unable to open %s", pFontPalette);
			Abortf(pTmpBuf);
			}	
		pFont->pFontPalettes[palletes_count] = pIcons_LOD->pTextures[pallete_index].pPalette16;
		++palletes_count;
		}
	va_end(palettes_ptr);
	pFont->palletes_count = palletes_count;
	return pFont;
	}



//----- (0044D2FD) --------------------------------------------------------
void GUIFont::_44D2FD_prolly_draw_credits_entry(GUIFont *pFont, int Str, int a4, unsigned int w, unsigned int h, unsigned __int16 a7, unsigned __int16 a8, const char *pString, unsigned __int16 *pPixels, unsigned int uPixelsWidth)
{
  int v11; // ebx@1
  int v12; // edi@1
  char *v13; // eax@1
  char *v14; // eax@1
  unsigned __int16 *v15; // esi@1
  GUIFont *v16; // edi@4
  signed int v17; // ecx@4
  signed int v18; // eax@6
  int v19; // [sp+Ch] [bp-5Ch]@1
  int v20; // [sp+10h] [bp-58h]@1
  unsigned int v21; // [sp+14h] [bp-54h]@1
  unsigned int v22; // [sp+18h] [bp-50h]@1
  unsigned int v23; // [sp+1Ch] [bp-4Ch]@1
  unsigned int v24; // [sp+20h] [bp-48h]@1
  GUIFont *v25; // [sp+60h] [bp-8h]@1
  GUIFont *v26; // [sp+64h] [bp-4h]@1
  char *Stra; // [sp+70h] [bp+8h]@1
  int a4a; // [sp+74h] [bp+Ch]@4
  int a7a; // [sp+80h] [bp+18h]@2

  v11 = a7;
  v22 = h;
  v12 = Str;
  v26 = this;
  v24 = a4 + h - 1;
  v21 = w;
  v25 = pFont;
  v23 = Str + w - 1;
  ui_current_text_color = a7;
  v19 = Str;
  v20 = a4;
  v13 = GUIFont::_44C933(pString, this, pFont, (int)&v19, 0, 1);
  v14 = strtok(v13, "\n");
  Stra = v14;
  v15 = &pPixels[uPixelsWidth * a4];
  if ( v14 )
  {
    a7a = v12 >> 1;
    while ( 1 )
    {
      v16 = v26;
      ui_current_text_color = v11;
      v17 = 0;
      a4a = v11;
      if ( *v14 == '_' )
      {
        v16 = v25;
        a4a = a8;
        ui_current_text_color = a8;
        v17 = 1;
      }
      v18 = (signed int)(w - v16->GetLineWidth(&v14[v17])) >> 1;
      if ( v18 < 0 )
        v18 = 0;
      v16->_44D0B5(a4a, a8, (int)&v15[v18 + a7a], Stra, uPixelsWidth);
      v15 += uPixelsWidth * (LOBYTE(v16->uFontHeight) - 3);
      Stra = strtok(0, "\n");
      if ( !Stra )
        break;
      v14 = Stra;
    }
  }
}
// 5C6DB4: using guessed type int ui_current_text_color;


//----- (0044D1E7) --------------------------------------------------------
void GUIFont::DrawTextLine(unsigned int uDefaultColor, signed int uX, signed int uY, const char *Str, int a6)
{
  size_t v6; // ebx@1
  GUIFont *pFont; // esi@1
  signed int v8; // edi@3
  unsigned __int8 v9; // cl@4
  int v10; // eax@5
  int v11; // ecx@5
  int v12; // ecx@6
  int v13; // ecx@7
  int v14; // ecx@9
  unsigned int v15; // edx@9
  unsigned __int16 v16; // cx@12
  unsigned __int8 *v17; // eax@12
  char Dest[20]; // [sp+Ch] [bp-1Ch]@16
  //char v19; // [sp+11h] [bp-17h]@16
  size_t v20; // [sp+20h] [bp-8h]@2
  int v21; // [sp+24h] [bp-4h]@1
  int uXa; // [sp+30h] [bp+8h]@9

  v6 = 0;
  v21 = uDefaultColor;
  pFont = this;
  if ( Str )
  {
    v21 = ui_current_text_color;
    v20 = strlen(Str);
    if ( (signed int)v20 > 0 )
    {
      v8 = uX;
      do
      {
        if ( pFont->IsCharValid(v9 = Str[v6]) )
        {
          v10 = v9;
          v11 = v9 - 9;
          if ( v11 )
          {
            v12 = v11 - 1;
            if ( !v12 )
              return;
            v13 = v12 - 2;
            if ( v13 )
            {
              if ( v13 != 1 )
              {
                v14 = 3 * v10 + 9;
                v15 = *((int *)&pFont->cFirstChar + v14);
                uXa = *((int *)&pFont->cFirstChar + v14);
                if ( v15 )
                {
                  if ( (signed int)v6 > 0 )
                    v8 += pFont->pMetrics[v10].uLeftSpacing;
                  v16 = v21;
                  v17 = (unsigned __int8 *)((char *)&pFont[1] + pFont->field_C20[v10]);
                  if ( !v21 )
                    v16 = -1;
                  pRenderer->DrawText(v8, uY, v17, v15, pFont->uFontHeight, pFont->pFontPalettes[0], v16, 0);
                  v8 += uXa;
                  if ( (signed int)v6 < (signed int)v20 )
                    v8 += pFont->pMetrics[(unsigned __int8)Str[v6]].uRightSpacing;
                }
              }
            }
            else
            {
              strncpy(Dest, &Str[v6 + 1], 5u);
              Dest[5] = 0;
              v21 = atoi(Dest);
              ui_current_text_color = v21;
              v6 += 5;
            }
          }
        }
        ++v6;
      }
      while ( (signed int)v6 < (signed int)v20 );
    }
  }
}
// 5C6DB4: using guessed type int ui_current_text_color;


//----- (0044D0B5) --------------------------------------------------------
void GUIFont::_44D0B5(int a2, int a3, int a4, const char *pString, int a6)
{
  int v6; // ebx@1
  GUIFont *v7; // esi@1
  int v8; // edi@3
  unsigned __int8 v9; // cl@4
  int v10; // eax@5
  int v11; // ecx@5
  int v12; // ecx@6
  int v13; // ecx@7
  int v14; // ecx@8
  int v15; // ebx@10
  int v16; // edx@13
  __int16 v17; // ax@13
  char Dest; // [sp+Ch] [bp-20h]@17
  char v19; // [sp+11h] [bp-1Bh]@17
  size_t v20; // [sp+20h] [bp-Ch]@2
  int v21; // [sp+24h] [bp-8h]@1
  int v22; // [sp+28h] [bp-4h]@2
  const char *v23; // [sp+38h] [bp+Ch]@4

  v6 = 0;
  v21 = a2;
  v7 = this;
  if ( pString )
  {
    v21 = ui_current_text_color;
    v20 = strlen(pString);
    v22 = 0;
    if ( (signed int)v20 > 0 )
    {
      v8 = a4;
      do
      {
        v23 = &pString[v6];
        if ( v7->IsCharValid(v9 = pString[v6]) )
        {
          v10 = v9;
          v11 = v9 - 9;
          if ( v11 )
          {
            v12 = v11 - 1;
            if ( !v12 )
              return;
            v13 = v12 - 2;
            if ( v13 )
            {
              v14 = v13 - 1;
              if ( v14 )
              {
                if ( v14 != 82 )
                {
                  v15 = *((int *)&v7->cFirstChar + 3 * v10 + 9);
                  if ( v15 )
                  {
                    if ( v22 > 0 )
                      v8 += 2 * v7->pMetrics[v10].uLeftSpacing;
                    v16 = (int)((char *)&v7[1] + v7->field_C20[v10]);
                    v17 = v21;
                    if ( !v21 )
                      v17 = -1;
                    sub_40F845(v8, v16, v15, LOBYTE(v7->uFontHeight), (int)v7->pFontPalettes[0], v17, 2 * a6);
                    v8 += 2 * v15;
                    if ( v22 < (signed int)v20 )
                      v8 += 2 * v7->pMetrics[(unsigned __int8)*v23].uRightSpacing;
                  }
                }
              }
            }
            else
            {
              strncpy(&Dest, &pString[v6 + 1], 5u);
              v19 = 0;
              v21 = atoi(&Dest);
              ui_current_text_color = v21;
              v22 = v6 + 5;
            }
          }
        }
        v6 = v22++ + 1;
      }
      while ( v22 < (signed int)v20 );
    }
  }
}
// 5C6DB4: using guessed type int ui_current_text_color;


//----- (0044C933) --------------------------------------------------------
char * GUIFont::_44C933(const char *pString, GUIFont *pFont, GUIFont *a3, int a4, int a5, int a6)
{
  const char *v6; // esi@1
  size_t v8; // eax@3
  size_t v9; // edi@3
  int v10; // eax@3
  GUIFont *v11; // esi@3
  int v12; // ebx@3
  char v13; // cl@5
  int v14; // edx@11
  int v15; // ecx@11
  int v16; // edx@12
  int v17; // edx@13
  int v18; // edx@14
  int v19; // edx@15
  int v20; // edi@17
  int v21; // edx@17
  int v22; // ecx@17
  int v23; // edi@18
  char v24; // zf@18
  int v25; // ecx@19
  int v26; // eax@19
  char v27; // dl@24
  int v28; // eax@46
  std::string v29; // [sp-18h] [bp-48h]@2
  const char *v30; // [sp-8h] [bp-38h]@2
  int v31; // [sp-4h] [bp-34h]@2
  const char *v32; // [sp+Ch] [bp-24h]@1
  char Str; // [sp+10h] [bp-20h]@46
  char v34; // [sp+13h] [bp-1Dh]@46
  GUIFont *v35; // [sp+14h] [bp-1Ch]@1
  int v36; // [sp+18h] [bp-18h]@3
  int v37; // [sp+1Ch] [bp-14h]@3
  int v38; // [sp+20h] [bp-10h]@4
  int v39; // [sp+24h] [bp-Ch]@3
  int v40; // [sp+28h] [bp-8h]@3
  int i; // [sp+2Ch] [bp-4h]@17
  std::string *v42; // [sp+38h] [bp+8h]@2

  v6 = pString;
  v35 = pFont;
  v32 = pString;
  if ( !pString )
  {
    MessageBoxW(nullptr, L"Invalid string passed !", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Font.cpp:558", 0);
    return 0;
  }
  v8 = strlen(pString);
  v9 = v8;
  v39 = v8;

  assert(strlen(v6) < sizeof(pTmpBuf3));
  strcpy(pTmpBuf3, v6);
  v10 = a5;
  v11 = v35;
  v12 = 0;
  v40 = 0;
  v37 = a5;
  v36 = 0;
  if ( (signed int)v9 > 0 )
  {
    v38 = v9 - 1;
    do
    {
      v13 = pTmpBuf3[v12];
      if ( (unsigned __int8)v13 >= v11->cFirstChar && (unsigned __int8)v13 <= v11->cLastChar
        || v13 == '\f'
        || v13 == '\r'
        || v13 == '\t'
        || v13 == '\n' )
      {
        v14 = (unsigned __int8)v13 - 9;
        v15 = (int)&v11->pMetrics[(unsigned __int8)v13];
        if ( v14 )
        {
          v16 = v14 - 1;
          if ( v16 )
          {
            v17 = v16 - 2;
            if ( v17 )
            {
              v18 = v17 - 1;
              if ( v18 )
              {
                v19 = v18 - 19;
                if ( v19 )
                {
                  if ( v19 == 63 )
                  {
                    v11 = a3;
                  }
                  else
                  {
                    v20 = *(int *)(v15 + 8);
                    v21 = *(int *)(v15 + 4);
                    v22 = *(int *)v15;
                    i = v20;
                    if ( (unsigned int)(v10 + v20 + v22 + v21) < *(int *)(a4 + 8) )
                    {
                      v12 = v36;
                      if ( v36 > v40 )
                        v10 += v22;
                      v10 += v21;
                      if ( v36 < v39 )
                        v10 += i;
                    }
                    else
                    {
                      v23 = v40;
                      v24 = v11 == a3;
                      pTmpBuf3[v40] = 10;
                      if ( v24 )
                      {
                        v25 = v38;
                        v26 = v23 + 1;
                        while ( v25 >= v26 )
                        {
                          pTmpBuf3[v25] = byte_5C45AF[v25];
                          --v25;
                        }
                        ++v39;
                        ++v38;
                        pTmpBuf3[v23++ + 1] = 95;
                        v40 = v26;
                      }
                      v12 = v36;
                      v10 = v37;
                      for ( i = v23; i <= v36; ++i )
                      {
                        v27 = pTmpBuf3[i];
                        if ( (unsigned __int8)v27 >= v11->cFirstChar && (unsigned __int8)v27 <= v11->cLastChar
                          || v27 == 12
                          || v27 == 13
                          || v27 == 9
                          || v27 == 10 )
                        {
                          if ( i > v23 )
                            v10 += v11->pMetrics[(unsigned __int8)v27].uLeftSpacing;
                          v10 += *((int *)&v11->cFirstChar + 3 * (unsigned __int8)v27 + 9);
                          if ( i < v36 )
                            v10 += v11->pMetrics[(unsigned __int8)v27].uRightSpacing;
                        }
                      }
                    }
                  }
                }
                else
                {
                  v10 += *(int *)(v15 + 4);
                  v40 = v12;
                }
              }
              else
              {
                if ( !a6 )
                  return (char *)v32;
              }
            }
            else
            {
              v12 += 5;
            }
          }
          else
          {
            v10 = v37;
            v11 = v35;
            v40 = v12;
          }
        }
        else
        {
          strncpy(&Str, &pTmpBuf3[v12 + 1], 3u);
          v34 = 0;
          v28 = atoi(&Str);
          v10 = a5 + v28;
          v12 += 3;
          v37 = v10;
        }
      }
      ++v12;
      v36 = v12;
    }
    while ( v12 < v39 );
  }
  return pTmpBuf3;
}


//----- (0044C6C2) --------------------------------------------------------
int GUIFont::_44C6C2(const char *pInString, GUIWindow *pWindow, unsigned int uX, int a5)
{
  const char *v5; // esi@1
  int v6; // edi@1
  unsigned __int8 *v8; // ebx@3
  size_t v9; // eax@3
  signed int v10; // esi@3
  int v11; // edx@4
  unsigned int v12; // cl@4
  GUIFont *v13; // [sp+Ch] [bp-4h]@1
  size_t uXa; // [sp+1Ch] [bp+Ch]@3

  auto pFont = this;
  v5 = pInString;
  v6 = 0;
  v13 = pFont;
  if ( !pInString )
    return 0;
  v8 = (unsigned __int8 *)FitTextInAWindow(pInString, pFont, pWindow, uX, 0);
  v9 = strlen(v5);
  v10 = 0;
  uXa = v9;
  if ( (signed int)v9 > 0 )
  {
    while ( v10 < (signed int)uXa )
    {
	  if(IsCharValid(*v8))
	  {
		v12=(unsigned int)v8;
		if ( v12 != 9 )
		{
		  if ( v12 == 10 )
		  {
			v6 = v6 + *(char *)(v11 + 5) - 3;
			if ( v6 >= (signed int)(a5 * pWindow->uFrameHeight) )
			  return (int)(v8 + 1);
			if ( v6 >= (signed int)(a5 * pWindow->uFrameHeight) )
			  return (int)v8;
		  }
		  else if ( v12 == 12 )
		  {
			v8 += 5;
			v10 += 5;
			if ( v6 >= (signed int)(a5 * pWindow->uFrameHeight) )
			  return (int)v8;
		  }
		  else if ( v12 != 13 )
		  {
			if ( v6 >= (signed int)(a5 * pWindow->uFrameHeight) )
			  return (int)v8; 
		  }
		}
		if(v12 == 13 || v12 == 9)
		{
			v8 += 3;
			v10 += 3;
		}
		if ( v6 >= (signed int)(a5 * pWindow->uFrameHeight) )
		  return (int)v8;
	  }
      ++v10;
      ++v8;
    }
  }
  return (int)v8;
}



//----- (0044C62E) --------------------------------------------------------
int GUIFont::GetStringHeight2(GUIFont *a2, const char *Str, int a4, int a5, int a6)
{
  GUIFont *v6; // edi@1
  int v8; // esi@3
  unsigned __int8 *v9; // ebx@3
  size_t v10; // eax@3
  unsigned __int8 v11; // cl@4
  signed int Stra; // [sp+Ch] [bp+8h]@3
  size_t v13; // [sp+14h] [bp+10h]@3

  auto a1 = this;
  v6 = a1;
  if ( !Str )
    return 0;
  v8 = LOBYTE(a1->uFontHeight) - 3;
  v9 = (unsigned __int8 *)GUIFont::_44C933(Str, a1, a2, a4, a5, 0);
  v10 = strlen(Str);
  Stra = 0;
  v13 = v10;
  while ( Stra < (signed int)v13 )
  {
    if ( GUIFont::IsCharValid(v11 = *v9) )
    {
      if ( v11 == 9 )
        goto LABEL_9;
      switch ( v11 )
      {
        case 0xAu:
          v8 = v8 + LOBYTE(v6->uFontHeight) - 3;
          break;
        case 0xCu:
          v9 += 5;
          Stra += 5;
          break;
        case 0xDu:
LABEL_9:
          if ( a6 != 1 )
          {
            v9 += 3;
            Stra += 3;
          }
          break;
      }
    }
    ++Stra;
    ++v9;
  }
  return v8;
}

//----- (0044C59D) --------------------------------------------------------
int GUIFont::CalcTextHeight(const char *pString, GUIWindow *pWindow, int uXOffset, int a5)
	{ 
	int uAllHeght; 
	unsigned int uStringLen; 
	char c; 
	char *test_string; 

	if (!pString)
		return 0;
	uAllHeght = this->uFontHeight - 3;
	test_string = FitTextInAWindow(pString, this, pWindow, uXOffset, 0);
	uStringLen = strlen(pString);
	for (int i = 0; i < uStringLen; ++i)
		{
		c = test_string[i];
		if (IsCharValid(c))
			{
			switch (c)
				{
			case '\n':	//Line Feed 0A 10:
				uAllHeght+= this->uFontHeight - 3;
				break;
			case '\f':  //Form Feed, page eject  0C 12 
				i += 5;		  
				break;
			case '\t':	// Horizontal tab 09
			case '\r':   //Carriage Return 0D 13
				if (a5 != 1)
					i += 3;
				break;
				}
			}
		}
	return uAllHeght;
	}


//----- (0044C51E) --------------------------------------------------------
int GUIFont::GetLineWidth(const char *pString)
	{
	unsigned int str_len; // ebp@3
	int string_line_width; // esi@3
	unsigned char c;

	if (!pString)
		return 0;
	str_len = strlen(pString);
	string_line_width = 0;
	for ( int i = 0; i < str_len; ++i )
		{
		c = pString[i];
		if (IsCharValid(c))
			{
			switch (c)
				{
			case '\t':
			case '\n':
			case '\r':
				return string_line_width;
			case '\f':
				i += 5;	  
				break;
			default:
				if (i > 0)
					string_line_width += this->pMetrics[c].uLeftSpacing;
				string_line_width += this->pMetrics[c].uWidth;
				if (i < str_len)
					string_line_width +=this->pMetrics[c].uRightSpacing;
				}
			}
		}
	return string_line_width;
	}


//----- (0044C502) --------------------------------------------------------
int GUIFont::AlignText_Center(unsigned int uCenterX, const char *pString)
{
  signed int position; // esi@1
 
  position = (signed int)(uCenterX - GetLineWidth(pString)) >> 1;
  if ( position >= 0 )
    return position;
  else
    return  0;

}

//----- (0044C768) --------------------------------------------------------
char * FitTextInAWindow( const char *pInString, GUIFont *pFont, GUIWindow *pWindow, signed int uX, int a5 )
    {
	unsigned char c;
	unsigned int uInStrLen;
	char digits[4];
	int possible_transition_point;
	int string_pixel_Width;
	int start_pixel_offset;

	if (!pInString)
		{
		MessageBoxW(nullptr, L"Invalid string passed !", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Font.cpp:445", 0);
		return 0;
		}
	uInStrLen = strlen(pInString);
	strcpy(&temp_string[0], pInString);
	if (uInStrLen==0)
		return &temp_string[0];

	start_pixel_offset=string_pixel_Width=uX;
	possible_transition_point=0;
	for(int i=0; i<uInStrLen; ++i) 
		{
		c=temp_string[i];
		if (pFont->IsCharValid(c))
			{
			switch (c)
				{
			case '\t':	// Horizontal tab 09
				{
				strncpy(digits, &temp_string[i+1],3);
				digits[3]=0;
				string_pixel_Width= atoi(digits)+uX;
				i+=3;
				break;
				}
			case  '\n':	//Line Feed 0A 10
				{
				string_pixel_Width=start_pixel_offset;
				possible_transition_point=i;
				break;
				}
			case  '\f':   //Form Feed, page eject  0C 12
				{
				i+=5;  
				break;
				}
			case  '\r':   //Carriage Return 0D 13
				{
				if (!a5)
					return (char*)pInString;
				break;
				}
			case ' ' :
				{
				string_pixel_Width+=pFont->pMetrics[c].uWidth;
				possible_transition_point=i;
				break;
				}
			default:

				if ((string_pixel_Width+pFont->pMetrics[c].uWidth+ pFont->pMetrics[c].uLeftSpacing+
					pFont->pMetrics[c].uRightSpacing)<pWindow->uFrameWidth)
					{
					if(i>possible_transition_point)
						string_pixel_Width+=pFont->pMetrics[c].uLeftSpacing;
					string_pixel_Width+=pFont->pMetrics[c].uWidth;
					if (i<uInStrLen)
						string_pixel_Width+=pFont->pMetrics[c].uRightSpacing;
					}
				else
					{
					temp_string[possible_transition_point]='\n';
					string_pixel_Width=start_pixel_offset;
					if (i>possible_transition_point)
						{
						for(int j=possible_transition_point;j<i; ++j ) 
							{
							c=temp_string[j];
							if (pFont->IsCharValid(c))
								{
								if(j>possible_transition_point)
									string_pixel_Width+=pFont->pMetrics[c].uLeftSpacing;
								string_pixel_Width+=pFont->pMetrics[c].uWidth;
								if (j<i)
									string_pixel_Width+=pFont->pMetrics[c].uRightSpacing;

								}
							}  
						}
					}
				}
			}
		}
	return &temp_string[0];
	}