/* drawkey.cpp
 *
 * Function for drawing the key signature
 *
 * for Denemo, a gtk+ frontend to GNU Lilypond
 * (c) 1999-2005  Matthew Hiller, Adam Tee
 */

#include "accwidths.h"
#include "drawingprims.h"
#include "utils.h"

#define SPACE_BETWEEN_ACCS 8
#define m * HALF_LINE_SPACE

/**
 * This function draws the key, if desired, and returns the width required
 * to draw it number describes the number of the new key, prevnumber the number of
 * the preceding key 
 */

gint
draw_key (cairo_t *cr, gint xx, gint y,
	  gint number, gint prevnumber, gint dclef, gboolean wetrun, keysig *keysig)
{
  /* These are just hard-coded offsets in pixels from the top of the staff.
   * mid_c_offset arrays. There's probably
   * a better way to do this, but I haven't thought of it */
  static gint treble_flat_ys[7] = { 4 m, 1 m, 5 m, 2 m, 6 m, 3 m, 7 m };
  static gint treble_sharp_ys[7] = { 0, 3 m, -1 m, 2 m, 5 m, 1 m, 4 m };
  static gint bass_flat_ys[7] = { 6 m, 3 m, 7 m, 4 m, 8 m, 5 m, 9 m };
  static gint bass_sharp_ys[7] = { 2 m, 5 m, 1 m, 4 m, 7 m, 3 m, 6 m };
  static gint alto_flat_ys[7] = { 5 m, 2 m, 6 m, 3 m, 7 m, 4 m, 8 m };
  static gint alto_sharp_ys[7] = { 1 m, 4 m, 0, 3 m, 6 m, 2 m, 5 m };
  static gint tenor_flat_ys[7] = { 2 m, 0, 4 m, 1 m, 5 m, 2 m, 6 m };
  static gint tenor_sharp_ys[7] = { -1 m, 2 m, 5 m, 1 m, 4 m, 0 m, 3 m };
  static gint soprano_flat_ys[7] = { 2 m, 6 m, 3 m, 7 m, 4 m, 8 m, 5 m };
  static gint soprano_sharp_ys[7] = { 5 m, 8 m, 4 m, 7 m, 3 m, 6 m, 2 m };

  gint *theys = 0;
  gint *theprevys = 0;
  gint i;
  gint startindex, endindex;
  gint origx = xx;
  
  gboolean override = FALSE;
  if(wetrun && keysig->directives) {
    gint count=0;
    GList *g=keysig->directives;
    for(;g;g=g->next, count++) {
      DenemoDirective* directive = g->data;
      override = override || directive->override;
      if(directive->display) { 
        drawnormaltext_cr( cr, directive->display->str, xx + directive->tx, y+count*10 );
      }
      if(directive->graphic) {
        drawbitmapinverse_cr (cr, directive->graphic,
			   xx+directive->gx+count,  y+directive->gy, FALSE);
      }
    }
  }
  if(!override) { 
  /* first, set the arrays we're using to something useful */
  if (wetrun)
    {
      switch (dclef)
	{
	case DENEMO_TREBLE_CLEF:
	case DENEMO_G_8_CLEF:
	  theprevys = (prevnumber < 0) ? treble_flat_ys : treble_sharp_ys;
	  theys = (number < 0) ? treble_flat_ys : treble_sharp_ys;
	  break;
	case DENEMO_BASS_CLEF:
	case DENEMO_F_8_CLEF:
	case DENEMO_FRENCH_CLEF:
	  theprevys = (prevnumber < 0) ? bass_flat_ys : bass_sharp_ys;
	  theys = (number < 0) ? bass_flat_ys : bass_sharp_ys;
	  break;
	case DENEMO_ALTO_CLEF:
	  theprevys = (prevnumber < 0) ? alto_flat_ys : alto_sharp_ys;
	  theys = (number < 0) ? alto_flat_ys : alto_sharp_ys;
	  break;

	case DENEMO_TENOR_CLEF:
	  theprevys = (prevnumber < 0) ? tenor_flat_ys : tenor_sharp_ys;
	  theys = (number < 0) ? tenor_flat_ys : tenor_sharp_ys;
	  break;
	case DENEMO_SOPRANO_CLEF:
	  theprevys = (prevnumber < 0) ? soprano_flat_ys : soprano_sharp_ys;
	  theys = (number < 0) ? soprano_flat_ys : soprano_sharp_ys;
	  break;
	default:
	  /* Silently default to the treble stuff. Fix me. */
	  theprevys = (prevnumber < 0) ? treble_flat_ys : treble_sharp_ys;
	  theys = (number < 0) ? treble_flat_ys : treble_sharp_ys;
	  break;
	}
    }

  /* First, check to see if we ought to draw naturals. */
  if (prevnumber < 0)
    {
      /* Draw as many accidentals as we need. */
      if (number < 0)
	startindex = -number;
      else
	startindex = 0;
      endindex = -prevnumber;
      /* Note that the loop will immediately exit if number <= prevnumber */
      for (i = startindex; i < endindex; i++, xx += NATURAL_WIDTH + 2)
	{
	  if (wetrun)
	    draw_accidental (cr, xx, y + theprevys[i], 0);
	}
    }
  else if (prevnumber > 0)
    {
      /* Analogous to above */
      if (number > 0)
	startindex = number;
      else
	startindex = 0;
      for (i = startindex; i < prevnumber; i++, xx += NATURAL_WIDTH + 2)
	{
	  if (wetrun)
	    draw_accidental (cr, xx, y + theprevys[i], 0);
	}
    }

  /* Now draw the new indicators themselves */
  if (number < 0)
    {
      number = -number;
      for (i = 0; i < number; i++, xx += FLAT_WIDTH + 2)
	if (wetrun)
	  draw_accidental (cr, xx, y + theys[i], -1);
    }
  else
    for (i = 0; i < number; i++, xx += SHARP_WIDTH + 2)
      if (wetrun)
	draw_accidental (cr, xx, y + theys[i], 1);
  }
  return xx - origx;
}
