/*
*	wintext.c - version 0.1
*
*	Routines for font-independent window-text system, which allows
*	writing of text based on character positions.
*	Still being tweaked.
*
*	MWS 3/92.
*/

#include <exec/types.h>
#include <exec/memory.h>
#include <graphics/gfxmacros.h>
#include <intuition/intuition.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>

#include <string.h>
#include <stdarg.h>
#include "sprintf.h"

#include "wintext.h"

/*
 *	InitWinTextInfo
 *	
 *	Gets information about workbench screen (font and borders) and 
 *	initialises passed WINTEXTINFO, and sets NewWindow's width and
 *	height based on rows and columns required. Once caller has
 *	opened window, he/she should do a SetFont on it's rastport with
 *	the TextAttr stored in the WINTEXTINFO structure.
 */
BOOL InitWinTextInfo(WINTEXTINFO *wti,
		     struct NewWindow *nw,
		     UWORD  rows, UWORD columns)
{
	struct Screen screen;
	struct TextFont *tf;
	UWORD	i;

	if (GetScreenData(&screen, sizeof(screen), WBENCHSCREEN, NULL))
	{
		if (wti->spaces = AllocMem(columns+1,0L))
		{
			for (i = 0; i < columns; i++)
				wti->spaces[i] = ' ';	
		}
		else return FALSE;

		if (tf = OpenFont(wti->tattr = screen.Font))	/* have a peek */
		{
			wti->font_x = tf->tf_XSize;
			wti->font_y = tf->tf_YSize;
			wti->font_baseline = tf->tf_Baseline;
			wti->toffset = screen.WBorTop + tf->tf_YSize + 2;
			wti->loffset = screen.WBorLeft + 4;
			wti->roffset = screen.WBorRight + 4;
			wti->boffset = screen.WBorBottom + 1;

			wti->rows = rows; wti->columns = columns;

			nw->TopEdge = screen.WBorTop + tf->tf_YSize + 1;
			nw->Height = rows*wti->font_y + wti->toffset + wti->boffset;
			nw->Width =  columns*wti->font_x + wti->loffset + wti->roffset;

			CloseFont(tf);		/* should be set to rastport of window */
			return TRUE;
		}
		FreeMem(wti->spaces, columns+1);	/* free memory */
	}
	return FALSE;
}


/*
 *	FinishWinText
 *	
 *	Should be called after all use of WinText routines for a
 *	particular window.
 */
void FinishWinText(WINTEXTINFO *wti)		/* end of WinText session - free mem */
{
	if (wti->spaces) FreeMem(wti->spaces, wti->columns+1);
}


/*
 *	RenderWinTexts
 *	
 *	Writes the each member of the wintext list to the window. Preforms
 *	clipping to window's rows and columns. If an overwriting drawmode is
 *	specified in the WINTEXT structure, the remaining area after drawing
 *	the text will be cleared by spaces (it is regardless of drawmode, but
 *	JAM1 has no effect.
 */
void RenderWinTexts(WINTEXTINFO *info, WINTEXT *wt)
{
	struct RastPort *rp;
	WORD	len,			/* string length */
		columns;		/* space we've got to render string */

	while (wt)
	{
		if (wt->tpos < info->rows)	/* within row bounds */
		{
			columns = MIN(info->columns - wt->lpos - 1, wt->columns);
			len = MIN(strlen(wt->text), columns);
			rp = info->window->RPort;
			SetAPen(rp, wt->pen);
			SetDrMd(rp, wt->mode);
			Move(rp, info->loffset + wt->lpos*info->font_x, 
			     info->toffset + wt->tpos*info->font_y + info->font_baseline);
			Text(rp, wt->text, len);
			Text(rp, info->spaces, columns - len);
		}
		wt = wt->next;
	}
}

/*
 *	RenderWinTextsFmt(WINTEXTINFO *, WINTEXT *, char *fmt, arg1, arg2, ... )
 *	
 *	Same as RenderWinTexts, but uses SPrintf to format string in
 *	first WINTEXT of list, passing additional arguments to SPrintf.
 *	Assumes that 1st WINTEXT->text contains a buffer large enough
 *	for the SPrintf call. If fmt is zero, WINTEXT->text is cleared
 *	(actually, 1st byte set to '\0').
 *
 */	
void RenderWinTextsFmt(WINTEXTINFO *info, WINTEXT *wt, char *fmt, ...)
{
	va_list ap;
	va_start(ap,fmt);

	if (fmt) VSPrintf(wt->text, fmt, (APTR)ap);
	else wt->text[0] = '\0';

	RenderWinTexts(info,wt);
}
