/*
	<TABSTEP=3>

	TstPubScr V1

	Tests whether there's a specific public-screen out there.
	Returns AmigaOS Errorlevel RETURN_ERROR(==10) if not found !

	TstPubScr PUBSCRNAME,FORMAT/K,DEFAULT/S,FORCE/S,BATCH/S,LOCK=UNLOCK/S

	PUBSCRNAME		:	Name of the pubscreen you want to access.
							If found, its name will be printed to stdout
							and the prog returns RETURN_OK(==0).
							If this screen couldn't be found, a blank "" will be
							return (indicates default pubscreen) and returncode
							RETURN_WARN(==5) will be returned.
							You may disable this feature by FORCE:
	FORCE				:	Do not print out alternative name of the default pubscr.
	DEFAULT			:	Get name of default publicscreen ("").
	FORMAT			:	Pattern to format output (include '%s' for the name of
							the publicscreen found).
							Note that the name of the public screen will always be
							quoted !
	BATCH				:	Does not print out any information except the requested
							name (thus you won't ever have any trash in an env.-
							variable).
	LOCK & UNLOCK	:	This switch says TstPubScr to keep a lock on the related
							publicscreen.
							Call TstPubScr twice (with the same parameters; you may
							replace 'LOCK' by 'UNLOCK' !) to unlock that specific screen.
							Uses ENV: to store address of the screens locked !

	No parameter	:	List names of all public screens.

	(c)6.3.1995 by Hans Bühler, Codex Design Software
*/

#include	<exec/types.h>
#include	<exec/exec.h>
#include	<dos/dos.h>
#include	<dos/rdargs.h>
#include	<intuition/intuition.h>
#include	<intuition/screens.h>
#include	<stdio.h>
#include	<string.h>
#include	<stdlib.h>

#include	<proto/exec.h>
#include	<proto/dos.h>
#include	<proto/intuition.h>

// ------------------------------------
// defines
// ------------------------------------

#define	PROGNAME			"TstPubScr V1.00"
#define	NAMELEN			40
#define	CONDEFLEN		255
#define	NAMEPATTERN		"TstPubScr: pubscr_$%08lx_lock"

/* offsets */
#define	ARG_PUBSCRNAME	0
#define	ARG_FORMAT		1
#define	ARG_DEFAULT		2
#define	ARG_FORCE		3
#define	ARG_BATCH		4
#define	ARG_LOCK			5
#define	ARG_NUM			6

/* defaults */
#define	DEF_PUBSCRNAME	0
#define	DEF_FORMAT		(LONG)("%s")
#define	DEF_DEFAULT		FALSE
#define	DEF_FORCE		FALSE
#define	DEF_BATCH		FALSE
#define	DEF_LOCK			FALSE

#define	DEF_CONDEF		"CON:100/50/400/100/ " PROGNAME ": public screen list/AUTO/CLOSE"

/* some shortcuts */
#define	Eprintf			if(!Args[ARG_BATCH]) printf

// ------------------------------------
// types
// ------------------------------------

struct NewPort		{	struct MsgPort		Port;
							char					Name[NAMELEN+1];
						};

struct NodeCopy	{	struct NodeCopy	*Next;
							char					Name[MAXPUBSCREENNAME+2];
						};

// ------------------------------------
// proto
// ------------------------------------

int	PrintPubScrList(void);

// ------------------------------------
// global
// ------------------------------------

static char				CmdLine[]		=	"PUBSCRNAME,"
													"FORMAT/K,"
													"DEFAULT/S,"
													"FORCE/S,"
													"BATCH/S,"
													"LOCK=UNLOCK/S";

static LONG				Args[ARG_NUM]	=	{	DEF_PUBSCRNAME,
														DEF_FORMAT,
														DEF_DEFAULT,
														DEF_FORCE,
														DEF_BATCH,
														DEF_LOCK
													};

static const char		HelpTxt[]		=	PROGNAME " (w)6.3.1995 by Hans Bühler, Codex Design Software\n"
													"\n"
													" This programm is able to find out whether a specific (or default)\n"
													"public screen is known to your system.\n"
													" It is dedicated for use in batch scripts.\n"
													"\n"
													"PUBSCRNAME : Name of public screen you want to find.\n"
													"             If found, RETURN_OK (0) is returned and its\n"
													"             name will be written to stdout.\n"
													"             In other cases, RETURN_WARN (5) will be returned\n"
													"             and the default pub name will be put out (\"\").\n"
													"FORMAT     : Output format string. Use '%s' for pubname.\n"
													"             Name will be quoted.\n"
													"DEFAULT    : Get default pubscreens name (\"\").\n"
													"FORCE      : Do not put out the default public screen name if\n"
													"             PUBSCRNAME is unknown to your system.\n"
													"BATCH      : Supress all output except the pub name.\n"
													"(UN)LOCK   : Lock screen. You MUST unlock it later: Use the same\n"
													"             cmdline (you may replace 'LOCK' by 'UNLOCK', but that\n"
													"             really wouldn't matter...), and run the program again.\n"
													"\n"
													" For further information, refer to the manual.\n"
													"This program is freeware. Source available.\n"
													"Suggestions/questions/etc. to:\n"
													" e-mail  h0348kil@rz.hu-berlin.de\n"
													" phone   ++49 (0)30 3963374\n";

static struct RDArgs	SetArgs			=	{	{	0,0,0	},
														0,0,0,HelpTxt,0
													};

char	__stdiowin[CONDEFLEN+1]			=	DEF_CONDEF;

// ------------------------------------
// fkt.
// ------------------------------------

int main(int argc, char **argp)
{
	struct RDArgs	*rdargs;
	struct Screen	*pubscr;
	char				*pubname,
						portname[MAXPUBSCREENNAME+3];
	struct NewPort	*port;
	int				error		=	RETURN_OK;

	if( rdargs = ReadArgs(CmdLine,Args,&SetArgs))
	{
		if(!Args[ARG_PUBSCRNAME] && !Args[ARG_DEFAULT])
			error	=	PrintPubScrList();
		else
		{
			pubname	=	(char *)(Args[ARG_DEFAULT] ? 0 : Args[ARG_PUBSCRNAME]);

			if(!(pubscr = LockPubScreen(pubname)))
			{
				if(!Args[ARG_DEFAULT])
					error	=	RETURN_WARN;

				if(!Args[ARG_FORCE] && pubname)
					pubscr = LockPubScreen(pubname = 0);
			}

			if(!pubscr)
			{
				Eprintf(	"ERROR: Can't find public-screen '%s' !\n",
							Args[ARG_PUBSCRNAME] ? (char *)Args[ARG_PUBSCRNAME] : "<default>");
				error	=	RETURN_ERROR;
			}
			else
			{
				if(Args[ARG_LOCK])
				{
					sprintf(portname,NAMEPATTERN,pubscr);

					if(port = (struct NewPort *)FindPort(portname))		// already locked ?
					{
						RemPort((struct MsgPort *)port);
						FreeVec(port);

						UnlockPubScreen(0,pubscr);			// unlock twice !
					}
					else
						if(port = AllocVec(sizeof(struct NewPort),MEMF_CLEAR|MEMF_PUBLIC))
						{
							port->Port.mp_Flags			=	PA_IGNORE;
							port->Port.mp_Node.ln_Name	=	port->Name;
							strcpy(port->Name,portname);
							AddPort((struct MsgPort *)port);

							LockPubScreen(pubname);			// lock it twice !
						}
						else
							Eprintf(	"ERROR: Can't lock publicscreen; not enough\n"
										" memory (%ld bytes) to store lock !\n",
										sizeof(struct NewPort));
				}

				sprintf(portname,"\"%s\"",pubname);
				printf((char *)Args[ARG_FORMAT],portname);
				UnlockPubScreen(0,pubscr);
			}
		}

		FreeArgs(rdargs);
	}
	else
	{
		if(!Args[ARG_BATCH])
			PrintFault(IoErr(),"ReadArgs() error: ");

		error	=	RETURN_FAIL;
	}


	/* shut down */

	exit(error);
}

// ------------------------------------
// additional funx
// ------------------------------------

/******************************************************/
/* Function made to browse through the pubscreen list */
/* --------------------------------------------------	*/
/* return:						RETURN_xxx code				*/
/******************************************************/

int PrintPubScrList(void)
{
	struct NodeCopy		*first,*last,*copy;
	struct PubScreenNode	*pubnode;
	struct List				*publist;
	char						buf[MAXPUBSCREENNAME+3];
	BOOL						MemErr	=	FALSE;
	int						ret		=	RETURN_OK;

	first	=	last	=	0;

	if(publist = LockPubScreenList())
	{
		// -- load list names --

		for(	pubnode = (struct PubScreenNode *)publist->lh_Head;
				pubnode->psn_Node.ln_Succ;
				pubnode = (struct PubScreenNode *)pubnode->psn_Node.ln_Succ)
			if(!(pubnode->psn_Flags & PSNF_PRIVATE))
			{
				if( copy = AllocVec(sizeof(struct NodeCopy),MEMF_CLEAR|MEMF_PUBLIC) )
				{
					if(last)
						last->Next	=	copy;
					else
						first			=	copy;

					last				=	copy;

					strncpy(copy->Name,pubnode->psn_Node.ln_Name,MAXPUBSCREENNAME);
				}
				else
				{
					MemErr	=	TRUE;
					break;
				}
			}

		UnlockPubScreenList();

		// -- put out names --

		Eprintf("PubScreens known to your system:\n\n");

		while(first)
		{
			sprintf(buf,"\"%s\"",first->Name);
			printf((char *)Args[ARG_FORMAT],buf);
			putchar('\n');

			copy	=	first;
			first	=	first->Next;

			FreeVec(copy);
		}

		if(MemErr)
		{
			Eprintf("ERROR: Can't load further pubscrnames; out of memory !\n");
			ret	=	RETURN_ERROR;
		}
	}
	else
	{
		Eprintf("ERROR: Can't lock pubscreenlist !\n");
		ret	=	RETURN_FAIL;
	}

	return ret;
}
