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

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

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


/* This file contains code for outputting one bar */


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



/*************************************************
*             Output one bar in a system         *
*************************************************/

/* The bar number is in out_bar. The yield is the number of the last bar output
plus one, which may be greater than the value of out_bar plus one when multiple
rests are involved.

Arguments:  none
Returns:    number of the next bar to be output
*/

int
out_setbar(void)
{
int i;
BOOL notfirst = FALSE;
bstr *lastp = NULL;
int numberwanted = 0;
usint *notsuspend = out_sysblock->notsuspend;
contstr *out_cont_save = out_cont;
barposstr *bp = curmovt->posvector + out_bar;
zcopystr *zcopy = curmovt->zcopy;

DEBUG(("out_setbar() start: bar %d\n", out_bar));

out_ystave = out_yposition + out_sysblock->systemdepth;
out_downgap = 24;

out_postable = out_posptr = bp->vector;
out_poslast = out_postable + bp->count - 1;
out_posxRL = -bp->posxRL;                    /* (stored positive) */

out_barlinex = out_barx + out_poslast->xoff;

out_repeatonbarline = out_lastbarwide;
out_lastbarwide = FALSE;

out_manyrest = bp->multi;
out_lineendflag = (out_bar + out_manyrest - 1) == out_sysblock->barend;

for (i = 0; i < dyn_max; i++)
  out_dynmovef[i] = out_dynmovex[i] = out_dynmovey[i] = 0;

/* Decide if a bar number is wanted. If there was a [nocount] directive in this
bar, then the next entry in the bar number vector is greater than the current
one. For such bars, a bar number is never printed. For other bars, the logical
bar number can be obtained from the true bar number, the bar number vector, and
the offset. */

if (curmovt->barnovector[out_bar+1] <= curmovt->barnovector[out_bar])
  {
  int bn = out_bar - curmovt->barnovector[out_bar] + curmovt->baroffset;
  int interval = curmovt->barno_interval;
  if (((interval > 0 && (bn % interval) == 0) ||
    (interval < 0 && out_startlinebar) || bp->barnoforce == 1) &&
      bn > 1 && bp->barnoforce != 255)
        numberwanted = bn;
  }

/* Deal with the data on each stave, skipping unwanted staves. We do the
printing from bottom to top so that each stave's stuff gets printed before the
bar line gets drawn into it from above - otherwise the wiping stuff for beams
may obliterate parts of the bar lines. */

for (out_stave = out_laststave; out_stave >= 0; out_stave--)
  {
  bstr *p;
  obeamstr *b;
  int barlinestyle = curmovt->barlinestyle;
  stavestr *ss = curmovt->stavetable[out_stave];

  int nextstave = 0;
  BOOL breakbarline = mac_teststave(curmovt->breakbarlines, out_stave);
  BOOL another;

  DEBUG(("stave %d\n", out_stave));

  /* Skip if stave is suspended */

  if (mac_testNstave(notsuspend, out_stave)) goto CHECKZCOPY;

  /* Do start of bar things (PostScript generates a comment) */

  ps_startbar(out_bar, out_stave);

  /* Each stave controls its own bit of barline */

  out_omitbarline = FALSE;
  out_barchar = bar_single;
  out_prevbar = NULL;            /* for omitempty previous bar lines */

  /* Lastp gets left pointing to the data for the top stave */

  lastp = p = (ss == NULL)? NULL : ss->barindex[out_bar];

  /* Set relative stave size */

  mac_setstavesize(out_stave);

  /* Reset hairpin starting halfway flag */

  out_hairpinhalf = FALSE;

  /* Set the gaps for coupling - must find previous printing stave. As the gaps
  are in pitch units, they must be made relative to the stave magnification. */

  if (out_stave == 0) out_upgap = 24; else
    {
    int previous;
    for (previous = out_stave - 1; previous > 0; previous--)
      {
      if (mac_teststave(notsuspend, previous) &&
        out_sysblock->stavespacing[previous] != 0) break;
      }
    out_upgap = out_sysblock->stavespacing[previous]/main_stavemagn;
    }

  out_downgap = (out_sysblock->stavespacing[out_stave])/main_stavemagn;
  if (out_downgap == 0)
    {
    int next;
    for (next = out_stave + 1; next <= out_laststave; next++)
      {
      if (mac_teststave(notsuspend, next) &&
        out_sysblock->stavespacing[next] != 0)
          {
          out_downgap = (out_sysblock->stavespacing[next])/main_stavemagn;
          break;
          }
      }
    }

  /* For all but the first to be printed (i.e. the bottom stave), move up by
  this stave's spacing */

  if (notfirst)
    {
    out_ystave -= out_sysblock->stavespacing[out_stave];
    }
  else notfirst = TRUE;

  /* Set the bar_cont data before skip testing; it is required to be left to
  the topmost stave for bar number printing. Also, we need to empty the beam
  continuation data if it set up. */

  bar_cont = out_cont + out_stave;

  /* Set up beaming variables. The value of out_overbeam must only ever be true
  while out_setupbeam() is computing spanning beams. Hence we make sure it is
  FALSE here. */

  beam_forceslope = BIGNUMBER;
  beam_offsetadjust = beam_accrit = 0;
  beam_overbeam = FALSE;

  /* If a beam has continued over a bar line, set up the various parameters;
  otherwise set no beaming. */

  b = bar_cont->overbeam;
  if (b != NULL && b->count > 0)
    {
    /* At the start of a line the beam has not been drawn. The continued flag
    will ensure that even one note gets a beam, and the longestnote value will
    be taken from this block. */

    if (out_startlinebar)
      {
      out_beaming = FALSE;
      beam_forceslope = b->slope;
      }

    /* For a non-start of line bar, the beam has already been drawn; set up the
    relevant parameters for the notes. */

    else
      {
      beam_firstX = b->firstX;
      beam_firstY = b->firstY;
      beam_slope = b->slope;
      beam_count = b->count;
      beam_Xcorrection = b->Xcorrection;
      beam_splitOK = b->splitOK;
      beam_upflag = b->upflag;
      out_beaming = TRUE;
      }

    beam_seq = 0;
    beam_continued = TRUE;
    b->count = -1;
    }
  else out_beaming = beam_continued = FALSE;

  /* Determine if there is a following printing stave, for the purpose of
  extending bar lines down. We have to look down to find it, in case it is an
  [omitempty] stave with no data. If any of the suspended staves we skip over
  have got their break barline bit set, we must break the barline here. If the
  current stavespacing is zero, we don't want to extend bar lines. */

  /* Searching the bit maps for a bit higher than this one is tedious. Maybe
  there should be a macro, but I think we do it just this once... Nope, it
  comes again in setwarn. */

  another = (notsuspend[out_stave >> 5] & (-main_bit[out_stave & 0x1f])) >
    main_bit[out_stave & 0x1f];

  if (!another)
    for (i = (out_stave >> 5) + 1; i < STAVE_BITVEC_SIZE; i++)
      if (notsuspend[i] != 0) { another = TRUE; break; }

  if (another && out_sysblock->stavespacing[out_stave] > 0)
    {
    for (i = out_stave + 1; i <= out_laststave; i++)
      {
      stavestr *sss;
      if (mac_testNstave(notsuspend, i))
        {
        if (mac_teststave(curmovt->breakbarlines, i))
          breakbarline = TRUE;
        }
      else
        {
        sss = curmovt->stavetable[i];
        if (sss == NULL || !sss->omitempty ||
          sss->barindex[out_bar] != NULL ||
            (!out_lineendflag && sss->barindex[out_bar+1] != NULL))
              nextstave = i;
        break;
        }
      }
    }

  /* Initialize miscellaneous global variables. */

  out_pnum = 1;
  out_pden = 2;
  out_plet = NULL;
  out_tremolo = NULL;

  out_passedreset = out_lastnotebeamed = FALSE;
  out_lastnotex = -100000;                  /* for accidental stretching */

  out_moff = out_lastmoff = out_Xadjustment = out_Yadjustment = 0;

  out_gracenotes = FALSE;
  n_gracecount = n_gracemoff = out_keycount = out_timecount = 0;

  out_drawqueueptr = 0;
  out_textqueueptr = out_textnextabove = out_textnextbelow = 0;
  out_textX = NULL;

  out_stavelines = ss->stavelines & 127;  /* Without the "no clefs/keys" bit */
  out_stavetop = stave_tops[out_stavelines];
  out_stavebottom = stave_bottoms[out_stavelines];

  n_pitch = 0;            /* in case no items in the bar */
  n_ornament = NULL;
  n_masq = -1;
  n_dotxadjust = 0;

  /* Calculate the bottom position of the bar line. We need to do this first
  because it is used within the bar sometimes (dotted lines, time signatures,
  repeats, etc.) If a [breakbarline] directive is encountered, the value will
  be reset to out_ystave; if [unbreakbarline] is found, the value will be reset
  to out_deepbarend. */

  out_ybarend = out_deepybarend = out_ystave;

  if (nextstave > 0)
    {
    out_deepybarend += out_sysblock->stavespacing[out_stave] -
      16*curmovt->stavesizes[nextstave];
    if (!breakbarline) out_ybarend = out_deepybarend;
    }

  /* Loop through all items in the bar, if there are any */

  if (p != NULL)
    {
    int type = p->type;
    while (type != b_End)
      {
      if (type == b_Jump)
        {
        p = (bstr *)(((b_Jumpstr *)p)->next);
        }

      /* Deal with a note or chord */

      else if (type == b_note)
        {
        p = out_setnote((b_notestr *)p);
        }

      /* Deal with a non-note, and then switch off accidental stretching for
      the note which follows. */

      else
        {
        out_setother(p);
        out_lastnotex = -100000;
        }

      /* Next item */

      p = (bstr *)((uschar *)p + length_table[type]);
      type = p->type;
      }
    barlinestyle = ((b_Endstr *)p)->barlinestyle;
    }

  /* Non-existent bars take their barline style from the stave's default. This
  isn't entirely satisfactory, but copes with common cases. A value of 255
  means no barlinestyle was ever set for the stave. */

  else
    {
    if (ss->barlinestyle != 255) barlinestyle = ss->barlinestyle;
    }

  /*  ---- End of loop through bar ---- */


  /* If this was the last bar on the line, deal with things which can be
  continued onto the next line. */

  if (out_lineendflag)
    {
    slurstr *s = bar_cont->slurs;
    int true_endline = out_barlinex;

    if (curmovt->tiesoverwarnings && (out_sysblock->flags & sysblock_warn) != 0)
      {
      if ((out_sysblock->flags & sysblock_stretch) != 0)
        {
        true_endline = curmovt->linelength;
        }
      else
        {
        if ((bp+1)->vector != NULL)     /* BUG FIX 04-Apr-2003 */
          true_endline += ((bp+1)->vector + 1)->xoff;
        }
      }

    /* Draw slurs to line end. Note that misc_drawslur frees the slur
    structure, and we must free the pointer so that freeing the whole cont
    structure works. */

    bar_cont->slurs = NULL;
    while (s != NULL)
      {
      slurstr *snext = s->next;
      misc_drawslur(s, true_endline - 3000 + curmovt->endlinesluradjust, 0,
        TRUE);
      s = snext;
      }

    /* Draw ties and glissandos to line end. For glissandos, invent a
    right-hand pitch that is in the right direction usually. */

    if ((n_prevtie = bar_cont->tie) != NULL)
      {
      int x = true_endline - 4*main_stavemagn + curmovt->endlinetieadjust;
      int flags = n_prevtie->flags;

      n_flags = n_acflags = n_accleft = 0;
      n_notetype = breve;
      n_nexttie = NULL;

      /* Deal with ties. For chords we have to look ahead to the start of the
      next line to get the list of notes in the first chord. If there isn't a
      next bar, or if it is empty, draw ties on all the notes. */

      if ((flags & (tief_slur | tief_default)) != 0)
        {
        if (n_chordcount == 1) out_setnotetie(x, TRUE, flags); else
          {
          int count = 0;
          b_notestr *notelist[20];

          if (out_bar < curmovt->barcount)
            {
            stavestr *st = curmovt->stavetable[out_stave];
            bstr *pp = (st == NULL)? NULL : st->barindex[out_bar+1];

            if (pp != NULL)
              {
              int type = pp->type;
              while (type != b_End)
                {
                if (type == b_Jump)
                  pp = (bstr *)(((b_Jumpstr *)pp)->next);

                else if (type == b_note)
                  {
                  b_notestr *tp = (b_notestr *)pp;
                  do
                    {
                    notelist[count++] = tp;
                    mac_advancechord(tp);
                    }
                  while (tp->type == b_chord);
                  break;
                  }

                pp = (bstr *)((uschar *)pp + length_table[type]);
                type = pp->type;
                }
              }
            }

          if (count > 0)
            out_setchordtie(notelist, count, x, TRUE, flags);
          else out_setchordtie(out_notelist, n_chordcount, x, TRUE, flags);
          }
        }

      /* Deal with glissandos - single notes only */

      if ((flags & tief_gliss) != 0 && n_chordcount == 1)
        {
        b_notestr *pp =
          (ss == NULL)? NULL : (b_notestr *)(ss->barindex[out_bar+1]);
        if (pp != NULL && pp->type != b_note) pp = misc_nextnote(pp, NULL);
        if (pp == NULL) n_pitch = (n_pitch > P_3L)? P_0S : P_5S;
          else n_pitch = pp->spitch;
        out_glissando(x + (45*main_stavemagn)/10, flags);
        }
      }

    /* If there is a hairpin outstanding, draw an incomplete one */

    if (bar_cont->hairpin != NULL)
      out_drawhairpin(NULL, out_barlinex - 4*main_stavemagn);

    /* If there is an outstanding nth-time requirement at the end of the last
    bar on a line, output the marking so far. We have to search the next bar to
    see if it starts a new one, to determine whether to draw a right-hand jog
    or not. */

    if (bar_cont->nbar != NULL)
      {
      BOOL flag = FALSE;

      if (out_bar >= curmovt->barcount) flag = TRUE; else
        {
        bstr *pp = ss->barindex[out_bar+1];
        if (pp != NULL)
          {
          int ttype = pp->type;
          while (ttype != b_End)
            {
            if (ttype == b_Jump)
              pp = (bstr *)(((b_Jumpstr *)pp)->next);
            else if (ttype == b_nbar)
              {
              flag = TRUE;
              break;
              }
            pp = (bstr *)((uschar *)pp + length_table[ttype]);
            ttype = pp->type;
            }
          }
        }

      (void)out_drawnbar(flag, out_barlinex);
      out_freenbar();
      }

    /* Deal with outstanding underlay extensions or rows of hyphens at the end
    of the last bar on a line. In the case of hyphens, we must ensure that at
    least one hyphen is always output.

    Extension lines are drawn note by note, so a line to the last note on the
    stave will have been drawn. However, if the syllable continues on the next
    system, we would like to draw the line a bit longer. If the preceding note
    did not have an "=" associated with it, the extender won't have been drawn.
    We must cope with this case too. */

    while (bar_cont->ulay != NULL)
      {
      ulaystr *u = bar_cont->ulay;
      BOOL contflag = FALSE;
      BOOL overlay = u->level >= olay_offset;
      int xx = u->x;
      int yy = u->y;

      int fontsize = mac_muldiv(main_stavemagn,
        overlay?
          ((curmovt->fontsizes)->fontsize_text)[ff_offset_olay] :
          ((curmovt->fontsizes)->fontsize_text)[ff_offset_ulay],
        1000);

      if (xx == 0)  /* A complete system of hyphens or extender */
        {
        xx = out_sysblock->firstnoteposition +
          out_sysblock->xjustify - 4000;
        yy = overlay?
          out_sysblock->olevel[out_stave] :
          out_sysblock->ulevel[out_stave];
        contflag = TRUE;
        }

      /* Remove this block from the chain */

      bar_cont->ulay = u->next;

      /* Deal with row of hyphens */

      if (u->type == '-')
        {
        int xend = out_barlinex - 2000;
        if (xend - xx < 800) xend += 1000;
        if (xend - xx < 800) xend = xx + 801;  /* In case xx < 0 */
        if (u->htype == 0)
          out_hyphens(xx, xend, yy, fontsize, contflag);
        else
          out_repeatstring(xx, xend, yy, contflag, TRUE, u->htype);
        }

      /* Deal with extender line */

      else if (n_pitch != 0)
        {
        BOOL extender_continues = FALSE;
        int xend;

        /* See if the syllable continues on to the next system; we assume it
        does if we find a note before any text; or if we find an underlay text
        string beginning with "=". */

        if (out_bar < curmovt->barcount)
          {
          stavestr *st = curmovt->stavetable[out_stave];
          bstr *pp = (st == NULL)? NULL : st->barindex[out_bar+1];

          if (pp != NULL)
            {
            int type = pp->type;
            while (type != b_End)
              {
              if (type == b_Jump)
                pp = (bstr *)(((b_Jumpstr *)pp)->next);

              /* Note or chord => extender continues (unless rest) */

              else if (type == b_note)
                {
                extender_continues = ((b_notestr *)pp)->spitch != 0;
                break;
                }

              /* Underlay text before any notes means the syllable does not
              continue, unless it is "=". */

              else if (type == b_text)
                {
                b_textstr *t = (b_textstr *)pp;
                if ((t->flags & text_ul) != 0)
                  {
                  extender_continues = ((t->string)[0] == '=');
                  break;
                  }
                }

              /* Next item in the bar */

              pp = (bstr *)((uschar *)pp + length_table[type]);
              type = pp->type;
              }
            }
          }

        /* End depends on whether continuing or not */

        xend = extender_continues?
          out_barlinex - 4000 : n_x + 5*main_stavemagn;

        if (xend - xx > 4000)
          out_extension(xx, xend, yy, fontsize);
        }

      store_free(u);
      }
    }

  /* --- End of processing continued items --- */


  /* First of all, we must extend ybarend if it is not extended and the option
  to have full barlines at the end of each system is set. */

  if (out_lineendflag && out_ybarend == out_ystave && curmovt->fullbarend &&
    nextstave > 0) out_ybarend = out_deepybarend;

  /* If we have just printed a multi-bar rest, we must use the appropriate kind
  of bar line for the *last* bar. This requires a scan of the last bar.

  The last bar is also permitted to contain a right-hand repeat mark. If this
  is found, we output it at the barline position, as we know there can be no
  notes in the bar.

  Thirdly, the last bar is permitted to contain a clef at the end, or an
  invisible bar line. */

  if (out_manyrest > 1)
    {
    bstr *pp = (ss == NULL)? NULL : ss->barindex[out_bar+out_manyrest-1];

    if (pp != NULL)
      {
      int type = pp->type;
      while (type != b_End)
        {
        if (type == b_Jump)
          pp = (bstr *)(((b_Jumpstr *)pp)->next);

        else if (type == b_dbar) out_barchar = bar_double;

        else if (type == b_rrepeat)
          {
          int magn = (curmovt->barlinesize > 0)? curmovt->barlinesize : main_stavemagn;

          out_omitbarline = out_lastbarwide = TRUE;
          out_writerepeat(out_barlinex -
              ((out_lineendflag? 68 : 50)*magn)/10, rep_right, magn);
          }

        else if (type == b_clef || type == b_ibar)
          {
          out_setother(pp);
          }

        pp = (bstr *)((uschar *)pp + length_table[type]);
        type = pp->type;
        }
      }
    }

  /* Now we can output appropriate bits of bar line. Do not print a barline for
  staff 0, or if already done for repeat, or for [omitempty] bars containing no
  data. Do, however, print a leading barline for non-line-starting omitempty
  bars with nothing preceding. */

  if (out_stave != 0)
    {
    int ytop = out_ystave +
      ((barlinestyle == 2 || barlinestyle == 3)? 16*main_stavemagn :
      (ss->stavelines == 6)? - 4*main_stavemagn : 0);
    int ybarstart = ytop;
    int magn = (curmovt->barlinesize > 0)? curmovt->barlinesize : main_stavemagn;

    if (!out_omitbarline && (!ss->omitempty || (ss->barindex)[out_bar] != NULL))
      {
      if ((barlinestyle == 1 || barlinestyle == 3) && out_barchar == bar_single)
        out_barchar = bar_dotted;

      if (out_ybarend >= ybarstart)
        {
        int x = 0;
        if (out_barchar == bar_double) x = 2*magn;
        else if (out_barchar == bar_thick ||
                (out_bar + out_manyrest - 1 >= curmovt->barcount &&
                  !curmovt->unfinished))
          {
          x = 3500;
          ps_barline(out_barlinex - (3*magn)/2, ybarstart, out_ybarend,
            bar_thick);
          }

        /* Deal with bar line styles that involve either or both of lines on
        the stave and lines between the staves. */

        if (out_barchar == bar_thick)
          ps_barline(out_barlinex - x, ybarstart, out_ybarend, bar_single);
        else if (barlinestyle < 4 || out_barchar == bar_double)
          {
          ps_barline(out_barlinex - x, ybarstart, out_ybarend, out_barchar);
          }

        /* Deal with the special bar line styles that involve markings only on
        the current stave. */

        else
          {
          ps_musstring((barlinestyle == 4)?
            US"~x\302\211yyyyyyx\302\211" : US"|\302\211yyyyyyxxxxx\302\211",
            10*main_stavemagn, out_barlinex, out_ystave);
          }
        }
      }

    /* Flag wide bar line for next bar */

    if (out_barchar == bar_double) out_lastbarwide = TRUE;

    /* For omitempty bars, output a bit of bar line at the start of the bar, if
    the previous bar was not printed. If we have encountered a prevbarstr in
    the bar, a pointer to it will have been saved. As the style may be
    different to the ending line, we have to compute everything again. */

    if (ss->omitempty && (ss->barindex)[out_bar] != NULL)
      {
      int x = 0;

      if (!out_startlinebar && (ss->barindex)[out_bar - 1] == NULL)
        {
        int barchar = bar_single;
        int style = (ss->barlinestyle != 255)?
          ss->barlinestyle : curmovt->barlinestyle;

        if (out_prevbar != NULL)
          {
          if (out_prevbar->dbar) barchar = bar_double;
          if (out_prevbar->ibar) barchar = 0;
          style = out_prevbar->style;
          }

        ytop = (style == 2 || style == 3)?
          (out_ystave + 16*main_stavemagn) : out_ystave;
        ybarstart = ytop;

        if (out_ybarend >= ybarstart)
          {
          if ((style == 1 || style == 3) && barchar == bar_single)
            barchar = bar_dotted;

          if (barchar != 0)
            {
            if (style < 4 || barchar == bar_double)
              {
              if (barchar == bar_double) x = 2*main_stavemagn;
              ps_barline(out_lastbarlinex - x, ybarstart, out_ybarend, barchar);
              }
            else
              {
              ps_musstring((style == 4)?
                US"~x\302\211yyyyyyx\302\211" : US"|\302\211yyyyyyxxxxx\302\211",
                10*main_stavemagn, out_lastbarlinex, out_ystave);
              }
            }
          }
        }

      /* For staves with [omitempty] set, we have to generate a bit of stave
      for this bar at this point. Other stave lines are printed as complete
      systems. */

      if (ss->stavelines > 0)
        {
        ps_stave((!out_startlinebar)? out_lastbarlinex - x :
          out_sysblock->startxposition + out_sysblock->xjustify,
            out_ystave, out_barlinex, ss->stavelines & 127);
        }
      }
    }

  /* When we reach stave zero, we have to see which systems it is to be printed
  over. It can get printed several times, with vertical adjustments. If zcopy
  is NULL, we have completed the list. We have to maintain a separate contstr
  for each copy of stave zero; there is a space in the zcopy block for doing
  this.

  If this copy is required, set stave = 1 and break out of inner loop; the
  outer loop with then iterate for stave 0. If there is more than one stave
  zero being printed, we must switch in the separate contstr copies. */

  CHECKZCOPY:

  if (out_stave <= 1) while (zcopy != NULL)
    {
    if (zcopy->level >= 0)
      {
      out_ystave = out_yposition + zcopy->level - zcopy->adjust - zcopy->baradjust;
      zcopy->baradjust = 0;
      if (out_zcopycount > 1) out_cont = (contstr *)zcopy->cont;
      zcopy = zcopy->next;
      out_stave = 1;
      break;
      }

    /* If this copy is not required, set stave = 0 so that if the inner loop
    now terminates, the outer one will too. */

    out_stave = 0;
    zcopy = zcopy->next;
    }
  }

/* Restore the contstr pointer that might have been changed when printing
copies of stave zero. */

out_cont = out_cont_save;

/* Output bar number if required, above the top stave */

if (numberwanted > 0)
  {
  uschar s[12];
  int x = bp->barnoX;
  int y = 24000;
  int *matrix = (curmovt->fontsizes)->fontmatrix_barno;

  /* Adjust position for start and non-start bars */

  if (out_startlinebar)
    {
    x += out_sysblock->startxposition + out_sysblock->xjustify;
    if (bar_cont->clef == clef_trebledescant) x += 15000;
      else if (bar_cont->clef == clef_soprabass) x += 9000;
    }
  else
    {
    b_notestr *next = (lastp == NULL)? NULL :
      (lastp->type == b_note)? (b_notestr *)lastp :
        misc_nextnote((b_notestr *)lastp, NULL);
    x += out_lastbarlinex;
    if (next != NULL && next->spitch > P_5L)
      y = (next->spitch - 120) * 1000;
    }

  /* Now print it */

  y = ((y + bp->barnoY)*main_stavemagn)/1000  + curmovt->barno_level;
  sprintf(CS s, "%d", numberwanted);
  if (matrix != NULL) memcpy(font_transform, matrix, 4*sizeof(int));
  out_string(s, curmovt->font_barnumber, (curmovt->fontsizes)->fontsize_barno,
    x, out_yposition - y, curmovt->barno_textflags);

  font_reset();
  }

/* Remember the position of the last barline, and return the number of the
following bar. */

out_lastbarlinex = out_barlinex;
DEBUG(("out_setbar() end\n"));
return out_bar + out_manyrest;
}


/* End of setbar.c */
