/*
 *	© 1992 by Michael Watzl, written with DICE: dcc PublicManager -2.0 -proto -o publicmanager
 */

#include <exec/memory.h>
#include <graphics/displayinfo.h>
#include <intuition/intuitionbase.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>
#include <libraries/gadtools.h>
#include <workbench/startup.h>
#include <intuition/gadgetclass.h>
#include <libraries/asl.h>
#include <stdlib.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/utility_protos.h>
#include <clib/icon_protos.h>
#include <clib/asl_protos.h>
#include <clib/diskfont_protos.h>

#define	TMPSIZE 512L			/* memory that will be allocated for temp stuff */
#define TOOLNUM 20			/* Maximal number of tools */

#define MENU_PROJ_PALETTE	0
#define	MENU_PROJ_ABOUT		1
#define	MENU_PROJ_SAVE          2
#define	MENU_PROJ_QUIT          3
#define MENU_PROJ_UPSCREEN      4
#define MENU_PROJ_UPMODES       5
#define MENU_PROJ_BACKDROP      6

#define MENU_MODE_DEFAULT       10
#define	MENU_MODE_SHANGHAI      11
#define	MENU_MODE_POPUP         12

#define MENU_MODE_NTSCHIRES	13
#define	MENU_MODE_NTSCHIRESLACE 14
#define	MENU_MODE_PALHIRES      15
#define MENU_MODE_PALHIRESLACE  16
#define	MENU_MODE_PRODUCTIVITY  17
#define	MENU_MODE_CUSTOM	18

#define MENU_MODE_NOOSCAN	20
#define MENU_MODE_TEXTOSCAN	21
#define MENU_MODE_STDOSCAN	22

#define MENU_MODE_DEPTH1	30
#define MENU_MODE_DEPTH2        31
#define MENU_MODE_DEPTH3	32
#define MENU_MODE_DEPTH4	33

#define MENU_MODE_WBFONT	40
#define MENU_MODE_TOPAZ		41
#define MENU_MODE_DISKFONT	42

#define MENU_MODE_SIZE          43

#define MENU_TOOLS_BASE		50

#define	PALETTESIGNAL		(1<<palwin->UserPort->mp_SigBit)
#define	WINDOWSIGNAL		(1<<window->UserPort->mp_SigBit)
#define	PUBLICSIGNAL		NULL /*(1<<publicsignal)*/

#define	FHEIGHT			screen->Font->ta_YSize

#define	PALGAD		0
#define	REDGAD          1
#define	GREENGAD	2
#define	BLUEGAD		3
#define	OKGAD		4
#define WBGAD		5
#define	CANCELGAD       6

#define	WBFONT		0
#define	TOPAZ           1
#define DISKFONT        2

/*
 *	PublicScreen configuration structure
 */
struct ScreenConfig {
	WORD	SizeX,SizeY;			/* Size of this Public Screen */
        WORD	Depth;				/* Depth (Number of Bitplanes */
	ULONG	DisplayID;			/* DisplayMode, look at your includes for more info! */
        UWORD	Overscan;
	UWORD   PubMode;			/* This may be SHANGHAI, POPPUBSCREEN */
	WORD	Font;				/* This can be WBFONT, TOPAZ or DISKFONT */
	struct 	TextAttr	textattr;	/* the TextAttr, which is used for this screen */
	BOOL	Default;
	BOOL	Backdrop;			/* Backdrop window or not? */
	BOOL	Tools;				/* Is there any configuration file? */
};


/*
 *	Prototypes
 */
STRPTR	strcpy( STRPTR dest, STRPTR source );
STRPTR	strncpy( STRPTR dest, STRPTR source , WORD length );
STRPTR	strcat( STRPTR dest, STRPTR source );
ULONG	strlen( STRPTR str );
WORD	sprintf( STRPTR dest, STRPTR format, ...);
STRPTR	strstr( STRPTR text , STRPTR findme );

VOID	main( VOID );
VOID	quit( STRPTR Text );

VOID	ReOpen( VOID );
BOOL	OpenScr( VOID );
BOOL	CloseScr( VOID );
VOID	OpenWin( VOID );
VOID	CloseWin( VOID );
VOID	OpenPalette( VOID );
VOID	ClosePalette( VOID );

VOID	About( VOID );
VOID	SetScreenColors( VOID );
VOID	Update( VOID );
LONG	GetCustomID( VOID );
LONG	GetNewSize( VOID );

WORD	usermessage( STRPTR text );
LONG	pix(STRPTR text);
ULONG	ahex2ulong( STRPTR ahex );
WORD	c2hex( WORD ch  );
WORD	hex2c( WORD hex );
VOID	getcolor( WORD index , struct Screen *s);


/*
 *	Static Data
 */
static	UBYTE *VersTag ="\0Public Manager V1.2 © 1992 by Michael Watzl";

const	STRPTR	FontTTString[] 	= {"WB","TOPAZ"};
const	UWORD	PenData[] 	= {~0};
const	STRPTR  OpenScrError[] 	= {"No error","The required monitor is not available!","You need ECS for this mode!","Not enough memory!","Not enough chip memory","This public screen already exists!","This displaymode is unknown!"};
const	STRPTR	OscanString[] 	= {"NO","TEXT","STANDARD"};

/*
 *	Global Data
 */
struct	IntuitionBase 	*IntuitionBase;
struct	Library		*GadToolsBase;
struct 	Library		*UtilityBase;
struct	Library		*IconBase;
struct	Library		*GfxBase;
struct	Library		*AslBase;
struct	Library		*DiskFontBase;
struct	Screen		*screen, *s;
struct	Window		*window, *palwin;
struct	Menu		*menu, *toolsmenu;
struct	NewMenu		*toolnm=NULL;
struct	DimensionInfo	dimensioninfo;
struct	MenuItem	*def_mitem, *sha_mitem, *pop_mitem;
struct	Gadget		*palcon, *gad[ 7 ];
struct	DiskObject      *mydob=NULL;
struct	FontRequester	*fontrequester;
struct	TextFont	*textfont;
struct  TextExtent	textextent;
struct	EasyStruct	easymessage = {sizeof(struct EazyStruct),0,"Public Manager Message", NULL , "Ok" };	/* Easy Reqs */
UBYTE	FontName[32];
ULONG	ScrError=NULL;
UBYTE	Name[129]="AutoPublic";
UBYTE	FileName[129];

UBYTE	ToolType[ TOOLNUM ][ 64 ];
UBYTE	Tool[ TOOLNUM ][64];

UBYTE	ColorChars[49];
UBYTE	myname[64];
VOID	*vi;
WORD	col0[3][16];					/* saved colors, for canceling the palette */
UWORD	r,g,b;						/* actual Colors (for Palette) */
WORD	activegad=0;					/* I need this for the palette (slidergads) */
STRPTR	temp;						/* will be allocated */
struct	ColorSpec	colors[17] = {/* COL0 */ 0, 10, 10, 10, /* COL1 */ 1,  0,  0, 2,  /* COL2 */ 2, 14, 14, 14, /* COL3 */ 3, 15, 11, 16, /* END */ -1};
struct  ScreenConfig	sc        = { 640 , 200 , 2 , HIRES_KEY , OSCAN_TEXT , NULL , TOPAZ , FontName     , 0 , 0 , FPF_ROMFONT | FPF_DISKFONT , FALSE , TRUE },
			defaultsc = { 640 , 200 , 2 , HIRES_KEY , OSCAN_TEXT , NULL , TOPAZ , "topaz.font" , 8 , 0 , FPF_ROMFONT | FPF_DISKFONT , FALSE , TRUE };
struct	TagItem SliderItem[] = {
	GA_FollowMouse,		TRUE,
	GTSL_Min,		0,
	GTSL_Max,		15,
	GTSL_Level,		0,
	GTSL_LevelFormat,	"%2.2ld",
	GA_RelVerify,		TRUE,
	GA_Immediate,		TRUE,
	GTSL_MaxLevelLen,	2,
	GTSL_LevelPlace,	PLACETEXT_RIGHT,
	STRINGA_Font,		&sc.textattr,
	TAG_END
};

VOID
wbmain(struct WBStartup* wbmsg)
{
        BPTR old,new;
        WORD i;

	if(!( temp = AllocMem( TMPSIZE , MEMF_PUBLIC )))	exit(0);
	if(!( toolnm = (struct NewMenu *)AllocMem( sizeof(struct NewMenu) * TOOLNUM , MEMF_PUBLIC | MEMF_CLEAR )))	quit( NULL );

	if(!(IconBase=(struct IconBase*)OpenLibrary("icon.library",0)))	exit(0);
	if(!(UtilityBase=(struct UtilityBase*)OpenLibrary("utility.library",37))) quit(NULL);

        old = CurrentDir( wbmsg->sm_ArgList->wa_Lock );

	strcpy( myname , wbmsg->sm_ArgList->wa_Name);
	if(!( mydob = GetDiskObjectNew( myname )))	quit(NULL);

	UnLock(new);

        strncpy( temp, FindToolType( mydob->do_ToolTypes , "NAME"), 79 );
        if( strlen(temp) ) strcpy( Name , temp );

	strncpy( temp , FindToolType( mydob->do_ToolTypes , "DISPLAYID" ), 79 );
	if(strlen( temp ) == 10) sc.DisplayID = ahex2ulong( temp );

	strcpy( temp , FindToolType( mydob->do_ToolTypes , "DEPTH" ) );
	if( strlen(temp) != 0) sc.Depth = atoi( temp );

	strcpy( temp , FindToolType( mydob->do_ToolTypes , "SIZEX" ));
	if( strlen(temp) != 0) sc.SizeX = atoi( temp );

	strcpy( temp , FindToolType( mydob->do_ToolTypes , "SIZEY" ));
	if( strlen(temp) != 0) sc.SizeY = atoi( temp );

	sc.Default  = (BOOL)FindToolType( mydob->do_ToolTypes , "DEFAULT"  );
        if( FindToolType( mydob->do_ToolTypes , "POP"      ) ) sc.PubMode  = POPPUBSCREEN;
        if( FindToolType( mydob->do_ToolTypes , "SHANGHAI" ) ) sc.PubMode |= SHANGHAI;
	sc.Backdrop = (BOOL)FindToolType( mydob->do_ToolTypes , "BACKDROP" );
	strcpy( temp , FindToolType( mydob->do_ToolTypes , "FONT" ) );
	     if( Stricmp( temp , FontTTString[0] ) == 0)	sc.Font = WBFONT ;
	else if( Stricmp( temp , FontTTString[1] ) == 0)	sc.Font = TOPAZ  ;
	else {
                sc.Font = DISKFONT;
		strncpy( FontName , temp , strstr( temp , ",") - temp );
		sc.textattr.ta_YSize = atoi( strstr(temp,",")+1 );
	}
        strncpy( temp, FindToolType( mydob->do_ToolTypes , "OSCAN" ) , 79 );
        if( Stricmp( temp , "TEXT" ) == 0 )       	sc.Overscan = OSCAN_TEXT;
        if( Stricmp( temp , "STD" ) == 0 )       	sc.Overscan = OSCAN_STANDARD;
        if( Stricmp( temp , "NO" ) == 0 )		sc.Overscan = NULL;
 	strncpy( ColorChars , FindToolType( mydob->do_ToolTypes , "COLORS") , 48 );
 	strncpy( FileName , FindToolType( mydob->do_ToolTypes , "CONFIG" ) , 128 );
	sc.Tools=TRUE;
	main();
}

VOID
main( VOID )
{
	struct	MenuItem 	*mi;
	struct	IntuiMessage	*msg;
	ULONG   waitsig, signal;
	UWORD	leave=FALSE;
	WORD	i;
        UWORD	index=1;
	BPTR 	old;
	ULONG	OldClass;
	WORD 	x=0;

	if(mydob == NULL ){
		PutStr("Please start me from WB!\n");
		exit(10);
	}

	if(!(GfxBase      =OpenLibrary("graphics.library",0L)))		exit(5);
	if(!(IntuitionBase=OpenLibrary("intuition.library",37L)))	quit(NULL);
	if(!(GadToolsBase = OpenLibrary("gadtools.library",37L)))	quit("No gadtools.library available");
	if(!(AslBase      = OpenLibrary("asl.library"     , 0L)))	quit("No asl.library available");

	if(!( OpenScr() ))	quit(NULL);

	waitsig = WINDOWSIGNAL;
        FOREVER{
        	signal = Wait( waitsig );
		if(signal & WINDOWSIGNAL)
		{
	        	while(msg = GT_GetIMsg( window->UserPort ))
			{
				if(msg->Class==IDCMP_CLOSEWINDOW){
					GT_ReplyIMsg( msg );
					while( msg = GT_GetIMsg( window->UserPort )) GT_ReplyIMsg( msg );
                                	msg=NULL;
					if( CloseScr() )	quit(NULL);
				}
				if(msg->Class==IDCMP_MENUPICK){
					mi = ItemAddress(menu,msg->Code);
                                	switch( GTMENUITEM_USERDATA(mi)){
					case MENU_PROJ_BACKDROP:
						GT_ReplyIMsg( msg );
						while( msg = GT_GetIMsg( window->UserPort )) GT_ReplyIMsg( msg );
                	                	msg=NULL;
						CloseWin();
                                                sc.Backdrop = !sc.Backdrop;
                                                OpenWin();
						break;
					case MENU_PROJ_PALETTE:
						OpenPalette();
						waitsig = WINDOWSIGNAL | PALETTESIGNAL;
						break;
        	                        case MENU_PROJ_ABOUT:
	                        		About();
                	        		break;
					case MENU_PROJ_SAVE:
						x=0;
       	        	         	        ColorChars[0]='\0';
						for( i=0 ; i< 16 ; i++ ){
							getcolor(i, screen);
							ColorChars[0+i*3] = hex2c( r );
							ColorChars[1+i*3] = hex2c( g );
							ColorChars[2+i*3] = hex2c( b );
						}
						ColorChars[ 48 ]='\0';
						if( Name     ){	strcpy( ToolType[ x ] , "NAME=");
                                                                strcat( ToolType[ x ] , Name);
                                                }
                                                sprintf( ToolType[++x],"DISPLAYID=0x%08lx", sc.DisplayID );
                                                strcpy( ToolType[++x] , "COLORS=" );
                                                strcat( ToolType[  x] , ColorChars );
						strcpy( ToolType[++x] , "OSCAN=" );
						strcat( ToolType[ x ] , OscanString[sc.Overscan] );
						if( sc.Default  )	strcpy( ToolType[++x] , "DEFAULT"  );
						if( sc.PubMode & SHANGHAI     == SHANGHAI     )	strcpy( ToolType[++x] , "SHANGHAI" );
						if( sc.PubMode & POPPUBSCREEN == POPPUBSCREEN )	strcpy( ToolType[++x] , "POP"      );
						if( sc.Backdrop )  strcpy( ToolType[++x] , "BACKDROP" );
						strcpy( ToolType[++x] , "FONT="   );
						if( sc.Font == DISKFONT ){
							strcat(ToolType[  x],sc.textattr.ta_Name);
							strcat(ToolType[  x],",");
							sprintf(temp,"%.4ld",sc.textattr.ta_YSize);
							strcat(ToolType[  x], temp);
						} else
							strcat( ToolType[  x] , FontTTString[ sc.Font ] );
						strcpy( ToolType[++x] , "DEPTH=" );
						ToolType[  x][6] = sc.Depth+48;
						ToolType[  x][7] = '\0';
						strcpy( ToolType[++x] , "SIZEX=" );
						sprintf( temp , "%ld" , sc.SizeX );
						strcat( ToolType[  x] , temp );

						strcpy( ToolType[++x] , "SIZEY=" );
						sprintf( temp , "%d" , sc.SizeY );
						strcat( ToolType[  x] , temp );

                                                ToolType[++x][0] = '\0';
						for( i=0 ; i<x ; i++) mydob->do_ToolTypes[i]=ToolType[i];					        old=CurrentDir( ((struct Process *)FindTask(NULL))->pr_HomeDir ); /* set home dir */
						PutDiskObject( myname , mydob );
						CurrentDir(old);
						break;
	                               	case MENU_PROJ_QUIT:
						GT_ReplyIMsg( msg );
						while( msg = GT_GetIMsg( window->UserPort )) GT_ReplyIMsg( msg );
                	                	msg=NULL;
						if( CloseScr() )  quit(NULL);
						break;
					case MENU_MODE_DEFAULT:
						sc.Default= !sc.Default;
						goto smallupdate;
					case MENU_MODE_SHANGHAI:
						sc.PubMode &= !(sc.PubMode & SHANGHAI);
						goto smallupdate;
					case MENU_MODE_POPUP:
						sc.PubMode &= !(sc.PubMode & POPPUBSCREEN);
smallupdate:					Update();
						break;
					case MENU_PROJ_UPSCREEN:
						GT_ReplyIMsg( msg );
						while( msg = GT_GetIMsg( window->UserPort )) GT_ReplyIMsg( msg );
						ReOpen();
						Update();
						break;
					case MENU_PROJ_UPMODES:
						Update();
						break;
                                        case MENU_MODE_NTSCHIRES:
						sc.DisplayID = NTSC_MONITOR_ID | HIRES_KEY;
						goto doit;
                                        case MENU_MODE_NTSCHIRESLACE:
						sc.DisplayID = NTSC_MONITOR_ID | HIRESLACE_KEY;
                				goto doit;
                                        case MENU_MODE_PALHIRES:
						sc.DisplayID = PAL_MONITOR_ID | HIRES_KEY;
						goto doit;
                                        case MENU_MODE_PALHIRESLACE:
						sc.DisplayID = PAL_MONITOR_ID | HIRESLACE_KEY;
						goto doit;
                                        case MENU_MODE_PRODUCTIVITY:
						sc.DisplayID = VGA_MONITOR_ID | VGAPRODUCT_KEY;
						goto doit;
					case MENU_MODE_CUSTOM:
                                                LONG id;
						id=GetCustomID();
						if( id == -1) break;
						sc.DisplayID=id;
						goto doit;
					case MENU_MODE_NOOSCAN:
						sc.Overscan=NULL;
						goto doit;
					case MENU_MODE_TEXTOSCAN:
						sc.Overscan=OSCAN_TEXT;
						goto doit;
					case MENU_MODE_STDOSCAN:
						sc.Overscan=OSCAN_STANDARD;
						goto doit;
					case MENU_MODE_DEPTH1:
						sc.Depth=1;
						goto doit;
					case MENU_MODE_DEPTH2:
						sc.Depth=2;
						goto doit;
					case MENU_MODE_DEPTH3:
						sc.Depth=3;
						goto doit;
					case MENU_MODE_DEPTH4:
						sc.Depth = 4;
						goto doit;
					case MENU_MODE_WBFONT:
						sc.Font=WBFONT;
						goto doit;
					case MENU_MODE_TOPAZ:
						sc.Font=TOPAZ;
doit:						GT_ReplyIMsg( msg );
						while( msg = GT_GetIMsg( window->UserPort )) GT_ReplyIMsg( msg );
                                		msg=NULL;
						ReOpen();
						break;
					case MENU_MODE_DISKFONT:
						struct TagItem asltag[]={
							ASL_Window	, window,
							ASL_Hail	, "Choose a font...",
							ASL_FontName	, screen->Font->ta_Name,
							ASL_FontHeight	, screen->Font->ta_YSize,
							TAG_END};
                                	       	if( fontrequester=( struct FontRequester *)AllocAslRequest(ASL_FontRequest , asltag))
						{
                	                               	if( AslRequest( fontrequester , asltag ))
							{
								sc.Font = DISKFONT;
								strcpy( FontName ,fontrequester->fo_Attr.ta_Name );
								sc.textattr.ta_YSize = fontrequester->fo_Attr.ta_YSize;
	                                	               	FreeAslRequest( fontrequester );
								goto doit;
                	                               	}
        	                                       	FreeAslRequest( fontrequester );
	                                        }
						break;
                                   	case MENU_MODE_SIZE:
	                                	LONG newsize;
        	                                newsize = GetNewSize();
        	                                if(newsize == -1 ) break;
                	                        sc.SizeY = (newsize & 0x0000ffff);		/* lower nibble */
                        	                sc.SizeX = (newsize & 0xffff0000) >> 16;	/* upper nibble */
                                	        goto doit;
                                                break;
					default:
						if( (WORD)GTMENUITEM_USERDATA(mi) >= MENU_TOOLS_BASE && (WORD)GTMENUITEM_USERDATA(mi)<= MENU_TOOLS_BASE + TOOLNUM ){
							strcpy( temp , "run ");
							strcat( temp , Tool[ (WORD)GTMENUITEM_USERDATA(mi)-MENU_TOOLS_BASE ] );
							Execute( temp , 0 , 0 );
						}
                                                break;
					} /* switch menu */
                                } /* if menupick */
                                GT_ReplyIMsg(msg);
                        }
                } /* WINDOWSIGNAL */
                if( signal & PALETTESIGNAL)
		{
			leave=FALSE;
			while( leave == FALSE )
			{
				while( msg = GT_GetIMsg( palwin->UserPort ) )
				{
			                switch(msg->Class){
					case IDCMP_CLOSEWINDOW:
			               		leave=TRUE;
		       	 	       		break;
			                case IDCMP_VANILLAKEY:
			        		switch(msg->Code){
			                	case    'u':
usecolors:							leave=TRUE;
								SetScreenColors();
								break;
       		 	        		case	'c':	for(i=0;i<16;i++) SetRGB4( &(screen->ViewPort), i , col0[0][i],col0[1][i],col0[2][i]);
								leave=TRUE;
								break;
						case	'w':	goto getwbcols;
						}
						break;
     		  	 	        case IDCMP_GADGETUP:
						activegad=0;

						switch(((struct Gadget*)(msg->IAddress))->GadgetID){
						case PALGAD:
							index=msg->Code;
							getcolor(index, screen);
							break;
						case REDGAD:
							r=msg->Code;
							SetRGB4( &(screen->ViewPort), index , r , g , b );
							break;
						case GREENGAD:
							g=msg->Code;
							SetRGB4( &(screen->ViewPort), index , r , g , b );
							break;
						case BLUEGAD:
							b=msg->Code;
							SetRGB4( &(screen->ViewPort), index , r , g , b );
							break;
						case WBGAD:
getwbcols:							if( s = LockPubScreen("Workbench" ) ){
		                                                for( i = 16 ; i>=0; i--){
									getcolor( i , s );
									SetRGB4( &(screen->ViewPort), i , r , g , b );
								}
       	                                         		UnlockPubScreen(NULL, s );
       		                                        } else usermessage("Can't lock wb");
	       	                                        break;
       			 	                case CANCELGAD:
							for(i=0;i<16;i++) SetRGB4( &(screen->ViewPort), i , col0[0][i],col0[1][i],col0[2][i] );
			                        case OKGAD:
							goto usecolors;
						} /* end switch GadgetID */
					case IDCMP_GADGETDOWN:
						i=(((struct Gadget*)(msg->IAddress))->GadgetID);
						activegad=i;
						if(i==1)	r=msg->Code;
						if(i==2)	g=msg->Code;
						if(i==3)	b=msg->Code;
						if(i==1 || i==2 || i==3) SetRGB4( &(screen->ViewPort), index , r , g , b );
						break;
					case IDCMP_MOUSEMOVE:
						if(activegad==1)	r=msg->Code;
						if(activegad==2)	g=msg->Code;
						if(activegad==3)	b=msg->Code;
						if(activegad==1 || activegad==2 || activegad==3) SetRGB4( &(screen->ViewPort), index , r , g , b );
						break;
			                } /* switch class */
		        	        GT_ReplyIMsg( msg );
				} /* while palette msg */
			} /* while leave */
			waitsig = WINDOWSIGNAL; /* only menu IDCPMs */
			ClosePalette();
	        } /* pal sig */
	} /* FROEVER */
}

BOOL
OpenScr( VOID )
{
	WORD res;
	struct	TagItem	screentag[] = {
		SA_ErrorCode,   &ScrError,
	        SA_Depth,	sc.Depth,
	        SA_Colors,	colors,
		SA_Font,	&sc.textattr,
		SA_DisplayID,	sc.DisplayID,
	        SA_Overscan,	sc.Overscan,
	        SA_Pens,        PenData,
		SA_PubName,	Name,
	        SA_Type,	PUBLICSCREEN,
		SA_Width,	sc.SizeX,
		SA_Height,	sc.SizeY,
		SA_DClip,	NULL,
		SA_FullPalette,	TRUE,
		SA_AutoScroll,	TRUE,
	        TAG_END
	};
	SetScreenColors();
	GetDisplayInfoData( NULL , (UBYTE *)&dimensioninfo , sizeof(struct DimensionInfo), DTAG_DIMS , sc.DisplayID );
	switch( sc.Overscan ) {
	case NULL:
		screentag[11].ti_Data = &dimensioninfo.Nominal;
		break;
	case OSCAN_TEXT:
		screentag[11].ti_Data = &dimensioninfo.TxtOScan;
		break;
	case OSCAN_STANDARD:
		screentag[11].ti_Data = &dimensioninfo.StdOScan;
		break;
	}
	if( sc.SizeX == 0 || sc.SizeX < ((struct Rectangle *)(screentag[11].ti_Data))->MaxX+1 ) screentag[  9 ].ti_Tag = TAG_IGNORE;
	if( sc.SizeY == 0 || sc.SizeY < ((struct Rectangle *)(screentag[11].ti_Data))->MaxY+1 ) screentag[ 10 ].ti_Tag = TAG_IGNORE;

	switch(sc.Font)
	{
	case WBFONT:
		if(s=LockPubScreen("Workbench")){
			strcpy( FontName , s->Font->ta_Name );
			sc.textattr.ta_YSize = s->Font->ta_YSize;
			UnlockPubScreen( NULL, s);
		}
		break;
	case TOPAZ:
                strcpy(FontName,"topaz.font");
		sc.textattr.ta_YSize=8;
		break;
	case DISKFONT:
		break;
	}
	if( ((sc.DisplayID & VGA_MONITOR_ID) == VGA_MONITOR_ID) && (sc.Depth >2) ) sc.Depth=2;
	if(!( textfont = OpenDiskFont( &(sc.textattr) ))) usermessage("WARNING: Couldn't open requested font!");

retry:	if(!( screen=OpenScreenTagList(NULL, screentag) ))
	{
		if( ScrError == OSERR_PUBNOTUNIQUE )
		{
			strcat( Name , "." );
                        goto retry;
                } else
                {
                        easymessage.es_GadgetFormat = "Retry|Default|Quit";
                	res = usermessage( OpenScrError[ ScrError ] );
			if( res == 1 ) goto retry;
			if( res == 2 ){
				CopyMem( &defaultsc , &sc , sizeof( struct ScreenConfig ) );
				if( OpenScr() )	return( TRUE );
			}
                	return( FALSE );
                }
	}
	easymessage.es_GadgetFormat = "Ok";

       	if(!( vi = GetVisualInfo(screen, TAG_END)))	quit("Can't get visual info!");
	if( PubScreenStatus(screen, 0L) != 1)	usermessage("WARNING: I was not able to make this screen public!");
	SetPubScreenModes( sc.PubMode );
        if( sc.Default ) SetDefaultPubScreen( Name );

	OpenWin();
	return( TRUE );
}

BOOL
CloseScr( VOID )
{
	if( screen ){
		ClosePalette();
		CloseWin();
		if( screen->FirstWindow != NULL){
			usermessage( "There are still windows on this screen.\nI can't close it.");
			OpenWin();
			return( FALSE );
		}
		if(screen)	CloseScreen( screen );
		screen   = NULL;
		CloseFont( textfont );
		textfont = NULL;
		if(vi)		FreeVisualInfo( vi );
		vi       = NULL;
	}
	return( TRUE );
}


VOID
quit( STRPTR text )
{
	if(text)                usermessage( text );

	if(!( CloseScr() ))	return;

	if( textfont )		CloseFont( textfont );
	if( sc.Default )	SetDefaultPubScreen( "Workbench" );
	if( mydob )		FreeDiskObject( mydob );
	if(GadToolsBase)	CloseLibrary(GadToolsBase);
	if(IntuitionBase)	CloseLibrary((struct Library *)IntuitionBase);
	if(UtilityBase)         CloseLibrary(UtilityBase);
	if(IconBase)		CloseLibrary(IconBase);
	if(GfxBase)		CloseLibrary(GfxBase);
	if(AslBase)		CloseLibrary(AslBase);
	if(DiskFontBase)        CloseLibrary(DiskFontBase);
	if(temp)		FreeMem( temp  , TMPSIZE );
	if( toolnm )		FreeMem( toolnm , sizeof(struct NewMenu) * TOOLNUM );
	exit(0);
}

WORD
usermessage( STRPTR text )
{
	UWORD m0;
	easymessage.es_TextFormat = text;
	m0 = SetPubScreenModes( NULL );
	SetPubScreenModes( m0 );

	if(!( m0 & POPPUBSCREEN )) ScreenToFront( NULL );
	return( EasyRequest( NULL , &easymessage, NULL,NULL) );
}

VOID
OpenPalette( VOID )
{
	BOOL leave=FALSE;
	WORD i=0, index=0, col;
	struct	Gadget *g;

	if( palwin ) return;

	for( i=0 ; i< 16  ; i++ ){ 	/* col is only temporary */
		col = GetRGB4( ((struct ViewPort)(screen->ViewPort)).ColorMap , i );
		col0[0][i] = ((col & (0x0f00)) >> 8);
		col0[1][i] = ((col & (0x00f0)) >> 4);
		col0[2][i] =  (col & (0x000f));
        }

	i     = 6*pix("CANCEL") + 40; 		/* windowwidth  */
	index = FHEIGHT*14;		        /* windowheight */
	struct NewGadget palette =	{ 10                    , FHEIGHT* 2,  i-20 , FHEIGHT*2 , NULL     , screen->Font , PALGAD    ,NULL           , vi , NULL};
	struct NewGadget rslide  =	{ pix("WGreenWW")       , FHEIGHT* 5,  i - rslide.ng_LeftEdge - pix("W00W") -20 , FHEIGHT+4 , "Red"    , screen->Font , REDGAD    ,PLACETEXT_LEFT , vi , NULL};
	struct NewGadget gslide  =	{ rslide.ng_LeftEdge    , FHEIGHT* 7, rslide.ng_Width                           , FHEIGHT+4 , "Green"  , screen->Font , GREENGAD  ,PLACETEXT_LEFT , vi , NULL};
	struct NewGadget bslide  =	{ rslide.ng_LeftEdge    , FHEIGHT* 9, rslide.ng_Width                           , FHEIGHT+4 , "Blue"   , screen->Font , BLUEGAD   ,PLACETEXT_LEFT , vi , NULL};
	struct NewGadget ok	 =	{ 10                    , FHEIGHT*11, 2*pix("CANCEL") , FHEIGHT*2 , "_USE"    , screen->Font , OKGAD     , PLACETEXT_IN  , vi , NULL};
	struct NewGadget wb	 =	{ 20+  ok.ng_Width      , FHEIGHT*11, ok.ng_Width     , FHEIGHT*2 , "_WB"     , screen->Font , WBGAD     , PLACETEXT_IN  , vi , NULL};
	struct NewGadget cancel  =	{ 30+2*ok.ng_Width      , FHEIGHT*11, ok.ng_Width     , FHEIGHT*2 , "_CANCEL" , screen->Font , CANCELGAD , PLACETEXT_IN  , vi , NULL};

	if(!( palcon           = CreateContext((struct Gadget **)&palcon)))					        leave=TRUE;
	if(!( gad[ PALGAD    ] = CreateGadget(PALETTE_KIND , palcon           ,&palette ,GTPA_Depth,sc.Depth,GTPA_IndicatorWidth,50,TAG_DONE,0)))	leave=TRUE;
	if(!( gad[ REDGAD    ] = CreateGadgetA(SLIDER_KIND , gad[ PALGAD    ] ,&rslide  ,SliderItem)))			 leave=TRUE;
	if(!( gad[ GREENGAD  ] = CreateGadgetA(SLIDER_KIND , gad[ REDGAD    ] ,&gslide  ,SliderItem)))			 leave=TRUE;
	if(!( gad[ BLUEGAD   ] = CreateGadgetA(SLIDER_KIND , gad[ GREENGAD  ] ,&bslide  ,SliderItem)))			 leave=TRUE;
	if(!( gad[ OKGAD     ] = CreateGadget( BUTTON_KIND , gad[ BLUEGAD   ] ,&ok      ,GT_Underscore,'_',TAG_DONE,0))) leave=TRUE;
	if(!( gad[ WBGAD     ] = CreateGadget( BUTTON_KIND , gad[ OKGAD     ] ,&wb      ,GT_Underscore,'_',TAG_DONE,0))) leave=TRUE;
	if(!( gad[ CANCELGAD ] = CreateGadget( BUTTON_KIND , gad[ WBGAD     ] ,&cancel  ,GT_Underscore,'_',TAG_DONE,0))) leave=TRUE;
	if(leave==TRUE){
		FreeGadgets(palcon);
		palcon=NULL;
		return;
	}
	if(!(palwin=(struct Window *)OpenWindowTags(NULL,
		WA_Left		, (screen->Width  - i ) /2,
		WA_Top		, (screen->Height - index ) /2,
		WA_Width	, i ,
		WA_Height	, index ,
		WA_Flags	, WFLG_ACTIVATE | WFLG_CLOSEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET,
                WA_Title	, "Palette Window",
		WA_IDCMP	, IDCMP_CLOSEWINDOW|SLIDERIDCMP|PALETTEIDCMP|IDCMP_MOUSEBUTTONS|IDCMP_MOUSEMOVE|IDCMP_VANILLAKEY,
		WA_Gadgets	, palcon ,
		WA_PubScreen,		screen,
		WA_PubScreenFallBack,	FALSE,
		TAG_DONE))){
		FreeGadgets(palcon);
		palcon=NULL;
		return;
	}
	for( i= REDGAD; i<=BLUEGAD; i++) DrawBevelBox( palwin->RPort , gad[ i ]->LeftEdge -4 , gad[ i ]->TopEdge-2 , gad[ i ]->Width+8 , gad[ i ]->Height+4, GT_VisualInfo,vi,TAG_END);
	DrawBevelBox( palwin->RPort, palette.ng_LeftEdge-1    , palette.ng_TopEdge , 50 + 2                , palette.ng_Height , GT_VisualInfo,vi,GTBB_Recessed,TRUE,TAG_END);
	DrawBevelBox( palwin->RPort, palette.ng_LeftEdge+59 -1, palette.ng_TopEdge , palette.ng_Width-59+2 , palette.ng_Height , GT_VisualInfo,vi,TAG_END);
	GT_SetGadgetAttrs( gad[ PALGAD ] , palwin , NULL , GTPA_Color , 1 , TAG_END );
    	getcolor( 1 , screen);
}

VOID
ClosePalette( VOID )
{
	if( palwin ){
		struct  IntuiMessage *m;
		while( m=GT_GetIMsg( palwin->UserPort ) ) GT_ReplyIMsg( m );
               	CloseWindow( palwin );
		if( palcon )	FreeGadgets( palcon );
		palwin = NULL;
		palcon = NULL;
	}
}

VOID
getcolor(WORD index, struct Screen *s)
{
	UWORD col;

	col = GetRGB4( s->ViewPort.ColorMap , index );
	b = (UWORD)  (col & (0x000f));
	g = (UWORD) ((col & (0x00f0)) >> 4);
	r = (UWORD) ((col & (0x0f00)) >> 8);

  	if(palwin){
	        GT_SetGadgetAttrs(gad[REDGAD]  ,palwin,NULL,GTSL_Level,r,TAG_DONE);
       		GT_SetGadgetAttrs(gad[GREENGAD],palwin,NULL,GTSL_Level,g,TAG_DONE);
	        GT_SetGadgetAttrs(gad[BLUEGAD] ,palwin,NULL,GTSL_Level,b,TAG_DONE);
	}
}

WORD
hex2c(WORD hex)
{
	if(hex < 10 ) return(hex+48);
        return(hex+65-10);
}

WORD
c2hex(WORD c)
{
	c=ToUpper(c);
	if( (WORD)c > 64 )	return(c-65+10);
	return((WORD)(c-48));
}




VOID
About( VOID )
{
	WORD	count;
	struct	PubScreenNode	*pubnode;
	struct	List		*publist;
	struct	EasyStruct	easyinfo  = {sizeof(struct EazyStruct),0,"PublicManager", "PublicManager V1.2 © 1992 by Michael Watzl\n\nWritten by:\n   Michael Watzl\n   Konradstr. 11\n   8850 Donauwoerth\n       GERMANY\n\nDefaultPubScreen: %s\nVisitors on this screen : %ld\n" ,"OK"}; /* Easy Reqs */

	if(!( publist = LockPubScreenList() )){
		usermessage("Can't lock pubscreenlist!");
		return;
	}
	pubnode = (struct PubScreenNode *)(publist->lh_Head);
	while( pubnode != NULL )
	{
                if( pubnode->psn_Screen == screen ) count=pubnode->psn_VisitorCount;
        	pubnode = pubnode->psn_Node.ln_Succ;
	}
	UnlockPubScreenList();

	s = LockPubScreen( NULL );
	EasyRequest( screen->FirstWindow , &easyinfo , NULL, s->Title , count-1 );
	UnlockPubScreen( NULL , s );
}

VOID
Update( VOID )
{
        sc.PubMode=NULL;
	if( pop_mitem->Flags & CHECKED ) sc.PubMode  = POPPUBSCREEN;
	if( sha_mitem->Flags & CHECKED ) sc.PubMode |= SHANGHAI;

	SetPubScreenModes( sc.PubMode );
	s=LockPubScreen( NULL );
	if( def_mitem->Flags & CHECKED ){
		if( s != screen )	SetDefaultPubScreen( screen->Title );
                sc.Default=TRUE;
        } else	if( s == screen )	SetDefaultPubScreen( "Workbench" );
	UnlockPubScreen( NULL, s );
}

LONG
pix( STRPTR text)					/* calc width of text */
{
        TextExtent( &(screen->RastPort) , text , strlen(text) , &textextent );
	return( textextent.te_Width );
}

VOID
SetScreenColors( VOID )
{
	WORD j;

	if( strlen(ColorChars) > 48 ) return;
	for( j=0 ; j< 16 ; j++ ){
			colors[j].ColorIndex	=j;
			colors[j].Red	=c2hex( (WORD)ColorChars[j*3+0] );
			colors[j].Green	=c2hex( (WORD)ColorChars[j*3+1] );
			colors[j].Blue	=c2hex( (WORD)ColorChars[j*3+2] );
	}
	colors[ j ].ColorIndex=-1;
}

VOID
CloseWin( VOID )
{
	struct  IntuiMessage *m;
	while( m=GT_GetIMsg( window->UserPort ) )	GT_ReplyIMsg( m );

	if( menu ){
		ClearMenuStrip( window );
		FreeMenus( menu );
		if( toolsmenu ) FreeMenus( toolsmenu );
	}
	if( window )		CloseWindow( window );

	menu	= NULL;
	window	= NULL;
}

VOID
OpenWin( VOID )
{
	WORD	i,j;
	BPTR	fh;

	struct NewMenu PubMenu[] = {
/* 0 */		{NM_TITLE, "Project",		NULL,0,0,NULL		},
		{NM_ITEM , "Backdrop",		"B" ,CHECKIT | MENUTOGGLE ,0,MENU_PROJ_BACKDROP},
		{NM_ITEM , "Update Screen",	"U" ,0,0,MENU_PROJ_UPSCREEN},
		{NM_ITEM , "Update Modes",	"M" ,0,0,MENU_PROJ_UPMODES},
	        {NM_ITEM , "Palette...",	"P" ,0,0,MENU_PROJ_PALETTE},
		{NM_ITEM , "About...",		"A" ,0,0,MENU_PROJ_ABOUT},
		{NM_ITEM , "Save Prefs",        "S" ,0,0,MENU_PROJ_SAVE },
		{NM_ITEM , NM_BARLABEL,		NULL,0,0,NULL		},
		{NM_ITEM , "Quit",		"Q" ,0,0,MENU_PROJ_QUIT	},

		{NM_TITLE, "Preferences",	NULL,0,0,NULL		},
/* 10 */	{NM_ITEM , "Default PubScreen",	NULL,CHECKIT | MENUTOGGLE ,0,MENU_MODE_DEFAULT	},
		{NM_ITEM , "Shanghai",		NULL,CHECKIT | MENUTOGGLE ,0,MENU_MODE_SHANGHAI	},
		{NM_ITEM , "Pop to front",	NULL,CHECKIT | MENUTOGGLE ,0,MENU_MODE_POPUP	},
		{NM_ITEM , NM_BARLABEL,		NULL,0,0,NULL		},
		{NM_ITEM , "Screen Modes",	NULL, 0 ,0,NULL		},
		{NM_SUB  , "NTSC:Hires",		NULL,CHECKIT , ~1 , MENU_MODE_NTSCHIRES	},
		{NM_SUB  , "NTSC:Hires-Interlaced",	NULL,CHECKIT , ~2 , MENU_MODE_NTSCHIRESLACE},
		{NM_SUB  , "PAL:Hires",			NULL,CHECKIT , ~4 , MENU_MODE_PALHIRES	},
		{NM_SUB  , "PAL:Hires-Interlaced",	NULL,CHECKIT , ~8 , MENU_MODE_PALHIRESLACE	},
		{NM_SUB  , "Productivity",		NULL,CHECKIT , ~16, MENU_MODE_PRODUCTIVITY	},
/* 20 */	{NM_SUB  , "Custom..." ,		NULL,CHECKIT , ~32, MENU_MODE_CUSTOM		}
		{NM_ITEM , "Overscan",          NULL, 0 , 0 , NULL		},
		{NM_SUB  , "No Overscan",	NULL, CHECKIT , ~1 , MENU_MODE_NOOSCAN   },
		{NM_SUB  , "Text",		NULL, CHECKIT , ~2 , MENU_MODE_TEXTOSCAN },
		{NM_SUB  , "Standard",		NULL, CHECKIT , ~4 , MENU_MODE_STDOSCAN  },
		{NM_ITEM , "Depth",		NULL, 0 , 0 , NULL		},
		{NM_SUB  , " 2 Colors",		NULL, CHECKIT , ~1 , MENU_MODE_DEPTH1	},
		{NM_SUB  , " 4 Colors",		NULL, CHECKIT , ~2 , MENU_MODE_DEPTH2	},
		{NM_SUB  , " 8 Colors",		NULL, CHECKIT , ~4 , MENU_MODE_DEPTH3	},
		{NM_SUB  , "16 Colors",		NULL, CHECKIT , ~8 , MENU_MODE_DEPTH4	},
/* 30 */	{NM_ITEM , "Font",		NULL, 0 , 0 , NULL		},
		{NM_SUB  , "Workbench",		NULL, CHECKIT , ~2 , MENU_MODE_WBFONT	},
		{NM_SUB  , "Topaz 8",		NULL, CHECKIT , ~4 , MENU_MODE_TOPAZ	},
		{NM_SUB  , "Open Disk Font...", "F" , CHECKIT , ~8 , MENU_MODE_DISKFONT	},
		{NM_ITEM , "Screensize...",     NULL, 0,0,           MENU_MODE_SIZE	},

		{NM_END}
	};
	struct IBox	AltCoords = { 0 , screen->BarHeight+1, 200 , screen->BarHeight };
	struct TagItem windowtag[] ={
		WA_Top,			screen->BarHeight+1,
		WA_Height,		screen->Height - screen->BarHeight-1,
		WA_IDCMP,		IDCMP_MENUPICK ,
		WA_PubScreen,		screen,
		WA_PubScreenFallBack,	FALSE,
		WA_Flags,		WFLG_ACTIVATE,
                WA_MouseQueue,		2,
                TAG_IGNORE,		&AltCoords,
		WA_MinWidth,		100,
		WA_MinHeight,		screen->BarHeight,
		WA_Title,		&VersTag[1],
		TAG_END
	};
	if(sc.Backdrop){
                PubMenu[1].nm_Flags    |=CHECKED;
		windowtag[ 5 ].ti_Data |= WFLG_BORDERLESS | WFLG_BACKDROP;
		windowtag[10 ].ti_Tag	= TAG_IGNORE;
	} else {
		windowtag[ 2 ].ti_Data |= IDCMP_CLOSEWINDOW;
		windowtag[ 5 ].ti_Data |= WFLG_CLOSEGADGET | WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET;
		windowtag[ 7 ].ti_Tag   = WA_Zoom;
	}

	if(!( window = OpenWindowTagList( NULL, windowtag )))	quit("Can't open window");

        if( sc.Default  ) PubMenu[  10 ].nm_Flags |= CHECKED;
        if( sc.PubMode & SHANGHAI     == SHANGHAI     ) PubMenu[ 11 ].nm_Flags |= CHECKED;
        if( sc.PubMode & POPPUBSCREEN == POPPUBSCREEN ) PubMenu[ 12 ].nm_Flags |= CHECKED;

		if( sc.DisplayID == (NTSC_MONITOR_ID | HIRES_KEY )	) PubMenu[15].nm_Flags |= CHECKED;
	else	if( sc.DisplayID == (NTSC_MONITOR_ID | HIRESLACE_KEY)	) PubMenu[16].nm_Flags |= CHECKED;
	else	if( sc.DisplayID == (PAL_MONITOR_ID  | HIRES_KEY )	) PubMenu[17].nm_Flags |= CHECKED;
	else	if( sc.DisplayID == (PAL_MONITOR_ID  | HIRESLACE_KEY )	) PubMenu[18].nm_Flags |= CHECKED;
	else	if( sc.DisplayID == (VGA_MONITOR_ID  | VGAPRODUCT_KEY )	) PubMenu[19].nm_Flags |= CHECKED;
 	else	PubMenu[20].nm_Flags |= CHECKED;

	PubMenu[ 22 + sc.Overscan ].nm_Flags |= CHECKED;
	PubMenu[ 26 + sc.Depth -1 ].nm_Flags |= CHECKED;
        PubMenu[ 31 + sc.Font     ].nm_Flags |= CHECKED;

	if( sc.Tools == TRUE ){
		if(!( fh = Open ( FileName , MODE_OLDFILE ))) goto notool;
		toolnm[0].nm_Type  = NM_TITLE;
		toolnm[0].nm_Label = "Tools";
		while( FGets( fh , Tool[ j ] , 63 )){
			Tool[ j ][ strlen( Tool[ j ] ) -1]='\0';
			toolnm[ j+1 ].nm_Type     = NM_ITEM;
			toolnm[ j+1 ].nm_Label    = FilePart( Tool[j] );
			toolnm[ j+1 ].nm_UserData = (APTR)(MENU_TOOLS_BASE+j);
			if( ++j == TOOLNUM-2) break;
		}
		Close( fh );
		toolnm[ j+1 ].nm_Type = NM_END;
		toolsmenu = CreateMenus( toolnm , TAG_END);
	}
notool:	menu = CreateMenus(PubMenu,TAG_END);
	menu->NextMenu->NextMenu=toolsmenu;
	LayoutMenus( menu , vi , TAG_END);

	SetMenuStrip( window , menu );

	def_mitem = menu->NextMenu->FirstItem;
        sha_mitem = menu->NextMenu->FirstItem->NextItem;
        pop_mitem = menu->NextMenu->FirstItem->NextItem->NextItem;

	if( (sc.DisplayID & VGA_MONITOR_ID) == VGA_MONITOR_ID ){
		OffMenu( window , 4289 ); /* Binary: SSSSSIIIIIIMMMMM S=Sub I=Item M=Menu */
		OffMenu( window , 6337 ); /* Binary: SSSSSIIIIIIMMMMM S=Sub I=Item M=Menu */
	}
}

VOID
ReOpen( VOID )
{
	if( CloseScr() ){
		if( OpenScr() ) return;
		quit( NULL );
	}
}

LONG
GetCustomID( VOID )
{
	LONG id=-2;
	BOOL leave=FALSE;
	struct Gadget		*idcon, *gad[3];
	struct Window   	*idwin;
	struct IntuiMessage     *message;

	struct NewGadget text	 = { (30+pix("   CANCEL   ")*2 - pix("WW0x00000000WW"))/2 , FHEIGHT*3 , pix("WW0x00000000WW")     , FHEIGHT*1+5   , "_Enter DisplayID",screen->Font, 0 , PLACETEXT_ABOVE | NG_HIGHLABEL , vi , NULL};
	struct NewGadget ok	 = { 10                       , FHEIGHT*5 , pix("   CANCEL   ")   , FHEIGHT+5   , "_USE"              ,screen->Font, 1 , PLACETEXT_IN    , vi , NULL};
	struct NewGadget cancel  = { 20 + pix("   CANCEL   ") , FHEIGHT*5 , pix("   CANCEL   ")   , FHEIGHT+5   , "_CANCEL"           ,screen->Font, 2 , PLACETEXT_IN    , vi , NULL};

	sprintf( temp , "0x%08lx", screen->ViewPort.ColorMap->VPModeID );
	if(!( idcon    = CreateContext((struct Gadget **)&idcon)))					                                              leave=TRUE;
	if(!( gad[ 0 ] = CreateGadget(STRING_KIND , idcon    ,&text   , GT_Underscore,'_' , GTST_String, temp , GTST_MaxChars, 10 , TAG_END )))       leave=TRUE;
	if(!( gad[ 1 ] = CreateGadget(BUTTON_KIND , gad[ 0 ] ,&ok     , GT_Underscore,'_' , TAG_END )))			                              leave=TRUE;
	if(!( gad[ 2 ] = CreateGadget(BUTTON_KIND , gad[ 1 ] ,&cancel , GT_Underscore,'_' , TAG_END )))			                              leave=TRUE;
	if(leave==TRUE){
		FreeGadgets(idcon);
		idcon=NULL;
		return(-1);
	}
	if(!( idwin = OpenWindowTags( NULL,
		WA_Left			, 50 ,
                WA_Top			, 30 ,
                WA_Width		,(30+pix("   CANCEL   ")*2),
                WA_Height		,FHEIGHT*7,
                WA_Flags		, WFLG_ACTIVATE | WFLG_CLOSEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_RMBTRAP,
                WA_IDCMP		, STRINGIDCMP | BUTTONIDCMP | IDCMP_VANILLAKEY | IDCMP_CLOSEWINDOW ,
		WA_Title		,"Public Manager Request",
		WA_Gadgets		,idcon,
		WA_PubScreen,		screen,
		WA_PubScreenFallBack,	FALSE,
		TAG_END))){
		FreeGadgets(idcon);
                idcon=NULL;
                return(-1);
        }
	ActivateGadget( gad[ 0 ] , idwin , NULL );
        while( id==-2 ){
        	Wait(1<<idwin->UserPort->mp_SigBit);
        	while( message = GT_GetIMsg( idwin->UserPort ) ){
                        switch( message->Class ){
        		case IDCMP_GADGETUP:
        			if( ((struct Gadget *)message->IAddress)->GadgetID == 1 )	id = ahex2ulong( ((struct StringInfo *)gad[0]->SpecialInfo)->Buffer );
				if( ((struct Gadget *)message->IAddress)->GadgetID == 2 )	id = -1;
				break;
        		case IDCMP_CLOSEWINDOW:
				id = -1;
				break;
			case IDCMP_VANILLAKEY:
				if( message->Code == 'u') id = ahex2ulong( ((struct StringInfo *)gad[0]->SpecialInfo)->Buffer );
				if( message->Code == 'c') id = -1;
				if( message->Code == 'e') ActivateGadget( gad[0] , idwin , NULL);
				break;
			}
			GT_ReplyIMsg( message );
		}
	}
	CloseWindow( idwin );
	FreeGadgets( idcon );
	return( id );
}

ULONG
ahex2ulong( STRPTR ahex )
{
	ULONG 	id=0, x=1;
	WORD	i;

     	for(i=9;i>1;i--){
      		id+= x * c2hex( ahex[i] );
		x*=16;
	}
	return( id );
}


LONG	/* upper nibble: X Size, lower nibble: YSize: 0xXXXXYYYY */
GetNewSize( VOID )
{
	LONG Size = -1;
	WORD	wwidth;
	WORD	cwidth;
	BOOL leave=FALSE;
	struct Gadget		*sizecon, *gad[6];
	struct Window   	*sizewin;
	struct IntuiMessage     *message;

        cwidth = pix("CANCEL");
	wwidth = 50 + 4* (pix("CANCEL")+20) ;
	struct NewGadget sizex	 = { cwidth+40                       , FHEIGHT*2 , pix("WWWW")+20   , FHEIGHT*1+5  , "_Width"  , screen->Font , 0 , PLACETEXT_RIGHT , vi , NULL};
	struct NewGadget sizey	 = { cwidth+40                       , FHEIGHT*4 , sizex.ng_Width   , FHEIGHT*1+5  , "_Height" , screen->Font , 1 , PLACETEXT_RIGHT , vi , NULL};
	struct NewGadget ok	 = { 10                              , FHEIGHT*6 , cwidth+20        , FHEIGHT+5    , "_OK"     , screen->Font , 2 , PLACETEXT_IN    , vi , NULL};
	struct NewGadget cancel  = { wwidth - 10 - ok.ng_Width       , FHEIGHT*6 , cwidth+20        , FHEIGHT+5    , "_CANCEL" , screen->Font , 3 , PLACETEXT_IN    , vi , NULL};
	struct NewGadget wb      = { ok.ng_LeftEdge+ok.ng_Width+10   , FHEIGHT*6 , cwidth+20        , FHEIGHT+5    , "_Get WB" , screen->Font , 4 , PLACETEXT_IN    , vi , NULL};
	struct NewGadget std     = { ok.ng_LeftEdge+ok.ng_Width*2+20 , FHEIGHT*6 , cwidth+20        , FHEIGHT+5    , "_STD"    , screen->Font , 5 , PLACETEXT_IN    , vi , NULL};

	if(!( sizecon  = CreateContext((struct Gadget **)&sizecon)))					                          leave=TRUE;
	if(!( gad[ 0 ] = CreateGadget(INTEGER_KIND , sizecon  ,&sizex  , GT_Underscore,'_' , GTIN_MaxChars, 5 , GTIN_Number , screen->Width  , TAG_END ))) leave=TRUE;
	if(!( gad[ 1 ] = CreateGadget(INTEGER_KIND , gad[ 0 ] ,&sizey  , GT_Underscore,'_' , GTIN_MaxChars, 5 , GTIN_Number , screen->Height , TAG_END ))) leave=TRUE;
	if(!( gad[ 2 ] = CreateGadget(BUTTON_KIND  , gad[ 1 ] ,&ok     , GT_Underscore,'_' , TAG_END )))                    leave=TRUE;
	if(!( gad[ 3 ] = CreateGadget(BUTTON_KIND  , gad[ 2 ] ,&cancel , GT_Underscore,'_' , TAG_END )))                    leave=TRUE;
	if(!( gad[ 4 ] = CreateGadget(BUTTON_KIND  , gad[ 3 ] ,&wb     , GT_Underscore,'_' , TAG_END )))                    leave=TRUE;
	if(!( gad[ 5 ] = CreateGadget(BUTTON_KIND  , gad[ 4 ] ,&std    , GT_Underscore,'_' , TAG_END )))                    leave=TRUE;

	if(leave==TRUE){
		FreeGadgets(sizecon);
		return(0);
	}

	if(!( sizewin = OpenWindowTags( NULL,
		WA_Left			, 50 ,
                WA_Top			, 50 ,
                WA_Width		, wwidth ,
                WA_Height		, FHEIGHT*8+4,
                WA_Flags		, WFLG_ACTIVATE | WFLG_CLOSEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_RMBTRAP,
                WA_IDCMP		, STRINGIDCMP | BUTTONIDCMP | IDCMP_VANILLAKEY | IDCMP_CLOSEWINDOW ,
		WA_Title		, "Public Manager Request",
		WA_Gadgets		, sizecon,
		WA_PubScreen,		screen,
		WA_PubScreenFallBack,	FALSE,
		TAG_END))){
		FreeGadgets(sizecon);
                return(0);
        }
	ActivateGadget( gad[ 0 ] , sizewin , NULL );
        while( leave == FALSE ){
        	Wait(1<<sizewin->UserPort->mp_SigBit);
        	while( message = GT_GetIMsg( sizewin->UserPort ) ){
                        switch( message->Class ){
        		case IDCMP_GADGETUP:
				switch( ((struct Gadget *)message->IAddress)->GadgetID ){
        			case 2:	goto getsize;
				case 3:	leave=TRUE;
					break;
				case 4:
getwbsize:				if( s = LockPubScreen("Workbench")){
						GT_SetGadgetAttrs( gad[ 0 ] , sizewin , NULL , GTIN_Number , s->Width  , TAG_END );
						GT_SetGadgetAttrs( gad[ 1 ] , sizewin , NULL , GTIN_Number , s->Height , TAG_END );
                                                UnlockPubScreen( NULL , s );
                                        }
					break;
				case 5:
getstdsize:                             switch( sc.Overscan ){
					case NULL:
						wwidth = dimensioninfo.Nominal.MaxX+1;
						cwidth = dimensioninfo.Nominal.MaxY+1;
						break;
					case OSCAN_TEXT:
						wwidth = dimensioninfo.TxtOScan.MaxX+1;
						cwidth = dimensioninfo.TxtOScan.MaxY+1;
						break;
					case OSCAN_STANDARD:
						wwidth = dimensioninfo.StdOScan.MaxX+1;
						cwidth = dimensioninfo.StdOScan.MaxY+1;
						break;
                                        }
					GT_SetGadgetAttrs( gad[0] , sizewin , NULL , GTIN_Number , wwidth , TAG_END );
                                        GT_SetGadgetAttrs( gad[1] , sizewin , NULL , GTIN_Number , cwidth , TAG_END );
					break;
                                }
				break;
        		case IDCMP_CLOSEWINDOW:
				leave=TRUE;
				break;
			case IDCMP_VANILLAKEY:
				switch( message->Code){
				case 'w':	ActivateGadget( gad[0] , sizewin , NULL);
                                                break;
				case 'h':	ActivateGadget( gad[1] , sizewin , NULL);
						break;
				case 'o':
getsize:					Size  =   ((struct StringInfo *)gad[ 1 ]->SpecialInfo)->LongInt ;
						Size |= ( ((struct StringInfo *)gad[ 0 ]->SpecialInfo)->LongInt ) << 16;
						leave = TRUE;
						break;
				case 'c':	leave=TRUE;
						break;
				case 'g':	goto getwbsize;
                                case 's':	goto getstdsize;
				}
				break;
			}
			GT_ReplyIMsg( message );
		}
	}
	CloseWindow( sizewin );
	FreeGadgets( sizecon );
	return( Size );
}
