/*	"Publicity" PubScreen manager
	V1.4 (27.06.95)
	(L) 1995 Matthias Bethke
*/


#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/diskfont.h>
#include <exec/memory.h>
#include <dos/dostags.h>
#include <stdlib.h>
#include <string.h>

#define OPT_NAME ((STRPTR)ArgPtrs[0])
#define OPT_WIDTH ((LONG*)ArgPtrs[1])
#define OPT_HEIGHT ((LONG*)ArgPtrs[2])
#define OPT_DEPTH ((LONG*)ArgPtrs[3])
#define OPT_MODE ((UBYTE*)ArgPtrs[4])
#define OPT_MODEID ((STRPTR)ArgPtrs[5])
#define OPT_FONTNAME ((UBYTE*)ArgPtrs[6])
#define OPT_FONTSIZE ((LONG*)ArgPtrs[7])
#define OPT_CLOSE (ArgPtrs[8])
#define OPT_DEFAULT (ArgPtrs[9])
#define OPT_SHANGHAI (ArgPtrs[10])
#define OPT_NOSHANGHAI (ArgPtrs[11])
#define OPT_POPSCREEN (ArgPtrs[12])
#define OPT_NOPOPSCREEN (ArgPtrs[13])
#define OPT_TOFRONT (ArgPtrs[14])
#define OPT_TOBACK (ArgPtrs[15])

#define CleanUp()	if(Args) FreeArgs(Args)

/* fuction protos */
ULONG IDFromName(STRPTR Name);

/* globals */
const char VersionString[]="$VER: Publicity V1.4 (27.06.95)";


LONG main(char *argv[])
{
/* the string section */
static char
oserr_nomonitor[]		= "Selected monitor not available!\n",
oserr_nochips[]		= "Your customchips can't display this mode!\n",
oserr_nomem[]			= "Not enough memory for screen!\n",
oserr_pubnotunique[]	= "The public screen name '%s' is already in use.\nChoose another name!\n",
oserr_unknownmode[]	= "Unrecognizable screenmode!\n",
oserr_toodeep[]		= "Your graphics hardware does not support screens with %d planes!\n",
oserr_notavailable[]	= "Screenmode not available for unknown reasons!\n",
default_screenerr[]	= "Unidentified error while opening screen!\n";
static const UWORD PenArray[]={0,1,1,2,1,3,1,0,2,(UWORD)-1};

LONG ScreenError;
struct Screen *PScreen;
struct RDArgs *Args;
struct TextAttr FontAttrib;
LONG ArgPtrs[16]={0};
static struct TagItem ScreenTags[12]=
{
	{SA_Top,			0},
	{SA_Left,		0},
	{SA_Width,		0},
	{SA_Height,		0},
	{SA_Depth,		0},
	{SA_DisplayID,	0},
	{SA_PubName,	0},
	{SA_AutoScroll,TRUE},
	{SA_Pens,		(ULONG)PenArray},
	{SA_ErrorCode,	0},
	{SA_SysFont,	TRUE},
	{TAG_DONE,		0}
};

	if(!(Args = ReadArgs("N=Name/A,W=Width/N,H=Height/N,D=Depth/N,M=Mode,MID=ModeID/K,F=Font/K,FS=FontSize/K/N,Close/S,Default/S,Shanghai/S,NoShanghai/S,PopScreen/S,NoPopScreen/S,ToFront/S,ToBack/S",ArgPtrs,NULL)))
	{
		PrintFault(IoErr(),NULL);
		return RETURN_WARN;
	}

	if(OPT_CLOSE)
	{
/* any option but "Name" is bogus when closing a screen :) */
		if(
			(ULONG)OPT_WIDTH |
			(ULONG)OPT_HEIGHT |
			(ULONG)OPT_DEPTH |
			(ULONG)OPT_MODEID |
			(ULONG)OPT_MODE |
			OPT_SHANGHAI |
			OPT_DEFAULT |
			OPT_POPSCREEN |
			OPT_TOBACK |
			OPT_TOFRONT |
			(ULONG)OPT_FONTNAME |
			(ULONG)OPT_FONTSIZE
			) PutStr("?EXTRA IGNORED\n");
		if(PScreen = LockPubScreen(OPT_NAME))
		{
			if(PScreen->FirstWindow == NULL)
			{
				BOOL WasDefault;
				char DPSName[MAXPUBSCREENNAME+1];

				GetDefaultPubScreen(DPSName);
				WasDefault = !strnicmp(DPSName,OPT_NAME,MAXPUBSCREENNAME);
				UnlockPubScreen(NULL,PScreen);
				if(!(CloseScreen(PScreen)))  PutStr("Cannot close screen, sorry!\n");
				CleanUp();
				if(WasDefault)	VPrintf("'%s' was the default public screen. Switched back to 'Workbench'!\n",(LONG*)&ArgPtrs[0]); /*OPT_NAME*/
				return RETURN_OK;
			} else
			{
				UnlockPubScreen(NULL,PScreen);
				PutStr("There are still windows open on the screen.\nPlease close them and try again!\n");
				CleanUp();
				return RETURN_WARN;
			}
		} else
		{
			VPrintf("Unable to find a screen called '%s'!\n",(LONG*)&ArgPtrs[0]);
			CleanUp();
			return 10;
		}
	}
	if(
		(ULONG)OPT_WIDTH |
		(ULONG)OPT_HEIGHT |
		(ULONG)OPT_DEPTH |
		(ULONG)OPT_MODEID |
		(ULONG)OPT_MODE
		)
	{
		if(OPT_FONTNAME)
		{
			FontAttrib.ta_Name = OPT_FONTNAME;
			FontAttrib.ta_YSize = OPT_FONTSIZE ? *OPT_FONTSIZE : 8;
			FontAttrib.ta_Style = FS_NORMAL;
			FontAttrib.ta_Flags = FPF_DISKFONT | FPF_PROPORTIONAL;
			ScreenTags[10].ti_Tag	=	SA_Font;
			ScreenTags[10].ti_Data	=	(ULONG)&FontAttrib;
		}
/* fill in the rest of TagList data */
		if(!(OPT_WIDTH)) PutStr("Warning: No width specified!");
		if(!(OPT_HEIGHT)) PutStr("Warning: No height specified!");
		if(!(OPT_DEPTH)) PutStr("Warning: No depth specified!");
		ScreenTags[2].ti_Data = OPT_WIDTH?*OPT_WIDTH>16?*OPT_WIDTH:16:16;
		ScreenTags[3].ti_Data = OPT_HEIGHT?*OPT_HEIGHT>16?*OPT_HEIGHT:16:16;
		ScreenTags[4].ti_Data = OPT_DEPTH?*OPT_DEPTH>0?*OPT_DEPTH:1:1;
		ScreenTags[6].ti_Data = (ULONG)OPT_NAME;
		ScreenTags[9].ti_Data = (ULONG)&ScreenError;
		if(OPT_MODE) ScreenTags[5].ti_Data = IDFromName(OPT_MODE);
		else if(OPT_MODEID)
		{
			sscanf(OPT_MODEID,"%ld",&(ScreenTags[5].ti_Data));
		}
/* open the screen */
		if(PScreen = OpenScreenTagList(NULL,ScreenTags))
		{
/* make screen public */
			PubScreenStatus(PScreen,0);
		} else
		{
			char *ErrStr;
			LONG Arg=0;
			switch(ScreenError)
			{

				case	OSERR_NOMONITOR	:	ErrStr = oserr_nomonitor;
													break;
				case	OSERR_NOCHIPS		:	ErrStr = oserr_nochips;
													break;
				case	OSERR_NOCHIPMEM	:	/* fall through */
				case	OSERR_NOMEM			:	ErrStr = oserr_nomem;
													break;
				case	OSERR_PUBNOTUNIQUE:	ErrStr = oserr_pubnotunique;
													Arg = (LONG)OPT_NAME;
													break;
				case	OSERR_UNKNOWNMODE	:	ErrStr = oserr_unknownmode;
													break;
				case	OSERR_TOODEEP		:	ErrStr = oserr_toodeep;
													Arg = *OPT_DEPTH;
													break;
				case	OSERR_NOTAVAILABLE:	ErrStr = oserr_notavailable;
													break;
				default						:	ErrStr = default_screenerr;
													break;
			}
			VPrintf(ErrStr,&Arg);
			CleanUp();
			return RETURN_FAIL;
		}
	}
	if(PScreen = LockPubScreen(OPT_NAME))
	{
	UWORD ScreenFlags;

		if(OPT_DEFAULT) SetDefaultPubScreen(OPT_NAME);

 		if(OPT_TOFRONT && OPT_TOBACK)
			PutStr("Can only move screen to front OR to back!\n");
		else
		{
			if(OPT_TOFRONT) ScreenToFront(PScreen);
			if(OPT_TOBACK) ScreenToBack(PScreen);
		}

/* get old screenflags... */
		ScreenFlags = SetPubScreenModes(0);

/* ...modify them... */
		if(OPT_SHANGHAI && OPT_NOSHANGHAI)
				PutStr("Wanna SHANGHAI or not?\n");
			else
			{
				if(OPT_SHANGHAI) ScreenFlags |= SHANGHAI;
				if(OPT_NOSHANGHAI) ScreenFlags &= ~SHANGHAI;
			}
	
			if(OPT_POPSCREEN && OPT_NOPOPSCREEN)
				PutStr("Popeye...err...Popscreen?\n");
			else
			{
				if(OPT_POPSCREEN) ScreenFlags |= POPPUBSCREEN;
				if(OPT_NOPOPSCREEN) ScreenFlags &= ~POPPUBSCREEN;
		}

/* ...and write them back! */
		SetPubScreenModes(ScreenFlags);
		UnlockPubScreen(NULL,PScreen);
		CleanUp();
		return RETURN_OK;
	} else
	{
		VPrintf("Unable to find a screen called '%s'!\n",(LONG*)&ArgPtrs[0]); //OPT_NAME
		CleanUp();
		return RETURN_ERROR;
	}

}

ULONG IDFromName(STRPTR Name)
{
ULONG DisplayID=INVALID_ID;
DisplayInfoHandle DisplayHandle;
struct NameInfo InfoBuf;

/* skip leading blanks */
	Name = stpblk(Name);
	
/* scan all display IDs */
	while((DisplayID = NextDisplayInfo(DisplayID)) != INVALID_ID)
	{
		DisplayHandle = FindDisplayInfo(DisplayID);

/* fill the InfoBuf structure with information about that ID */
		if(GetDisplayInfoData(DisplayHandle,(UBYTE*)&InfoBuf,sizeof(InfoBuf),DTAG_NAME,0))
		{
/* - skip leading blanks on current monitor name
	- compare function argument with monitor name
	- if equal, return the associated DisplayID
 */
			if(stricmp(Name,stpblk(InfoBuf.Name)) == 0) return InfoBuf.Header.DisplayID;
		}
	}
	PutStr("Screenmode name not found, using default!\n");
	return 0;	
}
