/* FarCom.c *****************************************************************
*
*	FarCom --------	Debugging functions for programs which don't
*			have links to their environment.
*
*			FarPrint communication routines.
*
*	Author --------	Olaf Barthel of ED Electronic Design Hannover
*			Brabeckstrasse 35
*			D-3000 Hannover 71
*
*			Federal Republic of Germany.
*
*	This program truly is in the PUBLIC DOMAIN. Written on a sunny
*	September day in 1989.
*
*	Compiled using Aztec C 3.6a, CygnusEd Professional & ARexx.
*
****************************************************************************/

#include <exec/ports.h>

	/* Forward declarations. */

extern struct MsgPort	*FindPort();
extern struct MsgPort	*CreatePort();

	/* Global task <-> task communication stuff. */

#define FM_ADDTXT	0
#define FM_REQTXT	1
#define FM_REQNUM	2

struct FarMessage
{
	struct Message	fm_ExecMessage;

	USHORT		fm_Command;
	STRPTR		fm_Identifier;
	STRPTR		fm_Text;
};

	/* SendIt(MessageText,Identifier,Command):
	 *
	 *	Sends message/request to FarPort, completely
	 *	reentrant, shouldn't work from interrupt code
	 *	since we wait for the reply.
	 */

BOOL
SendIt(MessageText,Identifier,Command)
STRPTR MessageText,Identifier;
USHORT Command;
{
	struct MsgPort *ReplyPort,*FarPort;
	struct FarMessage FarMessage;

		/* Destination port present? */

	if(FarPort = (struct MsgPort *)FindPort("FarPort"))
	{
			/* Create a replyport. */

		if(ReplyPort = (struct MsgPort *)CreatePort(NULL,0L))
		{
				/* Initialize custom message structure. */

			FarMessage . fm_ExecMessage . mn_Node . ln_Type	= NT_MESSAGE;
			FarMessage . fm_ExecMessage . mn_Length		= sizeof(struct FarMessage);
			FarMessage . fm_ExecMessage . mn_ReplyPort	= ReplyPort;
			FarMessage . fm_Text				= MessageText;
			FarMessage . fm_Identifier			= Identifier;
			FarMessage . fm_Command				= Command;

				/* Send it and wait for a reply. */

			PutMsg(FarPort,&FarMessage);
			Wait(1 << ReplyPort -> mp_SigBit);

				/* Remove the replyport. */

			DeletePort(ReplyPort);

			return(TRUE);
		}
	}

	return(FALSE);
}

	/* AddText(MessageText):
	 *
	 *	Subroutine called by SendText, adds a Text to
	 *	the list of messages FarPrint maintains.
	 */

BOOL
AddText(MessageText)
STRPTR MessageText;
{
	return(SendIt(MessageText,NULL,FM_ADDTXT));
}

	/* RequestNumber(Identifier):
	 *
	 *	Requests a number to be entered by the user.
	 *	Identifier points to a string which is to
	 *	identify the calling process.
	 */

long
RequestNumber(Identifier)
STRPTR Identifier;
{
	UBYTE NumBuff[81];

	setmem(NumBuff,81,0);

	SendIt(NumBuff,Identifier,FM_REQNUM);

	return(atoi(NumBuff));
}

	/* RequestString(Identifier):
	 *
	 *	Requests a string to be entered by the user,
	 *	Identifier points to a string which is to
	 *	identify the calling process. Note: this one
	 *	isn't reentrant since it uses a temporary
	 *	string buffer. This could easily be fixed
	 *	by using a second argument to be used as
	 *	a destination string buffer.
	 */

STRPTR
RequestString(Identifier)
STRPTR Identifier;
{
	static UBYTE TxtBuff[81];

	if(SendIt(TxtBuff,Identifier,FM_REQTXT))
		return(TxtBuff);
	else
		return(NULL);
}

	/* This embedded assembly fragment handles the SendText()
	 * function. It basically consists of a call to the
	 * exec RawDoFmt() function to build the argument string
	 * it passes to AddText(). Original Author: Justin V. McCormick.
	 */

#asm
_LVORawDoFmt	EQU	$FFFFFDF6

		XDEF	kput1

kput1:		MOVE.B	D0,(A3)+
		RTS

		XDEF	_SendText

_SendText:	LINK	A5,#-512
		MOVEM.L	D1/A0-A3,-(SP)

		MOVEA.L	8(A5),A0
		LEA	12(A5),A1
		LEA	kput1(PC),A2
		LEA	-512(A5),A3
		MOVE.L	4,A6
		JSR	_LVORawDoFmt(A6)
	
		LEA	-512(A5),A0

		MOVE.L	A5,-(SP)
		MOVE.L	A0,-(SP)

		JSR	_geta4#	; Use this call only with small code
				; memory model or it will pull half of the
				; standard library code into your
				; program (devilish when developing
				; a shared library!)

		JSR	_AddText

		ADD.W	#4,SP
		MOVE.L	(SP)+,A5

		MOVEM.L	(SP)+,D1/A0-A3
		UNLK	A5
		RTS
#endasm
