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

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

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


/* This file contains code for outputting warning key/time signatures, in a
pseudo-bar at the end of a line. */

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



/*************************************************
*             Output warning bar                 *
*************************************************/

/* We have to take care that multiple items on different sized staves line up.
This is somewhat messy, but it's easier to isolate the whole thing here in one
function than to spread it about with zillions of conditionals in the normal
setting code.

Arguments:  none
Returns:    nothing
*/

void
out_warnbar(void)
{
BOOL done= FALSE;
int x = out_barx;
int count;

/* Loop for each column of signatures */

for (count = 0; !done; count++)
  {
  int maxwidth = 0;
  int ystave = out_yposition;
  int stave;

  /* Done remains TRUE if we don't actually print anything */

  done = TRUE;
  for (stave = 1; stave <= out_laststave; stave++)
    {
    if (mac_teststave2(curmovt->staves, out_sysblock->notsuspend, stave))
      {
      bstr *p = ((curmovt->stavetable)[stave])->barindex[out_bar];

      if (p != NULL)
        {
        int type = p->type;
        int thiscount = count;

        mac_setstavesize(stave);

        while (type != b_End)
          {
          switch(type)
            {
            case b_Jump:
            p = (bstr *)(((b_Jumpstr *)p)->next);
            break;

            case b_note:     /* Give up when hit a note */
            goto ENDSTAVE;
            break;

            case b_time:
            if (thiscount-- <= 0)
              {
              b_timestr *t = (b_timestr *)p;
              int xx = x;
              int spacing = (count == 0)? curmovt->timespacing :
                                          curmovt->startline->timespace;
              int width = spacing +
                mac_muldiv(main_stavemagn, misc_timewidth(t->time) + 1000, 1000);
              if (width > maxwidth) maxwidth = width;
              if (count == 0) xx -= 2000;
              out_writetime(xx + spacing, ystave, t->time);
              done = FALSE;
              goto ENDSTAVE;
              }
            break;

            /* If the key signature is C major (= 2), ignore it completely.
            This occurs only when there has been a change to C major from some
            other key, and it follows the cancellation signature. Leaving it in
            messes up the spacing for any subsequent time signature. */

            case b_key:
            if (((b_keystr *)p)->key != 2 && thiscount-- <= 0)
              {
              b_keystr *k = (b_keystr *)p;
              int xx = x;
              int spacing = curmovt->keyspacing;
              int width = spacing +
                mac_muldiv(main_stavemagn, 
                           misc_keywidth(k->key, out_cont[stave].clef) + 1000,
                           1000);
              if (width > maxwidth) maxwidth = width;

              if (curmovt->keydoublebar && !out_lastbarwide)
                {
                int i;
                int ybarend = ystave;
                BOOL another =
                   (out_sysblock->notsuspend[stave >>5] & (-main_bit[stave & 0x1f])) >
                     main_bit[stave & 0x1f];
                if (!another)
                  for (i = (stave >> 5) + 1; i < stave_bitvec_size; i++)
                    if (out_sysblock->notsuspend[i] != 0) { another = TRUE; break; }
                if (another && mac_testNstave(curmovt->breakbarlines, stave))
                  ybarend += out_sysblock->stavespacing[stave];
                ps_barline(out_lastbarlinex, ystave, ybarend, bar_double);
                }
              else xx -= 1000;
              out_writekey(xx + spacing, ystave, out_cont[stave].clef, k->key);
              done = FALSE;
              goto ENDSTAVE;
              }
            break;
            }

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

      ENDSTAVE:
      ystave += out_sysblock->stavespacing[stave];
      }
    }
  x += maxwidth;
  }

/* Set a "last bar line" value as it is used for the stave length */

out_lastbarlinex = (out_sysblock->flags & sysblock_stretch)?
  curmovt->linelength : x + 2000;
}

/* End of setwarn.c */
