chiark / gitweb /
Import upstream version 5.3.
[mup] / mup / mup / mkchords.c
CommitLineData
69695f33
MW
1/* Copyright (c) 1995, 1996, 1997, 1998, 2002, 2003, 2004, 2006
2 * by Arkkra Enterprises */
3/* All rights reserved */
4/*
5 * Name: mkchords.c
6 *
7 * Description: This file contains functions for creating CHORD linked lists
8 * and erasing invisible voices.
9 */
10
11#include "defines.h"
12#include "structs.h"
13#include "globals.h"
14
15
16static void swingmidi P((void));
17static struct GRPSYL *voicevis P((struct GRPSYL *gs_p));
18static void combine_voices P((void));
19static void chkhand1 P((struct GRPSYL *gs1_p, struct MAINLL *staffmll_p));
20static int chk2groups P((struct GRPSYL *hi_p, struct GRPSYL *lo_p,
21 struct MAINLL *mll_p, int qual));
22static void chkhand2 P((struct GRPSYL *gs1_p, struct MAINLL *staffmll_p));
23static int chk2neighbors P((struct GRPSYL *first_p, struct GRPSYL *second_p,
24 struct GRPSYL *gs1_p, struct MAINLL *mll_p));
25static void dohand P((struct GRPSYL *gs1_p, struct MAINLL *staffmll_p));
26static void comb2groups P((struct GRPSYL *dest_p, struct GRPSYL *src_p,
27 struct MAINLL *mll_p));
28static void addsrc2dest P((struct GRPSYL *dest_p, struct GRPSYL *src_p));
29static int setgrpptrs P((struct GRPSYL *gs1_p, struct GRPSYL *v_p[]));
30static int hastieslur P((struct GRPSYL *gs_p));
31\f
32/*
33 * Name: makechords()
34 *
35 * Abstract: Set up the linked lists of chords.
36 *
37 * Returns: void
38 *
39 * Description: This function scans through the main linked list looking
40 * for STAFF structures. It joins the GRPSYL structures in
41 * the lists that they head, into perpendicular linked lists,
42 * allocating a CHORD to head each of these. It also links
43 * the CHORDs for each measure together into a linked list.
44 *
45 * While doing the above, it also calls voicevis() to check if a
46 * voice should be invisible, and if so changes it to a measure
47 * space. It also applies the swingunit and voicecombine
48 * parameters.
49 */
50
51
52void
53makechords()
54
55{
56 struct MAINLL *mainll_p; /* point at item in main linked list */
57 struct MAINLL *mainch_p; /* for headcell of a chord list */
58
59 RATIONAL *vtime; /* cum. time of each voice and verse */
60 struct GRPSYL **grpsyl_p; /* pointers along GRPSYL lists */
61 struct STAFF *staff_p; /* point at a staff structure */
62
63 RATIONAL mintime; /* the minimum vtime */
64 register int num; /* no. of visible voices/verses */
65 register int v; /* index into grpsyl_p[] */
66 struct CHORD *ch_p; /* pointer to current chord */
67 struct CHORD *och_p; /* pointer to old chord */
68 struct GRPSYL *gs_p; /* pointer to current group/syllable */
69 int n; /* loop variable */
70 int firstgs; /* flag for first group/syllable */
71 int quit; /* flag for being done */
72
73
74 debug(16, "makechords");
75 /*
76 * If we are generating MIDI, we may need to change lengths (fulltimes)
77 * of groups. This has to be done now, before we link groups together
78 * into chords.
79 */
80 if (Doing_MIDI == YES) {
81 swingmidi();
82 }
83
84 gs_p = 0; /* keep lint happy; will be set before used */
85
86 /* malloc enough of these for all voices and verses */
87 MALLOC(rational, vtime, MAXSTAFFS * (MAXVOICES + Maxverses));
88 MALLOC(GRPSYL *, grpsyl_p, MAXSTAFFS * (MAXVOICES + Maxverses));
89
90 mainll_p = Mainllhc_p; /* point at first thing in main LL */
91
92 initstructs(); /* clean out old SSV info */
93
94 /*
95 * Loop once for each measure in the input.
96 */
97 for (;;) {
98 num = 0; /* number of linked lists in measure */
99
100 /*
101 * Look for the first structure in this measure that points off
102 * to a linked list of groups/syllables. If we hit the end of
103 * the main linked list, we're all done, so break out.
104 */
105 while (mainll_p != 0 && mainll_p->str != S_STAFF) {
106 if (mainll_p->str == S_SSV)
107 asgnssv(mainll_p->u.ssv_p);
108 mainll_p = mainll_p->next;
109 }
110
111 if (mainll_p == 0) {
112 FREE(vtime);
113 FREE(grpsyl_p);
114 break;
115 }
116
117 /*
118 * We've found another measure with STAFF in it. Allocate
119 * a chord headcell for this measure, and put it in the
120 * main linked list.
121 */
122 mainch_p = newMAINLLstruct(S_CHHEAD, 0);
123 insertMAINLL(mainch_p, mainll_p->prev);
124
125 /*
126 * Look for the last STAFF structure in the measure. While
127 * doing this, point at first element of all the group/syllable
128 * linked lists, and keep count of them. Ignore invisible
129 * staffs. Skip over any grace groups.
130 */
131 while (mainll_p != 0 && mainll_p->str == S_STAFF) {
132 staff_p = mainll_p->u.staff_p;
133
134 if (staff_p->visible == YES) {
135
136 /* do all the voices on this staff */
137 for (n = 0; n < MAXVOICES &&
138 staff_p->groups_p[n] != 0; n++) {
139 /*
140 * Zap voice if invisible. Set both
141 * of these to point at the first
142 * GRPSYL, which will be a new one if
143 * we zapped it.
144 */
145 grpsyl_p[num] = staff_p->groups_p[n] =
146 voicevis(staff_p->groups_p[n]);
147
148 /* skip leading grace groups */
149 while (grpsyl_p[num] != 0 &&
150 grpsyl_p[num]->grpvalue == GV_ZERO)
151 grpsyl_p[num] = grpsyl_p[num]->next;
152 if (grpsyl_p[num] == 0)
153 pfatal("nothing but grace groups found");
154 num++;
155 }
156
157 /* do all the verses on this staff */
158 for (n = 0; n < staff_p->nsyllists; n++)
159 grpsyl_p[num++] = staff_p->syls_p[n];
160 }
161 mainll_p = mainll_p->next;
162 }
163
164 /*
165 * Set up the first chord from the first note in each
166 * voice/verse. Its linked list of GRPSYLs will include
167 * the first GRPSYL in every linked list off of a visible
168 * STAFF.
169 */
170 MALLOC(CHORD, ch_p, 1);
171 mainch_p->u.chhead_p->ch_p = ch_p; /* point at first chord */
172 ch_p->ch_p = 0; /* only member on list so far */
173 ch_p->starttime = Zero; /* start time = any voice */
174
175 /* point headcell at first and set its first group's time */
176 ch_p->gs_p = grpsyl_p[0];
177 vtime[0] = grpsyl_p[0]->fulltime;
178
179 /* for each remaining one, point prev one at it & set time */
180 for (v = 1; v < num; v++) {
181 grpsyl_p[v-1]->gs_p = grpsyl_p[v];
182 vtime[v] = grpsyl_p[v]->fulltime;
183 }
184 grpsyl_p[num-1]->gs_p = 0; /* terminate linked list */
185
186 /* point at second GRPSYL in each voice/verse, if any */
187 for (v = 0; v < num; v++)
188 grpsyl_p[v] = grpsyl_p[v]->next;
189
190 /*
191 * Loop until groups/syllables in the voices/verses are used
192 * up. Form a chord for each time at which any voice/verse
193 * has a GRPSYL structure, though ignore grace groups.
194 */
195 for (;;) {
196 /*
197 * If every GRPSYL currently pointed at by a grpsyl_p[]
198 * is the last in its list (the measure), there are no
199 * more chords in this measure, and quit will remain
200 * YES.
201 */
202 quit = YES; /* first assume "quit" */
203 for (v = 0; v < num; v++) {
204 /* find next item (if any) not a grace group */
205 while (grpsyl_p[v] != 0 &&
206 grpsyl_p[v]->grpsyl == GS_GROUP &&
207 grpsyl_p[v]->grpvalue == GV_ZERO) {
208
209 grpsyl_p[v] = grpsyl_p[v]->next;
210 }
211
212 /* check if voice/verse has another item */
213 if (grpsyl_p[v] != 0) {
214 quit = NO; /* yes, so don't quit yet */
215 }
216 }
217
218 /* if time to quit, skip rest of loop, and get out */
219 if (quit == YES)
220 break;
221
222 /*
223 * At least one voice/verse has another note in it.
224 * Find the earliest time at which something changes.
225 */
226 mintime = vtime[0];
227 for (v = 1; v < num; v++)
228 if (LT(vtime[v], mintime))
229 mintime = vtime[v];
230
231 /* allocate memory for another chord */
232 och_p = ch_p; /* remember where previous chord is */
233 MALLOC(CHORD, ch_p, 1);
234 och_p->ch_p = ch_p; /* point previous chord at it*/
235 ch_p->ch_p = 0; /* terminate in case last */
236
237 ch_p->starttime = mintime; /* starting time for chord*/
238
239 /*
240 * Form a new linked list. The head cell is the new
241 * chord, and the list connects it to all the groups/
242 * syllables that start at this time.
243 */
244 firstgs = YES;
245 for (v = 0; v < num; v++) {
246 if (EQ(vtime[v], mintime)) {
247 /*
248 * This voice/verse has a grpsyl at
249 * this time. Make the previous one
250 * point at it, set its pointer to 0
251 * in case it turns out to be the last,
252 * and add its length to vtime[v].
253 */
254 if (firstgs == YES) {
255 /* point headcell at first */
256 ch_p->gs_p = grpsyl_p[v];
257 firstgs = NO;
258 } else {
259 /* point previous one at ours*/
260 gs_p->gs_p = grpsyl_p[v];
261 }
262
263 /* set gs_p to point at our new one */
264 gs_p = grpsyl_p[v];
265
266 vtime[v] = radd(vtime[v],
267 gs_p->fulltime);
268
269 /* get next GRPSYL in voice/verse */
270 grpsyl_p[v] = gs_p->next;
271 }
272 }
273
274 gs_p->gs_p = 0; /* terminate linked list */
275 }
276
277 /*
278 * Set the duration of each chord in this measure. It's the
279 * next chord's start time minus this chord's start time.
280 * But for the last chord, it's the time signature minus
281 * this chord's start time. Also set pseudodur, which is a
282 * function of the duration. The amount of width the chord
283 * "deserves" to be allocated is proportional to pseudodur.
284 */
285 for (ch_p = mainch_p->u.chhead_p->ch_p; ch_p->ch_p != 0;
286 ch_p = ch_p->ch_p) {
287 ch_p->duration = rsub(ch_p->ch_p->starttime,
288 ch_p->starttime);
289 ch_p->pseudodur = pow(RAT2FLOAT(ch_p->duration),
290 Score.packexp);
291 }
292 ch_p->duration = rsub(Score.time, ch_p->starttime);
293 ch_p->pseudodur = pow(RAT2FLOAT(ch_p->duration), Score.packexp);
294 }
295
296 /* if voicecombine parm was ever set, combine voices if possible */
297 if (Vcombused == YES) {
298 combine_voices();
299 }
300}
301\f
302/*
303 * Name: swingmidi()
304 *
305 * Abstract: Alter groups' time to implement the "swingunit" parameter.
306 *
307 * Returns: void
308 *
309 * Description: This function loops through every GRPSYL in every voice,
310 * adjusting their fulltime so that they will start and end at
311 * different times, if necessary, to follow the "swingunit" parm.
312 * Each measure is divided into durations of "swingunit", starting
313 * at the beginning. (Usually the timesig divided by swingunit
314 * will be an integer, but if not, the last piece will be shorter.)
315 * The time where one group ends and the next group starts will be
316 * altered in either of these two circumstances:
317 * 1. The current boundary time is halfway into a swingunit, and
318 * each group is at least half a swingunit long.
319 * 2. The current boundary time is 3/4 of the way into a swingunit,
320 * and the first group is at least 3/4 of a swingunit long, and
321 * and the second group is at least 1/4 of a swingunit long.
322 * In both of these cases, the fulltimes are altered so that the
323 * meeting point is 2/3 of the way into the swingunit.
324 */
325
326void
327swingmidi()
328{
329 struct MAINLL *mainll_p; /* point along main linked list */
330 struct GRPSYL *gs_p; /* point along a GRPSYL list */
331 struct GRPSYL *prev_p; /* the GRPSYL before gs_p */
332 int vidx; /* voice index, 0 to MAXVOICES-1 */
333 RATIONAL quot; /* quotient */
334 RATIONAL swingunit; /* from SSV */
335 RATIONAL starttime; /* offset into measure of gs_p */
336 RATIONAL halfswing; /* swingunit/2 */
337 RATIONAL sixthswing; /* swingunit/6 */
338 RATIONAL twelfthswing; /* swingunit/12 */
339 RATIONAL threefourthsswing; /* 3/4 * swingunit */
340 RATIONAL onefourthswing; /* 1/4 * swingunit */
341 static RATIONAL six = {6,1};
342 static RATIONAL twelve = {12,1};
343
344
345 initstructs();
346
347 for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
348
349 switch (mainll_p->str) {
350 case S_SSV:
351 /* need to keep swingunit up to date */
352 asgnssv(mainll_p->u.ssv_p);
353 continue;
354 case S_STAFF:
355 break; /* break out and handle this staff */
356 default:
357 continue;
358 }
359
360 /* loop through every voice on this staff */
361 for (vidx = 0; vidx < MAXVOICES; vidx++) {
362
363 swingunit = vvpath(mainll_p->u.staff_p->staffno,
364 vidx + 1, SWINGUNIT)->swingunit;
365
366 /* skip this voice if swingunit was not set */
367 if (EQ(swingunit, Zero)) {
368 continue;
369 }
370
371 /* various rationals we will need in the loop below */
372 halfswing = rdiv(swingunit, Two);
373 threefourthsswing = rmul(swingunit, Three_fourths);
374 onefourthswing = rmul(swingunit, One_fourth);
375 sixthswing = rdiv(swingunit, six);
376 twelfthswing = rdiv(swingunit, twelve);
377
378 /* accumulate starttime */
379 starttime = Zero;
380
381 /* for lint; we'll never really check it when it's 0 */
382 prev_p = 0;
383
384 /* find first nongrace group in voice (0 if none) */
385 gs_p = mainll_p->u.staff_p->groups_p[vidx];
386 gs_p = gs_p != 0 && gs_p->grpvalue == GV_ZERO ?
387 nextnongrace(gs_p) : gs_p;
388
389 /* loop through every nongrace group in this voice */
390 for ( ; gs_p != 0; gs_p = nextnongrace(gs_p)) {
391
392 quot = rdiv(starttime, swingunit);
393
394 /* set starttime for the following group here
395 * because we may alter fulltime below */
396 starttime = radd(starttime, gs_p->fulltime);
397
398 /* handle case 1 (see prolog above) */
399 if (quot.d == 2 &&
400 GE(gs_p->fulltime, halfswing) &&
401 GE(prev_p->fulltime, halfswing)) {
402
403 prev_p->fulltime = radd(
404 prev_p->fulltime, sixthswing);
405 gs_p->fulltime = rsub(
406 gs_p->fulltime, sixthswing);
407 }
408
409 /* handle case 2 (see prolog above) */
410 if (quot.d == 4 && quot.n % 4 == 3 &&
411 GE(gs_p->fulltime, onefourthswing) &&
412 GE(prev_p->fulltime, threefourthsswing)) {
413
414 prev_p->fulltime = rsub(
415 prev_p->fulltime, twelfthswing);
416 gs_p->fulltime = radd(
417 gs_p->fulltime, twelfthswing);
418 }
419
420 prev_p = gs_p;
421 }
422 }
423 }
424}
425\f
426/*
427 * Name: voicevis()
428 *
429 * Abstract: If this voice is to be invisible, make it a measure space.
430 *
431 * Returns: pointer to first GRPSYL; this equals the input pointer if the
432 * voice is visible, else it points at the new measure space GRPSYL
433 *
434 * Description: This function finds out if the given voice is supposed to be
435 * invisible this measure. If so, it throws away the current
436 * GRPSYL list, replacing it with a single GRPSYL that is a
437 * measure space. See the big comment in svpath() in ssv.c.
438 */
439
440
441static struct GRPSYL *
442voicevis(gs_p)
443
444struct GRPSYL *gs_p; /* first GRPSYL in this voice's linked list */
445
446{
447 struct GRPSYL *ngs_p; /* pointer to the new GRPSYL */
448
449
450 /*
451 * At this point we know that the command line -s option allows this
452 * staff to be printed, and in fact this staff will be printed, because
453 * at least one of its voice(s) is supposed to be. (We know this
454 * because where we were called from, staff_p->visible == YES, and that
455 * was set by calling svpath().) If the staff weren't being printed,
456 * we wouldn't need to bother wiping out its invisible voice(s).
457 */
458
459 /*
460 * This voice must be changed to a measure space if the -s option says
461 * it should be invisible, or if the SSVs say so. The vvpath function
462 * checks both things.
463 */
464 if (vvpath(gs_p->staffno, gs_p->vno, VISIBLE)->visible == NO) {
465
466 /*
467 * Allocate a new GRPSYL and make it a measure space, with the
468 * same inputlineno etc. as the first in the current list.
469 */
470 ngs_p = newGRPSYL(GS_GROUP);
471
472 ngs_p->inputlineno = gs_p->inputlineno;
473 ngs_p->inputfile = gs_p->inputfile;
474 ngs_p->staffno = gs_p->staffno;
475 ngs_p->vno = gs_p->vno;
476 ngs_p->grpsyl = GS_GROUP;
477 ngs_p->is_meas = YES;
478 ngs_p->basictime = -1;
479
480 /* in one compiler the following had to be done separately */
481 /* like this, because it couldn't do the structure assignment */
482 ngs_p->fulltime.n = Score.time.n;
483 ngs_p->fulltime.d = Score.time.d;
484
485 ngs_p->grpcont = GC_SPACE;
486 ngs_p->prev = 0;
487 ngs_p->next = 0;
488 ngs_p->gs_p = 0;
489
490 /* throw away the old GRPSYL list */
491 free_grpsyls(gs_p);
492
493 return (ngs_p); /* ret pointer to the measure space */
494 }
495
496 return (gs_p); /* ret pointer to the original, unchanged GRPSYL */
497}
498\f
499/*
500 * Name: combine_voices()
501 *
502 * Abstract: Combine GRPSYLs in voices according to the voicecombine parm.
503 *
504 * Returns: void
505 *
506 * Description: This function, if requested by the voicecombine parameter,
507 * combines the appropriate groups in each chord on each staff
508 * where it can. (The set of groups in one chord on one staff is
509 * called a "hand" in the following code and in some other places
510 * in Mup, because I get tired of spelling out the whole phrase.)
511 * Because of beaming and ties/slurs, some groups may need to
512 * remain uncombined because their neighbors can't be combined.
513 * So the work is done in three passes. The first pass looks at
514 * each hand individually to see what can be done there. The
515 * second pass applies the neighbor rules. The third pass does
516 * the actual combining.
517 */
518/*
519 * NOTE: GRPSYL.pvno is used as a scratch area in these functions. The macro
520 * below defines COMB to be pvno for this use. We rely on the fact that CALLOC
521 * initialized it to 0. We count the low order bit as bit 0. Two sets of bits
522 * are used, as follows.
523 *
524 * Bit "x+y" being set to 1 means that the GRPSYLs of voices x and y can be
525 * combined (looking only at the groups in this chord, not groups they may be
526 * tie/beamed to, etc.). This scheme works only because the only voice numbers
527 * are 1, 2, and 3, so that uses bits 3, 4, and 5. The first pass sets them,
528 * and the second pass reads them.
529 *
530 * Bits 6 through 13 are used in pairs for voice numbers of groups that really
531 * should be combined, with all rules applied. The SHIFT macros below give the
532 * rightmost bit of each of the voice numbers, for the two possible sources and
533 * destinations that can happen, given that only 3 voices can exist. Pass 2
534 * sets these bits, and pass 3 reads them.
535 */
536#define COMB pvno
537#define SRC1SHIFT 6
538#define DEST1SHIFT 8
539#define SRC2SHIFT 10
540#define DEST2SHIFT 12
541
542static void
543combine_voices()
544{
545 struct MAINLL *mll_p; /* point along main linked list */
546 struct MAINLL *staffmll_p; /* point a group's staff's MLL struct */
547 struct CHORD *ch_p; /* point along a chord list */
548 struct GRPSYL *gs1_p; /* point along the GRPSYL list of a chord */
549 int staff; /* staff number we are working on */
550 int pass; /* the three passes we must make */
551
552
553 /* run the three passes */
554 for (pass = 1; pass <= 3; pass++) {
555
556 initstructs(); /* clean out old SSV info */
557
558 for (mll_p = Mainllhc_p; mll_p != 0; mll_p = mll_p->next) {
559
560 switch (mll_p->str) {
561 case S_SSV:
562 /* keep SSVs up to date (but midmeasure SSVs
563 * don't matter for what we're doing here) */
564 asgnssv(mll_p->u.ssv_p);
565 continue;
566 case S_CHHEAD:
567 break; /* break out to handle the chords */
568 default:
569 continue; /* ignore everything else */
570 }
571
572 /*
573 * Loop through each chord in this list.
574 */
575 for (ch_p = mll_p->u.chhead_p->ch_p; ch_p != 0;
576 ch_p = ch_p->ch_p) {
577 /*
578 * Loop through the linked list of GRPSYLs
579 * hanging off this chord. Skip the syllables;
580 * just deal with the groups.
581 */
582 gs1_p = ch_p->gs_p;
583 staff = 0; /* before first staff */
584 for (;;) {
585 /* find first group on next staff */
586 while (gs1_p != 0 &&
587 gs1_p->staffno == staff) {
588 gs1_p = gs1_p->gs_p;
589 }
590 if (gs1_p == 0) { /* no next staff */
591 break;
592 }
593
594 /* remember this new staff number */
595 staff = gs1_p->staffno;
596
597 /* tab ignores vcombine */
598 if (is_tab_staff(staff)) {
599 continue;
600 }
601
602 /* 1-line ignores vcombine */
603 if (svpath(staff, STAFFLINES)->
604 stafflines == 1) {
605 continue;
606 }
607
608 /* if no groups, only syls, ignore */
609 if (gs1_p->grpsyl == GS_SYLLABLE) {
610 continue;
611 }
612
613 /* skip staff if only one voice */
614 if (svpath(staff, VSCHEME)->vscheme
615 == V_1) {
616 continue;
617 }
618
619 /* get the staff's MLL struct */
620 staffmll_p = chmgrp2staffm(
621 mll_p, gs1_p);
622
623 switch (pass) {
624 case 1:
625 /*
626 * Set individual combineability
627 * in the "COMB" field.
628 */
629 chkhand1(gs1_p, staffmll_p);
630 break;
631 case 2:
632 /*
633 * Apply the neighbor rules.
634 */
635 chkhand2(gs1_p, staffmll_p);
636 break;
637 case 3:
638 /*
639 * Do the actual combining.
640 */
641 dohand(gs1_p, staffmll_p);
642 break;
643 }
644 }
645 }
646 }
647 }
648}
649\f
650/*
651 * Name: chkhand1()
652 *
653 * Abstract: Find which voices are combineable, ignoring neighbor rules.
654 *
655 * Returns: void
656 *
657 * Description: This function finds out which groups in this hand can be
658 * combined, of the ones requested by the voicecombine parameter,
659 * but ignoring neighbor rules. It stores the results in
660 * the COMB field of all the groups.
661 */
662
663static void
664chkhand1(gs1_p, mll_p)
665
666struct GRPSYL *gs1_p; /* first group in this hand */
667struct MAINLL *mll_p; /* MLL struct for this group */
668
669{
670 /*
671 * Index the following by voice number to find the expected "height" of
672 * the voices, relative to each other. A higher number means we expect
673 * that that voice should normally be higher.
674 */ /* v1 v2 v3 */
675 static int pitch[MAXVOICES + 1] = { 0, 3, 1, 2 };
676
677 struct SSV *ssv_p; /* the SSV with voice combine info */
678 struct GRPSYL *gs_p; /* point along GRPSYLs of the chord */
679 /* index the following by vno; it points at the GRPSYL for this vno */
680 struct GRPSYL *v_p[MAXVOICES + 1];
681 int slot1, slot2; /* indices into SSV's vcombine array */
682 int firstvno, secondvno; /* two voices from ssv_p->vcombine[] */
683 int combineable; /* YES or NO */
684 int comb; /* accumulate combineable bits */
685
686
687 /* point at each group; if only one, no combining can be done */
688 if (setgrpptrs(gs1_p, v_p) == 1) {
689 return;
690 }
691
692 /* get the list of groups we want to combine */
693 ssv_p = svpath(gs1_p->staffno, VCOMBINE);
694
695 /* for each pair of voices to be combined, see if they can be */
696 comb = 0;
697 for (slot1 = 0; slot1 < MAXVOICES; slot1++) {
698 firstvno = ssv_p->vcombine[slot1];
699 if (firstvno == 0) {
700 break; /* end of list, done with outer loop */
701 }
702 /* voice must have a group in this chord */
703 if (v_p[firstvno] == 0) {
704 continue; /* skip this iteration */
705 }
706 for (slot2 = slot1 + 1; slot2 < MAXVOICES; slot2++) {
707 secondvno = ssv_p->vcombine[slot2];
708 if (secondvno == 0) {
709 break; /* end of list, done with inner loop */
710 }
711 /* voice must have a group in this chord */
712 if (v_p[secondvno] == 0) {
713 continue; /* skip this iteration */
714 }
715 /* must pass higher voice first */
716 if (pitch[firstvno] > pitch[secondvno]) {
717 combineable = chk2groups(v_p[firstvno],
718 v_p[secondvno], mll_p,
719 ssv_p->vcombinequal);
720 } else {
721 combineable = chk2groups(v_p[secondvno],
722 v_p[firstvno], mll_p,
723 ssv_p->vcombinequal);
724 }
725
726 /* if this pair was combineable, remember that */
727 if (combineable == YES) {
728 comb |= 1 << (firstvno + secondvno);
729 }
730 }
731 }
732
733 /* save comb in all the groups, for easy access */
734 for (gs_p = gs1_p; gs_p != 0 && gs_p->staffno == gs1_p->staffno &&
735 gs_p->grpsyl == GS_GROUP; gs_p = gs_p->gs_p) {
736 gs_p->COMB = comb;
737 }
738}
739\f
740/*
741 * Name: chk2groups()
742 *
743 * Abstract: Find whether two groups are combineable.
744 *
745 * Returns: YES or NO
746 *
747 * Description: This function finds out if the given groups can be combined,
748 * ignoring beam and tie/slur issues. If either has preceding
749 * grace groups, they are also checked (via recursive calls) and
750 * they must also be able to be combined, to get a YES answer.
751 */
752
753static int
754chk2groups(hi_p, lo_p, mll_p, qual)
755
756struct GRPSYL *hi_p; /* group that should have higher pitch */
757struct GRPSYL *lo_p; /* group that should have lower pitch */
758struct MAINLL *mll_p; /* MLL struct for this group */
759int qual; /* voice combine qualifier */
760
761{
762 struct GRPSYL *phi_p; /* group before hi_p */
763 struct GRPSYL *plo_p; /* group before lo_p */
764 struct MAINLL *tempmll_p; /* temp copy of mll_p */
765 int widx; /* index into "with" lists */
766 int hidx, lidx; /* index into note lists */
767 int mintop; /* steps above c0 of top group's lowest note */
768 int maxbot; /* steps above c0 of bot group's highest note */
769 int n; /* loop variable */
770 struct NOTE *hnote_p; /* point at a note in the high group */
771 struct NOTE *lnote_p; /* point at a note in the low group */
772 struct SLURTO *hslur_p; /* point at a slur in the high group */
773 struct SLURTO *lslur_p; /* point at a slur in the high group */
774
775
776 /*
777 * Since the groups are in the same chord, we know they start at the
778 * same time. Require that they end at the same time.
779 */
780 if (NE(hi_p->fulltime, lo_p->fulltime)) {
781 return (NO);
782 }
783
784 /* covered by the fulltime check, except for bizarre tuplet cases */
785 if (hi_p->basictime != lo_p->basictime) {
786 return (NO);
787 }
788 if (hi_p->dots != lo_p->dots) {
789 return (NO);
790 }
791
792 /* don't allow "mr" and "1r" (for example) to combine */
793 if (hi_p->is_meas != lo_p->is_meas) {
794 return (NO);
795 }
796
797 /* tuploc must agree */
798 if (hi_p->tuploc != lo_p->tuploc) {
799 return (NO);
800 }
801
802 /* tupcont must agree */
803 if (hi_p->tupcont != lo_p->tupcont) {
804 return (NO);
805 }
806
807 /* if printtup is set in both groups, they must agree */
808 if (hi_p->printtup != PT_DEFAULT && lo_p->printtup != PT_DEFAULT &&
809 hi_p->printtup != lo_p->printtup) {
810 return (NO);
811 }
812
813 /* if tupside is set in both groups, they must agree */
814 if (hi_p->tupside != PL_UNKNOWN && lo_p->tupside != PL_UNKNOWN &&
815 hi_p->tupside != lo_p->tupside) {
816 return (NO);
817 }
818
819 /* don't allow cross staff beamed groups */
820 if (hi_p->beamto != CS_SAME || lo_p->beamto != CS_SAME) {
821 return (NO);
822 }
823
824 /* don't allow cross staff stemmed groups */
825 if (hi_p->stemto != CS_SAME || lo_p->stemto != CS_SAME) {
826 return (NO);
827 }
828
829 /* if either is a space, there can be no other conflict */
830 if (hi_p->grpcont == GC_SPACE || lo_p->grpcont == GC_SPACE) {
831 return (YES);
832 }
833
834 /***** both groups are GC_NOTES and/or GC_REST *****/
835
836 /* group size must agree */
837 if (hi_p->grpsize != lo_p->grpsize) {
838 return (NO);
839 }
840
841 /* if both are rests, there can be no other conflict */
842 if (hi_p->grpcont == GC_REST && lo_p->grpcont == GC_REST) {
843 return (YES);
844 }
845
846 /* if only one is a rest, there is a conflict */
847 if (hi_p->grpcont == GC_REST || lo_p->grpcont == GC_REST) {
848 return (NO);
849 }
850
851 /***** both groups are GC_NOTES *****/
852
853 /* head shape must agree */
854 if (hi_p->headshape != lo_p->headshape) {
855 return (NO);
856 }
857
858 /* beaming must be the same on both, except on grace beamloc doesn't
859 * matter, since if we combine them we'll beam them all anyway */
860 if (hi_p->beamloc != lo_p->beamloc && hi_p->grpvalue == GV_NORMAL) {
861 return (NO);
862 }
863 if (hi_p->breakbeam != lo_p->breakbeam) {
864 return (NO);
865 }
866 if (hi_p->beamslope != NOBEAMANGLE && lo_p->beamslope != NOBEAMANGLE &&
867 hi_p->beamslope != lo_p->beamslope) {
868 return (NO);
869 }
870
871 /* if both stemdirs are set, they must agree */
872 if (hi_p->stemlen != STEMLEN_UNKNOWN &&
873 lo_p->stemlen != STEMLEN_UNKNOWN &&
874 hi_p->stemlen != lo_p->stemlen) {
875 return (NO);
876 }
877
878 /* if both stemdirs are forced, they must agree */
879 if (hi_p->stemdir != UNKNOWN && lo_p->stemdir != UNKNOWN &&
880 hi_p->stemdir != lo_p->stemdir) {
881 return (NO);
882 }
883
884 /* group ties out of this group must agree */
885 if (hi_p->tie != lo_p->tie) {
886 return (NO);
887 }
888
889 /* group ties into this group must agree */
890 tempmll_p = mll_p;
891 phi_p = prevgrpsyl(hi_p, &tempmll_p);
892 tempmll_p = mll_p;
893 plo_p = prevgrpsyl(lo_p, &tempmll_p);
894 if (phi_p != 0 && plo_p != 0 && phi_p->tie != plo_p->tie) {
895 return (NO);
896 }
897
898 /* tremelo slashes or alternation slashes must agree */
899 if (hi_p->slash_alt != lo_p->slash_alt) {
900 return (NO);
901 }
902
903 /* neither group can have a horizontal offset */
904 if (hi_p->ho_usage != HO_NONE || lo_p->ho_usage != HO_NONE) {
905 return (NO);
906 }
907
908 /* "with" lists must both be nonexistent, or else identical */
909 if (hi_p->nwith != lo_p->nwith) {
910 return (NO);
911 }
912 for (widx = 0; widx < hi_p->nwith; widx++) {
913 if (strcmp(hi_p->withlist[widx], lo_p->withlist[widx]) != 0) {
914 return (NO);
915 }
916 }
917
918 /*
919 * Rolls aren't really implemented for voice 3. Voice 3 is just along
920 * for the ride, if it's in the middle of a roll. So we'll let it
921 * combine as long as both groups are in a roll, or not. But for
922 * voices 1 and 2, only allow specific combinations that make sense.
923 */
924 if (hi_p->vno == 1 && lo_p->vno == 2) {
925 switch ((hi_p->roll << 8) | lo_p->roll) {
926 case (NOITEM << 8) | NOITEM:
927 break;
928 case (STARTITEM << 8) | INITEM:
929 case (STARTITEM << 8) | ENDITEM:
930 case (INITEM << 8) | INITEM:
931 case (INITEM << 8) | ENDITEM:
932 if (hi_p->rolldir != lo_p->rolldir) {
933 return (NO);
934 }
935 break;
936 default:
937 return (NO);
938 }
939 } else {
940 if ((hi_p->roll == NOITEM) != (lo_p->roll == NOITEM)) {
941 return (NO);
942 }
943 }
944
945 /*
946 * If each group is preceded by a grace group, those grace groups must
947 * also be combineable. Notice that if there are multiple preceding
948 * grace groups, more recursive calls will occur. If one is preceded
949 * and the other isn't, there is no problem and nothing to check.
950 */
951 if (hi_p->prev != 0 && hi_p->prev->grpvalue == GV_ZERO &&
952 lo_p->prev != 0 && lo_p->prev->grpvalue == GV_ZERO) {
953 if (chk2groups(hi_p->prev, lo_p->prev, mll_p, qual) == NO) {
954 return (NO);
955 }
956 }
957
958 /* if either is a mrpt, the other must be, and there is no conflict */
959 if (hi_p->is_meas == YES) {
960 return (YES);
961 }
962
963 /***** both groups have a notelist *****/
964
965 /*
966 * Do some checks involving overlapping of the groups. We'd like to
967 * use stepsup, but it won't be set to its correct value until
968 * setnotes.c. Fortunately, we don't need to know the absolute
969 * vertical position, only the relative. So just use steps above c0.
970 */
971 mintop = hi_p->notelist[hi_p->nnotes - 1].octave * 7 +
972 Letshift[hi_p->notelist[hi_p->nnotes - 1].letter - 'a'];
973 maxbot = lo_p->notelist[0].octave * 7 +
974 Letshift[lo_p->notelist[0].letter - 'a'];
975 /*
976 * If the lowest note of the high group is higher than the highest of
977 * the low group, we are okay regardless of the vcombine qualifier,
978 * and there are no shared notes to check.
979 */
980 if (mintop > maxbot) {
981 return (YES);
982 }
983
984 /* if they are equal, and parm doesn't allow it, fail */
985 if (mintop == maxbot && qual == VC_NOOVERLAP) {
986 return (NO);
987 }
988
989 /* if there is true overlap, and parm doesn't allow it, fail */
990 if (mintop < maxbot && qual != VC_OVERLAP) {
991 return (NO);
992 }
993
994 /*
995 * Any shared notes must be compatible, so check every note in the top
996 * group against every note in the bottom group. If any are equal,
997 * they must be compatible.
998 */
999 for (hidx = 0; hidx < hi_p->nnotes; hidx++) {
1000
1001 hnote_p = &hi_p->notelist[hidx];
1002
1003 for (lidx = 0; lidx < lo_p->nnotes; lidx++) {
1004
1005 lnote_p = &lo_p->notelist[lidx];
1006
1007 /* if the notes aren't equal, don't check them */
1008 if (hnote_p->octave != lnote_p->octave ||
1009 hnote_p->letter != lnote_p->letter) {
1010 /* the notes differ; no problem */
1011 continue;
1012 }
1013
1014 /* notes match; check all the items that must agree */
1015
1016 /* any slurs they have must be the same */
1017 if (hnote_p->nslurto != lnote_p->nslurto) {
1018 return (NO);
1019 }
1020 for (n = 0; n < hnote_p->nslurto; n++) {
1021 hslur_p = &hnote_p->slurtolist[n];
1022 lslur_p = &lnote_p->slurtolist[n];
1023 if (hslur_p->letter != lslur_p->letter) {
1024 return (NO);
1025 }
1026 if (hslur_p->octave != lslur_p->octave) {
1027 return (NO);
1028 }
1029 if (hslur_p->slurstyle != lslur_p->slurstyle) {
1030 return (NO);
1031 }
1032 if (hslur_p->slurdir != lslur_p->slurdir) {
1033 return (NO);
1034 }
1035 }
1036
1037 /* must have same accidental, or none */
1038 if (hnote_p->accidental != lnote_p->accidental) {
1039 return (NO);
1040 }
1041
1042 /* head shape override, or none, must agree */
1043 if (hnote_p->headshape != lnote_p->headshape) {
1044 return (NO);
1045 }
1046
1047 /* note size must agree */
1048 if (hnote_p->notesize != lnote_p->notesize) {
1049 return (NO);
1050 }
1051
1052 /* tie related attributes must be the same */
1053 if (hnote_p->tie != lnote_p->tie) {
1054 return (NO);
1055 }
1056 if (hnote_p->tiestyle != lnote_p->tiestyle) {
1057 return (NO);
1058 }
1059 if (hnote_p->tiedir != lnote_p->tiedir) {
1060 return (NO);
1061 }
1062 if (hnote_p->is_bend != lnote_p->is_bend) {
1063 return (NO);
1064 }
1065 if (hnote_p->smallbend != lnote_p->smallbend) {
1066 return (NO);
1067 }
1068 }
1069 }
1070
1071 return (YES); /* passed all tests, the groups are combineable */
1072}
1073\f
1074/*
1075 * Name: chkhand2()
1076 *
1077 * Abstract: Make final decision on what can be combined in this hand.
1078 *
1079 * Returns: void
1080 *
1081 * Description: This function applies the additional rules about beaming and
1082 * ties/slurs to the results of chkhand1(), to decide what groups
1083 * in this hand truly should be combined. It stores the results
1084 * in the COMB field of all the groups.
1085 */
1086
1087static void
1088chkhand2(gs1_p, mll_p)
1089
1090struct GRPSYL *gs1_p; /* first group in this hand */
1091struct MAINLL *mll_p; /* MLL struct for this group */
1092
1093{
1094 struct SSV *ssv_p; /* the SSV with voice combine info */
1095 /* index the following by vno; it points at the GRPSYL for this vno */
1096 struct GRPSYL *v_p[MAXVOICES + 1];
1097 int slot1, slot2; /* indices into SSV's vcombine array */
1098 int firstvno, secondvno; /* two voices from ssv_p->vcombine[] */
1099 int keep_going; /* try some more? */
1100
1101
1102 /* if we already know no combining can be done, get out */
1103 if (gs1_p->COMB == 0) {
1104 return;
1105 }
1106
1107 /* point at all the groups in this hand */
1108 (void)setgrpptrs(gs1_p, v_p);
1109
1110 /* get the list of groups we want to combine */
1111 ssv_p = svpath(gs1_p->staffno, VCOMBINE);
1112
1113 /* for each pair of voices to be combined, apply the neighbor rules */
1114 for (slot1 = 0; slot1 < MAXVOICES; slot1++) {
1115 firstvno = ssv_p->vcombine[slot1];
1116 if (firstvno == 0) {
1117 break; /* end of list, done with outer loop */
1118 }
1119 /* voice must have a group in this chord */
1120 if (v_p[firstvno] == 0) {
1121 continue; /* skip this iteration */
1122 }
1123 for (slot2 = slot1 + 1; slot2 < MAXVOICES; slot2++) {
1124 secondvno = ssv_p->vcombine[slot2];
1125 if (secondvno == 0) {
1126 break; /* end of list, done with inner loop */
1127 }
1128 /* voice must have a group in this chord */
1129 if (v_p[secondvno] == 0) {
1130 continue; /* skip this iteration */
1131 }
1132 /*
1133 * The group with the lower voice number should be the
1134 * one that absorbs the other. Pass it first.
1135 */
1136 if (firstvno < secondvno) {
1137 keep_going = chk2neighbors(v_p[firstvno],
1138 v_p[secondvno], gs1_p, mll_p);
1139 } else {
1140 keep_going = chk2neighbors(v_p[secondvno],
1141 v_p[firstvno], gs1_p, mll_p);
1142 }
1143
1144 /* get out now if we are told to */
1145 if (keep_going == NO) {
1146 return;
1147 }
1148 }
1149 }
1150}
1151\f
1152/*
1153 * Name: chk2neighbors()
1154 *
1155 * Abstract: Apply beaming and tie/slur rules to two groups in a hand.
1156 *
1157 * Returns: YES or NO: should any further combining be attempted?
1158 *
1159 * Description: This function checks whether the two groups should be combined,
1160 * by looking at neighboring groups if beaming or ties/slurs
1161 * are involved. It stores the answer in the COMB field of all
1162 * the groups.
1163 *
1164 * If we shouldn't combine the groups, we return YES so that we
1165 * can come back and try a different pair, if appropriate. If we
1166 * can combine the groups, we may return YES or NO; see comments
1167 * below.
1168 */
1169
1170static int
1171chk2neighbors(dest_p, src_p, gs1_p, mll_p)
1172
1173struct GRPSYL *dest_p; /* group that should absorb the other */
1174struct GRPSYL *src_p; /* group that should be absorbed */
1175struct GRPSYL *gs1_p; /* first group in staff/chord */
1176struct MAINLL *mll_p; /* MLL struct for these groups' staff */
1177
1178{
1179 struct GRPSYL *d2_p, *s2_p; /* point at neighboring groups */
1180 struct GRPSYL *gs_p; /* point at groups in this chord */
1181 struct MAINLL *mll2_p, *mll3_p; /* more pointers into MLL */
1182 short mask; /* to be applied to "COMB" */
1183 short comb; /* hold combineability bits */
1184 int keep_going; /* return code */
1185
1186
1187 /*
1188 * Set up the bit that we must check in each chord to see if these two
1189 * voices are combineable.
1190 */
1191 mask = 1 << (dest_p->vno + src_p->vno);
1192
1193 /*
1194 * Start at this chord, and keep looking to the right as long as the
1195 * groups are beamed or tied/slurred.
1196 */
1197 mll2_p = mll_p;
1198 for (d2_p = dest_p, s2_p = src_p; d2_p != 0 && s2_p != 0;
1199 d2_p = nextglobnongrace(d2_p, &mll2_p),
1200 s2_p = nextglobnongrace(s2_p, &mll2_p)) {
1201 /*
1202 * If the groups in that chord are not combineable, we must not
1203 * combine our original groups either. The same flags are set
1204 * in d2_p and s2_p, so we could have checked either.
1205 */
1206 if ((d2_p->COMB & mask) == 0) {
1207 return (YES);
1208 }
1209
1210 /*
1211 * If the groups are not beamed or tied/slurred to the right,
1212 * we don't have to look any farther. For beams, we only have
1213 * to check one group, since the other must agree or we
1214 * wouldn't be here. For ties/slurs, we only have to check the
1215 * the src, since those are the ones that wouldn't work if
1216 * these groups were combined and the next ones weren't.
1217 */
1218 if ((s2_p->beamloc == NOITEM || s2_p->beamloc == ENDITEM) &&
1219 hastieslur(s2_p) == NO) {
1220 break;
1221 }
1222 }
1223
1224 /*
1225 * Start at this chord, and keep looking to the left as long as the
1226 * groups are beamed or tied/slurred.
1227 */
1228 mll2_p = mll_p;
1229 for (d2_p = dest_p, s2_p = src_p; d2_p != 0 && s2_p != 0;
1230 d2_p = prevglobnongrace(d2_p, &mll2_p),
1231 s2_p = prevglobnongrace(s2_p, &mll2_p)) {
1232
1233 if ((d2_p->COMB & mask) == 0) {
1234 return (YES);
1235 }
1236
1237 mll3_p = mll2_p; /* don't alter mll2_p */
1238 if ((s2_p->beamloc == NOITEM || s2_p->beamloc == STARTITEM) &&
1239 hastieslur(prevglobnongrace(s2_p, &mll3_p)) == NO) {
1240 break;
1241 }
1242 }
1243
1244 /* for convenience, copy the COMB bits into a local variable */
1245 comb = dest_p->COMB;
1246
1247 /*
1248 * We passed all the tests, so remember that we should combine the
1249 * original groups. Also decide whether any more should be tried.
1250 */
1251 if (((comb >> SRC1SHIFT) & 0x3) == 0) {
1252 /* first groups to be combined in this hand */
1253 comb |= src_p->vno << SRC1SHIFT;
1254 comb |= dest_p->vno << DEST1SHIFT;
1255 /*
1256 * If chkhand1() said all the groups in this hand were
1257 * combineable, we can come back later and try to combine the
1258 * other group. Otherwise, don't. We know the non-combineable
1259 * group will fail to combine, so don't waste the time.
1260 */
1261 if ((comb & 0x38) == ((1 << (1 + 2)) | (1 << (1 + 3)) |
1262 (1 << (2 + 3)))) {
1263 keep_going = YES;
1264 } else {
1265 keep_going = NO;
1266 }
1267 } else {
1268 /* second groups to be combined in this hand */
1269 comb |= src_p->vno << SRC2SHIFT;
1270 comb |= dest_p->vno << DEST2SHIFT;
1271 keep_going = NO; /* only 2 combinings can be done */
1272 }
1273
1274 /*
1275 * Since we will combine these two groups, the new dest group has
1276 * inherited any incompatibility that src might have had with the
1277 * other group (if any). So find the new value of the comb bits.
1278 * Set this new comb value into all the groups in this hand. We do
1279 * this for the benefit of later chords on this staff, if they are
1280 * beamed or tied/slurred to us.
1281 */
1282 switch (dest_p->vno + src_p->vno) {
1283 case 1 + 2: /* combined 2 into 1 */
1284 /* if 2 and 3 can't combine, now 1 and 3 can't */
1285 if ((comb & (1 << (2 + 3))) == 0) {
1286 comb &= ~(1 << (1 + 3));
1287 }
1288 break;
1289 case 1 + 3: /* combined 3 into 1 */
1290 /* if 3 and 2 can't combine, now 1 and 2 can't */
1291 if ((comb & (1 << (3 + 2))) == 0) {
1292 comb &= ~(1 << (1 + 2));
1293 }
1294 break;
1295 case 2 + 3: /* combined 3 into 2 */
1296 /* if 3 and 1 can't combine, now 2 and 1 can't */
1297 if ((comb & (1 << (3 + 1))) == 0) {
1298 comb &= ~(1 << (2 + 1));
1299 }
1300 break;
1301 }
1302 for (gs_p = gs1_p; gs_p != 0 && gs_p->staffno == gs1_p->staffno &&
1303 gs_p->grpsyl == GS_GROUP; gs_p = gs_p->gs_p) {
1304 gs_p->COMB = comb;
1305 }
1306
1307 return (keep_going);
1308}
1309\f
1310/*
1311 * Name: dohand()
1312 *
1313 * Abstract: Combine the appropriate GRPSYLs in one chord on one staff.
1314 *
1315 * Returns: void
1316 *
1317 * Description: This function combines GRPSYLs in one chord on one staff. It
1318 * uses the previously determined list of what is combineable in
1319 * gs1_p->COMB.
1320 */
1321
1322static void
1323dohand(gs1_p, mll_p)
1324
1325struct GRPSYL *gs1_p; /* first group on this staff in this chord */
1326struct MAINLL *mll_p; /* MLL struct for this group */
1327
1328{
1329 /* index the following by vno; it points at the GRPSYL for this vno */
1330 struct GRPSYL *v_p[MAXVOICES + 1];
1331 int srcv, destv; /* src and dest voice numbers */
1332
1333
1334 /* if we already know no combining can be done, get out */
1335 if (gs1_p->COMB == 0) {
1336 return;
1337 }
1338
1339 /* point at all the groups in this hand */
1340 (void)setgrpptrs(gs1_p, v_p);
1341
1342 /* get first src group's voice number */
1343 srcv = (gs1_p->COMB >> SRC1SHIFT) & 0x3;
1344
1345 if (srcv != 0) {
1346 /* find the dest's voice and combine */
1347 destv = (gs1_p->COMB >> DEST1SHIFT) & 0x3;
1348 comb2groups(v_p[destv], v_p[srcv], mll_p);
1349
1350 /* get second src group's voice number */
1351 srcv = (gs1_p->COMB >> SRC2SHIFT) & 0x3;
1352
1353 if (srcv != 0) {
1354 /* find the dest's voice and combine */
1355 destv = (gs1_p->COMB >> DEST2SHIFT) & 0x3;
1356 comb2groups(v_p[destv], v_p[srcv], mll_p);
1357 }
1358 }
1359}
1360\f
1361/*
1362 * Name: comb2groups()
1363 *
1364 * Abstract: Combine one group into another.
1365 *
1366 * Returns: void
1367 *
1368 * Description: This function combines the src group into the dest group,
1369 * including handling any preceding grace groups.
1370 */
1371
1372static void
1373comb2groups(dest_p, src_p, mll_p)
1374
1375struct GRPSYL *dest_p; /* group that should absorb the other */
1376struct GRPSYL *src_p; /* group that should be absorbed */
1377struct MAINLL *mll_p; /* MLL struct for these groups' staff */
1378
1379{
1380 struct GRPSYL *dgrace_p; /* dest grace group */
1381 struct GRPSYL *sgrace_p; /* src grace group */
1382 struct GRPSYL *dmem_p; /* remember a group from dest voice */
1383 struct GRPSYL *smem_p; /* remember a group from src voice */
1384 struct GRPSYL *temp_p; /* temp pointer */
1385 struct GRPSYL *fgs_p; /* first grace in src voice */
1386
1387
1388 /*
1389 * Add the src into the dest, and make the src group into a space if it
1390 * isn't already a space.
1391 */
1392 addsrc2dest(dest_p, src_p);
1393 if (src_p->grpcont != GC_SPACE) {
1394 src_p->grpcont = GC_SPACE;
1395 src_p->grpvalue = GV_NORMAL;
1396 src_p->grpsize = GS_NORMAL;
1397 src_p->headshape = HS_UNKNOWN;
1398 src_p->beamloc = NOITEM;
1399 src_p->beamslope = NOBEAMANGLE;
1400 src_p->stemlen = STEMLEN_UNKNOWN;
1401 src_p->stemdir = UNKNOWN;
1402 src_p->breakbeam = NO;
1403 src_p->beamloc = NOITEM;
1404 src_p->notelist = 0;
1405 src_p->nnotes = 0;
1406 src_p->tie = NO;
1407 src_p->slash_alt = 0;
1408 src_p->restdist = NORESTDIST;
1409 src_p->nwith = 0;
1410 src_p->roll = NOITEM;
1411 }
1412
1413 /* if source has no grace notes, we're done */
1414 if (src_p->prev == 0 || src_p->prev->grpvalue == GV_NORMAL) {
1415 return;
1416 }
1417
1418 /*
1419 * Loop through the matching grace groups preceding the src and dest
1420 * groups, adding the src into the dest. Remember the leftmost pair,
1421 * or the nongrace groups if there are no matching pairs.
1422 */
1423 dmem_p = dest_p;
1424 smem_p = src_p;
1425 for (sgrace_p = src_p->prev, dgrace_p = dest_p->prev;
1426 sgrace_p != 0 && sgrace_p->grpvalue == GV_ZERO &&
1427 dgrace_p != 0 && dgrace_p->grpvalue == GV_ZERO;
1428 sgrace_p = sgrace_p->prev, dgrace_p = dgrace_p->prev) {
1429
1430 addsrc2dest(dgrace_p, sgrace_p);
1431 dmem_p = dgrace_p; /* remember last one done */
1432 smem_p = sgrace_p;
1433 }
1434
1435 if (sgrace_p != 0 && sgrace_p->grpvalue == GV_ZERO) {
1436 /* extra src grace group(s) left over must be moved */
1437
1438 /* sgrace_p is the last (rightmost) grace to move */
1439 for (temp_p = sgrace_p; temp_p != 0 && temp_p->grpvalue ==
1440 GV_ZERO; temp_p = temp_p->prev) {
1441 fgs_p = temp_p;
1442 }
1443 /* fgs_p is the first (leftmost) grace to move */
1444
1445 if (dgrace_p == 0) { /* at start of measure? */
1446 /* in src voice, skip over all the graces */
1447 mll_p->u.staff_p->groups_p[src_p->vno-1] = src_p;
1448 src_p->prev = 0;
1449
1450 /* splice the left grace into the dest voice */
1451 mll_p->u.staff_p->groups_p[dest_p->vno-1] = fgs_p;
1452 fgs_p->prev = 0;
1453 } else {
1454 /* in src voice, skip over all the graces */
1455 fgs_p->prev->next = src_p;
1456 src_p->prev = fgs_p->prev;
1457
1458 /* splice the left grace into the dest voice */
1459 dgrace_p->next = fgs_p;
1460 fgs_p->prev = dgrace_p;
1461 }
1462
1463 /* splice the rightmost left over grace into the dest voice */
1464 dmem_p->prev = sgrace_p;
1465 sgrace_p->next = dmem_p;
1466
1467 /*
1468 * If there is now more than one grace in the dest, we have to
1469 * correct beamloc in a couple places.
1470 */
1471 if (fgs_p != dest_p->prev) {
1472 /*
1473 * If the dest voice had multiple graces before, the
1474 * leftmost one, which was STARTITEM, must be made
1475 * INITEM. If it had only one, it was NOITEM and
1476 * must be made ENDITEM, but go ahead and set INITEM;
1477 * it'll be set correctly below.
1478 */
1479 if (dmem_p != dest_p) { /* if dest had grace(s) */
1480 dmem_p->beamloc = INITEM;
1481 }
1482
1483 /* rightmost dest grace must always be made ENDITEM */
1484 dest_p->prev->beamloc = ENDITEM;
1485 }
1486
1487 /* change the voice number of the moved graces */
1488 for (temp_p = fgs_p; temp_p != sgrace_p->next;
1489 temp_p = temp_p->next) {
1490 temp_p->vno = dest_p->vno;
1491 }
1492 } else {
1493 /* no extra src grace group(s); just remove all src graces */
1494 if (sgrace_p == 0) {
1495 mll_p->u.staff_p->groups_p[src_p->vno-1] = src_p;
1496 src_p->prev = 0;
1497 } else {
1498 smem_p->prev->next = src_p;
1499 src_p->prev = smem_p->prev;
1500 }
1501 }
1502 /* could free the src graces, but is it worth the trouble? */
1503}
1504\f
1505/*
1506 * Name: addsrc2dest()
1507 *
1508 * Abstract: Adds src group to dest group.
1509 *
1510 * Returns: void
1511 *
1512 * Description: This function adds the src group info (if the src group exists)
1513 * into the dest group. But it doesn't mess with linkages. That
1514 * is the calling function's job.
1515 */
1516
1517static void
1518addsrc2dest(dest_p, src_p)
1519
1520struct GRPSYL *dest_p; /* destination group must exist */
1521struct GRPSYL *src_p; /* source group, or can be NULL */
1522
1523{
1524 struct NOTE *dnote_p; /* point at a note in the destination group */
1525 struct NOTE *snote_p; /* point at a note in the source group */
1526 struct NOTE *newlist; /* combined notelist */
1527 int didx, sidx; /* index into dest and src note lists */
1528 int totnotes; /* total number of notes after combining */
1529 int n; /* loop variable */
1530
1531
1532 /* if src doesn't exist, there is nothing to do */
1533 if (src_p == 0) {
1534 return;
1535 }
1536
1537 /* move references to the src group's coords */
1538 upd_ref(src_p->c, dest_p->c);
1539
1540 /* if src is space, nothing to do except carry over this space field */
1541 if (src_p->grpcont == GC_SPACE) {
1542 if (dest_p->grpcont == GC_SPACE &&
1543 src_p->uncompressible == YES) {
1544 dest_p->uncompressible = YES;
1545 }
1546 return;
1547 }
1548
1549 /* padding is the max of the two groups */
1550 dest_p->padding = MAX(dest_p->padding, src_p->padding);
1551
1552 /*
1553 * Some fields were allowed to disagree between the groups as long as
1554 * one was defaulted. The non-default value should prevail.
1555 */
1556 if (src_p->printtup != PT_DEFAULT) {
1557 dest_p->printtup = src_p->printtup;
1558 }
1559 if (src_p->tupside != PL_UNKNOWN) {
1560 dest_p->tupside = src_p->tupside;
1561 }
1562 if (src_p->beamslope != NOBEAMANGLE) {
1563 dest_p->beamslope = src_p->beamslope;
1564 }
1565 if (src_p->stemlen != STEMLEN_UNKNOWN) {
1566 dest_p->stemlen = src_p->stemlen;
1567 }
1568 if (src_p->stemdir != UNKNOWN) {
1569 dest_p->stemdir = src_p->stemdir;
1570 }
1571
1572 /* only when combining 1 & 2 might we have to adjust roll */
1573 if (dest_p->vno == 1 && src_p->vno == 2) {
1574 switch ((dest_p->roll << 8) | src_p->roll) {
1575 case (NOITEM << 8) | NOITEM:
1576 /* dest remains NOITEM */
1577 break;
1578 case (STARTITEM << 8) | INITEM:
1579 /* dest remains STARTITEM */
1580 break;
1581 case (STARTITEM << 8) | ENDITEM:
1582 dest_p->roll = LONEITEM;
1583 break;
1584 case (INITEM << 8) | INITEM:
1585 /* dest remains INITEM */
1586 break;
1587 case (INITEM << 8) | ENDITEM:
1588 dest_p->roll = ENDITEM;
1589 break;
1590 }
1591 }
1592
1593 /* if one is a rest, so is the other; combine */
1594 if (dest_p->grpcont == GC_REST) {
1595 /* throw away any restdist; probably would be inappropriate */
1596 dest_p->restdist = 0;
1597 return;
1598 }
1599
1600 /* if either is a mrpt, the other must be; nothing to copy */
1601 if (dest_p->is_meas == YES) {
1602 return;
1603 }
1604
1605 /* at this point we know src has notes, & dest has notes or is space */
1606
1607 /*
1608 * Make a new notelist. First copy the old dest notes into there, and
1609 * then add the src notes. We can't just realloc the dest, since
1610 * pointers into the array must be updated by calling upd_ref for each
1611 * array element. If any notes are shared, we won't really need this
1612 * many, but it doesn't waste much memory.
1613 */
1614 MALLOC(NOTE, newlist, dest_p->nnotes + src_p->nnotes);
1615 for (n = 0; n < dest_p->nnotes; n++) {
1616 newlist[n] = dest_p->notelist[n];
1617 }
1618
1619 /*
1620 * Keep track of the number of total resulting notes, which starts out
1621 * as the number of notes in dest. Loop through the src notes.
1622 */
1623 totnotes = dest_p->nnotes;
1624 for (sidx = 0; sidx < src_p->nnotes; sidx++) {
1625 snote_p = &src_p->notelist[sidx];
1626
1627 /* see if it matches any of the dest notes in the result array*/
1628 for (didx = 0; didx < dest_p->nnotes; didx++) {
1629 dnote_p = &newlist[didx];
1630 if (dnote_p->octave == snote_p->octave &&
1631 dnote_p->letter == snote_p->letter) {
1632 /*
1633 * If one has parens on the note or acc and the
1634 * other doesn't, ensure no parens in result.
1635 */
1636 if (dnote_p->note_has_paren !=
1637 snote_p->note_has_paren) {
1638 dnote_p->note_has_paren = NO;
1639 }
1640 if (dnote_p->acc_has_paren !=
1641 snote_p->acc_has_paren) {
1642 dnote_p->acc_has_paren = NO;
1643 }
1644 break;
1645 }
1646 }
1647 if (didx == dest_p->nnotes) {
1648 /* didn't find a match, so add it to the end */
1649 newlist[totnotes++] = *snote_p;
1650 }
1651 }
1652
1653 /* sort the combined list in pitch order */
1654 qsort((char *)newlist, (unsigned int)totnotes,
1655 sizeof (struct NOTE), notecomp);
1656
1657 /*
1658 * For every original dest and src note, find out where it ended up in
1659 * the combined list, and update and location tag references.
1660 */
1661 for (didx = 0; didx < dest_p->nnotes; didx++) {
1662 dnote_p = &dest_p->notelist[didx];
1663 for (n = 0; n < totnotes; n++) {
1664 if (newlist[n].octave == dnote_p->octave &&
1665 newlist[n].octave == dnote_p->letter) {
1666 upd_ref(newlist[n].c, dnote_p->c);
1667 }
1668 }
1669 }
1670 for (sidx = 0; sidx < src_p->nnotes; sidx++) {
1671 dnote_p = &src_p->notelist[sidx];
1672 for (n = 0; n < totnotes; n++) {
1673 if (newlist[n].octave == dnote_p->octave &&
1674 newlist[n].octave == dnote_p->letter) {
1675 upd_ref(newlist[n].c, dnote_p->c);
1676 }
1677 }
1678 }
1679
1680 /* free old dest list, and install the new one and its note count */
1681 if (dest_p->notelist != 0) { /* not a space */
1682 FREE(dest_p->notelist);
1683 }
1684 dest_p->notelist = newlist;
1685 dest_p->nnotes = totnotes;
1686}
1687\f
1688/*
1689 * Name: setgrpptrs()
1690 *
1691 * Abstract: Set pointers to the groups in a hand.
1692 *
1693 * Returns: number of GRPSYLs found in this hand
1694 *
1695 * Description: This function fill in the given array with pointers to the
1696 * groups in this hand. When a group doesn't exist for some
1697 * voice, a null pointer is used.
1698 */
1699
1700static int
1701setgrpptrs(gs1_p, v_p)
1702
1703struct GRPSYL *gs1_p; /* first group in this hand */
1704struct GRPSYL *v_p[]; /* fill this in, index by voice number */
1705
1706{
1707 struct GRPSYL *gs_p; /* point along GRPSYLs of the chord */
1708 int v; /* a voice number */
1709 int num; /* number of groups found */
1710
1711
1712 /* null out the list of pointers initially (note [0] is not used) */
1713 for (v = 1; v <= MAXVOICES; v++) {
1714 v_p[v] = 0;
1715 }
1716 /* for each group in the hand, set pointer to it */
1717 num = 0;
1718 for (gs_p = gs1_p; gs_p != 0 && gs_p->staffno == gs1_p->staffno &&
1719 gs_p->grpsyl == GS_GROUP; gs_p = gs_p->gs_p) {
1720 v_p[gs_p->vno] = gs_p;
1721 num++;
1722 }
1723
1724 return (num);
1725}
1726\f
1727/*
1728 * Name: hastieslur()
1729 *
1730 * Abstract: Is this group tied/slurred/bent to the next?
1731 *
1732 * Returns: YES or NO
1733 *
1734 * Description: This function checks whether there are any ties/slurs/bends to
1735 * the next group. If the given group doesn't exist, the answer
1736 * is NO.
1737 */
1738
1739static int
1740hastieslur(gs_p)
1741
1742struct GRPSYL *gs_p; /* group to check */
1743
1744{
1745 int idx; /* index into note list */
1746
1747
1748 /* if there's no group, it isn't tied/slurred */
1749 if (gs_p == 0) {
1750 return (NO);
1751 }
1752
1753 /* check group tie */
1754 if (gs_p->tie == YES) {
1755 return (YES);
1756 }
1757
1758 /* check note ties and slurs (bends are covered by slurs) */
1759 for (idx = 0; idx < gs_p->nnotes; idx++) {
1760 if (gs_p->notelist[idx].tie == YES ||
1761 gs_p->notelist[idx].nslurto != 0) {
1762 return (YES);
1763 }
1764 }
1765
1766 return (NO);
1767}