/*************************************************
*    The PMW Music Typesetter - 3rd incarnation  *
*************************************************/

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

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


/* This file contains part V of the code for reading in a PMW score file - code
for reading one note. */


#include "pmwhdr.h"
#include "readhdr.h"


#define ornset_trill    1
#define ornset_trem     2
#define ornset_mordturn 4


/* This table is used to convert from an accidental-less note in absolute units
to a stave-relative note. Only "white" notes are ever used to index into this
table. */

static uschar pitch_stave[] = {
   4, 0,  6, 0,  8, 10, 0, 12, 0, 14, 0, 16,
  18, 0, 20, 0, 22, 24, 0, 26, 0, 28, 0, 30,
  32, 0, 34, 0, 36, 38, 0, 40, 0, 42, 0, 44,
  46, 0, 48, 0, 50, 52, 0, 54, 0, 56, 0, 58,
  60, 0, 62, 0, 64, 66, 0, 68, 0, 70, 0, 72,
  74, 0, 76, 0, 78, 80, 0, 82, 0, 84, 0, 86,
  88, 0, 90, 0, 92, 94, 0, 96, 0, 98, 0,100,
 102, 0,104, 0,106,108, 0,110, 0,112, 0,114,
 116, 0,118, 0,120,122, 0,124, 0,126, 0,128 };

/* This table is used to convert a pitch obtained fom the above table into a
pitch relative to a stave, where 128 is the bottom line on the stave. This
table is for "real" clefs only. */

static uschar pitch_clef[] = { 64, 68, 72, 76, 80, 84, 84, 88, 92 };
                            /* Tr  S   M   A   Te  cBa Ba  B   DB */

/* These tables give the extra "accidental left" amounts for accidentals in
brackets */
                          /* -    ##    $     $$    %     # */
static int rbra_left[] = { 5800, 5800, 5300, 5300, 5800, 6800 };
static int sbra_left[] = { 5800, 6800, 6300, 6300, 6800, 6800 };

/* Static variables used for communication between read_note() and post_note() */

static int maxpitch, minpitch, chordcount;
static int notetype, length, stemforce;
static BOOL seconds;
static tiedata this_tiedata[MAX_CHORDSIZE];

/* This variable is set true when the only notes in a bar so far are notated
using "p" and "x" and are tied to their predecessors. It is used to determine
whether a following "p" or "x" should have its accidentals printed or not. */

static BOOL onlytieddup;

/* Used for copying ornaments for 'x' notes */

static b_ornamentstr *last_note_ornament;


/*************************************************
*     Read pitch for [printpitch]                *
*************************************************/

/* This function reads a stave-relative pitch for use by the [printpitch]
directive. It is placed here because it uses the tables in this module. The
character is already current on entry.

Arguments:  none
Returns:    the pitch
*/

int
read_stavepitch(void)
{
int pitch;
read_ch = tolower(read_ch);
if ('a' > read_ch || read_ch > 'g')
  {
  error_moan(ERR10, "Note letter");
  return 128;
  }
pitch = stave_octave + 36 + read_basicpitch[read_ch - 'a'];
next_ch();
while (read_ch == '\'') { pitch += 12; next_ch(); }
while (read_ch == '`' ) { pitch -= 12; next_ch(); }
return pitch_stave[pitch] + pitch_clef[stave_clef];
}


/*************************************************
*  Read optional move (or bracket) for ornament  *
*************************************************/

/* This is also used for dynamics.

Arguments:
  ax        address of the x movement, or NULL if not allowed
  ay        address of the y movement
  af        address of the bflags field, or NULL if not allowed

Returns:    nothing
*/

static void
ornmove(int *ax, int *ay, uschar *af)
{
*ay = 0;
if (ax != NULL) *ax = 0;
if (af != NULL) *af = 0;
while (read_ch == '/')
  {
  next_ch();
  switch (read_ch)
    {
    case 'u': *ay += read_movevalue(); break;
    case 'd': *ay -= read_movevalue(); break;

    case 'l':
    case 'r':
    if (ax == NULL)
      error_moan(ERR10, "/u or /d");
    else
      *ax += ((read_ch == 'r')?(+1):(-1)) * read_movevalue();
    break;

    default:
    if (af == NULL)
      error_moan(ERR10, "/u, /d, /l, or /r");
    else switch (read_ch)
      {
      case 'b': *af &= ~(DO_SBRA|DO_SKET); *af |= DO_RBRA | DO_RKET; break;
      case 'B': *af &= ~(DO_RBRA|DO_RKET); *af |= DO_SBRA | DO_SKET; break;
      case '(': *af &= ~DO_SBRA; *af |= DO_RBRA; break;
      case '[': *af &= ~DO_RBRA; *af |= DO_SBRA; break;
      case ')': *af &= ~DO_SKET; *af |= DO_RKET; break;
      case ']': *af &= ~DO_RKET; *af |= DO_SKET; break;

      default:
      error_moan(ERR10, "/u, /d, /l, /r, /b, /B, /(, /), /[, or /]");
      break;
      }
    if (read_ch != '\\') next_ch();  /* \ means there was an error */
    break;
    }
  }
}


/*************************************************
*    Read optional move or bracket for dynamic   *
*************************************************/

/* This function inserts a dynmove item into the data list.

Argument:   the dynamic
Returns:    nothing
*/

static void
dynmove(int dynamic)
{
b_dynmovestr *d;
if (read_ch != '/') return;
d = store_getitem(b_dynmove);
d->dynamic = dynamic;
ornmove(&(d->x), &(d->y), &(d->bflags));
}


/*************************************************
*        Output underlay text for one note       *
*************************************************/

/* This function processes underlay strings that have been saved up, inserting
an appropriate b_text item into the data, with text(s) for one note.

Arguments:  none
Returns:    nothing
*/

static void
do_underlay(void)
{
ulaypend **pp = &stave_pendulay;
ulaypend *p = stave_pendulay;

/* Loop for each "verse" */

while (p != NULL)
  {
  int endfont;
  uschar *s = p->string;
  b_textstr *q;

  if (p->halfway != 0 || p->offset != 0)
    {
    b_textXstr *xx = store_getitem(b_textX);
    xx->rotate = 0;
    xx->halfway = p->halfway;
    xx->offset = p->offset;
    p->halfway = 0;
    p->offset = 0;
    }

  q = store_getitem(b_text);
  q->font = endfont = p->font;
  q->size = p->size;
  q->htype = p->htype;
  q->ulevel = p->level;

  q->flags = p->flags;
  q->string = s;
  q->x = p->x;
  q->y = p->y;

  /* If we are at an equals sign, just output the one character; otherwise
  search for the end of the syllable. We must correctly skip over escapes,
  and also find the final font, to set for the next syllable. */

  if (*s == '=') s++; else
    {
    int font, revert;
    uschar ss[20];
    for (;;)
      {
      while (*s != '\\' && *s != '-' && *s != ' ' && *s != '=' && *s != 0) s++;
      if (*s != '\\') break;
      s = string_escape(++s, ss, &font, &revert);
      if (font >= 0 && !revert) endfont = font;
      }
    }

  /* Set string count - don't include a minus sign, but skip over it */

  q->ulen = s - p->string;
  if (*s == '-') s++;

  /* Skip spaces between syllables */

  while (*s == ' ') s++;

  /* Advance to next verse, freeing the current control block if reached the
  end of the string. */

  if (*s == 0)
    {
    *pp = p->next;
    store_free(p);
    }
  else
    {
    p->string = s;
    p->font = endfont;
    pp = &(p->next);
    }

  p = *pp;
  }
}


/*************************************************
*       Processing after reading a note          *
*************************************************/

/* This is called after reading an original note, or after copying a previous
note using 'x'. The flag is TRUE if called after an original note or after the
final copied note, in which case things that can follow a note are processed.
We first have to choose a stem direction, which is tied in with the beaming and
which we can't always complete at this point.

Argument:  TRUE for original note or last of some copies
Returns:   nothing
*/

static void
post_note(BOOL final_copy)
{
int i;
int pletending = FALSE;
int stempitch = (maxpitch + minpitch)/2;             /* zero for rests */

if (!stave_lastwastied) onlytieddup = FALSE;

/* Set up the tie data for this note before any chord sorting, because it has
to be sorted along with the chord. */

for (i = 0; i < chordcount; i++) stave_tiedata[i] = this_tiedata[i];

/* A note or rest longer than a quaver terminates a beam, unless it is a grace
note */

if (notetype < quaver && stave_beaming && length > 0) read_setbeamstems();

/* Deal with non-rests and non-grace notes */

if (stempitch > 0 && length != 0)
  {
  stave_lastgracestem = 0;      /* unset grace note forcing */

  /* If already beaming, count notes in the beam */

  if (stave_beaming) stave_beamcount++;

  /* Else a note shorter than a crotchet starts a beam */

  else if (notetype > crotchet)
    {
    stave_beaming = TRUE;
    stave_beamfirstnote = stave_firstnoteptr;    /* remember first note */
    stave_beamcount = 1;

    if (stemforce == 0) stemforce = stave_stemforce;

    if (stemforce != 0)
      {
      stave_beamstemforce = stemforce;
      mac_setstackedstems((stave_beamstemforce > 0)? nf_stemup : 0);
      }
    else
      {
      stave_beamstemforce = 0;
      stave_maxaway = stempitch;
      }
    }

  /* Deal with beamed and non-beamed notes which have their stem direction
  forced. Note that we must call setstemflag even for down stems, because it
  does other work for chords. */

  if (stemforce != 0 || (!stave_beaming && stave_stemforce != 0))
    {
    int flag;
    if (stemforce == 0) stemforce = stave_stemforce;
    flag = (stemforce > 0)? nf_stemup : 0;
    mac_setstemflag(stave_firstnoteptr, flag);

    /* For non-beamed notes, set the flag for any pending queued notes,
    and remember the direction. We don't remember the direction for
    forced notes in the middle of beams -- these are usually eccentric. */

    if (!stave_beaming)
      {
      mac_setstackedstems(flag);
      stave_laststemup = flag != 0;
      }
    }

  /* Deal with beamed note that does not have a forced stem - if the beam's
  stem direction was forced, set this note's direction. Otherwise use its pitch
  in computing the maxaway value, and add it to the beam stack. */

  else if (stave_beaming)
    {
    /* If the previous note was tied and we are at the start of a beam, copy
    the stem direction of the previous note, if known. */

    if (stave_lastwastied && stave_beamcount == 1 && stave_stemstackptr == 0)
      stave_beamstemforce = stave_laststemup? 1 : -1;

    if (stave_beamstemforce != 0)
      { /* NB */
      mac_setstemflag(stave_firstnoteptr, (stave_beamstemforce > 0)?
        nf_stemup : 0);
      }
    else
      {
      if (abs(stempitch-P_3L) > abs(stave_maxaway-P_3L))
        stave_maxaway = stempitch;
      stave_beamstack[stave_beamstackptr++] = stave_firstnoteptr;
      }
    }

  /* Deal with non-beamed note that does not have a forced stem - if the stem
  direction is immediately decidable, use it and empty the stack of any pending
  notes awaiting a decision. Otherwise add this note to the stack. Note that we
  must call setstemflag, even with a zero flag, because it also sorts chords
  and deals with inverted notes. */

  else if (stave_lastwastied && stave_stemstackptr == 0 &&
    (chordcount > 1 || stave_lasttiepitch == stave_firstnoteptr->spitch))
      { /* NB */
      mac_setstemflag(stave_firstnoteptr, stave_laststemup? nf_stemup : 0);
      }

  else if (stempitch != stave_stemswaplevel[curstave])
    {
    int flag;
    stave_laststemup = stempitch < stave_stemswaplevel[curstave];
    flag = (stave_laststemup)? nf_stemup : 0;
    mac_setstemflag(stave_firstnoteptr, flag);
    mac_setstackedstems(flag);
    }

  /* What happens to notes that are on the stemswap level depends on the type
  of stemswapping specified. */

  else switch (curmovt->stemswaptype)
    {
    case stemswap_default:
    if (stave_firstinbar || stave_stemstackptr > 0)
      stave_stemstack[stave_stemstackptr++] = stave_firstnoteptr;
    else
      { /* NB */
      mac_setstemflag(stave_firstnoteptr, stave_laststemup? nf_stemup : 0);
      }
    break;

    case stemswap_up:
    mac_setstemflag(stave_firstnoteptr, nf_stemup);
    break;

    case stemswap_down:
    mac_setstemflag(stave_firstnoteptr, 0);
    break;

    case stemswap_left:
    mac_setstemflag(stave_firstnoteptr, stave_laststemup? nf_stemup : 0);
    break;

    case stemswap_right:
    stave_stemstack[stave_stemstackptr++] = stave_firstnoteptr;
    break;
    }

  /* Subsequent notes are no longer the first in the bar */

  stave_firstinbar = FALSE;
  }

/* Grace notes are always stem up unless explicitly marked, but a single forced
grace note forces all immediately following. */

else if (length == 0)
  {
  if (stemforce == 0) stemforce = stave_lastgracestem;
  mac_setstemflag(stave_firstnoteptr, (stemforce >= 0)? nf_stemup : 0);
  stave_lastgracestem = stemforce;
  }

/* For a rest, unset grace stem forcing */

else
  {
  stave_lastgracestem = 0;
  }

/* We now need to deal with ties, glissando marks, beam breaks, and the ends of
plet groups. We permit the plet group ending to come before any of the other
items if no space intervenes. Skip this, though, for intermediate notes of a
copied set. */

if (!final_copy) return;

if (read_ch == '}') { pletending = TRUE; next_ch(); }

/* Deal with ties and glissandos */

if (read_ch == '_')
  {
  int acount = 0;
  int bcount = 0;
  int flags = tief_default;

  if (stave_ties > 0) acount = 255;
    else if (stave_ties < 0) bcount = 255;

  next_ch();

  while (read_ch == '/')
    {
    next_ch();
    if (read_ch == 'g') { flags &= ~tief_default; flags |= tief_gliss; }
    else if (read_ch == 's' || read_ch == 't') flags |= tief_slur;
    else if (read_ch == 'e') flags |= tief_editorial;
    else if (read_ch == 'i')
      {
      if (*read_chptr == 'p')
        {
        flags |= tief_dotted;
        next_ch();
        }
      else flags |= tief_dashed;
      }
    else
      {
      int count = 255;
      if (isdigit(read_ch)) count = read_integer(FALSE);
      if (read_ch == 'b') { bcount = count; acount = 0; }
        else if (read_ch == 'a') { acount = count; bcount = 0; }
          else error_moan(ERR37, "/a /b /e /g /i /p /s or /t");
      flags |= tief_slur;
      }
    next_ch();
    }

  if ((flags & tief_editorial) != 0)
    {
    if ((flags & (tief_dotted | tief_dashed)) != 0) error_moan(ERR94);
    }

  if (minpitch == 0) error_moan(ERR51); else
    {
    b_tiestr *p = store_getitem(b_tie);
    p->flags = flags;
    p->abovecount = acount;
    p->belowcount = bcount;
    p->note = stave_firstnoteptr;
    stave_lastwastied = TRUE;
    stave_lasttiepitch = stave_firstnoteptr->spitch;
    }

  stave_resetOK = FALSE;
  }
else
  {
  stave_lastwastied = FALSE;
  stave_resetOK = TRUE;
  }

/* If a relevant note is followed by a comma, set for a secondary beam break.
If followed by a semicolon, set for a primary beam break. We used to give an
error when either of these characters did not follow a quaver or shorter note.
This makes it annoying to use doublenotes or halvenotes to set a piece in
different ways. We now allow comma and semicolon after any note at this
point, only generating the relevant break for short enough notes. Any other
occurrences still give an error.

COMPATIBILITY FEATURE: For compatibility with the original program, if the
"oldbeambreak" option is set, use space or ! for a primary break. Semicolon
will be treated (elsewhere) as a general separator and ignored. */

if (opt_oldbeambreak)
  {
  if (read_ch == ' ' || read_ch == '!')
    {
    next_ch();
    if (notetype >= quaver)
      {
      (void)store_getitem(b_beambreak);
      if (stave_beaming) read_setbeamstems();
      }
    }
  else if (read_ch == ',') goto SECBEAMBREAK;
  }

else  /* Not oldbeambreak */
  {
  if (read_ch == ';')
    {
    next_ch();
    if (notetype >= quaver)
      {
      (void)store_getitem(b_beambreak);
      if (stave_beaming) read_setbeamstems();
      }
    }
  else if (read_ch == ',')
    {
    usint v;
    SECBEAMBREAK:
    next_ch();
    if (isdigit(read_ch))
      {
      v = read_ch - '0';
      next_ch();
      }
    else v = 1;
    if (notetype >= quaver)
      {
      b_beambreak2str *b = store_getitem(b_beambreak2);
      b->value = v;
      }
    }
  }

/* If we encountered '}' previously or here, end plet group */

sigch();
if (read_ch == '}')
  {
  next_ch();
  pletending = TRUE;
  }

if (pletending)
  {
  if (stave_pletlen == 0) error_moan(ERR52); else
    {
    stave_pletlen = 0;
    (void)store_getitem(b_endplet);
    }
  }

/* If there was a [smove] before the note, insert the appropriate
space directive. */

if (stave_smove != 0)
  {
  b_spacestr *s = store_getitem(b_space);
  s->value = stave_smove;
  s->relative = stave_smove_relative;
  stave_smove = 0;
  }

/* If we had a tied chord containing seconds, generate an implicit [ensure] */

if (seconds && stave_lastwastied)
  {
  b_ensurestr *pe = store_getitem(b_ensure);
  pe->value = 20000;
  read_lastensuredtie = pe;
  }
else read_lastensuredtie = NULL;

/* Finally, update the count of notes in this chord */

stave_chordcount = chordcount;
}


/*************************************************
*           Read one note or chord               *
*************************************************/

/* This function is called if the stave scanner cannot interpret the current
character as the start of a directive or any other non-note construction.

Arguments:  none
Returns:    nothing
*/

void
read_note(void)
{
BOOL nopack = FALSE;

int inchord = 0;                    /* Contains nf_chord when in a chord */
int item = b_note;
int ornament = stave_ornament;
int ornset = 0;
int prevpitch = 0;
int yextra;                         /* restlevel or stemlength */
int chordlength = 0;

stave_firstnoteptr = NULL;
maxpitch = 0;
minpitch = 256;
stemforce = 0;                      /* stem not forced */
seconds = FALSE;

/* If we are at the start of a bar, behave for "p" and "x" as if all previous
notes were tied duplicated (i.e. show accidentials unless this note is tied to
its predecessor). */

if (stave_firstinbar) onlytieddup = TRUE;

/* Handle exact duplication of the previous note or chord. Duplication of a
previous note's pitch(es) only is handled by the 'p' letter, and is mixed up
with other interpretation below. */

if (read_ch == 'x')
  {
  int count = 1;
  next_sigch();
  if (isdigit(read_ch)) count = read_integer(FALSE);

  if (read_ch == '\\')  /* No options are allowed */
    {
    next_ch();
    error_skip = skip_BACKSLASH;
    error_moan(ERR135);
    error_skip = skip_EOL;
    next_ch();
    }

  if (stave_lastbasenoteptr == NULL)
    {
    error_moan(ERR115);
    return;
    }

  /* Duplicate a note or chord */

  for (; count > 0; count--)
    {
    b_notestr *old = stave_lastnoteptr;
    b_notestr *oldbase = stave_lastbasenoteptr;
    b_notestr *new;
    bstr *p = (bstr *)last_note_ornament;
    do_underlay();
    chordcount = 0;

    if (p != NULL) while (p != (bstr *)old)
      {
      int type = p->type;
      if (type == b_Jump)
        p = (bstr *)(((b_Jumpstr *)p)->next);
      else if (type == b_ornament && ((b_ornamentstr *)p)->ornament < or_dsharp)
        {
        b_ornamentstr *pp = store_getitem(b_ornament);
        *pp = *((b_ornamentstr *)p);
        }
      p = (bstr *)((uschar *)p + length_table[type]);
      }

    stave_firstnoteptr = new = store_getitem(b_note);

    length = old->length;
    notetype = old->notetype;
    *new = *old;

    /* At bar start, or after only tied duplicates, retain the accidental;
    otherwise don't. The note itself is taken from the previous note (to get
    the length the same), but the accidentals are taken from the base note,
    because intermediate notes may have their accidentals disabled. */

    if (onlytieddup && !stave_lastwastied)
      {
      new->acc = oldbase->acc;
      new->accleft = oldbase->accleft;
      new->flags |= nf_accleft;            /* Spacing already set */
      }
    else
      {
      new->acc = 0;
      new->accleft = 0;
      }

    stave_pitchtotal += new->truepitch;
    stave_pitchcount++;
    chordcount++;

    /* This error should never occur because the original chord should be
    diagnosed. Paranoia. */

    if (chordcount >= MAX_CHORDSIZE) error_moan(ERR132, MAX_CHORDSIZE); /* Hard */
    if (new->spitch > maxpitch) maxpitch = new->spitch;
    if (new->spitch < minpitch) minpitch = new->spitch;

    if ((old->flags & nf_chord) != 0)
      {
      mac_advancechord(old);
      mac_advancechord(oldbase);
      while (old->type == b_chord)
        {
        new = store_getitem(b_chord);
        *new = *old;

        /* At bar start, or after only tied duplicates, retain the accidental
        from the base note; otherwise don't. */

        if (onlytieddup && !stave_lastwastied)
          {
          new->acc = oldbase->acc;
          new->accleft = oldbase->accleft;
          }
        else
          {
          new->acc = 0;
          new->accleft = 0;
          }

        if (new->spitch > maxpitch) maxpitch = new->spitch;
        if (new->spitch < minpitch) minpitch = new->spitch;
        stave_pitchtotal += new->truepitch;
        stave_pitchcount++;
        chordcount++;
        mac_advancechord(old);
        mac_advancechord(oldbase);
        }
      }

    new[1].type = b_End;             /* Mark end for sorting */
    stave_barlength += length;
    post_note(count <= 1);
    }

  return;
  }

/* Not an exact repetion: handle the reading of a new note or chord. */

last_note_ornament = NULL;   /* For remembering ornaments for 'x' */

/* Deal with the start of a chord */

if (read_ch == '(') { inchord = nf_chord; next_sigch(); }

/* Loop to read all the notes of a chord */

chordcount = 0;
for (;;)
  {
  b_notestr *noteptr;

  BOOL acc_invis = FALSE;
  BOOL acc_onenote = FALSE;
  BOOL duplicating = FALSE;
  uschar *acc_above = NULL;
  usint acflags = 0;
  int flags = stave_noteflags | stave_stemflag | inchord;
  int transposedaccforce = stave_transposedaccforce;
  int acc = 0;
  int accleft = 0;
  int masq = -1;
  int tiedcount = -1;
  int transposeacc = 0;
  int explicit_couple = 0;
  int dup_octave = 0;
  int pitch, abspitch, orig;

  if (chordcount == 0) acflags |= stave_accentflags;

  /* Deal with accidentals */

  if (read_ch == '#')
    {
    next_ch();
    switch(read_ch)
      {
      case '#':
      acc = ac_dsharp;
      next_ch();
      break;

      case '-':
      flags |= nf_halfacc;
      next_ch();
      /* Fall through */

      default:
      acc = ac_sharp;
      break;
      }
    }
  else if (read_ch == '$')
    {
    next_ch();
    switch (read_ch)
      {
      case '$':
      acc = ac_dflat;
      next_ch();
      break;

      case '-':
      flags |= nf_halfacc;
      next_ch();
      /* Fall through */

      default:
      acc = ac_flat;
      }
    }
  else if (read_ch == '%') { acc = ac_natural; next_ch(); }

  /* Save original accidental (prior to transposition) for use if this note has
  to be re-created for 'p'. The note letter is also saved later. */

  orig = acc;

  /* Deal with requests for transposed accidentals */

  if (read_ch == '^')
    {
    next_ch();
    if (read_ch == '-') { transposedaccforce = FALSE; next_ch(); }
    else if (read_ch == '+') { transposedaccforce = TRUE; next_ch(); }

    if (read_ch == '#')
      {
      next_ch();
      if (read_ch == '#') { transposeacc = ac_dsharp; next_ch(); }
        else transposeacc = ac_sharp;
      }
    else if (read_ch == '$')
      {
      next_ch();
      if (read_ch == '$') { transposeacc = ac_dflat; next_ch(); }
        else transposeacc = ac_flat;
      }
    else if (read_ch == '%') { transposeacc = ac_natural; next_ch(); }
    }

  /* Deal with special forms of accidental: invisible, above/below, bracketed,
  and moved. */

  if (acc != 0)
    {
    /* An invisible accidental may have no further options */

    if (read_ch == '?') { acc_invis = TRUE; next_ch(); } else
      {
      /* Deal with a request to print the accidental above or below the note.
      We do this by setting it invisible, and generating a suitable ornament.
      This is only allowed on the first note of a chord. */

      if (read_ch == 'o' || read_ch == 'u')
        {
        if (chordcount == 0)
          {
          b_ornamentstr *p = store_getitem(b_ornament);
          int value = ((read_ch == 'o')? or_dsharp : or_accbelow);
          next_ch();
          ornmove(&(p->x), &(p->y), NULL);
          p->bflags = 0;
          if (read_ch == ')') { value += 1; next_ch(); }
            else if (read_ch == ']') { value += 2; next_ch(); }
          p->ornament = value;
          acc_above = &(p->ornament);   /* To fill in the acc later */
          acc_invis = TRUE;
          acc_onenote = TRUE;
          }
        else error_moan(ERR96);
        }

      /* Deal with visible, normally placed, accidentals */

      else
        {
        if (read_ch == ')') { flags |= nf_accrbra; next_ch(); }
          else if (read_ch == ']') { flags |= nf_accsbra; next_ch(); }

        while (read_ch == '<')
          {
          next_ch();
          if (isdigit(read_ch)) accleft += read_integer(TRUE);
            else accleft += 5000;
          flags |= nf_accleft;
          }
        }
      }
    }

  /* Now read note letter. Non-letters will be assigned as crotchets. The only
  relevant one currently is '/'. */

  if (isupper(read_ch))
    {
    notetype = minim;
    length = len_minim;
    }
  else
    {
    notetype = crotchet;
    length = len_crotchet;
    }

  /* Now deal with the pitch. First of all get an absolute pitch which is
  independent of any clef. The units are semitones and the origin is such that
  middle C has the value 48, which should cope with any requirements. This
  pitch doesn't yet contain the accidental (if any). */

  read_ch = tolower(read_ch);

  /* Deal with duplication of previous pitch(es). This must not be in a chord
  and there must be no accidentals. We regenerate the pitch letter from the
  previous note, and the accidental if this is the start of a bar, unless after
  a tie. */

  if (read_ch == 'p')
    {
    if (acc != 0) error_moan(ERR114);
    if (inchord) { error_moan(ERR37, "Note letter"); read_ch = 'a'; }
    else if (stave_lastbasenoteptr == NULL) { error_moan(ERR115); read_ch = 'r'; }
    else
      {
      int x = stave_lastbasenoteptr->truepitch;
      if (stave_transpose != no_transpose) x -= stave_transpose;
      dup_octave = 12 - stave_octave;
      while (x < 48) { x += 12; dup_octave -= 12; }
      while (x > 59) { x -= 12; dup_octave += 12; }

      /* Set the accidental - needed for transposition, even if we aren't going
      to print it, for cases of forcing - and the original note letter. */

      orig = stave_lastbasenoteptr->orig;
      acc = orig & 0x0f;
      transposeacc = stave_lastbasenoteptr->acc;
      read_ch = (orig >> 4) + 'a';

      /* At bar start, or after only tied duplicates, retain the accidental;
      otherwise make it invisible. */

      if (onlytieddup && !stave_lastwastied)
        {
        if (stave_lastbasenoteptr->acc == 0) acc_invis = TRUE;
        accleft = stave_lastbasenoteptr->accleft;
        flags |= nf_accleft |
          (stave_lastbasenoteptr->flags & (nf_accrbra | nf_accsbra));
        }
      else acc_invis = TRUE;
      duplicating = TRUE;
      }
    }

  /* Deal with non-rests, i.e. notes */

  if ('a' <= read_ch && read_ch <= 'g')
    {
    pitch = stave_octave + 36 + read_basicpitch[read_ch - 'a'];
    yextra = stave_stemlength;     /* Default stem length */
    orig |= (read_ch - 'a') << 4;
    if (!duplicating) onlytieddup = FALSE;
    }

  /* Deal with rests. R is a normal rest, Q is a quiet (invisible) rest, S is
  like R but whole bars do not pack up, and / is a "repeat beat" mark that is
  handle as a differently printed crotchet rest. */

  else
    {
    pitch = 0;
    acflags &= ~af_dynamics;         /* Ignore any default dynamics */
    yextra = stave_restlevel;
    if (read_ch == 'q') flags |= nf_hidden;
    else if (read_ch == 's') nopack = TRUE;
    else if (read_ch == 't') flags |= nf_restrep;
    else if (read_ch != 'r')
      {
      error_moan(ERR37, inchord? "Note letter or end of chord" :
                                 "Note or rest letter");
      pitch = 30;                 /* Take a random pitch */
      inchord = FALSE;            /* Terminate a chord, in case missing ')' */
      stave_checklength = FALSE;  /* Disable length check for this bar */
      }
    if (inchord && pitch == 0) error_moan(ERR43);
    }

  /* If suspended and not a rest, resume automatically */

  if (stave_suspended && pitch > 0)
    {
    (void)store_getitem(b_resume);
    stave_suspended = FALSE;
    }

  /* Pitch adjustment for octave indicators, transposition and clef, except for
  rests, of course. */

  next_ch();
  if (pitch == 0) abspitch = minpitch = 0; else   /* min = max = 0 for rests */
    {
    if (duplicating) pitch += dup_octave; else
      {
      while (read_ch == '\'') { pitch += 12; next_ch(); }
      while (read_ch == '`' ) { pitch -= 12; next_ch(); }
      }

    /* Get a true absolute pitch which includes the accidental. Update the
    table which keeps track of the current accidental state for a given input
    pitch. After a tie, take the default accidental from the previous note,
    which may have been in the previous bar. Save the information in case this
    note is tied. */

    if (chordcount >= MAX_CHORDSIZE) error_moan(ERR132, MAX_CHORDSIZE); /* Hard */
    this_tiedata[chordcount].pitch = pitch;

    if (acc != 0)
      {
      int x = read_accpitch[acc];
      if (!acc_onenote) baraccs[pitch] = x;
      this_tiedata[chordcount].acc = x;
      abspitch = pitch + x - 2;
      }
    else
      {
      if (stave_lastwastied)
        {
        int i;
        for (i = 0; i < stave_chordcount; i++)
          {
          if (pitch == stave_tiedata[i].pitch)
            {
            int x = stave_tiedata[i].acc;
            abspitch = pitch + x - 2;
            this_tiedata[chordcount].acc = x;
            tiedcount = i;
            acc_invis = TRUE;   /* Could come from transpose if previous is invisible */
            goto TRANSPOSE;
            }
          }
        }

      /* Last not tied, or tie not matched up (slur) */

      abspitch = pitch + baraccs[pitch] - 2;
      this_tiedata[chordcount].acc = baraccs[pitch];
      }

TRANSPOSE:

    /* Transpose the note and its accidental if required */

    if (stave_transpose != no_transpose)
      {
      abspitch = transpose_note(abspitch, &pitch, &acc, transposeacc,
        transposedaccforce, acc_onenote, FALSE, tiedcount);
      this_tiedata[chordcount].acc_tp = baraccs_tp[pitch];
      }

    /* If there was a half-accidental that is now a natural, change it to the
    opposite half-accidental, and play similar games with double sharps and
    flats. */

    if ((flags & nf_halfacc) != 0)
      {
      if (acc == ac_none || acc == ac_natural)
        acc = ((orig & 0x0f) == ac_sharp)? ac_flat : ac_sharp;
      else if (acc == ac_dflat)
        {
        acc = ac_sharp;
        pitch -= 2;
        abspitch -= 2;
        }
      else if (acc == ac_dsharp)
        {
        acc = ac_flat;
        pitch += 2;
        abspitch += 2;
        }
      }

    /* Adjust absolute pitch for transposing clefs */

    abspitch += stave_clef_octave;

    /* Keep track of the absolute pitch range, and maintain data
    for tessitura computation. */

    if (abspitch > stave_maxpitch) stave_maxpitch = abspitch;
    if (abspitch < stave_minpitch) stave_minpitch = abspitch;

    stave_pitchtotal += abspitch;
    stave_pitchcount++;

    /* Now adjust the printing pitch to make it relative to the current clef,
    where a value of P_1L (=128) is the bottom line of the staff, and the note
    positions are 2 apart (because they are two points apart). However, the
    printing pitch may be explicitly forced (percussion staves), in which case
    the accidental must be cancelled. */

    if (stave_printpitch)
      {
      pitch = stave_printpitch;
      acc = 0;
      }
    else pitch = pitch_stave[pitch] + pitch_clef[stave_clef];

    /* Save max/min pitch per chord */

    if (pitch > maxpitch) maxpitch = pitch;
    if (pitch < minpitch) minpitch = pitch;

    /* Set flags for potentially auto-coupled notes; these may be unset
    later by the \h\ option. */

    if (pitch > P_6L) flags |= nf_coupleU;
      else if (pitch < P_0L) flags |= nf_coupleD;

    /* Flag chords containing seconds */

    if (abs(pitch - prevpitch) == 2) seconds = TRUE;
    prevpitch = pitch;
    }

  /* If the accidental is to be printed above or below, add in its value, which
  is not known till after transposition. */

  if (acc_above != NULL)
    {
    *acc_above += 3*(acc - 1);
    if ((flags & nf_halfacc) != 0)
      *acc_above += (acc == ac_sharp)? 6 : 12;
    }

  /* If the accidental is invisible, cancel it now that the true pitch has been
  determined. Don't cancel for a rest so that it gets an error below. */

  if (acc_invis && pitch != 0) acc = 0;

  /* Note or rest length adjustment by modifiers. */

  if (read_ch == '!')
    {
    if (notetype != minim) error_moan(ERR150);
    notetype = semibreve;
    length = stave_requiredbarlength;
    if (pitch == 0)
      {
      flags |= nf_centre;
      if ((flags & nf_restrep) != 0) nopack = TRUE;   /* Was T! */
      }
    next_ch();
    }

  else
    {
    while (read_ch == '=' )
      { next_ch(); notetype += 2; length /= 4; }
    while (read_ch == '-' )
      { next_ch(); notetype += 1; length /= 2; }
    while (read_ch == '+')
      { next_ch(); notetype -= 1; length *= 2; }
    if (notetype != crotchet) flags &= ~nf_restrep;  /* Ignore if not crotchet */
    }

  /* Set left movement for any accidental. We can't do this earlier, because
  transposition can alter which accidental is printed, and we need to have
  notetype set correctly for accadjusts. If duplicating, the movement has
  already been copied. */

  if (acc && !duplicating)
    {
    accleft += curmovt->accspacing[acc] - curmovt->accadjusts[notetype];
    if ((flags & nf_accrbra) != 0) accleft += rbra_left[acc];
      else if ((flags & nf_accsbra) != 0) accleft += sbra_left[acc];
    }

  /* Deal with non-standard lengths. */

  if (stave_pletlen != 0)
    length = (length*stave_pletsupnum)/(stave_pletlen*stave_pletsupden);

  /* Deal with dotted notes. For the first note of a chord, a movement of the
  dot is permitted. */

  if ((read_ch == '>' && *read_chptr == '.') || isdigit(read_ch))
    {
    if (chordcount == 0)
      {
      b_dotrightstr *d = store_getitem(b_dotright);
      if (read_ch == '>')
        {
        next_ch();
        d->value = 5000;
        }
      else
        {
        d->value = read_integer(TRUE);
        if (read_ch != '>' || *read_chptr != '.')
          error_moan(ERR37, "\">.\" (augmentation dot movement)");
        next_ch();
        }
      }
    else error_moan(ERR48, "Augmentation dot movement");
    }

  /* Lengthen the note according to .+ . or .. */

  if (read_ch == '.' )
    {
    next_ch();
    if (read_ch == '+')
      {
      next_ch();
      flags |= nf_plus;
      length = (length*5)/4;
      }
    else
      {
      flags |= nf_dot;
      length = (length*3)/2;
      if (read_ch == '.' )
        { next_ch(); flags |= nf_dot2; length = (length*7)/6; }
      }
    }

  /* Handle doubled or halved note lengths - note that full bar rests must be
  skipped (the centre flag is an indicator). */

  if ((stave_notenum != 1 || stave_noteden != 1) && (flags & nf_centre) == 0)
    {
    int i = stave_notenum;
    while (i > 1) { length += length; notetype--; i /= 2; }
    i = stave_noteden;
    while (i > 1) { length /= 2; notetype++; i /= 2; }
    }

  /* Can't handle anything longer than a breve or shorter than a
  hemidemisemiquaver. */

  if (notetype < 0 || notetype > 7) error_moan(ERR103);

  /* Now we have the final length for the note, adjust it if necessary to allow
  for triplet vs duplet time signatures, etc. */

  if (stave_matchnum > 0 && (flags & nf_centre) == 0)
    length = mac_muldiv(length, stave_matchnum, stave_matchden);

  /* Accents and ornaments etc. and local level for rests */

  if (read_ch == '\\')
    {
    BOOL had_error = FALSE;
    uschar *end_options;

    error_skip = skip_BACKSLASH;
    next_sigch();

    /* Search for the terminating backslash in the current line, to try to
    minimise error cascades when it is missing. */

    for (end_options = read_chptr;; end_options++)
      {
      if (end_options >= read_endptr ||
          (*end_options == '|' && end_options[-1] != '~' &&
            end_options[-1] != 't'))
        {
        error_skip = skip_BAR;
        error_moan(ERR133);
        goto ENDACCENT;
        }
      if (*end_options == '\\') break;
      }

    /* Now process the options */

    while (read_ch != '\\' && read_ch != EOF)
      {
      accent *ap;
      switch (read_ch)
        {

        /* ----- Handle things that are not accents or ornaments ----- */

        case ':':
        next_ch();
        if (read_ch == ':')
          {
          next_ch();
          flags |= nf_highdot;
          }
        else flags ^= nf_lowdot;
        break;

        case ')':
        next_ch();
        flags |= nf_headbra;
        break;

        case 'c':
        next_ch();
        explicit_couple = nf_couple;
        break;

        /* This flag centres a note iff it is the first note in the bar
        and has the barlength. */

        case 'C':
        next_ch();
        if (stave_barlength == 0 && length == stave_requiredbarlength)
          flags ^= nf_centre;
        break;

        case 'g':
        length = 0;
        next_ch();
        if (read_ch == '/') { flags |= nf_appogg; next_ch(); }
        break;

        case 'h':
        next_ch();
        flags &= ~nf_couple;
        explicit_couple = 0;
        break;

        case 'l':  /* local rest level */
        next_ch();
          {
          int y;
          if (read_expect_integer(&y, TRUE, TRUE))
            {
            if (opt_oldrestlevel) y *= 2;
            yextra += y;
            }
          }
        break;

        case 'M':
        case 'm':
        masq = (read_ch == 'm')? crotchet : minim;
        flags &= ~(nf_dot|nf_dot2|nf_plus);
        for (;;)
          {
          next_ch();
          if (read_ch == '-') masq++;
            else if (read_ch == '=') masq += 2;
              else if (read_ch == '+') masq--;
                else break;
          }
        if (masq < breve || masq > hdsquaver)
          { error_moan(ERR45); masq = -1; }

        if (read_ch == '.')
          {
          next_ch();
          if (read_ch == '+') { next_ch(); flags |= nf_plus; }
          else
            {
            flags |= nf_dot;
            if (read_ch == '.') { next_ch(); flags |= nf_dot2; }
            }
          }
        break;

        case 'n':
        next_ch();
        if (read_ch == 'h') { flags |= nf_nhharmonic; next_ch(); }
          else if (read_ch == 'x') { flags |= nf_nhcross; next_ch(); }
            else error_moan(ERR45);
        break;

        case 's':
        next_ch();
        if (read_ch == 'u')
          {
          if (stemforce < 0) error_moan(ERR46, inchord? "in chord" : "");
          stemforce = 1;
          next_ch();
          }
        else if (read_ch == 'd')
          {
          if (stemforce > 0) error_moan(ERR46, inchord? "in chord" : "");
          stemforce = -1;
          next_ch();
          }
        else if (read_ch == 'w')
          {
          if (stave_beaming && notetype >= quaver && stave_beamstemforce != 0)
            {
            if (stemforce) error_moan(ERR46, inchord? "in chord" : "");
            stave_beamstemforce = -stave_beamstemforce;
            if (abs(stave_beamstemforce) == 1) stave_beamstemforce *= 2;
            }
          else error_moan(ERR47);
          next_ch();
          }
        else if (read_ch == 'l')
          {
          int y;
          next_ch();
          if (read_expect_integer(&y, TRUE, TRUE))
            {
            if (opt_oldstemlength) y *= 2;
            yextra += y;
            }
          }
        else if (read_ch == 'm')
          {
          next_ch();
          flags |= nf_smallhead;
          }
        else if (read_ch == 'p')   /* sp is an ornament */
          {
          read_ch = 's';
          read_chptr--;
          goto ACCORN;
          }
        else
          {
          error_moan(ERR10, "su, sd, sw, sl, sm, or sp");  /* skips to '\' or EOL */
          if (read_ch != '\\') goto ENDACCENT;
          }
        break;

        case 'x':
        next_ch();
        acflags &= ~stave_accentflags;
        ornament = -1;
        break;

        /* ----- Handle accents and ornaments ----- */

        default:
        ACCORN:
        for (ap = accent_chars; ap->string != NULL; ap++)
          {
          int i;
          int ln = (int)Ustrlen(ap->string);
          for (i = 0; i < ln; i++)
            if (read_chptr[i-1] != ap->string[i]) break;
          if (i >= ln)
            {
            read_chptr += ln - 1;
            next_ch();
            break;
            }
          }

        /* Found in the table */

        if (ap->string != NULL)
          {
          if (ap->flag < 256)     /* Ornaments */
            {
            switch (ap->flag)
              {
              case or_mord:
              case or_dmord:
              case or_imord:
              case or_dimord:
              case or_turn:
              case or_iturn:
              if ((ornset & ornset_mordturn) != 0)
                error_moan(ERR45);   /* But carry on */
              else ornset |= ornset_mordturn;
              break;

              case or_trem1:
              case or_trem2:
              case or_trem3:
              if ((ornset & ornset_trem) != 0)
                error_moan(ERR45);   /* But carry on */
              else ornset |= ornset_trem;
              break;

              case or_tr:
              case or_trsh:
              case or_trfl:
              case or_trnat:
              if ((ornset & ornset_trill) != 0)
                error_moan(ERR45);   /* But carry on */
              else ornset |= ornset_trill;
              break;
              }

            if (chordcount == 0)
              {
              b_ornamentstr *p = store_getitem(b_ornament);
              if (last_note_ornament == NULL) last_note_ornament = p;
              p->ornament = ap->flag;
              p->bflags = 0;

              /* Tremolos have no horizontal movement or bracketing; arpeggios
              and spread have no bracketing, but can have arbitrary movement.
              Because tremelos use '/' as their character, the coding is
              messy. */

              if (ap->flag >= or_trem1 && ap->flag <= or_trem3)
                {
                p->x = 0;            /* No horizontal movement */
                p->y = 0;            /* Default no vertical movement */
                p->bflags = 0;       /* No bracketing */
                ornament = -1;       /* Cancel auto tremolo */

                if (read_ch == '/')                /* Move a trem3 */
                  ornmove(NULL, &(p->y), NULL);
                else if (ap->flag != or_trem1 &&   /* Move a trem1/trem2 */
                         (read_ch == 'u' || read_ch == 'd') &&
                         (read_chptr < read_endptr) &&
                         (isdigit(*read_chptr) || *read_chptr == '-'))
                  {
                  p->ornament -= 1;
                  read_ch = '/';
                  read_chptr--;
                  ornmove(NULL, &(p->y), NULL);
                  }
                }
              else ornmove(&(p->x), &(p->y),
                (ap->flag >= or_arp)? NULL : &(p->bflags));
              }
            else error_moan(ERR48, "Ornaments");
            }

          else    /* Accents */
            {
            if (chordcount == 0)
              {
              int i;
              acflags |= ap->flag;
              for (i = 1; i <= dyn_max; i++)
                {
                if (ap->flag == accent_list[i])
                  {
                  dynmove(i-1);
                  break;
                  }
                }
              }
            else error_moan(ERR48, "Accents");
            }
          }

        /* Not found in the big table; check for a<n>. */

        else if (read_ch == 'a')
          {
          int x;
          next_ch();
          error_skip = skip_OFF;  /* Temporarily no skip */
          if (read_expect_integer(&x, FALSE, FALSE))
            {
            if (chordcount == 0)
              {
              if (x <= dyn_max)
                {
                acflags |= accent_list[x];
                dynmove(x-1);
                }
              else error_moan(ERR128, x);
              }
            else error_moan(ERR48, "Accents");
            }
          error_skip = skip_BACKSLASH;
          }

        /* Unknown ornament or expression. Give up after two successive errors.
        */

        else
          {
          error_moan(ERR45);
          if (had_error)
            {
            fprintf(stderr, "** Assuming missing backslash after two "
              "expression/ornament errors\n\n");
            goto ENDACCENT;
            }
          else
            {
            had_error = TRUE;
            next_sigch();
            }
          }
        }

      if ((acflags & (af_staccato|af_staccatiss)) ==
        (af_staccato|af_staccatiss)) error_moan(ERR129);
      sigch();
      }                            /* end of loop */

    next_ch();                     /* moves past terminating '\' */
    }

  ENDACCENT:                       /* some error states jump here */
  error_skip = skip_EOL;           /* default setting */

  /* Rests should not have ornaments or accidentals or certain options. */

  if (pitch == 0 && (
      (ornset != 0 && (flags & nf_hidden) == 0) ||
      (flags & nf_notrests) != 0 ||
      acc != 0 ||
      stemforce != 0 ||
      (acflags & af_dynamics) != 0))
    error_moan(ERR68);

  /* A small notehead may not be specified for a grace note. */

  if (length == 0 && (flags & nf_smallhead) != 0) error_moan(ERR108);

  /* Accumulate bar length and check that chord notes are all same length. If
  not, and the current one is a crotchet (i.e. just a lower case letter) force
  it to be the same as the first note. Other lengths cause an error. Output an
  underlay syllable if one is pending. Can't do this earlier because of grace
  notes. */

  if (chordcount == 0)  /* First note of chord */
    {
    stave_barlength += length;
    chordlength = length;
    if (length != 0 && stave_pendulay != NULL)
      {
      if (pitch != 0 || Ustrcmp(stave_pendulay->string, "#") == 0)
        do_underlay();
      }
    }
  else if (length != chordlength)
    {
    if (notetype == crotchet && (flags & nf_dotted) == 0)
      {
      length = chordlength;
      notetype = stave_firstnoteptr->notetype;
      flags = (flags & ~nf_dotted) | (stave_firstnoteptr->flags & nf_dotted);
      }
    else error_moan(ERR44);
    }

  /* Allow automatic coupling flags through only if appropriately coupled, but
  allow explicit coupling at any time. */

  if (stave_couplestate == 0)
    {
    flags = (flags & ~nf_couple) | explicit_couple;
    if (pitch >= 136) flags &= ~nf_coupleD;
      else flags &= ~nf_coupleU;
    }
  else
    {
    flags |= explicit_couple;
    if (stave_couplestate > 0) flags &= ~nf_coupleD;
      else if (stave_couplestate < 0) flags &= ~nf_coupleU;
    }

  /* Deal with never-to-be-packed-up rest bar */

  if (nopack) (void) store_getitem(b_nopack);

  /* Output any masquerade instruction, and adjust stem flag */

  if (masq >= 0)
    {
    if (masq < minim) flags &= ~nf_stem;
    if (chordcount == 0)
      {
      b_masqstr *p = store_getitem(b_masq);
      p->value = masq;
      }
    }
  else if (notetype < minim) flags &= ~nf_stem;

  /* Output any default ornament (can only happen on first note) */

  if (ornament >= 0)
    {
    b_ornamentstr *p = store_getitem(b_ornament);
    if (last_note_ornament == NULL) last_note_ornament = p;
    p->ornament = ornament;
    p->x = p->y = 0;
    ornament = -1;
    }

  /* If a whole bar rest, flag it for centring unless we are in an unchecked
  bar. (If the rest was specified as R! then it has already been marked as a
  whole bar rest.) */

  if (pitch == 0 && length == stave_requiredbarlength && stave_checklength)
    flags |= nf_centre;

  /* Now create a data block for the note or rest, saving the address of the
  first one in a chord for exact duplications ('x') and the first one in a
  non-p-duplicated chord for subsequent 'p' duplications, except in the case of
  above/below accidentals. */

  noteptr = store_getitem(item);
  if (stave_firstnoteptr == NULL)  /* Rest, single, or first note in a chord */
    {
    stave_firstnoteptr = noteptr;
    if (pitch != 0)
      {
      stave_lastnoteptr = noteptr;
      if (!duplicating)
        stave_lastbasenoteptr = (acc_above != NULL)? NULL : noteptr;
      }
    }

  /* Insert the data for this note */

  noteptr->notetype = notetype;
  noteptr->acc = acc;
  noteptr->orig = orig;
  noteptr->spitch = pitch;
  noteptr->flags = flags;
  noteptr->acflags = acflags;
  noteptr->length = length;
  noteptr->yextra = yextra;
  noteptr->accleft = accleft;
  noteptr->truepitch = abspitch;

  /* Count note, and set different item for remaining notes of chord */

  chordcount++;
  item = b_chord;

  /* If we are duplicating, we must now copy the remaining notes of a chord,
  replacing the length and chopping off any accidentals where necessary. We
  must also set the relevant tiedata values. */

  if (duplicating && (stave_lastbasenoteptr->flags & nf_chord) != 0)
    {
    int i = 0;

    b_notestr *old = stave_lastbasenoteptr;
    noteptr->flags |= nf_chord;
    mac_advancechord(old);
    while (i++, old->type == b_chord)
      {
      noteptr = store_getitem(item);
      *noteptr = *old;
      noteptr->notetype = notetype;

      /* At bar start, or after only tied duplicates, retain the accidental;
      otherwise don't. */

      if (onlytieddup && !stave_lastwastied)
        {
        noteptr->acc = old->acc;
        noteptr->accleft = old->accleft;
        }
      else
        {
        noteptr->acc = 0;
        noteptr->accleft = 0;
        }

      noteptr->flags = (noteptr->flags & ~nf_dotted & ~nf_stem) |
        (flags & (nf_dotted | nf_stem));

      noteptr->acflags &= ~af_dynamics;
      noteptr->length = length;

      if (noteptr->spitch > maxpitch) maxpitch = noteptr->spitch;
      if (noteptr->spitch < minpitch) minpitch = noteptr->spitch;

      stave_pitchtotal += noteptr->truepitch;
      stave_pitchcount++;

      chordcount++;
      mac_advancechord(old);

      this_tiedata[i] = stave_tiedata[i];
      }
    }

  /* Insert a b_End item immediately after this note in case it is the last
  note of a chord, so that the function for sorting chords detects the end
  correctly. As there is always space for a b_Jump item after any item, this is
  safe to do. This is done unconditionally, because after an error inchord may
  not be set at this point. */

  noteptr[1].type = b_End;   /* Mark end for sorting */

  /* Check for end of chord */

  if (inchord)
    {
    sigch();
    if (read_ch == ')' || read_ch == EOF)
      {
      next_ch();
      break;
      }
    /* Continuing with chord */
    }
  else break;
  }

/* We have now reached the end of a chord, having output all the notes therein
contiguously, with any ornaments or masquerade items preceding. The remaining
code is put into a separate function so it can be called from the note-copying
code too. */

post_note(TRUE);
}

/* End of read5.c */
