#include "post_mus.h"

int     textunderend = 0,
        textoverend = 0;	/* for length of text */

int     heightsofar = 0;	/* total height of pictures */

extern int  in_beam;		/* whether currently in a beam */

extern struct barls barlv[];

char    baraccid[7];		/* whether this note is already n_accid in
				   this bar */
char    prevbaraccid[7];	/* whether this note was left n_accid in
				   last bar */

setpiece () {
    int     height,
            i;
    if (set_monitor == 2)
	fprintf (stderr, "Title: %s\n", piecev.left_title);
/*     print_ties( 1 ); */
    part_now = notev[0].n_part;
    staff_now = partv[part_now].pt_end_stave;
    offset_now = staffv[0][staff_now].s_key_offset;
    key_now = piecev.p_root;
    prev_key = 0;
    bar0start = 0;
    if (n_staffs > 1) {
	for (i = 0; i < n_staffs; i++)
	    if (bar0start < textwidth (staffv[0][i].s_instrument))
		bar0start = textwidth (staffv[0][i].s_instrument);
	bar0start += barlv[BLLEFT].offset;
    }
    for (bar = 0; bar <= piecev.p_bars; bar++) {
	setwidths (bar, 1);
    }
/*     print_ties( 2 ); */
    key_now = piecev.p_root;
    for (bar = 0; bar <= piecev.p_bars; bar++) {
	setbeam (bar, beamslope);
    }
/*     print_ties( 3 ); */
    in_tie = 0;
    for (bar = 0; bar <= piecev.p_bars; bar++) {
	setheights (bar);
    }
/*     print_ties( 4 ); */
    setstaves ();
/*     print_ties( 5 ); */
    for (stave = 0; stave < n_staves; stave++) {
	settxhts (stave);
    }
/*     print_ties( 6 ); */
    for (bar = 0; bar <= piecev.p_bars; bar++)
	setbeam (bar, beamslope);
/*     print_ties( 7 ); */
    for (stave = 0; stave < n_staves; stave++)
	setties (stave);
/*     print_ties( 8 ); */
    staveheights ();
/*     print_ties( 9 ); */
    if (set_monitor == 3)
	for (bar = 0; bar <= piecev.p_bars; bar++) {
	    barprint (bar);
	}
    height = stavev[0].s_y_wrt_page + staffv[0][0].s_y_wrt_stave
	+ staffv[0][0].sf_maxy - staffv[n_staves - 1][n_staffs - 1].sf_miny;
    heightsofar += height;
    if (set_monitor == 2)
	fprintf (stderr,
		"bps %d; height %3.1fi total so far %3.1fi\n",
		bps_now,
		height * 1.0 / reduction,
		heightsofar * 1.0 / reduction
	    );
}

setheights (bar) {		/* set heights of text, note max and mins
				   for bar */
    int     i,
            notemin,
            notemax,
            part;
    struct bars *barp = barv + bar;
    struct notes   *notep = notev + barp -> b_first_note;
    barp -> b_miny = -HALFSTAVE;
    barp -> b_maxy = HALFSTAVE;
    for (i = barp -> b_first_note; i < barp -> b_last_note; i++, notep++) {
	if (notep -> stickup == 0) {/* no stick, semibreve? */
	    notemin = notep -> n_y_wrt_staff - HALFLINE;
	    notemax = notep -> n_y_wrt_staff + HALFLINE;
	    if (notep -> n_tnote) {
		notemax += textheight (notep -> n_tnote);
	    }
	}
	else
	    if (notep -> stickup > 0) {/* stick up */
		notemin = notep -> n_y_wrt_staff - HALFLINE;
		notemax = notep -> n_y_end_stick;
		if (notep -> n_tnote) {
		    notemin -= textheight (notep -> n_tnote);
		}
	    }
	    else {		/* stick down */
		notemin = notep -> n_y_end_stick;
		notemax = notep -> n_y_wrt_staff + HALFLINE;
		if (notep -> n_tnote) {
		    notemax += textheight (notep -> n_tnote);
		}
	    }
	if (notemin > -HALFSTAVE)
	    notemin = -HALFSTAVE;
	if (notemax < HALFSTAVE)
	    notemax = HALFSTAVE;
	notep -> n_miny = notemin;
	notep -> n_maxy = notemax;
    }
    for (i = barp -> b_first_note, notep = notev + i;
	    i < barp -> b_last_note;
	    i++, notep++) {
	notemin = notep -> n_miny;
	notemax = notep -> n_maxy;
	part = notep -> n_part;
    /* check notes for length of text */
	if (notep -> n_tover) {
	    notep -> n_yover = notemax;
	    notemax += textheight (notep -> n_tover);
	}
	if (notep -> n_tunder) {
	    notep -> n_yunder = notemin;
	    notemin -= textheight (notep -> n_tunder);
	}
	notep -> n_miny = notemin;
	notep -> n_maxy = notemax;
	in_tie += notep -> n_tie_start;
	notemax += in_tie * TIEHT;
	in_tie -= notep -> n_tie_end;
	if (barp -> b_miny > notemin)
	    barp -> b_miny = notemin;
	if (barp -> b_maxy < notemax)
	    barp -> b_maxy = notemax;
	if (barp -> b_yunder[part] > notemin)
	    barp -> b_yunder[part] = notemin;
	if (barp -> b_yover[part] < notemax)
	    barp -> b_yover[part] = notemax;
    }
    if (barp -> b_tover[0]) {
	barp -> b_yover[0] = barp -> b_maxy;
	barp -> b_maxy += textheight (barp -> b_tover[0]);
    }
    if (barp -> b_tunder[0]) {
	barp -> b_yunder[0] = barp -> b_miny;
	barp -> b_miny -= textheight (barp -> b_tunder[0]);
    }
}

setstaves () {
    int     note,
            move;
    struct staves  *stavep = stavev;
    struct bars *barp = barv;
    int     stff;
    stave = 0;
    staff = 0;
    bar = 0;
    x_now = bar0start;
    width_now = page_width;
    for (bar = 0, barp = barv;
	    bar == 0 || (barv[bar - 1].b_last_note <= barv[bar - 1].b_first_note);
	    bar++, barp++
	) {
	barp -> b_x_wrt_staff = x_now;

	bps_now = piecev.p_bps;
	if (barp -> b_bps)
	    bps_now = barp -> b_bps;

	if (barp -> b_key)
	    key_now = barp -> b_key;
	else
	    barp -> b_key = key_now = piecev.p_root;

	if (barp -> b_n_tsig)
	    tsig_n_now = barp -> b_n_tsig;
	else
	    barp -> b_n_tsig = tsig_n_now = piecev.p_tsig_n;
	if (barp -> b_d_tsig)
	    tsig_d_now = barp -> b_d_tsig;
	else
	    barp -> b_d_tsig = tsig_d_now = piecev.p_tsigd;

	clef_now = barp -> b_clef[staff];
	for (stff = 0; stff < n_staffs; stff++)
	    if (barp -> b_clef[stff])
		clefs_now[stff] = barp -> b_clef[stff];
	    else
		barp -> b_clef[stff] = clefs_now[stff];

	if (!clefsig)
	    for (stff = 0; stff < n_staffs; stff++)
		barp -> b_clef[stff] = 0;

	if (!timesig)
	    barp -> b_n_tsig = barp -> b_d_tsig = 0;

	if (!keysig)
	    barp -> b_key = 0;

	setwidths (bar, 0);

	if (set_monitor == 2) {
	    fprintf (stderr, "Bar %d; clefs", bar);
	    for (stff = 0; stff < n_staffs; stff++)
		fprintf (stderr, " %d",
			barp -> b_clef[stff]);
	    fprintf (stderr, ";key %d; tsig %d %d\n",
		    barp -> b_key, barp -> b_n_tsig, barp -> b_d_tsig);
	}
    }
    bar--;
    barp--;
    stavep -> s_first_bar = bar;
    x_now = bar0start;
    while (bar <= piecev.p_bars && stave < NSTAVES) {
	if (barp -> b_key)
	    key_now = barp -> b_key;
	if (barp -> b_n_tsig) {
	    tsig_n_now = barp -> b_n_tsig;
	    tsig_d_now = barp -> b_d_tsig;
	}
	barp -> b_x_wrt_staff = x_now;
	x_now += barp -> b_width;
	if (x_now >= width_now * 19 / 20 - hgap/* leave some leeway */
		|| (bps_now
		    && (bar - (stavep -> s_first_bar ? stavep -> s_first_bar : 1)) == bps_now)
		|| (barp - 1) -> b_new_stave
	    ) {			/* end of stave */
	    if (x_now >= width_now - hgap)
		stavep -> s_x_right = barp -> b_x_wrt_staff;
	    else
		stavep -> s_x_right = barp -> b_x_wrt_staff + barp -> b_width;
	    stavep -> s_last_bar = bar;
	    spreadbars (stave, bar - stavep -> s_first_bar);

	    stave++;
	    stavep++;
/* set up first bar of new stave */
	    stavep -> s_first_bar = bar;

	    if (barp -> b_bps)
		bps_now = barp -> b_bps;
	    else
		barp -> b_bps = bps_now;

	    if (barp -> b_s_width)
		width_now = barp -> b_s_width;

	    if (barp -> b_n_tsig) {
		tsig_n_now = barp -> b_n_tsig;
		tsig_d_now = barp -> b_d_tsig;
	    }
	    else
		if (stave == 0 && timesig) {
		    barp -> b_n_tsig = tsig_n_now;
		    barp -> b_d_tsig = tsig_d_now;
		}
	    if (set_monitor == 3 && barp -> b_n_tsig)
		fprintf (stderr, "Bar %d timesig %d,%d; ",
			bar, barp -> b_n_tsig, barp -> b_d_tsig);

	    if (barp -> b_key) {
		key_now = barp -> b_key;
	    }
	    if (keysig) {
		barp -> b_key = key_now;
	    }
	    if (set_monitor == 3 && barp -> b_key)
		fprintf (stderr, "Newstave bar %d keysig %d; ", bar, barp -> b_key - 8);

	    if (barv[bar - 1].b_end_type == BLRPTR) {
		barv[bar - 1].b_end_type = BLTHICKL;
		barv[bar].b_stt_type =
		    stavev[stave].s_fst_bar_type = BLRPTR;
	    }
	    else
		if (barv[bar - 1].b_end_type == BLRPTB) {
		    barv[bar - 1].b_end_type = BLRPTL;
		    barv[bar].b_stt_type =
			stavev[stave].s_fst_bar_type = BLRPTR;
		}
		else
		    barv[bar].b_stt_type =
			stavev[stave].s_fst_bar_type = 0;

	    for (stff = 0; stff < n_staffs; stff++) {
		if (barp -> b_clef[stff]) {
		    clefs_now[stff] = barp -> b_clef[stff];
		}
		else
		    if (clefsig) {
			barp -> b_clef[stff] = clefs_now[stff];
		    }
		if (set_monitor == 3 && barp -> b_clef[stff])
		    fprintf (stderr,
			    "Bar %d clefsig staff %d clef %d; ",
			    bar, stff, barp -> b_clef[stff]);
	    }

	    if (set_monitor == 3)
		fprintf (stderr, "\n");
	    barp -> b_x_wrt_staff = 0;
	    setwidths (bar, 0);

	    if (leadsig) {	/* line up first bar under bar 1 */
		move = barv[0].b_width + barv[1].b_note_start - barp -> b_note_start;
		if (move > 0) {
		    for (note = barp -> b_first_note; note < barp -> b_last_note; note++)
			notev[note].n_x_wrt_bar += move;
		    barp -> b_width += move;
		    barp -> b_note_start += move;
		}
	    }
	    x_now = bar0start + barp -> b_width +
		stavev[stave].s_fst_bar_type == BLRPTR ?
		atom[barlv[BLRPTR].atomno].a_width : 0;
	}			/* if end-of-line */

	if (barp -> b_bps)
	    bps_now = barp -> b_bps;
	if (barp -> b_s_width)
	    width_now = barp -> b_s_width;
	if (barp -> b_n_tsig) {
	    tsig_n_now = barp -> b_n_tsig;
	    tsig_d_now = barp -> b_d_tsig;
	}
	for (stff = 0; stff < n_staffs; stff++)
	    if (barp -> b_clef[stff]) {
		clefs_now[stff] = barp -> b_clef[stff];
	    }
	bar++;
	barp++;
    }				/* while bar < n_bars ... */
    stavep -> s_x_right = barv[bar - 1].b_x_wrt_staff + barv[bar - 1].b_width;
     /* x_now */ ;
    stavep -> s_last_bar = bar;
    spreadbars (stave, bar - stavep -> s_first_bar);
 /*    (barp-1)->b_new_stave== 0 && bar-stavep->s_first_bar<bps_now ); */
    stave++;
    stavep++;
    n_staves = stave;
}

staveheights () {		/* set heights of staves on page */
    int     staff,
            stave;
    for (stave = n_staves - 1; stave >= 0; stave--) {
	for (staff = n_staffs - 1; staff >= 0; staff--) {
	    if (staff == n_staffs - 1)
		staffv[stave][staff].s_y_wrt_stave = 100;
	    else
		staffv[stave][staff].s_y_wrt_stave =
		    staffv[stave][staff + 1].s_y_wrt_stave
		    + staffv[stave][staff + 1].sf_maxy - staffv[stave][staff].sf_miny;
	    if (set_monitor == 2)
		fprintf (stderr,
			"stave %d staff %d y %d maxy %d miny %d\n",
			stave, staff, staffv[stave][staff].s_y_wrt_stave,
			staffv[stave][staff].sf_maxy,
			staffv[stave][staff].sf_miny);
	}			/* end for each staff */
	if (stave == n_staves - 1)
	    stavev[n_staves - 1].s_y_wrt_page = 0;
	else
	    stavev[stave].s_y_wrt_page =
		stavev[stave + 1].s_y_wrt_page
		+ staffv[stave + 1][0].s_y_wrt_stave + staffv[stave + 1][0].sf_maxy
		- staffv[stave][n_staffs - 1].s_y_wrt_stave
		- staffv[stave][n_staffs - 1].sf_miny;
	stavev[stave].sv_maxy =
	    stavev[stave].s_y_wrt_page
	    + staffv[stave][0].s_y_wrt_stave
	    + staffv[stave][0].sf_maxy;
	stavev[stave].sv_miny =
	    stavev[stave].s_y_wrt_page
	    + staffv[stave][n_staffs - 1].s_y_wrt_stave
	    + staffv[stave][n_staffs - 1].sf_miny;
	if (set_monitor == 2)
	    fprintf (stderr,
		    "stave %d y %d max %d min %d\n",
		    stave, stavev[stave].s_y_wrt_page,
		    stavev[stave].sv_maxy,
		    stavev[stave].sv_miny);
    }				/* end for each stave */
}


setcoord (beat, all) {		/* return ywrtstave */
    struct notes   *notep = notev + beat;
    int     p = notep -> n_pitch - 'a',
            o = notep -> n_octv - '0',
            l = notep -> n_length,
            w = 0,		/* note width */
            move,
            n,
            k,
            staff = notep -> n_staff,
            noteclef;
    if (part_now != notep -> n_part) {
	part_now = notep -> n_part;
	x_now = barv[bar].b_note_start;
	textoverend = textunderend = 0;
    }
    staff_now = partv[part_now].pt_end_stave;
    offset_now = key_now - 8 + staffv[0][staff_now].s_key_offset;
    noteclef = staffv[0][staff].s_clef;
    p += offset_now;
    o += staffv[0][staff_now].s_octv;
    if (notep -> n_tover && x_now < textoverend)
	x_now = textoverend;
    if (notep -> n_tunder && x_now < textunderend)
	x_now = textunderend;
    notep -> n_x_wrt_bar = x_now;
    notep -> n_head_x = 0;
    notep -> n_x_stick = 0;

 /* >=256 breve, .+64 hollow, else solid */
    notep -> n_width = w = notewidth (beat);

    if (notep -> n_beam > 0)
	in_beam = 1;

    if (notep -> n_pitch == RESTSYM || notep -> n_pitch == IRESTSYM) {
    /* rest */
	notep -> n_accid = ' ';
	setrest (notep -> n_length, &notep -> n_width);
	if ( set_monitor == 4 )
	    noteprint( beat );
	return;
    }
    if (p < 0)
	p += 12;
    if (p >= 21)
	p -= 12;
    if (p < 0 || p >= 21) {
	ioerror ("Error bar %d note %d\n",
		bar, beat - barv[bar].b_first_note + 1);
	abandon (1);
    }
    n = scale[p][0];		/* this note */
    k = scale[8 + offset_now][0];/* key note */
    if (k < 'c' || n < k)
	o++;
    if (k < 'c' && n < k)
	o++;
    notep -> n_y_wrt_staff =
	n - 'a' + 7 * o - clef[noteclef].offset;
    notep -> n_y_wrt_staff *= HALFLINE;
    notep -> n_miny = notep -> n_y_wrt_staff - HALFLINE;

    if (all) {
    /* set n_accids */
	if (notep -> n_pitch >= 'h' && notep -> n_pitch <= 'n') {
	    if (getaccid (notep -> n_pitch) == ' ') {
		if (nat_mode == 0 || prevgetaccid (notep -> n_pitch) == ' ') {
		    notep -> n_accid = ' ';
		}
		else {
		    notep -> n_accid =
			scale[p][1] == ' ' ? '=' : scale[p][1];
		    prevsetaccid (notep -> n_pitch, ' ');
		}
	    }
	    else {		/* n_accid already set in this bar */
		notep -> n_accid = scale[p][1] == ' ' ? '=' : scale[p][1];
		setaccid (notep -> n_pitch, ' ');
	    }
	}
	else {			/* pitch not in basic 7 notes of scale */
	    if (scale[p][1] == ' ') {
		notep -> n_accid = '=';
	    }
	    else {
		notep -> n_accid = scale[p][1];
	    }
/* cancel if n_accid already in force in this bar */
	    if (notep -> n_accid == getaccid (notep -> n_pitch))
		notep -> n_accid = ' ';
	    else
		setaccid (notep -> n_pitch, notep -> n_accid);
	}
    }

    if (notep -> n_accid != ' ') {
	move = atom[
		notep -> n_accid == '+' ? SHARP :
		notep -> n_accid == '-' ? FLAT :
		notep -> n_accid == '=' ? NATURAL : 0
	    ].a_width + hgap / 2;
	notep -> n_width += move;
	notep -> n_head_x += move;
	notep -> n_x_stick += move;
    }

    if (notep -> n_tnote) {
	move = textwidth (notep -> n_tnote + 1) + hgap / 2;
	switch (*(notep -> n_tnote)) {
	    case '<': 		/* text to left of note */
		notep -> n_width += move;
		notep -> n_head_x += move;
		notep -> n_x_stick += move;
		break;
	    case '>': 		/* text to right of note */
		notep -> n_width += move;
		break;
	}
    }

 /* sort out length */
    if (l >= SBL) {		/* no stick */
	notep -> stickup = notep -> n_y_end_stick = 0;
    }
    else
	if (
	  notep -> stickup < 0 || /* already set down */
	    (notep -> stickup == 0 && /* could go either way */
	     ( (notep -> n_y_wrt_staff > up_down_border) || /* blob above */
	      notep -> n_y_wrt_staff == up_down_border /* still either way */
		&& choosedown( beat )
	     )
	    )
	) { /* set stick down */
	    notep -> stickup = -1;
	    notep -> n_y_end_stick =
		notep -> n_y_wrt_staff - atom[STICK].height;
	    if (notep -> n_y_end_stick < barv[bar].b_miny)
		barv[bar].b_miny = notep -> n_y_end_stick;
	}
	else { /* set stick up */
	    notep -> stickup = 1;
	    notep -> n_x_stick += w;
	    notep -> n_y_end_stick =
		notep -> n_y_wrt_staff + atom[STICK].height;
	    if (notep -> n_y_end_stick > barv[bar].b_maxy)
		barv[bar].b_maxy = notep -> n_y_end_stick;
	}

 /* set hooks */
    if (all) {
	notep -> n_hooks = 1;
	while (l >= 32) {
	    notep -> n_hooks--;
	    l = l / 2;
	}
	while (l && l < 16) {
	    notep -> n_hooks++;
	    l = l * 2;
	}
	l -= 16;
	notep -> n_dots = 0;
	if (l == 8) {
	    notep -> n_width += atom[DOT].a_width;
	    notep -> n_dots = 1;
	}
	else
	    if (l == 12) {
		notep -> n_width += 2 * atom[DOT].a_width;
		notep -> n_dots = 2;
	    }
    }
    else
	notep -> n_width += notep -> n_dots * atom[DOT].a_width;

 /* if stickup && n_hooks>0 and few dots then width += hookwidth */
    if (notep -> stickup > 0 && notep -> n_hooks > 0 && in_beam == 0)
	notep -> n_width += atom[TOPHOOK].a_width;
    x_now += notep -> n_width + hgap;
    if (notep -> n_beam < 0)
	in_beam = 0;

 /* set text ending as minimum position for next text */
    if (notep -> n_tover) {
	textoverend = notep -> n_x_wrt_bar + textwidth (notep -> n_tover);
	notep -> n_yover = HALFSTAVE;
	if (notep -> stickup > 0) {/* check on stick end */
	    if (notep -> n_y_end_stick > HALFSTAVE)
		notep -> n_yover = notep -> n_y_end_stick;
	}
	else {			/* look at blob */
	    if (notep -> n_y_wrt_staff > HALFSTAVE)
		notep -> n_yover = notep -> n_y_wrt_staff + HALFLINE;
	}
    }
    if (notep -> n_tunder) {
	textunderend = notep -> n_x_wrt_bar + textwidth (notep -> n_tunder);
	notep -> n_yunder = -HALFSTAVE;
	if (notep -> stickup < 0) {/* stick down, look at stickend */
	    if (notep -> n_y_end_stick < -HALFSTAVE)
		notep -> n_yunder = notep -> n_y_end_stick;
	}
	else {			/* look at blob */
	    if (notep -> n_y_wrt_staff < -HALFSTAVE)
		notep -> n_yunder = notep -> n_y_wrt_staff - HALFLINE;
	}
    }
 /* frig lengths */
 /* triple */
    if (all && beat > 1 && (notep - 1) -> n_tnote) {
	switch (*(notep - 1) -> n_tnote) {
	    case '3': 
	    /* fprintf( stderr, "triple %d,%d\n", beat-1, beat+1 ); */
		(notep - 2) -> n_length = ((notep - 2) -> n_length * 2 + 1) / 3;
		(notep) -> n_length = ((notep) -> n_length * 2 + 1) / 3;
		(notep - 1) -> n_length =
		    (notep - 1) -> n_length * 2 - (notep) -> n_length - (notep - 2) -> n_length;
		(notep - 1) -> n_mus_wrt_bar = (notep - 2) -> n_mus_wrt_bar + (notep - 2) -> n_length;
		(notep) -> n_mus_wrt_bar = (notep - 1) -> n_mus_wrt_bar + (notep - 1) -> n_length;
		break;
	}
    }
    if (set_monitor == 4)
	noteprint (beat);
    return;			/* notep->n_y_wrt_staff; */
}

setwidths (bar, all) {		/* set all aspects if "all" */
    int     i;
    struct bars *barp = barv + bar;

    in_beam = 0;
    barp -> b_width = 0;
    for (i = 0; i < 7; i++) {
	prevbaraccid[i] = baraccid[i];
	baraccid[i] = ' ';
    }
    textoverend = 0;
    textunderend = 0;
    staff = 0;

    x_now = set_note_start( bar );

    for (ALLBTS) {
	setcoord (beat, all);
    }

    if (x_now < textoverend)
	x_now = textoverend;
    if (x_now < textunderend)
	x_now = textunderend;
    barp -> b_width = x_now + atom[barlv[barp -> b_end_type].atomno].a_width;
}

textwidth (s) char *s;		/* width occupied by string */
/* should really be looked up in font tables */
{
    int     l = 0,
            max = 0;
    char   *ss = s;
    while (*s) {
	if (*s == ESCAPE) {
	    l--;
	    s++;
	    if (*s == '(') {	/* nroff char '\(sh' */
		l++;
		s += 2;
	    }
	    else
		if (*s == 's') {/* size change */
		    s++;
		    if (*s != '0')
			s++;
		}
		else
		    if (*s == 'd' || *s == 'u') {
			;
		    }
		    else
			if (*s == 'v' || *s == 'h') {
			    s++;
			    while (*++s && *s != '\'');
			}
	}
	else
	    if (*s == '\n') {
		if (max < l)
		    max = l;
		l = -1;
	    }
	s++;
	l++;
    }
    if (max < l)
	max = l;
    if (set_monitor && max > 3)
	fprintf (stderr, "Text width %2d string \"%s\"\n", max, ss);
    return max * 7 + hgap;	/* 7 is average character width */
}

textheight (s) char *s;		/* height of text */
{
    int     h = 1;
    if (*s == 0)
	return 0;
    if (*s != ESCAPE) {
	while (*s) {
	    if (*s == '\n')
		h++;
	    s++;
	}
	return TEXTHT * h;
    }
    switch (*(s + 1)) {
	case '1': 
	case '2': 
	    return TEXTHT + 3;
	case 'b': 
	    return TEXTHT + 6;
	case 'c': 
	    return TEXTHT + 8;
    }
    return TEXTHT;
}

#ifdef junk
accidwidth (beat) {		/* width of the n_accid and half-gap */
    char    c = notev[beat].n_accid;
    return
	c == ' ' ? 0 :
	c == '+' ? atom[SHARP].a_width + hgap / 2 :
	c == '-' ? atom[FLAT].a_width + hgap / 2 :
	c == '=' ? atom[NATURAL].a_width + hgap / 2 :
	0;
}
#endif

notewidth (beat) {		/* blob width */
    int     l = notev[beat].n_length;
    return
	l < 64 ? atom[SOLID].a_width :
	l < SBL ? atom[HOLLOW].a_width :
	l < 256 ? atom[SEMIBREVE].a_width :
	atom[BREVE].a_width;
}

clearaccid () {			/* clear n_accids */
    int     i;
    for (i = 0; i < 7; i++)
	baraccid[i] = prevbaraccid[i] = ' ';
}

getaccid (p) {			/* get currently set n_accid for pitch */
    int     i = (p - 'h' + 14) % 7;
    char    c = baraccid[i];
    if (c != ' ' && set_monitor == 5)
	fprintf (stderr, "Getaccid bar %d pitch %d %c accid \"%c\"\n",
		bar, i, scale[i + key_now - 1][0], c);
    return c;
}

setaccid (p, a) char    a;	/* set current bar accid for p to a */
{
    int     i = (p - 'h' + 14) % 7;
    if (set_monitor == 5)
	fprintf (stderr, "Set accid bar %d pitch %d %c accid \"%c\"\n",
		bar, i, scale[i + key_now - 1][0], a);
    baraccid[i] = a;
}

prevgetaccid (p) {		/* get currently set n_accid for pitch */
    int     i = (p - 'h' + 14) % 7;
    char    c = prevbaraccid[i];
    if (c != ' ' && set_monitor == 2)
	fprintf (stderr, "Cancelled n_accid bar %d note %d pitch \"%c\" accid \"%c\"\n",
		bar, beat - barv[bar].b_first_note + 1, scale[i + key_now - 1][0], c);
    return c;
}

prevsetaccid (p, a) char    a;	/* set current bar accid for p to a */
{
    int     i = (p - 'h' + 14) % 7;
    if (set_monitor == 5)
	fprintf (stderr, "Cancelled n_accid bar %d pitch \"%c\" accid \"%c\"\n",
		bar, scale[i + key_now - 1][0], a);
    prevbaraccid[i] = a;
}

setrest (l, w) int *w;		/* put symbol for rest of length l */
{
    int     a = atom[
	        l >= 256 ? BREREST :
	        l >= SBL ? SBRREST :
	        l >= 64 ? MINREST :
	        l >= 32 ? CROREST :
	        l >= 16 ? QUAREST :
	        l >= 8 ? SQUREST :
	        DSQREST
    ].      a_width;
    x_now += a;
    *w = a;
    while (l % 2 == 0)
	l /= 2;
    if (l == 3)
	*w += atom[DOT].a_width;
    if (l == 7)
	*w += 2 * atom[DOT].a_width;

    return;
}

sigwidth (k) {			/* width of key k, k== 8 is C */
    int     nsharps = 0,
            nflats = 0,
            nnats = 0;
    k -= 8;
    if (prev_key > 0 && k >= 0 && k < prev_key)
	nnats = prev_key - k;
    if (prev_key < 0 && k <= 0 && k > prev_key)
	nnats = k - prev_key;
    if (k > 0)
	nsharps = k;
    if (k < 0)
	nflats = -k;
    prev_key = k;
    return nsharps * atom[SHARP].a_width +
	nflats * atom[FLAT].a_width +
	(nat_mode == 2 ? nnats * atom[NATURAL].a_width : 0);
}

set_note_start( bar )
{
    struct bars *barp = barv+bar;
    int x_now = hgap;

    if (barp -> b_clef[staff]) {
	clefs_now[staff] = clef_now = barp -> b_clef[staff];
	x_now += atom[clef[clef_now].atomno].a_width + hgap;
    }

    if (barp -> b_key) {
	x_now += sigwidth (barp -> b_key) + hgap;
	key_now = barp -> b_key;
    }

    if (barp -> b_n_tsig) {
	x_now += atom[TSIG].a_width + hgap;
	tsig_n_now = barp -> b_n_tsig;
	tsig_d_now = barp -> b_d_tsig;
	if (tsig_n_now > 9) /* two digits ! */
	    x_now += atom[TSIG].a_width;
	piecev.p_bar_length = (SBL / tsig_d_now) * tsig_n_now;
    }

    if (barp -> b_stt_type) {
	x_now += atom[barlv[barp -> b_stt_type].atomno].a_width + hgap;
    }

    if (barp -> b_note_start < x_now)
	barp -> b_note_start = x_now;

    return x_now;
}

choosedown( beat ) /* choose whether stick goes down */
{
    struct notes *notep = notev + beat;
    int lastnote = beat-1, nextnote = beat+1;
    int part = notep->n_part;
    while ( lastnote > 0 && notev[ lastnote].n_part != part )
	lastnote--;
    while ( nextnote < piecev.p_nnotes  && notev[ nextnote].n_part != part )
	nextnote++;
    if ( lastnote > 0 && nextnote < piecev.p_nnotes )
	return (notev[lastnote].n_y_wrt_staff + notev[nextnote].n_y_wrt_staff)
		    >= 2 * up_down_border;
    else
	return 0;
}
