/* drawnotes.cpp
 *
 * Functions for drawing notes and rests
 *
 * for Denemo, a gtk+ frontend to GNU Lilypond
 * (c) 1999, 2000, 2001, 2002 Matthew Hiller, Adam Tee
 */

#include "utils.h"		/* Includes <gdk.h> */
#include "drawingprims.h"
#include "notewidths.h"
#include "gcs.h"
#include <math.h>


gint restwidths[SMALLESTDURATION + 1] =
  { WHOLEREST_WIDTH, HALFREST_WIDTH, QUARTERREST_WIDTH, EIGHTHREST_WIDTH,
  SIXTEENTHREST_WIDTH, THIRTYSECONDREST_WIDTH, SIXTYFOURTHREST_WIDTH, HUNDREDTWENTYEIGHTHREST_WIDTH, TWOHUNDREDFIFTYSIXTHREST_WIDTH
};
gint headwidths[3] = { WHOLEHEAD_WIDTH, HALFHEAD_WIDTH, NOTEHEAD_WIDTH
};

/**
 * draw_dots
 * This draws dots after rests or notes 
 *
 */
static void
draw_dots (cairo_t *cr,
	   gint xstart, gint ystart, gint numdots)
{
  gint thinrecty = ystart - 2, shortrecty = ystart - 1;

  xstart += 4;
  for (; numdots; numdots--, xstart += 6)
    {
      cairo_arc( cr, xstart, ystart, 1.5, 0.0, 2*M_PI );
      cairo_fill( cr );
    }
}

/**
 * draw_rest
 * This function actually draws a rest onto the backing pixmap 
 *
 */
void
draw_rest (cairo_t *cr,
	   gint duration, gint numdots, gint xx, gint y)
{
  static gint restoffsets[SMALLESTDURATION + 1] =
    { WHOLEREST_OFFSETFROMTOP, HALFREST_OFFSETFROMTOP,
    QUARTERREST_OFFSETFROMTOP, EIGHTHREST_OFFSETFROMTOP,
    SIXTEENTHREST_OFFSETFROMTOP, THIRTYSECONDREST_OFFSETFROMTOP,
    SIXTYFOURTHREST_OFFSETFROMTOP,
    HUNDREDTWENTYEIGHTHREST_OFFSETFROMTOP,
    TWOHUNDREDFIFTYSIXTHREST_OFFSETFROMTOP
  };

  static gunichar rest_char[SMALLESTDURATION + 1] =
    { 0x20, 0x21, 0x27, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e
  };

  drawfetachar_cr (cr, rest_char[duration],
		     xx, y + restoffsets[duration]);
  /* Now draw any trailing dots and we're done */

  draw_dots (cr, xx + restwidths[duration],
	     y + restoffsets[duration]  - HALF_LINE_SPACE, numdots);
}

/**
 *  draw_notehead
 *  This function actually draws the note onto the backing pixmap 
 *
 */
void
draw_notehead (cairo_t *cr,
	       note * thenote, gint duration, gint numdots,
	       gint xx, gint y, gint * accs, gint is_stemup)
{
  /* Adam's changed this code; it used to be that these arrays only had
     three elements.  The change has defeated what had been semi-elegance;
     grrr.  */

  static gint headwidths[6] = { WHOLEHEAD_WIDTH, HALFHEAD_WIDTH,
    NOTEHEAD_WIDTH, DIAMOND_WIDTH,
    CROSS_WIDTH, HARMONIC_WIDTH,
  };

  static gunichar head_char[6] =
    { 0x54, 0x55, 0x56, 0x58, 0x64, 0x92
  };
  gint height = thenote->y;
  gint noteheadtype = 1;
  gint enshift = thenote->enshift;
  gint pitch = offsettonumber (thenote->mid_c_offset);

  if (thenote->noteheadtype == DENEMO_NORMAL_NOTEHEAD)
    {
      noteheadtype = MIN (duration, 2);	/* Index of relevant notehead */
    }
  else if (thenote->noteheadtype == DENEMO_CROSS_NOTEHEAD)
    {
      noteheadtype = 4;		/* Index of relevant notehead */
    }
  else if (thenote->noteheadtype == DENEMO_HARMONIC_NOTEHEAD)
    {
      noteheadtype = 5;
    }
  else if (thenote->noteheadtype == DENEMO_DIAMOND_NOTEHEAD)
    {
      noteheadtype = 3;
    }


  /* Draw the accidental, if necessary.  Note that this has to be
     done before xx is modified, as the the value in
     position_of_accidental already accounts for any reverse-alignment
     in the chord.  */
  if (thenote->showaccidental)
    {
      draw_accidental (cr, xx - thenote->position_of_accidental,
		       y + height, enshift);
      accs[pitch] = enshift;
    }

  if (thenote->reversealign) {
    if (is_stemup)
      xx += headwidths[noteheadtype];
    else
      xx -= headwidths[noteheadtype];
  }
  if(!(get_override(thenote->directives)&DENEMO_OVERRIDE_GRAPHIC)) {
    if (is_stemup)
      drawfetachar_cr ( cr, head_char[noteheadtype], xx, y + height);
    else
      drawfetachar_cr ( cr, head_char[noteheadtype], xx-0.5, y + height);
    /* Now draw any trailing dots */
    if ((height % LINE_SPACE) == 0)
      draw_dots (cr, xx + headwidths[noteheadtype],
		 y + height - HALF_LINE_SPACE, numdots);
    else
      draw_dots (cr, xx + headwidths[noteheadtype],
		 y + height, numdots);
  }
  
  /* any display for attached LilyPond */
 { GList *g = thenote->directives;
 GString *gstr=g_string_new("");
 gint count=10;
  for(;g;g=g->next, count+=10) {
    DenemoDirective *directive = (DenemoDirective *)g->data;
    if(directive->graphic) {
      gint width, height;
      gdk_drawable_get_size(GDK_DRAWABLE(directive->graphic), &width, &height);
      drawbitmapinverse_cr ( cr, (GdkBitmap *)directive->graphic,
			 xx+directive->gx+count,  y+thenote->y+directive->gy/*thechord.highesty*/, width, height);

    }
    if(directive->display) {
      drawnormaltext_cr (cr, directive->display->str, xx+directive->tx+count, y+thenote->y+directive->ty ); 
    }
  }
 }
}

/**
 * Draw the legder lines on the score
 *
 */
void
draw_ledgers (cairo_t *cr,
	      gint greaterheight, gint lesserheight,
	      gint xx, gint y, gint width)
{
  int ledgerheight;

#define EXTRA_ON_LEDGER 3

  cairo_set_line_width( cr, 1.0 );
  /* Draw the top ledger lines */
  for (ledgerheight = -LINE_SPACE; ledgerheight >= greaterheight;
       ledgerheight -= LINE_SPACE)
  {
    cairo_move_to( cr, xx - EXTRA_ON_LEDGER, ledgerheight + y );
    cairo_line_to( cr, xx + width + EXTRA_ON_LEDGER, ledgerheight + y );
  }

  /* Almost identically, draw the bottom ones */
  for (ledgerheight = STAFF_HEIGHT + LINE_SPACE;
       ledgerheight <= lesserheight; ledgerheight += LINE_SPACE)
  {
    cairo_move_to( cr, xx - EXTRA_ON_LEDGER, ledgerheight + y );
    cairo_line_to( cr, xx + width + EXTRA_ON_LEDGER, ledgerheight + y );
  }

  cairo_stroke( cr );
}

/**
 * Draw the chord object on the score
 *
 */
void
draw_chord ( cairo_t *cr, objnode * curobj, gint xx, gint y,
	    gint mwidth, gint * accs, gboolean selected)
{

  static gunichar upstem_char[SMALLESTDURATION + 1] =
    { 0, 0, 0, 0xb9, 0xba,
      0xbb,
      0xbc,
      0xbd,
      0xbd
  };

  static gunichar downstem_char[SMALLESTDURATION + 1] =
    { 0, 0, 0, 0xbe, 0xc1,
      0xc2,
      0xc3,
      0xc4,
      0xc4
  };

  DenemoObject *prevmuditem =
    (DenemoObject *) (curobj->prev ? curobj->prev->data : NULL);
  DenemoObject *mudelaitem = (DenemoObject *) curobj->data;
  DenemoObject *nextmuditem =
    (DenemoObject *) (curobj->next ? curobj->next->data : NULL);
  chord thechord = *(chord *) mudelaitem->object;
  gint duration = thechord.baseduration;
  gint noteheadtype = MIN (duration, 2);

  /* Change those two so that they're cached instead */
  gint i;
  gint beampainty, arcwidth;

  gint prevbaseduration, nextbaseduration;
  GList *curnode;
  gboolean is_grace = thechord.is_grace && thechord.notes;

  cairo_save(cr);
  cairo_set_line_width( cr, 1.0 );

  if(is_grace) {
    note *thenote = (note *) thechord.notes->data;
    cairo_translate( cr, xx, y+thenote->y);
    cairo_scale( cr, 0.8, 0.8);
    cairo_translate( cr, -xx, -(y+thenote->y));
  }

  if (mudelaitem->isinvisible) {
    if (selected)
      cairo_set_source_rgb( cr, 231.0/255 , 1, 39.0/255 ); 
    else
      cairo_set_source_rgb( cr, 180.0/255, 160.0/255, 32.0/255 );// yellow for non printing
  }


  if (!thechord.notes/* a rest */) {
     if( !(get_override(thechord.directives)&DENEMO_OVERRIDE_GRAPHIC))
       draw_rest (cr, duration, thechord.numdots, xx, y);  
  }  else {
    /* Draw the noteheads and accidentals */
    
    for (curnode = thechord.notes; curnode; curnode = curnode->next){
      note *thenote = (note *)curnode->data;

      draw_notehead (cr, thenote, duration,
		     thechord.numdots, xx, y, accs, thechord.is_stemup);

    }
    /* Now the stem and beams. This is complicated. */
    
    if (thechord.is_stemup)
      {
	if (mudelaitem->isstart_beamgroup && mudelaitem->isend_beamgroup)
	  {
	    if (duration >= 3)
	      /* Up-pointing stem pixmap */
	      drawfetachar_cr (cr, upstem_char[duration],
				 xx + NOTEHEAD_WIDTH,
				 thechord.highesty + y + 3
				 - (duration == 6 ? EXTRA_STEM_HEIGHT
				    : STEM_HEIGHT));
	  }
	else if (nextmuditem && !mudelaitem->isend_beamgroup)
	  {
	    /* Draw the thin beam across the gap */
	    cairo_rectangle (cr,
				xx + headwidths[noteheadtype] - 1,
				y + thechord.stemy,
				nextmuditem->x - mudelaitem->x,
				THINBEAM_HEIGHT);
	    cairo_fill(cr);
	    if (mudelaitem->isstart_beamgroup || !prevmuditem)
	      prevbaseduration = 0;
	    else
	      prevbaseduration =
		((chord *) prevmuditem->object)->baseduration;
	    nextbaseduration =
	      ((chord *) nextmuditem->object)->baseduration;
	    for (i = 4, beampainty = thechord.stemy + FIRSTBEAMSPACE;
		 i <= thechord.baseduration;
		 i++, beampainty += SUBSQBEAMSPACE)
	      {
		if (nextbaseduration >= i) {
		  /* Draw a thick beam across the gap */
		  cairo_rectangle (cr,
				      xx + headwidths[noteheadtype] - 1,
				      y + beampainty,
				      nextmuditem->x - mudelaitem->x,
				      THICKBEAM_HEIGHT);
		  cairo_fill(cr);

		} else if (prevbaseduration < i) {
		  /* Draw a stub to the right of the staff */
		  cairo_rectangle (cr,
				      xx + headwidths[noteheadtype] - 1,
				      y + beampainty, STUB_WIDTH,
				      THICKBEAM_HEIGHT);
		  cairo_fill( cr );
		}
	      }		/* end for loop */
	  }			/* end drawing for non-end-beamgroup notes */
	else
	  {			/* We're at the end of a beamgroup */
	    if (prevmuditem)
	      for (i = MAX (((chord *) prevmuditem->object)->baseduration + 1,
			    4),
		     beampainty = thechord.stemy + FIRSTBEAMSPACE +
		     (SUBSQBEAMSPACE * (i - 4));
		   i <= thechord.baseduration;
		   i++, beampainty += SUBSQBEAMSPACE)
		{
		  /* Draw a stub to the left of the staff */
		  cairo_rectangle (cr,
				      xx + headwidths[noteheadtype] - 1 -
				      STUB_WIDTH, y + beampainty, STUB_WIDTH,
				      THICKBEAM_HEIGHT);
		  cairo_fill(cr);
		}
	  }
	
	if (duration > 0) {
	  /* Vertical line */
	  cairo_move_to( cr, xx + headwidths[noteheadtype], thechord.stemy + y );
	  cairo_line_to( cr, xx + headwidths[noteheadtype], thechord.lowesty + y - 2 );
	  cairo_stroke( cr );
	}

	
	/* Now draw the tie, if appropriate */
	if (thechord.is_tied)
	  {
	    if (nextmuditem)
	      arcwidth = nextmuditem->x - mudelaitem->x;
	    else
	      arcwidth = mwidth - mudelaitem->x + SPACE_FOR_BARLINE;

	    cairo_set_line_width( cr, 1.0 );
	    cairo_move_to( cr, xx + headwidths[noteheadtype] / 2, y + thechord.highesty - 13 );
	    cairo_rel_curve_to( cr, arcwidth/3, -8, arcwidth*2/3, -8, arcwidth, 0 );
	    cairo_stroke( cr );
	  }
      }			/* End stemup stuff */
    else
      {			/* chord is stemdown */
	if (mudelaitem->isstart_beamgroup && mudelaitem->isend_beamgroup)
	  {
	    if (duration >= 3)
	      /* Down-pointing stem */
	      drawfetachar_cr (cr, downstem_char[duration],
				 xx,
				 thechord.lowesty + y 
				 + (duration == 6 ? EXTRA_STEM_HEIGHT
				    : STEM_HEIGHT)
				 );
	  }
	else if ((nextmuditem) && !mudelaitem->isend_beamgroup)
	  {
	    /* Draw the thin beam across the gap */
	    cairo_rectangle( cr, xx, y + thechord.stemy - THINBEAM_HEIGHT + 1,
			     nextmuditem->x - mudelaitem->x,
			     THINBEAM_HEIGHT);
	    cairo_fill( cr );

	    if (mudelaitem->isstart_beamgroup || !prevmuditem)
	      prevbaseduration = 0;
	    else
	      prevbaseduration =
		((chord *) prevmuditem->object)->baseduration;
	    
	    nextbaseduration =
	      ((chord *) nextmuditem->object)->baseduration;
	    for (i = 4, beampainty =
		   thechord.stemy - FIRSTBEAMSPACE - THICKBEAM_HEIGHT + 1;
		 i <= thechord.baseduration;
		 i++, beampainty -= SUBSQBEAMSPACE)
	      {
		if (nextbaseduration >= i) {
		  /* Draw a thick beam across the gap */
		  cairo_rectangle( cr, xx, y + beampainty,
		      nextmuditem->x - mudelaitem->x,
		      THICKBEAM_HEIGHT);
		  cairo_fill( cr );

		} else if (prevbaseduration < i) {
		  /* Draw a stub to the right of the staff */
		  cairo_rectangle (cr, xx, y + beampainty,
				      STUB_WIDTH, THICKBEAM_HEIGHT);
		  cairo_fill(cr);
		}
	      }		/* End for loop */
	  }			/* End drawing for non-end-beamgroup notes */
	else
	  {			/* We're at the end of a beamgroup */
	    if(prevmuditem)//sanity check
	    for (i = MAX (((chord *) prevmuditem->object)->baseduration,
			  4),
		   beampainty = thechord.stemy - FIRSTBEAMSPACE - 
		   THICKBEAM_HEIGHT + 1 -
		   (SUBSQBEAMSPACE * (i - 4));
		 i <= thechord.baseduration;
		 i++, beampainty -= SUBSQBEAMSPACE)
	      {
		/* Draw a stub to the left of the staff */
		cairo_rectangle (cr, xx - STUB_WIDTH,
				    y + beampainty, STUB_WIDTH,
				    THICKBEAM_HEIGHT);
		cairo_fill(cr);
	      }
	  }
	
	if (duration > 0) {
	  /* Vertical line */
	  cairo_move_to( cr, xx, thechord.highesty + y + 2 );
	  cairo_line_to( cr, xx, thechord.stemy + y );
	  cairo_stroke( cr );
	}
	/* Now draw the tie, if appropriate */
	if (thechord.is_tied)
	  {
	    if (nextmuditem)
	      arcwidth = nextmuditem->x - mudelaitem->x;
	    else
	      arcwidth = mwidth - mudelaitem->x + SPACE_FOR_BARLINE;
	    cairo_set_line_width( cr, 1.0 );
	    cairo_move_to( cr, xx + headwidths[noteheadtype] / 2, y + thechord.highesty - 13 );
	    cairo_rel_curve_to( cr, arcwidth/3, -8, arcwidth*2/3, -8, arcwidth, 0 );
	    cairo_stroke( cr );
	  }
      }
    /* End stemdown stuff */
    
    draw_articulations (cr, thechord, xx, y); 
    if(is_grace) cairo_restore(cr);
    draw_ledgers (cr, thechord.highesty, thechord.lowesty, xx, y,
		  headwidths[noteheadtype]);
    if(is_grace) cairo_save(cr);
    
  }				/* end else if there are notes in the chord*/
  { GList *g = thechord.directives;
  gint count = 0;
  for(;g;g=g->next) {
    DenemoDirective *directive = (DenemoDirective *)g->data;
    if(directive->graphic) {
      gint width, height;
      gdk_drawable_get_size(GDK_DRAWABLE(directive->graphic), &width, &height);
      drawbitmapinverse_cr (cr, (GdkBitmap*)directive->graphic,
			 xx+directive->gx, y+directive->gy, width, height);
    }
    if(directive->display) {
      drawnormaltext_cr (cr, directive->display->str, xx+directive->tx, y+STAFF_HEIGHT+40+count+directive->ty );
      count += 16;
    }
  } //for each chord directive
  }//block displaying chord directives
  cairo_restore (cr);
}



/**
 * Draw the articulations on the score
 *
 */
void
draw_articulations (cairo_t * cr,
		    chord thechord, gint xx, gint y)
{

  static gunichar options_char[25] = { 0x81, 0x82, 0x8a, 0x8a, 0x8c, 0x8f, 0x8d, 0x8e,
	                               0x92, 0x93, 0xa1, 0x9f, 0x94, 0xaf, 0xae, 0xac, 
				       0x98, 0xa0, 0x8a, 0x95, 0x89, 0xab, 0xa8, 0xb0,
				       0xa7 };

  static gunichar noteoptions_char[3] = { 0x9a, 0x99, 0xad };
  static gunichar strings_char[2] = { 0x97, 0x96 };
  static gunichar organ_char[4] = { 0x9b, 0x9c, 0x9d, 0x9e };

  /* extra y position for staccato, accent, tenuto, fermata when stacked */
  gint extra = 0;
  GList *tmp;

  /* Fermata, Accents, Staccato, tenuto stuff.  */

  /* The following code ought to see some serious reorganization.
     (It's another chunk of code that uses arrays in a situation
     where arrays aren't elegant -- rather, they're just confusing.
     And how 'bout some nesting of these if statements?)  */

  /* Calculate the offset required when stacking symbols */
  extra = calc_offset (thechord, thechord.is_stemup);

  /* These rely on notehead position and stem-ends 
   * Usually are above the stave except tenuto and 
   * staccato
   */
  for (tmp = thechord.ornamentlist; tmp; tmp = tmp->next)
    {
#ifdef DEBUG
      g_print ("ornament %d\n", *(enum ornament *) (tmp->data));
#endif
      if (*(enum ornament *) tmp->data == (enum ornament) STACCATO)
	drawfetachar_cr (cr, options_char[4],
			   xx + NOTEHEAD_WIDTH / 2,
			   y + extra);
      if (*(enum ornament *) tmp->data == (enum ornament) TENUTO)
	drawfetachar_cr (cr,
			   options_char[5], xx,
			   y + extra);
      if (*(enum ornament *) tmp->data == (enum ornament) STACCATISSIMO)
	drawfetachar_cr (cr, options_char[6],
			   xx + NOTEHEAD_WIDTH / 2,
			   y + extra);

      if (*(enum ornament *) tmp->data == (enum ornament) D_ACCENT)
	drawfetachar_cr (cr, options_char[2],
			   xx + 2, y + extra);

      else if (*(enum ornament *) tmp->data == (enum ornament) MARCATO)
	drawfetachar_cr (cr, options_char[8],
			   xx + 2, y + extra);


      /* 
       * Always should appear above the note(s) they
       * effect.
       */
      if (*(enum ornament *) tmp->data == (enum ornament) FERMATA)
	drawfetachar_cr (cr,
			   options_char[0], xx - FERMATA_WIDTH / 4,
			   y + extra);
      if (*(enum ornament *) tmp->data == (enum ornament) CODA)
	drawfetachar_cr (cr,
			   options_char[10], xx - CODA_WIDTH / 4,
			   y + extra);
      if (*(enum ornament *) tmp->data == (enum ornament) TRILL)
	drawfetachar_cr (cr,
			   noteoptions_char[0], xx - TRILL_WIDTH / 4,
			   y + extra);

      else if (*(enum ornament *) tmp->data == (enum ornament) TURN)
	drawfetachar_cr (cr,
			   noteoptions_char[1], xx - TURN_WIDTH / 4,
			   y + extra);

      else if (*(enum ornament *) tmp->data == (enum ornament) MORDENT)
	drawfetachar_cr (cr,
			   noteoptions_char[2], xx - MORDENT_WIDTH / 4,
			   y + extra);

      if (*(enum ornament *) tmp->data == (enum ornament) DBOW)
	drawfetachar_cr (cr,
			   strings_char[0], xx, y + extra);
      else if (*(enum ornament *) tmp->data == (enum ornament) UBOW)
	drawfetachar_cr (cr,
			   strings_char[1], xx, y + extra);

      if (*(enum ornament *) tmp->data == (enum ornament) RHEEL)
	{
	  drawfetachar_cr (cr,
			     organ_char[1], xx, y + extra);
	}
      else if (*(enum ornament *) tmp->data == (enum ornament) LHEEL)
	{
	  drawfetachar_cr (cr,
			     organ_char[0], xx, y + extra);
	}

      if (*(enum ornament *) tmp->data == (enum ornament) RTOE)
	{
	  drawfetachar_cr (cr,
			     organ_char[3], xx, y + extra);
	}
      else if (*(enum ornament *) tmp->data == (enum ornament) LTOE)
	{
	  drawfetachar_cr (cr,
			     organ_char[2], xx, y + extra);
	}
      if (*(enum ornament *) tmp->data == (enum ornament) D_ARPEGGIO)
	drawfetachar_cr (cr,
			   options_char[24], xx, y + extra);

      if (*(enum ornament *) tmp->data == (enum ornament) UPPRALL)
	drawfetachar_cr (cr, options_char[23],
			   xx, y + extra);

      if (*(enum ornament *) tmp->data == (enum ornament) FLAGEOLET)
	drawfetachar_cr (cr, options_char[11],
			   xx, y + extra);
      if (*(enum ornament *) tmp->data == (enum ornament) OPEN)
	drawfetachar_cr (cr, options_char[12],
			   xx, y + extra);
      if (*(enum ornament *) tmp->data == (enum ornament) PRALLMORDENT)
	drawfetachar_cr (cr, options_char[13],
			   xx, y + extra);
      if (*(enum ornament *) tmp->data == (enum ornament) PRALLPRALL)
	drawfetachar_cr (cr, options_char[14],
			   xx, y + extra);
      if (*(enum ornament *) tmp->data == (enum ornament) PRALL)
	drawfetachar_cr (cr, options_char[15],
			   xx, y + extra);
      if (*(enum ornament *) tmp->data == (enum ornament) REVERSETURN)
	drawfetachar_cr (cr, options_char[16],
			   xx, y + extra);
      if (*(enum ornament *) tmp->data == (enum ornament) SEGNO)
	drawfetachar_cr (cr, options_char[17],
			   xx, y + extra);
      if (*(enum ornament *) tmp->data == (enum ornament) SFORZATO)
	drawfetachar_cr (cr, options_char[18],
			   xx, y + extra);
      if (*(enum ornament *) tmp->data == (enum ornament) STOPPED)
	drawfetachar_cr (cr, options_char[19],
			   xx, y + extra);
      if (*(enum ornament *) tmp->data == (enum ornament) THUMB)
	drawfetachar_cr (cr, options_char[20],
			   xx, y + extra);
      if (*(enum ornament *) tmp->data == (enum ornament) TRILLELEMENT)
	drawfetachar_cr (cr, options_char[21],
			   xx, y + extra);
      if (*(enum ornament *) tmp->data == (enum ornament) TRILL_ELEMENT)
	drawfetachar_cr (cr, options_char[22],
			   xx, y + extra);

    }				//end for loop

}

/** 
 * Calculate the offset required for the given ornament
 *
 */
gint
calc_offset (chord thechord, gint stemdir)
{
  gint offset = 0;
  GList *tmp;

  for (tmp = thechord.ornamentlist; tmp; tmp = tmp->next)
    {
      if (*(enum ornament *) tmp->data == (enum ornament) FERMATA ||
	  *(enum ornament *) tmp->data == (enum ornament) TURN ||
	  *(enum ornament *) tmp->data == (enum ornament) TRILL ||
	  *(enum ornament *) tmp->data == (enum ornament) MORDENT)
	offset = -LINE_SPACE - 7;
      else if (( *(enum ornament *) tmp->data == (enum ornament) STACCATO ||
	         *(enum ornament *) tmp->data == (enum ornament) TENUTO      )
	         && stemdir)
	offset = thechord.lowesty + 10;
      else if (*(enum ornament *) tmp->data == (enum ornament) STACCATO ||
	       *(enum ornament *) tmp->data == (enum ornament) TENUTO)
	offset = thechord.highesty - 10;
      else if (*(enum ornament *) tmp->data == (enum ornament) D_ACCENT
	       && stemdir)
	offset = thechord.lowesty + 10;
      else if (*(enum ornament *) tmp->data == (enum ornament) MARCATO ||
	       *(enum ornament *) tmp->data == (enum ornament) D_ACCENT)
	offset = -thechord.highesty - 6;
    }

  return offset;
}
