2 /* Copyright (c) 1995, 1997, 1998, 1999, 2001, 2002 by Arkkra Enterprises */
3 /* All rights reserved */
5 /* This file contains functions for handling ties and slurs.
6 * This includes doing error checking to make sure
7 * there is a note to tie/slur to.
8 * There is also code to add padding to make space for ties/slurs
9 * that are carried into second endings. */
17 /* lengths of line segments of carried in tie marks */
18 #define HALFTIEPAD (3 * STEPSIZE)
20 /* infomation about a tied or slurred note that gets carried into an ending */
22 short letter
; /* pitch to be tied or slurred to */
23 short octave
; /* octave of the pitch */
24 short curveno
; /* slurto index or -1 for tie */
25 short is_bend
; /* if slurto is actually a bend */
26 struct MAINLL
*mll_p
; /* points to first group */
27 struct GRPSYL
*gs_p
; /* group of first note */
28 struct TIECARRY
*next
; /* linked list */
31 /* linked list of tie carry info for each staff/voice */
32 struct TIECARRY
*Tiecarryinfolist_p
[MAXSTAFFS
+ 1] [MAXVOICES
];
34 /* flag to mark if there are any carry ins */
35 static short Have_carry_ins
= NO
;
38 /* static functions */
39 static void do_tie
P((struct MAINLL
*mll_p
));
40 static void do_group_ties
P((struct GRPSYL
*gs_p
, struct MAINLL
*mll_p
));
41 static void chk_slides
P((struct NOTE
*note_p
, struct GRPSYL
*gs_p
,
42 struct MAINLL
*mll_p
));
43 static void chk_following4slide
P((struct NOTE
*note_p
, struct GRPSYL
*gs_p
,
44 struct MAINLL
*mll_p
));
45 static struct MAINLL
*do_carry_ties
P((struct MAINLL
*staff_mll_p
,
46 struct MAINLL
*bar_mll_p
));
47 static void savetieinfo
P((struct MAINLL
*mll_p
, struct GRPSYL
*gs_p
));
48 static void do_save_tieinfo
P((int staffno
, int vno
, int letter
, int octave
,
49 int is_tie
, struct MAINLL
*mainll_p
, struct GRPSYL
*gs_p
,
51 static void carryin_ties
P((struct MAINLL
*mll_p
));
52 static void add_carryin
P((struct STAFF
*staff_p
));
53 static void free_carryin_info
P((void));
54 static void free_cinfo
P((struct TIECARRY
*carryinfo_p
));
55 static void chk4xpose
P((struct MAINLL
*mll_p
));
56 static void chkxpstaff
P((struct MAINLL
*mll_p
, int s
));
57 static void chkxpgrp
P((struct GRPSYL
*gs_p
, char *inputfile
, int lineno
));
58 static void set_inhibitprint_if_appropriate
P((struct GRPSYL
*gs_p
,
59 struct MAINLL
*mll_p
));
63 /* go through main list, checking each STAFF struct for ties and slurs.
64 * For each, do appropriate error checking */
70 struct MAINLL
* mll_p
; /* walk through main list */
75 /* first check for any ties across transpositions, and delete them.
76 * Can't do inside the next loop, because by then a less informative
77 * message could be generated for the error */
79 for (mll_p
= Mainllhc_p
; mll_p
!= (struct MAINLL
*) 0;
80 mll_p
= mll_p
->next
) {
81 if (mll_p
->str
== S_SSV
) {
83 asgnssv(mll_p
->u
.ssv_p
);
87 /* go through the main list again for other checks */
89 for (mll_p
= Mainllhc_p
; mll_p
!= (struct MAINLL
*) 0;
90 mll_p
= mll_p
->next
) {
92 /* process any GRPSYL lists with note info */
93 if (mll_p
->str
== S_STAFF
) {
94 if ( (svpath(mll_p
->u
.staff_p
->staffno
, VISIBLE
))
99 else if (mll_p
->str
== S_SSV
) {
100 asgnssv(mll_p
->u
.ssv_p
);
106 /* do the ties and slurs on all groups off a STAFF struct */
111 struct MAINLL
*mll_p
; /* the STAFF struct with list of GRPSYLs */
114 struct GRPSYL
*gs_p
; /* walk through GRPSYL list */
115 int v
; /* walk through voices per staff */
116 int is_tab
; /* YES if tablature staff */
119 is_tab
= is_tab_staff(mll_p
->u
.staff_p
->staffno
);
121 for (v
= 0; v
< MAXVOICES
; v
++) {
122 /* go through entire list of GRPSYLs */
123 for (gs_p
= mll_p
->u
.staff_p
->groups_p
[v
];
124 gs_p
!= (struct GRPSYL
*) 0;
128 if (gs_p
->grpcont
!= GC_NOTES
) {
129 if (gs_p
->tie
== YES
) {
130 l_warning(mll_p
->inputfile
,
132 "tie can only apply to notes");
136 /* if rest or space, nothing more to do */
140 do_group_ties(gs_p
, mll_p
);
142 set_inhibitprint_if_appropriate(gs_p
, mll_p
);
149 /* do ties on all notes in a group that have ties. While we're at it, also
150 * make sure any staffs with clefs not printed, don't have accidentals on any
154 do_group_ties(gs_p
, mll_p
)
156 struct GRPSYL
*gs_p
; /* do ties from this group */
157 struct MAINLL
*mll_p
; /* points to gs_p */
160 struct GRPSYL
*gs2_p
; /* group to tie to */
161 register int n
; /* walk through note list */
162 struct NOTE
*note1_p
; /* info about note */
163 struct NOTE
*note2_p
; /* note slurred to */
164 int slur
; /* index into slurtolist */
165 int d
; /* index for deleting illegal slurs */
166 short err
= NO
; /* error flag */
167 short inhibitprint
; /* if to set inhibitprint flag on the
168 * tied-to group (tab staff only) */
171 /* if all notes in a group are tied on a tablature staff,
172 * then all the corresponding notes on the tied-to group
173 * should have their inhibitprint flag set. So we need to
174 * find out if that is a possibility */
175 if (is_tab_staff(gs_p
->staffno
) == YES
) {
176 if (gs_p
->tie
== YES
) {
180 /* first assume that all notes will be tied, then
181 * check them all. If any are found that are not
182 * tied, then turn the inhibitprint flag back off */
184 for (n
= 0; n
< gs_p
->nnotes
; n
++) {
185 if (gs_p
->notelist
[n
].tie
== NO
) {
193 /* inhibitprint flag is only used on tablature staffs */
197 /* go through all notes in group, looking for ties */
198 gs2_p
= (struct GRPSYL
*) 0;
199 for (n
= 0; n
< gs_p
->nnotes
; n
++) {
201 /* For staffs without clef, make sure there are no accidentals.
202 * But tab staffs keep accidentals, even with no clef.
203 * Philosophically, this isn't really a good place to
204 * do this, but since we're going through the list of notes
205 * anyway here, and time-wise in the scheme of the program
206 * this is the right time, rather than make yet another trip
207 * through the list later we do it here. But for MIDI
208 * purposes, we need to keep the accidental, or the wrong
210 if (svpath(gs_p
->staffno
, STAFFLINES
)->printclef
!= SS_NORMAL
211 && is_tab_staff(gs_p
->staffno
) == NO
212 && Doing_MIDI
== NO
) {
213 gs_p
->notelist
[n
].accidental
= '\0';
216 note1_p
= &(gs_p
->notelist
[n
]);
217 /* if this note's tie flag is set, check the tie */
218 if ( note1_p
->tie
== YES
) {
220 /* if haven't yet found the group to tie to, do that.
221 * (If this is not the first note to be tied
222 * in this group, we would have already found
223 * the other group) */
224 if (gs2_p
== (struct GRPSYL
*) 0) {
225 gs2_p
= find_next_group(mll_p
, gs_p
, "tie");
228 if (gs2_p
== (struct GRPSYL
*) 0) {
229 /* if nothing to tie to, cancel the tie. We
230 * will have already printed an error msg. */
235 /* if the inhibitprint flag is set, set it
236 * in the tied-to group. However,
237 * if the groups have different numbers of
238 * notes and the inhibitprint flag is set,
239 * we have to cancel it, because that only
240 * applies when the tied-from and tied-to
241 * groups have identical notes in them */
242 if (inhibitprint
== YES
) {
243 if (gs_p
->nnotes
== gs2_p
->nnotes
) {
244 gs2_p
->inhibitprint
= YES
;
246 /* turn flag off, so we don't
247 * waste time checking it
248 * again for each of the remaining
249 * notes in the group */
253 if (find_matching_note(gs2_p
, note1_p
->letter
,
254 note1_p
->octave
, "tie")
255 == (struct NOTE
*) 0) {
263 /* handle all slurs from current note */
264 for (slur
= 0; slur
< note1_p
->nslurto
; slur
++) {
266 /* slides to/from nowhere don't get processed here */
267 if (IS_NOWHERE(note1_p
->slurtolist
[slur
].octave
)) {
271 /* if haven't yet found the group to slur to, do that.
272 * (We may have already found it earlier) */
273 if (gs2_p
== (struct GRPSYL
*) 0) {
274 gs2_p
= find_next_group(mll_p
, gs_p
, "slur");
277 if (gs2_p
== (struct GRPSYL
*) 0) {
278 /* if nothing to slur to, cancel all slurs */
279 note1_p
->nslurto
= 0;
283 /* special case of 'M' when a group 'slur'
284 * has been specified. Find matching note
285 * in the second chord */
286 if (note1_p
->slurtolist
[slur
].letter
== 'M') {
287 if (gs_p
->nnotes
!= gs2_p
->nnotes
) {
288 /* only print message first time */
290 l_warning(gs_p
->inputfile
,
292 "'slur' requires equal number of notes in each chord");
294 note2_p
= (struct NOTE
*) 0;
296 /* don't do any more on this
297 * chord, to avoid multiple
302 note2_p
= & (gs2_p
->notelist
[n
]);
306 note2_p
= find_matching_note(gs2_p
,
307 note1_p
->slurtolist
[slur
].letter
,
308 note1_p
->slurtolist
[slur
].octave
,
309 note1_p
->is_bend ?
"bend" : "slur");
312 if (note2_p
!= (struct NOTE
*) 0) {
313 /* fill in the letter/octave if they had to
315 if ((note1_p
->slurtolist
[slur
].letter
== 'U')
316 || (note1_p
->slurtolist
[slur
].letter
== 'M')
317 || is_tab_staff(gs_p
->staffno
) == YES
) {
318 note1_p
->slurtolist
[slur
].letter
=
320 note1_p
->slurtolist
[slur
].octave
=
325 /* discard this slur--
326 * nothing to slur to */
327 for (d
= slur
+ 1; d
< note1_p
->nslurto
; d
++) {
328 note1_p
->slurtolist
[d
-1] =
329 note1_p
->slurtolist
[d
];
331 (note1_p
->nslurto
)--;
335 /* do additional slide checks for tab and tabnote */
336 if (is_tab_staff(gs_p
->staffno
) == YES
337 || (gs_p
->staffno
< MAXSTAFFS
338 && is_tab_staff(gs_p
->staffno
+ 1) == YES
)) {
339 chk_slides(note1_p
, gs_p
, mll_p
);
344 /* do extra checks for slide. There can be no more than one incoming and one
345 * outgoing slide for any given note */
348 chk_slides(note_p
, gs_p
, mll_p
)
350 struct NOTE
*note_p
; /* this note might have slides */
351 struct GRPSYL
*gs_p
; /* note is in this group */
352 struct MAINLL
*mll_p
; /* group is tied to this main list struct */
355 int s
; /* index through slurtolist */
356 int incoming
= 0, outgoing
= 0; /* how many slides of each type */
359 /* go through list counting up incoming and outgoing slides */
360 for (s
= 0; s
< note_p
->nslurto
; s
++) {
361 switch(note_p
->slurtolist
[s
].octave
) {
375 /* make sure following group doesn't have any
376 * incoming nowhere slides */
377 chk_following4slide(note_p
, gs_p
, mll_p
);
383 l_yyerror(gs_p
->inputfile
, gs_p
->inputlineno
,
384 "can't have more than one slide into a note");
387 l_yyerror(gs_p
->inputfile
, gs_p
->inputlineno
,
388 "can't have more than one slide from a note");
394 /* Given a note with a slide to a specific fret,
395 * if there is a following group, see if it has a matching note,
396 * and if so, check that note's slurtolist to see if it
397 * contains any incoming nowhere slides. If so, there is a
398 * problem, because we already have a slide to that note */
401 chk_following4slide(note_p
, gs_p
, mll_p
)
403 struct NOTE
*note_p
; /* this note has a slide to a specific fret */
404 struct GRPSYL
*gs_p
; /* note is in this group */
405 struct MAINLL
*mll_p
; /* group is attached to this main list struct */
408 struct GRPSYL
*ngs_p
; /* next group */
409 int n
; /* index through notes */
410 int ns
; /* index through slides on next group note */
413 if ((ngs_p
= nextgrpsyl(gs_p
, &mll_p
)) == (struct GRPSYL
*) 0) {
414 /* no next group, so no problem */
418 /* check each note in next group */
419 for (n
= 0; n
< ngs_p
->nnotes
; n
++) {
420 /* is this the matching note? If the letter matches and
421 * either it's a tab staff or the octave also matches,
422 * then it is the matching note. */
423 if (ngs_p
->notelist
[n
].letter
== note_p
->letter
&&
424 (is_tab_staff(gs_p
->staffno
) ||
425 ngs_p
->notelist
[n
].octave
== note_p
->octave
)) {
427 /* found the matching note. Check its slurtolist */
428 for (ns
= 0; ns
< ngs_p
->notelist
[n
].nslurto
; ns
++) {
429 switch (ngs_p
->notelist
[n
].slurtolist
[ns
].octave
) {
432 l_yyerror(gs_p
->inputfile
,
434 "can't slide to note that has </n> or <\\n>");
445 /* find note in following chord having specified pitch/octave.
446 * If the note is found, return pointer to it, otherwise 0
450 find_matching_note(gs_p
, letter
, octave
, type
)
452 struct GRPSYL
*gs_p
; /* which GRPSYL we're tying to */
453 int letter
; /* find note with this pitch, 'a' to 'g' */
454 int octave
; /* find note with this octave */
455 char *type
; /* "tie", "slur", "slide", or "bend",
456 * or null if not to print any error messages */
459 struct NOTE
*note2_p
; /* note to tie to */
460 register int n2
; /* index through notelist of 2nd group */
463 if (gs_p
== (struct GRPSYL
*) 0) {
464 return( (struct NOTE
*) 0);
467 /* we don't allow tie/slur into a measure repeat. */
468 if (is_mrpt(gs_p
) == YES
) {
469 l_warning(gs_p
->inputfile
, gs_p
->inputlineno
,
470 "tie/slur/bend not allowed into measure rpt");
471 return (struct NOTE
*) 0;
474 /* special case. On slurto, if second group has only a single
475 * note, user doesn't have to specify it. We will have marked the
476 * pitch as 'U'. If second group has only one note in it, use that
477 * one. If not, error */
478 if ( letter
== 'U') {
479 if ( gs_p
->nnotes
!= 1) {
480 if (type
!= (char *) 0) {
481 l_warning(gs_p
->inputfile
, gs_p
->inputlineno
,
482 "note to %s to not specified", type
);
484 return(struct NOTE
*) 0;
487 return( &(gs_p
->notelist
[0]) );
491 /* try to find matching note in second note group */
492 /* If first note has an accidental and the corresponding one in
493 * the next group doesn't, that's a
494 * match, 'cause we only print the accidental once.
496 for (n2
= 0; n2
< gs_p
->nnotes
; n2
++) {
498 note2_p
= &(gs_p
->notelist
[n2
]);
500 if (is_tab_staff(gs_p
->staffno
) == YES
) {
501 /* on tab staff, we just have to match
502 * the string number */
503 if (note2_p
->letter
== letter
) {
511 if ( (note2_p
->letter
== letter
)
512 && (note2_p
->octave
== octave
) ) {
514 if (type
!= (char *) 0 && (strcmp(type
, "tie") == 0)
515 && (note2_p
->accidental
!= '\0')
516 && is_tab_staff(gs_p
->staffno
) == NO
) {
517 l_warning(gs_p
->inputfile
, gs_p
->inputlineno
,
518 "second note of tie not allowed to have an accidental");
519 /* fix it so in case we're called again on the
520 * same note (which is possible), we'll only
521 * print one error message */
522 note2_p
->accidental
= '\0';
530 /* oh-oh. User goofed */
531 if (is_tab_staff(gs_p
->staffno
) == YES
) {
532 if (type
!= (char *) 0) {
533 l_yyerror(gs_p
->inputfile
, gs_p
->inputlineno
,
534 "can't do %s: %s string not in chord%s",
535 type
, stringname(letter
, gs_p
->staffno
),
537 " (in fact no strings at all)" : "");
541 if (type
!= (char *) 0) {
542 if (letter
< 'a' || letter
> 'g' || octave
< MINOCTAVE
543 || octave
> MAXOCTAVE
) {
544 l_warning(gs_p
->inputfile
, gs_p
->inputlineno
,
545 "can't do %s: note not in chord",
549 l_warning(gs_p
->inputfile
, gs_p
->inputlineno
,
550 "can't do %s: %c%d not in chord%s",
551 type
, letter
, octave
,
553 " (in fact no notes at all)" : "");
557 return( (struct NOTE
*) 0 );
561 /* given one GRPSYL, find the next one in the same staff and voice,
562 * which might be in the next measure */
565 find_next_group(mll_p
, gs_p
, type
)
567 struct MAINLL
*mll_p
; /* current place in main list */
568 struct GRPSYL
*gs_p
; /* group to tie from */
569 char *type
; /* "tie" or "slur" */
575 if ((gs_p
= nextgrpsyl(gs_p
, &ml_p
)) == (struct GRPSYL
*) 0) {
576 l_warning(mll_p
->inputfile
, mll_p
->inputlineno
,
577 "no chord to %s to", type
);
584 /* go through main list. If we hit a bar that begins an ending, back up
585 * and go through the previous measure. If the final group of any voice
586 * has any tied or slurred notes, save information about them. Then for
587 * each additional beginning of an ending up until an endending, add
588 * user padding to allow for carried in tie mark. At the endending, free
589 * the information and continue through the rest of the main list */
595 struct MAINLL
*mll_p
; /* walk through main list */
596 struct MAINLL
*first_staff_mll_p
; /* points to first STAFF
597 * struct of measure */
600 debug(2, "tie_carry");
603 first_staff_mll_p
= (struct MAINLL
*) 0;
604 for (mll_p
= Mainllhc_p
; mll_p
!= (struct MAINLL
*) 0;
605 mll_p
= mll_p
->next
) {
606 switch (mll_p
->str
) {
609 /* remember where list of staffs begins and skip
610 * the rest of the STAFFs */
611 first_staff_mll_p
= mll_p
;
612 for ( ; mll_p
->next
->str
== S_STAFF
;
613 mll_p
= mll_p
->next
) {
619 if (mll_p
->u
.bar_p
->endingloc
== STARTITEM
) {
620 mll_p
= do_carry_ties(first_staff_mll_p
, mll_p
);
625 /* actually, it should be impossible to hit this case,
626 * because clefsigs with pseudo-bar haven't been
627 * created yet at the time this is called, but if things
628 * are changed some day so things get done in a different
629 * order, this should then work. */
630 if (mll_p
->u
.clefsig_p
->bar_p
!= (struct BAR
*) 0 &&
631 mll_p
->u
.clefsig_p
->bar_p
->endingloc
633 mll_p
= do_carry_ties(first_staff_mll_p
, mll_p
);
638 asgnssv(mll_p
->u
.ssv_p
);
647 /* Save info about any ties and slurs on the last chords before the beginning
648 * of the ending. Then search forward in main list. If there are any more
649 * beginnings of endings, add padding to the appropriate groups.
650 * Return MAINLL at the end of the last ending processed. */
652 static struct MAINLL
*
653 do_carry_ties(staff_mll_p
, bar_mll_p
)
655 struct MAINLL
*staff_mll_p
; /* first staff in measure which ends on
656 * bar that begins an ending */
657 struct MAINLL
*bar_mll_p
; /* the bar that begins an ending */
660 struct MAINLL
*mll_p
; /* walk through list of staffs */
661 int v
; /* voice number */
664 /* save all the tie / slur info */
665 for (mll_p
= staff_mll_p
; mll_p
->str
== S_STAFF
; mll_p
= mll_p
->next
) {
667 for (v
= 0; v
< MAXVOICES
; v
++) {
668 savetieinfo(mll_p
, mll_p
->u
.staff_p
->groups_p
[v
]);
672 /* now search ahead for other endings */
673 for (mll_p
= bar_mll_p
->next
; mll_p
!= (struct MAINLL
*) 0;
674 mll_p
= mll_p
->next
) {
675 if (mll_p
->str
!= S_BAR
) {
679 switch (mll_p
->u
.bar_p
->endingloc
) {
685 carryin_ties(mll_p
->next
);
691 pfatal("fell off end of list while doing tie carries");
693 return( (struct MAINLL
*) 0);
697 /* given a GRPSYL, save info about any notes in it that have ties or slurs */
700 savetieinfo(mll_p
, gs_p
)
702 struct MAINLL
*mll_p
; /* main list struct that gs_p is connected to */
703 struct GRPSYL
*gs_p
; /* save info about ties/slurs on last group
707 int n
; /* note index */
708 int s
; /* slurto index */
711 if (gs_p
== (struct GRPSYL
*) 0) {
715 /* find last group in list */
716 for ( ; gs_p
->next
!= (struct GRPSYL
*) 0; gs_p
= gs_p
->next
) {
720 for (n
= 0; n
< gs_p
->nnotes
; n
++) {
723 if (gs_p
->notelist
[n
].tie
== YES
) {
724 do_save_tieinfo(gs_p
->staffno
, gs_p
->vno
,
725 gs_p
->notelist
[n
].letter
,
726 gs_p
->notelist
[n
].octave
, -1,
730 /* save slurto info */
731 for (s
= 0; s
< gs_p
->notelist
[n
].nslurto
; s
++) {
732 do_save_tieinfo(gs_p
->staffno
, gs_p
->vno
,
733 gs_p
->notelist
[n
].slurtolist
[s
].letter
,
734 gs_p
->notelist
[n
].slurtolist
[s
].octave
,
736 gs_p
->notelist
[n
].is_bend
);
742 /* save info about one tie or slur mark that will need to be carried into
743 * subsequent endings. Malloc space for info, fill it in, and put into table */
746 do_save_tieinfo(staffno
, vno
, letter
, octave
, curveno
, mll_p
, gs_p
, is_bend
)
750 int letter
; /* a to g */
753 struct MAINLL
*mll_p
; /* points to first group */
754 struct GRPSYL
*gs_p
; /* group of first note */
755 int is_bend
; /* YES if is actually a bend rather than slur */
758 struct TIECARRY
*new_p
;
760 MALLOC(TIECARRY
, new_p
, 1);
761 new_p
->letter
= (short) letter
;
762 new_p
->octave
= (short) octave
;
763 new_p
->curveno
= (short) curveno
;
764 new_p
->is_bend
= is_bend
;
765 new_p
->mll_p
= mll_p
;
767 new_p
->next
= Tiecarryinfolist_p
[staffno
] [vno
- 1];
768 Tiecarryinfolist_p
[staffno
] [vno
- 1] = new_p
;
770 Have_carry_ins
= YES
;
774 /* Once an ending has been found that may have ties/slurs carried in, use
775 * the saved information to add padding. */
780 struct MAINLL
*mll_p
; /* look for staffs from here for chords that may have
781 * things tied or slurred in */
784 if (Have_carry_ins
== NO
) {
789 /* skip everything up to STAFFS */
790 for ( ; mll_p
!= (struct MAINLL
*) 0; mll_p
= mll_p
->next
) {
791 if (mll_p
->str
== S_STAFF
) {
792 add_carryin(mll_p
->u
.staff_p
);
794 else if (mll_p
->str
== S_BAR
) {
801 /* given a STAFF which is at the beginning of an ending that may have ties/slurs
802 * carried in, go through each voice. If there is anything to carry in,
803 * add appropriate padding, then generate curve */
808 struct STAFF
*staff_p
; /* which staff to do ties/slur carry in on */
812 int v
; /* voice number */
813 int n
; /* index into notelist */
814 struct GRPSYL
*gs_p
; /* first chord in measure */
815 struct TIECARRY
*info_p
; /* info about things carried in */
816 int found
; /* if matching note found in chord */
817 double padding
; /* how much padding to add */
820 staffno
= staff_p
->staffno
;
821 /* do each carried in item on each voice */
822 for (v
= 0; v
< MAXVOICES
; v
++) {
824 padding
= HALFTIEPAD
;
826 for (info_p
= Tiecarryinfolist_p
[staffno
] [v
];
827 info_p
!= (struct TIECARRY
*) 0;
828 info_p
= info_p
->next
) {
830 gs_p
= staff_p
->groups_p
[v
];
832 /* add padding to allow for carried-in mark */
833 gs_p
->padding
+= padding
;
834 /* only add padding once per chord! */
837 /* mark any notes that will get carried-in mark */
838 for (found
= NO
, n
= 0; n
< gs_p
->nnotes
; n
++) {
839 if (gs_p
->notelist
[n
].letter
841 gs_p
->notelist
[n
].octave
844 /* A carried-in tie on a tablature
845 * staff isn't printed, but the fret
846 * is put in parentheses. */
847 if (is_tab_staff(staff_p
->staffno
) == YES
848 && info_p
->curveno
== -1) {
849 gs_p
->notelist
[n
].FRET_HAS_PAREN
= YES
;
857 l_warning(gs_p
->inputfile
, gs_p
->inputlineno
,
858 "can't carry tie/slur/bend into ending: %c%d not in chord",
859 info_p
->letter
, info_p
->octave
);
866 /* free all the tie carry in info */
876 for (s
= 1; s
<= MAXSTAFFS
; s
++) {
877 for (v
= 0; v
< MAXVOICES
; v
++) {
878 free_cinfo(Tiecarryinfolist_p
[s
] [v
]);
879 Tiecarryinfolist_p
[s
] [v
] = (struct TIECARRY
*) 0;
887 /* recursively free list of tie carry information */
890 free_cinfo(carryinfo_p
)
892 struct TIECARRY
*carryinfo_p
;
895 if (carryinfo_p
== (struct TIECARRY
*) 0) {
899 free_cinfo(carryinfo_p
->next
);
904 /* check if a transposition occurred, and if so, see if there were any
905 * ties that would cross the bar. If so, print warning and discard the tie */
910 struct MAINLL
*mll_p
; /* containing SSV that might contain transpose */
914 int s
; /* staff index */
915 int intnum
; /* transposition interval */
916 int inttype
; /* transposition interval type */
919 if (mll_p
->str
!= S_SSV
) {
923 ssv_p
= mll_p
->u
.ssv_p
;
924 if (ssv_p
->used
[TRANSPOSITION
] == YES
||
925 ssv_p
->used
[ADDTRANSPOSITION
] == YES
) {
926 /* this SSV changes transpose value, need to check further */
927 if (ssv_p
->context
== C_STAFF
) {
928 /* if staff now has a different transpose value than
929 * before, need to see if any notes tied over the
932 totaltrans(s
, &inttype
, & intnum
);
933 if (ssv_p
->inttype
!= inttype
934 || ssv_p
->intnum
!= intnum
) {
935 chkxpstaff(mll_p
, s
);
939 /* must be score wide change. This is a little
940 * trickier. Go through each staff. If its transpose
941 * value is not set in staff context and it's
942 * different than the new transpose value, then
943 * we need to check for ties */
944 for (s
= 1; s
<= Score
.staffs
; s
++) {
945 totaltrans(0, &inttype
, & intnum
);
946 if (Staff
[s
].used
[TRANSPOSITION
] == NO
&&
947 Staff
[s
].used
[ADDTRANSPOSITION
] == NO
&&
948 (ssv_p
->inttype
!= inttype
949 || ssv_p
->intnum
!= intnum
)) {
950 chkxpstaff(mll_p
, s
);
958 /* check a specific staff for possible ties across transposition */
963 struct MAINLL
*mll_p
; /* look backward in main list from here */
964 int s
; /* which staff */
970 /* back up to find appropriate staff */
971 for (mll_p
= mll_p
->prev
; mll_p
!= (struct MAINLL
*) 0;
972 mll_p
= mll_p
->prev
) {
973 if (mll_p
->str
== S_STAFF
) {
974 if (mll_p
->u
.staff_p
->staffno
== s
) {
975 /* found the correct staff. check each voice */
976 for (v
= 0; v
< MAXVOICES
; v
++) {
977 chkxpgrp(mll_p
->u
.staff_p
->groups_p
[v
],
983 else if (mll_p
->u
.staff_p
->staffno
< s
) {
984 /* user must have increased the number of
985 * staffs as well, so the staff in question
986 * didn't exist in previous measure */
994 /* find the last group in a list of grpsyls. If it has any ties on it,
995 * print warning message for trying to tie across a transposition, and discard
999 chkxpgrp(gs_p
, inputfile
, lineno
)
1001 struct GRPSYL
*gs_p
; /* check this grpsyl list */
1002 char *inputfile
; /* for error message */
1006 register int n
; /* index through notelist */
1009 /* find last group in list */
1010 for ( ; gs_p
!= (struct GRPSYL
*) 0; gs_p
= gs_p
->next
) {
1012 if (gs_p
->next
== (struct GRPSYL
*) 0) {
1013 /* this is the last group in the measure. See if
1014 * it has any ties on it */
1015 for (n
= 0; n
< gs_p
->nnotes
; n
++) {
1016 if (gs_p
->notelist
[n
].tie
== YES
) {
1017 /* Aha! User tried to do a tie over
1019 l_warning(inputfile
, lineno
,
1020 "can't tie into transposition change (use slur)");
1021 /* cancel any and all ties on this grp,
1022 * and return, so we don't print more
1023 * than one error per group */
1024 for (n
= 0; n
< gs_p
->nnotes
; n
++) {
1025 gs_p
->notelist
[n
].tie
= NO
;
1036 /* On tablature staffs, if two consecutive groups are tied together,
1037 * normally the frets are not printed for the second group, so we need
1038 * to set the inhibitprint flag on the group. However if there is any
1039 * reason why inhibiting printing on a given group isn't a good idea,
1040 * we won't set the inhibitprint flag. So this function checks all the
1041 * possible reasons for not setting inhibitprint, and if none of them
1042 * apply, then it is set.
1046 set_inhibitprint_if_appropriate(gs_p
, mll_p
)
1048 struct GRPSYL
*gs_p
;
1049 struct MAINLL
*mll_p
;
1052 struct GRPSYL
*nextgs_p
; /* the group after gs_p */
1053 struct GRPSYL
*following_p
; /* the group after next_gs_p */
1054 int n
; /* index through notelist */
1058 if ((nextgs_p
= nextgrpsyl(gs_p
, &mll_p
)) == (struct GRPSYL
*) 0) {
1059 /* no next group, so nothing to set */
1063 /* if this group and next group don't have same number of notes,
1064 * then there won't be an inhibitprint on the next group */
1065 if (gs_p
->nnotes
== 0 || gs_p
->nnotes
!= nextgs_p
->nnotes
) {
1069 /* if next group has a "with" list, no inhibitprint */
1070 if (nextgs_p
->nwith
!= 0) {
1074 for (n
= 0; n
< gs_p
->nnotes
; n
++) {
1075 /* if any notes in this group are not tied, then there won't be
1076 * an inhibitprint on the next group */
1077 if (gs_p
->notelist
[n
].tie
== NO
) {
1081 /* if next group has any slides to/from nowhere, or slurs
1082 * to the next group, it won't get inhibitprint set */
1083 if (nextgs_p
->notelist
[n
].nslurto
!= 0) {
1088 /* next group has a bend of any sort, it doesn't get inhibitprint */
1089 for (n
= 0; n
< nextgs_p
->nnotes
; n
++) {
1090 if (HASBEND(nextgs_p
->notelist
[n
]) == YES
) {
1095 /* if group following next group has a non-prebend bend, then the
1096 * next group does not get inhibitprint */
1097 if ((following_p
= nextgrpsyl(nextgs_p
, &mll_p
)) != (struct GRPSYL
*) 0) {
1098 for (n
= 0; n
< following_p
->nnotes
; n
++) {
1099 if (HASBEND(following_p
->notelist
[n
]) == YES
&&
1100 following_p
->notelist
[n
].FRETNO
== NOFRET
) {
1106 /* Whew! If we got here, the group passed all the tests to have its
1107 * inhibitprint flag set, so set it */
1108 nextgs_p
->inhibitprint
= YES
;