/*
 *   This file sends out REXX commands.  Now we start to get into
 *   the fun stuff.  Actually, it's pretty straightforward, from
 *   the TeX information.
 *
 *   For now, we do a no-no; we open and close the emacs port.
 *   Actually, this is probably fine, as we only expect REXX to
 *   send us messages in response to our messages.
 *
 *   The first thing we do is set up a cliplist variable called
 *   mg.
 */
#include "exec/ports.h"
#include "functions.h"
#include "fcntl.h"
#include "rexx/storage.h"
/*
 *   This is a hack.
 */
#undef TRUE
#undef FALSE
#undef VOID
#include "def.h"
extern BUFFER *curbp ;
extern WINDOW *curwp ;
struct MsgPort *mgport, *rport ;
long waitbits ;
struct REXXmsg {
   struct Message msgheader ;
   long *RexxTask, *LibBase ;
   long Command, Result1, Result2 ;
   char *Arg0, *Arg1, *Arg2 ; /* The rest we really don't care about */
   char *Args[13] ;
   void *PassPort, *CommAddr, *FileExt ;
   long Stdin, Stdout, avail ;
} *REXXmsg, setCmsg ;
/*
 *   This routine dispatches any REXX messages coming
 *   in.  We simply call our brand new fancy parsing
 *   routine!  (Getting some of those strings right
 *   might be fun, though . . .)
 */
mgdisp() {
   register char *p ;

   while (REXXmsg = (struct REXXmsg *)GetMsg(mgport)) {
      ewprintf(REXXmsg->Arg0) ;
      REXXmsg->Result1 = (excline(REXXmsg->Arg0) == TRUE ? 0 : 1) ;
      REXXmsg->Result2 = 0 ;
      ReplyMsg(REXXmsg) ;
   }
}
openmsgs() {
        Forbid() ;
        if (FindPort("mg")==NULL)
           mgport = CreatePort("mg", 0L) ;
        Permit() ;
        REXXmsg = NULL ;
        rport = CreatePort("mg:reply", 0L) ;
}
closemsgs() {
	if (mgport) {
	   FreeSignal((long)(mgport->mp_SigBit)) ;
	   RemPort(mgport) ;
	   mgdisp() ;
	   DeletePort(mgport) ;
	}
	if (rport) {
	   FreeSignal((long)(rport->mp_SigBit)) ;
	   RemPort(rport) ;
	   DeletePort(rport) ;
	}
}
struct MsgPort  *rexxport ;
poststring(n,s)
char *n, *s ;
{

	setCmsg.Arg0 = n ;
        setCmsg.Arg1 = s ;
	setCmsg.Arg2 = (char *)(long)strlen(s) ;
        setCmsg.Command = RXADDCON ;
        setCmsg.msgheader.mn_Node.ln_Type = NT_MESSAGE ;
        setCmsg.msgheader.mn_ReplyPort = rport ;
	Forbid() ;
	rexxport = FindPort("REXX") ;
	if (rexxport) {
	   PutMsg(rexxport, &setCmsg) ;
	}
	Permit() ;
	if (rexxport) {
	   WaitPort(rport) ;
	   GetMsg(rport) ;
	}
}
int pendingrexx ;
rexxcommand(f, n, k) {
	register BUFFER	*bp;
	int		s;
	char		cmd[120];

	if (pendingrexx)
	   return(FALSE) ;
	pendingrexx = 1 ;
	openmsgs() ;
        if (rport == NULL || mgport == NULL)
           goto failure ;
/*
 *   Now we tell everyone the name of the file we are editing,
 *   if any.
 */
	poststring("mg.BufferName", ((curbp && curbp->b_fname[0]) ?
               curbp->b_bname : "")) ;
/*
 *   Now, finally, we send out the message to the REXX port.
 */
	if ((s=ereply("REXX command: ", cmd, 120)) != TRUE)
		goto sfailure ;
        setCmsg.Arg0 = cmd ;
        setCmsg.Arg1 = (char *)(long)strlen(setCmsg.Arg0) ;
        setCmsg.Command = RXCOMM | RXFB_TOKEN | RXFB_NOIO ;
        setCmsg.FileExt = "mg" ;
        setCmsg.CommAddr = "mg" ;
        setCmsg.msgheader.mn_Node.ln_Type = NT_MESSAGE ;
        setCmsg.msgheader.mn_ReplyPort = rport ;
	Forbid() ;
	rexxport = FindPort("REXX") ;
	if (rexxport) {
	   PutMsg(rexxport, &setCmsg) ;
	}
	Permit() ;
	if (! rexxport)
	   goto failure ;
/*
 *   Now we iterate, waiting until we get the correct message.
 */
	waitbits = (1L << rport->mp_SigBit) | (1L << mgport->mp_SigBit) ;
	while (1) {
	   Wait(waitbits) ;
	   mgdisp() ;
	   if (GetMsg(rport)) {
              s = (setCmsg.Result1 ? FALSE : TRUE) ;
              goto sfailure ;
           }
	}
failure:
	s = FALSE ;
sfailure:
/*
 *   Here we clean up by closing down and deleting the ports.
 */
	closemsgs() ;
	pendingrexx = 0 ;
	return(s) ;
}
static char *rline(p)
struct LINE *p ;
{
   p->l_text[p->l_used] = 0 ;
   return(p->l_text) ;
}
static char *rint(i)
short i ;
{
   static char temp[8] ;
   char *p ;

   p = temp + 7 ;
   *p-- = 0 ;
   do {
      *p = ( i % 10 ) + '0' ;
      i = i / 10 ;
      p-- ;
   } while (i != 0) ;
   return(p+1) ;
}
publishline() {
	if (! curbp)
		return(FALSE) ;
	if (! pendingrexx)
		openmsgs() ;
	if (rport == NULL || mgport == NULL) {
		closemsgs() ;
		return(FALSE) ;
	}
	if (curwp->w_dotp) {
		poststring("mg.DotLine", rline(curwp->w_dotp)) ;
		poststring("mg.DotPos", rint(curwp->w_doto)) ;
	} else {
		poststring("mg.DotLine", "") ;
		poststring("mg.DotPos", "") ;
	}
/*	if (curwp->w_markp) {
		poststring("mg.MarkLine", rline(curwp->w_markp)) ;
		poststring("mg.MarkPos", rint(curwp->w_marko)) ;
	} else {
		poststring("mg.MarkLine", "") ;
		poststring("mg.MarkPos", "") ;
	} */
	if (! pendingrexx)
		closemsgs() ;
	return(TRUE) ;
}
extern struct Window *EmW ;
windowfront() {
	if (EmW)
		WindowToFront(EmW) ;
	return(TRUE) ;
}
windowback() {
	if (EmW)
		WindowToBack(EmW) ;
	return(TRUE) ;
}
/*
 *   Bump our priority by 2.  (Editors are important!)
 */
static int oprior ;
bumpprior() {
   struct Task *task ;

   task = FindTask(0L) ;
   oprior = task->tc_Node.ln_Pri ;
   SetTaskPri(task, (long)(2+oprior)) ;
}
unbumpprior() {
   struct Task *task ;

   task = FindTask(0L) ;
   SetTaskPri(task, (long)oprior) ;
}
