//-------------------------------------
//
// SuperCode (c) 1996 by T.Kühn 
//
// Programmiersprache:	ANSI-C
// Projektstart:			28.8.94
//
// Modul:				Screen-handling
//
//-------------------------------------

#include <pragma/intuition_lib.h>
#include <pragma/dos_lib.h>
#include <pragma/graphics_lib.h>
#include <pragma/diskfont_lib.h>
#include <pragma/gadtools_lib.h>

#include <Struct.h>

//-------------------------------------
//-- SUBS ----------------------------
VOID	Screen_Init(struct tkScreen *Scr);
ULONG	Screen_Open(struct tkScreen *Scr);
ULONG	Screen_Close(struct tkScreen *Scr);

//-------------------------------------

struct tkScreen Scrn;

WORD Pen_3D[]= { 1,0,1,2,1,3,1,0,4,1,2,-1 };

UBYTE PUB_NAME[]=	"SuperCode";
UBYTE PUB_WB[]=		"Workbench";

UBYTE Col[MAX_COL][3]=
{
	255,	255,	255,

	255,	0,		0,
	0,		0,		255,
	0,		255,	0,
	255,	255,	0,
	0,		255,	255,
	255,	0,		255,

	0,		0,		0,

	128,	0,		0,
	0,		0,		128,
	20,	168,	20,

	238,	150,	0,
	0,		128,	128,
	128,	0,		128,

	169,	119,	61,
};

UWORD	Reg_Col[MAX_COL+2]=	{0};

//-------------------------------------


//-------------------------------------
VOID Font_Open(struct tkFont *tkfont)
{
	struct TextAttr *attr;
	struct TextFont *font=tkfont->font;

	if (!font)
	{
		do	{
				attr=&tkfont->attr;
				font=OpenDiskFont(attr);
				if (!font)
				{
					font=OpenFont(attr);
					if (!font)
					{
						if (ASK_SELECT==display_error(ERR_FONT,ASK_EXIT|ASK_AGAIN|ASK_SELECT,attr->ta_Name,attr->ta_YSize))
						{
							prefs_askfont(attr);
						}
					}
				}
			} while(!font);

//		Window_SetLimits();
		tkfont->font=font;
	}
}
//-------------------------------------
VOID Font_Close(struct tkFont *tkfont)
{
	struct TextAttr *attr=&tkfont->attr;
	struct TextFont *font=tkfont->font;

	if (font)
	{
		CloseFont(font);
		tkfont->font=0;
	}
}
//-------------------------------------
VOID Font_Init(struct tkFont *tkfont,UBYTE *fontname,ULONG fontsize)
{
	struct TextAttr *attr=&tkfont->attr;

	Font_Close(tkfont);

	strncpy(tkfont->fontname,fontname,MAX_FONTNAME);

	attr->ta_Name=tkfont->fontname;
	attr->ta_YSize=fontsize;

	Font_Open(tkfont);
}
//-------------------------------------

//-------------------------------------
ULONG bit(ULONG c)
{
	ULONG r=0;

	r|=c;
	r|=c<<8;
	r|=c<<16;
	r|=c<<24;

	return r;
}
//-------------------------------------

//-------------------------------------
VOID Screen_Init(struct tkScreen *Scr)
{
	ULONG t;

	memset(Scr,0,sizeof(struct tkScreen));

	Scr->Width=prg_prefs->scr.scr_width;
	Scr->Height=prg_prefs->scr.scr_height;
	Scr->Depth=prg_prefs->scr.scr_depth;
	Scr->Mode=prg_prefs->scr.scr_mode;
	Scr->Public=prg_prefs->scr.scr_public;

	Scr->Scrn=0;
	Scr->FlgOwn=FALSE;
	Scr->FlgWB=FALSE;
	Scr->FlgPublic=FALSE;
	Scr->FlgPrivate=FALSE;

	for (t=0;t<MAX_COL;t++) Reg_Col[t]=-1;

}
//-------------------------------------
ULONG Screen_Open(struct tkScreen *Scr)
{
	BOOL scrn_chg=FALSE,font_chg=FALSE;
	ULONG Err=0;
	struct Screen *ScrPtr=0;

	if      (prg_prefs->scr.scr_width	!=Scr->Width )				scrn_chg=TRUE;
	else if (prg_prefs->scr.scr_height	!=Scr->Height)				scrn_chg=TRUE;
	else if (prg_prefs->scr.scr_depth	!=Scr->Depth)				scrn_chg=TRUE;
	else if (prg_prefs->scr.scr_mode		!=Scr->Mode)				scrn_chg=TRUE;
	else if (prg_prefs->scr.scr_overscan!=Scr->OverScan)			scrn_chg=TRUE;
	else if (prg_prefs->scr.scr_public	!=Scr->Public)				scrn_chg=TRUE;
	else if (0!=strcmp(Scr->PubName,prg_prefs->scr.scr_pubname)) scrn_chg=TRUE;

	if (0!=strcmp(Scr->tkfont.fontname,prg_prefs->scr.fontname))	font_chg=TRUE;
	else if (Scr->tkfont.attr.ta_YSize!=prg_prefs->scr.fontattr.ta_YSize) font_chg=TRUE;

	if (Scr && (scrn_chg || font_chg))
	{
//		Window_ScreenDown();
		Screen_Close(Scr);

		Scr->Width=prg_prefs->scr.scr_width;
		Scr->Height=prg_prefs->scr.scr_height;
		Scr->Depth=prg_prefs->scr.scr_depth;
		Scr->Mode=prg_prefs->scr.scr_mode;
		Scr->Public=prg_prefs->scr.scr_public;
		Scr->OverScan=prg_prefs->scr.scr_overscan;

		if (font_chg)
		{
			Font_Init(&Scr->tkfont,prg_prefs->scr.fontname,prg_prefs->scr.fontattr.ta_YSize);
		}

//		if (!ScrPtr && Scr->Private)			// privaten Screen mitbenutzen
//		{
//			printf("patch private Screen\n");
//		}

		if (!ScrPtr && Scr->Public)			// public Screen mitbenutzen (WB)
		{
			do	{
					StrCopy(Scr->PubName,prg_prefs->scr.scr_pubname,MAX_PUBSCREENNAME);
					ScrPtr=LockPubScreen(Scr->PubName);
					if (!ScrPtr)
					{
						display_error(ERR_SCRNPUB,ASK_EXIT|ASK_AGAIN,Scr->PubName);

//						if (ASK_SELECT==display_error(ERR_SCRNPUB,ASK_EXIT|ASK_AGAIN|ASK_SELECT,Scr->PubName))
//						{
//							prefs_askpubscreen(prg_prefs->scr_pubname,MAX_PUBSCREENNAME);
//						}
					}
				}	while(!ScrPtr);

			Scr->FlgWB= (0==strcmp(Scr->PubName,PUB_WB)) ? TRUE : FALSE;

			ScreenToFront(ScrPtr);
			Scr->FlgPublic=TRUE;
		}

		if (!ScrPtr && Scr->Mode==LIKE_WORKBENCH)
		{
//			printf("open wb-like screen\n");

			do	{	ScrPtr=OpenScreenTags(0,
						SA_LikeWorkbench,TRUE,
						SA_Title,CatStr(TXT_SCRTITLE),
						SA_AutoScroll,TRUE,
						SA_PubName,PUB_NAME,
						SA_ErrorCode,&Err,
						SA_Interleaved,TRUE,
						SA_Font,&Scr->tkfont.attr,
						(Scr->Depth!=0)?(SA_Depth):(TAG_IGNORE),Scr->Depth,
						TAG_END);
				}	while((!ScrPtr) && ASK_AGAIN==display_error(ERR_SCRNLIKEWB,ASK_EXIT|ASK_AGAIN,Scr->Depth));

			if (ScrPtr) Scr->FlgOwn=TRUE;
		}
		if (!ScrPtr && Scr->Mode)				// eigenen Screen öffnen
		{
//			printf("open own screen ID:%X\n",Scr->Mode);

			do	{	ScrPtr=OpenScreenTags(0,
						SA_Width,Scr->Width,
						SA_Height,Scr->Height,
						SA_Depth,Scr->Depth,
						SA_Title,CatStr(TXT_SCRTITLE),
						SA_PubName,PUB_NAME,
						SA_DisplayID,Scr->Mode,
						SA_Overscan,Scr->OverScan,
						SA_AutoScroll,TRUE,
						SA_Pens,(ULONG)Pen_3D,
						SA_ErrorCode,&Err,
						SA_Interleaved,TRUE,
						SA_Font,&Scr->tkfont.attr,
						TAG_END);
		
					if (!ScrPtr)
					{
						if (ASK_SELECT==display_error(ERR_SCRNOWN,ASK_EXIT|ASK_AGAIN|ASK_SELECT,Scr->Width,Scr->Height,Scr->Depth))
						{
							if (prefs_askscreen())
							{
								Scr->Width=prg_prefs->scr.scr_width;
								Scr->Height=prg_prefs->scr.scr_height;
								Scr->Depth=prg_prefs->scr.scr_depth;
								Scr->Mode=prg_prefs->scr.scr_mode;
								Scr->OverScan=prg_prefs->scr.scr_overscan;
							}
						}
					}
				}	while(!ScrPtr);

			Scr->FlgOwn=TRUE;
		}

		if (ScrPtr)
		{
			LONG rx,ry,s;

			Scr->Scrn=ScrPtr;
			Scr->Visual=GetVisualInfoA(ScrPtr,TAG_END);
			Scr->DrawInfo=GetScreenDrawInfo(ScrPtr);

			rx=Scr->DrawInfo->dri_Resolution.X;
			ry=Scr->DrawInfo->dri_Resolution.Y;

			Scr->Xres=rx;
			Scr->Yres=ry;

			if (rx<ry)			{ rx=ry/rx;ry=1; }
			else if (rx>ry)	{ ry=rx/ry;rx=1; }
			else					{ rx=1;ry=1; }

			Scr->Xmul=rx;
			Scr->Ymul=ry;

			if (Scr->FlgOwn) PubScreenStatus(ScrPtr,0);

			if (Scr->FlgWB)
			{
				ULONG t;
				ULONG d=1<<ScrPtr->RastPort.BitMap->Depth;

				if (GfxBase->lib_Version>=39 && ( d > 8))
				{
					for (t=0;t<MAX_COL;t++)
					{
						Reg_Col[t] = ObtainBestPen(ScrPtr->ViewPort.ColorMap,bit(Col[t][0]),bit(Col[t][1]),bit(Col[t][2]),
							OBP_Precision,PRECISION_IMAGE,
							OBP_FailIfBad,TRUE,
							TAG_END);
	
	//					Reg_Col[t] = ObtainPen(ScrPtr->ViewPort.ColorMap,-1,bit(Col[t][0]),bit(Col[t][1]),bit(Col[t][2]),0);
	
	
						for (s=0;s<t;s++)
						{
							if (Reg_Col[s]==Reg_Col[t]) Reg_Col[t]=0xffff;
						}
	
						if (Reg_Col[t]==0xffff) {break;}
					}
					Reg_Col[t]=-1;
				}
				else
				{
					for (t=0;t+1<d;t++)
					{
						Reg_Col[t] = t+1;
					}
					Reg_Col[t]=-1;
				}

			}
		}
		Menu_Layout();
//		Window_ScreenUp();
	}
	return(Err)
}
//-------------------------------------
ULONG Screen_Close(struct tkScreen *Scr)
{
	ULONG Err=0;
	struct Screen *Scrn=0;

	if (Scr)
	{
		Scrn=Scr->Scrn;
		if (Scrn)
		{
			ULONG t;

			if (GfxBase->lib_Version>=39)
			{
				for (t=0;t<MAX_COL;t++)
				{
					if (Reg_Col[t]!=-1) ReleasePen(Scrn->ViewPort.ColorMap,Reg_Col[t]);
					Reg_Col[t]=-1;
				}
			}
			if (Scr->Visual)
			{
				FreeVisualInfo(Scr->Visual);
				Scr->Visual=0;
			}
			if (Scr->DrawInfo)
			{
				FreeScreenDrawInfo(Scrn,Scr->DrawInfo);
				Scr->DrawInfo=0;
			}
	
			if (Scr->FlgOwn)
			{
	//			printf("remove own Screen\n");
	
				while(TRUE)
				{
					if (CloseScreen(Scrn)) break;
					Delay(25);
				}
			}
			else if (Scr->FlgPublic)
			{
	//			printf("free PubScreen\n");
				UnlockPubScreen(0,Scrn);
			}
		}
		Scr->Scrn=0;
		Scr->FlgWB=FALSE;
		Scr->FlgOwn=FALSE;
		Scr->FlgPublic=FALSE;
		Scr->FlgPrivate=FALSE;
	}
	return(Err)
}
//-------------------------------------

