
/* FAME DoorInclude
 *
 * $VER:FAMEDoorStartUp.c v0.22
 *
 * Used tab size: 2
 */

/* Includes:
 */

#include <FAME/FAMEPublic.h>

/* Global variables:
 */

struct MsgPort			*DoorControlPort	= NULL,
										*DoorReplyPort		= NULL;
struct FAMEDoorMsg	*MyFAMEDoorMsg		= NULL,
										*FAMEDoorReplyMsg	= NULL;
struct FAMEBase			*FAMEBase					= NULL;

STRPTR				FAMEDoorPort[30];
char					ErrorText[100];
int						EndFlag									= 0;
unsigned long	Signals,
							PortSig;

/* Prototypes:
 */

void GetString(char*,long);
void PutString(char*,long);
void PutStringFormat(char *ctl, ...);
void PutCommand(char*,long,long,ULONG,long);
void GetCommand(char*,long,long,ULONG,long);
int  CheckMessage(void);
int  PortStart(void);
void PortEnd(int code);
void PrintError(long);
void Center(char *stri,long lf,long col);
void CutAnsi(char*);
long FAMEAtol(STRPTR ConvertString);

/* -------------------------- Procedures: --------------------------------
 */

/* SPrintf via RawDoFmt:
 *
 * Note that you have to uses long aligned values means instead of only
 * using %d you have to use %ld! Also %lc ...
 */

void SPrintf(char *Buffer,char *ctl, ...)
	{RawDoFmt(ctl, (long *)(&ctl + 1), (void (*))"\x16\xc0\x4e\x75",Buffer);}

/* Let's have our own Atol:
 */

long FAMEAtol(STRPTR ConvertString)
{
	long ConvertLong;

	StrToLong(ConvertString,&ConvertLong);
	return(ConvertLong);
}

/* Something went wrong?
 */

void PrintError(long Fehler)
{
	long	wrongcommand;
  char	*Button[10] = {"NR","NC","CF","SR","SC","AR","AC","RD"};
  int		butnum = 0;

	wrongcommand = MyFAMEDoorMsg->fdom_Command;
	*ErrorText = '\0';
  switch(Fehler)
	{
		case 4:
			SPrintf(ErrorText,"\n\rCommand %ld not implemented until now in this Version of Fame !\n\n\r",wrongcommand);
		break;
		case 2:
			SPrintf(ErrorText,"\n\rCommand %ld doesn't exist !\n\n\r",wrongcommand);
		break;
		case 1:
			SPrintf(ErrorText,"\n\rCommand %ld couldn't be executed successfully !\n\n\r",wrongcommand);
		break;
		default:
			if(wrongcommand > 999)
				butnum = 7; // RD
			else if(wrongcommand > 899)
				butnum = 6;	// AC
			else if(wrongcommand > 799)
				butnum = 5;	// AR
			else if(wrongcommand > 699)
				butnum = 4;	// SC
			else if(wrongcommand > 599)
				butnum = 3;	// SR
			else if(wrongcommand > 399)
				butnum = 2;	// CF
			else if(wrongcommand > 199)
				butnum = 1;	// NC
			else if(wrongcommand > 9)
				butnum = 0;	// NR

			SPrintf(ErrorText,"\n\rDoor uses %s Command, please allow it in your SystemEditor!\n\n\r",Button[butnum]);
		break;
	}

  ShutDown(SHUTDOWN_NOTALLOWED);
}

/* Put the request and wait for response:
 */

int CheckMessage(void)
{
	if(DoorControlPort) {

		Forbid();
		PutMsg(DoorControlPort,(struct Message *)MyFAMEDoorMsg);
		Permit();

		Signals = Wait(PortSig);

		if(Signals & PortSig) {

			if(FAMEDoorReplyMsg = (struct FAMEDoorMsg *)GetMsg(DoorReplyPort))
				EndFlag = 0;
			if(MyFAMEDoorMsg->fdom_ReturnCode < 0)
				EndFlag = 1;
		}
	} else {

		FPuts(Output(),"Error! Can't longer locate FAMEDoorPort!\n");
		EndFlag = 1;
	}
	if(EndFlag)
		ShutDown(0);

	return(MyFAMEDoorMsg->fdom_ReturnCode);
}

/* Initialise the port and tell FAME that we are here:
 */

int PortStart(void)
{
  int error = 0;

	/* Open FAME.library and init door port:
   */

	if( ! (FAMEBase = (struct FAMEBase *) OpenLibrary(FAMENAME,FAMEVERSION)))
		exit(RETURN_FAIL);

  if(DoorReplyPort = CreatePort(NULL,0L)) {

    PortSig = 1<<DoorReplyPort->mp_SigBit;

    if(MyFAMEDoorMsg = (struct FAMEDoorMsg *)FAMEAllocObject(FOBJ_FAMEDoorMsg)) {

      MyFAMEDoorMsg->fdom_Msg.mn_Node.ln_Type	= NT_MESSAGE; /* Not realy needed, because PutMsg() does it also */
      MyFAMEDoorMsg->fdom_Msg.mn_Length				= sizeof(struct FAMEDoorMsg);
      MyFAMEDoorMsg->fdom_Msg.mn_ReplyPort			= DoorReplyPort;
      MyFAMEDoorMsg->fdom_Command							= MC_DoorStart; /* Register Door */

      Forbid();
      DoorControlPort = FindPort((UBYTE *)FAMEDoorPort);
      Permit();

      if( ! DoorControlPort) {

        Printf("Can't find FAMEDoorPort \"%s\"\n",FAMEDoorPort);
        error = 3;
      } else
				CheckMessage();
    } else {

      FPuts(Output(),"Can't allocate memory for FAMEDoorMsg Message Structure!\n");
      error = 2;
    }
  } else {

    FPuts(Output(),"Can't setup ReplyPort!\n");
    error = 1;
  }

  return(error);
}

/* Notify FAME of shutdown, and then exit safely
 * Known Code-values are :
 *                            0 = All went okay, normal exit
 *  SHUTDOWN_NOTALLOWED (10000) = Command Allow Gadget not activated, abort
 *                                with ShutDownLastWords!
 * SHUTDOWN_BACKGROUND (100000) = Normal stop, but doesn't exit, only Return
 *                                to work in Background!
 *                          < 0 = Any other error (no mem etc.), exit...
 */

void PortEnd(int code)
{
  if(code > 0 && DoorControlPort && code != SHUTDOWN_BACKGROUND) {

    SPrintf(MyFAMEDoorMsg->fdom_IOString,"[0mDoor failed returncode: %ld\n",code);
    MyFAMEDoorMsg->fdom_Command			= NR_SendStrCRLF;
    CheckMessage();
 	};
	if(code == SHUTDOWN_NOTALLOWED) {

		MyFAMEDoorMsg->fdom_Command			= MC_ShutDownLastWords;
		strcpy(MyFAMEDoorMsg->fdom_IOString,ErrorText);
	} else
		MyFAMEDoorMsg->fdom_Command = MC_ShutDown;

  if(DoorControlPort)
		CheckMessage();
  if(MyFAMEDoorMsg)
		FAMEFreeObject(MyFAMEDoorMsg);
  if(DoorReplyPort)
		DeletePort(DoorReplyPort);

	if(FAMEBase)
		CloseLibrary((struct Library *)FAMEBase);

	if(code == SHUTDOWN_BACKGROUND)
		return;
  else
		exit(code);
}

/* Request a string from the user:
 */

void GetString(char text[],long Data)
{
  MyFAMEDoorMsg->fdom_Command	= NR_PromptChars;
  MyFAMEDoorMsg->fdom_Data1		= Data;
  MyFAMEDoorMsg->fdom_Data2		= 6;
  strcpy(MyFAMEDoorMsg->fdom_IOString,text);
  if(CheckMessage() > 0)
		PrintError(MyFAMEDoorMsg->fdom_ReturnCode);
	if(text)	
		strcpy(text,MyFAMEDoorMsg->fdom_IOString);
}

/* Put a string to the user:
 */

void PutString(char text[],long lf)
{
	MyFAMEDoorMsg->fdom_Command		= AR_SendStr;
	if(lf)
		MyFAMEDoorMsg->fdom_Data1		= 1;
	else
		MyFAMEDoorMsg->fdom_Data1		= 0;
	MyFAMEDoorMsg->fdom_StringPtr	= text;
  if(CheckMessage() > 0)
		PrintError(MyFAMEDoorMsg->fdom_ReturnCode);
}

/* Put a formated string to the user:
 */

void PutStringFormat(char *ctl, ...)
{
	RawDoFmt(ctl, (long *)(&ctl + 1), (void (*))"\x16\xc0\x4e\x75",MyFAMEDoorMsg->fdom_IOString);
	MyFAMEDoorMsg->fdom_Command		= NR_SendStr;
	if(CheckMessage() > 0)
		PrintError(MyFAMEDoorMsg->fdom_ReturnCode);
}

/* Put a command, normaly for changing datas.
 */

void PutCommand(char text[],long Data1,long Data2,ULONG Data3,long Command)
{
  MyFAMEDoorMsg->fdom_Command	= Command;
  MyFAMEDoorMsg->fdom_Data1		= Data1;
  MyFAMEDoorMsg->fdom_Data2		= Data2;
  MyFAMEDoorMsg->fdom_Data3		= Data3;
  strcpy(MyFAMEDoorMsg->fdom_IOString,text);
	if(CheckMessage() > 0)
		PrintError(MyFAMEDoorMsg->fdom_ReturnCode);
}

/* Get datas over a command:
 */

void GetCommand(char text[],long Data1,long Data2,ULONG Data3,long Command)
{
  MyFAMEDoorMsg->fdom_Command	= Command;
  MyFAMEDoorMsg->fdom_Data1		= Data1;
  MyFAMEDoorMsg->fdom_Data2		= Data2;
  MyFAMEDoorMsg->fdom_Data3		= Data3;
  strcpy(MyFAMEDoorMsg->fdom_IOString,text);
  if(CheckMessage() > 0)
		PrintError(MyFAMEDoorMsg->fdom_ReturnCode);
	if(text)
		strcpy(text,MyFAMEDoorMsg->fdom_IOString);
}

/* Changed: AllocVec() removed, as to often called this function!
 *   PARMS:  lf : 0=No LineFeed, 1=LineFeed after Printing
 *          col : ANSI-Color to use for the String
 *
 * Center a string:
 */

void Center(char *stri,long lf,long col)
{
	char 	r[256];
	long	mitte;

  strcpy(r,stri);
	CutAnsi(r);
	mitte = ((78 - strlen(r)) / 2);
	r[0] = '\0';
	SPrintf(r,"\r[%ldm[%ldC%s\0",col,mitte,stri);
	PutString(r,lf);
}

/* Strip ansi colors:
 */

void CutAnsi(char *e)
{
	char	*d,
				*s,
				*b;
	int		i;

	d = s = e;

	while(*d)
	{
		if(*d == '' || *d == '›') {
			i = 1;
			b = d;

			while(i < 6 && i > 0)
			{
				switch(*b)
				{
					case ';':
						i = 1;
						*b ++;
					break;
					case 'm':
						i = NULL;
						*b ++;
					break;
					case '\0':
						i = 6;
					break;
					default:
						*b ++;
						i ++;
				}
			}
			if( ! i)
				d = b;
			else if(*d)
				*s ++ = *d ++;
		} else
			*s ++ = *d ++;
	}
	*s = '\0';
}

