// Speech.c

#include "ult_64.h"
#include "define.h"
#include "ml.h"

#include "menu.h"
#include "misc.h"
#include "audio.h"
#include "speech.h"

#include "playbyplay.h"
#include "colorguy.h"


extern int
	si___gPlyrRomCnt;


#define QUEUE_SIZE 16

#define BALANCE_LEFT  0
#define BALANCE_RIGHT 1

#define	QPos(x)	((x)%QUEUE_SIZE)

#define	DB_OR 0

#if defined(DEBUG) || DB_OR
	void Speech_Dump(char *msg);
#else
	#define	Speech_Dump(x)
#endif

typedef struct SQueue
{
	void
		*Bank;
	s16
		Index,
		Delay;
	u8
		Balance,
		Player,
		Announcer,
		pad;
} SQueue;


extern int
	lp_ctr;


#ifdef DEBUG
	static u32 ReturnAddress;
#endif


static void
	*PlayByPlay,
	*ColorGuy,
	*Players;

static u32
	*NickNames;

static s32
	AudioId,
	Check,
	Delay,
	Player,
	Time,
	Head,
	Tail,
	Count,
	Volume = AUDIO_MAX_VOLUME;

SpeechGuy
	Announcer;

static SQueue
	Queue[QUEUE_SIZE],
	Current;

static s16
	TeamNames[][2]=
	{
		{SFX_ATLANTA,SFX_ATLANTAHAWKS},				// Atlanta Hawks
		{SFX_BOSTON,SFX_BOSTONCELTICS},				// Boston Celtics
		{SFX_CHARLOTTE,SFX_CHARLOTTEHORNETTS},		// Charlotte Hornets
		{SFX_CHICAGO,SFX_CHICAGOBULLS},				// Chicago Bulls
		{SFX_CLEVELAND,SFX_CLEVELANDCAVALIERS},		// Cleveland Cavaliers
		{SFX_DALLAS,SFX_DALLASMAVERICKS},			// Dallas Mavericks
		{SFX_DENVER,SFX_DENVERNUGGETS},				// Denver Nuggets
		{SFX_DETROIT,SFX_DETROITPISTONS},			// Detroit Pistons
		{SFX_GOLDENSTATE,SFX_GOLDENSTATEWARRIORS},	// Golden State Warriors
		{SFX_HOUSTON,SFX_HOUSTONROCKETS},			// Houston Rockets
		{SFX_INDIANA,SFX_INDIANAPACERS},			// Indiana Pacers
		{SFX_LOSANGELES,SFX_LOSANGELESCLIPPERS},	// Los Angeles Clippers
		{SFX_LOSANGELES,SFX_LOSANGELESLAKERS},		// Los Angeles Lakers
		{SFX_MIAMI,SFX_MIAMIHEAT},					// Miami Heat
		{SFX_MILWAUKEE,SFX_MILWAUKEEBUCKS},			// Milwaukee Bucks
		{SFX_MINESOTTA,SFX_MINESOTATIMBERWOLVES},	// Minnesota Timberwolves
		{SFX_NEWJERSEY,SFX_NEWJERSEYNETS},			// New Jersey Nets
		{SFX_NEWYORK,SFX_NEWYORKKNICKS},			// New York Knicks
		{SFX_ORLANDO,SFX_ORLANDOMAGIC},				// Orlando Magic
		{SFX_PHILADELPHIA,SFX_PHILADELPHIA76ERS},	// Philadelphia 76ers
		{SFX_PHEONIX,SFX_PHEONIXSUNS},				// Phoenix Suns
		{SFX_PORTLAND,SFX_PORTLANDTRAILBLAZERS},	// Portland Trail Blazers
		{SFX_SACRAMENTO,SFX_SACRAMENTOKINGS},		// Sacramento Kings
		{SFX_SANANTONIO,SFX_SANANTONIOSPURS},		// San Antonio Spurs
		{SFX_SEATTLE,SFX_SEATTLESONICS},			// Seattle SuperSonics
		{SFX_TORONTO,SFX_TORONTORAPTORS},			// Toronto Raptors
		{SFX_UTAH,SFX_UTAHJAZZ},					// Utah Jazz
		{SFX_VANCOUVER,SFX_VANCOUVERGRIZZLIES},		// Vancouver Grizzlies
		{SFX_WASHINGTON,SFX_WASHINGTONWIZARDS},		// Washington Wizards
		{SFX_EAST,SFX_EASTERN},		// Eastern All-Stars
		{SFX_WEST,SFX_WESTERN},		// Western All-Stars
		{SFX_LEFTFIELDLEFTIES,SFX_LEFTFIELDLEFTIES},		// LFP
		{SFX_NINTENDOGAMERS,SFX_NINTENDOGAMERS},		// Nintendo
		{SFX_NOAPLUMMERS,SFX_NOAPLUMMERS},		// NOA
	};

static s16
	StuTeams[] =
	{
		-1,									// Null Team
		SFX_HAWKSS,					// Atlanta Hawks
		SFX_CELTICSS,					// Boston Celtics
		SFX_HORNETSS,				// Charlotte Hornets
		SFX_BULLSS,					// Chicago Bulls
		SFX_CAVALIERSS,			// Cleveland Cavaliers
		SFX_MAVERICKSS,				// Dallas Mavericks
		SFX_NUGGETSS,					// Denver Nuggets
		SFX_PISTONSS,				// Detroit Pistons
		SFX_WARRIORSS,			// Golden State Warriors
		SFX_ROCKETSS,				// Houston Rockets
		SFX_PACERSS,					// Indiana Pacers
		SFX_CLIPPERSS,			// Los Angeles Clippers
		SFX_LAKERSS,				// Los Angeles Lakers
		SFX_HEATS,						// Miami Heat
		SFX_BUCKSS,				// Milwaukee Bucks
		SFX_TWOLVESS,				// Minnesota Timberwolves
		SFX_NETSS,					// New Jersey Nets
		SFX_KNICKSS,					// New York Knicks
		SFX_MAGICS,					// Orlando Magic
		SFX_76ERSS,			// Philadelphia 76ers
		SFX_SUNSS,					// Phoenix Suns
		SFX_TRIALBLAZERSS,			// Portland Trail Blazers
		SFX_KINGSS,				// Sacramento Kings
		SFX_SPURSS,				// San Antonio Spurs
		SFX_SONICSS,					// Seattle SuperSonics
		SFX_RAPTORSS,				// Toronto Raptors
		SFX_JAZZS,						// Utah Jazz
		SFX_GRIZZLIES,			// Vancouver Grizzlies
		SFX_WIZARDSS,				// Washington Wizards

		SFX_EASTALLS,					// Eastern All-Stars
		SFX_WESTALLS,					// Western All-Stars
		SFX_LEFTFIELDS,				// LFP
		SFX_NINTENDOS,				// Nintendo
		SFX_NOAS,						// NOA
	};


void Speech_Init()
{
	AudioId = 0;
	Check = 0;
	Delay = 0;
	Player = -1;
	Time = 0;

	Head = 0;
	Tail = 0;
	Count = 0;

	Announcer=Chick;

	PlayByPlay = Audio_LoadBank( "CHICK.BNK" );
	ColorGuy = Audio_LoadBank( "STU.BNK" );
	Players = Audio_LoadBank( "PLAYERS.BNK" );

	NickNames = (u32 *)AllocAndLoadFile( "NickName.BIT", MEM_ANY );
}


void Speech_Deinit()
{
	if (AudioId)
		Audio_SfxStop( AudioId );

	Audio_Process();

	MemFree( NickNames );

	Audio_Process();

	Audio_FreeBank( Players );
	Audio_FreeBank( ColorGuy );
	Audio_FreeBank( PlayByPlay );
}


void Speech_Volume( const u32 volume )
{
	Volume = volume;
}


#if 0

static s32 CheckQueue()
{
	SQueue
		*queue;
	s32
		i,
		ok = TRUE;

	for (i=0; i<Count; i++)
	{
		queue = &Queue[QPos(Head+i)];

		if (queue->Special == 1)
			ok = FALSE;
		else if (queue->Special == 2)
			ok = TRUE;
	}

	return( ok );
}


static void ShowQueue()
{
	SQueue
		*queue;
	char
		text[64];
	s32
		i,
		c = 0;

	for (i=0; i<Count; i++)
	{
		queue = &Queue[QPos(Head+i)];

		text[c++] = '0' + queue->Special;
	}

	text[c++] = ' ';

	for (i=0; i<Count; i++)
	{
		queue = &Queue[QPos(Head+i)];

		text[c++] = '0' + queue->Announcer;
	}

	text[c++] = ' ';

	if (Speech_IsBusy())
		text[c++] = '1';
	else
		text[c++] = '0';

	text[c++] = '0' + Announcer;

	text[c++] = 0;

	_BlastMessage( text, __FILE__, __LINE__ );
}

#endif


void Speech_Process()
{
	SQueue
		*queue;

	if (menuFlag)
		return;

	if (AudioId)
	{
		if (Check == 2)
		{
			if (Audio_SfxActive( AudioId ))
				return;

			Check = 0;
			AudioId = 0;
		}
		else
			Check++;
	}
	else
	{
		if (Count)
		{
			queue = &Queue[Head];

			if (queue->Delay)
				queue->Delay--;
			else
			{
				if (queue->Player)
					Time = lp_ctr;

				Current=*queue;
				AudioId = Audio_SfxPlay( queue->Bank, queue->Index, AUDIO_MAX_VOLUME );

				Check = 0;

				if (queue->Balance == BALANCE_LEFT)
					Audio_SfxBalance( AudioId, Volume, Volume>>1 );
				else
					Audio_SfxBalance( AudioId, Volume>>1, Volume );

				Head = (Head + 1) & (QUEUE_SIZE-1);
				Count--;
			}
		}
	}
}


void Speech_Delay( const s32 delay )
{
#ifdef DEBUG

	char
		text[64],
		numstr[16];

	if (delay < 0 || delay > (2*60*30))
	{
		memset( numstr, 0, 16 );
		IntToDecStr( delay, numstr );
		sprintf( text, "Invalid delay of %s", numstr );
		FatalError( text, __FILE__, __LINE__ );
	}

#endif

	Delay = delay;
}


bool Speech_DoPriority(SpeechGuy who)
{
	int	i;

	// Check to see if the announcement should be queued or dropped
	if (who==Chick)		// Handle queueing of Chick's stuff
	{
		// If Stu is currently talking, just wait until he's done
		if (Speech_IsBusy() && Current.Announcer==Stu)
		{
#if defined(DEBUG)
			char	msg[128];
			char	num[16];

			memset(num,0,16);
			IntToDecStr(lp_ctr,num);

			sprintf(msg,"%s: Fini Kicked Chick\n",num);
			PCwrite(-1,msg,strlen(msg));
#endif
			return FALSE;
		}

		// If it's Stu's turn, but he's not talking, see if he wants to
		if (who!=Announcer)
		{
			for (i=0; i<Count; i++)
				if (Queue[QPos(Tail-1-i)].Announcer==Stu)
				{
#if defined(DEBUG)
					{
						char	msg[128];
						char	num[16];

						memset(num,0,16);
						IntToDecStr(lp_ctr,num);

						sprintf(msg,"%s: Kicked Chick\n",num);
						PCwrite(-1,msg,strlen(msg));
					}
#endif
					return FALSE;
				}
		}
		else // De-queue Stu stuff if necessary
		{
			for (i=Count; i>0; --i)
			{
				if (Queue[QPos(Tail-1)].Announcer==Stu)
				{
					Count--;
					Tail=QPos(Tail-1);

#if defined(DEBUG)
					{
						char	msg[128];
						char	num[16];

						memset(num,0,16);
						IntToDecStr(lp_ctr,num);

						sprintf(msg,"%s: Kicked Stu\n",num);
						PCwrite(-1,msg,strlen(msg));
					}
#endif

				}
				else
					break;
			}

			return TRUE;
		}
	}
#if 0
	else	// Handle Stu's stuff
	{
		// Only speak during Chick's time if nothing is being said
		if (who!=Announcer)
		{
		}
	}
#endif

	return TRUE;
}


void Speech_Queue(const s32 id, SpeechGuy who)
{
	bool
		talk=FALSE;

	SQueue
		*queue;

//	if (!Speech_DoPriority(who))
//		return;

	if (PracticeMode)
		return;

	if (Count < QUEUE_SIZE)
	{
		Player = -1;

		queue = &Queue[Tail];

		queue->Bank				= (who==Chick)? PlayByPlay : ColorGuy;
		queue->Index			= id;
		queue->Delay			= Delay;
		queue->Balance		= (who == Chick) ? BALANCE_LEFT : BALANCE_RIGHT;
		queue->Player			= FALSE;
		queue->Announcer	= who;

		Delay = 0;
		Tail = (Tail + 1) & (QUEUE_SIZE-1);
		Count++;
	}
#ifdef DEBUG
	else
	{
		asm( "sw $31,ReturnAddress" );
		FatalError( "Queue full in Speech_PlayByPlay()", __FILE__, __LINE__ );
	}
#endif
}

void Speech_PlayByPlay( const s32 id )
{
	Speech_Queue(id,Chick);
}


void Speech_PriorityGuy(SpeechGuy who)
{
	Announcer=who;
}


void Speech_PlayByPlay_Team(int team, int type)
{
	s32
		t;

	t = TROM(team)->ub___tTeam;

	Speech_PlayByPlay( TeamNames[t-1][type] );
}


static s16	Hundies[]={ SFX_100AND, SFX_200AND, SFX_300AND };
static s16	Nummies[]=
				{
					SFX_1,  SFX_2,  SFX_3,  SFX_4,  SFX_5,  SFX_6,  SFX_7,  SFX_8,  SFX_9,  SFX_10,
					SFX_11, SFX_12, SFX_13, SFX_14, SFX_15, SFX_16, SFX_17, SFX_18, SFX_19, SFX_20,
					SFX_21, SFX_22, SFX_23, SFX_24, SFX_25, SFX_26, SFX_27, SFX_28, SFX_29, SFX_30,
					SFX_31, SFX_32, SFX_33, SFX_34, SFX_35, SFX_36, SFX_37, SFX_38, SFX_39, SFX_40,
					SFX_41, SFX_42, SFX_43, SFX_44, SFX_45, SFX_46, SFX_47, SFX_48, SFX_49, SFX_50,
					SFX_51, SFX_52, SFX_53, SFX_54, SFX_55, SFX_56, SFX_57, SFX_58, SFX_59, SFX_60,
					SFX_61, SFX_62, SFX_63, SFX_64, SFX_65, SFX_66, SFX_67, SFX_68, SFX_69, SFX_70,
					SFX_71, SFX_72, SFX_73, SFX_74, SFX_75, SFX_76, SFX_77, SFX_78, SFX_79, SFX_80,
					SFX_81, SFX_82, SFX_83, SFX_84, SFX_85, SFX_86, SFX_87, SFX_88, SFX_89, SFX_90,
					SFX_91, SFX_92, SFX_93, SFX_94, SFX_95, SFX_96, SFX_97, SFX_98, SFX_99, SFX_100,
				};

void Speech_PlayByPlay_Number(int num)
{
	int	dig;

	// Do simple numbers here
	if (!num)
	{
		Speech_PlayByPlay(SFX_ZERO);
		return;
	}
	if (num==100)
	{
		Speech_PlayByPlay(SFX_100);
		return;
	}
	else if (num>100 && num<110)
	{
		Speech_PlayByPlay(SFX_1_O);
		Speech_PlayByPlay(Nummies[num-101]);
		return;
	}

	if (num == 200)
	{
		Speech_PlayByPlay( SFX_2 );
		Speech_PlayByPlay( SFX_ZERO );
		Speech_PlayByPlay( SFX_ZERO );
		return;
	}

	if (num == 300)
	{
		Speech_PlayByPlay( SFX_3 );
		Speech_PlayByPlay( SFX_ZERO );
		Speech_PlayByPlay( SFX_ZERO );
		return;
	}

	if (num >= 400)
	{
		Speech_PlayByPlay( Nummies[(num/100)-1] );

		num = num % 100;
		if (num < 10)
		{
			dig = num / 10;
			if (dig == 0)
				Speech_PlayByPlay( SFX_ZERO );
			else
				Speech_PlayByPlay( Nummies[dig-1] );

			num = num % 10;

			if (num == 0)
				Speech_PlayByPlay( SFX_ZERO );
			else
				Speech_PlayByPlay( Nummies[num-1] );

			return;
		}

		Speech_PlayByPlay( Nummies[num-1] );
		return;
	}

	// Over 100?
	if (num>100)
		Speech_PlayByPlay(Hundies[(num/100)-1]);
	
	dig=num%100;
	Speech_PlayByPlay(Nummies[dig-1]);
}


void Speech_PlayByPlay_Player( playert *plyr, s32 type )
{
	static u16
		positions[][4] =
		{
			SFX_POINTGUARD,
			SFX_POINTGUARDX,
			SFX_POINTGUARDTO,
			SFX_POINTGUARD,

			SFX_SHOOTINGGUARD,
			SFX_SHOOTINGGUARDX,
			SFX_SHOOTINGGUARDTO,
			SFX_SHOOTINGGUARD,

			SFX_SMALLFORWARD,
			SFX_SMALLFORWARDX,
			SFX_SMALLFORWARDTO,
			SFX_SMALLFORWARD,

			SFX_POWERFORWARD,
			SFX_POWERFORWARDX,
			SFX_POWERFORWARDTO,
			SFX_POWERFORWARD,

			SFX_CENTER,
			SFX_CENTERX,
			SFX_CENTERTO,
			SFX_CENTER,
		};
	SQueue
		*queue;
	u32
		mask;
	s32
		pnum,
		index;

	Speech_Dump("Chick player added to queue.\n");

#if 0
	if (!Speech_DoPriority(Chick))
	{
#if 0
		if (type != SPEECH_TO)
			PCwrite( -1, "DoPriority failed!\n", 19 );
#endif

		return;
	}
#endif

	if (PracticeMode)
		return;

	if (Count < QUEUE_SIZE)
	{
		pnum = plyr->plyrROM->uw___pIndx;

		if (pnum >= si___gPlyrRomCnt)			// Hack for custom players!
		{
			Speech_PlayByPlay( positions[plyr->no - plyr->base][type] );
			return;
		}

		Player = pnum;
		index = (pnum * 6) + type;

		if (type == SPEECH_NICKNAME)
		{
			mask = 1 << (index & 31);
			if (!(NickNames[index >> 5] & mask))
//				type = SPEECH_NORMAL;
				index = (pnum * 6) + SPEECH_NORMAL;
		}

		queue = &Queue[Tail];

		queue->Bank				= Players;
		queue->Index			= index;
		queue->Delay			= Delay;
		queue->Balance		= BALANCE_LEFT;
		queue->Player			= TRUE;
		queue->Announcer	= Chick;

		Delay = 0;
		Tail = (Tail + 1) & (QUEUE_SIZE-1);
		Count++;
	}
#ifdef DEBUG
	else
	{
		asm( "sw $31,ReturnAddress" );
		FatalError( "Queue full in Speech_PlayByPlay_Player()", __FILE__, __LINE__ );
	}
#endif
}


void Speech_ColorGuy( const s32 id )
{
	Speech_Queue(id,Stu);
}


void Speech_ColorGuy_Player( s32 pnum )
{
	SQueue
		*queue;
	u32
		mask;

	if (PracticeMode)
		return;

	if (Count < QUEUE_SIZE)
	{
		Player = pnum;

		if (pnum >= si___gPlyrRomCnt)			// Hack for custom players!
		{
			Speech_ColorGuy( SFX_THENEWCOMER );
			return;
		}

		queue = &Queue[Tail];

		queue->Bank				= Players;
		queue->Index			= (pnum * 6) + 4;
		queue->Delay			= Delay;
		queue->Balance		= BALANCE_RIGHT;
		queue->Player			= TRUE;
		queue->Announcer	= Stu;

		Delay = 0;
		Tail = (Tail + 1) & (QUEUE_SIZE-1);
		Count++;
	}
#ifdef DEBUG
	else
	{
		asm( "sw $31,ReturnAddress" );
		FatalError( "Queue full in Speech_PlayByPlay_Player()", __FILE__, __LINE__ );
	}
#endif
}


void Speech_ColorGuy_Team( int team )
{
	Speech_ColorGuy( StuTeams[TROM(team)->ub___tTeam] );
}


s32 Speech_IsBusy()
{
	return( AudioId );
}


s32 Speech_IsQueued()
{
	return( Count );
}


s32 Speech_LastPlayer()
{
	return( Player );
}


s32 Speech_PlayerTime()
{
	return( Time );
}


s32 Speech_IsAnnouncing( SpeechGuy who )
{
	SQueue
		*queue;
	s32
		i,
		c;

	if (AudioId && Current.Announcer == who)
		return( TRUE );

	i = Head;
	for (c=0; c<Count; c++)
	{
		queue = &Queue[i];

		if (queue->Announcer == who)
			return( TRUE );

		i = (i + 1) & (QUEUE_SIZE-1);
	}

	return( FALSE );
}


void Speech_Pause( const s32 pause )
{
	if (pause)
	{
		Audio_SfxStop( AudioId );
		AudioId = 0;
	}
}


typedef struct SAttract
{
	s16
		Frame,
		SfxId;
} SAttract;


void Speech_Attract( const s32 frame )
{
	static const SAttract
		c_list[] =
		{
			-1, -1,			// RICHMOND DUNK
			177-147, SFX_HEGOESINSIDE,
			198-147, SFX_SLAMDUNK,

			-1, -1,			// KOBE DUNK
			155-125, SFX_HEGOESUP2,

			-1, -1,			// IVERSON DUNK
			163-127, SFX_FLYSLIKEANEAGLE,

			-1, -1,			// Hill dunk

			-1, -1,			// Kobe face
			-1, -1,			// Shaq face
			-1, -1,			// Van Horn face
			-1, -1,			// Pippen face
			-1, -1,			// Morning face

			-1, -1,			// KOBE ARCADE
			178-133, SFX_HESLAMSITHOME,
			-1, -1,			// van horn arcade
			163-155, SFX_BIGLEAP8,
			-1, -1,			// Hill arcade
			-1, -1,			// richmond arcade

			-1, -1,			// KOBE DRIBBLES
			3, SFX_KOBEPHENOMENAL,
			-1, -1,			// KOBE DRIBBLES
			-1, -1,			// KOBE DRIBBLES

			-1, -1,			// DUNCAN SIG
			0, SFX_DUNCUN3,
			-1, -1,			// Pippen sig
			-1, -1,			// IVERSON SIG
			0, SFX_IVERSON2,
			-1, -1,			// Shaq sig

			-1, -1,
		},
		s_list[] =
		{
			-1, -1,			// RICHMOND DUNK
			-1, -1,			// KOBE DUNK
			168-125, SFX_WINDMILLDUNK,
			-1, -1,			// IVERSON DUNK
			-1, -1,			// Hill dunk
			173-141, SFX_LOOKATTHATJAM,

			-1, -1,			// Kobe face
			-1, -1,			// Shaq face
			-1, -1,			// Van Horn face
			-1, -1,			// Pippen face
			-1, -1,			// Morning face

			-1, -1,			// KOBE ARCADE
			-1, -1,			// van horn arcade
			206-155, SFX_OHMY,
			-1, -1,			// Hill arcade
			173-106, SFX_GUYONFIRE,
			-1, -1,			// richmond arcade
			209-152, SFX_WHOAH,

			-1, -1,			// KOBE DRIBBLES
			-1, -1,			// KOBE DRIBBLES
			-1, -1,			// KOBE DRIBBLES
			0, SFX_THATKIDISAMAZING,

			-1, -1,			// DUNCAN SIG
			-1, -1,			// Pippen sig
			174-114, SFX_THATWASSOMEDUNK,
			-1, -1,			// IVERSON SIG
			-1, -1,			// Shaq sig

			-1, -1,
		};
	static const SAttract
		*c_ptr,
		*s_ptr;
	s32
		count;

	if (frame < 0)
	{
		c_ptr = c_list;
		count = frame;
		while (count)
		{
			while (c_ptr->Frame != -1)
				c_ptr++;

			c_ptr++;
			count++;
		}

		s_ptr = s_list;
		count = frame;
		while (count)
		{
			while (s_ptr->Frame != -1)
				s_ptr++;

			s_ptr++;
			count++;
		}

		return;
	}


// Chick...
	if (frame == c_ptr->Frame)
	{
		Speech_PlayByPlay( c_ptr->SfxId );

		c_ptr++;
	}

// Stu...
	if (frame == s_ptr->Frame)
	{
		Speech_ColorGuy( s_ptr->SfxId );

		s_ptr++;
	}
}


#if defined(DEBUG) || DB_OR
void Speech_Dump(char *msg)
{
	char	num[16];
	char	txt[128];

	memset(num,0,sizeof(num));
	IntToDecStr(lp_ctr,num);

	sprintf(txt,"%s: %s\n",num,msg);

	PCwrite(-1,txt,strlen(txt));
}

#endif
