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;