/*everything to format texts with the following syntax: (all characters are lowercase)*/
/* /L:      line break*/
/* /Wnnn:   char width in millimeters*/
/* /Hnnn:   line height in millimeters*/
/* /Cnnn:   color code*/
/* /Rnnn:   random positionning radius in millimeters*/
/* /JC/L/R: justification center/left/right*/
/* /Znnn:		zoom factor in 1000th (will affect positioning)*/
/* //:      '/' character*/
/* /::      ':' character*/
 
 
/* ANNECY CG MODIFICATIONS*/
#define D_ObjsTbls_Define
/*ENDANNECY CG*/
 
 
#include "ToolsCPA.h"
 
#include "GameEng.h"
#include "Gam/TextFrmt.h"
 
#include "Actions/AllActs.h"
#include "Structur/Objects.h"
#include "Structur/ObjsTbls.h"
#include "ChanList.h"
 
#include "Family.h"
/*#include "Actions/3dData.h"*/
 
/* #include <ctype.h>	/*for toupper */
 
#include "actions\3ddata.h"
#include "safe.h"

#if defined(__cplusplus)
extern "C"
{
#endif /* __cplusplus */
tdstInfoTextAffiche g_stInfoTextAffiche[MAX_TEXTAFFICHE];
HIE_tdxHandleToSuperObject   gp_SuperObjPersoGenerated[MAX_TEXTAFFICHE];
BOOL g_bFreeTextAfficheBlocs[MAX_TEXTAFFICHE];
/*unsigned char g_ucTextAfficheId = 0;*/
#if defined(__cplusplus)
}
#endif /* __cplusplus */
 
/*global variables*/
static RND_tdxHandleToRandomIndex gs_hRandomHandleForTFMT = (RND_tdxHandleToRandomIndex) -1; /*should be invalid*/
 
/* Offset in object table */
int OffsetObjectTable = 0;
 
typedef struct tdstDefaultValuesForCharacter_
{
  MTH_tdxReal m_xCharWidth; 
  MTH_tdxReal m_xLineHeight;
  MTH_tdxReal m_xCharZoom;
}tdstDefaultValuesForCharacter;
tdstDefaultValuesForCharacter g_stDefaultValuesForCharacter =  {MTH_C_ZERO, MTH_C_2, MTH_C_ZERO};
 
MTH_tdxReal TFMT_ga_fLetterSpacing[TFMT_MAX_WIDTHTABLEELMENT] ;
MTH_tdxReal TFMT_ga_fLetterScale[TFMT_MAX_SCALEDPATTERN] ;
unsigned long TFMT_ga_ulNbScale = 0 ;
 
 
extern HIE_tdxHandleToSuperObject PLA_fn_hFindNextFreeSupObj(void);

static __inline unsigned char fn_ucToTableElement ( int _n )
{
	if ( _n < ' ' )
		_n = 0 ;
	else if ( _n >= 'a' && _n <= 'z' )
		_n -= ' ' + ' ' ;
	else if ( _n >= 'A' && _n <= 'Z' )
		_n -= ' ' ;
	else if ( _n >= 160 )
		_n -= ' ' + ' ' ;
	else
		_n -= ' ' ;

	return ( unsigned char ) _n ;
}


/* -----------------10/03/98 10:34-------------------
initialize all the global stuff
 --------------------------------------------------*/
void TFMT_vSetDefaultValuesCharacter
(
	MTH_tdxReal _xCharWidth, 
	MTH_tdxReal _xLineHeight,
	MTH_tdxReal _xCharZoom
)
{
	g_stDefaultValuesForCharacter.m_xCharWidth  = MTH_C_ZERO ;
	if ( MTH_M_bGreaterEqual(_xLineHeight, MTH_C_ZERO) )
		g_stDefaultValuesForCharacter.m_xLineHeight = _xLineHeight;
	if ( MTH_M_bGreaterEqual(_xCharZoom, MTH_C_ZERO) )
		g_stDefaultValuesForCharacter.m_xCharZoom   = _xCharZoom;
 
	TFMT_vInitScapingTable ( _xCharWidth ) ;
}
 
void TFMT_vInitFormatterStatus
(
	tdstTfmtStatus *_p_stStatus,
  HIE_tdxHandleToSuperObject _hSuperObjPerso,
  MTH_tdxReal _xScreenWidth
)
{
	OffsetObjectTable = 0;
	/*this must be done only ONCE in the game!!!*/
	if ( gs_hRandomHandleForTFMT == -1 )
		gs_hRandomHandleForTFMT = RND_fn_hReserveANewHandleIndex();
 
  _p_stStatus->xScreenWidth = _xScreenWidth;
  _p_stStatus->xBaseCharX = _p_stStatus->xBaseCharZ = MTH_C_ZERO;
  _p_stStatus->xBaseToAddX = MTH_C_ZERO;
 
	_p_stStatus->xCharWidth = g_stDefaultValuesForCharacter.m_xCharWidth;
	_p_stStatus->xLineHeight = g_stDefaultValuesForCharacter.m_xLineHeight;
	_p_stStatus->xCharZoom = g_stDefaultValuesForCharacter.m_xCharZoom;
  _p_stStatus->xCurCharZoom = MTH_C_ZERO ;
 
  _p_stStatus->cJustificationMode = 'l';
  _p_stStatus->hSourceObjectTable = fn_hGetObjectsTableOfFamilyByIndex(
    fn_h3dDataGetFamily(M_GetMSHandle(_hSuperObjPerso,3dData)),
    0
  );
  _p_stStatus->xRandomPosRadius = MTH_C_ZERO;
}
 
 
#pragma warning (disable : 4706)    /* There are some voluntary assignment inside this function*/
/* -----------------10/03/98 10:46-------------------
get next char, handle all escape sequences, and move the
pointer to the next unread char that is not the beginning
of an escape sequence
 --------------------------------------------------*/
char * TFMT_pszReadNextChar
(
	tdstTfmtStatus *_p_stStatus,
  HIE_tdxHandleToSuperObject _hSuperObjPerso,
  char *_pszCurrentChar,
  unsigned char *_p_ucReturnedChar,
  ACP_tdxBool *_p_bLineBreak
)
{
  unsigned char ucChar ;
 
  * _p_bLineBreak = FALSE ;
  if ( _pszCurrentChar && ( ( ucChar = * ( _pszCurrentChar ++ ) ) != 0 ) ) /*THIS ASSIGNMENT IS INTENTIONAL!!!*/
  {
    /*do we begin to scan one or nmore formatting sequences ?*/
    while ( ucChar == '/' )
    {
      switch ( *_pszCurrentChar )
      {
      case 'L':
      case 'l':
        *_p_bLineBreak = TRUE;
        _p_stStatus->xBaseCharX = _p_stStatus->xBaseToAddX = MTH_C_ZERO;
				_p_stStatus->xBaseCharZ -= _p_stStatus->xLineHeight;
        break;
 
			case 'Z':
			case 'z': /*zoom factor of the following letters*/
        _pszCurrentChar ++;
				_p_stStatus->xCharZoom = MTH_M_xDiv(MTH_M_xLongToReal(atoi(_pszCurrentChar)), MTH_M_xDoubleToReal(1000.0));
				break;
 
			case 'W':
      case 'w': /*width of following letters in mm (format is nnn: )*/
        _pszCurrentChar ++;
        _p_stStatus->xCharWidth = MTH_M_xMul(_p_stStatus->xCharZoom, MTH_M_xDiv(MTH_M_xLongToReal(atoi(_pszCurrentChar)), MTH_M_xDoubleToReal(1000.0)));
        break;
 
			case 'H':
      case 'h': /*height between lines in mm (format is nnn: )*/
        _pszCurrentChar ++;
        _p_stStatus->xLineHeight = MTH_M_xMul(_p_stStatus->xCharZoom, MTH_M_xDiv(MTH_M_xLongToReal(atoi(_pszCurrentChar)), MTH_M_xDoubleToReal(1000.0)));
        break;
 
			case 'C':
      case 'c': /*color of following letters (format is n: )*/
        _p_stStatus->hSourceObjectTable = fn_hGetObjectsTableOfFamilyByIndex(
          fn_h3dDataGetFamily(M_GetMSHandle(_hSuperObjPerso,3dData)),
          (ACP_tdxIndex) atoi(++ _pszCurrentChar)
        );
        break;
 
	  case 'o':
	 case 'O':
        _pszCurrentChar ++;
		 OffsetObjectTable = atoi(_pszCurrentChar);
		 break;
 
	 case 'J':
      case 'j': /*justification (format is C/L/R: )*/
        _p_stStatus->cJustificationMode = *(++ _pszCurrentChar);
        break;
 
			case 'R':
      case 'r': /*set random positioning radius*/
        {
          long lValue = atoi(++ _pszCurrentChar);
          _p_stStatus->xRandomPosRadius = MTH_M_xDiv(MTH_M_xLongToReal(lValue), MTH_M_xDoubleToReal(1000.0));
#ifndef U64
					/*we use the radius */
					RDN_fn_vSetRandomSeed(gs_hRandomHandleForTFMT, lValue);
#endif
        }
        break;
 
      case '/': /*slash (format is //: )*/
        ucChar = '/';
        _pszCurrentChar ++;
        break;
 
      case ':': /*colon (format is /:: )*/
        ucChar = ':';
        _pszCurrentChar ++;
        break;
      }
      /*move pointer to the letter following the formatting sequence*/
      while ( *(++ _pszCurrentChar) != ':' );
      ucChar = *(++ _pszCurrentChar);
			/*if we did not get a line break, we want the pointer to be on the next char*/
			if ( ! *_p_bLineBreak )
				_pszCurrentChar ++;
    }
 
		/*skip whitespaces at the beginning of the line (after we got all the sequences)*/
		if ( (_p_stStatus->xBaseCharX == MTH_C_ZERO) && (ucChar == ' ') )
			while ( (ucChar = *(_pszCurrentChar ++)) == ' ' );
 
    /*this is the base position of the char we are scanning*/
    /*(we add the offset caused by the previous char)*/
    _p_stStatus->xBaseCharX += _p_stStatus->xBaseToAddX;
 
    /*set the shift that will be applied to the next character relatively to the current one*/
    if ( ! *_p_bLineBreak )
	{
     if ( _p_stStatus->xCharWidth )
	 {
       _p_stStatus->xBaseToAddX = _p_stStatus->xCharWidth;
     }
     else
	 {
       MTH_tdxReal xZoom ;
	   unsigned char ucTemp ;
       
       xZoom = _p_stStatus->xCharZoom ;
       if ( MTH_M_bEqualZero (xZoom) ) {
         if ( TFMT_ga_ulNbScale )
           xZoom = TFMT_ga_fLetterScale[0] ;
         else
           xZoom = MTH_C_ONE ;
       }
	   ucTemp = fn_ucToTableElement ( ucChar ) ;
       _p_stStatus->xBaseToAddX = MTH_M_xMul ( xZoom , TFMT_ga_fLetterSpacing [ ucTemp ] ) ;
     }
    }
  }
	else
	{
	  /*if we reached the end of the text, say it!*/
    *_p_bLineBreak = TRUE;
		*_p_ucReturnedChar = '\0' ;
		return NULL;
	}
  *_p_ucReturnedChar = ucChar;
  return _pszCurrentChar;
}
#pragma warning (default : 4706)
 
/* -----------------10/03/98 10:44-------------------
returns the number of characters from the current position
that will fit in a single line (random alterations are not relevant)
 --------------------------------------------------*/
unsigned short TFMT_uwGetNbCharsFillingALine
(
	tdstTfmtStatus *_p_stStatus,
	HIE_tdxHandleToSuperObject _hSuperObjPerso,
	char *_pszText,
	MTH_tdxReal *_p_xActualWidth
)
{
  tdstTfmtStatus stTfmtStatusSave = *_p_stStatus;
  unsigned char ucCurrentChar;
  short wCharIndex = 0;
  ACP_tdxBool bLineBreak;
  MTH_tdxReal xCurrentWidth = MTH_C_ZERO, xScreenWidth = _p_stStatus->xScreenWidth;
 
  /*set an unlimited limit if the limit is negative*/
  if ( MTH_M_bLessZero(xScreenWidth) )
    xScreenWidth = MTH_M_xDoubleToReal(1000.0);
 
  do
  {
    /*read the next char, interpreting all escape sequences if relevant*/
    _pszText = TFMT_pszReadNextChar(_p_stStatus, _hSuperObjPerso, _pszText, & ucCurrentChar, &bLineBreak);
		if ( !bLineBreak )
		{
			MTH_tdxReal xNewWidth = xCurrentWidth + _p_stStatus->xCharWidth;
			if ( xNewWidth < xScreenWidth )
			{
				xCurrentWidth = xNewWidth;
	      wCharIndex ++;
			}
			else
				bLineBreak = 1;
		}
  } while ( !bLineBreak );
  /*restore the current status, because reading the various chars changed it*/
  *_p_stStatus = stTfmtStatusSave;
  /*and return the number of chars that fit in the line*/
  *_p_xActualWidth = xCurrentWidth;
  return wCharIndex;
}
 
/* -----------------10/03/98 11:14-------------------
position the specified channels of the current anim,
and set the current object table from the text
 --------------------------------------------------*/
short TFMT_wPositionModulesAccordingToText
(
	tdstTfmtStatus *_p_stStatus,
	HIE_tdxHandleToSuperObject _hSuperObjPerso,
	char *_pszText,
	long _lStart,
	long _lEnd,
	MTH_tdxReal _xScreenWidth,
	tdstTfmtLineResults *_d_stLineResults,
	short _wNbLines
)
{
  MTH_tdxReal xJustificationShift;
  short wNbCharsInCurrentLine, wCurrentChar = 0, wCurrentLine = 0;
  tdxHandleToObjectsTablesList hTargetObjectTable = fn_h3dDataGetCurrentObjectsTable(M_GetMSHandle(_hSuperObjPerso,3dData));
	short wNbObjectsInTargetTable = fn_uwGetObjectTableNumberOfelements(hTargetObjectTable);
	/*get the pointer where the scanning stops*/
	char *pszInitText = _pszText, *pszEndText = _pszText + (_lEnd >= 0 ? _lEnd : strlen(_pszText));
	/*get the pointer where the scanning starts*/
	_pszText += _lStart;
	/*initialize all the stuff*/
	TFMT_vInitFormatterStatus(_p_stStatus, _hSuperObjPerso, _xScreenWidth);
 
	/*for each character in the text*/
	while ( (_pszText < pszEndText) && *_pszText )
	{
		/*get the width and number of chars of the first line in the text*/
		wNbCharsInCurrentLine = TFMT_uwGetNbCharsFillingALine(_p_stStatus, _hSuperObjPerso, _pszText, &xJustificationShift);
		/*shift if the justification mode says so*/
		switch ( _p_stStatus->cJustificationMode )
		{
		case 'r':
			xJustificationShift = MTH_M_xSub(_p_stStatus->xScreenWidth, xJustificationShift);
			break;
 
		case 'c':
			xJustificationShift = MTH_M_xDiv(MTH_M_xSub(_p_stStatus->xScreenWidth, xJustificationShift), MTH_C_2);
			break;
 
		default:
			xJustificationShift = MTH_C_ZERO;
		}
 
		/* if we need some stats, record them*/
		if ( _d_stLineResults && (_wNbLines >= 0) )
			_d_stLineResults[wCurrentLine].wStartChar = (short) (_pszText - pszInitText);
 
		/*for each character of the line, set the geometric object in the object table, and position the channel in the anim*/
		while ( (wNbCharsInCurrentLine --) && (_pszText < pszEndText) )
		{
			unsigned char ucChar;
			ACP_tdxBool bLineBreak;
			short wSourceObject, wNbObjectsInSourceTable;
			/*read the next char in the text*/
			_pszText = TFMT_pszReadNextChar ( _p_stStatus , _hSuperObjPerso , _pszText , & ucChar , & bLineBreak ) ;
 
			if ( ! _d_stLineResults ) /*do the deed on the object table and the animation channels if we are not here for the stats*/
			{
				if ( ucChar < ' ' )
				{
					wSourceObject = -1 ;
				}
				else
				{
					unsigned char ucTemp = fn_ucToTableElement ( ucChar ) ;
					wSourceObject = (short) ( ucTemp + OffsetObjectTable ) ;
				}
				/*since the source object table may change, we need to check the size each time*/
				wNbObjectsInSourceTable = fn_uwGetObjectTableNumberOfelements(_p_stStatus->hSourceObjectTable);
				if ( wSourceObject < 0 || wSourceObject >= wNbObjectsInSourceTable )
				{
					wSourceObject = 0;
				}
				else
				{
					POS_tdstCompletePosition *hChannelLocalMatrix;
					HIE_tdxHandleToSuperObject hChannelSuperObject;
					/*copy the current object from the source to the target*/
					fn_vCopyObjectFromObjectTabletoAnother(hTargetObjectTable, _p_stStatus->hSourceObjectTable, wCurrentChar, wSourceObject);
					/*get the current channel's superobject*/
					hChannelSuperObject = fn_hGetSuperObjectInChannel(fn_h3dDataGetChannelSOList(M_GetMSHandle(_hSuperObjPerso,3dData)), wCurrentChar);
					if ( hChannelSuperObject )
					{
						MTH3D_tdstVector stV1, stV2, stV3;
						/*change its local position*/
						hChannelLocalMatrix = HIE_fn_hGetSuperObjectMatrix(hChannelSuperObject);
						/*set the channel position according to the formatter status*/
						MTH3D_M_vSetVectorElements(
							&stV1,
							MTH_M_xAdd(xJustificationShift, MTH_M_xAdd(_p_stStatus->xBaseCharX, RND_fn_xGetRealRandomValue(gs_hRandomHandleForTFMT, MTH_M_xNeg(_p_stStatus->xRandomPosRadius), _p_stStatus->xRandomPosRadius))),
							MTH_C_ZERO,
							MTH_M_xAdd(_p_stStatus->xBaseCharZ, RND_fn_xGetRealRandomValue(gs_hRandomHandleForTFMT, MTH_M_xNeg(_p_stStatus->xRandomPosRadius), _p_stStatus->xRandomPosRadius))
						);
						POS_fn_vSetTranslationVector(hChannelLocalMatrix, &stV1);
 
						/* and its local scale*/
						if ( MTH_M_bDifferentWithEpsilon(_p_stStatus->xCharZoom, MTH_C_ONE, MTH_M_xDoubleToReal(0.0001)) )
						{
							MTH3D_M_vSetVectorElements(&stV1,	_p_stStatus->xCharZoom, MTH_C_ZERO, MTH_C_ZERO);
							MTH3D_M_vSetVectorElements(&stV2,	MTH_C_ZERO, _p_stStatus->xCharZoom, MTH_C_ZERO);
							MTH3D_M_vSetVectorElements(&stV3, MTH_C_ZERO, MTH_C_ZERO, _p_stStatus->xCharZoom);
							POS_fn_vSetScaleMatrix(hChannelLocalMatrix, &stV1, &stV2, &stV3);				
						}
					}
				}
			}
			wCurrentChar ++;
		}
		/* if we want stats, record them*/
		if ( _d_stLineResults && (_wNbLines >= 0) )
		{
			_d_stLineResults[wCurrentLine].wEndChar = (short) (_pszText - pszInitText);
			MTH3D_M_vSetVectorElements(
				&_d_stLineResults[wCurrentLine].stLineOrigin,
				xJustificationShift,
				MTH_C_ZERO,
				_p_stStatus->xBaseCharZ /* - _p_stStatus->xLineHeight //since we do it after the line change, account for the vertical offset properly*/
			);
		}
		/*here we are done with the current line, but if it ended with escape sequences, one of which breaking the text*/
		/*we have not read it yet, so do it now*/
		if ( _pszText < pszEndText )
		{
			if ( *_pszText == '/' )
			{
				ACP_tdxBool bLineBreak;
				do
				{
					unsigned char ucChar;
					/*read the next char in the text*/
					_pszText = TFMT_pszReadNextChar(_p_stStatus, _hSuperObjPerso, _pszText, & ucChar, &bLineBreak);
				} while ( !bLineBreak ); /*until we reach the sequence that stops the current line*/
			}
			else /*the EOL is reached because no more chars will fit on the specified width -> do the carriage return ourselves*/
			{
				_p_stStatus->xBaseCharZ -= _p_stStatus->xLineHeight;
				_p_stStatus->xBaseCharX = _p_stStatus->xBaseToAddX = MTH_C_ZERO;
			}
		}
		/*one more line has gone by...*/
		_wNbLines --;
		wCurrentLine ++;
	}
	/*now fill the rest of the target object table with empty objects*/
	while ( wCurrentChar < wNbObjectsInTargetTable )
	{
		fn_vCopyObjectFromObjectTabletoAnother(hTargetObjectTable, _p_stStatus->hSourceObjectTable, wCurrentChar, 0);
		wCurrentChar ++;
	}
	/*return the number of lines that got filled in the info array*/
	return wCurrentLine;
}
/****************************************************************
 * Jean-Marc Drouaud
 * Le 26/11/98
 * traitement pour les caractères de formatage.
 ****************************************************************/
long TFMT_lProcessFormater
(
	tdstTfmtStatus * p_stStatus ,
	char * szString ,
	ACP_tdxBool * p_bLineBreak ,
	ACP_tdxBool * p_bStartLine
)
{
	long i = 1 ;
#ifdef ACTIVE_EDITOR
	char * p_szInitString = szString ;
#endif

	switch(*(szString++))
	{
	case 'C':
	case 'c':
		p_stStatus->cJustificationMode = 'c';
		break;

	case 'H':
	case 'h':
		/*height between lines in mm (format is nnn: )                    */
		p_stStatus->xLineHeight = MTH_M_xDiv(MTH_M_xLongToReal(atoi(szString)), MTH_M_xDoubleToReal(1000.0)) ;
		break;

	case 'L':
	case 'l':              
		*p_bLineBreak = TRUE;
		*p_bStartLine = TRUE;
		p_stStatus->xBaseCharX  = p_stStatus->xBaseToAddX = MTH_C_ZERO;
		p_stStatus->xBaseCharZ -= p_stStatus->xLineHeight;
		break;

	case 'W':
	case 'w':              
		/*width of following letters in mm (format is nnn: )*/
		p_stStatus->xCharWidth  = MTH_M_xDiv(MTH_M_xLongToReal(atoi(szString)), MTH_M_xDoubleToReal(1000.0)) ;
		break;

	case 'Z':
	case 'z':
		/*zoom factor of the following letters*/
		p_stStatus->xCharZoom = MTH_M_xDiv(MTH_M_xLongToReal(atoi(szString)), MTH_M_xDoubleToReal(1000.0));
		break;

	case  'o':
	case 'O':
		OffsetObjectTable = atoi(szString);
		break;
	}
	while ( * szString != ':' )
	{
#ifdef ACTIVE_EDITOR
		if ( * szString == 0 )
		{
			char szMsg [ 500 ] ;
			sprintf (
				szMsg ,
				"un formateur en fin de chaine ne se termine pas par ':'.\n"
				"Il est possible de le repérer en recharchant la chaîne %s\" dans les textes\n"
				"ou le cas échéant dans les scripts éditeurs des modèles" ,
				p_szInitString
			) ;
			SAF_M_AssertWithMsg( 0, szMsg );
		}
#endif
		szString ++ ;
		i ++;
	}
	return (++i) ;
}
 
/*----------------------------------------------------
- Christophe Giraud                                  -
- Le 09/09/98                                        -
- compute length of string without code              -
----------------------------------------------------*/
void TEXT_vComputeLengthOgString( char *p_szString, tdstTfmtStatus *p_stStatus )
{
	register long lNbChar = 0 ;
	MTH_tdxReal xZoom , xMaxScreenWidth = MTH_C_ZERO ;
	ACP_tdxBool bLineBreak = FALSE , bStartLine = FALSE;

	while( * p_szString )
	{
		if ( * p_szString == '/' )
		{
			p_szString += TFMT_lProcessFormater ( p_stStatus , ++ p_szString , & bLineBreak , & bStartLine ) ; 
			if ( bLineBreak )
			{
				xMaxScreenWidth = MTH_M_xMax ( xMaxScreenWidth , p_stStatus -> xScreenWidth ) ;
				p_stStatus -> xScreenWidth = MTH_C_ZERO ;
				bLineBreak = FALSE ;
			}
		}
		else
		{
			xZoom = p_stStatus -> xCharZoom ;
			if ( MTH_M_bEqualZero ( xZoom ) )
			{
				if ( TFMT_ga_ulNbScale )
					xZoom = TFMT_ga_fLetterScale [ ( lNbChar % TFMT_ga_ulNbScale ) ] ;
				else
					xZoom = MTH_C_ONE ;
			}
			lNbChar ++ ;
			if ( p_stStatus -> xCharWidth )
			{
				p_stStatus -> xScreenWidth += MTH_M_xMul ( xZoom , p_stStatus -> xCharWidth ) ;
			}
			else
			{
				unsigned char ucTemp = fn_ucToTableElement ( * p_szString ) ;
				p_stStatus -> xScreenWidth += MTH_M_xMul ( xZoom , TFMT_ga_fLetterSpacing [ ucTemp ] ) ;
			}
			p_szString ++ ;
		}
	}
	p_stStatus->xScreenWidth = MTH_M_xMax(p_stStatus->xScreenWidth, xMaxScreenWidth);
}
 
/*----------------------------------------------------
- Christophe Giraud                                  -
- Le 01/08/98                                        -
-  !!! UNDER CONSTRUCTION !!! UNDER CONSTRUCTION !!! -
----------------------------------------------------*/
char *TFMT_pszReadNextChar2(
                             tdstTfmtStatus             *_p_stStatus,
                             HIE_tdxHandleToSuperObject _hSuperObjPerso,
                             char                       *_pszCurrentChar,
                             unsigned char              *_p_ucReturnedChar,
                             ACP_tdxBool                *_p_bLineBreak,
                             BOOL                       bDisplayFullString,
                             short                      *wCurrentChar,
                             unsigned long              *ulEvent,
                             unsigned long              **ulDelay,
                             short                      *wCurrentChar4Channels,
                             unsigned short             *p_uwIndexOfChar
                          )
{
  register unsigned char ucChar;
  register unsigned short uwLenString;
  long lNbChar = 0 ;
  MTH_tdxReal xPrevZoom, xPrevWidth = 0, xWidth = 0 ;
  MTH_tdxReal xZoom = 0 ;
  ACP_tdxBool bStartLine ;
       
  *_p_bLineBreak = FALSE;
  xPrevZoom = 0.0f ;
  /********************************
  * Build String letter by letter *
  ********************************/
  if (!bDisplayFullString)
  {
    register long i             = 0;
 
 
    bStartLine    = TRUE;
    uwLenString   = (unsigned short) strlen(_pszCurrentChar);
    ucChar         = ( unsigned char ) * ( _pszCurrentChar + * wCurrentChar ) ;
    
    /**** Pointe t'on de nouveau sur un évènement ? ****/
    if ( * ulEvent )
    {
        if ( ucChar == '/' )
        {
            ucChar = (unsigned char) ( * ( _pszCurrentChar + * wCurrentChar ) + 1 ) ;
            if ( ( ucChar == 'E' ) || ( ucChar == 'e' ) )
            {   
                ( * wCurrentChar ) ++ ;
                /* Events (format is nnn: )*/
                * ulEvent = ( unsigned long ) atoi( _pszCurrentChar + ( ++ ( * wCurrentChar ) ) ) ;
                while ( * ( _pszCurrentChar + ( * wCurrentChar ) ++ ) != ':' ) ;
            }
            else
            {
                * ulEvent = 0 ;
            }
        }
        else
        {
            * ulEvent = 0 ;
        }
        /*  Retourner un caractère null*/
        *_p_ucReturnedChar = 0 ;
        _pszCurrentChar += uwLenString ;
        return _pszCurrentChar ;
    }
 
    while ( ucChar == '/' )
    {
        ucChar = ( unsigned char ) _pszCurrentChar [ ++ ( * wCurrentChar ) ] ;
        if ( ( ucChar == 'E' ) || ( ucChar == 'e' ) )
        {   
            /* Events (format is nnn: )*/
            * ulEvent = ( unsigned long ) atoi ( _pszCurrentChar + ( ++ ( * wCurrentChar ) ) ) ;
            while ( * ( _pszCurrentChar + ( * wCurrentChar ) ++ ) != ':' ) ;
 
            /*  Faire le return et retourner un caractere nul*/
            * _p_ucReturnedChar = 0 ;
            _pszCurrentChar += uwLenString ;
            return _pszCurrentChar ;
 
        }
        else if ( ( ucChar == 'D' ) || ( ucChar == 'd' ) || ( ucChar == 'P' ) || ( ucChar == 'p' ) )
        {
          /*Delay (format is nnn: )*/
          * * ulDelay = ( unsigned long ) atoi( _pszCurrentChar + ( ++ ( * wCurrentChar ) ) );
          if ( ( ucChar == 'P' ) || ( ucChar == 'p' ) )
          {
            * * ulDelay = - ( ( int ) * * ulDelay ) ;
          }
          
          while ( * ( _pszCurrentChar + ( * wCurrentChar ) ++ ) != ':' ) ;
          
          /*  Faire le return et retourner un caractere nul*/
          * _p_ucReturnedChar = 0 ;
          _pszCurrentChar += uwLenString ;
          return _pszCurrentChar ;
        }
        else 
        {
          while ( * ( _pszCurrentChar + ( * wCurrentChar ) ++ ) != ':' ) ;
          ucChar = * ( _pszCurrentChar + * wCurrentChar ) ;
        }
    }
  
    * wCurrentChar4Channels = -1 ;
    /* Parcours la chaîne du début jusqu'à la position courante pour récupérer les formatages*/
    for ( ; i <= * wCurrentChar ; i ++ )
    {
        ucChar = ( unsigned char ) * ( _pszCurrentChar + i) ;
        /* Faire le traitement pour les caractères de formatage.*/
        if ( ucChar == '/' )
        {
          i += TFMT_lProcessFormater ( _p_stStatus , _pszCurrentChar + i + 1 , _p_bLineBreak , & bStartLine ) ;
        }
        else
        {
          xZoom = _p_stStatus -> xCharZoom ;
 
          if ( MTH_M_bEqualZero ( xZoom ) )
		  {
            if ( TFMT_ga_ulNbScale )
              xZoom = TFMT_ga_fLetterScale [ ( lNbChar % TFMT_ga_ulNbScale ) ] ; 
            else
              xZoom = MTH_C_ONE ;
          }
          _p_stStatus -> xCurCharZoom = xZoom ;
 
          if ( _p_stStatus -> xCharWidth )
		  {
            xWidth = _p_stStatus -> xCharWidth ;
          }
          else 
		  {
			unsigned char ucTemp = fn_ucToTableElement ( ucChar ) ;
			xWidth = TFMT_ga_fLetterSpacing [ ucTemp ] ;
          }
 
 
          ( * wCurrentChar4Channels ) ++ ;
          if (! bStartLine )
          {
            _p_stStatus -> xBaseToAddX += MTH_M_xMul ( xPrevZoom , xPrevWidth ) ;
          }
          else
          {
            bStartLine = FALSE ;
          }
          lNbChar ++ ;
          xPrevZoom = xZoom ;
          xPrevWidth = xWidth ;
        }
    }
    _p_stStatus -> xCurCharWidth = MTH_M_xMul ( xZoom , xWidth ) ;
    _p_stStatus -> xBaseCharX  += _p_stStatus -> xBaseToAddX ;
  }
  /********************
  * Build Full string *
  ********************/
  else
  { 
    bStartLine = FALSE;
    uwLenString        = (unsigned short) strlen(_pszCurrentChar);
 
    lNbChar = * p_uwIndexOfChar ;
    while ( * _pszCurrentChar ++ == '/' )
    {
      _pszCurrentChar += TFMT_lProcessFormater ( _p_stStatus , _pszCurrentChar , _p_bLineBreak , & bStartLine ) ;
    }
 
     ucChar = ( unsigned char ) * ( _pszCurrentChar - 1 ) ;
 
     xZoom = _p_stStatus -> xCharZoom ;
     if ( MTH_M_bEqualZero ( xZoom ) )
	 {
       if ( TFMT_ga_ulNbScale )
         xZoom = TFMT_ga_fLetterScale [ ( lNbChar % TFMT_ga_ulNbScale ) ] ;
       else
         xZoom = MTH_C_ONE ;
     }
     _p_stStatus -> xCurCharZoom = xZoom ;
 
     if ( ! bStartLine ) 
     {
       _p_stStatus -> xBaseCharX  += _p_stStatus -> xBaseToAddX ;
     }
     else
     {
         bStartLine = FALSE ;
     }
 
     if ( _p_stStatus -> xCharWidth )
	 {
       _p_stStatus -> xBaseToAddX = MTH_M_xMul ( xZoom , _p_stStatus -> xCharWidth ) ;
     }
     else 
	 {
		unsigned char ucTemp = fn_ucToTableElement ( ucChar ) ;
		_p_stStatus -> xBaseToAddX = MTH_M_xMul ( xZoom , TFMT_ga_fLetterSpacing [ ucTemp ] ) ;
     }
     _p_stStatus -> xCurCharWidth = _p_stStatus -> xBaseToAddX ;
    lNbChar ++ ;
  }
  
  *_p_ucReturnedChar = ucChar ;
  if ( ! bDisplayFullString )
  {
      _pszCurrentChar += uwLenString ;
  }
 
  * p_uwIndexOfChar = ( unsigned short ) lNbChar ;
  return _pszCurrentChar ;
}
 
/*-----------------------------------------------------
 - Christophe Giraud                                  -
 - Le 02/07/98                                        -
 -  !!! UNDER CONSTRUCTION !!! UNDER CONSTRUCTION !!! -
 -----------------------------------------------------*/
unsigned long TFMT_wPositionModulesAccordingToText2(
                                                     tdstTfmtStatus             *_p_stStatus,
                                                     HIE_tdxHandleToSuperObject _hSuperObjPerso,
                                                     char                       *_pszText,
                                                     long                       _lStart,
                                                     long                       _lEnd,
                                                     ACP_tdxBool                *bFirstTimeZ,
                                                     short                      *pwCurrentChar,
                                                     unsigned long              *ulDelay
                                                   )
{
 
 
  MS_tdxHandleTo3dData                  h_Current3dData      = NULL;
  static CHN_tdxHandleToChannelArray    hChannelArray        = NULL;
  tdstAChannel                          *p_stChannel         = NULL;
  POS_tdstCompletePosition              *hChannelLocalMatrix = NULL;
  HIE_tdxHandleToSuperObject            hChannelSuperObject  = NULL;
  HIE_tdxHandleToSuperObject            p_stSO_Child         = NULL;
  struct tdstObjectsTableElement_       *d_stCurrentObjectsTable = NULL;
  
  MTH_tdxReal       xJustificationShift   = 0.0;
  short             wCurrentLine          = 0,
                    wCurrentChar          = 0,
                    wCurrentChar4Channels = 0;
 
  unsigned short    uwLenOfString = 0,
                    uwIndexOfChar ;
 
 
  unsigned long ulEvent = 0;
 
  BOOL  bDisplayFullString = FALSE;
 
  char *pszEndText  = _pszText + (_lEnd >= 0 ? _lEnd : strlen(_pszText));
 
 
  if (*bFirstTimeZ==TRUE)
  {
      uwLenOfString = (unsigned short) strlen(_pszText);
  }
 
  wCurrentChar = *pwCurrentChar;
 
    /* Display full string*/
  if (wCurrentChar == -1)
  {
      bDisplayFullString = TRUE;
      wCurrentChar = 0;
  }
 
  /* Get the pointer where the scanning starts*/
  _pszText += _lStart;
  uwIndexOfChar = (unsigned short)_lStart ;
 
  /* Initialize all the stuff*/
  TFMT_vInitFormatterStatus(_p_stStatus, _hSuperObjPerso, MTH_C_ZERO);
 
  h_Current3dData         = M_GetMSHandle(_hSuperObjPerso,3dData);
  d_stCurrentObjectsTable = fn_h3dDataGetCurrentObjectsTable(h_Current3dData)->d_stObjectsTable;
  
 
  /* For each character in the text*/
  while ( (_pszText < pszEndText) && *_pszText )
  {
      /* For each character of the line, set the geometric object in the object table, and position the channel in the anim*/
      while ( _pszText < pszEndText )
      {
          ACP_tdxBool   bLineBreak;
          unsigned char ucChar ;
          short         wSourceObject,
                        wNbObjectsInSourceTable;
          
          /*read the next char in the text          */
          _pszText = TFMT_pszReadNextChar2(_p_stStatus, _hSuperObjPerso, _pszText, &ucChar, &bLineBreak, bDisplayFullString, &wCurrentChar, &ulEvent, &ulDelay, &wCurrentChar4Channels, &uwIndexOfChar );
 
          
          /* Number of object in the object table*/
          wNbObjectsInSourceTable = fn_uwGetObjectTableNumberOfelements(_p_stStatus->hSourceObjectTable);
 
          /* Source object in function of the value of the character*/
		  if ( ucChar < ' ' )
		  {
			wSourceObject = -1 ;
		  }
		  else
		  {
			  unsigned char ucTemp = fn_ucToTableElement ( ucChar ) ;
			  wSourceObject = (short) ( ucTemp + OffsetObjectTable ) ;
		  }
          
          if ( wSourceObject < 0 || wSourceObject >= wNbObjectsInSourceTable )
          {
              wSourceObject = 0 ;
              *pwCurrentChar = wCurrentChar;
              return ulEvent;
          }
          else
          {
              /******************************
              * Do this only the first time * 
              ******************************/
              if (*bFirstTimeZ==TRUE)
              {    
				  SAF_M_AssertWithMsg(!h_Current3dData->hArrayOfChannels, "Erreur interne dans TFMT_wPositionModulesAccordingToText2");
				  /* FQ TMP OVERFLOW BUG FIX */
#ifdef U64
				  if ((h_Current3dData) && (h_Current3dData->hArrayOfChannels))
				  {
					fn_vFreeCSOList(&h_Current3dData->hArrayOfChannels);
				  }
#endif
                  /* Set the number of true caracters in string*/
                  fn_v3dDataSetNumberOfChannels(h_Current3dData,  uwLenOfString );
 
                  /* Set number of channels*/
                  fn_vInitCSOList( &hChannelArray, fn_ul3dDataGetNumberOfChannels(h_Current3dData) );
                  fn_v3dDataSetChannelSOList( h_Current3dData, hChannelArray );
 
                  /* Set the first active channel*/
                  fn_v3dDataSetFirstActiveChannel(h_Current3dData, hChannelArray);
                  *bFirstTimeZ=FALSE;
              }
              else
              {
                  hChannelArray = h_Current3dData->hArrayOfChannels;
              }
 
              /* Build&Add child in channel*/
              p_stSO_Child = PLA_fn_hFindNextFreeSupObj();
 
              HIE_fn_vSuperObjectAddTail( _hSuperObjPerso, p_stSO_Child );
 
              /* Get the channel*/
              p_stChannel = &hChannelArray[wCurrentChar4Channels];
 
              /* take control of matrix  */
              p_stChannel->bControlledChannel = TRUE;
              
              POS_fn_vSetIdentityMatrix(p_stSO_Child->hLocalMatrix);
 
              /*Mettre le SO dans le channel.*/
              p_stChannel->hSupObject = p_stSO_Child;
              
              HIE_fn_vSetSuperObjectObjectAndType(p_stSO_Child,(d_stCurrentObjectsTable+wSourceObject)->h_Target,HIE_C_ulPO);
              HIE_fn_vSetSuperObjectTransparenceLevel( p_stSO_Child, 255.0f );
 
              if( wCurrentChar4Channels )
              {
                  hChannelArray[wCurrentChar4Channels-1].p_stNextActiveChannel = p_stChannel;
              }
              
              /* Get the current channel's superobject*/
              hChannelSuperObject = fn_hGetSuperObjectInChannel(fn_h3dDataGetChannelSOList(M_GetMSHandle(_hSuperObjPerso,3dData)), wCurrentChar4Channels);
              
              if ( hChannelSuperObject )
              {
                  MTH3D_tdstVector stV1, stV2, stV3;
 
                  /* Change its local position*/
                  hChannelLocalMatrix = HIE_fn_hGetSuperObjectMatrix(hChannelSuperObject);
 
                  MTH3D_M_vSetVectorElements(
                                              &stV1,
                                              MTH_M_xAdd( 
                                                         MTH_M_xAdd( 
                                                                    xJustificationShift, 
                                                                    MTH_M_xAdd(
                                                                                _p_stStatus->xBaseCharX, 
                                                                                RND_fn_xGetRealRandomValue (gs_hRandomHandleForTFMT, MTH_M_xNeg(_p_stStatus->xRandomPosRadius), _p_stStatus->xRandomPosRadius)
                                                                              )
                                                                  ), 
                                                         MTH_M_xMul(_p_stStatus->xCurCharWidth, MTH_M_xFloatToReal(0.5f))
                                                       ),
                                              MTH_C_ZERO,
                                              MTH_M_xAdd(_p_stStatus->xBaseCharZ, RND_fn_xGetRealRandomValue(gs_hRandomHandleForTFMT, MTH_M_xNeg(_p_stStatus->xRandomPosRadius), _p_stStatus->xRandomPosRadius))
                                            );               
                  POS_fn_vSetTranslationVector(hChannelLocalMatrix, &stV1);
 
                  /* And its local scale*/
                  if ( MTH_M_bDifferentWithEpsilon(_p_stStatus->xCurCharZoom, MTH_C_ONE, MTH_M_xDoubleToReal(0.0001)) )
                  {
                      MTH3D_M_vSetVectorElements(&stV1,	_p_stStatus->xCurCharZoom, MTH_C_ZERO, MTH_C_ZERO);
                      MTH3D_M_vSetVectorElements(&stV2,	MTH_C_ZERO, _p_stStatus->xCurCharZoom, MTH_C_ZERO);
                      MTH3D_M_vSetVectorElements(&stV3, MTH_C_ZERO, MTH_C_ZERO, _p_stStatus->xCurCharZoom);
                      POS_fn_vSetScaleMatrix(hChannelLocalMatrix, &stV1, &stV2, &stV3);				
                  }
              }
          }
          wCurrentChar4Channels ++;
          *pwCurrentChar = ++wCurrentChar;
      }
      wCurrentLine ++;
  }
 
  /* Set the last active channel*/
 
/* begin Marc*/
  if(p_stChannel != NULL)
	p_stChannel->p_stNextActiveChannel = NULL;
/* end Marc*/
 
  /*return the number of lines that got filled in the info array*/
  return ulEvent;
}
 
 
 
/*-----------------------------------------------------
 - Christophe Giraud                                  -
 - Le 11/07/98                                        -
 -----------------------------------------------------*/
void TFMT_vChangeLetter
(
	HIE_tdxHandleToSuperObject hSuperObjPerso ,
	unsigned char ucPosLetter ,
	unsigned char ucLetter
)
{
	MS_tdxHandleTo3dData              h_Current3dData          = NULL ;
	CHN_tdxHandleToChannelArray       hChannelArray            = NULL ;
	tdstAChannel                      *p_stChannel             = NULL ;
	/* XB 05/05/99 */
	/*  POS_tdstCompletePosition          *hChannelLocalMatrix     = NULL; */
	/*  HIE_tdxHandleToSuperObject        hChannelSuperObject      = NULL; */
	/*  HIE_tdxHandleToSuperObject        p_stSO_Child             = NULL; */
	/* End XB 05/05/99 */
	struct tdstObjectsTableElement_   * d_stCurrentObjectsTable = NULL ;

	short wSourceObject = 0 , wNbObjectsInSourceTable = 0 ;


	h_Current3dData         = M_GetMSHandle(hSuperObjPerso,3dData);
	d_stCurrentObjectsTable = fn_h3dDataGetCurrentObjectsTable(h_Current3dData)->d_stObjectsTable;
	hChannelArray           = h_Current3dData->hArrayOfChannels;


	/* Number of object in the object table*/
	wNbObjectsInSourceTable = fn_uwGetObjectTableNumberOfelements( fn_hGetObjectsTableOfFamilyByIndex( fn_h3dDataGetFamily(h_Current3dData), 0 ) );

	/* Source object in function of the value of the character */
	if ( ucLetter < ' ' )
	{
		wSourceObject = -1 ;
	}
	else
	{
		unsigned char ucTemp = fn_ucToTableElement ( ucLetter ) ;
		wSourceObject = (short) ( ucTemp + OffsetObjectTable ) ;
	}

	if ( ( wSourceObject < 0 ) || ( wSourceObject >= wNbObjectsInSourceTable ) )
	{
		wSourceObject = 0 ;
	}
	else
	{
		/* Get the channel*/
		p_stChannel = &hChannelArray[ucPosLetter];   
		HIE_fn_vSetSuperObjectObjectAndType( p_stChannel->hSupObject,(d_stCurrentObjectsTable+wSourceObject)->h_Target,HIE_C_ulPO);   
	}
}
 
 
 
/********************************************************************
* Function : Init all datas for management of TEXT_Affiche function *
* Autor    : Giraud Christophe                                      *
* Historic : Created on 13/10/98                                    *
********************************************************************/
void TFMT_vInitTextAfficheStructure()
{
    register int iCpt = 0;
    register int iSizeOfStructure = sizeof(tdstInfoTextAffiche);
    for(;iCpt<MAX_TEXTAFFICHE;iCpt++)
    {
        memset( &g_stInfoTextAffiche[iCpt], 0x00, iSizeOfStructure );
        g_stInfoTextAffiche[iCpt].bFirstInit = TRUE;
        g_bFreeTextAfficheBlocs[iCpt]        = TRUE;
        gp_SuperObjPersoGenerated[iCpt]      = NULL;
    }
    /*g_ucTextAfficheId = 0;*/
}
 
/********************************************************************
* Function : return a free number of TEXT_Affiche function          *
* Autor    : Giraud Christophe                                      *
* Historic : Created on 13/10/98                                    *
********************************************************************/
unsigned char TFMT_ucNumberOfCurrentTextAffiche( HIE_tdxHandleToSuperObject p_SuperObjPersoTreated )
{
    register unsigned char i;
    for(i=0;i<MAX_TEXTAFFICHE;i++)
    {
        if( p_SuperObjPersoTreated == gp_SuperObjPersoGenerated[i] )
        {
            return i;
        }
    }
	SAF_M_AssertWithMsg(FALSE, "Erreur interne dans TFMT_ucNumberOfCurrentTextAffiche!" );
	/* prevent a compilation warning, but we should NEVER get here! */
	return i ;
}
 
/**************************************************************************
* Function : Search and assign a number for the new TEXT_Affiche function *
* Autor    : Giraud Christophe                                            *
* Historic : Created on 13/10/98                                          *
**************************************************************************/
unsigned char TFMT_ucSetNumber4CurrentTextAffiche( void )
{
    register unsigned char i;
    for(i=0;i<MAX_TEXTAFFICHE;i++)
    {
        if( g_bFreeTextAfficheBlocs[i] )
        {
            g_bFreeTextAfficheBlocs[i] = FALSE;
            return i;
        }
    }
 
    /* If we are here there is a number of Text_Affiche Id greater than MAX_TEXTAFFICHE*/
    /* Then we overwrite the last Id !!!*/
    return i;
}
 
/***************************************************************
* Function : Clear the Id of the current TEXT_Affiche function *
* Autor    : Giraud Christophe                                 *
* Historic : Created on 13/10/98                               *
***************************************************************/
void TFMT_ucClearNumberOfCurrentTextAffiche( HIE_tdxHandleToSuperObject p_SuperObjPersoTreated )
{
    register unsigned char i;
 
    for(i=0;i<MAX_TEXTAFFICHE;i++)
    {
        if( p_SuperObjPersoTreated == gp_SuperObjPersoGenerated[i] )
        {
            g_bFreeTextAfficheBlocs[i] = TRUE;
			gp_SuperObjPersoGenerated[i] = NULL ;
            memset( &g_stInfoTextAffiche[i], 0x00, sizeof(tdstInfoTextAffiche) );
            g_stInfoTextAffiche[i].bFirstInit = TRUE;
            break;
        }
    }
}
 
 
/************************************************************************************************
 * misc functions for text table managment
 ************************************************************************************************/
void TFMT_vInitScapingTable ( MTH_tdxReal xValue ) {
  long i ;
 
  for (i=0 ; i<TFMT_MAX_WIDTHTABLEELMENT ; i++ ) {
    TFMT_ga_fLetterSpacing[i] = xValue ;
  }
}
 
void TFMT_vUpdateSpacingTable ( char *szText ) {
  char *szCur ;
  int i ;
 
  szCur = strtok (szText, ":") ;
  TFMT_ga_fLetterSpacing[0] = MTH_M_xDiv(MTH_M_xLongToReal(atol ( szCur )), MTH_M_xDoubleToReal(1000.0)) ;
  i=1 ;
  while ( szCur != NULL && i<TFMT_MAX_WIDTHTABLEELMENT ) {
    szCur = strtok (NULL, ":") ;
    if ( szCur != NULL ) {
      TFMT_ga_fLetterSpacing[i++] = MTH_M_xDiv(MTH_M_xLongToReal(atol ( szCur )), MTH_M_xDoubleToReal(1000.0)) ;
      *(szCur-1) = ':' ;
    }
  }
}
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
void TFMT_vInitScaleTable ( MTH_tdxReal xValue ) {
  long i ;
 
  for (i=0 ; i<TFMT_MAX_WIDTHTABLEELMENT ; i++ ) {
    TFMT_ga_fLetterScale[i] = xValue ;
  }
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
void TFMT_vUpdateScaleTable ( char *szText ) {
  char *szCur ;
  int i ;
 
  szCur = strtok (szText, ":") ;
  TFMT_ga_fLetterScale[0] = MTH_M_xDiv(MTH_M_xLongToReal(atol ( szCur )), MTH_M_xDoubleToReal(1000.0)) ;
  i=1 ;
  while ( szCur != NULL && i<TFMT_MAX_WIDTHTABLEELMENT ) {
    szCur = strtok (NULL, ":") ;
    if ( szCur != NULL ) {
      TFMT_ga_fLetterScale[i++] = MTH_M_xDiv(MTH_M_xLongToReal(atol ( szCur )), MTH_M_xDoubleToReal(1000.0)) ;
      *(szCur-1) = ':' ;
    }
  }
  TFMT_ga_ulNbScale = i ;
}
