/* tmsg.c -- text message area	:ts=4 */

/*
Copyright (c) 1989 Commodore-Amiga, Inc.

Executables based on this information may be used in software
for Commodore Amiga computers. All other rights reserved.
This information is provided "as is"; no warranties are made.
All use is at your own risk, and no liability or responsibility
is assumed.
*/

#include "sysall.h"
#include "tmsg.h"

#define D(x)	;
#define DTLE(x)	;
#define DTF(x)	;

struct TextMsg	*
CreateTextMsg( totalchars )
{
	struct TextMsg	*tm;

	if ( tm =  (struct TextMsg *) AllocMem(
		sizeof (struct TextMsg) + totalchars, MEMF_CLEAR) )
	{
		tm->tm_Buffer = (UBYTE *) (tm + 1);
		tm->tm_BufSize = totalchars;
		LimitTextMsg( tm, -1 );
	}
	return ( tm );
}

DeleteTextMsg( tm, num )
struct TextMsg	*tm;
{
	struct TextMsg	*next;
	while ( tm && num-- )
	{
		next = tm->tm_Next;
		FreeMem( tm, (long) sizeof *tm + tm->tm_BufSize );
		tm = next;
	}
}

/* support only one-liners for now	*/
ChangeTextMsg( rp, tm, str, p1, p2, p3, p4, p5, p6  )
struct RastPort	*rp;
struct TextMsg	*tm;
UBYTE			*str;
{
	D( printf("CTM: erase, rp %lx, tm %lx\n", rp, tm ) );
	if ( rp )  EraseTextMsg( rp, tm, 1 );

	if ( str ) sprintf( tm->tm_Buffer, str, p1, p2, p3, p4, p5, p6 );
	else		tm->tm_Buffer[ 0 ] = '\0';

	if ( rp )	RefreshTextMsg( rp, tm, 1 );
}

TextMsgSize( rp, tm, widthp, heightp )
struct RastPort		*rp;
struct TextMsg		*tm;
UWORD				*widthp;
UWORD				*heightp;
{
	struct Rectangle	tmrect;
	TextMsgExtent( rp, tm, &tmrect );

	if ( widthp ) *widthp = tmrect.MaxX - tmrect.MinX + 1;
	if ( heightp ) *heightp = tmrect.MaxY - tmrect.MinY + 1;
}


TextMsgExtent( rp, tm, rect )
struct RastPort		*rp;
struct TextMsg		*tm;
struct Rectangle	*rect;
{
	D( printf("TME: rp %lx tm %lx rect %lx\n", rp, tm, rect ) );

	rect->MinX = rect->MaxX = tm->tm_Left;
	rect->MinY = rect->MaxY = tm->tm_Top;

	rect->MaxY += rp->TxHeight - 1;
	rect->MaxX += textLength( rp, tm->tm_Buffer) - 1;

	D( printf("TME: extent %d %d %d %d\n",
		rect->MinX, rect->MinY, rect->MaxX, rect->MaxY ) );

}

/*
 * -1 means no limit
 */
LimitTextMsg( tm, limitwidth )
struct TextMsg	*tm;
{

	tm->tm_LimitWidth = limitwidth;
}


/*
 * num = -1 means do all
 */
RefreshTextMsg( rp, tm, num )
struct RastPort	*rp;
struct TextMsg	*tm;
{
	int	numchars;	/* clip number of chars to fit	*/

	while ( tm && num-- )
	{
		numchars = textFit( rp, tm->tm_LimitWidth, tm->tm_Buffer);
		DTF( printf("RTM: numchars: %d, limit %d\n",
			numchars, tm->tm_LimitWidth ) );

		Move( rp, (long) tm->tm_Left, (long) tm->tm_Top + rp->TxBaseline );
		SetAPen( rp, 1L );
		SetDrMd( rp, (long) JAM1 );
		Text( rp, tm->tm_Buffer, (long) numchars );

		tm = tm->tm_Next;
	}
}


PositionTextMsg( tm, l, t )
struct TextMsg	*tm;
{
	tm->tm_Left = l;
	tm->tm_Top = t;
}


/*
 * num = -1 means do all
 */
EraseTextMsg( rp, tm, num )
struct RastPort	*rp;
struct TextMsg	*tm;
{
	struct Rectangle	tmrect;
	int	limitmaxx;

	while ( tm && num-- )
	{
		D( printf("ETM, rp %lx tm %lx\n", rp, tm ) );

		TextMsgExtent( rp, tm, &tmrect );
		if ( tm->tm_LimitWidth > 0 )
		{
			limitmaxx = tmrect.MinX + tm->tm_LimitWidth - 1;
			DTF( printf("maxx %d, limitmaxx %d\n", tmrect.MaxX, limitmaxx));
			tmrect.MaxX = jmin( tmrect.MaxX, limitmaxx );
		}

		D( printf("ETM: extent %d %d %d %d\n",
			tmrect.MinX, tmrect.MinY, tmrect.MaxX, tmrect.MaxY ) );

		if ( tmrect.MaxX > tmrect.MinX && tmrect.MaxY > tmrect.MinY )
		{
			SetAPen( rp, 0L );
			RectFill( rp, (long) tmrect.MinX, (long) tmrect.MinY,
						  (long) tmrect.MaxX, (long) tmrect.MaxY );
		}

		tm = tm->tm_Next;
	}
}


/** utility routines	**/
textLength( rp, str )
struct RastPort	*rp;
UBYTE			*str;
{
	DTLE( printf("tL: string <%s> length: %d\n", str, strlen(str) ));
	return ( TextLength( rp, str, (LONG) strlen( str ) ) );
}

/*
 * no limit if width <=0 
 */
textFit( rp, width, str )
struct RastPort	*rp;
int		width;
char	*str;
{
	int		i = strlen( str );

	if ( width > 0 )
	{
		for ( ; i > 0; --i )
		{
			if ( TextLength( rp, str, (LONG) i ) < width )
			{
				break;
			}
		}
	}

	return( i );
}


textListExtent( rp, argv, numgad, te )
struct RastPort	*rp;
UBYTE			**argv;
struct Rectangle	*te;
{

	int					width;

	DTLE( printf("textListExtent: rp text height: %d\n", rp->TxHeight ));

	/* measure text to get largest extent	*/
	width = 0;

	while ( numgad-- )
	{
		DTLE( printf("tLE:measure string: <%s>\n", *argv));
		width = jmax( width, textLength( rp, *argv ) );
		argv++;
		DTLE( printf("tLE: width %d\n", width ));
	}

	te->MinX = te->MinY = 0;
	te->MaxX = width - 1;
	te->MaxY = rp->TxHeight - 1;
}

/* I prefer functions to macros here */
jmin( a, b)
{
	return ( (a>b)? b: a );
}
jmax( a, b)
{
	return ( (a<b)? b: a );
}
