/***************************************************************
** helpwin.c: Affiche une fenêtre d'aide sur le caractère     **
**            Écrit par T.Pierron                             **
**            15-03-1999                                      **
***************************************************************/

#include <Intuition/Intuition.H>
#include <Graphics/Rastport.H>
#include <Graphics/Gfxmacros.H>
#include <Exec/Memory.H>

WORD I;

/**** Cette fonction, extrêmement importante, permet d'allouer	*****
***** un nouvel affichage sans être obligé d'ouvrir une fenê-	*****
***** tre, avec les lourdeurs qui suivent.							****/
struct RastPort *Alloc_rastport( WORD larg,WORD haut,WORD depth )
{
	static struct RastPort *RP;
	static struct BitMap *BM;
	static Point *P;

	/* Alloue les trois structures: */
	if( (RP=(void *) AllocMem(sizeof(struct tPoint)+sizeof(struct RastPort)+sizeof(struct BitMap),MEMF_PUBLIC))==NULL )
		return NULL;

	/* Sauvegarde quelques données: */
	BM = (struct BitMap *) (RP+1);
	P  = (Point *) (BM+1);
	RP->BitMap = BM; P->x = larg; P->y = haut;

	/* Prépare le BitMap: */
	InitBitMap( BM, depth, larg, haut );

	/* Alloue la mémoire pour le Raster: */ 
	for( I = 0; I < depth; I++ )
	{
		if( (BM->Planes[ I ] = (PLANEPTR) AllocRaster( larg, haut ))==NULL )
			return NULL;

		/* Efface la mémoire avec l'aide du Blitter: */
		BltClear( BM->Planes[ I ], RASSIZE( larg, haut ), 0 );
	}

	/* Prépare le RastPort, en donnant un pointeur sur le BitMap. */
	InitRastPort( RP );
	RP->BitMap = BM;
	return RP;
}

static struct RastPort *RPW=NULL;
extern struct RastPort *RP,RPT;

/**** Libère l'affichage alloué avec la fonction ci-dessus: ****/
void Free_helpwin()
{
	register struct BitMap *BM;
	register Point *P;
	register WORD depth;

	if(RPW) {
		/* Libère les bitplans un à un: */
		for( I = 0,BM = RPW->BitMap,depth = BM->Depth,P = (Point *)(BM+1); I < depth; I++ )
			if( BM->Planes[ I ] )
				FreeRaster( BM->Planes[ I ], P->x, P->y );

		/* Et la mémoire pour les structures de données: */
		FreeMem(RPW,sizeof(struct tPoint)+sizeof(struct RastPort)+sizeof(struct BitMap));
		RPW=0;
	}
}

static UBYTE *msg[]={ "Code:","Dec:","Hex:",0 };
static WORD WinW,WinH,Larg,X,Y;
extern UBYTE Font_height;

/* Calcule la largueur et la hauteur de la fenêtre en fonction de la taille de la police: */
void Init_helpwin()
{
	extern struct Screen *screen;

{	register UBYTE **p;
	for(p=msg,Larg=0,WinH=0; *p; p++,WinH += Font_height)
		if(Larg < (WinW=TextLength( &RPT,*p,strlen(*p)))) Larg = WinW;
}
	Larg += 10; WinW = Larg+5+TextLength(&RPT,"999",3); WinH -= 7;
	if( !(RPW=Alloc_rastport(WinW,WinH,screen->BitMap.Depth)) )
		abort("Pas assez de mémoire!");
}

/* Conversion binaire => décimal */
void convert_var_dec(UBYTE *Str,UBYTE var)
{
	UBYTE *ptr=Str,L=0;

	var &= 0xFF;

	do {
		ptr--; L++;
		*ptr = var%10+'0';
	} while(var /= 10);

	Text(RP,ptr,L);
}

/* Idem vers l'hexa: */
void convert_var_hex(UBYTE *Str,UBYTE var)
{
	UBYTE TabASC[]="0123456789ABCDEF";
	UBYTE *ptr=Str,L=0;

	var &= 0xFF;

	do {
		ptr--; L++;
		*ptr = TabASC[ var & 0xF ];
	} while(var >>= 4);

	Text(RP,ptr,L);
}

/* Affiche toute les infos de la fenêtre: */
void Open_helpwin(UBYTE Num,WORD x,WORD y)
{
	extern struct Window *window;
	static UBYTE Str[6];

	if(x+WinW>window->Width)  x=window->Width-WinW;
	if(y+WinH>window->Height) y=window->Height-WinH;

	/* Sauvegarde l'affichage de la fenêtre: */
	ClipBlit(RP,x,y,RPW,0,0,WinW,WinH,0xC0);

	SetOPen(RP,1); SetAPen(RP,4);
	RectFill(RP,x,y,x+WinW-1,y+WinH-1);
	BNDRYOFF(RP);  SetAPen(RP,1);

	Move(RP,x+5,y+Font_height-4);		Text(RP,msg[0],5);
	Move(RP,x+Larg,RP->cp_y);			Text(RP,&Num,1);
	Move(RP,x+5,y+WinH-Font_height);	Text(RP,msg[1],4);
	Move(RP,x+Larg,RP->cp_y);			convert_var_dec(Str+6,Num);
	Move(RP,x+5,y+WinH-3);				Text(RP,msg[2],4);
	Move(RP,x+Larg,RP->cp_y);			convert_var_hex(Str+6,Num);
	X=x; Y=y;
}

void Close_helpwin()
{
	ClipBlit(RPW,0,0,RP,X,Y,WinW,WinH,0xC0);
}
