/* processstaffname.cpp
 * for Denemo, the GNU graphical frontend to GNU Lilypond
 *
 * (c) 2000-2005 Matthew Hiller */

/* This function accepts a Denemo staff's canonicalized name
 * denemo_name, and sets lily_name to be what the corresponding voice
 * will be called in the mudela representation. Both GString *s should
 * be initialized before this function is called */
/* e.g., "bass voice"->"BassVoice" */

#include <glib.h>
#include <string.h>
#include <stdio.h>

#define ROWS     4
#define COLS     4

static guint pows[ROWS][COLS] = { {1000, 1000, 1000, 1000},
{900, 500, 400, 100},
{90, 50, 40, 10},
{9, 5, 4, 1}
};

static char *roms[ROWS][COLS] = { {"M", "M", "M", "M"},
{"CM", "D", "CD", "C"},
{"XC", "L", "XL", "X"},
{"IX", "V", "IV", "I"}
};
static void
to_roman (guint decimal, GString * lily_name)
{
  guint power;			/* current power of 10 */
  guint indx;			/* indexes through values to subtract */

  for (power = 0; power < ROWS; power++)
    for (indx = 0; indx < COLS; indx++)
      while (decimal >= pows[power][indx])
	{
	  g_string_append (lily_name, roms[power][indx]);
	  decimal -= pows[power][indx];
	}
}

/* make an acceptable lily name from denemo_name: FIXME - check for anything other than alphaword */
void
set_lily_name (GString * denemo_name, GString * lily_name)
{
  guint i;
  gchar c;
  gboolean last_char_was_space = TRUE;

  g_string_assign (lily_name, "");
  for (i = 0; i < denemo_name->len; i++)
    {
      c = denemo_name->str[i];
      if (c == ' ')
	last_char_was_space = TRUE;
      else
	{
	  guint decimal;
	  int numchars;
	  if (c == '0')		/* character 0 that is */
	    g_string_append (lily_name, "O");	/* replace with upper case o */
	  else
	    if ((sscanf (&denemo_name->str[i], "%u%n", &decimal, &numchars))
		== 1)
	    {
	      i += numchars;	/* move over digits that have been converted by sscanf */
	      to_roman (decimal, lily_name);
	    }
	  else
	    {
	      if (last_char_was_space && 'a' <= c && c <= 'z')
		{
		  /* Make the character uppercase */
		  c -= ('a' - 'A');
		}
	      g_string_append_c (lily_name, c);
	      last_char_was_space = FALSE;
	    }

	}
    }
}
void
dnm_set_lily_name (GString *denemo_name, GString * lily_name){
	set_lily_name (denemo_name,lily_name);
}

/* This function accepts a Lilypond voice name lily_name and calculates
 * from it the canonicalized denemo_name. Both Gstring *s should be
 * initialized before this function is called */
/* e.g., "BassVoice"->"bass voice" */

void
set_denemo_name (GString * lily_name, GString * denemo_name)
{
  guint i;
  gchar c;

  g_string_assign (denemo_name, "");
  for (i = 0; i < lily_name->len; i++)
    {
      c = lily_name->str[i];
      if ('A' <= c && c <= 'Z')
	{
	  /* Need to make the character lowercase and insert a space */
	  c += ('a' - 'A');
	  if (i)
	    /* insert a space before it as well */
	    g_string_append_c (denemo_name, ' ');
	}
      g_string_append_c (denemo_name, c);
    }
}

/* This function accepts a gchar *proposal as an argument. If 
 * this proposal can be made into a canonical Denemo staff name,
 * it is stored in denemo_name. If not, denemo_name is left
 * unchanged. It returns -1 if the name could not be canonicalized. */

gint
canonicalize_denemo_name (gchar * proposal, GString * denemo_name)
{
  gchar *accept =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890 ";
  guint i;
  gchar c;
  gboolean last_char_was_space = FALSE;

  //g_strdown (proposal);

  if (strspn (proposal, accept) == strlen (proposal))
    {
      /* Okay; we have only acceptable characters. Let's boogie */
      g_string_assign (denemo_name, proposal);
      for (i = 0; i < denemo_name->len;)
	{
	  c = denemo_name->str[i];
	  if (c == ' ')
	    {
	      if (last_char_was_space)
		g_string_erase (denemo_name, i, 1);
	      else
		{
		  last_char_was_space = TRUE;
		  i++;
		}
	    }
	  else
	    {
	      last_char_was_space = FALSE;
	      i++;
	    }
	}
      return 0;
    }
  return -1;
}
