💾 Archived View for runjimmyrunrunyoufuckerrun.com › src › foreign › pmw › src › setnote.c captured on 2021-12-17 at 13:26:06.

View Raw

More Information

-=-=-=-=-=-=-

/*************************************************


/* Copyright (c) Philip Hazel, 1991 - 2020 */

/* Written by Philip Hazel, starting November 1991 */
/* This file last modified: January 2020 */


/* This file contains the main code typesetting one note or chord */


#include "pmwhdr.h"
#include "pagehdr.h"
#include "poshdr.h"
#include "outhdr.h"





/*************************************************


/* For saving beaming state while setting grace notes */

static BOOL save_beaming;

static int save_beam_count;
static int save_beam_firstX;
static int save_beam_firstY;
static int save_beam_seq;
static int save_beam_slope;
static int save_beam_splitOK;
static int save_beam_upflag;
static int save_beam_Xcorrection;




/*************************************************


/* The data for notes is put into global variables so they can easily be shared
between the various functions. Note that chords have been sorted so that the
note nearest the stem comes first. The variables n_prevtie and n_nexttie point
to the incoming and outgoing ties, respectively.

Argument:  pointer to the first note
Returns:   pointer after the last note


bstr *
out_setnote(b_notestr *p)
{
int accleftnum = 0;

DEBUG(("out_setnote() start\n"));

n_lastnote = p;

n_notetype = p->notetype;
n_pitch = p->spitch;
n_length = p->length;

n_acc = n_firstacc = n_lastacc = p->acc;
n_accleft = n_maxaccleft = (p->accleft * main_stavemagn)/1000;
n_flags = n_chordflags = p->flags;
n_acflags = n_chordacflags = p->acflags;

/* Set parameters for a rest. We preserve the stem up flag from the previous
note. This is useful in obscure cases such as tieing over rests. A rest also
kills any outstanding underlay block for underlay extension (but not for
hyphens). */

if (n_pitch == 0)
  {
  ulaystr **uu = &(bar_cont->ulay);
  ulaystr *u = *uu;

  while (u != NULL)
    {
    if (u->type == '=')
      {
      *uu = u->next;
      store_free(u);
      }
    else uu = &(u->next);
    u = *uu;
    }

  n_restlevel = p->yextra;
  n_prevtie = n_nexttie = NULL;
  n_upflag = out_laststemup[out_stave];
  DEBUG(("rest level=%d upflag=%d\n", n_restlevel, n_upflag));
  }

/* Set parameters for a note, and find the number of notes in a chord. This is
needed for tie direction computations, even for single notes. At the same time
we can find the maximum accidental offset for the note/chord. This is also a
convenient place for setting up the next and previous tie pointers. */

else
  {
  b_notestr *tp = p;
  n_chordcount = 1;
  n_stemlength = p->yextra;
  n_upflag = (n_flags & nf_stemup) != 0;
  n_upfactor = n_upflag? (+1):(-1);

  n_invertleft = (!n_upflag && (n_flags & nf_invert) != 0);
  n_invertright = (n_upflag && (n_flags & nf_invert) != 0);

  /* Don't use the couplepitch macro, as want to test the distances. */

  if ((n_flags & (nf_coupleU | nf_coupleD)) != 0)
    {
    if ((n_flags & nf_coupleU) != 0)
      {
      n_pitch += out_upgap - 24;
      if ((out_upgap & 3) != 0) error_111 = TRUE;
      }
    else
      {
      n_pitch += 24 - out_downgap;
      if ((out_downgap & 3) != 0) error_111 = TRUE;
      }
    }

  n_maxpitch = n_minpitch = n_pitch;

  out_notelist[0] = tp;
  mac_advancechord(tp);

  while (tp->type == b_chord)
    {
    int pitch = tp->spitch;
    int accleft = (tp->accleft * main_stavemagn)/1000;
    if (accleft > n_maxaccleft) n_maxaccleft = accleft;
    n_lastacc = tp->acc;

    mac_couplepitch(pitch, tp->flags);
    if (pitch > n_maxpitch) n_maxpitch = pitch;
      else if (pitch < n_minpitch) n_minpitch = pitch;

    if (n_upflag)
      n_invertright |= (tp->flags & nf_invert) != 0;
    else
      n_invertleft |=  (tp->flags & nf_invert) != 0;

    n_chordflags |= tp->flags;
    n_chordacflags |= tp->acflags;

    if (abs(tp->yextra) > abs(n_stemlength)) n_stemlength = tp->yextra;
    out_notelist[n_chordcount++] = tp;
    mac_advancechord(tp);
    }

  n_prevtie = bar_cont->tie;
  bar_cont->tie = NULL;

  if (tp->type == b_tie)
    {
    n_nexttie = (b_tiestr *)tp;
    if (n_upflag) n_nhtied = n_nexttie->belowcount > 0;
      else n_nhtied = n_nexttie->abovecount > 0;
    }
  else
    {
    n_nexttie = NULL;
    n_nhtied = FALSE;
    }

  DEBUG(("note chordcount=%d upflag=%d\n", n_chordcount, n_upflag));
  }

/* Deal with grace notes. If this is the first in a sequence, preserve the
beaming state; after the last, restore it. */

if (n_length == 0)
  {
  posstr *pp;
  if (n_gracecount == 0)
    {
    save_beam_count        = beam_count;
    save_beam_firstX       = beam_firstX;
    save_beam_firstY       = beam_firstY;
    save_beam_seq          = beam_seq;
    save_beam_slope        = beam_slope;
    save_beam_splitOK      = beam_splitOK;
    save_beam_upflag       = beam_upflag;
    save_beam_Xcorrection  = beam_Xcorrection;
    save_beaming = out_beaming;
    out_beaming = FALSE;
    out_gracenotes = TRUE;
    out_grace_fudge = 0;
    }

  /* Set up the font size and the vertical & horizontal corrections */

  if ((n_flags & nf_cuesize) != 0)
    n_fontsize = (curmovt->fontsizes)->fontsize_cuegrace;
  else
    n_fontsize = (curmovt->fontsizes)->fontsize_grace;

  n_cueadjust = 0;
  n_pcorrection = (2*main_stavemagn*(10000 - n_fontsize))/10000;

  n_gracemoff = posx_gracefirst + n_gracecount++;
  n_x = out_findXoffset(out_moff + n_gracemoff);

  /* If there was an accidental on the next note or chord ON ANY STAVE, then
  the grace note position may have been set to the left of this, if there were
  grace notes on that stave too. We must correctly position the grace note on
  THIS stave. If no staves with accidentals had grace notes, then the grace
  note position will be the same as the accidental position, as no space will
  have been left for grace notes. However, if the accidentals are on chords,
  they may be far wider than grace notes. We must check the final grace note's
  position; if it is the same as the accidental's position, allow for one
  accidental's width (5 points). This is all very nasty. */

  if (n_gracecount == 1 && (pp = out_findTentry(out_moff + posx_acc)) != NULL)
    {
    int acc_x = pp->xoff;
    int next_x = out_findXoffset(out_moff);
    int maxaccleft;
    b_notestr *b = misc_nextnote(p, NULL);

    while (b->length == 0) b = misc_nextnote(b, NULL);
    maxaccleft = b->accleft;
    mac_advancechord(b);

    while (b->type == b_chord)
      {
      if (b->accleft > maxaccleft) maxaccleft = b->accleft;
      mac_advancechord(b);
      }

    out_grace_fudge = (next_x - acc_x) - maxaccleft;

    if ((pp-1)->xoff + out_grace_fudge > next_x - curmovt->gracespacing[0])
      out_grace_fudge = next_x - curmovt->gracespacing[0] - (pp-1)->xoff;

    if (out_grace_fudge < 0) out_grace_fudge = 0;
    }

  /* Incorporate any adjustment, and make relative to bar */

  out_Xadjustment += out_grace_fudge;
  n_x += out_barx + out_Xadjustment;
  }

/* Deal with non-grace notes, first restoring beaming state after gracenotes
have been encountered. */

else
  {
  if (n_gracecount)
    {
    beam_count        = save_beam_count;
    beam_firstX       = save_beam_firstX;
    beam_firstY       = save_beam_firstY;
    beam_seq          = save_beam_seq;
    beam_slope        = save_beam_slope;
    beam_splitOK      = save_beam_splitOK;
    beam_upflag       = save_beam_upflag;
    beam_Xcorrection  = save_beam_Xcorrection;
    out_beaming = save_beaming;
    out_gracenotes = FALSE;
    out_grace_fudge = 0;
    }

  /* Sort out the font size and horizontals & vertical corrections for small
  notes. */

  if ((n_flags & nf_cuesize) != 0)
    {
    n_fontsize = (curmovt->fontsizes)->fontsize_cue;
    n_cueadjust = mac_muldiv(3500 - mac_muldiv(3500, n_fontsize, 10000),
        main_stavemagn, 1000);
    n_pcorrection = (2*main_stavemagn*(10000 - n_fontsize))/10000;
    }

  /* Full-sized note */

  else
    {
    n_fontsize = 10000;
    n_pcorrection = n_cueadjust = 0;
    }

  /* Set the horizontal position - centred rests and (semi)breves are a special
  case */

  if ((n_flags & nf_centre) != 0)
    {
    int leftx = 4*main_stavemagn;

    if (out_findTentry(posx_RLright) != NULL)
      leftx += out_barx + out_findXoffset(posx_RLright);
    else if (out_findTentry(posx_timefirst) != NULL)
      leftx += out_barx + out_findXoffset(posx_timefirst);
    else if (out_findTentry(posx_keyfirst) != NULL)
      leftx += out_barx + out_findXoffset(posx_keyfirst);
    else if (out_startlinebar)
      {
      /* Move back to the key signature if no left repeat, else add width of
         repeat */
      leftx = (out_findTentry(posx_RLleft) == NULL)?
        out_barx - PAGE_LEFTBARSPACE : out_barx + 6 * main_stavemagn;
      }
    else leftx = out_lastbarlinex;

    if (out_manyrest == 1)
      {
      n_x = (leftx + out_barlinex)/2 - 3*main_stavemagn;

      /* Adjustments to centred notes to align with centred rest. */

      if (n_pitch != 0)
        {
        n_x -= (((n_notetype == breve)? 12 : (n_notetype == semibreve)?
          13 : 10) * main_stavemagn)/10;
        }

      else if (curmovt->breverests)
        {
        int t = bar_cont->time;
        int d = t & 255;
        int crotchets = 4 * (t >> 16);    /* 4 times multiplier */

        if (d != time_common && d != time_cut)
          crotchets = (crotchets * ((t >> 8) & 255)) / d;

        if (crotchets == 8 || crotchets == 12) n_notetype = breve;
        if (crotchets == 6 || crotchets == 12) n_flags |= nf_dot;
        }
      }

    else if ((n_flags & nf_hidden) == 0)  /* No number if Q-type rests */
      {
      uschar s[12];
      int font = curmovt->font_longrest;
      int size = (((curmovt->fontsizes)->fontsize_restct)*main_stavemagn)/1000;
      int *matrix = (curmovt->fontsizes)->fontmatrix_restct;
      int i = (curmovt->codemultirests && out_manyrest < 9)? out_manyrest : 0;

      n_x = (leftx + out_barlinex -
        mac_muldiv(longrest_widths[i], main_stavemagn, 1000))/2;

      if (matrix != NULL) memcpy(font_transform, matrix, 4*sizeof(int));

      /* Remember the mid-point where the long rest count is output to make
      it easier to draw a suitable sign when the bar is wide or narrow. */

      n_longrestmid = out_Xadjustment + (leftx + out_barlinex)/2;
      sprintf(CS s, "%d", out_manyrest);
      out_string(s, font, size, n_longrestmid -
        (font_stringwidth(s, font, size))/2,
          out_ystave - 18*main_stavemagn - out_Yadjustment, 0);
      font_reset();
      }
    }

  /* The normal, non-centred case. Unless outputting a grace note, search for
  either the first gracenote position, or (if not found) the note itself. */

  else
    {
    if (curmovt->gracestyle != 0 && n_gracecount == 0)
      n_x = out_barx + out_findGoffset(out_moff + posx_gracefirst, out_moff)
        + out_Xadjustment;
    else
      n_x = out_barx + out_findXoffset(out_moff) + out_Xadjustment;
    if (n_pitch == 0) n_x += 1000;   /* rests all need adjusting */
    }

  n_gracecount = n_gracemoff = out_keycount = out_timecount = 0;
  }

/* Compute accidental spacing adjustment factors. If the space between adjacent
notes is large, we stretch a bit. Note that out_lastnotex is set very large and
negative when the preceding object was not a note. */

if (n_maxaccleft > 0)
  {
  int accgap = n_x - out_lastnotex - n_maxaccleft;
  accleftnum = n_maxaccleft;
  if (out_lastnotex > 0 && accgap > 20*main_stavemagn)
     accleftnum = (11*n_maxaccleft)/10;
  n_accleft = (n_accleft * accleftnum)/n_maxaccleft;
  }

/* Remember beginning of plet if necessary */

if (out_plet_x < 0) out_plet_x = n_x;

/* Deal with beamed note. Take care with the messy code for keeping track of
beamed sequences for plets. The variable beam_seq is maintained for this
purpose:

beam_seq = 0  => not in a beamed sequence
          -1  => at start (first note) of plet
           1  => had beamed sequence in plet
           2  => had rest in beamed sequence

We reset 2 back to 1 if another beamed note is encountered. */

if (n_notetype >= quaver)
  {
  /* Deal with non-rests, either outside or inside beams */

  if (n_pitch != 0)
    {
    /* If not beaming, see if this is the start of one, and cause the beam to
    be output if it is. */

    if (!out_beaming && (bar_cont->flags & cf_noteheads) == 0)
      out_beaming = out_setupbeam(p, out_moff + n_gracemoff, FALSE, FALSE);

    /* If beaming, compute the correct stem length and turn the note type into
    a crotchet. Note that the units of n_stemlength are unmagnified; i.e. they
    are relative to the stave. */

    if (out_beaming)
      {
      n_stemlength = (n_upfactor*(beam_firstY + mac_muldiv(beam_slope,
        out_findXoffset(out_moff+n_gracemoff) + out_Xadjustment +
          (75*main_stavemagn)/100 +
            (n_upflag? beam_Xcorrection : 0) -
              beam_firstX, 1000) -
                (n_pitch - 128)*main_stavemagn -
                  (n_upfactor*14*n_fontsize*main_stavemagn)/10000)*1000)/
                    main_stavemagn;

      if (n_upflag != beam_upflag) n_stemlength += curmovt->beamdepth;
      n_notetype = crotchet;

      /* We can handle a beamed note turning into a minim by masquerade,
      but not anything else. */

      if (n_masq == minim) n_notetype = minim;

      /* If beam_splitOK is true, then we can have notes on the other side of
      the beam. In this case there may be additional stem length adjustments to
      make to any note. */

      if (beam_splitOK) n_stemlength += beam_stemadjusts[beam_count] * 1000;
      if (beam_seq != 0) beam_seq = 1;
      }

    /* Not a beamed note */

    else beam_seq = 0;
    }

  /* Deal with rests. We need to check if rests at beam starts are permitted
  and we are not currently in a beam. See if this is the start of a beam, and
  if so, fudge up a note for the beam-handling code to start off with.
  Otherwise, check for masquerading within a beam. */

  else
    {
    if (curmovt->beamendrests && !out_beaming)
      {
      b_notestr *next = misc_nextnote(p, NULL);

      while (next != NULL && next->spitch == 0 && next->notetype >= quaver)
        next = misc_nextnote(next, NULL);

      if (next != NULL && next->notetype >= quaver)
        {
        int save_yextra = p->yextra;
        int pextra = save_yextra/1000;
        int nextra = next->yextra/1000;
        int save_flags = p->flags;
        usint save_acflags = p->acflags;

        p->spitch = next->spitch;       /* pretend it's as for the real note */
        p->yextra = next->yextra;
        p->flags = n_flags = next->flags;
        p->acflags = n_acflags = next->acflags;
        n_upflag = (n_flags & nf_stemup) != 0;
        n_upfactor = n_upflag? (+1):(-1);

        if (n_upflag)
          {
          int tt = ((n_notetype > squaver)? 134 : 130) + pextra;
          int ss = p->spitch;
          if (ss < 122) ss = 122;
          ss += nextra;
          if (ss < tt) p->yextra += (tt - ss)*1000;
          }
        else
          {
          int tt = ((n_notetype > quaver)? 138 : 142) + pextra;
          int ss = p->spitch;
          if (ss > 150) ss = 150;
          ss -= nextra;
          if (ss > tt) p->yextra += (ss - tt)*1000;
          }

        out_beaming = out_setupbeam(p, out_moff + n_gracemoff, FALSE, TRUE);

        p->spitch = 0;
        p->yextra = save_yextra;
        n_flags = p->flags = save_flags;
        n_acflags = p->acflags = save_acflags;
        }
      }

    /* Handle masquerading rests within a beam -- outside a beam they are
    handled with ordinary notes. Any masquerade is allowed. */

    if (out_beaming && n_masq >= 0) n_notetype = n_masq;
    }
  }

/* Maintain beam_seq in the cases of long notes and rests */

else if (n_notetype < quaver) beam_seq = 0;
  else if (beam_seq == -1) beam_seq = 0;
    else if (beam_seq == 1) beam_seq = 2;

/* Remember whether this note was beamed or not */

DEBUG(("beaming=%d beam_seq=%d\n", out_beaming, beam_seq));

n_beamed = out_beaming;

/* If not beaming, compute some automatic stem length adjustments, and alter
the note type if masquerading. */

if (!out_beaming)
  {
  if (n_notetype >= minim)
    {
    int xl = curmovt->tailadjusts[n_notetype];

    if ((n_ornament != NULL && n_ornament->ornament == or_trem3) ||
      (n_upflag && (n_flags & nf_invert) != 0 && n_notetype >= quaver))
        xl += 4000;

    /* The stems of unbeamed, uncoupled notes must reach the centre of the
    stave if pointing that way. */

    if ((n_flags & nf_couple) == 0)
      {
      int minxl = 0;
      if (n_upflag)
        {
        if (n_pitch < P_0L - 2) minxl = (P_0L - 2 - n_pitch)*1000;
        }
      else
        {
        if (n_pitch > P_6L + 2) minxl = (n_pitch - P_6L - 2)*1000;
        }
      if (xl < minxl) xl = minxl;
      }

    n_stemlength += xl;
    }

  /* Deal with masquerade */

  if (n_masq >= 0) n_notetype = n_masq;
  }

/* Remember horizontal information for hairpins if needed. This must be done
for both visible and invisible things. */

if (out_hairpinhalf && bar_cont->hairpin != NULL)
  {
  hairpinstr *h = bar_cont->hairpin;
  b_hairpinstr *hh = h->hairpin;
  h->x += 6*main_stavemagn +
    mac_muldiv(out_barx + out_findXoffset(out_moff + n_length) - h->x -
      6*main_stavemagn, hh->h, 1000);
  out_hairpinhalf = FALSE;
  }

/* Remember data for marks that need to know what notes are under or above
them. We must do this for rests as well as for real notes, but not for
invisible things. */

if ((n_flags & nf_hidden) == 0)
  {
  slurstr *ss = bar_cont->slurs;
  int pt = misc_ybound(FALSE, n_nexttie, TRUE, TRUE);
  int pb = misc_ybound(TRUE, n_nexttie, TRUE, TRUE);

  /* Remember data for slur(s) if first note after start. We don't want any
  accidental on the note to influence the bounding pitch in this case. We must,
  however, use the combined accent flags for computing the bounding pitches.
  (Note: this code is for the true start only - restarts on a new line are
  different, as the accidental then is wanted.) */

  if (out_slurstarted)   /* This flag saves unnecessary work */
    {
    slurstr *s = ss;
    int flagsave = n_flags;
    usint acflagsave = n_acflags;
    n_flags = n_chordflags;
    n_acflags = n_chordacflags;

    while (s != NULL)
      {
      if (s->count == 0 && s->x != 0)
        {
        int flags = (s->slur)->flags;
        int below = (flags & sflag_b) != 0;
        s->moff = out_moff;
        s->x = n_x;

        if (!below &&                     /* Slur above */
            (flags & sflag_l) == 0 &&     /* Not a line (i.e. a slur) */
            (n_flags & nf_stem) != 0 &&   /* Note has a stem */
            n_upflag &&                   /* Stem is up */
            !main_righttoleft)            /* Not right-to-left */
          s->x += 5*main_stavemagn;

        s->lastx = s->x;
        s->y = misc_ybound(below, n_nexttie, FALSE, TRUE);

        /* If the note is beamed, and the slur is on the same side as the beam,
        we need to put in an additional bit of space for clearance. Also, if
        the slur is on the opposite side to the stem, ditto. */

        if (below)
          {
          if (n_upflag || out_beaming) s->y -= 1000;
          }
        else
          {
          if (!n_upflag || out_beaming) s->y += 1000;
          }

        /* Initialize max/min verticals */

        s->maxy = s->miny = s->lasty = s->y;
        }

      s = s->next;
      }

    out_slurstarted = FALSE;
    n_flags = flagsave;
    n_acflags = acflagsave;
    }

  /* Remember data at the start of continued slurs. If this note is not tied
  onwards, take note of an incoming tie. */

  if (out_moff == 0 && out_startlinebar && !out_passedreset)
    {
    slurstr *s = ss;
    int ptt, pbb;

    if (n_nexttie == NULL && n_prevtie != NULL)
      {
      ptt = misc_ybound(FALSE, n_prevtie, TRUE, TRUE);
      pbb = misc_ybound(TRUE, n_prevtie, TRUE, TRUE);
      }
    else { ptt = pt; pbb = pb; }

    while (s != NULL)
      {
      if (s->x == 0)
        {
        int below = ((s->slur)->flags & sflag_b) != 0;
        int pbbb = pbb;
        int pttt = ptt;

        if (below)
          {
          if (n_upflag || out_beaming) pbbb -= 1000;
          }
        else
          {
          if (!n_upflag || out_beaming) pttt += 1000;
          }

        s->lastx = n_x;
        s->y = s->lasty = s->maxy = s->miny = (below)? pbbb : pttt;
        }

      s = s->next;
      }
    }

  /* Remember data for slurs */

  while (ss != NULL)
    {
    BOOL below = ((ss->slur)->flags & sflag_b) != 0;

    /* Compute slope from start and current slope (for use at the end). Skip if
    at same x offset, which can happen after a reset. */

    if (ss->count != 0)              /* first time is different */
      {
      int xx = n_x - ss->lastx;
      if (xx > 0)
        ss->sloperight = mac_muldiv((below? pb : pt) - ss->lasty, 1000, xx);

      xx = n_x - ss->x;
      if (xx > 0)
        {
        int t = mac_muldiv((below? pb : pt) - ss->y, 1000, xx);

        if (below)
          {
          if (t < ss->slopeleft) ss->slopeleft = t;
          }
        else
          if (t > ss->slopeleft) ss->slopeleft = t;
        }

      /* Keep max/min y value -- note: we don't obey this for the first note as
      they have been set already, ignoring any accidental on the first note. We
      don't actually want to include the final note in here, so we actually
      operate one note behind here. */

      if (below)
        {
        if (ss->lasty < ss->miny) ss->miny = ss->lasty;
        }
      else
        {
        if (ss->lasty > ss->maxy) ss->maxy = ss->lasty;
        }

      /* Keep the last pitch and x position, for slope calculation */

      ss->lastx = n_x;
      ss->lasty = below? pb : pt;
      }

    /* Count notes under the slur and advance to next */

    ss->count++;
    ss = ss->next;
    }

  /* Remember data for plet */

  if (out_plet != NULL)
    {
    if (pt > out_plet_highest) out_plet_highest = pt;
    if (pb < out_plet_lowest) out_plet_lowest = pb;
    if (n_pitch > out_plet_highest_head) out_plet_highest_head = n_pitch;
    }

  /* Remember vertical data for hairpin */

  if (bar_cont->hairpin != NULL)
    {
    hairpinstr *h = bar_cont->hairpin;
    if (pt > h->maxy) h->maxy = pt;
    if (pb < h->miny) h->miny = pb;
    }

  /* Remember data for numbered repeat bars; a non-scaled value is required. */

  if (bar_cont->nbar != NULL)
    {
    nbarstr *b = bar_cont->nbar;
    if (pt > b->maxy) b->maxy = pt;
    }
  }

/* Output all saved up text that was waiting to find out about this
note/chord's pitch and accents, etc. We clear the above/below counts
afterwards, for the benefit of end-of-bar text. They are initially cleared at
the start of a bar. */

  {
  int i;
  int save_flags = n_flags;
  usint save_acflags = n_acflags;
  n_flags = n_chordflags;
  n_acflags = n_chordacflags;
  for (i = 0; i < out_textqueueptr; i++)
    {
    out_textX = out_textXqueue[i];
    out_text(out_textqueue[i], FALSE);
    }
  out_textqueueptr = out_textnextabove = out_textnextbelow = 0;
  out_textX = NULL;
  n_flags = save_flags;
  n_acflags = save_acflags;
  }

/* Output any draw items that were waiting likewise */

if (out_drawqueueptr > 0)
  {
  int i;
  draw_ox = n_x + n_cueadjust;  /* Set origin */
  draw_oy = 0;
  for (i = 0; i < out_drawqueueptr; i++)
    {
    b_drawstr *d = out_drawqueue[i];
    out_dodraw(d->item, d->args, d->overflag);
    }
  out_drawqueueptr = 0;
  }

/* Now we can reset the adjustment; it is left till after text and draw
output. */

out_Xadjustment = 0;
out_Yadjustment = 0;

/* Set the note or rest, first setting up the stemlength that will be used for
all accents etc. in a chord. */

n_orig_stemlength = n_stemlength;
out_shownote();
out_lastnotex = n_x;

/* Print tremolo bars if required. Note that the x-values required by ps_beam()
are relative to the bar start. Ignore if inside a beam, and if this note is a
rest. (The first can't be a rest if we have got this far.) We make use of the
beam drawing routine. */

if (out_tremolo != NULL)
  {
  if (!out_beaming && n_pitch != 0)
    {
    int i, y;
    int x0 = out_tremx - out_barx + (75*main_stavemagn)/100;
    int x1 = n_x - out_barx + (115*main_stavemagn)/100;

    beam_Xcorrection = (51*main_stavemagn)/10;

    if (n_notetype < minim)
      {
      beam_upflag = out_tremupflag = FALSE;
      out_tremolo->join = 0;     /* Force no join */
      x0 += beam_Xcorrection;
      }
    else beam_upflag = n_upflag;

    y = misc_ybound(!beam_upflag, NULL, FALSE, FALSE);

    beam_firstY = out_tremy;

    if (beam_upflag)
      {
      if (out_tremupflag)
        {
        x0 += beam_Xcorrection;
        beam_firstY -= 3*main_stavemagn;
        }
      else beam_firstY += 2*main_stavemagn;
      x1 += beam_Xcorrection;
      y -= 3*main_stavemagn;
      }
    else  /* !beam_upflag */
      {
      if (out_tremupflag)
        {
        x0 += beam_Xcorrection;
        y -= main_stavemagn;
        beam_firstY -= 4*main_stavemagn;
        }
      y += 3*main_stavemagn;
      beam_firstY += 3*main_stavemagn;
      }

    beam_firstX = x0;
    beam_slope = mac_muldiv(y - beam_firstY, 1000, x1 - x0);

    /* Now draw the beams. At the end of the joined ones, shorten the x values.
    If the right-hand note is a semibreve (no stem) and has accidentals,
    shorten even further. */

    for (i = 0; i < out_tremolo->count; i++)
      {
      if (i == out_tremolo->join)
        {
        int xx = (n_x - out_tremx)/5;
        x0 += xx;
        x1 -= xx;
        if ((n_flags & nf_stem) == 0) x1 -= n_accleft;
        }

      ps_beam(x0, x1, i, 0);
      }
    }

  out_tremolo = NULL;
  }

/* Clear ornament before printing the rest of a chord */

n_ornament = NULL;

/*** Finished with single note ***/


/* Deal with the remaining notes of a chord. Save and re-instate the note flags
for the main note, if they are printed on the stem side, because these contain
data about accents which is relevant to slurs that end on the note. */

if (n_chordcount > 1)
  {
  int lastpitch = n_pitch;
  usint n_orig_acflags = n_acflags;
  b_notestr *tp = p;

  mac_advancechord(tp);

  while (tp->type == b_chord)
    {
    n_pitch = tp->spitch;
    n_flags = tp->flags & ~nf_appogg;     /* No slashes on inside chord notes */
    n_acflags = tp->acflags;
    n_acc = tp->acc;
    n_accleft = (tp->accleft*main_stavemagn)/1000;

    mac_couplepitch(n_pitch, n_flags);
    n_stemlength = (abs(n_pitch - lastpitch) - (14*n_fontsize)/10000) * 1000;
    if (n_stemlength < n_orig_stemlength) n_stemlength = n_orig_stemlength;

    if (n_accleft) n_accleft = (n_accleft * accleftnum)/n_maxaccleft;
    n_notetype = (n_masq >= 0)? n_masq : tp->notetype;
    if (n_notetype >= quaver) n_notetype = crotchet;
    if ((bar_cont->flags & cf_notes) != 0) out_shownote();

    p = tp;               /* p must be left pointing to last note */
    mac_advancechord(tp);
    lastpitch = n_pitch;
    }

  n_stemlength = n_orig_stemlength;  /* restore for slur etc. calculations */

  /* Restore first accents if printed on stem side, else leave last ones */

  if ((n_orig_acflags & af_opposite) != 0) n_acflags = n_orig_acflags;
  }

/* Output a tie or glissando that ends on this note or chord */

if (n_prevtie != NULL)
  {
  int flags = n_prevtie->flags;
  if ((flags & (tief_slur|tief_default)) != 0)
    {
    b_notestr *prevnote = n_prevtie->note;
    mac_advancechord(prevnote);
    if (n_chordcount == 1 && prevnote->type != b_chord)
      out_setnotetie(n_x, FALSE, flags);
    else
      out_setchordtie(out_notelist, n_chordcount, n_x, FALSE, flags);
    }
  if ((flags & tief_gliss) != 0 && n_chordcount == 1) out_glissando(n_x, flags);
  }

/* Cancel the dot adjustment unless a tie follows */

if (n_nexttie == NULL) n_dotxadjust = 0;

/* Cancel masquerade and update last stem flag */

n_masq = -1;
out_laststemup[out_stave] = n_upflag;

/* Reset beaming flag if beam completed. Reset the beaming adjustments so as to
ignore directives that appear in the middle of beams. This is relevant when
beams may be split over a line end; adjustments at the start of the second bar
are ignored unless it is at the start of a line. */

if ((out_lastnotebeamed = out_beaming) == TRUE && --beam_count <= 0)
  {
  out_beaming = beam_continued = FALSE;
  beam_forceslope = BIGNUMBER;
  beam_offsetadjust = 0;
  }

/* Advance musical offset */

out_lastmoff = out_moff;
out_moff += n_length;
DEBUG(("out_setnote() end\n"));
return (bstr *)p;                   /* Pointer to last note of chord */
}

/* End of setnote.c */