
/*
 * FAME MsgHeader Door
 * ~~~~~~~~~~~~~~~~~~~
 *
 * $VER: FAMEMsgHeader.c v1.6
 *
 * FAMEMsgHeader.FIM is a replacement door for MainPart's internal mail header!
 *
 * Door coded by David 'Strider/tRSi' Wettig e-mail: strider@trsi.de
 *
 * Design and idea by sCANDIC/dCN.
 *
 * Code by: David 'Strider/tRSi' Wettig
 * E-Mail:  strider@trsi.de
 * URL:     http://www.trsi.de/inno/strider/index.html
 *
 * Used tab size: 2
 */

/*
 * Includes:
 */

#include <FAME/FAMEPublic.h>

/*
 * Disable Lattice CTRL-C handling:
 */

#ifdef LATTICE
int CXBRK(void) {return(0);}
int chkabort(void) {return(0);}
#endif

/*
 * Define our version string for the "version" command:
 */

char *VerStr={"$VER: FAMEMsgHeader.FIM v1.6 "__AMIGADATE__};

/*
 * _ProgramName contains our filename:
 */

extern char	*_ProgramName;

/*
 * Prototypes:
 */

void ShutDown( long ErrCode );
void UserSigHandle(ULONG UserSigs);

/*
 * No CON window please, quit immediately.
 */

void __autoopenfail(void) { _XCEXIT(0);}

/*
 * Variables for ReadArgs and Template.
 */

char 	ArgStr[]		= "NODENR/N/A";
long	ArgArray[]	= {0L};

/*
 * Global variables:
 */

struct FAMELibrary	*FAMEBase			= NULL;
struct Library			*UtilityBase	= NULL;

/*
 * void main( void );
 *
 * main() entry point:
 */

void main( void )
{
	struct  RDArgs				*rda					= NULL;
	long									NodeNr;
	char									WorkStr[256],
												Buffer[256];
	struct FAMEMailHeader	*MyMailHeader	= NULL;

	/*
	 * Use ReadArgs() for arguments.
	 */

	if(rda = ReadArgs(ArgStr,ArgArray,NULL))
	{
		/*
		 * Read the Node number:
		 */

		if(ArgArray[0])
		{
			long *LDummy = (long *)ArgArray[0];
			NodeNr = (*LDummy);
		}

		FreeArgs(rda);
	}
	else
	{
		/*
		 * Something failed with the argument, exit the door:
		 */

    Printf("\nSorry, %s is a Door and must be called from FAME BBS!\n\n",_ProgramName);

		SetIoErr( ERROR_REQUIRED_ARG_MISSING );
		PrintFault(IoErr(),"FAMEMsgHeader.FIM");

    exit( RETURN_FAIL );
  }

	/*
	 * Now we have to open the FAME.library.
	 *
	 * From now on we have to call our ShutDown() function if something fails
	 * on our own resource initialisation where we have to release all our
	 * Door resources in ShutDown(). We are allowed to use ShutDown() just to
	 * the point where we call FIMStart(). From then we *HAVE* to call
	 * FIMEnd(0) to end the door!
	 *
	 * FIMEnd(0) will do our ShutDown() call then for us.
	 */

	if( ! (FAMEBase = (struct FAMELibrary *) OpenLibrary("FAME.library",0L)))
	{
		ShutDown( RETURN_FAIL );
	}

	/*
	 * Now we have to open the utility.library, needed for Stricmp:
	 */

	if( ! (UtilityBase = (struct Library *) OpenLibrary("utility.library",37L)))
	{
		ShutDown( RETURN_FAIL );
	}

	/*
	 * Ok time to continue with the Door initialisation code.
	 *
	 * Now we have to build the MessagePort name string of the Door we
	 * are called from:
	 */

  SPrintf(FAMEDoorPort,"FAMEDoorPort%ld",NodeNr);

	/*
	 * Now we start the Door initialising code.
	 *
	 * Here we can define the buffer size for the Global String Pointer
	 * if we need more than the default of 1024 bytes. If we call FIMEnd()
	 * with a value < 1024 bytes (FIM_MINBUFSIZE) like here (0) FIMStart()
	 * will use automatically the default value of FIM_MINBUFSIZE (1024 bytes).
	 *
	 * With the second argument we can set some flags we might need for our
	 * Door to tell the FIM DoorStartUp code how to handle some things we
	 * need. Following flags are available (bit-flags you can combine them by
	 * separating them with the OR sign: |
	 * i.e.: FIMF_USERSIGMODE | FIMF_NOCHECK.
	 *
	 * - FIMF_USERSIGMODE to enable the user signal check.
	 * - FIMF_NOCHECK to disable the error check of FIM commands send to
	 *   the door. Some doors might need to continue work also if there is
	 *   a problem with the port or a command like a lost carrier.
	 *   If FIMF_NOCHECK is set *YOU* have to check the return code of the
	 *   support commands you are using yourself!
	 *
	 * Example: (FIM_CMDSUCCESSFULL = 0)
	 *
	 * if(GetString(StrBuffer,50) < FIM_CMDSUCCESSFULL)
	 * {
	 *   ...
	 *
	 *   FIMEnd(0);
	 * }
	 *
	 *
	 * From now on you *HAVE* to call FIMEnd(0) to end the door!
	 * FIMEnd(0) calls the from the door supported function ShutDown() itself.
	 * This is also the reason why if FIMStart() fails no longer ShutDown()
	 * will be called from here. FIMStart() has already called it if something
	 * failed during the Door initialisation so if FIMStart() fails just
	 * exit() is needed here:
	 */

  if(FIMStart( 0, FIMF_USERSIGMODE ))
	{
		exit( RETURN_ERROR );
	}

  /*
	 * Place your own code in here:
	 */

	// ****************************************************************

	/*
	 * Get the struct FAMEMailHeader pointer to read all datas from it:
	 */

	GetCommand("",0,0,0,RD_GetMailHeader);

	/*
	 * MyMailHeader (struct FAMEMailHeader) valid?
	 */

	if(MyMailHeader = (struct FAMEMailHeader *)MyFAMEDoorMsg->fdom_StructDummy1)
	{
		/*
		 * Pointer is valid, we now build the mail header:
		 */

		if(MyMailHeader->fmah_Private)
		{
			strcpy(WorkStr,"Private Message");
		}
		else
		{
			strcpy(WorkStr,"Public Message ");
		}
		PutStringFormat("[36m.---[34m[[35mMsgNo[34m:  [33m%6ld[34m][36m---[34m[[35mReal No[34m: [33m%6ld[34m][36m---[34m[[35mMsgStatus[34m: [33m%s [34m][36m------.\r\n",MyMailHeader->fmah_MsgNum,MyMailHeader->fmah_AktMsgNum,WorkStr);

		strcpy(WorkStr,ctime(&MyMailHeader->fmah_MsgDate));
		WorkStr[strlen(WorkStr) - 1] = '\0';
		PutStringFormat("| [35mDate    [34m: [m%s  [34m/  [35mCrypt       [34m: [mNot available yet[32m!     [36m|\r\n",WorkStr);

		if(MyMailHeader->fmah_DeleteInDays < 1)
		{
			strcpy(WorkStr,"switched off[32m!");
		}
		else
		{
			SPrintf(WorkStr,"%ld[32m",MyMailHeader->fmah_DeleteInDays);
		}
		FAMEStrCopy(MyMailHeader->fmah_ToName,Buffer,24);
		PutStringFormat("| [35mTo      [34m: [33m%-24s [34m/   [35mDel in Days [34m: [m%-27s [36m|\r\n",Buffer,WorkStr);

		if( ! Stricmp(MyMailHeader->fmah_ToName,"EALL") || !Stricmp(MyMailHeader->fmah_ToName,"ALL"))
		{
			strcpy(WorkStr,"-/-");
		}
		else if(MyMailHeader->fmah_ToNameRec)
		{
			strcpy(WorkStr,"YES");
		}
		else
		{
			strcpy(WorkStr,"NO");
		}
		FAMEStrCopy(MyMailHeader->fmah_FromName,Buffer,24);
		PutStringFormat("| [35mFrom    [34m: [33m%-24s [34m\\   [35mReceived    [34m: [33m%-3s [32m([mRead [33m",Buffer,WorkStr);

		SPrintf(WorkStr,"%ld [mtimes[32m)",MyMailHeader->fmah_Received);
		PutStringFormat("%-21s[36m|\r\n",WorkStr);

		if(MyMailHeader->fmah_AFileStat)
		{
			strcpy(WorkStr,"File[32m([ms[32m)[33m attached[32m!     ");
		}
		else
		{
			strcpy(WorkStr,"Msg only[32m!");
		}
		FAMEStrCopy(MyMailHeader->fmah_Subject,Buffer,24);
		PutStringFormat("| [35mSubject [34m: [33m%-24s [34m/   [35mFiles       [34m: [33m%-27s [36m|\r\n",Buffer,WorkStr);

		/*
		 * We copy our string into a buffer, because the strip ansi function will
     * used if a user won't have colors changes the origin data which will
     * be in this case here our global and READ-ONLY string between the ""
		 * chars. Normally everything will be ok if we don't copy it into a buffer,
		 * but if you run this door resident the string between the "" chars
     * will be modified by the internal strip ansi function. This may cause
     * wrong colors on resident doors. The strings like this one here
		 * are global data located in the code section of our tool! This means
		 * read only! Such strings are not in the NEAR data section and won't be
		 * copied for each new resident call. That's why we copy it into a buffer
		 * where the strip ansi procedure can change the string as it needs.
		 *
		 * Another way is if you don't like to save your global strings like
		 * here with copying it into a buffer before sending it to the MainPart
		 * is to compile with the code option: StrSect=NEAR where the compiler
		 * will put such strings into the NEAR data section which will be copied
		 * for each resident call.
		 *
		 * You can also replace PutString() with PutStringFormat(), but in this
		 * case the lentgh is limited to the IOString size of the door message
		 * structure.
		 *
		 * We will write in future a special strip ansi function a dynamical one
		 * were the buffer problem will be fixed so that the strip ansi
		 * function doesn't change anything in the origin string.
		 * You will find this ansi strip function in the FAME.libray if it's
		 * complete. If this function is ready we can handle unlimited string
		 * lengths without modifying the source string.
		 *
		 * But till this strip function is implemeted, beware that your string
		 * can be modified!!!
		 *
		 * Note: We only want to do it in an unlimited way, because we doesn't
		 *       like to code limited stuff... we love to write perfectionally
		 *       code, because we are perfectionalists.
		 *       The fact that you are able to send length unlimited strings
		 *       to the Node screen justifies not to do this also!
		 *       Due to the Amiga AutoDocs you shall not send more than
		 *       255 chars at once to a device, because if a console window
		 *       for example is full it have to scroll. If your string is
		 *       to long you interrupt the multitasking!
		 *       So take care of it... if you do a clear screen before or with
     *       the string at it's beginning you might send longer strings.
		 */

		strcpy(WorkStr,"`-----------------------------------[34m/[36m-----------------------------------------'[m\r\n\n");
		PutString(WorkStr,0);

		/*
		 * Header viewed, now set the number of viewed lines to let MainPart
		 * do the first pause prompt at the right place:
		 */

		MyMailHeader -> fmah_HeadNumLines = 7;
	}
	else
	{
		/*
		 * Pointer isn't valid, but a mail header *MUST* be displayed to the user!
		 *
		 * Solution: Inform MainPart to view the internal MailHeader:
		 */

		PutCommand("",1,0,0,RD_ShowMailHeader);
	}

	// ****************************************************************

	/*
	 * End the Door:
	 */

	FIMEnd(0);

} // void main( void );

/*
 * void ShutDown( long ErrCode );
 *
 * This function has to be supplied by the door and will be called if any
 * error occures. It's up to the door to exit or continue the work, but
 * remember that the DoorPort and therefor the communication to FAME is
 * CLOSED ! The errcode contains the errorcode supplied by FAME, you may
 * use it to your own requirements.
 */

void ShutDown( long ErrCode )
{
	/*
	 * Now close the utility.library.
	 *
	 * First check if the resource is really allocated:
	 */

	if(UtilityBase)
	{
		CloseLibrary((struct Library *)UtilityBase);
	}

	/*
	 * To NULL our pointers after freeing the resource of it is *VERY*
	 * important to avoid problems if ShutDown() gets called more the one time!
	 */

	UtilityBase	= NULL;

	/*
	 * Now close the FAME.library.
	 *
	 * First check if the resource is really allocated:
	 */

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

	/*
	 * To NULL our pointers after freeing the resource of it is *VERY*
	 * important to avoid problems if ShutDown() gets called more the one time!
	 */

	FAMEBase = NULL;

	/*
	 * Now do some standard AmigaOS error handling if needed:
	 */

	if(ErrCode < RETURN_OK )
	{
		SetIoErr( ERROR_OBJECT_NOT_FOUND );
		PrintFault(IoErr(),"FAMEMsgHeader.FIM");

		ErrCode = RETURN_ERROR;
	}

	/*
	 * Exit the Door with a standard and defined AmigaOS exit code:
	 */

	exit( ErrCode );

} // void ShutDown( long ErrCode );

/*
 * void UserSigHandle( ULONG UserSigs );
 *
 * This function has to be supplied by the door and will be called if any
 * user signal occures. User signals will be set via FIMHandlePort() in the
 * second argument "ULONG UserSigs". Use NULL here if you don't have any
 * signals to be supported. UserSigHandle() will be called if any user
 * signals are set and if FIMHandlePort() receives them. In this case
 * check the argument "UserSigs" in your UserSigHandle() function.
 *
 * You can also use the global variable "GlobUserSigs" to inform
 * FIMHandlePort() about your own additional signal bits.
 * In this case FIMHandlePort()'s second argument "ULONG UserSigs" has to
 * be always NULL, because this argument has the higher priority and
 * "GlobUserSigs" will not be used then.
 * "GlobUserSigs" is to handle your own signal bits more easy.
 * All support functions will pass NULL to FIMHandlePort() so usage of
 * "GlobUserSigs" is possible without doing any changes to the doorstartup
 * code.
 *
 *
 * FAMEMsgHeader.FIM needs no user signals so UserSigHandle() will just return.
 *
 * It's only implemented for FAMEDoorStartUp codes compiled with the
 * FIM_USERSIGMODE define.
 */

void UserSigHandle( ULONG UserSigs )
{
	// Do nothing - just return.

} // void UserSigHandle( ULONG UserSigs );

