1 /* Copyright (c) 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003 by Arkkra Enterprises */
2 /* All rights reserved */
4 /* This file contains functions that deal with
5 * extending underscores and dashes on lyric syllables.
12 static double end_dashes
P((struct MAINLL
*mll_p
, struct GRPSYL
*syl_p
,
13 int verse
, int place
, int *carryover_p
));
14 static double end_underscore
P((struct MAINLL
*mll_p
, struct GRPSYL
*syl_p
,
15 int verse
, int place
, int *carryover_p
));
16 static double endx
P((struct GRPSYL
*last_grp_p
, double end
));
17 static int has_above_lyr
P((struct MAINLL
*mll_p
, RATIONAL begin_time
,
18 struct GRPSYL
*group_p
, int verse
));
19 static int voice_is_above
P((int v1
, int v2
));
20 static struct GRPSYL
*find_verse_place
P((struct STAFF
*staff_p
,
21 int verse
, int place
));
22 static RATIONAL default_end
P((struct MAINLL
*mll_p
, struct GRPSYL
*syl_p
,
23 RATIONAL start_time
, double *end_p
));
24 static int bar_ends_extender
P((struct BAR
*bar_p
, struct MAINLL
*mll_p
,
25 int staffno
, int verse
, int place
,
26 struct GRPSYL
**nextsyl_p_p
));
27 static void pr_extender
P((int ch
, double start
, double end
, double y
,
29 static void insert_carryover_syllable
P((struct MAINLL
*mll_p
, int staffno
,
30 int sylplace
, int verseno
, char *dash_or_underscore
,
32 static void add_syllable
P((struct STAFF
*staff_p
, int sylplace
, int verseno
,
33 char *dash_or_underscore
, int font
, int size
,
34 double begin_x
, struct CHORD
*chord_p
));
35 static void stitch_syl_into_chord
P((struct CHORD
*chord_p
,
36 struct GRPSYL
*syl_gs_p
));
39 /* This function is called on lyric syllables in two cases:
40 * 1) During placement phase to determine if an extender needs to
41 * be carried over to a following staff. In this case, really_print
42 * will be NO. (The easiest way to see if an extender needs to carry
43 * over is to pretend to print an extender). The return value will
44 * be YES if there should be a carryover.
45 * 2) When printing the syllable, to draw an extender after it,
46 * if appropriate. In this case, really_print will be YES,
47 * and the return value is meaningless.
49 * If a syllable ends with a dash, the dash should be placed halfway between
50 * where this syllable ends and the next begins. Or if there is a big space,
51 * multiple dashes should be spread out in that space. If it ends with an
52 * underscore, then an underline should be drawn from the end of this
53 * syllable to the east edge of the notes in the last chord before
54 * the next syllable for the same staff/verse/place.
55 * But if there is a carryover, this just does the extender up to the
56 * end of the current score; it will get called again on the next score
57 * to continue the extender.
58 * If an underscore is used on a single chord, rather than a mellisma
59 * (which might technically be considered an "incorrect" usage of underscore),
60 * we figure the underscore should be drawn to just before the next syllable,
61 * unless there is a rest earlier. Or if the next syllable begins a measure,
62 * the underscore ends before the bar line, to look better.
63 * If really printing, the dash or underscore is removed
64 * from the end of the string so it won't get printed
69 spread_extender(syl_p
, mll_p
, verse
, sylplace
, really_print
)
71 struct GRPSYL
*syl_p
; /* current syllable */
72 struct MAINLL
*mll_p
; /* which MAINLL struct it's hanging off of */
73 int verse
; /* verse number */
74 int sylplace
; /* PL_ABOVE, etc */
75 int really_print
; /* if YES, actually print, otherwise just return
76 * whether needs to be carried over to next score */
79 char *syl
; /* to walk through characters of the syllable */
82 double start
; /* dash area or underscore starts here */
83 double end
; /* dash area or underscore ends here */
84 int ch
; /* current character in syllable */
85 int last_ch
= '\0'; /* final character in syllable */
86 int extndr_font
; /* in case user changes font/size after
87 * extender, keep track of what font/size the
90 char *ch_p
; /* pointer to where - or _ is in string */
91 int carryover
; /* YES if will carry over to next staff */
95 /* See if there is a dash or underscore at the end of the syllable.
96 * If so, save pointer to it. Note that this may not be the last
97 * byte in the string, because there could be font/size changes
100 size
= syl_p
->syl
[1];
101 syl
= syl_p
->syl
+ 2;
103 /* These two assignments avoid "used without being set" warnings */
107 /* Find last character of syllable */
108 while ( (ch
= next_str_char( &syl
, &font
, &size
)) != '\0') {
110 if ( ( ch
== '-' || ch
== '_') && ! IS_MUSIC_FONT(font
)
111 && (font
< FONT_XTR
) ) {
113 if ( ( ch
== '-' || ch
== '_') && ! IS_MUSIC_FONT(font
) ) {
125 /* If there is an extender, handle it */
126 if (last_ch
!= '\0') {
127 if ( last_ch
== '-') {
128 end
= end_dashes(mll_p
, syl_p
, verse
, sylplace
,
132 end
= end_underscore(mll_p
, syl_p
, verse
, sylplace
,
136 if (really_print
== NO
) {
140 /* Move the rest of the string
141 * over the dash or underscore,
142 * so it won't get printed with the syllable */
145 } while ( *++ch_p
!= '\0');
146 start
= syl_p
->c
[AE
];
148 /* procsyls() adjusted the east in certain cases for
149 * placement purposes. For printing we need to cancel out
150 * those adjustments. */
151 if (syl_p
->next
!= 0 && last_ch
!= '-') {
152 start
-= width(extndr_font
, extndr_size
, ' ');
154 if (syl_p
->next
== 0 && last_ch
== '-') {
155 start
+= width(extndr_font
, extndr_size
, ' ');
158 /* actually print the extender */
159 pr_extender(last_ch
, start
, end
, syl_p
->c
[AY
],
160 extndr_font
, extndr_size
);
166 /* Given a syllable ending with a dash, and some other info,
167 * return where to end the dash(es). If the dashes carry over
168 * to the following score, this will return a point near the east end of
169 * the current score, after setting *carryover_p to YES.
173 end_dashes(mll_p
, syl_p
, verse
, place
, carryover_p
)
175 struct MAINLL
*mll_p
; /* points to STAFF containing the syl with dash */
176 struct GRPSYL
*syl_p
; /* this is the syllable with dash */
177 int verse
; /* which verse the syl_p is for */
178 int place
; /* a PL_* value for where the lyric is */
179 int *carryover_p
; /* return value, set to YES if there was a carryover */
183 struct BAR
*lastbar_p
;
185 staffno
= syl_p
->staffno
;
187 lastbar_p
= 0; /* will get set to something better before being used */
191 /* Go forward looking for another non-space syllable */
193 for ( ; syl_p
!= 0; syl_p
= syl_p
->next
) {
194 if (syl_p
->grpcont
!= GC_SPACE
) {
196 return(syl_p
->c
[AW
] - Stepsize
);
201 /* No ending syl in current measure. Try the next. */
202 for (mll_p
= mll_p
->next
; mll_p
!= 0; mll_p
= mll_p
->next
) {
203 if (mll_p
->str
== S_BAR
) {
204 if (bar_ends_extender(mll_p
->u
.bar_p
,
205 mll_p
, staffno
, verse
,
207 return(mll_p
->u
.bar_p
->c
[AW
] - Stepsize
);
209 lastbar_p
= mll_p
->u
.bar_p
;
212 else if (mll_p
->str
== S_FEED
) {
213 /* If this is a feed at the very end of the
214 * main list, or one or more blocks follow it,
215 * this is not the kind of feed
216 * we're looking for. */
217 if (mll_p
->next
== 0 ||
218 mll_p
->next
->str
== S_BLOCKHEAD
) {
221 /* There is a carryover unless the
222 * pseudo-bar is something that would end
225 if (mll_p
->str
!= S_CLEFSIG
226 || mll_p
->u
.clefsig_p
->bar_p
228 if (mll_p
->str
== S_FEED
) {
229 /* Being here means there is
230 * a bug somewhere else,
231 * because the main list rules
232 * are violated. But we can
233 * render such a bug harmless
234 * by continuing here.
238 pfatal("end_dashes found unexpected main list contents after feed");
240 if (bar_ends_extender(mll_p
->u
.clefsig_p
->bar_p
,
241 mll_p
, staffno
, verse
, place
, 0)
245 return(lastbar_p
->c
[AW
] - Stepsize
);
248 else if (mll_p
->str
== S_STAFF
249 && mll_p
->u
.staff_p
->staffno
251 syl_p
= find_verse_place(mll_p
->u
.staff_p
,
256 } while (mll_p
!= 0);
258 /* Fell off end of song. Use final bar */
259 return(lastbar_p
->c
[AW
] - Stepsize
);
263 /* Given a syllable ending with an underscore, and some other info,
264 * return where to end the underscore. If the underscore carries over
265 * to the following score, this will return a point near the east end of
266 * the current score, after setting *carryover_p to YES.
270 end_underscore(mll_p
, syl_p
, verse
, place
, carryover_p
)
272 struct MAINLL
*mll_p
; /* points to STAFF containing the syl with underscore */
273 struct GRPSYL
*syl_p
; /* this is the syllable with underscore */
274 int verse
; /* which verse the syl_p is for */
275 int place
; /* a PL_* value for where the lyric is */
276 int *carryover_p
; /* return value, set to YES if there was a carryover */
279 struct GRPSYL
*current_grp_p
[MAXVOICES
];/* which group we are
280 * currently dealing with on
282 RATIONAL group_time
[MAXVOICES
]; /* accumulated time value of
283 * groups up to the one we
284 * are currently dealing with */
285 short had_rest
[MAXVOICES
]; /* YES or NO */
286 RATIONAL current_time
; /* how far we are in meas */
287 RATIONAL end_time
; /* where next non-space
288 * syllable is for this
289 * staff/place/verse, if
291 * in the current measure,
292 * otherwise the end of the
293 * current measure. */
294 struct GRPSYL
*last_grp_p
; /* if non-zero, this is the
295 * current candidate group
296 * with which we could
297 * potentially align the
298 * end of the underscore. */
299 double end
; /* this is how far we will
300 * draw the underscore if we
301 * don't find any reason to
303 struct GRPSYL
*grp_p
; /* walk through GRPSYLs */
304 struct STAFF
*staff_p
; /* next measure's STAFF */
305 struct GRPSYL
*nextsyl_p
; /* syl list for same verse/place
306 * in the next measure */
307 RATIONAL grp_end_time
; /* where a current group ends */
309 int vindex
; /* voice index */
310 int v
; /* voice index */
311 short found_feed
; /* YES or NO */
315 *carryover_p
= NO
; /* assume no carryover for now */
316 staffno
= mll_p
->u
.staff_p
->staffno
;
318 /* Back up from the syllable with underscore to count up time-wise how
319 * far into the measure it is */
321 for (grp_p
= syl_p
->prev
; grp_p
!= 0; grp_p
= grp_p
->prev
) {
322 current_time
= radd(current_time
, grp_p
->fulltime
);
325 /* Set a default end time and place.
326 * Most likely, we will discover later we need to stop the underscore
327 * earlier than this, but if the user is using underscore in a strange
328 * way, like on a single long note rather than a melissma,
329 * we'll use this as the default place to end the underscore. */
330 end_time
= default_end(mll_p
, syl_p
, current_time
, &end
);
332 /* We don't yet have any candidate group with which to align
333 * the ending of the underscore. */
336 /* For each voice, if it exists, find the group that contains
337 * the time of the syllable with the underscore, and make that
338 * the "current group" for that voice. If the voice doesn't exist,
339 * set the current group pointer to zero. */
340 staff_p
= mll_p
->u
.staff_p
;
341 for (vindex
= 0; vindex
< MAXVOICES
; vindex
++) {
342 group_time
[vindex
] = Zero
;
343 had_rest
[vindex
] = NO
;
344 if (staff_p
->groups_p
[vindex
] != 0) {
345 for (current_grp_p
[vindex
] = staff_p
->groups_p
[vindex
];
346 current_grp_p
[vindex
] != 0;
347 current_grp_p
[vindex
]
348 = current_grp_p
[vindex
]->next
) {
349 if (GE(current_time
, group_time
[vindex
]) &&
351 radd(group_time
[vindex
],
352 current_grp_p
[vindex
]->fulltime
))) {
353 /* This group contains the syl's time */
355 if (current_grp_p
[vindex
]->grpcont
== GC_REST
) {
356 had_rest
[vindex
] = YES
;
360 group_time
[vindex
] = radd(group_time
[vindex
],
361 current_grp_p
[vindex
]->fulltime
);
363 if (current_grp_p
[vindex
] == 0) {
364 pfatal("unable to find group containing syl's time");
368 /* voice doesn't exist in this measure */
369 current_grp_p
[vindex
] = 0;
374 /* Most of the time, we use voice 1 to determine where to
375 * end the underscore. However, if voice 1 has spaces,
376 * we'll use voice 3 (the "middle" voice), and
377 * if that is non-existent or space, we use voice 2.
378 * If everything is space, we keep going and hope for the
379 * best. If all else fails, we would end up using the "end"
380 * value as the default.
382 * However, if this is a below or between lyric,
383 * and there exists an above lyric
384 * during the time we are dealing with,
385 * we assume voice 1 goes with the above lyric, and the
386 * below lyric probably goes with voice 2, or possibly voice 3.
387 * If both those voices exist, it's probably not possible
388 * to divine which the user wants the lyric associated with
389 * without reading their mind. But 3 voices on a vocal staff
390 * is quite unusual, especially with rests in different places,
391 * so we use voice 2 if it exists and is non-space.
392 * If that fails, we try 3, then 1, then punt.
393 * If it is a between lyric, there is a slight chance the user
394 * really wanted us to use the staff below, but we always
395 * associate "between" things with the staff above.
396 * They should use "above" on the next staff instead.
398 vindex
= 0; /* use voice 1 as default */
399 if (place
!= PL_ABOVE
) {
400 /* The lyric is below or between.
401 * Test voices 2, 3, and 1 (indexes 1, 2, 0)
402 * in that order till we find one that isn't a space,
403 * and see if there is an above lyric
404 * during its time. If so, that is the voice to use
405 * during this time to figure out
406 * where to end underscore. */
407 if (current_grp_p
[1] != 0 &&
408 current_grp_p
[1]->grpcont
!= GC_SPACE
&&
409 has_above_lyr(mll_p
, current_time
,
410 current_grp_p
[1], verse
) == YES
) {
413 else if (current_grp_p
[2] != 0 &&
414 current_grp_p
[2]->grpcont
!= GC_SPACE
&&
415 has_above_lyr(mll_p
, current_time
,
416 current_grp_p
[2], verse
) == YES
) {
419 /* Otherwise we go with the default, voice 1.
420 * We know voice 1 will always exist. */
423 else { /* place is above */
424 /* Note that voice 1 always exists, so
425 * so we don't need to check for null first
427 if (current_grp_p
[0]->grpcont
!= GC_SPACE
) {
430 else if (current_grp_p
[2] != 0 &&
431 current_grp_p
[2]->grpcont
!= GC_SPACE
) {
434 else if (current_grp_p
[1] != 0 &&
435 current_grp_p
[1]->grpcont
!= GC_SPACE
) {
440 /* At this point, we know which voice is most relevant for
441 * checking if it is time to end the underscore.
442 * See if the current group in that voice contains the
443 * time value of the ending syllable. */
444 if ( GE(end_time
, group_time
[vindex
]) && LT(end_time
,
445 radd(group_time
[vindex
],
446 current_grp_p
[vindex
]->fulltime
)) ) {
447 /* We need to end the underscore now. */
448 return(endx(last_grp_p
, end
));
451 /* If the relevant group is a rest, need to stop here */
452 if (current_grp_p
[vindex
]->grpcont
== GC_REST
) {
453 return(endx(last_grp_p
, current_grp_p
[vindex
]->c
[AW
]));
455 else if (current_grp_p
[vindex
]->grpcont
== GC_NOTES
) {
456 /* Save as last known group so far at which we
457 * could potentially end the underscore. */
458 last_grp_p
= current_grp_p
[vindex
];
461 /* We're done with this group; move to next */
462 current_time
= radd(current_time
,
463 current_grp_p
[vindex
]->fulltime
);
465 /* Catch up all the voices to the current time */
466 for (v
= 0; v
< MAXVOICES
; v
++) {
467 if (current_grp_p
[v
] != 0) {
468 grp_end_time
= radd(group_time
[v
],
469 current_grp_p
[v
]->fulltime
);
471 while ( LE(grp_end_time
, current_time
) ){
472 /* Special case. Suppose,
473 * as an example, soprano and
474 * alto share a staff and the
475 * soprano has a long note
476 * while the alto has a
477 * melissma. The underscore
478 * should then go to the
479 * last note of the melissma,
480 * even though soprano is
481 * the reference voice.
482 * However, if the alto line
483 * had had rests, it's likely
484 * it's just accompaniment,
485 * not a vocal line, or at
486 * least they should have
487 * used separate above/below
489 * So if this group is below
490 * the reference group and
491 * hasn't had any rests and
492 * is east of our candidate
493 * last group, make it the
494 * new candidate last group. */
495 if (voice_is_above(vindex
, v
)
499 && current_grp_p
[v
]->grpcont
501 && current_grp_p
[v
]->c
[AX
]
502 > last_grp_p
->c
[AX
]) {
503 last_grp_p
= current_grp_p
[v
];
506 /* move on to next group */
508 current_grp_p
[v
]->next
;
509 if (current_grp_p
[v
] == 0) {
513 group_time
[v
] = grp_end_time
;
516 current_grp_p
[v
]->fulltime
);
517 if (current_grp_p
[v
]->grpcont
525 /* Are we now at the end of the current measure? */
526 if (current_grp_p
[vindex
] == 0) {
527 /* If there is a feed after this bar,
528 * we need to see if a carryover is needed.
529 * If so, we will end this underscore just before
530 * the bar, and carry it over to the next score.
533 for (mll_p
= mll_p
->next
; mll_p
!= 0; mll_p
= mll_p
->next
) {
534 if (mll_p
->str
== S_BAR
) {
535 if (bar_ends_extender(mll_p
->u
.bar_p
, mll_p
,
536 syl_p
->staffno
, verse
,
540 * where we should stop if
541 * we can't deduce a following
543 * if we go to the bar line,
544 * the user can always use
545 * a <> syllable to force
546 * an earlier ending if needed,
548 * with the last group,
549 * there's probably no
550 * reasonable workaround
551 * if that's not what they want,
552 * so use the bar line. */
553 if (nextsyl_p
== 0) {
556 else if (nextsyl_p
->grpcont
562 return(endx(last_grp_p
, end
));
566 else if (mll_p
->str
== S_FEED
) {
569 else if (mll_p
->str
== S_STAFF
&&
570 mll_p
->u
.staff_p
->staffno
==
574 else if (mll_p
->str
== S_SSV
) {
575 /* if this staff becomes invisible,
576 * end the underscore at the last
577 * group before that. */
579 ssv_p
= mll_p
->u
.ssv_p
;
580 if (ssv_p
->context
== C_STAFF
581 && ssv_p
->staffno
== staffno
582 && ssv_p
->used
[VISIBLE
] == YES
583 && ssv_p
->visible
== NO
) {
584 return(endx(last_grp_p
, end
));
589 /* fell off end of song */
590 return(endx(last_grp_p
, end
));
592 staff_p
= mll_p
->u
.staff_p
;
594 /* See if there is a syllable at the same verse/place */
595 if ((nextsyl_p
= find_verse_place(staff_p
,
596 verse
, place
)) != 0 &&
597 nextsyl_p
->grpcont
!= GC_SPACE
) {
598 /* There is a syllable at the
599 * beginning of the next meas,
600 * so we end the underscore,
601 * unless it was just a carryover syllable
602 * that we added earlier. */
603 if (nextsyl_p
->syl
[2] != '_'
604 || nextsyl_p
->syl
[3] != '\0') {
605 return(endx(last_grp_p
, end
));
608 if (found_feed
== YES
) {
609 if (staff_p
->groups_p
[vindex
] != 0 &&
610 staff_p
->groups_p
[vindex
]->grpcont
== GC_REST
) {
611 /* next meas begins with a rest,
612 * so no need to carry over */
613 return(endx(last_grp_p
, end
));
615 /* We need to end the underscore on the
616 * current score, and arrange to carry it
617 * over on the next score. */
623 /* Move to next measure by initing each
624 * current_grp_p[vindex] to the first group
625 * in the next measure. */
626 for (vindex
= 0; vindex
< MAXVOICES
; vindex
++) {
627 current_grp_p
[vindex
] = staff_p
->groups_p
[vindex
];
628 group_time
[vindex
] = Zero
;
629 if (current_grp_p
[vindex
] != 0 &&
630 current_grp_p
[vindex
]->grpcont
632 had_rest
[vindex
] = YES
;
635 end_time
= default_end(mll_p
,
636 find_verse_place(staff_p
, verse
, place
),
644 /* If we found a last group where we could end a underscore,
645 * return where the east edge of its notes are,
646 * otherwise return the "end" value as the default.
650 endx(last_grp_p
, end
)
652 struct GRPSYL
*last_grp_p
; /* if != 0, use east edge of notes of this */
653 double end
; /* if all else fails, use this */
656 int n
; /* note index */
657 double edge
; /* return value */
660 if (last_grp_p
== 0) {
664 if (last_grp_p
->grpcont
!= GC_NOTES
) {
665 /* This should actually never happen with the current code,
666 * but just in case, we use the east of the group */
667 return(last_grp_p
->c
[AE
]);
670 /* find east edge of notes, not counting any dots or flags */
671 edge
= -1000000.0; /* init to impossible value */
672 for (n
= 0; n
< last_grp_p
->nnotes
; n
++) {
673 if (last_grp_p
->notelist
[n
].c
[AE
] > edge
) {
674 edge
= last_grp_p
->notelist
[n
].c
[AE
];
677 /* If the edge we calculated is east of the default end, use
678 * the default end, because that is suppose to be the farthest
679 * possible east we can be. This could happen if the user used
680 * <^....> on a lyric to force part of the lyric to encroach
681 * into the previous groups' space. In that case we need to end
682 * the underscore where the encroaching lyric begins, not where
683 * the last note group ends.
693 * Return YES if there is an above lyrics during the specified time.
694 * We have to use some heuristics.
696 * If there is any non-space above lyric for the given verse
697 * at any point between the begin time
698 * and the begin time plus the fulltime of the group_p,
699 * then there is an above lyric.
701 * If there is a rest on voice 1, that implies a rest in an above lyric
704 * If there is lyric space for the duration in question, either
705 * explicit space, or just no above lyrics at all for the given verse
706 * in this measure, then we don't know for sure where there are no
707 * above lyrics, or there is an earlier above lyric for this verse
708 * that extends into the duration.
709 * If we find some earlier non-space above lyric
710 * and it ends with an extender (dash or underscore),
711 * we say there is an above lyric.
712 * If there is no such lyric, or the first non-space above lyric
713 * lyric we come to in backing up does not end with an extender,
714 * we say there isn't an above lyric.
718 has_above_lyr(mll_p
, begin_time
, group_p
, verse
)
720 struct MAINLL
*mll_p
; /* points to syl's STAFF */
722 struct GRPSYL
*group_p
; /* see if there a lyric above this group */
726 struct STAFF
*staff_p
;
727 struct GRPSYL
*grp_p
;
728 RATIONAL cumm_time
; /* current cummulative time */
729 RATIONAL new_cumm_time
; /* cumm_time + group's fulltime */
730 RATIONAL end_time
; /* begin_time + syl's fulltime */
731 int n
; /* syllist index */
732 int prev_extends
; /* YES/NO if prev syl has extender */
735 if (mll_p
->str
!= S_STAFF
) {
736 pfatal("has_above_lyr passed wrong type of struct");
739 staff_p
= mll_p
->u
.staff_p
;
740 end_time
= radd(begin_time
, group_p
->fulltime
);
742 /* Go through syllists for the staff */
744 for (n
= 0; n
< staff_p
->nsyllists
; n
++) {
745 if (staff_p
->sylplace
[n
] == PL_ABOVE
&&
746 staff_p
->syls_p
[n
]->vno
== verse
) {
748 for (grp_p
= staff_p
->syls_p
[n
]; grp_p
!= 0; grp_p
= grp_p
->next
) {
749 new_cumm_time
= radd(cumm_time
, grp_p
->fulltime
);
751 if ( LT(new_cumm_time
, begin_time
) &&
752 grp_p
->grpcont
!= GC_SPACE
) {
753 prev_extends
= has_extender(grp_p
->syl
);
756 /* See if this syllable overlaps the time
757 * of the group we are checking against. */
758 else if ( (GE(begin_time
, cumm_time
) &&
759 LT(begin_time
, new_cumm_time
)) ||
760 (GE(end_time
, cumm_time
) &&
761 LT(end_time
, new_cumm_time
)) ) {
763 /* This is a relevant group. If it isn't
764 * a space, then we know there is
765 * indeed an above lyric. */
766 if (grp_p
->grpcont
!= GC_SPACE
) {
769 if (prev_extends
== YES
) {
771 * earlier in the measure
772 * is extending into the
773 * duration, so that counts.
778 else if (GT(new_cumm_time
, end_time
)) {
779 /* we're past the relevant syl(s) */
782 cumm_time
= new_cumm_time
;
784 /* We've dealt with the only relevant syl list
785 * in this measure. */
790 /* If there is a rest on voice 1, there is an implicit above
791 * lyric (albeit a pause in the above lyrics). Or at least it hardly
792 * makes sense to use voice 1 for below/between lyrics if voice 1
793 * is a rest but there is another voice below it that isn't.
796 for (grp_p
= mll_p
->u
.staff_p
->groups_p
[0]; grp_p
!= 0; grp_p
= grp_p
->next
) {
797 new_cumm_time
= radd(cumm_time
, grp_p
->fulltime
);
798 if ( (GE(begin_time
, cumm_time
) &&
799 LT(begin_time
, new_cumm_time
)) ||
800 (GE(end_time
, cumm_time
) &&
801 LT(end_time
, new_cumm_time
)) ) {
802 if (grp_p
->grpcont
== GC_REST
) {
806 cumm_time
= new_cumm_time
;
807 if (GT(cumm_time
, end_time
)) {
808 /* past the relevant groups */
813 /* If we got here, we weren't able to tell for
814 * sure if there is an above lyric, because there
815 * was either implicit or explicit space.
816 * Most likely there is no above lyric,
817 * but there is a slight possibility there is
818 * a lyric holding over into this time period
819 * via a melisma or tied notes from a previous measure.
820 * So we back up looking for such a lyric. If we find an above lyric
821 * that ends with an extender (underscore or dash),
822 * we declare that there is an above lyric.
823 * If we find one without an extender or back up
824 * all the way to the beginning of the song without
825 * finding any above lyric, there is no above lyric here.
826 * But we give up after 20 measures, figuring it's
827 * really unlikely for any melisma or tie to last
828 * that long, especially since any scorefeeds
829 * would cause a syllable to get added. The exact
830 * value of 20 is arbitrary; it just seems like plenty.
832 * prevgrpsyl doesn't work on syls, just groups,
833 * but by giving it staff_p->groups_p[0] (we
834 * know voice 1 will always exist), it will give
835 * us the mll_p for the staff we need.
837 for (n
= 0; n
< 20; n
++) {
838 struct GRPSYL
*last_non_space_p
;
840 if (prevgrpsyl(mll_p
->u
.staff_p
->groups_p
[0],
842 /* Got to beginning of song */
846 grp_p
= find_verse_place(mll_p
->u
.staff_p
, verse
, PL_ABOVE
);
849 /* No relevant lyrics in this meas */
853 last_non_space_p
= 0;
854 for ( ; grp_p
!= 0; grp_p
= grp_p
->next
) {
855 if (grp_p
->grpcont
!= GC_SPACE
) {
856 last_non_space_p
= grp_p
;
859 if (last_non_space_p
!= 0) {
860 /* Found a preceeding syllable */
861 return(has_extender(last_non_space_p
->syl
));
864 /* We've backed up far enough that the chances of there actually being
865 * an above lyrics are very, very slim. */
870 /* Returns YES if voice with index v1 is "above" voice v2; else NO */
873 voice_is_above(v1
, v2
)
879 /* Voice number is one more than its index, so convert index to
880 * number so it's easier to think about */
884 /* Voice 1 is above voice 2 and 3 */
889 /* Voice 3 is the "middle" voice and thus "above" voice 2 */
890 if (v1
== 3 && v2
== 2) {
898 /* Given a STAFF, return the first GRPSYL in the syllable list for the given
899 * verse and place, if one exists. Otherwise return 0.
902 static struct GRPSYL
*
903 find_verse_place(staff_p
, verse
, place
)
905 struct STAFF
*staff_p
;
912 for (n
= 0; n
< staff_p
->nsyllists
; n
++) {
913 if (staff_p
->sylplace
[n
] == place
&&
914 staff_p
->syls_p
[n
]->vno
== verse
) {
915 return(staff_p
->syls_p
[n
]);
922 /* Given a syl and related info, return the default time and place at which to
923 * end an underscore from that syl, for this measure. If there is a
924 * non-space syl later in the measure, this will be right before that syl,
925 * otherwise right before the bar line.
929 default_end(mll_p
, syl_p
, start_time
, end_p
)
931 struct MAINLL
*mll_p
; /* the STAFF pointing to the syl */
932 struct GRPSYL
*syl_p
; /* start looking from the syl */
933 RATIONAL start_time
; /* syl is already this far into measure */
934 double *end_p
; /* X value at which to end underscore is
935 * returned via this pointer */
938 struct GRPSYL
*grp_p
;
939 RATIONAL end_time
; /* return value */
942 /* No syllable for current verse/place in current measure.
943 * Time signature may not be up to date, so add up the
944 * time of voice 1, which we know exists.
946 end_time
= start_time
;
947 for (grp_p
= mll_p
->u
.staff_p
->groups_p
[0]; grp_p
!= 0;
948 grp_p
= grp_p
->next
) {
949 end_time
= radd(end_time
, grp_p
->fulltime
);
953 /* Go forward in the syl list, finding where the next non-space
954 * syllable is, if there is one in the current measure,
955 * otherwise find the end of the measure.
956 * Save the time and location of this.
958 end_time
= radd(start_time
, syl_p
->fulltime
);
959 for (grp_p
= syl_p
->next
; grp_p
!= 0; grp_p
= grp_p
->next
) {
960 if (grp_p
->grpcont
== GC_SPACE
) {
961 /* Underscore continues through "space" syls */
962 end_time
= radd(end_time
, grp_p
->fulltime
);
966 /* We have found the syllable
967 * at which the underscore
968 * from the previous syllable ends */
974 /* If a next syl was found, set end to near its west.
975 * Most likely, we will discover later we need to stop the underscore
976 * earlier than this, but if the user is using underscore in a strange
977 * way, like on a single long note rather than a melissma,
978 * we'll use this as the default place to end the underscore.*/
980 *end_p
= grp_p
->c
[AW
] - Stepsize
;
983 /* The ending syllable (if any) is not in the current measure.
984 * So for now we set the end to near the west of the bar line.
985 * Note that end_time will have added up to
986 * the full measure duration in this case.
988 for ( ; mll_p
!= 0; mll_p
= mll_p
->next
) {
989 if (mll_p
->str
== S_BAR
) {
990 *end_p
= mll_p
->u
.bar_p
->c
[AW
] - Stepsize
;
995 pfatal("underscore: failed to find next bar");
1002 /* Given a bar, see if it is a bar that might force stopping an extender,
1003 * and return YES, if so. If nextsyl_p_p is non-null, it also attempts
1004 * to fill that in with a pointer to the next "logical" syllable.
1005 * (Usually the next syllable, but at the end of a repeat it would
1006 * be the first syllable in the repeated section).
1007 * If it can't figure out the correct syllable, it fills in null.
1011 bar_ends_extender(bar_p
, mll_p
, staffno
, verse
, place
, nextsyl_p_p
)
1014 struct MAINLL
*mll_p
; /* points to a BAR or CLEFSIG*/
1018 struct GRPSYL
**nextsyl_p_p
; /* If this is non-zero, and we can deduce
1019 * the next "logical" syl, the pointed to value
1020 * will be updated to point to that next syl,
1021 * else will be zero. */
1026 bartype
= bar_p
->bartype
;
1027 if (bartype
== RESTART
) {
1028 /* We shouldn't continue an extender over a restart.
1029 * The "next" logical measure is probably the
1030 * target of a D.S. or a D.C.
1031 * But we don't attempt to parse
1032 * STUFF strings to know such things.
1033 * So we say the extender ends here,
1034 * but we don't know what the "next" measure is.
1036 if (nextsyl_p_p
!= 0) {
1042 if (bartype
== REPEATEND
|| bartype
== REPEATBOTH
) {
1043 if (nextsyl_p_p
== 0) {
1047 /* This ends the extender. The next logical measure
1048 * is at the beginning of the repeat. */
1049 for (mll_p
= mll_p
->prev
; mll_p
!= 0; mll_p
= mll_p
->prev
) {
1050 if (mll_p
->str
== S_BAR
&&
1051 (mll_p
->u
.bar_p
->bartype
1053 mll_p
->u
.bar_p
->bartype
1055 mll_p
= mll_p
->next
;
1060 /* repeatstart is implicit at beginning of song */
1063 for ( ; mll_p
!= 0; mll_p
= mll_p
->next
) {
1064 if (mll_p
->str
== S_BAR
) {
1065 /* staff doesn't exist in this measure */
1069 if (mll_p
->str
== S_STAFF
&& mll_p
->u
.staff_p
->staffno
1071 *nextsyl_p_p
= find_verse_place(
1072 mll_p
->u
.staff_p
, verse
, place
);
1078 if (mll_p
->u
.bar_p
->endingloc
== STARTITEM
) {
1079 /* If this is the start of a second or subsequent ending,
1080 * this ends the extender. This is the case if the previous
1081 * bar was a STARTITEM on INITEM. But apparently there
1082 * isn't a repeat ending here, or we would have hit the
1083 * bartype check for that. So it is too hard to try to deduce
1084 * the next logical syllable. */
1085 for (mll_p
= mll_p
->prev
; mll_p
!= 0; mll_p
= mll_p
->prev
) {
1086 if (mll_p
->str
== S_BAR
) {
1087 if (mll_p
->u
.bar_p
->endingloc
== STARTITEM
||
1088 mll_p
->u
.bar_p
->endingloc
1090 if (nextsyl_p_p
!= 0) {
1104 /* Actually print an extender (dash or underscore) */
1107 pr_extender(ch
, start
, end
, y
, font
, size
)
1109 int ch
; /* dash or underscore */
1110 double start
; /* where to start printing */
1111 double end
; /* where to end printing */
1112 double y
; /* y coordinate */
1113 int font
; /* font to use for dash */
1114 int size
; /* size to use for dash */
1121 dashwidth
= width(font
, size
, '-');
1123 /* generate the internal string format of a dash */
1124 /* can't use dash_string function here since that also
1125 * deals with ~ which is okay for stuff but not lyrics */
1126 dashstring
[0] = (char) font
;
1127 dashstring
[1] = (char) size
;
1128 dashstring
[2] = '-';
1129 dashstring
[3] = '\0';
1131 if ( (end
- start
) < (15.0 * dashwidth
) ) {
1132 /* not much space, so find midpoint of
1133 * available distance and put dash there */
1134 pr_string(start
+ ((end
- start
) / 2.0)
1135 - (dashwidth
/ 2.0),
1136 y
, dashstring
, J_LEFT
,
1140 int numdashes
; /* how many dashes to print */
1141 double spacebetween
; /* between dashes */
1143 /* Lots of space, so will need to print multiple dashes.
1144 * Figure out how to spread out */
1145 numdashes
= (int) ((end
- start
) / (8.0 * dashwidth
));
1146 spacebetween
= ((end
- start
) - (dashwidth
* numdashes
))
1149 for ( ; numdashes
> 0; numdashes
--) {
1151 (numdashes
- 0.5) * spacebetween
1152 + ((numdashes
- 1.0) * dashwidth
),
1153 y
, dashstring
, J_LEFT
,
1159 /* if long enough to bother drawing underscore, draw it */
1160 if (end
- start
> Stepsize
) {
1161 /* Note: line width probably really ought to
1162 * be scaled based on the lyric size, but unless
1163 * somebody uses really huge or really tiny lyrics,
1164 * a normal line width looks good enough,
1165 * so we just go with that.
1167 do_linetype(L_NORMAL
);
1168 draw_line(start
, y
, end
, y
);
1174 /* Return YES if last character of syllable is an underscore or dash,
1181 char *syl
; /* the syllable to check */
1184 switch (last_char(syl
)) {
1196 /* Return last character in a string.
1197 * If last character is a music character,
1198 * or the string is null, return null.
1204 char *str
; /* return last character in this string */
1208 int ch
; /* current character in string */
1209 int last_font
= FONT_UNKNOWN
; /* font of last character */
1213 if (str
== (char *) 0) {
1220 /* keep track of each character. When we hit
1221 * end of string, return the last character we saw */
1222 for ( str
+= 2; (ch
= next_str_char(&str
, &font
, &size
)) != 0; ) {
1226 /* music characters don't count */
1227 if (IS_MUSIC_FONT(last_font
)) {
1230 return (last_ch
& 0xff);
1234 /* See if an underscore or dash will need to be carried to the following score.
1235 * If so, add an appropriate "syllable" at the beginning of that score */
1238 cont_extender(mll_p
, sylplace
, verseno
)
1240 struct MAINLL
*mll_p
; /* the syllable is hanging off of this STAFF */
1241 int sylplace
; /* PL_ABOVE, etc */
1242 int verseno
; /* verse number */
1245 struct GRPSYL
*syl_p
; /* walk through GRPSYL list */
1246 struct GRPSYL
*last_non_space_p
;
1247 int last_ch
; /* last character of syllable */
1248 int font
; /* of syllable */
1249 int size
; /* of syllable */
1252 if (mll_p
->str
!= S_STAFF
) {
1253 pfatal("cont_extender called with wrong argument");
1256 /* Find the actual syl grpsyl that is the last on the score */
1257 syl_p
= find_verse_place(mll_p
->u
.staff_p
, verseno
, sylplace
);
1260 pfatal("cont_extender called without any syllable");
1263 /* Find the final non-space syllable in the list */
1264 last_non_space_p
= 0;
1265 for ( ; syl_p
!= 0; syl_p
= syl_p
->next
) {
1266 if (syl_p
->grpcont
!= GC_SPACE
) {
1267 last_non_space_p
= syl_p
;
1271 if (last_non_space_p
== 0) {
1272 pfatal("cont_extender couldn't find non-space syllable");
1275 last_ch
= last_char(last_non_space_p
->syl
);
1276 if (last_ch
!= '-' && last_ch
!= '_') {
1277 pfatal("cont_extender called on syl without extender");
1280 /* See if will carry over */
1281 if (spread_extender(last_non_space_p
, mll_p
, verseno
, sylplace
, NO
)
1284 /* determine proper font/size of
1285 * carried over dash/underscore
1286 * based on font/size at end of syllable */
1287 end_fontsize(last_non_space_p
->syl
, &font
, &size
);
1289 /* insert the syllable on next score */
1290 insert_carryover_syllable(mll_p
,
1291 last_non_space_p
->staffno
, sylplace
,
1293 (last_ch
== '-' ?
"-" : "_"),
1299 /* A dash or underscore needs to be carried over to the following score.
1300 * Search forward for the appropriate STAFF. If there is already a lyric
1301 * there for the sylplace and verseno, if its first syllable is a space,
1302 * change it to a dash or underscore as appropriate.
1303 * If there is no lyric in that measure for the sylplace and verseno,
1304 * insert a measure long syllable of the appropriate type.
1305 * If there is no STAFF of the proper number after a FEED, assume we are
1306 * at the end of the piece or of visibility of the staff, and do nothing.
1307 * If there is already a syllable, leave it as is.
1312 insert_carryover_syllable(mll_p
, staffno
, sylplace
, verseno
, dash_or_underscore
,
1315 struct MAINLL
*mll_p
; /* points to staff info */
1316 int staffno
; /* staff number */
1317 int sylplace
; /* PL_ABOVE, etc */
1318 int verseno
; /* verse number */
1319 char *dash_or_underscore
; /* "-" or "_" */
1320 int font
; /* font and size to use for dash or underscore */
1324 struct STAFF
*staff_p
; /* add syllable to this staff */
1325 struct CHORD
*chord_p
; /* chord syllables goes with */
1326 int v
; /* verse index */
1327 float begin_x
; /* where to start carryover syllable */
1330 /* search forward for FEED */
1331 for ( ; mll_p
!= (struct MAINLL
*) 0; mll_p
= mll_p
->next
) {
1332 if (IS_CLEFSIG_FEED(mll_p
)) {
1337 if (mll_p
== (struct MAINLL
*) 0) {
1341 /* The AE coordinates of syllable groups
1342 * have already been set, but we need to have
1343 * this one set for the underscore/dash syllable being added. So deduce
1344 * where it should be using the pseudo-bar */
1345 if ((mll_p
= mll_p
->next
) == (struct MAINLL
*) 0) {
1348 if (mll_p
->str
== S_CLEFSIG
) {
1349 begin_x
= mll_p
->u
.clefsig_p
->bar_p
->c
[AE
] + STDPAD
;
1352 /* setting begin_x is just to shut up compilers that erroneously
1353 * think it could be used without being set. */
1355 pfatal("no clefsig after feed");
1358 /* silence compilers that think chord_p might not be set */
1359 chord_p
= (struct CHORD
*) 0;
1361 /* search forward for STAFF of interest, and save CHORD info */
1362 for ( mll_p
= mll_p
->next
; mll_p
!= (struct MAINLL
*) 0;
1363 mll_p
= mll_p
->next
) {
1365 if (mll_p
->str
== S_CHHEAD
) {
1366 chord_p
= mll_p
->u
.chhead_p
->ch_p
;
1368 else if (mll_p
->str
== S_STAFF
) {
1369 if (mll_p
->u
.staff_p
->staffno
== staffno
) {
1375 /* see if has syllable of specified place and verse */
1376 if (mll_p
!= (struct MAINLL
*) 0) {
1378 staff_p
= mll_p
->u
.staff_p
;
1379 for (v
= 0; v
< staff_p
->nsyllists
; v
++) {
1381 if (staff_p
->sylplace
[v
] == sylplace
&&
1382 staff_p
->syls_p
[v
]->vno
== verseno
) {
1384 /* are lyrics in this measure. See if first
1385 * syllable is a space. If so, replace with
1386 * a dash. Otherwise we are done */
1387 if (staff_p
->syls_p
[v
]->syl
== (char *) 0) {
1388 staff_p
->syls_p
[v
]->syl
=
1389 copy_string(dash_or_underscore
,
1391 /* no longer a "space" syllable */
1392 staff_p
->syls_p
[v
]->grpcont
= GC_NOTES
;
1398 /* no lyrics in first measure on next score for this
1399 * verse/place. Need to insert one */
1400 add_syllable(staff_p
, sylplace
, verseno
,
1401 dash_or_underscore
, font
, size
,
1407 /* Add a dash or underscore syllable to list of lyrics. Need to alloc new
1408 * space for the sylplace and syls_p arrays, copy the existing data into
1409 * them, adding the new syllable at the proper place (sorted by verseno),
1410 * then free the old arrays */
1413 add_syllable(staff_p
, sylplace
, verseno
, dash_or_underscore
, font
, size
,
1416 struct STAFF
*staff_p
; /* add syllable to this staff */
1417 int sylplace
; /* PL_ABOVE, etc */
1419 char *dash_or_underscore
; /* "-" or "_" */
1422 double begin_x
; /* where syllable is to start */
1423 struct CHORD
*chord_p
; /* what chord to attach to */
1426 short *new_sylplace
; /* new, expanded sylplace array */
1427 struct GRPSYL
**new_syls_p
; /* new, expanded syls_p array */
1428 int v
; /* verse index */
1429 int insert_index
; /* where to put in new arrays */
1430 int inserted
; /* 0 if haven't found where to insert
1431 * yet, 1 if we have. This is then the
1432 * difference between the index of the
1433 * original arrays and where the copy
1434 * goes in the new arrays. Since it's
1435 * used in array subscript calculation
1436 * we can't use YES and NO here */
1439 /* alloc arrays that are one larger than the current arrays */
1440 MALLOCA(short, new_sylplace
, staff_p
->nsyllists
+ 1);
1441 MALLOCA(struct GRPSYL
*, new_syls_p
, staff_p
->nsyllists
+ 1);
1443 /* now copy and insert */
1444 insert_index
= staff_p
->nsyllists
;
1445 for (inserted
= v
= 0; v
< staff_p
->nsyllists
; v
++) {
1446 if (insert_index
> v
&& staff_p
->syls_p
[v
]->vno
> verseno
) {
1452 new_sylplace
[v
+ inserted
] = staff_p
->sylplace
[v
];
1453 new_syls_p
[v
+ inserted
] = staff_p
->syls_p
[v
];
1456 /* alloc and fill in the new GRPSYL */
1457 new_sylplace
[insert_index
] = (short) sylplace
;
1458 new_syls_p
[insert_index
] = newGRPSYL(GS_SYLLABLE
);
1459 new_syls_p
[insert_index
]->syl
= copy_string(dash_or_underscore
,
1461 new_syls_p
[insert_index
]->inputlineno
= -1;
1462 new_syls_p
[insert_index
]->basictime
= -1;
1463 new_syls_p
[insert_index
]->is_meas
= YES
;
1464 new_syls_p
[insert_index
]->fulltime
= Score
.time
;
1465 new_syls_p
[insert_index
]->staffno
= staff_p
->staffno
;
1466 new_syls_p
[insert_index
]->vno
= (short) verseno
;
1467 /* X coords of normal syllables already set, so have to set for
1468 * this special syllable here */
1469 new_syls_p
[insert_index
]->c
[AE
] = begin_x
1470 + strwidth(new_syls_p
[insert_index
]->syl
);
1471 new_syls_p
[insert_index
]->c
[AW
] = begin_x
;
1472 new_syls_p
[insert_index
]->c
[AX
] = begin_x
;
1474 /* now have one one list of syllables */
1475 (staff_p
->nsyllists
)++;
1477 /* free old arrays if non-null */
1478 if (staff_p
->sylplace
!= (short *) 0) {
1479 FREE(staff_p
->sylplace
);
1481 if (staff_p
->syls_p
!= (struct GRPSYL
**) 0) {
1482 FREE(staff_p
->syls_p
);
1485 /* now link up the new arrays */
1486 staff_p
->sylplace
= new_sylplace
;
1487 staff_p
->syls_p
= new_syls_p
;
1489 /* add to appropriate chord */
1490 stitch_syl_into_chord(chord_p
, new_syls_p
[insert_index
]);
1494 /* Given a syllable and chord to attach it to, attach it */
1495 /* Strictly speaking, this function probably isn't necessary, since I think
1496 * all use of the CHORD struct has already been done before this function is
1497 * called, but it's probably good to do anyway on general principles, in case
1498 * some day the CHORDs are looked at later */
1501 stitch_syl_into_chord(chord_p
, syl_gs_p
)
1503 struct CHORD
*chord_p
; /* add to this chord */
1504 struct GRPSYL
*syl_gs_p
; /* add this syllable */
1507 struct GRPSYL
*gs_p
; /* walk through chord */
1510 /* go down chord list */
1511 for (gs_p
= chord_p
->gs_p
; gs_p
->gs_p
!= (struct GRPSYL
*) 0;
1512 gs_p
= gs_p
->gs_p
) {
1514 /* if next grpsyl in chord has staffno < staffno of syl to add,
1516 if (gs_p
->gs_p
->staffno
< syl_gs_p
->staffno
) {
1520 /* if next grpsyl in chord had staffno > staffno of syl to add,
1522 if (gs_p
->gs_p
->staffno
> syl_gs_p
->staffno
) {
1523 /* found where to insert */
1527 /* If here, must be same staffno.
1528 * Keep going until find syllable with larger vno. */
1529 if (gs_p
->gs_p
->grpsyl
== GS_GROUP
) {
1533 if (gs_p
->gs_p
->vno
> syl_gs_p
->vno
) {
1534 /* found where to insert */
1539 /* insert syllable */
1540 syl_gs_p
->gs_p
= gs_p
->gs_p
;
1541 gs_p
->gs_p
= syl_gs_p
;