/* Output from p2c, the Pascal-to-C translator */
/* From input file "tp_heap1.pas" */


#define TP_HEAP1_G
#include "tp_heap1.h"
/*
#ifndef THINK_C
#include "conio.h"
#endif
*/
#ifdef __TURBOC__
#include "conio.h"
#endif

#include <stdlib.h>
#include <string.h>

/**********************************************************/
boolean Empty(ThisList)
HeapRecord ThisList;
{
  /**********************************************************/
  /* Empty:=ThisList.Tail=nil; */
  /* does not work properly yet, FIX !! */
  return (ThisList.Size == 0);
}


/********************************************************************/
Void InsertOnTop(ThisList, N)
HeapRecord *ThisList;
NoteRecord *N;
{
  /********************************************************************/
  if (ThisList->Tail == NULL) {
    ThisList->Tail = N;
    N->Next = N;
    N->Prev = N;
  } else {
    N->Next = ThisList->Tail->Next;
    N->Prev = ThisList->Tail;
    ThisList->Tail->Next->Prev = N;
    ThisList->Tail->Next = N;
  }
  ThisList->Size++;
}


/**********************************************************/
Void Append(ThisList, N)
HeapRecord *ThisList;
NoteRecord *N;
{
  /**********************************************************/
  if (ThisList->Tail == NULL) {
    ThisList->Tail = N;
    N->Next = N;
    N->Prev = N;
  } else {
    N->Prev = ThisList->Tail;
    N->Next = ThisList->Tail->Next;
    ThisList->Tail->Next->Prev = N;
    ThisList->Tail->Next = N;
    ThisList->Tail = N;
  }
  ThisList->Size++;
}


/*****************************************************************/
Void Insert(ThisList, Nin, N)
HeapRecord *ThisList;
NoteRecord *Nin, *N;
{
  /* inserts N BEFORE Nin !!                                       */
  /*****************************************************************/
  if (ThisList->Tail == NULL) {   /* NoteList is empty */
    InsertOnTop(ThisList, N);
    return;
  }
  /* with */
  if (Nin == ThisList->Tail->Next)
  {   /* N should be inserted in front of the first item in list ...*/
    /* Append(ThisList,N) */
    InsertOnTop(ThisList, N);
    return;
  }
  Nin->Prev->Next = N;
  N->Prev = Nin->Prev;
  Nin->Prev = N;
  N->Next = Nin;
  ThisList->Size++;
}


/**************************************************************/
Void Re_move(ThisList, N)
HeapRecord *ThisList;
NoteRecord *N;
{
  /**************************************************************/
  NoteRecord *P;

  if (ThisList->Tail != NULL) {
    P = ThisList->Tail;   /* pointer to Tail */
    while (P->Next != N && P->Next != ThisList->Tail)
      P = P->Next;
    if (P->Next == N) {
      P->Next = N->Next;
      N->Next->Prev = P;
      if (ThisList->Tail == N) {
	if (P == N)
	  ThisList->Tail = NULL;
	else
	  ThisList->Tail = N->Prev;
      }
    }  /* if */
  }  /* if */
  ThisList->Size--;   /* with */
}


/*****************************************************/
Void FirstNote(ThisList, N)
HeapRecord ThisList;
NoteRecord **N;
{
  /*****************************************************/
  Char c;

  *N = ThisList.Tail->Next;
#ifdef __TURBOC__
  if (!kbhit())
    return;
  c = getch();
  if (c == 'q')
    ErrorExit(17L);
#endif
}


/*****************************************************/
Void LastNote(ThisList, N)
HeapRecord ThisList;
NoteRecord **N;
{
  /*****************************************************/
  Char c;

  *N = ThisList.Tail;
#ifdef __TURBOC__
  if (!kbhit())
    return;
  c = getch();
  if (c == 'q')
    ErrorExit(17L);
#endif
}


/*****************************************************/
Void NextNote(N, P)
NoteRecord *N, **P;
{
  /*****************************************************/
  Char c;

  *P = N->Next;
#ifdef __TURBOC__
  if (!kbhit())
    return;
  c = getch();
  if (c == 'q')
    ErrorExit(17L);
#endif
}


/*****************************************************/
Void PrevNote(N, P)
NoteRecord *N, **P;
{
  /*****************************************************/
  *P = N->Prev;
}


/***************************************************/
Void ResetNoteRec(N)
NoteRecord *N;
{
  /***************************************************/
  memset(N, 0, sizeof(NoteRecord));
}


/*****************************************************/
NoteRecord *GetFreeNote()
{
  /*****************************************************/
  NoteRecord *N;

  if (NotePool.Size <= 0) {
    ErrorExit(10L);
    return N;
  }
  N = NotePool.Tail;
  Re_move(&NotePool, N);
  ResetNoteRec(N);
  return N;
}


/*****************************************************/
Void BringFreeNote(N)
NoteRecord *N;
{
  /*****************************************************/
  Append(&NotePool, N);
}


/*************************************************************/
boolean EqualsNote(NoteRecord *N, uchar ThisNote)
{
  /*************************************************************/
  if (N->NoteVal == ThisNote)
    return true;
  else
    return false;
}


#define POOLSIZE        200


/*************************/
Void InitNotePool()
{
  /*************************/
  NoteRecord *N;

  for (i = 1; i <= POOLSIZE; i++) {
    N = (NoteRecord *)malloc(sizeof(NoteRecord));
    if (N==NULL) ErrorExit(9L);
    Append(&NotePool, N);
  }
}  /* InitNotePool */

#undef POOLSIZE


/*************************/
Void KillNotePool()
{
  /*************************/
  KillList(&NotePool);
}


/*************************/
Void KillNoteLists()
{
  /*************************/
  long I;
  TrackRecord *WITH;

  for (I = 0; I <= 15; I++) {
    WITH = &TrackArray[I];
    if (WITH->NoteList.Tail != NULL)
      KillList(&WITH->NoteList);
    WITH = &TrackArray[I];
    if (WITH->SpillList.Tail != NULL)
      KillList(&WITH->SpillList);
  }
  KillList(&NotePool);
}


/***********************************************/
Void KillList(ThisList)
HeapRecord *ThisList;
{
  /***********************************************/
  NoteRecord *N, *P;

  LastNote(*ThisList, &P);
  while (!Empty(*ThisList)) {
    N = P->Next;
    Re_move(ThisList, N);
/* p2c: tp_heap1.pas, line 263:
 * Warning: Too many arguments for freemem [299] */
    free(N);
  }
}  /* InitNoteHeap */


/***********************************************************/
Char *NoteList2String(Result, ThisList)
Char *Result;
HeapRecord ThisList;
{
  /***********************************************************/
  Char Tmpstr[256], tmp[256];
  NoteRecord *N, *P;

  N = ThisList.Tail->Next;
  P = N;
  *Tmpstr = '\0';
  do {
    switch (N->Event) {

    case NOTEON:
    case NOTEOFF:
      sprintf(tmp, "%d", N->NoteVal);
      sprintf(Tmpstr + strlen(Tmpstr), "%s ", tmp);
      break;

    default:
      strcat(Tmpstr, "n ");
      break;
    }
    NextNote(N, &N);
  } while (N != P);
  strcpy(Result, Tmpstr);
  return Result;
}


/***********************************************************/
Char *ChordNoteList2String(Result, ThisList)
Char *Result;
HeapRecord ThisList;
{
  /***********************************************************/
  Char Tmpstr[256], tmp[256];
  NoteRecord *N, *P;

  N = ThisList.Tail->Next;
  P = N;
  *Tmpstr = '\0';
  do {
    switch (N->Event) {

    case NOTEON:
    case NOTEOFF:
      sprintf(tmp, "%d", N->NoteVal);
      if (N->ChordNote)
	strcat(Tmpstr, "-- ");
      else
	sprintf(Tmpstr + strlen(Tmpstr), "%s ", tmp);
      break;

    default:
      strcat(Tmpstr, "n ");
      break;
    }
    NextNote(N, &N);
  } while (N != P);
  strcpy(Result, Tmpstr);
  return Result;
}


/*************************************************/
Void Exchange(ThisList, N1, N2)
HeapRecord *ThisList;
NoteRecord **N1, **N2;
{
  /*************************************************/
  NoteRecord *P1, *P2, *F;

  F = ThisList->Tail->Next;   /* first item in notelist */
  NextNote(*N1, &P1);
  NextNote(*N2, &P2);
  if (P1 == *N2) {
    if (P2 == *N1) {   /* only two notes in the list */
      NextNote(ThisList->Tail, &ThisList->Tail);
      return;
    }
    Re_move(ThisList, *N2);
    /*If N1=F Then Append(ThisList,N2) Else */
    Insert(ThisList, *N1, *N2);
    Re_move(ThisList, *N1);
    if (P2 == F)
      Append(ThisList, *N1);
    else
      Insert(ThisList, P2, *N1);
    return;
  }
  Re_move(ThisList, *N1);
  /* If N2=F Then Append(ThisList,N1) Else */
  Insert(ThisList, *N2, *N1);
  Re_move(ThisList, *N2);
  if (P1 == F)
    Append(ThisList, *N2);
  else
    Insert(ThisList, P1, *N2);
}  /* exchange */


void _TP_Heap1_init()
{
  HeapRecord *WITH;

  static int _was_initialized = 0;
  if (_was_initialized++)
    return;
  NotePool.Tail = NULL;
  NotePool.Size = 0;
  for (i = 1; i <= 16; i++) {
    WITH = &TrackArray[i - 1].NoteList;
    WITH->Size = 0;
    WITH->Tail = NULL;
    WITH = &TrackArray[i - 1].SpillList;
    WITH->Size = 0;
    WITH->Tail = NULL;
  }
}

/* End. */
