2 /* Copyright (c) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 by Arkkra Enterprises */
3 /* All rights reserved */
5 /* miscellaneous utility functions for music publication program, mostly
6 * for the print phase */
12 static void grp_octave_adjust
P((struct GRPSYL
*gs_p
, int adj
, struct MAINLL
*mll_p
));
13 static void set_height_blockhead
P((struct BLOCKHEAD
*blockhead_p
, int context
,
14 struct MAINLL
*mll_p
));
15 static double coord_staffscale
P((float *coord_array
));
19 /* set _cur location variable to specified value */
24 float x
, y
; /* x, east, and west get set to x value. y, north and south,
25 * get set to y value */
28 float *cur_p
; /* coord array for _cur in current context */
31 /* look up _cur symbol and fill in the values */
32 cur_p
= symval("_cur", (float **) 0);
33 cur_p
[AX
] = cur_p
[AE
] = cur_p
[AW
] = x
;
34 cur_p
[AY
] = cur_p
[AN
] = cur_p
[AS
] = y
;
38 /* set the values for location variable _win */
43 float n
, s
, e
, w
; /* north, south, east, and west */
46 float *window
; /* coordinate info for _win */
49 /* look up symbol and fill in values */
50 window
= symval("_win", (float **) 0);
55 /* set x and y to midpoints of rectangle */
56 window
[AY
] = s
+ (n
- s
)/2.0;
57 window
[AX
] = w
+ (e
- w
)/2.0;
61 /* Return width of a bar line. Allow a couple pixels on either side
62 * of the actual line(s) [and dots]. Does not include user padding.
63 * Since an invisbar has no lines or dots, it has zero width.
69 struct BAR
*bar_p
; /* return width of this bar line */
72 if (bar_p
== (struct BAR
*) 0) {
76 switch(bar_p
->bartype
) {
95 return(2.0 * HALF_RESTART_WIDTH
);
101 pfatal("bad bar type");
111 /* Normally, we want some padding on both sides of a bar line,
112 * but at the end of a staff, we don't want right padding.
113 * This applies either if we are at the right
114 * margin or if the next bar is a restart.
115 * This function returns how much to adjust an end-of-score bar line
116 * eastward to make it at the right edge of the score.
120 eos_bar_adjust(bar_p
)
122 struct BAR
*bar_p
; /* the bar to adjust */
127 halfbarwidth
= width_barline(bar_p
) / 2.0;
128 switch (bar_p
->bartype
) {
130 return(halfbarwidth
- STDPAD
- (W_NORMAL
/ PPI
/ 2.0));
132 return(halfbarwidth
- (W_NORMAL
/ PPI
/ 2.0));
134 return(halfbarwidth
- (4.0 * STDPAD
) - (W_WIDE
/ PPI
/ 2.0));
136 return(halfbarwidth
- (2.0 * STDPAD
) - (W_WIDE
/ PPI
/ 2.0));
144 /* width of clef, keysig, timesig */
147 width_clefsig(clefsig_p
)
149 struct CLEFSIG
*clefsig_p
; /* return width of this clefsig */
152 /* we just call the routine to print a clefsig, but with
153 * flag to tell it to not really print */
154 return(pr_clefsig((struct MAINLL
*) 0, clefsig_p
, NO
));
158 /* translate clef name to clef output character */
163 int clef
; /* TREBLE, etc */
178 /* everything else uses the C clef */
184 /* Returns width of the given clef in inches in the default size.
185 * If is_small is YES, give width of the 3/4 sized one used in mid-score,
186 * rather than the full-sized used at beginning of line.
187 * Caller must adjust by staffscale if they need that.
188 * No padding is included beyond the padding of the clef music character
189 * itself, so caller needs to add any they deem appropriate for aesthetics.
193 clefwidth(clef
, is_small
)
195 int clef
; /* TREBLE, BASS, ALTO, FRENCHVIOLIN, etc */
196 int is_small
; /* If YES, assume mid-score clef, not full sized one */
199 return(width(FONT_MUSIC
, (is_small ?
(3 * DFLT_SIZE
) / 4 : DFLT_SIZE
),
204 /* Returns where the given clef's baseline should be
205 * relative to the middle line of the staff, in stepsizes.
206 * (Above the middle line is positive, below is negative).
207 * If north_p and/or south_p are non-null, the relative north/south values
208 * of the clef are returned via the pointers. These will be relative
209 * to the middle line of the staff and will be in inches
210 * in the default staffscale, using default size
211 * (unless is_small == YES, in which case it will be 3/4 size).
212 * Note that this should not be called with TABCLEF or NOCLEF.
216 clefvert(clef
, is_small
, north_p
, south_p
)
218 int clef
; /* TREBLE, BASS, ALTO, FRENCHVIOLIN, etc */
219 int is_small
; /* If YES, assume mid-score clef, not full sized one.
220 * Note that if both of the following arguments are null,
221 * this is_small argument's value is actually irrelevent. */
222 float *north_p
; /* if non-null, relative north will be returned here */
223 float *south_p
; /* if non-null, relative south will be returned here */
226 int steps
; /* relative to middle line, to be returned */
263 pfatal("clefvert called with invalid clef %d", clef
);
265 steps
= 0; /* shut up bogus compiler warning */
269 /* If caller wants relative north/south values, calculate them */
270 if (north_p
!= 0 || south_p
!= 0) {
271 char muschar
; /* music character to print for the clef */
273 char tr8str
[4]; /* "8" of treble8 or 8treble */
274 float value
; /* of north or south */
276 muschar
= clefchar(clef
);
277 clefsize
= (is_small ?
(3 * DFLT_SIZE
) / 4 : DFLT_SIZE
);
284 value
= (float) ascent(FONT_MUSIC
, clefsize
, muschar
);
285 if (clef
== TREBLE_8A
) {
286 value
+= (float) strheight(tr8str
);
288 *north_p
= value
+ (float)(steps
* STEPSIZE
);
292 value
= (float) descent(FONT_MUSIC
, clefsize
, muschar
);
293 if (clef
== TREBLE_8
) {
294 value
+= (float) strheight(tr8str
);
296 *south_p
= -value
+ (float)(steps
* STEPSIZE
);
304 /* Given a BLOCKHEAD, fill in its height. BLOCKHEADs are a bit strange,
305 * in that they are in a separate coordinate space of unknown size.
306 * So we start out assuming it is infinitely thin. Then we check
307 * each string in the list and keep track of the lowest one, by
308 * pretending to go where it would be printed and adding the descent
309 * of the string. At the end, the height must be the page height minus the
310 * lowest, since upwards is positive */
313 set_height_blockhead(blockhead_p
, context
, mll_p
)
315 struct BLOCKHEAD
*blockhead_p
; /* which block to get height of */
316 int context
; /* C_HEADER, etc */
317 struct MAINLL
*mll_p
; /* for getting margin overrides */
320 float distance
; /* of headfoot from bottom of page */
322 float x_offset
; /* because of justification */
323 float yval
; /* y coordinate value */
324 struct PRINTDATA
*pr_p
; /* walk through list of things to print */
325 float block_width
; /* page width minus margins */
326 float s_descent
; /* strdescent() of the current string */
327 float extra
; /* how much farther the string descended
328 * than would be expected of a normal,
330 struct MAINLL
*rightmargin_mll_p
; /* mll_p to use for
331 * finding the right margin */
334 /* Set _win in this context to zero height at top margin */
336 rightmargin_mll_p
= (mll_p ? mll_p
->next
: 0);
337 set_win_coord(blockhead_p
->c
);
338 set_win(PGHEIGHT
- EFF_TOPMARGIN
, PGHEIGHT
- EFF_TOPMARGIN
,
339 PGWIDTH
- eff_rightmargin(rightmargin_mll_p
),
340 eff_leftmargin(mll_p
));
341 block_width
= PGWIDTH
- eff_rightmargin(rightmargin_mll_p
) -
342 eff_leftmargin(mll_p
);
344 if (blockhead_p
->printdata_p
!= (struct PRINTDATA
*) 0) {
345 /* set current to left corner */
346 set_cur(eff_leftmargin((struct MAINLL
*)0),
347 PGHEIGHT
- EFF_TOPMARGIN
);
351 /* Process each item in the list */
352 for (pr_p
= blockhead_p
->printdata_p
;
353 pr_p
!= (struct PRINTDATA
*) 0;
356 /* If this is a paragraph,
357 * split it into as many lines as needed. */
358 if (pr_p
->justifytype
== J_JUSTPARA
||
359 pr_p
->justifytype
== J_RAGPARA
) {
360 pr_p
->string
= split_string(pr_p
->string
,
363 pr_p
->width
= strwidth(pr_p
->string
);
364 /* stretch justified paragraphs to full width */
365 if (pr_p
->justifytype
== J_JUSTPARA
&&
366 pr_p
->width
< block_width
) {
367 pr_p
->width
= block_width
;
370 /* adjust for justification */
371 switch (pr_p
->justifytype
) {
374 x_offset
= pr_p
->width
;
378 x_offset
= pr_p
->width
/ 2.0;
386 /* set current to specified location */
387 yval
= inpc_y (&(pr_p
->location
), (char *) 0, -1);
388 set_cur( inpc_x( &(pr_p
->location
), (char *) 0, -1 )
391 /* if user said to go off of south or y of _win,
392 * change to equivalent offset off of north of _win.
393 * because the south and y could change */
394 if (pr_p
->location
.vtype
== AS
||
395 pr_p
->location
.vtype
== AY
) {
396 if (pr_p
->location
.vert_p
== blockhead_p
->c
) {
397 pr_p
->location
.vtype
= AN
;
398 pr_p
->location
.vsteps
= (yval
399 - (PGHEIGHT
- EFF_TOPMARGIN
)
404 /* determine lowest descent of current string */
405 if (pr_p
->isPostScript
== YES
) {
409 s_descent
= strdescent(pr_p
->string
);
411 lowest
= _Cur
[AY
] - s_descent
;
413 /* if lowest of anything found so far, note that */
414 if ( lowest
< distance
) {
416 set_win(PGHEIGHT
- EFF_TOPMARGIN
, distance
,
417 PGWIDTH
- eff_rightmargin((struct MAINLL
*)0),
418 eff_leftmargin((struct MAINLL
*)0));
421 /* Set to end of string just "printed."
422 * If the string when down farther than a single line
425 if (pr_p
->isPostScript
== YES
) {
429 extra
= s_descent
- fontdescent(pr_p
->string
[0],
435 set_cur( _Cur
[AX
] + pr_p
->width
, _Cur
[AY
] - extra
);
438 /* set height to lowest distance encountered */
439 blockhead_p
->height
= (PGHEIGHT
- distance
- EFF_TOPMARGIN
);
443 /* empty header/footer */
444 blockhead_p
->height
= 0.0;
447 /* if was a footer, now we can set the actual _win coordinates,
448 * by offsetting from bottom of page instead of top */
449 if ( (context
== C_FOOTER
) || (context
== C_FOOT2
) ) {
450 set_win(EFF_BOTMARGIN
+ blockhead_p
->height
, EFF_BOTMARGIN
,
451 PGWIDTH
- eff_rightmargin((struct MAINLL
*)0),
452 eff_leftmargin((struct MAINLL
*)0));
458 /* Calculate the height of all blocks, including headers and footers,
459 * and fill in the height field of the struct. */
465 struct MAINLL
*mll_p
;
466 double topheight
= -1.0; /* if > 0.0, is height of "top" */
467 double botheight
= -1.0; /* if > 0.0, is height of "bottom" */
469 debug(2, "calc_block_heights");
471 set_height_blockhead(&Header
, C_HEADER
, 0);
472 set_height_blockhead(&Footer
, C_FOOTER
, 0);
473 set_height_blockhead(&Header2
, C_HEAD2
, 0);
474 set_height_blockhead(&Footer2
, C_FOOT2
, 0);
476 /* set main _win to space within margins and header/footer
480 /* set the size of _page */
481 _Page
[AW
] = _Page
[AS
] = 0.0;
483 _Page
[AN
] = PGHEIGHT
;
484 _Page
[AX
] = PGWIDTH
/ 2.0;
485 _Page
[AY
] = PGHEIGHT
/ 2.0;
487 /* now calculate top/bot and any other blocks in the main list */
489 for (mll_p
= Mainllhc_p
; mll_p
!= 0; mll_p
= mll_p
->next
) {
490 if (mll_p
->str
== S_SSV
) {
491 /* keep margins up to date */
492 asgnssv(mll_p
->u
.ssv_p
);
494 else if (mll_p
->str
== S_FEED
) {
495 if (mll_p
->u
.feed_p
->top_p
!= 0) {
496 set_height_blockhead(mll_p
->u
.feed_p
->top_p
,
498 if (topheight
< 0.0) {
499 /* save for setting music _win */
500 topheight
= mll_p
->u
.feed_p
->top_p
->height
;
503 if (mll_p
->u
.feed_p
->top2_p
!= 0) {
504 set_height_blockhead(mll_p
->u
.feed_p
->top2_p
,
507 if (mll_p
->u
.feed_p
->bot_p
!= 0) {
508 set_height_blockhead(mll_p
->u
.feed_p
->bot_p
,
510 if (botheight
< 0.0) {
511 /* save for setting music _win */
512 botheight
= mll_p
->u
.feed_p
->bot_p
->height
;
515 if (mll_p
->u
.feed_p
->bot2_p
!= 0) {
516 set_height_blockhead(mll_p
->u
.feed_p
->bot2_p
,
520 else if (mll_p
->str
== S_BLOCKHEAD
) {
521 set_height_blockhead(mll_p
->u
.blockhead_p
,
526 set_win(PGHEIGHT
- EFF_TOPMARGIN
- Header
.height
527 - (topheight
> 0.0 ? topheight
: 0.0),
528 EFF_BOTMARGIN
+ Footer
.height
529 + (botheight
> 0.0 ? botheight
: 0.0),
530 PGWIDTH
- eff_rightmargin((struct MAINLL
*)0),
531 eff_leftmargin((struct MAINLL
*)0));
535 /* return number of beams or flags to use for a given basic time */
540 int btime
; /* basic time of note to be checked */
545 /* no beams for long notes */
550 /* number of beams is equal to the number of bits 4 has to be
551 * shifted left in order to equal the given basic time */
552 for (n
= 1; (4 << n
) <= MAXBASICTIME
; n
++) {
553 if (btime
== (4 << n
)) {
561 /* given an accidental (#, &, x, B, n) return its music character
562 * C_SHARP, etc of the proper size. If not a valid accidental,
590 /* get the absolute x and y values for an INPCOORD */
591 /* get the proper one of the coordinates of the specified location, and
592 * add in any offsets */
595 inpc_x(inpcoord_p
, fname
, lineno
)
597 struct INPCOORD
*inpcoord_p
; /* return the x value of this inpcoord */
598 char *fname
; /* filename, for error message */
599 int lineno
; /* for error message */
605 /* if hor_p is null, then this is an absolute coord, rather
606 * than relative to some variable */
607 if (inpcoord_p
->hor_p
== (float *) 0) {
608 if (inpcoord_p
->counts
!= 0.0) {
609 /* parser should have blocked this case */
610 pfatal("can't specify time offset if no variable specified");
612 retval
= inpcoord_p
->hsteps
* STEPSIZE
;
615 /* X location is the x, e, or w value of the specified location
616 * variable, plus any offset plus any time offset */
618 retval
= inpcoord_p
->hor_p
[ inpcoord_p
->htype
]
619 + inpcoord_p
->hsteps
* STEPSIZE
620 * coord_staffscale(inpcoord_p
->hor_p
)
621 + ( inpcoord_p
->counts
* inpcoord_p
->hor_p
[INCHPERWHOLE
] /
622 (double) Score
.timeden
);
625 if (retval
< 0.0 || retval
> PGWIDTH
) {
626 if (lineno
> 0 && fname
!= (char *) 0) {
627 l_warning(fname
, lineno
,
628 "x value of %f is off the page", retval
);
635 /* given an inpcoord, return its y coordinate */
638 inpc_y(inpcoord_p
, fname
, lineno
)
640 struct INPCOORD
*inpcoord_p
; /* return y value of this inpcoord */
641 char *fname
; /* filename, for error message */
642 int lineno
; /* for error message */
648 /* if vert_p is null, then this is absolute rather than relative */
649 if ( inpcoord_p
->vert_p
== (float *) 0) {
650 retval
= inpcoord_p
->vsteps
* STEPSIZE
;
653 /* Y value is y, n, or s value of specified location variable
654 * plus any vertical offset plus any vsteps offset */
656 retval
= inpcoord_p
->vert_p
[ inpcoord_p
->vtype
]
657 + (inpcoord_p
->vsteps
* STEPSIZE
658 * coord_staffscale(inpcoord_p
->vert_p
));
661 if (retval
< 0.0 || retval
> PGHEIGHT
) {
662 if (lineno
> 0 && fname
!= (char *) 0) {
663 l_warning(fname
, lineno
,
664 "y value of %f is off the page", retval
);
671 /* Given an INPCOORD, return the appropriate staffscale value. Look
672 * up which staff, if any, the INPCOORD is associated with, and then get
673 * the staffscale out of the SSVs.
677 coord_staffscale(coord_array
)
682 struct COORD_INFO
*coord_info_p
;
685 /* figure out what staffscale value to use, based on
686 * which staff the coordinate is associated with */
687 if ((coord_info_p
= find_coord(coord_array
))
688 != (struct COORD_INFO
*) 0 &&
689 coord_info_p
->staffno
!= 0) {
690 return(svpath(coord_info_p
->staffno
, STAFFSCALE
)->staffscale
);
698 /* return the y coordinate of the end of a note stem */
699 /* (the end farthest from the note head) */
704 struct GRPSYL
*gs_p
; /* which group to get the stem of */
708 if (gs_p
== (struct GRPSYL
*) 0) {
709 pfatal("null group passed to find_y_stem");
712 if (gs_p
->nnotes
== 0) {
713 pfatal("group with no notes passed to find_y_stem (from line %d, grpcont %d)",
714 gs_p
->inputlineno
, gs_p
->grpcont
);
717 /* if stem is up, start at bottom note, if down at top */
718 if (gs_p
->stemdir
== UP
) {
719 return(gs_p
->notelist
[ gs_p
->nnotes
- 1].c
[AY
] + gs_p
->stemlen
);
722 return(gs_p
->notelist
[0].c
[AY
] - gs_p
->stemlen
);
727 /* return x coordinate of a note stem */
732 struct GRPSYL
*gs_p
; /* return x of stem of this group */
735 double stem_adjust
; /* to overlap the note head */
737 if ( gs_p
== (struct GRPSYL
*) 0) {
738 pfatal("bad group passed to find_x_stem");
741 /* if called with something longer than a half note, then there
742 * is no real stem. We must be being called for printing slashes,
743 * so in that case, the x of the "stem" is the x of the group */
744 if (gs_p
->basictime
< 2) {
748 /* move stem by half of stem width so edge lines up with edge of note */
749 stem_adjust
= W_NORMAL
/ PPI
/ 2.0;
750 if (gs_p
->stemdir
== UP
) {
751 stem_adjust
= -stem_adjust
;
753 return(gs_p
->c
[AX
] + (gs_p
->stemx
+ stem_adjust
) * Staffscale
);
757 /* return the width of a key signature in inches */
760 width_keysig(sharps
, naturals
)
762 int sharps
; /* how many sharps to print, or if negative, how many flats. */
763 int naturals
; /* how many naturals to print for canceling previous key */
766 double total_width
= 0.0;
769 /* In keysig, things are drawn closer together than
770 * in other places, so to get the total width, we first
771 * multiply the width of the sharp, flat, or natural character
772 * by the number of times it is to be printed, then subtract off
773 * two points for each character printed, except for naturals,
774 * which are only jammed together by one point. */
776 size
= adj_size(DFLT_SIZE
, Staffscale
, (char *) 0, -1);
778 total_width
= (width(FONT_MUSIC
, size
, C_SHARP
) - 2.0 * Stdpad
)
781 else if (sharps
<= -1) {
782 /* negative sharps are flats */
783 total_width
= (width(FONT_MUSIC
, size
, C_FLAT
) - 2.0 * Stdpad
)
787 total_width
+= (width(FONT_MUSIC
, size
, C_NAT
) - Stdpad
)
788 * abs(naturals
) + 3.0 * Stdpad
;
796 * Abstract: Find next GRPSYL in this voice (same measure or not).
798 * Returns: Pointer to the GRPSYL, or 0 if none.
800 * Description: This function, given a GRPSYL and the MLL structure it hangs
801 * off of, returns the next GRPSYL in this voice, even if it's in
802 * the next measure. If it is in the next measure, *mll_p_p gets
803 * updated. But if that next measure is a second or later ending,
804 * it's not considered to be a "next" measure, so return 0.
808 nextgrpsyl(gs_p
, mll_p_p
)
810 struct GRPSYL
*gs_p
; /* the given GRPSYL */
811 struct MAINLL
**mll_p_p
; /* main linked list structure it is hanging off of */
814 struct MAINLL
*mll_p
; /* point at a MLL item */
815 int endingloc
; /* of the following barline */
818 /* if not at end of measure, just return the next GRPSYL */
819 if (gs_p
->next
!= 0) {
823 mll_p
= *mll_p_p
; /* save original MLL item */
826 * We hit the end of the measure. We need to find the first group in
827 * the next measure. Find the coming bar line, then the corresponding
828 * staff in the next measure. We do this in case the number of staffs
829 * changes back and forth; we don't want to find the staff in some
832 for (*mll_p_p
= (*mll_p_p
)->next
; *mll_p_p
!= (struct MAINLL
*) 0 &&
833 (*mll_p_p
)->str
!= S_BAR
; *mll_p_p
= (*mll_p_p
)->next
) {
837 /* if we hit the end of the MLL, there is no next GRPSYL */
838 if (*mll_p_p
== (struct MAINLL
*) 0) {
839 return (struct GRPSYL
*) 0;
842 /* we found a bar; get its endingloc */
843 endingloc
= (*mll_p_p
)->u
.bar_p
->endingloc
;
846 * Search for this staff in next measure. If we find a pseudobar while
847 * doing this, save its endingloc in preference to the real bar's.
849 for (*mll_p_p
= (*mll_p_p
)->next
; *mll_p_p
!= (struct MAINLL
*) 0 &&
850 (*mll_p_p
)->str
!= S_BAR
&&
851 ((*mll_p_p
)->str
!= S_STAFF
||
852 (*mll_p_p
)->u
.staff_p
->staffno
!= gs_p
->staffno
);
853 *mll_p_p
= (*mll_p_p
)->next
) {
855 if ((*mll_p_p
)->str
== S_CLEFSIG
&&
856 (*mll_p_p
)->u
.clefsig_p
->bar_p
!= (struct BAR
*) 0) {
857 endingloc
= (*mll_p_p
)->u
.clefsig_p
->bar_p
->endingloc
;
861 /* if we hit the end or another bar before finding our staff, return */
862 if (*mll_p_p
== (struct MAINLL
*) 0 || (*mll_p_p
)->str
== S_BAR
) {
863 return (struct GRPSYL
*) 0;
867 * We found the appropriate staff in the next measure. But if we have
868 * crossed into a second or later ending, this bar doesn't really
869 * "follow" the previous bar, and we must return null. So if endingloc
870 * shows this is the case, we must search backwards to find out if we
871 * were already in an ending.
873 if (endingloc
== STARTITEM
) {
874 while (mll_p
!= 0 && mll_p
->str
!= S_BAR
&& (mll_p
->str
!=
875 S_CLEFSIG
|| mll_p
->u
.clefsig_p
->bar_p
== 0))
878 /* set endingloc of the previous measure */
881 } else if (mll_p
->str
== S_BAR
) {
882 endingloc
= mll_p
->u
.bar_p
->endingloc
;
884 endingloc
= mll_p
->u
.clefsig_p
->bar_p
->endingloc
;
887 /* if we were already in an ending, there's no next GRPSYL */
888 if (endingloc
== STARTITEM
|| endingloc
== INITEM
) {
889 return (struct GRPSYL
*) 0;
893 /* return the first GRPSYL of the appropriate voice */
894 return ((*mll_p_p
)->u
.staff_p
->groups_p
[ gs_p
->vno
- 1 ]);
900 * Abstract: Find previous GRPSYL in this voice (same measure or not).
902 * Returns: Pointer to the GRPSYL, or 0 if none.
904 * Description: This function, given a GRPSYL and the MLL structure it hangs
905 * off of, returns the previous GRPSYL in this voice, even if it's
906 * in an earlier measure. If we are at the start of an ending,
907 * it skips over any previous ending and goes to the measure
908 * preceding the first ending. If the resulting GRPSYL is in a
909 * previous measure, *mll_p_p gets updated.
913 prevgrpsyl(gs_p
, mll_p_p
)
915 struct GRPSYL
*gs_p
; /* the given GRPSYL */
916 struct MAINLL
**mll_p_p
; /* main linked list structure it is hanging off of */
919 struct GRPSYL
*gs2_p
; /* for looping through prev measure's list */
920 struct BAR
*bar_p
; /* point at a bar line */
921 struct MAINLL
*mll_p
; /* point at a MLL item */
922 int pseudo
; /* was the last thing we saw a pseudobar? */
923 int barcount
; /* how many bar lines we looped backward thru*/
924 int safmoae
; /* "started at first measure of an ending" */
927 /* if not at start of measure, just return the previous GRPSYL */
928 if (gs_p
->prev
!= (struct GRPSYL
*) 0) {
933 * We hit the start of the measure. Loop backwards through the MLL
934 * looking for the bar line at the start of the "previous" measure.
935 * If our measure is not the first measure of an ending, this is
936 * simply the bar at the start of the previous measure. Otherwise,
937 * this is the bar before the measure before the first ending. Also
938 * handle the cases where we fall off the start of the MLL.
946 /* find preceding bar or pseudobar, if either exists */
947 for (mll_p
= mll_p
->prev
; mll_p
!= (struct MAINLL
*) 0 &&
948 mll_p
->str
!= S_BAR
&&
949 (mll_p
->str
!= S_CLEFSIG
||
950 mll_p
->u
.clefsig_p
->bar_p
== 0);
951 mll_p
= mll_p
->prev
) {
956 * If we hit the start of the MLL without crossing any bars, or
957 * just a pseudobar, there is no preceding GRPSYL, so return 0.
958 * (Depending on who is calling this function, the pseudobar at
959 * the start of the song may or may not exist.) Otherwise, it
960 * must be that we started in the second measure, or an ending
961 * that we skipped over started there. Point at the start of
962 * the MLL, and get out of the loop. Note that we can't still
963 * be in the process of skipping over endings: no ending can
964 * start at the first measure of the song, because there is no
968 if (barcount
== 0 || (barcount
== 1 && pseudo
== YES
)) {
969 return (struct GRPSYL
*) 0;
978 * Point bar_p at the relevant bar/pseudobar for checking the
979 * endingloc. If this is a pseudobar, it's relevant. If this
980 * is a bar, it's relevant only if it's the first thing we've
981 * seen, or the thing we saw last was not a pseudobar. That
982 * is, the endingloc of the bar at the end of a score is to be
983 * ignored, because the true endingloc has been moved to the
984 * next score's pseudobar. We need to worry about this because
985 * of the case where a second ending starts at the start of the
986 * new score (STARTITEM) and the previous score ends with
987 * ENDITEM, which should be ignored.
989 if (mll_p
->str
== S_BAR
) {
990 if (bar_p
== 0 || pseudo
== NO
) {
991 bar_p
= mll_p
->u
.bar_p
;
994 barcount
--; /* forget this bar */
998 bar_p
= mll_p
->u
.clefsig_p
->bar_p
;
1003 * If this is the first measure we're backing into, and this
1004 * first bar we hit shows that our GRPSYL was in the first
1005 * measure of an ending, remember that fact.
1007 if (barcount
== 1 && bar_p
->endingloc
== STARTITEM
) {
1012 * Get out, when, in the normal case, we've hit the second meaningful
1013 * bar; or in the safmoae case, we've skipped back to the back before
1014 * the first bar of the first ending.
1016 } while (! ( (safmoae
== NO
&& barcount
== 2) || (safmoae
== YES
&&
1017 (bar_p
->endingloc
== NOITEM
|| bar_p
->endingloc
== ENDITEM
))));
1020 * Search forward to the next bar, which is the bar before which we
1021 * want to find a GRPSYL. We don't care about pseudobars here.
1023 for (mll_p
= mll_p
->next
; mll_p
->str
!= S_BAR
; mll_p
= mll_p
->next
) {
1028 * Now mll_p is the bar before which we want to find the GRPSYL.
1029 * Find the corresponding staff in the previous measure. We do
1030 * this in case the number of staffs changes back and forth; we
1031 * don't want to find the staff in some earlier measure.
1034 /* search for this staff in previous measure */
1035 for (*mll_p_p
= mll_p
->prev
; *mll_p_p
!= (struct MAINLL
*) 0 &&
1036 (*mll_p_p
)->str
!= S_BAR
&&
1037 ((*mll_p_p
)->str
!= S_STAFF
||
1038 (*mll_p_p
)->u
.staff_p
->staffno
!= gs_p
->staffno
);
1039 *mll_p_p
= (*mll_p_p
)->prev
) {
1043 /* if we hit the start or another bar before finding our staff, return*/
1044 if (*mll_p_p
== (struct MAINLL
*) 0 || (*mll_p_p
)->str
== S_BAR
) {
1045 return (struct GRPSYL
*) 0;
1048 /* return the last GRPSYL of the appropriate voice */
1049 gs2_p
= (*mll_p_p
)->u
.staff_p
->groups_p
[ gs_p
->vno
- 1 ];
1050 if (gs2_p
== (struct GRPSYL
*) 0) {
1053 while (gs2_p
->next
!= (struct GRPSYL
*) 0) {
1054 gs2_p
= gs2_p
->next
;
1061 /* if user asked for octave marks, we need to transpose any affected notes
1062 * by the appropriate number of octaves. This should be called for a measure
1063 * at a time. It will handle all the octave marks
1064 * within the measure for the current voice, both those carrying over into
1065 * this measure and ones starting there. If an octave mark spills beyond
1066 * the end of the measure, the amount to transpose and how long to do so
1067 * is saved away for use in the next measure. Checks for things becoming
1068 * out of range because of the transposition are not done here; caller
1069 * must do that if they care. */
1072 octave_transpose(staff_p
, mll_p
, vno
, normdir
)
1074 struct STAFF
*staff_p
;
1075 struct MAINLL
*mll_p
; /* staff_p connects here, used for bends */
1076 int vno
; /* voice number */
1077 int normdir
; /* YES if should move note pitches up for above and
1078 * down for below. NO if the inverse should be done */
1081 struct GRPSYL
*gs_p
; /* walk through list of GRPSYLs */
1082 struct GRPSYL
*gs_roll_p
; /* group generated for a roll */
1083 struct STUFF
*stuff_p
; /* to look for octave marks */
1084 RATIONAL total_time
; /* accumulated time in measure */
1085 float float_total_time
; /* for comparing with count */
1086 int carry_adjust
; /* adjust to carry into next measure */
1087 int carry_bars
; /* how many bars to carry over */
1088 float carry_counts
; /* how many counts in final bar */
1089 int staffno
; /* which staff we are working with */
1092 staffno
= staff_p
->staffno
;
1093 carry_adjust
= carry_bars
= 0;
1096 /* if currently have octave mark */
1097 if (Octave_adjust
[staffno
] != 0) {
1099 /* if bar count > 0, transpose all notes in measure */
1100 if (--(Octave_bars
[staffno
]) > 0) {
1102 for (gs_p
= staff_p
->groups_p
[vno
];
1103 gs_p
!= (struct GRPSYL
*) 0;
1104 gs_p
= gs_p
->next
) {
1106 grp_octave_adjust(gs_p
, Octave_adjust
[staffno
], mll_p
);
1110 /* otherwise just transpose until specified time */
1113 for (gs_p
= staff_p
->groups_p
[vno
];
1114 gs_p
!= (struct GRPSYL
*) 0;
1115 gs_p
= gs_p
->next
) {
1117 float_total_time
= RAT2FLOAT(total_time
)
1118 * Score
.timeden
+ 1.0;
1120 if (float_total_time
<= Octave_count
[staffno
]) {
1121 grp_octave_adjust(gs_p
,
1122 Octave_adjust
[staffno
], mll_p
);
1127 total_time
= radd(total_time
, gs_p
->fulltime
);
1130 Octave_adjust
[staffno
] = 0;
1134 /* go through stuff list. If any octave marks, transpose appropriate
1135 * notes in this measure. If extends to next measure, remember for
1136 * next time. If user put in more than one octave
1137 * mark going over the bar, catch that. If there are overlaps within
1138 * a measure, it seems like too much trouble to catch this, so just
1139 * transpose as often as they say and let them figure out why it
1141 for (stuff_p
= staff_p
->stuff_p
; stuff_p
!= (struct STUFF
*) 0;
1142 stuff_p
= stuff_p
->next
) {
1144 if (stuff_p
->stuff_type
== ST_OCTAVE
) {
1146 if (Octave_adjust
[staffno
] != 0) {
1147 l_warning(stuff_p
->inputfile
,
1148 stuff_p
->inputlineno
,
1149 "overlapping octave marks");
1152 /* figure out how many octaves to move */
1153 Octave_adjust
[staffno
] = parse_octave(stuff_p
->string
,
1154 stuff_p
->place
, stuff_p
->inputfile
,
1155 stuff_p
->inputlineno
);
1157 /* if this call is for inverse transpostion, adjust
1158 * to go in opposite direction */
1159 if (normdir
== NO
) {
1160 Octave_adjust
[staffno
] *= -1;
1163 /* figure out to which count the octave mark applies
1164 * within this measure. */
1165 Octave_count
[staffno
] = (stuff_p
->end
.bars
> 0 ?
1.0 +
1166 RAT2FLOAT(Score
.time
) * Score
.timeden
1167 : stuff_p
->end
.count
);
1170 for (gs_p
= staff_p
->groups_p
[vno
];
1171 gs_p
!= (struct GRPSYL
*) 0;
1172 gs_p
= gs_p
->next
) {
1174 float_total_time
= RAT2FLOAT(total_time
) *
1175 Score
.timeden
+ 1.0;
1176 if (float_total_time
>= stuff_p
->start
.count
) {
1178 if (float_total_time
<=
1179 Octave_count
[staffno
]) {
1180 /* is within the mark, so move */
1181 grp_octave_adjust(gs_p
,
1182 Octave_adjust
[staffno
],
1186 /* special case. If we have a rolled
1187 * chord, and user specified
1188 * an octave mark without a til clause,
1189 * all the chords that got
1190 * generated internally to cause the
1191 * "roll" effect need to be transposed,
1192 * even though they have been moved
1194 if (float_total_time
== stuff_p
->start
.count
1195 && stuff_p
->end
.bars
== 0
1196 && stuff_p
->end
.count
== 0.0
1197 && gs_p
->inputlineno
< 0) {
1199 /* adjust all the groups generated
1200 * to create the roll effect */
1201 for (gs_roll_p
= gs_p
->next
;
1202 gs_roll_p
!= (struct GRPSYL
*) 0;
1203 gs_roll_p
= gs_roll_p
->next
) {
1205 grp_octave_adjust(gs_roll_p
,
1206 Octave_adjust
[staffno
],
1208 /* stop when we hit the
1209 * end of the roll */
1210 if (gs_roll_p
->inputlineno
> 0) {
1217 total_time
= radd(total_time
, gs_p
->fulltime
);
1220 /* if octave mark carried over into subsequent
1221 * measure(s), make a note of that for future use */
1222 if (stuff_p
->end
.bars
> 0) {
1223 if (carry_adjust
!= 0) {
1224 l_warning(stuff_p
->inputfile
,
1225 stuff_p
->inputlineno
,
1226 "overlapping octave marks");
1228 carry_bars
= stuff_p
->end
.bars
;
1229 carry_counts
= stuff_p
->end
.count
;
1230 carry_adjust
= Octave_adjust
[staffno
];
1233 Octave_adjust
[staffno
] = 0;
1237 /* above octave marks that were put in on the same input line will
1238 * be in backwards order (because above stuff needs to be that
1239 * way to pile on correctly). However, if the last octave in the
1240 * stuff input line carried over a bar line, we would see it
1241 * first and lose the carryover information when handling the earlier
1242 * octave marks (which are later in the stuff list). That's why the
1243 * carryover information had to be saved. Now we can assign it */
1244 if (carry_bars
> 0) {
1245 Octave_adjust
[staffno
] = carry_adjust
;
1246 Octave_bars
[staffno
] = carry_bars
;
1247 Octave_count
[staffno
] = carry_counts
;
1252 /* transpose all the notes in a group by the specified octave adjustment */
1255 grp_octave_adjust(gs_p
, adj
, mll_p
)
1257 struct GRPSYL
*gs_p
; /* adjust this group */
1258 int adj
; /* add this (potentially negative) value to
1259 * each notelist octave */
1260 struct MAINLL
*mll_p
; /* STAFF of gs_p for finding prev grp for bends */
1264 struct GRPSYL
*prevgs_p
; /* previous group, for bends */
1266 for (n
= 0; n
< gs_p
->nnotes
; n
++) {
1267 gs_p
->notelist
[n
].octave
+= adj
;
1269 /* Transpose any bends going to this group */
1270 prevgs_p
= prevgrpsyl(gs_p
, &mll_p
);
1271 if (prevgs_p
== 0) {
1272 /* If there is no previous group, nothing to transpose. */
1275 for (n
= 0; n
< prevgs_p
->nnotes
; n
++) {
1276 if (prevgs_p
->notelist
[n
].is_bend
== YES
) {
1277 /* Note that when is_bend is YES, nslurto will always
1278 * be 1, but we loop through as many as there are
1279 * (all 1 of them!), to not be dependent
1280 * on that piece of inside information.
1283 for (s
= 0; s
< prevgs_p
->notelist
[n
].nslurto
; s
++) {
1284 prevgs_p
->notelist
[n
].slurtolist
[s
].octave
+= adj
;
1291 /* Given a group and note value, return the effective accidental
1292 * on that note, (-2 to +2) taking key signature
1293 * and previous accidentals into account.
1294 * There are certain pathological cases that this doesn't
1295 * handle right, notably if the user changes the key signature at a bar
1296 * line, and the note in question is tied to from before that bar line,
1297 * and the key signature change is such that it changes what the accidental
1298 * should be. But it should handle anything less convoluted than that.
1302 eff_acc(gs_p
, note_p
, mll_p
)
1304 struct GRPSYL
*gs_p
; /* get effective accidental for note in this group */
1305 struct NOTE
*note_p
; /* get for this note */
1306 struct MAINLL
*mll_p
; /* main list item that points to gs_p */
1309 struct MAINLL
*orig_mll_p
;
1310 struct GRPSYL
*pgs_p
; /* previous group */
1312 int tie_break
; /* YES if there has been a break
1313 * in the chain of notes
1315 int eff_accidental
; /* effective accidental so far */
1318 /* if this group has an explicit accidental, that's also the
1319 * effective accidental */
1320 if (note_p
->accidental
!= '\0') {
1321 /* note: the - 2 is to adjust for natural being element 2
1322 * of the Circle array */
1323 return( (int) (strchr(Acclets
, note_p
->accidental
) - Acclets
) - 2);
1326 /* remember which measure we are starting in, so we know when we cross
1330 /* init to assume we might have ties */
1333 /* if all else fails, we will use the accidental from the key sig */
1334 eff_accidental
= acc_from_keysig(note_p
->letter
, gs_p
->staffno
,
1337 /* back up until we figure out the effective accidental */
1338 for (pgs_p
= prevgrpsyl(gs_p
, &mll_p
); pgs_p
!= (struct GRPSYL
*) 0;
1339 pgs_p
= prevgrpsyl(pgs_p
, &mll_p
)) {
1342 /* see if this group contains the note in question */
1343 for (n
= 0; n
< pgs_p
->nnotes
; n
++) {
1344 if (pgs_p
->notelist
[n
].letter
== note_p
->letter
&&
1345 pgs_p
->notelist
[n
].octave
1346 == note_p
->octave
) {
1347 /* it does have the note: it's notelist[n] */
1352 /* see if this is end of ties to the note, working backwards */
1353 if (n
== pgs_p
->nnotes
) {
1354 /* no note at all, so clearly no tied note */
1357 else if (pgs_p
->notelist
[n
].tie
== NO
) {
1358 /* end of chain of tied notes */
1362 if (orig_mll_p
== mll_p
) {
1363 /* we're still in same measure. If we have a matching
1364 * note, see if it has an accidental */
1365 if (n
< pgs_p
->nnotes
) {
1366 if (pgs_p
->notelist
[n
].accidental
!= '\0') {
1367 return( (int) (strchr(Acclets
,
1368 pgs_p
->notelist
[n
].accidental
)
1373 /* have to keep backing up */
1376 /* Now in previous measure. If no matching note,
1377 * we use the effective accidental found so far */
1378 if (n
== pgs_p
->nnotes
) {
1379 return(eff_accidental
);
1382 /* if the note isn't tied, then use the most recent
1383 * effective accidental we found */
1384 if (pgs_p
->notelist
[n
].tie
== NO
|| tie_break
== YES
) {
1385 return(eff_accidental
);
1388 /* if there is an accidental on this note,
1389 * then it's the one we're looking for. */
1390 if (pgs_p
->notelist
[n
].accidental
!= '\0') {
1391 return( (int) (strchr(Acclets
,
1392 pgs_p
->notelist
[n
].accidental
) -
1396 /* need to continue working backwards toward
1397 * the beginning of this new measure */
1399 eff_accidental
= acc_from_keysig(note_p
->letter
,
1400 gs_p
->staffno
, mll_p
);
1404 /* backed up all the way to the beginning of the song, use last we
1406 return(eff_accidental
);
1410 /* given a letter and staff number, return 1 if the pitch with that letter
1411 * gets a sharps according to the key signature, or -1 if it gets a flat,
1412 * or 0 if it gets neither. */
1415 acc_from_keysig(letter
, staffno
, mll_p
)
1417 int letter
; /* which pitch */
1418 int staffno
; /* which staff to get the key signature from */
1419 struct MAINLL
*mll_p
; /* pitch is from the staff hanging off of here */
1422 int index
; /* where the letter is in circle of fifths */
1423 int sharps
; /* sharps in key sig for the given staff */
1424 struct SSV
*ssv_p
; /* to get key signature */
1427 /* find letter in circle of fifths */
1428 index
= strchr(Circle
, letter
) - Circle
+ 1;
1430 /* get key signature. Unfortunately, the SSVs may not be
1431 * accurate at the time we are called, so we have to search
1432 * backwards in the main list for the most recent relevant
1433 * key signature change. */
1434 for (sharps
= 0; mll_p
!= (struct MAINLL
*) 0; mll_p
= mll_p
->prev
) {
1435 if (mll_p
->str
== S_SSV
) {
1436 ssv_p
= mll_p
->u
.ssv_p
;
1438 /* does this SSV have a key signature change in it? */
1439 if (ssv_p
->used
[SHARPS
] == YES
) {
1440 if (ssv_p
->context
== C_STAFF
&&
1441 ssv_p
->staffno
== staffno
) {
1442 /* aha! found the most recent
1444 * for the relevant staff */
1445 sharps
= ssv_p
->sharps
;
1448 else if (ssv_p
->context
== C_SCORE
) {
1449 /* this will be the score-wide default
1450 * if we don't find a staff-specific
1451 * value, so save this as our default */
1452 sharps
= ssv_p
->sharps
;
1459 /* key signature is one with sharps */
1460 if (index
<= sharps
) {
1461 /* this letter gets a sharp */
1465 else if (sharps
< 0) {
1466 /* key signature is one with flats */
1467 if ( (8 - index
) <= -sharps
) {
1468 /* this letter gets a flat */
1473 /* must be a natural */
1477 /* Set Staffscale, Stepsize, Stdpad, and other similar values based on the
1478 * specified staff number. If staff of 0 is given, set Staffscale to the
1485 int s
; /* which staff */
1488 Staffscale
= (s
== 0 ? Score
.staffscale
1489 : svpath(s
, STAFFSCALE
)->staffscale
);
1490 Stepsize
= STEPSIZE
* Staffscale
;
1491 Stdpad
= STDPAD
* Staffscale
;
1492 Flagsep
= FLAGSEP
* Staffscale
;
1493 Smflagsep
= SMFLAGSEP
* Staffscale
;
1494 Tupheight
= TUPHEIGHT
* Staffscale
;
1498 /* Determine the space between lines of a grid. A staff of 0 means use
1499 * the score size. A staff of -1 means ATEND. Return distance in inches. */
1510 space
= ATEND_GS
* STEPSIZE
* Score
.gridscale
;
1513 space
= WHEREUSED_GS
* STEPSIZE
1514 * svpath(staff
, STAFFSCALE
)->staffscale
1515 * svpath(staff
, GRIDSCALE
)->gridscale
;
1521 /* Given a grid, return (via pointer) the items needed for the PostScript
1522 * plus the top fret.
1526 gridinfo(grid_p
, staff
, frets_p
, fretnum_p
, numvert_p
, topfret_p
)
1528 struct GRID
*grid_p
;
1529 int staff
; /* 0 == score, -1 = ATEND, otherwise the staff number */
1530 int *frets_p
; /* how many frets high the grid should be */
1531 int *fretnum_p
; /* the N of "N fr" */
1532 int *numvert_p
; /* how many frets from the top to print the "N fr" */
1533 int *topfret_p
; /* the fret number of the top line of the grid */
1536 int minfret
, maxfret
; /* smallest and largest frets used */
1537 int rightmost_fret
; /* the 'N' of 'N fr" if any */
1538 int right_stringnum
; /* string number having rightmost_fret */
1539 int mincurvefret
; /* smallest fret number inside curve */
1540 int has_o
; /* if there are 'o' items */
1545 /* Go through strings finding min/max/rightmost */
1546 minfret
= MAXFRET
+ 1;
1547 maxfret
= MINFRET
- 1;
1548 mincurvefret
= MAXFRET
+ 1;
1550 rightmost_fret
= right_stringnum
= 0; /* avoids bogus warnings */
1551 for (s
= 0; s
< grid_p
->numstr
; s
++) {
1552 /* x o and - things don't count */
1553 if (grid_p
->positions
[s
] > 0) {
1554 if (grid_p
->positions
[s
] < minfret
) {
1555 minfret
= grid_p
->positions
[s
];
1557 if (grid_p
->positions
[s
] > maxfret
) {
1558 maxfret
= grid_p
->positions
[s
];
1560 rightmost_fret
= grid_p
->positions
[s
];
1561 right_stringnum
= s
;
1563 /* find smallest fret inside curve */
1564 if (grid_p
->curvel
!= 0 && s
>= grid_p
->curvel
- 1 &&
1565 s
<= grid_p
->curver
- 1 &&
1566 grid_p
->positions
[s
] < mincurvefret
) {
1567 mincurvefret
= grid_p
->positions
[s
];
1570 else if (grid_p
->positions
[s
] == 0) {
1575 /* set the values to defaults, then calculate actuals if needed */
1579 if (minfret
<= MAXFRET
) {
1580 /* at least one fret was used */
1582 /* figure out how many frets tall to make the grid */
1583 *frets_p
= maxfret
+ 1;
1585 /* see if gridfret is set */
1586 gridfret
= svpath(staff
== -1 ?
0 : staff
, GRIDFRET
)->gridfret
;
1587 if (gridfret
!= NOGRIDFRET
) {
1588 /* gridfret is set; see if all frets larger than that.
1589 * But we only use "N fr" if there are no 'o' items. */
1590 if (has_o
== NO
&& minfret
>= gridfret
) {
1591 /* We will need "N fr"
1592 * Usually we use the rightmost string
1593 * that has a fret on it,
1594 * but there is one special case:
1595 * if the curve comes at least that far right,
1596 * and the minimum fret inside the curve is
1597 * smaller than the rightmost_fret, then we
1598 * put the "N fr" by the curve minimum.
1600 if (grid_p
->curver
- 1 >= right_stringnum
1601 && mincurvefret
< rightmost_fret
) {
1602 rightmost_fret
= mincurvefret
;
1604 *fretnum_p
= rightmost_fret
;
1605 *numvert_p
= rightmost_fret
- minfret
+ 1;
1606 *frets_p
= maxfret
- minfret
+ 2;
1611 /* always at least 4 frets plus top line */
1615 *topfret_p
= (*fretnum_p
== 0 ?
0 : *fretnum_p
- *numvert_p
);
1619 /* Determine the dimensions of a grid, relative to a point in the middle
1620 * of the top line of the grid, and return them via pointers.
1621 * If pointers are 0, don't bother; caller doesn't care about these things.
1622 * Things in this function must be kept in sync with the PostScript prolog
1623 * definition of grids.
1627 gridsize(grid_p
, staff
, north_p
, south_p
, east_p
, west_p
)
1629 struct GRID
*grid_p
; /* find the size of this grid */
1630 int staff
; /* use this staff for scaling. 0 means score,
1632 float *north_p
; /* return values... */
1638 double space
; /* distance between adjacent line of the grid */
1643 int s
; /* string index */
1646 pfatal("gridsize() was passed a null pointer");
1649 /* determine distance between grid lines and other needed info */
1650 space
= gridspace(staff
);
1651 gridinfo(grid_p
, staff
, &frets
, &fretnum
, &numvert
, &topfret
);
1653 /* Start with minimum. East and west are equal, at half the
1654 * total grid width, based on number of strings. The number of
1655 * spaces is the number of strings minus one, but dots, X's,
1656 * and O's will hang over the sides, so use the number of strings.
1657 * Then adjust east for "N fr" if needed. */
1659 *west_p
= -((space
* grid_p
->numstr
) / 2.0);
1662 *east_p
= (space
* grid_p
->numstr
) / 2.0;
1664 /* We will need "N fr".
1665 * Get enough space to hold
1666 * font, size, 2 digits, space, "fr", null */
1669 /* this is printed in Palatino Roman */
1670 tmp
[0] = (char) FONT_PR
;
1672 /* Between staffscale and gridscale,
1673 * we could get a size that we can't represent
1674 * in internal format, so get string width
1675 * in default size and adjust afterwards. */
1676 tmp
[1] = (char) DFLT_SIZE
;
1678 /* since we know there are no funny characters
1679 * in this string, we can cheat and not bother
1680 * to call the string normalizer. */
1681 sprintf(tmp
+ 2, "%d fr", fretnum
);
1683 *east_p
+= strwidth(tmp
) *
1684 (space
* PPI
* 1.9)/ DFLT_SIZE
;
1689 /* Always put almost one space of padding on top, which allows
1690 * room for x's and o's and curves. Even if this particular grid
1691 * doesn't have those, many do, so it's nice to line
1692 * all of them up as much as possible */
1693 *north_p
= 0.85 * space
;
1694 /* If there is a curve above the top fret,
1695 * with x's or o's above it, leave some more space */
1696 if (grid_p
->positions
[grid_p
->curvel
- 1] == topfret
+ 1
1697 || grid_p
->positions
[grid_p
->curver
- 1]
1699 for (s
= grid_p
->curvel
; s
<= grid_p
->curver
; s
++) {
1700 if (grid_p
->positions
[s
-1] == 0 ||
1701 grid_p
->positions
[s
-1]
1703 *north_p
+= 0.7 * space
;
1710 /* Grid is always at least 4 boxes high, more if needed,
1711 * plus 1/2 space of padding at bottom */
1713 *south_p
= -(frets
- 0.5) * space
;
1718 /* This function returns the minimum distance needed between the current
1719 * staff and previous one, given their clefs and allowing for a measure
1720 * number. The clefs might be NOCLEF, like if this is for the top
1721 * staff of a page or a staff where printclef is false.
1725 clefspace(prevclef
, prevscale
, curclef
, curscale
, measnum
)
1727 int prevclef
; /* clef on staff above */
1728 double prevscale
; /* staffscale for the staff above */
1729 int curclef
; /* clef on staff below */
1730 double curscale
; /* staffscale for the staff below */
1731 int measnum
; /* YES if a measure number needs to be printed */
1734 double cur_extend
; /* space needed for current clef */
1735 double prev_extend
; /* space needed for clef above */
1736 double space_needed
; /* total for both clefs and measure number */
1739 /* Figure out how much the clef on current staff sticks up,
1740 * Do in approximate STEPSIZEs here, and adjust later for scale. */
1763 /* Similar for the clef above, only how much it sticks down
1785 /* Add top and bottom together, adjusting for scale factors,
1786 * and adding a little padding */
1787 space_needed
= prev_extend
* STEPSIZE
* prevscale
+
1788 cur_extend
* STEPSIZE
* curscale
+
1791 /* Add on the space for the measure number, if necessary.
1792 * Note that we can use fontascent since all digits are that high. */
1793 if (measnum
== YES
) {
1794 space_needed
+= fontascent(Score
.measnumfamily
+ Score
.measnumfont
,
1795 Score
.measnumsize
) + STDPAD
;
1797 return(space_needed
);
1801 * Name: eff_rightmargin()
1803 * Abstract: Return the effective right margin for this score.
1805 * Returns: the margin in inches
1807 * Description: There are two reason that code can't just use Score.rightmargin
1808 * but must call this function. First, the way the "scale" param
1809 * works, we pretend the paper is smaller by that amount and then
1810 * in PostScript magnify it back to the real size; but margins are
1811 * not to be scaled, so we have to fake out the code by dividing
1812 * out the scale here. Second, the user can override the param
1813 * on a "newscore" or "newpage". To ignore a user override, pass
1814 * 0 for mainll_p, else pass some MLL on that score.
1818 eff_rightmargin(mainll_p
)
1820 struct MAINLL
*mainll_p
; /* MLL struct on some score, or 0 for normal margin */
1823 /* if not already at a FEED, find FEED at right end of this score */
1824 while (mainll_p
!= 0 && mainll_p
->str
!= S_FEED
)
1825 mainll_p
= mainll_p
->next
;
1827 /* if there is none, or there is no override, use the parameter */
1828 if (mainll_p
== 0 || mainll_p
->u
.feed_p
->rightmargin
< 0.0)
1829 return (Score
.rightmargin
/ Score
.scale_factor
);
1831 /* use this override value */
1832 return (mainll_p
->u
.feed_p
->rightmargin
/ Score
.scale_factor
);
1836 * Name: eff_leftmargin()
1838 * Abstract: Return the effective left margin for this score.
1840 * Returns: the margin in inches
1842 * Description: There are two reason that code can't just use Score.leftmargin
1843 * but must call this function. First, the way the "scale" param
1844 * works, we pretend the paper is smaller by that amount and then
1845 * in PostScript magnify it back to the real size; but margins are
1846 * not to be scaled, so we have to fake out the code by dividing
1847 * out the scale here. Second, the user can override the param
1848 * on a "newscore" or "newpage". To ignore a user override, pass
1849 * 0 for mainll_p, else pass some MLL on that score.
1853 eff_leftmargin(mainll_p
)
1855 struct MAINLL
*mainll_p
; /* MLL struct on some score, or 0 for normal margin */
1858 /* if not already at a FEED, find FEED at left end of this score */
1859 while (mainll_p
!= 0 && mainll_p
->str
!= S_FEED
)
1860 mainll_p
= mainll_p
->prev
;
1862 /* if there is none, or there is no override, use the parameter */
1863 if (mainll_p
== 0 || mainll_p
->u
.feed_p
->leftmargin
< 0.0)
1864 return (Score
.leftmargin
/ Score
.scale_factor
);
1866 /* use this override value */
1867 return (mainll_p
->u
.feed_p
->leftmargin
/ Score
.scale_factor
);
1871 * Name: findprimes()
1873 * Abstract: Find all the prime numbers up to the given number ("max").
1875 * Returns: array indexed 0 to max, each element YES or NO (is index prime?)
1877 * Description: This function mallocs and returns an array of shorts, indexed
1878 * from 0 to max. Each element is YES or NO, telling whether its
1879 * index is a prime number. The first time it is called, or if
1880 * max is greater than the previous time, it calculates all this,
1881 * but on other calls it just returns the answer from before.
1887 int max
; /* max integer we need to consider */
1890 static short *isprime
= 0; /* array to be malloc'ed */
1891 static int oldmax
= 0; /* the max passed in previously */
1892 int stop
; /* where to stop looking */
1893 int prime
; /* a prime number */
1894 int n
; /* loop index */
1897 /* if we've already been here ... */
1899 /* if we've already done the same or more, just return answer*/
1900 if (max
<= oldmax
) {
1903 /* max increased; free the old array */
1906 oldmax
= max
; /* remember if for next time */
1908 MALLOCA(short, isprime
, max
+ 1);
1910 /* 0 and 1 are not primes */
1911 isprime
[0] = isprime
[1] = NO
;
1914 * We're going to use the Sieve of Eristosthenes. We start out by
1915 * assuming everything 2 and greater is prime.
1917 for (n
= 2; n
<= max
; n
++) {
1921 /* the following loop can stop when it gets to this point */
1922 stop
= sqrt((double)max
) + 1;
1925 while (prime
<= stop
) {
1926 /* knock out all multiples of this prime number */
1927 for (n
= 2 * prime
; n
<= max
; n
+= prime
) {
1930 /* find the next prime */
1931 for (n
= prime
+ 1; n
<= stop
&& isprime
[n
] == NO
; n
++)
1942 * Abstract: Factor the given number.
1944 * Returns: array indexed 0 to num, giving the prime factors
1946 * Description: This function mallocs and returns an array of shorts, indexed
1947 * from 0 to max. Each element indexed by a prime number tells
1948 * how many times that prime factor occurs in num. All other
1949 * elements are 0. The first time it is called, or if num is
1950 * different from the previous time, it calculates all this,
1951 * but on other calls it just returns the answer from before.
1957 int num
; /* the integer to be factored */
1960 static short *factors
= 0; /* array to be malloc'ed */
1961 static int oldnum
= 0; /* the number passed in previously */
1962 short *isprime
; /* list of which numbers are prime */
1963 int orignum
; /* remember original num */
1964 int n
; /* loop index */
1967 /* if we've just done the same number, just return the answer */
1969 /* if we've already done the same or more, just return answer*/
1970 if (num
== oldnum
) {
1973 /* num changed; free the old array */
1976 oldnum
= num
; /* remember it for next time */
1978 CALLOCA(short, factors
, num
+ 1);
1980 /* find which numbers up to num are primes */
1981 isprime
= findprimes(num
);
1984 * For every prime number until "num" is used up, divide it into num
1985 * as many times as possible, keeping track of how many times.
1988 for (n
= 2; n
<= orignum
&& num
> 1; n
++) {
1989 if (isprime
[n
] == YES
) {
1990 while (num
% n
== 0) {
2001 /* Return the width of the widest note head in the given GRPSYL. */
2006 struct GRPSYL
*gs_p
;
2009 double widest
; /* widest note head in the group */
2010 double thiswidth
; /* width of current note */
2011 int n
; /* note index */
2014 for (n
= 0; n
< gs_p
->nnotes
; n
++) {
2015 thiswidth
= width(gs_p
->notelist
[n
].headfont
,
2016 (gs_p
->notelist
[n
].notesize
== GS_NORMAL ?
2017 DFLT_SIZE
: SMALLSIZE
),
2018 gs_p
->notelist
[n
].headchar
);
2019 if (thiswidth
> widest
) {