/*
 * MandelVroom 2.0
 *
 * (c) Copyright 1987,1989  Kevin L. Clague, San Jose, CA
 *
 * All rights reserved.
 *
 * Permission is hereby granted to distribute this program's source
 * executable, and documentation for non-comercial purposes, so long as the
 * copyright notices are not removed from the sources, executable or
 * documentation.  This program may not be distributed for a profit without
 * the express written consent of the author Kevin L. Clague.
 *
 * This program is not in the public domain.
 *
 * Fred Fish is expressly granted permission to distribute this program's
 * source and executable as part of the "Fred Fish freely redistributable
 * Amiga software library."
 *
 * Permission is expressly granted for this program and it's source to be
 * distributed as part of the Amicus Amiga software disks, and the
 * First Amiga User Group's Hot Mix disks.
 *
 * contents: this file contains functions used to manage tasks used by
 * MandelVroom for picture generation and picture recoloring.
 */

#include "mandp.h"

LONG MainPri =  0;
LONG TaskPri = -1;

LONG pSigMask, pSigBit;

PauseChild( Pict )
  register struct Picture *Pict;
{
  if (Pict->gTask) {

    if (Pict->GenState == GENERATESTATE) {

      SetTaskPri( Pict->gTask, MainPri );

      Pict->GenState = PAUSESTATE;

      Wait( pSigMask );

      SetTaskPri( Pict->gTask, TaskPri );
    }
  }
}

ChildSignal( Pict )
  register struct Picture *Pict;
{
#ifdef MULTI
  if ( Pict->GenState == PAUSESTATE ) {
    Signal( mTask, pSigMask );
    Wait( Pict->gSigMask );
  }
#endif
}

AwakenChild( Pict )
  register struct Picture *Pict;
{
  if (Pict->gTask) {
    if (Pict->GenState == PAUSESTATE) {

      Pict->GenState = GENERATESTATE;

      Signal( Pict->gTask, Pict->gSigMask );

      if (Pict->gTask->tc_State == TS_WAIT) {
        printf("Child still waiting\n");
      }
    }
  }
}

CheckEOL( Pict )
  register struct Picture *Pict;
{
  ChildPause( Pict );

  ReColorLine( Pict );

  Pict->CurLine++;
}

KillDoneChild( Pict )
  register struct Picture *Pict;
{
  if (Pict->gTask) {

    SetTaskPri( Pict->gTask, MainPri );

    Pict->GenState = KILLSTATE;   /* Child is spinning waiting for this */
    Wait( pSigMask );      /* wait till child says it notices this */

    DeleteTask(Pict->gTask);
    Pict->gTask = NULL;
  }
}

GetTaskSig( Pict )
  register struct Picture *Pict;
{
  register LONG bit;

  Pict->gSigBit = bit = AllocSignal( (long) -1 );

  if ( bit == -1 )
    return( UNSUCCESSFUL );

  Pict->gSigMask = 1 << bit;

  return( SUCCESSFUL );
}

int
OpenTasks()
{
  mTask = FindTask( NULL );

  mSigBit = AllocSignal( (long) -1 );

  if ( mSigBit == -1 ) {
    return (-1);
  }

  mSigMask = 1 << mSigBit;

  pSigBit = AllocSignal( (long) -1 );

  if ( pSigBit == -1 ) {

    FreeSignal( mSigBit );
    return (-1);
  }

  pSigMask = 1 << pSigBit;

  return( 0 );
}

CloseTasks()
{
  FreeSignal( mSigBit );
  FreeSignal( pSigBit );
}

/* This is called by main task */

ThrowTask( Pict )
  register struct Picture *Pict;
{
  register struct Task *gTask = Pict->gTask;

  if (gTask) {

    PauseChild( Pict );
    DeleteTask( gTask );
    Pict->gTask = NULL;

    SetGenGad( Pict );
  }
}

CloseZoomedPicts( Pict )
  register struct Picture *Pict;
{
  register struct Node    *zNode;
  register struct Picture *ZoomPict;

  struct Picture *PictAddr();

  zNode = Pict->zList.lh_Head;

  while ( zNode = RemHead( &Pict->zList ) ) {

    ZoomPict = PictAddr( zNode );

    CloseZoomBox(ZoomPict);
  }
}

/* Calculate pointer to the beginning of Picture struct */

struct Picture *
PictAddr( zNodeAddr )
  register struct Node *zNodeAddr;
{
  register char *ZoomPict;

  ZoomPict = (char *) zNodeAddr;

  ZoomPict -= ((char *) &CurPict->zNode - (char *) &CurPict->pNode);

  return( (struct Picture *) ZoomPict );
}

PauseReColor( Pict )
  register struct Picture *Pict;
{
  if (Pict->gTask) {

    if (Pict->ColorState == GENERATESTATE) {

      Pict->ColorState = PAUSESTATE;

      (void) Wait( pSigMask );
    }
  }
}

ReColorPause( Pict )
  register struct Picture *Pict;
{
  if ( Pict->ColorState == PAUSESTATE ) {

    Signal( mTask, pSigMask );
    (void) Wait( 0L );
  }
}
