/**	Screens.c
  *
  *	Implement the basic screen functions for rexxarplib.library.
  *
  *   AUTHOR/DATE:  W.G.J. Langeveld, November 1987.
  *   ============
  *
  *	CURRENT VERSION:
  *
  *	This version has been converted to SAS C 6.5 format. It has been modified
  *	for modern definition sequences for ANSI compilation. This no longer works
  *	with OS versions prior to 2.04.
  *
  *	rxf_sopen to a public screen will exit through a closescreen with the old
  *	code. This code ends that behavior.
  *
  *	rxf_sopen would produce random color choices either if the color string was
  *	too short. Also the screen title pens were defaulted not matching Workbench
  *	defaults.
  *
  *   AUTHOR/DATE:  Joanne Dow, jdow@bix.com, June 1998.
  *   ============
  *
  **/

#include <functions.h>
#include "ralprotos.h"
#include <exec/types.h>
#include <exec/exec.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <libraries/MyARP.h>
#include <proto/rexxsyslib.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "rexxarplib.h"
#include <simpreq.h>

/**
 *
 *   Function to bring a screen to the front
 *
**/
char *rxf_showtitle( long *err, int n, char *args[] )
{
	struct Screen *ps;
	long onoff;
	
	*err = 0;
	
	ps = NULL;
	if (n == 2) 
	{
		ps = LockScreen(args[0]);
		onoff = atol(args[1]);
		
		if (ps) 
		{
			ShowTitle(ps, onoff);
			UnlockScreen(args[0], ps);
			return(CAS("1"));
		}
	}
	
	return(CAS("0"));
}

/**
 *
 *   Function to bring a screen to the front
 *
**/
char *rxf_stofront( long *err, int n, char *args[] )
{
	struct Screen *ps;
	
	*err = 0;
	
	ps = NULL;
	if (n >= 1) 
	{
		ps = LockScreen(args[0]);
		if (ps) 
		{
			ScreenToFront(ps);
			UnlockScreen(args[0], ps);
		}
		else
		{
			return(CAS("0"));
		}
	}
	else
	{
		WBenchToFront();
	}
	
	return(CAS("1"));
}

/**
 *
 *   Function to move a screen to the back
 *
**/
char *rxf_stoback( long *err, int n, char *args[] )
{
	struct Screen *ps;
	
	*err = 0;
	
	ps = NULL;
	if (n >= 1) 
	{
		ps = LockScreen(args[0]);
		if (ps) 
		{
			ScreenToBack(ps);
			UnlockScreen(args[0], ps);
		}
		else
		{
			return(CAS("0"));
		}
	}
	else
	{
		WBenchToBack();
	}
	
	return(CAS("1"));
}

/**
 *
 *   Function to get the number of rows on a screen
 *
**/
char *rxf_srows( long *err, int n, char *args[] )
{
	struct Screen *ps;
	int rows = -1;
	char bf[11];
	
	*err = 0;
	
	if (n >= 1) 
	{
		ps = LockScreen(args[0]);
		if (ps) 
		{
			rows = ps->Height;
			UnlockScreen(args[0], ps);
		}
	}
	else
	{
		rows = GetWBRows();
		if (GetWBLace() > 0)
			rows <<= 1;
	}
	
	return( CAS(ltoa(bf, (long) rows)) );
}


/**
 *
 *   Function to get the number of columns on a screen
 *
**/
char *rxf_scols( long *err, int n, char *args[] )
{
	struct Screen *ps;
	char bf[11];
	int cols = -1;
	
	*err = 0;
	
	if (n >= 1) 
	{
		ps = LockScreen(args[0]);
		if (ps) 
		{
			cols = ps->Width;
			UnlockScreen(args[0], ps);
		}
	}
	else
	{
		cols = GetWBCols();
	}
	
	return( CAS(ltoa(bf, (long) cols)) );
}


/**
 *
 *   Function to get the interlace status of a screen
 *
**/
char *rxf_slace( long *err, int n, char *args[] )
{
	struct Screen *ps;
	char bf[11];
	int lace = -1;
	
	*err = 0;
	
	if (n >= 1) 
	{
		ps = LockScreen(args[0]);
		if (ps)
		{
			if (ps->ViewPort.Modes & LACE)
				lace = 1;
			else
				lace = 0;
			UnlockScreen(args[0], ps);
		}
	}
	else
	{
		lace = GetWBLace();
	}
	
	return( CAS(ltoa(bf, (long) lace)) );
}

/**
 *
 *   Function to get the colors of the screen
 *
**/
char *rxf_scolor( long *err, int n, char *args[] )
{
	struct Screen *ps;
	char bf[11], s[30];
	int ncol, maxcol;
	short colors;
	
	*err = 17;
	
	if (n != 2 && n != 5)
		return(CAS("-1"));
	
	*err = 12;
	
	ps = LockScreen(args[0]);
	if (ps) 
	{
		ncol = atoi(args[1]);
		maxcol = 1 << (ps->BitMap.Depth);
		if (maxcol > 32)
			maxcol = 32;
		if (ncol < maxcol) 
		{
			*err = 0;
			if ((colors = GetRGB4((&(ps->ViewPort))->ColorMap,
			(long) ncol)) != -1) 
			{
				strcpy(s, ltoa(bf, (long) ((colors >> 8) & 0xF)));
				strcat(s, " ");
				strcat(s, ltoa(bf, (long) ((colors >> 4) & 0xF)));
				strcat(s, " ");
				strcat(s, ltoa(bf, (long) ( colors       & 0xF)));
			}
			if (n == 5) 
			{
				SetRGB4(&(ps->ViewPort), (long) ncol, atol(args[2]),
				atol(args[3]), atol(args[4]));
			}
		}
		UnlockScreen(args[0], ps);
	}
	else
	{
		return(CAS("-1"));
	}
	
	return( CAS(s) );
}



/**
 *
 *   Function to move a screen
 *
**/
char *rxf_smove( long *err, int n, char *args[] )
{
	struct Screen *ps;
	int dx = 0, dy = 0;
	char s[30];
	
	*err = 17;
	
	if (n < 1)
		return( CAS("0") );
	
	*err = 12;
	
	ps = LockScreen(args[0]);
	if (ps) 
	{
		*err = 0;
		if ((n >= 2) && args[1])
			dx = atoi(args[1]);
		if ((n >= 3) && args[2])
			dy = atoi(args[2]);
		
		if (dx || dy)
			MoveScreen(ps, (LONG) dx, (LONG) dy);
		
		ltoa(s, (long) ps->LeftEdge);
		strcat(s, " ");
		ltoa(&s[strlen(s)], (long) ps->TopEdge);
		
		UnlockScreen(args[0], ps);
	}
	else
	{
		return(CAS("0"));
	}
	
	return(CAS(s));
}



/**
 *
 *   Open a public screen
 *
**/
#include "newlook.h"

#define NSSIZE ((long) sizeof(struct ExtNewScreen))
	
static UWORD std_pens[10] =
{
	1, 2, 1, 2, 1, 3, 1, 0, 2, 0xffff
};

char *rxf_sopen( long *err, int n, char *args[] )
{
	struct ExtNewScreen	*ns = NULL;
	struct Screen		*ps = NULL;
	char				*tp = NULL;
	int					 result = 0;
	struct TagItem		 tags[3];
	UWORD				 p_pens[10];
	int					 i;
	int					 j;
	int					 oscanflag = 0;
	int					 autosflag = 0;
	ULONG				 screenmode = 0xffffffff;
#define SCREENTEST	1
#if screentest
	FILE				 ofile;
	ofile = fopen( "con:", "w" );
#endif



	*err = 18;
	if (!args[4])
		goto cleanup;

	ps = LockScreen(args[4]);
	if (ps) 
	{
		UnlockScreen(args[4], ps);
		ps = NULL;	/* Added June 1998, JDow */
		goto cleanup;	/* Screen already exists! */
	}

	*err = 12;
	ns = (struct ExtNewScreen *) AllocMem(NSSIZE, MEMF_PUBLIC | MEMF_CLEAR);
	if (!ns)
		goto cleanup;
	
	if ((n >= 1) && args[0])
		ns->TopEdge  = atoi(args[0]);
	if ((n >= 2) && args[1])
		ns->Depth    = atoi(args[1]);
	if ((n >= 3) && args[2]) 
	{
		if (strstr(args[2], "HIRES"))
			ns->ViewModes |= HIRES;
		if (strstr(args[2], "LACE"))
			ns->ViewModes |= LACE;
		if (strstr(args[2], "HAM"))
			ns->ViewModes |= HAM;
		if (strstr(args[2], "SCREENBEHIND"))
			ns->Type |= SCREENBEHIND;
		if (strstr(args[2], "OVERSCAN"))
			oscanflag = 1;
		if (strstr(args[2], "AUTOSCROLL"))
			autosflag = 1;
		if ( tp = strstr( args[ 2 ], "SCREENMODE" ))
		{
			tp += 10;	// Point past "SCREENMODE"
			while ( *tp && ( *tp == ' ' || *tp == 0x09 ))
				tp++;
			stch_l( tp, (long*) &screenmode );
		}
	}
	if ((n >= 7) && args[6])
		ns->Width = atoi(args[6]);
	if ((n >= 8) && args[7])
		ns->Height = atoi(args[7]);
	if ((n >= 9) && args[8])
		ns->LeftEdge = atoi(args[8]);
	
	if (ns->Width <= 0) 
	{
		ns->Width = GetWBCols();
		if ((ns->ViewModes & HIRES) == 0)
			ns->Width >>= 1;
	}
	
	if (ns->Height <= 0) 
	{
		ns->Height = GetWBRows();
		if (ns->ViewModes & LACE)
			ns->Height <<= 1;
	}
	
	if ((n >= 3) && args[2])
	{
		if (strstr(args[2], "TRUNCATE"))
			ns->Height -= ns->TopEdge;
	}
	
	if (ns->Depth == 0)
		ns->Depth   = 2;
	
	ns->DetailPen = 0;
	ns->BlockPen  = 1;
	ns->Font      = Topaz80Equiv();
	
	ns->Type = PUBLICSCREEN | NS_EXTENDED;
	ns->Extension = tags;
	
	i = 0;
	tags[i].ti_Tag = SA_PubName;       tags[i].ti_Data = (ULONG) args[4];
	i++;

	if ( screenmode != 0xffffffff )
	{
		tags[i].ti_Tag = SA_DisplayID; tags[i].ti_Data = screenmode;
		i++;
	}
	if (autosflag) 
	{
		tags[i].ti_Tag = SA_AutoScroll; tags[i].ti_Data = (ULONG) 1L;
		i++;
	}
	if (oscanflag) 
	{
		tags[i].ti_Tag = SA_Overscan;   tags[i].ti_Data = (ULONG) 1L;
		i++;
	}
	if (ns->Depth > 1) 
	{
		for (j = 0; j < 10; j++)
			p_pens[j] = std_pens[j];
		if ((n >= 6) && args[5]) 
		{
			for (j = 0;  (args[5][j] != '\0') && (j < 9); j++) 
			{
				p_pens[j] = ((unsigned char) args[5][j] - '0') & 0x1F;

				if (j == 0)	// Screen Title Detail (text) Pen
					ns->DetailPen = p_pens[j];
				if (j == 1)	// Screen Title Block (background) Pen
					ns->BlockPen = p_pens[j];
			}
			p_pens[j] = 0xffff;
		}
		tags[i].ti_Tag = SA_Pens;       tags[i].ti_Data = (ULONG) p_pens;
		i++;
	}
	tags[i].ti_Tag = TAG_END;          tags[i].ti_Data = (ULONG) 0L;
	
	if ((n >= 4) && args[3]) 
	{
		tp = mymalloc(strlen(args[3]) + 1);
		if (!tp)
			goto cleanup;
		strcpy(tp, args[3]);
		ns->DefaultTitle = (UBYTE *) tp;
	}
	
	ps = OpenScreen( (struct NewScreen *) ns);
	if (!ps)
		goto cleanup;
	
	result = PubScreenStatus(ps, 0L);
	
	cleanup:
#if screentest
	if (ofile)
		fclose( ofile )
#endif
	if (ns)
		FreeMem(ns, NSSIZE);
	
	if (result & 1) 
	{
		*err = 0;
		return(CAS("1"));
	}
	
	if (ps)
		CloseScreen(ps);

	if (tp)
		myfree(tp);
	
	return(CAS("0"));
}


/**
 *
 *   Close a public screen
 *
**/
char *rxf_sclose( long *err, int n, char *args[] )
{
	struct Screen *ps = NULL;
	char *tp = NULL;
	long sts;
	
	*err = 18;
	if (!args[0])
		goto cleanup;
	
	*err = 12;
	
	ps = LockScreen(args[0]);
	if (ps) 
	{
		UnlockScreen(args[0], ps);
		sts = PubScreenStatus(ps, PSNF_PRIVATE);

		if (sts & 1L)
		{
			tp = (char *) ps->DefaultTitle;
			CloseScreen(ps);
			if (tp)
				myfree(tp);
			*err = 0;
		}
	}
	
	cleanup:
	if (*err)
		return(CAS("0"));
	
	return(CAS("1"));
}

/**
 *
 *   Encapsulation of (un)locking screens
 *
**/
struct Screen *LockScreen( char *name )
{
	struct Screen *ps = NULL;
	
	if (name == NULL)
		return(NULL);
	
	ps = LockPubScreen(name);
	
	return(ps);
}

struct Screen *UnlockScreen( char *name, struct Screen *ps )
{
	if (name && ps) 
		UnlockPubScreen(NULL, ps);
	return(NULL);
}

/**
 *
 *  Function to set GLOBAL workbench screen shanghai mode....
 *	I wonder what it does with THREE screens?
 *
**/
char *rxf_sshanghai( long *err, int n, char *args[] )
{
	UWORD	 oldmode = 0;
	ULONG	 newmode = 0;
	char	 returnval[8];

	if ( n < 1 || !args[0] )
	{
		SetDefaultPubScreen( NULL );
		newmode = 0;
	}
	else
	{
		if ( *args[0] == 0 )
			SetDefaultPubScreen( NULL );
		else
			SetDefaultPubScreen( args[0] );
    
		if ( n >= 2 && args[1] )
		{
			if ( *args[1] >= '0' && *args[1] <= '3' )
				stch_l( args[1], (long*) &newmode );
			else
			{
				if ( strstr( args[ 1 ], "POPPUBSCREEN" ))
					newmode |= POPPUBSCREEN;
				if ( strstr( args[ 1 ], "SHANGHAI" ))
					newmode |= SHANGHAI;
			}
		}
	}

	oldmode = SetPubScreenModes( newmode );
	*err = 0;
cleanup:
	stci_d( returnval, oldmode );
	if ( *err )
		return CAS("0");
	return CAS(returnval);
}

/**
 *
 *  Function to set GLOBAL workbench screen shanghai mode....
 *	I wonder what it does with THREE screens?
 *
**/
char *rxf_sgdefpubscr( long *err, int n, char *args[] )
{
	char	 returnval[MAXPUBSCREENNAME];

	*err = 0;
	GetDefaultPubScreen( returnval );
	return CAS ( returnval );
}
