/*
 * 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 that create, delete, and performs
 * operations on lists of projects.
 */

#include "mandp.h"

extern LONG MainPri, TaskPri;

#define LT_PICTLIST 0xff
#define LT_ZOOMLIST 0xfe

struct List pList = {
  (struct Node *) &pList.lh_Tail,
  (struct Node *) NULL,
  (struct Node *) &pList.lh_Head,
  LT_PICTLIST
};

union PictNode {
  struct Node    *Node;
  struct Picture *Pict;
};

struct Picture *
NewPict( Type )
  UBYTE Type;
{
  register union PictNode ln;
  register struct List *Head;

  extern struct NewWindow NewMand;

  ln.Pict = (struct Picture *)
            safeAllocMem( (long) sizeof(struct Picture), (long) MEMF_CLEAR);

  if (ln.Pict == NULL)
    return( ln.Pict );

  ln.Node->ln_Type = Type;
  ln.Node->ln_Name = ln.Pict->Title;

#if 0
  strcpy( ln.Pict->Title, "* ");
#endif

  if ( Type == MANDPICT ) {

    InitMand( ln.Pict );
  }

  ln.Pict->NewWind = &NewMand;

  ln.Pict->TopEdge = 12;

  if ( pList.lh_Head->ln_Succ == NULL ) {

    ToggleEnableds();
  }

  AddHead( &pList, ln.Node );

  ln.Pict->gSigBit = -1;

  Head = &ln.Pict->zList;

  Head->lh_Head     = (struct Node *) &Head->lh_Tail;
  Head->lh_TailPred = (struct Node *) &Head->lh_Head;
  Head->lh_Type     = LT_ZOOMLIST;

  ln.Pict->WindowSemi.ss_Link.ln_Name = NULL;
  ln.Pict->WindowSemi.ss_Link.ln_Pri  = 0;

  AddSemaphore( &ln.Pict->WindowSemi );

  return( ln.Pict );
}

/* Dale Luck's Add Semaphore code */

myAddSemaphore( ss )
  struct SignalSempahore *ss;
{
  extern struct ExecBase *SysBase;

  InitSemaphore(ss);
  Forbid();
  Enqueue(&SysBase->SemaphoreList, ss);
  Permit();
}


DisposePict( NPict )
  register struct Picture *NPict;
{
  Remove( &NPict->pNode );

  RemSemaphore( &NPict->WindowSemi );

  if (NPict == CurPict)
    CurPict = NULL;

  FreeMem( (char *) NPict, (long) sizeof( struct Picture ) );

  if ( pList.lh_Head->ln_Succ == NULL ) {

    ToggleEnableds();
  }
}

GetCurPict( )
{
  register struct Picture *NewPict;

  if ( pList.lh_Head->ln_Succ ) {

    NewPict = (struct Picture *) pList.lh_Head;

    MakeCurProj( NewPict );

  } else {

    CurPict = NULL;
  }
}

ThrowPicts()
{
  register union PictNode ln;
  register union PictNode lnt;

  ln.Node = pList.lh_Head;

  while ( ln.Node->ln_Succ ) {

    lnt.Node = ln.Node;
    ln.Node = ln.Node->ln_Succ;
    ThrowPict( lnt.Pict );
  }
}

ThrowPict( Pict )
  register struct Picture *Pict;
{
  ThrowTask( Pict );

  KillReColor( Pict );

  FreeCounts( Pict );

  FreeHist( Pict->Hist );
  Pict->Hist = NULL;

  ClosePicture( Pict );
  DisposePict( Pict );
}

ReColorPicts()
{
  register union PictNode ln;

  ln.Node = pList.lh_Head;

  while ( ln.Node->ln_Succ ) {

    ReColor( ln.Pict );
    ln.Node = ln.Node->ln_Succ;
  }
}

CheckNewScreen( ViewModes )
  USHORT ViewModes;
{
  register union PictNode ln;

  struct NewScreen MaybeScreen;
  register struct NewScreen *ns;

  ns = &MaybeScreen;

  ns->ViewModes = ViewModes;

  NewScreenSize( ns );

  ln.Node = pList.lh_Head;

  while ( ln.Node->ln_Succ ) {

    if (ln.Pict->Window && ( ln.Pict->Window->Width  > ns->Width  ||
                             ln.Pict->Window->Height > ns->Height))
      return( UNSUCCESSFUL );

    ln.Node = ln.Node->ln_Succ;
  }
  return( SUCCESSFUL );
}

ReOpenPicts()
{
  register union PictNode ln;
  register union PictNode temp_ln;

  extern struct NewWindow NewMand;

  ln.Node = pList.lh_Head;

  while ( ln.Node->ln_Succ ) {

    ReleaseSemaphore( &ln.Pict->WindowSemi );

    if ( OpenPicture( ln.Pict ) != 0 ) {

      temp_ln.Node = ln.Node;

      ln.Node = ln.Node->ln_Succ;

      ThrowPict( temp_ln.Pict );

    } else {
      if ( ln.Pict->Counts && ! (ln.Pict->Flags & NO_RAM_GENERATE) ) {
        ReColor( ln.Pict );
      }

      AwakenChild( ln.Pict );

      if ( ln.Pict->GenState == GENPENDSTATE ) {
        Generate( ln.Pict );
      }

      ln.Node = ln.Node->ln_Succ;
    }
  }
  ServiceTasks();
}

ClosePicts()
{
  register union PictNode ln;

  ln.Node = pList.lh_Head;

  while ( ln.Node->ln_Succ ) {

    if ( ln.Pict->cTask ) {

      KillReColor( ln.Pict );
    }



    ObtainSemaphore( &ln.Pict->WindowSemi );

    ClosePicture( ln.Pict );

    ln.Node = ln.Node->ln_Succ;
  }
}

ServiceTasks()
{
  register union PictNode ln;

  ln.Node = pList.lh_Head;

  while ( ln.Node->ln_Succ ) {

    switch( ln.Pict->GenChildState ) {

      case NOSIGSTATE:
      case GENCOMPLETE:

           KillDoneChild( ln.Pict );
           SetGenGad( ln.Pict );
           ln.Pict->gTask = NULL;
           PrintTime( ln.Pict );
           break;
    }

    if ( ln.Pict->ColorChildState == RECOLORCOMPLETE ) {
      KillReColor( ln.Pict );
      AwakenChild( ln.Pict );
    }

    ln.Node = ln.Node->ln_Succ;
  }
}

PrintTime( Pict )
 register struct Picture *Pict;
{
 LONG t2[3];
 LONG *t1,t;

 if (FromWB)
   return;

 return;

 DateStamp(t2);

 t1 = Pict->TimeStamp;

 t = ((t2[0]-t1[0]) * 1440 + t2[1] - t1[1]) * 3000 + t2[2] - t1[2] ;

 printf("time is %ld.%ld seconds\n",t/50,2*(t%50));
}

ReColorLine( Pict )
  register struct Picture *Pict;
{
  register struct RastPort *Rp;
  register UBYTE *ColorXLate;
  register SHORT *LinePtr;
  register LONG   Top;
  register LONG   Width;
  register struct Window   *Window;

  LONG i;

  (void) SetTaskPri( Pict->gTask, MainPri );

  ObtainSemaphore( &Pict->WindowSemi );

  Top     = Pict->CurLine;
  Width   = Pict->CountX;
  Window  = Pict->Window;

  if ( Window ) {

    ColorXLate = Pict->ClrXlate;

    if ( Pict->Flags & NO_RAM_GENERATE ) {

      LinePtr = Pict->Counts;
    } else {
      LinePtr = Pict->Counts + Top * Width;
    }

    Top   += Pict->TopMarg;
    Width += Pict->LeftMarg;

    Rp = Window->RPort;

    for (i = Pict->LeftMarg; i < Width; i++) {

      SetAPen( Rp, (long) *(ColorXLate + *LinePtr++) );

      if ( i < Window->Width - Pict->RightMarg )
        WritePixel( Rp, i, Top );
    }
  }

  ReleaseSemaphore( &Pict->WindowSemi );

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