/* SymbolicDuration.c */
/*****************************************************************************/
/*                                                                           */
/*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
/*    Copyright (C) 1994  Thomas R. Lawrence                                 */
/*                                                                           */
/*    This program is free software; you can redistribute it and/or modify   */
/*    it under the terms of the GNU General Public License as published by   */
/*    the Free Software Foundation; either version 2 of the License, or      */
/*    (at your option) any later version.                                    */
/*                                                                           */
/*    This program is distributed in the hope that it will be useful,        */
/*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
/*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
/*    GNU General Public License for more details.                           */
/*                                                                           */
/*    You should have received a copy of the GNU General Public License      */
/*    along with this program; if not, write to the Free Software            */
/*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
/*                                                                           */
/*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
/*                                                                           */
/*****************************************************************************/

#include "MiscInfo.h"
#include "Audit.h"
#include "Debug.h"
#include "Definitions.h"

#include "SymbolicDuration.h"
#include "DataMunging.h"
#include "NoteObject.h"
#include "Memory.h"
#include "SymbolicIsItInThere.h"


/* convert the duration flags into a heap allocated string */
char*								NumericDurationToString(unsigned long Duration,
											MyBoolean DotFlag, unsigned long Division)
	{
		char*							RootString;
		char*							DotPrefix;
		char*							DivisionSuffix;
		char*							PrefixNoNull;
		char*							ResultingString;

		switch (Duration)
			{
				default:
					EXECUTE(PRERR(ForceAbort,"NumericDurationToString:  bad duration value"));
					break;
				case e64thNote:
					RootString = "64th";
					break;
				case e32ndNote:
					RootString = "32nd";
					break;
				case e16thNote:
					RootString = "16th";
					break;
				case e8thNote:
					RootString = "8th";
					break;
				case e4thNote:
					RootString = "quarter";
					break;
				case e2ndNote:
					RootString = "half";
					break;
				case eWholeNote:
					RootString = "whole";
					break;
				case eDoubleNote:
					RootString = "double";
					break;
				case eQuadNote:
					RootString = "quad";
					break;
			}
		if (DotFlag)
			{
				DotPrefix = "dotted ";
			}
		 else
			{
				DotPrefix = "";
			}
		switch (Division)
			{
				default:
					EXECUTE(PRERR(ForceAbort,"NumericDurationToString:  bad division value"));
					break;
				case eDiv1Modifier:
					DivisionSuffix = "";
					break;
				case eDiv3Modifier:
					DivisionSuffix = " triplet";
					break;
				case eDiv5Modifier:
					DivisionSuffix = " div 5";
					break;
				case eDiv7Modifier:
					DivisionSuffix = " div 7";
					break;
			}

		ResultingString = NIL;

		PrefixNoNull = StringToBlockCopy(DotPrefix);
		if (PrefixNoNull != NIL)
			{
				char*							RootNoNull;

				RootNoNull = StringToBlockCopy(RootString);
				if (RootNoNull != NIL)
					{
						char*							FirstHalf;

						FirstHalf = ConcatBlockCopy(PrefixNoNull,RootNoNull);
						if (FirstHalf != NIL)
							{
								char*							PostfixNoNull;

								PostfixNoNull = StringToBlockCopy(DivisionSuffix);
								if (PostfixNoNull != NIL)
									{
										ResultingString = ConcatBlockCopy(FirstHalf,PostfixNoNull);
										if (ResultingString != NIL)
											{
												SetTag(ResultingString,"NumericDurationToString");
											}
										ReleasePtr(PostfixNoNull);
									}
								ReleasePtr(FirstHalf);
							}
						ReleasePtr(RootNoNull);
					}
				ReleasePtr(PrefixNoNull);
			}

		return ResultingString;
	}


/* obtain duration attributes from the string passed in.  if the duration attribute */
/* can't be determined, then *Duration will remain unchanged */
/* this routine is kinda yucky. */
void								StringToNumericDuration(char* String, unsigned long* Duration,
											MyBoolean* DotFlag, unsigned long* Division)
	{
		CheckPtrExistence(String);
		ERROR((Duration == NIL) || (DotFlag == NIL) || (Division == NIL),PRERR(ForceAbort,
			"StringToNumericDuration:  an output parameter is NIL"));

		/* look for hint of duration */
		if (IsItInThere(String,"64") || IsItInThere(String,"sixty"))
			{
				*Duration = e64thNote;
			}
		else if (IsItInThere(String,"32") || IsItInThere(String,"thirty"))
			{
				*Duration = e32ndNote;
			}
		else if (IsItInThere(String,"16") || IsItInThere(String,"sixteen"))
			{
				*Duration = e16thNote;
			}
		else if (IsItInThere(String,"8") || IsItInThere(String,"eight"))
			{
				*Duration = e8thNote;
			}
		else if (IsItInThere(String,"4th") || IsItInThere(String,"quarter"))
			{
				*Duration = e4thNote;
			}
		else if (IsItInThere(String,"half"))
			{
				*Duration = e2ndNote;
			}
		else if (IsItInThere(String,"whole"))
			{
				*Duration = eWholeNote;
			}
		else if (IsItInThere(String,"double"))
			{
				*Duration = eDoubleNote;
			}
		else if (IsItInThere(String,"quad"))
			{
				*Duration = eQuadNote;
			}
		else
			{
				/* didn't find anything */
			}

		/* look for dot hint */
		if (IsItInThere(String,"dot"))
			{
				*DotFlag = True;
			}
		else
			{
				*DotFlag = False;
			}

		/* look for hint of division */
		if (IsItInThere(String,"div 3") || IsItInThere(String,"trip"))
			{
				*Division = eDiv3Modifier;
			}
		else if (IsItInThere(String,"div 5") || IsItInThere(String,"quint"))
			{
				*Division = eDiv5Modifier;
			}
		else if (IsItInThere(String,"div 7") || IsItInThere(String,"sept"))
			{
				*Division = eDiv7Modifier;
			}
		else
			{
				*Division = eDiv1Modifier;
			}
	}
