chiark / gitweb /
Import upstream version 5.3.
[mup] / mup / mup / beaming.c
CommitLineData
69695f33
MW
1
2/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005 by Arkkra Enterprises */
3/* All rights reserved */
4
5/* functions called at parse time to deal with beaming. */
6
7
8#include "defines.h"
9#include "structs.h"
10#include "globals.h"
11
12
13static void subbeam P((struct SSV *ssv_p, RATIONAL outer_time, int obi,
14 struct GRPSYL *begin_gs_p, struct GRPSYL *end_gs_p));
15static struct GRPSYL *verify_crossbeam P((struct GRPSYL *gs_p,
16 struct GRPSYL *other_gs_p, RATIONAL start_time, RATIONAL *end_time_p,
17 int staffno, int size));
18static void
19slopelencheck P((struct GRPSYL *first_p, struct GRPSYL *last_p, char *bmtype));
20
21
22/* this function will get called whenever a group is not the start or end
23 * of a custom beam group. This will fill in the beamloc based on past
24 * history. If we were most recently in a custom beam group, we still are.
25 * If we weren't before, we aren't now either. The non-custom beaming
26 * gets done later after we have collected a whole bar in do_beaming()
27 * which is called via do_bar(). */
28
29void
30setbeamloc(curr_grp_p, last_grp_p)
31
32struct GRPSYL *curr_grp_p; /* the group we're working on */
33struct GRPSYL *last_grp_p; /* the last group we did */
34
35{
36 if (curr_grp_p->grpvalue == GV_ZERO) {
37 /* grace notes don't get handled here */
38 curr_grp_p->beamloc = NOITEM;
39 return;
40 }
41
42 /* if the previous group is a grace group, that doesn't count. Back
43 * up in the list to the first non-grace or beginning of list */
44 for ( ; last_grp_p != (struct GRPSYL *) 0
45 && last_grp_p->grpvalue == GV_ZERO;
46 last_grp_p = last_grp_p->prev) {
47 ;
48 }
49
50 if (last_grp_p != (struct GRPSYL *) 0) {
51
52 switch (last_grp_p->beamloc) {
53
54 case STARTITEM:
55 case INITEM:
56 curr_grp_p->beamto = last_grp_p->beamto;
57 /* Make sure notes are 8th or shorter. Spaces (which
58 * are allowed in cross-staff beams) can be longer. */
59 if (curr_grp_p->basictime < 8) {
60 /* At this point, spaces are still
61 * pseudo-pitches, so have to figure out
62 * if this group is really notes */
63 int letter; /* pitch */
64 int n; /* index through notelist */
65 for (n = 0; n < curr_grp_p->nnotes; n++) {
66 letter = curr_grp_p->notelist[n].letter;
67 if ((letter >= 'a' && letter <= 'g') ||
68 letter == PP_NO_PITCH) {
69 yyerror("beamed notes must be 8th or shorter");
70 break;
71 }
72 }
73 }
74
75 /* if previous began beaming, we must be inside now */
76 /* if in beam before, we still are */
77 curr_grp_p->beamloc = INITEM;
78 break;
79
80 case ENDITEM:
81 case NOITEM:
82 default:
83 /* if previous was ending beaming, or
84 * we weren't inside a beam, must be no beam now */
85 curr_grp_p->beamloc = NOITEM;
86 break;
87 }
88 }
89 else {
90 /* nothing specified before, so no beam */
91 curr_grp_p->beamloc = NOITEM;
92 }
93}
94\f
95
96/* take a quick jaunt through a GRPSYL list, seeing if custom
97 * beaming was already done. If so, return YES, otherwise NO.
98 * If there are any non-grace groups with beaming info, there must
99 * have been custom beaming. Also, verify that user didn't attempt to
100 * custom beam a mixture of normal and cue size notes,
101 * or try to put illegal rests or spaces inside a beam.
102 * Spaces are only allowed in cross-staff beams, unless user explicitly
103 * says to beam across spaces. Rests are also only allowed in beams if
104 * the user explicitly states they should be. Rests and spaces cannot be on
105 * the ends, and must be eighth note or shorter.
106 * We allow beaming together chords that are stemmed to another staff
107 * only if all such instances are to the same staff--not some to staff above
108 * and others to staff below--because beaming involving 3 staffs at once is
109 * just too hard to deal with.
110 * Also check that any esbm has at least 2 notes before and after it.
111 */
112
113int
114has_cust_beaming(grpsyl_p)
115
116struct GRPSYL *grpsyl_p; /* list of GRPSYLs to check */
117
118{
119 int has = NO;
120 int size = GS_NORMAL;
121 int numnotes = 0; /* how many notes groups, for esbm check */
122 short stemto = CS_SAME; /* to check for mixed CS_ABOVE/CS_BELOW */
123 struct GRPSYL *start_p = 0; /* first beamed group */
124
125 for ( ; grpsyl_p != (struct GRPSYL *) NULL;
126 grpsyl_p = grpsyl_p->next) {
127
128 if ((grpsyl_p->grpvalue != GV_ZERO)
129 && (grpsyl_p->beamloc != NOITEM)) {
130 /* have non-grace with beam info set */
131 has = YES;
132
133 /* check for size or cross-staff stem mixtures */
134 if (grpsyl_p->beamloc == STARTITEM) {
135 size = grpsyl_p->grpsize;
136 numnotes = 0;
137 stemto = CS_SAME;
138 }
139 /* check for size mixture. But only do non-cross-staff
140 * beams here, because it's a lot easier to do the
141 * cross-staff beam check in chk_crossbeams() */
142 else if (grpsyl_p->grpsize != size
143 && grpsyl_p->beamto == CS_SAME) {
144 l_yyerror(grpsyl_p->inputfile,
145 grpsyl_p->inputlineno,
146 "can't beam normal and cue notes together");
147 }
148
149 if (grpsyl_p->grpcont != GC_NOTES) {
150 if (grpsyl_p->grpcont == GC_REST) {
151 if (grpsyl_p->basictime < 8) {
152 l_yyerror(grpsyl_p->inputfile,
153 grpsyl_p->inputlineno,
154 "rests inside a beam must be less than quarter note duration");
155 }
156 if (grpsyl_p->beamloc != INITEM) {
157 l_yyerror(grpsyl_p->inputfile,
158 grpsyl_p->inputlineno,
159 "beam cannot %s with a rest",
160 grpsyl_p->beamloc == STARTITEM ?
161 "begin" : "end");
162 }
163 }
164 else if (grpsyl_p->beamto == CS_SAME) {
165 if (grpsyl_p->beamloc != INITEM) {
166 l_yyerror(grpsyl_p->inputfile,
167 grpsyl_p->inputlineno,
168 "beam cannot begin or end with a space");
169 }
170 if (grpsyl_p->basictime < 8) {
171 l_yyerror(grpsyl_p->inputfile,
172 grpsyl_p->inputlineno,
173 "spaces inside a beam must be less than quarter note duration");
174 }
175 }
176 }
177 else if (grpsyl_p->grpvalue != GV_ZERO) {
178 numnotes++;
179 }
180
181 if (grpsyl_p->stemto != CS_SAME) {
182 if (stemto != CS_SAME && grpsyl_p->stemto
183 != stemto) {
184 l_yyerror(grpsyl_p->inputfile,
185 grpsyl_p->inputlineno,
186 "beam cannot include chords with stems to both above and below staffs");
187 }
188 stemto = grpsyl_p->stemto;
189 }
190
191 if (grpsyl_p->beamloc == INITEM &&
192 IS_STEMLEN_KNOWN(grpsyl_p->stemlen)) {
193 l_yyerror(grpsyl_p->inputfile,
194 grpsyl_p->inputlineno,
195 "stem len specification not allowed inside a beam");
196 }
197
198 if (grpsyl_p->beamloc == STARTITEM) {
199 start_p = grpsyl_p;
200 }
201 else if (grpsyl_p->beamloc == ENDITEM) {
202 if (start_p != 0) {
203 slopelencheck(start_p, grpsyl_p, "beam");
204 start_p = 0;
205 }
206 }
207
208 if (grpsyl_p->breakbeam == YES
209 && grpsyl_p->beamto == CS_SAME) {
210 if (numnotes < 2) {
211 l_warning(grpsyl_p->inputfile,
212 grpsyl_p->inputlineno,
213 "esbm must be preceeded by at least 2 beamed notes");
214 grpsyl_p->breakbeam = NO;
215 }
216 else {
217 struct GRPSYL *g_p;
218
219 /* Check that there are
220 * at least 2 following beamed notes */
221 numnotes = 0;
222 for (g_p = grpsyl_p->next; g_p != 0;
223 g_p = g_p->next) {
224 if (g_p->grpcont == GC_NOTES &&
225 g_p->grpvalue != GV_ZERO) {
226 numnotes++;
227 }
228 if (g_p->breakbeam == YES) {
229 break;
230 }
231 if (g_p->beamloc == ENDITEM) {
232 break;
233 }
234 }
235 if (numnotes < 2) {
236 l_warning(grpsyl_p->inputfile,
237 grpsyl_p->inputlineno,
238 "esbm must be followed by at least 2 beamed notes");
239 grpsyl_p->breakbeam = NO;
240 }
241 else if (grpsyl_p->grpcont != GC_NOTES) {
242 /* User really should have put
243 * the esbm on the preceeding
244 * NOTES group. We'll be nice
245 * and move it for them.
246 */
247 grpsyl_p->breakbeam = NO;
248 for (g_p = grpsyl_p->prev;
249 g_p->grpcont != GC_NOTES;
250 g_p = g_p->prev) {
251 ;
252 }
253 g_p->breakbeam = YES;
254 }
255 }
256 numnotes = 0;
257 }
258 }
259 }
260
261 return(has);
262}
263\f
264
265/* beam notes together according to user-specified default beaming style */
266
267void
268do_beaming(gs_p, grpsize, staffno, vno)
269
270struct GRPSYL *gs_p; /* list of GRPSYLs to do beaming on */
271int grpsize; /* GS_NORMAL or GS_SMALL
272 * (grace are handled separately) */
273int staffno;
274int vno; /* voice number */
275
276{
277 struct SSV *ssv_beaminfo_p; /* ssv having relevent beam info */
278 register int n; /* index into beamstyle list */
279 RATIONAL styletime; /* accumulated time to beam together */
280 RATIONAL tot_time; /* cumulative grpsyl time */
281 struct GRPSYL *first_p; /* first in beam group */
282 struct GRPSYL *last_p; /* last in beam group */
283 int stop; /* YES if need to stop beaming */
284 int beamrests; /* if to include rests inside beams */
285 int beamspaces; /* if to include spaces inside beams */
286 short stemto = CS_SAME; /* check for mixed CS_ABOVE/CS_BELOW */
287 short restart = NO; /* YES if could start another beam
288 * with current group, even though
289 * it can go with previous */
290
291
292
293 debug(4, "do_beaming file=%s line=%d grpsize=%d staff=%d voice=%d",
294 gs_p->inputfile, gs_p->inputlineno, grpsize, staffno, vno);
295
296 /* if no default beaming scheme for this voice, then nothing to do--
297 * any custom beaming would have already been done */
298 ssv_beaminfo_p = vvpath(staffno, vno, BEAMSTLIST);
299 if (ssv_beaminfo_p->nbeam == 0) {
300 return;
301 }
302
303 /* ok. We may need to do some beaming. Go through the beamstlist and
304 * see if there are any groups to beam together */
305
306 /* initialize */
307 /* point to first non-grace group */
308 for ( ; gs_p != (struct GRPSYL *) 0 && gs_p->grpcont == GC_NOTES
309 && gs_p->grpvalue == GV_ZERO; gs_p = gs_p->next) {
310 ;
311 }
312
313 /* if no groups, nothing to do */
314 if (gs_p == (struct GRPSYL *) 0) {
315 return;
316 }
317
318 beamrests = vvpath(staffno, vno, BEAMSTLIST)->beamrests;
319 beamspaces = vvpath(staffno, vno, BEAMSTLIST)->beamspaces;
320 styletime = tot_time = Zero;
321 for (n = 0; n < ssv_beaminfo_p->nbeam; n++) {
322 styletime = radd(styletime, ssv_beaminfo_p->beamstlist[n]);
323
324 if (GE(tot_time, styletime)) {
325 /* we're already past this beamstyle segment */
326 continue;
327 }
328
329 for (first_p = last_p = 0, stop = NO;
330 LT(tot_time, styletime); gs_p = gs_p->next) {
331
332 if (gs_p == 0) {
333 /* Must be too few groups in measure.
334 * This error will already have been
335 * reported elsewhere.
336 */
337 return;
338 }
339
340 /* ignore grace */
341 while (gs_p->grpvalue == GV_ZERO) {
342 gs_p = gs_p->next;
343 if (gs_p == 0) {
344 /* Must have tried to end a measure
345 * with grace. Already reported. */
346 return;
347 }
348 }
349
350 tot_time = radd(tot_time, gs_p->fulltime);
351 if (GE(tot_time, styletime)) {
352 /* This group puts us at or past
353 * the current beamstyle segment */
354 stop = YES;
355 }
356
357 /* only 8th and shorter get beamed */
358 if (gs_p->basictime < 8 || (gs_p->grpcont == GC_SPACE &&
359 beamspaces == NO) ) {
360 stop = YES;
361 }
362 else if (gs_p->grpcont == GC_REST && beamrests == NO) {
363 stop = YES;
364 }
365 else if (gs_p->grpsize != grpsize) {
366 /* Wrong size to beam on this call */
367 stop = YES;
368 }
369 else if (gs_p->stemto != CS_SAME && stemto != CS_SAME
370 && gs_p->stemto != stemto) {
371 /* We don't allow beaming across three staffs,
372 * so have to stop current beam, but could
373 * possibly beam this group with following
374 * groups, as long as they don't have a
375 * conflicting stemto */
376 stop = YES;
377 restart = YES;
378 }
379 else if (gs_p->grpcont == GC_NOTES &&
380 LE(tot_time, styletime)) {
381 /* found something beam-able */
382 if (first_p == 0) {
383 first_p = gs_p;
384 }
385 last_p = gs_p;
386 }
387 if (gs_p->stemto != CS_SAME) {
388 stemto = gs_p->stemto;
389 }
390
391 if (stop == YES) {
392 if (first_p != 0 && last_p != 0
393 && first_p != last_p) {
394 /* Disallow illegal combinations of
395 * slope and stem length */
396 slopelencheck(first_p, last_p, "beam");
397
398 /* If there are subbeam groupings,
399 * do those. */
400 subbeam(ssv_beaminfo_p,
401 rsub(styletime, ssv_beaminfo_p->beamstlist[n]),
402 n, first_p, last_p);
403
404 /* mark beginning of beam group */
405 first_p->beamloc = STARTITEM;
406
407 /* mark all intermediate groups,
408 * skipping grace */
409 for (first_p = first_p->next;
410 first_p != last_p;
411 first_p = first_p->next) {
412
413 if (first_p->grpvalue
414 == GV_ZERO) {
415 continue;
416 }
417
418 first_p->beamloc = INITEM;
419
420 if (IS_STEMLEN_KNOWN(first_p->stemlen)) {
421 l_yyerror(first_p->inputfile, first_p->inputlineno,
422 "stem len specification not allowed inside a beam");
423 }
424 }
425
426 /* mark the end of the beam group */
427 last_p->beamloc = ENDITEM;
428 }
429
430 /* Re-init for any more bunches to beam */
431 first_p = last_p = 0;
432 stop = NO;
433 stemto = CS_SAME;
434 if (restart == YES) {
435 if (gs_p->grpcont == GC_NOTES) {
436 first_p = gs_p;
437 }
438 restart = NO;
439 }
440 }
441 }
442 }
443}
444\f
445
446/* Once a STARTITEM and ENDITEM groups of the regular beamstyle
447 * have been identified, go through them to see if there should
448 * be subgroups. If so, mark breakbeam = YES on the last group of
449 * each subgroup.
450 */
451
452static void
453subbeam(ssv_p, outer_time, obi, begin_gs_p, end_gs_p)
454
455struct SSV *ssv_p; /* to get beamstlist and subbeamstlist */
456RATIONAL outer_time; /* Time in measure when outer beam begins */
457int obi; /* outer beam index, subscript into ssv_p->beamstlist */
458struct GRPSYL *begin_gs_p;
459struct GRPSYL *end_gs_p;
460
461{
462 int sbi; /* sub beam index, subscript of ssv_p->subbeamstlist */
463 RATIONAL subgroup_time; /* duration of items in subbeamstlist */
464 RATIONAL tot_time; /* sum of note groups in subbeaming */
465 struct GRPSYL *gs_p; /* walk through groups */
466 struct GRPSYL *last_notegroup_p;/* Most recent GC_NOTES GRPSYL */
467
468
469 /* Check if more than one beam subgroup
470 * makes up the outer beam grouping. */
471 if (ssv_p->nbeam == ssv_p->nsubbeam) {
472 /* There are no sub-beam groupings anywhere in the measure */
473 return;
474 }
475
476 /* Find the subbeamlist entry that matches with the outer beam entry */
477 subgroup_time = Zero;
478 for (sbi = 0; LT(subgroup_time, outer_time); sbi++) {
479 subgroup_time = radd(subgroup_time, ssv_p->subbeamstlist[sbi]);
480 }
481
482 if ( EQ(ssv_p->beamstlist[obi], ssv_p->subbeamstlist[sbi]) ) {
483 /* Outer and subbeam have the same time duration,
484 * so there aren't any subgroups in this outer beam grouping. */
485 return;
486 }
487
488 /* There are subgroups inside the outer beam grouping,
489 * so we may need to set one or more breakbeams. */
490 subgroup_time = ssv_p->subbeamstlist[sbi];
491
492 /* If beam starts later than the outer beamstyle item begins,
493 * (e.g., if there was a rest at the beginning of the beam time),
494 * we have to count that time as already taken up from the subbeam.
495 */
496 for (tot_time = Zero, gs_p = begin_gs_p->prev; gs_p != 0;
497 gs_p = gs_p->prev) {
498 tot_time = radd(tot_time, gs_p->fulltime);
499 }
500 tot_time = rsub(tot_time, outer_time);
501 last_notegroup_p = 0;
502 for (gs_p = begin_gs_p; gs_p != end_gs_p; gs_p = gs_p->next) {
503
504 /* Grace notes are irrelevant */
505 if (gs_p->grpvalue == GV_ZERO) {
506 continue;
507 }
508
509 /* Remember where last note group is, in case we
510 * need to set breakbeam on it. */
511 if (gs_p->grpcont == GC_NOTES) {
512 last_notegroup_p = gs_p;
513 }
514
515 /* Add up group time values until the total equals
516 * or exceeds that of the subgroup. */
517 tot_time = radd(tot_time, gs_p->fulltime);
518 if (LT(tot_time, subgroup_time)) {
519 /* not far enough yet */
520 continue;
521 }
522
523 /* If the value exceeds, there is a note spanning the
524 * subgroup boundary, so just ignore the subgrouping. */
525 if (GT(tot_time, subgroup_time)) {
526 tot_time = rsub(tot_time, subgroup_time);
527 subgroup_time = ssv_p->subbeamstlist[++sbi];
528 if (gs_p->grpcont != GC_NOTES) {
529 last_notegroup_p = 0;
530 }
531 }
532
533 else {
534 /* A group ends right at the subbeam boundary.
535 * Set breakbeam on last group, if there was one.
536 */
537 if (last_notegroup_p != 0) {
538 last_notegroup_p->breakbeam = YES;
539 }
540
541 /* The current subbeam is finished.
542 * Move on to the next subbeam, if there is one. */
543 if (++sbi < ssv_p->nsubbeam) {
544 subgroup_time = ssv_p->subbeamstlist[sbi];
545 /* Since we know the subbeam we just
546 * finished ended exactly
547 * at the subbeam boundary,
548 * we set to time taken up so far
549 * by the new subbeam to zero.
550 */
551 tot_time = Zero;
552 last_notegroup_p = 0;
553 }
554 }
555 }
556}
557\f
558
559/* alt groups must always have beamloc set, so fix them */
560
561void
562set_alt_beams(gs_p)
563
564struct GRPSYL *gs_p; /* a measure's worth of GRPSYLs for a voice */
565
566{
567 struct GRPSYL *other_gs_p; /* group on other end of alt pair */
568
569
570 debug(4, "set_alt_beams file=%s line=%d",
571 gs_p->inputfile, gs_p->inputlineno);
572
573 /* walk through the list, fixing any alt groups */
574 for ( ; gs_p != (struct GRPSYL *) 0; gs_p = gs_p->next) {
575
576 /* check if is an alt pair */
577 if (gs_p->slash_alt < 0) {
578
579 if (gs_p->next == (struct GRPSYL *) 0) {
580 /* no second group in alt, will be flagged
581 * elsewhere */
582 continue;
583 }
584
585 /* set the pair as a beam group */
586 gs_p->beamloc = STARTITEM;
587 gs_p->next->beamloc = ENDITEM;
588
589 slopelencheck(gs_p, gs_p->next, "alt");
590
591 /* middle phase wants to have both notes in an alt group
592 * have their alt field set, so do that */
593 gs_p->next->slash_alt = gs_p->slash_alt;
594
595 /* adjust preceeding and following groups if necessary.
596 * If was already in a beam group, split off the other
597 * parts into their own groups or put flags on the
598 * extras if they are down to one group */
599
600 /* find previous normal group if any and adjust */
601 for (other_gs_p = gs_p->prev;
602 other_gs_p != (struct GRPSYL *) 0;
603 other_gs_p = other_gs_p->prev) {
604
605 if (other_gs_p->grpvalue != GV_ZERO) {
606 if (other_gs_p->grpcont == GC_REST) {
607 other_gs_p->beamloc = NOITEM;
608 }
609 else {
610 break;
611 }
612 }
613 }
614
615 if (other_gs_p != (struct GRPSYL *) 0) {
616
617 switch (other_gs_p->beamloc) {
618
619 case INITEM:
620 other_gs_p->beamloc = ENDITEM;
621 break;
622
623 case STARTITEM:
624 other_gs_p->beamloc = NOITEM;
625 break;
626
627 default:
628 break;
629 }
630 }
631
632 /* now do the same for the following group */
633 for (other_gs_p = gs_p->next->next;
634 other_gs_p != (struct GRPSYL *) 0;
635 other_gs_p = other_gs_p->next) {
636
637 if (other_gs_p->grpvalue != GV_ZERO) {
638 if (other_gs_p->grpcont == GC_REST) {
639 other_gs_p->beamloc = NOITEM;
640 }
641 else {
642 break;
643 }
644 }
645 }
646
647 if (other_gs_p != (struct GRPSYL *) 0) {
648
649 switch (other_gs_p->beamloc) {
650
651 case INITEM:
652 other_gs_p->beamloc = STARTITEM;
653 break;
654
655 case ENDITEM:
656 other_gs_p->beamloc = NOITEM;
657 break;
658
659 default:
660 break;
661 }
662 }
663
664 /* skip over the second in the pair */
665 gs_p = gs_p->next;
666 }
667 }
668}
669\f
670
671/* Given a list of GRPSYLs on a visible voice
672 * having "bm with staff below" do all the error checking.
673 * This list of groups has to be for the bottom visible voice
674 * for the duration of the beam.
675 * There has to be a set of groups on the top non-space visible
676 * voice of the first visible staff below,
677 * which starts a "bm with staff above" at exactly
678 * the same time value. The ebm values also have to match. At every
679 * point inside the beam, one voice must have notes and the other voice
680 * must have spaces.
681 *
682 * Have to be careful in this function,
683 * because the gs_p->staffno and gs_p->vno may not be filled in yet,
684 * so have to use the staffno from the STAFF struct, and get vno from the
685 * first gs_p, which the caller is supposed to have filled in correctly.
686 *
687 * Returns the staff number of the staff containing the matching
688 * "bm with staff above" or -1 if no such staff was found.
689 */
690
691int
692chk_crossbeam(gs_p, mll_p)
693
694struct GRPSYL *gs_p; /* first group in above voice of cross staff beam */
695struct MAINLL *mll_p; /* gs_p hangs off of here */
696
697{
698 struct GRPSYL *g_p; /* for walking through group list */
699 struct GRPSYL *other_p; /* group on other staff */
700 struct MAINLL *assoc_mll_p; /* other staff hangs off of here */
701 struct GRPSYL *assoc_grps_p; /* the measure-worth of groups in
702 * the voice being beamed to */
703 RATIONAL start_time, end_time; /* of the above voice */
704 RATIONAL other_start, other_end;/* time of groups on below staff */
705 int user_specified_stem_len; /* YES or NO */
706 int size = GS_NORMAL;
707 int assoc_vno; /* voice number on below staff */
708 struct STAFF *staff_p;
709 int staffno;
710 int vno;
711
712
713 /* only the first gs_p is guaranteed to have the right vno at this
714 * point, so save that. */
715 vno = gs_p->vno;
716 staff_p = mll_p->u.staff_p;
717 staffno = staff_p->staffno;
718
719 /* find where in the measure the beam begins, by adding up the
720 * time values of all the groups prior to the first beamed group */
721 for (start_time = Zero, g_p = gs_p->prev; g_p != (struct GRPSYL *) 0;
722 g_p = g_p->prev) {
723 start_time = radd(start_time, g_p->fulltime);
724 }
725
726 /* find how long the beam lasts. Also see if there are any small
727 * groups */
728 for (end_time = start_time, g_p = gs_p; g_p != (struct GRPSYL *) 0;
729 g_p = g_p->next) {
730 /* accumulate the time */
731 end_time = radd(end_time, g_p->fulltime);
732
733 /* check for small groups */
734 if (g_p->grpcont == GC_NOTES && g_p->grpsize == GS_SMALL
735 && g_p->grpvalue != GV_ZERO) {
736 size= GS_SMALL;
737 }
738
739 /* end of the beam? */
740 if (g_p->beamloc == ENDITEM && g_p->grpvalue != GV_ZERO) {
741 break;
742 }
743 }
744 if (g_p == (struct GRPSYL *) 0) {
745 /* maybe this should be silent, since another error message
746 * should already be printed, but this will point out that
747 * the problem was on a cross-staff beam */
748 l_yyerror(gs_p->inputfile, gs_p->inputlineno,
749 "can't find end of cross-staff beam");
750 return(-1);
751 }
752
753 /* Make sure this is the bottom voice of the above staff.
754 * If it's voice 2 (subscript 1) then it is for sure.
755 * Otherwise, have to make sure the second and third voices, if any,
756 * have all spaces for the duration of the cross-staff beam */
757 if (vno != 1) {
758 /* If voice 2 is visible and not all spaces,
759 * or if we are working on voice 1 while voice 3 is
760 * visible and not all space, there is a problem. */
761 if (vvpath(staffno, 2, VISIBLE)->visible == YES &&
762 hasspace(staff_p->groups_p[1], start_time,
763 end_time) == NO || (vno == 0 &&
764 vvpath(staffno, 3, VISIBLE)->visible == YES &&
765 hasspace(mll_p->u.staff_p->groups_p[2],
766 start_time, end_time) == NO)) {
767 l_yyerror(gs_p->inputfile, gs_p->inputlineno,
768 "cross-staff beam must be from bottom voice of staff %d",
769 mll_p->u.staff_p->staffno);
770 return(-1);
771 }
772 }
773
774 /* Find the associated voice, and the associated bm group
775 * in that voice. First find the next visible staff */
776 for (assoc_mll_p = mll_p->next; ; assoc_mll_p = assoc_mll_p->next) {
777 if (assoc_mll_p == (struct MAINLL *) 0 ||
778 assoc_mll_p->str != S_STAFF) {
779 l_yyerror(gs_p->inputfile, gs_p->inputlineno,
780 "no visible staff below to beam with");
781 return(-1);
782 }
783
784 if (svpath(assoc_mll_p->u.staff_p->staffno, VISIBLE)->visible
785 == YES) {
786 /* found the right staff */
787 break;
788 }
789 }
790
791 /* Associated voice is probably voice 1 of the below staff.
792 * But there is a slight possibility it is voice 2, or even voice 3.
793 * Skip over voices that are all spaces for the duration of the beam.
794 * Since voice 3 is the "middle" voice, we check 1, then 3, then 2.
795 */
796 if (vvpath(staffno, 1, VISIBLE)->visible == YES &&
797 hasspace(assoc_mll_p->u.staff_p->groups_p[0],
798 start_time, end_time) == NO) {
799 assoc_grps_p = assoc_mll_p->u.staff_p->groups_p[0];
800 assoc_vno = 0;
801 }
802 else if (vvpath(staffno, 3, VISIBLE)->visible == YES &&
803 hasspace(assoc_mll_p->u.staff_p->groups_p[2],
804 start_time, end_time) == NO) {
805 assoc_grps_p = assoc_mll_p->u.staff_p->groups_p[2];
806 assoc_vno = 2;
807 }
808 else if (vvpath(staffno, 2, VISIBLE)->visible == YES &&
809 hasspace(assoc_mll_p->u.staff_p->groups_p[1],
810 start_time, end_time) == NO) {
811 assoc_grps_p = assoc_mll_p->u.staff_p->groups_p[1];
812 assoc_vno = 1;
813 }
814 else {
815 l_yyerror(gs_p->inputfile, gs_p->inputlineno,
816 "cross-staff beam has no notes on staff %d",
817 assoc_mll_p->u.staff_p->staffno);
818 return(-1);
819 }
820
821 /* Tab staffs can't be involved in cross-staff beaming */
822 if (is_tab_staff(mll_p->u.staff_p->staffno) ||
823 is_tab_staff(assoc_mll_p->u.staff_p->staffno)) {
824 l_yyerror(gs_p->inputfile, gs_p->inputlineno,
825 "cross-staff beaming not allowed on tab staff");
826 return(-1);
827 }
828
829 /* We don't allow the different staffs to have different staffscale
830 * values: it doesn't really make much sense to allow it, and avoids
831 * all the issues like how wide to make the beams.
832 */
833 if (svpath(mll_p->u.staff_p->staffno, STAFFSCALE)->staffscale !=
834 svpath(assoc_mll_p->u.staff_p->staffno,
835 STAFFSCALE)->staffscale) {
836 l_yyerror(gs_p->inputfile, gs_p->inputlineno,
837 "staffs involved with cross-staff beams must have identical staffscale values");
838 /* We did find which to associate with, even though
839 * its staffscale was wrong. */
840 return(assoc_mll_p->u.staff_p->staffno);
841 }
842
843 /* find the group that ought to be the "bm with staff above" group, by
844 * going that far time-wise into the measure on the associated voice */
845 for (other_start = Zero, other_p = assoc_grps_p;
846 other_p != (struct GRPSYL *) 0;
847 other_p = other_p->next) {
848
849 if (GT(other_start, start_time)) {
850 /* too far. pretend to be at end of list so we
851 * and fall out of loop to print the error message
852 * for this case */
853 other_p = (struct GRPSYL *) 0;
854 break;
855 }
856
857 if (EQ(other_start, start_time)) {
858 /* found it! */
859 break;
860 }
861
862 if (other_p->grpvalue == GV_ZERO) {
863 continue;
864 }
865
866 /* have to keep going. Keep track of how far we are in time */
867 other_start = radd(other_start, other_p->fulltime);
868 }
869
870 /* skip past any grace groups */
871 while (other_p != 0 && other_p->grpvalue == GV_ZERO) {
872 other_p = other_p->next;
873 }
874
875 /* If we didn't find a voice below, or that voice's group
876 * isn't the start of a beam with above, there is a problem.
877 * In the second case, maybe user really meant to beam with some
878 * lower voice, but that would collide, which we don't allow.
879 */
880 if (other_p == (struct GRPSYL *) 0 || other_p->beamloc != STARTITEM
881 || other_p->beamto != CS_ABOVE) {
882 l_yyerror(gs_p->inputfile, gs_p->inputlineno,
883 "'bm with staff below' has no matching 'bm with staff above' (may be missing, invisible, or on wrong voice)");
884 return(assoc_mll_p->u.staff_p->staffno);
885 }
886
887 /* check if user specified a stem length on the first group */
888 if (IS_STEMLEN_KNOWN(gs_p->stemlen)
889 || IS_STEMLEN_KNOWN(other_p->stemlen)) {
890 user_specified_stem_len = YES;
891 }
892 else {
893 user_specified_stem_len = NO;
894 }
895
896 /* go through the two voices. For each note group, verify that
897 * the other voice has space during that time period. Do the "other"
898 * staff first, because in a previous version of this function it
899 * had to be done in that order to avoid possible null pointer
900 * dereference. Now things have changed, so that doesn't matter
901 * any more, but I don't want to change the order, to make sure I
902 * don't break something.
903 */
904 other_p = verify_crossbeam(other_p,
905 mll_p->u.staff_p->groups_p[vno], start_time,
906 &other_end, assoc_mll_p->u.staff_p->staffno, size);
907 gs_p = verify_crossbeam(gs_p, assoc_grps_p, start_time, &end_time,
908 mll_p->u.staff_p->staffno, size);
909
910 /* we should be pointing to the ebm group for each staff,
911 * unless of course, something went wrong, like user didn't
912 * specify an ebm */
913 if (gs_p == (struct GRPSYL *) 0 || other_p == (struct GRPSYL *) 0) {
914 /* maybe this should be silent, since another error message
915 * should already be printed, but this will point out that
916 * the problem was on a cross-staff beam */
917 l_yyerror(assoc_grps_p->inputfile, assoc_grps_p->inputlineno,
918 "failed to find ebm for cross-staff beam");
919 return(assoc_mll_p->u.staff_p->staffno);
920 }
921
922 if (NE(end_time, other_end)) {
923 l_yyerror(gs_p->inputfile, gs_p->inputlineno,
924 "ebm not at same time in measure for both voices of cross-staff beam");
925 }
926
927 /* Disallow illegal combinations of slope and stem length */
928 slopelencheck(gs_p, other_p, "beam");
929
930 return(assoc_mll_p->u.staff_p->staffno);
931}
932\f
933
934/* Given the first group of a cross-staff beam, and the beginning of the
935 * list of GRPSYLs in the associated voice (the voice beamed to), and the
936 * time into the measure where the beam starts, check each group. Verify
937 * that each GC_NOTES group has GC_SPACE in the other voice and vice-versa.
938 * Also check that all note groups are the same size, and mark the spaces
939 * as the correct size so that everything in the beam has the same size.
940 * Return a pointer to the last group in the beam (null if something goes
941 * wrong). Also, return the time into the measure of the end of the beam,
942 * via the end_time_p pointer.
943 */
944
945static struct GRPSYL *
946verify_crossbeam(gs_p, other_gs_p, start_time, end_time_p, staffno, size)
947
948struct GRPSYL *gs_p; /* first group in list to be checked */
949struct GRPSYL *other_gs_p; /* the groups_p of the associated voice */
950RATIONAL start_time; /* when the beam begins */
951RATIONAL *end_time_p; /* time through end of beam will be returned here */
952int staffno;
953int size; /* GS_NORMAL or GS_SMALL */
954
955{
956 RATIONAL end_time;
957 int has_at_least_1_note_group = NO;
958
959
960 /* go through each group in the beam */
961 for ( ; gs_p != (struct GRPSYL *) 0; gs_p = gs_p->next) {
962
963 /* skip over any grace groups */
964 if (gs_p->grpvalue == GV_ZERO) {
965 continue;
966 }
967
968 /* find the end time of the group, for passing to hasspace() */
969 end_time = radd(start_time, gs_p->fulltime);
970
971 /* if notes, other voice must have space */
972 if (gs_p->grpcont == GC_NOTES) {
973 if (hasspace(other_gs_p, start_time, end_time) == NO) {
974 l_yyerror(gs_p->inputfile, gs_p->inputlineno,
975 "cross-staff beam must always have notes in one voice and space in the other voice");
976 return (struct GRPSYL *) 0;
977 }
978 has_at_least_1_note_group = YES;
979 if (gs_p->grpsize != size) {
980 l_yyerror(gs_p->inputfile, gs_p->inputlineno,
981 "can't mix normal and cue size chords in cross-staff beam");
982 }
983 }
984
985 /* conversely, if space, other voice must not have space */
986 else if (gs_p->grpcont == GC_SPACE) {
987 struct GRPSYL *g_p;
988 RATIONAL t;
989 int oldcont = GC_SPACE;
990
991 /* This is somewhat like hasspace() except that checks
992 * that the entire duration is space. Here we need
993 * to check if there is space at least somewhere during
994 * the time period. If so, user error.
995 */
996 for (g_p = other_gs_p, t = Zero; LT(t, start_time);
997 g_p = g_p->next) {
998 if (g_p->grpvalue == GV_ZERO) {
999 continue;
1000 }
1001 t = radd(t, g_p->fulltime);
1002 oldcont = g_p->grpcont;
1003 }
1004 if (GT(t, start_time) && oldcont == GC_SPACE) {
1005 /* group spilling into this time is space */
1006 l_yyerror(gs_p->inputfile, gs_p->inputlineno,
1007 "cross-staff beam must always have notes in one voice and space in the other voice");
1008 return (struct GRPSYL *) 0;
1009 }
1010 for ( ; g_p != 0 && LT(t, end_time); g_p = g_p->next) {
1011 if (g_p->grpvalue == GV_ZERO) {
1012 continue;
1013 }
1014 if (g_p->grpcont == GC_SPACE) {
1015 l_yyerror(gs_p->inputfile, gs_p->inputlineno,
1016 "cross-staff beam must always have notes in one voice and space in the other voice");
1017 return (struct GRPSYL *) 0;
1018 }
1019 t = radd(t, g_p->fulltime);
1020 }
1021
1022 /* mark size of spaces. Normally space can't be cue * size, but in this case, it makes it easier for later
1023 * code (in print phrase at least) if everything in the
1024 * beam--even spaces--is marked as cue size */
1025 gs_p->grpsize = size;
1026 }
1027
1028 /* esbm is not currently allowed on cross-staff beams.
1029 * It would much more complicated than normal beams,
1030 * because the "primary" beam might perhaps best be the top,
1031 * the bottom, or the middle, depending on where the notes are.
1032 * Placement and print phase would have to know about that,
1033 * so that stems could be adjusted properly,
1034 * and beams drawn in the right places.
1035 */
1036 if (gs_p->breakbeam == YES) {
1037 l_warning(gs_p->inputfile, gs_p->inputlineno,
1038 "esbm is not supported on cross-staff beams; being ignored");
1039 gs_p->breakbeam = NO;
1040 }
1041
1042 /* see if we reached the end of the beam */
1043 if (gs_p->beamloc == ENDITEM) {
1044 *end_time_p = end_time;
1045 if (has_at_least_1_note_group == NO) {
1046 l_yyerror(gs_p->inputfile, gs_p->inputlineno,
1047 "cross-staff beam has no notes on staff %d",
1048 staffno);
1049 }
1050
1051 return(gs_p);
1052 }
1053
1054 /* arrange for next time through the loop, by moving the
1055 * start_time to the next group */
1056 start_time = end_time;
1057 }
1058
1059 /* failed to find an ebm */
1060 return (struct GRPSYL *) 0;
1061}
1062\f
1063
1064/* User is not allowed to specify length on both ends of a beam along with
1065 * a slope, because they could becontradictory. */
1066
1067static void
1068slopelencheck(first_p, last_p, bmtype)
1069
1070struct GRPSYL *first_p; /* first beamed group */
1071struct GRPSYL *last_p; /* last beamed group */
1072char *bmtype; /* "beam" or "alt" */
1073
1074{
1075 if (IS_STEMLEN_KNOWN(first_p->stemlen) == YES &&
1076 IS_STEMLEN_KNOWN(last_p->stemlen) == YES &&
1077 fabs(first_p->beamslope - NOBEAMANGLE) > 0.001) {
1078 l_yyerror(last_p->inputfile, last_p->inputlineno,
1079 "can't specify both end stem lengths and slope for %s",
1080 bmtype);
1081 }
1082}