/*
 *  FILE: subtinit.c
 *  Support routines for spawning subtasks (not processes).
 *  This means the subtask shares the same memory space as its parent task.
 *
 *  Note: this "library" is re-entrant, so any task can spawn and keep track
 *  of its own subtasks independantly of other users of this "library".
 *
 *  Public Domain, but keep my name in it as the original author.
 *  31-Oct-88	Jan Sven Trabandt   split from subtask.c
 */


#define I_AM_SUBTINIT
#include "gimmelib/gimmefuncs.h"
#define GIM_BUILTIN
#include "gimmelib/macros.h"


short initSubTasker( countptr, portptr )
    SHORT	    *countptr;
    struct MsgPort  **portptr;
{
    if( countptr ) {
	*countptr = 0;
    }
    if( portptr ) {
	*portptr = CreatePort( NULL, 0L );
	if( !*portptr ) {
	    return( -1 );
	}
    }
    return( 0 );
} /* initSubTasker */


short doneSubTasker( countptr, portptr )
    SHORT	    *countptr;
    struct MsgPort  **portptr;
{
    struct MsgPort  *myport;

    if( countptr && *countptr ) {
	return( -1 );
    }
    if( portptr && (myport = *portptr) ) {
	*portptr = NULL;
	DeletePort( myport );
    }
    return( 0 );
} /* doneSubTasker */


/****************************************************************/
/* routines to handle printing messages from subtasks to Output()

extern struct Message *gimmeMessage();

struct print_msg {
    struct Message msg;
    ULONG flags;
    UBYTE buf[164];
};
typedef struct print_msg PRINTMSG;

#define PRINTMSG_FLAG	218572L


short doPrintf( port, replyport, s, p1, p2, p3, p4 )
    struct MsgPort  *port, *replyport;
    UBYTE	    *s;
    LONG	    p1, p2;
    double	    p3, p4;
{
    PRINTMSG	*pmsg;

    if( !port || !s ) {
	return( -1 );
    }
    pmsg = (PRINTMSG *) gimmeMessage( (ULONG)sizeof(PRINTMSG), replyport );
    if( !pmsg ) {
	return( -1 );
    }
    pmsg->flags = PRINTMSG_FLAG;
    sprintf( pmsg->buf, s, p1, p2, p3, p4 );
    PutMsg( port, pmsg );
    if( replyport ) {
	WaitPort( replyport );
	pmsg = (PRINTMSG *) GetMsg( port );
/***
	if( pmsg->msg.mn_Node.ln_Type != NT_REPLYMSG
	     || pmsg->flags != PRINTMSG_FLAG ) {
	}
***/
	getRidOfMessage( pmsg );
    } /* endif */
    return( 0 );
} /* doPrintf */


SHORT handleSpecialSubTaskMsg( countptr, portptr )
    SHORT	    *countptr;
    struct MsgPort  **portptr;
{
    PRINTMSG	*msg;
    SHORT	died = 0;

    if( !portptr || !*portptr ) {
	return( died );
    }
    while( msg = (PRINTMSG *) GetMsg(*portptr) ) {
	if( msg->flags == PRINTMSG_FLAG ) {
	    if( Output() ) {
		Forbid();
		Write( Output(), msg->buf, (ULONG)strlen(msg->buf) );
		Permit();
	    }
	    if( !msg->msg.mn_ReplyPort ) {
		getRidOfMessage( msg );
	    } else {
		ReplyMsg( msg );
	    }
	} else {	/* otherwise its a DONEMSG (see subtask.c) */
	    ReplyMsg( msg );
	    ++died;
	} /* endif */
    } /* while */
    return( died );
} /* handleSpecialSubTaskMsg */
